Merge commit '845d0c059d9522ed9475609fc07794977bd55c21' as 'third_party/libevent'

Change-Id: Ib2e5bf05a5aaa00ee4bb971434cc34325c498bc9
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..11973e3
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1 @@
+BasedOnStyle: 'google'
diff --git a/.gitignore b/.gitignore
index 622ab17..0d20b64 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,98 +1 @@
-### These files should get ignored no matter where they appear.
-
-# Editors leave these lying around
-\#*\#
-.#*
-*~
-*.swp
-
-# C stuff
-*.o
-
-# Windows stuff
-*.obj
-*.exe
-*.lib
-
-# Patch leaves these lying arround
-*.orig
-*.rej
-
-# gcov stuff
-*.gcno
-*.gcov
-*.gcda
-
-# Autotools stuff
-.deps
-Makefile
-Makefile.in
-
-# Libtool stuff
-.libs
-*.lo
-*.la
-
-# ctags stuff
-TAGS
-
-# Stuff made by our makefiles
-libevent.pc
-libevent_pthreads.pc
-libevent_openssl.pc
-*.log
-*.trs
-
-## The initial / makes these files only get ignored in particular directories.
-/autom4te.cache
-
-# Libtool adds these, at least sometimes
-/m4/libtool.m4
-/m4/ltoptions.m4
-/m4/ltsugar.m4
-/m4/ltversion.m4
-/m4/lt~obsolete.m4
-
-/aclocal.m4
-/compile
-/doxygen
-/config.guess
-/config.log
-/config.status
-/config.sub
-/configure
-/depcomp
-/config.h
-/config.h.in
-/install-sh
-/libtool
-/ltmain.sh
-/missing
-/stamp-h1
-
-/include/event2/event-config.h
-
-/sample/dns-example
-/sample/event-test
-/sample/hello-world
-/sample/http-server
-/sample/le-proxy
-/sample/signal-test
-/sample/time-test
-
-/test/bench
-/test/bench_cascade
-/test/bench_http
-/test/bench_httpclient
-/test/regress
-/test/regress.gen.c
-/test/regress.gen.h
-/test/rpcgen-attempted
-/test/test-eof
-/test/test-init
-/test/test-ratelim
-/test/test-script.sh
-/test/test-time
-/test/test-weof
-/test/test-changelist
-
+*.pyc
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..89fa70a
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,7 @@
+This is the README.txt file for git. If you are looking at this file and you got it through SVN, somebody messed up and it should be fixed.
+
+This is team 971's code. We only keep code in this git repository. For details about how we use git, see doc/gitsetup.txt.
+
+You can get to this code in a web browser through <https://robotics.mvla.net/git971> (useful for ie sending links). You have to use your SVN credentials to log in there.
+
+aos/README.txt has some more details about what's where.
diff --git a/aos/README.txt b/aos/README.txt
new file mode 100644
index 0000000..e0f9377
--- /dev/null
+++ b/aos/README.txt
@@ -0,0 +1,34 @@
+see ../README.txt for overall information
+
+[FILES]
+config/ has some configuration files
+	aos.conf has directions for setting up resource limits so you can run the code on any linux machine (the directions are there to keep them with the file)
+	setup_rc_caps.sh is a shell script (you have to run as root) that lets you run the realtime code without installing aos.conf for an individual file
+	starter is an init.d file
+		install it by putting it in /etc/init.d an running "update-rc.d starter defaults"
+		restart it by running "invoke-rc.d starter restart" (doesn't always work very well...)
+	the .config files are for building linux kernels
+
+linux/ has code that only runs on linux systems
+
+common/ is where stuff that runs on all platforms is
+common/input/ is where the framework code for reading stuff into the queues system is
+common/output/ is where the framework for writing things out of the queues system is
+common/messages is where the c++ wrappers for "queues" are
+
+[NOTES]
+Some functions need to be in separate translation units in order for them to be guaranteed to work. As the C standard says,
+	Alternatively, an implementation might perform various optimizations within each translation unit, such
+	that the actual semantics would agree with the abstract semantics only when making function calls across
+	translation unit boundaries. In such an implementation, at the time of each function entry and function
+	return where the calling function and the called function are in different translation units, the values of all
+	externally linked objects and of all objects accessible via pointers therein would agree with the abstract
+	semantics. Furthermore, at the time of each such function entry the values of the parameters of the called
+	function and of all objects accessible via pointers therein would agree with the abstract semantics. In this
+	type of implementation, objects referred to by interrupt service routines activated by the signal function
+	would require explicit specification of volatile storage, as well as other implementation-defined
+	restrictions.
+
+The C++ namespace aos is used for all of the aos code. The crio and linux_code namespaces are for APIs that only make sense on one platform or the other.
+
+Almost everything in aos/ is thread-safe. Files with a main() might not be, and some pieces of code explicitly say at their declaration that they aren't. Also, code which shares non-const pointers (including this) is not generally thread-safe. Other than those exceptions, everything is assumed to be thread-safe so the comments don't say so explicitly.
diff --git a/aos/build/aos.gyp b/aos/build/aos.gyp
new file mode 100644
index 0000000..648718c
--- /dev/null
+++ b/aos/build/aos.gyp
@@ -0,0 +1,63 @@
+# This file has all of the aos targets.
+{
+  'targets': [
+    # A target for things used by the logging implementation (except die) to
+    # depend on that allows linking successfully with logging calls. However,
+    # executables containing targets that depend on this still need a dependency
+    # on logging somewhere or else they won't link.
+    {
+      'target_name': 'logging_interface',
+      'type': 'static_library',
+      'sources': [
+        '<(AOS)/common/logging/logging_interface.cc',
+      ],
+      'conditions': [
+        ['OS=="linux"', {
+          'sources': [
+            '<(AOS)/linux_code/logging/linux_interface.cc',
+          ],
+          'dependencies': [
+            '<(AOS)/linux_code/linux_code.gyp:complex_thread_local',
+          ],
+        }],
+      ],
+      'dependencies': [
+        '<(AOS)/common/common.gyp:die',
+        '<(AOS)/common/libc/libc.gyp:aos_strerror',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/libc/libc.gyp:aos_strerror',
+      ],
+    },
+    {
+      'target_name': 'logging',
+      'type': 'static_library',
+      'sources': [
+        '<(AOS)/common/logging/logging_impl.cc',
+      ],
+      'conditions': [
+        ['OS=="linux"', {
+          'sources': [
+            '<(AOS)/linux_code/logging/linux_logging.cc',
+          ],
+          'dependencies': [
+            '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:queue',
+            '<(AOS)/common/common.gyp:time',
+          ],
+          'export_dependent_settings': [
+            '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:queue',
+          ],
+        }],
+      ],
+      'dependencies': [
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/common/common.gyp:once',
+        'logging_interface',
+        '<(AOS)/common/common.gyp:queue_types',
+      ],
+      'export_dependent_settings': [
+        'logging_interface',
+      ],
+    },
+  ],
+}
diff --git a/aos/build/aos.gypi b/aos/build/aos.gypi
new file mode 100644
index 0000000..8bddd0e
--- /dev/null
+++ b/aos/build/aos.gypi
@@ -0,0 +1,310 @@
+# This file gets passed to gyp with -I so that it gets included everywhere.
+{
+  'variables': {
+    'AOS': '<(DEPTH)/aos',
+# A directory with everything in it ignored from source control.
+    'TMPDIR': '<(DEPTH)/aos/build/temp',
+    'aos_abs': '<!(readlink -f <(DEPTH)/aos)', # for use in non-path contexts
+# The .gyp file that has targets for the various external libraries.
+    'EXTERNALS': '<(AOS)/build/externals.gyp',
+# The directory that gets rsynced to the target.
+    'rsync_dir': '<(PRODUCT_DIR)/outputs',
+# The directory for executables that don't get rsynced to the target.
+    'other_outputs_dir': '<(PRODUCT_DIR)/other_outputs',
+# The directory that executables that depend on <(EXTERNALS):gtest get put into.
+    'test_dir': '<(PRODUCT_DIR)/tests',
+
+# Stuck into a variable (with a space on the end) to make disabling it easy.
+    'ccache': '<!(which ccache) ',
+
+    'disable_sanitizers': [
+      # Bad alignment is just slow on x86 and traps on ARM, so we'll find
+      # it other ways, and some x86 code does it on purpose.
+      'alignment',
+    ],
+  },
+  'conditions': [
+    ['PLATFORM=="linux-arm_frc-gcc"', {
+        'make_global_settings': [
+          ['CC', '<(ccache)<!(which arm-frc-linux-gnueabi-gcc-4.9)'],
+          ['CXX', '<(ccache)<!(which arm-frc-linux-gnueabi-g++-4.9)'],
+          ['LINK_wrapper', '<!(realpath -s <(AOS)/build/strip_debuglink) <!(which arm-frc-linux-gnueabi-objcopy)'],
+        ],
+      },
+    ], ['PLATFORM=="linux-arm_frc-clang"', {
+        'variables': {
+          'arm-clang-symlinks': '<!(realpath -s <(AOS)/build/arm-clang-symlinks)',
+          'arm-clang-sysroot': '<(arm-clang-symlinks)/sysroot',
+# Flags that should be passed to all compile/link/etc commands.
+          'platflags': [
+            '-target', 'armv7a-frc-linux-gnueabi',
+            '-mfloat-abi=softfp',
+            '--sysroot=<(arm-clang-sysroot)',
+
+            # TODO(brians): See if it will run with this enabled.
+            #-mhwdiv=arm,thumb
+          ],
+        },
+        'make_global_settings': [
+          ['CC', '<(ccache)<(arm-clang-symlinks)/bin/clang'],
+          ['CXX', '<(ccache)<(arm-clang-symlinks)/bin/clang++'],
+          ['LINK_wrapper', '<!(realpath -s <(AOS)/build/strip_debuglink) <!(which arm-frc-linux-gnueabi-objcopy)'],
+        ],
+        'target_defaults': {
+          'cflags': [
+            '<@(platflags)',
+          ],
+          'cflags_cc': [
+            '-isystem', '<(arm-clang-sysroot)/include/c++/4.9.1',
+            '-isystem', '<(arm-clang-sysroot)/include/c++/4.9.1/arm-frc-linux-gnueabi',
+          ],
+          'ldflags': [
+            '<@(platflags)',
+            '-L/usr/lib/x86_64-linux-gnu/gcc/arm-frc-linux-gnueabi/4.9.1',
+            '-L<(arm-clang-symlinks)/more_libs',
+            '-B/usr/lib/x86_64-linux-gnu/gcc/arm-frc-linux-gnueabi/4.9.1',
+          ],
+        },
+      },
+    ], ['PLATFORM=="linux-amd64-clang"', {
+        'make_global_settings': [
+          ['CC', '<(ccache)<!(which clang)'],
+          ['CXX', '<(ccache)<!(which clang++)'],
+        ],
+      },
+    ], ['PLATFORM=="linux-amd64-gcc_4.8"', {
+        'make_global_settings': [
+          ['CC', '<(ccache)/opt/clang-3.5/bin/gcc'],
+          ['CXX', '<(ccache)/opt/clang-3.5/bin/g++'],
+        ],
+      },
+    ], ['SANITIZER!="none"', {
+        'target_defaults': {
+          'cflags': [
+            '-fsanitize=<(SANITIZER)',
+          ],
+          'ldflags': [
+            '-fsanitize=<(SANITIZER)',
+          ],
+          'defines': [
+# GCC doesn't have __has_feature, so we have to use this instead.
+            'AOS_SANITIZER_<(SANITIZER)',
+          ],
+        },
+      },
+    ], ['SANITIZER!="none" and COMPILER!="gcc"', {
+        'target_defaults': {
+          'cflags': [
+            '-fno-sanitize-recover',
+            '-fno-sanitize=<!(echo <(disable_sanitizers) | sed "s/ /,/g")',
+          ],
+        },
+      },
+    ], ['SANITIZER!="thread"', {
+        'libraries': [
+          '<!(readlink -f <(AOS)/../output/compiled-<(ARCHITECTURE)<(EXTERNALS_EXTRA)/gperftools-2.3-prefix/lib/libtcmalloc.a)',
+          '<!(readlink -f <(AOS)/../output/compiled-<(ARCHITECTURE)<(EXTERNALS_EXTRA)/libunwind-1.1-prefix/lib/libunwind.a)',
+        ],
+        'defines': [
+          'TCMALLOC',
+        ],
+      },
+    ], ['EXTERNALS_EXTRA=="-fPIE"', {
+        'target_defaults': {
+          'cflags': [
+            '-fPIE',
+          ],
+          'ldflags': [
+            '-fPIE',
+          ],
+          'link_settings': {
+            'ldflags': [
+              '-pie',
+            ],
+          },
+        },
+      },
+    ], ['SANITIZER=="memory"', {
+        'target_defaults': {
+          'cflags': [
+            '-fsanitize-memory-track-origins',
+          ],
+          'ldflags': [
+            '-fsanitize-memory-track-origins',
+          ],
+        },
+      },
+    ],
+  ],
+  'target_defaults': {
+    'defines': [
+      '__STDC_FORMAT_MACROS',
+      '__STDC_CONSTANT_MACROS',
+      '__STDC_LIMIT_MACROS',
+      'AOS_COMPILER_<!(echo <(FULL_COMPILER) | sed \'s/\./_/g\')',
+      'AOS_ARCHITECTURE_<(ARCHITECTURE)',
+      '_FILE_OFFSET_BITS=64',
+    ],
+    'ldflags': [
+      '-pipe',
+      '-pthread',
+    ],
+    'libraries': [
+      '-lm',
+      '-lrt',
+    ],
+    'cflags': [
+      '-pipe',
+
+      '-pthread',
+
+      '-Wall',
+      '-Wextra',
+      '-Wswitch-enum',
+      '-Wpointer-arith',
+      '-Wstrict-aliasing=2',
+      '-Wcast-qual',
+      '-Wcast-align',
+      '-Wwrite-strings',
+      '-Wtype-limits',
+      '-Wsign-compare',
+      '-Wformat=2',
+      '-Werror',
+
+      '-ggdb3',
+      # Generate debugging info that gdb 7.4.1 can understand (Wheezy).
+      # TODO(Brian): Remove this once we upgrade to Jessie.
+      '-gdwarf-3',
+    ],
+    'cflags_c': [
+      '-std=gnu99',
+    ],
+    'cflags_cc': [
+      '-std=gnu++11',
+    ],
+    'include_dirs': [
+      '<(DEPTH)',
+    ],
+    # These have to be here because apparently gyp evaluates target_conditions
+    # even if the target is never used.
+    'variables': {
+      # Set this to 1 to disable rsyncing the file to the target.
+      'no_rsync%': 0,
+      # Set this to 1 if this file is a test that should not be run by
+      # `build.py tests`.
+      'is_special_test%': 0,
+    },
+    'conditions': [
+      ['DEBUG=="yes"', {
+          'defines': [
+            'AOS_DEBUG=1',
+          ],
+          'conditions': [
+            ['COMPILER!="clang"', {
+                'cflags': [
+                  '-Og',
+                ],
+              },
+            ], ['COMPILER=="clang" and SANITIZER=="none"', {
+                'cflags': [
+                  '-O0',
+                ],
+              },
+            ], ['COMPILER=="clang" and SANITIZER!="none"', {
+                'cflags': [
+                  '-O1',
+                ],
+              }
+            ]
+          ],
+          'cflags': [
+            '-fno-omit-frame-pointer',
+          ],
+        }, { # 'DEBUG=="no"'
+          'defines': [
+            'AOS_DEBUG=0',
+            '_FORTIFY_SOURCE=2',
+          ],
+          'conditions': [
+            # TODO(Brian): Remove this special case once we get a new enough
+            # GCC here that it supports -Oz.
+            ['COMPILER=="gcc" and ARCHITECTURE=="arm_frc"', {
+                'cflags': [
+                  '-Os',
+                ],
+                'ldflags': [
+                  '-Os',
+                ],
+              }, {
+                'cflags': [
+                  '-Oz',
+                ],
+                'ldflags': [
+                  '-Oz',
+                ],
+              }
+            ], ['ARCHITECTURE=="amd64"', {
+              'cflags': [
+                '-fstack-protector-all',
+                ],
+              }
+            ],
+          ],
+          'cflags': [
+            '-fomit-frame-pointer',
+          ],
+        }
+      ], ['OS=="linux" and ARCHITECTURE=="arm" and COMPILER=="gcc" and DEBUG=="yes"', {
+          'cflags': [
+              # GCC doesn't like letting us use r7 (which is also the frame
+              # pointer) to pass the syscall number to the kernel even when
+              # it's marked as clobbered.
+              # See <https://bugzilla.mozilla.org/show_bug.cgi?id=633436> for
+              # some more discussion.
+            '-fomit-frame-pointer',
+          ],
+        }
+      ],
+      ['ARCHITECTURE=="arm"', {
+        'cflags': [
+          '-mcpu=cortex-a9',
+          '-mfpu=neon',
+          '-mfloat-abi=softfp',
+        ],
+        'ldflags': [
+          '-mcpu=cortex-a9',
+          '-mfpu=neon',
+          '-mfloat-abi=softfp',
+        ],
+      }],
+      ['COMPILER=="gcc"', {
+        'cflags': [
+          '-Wunused-local-typedefs',
+        ],
+        'defines': [
+          '__has_feature(n)=0'
+        ],
+      }], ['COMPILER=="clang"', {
+        'cflags': [
+          '-fcolor-diagnostics',
+          '-fmessage-length=80',
+          '-fmacro-backtrace-limit=0',
+        ],
+        'defines': [
+          # This tells clang's optimizer the same thing.
+          '__builtin_assume_aligned(p, a)=({ const typeof(p) my_p_ = (p); ((((uintptr_t)my_p_ % (a)) == 0u) ? my_p_ : (__builtin_unreachable(), (my_p_))); })',
+        ],
+      }],
+    ],
+    'target_conditions': [
+# Default to putting outputs into rsync_dir.
+      ['no_rsync==0 and _type!="static_library"', {
+          'product_dir': '<(rsync_dir)',
+        },
+      ], ['no_rsync==1 and _type!="static_library"', {
+        'product_dir': '<(other_outputs_dir)',
+        },
+      ],
+    ],
+  },
+}
diff --git a/aos/build/aos_all.gyp b/aos/build/aos_all.gyp
new file mode 100644
index 0000000..195997a
--- /dev/null
+++ b/aos/build/aos_all.gyp
@@ -0,0 +1,54 @@
+# This file has the executables etc that AOS builds.
+# User .gyp files for the prime should depend on :Prime.
+{
+  'targets': [
+    {
+      'target_name': 'Prime',
+      'type': 'none',
+      'variables': {
+        'no_rsync': 1,
+      },
+      'dependencies': [
+        'Common',
+        '<(AOS)/linux_code/linux_code.gyp:core',
+        '<(AOS)/linux_code/logging/logging.gyp:binary_log_writer',
+        '<(AOS)/linux_code/logging/logging.gyp:log_streamer',
+        '<(AOS)/linux_code/logging/logging.gyp:log_displayer',
+        '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:raw_queue_test',
+        '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:ipc_stress_test',
+        '<(AOS)/linux_code/starter/starter.gyp:starter_exe',
+        '<(AOS)/linux_code/linux_code.gyp:complex_thread_local_test',
+        '<(AOS)/common/common.gyp:stl_mutex_test',
+        '<(AOS)/linux_code/linux_code.gyp:dump_rtprio',
+        '<(AOS)/common/actions/actions.gyp:action_test',
+      ],
+    },
+    {
+      'target_name': 'Common',
+      'type': 'none',
+      'variables': {
+        'no_rsync': 1,
+      },
+      'dependencies': [
+        '<(AOS)/common/common.gyp:type_traits_test',
+        '<(AOS)/common/common.gyp:time_test',
+        '<(AOS)/common/common.gyp:mutex_test',
+        '<(AOS)/common/common.gyp:condition_test',
+        '<(AOS)/common/common.gyp:once_test',
+        '<(AOS)/common/common.gyp:event_test',
+        '<(AOS)/common/common.gyp:queue_testutils_test',
+        '<(AOS)/common/logging/logging.gyp:logging_impl_test',
+        '<(AOS)/common/util/util.gyp:options_test',
+        '<(AOS)/common/common.gyp:queue_test',
+        '<(AOS)/common/common.gyp:die_test',
+        '<(AOS)/common/common.gyp:queue_types_test',
+        '<(AOS)/common/util/util.gyp:trapezoid_profile_test',
+        '<(AOS)/common/util/util.gyp:wrapping_counter_test',
+        '<(AOS)/common/libc/libc.gyp:dirname_test',
+        '<(AOS)/common/libc/libc.gyp:aos_strerror_test',
+        '<(AOS)/common/libc/libc.gyp:aos_strsignal_test',
+        '<(AOS)/common/util/util.gyp:run_command_test',
+      ],
+    },
+  ],
+}
diff --git a/aos/build/arm-clang-symlinks/README b/aos/build/arm-clang-symlinks/README
new file mode 100644
index 0000000..75210a5
--- /dev/null
+++ b/aos/build/arm-clang-symlinks/README
@@ -0,0 +1,11 @@
+This directory has symlinks to various other files to help clang figure out how
+to cross compile for arm with FIRST's toolchain setup.
+
+sysroot/ has symlinks to various places so it can be used as a sysroot when
+  compiling.
+bin/ has symlinks to the various tools so clang can find the native toolchain.
+more_libs/ has modified files of several psuedo-shared-objects which are
+  actually linker scripts as distributed with the FIRST toolchain. For some
+  reason, I can't get the linker to follow the documented behavior of
+  prefixing the absolute paths contained in them with the sysroot, so we have
+  copies which don't have any paths.
diff --git a/aos/build/arm-clang-symlinks/bin/as b/aos/build/arm-clang-symlinks/bin/as
new file mode 120000
index 0000000..f5bd4f8
--- /dev/null
+++ b/aos/build/arm-clang-symlinks/bin/as
@@ -0,0 +1 @@
+/usr/bin/arm-frc-linux-gnueabi-as
\ No newline at end of file
diff --git a/aos/build/arm-clang-symlinks/bin/clang b/aos/build/arm-clang-symlinks/bin/clang
new file mode 120000
index 0000000..c456250
--- /dev/null
+++ b/aos/build/arm-clang-symlinks/bin/clang
@@ -0,0 +1 @@
+/usr/bin/clang
\ No newline at end of file
diff --git a/aos/build/arm-clang-symlinks/bin/clang++ b/aos/build/arm-clang-symlinks/bin/clang++
new file mode 120000
index 0000000..2932265
--- /dev/null
+++ b/aos/build/arm-clang-symlinks/bin/clang++
@@ -0,0 +1 @@
+/usr/bin/clang++
\ No newline at end of file
diff --git a/aos/build/arm-clang-symlinks/bin/ld b/aos/build/arm-clang-symlinks/bin/ld
new file mode 120000
index 0000000..a12d1ed
--- /dev/null
+++ b/aos/build/arm-clang-symlinks/bin/ld
@@ -0,0 +1 @@
+/usr/bin/arm-frc-linux-gnueabi-ld
\ No newline at end of file
diff --git a/aos/build/arm-clang-symlinks/more_libs/libc.so b/aos/build/arm-clang-symlinks/more_libs/libc.so
new file mode 100644
index 0000000..714bcfe
--- /dev/null
+++ b/aos/build/arm-clang-symlinks/more_libs/libc.so
@@ -0,0 +1,5 @@
+/* GNU ld script
+   Use the shared library, but some functions are only in
+   the static library, so try that secondarily.  */
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libc.so.6 libc_nonshared.a  AS_NEEDED ( ld-linux.so.3 ) )
diff --git a/aos/build/arm-clang-symlinks/more_libs/libpthread.so b/aos/build/arm-clang-symlinks/more_libs/libpthread.so
new file mode 100644
index 0000000..71f034f
--- /dev/null
+++ b/aos/build/arm-clang-symlinks/more_libs/libpthread.so
@@ -0,0 +1,5 @@
+/* GNU ld script
+   Use the shared library, but some functions are only in
+   the static library, so try that secondarily.  */
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libpthread.so.0 libpthread_nonshared.a )
diff --git a/aos/build/arm-clang-symlinks/sysroot/include b/aos/build/arm-clang-symlinks/sysroot/include
new file mode 120000
index 0000000..f4878ac
--- /dev/null
+++ b/aos/build/arm-clang-symlinks/sysroot/include
@@ -0,0 +1 @@
+/usr/arm-frc-linux-gnueabi/include
\ No newline at end of file
diff --git a/aos/build/arm-clang-symlinks/sysroot/lib b/aos/build/arm-clang-symlinks/sysroot/lib
new file mode 120000
index 0000000..5a01f30
--- /dev/null
+++ b/aos/build/arm-clang-symlinks/sysroot/lib
@@ -0,0 +1 @@
+/usr/arm-frc-linux-gnueabi/lib
\ No newline at end of file
diff --git a/aos/build/arm-clang-symlinks/sysroot/usr b/aos/build/arm-clang-symlinks/sysroot/usr
new file mode 120000
index 0000000..5d4ffd7
--- /dev/null
+++ b/aos/build/arm-clang-symlinks/sysroot/usr
@@ -0,0 +1 @@
+/usr/arm-frc-linux-gnueabi/usr
\ No newline at end of file
diff --git a/aos/build/bin-ld.gold/ld b/aos/build/bin-ld.gold/ld
new file mode 120000
index 0000000..af8591b
--- /dev/null
+++ b/aos/build/bin-ld.gold/ld
@@ -0,0 +1 @@
+/usr/bin/ld.gold
\ No newline at end of file
diff --git a/aos/build/build.py b/aos/build/build.py
new file mode 100755
index 0000000..613dedb
--- /dev/null
+++ b/aos/build/build.py
@@ -0,0 +1,1010 @@
+#!/usr/bin/python3
+
+import sys
+import subprocess
+import re
+import os
+import os.path
+import string
+import shutil
+import errno
+import queue
+import threading
+import pty
+import signal
+
+class TestThread(threading.Thread):
+  """Runs 1 test and keeps track of its current state.
+
+  A TestThread is either waiting to start the test, actually running it, done,
+  running it, or stopped. The first 3 always happen in that order and can
+  change to stopped at any time.
+
+  It will finish (ie join() will return) once the process has exited, at which
+  point accessing process to see the status is OK.
+
+  Attributes:
+    executable: The file path of the executable to run.
+    args: A tuple of arguments to give the executable.
+    env: The environment variables to set.
+    done_queue: A queue.Queue to place self on once done running the test.
+    start_semaphore: A threading.Semaphore to wait on before starting.
+    process_lock: A lock around process.
+    process: The currently executing test process or None. Synchronized by
+        process_lock.
+    stopped: True if we're stopped.
+    output: A queue of lines of output from the test.
+  """
+
+  class OutputCopier(threading.Thread):
+    """Copies the output of a test from its output pty into a queue.
+
+    This is necessary because otherwise everything locks up if the test writes
+    too much output and fills up the pty's buffer.
+    """
+
+    def __init__(self, name, fd, queue):
+      super(TestThread.OutputCopier, self).__init__(
+          name=(name + '.OutputCopier'))
+
+      self.fd = fd
+      self.queue = queue
+
+    def run(self):
+      with os.fdopen(self.fd) as to_read:
+        try:
+          for line in to_read:
+            self.queue.put(line)
+        except IOError as e:
+# An EIO from the master side of the pty means we hit the end.
+          if e.errno == errno.EIO:
+            return
+          else:
+            raise e
+
+  def __init__(self, executable, args, env, done_queue, start_semaphore):
+    super(TestThread, self).__init__(
+        name=os.path.split(executable)[-1])
+
+    self.executable = executable
+    self.args = args
+    self.env = env
+    self.done_queue = done_queue
+    self.start_semaphore = start_semaphore
+
+    self.output = queue.Queue()
+
+    self.process_lock = threading.Lock()
+    self.process = None
+    self.stopped = False
+    self.returncode = None
+    self.output_copier = None
+
+  def run(self):
+    def setup_test_process():
+# Shove it into its own process group so we can kill any subprocesses easily.
+      os.setpgid(0, 0)
+
+    with self.start_semaphore:
+      with self.process_lock:
+        if self.stopped:
+          return
+      test_output('Starting test %s...' % self.name)
+      output_to_read, subprocess_output = pty.openpty()
+      self.output_copier = TestThread.OutputCopier(self.name, output_to_read,
+                                                   self.output)
+      self.output_copier.start()
+      try:
+        with self.process_lock:
+          self.process = subprocess.Popen((self.name,) + self.args,
+                                          executable=self.executable,
+                                          env=self.env,
+                                          stderr=subprocess.STDOUT,
+                                          stdout=subprocess_output,
+                                          stdin=open(os.devnull, 'r'),
+                                          preexec_fn=setup_test_process)
+      finally:
+        os.close(subprocess_output)
+      self.process.wait()
+      with self.process_lock:
+        self.returncode = self.process.returncode
+        self.process = None
+        if not self.stopped:
+          self.output_copier.join()
+          self.done_queue.put(self)
+
+  def kill_process(self):
+    """Forcibly terminates any running process."""
+    with self.process_lock:
+      if not self.process:
+        return
+      try:
+        os.killpg(self.process.pid, signal.SIGKILL)
+      except OSError as e:
+        if e.errno == errno.ESRCH:
+          # We don't really care if it's already gone.
+          pass
+        else:
+          raise e
+  def stop(self):
+    """Changes self to the stopped state."""
+    with self.process_lock:
+      self.stopped = True
+
+def aos_path():
+  """Returns:
+    A relative path to the aos directory.
+  """
+  return os.path.join(os.path.dirname(__file__), '..')
+
+def get_ip():
+  """Retrieves the IP address to download code to."""
+  FILENAME = os.path.normpath(os.path.join(aos_path(), '..',
+                                           'output', 'ip_address.txt'))
+  if not os.access(FILENAME, os.R_OK):
+    os.makedirs(os.path.dirname(FILENAME), exist_ok=True)
+    with open(FILENAME, 'w') as f:
+      f.write('roboRIO-971.local')
+  with open(FILENAME, 'r') as f:
+    return f.readline().strip()
+
+def get_temp_dir():
+  """Retrieves the temporary directory to use when downloading."""
+  return '/home/admin/tmp/aos_downloader'
+
+def get_target_dir():
+  """Retrieves the tempory deploy directory for downloading code."""
+  return '/home/admin/robot_code'
+
+def user_output(message):
+  """Prints message to the user."""
+  print('build.py: ' + message, file=sys.stderr)
+
+# A lock to avoid making a mess intermingling test-related messages.
+test_output_lock = threading.RLock()
+def test_output(message):
+  """Prints message to the user. Intended for messages related to tests."""
+  with test_output_lock:
+    print('tests: ' + message, file=sys.stdout)
+
+def call_download_externals(argument):
+  """Calls download_externals.sh for a given set of externals.
+
+  Args:
+    argument: The argument to pass to the shell script to tell it what to
+        download.
+  """
+  subprocess.check_call(
+      (os.path.join(aos_path(), 'build', 'download_externals.sh'),
+       argument),
+      stdin=open(os.devnull, 'r'))
+
+class Processor(object):
+  """Represents a processor architecture we can build for."""
+
+  class UnknownPlatform(Exception):
+    def __init__(self, message):
+      super(Processor.UnknownPlatform, self).__init__()
+      self.message = message
+
+  class Platform(object):
+    """Represents a single way to build the code."""
+
+    def outdir(self):
+      """Returns:
+        The path of the directory build outputs get put in to.
+      """
+      return os.path.join(
+          aos_path(), '..', 'output', self.outname())
+    def build_ninja(self):
+      """Returns:
+        The path of the build.ninja file.
+      """
+      return os.path.join(self.outdir(), 'build.ninja')
+
+    def do_deploy(self, dry_run, command):
+      """Helper for subclasses to implement deploy.
+
+      Args:
+        dry_run: If True, prints the command instead of actually running it.
+        command: A tuple of command-line arguments.
+      """
+      real_command = (('echo',) + command) if dry_run else command
+      subprocess.check_call(real_command, stdin=open(os.devnull, 'r'))
+
+    def deploy(self, dry_run):
+      """Downloads the compiled code to the target computer."""
+      raise NotImplementedError('deploy should be overriden')
+    def outname(self):
+      """Returns:
+        The name of the directory the code will be compiled to.
+      """
+      raise NotImplementedError('outname should be overriden')
+    def os(self):
+      """Returns:
+        The name of the operating system this platform is for.
+
+        This will be used as the value of the OS gyp variable.
+      """
+      raise NotImplementedError('os should be overriden')
+    def gyp_platform(self):
+      """Returns:
+        The platform name the .gyp files know.
+
+        This will be used as the value of the PLATFORM gyp variable.
+      """
+      raise NotImplementedError('gyp_platform should be overriden')
+    def architecture(self):
+      """Returns:
+        The processor architecture for this platform.
+
+        This will be used as the value of the ARCHITECTURE gyp variable.
+      """
+      raise NotImplementedError('architecture should be overriden')
+    def compiler(self):
+      """Returns:
+        The compiler used for this platform.
+
+        Everything before the first _ will be used as the value of the
+        COMPILER gyp variable and the whole thing will be used as the value
+        of the FULL_COMPILER gyp variable.
+      """
+      raise NotImplementedError('compiler should be overriden')
+    def sanitizer(self):
+      """Returns:
+        The sanitizer used on this platform.
+
+        This will be used as the value of the SANITIZER gyp variable.
+
+        "none" if there isn't one.
+      """
+      raise NotImplementedError('sanitizer should be overriden')
+    def debug(self):
+      """Returns:
+        Whether or not this platform compiles with debugging information.
+
+        The DEBUG gyp variable will be set to "yes" or "no" based on this.
+      """
+      raise NotImplementedError('debug should be overriden')
+    def build_env(self):
+      """Returns:
+        A map of environment variables to set while building this platform.
+      """
+      raise NotImplementedError('build_env should be overriden')
+    def priority(self):
+      """Returns:
+        A relative priority for this platform relative to other ones.
+
+      Higher priority platforms will get built, tested, etc first. Generally,
+      platforms which give higher-quality compiler errors etc should come first.
+      """
+      return 0
+
+  def check_installed(self, platforms, is_deploy):
+    """Makes sure that everything necessary to build platforms are installed."""
+    raise NotImplementedError('check_installed should be overriden')
+  def parse_platforms(self, platforms_string):
+    """Args:
+      string: A user-supplied string saying which platforms to select.
+
+    Returns:
+      A tuple of Platform objects.
+
+    Raises:
+      Processor.UnknownPlatform: Parsing string didn't work out.
+    """
+    raise NotImplementedError('parse_platforms should be overriden')
+  def extra_gyp_flags(self):
+    """Returns:
+      A tuple of extra flags to pass to gyp (if any).
+    """
+    return ()
+  def modify_ninja_file(self, ninja_file):
+    """Modifies a freshly generated ninja file as necessary.
+
+    Args:
+      ninja_file: Path to the file to modify.
+    """
+    pass
+  def download_externals(self, platforms):
+    """Calls download_externals as appropriate to build platforms.
+
+    Args:
+      platforms: A list of platforms to download external libraries for.
+    """
+    raise NotImplementedError('download_externals should be overriden')
+
+  def do_check_installed(self, other_packages):
+    """Helper for subclasses to implement check_installed.
+
+    Args:
+      other_packages: A tuple of platform-specific packages to check for."""
+    all_packages = other_packages
+    # Necessary to build stuff.
+    all_packages += ('ccache', 'make')
+    # Necessary to download stuff to build.
+    all_packages += ('wget', 'git', 'subversion', 'patch', 'unzip', 'bzip2')
+    # Necessary to build externals stuff.
+    all_packages += ('python', 'gcc', 'g++')
+    not_found = []
+    try:
+      # TODO(brians): Check versions too.
+      result = subprocess.check_output(
+          ('dpkg-query',
+           r"--showformat='${binary:Package}\t${db:Status-Abbrev}\n'",
+           '--show') + all_packages,
+          stdin=open(os.devnull, 'r'),
+          stderr=subprocess.STDOUT)
+      for line in result.decode('utf-8').rstrip().splitlines(True):
+        match = re.match('^([^\t]+)\t[^i][^i]$', line)
+        if match:
+          not_found.append(match.group(1))
+    except subprocess.CalledProcessError as e:
+      output = e.output.decode('utf-8').rstrip()
+      for line in output.splitlines(True):
+        match = re.match(r'dpkg-query: no packages found matching (.*)',
+                         line)
+        if match:
+          not_found.append(match.group(1))
+    if not_found:
+      user_output('Some packages not installed: %s.' % ', '.join(not_found))
+      user_output('Try something like `sudo apt-get install %s`.' %
+                  ' '.join(not_found))
+      exit(1)
+
+class PrimeProcessor(Processor):
+  """A Processor subclass for building prime code."""
+
+  class Platform(Processor.Platform):
+    def __init__(self, architecture, folder, compiler, debug, sanitizer):
+      super(PrimeProcessor.Platform, self).__init__()
+
+      self.__architecture = architecture
+      self.__folder = folder
+      self.__compiler = compiler
+      self.__debug = debug
+      self.__sanitizer = sanitizer
+
+    def __repr__(self):
+      return 'PrimeProcessor.Platform(architecture=%s, compiler=%s, debug=%s' \
+          ', sanitizer=%s)' \
+          % (self.architecture(), self.compiler(), self.debug(),
+             self.sanitizer())
+    def __str__(self):
+      return '%s-%s-%s%s-%s' % (self.architecture(), self.folder(),
+                                self.compiler(),
+                                '-debug' if self.debug() else '',
+                                self.sanitizer())
+
+    def os(self):
+      return 'linux'
+    def gyp_platform(self):
+      return '%s-%s-%s' % (self.os(), self.architecture(), self.compiler())
+    def architecture(self):
+      return self.__architecture
+    def folder(self):
+      return self.__folder
+    def compiler(self):
+      return self.__compiler
+    def sanitizer(self):
+      return self.__sanitizer
+    def debug(self):
+      return self.__debug
+
+    def outname(self):
+      return str(self)
+
+    def priority(self):
+      r = 0
+      if self.compiler() == 'clang':
+        r += 100
+      if self.sanitizer() != 'none':
+        r -= 50
+      elif self.debug():
+        r -= 10
+      if self.architecture() == 'amd64':
+        r += 5
+      return r
+
+    def deploy(self, dry_run):
+      """Downloads code to the prime in a way that avoids clashing too badly with
+      starter (like the naive download everything one at a time)."""
+      if not self.architecture().endswith('_frc'):
+        raise Exception("Don't know how to download code to a %s." %
+                        self.architecture())
+      SUM = 'md5sum'
+      TARGET_DIR = get_target_dir()
+      TEMP_DIR = get_temp_dir()
+      TARGET = 'admin@' + get_ip()
+
+      from_dir = os.path.join(self.outdir(), 'outputs')
+      sums = subprocess.check_output((SUM,) + tuple(os.listdir(from_dir)),
+                                     stdin=open(os.devnull, 'r'),
+                                     cwd=from_dir)
+      to_download = subprocess.check_output(
+          ('ssh', TARGET,
+           """rm -rf {TMPDIR} && mkdir -p {TMPDIR} && \\
+             mkdir -p {TO_DIR} && cd {TO_DIR} \\
+             && echo '{SUMS}' | {SUM} -c \\
+             |& grep -F FAILED | sed 's/^\\(.*\\): FAILED.*$/\\1/g'""".
+           format(TMPDIR=TEMP_DIR, TO_DIR=TARGET_DIR, SUMS=sums.decode('utf-8'),
+                  SUM=SUM)))
+      if not to_download:
+        user_output("Nothing to download")
+        return
+      self.do_deploy(
+          dry_run,
+          ('scp', '-o', 'Compression yes')
+          + tuple([os.path.join(from_dir, f) for f in to_download.decode('utf-8').split('\n')[:-1]])
+          + (('%s:%s' % (TARGET, TEMP_DIR)),))
+      if not dry_run:
+        mv_cmd = ['mv {TMPDIR}/* {TO_DIR} ']
+        mv_cmd.append('&& chmod u+s {TO_DIR}/starter_exe ')
+        mv_cmd.append('&& echo \'Done moving new executables into place\' ')
+        mv_cmd.append('&& bash -c \'sync && sync && sync\'')
+        subprocess.check_call(
+            ('ssh', TARGET,
+             ''.join(mv_cmd).format(TMPDIR=TEMP_DIR, TO_DIR=TARGET_DIR)))
+
+    def build_env(self):
+      OTHER_SYSROOT = '/usr/lib/llvm-3.5/'
+      SYMBOLIZER_PATH = OTHER_SYSROOT + 'bin/llvm-symbolizer'
+      r = {}
+      if self.sanitizer() == 'address':
+        r['ASAN_SYMBOLIZER_PATH'] = SYMBOLIZER_PATH
+        r['ASAN_OPTIONS'] = \
+            'detect_leaks=1:check_initialization_order=1:strict_init_order=1' \
+            ':detect_stack_use_after_return=1:detect_odr_violation=2' \
+            ':allow_user_segv_handler=1'
+      elif self.sanitizer() == 'memory':
+        r['MSAN_SYMBOLIZER_PATH'] = SYMBOLIZER_PATH
+      elif self.sanitizer() == 'thread':
+        r['TSAN_OPTIONS'] = 'external_symbolizer_path=' + SYMBOLIZER_PATH
+        # This is apparently the default for newer versions, which disagrees
+        # with documentation, so just turn it on explicitly.
+        r['TSAN_OPTIONS'] += ':detect_deadlocks=1'
+        # Print more useful stacks for mutex locking order problems.
+        r['TSAN_OPTIONS'] += ':second_deadlock_stack=1'
+
+      r['CCACHE_COMPRESS'] = 'yes'
+      r['CCACHE_DIR'] = os.path.abspath(os.path.join(aos_path(), '..', 'output',
+                                                     'ccache_dir'))
+      r['CCACHE_HASHDIR'] = 'yes'
+      if self.compiler().startswith('clang'):
+        # clang doesn't like being run directly on the preprocessed files.
+        r['CCACHE_CPP2'] = 'yes'
+      # Without this, ccache slows down because of the generated header files.
+      # The race condition that this opens up isn't a problem because the build
+      # system finishes modifying header files before compiling anything that
+      # uses them.
+      r['CCACHE_SLOPPINESS'] = 'include_file_mtime'
+
+      if self.architecture() == 'amd64':
+        r['PATH'] = os.path.join(aos_path(), 'build', 'bin-ld.gold') + \
+            ':' + os.environ['PATH']
+
+      return r
+
+  ARCHITECTURES = ('arm_frc', 'amd64')
+  COMPILERS = ('clang', 'gcc')
+  SANITIZERS = ('address', 'undefined', 'integer', 'memory', 'thread', 'none')
+  SANITIZER_TEST_WARNINGS = {
+      'memory': (True,
+"""We don't have all of the libraries instrumented which leads to lots of false
+  errors with msan (especially stdlibc++).
+  TODO(brians): Figure out a way to deal with it."""),
+  }
+  PIE_SANITIZERS = ('memory', 'thread')
+
+  def __init__(self, folder, is_test, is_deploy):
+    super(PrimeProcessor, self).__init__()
+
+    self.__folder = folder
+
+    platforms = []
+    for architecture in PrimeProcessor.ARCHITECTURES:
+      for compiler in PrimeProcessor.COMPILERS:
+        for debug in [True, False]:
+          if architecture == 'amd64' and compiler == 'gcc':
+            # We don't have a compiler to use here.
+            continue
+          platforms.append(
+              self.Platform(architecture, folder, compiler, debug, 'none'))
+    for sanitizer in PrimeProcessor.SANITIZERS:
+      for compiler in ('clang',):
+        if compiler == 'gcc_4.8' and (sanitizer == 'undefined' or
+                                      sanitizer == 'integer' or
+                                      sanitizer == 'memory'):
+          # GCC 4.8 doesn't support these sanitizers.
+          continue
+        if sanitizer == 'none':
+          # We already added sanitizer == 'none' above.
+          continue
+        platforms.append(
+            self.Platform('amd64', folder, compiler, True, sanitizer))
+    self.__platforms = frozenset(platforms)
+
+    if is_test:
+      default_platforms = self.select_platforms(architecture='amd64',
+                                                debug=True)
+      for sanitizer, warning in PrimeProcessor.SANITIZER_TEST_WARNINGS.items():
+        if warning[0]:
+          default_platforms -= self.select_platforms(sanitizer=sanitizer)
+    elif is_deploy:
+      default_platforms = self.select_platforms(architecture='arm_frc',
+                                                compiler='gcc',
+                                                debug=False)
+    else:
+      default_platforms = self.select_platforms(debug=False)
+    self.__default_platforms = frozenset(default_platforms)
+
+  def folder(self):
+    return self.__folder
+  def platforms(self):
+    return self.__platforms
+  def default_platforms(self):
+    return self.__default_platforms
+
+  def download_externals(self, platforms):
+    to_download = set()
+    for architecture in PrimeProcessor.ARCHITECTURES:
+      pie_sanitizers = set()
+      for sanitizer in PrimeProcessor.PIE_SANITIZERS:
+        pie_sanitizers.update(self.select_platforms(architecture=architecture,
+                                                    sanitizer=sanitizer))
+      if platforms & pie_sanitizers:
+        to_download.add(architecture + '-fPIE')
+
+      if platforms & (self.select_platforms(architecture=architecture) -
+                      pie_sanitizers):
+        to_download.add(architecture)
+
+    for download_target in to_download:
+      call_download_externals(download_target)
+
+  def parse_platforms(self, platform_string):
+    if platform_string is None:
+      return self.default_platforms()
+    r = self.default_platforms()
+    for part in platform_string.split(','):
+      if part == 'all':
+        r = self.platforms()
+      elif part[0] == '+':
+        r = r | self.select_platforms_string(part[1:])
+      elif part[0] == '-':
+        r = r - self.select_platforms_string(part[1:])
+      elif part[0] == '=':
+        r = self.select_platforms_string(part[1:])
+      else:
+        selected = self.select_platforms_string(part)
+        r = r - (self.platforms() - selected)
+        if not r:
+          r = selected
+    return r
+
+  def select_platforms(self, architecture=None, compiler=None, debug=None,
+                       sanitizer=None):
+    r = []
+    for platform in self.platforms():
+      if architecture is None or platform.architecture() == architecture:
+        if compiler is None or platform.compiler() == compiler:
+          if debug is None or platform.debug() == debug:
+            if sanitizer is None or platform.sanitizer() == sanitizer:
+              r.append(platform)
+    return set(r)
+
+  def select_platforms_string(self, platforms_string):
+    architecture, compiler, debug, sanitizer = None, None, None, None
+    for part in platforms_string.split('-'):
+      if part in PrimeProcessor.ARCHITECTURES:
+        architecture = part
+      elif part in PrimeProcessor.COMPILERS:
+        compiler = part
+      elif part in ['debug', 'dbg']:
+        debug = True
+      elif part in ['release', 'nodebug', 'ndb']:
+        debug = False
+      elif part in PrimeProcessor.SANITIZERS:
+        sanitizer = part
+      elif part == 'all':
+        architecture = compiler = debug = sanitizer = None
+      elif part == self.folder():
+        pass
+      else:
+        raise Processor.UnknownPlatform(
+            '"%s" not recognized as a platform string component.' % part)
+    return self.select_platforms(
+        architecture=architecture,
+        compiler=compiler,
+        debug=debug,
+        sanitizer=sanitizer)
+
+  def check_installed(self, platforms, is_deploy):
+    packages = set(('lzip', 'm4', 'realpath'))
+    packages.add('ruby')
+    packages.add('clang-3.5')
+    packages.add('clang-format-3.5')
+    for platform in platforms:
+      if platform.compiler() == 'clang' or platform.compiler() == 'gcc_4.8':
+        packages.add('clang-3.5')
+      if platform.compiler() == 'gcc_4.8':
+        packages.add('libcloog-isl3:amd64')
+      if is_deploy:
+        packages.add('openssh-client')
+      elif platform.architecture == 'arm_frc':
+        packages.add('gcc-4.9-arm-frc-linux-gnueabi')
+        packages.add('g++-4.9-arm-frc-linux-gnueabi')
+
+    self.do_check_installed(tuple(packages))
+
+def strsignal(num):
+  # It ends up with SIGIOT instead otherwise, which is weird.
+  if num == signal.SIGABRT:
+    return 'SIGABRT'
+  # SIGCLD is a weird way to spell it.
+  if num == signal.SIGCHLD:
+    return 'SIGCHLD'
+
+  SIGNALS_TO_NAMES = dict((getattr(signal, n), n)
+                          for n in dir(signal) if n.startswith('SIG')
+                          and '_' not in n)
+  return SIGNALS_TO_NAMES.get(num, 'Unknown signal %d' % num)
+
+def main():
+  sys.argv.pop(0)
+  exec_name = sys.argv.pop(0)
+  def print_help(exit_status=None, message=None):
+    if message:
+      print(message)
+    sys.stdout.write(
+"""Usage: {name} [-j n] [action] [-n] [platform] [target|extra_flag]...
+Arguments:
+  -j, --jobs               Explicitly specify how many jobs to run at a time.
+                           Defaults to the number of processors + 2.
+  -n, --dry-run            Don't actually do whatever.
+                           Currently only meaningful for deploy.
+  action                   What to do. Defaults to build.
+                           build: Build the code.
+                           clean: Remove all the built output.
+                           tests: Build and then run tests.
+                           deploy: Build and then download.
+                           environment: Dump the environment for building.
+  platform                 What variants of the code to build.
+                           Defaults to something reasonable.
+                           See below for details.
+  target...                Which targets to build/test/etc.
+                           Defaults to everything.
+  extra_flag...            Extra flags associated with the targets.
+                           --gtest_*: Arguments to pass on to tests.
+                           --print_logs, --log_file=*: More test arguments.
+
+Specifying targets:
+ Targets are combinations of architecture, compiler, and debug flags. Which
+  ones actually get run is built up as a set. It defaults to something
+  reasonable for the action (specified below).
+ The platform specification (the argument given to this script) is a comma-
+  separated sequence of hyphen-separated platforms, each with an optional
+  prefix.
+ Each selector (the things separated by commas) selects all of the platforms
+  which match all of its components. Its effect on the set of current platforms
+  depends on the prefix character.
+ Here are the prefix characters:
+    +          Adds the selected platforms.
+    -          Removes the selected platforms.
+    =          Sets the current set to the selected platforms.
+    [none]     Removes all non-selected platforms.
+               If this makes the current set empty, acts like =.
+  There is also the special psuedo-platform "all" which selects all platforms.
+ All of the available platforms:
+  {all_platforms}
+ Default platforms for deploying:
+  {deploy_platforms}
+ Default platforms for testing:
+  {test_platforms}
+ Default platforms for everything else:
+  {default_platforms}
+
+Examples of specifying targets:
+ build everything: "all"
+ only build things with clang: "clang"
+ build everything that uses GCC 4.8 (not just the defaults): "=gcc_4.8"
+ build all of the arm targets that use clang: "clang-arm" or "arm-clang"
+""".format(
+    name=exec_name,
+    all_platforms=str_platforms(PrimeProcessor(False, False).platforms()),
+    deploy_platforms=str_platforms(PrimeProcessor(False, True).default_platforms()),
+    test_platforms=str_platforms(PrimeProcessor(True, False).default_platforms()),
+    default_platforms=str_platforms(PrimeProcessor(False, False).default_platforms()),
+    ))
+    if exit_status is not None:
+      sys.exit(exit_status)
+
+  def sort_platforms(platforms):
+    return sorted(
+        platforms, key=lambda platform: (-platform.priority(), str(platform)))
+
+  def str_platforms(platforms):
+    r = []
+    for platform in sort_platforms(platforms):
+      r.append(str(platform))
+    if len(r) > 1:
+      r[-1] = 'and ' + r[-1]
+    return ', '.join(r)
+
+  class Arguments(object):
+    def __init__(self):
+      self.jobs = os.sysconf('SC_NPROCESSORS_ONLN') + 2
+      self.action_name = 'build'
+      self.dry_run = False
+      self.targets = []
+      self.platform = None
+      self.extra_flags = []
+
+  args = Arguments()
+
+  if len(sys.argv) < 2:
+    print_help(1, 'Not enough arguments')
+  args.processor = sys.argv.pop(0)
+  args.folder = sys.argv.pop(0)
+  args.main_gyp = sys.argv.pop(0)
+  VALID_ACTIONS = ['build', 'clean', 'deploy', 'tests', 'environment']
+  while sys.argv:
+    arg = sys.argv.pop(0)
+    if arg == '-j' or arg == '--jobs':
+      args.jobs = int(sys.argv.pop(0))
+      continue
+    if arg in VALID_ACTIONS:
+      args.action_name = arg
+      continue
+    if arg == '-n' or arg == '--dry-run':
+      if args.action_name != 'deploy':
+        print_help(1, '--dry-run is only valid for deploy')
+      args.dry_run = True
+      continue
+    if arg == '-h' or arg == '--help':
+      print_help(0)
+    if (re.match('^--gtest_.*$', arg) or arg == '--print-logs' or
+        re.match('^--log_file=.*$', arg)):
+      if args.action_name == 'tests':
+        args.extra_flags.append(arg)
+        continue
+      else:
+        print_help(1, '%s is only valid for tests' % arg)
+    if args.platform:
+      args.targets.append(arg)
+    else:
+      args.platform = arg
+
+  if args.processor == 'prime':
+    processor = PrimeProcessor(args.folder,
+                               args.action_name == 'tests',
+                               args.action_name == 'deploy')
+  else:
+    print_help(1, message='Unknown processor "%s".' % args.processor)
+
+  unknown_platform_error = None
+  try:
+    platforms = processor.parse_platforms(args.platform)
+  except Processor.UnknownPlatform as e:
+    unknown_platform_error = e.message
+    args.targets.insert(0, args.platform)
+    platforms = processor.parse_platforms(None)
+  if not platforms:
+    print_help(1, 'No platforms selected')
+
+  processor.check_installed(platforms, args.action_name == 'deploy')
+  processor.download_externals(platforms)
+
+  class ToolsConfig(object):
+    def __init__(self):
+      self.variables = {'AOS': aos_path()}
+      with open(os.path.join(aos_path(), 'build', 'tools_config'), 'r') as f:
+        for line in f:
+          if line[0] == '#':
+            pass
+          elif line.isspace():
+            pass
+          else:
+            new_name, new_value = line.rstrip().split('=')
+            for name, value in self.variables.items():
+              new_value = new_value.replace('${%s}' % name, value)
+            self.variables[new_name] = new_value
+    def __getitem__(self, key):
+      return self.variables[key]
+
+  tools_config = ToolsConfig()
+
+  def handle_clean_error(function, path, excinfo):
+    _, _ = function, path
+    if issubclass(OSError, excinfo[0]):
+      if excinfo[1].errno == errno.ENOENT:
+        # Who cares if the file we're deleting isn't there?
+        return
+    raise excinfo[1]
+
+  def need_to_run_gyp(platform):
+    """Determines if we need to run gyp again or not.
+
+    The generated build files are supposed to re-run gyp again themselves, but
+    that doesn't work (or at least it used to not) and we sometimes want to
+    modify the results anyways.
+
+    Args:
+      platform: The platform to check for.
+    """
+    if not os.path.exists(platform.build_ninja()):
+      return True
+    if os.path.getmtime(__file__) > os.path.getmtime(platform.build_ninja()):
+      return True
+    dirs = os.listdir(os.path.join(aos_path(), '..'))
+    # Looking through these folders takes a long time and isn't useful.
+    if dirs.count('output'):
+      dirs.remove('output')
+    if dirs.count('.git'):
+      dirs.remove('.git')
+    return not not subprocess.check_output(
+        ('find',) + tuple(os.path.join(aos_path(), '..', d) for d in dirs)
+        + ('-newer', platform.build_ninja(),
+           '(', '-name', '*.gyp', '-or', '-name', '*.gypi', ')'),
+        stdin=open(os.devnull, 'r'))
+
+  def env(platform):
+    """Makes sure we pass through important environmental variables.
+
+    Returns:
+      An environment suitable for passing to subprocess.Popen and friends.
+    """
+    build_env = dict(platform.build_env())
+    if not 'TERM' in build_env:
+      build_env['TERM'] = os.environ['TERM']
+    if not 'PATH' in build_env:
+      build_env['PATH'] = os.environ['PATH']
+    return build_env
+
+  sorted_platforms = sort_platforms(platforms)
+  user_output('Building %s...' % str_platforms(sorted_platforms))
+
+  if args.action_name == 'tests':
+    for sanitizer, warning in PrimeProcessor.SANITIZER_TEST_WARNINGS.items():
+      warned_about = platforms & processor.select_platforms(sanitizer=sanitizer)
+      if warned_about:
+        user_output(warning[1])
+        if warning[0]:
+          # TODO(brians): Add a --force flag or something to override this?
+          user_output('Refusing to run tests for sanitizer %s.' % sanitizer)
+          exit(1)
+
+  num = 1
+  for platform in sorted_platforms:
+    user_output('Building %s (%d/%d)...' % (platform, num, len(platforms)))
+    if args.action_name == 'clean':
+      shutil.rmtree(platform.outdir(), onerror=handle_clean_error)
+    elif args.action_name == 'environment':
+      user_output('Environment for building <<END')
+      for name, value in env(platform).items():
+        print('%s=%s' % (name, value))
+      print('END')
+    else:
+      if need_to_run_gyp(platform):
+        user_output('Running gyp...')
+        gyp = subprocess.Popen(
+            (tools_config['GYP'],
+             '--check',
+             '--depth=%s' % os.path.join(aos_path(), '..'),
+             '--no-circular-check',
+             '-f', 'ninja',
+             '-I%s' % os.path.join(aos_path(), 'build', 'aos.gypi'),
+             '-I/dev/stdin', '-Goutput_dir=output',
+             '-DOS=%s' % platform.os(),
+             '-DPLATFORM=%s' % platform.gyp_platform(),
+             '-DARCHITECTURE=%s' % platform.architecture(),
+             '-DCOMPILER=%s' % platform.compiler().split('_')[0],
+             '-DFULL_COMPILER=%s' % platform.compiler(),
+             '-DDEBUG=%s' % ('yes' if platform.debug() else 'no'),
+             '-DSANITIZER=%s' % platform.sanitizer(),
+             '-DEXTERNALS_EXTRA=%s' %
+             ('-fPIE' if platform.sanitizer() in PrimeProcessor.PIE_SANITIZERS
+              else '')) +
+            processor.extra_gyp_flags() + (args.main_gyp,),
+            stdin=subprocess.PIPE)
+        gyp.communicate(("""
+{
+  'target_defaults': {
+    'configurations': {
+      '%s': {}
+    }
+  }
+}""" % platform.outname()).encode())
+        if gyp.returncode:
+          user_output("Running gyp failed!")
+          exit(1)
+        processor.modify_ninja_file(platform.build_ninja())
+        user_output('Done running gyp')
+      else:
+        user_output("Not running gyp")
+
+      try:
+        call = (tools_config['NINJA'],
+                '-C', platform.outdir()) + tuple(args.targets)
+        if args.jobs:
+          call += ('-j', str(args.jobs))
+        subprocess.check_call(call,
+                              stdin=open(os.devnull, 'r'),
+                              env=env(platform))
+      except subprocess.CalledProcessError as e:
+        if unknown_platform_error is not None:
+          user_output(unknown_platform_error)
+        raise e
+
+    if args.action_name == 'deploy':
+      platform.deploy(args.dry_run)
+    elif args.action_name == 'tests':
+      dirname = os.path.join(platform.outdir(), 'tests')
+      done_queue = queue.Queue()
+      running = []
+      test_start_semaphore = threading.Semaphore(args.jobs)
+      if args.targets:
+        to_run = []
+        for target in args.targets:
+          if target.endswith('_test'):
+            to_run.append(target)
+      else:
+        to_run = os.listdir(dirname)
+      for f in to_run:
+        thread = TestThread(os.path.join(dirname, f), tuple(args.extra_flags),
+                            env(platform), done_queue,
+                            test_start_semaphore)
+        running.append(thread)
+        thread.start()
+      try:
+        while running:
+          done = done_queue.get()
+          running.remove(done)
+          with test_output_lock:
+            test_output('Output from test %s:' % done.name)
+            try:
+              while True:
+                line = done.output.get(False)
+                if not sys.stdout.isatty():
+                  # Remove color escape codes.
+                  line = re.sub(r'\x1B\[[0-9;]*[a-zA-Z]', '', line)
+                sys.stdout.write(line)
+            except queue.Empty:
+              pass
+            if not done.returncode:
+              test_output('Test %s succeeded' % done.name)
+            else:
+              if done.returncode < 0:
+                sig = -done.returncode
+                test_output('Test %s was killed by signal %d (%s)' % \
+                            (done.name, sig, strsignal(sig)))
+              elif done.returncode != 1:
+                test_output('Test %s exited with %d' % \
+                            (done.name, done.returncode))
+              else:
+                test_output('Test %s failed' % done.name)
+              user_output('Aborting because of test failure for %s.' % \
+                          platform)
+              exit(1)
+      finally:
+        if running:
+          test_output('Killing other tests...')
+# Stop all of them before killing processes because otherwise stopping some of
+# them tends to let other ones that are waiting to start go.
+          for thread in running:
+            thread.stop()
+          for thread in running:
+            test_output('\tKilling %s' % thread.name)
+            thread.kill_process()
+            thread.kill_process()
+          test_output('Waiting for other tests to die')
+          for thread in running:
+            thread.kill_process()
+            thread.join()
+          test_output('Done killing other tests')
+
+    user_output('Done building %s (%d/%d)' % (platform, num, len(platforms)))
+    num += 1
+
+if __name__ == '__main__':
+  main()
diff --git a/aos/build/download_externals.sh b/aos/build/download_externals.sh
new file mode 100755
index 0000000..ca49fd2
--- /dev/null
+++ b/aos/build/download_externals.sh
@@ -0,0 +1,222 @@
+#!/bin/bash
+
+#set -x
+set -e
+
+AOS=$(readlink -f $(dirname $0)/..)
+. $(dirname $0)/tools_config
+
+# A separate variable for stuff that should be in LDFLAGS for everything because
+# the value from CONFIGURE_FLAGS has to get overriden in some places.
+ALL_LDFLAGS=""
+
+# Flags that should get passed to all configure scripts.
+# Some of them need to set LDFLAGS separately to work around stupid configure
+# scripts, so we can't just set that here.
+CONFIGURE_FLAGS=""
+
+if [ "$1" == "arm" ]; then
+  COMPILED=${EXTERNALS}/../compiled-arm
+
+  CROSS_COMPILE=arm-linux-gnueabihf-
+
+  export CC=${CROSS_COMPILE}gcc-4.7
+  export CXX=${CROSS_COMPILE}g++-4.7
+  export CFLAGS="-mcpu=cortex-a8 -mfpu=neon"
+  export CXXFLAGS="-mcpu=cortex-a8 -mfpu=neon"
+  export OBJDUMP=${CROSS_COMPILE}objdump
+  CONFIGURE_FLAGS="--host=arm-linux-gnueabihf CC=${CC} CXX=${CXX} CFLAGS=\"${CFLAGS}\" CXXFLAGS=\"${CXXFLAGS}\" OBJDUMP=${OBJDUMP}"
+elif [ "$1" == "arm_frc" ]; then
+  COMPILED=${EXTERNALS}/../compiled-arm_frc
+
+  CROSS_COMPILE=arm-frc-linux-gnueabi-
+
+  export CC=${CROSS_COMPILE}gcc-4.9
+  export CXX=${CROSS_COMPILE}g++-4.9
+  export CFLAGS="-mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp"
+  export CXXFLAGS="-mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp"
+  export OBJDUMP=${CROSS_COMPILE}objdump
+  CONFIGURE_FLAGS="--host=arm-frc-linux-gnueabi CC=${CC} CXX=${CXX} CFLAGS=\"${CFLAGS}\" CXXFLAGS=\"${CXXFLAGS}\" OBJDUMP=${OBJDUMP}"
+elif [ "$1" == "amd64" ]; then
+  COMPILED=${EXTERNALS}/../compiled-amd64
+elif [ "$1" == "amd64-fPIE" ]; then
+  COMPILED=${EXTERNALS}/../compiled-amd64-fPIE
+
+  export CFLAGS="-fPIE"
+  export CXXFLAGS="-fPIE"
+  ALL_LDFLAGS="-fPIE"
+  export LDFLAGS=${ALL_LDFLAGS}
+  CONFIGURE_FLAGS="CFLAGS=\"${CFLAGS}\" CXXFLAGS=\"${CXXFLAGS}\" LDFLAGS=\"${LDFLAGS}\""
+else
+  echo "Unknown platform $1 to download externals for." 1>&2
+  exit 1
+fi
+
+TMPDIR=/tmp/$$-aos-tmpdir
+mkdir -p ${EXTERNALS}
+[[ -n "${COMPILED}" ]] && mkdir -p ${COMPILED}
+
+# get and build ninja
+[ -d ${NINJA_DIR} ] || git clone --branch ${NINJA_RELEASE} https://github.com/martine/ninja.git ${NINJA_DIR}
+[ -x ${NINJA} ] || env -i "PATH=$PATH" ${NINJA_DIR}/bootstrap.py
+
+# get gyp
+[ -d ${GYP_DIR} ] || ( svn co http://gyp.googlecode.com/svn/trunk -r ${GYP_REVISION} ${GYP_DIR} && patch -p1 -d ${GYP_DIR} < ${AOS}/externals/gyp.patch )
+
+# get eigen
+EIGEN_VERSION=3.2.1
+EIGEN_DIR=${EXTERNALS}/eigen-${EIGEN_VERSION}
+[ -f ${EIGEN_DIR}.tar.bz2 ] || wget http://bitbucket.org/eigen/eigen/get/${EIGEN_VERSION}.tar.bz2 -O ${EIGEN_DIR}.tar.bz2
+[ -d ${EIGEN_DIR} ] || ( mkdir ${EIGEN_DIR} && tar --strip-components=1 -C ${EIGEN_DIR} -xf ${EIGEN_DIR}.tar.bz2 )
+
+# get gtest
+GTEST_VERSION=1.6.0
+GTEST_DIR=${EXTERNALS}/gtest-${GTEST_VERSION}-p2
+GTEST_ZIP=${EXTERNALS}/gtest-${GTEST_VERSION}.zip
+[ -f ${GTEST_ZIP} ] || wget http://googletest.googlecode.com/files/gtest-${GTEST_VERSION}.zip -O ${GTEST_ZIP}
+[ -d ${GTEST_DIR} ] || ( unzip ${GTEST_ZIP} -d ${TMPDIR} && mv ${TMPDIR}/gtest-${GTEST_VERSION} ${GTEST_DIR} && cd ${GTEST_DIR} && patch -p1 < ${AOS}/externals/gtest.patch )
+
+# get and build libjpeg
+LIBJPEG_VERSION=8d
+LIBJPEG_DIR=${COMPILED}/jpeg-${LIBJPEG_VERSION}
+# NOTE: this directory ends up in #include names
+LIBJPEG_PREFIX=${COMPILED}/libjpeg
+LIBJPEG_LIB=${LIBJPEG_PREFIX}/lib/libjpeg.a
+LIBJPEG_TAR=${EXTERNALS}/jpegsrc.v${LIBJPEG_VERSION}.tar.gz
+[ -f ${LIBJPEG_TAR} ] || wget http://www.ijg.org/files/jpegsrc.v${LIBJPEG_VERSION}.tar.gz -O ${LIBJPEG_TAR}
+[ -d ${LIBJPEG_DIR} ] || ( mkdir ${LIBJPEG_DIR} && tar --strip-components=1 -C ${LIBJPEG_DIR} -xf ${LIBJPEG_TAR} )
+[ -f ${LIBJPEG_LIB} ] || bash -c \
+	"cd ${LIBJPEG_DIR} && ./configure --disable-shared \
+	${CONFIGURE_FLAGS} --prefix=`readlink -f ${LIBJPEG_PREFIX}` \
+	&& make && make install"
+
+# get and build ctemplate
+# This is the next revision after the 2.2 release and it only adds spaces to
+# make gcc 4.7 with --std=c++11 happy (user-defined string literals...).
+CTEMPLATE_VERSION=129
+CTEMPLATE_TAR=${EXTERNALS}/ctemplate-${CTEMPLATE_VERSION}.tar.gz
+CTEMPLATE_DIR=${COMPILED}/ctemplate-${CTEMPLATE_VERSION}
+CTEMPLATE_PREFIX=${CTEMPLATE_DIR}-prefix
+CTEMPLATE_LIB=${CTEMPLATE_PREFIX}/lib/libctemplate.a
+CTEMPLATE_URL=http://ctemplate.googlecode.com
+if [[ "${CTEMPLATE_VERSION}" =~ /\./ ]]; then
+	CTEMPLATE_URL=${CTEMPLATE_URL}/files/ctemplate-${CTEMPLATE_VERSION}.tar.gz
+	[ -f ${CTEMPLATE_TAR} ] || \
+		wget ${CTEMPLATE_URL} -O ${CTEMPLATE_TAR}
+	[ -d ${CTEMPLATE_DIR} ] || ( mkdir ${CTEMPLATE_DIR} && tar \
+		--strip-components=1 -C ${CTEMPLATE_DIR} -xf ${CTEMPLATE_TAR} )
+else
+	CTEMPLATE_URL=${CTEMPLATE_URL}/svn/trunk
+	[ -d ${CTEMPLATE_DIR} ] || \
+		svn checkout ${CTEMPLATE_URL} -r ${CTEMPLATE_VERSION} ${CTEMPLATE_DIR}
+fi
+[ -f ${CTEMPLATE_LIB} ] || bash -c "cd ${CTEMPLATE_DIR} && \
+	./configure --disable-shared \
+	${CONFIGURE_FLAGS} --prefix=`readlink -f ${CTEMPLATE_PREFIX}` \
+	&& make && make install"
+
+# get and build gflags
+GFLAGS_VERSION=2.0
+GFLAGS_TAR=${EXTERNALS}/gflags-${GFLAGS_VERSION}.tar.gz
+GFLAGS_DIR=${COMPILED}/gflags-${GFLAGS_VERSION}
+GFLAGS_PREFIX=${GFLAGS_DIR}-prefix
+GFLAGS_LIB=${GFLAGS_PREFIX}/lib/libgflags.a
+GFLAGS_URL=https://gflags.googlecode.com/files/gflags-${GFLAGS_VERSION}.tar.gz
+[ -f ${GFLAGS_TAR} ] || wget ${GFLAGS_URL} -O ${GFLAGS_TAR}
+[ -d ${GFLAGS_DIR} ] || ( mkdir ${GFLAGS_DIR} && tar \
+  --strip-components=1 -C ${GFLAGS_DIR} -xf ${GFLAGS_TAR} )
+[ -f ${GFLAGS_LIB} ] || bash -c "cd ${GFLAGS_DIR} && ./configure \
+  ${CONFIGURE_FLAGS} --prefix=`readlink -f ${GFLAGS_PREFIX}` \
+  && make && make install"
+
+# get and build libevent
+LIBEVENT_VERSION=2.0.21
+LIBEVENT_TAR=${EXTERNALS}/libevent-${LIBEVENT_VERSION}.tar.gz
+LIBEVENT_DIR=${COMPILED}/libevent-${LIBEVENT_VERSION}
+LIBEVENT_PREFIX=${LIBEVENT_DIR}-prefix
+LIBEVENT_LIB=${LIBEVENT_PREFIX}/lib/libevent.a
+LIBEVENT_URL=https://github.com/downloads/libevent/libevent
+LIBEVENT_URL=${LIBEVENT_URL}/libevent-${LIBEVENT_VERSION}-stable.tar.gz
+[ -f ${LIBEVENT_TAR} ] || wget ${LIBEVENT_URL} -O ${LIBEVENT_TAR}
+[ -d ${LIBEVENT_DIR} ] || ( mkdir ${LIBEVENT_DIR} && tar \
+  --strip-components=1 -C ${LIBEVENT_DIR} -xf ${LIBEVENT_TAR} )
+[ -f ${LIBEVENT_LIB} ] || bash -c "cd ${LIBEVENT_DIR} && ./configure \
+	${CONFIGURE_FLAGS} --prefix=`readlink -f ${LIBEVENT_PREFIX}` \
+	&& make && make install"
+
+# get and build gmp
+GMP_VERSION=5.1.3
+GMP_TAR=${EXTERNALS}/gmp-${GMP_VERSION}.tar.lz
+GMP_DIR=${COMPILED}/gmp-${GMP_VERSION}
+GMP_PREFIX=${GMP_DIR}-prefix
+GMP_LIB=${GMP_PREFIX}/lib/libgmp.a
+GMP_URL=https://gmplib.org/download/gmp/gmp-${GMP_VERSION}.tar.lz
+[ -f ${GMP_TAR} ] || wget ${GMP_URL} -O ${GMP_TAR}
+[ -d ${GMP_DIR} ] || ( mkdir ${GMP_DIR} && tar \
+	--strip-components=1 -C ${GMP_DIR} -xf ${GMP_TAR} )
+[ -f ${GMP_LIB} ] || bash -c "cd ${GMP_DIR} && ./configure \
+	${CONFIGURE_FLAGS} --prefix=$(readlink -f ${GMP_PREFIX}) \
+	&& make && make install"
+
+# get and build libcdd
+LIBCDD_VERSION=094g
+LIBCDD_TAR=${EXTERNALS}/libcdd-${LIBCDD_VERSION}.tar.gz
+LIBCDD_DIR=${COMPILED}/libcdd-${LIBCDD_VERSION}
+LIBCDD_PREFIX=${LIBCDD_DIR}-prefix
+LIBCDD_LIB=${LIBCDD_PREFIX}/lib/libcdd.a
+LIBCDD_URL=ftp://ftp.ifor.math.ethz.ch/pub/fukuda/cdd/cddlib-${LIBCDD_VERSION}.tar.gz
+[ -f ${LIBCDD_TAR} ] || \
+        wget ${LIBCDD_URL} -O ${LIBCDD_TAR}
+[ -d ${LIBCDD_DIR} ] || ( mkdir ${LIBCDD_DIR} && tar \
+        --strip-components=1 -C ${LIBCDD_DIR} -xf ${LIBCDD_TAR} )
+[ -f ${LIBCDD_LIB} ] || \
+	bash -c "cd ${LIBCDD_DIR} && ./configure \
+	--disable-shared ${CONFIGURE_FLAGS} \
+	LDFLAGS=\"${ALL_LDFLAGS} -L${GMP_PREFIX}/lib\" \
+	--prefix=$(readlink -f ${LIBCDD_PREFIX}) \
+	&& make gmpdir=${GMP_PREFIX} && make install"
+
+# get and build libunwind
+LIBUNWIND_VERSION=1.1
+LIBUNWIND_TAR=${EXTERNALS}/libunwind-${LIBUNWIND_VERSION}.tar.gz
+LIBUNWIND_DIR=${COMPILED}/libunwind-${LIBUNWIND_VERSION}
+LIBUNWIND_PREFIX=${LIBUNWIND_DIR}-prefix
+LIBUNWIND_LIB=${LIBUNWIND_PREFIX}/lib/libunwind.a
+LIBUNWIND_URL=http://download.savannah.gnu.org/releases/libunwind/libunwind-${LIBUNWIND_VERSION}.tar.gz
+[ -f ${LIBUNWIND_TAR} ] || \
+	wget ${LIBUNWIND_URL} -O ${LIBUNWIND_TAR}
+[ -d ${LIBUNWIND_DIR} ] || ( mkdir ${LIBUNWIND_DIR} && tar \
+	--strip-components=1 -C ${LIBUNWIND_DIR} -xf ${LIBUNWIND_TAR} )
+[ -f ${LIBUNWIND_LIB} ] || \
+	bash -c "cd ${LIBUNWIND_DIR} && ./configure \
+	--prefix=$(readlink -f ${LIBUNWIND_PREFIX}) \
+	${CONFIGURE_FLAGS} \
+	&& make && make install"
+
+# get and build gperftools
+GPERFTOOLS_VERSION=2.3
+GPERFTOOLS_TAR=${EXTERNALS}/gperftools-${GPERFTOOLS_VERSION}.tar.gz
+GPERFTOOLS_DIR=${COMPILED}/gperftools-${GPERFTOOLS_VERSION}
+GPERFTOOLS_PREFIX=${GPERFTOOLS_DIR}-prefix
+TCMALLOC_LIB=${GPERFTOOLS_PREFIX}/lib/libtcmalloc.a
+GPERFTOOLS_URL=https://googledrive.com/host/0B6NtGsLhIcf7MWxMMF9JdTN3UVk/gperftools-2.3.tar.gz
+[ -f ${GPERFTOOLS_TAR} ] || \
+	wget ${GPERFTOOLS_URL} -O ${GPERFTOOLS_TAR}
+[ -d ${GPERFTOOLS_DIR} ] || ( mkdir ${GPERFTOOLS_DIR} && tar \
+	--strip-components=1 -C ${GPERFTOOLS_DIR} -xf ${GPERFTOOLS_TAR} )
+[ -f ${TCMALLOC_LIB} ] || \
+	bash -c "cd ${GPERFTOOLS_DIR} && ./configure \
+	${CONFIGURE_FLAGS} --prefix=$(readlink -f ${GPERFTOOLS_PREFIX}) \
+	LDFLAGS=\"${ALL_LDFLAGS} -L${LIBUNWIND_PREFIX}/lib -Wl,-rpath-link=${LIBUNWIND_PREFIX}/lib\" \
+	CPPFLAGS=\"-I ${LIBUNWIND_PREFIX}/include\" \
+	&& make && make install"
+
+# get and build seasocks
+SEASOCKS_VERSION=1.1.2
+SEASOCKS_PATCH=1
+SEASOCKS_DIR=${EXTERNALS}/seasocks-${SEASOCKS_VERSION}-p${SEASOCKS_PATCH}
+[ -d ${SEASOCKS_DIR} ] || ( git clone --branch v${SEASOCKS_VERSION} \
+  https://github.com/mattgodbolt/seasocks.git ${SEASOCKS_DIR} && \
+  patch -p1 -d ${SEASOCKS_DIR} < ${AOS}/externals/seasocks.patch )
+
+rm -rf ${TMPDIR}
diff --git a/aos/build/externals.gyp b/aos/build/externals.gyp
new file mode 100644
index 0000000..c4bbaa2
--- /dev/null
+++ b/aos/build/externals.gyp
@@ -0,0 +1,219 @@
+# This file has targets for various external libraries.
+# download_externals.sh makes sure that all of them have been downloaded.
+{
+  'variables': {
+    'externals': '<(AOS)/../output/downloaded',
+    'externals_abs': '<!(readlink -f ../../output/downloaded)',
+    'compiled': '<(externals)/../compiled-<(ARCHITECTURE)<(EXTERNALS_EXTRA)',
+    'compiled_abs': '<(externals_abs)/../compiled-<(ARCHITECTURE)<(EXTERNALS_EXTRA)',
+
+# These versions have to be kept in sync with the ones in download_externals.sh.
+    'eigen_version': '3.2.1',
+    'gtest_version': '1.6.0-p2',
+    'ctemplate_version': '129',
+    'gflags_version': '2.0',
+    'compiler_rt_version': 'RELEASE_32_final',
+    'libevent_version': '2.0.21',
+    'libcdd_version': '094g',
+    'stm32flash_commit': '8399fbe1baf2b7d097746786458021d92895d71b',
+    'seasocks_version': '1.1.2-p1',
+
+    'allwpilib': '<(AOS)/externals/allwpilib',
+    'forwpilib': '<(AOS)/externals/forwpilib',
+  },
+  'targets': [
+    {
+      'target_name': 'WPILib',
+      'type': 'static_library',
+      'variables': {
+        'header_dirs': [
+          '<(forwpilib)',
+          '<(allwpilib)/wpilibc/wpilibC++/include',
+          '<(allwpilib)/wpilibc/wpilibC++Devices/include',
+          '<(allwpilib)/hal/include',
+          '<(allwpilib)/hal/lib/Athena/FRC_FPGA_ChipObject',
+          '<(allwpilib)/hal/lib/Athena',
+        ],
+      },
+      'include_dirs': [
+        '<@(header_dirs)'
+      ],
+      'cflags': [
+        '-Wno-error',
+        '-fno-strict-aliasing',
+        '-O0',
+      ],
+      'sources': [
+        '<!@(ls <(allwpilib)/wpilibc/wpilibC++/src/*.cpp)',
+        '<!@(ls <(allwpilib)/wpilibc/wpilibC++Devices/src/*.cpp)',
+        '<!@(ls <(allwpilib)/wpilibc/wpilibC++Devices/src/Internal/*.cpp)',
+        '<!@(ls <(allwpilib)/hal/lib/Athena/*.cpp)',
+        '<!@(ls <(allwpilib)/hal/lib/Athena/ctre/*.cpp)',
+        '<(forwpilib)/dma.cc',
+      ],
+      'link_settings': {
+        'library_dirs': [
+          '<(allwpilib)/ni-libraries',
+        ],
+        'libraries': [
+          '-lpthread',
+          '-lFRC_NetworkCommunication',
+          '-lRoboRIO_FRC_ChipObject',
+          '-lNiFpgaLv',
+          '-lNiFpga',
+          '-lNiRioSrv',
+          '-lspi',
+          '-li2c',
+        ],
+      },
+      'direct_dependent_settings': {
+        'include_dirs': [
+          '<@(header_dirs)'
+        ],
+      },
+    },
+    {
+      'target_name': 'opencv',
+      'type': 'none',
+      'link_settings': {
+        'libraries': [
+          '-lopencv_core',
+          '-lopencv_imgproc',
+        ],
+      },
+    },
+    {
+      'target_name': 'libevent',
+      'type': 'none',
+      'link_settings': {
+        'libraries': ['<(compiled_abs)/libevent-<(libevent_version)-prefix/lib/libevent.a'],
+      },
+      'direct_dependent_settings': {
+        'include_dirs': ['<(compiled)/libevent-<(libevent_version)-prefix/include'],
+      },
+    },
+    {
+      'target_name': 'eigen',
+      'type': 'none',
+      'direct_dependent_settings': {
+        'cflags': [
+          '-isystem', '<(externals)/eigen-<(eigen_version)'
+        ],
+      },
+    },
+    {
+      'target_name': 'libjpeg',
+      'type': 'none',
+      'direct_dependent_settings': {
+        'libraries': ['<(compiled_abs)/libjpeg/lib/libjpeg.a'],
+        'cflags': [
+          '-isystem', '<(compiled)',
+        ],
+      },
+    },
+    {
+# Dependents should only use the "gtest/gtest_prod.h" header.
+# This target is NOT the correct one for "aos/common/gtest_prod.h". That one is
+#   aos/common/common.gyp:gtest_prod. This target just deals with setting up to
+#   use the gtest header.
+      'target_name': 'gtest_prod',
+      'type': 'static_library',
+      'direct_dependent_settings': {
+        'include_dirs': [
+          '<(externals)/gtest-<(gtest_version)/include'
+        ],
+      },
+    },
+    {
+      'target_name': 'gtest',
+      'type': 'static_library',
+      'sources': [
+        '<(externals)/gtest-<(gtest_version)/src/gtest-all.cc',
+        '<(AOS)/externals/gtest/gtest_main.cc',
+      ],
+      'include_dirs': [
+        '<(externals)/gtest-<(gtest_version)',
+      ],
+      'dependencies': [
+        'gtest_prod',
+      ],
+      'export_dependent_settings': [
+        'gtest_prod',
+      ],
+      'cflags!': ['-Werror'],
+      'direct_dependent_settings': {
+        'include_dirs': ['<(externals)/gtest-<(gtest_version)/include'],
+        'target_conditions': [
+          ['_type=="executable" and is_special_test==0', {
+              'product_dir': '<(test_dir)',
+            },
+          ], ['_type=="executable" and is_special_test==1', {
+              'product_dir': '<(test_dir)-special',
+            },
+          ],
+        ],
+      },
+    },
+    {
+      'target_name': 'ctemplate',
+      'type': 'none',
+      'link_settings': {
+        'libraries': ['<(compiled_abs)/ctemplate-<(ctemplate_version)-prefix/lib/libctemplate.a'],
+      },
+      'direct_dependent_settings': {
+        'include_dirs': ['<(compiled)/ctemplate-<(ctemplate_version)-prefix/include'],
+      },
+    },
+    {
+      'target_name': 'gflags',
+      'type': 'none',
+      'link_settings': {
+        'libraries': ['<(compiled_abs)/gflags-<(gflags_version)-prefix/lib/libgflags.a'],
+      },
+      'direct_dependent_settings': {
+        'include_dirs': ['<(compiled)/gflags-<(gflags_version)-prefix/include'],
+      },
+    },
+    {
+      'target_name': 'libcdd',
+      'type': 'none',
+      'link_settings': {
+        'libraries': ['<(compiled_abs)/libcdd-<(libcdd_version)-prefix/lib/libcdd.a'],
+      },
+      'direct_dependent_settings': {
+        'include_dirs': ['<(compiled_abs)/'],
+      },
+    },
+    {
+      'target_name': 'seasocks',
+      'type': 'static_library',
+      'sources': [
+        '<!@(find <(externals)/seasocks-<(seasocks_version)/src/main/c -name *.cpp)',
+      ],
+      'include_dirs': [
+        '<(AOS)/externals/seasocks',
+        '<(externals_abs)/seasocks-<(seasocks_version)/src/main/c',
+      ],
+      'cflags': [
+        '-Wno-unused-parameter',
+        '-Wno-format-nonliteral',
+        '-Wno-error=cast-align',
+        '-Wno-switch-enum',
+        '-Wno-cast-qual',
+        '-Wno-error=strict-aliasing',
+      ],
+      'direct_dependent_settings': {
+        'include_dirs': [
+          '<(AOS)/externals/seasocks',
+          '<(externals)/seasocks-<(seasocks_version)/src/main/c',
+        ],
+        'cflags': [
+          # Since seasocks/WebSocket.h has functions implemented that don't use
+          # their parameters, the compilation of http_status would fail without
+          # the following exception.
+          '-Wno-unused-parameter',
+        ],
+      },
+    },
+  ],
+}
diff --git a/aos/build/queues.gypi b/aos/build/queues.gypi
new file mode 100644
index 0000000..7c0343a
--- /dev/null
+++ b/aos/build/queues.gypi
@@ -0,0 +1,83 @@
+# Include this file in any target that needs to use files generated from queue
+#   etc. definitions.
+#
+# To use, create a target of the following form:
+# {
+#   'target_name': 'my_queues',
+#   'type': 'static_library', # or any other type that can handle .cc files
+#   'sources': [
+#     'aos/example/Queue.q',
+#     'aos/example/ControlLoop.q',
+#   ],
+#   'variables': {
+#     'header_path': 'aos/example',
+#   },
+#   'includes': ['path/to/queues.gypi'],
+# },
+# Code that depends on this target will be able to #include
+#   "aos/example/Queue.q.h" and "aos/example/ControlLoop.q.h".
+#
+# using <http://src.chromium.org/svn/trunk/src/build/protoc.gypi> as an
+# example of how this should work
+{
+  'variables': {
+    #'header_path': '>!(python -c "import os.path; print os.path.relpath(\'<(RULE_INPUT_PATH)\', \'<(DEPTH)\')")',
+    'prefix_dir': '<(SHARED_INTERMEDIATE_DIR)/<!(echo <(header_path) | sed "s/[^A-Za-z0-9]/_/g")',
+    'out_dir': '<(prefix_dir)/<(_target_name)/<(header_path)',
+    'gen_namespace%': '>!(echo >(header_path) | sed "s:\([^/]*\).*:\\1:g")',
+    'output_h': '<(out_dir)/<(RULE_INPUT_ROOT).q.h',
+    'output_cc': '<(out_dir)/<(RULE_INPUT_ROOT).q.cc',
+    'output_main': '<(out_dir)/<(RULE_INPUT_ROOT)_main.cc',
+    'no_rsync': 1,
+    'aos_q_dependent_paths%': [],
+  },
+  'rules': [
+    {
+      'variables': {
+        'script': '<(AOS)/build/queues/compiler.rb',
+      },
+      'rule_name': 'genqueue',
+      'extension': 'q',
+      'outputs': [
+        '<(output_h)',
+        '<(output_cc)',
+      ],
+      'inputs': [
+        '<(script)',
+        '<!@(find <(AOS)/build/queues/ -name *.rb)',
+        '<(AOS)/common/queue.h',
+        '<(AOS)/common/time.h',
+        '>@(aos_q_dependent_paths)',
+      ],
+      'action': ['ruby', '<(script)',
+        '-I', '<(DEPTH)',
+        '<(RULE_INPUT_PATH)',
+        '-cpp_out',
+        '<(header_path)',
+        '-cpp_base',
+        '<(prefix_dir)/<(_target_name)'],
+      'message': 'Generating C++ code for <(header_path)/<(RULE_INPUT_PATH)',
+      'process_outputs_as_sources': 1,
+    },
+  ],
+  'include_dirs': [
+    '<(prefix_dir)/<(_target_name)',
+  ],
+  'direct_dependent_settings': {
+    'include_dirs': [
+      '<(prefix_dir)/<(_target_name)',
+    ],
+    'variables': {
+      'aos_q_dependent_paths': ['<@(_sources)'],
+    },
+  },
+  'dependencies': [
+    '<(AOS)/common/common.gyp:queues',
+    '<(AOS)/common/common.gyp:once',
+    '<(AOS)/common/common.gyp:queue_types',
+  ],
+  'export_dependent_settings': [
+    '<(AOS)/common/common.gyp:queues',
+  ],
+  'hard_dependency': 1,
+}
diff --git a/aos/build/queues/compiler.rb b/aos/build/queues/compiler.rb
new file mode 100644
index 0000000..52c0005
--- /dev/null
+++ b/aos/build/queues/compiler.rb
@@ -0,0 +1,131 @@
+require File.dirname(__FILE__) + '/load.rb'
+
+def parse_args(globals,args)
+	i = 0
+	while(i < args.length)
+		if(args[i] == "-I")
+			args.delete_at(i)
+			if(!args[i])
+				$stderr.puts "hey! -I is followed by nothing."
+				$stderr.puts "\tnot a supported usage..."
+				$stderr.puts "\tWot. Wot."
+				exit!(-1)
+			end
+			path = args.delete_at(i)
+			globals.add_path(path)
+		elsif(args[i] == "-cpp_out")
+			args.delete_at(i)
+			path = args.delete_at(i)
+			if(path =~ /\./)
+				$stderr.puts "hey! path #{path} has a \".\" char which is "
+				$stderr.puts "\tnot a supported usage..."
+				$stderr.puts "\tWot. Wot."
+				exit!(-1)
+			elsif(!path)
+				$stderr.puts "hey! No cpp_out path provided."
+				$stderr.puts "\tumm, you could try -cpp_out \"\""
+				$stderr.puts "\tThat might do the trick"
+				$stderr.puts "\tWot. Wot."
+				exit!(-1)
+			end
+			$cpp_out = path.split(/\\|\//)
+		elsif(args[i] == "-cpp_base")
+			args.delete_at(i)
+			path = args.delete_at(i)
+			$cpp_base = File.expand_path(path)
+			if(!File.exists?($cpp_base))
+				$stderr.puts "output directory #{$cpp_base.inspect} does not exist."
+				$stderr.puts "\tI'm not going to make that! sheesh, who do you think I am?"
+				$stderr.puts "\tWot. Wot."
+				exit!(-1)
+			end
+		elsif(args[i] =~ /^-/)
+			$stderr.puts "hey! unknown argument #{args[i]}."
+			$stderr.puts "\tWot. Wot."
+			exit!(-1)
+		else
+			i += 1
+		end
+	end
+	if(!$cpp_base)
+		$stderr.puts "hey! missing -cpp_base argument."
+		$stderr.puts "\tWot. Wot."
+		exit!(-1)
+	end
+	if(!$cpp_out)
+		$stderr.puts "hey! missing -cpp_out argument."
+		$stderr.puts "\tWot. Wot."
+		exit!(-1)
+	end
+end
+def format_pipeline(output)
+  read_in, write_in = IO.pipe()
+  child = Process.spawn('/usr/bin/clang-format-3.5 --style=google',
+                        {:in=>read_in, write_in=>:close,
+                         :out=>output.fileno})
+  read_in.close
+  [child, write_in]
+end
+def build(filename,globals_template)
+	globals = Globals.new()
+	globals_template.paths.each do |path|
+		globals.add_path(path)
+	end
+	filename = File.expand_path(filename)
+	q_file = QFile.parse(filename)
+	output_file = q_file.q_eval(globals)
+	q_filename = File.basename(filename)
+	rel_path = ($cpp_out + [q_filename]).join("/")
+
+	FileUtils.mkdir_p(Pathname.new($cpp_base) + $cpp_out.join("/"))
+
+	cpp_tree = output_file.make_cpp_tree(rel_path)
+
+	h_file_path = $cpp_base + "/" + rel_path + ".h"
+	cc_file_path = $cpp_base + "/" + rel_path + ".cc"
+	cpp_tree.add_cc_include((rel_path + ".h").inspect)
+	cpp_tree.add_cc_include("aos/common/byteorder.h".inspect)
+	cpp_tree.add_cc_include("<inttypes.h>")
+	cpp_tree.add_cc_include("aos/common/queue_types.h".inspect)
+  cpp_tree.add_cc_include("aos/common/once.h".inspect)
+  cpp_tree.add_cc_include("aos/common/logging/logging_printf_formats.h".inspect)
+	cpp_tree.add_cc_using("::aos::to_network")
+	cpp_tree.add_cc_using("::aos::to_host")
+
+	header_file = WriteIffChanged.new(h_file_path)
+	cc_file = WriteIffChanged.new(cc_file_path)
+  header_child, header_output = format_pipeline(header_file)
+  cc_child, cc_output = format_pipeline(cc_file)
+	cpp_tree.write_header_file($cpp_base,header_output)
+	cpp_tree.write_cc_file($cpp_base,cc_output)
+	header_output.close()
+	cc_output.close()
+  if !Process.wait2(cc_child)[1].success?
+    $stderr.puts "Formatting cc file failed."
+    exit 1
+  end
+  if !Process.wait2(header_child)[1].success?
+    $stderr.puts "Formatting header file failed."
+    exit 1
+  end
+  header_file.close()
+  cc_file.close()
+end
+begin
+	args = ARGV.dup
+	globals = Globals.new()
+	parse_args(globals,args)
+	if(args.length == 0)
+		$stderr.puts "hey! you want me to do something,"
+		$stderr.puts "\tbut you gave me no q files to build!"
+		$stderr.puts "\tWot. Wot."
+		exit!(-1)
+	end
+	args.each do |filename|
+		build(filename,globals)
+	end
+	exit(0)
+rescue QError => e
+	$stderr.print(e.to_s)
+	exit!(-1)
+end
diff --git a/aos/build/queues/cpp_pretty_print/auto_gen.rb b/aos/build/queues/cpp_pretty_print/auto_gen.rb
new file mode 100644
index 0000000..d3fb480
--- /dev/null
+++ b/aos/build/queues/cpp_pretty_print/auto_gen.rb
@@ -0,0 +1,306 @@
+module CPP
+end
+class CPP::Comment
+	def initialize(text)
+		@text = text
+	end
+	def pp(state)
+		state.needs_semi = false
+		if(@text.include?("\n"))
+			state.print("/* #{@text} */")
+		else
+			state.print("// #{@text}")
+		end
+	end
+end
+class CPP::TODO < CPP::Comment
+	def initialize(owner,text)
+		@text = "TODO(#{owner}): #{text}"
+	end
+end
+class CPP::StaticVar
+	class ForwardDec
+		def initialize(func) ; @func = func ; end
+		def pp(state) ; @func.pp_forward_dec(state) ; end
+	end
+	attr_accessor :args, :static
+	def initialize(type_class, val_type, name, args = CPP::Args.new())
+		@type_class = type_class
+		@val_type = val_type
+		@name = name
+		@args = args
+		@static = true
+	end
+	def forward_dec() ; ForwardDec.new(self) ; end
+	def pp_forward_dec(state)
+    if (@static)
+      state.print("static ")
+		end
+		state.print("#{@val_type} #{@name}")
+	end
+	def pp(state)
+		state.print("#{@val_type} #{@type_class.chop_method_prefix}#{@name}(")
+		state.pp(@args)
+		state.print(")")
+	end
+	alias_method :pp_header_file, :pp_forward_dec
+	alias_method :pp_cc_file, :pp
+end
+class CPP::MemberFunc
+	class ForwardDec
+		def initialize(func) ; @func = func ; end
+		def pp(state) ; @func.pp_forward_dec(state) ; end
+	end
+	attr_accessor :args,:suite,:return_type,:name,:pre_func_types,:const,:static,:virtual
+	def initialize(type_class,return_type,name)
+		@type_class = type_class
+		@return_type = return_type
+		@name = name
+		@const = false
+		@static = false
+		@virtual = false
+		@args = CPP::Args.new()
+		@suite = CPP::Suite.new()
+	end
+	attr_accessor :inline
+	def forward_dec() ; ForwardDec.new(self) ; end
+	def pp_forward_dec(state)
+		return self.pp_inline(state) if(@inline)
+        if (@static)
+          state.print("static ")
+				elsif (@virtual)
+          state.print("virtual ")
+        end
+		state.print("#{@return_type} #{@pre_func_types}#{@name}(")
+		state.pp(@args)
+		state.print(")")
+        if (@const)
+          state.print(" const")
+        end
+	end
+	def pp_inline(state)
+        if (@static)
+          state.print("static ")
+				elsif (@virtual)
+          state.print("virtual ")
+        end
+		state.print("#{@return_type} #{@pre_func_types}#{@name}(")
+		state.pp(@args)
+		state.print(") ")
+        if (@const)
+          state.print(" const")
+        end
+		@suite.pp_one_line(state)
+	end
+	def pp(state)
+		return if(@inline)
+		state.print("#{@return_type} #{@pre_func_types}#{@type_class.chop_method_prefix}#{@name}(")
+		state.pp(@args)
+		state.print(") ")
+		if (@const)
+			state.print("const ")
+		end
+		state.pp(@suite)
+		state.v_pad(2)
+	end
+	alias_method :pp_header_file, :pp_forward_dec
+	alias_method :pp_cc_file, :pp
+	
+end
+class CPP::Constructor
+	class ForwardDec
+		def initialize(func) ; @func = func ; end
+		def pp(state) ; @func.pp_forward_dec(state) ; end
+	end
+	attr_accessor :args,:suite,:return_type,:name
+	def initialize(type_class)
+		@type_class = type_class
+		@args = CPP::Args.new()
+		@suite = CPP::Suite.new()
+		@var_cons = CPP::Args.new()
+	end
+	def forward_dec() ; ForwardDec.new(self) ; end
+	def add_cons(*args)
+		@var_cons.push(CPP::FuncCall.build(*args))
+	end
+	def pp_forward_dec(state)
+		state.print("#{@type_class.name}(")
+		state.pp(@args)
+		state.print(")")
+	end
+	def pp_inline(state)
+		pp(state,false)
+	end
+	def pp(state,prefix = true)
+		state.needs_semi = false
+		state.print(@type_class.chop_method_prefix) if(prefix)
+		state.print("#{@type_class.name}(")
+		state.pp(@args)
+		if(@var_cons.length >= 1)
+			state.print(")")
+			state.endline()
+			state.indent += 4
+			state.print(": ")
+			state.pp(@var_cons)
+			state.indent -= 4
+			state.print(" ")
+		else
+			state.print(") ")
+		end
+		state.pp(@suite)
+		state.v_pad(2)
+	end
+	alias_method :pp_header_file, :pp_forward_dec
+	alias_method :pp_cc_file, :pp
+end
+class CPP::Destructor
+	class ForwardDec
+		def initialize(func) ; @func = func ; end
+		def pp(state) ; @func.pp_forward_dec(state) ; end
+	end
+	attr_accessor :args,:suite,:return_type,:name
+	def initialize(type_class)
+		@type_class = type_class
+		@args = CPP::Args.new()
+		@suite = CPP::Suite.new()
+	end
+	def forward_dec() ; ForwardDec.new(self) ; end
+	def pp_forward_dec(state)
+		state.print("~#{@type_class.name}(")
+		state.pp(@args)
+		state.print(")")
+	end
+	def pp(state)
+		state.print("#{@type_class.chop_method_prefix}~#{@type_class.name}(")
+		state.pp(@args)
+		state.print(") ")
+		state.pp(@suite)
+		state.v_pad(2)
+	end
+	alias_method :pp_header_file, :pp_forward_dec
+	alias_method :pp_cc_file, :pp
+end
+class CPP::Include
+	attr_accessor :filename
+	def initialize(filename)
+		@filename = filename
+	end
+	def pp(state)
+		state.needs_semi = false
+		state.suppress_indent()
+		state.print("#include #{@filename}")
+		state.endline()
+	end
+end
+class CPP::IncludeGuard
+	attr_accessor :name,:suite
+	def initialize(suite = CPP::Suite.new())
+		@suite = suite
+	end
+	def self.rand_name(len = 40)
+		str = ""
+		len.times { str += ((rand(26) + ?A).chr)}
+		return str
+	end
+	def pp(state)
+		@name ||= IncludeGuard.rand_name
+		state.needs_semi = false
+		state.suppress_indent()
+		state.print("#ifndef #{@name}")
+		state.endline()
+		state.suppress_indent()
+		state.print("#define #{@name}")
+		state.endline()
+		if(@suite.respond_to?(:pp_no_braces))
+			@suite.pp_no_braces(state)
+		else
+			state.pp(@suite)
+		end
+		state.endline()
+		state.needs_semi = false
+		state.suppress_indent()
+		state.print("#endif  // #{@name}")
+		state.endline()
+	end
+end
+class CPP::IfnDef
+	attr_accessor :name,:suite
+	def initialize(suite = CPP::Suite.new())
+		@suite = suite
+	end
+	def pp(state)
+		state.needs_semi = false
+		state.suppress_indent()
+		state.print("#ifndef #{@name}")
+		state.endline()
+		if(@suite.respond_to?(:pp_no_braces))
+			@suite.pp_no_braces(state)
+		else
+			state.pp(@suite)
+		end
+		state.endline()
+		state.needs_semi = false
+		state.suppress_indent()
+		state.print("#endif  // #{@name}")
+		state.endline()
+	end
+end
+class CPP::PreprocessorIf
+	attr_accessor :name,:suite
+	def initialize(ifsuite, elsesuite)
+		@ifsuite = ifsuite
+		@elsesuite = elsesuite
+	end
+	def write_if(state)
+		state.needs_semi = false
+		state.suppress_indent()
+		state.print("#if #{@name}")
+		state.endline()
+	end
+	def write_else(state)
+		state.needs_semi = false
+		state.suppress_indent()
+		state.print("#else  // #{@name}")
+		state.endline()
+	end
+	def write_endif(state)
+		state.needs_semi = false
+		state.suppress_indent()
+		state.print("#endif  // #{@name}")
+		state.endline()
+	end
+	def pp_inline(state)
+		self.write_if(state)
+		@ifsuite.pp_inline(state)
+		if(@elsesuite != nil)
+			self.write_else(state)
+			@elsesuite.pp_inline(state)
+		end
+		self.write_endif(state)
+	end
+	def pp(state)
+		self.write_if(state)
+		if(@ifsuite.respond_to?(:pp_no_braces))
+			@ifsuite.pp_no_braces(state)
+		else
+			state.pp(@ifsuite)
+		end
+		if(@elsesuite != nil)
+			self.write_else(state)
+			if(@elsesuite.respond_to?(:pp_no_braces))
+				@elsesuite.pp_no_braces(state)
+			else
+				state.pp(@elsesuite)
+			end
+		end
+		self.write_endif(state)
+	end
+end
+class CPP::Using
+	def initialize(using)
+		@using = using
+	end
+	def pp(state)
+		state.print("using #{@using}")
+	end
+end
diff --git a/aos/build/queues/cpp_pretty_print/dep_file_pair.rb b/aos/build/queues/cpp_pretty_print/dep_file_pair.rb
new file mode 100644
index 0000000..63b3fbd
--- /dev/null
+++ b/aos/build/queues/cpp_pretty_print/dep_file_pair.rb
@@ -0,0 +1,470 @@
+class GroupElement
+	def add_group_dep(group_dep)
+		@group_dep = group_dep
+	end
+	def adjust_group(state,old_group)
+		if(@group_dep != old_group)
+			@group_dep.adjust_from(state,old_group)
+		end
+		return @group_dep
+	end
+end
+class DepMask < GroupElement
+	def initialize(elem)
+		@elem = elem
+		@deps = []
+	end
+	def add_dep(dep)
+		@deps << dep
+		self
+	end
+	def method_missing(method,*args,&blk)
+		@elem.send(method,*args,&blk)
+	end
+	alias_method :old_respond_to, :respond_to?
+	def respond_to?(method)
+		old_respond_to(method) || @elem.respond_to?(method)
+	end
+end
+
+class MemberElementHeader < GroupElement
+	def initialize(elem)
+		@elem = elem
+	end
+	def pp(state)
+		if(@elem.respond_to?(:pp_header_file))
+			@elem.pp_header_file(state)
+		else
+			state.pp(@elem)
+		end
+	end
+	def self.check(plan,elem)
+		plan.push(self.new(elem))
+	end
+end
+class MemberElementInline < GroupElement
+	def initialize(elem)
+		@elem = elem
+	end
+	def pp(state)
+		if(@elem.respond_to?(:pp_inline))
+			@elem.pp_inline(state)
+		else
+			state.pp(@elem)
+		end
+	end
+end
+class MemberElementCC < GroupElement
+	attr_accessor :pp_override
+	def initialize(elem)
+		@elem = elem
+	end
+	def pp(state)
+		return state.pp(@elem) if(@pp_override)
+		@elem.pp_cc_file(state)
+	end
+	def self.check(plan,elem)
+		plan.push(self.new(elem)) if(elem.respond_to?(:pp_cc_file))
+	end
+end
+class ImplicitName
+	attr_accessor :parent
+	def initialize(name,parent)
+		@name = name
+		@parent = parent
+	end
+	def close(state)
+		state.endline()
+		state.needs_semi = false
+		state.print("}  // namespace #{@name}\n")
+	end
+	def name()
+		if(@parent)
+			return @parent.name + "." + @name
+		else
+			return "." + @name
+		end
+	end
+	def open(state)
+		state.endline()
+		state.needs_semi = false
+		state.print("namespace #{@name} {\n")
+	end
+	def adjust_from(state,old_group)
+		close_grps = []
+		grp = old_group
+		while(grp)
+			close_grps << grp
+			grp = grp.parent
+		end
+		open_grps = []
+		grp = self
+		while(grp)
+			open_grps << grp
+			grp = grp.parent
+		end
+		while(open_grps[-1] == close_grps[-1] && close_grps[-1])
+			close_grps.pop()
+			open_grps.pop()
+		end
+		close_grps.each do |grp|
+			grp.close(state)
+		end
+		open_grps.reverse.each do |grp|
+			grp.open(state)
+		end
+	end
+	def adjust_to(state,new_group)
+		grp = self
+		while(grp)
+			grp.close(state)
+			grp = grp.parent
+		end
+	end
+end
+class GroupPlan < GroupElement
+	attr_accessor :implicit
+	def initialize(group_elem,members = [])
+		@group_elem = group_elem
+		@members = CPP::Suite.new(members)
+	end
+	def push(mem)
+		mem.add_group_dep(@implicit) if(@implicit)
+		@members << mem
+	end
+	def pp(state)
+		if(@group_elem)
+			@group_elem.open(state)
+		end
+		group = nil
+		@members.each do |member|
+			group = member.adjust_group(state,group)
+			#puts "at:#{group.name}" if(group.respond_to?(:name))
+			state.endline()
+			state.needs_semi = true
+			state.pp(member)
+			state.endline()
+		end
+		group.adjust_to(state,nil) if(group)
+		if(@group_elem)
+			@group_elem.close(state)
+		end
+	end
+end
+class CC_Mask
+	def initialize(elem)
+		@elem = elem
+	end
+	def plan_cc(plan)
+		elem = MemberElementCC.new(@elem)
+		elem.pp_override = true
+		plan.push(elem)
+	end
+	def plan_header(plan);
+	end
+end
+module Types
+	class TypeDef
+		def initialize(type,name)
+			@type = type
+			@name = name
+		end
+		def pp(state)
+			state.pp("typedef #{@type.name} #{@name}")
+		end
+	end
+	class Type
+		attr_accessor :name,:static,:dec,:space
+		def initialize(namespace,name)
+			@space = namespace
+			@name = name
+			@members = []
+			@protections = {}
+			@deps = []
+		end
+    def parent_class
+      @parent.split(' ')[1] if @parent
+    end
+		class ProtectionGroup
+			def initialize(name)
+				@name = name
+			end
+			def adjust_from(state,other)
+				state.indent -= 1
+				state.pp("#@name:")
+				state.endline
+				state.indent += 1
+			end
+			def adjust_to(state,other)
+				other.adjust_from(state,self) if other
+			end
+		end
+		ProtectionGroups = { :public => ProtectionGroup.new(:public),
+			:protected => ProtectionGroup.new(:protected),
+		 	:private => ProtectionGroup.new(:private)}
+		def set_parent(parent)
+			@parent = parent
+		end
+		def chop_method_prefix()
+			@space.chop_method_prefix + "#@name::"
+		end
+		def def_func(*args)
+			func = CPP::MemberFunc.new(self,*args)
+			@protections[func] = @protection
+			@members << func
+			return func
+		end
+		def add_cc_comment(*args)
+			args.each do |arg|
+				@members.push(CC_Mask.new(CPP::Comment.new(arg)))
+			end
+		end
+		def plan_cc(plan)
+			@members.each do |member|
+				if(member.respond_to?(:plan_cc))
+					member.plan_cc(plan)
+				elsif(member.respond_to?(:pp_cc_file))
+					plan.push(MemberElementCC.new(member))
+				end
+			end
+		end
+		def plan_header(plan)
+			group_plan = GroupPlan.new(self)
+			plan.push(group_plan)
+			@members.each do |member|
+				group_plan.implicit = ProtectionGroups[@protections[member]]
+				if(member.respond_to?(:plan_header))
+					member.plan_header(group_plan)
+				else
+					group_plan.push(MemberElementHeader.new(member))
+				end
+				#member.plan_cc(plan)
+			end
+		end
+		def open(state)
+			state.needs_semi = false
+			state.v_pad(2)
+			if(@static)
+				state.print("static ")
+			end
+			self.template_header(state) if(self.respond_to?(:template_header))
+			state.print("#{self.class.type_name} #{@name}")
+			self.template_spec_args(state) if(self.respond_to?(:template_spec_args))
+			if(@parent)
+				state.print(" : #{@parent} {\n")
+			else
+				state.pp(" {\n")
+			end
+			state.indent += 2
+		end
+		def close(state)
+			state.indent -= 2
+			state.needs_semi = true
+			if(@dec)
+				state.print("\n} #{@dec}")
+			else
+				state.print("\n}")
+			end
+			state.v_pad(2)
+		end
+		def add_dep(other)
+			@deps << other
+			self
+		end
+	end
+	class Class < Type
+		def add_member(protection,member)
+			@protection = protection
+			@members.push(member)
+			@protections[member] = protection
+			return member
+		end
+		def add_struct(*args)
+			add_member(:public, Types::Struct.new(self,*args))
+		end
+		def public() ; @protection = :public ; end 
+		def protected() ; @protection = :protected ; end 
+		def private() ; @protection = :private ; end 
+		def self.type_name() ; "class" ; end
+	end
+	class PreprocessorIf < Type
+		def initialize(*args)
+			super(*args)
+		end
+		def add_member(member)
+			@members.push(member)
+			return member
+		end
+		def self.type_name() ; "#if" ; end
+		def open(state)
+			state.needs_semi = false
+			state.print("\n#if #{@name}")
+		end
+		def close(state)
+			state.needs_semi = false
+			state.print("\n#endif  // #{@name}")
+		end
+	end
+	class Struct < Type
+		attr_accessor :members
+		def add_member(member)
+			@members.push(member)
+			return member
+		end
+		def self.type_name() ; "struct" ; end
+	end
+	class TemplateClass < Class
+		def initialize(*args)
+			super(*args)
+			@t_args = CPP::Args.new()
+		end
+		def spec_args()
+			return @spec_args ||= CPP::Args.new()
+		end
+		def template_header(state)
+			if(@t_args.length > 0)
+				state.pp("template < ")
+				state.pp(@t_args)
+			else
+				state.pp("template < ")
+			end
+			state.pp(">\n")
+		end
+		def plan_cc(plan)
+
+		end
+		def plan_header(plan)
+			group_plan = GroupPlan.new(self)
+			plan.push(group_plan)
+			@members.each do |member|
+				group_plan.implicit = ProtectionGroups[@protections[member]]
+				if(member.respond_to?(:plan_header))
+					member.plan_header(group_plan)
+				else
+					group_plan.push(MemberElementInline.new(member))
+				end
+			end
+		end
+		def template_spec_args(state)
+			if(@spec_args)
+				state.pp("< ")
+				state.pp(@spec_args)
+				state.pp(">")
+			end
+		end
+	end
+end
+class DepFilePair
+	class NameSpace
+		def initialize(name,parent)
+			@name,@parent = name,parent
+			@members = []
+		end
+		def add_struct(*args)
+			add Types::Struct.new(self,*args)
+		end
+		def add_template(*args)
+			add Types::TemplateClass.new(self,*args)
+		end
+		def add_class(*args)
+			add Types::Class.new(self,*args)
+		end
+		def add_cc(arg)
+			@members.push(CC_Mask.new(arg))
+		end
+		def chop_method_prefix()
+			""
+		end
+		def class_comment(*args)
+			add CPP::Comment.new(*args)
+		end
+		def var_dec_comment(*args)
+			add CPP::Comment.new(*args)
+		end
+		def add_var_dec(arg)
+			add DepMask.new(arg)
+		end
+		def plan_cc(plan)
+			plan.implicit = ImplicitName.new(@name,plan.implicit)
+			@members.each do |member|
+				if(member.respond_to?(:plan_cc))
+					member.plan_cc(plan)
+				else
+					MemberElementCC.check(plan,member)
+				end
+			end
+			plan.implicit = plan.implicit.parent
+		end
+		def plan_header(plan)
+			plan.implicit = ImplicitName.new(@name,plan.implicit)
+			@members.each do |member|
+				if(member.respond_to?(:plan_header))
+					member.plan_header(plan)
+				else
+					MemberElementHeader.check(plan,member)
+				end
+			end
+			plan.implicit = plan.implicit.parent
+		end
+		def add val
+			@members << val
+			val
+		end
+	end
+	def initialize(rel_path)
+		@rel_path = rel_path
+		@cc_includes = []
+		@header_includes = []
+		@spaces = []
+		@cc_usings = []
+		@cache = {}
+	end
+	def add_cc_include(inc_path)
+		@cc_includes << CPP::Include.new(inc_path)
+	end
+	def add_cc_using(using)
+		@cc_usings << CPP::Using.new(using)
+	end
+	def add_header_include(inc_path)
+		@header_includes << CPP::Include.new(inc_path)
+	end
+	def add_namespace(name,parent)
+		space = NameSpace.new(name,parent)
+		if(parent != self)
+			parent.add(space)
+		else
+			@spaces.push(space)
+		end
+		return space
+	end
+	def set(type,cached)
+		@cache[type] = cached
+	end
+	def get(type)
+		cached = @cache[type]
+		return cached if cached
+		cached = type.create(self)
+		cached_check = @cache[type]
+		return cached_check if cached_check
+		set(type,cached)
+		return cached
+	end
+	def write_cc_file(cpp_base,cc_file)
+		plan_cc = GroupPlan.new(nil,elems_cc = [])
+		@spaces.each do |space|
+			space.plan_cc(plan_cc)
+		end
+		suite = CPP::Suite.new(@cc_includes + @cc_usings + [plan_cc])
+		CPP.pretty_print(suite,cc_file)
+	end
+	def write_header_file(cpp_base,header_file)
+		plan_header = GroupPlan.new(nil,elems_cc = [])
+		@spaces.each do |space|
+			space.plan_header(plan_header)
+		end
+		suite = CPP::Suite.new(@header_includes + [plan_header])
+		include_guard = CPP::IncludeGuard.new(suite)
+		include_guard.name = @rel_path.upcase.gsub(/[\.\/\\]/,"_") + "_H_"
+		CPP.pretty_print(include_guard,header_file)
+	end
+end
diff --git a/aos/build/queues/cpp_pretty_print/file_pair_types.rb b/aos/build/queues/cpp_pretty_print/file_pair_types.rb
new file mode 100644
index 0000000..25ce4fe
--- /dev/null
+++ b/aos/build/queues/cpp_pretty_print/file_pair_types.rb
@@ -0,0 +1,204 @@
+module CPP
+end
+class CPP::TypePair
+	attr_accessor :name,:static,:dec
+	def initialize(namespace,name)
+		@space,@name = namespace,name
+		@members = []
+		@protections = {}
+		@dont_sort = {}
+	end
+	ProtectionTable = { :public => 0,:protected => 1,:private => 2 }
+	def comp(m1,m2)
+		if(!(@dont_sort[m1] || @dont_sort[m2]))
+			if(@protections[m1] && @protections[m2])
+				comp = ProtectionTable[@protections[m1]] <=> ProtectionTable[@protections[m2]]
+				return comp if(comp != 0)
+			end
+			comp = TypeTable[m1.class] <=> TypeTable[m2.class]
+			return comp if(comp != 0)
+		end
+		return @stable[m1] <=> @stable[m2]
+	end
+	def set_parent(parent)
+		@parent = parent
+	end
+	def add_class(name)
+		return add_member(:public,CPP::ClassPair.new(self,name))
+	end
+	def add_struct(name)
+		return add_member(:public,CPP::StructPair.new(self,name))
+	end
+	def add_cc_comment(*strs)
+		strs.each do |str|
+			@members << comment = CPP::CCMemberWrapper.new(CPP::Comment.new(str))
+			@protections[comment] = @protection
+		end
+		#@dont_sort[comment] = true
+	end
+	def method_prefix()
+		@space.method_prefix + "#@name::"
+	end
+	def chop_method_prefix()
+		@space.chop_method_prefix + "#@name::"
+	end
+	def pp(state)
+		@stable = {}
+		@members.each_with_index { |mem,i| @stable[mem] = i }
+		members = @members.sort { |m1,m2| comp(m1,m2) }
+
+		state.needs_semi = false
+		state.v_pad(2)
+		if(@static)
+			state.print("static ")
+		end
+		if(@parent)
+			state.print("#{self.class.type_name} #{@name} : #{@parent} {\n")
+		else
+			state.print("#{self.class.type_name} #{@name} {\n")
+		end 
+		state.indent += 2
+		protection = nil 
+		members.each do |member|
+			if(protection != @protections[member])
+				state.indent -= 1
+				state.needs_semi = false
+				state.v_pad(2) if(protection)
+				protection = @protections[member]
+				state.print("#{protection}:\n")
+				state.indent += 1
+				state.endline()
+			end
+			state.endline()
+			state.needs_semi = true
+			if(member.respond_to?(:pp_header_file))
+				member.pp_header_file(state)
+			else
+				state.pp(member)
+			end
+			state.endline()
+		end 
+		state.indent -= 2
+		state.needs_semi = true
+		if(@dec)
+		state.print("\n} #{@dec}")
+		else
+		state.print("\n}")
+		end
+		state.v_pad(2)
+	end
+	def pp_header_file(state)
+		pp(state)
+	end
+	def pp_cc_file(state)
+		@members.each do |member|
+			state.needs_semi = true
+			member.pp_cc_file(state) if(member.respond_to?(:pp_cc_file))
+			state.endline()
+		end
+	end
+	def def_func(*args)
+		func = CPP::MemberFunc.new(self,*args)
+		@protections[func] = @protection
+		@members << func
+		return func
+	end
+end
+class CPP::CCMemberWrapper
+	def initialize(member)
+		@member = member
+	end
+	def pp_header_file(state) ; end
+	def pp_cc_file(state)
+		state.pp(@member)
+	end
+end
+class CPP::ClassPair < CPP::TypePair
+	attr_accessor :name
+	def initialize(namespace,name)
+		super(namespace,name)
+		@protection = :public #default to public
+	end
+	def add_member(protection,member)
+		@protection = protection
+		@members << member
+		@protections[member] = protection
+		return member
+	end
+	def public() ; @protection = :public ; end
+	def protected() ; @protection = :protected ; end
+	def private() ; @protection = :private ; end
+	def self.type_name() ; "class" ; end
+end
+class CPP::StructPair < CPP::TypePair
+	def self.type_name() ; "struct" ; end
+	def add_member(member)
+		@members << member
+		return member
+	end
+end
+CPP::TypePair::TypeTable = { CPP::StructPair => 0, CPP::ClassPair => 1,CPP::Constructor => 2 }
+CPP::TypePair::TypeTable.default = 3
+class CPP::TemplateClass < CPP::ClassPair
+	def initialize(namespace,name)
+		super(namespace,name)
+		@t_args = CPP::Args.new()
+	end
+	def spec_args()
+		return @spec_args ||= CPP::Args.new()
+	end
+	def pp(state)
+		@stable = {}
+		@members.each_with_index { |mem,i| @stable[mem] = i }
+		members = @members.sort { |m1,m2| comp(m1,m2) }
+		state.needs_semi = false
+		state.v_pad(2)
+		if(@t_args.length > 0)
+			state.pp("template < ")
+			state.pp(@t_args)
+		else
+			state.pp("template < ")
+		end
+		state.pp(">\n")
+		state.pp("class #@name")
+		if(@spec_args)
+			state.pp("< ")
+			state.pp(@spec_args)
+			state.pp("> {")
+		else
+			state.pp(" {")
+		end
+		state.endline()
+		state.indent += 2
+		protection = nil 
+		members.each do |member|
+			if(protection != @protections[member])
+				state.indent -= 1
+				state.needs_semi = false
+				state.v_pad(2) if(protection)
+				protection = @protections[member]
+				state.print("#{protection}:\n")
+				state.indent += 1
+				state.endline()
+			end
+			state.endline()
+			state.needs_semi = true
+			if(member.respond_to?(:pp_inline))
+				member.pp_inline(state)
+			else
+				state.pp(member)
+			end
+			state.endline()
+		end 
+		state.indent -= 2
+		state.needs_semi = true
+		if(@dec)
+			state.print("\n} #{@dec}")
+		else
+			state.print("\n}")
+		end
+		state.v_pad(2)
+	end
+	def pp_cc_file(state); end
+end
+
diff --git a/aos/build/queues/cpp_pretty_print/standard_types.rb b/aos/build/queues/cpp_pretty_print/standard_types.rb
new file mode 100644
index 0000000..566f542
--- /dev/null
+++ b/aos/build/queues/cpp_pretty_print/standard_types.rb
@@ -0,0 +1,363 @@
+module CPP
+	class Class
+
+	end
+	class Funct
+		attr_accessor :retval,:name,:args,:suite
+		def initialize(retval = nil,name = nil,args = Args.new(),suite = Suite.new())
+			@retval,@name,@args,@suite = retval,name,args,suite
+		end
+		def pp(state)
+			state.pp(@retval)
+			state.print(" ")
+			state.pp(@name)
+			state.print("(")
+			state.pp(@args)
+			state.print(")")
+			state.pp(@suite)
+		end
+	end
+	class If
+		attr_accessor :cond,:suite,:else_suite
+		def initialize(cond = nil,suite = Suite.new(),else_suite = nil)
+			@cond,@suite,@else_suite = cond,suite,else_suite
+		end
+		def pp(state)
+			state.print("if (")
+			state.pp(@cond)
+			state.print(") ")
+			state.needs_semi = false
+			state.pp(@suite)
+			if(@else_suite)
+				state.print(" else ")
+				state.pp(@else_suite)
+			end
+		end
+		def else_suite()
+			return(@else_suite ||= Suite.new())
+		end
+	end
+	class For
+		attr_accessor :init,:cond,:update,:suite
+		def initialize(init = nil,cond = nil,update = nil,suite = Suite.new())
+			@init,@cond,@update,@suite = init,cond,update,suite
+		end
+		def pp(state)
+			state.print("for (")
+			Args.new([@init,@cond,@update]).pp(state,";")
+			state.print(") ")
+			state.needs_semi = false
+			state.pp(@suite)
+		end
+	end
+	class Args < Array
+		attr_accessor :dont_wrap
+		def pp(state,sep = ",")
+			pos = start = state.col
+			self.each_with_index do |arg,i|
+				#puts "#{state.col - start} , #{start}"
+				state.print(sep) if(i != 0)
+				if(pos > 80)
+					state.wrap(state.indent + 4)
+					pos = start = state.col
+				elsif(state.col * 2 - pos > 80 && !@dont_wrap)
+					state.wrap(start)
+					start = pos
+				else
+					state.print(" ") if(i != 0)
+					pos = state.col
+				end
+				state.pp(arg)
+			end
+		end
+	end
+	class Suite < Array
+		def pp(state)
+			state.print("{")
+			state.>>
+			state.needs_semi = false
+			self.pp_no_braces(state)
+			state.<<
+			state.print("}")
+		end
+		def pp_no_braces(state)
+			self.each do |arg,i|
+				state.endline()
+				state.needs_semi = true
+				state.pp(arg)
+				state.endline()
+			end
+		end
+		def pp_one_line(state)
+			if(self.length == 1)
+				state.needs_semi = true
+				state.print("{ ")
+				state.pp(self[0])
+				state.print(";") if(state.needs_semi)
+				state.needs_semi = false
+				state.print(" }")
+			else
+				self.pp(state)
+			end
+		end
+	end
+	class FuncCall
+		attr_accessor :name,:args
+		def initialize(name = nil,args = Args.new())
+			@name,@args = name,args
+		end
+		def self.build(name,*args)
+			self.new(name,Args.new(args))
+		end
+		def pp(state)
+			state.pp(@name)
+			state.print("(")
+			state.pp(@args)
+			state.print(")")
+		end
+	end
+	class BIT_OR
+		attr_accessor :val1,:val2
+		def initialize(val1,val2)
+			@val1,@val2 = val1,val2
+		end
+		def pp(state)
+			state.pp(@val1)
+			state.print(" | ")
+			state.pp(@val2)
+		end
+	end
+	class LT
+		attr_accessor :val1,:val2
+		def initialize(val1,val2)
+			@val1,@val2 = val1,val2
+		end
+		def pp(state)
+			state.pp(@val1)
+			state.print(" < ")
+			state.pp(@val2)
+		end
+	end
+	class Div
+		attr_accessor :val1,:val2
+		def initialize(val1,val2)
+			@val1,@val2 = val1,val2
+		end
+		def pp(state)
+			state.pp(@val1)
+			state.print(" / ")
+			state.pp(@val2)
+		end
+	end
+	class Add
+		attr_accessor :val1,:val2
+		def initialize(val1,val2)
+			@val1,@val2 = val1,val2
+		end
+		def pp(state)
+			state.pp(@val1)
+			state.print(" + ")
+			state.pp(@val2)
+		end
+	end
+	class Member
+		attr_accessor :obj,:name
+		def initialize(obj,name)
+			@obj,@name = obj,name
+		end
+		def pp(state)
+			state.pp(@obj)
+			state.print(".")
+			state.pp(@name)
+		end
+	end
+	class PointerMember
+		attr_accessor :obj,:name
+		def initialize(obj,name)
+			@obj,@name = obj,name
+		end
+		def pp(state)
+			state.pp(@obj)
+			state.print("->")
+			state.pp(@name)
+		end
+	end
+	class Minus
+		attr_accessor :val
+		def initialize(val)
+			@val = val
+		end
+		def pp(state)
+			state.print("-")
+			state.pp(@val)
+		end
+	end
+	class Not
+		attr_accessor :val
+		def initialize(val)
+			@val = val
+		end
+		def pp(state)
+			state.print("!")
+			state.pp(@val)
+		end
+	end
+	class Address
+		attr_accessor :val
+		def initialize(val)
+			@val = val
+		end
+		def pp(state)
+			state.print("&")
+			state.pp(@val)
+		end
+	end
+	class Paran
+		attr_accessor :val
+		def initialize(val)
+			@val = val
+		end
+		def pp(state)
+			state.print("(")
+			state.pp(@val)
+			state.print(")")
+		end
+	end
+	class Assign
+		attr_accessor :lval,:rval
+		def initialize(lval = nil,rval = Args.new())
+			@lval,@rval = lval,rval
+		end
+		def pp(state)
+			state.pp(@lval)
+			state.print(" = ")
+			state.pp(@rval)
+		end
+	end
+	class PointerDeref
+		attr_accessor :val
+		def initialize(val)
+			@val = val
+		end
+		def pp(state)
+			state.print("*")
+			state.pp(@val)
+		end
+	end
+	class Cast
+		attr_accessor :to,:val
+		def initialize(to,val)
+			@to,@val = to,val
+		end
+		def pp(state)
+			state.print("(")
+			state.pp(@to)
+			state.print(")")
+			state.pp(@val)
+		end
+	end
+	class VarDec
+		attr_accessor :type,:name
+		def initialize(type = nil,name = nil)
+			@type,@name = type,name
+		end
+		def pp(state)
+			state.pp(@type)
+			state.print(" ")
+			state.pp(@name)
+		end
+	end
+	class Return
+		attr_accessor :val
+		def initialize(val = nil)
+			@val = val
+		end
+		def pp(state)
+			state.print("return ")
+			state.pp(@val)
+		end
+	end
+	class TraversalState
+		attr_accessor :needs_semi,:indent,:col
+		def initialize(file)
+			@file = file
+			@indent = 0
+			@not_indented = true
+			@just_endlined = true
+			@hold_points = []
+			@col = 0
+		end
+		def set_hold_point()
+			@hold_points.push(@col)
+		end
+		def wrap(col)
+			@file.print("\n")
+			@file.print(" " * col)
+			@col = col
+		end
+		def suppress_indent()
+			@not_indented = false
+		end
+		def <<()
+			@indent -= 2
+		end
+		def >>()
+			@indent += 2
+		end
+		def pp(ast)
+			return ast.pp(self) if(ast.respond_to?(:pp))
+			self.print(ast)
+		end
+		def print(chars)
+			return print_no_split(chars) if(!chars.respond_to?(:split))
+			chars.split(/\n/,-1).each_with_index do |line,i|
+				endline() if(i != 0)
+				print_no_split(line) if(line && line.length > 0)
+			end
+		end
+		def print_no_split(chars)
+			if(@not_indented)
+				@file.print(" "*@indent)
+				@col += @indent
+				@not_indented = false
+			end
+			if(chars)
+				chars = chars.to_s
+				if(chars.length > 0)
+					@col += chars.length
+					@file.print(chars)
+					@just_endlined = false
+					@v_pad = 0
+				end
+			end
+		end
+		def endline()
+			return if(@just_endlined)
+			@file.print(";") if(@needs_semi)
+			@needs_semi = false
+			@file.print("\n")
+			@not_indented = true
+			@just_endlined = true
+			@hold_points.clear()
+			@v_pad += 1
+			@col = 0
+		end
+		def v_pad(n)
+			while(@v_pad < n)
+				force_endline()
+			end
+		end
+		def force_endline()
+			@just_endlined = false
+			endline()
+		end
+	end
+	def self.pretty_print(ast,file)
+		state = TraversalState.new(file)
+		if(ast.respond_to?(:pp_no_braces))
+			ast.pp_no_braces(state) 
+		else
+			state.pp(ast)
+		end
+	end
+end
diff --git a/aos/build/queues/load.rb b/aos/build/queues/load.rb
new file mode 100644
index 0000000..59a4590
--- /dev/null
+++ b/aos/build/queues/load.rb
@@ -0,0 +1,15 @@
+$LOAD_PATH.unshift(".")
+["tokenizer.rb","q_file.rb","queue_group.rb","queue.rb","namespaces.rb",
+"interface.rb","errors.rb", "q_struct.rb"].each do |name|
+	require File.dirname(__FILE__) + "/objects/" + name
+end
+["standard_types.rb","auto_gen.rb","file_pair_types.rb",
+"dep_file_pair.rb"].each do |name|
+	require File.dirname(__FILE__) + "/cpp_pretty_print/" + name
+end
+["q_file.rb","message_dec.rb","queue_dec.rb", "q_struct.rb"].each do |name|
+	require File.dirname(__FILE__) + "/output/" + name
+end
+require File.dirname(__FILE__) + '/write_iff_changed.rb'
+require "fileutils"
+require "pathname"
diff --git a/aos/build/queues/objects/errors.rb b/aos/build/queues/objects/errors.rb
new file mode 100644
index 0000000..d776a22
--- /dev/null
+++ b/aos/build/queues/objects/errors.rb
@@ -0,0 +1,43 @@
+class QError < Exception
+	def initialize(msg)
+		super()
+		@msg = msg
+		@qstacktrace = []
+	end
+	def self.set_name(name)
+		@pretty_name = name
+	end
+	def self.pretty_name()
+		@pretty_name
+	end
+	def to_s
+		msg = "Error:(#{self.class.pretty_name})\n\t"
+		msg += @msg
+		msg += "\n" if(msg[-1] != "\n")
+		@qstacktrace.each do |part|
+			part = part.q_stack_name if(part.respond_to?(:q_stack_name))
+			msg += "\tfrom: #{part}\n"
+		end
+		return msg
+	end
+	set_name("Base Level Exception.")
+	attr_accessor :qstacktrace
+end
+class QSyntaxError < QError
+	def initialize(msg)
+		super(msg)
+	end
+	set_name("Syntax Error")
+end
+class QNamespaceCollision < QError
+	def initialize(msg)
+		super(msg)
+	end
+	set_name("Namespace Collision")
+end
+class QImportNotFoundError < QError
+	def initialize(msg)
+		super(msg)
+	end
+	set_name("Couldn't Find Target of Import Statement")
+end
diff --git a/aos/build/queues/objects/interface.rb b/aos/build/queues/objects/interface.rb
new file mode 100644
index 0000000..52332b6
--- /dev/null
+++ b/aos/build/queues/objects/interface.rb
@@ -0,0 +1,69 @@
+class MessageElementReq
+	def initialize(type,name)
+		@type = type
+		@name = name
+	end
+	def self.parse(tokens)
+		type = tokens.expect(:tWord).data
+		name = tokens.expect(:tWord).data
+		tokens.expect(:tSemi)
+		return self.new(type,name)
+	end 
+end 
+class QueueReq
+	def initialize(name,type = nil)
+		@name = name
+		@type = type
+	end
+	def self.parse(tokens)
+		type_or_name = tokens.expect(:tWord).data
+		if(tokens.peak == :tSemi)
+			tokens.expect(:tSemi)
+			return self.new(type_or_name)
+		else
+			name = tokens.expect(:tWord).data
+			tokens.expect(:tSemi)
+			return self.new(name,type_or_name)
+		end
+	end
+end
+class InterfaceStmt < QStmt
+	def initialize(name,elements)
+		@name = name
+		@elements = elements
+	end
+	def q_eval(locals)
+
+	end
+	def self.check_type(tokens,new_type,old_type)
+		return new_type if(old_type == nil)
+		if(new_type != old_type)
+			tokens.qError(<<ERROR_MSG)
+error: intermixing queue definitions (a queue_group feature)
+	and type definitions (a message_group feature)
+	this results in an undefined type value.
+	Wot. Wot.
+ERROR_MSG
+		end
+		return old_type
+	end
+	def self.parse(tokens)
+		name = tokens.expect(:tWord).data
+		values = []
+		type = nil
+		tokens.expect(:tOpenB)
+		while(tokens.peak != :tCloseB)
+			if(tokens.peak.data == "queue")
+				tokens.expect(:tWord)
+				values << QueueReq.parse(tokens)
+				type = check_type(tokens,:queue_group,type)
+			else
+				values << MessageElementReq.parse(tokens)
+				type = check_type(tokens,:message_group,type)
+			end
+		end 
+		tokens.expect(:tCloseB)
+		tokens.expect(:tSemi)
+		self.new(name,values)
+	end
+end
diff --git a/aos/build/queues/objects/namespaces.rb b/aos/build/queues/objects/namespaces.rb
new file mode 100644
index 0000000..ea3aa80
--- /dev/null
+++ b/aos/build/queues/objects/namespaces.rb
@@ -0,0 +1,211 @@
+class LocalSituation
+	attr_accessor :globals,:local
+	def initialize(globals)
+		@globals = globals
+		@local = nil
+	end
+	def package=(qualified)
+		if(@local)
+			raise QSyntaxError.new(<<ERROR_MSG)
+You are redefining the package path.
+ Stuff might break if you do that.
+ Other options include: using another header file, and just using the same namespace.
+ If you are confident that you need this you can remove this check at
+ 	#{__FILE__}:#{__LINE__}.
+ Or file a feature request.
+ But that would be weird...
+ Wot. Wot.
+ERROR_MSG
+		end
+		@local = @globals.space
+		qualified.names.each do |name|
+			@local = @local.get_make(name)
+		end
+	end
+	def register(value)
+		if(!@local)
+			raise QError.new(<<ERROR_MSG)
+There is no package path defined, This is a big problem because
+ we are kindof expecting you to have a package path...
+ use a :
+    package my_super.cool.project;
+ statement to remedy this situation. (or file a feature request)
+ Wot. Wot.
+ERROR_MSG
+		end
+		@local[value.name] = value
+		value.parent = @local if(value.respond_to?(:parent=))
+		value.loc = @local
+	end
+	def bind(bind_to)
+		return BoundSituation.new(self,bind_to)
+	end
+end
+class BoundSituation < LocalSituation
+	def initialize(locals,bind_to)
+		@globals = locals.globals
+		@local = bind_to
+	end
+end
+class NameSpace
+	attr_accessor :parent,:name
+	def initialize(name = nil,parent = nil)
+		@name = name
+		@parent = parent
+		@spaces = {}
+	end
+	def []=(key,val)
+		if(old_val = @spaces[key])
+			old_val = old_val.created_by if(old_val.respond_to?(:created_by) && old_val.created_by)
+			if(old_val.respond_to?(:q_stack_name))
+				old_val = old_val.q_stack_name
+			else
+				old_val = "eh, it is a #{old_val.class} thats all I know..."
+			end
+			raise QNamespaceCollision.new(<<ERROR_MSG)
+Woah! The name #{queue_name(key).inspect} is already taken by some chap at #{old_val}.
+\tFind somewhere else to peddle your wares.
+\tWot. Wot.
+ERROR_MSG
+		end
+		@spaces[key] = val
+	end
+	def to_cpp_id(name)
+		txt = @name + "::" + name
+		return @parent.to_cpp_id(txt) if(@parent && parent.name)
+		return "::" + txt
+	end
+	def queue_name(queue)
+		get_name() + "." + queue
+	end
+	def [](key)
+		#puts "getting #{get_name}.#{key}"
+		@spaces[key]
+	end
+	def get_make(name)
+		@spaces[name] ||= self.class.new(name,self)
+	end
+	def get_name()
+		if(@parent)
+			return "#{@parent.get_name}.#{@name}"
+		else
+			return "#{@name}"
+		end
+	end
+	def create(cpp_tree)
+		if(@parent && @parent.name)
+			parent = cpp_tree.get(@parent)
+		else
+			parent = cpp_tree
+		end
+		return cpp_tree.add_namespace(@name,parent)
+	end
+	def to_s()
+		"<NameSpace: #{get_name()}>"
+	end
+	def inspect()
+		"<NameSpace: #{get_name()}>"
+	end
+	def root()
+		return self if(@parent == nil)
+		return @parent.root
+	end
+end
+class Globals
+	attr_accessor :space
+	def initialize()
+		@space = NameSpace.new()
+		@space.get_make("aos")
+		@include_paths = []
+	end
+	def paths()
+		@include_paths
+	end
+	def add_path(path)
+		@include_paths << path
+	end
+	def find_file(filename)
+		@include_paths.each do |path_name|
+			new_path = File.expand_path(path_name) + "/" + filename
+			if(File.exists?(new_path))
+				return new_path 
+			end
+		end
+		raise QImportNotFoundError.new(<<ERROR_MSG)
+Problem Loading:#{filename.inspect} I looked in:
+\t#{(@include_paths.collect {|name| name.inspect}).join("\n\t")}
+\tbut alas, it was nowhere to be found.
+\tIt is popular to include the top of the repository as the include path start, 
+\tand then reference off of that. 
+\tI would suggest doing that and then trying to build again.
+\tWot. Wot.
+ERROR_MSG
+	end
+end
+class QualifiedName
+	attr_accessor :names,:off_root
+	def initialize(names,off_root = false)
+		@names = names
+		@off_root = off_root
+	end
+	def test_lookup(namespace)
+		@names.each do |name|
+			return nil if(!namespace.respond_to?(:[]))
+			namespace = namespace[name]
+			return nil if(!namespace)
+		end
+		return namespace
+	end
+	def is_simple?()
+		return !@off_root && @names.length == 1
+	end
+	def to_simple()
+		return @names[-1]
+	end
+	def to_s()
+		if(@off_root)
+			return ".#{@names.join(".")}"
+		else
+			return @names.join(".")
+		end
+	end
+	def lookup(locals)
+		if(@off_root)
+			local = locals.globals.space
+		else
+			local = locals.local
+		end
+		target = nil
+		while(!target && local)
+			target = test_lookup(local)
+			local = local.parent
+		end
+		return target if(target)
+		if(@off_root)
+			raise QError.new(<<ERROR_MSG)
+I was looking for .#{@names.join(".")}, but alas, it was not under
+\tthe root namespace.
+\tI'm really sorry old chap.
+\tWot. Wot.
+ERROR_MSG
+		else
+			raise QError.new(<<ERROR_MSG)
+I was looking for #{@names.join(".")}, but alas, I could not find
+\tit in #{locals.local.get_name} or any parent namespaces.
+\tI'm really sorry old chap.
+\tWot. Wot.
+ERROR_MSG
+		end
+	end
+	def self.parse(tokens)
+		names = []
+		off_root = (tokens.peak == :tDot)
+		tokens.next if(off_root)
+		names << tokens.expect(:tWord).data
+		while(tokens.peak == :tDot)
+			tokens.next
+			names << tokens.expect(:tWord).data
+		end
+		return self.new(names,off_root)
+	end
+end
diff --git a/aos/build/queues/objects/q_file.rb b/aos/build/queues/objects/q_file.rb
new file mode 100644
index 0000000..f73b638
--- /dev/null
+++ b/aos/build/queues/objects/q_file.rb
@@ -0,0 +1,150 @@
+class QStmt
+	def set_line(val)
+		@file_line = val
+		return self
+	end
+	def q_stack_name()
+		@file_line
+	end
+	def self.method_added(name)
+		@wrapped ||= {}
+		return if(name != :q_eval && name != :q_eval_extern)
+		return if(@wrapped[name])
+		@wrapped[name] = true
+		method = self.instance_method(name)
+		define_method(name) do |*args,&blk|
+			begin 
+				method.bind(self).call(*args,&blk)
+			rescue QError => e
+				e.qstacktrace << self
+				raise e
+			end 
+		end 
+	end 
+
+end
+class ImportStmt < QStmt
+	def initialize(filename)
+		@filename = filename
+	end
+	def q_eval(locals)
+		filename = locals.globals.find_file(@filename)
+		#puts "importing #{filename.inspect}"
+		q_file = QFile.parse(filename)
+		q_output = q_file.q_eval_extern(locals.globals)
+		q_output.extern = true
+		return Target::QInclude.new(@filename + ".h")
+	end
+	def self.parse(tokens)
+		line = tokens.pos
+		to_import = (tokens.expect(:tString) do |token|
+			<<ERROR_MSG
+I found a #{token.humanize} at #{token.pos}.
+\tI was really looking for a "filename" for this import statement.
+\tSomething like: import "super_cool_file";
+\tWot.Wot
+ERROR_MSG
+		end).data
+		tokens.expect(:tSemi) do |token|
+			<<ERROR_MSG
+I found a #{token.humanize} at #{token.pos}.
+\tI was really looking for a ";" to finish off this import statement
+\tat line #{line};
+\tSomething like: import #{to_import.inspect};
+\tWot.Wot                #{" "*to_import.inspect.length}^
+ERROR_MSG
+		end
+		return self.new(to_import).set_line(line)
+	end
+end
+class PackageStmt < QStmt
+	def initialize(name)
+		@name = name
+	end
+	def q_eval(locals)
+		locals.package = @name
+		return nil
+	end
+	def self.parse(tokens)
+		line = tokens.pos
+		qualified_name = QualifiedName.parse(tokens)
+		tokens.expect(:tSemi)
+		return self.new(qualified_name).set_line(line)
+	end
+end
+class QFile
+	attr_accessor :namespace
+	def initialize(filename,suite)
+		@filename,@suite = filename,suite
+	end
+	def q_eval(globals = Globals.new())
+		local_pos = LocalSituation.new(globals)
+		q_file = Target::QFile.new()
+		@suite.each do |name|
+			val = name.q_eval(local_pos)
+			if(val)
+				if(val.respond_to?(:create))
+					q_file.add_type(val)
+				end
+			end
+		end
+		@namespace = local_pos.local
+		return q_file
+	end
+	def q_eval_extern(globals)
+		local_pos = LocalSituation.new(globals)
+		q_file = Target::QFile.new()
+		@suite.each do |name|
+			if(name.respond_to?(:q_eval_extern))
+				val = name.q_eval_extern(local_pos)
+			else
+				val = name.q_eval(local_pos)
+			end
+			if(val)
+				if(val.respond_to?(:create))
+					q_file.add_type(val)
+				end
+			end
+		end
+		return q_file
+	end
+	def self.parse(filename)
+		tokens = Tokenizer.new(filename)
+		suite = []
+		while(tokens.peak != :tEnd)
+			token = tokens.expect(:tWord) do |token| #symbol
+			<<ERROR_MSG
+I found a #{token.humanize} at #{token.pos}.
+\tI was really looking for a "package", "import", "queue_group",
+\t"message", or "queue" statement to get things moving.
+\tSomething like: import "super_cool_file";
+\tWot.Wot
+ERROR_MSG
+			end
+			case token.data
+			when "package"
+				suite << PackageStmt.parse(tokens)
+			when "import"
+				suite << ImportStmt.parse(tokens)
+			when "queue_group"
+				suite << QueueGroupStmt.parse(tokens)
+			when "message"
+				suite << MessageStmt.parse(tokens)
+			when "queue"
+				suite << QueueStmt.parse(tokens)
+			when "interface"
+				suite << InterfaceStmt.parse(tokens)
+			when "struct"
+				suite << StructStmt.parse(tokens)
+			else
+				tokens.qError(<<ERROR_MSG)
+expected a "package","import","queue","struct","queue_group", or "message" statement rather
+	than a #{token.data.inspect}, (whatever that is?)
+	oh! no! a feature request!?
+	Wot. Wot.
+ERROR_MSG
+			end
+		end
+		return self.new(filename,suite)
+	end
+end
diff --git a/aos/build/queues/objects/q_struct.rb b/aos/build/queues/objects/q_struct.rb
new file mode 100644
index 0000000..cd47fe6
--- /dev/null
+++ b/aos/build/queues/objects/q_struct.rb
@@ -0,0 +1,37 @@
+
+class StructStmt 
+	def initialize(name,suite)
+		@name = name
+		@suite = suite
+	end
+	def q_eval(locals)
+		group = Target::StructDec.new(@name)
+		locals.register(group)
+		@suite.each do |stmt|
+			stmt.q_eval(locals.bind(group))
+		end 
+		return group
+	end
+	def self.parse(tokens)
+		name = tokens.expect(:tWord).data
+		values = []
+		tokens.expect(:tOpenB)
+		while(tokens.peak != :tCloseB)
+			values << MessageElementStmt.parse(tokens)
+		end
+		names = {}
+		values.each do |val|
+			if(names[val.name])
+				raise QSyntaxError.new(<<ERROR_MSG)
+Hey! duplicate name #{val.name.inspect} in your message declaration statement (message #{name}).
+\tI found them at: #{names[val.name].q_stack_name()} and #{val.q_stack_name()}.
+\tWot. Wot.
+ERROR_MSG
+			end
+			names[val.name] = val
+		end
+		tokens.expect(:tCloseB)
+		tokens.expect(:tSemi)
+		self.new(name,values)
+	end
+end
diff --git a/aos/build/queues/objects/queue.rb b/aos/build/queues/objects/queue.rb
new file mode 100644
index 0000000..81cd181
--- /dev/null
+++ b/aos/build/queues/objects/queue.rb
@@ -0,0 +1,173 @@
+class MessageElementStmt < QStmt
+	attr_accessor :name
+	def initialize(type_name,name,length = nil) #lengths are for arrays
+		@type_name = type_name
+		@type = type_name.to_s
+    @type = '::aos::time::Time' if @type == 'Time'
+		@name = name
+		@length = length
+	end
+	CommonMistakes = {"short" => "int16_t","int" => "int32_t","long" => "int64_t","time" => "Time"}
+	def check_type_error(locals)
+		if(!(Sizes[@type] || (@length != nil && @type == "char")) )
+			if(correction = CommonMistakes[@type])
+				raise QError.new(<<ERROR_MSG)
+Hey! you have a \"#{@type}\" in your message statement.
+\tplease use #{correction} instead. Your type is not supported because we
+\twant to guarantee that the sizes of the messages stay the same across platforms.
+\tWot. Wot.
+ERROR_MSG
+			elsif(@type == "char")
+				raise QError.new(<<ERROR_MSG)
+Hey! you have a \"#{@type}\" in your message statement.
+\tyou need your declaration to be a char array like: char[10].
+\tor, please use int8_t or uint8_t.
+\tWot. Wot.
+ERROR_MSG
+			else
+				@is_struct_type = true
+				return if(lookup_type(locals))
+				raise QError.new(<<ERROR_MSG)
+Hey! you have a \"#{@type}\" in your message statement.
+\tThat is not in the list of supported types.
+\there is the list of supported types:
+\tint{8,16,32,64}_t,uint{8,16,32,64}_t,bool,float,double
+\tWot. Wot.
+ERROR_MSG
+			end
+		end
+	end
+
+	PrintFormat = {"bool" => "%c",
+                       "float" => "%f",
+                       "char" => "%c",
+                       "double" => "%f",
+                       "uint8_t" => "%\" PRIu8 \"",
+                       "uint16_t" => "%\" PRIu16 \"",
+                       "uint32_t" => "%\" PRIu32 \"",
+                       "uint64_t" => "%\" PRIu64 \"",
+                       "int8_t" => "%\" PRId8 \"",
+                       "int16_t" => "%\" PRId16 \"",
+                       "int32_t" => "%\" PRId32 \"",
+                       "int64_t" => "%\" PRId64 \"",
+                       "::aos::time::Time" => "\" AOS_TIME_FORMAT \""}
+        def toPrintFormat()
+		if(format = PrintFormat[@type])
+			return format;
+		end
+		raise QError.new(<<ERROR_MSG)
+Somehow this slipped past me, but
+\tI couldn't find the print format of #{@type}. Really, my bad.
+\tWot. Wot.
+ERROR_MSG
+	end
+
+	Sizes = {"bool" => 1, "float" => 4,"double" => 8,"::aos::time::Time" => 8}
+	[8,16,32,64].each do |len|
+		Sizes["int#{len}_t"] = len / 8
+		Sizes["uint#{len}_t"] = len / 8
+	end
+	Zero = {"float" => "0.0f","double" => "0.0","bool" => "false","::aos::time::Time" => "::aos::time::Time(0, 0)"}
+	def size()
+		if(size = Sizes[@type]); return size; end
+		return 1 if(@type == "char")
+		raise QError.new(<<ERROR_MSG)
+Somehow this slipped past me, but
+\tI couldn't find the size of #{@type}. Really, my bad.
+\tWot. Wot.
+ERROR_MSG
+	end
+	def lookup_type(locals)
+		return @type_name.lookup(locals)
+	end
+	def q_eval(locals)
+		check_type_error(locals)
+		if(@is_struct_type)
+			tval = lookup_type(locals)
+			member = Target::MessageStructElement.new(tval, @name)
+      if (@length != nil)
+        inner_member = member
+        member = Target::MessageArrayElement.new(inner_member, @length)
+      end
+		else
+			member = Target::MessageElement.new(@type,@name)
+			member.size = size()
+			member.zero = Zero[@type] || "0";
+			member.printformat = toPrintFormat()
+
+			if(@length != nil)
+        inner_member = member
+				member = Target::MessageArrayElement.new(inner_member,@length)
+			end
+		end
+		locals.local.add_member(member)
+	end
+	def self.parse(tokens)
+		line = tokens.pos
+		#type = tokens.expect(:tWord).data
+		type_name = QualifiedName.parse(tokens)
+		len = nil
+		if(tokens.peak == :tOpenB)
+			tokens.expect(:tOpenB)
+			len = tokens.expect(:tNumber).data
+			tokens.expect(:tCloseB)
+		end
+		name = tokens.expect(:tWord).data
+		tokens.expect(:tSemi)
+		return self.new(type_name,name,len).set_line(line)
+	end
+end
+class MessageStmt < QStmt
+	def initialize(name,suite)
+		@name = name
+		@suite = suite
+	end
+	def q_eval(locals)
+		group = Target::MessageDec.new(@name)
+		locals.register(group)
+		@suite.each do |stmt|
+			stmt.q_eval(locals.bind(group))
+		end 
+		return group
+	end
+	def self.parse(tokens)
+		name = tokens.expect(:tWord).data
+		values = []
+		tokens.expect(:tOpenB)
+		while(tokens.peak != :tCloseB)
+			values << MessageElementStmt.parse(tokens)
+		end
+		names = {}
+		values.each do |val|
+			if(names[val.name])
+				raise QSyntaxError.new(<<ERROR_MSG)
+Hey! duplicate name #{val.name.inspect} in your message declaration statement (message #{name}).
+\tI found them at: #{names[val.name].q_stack_name()} and #{val.q_stack_name()}.
+\tWot. Wot.
+ERROR_MSG
+			end
+			names[val.name] = val
+		end
+		tokens.expect(:tCloseB)
+		tokens.expect(:tSemi)
+		self.new(name,values)
+	end
+end
+class QueueStmt < QStmt
+	def initialize(type,name)
+		@type,@name = type,name
+	end
+	def q_eval(locals)
+		queue = Target::QueueDec.new(@type.lookup(locals),@name)
+		locals.register(queue)
+		locals.local.add_queue(queue) if(locals.local.respond_to?(:add_queue))
+		return queue
+	end
+	def self.parse(tokens)
+		line = tokens.pos
+		type_name = QualifiedName.parse(tokens)
+		name = tokens.expect(:tWord).data
+		tokens.expect(:tSemi)
+		return self.new(type_name,name).set_line(line)
+	end
+end
diff --git a/aos/build/queues/objects/queue_group.rb b/aos/build/queues/objects/queue_group.rb
new file mode 100644
index 0000000..136834f
--- /dev/null
+++ b/aos/build/queues/objects/queue_group.rb
@@ -0,0 +1,115 @@
+class QueueGroupTypeStmt < QStmt
+	def initialize(name,suite)
+		@name,@suite = name,suite
+	end
+	def q_eval(locals)
+		group = Target::QueueGroupDec.new(@name)
+		group.created_by = self
+		locals.register(group)
+		@suite.each do |stmt|
+			stmt.q_eval(locals.bind(group))
+		end
+		return group
+	end
+end
+class ImplementsStmt < QStmt
+	def initialize(name)
+		@name = name
+	end
+	def q_eval(locals)
+
+	end
+	def self.parse(tokens)
+		name = QualifiedName.parse(tokens)
+		tokens.expect(:tSemi)
+		return self.new(name)
+	end
+end
+class QueueGroupStmt < QStmt
+	def initialize(type,name)
+		@type,@name = type,name
+	end
+	def q_eval(locals)
+		group = Target::QueueGroup.new(@type.lookup(locals),@name)
+		group.created_by = self
+		locals.register(group)
+		return group
+	end
+	def self.parse(tokens)
+		line = tokens.pos
+		type_name = QualifiedName.parse(tokens)
+		if(type_name.names.include?("queue_group"))
+			tokens.qError(<<ERROR_MSG)
+I was looking at the identifier you gave 
+\tfor the queue group type between line #{line} and #{tokens.pos}
+\tThere shouldn't be a queue_group type called queue_group
+\tor including queue_group in it's path, it is a reserved keyword.
+\tWot. Wot.
+ERROR_MSG
+		end
+		if(tokens.peak == :tOpenB)
+			if(type_name.is_simple?())
+				type_name = type_name.to_simple
+			else
+				tokens.qError(<<ERROR_MSG)
+You gave the name: "#{type_name.to_s}" but you're only allowed to 
+\thave simple names like "#{type_name.names[-1]}" in queue_group definitions
+\ttry something like:
+\tqueue_group ControlLoop { }
+\tWot. Wot.
+ERROR_MSG
+			end
+			tokens.expect(:tOpenB)
+			suite = []
+			while(tokens.peak != :tCloseB)
+				token = tokens.expect(:tWord) do |token|
+					<<ERROR_MSG
+I'm a little confused, I found a #{token.humanize} at #{token.pos}
+\tbut what I really wanted was an identifier signifying a nested 
+\tmessage declaration, or queue definition, or an impliments statement.
+\tWot.Wot
+ERROR_MSG
+				end
+				case token.data
+				when "message"
+					suite << MessageStmt.parse(tokens)
+				when "queue"
+					suite << QueueStmt.parse(tokens)
+				when "implements"
+					suite << ImplementsStmt.parse(tokens)
+				else
+					tokens.qError(<<ERROR_MSG)
+expected a "queue","implements" or "message" statement rather
+\tthan a #{token.data.inspect}.
+\tWot. Wot.
+ERROR_MSG
+				end 
+			end
+			tokens.expect(:tCloseB)
+			obj = QueueGroupTypeStmt.new(type_name,suite).set_line(line)
+		else
+			name = (tokens.expect(:tWord) do |token|
+				<<ERROR_MSG
+I found a #{token.humanize} at #{token.pos}
+\tbut I was in the middle of parsing a queue_group statement, and
+\twhat I really wanted was an identifier to store the queue group.
+\tSomething like: queue_group control_loops.Drivetrain my_cool_group;
+\tWot.Wot
+ERROR_MSG
+			end).data
+			obj = QueueGroupStmt.new(type_name,name).set_line(line)
+			if(tokens.peak == :tDot)
+				tokens.qError(<<ERROR_MSG)
+Hey! It looks like you're trying to use a complex identifier at: #{tokens.pos}
+\tThats not going to work. Queue Group definitions have to be of the form:
+\tqueue_group ComplexID SimpleID
+\tWot. Wot.
+ERROR_MSG
+			end	
+		end
+		tokens.expect(:tSemi) do |token|
+			token.pos
+		end
+		return obj
+	end
+end
diff --git a/aos/build/queues/objects/tokenizer.rb b/aos/build/queues/objects/tokenizer.rb
new file mode 100644
index 0000000..2a33b90
--- /dev/null
+++ b/aos/build/queues/objects/tokenizer.rb
@@ -0,0 +1,213 @@
+class BufferedReader
+	def initialize(file)
+		@file = file
+		@line = 1
+		@chars = []
+		@col_nums = []
+		@col = 0
+	end
+	def filename
+		return File.basename(@file.path)
+	end
+	def pos()
+		"#{filename()}:#{lineno()},#{@col}"
+	end
+	def clear_comment()
+		@file.gets
+		@line += 1
+	end
+	def lineno()
+		return @line
+		return @file.lineno + 1
+	end
+	def pop_char()
+		val = @chars.pop() || @file.read(1)
+		@col_nums[@line] = @col += 1
+		if(val == "\n")
+			@line += 1
+			@col = 0
+		end
+
+		return val
+	end
+	def unpop_char(char)
+		if(char == "\n")
+			@line -= 1
+			@col = @col_nums[@line]
+		end
+		@col -= 1
+		@chars.push(char)
+	end
+end
+class Tokenizer
+	TOKEN_TYPES = {"{" => :tOpenB,"}"=> :tCloseB,";" => :tSemi,"," => :tComma,
+		"(" => :tOpenParan,")" => :tCloseParan,"=" => :tAssign,"." => :tDot,
+		"<<"=> :tLShift,"*" => :tMult,"+" => :tAdd,"[" => :tOpenB,
+		"]" => :tCloseB}
+	Humanize = TOKEN_TYPES.invert
+	class Token
+		attr_accessor :type,:data,:pos
+		def to_s
+			if(@type == :tString)
+				val = @data.inspect.to_s
+			elsif(@type == :tWord)
+				val = @data.to_s
+			else
+				val = @data.to_s
+			end
+			return "#{val.ljust(50)}:#{@type}"
+		end
+		def humanize()
+			if(@type == :tString)
+				return "#{@data.inspect.to_s} string"
+			elsif(@type == :tWord)
+				return "#{@data.inspect} identifier"
+			end
+			return Humanize[@type].inspect
+		end
+		def inspect()
+			data = ""
+			data = " #{@data.inspect}" if(@data)
+			"<Token :#{@type}#{data} at #{@pos}>"
+		end
+		def ==(other)
+			if(other.class == Symbol)
+				return @type == other
+			elsif(other.class == self.class)
+				return @type == other.type && @data == other.data
+			else
+				return nil
+			end
+		end
+	end
+	def initialize(file)
+		file = File.open(file,"r") if(file.class == String)
+		@read = BufferedReader.new(file)
+	end
+	def qError(error)
+		syntax_error(error)
+	end
+	def syntax_error(msg)
+		err = QSyntaxError.new(msg)
+		err.qstacktrace << "#{@read.lineno} of #{@read.filename}"
+		raise err
+	end
+	def peak_token()
+		@peak_token = next_token()
+	end
+	def peak()
+		peak_token()
+	end
+	def next()
+		next_token()
+	end
+	def pos()
+		@read.pos
+	end
+	def tokenize(string_token)
+		token = Token.new()
+		token.type = TOKEN_TYPES[string_token]
+		return token
+	end
+	def next_token()
+		if(token = @peak_token)
+			@peak_token = nil
+			return token
+		end
+		token = next_token_cache()
+		pos = self.pos()
+		token.pos = pos
+		return token
+	end
+	def next_token_cache()
+		token = Token.new()
+		token.data = ""
+		while (char = @read.pop_char())
+			#puts "#{char.inspect}:#{token.inspect}"
+			if(char == "/")
+				if(@read.pop_char == "/")
+					@read.clear_comment()
+				else
+					syntax_error("unexpected #{char.inspect}")
+				end
+			elsif(char == "#")
+				@read.clear_comment()
+			elsif(char =~ /[\s\r\n]/)
+				if(token.type)
+					return token
+				end
+			elsif(char =~ /\"/)
+				token.type = :tString
+				token.data = ""
+				while((char = @read.pop_char) != "\"")
+					token.data += char
+				end
+				return token
+			elsif(char =~ /[1-9]/)
+				token.type = :tNumber
+				token.data = char.to_i
+				while(char != ".")
+					char = @read.pop_char
+					if(char =~ /[0-9]/)
+						token.data = char.to_i + token.data * 10
+					elsif(char == ".")
+					else
+						@read.unpop_char(char)
+						return token
+					end
+				end
+				second_char = 0
+				man = 0
+				while(true)
+					char = @read.pop_char
+					if(char =~ /[0-9]/)
+						second_char = char.to_i + second_char * 10
+						man = man * 10
+					else
+						@read.unpop_char(char)
+						token.data += second_char / man.to_f
+						return token
+					end
+				end
+			elsif(char == ":")
+				if(@read.pop_char == "=")
+					return tokenize(":=")
+				end
+				syntax_error("unexpected \":\"")
+			elsif(char =~ /[;\{\}=()\",\*\+\.\[\]]/)
+				return(tokenize(char))
+			elsif(char =~ /[a-zA-Z_]/)
+				token.type = :tWord
+				token.data = char
+				while(true)
+					char = @read.pop_char()
+					if(char && char =~ /\w/)
+						token.data += char
+					else
+						@read.unpop_char(char)
+						return token
+					end
+				end
+			elsif(char == "<")
+				if((char = @read.pop_char()) == "<")
+					return tokenize("<<")
+				else
+					@read.unpop_char(char)
+					return tokenize("<")
+				end
+			else
+				syntax_error("unexpected #{char.inspect}")
+			end
+		end
+		token.type = :tEnd
+		return token
+	end
+	def expect(type,&blk)
+		token = self.next
+		if(token != type)
+			syntax_error(blk.call(token)) if(blk)
+			syntax_error("unexpected: #{token.type}")
+		end
+		return token
+	end
+end
diff --git a/aos/build/queues/output/message_dec.rb b/aos/build/queues/output/message_dec.rb
new file mode 100644
index 0000000..5b4e136
--- /dev/null
+++ b/aos/build/queues/output/message_dec.rb
@@ -0,0 +1,428 @@
+begin
+  require "sha1"
+rescue LoadError
+  require "digest/sha1"
+end
+
+class Target::StructBase < Target::Node
+  def create_DoGetType(type_class, cpp_tree)
+    member_func = CPP::MemberFunc.new(type_class,"const ::aos::MessageType*","DoGetType")
+    member_func.static = true
+    fields = []
+    register_members = []
+    @members.each do |member|
+      tId = member.getTypeID()
+      fieldName = member.name.inspect
+      if(member.respond_to?(:add_TypeRegister))
+        register_members.push(member)
+      end
+      fields << "new ::aos::MessageType::Field{#{tId}, #{member.respond_to?(:length) ? member.length : 0}, #{fieldName}}"
+    end
+    register_members.uniq do |member|
+      member.type
+    end.each do |member|
+      member.add_TypeRegister(cpp_tree, type_class, member_func)
+    end
+    id = getTypeID()
+    member_func.suite << ("static const ::aos::MessageType kMsgMessageType(#{type_class.parent_class ? type_class.parent_class + '::Size()' : 0}, #{id}, #{(@loc.respond_to?(:queue_name) ? @loc.queue_name(@name) : "#{@loc.get_name()}.#{@name}").inspect}, {" +
+                          "#{fields.join(", ")}})");
+                          type_class.add_member(member_func)
+                          member_func.suite << "::aos::type_cache::Add(kMsgMessageType)"
+                          member_func.suite << CPP::Return.new("&kMsgMessageType")
+  end
+  def create_InOrderConstructor(type_class, cpp_tree)
+    if @members.empty?
+      return
+    end
+    cons = CPP::Constructor.new(type_class)
+    type_class.add_member(cons)
+    @members.each do |member|
+      if member.respond_to?(:type_name)
+        type_name = "#{member.type_name(cpp_tree)} #{member.name}_in"
+      else
+        type_name = member.create_usage(cpp_tree, "#{member.name}_in")
+      end
+
+      cons.args << type_name
+      cons.add_cons(member.name, member.name + '_in')
+    end
+  end
+  def create_DefaultConstructor(type_class, cpp_tree)
+    cons = CPP::Constructor.new(type_class)
+    type_class.add_member(cons)
+    cons.add_cons(type_class.parent_class) if type_class.parent_class
+    cons.suite << CPP::FuncCall.build('Zero')
+  end
+  def create_Zero(type_class,cpp_tree)
+    member_func = CPP::MemberFunc.new(type_class,"void","Zero")
+    type_class.add_member(member_func)
+    @members.each do |elem|
+      elem.zeroCall(member_func.suite)
+    end
+    member_func.suite << CPP::FuncCall.new(type_class.parent_class + '::Zero') if type_class.parent_class
+  end
+  def create_Size(type_class,cpp_tree)
+    member_func = CPP::MemberFunc.new(type_class,"size_t","Size")
+    member_func.inline = true
+    member_func.static = true
+    type_class.add_member(member_func.forward_dec)
+    size = 0
+    @members.each do |elem|
+      size += elem.size
+    end
+    if type_class.parent_class
+      member_func.suite << CPP::Return.new(CPP::Add.new(size,
+                                                        "#{type_class.parent_class}::Size()"))
+    else
+      member_func.suite << CPP::Return.new(size)
+    end
+  end
+  def create_Serialize(type_class,cpp_tree)
+    member_func = CPP::MemberFunc.new(type_class,"size_t","Serialize")
+    type_class.add_member(member_func)
+    member_func.args << "char *buffer"
+    member_func.suite << "#{type_class.parent_class}::Serialize(buffer)" if type_class.parent_class
+    member_func.const = true
+    offset = type_class.parent_class ? type_class.parent_class + '::Size()' : '0'
+    @members.each do |elem|
+      elem.toNetwork(offset,member_func.suite)
+      offset += " + #{elem.size}";
+    end
+    member_func.suite << CPP::Return.new(CPP::FuncCall.new('Size'))
+  end
+  def create_Deserialize(type_class,cpp_tree)
+    member_func = CPP::MemberFunc.new(type_class,"size_t","Deserialize")
+    type_class.add_member(member_func)
+    member_func.args << "const char *buffer"
+    member_func.suite << "#{type_class.parent_class}::Deserialize(buffer)" if type_class.parent_class
+    offset = type_class.parent_class ? type_class.parent_class + '::Size()' : '0'
+    @members.each do |elem|
+      elem.toHost(offset,member_func.suite)
+      offset += " + #{elem.size}";
+    end
+    member_func.suite << CPP::Return.new(CPP::FuncCall.new('Size'))
+  end
+  def create_EqualsNoTime(type_class,cpp_tree)
+    member_func = CPP::MemberFunc.new(type_class,"bool","EqualsNoTime")
+    member_func.const = true
+    type_class.add_member(member_func)
+    member_func.args << "const #{type_class.name} &other"
+    member_func.suite << "if (!#{type_class.parent_class}::EqualsNoTime(other)) return false;" if type_class.parent_class
+    @members.each do |elem|
+      if elem.respond_to? :create_EqualsNoTime
+        member_func.suite << "if (!other.#{elem.name}.EqualsNoTime(#{elem.name})) return false;"
+      elsif elem.respond_to?(:length) && elem.member_type.respond_to?(:create_EqualsNoTime)
+        0.upto(elem.length - 1) do |i|
+          member_func.suite << "if (!other.#{elem.name}[#{i}].EqualsNoTime(#{elem.name}[#{i}])) return false;"
+        end
+      else
+        member_func.suite << "if (other.#{elem.name} != #{elem.name}) return false;"
+      end
+    end
+    member_func.suite << CPP::Return.new('true')
+  end
+  def simpleStr()
+    return "{\n" + @members.collect() { |elem| elem.simpleStr() + "\n"}.join("") + "}"
+  end
+  def getTypeID()
+    return "0x" + (((Digest::SHA1.hexdigest(simpleStr())[0..3].to_i(16)) << 16) | size).to_s(16)
+  end
+  def add_member(member)
+    @members << member
+  end
+  def size()
+    return @size if(@size)
+    @size = 0
+    @members.each do |elem|
+      @size += elem.size
+    end
+    return @size
+  end
+end
+
+class Target::MessageDec < Target::StructBase
+  attr_accessor :name,:loc,:parent,:msg_hash
+  def initialize(name)
+    @name = name
+    @members = []
+  end
+  def extern=(value)
+    @extern=value
+  end
+  def get_name()
+    if(@parent)
+      return "#{@parent.get_name}.#{@name}"
+    else
+      return "#{@name}"
+    end
+  end
+  def create_Print(type_class,cpp_tree)
+    member_func = CPP::MemberFunc.new(type_class,"size_t","Print")
+    type_class.add_member(member_func)
+    member_func.args << "char *buffer"
+    member_func.args << "size_t length"
+    member_func.const = true
+    format = "\""
+    args = []
+    @members.each do |elem|
+      format += ", "
+      format += elem.toPrintFormat()
+      elem.fetchPrintArgs(args)
+    end
+    format += "\""
+    member_func.suite << "size_t super_size = ::aos::Message::Print(buffer, length)"
+    member_func.suite << "buffer += super_size"
+    member_func.suite << "length -= super_size"
+    if !args.empty?
+      member_func.suite << "return super_size + snprintf(buffer, length, " + ([format] + args).join(", ") + ")";
+    else
+      # snprintf will return zero.
+      member_func.suite << "return super_size"
+    end
+  end
+  def create_GetType(type_class, cpp_tree)
+    member_func = CPP::MemberFunc.new(type_class,"const ::aos::MessageType*","GetType")
+    type_class.add_member(member_func)
+    member_func.static = true
+    member_func.suite << "static ::aos::Once<const ::aos::MessageType> getter(#{type_class.name}::DoGetType)"
+    member_func.suite << CPP::Return.new("getter.Get()")
+  end
+  def self.builder_loc(loc)
+    return @builder_loc if(@builder_loc)
+    return @builder_loc = loc.root.get_make("aos")
+  end
+  def type_name(builder_loc,name)
+    if(builder_loc == @loc) #use relative name
+      return name
+    else #use full name
+      return @loc.to_cpp_id(name)
+    end
+  end
+  def create(cpp_tree)
+    return self if(@extern)
+    orig_namespace = namespace = cpp_tree.get(@loc)
+    name = ""
+    if(namespace.class < Types::Type) #is nested
+      name = namespace.name + "_" + name
+      namespace = namespace.space
+    end
+    type_class = namespace.add_struct(name + @name)
+    if(name.length > 0)
+      orig_namespace.add_member(:public, Types::TypeDef.new(type_class,@name))
+    end
+    cpp_tree.set(self,type_class)
+    type_class.set_parent("public ::aos::Message")
+    ts = self.simpleStr()
+    self.msg_hash = "0x#{Digest::SHA1.hexdigest(ts)[-8..-1]}"
+    type_class.add_member("enum {kQueueLength = 100, kHash = #{self.msg_hash}}")
+    @members.each do |elem|
+      type_class.add_member(elem.create_usage(cpp_tree))
+    end
+
+    create_Serialize(type_class,cpp_tree)
+    create_Deserialize(type_class,cpp_tree)
+    create_Zero(type_class,cpp_tree)
+    create_Size(type_class,cpp_tree)
+    create_Print(type_class,cpp_tree)
+    create_GetType(type_class, cpp_tree)
+    create_DoGetType(type_class, cpp_tree)
+    create_DefaultConstructor(type_class, cpp_tree)
+    create_InOrderConstructor(type_class, cpp_tree)
+    create_EqualsNoTime(type_class, cpp_tree)
+
+    b_namespace = cpp_tree.get(b_loc = self.class.builder_loc(@loc))
+
+    template = b_namespace.add_template("MessageBuilder")
+    template.spec_args << t = @loc.to_cpp_id(@name)
+    msg_ptr_t = "ScopedMessagePtr< #{t}>"
+    msg_bld_t = "MessageBuilder< #{t}>"
+    template.add_member(:private,"#{msg_ptr_t} msg_ptr_")
+    template.add_member(:private,"#{msg_bld_t}(const #{msg_bld_t}&)")
+    template.add_member(:private,"void operator=(const #{msg_bld_t}&)")
+    template.add_member(:private,"friend class ::aos::Queue< #{t}>")
+
+    cons = CPP::Constructor.new(template)
+    template.add_member(:private,cons)
+    cons.args << "RawQueue *queue"
+    cons.args << "#{t} *msg"
+    cons.add_cons("msg_ptr_","queue","msg")
+    template.public
+    DefineMembers(cpp_tree, template, msg_bld_t)
+  end
+  def DefineMembers(cpp_tree, template, msg_bld_t) 
+    send = template.def_func("bool","Send")
+    send.suite << CPP::Return.new("msg_ptr_.Send()")
+    @members.each do |elem|
+=begin
+      MessageBuilder<frc971::control_loops::Drivetrain::Goal> &steering(
+              double steering) {
+            msg_ptr_->steering = steering;
+              return *this;
+              }
+=end
+      setter = template.def_func(msg_bld_t,"&#{elem.name}")
+        setter.args << elem.create_usage(cpp_tree)
+      elem.set_message_builder(setter.suite)
+      setter.suite << CPP::Return.new("*this")
+
+    end
+  end
+end
+class Target::MessageElement < Target::Node
+  attr_accessor :name,:loc,:size,:zero,:type,:printformat
+  def initialize(type,name)
+    @type,@name = type,name
+  end
+  def type()
+    return @type
+  end
+  def type_name(cpp_tree)
+    return type()
+  end
+  def toPrintFormat()
+    return printformat
+  end
+  def create_usage(cpp_tree, this_name=nil)
+    if (this_name == nil)
+      this_name = @name
+    end
+    "#{@type} #{this_name}"
+  end
+  def toNetwork(offset,suite, parent = "", this_name=nil)
+    if (this_name == nil)
+      this_name = @name
+    end
+    suite << f_call = CPP::FuncCall.build("to_network",
+                                          "&#{parent}#{this_name}",
+                                          "&buffer[#{offset}]")
+    f_call.args.dont_wrap = true
+  end
+  def toHost(offset,suite, parent = "", this_name=nil)
+    if (this_name == nil)
+      this_name = @name
+    end
+    suite << f_call = CPP::FuncCall.build("to_host",
+                                          "&buffer[#{offset}]",
+                                          "&#{parent}#{this_name}")
+                                            f_call.args.dont_wrap = true
+  end
+  def getTypeID()
+    '0x' + ((Digest::SHA1.hexdigest(@type)[0..3].to_i(16) << 16) |
+            0x2000 | # marks it as primitive
+            size).to_s(16)
+  end
+  def simpleStr()
+    "#{@type} #{@name}"
+  end
+  def set_message_builder(suite, this_name=nil)
+    this_name ||= @name
+    suite << "msg_ptr_->#{this_name} = #{this_name}"
+  end
+
+  def zeroCall(suite, parent = "", this_name=nil)
+    if (this_name == nil)
+      this_name = @name
+    end
+    suite << CPP::Assign.new(parent + this_name,@zero)
+  end
+  def fetchPrintArgs(args, parent = "", this_name=nil)
+    if (this_name == nil)
+      this_name = @name
+    end
+    if (@type == 'bool')
+      args.push("#{parent}#{this_name} ? 'T' : 'f'")
+    elsif (@type == '::aos::time::Time')
+      args.push("AOS_TIME_ARGS(#{parent}#{this_name}.sec(), #{parent}#{this_name}.nsec())")
+    else
+      args.push("#{parent}#{this_name}")
+    end
+  end
+end
+class Target::MessageArrayElement < Target::Node
+  attr_accessor :loc, :length
+  def initialize(type,length)
+    @type,@length = type,length
+  end
+  def zero()
+    return @type.zero()
+  end
+  def name()
+    return @type.name()
+  end
+
+  def add_TypeRegister(*args)
+    if @type.respond_to?(:add_TypeRegister)
+      @type.add_TypeRegister(*args)
+    end
+  end
+
+  def toPrintFormat()
+    return ([@type.toPrintFormat] * @length).join(", ")
+  end
+  def create_usage(cpp_tree, this_name=nil)
+    if (this_name == nil)
+      this_name = name
+    end
+    return "::std::array< #{@type.type_name(cpp_tree)}, #{@length}> #{this_name}"
+  end
+  def type()
+    return "::std::array< #{@type.type()}, #{@length}>"
+  end
+  def member_type()
+    return @type
+  end
+  def simpleStr()
+    return "#{@type.type} #{@name}[#{@length}]"
+  end
+  def getTypeID()
+    return @type.getTypeID()
+  end
+  def size()
+    return @type.size * @length
+  end
+  def toNetwork(offset, suite, parent="", this_name=nil)
+    if (this_name == nil)
+      this_name = name
+    end
+    offset = (offset == 0) ? "" : "#{offset} + "
+    for_loop_var = getForLoopVar()
+    suite << for_stmt = CPP::For.new("int #{for_loop_var} = 0","#{for_loop_var} < #{@length}","#{for_loop_var}++")
+    @type.toNetwork("#{offset} (#{for_loop_var} * #{@type.size})", for_stmt.suite, parent, "#{this_name}[#{for_loop_var}]")
+  end
+  def toHost(offset, suite, parent="", this_name=nil)
+    if (this_name == nil)
+      this_name = name
+    end
+    offset = (offset == 0) ? "" : "#{offset} + "
+    for_loop_var = getForLoopVar()
+    suite << for_stmt = CPP::For.new("int #{for_loop_var} = 0","#{for_loop_var} < #{@length}","#{for_loop_var}++")
+    @type.toHost("#{offset} (#{for_loop_var} * #{@type.size})", for_stmt.suite, parent, "#{this_name}[#{for_loop_var}]")
+  end
+  def set_message_builder(suite, this_name=nil)
+    if (this_name == nil)
+      this_name = name
+    end
+
+    for_loop_var = getForLoopVar()
+    suite << for_stmt = CPP::For.new("int #{for_loop_var} = 0","#{for_loop_var} < #{@length}","#{for_loop_var}++")
+    @type.set_message_builder(for_stmt.suite, "#{this_name}[#{for_loop_var}]")
+  end
+  def zeroCall(suite, parent="", this_name=nil)
+    if (this_name == nil)
+      this_name = name
+    end
+
+    offset = (offset == 0) ? "" : "#{offset} + "
+    for_loop_var = getForLoopVar()
+    suite << for_stmt = CPP::For.new("int #{for_loop_var} = 0","#{for_loop_var} < #{@length}","#{for_loop_var}++")
+    @type.zeroCall(for_stmt.suite, parent, "#{this_name}[#{for_loop_var}]")
+  end
+  def fetchPrintArgs(args, parent = "", this_name=nil)
+    if (this_name == nil)
+      this_name = name
+    end
+    for i in 0..(@length-1)
+      @type.fetchPrintArgs(args, parent, "#{this_name}[#{i}]")
+    end
+  end
+end
diff --git a/aos/build/queues/output/q_file.rb b/aos/build/queues/output/q_file.rb
new file mode 100644
index 0000000..471bdcb
--- /dev/null
+++ b/aos/build/queues/output/q_file.rb
@@ -0,0 +1,198 @@
+begin
+  require "sha1"
+rescue LoadError
+  require "digest/sha1"
+end
+
+$i = 0
+def getForLoopVar()
+  $i = $i + 1
+  return "_autogen_index_#{$i}"
+end
+
+module Target
+end
+class Target::Node
+	attr_accessor :created_by
+	def get_name()
+		if(@parent)
+			return "#{@parent.get_name}.#{@name}"
+		else
+			return "#{@name}"
+		end 
+	end
+end
+class Target::QFile < Target::Node
+	def initialize() #needs to know repo_path, 
+		@class_types = []
+	end
+	def add_type(type)
+		@class_types << type
+	end
+	def extern=(value)
+		@class_types.each do |type|
+			type.extern=value
+		end
+	end
+	def make_cpp_tree(rel_path)
+		cpp_tree = DepFilePair.new(rel_path)
+		cpp_tree.add_header_include("<array>")
+		cpp_tree.add_header_include("\"aos/common/macros.h\"")
+		cpp_tree.add_header_include("\"aos/common/queue.h\"")
+		@class_types.each do |type|
+			cpp_tree.get(type)
+		end
+		return cpp_tree
+	end
+end
+class Target::QInclude < Target::Node
+	def initialize(path)
+		@path = path
+	end
+	def create(cpp_tree)
+#		inc = cpp_tree.header.add_include("\"#{@path}\"")
+		inc = cpp_tree.add_header_include("\"#{@path}\"")
+		cpp_tree.set(self,inc)
+	end
+end
+class Target::QueueGroupDec < Target::Node
+	attr_accessor :name,:loc,:parent,:queues
+	def initialize(name)
+		@name = name
+		@queues = []
+		@subs = {}
+	end
+	def root()
+		@parent.root()
+	end
+	def []=(key,val)
+		#puts "#{key}= #{val}"
+		@subs[key] = val
+	end
+	def extern=(value)
+		@extern=value
+	end
+	def get_name()
+		if(@parent)
+			return "#{@parent.get_name}.#{@name}"
+		else
+			return "#{@name}"
+		end 
+	end
+	def to_cpp_id(id)
+		name = "#{@name}::#{id}"
+		return @parent.to_cpp_id(name) if(@parent)
+		return name
+	end
+	def [](key)
+		#puts "#{key}"
+		@subs[key]
+	end
+	def add_queue(queue)
+		@queues.push(queue)
+	end
+	def hash_with_name(name)
+		ts = (@queues.collect { |queue|
+			queue.msg_hash()
+		}).join("") + name
+		return "0x#{Digest::SHA1.hexdigest(ts)[-8..-1]}"
+	end
+	def create(cpp_tree)
+		return if(@extern)
+		namespace = cpp_tree.get(@loc)
+		type_class = Types::Class.new(namespace,@name)
+		cpp_tree.set(self,type_class)  #breaks infinite recursion
+		type_class.set_parent("public ::aos::QueueGroup")
+		@queues.each do |queue|
+			type_class.add_member(:public,queue.create_usage(cpp_tree))
+		end
+		create_Constructor(type_class,cpp_tree)
+		namespace.add(type_class)
+	end
+	def create_Constructor(type_class,cpp_tree)
+		member_func = CPP::Constructor.new(type_class)
+		type_class.add_member(:public,member_func)
+		#cpp_tree.cc_file.add_funct(member_func)
+		member_func.args << "const char *name";
+		member_func.args << "uint32_t hash";
+		member_func.add_cons("::aos::QueueGroup","name", "hash")
+		@queues.each do |queue|
+			member_func.args << "const char *#{queue.name}_name";
+			member_func.add_cons(queue.name,"#{queue.name}_name")
+		end
+	end
+end
+class Target::QueueGroup < Target::Node
+	attr_accessor :name,:loc
+	def initialize(type,name)
+		@type,@name = type,name
+	end
+	def type_name()
+		if(@type.loc == @loc) #use relative name
+			return @type.name
+		else #use full name
+			return @type.loc.to_cpp_id(@type.name)
+		end 
+	end
+	def create(cpp_tree)
+		namespace = cpp_tree.get(@loc)
+		type = cpp_tree.get(@type)
+		cpp_tree.set(self,self)
+		namespace.add_cc("static #{type_name} *#{@name}_ptr")
+		counter = "#{@name}_counter"
+		namespace.add_cc("static int #{counter}")
+
+		str = <<COMMENT_END
+Schwarz counter to construct and destruct the #{@name} object.
+Must be constructed before &#{@name} is constructed so that #{@name}_ptr
+is valid so we can store a reference to the object.
+COMMENT_END
+		str.split(/\n/).each do |str_sec|
+			namespace.class_comment(str_sec)
+		end
+		init_class = namespace.add_class("InitializerFor_" + @name).add_dep(type)
+		
+
+		init_class.add_cc_comment(
+        "The counter is initialized at load-time, i.e., before any of the static",
+		"objects are initialized.")
+
+
+		cons = CPP::Constructor.new(init_class)
+		init_class.add_member(:public,cons)
+		cons.suite << if_stmt = CPP::If.new("0 == #{counter}++")
+
+		cons_call = CPP::FuncCall.new("new #{type_name}")
+		cons_call.args.push(@loc.queue_name(@name).inspect)
+
+		cons_call.args.push(@type.hash_with_name(@loc.queue_name(@name).inspect))
+		@type.queues.collect do |queue|
+			cons_call.args.push(@loc.queue_name(@name + "." + queue.name).inspect)
+		end
+		if_stmt.suite << CPP::Assign.new("#{@name}_ptr",cons_call)
+
+
+		destruct = CPP::Destructor.new(init_class)
+		destruct.suite << if_stmt = CPP::If.new("0 == --#{counter}")
+		if_stmt.suite << "delete #{@name}_ptr"
+		if_stmt.suite << CPP::Assign.new("#{@name}_ptr","NULL")
+
+		init_class.add_member(:public,destruct)
+		init_class.static = true
+		init_class.dec = @name + "_initializer";
+
+		str = <<COMMENT_END
+Create a reference to the new object in the pointer.  Since we have already
+created the initializer
+COMMENT_END
+		str.split(/\n/).map{|str_sec| CPP::Comment.new(str_sec)}.each do |comment|
+      namespace.add(comment)
+    end
+		namespace.add("static UNUSED_VARIABLE #{type_name} &#{@name}" +
+                  " = #{@name}_initializer.get()")
+
+		get = init_class.def_func(type_name,"get") #.add_dep(type)
+		get.pre_func_types = "&"
+		get.suite << CPP::Return.new("*#{@name}_ptr")
+	end
+end
diff --git a/aos/build/queues/output/q_struct.rb b/aos/build/queues/output/q_struct.rb
new file mode 100644
index 0000000..f538bb3
--- /dev/null
+++ b/aos/build/queues/output/q_struct.rb
@@ -0,0 +1,156 @@
+class Target::StructDec < Target::StructBase
+  attr_accessor :name,:loc,:parent, :extern
+  def initialize(name)
+    @name = name
+    @members = []
+  end
+  def add_member(member)
+    @members << member
+  end
+  def create_GetType(type_class, cpp_tree)
+    member_func = CPP::MemberFunc.new(type_class,"const ::aos::MessageType*","GetType")
+    type_class.add_member(member_func)
+    member_func.static = true
+    member_func.suite << "static ::aos::Once<const ::aos::MessageType> getter(#{type_class.name}::DoGetType)"
+    member_func.suite << CPP::Return.new("getter.Get()")
+  end
+  def create(cpp_tree)
+    return self if(@extern)
+    orig_namespace = namespace = cpp_tree.get(@loc)
+    name = ""
+    if(namespace.class < Types::Type) #is nested
+      name = namespace.name + "_" + name
+      namespace = namespace.space
+    end
+    type_class = namespace.add_struct(name + @name)
+
+    @members.each do |elem|
+      type_class.add_member(elem.create_usage(cpp_tree))
+    end
+    create_DoGetType(type_class, cpp_tree)
+    create_GetType(type_class, cpp_tree)
+    create_DefaultConstructor(type_class, cpp_tree)
+    create_InOrderConstructor(type_class, cpp_tree)
+    create_Zero(type_class, cpp_tree)
+    create_Size(type_class, cpp_tree)
+    create_Serialize(type_class, cpp_tree)
+    create_Deserialize(type_class, cpp_tree)
+    create_EqualsNoTime(type_class, cpp_tree)
+    return type_class
+  end
+  def getPrintFormat()
+    return "{" + @members.collect { |elem| elem.toPrintFormat() }.join(", ") + "}"
+  end
+  def fetchPrintArgs(args, parent = "")
+    @members.each do |elem|
+      elem.fetchPrintArgs(args, parent)
+    end
+  end
+  def toHost(offset, suite, parent)
+    @members.each do |elem|
+      elem.toHost(offset, suite, parent)
+      offset += " + #{elem.size()}"
+    end
+  end
+  def toNetwork(offset, suite, parent)
+    @members.each do |elem|
+      elem.toNetwork(offset, suite, parent)
+      offset += " + #{elem.size()}"
+    end
+  end
+  def zeroCall(suite, parent)
+    @members.each do |elem|
+      elem.zeroCall(suite, parent)
+    end
+  end
+end
+class Target::MessageStructElement < Target::Node
+  attr_accessor :name,:loc
+  def initialize(type,name)
+    @type, @name = type, name
+  end
+  def type()
+    return @type.get_name
+  end
+  def create_EqualsNoTime(type_class,cpp_tree)
+    member_func = CPP::MemberFunc.new(type_class,"bool","EqualsNoTime")
+    member_func.const = true
+    type_class.add_member(member_func)
+    member_func.args << "const #{type_class.name} &other"
+    member_func.suite << "if (!#{type_class.parent_class}::EqualsNoTime(other)) return false;" if type_class.parent_class
+    @members.each do |elem|
+      if elem.respond_to? :create_EqualsNoTime
+        member_func.suite << "if (!other.#{elem.name}.EqualsNoTime(#{elem.name})) return false;"
+      elsif elem.respond_to?(:length) && elem.member_type.respond_to?(:create_EqualsNoTime)
+        0.upto(elem.length - 1) do |i|
+          member_func.suite << "if (!other.#{elem.name}[#{i}].EqualsNoTime(#{elem.name}[#{i}])) return false;"
+        end
+      else
+        member_func.suite << "if (other.#{elem.name} != #{elem.name}) return false;"
+      end
+    end
+    member_func.suite << CPP::Return.new('true')
+  end
+  def type_name(cpp_tree)
+    type = cpp_tree.get(@type)
+    if(@type.loc == @loc) #use relative name
+      return type.name
+    else #use full name
+      return @type.loc.to_cpp_id(type.name)
+    end 
+  end
+  def size()
+    return @type.size()
+  end
+  def toPrintFormat()
+    @type.getPrintFormat()
+  end
+  def create_usage(cpp_tree, this_name=nil)
+    if (this_name == nil)
+      this_name = @name
+    end
+    return "#{type_name(cpp_tree)} #{this_name}"
+  end
+  def add_TypeRegister(cpp_tree, o_type, member_func)
+    type = cpp_tree.get(@type)
+    tName = @type.loc.to_cpp_id(type.name)
+    member_func.suite << "#{tName}::GetType()"
+  end
+  def fetchPrintArgs(args, parent = "", this_name=nil)
+    if (this_name == nil)
+      this_name = @name
+    end
+    @type.fetchPrintArgs(args, parent + "#{this_name}.")
+  end
+  def toNetwork(offset,suite, parent = "", this_name=nil)
+    if (this_name == nil)
+      this_name = @name
+    end
+    @type.toNetwork(offset, suite, parent + "#{this_name}.")
+  end
+  def toHost(offset,suite, parent = "", this_name=nil)
+    if (this_name == nil)
+      this_name = @name
+    end
+    @type.toHost(offset, suite, parent + "#{this_name}.")
+  end
+  def set_message_builder(suite, this_name=nil)
+    if (this_name == nil)
+      this_name = @name
+    end
+    suite << "msg_ptr_->#{this_name} = #{this_name}"
+  end
+
+  def zeroCall(suite, parent = "", this_name=nil)
+    if (this_name == nil)
+      this_name = @name
+    end
+    @type.zeroCall(suite, parent + "#{this_name}.")
+  end
+  def simpleStr()
+    "#{@type.simpleStr()} #{@name}"
+  end
+  def getTypeID()
+    return @type.getTypeID()
+  end
+end
diff --git a/aos/build/queues/output/queue_dec.rb b/aos/build/queues/output/queue_dec.rb
new file mode 100644
index 0000000..031c033
--- /dev/null
+++ b/aos/build/queues/output/queue_dec.rb
@@ -0,0 +1,89 @@
+class Target::QueueDec < Target::Node
+	attr_accessor :name,:loc
+	def initialize(type,name)
+		@type,@name = type,name
+	end
+	def msg_hash()
+		return @type.msg_hash
+	end
+	def full_message_name(cpp_tree)
+		type = cpp_tree.get(@type)
+		return @type.loc.to_cpp_id(type.name)
+	end
+	def full_builder_name(cpp_tree)
+		return "::aos::MessageBuilder< #{full_message_name(cpp_tree)}>"
+	end
+	def full_type_name(cpp_tree)
+		return "::aos::Queue< #{full_message_name(cpp_tree)}>"
+	end
+	def type_name(cpp_tree,queue_type = "::aos::Queue")
+		type = cpp_tree.get(@type)
+		if(@type.loc == @loc) #use relative name
+			return "#{queue_type}<#{type.name}>"
+		else #use full name
+			return "#{queue_type}< #{@type.loc.to_cpp_id(type.name)}>"
+		end
+	end
+	def create_usage(cpp_tree)
+		"#{type_name(cpp_tree)} #{@name}"
+	end
+	def create(cpp_tree)
+		namespace = cpp_tree.get(@loc)
+		type = cpp_tree.get(@type)
+		cpp_tree.set(self,self)
+		type_name = type_name(cpp_tree)
+		full_type_name = full_type_name(cpp_tree)
+		namespace.add_cc("static #{type_name} *#{@name}_ptr")
+		counter = "#{@name}_counter"
+		namespace.add_cc("static int #{counter}")
+
+		str = <<COMMENT_END
+Schwarz counter to construct and destruct the #{@name} queue.
+Must be constructed before &#{@name} is constructed so that #{@name}_ptr
+is valid so we can store a reference to the object.
+COMMENT_END
+		str.split(/\n/).each do |str_sec|
+			namespace.class_comment(str_sec)
+		end
+		init_class = namespace.add_class("InitializerFor_" + @name)
+
+		init_class.add_cc_comment(
+        "The counter is initialized at load-time, i.e., before any of the static",
+		"objects are initialized.")
+
+
+		cons = CPP::Constructor.new(init_class)
+		init_class.add_member(:public,cons)
+		cons.suite << if_stmt = CPP::If.new("0 == #{counter}++")
+
+		cons_call = CPP::FuncCall.new("new #{type_name}")
+		cons_call.args.push(@loc.queue_name(@name).inspect)
+		if_stmt.suite << CPP::Assign.new("#{@name}_ptr",cons_call)
+
+
+		destruct = CPP::Destructor.new(init_class)
+		init_class.add_member(:public,destruct)
+		destruct.suite << if_stmt = CPP::If.new("0 == --#{counter}")
+		if_stmt.suite << "delete #{@name}_ptr"
+		if_stmt.suite << CPP::Assign.new("#{@name}_ptr","NULL")
+
+		init_class.static = true
+		init_class.dec = @name + "_initializer";
+
+		str = <<COMMENT_END
+Create a reference to the new object in the pointer.  Since we have already
+created the initializer
+COMMENT_END
+		str.split(/\n/).map{|str_sec| CPP::Comment.new(str_sec)}.each do |comment|
+      namespace.add(comment)
+    end
+		namespace.add("static UNUSED_VARIABLE #{type_name} &#{@name}" +
+                  " = #{@name}_initializer.get()")
+
+		get = init_class.def_func(full_type_name,"get")
+		get.pre_func_types = "&"
+		get.suite << CPP::Return.new("*#{@name}_ptr")
+		
+	end
+end
+
diff --git a/aos/build/queues/print_field.rb b/aos/build/queues/print_field.rb
new file mode 100644
index 0000000..75cc1da
--- /dev/null
+++ b/aos/build/queues/print_field.rb
@@ -0,0 +1,91 @@
+require File.dirname(__FILE__) + '/load.rb'
+
+# TODO(brians): Special-case Time too and float/double if we can find a good way to do it.
+GenericTypeNames = ['float', 'double', 'char', '::aos::time::Time']
+IntegerSizes = [8, 16, 32, 64]
+
+WriteIffChanged.open(ARGV[0]) do |output|
+  output.puts <<END
+// This file is generated by #{File.expand_path(__FILE__)}.
+// DO NOT EDIT BY HAND!
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "aos/common/byteorder.h"
+#include "aos/common/time.h"
+#include "aos/common/print_field_helpers.h"
+#include "aos/common/logging/logging_printf_formats.h"
+
+namespace aos {
+
+bool PrintField(char *output, size_t *output_bytes, const void *input,
+                size_t *input_bytes, uint32_t type) {
+  switch (type) {
+#{GenericTypeNames.collect do |name|
+  message_element = Target::MessageElement.new(name, 'value')
+  statement = MessageElementStmt.new(name, 'value')
+  message_element.size = statement.size
+  print_args = []
+  message_element.fetchPrintArgs(print_args)
+  next <<END2
+    case #{message_element.getTypeID()}:
+      {
+        if (*input_bytes < #{statement.size}) return false;
+        *input_bytes -= #{statement.size};
+        #{name} value;
+        to_host(static_cast<const char *>(input), &value);
+        int ret = snprintf(output, *output_bytes,
+                           "#{statement.toPrintFormat()}",
+                           #{print_args[0]});
+        if (ret < 0) return false;
+        if (static_cast<unsigned int>(ret) >= *output_bytes) return false;
+        *output_bytes -= ret;
+        return true;
+      }
+END2
+end.join('')}
+#{IntegerSizes.collect do |size|
+  [true, false].collect do |signed|
+    size_bytes = size / 8
+    name = "#{signed ? '' : 'u'}int#{size}_t"
+    message_element = Target::MessageElement.new(name, 'value')
+    message_element.size = size_bytes
+    next <<END2
+    case #{message_element.getTypeID()}:
+      {
+        if (*input_bytes < #{size_bytes}) return false;
+        *input_bytes -= #{size_bytes};
+        #{name} value;
+        to_host(static_cast<const char *>(input), &value);
+        return PrintInteger<#{name}>(output, value, output_bytes);
+      }
+END2
+  end
+end.flatten.join('')}
+#{
+  message_element = Target::MessageElement.new('bool', 'value')
+  message_element.size = 1
+  r = <<END2
+    case #{message_element.getTypeID()}:
+      {
+        if (*input_bytes < 1) return false;
+        if (*output_bytes < 1) return false;
+        *input_bytes -= 1;
+        bool value = static_cast<const char *>(input)[0];
+        *output_bytes -= 1;
+        *output = value ? 'T' : 'f';
+        return true;
+      }
+END2
+}
+    default:
+      return false;
+  }
+}
+
+}  // namespace aos
+END
+end
diff --git a/aos/build/queues/q_specs/nested_structs.q b/aos/build/queues/q_specs/nested_structs.q
new file mode 100644
index 0000000..7162620
--- /dev/null
+++ b/aos/build/queues/q_specs/nested_structs.q
@@ -0,0 +1,12 @@
+package aos.test;
+
+import "q_specs/struct_test.q";
+
+
+message Position {
+	int32_t a;
+	int32_t[2] b;
+	.aos.test2.ClawHalfPosition top;
+	.aos.test2.ClawHalfPosition bottom;
+	bool c;
+};
diff --git a/aos/build/queues/q_specs/struct_queue_group.q b/aos/build/queues/q_specs/struct_queue_group.q
new file mode 100644
index 0000000..2bc5046
--- /dev/null
+++ b/aos/build/queues/q_specs/struct_queue_group.q
@@ -0,0 +1,20 @@
+package aos.test;
+
+struct Claw {
+	int32_t a;
+	int32_t b;
+};
+
+	message HPosition {
+		Claw top;
+	};
+
+// All angles here are 0 horizontal, positive up. 
+queue_group ClawGroup {
+
+	message Position {
+		Claw top;
+	};
+	queue Position kjks;
+};
+
diff --git a/aos/build/queues/q_specs/struct_test.q b/aos/build/queues/q_specs/struct_test.q
new file mode 100644
index 0000000..afb22ac
--- /dev/null
+++ b/aos/build/queues/q_specs/struct_test.q
@@ -0,0 +1,12 @@
+package aos.test2;
+
+struct SubStruct {
+	int32_t g;
+};
+
+struct ClawHalfPosition {
+	double position; 
+	bool hall_effect;
+	SubStruct clampy;
+};
+
diff --git a/aos/build/queues/queue_primitives.rb b/aos/build/queues/queue_primitives.rb
new file mode 100644
index 0000000..421c3b4
--- /dev/null
+++ b/aos/build/queues/queue_primitives.rb
@@ -0,0 +1,54 @@
+require File.dirname(__FILE__) + '/load.rb'
+
+require 'fileutils'
+
+TypeNames = [8, 16, 32, 64].collect do |size|
+  ["uint#{size}_t", "int#{size}_t"]
+end.flatten + ['bool', 'float', 'char', 'double', '::aos::time::Time']
+
+FileUtils.mkdir_p(File.dirname(ARGV[0]))
+WriteIffChanged.open(ARGV[0]) do |output|
+  output.puts <<END
+// This file is generated by #{File.expand_path(__FILE__)}.
+// DO NOT EDIT BY HAND!
+
+#include <stdint.h>
+
+#include "aos/common/time.h"
+
+namespace aos {
+namespace queue_primitive_types {
+#{TypeNames.collect do |name|
+  message_element = Target::MessageElement.new(name, 'value')
+  statement = MessageElementStmt.new(name, 'value')
+  message_element.size = statement.size
+  name = 'Time' if name == '::aos::time::Time'
+  next <<END2
+  static const uint32_t #{name}_p = #{message_element.getTypeID()};
+END2
+end.join('')}
+}  // namespace queue_primitive_types
+
+// A class for mapping an actual type to a type ID.
+// There are specializations for all of the actual primitive types.
+template<typename T>
+class TypeID {
+ public:
+  static const uint32_t id;
+};
+
+#{TypeNames.collect do |name|
+  message_element = Target::MessageElement.new(name, 'value')
+  statement = MessageElementStmt.new(name, 'value')
+  message_element.size = statement.size
+  next <<END2
+template<>
+class TypeID< #{name}> {
+ public:
+  static const uint32_t id = #{message_element.getTypeID()};
+};
+END2
+end.join('')}
+}  // namespace aos
+END
+end
diff --git a/aos/build/queues/write_iff_changed.rb b/aos/build/queues/write_iff_changed.rb
new file mode 100644
index 0000000..74373a9
--- /dev/null
+++ b/aos/build/queues/write_iff_changed.rb
@@ -0,0 +1,30 @@
+require 'tempfile'
+
+# Writes a file like normal except doesn't do anything if the new contents are
+# the same as what's already there. Useful for helping build tools not rebuild
+# if generated files are re-generated but don't change.
+# Usable as a standard File, including to redirect to with IO.popen etc.
+class WriteIffChanged < Tempfile
+  def initialize(filename)
+    super('write_iff_changed')
+    @filename = filename
+  end
+  def WriteIffChanged.open(filename)
+    out = WriteIffChanged.new(filename)
+    yield out
+    out.close
+  end
+  def close
+    flush
+    contents = File.open(path, 'r') do |f|
+      f.readlines(nil)
+    end
+    if !File.exists?(@filename) ||
+        File.new(@filename, 'r').readlines(nil) != contents
+      File.open(@filename, 'w') do |out|
+        out.write(contents[0])
+      end
+    end
+    super
+  end
+end
diff --git a/aos/build/strip_debuglink b/aos/build/strip_debuglink
new file mode 100755
index 0000000..fce95e6
--- /dev/null
+++ b/aos/build/strip_debuglink
@@ -0,0 +1,18 @@
+#!/bin/dash
+
+set -e
+
+OBJCOPY=$1
+shift
+
+# The arguments after any -o flags.
+OUTPUT=`echo "$@" | awk \
+  'BEGIN { RS=" " }; output { print ; output = 0 }; /-o/ { output = 1 }'`
+DEBUG_DIR=$(dirname $(dirname ${OUTPUT}))/unstripped_files
+mkdir -p ${DEBUG_DIR}
+DEBUG_FILE=${DEBUG_DIR}/$(basename ${OUTPUT}).full
+
+"$@"
+
+cp ${OUTPUT} ${DEBUG_FILE}
+${OBJCOPY} --strip-debug --add-gnu-debuglink=${DEBUG_FILE} ${OUTPUT}
diff --git a/aos/build/tools_config b/aos/build/tools_config
new file mode 100644
index 0000000..88931af
--- /dev/null
+++ b/aos/build/tools_config
@@ -0,0 +1,15 @@
+# This is a shell fragment that sets up variables related to where the tools
+# that download_externals.sh downloads so build.sh can use.
+# It also gets parsed by build.py, so it has to stay just variable assignments
+# and comments.
+
+EXTERNALS=${AOS}/../output/downloaded
+
+NINJA_RELEASE=v1.4.0
+NINJA_DIR=${EXTERNALS}/ninja-${NINJA_RELEASE}
+NINJA=${NINJA_DIR}/ninja
+
+# From chromium@154360:trunk/src/DEPS.
+GYP_REVISION=1738
+GYP_DIR=${EXTERNALS}/gyp-${GYP_REVISION}
+GYP=${GYP_DIR}/gyp
diff --git a/aos/common/actions/action_test.cc b/aos/common/actions/action_test.cc
new file mode 100644
index 0000000..1e94b32
--- /dev/null
+++ b/aos/common/actions/action_test.cc
@@ -0,0 +1,482 @@
+#include <unistd.h>
+
+#include <memory>
+#include <thread>
+
+#include "gtest/gtest.h"
+#include "aos/common/queue.h"
+#include "aos/common/queue_testutils.h"
+#include "aos/common/actions/actor.h"
+#include "aos/common/actions/actions.h"
+#include "aos/common/actions/actions.q.h"
+#include "aos/common/actions/test_action.q.h"
+#include "aos/common/event.h"
+
+using ::aos::time::Time;
+
+namespace aos {
+namespace common {
+namespace actions {
+namespace testing {
+
+class TestActorIndex
+    : public aos::common::actions::ActorBase<actions::TestActionQueueGroup> {
+ public:
+  explicit TestActorIndex(actions::TestActionQueueGroup *s)
+      : aos::common::actions::ActorBase<actions::TestActionQueueGroup>(s) {}
+
+  bool RunAction(const uint32_t &new_index) override {
+    index = new_index;
+    return true;
+  }
+
+  uint32_t index = 0;
+};
+
+::std::unique_ptr<
+    aos::common::actions::TypedAction<actions::TestActionQueueGroup>>
+MakeTestActionIndex(uint32_t index) {
+  return ::std::unique_ptr<
+      aos::common::actions::TypedAction<actions::TestActionQueueGroup>>(
+      new aos::common::actions::TypedAction<actions::TestActionQueueGroup>(
+          &actions::test_action, index));
+}
+
+class TestActorNOP
+    : public aos::common::actions::ActorBase<actions::TestActionQueueGroup> {
+ public:
+  explicit TestActorNOP(actions::TestActionQueueGroup *s)
+      : actions::ActorBase<actions::TestActionQueueGroup>(s) {}
+
+  bool RunAction(const uint32_t &) override { return true; }
+};
+
+::std::unique_ptr<
+    aos::common::actions::TypedAction<actions::TestActionQueueGroup>>
+MakeTestActionNOP() {
+  return MakeTestActionIndex(0);
+}
+
+class TestActorShouldCancel
+    : public aos::common::actions::ActorBase<actions::TestActionQueueGroup> {
+ public:
+  explicit TestActorShouldCancel(actions::TestActionQueueGroup *s)
+      : aos::common::actions::ActorBase<actions::TestActionQueueGroup>(s) {}
+
+  bool RunAction(const uint32_t &) override {
+    while (!ShouldCancel()) {
+      LOG(FATAL, "NOT CANCELED!!\n");
+    }
+    return true;
+  }
+};
+
+::std::unique_ptr<
+    aos::common::actions::TypedAction<actions::TestActionQueueGroup>>
+MakeTestActionShouldCancel() {
+  return MakeTestActionIndex(0);
+}
+
+class TestActor2Nop
+    : public aos::common::actions::ActorBase<actions::TestAction2QueueGroup> {
+ public:
+  explicit TestActor2Nop(actions::TestAction2QueueGroup *s)
+      : actions::ActorBase<actions::TestAction2QueueGroup>(s) {}
+
+  bool RunAction(const actions::MyParams &) { return true; }
+};
+
+::std::unique_ptr<
+    aos::common::actions::TypedAction<actions::TestAction2QueueGroup>>
+MakeTestAction2NOP(const actions::MyParams &params) {
+  return ::std::unique_ptr<
+      aos::common::actions::TypedAction<actions::TestAction2QueueGroup>>(
+      new aos::common::actions::TypedAction<actions::TestAction2QueueGroup>(
+          &actions::test_action2, params));
+}
+
+class ActionTest : public ::testing::Test {
+ protected:
+  ActionTest() {
+    // Flush the robot state queue so we can use clean shared memory for this.
+    // test.
+    actions::test_action.goal.Clear();
+    actions::test_action.status.Clear();
+    actions::test_action2.goal.Clear();
+    actions::test_action2.status.Clear();
+  }
+
+  virtual ~ActionTest() {
+    actions::test_action.goal.Clear();
+    actions::test_action.status.Clear();
+    actions::test_action2.goal.Clear();
+    actions::test_action2.status.Clear();
+  }
+
+  // Bring up and down Core.
+  ::aos::common::testing::GlobalCoreInstance my_core;
+  ::aos::common::actions::ActionQueue action_queue_;
+};
+
+// Tests that the the actions exist in a safe state at startup.
+TEST_F(ActionTest, DoesNothing) {
+  // Tick an empty queue and make sure it was not running.
+  EXPECT_FALSE(action_queue_.Running());
+  action_queue_.Tick();
+  EXPECT_FALSE(action_queue_.Running());
+}
+
+// Tests that starting with an old run message in the goal queue actually works.
+// This used to result in the client hanging, waiting for a response to its
+// cancel message.
+TEST_F(ActionTest, StartWithOldGoal) {
+  ASSERT_TRUE(actions::test_action.goal.MakeWithBuilder().run(971).Send());
+
+  TestActorNOP nop_act(&actions::test_action);
+
+  ASSERT_FALSE(actions::test_action.status.FetchLatest());
+  ::std::thread init_thread([&nop_act]() { nop_act.Initialize(); });
+  ::aos::time::SleepFor(::aos::time::Time::InSeconds(0.1));
+  ASSERT_TRUE(actions::test_action.goal.MakeWithBuilder().run(1).Send());
+  init_thread.join();
+  ASSERT_TRUE(actions::test_action.status.FetchLatest());
+  EXPECT_EQ(0u, actions::test_action.status->running);
+  EXPECT_EQ(0u, actions::test_action.status->last_running);
+
+  action_queue_.EnqueueAction(MakeTestActionNOP());
+  nop_act.WaitForActionRequest();
+
+  // We started an action and it should be running.
+  EXPECT_TRUE(action_queue_.Running());
+
+  action_queue_.CancelAllActions();
+  action_queue_.Tick();
+
+  EXPECT_TRUE(action_queue_.Running());
+
+  // Run the action so it can signal completion.
+  nop_act.RunIteration();
+  action_queue_.Tick();
+
+  // Make sure it stopped.
+  EXPECT_FALSE(action_queue_.Running());
+}
+
+// Tests that the queues are properly configured for testing. Tests that queues
+// work exactly as used in the tests.
+TEST_F(ActionTest, QueueCheck) {
+  actions::TestActionQueueGroup *send_side = &actions::test_action;
+  actions::TestActionQueueGroup *recv_side = &actions::test_action;
+
+  send_side->goal.MakeWithBuilder().run(1).Send();
+
+  EXPECT_TRUE(recv_side->goal.FetchLatest());
+  EXPECT_TRUE(recv_side->goal->run);
+
+  send_side->goal.MakeWithBuilder().run(0).Send();
+
+  EXPECT_TRUE(recv_side->goal.FetchLatest());
+  EXPECT_FALSE(recv_side->goal->run);
+
+  send_side->status.MakeWithBuilder().running(5).last_running(6).Send();
+
+  EXPECT_TRUE(recv_side->status.FetchLatest());
+  EXPECT_EQ(5, static_cast<int>(recv_side->status->running));
+  EXPECT_EQ(6, static_cast<int>(recv_side->status->last_running));
+}
+
+// Tests that an action starts and stops.
+TEST_F(ActionTest, ActionQueueWasRunning) {
+  TestActorNOP nop_act(&actions::test_action);
+
+  // Tick an empty queue and make sure it was not running.
+  action_queue_.Tick();
+  EXPECT_FALSE(action_queue_.Running());
+
+  action_queue_.EnqueueAction(MakeTestActionNOP());
+  nop_act.WaitForActionRequest();
+
+  // We started an action and it should be running.
+  EXPECT_TRUE(action_queue_.Running());
+
+  // Tick it and make sure it is still running.
+  action_queue_.Tick();
+  EXPECT_TRUE(action_queue_.Running());
+
+  // Run the action so it can signal completion.
+  nop_act.RunIteration();
+  action_queue_.Tick();
+
+  // Make sure it stopped.
+  EXPECT_FALSE(action_queue_.Running());
+}
+
+// Tests that we can cancel two actions and have them both stop.
+TEST_F(ActionTest, ActionQueueCancelAll) {
+  TestActorNOP nop_act(&actions::test_action);
+
+  // Tick an empty queue and make sure it was not running.
+  action_queue_.Tick();
+  EXPECT_FALSE(action_queue_.Running());
+
+  // Enqueue two actions to test both cancel. We can have an action and a next
+  // action so we want to test that.
+  action_queue_.EnqueueAction(MakeTestActionNOP());
+  action_queue_.EnqueueAction(MakeTestActionNOP());
+  nop_act.WaitForActionRequest();
+  action_queue_.Tick();
+
+  // Check that current and next exist.
+  EXPECT_TRUE(action_queue_.GetCurrentActionState(nullptr, nullptr, nullptr,
+                                                  nullptr, nullptr, nullptr));
+  EXPECT_TRUE(action_queue_.GetNextActionState(nullptr, nullptr, nullptr,
+                                               nullptr, nullptr, nullptr));
+
+  action_queue_.CancelAllActions();
+  action_queue_.Tick();
+
+  // It should still be running as the actor could not have signaled.
+  EXPECT_TRUE(action_queue_.Running());
+
+  bool sent_started, sent_cancel, interrupted;
+  EXPECT_TRUE(action_queue_.GetCurrentActionState(
+      nullptr, &sent_started, &sent_cancel, &interrupted, nullptr, nullptr));
+  EXPECT_TRUE(sent_started);
+  EXPECT_TRUE(sent_cancel);
+  EXPECT_FALSE(interrupted);
+
+  EXPECT_FALSE(action_queue_.GetNextActionState(nullptr, nullptr, nullptr,
+                                                nullptr, nullptr, nullptr));
+
+  // Run the action so it can signal completion.
+  nop_act.RunIteration();
+  action_queue_.Tick();
+
+  // Make sure it stopped.
+  EXPECT_FALSE(action_queue_.Running());
+}
+
+// Tests that an action that would block forever stops when canceled.
+TEST_F(ActionTest, ActionQueueCancelOne) {
+  TestActorShouldCancel cancel_act(&actions::test_action);
+
+  // Enqueue blocking action.
+  action_queue_.EnqueueAction(MakeTestActionShouldCancel());
+
+  cancel_act.WaitForActionRequest();
+  action_queue_.Tick();
+  EXPECT_TRUE(action_queue_.Running());
+
+  // Tell action to cancel.
+  action_queue_.CancelCurrentAction();
+  action_queue_.Tick();
+
+  // This will block forever on failure.
+  // TODO(ben): prolly a bad way to fail
+  cancel_act.RunIteration();
+  action_queue_.Tick();
+
+  // It should still be running as the actor could not have signalled.
+  EXPECT_FALSE(action_queue_.Running());
+}
+
+// Tests that an action starts and stops.
+TEST_F(ActionTest, ActionQueueTwoActions) {
+  TestActorNOP nop_act(&actions::test_action);
+
+  // Tick an empty queue and make sure it was not running.
+  action_queue_.Tick();
+  EXPECT_FALSE(action_queue_.Running());
+
+  // Enqueue action to be canceled.
+  action_queue_.EnqueueAction(MakeTestActionNOP());
+  nop_act.WaitForActionRequest();
+  action_queue_.Tick();
+
+  // Should still be running as the actor could not have signalled.
+  EXPECT_TRUE(action_queue_.Running());
+
+  // id for the first time run.
+  uint32_t nop_act_id = 0;
+  // Check the internal state and write down id for later use.
+  bool sent_started, sent_cancel, interrupted;
+  EXPECT_TRUE(action_queue_.GetCurrentActionState(nullptr, &sent_started,
+                                                  &sent_cancel, &interrupted,
+                                                  &nop_act_id, nullptr));
+  EXPECT_TRUE(sent_started);
+  EXPECT_FALSE(sent_cancel);
+  EXPECT_FALSE(interrupted);
+  ASSERT_NE(0u, nop_act_id);
+
+  // Add the next action which should ensure the first stopped.
+  action_queue_.EnqueueAction(MakeTestActionNOP());
+
+  // id for the second run.
+  uint32_t nop_act2_id = 0;
+  // Check the internal state and write down id for later use.
+  EXPECT_TRUE(action_queue_.GetNextActionState(nullptr, &sent_started,
+                                               &sent_cancel, &interrupted,
+                                               &nop_act2_id, nullptr));
+  EXPECT_NE(nop_act_id, nop_act2_id);
+  EXPECT_FALSE(sent_started);
+  EXPECT_FALSE(sent_cancel);
+  EXPECT_FALSE(interrupted);
+  ASSERT_NE(0u, nop_act2_id);
+
+  action_queue_.Tick();
+
+  // Run the action so it can signal completion.
+  nop_act.RunIteration();
+  action_queue_.Tick();
+  // Wait for the first id to finish, needed for the correct number of fetches.
+  nop_act.WaitForStop(nop_act_id);
+
+  // Start the next action on the actor side.
+  nop_act.WaitForActionRequest();
+
+  // Check the new action is the right one.
+  uint32_t test_id = 0;
+  EXPECT_TRUE(action_queue_.GetCurrentActionState(
+      nullptr, &sent_started, &sent_cancel, &interrupted, &test_id, nullptr));
+  EXPECT_TRUE(sent_started);
+  EXPECT_FALSE(sent_cancel);
+  EXPECT_FALSE(interrupted);
+  EXPECT_EQ(nop_act2_id, test_id);
+
+  // Make sure it is still going.
+  EXPECT_TRUE(action_queue_.Running());
+
+  // Run the next action so it can accomplish signal completion.
+  nop_act.RunIteration();
+  action_queue_.Tick();
+  nop_act.WaitForStop(nop_act_id);
+
+  // Make sure it stopped.
+  EXPECT_FALSE(action_queue_.Running());
+}
+
+// Tests that we do get an index with our goal
+TEST_F(ActionTest, ActionIndex) {
+  TestActorIndex idx_act(&actions::test_action);
+
+  // Tick an empty queue and make sure it was not running.
+  action_queue_.Tick();
+  EXPECT_FALSE(action_queue_.Running());
+
+  // Enqueue action to post index.
+  action_queue_.EnqueueAction(MakeTestActionIndex(5));
+  EXPECT_TRUE(actions::test_action.goal.FetchLatest());
+  EXPECT_EQ(5u, actions::test_action.goal->params);
+  EXPECT_EQ(0u, idx_act.index);
+
+  idx_act.WaitForActionRequest();
+  action_queue_.Tick();
+
+  // Check the new action is the right one.
+  uint32_t test_id = 0;
+  EXPECT_TRUE(action_queue_.GetCurrentActionState(nullptr, nullptr, nullptr,
+                                                  nullptr, &test_id, nullptr));
+
+  // Run the next action so it can accomplish signal completion.
+  idx_act.RunIteration();
+  action_queue_.Tick();
+  idx_act.WaitForStop(test_id);
+  EXPECT_EQ(5u, idx_act.index);
+
+  // Enqueue action to post index.
+  action_queue_.EnqueueAction(MakeTestActionIndex(3));
+  EXPECT_TRUE(actions::test_action.goal.FetchLatest());
+  EXPECT_EQ(3u, actions::test_action.goal->params);
+
+  // Run the next action so it can accomplish signal completion.
+  idx_act.RunIteration();
+  action_queue_.Tick();
+  idx_act.WaitForStop(test_id);
+  EXPECT_EQ(3u, idx_act.index);
+}
+
+// Tests that an action with a structure params works.
+TEST_F(ActionTest, StructParamType) {
+  TestActor2Nop nop_act(&actions::test_action2);
+
+  // Tick an empty queue and make sure it was not running.
+  action_queue_.Tick();
+  EXPECT_FALSE(action_queue_.Running());
+
+  actions::MyParams p;
+  p.param1 = 5.0;
+  p.param2 = 7;
+
+  action_queue_.EnqueueAction(MakeTestAction2NOP(p));
+  nop_act.WaitForActionRequest();
+
+  // We started an action and it should be running.
+  EXPECT_TRUE(action_queue_.Running());
+
+  // Tick it and make sure it is still running.
+  action_queue_.Tick();
+  EXPECT_TRUE(action_queue_.Running());
+
+  // Run the action so it can signal completion.
+  nop_act.RunIteration();
+  action_queue_.Tick();
+
+  // Make sure it stopped.
+  EXPECT_FALSE(action_queue_.Running());
+}
+
+// Tests that cancelling an action before the message confirming it started is
+// received works.
+// Situations like this used to lock the action queue up waiting for an action
+// to report that it successfully cancelled.
+// This situation is kind of a race condition, but it happens very consistently
+// when hitting buttons while the robot is in teleop-disabled. To hit the race
+// condition consistently in the test, there are a couple of Events inserted in
+// between various things running.
+TEST_F(ActionTest, CancelBeforeStart) {
+  Event thread_ready, ready_to_start, ready_to_stop;
+  ::std::thread action_thread(
+      [this, &thread_ready, &ready_to_start, &ready_to_stop]() {
+        TestActorNOP nop_act(&actions::test_action);
+        nop_act.Initialize();
+        thread_ready.Set();
+        ready_to_start.Wait();
+        nop_act.WaitForActionRequest();
+        LOG(DEBUG, "got a request to run\n");
+        const uint32_t running_id = nop_act.RunIteration();
+        LOG(DEBUG, "waiting for %" PRIx32 " to be stopped\n", running_id);
+        ready_to_stop.Set();
+        nop_act.WaitForStop(running_id);
+      });
+
+  action_queue_.CancelAllActions();
+  EXPECT_FALSE(action_queue_.Running());
+  thread_ready.Wait();
+  LOG(DEBUG, "starting action\n");
+  action_queue_.EnqueueAction(MakeTestActionNOP());
+  action_queue_.Tick();
+  action_queue_.CancelAllActions();
+  ready_to_start.Set();
+  LOG(DEBUG, "started action\n");
+  EXPECT_TRUE(action_queue_.Running());
+  ready_to_stop.Wait();
+  EXPECT_TRUE(action_queue_.Running());
+  LOG(DEBUG, "action is ready to stop\n");
+
+  action_queue_.Tick();
+  action_queue_.CancelAllActions();
+  EXPECT_FALSE(action_queue_.Running());
+  action_queue_.Tick();
+  action_queue_.CancelAllActions();
+  ASSERT_FALSE(action_queue_.Running());
+  action_thread.join();
+
+  action_queue_.Tick();
+  action_queue_.CancelAllActions();
+  ASSERT_FALSE(action_queue_.Running());
+}
+
+}  // namespace testing
+}  // namespace actions
+}  // namespace common
+}  // namespace aos
diff --git a/aos/common/actions/actions.cc b/aos/common/actions/actions.cc
new file mode 100644
index 0000000..ff3f386
--- /dev/null
+++ b/aos/common/actions/actions.cc
@@ -0,0 +1,75 @@
+#include "aos/common/actions/actions.h"
+
+namespace aos {
+namespace common {
+namespace actions {
+
+void ActionQueue::EnqueueAction(::std::unique_ptr<Action> action) {
+  if (current_action_) {
+    LOG(INFO, "Queueing action, canceling prior\n");
+    current_action_->Cancel();
+    next_action_ = ::std::move(action);
+  } else {
+    LOG(INFO, "Queueing action\n");
+    current_action_ = ::std::move(action);
+    current_action_->Start();
+  }
+}
+
+void ActionQueue::CancelCurrentAction() {
+  LOG(INFO, "Canceling current action\n");
+  if (current_action_) {
+    current_action_->Cancel();
+  }
+}
+
+void ActionQueue::CancelAllActions() {
+  LOG(DEBUG, "Cancelling all actions\n");
+  if (current_action_) {
+    current_action_->Cancel();
+  }
+  next_action_.reset();
+}
+
+void ActionQueue::Tick() {
+  if (current_action_) {
+    if (!current_action_->Running()) {
+      LOG(INFO, "Action is done.\n");
+      current_action_ = ::std::move(next_action_);
+      if (current_action_) {
+        LOG(INFO, "Running next action\n");
+        current_action_->Start();
+      }
+    }
+  }
+}
+
+bool ActionQueue::Running() { return static_cast<bool>(current_action_); }
+
+bool ActionQueue::GetCurrentActionState(bool* has_started, bool* sent_started,
+                                        bool* sent_cancel, bool* interrupted,
+                                        uint32_t* run_value,
+                                        uint32_t* old_run_value) {
+  if (current_action_) {
+    current_action_->GetState(has_started, sent_started, sent_cancel,
+                              interrupted, run_value, old_run_value);
+    return true;
+  }
+  return false;
+}
+
+bool ActionQueue::GetNextActionState(bool* has_started, bool* sent_started,
+                                     bool* sent_cancel, bool* interrupted,
+                                     uint32_t* run_value,
+                                     uint32_t* old_run_value) {
+  if (next_action_) {
+    next_action_->GetState(has_started, sent_started, sent_cancel, interrupted,
+                           run_value, old_run_value);
+    return true;
+  }
+  return false;
+}
+
+}  // namespace actions
+}  // namespace common
+}  // namespace aos
diff --git a/aos/common/actions/actions.gyp b/aos/common/actions/actions.gyp
new file mode 100644
index 0000000..69c9c7a
--- /dev/null
+++ b/aos/common/actions/actions.gyp
@@ -0,0 +1,71 @@
+{
+  'targets': [
+    {
+      'target_name': 'action_lib',
+      'type': 'static_library',
+      'sources': [
+        'actions.cc',
+        'actor.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/common.gyp:queues',
+        '<(AOS)/common/logging/logging.gyp:queue_logging',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+        '<(AOS)/common/util/util.gyp:phased_loop',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/common.gyp:queues',
+        '<(AOS)/common/logging/logging.gyp:queue_logging',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+        '<(AOS)/common/util/util.gyp:phased_loop',
+      ],
+    },
+    {
+      'target_name': 'action_queue',
+      'type': 'static_library',
+      'sources': ['actions.q'],
+      'variables': {
+        'header_path': 'aos/common/actions',
+      },
+      'includes': ['../../build/queues.gypi'],
+    },
+    {
+      'target_name': 'test_action_queue',
+      'type': 'static_library',
+      'sources': ['test_action.q'],
+      'variables': {
+        'header_path': 'aos/common/actions',
+      },
+      'dependencies': [
+        'action_queue',
+      ],
+      'export_dependent_settings': [
+        'action_queue',
+      ],
+      'includes': ['../../build/queues.gypi'],
+    },
+    {
+      'target_name': 'action_test',
+      'type': 'executable',
+      'sources': [
+        'action_test.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+        'action_lib',
+        'test_action_queue',
+        '<(AOS)/common/common.gyp:queue_testutils',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/logging/logging.gyp:queue_logging',
+        '<(AOS)/common/common.gyp:queues',
+        '<(AOS)/common/common.gyp:time',
+        'action_queue',
+        '<(AOS)/common/common.gyp:event',
+      ],
+    },
+  ],
+}
diff --git a/aos/common/actions/actions.h b/aos/common/actions/actions.h
new file mode 100644
index 0000000..fd88903
--- /dev/null
+++ b/aos/common/actions/actions.h
@@ -0,0 +1,358 @@
+#ifndef AOS_COMMON_ACTIONS_ACTIONS_H_
+#define AOS_COMMON_ACTIONS_ACTIONS_H_
+
+#include <inttypes.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <type_traits>
+#include <atomic>
+#include <memory>
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/queue.h"
+#include "aos/common/logging/queue_logging.h"
+
+namespace aos {
+namespace common {
+namespace actions {
+
+class Action;
+
+// A queue which queues Actions, verifies a single action is running, and
+// cancels Actions.
+class ActionQueue {
+ public:
+  // Queues up an action for sending.
+  void EnqueueAction(::std::unique_ptr<Action> action);
+
+  // Cancels the current action, and runs the next one after the current one has
+  // finished and the action queue ticks again.
+  void CancelCurrentAction();
+
+  // Cancels all running actions.
+  void CancelAllActions();
+
+  // Runs the next action when the current one is finished running and polls the
+  // running action state for use by Running.
+  void Tick();
+
+  // Returns true if any action is running or could be running.
+  bool Running();
+
+  // Retrieves the internal state of the current action for testing.
+  // See comments on the private members of TypedAction<T, S> for details.
+  bool GetCurrentActionState(bool* has_started, bool* sent_started,
+                             bool* sent_cancel, bool* interrupted,
+                             uint32_t* run_value, uint32_t* old_run_value);
+
+  // Retrieves the internal state of the next action for testing.
+  // See comments on the private members of TypedAction<T, S> for details.
+  bool GetNextActionState(bool* has_started, bool* sent_started,
+                          bool* sent_cancel, bool* interrupted,
+                          uint32_t* run_value, uint32_t* old_run_value);
+
+ private:
+  ::std::unique_ptr<Action> current_action_;
+  ::std::unique_ptr<Action> next_action_;
+};
+
+// The basic interface an ActionQueue can access.
+class Action {
+ public:
+  virtual ~Action() {}
+
+  // Cancels the action.
+  void Cancel() { DoCancel(); }
+  // Returns true if the action is currently running.
+  bool Running() { return DoRunning(); }
+  // Starts the action.
+  void Start() { DoStart(); }
+
+  // Waits until the action has finished.
+  void WaitUntilDone() { DoWaitUntilDone(); }
+
+  // Run all the checks for one iteration of waiting. Will return true when the
+  // action has completed, successfully or not. This is non-blocking.
+  bool CheckIteration() { return DoCheckIteration(false); }
+
+  // Retrieves the internal state of the action for testing.
+  // See comments on the private members of TypedAction<T, S> for details.
+  void GetState(bool* has_started, bool* sent_started, bool* sent_cancel,
+                bool* interrupted, uint32_t* run_value,
+                uint32_t* old_run_value) {
+    DoGetState(has_started, sent_started, sent_cancel, interrupted, run_value,
+               old_run_value);
+  }
+
+ private:
+  // Cancels the action.
+  virtual void DoCancel() = 0;
+  // Returns true if the action is running or we don't have an initial response
+  // back from it to signal whether or not it is running.
+  virtual bool DoRunning() = 0;
+  // Starts the action if a goal has been created.
+  virtual void DoStart() = 0;
+  // Blocks until complete.
+  virtual void DoWaitUntilDone() = 0;
+  // Updates status for one cycle of waiting
+  virtual bool DoCheckIteration(bool blocking) = 0;
+  // For testing we will need to get the internal state.
+  // See comments on the private members of TypedAction<T, S> for details.
+  virtual void DoGetState(bool* has_started, bool* sent_started,
+                          bool* sent_cancel, bool* interrupted,
+                          uint32_t* run_value, uint32_t* old_run_value) = 0;
+};
+
+// Templated subclass to hold the type information.
+template <typename T>
+class TypedAction : public Action {
+ public:
+  // A convenient way to refer to the type of our goals.
+  typedef typename std::remove_reference<decltype(
+      *(static_cast<T*>(nullptr)->goal.MakeMessage().get()))>::type GoalType;
+  typedef typename std::remove_reference<
+      decltype(static_cast<GoalType*>(nullptr)->params)>::type ParamType;
+
+  TypedAction(T* queue_group, const ParamType &params)
+      : queue_group_(queue_group),
+        goal_(queue_group_->goal.MakeMessage()),
+        // This adds 1 to the counter (atomically because it's potentially
+        // shared across threads) and then bitwise-ORs the bottom of the PID to
+        // differentiate it from other processes's values (ie a unique id).
+        run_value_(run_counter_.fetch_add(1, ::std::memory_order_relaxed) |
+                   ((getpid() & 0xFFFF) << 16)),
+        params_(params) {
+    LOG(INFO, "Action %" PRIx32 " created on queue %s\n", run_value_,
+        queue_group_->goal.name());
+    // Clear out any old status messages from before now.
+    queue_group_->status.FetchLatest();
+    if (queue_group_->status.get()) {
+      LOG_STRUCT(DEBUG, "have status", *queue_group_->status);
+    }
+  }
+
+  virtual ~TypedAction() {
+    LOG(DEBUG, "Calling destructor of %" PRIx32 "\n", run_value_);
+    DoCancel();
+  }
+
+  // Returns the current goal that will be sent when the action is sent.
+  GoalType* GetGoal() { return goal_.get(); }
+
+ private:
+  void DoCancel() override;
+
+  bool DoRunning() override;
+
+  void DoWaitUntilDone() override;
+
+  bool DoCheckIteration(bool blocking);
+
+  // Sets the started flag (also possibly the interrupted flag).
+  void CheckStarted();
+
+  // Checks for interrupt.
+  void CheckInterrupted();
+
+  void DoStart() override;
+
+  void DoGetState(bool* has_started, bool* sent_started, bool* sent_cancel,
+                  bool* interrupted, uint32_t* run_value,
+                  uint32_t* old_run_value) override {
+    if (has_started != nullptr) *has_started = has_started_;
+    if (sent_started != nullptr) *sent_started = sent_started_;
+    if (sent_cancel != nullptr) *sent_cancel = sent_cancel_;
+    if (interrupted != nullptr) *interrupted = interrupted_;
+    if (run_value != nullptr) *run_value = run_value_;
+    if (old_run_value != nullptr) *old_run_value = old_run_value_;
+  }
+
+  T* const queue_group_;
+  ::aos::ScopedMessagePtr<GoalType> goal_;
+
+  // Track if we have seen a response to the start message.
+  bool has_started_ = false;
+  // Track if we have sent an initial start message.
+  bool sent_started_ = false;
+
+  bool sent_cancel_ = false;
+
+  // Gets set to true if we ever see somebody else's value in running.
+  bool interrupted_ = false;
+
+  // The value we're going to use for goal.run etc.
+  const uint32_t run_value_;
+
+  // flag passed to action in order to have differing types
+  const ParamType params_;
+
+  // The old value for running that we may have seen. If we see any value other
+  // than this or run_value_, somebody else got in the way and we're done. 0 if
+  // there was nothing there to start with. Only valid after sent_started_
+  // changes to true.
+  uint32_t old_run_value_;
+
+  static ::std::atomic<uint16_t> run_counter_;
+};
+
+template <typename T>
+::std::atomic<uint16_t> TypedAction<T>::run_counter_{0};
+
+template <typename T>
+void TypedAction<T>::DoCancel() {
+  if (!sent_started_) {
+    LOG(INFO, "Action %" PRIx32 " on queue %s was never started\n", run_value_,
+        queue_group_->goal.name());
+  } else {
+    if (interrupted_) {
+      LOG(INFO,
+          "Action %" PRIx32 " on queue %s was interrupted -> not cancelling\n",
+          run_value_, queue_group_->goal.name());
+    } else {
+      if (sent_cancel_) {
+        LOG(INFO, "Action %" PRIx32 " on queue %s already cancelled\n",
+            run_value_, queue_group_->goal.name());
+      } else {
+        LOG(INFO, "Canceling action %" PRIx32 " on queue %s\n", run_value_,
+            queue_group_->goal.name());
+        queue_group_->goal.MakeWithBuilder().run(0).Send();
+        sent_cancel_ = true;
+      }
+    }
+  }
+}
+
+template <typename T>
+bool TypedAction<T>::DoRunning() {
+  if (!sent_started_) {
+    LOG(DEBUG, "haven't sent start message yet\n");
+    return false;
+  }
+  if (has_started_) {
+    queue_group_->status.FetchNext();
+    CheckInterrupted();
+  } else {
+    while (queue_group_->status.FetchNext()) {
+      LOG_STRUCT(DEBUG, "got status", *queue_group_->status);
+      CheckStarted();
+      if (has_started_) CheckInterrupted();
+    }
+  }
+  if (interrupted_) return false;
+  // We've asked it to start but haven't gotten confirmation that it's started
+  // yet.
+  if (!has_started_) return true;
+  return queue_group_->status.get() &&
+         queue_group_->status->running == run_value_;
+}
+
+template <typename T>
+void TypedAction<T>::DoWaitUntilDone() {
+  CHECK(sent_started_);
+  queue_group_->status.FetchNext();
+  LOG_STRUCT(DEBUG, "got status", *queue_group_->status);
+  CheckInterrupted();
+  while (true) {
+    if (DoCheckIteration(true)) {
+      return;
+    }
+  }
+}
+
+template <typename T>
+bool TypedAction<T>::DoCheckIteration(bool blocking) {
+  CHECK(sent_started_);
+  if (interrupted_) return true;
+  CheckStarted();
+  if (blocking) {
+    queue_group_->status.FetchNextBlocking();
+    LOG_STRUCT(DEBUG, "got status", *queue_group_->status);
+  } else {
+    if (!queue_group_->status.FetchNext()) {
+      return false;
+    }
+    LOG_STRUCT(DEBUG, "got status", *queue_group_->status);
+  }
+  CheckStarted();
+  CheckInterrupted();
+  if (has_started_ && (queue_group_->status.get() &&
+                       queue_group_->status->running != run_value_)) {
+    return true;
+  }
+  return false;
+}
+
+template <typename T>
+void TypedAction<T>::CheckStarted() {
+  if (has_started_) return;
+  if (queue_group_->status.get()) {
+    if (queue_group_->status->running == run_value_ ||
+        (queue_group_->status->running == 0 &&
+         queue_group_->status->last_running == run_value_)) {
+      // It's currently running our instance.
+      has_started_ = true;
+      LOG(INFO, "Action %" PRIx32 " on queue %s has been started\n",
+          run_value_, queue_group_->goal.name());
+    } else if (old_run_value_ != 0 &&
+               queue_group_->status->running == old_run_value_) {
+      LOG(DEBUG, "still running old instance %" PRIx32 "\n", old_run_value_);
+    } else {
+      LOG(WARNING, "Action %" PRIx32 " on queue %s interrupted by %" PRIx32
+                   " before starting\n",
+          run_value_, queue_group_->goal.name(), queue_group_->status->running);
+      has_started_ = true;
+      interrupted_ = true;
+    }
+  } else {
+    LOG(WARNING, "No status message recieved.\n");
+  }
+}
+
+template <typename T>
+void TypedAction<T>::CheckInterrupted() {
+  if (!interrupted_ && has_started_ && queue_group_->status.get()) {
+    if (queue_group_->status->running != 0 &&
+        queue_group_->status->running != run_value_) {
+      LOG(WARNING, "Action %" PRIx32 " on queue %s interrupted by %" PRIx32
+                   " after starting\n",
+          run_value_, queue_group_->goal.name(), queue_group_->status->running);
+    }
+  }
+}
+
+template <typename T>
+void TypedAction<T>::DoStart() {
+  if (goal_) {
+    LOG(INFO, "Starting action %" PRIx32 "\n", run_value_);
+    goal_->run = run_value_;
+    goal_->params = params_;
+    sent_started_ = true;
+    if (!goal_.Send()) {
+      LOG(ERROR, "sending goal for action %" PRIx32 " on queue %s failed\n",
+          run_value_, queue_group_->goal.name());
+      // Don't wait to see a message with it.
+      has_started_ = true;
+    }
+    queue_group_->status.FetchNext();
+    if (queue_group_->status.get()) {
+      LOG_STRUCT(DEBUG, "got status", *queue_group_->status);
+    }
+    if (queue_group_->status.get() && queue_group_->status->running != 0) {
+      old_run_value_ = queue_group_->status->running;
+      LOG(INFO, "Action %" PRIx32 " on queue %s already running\n",
+          old_run_value_, queue_group_->goal.name());
+    } else {
+      old_run_value_ = 0;
+    }
+  } else {
+    LOG(WARNING, "Action %" PRIx32 " on queue %s already started\n", run_value_,
+        queue_group_->goal.name());
+  }
+}
+
+}  // namespace actions
+}  // namespace common
+}  // namespace aos
+
+#endif  // AOS_COMMON_ACTIONS_ACTIONS_H_
diff --git a/aos/common/actions/actions.q b/aos/common/actions/actions.q
new file mode 100644
index 0000000..e3046c9
--- /dev/null
+++ b/aos/common/actions/actions.q
@@ -0,0 +1,35 @@
+package aos.common.actions;
+
+interface StatusInterface {
+  // 0 if the action isn't running or the value from goal.run.
+  uint32_t running;
+};
+
+interface GoalInterface {
+  // 0 to stop or an arbitrary value to put in status.running.
+  uint32_t run;
+};
+
+message Status {
+  // The run value of the instance we're currently running or 0.
+  uint32_t running;
+  // A run value we were previously running or 0.
+  uint32_t last_running;
+  // If false the action failed to complete and may be in a bad state,
+  // this is a critical problem not a cancellation.
+  bool success;
+};
+
+message Goal {
+  // The unique value to put into status.running while running this instance or
+  // 0 to cancel.
+  uint32_t run;
+  // Default parameter.  The more useful thing to do would be to define your own
+  // goal type to change param to a useful structure.
+  double params;
+};
+
+interface ActionQueueGroup {
+  queue Status status;
+  queue Goal goal;
+};
diff --git a/aos/common/actions/actor.cc b/aos/common/actions/actor.cc
new file mode 100644
index 0000000..6c6bef7
--- /dev/null
+++ b/aos/common/actions/actor.cc
@@ -0,0 +1,9 @@
+#include "aos/common/actions/actor.h"
+
+namespace aos {
+namespace common {
+namespace actions {
+
+}  // namespace actions
+}  // namespace common
+}  // namespace aos
diff --git a/aos/common/actions/actor.h b/aos/common/actions/actor.h
new file mode 100644
index 0000000..b3a0220
--- /dev/null
+++ b/aos/common/actions/actor.h
@@ -0,0 +1,247 @@
+#ifndef AOS_COMMON_ACTIONS_ACTOR_H_
+#define AOS_COMMON_ACTIONS_ACTOR_H_
+
+#include <stdio.h>
+#include <inttypes.h>
+
+#include <functional>
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/logging/queue_logging.h"
+#include "aos/common/time.h"
+#include "aos/common/controls/control_loop.h"
+#include "aos/common/util/phased_loop.h"
+
+namespace aos {
+namespace common {
+namespace actions {
+
+template <class T>
+class ActorBase {
+ public:
+  typedef typename std::remove_reference<decltype(
+      *(static_cast<T*>(nullptr)->goal.MakeMessage().get()))>::type GoalType;
+  typedef typename std::remove_reference<
+      decltype(static_cast<GoalType*>(nullptr)->params)>::type ParamType;
+
+  ActorBase(T* acq) : action_q_(acq) {}
+
+  // Will return true if finished or asked to cancel.
+  // Will return false if it failed accomplish its goal
+  // due to a problem with the system.
+  virtual bool RunAction(const ParamType& params) = 0;
+
+  // Runs action while enabled.
+  void Run();
+
+  // Gets ready to run actions.
+  void Initialize();
+
+  // Checks if an action was initially running when the thread started.
+  bool CheckInitialRunning();
+
+  // Wait here until someone asks us to go.
+  void WaitForActionRequest();
+
+  // Do work son.
+  uint32_t RunIteration();
+
+  // Wait for stop is signalled.
+  void WaitForStop(uint32_t running_id);
+
+  // Will run until the done condition is met or times out.
+  // Will return false if successful or end_time is reached and true if the
+  // action was canceled or failed.
+  // Done condition are defined as functions that return true when done and have
+  // some sort of blocking statement (such as FetchNextBlocking) to throttle
+  // spin rate.
+  // end_time is when to stop and return true. Time(0, 0) (the default) means
+  // never time out.
+  bool WaitUntil(::std::function<bool(void)> done_condition,
+                 const ::aos::time::Time& end_time = ::aos::time::Time(0, 0));
+
+  // Waits for a certain amount of time from when this method is called.
+  // Returns false if the action was canceled or failed, and true if the wait
+  // succeeded.
+  bool WaitOrCancel(const ::aos::time::Time& duration) {
+    return !WaitUntil([]() {
+                        ::aos::time::PhasedLoopXMS(
+                            ::aos::controls::kLoopFrequency.ToMSec(), 2500);
+                        return false;
+                      },
+                      ::aos::time::Time::Now() + duration);
+  }
+
+  // Returns true if the action should be canceled.
+  bool ShouldCancel();
+
+ protected:
+  // Set to true when we should stop ASAP.
+  bool abort_ = false;
+
+  // The queue for this action.
+  T* action_q_;
+};
+
+template <class T>
+bool ActorBase<T>::CheckInitialRunning() {
+  LOG(DEBUG, "Waiting for input to start\n");
+
+  if (action_q_->goal.FetchLatest()) {
+    LOG_STRUCT(DEBUG, "goal queue", *action_q_->goal);
+    const uint32_t initially_running = action_q_->goal->run;
+    if (initially_running != 0) {
+      while (action_q_->goal->run == initially_running) {
+        LOG(INFO, "run is still %" PRIx32 "\n", initially_running);
+        action_q_->goal.FetchNextBlocking();
+        LOG_STRUCT(DEBUG, "goal queue", *action_q_->goal);
+      }
+    }
+    LOG(DEBUG, "Done waiting, goal\n");
+    return true;
+  }
+  LOG(DEBUG, "Done waiting, no goal\n");
+  return false;
+}
+
+template <class T>
+void ActorBase<T>::WaitForActionRequest() {
+  while (action_q_->goal.get() == nullptr || !action_q_->goal->run) {
+    LOG(INFO, "Waiting for an action request.\n");
+    action_q_->goal.FetchNextBlocking();
+    LOG_STRUCT(DEBUG, "goal queue", *action_q_->goal);
+    if (!action_q_->goal->run) {
+      if (!action_q_->status.MakeWithBuilder()
+               .running(0)
+               .last_running(0)
+               .success(!abort_)
+               .Send()) {
+        LOG(ERROR, "Failed to send the status.\n");
+      }
+    }
+  }
+}
+
+template <class T>
+uint32_t ActorBase<T>::RunIteration() {
+  CHECK(action_q_->goal.get() != nullptr);
+  const uint32_t running_id = action_q_->goal->run;
+  LOG(INFO, "Starting action %" PRIx32 "\n", running_id);
+  if (!action_q_->status.MakeWithBuilder()
+           .running(running_id)
+           .last_running(0)
+           .success(!abort_)
+           .Send()) {
+    LOG(ERROR, "Failed to send the status.\n");
+  }
+  LOG_STRUCT(INFO, "goal", *action_q_->goal);
+  abort_ = !RunAction(action_q_->goal->params);
+  LOG(INFO, "Done with action %" PRIx32 "\n", running_id);
+
+  // If we have a new one to run, we shouldn't say we're stopped in between.
+  if (action_q_->goal->run == 0 || action_q_->goal->run == running_id) {
+    if (!action_q_->status.MakeWithBuilder()
+             .running(0)
+             .last_running(running_id)
+             .success(!abort_)
+             .Send()) {
+      LOG(ERROR, "Failed to send the status.\n");
+    } else {
+      LOG(INFO, "Sending Done status %" PRIx32 "\n", running_id);
+    }
+  } else {
+    LOG(INFO, "skipping sending stopped status for %" PRIx32 "\n", running_id);
+  }
+
+  return running_id;
+}
+
+template <class T>
+void ActorBase<T>::WaitForStop(uint32_t running_id) {
+  assert(action_q_->goal.get() != nullptr);
+  while (action_q_->goal->run == running_id) {
+    LOG(INFO, "Waiting for the action (%" PRIx32 ") to be stopped.\n",
+        running_id);
+    action_q_->goal.FetchNextBlocking();
+    LOG_STRUCT(DEBUG, "goal queue", *action_q_->goal);
+  }
+}
+
+template <class T>
+void ActorBase<T>::Run() {
+  Initialize();
+
+  while (true) {
+    // Wait for a request to come in before starting.
+    WaitForActionRequest();
+
+    LOG_STRUCT(INFO, "running with goal", *action_q_->goal);
+
+    // Perform the action once.
+    uint32_t running_id = RunIteration();
+
+    LOG(INFO, "done running\n");
+
+    // Don't start again until asked.
+    WaitForStop(running_id);
+    LOG(DEBUG, "action %" PRIx32 " was stopped\n", running_id);
+  }
+}
+
+template <class T>
+void ActorBase<T>::Initialize() {
+  // Make sure the last job is done and we have a signal.
+  if (CheckInitialRunning()) {
+    LOG(DEBUG, "action %" PRIx32 " was stopped\n", action_q_->goal->run);
+  }
+
+  if (!action_q_->status.MakeWithBuilder()
+           .running(0)
+           .last_running(0)
+           .success(!abort_)
+           .Send()) {
+    LOG(ERROR, "Failed to send the status.\n");
+  }
+}
+
+template <class T>
+bool ActorBase<T>::WaitUntil(::std::function<bool(void)> done_condition,
+                             const ::aos::time::Time& end_time) {
+  while (!done_condition()) {
+    if (ShouldCancel() || abort_) {
+      // Clear abort bit as we have just aborted.
+      abort_ = false;
+      return true;
+    }
+    if (end_time != ::aos::time::Time(0, 0) &&
+        ::aos::time::Time::Now() >= end_time) {
+      LOG(DEBUG, "WaitUntil timed out\n");
+      return false;
+    }
+  }
+  if (ShouldCancel() || abort_) {
+    // Clear abort bit as we have just aborted.
+    abort_ = false;
+    return true;
+  } else {
+    return false;
+  }
+}
+
+template <class T>
+bool ActorBase<T>::ShouldCancel() {
+  if (action_q_->goal.FetchNext()) {
+    LOG_STRUCT(DEBUG, "goal queue", *action_q_->goal);
+  }
+  bool ans = !action_q_->goal->run;
+  if (ans) {
+    LOG(INFO, "Time to stop action\n");
+  }
+  return ans;
+}
+
+}  // namespace actions
+}  // namespace common
+}  // namespace aos
+
+#endif  // AOS_COMMON_ACTIONS_ACTOR_H_
diff --git a/aos/common/actions/test_action.q b/aos/common/actions/test_action.q
new file mode 100644
index 0000000..3451c04
--- /dev/null
+++ b/aos/common/actions/test_action.q
@@ -0,0 +1,35 @@
+package aos.common.actions;
+
+import "aos/common/actions/actions.q";
+
+queue_group TestActionQueueGroup {
+  implements aos.common.actions.ActionQueueGroup;
+
+  message Goal {
+    uint32_t run;
+    uint32_t params;
+  };
+
+  queue Goal goal;
+  queue aos.common.actions.Status status;
+};
+
+struct MyParams {
+  double param1;
+  int32_t param2;
+};
+
+queue_group TestAction2QueueGroup {
+  implements aos.common.actions.ActionQueueGroup;
+
+  message Goal {
+    uint32_t run;
+    MyParams params;
+  };
+
+  queue Goal goal;
+  queue aos.common.actions.Status status;
+};
+
+queue_group TestActionQueueGroup test_action;
+queue_group TestAction2QueueGroup test_action2;
diff --git a/aos/common/byteorder.h b/aos/common/byteorder.h
new file mode 100644
index 0000000..ae6ecf4
--- /dev/null
+++ b/aos/common/byteorder.h
@@ -0,0 +1,201 @@
+#ifndef AOS_COMMON_BYTEORDER_H_
+#define AOS_COMMON_BYTEORDER_H_
+
+#ifndef __VXWORKS__
+#include <endian.h> // endian(3)
+#endif
+#include <string.h>
+#include <stdint.h>
+
+// Contains functions for converting between host and network byte order for
+// things other than 16/32 bit integers (those are provided by byteorder(3)).
+// Also gives a nice templated interface to these functions.
+
+namespace aos {
+namespace {
+
+template <typename int_type, int_type (*function)(int_type)>
+static inline void copier(const void *in, void *out) {
+  // Have confirmed by looking at the assembly code that this generates the same
+  // code as the (undefined by the c++ standard) way of using a union to do it.
+  // (which is pretty efficient)
+  int_type temp;
+  memcpy(&temp, in, sizeof(int_type));
+  temp = function(temp);
+  memcpy(out, &temp, sizeof(int_type));
+}
+template <typename int_type, typename T, int_type (*function)(int_type)>
+static inline T memcpier(T in) {
+  copier<int_type, function>(&in, &in);
+  return in;
+}
+
+// Needed because be64toh etc are macros (not that the manpage says
+// anything...).
+// These are used instead of ntohs etc because gcc didn't inline those.
+#ifdef __clang__
+// Apparently the macros use "register", and clang doesn't like that.
+#define register
+#endif
+static inline uint64_t _be64toh(uint64_t in) { return be64toh(in); }
+static inline uint64_t _htobe64(uint64_t in) { return htobe64(in); }
+static inline uint32_t _be32toh(uint32_t in) { return be32toh(in); }
+static inline uint32_t _htobe32(uint32_t in) { return htobe32(in); }
+static inline uint16_t _be16toh(uint16_t in) { return be16toh(in); }
+static inline uint16_t _htobe16(uint16_t in) { return htobe16(in); }
+#ifdef __clang__
+#undef register
+#endif
+
+template<int bytes, typename T> class do_ntoh {
+ public:
+  static inline T apply(T net);
+  static inline void copy(const char *in, T &net);
+};
+template<typename T> class do_ntoh<1, T> {
+ public:
+  static inline T apply(T net) { return net; }
+  static inline void copy(const char *in, T *host) { host[0] = in[0]; }
+};
+template<typename T> class do_ntoh<2, T> {
+ public:
+  static inline T apply(T net) { return memcpier<uint16_t, T, _be16toh>(net); }
+  static inline void copy(const char *in, T *host) {
+    copier<uint16_t, _be16toh>(in, host);
+  }
+};
+template<typename T> class do_ntoh<4, T> {
+ public:
+  static inline T apply(T net) { return memcpier<uint32_t, T, _be32toh>(net); }
+  static inline void copy(const char *in, T *host) {
+    copier<uint32_t, _be32toh>(in, host);
+  }
+};
+template<typename T> class do_ntoh<8, T> {
+ public:
+  static inline T apply(T net) { return memcpier<uint64_t, T, _be64toh>(net); }
+  static inline void copy(const char *in, T *host) {
+    copier<uint64_t, _be64toh>(in, host);
+  }
+};
+
+template <size_t Size>
+struct do_ntoh_int {
+  static inline void copy(const char *in, char *host);
+};
+template <>
+struct do_ntoh_int<1> {
+  static inline void copy(const char *in, char *host) { host[0] = in[0]; }
+};
+template <>
+struct do_ntoh_int<2> {
+  static inline void copy(const char *in, char *host) {
+    copier<uint16_t, _be16toh>(in, host);
+  }
+};
+template <>
+struct do_ntoh_int<4> {
+  static inline void copy(const char *in, char *host) {
+    copier<uint32_t, _be32toh>(in, host);
+  }
+};
+template <>
+struct do_ntoh_int<8> {
+  static inline void copy(const char *in, char *host) {
+    copier<uint64_t, _be64toh>(in, host);
+  }
+};
+
+template<int bytes, typename T> class do_hton {
+ public:
+  static inline T apply(T host);
+  static inline void copy(const T *host, char *out);
+};
+template<typename T> class do_hton<1, T> {
+ public:
+  static inline T apply(T host) { return host; }
+  static inline void copy(const T *host, char *out) { out[0] = host[0]; }
+};
+template<typename T> class do_hton<2, T> {
+ public:
+  static inline T apply(T host) { return memcpier<uint16_t, T, _htobe16>(host); }
+  static inline void copy(const T *host, char *out) {
+    copier<uint16_t, _htobe16>(host, out);
+  }
+};
+template<typename T> class do_hton<4, T> {
+ public:
+  static inline T apply(T host) { return memcpier<uint32_t, T, _htobe32>(host); }
+  static inline void copy(const T *host, char *out) {
+    copier<uint32_t, _htobe32>(host, out);
+  }
+};
+template<typename T> class do_hton<8, T> {
+ public:
+  static inline T apply(T host) { return memcpier<uint64_t, T, _htobe64>(host); }
+  static inline void copy(const T *host, char *out) {
+    copier<uint64_t, _htobe64>(host, out);
+  }
+};
+
+template <size_t Size>
+struct do_hton_int {
+  static inline void copy(const char *host, char *out);
+};
+template <>
+struct do_hton_int<1> {
+  static inline void copy(const char *host, char *out) { out[0] = host[0]; }
+};
+template <>
+struct do_hton_int<2> {
+  static inline void copy(const char *host, char *out) {
+    copier<uint16_t, _htobe16>(host, out);
+  }
+};
+template <>
+struct do_hton_int<4> {
+  static inline void copy(const char *host, char *out) {
+    copier<uint32_t, _htobe32>(host, out);
+  }
+};
+template <>
+struct do_hton_int<8> {
+  static inline void copy(const char *host, char *out) {
+    copier<uint64_t, _htobe64>(host, out);
+  }
+};
+
+}  // namespace
+
+// Converts T from network to host byte order.
+template <typename T>
+static inline T ntoh(T net) {
+  return do_ntoh<sizeof(net), T>::apply(net);
+}
+// Converts T from host to network byte order.
+template <typename T>
+static inline T hton(T host) {
+  return do_hton<sizeof(host), T>::apply(host);
+}
+
+template <typename T>
+static inline void to_host(const char *input, T *host) {
+  do_ntoh<sizeof(*host), T>::copy(input, host);
+}
+template <typename T>
+static inline void to_network(const T *host, char *output) {
+  do_hton<sizeof(*host), T>::copy(host, output);
+}
+
+template <size_t Size>
+static inline void to_host(const char *input, char *host) {
+  do_ntoh_int<Size>::copy(input, host);
+}
+template <size_t Size>
+static inline void to_network(const char *host, char *output) {
+  do_hton_int<Size>::copy(host, output);
+}
+
+} // namespace aos
+
+#endif
diff --git a/aos/common/common.gyp b/aos/common/common.gyp
new file mode 100644
index 0000000..461200e
--- /dev/null
+++ b/aos/common/common.gyp
@@ -0,0 +1,370 @@
+{
+  'targets': [
+    {
+      'target_name': 'test_queue',
+      'type': 'static_library',
+      'sources': [
+        '<(AOS)/common/test_queue.q',
+      ],
+      'variables': {
+        'header_path': 'aos/common',
+      },
+      'includes': ['../build/queues.gypi'],
+    },
+    {
+      'target_name': 'queue_testutils',
+      'type': 'static_library',
+      'sources': [
+        'queue_testutils.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/build/aos.gyp:logging',
+        'once',
+        '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:shared_mem',
+        'mutex',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:shared_mem',
+       ],
+    },
+    {
+      'target_name': 'time',
+      'type': 'static_library',
+      'sources': [
+        'time.cc'
+      ],
+      'dependencies': [
+        '<(AOS)/build/aos.gyp:logging_interface',
+        'mutex',
+      ],
+    },
+    {
+      'target_name': 'queue_types',
+      'type': 'static_library',
+      'variables': {
+        'print_field_cc': '<(SHARED_INTERMEDIATE_DIR)/print_field.cc',
+        'queue_primitives_h': '<(SHARED_INTERMEDIATE_DIR)/aos_queue_primitives/aos/queue_primitives.h',
+      },
+      'sources': [
+        'queue_types.cc',
+        '<(print_field_cc)',
+      ],
+      'dependencies': [
+        '<(AOS)/build/aos.gyp:logging_interface',
+        '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:shared_mem',
+        '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:core_lib',
+        'mutex',
+        'time',
+      ],
+      'export_dependent_settings': [
+        'time',
+      ],
+      'actions': [
+        {
+          'variables': {
+            'script': '<(AOS)/build/queues/print_field.rb',
+          },
+          'action_name': 'gen_print_field',
+          'inputs': [
+            '<(script)',
+            '<!@(find <(AOS)/build/queues/ -name *.rb)',
+          ],
+          'outputs': [
+            '<(print_field_cc)',
+          ],
+          'action': ['ruby', '<(script)', '<(print_field_cc)'],
+          'message': 'Generating print_field.cc',
+        },
+        {
+          'variables': {
+            'script': '<(AOS)/build/queues/queue_primitives.rb',
+          },
+          'action_name': 'gen_queue_primitives',
+          'inputs': [
+            '<(script)',
+            '<!@(find <(AOS)/build/queues/ -name *.rb)',
+          ],
+          'outputs': [
+            '<(queue_primitives_h)',
+          ],
+          'action': ['ruby', '<(script)', '<(queue_primitives_h)'],
+          'message': 'Generating queue_primitives.h',
+        },
+      ],
+      'direct_dependent_settings': {
+        'include_dirs': [
+          '<(SHARED_INTERMEDIATE_DIR)/aos_queue_primitives',
+        ],
+      },
+      'hard_dependency': 1,
+    },
+    {
+      'target_name': 'queue_types_test',
+      'type': 'executable',
+      'sources': [
+        'queue_types_test.cc',
+      ],
+      'dependencies': [
+        'queue_types',
+        '<(EXTERNALS):gtest',
+        'test_queue',
+        '<(AOS)/build/aos.gyp:logging',
+        'queue_testutils',
+      ],
+    },
+    {
+      'target_name': 'queues',
+      'type': 'static_library',
+      'sources': [
+        'queue.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:queue',
+        'time',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:queue',
+        'time',
+      ],
+    },
+    {
+      'target_name': 'scoped_fd',
+      'type': 'static_library',
+      'sources': [
+        # 'scoped_fd.h'
+      ],
+      'dependencies': [
+        '<(AOS)/build/aos.gyp:logging',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/build/aos.gyp:logging',
+      ],
+    },
+    {
+      'target_name': 'queue_test',
+      'type': 'executable',
+      'sources': [
+        'queue_test.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+        'queue_testutils',
+        'test_queue',
+        '<(AOS)/common/util/util.gyp:thread',
+        'die',
+      ],
+    },
+    {
+      'target_name': 'type_traits_test',
+      'type': 'executable',
+      'sources': [
+        'type_traits_test.cpp',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+      ],
+    },
+    {
+      'target_name': 'gtest_prod',
+      'type': 'static_library',
+      'dependencies': [
+        '<(EXTERNALS):gtest_prod',
+      ],
+      'export_dependent_settings': [
+        '<(EXTERNALS):gtest_prod',
+      ],
+    },
+    {
+      'target_name': 'once',
+      'type': 'static_library',
+      'dependencies': [
+        '<(EXTERNALS):gtest_prod',
+      ],
+      'export_dependent_settings': [
+        '<(EXTERNALS):gtest_prod',
+      ],
+    },
+    {
+      'target_name': 'once_test',
+      'type': 'executable',
+      'sources': [
+        'once_test.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+        'once',
+      ],
+    },
+    {
+      'target_name': 'time_test',
+      'type': 'executable',
+      'sources': [
+        'time_test.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+        'time',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/util/util.gyp:death_test_log_implementation',
+      ],
+    },
+    {
+      'target_name': 'die',
+      'type': 'static_library',
+      'sources': [
+        'die.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/common/libc/libc.gyp:aos_strerror',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/libc/libc.gyp:aos_strerror',
+      ],
+    },
+    {
+      'target_name': 'condition',
+      'type': 'static_library',
+      'sources': [
+        '<(AOS)/linux_code/ipc_lib/condition.cc',
+      ],
+      'dependencies': [
+        'mutex',
+        '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:aos_sync',
+        '<(AOS)/build/aos.gyp:logging_interface',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:aos_sync',
+      ],
+    },
+    {
+      'target_name': 'mutex',
+      'type': 'static_library',
+      'sources': [
+        '<(AOS)/linux_code/ipc_lib/mutex.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:aos_sync',
+        '<(AOS)/build/aos.gyp:logging_interface',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:aos_sync',
+      ],
+    },
+    {
+      'target_name': 'event',
+      'type': 'static_library',
+      'sources': [
+        '<(AOS)/linux_code/ipc_lib/event.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:aos_sync',
+        '<(AOS)/build/aos.gyp:logging_interface',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:aos_sync',
+      ],
+    },
+    {
+      'target_name': 'queue_testutils_test',
+      'type': 'executable',
+      'sources': [
+        'queue_testutils_test.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+        'queue_testutils',
+        '<(AOS)/build/aos.gyp:logging',
+      ],
+    },
+    {
+      'target_name': 'mutex_test',
+      'type': 'executable',
+      'sources': [
+        'mutex_test.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+        'mutex',
+        'die',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/util/util.gyp:death_test_log_implementation',
+        '<(AOS)/common/util/util.gyp:thread',
+        '<(AOS)/common/common.gyp:time',
+        'queue_testutils',
+      ],
+    },
+    {
+      'target_name': 'event_test',
+      'type': 'executable',
+      'sources': [
+        'event_test.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+        'event',
+        'queue_testutils',
+        'time',
+      ],
+    },
+    {
+      'target_name': 'condition_test',
+      'type': 'executable',
+      'sources': [
+        'condition_test.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+        'condition',
+        '<(AOS)/common/util/util.gyp:thread',
+        'time',
+        'mutex',
+        '<(AOS)/build/aos.gyp:logging',
+        'queue_testutils',
+        '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:core_lib',
+        '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:aos_sync',
+        'die',
+        '<(AOS)/common/util/util.gyp:thread',
+       ],
+    },
+    {
+      'target_name': 'die_test',
+      'type': 'executable',
+      'sources': [
+        'die_test.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+        'die',
+      ],
+    },
+    {
+      'target_name': 'stl_mutex',
+      'type': 'static_library',
+      'sources': [
+        #'stl_mutex.h'
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:aos_sync',
+        '<(AOS)/build/aos.gyp:logging',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:aos_sync',
+        '<(AOS)/build/aos.gyp:logging',
+      ],
+    },
+    {
+      'target_name': 'stl_mutex_test',
+      'type': 'executable',
+      'sources': [
+        'stl_mutex_test.cc',
+      ],
+      'dependencies': [
+        'stl_mutex',
+        '<(EXTERNALS):gtest',
+        'queue_testutils',
+        '<(AOS)/common/util/util.gyp:thread',
+        'die',
+      ],
+    },
+  ],
+}
diff --git a/aos/common/commonmath.h b/aos/common/commonmath.h
new file mode 100644
index 0000000..f9337b2
--- /dev/null
+++ b/aos/common/commonmath.h
@@ -0,0 +1,27 @@
+#ifndef AOS_COMMON_MATH_H_
+#define AOS_COMMON_MATH_H_
+
+namespace aos {
+
+// Clips a value so that it is in [min, max]
+static inline double Clip(double value, double min, double max) {
+  if (value > max) {
+    value = max;
+  } else if (value < min) {
+    value = min;
+  }
+  return value;
+}
+
+template <typename T>
+static inline int sign(T val) {
+  if (val > T(0)) {
+    return 1;
+  } else {
+    return -1;
+  }
+}
+
+}  // namespace aos
+
+#endif  // AOS_COMMON_MATH_H_
diff --git a/aos/common/condition.h b/aos/common/condition.h
new file mode 100644
index 0000000..eccc0da
--- /dev/null
+++ b/aos/common/condition.h
@@ -0,0 +1,83 @@
+#ifndef AOS_COMMON_CONDITION_H_
+#define AOS_COMMON_CONDITION_H_
+
+#include "aos/linux_code/ipc_lib/aos_sync.h"
+
+namespace aos {
+
+class Mutex;
+
+// A condition variable (IPC mechanism where 1 process/task can notify all
+// others that are waiting for something to happen) without the race condition
+// where a notification is sent after some process has checked if the thing has
+// happened but before it has started listening for notifications.
+//
+// This implementation will LOG(FATAL) if anything weird happens.
+//
+// A simple example of the use of a condition variable (adapted from
+// pthread_cond(3)):
+//
+// int x, y;
+// Mutex mutex;
+// Condition condition(&mutex);
+//
+// // Waiting until x is greater than y:
+// {
+//   MutexLocker locker(&mutex);
+//   while (!(x > y)) condition.Wait();
+//   // do whatever
+// }
+//
+// // Modifying x and/or y:
+// {
+//   MutexLocker locker(&mutex);
+//   // modify x and y
+//   if (x > y) condition.Broadcast();
+// }
+//
+// Notice the loop around the Wait(). This is very important because some other
+// process can lock the mutex and modify the shared state (possibly undoing
+// whatever the Wait()er was waiting for) in between the Broadcast()er unlocking
+// the mutex and the Wait()er(s) relocking it.
+//
+// Multiple condition variables may be associated with the same mutex but
+// exactly one mutex must be associated with each condition variable.
+class Condition {
+ public:
+  // m is the mutex that will be associated with this condition variable. This
+  // object will hold on to a reference to it but does not take ownership.
+  explicit Condition(Mutex *m);
+
+  // Waits for the condition variable to be signalled, atomically unlocking the
+  // mutex associated with this condition variable at the same time. The mutex
+  // associated with this condition variable must be locked when this is called
+  // and will be locked when this method returns.
+  // NOTE: The relocking of the mutex is not performed atomically with waking
+  // up.
+  // Returns false.
+  bool Wait() __attribute__((warn_unused_result));
+
+  // Signals approximately 1 other process currently Wait()ing on this condition
+  // variable. Calling this does not require the mutex associated with this
+  // condition variable to be locked.
+  // One of the processes with the highest priority level will be woken.
+  // If there aren't any waiting at the time, none will be woken. There is a
+  // small race condition in the Linux implementation that can result in more
+  // than 1 being woken.
+  void Signal();
+  // Wakes all processes that are currently Wait()ing on this condition
+  // variable. Calling this does not require the mutex associated with this
+  // condition variable to be locked.
+  void Broadcast();
+
+  // Retrieves the mutex associated with this condition variable.
+  Mutex *m() { return m_; }
+
+ private:
+  aos_condition impl_;
+  Mutex *m_;
+};
+
+}  // namespace aos
+
+#endif  // AOS_COMMON_CONDITION_H_
diff --git a/aos/common/condition_test.cc b/aos/common/condition_test.cc
new file mode 100644
index 0000000..2310273
--- /dev/null
+++ b/aos/common/condition_test.cc
@@ -0,0 +1,367 @@
+#include "aos/common/condition.h"
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <atomic>
+
+#include "gtest/gtest.h"
+
+#include "aos/common/time.h"
+#include "aos/common/mutex.h"
+#include "aos/common/queue_testutils.h"
+#include "aos/common/type_traits.h"
+#include "aos/linux_code/ipc_lib/core_lib.h"
+#include "aos/common/logging/logging.h"
+#include "aos/common/macros.h"
+#include "aos/linux_code/ipc_lib/aos_sync.h"
+#include "aos/common/die.h"
+#include "aos/common/util/thread.h"
+
+using ::aos::time::Time;
+using ::aos::common::testing::GlobalCoreInstance;
+
+namespace aos {
+namespace testing {
+
+class ConditionTestCommon : public ::testing::Test {
+ public:
+  ConditionTestCommon() {}
+
+  void Settle() {
+    time::SleepFor(::Time::InSeconds(0.008));
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ConditionTestCommon);
+};
+
+// Some simple tests that don't rely on a GlobalCoreInstance to help with
+// debugging problems that cause tests using that to just completely lock up.
+class SimpleConditionTest : public ConditionTestCommon {
+ public:
+  SimpleConditionTest() : condition_(&mutex_) {}
+
+  Mutex mutex_;
+  Condition condition_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SimpleConditionTest);
+};
+
+// Makes sure that nothing crashes or anything with a basic Wait() and then
+// Signal().
+// This test is written to hopefully fail instead of deadlocking on failure, but
+// it's tricky because there's no way to kill the child in the middle.
+TEST_F(SimpleConditionTest, Basic) {
+  ::std::atomic_bool child_finished(false);
+  Condition child_ready(&mutex_);
+  ASSERT_FALSE(mutex_.Lock());
+  util::FunctionThread child([this, &child_finished, &child_ready](
+      util::FunctionThread *) {
+    ASSERT_FALSE(mutex_.Lock());
+    child_ready.Broadcast();
+    ASSERT_FALSE(condition_.Wait());
+    child_finished.store(true);
+    mutex_.Unlock();
+  });
+  child.Start();
+  ASSERT_FALSE(child_ready.Wait());
+  EXPECT_FALSE(child_finished.load());
+  condition_.Signal();
+  mutex_.Unlock();
+  child.Join();
+  EXPECT_TRUE(child_finished.load());
+}
+
+class ConditionTest : public ConditionTestCommon {
+ public:
+  struct Shared {
+    Shared() : condition(&mutex) {}
+
+    Mutex mutex;
+    Condition condition;
+  };
+  static_assert(shm_ok<Shared>::value,
+                "it's going to get shared between forked processes");
+
+  ConditionTest() : shared_(static_cast<Shared *>(shm_malloc(sizeof(Shared)))) {
+    new (shared_) Shared();
+  }
+  ~ConditionTest() {
+    shared_->~Shared();
+  }
+
+  GlobalCoreInstance my_core;
+
+  Shared *const shared_;
+
+ protected:
+  void SetUp() override {
+    SetDieTestMode(true);
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ConditionTest);
+};
+
+class ConditionTestProcess {
+ public:
+  enum class Action {
+    kWaitLockStart,  // lock, delay, wait, unlock
+    kWait,  // delay, lock, wait, unlock
+    kWaitNoUnlock,  // delay, lock, wait
+  };
+
+  // This amount gets added to any passed in delay to make the test repeatable.
+  static constexpr ::Time kMinimumDelay = ::Time::InSeconds(0.15);
+  static constexpr ::Time kDefaultTimeout = ::Time::InSeconds(0.15);
+
+  // delay is how long to wait before doing action to condition.
+  // timeout is how long to wait after delay before deciding that it's hung.
+  ConditionTestProcess(const ::Time &delay, Action action, Condition *condition,
+                       const ::Time &timeout = kDefaultTimeout)
+    : delay_(kMinimumDelay + delay), action_(action), condition_(condition),
+      timeout_(delay_ + timeout), child_(-1),
+      shared_(static_cast<Shared *>(shm_malloc(sizeof(Shared)))) {
+    new (shared_) Shared();
+  }
+  ~ConditionTestProcess() {
+    CHECK_EQ(child_, -1);
+  }
+
+  void Start() {
+    ASSERT_FALSE(shared_->started);
+
+    child_ = fork();
+    if (child_ == 0) {  // in child
+      ::aos::common::testing::PreventExit();
+      Run();
+      exit(EXIT_SUCCESS);
+    } else {  // in parent
+      CHECK_NE(child_, -1);
+
+      ASSERT_EQ(0, futex_wait(&shared_->ready));
+
+      shared_->started = true;
+    }
+  }
+
+  bool IsFinished() {
+    return shared_->finished;
+  }
+
+  ::testing::AssertionResult Hung() {
+    if (!shared_->started) {
+      ADD_FAILURE();
+      return ::testing::AssertionFailure() << "not started yet";
+    }
+    if (shared_->finished) {
+      Join();
+      return ::testing::AssertionFailure() << "already returned";
+    }
+    if (shared_->delayed) {
+      if (shared_->start_time > ::Time::Now() + timeout_) {
+        Kill();
+        return ::testing::AssertionSuccess() << "already been too long";
+      }
+    } else {
+      CHECK_EQ(0, futex_wait(&shared_->done_delaying));
+    }
+    time::SleepFor(::Time::InSeconds(0.01));
+    if (!shared_->finished) time::SleepUntil(shared_->start_time + timeout_);
+    if (shared_->finished) {
+      Join();
+      return ::testing::AssertionFailure() << "completed within timeout";
+    } else {
+      Kill();
+      return ::testing::AssertionSuccess() << "took too long";
+    }
+  }
+  ::testing::AssertionResult Test() {
+    Start();
+    return Hung();
+  }
+
+ private:
+  struct Shared {
+    Shared()
+      : started(false), delayed(false), done_delaying(0), start_time(0, 0),
+        finished(false), ready(0) {
+    }
+
+    volatile bool started;
+    volatile bool delayed;
+    aos_futex done_delaying;
+    ::Time start_time;
+    volatile bool finished;
+    aos_futex ready;
+  };
+  static_assert(shm_ok<Shared>::value,
+                "it's going to get shared between forked processes");
+
+  void Run() {
+    if (action_ == Action::kWaitLockStart) {
+      ASSERT_EQ(1, futex_set(&shared_->ready));
+      ASSERT_FALSE(condition_->m()->Lock());
+    }
+    time::SleepFor(delay_);
+    shared_->start_time = ::Time::Now();
+    shared_->delayed = true;
+    ASSERT_NE(-1, futex_set(&shared_->done_delaying));
+    if (action_ != Action::kWaitLockStart) {
+      ASSERT_EQ(1, futex_set(&shared_->ready));
+      ASSERT_FALSE(condition_->m()->Lock());
+    }
+    // TODO(brians): Test this returning true (aka the owner dying).
+    ASSERT_FALSE(condition_->Wait());
+    shared_->finished = true;
+    if (action_ != Action::kWaitNoUnlock) {
+      condition_->m()->Unlock();
+    }
+  }
+
+  void Join() {
+    CHECK_NE(child_, -1);
+    int status;
+    do {
+      CHECK_EQ(waitpid(child_, &status, 0), child_);
+    } while (!(WIFEXITED(status) || WIFSIGNALED(status)));
+    child_ = -1;
+  }
+  void Kill() {
+    CHECK_NE(child_, -1);
+    PCHECK(kill(child_, SIGTERM));
+    Join();
+  }
+
+  const ::Time delay_;
+  const Action action_;
+  Condition *const condition_;
+  const ::Time timeout_;
+
+  pid_t child_;
+
+  Shared *const shared_;
+
+  DISALLOW_COPY_AND_ASSIGN(ConditionTestProcess);
+};
+constexpr ::Time ConditionTestProcess::kMinimumDelay;
+constexpr ::Time ConditionTestProcess::kDefaultTimeout;
+
+// Makes sure that the testing framework and everything work for a really simple
+// Wait() and then Signal().
+TEST_F(ConditionTest, Basic) {
+  ConditionTestProcess child(::Time(0, 0),
+                             ConditionTestProcess::Action::kWait,
+                             &shared_->condition);
+  child.Start();
+  Settle();
+  EXPECT_FALSE(child.IsFinished());
+  shared_->condition.Signal();
+  EXPECT_FALSE(child.Hung());
+}
+
+// Makes sure that the worker child locks before it tries to Wait() etc.
+TEST_F(ConditionTest, Locking) {
+  ConditionTestProcess child(::Time(0, 0),
+                             ConditionTestProcess::Action::kWait,
+                             &shared_->condition);
+  ASSERT_FALSE(shared_->mutex.Lock());
+  child.Start();
+  Settle();
+  // This Signal() shouldn't do anything because the child should still be
+  // waiting to lock the mutex.
+  shared_->condition.Signal();
+  Settle();
+  shared_->mutex.Unlock();
+  EXPECT_TRUE(child.Hung());
+}
+
+// Tests that the work child only catches a Signal() after the mutex gets
+// unlocked.
+TEST_F(ConditionTest, LockFirst) {
+  ConditionTestProcess child(::Time(0, 0),
+                             ConditionTestProcess::Action::kWait,
+                             &shared_->condition);
+  ASSERT_FALSE(shared_->mutex.Lock());
+  child.Start();
+  Settle();
+  shared_->condition.Signal();
+  Settle();
+  EXPECT_FALSE(child.IsFinished());
+  shared_->mutex.Unlock();
+  Settle();
+  EXPECT_FALSE(child.IsFinished());
+  shared_->condition.Signal();
+  EXPECT_FALSE(child.Hung());
+}
+
+// Tests that the mutex gets relocked after Wait() returns.
+TEST_F(ConditionTest, Relocking) {
+  ConditionTestProcess child(::Time(0, 0),
+                             ConditionTestProcess::Action::kWaitNoUnlock,
+                             &shared_->condition);
+  child.Start();
+  Settle();
+  shared_->condition.Signal();
+  EXPECT_FALSE(child.Hung());
+  EXPECT_EQ(Mutex::State::kLockFailed, shared_->mutex.TryLock());
+}
+
+// Tests that Signal() stops exactly 1 Wait()er.
+TEST_F(ConditionTest, SignalOne) {
+  ConditionTestProcess child1(::Time(0, 0),
+                              ConditionTestProcess::Action::kWait,
+                              &shared_->condition);
+  ConditionTestProcess child2(::Time(0, 0),
+                              ConditionTestProcess::Action::kWait,
+                              &shared_->condition);
+  ConditionTestProcess child3(::Time(0, 0),
+                              ConditionTestProcess::Action::kWait,
+                              &shared_->condition);
+  auto number_finished = [&]() { return (child1.IsFinished() ? 1 : 0) +
+    (child2.IsFinished() ? 1 : 0) + (child3.IsFinished() ? 1 : 0); };
+  child1.Start();
+  child2.Start();
+  child3.Start();
+  Settle();
+  EXPECT_EQ(0, number_finished());
+  shared_->condition.Signal();
+  Settle();
+  EXPECT_EQ(1, number_finished());
+  shared_->condition.Signal();
+  Settle();
+  EXPECT_EQ(2, number_finished());
+  shared_->condition.Signal();
+  Settle();
+  EXPECT_EQ(3, number_finished());
+  EXPECT_FALSE(child1.Hung());
+  EXPECT_FALSE(child2.Hung());
+  EXPECT_FALSE(child3.Hung());
+}
+
+// Tests that Brodcast() wakes multiple Wait()ers.
+TEST_F(ConditionTest, Broadcast) {
+  ConditionTestProcess child1(::Time(0, 0),
+                              ConditionTestProcess::Action::kWait,
+                              &shared_->condition);
+  ConditionTestProcess child2(::Time(0, 0),
+                              ConditionTestProcess::Action::kWait,
+                              &shared_->condition);
+  ConditionTestProcess child3(::Time(0, 0),
+                              ConditionTestProcess::Action::kWait,
+                              &shared_->condition);
+  child1.Start();
+  child2.Start();
+  child3.Start();
+  Settle();
+  shared_->condition.Broadcast();
+  EXPECT_FALSE(child1.Hung());
+  EXPECT_FALSE(child2.Hung());
+  EXPECT_FALSE(child3.Hung());
+}
+
+}  // namespace testing
+}  // namespace aos
diff --git a/aos/common/controls/control_loop-tmpl.h b/aos/common/controls/control_loop-tmpl.h
new file mode 100644
index 0000000..9bf395e
--- /dev/null
+++ b/aos/common/controls/control_loop-tmpl.h
@@ -0,0 +1,130 @@
+#include <stddef.h>
+#include <inttypes.h>
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/messages/robot_state.q.h"
+#include "aos/common/logging/queue_logging.h"
+#include "aos/common/util/phased_loop.h"
+
+namespace aos {
+namespace controls {
+
+// TODO(aschuh): Tests.
+
+template <class T>
+constexpr ::aos::time::Time ControlLoop<T>::kStaleLogInterval;
+template <class T>
+constexpr ::aos::time::Time ControlLoop<T>::kPwmDisableTime;
+
+template <class T>
+void ControlLoop<T>::ZeroOutputs() {
+  aos::ScopedMessagePtr<OutputType> output =
+      control_loop_->output.MakeMessage();
+  Zero(output.get());
+  output.Send();
+}
+
+template <class T>
+void ControlLoop<T>::Iterate() {
+  no_goal_.Print();
+  driver_station_old_.Print();
+  no_sensor_state_.Print();
+  no_driver_station_.Print();
+  motors_off_log_.Print();
+
+  control_loop_->position.FetchAnother();
+  const PositionType *const position = control_loop_->position.get();
+  LOG_STRUCT(DEBUG, "position", *position);
+
+  // Fetch the latest control loop goal. If there is no new
+  // goal, we will just reuse the old one.
+  control_loop_->goal.FetchLatest();
+  const GoalType *goal = control_loop_->goal.get();
+  if (goal) {
+    LOG_STRUCT(DEBUG, "goal", *goal);
+  } else {
+    LOG_INTERVAL(no_goal_);
+  }
+
+  ::aos::robot_state.FetchLatest();
+  if (!::aos::robot_state.get()) {
+    LOG_INTERVAL(no_sensor_state_);
+    return;
+  }
+  if (sensor_reader_pid_ != ::aos::robot_state->reader_pid) {
+    LOG(INFO, "new sensor reader PID %" PRId32 ", old was %" PRId32 "\n",
+        ::aos::robot_state->reader_pid, sensor_reader_pid_);
+    reset_ = true;
+    sensor_reader_pid_ = ::aos::robot_state->reader_pid;
+  }
+
+  bool outputs_enabled = false;
+
+  // Check to see if we got a driver station packet recently.
+  if (::aos::joystick_state.FetchLatest()) {
+    if (::aos::joystick_state->enabled) outputs_enabled = true;
+    if (::aos::robot_state->outputs_enabled) {
+      // If the driver's station reports being disabled, we're probably not
+      // actually going to send motor values regardless of what the FPGA
+      // reports.
+      if (::aos::joystick_state->enabled) {
+        last_pwm_sent_ = ::aos::robot_state->sent_time;
+      } else {
+        LOG(WARNING, "outputs enabled while disabled\n");
+      }
+    } else if (::aos::joystick_state->enabled) {
+      LOG(WARNING, "outputs disabled while enabled\n");
+    }
+  } else if (::aos::joystick_state.IsNewerThanMS(kDSPacketTimeoutMs)) {
+    if (::aos::joystick_state->enabled) {
+      outputs_enabled = true;
+    }
+  } else {
+    if (::aos::joystick_state.get()) {
+      LOG_INTERVAL(driver_station_old_);
+    } else {
+      LOG_INTERVAL(no_driver_station_);
+    }
+  }
+
+  const bool motors_off =
+      (::aos::time::Time::Now() - last_pwm_sent_) >= kPwmDisableTime;
+  if (motors_off) {
+    if (::aos::joystick_state.get() && ::aos::joystick_state->enabled) {
+      LOG_INTERVAL(motors_off_log_);
+    }
+    outputs_enabled = false;
+  }
+
+  aos::ScopedMessagePtr<StatusType> status =
+      control_loop_->status.MakeMessage();
+  if (status.get() == nullptr) {
+    return;
+  }
+
+  if (outputs_enabled) {
+    aos::ScopedMessagePtr<OutputType> output =
+        control_loop_->output.MakeMessage();
+    RunIteration(goal, position, output.get(), status.get());
+
+    LOG_STRUCT(DEBUG, "output", *output);
+    output.Send();
+  } else {
+    // The outputs are disabled, so pass nullptr in for the output.
+    RunIteration(goal, position, nullptr, status.get());
+    ZeroOutputs();
+  }
+
+  LOG_STRUCT(DEBUG, "status", *status);
+  status.Send();
+}
+
+template <class T>
+void ControlLoop<T>::Run() {
+  while (true) {
+    Iterate();
+  }
+}
+
+}  // namespace controls
+}  // namespace aos
diff --git a/aos/common/controls/control_loop.cc b/aos/common/controls/control_loop.cc
new file mode 100644
index 0000000..c314254
--- /dev/null
+++ b/aos/common/controls/control_loop.cc
@@ -0,0 +1,7 @@
+#include "aos/common/controls/control_loop.h"
+
+namespace aos {
+namespace controls {
+
+}  // namespace controls
+}  // namespace aos
diff --git a/aos/common/controls/control_loop.h b/aos/common/controls/control_loop.h
new file mode 100644
index 0000000..d56e5d8
--- /dev/null
+++ b/aos/common/controls/control_loop.h
@@ -0,0 +1,176 @@
+#ifndef AOS_CONTROL_LOOP_CONTROL_LOOP_H_
+#define AOS_CONTROL_LOOP_CONTROL_LOOP_H_
+
+#include <string.h>
+
+#include "aos/common/type_traits.h"
+#include "aos/common/queue.h"
+#include "aos/common/time.h"
+#include "aos/common/util/log_interval.h"
+
+namespace aos {
+namespace controls {
+
+// Interface to describe runnable jobs.
+class Runnable {
+ public:
+  virtual ~Runnable() {}
+  // Runs forever.
+  virtual void Run() = 0;
+  // Does one quick piece of work and return.  Does _not_ block.
+  virtual void Iterate() = 0;
+};
+
+class SerializableControlLoop : public Runnable {
+ public:
+  // Returns the size of all the data to be sent when serialized.
+  virtual size_t SeralizedSize() = 0;
+  // Serialize the current data.
+  virtual void Serialize(char *buffer) const = 0;
+  // Serialize zeroed data in case the data is out of date.
+  virtual void SerializeZeroMessage(char *buffer) const = 0;
+  // Deserialize data into the control loop.
+  virtual void Deserialize(const char *buffer) = 0;
+  // Unique identifier for the control loop.
+  // Most likely the hash of the queue group.
+  virtual uint32_t UniqueID() = 0;
+};
+
+// Control loops run this often, "starting" at time 0.
+constexpr time::Time kLoopFrequency = time::Time::InSeconds(0.005);
+
+// Provides helper methods to assist in writing control loops.
+// This template expects to be constructed with a queue group as an argument
+// that has a goal, position, status, and output queue.
+// It will then call the RunIteration method every cycle that it has enough
+// valid data for the control loop to run.
+template <class T>
+class ControlLoop : public SerializableControlLoop {
+ public:
+  // Create some convenient typedefs to reference the Goal, Position, Status,
+  // and Output structures.
+  typedef typename std::remove_reference<
+      decltype(*(static_cast<T *>(NULL)->goal.MakeMessage().get()))>::type
+        GoalType;
+  typedef typename std::remove_reference<
+      decltype(*(static_cast<T *>(NULL)->position.MakeMessage().get()))>::type
+        PositionType;
+  typedef typename std::remove_reference<
+    decltype(*(static_cast<T *>(NULL)->status.MakeMessage().get()))>::type
+      StatusType;
+  typedef typename std::remove_reference<
+    decltype(*(static_cast<T *>(NULL)->output.MakeMessage().get()))>::type
+      OutputType;
+
+  ControlLoop(T *control_loop) : control_loop_(control_loop) {}
+
+  // Returns true if all the counters etc in the sensor data have been reset.
+  // This will return true only a single time per reset.
+  bool WasReset() {
+    if (reset_) {
+      reset_ = false;
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  // Constructs and sends a message on the output queue which sets everything to
+  // a safe state (generally motors off). For some subclasses, this will be a
+  // bit different (ie pistons).
+  // The implementation here creates a new Output message, calls Zero() on it,
+  // and then sends it.
+  virtual void ZeroOutputs();
+
+  // Sets the output to zero.
+  // Over-ride if a value of zero is not "off" for this subsystem.
+  virtual void Zero(OutputType *output) { output->Zero(); }
+
+  // Runs the loop forever.
+  void Run() override;
+
+  // Runs one cycle of the loop.
+  void Iterate() override;
+
+  // Returns the name of the queue group.
+  const char *name() { return control_loop_->name(); }
+
+  // Methods to serialize all the data that should be sent over the network.
+  size_t SeralizedSize() override { return control_loop_->goal->Size(); }
+  void Serialize(char *buffer) const override {
+    control_loop_->goal->Serialize(buffer);
+  }
+  void SerializeZeroMessage(char *buffer) const override {
+    GoalType zero_goal;
+    zero_goal.Zero();
+    zero_goal.Serialize(buffer);
+  }
+
+  void Deserialize(const char *buffer) override {
+    ScopedMessagePtr<GoalType> new_msg = control_loop_->goal.MakeMessage();
+    new_msg->Deserialize(buffer);
+    new_msg.Send();
+  }
+
+  uint32_t UniqueID() override { return control_loop_->hash(); }
+
+ protected:
+  // Runs an iteration of the control loop.
+  // goal is the last goal that was sent.  It might be any number of cycles old
+  // or nullptr if we haven't ever received a goal.
+  // position is the current position, or nullptr if we didn't get a position
+  // this cycle.
+  // output is the values to be sent to the motors.  This is nullptr if the
+  // output is going to be ignored and set to 0.
+  // status is the status of the control loop.
+  // Both output and status should be filled in by the implementation.
+  virtual void RunIteration(const GoalType *goal,
+                            const PositionType *position,
+                            OutputType *output,
+                            StatusType *status) = 0;
+
+  T *queue_group() { return control_loop_; }
+  const T *queue_group() const { return control_loop_; }
+
+ private:
+  static constexpr ::aos::time::Time kStaleLogInterval =
+      ::aos::time::Time::InSeconds(0.1);
+  // The amount of time after the last PWM pulse we consider motors enabled for.
+  // 100ms is the result of using an oscilliscope to look at the input and
+  // output of a Talon. The Info Sheet also lists 100ms for Talon SR, Talon SRX,
+  // and Victor SP.
+  static constexpr ::aos::time::Time kPwmDisableTime =
+      ::aos::time::Time::InMS(100);
+
+  // Maximum age of driver station packets before the loop will be disabled.
+  static const int kDSPacketTimeoutMs = 500;
+
+  // Pointer to the queue group
+  T *control_loop_;
+
+  bool reset_ = false;
+  int32_t sensor_reader_pid_ = 0;
+
+  ::aos::time::Time last_pwm_sent_{0, 0};
+
+  typedef ::aos::util::SimpleLogInterval SimpleLogInterval;
+  SimpleLogInterval no_driver_station_ =
+      SimpleLogInterval(kStaleLogInterval, ERROR,
+                        "no driver station packet");
+  SimpleLogInterval driver_station_old_ =
+      SimpleLogInterval(kStaleLogInterval, ERROR,
+                        "driver station packet is too old");
+  SimpleLogInterval no_sensor_state_ =
+      SimpleLogInterval(kStaleLogInterval, ERROR, "no sensor state");
+  SimpleLogInterval motors_off_log_ =
+      SimpleLogInterval(kStaleLogInterval, WARNING, "motors disabled");
+  SimpleLogInterval no_goal_ =
+      SimpleLogInterval(kStaleLogInterval, ERROR, "no goal");
+};
+
+}  // namespace controls
+}  // namespace aos
+
+#include "aos/common/controls/control_loop-tmpl.h"  // IWYU pragma: export
+
+#endif
diff --git a/aos/common/controls/control_loop_test.cc b/aos/common/controls/control_loop_test.cc
new file mode 100644
index 0000000..fd461b6
--- /dev/null
+++ b/aos/common/controls/control_loop_test.cc
@@ -0,0 +1,59 @@
+#include "aos/common/controls/control_loop_test.h"
+
+#include "aos/common/messages/robot_state.q.h"
+
+namespace aos {
+namespace testing {
+
+constexpr ::aos::time::Time ControlLoopTest::kTimeTick;
+constexpr ::aos::time::Time ControlLoopTest::kDSPacketTime;
+
+ControlLoopTest::ControlLoopTest() {
+  ::aos::joystick_state.Clear();
+  ::aos::robot_state.Clear();
+
+  ::aos::time::Time::EnableMockTime(current_time_);
+
+  SendMessages(false);
+}
+
+ControlLoopTest::~ControlLoopTest() {
+  ::aos::joystick_state.Clear();
+  ::aos::robot_state.Clear();
+
+  ::aos::time::Time::DisableMockTime();
+}
+
+void ControlLoopTest::SendMessages(bool enabled) {
+  if (current_time_ - last_ds_time_ >= kDSPacketTime) {
+    last_ds_time_ = current_time_;
+    auto new_state = ::aos::joystick_state.MakeMessage();
+    new_state->fake = true;
+
+    new_state->enabled = enabled;
+    new_state->autonomous = false;
+    new_state->team_id = team_id_;
+
+    new_state.Send();
+  }
+
+  {
+    auto new_state = ::aos::robot_state.MakeMessage();
+
+    new_state->reader_pid = reader_pid_;
+    new_state->outputs_enabled = enabled;
+    new_state->browned_out = false;
+
+    new_state->is_3v3_active = true;
+    new_state->is_5v_active = true;
+    new_state->voltage_3v3 = 3.3;
+    new_state->voltage_5v = 5.0;
+
+    new_state->voltage_roborio_in = 12.4;
+
+    new_state.Send();
+  }
+}
+
+}  // namespace testing
+}  // namespace aos
diff --git a/aos/common/controls/control_loop_test.h b/aos/common/controls/control_loop_test.h
new file mode 100644
index 0000000..4fd13a3
--- /dev/null
+++ b/aos/common/controls/control_loop_test.h
@@ -0,0 +1,61 @@
+#ifndef AOS_COMMON_CONTROLS_CONTROL_LOOP_TEST_H_
+#define AOS_COMMON_CONTROLS_CONTROL_LOOP_TEST_H_
+
+#include "gtest/gtest.h"
+
+#include "aos/common/queue_testutils.h"
+#include "aos/common/time.h"
+
+namespace aos {
+namespace testing {
+
+// Handles setting up the environment that all control loops need to actually
+// run.
+// This includes sending the queue messages and Clear()ing the queues when
+// appropriate.
+// It also includes dealing with ::aos::time.
+class ControlLoopTest : public ::testing::Test {
+ public:
+  ControlLoopTest();
+  virtual ~ControlLoopTest();
+
+  void set_team_id(uint16_t team_id) { team_id_ = team_id; }
+  uint16_t team_id() const { return team_id_; }
+
+  // Sends out all of the required queue messages.
+  void SendMessages(bool enabled);
+  // Ticks time for a single control loop cycle.
+  void TickTime() {
+    ::aos::time::Time::SetMockTime(current_time_ += kTimeTick);
+  }
+
+  // Simulates everything that happens during 1 loop time step.
+  void SimulateTimestep(bool enabled) {
+    SendMessages(enabled);
+    TickTime();
+  }
+
+  // Simulate a reset of the process reading sensors, which tells loops that all
+  // index counts etc will be reset.
+  void SimulateSensorReset() {
+    ++reader_pid_;
+  }
+
+ private:
+  static constexpr ::aos::time::Time kTimeTick = ::aos::time::Time::InUS(5000);
+  static constexpr ::aos::time::Time kDSPacketTime =
+      ::aos::time::Time::InMS(20);
+
+  uint16_t team_id_ = 971;
+  int32_t reader_pid_ = 1;
+
+  ::aos::time::Time last_ds_time_ = ::aos::time::Time::InSeconds(0);
+  ::aos::time::Time current_time_ = ::aos::time::Time::InSeconds(0);
+
+  ::aos::common::testing::GlobalCoreInstance my_core;
+};
+
+}  // namespace testing
+}  // namespace aos
+
+#endif  // AOS_COMMON_CONTROLS_CONTROL_LOOP_TEST_H_
diff --git a/aos/common/controls/control_loops.q b/aos/common/controls/control_loops.q
new file mode 100644
index 0000000..2b0bfb1
--- /dev/null
+++ b/aos/common/controls/control_loops.q
@@ -0,0 +1,34 @@
+package aos.control_loops;
+
+interface ControlLoop {
+  queue goal;
+  queue position;
+  queue output;
+  queue status;
+};
+
+message Goal {
+  double goal;
+};
+
+message Position {
+  double position;
+};
+
+message Output {
+  double voltage;
+};
+
+message Status {
+  bool done;
+};
+
+// Single Input Single Output control loop.
+queue_group SISO {
+  implements ControlLoop;
+
+  queue Goal goal;
+  queue Position position;
+  queue Output output;
+  queue Status status;
+};
diff --git a/aos/common/controls/controls.gyp b/aos/common/controls/controls.gyp
new file mode 100644
index 0000000..4e0bc79
--- /dev/null
+++ b/aos/common/controls/controls.gyp
@@ -0,0 +1,94 @@
+{
+  'targets': [
+    {
+      'target_name': 'replay_control_loop',
+      'type': 'static_library',
+      'sources': [
+        #'replay_control_loop.h',
+      ],
+      'dependencies': [
+        '<(AOS)/common/common.gyp:queues',
+        'control_loop',
+        '<(AOS)/linux_code/logging/logging.gyp:log_replay',
+        '<(AOS)/common/logging/logging.gyp:queue_logging',
+        '<(AOS)/common/common.gyp:time',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/common.gyp:queues',
+        'control_loop',
+        '<(AOS)/linux_code/logging/logging.gyp:log_replay',
+        '<(AOS)/common/logging/logging.gyp:queue_logging',
+        '<(AOS)/common/common.gyp:time',
+      ],
+    },
+    {
+      'target_name': 'control_loop_test',
+      'type': 'static_library',
+      'sources': [
+        'control_loop_test.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/common/messages/messages.gyp:robot_state',
+        '<(EXTERNALS):gtest',
+        '<(AOS)/common/common.gyp:queue_testutils',
+      ],
+      'export_dependent_settings': [
+        '<(EXTERNALS):gtest',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/common/common.gyp:queue_testutils',
+      ],
+    },
+    {
+      'target_name': 'polytope',
+      'type': 'static_library',
+      'sources': [
+        #'polytope.h',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):eigen',
+        '<(EXTERNALS):libcdd',
+      ],
+      'export_dependent_settings': [
+        '<(EXTERNALS):eigen',
+        '<(EXTERNALS):libcdd',
+      ],
+    },
+    {
+      'target_name': 'control_loop_queues',
+      'type': 'static_library',
+      'sources': [ '<(AOS)/common/controls/control_loops.q' ],
+      'variables': {
+        'header_path': 'aos/common/controls',
+      },
+      'includes': ['../../../aos/build/queues.gypi'],
+    },
+    {
+      'target_name': 'control_loop',
+      'type': 'static_library',
+      'sources': [
+        'control_loop.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/common/messages/messages.gyp:robot_state',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/util/util.gyp:phased_loop',
+        '<(AOS)/common/common.gyp:time',
+        'control_loop_queues',
+        '<(AOS)/common/logging/logging.gyp:queue_logging',
+        '<(AOS)/common/util/util.gyp:log_interval',
+        '<(AOS)/common/common.gyp:queues',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/messages/messages.gyp:robot_state',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/util/util.gyp:phased_loop',
+        '<(AOS)/common/common.gyp:time',
+        'control_loop_queues',
+        '<(AOS)/common/logging/logging.gyp:queue_logging',
+        '<(AOS)/common/util/util.gyp:log_interval',
+        '<(AOS)/common/common.gyp:queues',
+      ],
+    },
+  ],
+}
diff --git a/aos/common/controls/polytope.h b/aos/common/controls/polytope.h
new file mode 100644
index 0000000..e37346e
--- /dev/null
+++ b/aos/common/controls/polytope.h
@@ -0,0 +1,130 @@
+#ifndef AOS_COMMON_CONTROLS_POLYTOPE_H_
+#define AOS_COMMON_CONTROLS_POLYTOPE_H_
+
+#include "Eigen/Dense"
+#include "libcdd-094g-prefix/include/setoper.h"
+#include "libcdd-094g-prefix/include/cdd.h"
+
+namespace aos {
+namespace controls {
+
+// A n dimension polytope.
+template <int number_of_dimensions>
+class HPolytope {
+ public:
+  // Constructs a polytope given the H and k matricies.
+  HPolytope(Eigen::Matrix<double, Eigen::Dynamic, number_of_dimensions> H,
+            Eigen::Matrix<double, Eigen::Dynamic, 1> k)
+      : H_(H),
+        k_(k) {
+  }
+
+  // This is an initialization function shared across all instantiations of this
+  // template.
+  // This must be called at least once before calling any of the methods. It is
+  // not thread-safe.
+  static void Init() {
+    dd_set_global_constants();
+  }
+
+  // Returns a reference to H.
+  const Eigen::Matrix<double, Eigen::Dynamic,
+                      number_of_dimensions> &H() const {
+    return H_;
+  }
+
+  // Returns a reference to k.
+  const Eigen::Matrix<double, Eigen::Dynamic,
+                      1> &k() const {
+    return k_;
+  }
+
+  // Returns the number of dimensions in the polytope.
+  int ndim() const { return number_of_dimensions; }
+
+  // Returns the number of constraints currently in the polytope.
+  int num_constraints() const { return k_.rows(); }
+
+  // Returns true if the point is inside the polytope.
+  bool IsInside(Eigen::Matrix<double, number_of_dimensions, 1> point) const;
+
+  // Returns the list of vertices inside the polytope.
+  Eigen::Matrix<double, number_of_dimensions, Eigen::Dynamic> Vertices() const;
+
+ private:
+  Eigen::Matrix<double, Eigen::Dynamic, number_of_dimensions> H_;
+  Eigen::Matrix<double, Eigen::Dynamic, 1> k_;
+};
+
+template <int number_of_dimensions>
+bool HPolytope<number_of_dimensions>::IsInside(
+    Eigen::Matrix<double, number_of_dimensions, 1> point) const {
+  auto ev = H_ * point;
+  for (int i = 0; i < num_constraints(); ++i) {
+    if (ev(i, 0) > k_(i, 0)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+template <int number_of_dimensions>
+Eigen::Matrix<double, number_of_dimensions, Eigen::Dynamic>
+    HPolytope<number_of_dimensions>::Vertices() const {
+  dd_MatrixPtr matrix = dd_CreateMatrix(num_constraints(), ndim() + 1);
+
+  // Copy the data over. TODO(aschuh): Is there a better way?  I hate copying...
+  for (int i = 0; i < num_constraints(); ++i) {
+    dd_set_d(matrix->matrix[i][0], k_(i, 0));
+    for (int j = 0; j < ndim(); ++j) {
+      dd_set_d(matrix->matrix[i][j + 1], -H_(i, j));
+    }
+  }
+
+  matrix->representation = dd_Inequality;
+  matrix->numbtype = dd_Real;
+
+  dd_ErrorType error;
+  dd_PolyhedraPtr polyhedra = dd_DDMatrix2Poly(matrix, &error);
+  if (error != dd_NoError || polyhedra == NULL) {
+    dd_WriteErrorMessages(stderr, error);
+    dd_FreeMatrix(matrix);
+    Eigen::Matrix<double, number_of_dimensions, Eigen::Dynamic> ans(0, 0);
+    return ans;
+  }
+
+  dd_MatrixPtr vertex_matrix = dd_CopyGenerators(polyhedra);
+
+  int num_vertices = 0;
+  int num_rays = 0;
+  for (int i = 0; i < vertex_matrix->rowsize; ++i) {
+    if (dd_get_d(vertex_matrix->matrix[i][0]) == 0) {
+      num_rays += 1;
+    } else {
+      num_vertices += 1;
+    }
+  }
+
+  Eigen::Matrix<double, number_of_dimensions, Eigen::Dynamic> vertices(
+      number_of_dimensions, num_vertices);
+
+  int vertex_index = 0;
+  for (int i = 0; i < vertex_matrix->rowsize; ++i) {
+    if (dd_get_d(vertex_matrix->matrix[i][0]) != 0) {
+      for (int j = 0; j < number_of_dimensions; ++j) {
+        vertices(j, vertex_index) = dd_get_d(vertex_matrix->matrix[i][j + 1]);
+      }
+      ++vertex_index;
+    }
+  }
+  dd_FreeMatrix(vertex_matrix);
+  dd_FreePolyhedra(polyhedra);
+  dd_FreeMatrix(matrix);
+
+  return vertices;
+}
+
+}  // namespace controls
+}  // namespace aos
+
+#endif  // AOS_COMMON_CONTROLS_POLYTOPE_H_
diff --git a/aos/common/controls/replay_control_loop.h b/aos/common/controls/replay_control_loop.h
new file mode 100644
index 0000000..e258267
--- /dev/null
+++ b/aos/common/controls/replay_control_loop.h
@@ -0,0 +1,185 @@
+#ifndef AOS_COMMON_CONTROLS_REPLAY_CONTROL_LOOP_H_
+#define AOS_COMMON_CONTROLS_REPLAY_CONTROL_LOOP_H_
+
+#include <fcntl.h>
+
+#include "aos/common/queue.h"
+#include "aos/common/controls/control_loop.h"
+#include "aos/linux_code/logging/log_replay.h"
+#include "aos/common/logging/queue_logging.h"
+#include "aos/common/time.h"
+#include "aos/common/macros.h"
+
+namespace aos {
+namespace controls {
+
+// Handles reading logged messages and running them through a control loop
+// again.
+// T should be a queue group suitable for use with ControlLoop.
+template <class T>
+class ControlLoopReplayer {
+ public:
+  typedef typename ControlLoop<T>::GoalType GoalType;
+  typedef typename ControlLoop<T>::PositionType PositionType;
+  typedef typename ControlLoop<T>::StatusType StatusType;
+  typedef typename ControlLoop<T>::OutputType OutputType;
+
+  // loop_group is where to send the messages out.
+  // process_name is the name of the process which wrote the log messages in the
+  // file(s).
+  ControlLoopReplayer(T *loop_group, const ::std::string &process_name)
+      : loop_group_(loop_group) {
+    // Clear out any old messages which will confuse the code.
+    loop_group_->status.FetchLatest();
+    loop_group_->output.FetchLatest();
+
+    replayer_.AddDirectQueueSender("wpilib_interface.DSReader",
+                                   "joystick_state", ::aos::joystick_state);
+    replayer_.AddDirectQueueSender("wpilib_interface.SensorReader",
+                                   "robot_state", ::aos::robot_state);
+
+    replayer_.AddHandler(
+        process_name, "position",
+        ::std::function<void(const PositionType &)>(::std::ref(position_)));
+    replayer_.AddHandler(
+        process_name, "output",
+        ::std::function<void(const OutputType &)>(::std::ref(output_)));
+    replayer_.AddHandler(
+        process_name, "status",
+        ::std::function<void(const StatusType &)>(::std::ref(status_)));
+    // The timing of goal messages doesn't matter, and we don't need to look
+    // back at them after running the loop.
+    replayer_.AddDirectQueueSender(process_name, "goal", loop_group_->goal);
+  }
+
+  // Replays messages from a file.
+  // filename can be straight from the command line; all sanity checking etc is
+  // handled by this function.
+  void ProcessFile(const char *filename);
+
+ private:
+  // A message handler which saves off messages and records whether it currently
+  // has a new one or not.
+  template <class S>
+  class CaptureMessage {
+   public:
+    CaptureMessage() {}
+
+    void operator()(const S &message) {
+      CHECK(!have_new_message_);
+      saved_message_ = message;
+      have_new_message_ = true;
+    }
+
+    const S &saved_message() const { return saved_message_; }
+    bool have_new_message() const { return have_new_message_; }
+    void clear_new_message() { have_new_message_ = false; }
+
+   private:
+    S saved_message_;
+    bool have_new_message_ = false;
+
+    DISALLOW_COPY_AND_ASSIGN(CaptureMessage);
+  };
+
+  // Runs through the file currently loaded in replayer_.
+  // Returns after going through the entire file.
+  void DoProcessFile();
+
+  T *const loop_group_;
+
+  CaptureMessage<PositionType> position_;
+  CaptureMessage<OutputType> output_;
+  CaptureMessage<StatusType> status_;
+
+  // The output that the loop sends for ZeroOutputs(). It might not actually be
+  // all fields zeroed, so we pick the first one and remember it to compare.
+  CaptureMessage<OutputType> zero_output_;
+
+  ::aos::logging::linux_code::LogReplayer replayer_;
+};
+
+template <class T>
+void ControlLoopReplayer<T>::ProcessFile(const char *filename) {
+  int fd;
+  if (strcmp(filename, "-") == 0) {
+    fd = STDIN_FILENO;
+  } else {
+    fd = open(filename, O_RDONLY);
+  }
+  if (fd == -1) {
+    PLOG(FATAL, "couldn't open file '%s' for reading", filename);
+  }
+
+  replayer_.OpenFile(fd);
+  DoProcessFile();
+  replayer_.CloseCurrentFile();
+
+  PCHECK(close(fd));
+}
+
+template <class T>
+void ControlLoopReplayer<T>::DoProcessFile() {
+  while (true) {
+    // Dig through messages until we get a status, which indicates the end of
+    // the control loop cycle.
+    while (!status_.have_new_message()) {
+      if (replayer_.ProcessMessage()) return;
+    }
+
+    // Send out the position message (after adjusting the time offset) so the
+    // loop will run right now.
+    if (!position_.have_new_message()) {
+      LOG(WARNING, "don't have a new position this cycle -> skipping\n");
+      status_.clear_new_message();
+      position_.clear_new_message();
+      output_.clear_new_message();
+      continue;
+    }
+    ::aos::time::OffsetToNow(position_.saved_message().sent_time);
+    {
+      auto position_message = loop_group_->position.MakeMessage();
+      *position_message = position_.saved_message();
+      CHECK(position_message.Send());
+    }
+    position_.clear_new_message();
+
+    // Wait for the loop to finish running.
+    loop_group_->status.FetchNextBlocking();
+
+    // Point out if the status is different.
+    if (!loop_group_->status->EqualsNoTime(status_.saved_message())) {
+      LOG_STRUCT(WARNING, "expected status", status_.saved_message());
+      LOG_STRUCT(WARNING, "got status", *loop_group_->status);
+    }
+    status_.clear_new_message();
+
+    // Point out if the output is different. This is a lot more complicated than
+    // for the status because there isn't always an output logged.
+    bool loop_new_output = loop_group_->output.FetchLatest();
+    if (output_.have_new_message()) {
+      if (!loop_new_output) {
+        LOG_STRUCT(WARNING, "no output, expected", output_.saved_message());
+      } else if (!loop_group_->output->EqualsNoTime(output_.saved_message())) {
+        LOG_STRUCT(WARNING, "expected output", output_.saved_message());
+        LOG_STRUCT(WARNING, "got output", *loop_group_->output);
+      }
+    } else if (loop_new_output) {
+      if (zero_output_.have_new_message()) {
+        if (!loop_group_->output->EqualsNoTime(zero_output_.saved_message())) {
+          LOG_STRUCT(WARNING, "expected null output",
+                     zero_output_.saved_message());
+          LOG_STRUCT(WARNING, "got output", *loop_group_->output);
+        }
+      } else {
+        zero_output_(*loop_group_->output);
+      }
+    }
+    output_.clear_new_message();
+  }
+}
+
+}  // namespace controls
+}  // namespace aos
+
+#endif  // AOS_COMMON_CONTROLS_REPLAY_CONTROL_LOOP_H_
diff --git a/aos/common/debugging-tips.txt b/aos/common/debugging-tips.txt
new file mode 100644
index 0000000..b9a50f3
--- /dev/null
+++ b/aos/common/debugging-tips.txt
@@ -0,0 +1,45 @@
+[General]
+Check the logs! Very few things will fail without putting something in the logs.
+  If they do, that is a bug unless our code is never getting run (there are
+    innumerable ways that could happen, but it generally doesn't).
+  To check the logs, run `log_displayer` if `binary_log_writer` has been started
+    or just run `log_streamer` if you want to do simple testing without writing
+	logs to a file. See `log_displayer --help` for options.
+All of the binaries get put in the same place. That is
+  src/outputs/prime/outputs on the build machine and
+  /home/driver/robot_code/bin on linux.
+
+[Startup]
+Low level startup errors often end up in
+  /tmp/aos_fatal_error.* under linux. Also helpful are the /tmp/starter*_std*
+  files (if the standard start scripts are being used).
+    If lots of the /tmp/starter_*std* files (with different numbers) are being
+    created, that means that starter_exe is dying constantly.
+
+[Anything Not Running]
+Check starter_exe's log messages. They might mention that it is constantly dying
+  on startup and being restarted.
+
+[Control Loop(s) Not Working]
+Are robot_state messages going out? An aos::JoystickInput (often
+  joystick_reader) should be sending them.
+  Also, kFakeJoysticks in aos/prime/input/joystick_reader.cc has to be set to
+    false in order for anything to get output.
+Is it being fed goal messages?
+Is it getting position messages?
+Is something looking at the output and doing something useful with it?
+
+[No Driver Station Packets]
+TODO(brians): This is out of date.
+Check to make sure that JSR (a cRIO-side task) is saying that it's sending
+  messages. Also check JoystickReader (or whatever inherits from
+  aos::JoystickInput) is running and see if it's receiving anything.
+
+[Attaching a Debugger]
+Attaching GDB to an existing robot code process works like normal (you have to
+  su root first because that's what all of the code currently runs as).
+If a process is dying repeatedly, the easiest way to debug it is to kill
+  starter_loop.sh and (it has to be after that) starter_exe. After doing that,
+  NOTHING will get restarted (including the normal restart after changing a
+  binary) so that you can start a process under GDB like usual (shouldn't need
+  anything special if done as root).
diff --git a/aos/common/die.cc b/aos/common/die.cc
new file mode 100644
index 0000000..69b2aef
--- /dev/null
+++ b/aos/common/die.cc
@@ -0,0 +1,85 @@
+#include "aos/common/die.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <stdint.h>
+
+#include <string>
+#include <atomic>
+
+namespace aos {
+
+void Die(const char *format, ...) {
+  va_list args;
+  va_start(args, format);
+  VDie(format, args);
+  // va_end(args)  // not because VDie never returns
+}
+
+namespace {
+
+// Calculates the filename to dump the message into.
+const std::string GetFilename() {
+#ifdef __VXWORKS__
+  const char *name = taskName(0);  // get the name of this task
+  if (name == NULL) name = "<unknown>";
+  const std::string first_part = "/aos_fatal_error.";
+  return first_part + std::string(name);
+#else
+  char *filename;
+  if (asprintf(&filename, "/tmp/aos_fatal_error.%jd",
+               static_cast<intmax_t>(getpid())) > 0) {
+    std::string r(filename);
+    free(filename);
+    return r;
+  } else {
+    fprintf(stderr, "aos fatal: asprintf(%p, \"thingie with %%jd\", %jd)"
+            " failed with %d\n", &filename,
+            static_cast<intmax_t>(getpid()), errno);
+    return std::string();
+  }
+#endif
+}
+
+::std::atomic_bool test_mode(false);
+
+}  // namespace
+
+void VDie(const char *format, va_list args_in) {
+  // We don't bother va_ending either of these because we're going nowhere and
+  // vxworks has some weird bugs that sometimes show up...
+  va_list args1, args2;
+
+  fputs("aos fatal: ERROR!! details following\n", stderr);
+  va_copy(args1, args_in);
+  vfprintf(stderr, format, args1);
+  if (!test_mode.load()) {
+    fputs("aos fatal: ERROR!! see stderr for details\n", stdout);
+
+    const std::string filename = GetFilename();
+    if (!filename.empty()) {
+      FILE *error_file = fopen(filename.c_str(), "w");
+      if (error_file != NULL) {
+        va_copy(args2, args_in);
+        vfprintf(error_file, format, args2);
+        fclose(error_file);
+      } else {
+        fprintf(stderr, "aos fatal: fopen('%s', \"w\") failed with %d\n",
+                filename.c_str(), errno);
+      }
+    }
+  }
+
+  abort();
+}
+
+void SetDieTestMode(bool new_test_mode) {
+  test_mode.store(new_test_mode);
+}
+
+}  // namespace aos
diff --git a/aos/common/die.h b/aos/common/die.h
new file mode 100644
index 0000000..f9ff457
--- /dev/null
+++ b/aos/common/die.h
@@ -0,0 +1,51 @@
+#ifndef AOS_COMMON_DIE_H_
+#define AOS_COMMON_DIE_H_
+
+#include <stdarg.h>
+
+#include "aos/common/macros.h"
+#include "aos/common/libc/aos_strerror.h"
+
+namespace aos {
+
+// Terminates the task/process and logs a message (without using the logging
+// framework). Designed for use in code that can't use the logging framework
+// (code that can should LOG(FATAL), which calls this).
+void Die(const char *format, ...)
+    __attribute__((noreturn))
+    __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 1, 2)));
+void VDie(const char *format, va_list args)
+    __attribute__((noreturn))
+    __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 1, 0)));
+
+
+// The same as Die except appends " because of %d (%s)" (formatted with errno
+// and aos_strerror(errno)) to the message.
+#define PDie(format, args...)                               \
+  do {                                                      \
+    const int error = errno;                                \
+    ::aos::Die(format " because of %d (%s)", ##args, error, \
+               aos_strerror(error));                        \
+  } while (false)
+
+// The same as Die except appends " because of %d (%s)" (formatted with error
+// and aos_strerror(error)) to the message.
+// PCHECK is to PDie as PRCHECK is to PRDie
+//
+// Example:
+// const int ret = pthread_mutex_lock(whatever);
+// if (ret != 0) PRDie(ret, "pthread_mutex_lock(%p) failed", whatever);
+#define PRDie(error, format, args...)                       \
+  do {                                                      \
+    ::aos::Die(format " because of %d (%s)", ##args, error, \
+               aos_strerror(error));                        \
+  } while (false)
+
+// Turns on (or off) "test mode", where (V)Die doesn't write out files and
+// doesn't print to stdout.
+// Test mode defaults to false.
+void SetDieTestMode(bool test_mode);
+
+}  // namespace aos
+
+#endif  // AOS_COMMON_DIE_H_
diff --git a/aos/common/die_test.cc b/aos/common/die_test.cc
new file mode 100644
index 0000000..687543c
--- /dev/null
+++ b/aos/common/die_test.cc
@@ -0,0 +1,14 @@
+#include "aos/common/die.h"
+
+#include "gtest/gtest.h"
+
+namespace aos {
+namespace testing {
+
+TEST(DieDeathTest, Works) {
+  EXPECT_EXIT(Die("str=%s num=%d\n", "hi", 5),
+              ::testing::KilledBySignal(SIGABRT), ".*str=hi num=5\n");
+}
+
+}  // namespace testing
+}  // namespace aos
diff --git a/aos/common/event.h b/aos/common/event.h
new file mode 100644
index 0000000..9839d41
--- /dev/null
+++ b/aos/common/event.h
@@ -0,0 +1,53 @@
+#ifndef AOS_COMMON_EVENT_H_
+#define AOS_COMMON_EVENT_H_
+
+#include "aos/linux_code/ipc_lib/aos_sync.h"
+
+namespace aos {
+
+// An abstraction of an event which is easy to implement for Linux and in other
+// environments.
+// On Linux at least, this is definitely safe for passing through C code with
+// memcpy etc.
+//
+// An event is either "set" or "unset". Any thread can transition it between
+// these two states and other threads can wait for an unset->set transition.
+// This is not a particularly powerful synchronization primitive, but it can be
+// much easier to use than more complicated ones in some situations. The name is
+// taken from Python's implementation of the same thing.
+//
+// An event is equivalent to a semaphore which is either set to 0 or infinity.
+// It is also equivalent to a condition variable with the monitored condition
+// being "is it set or not".
+//
+// IMPORTANT: You can NOT use this to successfully replace a standard condition
+// variable in most cases. When the condition being monitored changes separately
+// from the actual state of the condition variable/event, there WILL be race
+// conditions if you try to use this class.
+//
+// It is undefined behavior to destroy an Event while there are current
+// Wait()ers.
+class Event {
+ public:
+  // Creates an unset event.
+  Event();
+  // There must be no waiters when an Event is destroyed.
+  ~Event() = default;
+
+  // Waits for the event to be set. Returns immediately if it is already set.
+  void Wait();
+
+  // Wakes up all Wait()ers and sets the event (atomically).
+  void Set();
+  // Unsets the event so future Wait() callers will block instead of returning
+  // immediately.
+  // Returns true if the event was previously set.
+  bool Clear();
+
+ private:
+  aos_futex impl_;
+};
+
+}  // namespace aos
+
+#endif  // AOS_COMMON_EVENT_H_
diff --git a/aos/common/event_test.cc b/aos/common/event_test.cc
new file mode 100644
index 0000000..d8671eb
--- /dev/null
+++ b/aos/common/event_test.cc
@@ -0,0 +1,71 @@
+#include "aos/common/event.h"
+
+#include <thread>
+
+#include "gtest/gtest.h"
+
+#include "aos/common/queue_testutils.h"
+#include "aos/common/time.h"
+
+namespace aos {
+namespace testing {
+
+class EventTest : public ::testing::Test {
+ public:
+  Event test_event;
+
+ protected:
+  void SetUp() override {
+    ::aos::common::testing::EnableTestLogging();
+  }
+};
+
+// Makes sure that basic operations with no blocking or anything work.
+TEST_F(EventTest, Basic) {
+  EXPECT_FALSE(test_event.Clear());
+  EXPECT_FALSE(test_event.Clear());
+
+  test_event.Set();
+  test_event.Wait();
+  EXPECT_TRUE(test_event.Clear());
+  EXPECT_FALSE(test_event.Clear());
+}
+
+// Tests that tsan understands that events establish a happens-before
+// relationship.
+TEST_F(EventTest, ThreadSanitizer) {
+  for (int i = 0; i < 3000; ++i) {
+    int variable = 0;
+    test_event.Clear();
+    ::std::thread thread([this, &variable]() {
+      test_event.Wait();
+      --variable;
+    });
+    ++variable;
+    test_event.Set();
+    thread.join();
+    EXPECT_EQ(0, variable);
+  }
+}
+
+// Tests that an event blocks correctly.
+TEST_F(EventTest, Blocks) {
+  time::Time start_time, finish_time;
+  // Without this, it sometimes manages to fail under tsan.
+  Event started;
+  ::std::thread thread([this, &start_time, &finish_time, &started]() {
+    start_time = time::Time::Now();
+    started.Set();
+    test_event.Wait();
+    finish_time = time::Time::Now();
+  });
+  static const time::Time kWaitTime = time::Time::InSeconds(0.05);
+  started.Wait();
+  time::SleepFor(kWaitTime);
+  test_event.Set();
+  thread.join();
+  EXPECT_GE(finish_time - start_time, kWaitTime);
+}
+
+}  // namespace testing
+}  // namespace aos
diff --git a/aos/common/gtest_prod.h b/aos/common/gtest_prod.h
new file mode 100644
index 0000000..fe0b056
--- /dev/null
+++ b/aos/common/gtest_prod.h
@@ -0,0 +1,37 @@
+#ifndef AOS_COMMON_GTEST_PROD_H_
+#define AOS_COMMON_GTEST_PROD_H_
+
+#include "gtest/gtest_prod.h"
+
+// These macros replace gtest's FRIEND_TEST if the test is in a different
+// namespace than the code that needs to make it a friend.
+// Example:
+//  foo.h:
+//   namespace bla {
+//   namespace testing {
+//
+//   FORWARD_DECLARE_TEST_CASE(FooTest, Bar);
+//
+//   }  // namespace testing
+//
+//   class Foo {
+//     FRIEND_TEST_NAMESPACE(FooTest, Bar, testing);
+//   };
+//
+//   }  // namespace bla
+//  foo_test.cc:
+//   namespace bla {
+//   namespace testing {
+//
+//   TEST(FooTest, Bar) {
+//     access private members of Foo
+//   }
+//
+//   }  // namespace testing
+//   }  // namespace bla
+#define FORWARD_DECLARE_TEST_CASE(test_case_name, test_name) \
+    class test_case_name##_##test_name##_Test;
+#define FRIEND_TEST_NAMESPACE(test_case_name, test_name, namespace_name) \
+    friend class namespace_name::test_case_name##_##test_name##_Test
+
+#endif  // AOS_COMMON_GTEST_PROD_H_
diff --git a/aos/common/input/driver_station_data.cc b/aos/common/input/driver_station_data.cc
new file mode 100644
index 0000000..2df98be
--- /dev/null
+++ b/aos/common/input/driver_station_data.cc
@@ -0,0 +1,100 @@
+#include "aos/common/input/driver_station_data.h"
+
+namespace aos {
+namespace input {
+namespace driver_station {
+
+Data::Data() : current_values_(), old_values_() {}
+
+void Data::Update(const JoystickState &new_values) {
+  old_values_ = current_values_;
+  current_values_ = new_values;
+}
+
+namespace {
+
+bool GetButton(const ButtonLocation location,
+               const JoystickState &values) {
+  return values.joysticks[location.joystick() - 1].buttons &
+      (1 << (location.number() - 1));
+}
+
+bool DoGetPOV(const POVLocation location, const JoystickState &values) {
+  return values.joysticks[location.joystick() - 1].pov == location.number();
+}
+
+bool GetControlBitValue(const ControlBit bit,
+                        const JoystickState &values) {
+  switch (bit) {
+    case ControlBit::kTestMode:
+      return values.test_mode;
+    case ControlBit::kFmsAttached:
+      return values.fms_attached;
+    case ControlBit::kAutonomous:
+      return values.autonomous;
+    case ControlBit::kEnabled:
+      return values.enabled;
+    default:
+      __builtin_unreachable();
+  }
+}
+
+}  // namespace
+
+bool Data::IsPressed(const ButtonLocation location) const {
+  return GetButton(location, current_values_);
+}
+
+bool Data::PosEdge(const ButtonLocation location) const {
+  return !GetButton(location, old_values_) &&
+      GetButton(location, current_values_);
+}
+
+bool Data::NegEdge(const ButtonLocation location) const {
+  return GetButton(location, old_values_) &&
+      !GetButton(location, current_values_);
+}
+
+bool Data::IsPressed(const POVLocation location) const {
+  return DoGetPOV(location, current_values_);
+}
+
+bool Data::PosEdge(const POVLocation location) const {
+  return !DoGetPOV(location, old_values_) &&
+         DoGetPOV(location, current_values_);
+}
+
+bool Data::NegEdge(const POVLocation location) const {
+  return DoGetPOV(location, old_values_) &&
+         !DoGetPOV(location, current_values_);
+}
+
+int32_t Data::GetPOV(int joystick) const {
+  return current_values_.joysticks[joystick - 1].pov;
+}
+
+int32_t Data::GetOldPOV(int joystick) const {
+  return old_values_.joysticks[joystick - 1].pov;
+}
+
+bool Data::GetControlBit(const ControlBit bit) const {
+  return GetControlBitValue(bit, current_values_);
+}
+
+bool Data::PosEdge(const ControlBit bit) const {
+  return !GetControlBitValue(bit, old_values_) &&
+      GetControlBitValue(bit, current_values_);
+}
+
+bool Data::NegEdge(const ControlBit bit) const {
+  return GetControlBitValue(bit, old_values_) &&
+      !GetControlBitValue(bit, current_values_);
+}
+
+float Data::GetAxis(JoystickAxis axis) const {
+  return current_values_.joysticks[axis.joystick() - 1].axis[axis.number() - 1];
+}
+
+}  // namespace driver_station
+}  // namespace input
+}  // namespace aos
diff --git a/aos/common/input/driver_station_data.h b/aos/common/input/driver_station_data.h
new file mode 100644
index 0000000..507ad61
--- /dev/null
+++ b/aos/common/input/driver_station_data.h
@@ -0,0 +1,111 @@
+#ifndef AOS_COMMON_INPUT_DRIVER_STATION_DATA_H_
+#define AOS_COMMON_INPUT_DRIVER_STATION_DATA_H_
+
+// This file defines several types to support nicely looking at the data
+// received from the driver's station.
+
+#include <memory>
+
+#include "aos/common/messages/robot_state.q.h"
+
+namespace aos {
+namespace input {
+namespace driver_station {
+
+// Represents a feature of a joystick (a button or an axis).
+// All indices are 1-based.
+class JoystickFeature {
+ public:
+  JoystickFeature(int joystick, int number)
+      : joystick_(joystick), number_(number) {}
+
+  // How many joysticks there are.
+  static const int kJoysticks = sizeof(JoystickState::joysticks) /
+                                sizeof(JoystickState::joysticks[0]);
+
+  // Which joystick number this is (1-based).
+  int joystick() const { return joystick_; }
+  // Which feature on joystick() this is (1-based).
+  int number() const { return number_; }
+
+ private:
+  const int joystick_, number_;
+};
+
+// Represents the location of a button.
+// Use Data to actually get the value.
+// Safe for static initialization.
+class ButtonLocation : public JoystickFeature {
+ public:
+  ButtonLocation(int joystick, int number)
+      : JoystickFeature(joystick, number) {}
+
+  // How many buttons there are available on each joystick.
+  static const int kButtons = 12;
+};
+
+// Represents the direction of a POV on a joystick.
+// Use Data to actually get the value.
+// Safe for static initialization.
+class POVLocation : public JoystickFeature {
+ public:
+  POVLocation(int joystick, int number)
+      : JoystickFeature(joystick, number) {}
+};
+
+// Represents various bits of control information that the DS sends.
+// Use Data to actually get the value.
+enum class ControlBit {
+  kTestMode, kFmsAttached, kAutonomous, kEnabled
+};
+
+// Represents a single axis of a joystick.
+// Use Data to actually get the value.
+// Safe for static initialization.
+class JoystickAxis : public JoystickFeature {
+ public:
+  JoystickAxis(int joystick, int number)
+      : JoystickFeature(joystick, number) {}
+
+  // How many axes there are available on each joystick.
+  static const int kAxes = sizeof(Joystick::axis) /
+                           sizeof(Joystick::axis[0]);
+};
+
+class Data {
+ public:
+  // Initializes the data to all buttons and control bits off and all joysticks
+  // at 0.
+  Data();
+
+  // Updates the current information with a new set of values.
+  void Update(const JoystickState &new_values);
+
+  bool IsPressed(POVLocation location) const;
+  bool PosEdge(POVLocation location) const;
+  bool NegEdge(POVLocation location) const;
+
+  // Returns the current and previous "values" for the POV.
+  int32_t GetPOV(int joystick) const;
+  int32_t GetOldPOV(int joystick) const;
+
+  bool IsPressed(ButtonLocation location) const;
+  bool PosEdge(ButtonLocation location) const;
+  bool NegEdge(ButtonLocation location) const;
+
+  bool GetControlBit(ControlBit bit) const;
+  bool PosEdge(ControlBit bit) const;
+  bool NegEdge(ControlBit bit) const;
+
+  // Returns the value in the range [-1.0, 1.0].
+  float GetAxis(JoystickAxis axis) const;
+
+ private:
+  JoystickState current_values_, old_values_;
+};
+
+}  // namespace driver_station
+}  // namespace input
+}  // namespace aos
+
+#endif  // AOS_COMMON_INPUT_DRIVER_STATION_DATA_H_
diff --git a/aos/common/input/input.gyp b/aos/common/input/input.gyp
new file mode 100644
index 0000000..5674ce7
--- /dev/null
+++ b/aos/common/input/input.gyp
@@ -0,0 +1,17 @@
+{
+  'targets': [
+    {
+      'target_name': 'driver_station_data',
+      'type': 'static_library',
+      'sources': [
+        'driver_station_data.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/common/messages/messages.gyp:robot_state',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/messages/messages.gyp:robot_state',
+      ],
+    },
+  ],
+}
diff --git a/aos/common/libc/README b/aos/common/libc/README
new file mode 100644
index 0000000..c4ee817
--- /dev/null
+++ b/aos/common/libc/README
@@ -0,0 +1,18 @@
+This directory has replacements for some libc functions that we don't want to
+use because they're not thread-safe and/or they allocate memory.
+
+Some of them are implemented as C++ functions because it makes fixing the
+memory management issues that cause the standard versions to be not thread-safe
+possible and some of them are still callable from C when it makes sense.
+
+<http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_09_01>
+has a list of the not-thread-safe POSIX functions. We've gotten rid of all of
+those except for the following:
+  getenv(3): <http://austingroupbugs.net/view.php?id=188> proposes changing
+    POSIX to require it to return a pointer into environ, making it thread-safe,
+    which glibc already does.
+  inet_ntoa(3): Glibc uses a thread-local buffer, which makes it thread-safe,
+    and uses of this function should go away soon.
+  readdir(3): Glibc already guarantees that only invocations on the same
+    directory stream aren't thread-safe, and there's talk of changing POSIX to
+    say the same thing.
diff --git a/aos/common/libc/aos_strerror.cc b/aos/common/libc/aos_strerror.cc
new file mode 100644
index 0000000..2c9735d
--- /dev/null
+++ b/aos/common/libc/aos_strerror.cc
@@ -0,0 +1,41 @@
+#include "aos/common/libc/aos_strerror.h"
+
+#include <assert.h>
+#include <sys/types.h>
+#include <string.h>
+#include <stdio.h>
+
+// This code uses an overloaded function to handle the result from either
+// version of strerror_r correctly without needing a way to get the choice out
+// of the compiler/glibc/whatever explicitly.
+
+namespace {
+
+const size_t kBufferSize = 128;
+
+// Handle the result from the GNU version of strerror_r. It never fails, so
+// that's pretty easy...
+__attribute__((unused))
+char *aos_strerror_handle_result(int /*error*/, char *ret, char * /*buffer*/) {
+  return ret;
+}
+
+// Handle the result from the POSIX version of strerror_r.
+__attribute__((unused))
+char *aos_strerror_handle_result(int error, int ret, char *buffer) {
+  if (ret != 0) {
+    const int r = snprintf(buffer, kBufferSize, "Unknown error %d", error);
+    assert(r > 0);
+  }
+  return buffer;
+}
+
+}  // namespace
+
+const char *aos_strerror(int error) {
+  static thread_local char buffer[kBufferSize];
+
+  // Call the overload for whichever version we're using.
+  return aos_strerror_handle_result(
+      error, strerror_r(error, buffer, sizeof(buffer)), buffer);
+}
diff --git a/aos/common/libc/aos_strerror.h b/aos/common/libc/aos_strerror.h
new file mode 100644
index 0000000..acce427
--- /dev/null
+++ b/aos/common/libc/aos_strerror.h
@@ -0,0 +1,23 @@
+#ifndef AOS_COMMON_LIBC_AOS_STRERROR_H_
+#define AOS_COMMON_LIBC_AOS_STRERROR_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Thread-safe version of strerror(3) (except it may change errno).
+//
+// Returns a pointer to static data or a thread-local buffer.
+//
+// Necessary because strerror_r(3) is such a mess (which version you get is
+// determined at compile time by black magic related to feature macro
+// definitions, compiler flags, glibc version, and even whether you're using g++
+// or clang++) and strerror_l(3) might not work if you end up with the magic
+// LC_GLOBAL_LOCALE locale.
+const char *aos_strerror(int error);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // AOS_COMMON_LIBC_AOS_STRERROR_H_
diff --git a/aos/common/libc/aos_strerror_test.cc b/aos/common/libc/aos_strerror_test.cc
new file mode 100644
index 0000000..c4574fe
--- /dev/null
+++ b/aos/common/libc/aos_strerror_test.cc
@@ -0,0 +1,29 @@
+#include "aos/common/libc/aos_strerror.h"
+
+#include <errno.h>
+
+#include "gtest/gtest.h"
+
+namespace aos {
+namespace libc {
+namespace testing {
+
+// Tries a couple of easy ones.
+TEST(StrerrorTest, Basic) {
+  EXPECT_STREQ("Argument list too long", aos_strerror(E2BIG));
+  EXPECT_STREQ("Bad file descriptor", aos_strerror(EBADF));
+  EXPECT_STREQ("Unknown error 4021", aos_strerror(4021));
+}
+
+// Runs through all errno values and makes sure it gives the same result as
+// strerror(3).
+TEST(StrerrorTest, All) {
+  for (int i = 0; i < 4095; ++i) {
+    SCOPED_TRACE("iteration " + ::std::to_string(i));
+    EXPECT_STREQ(strerror(i), aos_strerror(i));
+  }
+}
+
+}  // namespace testing
+}  // namespace libc
+}  // namespace aos
diff --git a/aos/common/libc/aos_strsignal.cc b/aos/common/libc/aos_strsignal.cc
new file mode 100644
index 0000000..2321a07
--- /dev/null
+++ b/aos/common/libc/aos_strsignal.cc
@@ -0,0 +1,22 @@
+#include "aos/common/libc/aos_strsignal.h"
+
+#include <signal.h>
+
+#include "aos/common/logging/logging.h"
+
+const char *aos_strsignal(int signal) {
+  static thread_local char buffer[512];
+
+  if (signal >= SIGRTMIN && signal <= SIGRTMAX) {
+    CHECK(snprintf(buffer, sizeof(buffer), "Real-time signal %d",
+                   signal - SIGRTMIN) > 0);
+    return buffer;
+  }
+
+  if (signal > 0 && signal < NSIG && sys_siglist[signal] != nullptr) {
+    return sys_siglist[signal];
+  }
+
+  CHECK(snprintf(buffer, sizeof(buffer), "Unknown signal %d", signal) > 0);
+  return buffer;
+}
diff --git a/aos/common/libc/aos_strsignal.h b/aos/common/libc/aos_strsignal.h
new file mode 100644
index 0000000..ef6795c
--- /dev/null
+++ b/aos/common/libc/aos_strsignal.h
@@ -0,0 +1,17 @@
+#ifndef AOS_COMMON_LIBC_AOS_STRSIGNAL_H_
+#define AOS_COMMON_LIBC_AOS_STRSIGNAL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Thread-safe version of strsignal(3) (except it will never return NULL).
+//
+// Returns a pointer to static data or a thread-local buffer.
+const char *aos_strsignal(int signal);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // AOS_COMMON_LIBC_AOS_STRSIGNAL_H_
diff --git a/aos/common/libc/aos_strsignal_test.cc b/aos/common/libc/aos_strsignal_test.cc
new file mode 100644
index 0000000..3d90b21
--- /dev/null
+++ b/aos/common/libc/aos_strsignal_test.cc
@@ -0,0 +1,47 @@
+#include "aos/common/libc/aos_strsignal.h"
+
+#include <signal.h>
+#include <thread>
+
+#include "gtest/gtest.h"
+
+namespace aos {
+namespace libc {
+namespace testing {
+
+// Tries a couple of easy ones.
+TEST(StrsignalTest, Basic) {
+  EXPECT_STREQ("Hangup", aos_strsignal(SIGHUP));
+  EXPECT_STREQ("Broken pipe", aos_strsignal(SIGPIPE));
+  EXPECT_STREQ("Real-time signal 2", aos_strsignal(SIGRTMIN + 2));
+  EXPECT_STREQ("Unknown signal 155", aos_strsignal(155));
+}
+
+class SignalNameTester {
+ public:
+  void operator()() {
+    for (int i = 0; i < SIGRTMAX + 5; ++i) {
+      EXPECT_STREQ(strsignal(i), aos_strsignal(i));
+    }
+  }
+};
+
+// Tests that all the signals give the same result as strsignal(3).
+TEST(StrsignalTest, All) {
+  // Sigh, strsignal allocates a buffer that uses pthread local storage.  This
+  // interacts poorly with asan.  Spawning a thread causes the storage to get
+  // cleaned up before asan checks.
+  SignalNameTester t;
+#ifdef AOS_SANITIZER_thread
+  // tsan doesn't like this usage of ::std::thread. It looks like
+  // <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57507>.
+  t();
+#else
+  ::std::thread thread(::std::ref(t));
+  thread.join();
+#endif
+}
+
+}  // namespace testing
+}  // namespace libc
+}  // namespace aos
diff --git a/aos/common/libc/dirname.cc b/aos/common/libc/dirname.cc
new file mode 100644
index 0000000..c843898
--- /dev/null
+++ b/aos/common/libc/dirname.cc
@@ -0,0 +1,39 @@
+#include "aos/common/libc/dirname.h"
+
+namespace aos {
+namespace libc {
+namespace {
+
+::std::string DoDirname(const ::std::string &path, size_t last_slash) {
+  // If there aren't any other '/'s in it.
+  if (last_slash == ::std::string::npos) return ".";
+
+  // Back up as long as we see '/'s.
+  do {
+    // If we get all the way to the beginning.
+    if (last_slash == 0) return "/";
+    --last_slash;
+  } while (path[last_slash] == '/');
+
+  return path.substr(0, last_slash + 1);
+}
+
+}  // namespace
+
+::std::string Dirname(const ::std::string &path) {
+  // Without this, we end up with integer underflows below, which is technically
+  // undefined.
+  if (path.size() == 0) return ".";
+
+  size_t last_slash = path.rfind('/');
+
+  // If the path ends with a '/'.
+  if (last_slash == path.size() - 1) {
+    last_slash = DoDirname(path, last_slash).rfind('/');
+  }
+
+  return DoDirname(path, last_slash);
+}
+
+}  // namespace libc
+}  // namespace aos
diff --git a/aos/common/libc/dirname.h b/aos/common/libc/dirname.h
new file mode 100644
index 0000000..f05f8f1
--- /dev/null
+++ b/aos/common/libc/dirname.h
@@ -0,0 +1,15 @@
+#ifndef AOS_COMMON_LIBC_DIRNAME_H_
+#define AOS_COMMON_LIBC_DIRNAME_H_
+
+#include <string>
+
+namespace aos {
+namespace libc {
+
+// Thread-safe version of dirname(3).
+::std::string Dirname(const ::std::string &path);
+
+}  // namespace libc
+}  // namespace aos
+
+#endif  // AOS_COMMON_LIBC_DIRNAME_H_
diff --git a/aos/common/libc/dirname_test.cc b/aos/common/libc/dirname_test.cc
new file mode 100644
index 0000000..0207961
--- /dev/null
+++ b/aos/common/libc/dirname_test.cc
@@ -0,0 +1,79 @@
+#include "aos/common/libc/dirname.h"
+
+#include <libgen.h>
+
+#include "gtest/gtest.h"
+
+namespace aos {
+namespace libc {
+namespace testing {
+
+// Tests the examples from the Linux man-pages release 3.44 dirname(3).
+TEST(DirnameTest, ManPageExamples) {
+  EXPECT_EQ("/usr", Dirname("/usr/lib"));
+  EXPECT_EQ("/", Dirname("/usr/"));
+  EXPECT_EQ(".", Dirname("usr"));
+  EXPECT_EQ("/", Dirname("/"));
+  EXPECT_EQ(".", Dirname("."));
+  EXPECT_EQ(".", Dirname(".."));
+}
+
+// Tests that it handles multiple '/'s in a row correctly.
+TEST(DirnameTest, MultipleSlashes) {
+  EXPECT_EQ("//usr", Dirname("//usr//lib"));
+  EXPECT_EQ("//usr/lib", Dirname("//usr/lib//bla"));
+  EXPECT_EQ("/", Dirname("//usr//"));
+  EXPECT_EQ(".", Dirname("usr//"));
+  EXPECT_EQ("/", Dirname("//"));
+  EXPECT_EQ(".", Dirname(".//"));
+  EXPECT_EQ(".", Dirname("..//"));
+}
+
+TEST(DirnameTest, WeirdInputs) {
+  EXPECT_EQ(".", Dirname(""));
+  EXPECT_EQ(".", Dirname("..."));
+}
+
+// Runs through a bunch of randomly constructed pathnames and makes sure it
+// gives the same result as dirname(3).
+TEST(DirnameTest, Random) {
+  static const char kTestBytes[] = "a0//.. ";
+  static const size_t kTestBytesSize = sizeof(kTestBytes) - 1;
+  static const size_t kTestPathSize = 6;
+
+  ::std::string test_string(kTestPathSize, '\0');
+  char test_path[kTestPathSize + 1];
+  for (size_t i0 = 0; i0 < kTestBytesSize; ++i0) {
+    test_string[0] = kTestBytes[i0];
+    for (size_t i1 = 0; i1 < kTestBytesSize; ++i1) {
+      // dirname(3) returns "//" in this case which is weird and our Dirname
+      // doesn't.
+      if (test_string[0] == '/' && kTestBytes[i1] == '/') continue;
+
+      test_string[1] = kTestBytes[i1];
+      for (size_t i2 = 0; i2 < kTestBytesSize; ++i2) {
+        test_string[2] = kTestBytes[i2];
+        for (size_t i3 = 0; i3 < kTestBytesSize; ++i3) {
+          test_string[3] = kTestBytes[i3];
+          for (size_t i4 = 0; i4 < kTestBytesSize; ++i4) {
+            test_string[4] = kTestBytes[i4];
+            for (size_t i5 = 0; i5 < kTestBytesSize; ++i5) {
+              test_string[5] = kTestBytes[i5];
+
+              memcpy(test_path, test_string.c_str(), kTestPathSize);
+              test_path[kTestPathSize] = '\0';
+
+              SCOPED_TRACE("path is '" + test_string + "'");
+              EXPECT_EQ(::std::string(dirname(test_path)),
+                        Dirname(test_string));
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+}  // namespace testing
+}  // namespace libc
+}  // namespace aos
diff --git a/aos/common/libc/libc.gyp b/aos/common/libc/libc.gyp
new file mode 100644
index 0000000..d7fc357
--- /dev/null
+++ b/aos/common/libc/libc.gyp
@@ -0,0 +1,62 @@
+{
+  'targets': [
+    {
+      'target_name': 'aos_strsignal',
+      'type': 'static_library',
+      'sources': [
+        'aos_strsignal.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/build/aos.gyp:logging_interface',
+      ],
+    },
+    {
+      'target_name': 'aos_strsignal_test',
+      'type': 'executable',
+      'sources': [
+        'aos_strsignal_test.cc',
+      ],
+      'dependencies': [
+        'aos_strsignal',
+        '<(EXTERNALS):gtest',
+        '<(AOS)/build/aos.gyp:logging',
+      ],
+    },
+    {
+      'target_name': 'dirname',
+      'type': 'static_library',
+      'sources': [
+        'dirname.cc',
+      ],
+    },
+    {
+      'target_name': 'dirname_test',
+      'type': 'executable',
+      'sources': [
+        'dirname_test.cc',
+      ],
+      'dependencies': [
+        'dirname',
+        '<(EXTERNALS):gtest',
+      ],
+    },
+    {
+      'target_name': 'aos_strerror',
+      'type': 'static_library',
+      'sources': [
+        'aos_strerror.cc',
+      ],
+    },
+    {
+      'target_name': 'aos_strerror_test',
+      'type': 'executable',
+      'sources': [
+        'aos_strerror_test.cc',
+      ],
+      'dependencies': [
+        'aos_strerror',
+        '<(EXTERNALS):gtest',
+      ],
+    },
+  ],
+}
diff --git a/aos/common/logging/logging.gyp b/aos/common/logging/logging.gyp
new file mode 100644
index 0000000..36d58b7
--- /dev/null
+++ b/aos/common/logging/logging.gyp
@@ -0,0 +1,50 @@
+{
+  'targets': [
+    {
+      'target_name': 'logging_impl_test',
+      'type': 'executable',
+      'sources': [
+        'logging_impl_test.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+        '<(AOS)/build/aos.gyp:logging',
+      ],
+    },
+    {
+      'target_name': 'queue_logging',
+      'type': 'static_library',
+      'sources': [
+        'queue_logging.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/common.gyp:die',
+        '<(AOS)/common/common.gyp:queue_types',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/common.gyp:die',
+      ],
+    },
+    {
+      'target_name': 'matrix_logging',
+      'type': 'static_library',
+      'sources': [
+        'matrix_logging.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/common.gyp:die',
+        '<(AOS)/common/common.gyp:queue_types',
+        '<(EXTERNALS):eigen',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/common.gyp:die',
+        '<(AOS)/common/common.gyp:queue_types',
+        '<(EXTERNALS):eigen',
+      ],
+    },
+  ],
+}
diff --git a/aos/common/logging/logging.h b/aos/common/logging/logging.h
new file mode 100644
index 0000000..66b88c7
--- /dev/null
+++ b/aos/common/logging/logging.h
@@ -0,0 +1,261 @@
+#ifndef AOS_COMMON_LOGGING_LOGGING_H_
+#define AOS_COMMON_LOGGING_LOGGING_H_
+
+// This file contains the logging client interface. It works with both C and C++
+// code.
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "aos/common/macros.h"
+#include "aos/common/libc/aos_strerror.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef uint8_t log_level;
+
+#define DECL_LEVELS \
+DECL_LEVEL(DEBUG, 0); /* stuff that gets printed out every cycle */ \
+DECL_LEVEL(INFO, 1); /* things like PosEdge/NegEdge */ \
+/* things that might still work if they happen occasionally */ \
+DECL_LEVEL(WARNING, 2); \
+/*-1 so that vxworks macro of same name will have same effect if used*/ \
+DECL_LEVEL(ERROR, -1); /* errors */ \
+/* serious errors. the logging code will terminate the process/task */ \
+DECL_LEVEL(FATAL, 4); \
+DECL_LEVEL(LOG_UNKNOWN, 5); /* unknown logging level */
+#define DECL_LEVEL(name, value) static const log_level name = value;
+DECL_LEVELS;
+#undef DECL_LEVEL
+
+// Not static const size_t for C code.
+#define LOG_MESSAGE_LEN 400
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Actually implements the basic logging call.
+// Does not check that level is valid.
+void log_do(log_level level, const char *format, ...)
+  __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 2, 3)));
+
+void log_cork(int line, const char *function, const char *format, ...)
+  __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 4)));
+// Implements the uncork logging call.
+void log_uncork(int line, const char *function, log_level level,
+                const char *file, const char *format, ...)
+  __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 5, 6)));
+
+#ifdef __cplusplus
+}
+#endif
+
+// A magical static const char[] or string literal that communicates the name
+// of the enclosing function.
+// It's currently using __PRETTY_FUNCTION__ because both GCC and Clang support
+// that and it gives nicer results in C++ than the standard __func__ (which
+// would also work).
+//#define LOG_CURRENT_FUNCTION __PRETTY_FUNCTION__
+#define LOG_CURRENT_FUNCTION __func__
+
+#define LOG_SOURCENAME __FILE__
+
+// The basic logging call.
+#define LOG(level, format, args...)                                        \
+  do {                                                                     \
+    log_do(level, LOG_SOURCENAME ": " STRINGIFY(__LINE__) ": %s: " format, \
+           LOG_CURRENT_FUNCTION, ##args);                                  \
+    /* so that GCC knows that it won't return */                           \
+    if (level == FATAL) {                                                  \
+      fprintf(stderr, "log_do(FATAL) fell through!!!!!\n");                \
+      printf("see stderr\n");                                              \
+      abort();                                                             \
+    }                                                                      \
+  } while (0)
+
+// Same as LOG except appends " due to %d (%s)\n" (formatted with errno and
+// aos_strerror(errno)) to the message.
+#define PLOG(level, format, args...) PELOG(level, errno, format, ##args)
+
+// Like PLOG except allows specifying an error other than errno.
+#define PELOG(level, error_in, format, args...)           \
+  do {                                                    \
+    const int error = error_in;                           \
+    LOG(level, format " due to %d (%s)\n", ##args, error, \
+        aos_strerror(error));                             \
+  } while (0);
+
+// Allows format to not be a string constant.
+#define LOG_DYNAMIC(level, format, args...)                             \
+  do {                                                                  \
+    static char log_buf[LOG_MESSAGE_LEN];                               \
+    int ret = snprintf(log_buf, sizeof(log_buf), format, ##args);       \
+    if (ret < 0 || (uintmax_t)ret >= LOG_MESSAGE_LEN) {                 \
+      LOG(ERROR, "next message was too long so not subbing in args\n"); \
+      LOG(level, "%s", format);                                         \
+    } else {                                                            \
+      LOG(level, "%s", log_buf);                                        \
+    }                                                                   \
+  } while (0)
+
+// Allows "bottling up" multiple log fragments which can then all be logged in
+// one message with LOG_UNCORK.
+// Calls from a given thread/task will be grouped together.
+#define LOG_CORK(format, args...)                             \
+  do {                                                        \
+    log_cork(__LINE__, LOG_CURRENT_FUNCTION, format, ##args); \
+  } while (0)
+// Actually logs all of the saved up log fragments (including format and args on
+// the end).
+#define LOG_UNCORK(level, format, args...)                                    \
+  do {                                                                        \
+    log_uncork(__LINE__, LOG_CURRENT_FUNCTION, level, LOG_SOURCENAME, format, \
+               ##args);                                                       \
+  } while (0)
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef __cplusplus
+
+namespace aos {
+
+// CHECK* macros, similar to glog
+// (<http://google-glog.googlecode.com/svn/trunk/doc/glog.html>)'s, except they
+// don't support streaming in extra text. Some of the implementation is borrowed
+// from there too.
+// They all LOG(FATAL) with a helpful message when the check fails.
+// Portions copyright (c) 1999, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// CHECK dies with a fatal error if condition is not true.  It is *not*
+// controlled by NDEBUG, so the check will be executed regardless of
+// compilation mode.  Therefore, it is safe to do things like:
+//    CHECK(fp->Write(x) == 4)
+#define CHECK(condition)                          \
+  if (__builtin_expect(!(condition), 0)) {        \
+    LOG(FATAL, "CHECK(%s) failed\n", #condition); \
+  }
+
+// Helper functions for CHECK_OP macro.
+// The (int, int) specialization works around the issue that the compiler
+// will not instantiate the template version of the function on values of
+// unnamed enum type.
+#define DEFINE_CHECK_OP_IMPL(name, op)                                       \
+  template <typename T1, typename T2>                                        \
+  inline void LogImpl##name(const T1 &v1, const T2 &v2,                      \
+                            const char *exprtext) {                          \
+    if (!__builtin_expect(v1 op v2, 1)) {                                    \
+      log_do(FATAL,                                                          \
+             LOG_SOURCENAME ": " STRINGIFY(__LINE__) ": CHECK(%s) failed\n", \
+             exprtext);                                                      \
+      fprintf(stderr, "log_do(FATAL) fell through!!!!!\n");                  \
+      printf("see stderr\n");                                                \
+      abort();                                                               \
+    }                                                                        \
+  }                                                                          \
+  inline void LogImpl##name(int v1, int v2, const char *exprtext) {          \
+    ::aos::LogImpl##name<int, int>(v1, v2, exprtext);                        \
+  }
+
+// We use the full name Check_EQ, Check_NE, etc. in case the file including
+// base/logging.h provides its own #defines for the simpler names EQ, NE, etc.
+// This happens if, for example, those are used as token names in a
+// yacc grammar.
+DEFINE_CHECK_OP_IMPL(Check_EQ, ==)  // Compilation error with CHECK_EQ(NULL, x)?
+DEFINE_CHECK_OP_IMPL(Check_NE, !=)  // Use CHECK(x == NULL) instead.
+DEFINE_CHECK_OP_IMPL(Check_LE, <=)
+DEFINE_CHECK_OP_IMPL(Check_LT, < )
+DEFINE_CHECK_OP_IMPL(Check_GE, >=)
+DEFINE_CHECK_OP_IMPL(Check_GT, > )
+
+#define CHECK_OP(name, op, val1, val2)  \
+  ::aos::LogImplCheck##name(val1, val2, \
+                            STRINGIFY(val1) STRINGIFY(op) STRINGIFY(val2))
+
+#define CHECK_EQ(val1, val2) CHECK_OP(_EQ, ==, val1, val2)
+#define CHECK_NE(val1, val2) CHECK_OP(_NE, !=, val1, val2)
+#define CHECK_LE(val1, val2) CHECK_OP(_LE, <=, val1, val2)
+#define CHECK_LT(val1, val2) CHECK_OP(_LT, < , val1, val2)
+#define CHECK_GE(val1, val2) CHECK_OP(_GE, >=, val1, val2)
+#define CHECK_GT(val1, val2) CHECK_OP(_GT, > , val1, val2)
+
+// A small helper for CHECK_NOTNULL().
+template <typename T>
+inline T* CheckNotNull(const char *value_name, T *t) {
+  if (t == NULL) {
+    LOG(FATAL, "'%s' must not be NULL\n", value_name);
+  }
+  return t;
+}
+
+// Check that the input is non NULL.  This very useful in constructor
+// initializer lists.
+#define CHECK_NOTNULL(val) ::aos::CheckNotNull(STRINGIFY(val), val)
+
+inline int CheckSyscall(const char *syscall_string, int value) {
+  if (__builtin_expect(value == -1, false)) {
+    PLOG(FATAL, "%s failed", syscall_string);
+  }
+  return value;
+}
+
+inline void CheckSyscallReturn(const char *syscall_string, int value) {
+  if (__builtin_expect(value != 0, false)) {
+    PELOG(FATAL, value, "%s failed", syscall_string);
+  }
+}
+
+// Check that syscall does not return -1. If it does, PLOG(FATAL)s. This is
+// useful for quickly checking syscalls where it's not very useful to print out
+// the values of any of the arguments. Returns the result otherwise.
+//
+// Example: const int fd = PCHECK(open("/tmp/whatever", O_WRONLY))
+#define PCHECK(syscall) ::aos::CheckSyscall(STRINGIFY(syscall), syscall)
+
+// PELOG(FATAL)s with the result of syscall if it returns anything other than 0.
+// This is useful for quickly checking things like many of the pthreads
+// functions where it's not very useful to print out the values of any of the
+// arguments.
+//
+// Example: PRCHECK(munmap(address, length))
+#define PRCHECK(syscall) ::aos::CheckSyscallReturn(STRINGIFY(syscall), syscall)
+
+}  // namespace aos
+
+#endif  // __cplusplus
+
+#endif
diff --git a/aos/common/logging/logging_impl.cc b/aos/common/logging/logging_impl.cc
new file mode 100644
index 0000000..c776991
--- /dev/null
+++ b/aos/common/logging/logging_impl.cc
@@ -0,0 +1,330 @@
+#include "aos/common/logging/logging_impl.h"
+
+#include <stdarg.h>
+
+#include "aos/common/time.h"
+#include <inttypes.h>
+#include "aos/common/once.h"
+#include "aos/common/queue_types.h"
+#include "aos/common/logging/logging_printf_formats.h"
+
+namespace aos {
+namespace logging {
+namespace {
+
+using internal::Context;
+using internal::global_top_implementation;
+
+// The root LogImplementation. It only logs to stderr/stdout.
+// Some of the things specified in the LogImplementation documentation doesn't
+// apply here (mostly the parts about being able to use LOG) because this is the
+// root one.
+class RootLogImplementation : public LogImplementation {
+ public:
+  void have_other_implementation() { only_implementation_ = false; }
+
+ private:
+  virtual void set_next(LogImplementation *) {
+    LOG(FATAL, "can't have a next logger from here\n");
+  }
+
+  __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0)))
+  virtual void DoLog(log_level level, const char *format, va_list ap) {
+    LogMessage message;
+    internal::FillInMessage(level, format, ap, &message);
+    internal::PrintMessage(stderr, message);
+    if (!only_implementation_) {
+      fputs("root logger got used, see stderr for message\n", stdout);
+    }
+  }
+
+  bool only_implementation_ = true;
+};
+
+RootLogImplementation *root_implementation = nullptr;
+
+void SetGlobalImplementation(LogImplementation *implementation) {
+  if (root_implementation == nullptr) {
+    fputs("Somebody didn't call logging::Init()!\n", stderr);
+    abort();
+  }
+
+  Context *context = Context::Get();
+
+  context->implementation = implementation;
+  global_top_implementation.store(implementation);
+}
+
+void NewContext() {
+  Context::Delete();
+}
+
+void *DoInit() {
+  SetGlobalImplementation(root_implementation = new RootLogImplementation());
+
+  if (pthread_atfork(NULL /*prepare*/, NULL /*parent*/,
+                     NewContext /*child*/) != 0) {
+    LOG(FATAL, "pthread_atfork(NULL, NULL, %p) failed\n",
+        NewContext);
+  }
+
+  return NULL;
+}
+
+}  // namespace
+namespace internal {
+namespace {
+
+void FillInMessageBase(log_level level, LogMessage *message) {
+  Context *context = Context::Get();
+
+  message->level = level;
+  message->source = context->source;
+  memcpy(message->name, context->name, context->name_size);
+  message->name_length = context->name_size;
+
+  time::Time now = time::Time::Now();
+  message->seconds = now.sec();
+  message->nseconds = now.nsec();
+
+  message->sequence = context->sequence++;
+}
+
+}  // namespace
+
+void FillInMessageStructure(log_level level,
+                            const ::std::string &message_string, size_t size,
+                            const MessageType *type,
+                            const ::std::function<size_t(char *)> &serialize,
+                            LogMessage *message) {
+  type_cache::AddShm(type->id);
+  message->structure.type_id = type->id;
+
+  FillInMessageBase(level, message);
+
+  if (message_string.size() + size > sizeof(message->structure.serialized)) {
+    LOG(FATAL, "serialized struct %s (size %zd) and message %s too big\n",
+        type->name.c_str(), size, message_string.c_str());
+  }
+  message->structure.string_length = message_string.size();
+  memcpy(message->structure.serialized, message_string.data(),
+         message->structure.string_length);
+
+  message->message_length = serialize(
+      &message->structure.serialized[message->structure.string_length]);
+  message->type = LogMessage::Type::kStruct;
+}
+
+void FillInMessageMatrix(log_level level,
+                         const ::std::string &message_string, uint32_t type_id,
+                         int rows, int cols, const void *data,
+                         LogMessage *message) {
+  CHECK(MessageType::IsPrimitive(type_id));
+  message->matrix.type = type_id;
+
+  const auto element_size = MessageType::Sizeof(type_id);
+
+  FillInMessageBase(level, message);
+
+  message->message_length = rows * cols * element_size;
+  if (message_string.size() + message->message_length >
+      sizeof(message->matrix.data)) {
+    LOG(FATAL, "%dx%d matrix of type %" PRIu32
+               " (size %u) and message %s is too big\n",
+        rows, cols, type_id, element_size, message_string.c_str());
+  }
+  message->matrix.string_length = message_string.size();
+  memcpy(message->matrix.data, message_string.data(),
+         message->matrix.string_length);
+
+  message->matrix.rows = rows;
+  message->matrix.cols = cols;
+  SerializeMatrix(type_id, &message->matrix.data[message->matrix.string_length],
+                  data, rows, cols);
+  message->type = LogMessage::Type::kMatrix;
+}
+
+void FillInMessage(log_level level, const char *format, va_list ap,
+                   LogMessage *message) {
+  FillInMessageBase(level, message);
+
+  message->message_length =
+      ExecuteFormat(message->message, sizeof(message->message), format, ap);
+  message->type = LogMessage::Type::kString;
+}
+
+void PrintMessage(FILE *output, const LogMessage &message) {
+#define BASE_ARGS                                                              \
+  AOS_LOGGING_BASE_ARGS(                                                       \
+      message.name_length, message.name, static_cast<int32_t>(message.source), \
+      message.sequence, message.level, message.seconds, message.nseconds)
+  switch (message.type) {
+    case LogMessage::Type::kString:
+      fprintf(output, AOS_LOGGING_BASE_FORMAT "%.*s", BASE_ARGS,
+              static_cast<int>(message.message_length), message.message);
+      break;
+    case LogMessage::Type::kStruct: {
+      char buffer[2048];
+      size_t output_length = sizeof(buffer);
+      size_t input_length = message.message_length;
+      if (!PrintMessage(
+              buffer, &output_length,
+              message.structure.serialized + message.structure.string_length,
+              &input_length, type_cache::Get(message.structure.type_id))) {
+        LOG(FATAL,
+            "printing message (%.*s) of type %s into %zu-byte buffer failed\n",
+            static_cast<int>(message.message_length), message.message,
+            type_cache::Get(message.structure.type_id).name.c_str(),
+            sizeof(buffer));
+      }
+      if (input_length > 0) {
+        LOG(WARNING, "%zu extra bytes on message of type %s\n", input_length,
+            type_cache::Get(message.structure.type_id).name.c_str());
+      }
+      fprintf(output, AOS_LOGGING_BASE_FORMAT "%.*s: %.*s\n", BASE_ARGS,
+              static_cast<int>(message.structure.string_length),
+              message.structure.serialized,
+              static_cast<int>(sizeof(buffer) - output_length), buffer);
+    } break;
+    case LogMessage::Type::kMatrix: {
+      char buffer[1024];
+      size_t output_length = sizeof(buffer);
+      if (message.message_length !=
+          static_cast<size_t>(message.matrix.rows * message.matrix.cols *
+                              MessageType::Sizeof(message.matrix.type))) {
+        LOG(FATAL, "expected %d bytes of matrix data but have %zu\n",
+            message.matrix.rows * message.matrix.cols *
+                MessageType::Sizeof(message.matrix.type),
+            message.message_length);
+      }
+      if (!PrintMatrix(buffer, &output_length,
+                       message.matrix.data + message.matrix.string_length,
+                       message.matrix.type, message.matrix.rows,
+                       message.matrix.cols)) {
+        LOG(FATAL, "printing %dx%d matrix of type %" PRIu32 " failed\n",
+            message.matrix.rows, message.matrix.cols, message.matrix.type);
+      }
+      fprintf(output, AOS_LOGGING_BASE_FORMAT "%.*s: %.*s\n", BASE_ARGS,
+              static_cast<int>(message.matrix.string_length),
+              message.matrix.data,
+              static_cast<int>(sizeof(buffer) - output_length), buffer);
+    } break;
+  }
+#undef BASE_ARGS
+}
+
+}  // namespace internal
+
+void LogImplementation::LogStruct(
+    log_level level, const ::std::string &message, size_t size,
+    const MessageType *type, const ::std::function<size_t(char *)> &serialize) {
+  char serialized[1024];
+  if (size > sizeof(serialized)) {
+    LOG(FATAL, "structure of type %s too big to serialize\n",
+        type->name.c_str());
+  }
+  size_t used = serialize(serialized);
+  char printed[1024];
+  size_t printed_bytes = sizeof(printed);
+  if (!PrintMessage(printed, &printed_bytes, serialized, &used, *type)) {
+    LOG(FATAL, "PrintMessage(%p, %p(=%zd), %p, %p(=%zd), %p(name=%s)) failed\n",
+        printed, &printed_bytes, printed_bytes, serialized, &used, used, type,
+        type->name.c_str());
+  }
+  DoLogVariadic(level, "%.*s: %.*s\n", static_cast<int>(message.size()),
+                message.data(),
+                static_cast<int>(sizeof(printed) - printed_bytes), printed);
+}
+
+void LogImplementation::LogMatrix(
+    log_level level, const ::std::string &message, uint32_t type_id,
+    int rows, int cols, const void *data) {
+  char serialized[1024];
+  if (static_cast<size_t>(rows * cols * MessageType::Sizeof(type_id)) >
+      sizeof(serialized)) {
+    LOG(FATAL, "matrix of size %u too big to serialize\n",
+        rows * cols * MessageType::Sizeof(type_id));
+  }
+  SerializeMatrix(type_id, serialized, data, rows, cols);
+  char printed[1024];
+  size_t printed_bytes = sizeof(printed);
+  if (!PrintMatrix(printed, &printed_bytes, serialized, type_id, rows, cols)) {
+    LOG(FATAL, "PrintMatrix(%p, %p(=%zd), %p, %" PRIu32 ", %d, %d) failed\n",
+        printed, &printed_bytes, printed_bytes, serialized, type_id, rows,
+        cols);
+  }
+  DoLogVariadic(level, "%.*s: %.*s\n", static_cast<int>(message.size()),
+                message.data(),
+                static_cast<int>(sizeof(printed) - printed_bytes), printed);
+}
+
+void HandleMessageLogImplementation::DoLog(log_level level, const char *format,
+                                           va_list ap) {
+  LogMessage message;
+  internal::FillInMessage(level, format, ap, &message);
+  HandleMessage(message);
+}
+
+void HandleMessageLogImplementation::LogStruct(
+    log_level level, const ::std::string &message_string, size_t size,
+    const MessageType *type, const ::std::function<size_t(char *)> &serialize) {
+  LogMessage message;
+  internal::FillInMessageStructure(level, message_string, size, type, serialize,
+                                   &message);
+  HandleMessage(message);
+}
+
+void HandleMessageLogImplementation::LogMatrix(
+    log_level level, const ::std::string &message_string, uint32_t type_id,
+    int rows, int cols, const void *data) {
+  LogMessage message;
+  internal::FillInMessageMatrix(level, message_string, type_id, rows, cols,
+                                data, &message);
+  HandleMessage(message);
+}
+
+StreamLogImplementation::StreamLogImplementation(FILE *stream)
+    : stream_(stream) {}
+
+void StreamLogImplementation::HandleMessage(const LogMessage &message) {
+  internal::PrintMessage(stream_, message);
+}
+
+void LogNext(log_level level, const char *format, ...) {
+  va_list ap;
+  va_start(ap, format);
+  LogImplementation::DoVLog(level, format, ap, 2);
+  va_end(ap);
+}
+
+void AddImplementation(LogImplementation *implementation) {
+  Context *context = Context::Get();
+
+  if (implementation->next() != NULL) {
+    LOG(FATAL, "%p already has a next implementation, but it's not"
+        " being used yet\n", implementation);
+  }
+
+  LogImplementation *old = context->implementation;
+  if (old != NULL) {
+    implementation->set_next(old);
+  }
+  SetGlobalImplementation(implementation);
+  root_implementation->have_other_implementation();
+}
+
+void Init() {
+  static Once<void> once(DoInit);
+  once.Get();
+}
+
+void Load() {
+  Context::Get();
+}
+
+void Cleanup() {
+  Context::Delete();
+}
+
+}  // namespace logging
+}  // namespace aos
diff --git a/aos/common/logging/logging_impl.h b/aos/common/logging/logging_impl.h
new file mode 100644
index 0000000..367c1a1
--- /dev/null
+++ b/aos/common/logging/logging_impl.h
@@ -0,0 +1,362 @@
+#ifndef AOS_COMMON_LOGGING_LOGGING_IMPL_H_
+#define AOS_COMMON_LOGGING_LOGGING_IMPL_H_
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <limits.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <string>
+#include <functional>
+#include <atomic>
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/type_traits.h"
+#include "aos/common/mutex.h"
+#include "aos/common/macros.h"
+
+namespace aos {
+
+struct MessageType;
+
+}  // namespace aos
+
+// This file has all of the logging implementation. It can't be #included by C
+// code like logging.h can.
+// It is useful for the rest of the logging implementation and other C++ code
+// that needs to do special things with logging.
+//
+// It is implemented in logging_impl.cc and logging_interface.cc. They are
+// separate so that code used by logging_impl.cc can link in
+// logging_interface.cc to use logging without creating a circular dependency.
+// However, any executables with such code still need logging_impl.cc linked in.
+
+namespace aos {
+namespace logging {
+
+// Unless explicitly stated otherwise, format must always be a string constant,
+// args are printf-style arguments for format, and ap is a va_list of args.
+// The validity of format and args together will be checked at compile time
+// using a gcc function attribute.
+
+// The struct that the code uses for making logging calls.
+struct LogMessage {
+  enum class Type : uint8_t {
+    kString, kStruct, kMatrix
+  };
+
+  int32_t seconds, nseconds;
+  // message_length is just the length of the actual data (which member depends
+  // on the type).
+  size_t message_length, name_length;
+  pid_t source;
+  static_assert(sizeof(source) == 4, "that's how they get printed");
+  // Per task/thread.
+  uint16_t sequence;
+  Type type;
+  log_level level;
+  char name[100];
+  union {
+    char message[LOG_MESSAGE_LEN];
+    struct {
+      uint32_t type_id;
+      size_t string_length;
+      // The message string and then the serialized structure.
+      char serialized[LOG_MESSAGE_LEN - sizeof(type) - sizeof(string_length)];
+    } structure;
+    struct {
+      // The type ID of the element type.
+      uint32_t type;
+      int rows, cols;
+      size_t string_length;
+      // The message string and then the serialized matrix.
+      char
+          data[LOG_MESSAGE_LEN - sizeof(type) - sizeof(rows) - sizeof(cols)];
+    } matrix;
+  };
+};
+static_assert(shm_ok<LogMessage>::value, "it's going in a queue");
+
+// Returns left > right. LOG_UNKNOWN is most important.
+static inline bool log_gt_important(log_level left, log_level right) {
+  if (left == ERROR) left = 3;
+  if (right == ERROR) right = 3;
+  return left > right;
+}
+
+// Returns a string representing level or "unknown".
+static inline const char *log_str(log_level level) {
+#define DECL_LEVEL(name, value) if (level == name) return #name;
+  DECL_LEVELS;
+#undef DECL_LEVEL
+  return "unknown";
+}
+// Returns the log level represented by str or LOG_UNKNOWN.
+static inline log_level str_log(const char *str) {
+#define DECL_LEVEL(name, value) if (!strcmp(str, #name)) return name;
+  DECL_LEVELS;
+#undef DECL_LEVEL
+  return LOG_UNKNOWN;
+}
+
+// Takes a message and logs it. It will set everything up and then call DoLog
+// for the current LogImplementation.
+void VLog(log_level level, const char *format, va_list ap)
+    __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 2, 0)));
+// Adds to the saved up message.
+void VCork(int line, const char *function, const char *format, va_list ap)
+    __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0)));
+// Actually logs the saved up message.
+void VUnCork(int line, const char *function, log_level level, const char *file,
+             const char *format, va_list ap)
+    __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 5, 0)));
+
+// Will call VLog with the given arguments for the next logger in the chain.
+void LogNext(log_level level, const char *format, ...)
+  __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 2, 3)));
+
+// Takes a structure and log it.
+template <class T>
+void DoLogStruct(log_level, const ::std::string &, const T &);
+// Takes a matrix and logs it.
+template <class T>
+void DoLogMatrix(log_level, const ::std::string &, const T &);
+
+// Represents a system that can actually take log messages and do something
+// useful with them.
+// All of the code (transitively too!) in the DoLog here can make
+// normal LOG and LOG_DYNAMIC calls but can NOT call LOG_CORK/LOG_UNCORK. These
+// calls will not result in DoLog recursing. However, implementations must be
+// safe to call from multiple threads/tasks at the same time. Also, any other
+// overriden methods may end up logging through a given implementation's DoLog.
+class LogImplementation {
+ public:
+  LogImplementation() : next_(NULL) {}
+
+  // The one that this one's implementation logs to.
+  // NULL means that there is no next one.
+  LogImplementation *next() { return next_; }
+  // Virtual in case a subclass wants to perform checks. There will be a valid
+  // logger other than this one available while this is called.
+  virtual void set_next(LogImplementation *next) { next_ = next; }
+
+ private:
+  // Actually logs the given message. Implementations should somehow create a
+  // LogMessage and then call internal::FillInMessage.
+  __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0)))
+  virtual void DoLog(log_level level, const char *format, va_list ap) = 0;
+  __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 4)))
+  void DoLogVariadic(log_level level, const char *format, ...) {
+    va_list ap;
+    va_start(ap, format);
+    DoLog(level, format, ap);
+    va_end(ap);
+  }
+
+  // Logs the contents of an auto-generated structure. The implementation here
+  // just converts it to a string with PrintMessage and then calls DoLog with
+  // that, however some implementations can be a lot more efficient than that.
+  // size and type are the result of calling Size() and Type() on the type of
+  // the message.
+  // serialize will call Serialize on the message.
+  virtual void LogStruct(log_level level, const ::std::string &message,
+                         size_t size, const MessageType *type,
+                         const ::std::function<size_t(char *)> &serialize);
+  // Similiar to LogStruct, except for matrixes.
+  // type_id is the type of the elements of the matrix.
+  // data points to rows*cols*type_id.Size() bytes of data in row-major order.
+  virtual void LogMatrix(log_level level, const ::std::string &message,
+                         uint32_t type_id, int rows, int cols,
+                         const void *data);
+
+  // These functions call similar methods on the "current" LogImplementation or
+  // Die if they can't find one.
+  // levels is how many LogImplementations to not use off the stack.
+  static void DoVLog(log_level, const char *format, va_list ap, int levels)
+      __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 2, 0)));
+  // This one is implemented in queue_logging.cc.
+  static void DoLogStruct(log_level level, const ::std::string &message,
+                          size_t size, const MessageType *type,
+                          const ::std::function<size_t(char *)> &serialize,
+                          int levels);
+  // This one is implemented in matrix_logging.cc.
+  static void DoLogMatrix(log_level level, const ::std::string &message,
+                          uint32_t type_id, int rows, int cols,
+                          const void *data, int levels);
+
+  // Friends so that they can access the static Do* functions.
+  friend void VLog(log_level, const char *, va_list);
+  friend void LogNext(log_level, const char *, ...);
+  template <class T>
+  friend void DoLogStruct(log_level, const ::std::string &, const T &);
+  template <class T>
+  friend void DoLogMatrix(log_level, const ::std::string &, const T &);
+
+  LogImplementation *next_;
+};
+
+// Implements all of the DoLog* methods in terms of a (pure virtual in this
+// class) HandleMessage method that takes a pointer to the message.
+class HandleMessageLogImplementation : public LogImplementation {
+ public:
+  __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0)))
+  virtual void DoLog(log_level level, const char *format, va_list ap) override;
+  virtual void LogStruct(log_level level, const ::std::string &message_string,
+                         size_t size, const MessageType *type,
+                         const ::std::function<size_t(char *)> &serialize)
+      override;
+  virtual void LogMatrix(log_level level, const ::std::string &message_string,
+                         uint32_t type_id, int rows, int cols, const void *data)
+      override;
+
+  virtual void HandleMessage(const LogMessage &message) = 0;
+};
+
+// A log implementation that dumps all messages to a C stdio stream.
+class StreamLogImplementation : public HandleMessageLogImplementation {
+ public:
+  StreamLogImplementation(FILE *stream);
+
+ private:
+  virtual void HandleMessage(const LogMessage &message) override;
+
+  FILE *const stream_;
+};
+
+// Adds another implementation to the stack of implementations in this
+// task/thread.
+// Any tasks/threads created after this call will also use this implementation.
+// The cutoff is when the state in a given task/thread is created (either lazily
+// when needed or by calling Load()).
+// The logging system takes ownership of implementation. It will delete it if
+// necessary, so it must be created with new.
+void AddImplementation(LogImplementation *implementation);
+
+// Must be called at least once per process/load before anything else is
+// called. This function is safe to call multiple times from multiple
+// tasks/threads.
+void Init();
+
+// Forces all of the state that is usually lazily created when first needed to
+// be created when called. Cleanup() will delete it.
+void Load();
+// Resets all information in this task/thread to its initial state.
+// NOTE: This is not the opposite of Init(). The state that this deletes is
+// lazily created when needed. It is actually the opposite of Load().
+void Cleanup();
+
+// This is where all of the code that is only used by actual LogImplementations
+// goes.
+namespace internal {
+
+extern ::std::atomic<LogImplementation *> global_top_implementation;
+
+// An separate instance of this class is accessible from each task/thread.
+// NOTE: It will get deleted in the child of a fork.
+//
+// Get() and Delete() are implemented in the platform-specific interface.cc
+// file.
+struct Context {
+  Context();
+
+  // Gets the Context object for this task/thread. Will create one the first
+  // time it is called.
+  //
+  // The implementation for each platform will lazily instantiate a new instance
+  // and then initialize name the first time.
+  // IMPORTANT: The implementation of this can not use logging.
+  static Context *Get();
+  // Deletes the Context object for this task/thread so that the next Get() is
+  // called it will create a new one.
+  // It is valid to call this when Get() has never been called.
+  // This also gets called after a fork(2) in the new process, where it should
+  // still work to clean up any state.
+  static void Delete();
+
+  // Which one to log to right now.
+  // Will be NULL if there is no logging implementation to use right now.
+  LogImplementation *implementation;
+
+  // A name representing this task/(process and thread).
+  char name[sizeof(LogMessage::name)];
+  size_t name_size;
+
+  // What to assign LogMessage::source to in this task/thread.
+  pid_t source;
+
+  // The sequence value to send out with the next message.
+  uint16_t sequence;
+
+  // Contains all of the information related to implementing LOG_CORK and
+  // LOG_UNCORK.
+  struct {
+    char message[LOG_MESSAGE_LEN];
+    int line_min, line_max;
+    // Sets the data up to record a new series of corked logs.
+    void Reset() {
+      message[0] = '\0';  // make strlen of it 0
+      line_min = INT_MAX;
+      line_max = -1;
+      function = NULL;
+    }
+    // The function that the calls are in.
+    // REMEMBER: While the compiler/linker will probably optimize all of the
+    // identical strings to point to the same data, it might not, so using == to
+    // compare this with another value is a bad idea.
+    const char *function;
+  } cork_data;
+};
+
+// Fills in all the parts of message according to the given inputs (with type
+// kStruct).
+void FillInMessageStructure(log_level level,
+                            const ::std::string &message_string, size_t size,
+                            const MessageType *type,
+                            const ::std::function<size_t(char *)> &serialize,
+                            LogMessage *message);
+
+// Fills in all the parts of the message according to the given inputs (with
+// type kMatrix).
+void FillInMessageMatrix(log_level level,
+                         const ::std::string &message_string, uint32_t type_id,
+                         int rows, int cols, const void *data,
+                         LogMessage *message);
+
+// Fills in *message according to the given inputs (with type kString).
+// Used for implementing LogImplementation::DoLog.
+void FillInMessage(log_level level, const char *format, va_list ap,
+                   LogMessage *message)
+    __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 2, 0)));
+
+__attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 4)))
+static inline void FillInMessageVarargs(log_level level, LogMessage *message,
+                                        const char *format, ...) {
+  va_list ap;
+  va_start(ap, format);
+  FillInMessage(level, format, ap, message);
+  va_end(ap);
+}
+
+// Prints message to output.
+void PrintMessage(FILE *output, const LogMessage &message);
+
+// Prints format (with ap) into output and correctly deals with the result
+// being too long etc.
+size_t ExecuteFormat(char *output, size_t output_size, const char *format,
+                     va_list ap)
+    __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0)));
+
+// Runs the given function with the current LogImplementation (handles switching
+// it out while running function etc).
+// levels is how many LogImplementations to not use off the stack.
+void RunWithCurrentImplementation(
+    int levels, ::std::function<void(LogImplementation *)> function);
+
+}  // namespace internal
+}  // namespace logging
+}  // namespace aos
+
+#endif  // AOS_COMMON_LOGGING_LOGGING_IMPL_H_
diff --git a/aos/common/logging/logging_impl_test.cc b/aos/common/logging/logging_impl_test.cc
new file mode 100644
index 0000000..dec962b
--- /dev/null
+++ b/aos/common/logging/logging_impl_test.cc
@@ -0,0 +1,239 @@
+#include <string>
+
+#include <inttypes.h>
+
+#include "gtest/gtest.h"
+
+#include "aos/common/logging/logging_impl.h"
+#include "aos/common/time.h"
+#include "aos/common/logging/logging_printf_formats.h"
+
+using ::testing::AssertionResult;
+using ::testing::AssertionSuccess;
+using ::testing::AssertionFailure;
+
+namespace aos {
+namespace logging {
+namespace testing {
+
+class TestLogImplementation : public LogImplementation {
+  __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0)))
+  virtual void DoLog(log_level level, const char *format, va_list ap) {
+    internal::FillInMessage(level, format, ap, &message_);
+
+    if (level == FATAL) {
+      internal::PrintMessage(stderr, message_);
+      abort();
+    }
+
+    used_ = true;
+  }
+
+  LogMessage message_;
+
+ public:
+  const LogMessage &message() { return message_; }
+  bool used() { return used_; }
+  void reset_used() { used_ = false; }
+
+  TestLogImplementation() : used_(false) {}
+
+  bool used_;
+};
+class LoggingTest : public ::testing::Test {
+ protected:
+  AssertionResult WasAnythingLogged() {
+    if (log_implementation->used()) {
+      return AssertionSuccess() << "read message '" <<
+          log_implementation->message().message << "'";
+    }
+    return AssertionFailure();
+  }
+  AssertionResult WasLogged(log_level level, const std::string message) {
+    if (!log_implementation->used()) {
+      return AssertionFailure() << "nothing was logged";
+    }
+    if (log_implementation->message().level != level) {
+      return AssertionFailure() << "a message with level " <<
+          log_str(log_implementation->message().level) <<
+          " was logged instead of " << log_str(level);
+    }
+    internal::Context *context = internal::Context::Get();
+    if (log_implementation->message().source != context->source) {
+      LOG(FATAL, "got a message from %" PRIu32 ", but we're %" PRIu32 "\n",
+          static_cast<uint32_t>(log_implementation->message().source),
+          static_cast<uint32_t>(context->source));
+    }
+    if (log_implementation->message().name_length != context->name_size ||
+        memcmp(log_implementation->message().name, context->name,
+               context->name_size) !=
+            0) {
+      LOG(FATAL, "got a message from %.*s, but we're %s\n",
+          static_cast<int>(log_implementation->message().name_length),
+          log_implementation->message().name, context->name);
+    }
+    if (strstr(log_implementation->message().message, message.c_str())
+        == NULL) {
+      return AssertionFailure() << "got a message of '" <<
+          log_implementation->message().message <<
+          "' but expected it to contain '" << message << "'";
+    }
+
+    return AssertionSuccess() << log_implementation->message().message;
+  }
+
+ private:
+  virtual void SetUp() {
+    static bool first = true;
+    if (first) {
+      first = false;
+
+      Init();
+      AddImplementation(log_implementation = new TestLogImplementation());
+    }
+
+    log_implementation->reset_used();
+  }
+  virtual void TearDown() {
+    Cleanup();
+  }
+
+  static TestLogImplementation *log_implementation;
+};
+TestLogImplementation *LoggingTest::log_implementation(NULL);
+typedef LoggingTest LoggingDeathTest;
+
+// Tests both basic logging functionality and that the test setup works
+// correctly.
+TEST_F(LoggingTest, Basic) {
+  EXPECT_FALSE(WasAnythingLogged());
+  LOG(INFO, "test log 1\n");
+  EXPECT_TRUE(WasLogged(INFO, "test log 1\n"));
+  LOG(INFO, "test log 1.5\n");
+  // there's a subtle typo on purpose...
+  EXPECT_FALSE(WasLogged(INFO, "test log 15\n"));
+  LOG(ERROR, "test log 2=%d\n", 55);
+  EXPECT_TRUE(WasLogged(ERROR, "test log 2=55\n"));
+  LOG(ERROR, "test log 3\n");
+  EXPECT_FALSE(WasLogged(WARNING, "test log 3\n"));
+  LOG(WARNING, "test log 4\n");
+  EXPECT_TRUE(WasAnythingLogged());
+}
+TEST_F(LoggingTest, Cork) {
+  static const int begin_line = __LINE__;
+  LOG_CORK("first part ");
+  LOG_CORK("second part (=%d) ", 19);
+  EXPECT_FALSE(WasAnythingLogged());
+  LOG_CORK("third part ");
+  static const int end_line = __LINE__;
+  LOG_UNCORK(WARNING, "last part %d\n", 5);
+  std::stringstream expected;
+  expected << "logging_impl_test.cc: ";
+  expected << (begin_line + 1);
+  expected << "-";
+  expected << (end_line + 1);
+  expected << ": ";
+  expected << __func__;
+  expected << ": first part second part (=19) third part last part 5\n";
+  EXPECT_TRUE(WasLogged(WARNING, expected.str()));
+}
+
+TEST_F(LoggingDeathTest, Fatal) {
+  ASSERT_EXIT(LOG(FATAL, "this should crash it\n"),
+              ::testing::KilledBySignal(SIGABRT),
+              "this should crash it");
+}
+
+TEST_F(LoggingDeathTest, PCHECK) {
+  EXPECT_DEATH(PCHECK(fprintf(stdin, "nope")),
+               ".*fprintf\\(stdin, \"nope\"\\).*failed.*");
+}
+
+TEST_F(LoggingTest, PCHECK) {
+  EXPECT_EQ(7, PCHECK(printf("abc123\n")));
+}
+
+TEST_F(LoggingTest, PrintfDirectives) {
+  LOG(INFO, "test log %%1 %%d\n");
+  EXPECT_TRUE(WasLogged(INFO, "test log %1 %d\n"));
+  LOG_DYNAMIC(WARNING, "test log %%2 %%f\n");
+  EXPECT_TRUE(WasLogged(WARNING, "test log %2 %f\n"));
+  LOG_CORK("log 3 part %%1 %%d ");
+  LOG_UNCORK(DEBUG, "log 3 part %%2 %%f\n");
+  EXPECT_TRUE(WasLogged(DEBUG, "log 3 part %1 %d log 3 part %2 %f\n"));
+}
+
+TEST_F(LoggingTest, Timing) {
+  // For writing only.
+  //static const long kTimingCycles = 5000000;
+  static const long kTimingCycles = 5000;
+
+  time::Time start = time::Time::Now();
+  for (long i = 0; i < kTimingCycles; ++i) {
+    LOG(INFO, "a\n");
+  }
+  time::Time end = time::Time::Now();
+  time::Time diff = end - start;
+  printf("short message took %" PRId64 " nsec for %ld\n",
+         diff.ToNSec(), kTimingCycles);
+
+  start = time::Time::Now();
+  for (long i = 0; i < kTimingCycles; ++i) {
+    LOG(INFO, "something longer than just \"a\" to log to test timing\n");
+  }
+  end = time::Time::Now();
+  diff = end - start;
+  printf("long message took %" PRId64 " nsec for %ld\n",
+         diff.ToNSec(), kTimingCycles);
+}
+
+TEST(LoggingPrintFormatTest, Time) {
+  char buffer[1024];
+
+  // Easy ones.
+  ASSERT_EQ(18, snprintf(buffer, sizeof(buffer), AOS_TIME_FORMAT,
+                         AOS_TIME_ARGS(2, 0)));
+  EXPECT_EQ("0000000002.000000s", ::std::string(buffer));
+  ASSERT_EQ(18, snprintf(buffer, sizeof(buffer), AOS_TIME_FORMAT,
+                         AOS_TIME_ARGS(2, 1)));
+  EXPECT_EQ("0000000002.000000s", ::std::string(buffer));
+
+  // This one should be exact.
+  ASSERT_EQ(18, snprintf(buffer, sizeof(buffer), AOS_TIME_FORMAT,
+                         AOS_TIME_ARGS(2, 1000)));
+  EXPECT_EQ("0000000002.000001s", ::std::string(buffer));
+
+  // Make sure rounding works correctly.
+  ASSERT_EQ(18, snprintf(buffer, sizeof(buffer), AOS_TIME_FORMAT,
+                         AOS_TIME_ARGS(2, 999)));
+  EXPECT_EQ("0000000002.000001s", ::std::string(buffer));
+  ASSERT_EQ(18, snprintf(buffer, sizeof(buffer), AOS_TIME_FORMAT,
+                         AOS_TIME_ARGS(2, 500)));
+  EXPECT_EQ("0000000002.000001s", ::std::string(buffer));
+  ASSERT_EQ(18, snprintf(buffer, sizeof(buffer), AOS_TIME_FORMAT,
+                         AOS_TIME_ARGS(2, 499)));
+  EXPECT_EQ("0000000002.000000s", ::std::string(buffer));
+
+  // This used to result in "0000000001.099500s".
+  ASSERT_EQ(18, snprintf(buffer, sizeof(buffer), AOS_TIME_FORMAT,
+                         AOS_TIME_ARGS(1, 995000000)));
+  EXPECT_EQ("0000000001.995000s", ::std::string(buffer));
+}
+
+TEST(LoggingPrintFormatTest, Base) {
+  char buffer[1024];
+
+  static const ::std::string kExpected1 =
+      "name(971)(01678): ERROR   at 0000000001.995000s: ";
+  ASSERT_GT(sizeof(buffer), kExpected1.size());
+  ASSERT_EQ(
+      kExpected1.size(),
+      static_cast<size_t>(snprintf(
+          buffer, sizeof(buffer), AOS_LOGGING_BASE_FORMAT,
+          AOS_LOGGING_BASE_ARGS(4, "name", 971, 1678, ERROR, 1, 995000000))));
+  EXPECT_EQ(kExpected1, ::std::string(buffer));
+}
+
+}  // namespace testing
+}  // namespace logging
+}  // namespace aos
diff --git a/aos/common/logging/logging_interface.cc b/aos/common/logging/logging_interface.cc
new file mode 100644
index 0000000..0bec52c
--- /dev/null
+++ b/aos/common/logging/logging_interface.cc
@@ -0,0 +1,141 @@
+#include "aos/common/logging/logging_impl.h"
+
+#include <stdarg.h>
+#include <string.h>
+
+#include <type_traits>
+
+#include "aos/common/die.h"
+
+// This file only contains the code necessary to link (ie no implementations).
+// See logging_impl.h for why this is necessary.
+
+namespace aos {
+namespace logging {
+namespace internal {
+
+::std::atomic<LogImplementation *> global_top_implementation(NULL);
+
+Context::Context()
+    : implementation(global_top_implementation.load()),
+      sequence(0) {
+  cork_data.Reset();
+}
+
+size_t ExecuteFormat(char *output, size_t output_size, const char *format,
+                     va_list ap) {
+  static const char *const continued = "...\n";
+  const size_t size = output_size - strlen(continued);
+  const int ret = vsnprintf(output, size, format, ap);
+  typedef ::std::common_type<typeof(ret), typeof(size)>::type RetType;
+  if (ret < 0) {
+    PLOG(FATAL, "vsnprintf(%p, %zd, %s, args) failed",
+         output, size, format);
+  } else if (static_cast<RetType>(ret) >= static_cast<RetType>(size)) {
+    // Overwrite the '\0' at the end of the existing data and
+    // copy in the one on the end of continued.
+    memcpy(&output[size - 1], continued, strlen(continued) + 1);
+  }
+  return ::std::min<RetType>(ret, size);
+}
+
+void RunWithCurrentImplementation(
+    int levels, ::std::function<void(LogImplementation *)> function) {
+  Context *context = Context::Get();
+
+  LogImplementation *const top_implementation = context->implementation;
+  LogImplementation *new_implementation = top_implementation;
+  LogImplementation *implementation = NULL;
+  for (int i = 0; i < levels; ++i) {
+    implementation = new_implementation;
+    if (new_implementation == NULL) {
+      Die("no logging implementation to use\n");
+    }
+    new_implementation = new_implementation->next();
+  }
+  context->implementation = new_implementation;
+  function(implementation);
+  context->implementation = top_implementation;
+}
+
+}  // namespace internal
+
+using internal::Context;
+
+void LogImplementation::DoVLog(log_level level, const char *format, va_list ap,
+                               int levels) {
+  internal::RunWithCurrentImplementation(
+      levels, [&](LogImplementation * implementation) {
+    va_list ap1;
+    va_copy(ap1, ap);
+    implementation->DoLog(level, format, ap1);
+    va_end(ap1);
+
+    if (level == FATAL) {
+      VDie(format, ap);
+    }
+  });
+}
+
+void VLog(log_level level, const char *format, va_list ap) {
+  LogImplementation::DoVLog(level, format, ap, 1);
+}
+
+void VCork(int line, const char *function, const char *format, va_list ap) {
+  Context *context = Context::Get();
+
+  const size_t message_length = strlen(context->cork_data.message);
+  if (line > context->cork_data.line_max) context->cork_data.line_max = line;
+  if (line < context->cork_data.line_min) context->cork_data.line_min = line;
+
+  if (context->cork_data.function == NULL) {
+    context->cork_data.function = function;
+  } else {
+    if (strcmp(context->cork_data.function, function) != 0) {
+      LOG(FATAL, "started corking data in function %s but then moved to %s\n",
+          context->cork_data.function, function);
+    }
+  }
+
+  internal::ExecuteFormat(context->cork_data.message + message_length,
+                          sizeof(context->cork_data.message) - message_length,
+                          format, ap);
+}
+
+void VUnCork(int line, const char *function, log_level level, const char *file,
+             const char *format, va_list ap) {
+  Context *context = Context::Get();
+
+  VCork(line, function, format, ap);
+
+  log_do(level, "%s: %d-%d: %s: %s", file,
+         context->cork_data.line_min, context->cork_data.line_max, function,
+         context->cork_data.message);
+
+  context->cork_data.Reset();
+}
+
+}  // namespace logging
+}  // namespace aos
+
+void log_do(log_level level, const char *format, ...) {
+  va_list ap;
+  va_start(ap, format);
+  aos::logging::VLog(level, format, ap);
+  va_end(ap);
+}
+
+void log_cork(int line, const char *function, const char *format, ...) {
+  va_list ap;
+  va_start(ap, format);
+  aos::logging::VCork(line, function, format, ap);
+  va_end(ap);
+}
+
+void log_uncork(int line, const char *function, log_level level,
+                const char *file, const char *format, ...) {
+  va_list ap;
+  va_start(ap, format);
+  aos::logging::VUnCork(line, function, level, file, format, ap);
+  va_end(ap);
+}
diff --git a/aos/common/logging/logging_printf_formats.h b/aos/common/logging/logging_printf_formats.h
new file mode 100644
index 0000000..57a83c3
--- /dev/null
+++ b/aos/common/logging/logging_printf_formats.h
@@ -0,0 +1,30 @@
+#ifndef AOS_COMMON_LOGGING_LOGGING_PRINTF_FORMATS_H_
+#define AOS_COMMON_LOGGING_LOGGING_PRINTF_FORMATS_H_
+
+#include "aos/common/macros.h"
+
+// This file has printf(3) formats and corresponding arguments for printing out
+// times and log messages.
+// They are all split out as macros because there are 2 things that want to
+// print using the same format: log_displayer and PrintMessage in
+// logging_impl.cc.
+
+#define AOS_TIME_FORMAT \
+  "%010" PRId32 ".%0" STRINGIFY(AOS_TIME_NSECONDS_DIGITS) PRId32 "s"
+#define AOS_TIME_ARGS(sec, nsec)                      \
+  sec, (nsec + (AOS_TIME_NSECONDS_DENOMINATOR / 2)) / \
+      AOS_TIME_NSECONDS_DENOMINATOR
+
+#define AOS_LOGGING_BASE_FORMAT \
+  "%.*s(%" PRId32 ")(%05" PRIu16 "): %-7s at " AOS_TIME_FORMAT ": "
+#define AOS_LOGGING_BASE_ARGS(name_length, name, source, sequence, level, sec, \
+                              nsec)                                            \
+  static_cast<int>(name_length), name, source, sequence,                       \
+      ::aos::logging::log_str(level), AOS_TIME_ARGS(sec, nsec)
+
+// These 2 define how many digits we use to print out the nseconds fields of
+// times. They have to stay matching.
+#define AOS_TIME_NSECONDS_DIGITS 6
+#define AOS_TIME_NSECONDS_DENOMINATOR 1000
+
+#endif  // AOS_COMMON_LOGGING_LOGGING_PRINTF_FORMATS_H_
diff --git a/aos/common/logging/matrix_logging-tmpl.h b/aos/common/logging/matrix_logging-tmpl.h
new file mode 100644
index 0000000..bfc3ce5
--- /dev/null
+++ b/aos/common/logging/matrix_logging-tmpl.h
@@ -0,0 +1,20 @@
+#include "aos/common/logging/logging_impl.h"
+
+#include <functional>
+
+#include "aos/queue_primitives.h"
+
+namespace aos {
+namespace logging {
+
+template <class T>
+void DoLogMatrix(log_level level, const ::std::string &message,
+                 const T &matrix) {
+  static_assert(!T::IsRowMajor, "we only handle column-major storage");
+  LogImplementation::DoLogMatrix(level, message, TypeID<typename T::Scalar>::id,
+                                 matrix.rows(), matrix.cols(), matrix.data(),
+                                 1);
+}
+
+}  // namespace logging
+}  // namespace aos
diff --git a/aos/common/logging/matrix_logging.cc b/aos/common/logging/matrix_logging.cc
new file mode 100644
index 0000000..6173074
--- /dev/null
+++ b/aos/common/logging/matrix_logging.cc
@@ -0,0 +1,35 @@
+#include "aos/common/logging/matrix_logging.h"
+
+#include "aos/common/queue_types.h"
+
+namespace aos {
+namespace logging {
+
+void LogImplementation::DoLogMatrix(log_level level,
+                                    const ::std::string &message,
+                                    uint32_t type_id, int rows, int cols,
+                                    const void *data, int levels) {
+  internal::RunWithCurrentImplementation(
+      levels, [&](LogImplementation * implementation) {
+    implementation->LogMatrix(level, message, type_id, rows, cols, data);
+  });
+
+  if (level == FATAL) {
+    char serialized[1024];
+    if (static_cast<size_t>(rows * cols * MessageType::Sizeof(type_id)) >
+        sizeof(serialized)) {
+      Die("LOG(FATAL) matrix too big to serialize");
+    }
+    SerializeMatrix(type_id, serialized, data, rows, cols);
+    char printed[LOG_MESSAGE_LEN];
+    size_t printed_bytes = sizeof(printed);
+    if (!PrintMatrix(printed, &printed_bytes, serialized, type_id, rows, cols)) {
+      Die("LOG(FATAL) PrintMatrix call failed");
+    }
+    Die("%.*s: %.*s\n", static_cast<int>(message.size()), message.data(),
+        static_cast<int>(printed_bytes), printed);
+  }
+}
+
+}  // namespace logging
+}  // namespace aos
diff --git a/aos/common/logging/matrix_logging.h b/aos/common/logging/matrix_logging.h
new file mode 100644
index 0000000..6efaa06
--- /dev/null
+++ b/aos/common/logging/matrix_logging.h
@@ -0,0 +1,36 @@
+#ifndef AOS_COMMON_LOGGING_MATRIX_LOGGING_H_
+#define AOS_COMMON_LOGGING_MATRIX_LOGGING_H_
+
+#include <string>
+
+#include "Eigen/Dense"
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/die.h"
+
+namespace aos {
+namespace logging {
+
+// Logs the contents of a matrix and a constant string.
+// matrix must be an instance of an Eigen matrix (or something similar).
+#define LOG_MATRIX(level, message, matrix)                          \
+  do {                                                              \
+    static const ::std::string kAosLoggingMessage(                  \
+        LOG_SOURCENAME ": " STRINGIFY(__LINE__) ": " message);      \
+    ::aos::logging::DoLogMatrix(level, kAosLoggingMessage, matrix); \
+    /* so that GCC knows that it won't return */                    \
+    if (level == FATAL) {                                           \
+      ::aos::Die("DoLogStruct(FATAL) fell through!!!!!\n");         \
+    }                                                               \
+  } while (false)
+
+template <class T>
+void DoLogMatrix(log_level level, const ::std::string &message,
+                 const T &matrix);
+
+}  // namespace logging
+}  // namespace aos
+
+#include "aos/common/logging/matrix_logging-tmpl.h"
+
+#endif  // AOS_COMMON_LOGGING_MATRIX_LOGGING_H_
diff --git a/aos/common/logging/queue_logging-tmpl.h b/aos/common/logging/queue_logging-tmpl.h
new file mode 100644
index 0000000..e0a89e4
--- /dev/null
+++ b/aos/common/logging/queue_logging-tmpl.h
@@ -0,0 +1,19 @@
+#include "aos/common/logging/logging_impl.h"
+
+#include <functional>
+
+namespace aos {
+namespace logging {
+
+template <class T>
+void DoLogStruct(log_level level, const ::std::string &message,
+                 const T &structure) {
+  LogImplementation::DoLogStruct(level, message, T::Size(), T::GetType(),
+                                 [&structure](char * buffer)->size_t{
+    return structure.Serialize(buffer);
+  },
+                                 1);
+}
+
+}  // namespace logging
+}  // namespace aos
diff --git a/aos/common/logging/queue_logging.cc b/aos/common/logging/queue_logging.cc
new file mode 100644
index 0000000..ce96c29
--- /dev/null
+++ b/aos/common/logging/queue_logging.cc
@@ -0,0 +1,35 @@
+#include "aos/common/logging/queue_logging.h"
+
+#include "aos/common/logging/logging_impl.h"
+#include "aos/common/queue_types.h"
+
+namespace aos {
+namespace logging {
+
+void LogImplementation::DoLogStruct(
+    log_level level, const ::std::string &message, size_t size,
+    const MessageType *type, const ::std::function<size_t(char *)> &serialize,
+    int levels) {
+  internal::RunWithCurrentImplementation(
+      levels, [&](LogImplementation * implementation) {
+    implementation->LogStruct(level, message, size, type, serialize);
+  });
+
+  if (level == FATAL) {
+    char serialized[1024];
+    if (size > sizeof(serialized)) {
+      Die("LOG(FATAL) structure too big to serialize");
+    }
+    size_t used = serialize(serialized);
+    char printed[LOG_MESSAGE_LEN];
+    size_t printed_bytes = sizeof(printed);
+    if (!PrintMessage(printed, &printed_bytes, serialized, &used, *type)) {
+      Die("LOG(FATAL) PrintMessage call failed");
+    }
+    Die("%.*s: %.*s\n", static_cast<int>(message.size()), message.data(),
+        static_cast<int>(printed_bytes), printed);
+  }
+}
+
+}  // namespace logging
+}  // namespace aos
diff --git a/aos/common/logging/queue_logging.h b/aos/common/logging/queue_logging.h
new file mode 100644
index 0000000..ff0167a
--- /dev/null
+++ b/aos/common/logging/queue_logging.h
@@ -0,0 +1,37 @@
+#ifndef AOS_COMMON_LOGGING_QUEUE_LOGGING_H_
+#define AOS_COMMON_LOGGING_QUEUE_LOGGING_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string>
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/die.h"
+
+namespace aos {
+namespace logging {
+
+// Logs the contents of a structure (or Queue message) and a constant string.
+// structure must be an instance of one of the generated queue types.
+#define LOG_STRUCT(level, message, structure)                          \
+  do {                                                                 \
+    static const ::std::string kAosLoggingMessage(                     \
+        LOG_SOURCENAME ": " STRINGIFY(__LINE__) ": " message);         \
+    ::aos::logging::DoLogStruct(level, kAosLoggingMessage, structure); \
+    /* so that GCC knows that it won't return */                       \
+    if (level == FATAL) {                                              \
+      ::aos::Die("DoLogStruct(FATAL) fell through!!!!!\n");            \
+    }                                                                  \
+  } while (false)
+
+template <class T>
+void DoLogStruct(log_level level, const ::std::string &message,
+                 const T &structure);
+
+}  // namespace logging
+}  // namespace aos
+
+#include "aos/common/logging/queue_logging-tmpl.h"
+
+#endif  // AOS_COMMON_LOGGING_QUEUE_LOGGING_H_
diff --git a/aos/common/macros.h b/aos/common/macros.h
new file mode 100644
index 0000000..e8558b2
--- /dev/null
+++ b/aos/common/macros.h
@@ -0,0 +1,41 @@
+#ifndef _AOS_COMMON_MACROS_H_
+#define _AOS_COMMON_MACROS_H_
+
+// This file has some common macros etc.
+
+// A macro to disallow the copy constructor and operator= functions
+// This should be used in the private: declarations for a class
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+  TypeName(const TypeName&) = delete;      \
+  void operator=(const TypeName&) = delete
+
+// A macro to wrap arguments to macros that contain commas.
+// Useful for DISALLOW_COPY_AND_ASSIGNing templated types with multiple template
+// arguments.
+#define MACRO_ARG(...) __VA_ARGS__
+// Double-wraps macro arguments.
+// Necessary to use commas in gtest predicate arguments.
+#define MACRO_DARG(...) (__VA_ARGS__)
+
+#ifdef __GNUC__
+#define UNUSED_VARIABLE __attribute__ ((unused))
+#else
+#define UNUSED_VARIABLE
+#endif
+
+#define STRINGIFY(x) TO_STRING(x)
+#define TO_STRING(x) #x
+
+#ifdef __VXWORKS__
+// We're using ancient glibc, so sticking to just what the syscall can handle is
+// probably safer.
+#define GOOD_PRINTF_FORMAT_TYPE printf
+#else
+#ifdef __clang__
+#define GOOD_PRINTF_FORMAT_TYPE __printf__
+#else
+#define GOOD_PRINTF_FORMAT_TYPE gnu_printf
+#endif
+#endif
+
+#endif  // _AOS_COMMON_MACROS_H_
diff --git a/aos/common/messages/messages.gyp b/aos/common/messages/messages.gyp
new file mode 100644
index 0000000..ab336b9
--- /dev/null
+++ b/aos/common/messages/messages.gyp
@@ -0,0 +1,15 @@
+{
+  'targets': [
+    {
+      'target_name': 'robot_state',
+      'type': 'static_library',
+      'sources': [
+        'robot_state.q',
+      ],
+      'variables': {
+        'header_path': 'aos/common/messages',
+      },
+      'includes': ['../../build/queues.gypi'],
+    },
+  ],
+}
diff --git a/aos/common/messages/robot_state.q b/aos/common/messages/robot_state.q
new file mode 100644
index 0000000..3ecb653
--- /dev/null
+++ b/aos/common/messages/robot_state.q
@@ -0,0 +1,67 @@
+package aos;
+
+struct Joystick {
+  // A bitmask of the button state.
+  uint16_t buttons;
+
+  // The 4 joystick axes.
+  double[4] axis;
+
+  // The POV axis.
+  int32_t pov;
+};
+
+message JoystickState {
+  Joystick[4] joysticks;
+
+  bool test_mode;
+  bool fms_attached;
+  bool enabled;
+  bool autonomous;
+  uint16_t team_id;
+
+  // If this is true, then this message isn't actually from the control
+  // system and so should not be trusted as evidence that the button inputs
+  // etc are actually real and should be acted on.
+  // However, most things should ignore this so that sending fake messages is
+  // useful for testing. The only difference in behavior should be motors not
+  // actually turning on.
+  bool fake;
+};
+
+// This queue is checked by all control loops to make sure that the
+// joystick code hasn't died.
+queue JoystickState joystick_state;
+
+message RobotState {
+  // The PID of the process reading sensors.
+  // This is here so control loops can tell when it changes.
+  int32_t reader_pid;
+
+  // True when outputs are enabled.
+  // Motor controllers keep going for a bit after this goes to false.
+  bool outputs_enabled;
+  // Indicates whether something is browned out (I think motor controller
+  // outputs). IMPORTANT: This is NOT !outputs_enabled. outputs_enabled goes to
+  // false for other reasons too (disabled, e-stopped, maybe more).
+  bool browned_out;
+
+  // Whether the two sensor rails are currently working.
+  bool is_3v3_active;
+  bool is_5v_active;
+  // The current voltages measured on the two sensor rails.
+  double voltage_3v3;
+  double voltage_5v;
+
+  // The input voltage to the roboRIO.
+  double voltage_roborio_in;
+
+  // From the DriverStation object, aka what FMS sees and what shows up on the
+  // actual driver's station.
+  double voltage_battery;
+};
+
+// Messages are sent out on this queue along with reading sensors. It contains
+// global robot state and information about whether the process reading sensors
+// has been restarted, along with all counters etc it keeps track of.
+queue RobotState robot_state;
diff --git a/aos/common/mutex.h b/aos/common/mutex.h
new file mode 100644
index 0000000..ca35b10
--- /dev/null
+++ b/aos/common/mutex.h
@@ -0,0 +1,144 @@
+#ifndef AOS_COMMON_MUTEX_H_
+#define AOS_COMMON_MUTEX_H_
+
+#include "aos/common/macros.h"
+#include "aos/linux_code/ipc_lib/aos_sync.h"
+#include "aos/common/die.h"
+
+namespace aos {
+
+class Condition;
+
+// An abstraction of a mutex that is easy to implement for environments other
+// than Linux too.
+// If there are multiple threads or processes contending for the mutex,
+// higher priority ones will succeed in locking first,
+// and tasks of equal priorities have the same chance of getting the lock.
+// To deal with priority inversion, the linux implementation does priority
+// inheritance.
+// Before destroying a mutex, it is important to make sure it isn't locked.
+// Otherwise, the destructor will LOG(FATAL).
+class Mutex {
+ public:
+  // States that signify the result of TryLock.
+  enum class State {
+    // The mutex was acquired successfully.
+    kLocked,
+    // TryLock tried to grab the mutex and failed.
+    kLockFailed
+  };
+
+  // Creates an unlocked mutex.
+  Mutex();
+  // Verifies that it isn't locked.
+  //
+  // This is important because freeing a locked mutex means there is freed
+  // memory in the middle of the robust list, which breaks things horribly.
+  ~Mutex();
+
+  // Locks the mutex. If it fails, it calls LOG(FATAL).
+  // Returns false.
+  bool Lock() __attribute__((warn_unused_result));
+  // Unlocks the mutex. Fails like Lock.
+  // Multiple unlocking is undefined.
+  void Unlock();
+  // Locks the mutex unless it is already locked.
+  // Returns the new state of the mutex.
+  // Doesn't wait for the mutex to be unlocked if it is locked.
+  State TryLock() __attribute__((warn_unused_result));
+
+  // Returns true iff the current task has this mutex locked.
+  // This is mainly for IPCRecursiveMutexLocker to use.
+  bool OwnedBySelf() const;
+
+ private:
+  aos_mutex impl_;
+
+  friend class Condition;  // for access to impl_
+};
+
+// A class that locks a Mutex when constructed and unlocks it when destructed.
+// Designed to be used as a local variable so that
+// the mutex will be unlocked when the scope is exited.
+// This one immediately Dies if the previous owner died. This makes it a good
+// choice for mutexes that are only used within a single process, but NOT for
+// mutexes shared by multiple processes. For those, use IPCMutexLocker.
+class MutexLocker {
+ public:
+  explicit MutexLocker(Mutex *mutex) : mutex_(mutex) {
+    if (__builtin_expect(mutex_->Lock(), false)) {
+      ::aos::Die("previous owner of mutex %p died but it shouldn't be able to",
+                 this);
+    }
+  }
+  ~MutexLocker() {
+    mutex_->Unlock();
+  }
+
+ private:
+  Mutex *const mutex_;
+
+  DISALLOW_COPY_AND_ASSIGN(MutexLocker);
+};
+
+// A version of MutexLocker which reports the previous owner dying instead of
+// immediately LOG(FATAL)ing.
+class IPCMutexLocker {
+ public:
+  explicit IPCMutexLocker(Mutex *mutex)
+      : mutex_(mutex), owner_died_(mutex_->Lock()) {}
+  ~IPCMutexLocker() {
+    if (__builtin_expect(!owner_died_checked_, false)) {
+      ::aos::Die("nobody checked if the previous owner of mutex %p died", this);
+    }
+    mutex_->Unlock();
+  }
+
+  // Whether or not the previous owner died. If this is not called at least
+  // once, the destructor will ::aos::Die.
+  __attribute__((warn_unused_result)) bool owner_died() {
+    owner_died_checked_ = true;
+    return __builtin_expect(owner_died_, false);
+  }
+
+ private:
+  Mutex *const mutex_;
+  const bool owner_died_;
+  bool owner_died_checked_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(IPCMutexLocker);
+};
+
+// A version of IPCMutexLocker which only locks (and unlocks) the mutex if the
+// current task does not already hold it.
+class IPCRecursiveMutexLocker {
+ public:
+  explicit IPCRecursiveMutexLocker(Mutex *mutex)
+      : mutex_(mutex),
+        locked_(!mutex_->OwnedBySelf()),
+        owner_died_(locked_ ? mutex_->Lock() : false) {}
+  ~IPCRecursiveMutexLocker() {
+    if (__builtin_expect(!owner_died_checked_, false)) {
+      ::aos::Die("nobody checked if the previous owner of mutex %p died", this);
+    }
+    if (locked_) mutex_->Unlock();
+  }
+
+  // Whether or not the previous owner died. If this is not called at least
+  // once, the destructor will ::aos::Die.
+  __attribute__((warn_unused_result)) bool owner_died() {
+    owner_died_checked_ = true;
+    return __builtin_expect(owner_died_, false);
+  }
+
+ private:
+  Mutex *const mutex_;
+  const bool locked_, owner_died_;
+  bool owner_died_checked_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(IPCRecursiveMutexLocker);
+};
+
+}  // namespace aos
+
+#endif  // AOS_COMMON_MUTEX_H_
diff --git a/aos/common/mutex_test.cc b/aos/common/mutex_test.cc
new file mode 100644
index 0000000..6614d5c
--- /dev/null
+++ b/aos/common/mutex_test.cc
@@ -0,0 +1,273 @@
+#include "aos/common/mutex.h"
+
+#include <sched.h>
+#include <math.h>
+#include <pthread.h>
+
+#include <thread>
+
+#include "gtest/gtest.h"
+
+#include "aos/linux_code/ipc_lib/aos_sync.h"
+#include "aos/common/die.h"
+#include "aos/common/util/death_test_log_implementation.h"
+#include "aos/common/util/thread.h"
+#include "aos/common/time.h"
+#include "aos/common/queue_testutils.h"
+#include "aos/linux_code/ipc_lib/core_lib.h"
+
+namespace aos {
+namespace testing {
+
+class MutexTest : public ::testing::Test {
+ public:
+  Mutex test_mutex_;
+
+ protected:
+  void SetUp() override {
+    ::aos::common::testing::EnableTestLogging();
+    SetDieTestMode(true);
+  }
+};
+
+typedef MutexTest MutexDeathTest;
+typedef MutexTest MutexLockerTest;
+typedef MutexTest MutexLockerDeathTest;
+typedef MutexTest IPCMutexLockerTest;
+typedef MutexTest IPCMutexLockerDeathTest;
+typedef MutexTest IPCRecursiveMutexLockerTest;
+
+TEST_F(MutexTest, TryLock) {
+  EXPECT_EQ(Mutex::State::kLocked, test_mutex_.TryLock());
+  EXPECT_EQ(Mutex::State::kLockFailed, test_mutex_.TryLock());
+
+  test_mutex_.Unlock();
+}
+
+TEST_F(MutexTest, Lock) {
+  ASSERT_FALSE(test_mutex_.Lock());
+  EXPECT_EQ(Mutex::State::kLockFailed, test_mutex_.TryLock());
+
+  test_mutex_.Unlock();
+}
+
+TEST_F(MutexTest, Unlock) {
+  ASSERT_FALSE(test_mutex_.Lock());
+  EXPECT_EQ(Mutex::State::kLockFailed, test_mutex_.TryLock());
+  test_mutex_.Unlock();
+  EXPECT_EQ(Mutex::State::kLocked, test_mutex_.TryLock());
+
+  test_mutex_.Unlock();
+}
+
+// Sees what happens with multiple unlocks.
+TEST_F(MutexDeathTest, RepeatUnlock) {
+  logging::Init();
+  ASSERT_FALSE(test_mutex_.Lock());
+  test_mutex_.Unlock();
+  EXPECT_DEATH(
+      {
+        logging::AddImplementation(new util::DeathTestLogImplementation());
+        test_mutex_.Unlock();
+      },
+      ".*multiple unlock.*");
+}
+
+// Sees what happens if you unlock without ever locking (or unlocking) it.
+TEST_F(MutexDeathTest, NeverLock) {
+  logging::Init();
+  EXPECT_DEATH(
+      {
+        logging::AddImplementation(new util::DeathTestLogImplementation());
+        test_mutex_.Unlock();
+      },
+      ".*multiple unlock.*");
+}
+
+// Sees what happens with multiple locks.
+TEST_F(MutexDeathTest, RepeatLock) {
+  EXPECT_DEATH(
+      {
+        logging::AddImplementation(new util::DeathTestLogImplementation());
+        ASSERT_FALSE(test_mutex_.Lock());
+        ASSERT_FALSE(test_mutex_.Lock());
+      },
+      ".*multiple lock.*");
+}
+
+TEST_F(MutexDeathTest, DestroyLocked) {
+  EXPECT_DEATH(
+      {
+        logging::AddImplementation(new util::DeathTestLogImplementation());
+        Mutex new_mutex;
+        ASSERT_FALSE(new_mutex.Lock());
+      },
+      ".*destroying locked mutex.*");
+}
+
+namespace {
+
+class AdderThread : public ::aos::util::Thread {
+ public:
+  AdderThread(int *counter, Mutex *mutex, ::aos::time::Time sleep_before_time,
+              ::aos::time::Time sleep_after_time)
+      : counter_(counter),
+        mutex_(mutex),
+        sleep_before_time_(sleep_before_time),
+        sleep_after_time_(sleep_after_time) {}
+  virtual void Run() override {
+    ::aos::time::SleepFor(sleep_before_time_);
+    MutexLocker locker(mutex_);
+    ++(*counter_);
+    ::aos::time::SleepFor(sleep_after_time_);
+  }
+
+ private:
+  int *const counter_;
+  Mutex *const mutex_;
+  const ::aos::time::Time sleep_before_time_, sleep_after_time_;
+};
+
+}  // namespace
+
+// Verifies that ThreadSanitizer understands that a contended mutex establishes
+// a happens-before relationship.
+TEST_F(MutexTest, ThreadSanitizerContended) {
+  int counter = 0;
+  AdderThread threads[2]{
+      {&counter, &test_mutex_, ::aos::time::Time::InSeconds(0.2),
+       ::aos::time::Time::InSeconds(0)},
+      {&counter, &test_mutex_, ::aos::time::Time::InSeconds(0),
+       ::aos::time::Time::InSeconds(0)}, };
+  for (auto &c : threads) {
+    c.Start();
+  }
+  for (auto &c : threads) {
+    c.WaitUntilDone();
+  }
+  EXPECT_EQ(2, counter);
+}
+
+// Verifiers that ThreadSanitizer understands how a mutex works.
+// For some reason this used to fail when the other tests didn't...
+TEST_F(MutexTest, ThreadSanitizerMutexLocker) {
+  int counter = 0;
+  ::std::thread thread([&counter, this]() {
+    for (int i = 0; i < 1000; ++i) {
+      MutexLocker locker(&test_mutex_);
+      ++counter;
+    }
+  });
+  for (int i = 0; i < 1000; ++i) {
+    MutexLocker locker(&test_mutex_);
+    --counter;
+  }
+  thread.join();
+  EXPECT_EQ(0, counter);
+}
+
+// Verifies that ThreadSanitizer understands that an uncontended mutex
+// establishes a happens-before relationship.
+TEST_F(MutexTest, ThreadSanitizerUncontended) {
+  int counter = 0;
+  AdderThread threads[2]{
+      {&counter, &test_mutex_, ::aos::time::Time::InSeconds(0.2),
+       ::aos::time::Time::InSeconds(0)},
+      {&counter, &test_mutex_, ::aos::time::Time::InSeconds(0),
+       ::aos::time::Time::InSeconds(0)}, };
+  for (auto &c : threads) {
+    c.Start();
+  }
+  for (auto &c : threads) {
+    c.WaitUntilDone();
+  }
+  EXPECT_EQ(2, counter);
+}
+
+namespace {
+
+class LockerThread : public util::Thread {
+ public:
+  LockerThread(Mutex *mutex, bool lock, bool unlock)
+      : mutex_(mutex), lock_(lock), unlock_(unlock) {}
+
+ private:
+  virtual void Run() override {
+    if (lock_) ASSERT_FALSE(mutex_->Lock());
+    if (unlock_) mutex_->Unlock();
+  }
+
+  Mutex *const mutex_;
+  const bool lock_, unlock_;
+};
+
+}  // namespace
+
+// Makes sure that we don't SIGSEGV or something with multiple threads.
+TEST_F(MutexTest, MultiThreadedLock) {
+  LockerThread t(&test_mutex_, true, true);
+  t.Start();
+  ASSERT_FALSE(test_mutex_.Lock());
+  test_mutex_.Unlock();
+  t.Join();
+}
+
+TEST_F(MutexLockerTest, Basic) {
+  {
+    aos::MutexLocker locker(&test_mutex_);
+    EXPECT_EQ(Mutex::State::kLockFailed, test_mutex_.TryLock());
+  }
+  EXPECT_EQ(Mutex::State::kLocked, test_mutex_.TryLock());
+
+  test_mutex_.Unlock();
+}
+
+TEST_F(IPCMutexLockerTest, Basic) {
+  {
+    aos::IPCMutexLocker locker(&test_mutex_);
+    EXPECT_EQ(Mutex::State::kLockFailed, test_mutex_.TryLock());
+    EXPECT_FALSE(locker.owner_died());
+  }
+  EXPECT_EQ(Mutex::State::kLocked, test_mutex_.TryLock());
+
+  test_mutex_.Unlock();
+}
+
+// Tests what happens when the caller doesn't check if the previous owner died
+// with an IPCMutexLocker.
+TEST_F(IPCMutexLockerDeathTest, NoCheckOwnerDied) {
+  EXPECT_DEATH({ aos::IPCMutexLocker locker(&test_mutex_); },
+               "nobody checked if the previous owner of mutex [^ ]+ died.*");
+}
+
+TEST_F(IPCRecursiveMutexLockerTest, Basic) {
+  {
+    aos::IPCRecursiveMutexLocker locker(&test_mutex_);
+    EXPECT_EQ(Mutex::State::kLockFailed, test_mutex_.TryLock());
+    EXPECT_FALSE(locker.owner_died());
+  }
+  EXPECT_EQ(Mutex::State::kLocked, test_mutex_.TryLock());
+
+  test_mutex_.Unlock();
+}
+
+// Tests actually locking a mutex recursively with IPCRecursiveMutexLocker.
+TEST_F(IPCRecursiveMutexLockerTest, RecursiveLock) {
+  {
+    aos::IPCRecursiveMutexLocker locker(&test_mutex_);
+    EXPECT_EQ(Mutex::State::kLockFailed, test_mutex_.TryLock());
+    {
+      aos::IPCRecursiveMutexLocker locker(&test_mutex_);
+      EXPECT_EQ(Mutex::State::kLockFailed, test_mutex_.TryLock());
+      EXPECT_FALSE(locker.owner_died());
+    }
+    EXPECT_EQ(Mutex::State::kLockFailed, test_mutex_.TryLock());
+    EXPECT_FALSE(locker.owner_died());
+  }
+  EXPECT_EQ(Mutex::State::kLocked, test_mutex_.TryLock());
+
+  test_mutex_.Unlock();
+}
+
+}  // namespace testing
+}  // namespace aos
diff --git a/aos/common/network/network.gyp b/aos/common/network/network.gyp
new file mode 100644
index 0000000..cf52f9f
--- /dev/null
+++ b/aos/common/network/network.gyp
@@ -0,0 +1,36 @@
+{
+  'targets': [
+    {
+      'target_name': 'team_number',
+      'type': 'static_library',
+      'sources': [
+        'team_number.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:configuration',
+        '<(AOS)/common/common.gyp:once',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/util/util.gyp:string_to_num',
+      ],
+    },
+    {
+      'target_name': 'socket',
+      'type': 'static_library',
+      'sources': [
+        'receive_socket.cc',
+        'send_socket.cc',
+        'socket.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/common/util/util.gyp:inet_addr',
+        '<(AOS)/linux_code/linux_code.gyp:configuration',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/common.gyp:time',
+      ],
+    },
+  ],
+}
diff --git a/aos/common/network/receive_socket.cc b/aos/common/network/receive_socket.cc
new file mode 100644
index 0000000..c3a7710
--- /dev/null
+++ b/aos/common/network/receive_socket.cc
@@ -0,0 +1,33 @@
+#include "aos/common/network/receive_socket.h"
+
+#include <string.h>
+#include <math.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <sys/socket.h>
+
+#include "aos/common/logging/logging.h"
+
+namespace aos {
+namespace network {
+
+static const char *localhost = "0.0.0.0";
+
+int ReceiveSocket::Connect(NetworkPort port) {
+  Reset();
+  const int ret = Socket::Connect(port, localhost);
+  if (ret != 0) {
+    return ret;
+  }
+
+  if (bind(socket_, &addr_.addr,
+           sizeof(addr_)) == -1) {
+    PLOG(ERROR, "failed to bind to address '%s'", localhost);
+    return last_ret_ = -1;
+  }
+  return last_ret_ = 0;
+}
+
+}  // namespace network
+}  // namespace aos
diff --git a/aos/common/network/receive_socket.h b/aos/common/network/receive_socket.h
new file mode 100644
index 0000000..afa0726
--- /dev/null
+++ b/aos/common/network/receive_socket.h
@@ -0,0 +1,18 @@
+#ifndef AOS_COMMON_NETWORK_RECEIVE_SOCKET_H_
+#define AOS_COMMON_NETWORK_RECEIVE_SOCKET_H_
+
+#include "aos/common/network/socket.h"
+
+namespace aos {
+namespace network {
+
+class ReceiveSocket : public Socket {
+ public:
+  explicit ReceiveSocket(NetworkPort port) { Connect(port); }
+  int Connect(NetworkPort port);
+};
+
+}  // namespace network
+}  // namespace aos
+
+#endif  // AOS_COMMON_NETWORK_RECEIVE_SOCKET_H_
diff --git a/aos/common/network/send_socket.cc b/aos/common/network/send_socket.cc
new file mode 100644
index 0000000..9886893
--- /dev/null
+++ b/aos/common/network/send_socket.cc
@@ -0,0 +1,31 @@
+#include "aos/common/network/send_socket.h"
+
+#include <string.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <math.h>
+#include <sys/socket.h>
+
+#include "aos/common/logging/logging.h"
+
+namespace aos {
+namespace network {
+
+int SendSocket::Connect(NetworkPort port, const char *robot_ip, int type) {
+  Reset();
+  const int ret = Socket::Connect(port, robot_ip, type);
+  if (ret != 0) {
+    return ret;
+  }
+
+  if (connect(socket_, &addr_.addr, sizeof(addr_)) < 0) {
+    PLOG(ERROR, "couldn't connect to ip '%s'", robot_ip);
+    return last_ret_ = 1;
+  }
+
+  return last_ret_ = 0;
+}
+
+}  // namespace network
+}  // namespace aos
diff --git a/aos/common/network/send_socket.h b/aos/common/network/send_socket.h
new file mode 100644
index 0000000..77db726
--- /dev/null
+++ b/aos/common/network/send_socket.h
@@ -0,0 +1,29 @@
+#ifndef AOS_COMMON_NETWORK_SEND_SOCKET_H_
+#define AOS_COMMON_NETWORK_SEND_SOCKET_H_
+
+#include "aos/common/network/socket.h"
+
+#include "aos/linux_code/configuration.h"
+#include "aos/common/network_port.h"
+#include "aos/common/util/inet_addr.h"
+
+namespace aos {
+namespace network {
+
+class SendSocket : public Socket {
+ public:
+  // Connect must be called before use.
+  SendSocket() {}
+  // Calls Connect automatically.
+  SendSocket(NetworkPort port, ::aos::NetworkAddress address) {
+    Connect(port,
+            ::aos::util::MakeIPAddress(::aos::configuration::GetOwnIPAddress(),
+                                       address));
+  }
+  int Connect(NetworkPort port, const char *robot_ip, int type = SOCK_DGRAM);
+};
+
+}  // namespace network
+}  // namespace aos
+
+#endif  // AOS_COMMON_NETWORK_SEND_SOCKET_H_
diff --git a/aos/common/network/socket.cc b/aos/common/network/socket.cc
new file mode 100644
index 0000000..b674ff1
--- /dev/null
+++ b/aos/common/network/socket.cc
@@ -0,0 +1,83 @@
+#include "aos/common/network/socket.h"
+
+#include <string.h>
+#include <errno.h>
+#include <sys/socket.h>
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/byteorder.h"
+
+namespace aos {
+namespace network {
+
+int Socket::Connect(NetworkPort port, const char *address, int type) {
+  last_ret_ = 0;
+  if ((socket_ = socket(AF_INET, type, 0)) < 0) {
+    PLOG(ERROR, "failed to create socket");
+    return last_ret_ = 1;
+  }
+
+  memset(&addr_, 0, sizeof(addr_));
+  addr_.in.sin_family = AF_INET;
+  addr_.in.sin_port = hton<uint16_t>(static_cast<uint16_t>(port));
+#ifndef __VXWORKS__
+  const int failure_return = 0;
+#else
+  const int failure_return = -1;
+#endif
+  if (inet_aton(address, &addr_.in.sin_addr) == failure_return) {
+    PLOG(ERROR, "invalid IP address '%s'", address);
+    return last_ret_ = -1;
+  }
+
+  return last_ret_ = 0;
+}
+
+Socket::Socket() : socket_(-1), last_ret_(2) {}
+
+Socket::~Socket() {
+  close(socket_);
+}
+
+void Socket::Reset() {
+  if (socket_ != -1) {
+    close(socket_);
+    socket_ = -1;
+  }
+  last_ret_ = 0;
+}
+
+int Socket::Receive(void *buf, int length) {
+  const int ret = recv(socket_, static_cast<char *>(buf), length, 0);
+  last_ret_ = (ret == -1) ? -1 : 0;
+  return ret;
+}
+
+int Socket::Receive(void *buf, int length, time::Time timeout) {
+  timeval timeout_timeval = timeout.ToTimeval();
+  fd_set fds;
+  FD_ZERO(&fds);
+  FD_SET(socket_, &fds);
+  switch (select(FD_SETSIZE, &fds, NULL, NULL, &timeout_timeval)) {
+    case 1:
+      return Receive(buf, length);
+    case 0:
+      return last_ret_ = 0;
+    default:
+      if (errno == EINTR) {
+        return last_ret_ = 0;
+      }
+      PLOG(FATAL, "select(FD_SETSIZE, %p, NULL, NULL, %p) failed",
+          &fds, &timeout_timeval);
+  }
+}
+
+int Socket::Send(const void *buf, int length) {
+  const int ret = write(socket_,
+                        static_cast<const char *>(buf), length);
+  last_ret_ = (ret == -1) ? -1 : 0;
+  return ret;
+}
+
+}  // namespace network
+}  // namespace aos
diff --git a/aos/common/network/socket.h b/aos/common/network/socket.h
new file mode 100644
index 0000000..9e8eaf5
--- /dev/null
+++ b/aos/common/network/socket.h
@@ -0,0 +1,53 @@
+#ifndef AOS_COMMON_NETWORK_SOCKET_H_
+#define AOS_COMMON_NETWORK_SOCKET_H_
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#include "aos/common/time.h"
+#include "aos/common/network_port.h"
+
+namespace aos {
+namespace network {
+
+class Socket {
+ public:
+  int LastStatus() const { return last_ret_; }
+
+  int Send(const void *buf, int length);
+
+  // buf is where to put the data and length is the maximum amount of data to
+  // put in for all overloads.
+  // All overloads return how many bytes were received or -1 for error. 0 is a
+  // valid return value for all overloads.
+  // No timeout.
+  int Receive(void *buf, int length);
+  // timeout is relative
+  int Receive(void *buf, int length, time::Time timeout);
+
+ protected:
+  int Connect(NetworkPort port, const char *address, int type = SOCK_DGRAM);
+  Socket();
+  ~Socket();
+
+  // Resets socket_ and last_ret_.
+  void Reset();
+
+  union {
+    sockaddr_in in;
+    sockaddr addr;
+  } addr_; // filled in by Connect
+
+  int socket_;
+  int last_ret_;
+};
+
+}  // namespace network
+}  // namespace aos
+
+#endif  // AOS_COMMON_NETWORK_SOCKET_H_
diff --git a/aos/common/network/team_number.cc b/aos/common/network/team_number.cc
new file mode 100644
index 0000000..134113a
--- /dev/null
+++ b/aos/common/network/team_number.cc
@@ -0,0 +1,81 @@
+#include "aos/common/network/team_number.h"
+
+#include <netinet/in.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <string>
+
+#include "aos/common/once.h"
+#include "aos/linux_code/configuration.h"
+#include "aos/common/logging/logging.h"
+#include "aos/common/util/string_to_num.h"
+
+namespace aos {
+namespace network {
+namespace {
+
+uint16_t override_team;
+
+::std::string GetHostname() {
+  char buf[256];
+  buf[sizeof(buf) - 1] = '\0';
+  PCHECK(gethostname(buf, sizeof(buf) - 1));
+  return buf;
+}
+
+int ParseTeamNumber(const std::string &hostname, uint16_t *teamnumber) {
+  for (size_t i = 0; i < hostname.size(); i++) {
+    if (hostname[i] == '-') {
+      const std::string num_as_s = hostname.substr(i + 1);
+
+      int num;
+      if (!::aos::util::StringToNumber(num_as_s, &num)) {
+        return -1;
+      }
+      if (hostname.substr(0, i) == "roboRIO" &&
+          std::to_string(num) == num_as_s) {
+        *teamnumber = num;
+        return 0;
+      } else {
+        return -1;
+      }
+    }
+  }
+  return -1;
+}
+
+uint16_t *DoGetTeamNumber() {
+  if (override_team != 0) return &override_team;
+
+  static uint16_t r;
+
+  const char *override_number = getenv("AOS_TEAM_NUMBER");
+  if (override_number != nullptr) {
+    if (!::aos::util::StringToNumber(override_number, &r)) {
+      LOG(FATAL, "error parsing AOS_TEAM_NUMBER '%s'\n", override_number);
+    }
+    LOG(WARNING, "team number overridden by AOS_TEAM_NUMBER to %" PRIu16 "\n",
+        r);
+  } else {
+    int error = ParseTeamNumber(GetHostname(), &r);
+    if (error) {
+      LOG(FATAL, "Invalid hostname %s\n", GetHostname().c_str());
+    }
+    LOG(INFO, "team number is %" PRIu16 "\n", r);
+  }
+  return &r;
+}
+
+}  // namespace
+
+uint16_t GetTeamNumber() {
+  static Once<uint16_t> once(DoGetTeamNumber);
+  return *once.Get();
+}
+
+void OverrideTeamNumber(uint16_t team) { override_team = team; }
+
+}  // namespace network
+}  // namespace aos
diff --git a/aos/common/network/team_number.h b/aos/common/network/team_number.h
new file mode 100644
index 0000000..520b9ba
--- /dev/null
+++ b/aos/common/network/team_number.h
@@ -0,0 +1,24 @@
+#ifndef AOS_COMMON_NETWORK_TEAM_NUMBER_H_
+#define AOS_COMMON_NETWORK_TEAM_NUMBER_H_
+
+#include <stdint.h>
+
+namespace aos {
+namespace network {
+
+// Retrieves the current team number based off of the network address.
+// This function will only do the complicated stuff once so it is cheap to call
+// repeatedly.
+uint16_t GetTeamNumber();
+
+// Overrides the team number returned from GetTeamNumber(). Must be called
+// before GetTeamNumber() is ever called.
+// Overriding to team 0 won't work.
+// Intended only for tests.
+// Guaranteed to be safe to call during static initialization time.
+void OverrideTeamNumber(uint16_t team);
+
+}  // namespace network
+}  // namespace aos
+
+#endif  // AOS_COMMON_NETWORK_TEAM_NUMBER_H_
diff --git a/aos/common/network_port.h b/aos/common/network_port.h
new file mode 100644
index 0000000..b523674
--- /dev/null
+++ b/aos/common/network_port.h
@@ -0,0 +1,32 @@
+#ifndef AOS_COMMON_NETWORK_PORT_H_
+#define AOS_COMMON_NETWORK_PORT_H_
+
+#include <stdint.h>
+
+namespace aos {
+
+// Constants representing the various ports used for communications and some
+// documentation about what each is used for.
+enum class NetworkPort : uint16_t {
+  // UDP socket sending motor values from the prime to the crio.
+  kMotors = 9710,
+  // UDP socket forwarding drivers station packets from the crio to the prime.
+  kDS = 9711,
+  // UDP socket sending sensor values from the crio to the prime.
+  kSensors = 9712,
+  // HTTP server that sends out camera feeds in mjpg format.
+  // Should not be changed because this number shows up elsewhere too.
+  kCameraStreamer = 9714,
+};
+
+// Constants representing the various devices that talk on the network and the
+// last segment of their IP addresses.
+enum class NetworkAddress : uint8_t {
+  // The computer that the cRIO talks to.
+  kPrime = 179,
+  kCRIO = 2,
+};
+
+}  // namespace aos
+
+#endif  // AOS_COMMON_NETWORK_PORT_H_
diff --git a/aos/common/once-tmpl.h b/aos/common/once-tmpl.h
new file mode 100644
index 0000000..0618395
--- /dev/null
+++ b/aos/common/once-tmpl.h
@@ -0,0 +1,43 @@
+#ifdef __VXWORKS__
+#include <taskLib.h>
+#else
+#include <sched.h>
+#endif
+
+#include "aos/common/type_traits.h"
+
+// It doesn't use pthread_once, because Brian looked at the pthreads
+// implementation for vxworks and noticed that it is completely and entirely
+// broken for doing just about anything (including its pthread_once). It has the
+// same implementation under linux for simplicity.
+
+namespace aos {
+
+// Setting function_ multiple times would be OK because it'll get set to the
+// same value each time.
+template<typename T>
+Once<T>::Once(Function function)
+    : function_(function) {
+  static_assert(shm_ok<Once<T>>::value, "Once should work in shared memory");
+}
+
+template<typename T>
+void Once<T>::Reset() {
+  __atomic_store_n(&run_, false, __ATOMIC_SEQ_CST);
+  __atomic_store_n(&done_, false, __ATOMIC_SEQ_CST);
+}
+
+template<typename T>
+T *Once<T>::Get() {
+  if (__atomic_exchange_n(&run_, true, __ATOMIC_RELAXED) == false) {
+    result_ = function_();
+    __atomic_store_n(&done_, true, __ATOMIC_RELEASE);
+  } else {
+    while (!__atomic_load_n(&done_, __ATOMIC_ACQUIRE)) {
+      sched_yield();
+    }
+  }
+  return result_;
+}
+
+}  // namespace aos
diff --git a/aos/common/once.h b/aos/common/once.h
new file mode 100644
index 0000000..b7fbcb1
--- /dev/null
+++ b/aos/common/once.h
@@ -0,0 +1,69 @@
+#ifndef AOS_COMMON_ONCE_H_
+#define AOS_COMMON_ONCE_H_
+
+#include <stdint.h>
+
+#include "aos/common/gtest_prod.h"
+
+namespace aos {
+namespace testing {
+
+FORWARD_DECLARE_TEST_CASE(OnceTest, MemoryClearing);
+
+}  // namespace testing
+
+// Designed for the same thing as pthread_once: to run something exactly 1 time.
+//
+// Intended use case:
+//   const char *CalculateSomethingCool() {
+//     static ::aos::Once<const char> once(DoCalculateSomethingCool);
+//     return once.Get();
+//   }
+//
+// IMPORTANT: Instances _must_ be placed in memory that gets 0-initialized
+// automatically or Reset() must be called exactly once!!
+// The expected use case is to use one of these as a static variable, and those
+// do get 0-initialized under the C++ standard. Global variables are treated the
+// same way by the C++ Standard.
+// Placing an instance in shared memory (and using Reset()) is also supported.
+// The constructor does not initialize all of the member variables!
+// This is because initializing them in the constructor creates a race condition
+// if initialization of static variables isn't thread safe.
+template<typename T>
+class Once {
+ public:
+  typedef T *(*Function)();
+  explicit Once(Function function);
+
+  // Returns the result of calling function_. The first call will actually run
+  // it and then any other ones will block (if necessary) until it's finished
+  // and then return the same thing.
+  T *Get();
+
+  // Will clear out all the member variables. If this is going to be used
+  // instead of creating an instance in 0-initialized memory, then this method
+  // must be called exactly once before Get() is called anywhere.
+  // This method can also be called to run the function again the next time
+  // Get() is called. However, calling it again is not thread safe.
+  void Reset();
+
+ private:
+  // The function to run to calculate result_.
+  Function function_;
+  // Whether or not it is running. Gets atomically swapped from false to true by
+  // the thread that actually runs function_.
+  bool run_;
+  // Whether or not it is done. Gets set to true after the thread that is
+  // running function_ finishes running it and storing the result in result_.
+  bool done_;
+  // What function_ returned when it was executed.
+  T *result_;
+
+  FRIEND_TEST_NAMESPACE(OnceTest, MemoryClearing, testing);
+};
+
+}  // namespace aos
+
+#include "aos/common/once-tmpl.h"
+
+#endif  // AOS_COMMON_ONCE_H_
diff --git a/aos/common/once_test.cc b/aos/common/once_test.cc
new file mode 100644
index 0000000..3773b5b
--- /dev/null
+++ b/aos/common/once_test.cc
@@ -0,0 +1,130 @@
+#include "aos/common/once.h"
+
+#include <stdlib.h>
+#include <limits.h>
+
+#include "gtest/gtest.h"
+
+namespace aos {
+namespace testing {
+
+class OnceTest : public ::testing::Test {
+ public:
+  static int *Function() {
+    ++times_run_;
+    value_ = 971 + times_run_;
+    return &value_;
+  }
+
+ protected:
+  void SetUp() {
+    value_ = 0;
+    times_run_ = 0;
+  }
+
+  static int value_;
+  static int times_run_;
+};
+int OnceTest::value_, OnceTest::times_run_;
+
+// Makes sure that it calls the function at the right time and that it correctly
+// passes the result out.
+TEST_F(OnceTest, Works) {
+  static Once<int> once(Function);
+
+  EXPECT_EQ(0, value_);
+  EXPECT_EQ(0, times_run_);
+
+  EXPECT_EQ(value_, *once.Get());
+  EXPECT_NE(0, value_);
+  EXPECT_NE(0, times_run_);
+  // Make sure it's not passing it through an assignment by value or something
+  // else weird.
+  EXPECT_EQ(&value_, once.Get());
+}
+
+// Makes sure that having a Once at namespace scope works correctly.
+namespace {
+
+Once<int> global_once(OnceTest::Function);
+
+}  // namespace
+
+TEST_F(OnceTest, Global) {
+  EXPECT_EQ(value_, *global_once.Get());
+  EXPECT_NE(0, value_);
+  EXPECT_NE(0, times_run_);
+}
+
+// Makes sure that an instance keeps returning the same value without running
+// the function again.
+TEST_F(OnceTest, MultipleGets) {
+  static Once<int> once(Function);
+
+  EXPECT_EQ(value_, *once.Get());
+  EXPECT_EQ(1, times_run_);
+  EXPECT_EQ(value_, *once.Get());
+  EXPECT_EQ(1, times_run_);
+  EXPECT_EQ(value_, *once.Get());
+  EXPECT_EQ(1, times_run_);
+}
+
+// Tests to make sure that the right methods clear out the instance variables at
+// the right times.
+TEST_F(OnceTest, MemoryClearing) {
+  Once<int> once(NULL);
+
+  once.run_ = 1;
+  once.done_ = true;
+  // Run the constructor again to make sure it doesn't touch the variables set
+  // above.
+  new (&once)Once<int>(Function);
+
+  // Should return a random, (potentially) uninitialized value.
+  once.Get();
+  EXPECT_EQ(0, times_run_);
+
+  once.Reset();
+  EXPECT_EQ(0, times_run_);
+  EXPECT_EQ(value_, *once.Get());
+  EXPECT_EQ(1, times_run_);
+}
+
+namespace {
+
+int second_result = 0;
+int *SecondFunction() {
+  static int result = 254;
+  second_result = ++result;
+  return &second_result;
+}
+
+}  // namespace
+
+// Makes sure that multiple instances don't interfere with each other.
+TEST_F(OnceTest, MultipleInstances) {
+  static Once<int> once1(Function);
+  static Once<int> once2(SecondFunction);
+
+  EXPECT_EQ(&value_, once1.Get());
+  EXPECT_EQ(&second_result, once2.Get());
+  EXPECT_EQ(&value_, once1.Get());
+  EXPECT_EQ(&second_result, once2.Get());
+}
+
+// Tests calling Reset() to run the function a second time.
+TEST_F(OnceTest, Recalculate) {
+  Once<int> once(Function);
+  once.Reset();
+
+  EXPECT_EQ(value_, *once.Get());
+  EXPECT_EQ(1, times_run_);
+
+  value_ = 0;
+  once.Reset();
+  EXPECT_EQ(value_, *once.Get());
+  EXPECT_EQ(2, times_run_);
+}
+
+}  // namespace testing
+}  // namespace aos
diff --git a/aos/common/print_field_helpers.h b/aos/common/print_field_helpers.h
new file mode 100644
index 0000000..0dd2fab
--- /dev/null
+++ b/aos/common/print_field_helpers.h
@@ -0,0 +1,41 @@
+#ifndef AOS_COMMON_PRINT_FIELD_HELPERS_H_
+#define AOS_COMMON_PRINT_FIELD_HELPERS_H_
+
+#include <stdint.h>
+
+#include <type_traits>
+
+namespace aos {
+
+template<typename T>
+inline bool PrintInteger(char *buf, T val, size_t *output) {
+  static const bool is_signed = ::std::is_signed<T>::value;
+  const bool is_negative =
+      is_signed ? (val & (static_cast<T>(1) << (sizeof(T) * 8 - 1))) : false;
+
+  size_t len = 0;
+  if (is_negative) {
+    do {
+      if (len == *output) return false;
+      buf[len++] = '0' - (val % 10);
+      val /= 10;
+    } while (val != 0);
+    if (len == *output) return false;
+    buf[len++] = '-';
+  } else {
+    do {
+      if (len == *output) return false;
+      buf[len++] = '0' + (val % 10);
+      val /= 10;
+    } while (val != 0);
+  }
+  for (size_t i = 0; i < (len >> 1); i++) {
+    std::swap(buf[len - 1 - i], buf[i]);
+  }
+  *output -= len;
+  return true;
+}
+
+}  // namespace aos
+
+#endif  // AOS_COMMON_PRINT_FIELD_HELPERS_H_
diff --git a/aos/common/queue.cc b/aos/common/queue.cc
new file mode 100644
index 0000000..893e62b
--- /dev/null
+++ b/aos/common/queue.cc
@@ -0,0 +1,37 @@
+#include "aos/common/queue.h"
+
+#include "aos/common/byteorder.h"
+#include <inttypes.h>
+
+namespace aos {
+
+void Message::Zero() {
+  sent_time.set_sec(0);
+  sent_time.set_nsec(0);
+}
+
+size_t Message::Deserialize(const char *buffer) {
+  int32_t sec;
+  int32_t nsec;
+  to_host(&buffer[0], &sec);
+  to_host(&buffer[4], &nsec);
+  sent_time.set_sec(sec);
+  sent_time.set_nsec(nsec);
+  return Size();
+}
+// Serializes the common fields into the buffer.
+size_t Message::Serialize(char *buffer) const {
+  // TODO(aschuh): to_network shouldn't need a pointer.
+  int32_t sec = sent_time.sec();
+  int32_t nsec = sent_time.nsec();
+  to_network(&sec, &buffer[0]);
+  to_network(&nsec, &buffer[4]);
+  return Size();
+}
+
+size_t Message::Print(char *buffer, int length) const {
+  return snprintf(buffer, length, "%" PRId32 ".%09" PRId32 "s",
+                  sent_time.sec(), sent_time.nsec());
+}
+
+}  // namespace aos
diff --git a/aos/common/queue.h b/aos/common/queue.h
new file mode 100644
index 0000000..5f6adeb
--- /dev/null
+++ b/aos/common/queue.h
@@ -0,0 +1,282 @@
+#ifndef AOS_COMMON_QUEUE_H_
+#define AOS_COMMON_QUEUE_H_
+
+#include <assert.h>
+
+#include "aos/common/time.h"
+#include "aos/common/macros.h"
+#include "aos/linux_code/ipc_lib/queue.h"
+#include "aos/common/time.h"
+
+namespace aos {
+
+struct MessageType;
+
+// This class is a base class for all messages sent over queues.
+// All of the methods are overloaded in (generated) subclasses to do the same
+// thing for the whole thing.
+class Message {
+ public:
+  typedef ::aos::time::Time Time;
+  // The time that the message was sent at.
+  Time sent_time;
+
+  Message() : sent_time(0, 0) {}
+
+  // Zeros out the time.
+  void Zero();
+  // Returns the size of the common fields.
+  static size_t Size() { return sizeof(Time); }
+
+  // Deserializes the common fields from the buffer.
+  size_t Deserialize(const char *buffer);
+  // Serializes the common fields into the buffer.
+  size_t Serialize(char *buffer) const;
+
+  // Populates sent_time with the current time.
+  void SetTimeToNow() { sent_time = Time::Now(); }
+
+  // Writes the contents of the message to the provided buffer.
+  size_t Print(char *buffer, int length) const;
+
+  // Compares two messages for equality, excluding their sent_time.
+  bool EqualsNoTime(const Message & /*other*/) const { return true; }
+
+  static const MessageType *GetType();
+};
+
+template <class T> class Queue;
+template <class T> class MessageBuilder;
+template <class T> class ScopedMessagePtr;
+
+// A ScopedMessagePtr<> manages a queue message pointer.
+// It frees it properly when the ScopedMessagePtr<> goes out of scope or gets
+// sent.  By design, there is no way to get the ScopedMessagePtr to release the
+// message pointer to external code.
+template <class T>
+class ScopedMessagePtr {
+ public:
+  // Returns a pointer to the message.
+  // This stays valid until Send or the destructor have been called.
+  const T *get() const { return msg_; }
+  T *get() { return msg_; }
+
+  const T &operator*() const {
+    const T *msg = get();
+    assert(msg != NULL);
+    return *msg;
+  }
+
+  T &operator*() {
+    T *msg = get();
+    assert(msg != NULL);
+    return *msg;
+  }
+
+  const T *operator->() const {
+    const T *msg = get();
+    assert(msg != NULL);
+    return msg;
+  }
+
+  T *operator->() {
+    T *msg = get();
+    assert(msg != NULL);
+    return msg;
+  }
+
+  operator bool() {
+    return msg_ != NULL;
+  }
+
+  // Sends the message and removes our reference to it.
+  // If the queue is full, over-ride the oldest message in it with our new
+  // message.
+  // Returns true on success, and false otherwise.
+  // The message will be freed.
+  bool Send();
+
+  // Sends the message and removes our reference to it.
+  // If the queue is full, block until it is no longer full.
+  // Returns true on success, and false otherwise.
+  // The message will be freed.
+  bool SendBlocking();
+
+  // Frees the contained message.
+  ~ScopedMessagePtr() {
+    reset();
+  }
+
+  // Implements a move constructor.  This only takes rvalue references
+  // because we want to allow someone to say
+  // ScopedMessagePtr<X> ptr = queue.MakeMessage();
+  // but we don't want to allow them to then say
+  // ScopedMessagePtr<X> new_ptr = ptr;
+  // And, if they do actually want to move the pointer, then it will correctly
+  // clear out the source so there aren't 2 pointers to the message lying
+  // around.
+  ScopedMessagePtr(ScopedMessagePtr<T> &&ptr)
+      : queue_(ptr.queue_), msg_(ptr.msg_) {
+    ptr.msg_ = NULL;
+  }
+
+ private:
+  // Provide access to set_queue and the constructor for init.
+  friend class aos::Queue<typename std::remove_const<T>::type>;
+  // Provide access to the copy constructor for MakeWithBuilder.
+  friend class aos::MessageBuilder<T>;
+
+  // Only Queue should be able to build a message.
+  ScopedMessagePtr(RawQueue *queue, T *msg)
+      : queue_(queue), msg_(msg) {}
+
+  // Sets the pointer to msg, freeing the old value if it was there.
+  // This is private because nobody should be able to get a pointer to a message
+  // that needs to be scoped without using the queue.
+  void reset(T *msg = NULL);
+
+  // Sets the queue that owns this message.
+  void set_queue(RawQueue *queue) { queue_ = queue; }
+
+  // The queue that the message is a part of.
+  RawQueue *queue_;
+  // The message or NULL.
+  T *msg_;
+
+  // Protect evil constructors.
+  DISALLOW_COPY_AND_ASSIGN(ScopedMessagePtr<T>);
+};
+
+// Specializations for the Builders will be automatically generated in the .q.h
+// header files with all of the handy builder methods.
+template <class T>
+class MessageBuilder {
+ public:
+  typedef T Message;
+  bool Send();
+};
+
+// TODO(aschuh): Base class
+// T must be a Message with the same format as the messages generated by
+// the .q files.
+template <class T>
+class Queue {
+ public:
+  typedef T Message;
+
+  Queue(const char *queue_name)
+      : queue_name_(queue_name), queue_(NULL), queue_msg_(NULL, NULL) {
+    static_assert(shm_ok<T>::value,
+                  "The provided message type can't be put in shmem.");
+  }
+
+  // Initializes the queue.  This may optionally be called to do any one time
+  // work before sending information, and may be be called multiple times.
+  // Init will be called when a message is sent, but this will cause sending to
+  // take a different amount of time the first cycle.
+  void Init();
+
+  // Removes all internal references to shared memory so shared memory can be
+  // restarted safely.  This should only be used in testing.
+  void Clear();
+
+  // Fetches the next message from the queue.
+  // Returns true if there was a new message available and we successfully
+  // fetched it.
+  bool FetchNext();
+
+  // Fetches the next message from the queue, waiting if necessary until there
+  // is one.
+  void FetchNextBlocking();
+
+  // Fetches the last message from the queue.
+  // Returns true if there was a new message available and we successfully
+  // fetched it.
+  bool FetchLatest();
+
+  // Fetches the latest message from the queue, or blocks if we have already
+  // fetched it until another is avilable.
+  void FetchAnother();
+
+  // Returns the age of the message.
+  const time::Time Age() const {
+    return time::Time::Now() - queue_msg_->sent_time;
+  }
+
+  // Returns true if the latest value in the queue is newer than age mseconds.
+  // DEPRECATED(brians): Use IsNewerThan(const time::Time&) instead.
+  bool IsNewerThanMS(int age) const {
+    // TODO(aschuh): Log very verbosely if something is _ever_ stale.
+    return IsNewerThan(time::Time::InMS(age));
+  }
+
+  bool IsNewerThan(const time::Time &age) const {
+    return get() != nullptr && Age() < age;
+  }
+
+  // Returns a pointer to the current message.
+  // This pointer will be valid until a new message is fetched.
+  const T *get() const { return queue_msg_.get(); }
+
+  // Returns a reference to the message.
+  // The message will be valid until a new message is fetched.
+  const T &operator*() const {
+    const T *msg = get();
+    assert(msg != NULL);
+    return *msg;
+  }
+
+  // Returns a pointer to the current message.
+  // This pointer will be valid until a new message is fetched.
+  const T *operator->() const {
+    const T *msg = get();
+    assert(msg != NULL);
+    return msg;
+  }
+
+  // Returns a scoped_ptr containing a message.
+  // GCC will optimize away the copy constructor, so this is safe.
+  ScopedMessagePtr<T> MakeMessage();
+
+  // Returns a message builder that contains a pre-allocated message.
+  // This message will start out completely zeroed.
+  aos::MessageBuilder<T> MakeWithBuilder();
+
+  const char *name() const { return queue_name_; }
+
+ private:
+  const char *queue_name_;
+
+  T *MakeRawMessage();
+
+  // Pointer to the queue that this object fetches from.
+  RawQueue *queue_;
+  int index_ = 0;
+  // Scoped pointer holding the latest message or NULL.
+  ScopedMessagePtr<const T> queue_msg_;
+
+  DISALLOW_COPY_AND_ASSIGN(Queue<T>);
+};
+
+// Base class for all queue groups.
+class QueueGroup {
+ public:
+  // Constructs a queue group given its name and a unique hash of the name and
+  // type.
+  QueueGroup(const char *name, uint32_t hash) : name_(name), hash_(hash) {}
+
+  // Returns the name of the queue group.
+  const char *name() const { return name_.c_str(); }
+  // Returns a unique hash representing this instance of the queue group.
+  uint32_t hash() const { return hash_; }
+
+ private:
+  std::string name_;
+  uint32_t hash_;
+};
+
+}  // namespace aos
+
+#include "aos/linux_code/queue-tmpl.h"
+
+#endif  // AOS_COMMON_QUEUE_H_
diff --git a/aos/common/queue_test.cc b/aos/common/queue_test.cc
new file mode 100644
index 0000000..310301d
--- /dev/null
+++ b/aos/common/queue_test.cc
@@ -0,0 +1,324 @@
+#include <unistd.h>
+
+#include <memory>
+
+#include "gtest/gtest.h"
+#include "aos/common/test_queue.q.h"
+#include "aos/common/queue_testutils.h"
+#include "aos/common/util/thread.h"
+#include "aos/common/die.h"
+
+using ::aos::time::Time;
+
+namespace aos {
+namespace common {
+namespace testing {
+
+class QueueTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    SetDieTestMode(true);
+  }
+
+  GlobalCoreInstance my_core;
+  // Create a new instance of the test queue so that it invalidates the queue
+  // that it points to.  Otherwise, we will have a pointer to shared memory that
+  // is no longer valid.
+  ::aos::Queue<TestingMessage> my_test_queue;
+
+  QueueTest() : my_test_queue(".aos.common.testing.test_queue") {}
+};
+
+class MyThread : public util::Thread {
+ public:
+  MyThread() : threaded_test_queue(".aos.common.testing.test_queue") {}
+
+  virtual void Run() {
+    threaded_test_queue.FetchNextBlocking();
+    EXPECT_TRUE(threaded_test_queue->test_bool);
+    EXPECT_EQ(0x971, threaded_test_queue->test_int);
+  }
+
+  ::aos::Queue<TestingMessage> threaded_test_queue;
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MyThread);
+};
+
+
+// Tests that we can send a message to another thread and it blocking receives
+// it at the correct time.
+TEST_F(QueueTest, FetchBlocking) {
+  MyThread t;
+  t.Start();
+  usleep(50000);
+  my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x971).Send();
+  t.Join();
+  EXPECT_LE(t.threaded_test_queue.Age(), time::Time::InMS(57));
+}
+
+// Tests that we can send a message with the message pointer and get it back.
+TEST_F(QueueTest, SendMessage) {
+  ScopedMessagePtr<TestingMessage> msg = my_test_queue.MakeMessage();
+  msg->test_bool = true;
+  msg->test_int = 0x971;
+  msg.Send();
+
+  ASSERT_TRUE(my_test_queue.FetchLatest());
+  EXPECT_TRUE(my_test_queue->test_bool);
+  EXPECT_EQ(0x971, my_test_queue->test_int);
+}
+
+// Tests that we can send a message with the builder and get it back.
+TEST_F(QueueTest, SendWithBuilder) {
+  my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x971).Send();
+
+  ASSERT_TRUE(my_test_queue.FetchLatest());
+  EXPECT_EQ(true, my_test_queue->test_bool);
+  EXPECT_EQ(0x971, my_test_queue->test_int);
+  EXPECT_EQ(true, my_test_queue.IsNewerThanMS(10000));
+}
+
+// Tests that multiple queue instances don't break each other.
+TEST_F(QueueTest, MultipleQueues) {
+  my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x971).Send();
+  ASSERT_TRUE(my_test_queue.FetchLatest());
+  EXPECT_TRUE(my_test_queue.get());
+
+  {
+    ::aos::Queue<TestingMessage> my_other_test_queue(
+        ".aos.common.testing.queue_name");
+    my_other_test_queue.MakeMessage();
+    EXPECT_FALSE(my_other_test_queue.FetchLatest());
+    EXPECT_FALSE(my_test_queue.FetchLatest());
+  }
+
+  EXPECT_TRUE(my_test_queue.get());
+}
+
+// Tests that using a queue from multiple threads works correctly.
+TEST_F(QueueTest, MultipleThreads) {
+  my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x971).Send();
+  ASSERT_TRUE(my_test_queue.FetchLatest());
+  my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x254).Send();
+  EXPECT_EQ(0x971, my_test_queue->test_int);
+
+  ::aos::util::FunctionThread::RunInOtherThread([this]() {
+    ASSERT_TRUE(my_test_queue.FetchLatest());
+    EXPECT_EQ(0x254, my_test_queue->test_int);
+  });
+  EXPECT_EQ(0x254, my_test_queue->test_int);
+}
+
+// Makes sure that MakeWithBuilder zeros the message initially.
+// This might randomly succeed sometimes, but it will fail with asan if it
+// doesn't.
+TEST_F(QueueTest, BuilderZero) {
+  my_test_queue.MakeWithBuilder().Send();
+
+  ASSERT_TRUE(my_test_queue.FetchLatest());
+  EXPECT_FALSE(my_test_queue->test_bool);
+  EXPECT_EQ(0, my_test_queue->test_int);
+}
+
+// Tests that various pointer deref functions at least seem to work.
+TEST_F(QueueTest, PointerDeref) {
+  my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x971).Send();
+
+  ASSERT_TRUE(my_test_queue.FetchLatest());
+  const TestingMessage *msg_ptr = my_test_queue.get();
+  ASSERT_NE(static_cast<TestingMessage*>(NULL), msg_ptr);
+  EXPECT_EQ(0x971, msg_ptr->test_int);
+  EXPECT_EQ(msg_ptr, &(*my_test_queue));
+}
+
+// Tests that FetchNext doesn't miss any messages.
+TEST_F(QueueTest, FetchNext) {
+  for (int i = 0; i < 10; ++i) {
+    my_test_queue.MakeWithBuilder().test_bool(true).test_int(i).Send();
+  }
+
+  for (int i = 0; i < 10; ++i) {
+    ASSERT_TRUE(my_test_queue.FetchNext());
+    EXPECT_EQ(i, my_test_queue->test_int);
+  }
+}
+
+// Tests that FetchLatest skips a missing message.
+TEST_F(QueueTest, FetchLatest) {
+  my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x254).Send();
+  my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x971).Send();
+
+  ASSERT_TRUE(my_test_queue.FetchLatest());
+  EXPECT_EQ(0x971, my_test_queue->test_int);
+}
+
+// Tests that FetchLatest works with multiple readers.
+TEST_F(QueueTest, FetchLatestMultiple) {
+  ::aos::Queue<TestingMessage> my_second_test_queue(
+      ".aos.common.testing.test_queue");
+  my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x254).Send();
+  my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x971).Send();
+
+  ASSERT_TRUE(my_test_queue.FetchLatest());
+  EXPECT_EQ(0x971, my_test_queue->test_int);
+  ASSERT_TRUE(my_second_test_queue.FetchLatest());
+  ASSERT_TRUE(my_second_test_queue.get() != NULL);
+  EXPECT_EQ(0x971, my_second_test_queue->test_int);
+}
+
+
+// Tests that fetching without a new message returns false.
+TEST_F(QueueTest, FetchLatestWithoutMessage) {
+  my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x254).Send();
+  EXPECT_TRUE(my_test_queue.FetchLatest());
+  EXPECT_FALSE(my_test_queue.FetchLatest());
+  EXPECT_FALSE(my_test_queue.FetchLatest());
+  EXPECT_EQ(0x254, my_test_queue->test_int);
+}
+
+// Tests that fetching without a message returns false.
+TEST_F(QueueTest, FetchOnFreshQueue) {
+  EXPECT_FALSE(my_test_queue.FetchLatest());
+  EXPECT_EQ(static_cast<TestingMessage*>(NULL), my_test_queue.get());
+}
+
+// Tests that fetch next without a message returns false.
+TEST_F(QueueTest, FetchNextOnFreshQueue) {
+  EXPECT_FALSE(my_test_queue.FetchNext());
+  EXPECT_EQ(static_cast<TestingMessage*>(NULL), my_test_queue.get());
+}
+
+// Tests that fetch next without a new message returns false.
+TEST_F(QueueTest, FetchNextWithoutMessage) {
+  my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x254).Send();
+  EXPECT_TRUE(my_test_queue.FetchNext());
+  EXPECT_FALSE(my_test_queue.FetchNext());
+  EXPECT_NE(static_cast<TestingMessage*>(NULL), my_test_queue.get());
+}
+
+// Tests that age makes some sense.
+TEST_F(QueueTest, Age) {
+  my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x971).Send();
+
+  ASSERT_TRUE(my_test_queue.FetchLatest());
+  EXPECT_TRUE(my_test_queue.IsNewerThanMS(100));
+  const Time age = my_test_queue.Age();
+  EXPECT_EQ(0, age.sec());
+  EXPECT_GE(100000000, age.nsec());
+}
+
+
+class GroupTest : public ::testing::Test {
+ protected:
+  GlobalCoreInstance my_core;
+  // Create a new instance of the test group so that it invalidates the queue
+  // that it points to.  Otherwise, we will have a pointer to shared memory that
+  // is no longer valid.
+  TwoQueues my_test_queuegroup;
+
+  GroupTest()
+      : my_test_queuegroup(".aos.common.testing.test_queuegroup",
+                           0x20561114,
+                           ".aos.common.testing.test_queuegroup.first",
+                           ".aos.common.testing.test_queuegroup.second") {}
+};
+
+// Tests that the hash gets preserved.
+TEST_F(GroupTest, Hash) {
+  EXPECT_EQ(static_cast<uint32_t>(0x20561114), my_test_queuegroup.hash());
+}
+
+// Tests that the hash works.
+TEST_F(GroupTest, RealHash) {
+  EXPECT_EQ(static_cast<uint32_t>(0x93596b2f), test_queuegroup.hash());
+}
+
+// Tests that name works.
+TEST_F(GroupTest, Name) {
+  EXPECT_EQ(std::string(".aos.common.testing.test_queuegroup"),
+            std::string(my_test_queuegroup.name()));
+}
+
+
+class MessageTest : public ::testing::Test {
+ public:
+  TestingMessage msg;
+};
+
+TEST_F(MessageTest, Zeroing) {
+  msg.test_bool = true;
+  msg.test_int = 0x254;
+  msg.SetTimeToNow();
+
+  msg.Zero();
+
+  EXPECT_FALSE(msg.test_bool);
+  EXPECT_EQ(0, msg.test_int);
+  EXPECT_EQ(0, msg.sent_time.sec());
+  EXPECT_EQ(0, msg.sent_time.nsec());
+}
+
+TEST_F(MessageTest, Size) {
+  EXPECT_EQ(static_cast<size_t>(13), msg.Size());
+}
+
+TEST_F(MessageTest, Serialize) {
+  char serialized_data[msg.Size()];
+  msg.test_bool = true;
+  msg.test_int = 0x254;
+  msg.SetTimeToNow();
+
+  msg.Serialize(serialized_data);
+
+  TestingMessage new_msg;
+  new_msg.Deserialize(serialized_data);
+
+  EXPECT_EQ(msg.test_bool, new_msg.test_bool);
+  EXPECT_EQ(msg.test_int, new_msg.test_int);
+  EXPECT_EQ(msg.sent_time, new_msg.sent_time);
+}
+
+// Tests that Print prints out a message nicely.
+TEST_F(MessageTest, Print) {
+  char printdata[1024];
+  msg.test_bool = true;
+  msg.test_int = 2056;
+  msg.sent_time = Time(971, 254);
+
+  std::string golden("971.000000254s, T, 2056");
+  EXPECT_EQ(golden.size(), msg.Print(printdata, sizeof(printdata)));
+
+  EXPECT_EQ(golden, std::string(printdata));
+}
+
+// Tests that the hash never changes.  If it changes, then someone broke the
+// hash routine or changed the message declaration.  Both changes need to be
+// validated by hand.
+TEST_F(MessageTest, Hash) {
+  EXPECT_EQ(static_cast<uint32_t>(0xc33651ac),
+            static_cast<uint32_t>(TestingMessage::kHash));
+}
+
+TEST_F(MessageTest, SetNow) {
+  msg.SetTimeToNow();
+  EXPECT_LE(msg.sent_time - Time::Now(), Time::InMS(20));
+}
+
+// Tests that EqualsNoTime works.
+TEST_F(MessageTest, EqualsNoTime) {
+  msg.test_bool = true;
+  msg.test_int = 971;
+  TestingMessage other;
+  other.test_int = 971;
+  EXPECT_FALSE(other.EqualsNoTime(msg));
+  EXPECT_FALSE(msg.EqualsNoTime(other));
+  other.test_bool = true;
+  EXPECT_TRUE(other.EqualsNoTime(msg));
+  EXPECT_TRUE(msg.EqualsNoTime(other));
+  msg.SetTimeToNow();
+  EXPECT_TRUE(msg.EqualsNoTime(other));
+}
+
+}  // namespace testing
+}  // namespace common
+}  // namespace aos
diff --git a/aos/common/queue_testutils.cc b/aos/common/queue_testutils.cc
new file mode 100644
index 0000000..a40b5e9
--- /dev/null
+++ b/aos/common/queue_testutils.cc
@@ -0,0 +1,177 @@
+#include "aos/common/queue_testutils.h"
+
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "gtest/gtest.h"
+
+#include "aos/common/queue.h"
+#include "aos/common/logging/logging_impl.h"
+#include "aos/common/once.h"
+#include "aos/common/mutex.h"
+
+using ::aos::logging::LogMessage;
+
+namespace aos {
+namespace common {
+namespace testing {
+namespace {
+
+class TestLogImplementation : public logging::HandleMessageLogImplementation {
+ public:
+  const ::std::vector<LogMessage> &messages() { return messages_; }
+
+  // This class has to be a singleton so that everybody can get access to the
+  // same instance to read out the messages etc.
+  static TestLogImplementation *GetInstance() {
+    static Once<TestLogImplementation> once(CreateInstance);
+    return once.Get();
+  }
+
+  // Clears out all of the messages already recorded.
+  void ClearMessages() {
+    ::aos::MutexLocker locker(&messages_mutex_);
+    messages_.clear();
+  }
+
+  // Prints out all of the messages (like when a test fails).
+  void PrintAllMessages() {
+    ::aos::MutexLocker locker(&messages_mutex_);
+    for (auto it = messages_.begin(); it != messages_.end(); ++it) {
+      logging::internal::PrintMessage(stdout, *it);
+    }
+  }
+
+  void SetOutputFile(const char *filename) {
+    if (strcmp("-", filename) != 0) {
+      FILE *newfile = fopen(filename, "w");
+
+      if (newfile) {
+        output_file_ = newfile;
+      }
+    }
+  }
+
+  void PrintMessagesAsTheyComeIn() { print_as_messages_come_in_ = true; }
+
+ private:
+  TestLogImplementation() {}
+  ~TestLogImplementation() {
+    if (output_file_ != stdout) {
+      fclose(output_file_);
+    }
+  }
+
+  static TestLogImplementation *CreateInstance() {
+    return new TestLogImplementation();
+  }
+
+  virtual void HandleMessage(const LogMessage &message) override {
+    ::aos::MutexLocker locker(&messages_mutex_);
+    if (message.level == FATAL || print_as_messages_come_in_) {
+      logging::internal::PrintMessage(output_file_, message);
+    }
+
+    messages_.push_back(message);
+  }
+
+  ::std::vector<LogMessage> messages_;
+  bool print_as_messages_come_in_ = false;
+  FILE *output_file_ = stdout;
+  ::aos::Mutex messages_mutex_;
+};
+
+class MyTestEventListener : public ::testing::EmptyTestEventListener {
+  virtual void OnTestStart(const ::testing::TestInfo &/*test_info*/) {
+    TestLogImplementation::GetInstance()->ClearMessages();
+  }
+  virtual void OnTestEnd(const ::testing::TestInfo &test_info) {
+    if (test_info.result()->Failed()) {
+      printf("Test %s failed. Use '--print-logs' to see all log messages.\n",
+             test_info.name());
+    }
+  }
+
+  virtual void OnTestPartResult( const ::testing::TestPartResult &result) {
+    if (result.failed()) {
+      const char *failure_type = "unknown";
+      switch (result.type()) {
+        case ::testing::TestPartResult::Type::kNonFatalFailure:
+          failure_type = "EXPECT";
+          break;
+        case ::testing::TestPartResult::Type::kFatalFailure:
+          failure_type = "ASSERT";
+          break;
+        case ::testing::TestPartResult::Type::kSuccess:
+          break;
+      }
+      log_do(ERROR, "%s: %d: gtest %s failure\n%s\n",
+             result.file_name(),
+             result.line_number(),
+             failure_type,
+             result.message());
+    }
+  }
+};
+
+void *DoEnableTestLogging() {
+  logging::Init();
+  logging::AddImplementation(TestLogImplementation::GetInstance());
+
+  ::testing::UnitTest::GetInstance()->listeners().Append(
+      new MyTestEventListener());
+
+  return NULL;
+}
+
+Once<void> enable_test_logging_once(DoEnableTestLogging);
+
+const size_t kCoreSize = 0x100000;
+
+void TerminateExitHandler() {
+  _exit(EXIT_SUCCESS);
+}
+
+}  // namespace
+
+GlobalCoreInstance::GlobalCoreInstance() {
+  global_core = &global_core_data_;
+  global_core->owner = true;
+  // Use mmap(2) manually instead of through malloc(3) so that we can pass
+  // MAP_SHARED which allows forked processes to communicate using the
+  // "shared" memory.
+  void *memory = mmap(NULL, kCoreSize, PROT_READ | PROT_WRITE,
+                      MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+  CHECK_NE(memory, MAP_FAILED);
+
+  aos_core_use_address_as_shared_mem(memory, kCoreSize);
+
+  EnableTestLogging();
+}
+
+GlobalCoreInstance::~GlobalCoreInstance() {
+  PCHECK(munmap(global_core->mem_struct, kCoreSize));
+  global_core = NULL;
+}
+
+void EnableTestLogging() {
+  enable_test_logging_once.Get();
+}
+
+void PreventExit() {
+  CHECK_EQ(atexit(TerminateExitHandler), 0);
+}
+
+void SetLogFileName(const char* filename) {
+  TestLogImplementation::GetInstance()->SetOutputFile(filename);
+}
+
+void ForcePrintLogsDuringTests() {
+  TestLogImplementation::GetInstance()->PrintMessagesAsTheyComeIn();
+}
+
+}  // namespace testing
+}  // namespace common
+}  // namespace aos
diff --git a/aos/common/queue_testutils.h b/aos/common/queue_testutils.h
new file mode 100644
index 0000000..fb0ffcd
--- /dev/null
+++ b/aos/common/queue_testutils.h
@@ -0,0 +1,52 @@
+#ifndef AOS_COMMON_QUEUE_TESTUTILS_H_
+#define AOS_COMMON_QUEUE_TESTUTILS_H_
+
+#include "aos/linux_code/ipc_lib/shared_mem.h"
+
+// This file has some general helper functions for dealing with testing things
+// that use shared memory etc.
+
+namespace aos {
+namespace common {
+namespace testing {
+
+// Manages creating and cleaning up "shared memory" which works within this
+// process and any that it fork(2)s.
+class GlobalCoreInstance {
+ public:
+  // Calls EnableTestLogging().
+  GlobalCoreInstance();
+  ~GlobalCoreInstance();
+
+ private:
+  struct aos_core global_core_data_;
+};
+
+// Enables the logging framework for use during a gtest test.
+// It will print out all WARNING and above messages all of the time. It will
+// also print out all log messages when a test fails.
+// This function only needs to be called once in each process (after gtest is
+// initialized), however it can be called more than that.
+void EnableTestLogging();
+
+// Registers an exit handler (using atexit(3)) which will call _exit(2).
+// Intended to be called in a freshly fork(2)ed process where it will run before
+// any other exit handlers that were already registered and prevent them from
+// being run.
+void PreventExit();
+
+// Redirect the messages enabled by EnableTestLogging() function to a file.
+// By default the messages are printed to standard output.
+void SetLogFileName(const char* filename);
+
+// Force the messages to be printed as they are handled by the logging
+// framework. This can be useful for tests that hang where no messages would
+// otherwise be printed. This is also useful for tests that do pass, but where
+// we want to use graphing tools to verify what's happening.
+void ForcePrintLogsDuringTests();
+
+}  // namespace testing
+}  // namespace common
+}  // namespace aos
+
+#endif  // AOS_COMMON_QUEUE_TESTUTILS_H_
diff --git a/aos/common/queue_testutils_test.cc b/aos/common/queue_testutils_test.cc
new file mode 100644
index 0000000..2defe74
--- /dev/null
+++ b/aos/common/queue_testutils_test.cc
@@ -0,0 +1,31 @@
+#include "aos/common/queue_testutils.h"
+
+#include <thread>
+
+#include "gtest/gtest.h"
+
+#include "aos/common/logging/logging.h"
+
+namespace aos {
+namespace common {
+namespace testing {
+
+// Tests logging from multiple threads.
+// tsan used to complain about this.
+TEST(QueueTestutilsTest, MultithreadedLog) {
+  EnableTestLogging();
+
+  ::std::thread thread([]() {
+    for (int i = 0; i < 1000; ++i) {
+      LOG(INFO, "test from thread\n");
+    }
+  });
+  for (int i = 0; i < 1000; ++i) {
+    LOG(INFO, "not from thread\n");
+  }
+  thread.join();
+}
+
+}  // namespace testing
+}  // namespace common
+}  // namespace aos
diff --git a/aos/common/queue_types.cc b/aos/common/queue_types.cc
new file mode 100644
index 0000000..9e9505d
--- /dev/null
+++ b/aos/common/queue_types.cc
@@ -0,0 +1,442 @@
+#include "aos/common/queue_types.h"
+
+#include <inttypes.h>
+
+#include <memory>
+#include <unordered_map>
+
+#include "aos/common/byteorder.h"
+#include "aos/linux_code/ipc_lib/shared_mem.h"
+#include "aos/common/logging/logging.h"
+#include "aos/linux_code/ipc_lib/core_lib.h"
+#include "aos/common/mutex.h"
+
+namespace aos {
+
+ssize_t MessageType::Serialize(char *buffer, size_t max_bytes) const {
+  char *const buffer_start = buffer;
+  uint16_t fields_size = 0;
+  for (int i = 0; i < number_fields; ++i) {
+    fields_size += sizeof(fields[i]->type);
+    fields_size += sizeof(fields[i]->length);
+    fields_size += sizeof(uint16_t);
+    fields_size += fields[i]->name.size();
+  }
+  if (max_bytes < sizeof(id) + sizeof(super_size) + sizeof(uint16_t) +
+                      sizeof(number_fields) + name.size() + fields_size) {
+    return -1;
+  }
+
+  uint16_t length;
+
+  to_network(&super_size, buffer);
+  buffer += sizeof(super_size);
+  to_network(&id, buffer);
+  buffer += sizeof(id);
+  length = name.size();
+  to_network(&length, buffer);
+  buffer += sizeof(length);
+  to_network(&number_fields, buffer);
+  buffer += sizeof(number_fields);
+  memcpy(buffer, name.data(), length);
+  buffer += name.size();
+
+  for (int i = 0; i < number_fields; ++i) {
+    to_network(&fields[i]->type, buffer);
+    buffer += sizeof(fields[i]->type);
+    to_network(&fields[i]->length, buffer);
+    buffer += sizeof(fields[i]->length);
+    length = fields[i]->name.size();
+    to_network(&length, buffer);
+    buffer += sizeof(length);
+    memcpy(buffer, fields[i]->name.data(), length);
+    buffer += length;
+  }
+
+  return buffer - buffer_start;
+}
+
+MessageType *MessageType::Deserialize(const char *buffer, size_t *bytes,
+                                      bool deserialize_length) {
+  uint16_t name_length;
+  decltype(MessageType::super_size) super_size;
+  decltype(MessageType::id) id;
+  decltype(MessageType::number_fields) number_fields;
+  if (*bytes < sizeof(super_size) + sizeof(id) + sizeof(name_length) +
+                   sizeof(number_fields)) {
+    return nullptr;
+  }
+  *bytes -= sizeof(super_size) + sizeof(id) + sizeof(name_length) +
+            sizeof(number_fields);
+
+  to_host(buffer, &super_size);
+  buffer += sizeof(super_size);
+  to_host(buffer, &id);
+  buffer += sizeof(id);
+  to_host(buffer, &name_length);
+  buffer += sizeof(name_length);
+  to_host(buffer, &number_fields);
+  buffer += sizeof(number_fields);
+
+  if (*bytes < name_length) {
+    return nullptr;
+  }
+  *bytes -= name_length;
+
+  Field **fields = new Field *[number_fields];
+  ::std::unique_ptr<MessageType> r(
+      new MessageType(super_size, id, ::std::string(buffer, name_length),
+                      number_fields, fields));
+  buffer += name_length;
+
+  for (int i = 0; i < number_fields; ++i) {
+    uint16_t field_name_length;
+    if (*bytes < sizeof(fields[i]->type) + sizeof(field_name_length) +
+                     (deserialize_length ? sizeof(fields[i]->length) : 0)) {
+      return nullptr;
+    }
+    *bytes -= sizeof(fields[i]->type) + sizeof(field_name_length);
+
+    to_host(buffer, &fields[i]->type);
+    buffer += sizeof(fields[i]->type);
+    if (deserialize_length) {
+      to_host(buffer, &fields[i]->length);
+      buffer += sizeof(fields[i]->length);
+      *bytes -= sizeof(fields[i]->length);
+    }
+    to_host(buffer, &field_name_length);
+    buffer += sizeof(field_name_length);
+
+    if (*bytes < field_name_length) {
+      return nullptr;
+    }
+    *bytes -= field_name_length;
+    fields[i]->name = ::std::string(buffer, field_name_length);
+    buffer += field_name_length;
+  }
+
+  return r.release();
+}
+
+bool PrintArray(char *output, size_t *output_bytes, const void *input,
+                size_t *input_bytes, uint32_t type_id, uint32_t length) {
+  if (*output_bytes < 1) return false;
+  *output_bytes -= 1;
+  *(output++) = '[';
+
+  bool first = true;
+  for (uint32_t i = 0; i < length; ++i) {
+    if (first) {
+      first = false;
+    } else {
+      if (*output_bytes < 2) return false;
+      *output_bytes -= 2;
+      *(output++) = ',';
+      *(output++) = ' ';
+    }
+
+    const size_t output_bytes_before = *output_bytes,
+                 input_bytes_before = *input_bytes;
+    if (MessageType::IsPrimitive(type_id)) {
+      if (!PrintField(output, output_bytes, input, input_bytes, type_id)) {
+        return false;
+      }
+    } else {
+      if (!PrintMessage(output, output_bytes, input, input_bytes,
+                        type_cache::Get(type_id))) {
+        return false;
+      }
+      // Ignore the trailing '\0' that the subcall put on.
+      *output_bytes += 1;
+    }
+
+    // Update the input and output pointers.
+    output += output_bytes_before - *output_bytes;
+    input =
+        static_cast<const char *>(input) + input_bytes_before - *input_bytes;
+  }
+  if (*output_bytes < 2) return false;
+  *output_bytes -= 2;
+  *(output++) = ']';
+  *(output++) = '\0';
+  return true;
+}
+
+bool PrintMessage(char *output, size_t *output_bytes, const void *input,
+                  size_t *input_bytes, const MessageType &type) {
+  *input_bytes -= type.super_size;
+  input = static_cast<const char *>(input) + type.super_size;
+
+  if (*output_bytes < type.name.size() + 1) return false;
+  *output_bytes -= type.name.size() + 1;
+  memcpy(output, type.name.data(), type.name.size());
+  output += type.name.size();
+  *(output++) = '{';
+
+  bool first = true;
+  for (int i = 0; i < type.number_fields; ++i) {
+    if (first) {
+      first = false;
+    } else {
+      if (*output_bytes < 2) return false;
+      *output_bytes -= 2;
+      *(output++) = ',';
+      *(output++) = ' ';
+    }
+
+    if (*output_bytes < type.fields[i]->name.size() + 1) return false;
+    *output_bytes -= type.fields[i]->name.size() + 1;
+    memcpy(output, type.fields[i]->name.data(), type.fields[i]->name.size());
+    output += type.fields[i]->name.size();
+    *(output++) = ':';
+
+    const size_t output_bytes_before = *output_bytes,
+                 input_bytes_before = *input_bytes;
+    const uint32_t type_id = type.fields[i]->type;
+    if (type.fields[i]->length > 0) {
+      if (!PrintArray(output, output_bytes, input, input_bytes, type_id,
+                      type.fields[i]->length)) {
+        return false;
+      }
+      // Ignore the trailing '\0' that the subcall put on.
+      *output_bytes += 1;
+    } else if (MessageType::IsPrimitive(type_id)) {
+      if (!PrintField(output, output_bytes, input, input_bytes, type_id)) {
+        return false;
+      }
+    } else {
+      if (!PrintMessage(output, output_bytes, input, input_bytes,
+                        type_cache::Get(type_id))) {
+        return false;
+      }
+      // Ignore the trailing '\0' that the subcall put on.
+      *output_bytes += 1;
+    }
+
+    // Update the input and output pointers.
+    output += output_bytes_before - *output_bytes;
+    input =
+        static_cast<const char *>(input) + input_bytes_before - *input_bytes;
+  }
+  if (*output_bytes < 2) return false;
+  *output_bytes -= 2;
+  *(output++) = '}';
+  *(output++) = '\0';
+  return true;
+}
+
+bool PrintMatrix(char *output, size_t *output_bytes, const void *input,
+                 uint32_t type_id, int rows, int cols) {
+  CHECK(MessageType::IsPrimitive(type_id));
+  const size_t element_size = MessageType::Sizeof(type_id);
+
+  if (*output_bytes < 1) return false;
+  *output_bytes -= 1;
+  *(output++) = '[';
+
+  bool first_row = true;
+  for (int row = 0; row < rows; ++row) {
+    if (first_row) {
+      first_row = false;
+    } else {
+      if (*output_bytes < 2) return false;
+      *output_bytes -= 2;
+      *(output++) = ',';
+      *(output++) = ' ';
+    }
+
+    if (*output_bytes < 1) return false;
+    *output_bytes -= 1;
+    *(output++) = '[';
+
+    bool first_col = true;
+    for (int col = 0; col < cols; ++col) {
+      if (first_col) {
+        first_col = false;
+      } else {
+        if (*output_bytes < 2) return false;
+        *output_bytes -= 2;
+        *(output++) = ',';
+        *(output++) = ' ';
+      }
+
+      const size_t output_bytes_before = *output_bytes;
+      size_t input_bytes = element_size;
+      if (!PrintField(output, output_bytes,
+                      static_cast<const char *>(input) +
+                          (row + col * rows) * element_size,
+                      &input_bytes, type_id)) {
+        return false;
+      }
+      CHECK_EQ(0u, input_bytes);
+      // Update the output pointer.
+      output += output_bytes_before - *output_bytes;
+    }
+
+    if (*output_bytes < 1) return false;
+    *output_bytes -= 1;
+    *(output++) = ']';
+  }
+  if (*output_bytes < 2) return false;
+  *output_bytes -= 2;
+  *(output++) = ']';
+  *(output++) = '\0';
+  return true;
+}
+
+void SerializeMatrix(int type_id, void *output_void, const void *input_void,
+                     int rows, int cols) {
+  char *const output = static_cast<char *>(output_void);
+  const char *const input = static_cast<const char *>(input_void);
+
+  CHECK(MessageType::IsPrimitive(type_id));
+  const size_t element_size = MessageType::Sizeof(type_id);
+
+  for (int i = 0; i < rows * cols; ++i) {
+    switch(element_size) {
+      case 1:
+        to_network<1>(&input[i * element_size], &output[i * element_size]);
+        break;
+      case 2:
+        to_network<2>(&input[i * element_size], &output[i * element_size]);
+        break;
+      case 4:
+        to_network<4>(&input[i * element_size], &output[i * element_size]);
+        break;
+      case 8:
+        to_network<8>(&input[i * element_size], &output[i * element_size]);
+        break;
+      default:
+        LOG(FATAL, "illegal primitive type size %zu\n", element_size);
+    }
+  }
+}
+
+namespace type_cache {
+namespace {
+
+struct CacheEntry {
+  const MessageType &type;
+  bool in_shm;
+
+  CacheEntry(const MessageType &type, bool in_shm)
+      : type(type), in_shm(in_shm) {}
+};
+
+struct ShmType {
+  uint32_t id;
+  volatile ShmType *next;
+
+  size_t serialized_size;
+  char serialized[];
+};
+
+::std::unordered_map<uint32_t, CacheEntry> cache;
+::aos::Mutex cache_lock;
+
+}  // namespace
+
+void Add(const MessageType &type) {
+  ::aos::MutexLocker locker(&cache_lock);
+  if (cache.count(type.id) == 0) {
+    cache.emplace(::std::piecewise_construct, ::std::forward_as_tuple(type.id),
+                  ::std::forward_as_tuple(type, false));
+  }
+}
+
+const MessageType &Get(uint32_t type_id) {
+  ::aos::MutexLocker locker(&cache_lock);
+
+  {
+    const auto cached = cache.find(type_id);
+    if (cached != cache.end()) {
+      return cached->second.type;
+    }
+  }
+
+  if (aos_core_is_init()) {
+    // No need to lock because the only thing that happens is somebody adds on
+    // to the end, and they shouldn't be adding the one we're looking for.
+    const volatile ShmType *c = static_cast<volatile ShmType *>(
+        global_core->mem_struct->queue_types.pointer);
+    while (c != nullptr) {
+      if (c->id == type_id) {
+        size_t bytes = c->serialized_size;
+        MessageType *type = MessageType::Deserialize(
+            const_cast<const char *>(c->serialized), &bytes);
+        cache.emplace(::std::piecewise_construct,
+                      ::std::forward_as_tuple(type_id),
+                      ::std::forward_as_tuple(*type, true));
+        return *type;
+      }
+      c = c->next;
+    }
+  } else {
+    LOG(INFO, "FYI: no shm. going to LOG(FATAL) now\n");
+  }
+
+  LOG(FATAL, "MessageType for id 0x%" PRIx32 " not found\n", type_id);
+}
+
+void AddShm(uint32_t type_id) {
+  if (!aos_core_is_init()) {
+    LOG(FATAL, "can't AddShm(%" PRIu32 ") without shm!\n", type_id);
+  }
+
+  const MessageType::Field **fields;
+  int number_fields;
+  {
+    ::aos::MutexLocker locker(&cache_lock);
+    CacheEntry &cached = cache.at(type_id);
+    if (cached.in_shm) return;
+
+    fields = cached.type.fields;
+    number_fields = cached.type.number_fields;
+
+    if (mutex_lock(&global_core->mem_struct->queue_types.lock) != 0) {
+      LOG(FATAL, "locking queue_types lock failed\n");
+    }
+    volatile ShmType *current = static_cast<volatile ShmType *>(
+        global_core->mem_struct->queue_types.pointer);
+    if (current != nullptr) {
+      while (true) {
+        if (current->id == type_id) {
+          cached.in_shm = true;
+          mutex_unlock(&global_core->mem_struct->queue_types.lock);
+          return;
+        }
+        if (current->next == nullptr) break;
+        current = current->next;
+      }
+    }
+    char buffer[768];
+    ssize_t size = cached.type.Serialize(buffer, sizeof(buffer));
+    if (size == -1) {
+      LOG(FATAL, "type %s is too big to fit into %zd bytes\n",
+          cached.type.name.c_str(), sizeof(buffer));
+    }
+
+    volatile ShmType *shm =
+        static_cast<volatile ShmType *>(shm_malloc(sizeof(ShmType) + size));
+    shm->id = type_id;
+    shm->next = nullptr;
+    shm->serialized_size = size;
+    memcpy(const_cast<char *>(shm->serialized), buffer, size);
+
+    if (current == NULL) {
+      global_core->mem_struct->queue_types.pointer = const_cast<ShmType *>(shm);
+    } else {
+      current->next = shm;
+    }
+    mutex_unlock(&global_core->mem_struct->queue_types.lock);
+  }
+
+  for (int i = 0; i < number_fields; ++i) {
+    if (!MessageType::IsPrimitive(fields[i]->type)) {
+      AddShm(fields[i]->type);
+    }
+  }
+}
+
+}  // namespace type_cache
+}  // namespace aos
diff --git a/aos/common/queue_types.h b/aos/common/queue_types.h
new file mode 100644
index 0000000..be943c1
--- /dev/null
+++ b/aos/common/queue_types.h
@@ -0,0 +1,148 @@
+#ifndef AOS_COMMON_QUEUE_TYPES_H_
+#define AOS_COMMON_QUEUE_TYPES_H_
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <initializer_list>
+#include <string>
+
+#include "aos/common/macros.h"
+#include "aos/common/byteorder.h"
+
+namespace aos {
+
+// The type IDs this uses are 2 parts: a 16 bit size and a 16 bit hash. Sizes
+// for primitive types are stored with 8192 (0x2000) added.
+//
+// Serializing/deserializing includes all of the fields too.
+struct MessageType {
+  struct Field {
+    // The type ID for the type of this field.
+    uint32_t type;
+    // The length of the array if it is one or 0.
+    uint32_t length;
+    ::std::string name;
+  };
+
+  // Takes ownership of all the Field pointers in fields_initializer.
+  MessageType(size_t super_size, uint32_t id, const ::std::string &name,
+              ::std::initializer_list<const Field *> fields_initializer)
+      : super_size(super_size), id(id), name(name) {
+    number_fields = fields_initializer.size();
+    fields = new const Field *[number_fields];
+    int i = 0;
+    for (const Field *c : fields_initializer) {
+      fields[i++] = c;
+    }
+  }
+
+  ~MessageType() {
+    for (int i = 0; i < number_fields; ++i) {
+      delete fields[i];
+    }
+    delete[] fields;
+  }
+
+  // Returns -1 if max_bytes is too small.
+  ssize_t Serialize(char *buffer, size_t max_bytes) const;
+  // bytes should start out as the number of bytes available in buffer and gets
+  // reduced by the number actually read before returning.
+  // deserialize_length is whether to look for a length field in the serialized
+  // data.
+  // Returns a new instance allocated with new or nullptr for error.
+  static MessageType *Deserialize(const char *buffer, size_t *bytes,
+                                  bool deserialize_length = true);
+
+  static bool IsPrimitive(uint32_t type_id) {
+    return (type_id & 0x2000) != 0;
+  }
+
+  static unsigned int Sizeof(uint32_t type_id) {
+    if (IsPrimitive(type_id)) {
+      return (type_id & 0xFFFF) - 0x2000;
+    } else {
+      return type_id & 0xFFFF;
+    }
+  }
+
+  // How many (serialized) bytes the superclass takes up.
+  uint16_t super_size;
+  // The type ID for this.
+  uint32_t id;
+  ::std::string name;
+
+  uint16_t number_fields;
+  const Field **fields;
+
+ private:
+  // Internal constructor for Deserialize to use.
+  MessageType(uint16_t super_size, uint32_t id, ::std::string &&name,
+              uint16_t number_fields, Field **fields)
+      : super_size(super_size),
+        id(id),
+        name(name),
+        number_fields(number_fields),
+        fields(const_cast<const Field **>(fields)) {
+    for (int i = 0; i < number_fields; ++i) {
+      fields[i] = new Field();
+    }
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(MessageType);
+};
+
+// The arguments are the same for both of these.
+//
+// output is where to write the text representation ('\0'-terminated
+// human-readable string).
+// output_bytes should point to the number of bytes available to write in
+// output. It will be reduced by the number of bytes that were actually written.
+// input is where to read the data in from (in network byte order, aka from
+// Serialize).
+// input_bytes should point to the number of bytes available to read from input.
+// It will be reduced by the number of bytes that were actually read.
+// type is which type to print.
+// Returns true for success and false for not.
+//
+// Prints the value from 1 primitive message field into output.
+// The implementation of this is generated by the ruby code.
+// Does not include a trailing '\0' in what it subtracts from *output_bytes.
+bool PrintField(char *output, size_t *output_bytes, const void *input,
+                size_t *input_bytes, uint32_t type)
+    __attribute__((warn_unused_result));
+// Prints a whole message into output.
+// This calls itself recursively and PrintField to print out the whole thing.
+bool PrintMessage(char *output, size_t *output_bytes, const void *input,
+                  size_t *input_bytes, const MessageType &type)
+    __attribute__((warn_unused_result));
+// Calls PrintField to print out a matrix of values.
+bool PrintMatrix(char *output, size_t *output_bytes, const void *input,
+                 uint32_t type, int rows, int cols);
+
+// "Serializes" a matrix (basically just converts to network byte order). The
+// result can be passed to PrintMatrix.
+void SerializeMatrix(int type_id, void *output_void, const void *input_void,
+                     int rows, int cols);
+
+// Implements a cache of types which generally works per-process but can (when
+// instructed) put a type in shared memory which other processes will
+// automatically be able to retrieve.
+// All of these functions are thread-safe.
+namespace type_cache {
+
+// Makes sure a type is in the type cache. This will store a reference to type.
+// The types of any non-primitive fields of type must already be added.
+void Add(const MessageType &type);
+// Retrieves a type from the type cache or shm. LOG(FATAL)s if it can't find it.
+const MessageType &Get(uint32_t type_id);
+// Makes sure a type is in the list in shm. Add must have already been called
+// for type.
+// Also adds the types of any non-primitive fields of type.
+void AddShm(uint32_t type_id);
+
+}  // namespace type_cache
+}  // namespace aos
+
+#endif  // AOS_COMMON_QUEUE_TYPES_H_
diff --git a/aos/common/queue_types_test.cc b/aos/common/queue_types_test.cc
new file mode 100644
index 0000000..868820f
--- /dev/null
+++ b/aos/common/queue_types_test.cc
@@ -0,0 +1,274 @@
+#include "aos/common/queue_types.h"
+
+#include <memory>
+#include <limits>
+#include <string>
+
+#include "gtest/gtest.h"
+
+#include "aos/common/test_queue.q.h"
+#include "aos/common/byteorder.h"
+#include "aos/queue_primitives.h"
+#include "aos/common/logging/logging.h"
+#include "aos/common/queue_testutils.h"
+
+using ::aos::common::testing::Structure;
+using ::aos::common::testing::MessageWithStructure;
+using ::aos::common::testing::OtherTestingMessage;
+using ::aos::common::testing::MessageWithArrays;
+
+namespace aos {
+namespace testing {
+
+typedef MessageType::Field Field;
+
+static const MessageType kTestType1(5, 0x1234, "TestType1",
+                                    {new Field{0, 0, "field1"},
+                                     new Field{0, 0, "field2"},
+                                     new Field{0, 0, "field3"}});
+
+class QueueTypesTest : public ::testing::Test {
+ public:
+  QueueTypesTest() {
+    ::aos::common::testing::EnableTestLogging();
+  }
+
+  ::testing::AssertionResult Equal(const MessageType &l, const MessageType &r) {
+    using ::testing::AssertionFailure;
+    if (l.id != r.id) {
+      return AssertionFailure() << "id " << l.id << " != " << r.id;
+    }
+    if (l.name != r.name) {
+      return AssertionFailure() << "name '" << l.name << "' != '" << r.name
+                                << "'";
+    }
+    if (l.number_fields != r.number_fields) {
+      return AssertionFailure() << "number_fields " << l.number_fields
+                                << " != " << r.number_fields;
+    }
+    for (int i = 0; i < l.number_fields; ++i) {
+      SCOPED_TRACE("field " + ::std::to_string(i));
+      if (l.fields[i]->type != r.fields[i]->type) {
+        return AssertionFailure() << "type " << l.fields[i]->type
+                                  << " != " << r.fields[i]->type;
+      }
+      if (l.fields[i]->name != r.fields[i]->name) {
+        return AssertionFailure() << "name '" << l.fields[i]->name << "' != '"
+                                  << r.fields[i]->name << "'";
+      }
+    }
+    return ::testing::AssertionSuccess();
+  }
+};
+
+TEST_F(QueueTypesTest, Serialization) {
+  char buffer[512];
+  ssize_t size;
+  size_t out_size;
+  ::std::unique_ptr<MessageType> deserialized;
+
+  size = kTestType1.Serialize(buffer, sizeof(buffer));
+  ASSERT_GT(size, 1);
+  ASSERT_LE(static_cast<size_t>(size), sizeof(buffer));
+
+  out_size = size;
+  deserialized.reset(MessageType::Deserialize(buffer, &out_size));
+  EXPECT_EQ(0u, out_size);
+  EXPECT_TRUE(Equal(kTestType1, *deserialized));
+
+  out_size = size - 1;
+  deserialized.reset(MessageType::Deserialize(buffer, &out_size));
+  EXPECT_EQ(nullptr, deserialized.get());
+
+  out_size = size + 1;
+  ASSERT_LE(out_size, sizeof(buffer));
+  deserialized.reset(MessageType::Deserialize(buffer, &out_size));
+  EXPECT_EQ(1u, out_size);
+  EXPECT_TRUE(Equal(kTestType1, *deserialized));
+}
+
+class PrintMessageTest : public ::testing::Test {
+ public:
+  char input[128], output[256];
+  size_t input_bytes, output_bytes;
+};
+
+class PrintFieldTest : public PrintMessageTest {
+ public:
+  template <typename T>
+  void TestInteger(T value, ::std::string result) {
+    input_bytes = sizeof(value);
+    to_network(&value, input);
+    output_bytes = sizeof(output);
+    ASSERT_TRUE(
+        PrintField(output, &output_bytes, input, &input_bytes, TypeID<T>::id));
+    EXPECT_EQ(0u, input_bytes);
+    EXPECT_EQ(sizeof(output) - result.size(), output_bytes);
+    EXPECT_EQ(result, ::std::string(output, sizeof(output) - output_bytes));
+  }
+
+  template <typename T>
+  void TestAllIntegers(T multiple) {
+    for (T i = ::std::numeric_limits<T>::min();
+         i < ::std::numeric_limits<T>::max() - multiple; i += multiple) {
+      TestInteger<T>(i, ::std::to_string(i));
+    }
+  }
+};
+
+TEST_F(PrintFieldTest, Basic) {
+  TestInteger<uint16_t>(971, "971");
+  TestInteger<uint8_t>(8, "8");
+  TestInteger<uint8_t>(254, "254");
+  TestInteger<uint8_t>(0, "0");
+  TestInteger<int8_t>(254, "-2");
+  TestInteger<int8_t>(67, "67");
+  TestInteger<int8_t>(0, "0");
+
+  input_bytes = 1;
+  input[0] = 1;
+  output_bytes = sizeof(output);
+  ASSERT_TRUE(PrintField(output, &output_bytes, input, &input_bytes,
+                         queue_primitive_types::bool_p));
+  EXPECT_EQ(0u, input_bytes);
+  EXPECT_EQ(sizeof(output) - 1, output_bytes);
+  EXPECT_EQ(::std::string("T"),
+            ::std::string(output, sizeof(output) - output_bytes));
+
+  input_bytes = 1;
+  input[0] = 0;
+  output_bytes = sizeof(output);
+  ASSERT_TRUE(PrintField(output, &output_bytes, input, &input_bytes,
+                         queue_primitive_types::bool_p));
+  EXPECT_EQ(0u, input_bytes);
+  EXPECT_EQ(sizeof(output) - 1, output_bytes);
+  EXPECT_EQ(::std::string("f"),
+            ::std::string(output, sizeof(output) - output_bytes));
+}
+
+// Runs through lots of integers and makes sure PrintField gives the same result
+// as ::std::to_string.
+TEST_F(PrintFieldTest, Integers) {
+  TestAllIntegers<uint8_t>(1);
+  TestAllIntegers<int8_t>(1);
+  TestAllIntegers<uint16_t>(1);
+  TestAllIntegers<int16_t>(3);
+  TestAllIntegers<uint32_t>(43129);
+  TestAllIntegers<int32_t>(654321);
+  TestAllIntegers<uint64_t>(123456789101112);
+  TestAllIntegers<int64_t>(91011121249856532);
+}
+
+// Tests PrintField with trailing input bytes and only 1 extra output byte.
+TEST_F(PrintFieldTest, OtherSizes) {
+  static const float kData = 16.78;
+  static const ::std::string kString("16.780001");
+  static const size_t kExtraInputBytes = 4;
+  input_bytes = sizeof(kData) + kExtraInputBytes;
+  to_network(&kData, input);
+  output_bytes = kString.size() + 1;
+  CHECK_LE(output_bytes, sizeof(output));
+  ASSERT_TRUE(PrintField(output, &output_bytes, input, &input_bytes,
+                         Structure::GetType()->fields[2]->type));
+  EXPECT_EQ(kExtraInputBytes, input_bytes);
+  EXPECT_EQ(1u, output_bytes);
+  EXPECT_EQ(kString, ::std::string(output));
+}
+
+TEST_F(PrintFieldTest, InputTooSmall) {
+  static const float kData = 0;
+  input_bytes = sizeof(kData) - 1;
+  output_bytes = sizeof(output);
+  EXPECT_FALSE(PrintField(output, &output_bytes, input, &input_bytes,
+                          Structure::GetType()->fields[2]->type));
+}
+
+TEST_F(PrintFieldTest, OutputTooSmall) {
+  static const uint16_t kData = 12345;
+  input_bytes = sizeof(input);
+  to_network(&kData, input);
+  output_bytes = 4;
+  EXPECT_FALSE(PrintField(output, &output_bytes, input, &input_bytes,
+                          Structure::GetType()->fields[1]->type));
+}
+
+static const OtherTestingMessage kTestMessage1(true, 8971, 3.2);
+static const ::std::string kTestMessage1String =
+    ".aos.common.testing.OtherTestingMessage{test_bool:T, test_int:8971"
+    ", test_double:3.200000}";
+static const Structure kTestStructure1(false, 973, 8.56);
+static const ::std::string kTestStructure1String =
+    ".aos.common.testing.Structure{struct_bool:f, struct_int:973"
+    ", struct_float:8.560000}";
+static const ::aos::common::testing::Structure kStructureValue(true, 973, 3.14);
+static const MessageWithArrays kTestMessageWithArrays({{971, 254, 1678}},
+                                                      {{kStructureValue,
+                                                        kStructureValue}});
+static const ::std::string kTestMessageWithArraysString =
+    ".aos.common.testing.MessageWithArrays{test_int:[971, 254, 1678], "
+    "test_struct:[.aos.common.testing.Structure{struct_bool:T, struct_int:973, "
+    "struct_float:3.140000}, .aos.common.testing.Structure{struct_bool:T, "
+    "struct_int:973, struct_float:3.140000}]}";
+
+TEST_F(PrintMessageTest, Basic) {
+  CHECK_GE(sizeof(input), kTestMessage1.Size());
+  input_bytes = kTestMessage1.Serialize(input);
+  output_bytes = sizeof(output);
+  ASSERT_TRUE(PrintMessage(output, &output_bytes, input, &input_bytes,
+                           *kTestMessage1.GetType()));
+  EXPECT_EQ(kTestMessage1String, ::std::string(output));
+  EXPECT_EQ(kTestMessage1String.size() + 1, sizeof(output) - output_bytes);
+}
+
+TEST_F(PrintMessageTest, OutputTooSmall) {
+  CHECK_GE(sizeof(input), kTestMessage1.Size());
+  input_bytes = kTestMessage1.Serialize(input);
+  output_bytes = kTestMessage1String.size();
+  EXPECT_FALSE(PrintMessage(output, &output_bytes, input, &input_bytes,
+                           *kTestMessage1.GetType()));
+}
+
+TEST_F(PrintMessageTest, InputTooSmall) {
+  input_bytes = kTestMessage1.Size() - 1;
+  output_bytes = sizeof(output);
+  EXPECT_FALSE(PrintMessage(output, &output_bytes, input, &input_bytes,
+                           *kTestMessage1.GetType()));
+}
+
+TEST_F(PrintMessageTest, Structure) {
+  CHECK_GE(sizeof(input), kTestStructure1.Size());
+  input_bytes = kTestStructure1.Serialize(input);
+  output_bytes = sizeof(output);
+  ASSERT_TRUE(PrintMessage(output, &output_bytes, input, &input_bytes,
+                           *kTestStructure1.GetType()));
+  EXPECT_EQ(kTestStructure1String, ::std::string(output));
+  EXPECT_EQ(kTestStructure1String.size() + 1, sizeof(output) - output_bytes);
+}
+
+TEST_F(PrintMessageTest, Matrix) {
+  static const uint16_t kTestMatrix[] = {971, 254, 1768, 8971, 9971, 973};
+  uint16_t test_matrix[sizeof(kTestMatrix) / sizeof(kTestMatrix[0])];
+  SerializeMatrix(queue_primitive_types::uint16_t_p, test_matrix, kTestMatrix,
+                  3, 2);
+  static const ::std::string kOutput =
+      "[[971, 8971], [254, 9971], [1768, 973]]";
+  output_bytes = sizeof(output);
+  ASSERT_TRUE(PrintMatrix(output, &output_bytes, test_matrix,
+                          queue_primitive_types::uint16_t_p, 3, 2));
+  EXPECT_EQ(kOutput, ::std::string(output));
+  EXPECT_EQ(kOutput.size() + 1, sizeof(output) - output_bytes);
+}
+
+TEST_F(PrintMessageTest, Array) {
+  CHECK_GE(sizeof(input), kTestMessageWithArrays.Size());
+  input_bytes = kTestMessageWithArrays.Serialize(input);
+  output_bytes = sizeof(output);
+  ASSERT_TRUE(PrintMessage(output, &output_bytes, input, &input_bytes,
+                           *kTestMessageWithArrays.GetType()));
+  EXPECT_EQ(kTestMessageWithArraysString, ::std::string(output));
+  EXPECT_EQ(kTestMessageWithArraysString.size() + 1,
+            sizeof(output) - output_bytes);
+}
+
+}  // namespace testing
+}  // namespace aos
diff --git a/aos/common/scoped_fd.h b/aos/common/scoped_fd.h
new file mode 100644
index 0000000..57ecdd8
--- /dev/null
+++ b/aos/common/scoped_fd.h
@@ -0,0 +1,40 @@
+#include <unistd.h>
+
+#include "aos/common/macros.h"
+#include "aos/common/logging/logging.h"
+
+namespace aos {
+
+// Smart "pointer" (container) for a file descriptor.
+class ScopedFD {
+ public:
+  explicit ScopedFD(int fd = -1) : fd_(fd) {}
+  ~ScopedFD() {
+    Close();
+  }
+  int get() const { return fd_; }
+  int release() {
+    const int r = fd_;
+    fd_ = -1;
+    return r;
+  }
+  void reset(int new_fd = -1) {
+    if (fd_ != new_fd) {
+      Close();
+      fd_ = new_fd;
+    }
+  }
+  operator bool() const { return fd_ != -1; }
+ private:
+  int fd_;
+  void Close() {
+    if (fd_ != -1) {
+      if (close(fd_) == -1) {
+        PLOG(WARNING, "close(%d) failed", fd_);
+      }
+    }
+  }
+  DISALLOW_COPY_AND_ASSIGN(ScopedFD);
+};
+
+}  // namespace aos
diff --git a/aos/common/scoped_ptr.h b/aos/common/scoped_ptr.h
new file mode 100644
index 0000000..e4df78e
--- /dev/null
+++ b/aos/common/scoped_ptr.h
@@ -0,0 +1,43 @@
+#ifndef AOS_COMMON_SCOPED_PTR_H_
+#define AOS_COMMON_SCOPED_PTR_H_
+
+#include "aos/common/macros.h"
+
+namespace aos {
+
+// A simple scoped_ptr implementation that works under both linux and vxworks.
+template<typename T>
+class scoped_ptr {
+ public:
+  typedef T element_type;
+  
+  explicit scoped_ptr(T *p = NULL) : p_(p) {}
+  ~scoped_ptr() {
+    delete p_;
+  }
+
+  T &operator*() const { return *p_; }
+  T *operator->() const { return p_; }
+  T *get() const { return p_; }
+
+  operator bool() const { return p_ != NULL; }
+
+  void swap(scoped_ptr<T> &other) {
+    T *temp = other.p_;
+    other.p_ = p_;
+    p_ = other.p_;
+  }
+  void reset(T *p = NULL) {
+    if (p_ != NULL) delete p_;
+    p_ = p;
+  }
+
+ private:
+  T *p_;
+
+  DISALLOW_COPY_AND_ASSIGN(scoped_ptr<T>);
+};
+
+}  // namespace aos
+
+#endif  // AOS_COMMON_SCOPED_PTR_H_
diff --git a/aos/common/stl_mutex.h b/aos/common/stl_mutex.h
new file mode 100644
index 0000000..9242312
--- /dev/null
+++ b/aos/common/stl_mutex.h
@@ -0,0 +1,144 @@
+#ifndef AOS_COMMON_STL_MUTEX_H_
+#define AOS_COMMON_STL_MUTEX_H_
+
+#include <mutex>
+
+#include "aos/linux_code/ipc_lib/aos_sync.h"
+#include "aos/common/logging/logging.h"
+#include "aos/common/type_traits.h"
+#include "aos/common/macros.h"
+
+namespace aos {
+
+// A mutex with the same API and semantics as ::std::mutex, with the addition of
+// methods for checking if the previous owner died and a constexpr default
+// constructor.
+// Definitely safe to put in SHM.
+// This uses the pthread_mutex semantics for owner-died: once somebody dies with
+// the lock held, anybody else who takes it will see true for owner_died() until
+// one of them calls consistent(). It is an error to call unlock() when
+// owner_died() returns true.
+class stl_mutex {
+ public:
+  constexpr stl_mutex() : native_handle_() {}
+
+  void lock() {
+    const int ret = mutex_grab(&native_handle_);
+    switch (ret) {
+      case 0:
+        break;
+      case 1:
+        owner_died_ = true;
+        break;
+      default:
+        LOG(FATAL, "mutex_grab(%p) failed with %d\n", &native_handle_, ret);
+    }
+  }
+
+  bool try_lock() {
+    const int ret = mutex_trylock(&native_handle_);
+    switch (ret) {
+      case 0:
+        return true;
+      case 1:
+        owner_died_ = true;
+        return true;
+      case 4:
+        return false;
+      default:
+        LOG(FATAL, "mutex_trylock(%p) failed with %d\n", &native_handle_, ret);
+    }
+  }
+
+  void unlock() {
+    CHECK(!owner_died_);
+    mutex_unlock(&native_handle_);
+  }
+
+  typedef aos_mutex *native_handle_type;
+  native_handle_type native_handle() { return &native_handle_; }
+
+  bool owner_died() const { return owner_died_; }
+  void consistent() { owner_died_ = false; }
+
+ private:
+  aos_mutex native_handle_;
+
+  bool owner_died_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(stl_mutex);
+};
+
+// A mutex with the same API and semantics as ::std::recursive_mutex, with the
+// addition of methods for checking if the previous owner died and a constexpr
+// default constructor.
+// Definitely safe to put in SHM.
+// This uses the pthread_mutex semantics for owner-died: once somebody dies with
+// the lock held, anybody else who takes it will see true for owner_died() until
+// one of them calls consistent(). It is an error to call unlock() or lock()
+// again when owner_died() returns true.
+class stl_recursive_mutex {
+ public:
+  constexpr stl_recursive_mutex() {}
+
+  void lock() {
+    if (mutex_islocked(mutex_.native_handle())) {
+      CHECK(!owner_died());
+      ++recursive_locks_;
+    } else {
+      mutex_.lock();
+      if (mutex_.owner_died()) {
+        recursive_locks_ = 0;
+      } else {
+        CHECK_EQ(0, recursive_locks_);
+      }
+    }
+  }
+  bool try_lock() {
+    if (mutex_islocked(mutex_.native_handle())) {
+      CHECK(!owner_died());
+      ++recursive_locks_;
+      return true;
+    } else {
+      if (mutex_.try_lock()) {
+        if (mutex_.owner_died()) {
+          recursive_locks_ = 0;
+        } else {
+          CHECK_EQ(0, recursive_locks_);
+        }
+        return true;
+      } else {
+        return false;
+      }
+    }
+  }
+  void unlock() {
+    if (recursive_locks_ == 0) {
+      mutex_.unlock();
+    } else {
+      --recursive_locks_;
+    }
+  }
+
+  typedef stl_mutex::native_handle_type native_handle_type;
+  native_handle_type native_handle() { return mutex_.native_handle(); }
+
+  bool owner_died() const { return mutex_.owner_died(); }
+  void consistent() { mutex_.consistent(); }
+
+ private:
+  stl_mutex mutex_;
+  int recursive_locks_ = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(stl_recursive_mutex);
+};
+
+// Convenient typedefs for various types of locking objects.
+typedef ::std::lock_guard<stl_mutex> mutex_lock_guard;
+typedef ::std::lock_guard<stl_recursive_mutex> recursive_lock_guard;
+typedef ::std::unique_lock<stl_mutex> mutex_unique_lock;
+typedef ::std::unique_lock<stl_recursive_mutex> recursive_unique_lock;
+
+}  // namespace aos
+
+#endif  // AOS_COMMON_STL_MUTEX_H_
diff --git a/aos/common/stl_mutex_test.cc b/aos/common/stl_mutex_test.cc
new file mode 100644
index 0000000..7d84416
--- /dev/null
+++ b/aos/common/stl_mutex_test.cc
@@ -0,0 +1,74 @@
+#include "aos/common/stl_mutex.h"
+
+#include "gtest/gtest.h"
+
+#include "aos/common/queue_testutils.h"
+#include "aos/common/util/thread.h"
+#include "aos/common/die.h"
+
+namespace aos {
+namespace testing {
+
+class StlMutexDeathTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    ::aos::common::testing::EnableTestLogging();
+    SetDieTestMode(true);
+  }
+};
+
+typedef StlMutexDeathTest StlRecursiveMutexDeathTest;
+
+// Tests that locking/unlocking without any blocking works.
+TEST(StlMutexTest, Basic) {
+  stl_mutex mutex;
+
+  mutex.lock();
+  mutex.unlock();
+
+  ASSERT_TRUE(mutex.try_lock());
+  ASSERT_FALSE(mutex.try_lock());
+  mutex.unlock();
+
+  mutex.lock();
+  ASSERT_FALSE(mutex.try_lock());
+  mutex.unlock();
+}
+
+// Tests that unlocking an unlocked mutex fails.
+TEST_F(StlMutexDeathTest, MultipleUnlock) {
+  stl_mutex mutex;
+  mutex.lock();
+  mutex.unlock();
+  EXPECT_DEATH(mutex.unlock(), ".*multiple unlock.*");
+}
+
+// Tests that locking/unlocking (including recursively) without any blocking
+// works.
+TEST(StlRecursiveMutexTest, Basic) {
+  stl_recursive_mutex mutex;
+
+  mutex.lock();
+  mutex.unlock();
+
+  ASSERT_TRUE(mutex.try_lock());
+  ASSERT_TRUE(mutex.try_lock());
+  mutex.unlock();
+  mutex.unlock();
+
+  mutex.lock();
+  ASSERT_TRUE(mutex.try_lock());
+  mutex.unlock();
+	mutex.unlock();
+}
+
+// Tests that unlocking an unlocked recursive mutex fails.
+TEST_F(StlRecursiveMutexDeathTest, MultipleUnlock) {
+  stl_recursive_mutex mutex;
+  mutex.lock();
+  mutex.unlock();
+  EXPECT_DEATH(mutex.unlock(), ".*multiple unlock.*");
+}
+
+}  // namespace testing
+}  // namespace aos
diff --git a/aos/common/test_queue.q b/aos/common/test_queue.q
new file mode 100644
index 0000000..827b607
--- /dev/null
+++ b/aos/common/test_queue.q
@@ -0,0 +1,38 @@
+package aos.common.testing;
+
+struct Structure {
+  bool struct_bool;
+  uint16_t struct_int;
+  float struct_float;
+};
+
+message MessageWithStructure {
+  bool other_member;
+  Structure struct1;
+  Structure struct2;
+};
+
+message TestingMessage {
+  bool test_bool;
+  int32_t test_int;
+};
+
+message OtherTestingMessage {
+  bool test_bool;
+  int32_t test_int;
+  double test_double;
+};
+
+message MessageWithArrays {
+  uint16_t[3] test_int;
+  Structure[2] test_struct;
+};
+
+queue TestingMessage test_queue;
+
+queue_group TwoQueues {
+  queue TestingMessage first;
+  queue OtherTestingMessage second;
+};
+
+queue_group TwoQueues test_queuegroup;
diff --git a/aos/common/time.cc b/aos/common/time.cc
new file mode 100644
index 0000000..7318afb
--- /dev/null
+++ b/aos/common/time.cc
@@ -0,0 +1,233 @@
+#include "aos/common/time.h"
+
+#include <string.h>
+#include <inttypes.h>
+
+// We only use global_core from here, which is weak, so we don't really have a
+// dependency on it.
+#include "aos/linux_code/ipc_lib/shared_mem.h"
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/mutex.h"
+
+namespace aos {
+namespace time {
+
+// State required to enable and use mock time.
+namespace {
+// True if mock time is enabled.
+// This does not need to be checked with the mutex held because setting time to
+// be enabled or disabled is atomic, and all future operations are atomic
+// anyways.  If there is a race condition setting or clearing whether time is
+// enabled or not, it will still be a race condition if current_mock_time is
+// also set atomically with enabled.
+bool mock_time_enabled = false;
+// Mutex to make time reads and writes thread safe.
+Mutex time_mutex;
+// Current time when time is mocked.
+Time current_mock_time(0, 0);
+
+// TODO(aschuh): This doesn't include SleepFor and SleepUntil.
+// TODO(aschuh): Create a clock source object and change the default?
+//  That would let me create a MockTime clock source.
+
+Time NowImpl(clockid_t clock) {
+  timespec temp;
+  if (clock_gettime(clock, &temp) != 0) {
+    PLOG(FATAL, "clock_gettime(%jd, %p) failed",
+         static_cast<uintmax_t>(clock), &temp);
+  }
+
+  const timespec offset = (global_core == nullptr)
+                              ? timespec{0, 0}
+                              : global_core->mem_struct->time_offset;
+  return Time(temp) + Time(offset);
+}
+
+}  // namespace
+
+void Time::EnableMockTime(const Time &now) {
+  MutexLocker time_mutex_locker(&time_mutex);
+  mock_time_enabled = true;
+  current_mock_time = now;
+}
+
+void Time::UpdateMockTime() {
+  SetMockTime(NowImpl(kDefaultClock));
+}
+
+void Time::DisableMockTime() {
+  MutexLocker time_mutex_locker(&time_mutex);
+  mock_time_enabled = false;
+}
+
+void Time::SetMockTime(const Time &now) {
+  MutexLocker time_mutex_locker(&time_mutex);
+  if (__builtin_expect(!mock_time_enabled, 0)) {
+    LOG(FATAL, "Tried to set mock time and mock time is not enabled\n");
+  }
+  current_mock_time = now;
+}
+
+void Time::IncrementMockTime(const Time &amount) {
+  static ::aos::Mutex mutex;
+  ::aos::MutexLocker sync(&mutex);
+  SetMockTime(Now() + amount);
+}
+
+Time Time::Now(clockid_t clock) {
+  {
+    MutexLocker time_mutex_locker(&time_mutex);
+    if (mock_time_enabled) {
+      return current_mock_time;
+    }
+  }
+  return NowImpl(clock);
+}
+
+void Time::CheckImpl(int32_t nsec) {
+  static_assert(aos::shm_ok<Time>::value,
+                "it should be able to go through shared memory");
+  if (nsec >= kNSecInSec || nsec < 0) {
+    LOG(FATAL, "0 <= nsec(%" PRId32 ") < %" PRId32 " isn't true.\n",
+        nsec, kNSecInSec);
+  }
+}
+
+Time &Time::operator+=(const Time &rhs) {
+  sec_ += rhs.sec_;
+  nsec_ += rhs.nsec_;
+  if (nsec_ >= kNSecInSec) {
+    nsec_ -= kNSecInSec;
+    sec_ += 1;
+  }
+  return *this;
+}
+const Time Time::operator+(const Time &rhs) const {
+  return Time(*this) += rhs;
+}
+Time &Time::operator-=(const Time &rhs) {
+  sec_ -= rhs.sec_;
+  nsec_ -= rhs.nsec_;
+  if (nsec_ < 0) {
+    nsec_ += kNSecInSec;
+    sec_ -= 1;
+  }
+  return *this;
+}
+const Time Time::operator-(const Time &rhs) const {
+  return Time(*this) -= rhs;
+}
+Time &Time::operator*=(int32_t rhs) {
+  const int64_t temp = static_cast<int64_t>(nsec_) *
+      static_cast<int64_t>(rhs);
+  sec_ *= rhs;  // better not overflow, or the result is just too big
+  nsec_ = temp % kNSecInSec;
+  sec_ += (temp - nsec_) / kNSecInSec;
+  if (nsec_ < 0) {
+    nsec_ += kNSecInSec;
+    sec_ -= 1;
+  }
+  return *this;
+}
+const Time Time::operator*(int32_t rhs) const {
+  return Time(*this) *= rhs;
+}
+Time &Time::operator/=(int32_t rhs) {
+  nsec_ = (sec_ % rhs) * (kNSecInSec / rhs) + nsec_ / rhs;
+  sec_ /= rhs;
+  if (nsec_ < 0) {
+    nsec_ += kNSecInSec;
+    sec_ -= 1;
+  }
+  return *this;
+}
+const Time Time::operator/(int32_t rhs) const {
+  return Time(*this) /= rhs;
+}
+double Time::operator/(const Time &rhs) const {
+  return ToSeconds() / rhs.ToSeconds();
+}
+Time &Time::operator%=(int32_t rhs) {
+  nsec_ = ToNSec() % rhs;
+  const int wraps = nsec_ / ((rhs / kNSecInSec + 1) * kNSecInSec);
+  sec_ = wraps + rhs / kNSecInSec;
+  nsec_ -= kNSecInSec * wraps;
+  if (nsec_ < 0) {
+    nsec_ += kNSecInSec;
+    sec_ -= 1;
+  }
+  return *this;
+}
+const Time Time::operator%(int32_t rhs) const {
+  return Time(*this) %= rhs;
+}
+
+const Time Time::operator-() const {
+  return Time(-sec_ - 1, kNSecInSec - nsec_);
+}
+
+bool Time::operator==(const Time &rhs) const {
+  return sec_ == rhs.sec_ && nsec_ == rhs.nsec_;
+}
+bool Time::operator!=(const Time &rhs) const {
+  return !(*this == rhs);
+}
+bool Time::operator<(const Time &rhs) const {
+  return sec_ < rhs.sec_ || (sec_ == rhs.sec_ && nsec_ < rhs.nsec_);
+}
+bool Time::operator>(const Time &rhs) const {
+  return sec_ > rhs.sec_ || (sec_ == rhs.sec_ && nsec_ > rhs.nsec_);
+}
+bool Time::operator<=(const Time &rhs) const {
+  return sec_ < rhs.sec_ || (sec_ == rhs.sec_ && nsec_ <= rhs.nsec_);
+}
+bool Time::operator>=(const Time &rhs) const {
+  return sec_ > rhs.sec_ || (sec_ == rhs.sec_ && nsec_ >= rhs.nsec_);
+}
+
+bool Time::IsWithin(const Time &other, int64_t amount) const {
+  const int64_t temp = ToNSec() - other.ToNSec();
+  return temp <= amount && temp >= -amount;
+}
+
+std::ostream &operator<<(std::ostream &os, const Time& time) {
+  return os << "Time{" << time.sec_ << "s, " << time.nsec_ << "ns}";
+}
+
+void SleepFor(const Time &time, clockid_t clock) {
+  timespec converted(time.ToTimespec()), remaining;
+  int failure = EINTR;
+  do {
+    // This checks whether the last time through the loop actually failed or got
+    // interrupted.
+    if (failure != EINTR) {
+      PELOG(FATAL, failure, "clock_nanosleep(%jd, 0, %p, %p) failed",
+            static_cast<intmax_t>(clock), &converted, &remaining);
+    }
+    failure = clock_nanosleep(clock, 0, &converted, &remaining);
+    memcpy(&converted, &remaining, sizeof(converted));
+  } while (failure != 0);
+}
+
+void SleepUntil(const Time &time, clockid_t clock) {
+  timespec converted(time.ToTimespec());
+  int failure;
+  while ((failure = clock_nanosleep(clock, TIMER_ABSTIME,
+                                    &converted, NULL)) != 0) {
+    if (failure != EINTR) {
+      PELOG(FATAL, failure, "clock_nanosleep(%jd, TIMER_ABSTIME, %p, NULL)"
+            " failed", static_cast<intmax_t>(clock), &converted);
+    }
+  }
+}
+
+void OffsetToNow(const Time &now) {
+  CHECK_NOTNULL(global_core);
+  global_core->mem_struct->time_offset.tv_nsec = 0;
+  global_core->mem_struct->time_offset.tv_sec = 0;
+  global_core->mem_struct->time_offset = (now - Time::Now()).ToTimespec();
+}
+
+}  // namespace time
+}  // namespace aos
diff --git a/aos/common/time.h b/aos/common/time.h
new file mode 100644
index 0000000..9afe9a0
--- /dev/null
+++ b/aos/common/time.h
@@ -0,0 +1,271 @@
+#ifndef AOS_COMMON_TIME_H_
+#define AOS_COMMON_TIME_H_
+
+#include <stdint.h>
+#include <time.h>
+#include <sys/time.h>
+#include <stdint.h>
+
+#include <type_traits>
+#include <ostream>
+
+#include "aos/common/type_traits.h"
+#include "aos/common/macros.h"
+
+namespace aos {
+namespace time {
+
+// A nice structure for representing times.
+// 0 <= nsec_ < kNSecInSec should always be true. All functions here will make
+// sure that that is true if it was on all inputs (including *this).
+//
+// Negative times are supported so that all of the normal arithmetic identities
+// work. nsec_ is still always positive.
+//
+// The arithmetic and comparison operators are overloaded because they make
+// complete sense and are very useful. The default copy and assignment stuff is
+// left because it works fine. Multiplication of Times by Times is
+// not implemented because I can't think of any uses for them and there are
+// multiple ways to do it. Division of Times by Times is implemented as the
+// ratio of them. Multiplication, division, and modulus of Times by integers are
+// implemented as interpreting the argument as nanoseconds. Modulus takes the
+// sign from the first operand.
+struct Time {
+#ifdef SWIG
+// All of the uses of constexpr here can safely be simply removed.
+// NOTE: This means that relying on the fact that constexpr implicitly makes
+// member functions const is not valid, so they all have to be explicitly marked
+// const.
+#define constexpr
+#endif  // SWIG
+ public:
+  static const int32_t kNSecInSec = 1000000000;
+  static const int32_t kNSecInMSec = 1000000;
+  static const int32_t kNSecInUSec = 1000;
+  static const int32_t kMSecInSec = 1000;
+  static const int32_t kUSecInSec = 1000000;
+  constexpr Time(int32_t sec = 0, int32_t nsec = 0)
+      : sec_(sec), nsec_(CheckConstexpr(nsec)) {
+  }
+  #ifndef SWIG
+  explicit constexpr Time(const struct timespec &value)
+      : sec_(value.tv_sec), nsec_(CheckConstexpr(value.tv_nsec)) {
+  }
+  struct timespec ToTimespec() const {
+    struct timespec ans;
+    ans.tv_sec = sec_;
+    ans.tv_nsec = nsec_;
+    return ans;
+  }
+  explicit constexpr Time(const struct timeval &value)
+      : sec_(value.tv_sec), nsec_(CheckConstexpr(value.tv_usec * kNSecInUSec)) {
+  }
+  struct timeval ToTimeval() const {
+    struct timeval ans;
+    ans.tv_sec = sec_;
+    ans.tv_usec = nsec_ / kNSecInUSec;
+    return ans;
+  }
+  #endif  // SWIG
+
+  // CLOCK_MONOTONIC on linux and CLOCK_REALTIME on the cRIO because the
+  // cRIO doesn't have any others.
+  // CLOCK_REALTIME is the default realtime clock and CLOCK_MONOTONIC doesn't
+  // change when somebody changes the wall clock (like the ntp deamon or
+  // whatever). See clock_gettime(2) for details.
+  //
+  // This is the clock that code that just wants to sleep for a certain amount
+  // of time or measure how long something takes should use.
+  #ifndef __VXWORKS__
+  static const clockid_t kDefaultClock = CLOCK_MONOTONIC;
+  #else
+  static const clockid_t kDefaultClock = CLOCK_REALTIME;
+  #endif
+  // Creates a Time representing the current value of the specified clock or
+  // dies.
+  static Time Now(clockid_t clock = kDefaultClock);
+
+  // Constructs a Time representing seconds.
+  static constexpr Time InSeconds(double seconds) {
+    return (seconds < 0.0) ?
+        Time(static_cast<int32_t>(seconds) - 1,
+             (seconds - static_cast<int32_t>(seconds) + 1.0) * kNSecInSec) :
+        Time(static_cast<int32_t>(seconds),
+             (seconds - static_cast<int32_t>(seconds)) * kNSecInSec);
+  }
+
+  // Constructs a time representing microseconds.
+  static constexpr Time InNS(int64_t nseconds) {
+    return (nseconds < 0) ?
+        Time(nseconds / static_cast<int64_t>(kNSecInSec) - 1,
+             (nseconds % kNSecInSec) + kNSecInSec) :
+        Time(nseconds / static_cast<int64_t>(kNSecInSec),
+             nseconds % kNSecInSec);
+  }
+
+  // Constructs a time representing microseconds.
+  static constexpr Time InUS(int useconds) {
+    return (useconds < 0) ?
+        Time(useconds / kUSecInSec - 1,
+             (useconds % kUSecInSec) * kNSecInUSec + kNSecInSec) :
+      Time(useconds / kUSecInSec, (useconds % kUSecInSec) * kNSecInUSec);
+  }
+
+  // Constructs a time representing mseconds.
+  static constexpr Time InMS(int mseconds) {
+    return (mseconds < 0) ?
+        Time(mseconds / kMSecInSec - 1,
+             (mseconds % kMSecInSec) * kNSecInMSec + kNSecInSec) :
+        Time(mseconds / kMSecInSec, (mseconds % kMSecInSec) * kNSecInMSec);
+  }
+
+  // Checks whether or not this time is within amount nanoseconds of other.
+  bool IsWithin(const Time &other, int64_t amount) const;
+
+  // Returns the time represented all in nanoseconds.
+  int64_t constexpr ToNSec() const {
+    return static_cast<int64_t>(sec_) * static_cast<int64_t>(kNSecInSec) +
+        static_cast<int64_t>(nsec_);
+  }
+#ifdef __VXWORKS__
+  // Returns the time represented all in system clock ticks. The system clock
+  // rate is retrieved using sysClkRateGet().
+  int ToTicks() const {
+    return ToNSec() / static_cast<int64_t>(kNSecInSec / sysClkRateGet());
+  }
+  // Constructs a Time representing ticks.
+  static Time InTicks(int ticks) {
+    return Time::InSeconds(static_cast<double>(ticks) / sysClkRateGet());
+  }
+#endif
+
+  // Returns the time represented in milliseconds.
+  int64_t constexpr ToMSec() const {
+    return static_cast<int64_t>(sec_) * static_cast<int64_t>(kMSecInSec) +
+        (static_cast<int64_t>(nsec_) / static_cast<int64_t>(kNSecInMSec));
+  }
+
+  // Returns the time represent in microseconds.
+  int64_t constexpr ToUSec() const {
+    return static_cast<int64_t>(sec_) * static_cast<int64_t>(kUSecInSec) +
+        (static_cast<int64_t>(nsec_) / static_cast<int64_t>(kNSecInUSec));
+  }
+
+  // Returns the time represented in fractional seconds.
+  double constexpr ToSeconds() const {
+    return static_cast<double>(sec_) + static_cast<double>(nsec_) / kNSecInSec;
+  }
+
+  #ifndef SWIG
+  Time &operator+=(const Time &rhs);
+  Time &operator-=(const Time &rhs);
+  Time &operator*=(int32_t rhs);
+  Time &operator/=(int32_t rhs);
+  Time &operator%=(int32_t rhs);
+  Time &operator%=(double rhs) = delete;
+  Time &operator*=(double rhs) = delete;
+  Time &operator/=(double rhs) = delete;
+  const Time operator*(double rhs) const = delete;
+  const Time operator/(double rhs) const = delete;
+  const Time operator%(double rhs) const = delete;
+  #endif
+  const Time operator+(const Time &rhs) const;
+  const Time operator-(const Time &rhs) const;
+  const Time operator*(int32_t rhs) const;
+  const Time operator/(int32_t rhs) const;
+  double operator/(const Time &rhs) const;
+  const Time operator%(int32_t rhs) const;
+
+  const Time operator-() const;
+
+  bool operator==(const Time &rhs) const;
+  bool operator!=(const Time &rhs) const;
+  bool operator<(const Time &rhs) const;
+  bool operator>(const Time &rhs) const;
+  bool operator<=(const Time &rhs) const;
+  bool operator>=(const Time &rhs) const;
+
+  #ifndef SWIG
+  // For gtest etc.
+  friend std::ostream &operator<<(std::ostream &os, const Time &time);
+  #endif  // SWIG
+
+  int32_t constexpr sec() const { return sec_; }
+  void set_sec(int32_t sec) { sec_ = sec; }
+  int32_t constexpr nsec() const { return nsec_; }
+  void set_nsec(int32_t nsec) {
+    nsec_ = nsec;
+    Check();
+  }
+
+  // Absolute value.
+  Time abs() const {
+    if (*this > Time(0, 0)) return *this;
+    if (nsec_ == 0) return Time(-sec_, 0);
+    return Time(-sec_ - 1, kNSecInSec - nsec_);
+  }
+
+  // Enables returning the mock time value for Now instead of checking the
+  // system clock.
+  static void EnableMockTime(const Time &now = Now());
+  // Calls SetMockTime with the current actual time.
+  static void UpdateMockTime();
+  // Sets now when time is being mocked.
+  static void SetMockTime(const Time &now);
+  // Convenience function to just increment the mock time by a certain amount in
+  // a thread safe way.
+  static void IncrementMockTime(const Time &amount);
+  // Disables mocking time.
+  static void DisableMockTime();
+
+ private:
+  int32_t sec_, nsec_;
+
+  // LOG(FATAL)s if nsec is >= kNSecInSec or negative.
+  static void CheckImpl(int32_t nsec);
+  void Check() { CheckImpl(nsec_); }
+  // A constexpr version of CheckImpl that returns the given value when it
+  // succeeds or evaluates to non-constexpr and returns 0 when it fails.
+  // This will result in the usual LOG(FATAL) if this is used where it isn't
+  // required to be constexpr or a compile error if it is.
+  static constexpr int32_t CheckConstexpr(int32_t nsec) {
+    return (nsec >= kNSecInSec || nsec < 0) ? CheckImpl(nsec), 0 : nsec;
+  }
+
+#ifdef SWIG
+#undef constexpr
+#endif  // SWIG
+};
+
+// Sleeps for the amount of time represented by time counted by clock.
+void SleepFor(const Time &time, clockid_t clock = Time::kDefaultClock);
+// Sleeps until clock is at the time represented by time.
+void SleepUntil(const Time &time, clockid_t clock = Time::kDefaultClock);
+
+// Sets the global offset for all times so ::aos::time::Time::Now() will return
+// now.
+// There is no synchronization here, so this is only safe when only a single
+// task is running.
+// This is only allowed when the shared memory core infrastructure has been
+// initialized in this process.
+void OffsetToNow(const Time &now);
+
+// RAII class that freezes Time::Now() (to avoid making large numbers of
+// syscalls to find the real time).
+class TimeFreezer {
+ public:
+  TimeFreezer() {
+    Time::EnableMockTime();
+  }
+  ~TimeFreezer() {
+    Time::DisableMockTime();
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TimeFreezer);
+};
+
+}  // namespace time
+}  // namespace aos
+
+#endif  // AOS_COMMON_TIME_H_
diff --git a/aos/common/time_test.cc b/aos/common/time_test.cc
new file mode 100644
index 0000000..c6ddd0c
--- /dev/null
+++ b/aos/common/time_test.cc
@@ -0,0 +1,233 @@
+#include "aos/common/time.h"
+
+#include "gtest/gtest.h"
+
+#include "aos/common/macros.h"
+#include "aos/common/util/death_test_log_implementation.h"
+
+namespace aos {
+namespace time {
+namespace testing {
+
+TEST(TimeTest, timespecConversions) {
+  timespec start{1234, 5678};  // NOLINT
+  Time time(start);
+  EXPECT_EQ(start.tv_sec, static_cast<time_t>(time.sec()));
+  EXPECT_EQ(start.tv_nsec, time.nsec());
+  timespec end = time.ToTimespec();
+  EXPECT_EQ(start.tv_sec, end.tv_sec);
+  EXPECT_EQ(start.tv_nsec, end.tv_nsec);
+}
+
+TEST(TimeTest, timevalConversions) {
+  timeval start{1234, 5678};  // NOLINT
+  Time time(start);
+  EXPECT_EQ(start.tv_sec, static_cast<long>(time.sec()));
+  EXPECT_EQ(start.tv_usec, time.nsec() / Time::kNSecInUSec);
+  timeval end = time.ToTimeval();
+  EXPECT_EQ(start.tv_sec, end.tv_sec);
+  EXPECT_EQ(start.tv_usec, end.tv_usec);
+}
+
+TEST(TimeDeathTest, ConstructorChecking) {
+  logging::Init();
+  EXPECT_DEATH(
+      {
+        logging::AddImplementation(new util::DeathTestLogImplementation());
+        Time(0, -1);
+      },
+      ".*0 <= nsec\\(-1\\) < 10+ .*");
+  EXPECT_DEATH(
+      {
+        logging::AddImplementation(new util::DeathTestLogImplementation());
+        Time(0, Time::kNSecInSec);
+      },
+      ".*0 <= nsec\\(10+\\) < 10+ .*");
+}
+
+// It's kind of hard not to test Now and SleepFor at the same time.
+TEST(TimeTest, NowAndSleepFor) {
+  // without this, it tends to fail the first time (ends up sleeping for way
+  // longer than it should the second time, where it actually matters)
+  SleepFor(Time(0, Time::kNSecInSec / 10));
+  Time start = Time::Now();
+  static constexpr Time kSleepTime = Time(0, Time::kNSecInSec * 2 / 10);
+  SleepFor(kSleepTime);
+  Time difference = Time::Now() - start;
+  EXPECT_GE(difference, kSleepTime);
+  EXPECT_LT(difference, kSleepTime + Time(0, Time::kNSecInSec / 100));
+}
+
+TEST(TimeTest, AbsoluteSleep) {
+  Time start = Time::Now();
+  SleepFor(Time(0, Time::kNSecInSec / 10));
+  static constexpr Time kSleepTime = Time(0, Time::kNSecInSec * 2 / 10);
+  SleepUntil(start + kSleepTime);
+  Time difference = Time::Now() - start;
+  EXPECT_GE(difference, kSleepTime);
+  EXPECT_LT(difference, kSleepTime + Time(0, Time::kNSecInSec / 100));
+}
+
+TEST(TimeTest, Addition) {
+  Time t(54, 500);
+  EXPECT_EQ(MACRO_DARG(Time(54, 5500)), t + MACRO_DARG(Time(0, 5000)));
+  EXPECT_EQ(MACRO_DARG(Time(56, 500)), t + MACRO_DARG(Time(2, 0)));
+  EXPECT_EQ(MACRO_DARG(Time(57, 6500)), t + MACRO_DARG(Time(3, 6000)));
+  EXPECT_EQ(MACRO_DARG(Time(50, 300)),
+            t + MACRO_DARG(Time(-5, Time::kNSecInSec - 200)));
+  EXPECT_EQ(Time(-46, 500), t + Time(-100, 0));
+  EXPECT_EQ(Time(-47, Time::kNSecInSec - 500),
+            Time(-101, Time::kNSecInSec - 1000) + t);
+}
+TEST(TimeTest, Subtraction) {
+  Time t(54, 500);
+  EXPECT_EQ(MACRO_DARG(Time(54, 300)), t - MACRO_DARG(Time(0, 200)));
+  EXPECT_EQ(MACRO_DARG(Time(42, 500)), t - MACRO_DARG(Time(12, 0)));
+  EXPECT_EQ(MACRO_DARG(Time(50, 100)), t - MACRO_DARG(Time(4, 400)));
+  EXPECT_EQ(MACRO_DARG(Time(53, 600)),
+            t - MACRO_DARG(Time(0, Time::kNSecInSec - 100)));
+  EXPECT_EQ(MACRO_DARG(Time(55, 800)),
+            t - MACRO_DARG(Time(-2, Time::kNSecInSec - 300)));
+  EXPECT_EQ(Time(54, 5500), t - Time(-1, Time::kNSecInSec - 5000));
+  EXPECT_EQ(Time(-50, Time::kNSecInSec - 300),
+            Time(5, 200) - t);
+}
+
+TEST(TimeTest, Multiplication) {
+  Time t(54, Time::kNSecInSec / 3);
+  EXPECT_EQ(MACRO_DARG(Time(108, Time::kNSecInSec / 3 * 2)), t * 2);
+  EXPECT_EQ(MACRO_DARG(Time(271, Time::kNSecInSec / 3 * 2 - 1)), t * 5);
+  EXPECT_EQ(Time(-109, Time::kNSecInSec / 3 + 1), t * -2);
+  EXPECT_EQ(Time(-55, Time::kNSecInSec / 3 * 2 + 1), t * -1);
+  EXPECT_EQ(Time(-218, Time::kNSecInSec / 3 * 2 + 2), (t * -1) * 4);
+}
+TEST(TimeTest, DivisionByInt) {
+  EXPECT_EQ(Time(5, Time::kNSecInSec / 10 * 4 + 50), Time(54, 500) / 10);
+  EXPECT_EQ(Time(2, Time::kNSecInSec / 4 * 3),
+            Time(5, Time::kNSecInSec / 2) / 2);
+  EXPECT_EQ(Time(-3, Time::kNSecInSec / 4 * 3),
+            Time(-5, Time::kNSecInSec / 2) / 2);
+}
+TEST(TimeTest, DivisionByTime) {
+  EXPECT_DOUBLE_EQ(2, Time(10, 0) / Time(5, 0));
+  EXPECT_DOUBLE_EQ(9, Time(27, 0) / Time(3, 0));
+  EXPECT_DOUBLE_EQ(9.25, Time(37, 0) / Time(4, 0));
+  EXPECT_DOUBLE_EQ(5.25, Time(36, Time::kNSecInSec / 4 * 3) / Time(7, 0));
+  EXPECT_DOUBLE_EQ(-5.25, Time(-37, Time::kNSecInSec / 4) / Time(7, 0));
+  EXPECT_DOUBLE_EQ(-5.25, Time(36, Time::kNSecInSec / 4 * 3) / Time(-7, 0));
+}
+
+TEST(TimeTest, Negation) {
+  EXPECT_EQ(Time(-5, 1234), -Time(4, Time::kNSecInSec - 1234));
+  EXPECT_EQ(Time(5, Time::kNSecInSec * 2 / 3 + 1),
+            -Time(-6, Time::kNSecInSec / 3));
+}
+
+TEST(TimeTest, Comparisons) {
+  EXPECT_TRUE(Time(971, 254) > Time(971, 253));
+  EXPECT_TRUE(Time(971, 254) >= Time(971, 253));
+  EXPECT_TRUE(Time(971, 254) < Time(971, 255));
+  EXPECT_TRUE(Time(971, 254) <= Time(971, 255));
+  EXPECT_TRUE(Time(971, 254) >= Time(971, 253));
+  EXPECT_TRUE(Time(971, 254) <= Time(971, 254));
+  EXPECT_TRUE(Time(971, 254) >= Time(971, 254));
+  EXPECT_TRUE(Time(972, 254) > Time(971, 254));
+  EXPECT_TRUE(Time(971, 254) < Time(972, 254));
+
+  EXPECT_TRUE(Time(-971, 254) > Time(-971, 253));
+  EXPECT_TRUE(Time(-971, 254) >= Time(-971, 253));
+  EXPECT_TRUE(Time(-971, 254) < Time(-971, 255));
+  EXPECT_TRUE(Time(-971, 254) <= Time(-971, 255));
+  EXPECT_TRUE(Time(-971, 254) >= Time(-971, 253));
+  EXPECT_TRUE(Time(-971, 254) <= Time(-971, 254));
+  EXPECT_TRUE(Time(-971, 254) >= Time(-971, 254));
+  EXPECT_TRUE(Time(-972, 254) < Time(-971, 254));
+  EXPECT_TRUE(Time(-971, 254) > Time(-972, 254));
+}
+
+TEST(TimeTest, Within) {
+  EXPECT_TRUE(MACRO_DARG(Time(55, 5000).IsWithin(Time(55, 4900), 100)));
+  EXPECT_FALSE(MACRO_DARG(Time(55, 5000).IsWithin(Time(55, 4900), 99)));
+  EXPECT_TRUE(MACRO_DARG(Time(5, 0).IsWithin(Time(4, Time::kNSecInSec - 200),
+                                             250)));
+  EXPECT_TRUE(Time(-5, Time::kNSecInSec - 200).IsWithin(Time(-4, 0), 250));
+  EXPECT_TRUE(Time(-5, 200).IsWithin(Time(-5, 0), 250));
+}
+
+TEST(TimeTest, Modulus) {
+  EXPECT_EQ(MACRO_DARG(Time(0, Time::kNSecInSec / 10 * 2)),
+            MACRO_DARG(Time(50, 0) % (Time::kNSecInSec / 10 * 3)));
+  EXPECT_EQ(Time(-1, Time::kNSecInSec / 10 * 8),
+            Time(-50, 0) % (Time::kNSecInSec / 10 * 3));
+  EXPECT_EQ(Time(-1, Time::kNSecInSec / 10 * 8),
+            Time(-50, 0) % (-Time::kNSecInSec / 10 * 3));
+  EXPECT_EQ(Time(0, Time::kNSecInSec / 10 * 2),
+            Time(50, 0) % (-Time::kNSecInSec / 10 * 3));
+  EXPECT_EQ(Time(1, Time::kNSecInSec / 10),
+            Time(60, Time::kNSecInSec / 10) % (Time::kNSecInSec / 10 * 12));
+}
+
+TEST(TimeTest, InSeconds) {
+  EXPECT_EQ(MACRO_DARG(Time(2, Time::kNSecInSec / 100 * 55 - 1)),
+            Time::InSeconds(2.55));
+  EXPECT_EQ(MACRO_DARG(Time(-3, Time::kNSecInSec / 100 * 45)),
+            Time::InSeconds(-2.55));
+}
+
+TEST(TimeTest, ToSeconds) {
+  EXPECT_DOUBLE_EQ(13.23, Time::InSeconds(13.23).ToSeconds());
+  EXPECT_NEAR(-13.23, Time::InSeconds(-13.23).ToSeconds(),
+              1.0 / Time::kNSecInSec * 2);
+}
+
+TEST(TimeTest, InMS) {
+  Time t = Time::InMS(254971);
+  EXPECT_EQ(254, t.sec());
+  EXPECT_EQ(971000000, t.nsec());
+
+  Time t2 = Time::InMS(-254971);
+  EXPECT_EQ(-255, t2.sec());
+  EXPECT_EQ(Time::kNSecInSec - 971000000, t2.nsec());
+}
+
+TEST(TimeTest, ToMSec) {
+  EXPECT_EQ(254971, Time(254, 971000000).ToMSec());
+  EXPECT_EQ(-254971, Time(-255, Time::kNSecInSec - 971000000).ToMSec());
+}
+
+TEST(TimeTest, InNS) {
+  Time t = Time::InNS(static_cast<int64_t>(973254111971ll));
+  EXPECT_EQ(973, t.sec());
+  EXPECT_EQ(254111971, t.nsec());
+
+  Time t2 = Time::InNS(static_cast<int64_t>(-973254111971ll));
+  EXPECT_EQ(-974, t2.sec());
+  EXPECT_EQ(Time::kNSecInSec - 254111971, t2.nsec());
+}
+
+TEST(TimeTest, InUS) {
+  Time t = Time::InUS(254111971);
+  EXPECT_EQ(254, t.sec());
+  EXPECT_EQ(111971000, t.nsec());
+
+  Time t2 = Time::InUS(-254111971);
+  EXPECT_EQ(-255, t2.sec());
+  EXPECT_EQ(Time::kNSecInSec - 111971000, t2.nsec());
+}
+
+TEST(TimeTest, ToUSec) {
+  EXPECT_EQ(254000971, Time(254, 971000).ToUSec());
+  EXPECT_EQ(-254000971, Time(-255, Time::kNSecInSec - 971000).ToUSec());
+}
+
+TEST(TimeTest, Abs) {
+  EXPECT_EQ(MACRO_DARG(Time(971, 1114)), MACRO_DARG(Time(971, 1114).abs()));
+  EXPECT_EQ(MACRO_DARG(Time(253, Time::kNSecInSec * 0.3)),
+            MACRO_DARG(Time(-254, Time::kNSecInSec * 0.7).abs()));
+  EXPECT_EQ(MACRO_DARG(-Time(-971, 973).ToNSec()),
+            MACRO_DARG(Time(970, Time::kNSecInSec - 973).ToNSec()));
+}
+
+}  // namespace testing
+}  // namespace time
+}  // namespace aos
diff --git a/aos/common/type_traits.h b/aos/common/type_traits.h
new file mode 100644
index 0000000..4b5fa8c
--- /dev/null
+++ b/aos/common/type_traits.h
@@ -0,0 +1,38 @@
+#ifndef AOS_COMMON_TYPE_TRAITS_
+#define AOS_COMMON_TYPE_TRAITS_
+
+#include <features.h>
+
+#include <type_traits>
+
+namespace aos {
+namespace {
+
+template<typename Tp>
+struct has_trivial_copy_assign : public std::integral_constant<bool,
+// This changed between 4.4.5 and 4.6.3. Unless somebody discovers otherwise,
+// 4.6 seems like a reasonable place to switch.
+#if ((__GNUC__ < 4) || (__GNUC_MINOR__ < 6)) && !defined(__clang__)
+    ::std::has_trivial_assign<Tp>::value> {};
+#else
+    ::std::has_trivial_copy_assign<Tp>::value> {};
+#endif
+
+}  // namespace
+
+// A class template that determines whether or not it is safe to pass a type
+// through the shared memory system (aka whether or not you can memcpy it).
+// Useful in combination with static_assert.
+//
+// Doesn't need a trivial constructor because it's bytes only need to get
+// copied. If it has a non-trivial destructor, somebody has to make sure to call
+// it when appropriate.
+// See also (3.9) [basic.types] in the C++11 standard.
+template<typename Tp>
+struct shm_ok : public std::integral_constant<bool,
+    (std::has_trivial_copy_constructor<Tp>::value &&
+     aos::has_trivial_copy_assign<Tp>::value)> {};
+
+}  // namespace aos
+
+#endif
diff --git a/aos/common/type_traits_test.cpp b/aos/common/type_traits_test.cpp
new file mode 100644
index 0000000..aa104ee
--- /dev/null
+++ b/aos/common/type_traits_test.cpp
@@ -0,0 +1,98 @@
+#include "aos/common/type_traits.h"
+
+#include "gtest/gtest.h"
+
+namespace aos {
+namespace testing {
+
+class BadVirtualFunction {
+  virtual void Test() {}
+};
+TEST(TypeTraitsTest, VirtualFunction) {
+  EXPECT_FALSE(shm_ok<BadVirtualFunction>::value);
+}
+class BadPureVirtualFunction {
+  virtual void Test() = 0;
+};
+TEST(TypeTraitsTest, PureVirtualFunction) {
+  EXPECT_FALSE(shm_ok<BadPureVirtualFunction>::value);
+}
+class BadInheritedVirtual : public BadVirtualFunction {};
+TEST(TypeTraitsTest, InheritedVirtualFunction) {
+  EXPECT_FALSE(shm_ok<BadInheritedVirtual>::value);
+}
+class BadVirtualDestructor {
+  virtual ~BadVirtualDestructor();
+};
+TEST(TypeTraitsTest, VirtualDestructor) {
+  EXPECT_FALSE(shm_ok<BadVirtualDestructor>::value);
+}
+class Boring {};
+class BadVirtualBase : public virtual Boring {};
+TEST(TypeTraitsTest, VirtualBase) {
+  EXPECT_FALSE(shm_ok<BadVirtualBase>::value);
+}
+
+class GoodSimple {
+ public:
+  int test1, test2;
+  double test3;
+};
+// Make sure that it lets simple classes through and that the compiler isn't
+// completely nuts.
+TEST(TypeTraitsTest, Basic) {
+  EXPECT_TRUE(shm_ok<GoodSimple>::value);
+  GoodSimple test{5, 4, 34.2};
+  EXPECT_EQ(5, test.test1);
+  EXPECT_EQ(4, test.test2);
+  EXPECT_EQ(34.2, test.test3);
+  memset(&test, 0, sizeof(test));
+  EXPECT_EQ(0, test.test1);
+  EXPECT_EQ(0, test.test2);
+  EXPECT_EQ(0, test.test3);
+}
+
+class GoodWithConstructor {
+ public:
+  int val_;
+  GoodWithConstructor(int val) : val_(val) {}
+};
+// Make sure that it lets classes with constructors through.
+TEST(TypeTraitsTest, GoodWithConstructor) {
+  EXPECT_TRUE(shm_ok<GoodWithConstructor>::value);
+  GoodWithConstructor test(971);
+  EXPECT_EQ(971, test.val_);
+}
+
+class GoodPublicPrivateFunction {
+ public:
+  int32_t a_;
+  void set_a(int32_t a) { a_ = a; }
+  int32_t b() { return b_; }
+  void set_b(int32_t b) { b_ = b; }
+ private:
+  int32_t b_;
+};
+// Make sure that member functions still work.
+TEST(TypeTraitsTest, Function) {
+  EXPECT_TRUE(shm_ok<GoodPublicPrivateFunction>::value);
+  EXPECT_EQ(static_cast<unsigned>(8), sizeof(GoodPublicPrivateFunction)) <<
+      "The compiler did something weird, but it might not be a problem.";
+  GoodPublicPrivateFunction test;
+  test.a_ = 5;
+  test.set_b(971);
+  EXPECT_EQ(5, test.a_);
+  EXPECT_EQ(971, test.b());
+  test.set_a(74);
+  EXPECT_EQ(74, test.a_);
+  memset(&test, 0, sizeof(test));
+  EXPECT_EQ(0, test.a_);
+  EXPECT_EQ(0, test.b());
+  test.set_a(123);
+  test.set_b(254);
+  EXPECT_EQ(123, test.a_);
+  EXPECT_EQ(254, test.b());
+}
+
+}  // namespace testing
+}  // namespace aos
diff --git a/aos/common/unique_malloc_ptr.h b/aos/common/unique_malloc_ptr.h
new file mode 100644
index 0000000..bd2c37c
--- /dev/null
+++ b/aos/common/unique_malloc_ptr.h
@@ -0,0 +1,44 @@
+#include <memory>
+
+namespace aos {
+
+namespace {
+
+// Written as a functor so that it doesn't have to get passed to
+// std::unique_ptr's constructor as an argument.
+template<typename T, void(*function)(T *)>
+class const_wrap {
+ public:
+  void operator()(const T *ptr) {
+    function(const_cast<T *>(ptr));
+  }
+};
+
+// Wrapper function to deal with the differences between C and C++ (C++ doesn't
+// automatically convert T* to void* like C).
+template<typename T>
+void free_type(T *ptr) { ::free(reinterpret_cast<void *>(ptr)); }
+
+}  // namespace
+
+// A std::unique_ptr that should get freed with a C-style free function
+// (free(2) by default).
+template<typename T, void(*function)(T *) = free_type<T>>
+class unique_c_ptr : public std::unique_ptr<T, const_wrap<T, function>> {
+ public:
+  unique_c_ptr(T *value) : std::unique_ptr<T, const_wrap<T, function>>(value) {}
+
+  // perfect forwarding of these 2 to make unique_ptr work
+  template<typename... Args>
+  unique_c_ptr(Args&&... args)
+    : std::unique_ptr<T, const_wrap<T, function>>(std::forward<Args>(args)...) {
+  }
+  template<typename... Args>
+  unique_c_ptr<T, function> &operator=(Args&&... args) {
+    std::unique_ptr<T, const_wrap<T, function>>::operator=(
+        std::forward<Args>(args)...);
+    return *this;
+  }
+};
+
+}  // namespace aos
diff --git a/aos/common/util/death_test_log_implementation.h b/aos/common/util/death_test_log_implementation.h
new file mode 100644
index 0000000..c1b12c0
--- /dev/null
+++ b/aos/common/util/death_test_log_implementation.h
@@ -0,0 +1,27 @@
+#ifndef AOS_COMMON_UTIL_DEATH_TEST_LOG_IMPLEMENTATION_H_
+#define AOS_COMMON_UTIL_DEATH_TEST_LOG_IMPLEMENTATION_H_
+
+#include <stdlib.h>
+
+#include "aos/common/logging/logging_impl.h"
+
+namespace aos {
+namespace util {
+
+// Prints all FATAL messages to stderr and then abort(3)s before the regular
+// stuff can print out anything else. Ignores all other messages.
+// This is useful in death tests that expect a LOG(FATAL) to cause the death.
+class DeathTestLogImplementation : public logging::HandleMessageLogImplementation {
+ public:
+  virtual void HandleMessage(const logging::LogMessage &message) override {
+    if (message.level == FATAL) {
+      logging::internal::PrintMessage(stderr, message);
+      abort();
+    }
+  }
+};
+
+}  // namespace util
+}  // namespace aos
+
+#endif  // AOS_COMMON_UTIL_DEATH_TEST_LOG_IMPLEMENTATION_H_
diff --git a/aos/common/util/inet_addr.cc b/aos/common/util/inet_addr.cc
new file mode 100644
index 0000000..48bde1d
--- /dev/null
+++ b/aos/common/util/inet_addr.cc
@@ -0,0 +1,41 @@
+#include "aos/common/util/inet_addr.h"
+
+#include <stdlib.h>
+#ifndef __VXWORKS__
+#include <string.h>
+
+#include "aos/common/byteorder.h"
+#else
+
+template<typename T>
+T hton(T);
+
+template<uint32_t>
+uint32_t hton(uint32_t v) { return v; }
+
+#endif
+
+namespace aos {
+namespace util {
+
+const char *MakeIPAddress(const in_addr &base_address,
+                          ::aos::NetworkAddress last_segment) {
+  in_addr address = base_address;
+  SetLastSegment(&address, last_segment);
+
+#ifdef __VXWORKS__
+  char *r = static_cast<char *>(malloc(INET_ADDR_LEN));
+  inet_ntoa_b(address, r);
+  return r;
+#else
+  return strdup(inet_ntoa(address));
+#endif
+}
+
+void SetLastSegment(in_addr *address, ::aos::NetworkAddress last_segment) {
+  address->s_addr &= ~(hton<uint32_t>(0xFF));
+  address->s_addr |= hton<uint32_t>(static_cast<uint8_t>(last_segment));
+}
+
+}  // namespace util
+}  // namespace aos
diff --git a/aos/common/util/inet_addr.h b/aos/common/util/inet_addr.h
new file mode 100644
index 0000000..35368f1
--- /dev/null
+++ b/aos/common/util/inet_addr.h
@@ -0,0 +1,29 @@
+#ifndef AOS_COMMON_UTIL_INET_ADDR_H_
+#define AOS_COMMON_UTIL_INET_ADDR_H_
+
+#ifdef __VXWORKS__
+#include <inetLib.h>
+#else
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+
+#include "aos/common/network_port.h"
+
+namespace aos {
+namespace util {
+
+// Makes an IP address string from base_address with the last byte set to
+// last_segment.
+// Returns a malloc(3)ed string.
+const char *MakeIPAddress(const in_addr &base_address,
+                          ::aos::NetworkAddress last_segment);
+
+// Sets the last byte of *address to last_segment.
+void SetLastSegment(in_addr *address, ::aos::NetworkAddress last_segment);
+
+}  // namespace util
+}  // namespace aos
+
+#endif  // AOS_COMMON_UTIL_INET_ADDR_H_
diff --git a/aos/common/util/log_interval.h b/aos/common/util/log_interval.h
new file mode 100644
index 0000000..7c8a329
--- /dev/null
+++ b/aos/common/util/log_interval.h
@@ -0,0 +1,93 @@
+#ifndef AOS_COMMON_UTIL_LOG_INTERVAL_H_
+#define AOS_COMMON_UTIL_LOG_INTERVAL_H_
+
+#include "aos/common/time.h"
+#include "aos/common/logging/logging.h"
+
+#include <string>
+
+namespace aos {
+namespace util {
+
+// A class to help with logging things that happen a lot only occasionally.
+//
+// Intended use {
+//   static LogInterval interval(::aos::time::Time::InSeconds(0.2));
+//
+//   if (WantToLog()) {
+//     interval.WantToLog();
+//   }
+//   if (interval.ShouldLog()) {
+//     LOG(DEBUG, "thingie happened! (%d times)\n", interval.Count());
+//   }
+// }
+class LogInterval {
+ public:
+  constexpr LogInterval(const ::aos::time::Time &interval)
+      : count_(0), interval_(interval), last_done_(0, 0) {}
+
+  void WantToLog() {
+    if (count_ == 0) {
+      last_done_ = ::aos::time::Time::Now();
+    }
+    ++count_;
+  }
+  bool ShouldLog() {
+    const ::aos::time::Time now = ::aos::time::Time::Now();
+    const bool r = (now - last_done_) >= interval_ && count_ > 0;
+    if (r) {
+      last_done_ = now;
+    }
+    return r;
+  }
+  int Count() {
+    const int r = count_;
+    count_ = 0;
+    return r;
+  }
+
+  const ::aos::time::Time &interval() const { return interval_; }
+
+ private:
+  int count_;
+  const ::aos::time::Time interval_;
+  ::aos::time::Time last_done_;
+};
+
+// This one is even easier to use. It always logs with a message "%s %d
+// times\n". Call LOG_INTERVAL wherever it should log and make sure Print gets
+// called often (ie not after a conditional return)
+class SimpleLogInterval {
+ public:
+  SimpleLogInterval(const ::aos::time::Time &interval, log_level level,
+                    const ::std::string &message)
+      : interval_(interval), level_(level), message_(message) {}
+
+#define LOG_INTERVAL(simple_log) \
+  simple_log.WantToLog(LOG_SOURCENAME ": " STRINGIFY(__LINE__))
+  void WantToLog(const char *context) {
+    context_ = context;
+    interval_.WantToLog();
+  }
+
+  void Print() {
+    if (interval_.ShouldLog()) {
+      CHECK_NOTNULL(context_);
+      log_do(level_, "%s: %.*s %d times over %f sec\n", context_,
+             static_cast<int>(message_.size()), message_.data(),
+             interval_.Count(), interval_.interval().ToSeconds());
+      context_ = NULL;
+    }
+  }
+
+ private:
+  LogInterval interval_;
+  const log_level level_;
+  const ::std::string message_;
+  const char *context_ = NULL;
+};
+
+}  // namespace util
+}  // namespace aos
+
+#endif  // AOS_COMMON_UTIL_LOG_INTERVAL_H_
diff --git a/aos/common/util/options.h b/aos/common/util/options.h
new file mode 100644
index 0000000..48c4fd8
--- /dev/null
+++ b/aos/common/util/options.h
@@ -0,0 +1,92 @@
+#ifndef AOS_COMMON_UTIL_OPTIONS_H_
+#define AOS_COMMON_UTIL_OPTIONS_H_
+
+#include <sys/types.h>
+
+namespace aos {
+
+template <class Owner>
+class Options;
+
+// An "option" that can be combined with other options and passed as one
+// argument. This class is designed to emulate integral constants (except be
+// type-safe), so its instances can be combined with operator| (creating an
+// Options), and an Options can be tested for membership with operator&.
+// Owner is the only class that can construct Option instances and is used to
+// differentiate between options for different classes. It is safe to only have
+// a forward declaration for Owner in scope when instantiating either of these
+// template classes.
+template <class Owner>
+class Options {
+ public:
+  // Represents a single options. Instances of this should be created as
+  // constants by Owner.
+  class Option {
+   public:
+    constexpr Options operator|(Option option) const {
+      return Options(bit_ | option.bit_);
+    }
+
+    constexpr bool operator==(Option other) const { return bit_ == other.bit_; }
+
+    constexpr unsigned int printable() const { return bit_; }
+
+   private:
+    // Bit must have exactly 1 bit set and that must be a different one for each
+    // instance.
+    explicit constexpr Option(unsigned int bit) : bit_(bit) {}
+
+    unsigned int bit_;
+
+    friend class Options;
+    friend Owner;
+  };
+
+  constexpr Options(Option option) : bits_(option.bit_) {}
+
+  constexpr bool operator&(Option option) const {
+    return (bits_ & option.bit_) != 0;
+  }
+
+  constexpr Options operator|(Option option) const {
+    return Options(bits_ | option.bit_);
+  }
+  constexpr Options operator|(Options options) const {
+    return Options(bits_ | options.bits_);
+  }
+
+  constexpr bool operator==(Options other) const {
+    return bits_ == other.bits_;
+  }
+
+  constexpr unsigned int printable() const { return bits_; }
+
+  // Returns true if no Options other than the ones in options are set.
+  // Useful for validating that no illegal options are passed.
+  constexpr bool NoOthersSet(Options options) const {
+    return (bits_ & ~options.bits_) == 0;
+  }
+
+  // Returns true if exactly 1 of the Options in options is set.
+  // Useful for validating that one of a group of mutually exclusive options has
+  // been passed.
+  constexpr bool ExactlyOneSet(Options options) const {
+    return __builtin_popcount(bits_ & options.bits_) == 1;
+  }
+
+  // Returns true if all of the Options in options are set.
+  constexpr bool AllSet(Options options) const {
+    return (bits_ & options.bits_) == options.bits_;
+  }
+
+ private:
+  explicit constexpr Options(unsigned int bits) : bits_(bits) {}
+
+  unsigned int bits_;
+
+  friend class Option;
+};
+
+}  // namespace options
+
+#endif  // AOS_COMMON_UTIL_OPTIONS_H_
diff --git a/aos/common/util/options_test.cc b/aos/common/util/options_test.cc
new file mode 100644
index 0000000..197340c
--- /dev/null
+++ b/aos/common/util/options_test.cc
@@ -0,0 +1,56 @@
+#include "aos/common/util/options.h"
+
+#include "gtest/gtest.h"
+
+namespace aos {
+namespace testing {
+
+class OptionsTest : public ::testing::Test {
+ public:
+  static constexpr Options<OptionsTest>::Option kOne{1}, kTwo{2}, kThree{4},
+      kFour{8};
+};
+
+constexpr Options<OptionsTest>::Option OptionsTest::kOne, OptionsTest::kTwo,
+    OptionsTest::kThree, OptionsTest::kFour;
+
+TEST_F(OptionsTest, Basic) {
+  const Options<OptionsTest> one_three = kOne | kThree;
+  EXPECT_TRUE(one_three & kOne);
+  EXPECT_FALSE(one_three & kTwo);
+  EXPECT_TRUE(one_three & kThree);
+}
+
+TEST_F(OptionsTest, NoOthersSet) {
+  const Options<OptionsTest> one_three = kOne | kThree;
+  EXPECT_TRUE(one_three.NoOthersSet(one_three));
+  EXPECT_TRUE(one_three.NoOthersSet(kOne | kTwo | kThree));
+  EXPECT_TRUE(one_three.NoOthersSet(kOne | kThree | kFour));
+  EXPECT_TRUE(one_three.NoOthersSet(kOne | kTwo | kThree | kFour));
+  EXPECT_FALSE(one_three.NoOthersSet(kOne));
+  EXPECT_FALSE(one_three.NoOthersSet(kThree));
+  EXPECT_FALSE(one_three.NoOthersSet(kTwo | kFour));
+}
+
+TEST_F(OptionsTest, ExactlyOneSet) {
+  const Options<OptionsTest> one_three = kOne | kThree;
+  EXPECT_TRUE(one_three.ExactlyOneSet(kOne | kTwo));
+  EXPECT_FALSE(one_three.ExactlyOneSet(one_three));
+  EXPECT_TRUE(one_three.ExactlyOneSet(kTwo | kThree | kFour));
+  EXPECT_FALSE(one_three.ExactlyOneSet(kOne | kTwo | kThree | kFour));
+}
+
+TEST_F(OptionsTest, AllSet) {
+  const Options<OptionsTest> one_three = kOne | kThree;
+  EXPECT_TRUE(one_three.AllSet(one_three));
+  EXPECT_TRUE(one_three.AllSet(kOne));
+  EXPECT_FALSE(one_three.AllSet(kTwo));
+  EXPECT_TRUE(one_three.AllSet(kThree));
+  EXPECT_FALSE(one_three.AllSet(kFour));
+  EXPECT_FALSE(one_three.AllSet(kOne | kTwo | kFour));
+  EXPECT_FALSE(one_three.AllSet(kTwo | kThree | kFour));
+  EXPECT_FALSE(one_three.AllSet(kOne | kTwo | kThree | kFour));
+}
+
+}  // namespace testing
+}  // namespace aos
diff --git a/aos/common/util/phased_loop.cc b/aos/common/util/phased_loop.cc
new file mode 100644
index 0000000..4b9dcdb
--- /dev/null
+++ b/aos/common/util/phased_loop.cc
@@ -0,0 +1,20 @@
+#include "aos/common/util/phased_loop.h"
+
+#include <string.h>
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/time.h"
+
+namespace aos {
+namespace time {
+
+void PhasedLoopXMS(int ms, int offset) {
+  // TODO(brians): Tests!
+  const Time frequency = Time::InMS(ms);
+  SleepUntil((Time::Now() / static_cast<int32_t>(frequency.ToNSec())) *
+             static_cast<int32_t>(frequency.ToNSec()) +
+             frequency + Time::InUS(offset));
+}
+
+}  // namespace timing
+}  // namespace aos
diff --git a/aos/common/util/phased_loop.h b/aos/common/util/phased_loop.h
new file mode 100644
index 0000000..f3c417a
--- /dev/null
+++ b/aos/common/util/phased_loop.h
@@ -0,0 +1,17 @@
+#ifndef AOS_COMMON_UTIL_PHASED_LOOP_H_
+#define AOS_COMMON_UTIL_PHASED_LOOP_H_
+
+#include <time.h>
+#include <string>
+
+namespace aos {
+namespace time {
+
+// Will not be accurate if ms isn't a factor of 1000.
+// offset is in us.
+void PhasedLoopXMS(int ms, int offset);
+
+}  // namespace time
+}  // namespace aos
+
+#endif  // AOS_COMMON_UTIL_PHASED_LOOP_H_
diff --git a/aos/common/util/run_command.cc b/aos/common/util/run_command.cc
new file mode 100644
index 0000000..a4a19d8
--- /dev/null
+++ b/aos/common/util/run_command.cc
@@ -0,0 +1,73 @@
+#include "aos/common/util/run_command.h"
+
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include "aos/common/logging/logging.h"
+
+namespace aos {
+namespace util {
+namespace {
+
+// RAII class to block SIGCHLD and then restore it on destruction.
+class BlockSIGCHLD {
+ public:
+  BlockSIGCHLD() {
+    sigset_t to_block;
+    sigemptyset(&to_block);
+    sigaddset(&to_block, SIGCHLD);
+    if (sigprocmask(SIG_BLOCK, &to_block, &original_blocked_) == -1) {
+      PLOG(FATAL, "sigprocmask(SIG_BLOCK, %p, %p) failed",
+           &to_block, &original_blocked_);
+    }
+  }
+  ~BlockSIGCHLD() {
+    if (sigprocmask(SIG_SETMASK, &original_blocked_, nullptr) == -1) {
+      PLOG(FATAL, "sigprocmask(SIG_SETMASK, %p, nullptr) failed",
+           &original_blocked_);
+    }
+  }
+
+ private:
+  sigset_t original_blocked_;
+};
+
+}  // namespace
+
+int RunCommand(const char *command) {
+  BlockSIGCHLD blocker;
+  const pid_t pid = fork();
+  switch (pid) {
+    case 0:  // in child
+      {
+        int new_stdin = open("/dev/null", O_RDONLY);
+        if (new_stdin == -1) _exit(127);
+        int new_stdout = open("/dev/null", O_WRONLY);
+        if (new_stdout == -1) _exit(127);
+        int new_stderr = open("/dev/null", O_WRONLY);
+        if (new_stderr == -1) _exit(127);
+        if (dup2(new_stdin, 0) != 0) _exit(127);
+        if (dup2(new_stdout, 1) != 1) _exit(127);
+        if (dup2(new_stderr, 2) != 2) _exit(127);
+        execl("/bin/sh", "sh", "-c", command, nullptr);
+        _exit(127);
+      }
+    case -1:
+      return -1;
+    default:
+      int stat;
+      while (waitpid(pid, &stat, 0) == -1) {
+        if (errno != EINTR) {
+          return -1;
+        }
+      }
+      return stat;
+  }
+}
+
+}  // namespace util
+}  // namespace aos
diff --git a/aos/common/util/run_command.h b/aos/common/util/run_command.h
new file mode 100644
index 0000000..d116481
--- /dev/null
+++ b/aos/common/util/run_command.h
@@ -0,0 +1,17 @@
+#ifndef AOS_COMMON_UTIL_RUN_COMMAND_H_
+#define AOS_COMMON_UTIL_RUN_COMMAND_H_
+
+namespace aos {
+namespace util {
+
+// Improved replacement for system(3). Doesn't block signals like system(3) and
+// is thread-safe. Also makes sure all 3 standard streams are /dev/null.
+//
+// This means that it passes command to `/bin/sh -c` and returns -1 or a status
+// like from wait(2).
+int RunCommand(const char *command);
+
+}  // namespace util
+}  // namespace aos
+
+#endif  // AOS_COMMON_UTIL_RUN_COMMAND_H_
diff --git a/aos/common/util/run_command_test.cc b/aos/common/util/run_command_test.cc
new file mode 100644
index 0000000..daff3c5
--- /dev/null
+++ b/aos/common/util/run_command_test.cc
@@ -0,0 +1,61 @@
+#include "aos/common/util/run_command.h"
+
+#include "gtest/gtest.h"
+
+#include "aos/common/util/thread.h"
+
+namespace aos {
+namespace util {
+namespace testing {
+
+TEST(RunCommandTest, True) {
+  int result = RunCommand("true");
+  ASSERT_NE(-1, result);
+  ASSERT_TRUE(WIFEXITED(result));
+  EXPECT_EQ(0, WEXITSTATUS(result));
+}
+
+TEST(RunCommandTest, False) {
+  int result = RunCommand("false");
+  ASSERT_NE(-1, result);
+  ASSERT_TRUE(WIFEXITED(result));
+  EXPECT_EQ(1, WEXITSTATUS(result));
+}
+
+TEST(RunCommandTest, CommandNotFound) {
+  int result = RunCommand("ajflkjasdlfa");
+  ASSERT_NE(-1, result);
+  ASSERT_TRUE(WIFEXITED(result));
+  EXPECT_EQ(127, WEXITSTATUS(result));
+}
+
+TEST(RunCommandTest, KilledBySignal) {
+  int result = RunCommand("kill -QUIT $$");
+  ASSERT_NE(-1, result);
+  ASSERT_TRUE(WIFSIGNALED(result));
+  EXPECT_EQ(SIGQUIT, WTERMSIG(result));
+}
+
+TEST(RunCommandTest, MultipleThreads) {
+  int result1, result2;
+  util::FunctionThread t1([&result1](util::Thread *) {
+    result1 = RunCommand("true");
+  });
+  util::FunctionThread t2([&result2](util::Thread *) {
+    result2 = RunCommand("true");
+  });
+  t1.Start();
+  t2.Start();
+  t1.WaitUntilDone();
+  t2.WaitUntilDone();
+  ASSERT_NE(-1, result1);
+  ASSERT_NE(-1, result2);
+  ASSERT_TRUE(WIFEXITED(result1));
+  ASSERT_TRUE(WIFEXITED(result2));
+  EXPECT_EQ(0, WEXITSTATUS(result1));
+  EXPECT_EQ(0, WEXITSTATUS(result2));
+}
+
+}  // namespace testing
+}  // namespace util
+}  // namespace aos
diff --git a/aos/common/util/string_to_num.h b/aos/common/util/string_to_num.h
new file mode 100644
index 0000000..d99ed91
--- /dev/null
+++ b/aos/common/util/string_to_num.h
@@ -0,0 +1,29 @@
+#ifndef AOS_COMMON_UTIL_STRING_TO_NUM_H_
+#define AOS_COMMON_UTIL_STRING_TO_NUM_H_
+
+#include <sstream>
+#include <string>
+
+namespace aos {
+namespace util {
+
+// Converts a string into a specified numeric type. If it can't be converted
+// completely or at all, or if the converted number would overflow the
+// specified type, it returns false.
+template<typename T>
+inline bool StringToNumber(const ::std::string &input, T *out_num) {
+  ::std::istringstream stream(input);
+  stream >> *out_num;
+
+  if (stream.fail() || !stream.eof()) {
+    return false;
+  }
+
+  return true;
+}
+
+
+}  // util
+}  // aos
+
+#endif
diff --git a/aos/common/util/string_to_num_test.cc b/aos/common/util/string_to_num_test.cc
new file mode 100644
index 0000000..705de42
--- /dev/null
+++ b/aos/common/util/string_to_num_test.cc
@@ -0,0 +1,49 @@
+#include <stdint.h>
+
+#include <string>
+
+#include "gtest/gtest.h"
+
+#include "aos/common/util/string_to_num.h"
+
+namespace aos {
+namespace util {
+namespace testing {
+
+TEST(StringToNumTest, CorrectNumber) {
+  int result;
+  ASSERT_TRUE(StringToNumber<int>(::std::string("42"), &result));
+  EXPECT_EQ(result, 42);
+}
+
+TEST(StringToNumTest, NegativeTest) {
+  int result;
+  ASSERT_TRUE(StringToNumber<int>(::std::string("-42"), &result));
+  EXPECT_EQ(result, -42);
+}
+
+TEST(StringToNumTest, NonNumber) {
+  int result;
+  ASSERT_FALSE(StringToNumber<int>(::std::string("Daniel"), &result));
+}
+
+TEST(StringToNumTest, NumberWithText) {
+  int result;
+  ASSERT_FALSE(StringToNumber<int>(::std::string("42Daniel"), &result));
+}
+
+TEST(StringToNumTest, OverflowTest) {
+  uint32_t result;
+  // 2 << 32 should overflow.
+  ASSERT_FALSE(StringToNumber<uint32_t>(::std::string("4294967296"), &result));
+}
+
+TEST(StringToNumTest, FloatingPointTest) {
+  double result;
+  ASSERT_TRUE(StringToNumber<double>(::std::string("3.1415927")));
+  EXPECT_EQ(result, 3.1415927);
+}
+
+}  // testing
+}  // util
+}  // aos
diff --git a/aos/common/util/thread.cc b/aos/common/util/thread.cc
new file mode 100644
index 0000000..54a8ef2
--- /dev/null
+++ b/aos/common/util/thread.cc
@@ -0,0 +1,76 @@
+#include "aos/common/util/thread.h"
+
+#include <pthread.h>
+#include <signal.h>
+
+#include "aos/common/logging/logging.h"
+
+namespace aos {
+namespace util {
+
+Thread::Thread() : started_(false), joined_(false), should_terminate_(false) {}
+
+Thread::~Thread() {
+  CHECK(!(started_ && !joined_));
+}
+
+void Thread::Start() {
+  CHECK(!started_);
+  started_ = true;
+  CHECK(pthread_create(&thread_, NULL, &Thread::StaticRun, this) == 0);
+}
+
+void Thread::Join() {
+  CHECK(!joined_ && started_);
+  joined_ = true;
+  should_terminate_.store(true);
+  CHECK(pthread_join(thread_, NULL) == 0);
+}
+
+bool Thread::TryJoin() {
+  CHECK(!joined_ && started_);
+#ifdef AOS_SANITIZER_thread
+  // ThreadSanitizer misses the tryjoin and then complains about leaking the
+  // thread. Instead, we'll just check if the thread is still around and then
+  // do a regular Join() iff it isn't.
+  // TODO(brians): Remove this once tsan learns about pthread_tryjoin_np.
+  const int kill_ret = pthread_kill(thread_, 0);
+  // If it's still around.
+  if (kill_ret == 0) return false;
+  // If it died, we'll get ESRCH. Otherwise, something went wrong.
+  if (kill_ret != ESRCH) {
+    PELOG(FATAL, kill_ret, "pthread_kill(thread_, 0) failed");
+  }
+  Join();
+  return true;
+#else
+  const int ret = pthread_tryjoin_np(thread_, nullptr);
+  if (ret == 0) {
+    joined_ = true;
+    return true;
+  } else if (ret == EBUSY) {
+    return false;
+  } else {
+    PELOG(FATAL, ret, "pthread_tryjoin_np(thread_, nullptr) failed");
+  }
+#endif
+}
+
+void Thread::RequestStop() {
+  CHECK(!joined_ && started_);
+  should_terminate_.store(true);
+}
+
+void Thread::WaitUntilDone() {
+  CHECK(!joined_ && started_);
+  joined_ = true;
+  CHECK(pthread_join(thread_, NULL) == 0);
+}
+
+void *Thread::StaticRun(void *self) {
+  static_cast<Thread *>(self)->Run();
+  return NULL;
+}
+
+}  // namespace util
+}  // namespace aos
diff --git a/aos/common/util/thread.h b/aos/common/util/thread.h
new file mode 100644
index 0000000..993e343
--- /dev/null
+++ b/aos/common/util/thread.h
@@ -0,0 +1,90 @@
+#ifndef AOS_COMMON_UTIL_THREAD_H_
+#define AOS_COMMON_UTIL_THREAD_H_
+
+#include <functional>
+#include <atomic>
+
+#include <pthread.h>
+
+#include "aos/common/macros.h"
+
+namespace aos {
+namespace util {
+
+// A nice wrapper around a pthreads thread.
+//
+// TODO(aschuh): Test this.
+class Thread {
+ public:
+  Thread();
+  virtual ~Thread();
+
+  // Actually creates the thread.
+  void Start();
+
+  // Asks the code to stop and then waits until it has done so.
+  // This or TryJoin() (returning true) must be called exactly once for every
+  // instance.
+  void Join();
+
+  // If the code has already finished, returns true. Does not block waiting if
+  // it isn't.
+  // Join() must not be called on this instance if this returns true.
+  // This must return true or Join() must be called exactly once for every
+  // instance.
+  bool TryJoin();
+
+  // Asks the code to stop (in preparation for a Join()).
+  void RequestStop();
+
+  // Waits until the code has stopped. Does not ask it to do so.
+  void WaitUntilDone();
+
+ protected:
+  // Subclasses need to call this periodically if they are going to loop to
+  // check whether they have been asked to stop.
+  bool should_continue() {
+    return !should_terminate_.load();
+  }
+
+ private:
+  // Where subclasses actually do something.
+  //
+  // They should not block for long periods of time without checking
+  // should_continue().
+  virtual void Run() = 0;
+
+  static void *StaticRun(void *self);
+
+  pthread_t thread_;
+  bool started_;
+  bool joined_;
+  ::std::atomic_bool should_terminate_;
+
+  DISALLOW_COPY_AND_ASSIGN(Thread);
+};
+
+class FunctionThread : public Thread {
+ public:
+  FunctionThread(::std::function<void(FunctionThread *)> function)
+      : function_(function) {}
+
+  // Runs function in a new thread and waits for it to return.
+  static void RunInOtherThread(::std::function<void()> function) {
+    FunctionThread t([&function](FunctionThread *) { function(); });
+    t.Start();
+    t.Join();
+  }
+
+ private:
+  virtual void Run() override {
+    function_(this);
+  }
+
+  const ::std::function<void(FunctionThread *)> function_;
+};
+
+}  // namespace util
+}  // namespace aos
+
+#endif  // AOS_COMMON_UTIL_THREAD_H_
diff --git a/aos/common/util/trapezoid_profile.cc b/aos/common/util/trapezoid_profile.cc
new file mode 100644
index 0000000..cd8d02c
--- /dev/null
+++ b/aos/common/util/trapezoid_profile.cc
@@ -0,0 +1,130 @@
+#include "aos/common/util/trapezoid_profile.h"
+
+#include "aos/common/logging/logging.h"
+
+using ::Eigen::Matrix;
+
+namespace aos {
+namespace util {
+
+TrapezoidProfile::TrapezoidProfile(const time::Time &delta_time)
+    : maximum_acceleration_(0),
+      maximum_velocity_(0),
+      timestep_(delta_time) {
+  output_.setZero();
+}
+
+void TrapezoidProfile::UpdateVals(double acceleration,
+                                  double delta_time) {
+  output_(0) += output_(1) * delta_time +
+      0.5 * acceleration * delta_time * delta_time;
+  output_(1) += acceleration * delta_time;
+}
+
+const Matrix<double, 2, 1> &TrapezoidProfile::Update(
+    double goal_position,
+    double goal_velocity) {
+  CalculateTimes(goal_position - output_(0), goal_velocity);
+
+  double next_timestep = timestep_.ToSeconds();
+
+  if (acceleration_time_ > next_timestep) {
+    UpdateVals(acceleration_, next_timestep);
+  } else {
+    UpdateVals(acceleration_, acceleration_time_);
+
+    next_timestep -= acceleration_time_;
+    if (constant_time_ > next_timestep) {
+      UpdateVals(0, next_timestep);
+    } else {
+      UpdateVals(0, constant_time_);
+      next_timestep -= constant_time_;
+      if (deceleration_time_ > next_timestep) {
+        UpdateVals(deceleration_, next_timestep);
+      } else {
+        UpdateVals(deceleration_, deceleration_time_);
+        next_timestep -= deceleration_time_;
+        UpdateVals(0, next_timestep);
+      }
+    }
+  }
+
+  return output_;
+}
+
+void TrapezoidProfile::CalculateTimes(double distance_to_target,
+                                      double goal_velocity) {
+  if (distance_to_target == 0) {
+    // We're there. Stop everything.
+    // TODO(aschuh): Deal with velocity not right.
+    acceleration_time_ = 0;
+    acceleration_ = 0;
+    constant_time_ = 0;
+    deceleration_time_ = 0;
+    deceleration_ = 0;
+    return;
+  } else if (distance_to_target < 0) {
+    // Recurse with everything inverted.
+    output_(1) *= -1;
+    CalculateTimes(-distance_to_target,
+                   -goal_velocity);
+    output_(1) *= -1;
+    acceleration_ *= -1;
+    deceleration_ *= -1;
+    return;
+  }
+
+  constant_time_ = 0;
+  acceleration_ = maximum_acceleration_;
+  double maximum_acceleration_velocity = distance_to_target * 2 *
+      std::abs(acceleration_) + output_(1) * output_(1);
+  if (maximum_acceleration_velocity > 0) {
+    maximum_acceleration_velocity = sqrt(maximum_acceleration_velocity);
+  } else {
+    maximum_acceleration_velocity = -sqrt(-maximum_acceleration_velocity);
+  }
+
+  // Since we know what we'd have to do if we kept after it to decelerate, we
+  // know the sign of the acceleration.
+  if (maximum_acceleration_velocity > goal_velocity) {
+    deceleration_ = -maximum_acceleration_;
+  } else {
+    deceleration_ = maximum_acceleration_;
+  }
+
+  // We now know the top velocity we can get to.
+  double top_velocity = sqrt((distance_to_target +
+                              (output_(1) * output_(1)) /
+                              (2.0 * acceleration_) +
+                              (goal_velocity * goal_velocity) /
+                              (2.0 * deceleration_)) /
+                             (-1.0 / (2.0 * deceleration_) +
+                              1.0 / (2.0 * acceleration_)));
+
+  // If it can go too fast, we now know how long we get to accelerate for and
+  // how long to go at constant velocity.
+  if (top_velocity > maximum_velocity_) {
+    acceleration_time_ = (maximum_velocity_ - output_(1)) /
+        maximum_acceleration_;
+    constant_time_ = (distance_to_target +
+                      (goal_velocity * goal_velocity -
+                       maximum_velocity_ * maximum_velocity_) /
+                      (2.0 * maximum_acceleration_)) / maximum_velocity_;
+  } else {
+    acceleration_time_ = (top_velocity - output_(1)) /
+        acceleration_;
+  }
+
+  CHECK_GT(top_velocity, -maximum_velocity_);
+
+  if (output_(1) > maximum_velocity_) {
+    constant_time_ = 0;
+    acceleration_time_ = 0;
+  }
+
+  deceleration_time_ = (goal_velocity - top_velocity) /
+      deceleration_;
+}
+
+}  // namespace util
+}  // namespace aos
diff --git a/aos/common/util/trapezoid_profile.h b/aos/common/util/trapezoid_profile.h
new file mode 100644
index 0000000..fe63352
--- /dev/null
+++ b/aos/common/util/trapezoid_profile.h
@@ -0,0 +1,69 @@
+#ifndef AOS_COMMON_UTIL_TRAPEZOID_PROFILE_H_
+#define AOS_COMMON_UTIL_TRAPEZOID_PROFILE_H_
+
+#include "Eigen/Dense"
+
+#include "aos/common/macros.h"
+#include "aos/common/time.h"
+
+namespace aos {
+namespace util {
+
+// Calculates a trapezoidal motion profile (like for a control loop's goals).
+// Supports having the end speed and position changed in the middle.
+//
+// The only units assumption that this class makes is that the unit of time is
+// seconds.
+class TrapezoidProfile {
+ public:
+  // delta_time is how long between each call to Update.
+  TrapezoidProfile(const time::Time &delta_time);
+
+  // Updates the state.
+  const Eigen::Matrix<double, 2, 1> &Update(double goal_position,
+                                            double goal_velocity);
+  // Useful for preventing windup etc.
+  void MoveCurrentState(const Eigen::Matrix<double, 2, 1> &current) {
+    output_ = current;
+  }
+
+  // Useful for preventing windup etc.
+  void MoveGoal(double dx) { output_(0, 0) += dx; }
+
+  void SetGoal(double x) { output_(0, 0) = x; }
+
+  void set_maximum_acceleration(double maximum_acceleration) {
+    maximum_acceleration_ = maximum_acceleration;
+  }
+  void set_maximum_velocity(double maximum_velocity) {
+    maximum_velocity_ = maximum_velocity;
+  }
+
+ private:
+  // Basic kinematics to update output_, given that we are going to accelerate
+  // by acceleration over delta_time.
+  void UpdateVals(double acceleration, double delta_time);
+  // Calculates how long to go for each segment.
+  void CalculateTimes(double distance_to_target, double goal_velocity);
+  // output_ is where it should go at time_.
+  Eigen::Matrix<double, 2, 1> output_;
+
+  double acceleration_time_;
+  double acceleration_;
+  double constant_time_;
+  double deceleration_time_;
+  double deceleration_;
+
+  double maximum_acceleration_;
+  double maximum_velocity_;
+
+  // How long between calls to Update.
+  const time::Time timestep_;
+
+  DISALLOW_COPY_AND_ASSIGN(TrapezoidProfile);
+};
+
+}  // namespace util
+}  // namespace aos
+
+#endif  // AOS_COMMON_UTIL_TRAPEZOID_PROFILE_H_
diff --git a/aos/common/util/trapezoid_profile_test.cc b/aos/common/util/trapezoid_profile_test.cc
new file mode 100644
index 0000000..1dfeff3
--- /dev/null
+++ b/aos/common/util/trapezoid_profile_test.cc
@@ -0,0 +1,116 @@
+#include "gtest/gtest.h"
+
+#include "Eigen/Dense"
+
+#include "aos/common/util/trapezoid_profile.h"
+
+namespace aos {
+namespace util {
+namespace testing {
+
+class TrapezoidProfileTest : public ::testing::Test {
+ public:
+  EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
+
+ protected:
+  TrapezoidProfileTest() : profile_(delta_time) {
+    position_.setZero();
+    profile_.set_maximum_acceleration(0.75);
+    profile_.set_maximum_velocity(1.75);
+  }
+
+  // Runs an iteration.
+  void RunIteration(double goal_position,
+                    double goal_velocity) {
+    position_ = profile_.Update(goal_position,
+                                goal_velocity);
+  }
+
+  const Eigen::Matrix<double, 2, 1> &position() { return position_; }
+
+  TrapezoidProfile profile_;
+
+  ::testing::AssertionResult At(double position, double velocity) {
+    static const double kDoubleNear = 0.00001;
+    if (::std::abs(velocity - position_(1)) > kDoubleNear) {
+      return ::testing::AssertionFailure() << "velocity is " << position_(1) <<
+          " not " << velocity;
+    }
+    if (::std::abs(position - position_(0)) > kDoubleNear) {
+      return ::testing::AssertionFailure() << "position is " << position_(0) <<
+          " not " << position;
+    }
+    return ::testing::AssertionSuccess() << "at " << position <<
+        " moving at " << velocity;
+  }
+
+ private:
+  static const time::Time delta_time;
+
+  Eigen::Matrix<double, 2, 1> position_;
+};
+const time::Time TrapezoidProfileTest::delta_time = time::Time::InSeconds(0.01);
+
+TEST_F(TrapezoidProfileTest, ReachesGoal) {
+  for (int i = 0; i < 450; ++i) {
+    RunIteration(3, 0);
+  }
+  EXPECT_TRUE(At(3, 0));
+}
+
+// Tests that decresing the maximum velocity in the middle when it is already
+// moving faster than the new max is handled correctly.
+TEST_F(TrapezoidProfileTest, ContinousUnderVelChange) {
+  profile_.set_maximum_velocity(1.75);
+  RunIteration(12.0, 0);
+  double last_pos = position()(0);
+  double last_vel = 1.75;
+  for (int i = 0; i < 1600; ++i) {
+    if (i == 400) {
+      profile_.set_maximum_velocity(0.75);
+    }
+    RunIteration(12.0, 0);
+    if (i >= 400) {
+      EXPECT_TRUE(::std::abs(last_pos - position()(0)) <= 1.75 * 0.01);
+      EXPECT_NEAR(last_vel, ::std::abs(last_pos - position()(0)), 0.0001);
+    }
+    last_vel = ::std::abs(last_pos - position()(0));
+    last_pos = position()(0);
+  }
+  EXPECT_TRUE(At(12.0, 0));
+}
+
+// There is some somewhat tricky code for dealing with going backwards.
+TEST_F(TrapezoidProfileTest, Backwards) {
+  for (int i = 0; i < 400; ++i) {
+    RunIteration(-2, 0);
+  }
+  EXPECT_TRUE(At(-2, 0));
+}
+
+TEST_F(TrapezoidProfileTest, SwitchGoalInMiddle) {
+  for (int i = 0; i < 200; ++i) {
+    RunIteration(-2, 0);
+  }
+  EXPECT_FALSE(At(-2, 0));
+  for (int i = 0; i < 550; ++i) {
+    RunIteration(0, 0);
+  }
+  EXPECT_TRUE(At(0, 0));
+}
+
+// Checks to make sure that it hits top speed.
+TEST_F(TrapezoidProfileTest, TopSpeed) {
+  for (int i = 0; i < 200; ++i) {
+    RunIteration(4, 0);
+  }
+  EXPECT_NEAR(1.5, position()(1), 10e-5);
+  for (int i = 0; i < 2000; ++i) {
+    RunIteration(4, 0);
+  }
+  EXPECT_TRUE(At(4, 0));
+}
+
+}  // namespace testing
+}  // namespace util
+}  // namespace aos
diff --git a/aos/common/util/util.gyp b/aos/common/util/util.gyp
new file mode 100644
index 0000000..e9a37c9
--- /dev/null
+++ b/aos/common/util/util.gyp
@@ -0,0 +1,153 @@
+{
+  'targets': [
+    {
+      'target_name': 'run_command',
+      'type': 'static_library',
+      'sources': [
+        'run_command.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/build/aos.gyp:logging_interface',
+      ],
+    },
+    {
+      'target_name': 'run_command_test',
+      'type': 'executable',
+      'sources': [
+        'run_command_test.cc',
+      ],
+      'dependencies': [
+        'run_command',
+        '<(EXTERNALS):gtest',
+        '<(AOS)/build/aos.gyp:logging',
+        'thread',
+      ],
+    },
+    {
+      'target_name': 'death_test_log_implementation',
+      'type': 'static_library',
+      'sources': [
+        #'death_test_log_implementation',
+      ],
+      'dependencies': [
+        '<(AOS)/build/aos.gyp:logging',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/build/aos.gyp:logging',
+      ],
+    },
+    {
+      'target_name': 'inet_addr',
+      'type': 'static_library',
+      'sources': [
+        'inet_addr.cc',
+      ],
+    },
+    {
+      'target_name': 'phased_loop',
+      'type': 'static_library',
+      'sources': [
+        'phased_loop.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/common.gyp:time',
+      ],
+    },
+    {
+      'target_name': 'log_interval',
+      'type': 'static_library',
+      'sources': [
+        #'log_interval.h',
+      ],
+      'dependencies': [
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/build/aos.gyp:logging',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/build/aos.gyp:logging',
+      ],
+    },
+    {
+      'target_name': 'string_to_num',
+      'type': 'static_library',
+      'sources': [
+        #'string_to_num.h',
+      ],
+    },
+    {
+      'target_name': 'string_to_num_test',
+      'type': 'executable',
+      'sources': [
+        'string_to_num_test.cc',
+      ],
+      'dependencies': [
+        ':string_to_num',
+        '<(EXTERNALS):gtest',
+      ],
+    },
+    {
+      'target_name': 'thread',
+      'type': 'static_library',
+      'sources': [
+        'thread.cc',
+      ],
+    },
+    {
+      'target_name': 'trapezoid_profile',
+      'type': 'static_library',
+      'sources': [
+        'trapezoid_profile.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):eigen',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/build/aos.gyp:logging',
+      ],
+      'export_dependent_settings': [
+        '<(EXTERNALS):eigen',
+        '<(AOS)/common/common.gyp:time',
+      ],
+    },
+    {
+      'target_name': 'trapezoid_profile_test',
+      'type': 'executable',
+      'sources': [
+        'trapezoid_profile_test.cc',
+      ],
+      'dependencies': [
+        ':trapezoid_profile',
+        '<(EXTERNALS):gtest',
+      ],
+    },
+    {
+      'target_name': 'wrapping_counter',
+      'type': 'static_library',
+      'sources': [
+        'wrapping_counter.cc',
+      ],
+    },
+    {
+      'target_name': 'wrapping_counter_test',
+      'type': 'executable',
+      'sources': [
+        'wrapping_counter_test.cc',
+      ],
+      'dependencies': [
+        'wrapping_counter',
+        '<(EXTERNALS):gtest',
+      ],
+    },
+    {
+      'target_name': 'options_test',
+      'type': 'executable',
+      'sources': [
+        'options_test.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+      ],
+    },
+  ],
+}
diff --git a/aos/common/util/wrapping_counter.cc b/aos/common/util/wrapping_counter.cc
new file mode 100644
index 0000000..61f5047
--- /dev/null
+++ b/aos/common/util/wrapping_counter.cc
@@ -0,0 +1,19 @@
+#include "aos/common/util/wrapping_counter.h"
+
+namespace aos {
+namespace util {
+
+WrappingCounter::WrappingCounter(int32_t initial_count)
+    : count_(initial_count), last_count_(0) {}
+
+int32_t WrappingCounter::Update(uint8_t current) {
+  if (last_count_ > current) {
+    count_ += 0x100;
+  }
+  count_ = (count_ & 0xffffff00) | current;
+  last_count_ = current;
+  return count_;
+}
+
+}  // namespace util
+}  // namespace aos
diff --git a/aos/common/util/wrapping_counter.h b/aos/common/util/wrapping_counter.h
new file mode 100644
index 0000000..fbf3611
--- /dev/null
+++ b/aos/common/util/wrapping_counter.h
@@ -0,0 +1,34 @@
+#ifndef AOS_COMMON_UTIL_WRAPPING_COUNTER_H_
+#define AOS_COMMON_UTIL_WRAPPING_COUNTER_H_
+
+#include <stdint.h>
+
+namespace aos {
+namespace util {
+
+// Deals correctly with 1-byte counters which wrap.
+// This is only possible if the counter never wraps twice between Update calls.
+// It will also fail if the counter ever goes down (that will be interpreted as
+// +255 instead of -1, for example).
+class WrappingCounter {
+ public:
+  WrappingCounter(int32_t initial_count = 0);
+
+  // Updates the internal counter with a new raw value.
+  // Returns count() for convenience.
+  int32_t Update(uint8_t current);
+
+  // Resets the actual count to value.
+  void Reset(int32_t value = 0) { count_ = value; }
+
+  int32_t count() const { return count_; }
+
+ private:
+  int32_t count_;
+  uint8_t last_count_;
+};
+
+}  // namespace util
+}  // namespace aos
+
+#endif  // AOS_COMMON_UTIL_WRAPPING_COUNTER_H_
diff --git a/aos/common/util/wrapping_counter_test.cc b/aos/common/util/wrapping_counter_test.cc
new file mode 100644
index 0000000..e257fb0
--- /dev/null
+++ b/aos/common/util/wrapping_counter_test.cc
@@ -0,0 +1,58 @@
+#include "aos/common/util/wrapping_counter.h"
+
+#include <limits.h>
+
+#include "gtest/gtest.h"
+
+namespace aos {
+namespace util {
+namespace testing {
+
+TEST(WrappingCounterTest, Basic) {
+  WrappingCounter test_counter;
+  EXPECT_EQ(0, test_counter.count());
+  EXPECT_EQ(1, test_counter.Update(1));
+  EXPECT_EQ(1, test_counter.Update(1));
+  EXPECT_EQ(2, test_counter.Update(2));
+  EXPECT_EQ(7, test_counter.Update(7));
+  EXPECT_EQ(7, test_counter.count());
+  EXPECT_EQ(123, test_counter.Update(123));
+  EXPECT_EQ(123, test_counter.count());
+}
+
+TEST(WrappingCounterTest, Reset) {
+  WrappingCounter test_counter;
+  test_counter.Update(5);
+  test_counter.Reset();
+  EXPECT_EQ(0, test_counter.count());
+  test_counter.Reset(56);
+  EXPECT_EQ(56, test_counter.count());
+}
+
+namespace {
+void test_wrapping(int16_t start, int16_t step) {
+  WrappingCounter test_counter;
+  for (int16_t i = start; i < INT16_MAX - step; i += step) {
+    EXPECT_EQ(i, test_counter.Update(i & 0xFF));
+  }
+}
+}
+
+// This tests the basic wrapping functionality.
+TEST(WrappingCounterTest, ReasonableWrapping) {
+  test_wrapping(0, 13);
+  test_wrapping(0, 53);
+  test_wrapping(0, 64);
+  test_wrapping(0, 73);
+}
+
+// It would be reasonable for these to fail if the implementation changes.
+TEST(WrappingCounterTest, UnreasonableWrapping) {
+  test_wrapping(0, 128);
+  test_wrapping(0, 213);
+  test_wrapping(0, 255);
+}
+
+}  // namespace testing
+}  // namespace util
+}  // namespace aos
diff --git a/aos/config/10-net-eth0.rules b/aos/config/10-net-eth0.rules
new file mode 100644
index 0000000..0d8d807
--- /dev/null
+++ b/aos/config/10-net-eth0.rules
@@ -0,0 +1,6 @@
+# This is a file that will make any NIC eth0.
+# It prevents the persistent net rules generator from running because that ends
+# up naming the 1 NIC eth1 instead of when you move a disk between boxes.
+# Put it in /etc/udev/rules.d/ to use it.
+
+SUBSYSTEM=="net", ACTION=="add", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"
diff --git a/aos/config/aos.conf b/aos/config/aos.conf
new file mode 100644
index 0000000..bda250f
--- /dev/null
+++ b/aos/config/aos.conf
@@ -0,0 +1,6 @@
+# put this file in /etc/security/limits.d/ to make it work
+# you have to create a group named aos (groupadd aos) and then add anybody you want to it (vim /etc/group)
+# See limits.conf(5) for details.
+
+@aos hard memlock unlimited
+@aos hard rtprio 40
diff --git a/aos/config/configure-prime.txt b/aos/config/configure-prime.txt
new file mode 100644
index 0000000..1adaccd
--- /dev/null
+++ b/aos/config/configure-prime.txt
@@ -0,0 +1,79 @@
+This file contains notes on setting up a new BBB image.
+Doing it right requires knowing what you're doing as a Debian sysadmin, so the
+main goal of this file is to avoid forgetting anything.
+
+Daniel last updated this on 2014-01-20 with Debian Wheezy.
+
+1.  Install Debian stable.
+    Follow the instructions here:
+    http://blogs.bu.edu/mhirsch/2013/11/install-debian-7-to-emmc-internal-flash-drive-of-beaglebone-black/
+    Create a "driver" user.
+2.  Install aos.conf and starter.
+	  I just changed aos.conf to give driver permissions instead of the group.
+3.  Install and configure exim4.
+    TODO (daniel): We might not need this.
+    `apt-get install exim4-config`
+    `dpkg-reconfigure exim4-config` and select the option for making minimal
+    DNS queries (it also says some junk about modems).
+4.  Configure the network.
+    Edit /etc/network/interfaces to give it the right static IP address.
+	  Set up eth1 like the default eth0 in case the NIC gets assigned that (see
+    #8 below). That shouldn't be a problem any more, but it's probably good
+		to be on the safe side because it can be a pain to find a screen to fix
+		it otherwise.
+5.  Install stuff.
+    This includes the realtime kernel.
+    Note that at the time of this writing, you can't apt-get install the
+    realtime kernel packages directly on the beaglebone.
+    You must download them on your computer, copy them to the beaglebone,
+    and install them using dpkg -i.
+    <http://robotics.mvla.net/files/frc971/packages/>.
+    After you do this, you will still need to modify the zImage
+    symlink to point to the right kernel.
+    `rm /boot/zImage`
+    `ln -s /boot/vmlinuz-3.8.13.9-rt20+ /boot/zImage`
+    After you reboot, you should be running the rt kernel.
+    (Check it with `uname -r`.)
+    Besides the realtime kernel packages, you'll figure everything else out
+    as you start trying to run stuff.
+6.  Make SSH logins faster.
+    Add the line "UseDNS no" to /etc/ssh/sshd_config.
+7.  Make it so that the programming team can log in without passwords.
+    Everybody will have to run `ssh-copy-id -i ~/.ssh/id_rsa.pub BBB` (see
+    <http://www.debian-administration.org/articles/152> for details).
+8.  Make udev stop being annoying and naming NICs eth1.
+    udev wants to remember the ethernet NIC from each device and name the one
+    in a new BBB eth1, which breaks stuff. If that happens, removing
+    /etc/udev/rules.d/70-persistent-net.rules will make it autogenerate a
+    new one and fix it.
+    To prevent this problem from happening in the first place, follow the
+    directions in 10-net-eth0.rules.
+9.  Set up /etc/fstab sanely.
+    Open /etc/fstab on the bbb and remove the last two lines, which the
+    comments indicate mount both partitions on the uSD card.
+	Because the uSD card shows up as /dev/mmcblk0 and pushes the internal emmc
+	to /dev/mmcblk1 when it's plugged in, using those names for the two of them
+	doesn't work very well. Instead, we use /dev/disk/by-path.
+	Add "/dev/disk/by-path/platform-mmc.14-part1 /boot/uboot msdos defaults 0 2"
+	to mount the uboot partition.
+    Also add
+	"/dev/disk/by-path/platform-mmc.5-part1 /home/driver/tmp/robot_logs ext4 defaults,noatime,data=writeback 0 0"
+	to mount the uSD card in the right place for the logs to go to it.
+10. Set up logging.
+    Fairly straightforward here. We want it to log to the uSD card, so:
+    `mkdir ~/tmp`
+    `mkdir /media/driver/sdcard/robot_logs`
+    `ln -s /media/driver/sdcard/robot_logs ~/tmp/robot_logs`
+11. Set the correct date.
+    `date` to check if date is correct.
+    `date -s <date string>` to set it if it isn't.
+12. Fix the locale setup for SSHing in.
+    `dpkg-reconfigure locales`, leave it with "en_US.UTF-8" only being
+	enabled, and then select "None" instead of that for the default in
+	the second screen.
+30. Download the code!
+50. Clone the image to the rest of the BBBs.
+    Boot up from a uSD card.
+    `dd if=/dev/mmcblk1 | gzip -c > BBB.img.gz`
+    You can then copy this image to your computer.
+    Use this image to flash other uSD cards and/or BBBs.
diff --git a/aos/config/robotCommand b/aos/config/robotCommand
new file mode 100755
index 0000000..7b726a7
--- /dev/null
+++ b/aos/config/robotCommand
@@ -0,0 +1 @@
+/home/admin/robot_code/starter.sh
diff --git a/aos/config/setup_rt_caps.sh b/aos/config/setup_rt_caps.sh
new file mode 100755
index 0000000..1ba4f65
--- /dev/null
+++ b/aos/config/setup_rt_caps.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+# Sets capabilities on a binary so it can run as realtime code as a user who
+# doesn't have those rlimits or some other reason they can.
+# Has to be run as root.
+
+setcap 'CAP_IPC_LOCK+pie CAP_SYS_NICE+pie' $0
+
diff --git a/aos/externals/allwpilib/README b/aos/externals/allwpilib/README
new file mode 100644
index 0000000..90595b6
--- /dev/null
+++ b/aos/externals/allwpilib/README
@@ -0,0 +1,3 @@
+This is our version of WPILib. We copy the wpilibc/ and hal/ folders from
+our customized version periodically. The commit messages all include the commit
+which is being copied in and the corresponding FPGA image version.
diff --git a/aos/externals/allwpilib/hal/CMakeLists.txt b/aos/externals/allwpilib/hal/CMakeLists.txt
new file mode 100644
index 0000000..5ad2e64
--- /dev/null
+++ b/aos/externals/allwpilib/hal/CMakeLists.txt
@@ -0,0 +1,17 @@
+cmake_minimum_required(VERSION 2.8)
+project(HAL)
+
+file(GLOB_RECURSE SRC_FILES lib/Athena/*.cpp)
+include_directories(lib/Athena lib/Athena/FRC_FPGA_ChipObject include)
+add_library(HALAthena STATIC ${SRC_FILES})
+target_link_libraries(HALAthena ${NI_LIBS})
+INSTALL(TARGETS HALAthena ARCHIVE DESTINATION lib COMPONENT lib)
+INSTALL(FILES ${NI_LIBS} ${WPI_LD_LIBS} DESTINATION lib COMPONENT ni_lib)
+INSTALL(DIRECTORY include DESTINATION ${CMAKE_INSTALL_PREFIX} COMPONENT headers)
+
+add_library(HALAthena_shared SHARED ${SRC_FILES})
+target_link_libraries(HALAthena_shared ${NI_LIBS})
+INSTALL(TARGETS HALAthena_shared LIBRARY DESTINATION lib COMPONENT lib)
+# lib/ c m gcc_s ld-linux
+# usr/lib 
+# FRC_NetworkCommunication FRC_FPGA_ChipObject RoboRIO_FRC_ChipObject
diff --git a/aos/externals/allwpilib/hal/README.org b/aos/externals/allwpilib/hal/README.org
new file mode 100644
index 0000000..9eb132a
--- /dev/null
+++ b/aos/externals/allwpilib/hal/README.org
@@ -0,0 +1,94 @@
+
+* Purpose
+The HAL is a hardware abstraction layer that provides a uniform
+interface that can be used to access a number of primarily I/O
+features in the underlying platform. The features include:
+- Analog input, accumulation and triggers
+- PWM, Relay and Solenoid output
+- Digital input and output
+- I2C and SPI communication
+- Encoders and counters
+- Interrupts and Notifiers
+
+The initial goal is to allow a higher level like WPILib to support
+both the CRIO and the upcoming Athena platform only by changing which
+version of the HAL it's running on.
+
+* Editing
+You can always use any text editor and then build with Maven. There
+are also eclipse project files so that it can be edited in the same
+eclipse environment that teams develop with. For the AthenaXX, this
+can be found in the =root= directory of this project. It imports as an
+FRC Robot C++ Eclipse project. The Windriver project can be imported
+from the =src= directory.
+
+* Building with Maven
+There are multiple build targets that the HAL supports. Instructions
+for setting up the environment and building each of these is described
+below. Current targets are listed below:
+- All: All of the following targets.
+- include: The header files for the HAL.
+- Azalea: CRIO C++ build.
+- AthenaXX: Athena Dos Equis C++ build.
+- AthenaXXJava: Athena Dos Equis Java build with auto-generated JNA
+  wrappers.
+
+Output from each build target is placed in the directory
+=target/<target-name>=. So, the Azalea output is placed in
+=target/Azalea=.
+
+** All
+Note: Windows only due to the Windriver requirement.
+1. Ensure that =C:\WindRiver\gnu\3.4.4-vxworks-6.3\x86-win32\bin= is
+   on the system path so that =ccppc= and =arppc= can be accessed.
+2. Set the environment variable =WIND_BASE= to =C:\WindRiver\vxworks-6.3=.
+3. Ensure that
+   =$HOME/wpilib/toolchains/arm-none-linux-gnueabi-4.4.1/bin/= is on
+   the system path so that =arm-none-linux-gnueabi-g++= and
+   =arm-none-linux-gnueabi-ar= can be accessed.
+4. Checkout and install the NI-Libraries from Github:
+   [[https://github.com/first/NI-Libraries]].
+5. Run the following maven command:
+   =mvn clean install=
+6. Success
+
+** include
+1. =cd= into the include directory: =cd include=
+2. Run the following maven command:
+   =mvn clean install=
+3. Success
+
+** Azalea
+Note: Windows only.
+1. Ensure that =C:\WindRiver\gnu\3.4.4-vxworks-6.3\x86-win32\bin= is
+   on the system path so that =ccppc= and =arppc= can be accessed.
+2. Set the environment variable =WIND_BASE= to =C:\WindRiver\vxworks-6.3=.
+3. =cd= into the AthenaXX directory: =cd AthenaXX=
+4. =cd= into the Azalea directory:  =cd Azalea=
+5. Run the following maven command:
+   =mvn clean install=
+6. Success
+
+** AthenaXX
+1. Ensure that
+   =$HOME/wpilib/toolchains/arm-none-linux-gnueabi-4.4.1/bin/= is on
+   the system path so that =arm-none-linux-gnueabi-g++= and
+   =arm-none-linux-gnueabi-ar= can be accessed.
+2. Install the include target.
+3. =cd= into the AthenaXX directory: =cd AthenaXX=
+4. Run the following maven command:
+   =mvn clean install=
+5. Success
+
+** AthenaXXJava
+1. Ensure that
+   =$HOME/wpilib/toolchains/arm-none-linux-gnueabi-4.4.1/bin/= is on
+   the system path so that =arm-none-linux-gnueabi-g++= and
+   =arm-none-linux-gnueabi-ar= can be accessed.
+2. Checkout and install the NI-Libraries from Github:
+   [[https://github.com/first/NI-Libraries]].
+3. Install the include target.
+4. =cd= into the AthenaXXJava directory: =cd AthenaXXJava=
+5. Run the following maven command:
+   =mvn clean install=
+6. Success
diff --git a/aos/externals/allwpilib/hal/include/HAL/Accelerometer.hpp b/aos/externals/allwpilib/hal/include/HAL/Accelerometer.hpp
new file mode 100644
index 0000000..103fb2a
--- /dev/null
+++ b/aos/externals/allwpilib/hal/include/HAL/Accelerometer.hpp
@@ -0,0 +1,15 @@
+#pragma once
+
+enum AccelerometerRange {
+	kRange_2G = 0,
+	kRange_4G = 1,
+	kRange_8G = 2,
+};
+
+extern "C" {
+	void setAccelerometerActive(bool);
+	void setAccelerometerRange(AccelerometerRange);
+	double getAccelerometerX();
+	double getAccelerometerY();
+	double getAccelerometerZ();
+}
diff --git a/aos/externals/allwpilib/hal/include/HAL/Analog.hpp b/aos/externals/allwpilib/hal/include/HAL/Analog.hpp
new file mode 100644
index 0000000..981aa9e
--- /dev/null
+++ b/aos/externals/allwpilib/hal/include/HAL/Analog.hpp
@@ -0,0 +1,80 @@
+#pragma once
+
+#ifdef __vxworks
+#include <vxWorks.h>
+#else
+#include <stdint.h>
+#endif
+
+enum AnalogTriggerType
+{
+	kInWindow = 0,
+	kState = 1,
+	kRisingPulse = 2,
+	kFallingPulse = 3
+};
+
+extern "C"
+{
+	// Analog output functions
+	void* initializeAnalogOutputPort(void* port_pointer, int32_t *status);
+	void setAnalogOutput(void* analog_port_pointer, double voltage, int32_t *status);
+	double getAnalogOutput(void* analog_port_pointer, int32_t *status);
+	bool checkAnalogOutputChannel(uint32_t pin);
+
+	// Analog input functions
+	void* initializeAnalogInputPort(void* port_pointer, int32_t *status);
+	bool checkAnalogModule(uint8_t module);
+	bool checkAnalogInputChannel(uint32_t pin);
+
+	void setAnalogSampleRate(double samplesPerSecond, int32_t *status);
+	float getAnalogSampleRate(int32_t *status);
+	void setAnalogAverageBits(void* analog_port_pointer, uint32_t bits, int32_t *status);
+	uint32_t getAnalogAverageBits(void* analog_port_pointer, int32_t *status);
+	void setAnalogOversampleBits(void* analog_port_pointer, uint32_t bits, int32_t *status);
+	uint32_t getAnalogOversampleBits(void* analog_port_pointer, int32_t *status);
+	int16_t getAnalogValue(void* analog_port_pointer, int32_t *status);
+	int32_t getAnalogAverageValue(void* analog_port_pointer, int32_t *status);
+	int32_t getAnalogVoltsToValue(void* analog_port_pointer, double voltage, int32_t *status);
+	float getAnalogVoltage(void* analog_port_pointer, int32_t *status);
+	float getAnalogAverageVoltage(void* analog_port_pointer, int32_t *status);
+	uint32_t getAnalogLSBWeight(void* analog_port_pointer, int32_t *status);
+	int32_t getAnalogOffset(void* analog_port_pointer, int32_t *status);
+
+	bool isAccumulatorChannel(void* analog_port_pointer, int32_t *status);
+	void initAccumulator(void* analog_port_pointer, int32_t *status);
+	void resetAccumulator(void* analog_port_pointer, int32_t *status);
+	void setAccumulatorCenter(void* analog_port_pointer, int32_t center, int32_t *status);
+	void setAccumulatorDeadband(void* analog_port_pointer, int32_t deadband, int32_t *status);
+	int64_t getAccumulatorValue(void* analog_port_pointer, int32_t *status);
+	uint32_t getAccumulatorCount(void* analog_port_pointer, int32_t *status);
+	void getAccumulatorOutput(void* analog_port_pointer, int64_t *value, uint32_t *count,
+			int32_t *status);
+
+	void* initializeAnalogTrigger(void* port_pointer, uint32_t *index, int32_t *status);
+	void cleanAnalogTrigger(void* analog_trigger_pointer, int32_t *status);
+	void setAnalogTriggerLimitsRaw(void* analog_trigger_pointer, int32_t lower, int32_t upper,
+			int32_t *status);
+	void setAnalogTriggerLimitsVoltage(void* analog_trigger_pointer, double lower, double upper,
+			int32_t *status);
+	void setAnalogTriggerAveraged(void* analog_trigger_pointer, bool useAveragedValue,
+			int32_t *status);
+	void setAnalogTriggerFiltered(void* analog_trigger_pointer, bool useFilteredValue,
+			int32_t *status);
+	bool getAnalogTriggerInWindow(void* analog_trigger_pointer, int32_t *status);
+	bool getAnalogTriggerTriggerState(void* analog_trigger_pointer, int32_t *status);
+	bool getAnalogTriggerOutput(void* analog_trigger_pointer, AnalogTriggerType type,
+			int32_t *status);
+
+	//// Float JNA Hack
+	// Float
+	int getAnalogSampleRateIntHack(int32_t *status);
+	int getAnalogVoltageIntHack(void* analog_port_pointer, int32_t *status);
+	int getAnalogAverageVoltageIntHack(void* analog_port_pointer, int32_t *status);
+
+	// Doubles
+	void setAnalogSampleRateIntHack(int samplesPerSecond, int32_t *status);
+	int32_t getAnalogVoltsToValueIntHack(void* analog_port_pointer, int voltage, int32_t *status);
+	void setAnalogTriggerLimitsVoltageIntHack(void* analog_trigger_pointer, int lower, int upper,
+			int32_t *status);
+}
diff --git a/aos/externals/allwpilib/hal/include/HAL/CAN.hpp b/aos/externals/allwpilib/hal/include/HAL/CAN.hpp
new file mode 100644
index 0000000..80b589c
--- /dev/null
+++ b/aos/externals/allwpilib/hal/include/HAL/CAN.hpp
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <stdint.h>
+#include "NetworkCommunication/CANSessionMux.h"
+
+void canTxSend(uint32_t arbID, uint8_t length, int32_t period = CAN_SEND_PERIOD_NO_REPEAT);
+
+void canTxPackInt8 (uint32_t arbID, uint8_t offset, uint8_t  value);
+void canTxPackInt16(uint32_t arbID, uint8_t offset, uint16_t value);
+void canTxPackInt32(uint32_t arbID, uint8_t offset, uint32_t value);
+void canTxPackFXP16(uint32_t arbID, uint8_t offset, double   value);
+void canTxPackFXP32(uint32_t arbID, uint8_t offset, double   value);
+
+uint8_t  canTxUnpackInt8 (uint32_t arbID, uint8_t offset);
+uint32_t canTxUnpackInt32(uint32_t arbID, uint8_t offset);
+uint16_t canTxUnpackInt16(uint32_t arbID, uint8_t offset);
+double   canTxUnpackFXP16(uint32_t arbID, uint8_t offset);
+double   canTxUnpackFXP32(uint32_t arbID, uint8_t offset);
+
+bool canRxReceive(uint32_t arbID);
+
+uint8_t  canRxUnpackInt8 (uint32_t arbID, uint8_t offset);
+uint16_t canRxUnpackInt16(uint32_t arbID, uint8_t offset);
+uint32_t canRxUnpackInt32(uint32_t arbID, uint8_t offset);
+double   canRxUnpackFXP16(uint32_t arbID, uint8_t offset);
+double   canRxUnpackFXP32(uint32_t arbID, uint8_t offset);
diff --git a/aos/externals/allwpilib/hal/include/HAL/Compressor.hpp b/aos/externals/allwpilib/hal/include/HAL/Compressor.hpp
new file mode 100644
index 0000000..5c222eb
--- /dev/null
+++ b/aos/externals/allwpilib/hal/include/HAL/Compressor.hpp
@@ -0,0 +1,37 @@
+/**
+ * Compressor.h
+ * Methods for interacting with a compressor with the CAN PCM device
+ */
+
+#ifdef __vxworks
+#include <vxWorks.h>
+#else
+#include <stdint.h>
+#endif
+
+#ifndef __HAL_COMPRESSOR_H__
+#define __HAL_COMPRESSOR_H__
+
+extern "C" {
+	void *initializeCompressor(uint8_t module);
+	bool checkCompressorModule(uint8_t module);
+	
+	bool getCompressor(void *pcm_pointer, int32_t *status);
+	
+	void setClosedLoopControl(void *pcm_pointer, bool value, int32_t *status);
+	bool getClosedLoopControl(void *pcm_pointer, int32_t *status);
+	
+	bool getPressureSwitch(void *pcm_pointer, int32_t *status);
+	float getCompressorCurrent(void *pcm_pointer, int32_t *status);
+
+	bool getCompressorCurrentTooHighFault(void *pcm_pointer, int32_t *status);
+	bool getCompressorCurrentTooHighStickyFault(void *pcm_pointer, int32_t *status);
+	bool getCompressorShortedStickyFault(void *pcm_pointer, int32_t *status);
+	bool getCompressorShortedFault(void *pcm_pointer, int32_t *status);
+	bool getCompressorNotConnectedStickyFault(void *pcm_pointer, int32_t *status);
+	bool getCompressorNotConnectedFault(void *pcm_pointer, int32_t *status);
+	void clearAllPCMStickyFaults(void *pcm_pointer, int32_t *status);
+}
+
+#endif
+
diff --git a/aos/externals/allwpilib/hal/include/HAL/Digital.hpp b/aos/externals/allwpilib/hal/include/HAL/Digital.hpp
new file mode 100644
index 0000000..4d77976
--- /dev/null
+++ b/aos/externals/allwpilib/hal/include/HAL/Digital.hpp
@@ -0,0 +1,124 @@
+#pragma once
+#ifdef __vxworks
+#include <vxWorks.h>
+#else
+#include <stdint.h>
+#endif
+#include "HAL/cpp/Synchronized.hpp"
+
+enum Mode
+{
+	kTwoPulse = 0,
+	kSemiperiod = 1,
+	kPulseLength = 2,
+	kExternalDirection = 3
+};
+
+extern "C"
+{
+	void* initializeDigitalPort(void* port_pointer, int32_t *status);
+	bool checkPWMChannel(void* digital_port_pointer);
+	bool checkRelayChannel(void* digital_port_pointer);
+
+	void setPWM(void* digital_port_pointer, unsigned short value, int32_t *status);
+	bool allocatePWMChannel(void* digital_port_pointer, int32_t *status);
+	void freePWMChannel(void* digital_port_pointer, int32_t *status);
+	unsigned short getPWM(void* digital_port_pointer, int32_t *status);
+	void latchPWMZero(void* digital_port_pointer, int32_t *status);
+	void setPWMPeriodScale(void* digital_port_pointer, uint32_t squelchMask, int32_t *status);
+	void* allocatePWM(int32_t *status);
+	void freePWM(void* pwmGenerator, int32_t *status);
+	void setPWMRate(double rate, int32_t *status);
+	void setPWMDutyCycle(void* pwmGenerator, double dutyCycle, int32_t *status);
+	void setPWMOutputChannel(void* pwmGenerator, uint32_t pin, int32_t *status);
+
+	void setRelayForward(void* digital_port_pointer, bool on, int32_t *status);
+	void setRelayReverse(void* digital_port_pointer, bool on, int32_t *status);
+	bool getRelayForward(void* digital_port_pointer, int32_t *status);
+	bool getRelayReverse(void* digital_port_pointer, int32_t *status);
+
+	bool allocateDIO(void* digital_port_pointer, bool input, int32_t *status);
+	void freeDIO(void* digital_port_pointer, int32_t *status);
+	void setDIO(void* digital_port_pointer, short value, int32_t *status);
+	bool getDIO(void* digital_port_pointer, int32_t *status);
+	bool getDIODirection(void* digital_port_pointer, int32_t *status);
+	void pulse(void* digital_port_pointer, double pulseLength, int32_t *status);
+	bool isPulsing(void* digital_port_pointer, int32_t *status);
+	bool isAnyPulsing(int32_t *status);
+
+	void setFilterSelect(void* digital_port_pointer, int filter_index,
+	                   int32_t* status);
+	int getFilterSelect(void* digital_port_pointer, int32_t* status);
+
+	void setFilterPeriod(int filter_index, uint32_t value, int32_t *status);
+	uint32_t getFilterPeriod(int filter_index, int32_t *status);
+
+	void* initializeCounter(Mode mode, uint32_t *index, int32_t *status);
+	void freeCounter(void* counter_pointer, int32_t *status);
+	void setCounterAverageSize(void* counter_pointer, int32_t size, int32_t *status);
+	void setCounterUpSource(void* counter_pointer, uint32_t pin, bool analogTrigger, int32_t *status);
+	void setCounterUpSourceEdge(void* counter_pointer, bool risingEdge, bool fallingEdge,
+			int32_t *status);
+	void clearCounterUpSource(void* counter_pointer, int32_t *status);
+	void setCounterDownSource(void* counter_pointer, uint32_t pin, bool analogTrigger, int32_t *status);
+	void setCounterDownSourceEdge(void* counter_pointer, bool risingEdge, bool fallingEdge,
+			int32_t *status);
+	void clearCounterDownSource(void* counter_pointer, int32_t *status);
+	void setCounterUpDownMode(void* counter_pointer, int32_t *status);
+	void setCounterExternalDirectionMode(void* counter_pointer, int32_t *status);
+	void setCounterSemiPeriodMode(void* counter_pointer, bool highSemiPeriod, int32_t *status);
+	void setCounterPulseLengthMode(void* counter_pointer, double threshold, int32_t *status);
+	int32_t getCounterSamplesToAverage(void* counter_pointer, int32_t *status);
+	void setCounterSamplesToAverage(void* counter_pointer, int samplesToAverage, int32_t *status);
+	void resetCounter(void* counter_pointer, int32_t *status);
+	int32_t getCounter(void* counter_pointer, int32_t *status);
+	double getCounterPeriod(void* counter_pointer, int32_t *status);
+	void setCounterMaxPeriod(void* counter_pointer, double maxPeriod, int32_t *status);
+	void setCounterUpdateWhenEmpty(void* counter_pointer, bool enabled, int32_t *status);
+	bool getCounterStopped(void* counter_pointer, int32_t *status);
+	bool getCounterDirection(void* counter_pointer, int32_t *status);
+	void setCounterReverseDirection(void* counter_pointer, bool reverseDirection, int32_t *status);
+
+	void* initializeEncoder(uint8_t port_a_module, uint32_t port_a_pin, bool port_a_analog_trigger,
+			uint8_t port_b_module, uint32_t port_b_pin, bool port_b_analog_trigger,
+			bool reverseDirection, int32_t *index, int32_t *status); // TODO: fix routing
+	void freeEncoder(void* encoder_pointer, int32_t *status);
+	void resetEncoder(void* encoder_pointer, int32_t *status);
+	int32_t getEncoder(void* encoder_pointer, int32_t *status); // Raw value
+	double getEncoderPeriod(void* encoder_pointer, int32_t *status);
+	void setEncoderMaxPeriod(void* encoder_pointer, double maxPeriod, int32_t *status);
+	bool getEncoderStopped(void* encoder_pointer, int32_t *status);
+	bool getEncoderDirection(void* encoder_pointer, int32_t *status);
+	void setEncoderReverseDirection(void* encoder_pointer, bool reverseDirection, int32_t *status);
+	void setEncoderSamplesToAverage(void* encoder_pointer, uint32_t samplesToAverage,
+			int32_t *status);
+	uint32_t getEncoderSamplesToAverage(void* encoder_pointer, int32_t *status);
+	void setEncoderIndexSource(void *encoder_pointer, uint32_t pin, bool analogTrigger, bool activeHigh,
+			bool edgeSensitive, int32_t *status);
+
+	uint16_t getLoopTiming(int32_t *status);
+
+	void spiInitialize(uint8_t port, int32_t *status);
+	int32_t spiTransaction(uint8_t port, uint8_t *dataToSend, uint8_t *dataReceived, uint8_t size);
+	int32_t spiWrite(uint8_t port, uint8_t* dataToSend, uint8_t sendSize);
+	int32_t spiRead(uint8_t port, uint8_t *buffer, uint8_t count);
+	void spiClose(uint8_t port);
+	void spiSetSpeed(uint8_t port, uint32_t speed);
+	void spiSetBitsPerWord(uint8_t port, uint8_t bpw);
+	void spiSetOpts(uint8_t port, int msb_first, int sample_on_trailing, int clk_idle_high);
+	void spiSetChipSelectActiveHigh(uint8_t port, int32_t *status);
+	void spiSetChipSelectActiveLow(uint8_t port, int32_t *status);
+	int32_t spiGetHandle(uint8_t port);
+	void spiSetHandle(uint8_t port, int32_t handle);
+
+	void i2CInitialize(uint8_t port, int32_t *status);
+	int32_t i2CTransaction(uint8_t port, uint8_t deviceAddress, uint8_t *dataToSend, uint8_t sendSize, uint8_t *dataReceived, uint8_t receiveSize);
+	int32_t i2CWrite(uint8_t port, uint8_t deviceAddress, uint8_t *dataToSend, uint8_t sendSize);
+	int32_t i2CRead(uint8_t port, uint8_t deviceAddress, uint8_t *buffer, uint8_t count);
+	void i2CClose(uint8_t port);
+
+	//// Float JNA Hack
+	// double
+	void setPWMRateIntHack(int rate, int32_t *status);
+	void setPWMDutyCycleIntHack(void* pwmGenerator, int32_t dutyCycle, int32_t *status);
+}
diff --git a/aos/externals/allwpilib/hal/include/HAL/Errors.hpp b/aos/externals/allwpilib/hal/include/HAL/Errors.hpp
new file mode 100644
index 0000000..a64c3c4
--- /dev/null
+++ b/aos/externals/allwpilib/hal/include/HAL/Errors.hpp
@@ -0,0 +1,65 @@
+#pragma once
+
+#define CTR_RxTimeout_MESSAGE "CTRE CAN Recieve Timeout"
+#define CTR_TxTimeout_MESSAGE "CTRE CAN Transmit Timeout"
+#define CTR_InvalidParamValue_MESSAGE "CTRE CAN Invalid Parameter"
+#define CTR_UnexpectedArbId_MESSAGE "CTRE Unexpected Arbitration ID (CAN Node ID)"
+#define CTR_TxFailed_MESSAGE "CTRE CAN Transmit Error"
+#define CTR_SigNotUpdated_MESSAGE "CTRE CAN Signal Not Updated"
+
+#define NiFpga_Status_FifoTimeout_MESSAGE "NIFPGA: FIFO timeout error"
+#define NiFpga_Status_TransferAborted_MESSAGE "NIFPGA: Transfer aborted error"
+#define NiFpga_Status_MemoryFull_MESSAGE "NIFPGA: Memory Allocation failed, memory full"
+#define NiFpga_Status_SoftwareFault_MESSAGE "NIFPGA: Unexepected software error"
+#define NiFpga_Status_InvalidParameter_MESSAGE "NIFPGA: Invalid Parameter"
+#define NiFpga_Status_ResourceNotFound_MESSAGE "NIFPGA: Resource not found"
+#define NiFpga_Status_ResourceNotInitialized_MESSAGE "NIFPGA: Resource not initialized"
+#define NiFpga_Status_HardwareFault_MESSAGE "NIFPGA: Hardware Fault"
+#define NiFpga_Status_IrqTimeout_MESSAGE "NIFPGA: Interrupt timeout"
+#define NiFpga_Status_VersionMismatch_MESSAGE "NIFPGA: Version Mismatch"
+
+#define ERR_CANSessionMux_InvalidBuffer_MESSAGE "CAN: Invalid Buffer"
+#define ERR_CANSessionMux_MessageNotFound_MESSAGE "CAN: Message not found"
+#define WARN_CANSessionMux_NoToken_MESSAGE "CAN: No token"
+#define ERR_CANSessionMux_NotAllowed_MESSAGE "CAN: Not allowed"
+#define ERR_CANSessionMux_NotInitialized_MESSAGE "CAN: Not initialized" 
+
+#define SAMPLE_RATE_TOO_HIGH 1001
+#define SAMPLE_RATE_TOO_HIGH_MESSAGE "HAL: Analog module sample rate is too high"
+#define VOLTAGE_OUT_OF_RANGE 1002
+#define VOLTAGE_OUT_OF_RANGE_MESSAGE "HAL: Voltage to convert to raw value is out of range [0; 5]"
+#define LOOP_TIMING_ERROR 1004
+#define LOOP_TIMING_ERROR_MESSAGE "HAL: Digital module loop timing is not the expected value"
+#define SPI_WRITE_NO_MOSI 1012
+#define SPI_WRITE_NO_MOSI_MESSAGE "HAL: Cannot write to SPI port with no MOSI output"
+#define SPI_READ_NO_MISO 1013
+#define SPI_READ_NO_MISO_MESSAGE "HAL: Cannot read from SPI port with no MISO input"
+#define SPI_READ_NO_DATA 1014
+#define SPI_READ_NO_DATA_MESSAGE "HAL: No data available to read from SPI"
+#define INCOMPATIBLE_STATE 1015
+#define INCOMPATIBLE_STATE_MESSAGE "HAL: Incompatible State: The operation cannot be completed"
+#define NO_AVAILABLE_RESOURCES -1004
+#define NO_AVAILABLE_RESOURCES_MESSAGE "HAL: No available resources to allocate"
+#define NULL_PARAMETER -1005
+#define NULL_PARAMETER_MESSAGE "HAL: A pointer parameter to a method is NULL"
+#define ANALOG_TRIGGER_LIMIT_ORDER_ERROR -1010
+#define ANALOG_TRIGGER_LIMIT_ORDER_ERROR_MESSAGE "HAL: AnalogTrigger limits error.  Lower limit > Upper Limit"
+#define ANALOG_TRIGGER_PULSE_OUTPUT_ERROR -1011
+#define ANALOG_TRIGGER_PULSE_OUTPUT_ERROR_MESSAGE "HAL: Attempted to read AnalogTrigger pulse output."
+#define PARAMETER_OUT_OF_RANGE -1028
+#define PARAMETER_OUT_OF_RANGE_MESSAGE "HAL: A parameter is out of range."
+#define RESOURCE_IS_ALLOCATED -1029
+#define RESOURCE_IS_ALLOCATED_MESSAGE "HAL: Resource already allocated"
+
+#define VI_ERROR_SYSTEM_ERROR_MESSAGE "HAL - VISA: System Error";
+#define VI_ERROR_INV_OBJECT_MESSAGE "HAL - VISA: Invalid Object"
+#define VI_ERROR_RSRC_LOCKED_MESSAGE "HAL - VISA: Resource Locked"
+#define VI_ERROR_RSRC_NFOUND_MESSAGE "HAL - VISA: Resource Not Found"
+#define VI_ERROR_INV_RSRC_NAME_MESSAGE "HAL - VISA: Invalid Resource Name"  
+#define VI_ERROR_QUEUE_OVERFLOW_MESSAGE "HAL - VISA: Queue Overflow" 
+#define VI_ERROR_IO_MESSAGE "HAL - VISA: General IO Error"
+#define VI_ERROR_ASRL_PARITY_MESSAGE "HAL - VISA: Parity Error"
+#define VI_ERROR_ASRL_FRAMING_MESSAGE "HAL - VISA: Framing Error"
+#define VI_ERROR_ASRL_OVERRUN_MESSAGE "HAL - VISA: Buffer Overrun Error" 
+#define VI_ERROR_RSRC_BUSY_MESSAGE "HAL - VISA: Resource Busy"
+#define VI_ERROR_INV_PARAMETER_MESSAGE "HAL - VISA: Invalid Parameter" 
diff --git a/aos/externals/allwpilib/hal/include/HAL/HAL.hpp b/aos/externals/allwpilib/hal/include/HAL/HAL.hpp
new file mode 100644
index 0000000..9c6acb7
--- /dev/null
+++ b/aos/externals/allwpilib/hal/include/HAL/HAL.hpp
@@ -0,0 +1,257 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2013. All Rights Reserved.  			      */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#ifdef __vxworks
+#include <vxWorks.h>
+#else
+#include <stdint.h>
+#endif
+#include <cmath>
+
+#include "Accelerometer.hpp"
+#include "Analog.hpp"
+#include "Compressor.hpp"
+#include "Digital.hpp"
+#include "Solenoid.hpp"
+#include "Notifier.hpp"
+#include "Interrupts.hpp"
+#include "Errors.hpp"
+#include "PDP.hpp"
+#include "Power.hpp"
+
+#include "Utilities.hpp"
+#include "Semaphore.hpp"
+#include "Task.hpp"
+
+#define HAL_IO_CONFIG_DATA_SIZE 32
+#define HAL_SYS_STATUS_DATA_SIZE 44
+#define HAL_USER_STATUS_DATA_SIZE (984 - HAL_IO_CONFIG_DATA_SIZE - HAL_SYS_STATUS_DATA_SIZE)
+
+#define HALFRC_NetworkCommunication_DynamicType_DSEnhancedIO_Input 17
+#define HALFRC_NetworkCommunication_DynamicType_DSEnhancedIO_Output 18
+#define HALFRC_NetworkCommunication_DynamicType_Kinect_Header 19
+#define HALFRC_NetworkCommunication_DynamicType_Kinect_Extra1 20
+#define HALFRC_NetworkCommunication_DynamicType_Kinect_Vertices1 21
+#define HALFRC_NetworkCommunication_DynamicType_Kinect_Extra2 22
+#define HALFRC_NetworkCommunication_DynamicType_Kinect_Vertices2 23
+#define HALFRC_NetworkCommunication_DynamicType_Kinect_Joystick 24
+#define HALFRC_NetworkCommunication_DynamicType_Kinect_Custom 25
+
+namespace HALUsageReporting
+{
+	enum tResourceType
+	{
+		kResourceType_Controller,
+		kResourceType_Module,
+		kResourceType_Language,
+		kResourceType_CANPlugin,
+		kResourceType_Accelerometer,
+		kResourceType_ADXL345,
+		kResourceType_AnalogChannel,
+		kResourceType_AnalogTrigger,
+		kResourceType_AnalogTriggerOutput,
+		kResourceType_CANJaguar,
+		kResourceType_Compressor,
+		kResourceType_Counter,
+		kResourceType_Dashboard,
+		kResourceType_DigitalInput,
+		kResourceType_DigitalOutput,
+		kResourceType_DriverStationCIO,
+		kResourceType_DriverStationEIO,
+		kResourceType_DriverStationLCD,
+		kResourceType_Encoder,
+		kResourceType_GearTooth,
+		kResourceType_Gyro,
+		kResourceType_I2C,
+		kResourceType_Framework,
+		kResourceType_Jaguar,
+		kResourceType_Joystick,
+		kResourceType_Kinect,
+		kResourceType_KinectStick,
+		kResourceType_PIDController,
+		kResourceType_Preferences,
+		kResourceType_PWM,
+		kResourceType_Relay,
+		kResourceType_RobotDrive,
+		kResourceType_SerialPort,
+		kResourceType_Servo,
+		kResourceType_Solenoid,
+		kResourceType_SPI,
+		kResourceType_Task,
+		kResourceType_Ultrasonic,
+		kResourceType_Victor,
+		kResourceType_Button,
+		kResourceType_Command,
+		kResourceType_AxisCamera,
+		kResourceType_PCVideoServer,
+		kResourceType_SmartDashboard,
+		kResourceType_Talon,
+		kResourceType_HiTechnicColorSensor,
+		kResourceType_HiTechnicAccel,
+		kResourceType_HiTechnicCompass,
+		kResourceType_SRF08,
+		kResourceType_DigitalGlitchFilter,
+	};
+
+	enum tInstances
+	{
+		kLanguage_LabVIEW = 1,
+		kLanguage_CPlusPlus = 2,
+		kLanguage_Java = 3,
+		kLanguage_Python = 4,
+
+		kCANPlugin_BlackJagBridge = 1,
+		kCANPlugin_2CAN = 2,
+
+		kFramework_Iterative = 1,
+		kFramework_Simple = 2,
+
+		kRobotDrive_ArcadeStandard = 1,
+		kRobotDrive_ArcadeButtonSpin = 2,
+		kRobotDrive_ArcadeRatioCurve = 3,
+		kRobotDrive_Tank = 4,
+		kRobotDrive_MecanumPolar = 5,
+		kRobotDrive_MecanumCartesian = 6,
+
+		kDriverStationCIO_Analog = 1,
+		kDriverStationCIO_DigitalIn = 2,
+		kDriverStationCIO_DigitalOut = 3,
+
+		kDriverStationEIO_Acceleration = 1,
+		kDriverStationEIO_AnalogIn = 2,
+		kDriverStationEIO_AnalogOut = 3,
+		kDriverStationEIO_Button = 4,
+		kDriverStationEIO_LED = 5,
+		kDriverStationEIO_DigitalIn = 6,
+		kDriverStationEIO_DigitalOut = 7,
+		kDriverStationEIO_FixedDigitalOut = 8,
+		kDriverStationEIO_PWM = 9,
+		kDriverStationEIO_Encoder = 10,
+		kDriverStationEIO_TouchSlider = 11,
+
+		kADXL345_SPI = 1,
+		kADXL345_I2C = 2,
+
+		kCommand_Scheduler = 1,
+
+		kSmartDashboard_Instance = 1,
+	};
+}
+
+struct HALControlWord {
+	uint32_t enabled : 1;
+	uint32_t autonomous : 1;
+	uint32_t test :1;
+	uint32_t eStop : 1;
+	uint32_t fmsAttached:1;
+	uint32_t dsAttached:1;
+	uint32_t control_reserved : 26;
+};
+
+enum HALAllianceStationID {
+	kHALAllianceStationID_red1,
+	kHALAllianceStationID_red2,
+	kHALAllianceStationID_red3,
+	kHALAllianceStationID_blue1,
+	kHALAllianceStationID_blue2,
+	kHALAllianceStationID_blue3,
+};
+
+/* The maximum number of axes that will be stored in a single HALJoystickAxes
+	struct. This is used for allocating buffers, not bounds checking, since
+	there are usually less axes in practice. */
+static constexpr size_t kMaxJoystickAxes = 12;
+static constexpr size_t kMaxJoystickPOVs = 12;
+
+struct HALJoystickAxes {
+	uint16_t count;
+	int16_t axes[kMaxJoystickAxes];
+};
+
+struct HALJoystickPOVs {
+	uint16_t count;
+	int16_t povs[kMaxJoystickPOVs];
+};
+
+struct HALJoystickButtons {
+	uint32_t buttons;
+	uint8_t count;
+};
+
+struct HALJoystickDescriptor {
+	uint8_t isXbox;
+	uint8_t type;
+	char name[256];
+	uint8_t axisCount;
+	uint8_t axisTypes;
+	uint8_t buttonCount;
+	uint8_t povCount;
+};
+
+inline float intToFloat(int value)
+{
+	return (float)value;
+}
+
+inline int floatToInt(float value)
+{
+	return round(value);
+}
+
+extern "C"
+{
+	extern const uint32_t dio_kNumSystems;
+	extern const uint32_t solenoid_kNumDO7_0Elements;
+	extern const uint32_t interrupt_kNumSystems;
+	extern const uint32_t kSystemClockTicksPerMicrosecond;
+
+	void* getPort(uint8_t pin);
+	void* getPortWithModule(uint8_t module, uint8_t pin);
+	const char* getHALErrorMessage(int32_t code);
+
+	uint16_t getFPGAVersion(int32_t *status);
+	uint32_t getFPGARevision(int32_t *status);
+	uint32_t getFPGATime(int32_t *status);
+
+	bool getFPGAButton(int32_t *status);
+
+	int HALSetErrorData(const char *errors, int errorsLength, int wait_ms);
+
+	int HALGetControlWord(HALControlWord *data);
+	int HALGetAllianceStation(enum HALAllianceStationID *allianceStation);
+	int HALGetJoystickAxes(uint8_t joystickNum, HALJoystickAxes *axes);
+	int HALGetJoystickPOVs(uint8_t joystickNum, HALJoystickPOVs *povs);
+	int HALGetJoystickButtons(uint8_t joystickNum, HALJoystickButtons *buttons);
+	int HALGetJoystickDescriptor(uint8_t joystickNum, HALJoystickDescriptor *desc);
+	int HALSetJoystickOutputs(uint8_t joystickNum, uint32_t outputs, uint16_t leftRumble, uint16_t rightRumble);
+	int HALGetMatchTime(float *matchTime);
+
+	void HALSetNewDataSem(MULTIWAIT_ID sem);
+	
+	bool HALGetSystemActive(int32_t *status);
+	bool HALGetBrownedOut(int32_t *status);
+
+	int HALInitialize(int mode = 0);
+	void HALNetworkCommunicationObserveUserProgramStarting();
+	void HALNetworkCommunicationObserveUserProgramDisabled();
+	void HALNetworkCommunicationObserveUserProgramAutonomous();
+	void HALNetworkCommunicationObserveUserProgramTeleop();
+	void HALNetworkCommunicationObserveUserProgramTest();
+
+	uint32_t HALReport(uint8_t resource, uint8_t instanceNumber, uint8_t context = 0,
+			const char *feature = NULL);
+}
+
+// TODO: HACKS for now...
+extern "C"
+{
+
+	void NumericArrayResize();
+	void RTSetCleanupProc();
+	void EDVR_CreateReference();
+	void Occur();
+}
diff --git a/aos/externals/allwpilib/hal/include/HAL/Interrupts.hpp b/aos/externals/allwpilib/hal/include/HAL/Interrupts.hpp
new file mode 100644
index 0000000..636e809
--- /dev/null
+++ b/aos/externals/allwpilib/hal/include/HAL/Interrupts.hpp
@@ -0,0 +1,30 @@
+#pragma once
+
+#ifdef __vxworks
+#include <vxWorks.h>
+#else
+#include <stdint.h>
+#endif
+
+#include <iostream>
+#include "errno.h"
+
+extern "C"
+{
+	typedef void (*InterruptHandlerFunction)(uint32_t interruptAssertedMask, void *param);
+
+	void* initializeInterrupts(uint32_t interruptIndex, bool watcher, int32_t *status);
+	void cleanInterrupts(void* interrupt_pointer, int32_t *status);
+
+	uint32_t waitForInterrupt(void* interrupt_pointer, double timeout, bool ignorePrevious, int32_t *status);
+	void enableInterrupts(void* interrupt_pointer, int32_t *status);
+	void disableInterrupts(void* interrupt_pointer, int32_t *status);
+	double readRisingTimestamp(void* interrupt_pointer, int32_t *status);
+	double readFallingTimestamp(void* interrupt_pointer, int32_t *status);
+	void requestInterrupts(void* interrupt_pointer, uint8_t routing_module, uint32_t routing_pin,
+			bool routing_analog_trigger, int32_t *status);
+	void attachInterruptHandler(void* interrupt_pointer, InterruptHandlerFunction handler,
+			void* param, int32_t *status);
+	void setInterruptUpSourceEdge(void* interrupt_pointer, bool risingEdge, bool fallingEdge,
+			int32_t *status);
+}
diff --git a/aos/externals/allwpilib/hal/include/HAL/Notifier.hpp b/aos/externals/allwpilib/hal/include/HAL/Notifier.hpp
new file mode 100644
index 0000000..987686c
--- /dev/null
+++ b/aos/externals/allwpilib/hal/include/HAL/Notifier.hpp
@@ -0,0 +1,15 @@
+#pragma once
+
+#ifdef __vxworks
+#include <vxWorks.h>
+#else
+#include <stdint.h>
+#endif
+
+extern "C"
+{
+	void* initializeNotifier(void (*ProcessQueue)(uint32_t, void*), int32_t *status);
+	void cleanNotifier(void* notifier_pointer, int32_t *status);
+
+	void updateNotifierAlarm(void* notifier_pointer, uint32_t triggerTime, int32_t *status);
+}
diff --git a/aos/externals/allwpilib/hal/include/HAL/PDP.hpp b/aos/externals/allwpilib/hal/include/HAL/PDP.hpp
new file mode 100644
index 0000000..3dde22b
--- /dev/null
+++ b/aos/externals/allwpilib/hal/include/HAL/PDP.hpp
@@ -0,0 +1,19 @@
+#pragma once
+
+#ifdef __vxworks
+#include <vxWorks.h>
+#else
+#include <stdint.h>
+#endif
+
+extern "C"
+{
+	double getPDPTemperature(int32_t *status);
+	double getPDPVoltage(int32_t *status);
+	double getPDPChannelCurrent(uint8_t channel, int32_t *status);
+	double getPDPTotalCurrent(int32_t *status);
+	double getPDPTotalPower(int32_t *status);
+	double getPDPTotalEnergy(int32_t *status);
+	void resetPDPTotalEnergy(int32_t *status);
+	void clearPDPStickyFaults(int32_t *status);
+}
diff --git a/aos/externals/allwpilib/hal/include/HAL/Power.hpp b/aos/externals/allwpilib/hal/include/HAL/Power.hpp
new file mode 100644
index 0000000..b430c1e
--- /dev/null
+++ b/aos/externals/allwpilib/hal/include/HAL/Power.hpp
@@ -0,0 +1,21 @@
+#pragma once
+
+#include <stdint.h>
+
+extern "C"
+{
+	float getVinVoltage(int32_t *status);
+	float getVinCurrent(int32_t *status);
+	float getUserVoltage6V(int32_t *status);
+	float getUserCurrent6V(int32_t *status);
+	bool getUserActive6V(int32_t *status);
+	int getUserCurrentFaults6V(int32_t *status);
+	float getUserVoltage5V(int32_t *status);
+	float getUserCurrent5V(int32_t *status);
+	bool getUserActive5V(int32_t *status);
+	int getUserCurrentFaults5V(int32_t *status);
+	float getUserVoltage3V3(int32_t *status);
+	float getUserCurrent3V3(int32_t *status);
+	bool getUserActive3V3(int32_t *status);
+	int getUserCurrentFaults3V3(int32_t *status);
+}
diff --git a/aos/externals/allwpilib/hal/include/HAL/Semaphore.hpp b/aos/externals/allwpilib/hal/include/HAL/Semaphore.hpp
new file mode 100644
index 0000000..e02011f
--- /dev/null
+++ b/aos/externals/allwpilib/hal/include/HAL/Semaphore.hpp
@@ -0,0 +1,53 @@
+#pragma once
+
+#ifdef __vxworks
+#include <vxWorks.h>
+#else
+#include <stdint.h>
+#include <pthread.h>
+#include <semaphore.h>
+#endif
+
+#ifdef __vxworks
+typedef SEM_ID MUTEX_ID;
+typedef SEM_ID SEMAPHORE_ID;
+typedef SEM_ID MULTIWAIT_ID;
+#else
+class MutexInterface;
+typedef MutexInterface* MUTEX_ID;
+typedef sem_t* SEMAPHORE_ID;
+typedef pthread_cond_t* MULTIWAIT_ID;
+#endif
+
+extern "C"
+{
+	extern const uint32_t SEMAPHORE_Q_FIFO;
+	extern const uint32_t SEMAPHORE_Q_PRIORITY;
+	extern const uint32_t SEMAPHORE_DELETE_SAFE;
+	extern const uint32_t SEMAPHORE_INVERSION_SAFE;
+
+	extern const int32_t SEMAPHORE_NO_WAIT;
+	extern const int32_t SEMAPHORE_WAIT_FOREVER;
+
+	extern const uint32_t SEMAPHORE_EMPTY;
+	extern const uint32_t SEMAPHORE_FULL;
+
+	MUTEX_ID initializeMutexRecursive();
+	MUTEX_ID initializeMutexNormal();
+	void deleteMutex(MUTEX_ID sem);
+	int8_t lockMutex(MUTEX_ID sem);
+	int8_t tryLockMutex(MUTEX_ID sem);
+	int8_t unlockMutex(MUTEX_ID sem);
+
+	SEMAPHORE_ID initializeSemaphore(uint32_t initial_value);
+	void deleteSemaphore(SEMAPHORE_ID sem);
+	int8_t takeSemaphore(SEMAPHORE_ID sem);
+	int8_t tryTakeSemaphore(SEMAPHORE_ID sem);
+	int8_t giveSemaphore(SEMAPHORE_ID sem);
+
+	MULTIWAIT_ID initializeMultiWait();
+	void deleteMultiWait(MULTIWAIT_ID sem);
+	int8_t takeMultiWait(MULTIWAIT_ID sem, MUTEX_ID m, int32_t timeout);
+	int8_t giveMultiWait(MULTIWAIT_ID sem);
+}
+
diff --git a/aos/externals/allwpilib/hal/include/HAL/Solenoid.hpp b/aos/externals/allwpilib/hal/include/HAL/Solenoid.hpp
new file mode 100644
index 0000000..1654dc2
--- /dev/null
+++ b/aos/externals/allwpilib/hal/include/HAL/Solenoid.hpp
@@ -0,0 +1,22 @@
+#pragma once
+
+#ifdef __vxworks
+#include <vxWorks.h>
+#else
+#include <stdint.h>
+#endif
+
+extern "C"
+{
+	void* initializeSolenoidPort(void* port_pointer, int32_t *status);
+	bool checkSolenoidModule(uint8_t module);
+
+	bool getSolenoid(void* solenoid_port_pointer, int32_t *status);
+	void setSolenoid(void* solenoid_port_pointer, bool value, int32_t *status);
+	void setSolenoids(void* solenoid_port_pointer, uint8_t value, uint8_t mask, int32_t *status);
+
+	int getPCMSolenoidBlackList(void* solenoid_port_pointer, int32_t *status);
+	bool getPCMSolenoidVoltageStickyFault(void* solenoid_port_pointer, int32_t *status);
+	bool getPCMSolenoidVoltageFault(void* solenoid_port_pointer, int32_t *status);
+	void clearAllPCMStickyFaults_sol(void *solenoid_port_pointer, int32_t *status);
+}
diff --git a/aos/externals/allwpilib/hal/include/HAL/Task.hpp b/aos/externals/allwpilib/hal/include/HAL/Task.hpp
new file mode 100644
index 0000000..ec3ed9b
--- /dev/null
+++ b/aos/externals/allwpilib/hal/include/HAL/Task.hpp
@@ -0,0 +1,55 @@
+#pragma once
+
+#ifdef __vxworks
+#include <vxWorks.h>
+#else
+#include <stdint.h>
+#include <pthread.h>
+#endif
+
+#ifndef _FUNCPTR_DEFINED
+#define _FUNCPTR_DEFINED
+#ifdef __cplusplus
+typedef int (*FUNCPTR)(...);
+/* ptr to function returning int */
+#else
+typedef int (*FUNCPTR) (); /* ptr to function returning int */
+#endif /* __cplusplus */
+#endif /* _FUNCPTR_DEFINED */
+
+#ifndef _STATUS_DEFINED
+#define _STATUS_DEFINED
+typedef int STATUS;
+#endif /* _STATUS_DEFINED */
+
+#ifdef __vxworks
+#define NULL_TASK -1
+typedef int32_t TASK;
+#else
+#define NULL_TASK NULL
+typedef pthread_t* TASK;
+#endif
+
+extern "C"
+{
+	extern const uint32_t VXWORKS_FP_TASK;
+	extern const int32_t HAL_objLib_OBJ_ID_ERROR;
+	extern const int32_t HAL_objLib_OBJ_DELETED;
+	extern const int32_t HAL_taskLib_ILLEGAL_OPTIONS;
+	extern const int32_t HAL_memLib_NOT_ENOUGH_MEMORY;
+	extern const int32_t HAL_taskLib_ILLEGAL_PRIORITY;
+
+	TASK spawnTask(char * name, int priority, int options, int stackSize, FUNCPTR entryPt,
+			uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4,
+			uint32_t arg5, uint32_t arg6, uint32_t arg7, uint32_t arg8, uint32_t arg9);
+	STATUS restartTask(TASK task);
+	STATUS deleteTask(TASK task);
+	STATUS isTaskReady(TASK task);
+	STATUS isTaskSuspended(TASK task);
+	STATUS suspendTask(TASK task);
+	STATUS resumeTask(TASK task);
+	STATUS verifyTaskID(TASK task);
+	STATUS setTaskPriority(TASK task, int priority);
+	STATUS getTaskPriority(TASK task, int* priority);
+}
+
diff --git a/aos/externals/allwpilib/hal/include/HAL/Utilities.hpp b/aos/externals/allwpilib/hal/include/HAL/Utilities.hpp
new file mode 100644
index 0000000..b24cd29
--- /dev/null
+++ b/aos/externals/allwpilib/hal/include/HAL/Utilities.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+#ifdef __vxworks
+#include <vxWorks.h>
+#else
+#include <stdint.h>
+#endif
+
+extern "C"
+{
+	extern const int32_t HAL_NO_WAIT;
+	extern const int32_t HAL_WAIT_FOREVER;
+
+	void delayTicks(int32_t ticks);
+	void delayMillis(double ms);
+	void delaySeconds(double s);
+}
diff --git a/aos/externals/allwpilib/hal/include/HAL/cpp/Resource.hpp b/aos/externals/allwpilib/hal/include/HAL/cpp/Resource.hpp
new file mode 100644
index 0000000..931407f
--- /dev/null
+++ b/aos/externals/allwpilib/hal/include/HAL/cpp/Resource.hpp
@@ -0,0 +1,45 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "../Errors.hpp"
+#include "Synchronized.hpp"
+#ifdef __vxworks
+#include <vxWorks.h>
+#else
+#include <stdint.h>
+#endif
+
+/**
+ * The Resource class is a convenient way to track allocated resources.
+ * It tracks them as indicies in the range [0 .. elements - 1].
+ * E.g. the library uses this to track hardware channel allocation.
+ *
+ * The Resource class does not allocate the hardware channels or other
+ * resources; it just tracks which indices were marked in use by
+ * Allocate and not yet freed by Free.
+ */
+class Resource
+{
+public:
+	virtual ~Resource();
+	static void CreateResourceObject(Resource **r, uint32_t elements);
+	uint32_t Allocate(const char *resourceDesc);
+	uint32_t Allocate(uint32_t index, const char *resourceDesc);
+	void Free(uint32_t index);
+
+private:
+	explicit Resource(uint32_t size);
+
+	bool *m_isAllocated;
+	ReentrantMutex m_allocateLock;
+	uint32_t m_size;
+
+	static ReentrantMutex m_createLock;
+
+	DISALLOW_COPY_AND_ASSIGN(Resource);
+};
+
diff --git a/aos/externals/allwpilib/hal/include/HAL/cpp/Synchronized.hpp b/aos/externals/allwpilib/hal/include/HAL/cpp/Synchronized.hpp
new file mode 100644
index 0000000..af8b149
--- /dev/null
+++ b/aos/externals/allwpilib/hal/include/HAL/cpp/Synchronized.hpp
@@ -0,0 +1,144 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include <mutex>
+#include "HAL/Semaphore.hpp"
+
+// A macro to disallow the copy constructor and operator= functions
+// This should be used in the private: declarations for a class
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+  TypeName(const TypeName&) = delete;      \
+  void operator=(const TypeName&) = delete
+
+class Synchronized;
+
+/**
+ * Wrap a pthead mutex for easier use in C++. For a static
+ * instance, the constructor runs at program load time before main() can spawn
+ * any tasks. Use that to fix race conditions in setup code.
+ *
+ * This uses a pthread mutex which has PTHREAD_MUTEX_RECURSIVE set, making it
+ * "reentrant" in the sense that the owning task can lock it more than once. The
+ * task will need to unlock the mutex the same number of times to make it
+ * available for other threads to acquire.
+ *
+ * This class is safe to use in static variables because it does not depend on
+ * any other C++ static constructors or destructors.
+ */
+class ReentrantMutex {
+ public:
+  typedef pthread_mutex_t *native_handle_type;
+
+  constexpr ReentrantMutex() noexcept = default;
+  ReentrantMutex(const ReentrantMutex &) = delete;
+  ReentrantMutex &operator=(const ReentrantMutex &) = delete;
+
+  /**
+   * Lock the mutex, blocking until it's available.
+   */
+  void lock() { pthread_mutex_lock(&mutex_); }
+
+  /**
+   * Unlock the mutex.
+   */
+  void unlock() { pthread_mutex_unlock(&mutex_); }
+
+  /**
+   * Tries to lock the mutex.
+   */
+  bool try_lock() noexcept { return !pthread_mutex_trylock(&mutex_); }
+
+  pthread_mutex_t *native_handle() { return &mutex_; }
+
+ private:
+  // Do the equivalent of setting PTHREAD_PRIO_INHERIT and
+  // PTHREAD_MUTEX_RECURSIVE_NP.
+#if __WORDSIZE == 64
+  #error "Should work, but need to run test case to verify"
+  pthread_mutex_t mutex_ = {
+      {0, 0, 0, 0, 0x20 | PTHREAD_MUTEX_RECURSIVE_NP, 0, {0, 0}}};
+#else
+  pthread_mutex_t mutex_ = {
+      {0, 0, 0, 0x20 | PTHREAD_MUTEX_RECURSIVE_NP, 0, {0}}};
+#endif
+};
+
+/**
+ * Wrap a pthead mutex for easier use in C++. For a static
+ * instance, the constructor runs at program load time before main() can spawn
+ * any tasks. Use that to fix race conditions in setup code.
+ *
+ * This class is safe to use in static variables because it does not depend on
+ * any other C++ static constructors or destructors.
+ */
+class Mutex {
+ public:
+  typedef pthread_mutex_t *native_handle_type;
+
+  constexpr Mutex() noexcept = default;
+  Mutex(const Mutex &) = delete;
+  Mutex &operator=(const Mutex &) = delete;
+
+  /**
+   * Lock the mutex, blocking until it's available.
+   */
+  void lock() { pthread_mutex_lock(&mutex_); }
+
+  /**
+   * Unlock the mutex.
+   */
+  void unlock() { pthread_mutex_unlock(&mutex_); }
+
+  /**
+   * Tries to lock the mutex.
+   */
+  bool try_lock() noexcept { return !pthread_mutex_trylock(&mutex_); }
+
+  native_handle_type native_handle() { return &mutex_; }
+
+ private:
+  // Do the equivalent of setting PTHREAD_PRIO_INHERIT.
+#if __WORDSIZE == 64
+  #error "Should work, but need to run test case to verify"
+  pthread_mutex_t mutex_ = { { 0, 0, 0, 0, 0x20, 0, { 0, 0 } } };
+#else
+  pthread_mutex_t mutex_ = { { 0, 0, 0, 0x20, 0, { 0 } } };
+#endif
+};
+
+
+/**
+ * Provide easy support for critical regions.
+ *
+ * A critical region is an area of code that is always executed under mutual exclusion. Only
+ * one task can be executing this code at any time. The idea is that code that manipulates data
+ * that is shared between two or more tasks has to be prevented from executing at the same time
+ * otherwise a race condition is possible when both tasks try to update the data. Typically
+ * semaphores are used to ensure only single task access to the data.
+ *
+ * Synchronized objects are a simple wrapper around semaphores to help ensure
+ * that semaphores are always unlocked (semGive) after locking (semTake).
+ *
+ * You allocate a Synchronized as a local variable, *not* on the heap. That
+ * makes it a "stack object" whose destructor runs automatically when it goes
+ * out of scope. E.g.
+ *
+ *   { Synchronized _sync(aReentrantSemaphore); ... critical region ... }
+ */
+class Synchronized
+{
+public:
+#ifndef __vxworks
+	explicit Synchronized(SEMAPHORE_ID);
+#endif
+	virtual ~Synchronized();
+private:
+	SEMAPHORE_ID m_semaphore;
+
+	DISALLOW_COPY_AND_ASSIGN(Synchronized);
+};
+
diff --git a/aos/externals/allwpilib/hal/include/Log.hpp b/aos/externals/allwpilib/hal/include/Log.hpp
new file mode 100644
index 0000000..eb221e7
--- /dev/null
+++ b/aos/externals/allwpilib/hal/include/Log.hpp
@@ -0,0 +1,103 @@
+#pragma once
+
+#include <sstream>
+#include <iomanip>
+#include <string>
+#include <stdio.h>
+#include <sys/time.h>
+
+inline std::string NowTime();
+
+enum TLogLevel {logNONE, logERROR, logWARNING, logINFO, logDEBUG, logDEBUG1, logDEBUG2, logDEBUG3, logDEBUG4};
+
+class Log
+{
+public:
+    Log();
+    virtual ~Log();
+    std::ostringstream& Get(TLogLevel level = logINFO);
+public:
+    static TLogLevel& ReportingLevel();
+    static std::string ToString(TLogLevel level);
+    static TLogLevel FromString(const std::string& level);
+protected:
+    std::ostringstream os;
+private:
+    Log(const Log&);
+    Log& operator =(const Log&);
+};
+
+inline Log::Log()
+{
+}
+
+inline std::ostringstream& Log::Get(TLogLevel level)
+{
+    os << "- " << NowTime();
+    os << " " << ToString(level) << ": ";
+    os << std::string(level > logDEBUG ? level - logDEBUG : 0, '\t');
+    return os;
+}
+
+inline Log::~Log()
+{
+    os << std::endl;
+    fprintf(stderr, "%s", os.str().c_str());
+    fflush(stderr);
+}
+
+inline TLogLevel& Log::ReportingLevel()
+{
+    static TLogLevel reportingLevel = logDEBUG4;
+    return reportingLevel;
+}
+
+inline std::string Log::ToString(TLogLevel level)
+{
+	static const char* const buffer[] = {"NONE", "ERROR", "WARNING", "INFO", "DEBUG", "DEBUG1", "DEBUG2", "DEBUG3", "DEBUG4"};
+    return buffer[level];
+}
+
+inline TLogLevel Log::FromString(const std::string& level)
+{
+    if (level == "DEBUG4")
+        return logDEBUG4;
+    if (level == "DEBUG3")
+        return logDEBUG3;
+    if (level == "DEBUG2")
+        return logDEBUG2;
+    if (level == "DEBUG1")
+        return logDEBUG1;
+    if (level == "DEBUG")
+        return logDEBUG;
+    if (level == "INFO")
+        return logINFO;
+    if (level == "WARNING")
+        return logWARNING;
+    if (level == "ERROR")
+        return logERROR;
+    if (level == "NONE")
+    	return logNONE;
+    Log().Get(logWARNING) << "Unknown logging level '" << level << "'. Using INFO level as default.";
+    return logINFO;
+}
+
+typedef Log FILELog;
+
+#define FILE_LOG(level) \
+    if (level > FILELog::ReportingLevel()) ; \
+    else Log().Get(level)
+
+inline std::string NowTime()
+{
+    char buffer[11];
+    time_t t;
+    time(&t);
+    tm * r = gmtime(&t);
+    strftime(buffer, sizeof(buffer), "%H:%M:%S", r);
+    struct timeval tv;
+    gettimeofday(&tv, 0);
+    char result[100] = {0};
+    sprintf(result, "%s.%03ld", buffer, (long)tv.tv_usec / 1000);
+    return result;
+}
diff --git a/aos/externals/allwpilib/hal/lib/Athena/Accelerometer.cpp b/aos/externals/allwpilib/hal/lib/Athena/Accelerometer.cpp
new file mode 100644
index 0000000..0895c9c
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/Accelerometer.cpp
@@ -0,0 +1,234 @@
+#include "HAL/Accelerometer.hpp"
+
+#include "ChipObject.h"
+#include <stdint.h>
+#include <stdio.h>
+#include <assert.h>
+
+// The 7-bit I2C address with a 0 "send" bit
+static const uint8_t kSendAddress = (0x1c << 1) | 0;
+
+// The 7-bit I2C address with a 1 "receive" bit
+static const uint8_t kReceiveAddress = (0x1c << 1) | 1;
+
+static const uint8_t kControlTxRx = 1;
+static const uint8_t kControlStart = 2;
+static const uint8_t kControlStop = 4;
+
+static tAccel *accel = 0;
+static AccelerometerRange accelerometerRange;
+
+// Register addresses
+enum Register {
+	kReg_Status = 0x00,
+	kReg_OutXMSB = 0x01,
+	kReg_OutXLSB = 0x02,
+	kReg_OutYMSB = 0x03,
+	kReg_OutYLSB = 0x04,
+	kReg_OutZMSB = 0x05,
+	kReg_OutZLSB = 0x06,
+	kReg_Sysmod = 0x0B,
+	kReg_IntSource = 0x0C,
+	kReg_WhoAmI = 0x0D,
+	kReg_XYZDataCfg = 0x0E,
+	kReg_HPFilterCutoff = 0x0F,
+	kReg_PLStatus = 0x10,
+	kReg_PLCfg = 0x11,
+	kReg_PLCount = 0x12,
+	kReg_PLBfZcomp = 0x13,
+	kReg_PLThsReg = 0x14,
+	kReg_FFMtCfg = 0x15,
+	kReg_FFMtSrc = 0x16,
+	kReg_FFMtThs = 0x17,
+	kReg_FFMtCount = 0x18,
+	kReg_TransientCfg = 0x1D,
+	kReg_TransientSrc = 0x1E,
+	kReg_TransientThs = 0x1F,
+	kReg_TransientCount = 0x20,
+	kReg_PulseCfg = 0x21,
+	kReg_PulseSrc = 0x22,
+	kReg_PulseThsx = 0x23,
+	kReg_PulseThsy = 0x24,
+	kReg_PulseThsz = 0x25,
+	kReg_PulseTmlt = 0x26,
+	kReg_PulseLtcy = 0x27,
+	kReg_PulseWind = 0x28,
+	kReg_ASlpCount = 0x29,
+	kReg_CtrlReg1 = 0x2A,
+	kReg_CtrlReg2 = 0x2B,
+	kReg_CtrlReg3 = 0x2C,
+	kReg_CtrlReg4 = 0x2D,
+	kReg_CtrlReg5 = 0x2E,
+	kReg_OffX = 0x2F,
+	kReg_OffY = 0x30,
+	kReg_OffZ = 0x31
+};
+
+extern "C" uint32_t getFPGATime(int32_t *status);
+
+static void writeRegister(Register reg, uint8_t data);
+static uint8_t readRegister(Register reg);
+
+/**
+ * Initialize the accelerometer.
+ */
+static void initializeAccelerometer() {
+	int32_t status;
+
+	if(!accel) {
+		accel = tAccel::create(&status);
+
+		// Enable I2C
+		accel->writeCNFG(1, &status);
+
+		// Set the counter to 100 kbps
+		accel->writeCNTR(213, &status);
+
+		// The device identification number should be 0x2a
+		assert(readRegister(kReg_WhoAmI) == 0x2a);
+	}
+}
+
+static void writeRegister(Register reg, uint8_t data) {
+	int32_t status = 0;
+	uint32_t initialTime;
+
+	accel->writeADDR(kSendAddress, &status);
+
+	// Send a start transmit/receive message with the register address
+	accel->writeCNTL(kControlStart | kControlTxRx, &status);
+	accel->writeDATO(reg, &status);
+	accel->strobeGO(&status);
+
+	// Execute and wait until it's done (up to a millisecond)
+	initialTime = getFPGATime(&status);
+	while(accel->readSTAT(&status) & 1) {
+		if(getFPGATime(&status) > initialTime + 1000) break;
+	}
+
+	// Send a stop transmit/receive message with the data
+	accel->writeCNTL(kControlStop | kControlTxRx, &status);
+	accel->writeDATO(data, &status);
+	accel->strobeGO(&status);
+
+	// Execute and wait until it's done (up to a millisecond)
+	initialTime = getFPGATime(&status);
+	while(accel->readSTAT(&status) & 1) {
+		if(getFPGATime(&status) > initialTime + 1000) break;
+	}
+
+	fflush(stdout);
+}
+
+static uint8_t readRegister(Register reg) {
+	int32_t status = 0;
+	uint32_t initialTime;
+
+	// Send a start transmit/receive message with the register address
+	accel->writeADDR(kSendAddress, &status);
+	accel->writeCNTL(kControlStart | kControlTxRx, &status);
+	accel->writeDATO(reg, &status);
+	accel->strobeGO(&status);
+
+	// Execute and wait until it's done (up to a millisecond)
+	initialTime = getFPGATime(&status);
+	while(accel->readSTAT(&status) & 1) {
+		if(getFPGATime(&status) > initialTime + 1000) break;
+	}
+
+	// Receive a message with the data and stop
+	accel->writeADDR(kReceiveAddress, &status);
+	accel->writeCNTL(kControlStart | kControlStop | kControlTxRx, &status);
+	accel->strobeGO(&status);
+
+	// Execute and wait until it's done (up to a millisecond)
+	initialTime = getFPGATime(&status);
+	while(accel->readSTAT(&status) & 1) {
+		if(getFPGATime(&status) > initialTime + 1000) break;
+	}
+
+	fflush(stdout);
+
+	return accel->readDATI(&status);
+}
+
+/**
+ * Convert a 12-bit raw acceleration value into a scaled double in units of
+ * 1 g-force, taking into account the accelerometer range.
+ */
+static double unpackAxis(int16_t raw) {
+	// The raw value is actually 12 bits, not 16, so we need to propogate the
+	// 2's complement sign bit to the unused 4 bits for this to work with
+	// negative numbers.
+	raw <<= 4;
+	raw >>= 4;
+
+	switch(accelerometerRange) {
+	case kRange_2G: return raw / 1024.0;
+	case kRange_4G: return raw / 512.0;
+	case kRange_8G: return raw / 256.0;
+	default: return 0.0;
+	}
+}
+
+/**
+ * Set the accelerometer to active or standby mode.  It must be in standby
+ * mode to change any configuration.
+ */
+void setAccelerometerActive(bool active) {
+	initializeAccelerometer();
+
+	uint8_t ctrlReg1 = readRegister(kReg_CtrlReg1);
+	ctrlReg1 &= ~1; // Clear the existing active bit
+	writeRegister(kReg_CtrlReg1, ctrlReg1 | (active? 1 : 0));
+}
+
+/**
+ * Set the range of values that can be measured (either 2, 4, or 8 g-forces).
+ * The accelerometer should be in standby mode when this is called.
+ */
+void setAccelerometerRange(AccelerometerRange range) {
+	initializeAccelerometer();
+
+	accelerometerRange = range;
+
+	uint8_t xyzDataCfg = readRegister(kReg_XYZDataCfg);
+	xyzDataCfg &= ~3; // Clear the existing two range bits
+	writeRegister(kReg_XYZDataCfg, xyzDataCfg | range);
+}
+
+/**
+ * Get the x-axis acceleration
+ *
+ * This is a floating point value in units of 1 g-force
+ */
+double getAccelerometerX() {
+	initializeAccelerometer();
+
+	int raw = (readRegister(kReg_OutXMSB) << 4) | (readRegister(kReg_OutXLSB) >> 4);
+	return unpackAxis(raw);
+}
+
+/**
+ * Get the y-axis acceleration
+ *
+ * This is a floating point value in units of 1 g-force
+ */
+double getAccelerometerY() {
+	initializeAccelerometer();
+
+	int raw = (readRegister(kReg_OutYMSB) << 4) | (readRegister(kReg_OutYLSB) >> 4);
+	return unpackAxis(raw);
+}
+
+/**
+ * Get the z-axis acceleration
+ *
+ * This is a floating point value in units of 1 g-force
+ */
+double getAccelerometerZ() {
+	initializeAccelerometer();
+
+	int raw = (readRegister(kReg_OutZMSB) << 4) | (readRegister(kReg_OutZLSB) >> 4);
+	return unpackAxis(raw);
+}
diff --git a/aos/externals/allwpilib/hal/lib/Athena/Analog.cpp b/aos/externals/allwpilib/hal/lib/Athena/Analog.cpp
new file mode 100644
index 0000000..bba7043
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/Analog.cpp
@@ -0,0 +1,725 @@
+
+#include "HAL/Analog.hpp"
+
+#include "Port.h"
+#include "HAL/HAL.hpp"
+#include "ChipObject.h"
+#include "HAL/cpp/Synchronized.hpp"
+#include "HAL/cpp/Resource.hpp"
+#include "NetworkCommunication/AICalibration.h"
+#include "NetworkCommunication/LoadOut.h"
+
+static const long kTimebase = 40000000; ///< 40 MHz clock
+static const long kDefaultOversampleBits = 0;
+static const long kDefaultAverageBits = 7;
+static const float kDefaultSampleRate = 50000.0;
+static const uint32_t kAnalogInputPins = 8;
+static const uint32_t kAnalogOutputPins = 2;
+
+static const uint32_t kAccumulatorNumChannels = 2;
+static const uint32_t kAccumulatorChannels[] = {0, 1};
+
+struct AnalogPort {
+  Port port;
+  tAccumulator *accumulator;
+};
+
+bool analogSampleRateSet = false;
+ReentrantMutex analogRegisterWindowMutex;
+tAI* analogInputSystem = NULL;
+tAO* analogOutputSystem = NULL;
+uint32_t analogNumChannelsToActivate = 0;
+
+// Utility methods defined below.
+uint32_t getAnalogNumActiveChannels(int32_t *status);
+uint32_t getAnalogNumChannelsToActivate(int32_t *status);
+void setAnalogNumChannelsToActivate(uint32_t channels);
+
+bool analogSystemInitialized = false;
+
+/**
+ * Initialize the analog System.
+ */
+void initializeAnalog(int32_t *status) {
+  ::std::unique_lock<ReentrantMutex> sync(analogRegisterWindowMutex);
+  if (analogSystemInitialized) return;
+  analogInputSystem = tAI::create(status);
+  analogOutputSystem = tAO::create(status);
+  setAnalogNumChannelsToActivate(kAnalogInputPins);
+  setAnalogSampleRate(kDefaultSampleRate, status);
+  analogSystemInitialized = true;
+}
+
+/**
+ * Initialize the analog input port using the given port object.
+ */
+void* initializeAnalogInputPort(void* port_pointer, int32_t *status) {
+  initializeAnalog(status);
+  Port* port = (Port*) port_pointer;
+
+  // Initialize port structure
+  AnalogPort* analog_port = new AnalogPort();
+  analog_port->port = *port;
+  if (isAccumulatorChannel(analog_port, status)) {
+    analog_port->accumulator = tAccumulator::create(port->pin, status);
+  } else analog_port->accumulator = NULL;
+
+  // Set default configuration
+  analogInputSystem->writeScanList(port->pin, port->pin, status);
+  setAnalogAverageBits(analog_port, kDefaultAverageBits, status);
+  setAnalogOversampleBits(analog_port, kDefaultOversampleBits, status);
+  return analog_port;
+}
+
+/**
+ * Initialize the analog output port using the given port object.
+ */
+void* initializeAnalogOutputPort(void* port_pointer, int32_t *status) {
+  initializeAnalog(status);
+  Port* port = (Port*) port_pointer;
+
+  // Initialize port structure
+  AnalogPort* analog_port = new AnalogPort();
+  analog_port->port = *port;
+  return analog_port;
+}
+
+
+/**
+ * Check that the analog module number is valid.
+ *
+ * @return Analog module is valid and present
+ */
+bool checkAnalogModule(uint8_t module) {
+  return module == 1;
+}
+
+/**
+ * Check that the analog output channel number is value.
+ * Verify that the analog channel number is one of the legal channel numbers. Channel numbers
+ * are 0-based.
+ *
+ * @return Analog channel is valid
+ */
+bool checkAnalogInputChannel(uint32_t pin) {
+  if (pin < kAnalogInputPins)
+    return true;
+  return false;
+}
+
+/**
+ * Check that the analog output channel number is value.
+ * Verify that the analog channel number is one of the legal channel numbers. Channel numbers
+ * are 0-based.
+ *
+ * @return Analog channel is valid
+ */
+bool checkAnalogOutputChannel(uint32_t pin) {
+  if (pin < kAnalogOutputPins)
+    return true;
+  return false;
+}
+
+void setAnalogOutput(void* analog_port_pointer, double voltage, int32_t *status) {
+  AnalogPort* port = (AnalogPort*) analog_port_pointer;
+
+  uint16_t rawValue = (uint16_t)(voltage / 5.0 * 0x1000);
+
+  if(voltage < 0.0) rawValue = 0;
+  else if(voltage > 5.0) rawValue = 0x1000;
+
+  analogOutputSystem->writeMXP(port->port.pin, rawValue, status);
+}
+
+double getAnalogOutput(void* analog_port_pointer, int32_t *status) {
+  AnalogPort* port = (AnalogPort*) analog_port_pointer;
+
+  uint16_t rawValue = analogOutputSystem->readMXP(port->port.pin, status);
+
+  return rawValue * 5.0 / 0x1000;
+}
+
+/**
+ * Set the sample rate.
+ *
+ * This is a global setting for the Athena and effects all channels.
+ *
+ * @param samplesPerSecond The number of samples per channel per second.
+ */
+void setAnalogSampleRate(double samplesPerSecond, int32_t *status) {
+  // TODO: This will change when variable size scan lists are implemented.
+  // TODO: Need float comparison with epsilon.
+  //wpi_assert(!sampleRateSet || GetSampleRate() == samplesPerSecond);
+  analogSampleRateSet = true;
+
+  // Compute the convert rate
+  uint32_t ticksPerSample = (uint32_t)((float)kTimebase / samplesPerSecond);
+  uint32_t ticksPerConversion = ticksPerSample / getAnalogNumChannelsToActivate(status);
+  // ticksPerConversion must be at least 80
+  if (ticksPerConversion < 80) {
+    if ((*status) >= 0) *status = SAMPLE_RATE_TOO_HIGH;
+    ticksPerConversion = 80;
+  }
+
+  // Atomically set the scan size and the convert rate so that the sample rate is constant
+  tAI::tConfig config;
+  config.ScanSize = getAnalogNumChannelsToActivate(status);
+  config.ConvertRate = ticksPerConversion;
+  analogInputSystem->writeConfig(config, status);
+
+  // Indicate that the scan size has been commited to hardware.
+  setAnalogNumChannelsToActivate(0);
+}
+
+/**
+ * Get the current sample rate.
+ *
+ * This assumes one entry in the scan list.
+ * This is a global setting for the Athena and effects all channels.
+ *
+ * @return Sample rate.
+ */
+float getAnalogSampleRate(int32_t *status) {
+  uint32_t ticksPerConversion = analogInputSystem->readLoopTiming(status);
+  uint32_t ticksPerSample = ticksPerConversion * getAnalogNumActiveChannels(status);
+  return (float)kTimebase / (float)ticksPerSample;
+}
+
+/**
+ * Set the number of averaging bits.
+ *
+ * This sets the number of averaging bits. The actual number of averaged samples is 2**bits.
+ * Use averaging to improve the stability of your measurement at the expense of sampling rate.
+ * The averaging is done automatically in the FPGA.
+ *
+ * @param analog_port_pointer Pointer to the analog port to configure.
+ * @param bits Number of bits to average.
+ */
+void setAnalogAverageBits(void* analog_port_pointer, uint32_t bits, int32_t *status) {
+  AnalogPort* port = (AnalogPort*) analog_port_pointer;
+  analogInputSystem->writeAverageBits(port->port.pin, bits, status);
+}
+
+/**
+ * Get the number of averaging bits.
+ *
+ * This gets the number of averaging bits from the FPGA. The actual number of averaged samples is 2**bits.
+ * The averaging is done automatically in the FPGA.
+ *
+ * @param analog_port_pointer Pointer to the analog port to use.
+ * @return Bits to average.
+ */
+uint32_t getAnalogAverageBits(void* analog_port_pointer, int32_t *status) {
+  AnalogPort* port = (AnalogPort*) analog_port_pointer;
+  uint32_t result = analogInputSystem->readAverageBits(port->port.pin, status);
+  return result;
+}
+
+/**
+ * Set the number of oversample bits.
+ *
+ * This sets the number of oversample bits. The actual number of oversampled values is 2**bits.
+ * Use oversampling to improve the resolution of your measurements at the expense of sampling rate.
+ * The oversampling is done automatically in the FPGA.
+ *
+ * @param analog_port_pointer Pointer to the analog port to use.
+ * @param bits Number of bits to oversample.
+ */
+void setAnalogOversampleBits(void* analog_port_pointer, uint32_t bits, int32_t *status) {
+  AnalogPort* port = (AnalogPort*) analog_port_pointer;
+  analogInputSystem->writeOversampleBits(port->port.pin, bits, status);
+}
+
+
+/**
+ * Get the number of oversample bits.
+ *
+ * This gets the number of oversample bits from the FPGA. The actual number of oversampled values is
+ * 2**bits. The oversampling is done automatically in the FPGA.
+ *
+ * @param analog_port_pointer Pointer to the analog port to use.
+ * @return Bits to oversample.
+ */
+uint32_t getAnalogOversampleBits(void* analog_port_pointer, int32_t *status) {
+  AnalogPort* port = (AnalogPort*) analog_port_pointer;
+  uint32_t result = analogInputSystem->readOversampleBits(port->port.pin, status);
+  return result;
+}
+
+/**
+ * Get a sample straight from the channel on this module.
+ *
+ * The sample is a 12-bit value representing the 0V to 5V range of the A/D converter in the module.
+ * The units are in A/D converter codes.  Use GetVoltage() to get the analog value in calibrated units.
+ *
+ * @param analog_port_pointer Pointer to the analog port to use.
+ * @return A sample straight from the channel on this module.
+ */
+int16_t getAnalogValue(void* analog_port_pointer, int32_t *status) {
+  AnalogPort* port = (AnalogPort*) analog_port_pointer;
+  int16_t value;
+  checkAnalogInputChannel(port->port.pin);
+
+  tAI::tReadSelect readSelect;
+  readSelect.Channel = port->port.pin;
+  readSelect.Averaged = false;
+
+  {
+    ::std::unique_lock<ReentrantMutex> sync(analogRegisterWindowMutex);
+    analogInputSystem->writeReadSelect(readSelect, status);
+    analogInputSystem->strobeLatchOutput(status);
+    value = (int16_t) analogInputSystem->readOutput(status);
+  }
+
+  return value;
+}
+
+/**
+ * Get a sample from the output of the oversample and average engine for the channel.
+ *
+ * The sample is 12-bit + the value configured in SetOversampleBits().
+ * The value configured in SetAverageBits() will cause this value to be averaged 2**bits number of samples.
+ * This is not a sliding window.  The sample will not change until 2**(OversamplBits + AverageBits) samples
+ * have been acquired from the module on this channel.
+ * Use GetAverageVoltage() to get the analog value in calibrated units.
+ *
+ * @param analog_port_pointer Pointer to the analog port to use.
+ * @return A sample from the oversample and average engine for the channel.
+ */
+int32_t getAnalogAverageValue(void* analog_port_pointer, int32_t *status) {
+  AnalogPort* port = (AnalogPort*) analog_port_pointer;
+  int32_t value;
+  checkAnalogInputChannel(port->port.pin);
+
+  tAI::tReadSelect readSelect;
+  readSelect.Channel = port->port.pin;
+  readSelect.Averaged = true;
+
+  {
+    ::std::unique_lock<ReentrantMutex> sync(analogRegisterWindowMutex);
+    analogInputSystem->writeReadSelect(readSelect, status);
+    analogInputSystem->strobeLatchOutput(status);
+    value = (int32_t) analogInputSystem->readOutput(status);
+  }
+
+  return value;
+}
+
+/**
+ * Get a scaled sample straight from the channel on this module.
+ *
+ * The value is scaled to units of Volts using the calibrated scaling data from GetLSBWeight() and GetOffset().
+ *
+ * @param analog_port_pointer Pointer to the analog port to use.
+ * @return A scaled sample straight from the channel on this module.
+ */
+float getAnalogVoltage(void* analog_port_pointer, int32_t *status) {
+  int16_t value = getAnalogValue(analog_port_pointer, status);
+  uint32_t LSBWeight = getAnalogLSBWeight(analog_port_pointer, status);
+  int32_t offset = getAnalogOffset(analog_port_pointer, status);
+  float voltage = LSBWeight * 1.0e-9 * value - offset * 1.0e-9;
+  return voltage;
+}
+
+/**
+ * Get a scaled sample from the output of the oversample and average engine for the channel.
+ *
+ * The value is scaled to units of Volts using the calibrated scaling data from GetLSBWeight() and GetOffset().
+ * Using oversampling will cause this value to be higher resolution, but it will update more slowly.
+ * Using averaging will cause this value to be more stable, but it will update more slowly.
+ *
+ * @param analog_port_pointer Pointer to the analog port to use.
+ * @return A scaled sample from the output of the oversample and average engine for the channel.
+ */
+float getAnalogAverageVoltage(void* analog_port_pointer, int32_t *status) {
+  int32_t value = getAnalogAverageValue(analog_port_pointer, status);
+  uint32_t LSBWeight = getAnalogLSBWeight(analog_port_pointer, status);
+  int32_t offset = getAnalogOffset(analog_port_pointer, status);
+  uint32_t oversampleBits = getAnalogOversampleBits(analog_port_pointer, status);
+  float voltage = ((LSBWeight * 1.0e-9 * value) / (float)(1 << oversampleBits)) - offset * 1.0e-9;
+  return voltage;
+}
+
+/**
+ * Convert a voltage to a raw value for a specified channel.
+ *
+ * This process depends on the calibration of each channel, so the channel
+ * must be specified.
+ *
+ * @todo This assumes raw values.  Oversampling not supported as is.
+ *
+ * @param analog_port_pointer Pointer to the analog port to use.
+ * @param voltage The voltage to convert.
+ * @return The raw value for the channel.
+ */
+int32_t getAnalogVoltsToValue(void* analog_port_pointer, double voltage, int32_t *status) {
+  if (voltage > 5.0) {
+    voltage = 5.0;
+    *status = VOLTAGE_OUT_OF_RANGE;
+  }
+  if (voltage < 0.0) {
+    voltage = 0.0;
+    *status = VOLTAGE_OUT_OF_RANGE;
+  }
+  uint32_t LSBWeight = getAnalogLSBWeight(analog_port_pointer, status);
+  int32_t offset = getAnalogOffset(analog_port_pointer, status);
+  int32_t value = (int32_t) ((voltage + offset * 1.0e-9) / (LSBWeight * 1.0e-9));
+  return value;
+}
+
+/**
+ * Get the factory scaling least significant bit weight constant.
+ * The least significant bit weight constant for the channel that was calibrated in
+ * manufacturing and stored in an eeprom in the module.
+ *
+ * Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9)
+ *
+ * @param analog_port_pointer Pointer to the analog port to use.
+ * @return Least significant bit weight.
+ */
+uint32_t getAnalogLSBWeight(void* analog_port_pointer, int32_t *status) {
+  AnalogPort* port = (AnalogPort*) analog_port_pointer;
+  uint32_t lsbWeight = FRC_NetworkCommunication_nAICalibration_getLSBWeight(0, port->port.pin, status); // XXX: aiSystemIndex == 0?
+  return lsbWeight;
+}
+
+/**
+ * Get the factory scaling offset constant.
+ * The offset constant for the channel that was calibrated in manufacturing and stored
+ * in an eeprom in the module.
+ *
+ * Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9)
+ *
+ * @param analog_port_pointer Pointer to the analog port to use.
+ * @return Offset constant.
+ */
+int32_t getAnalogOffset(void* analog_port_pointer, int32_t *status) {
+  AnalogPort* port = (AnalogPort*) analog_port_pointer;
+  int32_t offset = FRC_NetworkCommunication_nAICalibration_getOffset(0, port->port.pin, status); // XXX: aiSystemIndex == 0?
+  return offset;
+}
+
+
+/**
+ * Return the number of channels on the module in use.
+ *
+ * @return Active channels.
+ */
+uint32_t getAnalogNumActiveChannels(int32_t *status) {
+  uint32_t scanSize = analogInputSystem->readConfig_ScanSize(status);
+  if (scanSize == 0)
+    return 8;
+  return scanSize;
+}
+
+/**
+ * Get the number of active channels.
+ *
+ * This is an internal function to allow the atomic update of both the
+ * number of active channels and the sample rate.
+ *
+ * When the number of channels changes, use the new value.  Otherwise,
+ * return the curent value.
+ *
+ * @return Value to write to the active channels field.
+ */
+uint32_t getAnalogNumChannelsToActivate(int32_t *status) {
+  if(analogNumChannelsToActivate == 0) return getAnalogNumActiveChannels(status);
+  return analogNumChannelsToActivate;
+}
+
+/**
+ * Set the number of active channels.
+ *
+ * Store the number of active channels to set.  Don't actually commit to hardware
+ * until SetSampleRate().
+ *
+ * @param channels Number of active channels.
+ */
+void setAnalogNumChannelsToActivate(uint32_t channels) {
+  analogNumChannelsToActivate = channels;
+}
+
+//// Accumulator Stuff
+
+/**
+ * Is the channel attached to an accumulator.
+ *
+ * @return The analog channel is attached to an accumulator.
+ */
+bool isAccumulatorChannel(void* analog_port_pointer, int32_t *status) {
+  AnalogPort* port = (AnalogPort*) analog_port_pointer;
+  for (uint32_t i=0; i < kAccumulatorNumChannels; i++) {
+    if (port->port.pin == kAccumulatorChannels[i]) return true;
+  }
+  return false;
+}
+
+/**
+ * Initialize the accumulator.
+ */
+void initAccumulator(void* analog_port_pointer, int32_t *status) {
+  setAccumulatorCenter(analog_port_pointer, 0, status);
+  resetAccumulator(analog_port_pointer, status);
+}
+
+/**
+ * Resets the accumulator to the initial value.
+ */
+void resetAccumulator(void* analog_port_pointer, int32_t *status) {
+  AnalogPort* port = (AnalogPort*) analog_port_pointer;
+  if (port->accumulator == NULL) {
+    *status = NULL_PARAMETER;
+    return;
+  }
+  port->accumulator->strobeReset(status);
+}
+
+/**
+ * Set the center value of the accumulator.
+ *
+ * The center value is subtracted from each A/D value before it is added to the accumulator. This
+ * is used for the center value of devices like gyros and accelerometers to make integration work
+ * and to take the device offset into account when integrating.
+ *
+ * This center value is based on the output of the oversampled and averaged source from channel 1.
+ * Because of this, any non-zero oversample bits will affect the size of the value for this field.
+ */
+void setAccumulatorCenter(void* analog_port_pointer, int32_t center, int32_t *status) {
+  AnalogPort* port = (AnalogPort*) analog_port_pointer;
+  if (port->accumulator == NULL) {
+    *status = NULL_PARAMETER;
+    return;
+  }
+  port->accumulator->writeCenter(center, status);
+}
+
+/**
+ * Set the accumulator's deadband.
+ */
+void setAccumulatorDeadband(void* analog_port_pointer, int32_t deadband, int32_t *status) {
+  AnalogPort* port = (AnalogPort*) analog_port_pointer;
+  if (port->accumulator == NULL) {
+    *status = NULL_PARAMETER;
+    return;
+  }
+  port->accumulator->writeDeadband(deadband, status);
+}
+
+/**
+ * Read the accumulated value.
+ *
+ * Read the value that has been accumulating on channel 1.
+ * The accumulator is attached after the oversample and average engine.
+ *
+ * @return The 64-bit value accumulated since the last Reset().
+ */
+int64_t getAccumulatorValue(void* analog_port_pointer, int32_t *status) {
+  AnalogPort* port = (AnalogPort*) analog_port_pointer;
+  if (port->accumulator == NULL) {
+    *status = NULL_PARAMETER;
+    return 0;
+  }
+  int64_t value = port->accumulator->readOutput_Value(status);
+  return value;
+}
+
+/**
+ * Read the number of accumulated values.
+ *
+ * Read the count of the accumulated values since the accumulator was last Reset().
+ *
+ * @return The number of times samples from the channel were accumulated.
+ */
+uint32_t getAccumulatorCount(void* analog_port_pointer, int32_t *status) {
+  AnalogPort* port = (AnalogPort*) analog_port_pointer;
+  if (port->accumulator == NULL) {
+    *status = NULL_PARAMETER;
+    return 0;
+  }
+  return port->accumulator->readOutput_Count(status);
+}
+
+/**
+ * Read the accumulated value and the number of accumulated values atomically.
+ *
+ * This function reads the value and count from the FPGA atomically.
+ * This can be used for averaging.
+ *
+ * @param value Pointer to the 64-bit accumulated output.
+ * @param count Pointer to the number of accumulation cycles.
+ */
+void getAccumulatorOutput(void* analog_port_pointer, int64_t *value, uint32_t *count, int32_t *status) {
+  AnalogPort* port = (AnalogPort*) analog_port_pointer;
+  if (port->accumulator == NULL) {
+    *status = NULL_PARAMETER;
+    return;
+  }
+  if (value == NULL || count == NULL) {
+    *status = NULL_PARAMETER;
+    return;
+  }
+
+  tAccumulator::tOutput output = port->accumulator->readOutput(status);
+
+  *value = output.Value;
+  *count = output.Count;
+}
+
+
+struct trigger_t {
+  tAnalogTrigger* trigger;
+  AnalogPort* port;
+  uint32_t index;
+};
+typedef struct trigger_t AnalogTrigger;
+
+static Resource *triggers = NULL;
+
+void* initializeAnalogTrigger(void* port_pointer, uint32_t *index, int32_t *status) {
+  Port* port = (Port*) port_pointer;
+  Resource::CreateResourceObject(&triggers, tAnalogTrigger::kNumSystems);
+
+  AnalogTrigger* trigger = new AnalogTrigger();
+  trigger->port = (AnalogPort*) initializeAnalogInputPort(port, status);
+  trigger->index = triggers->Allocate("Analog Trigger");
+  *index = trigger->index;
+  // TODO: if (index == ~0ul) { CloneError(triggers); return; }
+
+  trigger->trigger = tAnalogTrigger::create(trigger->index, status);
+  trigger->trigger->writeSourceSelect_Channel(port->pin, status);
+
+  return trigger;
+}
+
+void cleanAnalogTrigger(void* analog_trigger_pointer, int32_t *status) {
+  AnalogTrigger* trigger = (AnalogTrigger*) analog_trigger_pointer;
+  triggers->Free(trigger->index);
+  delete trigger->trigger;
+  delete trigger;
+}
+
+void setAnalogTriggerLimitsRaw(void* analog_trigger_pointer, int32_t lower, int32_t upper, int32_t *status) {
+  AnalogTrigger* trigger = (AnalogTrigger*) analog_trigger_pointer;
+  if (lower > upper) {
+	*status = ANALOG_TRIGGER_LIMIT_ORDER_ERROR;
+  }
+  trigger->trigger->writeLowerLimit(lower, status);
+  trigger->trigger->writeUpperLimit(upper, status);
+}
+
+/**
+ * Set the upper and lower limits of the analog trigger.
+ * The limits are given as floating point voltage values.
+ */
+void setAnalogTriggerLimitsVoltage(void* analog_trigger_pointer, double lower, double upper, int32_t *status) {
+  AnalogTrigger* trigger = (AnalogTrigger*) analog_trigger_pointer;
+  if (lower > upper) {
+	*status = ANALOG_TRIGGER_LIMIT_ORDER_ERROR;
+  }
+  // TODO: This depends on the averaged setting.  Only raw values will work as is.
+  trigger->trigger->writeLowerLimit(getAnalogVoltsToValue(trigger->port, lower, status), status);
+  trigger->trigger->writeUpperLimit(getAnalogVoltsToValue(trigger->port, upper, status), status);
+}
+
+/**
+ * Configure the analog trigger to use the averaged vs. raw values.
+ * If the value is true, then the averaged value is selected for the analog trigger, otherwise
+ * the immediate value is used.
+ */
+void setAnalogTriggerAveraged(void* analog_trigger_pointer, bool useAveragedValue, int32_t *status) {
+  AnalogTrigger* trigger = (AnalogTrigger*) analog_trigger_pointer;
+  if (trigger->trigger->readSourceSelect_Filter(status) != 0) {
+	*status = INCOMPATIBLE_STATE;
+	// TODO: wpi_setWPIErrorWithContext(IncompatibleMode, "Hardware does not support average and filtering at the same time.");
+  }
+  trigger->trigger->writeSourceSelect_Averaged(useAveragedValue, status);
+}
+
+/**
+ * Configure the analog trigger to use a filtered value.
+ * The analog trigger will operate with a 3 point average rejection filter. This is designed to
+ * help with 360 degree pot applications for the period where the pot crosses through zero.
+ */
+void setAnalogTriggerFiltered(void* analog_trigger_pointer, bool useFilteredValue, int32_t *status) {
+  AnalogTrigger* trigger = (AnalogTrigger*) analog_trigger_pointer;
+  if (trigger->trigger->readSourceSelect_Averaged(status) != 0) {
+	*status = INCOMPATIBLE_STATE;
+	// TODO: wpi_setWPIErrorWithContext(IncompatibleMode, "Hardware does not support average and filtering at the same time.");
+  }
+  trigger->trigger->writeSourceSelect_Filter(useFilteredValue, status);
+}
+
+/**
+ * Return the InWindow output of the analog trigger.
+ * True if the analog input is between the upper and lower limits.
+ * @return The InWindow output of the analog trigger.
+ */
+bool getAnalogTriggerInWindow(void* analog_trigger_pointer, int32_t *status) {
+  AnalogTrigger* trigger = (AnalogTrigger*) analog_trigger_pointer;
+  return trigger->trigger->readOutput_InHysteresis(trigger->index, status) != 0;
+}
+
+/**
+ * Return the TriggerState output of the analog trigger.
+ * True if above upper limit.
+ * False if below lower limit.
+ * If in Hysteresis, maintain previous state.
+ * @return The TriggerState output of the analog trigger.
+ */
+bool getAnalogTriggerTriggerState(void* analog_trigger_pointer, int32_t *status) {
+  AnalogTrigger* trigger = (AnalogTrigger*) analog_trigger_pointer;
+  return trigger->trigger->readOutput_OverLimit(trigger->index, status) != 0;
+}
+
+/**
+ * Get the state of the analog trigger output.
+ * @return The state of the analog trigger output.
+ */
+bool getAnalogTriggerOutput(void* analog_trigger_pointer, AnalogTriggerType type, int32_t *status) {
+  AnalogTrigger* trigger = (AnalogTrigger*) analog_trigger_pointer;
+  bool result = false;
+  switch(type) {
+  case kInWindow:
+	result = trigger->trigger->readOutput_InHysteresis(trigger->index, status);
+	break; // XXX: Backport
+  case kState:
+	result = trigger->trigger->readOutput_OverLimit(trigger->index, status);
+	break; // XXX: Backport
+  case kRisingPulse:
+  case kFallingPulse:
+	*status = ANALOG_TRIGGER_PULSE_OUTPUT_ERROR;
+	return false;
+  }
+  return result;
+}
+
+
+
+//// Float JNA Hack
+// Float
+int getAnalogSampleRateIntHack(int32_t *status) {
+  return floatToInt(getAnalogSampleRate(status));
+}
+
+int getAnalogVoltageIntHack(void* analog_port_pointer, int32_t *status) {
+  return floatToInt(getAnalogVoltage(analog_port_pointer, status));
+}
+
+int getAnalogAverageVoltageIntHack(void* analog_port_pointer, int32_t *status) {
+  return floatToInt(getAnalogAverageVoltage(analog_port_pointer, status));
+}
+
+
+// Doubles
+void setAnalogSampleRateIntHack(int samplesPerSecond, int32_t *status) {
+  setAnalogSampleRate(intToFloat(samplesPerSecond), status);
+}
+
+int32_t getAnalogVoltsToValueIntHack(void* analog_port_pointer, int voltage, int32_t *status) {
+  return getAnalogVoltsToValue(analog_port_pointer, intToFloat(voltage), status);
+}
+
+void setAnalogTriggerLimitsVoltageIntHack(void* analog_trigger_pointer, int lower, int upper, int32_t *status) {
+  setAnalogTriggerLimitsVoltage(analog_trigger_pointer, intToFloat(lower), intToFloat(upper), status);
+}
diff --git a/aos/externals/allwpilib/hal/lib/Athena/ChipObject.h b/aos/externals/allwpilib/hal/lib/Athena/ChipObject.h
new file mode 100644
index 0000000..630c34d
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/ChipObject.h
@@ -0,0 +1,43 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+#pragma GCC diagnostic ignored "-Wignored-qualifiers"
+
+#include <stdint.h>
+
+#include "FRC_FPGA_ChipObject/RoboRIO_FRC_ChipObject_Aliases.h"
+#include "FRC_FPGA_ChipObject/tDMAChannelDescriptor.h"
+#include "FRC_FPGA_ChipObject/tDMAManager.h"
+#include "FRC_FPGA_ChipObject/tInterruptManager.h"
+#include "FRC_FPGA_ChipObject/tSystem.h"
+#include "FRC_FPGA_ChipObject/tSystemInterface.h"
+
+#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/nInterfaceGlobals.h"
+#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAccel.h"
+#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAccumulator.h"
+#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAI.h"
+#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAlarm.h"
+#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAnalogTrigger.h"
+#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAO.h"
+#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tBIST.h"
+#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tCounter.h"
+#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tDIO.h"
+#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tDMA.h"
+#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tEncoder.h"
+#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tGlobal.h"
+#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tInterrupt.h"
+#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tPower.h"
+#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tPWM.h"
+#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tRelay.h"
+#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tSPI.h"
+#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tSysWatchdog.h"
+
+// FIXME: these should not be here!
+using namespace nFPGA;
+using namespace nRoboRIO_FPGANamespace;
+#pragma GCC diagnostic pop
diff --git a/aos/externals/allwpilib/hal/lib/Athena/Compressor.cpp b/aos/externals/allwpilib/hal/lib/Athena/Compressor.cpp
new file mode 100644
index 0000000..9305097
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/Compressor.cpp
@@ -0,0 +1,116 @@
+#include "HAL/Compressor.hpp"
+#include "ctre/PCM.h"
+#include <iostream>
+
+static const int NUM_MODULE_NUMBERS = 63;
+extern PCM *modules[NUM_MODULE_NUMBERS];
+extern void initializePCM(int module);
+
+void *initializeCompressor(uint8_t module) {
+	initializePCM(module);
+	
+	return modules[module];
+}
+
+bool checkCompressorModule(uint8_t module) {
+	return module < NUM_MODULE_NUMBERS;
+}
+
+bool getCompressor(void *pcm_pointer, int32_t *status) {
+	PCM *module = (PCM *)pcm_pointer;
+	bool value;
+	
+	*status = module->GetCompressor(value);
+	
+	return value;
+}
+
+
+void setClosedLoopControl(void *pcm_pointer, bool value, int32_t *status) {
+	PCM *module = (PCM *)pcm_pointer;
+	
+	*status = module->SetClosedLoopControl(value);
+}
+
+
+bool getClosedLoopControl(void *pcm_pointer, int32_t *status) {
+	PCM *module = (PCM *)pcm_pointer;
+	bool value;
+	
+	*status = module->GetClosedLoopControl(value);
+	
+	return value;
+}
+
+
+bool getPressureSwitch(void *pcm_pointer, int32_t *status) {
+	PCM *module = (PCM *)pcm_pointer;
+	bool value;
+	
+	*status = module->GetPressure(value);
+	
+	return value;
+}
+
+
+float getCompressorCurrent(void *pcm_pointer, int32_t *status) {
+	PCM *module = (PCM *)pcm_pointer;
+	float value;
+	
+	*status = module->GetCompressorCurrent(value);
+	
+	return value;
+}
+bool getCompressorCurrentTooHighFault(void *pcm_pointer, int32_t *status) {
+	PCM *module = (PCM *)pcm_pointer;
+	bool value;
+	
+	*status = module->GetCompressorCurrentTooHighFault(value);
+	
+	return value;
+}
+bool getCompressorCurrentTooHighStickyFault(void *pcm_pointer, int32_t *status) {
+	PCM *module = (PCM *)pcm_pointer;
+	bool value;
+	
+	*status = module->GetCompressorCurrentTooHighStickyFault(value);
+	
+	return value;
+}
+bool getCompressorShortedStickyFault(void *pcm_pointer, int32_t *status) {
+	PCM *module = (PCM *)pcm_pointer;
+	bool value;
+	
+	*status = module->GetCompressorShortedStickyFault(value);
+	
+	return value;
+}
+bool getCompressorShortedFault(void *pcm_pointer, int32_t *status) {
+	PCM *module = (PCM *)pcm_pointer;
+	bool value;
+	
+	*status = module->GetCompressorShortedFault(value);
+	
+	return value;
+}
+bool getCompressorNotConnectedStickyFault(void *pcm_pointer, int32_t *status) {
+	PCM *module = (PCM *)pcm_pointer;
+	bool value;
+	
+	*status = module->GetCompressorNotConnectedStickyFault(value);
+	
+	return value;
+}
+bool getCompressorNotConnectedFault(void *pcm_pointer, int32_t *status) {
+	PCM *module = (PCM *)pcm_pointer;
+	bool value;
+	
+	*status = module->GetCompressorNotConnectedFault(value);
+	
+	return value;
+}
+void clearAllPCMStickyFaults(void *pcm_pointer, int32_t *status) {
+	PCM *module = (PCM *)pcm_pointer;
+	
+	*status = module->ClearStickyFaults();
+}
diff --git a/aos/externals/allwpilib/hal/lib/Athena/Digital.cpp b/aos/externals/allwpilib/hal/lib/Athena/Digital.cpp
new file mode 100644
index 0000000..3daaf09
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/Digital.cpp
@@ -0,0 +1,1563 @@
+
+#include "HAL/Digital.hpp"
+
+#include "Port.h"
+#include "HAL/HAL.hpp"
+#include "ChipObject.h"
+#include "HAL/cpp/Synchronized.hpp"
+#include "HAL/cpp/Resource.hpp"
+#include "NetworkCommunication/LoadOut.h"
+#include <stdio.h>
+#include <math.h>
+#include "i2clib/i2c-lib.h"
+#include "spilib/spi-lib.h"
+
+static const uint32_t kExpectedLoopTiming = 40;
+static const uint32_t kDigitalPins = 26;
+static const uint32_t kPwmPins = 20;
+static const uint32_t kRelayPins = 8;
+static const uint32_t kNumHeaders = 10; // Number of non-MXP pins
+
+ReentrantMutex& spiGetSemaphore(uint8_t port);
+
+/**
+ * kDefaultPwmPeriod is in ms
+ *
+ * - 20ms periods (50 Hz) are the "safest" setting in that this works for all devices
+ * - 20ms periods seem to be desirable for Vex Motors
+ * - 20ms periods are the specified period for HS-322HD servos, but work reliably down
+ *      to 10.0 ms; starting at about 8.5ms, the servo sometimes hums and get hot;
+ *      by 5.0ms the hum is nearly continuous
+ * - 10ms periods work well for Victor 884
+ * - 5ms periods allows higher update rates for Luminary Micro Jaguar speed controllers.
+ *      Due to the shipping firmware on the Jaguar, we can't run the update period less
+ *      than 5.05 ms.
+ *
+ * kDefaultPwmPeriod is the 1x period (5.05 ms).  In hardware, the period scaling is implemented as an
+ * output squelch to get longer periods for old devices.
+ */
+static const float kDefaultPwmPeriod = 5.05;
+/**
+ * kDefaultPwmCenter is the PWM range center in ms
+ */
+static const float kDefaultPwmCenter = 1.5;
+/**
+ * kDefaultPWMStepsDown is the number of PWM steps below the centerpoint
+ */
+static const int32_t kDefaultPwmStepsDown = 1000;
+static const int32_t kPwmDisabled = 0;
+
+struct DigitalPort {
+  Port port;
+  uint32_t PWMGeneratorID;
+};
+
+// XXX: Set these back to static once we figure out the memory clobbering issue
+// Create a semaphore to protect changes to the digital output values
+ReentrantMutex digitalDIOSemaphore;
+// Create a semaphore to protect changes to the relay values
+ReentrantMutex digitalRelaySemaphore;
+// Create a semaphore to protect changes to the DO PWM config
+ReentrantMutex digitalPwmSemaphore;
+ReentrantMutex digitalI2COnBoardSemaphore;
+ReentrantMutex digitalI2CMXPSemaphore;
+
+tDIO* digitalSystem = NULL;
+tRelay* relaySystem = NULL;
+tPWM* pwmSystem = NULL;
+Resource *DIOChannels = NULL;
+Resource *DO_PWMGenerators = NULL;
+Resource *PWMChannels = NULL;
+
+bool digitalSystemsInitialized = false;
+
+uint8_t i2COnboardObjCount = 0;
+uint8_t i2CMXPObjCount = 0;
+uint8_t i2COnBoardHandle = 0;
+uint8_t i2CMXPHandle = 0;
+
+int32_t m_spiCS0Handle = 0;
+int32_t m_spiCS1Handle = 0;
+int32_t m_spiCS2Handle = 0;
+int32_t m_spiCS3Handle = 0;
+int32_t m_spiMXPHandle = 0;
+ReentrantMutex spiOnboardSemaphore;
+ReentrantMutex spiMXPSemaphore;
+tSPI *spiSystem;
+
+/**
+ * Initialize the digital system.
+ */
+void initializeDigital(int32_t *status) {
+  if (digitalSystemsInitialized) return;
+
+  Resource::CreateResourceObject(&DIOChannels, tDIO::kNumSystems * kDigitalPins);
+  Resource::CreateResourceObject(&DO_PWMGenerators, tDIO::kNumPWMDutyCycleAElements + tDIO::kNumPWMDutyCycleBElements);
+  Resource::CreateResourceObject(&PWMChannels, tPWM::kNumSystems * kPwmPins);
+  digitalSystem = tDIO::create(status);
+
+  // Relay Setup
+  relaySystem = tRelay::create(status);
+
+  // Turn off all relay outputs.
+  relaySystem->writeValue_Forward(0, status);
+  relaySystem->writeValue_Reverse(0, status);
+
+  // PWM Setup
+  pwmSystem = tPWM::create(status);
+
+  // Make sure that the 9403 IONode has had a chance to initialize before continuing.
+  while(pwmSystem->readLoopTiming(status) == 0) delayTicks(1);
+
+  if (pwmSystem->readLoopTiming(status) != kExpectedLoopTiming) {
+	// TODO: char err[128];
+	// TODO: sprintf(err, "DIO LoopTiming: %d, expecting: %lu\n", digitalModules[port->module-1]->readLoopTiming(status), kExpectedLoopTiming);
+	*status = LOOP_TIMING_ERROR; // NOTE: Doesn't display the error
+  }
+
+  //Calculate the length, in ms, of one DIO loop
+  double loopTime = pwmSystem->readLoopTiming(status)/(kSystemClockTicksPerMicrosecond*1e3);
+
+  pwmSystem->writeConfig_Period((uint16_t) (kDefaultPwmPeriod/loopTime + .5), status);
+  uint16_t minHigh = (uint16_t) ((kDefaultPwmCenter-kDefaultPwmStepsDown*loopTime)/loopTime + .5);
+  pwmSystem->writeConfig_MinHigh(minHigh, status);
+//  printf("MinHigh: %d\n", minHigh);
+  // Ensure that PWM output values are set to OFF
+  for (uint32_t pwm_index = 0; pwm_index < kPwmPins; pwm_index++) {
+    // Initialize port structure
+    DigitalPort* digital_port = new DigitalPort();
+    digital_port->port.pin = pwm_index;
+
+    setPWM(digital_port, kPwmDisabled, status);
+    setPWMPeriodScale(digital_port, 3, status); // Set all to 4x by default.
+  }
+
+  digitalSystemsInitialized = true;
+}
+
+/**
+ * Create a new instance of a digital port.
+ */
+void* initializeDigitalPort(void* port_pointer, int32_t *status) {
+  initializeDigital(status);
+  Port* port = (Port*) port_pointer;
+
+  // Initialize port structure
+  DigitalPort* digital_port = new DigitalPort();
+  digital_port->port = *port;
+
+  return digital_port;
+}
+
+bool checkPWMChannel(void* digital_port_pointer) {
+  DigitalPort* port = (DigitalPort*) digital_port_pointer;
+  return port->port.pin < kPwmPins;
+}
+
+bool checkRelayChannel(void* digital_port_pointer) {
+  DigitalPort* port = (DigitalPort*) digital_port_pointer;
+  return port->port.pin < kRelayPins;
+}
+
+/**
+ * Map DIO pin numbers from their physical number (10 to 26) to their position
+ * in the bit field.
+ */
+uint32_t remapMXPChannel(uint32_t pin) {
+    return pin - 10;
+}
+
+uint32_t remapMXPPWMChannel(uint32_t pin) {
+	if(pin < 14) {
+		return pin - 10;	//first block of 4 pwms (MXP 0-3)
+	} else {
+		return pin - 6;	//block of PWMs after SPI
+	}
+}
+
+/**
+ * Set a PWM channel to the desired value. The values range from 0 to 255 and the period is controlled
+ * by the PWM Period and MinHigh registers.
+ *
+ * @param channel The PWM channel to set.
+ * @param value The PWM value to set.
+ */
+void setPWM(void* digital_port_pointer, unsigned short value, int32_t *status) {
+  DigitalPort* port = (DigitalPort*) digital_port_pointer;
+  checkPWMChannel(port);
+
+  if(port->port.pin < tPWM::kNumHdrRegisters) {
+    pwmSystem->writeHdr(port->port.pin, value, status);
+  } else {
+    pwmSystem->writeMXP(port->port.pin - tPWM::kNumHdrRegisters, value, status);
+  }
+}
+
+/**
+ * Get a value from a PWM channel. The values range from 0 to 255.
+ *
+ * @param channel The PWM channel to read from.
+ * @return The raw PWM value.
+ */
+unsigned short getPWM(void* digital_port_pointer, int32_t *status) {
+  DigitalPort* port = (DigitalPort*) digital_port_pointer;
+  checkPWMChannel(port);
+
+  if(port->port.pin < tPWM::kNumHdrRegisters) {
+    return pwmSystem->readHdr(port->port.pin, status);
+  } else {
+    return pwmSystem->readMXP(port->port.pin - tPWM::kNumHdrRegisters, status);
+  }
+}
+
+void latchPWMZero(void* digital_port_pointer, int32_t *status) {
+	DigitalPort* port = (DigitalPort*) digital_port_pointer;
+	pwmSystem->writeZeroLatch(port->port.pin, true, status);
+	pwmSystem->writeZeroLatch(port->port.pin, false, status);
+}
+
+/**
+ * Set how how often the PWM signal is squelched, thus scaling the period.
+ *
+ * @param channel The PWM channel to configure.
+ * @param squelchMask The 2-bit mask of outputs to squelch.
+ */
+void setPWMPeriodScale(void* digital_port_pointer, uint32_t squelchMask, int32_t *status) {
+  DigitalPort* port = (DigitalPort*) digital_port_pointer;
+  checkPWMChannel(port);
+
+  if(port->port.pin < tPWM::kNumPeriodScaleHdrElements) {
+    pwmSystem->writePeriodScaleHdr(port->port.pin, squelchMask, status);
+  } else {
+    pwmSystem->writePeriodScaleMXP(port->port.pin - tPWM::kNumPeriodScaleHdrElements, squelchMask, status);
+  }
+}
+
+/**
+ * Allocate a DO PWM Generator.
+ * Allocate PWM generators so that they are not accidentally reused.
+ *
+ * @return PWM Generator refnum
+ */
+void* allocatePWM(int32_t *status) {
+  return (void*)DO_PWMGenerators->Allocate("DO_PWM");
+}
+
+/**
+ * Free the resource associated with a DO PWM generator.
+ *
+ * @param pwmGenerator The pwmGen to free that was allocated with AllocateDO_PWM()
+ */
+void freePWM(void* pwmGenerator, int32_t *status) {
+  uint32_t id = (uint32_t) pwmGenerator;
+  if (id == ~0ul) return;
+  DO_PWMGenerators->Free(id);
+}
+
+/**
+ * Change the frequency of the DO PWM generator.
+ *
+ * The valid range is from 0.6 Hz to 19 kHz.  The frequency resolution is logarithmic.
+ *
+ * @param rate The frequency to output all digital output PWM signals.
+ */
+void setPWMRate(double rate, int32_t *status) {
+  // Currently rounding in the log rate domain... heavy weight toward picking a higher freq.
+  // TODO: Round in the linear rate domain.
+  uint8_t pwmPeriodPower = (uint8_t)(log(1.0 / (pwmSystem->readLoopTiming(status) * 0.25E-6 * rate))/log(2.0) + 0.5);
+  digitalSystem->writePWMPeriodPower(pwmPeriodPower, status);
+}
+
+
+/**
+ * Configure the duty-cycle of the PWM generator
+ *
+ * @param pwmGenerator The generator index reserved by AllocateDO_PWM()
+ * @param dutyCycle The percent duty cycle to output [0..1].
+ */
+void setPWMDutyCycle(void* pwmGenerator, double dutyCycle, int32_t *status) {
+  uint32_t id = (uint32_t) pwmGenerator;
+  if (id == ~0ul) return;
+  if (dutyCycle > 1.0) dutyCycle = 1.0;
+  if (dutyCycle < 0.0) dutyCycle = 0.0;
+  float rawDutyCycle = 256.0 * dutyCycle;
+  if (rawDutyCycle > 255.5) rawDutyCycle = 255.5;
+  {
+    ::std::unique_lock<ReentrantMutex> sync(digitalPwmSemaphore);
+    uint8_t pwmPeriodPower = digitalSystem->readPWMPeriodPower(status);
+    if (pwmPeriodPower < 4) {
+	  // The resolution of the duty cycle drops close to the highest frequencies.
+	  rawDutyCycle = rawDutyCycle / pow(2.0, 4 - pwmPeriodPower);
+	}
+	if(id < 4)
+		digitalSystem->writePWMDutyCycleA(id, (uint8_t)rawDutyCycle, status);
+	else 
+		digitalSystem->writePWMDutyCycleB(id - 4, (uint8_t)rawDutyCycle, status);
+  }
+}
+
+/**
+ * Configure which DO channel the PWM signal is output on
+ *
+ * @param pwmGenerator The generator index reserved by AllocateDO_PWM()
+ * @param channel The Digital Output channel to output on
+ */
+void setPWMOutputChannel(void* pwmGenerator, uint32_t pin, int32_t *status) {
+  uint32_t id = (uint32_t) pwmGenerator;
+  if (id > 5) return;
+  digitalSystem->writePWMOutputSelect(id, pin, status);
+}
+
+/**
+ * Set the state of a relay.
+ * Set the state of a relay output to be forward. Relays have two outputs and each is
+ * independently set to 0v or 12v.
+ */
+void setRelayForward(void* digital_port_pointer, bool on, int32_t *status) {
+  DigitalPort* port = (DigitalPort*) digital_port_pointer;
+  checkRelayChannel(port);
+  {
+    ::std::unique_lock<ReentrantMutex> sync(digitalRelaySemaphore);
+    uint8_t forwardRelays = relaySystem->readValue_Forward(status);
+    if (on)
+      forwardRelays |= 1 << port->port.pin;
+    else
+      forwardRelays &= ~(1 << port->port.pin);
+    relaySystem->writeValue_Forward(forwardRelays, status);
+  }
+}
+
+/**
+ * Set the state of a relay.
+ * Set the state of a relay output to be reverse. Relays have two outputs and each is
+ * independently set to 0v or 12v.
+ */
+void setRelayReverse(void* digital_port_pointer, bool on, int32_t *status) {
+  DigitalPort* port = (DigitalPort*) digital_port_pointer;
+  checkRelayChannel(port);
+  {
+    ::std::unique_lock<ReentrantMutex> sync(digitalRelaySemaphore);
+    uint8_t reverseRelays = relaySystem->readValue_Reverse(status);
+    if (on)
+      reverseRelays |= 1 << port->port.pin;
+    else
+      reverseRelays &= ~(1 << port->port.pin);
+    relaySystem->writeValue_Reverse(reverseRelays, status);
+  }
+}
+
+/**
+ * Get the current state of the forward relay channel
+ */
+bool getRelayForward(void* digital_port_pointer, int32_t *status) {
+  DigitalPort* port = (DigitalPort*) digital_port_pointer;
+  uint8_t forwardRelays = relaySystem->readValue_Forward(status);
+  return (forwardRelays & (1 << port->port.pin)) != 0;
+}
+
+/**
+ * Get the current state of the reverse relay channel
+ */
+bool getRelayReverse(void* digital_port_pointer, int32_t *status) {
+  DigitalPort* port = (DigitalPort*) digital_port_pointer;
+  uint8_t reverseRelays = relaySystem->readValue_Reverse(status);
+  return (reverseRelays & (1 << port->port.pin)) != 0;
+}
+
+/**
+ * Allocate Digital I/O channels.
+ * Allocate channels so that they are not accidently reused. Also the direction is set at the
+ * time of the allocation.
+ *
+ * @param channel The Digital I/O channel
+ * @param input If true open as input; if false open as output
+ * @return Was successfully allocated
+ */
+bool allocateDIO(void* digital_port_pointer, bool input, int32_t *status) {
+  DigitalPort* port = (DigitalPort*) digital_port_pointer;
+  char buf[64];
+  snprintf(buf, 64, "DIO %d", port->port.pin);
+  if (DIOChannels->Allocate(port->port.pin, buf) == ~0ul) {
+    *status = RESOURCE_IS_ALLOCATED;
+    return false;
+  }
+
+  {
+    ::std::unique_lock<ReentrantMutex> sync(digitalDIOSemaphore);
+
+    tDIO::tOutputEnable outputEnable = digitalSystem->readOutputEnable(status);
+
+    if(port->port.pin < kNumHeaders) {
+      uint32_t bitToSet = 1 << port->port.pin;
+      if (input) {
+        outputEnable.Headers = outputEnable.Headers & (~bitToSet); // clear the bit for read
+      } else {
+        outputEnable.Headers = outputEnable.Headers | bitToSet; // set the bit for write
+      }
+    } else {
+      uint32_t bitToSet = 1 << remapMXPChannel(port->port.pin);
+
+      // Disable special functions on this pin
+      short specialFunctions = digitalSystem->readEnableMXPSpecialFunction(status);
+      digitalSystem->writeEnableMXPSpecialFunction(specialFunctions & ~bitToSet, status);
+
+      if (input) {
+        outputEnable.MXP = outputEnable.MXP & (~bitToSet); // clear the bit for read
+      } else {
+        outputEnable.MXP = outputEnable.MXP | bitToSet; // set the bit for write
+      }
+    }
+
+    digitalSystem->writeOutputEnable(outputEnable, status);
+  }
+  return true;
+}
+
+bool allocatePWMChannel(void* digital_port_pointer, int32_t *status) {
+		DigitalPort* port = (DigitalPort*) digital_port_pointer;
+		char buf[64];
+		snprintf(buf, 64, "PWM %d", port->port.pin);
+		if (PWMChannels->Allocate(port->port.pin, buf) == ~0ul) {
+      *status = RESOURCE_IS_ALLOCATED;
+      return false;
+    }
+
+		if (port->port.pin > tPWM::kNumHdrRegisters-1) {
+			snprintf(buf, 64, "PWM %d and DIO %d", port->port.pin, remapMXPPWMChannel(port->port.pin) + 10);
+			if (DIOChannels->Allocate(remapMXPPWMChannel(port->port.pin) + 10, buf) == ~0ul) return false;
+		    uint32_t bitToSet = 1 << remapMXPPWMChannel(port->port.pin);
+		    short specialFunctions = digitalSystem->readEnableMXPSpecialFunction(status);
+		    digitalSystem->writeEnableMXPSpecialFunction(specialFunctions | bitToSet, status);
+		}
+		return true;
+}
+
+void freePWMChannel(void* digital_port_pointer, int32_t *status) {
+    DigitalPort* port = (DigitalPort*) digital_port_pointer;
+    PWMChannels->Free(port->port.pin);
+    if(port->port.pin > tPWM::kNumHdrRegisters-1) {
+        DIOChannels->Free(remapMXPPWMChannel(port->port.pin) + 10);
+        uint32_t bitToUnset = 1 << remapMXPPWMChannel(port->port.pin);
+        short specialFunctions = digitalSystem->readEnableMXPSpecialFunction(status);
+        digitalSystem->writeEnableMXPSpecialFunction(specialFunctions & ~bitToUnset, status);
+    }
+}
+
+/**
+ * Free the resource associated with a digital I/O channel.
+ *
+ * @param channel The Digital I/O channel to free
+ */
+void freeDIO(void* digital_port_pointer, int32_t *status) {
+  DigitalPort* port = (DigitalPort*) digital_port_pointer;
+  DIOChannels->Free(port->port.pin);
+}
+
+/**
+ * Write a digital I/O bit to the FPGA.
+ * Set a single value on a digital I/O channel.
+ *
+ * @param channel The Digital I/O channel
+ * @param value The state to set the digital channel (if it is configured as an output)
+ */
+void setDIO(void* digital_port_pointer, short value, int32_t *status) {
+  DigitalPort* port = (DigitalPort*) digital_port_pointer;
+  if (value != 0 && value != 1) {
+    if (value != 0)
+      value = 1;
+  }
+  {
+    ::std::unique_lock<ReentrantMutex> sync(digitalDIOSemaphore);
+    tDIO::tDO currentDIO = digitalSystem->readDO(status);
+
+    if(port->port.pin < kNumHeaders) {
+      if(value == 0) {
+        currentDIO.Headers = currentDIO.Headers & ~(1 << port->port.pin);
+      } else if (value == 1) {
+        currentDIO.Headers = currentDIO.Headers | (1 << port->port.pin);
+      }
+    } else {
+      if(value == 0) {
+        currentDIO.MXP = currentDIO.MXP & ~(1 << remapMXPChannel(port->port.pin));
+      } else if (value == 1) {
+        currentDIO.MXP = currentDIO.MXP | (1 << remapMXPChannel(port->port.pin));
+      }
+
+      uint32_t bitToSet = 1 << remapMXPChannel(port->port.pin);
+      short specialFunctions = digitalSystem->readEnableMXPSpecialFunction(status);
+      digitalSystem->writeEnableMXPSpecialFunction(specialFunctions & ~bitToSet, status);
+    }
+    digitalSystem->writeDO(currentDIO, status);
+  }
+}
+
+/**
+ * Write the filter index from the FPGA.
+ * Set the filter index used to filter out short pulses.
+ *
+ * @param digital_port_pointer The digital I/O channel
+ * @param filter_index The filter index.  Must be between 0 and 3.
+ */
+void setFilterSelect(void* digital_port_pointer, int filter_index,
+                     int32_t* status) {
+  DigitalPort* port = (DigitalPort*)digital_port_pointer;
+  {
+    ::std::unique_lock<ReentrantMutex> sync(digitalDIOSemaphore);
+    if (port->port.pin < kNumHeaders) {
+      digitalSystem->writeFilterSelectHdr(port->port.pin, filter_index, status);
+    } else {
+      digitalSystem->writeFilterSelectMXP(remapMXPChannel(port->port.pin),
+                                          filter_index, status);
+    }
+  }
+}
+
+/**
+ * Read the filter index from the FPGA.
+ * Get the filter index used to filter out short pulses.
+ *
+ * @param digital_port_pointer The digital I/O channel
+ * @return filter_index The filter index.  Must be between 0 and 3.
+ */
+int getFilterSelect(void* digital_port_pointer, int32_t* status) {
+  DigitalPort* port = (DigitalPort*)digital_port_pointer;
+  {
+    ::std::unique_lock<ReentrantMutex> sync(digitalDIOSemaphore);
+    if (port->port.pin < kNumHeaders) {
+      return digitalSystem->readFilterSelectHdr(port->port.pin, status);
+    } else {
+      return digitalSystem->readFilterSelectMXP(remapMXPChannel(port->port.pin),
+                                                status);
+    }
+  }
+}
+
+/**
+ * Set the filter period for the specified filter index.
+ *
+ * Set the filter period in FPGA cycles.  Even though there are 2 different
+ * filter index domains (MXP vs HDR), ignore that distinction for now since it
+ * compilicates the interface.  That can be changed later.
+ *
+ * @param filter_index The filter index, 0 - 2.
+ * @param value The number of cycles that the signal must not transition to be
+ * counted as a transition.
+ */
+void setFilterPeriod(int filter_index, uint32_t value, int32_t* status) {
+  {
+    ::std::unique_lock<ReentrantMutex> sync(digitalDIOSemaphore);
+    digitalSystem->writeFilterPeriodHdr(filter_index, value, status);
+    if (*status == 0) {
+      digitalSystem->writeFilterPeriodMXP(filter_index, value, status);
+    }
+  }
+}
+
+/**
+ * Get the filter period for the specified filter index.
+ *
+ * Get the filter period in FPGA cycles.  Even though there are 2 different
+ * filter index domains (MXP vs HDR), ignore that distinction for now since it
+ * compilicates the interface.  Set status to NiFpga_Status_SoftwareFault if the
+ * filter values miss-match.
+ *
+ * @param filter_index The filter index, 0 - 2.
+ * @param value The number of cycles that the signal must not transition to be
+ * counted as a transition.
+ */
+uint32_t getFilterPeriod(int filter_index, int32_t* status) {
+  uint32_t hdr_period = 0;
+  uint32_t mxp_period = 0;
+  {
+    ::std::unique_lock<ReentrantMutex> sync(digitalDIOSemaphore);
+    hdr_period = digitalSystem->readFilterPeriodHdr(filter_index, status);
+    if (*status == 0) {
+      mxp_period = digitalSystem->readFilterPeriodMXP(filter_index, status);
+    }
+  }
+  if (hdr_period != mxp_period) {
+    printf("Periods %d %d\n", hdr_period, mxp_period);
+    *status = NiFpga_Status_SoftwareFault;
+    return -1;
+  }
+  return hdr_period;
+}
+
+/**
+ * Read a digital I/O bit from the FPGA.
+ * Get a single value from a digital I/O channel.
+ *
+ * @param channel The digital I/O channel
+ * @return The state of the specified channel
+ */
+bool getDIO(void* digital_port_pointer, int32_t *status) {
+  DigitalPort* port = (DigitalPort*) digital_port_pointer;
+  tDIO::tDI currentDIO = digitalSystem->readDI(status);
+  //Shift 00000001 over channel-1 places.
+  //AND it against the currentDIO
+  //if it == 0, then return false
+  //else return true
+
+  if(port->port.pin < kNumHeaders) {
+    return ((currentDIO.Headers >> port->port.pin) & 1) != 0;
+  } else {
+    // Disable special functions
+    uint32_t bitToSet = 1 << remapMXPChannel(port->port.pin);
+    short specialFunctions = digitalSystem->readEnableMXPSpecialFunction(status);
+    digitalSystem->writeEnableMXPSpecialFunction(specialFunctions & ~bitToSet, status);
+
+    return ((currentDIO.MXP >> remapMXPChannel(port->port.pin)) & 1) != 0;
+  }
+}
+
+/**
+ * Read the direction of a the Digital I/O lines
+ * A 1 bit means output and a 0 bit means input.
+ *
+ * @param channel The digital I/O channel
+ * @return The direction of the specified channel
+ */
+bool getDIODirection(void* digital_port_pointer, int32_t *status) {
+  DigitalPort* port = (DigitalPort*) digital_port_pointer;
+  tDIO::tOutputEnable currentOutputEnable = digitalSystem->readOutputEnable(status);
+	//Shift 00000001 over port->port.pin-1 places.
+  //AND it against the currentOutputEnable
+  //if it == 0, then return false
+  //else return true
+
+  if(port->port.pin < kNumHeaders) {
+    return ((currentOutputEnable.Headers >> port->port.pin) & 1) != 0;
+  } else {
+    return ((currentOutputEnable.MXP >> remapMXPChannel(port->port.pin)) & 1) != 0;
+  }
+}
+
+/**
+ * Generate a single pulse.
+ * Write a pulse to the specified digital output channel. There can only be a single pulse going at any time.
+ *
+ * @param channel The Digital Output channel that the pulse should be output on
+ * @param pulseLength The active length of the pulse (in seconds)
+ */
+void pulse(void* digital_port_pointer, double pulseLength, int32_t *status) {
+  DigitalPort* port = (DigitalPort*) digital_port_pointer;
+  tDIO::tPulse pulse;
+
+  if(port->port.pin < kNumHeaders) {
+    pulse.Headers = 1 << port->port.pin;
+  } else {
+    pulse.MXP = 1 << remapMXPChannel(port->port.pin);
+  }
+
+  digitalSystem->writePulseLength((uint8_t)(1.0e9 * pulseLength / (pwmSystem->readLoopTiming(status) * 25)), status);
+  digitalSystem->writePulse(pulse, status);
+}
+
+/**
+ * Check a DIO line to see if it is currently generating a pulse.
+ *
+ * @return A pulse is in progress
+ */
+bool isPulsing(void* digital_port_pointer, int32_t *status) {
+  DigitalPort* port = (DigitalPort*) digital_port_pointer;
+  tDIO::tPulse pulseRegister = digitalSystem->readPulse(status);
+
+  if(port->port.pin < kNumHeaders) {
+    return (pulseRegister.Headers & (1 << port->port.pin)) != 0;
+  } else {
+    return (pulseRegister.MXP & (1 << remapMXPChannel(port->port.pin))) != 0;
+  }
+}
+
+/**
+ * Check if any DIO line is currently generating a pulse.
+ *
+ * @return A pulse on some line is in progress
+ */
+bool isAnyPulsing(int32_t *status) {
+  tDIO::tPulse pulseRegister = digitalSystem->readPulse(status);
+  return pulseRegister.Headers != 0 && pulseRegister.MXP != 0;
+}
+
+struct counter_t {
+  tCounter* counter;
+  uint32_t index;
+};
+typedef struct counter_t Counter;
+
+static Resource *counters = NULL;
+
+void* initializeCounter(Mode mode, uint32_t *index, int32_t *status) {
+	Resource::CreateResourceObject(&counters, tCounter::kNumSystems);
+	*index = counters->Allocate("Counter");
+	if (*index == ~0ul) {
+		*status = NO_AVAILABLE_RESOURCES;
+		return NULL;
+	}
+	Counter* counter = new Counter();
+	counter->counter = tCounter::create(*index, status);
+	counter->counter->writeConfig_Mode(mode, status);
+	counter->counter->writeTimerConfig_AverageSize(1, status);
+	counter->index = *index;
+	return counter;
+}
+
+void freeCounter(void* counter_pointer, int32_t *status) {
+  if (counter_pointer != NULL) {
+	  Counter* counter = (Counter*) counter_pointer;
+	  delete counter->counter;
+	  counters->Free(counter->index);
+  } else {
+	  *status = NULL_PARAMETER;
+  }
+}
+
+void setCounterAverageSize(void* counter_pointer, int32_t size, int32_t *status) {
+  Counter* counter = (Counter*) counter_pointer;
+  counter->counter->writeTimerConfig_AverageSize(size, status);
+}
+
+/**
+ * Set the source object that causes the counter to count up.
+ * Set the up counting DigitalSource.
+ */
+void setCounterUpSource(void* counter_pointer, uint32_t pin, bool analogTrigger, int32_t *status) {
+  Counter* counter = (Counter*) counter_pointer;
+
+  uint8_t module;
+
+  if(pin >= kNumHeaders) {
+    pin = remapMXPChannel(pin);
+    module = 1;
+  } else {
+    module = 0;
+  }
+
+  counter->counter->writeConfig_UpSource_Module(module, status);
+  counter->counter->writeConfig_UpSource_Channel(pin, status);
+  counter->counter->writeConfig_UpSource_AnalogTrigger(analogTrigger, status);
+
+  if(counter->counter->readConfig_Mode(status) == kTwoPulse ||
+	 counter->counter->readConfig_Mode(status) == kExternalDirection) {
+	setCounterUpSourceEdge(counter_pointer, true, false, status);
+  }
+  counter->counter->strobeReset(status);
+}
+
+/**
+ * Set the edge sensitivity on an up counting source.
+ * Set the up source to either detect rising edges or falling edges.
+ */
+void setCounterUpSourceEdge(void* counter_pointer, bool risingEdge, bool fallingEdge, int32_t *status) {
+  Counter* counter = (Counter*) counter_pointer;
+  counter->counter->writeConfig_UpRisingEdge(risingEdge, status);
+  counter->counter->writeConfig_UpFallingEdge(fallingEdge, status);
+}
+
+/**
+ * Disable the up counting source to the counter.
+ */
+void clearCounterUpSource(void* counter_pointer, int32_t *status) {
+  Counter* counter = (Counter*) counter_pointer;
+  counter->counter->writeConfig_UpFallingEdge(false, status);
+  counter->counter->writeConfig_UpRisingEdge(false, status);
+  // Index 0 of digital is always 0.
+  counter->counter->writeConfig_UpSource_Channel(0, status);
+  counter->counter->writeConfig_UpSource_AnalogTrigger(false, status);
+}
+
+/**
+ * Set the source object that causes the counter to count down.
+ * Set the down counting DigitalSource.
+ */
+void setCounterDownSource(void* counter_pointer, uint32_t pin, bool analogTrigger, int32_t *status) {
+  Counter* counter = (Counter*) counter_pointer;
+  unsigned char mode = counter->counter->readConfig_Mode(status);
+  if (mode != kTwoPulse && mode != kExternalDirection) {
+	// TODO: wpi_setWPIErrorWithContext(ParameterOutOfRange, "Counter only supports DownSource in TwoPulse and ExternalDirection modes.");
+	*status = PARAMETER_OUT_OF_RANGE;
+	return;
+  }
+
+  uint8_t module;
+
+  if(pin >= kNumHeaders) {
+    pin = remapMXPChannel(pin);
+    module = 1;
+  } else {
+    module = 0;
+  }
+
+  counter->counter->writeConfig_DownSource_Module(module, status);
+  counter->counter->writeConfig_DownSource_Channel(pin, status);
+  counter->counter->writeConfig_DownSource_AnalogTrigger(analogTrigger, status);
+
+  setCounterDownSourceEdge(counter_pointer, true, false, status);
+  counter->counter->strobeReset(status);
+}
+
+/**
+ * Set the edge sensitivity on a down counting source.
+ * Set the down source to either detect rising edges or falling edges.
+ */
+void setCounterDownSourceEdge(void* counter_pointer, bool risingEdge, bool fallingEdge, int32_t *status) {
+  Counter* counter = (Counter*) counter_pointer;
+  counter->counter->writeConfig_DownRisingEdge(risingEdge, status);
+  counter->counter->writeConfig_DownFallingEdge(fallingEdge, status);
+}
+
+/**
+ * Disable the down counting source to the counter.
+ */
+void clearCounterDownSource(void* counter_pointer, int32_t *status) {
+  Counter* counter = (Counter*) counter_pointer;
+  counter->counter->writeConfig_DownFallingEdge(false, status);
+  counter->counter->writeConfig_DownRisingEdge(false, status);
+  // Index 0 of digital is always 0.
+  counter->counter->writeConfig_DownSource_Channel(0, status);
+  counter->counter->writeConfig_DownSource_AnalogTrigger(false, status);
+}
+
+/**
+ * Set standard up / down counting mode on this counter.
+ * Up and down counts are sourced independently from two inputs.
+ */
+void setCounterUpDownMode(void* counter_pointer, int32_t *status) {
+  Counter* counter = (Counter*) counter_pointer;
+  counter->counter->writeConfig_Mode(kTwoPulse, status);
+}
+
+/**
+ * Set external direction mode on this counter.
+ * Counts are sourced on the Up counter input.
+ * The Down counter input represents the direction to count.
+ */
+void setCounterExternalDirectionMode(void* counter_pointer, int32_t *status) {
+  Counter* counter = (Counter*) counter_pointer;
+  counter->counter->writeConfig_Mode(kExternalDirection, status);
+}
+
+/**
+ * Set Semi-period mode on this counter.
+ * Counts up on both rising and falling edges.
+ */
+void setCounterSemiPeriodMode(void* counter_pointer, bool highSemiPeriod, int32_t *status) {
+  Counter* counter = (Counter*) counter_pointer;
+  counter->counter->writeConfig_Mode(kSemiperiod, status);
+  counter->counter->writeConfig_UpRisingEdge(highSemiPeriod, status);
+  setCounterUpdateWhenEmpty(counter_pointer, false, status);
+}
+
+/**
+ * Configure the counter to count in up or down based on the length of the input pulse.
+ * This mode is most useful for direction sensitive gear tooth sensors.
+ * @param threshold The pulse length beyond which the counter counts the opposite direction.  Units are seconds.
+ */
+void setCounterPulseLengthMode(void* counter_pointer, double threshold, int32_t *status) {
+  Counter* counter = (Counter*) counter_pointer;
+  counter->counter->writeConfig_Mode(kPulseLength, status);
+  counter->counter->writeConfig_PulseLengthThreshold((uint32_t)(threshold * 1.0e6) * kSystemClockTicksPerMicrosecond, status);
+}
+
+/**
+ * Get the Samples to Average which specifies the number of samples of the timer to
+ * average when calculating the period. Perform averaging to account for
+ * mechanical imperfections or as oversampling to increase resolution.
+ * @return SamplesToAverage The number of samples being averaged (from 1 to 127)
+ */
+int32_t getCounterSamplesToAverage(void* counter_pointer, int32_t *status) {
+  Counter* counter = (Counter*) counter_pointer;
+  return counter->counter->readTimerConfig_AverageSize(status);
+}
+
+/**
+ * Set the Samples to Average which specifies the number of samples of the timer to
+ * average when calculating the period. Perform averaging to account for
+ * mechanical imperfections or as oversampling to increase resolution.
+ * @param samplesToAverage The number of samples to average from 1 to 127.
+ */
+void setCounterSamplesToAverage(void* counter_pointer, int samplesToAverage, int32_t *status) {
+  Counter* counter = (Counter*) counter_pointer;
+  if (samplesToAverage < 1 || samplesToAverage > 127) {
+	*status = PARAMETER_OUT_OF_RANGE;
+  }
+  counter->counter->writeTimerConfig_AverageSize(samplesToAverage, status);
+}
+
+/**
+ * Reset the Counter to zero.
+ * Set the counter value to zero. This doesn't effect the running state of the counter, just sets
+ * the current value to zero.
+ */
+void resetCounter(void* counter_pointer, int32_t *status) {
+  Counter* counter = (Counter*) counter_pointer;
+  counter->counter->strobeReset(status);
+}
+
+/**
+ * Read the current counter value.
+ * Read the value at this instant. It may still be running, so it reflects the current value. Next
+ * time it is read, it might have a different value.
+ */
+int32_t getCounter(void* counter_pointer, int32_t *status) {
+  Counter* counter = (Counter*) counter_pointer;
+  int32_t value = counter->counter->readOutput_Value(status);
+  return value;
+}
+
+/*
+ * Get the Period of the most recent count.
+ * Returns the time interval of the most recent count. This can be used for velocity calculations
+ * to determine shaft speed.
+ * @returns The period of the last two pulses in units of seconds.
+ */
+double getCounterPeriod(void* counter_pointer, int32_t *status) {
+  Counter* counter = (Counter*) counter_pointer;
+  tCounter::tTimerOutput output = counter->counter->readTimerOutput(status);
+  double period;
+  if (output.Stalled)	{
+	// Return infinity
+	double zero = 0.0;
+	period = 1.0 / zero;
+  } else {
+	// output.Period is a fixed point number that counts by 2 (24 bits, 25 integer bits)
+	period = (double)(output.Period << 1) / (double)output.Count;
+  }
+  return period * 2.5e-8;  // result * timebase (currently 40ns)
+}
+
+/**
+ * Set the maximum period where the device is still considered "moving".
+ * Sets the maximum period where the device is considered moving. This value is used to determine
+ * the "stopped" state of the counter using the GetStopped method.
+ * @param maxPeriod The maximum period where the counted device is considered moving in
+ * seconds.
+ */
+void setCounterMaxPeriod(void* counter_pointer, double maxPeriod, int32_t *status) {
+  Counter* counter = (Counter*) counter_pointer;
+  counter->counter->writeTimerConfig_StallPeriod((uint32_t)(maxPeriod * 4.0e8), status);
+}
+
+/**
+ * Select whether you want to continue updating the event timer output when there are no samples captured.
+ * The output of the event timer has a buffer of periods that are averaged and posted to
+ * a register on the FPGA.  When the timer detects that the event source has stopped
+ * (based on the MaxPeriod) the buffer of samples to be averaged is emptied.  If you
+ * enable the update when empty, you will be notified of the stopped source and the event
+ * time will report 0 samples.  If you disable update when empty, the most recent average
+ * will remain on the output until a new sample is acquired.  You will never see 0 samples
+ * output (except when there have been no events since an FPGA reset) and you will likely not
+ * see the stopped bit become true (since it is updated at the end of an average and there are
+ * no samples to average).
+ */
+void setCounterUpdateWhenEmpty(void* counter_pointer, bool enabled, int32_t *status) {
+  Counter* counter = (Counter*) counter_pointer;
+  counter->counter->writeTimerConfig_UpdateWhenEmpty(enabled, status);
+}
+
+/**
+ * Determine if the clock is stopped.
+ * Determine if the clocked input is stopped based on the MaxPeriod value set using the
+ * SetMaxPeriod method. If the clock exceeds the MaxPeriod, then the device (and counter) are
+ * assumed to be stopped and it returns true.
+ * @return Returns true if the most recent counter period exceeds the MaxPeriod value set by
+ * SetMaxPeriod.
+ */
+bool getCounterStopped(void* counter_pointer, int32_t *status) {
+  Counter* counter = (Counter*) counter_pointer;
+  return counter->counter->readTimerOutput_Stalled(status);
+}
+
+/**
+ * The last direction the counter value changed.
+ * @return The last direction the counter value changed.
+ */
+bool getCounterDirection(void* counter_pointer, int32_t *status) {
+  Counter* counter = (Counter*) counter_pointer;
+  bool value = counter->counter->readOutput_Direction(status);
+  return value;
+}
+
+/**
+ * Set the Counter to return reversed sensing on the direction.
+ * This allows counters to change the direction they are counting in the case of 1X and 2X
+ * quadrature encoding only. Any other counter mode isn't supported.
+ * @param reverseDirection true if the value counted should be negated.
+ */
+void setCounterReverseDirection(void* counter_pointer, bool reverseDirection, int32_t *status) {
+  Counter* counter = (Counter*) counter_pointer;
+  if (counter->counter->readConfig_Mode(status) == kExternalDirection) {
+	if (reverseDirection)
+	  setCounterDownSourceEdge(counter_pointer, true, true, status);
+	else
+	  setCounterDownSourceEdge(counter_pointer, false, true, status);
+  }
+}
+
+struct encoder_t {
+  tEncoder* encoder;
+  uint32_t index;
+};
+typedef struct encoder_t Encoder;
+
+static const double DECODING_SCALING_FACTOR = 0.25;
+static Resource *quadEncoders = NULL;
+
+void* initializeEncoder(uint8_t port_a_module, uint32_t port_a_pin, bool port_a_analog_trigger,
+						uint8_t port_b_module, uint32_t port_b_pin, bool port_b_analog_trigger,
+						bool reverseDirection, int32_t *index, int32_t *status) {
+
+  // Initialize encoder structure
+  Encoder* encoder = new Encoder();
+
+  if(port_a_pin >= kNumHeaders) {
+    port_a_pin = remapMXPChannel(port_a_pin);
+    port_a_module = 1;
+  }
+
+  if(port_b_pin >= kNumHeaders) {
+    port_b_pin = remapMXPChannel(port_b_pin);
+    port_b_module = 1;
+  }
+
+  Resource::CreateResourceObject(&quadEncoders, tEncoder::kNumSystems);
+  encoder->index = quadEncoders->Allocate("4X Encoder");
+  *index = encoder->index;
+  // TODO: if (index == ~0ul) { CloneError(quadEncoders); return; }
+  encoder->encoder = tEncoder::create(encoder->index, status);
+  encoder->encoder->writeConfig_ASource_Module(port_a_module, status);
+  encoder->encoder->writeConfig_ASource_Channel(port_a_pin, status);
+  encoder->encoder->writeConfig_ASource_AnalogTrigger(port_a_analog_trigger, status);
+  encoder->encoder->writeConfig_BSource_Module(port_b_module, status);
+  encoder->encoder->writeConfig_BSource_Channel(port_b_pin, status);
+  encoder->encoder->writeConfig_BSource_AnalogTrigger(port_b_analog_trigger, status);
+  encoder->encoder->strobeReset(status);
+  encoder->encoder->writeConfig_Reverse(reverseDirection, status);
+  encoder->encoder->writeTimerConfig_AverageSize(4, status);
+
+  return encoder;
+}
+
+void freeEncoder(void* encoder_pointer, int32_t *status) {
+  Encoder* encoder = (Encoder*) encoder_pointer;
+  quadEncoders->Free(encoder->index);
+  delete encoder->encoder;
+}
+
+/**
+ * Reset the Encoder distance to zero.
+ * Resets the current count to zero on the encoder.
+ */
+void resetEncoder(void* encoder_pointer, int32_t *status) {
+  Encoder* encoder = (Encoder*) encoder_pointer;
+  encoder->encoder->strobeReset(status);
+}
+
+/**
+ * Gets the raw value from the encoder.
+ * The raw value is the actual count unscaled by the 1x, 2x, or 4x scale
+ * factor.
+ * @return Current raw count from the encoder
+ */
+int32_t getEncoder(void* encoder_pointer, int32_t *status) {
+  Encoder* encoder = (Encoder*) encoder_pointer;
+  return encoder->encoder->readOutput_Value(status);
+}
+
+/**
+ * Returns the period of the most recent pulse.
+ * Returns the period of the most recent Encoder pulse in seconds.
+ * This method compenstates for the decoding type.
+ *
+ * @deprecated Use GetRate() in favor of this method.  This returns unscaled periods and GetRate() scales using value from SetDistancePerPulse().
+ *
+ * @return Period in seconds of the most recent pulse.
+ */
+double getEncoderPeriod(void* encoder_pointer, int32_t *status) {
+  Encoder* encoder = (Encoder*) encoder_pointer;
+  tEncoder::tTimerOutput output = encoder->encoder->readTimerOutput(status);
+  double value;
+  if (output.Stalled) {
+	// Return infinity
+	double zero = 0.0;
+	value = 1.0 / zero;
+  } else {
+	// output.Period is a fixed point number that counts by 2 (24 bits, 25 integer bits)
+	value = (double)(output.Period << 1) / (double)output.Count;
+  }
+  double measuredPeriod = value * 2.5e-8;
+  return measuredPeriod / DECODING_SCALING_FACTOR;
+}
+
+/**
+ * Sets the maximum period for stopped detection.
+ * Sets the value that represents the maximum period of the Encoder before it will assume
+ * that the attached device is stopped. This timeout allows users to determine if the wheels or
+ * other shaft has stopped rotating.
+ * This method compensates for the decoding type.
+ *
+ * @deprecated Use SetMinRate() in favor of this method.  This takes unscaled periods and SetMinRate() scales using value from SetDistancePerPulse().
+ *
+ * @param maxPeriod The maximum time between rising and falling edges before the FPGA will
+ * report the device stopped. This is expressed in seconds.
+ */
+void setEncoderMaxPeriod(void* encoder_pointer, double maxPeriod, int32_t *status) {
+  Encoder* encoder = (Encoder*) encoder_pointer;
+  encoder->encoder->writeTimerConfig_StallPeriod((uint32_t)(maxPeriod * 4.0e8 * DECODING_SCALING_FACTOR), status);
+}
+
+/**
+ * Determine if the encoder is stopped.
+ * Using the MaxPeriod value, a boolean is returned that is true if the encoder is considered
+ * stopped and false if it is still moving. A stopped encoder is one where the most recent pulse
+ * width exceeds the MaxPeriod.
+ * @return True if the encoder is considered stopped.
+ */
+bool getEncoderStopped(void* encoder_pointer, int32_t *status) {
+  Encoder* encoder = (Encoder*) encoder_pointer;
+  return encoder->encoder->readTimerOutput_Stalled(status) != 0;
+}
+
+/**
+ * The last direction the encoder value changed.
+ * @return The last direction the encoder value changed.
+ */
+bool getEncoderDirection(void* encoder_pointer, int32_t *status) {
+  Encoder* encoder = (Encoder*) encoder_pointer;
+  return encoder->encoder->readOutput_Direction(status);
+}
+
+/**
+ * Set the direction sensing for this encoder.
+ * This sets the direction sensing on the encoder so that it could count in the correct
+ * software direction regardless of the mounting.
+ * @param reverseDirection true if the encoder direction should be reversed
+ */
+void setEncoderReverseDirection(void* encoder_pointer, bool reverseDirection, int32_t *status) {
+  Encoder* encoder = (Encoder*) encoder_pointer;
+  encoder->encoder->writeConfig_Reverse(reverseDirection, status);
+}
+
+/**
+ * Set the Samples to Average which specifies the number of samples of the timer to
+ * average when calculating the period. Perform averaging to account for
+ * mechanical imperfections or as oversampling to increase resolution.
+ * @param samplesToAverage The number of samples to average from 1 to 127.
+ */
+void setEncoderSamplesToAverage(void* encoder_pointer, uint32_t samplesToAverage, int32_t *status) {
+  Encoder* encoder = (Encoder*) encoder_pointer;
+  if (samplesToAverage < 1 || samplesToAverage > 127) {
+	*status = PARAMETER_OUT_OF_RANGE;
+  }
+  encoder->encoder->writeTimerConfig_AverageSize(samplesToAverage, status);
+}
+
+/**
+ * Get the Samples to Average which specifies the number of samples of the timer to
+ * average when calculating the period. Perform averaging to account for
+ * mechanical imperfections or as oversampling to increase resolution.
+ * @return SamplesToAverage The number of samples being averaged (from 1 to 127)
+ */
+uint32_t getEncoderSamplesToAverage(void* encoder_pointer, int32_t *status) {
+  Encoder* encoder = (Encoder*) encoder_pointer;
+  return encoder->encoder->readTimerConfig_AverageSize(status);
+}
+
+/**
+ * Set an index source for an encoder, which is an input that resets the
+ * encoder's count.
+ */
+void setEncoderIndexSource(void *encoder_pointer, uint32_t pin, bool analogTrigger, bool activeHigh,
+    bool edgeSensitive, int32_t *status) {
+  Encoder* encoder = (Encoder*) encoder_pointer;
+  encoder->encoder->writeConfig_IndexSource_Channel((unsigned char)pin, status);
+  encoder->encoder->writeConfig_IndexSource_Module((unsigned char)0, status);
+  encoder->encoder->writeConfig_IndexSource_AnalogTrigger(analogTrigger, status);
+  encoder->encoder->writeConfig_IndexActiveHigh(activeHigh, status);
+  encoder->encoder->writeConfig_IndexEdgeSensitive(edgeSensitive, status);
+}
+
+/**
+ * Get the loop timing of the PWM system
+ *
+ * @return The loop time
+ */
+uint16_t getLoopTiming(int32_t *status) {
+  return pwmSystem->readLoopTiming(status);
+}
+
+/*
+ * Initialize the spi port. Opens the port if necessary and saves the handle.
+ * If opening the MXP port, also sets up the pin functions appropriately
+ * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
+ */
+void spiInitialize(uint8_t port, int32_t *status) {
+	if(spiSystem == NULL)
+		spiSystem = tSPI::create(status);
+	if(spiGetHandle(port) !=0 ) return;
+	switch(port){
+	case 0:
+		spiSetHandle(0, spilib_open("/dev/spidev0.0"));
+		break;
+	case 1:
+		spiSetHandle(1, spilib_open("/dev/spidev0.1"));
+		break;
+	case 2:
+		spiSetHandle(2, spilib_open("/dev/spidev0.2"));
+		break;
+	case 3:
+		spiSetHandle(3, spilib_open("/dev/spidev0.3"));
+		break;
+	case 4:
+		initializeDigital(status);
+		if(!allocateDIO(getPort(14), false, status)){printf("Failed to allocate DIO 14\n"); return;}
+		if(!allocateDIO(getPort(15), false, status)) {printf("Failed to allocate DIO 15\n"); return;}
+		if(!allocateDIO(getPort(16), true, status)) {printf("Failed to allocate DIO 16\n"); return;}
+		if(!allocateDIO(getPort(17), false, status)) {printf("Failed to allocate DIO 17\n"); return;}
+		digitalSystem->writeEnableMXPSpecialFunction(digitalSystem->readEnableMXPSpecialFunction(status)|0x00F0, status);
+		spiSetHandle(4, spilib_open("/dev/spidev1.0"));
+		break;
+	default:
+		break;
+	}
+	return;
+}
+
+/**
+ * Generic transaction.
+ *
+ * This is a lower-level interface to the spi hardware giving you more control over each transaction.
+ *
+ * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
+ * @param dataToSend Buffer of data to send as part of the transaction.
+ * @param dataReceived Buffer to read data into.
+ * @param size Number of bytes to transfer. [0..7]
+ * @return Number of bytes transferred, -1 for error
+ */
+int32_t spiTransaction(uint8_t port, uint8_t *dataToSend, uint8_t *dataReceived, uint8_t size)
+{
+	::std::unique_lock<ReentrantMutex> sync(spiGetSemaphore(port));
+	return spilib_writeread(spiGetHandle(port), (const char*) dataToSend, (char*) dataReceived, (int32_t) size);
+}
+
+/**
+ * Execute a write transaction with the device.
+ *
+ * Write to a device and wait until the transaction is complete.
+ *
+ * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
+ * @param datToSend The data to write to the register on the device.
+ * @param sendSize The number of bytes to be written
+ * @return The number of bytes written. -1 for an error
+ */
+int32_t spiWrite(uint8_t port, uint8_t* dataToSend, uint8_t sendSize)
+{
+	::std::unique_lock<ReentrantMutex> sync(spiGetSemaphore(port));
+	return spilib_write(spiGetHandle(port), (const char*) dataToSend, (int32_t) sendSize);
+}
+
+/**
+ * Execute a read from the device.
+ *
+ *   This methdod does not write any data out to the device
+ *   Most spi devices will require a register address to be written before
+ *   they begin returning data
+ *
+ * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
+ * @param buffer A pointer to the array of bytes to store the data read from the device.
+ * @param count The number of bytes to read in the transaction. [1..7]
+ * @return Number of bytes read. -1 for error.
+ */
+int32_t spiRead(uint8_t port, uint8_t *buffer, uint8_t count)
+{
+	::std::unique_lock<ReentrantMutex> sync(spiGetSemaphore(port));
+	return spilib_read(spiGetHandle(port), (char*) buffer, (int32_t) count);
+}
+
+/**
+ * Close the SPI port
+ *
+ * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
+ */
+void spiClose(uint8_t port) {
+	::std::unique_lock<ReentrantMutex> sync(spiGetSemaphore(port));
+	spilib_close(spiGetHandle(port));
+	spiSetHandle(port, 0);
+	return;
+}
+
+/**
+ * Set the clock speed for the SPI bus.
+ *
+ * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
+ * @param speed The speed in Hz (0-1MHz)
+ */
+void spiSetSpeed(uint8_t port, uint32_t speed) {
+	::std::unique_lock<ReentrantMutex> sync(spiGetSemaphore(port));
+	spilib_setspeed(spiGetHandle(port), speed);
+}
+
+/**
+ * Set the SPI options
+ *
+ * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
+ * @param msb_first True to write the MSB first, False for LSB first
+ * @param sample_on_trailing True to sample on the trailing edge, False to sample on the leading edge
+ * @param clk_idle_high True to set the clock to active low, False to set the clock active high
+ */
+void spiSetOpts(uint8_t port, int msb_first, int sample_on_trailing, int clk_idle_high) {
+	::std::unique_lock<ReentrantMutex> sync(spiGetSemaphore(port));
+	spilib_setopts(spiGetHandle(port), msb_first, sample_on_trailing, clk_idle_high);
+}
+
+/**
+ * Set the CS Active high for a SPI port
+ *
+ * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
+ */
+void spiSetChipSelectActiveHigh(uint8_t port, int32_t *status){
+	::std::unique_lock<ReentrantMutex> sync(spiGetSemaphore(port));
+	if(port < 4)
+	{
+		spiSystem->writeChipSelectActiveHigh_Hdr(spiSystem->readChipSelectActiveHigh_Hdr(status) | (1<<port), status);
+	}
+	else
+	{
+		spiSystem->writeChipSelectActiveHigh_MXP(1, status);
+	}
+}
+
+/**
+ * Set the CS Active low for a SPI port
+ *
+ * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
+ */
+void spiSetChipSelectActiveLow(uint8_t port, int32_t *status){
+	::std::unique_lock<ReentrantMutex> sync(spiGetSemaphore(port));
+	if(port < 4)
+	{
+		spiSystem->writeChipSelectActiveHigh_Hdr(spiSystem->readChipSelectActiveHigh_Hdr(status) & ~(1<<port), status);
+	}
+	else
+	{
+		spiSystem->writeChipSelectActiveHigh_MXP(0, status);
+	}
+}
+
+/**
+ * Get the stored handle for a SPI port
+ *
+ * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
+ * @return The stored handle for the SPI port. 0 represents no stored handle.
+ */
+int32_t spiGetHandle(uint8_t port){
+	::std::unique_lock<ReentrantMutex> sync(spiGetSemaphore(port));
+	switch(port){
+	case 0:
+		return m_spiCS0Handle;
+	case 1:
+		return m_spiCS1Handle;
+	case 2:
+		return m_spiCS2Handle;
+	case 3:
+		return m_spiCS3Handle;
+	case 4:
+		return m_spiMXPHandle;
+	default:
+		return 0;
+	}
+}
+
+/**
+ * Set the stored handle for a SPI port
+ *
+ * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP.
+ * @param handle The value of the handle for the port.
+ */
+void spiSetHandle(uint8_t port, int32_t handle){
+	::std::unique_lock<ReentrantMutex> sync(spiGetSemaphore(port));
+	switch(port){
+	case 0:
+		m_spiCS0Handle = handle;
+		break;
+	case 1:
+		m_spiCS1Handle = handle;
+		break;
+	case 2:
+		m_spiCS2Handle = handle;
+		break;
+	case 3:
+		m_spiCS3Handle = handle;
+		break;
+	case 4:
+		m_spiMXPHandle = handle;
+		break;
+	default:
+		break;
+	}
+}
+
+/**
+ * Get the semaphore for a SPI port
+ *
+ * @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
+ * @return The semaphore for the SPI port.
+ */
+ReentrantMutex& spiGetSemaphore(uint8_t port) {
+	if(port < 4)
+		return spiOnboardSemaphore;
+	else
+		return spiMXPSemaphore;
+}
+
+/*
+ * Initialize the I2C port. Opens the port if necessary and saves the handle.
+ * If opening the MXP port, also sets up the pin functions appropriately
+ * @param port The port to open, 0 for the on-board, 1 for the MXP.
+ */
+void i2CInitialize(uint8_t port, int32_t *status) {
+	initializeDigital(status);
+
+	if(port > 1)
+	{
+		//Set port out of range error here
+		return;
+	}
+
+	ReentrantMutex &lock = port == 0 ? digitalI2COnBoardSemaphore : digitalI2CMXPSemaphore;
+	{
+    ::std::unique_lock<ReentrantMutex> sync(lock);
+		if(port == 0) {
+			i2COnboardObjCount++;
+			if (i2COnBoardHandle > 0) return;
+			i2COnBoardHandle = i2clib_open("/dev/i2c-2");
+		} else if(port == 1) {
+			i2CMXPObjCount++;
+			if (i2CMXPHandle > 0) return;
+			if(!allocateDIO(getPort(24), false, status)) return;
+			if(!allocateDIO(getPort(25), false, status)) return;
+			digitalSystem->writeEnableMXPSpecialFunction(digitalSystem->readEnableMXPSpecialFunction(status)|0xC000, status);
+			i2CMXPHandle = i2clib_open("/dev/i2c-1");
+		}
+	return;
+	}
+}
+
+/**
+ * Generic transaction.
+ *
+ * This is a lower-level interface to the I2C hardware giving you more control over each transaction.
+ *
+ * @param dataToSend Buffer of data to send as part of the transaction.
+ * @param sendSize Number of bytes to send as part of the transaction. [0..6]
+ * @param dataReceived Buffer to read data into.
+ * @param receiveSize Number of bytes to read from the device. [0..7]
+ * @return Transfer Aborted... false for success, true for aborted.
+ */
+int32_t i2CTransaction(uint8_t port, uint8_t deviceAddress, uint8_t *dataToSend, uint8_t sendSize, uint8_t *dataReceived, uint8_t receiveSize)
+{
+	if(port > 1) {
+		//Set port out of range error here
+		return -1;
+	}
+	/*if (sendSize > 6) // Optional, provides better error message.	TODO: Are these limits still right? Implement error. Check for null buffer
+	{
+		wpi_setWPIErrorWithContext(ParameterOutOfRange, "sendSize");
+		return true;
+	}
+	if (receiveSize > 7) // Optional, provides better error message.
+	{
+		wpi_setWPIErrorWithContext(ParameterOutOfRange, "receiveSize");
+		return true;
+	}*/
+	int32_t handle = port == 0 ? i2COnBoardHandle:i2CMXPHandle;
+	ReentrantMutex &lock = port == 0 ? digitalI2COnBoardSemaphore : digitalI2CMXPSemaphore;
+
+	{
+    ::std::unique_lock<ReentrantMutex> sync(lock);
+		return i2clib_writeread(handle, deviceAddress, (const char*) dataToSend, (int32_t) sendSize, (char*) dataReceived, (int32_t) receiveSize);
+	}
+}
+
+/**
+ * Execute a write transaction with the device.
+ *
+ * Write a single byte to a register on a device and wait until the
+ *   transaction is complete.
+ *
+ * @param registerAddress The address of the register on the device to be written.
+ * @param data The byte to write to the register on the device.
+ * @return Transfer Aborted... false for success, true for aborted.
+ */
+int32_t i2CWrite(uint8_t port, uint8_t deviceAddress, uint8_t* dataToSend, uint8_t sendSize)
+{
+	if(port > 1) {
+		//Set port out of range error here
+		return -1;
+	}
+	/*if (sendSize > 6) // Optional, provides better error message.	TODO: Are these limits still right? Implement error. Check for null buffer
+	{
+		wpi_setWPIErrorWithContext(ParameterOutOfRange, "sendSize");
+		return true;
+	}*/
+	int32_t handle = port == 0 ? i2COnBoardHandle:i2CMXPHandle;
+	ReentrantMutex &lock = port == 0 ? digitalI2COnBoardSemaphore : digitalI2CMXPSemaphore;
+	{
+    ::std::unique_lock<ReentrantMutex> sync(lock);
+		return i2clib_write(handle, deviceAddress, (const char*) dataToSend, (int32_t) sendSize);
+	}
+}
+
+/**
+ * Execute a read transaction with the device.
+ *
+ * Read 1 to 7 bytes from a device.
+ * Most I2C devices will auto-increment the register pointer internally
+ *   allowing you to read up to 7 consecutive registers on a device in a
+ *   single transaction.
+ *
+ * @param registerAddress The register to read first in the transaction.
+ * @param count The number of bytes to read in the transaction. [1..7]
+ * @param buffer A pointer to the array of bytes to store the data read from the device.
+ * @return Transfer Aborted... false for success, true for aborted.
+ */
+int32_t i2CRead(uint8_t port, uint8_t deviceAddress, uint8_t *buffer, uint8_t count)
+{
+	if(port > 1) {
+		//Set port out of range error here
+		return -1;
+	}
+	/*	if (count < 1 || count > 7) Todo: Are these limits still right? Implement error
+		{
+			wpi_setWPIErrorWithContext(ParameterOutOfRange, "count");
+			return true;
+		}
+		if (buffer == NULL)
+		{
+			wpi_setWPIErrorWithContext(NullParameter, "buffer");
+			return true;
+		}*/
+	int32_t handle = port == 0 ? i2COnBoardHandle:i2CMXPHandle;
+	ReentrantMutex &lock = port == 0 ? digitalI2COnBoardSemaphore : digitalI2CMXPSemaphore;
+	{
+    ::std::unique_lock<ReentrantMutex> sync(lock);
+		return i2clib_read(handle, deviceAddress, (char*) buffer, (int32_t) count);
+	}
+
+}
+
+void i2CClose(uint8_t port) {
+	if(port > 1) {
+		//Set port out of range error here
+		return;
+	}
+	ReentrantMutex &lock = port == 0 ? digitalI2COnBoardSemaphore : digitalI2CMXPSemaphore;
+	{
+    ::std::unique_lock<ReentrantMutex> sync(lock);
+		if((port == 0 ? i2COnboardObjCount--:i2CMXPObjCount--) == 0) {
+			int32_t handle = port == 0 ? i2COnBoardHandle:i2CMXPHandle;
+			i2clib_close(handle);
+		}
+	}
+	return;
+}
diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/FRC_FPGA_ChipObject_Aliases.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/FRC_FPGA_ChipObject_Aliases.h
new file mode 100644
index 0000000..d9fba25
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/FRC_FPGA_ChipObject_Aliases.h
@@ -0,0 +1,10 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __FRC_FPGA_ChipObject_Aliases_h__

+#define __FRC_FPGA_ChipObject_Aliases_h__

+

+#define nRuntimeFPGANamespace nFRC_2012_1_6_4

+#define nInvariantFPGANamespace nFRC_C0EF_1_1_0

+

+#endif // __FRC_FPGA_ChipObject_Aliases_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/RoboRIO_FRC_ChipObject_Aliases.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/RoboRIO_FRC_ChipObject_Aliases.h
new file mode 100644
index 0000000..7bae082
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/RoboRIO_FRC_ChipObject_Aliases.h
@@ -0,0 +1,9 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __RoboRIO_FRC_ChipObject_Aliases_h__

+#define __RoboRIO_FRC_ChipObject_Aliases_h__

+

+#define nRoboRIO_FPGANamespace nFRC_2015_1_0_A

+

+#endif // __RoboRIO_FRC_ChipObject_Aliases_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/fpgainterfacecapi/NiFpga.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/fpgainterfacecapi/NiFpga.h
new file mode 100644
index 0000000..27b0665
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/fpgainterfacecapi/NiFpga.h
@@ -0,0 +1,2450 @@
+/*

+ * FPGA Interface C API 14.0 header file.

+ *

+ * Copyright (c) 2014,

+ * National Instruments Corporation.

+ * All rights reserved.

+ */

+

+#ifndef __NiFpga_h__

+#define __NiFpga_h__

+

+/*

+ * Determine platform details.

+ */

+#if defined(_M_IX86) \

+ || defined(_M_X64) \

+ || defined(_M_AMD64) \

+ || defined(i386) \

+ || defined(__i386) \

+ || defined(__i386__) \

+ || defined(__i486__) \

+ || defined(__i586__) \

+ || defined(__i686__) \

+ || defined(__amd64__) \

+ || defined(__amd64) \

+ || defined(__x86_64__) \

+ || defined(__x86_64) \

+ || defined(__IA32__) \

+ || defined(_X86_) \

+ || defined(__THW_INTEL__) \

+ || defined(__I86__) \

+ || defined(__INTEL__) \

+ || defined(__X86__) \

+ || defined(__386__) \

+ || defined(__I86__) \

+ || defined(M_I386) \

+ || defined(M_I86) \

+ || defined(_M_I386) \

+ || defined(_M_I86)

+   #if defined(_WIN32) \

+    || defined(_WIN64) \

+    || defined(__WIN32__) \

+    || defined(__TOS_WIN__) \

+    || defined(__WINDOWS__) \

+    || defined(_WINDOWS) \

+    || defined(__WINDOWS_386__) \

+    || defined(__CYGWIN__)

+      /* Either Windows or Phar Lap ETS. */

+      #define NiFpga_Windows 1

+   #elif defined(__linux__) \

+      || defined(__linux) \

+      || defined(linux) \

+      || defined(__gnu_linux__)

+      #define NiFpga_Linux 1

+   #elif defined(__APPLE__) && defined(__MACH__)

+      #define NiFpga_MacOsX 1

+   #else

+      #error Unsupported OS.

+   #endif

+#elif defined(__powerpc) \

+   || defined(__powerpc__) \

+   || defined(__POWERPC__) \

+   || defined(__ppc__) \

+   || defined(__PPC) \

+   || defined(_M_PPC) \

+   || defined(_ARCH_PPC) \

+   || defined(__PPC__) \

+   || defined(__ppc)

+   #if defined(__vxworks)

+      #define NiFpga_VxWorks 1

+   #else

+      #error Unsupported OS.

+   #endif

+#elif defined(__arm__) \

+   || defined(__thumb__) \

+   || defined(__TARGET_ARCH_ARM) \

+   || defined(__TARGET_ARCH_THUMB) \

+   || defined(_ARM) \

+   || defined(_M_ARM) \

+   || defined(_M_ARMT)

+#if defined(__linux__) \

+ || defined(__linux) \

+ || defined(linux) \

+ || defined(__gnu_linux__)

+   #define NiFpga_Linux 1

+#else

+      #error Unsupported OS.

+   #endif

+#else

+   #error Unsupported architecture.

+#endif

+

+/*

+ * Determine compiler.

+ */

+#if defined(_MSC_VER)

+   #define NiFpga_Msvc 1

+#elif defined(__GNUC__)

+   #define NiFpga_Gcc 1

+#elif defined(_CVI_) && !defined(_TPC_)

+   #define NiFpga_Cvi 1

+   /* Enables CVI Library Protection Errors. */

+   #pragma EnableLibraryRuntimeChecking

+#else

+   /* Unknown compiler. */

+#endif

+

+/*

+ * Determine compliance with different C/C++ language standards.

+ */

+#if defined(__cplusplus)

+   #define NiFpga_Cpp 1

+   #if __cplusplus >= 199707L

+      #define NiFpga_Cpp98 1

+      #if __cplusplus >= 201103L

+         #define NiFpga_Cpp11 1

+      #endif

+   #endif

+#endif

+#if defined(__STDC__)

+   #define NiFpga_C89 1

+   #if defined(__STDC_VERSION__)

+      #define NiFpga_C90 1

+      #if __STDC_VERSION__ >= 199409L

+         #define NiFpga_C94 1

+         #if __STDC_VERSION__ >= 199901L

+            #define NiFpga_C99 1

+            #if __STDC_VERSION__ >= 201112L

+               #define NiFpga_C11 1

+            #endif

+         #endif

+      #endif

+   #endif

+#endif

+

+/*

+ * Determine ability to inline functions.

+ */

+#if NiFpga_Cpp || NiFpga_C99

+   /* The inline keyword exists in C++ and C99. */

+#define NiFpga_Inline inline

+#elif NiFpga_Msvc

+   /* Visual C++ (at least since 6.0) also supports an alternate keyword. */

+   #define NiFpga_Inline __inline

+#elif NiFpga_Gcc

+   /* GCC (at least since 2.95.2) also supports an alternate keyword. */

+   #define NiFpga_Inline __inline__

+#elif !defined(NiFpga_Inline)

+   /*

+    * Disable inlining if inline support is unknown. To manually enable

+    * inlining, #define the following macro before #including NiFpga.h:

+    *

+    *    #define NiFpga_Inline inline

+    */

+   #define NiFpga_Inline

+#endif

+

+/*

+ * Define exact-width integer types, if they have not already been defined.

+ */

+#if NiFpga_ExactWidthIntegerTypesDefined \

+ || defined(_STDINT) \

+ || defined(_STDINT_H) \

+ || defined(_STDINT_H_) \

+ || defined(_INTTYPES_H) \

+ || defined(_INTTYPES_H_) \

+ || defined(_SYS_STDINT_H) \

+ || defined(_SYS_STDINT_H_) \

+ || defined(_SYS_INTTYPES_H) \

+ || defined(_SYS_INTTYPES_H_) \

+ || defined(_STDINT_H_INCLUDED) \

+ || defined(_MSC_STDINT_H_) \

+ || defined(_PSTDINT_H_INCLUDED)

+   /* Assume that exact-width integer types have already been defined. */

+#elif NiFpga_VxWorks

+   /* VxWorks (at least 6.3 and earlier) did not have stdint.h. */

+   #include <types/vxTypes.h>

+#elif NiFpga_C99 \

+   || NiFpga_Gcc /* GCC (at least since 3.0) has a stdint.h. */ \

+   || defined(HAVE_STDINT_H)

+   /* Assume that stdint.h can be included. */

+   #include <stdint.h>

+#elif NiFpga_Msvc \

+   || NiFpga_Cvi

+   /* Manually define exact-width integer types. */

+   typedef   signed    char  int8_t;

+   typedef unsigned    char uint8_t;

+   typedef            short  int16_t;

+   typedef unsigned   short uint16_t;

+   typedef              int  int32_t;

+   typedef unsigned     int uint32_t;

+   typedef          __int64  int64_t;

+   typedef unsigned __int64 uint64_t;

+#else

+   /*

+    * Exact-width integer types must be defined by the user, and the following

+    * macro must be #defined, before #including NiFpga.h:

+    *

+    *    #define NiFpga_ExactWidthIntegerTypesDefined 1

+    */

+   #error Exact-width integer types must be defined by the user. See comment.

+#endif

+

+/* Included for definition of size_t. */

+#include <stddef.h>

+

+#if NiFpga_Cpp

+extern "C"

+{

+#endif

+

+/**

+ * A boolean value; either NiFpga_False or NiFpga_True.

+ */

+typedef uint8_t NiFpga_Bool;

+

+/**

+ * Represents a false condition.

+ */

+static const NiFpga_Bool NiFpga_False = 0;

+

+/**

+ * Represents a true condition.

+ */

+static const NiFpga_Bool NiFpga_True = 1;

+

+/**

+ * Represents the resulting status of a function call through its return value.

+ * 0 is success, negative values are errors, and positive values are warnings.

+ */

+typedef int32_t NiFpga_Status;

+

+/**

+ * No errors or warnings.

+ */

+static const NiFpga_Status NiFpga_Status_Success = 0;

+

+/**

+ * The timeout expired before the FIFO operation could complete.

+ */

+static const NiFpga_Status NiFpga_Status_FifoTimeout = -50400;

+

+/**

+ * No transfer is in progress because the transfer was aborted by the client.

+ * The operation could not be completed as specified.

+ */

+static const NiFpga_Status NiFpga_Status_TransferAborted = -50405;

+

+/**

+ * A memory allocation failed. Try again after rebooting.

+ */

+static const NiFpga_Status NiFpga_Status_MemoryFull = -52000;

+

+/**

+ * An unexpected software error occurred.

+ */

+static const NiFpga_Status NiFpga_Status_SoftwareFault = -52003;

+

+/**

+ * A parameter to a function was not valid. This could be a NULL pointer, a bad

+ * value, etc.

+ */

+static const NiFpga_Status NiFpga_Status_InvalidParameter = -52005;

+

+/**

+ * A required resource was not found. The NiFpga.* library, the RIO resource, or

+ * some other resource may be missing.

+ */

+static const NiFpga_Status NiFpga_Status_ResourceNotFound = -52006;

+

+/**

+ * A required resource was not properly initialized. This could occur if

+ * NiFpga_Initialize was not called or a required NiFpga_IrqContext was not

+ * reserved.

+ */

+static const NiFpga_Status NiFpga_Status_ResourceNotInitialized = -52010;

+

+/**

+ * A hardware failure has occurred. The operation could not be completed as

+ * specified.

+ */

+static const NiFpga_Status NiFpga_Status_HardwareFault = -52018;

+

+/**

+ * The FPGA is already running.

+ */

+static const NiFpga_Status NiFpga_Status_FpgaAlreadyRunning = -61003;

+

+/**

+ * An error occurred downloading the VI to the FPGA device. Verify that

+ * the target is connected and powered and that the resource of the target

+ * is properly configured.

+ */

+static const NiFpga_Status NiFpga_Status_DownloadError = -61018;

+

+/**

+ * The bitfile was not compiled for the specified resource's device type.

+ */

+static const NiFpga_Status NiFpga_Status_DeviceTypeMismatch = -61024;

+

+/**

+ * An error was detected in the communication between the host computer and the

+ * FPGA target.

+ */

+static const NiFpga_Status NiFpga_Status_CommunicationTimeout = -61046;

+

+/**

+ * The timeout expired before any of the IRQs were asserted.

+ */

+static const NiFpga_Status NiFpga_Status_IrqTimeout = -61060;

+

+/**

+ * The specified bitfile is invalid or corrupt.

+ */

+static const NiFpga_Status NiFpga_Status_CorruptBitfile = -61070;

+

+/**

+ * The requested FIFO depth is invalid. It is either 0 or an amount not

+ * supported by the hardware.

+ */

+static const NiFpga_Status NiFpga_Status_BadDepth = -61072;

+

+/**

+ * The number of FIFO elements is invalid. Either the number is greater than the

+ * depth of the host memory DMA FIFO, or more elements were requested for

+ * release than had been acquired.

+ */

+static const NiFpga_Status NiFpga_Status_BadReadWriteCount = -61073;

+

+/**

+ * A hardware clocking error occurred. A derived clock lost lock with its base

+ * clock during the execution of the LabVIEW FPGA VI. If any base clocks with

+ * derived clocks are referencing an external source, make sure that the

+ * external source is connected and within the supported frequency, jitter,

+ * accuracy, duty cycle, and voltage specifications. Also verify that the

+ * characteristics of the base clock match the configuration specified in the

+ * FPGA Base Clock Properties. If all base clocks with derived clocks are

+ * generated from free-running, on-board sources, please contact National

+ * Instruments technical support at ni.com/support.

+ */

+static const NiFpga_Status NiFpga_Status_ClockLostLock = -61083;

+

+/**

+ * The operation could not be performed because the FPGA is busy. Stop all

+ * activities on the FPGA before requesting this operation. If the target is in

+ * Scan Interface programming mode, put it in FPGA Interface programming mode.

+ */

+static const NiFpga_Status NiFpga_Status_FpgaBusy = -61141;

+

+/**

+ * The operation could not be performed because the FPGA is busy operating in

+ * FPGA Interface C API mode. Stop all activities on the FPGA before requesting

+ * this operation.

+ */

+static const NiFpga_Status NiFpga_Status_FpgaBusyFpgaInterfaceCApi = -61200;

+

+/**

+ * The chassis is in Scan Interface programming mode. In order to run FPGA VIs,

+ * you must go to the chassis properties page, select FPGA programming mode, and

+ * deploy settings.

+ */

+static const NiFpga_Status NiFpga_Status_FpgaBusyScanInterface = -61201;

+

+/**

+ * The operation could not be performed because the FPGA is busy operating in

+ * FPGA Interface mode. Stop all activities on the FPGA before requesting this

+ * operation.

+ */

+static const NiFpga_Status NiFpga_Status_FpgaBusyFpgaInterface = -61202;

+

+/**

+ * The operation could not be performed because the FPGA is busy operating in

+ * Interactive mode. Stop all activities on the FPGA before requesting this

+ * operation.

+ */

+static const NiFpga_Status NiFpga_Status_FpgaBusyInteractive = -61203;

+

+/**

+ * The operation could not be performed because the FPGA is busy operating in

+ * Emulation mode. Stop all activities on the FPGA before requesting this

+ * operation.

+ */

+static const NiFpga_Status NiFpga_Status_FpgaBusyEmulation = -61204;

+

+/**

+ * LabVIEW FPGA does not support the Reset method for bitfiles that allow

+ * removal of implicit enable signals in single-cycle Timed Loops.

+ */

+static const NiFpga_Status NiFpga_Status_ResetCalledWithImplicitEnableRemoval = -61211;

+

+/**

+ * LabVIEW FPGA does not support the Abort method for bitfiles that allow

+ * removal of implicit enable signals in single-cycle Timed Loops.

+ */

+static const NiFpga_Status NiFpga_Status_AbortCalledWithImplicitEnableRemoval = -61212;

+

+/**

+ * LabVIEW FPGA does not support Close and Reset if Last Reference for bitfiles

+ * that allow removal of implicit enable signals in single-cycle Timed Loops.

+ * Pass the NiFpga_CloseAttribute_NoResetIfLastSession attribute to NiFpga_Close

+ * instead of 0.

+ */

+static const NiFpga_Status NiFpga_Status_CloseAndResetCalledWithImplicitEnableRemoval = -61213;

+

+/**

+ * For bitfiles that allow removal of implicit enable signals in single-cycle

+ * Timed Loops, LabVIEW FPGA does not support this method prior to running the

+ * bitfile.

+ */

+static const NiFpga_Status NiFpga_Status_ImplicitEnableRemovalButNotYetRun = -61214;

+

+/**

+ * Bitfiles that allow removal of implicit enable signals in single-cycle Timed

+ * Loops can run only once. Download the bitfile again before re-running the VI.

+ */

+static const NiFpga_Status NiFpga_Status_RunAfterStoppedCalledWithImplicitEnableRemoval = -61215;

+

+/**

+ * A gated clock has violated the handshaking protocol. If you are using

+ * external gated clocks, ensure that they follow the required clock gating

+ * protocol. If you are generating your clocks internally, please contact

+ * National Instruments Technical Support.

+ */

+static const NiFpga_Status NiFpga_Status_GatedClockHandshakingViolation = -61216;

+

+/**

+ * The number of elements requested must be less than or equal to the number of

+ * unacquired elements left in the host memory DMA FIFO. There are currently

+ * fewer unacquired elements left in the FIFO than are being requested. Release

+ * some acquired elements before acquiring more elements.

+ */

+static const NiFpga_Status NiFpga_Status_ElementsNotPermissibleToBeAcquired = -61219;

+

+/**

+ * An unexpected internal error occurred.

+ */

+static const NiFpga_Status NiFpga_Status_InternalError = -61499;

+

+/**

+ * The NI-RIO driver was unable to allocate memory for a FIFO. This can happen

+ * when the combined depth of all DMA FIFOs exceeds the maximum depth for the

+ * controller, or when the controller runs out of system memory. You may be able

+ * to reconfigure the controller with a greater maximum FIFO depth. For more

+ * information, refer to the NI KnowledgeBase article 65OF2ERQ.

+ */

+static const NiFpga_Status NiFpga_Status_TotalDmaFifoDepthExceeded = -63003;

+

+/**

+ * Access to the remote system was denied. Use MAX to check the Remote Device

+ * Access settings under Software>>NI-RIO>>NI-RIO Settings on the remote system.

+ */

+static const NiFpga_Status NiFpga_Status_AccessDenied = -63033;

+

+/**

+ * The NI-RIO software on the host is not compatible with the software on the

+ * target. Upgrade the NI-RIO software on the host in order to connect to this

+ * target.

+ */

+static const NiFpga_Status NiFpga_Status_HostVersionMismatch = -63038;

+

+/**

+ * A connection could not be established to the specified remote device. Ensure

+ * that the device is on and accessible over the network, that NI-RIO software

+ * is installed, and that the RIO server is running and properly configured.

+ */

+static const NiFpga_Status NiFpga_Status_RpcConnectionError = -63040;

+

+/**

+ * The RPC session is invalid. The target may have reset or been rebooted. Check

+ * the network connection and retry the operation.

+ */

+static const NiFpga_Status NiFpga_Status_RpcSessionError = -63043;

+

+/**

+ * The operation could not complete because another session is accessing the

+ * FIFO. Close the other session and retry.

+ */

+static const NiFpga_Status NiFpga_Status_FifoReserved = -63082;

+

+/**

+ * A Configure FIFO, Stop FIFO, Read FIFO, or Write FIFO function was called

+ * while the host had acquired elements of the FIFO. Release all acquired

+ * elements before configuring, stopping, reading, or writing.

+ */

+static const NiFpga_Status NiFpga_Status_FifoElementsCurrentlyAcquired = -63083;

+

+/**

+ * A function was called using a misaligned address. The address must be a

+ * multiple of the size of the datatype.

+ */

+static const NiFpga_Status NiFpga_Status_MisalignedAccess = -63084;

+

+/**

+ * The FPGA Read/Write Control Function is accessing a control or indicator

+ * with data that exceeds the maximum size supported on the current target.

+ * Refer to the hardware documentation for the limitations on data types for

+ * this target.

+ */

+static const NiFpga_Status NiFpga_Status_ControlOrIndicatorTooLarge = -63085;

+

+/**

+ * A valid .lvbitx bitfile is required. If you are using a valid .lvbitx

+ * bitfile, the bitfile may not be compatible with the software you are using.

+ * Determine which version of LabVIEW was used to make the bitfile, update your

+ * software to that version or later, and try again.

+ */

+static const NiFpga_Status NiFpga_Status_BitfileReadError = -63101;

+

+/**

+ * The specified signature does not match the signature of the bitfile. If the

+ * bitfile has been recompiled, regenerate the C API and rebuild the

+ * application.

+ */

+static const NiFpga_Status NiFpga_Status_SignatureMismatch = -63106;

+

+/**

+ * The bitfile you are trying to use is not compatible with the version of

+ * NI-RIO installed on the target and/or the host. Determine which versions of

+ * NI-RIO and LabVIEW were used to make the bitfile, update the software on the

+ * target and host to that version or later, and try again.

+ */

+static const NiFpga_Status NiFpga_Status_IncompatibleBitfile = -63107;

+

+/**

+ * Either the supplied resource name is invalid as a RIO resource name, or the

+ * device was not found. Use MAX to find the proper resource name for the

+ * intended device.

+ */

+static const NiFpga_Status NiFpga_Status_InvalidResourceName = -63192;

+

+/**

+ * The requested feature is not supported.

+ */

+static const NiFpga_Status NiFpga_Status_FeatureNotSupported = -63193;

+

+/**

+ * The NI-RIO software on the target system is not compatible with this

+ * software. Upgrade the NI-RIO software on the target system.

+ */

+static const NiFpga_Status NiFpga_Status_VersionMismatch = -63194;

+

+/**

+ * The session is invalid or has been closed.

+ */

+static const NiFpga_Status NiFpga_Status_InvalidSession = -63195;

+

+/**

+ * The maximum number of open FPGA sessions has been reached. Close some open

+ * sessions.

+ */

+static const NiFpga_Status NiFpga_Status_OutOfHandles = -63198;

+

+/**

+ * Tests whether a status is an error.

+ *

+ * @param status status to check for an error

+ * @return whether the status was an error

+ */

+static NiFpga_Inline NiFpga_Bool NiFpga_IsError(const NiFpga_Status status)

+{

+   return status < NiFpga_Status_Success;

+}

+

+/**

+ * Tests whether a status is not an error. Success and warnings are not errors.

+ *

+ * @param status status to check for an error

+ * @return whether the status was a success or warning

+ */

+static NiFpga_Inline NiFpga_Bool NiFpga_IsNotError(const NiFpga_Status status)

+{

+   return status >= NiFpga_Status_Success;

+}

+

+/**

+ * Conditionally sets the status to a new value. The previous status is

+ * preserved unless the new status is more of an error, which means that

+ * warnings and errors overwrite successes, and errors overwrite warnings. New

+ * errors do not overwrite older errors, and new warnings do not overwrite

+ * older warnings.

+ *

+ * @param status status to conditionally set

+ * @param newStatus new status value that may be set

+ * @return the resulting status

+ */

+static NiFpga_Inline NiFpga_Status NiFpga_MergeStatus(

+                                               NiFpga_Status* const status,

+                                               const NiFpga_Status  newStatus)

+{

+   if (!status)

+      return NiFpga_Status_InvalidParameter;

+   if (NiFpga_IsNotError(*status)

+   &&  (*status == NiFpga_Status_Success || NiFpga_IsError(newStatus)))

+      *status = newStatus;

+   return *status;

+}

+

+/**

+ * This macro evaluates the expression only if the status is not an error. The

+ * expression must evaluate to an NiFpga_Status, such as a call to any NiFpga_*

+ * function, because the status will be set to the returned status if the

+ * expression is evaluated.

+ *

+ * You can use this macro to mimic status chaining in LabVIEW, where the status

+ * does not have to be explicitly checked after each call. Such code may look

+ * like the following example.

+ *

+ *    NiFpga_Status status = NiFpga_Status_Success;

+ *    NiFpga_IfIsNotError(status, NiFpga_WriteU32(...));

+ *    NiFpga_IfIsNotError(status, NiFpga_WriteU32(...));

+ *    NiFpga_IfIsNotError(status, NiFpga_WriteU32(...));

+ *

+ * @param status status to check for an error

+ * @param expression expression to call if the incoming status is not an error

+ */

+#define NiFpga_IfIsNotError(status, expression) \

+   if (NiFpga_IsNotError(status)) \

+      NiFpga_MergeStatus(&status, (expression)); \

+

+/**

+ * You must call this function before all other function calls. This function

+ * loads the NiFpga library so that all the other functions will work. If this

+ * function succeeds, you must call NiFpga_Finalize after all other function

+ * calls.

+ *

+ * @warning This function is not thread safe.

+ *

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_Initialize(void);

+

+/**

+ * You must call this function after all other function calls if

+ * NiFpga_Initialize succeeds. This function unloads the NiFpga library.

+ *

+ * @warning This function is not thread safe.

+ *

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_Finalize(void);

+

+/**

+ * A handle to an FPGA session.

+ */

+typedef uint32_t NiFpga_Session;

+

+/**

+ * Attributes that NiFpga_Open accepts.

+ */

+typedef enum

+{

+   NiFpga_OpenAttribute_NoRun = 1

+} NiFpga_OpenAttribute;

+

+/**

+ * Opens a session to the FPGA. This call ensures that the contents of the

+ * bitfile are programmed to the FPGA. The FPGA runs unless the

+ * NiFpga_OpenAttribute_NoRun attribute is used.

+ *

+ * Because different operating systems have different default current working

+ * directories for applications, you must pass an absolute path for the bitfile

+ * parameter. If you pass only the filename instead of an absolute path, the

+ * operating system may not be able to locate the bitfile. For example, the

+ * default current working directories are C:\ni-rt\system\ for Phar Lap ETS and

+ * /c/ for VxWorks. Because the generated *_Bitfile constant is a #define to a

+ * string literal, you can use C/C++ string-literal concatenation to form an

+ * absolute path. For example, if the bitfile is in the root directory of a

+ * Phar Lap ETS system, pass the following for the bitfile parameter.

+ *

+ *    "C:\\" NiFpga_MyApplication_Bitfile

+ *

+ * @param bitfile path to the bitfile

+ * @param signature signature of the bitfile

+ * @param resource RIO resource string to open ("RIO0" or "rio://mysystem/RIO")

+ * @param attribute bitwise OR of any NiFpga_OpenAttributes, or 0

+ * @param session outputs the session handle, which must be closed when no

+ *                longer needed

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_Open(const char*     bitfile,

+                          const char*     signature,

+                          const char*     resource,

+                          uint32_t        attribute,

+                          NiFpga_Session* session);

+

+/**

+ * Attributes that NiFpga_Close accepts.

+ */

+typedef enum

+{

+   NiFpga_CloseAttribute_NoResetIfLastSession = 1

+} NiFpga_CloseAttribute;

+

+/**

+ * Closes the session to the FPGA. The FPGA resets unless either another session

+ * is still open or you use the NiFpga_CloseAttribute_NoResetIfLastSession

+ * attribute.

+ *

+ * @param session handle to a currently open session

+ * @param attribute bitwise OR of any NiFpga_CloseAttributes, or 0

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_Close(NiFpga_Session session,

+                           uint32_t       attribute);

+

+/**

+ * Attributes that NiFpga_Run accepts.

+ */

+typedef enum

+{

+   NiFpga_RunAttribute_WaitUntilDone = 1

+} NiFpga_RunAttribute;

+

+/**

+ * Runs the FPGA VI on the target. If you use NiFpga_RunAttribute_WaitUntilDone,

+ * NiFpga_Run blocks the thread until the FPGA finishes running.

+ *

+ * @param session handle to a currently open session

+ * @param attribute bitwise OR of any NiFpga_RunAttributes, or 0

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_Run(NiFpga_Session session,

+                         uint32_t       attribute);

+

+/**

+ * Aborts the FPGA VI.

+ *

+ * @param session handle to a currently open session

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_Abort(NiFpga_Session session);

+

+/**

+ * Resets the FPGA VI.

+ *

+ * @param session handle to a currently open session

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_Reset(NiFpga_Session session);

+

+/**

+ * Re-downloads the FPGA bitstream to the target.

+ *

+ * @param session handle to a currently open session

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_Download(NiFpga_Session session);

+

+/**

+ * Reads a boolean value from a given indicator or control.

+ *

+ * @param session handle to a currently open session

+ * @param indicator indicator or control from which to read

+ * @param value outputs the value that was read

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReadBool(NiFpga_Session session,

+                              uint32_t       indicator,

+                              NiFpga_Bool*   value);

+

+/**

+ * Reads a signed 8-bit integer value from a given indicator or control.

+ *

+ * @param session handle to a currently open session

+ * @param indicator indicator or control from which to read

+ * @param value outputs the value that was read

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReadI8(NiFpga_Session session,

+                            uint32_t       indicator,

+                            int8_t*        value);

+

+/**

+ * Reads an unsigned 8-bit integer value from a given indicator or control.

+ *

+ * @param session handle to a currently open session

+ * @param indicator indicator or control from which to read

+ * @param value outputs the value that was read

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReadU8(NiFpga_Session session,

+                            uint32_t       indicator,

+                            uint8_t*       value);

+

+/**

+ * Reads a signed 16-bit integer value from a given indicator or control.

+ *

+ * @param session handle to a currently open session

+ * @param indicator indicator or control from which to read

+ * @param value outputs the value that was read

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReadI16(NiFpga_Session session,

+                             uint32_t       indicator,

+                             int16_t*       value);

+

+/**

+ * Reads an unsigned 16-bit integer value from a given indicator or control.

+ *

+ * @param session handle to a currently open session

+ * @param indicator indicator or control from which to read

+ * @param value outputs the value that was read

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReadU16(NiFpga_Session session,

+                             uint32_t       indicator,

+                             uint16_t*      value);

+

+/**

+ * Reads a signed 32-bit integer value from a given indicator or control.

+ *

+ * @param session handle to a currently open session

+ * @param indicator indicator or control from which to read

+ * @param value outputs the value that was read

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReadI32(NiFpga_Session session,

+                             uint32_t       indicator,

+                             int32_t*       value);

+

+/**

+ * Reads an unsigned 32-bit integer value from a given indicator or control.

+ *

+ * @param session handle to a currently open session

+ * @param indicator indicator or control from which to read

+ * @param value outputs the value that was read

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReadU32(NiFpga_Session session,

+                             uint32_t       indicator,

+                             uint32_t*      value);

+

+/**

+ * Reads a signed 64-bit integer value from a given indicator or control.

+ *

+ * @param session handle to a currently open session

+ * @param indicator indicator or control from which to read

+ * @param value outputs the value that was read

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReadI64(NiFpga_Session session,

+                             uint32_t       indicator,

+                             int64_t*       value);

+

+/**

+ * Reads an unsigned 64-bit integer value from a given indicator or control.

+ *

+ * @param session handle to a currently open session

+ * @param indicator indicator or control from which to read

+ * @param value outputs the value that was read

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReadU64(NiFpga_Session session,

+                             uint32_t       indicator,

+                             uint64_t*      value);

+

+/**

+ * Writes a boolean value to a given control or indicator.

+ *

+ * @param session handle to a currently open session

+ * @param control control or indicator to which to write

+ * @param value value to write

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WriteBool(NiFpga_Session session,

+                               uint32_t       control,

+                               NiFpga_Bool    value);

+

+/**

+ * Writes a signed 8-bit integer value to a given control or indicator.

+ *

+ * @param session handle to a currently open session

+ * @param control control or indicator to which to write

+ * @param value value to write

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WriteI8(NiFpga_Session session,

+                             uint32_t       control,

+                             int8_t         value);

+

+/**

+ * Writes an unsigned 8-bit integer value to a given control or indicator.

+ *

+ * @param session handle to a currently open session

+ * @param control control or indicator to which to write

+ * @param value value to write

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WriteU8(NiFpga_Session session,

+                             uint32_t       control,

+                             uint8_t        value);

+

+/**

+ * Writes a signed 16-bit integer value to a given control or indicator.

+ *

+ * @param session handle to a currently open session

+ * @param control control or indicator to which to write

+ * @param value value to write

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WriteI16(NiFpga_Session session,

+                              uint32_t       control,

+                              int16_t        value);

+

+/**

+ * Writes an unsigned 16-bit integer value to a given control or indicator.

+ *

+ * @param session handle to a currently open session

+ * @param control control or indicator to which to write

+ * @param value value to write

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WriteU16(NiFpga_Session session,

+                              uint32_t       control,

+                              uint16_t       value);

+

+/**

+ * Writes a signed 32-bit integer value to a given control or indicator.

+ *

+ * @param session handle to a currently open session

+ * @param control control or indicator to which to write

+ * @param value value to write

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WriteI32(NiFpga_Session session,

+                              uint32_t       control,

+                              int32_t        value);

+

+/**

+ * Writes an unsigned 32-bit integer value to a given control or indicator.

+ *

+ * @param session handle to a currently open session

+ * @param control control or indicator to which to write

+ * @param value value to write

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WriteU32(NiFpga_Session session,

+                              uint32_t       control,

+                              uint32_t       value);

+

+/**

+ * Writes a signed 64-bit integer value to a given control or indicator.

+ *

+ * @param session handle to a currently open session

+ * @param control control or indicator to which to write

+ * @param value value to write

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WriteI64(NiFpga_Session session,

+                              uint32_t       control,

+                              int64_t        value);

+

+/**

+ * Writes an unsigned 64-bit integer value to a given control or indicator.

+ *

+ * @param session handle to a currently open session

+ * @param control control or indicator to which to write

+ * @param value value to write

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WriteU64(NiFpga_Session session,

+                              uint32_t       control,

+                              uint64_t       value);

+

+/**

+ * Reads an entire array of boolean values from a given array indicator or

+ * control.

+ *

+ * @warning The size passed must be the exact number of elements in the

+ *          indicator or control.

+ *

+ * @param session handle to a currently open session

+ * @param indicator indicator or control from which to read

+ * @param array outputs the entire array that was read

+ * @param size exact number of elements in the indicator or control

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReadArrayBool(NiFpga_Session session,

+                                   uint32_t       indicator,

+                                   NiFpga_Bool*   array,

+                                   size_t         size);

+

+/**

+ * Reads an entire array of signed 8-bit integer values from a given array

+ * indicator or control.

+ *

+ * @warning The size passed must be the exact number of elements in the

+ *          indicator or control.

+ *

+ * @param session handle to a currently open session

+ * @param indicator indicator or control from which to read

+ * @param array outputs the entire array that was read

+ * @param size exact number of elements in the indicator or control

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReadArrayI8(NiFpga_Session session,

+                                 uint32_t       indicator,

+                                 int8_t*        array,

+                                 size_t         size);

+

+/**

+ * Reads an entire array of unsigned 8-bit integer values from a given array

+ * indicator or control.

+ *

+ * @warning The size passed must be the exact number of elements in the

+ *          indicator or control.

+ *

+ * @param session handle to a currently open session

+ * @param indicator indicator or control from which to read

+ * @param array outputs the entire array that was read

+ * @param size exact number of elements in the indicator or control

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReadArrayU8(NiFpga_Session session,

+                                 uint32_t       indicator,

+                                 uint8_t*       array,

+                                 size_t         size);

+

+/**

+ * Reads an entire array of signed 16-bit integer values from a given array

+ * indicator or control.

+ *

+ * @warning The size passed must be the exact number of elements in the

+ *          indicator or control.

+ *

+ * @param session handle to a currently open session

+ * @param indicator indicator or control from which to read

+ * @param array outputs the entire array that was read

+ * @param size exact number of elements in the indicator or control

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReadArrayI16(NiFpga_Session session,

+                                  uint32_t       indicator,

+                                  int16_t*       array,

+                                  size_t         size);

+

+/**

+ * Reads an entire array of unsigned 16-bit integer values from a given array

+ * indicator or control.

+ *

+ * @warning The size passed must be the exact number of elements in the

+ *          indicator or control.

+ *

+ * @param session handle to a currently open session

+ * @param indicator indicator or control from which to read

+ * @param array outputs the entire array that was read

+ * @param size exact number of elements in the indicator or control

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReadArrayU16(NiFpga_Session session,

+                                  uint32_t       indicator,

+                                  uint16_t*      array,

+                                  size_t         size);

+

+/**

+ * Reads an entire array of signed 32-bit integer values from a given array

+ * indicator or control.

+ *

+ * @warning The size passed must be the exact number of elements in the

+ *          indicator or control.

+ *

+ * @param session handle to a currently open session

+ * @param indicator indicator or control from which to read

+ * @param array outputs the entire array that was read

+ * @param size exact number of elements in the indicator or control

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReadArrayI32(NiFpga_Session session,

+                                  uint32_t       indicator,

+                                  int32_t*       array,

+                                  size_t         size);

+

+/**

+ * Reads an entire array of unsigned 32-bit integer values from a given array

+ * indicator or control.

+ *

+ * @warning The size passed must be the exact number of elements in the

+ *          indicator or control.

+ *

+ * @param session handle to a currently open session

+ * @param indicator indicator or control from which to read

+ * @param array outputs the entire array that was read

+ * @param size exact number of elements in the indicator or control

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReadArrayU32(NiFpga_Session session,

+                                  uint32_t       indicator,

+                                  uint32_t*      array,

+                                  size_t         size);

+

+/**

+ * Reads an entire array of signed 64-bit integer values from a given array

+ * indicator or control.

+ *

+ * @warning The size passed must be the exact number of elements in the

+ *          indicator or control.

+ *

+ * @param session handle to a currently open session

+ * @param indicator indicator or control from which to read

+ * @param array outputs the entire array that was read

+ * @param size exact number of elements in the indicator or control

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReadArrayI64(NiFpga_Session session,

+                                  uint32_t       indicator,

+                                  int64_t*       array,

+                                  size_t         size);

+

+/**

+ * Reads an entire array of unsigned 64-bit integer values from a given array

+ * indicator or control.

+ *

+ * @warning The size passed must be the exact number of elements in the

+ *          indicator or control.

+ *

+ * @param session handle to a currently open session

+ * @param indicator indicator or control from which to read

+ * @param array outputs the entire array that was read

+ * @param size exact number of elements in the indicator or control

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReadArrayU64(NiFpga_Session session,

+                                  uint32_t       indicator,

+                                  uint64_t*      array,

+                                  size_t         size);

+

+/**

+ * Writes an entire array of boolean values to a given array control or

+ * indicator.

+ *

+ * @warning The size passed must be the exact number of elements in the

+ *          control or indicator.

+ *

+ * @param session handle to a currently open session

+ * @param control control or indicator to which to write

+ * @param array entire array to write

+ * @param size exact number of elements in the control or indicator

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WriteArrayBool(NiFpga_Session     session,

+                                    uint32_t           control,

+                                    const NiFpga_Bool* array,

+                                    size_t             size);

+

+/**

+ * Writes an entire array of signed 8-bit integer values to a given array

+ * control or indicator.

+ *

+ * @warning The size passed must be the exact number of elements in the

+ *          control or indicator.

+ *

+ * @param session handle to a currently open session

+ * @param control control or indicator to which to write

+ * @param array entire array to write

+ * @param size exact number of elements in the control or indicator

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WriteArrayI8(NiFpga_Session session,

+                                  uint32_t       control,

+                                  const int8_t*  array,

+                                  size_t         size);

+

+/**

+ * Writes an entire array of unsigned 8-bit integer values to a given array

+ * control or indicator.

+ *

+ * @warning The size passed must be the exact number of elements in the

+ *          control or indicator.

+ *

+ * @param session handle to a currently open session

+ * @param control control or indicator to which to write

+ * @param array entire array to write

+ * @param size exact number of elements in the control or indicator

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WriteArrayU8(NiFpga_Session session,

+                                  uint32_t       control,

+                                  const uint8_t* array,

+                                  size_t         size);

+

+/**

+ * Writes an entire array of signed 16-bit integer values to a given array

+ * control or indicator.

+ *

+ * @warning The size passed must be the exact number of elements in the

+ *          control or indicator.

+ *

+ * @param session handle to a currently open session

+ * @param control control or indicator to which to write

+ * @param array entire array to write

+ * @param size exact number of elements in the control or indicator

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WriteArrayI16(NiFpga_Session session,

+                                   uint32_t       control,

+                                   const int16_t* array,

+                                   size_t         size);

+

+/**

+ * Writes an entire array of unsigned 16-bit integer values to a given array

+ * control or indicator.

+ *

+ * @warning The size passed must be the exact number of elements in the

+ *          control or indicator.

+ *

+ * @param session handle to a currently open session

+ * @param control control or indicator to which to write

+ * @param array entire array to write

+ * @param size exact number of elements in the control or indicator

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WriteArrayU16(NiFpga_Session  session,

+                                   uint32_t        control,

+                                   const uint16_t* array,

+                                   size_t          size);

+

+/**

+ * Writes an entire array of signed 32-bit integer values to a given array

+ * control or indicator.

+ *

+ * @warning The size passed must be the exact number of elements in the

+ *          control or indicator.

+ *

+ * @param session handle to a currently open session

+ * @param control control or indicator to which to write

+ * @param array entire array to write

+ * @param size exact number of elements in the control or indicator

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WriteArrayI32(NiFpga_Session session,

+                                   uint32_t       control,

+                                   const int32_t* array,

+                                   size_t         size);

+

+/**

+ * Writes an entire array of unsigned 32-bit integer values to a given array

+ * control or indicator.

+ *

+ * @warning The size passed must be the exact number of elements in the

+ *          control or indicator.

+ *

+ * @param session handle to a currently open session

+ * @param control control or indicator to which to write

+ * @param array entire array to write

+ * @param size exact number of elements in the control or indicator

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WriteArrayU32(NiFpga_Session  session,

+                                   uint32_t        control,

+                                   const uint32_t* array,

+                                   size_t          size);

+

+/**

+ * Writes an entire array of signed 64-bit integer values to a given array

+ * control or indicator.

+ *

+ * @warning The size passed must be the exact number of elements in the

+ *          control or indicator.

+ *

+ * @param session handle to a currently open session

+ * @param control control or indicator to which to write

+ * @param array entire array to write

+ * @param size exact number of elements in the control or indicator

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WriteArrayI64(NiFpga_Session session,

+                                   uint32_t       control,

+                                   const int64_t* array,

+                                   size_t         size);

+

+/**

+ * Writes an entire array of unsigned 64-bit integer values to a given array

+ * control or indicator.

+ *

+ * @warning The size passed must be the exact number of elements in the

+ *          control or indicator.

+ *

+ * @param session handle to a currently open session

+ * @param control control or indicator to which to write

+ * @param array entire array to write

+ * @param size exact number of elements in the control or indicator

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WriteArrayU64(NiFpga_Session  session,

+                                   uint32_t        control,

+                                   const uint64_t* array,

+                                   size_t          size);

+

+/**

+ * Enumeration of all 32 possible IRQs. Multiple IRQs can be bitwise ORed

+ * together like this:

+ *

+ *    NiFpga_Irq_3 | NiFpga_Irq_23

+ */

+typedef enum

+{

+   NiFpga_Irq_0  = 1 << 0,

+   NiFpga_Irq_1  = 1 << 1,

+   NiFpga_Irq_2  = 1 << 2,

+   NiFpga_Irq_3  = 1 << 3,

+   NiFpga_Irq_4  = 1 << 4,

+   NiFpga_Irq_5  = 1 << 5,

+   NiFpga_Irq_6  = 1 << 6,

+   NiFpga_Irq_7  = 1 << 7,

+   NiFpga_Irq_8  = 1 << 8,

+   NiFpga_Irq_9  = 1 << 9,

+   NiFpga_Irq_10 = 1 << 10,

+   NiFpga_Irq_11 = 1 << 11,

+   NiFpga_Irq_12 = 1 << 12,

+   NiFpga_Irq_13 = 1 << 13,

+   NiFpga_Irq_14 = 1 << 14,

+   NiFpga_Irq_15 = 1 << 15,

+   NiFpga_Irq_16 = 1 << 16,

+   NiFpga_Irq_17 = 1 << 17,

+   NiFpga_Irq_18 = 1 << 18,

+   NiFpga_Irq_19 = 1 << 19,

+   NiFpga_Irq_20 = 1 << 20,

+   NiFpga_Irq_21 = 1 << 21,

+   NiFpga_Irq_22 = 1 << 22,

+   NiFpga_Irq_23 = 1 << 23,

+   NiFpga_Irq_24 = 1 << 24,

+   NiFpga_Irq_25 = 1 << 25,

+   NiFpga_Irq_26 = 1 << 26,

+   NiFpga_Irq_27 = 1 << 27,

+   NiFpga_Irq_28 = 1 << 28,

+   NiFpga_Irq_29 = 1 << 29,

+   NiFpga_Irq_30 = 1 << 30,

+   NiFpga_Irq_31 = 1U << 31

+} NiFpga_Irq;

+

+/**

+ * Represents an infinite timeout.

+ */

+static const uint32_t NiFpga_InfiniteTimeout = 0xFFFFFFFF;

+

+/**

+ * See NiFpga_ReserveIrqContext for more information.

+ */

+typedef void* NiFpga_IrqContext;

+

+/**

+ * IRQ contexts are single-threaded; only one thread can wait with a

+ * particular context at any given time. To minimize jitter when first

+ * waiting on IRQs, reserve as many contexts as the application

+ * requires.

+ *

+ * If a context is successfully reserved (the returned status is not an error),

+ * it must be unreserved later. Otherwise a memory leak will occur.

+ *

+ * @param session handle to a currently open session

+ * @param context outputs the IRQ context

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReserveIrqContext(NiFpga_Session     session,

+                                       NiFpga_IrqContext* context);

+

+/**

+ * Unreserves an IRQ context obtained from NiFpga_ReserveIrqContext.

+ *

+ * @param session handle to a currently open session

+ * @param context IRQ context to unreserve

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_UnreserveIrqContext(NiFpga_Session    session,

+                                         NiFpga_IrqContext context);

+

+/**

+ * This is a blocking function that stops the calling thread until the

+ * FPGA asserts any IRQ in the irqs parameter, or until the function

+ * call times out.  Before calling this function, use

+ * NiFpga_ReserveIrqContext to reserve an IRQ context. No other

+ * threads can use the same context when this function is called.

+ *

+ * You can use the irqsAsserted parameter to determine which IRQs were asserted

+ * for each function call.

+ *

+ * @param session handle to a currently open session

+ * @param context IRQ context with which to wait

+ * @param irqs bitwise OR of NiFpga_Irqs

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param irqsAsserted if non-NULL, outputs bitwise OR of IRQs that were

+ *                     asserted

+ * @param timedOut if non-NULL, outputs whether the timeout expired

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WaitOnIrqs(NiFpga_Session    session,

+                                NiFpga_IrqContext context,

+                                uint32_t          irqs,

+                                uint32_t          timeout,

+                                uint32_t*         irqsAsserted,

+                                NiFpga_Bool*      timedOut);

+

+/**

+ * Acknowledges an IRQ or set of IRQs.

+ *

+ * @param session handle to a currently open session

+ * @param irqs bitwise OR of NiFpga_Irqs

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_AcknowledgeIrqs(NiFpga_Session session,

+                                     uint32_t       irqs);

+

+/**

+ * Specifies the depth of the host memory part of the DMA FIFO. This method is

+ * optional. In order to see the actual depth configured, use

+ * NiFpga_ConfigureFifo2.

+ *

+ * @param session handle to a currently open session

+ * @param fifo FIFO to configure

+ * @param depth requested number of elements in the host memory part of the

+ *              DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ConfigureFifo(NiFpga_Session session,

+                                   uint32_t       fifo,

+                                   size_t         depth);

+

+/**

+ * Specifies the depth of the host memory part of the DMA FIFO. This method is

+ * optional.

+ *

+ * @param session handle to a currently open session

+ * @param fifo FIFO to configure

+ * @param requestedDepth requested number of elements in the host memory part

+ *                       of the DMA FIFO

+ * @param actualDepth if non-NULL, outputs the actual number of elements in the

+ *                    host memory part of the DMA FIFO, which may be more than

+ *                    the requested number

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ConfigureFifo2(NiFpga_Session session,

+                                    uint32_t       fifo,

+                                    size_t         requestedDepth,

+                                    size_t*        actualDepth);

+

+/**

+ * Starts a FIFO. This method is optional.

+ *

+ * @param session handle to a currently open session

+ * @param fifo FIFO to start

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_StartFifo(NiFpga_Session session,

+                               uint32_t       fifo);

+

+/**

+ * Stops a FIFO. This method is optional.

+ *

+ * @param session handle to a currently open session

+ * @param fifo FIFO to stop

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_StopFifo(NiFpga_Session session,

+                              uint32_t       fifo);

+

+/**

+ * Reads from a target-to-host FIFO of booleans.

+ *

+ * @param session handle to a currently open session

+ * @param fifo target-to-host FIFO from which to read

+ * @param data outputs the data that was read

+ * @param numberOfElements number of elements to read

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param elementsRemaining if non-NULL, outputs the number of elements

+ *                          remaining in the host memory part of the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReadFifoBool(NiFpga_Session session,

+                                  uint32_t       fifo,

+                                  NiFpga_Bool*   data,

+                                  size_t         numberOfElements,

+                                  uint32_t       timeout,

+                                  size_t*        elementsRemaining);

+

+/**

+ * Reads from a target-to-host FIFO of signed 8-bit integers.

+ *

+ * @param session handle to a currently open session

+ * @param fifo target-to-host FIFO from which to read

+ * @param data outputs the data that was read

+ * @param numberOfElements number of elements to read

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param elementsRemaining if non-NULL, outputs the number of elements

+ *                          remaining in the host memory part of the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReadFifoI8(NiFpga_Session session,

+                                uint32_t       fifo,

+                                int8_t*        data,

+                                size_t         numberOfElements,

+                                uint32_t       timeout,

+                                size_t*        elementsRemaining);

+

+/**

+ * Reads from a target-to-host FIFO of unsigned 8-bit integers.

+ *

+ * @param session handle to a currently open session

+ * @param fifo target-to-host FIFO from which to read

+ * @param data outputs the data that was read

+ * @param numberOfElements number of elements to read

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param elementsRemaining if non-NULL, outputs the number of elements

+ *                          remaining in the host memory part of the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReadFifoU8(NiFpga_Session session,

+                                uint32_t       fifo,

+                                uint8_t*       data,

+                                size_t         numberOfElements,

+                                uint32_t       timeout,

+                                size_t*        elementsRemaining);

+

+/**

+ * Reads from a target-to-host FIFO of signed 16-bit integers.

+ *

+ * @param session handle to a currently open session

+ * @param fifo target-to-host FIFO from which to read

+ * @param data outputs the data that was read

+ * @param numberOfElements number of elements to read

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param elementsRemaining if non-NULL, outputs the number of elements

+ *                          remaining in the host memory part of the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReadFifoI16(NiFpga_Session session,

+                                 uint32_t       fifo,

+                                 int16_t*       data,

+                                 size_t         numberOfElements,

+                                 uint32_t       timeout,

+                                 size_t*        elementsRemaining);

+

+/**

+ * Reads from a target-to-host FIFO of unsigned 16-bit integers.

+ *

+ * @param session handle to a currently open session

+ * @param fifo target-to-host FIFO from which to read

+ * @param data outputs the data that was read

+ * @param numberOfElements number of elements to read

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param elementsRemaining if non-NULL, outputs the number of elements

+ *                          remaining in the host memory part of the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReadFifoU16(NiFpga_Session session,

+                                 uint32_t       fifo,

+                                 uint16_t*      data,

+                                 size_t         numberOfElements,

+                                 uint32_t       timeout,

+                                 size_t*        elementsRemaining);

+

+/**

+ * Reads from a target-to-host FIFO of signed 32-bit integers.

+ *

+ * @param session handle to a currently open session

+ * @param fifo target-to-host FIFO from which to read

+ * @param data outputs the data that was read

+ * @param numberOfElements number of elements to read

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param elementsRemaining if non-NULL, outputs the number of elements

+ *                          remaining in the host memory part of the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReadFifoI32(NiFpga_Session session,

+                                 uint32_t       fifo,

+                                 int32_t*       data,

+                                 size_t         numberOfElements,

+                                 uint32_t       timeout,

+                                 size_t*        elementsRemaining);

+

+/**

+ * Reads from a target-to-host FIFO of unsigned 32-bit integers.

+ *

+ * @param session handle to a currently open session

+ * @param fifo target-to-host FIFO from which to read

+ * @param data outputs the data that was read

+ * @param numberOfElements number of elements to read

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param elementsRemaining if non-NULL, outputs the number of elements

+ *                          remaining in the host memory part of the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReadFifoU32(NiFpga_Session session,

+                                 uint32_t       fifo,

+                                 uint32_t*      data,

+                                 size_t         numberOfElements,

+                                 uint32_t       timeout,

+                                 size_t*        elementsRemaining);

+

+/**

+ * Reads from a target-to-host FIFO of signed 64-bit integers.

+ *

+ * @param session handle to a currently open session

+ * @param fifo target-to-host FIFO from which to read

+ * @param data outputs the data that was read

+ * @param numberOfElements number of elements to read

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param elementsRemaining if non-NULL, outputs the number of elements

+ *                          remaining in the host memory part of the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReadFifoI64(NiFpga_Session session,

+                                 uint32_t       fifo,

+                                 int64_t*       data,

+                                 size_t         numberOfElements,

+                                 uint32_t       timeout,

+                                 size_t*        elementsRemaining);

+

+/**

+ * Reads from a target-to-host FIFO of unsigned 64-bit integers.

+ *

+ * @param session handle to a currently open session

+ * @param fifo target-to-host FIFO from which to read

+ * @param data outputs the data that was read

+ * @param numberOfElements number of elements to read

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param elementsRemaining if non-NULL, outputs the number of elements

+ *                          remaining in the host memory part of the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReadFifoU64(NiFpga_Session session,

+                                 uint32_t       fifo,

+                                 uint64_t*      data,

+                                 size_t         numberOfElements,

+                                 uint32_t       timeout,

+                                 size_t*        elementsRemaining);

+

+/**

+ * Writes to a host-to-target FIFO of booleans.

+ *

+ * @param session handle to a currently open session

+ * @param fifo host-to-target FIFO to which to write

+ * @param data data to write

+ * @param numberOfElements number of elements to write

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param emptyElementsRemaining if non-NULL, outputs the number of empty

+ *                               elements remaining in the host memory part of

+ *                               the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WriteFifoBool(NiFpga_Session     session,

+                                   uint32_t           fifo,

+                                   const NiFpga_Bool* data,

+                                   size_t             numberOfElements,

+                                   uint32_t           timeout,

+                                   size_t*            emptyElementsRemaining);

+

+/**

+ * Writes to a host-to-target FIFO of signed 8-bit integers.

+ *

+ * @param session handle to a currently open session

+ * @param fifo host-to-target FIFO to which to write

+ * @param data data to write

+ * @param numberOfElements number of elements to write

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param emptyElementsRemaining if non-NULL, outputs the number of empty

+ *                               elements remaining in the host memory part of

+ *                               the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WriteFifoI8(NiFpga_Session session,

+                                 uint32_t       fifo,

+                                 const int8_t*  data,

+                                 size_t         numberOfElements,

+                                 uint32_t       timeout,

+                                 size_t*        emptyElementsRemaining);

+

+/**

+ * Writes to a host-to-target FIFO of unsigned 8-bit integers.

+ *

+ * @param session handle to a currently open session

+ * @param fifo host-to-target FIFO to which to write

+ * @param data data to write

+ * @param numberOfElements number of elements to write

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param emptyElementsRemaining if non-NULL, outputs the number of empty

+ *                               elements remaining in the host memory part of

+ *                               the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WriteFifoU8(NiFpga_Session session,

+                                 uint32_t       fifo,

+                                 const uint8_t* data,

+                                 size_t         numberOfElements,

+                                 uint32_t       timeout,

+                                 size_t*        emptyElementsRemaining);

+

+/**

+ * Writes to a host-to-target FIFO of signed 16-bit integers.

+ *

+ * @param session handle to a currently open session

+ * @param fifo host-to-target FIFO to which to write

+ * @param data data to write

+ * @param numberOfElements number of elements to write

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param emptyElementsRemaining if non-NULL, outputs the number of empty

+ *                               elements remaining in the host memory part of

+ *                               the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WriteFifoI16(NiFpga_Session session,

+                                  uint32_t       fifo,

+                                  const int16_t* data,

+                                  size_t         numberOfElements,

+                                  uint32_t       timeout,

+                                  size_t*        emptyElementsRemaining);

+

+/**

+ * Writes to a host-to-target FIFO of unsigned 16-bit integers.

+ *

+ * @param session handle to a currently open session

+ * @param fifo host-to-target FIFO to which to write

+ * @param data data to write

+ * @param numberOfElements number of elements to write

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param emptyElementsRemaining if non-NULL, outputs the number of empty

+ *                               elements remaining in the host memory part of

+ *                               the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WriteFifoU16(NiFpga_Session  session,

+                                  uint32_t        fifo,

+                                  const uint16_t* data,

+                                  size_t          numberOfElements,

+                                  uint32_t        timeout,

+                                  size_t*         emptyElementsRemaining);

+

+/**

+ * Writes to a host-to-target FIFO of signed 32-bit integers.

+ *

+ * @param session handle to a currently open session

+ * @param fifo host-to-target FIFO to which to write

+ * @param data data to write

+ * @param numberOfElements number of elements to write

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param emptyElementsRemaining if non-NULL, outputs the number of empty

+ *                               elements remaining in the host memory part of

+ *                               the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WriteFifoI32(NiFpga_Session session,

+                                  uint32_t       fifo,

+                                  const int32_t* data,

+                                  size_t         numberOfElements,

+                                  uint32_t       timeout,

+                                  size_t*        emptyElementsRemaining);

+

+/**

+ * Writes to a host-to-target FIFO of unsigned 32-bit integers.

+ *

+ * @param session handle to a currently open session

+ * @param fifo host-to-target FIFO to which to write

+ * @param data data to write

+ * @param numberOfElements number of elements to write

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param emptyElementsRemaining if non-NULL, outputs the number of empty

+ *                               elements remaining in the host memory part of

+ *                               the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WriteFifoU32(NiFpga_Session  session,

+                                  uint32_t        fifo,

+                                  const uint32_t* data,

+                                  size_t          numberOfElements,

+                                  uint32_t        timeout,

+                                  size_t*         emptyElementsRemaining);

+

+/**

+ * Writes to a host-to-target FIFO of signed 64-bit integers.

+ *

+ * @param session handle to a currently open session

+ * @param fifo host-to-target FIFO to which to write

+ * @param data data to write

+ * @param numberOfElements number of elements to write

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param emptyElementsRemaining if non-NULL, outputs the number of empty

+ *                               elements remaining in the host memory part of

+ *                               the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WriteFifoI64(NiFpga_Session session,

+                                  uint32_t       fifo,

+                                  const int64_t* data,

+                                  size_t         numberOfElements,

+                                  uint32_t       timeout,

+                                  size_t*        emptyElementsRemaining);

+

+/**

+ * Writes to a host-to-target FIFO of unsigned 64-bit integers.

+ *

+ * @param session handle to a currently open session

+ * @param fifo host-to-target FIFO to which to write

+ * @param data data to write

+ * @param numberOfElements number of elements to write

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param emptyElementsRemaining if non-NULL, outputs the number of empty

+ *                               elements remaining in the host memory part of

+ *                               the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_WriteFifoU64(NiFpga_Session  session,

+                                  uint32_t        fifo,

+                                  const uint64_t* data,

+                                  size_t          numberOfElements,

+                                  uint32_t        timeout,

+                                  size_t*         emptyElementsRemaining);

+

+/**

+ * Acquires elements for reading from a target-to-host FIFO of booleans.

+ *

+ * Acquiring, reading, and releasing FIFO elements prevents the need to copy

+ * the contents of elements from the host memory buffer to a separate

+ * user-allocated buffer before reading. The FPGA target cannot write to

+ * elements acquired by the host. Therefore, the host must release elements

+ * after reading them. The number of elements acquired may differ from the

+ * number of elements requested if, for example, the number of elements

+ * requested reaches the end of the host memory buffer. Always release all

+ * acquired elements before closing the session. Do not attempt to access FIFO

+ * elements after the elements are released or the session is closed.

+ *

+ * @param session handle to a currently open session

+ * @param fifo target-to-host FIFO from which to read

+ * @param elements outputs a pointer to the elements acquired

+ * @param elementsRequested requested number of elements

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param elementsAcquired actual number of elements acquired, which may be

+ *                         less than the requested number

+ * @param elementsRemaining if non-NULL, outputs the number of elements

+ *                          remaining in the host memory part of the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_AcquireFifoReadElementsBool(

+                                             NiFpga_Session session,

+                                             uint32_t       fifo,

+                                             NiFpga_Bool**  elements,

+                                             size_t         elementsRequested,

+                                             uint32_t       timeout,

+                                             size_t*        elementsAcquired,

+                                             size_t*        elementsRemaining);

+

+/**

+ * Acquires elements for reading from a target-to-host FIFO of signed 8-bit

+ * integers.

+ *

+ * Acquiring, reading, and releasing FIFO elements prevents the need to copy

+ * the contents of elements from the host memory buffer to a separate

+ * user-allocated buffer before reading. The FPGA target cannot write to

+ * elements acquired by the host. Therefore, the host must release elements

+ * after reading them. The number of elements acquired may differ from the

+ * number of elements requested if, for example, the number of elements

+ * requested reaches the end of the host memory buffer. Always release all

+ * acquired elements before closing the session. Do not attempt to access FIFO

+ * elements after the elements are released or the session is closed.

+ *

+ * @param session handle to a currently open session

+ * @param fifo target-to-host FIFO from which to read

+ * @param elements outputs a pointer to the elements acquired

+ * @param elementsRequested requested number of elements

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param elementsAcquired actual number of elements acquired, which may be

+ *                         less than the requested number

+ * @param elementsRemaining if non-NULL, outputs the number of elements

+ *                          remaining in the host memory part of the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_AcquireFifoReadElementsI8(

+                                             NiFpga_Session session,

+                                             uint32_t       fifo,

+                                             int8_t**       elements,

+                                             size_t         elementsRequested,

+                                             uint32_t       timeout,

+                                             size_t*        elementsAcquired,

+                                             size_t*        elementsRemaining);

+

+/**

+ * Acquires elements for reading from a target-to-host FIFO of unsigned 8-bit

+ * integers.

+ *

+ * Acquiring, reading, and releasing FIFO elements prevents the need to copy

+ * the contents of elements from the host memory buffer to a separate

+ * user-allocated buffer before reading. The FPGA target cannot write to

+ * elements acquired by the host. Therefore, the host must release elements

+ * after reading them. The number of elements acquired may differ from the

+ * number of elements requested if, for example, the number of elements

+ * requested reaches the end of the host memory buffer. Always release all

+ * acquired elements before closing the session. Do not attempt to access FIFO

+ * elements after the elements are released or the session is closed.

+ *

+ * @param session handle to a currently open session

+ * @param fifo target-to-host FIFO from which to read

+ * @param elements outputs a pointer to the elements acquired

+ * @param elementsRequested requested number of elements

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param elementsAcquired actual number of elements acquired, which may be

+ *                         less than the requested number

+ * @param elementsRemaining if non-NULL, outputs the number of elements

+ *                          remaining in the host memory part of the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_AcquireFifoReadElementsU8(

+                                            NiFpga_Session  session,

+                                            uint32_t        fifo,

+                                            uint8_t**       elements,

+                                            size_t          elementsRequested,

+                                            uint32_t        timeout,

+                                            size_t*         elementsAcquired,

+                                            size_t*         elementsRemaining);

+

+/**

+ * Acquires elements for reading from a target-to-host FIFO of signed 16-bit

+ * integers.

+ *

+ * Acquiring, reading, and releasing FIFO elements prevents the need to copy

+ * the contents of elements from the host memory buffer to a separate

+ * user-allocated buffer before reading. The FPGA target cannot write to

+ * elements acquired by the host. Therefore, the host must release elements

+ * after reading them. The number of elements acquired may differ from the

+ * number of elements requested if, for example, the number of elements

+ * requested reaches the end of the host memory buffer. Always release all

+ * acquired elements before closing the session. Do not attempt to access FIFO

+ * elements after the elements are released or the session is closed.

+ *

+ * @param session handle to a currently open session

+ * @param fifo target-to-host FIFO from which to read

+ * @param elements outputs a pointer to the elements acquired

+ * @param elementsRequested requested number of elements

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param elementsAcquired actual number of elements acquired, which may be

+ *                         less than the requested number

+ * @param elementsRemaining if non-NULL, outputs the number of elements

+ *                          remaining in the host memory part of the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_AcquireFifoReadElementsI16(

+                                            NiFpga_Session  session,

+                                            uint32_t        fifo,

+                                            int16_t**       elements,

+                                            size_t          elementsRequested,

+                                            uint32_t        timeout,

+                                            size_t*         elementsAcquired,

+                                            size_t*         elementsRemaining);

+

+/**

+ * Acquires elements for reading from a target-to-host FIFO of unsigned 16-bit

+ * integers.

+ *

+ * Acquiring, reading, and releasing FIFO elements prevents the need to copy

+ * the contents of elements from the host memory buffer to a separate

+ * user-allocated buffer before reading. The FPGA target cannot write to

+ * elements acquired by the host. Therefore, the host must release elements

+ * after reading them. The number of elements acquired may differ from the

+ * number of elements requested if, for example, the number of elements

+ * requested reaches the end of the host memory buffer. Always release all

+ * acquired elements before closing the session. Do not attempt to access FIFO

+ * elements after the elements are released or the session is closed.

+ *

+ * @param session handle to a currently open session

+ * @param fifo target-to-host FIFO from which to read

+ * @param elements outputs a pointer to the elements acquired

+ * @param elementsRequested requested number of elements

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param elementsAcquired actual number of elements acquired, which may be

+ *                         less than the requested number

+ * @param elementsRemaining if non-NULL, outputs the number of elements

+ *                          remaining in the host memory part of the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_AcquireFifoReadElementsU16(

+                                           NiFpga_Session   session,

+                                           uint32_t         fifo,

+                                           uint16_t**       elements,

+                                           size_t           elementsRequested,

+                                           uint32_t         timeout,

+                                           size_t*          elementsAcquired,

+                                           size_t*          elementsRemaining);

+

+/**

+ * Acquires elements for reading from a target-to-host FIFO of signed 32-bit

+ * integers.

+ *

+ * Acquiring, reading, and releasing FIFO elements prevents the need to copy

+ * the contents of elements from the host memory buffer to a separate

+ * user-allocated buffer before reading. The FPGA target cannot write to

+ * elements acquired by the host. Therefore, the host must release elements

+ * after reading them. The number of elements acquired may differ from the

+ * number of elements requested if, for example, the number of elements

+ * requested reaches the end of the host memory buffer. Always release all

+ * acquired elements before closing the session. Do not attempt to access FIFO

+ * elements after the elements are released or the session is closed.

+ *

+ * @param session handle to a currently open session

+ * @param fifo target-to-host FIFO from which to read

+ * @param elements outputs a pointer to the elements acquired

+ * @param elementsRequested requested number of elements

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param elementsAcquired actual number of elements acquired, which may be

+ *                         less than the requested number

+ * @param elementsRemaining if non-NULL, outputs the number of elements

+ *                          remaining in the host memory part of the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_AcquireFifoReadElementsI32(

+                                            NiFpga_Session  session,

+                                            uint32_t        fifo,

+                                            int32_t**       elements,

+                                            size_t          elementsRequested,

+                                            uint32_t        timeout,

+                                            size_t*         elementsAcquired,

+                                            size_t*         elementsRemaining);

+

+/**

+ * Acquires elements for reading from a target-to-host FIFO of unsigned 32-bit

+ * integers.

+ *

+ * Acquiring, reading, and releasing FIFO elements prevents the need to copy

+ * the contents of elements from the host memory buffer to a separate

+ * user-allocated buffer before reading. The FPGA target cannot write to

+ * elements acquired by the host. Therefore, the host must release elements

+ * after reading them. The number of elements acquired may differ from the

+ * number of elements requested if, for example, the number of elements

+ * requested reaches the end of the host memory buffer. Always release all

+ * acquired elements before closing the session. Do not attempt to access FIFO

+ * elements after the elements are released or the session is closed.

+ *

+ * @param session handle to a currently open session

+ * @param fifo target-to-host FIFO from which to read

+ * @param elements outputs a pointer to the elements acquired

+ * @param elementsRequested requested number of elements

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param elementsAcquired actual number of elements acquired, which may be

+ *                         less than the requested number

+ * @param elementsRemaining if non-NULL, outputs the number of elements

+ *                          remaining in the host memory part of the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_AcquireFifoReadElementsU32(

+                                           NiFpga_Session   session,

+                                           uint32_t         fifo,

+                                           uint32_t**       elements,

+                                           size_t           elementsRequested,

+                                           uint32_t         timeout,

+                                           size_t*          elementsAcquired,

+                                           size_t*          elementsRemaining);

+

+/**

+ * Acquires elements for reading from a target-to-host FIFO of signed 64-bit

+ * integers.

+ *

+ * Acquiring, reading, and releasing FIFO elements prevents the need to copy

+ * the contents of elements from the host memory buffer to a separate

+ * user-allocated buffer before reading. The FPGA target cannot write to

+ * elements acquired by the host. Therefore, the host must release elements

+ * after reading them. The number of elements acquired may differ from the

+ * number of elements requested if, for example, the number of elements

+ * requested reaches the end of the host memory buffer. Always release all

+ * acquired elements before closing the session. Do not attempt to access FIFO

+ * elements after the elements are released or the session is closed.

+ *

+ * @param session handle to a currently open session

+ * @param fifo target-to-host FIFO from which to read

+ * @param elements outputs a pointer to the elements acquired

+ * @param elementsRequested requested number of elements

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param elementsAcquired actual number of elements acquired, which may be

+ *                         less than the requested number

+ * @param elementsRemaining if non-NULL, outputs the number of elements

+ *                          remaining in the host memory part of the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_AcquireFifoReadElementsI64(

+                                            NiFpga_Session  session,

+                                            uint32_t        fifo,

+                                            int64_t**       elements,

+                                            size_t          elementsRequested,

+                                            uint32_t        timeout,

+                                            size_t*         elementsAcquired,

+                                            size_t*         elementsRemaining);

+

+/**

+ * Acquires elements for reading from a target-to-host FIFO of unsigned 64-bit

+ * integers.

+ *

+ * Acquiring, reading, and releasing FIFO elements prevents the need to copy

+ * the contents of elements from the host memory buffer to a separate

+ * user-allocated buffer before reading. The FPGA target cannot write to

+ * elements acquired by the host. Therefore, the host must release elements

+ * after reading them. The number of elements acquired may differ from the

+ * number of elements requested if, for example, the number of elements

+ * requested reaches the end of the host memory buffer. Always release all

+ * acquired elements before closing the session. Do not attempt to access FIFO

+ * elements after the elements are released or the session is closed.

+ *

+ * @param session handle to a currently open session

+ * @param fifo target-to-host FIFO from which to read

+ * @param elements outputs a pointer to the elements acquired

+ * @param elementsRequested requested number of elements

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param elementsAcquired actual number of elements acquired, which may be

+ *                         less than the requested number

+ * @param elementsRemaining if non-NULL, outputs the number of elements

+ *                          remaining in the host memory part of the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_AcquireFifoReadElementsU64(

+                                           NiFpga_Session   session,

+                                           uint32_t         fifo,

+                                           uint64_t**       elements,

+                                           size_t           elementsRequested,

+                                           uint32_t         timeout,

+                                           size_t*          elementsAcquired,

+                                           size_t*          elementsRemaining);

+

+/**

+ * Acquires elements for writing to a host-to-target FIFO of booleans.

+ *

+ * Acquiring, writing, and releasing FIFO elements prevents the need to write

+ * first into a separate user-allocated buffer and then copy the contents of

+ * elements to the host memory buffer. The FPGA target cannot read elements

+ * acquired by the host. Therefore, the host must release elements after

+ * writing to them. The number of elements acquired may differ from the number

+ * of elements requested if, for example, the number of elements requested

+ * reaches the end of the host memory buffer. Always release all acquired

+ * elements before closing the session. Do not attempt to access FIFO elements

+ * after the elements are released or the session is closed.

+ *

+ * @param session handle to a currently open session

+ * @param fifo host-to-target FIFO to which to write

+ * @param elements outputs a pointer to the elements acquired

+ * @param elementsRequested requested number of elements

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param elementsAcquired actual number of elements acquired, which may be

+ *                         less than the requested number

+ * @param elementsRemaining if non-NULL, outputs the number of elements

+ *                          remaining in the host memory part of the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_AcquireFifoWriteElementsBool(

+                                             NiFpga_Session session,

+                                             uint32_t       fifo,

+                                             NiFpga_Bool**  elements,

+                                             size_t         elementsRequested,

+                                             uint32_t       timeout,

+                                             size_t*        elementsAcquired,

+                                             size_t*        elementsRemaining);

+

+/**

+ * Acquires elements for writing to a host-to-target FIFO of signed 8-bit

+ * integers.

+ *

+ * Acquiring, writing, and releasing FIFO elements prevents the need to write

+ * first into a separate user-allocated buffer and then copy the contents of

+ * elements to the host memory buffer. The FPGA target cannot read elements

+ * acquired by the host. Therefore, the host must release elements after

+ * writing to them. The number of elements acquired may differ from the number

+ * of elements requested if, for example, the number of elements requested

+ * reaches the end of the host memory buffer. Always release all acquired

+ * elements before closing the session. Do not attempt to access FIFO elements

+ * after the elements are released or the session is closed.

+ *

+ * @param session handle to a currently open session

+ * @param fifo host-to-target FIFO to which to write

+ * @param elements outputs a pointer to the elements acquired

+ * @param elementsRequested requested number of elements

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param elementsAcquired actual number of elements acquired, which may be

+ *                         less than the requested number

+ * @param elementsRemaining if non-NULL, outputs the number of elements

+ *                          remaining in the host memory part of the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_AcquireFifoWriteElementsI8(

+                                             NiFpga_Session session,

+                                             uint32_t       fifo,

+                                             int8_t**       elements,

+                                             size_t         elementsRequested,

+                                             uint32_t       timeout,

+                                             size_t*        elementsAcquired,

+                                             size_t*        elementsRemaining);

+

+/**

+ * Acquires elements for writing to a host-to-target FIFO of unsigned 8-bit

+ * integers.

+ *

+ * Acquiring, writing, and releasing FIFO elements prevents the need to write

+ * first into a separate user-allocated buffer and then copy the contents of

+ * elements to the host memory buffer. The FPGA target cannot read elements

+ * acquired by the host. Therefore, the host must release elements after

+ * writing to them. The number of elements acquired may differ from the number

+ * of elements requested if, for example, the number of elements requested

+ * reaches the end of the host memory buffer. Always release all acquired

+ * elements before closing the session. Do not attempt to access FIFO elements

+ * after the elements are released or the session is closed.

+ *

+ * @param session handle to a currently open session

+ * @param fifo host-to-target FIFO to which to write

+ * @param elements outputs a pointer to the elements acquired

+ * @param elementsRequested requested number of elements

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param elementsAcquired actual number of elements acquired, which may be

+ *                         less than the requested number

+ * @param elementsRemaining if non-NULL, outputs the number of elements

+ *                          remaining in the host memory part of the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_AcquireFifoWriteElementsU8(

+                                             NiFpga_Session session,

+                                             uint32_t       fifo,

+                                             uint8_t**      elements,

+                                             size_t         elementsRequested,

+                                             uint32_t       timeout,

+                                             size_t*        elementsAcquired,

+                                             size_t*        elementsRemaining);

+

+/**

+ * Acquires elements for writing to a host-to-target FIFO of signed 16-bit

+ * integers.

+ *

+ * Acquiring, writing, and releasing FIFO elements prevents the need to write

+ * first into a separate user-allocated buffer and then copy the contents of

+ * elements to the host memory buffer. The FPGA target cannot read elements

+ * acquired by the host. Therefore, the host must release elements after

+ * writing to them. The number of elements acquired may differ from the number

+ * of elements requested if, for example, the number of elements requested

+ * reaches the end of the host memory buffer. Always release all acquired

+ * elements before closing the session. Do not attempt to access FIFO elements

+ * after the elements are released or the session is closed.

+ *

+ * @param session handle to a currently open session

+ * @param fifo host-to-target FIFO to which to write

+ * @param elements outputs a pointer to the elements acquired

+ * @param elementsRequested requested number of elements

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param elementsAcquired actual number of elements acquired, which may be

+ *                         less than the requested number

+ * @param elementsRemaining if non-NULL, outputs the number of elements

+ *                          remaining in the host memory part of the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_AcquireFifoWriteElementsI16(

+                                             NiFpga_Session session,

+                                             uint32_t       fifo,

+                                             int16_t**      elements,

+                                             size_t         elementsRequested,

+                                             uint32_t       timeout,

+                                             size_t*        elementsAcquired,

+                                             size_t*        elementsRemaining);

+

+/**

+ * Acquires elements for writing to a host-to-target FIFO of unsigned 16-bit

+ * integers.

+ *

+ * Acquiring, writing, and releasing FIFO elements prevents the need to write

+ * first into a separate user-allocated buffer and then copy the contents of

+ * elements to the host memory buffer. The FPGA target cannot read elements

+ * acquired by the host. Therefore, the host must release elements after

+ * writing to them. The number of elements acquired may differ from the number

+ * of elements requested if, for example, the number of elements requested

+ * reaches the end of the host memory buffer. Always release all acquired

+ * elements before closing the session. Do not attempt to access FIFO elements

+ * after the elements are released or the session is closed.

+ *

+ * @param session handle to a currently open session

+ * @param fifo host-to-target FIFO to which to write

+ * @param elements outputs a pointer to the elements acquired

+ * @param elementsRequested requested number of elements

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param elementsAcquired actual number of elements acquired, which may be

+ *                         less than the requested number

+ * @param elementsRemaining if non-NULL, outputs the number of elements

+ *                          remaining in the host memory part of the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_AcquireFifoWriteElementsU16(

+                                             NiFpga_Session session,

+                                             uint32_t       fifo,

+                                             uint16_t**     elements,

+                                             size_t         elementsRequested,

+                                             uint32_t       timeout,

+                                             size_t*        elementsAcquired,

+                                             size_t*        elementsRemaining);

+

+/**

+ * Acquires elements for writing to a host-to-target FIFO of signed 32-bit

+ * integers.

+ *

+ * Acquiring, writing, and releasing FIFO elements prevents the need to write

+ * first into a separate user-allocated buffer and then copy the contents of

+ * elements to the host memory buffer. The FPGA target cannot read elements

+ * acquired by the host. Therefore, the host must release elements after

+ * writing to them. The number of elements acquired may differ from the number

+ * of elements requested if, for example, the number of elements requested

+ * reaches the end of the host memory buffer. Always release all acquired

+ * elements before closing the session. Do not attempt to access FIFO elements

+ * after the elements are released or the session is closed.

+ *

+ * @param session handle to a currently open session

+ * @param fifo host-to-target FIFO to which to write

+ * @param elements outputs a pointer to the elements acquired

+ * @param elementsRequested requested number of elements

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param elementsAcquired actual number of elements acquired, which may be

+ *                         less than the requested number

+ * @param elementsRemaining if non-NULL, outputs the number of elements

+ *                          remaining in the host memory part of the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_AcquireFifoWriteElementsI32(

+                                             NiFpga_Session session,

+                                             uint32_t       fifo,

+                                             int32_t**      elements,

+                                             size_t         elementsRequested,

+                                             uint32_t       timeout,

+                                             size_t*        elementsAcquired,

+                                             size_t*        elementsRemaining);

+

+/**

+ * Acquires elements for writing to a host-to-target FIFO of unsigned 32-bit

+ * integers.

+ *

+ * Acquiring, writing, and releasing FIFO elements prevents the need to write

+ * first into a separate user-allocated buffer and then copy the contents of

+ * elements to the host memory buffer. The FPGA target cannot read elements

+ * acquired by the host. Therefore, the host must release elements after

+ * writing to them. The number of elements acquired may differ from the number

+ * of elements requested if, for example, the number of elements requested

+ * reaches the end of the host memory buffer. Always release all acquired

+ * elements before closing the session. Do not attempt to access FIFO elements

+ * after the elements are released or the session is closed.

+ *

+ * @param session handle to a currently open session

+ * @param fifo host-to-target FIFO to which to write

+ * @param elements outputs a pointer to the elements acquired

+ * @param elementsRequested requested number of elements

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param elementsAcquired actual number of elements acquired, which may be

+ *                         less than the requested number

+ * @param elementsRemaining if non-NULL, outputs the number of elements

+ *                          remaining in the host memory part of the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_AcquireFifoWriteElementsU32(

+                                             NiFpga_Session session,

+                                             uint32_t       fifo,

+                                             uint32_t**     elements,

+                                             size_t         elementsRequested,

+                                             uint32_t       timeout,

+                                             size_t*        elementsAcquired,

+                                             size_t*        elementsRemaining);

+

+/**

+ * Acquires elements for writing to a host-to-target FIFO of signed 64-bit

+ * integers.

+ *

+ * Acquiring, writing, and releasing FIFO elements prevents the need to write

+ * first into a separate user-allocated buffer and then copy the contents of

+ * elements to the host memory buffer. The FPGA target cannot read elements

+ * acquired by the host. Therefore, the host must release elements after

+ * writing to them. The number of elements acquired may differ from the number

+ * of elements requested if, for example, the number of elements requested

+ * reaches the end of the host memory buffer. Always release all acquired

+ * elements before closing the session. Do not attempt to access FIFO elements

+ * after the elements are released or the session is closed.

+ *

+ * @param session handle to a currently open session

+ * @param fifo host-to-target FIFO to which to write

+ * @param elements outputs a pointer to the elements acquired

+ * @param elementsRequested requested number of elements

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param elementsAcquired actual number of elements acquired, which may be

+ *                         less than the requested number

+ * @param elementsRemaining if non-NULL, outputs the number of elements

+ *                          remaining in the host memory part of the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_AcquireFifoWriteElementsI64(

+                                             NiFpga_Session session,

+                                             uint32_t       fifo,

+                                             int64_t**      elements,

+                                             size_t         elementsRequested,

+                                             uint32_t       timeout,

+                                             size_t*        elementsAcquired,

+                                             size_t*        elementsRemaining);

+

+/**

+ * Acquires elements for writing to a host-to-target FIFO of unsigned 64-bit

+ * integers.

+ *

+ * Acquiring, writing, and releasing FIFO elements prevents the need to write

+ * first into a separate user-allocated buffer and then copy the contents of

+ * elements to the host memory buffer. The FPGA target cannot read elements

+ * acquired by the host. Therefore, the host must release elements after

+ * writing to them. The number of elements acquired may differ from the number

+ * of elements requested if, for example, the number of elements requested

+ * reaches the end of the host memory buffer. Always release all acquired

+ * elements before closing the session. Do not attempt to access FIFO elements

+ * after the elements are released or the session is closed.

+ *

+ * @param session handle to a currently open session

+ * @param fifo host-to-target FIFO to which to write

+ * @param elements outputs a pointer to the elements acquired

+ * @param elementsRequested requested number of elements

+ * @param timeout timeout in milliseconds, or NiFpga_InfiniteTimeout

+ * @param elementsAcquired actual number of elements acquired, which may be

+ *                         less than the requested number

+ * @param elementsRemaining if non-NULL, outputs the number of elements

+ *                          remaining in the host memory part of the DMA FIFO

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_AcquireFifoWriteElementsU64(

+                                             NiFpga_Session session,

+                                             uint32_t       fifo,

+                                             uint64_t**     elements,

+                                             size_t         elementsRequested,

+                                             uint32_t       timeout,

+                                             size_t*        elementsAcquired,

+                                             size_t*        elementsRemaining);

+

+/**

+ * Releases previously acquired FIFO elements.

+ *

+ * The FPGA target cannot read elements acquired by the host. Therefore, the

+ * host must release elements after acquiring them. Always release all acquired

+ * elements before closing the session. Do not attempt to access FIFO elements

+ * after the elements are released or the session is closed.

+ *

+ * @param session handle to a currently open session

+ * @param fifo FIFO from which to release elements

+ * @param elements number of elements to release

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_ReleaseFifoElements(NiFpga_Session session,

+                                         uint32_t       fifo,

+                                         size_t         elements);

+

+/**

+ * Gets an endpoint reference to a peer-to-peer FIFO.

+ *

+ * @param session handle to a currently open session

+ * @param fifo peer-to-peer FIFO

+ * @param endpoint outputs the endpoint reference

+ * @return result of the call

+ */

+NiFpga_Status NiFpga_GetPeerToPeerFifoEndpoint(NiFpga_Session session,

+                                               uint32_t       fifo,

+                                               uint32_t*      endpoint);

+

+#if NiFpga_Cpp

+}

+#endif

+

+#endif

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nInvariantFPGANamespace/nInterfaceGlobals.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nInvariantFPGANamespace/nInterfaceGlobals.h
new file mode 100644
index 0000000..abd07d4
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nInvariantFPGANamespace/nInterfaceGlobals.h
@@ -0,0 +1,15 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_C0EF_1_1_0_nInterfaceGlobals_h__

+#define __nFRC_C0EF_1_1_0_nInterfaceGlobals_h__

+

+namespace nFPGA

+{

+namespace nFRC_C0EF_1_1_0

+{

+   extern unsigned int g_currentTargetClass;

+}

+}

+

+#endif // __nFRC_C0EF_1_1_0_nInterfaceGlobals_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nInvariantFPGANamespace/tAI.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nInvariantFPGANamespace/tAI.h
new file mode 100644
index 0000000..14121b5
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nInvariantFPGANamespace/tAI.h
@@ -0,0 +1,73 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_C0EF_1_1_0_AI_h__

+#define __nFRC_C0EF_1_1_0_AI_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_C0EF_1_1_0

+{

+

+class tAI

+{

+public:

+   tAI(){}

+   virtual ~tAI(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tAI* create(unsigned char sys_index, tRioStatusCode *status);

+   virtual unsigned char getSystemIndex() = 0;

+

+

+   typedef enum

+   {

+      kNumSystems = 2,

+   } tIfaceConstants;

+

+

+

+   typedef enum

+   {

+   } tCalOK_IfaceConstants;

+

+   virtual bool readCalOK(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tDoneTime_IfaceConstants;

+

+   virtual unsigned int readDoneTime(tRioStatusCode *status) = 0;

+

+

+

+

+   typedef enum

+   {

+      kNumOffsetRegisters = 8,

+   } tOffset_IfaceConstants;

+

+   virtual signed int readOffset(unsigned char reg_index, tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+      kNumLSBWeightRegisters = 8,

+   } tLSBWeight_IfaceConstants;

+

+   virtual unsigned int readLSBWeight(unsigned char reg_index, tRioStatusCode *status) = 0;

+

+

+

+private:

+   tAI(const tAI&);

+   void operator=(const tAI&);

+};

+

+}

+}

+

+#endif // __nFRC_C0EF_1_1_0_AI_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nInvariantFPGANamespace/tGlobal.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nInvariantFPGANamespace/tGlobal.h
new file mode 100644
index 0000000..0b74117
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nInvariantFPGANamespace/tGlobal.h
@@ -0,0 +1,69 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_C0EF_1_1_0_Global_h__

+#define __nFRC_C0EF_1_1_0_Global_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_C0EF_1_1_0

+{

+

+class tGlobal

+{

+public:

+   tGlobal(){}

+   virtual ~tGlobal(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tGlobal* create(tRioStatusCode *status);

+

+   typedef enum

+   {

+      kNumSystems = 1,

+   } tIfaceConstants;

+

+

+

+

+   typedef enum

+   {

+   } tVersion_IfaceConstants;

+

+   virtual unsigned short readVersion(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tLocalTime_IfaceConstants;

+

+   virtual unsigned int readLocalTime(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tRevision_IfaceConstants;

+

+   virtual unsigned int readRevision(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tReserved_IfaceConstants;

+

+   virtual unsigned char readReserved(tRioStatusCode *status) = 0;

+

+

+

+

+private:

+   tGlobal(const tGlobal&);

+   void operator=(const tGlobal&);

+};

+

+}

+}

+

+#endif // __nFRC_C0EF_1_1_0_Global_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nInvariantFPGANamespace/tLoadOut.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nInvariantFPGANamespace/tLoadOut.h
new file mode 100644
index 0000000..a7c4ebb
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nInvariantFPGANamespace/tLoadOut.h
@@ -0,0 +1,79 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_C0EF_1_1_0_LoadOut_h__

+#define __nFRC_C0EF_1_1_0_LoadOut_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_C0EF_1_1_0

+{

+

+class tLoadOut

+{

+public:

+   tLoadOut(){}

+   virtual ~tLoadOut(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tLoadOut* create(tRioStatusCode *status);

+

+   typedef enum

+   {

+      kNumSystems = 1,

+   } tIfaceConstants;

+

+

+

+

+   typedef enum

+   {

+   } tReady_IfaceConstants;

+

+   virtual bool readReady(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tDoneTime_IfaceConstants;

+

+   virtual unsigned int readDoneTime(tRioStatusCode *status) = 0;

+

+

+

+

+   typedef enum

+   {

+      kNumVendorIDRegisters = 8,

+   } tVendorID_IfaceConstants;

+

+   virtual unsigned short readVendorID(unsigned char reg_index, tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+      kNumSerialNumberRegisters = 8,

+   } tSerialNumber_IfaceConstants;

+

+   virtual unsigned int readSerialNumber(unsigned char reg_index, tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+      kNumModuleIDRegisters = 8,

+   } tModuleID_IfaceConstants;

+

+   virtual unsigned short readModuleID(unsigned char reg_index, tRioStatusCode *status) = 0;

+

+

+private:

+   tLoadOut(const tLoadOut&);

+   void operator=(const tLoadOut&);

+};

+

+}

+}

+

+#endif // __nFRC_C0EF_1_1_0_LoadOut_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/nInterfaceGlobals.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/nInterfaceGlobals.h
new file mode 100644
index 0000000..9ff5a0e
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/nInterfaceGlobals.h
@@ -0,0 +1,15 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2015_1_0_A_nInterfaceGlobals_h__

+#define __nFRC_2015_1_0_A_nInterfaceGlobals_h__

+

+namespace nFPGA

+{

+namespace nFRC_2015_1_0_A

+{

+   extern unsigned int g_currentTargetClass;

+}

+}

+

+#endif // __nFRC_2015_1_0_A_nInterfaceGlobals_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAI.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAI.h
new file mode 100644
index 0000000..2a8f614
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAI.h
@@ -0,0 +1,143 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2015_1_0_A_AI_h__

+#define __nFRC_2015_1_0_A_AI_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2015_1_0_A

+{

+

+class tAI

+{

+public:

+   tAI(){}

+   virtual ~tAI(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tAI* create(tRioStatusCode *status);

+

+   typedef enum

+   {

+      kNumSystems = 1,

+   } tIfaceConstants;

+

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned ScanSize : 3;

+         unsigned ConvertRate : 26;

+#else

+         unsigned ConvertRate : 26;

+         unsigned ScanSize : 3;

+#endif

+      };

+      struct{

+         unsigned value : 29;

+      };

+   } tConfig;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned Channel : 3;

+         unsigned Averaged : 1;

+#else

+         unsigned Averaged : 1;

+         unsigned Channel : 3;

+#endif

+      };

+      struct{

+         unsigned value : 4;

+      };

+   } tReadSelect;

+

+

+

+   typedef enum

+   {

+   } tOutput_IfaceConstants;

+

+   virtual signed int readOutput(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tConfig_IfaceConstants;

+

+   virtual void writeConfig(tConfig value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_ScanSize(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_ConvertRate(unsigned int value, tRioStatusCode *status) = 0;

+   virtual tConfig readConfig(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_ScanSize(tRioStatusCode *status) = 0;

+   virtual unsigned int readConfig_ConvertRate(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tLoopTiming_IfaceConstants;

+

+   virtual unsigned int readLoopTiming(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+      kNumOversampleBitsElements = 8,

+   } tOversampleBits_IfaceConstants;

+

+   virtual void writeOversampleBits(unsigned char bitfield_index, unsigned char value, tRioStatusCode *status) = 0;

+   virtual unsigned char readOversampleBits(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+      kNumAverageBitsElements = 8,

+   } tAverageBits_IfaceConstants;

+

+   virtual void writeAverageBits(unsigned char bitfield_index, unsigned char value, tRioStatusCode *status) = 0;

+   virtual unsigned char readAverageBits(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+      kNumScanListElements = 8,

+   } tScanList_IfaceConstants;

+

+   virtual void writeScanList(unsigned char bitfield_index, unsigned char value, tRioStatusCode *status) = 0;

+   virtual unsigned char readScanList(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tLatchOutput_IfaceConstants;

+

+   virtual void strobeLatchOutput(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tReadSelect_IfaceConstants;

+

+   virtual void writeReadSelect(tReadSelect value, tRioStatusCode *status) = 0;

+   virtual void writeReadSelect_Channel(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeReadSelect_Averaged(bool value, tRioStatusCode *status) = 0;

+   virtual tReadSelect readReadSelect(tRioStatusCode *status) = 0;

+   virtual unsigned char readReadSelect_Channel(tRioStatusCode *status) = 0;

+   virtual bool readReadSelect_Averaged(tRioStatusCode *status) = 0;

+

+

+

+

+private:

+   tAI(const tAI&);

+   void operator=(const tAI&);

+};

+

+}

+}

+

+#endif // __nFRC_2015_1_0_A_AI_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAO.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAO.h
new file mode 100644
index 0000000..7160f04
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAO.h
@@ -0,0 +1,50 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2015_1_0_A_AO_h__

+#define __nFRC_2015_1_0_A_AO_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2015_1_0_A

+{

+

+class tAO

+{

+public:

+   tAO(){}

+   virtual ~tAO(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tAO* create(tRioStatusCode *status);

+

+   typedef enum

+   {

+      kNumSystems = 1,

+   } tIfaceConstants;

+

+

+

+

+

+

+   typedef enum

+   {

+      kNumMXPRegisters = 2,

+   } tMXP_IfaceConstants;

+

+   virtual void writeMXP(unsigned char reg_index, unsigned short value, tRioStatusCode *status) = 0;

+   virtual unsigned short readMXP(unsigned char reg_index, tRioStatusCode *status) = 0;

+

+

+private:

+   tAO(const tAO&);

+   void operator=(const tAO&);

+};

+

+}

+}

+

+#endif // __nFRC_2015_1_0_A_AO_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAccel.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAccel.h
new file mode 100644
index 0000000..02318de
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAccel.h
@@ -0,0 +1,102 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2015_1_0_A_Accel_h__

+#define __nFRC_2015_1_0_A_Accel_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2015_1_0_A

+{

+

+class tAccel

+{

+public:

+   tAccel(){}

+   virtual ~tAccel(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tAccel* create(tRioStatusCode *status);

+

+   typedef enum

+   {

+      kNumSystems = 1,

+   } tIfaceConstants;

+

+

+

+

+   typedef enum

+   {

+   } tSTAT_IfaceConstants;

+

+   virtual unsigned char readSTAT(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tCNTR_IfaceConstants;

+

+   virtual void writeCNTR(unsigned char value, tRioStatusCode *status) = 0;

+   virtual unsigned char readCNTR(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tDATO_IfaceConstants;

+

+   virtual void writeDATO(unsigned char value, tRioStatusCode *status) = 0;

+   virtual unsigned char readDATO(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tCNFG_IfaceConstants;

+

+   virtual void writeCNFG(unsigned char value, tRioStatusCode *status) = 0;

+   virtual unsigned char readCNFG(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tCNTL_IfaceConstants;

+

+   virtual void writeCNTL(unsigned char value, tRioStatusCode *status) = 0;

+   virtual unsigned char readCNTL(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tDATI_IfaceConstants;

+

+   virtual unsigned char readDATI(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tGO_IfaceConstants;

+

+   virtual void strobeGO(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tADDR_IfaceConstants;

+

+   virtual void writeADDR(unsigned char value, tRioStatusCode *status) = 0;

+   virtual unsigned char readADDR(tRioStatusCode *status) = 0;

+

+

+

+

+private:

+   tAccel(const tAccel&);

+   void operator=(const tAccel&);

+};

+

+}

+}

+

+#endif // __nFRC_2015_1_0_A_Accel_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAccumulator.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAccumulator.h
new file mode 100644
index 0000000..991c5fb
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAccumulator.h
@@ -0,0 +1,87 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2015_1_0_A_Accumulator_h__

+#define __nFRC_2015_1_0_A_Accumulator_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2015_1_0_A

+{

+

+class tAccumulator

+{

+public:

+   tAccumulator(){}

+   virtual ~tAccumulator(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tAccumulator* create(unsigned char sys_index, tRioStatusCode *status);

+   virtual unsigned char getSystemIndex() = 0;

+

+

+   typedef enum

+   {

+      kNumSystems = 2,

+   } tIfaceConstants;

+

+   typedef

+   union{

+      struct{

+         signed long long Value;

+         unsigned Count : 32;

+      };

+      struct{

+         unsigned value : 32;

+         unsigned value2 : 32;

+         unsigned value3 : 32;

+      };

+   } tOutput;

+

+

+   typedef enum

+   {

+   } tOutput_IfaceConstants;

+

+   virtual tOutput readOutput(tRioStatusCode *status) = 0;

+   virtual signed long long readOutput_Value(tRioStatusCode *status) = 0;

+   virtual unsigned int readOutput_Count(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tCenter_IfaceConstants;

+

+   virtual void writeCenter(signed int value, tRioStatusCode *status) = 0;

+   virtual signed int readCenter(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tDeadband_IfaceConstants;

+

+   virtual void writeDeadband(signed int value, tRioStatusCode *status) = 0;

+   virtual signed int readDeadband(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tReset_IfaceConstants;

+

+   virtual void strobeReset(tRioStatusCode *status) = 0;

+

+

+

+

+

+private:

+   tAccumulator(const tAccumulator&);

+   void operator=(const tAccumulator&);

+};

+

+}

+}

+

+#endif // __nFRC_2015_1_0_A_Accumulator_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAlarm.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAlarm.h
new file mode 100644
index 0000000..8739405
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAlarm.h
@@ -0,0 +1,57 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2015_1_0_A_Alarm_h__

+#define __nFRC_2015_1_0_A_Alarm_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2015_1_0_A

+{

+

+class tAlarm

+{

+public:

+   tAlarm(){}

+   virtual ~tAlarm(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tAlarm* create(tRioStatusCode *status);

+

+   typedef enum

+   {

+      kNumSystems = 1,

+   } tIfaceConstants;

+

+

+

+

+   typedef enum

+   {

+   } tEnable_IfaceConstants;

+

+   virtual void writeEnable(bool value, tRioStatusCode *status) = 0;

+   virtual bool readEnable(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tTriggerTime_IfaceConstants;

+

+   virtual void writeTriggerTime(unsigned int value, tRioStatusCode *status) = 0;

+   virtual unsigned int readTriggerTime(tRioStatusCode *status) = 0;

+

+

+

+

+private:

+   tAlarm(const tAlarm&);

+   void operator=(const tAlarm&);

+};

+

+}

+}

+

+#endif // __nFRC_2015_1_0_A_Alarm_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAnalogTrigger.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAnalogTrigger.h
new file mode 100644
index 0000000..6b89bc2
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAnalogTrigger.h
@@ -0,0 +1,129 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2015_1_0_A_AnalogTrigger_h__

+#define __nFRC_2015_1_0_A_AnalogTrigger_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2015_1_0_A

+{

+

+class tAnalogTrigger

+{

+public:

+   tAnalogTrigger(){}

+   virtual ~tAnalogTrigger(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tAnalogTrigger* create(unsigned char sys_index, tRioStatusCode *status);

+   virtual unsigned char getSystemIndex() = 0;

+

+

+   typedef enum

+   {

+      kNumSystems = 8,

+   } tIfaceConstants;

+

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned InHysteresis : 1;

+         unsigned OverLimit : 1;

+         unsigned Rising : 1;

+         unsigned Falling : 1;

+#else

+         unsigned Falling : 1;

+         unsigned Rising : 1;

+         unsigned OverLimit : 1;

+         unsigned InHysteresis : 1;

+#endif

+      };

+      struct{

+         unsigned value : 4;

+      };

+   } tOutput;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned Channel : 3;

+         unsigned Averaged : 1;

+         unsigned Filter : 1;

+         unsigned FloatingRollover : 1;

+         signed RolloverLimit : 8;

+#else

+         signed RolloverLimit : 8;

+         unsigned FloatingRollover : 1;

+         unsigned Filter : 1;

+         unsigned Averaged : 1;

+         unsigned Channel : 3;

+#endif

+      };

+      struct{

+         unsigned value : 14;

+      };

+   } tSourceSelect;

+

+

+   typedef enum

+   {

+   } tSourceSelect_IfaceConstants;

+

+   virtual void writeSourceSelect(tSourceSelect value, tRioStatusCode *status) = 0;

+   virtual void writeSourceSelect_Channel(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeSourceSelect_Averaged(bool value, tRioStatusCode *status) = 0;

+   virtual void writeSourceSelect_Filter(bool value, tRioStatusCode *status) = 0;

+   virtual void writeSourceSelect_FloatingRollover(bool value, tRioStatusCode *status) = 0;

+   virtual void writeSourceSelect_RolloverLimit(signed short value, tRioStatusCode *status) = 0;

+   virtual tSourceSelect readSourceSelect(tRioStatusCode *status) = 0;

+   virtual unsigned char readSourceSelect_Channel(tRioStatusCode *status) = 0;

+   virtual bool readSourceSelect_Averaged(tRioStatusCode *status) = 0;

+   virtual bool readSourceSelect_Filter(tRioStatusCode *status) = 0;

+   virtual bool readSourceSelect_FloatingRollover(tRioStatusCode *status) = 0;

+   virtual signed short readSourceSelect_RolloverLimit(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tUpperLimit_IfaceConstants;

+

+   virtual void writeUpperLimit(signed int value, tRioStatusCode *status) = 0;

+   virtual signed int readUpperLimit(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tLowerLimit_IfaceConstants;

+

+   virtual void writeLowerLimit(signed int value, tRioStatusCode *status) = 0;

+   virtual signed int readLowerLimit(tRioStatusCode *status) = 0;

+

+

+

+   typedef enum

+   {

+      kNumOutputElements = 8,

+   } tOutput_IfaceConstants;

+

+   virtual tOutput readOutput(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+   virtual bool readOutput_InHysteresis(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+   virtual bool readOutput_OverLimit(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+   virtual bool readOutput_Rising(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+   virtual bool readOutput_Falling(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+

+

+

+

+private:

+   tAnalogTrigger(const tAnalogTrigger&);

+   void operator=(const tAnalogTrigger&);

+};

+

+}

+}

+

+#endif // __nFRC_2015_1_0_A_AnalogTrigger_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tBIST.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tBIST.h
new file mode 100644
index 0000000..41b8626
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tBIST.h
@@ -0,0 +1,90 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2015_1_0_A_BIST_h__

+#define __nFRC_2015_1_0_A_BIST_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2015_1_0_A

+{

+

+class tBIST

+{

+public:

+   tBIST(){}

+   virtual ~tBIST(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tBIST* create(tRioStatusCode *status);

+

+   typedef enum

+   {

+      kNumSystems = 1,

+   } tIfaceConstants;

+

+

+

+

+   typedef enum

+   {

+   } tDO0SquareTicks_IfaceConstants;

+

+   virtual void writeDO0SquareTicks(unsigned int value, tRioStatusCode *status) = 0;

+   virtual unsigned int readDO0SquareTicks(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tEnable_IfaceConstants;

+

+   virtual void writeEnable(bool value, tRioStatusCode *status) = 0;

+   virtual bool readEnable(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tDO1SquareEnable_IfaceConstants;

+

+   virtual void writeDO1SquareEnable(bool value, tRioStatusCode *status) = 0;

+   virtual bool readDO1SquareEnable(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tDO0SquareEnable_IfaceConstants;

+

+   virtual void writeDO0SquareEnable(bool value, tRioStatusCode *status) = 0;

+   virtual bool readDO0SquareEnable(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tDO1SquareTicks_IfaceConstants;

+

+   virtual void writeDO1SquareTicks(unsigned int value, tRioStatusCode *status) = 0;

+   virtual unsigned int readDO1SquareTicks(tRioStatusCode *status) = 0;

+

+

+

+

+   typedef enum

+   {

+      kNumDORegisters = 2,

+   } tDO_IfaceConstants;

+

+   virtual void writeDO(unsigned char reg_index, bool value, tRioStatusCode *status) = 0;

+   virtual bool readDO(unsigned char reg_index, tRioStatusCode *status) = 0;

+

+

+private:

+   tBIST(const tBIST&);

+   void operator=(const tBIST&);

+};

+

+}

+}

+

+#endif // __nFRC_2015_1_0_A_BIST_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tCounter.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tCounter.h
new file mode 100644
index 0000000..6eff544
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tCounter.h
@@ -0,0 +1,219 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2015_1_0_A_Counter_h__

+#define __nFRC_2015_1_0_A_Counter_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2015_1_0_A

+{

+

+class tCounter

+{

+public:

+   tCounter(){}

+   virtual ~tCounter(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tCounter* create(unsigned char sys_index, tRioStatusCode *status);

+   virtual unsigned char getSystemIndex() = 0;

+

+

+   typedef enum

+   {

+      kNumSystems = 8,

+   } tIfaceConstants;

+

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned Direction : 1;

+         signed Value : 31;

+#else

+         signed Value : 31;

+         unsigned Direction : 1;

+#endif

+      };

+      struct{

+         unsigned value : 32;

+      };

+   } tOutput;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned UpSource_Channel : 4;

+         unsigned UpSource_Module : 1;

+         unsigned UpSource_AnalogTrigger : 1;

+         unsigned DownSource_Channel : 4;

+         unsigned DownSource_Module : 1;

+         unsigned DownSource_AnalogTrigger : 1;

+         unsigned IndexSource_Channel : 4;

+         unsigned IndexSource_Module : 1;

+         unsigned IndexSource_AnalogTrigger : 1;

+         unsigned IndexActiveHigh : 1;

+         unsigned IndexEdgeSensitive : 1;

+         unsigned UpRisingEdge : 1;

+         unsigned UpFallingEdge : 1;

+         unsigned DownRisingEdge : 1;

+         unsigned DownFallingEdge : 1;

+         unsigned Mode : 2;

+         unsigned PulseLengthThreshold : 6;

+#else

+         unsigned PulseLengthThreshold : 6;

+         unsigned Mode : 2;

+         unsigned DownFallingEdge : 1;

+         unsigned DownRisingEdge : 1;

+         unsigned UpFallingEdge : 1;

+         unsigned UpRisingEdge : 1;

+         unsigned IndexEdgeSensitive : 1;

+         unsigned IndexActiveHigh : 1;

+         unsigned IndexSource_AnalogTrigger : 1;

+         unsigned IndexSource_Module : 1;

+         unsigned IndexSource_Channel : 4;

+         unsigned DownSource_AnalogTrigger : 1;

+         unsigned DownSource_Module : 1;

+         unsigned DownSource_Channel : 4;

+         unsigned UpSource_AnalogTrigger : 1;

+         unsigned UpSource_Module : 1;

+         unsigned UpSource_Channel : 4;

+#endif

+      };

+      struct{

+         unsigned value : 32;

+      };

+   } tConfig;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned Period : 23;

+         signed Count : 8;

+         unsigned Stalled : 1;

+#else

+         unsigned Stalled : 1;

+         signed Count : 8;

+         unsigned Period : 23;

+#endif

+      };

+      struct{

+         unsigned value : 32;

+      };

+   } tTimerOutput;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned StallPeriod : 24;

+         unsigned AverageSize : 7;

+         unsigned UpdateWhenEmpty : 1;

+#else

+         unsigned UpdateWhenEmpty : 1;

+         unsigned AverageSize : 7;

+         unsigned StallPeriod : 24;

+#endif

+      };

+      struct{

+         unsigned value : 32;

+      };

+   } tTimerConfig;

+

+

+   typedef enum

+   {

+   } tOutput_IfaceConstants;

+

+   virtual tOutput readOutput(tRioStatusCode *status) = 0;

+   virtual bool readOutput_Direction(tRioStatusCode *status) = 0;

+   virtual signed int readOutput_Value(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tConfig_IfaceConstants;

+

+   virtual void writeConfig(tConfig value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_UpSource_Channel(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_UpSource_Module(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_UpSource_AnalogTrigger(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_DownSource_Channel(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_DownSource_Module(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_DownSource_AnalogTrigger(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_IndexSource_Channel(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_IndexSource_Module(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_IndexSource_AnalogTrigger(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_IndexActiveHigh(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_IndexEdgeSensitive(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_UpRisingEdge(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_UpFallingEdge(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_DownRisingEdge(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_DownFallingEdge(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Mode(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_PulseLengthThreshold(unsigned short value, tRioStatusCode *status) = 0;

+   virtual tConfig readConfig(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_UpSource_Channel(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_UpSource_Module(tRioStatusCode *status) = 0;

+   virtual bool readConfig_UpSource_AnalogTrigger(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_DownSource_Channel(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_DownSource_Module(tRioStatusCode *status) = 0;

+   virtual bool readConfig_DownSource_AnalogTrigger(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_IndexSource_Channel(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_IndexSource_Module(tRioStatusCode *status) = 0;

+   virtual bool readConfig_IndexSource_AnalogTrigger(tRioStatusCode *status) = 0;

+   virtual bool readConfig_IndexActiveHigh(tRioStatusCode *status) = 0;

+   virtual bool readConfig_IndexEdgeSensitive(tRioStatusCode *status) = 0;

+   virtual bool readConfig_UpRisingEdge(tRioStatusCode *status) = 0;

+   virtual bool readConfig_UpFallingEdge(tRioStatusCode *status) = 0;

+   virtual bool readConfig_DownRisingEdge(tRioStatusCode *status) = 0;

+   virtual bool readConfig_DownFallingEdge(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_Mode(tRioStatusCode *status) = 0;

+   virtual unsigned short readConfig_PulseLengthThreshold(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tTimerOutput_IfaceConstants;

+

+   virtual tTimerOutput readTimerOutput(tRioStatusCode *status) = 0;

+   virtual unsigned int readTimerOutput_Period(tRioStatusCode *status) = 0;

+   virtual signed char readTimerOutput_Count(tRioStatusCode *status) = 0;

+   virtual bool readTimerOutput_Stalled(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tReset_IfaceConstants;

+

+   virtual void strobeReset(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tTimerConfig_IfaceConstants;

+

+   virtual void writeTimerConfig(tTimerConfig value, tRioStatusCode *status) = 0;

+   virtual void writeTimerConfig_StallPeriod(unsigned int value, tRioStatusCode *status) = 0;

+   virtual void writeTimerConfig_AverageSize(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeTimerConfig_UpdateWhenEmpty(bool value, tRioStatusCode *status) = 0;

+   virtual tTimerConfig readTimerConfig(tRioStatusCode *status) = 0;

+   virtual unsigned int readTimerConfig_StallPeriod(tRioStatusCode *status) = 0;

+   virtual unsigned char readTimerConfig_AverageSize(tRioStatusCode *status) = 0;

+   virtual bool readTimerConfig_UpdateWhenEmpty(tRioStatusCode *status) = 0;

+

+

+

+

+

+private:

+   tCounter(const tCounter&);

+   void operator=(const tCounter&);

+};

+

+}

+}

+

+#endif // __nFRC_2015_1_0_A_Counter_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tDIO.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tDIO.h
new file mode 100644
index 0000000..0d9659b
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tDIO.h
@@ -0,0 +1,248 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2015_1_0_A_DIO_h__

+#define __nFRC_2015_1_0_A_DIO_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2015_1_0_A

+{

+

+class tDIO

+{

+public:

+   tDIO(){}

+   virtual ~tDIO(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tDIO* create(tRioStatusCode *status);

+

+   typedef enum

+   {

+      kNumSystems = 1,

+   } tIfaceConstants;

+

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned Headers : 10;

+         unsigned Reserved : 6;

+         unsigned MXP : 16;

+#else

+         unsigned MXP : 16;

+         unsigned Reserved : 6;

+         unsigned Headers : 10;

+#endif

+      };

+      struct{

+         unsigned value : 32;

+      };

+   } tDO;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned Headers : 10;

+         unsigned Reserved : 6;

+         unsigned MXP : 16;

+#else

+         unsigned MXP : 16;

+         unsigned Reserved : 6;

+         unsigned Headers : 10;

+#endif

+      };

+      struct{

+         unsigned value : 32;

+      };

+   } tOutputEnable;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned Headers : 10;

+         unsigned Reserved : 6;

+         unsigned MXP : 16;

+#else

+         unsigned MXP : 16;

+         unsigned Reserved : 6;

+         unsigned Headers : 10;

+#endif

+      };

+      struct{

+         unsigned value : 32;

+      };

+   } tPulse;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned Headers : 10;

+         unsigned Reserved : 6;

+         unsigned MXP : 16;

+#else

+         unsigned MXP : 16;

+         unsigned Reserved : 6;

+         unsigned Headers : 10;

+#endif

+      };

+      struct{

+         unsigned value : 32;

+      };

+   } tDI;

+

+

+

+   typedef enum

+   {

+   } tDO_IfaceConstants;

+

+   virtual void writeDO(tDO value, tRioStatusCode *status) = 0;

+   virtual void writeDO_Headers(unsigned short value, tRioStatusCode *status) = 0;

+   virtual void writeDO_Reserved(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeDO_MXP(unsigned short value, tRioStatusCode *status) = 0;

+   virtual tDO readDO(tRioStatusCode *status) = 0;

+   virtual unsigned short readDO_Headers(tRioStatusCode *status) = 0;

+   virtual unsigned char readDO_Reserved(tRioStatusCode *status) = 0;

+   virtual unsigned short readDO_MXP(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+      kNumPWMDutyCycleAElements = 4,

+   } tPWMDutyCycleA_IfaceConstants;

+

+   virtual void writePWMDutyCycleA(unsigned char bitfield_index, unsigned char value, tRioStatusCode *status) = 0;

+   virtual unsigned char readPWMDutyCycleA(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+      kNumPWMDutyCycleBElements = 2,

+   } tPWMDutyCycleB_IfaceConstants;

+

+   virtual void writePWMDutyCycleB(unsigned char bitfield_index, unsigned char value, tRioStatusCode *status) = 0;

+   virtual unsigned char readPWMDutyCycleB(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+      kNumFilterSelectHdrElements = 16,

+   } tFilterSelectHdr_IfaceConstants;

+

+   virtual void writeFilterSelectHdr(unsigned char bitfield_index, unsigned char value, tRioStatusCode *status) = 0;

+   virtual unsigned char readFilterSelectHdr(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tOutputEnable_IfaceConstants;

+

+   virtual void writeOutputEnable(tOutputEnable value, tRioStatusCode *status) = 0;

+   virtual void writeOutputEnable_Headers(unsigned short value, tRioStatusCode *status) = 0;

+   virtual void writeOutputEnable_Reserved(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeOutputEnable_MXP(unsigned short value, tRioStatusCode *status) = 0;

+   virtual tOutputEnable readOutputEnable(tRioStatusCode *status) = 0;

+   virtual unsigned short readOutputEnable_Headers(tRioStatusCode *status) = 0;

+   virtual unsigned char readOutputEnable_Reserved(tRioStatusCode *status) = 0;

+   virtual unsigned short readOutputEnable_MXP(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+      kNumPWMOutputSelectElements = 6,

+   } tPWMOutputSelect_IfaceConstants;

+

+   virtual void writePWMOutputSelect(unsigned char bitfield_index, unsigned char value, tRioStatusCode *status) = 0;

+   virtual unsigned char readPWMOutputSelect(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tPulse_IfaceConstants;

+

+   virtual void writePulse(tPulse value, tRioStatusCode *status) = 0;

+   virtual void writePulse_Headers(unsigned short value, tRioStatusCode *status) = 0;

+   virtual void writePulse_Reserved(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writePulse_MXP(unsigned short value, tRioStatusCode *status) = 0;

+   virtual tPulse readPulse(tRioStatusCode *status) = 0;

+   virtual unsigned short readPulse_Headers(tRioStatusCode *status) = 0;

+   virtual unsigned char readPulse_Reserved(tRioStatusCode *status) = 0;

+   virtual unsigned short readPulse_MXP(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tDI_IfaceConstants;

+

+   virtual tDI readDI(tRioStatusCode *status) = 0;

+   virtual unsigned short readDI_Headers(tRioStatusCode *status) = 0;

+   virtual unsigned char readDI_Reserved(tRioStatusCode *status) = 0;

+   virtual unsigned short readDI_MXP(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tEnableMXPSpecialFunction_IfaceConstants;

+

+   virtual void writeEnableMXPSpecialFunction(unsigned short value, tRioStatusCode *status) = 0;

+   virtual unsigned short readEnableMXPSpecialFunction(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+      kNumFilterSelectMXPElements = 16,

+   } tFilterSelectMXP_IfaceConstants;

+

+   virtual void writeFilterSelectMXP(unsigned char bitfield_index, unsigned char value, tRioStatusCode *status) = 0;

+   virtual unsigned char readFilterSelectMXP(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tPulseLength_IfaceConstants;

+

+   virtual void writePulseLength(unsigned char value, tRioStatusCode *status) = 0;

+   virtual unsigned char readPulseLength(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tPWMPeriodPower_IfaceConstants;

+

+   virtual void writePWMPeriodPower(unsigned short value, tRioStatusCode *status) = 0;

+   virtual unsigned short readPWMPeriodPower(tRioStatusCode *status) = 0;

+

+

+

+

+   typedef enum

+   {

+      kNumFilterPeriodMXPRegisters = 3,

+   } tFilterPeriodMXP_IfaceConstants;

+

+   virtual void writeFilterPeriodMXP(unsigned char reg_index, unsigned int value, tRioStatusCode *status) = 0;

+   virtual unsigned int readFilterPeriodMXP(unsigned char reg_index, tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+      kNumFilterPeriodHdrRegisters = 3,

+   } tFilterPeriodHdr_IfaceConstants;

+

+   virtual void writeFilterPeriodHdr(unsigned char reg_index, unsigned int value, tRioStatusCode *status) = 0;

+   virtual unsigned int readFilterPeriodHdr(unsigned char reg_index, tRioStatusCode *status) = 0;

+

+

+private:

+   tDIO(const tDIO&);

+   void operator=(const tDIO&);

+};

+

+}

+}

+

+#endif // __nFRC_2015_1_0_A_DIO_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tDMA.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tDMA.h
new file mode 100644
index 0000000..4b57edf
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tDMA.h
@@ -0,0 +1,188 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2015_1_0_A_DMA_h__

+#define __nFRC_2015_1_0_A_DMA_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2015_1_0_A

+{

+

+class tDMA

+{

+public:

+   tDMA(){}

+   virtual ~tDMA(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tDMA* create(tRioStatusCode *status);

+

+   typedef enum

+   {

+      kNumSystems = 1,

+   } tIfaceConstants;

+

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned Pause : 1;

+         unsigned Enable_AI0_Low : 1;

+         unsigned Enable_AI0_High : 1;

+         unsigned Enable_AIAveraged0_Low : 1;

+         unsigned Enable_AIAveraged0_High : 1;

+         unsigned Enable_AI1_Low : 1;

+         unsigned Enable_AI1_High : 1;

+         unsigned Enable_AIAveraged1_Low : 1;

+         unsigned Enable_AIAveraged1_High : 1;

+         unsigned Enable_Accumulator0 : 1;

+         unsigned Enable_Accumulator1 : 1;

+         unsigned Enable_DI : 1;

+         unsigned Enable_AnalogTriggers : 1;

+         unsigned Enable_Counters_Low : 1;

+         unsigned Enable_Counters_High : 1;

+         unsigned Enable_CounterTimers_Low : 1;

+         unsigned Enable_CounterTimers_High : 1;

+         unsigned Enable_Encoders : 1;

+         unsigned Enable_EncoderTimers : 1;

+         unsigned ExternalClock : 1;

+#else

+         unsigned ExternalClock : 1;

+         unsigned Enable_EncoderTimers : 1;

+         unsigned Enable_Encoders : 1;

+         unsigned Enable_CounterTimers_High : 1;

+         unsigned Enable_CounterTimers_Low : 1;

+         unsigned Enable_Counters_High : 1;

+         unsigned Enable_Counters_Low : 1;

+         unsigned Enable_AnalogTriggers : 1;

+         unsigned Enable_DI : 1;

+         unsigned Enable_Accumulator1 : 1;

+         unsigned Enable_Accumulator0 : 1;

+         unsigned Enable_AIAveraged1_High : 1;

+         unsigned Enable_AIAveraged1_Low : 1;

+         unsigned Enable_AI1_High : 1;

+         unsigned Enable_AI1_Low : 1;

+         unsigned Enable_AIAveraged0_High : 1;

+         unsigned Enable_AIAveraged0_Low : 1;

+         unsigned Enable_AI0_High : 1;

+         unsigned Enable_AI0_Low : 1;

+         unsigned Pause : 1;

+#endif

+      };

+      struct{

+         unsigned value : 20;

+      };

+   } tConfig;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned ExternalClockSource_Channel : 4;

+         unsigned ExternalClockSource_Module : 1;

+         unsigned ExternalClockSource_AnalogTrigger : 1;

+         unsigned RisingEdge : 1;

+         unsigned FallingEdge : 1;

+#else

+         unsigned FallingEdge : 1;

+         unsigned RisingEdge : 1;

+         unsigned ExternalClockSource_AnalogTrigger : 1;

+         unsigned ExternalClockSource_Module : 1;

+         unsigned ExternalClockSource_Channel : 4;

+#endif

+      };

+      struct{

+         unsigned value : 8;

+      };

+   } tExternalTriggers;

+

+

+

+   typedef enum

+   {

+   } tRate_IfaceConstants;

+

+   virtual void writeRate(unsigned int value, tRioStatusCode *status) = 0;

+   virtual unsigned int readRate(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tConfig_IfaceConstants;

+

+   virtual void writeConfig(tConfig value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Pause(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_AI0_Low(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_AI0_High(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_AIAveraged0_Low(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_AIAveraged0_High(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_AI1_Low(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_AI1_High(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_AIAveraged1_Low(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_AIAveraged1_High(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_Accumulator0(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_Accumulator1(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_DI(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_AnalogTriggers(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_Counters_Low(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_Counters_High(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_CounterTimers_Low(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_CounterTimers_High(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_Encoders(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_EncoderTimers(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_ExternalClock(bool value, tRioStatusCode *status) = 0;

+   virtual tConfig readConfig(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Pause(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_AI0_Low(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_AI0_High(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_AIAveraged0_Low(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_AIAveraged0_High(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_AI1_Low(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_AI1_High(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_AIAveraged1_Low(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_AIAveraged1_High(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_Accumulator0(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_Accumulator1(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_DI(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_AnalogTriggers(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_Counters_Low(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_Counters_High(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_CounterTimers_Low(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_CounterTimers_High(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_Encoders(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_EncoderTimers(tRioStatusCode *status) = 0;

+   virtual bool readConfig_ExternalClock(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+      kNumExternalTriggersElements = 4,

+   } tExternalTriggers_IfaceConstants;

+

+   virtual void writeExternalTriggers(unsigned char bitfield_index, tExternalTriggers value, tRioStatusCode *status) = 0;

+   virtual void writeExternalTriggers_ExternalClockSource_Channel(unsigned char bitfield_index, unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeExternalTriggers_ExternalClockSource_Module(unsigned char bitfield_index, unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeExternalTriggers_ExternalClockSource_AnalogTrigger(unsigned char bitfield_index, bool value, tRioStatusCode *status) = 0;

+   virtual void writeExternalTriggers_RisingEdge(unsigned char bitfield_index, bool value, tRioStatusCode *status) = 0;

+   virtual void writeExternalTriggers_FallingEdge(unsigned char bitfield_index, bool value, tRioStatusCode *status) = 0;

+   virtual tExternalTriggers readExternalTriggers(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+   virtual unsigned char readExternalTriggers_ExternalClockSource_Channel(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+   virtual unsigned char readExternalTriggers_ExternalClockSource_Module(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+   virtual bool readExternalTriggers_ExternalClockSource_AnalogTrigger(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+   virtual bool readExternalTriggers_RisingEdge(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+   virtual bool readExternalTriggers_FallingEdge(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+

+

+

+

+private:

+   tDMA(const tDMA&);

+   void operator=(const tDMA&);

+};

+

+}

+}

+

+#endif // __nFRC_2015_1_0_A_DMA_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tEncoder.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tEncoder.h
new file mode 100644
index 0000000..466b9c1
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tEncoder.h
@@ -0,0 +1,199 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2015_1_0_A_Encoder_h__

+#define __nFRC_2015_1_0_A_Encoder_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2015_1_0_A

+{

+

+class tEncoder

+{

+public:

+   tEncoder(){}

+   virtual ~tEncoder(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tEncoder* create(unsigned char sys_index, tRioStatusCode *status);

+   virtual unsigned char getSystemIndex() = 0;

+

+

+   typedef enum

+   {

+      kNumSystems = 8,

+   } tIfaceConstants;

+

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned Direction : 1;

+         signed Value : 31;

+#else

+         signed Value : 31;

+         unsigned Direction : 1;

+#endif

+      };

+      struct{

+         unsigned value : 32;

+      };

+   } tOutput;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned ASource_Channel : 4;

+         unsigned ASource_Module : 1;

+         unsigned ASource_AnalogTrigger : 1;

+         unsigned BSource_Channel : 4;

+         unsigned BSource_Module : 1;

+         unsigned BSource_AnalogTrigger : 1;

+         unsigned IndexSource_Channel : 4;

+         unsigned IndexSource_Module : 1;

+         unsigned IndexSource_AnalogTrigger : 1;

+         unsigned IndexActiveHigh : 1;

+         unsigned IndexEdgeSensitive : 1;

+         unsigned Reverse : 1;

+#else

+         unsigned Reverse : 1;

+         unsigned IndexEdgeSensitive : 1;

+         unsigned IndexActiveHigh : 1;

+         unsigned IndexSource_AnalogTrigger : 1;

+         unsigned IndexSource_Module : 1;

+         unsigned IndexSource_Channel : 4;

+         unsigned BSource_AnalogTrigger : 1;

+         unsigned BSource_Module : 1;

+         unsigned BSource_Channel : 4;

+         unsigned ASource_AnalogTrigger : 1;

+         unsigned ASource_Module : 1;

+         unsigned ASource_Channel : 4;

+#endif

+      };

+      struct{

+         unsigned value : 21;

+      };

+   } tConfig;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned Period : 23;

+         signed Count : 8;

+         unsigned Stalled : 1;

+#else

+         unsigned Stalled : 1;

+         signed Count : 8;

+         unsigned Period : 23;

+#endif

+      };

+      struct{

+         unsigned value : 32;

+      };

+   } tTimerOutput;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned StallPeriod : 24;

+         unsigned AverageSize : 7;

+         unsigned UpdateWhenEmpty : 1;

+#else

+         unsigned UpdateWhenEmpty : 1;

+         unsigned AverageSize : 7;

+         unsigned StallPeriod : 24;

+#endif

+      };

+      struct{

+         unsigned value : 32;

+      };

+   } tTimerConfig;

+

+

+   typedef enum

+   {

+   } tOutput_IfaceConstants;

+

+   virtual tOutput readOutput(tRioStatusCode *status) = 0;

+   virtual bool readOutput_Direction(tRioStatusCode *status) = 0;

+   virtual signed int readOutput_Value(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tConfig_IfaceConstants;

+

+   virtual void writeConfig(tConfig value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_ASource_Channel(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_ASource_Module(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_ASource_AnalogTrigger(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_BSource_Channel(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_BSource_Module(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_BSource_AnalogTrigger(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_IndexSource_Channel(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_IndexSource_Module(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_IndexSource_AnalogTrigger(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_IndexActiveHigh(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_IndexEdgeSensitive(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Reverse(bool value, tRioStatusCode *status) = 0;

+   virtual tConfig readConfig(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_ASource_Channel(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_ASource_Module(tRioStatusCode *status) = 0;

+   virtual bool readConfig_ASource_AnalogTrigger(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_BSource_Channel(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_BSource_Module(tRioStatusCode *status) = 0;

+   virtual bool readConfig_BSource_AnalogTrigger(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_IndexSource_Channel(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_IndexSource_Module(tRioStatusCode *status) = 0;

+   virtual bool readConfig_IndexSource_AnalogTrigger(tRioStatusCode *status) = 0;

+   virtual bool readConfig_IndexActiveHigh(tRioStatusCode *status) = 0;

+   virtual bool readConfig_IndexEdgeSensitive(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Reverse(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tTimerOutput_IfaceConstants;

+

+   virtual tTimerOutput readTimerOutput(tRioStatusCode *status) = 0;

+   virtual unsigned int readTimerOutput_Period(tRioStatusCode *status) = 0;

+   virtual signed char readTimerOutput_Count(tRioStatusCode *status) = 0;

+   virtual bool readTimerOutput_Stalled(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tReset_IfaceConstants;

+

+   virtual void strobeReset(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tTimerConfig_IfaceConstants;

+

+   virtual void writeTimerConfig(tTimerConfig value, tRioStatusCode *status) = 0;

+   virtual void writeTimerConfig_StallPeriod(unsigned int value, tRioStatusCode *status) = 0;

+   virtual void writeTimerConfig_AverageSize(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeTimerConfig_UpdateWhenEmpty(bool value, tRioStatusCode *status) = 0;

+   virtual tTimerConfig readTimerConfig(tRioStatusCode *status) = 0;

+   virtual unsigned int readTimerConfig_StallPeriod(tRioStatusCode *status) = 0;

+   virtual unsigned char readTimerConfig_AverageSize(tRioStatusCode *status) = 0;

+   virtual bool readTimerConfig_UpdateWhenEmpty(tRioStatusCode *status) = 0;

+

+

+

+

+

+private:

+   tEncoder(const tEncoder&);

+   void operator=(const tEncoder&);

+};

+

+}

+}

+

+#endif // __nFRC_2015_1_0_A_Encoder_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tGlobal.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tGlobal.h
new file mode 100644
index 0000000..e2014de
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tGlobal.h
@@ -0,0 +1,104 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2015_1_0_A_Global_h__

+#define __nFRC_2015_1_0_A_Global_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2015_1_0_A

+{

+

+class tGlobal

+{

+public:

+   tGlobal(){}

+   virtual ~tGlobal(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tGlobal* create(tRioStatusCode *status);

+

+   typedef enum

+   {

+      kNumSystems = 1,

+   } tIfaceConstants;

+

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned Radio : 8;

+         unsigned Comm : 8;

+         unsigned Mode : 8;

+         unsigned RSL : 1;

+#else

+         unsigned RSL : 1;

+         unsigned Mode : 8;

+         unsigned Comm : 8;

+         unsigned Radio : 8;

+#endif

+      };

+      struct{

+         unsigned value : 25;

+      };

+   } tLEDs;

+

+

+

+   typedef enum

+   {

+   } tLEDs_IfaceConstants;

+

+   virtual void writeLEDs(tLEDs value, tRioStatusCode *status) = 0;

+   virtual void writeLEDs_Radio(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeLEDs_Comm(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeLEDs_Mode(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeLEDs_RSL(bool value, tRioStatusCode *status) = 0;

+   virtual tLEDs readLEDs(tRioStatusCode *status) = 0;

+   virtual unsigned char readLEDs_Radio(tRioStatusCode *status) = 0;

+   virtual unsigned char readLEDs_Comm(tRioStatusCode *status) = 0;

+   virtual unsigned char readLEDs_Mode(tRioStatusCode *status) = 0;

+   virtual bool readLEDs_RSL(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tVersion_IfaceConstants;

+

+   virtual unsigned short readVersion(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tLocalTime_IfaceConstants;

+

+   virtual unsigned int readLocalTime(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tUserButton_IfaceConstants;

+

+   virtual bool readUserButton(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tRevision_IfaceConstants;

+

+   virtual unsigned int readRevision(tRioStatusCode *status) = 0;

+

+

+

+

+private:

+   tGlobal(const tGlobal&);

+   void operator=(const tGlobal&);

+};

+

+}

+}

+

+#endif // __nFRC_2015_1_0_A_Global_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tInterrupt.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tInterrupt.h
new file mode 100644
index 0000000..16233e1
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tInterrupt.h
@@ -0,0 +1,100 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2015_1_0_A_Interrupt_h__

+#define __nFRC_2015_1_0_A_Interrupt_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2015_1_0_A

+{

+

+class tInterrupt

+{

+public:

+   tInterrupt(){}

+   virtual ~tInterrupt(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tInterrupt* create(unsigned char sys_index, tRioStatusCode *status);

+   virtual unsigned char getSystemIndex() = 0;

+

+

+   typedef enum

+   {

+      kNumSystems = 8,

+   } tIfaceConstants;

+

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned Source_Channel : 4;

+         unsigned Source_Module : 1;

+         unsigned Source_AnalogTrigger : 1;

+         unsigned RisingEdge : 1;

+         unsigned FallingEdge : 1;

+         unsigned WaitForAck : 1;

+#else

+         unsigned WaitForAck : 1;

+         unsigned FallingEdge : 1;

+         unsigned RisingEdge : 1;

+         unsigned Source_AnalogTrigger : 1;

+         unsigned Source_Module : 1;

+         unsigned Source_Channel : 4;

+#endif

+      };

+      struct{

+         unsigned value : 9;

+      };

+   } tConfig;

+

+

+   typedef enum

+   {

+   } tFallingTimeStamp_IfaceConstants;

+

+   virtual unsigned int readFallingTimeStamp(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tConfig_IfaceConstants;

+

+   virtual void writeConfig(tConfig value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Source_Channel(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Source_Module(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Source_AnalogTrigger(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_RisingEdge(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_FallingEdge(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_WaitForAck(bool value, tRioStatusCode *status) = 0;

+   virtual tConfig readConfig(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_Source_Channel(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_Source_Module(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Source_AnalogTrigger(tRioStatusCode *status) = 0;

+   virtual bool readConfig_RisingEdge(tRioStatusCode *status) = 0;

+   virtual bool readConfig_FallingEdge(tRioStatusCode *status) = 0;

+   virtual bool readConfig_WaitForAck(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tRisingTimeStamp_IfaceConstants;

+

+   virtual unsigned int readRisingTimeStamp(tRioStatusCode *status) = 0;

+

+

+

+

+

+private:

+   tInterrupt(const tInterrupt&);

+   void operator=(const tInterrupt&);

+};

+

+}

+}

+

+#endif // __nFRC_2015_1_0_A_Interrupt_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tPWM.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tPWM.h
new file mode 100644
index 0000000..5dcf5e2
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tPWM.h
@@ -0,0 +1,120 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2015_1_0_A_PWM_h__

+#define __nFRC_2015_1_0_A_PWM_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2015_1_0_A

+{

+

+class tPWM

+{

+public:

+   tPWM(){}

+   virtual ~tPWM(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tPWM* create(tRioStatusCode *status);

+

+   typedef enum

+   {

+      kNumSystems = 1,

+   } tIfaceConstants;

+

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned Period : 16;

+         unsigned MinHigh : 16;

+#else

+         unsigned MinHigh : 16;

+         unsigned Period : 16;

+#endif

+      };

+      struct{

+         unsigned value : 32;

+      };

+   } tConfig;

+

+

+

+   typedef enum

+   {

+   } tConfig_IfaceConstants;

+

+   virtual void writeConfig(tConfig value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Period(unsigned short value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_MinHigh(unsigned short value, tRioStatusCode *status) = 0;

+   virtual tConfig readConfig(tRioStatusCode *status) = 0;

+   virtual unsigned short readConfig_Period(tRioStatusCode *status) = 0;

+   virtual unsigned short readConfig_MinHigh(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tLoopTiming_IfaceConstants;

+

+   virtual unsigned short readLoopTiming(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+      kNumPeriodScaleMXPElements = 10,

+   } tPeriodScaleMXP_IfaceConstants;

+

+   virtual void writePeriodScaleMXP(unsigned char bitfield_index, unsigned char value, tRioStatusCode *status) = 0;

+   virtual unsigned char readPeriodScaleMXP(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+      kNumPeriodScaleHdrElements = 10,

+   } tPeriodScaleHdr_IfaceConstants;

+

+   virtual void writePeriodScaleHdr(unsigned char bitfield_index, unsigned char value, tRioStatusCode *status) = 0;

+   virtual unsigned char readPeriodScaleHdr(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+      kNumZeroLatchElements = 20,

+   } tZeroLatch_IfaceConstants;

+

+   virtual void writeZeroLatch(unsigned char bitfield_index, bool value, tRioStatusCode *status) = 0;

+   virtual bool readZeroLatch(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+

+

+

+

+   typedef enum

+   {

+      kNumHdrRegisters = 10,

+   } tHdr_IfaceConstants;

+

+   virtual void writeHdr(unsigned char reg_index, unsigned short value, tRioStatusCode *status) = 0;

+   virtual unsigned short readHdr(unsigned char reg_index, tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+      kNumMXPRegisters = 10,

+   } tMXP_IfaceConstants;

+

+   virtual void writeMXP(unsigned char reg_index, unsigned short value, tRioStatusCode *status) = 0;

+   virtual unsigned short readMXP(unsigned char reg_index, tRioStatusCode *status) = 0;

+

+

+private:

+   tPWM(const tPWM&);

+   void operator=(const tPWM&);

+};

+

+}

+}

+

+#endif // __nFRC_2015_1_0_A_PWM_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tPower.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tPower.h
new file mode 100644
index 0000000..6084c66
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tPower.h
@@ -0,0 +1,217 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2015_1_0_A_Power_h__

+#define __nFRC_2015_1_0_A_Power_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2015_1_0_A

+{

+

+class tPower

+{

+public:

+   tPower(){}

+   virtual ~tPower(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tPower* create(tRioStatusCode *status);

+

+   typedef enum

+   {

+      kNumSystems = 1,

+   } tIfaceConstants;

+

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned User3V3 : 8;

+         unsigned User5V : 8;

+         unsigned User6V : 8;

+#else

+         unsigned User6V : 8;

+         unsigned User5V : 8;

+         unsigned User3V3 : 8;

+#endif

+      };

+      struct{

+         unsigned value : 24;

+      };

+   } tStatus;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned OverCurrentFaultCount3V3 : 10;

+         unsigned OverCurrentFaultCount5V : 10;

+         unsigned OverCurrentFaultCount6V : 10;

+#else

+         unsigned OverCurrentFaultCount6V : 10;

+         unsigned OverCurrentFaultCount5V : 10;

+         unsigned OverCurrentFaultCount3V3 : 10;

+#endif

+      };

+      struct{

+         unsigned value : 30;

+      };

+   } tOverCurrentFaultCounts;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned User3V3 : 1;

+         unsigned User5V : 1;

+         unsigned User6V : 1;

+#else

+         unsigned User6V : 1;

+         unsigned User5V : 1;

+         unsigned User3V3 : 1;

+#endif

+      };

+      struct{

+         unsigned value : 3;

+      };

+   } tDisable;

+

+

+

+   typedef enum

+   {

+   } tUserVoltage3V3_IfaceConstants;

+

+   virtual unsigned short readUserVoltage3V3(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tStatus_IfaceConstants;

+

+   virtual tStatus readStatus(tRioStatusCode *status) = 0;

+   virtual unsigned char readStatus_User3V3(tRioStatusCode *status) = 0;

+   virtual unsigned char readStatus_User5V(tRioStatusCode *status) = 0;

+   virtual unsigned char readStatus_User6V(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tUserVoltage6V_IfaceConstants;

+

+   virtual unsigned short readUserVoltage6V(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tOnChipTemperature_IfaceConstants;

+

+   virtual unsigned short readOnChipTemperature(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tUserVoltage5V_IfaceConstants;

+

+   virtual unsigned short readUserVoltage5V(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tResetFaultCounts_IfaceConstants;

+

+   virtual void strobeResetFaultCounts(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tOverCurrentFaultCounts_IfaceConstants;

+

+   virtual tOverCurrentFaultCounts readOverCurrentFaultCounts(tRioStatusCode *status) = 0;

+   virtual unsigned short readOverCurrentFaultCounts_OverCurrentFaultCount3V3(tRioStatusCode *status) = 0;

+   virtual unsigned short readOverCurrentFaultCounts_OverCurrentFaultCount5V(tRioStatusCode *status) = 0;

+   virtual unsigned short readOverCurrentFaultCounts_OverCurrentFaultCount6V(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tIntegratedIO_IfaceConstants;

+

+   virtual unsigned short readIntegratedIO(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tMXP_DIOVoltage_IfaceConstants;

+

+   virtual unsigned short readMXP_DIOVoltage(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tUserCurrent3V3_IfaceConstants;

+

+   virtual unsigned short readUserCurrent3V3(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tVinVoltage_IfaceConstants;

+

+   virtual unsigned short readVinVoltage(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tUserCurrent6V_IfaceConstants;

+

+   virtual unsigned short readUserCurrent6V(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tUserCurrent5V_IfaceConstants;

+

+   virtual unsigned short readUserCurrent5V(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tAOVoltage_IfaceConstants;

+

+   virtual unsigned short readAOVoltage(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tVinCurrent_IfaceConstants;

+

+   virtual unsigned short readVinCurrent(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tDisable_IfaceConstants;

+

+   virtual void writeDisable(tDisable value, tRioStatusCode *status) = 0;

+   virtual void writeDisable_User3V3(bool value, tRioStatusCode *status) = 0;

+   virtual void writeDisable_User5V(bool value, tRioStatusCode *status) = 0;

+   virtual void writeDisable_User6V(bool value, tRioStatusCode *status) = 0;

+   virtual tDisable readDisable(tRioStatusCode *status) = 0;

+   virtual bool readDisable_User3V3(tRioStatusCode *status) = 0;

+   virtual bool readDisable_User5V(tRioStatusCode *status) = 0;

+   virtual bool readDisable_User6V(tRioStatusCode *status) = 0;

+

+

+

+

+private:

+   tPower(const tPower&);

+   void operator=(const tPower&);

+};

+

+}

+}

+

+#endif // __nFRC_2015_1_0_A_Power_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tRelay.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tRelay.h
new file mode 100644
index 0000000..e3f0286
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tRelay.h
@@ -0,0 +1,68 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2015_1_0_A_Relay_h__

+#define __nFRC_2015_1_0_A_Relay_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2015_1_0_A

+{

+

+class tRelay

+{

+public:

+   tRelay(){}

+   virtual ~tRelay(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tRelay* create(tRioStatusCode *status);

+

+   typedef enum

+   {

+      kNumSystems = 1,

+   } tIfaceConstants;

+

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned Forward : 4;

+         unsigned Reverse : 4;

+#else

+         unsigned Reverse : 4;

+         unsigned Forward : 4;

+#endif

+      };

+      struct{

+         unsigned value : 8;

+      };

+   } tValue;

+

+

+

+   typedef enum

+   {

+   } tValue_IfaceConstants;

+

+   virtual void writeValue(tValue value, tRioStatusCode *status) = 0;

+   virtual void writeValue_Forward(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeValue_Reverse(unsigned char value, tRioStatusCode *status) = 0;

+   virtual tValue readValue(tRioStatusCode *status) = 0;

+   virtual unsigned char readValue_Forward(tRioStatusCode *status) = 0;

+   virtual unsigned char readValue_Reverse(tRioStatusCode *status) = 0;

+

+

+

+

+private:

+   tRelay(const tRelay&);

+   void operator=(const tRelay&);

+};

+

+}

+}

+

+#endif // __nFRC_2015_1_0_A_Relay_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tSPI.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tSPI.h
new file mode 100644
index 0000000..93a2b3e
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tSPI.h
@@ -0,0 +1,68 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2015_1_0_A_SPI_h__

+#define __nFRC_2015_1_0_A_SPI_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2015_1_0_A

+{

+

+class tSPI

+{

+public:

+   tSPI(){}

+   virtual ~tSPI(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tSPI* create(tRioStatusCode *status);

+

+   typedef enum

+   {

+      kNumSystems = 1,

+   } tIfaceConstants;

+

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned Hdr : 4;

+         unsigned MXP : 1;

+#else

+         unsigned MXP : 1;

+         unsigned Hdr : 4;

+#endif

+      };

+      struct{

+         unsigned value : 5;

+      };

+   } tChipSelectActiveHigh;

+

+

+

+   typedef enum

+   {

+   } tChipSelectActiveHigh_IfaceConstants;

+

+   virtual void writeChipSelectActiveHigh(tChipSelectActiveHigh value, tRioStatusCode *status) = 0;

+   virtual void writeChipSelectActiveHigh_Hdr(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeChipSelectActiveHigh_MXP(unsigned char value, tRioStatusCode *status) = 0;

+   virtual tChipSelectActiveHigh readChipSelectActiveHigh(tRioStatusCode *status) = 0;

+   virtual unsigned char readChipSelectActiveHigh_Hdr(tRioStatusCode *status) = 0;

+   virtual unsigned char readChipSelectActiveHigh_MXP(tRioStatusCode *status) = 0;

+

+

+

+

+private:

+   tSPI(const tSPI&);

+   void operator=(const tSPI&);

+};

+

+}

+}

+

+#endif // __nFRC_2015_1_0_A_SPI_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tSysWatchdog.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tSysWatchdog.h
new file mode 100644
index 0000000..67dcd13
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tSysWatchdog.h
@@ -0,0 +1,108 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2015_1_0_A_SysWatchdog_h__

+#define __nFRC_2015_1_0_A_SysWatchdog_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2015_1_0_A

+{

+

+class tSysWatchdog

+{

+public:

+   tSysWatchdog(){}

+   virtual ~tSysWatchdog(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tSysWatchdog* create(tRioStatusCode *status);

+

+   typedef enum

+   {

+      kNumSystems = 1,

+   } tIfaceConstants;

+

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned SystemActive : 1;

+         unsigned PowerAlive : 1;

+         unsigned SysDisableCount : 15;

+         unsigned PowerDisableCount : 15;

+#else

+         unsigned PowerDisableCount : 15;

+         unsigned SysDisableCount : 15;

+         unsigned PowerAlive : 1;

+         unsigned SystemActive : 1;

+#endif

+      };

+      struct{

+         unsigned value : 32;

+      };

+   } tStatus;

+

+

+

+   typedef enum

+   {

+   } tStatus_IfaceConstants;

+

+   virtual tStatus readStatus(tRioStatusCode *status) = 0;

+   virtual bool readStatus_SystemActive(tRioStatusCode *status) = 0;

+   virtual bool readStatus_PowerAlive(tRioStatusCode *status) = 0;

+   virtual unsigned short readStatus_SysDisableCount(tRioStatusCode *status) = 0;

+   virtual unsigned short readStatus_PowerDisableCount(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tCommand_IfaceConstants;

+

+   virtual void writeCommand(unsigned short value, tRioStatusCode *status) = 0;

+   virtual unsigned short readCommand(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tChallenge_IfaceConstants;

+

+   virtual unsigned char readChallenge(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tActive_IfaceConstants;

+

+   virtual void writeActive(bool value, tRioStatusCode *status) = 0;

+   virtual bool readActive(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tTimer_IfaceConstants;

+

+   virtual unsigned int readTimer(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tForcedKills_IfaceConstants;

+

+   virtual unsigned short readForcedKills(tRioStatusCode *status) = 0;

+

+

+

+

+private:

+   tSysWatchdog(const tSysWatchdog&);

+   void operator=(const tSysWatchdog&);

+};

+

+}

+}

+

+#endif // __nFRC_2015_1_0_A_SysWatchdog_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/nInterfaceGlobals.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/nInterfaceGlobals.h
new file mode 100644
index 0000000..f34cc74
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/nInterfaceGlobals.h
@@ -0,0 +1,15 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2012_1_6_4_nInterfaceGlobals_h__

+#define __nFRC_2012_1_6_4_nInterfaceGlobals_h__

+

+namespace nFPGA

+{

+namespace nFRC_2012_1_6_4

+{

+   extern unsigned int g_currentTargetClass;

+}

+}

+

+#endif // __nFRC_2012_1_6_4_nInterfaceGlobals_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tAI.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tAI.h
new file mode 100644
index 0000000..78c423a
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tAI.h
@@ -0,0 +1,149 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2012_1_6_4_AI_h__

+#define __nFRC_2012_1_6_4_AI_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2012_1_6_4

+{

+

+class tAI

+{

+public:

+   tAI(){}

+   virtual ~tAI(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tAI* create(unsigned char sys_index, tRioStatusCode *status);

+   virtual unsigned char getSystemIndex() = 0;

+

+

+   typedef enum

+   {

+      kNumSystems = 2,

+   } tIfaceConstants;

+

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned Channel : 3;

+         unsigned Module : 1;

+         unsigned Averaged : 1;

+#else

+         unsigned Averaged : 1;

+         unsigned Module : 1;

+         unsigned Channel : 3;

+#endif

+      };

+      struct{

+         unsigned value : 5;

+      };

+   } tReadSelect;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned ScanSize : 3;

+         unsigned ConvertRate : 26;

+#else

+         unsigned ConvertRate : 26;

+         unsigned ScanSize : 3;

+#endif

+      };

+      struct{

+         unsigned value : 29;

+      };

+   } tConfig;

+

+

+   typedef enum

+   {

+   } tConfig_IfaceConstants;

+

+   virtual void writeConfig(tConfig value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_ScanSize(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_ConvertRate(unsigned int value, tRioStatusCode *status) = 0;

+   virtual tConfig readConfig(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_ScanSize(tRioStatusCode *status) = 0;

+   virtual unsigned int readConfig_ConvertRate(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tLoopTiming_IfaceConstants;

+

+   virtual unsigned int readLoopTiming(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+      kNumOversampleBitsElements = 8,

+   } tOversampleBits_IfaceConstants;

+

+   virtual void writeOversampleBits(unsigned char bitfield_index, unsigned char value, tRioStatusCode *status) = 0;

+   virtual unsigned char readOversampleBits(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+      kNumAverageBitsElements = 8,

+   } tAverageBits_IfaceConstants;

+

+   virtual void writeAverageBits(unsigned char bitfield_index, unsigned char value, tRioStatusCode *status) = 0;

+   virtual unsigned char readAverageBits(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+      kNumScanListElements = 8,

+   } tScanList_IfaceConstants;

+

+   virtual void writeScanList(unsigned char bitfield_index, unsigned char value, tRioStatusCode *status) = 0;

+   virtual unsigned char readScanList(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+

+

+

+   typedef enum

+   {

+   } tOutput_IfaceConstants;

+

+   virtual signed int readOutput(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tLatchOutput_IfaceConstants;

+

+   virtual void strobeLatchOutput(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tReadSelect_IfaceConstants;

+

+   virtual void writeReadSelect(tReadSelect value, tRioStatusCode *status) = 0;

+   virtual void writeReadSelect_Channel(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeReadSelect_Module(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeReadSelect_Averaged(bool value, tRioStatusCode *status) = 0;

+   virtual tReadSelect readReadSelect(tRioStatusCode *status) = 0;

+   virtual unsigned char readReadSelect_Channel(tRioStatusCode *status) = 0;

+   virtual unsigned char readReadSelect_Module(tRioStatusCode *status) = 0;

+   virtual bool readReadSelect_Averaged(tRioStatusCode *status) = 0;

+

+

+

+

+private:

+   tAI(const tAI&);

+   void operator=(const tAI&);

+};

+

+}

+}

+

+#endif // __nFRC_2012_1_6_4_AI_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tAccumulator.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tAccumulator.h
new file mode 100644
index 0000000..1a0972a
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tAccumulator.h
@@ -0,0 +1,87 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2012_1_6_4_Accumulator_h__

+#define __nFRC_2012_1_6_4_Accumulator_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2012_1_6_4

+{

+

+class tAccumulator

+{

+public:

+   tAccumulator(){}

+   virtual ~tAccumulator(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tAccumulator* create(unsigned char sys_index, tRioStatusCode *status);

+   virtual unsigned char getSystemIndex() = 0;

+

+

+   typedef enum

+   {

+      kNumSystems = 2,

+   } tIfaceConstants;

+

+   typedef

+   union{

+      struct{

+         signed long long Value;

+         unsigned Count : 32;

+      };

+      struct{

+         unsigned value : 32;

+         unsigned value2 : 32;

+         unsigned value3 : 32;

+      };

+   } tOutput;

+

+

+   typedef enum

+   {

+   } tOutput_IfaceConstants;

+

+   virtual tOutput readOutput(tRioStatusCode *status) = 0;

+   virtual signed long long readOutput_Value(tRioStatusCode *status) = 0;

+   virtual unsigned int readOutput_Count(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tCenter_IfaceConstants;

+

+   virtual void writeCenter(signed int value, tRioStatusCode *status) = 0;

+   virtual signed int readCenter(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tDeadband_IfaceConstants;

+

+   virtual void writeDeadband(signed int value, tRioStatusCode *status) = 0;

+   virtual signed int readDeadband(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tReset_IfaceConstants;

+

+   virtual void strobeReset(tRioStatusCode *status) = 0;

+

+

+

+

+

+private:

+   tAccumulator(const tAccumulator&);

+   void operator=(const tAccumulator&);

+};

+

+}

+}

+

+#endif // __nFRC_2012_1_6_4_Accumulator_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tAlarm.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tAlarm.h
new file mode 100644
index 0000000..f3eb33f
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tAlarm.h
@@ -0,0 +1,57 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2012_1_6_4_Alarm_h__

+#define __nFRC_2012_1_6_4_Alarm_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2012_1_6_4

+{

+

+class tAlarm

+{

+public:

+   tAlarm(){}

+   virtual ~tAlarm(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tAlarm* create(tRioStatusCode *status);

+

+   typedef enum

+   {

+      kNumSystems = 1,

+   } tIfaceConstants;

+

+

+

+

+   typedef enum

+   {

+   } tEnable_IfaceConstants;

+

+   virtual void writeEnable(bool value, tRioStatusCode *status) = 0;

+   virtual bool readEnable(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tTriggerTime_IfaceConstants;

+

+   virtual void writeTriggerTime(unsigned int value, tRioStatusCode *status) = 0;

+   virtual unsigned int readTriggerTime(tRioStatusCode *status) = 0;

+

+

+

+

+private:

+   tAlarm(const tAlarm&);

+   void operator=(const tAlarm&);

+};

+

+}

+}

+

+#endif // __nFRC_2012_1_6_4_Alarm_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tAnalogTrigger.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tAnalogTrigger.h
new file mode 100644
index 0000000..43150f7
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tAnalogTrigger.h
@@ -0,0 +1,133 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2012_1_6_4_AnalogTrigger_h__

+#define __nFRC_2012_1_6_4_AnalogTrigger_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2012_1_6_4

+{

+

+class tAnalogTrigger

+{

+public:

+   tAnalogTrigger(){}

+   virtual ~tAnalogTrigger(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tAnalogTrigger* create(unsigned char sys_index, tRioStatusCode *status);

+   virtual unsigned char getSystemIndex() = 0;

+

+

+   typedef enum

+   {

+      kNumSystems = 8,

+   } tIfaceConstants;

+

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned InHysteresis : 1;

+         unsigned OverLimit : 1;

+         unsigned Rising : 1;

+         unsigned Falling : 1;

+#else

+         unsigned Falling : 1;

+         unsigned Rising : 1;

+         unsigned OverLimit : 1;

+         unsigned InHysteresis : 1;

+#endif

+      };

+      struct{

+         unsigned value : 4;

+      };

+   } tOutput;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned Channel : 3;

+         unsigned Module : 1;

+         unsigned Averaged : 1;

+         unsigned Filter : 1;

+         unsigned FloatingRollover : 1;

+         signed RolloverLimit : 8;

+#else

+         signed RolloverLimit : 8;

+         unsigned FloatingRollover : 1;

+         unsigned Filter : 1;

+         unsigned Averaged : 1;

+         unsigned Module : 1;

+         unsigned Channel : 3;

+#endif

+      };

+      struct{

+         unsigned value : 15;

+      };

+   } tSourceSelect;

+

+

+   typedef enum

+   {

+   } tSourceSelect_IfaceConstants;

+

+   virtual void writeSourceSelect(tSourceSelect value, tRioStatusCode *status) = 0;

+   virtual void writeSourceSelect_Channel(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeSourceSelect_Module(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeSourceSelect_Averaged(bool value, tRioStatusCode *status) = 0;

+   virtual void writeSourceSelect_Filter(bool value, tRioStatusCode *status) = 0;

+   virtual void writeSourceSelect_FloatingRollover(bool value, tRioStatusCode *status) = 0;

+   virtual void writeSourceSelect_RolloverLimit(signed short value, tRioStatusCode *status) = 0;

+   virtual tSourceSelect readSourceSelect(tRioStatusCode *status) = 0;

+   virtual unsigned char readSourceSelect_Channel(tRioStatusCode *status) = 0;

+   virtual unsigned char readSourceSelect_Module(tRioStatusCode *status) = 0;

+   virtual bool readSourceSelect_Averaged(tRioStatusCode *status) = 0;

+   virtual bool readSourceSelect_Filter(tRioStatusCode *status) = 0;

+   virtual bool readSourceSelect_FloatingRollover(tRioStatusCode *status) = 0;

+   virtual signed short readSourceSelect_RolloverLimit(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tUpperLimit_IfaceConstants;

+

+   virtual void writeUpperLimit(signed int value, tRioStatusCode *status) = 0;

+   virtual signed int readUpperLimit(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tLowerLimit_IfaceConstants;

+

+   virtual void writeLowerLimit(signed int value, tRioStatusCode *status) = 0;

+   virtual signed int readLowerLimit(tRioStatusCode *status) = 0;

+

+

+

+   typedef enum

+   {

+      kNumOutputElements = 8,

+   } tOutput_IfaceConstants;

+

+   virtual tOutput readOutput(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+   virtual bool readOutput_InHysteresis(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+   virtual bool readOutput_OverLimit(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+   virtual bool readOutput_Rising(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+   virtual bool readOutput_Falling(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+

+

+

+

+private:

+   tAnalogTrigger(const tAnalogTrigger&);

+   void operator=(const tAnalogTrigger&);

+};

+

+}

+}

+

+#endif // __nFRC_2012_1_6_4_AnalogTrigger_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tCounter.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tCounter.h
new file mode 100644
index 0000000..b23a7f0
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tCounter.h
@@ -0,0 +1,219 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2012_1_6_4_Counter_h__

+#define __nFRC_2012_1_6_4_Counter_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2012_1_6_4

+{

+

+class tCounter

+{

+public:

+   tCounter(){}

+   virtual ~tCounter(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tCounter* create(unsigned char sys_index, tRioStatusCode *status);

+   virtual unsigned char getSystemIndex() = 0;

+

+

+   typedef enum

+   {

+      kNumSystems = 8,

+   } tIfaceConstants;

+

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned Direction : 1;

+         signed Value : 31;

+#else

+         signed Value : 31;

+         unsigned Direction : 1;

+#endif

+      };

+      struct{

+         unsigned value : 32;

+      };

+   } tOutput;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned UpSource_Channel : 4;

+         unsigned UpSource_Module : 1;

+         unsigned UpSource_AnalogTrigger : 1;

+         unsigned DownSource_Channel : 4;

+         unsigned DownSource_Module : 1;

+         unsigned DownSource_AnalogTrigger : 1;

+         unsigned IndexSource_Channel : 4;

+         unsigned IndexSource_Module : 1;

+         unsigned IndexSource_AnalogTrigger : 1;

+         unsigned IndexActiveHigh : 1;

+         unsigned UpRisingEdge : 1;

+         unsigned UpFallingEdge : 1;

+         unsigned DownRisingEdge : 1;

+         unsigned DownFallingEdge : 1;

+         unsigned Mode : 2;

+         unsigned PulseLengthThreshold : 6;

+         unsigned Enable : 1;

+#else

+         unsigned Enable : 1;

+         unsigned PulseLengthThreshold : 6;

+         unsigned Mode : 2;

+         unsigned DownFallingEdge : 1;

+         unsigned DownRisingEdge : 1;

+         unsigned UpFallingEdge : 1;

+         unsigned UpRisingEdge : 1;

+         unsigned IndexActiveHigh : 1;

+         unsigned IndexSource_AnalogTrigger : 1;

+         unsigned IndexSource_Module : 1;

+         unsigned IndexSource_Channel : 4;

+         unsigned DownSource_AnalogTrigger : 1;

+         unsigned DownSource_Module : 1;

+         unsigned DownSource_Channel : 4;

+         unsigned UpSource_AnalogTrigger : 1;

+         unsigned UpSource_Module : 1;

+         unsigned UpSource_Channel : 4;

+#endif

+      };

+      struct{

+         unsigned value : 32;

+      };

+   } tConfig;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned Period : 23;

+         signed Count : 8;

+         unsigned Stalled : 1;

+#else

+         unsigned Stalled : 1;

+         signed Count : 8;

+         unsigned Period : 23;

+#endif

+      };

+      struct{

+         unsigned value : 32;

+      };

+   } tTimerOutput;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned StallPeriod : 24;

+         unsigned AverageSize : 7;

+         unsigned UpdateWhenEmpty : 1;

+#else

+         unsigned UpdateWhenEmpty : 1;

+         unsigned AverageSize : 7;

+         unsigned StallPeriod : 24;

+#endif

+      };

+      struct{

+         unsigned value : 32;

+      };

+   } tTimerConfig;

+

+

+   typedef enum

+   {

+   } tOutput_IfaceConstants;

+

+   virtual tOutput readOutput(tRioStatusCode *status) = 0;

+   virtual bool readOutput_Direction(tRioStatusCode *status) = 0;

+   virtual signed int readOutput_Value(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tConfig_IfaceConstants;

+

+   virtual void writeConfig(tConfig value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_UpSource_Channel(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_UpSource_Module(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_UpSource_AnalogTrigger(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_DownSource_Channel(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_DownSource_Module(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_DownSource_AnalogTrigger(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_IndexSource_Channel(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_IndexSource_Module(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_IndexSource_AnalogTrigger(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_IndexActiveHigh(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_UpRisingEdge(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_UpFallingEdge(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_DownRisingEdge(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_DownFallingEdge(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Mode(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_PulseLengthThreshold(unsigned short value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable(bool value, tRioStatusCode *status) = 0;

+   virtual tConfig readConfig(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_UpSource_Channel(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_UpSource_Module(tRioStatusCode *status) = 0;

+   virtual bool readConfig_UpSource_AnalogTrigger(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_DownSource_Channel(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_DownSource_Module(tRioStatusCode *status) = 0;

+   virtual bool readConfig_DownSource_AnalogTrigger(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_IndexSource_Channel(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_IndexSource_Module(tRioStatusCode *status) = 0;

+   virtual bool readConfig_IndexSource_AnalogTrigger(tRioStatusCode *status) = 0;

+   virtual bool readConfig_IndexActiveHigh(tRioStatusCode *status) = 0;

+   virtual bool readConfig_UpRisingEdge(tRioStatusCode *status) = 0;

+   virtual bool readConfig_UpFallingEdge(tRioStatusCode *status) = 0;

+   virtual bool readConfig_DownRisingEdge(tRioStatusCode *status) = 0;

+   virtual bool readConfig_DownFallingEdge(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_Mode(tRioStatusCode *status) = 0;

+   virtual unsigned short readConfig_PulseLengthThreshold(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tTimerOutput_IfaceConstants;

+

+   virtual tTimerOutput readTimerOutput(tRioStatusCode *status) = 0;

+   virtual unsigned int readTimerOutput_Period(tRioStatusCode *status) = 0;

+   virtual signed char readTimerOutput_Count(tRioStatusCode *status) = 0;

+   virtual bool readTimerOutput_Stalled(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tReset_IfaceConstants;

+

+   virtual void strobeReset(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tTimerConfig_IfaceConstants;

+

+   virtual void writeTimerConfig(tTimerConfig value, tRioStatusCode *status) = 0;

+   virtual void writeTimerConfig_StallPeriod(unsigned int value, tRioStatusCode *status) = 0;

+   virtual void writeTimerConfig_AverageSize(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeTimerConfig_UpdateWhenEmpty(bool value, tRioStatusCode *status) = 0;

+   virtual tTimerConfig readTimerConfig(tRioStatusCode *status) = 0;

+   virtual unsigned int readTimerConfig_StallPeriod(tRioStatusCode *status) = 0;

+   virtual unsigned char readTimerConfig_AverageSize(tRioStatusCode *status) = 0;

+   virtual bool readTimerConfig_UpdateWhenEmpty(tRioStatusCode *status) = 0;

+

+

+

+

+

+private:

+   tCounter(const tCounter&);

+   void operator=(const tCounter&);

+};

+

+}

+}

+

+#endif // __nFRC_2012_1_6_4_Counter_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tDIO.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tDIO.h
new file mode 100644
index 0000000..babb691
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tDIO.h
@@ -0,0 +1,330 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2012_1_6_4_DIO_h__

+#define __nFRC_2012_1_6_4_DIO_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2012_1_6_4

+{

+

+class tDIO

+{

+public:

+   tDIO(){}

+   virtual ~tDIO(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tDIO* create(unsigned char sys_index, tRioStatusCode *status);

+   virtual unsigned char getSystemIndex() = 0;

+

+

+   typedef enum

+   {

+      kNumSystems = 2,

+   } tIfaceConstants;

+

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned Period : 16;

+         unsigned MinHigh : 16;

+#else

+         unsigned MinHigh : 16;

+         unsigned Period : 16;

+#endif

+      };

+      struct{

+         unsigned value : 32;

+      };

+   } tPWMConfig;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned RelayFwd : 8;

+         unsigned RelayRev : 8;

+         unsigned I2CHeader : 4;

+#else

+         unsigned I2CHeader : 4;

+         unsigned RelayRev : 8;

+         unsigned RelayFwd : 8;

+#endif

+      };

+      struct{

+         unsigned value : 20;

+      };

+   } tSlowValue;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned Transaction : 1;

+         unsigned Done : 1;

+         unsigned Aborted : 1;

+         unsigned DataReceivedHigh : 24;

+#else

+         unsigned DataReceivedHigh : 24;

+         unsigned Aborted : 1;

+         unsigned Done : 1;

+         unsigned Transaction : 1;

+#endif

+      };

+      struct{

+         unsigned value : 27;

+      };

+   } tI2CStatus;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned Address : 8;

+         unsigned BytesToRead : 3;

+         unsigned BytesToWrite : 3;

+         unsigned DataToSendHigh : 16;

+         unsigned BitwiseHandshake : 1;

+#else

+         unsigned BitwiseHandshake : 1;

+         unsigned DataToSendHigh : 16;

+         unsigned BytesToWrite : 3;

+         unsigned BytesToRead : 3;

+         unsigned Address : 8;

+#endif

+      };

+      struct{

+         unsigned value : 31;

+      };

+   } tI2CConfig;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned PeriodPower : 4;

+         unsigned OutputSelect_0 : 4;

+         unsigned OutputSelect_1 : 4;

+         unsigned OutputSelect_2 : 4;

+         unsigned OutputSelect_3 : 4;

+#else

+         unsigned OutputSelect_3 : 4;

+         unsigned OutputSelect_2 : 4;

+         unsigned OutputSelect_1 : 4;

+         unsigned OutputSelect_0 : 4;

+         unsigned PeriodPower : 4;

+#endif

+      };

+      struct{

+         unsigned value : 20;

+      };

+   } tDO_PWMConfig;

+

+

+   typedef enum

+   {

+      kNumFilterSelectElements = 16,

+   } tFilterSelect_IfaceConstants;

+

+   virtual void writeFilterSelect(unsigned char bitfield_index, unsigned char value, tRioStatusCode *status) = 0;

+   virtual unsigned char readFilterSelect(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tI2CDataToSend_IfaceConstants;

+

+   virtual void writeI2CDataToSend(unsigned int value, tRioStatusCode *status) = 0;

+   virtual unsigned int readI2CDataToSend(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tDO_IfaceConstants;

+

+   virtual void writeDO(unsigned short value, tRioStatusCode *status) = 0;

+   virtual unsigned short readDO(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+      kNumFilterPeriodElements = 3,

+   } tFilterPeriod_IfaceConstants;

+

+   virtual void writeFilterPeriod(unsigned char bitfield_index, unsigned char value, tRioStatusCode *status) = 0;

+   virtual unsigned char readFilterPeriod(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tOutputEnable_IfaceConstants;

+

+   virtual void writeOutputEnable(unsigned short value, tRioStatusCode *status) = 0;

+   virtual unsigned short readOutputEnable(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tPulse_IfaceConstants;

+

+   virtual void writePulse(unsigned short value, tRioStatusCode *status) = 0;

+   virtual unsigned short readPulse(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tSlowValue_IfaceConstants;

+

+   virtual void writeSlowValue(tSlowValue value, tRioStatusCode *status) = 0;

+   virtual void writeSlowValue_RelayFwd(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeSlowValue_RelayRev(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeSlowValue_I2CHeader(unsigned char value, tRioStatusCode *status) = 0;

+   virtual tSlowValue readSlowValue(tRioStatusCode *status) = 0;

+   virtual unsigned char readSlowValue_RelayFwd(tRioStatusCode *status) = 0;

+   virtual unsigned char readSlowValue_RelayRev(tRioStatusCode *status) = 0;

+   virtual unsigned char readSlowValue_I2CHeader(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tI2CStatus_IfaceConstants;

+

+   virtual tI2CStatus readI2CStatus(tRioStatusCode *status) = 0;

+   virtual unsigned char readI2CStatus_Transaction(tRioStatusCode *status) = 0;

+   virtual bool readI2CStatus_Done(tRioStatusCode *status) = 0;

+   virtual bool readI2CStatus_Aborted(tRioStatusCode *status) = 0;

+   virtual unsigned int readI2CStatus_DataReceivedHigh(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tI2CDataReceived_IfaceConstants;

+

+   virtual unsigned int readI2CDataReceived(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tDI_IfaceConstants;

+

+   virtual unsigned short readDI(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tPulseLength_IfaceConstants;

+

+   virtual void writePulseLength(unsigned char value, tRioStatusCode *status) = 0;

+   virtual unsigned char readPulseLength(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+      kNumPWMPeriodScaleElements = 10,

+   } tPWMPeriodScale_IfaceConstants;

+

+   virtual void writePWMPeriodScale(unsigned char bitfield_index, unsigned char value, tRioStatusCode *status) = 0;

+   virtual unsigned char readPWMPeriodScale(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+      kNumDO_PWMDutyCycleElements = 4,

+   } tDO_PWMDutyCycle_IfaceConstants;

+

+   virtual void writeDO_PWMDutyCycle(unsigned char bitfield_index, unsigned char value, tRioStatusCode *status) = 0;

+   virtual unsigned char readDO_PWMDutyCycle(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tBFL_IfaceConstants;

+

+   virtual void writeBFL(bool value, tRioStatusCode *status) = 0;

+   virtual bool readBFL(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tI2CConfig_IfaceConstants;

+

+   virtual void writeI2CConfig(tI2CConfig value, tRioStatusCode *status) = 0;

+   virtual void writeI2CConfig_Address(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeI2CConfig_BytesToRead(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeI2CConfig_BytesToWrite(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeI2CConfig_DataToSendHigh(unsigned short value, tRioStatusCode *status) = 0;

+   virtual void writeI2CConfig_BitwiseHandshake(bool value, tRioStatusCode *status) = 0;

+   virtual tI2CConfig readI2CConfig(tRioStatusCode *status) = 0;

+   virtual unsigned char readI2CConfig_Address(tRioStatusCode *status) = 0;

+   virtual unsigned char readI2CConfig_BytesToRead(tRioStatusCode *status) = 0;

+   virtual unsigned char readI2CConfig_BytesToWrite(tRioStatusCode *status) = 0;

+   virtual unsigned short readI2CConfig_DataToSendHigh(tRioStatusCode *status) = 0;

+   virtual bool readI2CConfig_BitwiseHandshake(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tDO_PWMConfig_IfaceConstants;

+

+   virtual void writeDO_PWMConfig(tDO_PWMConfig value, tRioStatusCode *status) = 0;

+   virtual void writeDO_PWMConfig_PeriodPower(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeDO_PWMConfig_OutputSelect_0(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeDO_PWMConfig_OutputSelect_1(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeDO_PWMConfig_OutputSelect_2(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeDO_PWMConfig_OutputSelect_3(unsigned char value, tRioStatusCode *status) = 0;

+   virtual tDO_PWMConfig readDO_PWMConfig(tRioStatusCode *status) = 0;

+   virtual unsigned char readDO_PWMConfig_PeriodPower(tRioStatusCode *status) = 0;

+   virtual unsigned char readDO_PWMConfig_OutputSelect_0(tRioStatusCode *status) = 0;

+   virtual unsigned char readDO_PWMConfig_OutputSelect_1(tRioStatusCode *status) = 0;

+   virtual unsigned char readDO_PWMConfig_OutputSelect_2(tRioStatusCode *status) = 0;

+   virtual unsigned char readDO_PWMConfig_OutputSelect_3(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tI2CStart_IfaceConstants;

+

+   virtual void strobeI2CStart(tRioStatusCode *status) = 0;

+

+

+

+   typedef enum

+   {

+   } tLoopTiming_IfaceConstants;

+

+   virtual unsigned short readLoopTiming(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tPWMConfig_IfaceConstants;

+

+   virtual void writePWMConfig(tPWMConfig value, tRioStatusCode *status) = 0;

+   virtual void writePWMConfig_Period(unsigned short value, tRioStatusCode *status) = 0;

+   virtual void writePWMConfig_MinHigh(unsigned short value, tRioStatusCode *status) = 0;

+   virtual tPWMConfig readPWMConfig(tRioStatusCode *status) = 0;

+   virtual unsigned short readPWMConfig_Period(tRioStatusCode *status) = 0;

+   virtual unsigned short readPWMConfig_MinHigh(tRioStatusCode *status) = 0;

+

+

+

+   typedef enum

+   {

+      kNumPWMValueRegisters = 10,

+   } tPWMValue_IfaceConstants;

+

+   virtual void writePWMValue(unsigned char reg_index, unsigned char value, tRioStatusCode *status) = 0;

+   virtual unsigned char readPWMValue(unsigned char reg_index, tRioStatusCode *status) = 0;

+

+

+

+private:

+   tDIO(const tDIO&);

+   void operator=(const tDIO&);

+};

+

+}

+}

+

+#endif // __nFRC_2012_1_6_4_DIO_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tDMA.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tDMA.h
new file mode 100644
index 0000000..006ec60
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tDMA.h
@@ -0,0 +1,188 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2012_1_6_4_DMA_h__

+#define __nFRC_2012_1_6_4_DMA_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2012_1_6_4

+{

+

+class tDMA

+{

+public:

+   tDMA(){}

+   virtual ~tDMA(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tDMA* create(tRioStatusCode *status);

+

+   typedef enum

+   {

+      kNumSystems = 1,

+   } tIfaceConstants;

+

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned Pause : 1;

+         unsigned Enable_AI0_Low : 1;

+         unsigned Enable_AI0_High : 1;

+         unsigned Enable_AIAveraged0_Low : 1;

+         unsigned Enable_AIAveraged0_High : 1;

+         unsigned Enable_AI1_Low : 1;

+         unsigned Enable_AI1_High : 1;

+         unsigned Enable_AIAveraged1_Low : 1;

+         unsigned Enable_AIAveraged1_High : 1;

+         unsigned Enable_Accumulator0 : 1;

+         unsigned Enable_Accumulator1 : 1;

+         unsigned Enable_DI : 1;

+         unsigned Enable_AnalogTriggers : 1;

+         unsigned Enable_Counters_Low : 1;

+         unsigned Enable_Counters_High : 1;

+         unsigned Enable_CounterTimers_Low : 1;

+         unsigned Enable_CounterTimers_High : 1;

+         unsigned Enable_Encoders : 1;

+         unsigned Enable_EncoderTimers : 1;

+         unsigned ExternalClock : 1;

+#else

+         unsigned ExternalClock : 1;

+         unsigned Enable_EncoderTimers : 1;

+         unsigned Enable_Encoders : 1;

+         unsigned Enable_CounterTimers_High : 1;

+         unsigned Enable_CounterTimers_Low : 1;

+         unsigned Enable_Counters_High : 1;

+         unsigned Enable_Counters_Low : 1;

+         unsigned Enable_AnalogTriggers : 1;

+         unsigned Enable_DI : 1;

+         unsigned Enable_Accumulator1 : 1;

+         unsigned Enable_Accumulator0 : 1;

+         unsigned Enable_AIAveraged1_High : 1;

+         unsigned Enable_AIAveraged1_Low : 1;

+         unsigned Enable_AI1_High : 1;

+         unsigned Enable_AI1_Low : 1;

+         unsigned Enable_AIAveraged0_High : 1;

+         unsigned Enable_AIAveraged0_Low : 1;

+         unsigned Enable_AI0_High : 1;

+         unsigned Enable_AI0_Low : 1;

+         unsigned Pause : 1;

+#endif

+      };

+      struct{

+         unsigned value : 20;

+      };

+   } tConfig;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned ExternalClockSource_Channel : 4;

+         unsigned ExternalClockSource_Module : 1;

+         unsigned ExternalClockSource_AnalogTrigger : 1;

+         unsigned RisingEdge : 1;

+         unsigned FallingEdge : 1;

+#else

+         unsigned FallingEdge : 1;

+         unsigned RisingEdge : 1;

+         unsigned ExternalClockSource_AnalogTrigger : 1;

+         unsigned ExternalClockSource_Module : 1;

+         unsigned ExternalClockSource_Channel : 4;

+#endif

+      };

+      struct{

+         unsigned value : 8;

+      };

+   } tExternalTriggers;

+

+

+

+   typedef enum

+   {

+   } tRate_IfaceConstants;

+

+   virtual void writeRate(unsigned int value, tRioStatusCode *status) = 0;

+   virtual unsigned int readRate(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tConfig_IfaceConstants;

+

+   virtual void writeConfig(tConfig value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Pause(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_AI0_Low(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_AI0_High(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_AIAveraged0_Low(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_AIAveraged0_High(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_AI1_Low(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_AI1_High(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_AIAveraged1_Low(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_AIAveraged1_High(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_Accumulator0(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_Accumulator1(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_DI(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_AnalogTriggers(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_Counters_Low(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_Counters_High(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_CounterTimers_Low(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_CounterTimers_High(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_Encoders(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable_EncoderTimers(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_ExternalClock(bool value, tRioStatusCode *status) = 0;

+   virtual tConfig readConfig(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Pause(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_AI0_Low(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_AI0_High(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_AIAveraged0_Low(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_AIAveraged0_High(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_AI1_Low(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_AI1_High(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_AIAveraged1_Low(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_AIAveraged1_High(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_Accumulator0(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_Accumulator1(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_DI(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_AnalogTriggers(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_Counters_Low(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_Counters_High(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_CounterTimers_Low(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_CounterTimers_High(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_Encoders(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable_EncoderTimers(tRioStatusCode *status) = 0;

+   virtual bool readConfig_ExternalClock(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+      kNumExternalTriggersElements = 4,

+   } tExternalTriggers_IfaceConstants;

+

+   virtual void writeExternalTriggers(unsigned char bitfield_index, tExternalTriggers value, tRioStatusCode *status) = 0;

+   virtual void writeExternalTriggers_ExternalClockSource_Channel(unsigned char bitfield_index, unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeExternalTriggers_ExternalClockSource_Module(unsigned char bitfield_index, unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeExternalTriggers_ExternalClockSource_AnalogTrigger(unsigned char bitfield_index, bool value, tRioStatusCode *status) = 0;

+   virtual void writeExternalTriggers_RisingEdge(unsigned char bitfield_index, bool value, tRioStatusCode *status) = 0;

+   virtual void writeExternalTriggers_FallingEdge(unsigned char bitfield_index, bool value, tRioStatusCode *status) = 0;

+   virtual tExternalTriggers readExternalTriggers(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+   virtual unsigned char readExternalTriggers_ExternalClockSource_Channel(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+   virtual unsigned char readExternalTriggers_ExternalClockSource_Module(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+   virtual bool readExternalTriggers_ExternalClockSource_AnalogTrigger(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+   virtual bool readExternalTriggers_RisingEdge(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+   virtual bool readExternalTriggers_FallingEdge(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+

+

+

+

+private:

+   tDMA(const tDMA&);

+   void operator=(const tDMA&);

+};

+

+}

+}

+

+#endif // __nFRC_2012_1_6_4_DMA_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tEncoder.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tEncoder.h
new file mode 100644
index 0000000..7255920
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tEncoder.h
@@ -0,0 +1,199 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2012_1_6_4_Encoder_h__

+#define __nFRC_2012_1_6_4_Encoder_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2012_1_6_4

+{

+

+class tEncoder

+{

+public:

+   tEncoder(){}

+   virtual ~tEncoder(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tEncoder* create(unsigned char sys_index, tRioStatusCode *status);

+   virtual unsigned char getSystemIndex() = 0;

+

+

+   typedef enum

+   {

+      kNumSystems = 4,

+   } tIfaceConstants;

+

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned Direction : 1;

+         signed Value : 31;

+#else

+         signed Value : 31;

+         unsigned Direction : 1;

+#endif

+      };

+      struct{

+         unsigned value : 32;

+      };

+   } tOutput;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned ASource_Channel : 4;

+         unsigned ASource_Module : 1;

+         unsigned ASource_AnalogTrigger : 1;

+         unsigned BSource_Channel : 4;

+         unsigned BSource_Module : 1;

+         unsigned BSource_AnalogTrigger : 1;

+         unsigned IndexSource_Channel : 4;

+         unsigned IndexSource_Module : 1;

+         unsigned IndexSource_AnalogTrigger : 1;

+         unsigned IndexActiveHigh : 1;

+         unsigned Reverse : 1;

+         unsigned Enable : 1;

+#else

+         unsigned Enable : 1;

+         unsigned Reverse : 1;

+         unsigned IndexActiveHigh : 1;

+         unsigned IndexSource_AnalogTrigger : 1;

+         unsigned IndexSource_Module : 1;

+         unsigned IndexSource_Channel : 4;

+         unsigned BSource_AnalogTrigger : 1;

+         unsigned BSource_Module : 1;

+         unsigned BSource_Channel : 4;

+         unsigned ASource_AnalogTrigger : 1;

+         unsigned ASource_Module : 1;

+         unsigned ASource_Channel : 4;

+#endif

+      };

+      struct{

+         unsigned value : 21;

+      };

+   } tConfig;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned Period : 23;

+         signed Count : 8;

+         unsigned Stalled : 1;

+#else

+         unsigned Stalled : 1;

+         signed Count : 8;

+         unsigned Period : 23;

+#endif

+      };

+      struct{

+         unsigned value : 32;

+      };

+   } tTimerOutput;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned StallPeriod : 24;

+         unsigned AverageSize : 7;

+         unsigned UpdateWhenEmpty : 1;

+#else

+         unsigned UpdateWhenEmpty : 1;

+         unsigned AverageSize : 7;

+         unsigned StallPeriod : 24;

+#endif

+      };

+      struct{

+         unsigned value : 32;

+      };

+   } tTimerConfig;

+

+

+   typedef enum

+   {

+   } tOutput_IfaceConstants;

+

+   virtual tOutput readOutput(tRioStatusCode *status) = 0;

+   virtual bool readOutput_Direction(tRioStatusCode *status) = 0;

+   virtual signed int readOutput_Value(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tConfig_IfaceConstants;

+

+   virtual void writeConfig(tConfig value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_ASource_Channel(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_ASource_Module(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_ASource_AnalogTrigger(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_BSource_Channel(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_BSource_Module(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_BSource_AnalogTrigger(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_IndexSource_Channel(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_IndexSource_Module(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_IndexSource_AnalogTrigger(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_IndexActiveHigh(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Reverse(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Enable(bool value, tRioStatusCode *status) = 0;

+   virtual tConfig readConfig(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_ASource_Channel(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_ASource_Module(tRioStatusCode *status) = 0;

+   virtual bool readConfig_ASource_AnalogTrigger(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_BSource_Channel(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_BSource_Module(tRioStatusCode *status) = 0;

+   virtual bool readConfig_BSource_AnalogTrigger(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_IndexSource_Channel(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_IndexSource_Module(tRioStatusCode *status) = 0;

+   virtual bool readConfig_IndexSource_AnalogTrigger(tRioStatusCode *status) = 0;

+   virtual bool readConfig_IndexActiveHigh(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Reverse(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Enable(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tTimerOutput_IfaceConstants;

+

+   virtual tTimerOutput readTimerOutput(tRioStatusCode *status) = 0;

+   virtual unsigned int readTimerOutput_Period(tRioStatusCode *status) = 0;

+   virtual signed char readTimerOutput_Count(tRioStatusCode *status) = 0;

+   virtual bool readTimerOutput_Stalled(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tReset_IfaceConstants;

+

+   virtual void strobeReset(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tTimerConfig_IfaceConstants;

+

+   virtual void writeTimerConfig(tTimerConfig value, tRioStatusCode *status) = 0;

+   virtual void writeTimerConfig_StallPeriod(unsigned int value, tRioStatusCode *status) = 0;

+   virtual void writeTimerConfig_AverageSize(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeTimerConfig_UpdateWhenEmpty(bool value, tRioStatusCode *status) = 0;

+   virtual tTimerConfig readTimerConfig(tRioStatusCode *status) = 0;

+   virtual unsigned int readTimerConfig_StallPeriod(tRioStatusCode *status) = 0;

+   virtual unsigned char readTimerConfig_AverageSize(tRioStatusCode *status) = 0;

+   virtual bool readTimerConfig_UpdateWhenEmpty(tRioStatusCode *status) = 0;

+

+

+

+

+

+private:

+   tEncoder(const tEncoder&);

+   void operator=(const tEncoder&);

+};

+

+}

+}

+

+#endif // __nFRC_2012_1_6_4_Encoder_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tGlobal.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tGlobal.h
new file mode 100644
index 0000000..0782f35
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tGlobal.h
@@ -0,0 +1,70 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2012_1_6_4_Global_h__

+#define __nFRC_2012_1_6_4_Global_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2012_1_6_4

+{

+

+class tGlobal

+{

+public:

+   tGlobal(){}

+   virtual ~tGlobal(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tGlobal* create(tRioStatusCode *status);

+

+   typedef enum

+   {

+      kNumSystems = 1,

+   } tIfaceConstants;

+

+

+

+

+   typedef enum

+   {

+   } tVersion_IfaceConstants;

+

+   virtual unsigned short readVersion(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tLocalTime_IfaceConstants;

+

+   virtual unsigned int readLocalTime(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tFPGA_LED_IfaceConstants;

+

+   virtual void writeFPGA_LED(bool value, tRioStatusCode *status) = 0;

+   virtual bool readFPGA_LED(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tRevision_IfaceConstants;

+

+   virtual unsigned int readRevision(tRioStatusCode *status) = 0;

+

+

+

+

+private:

+   tGlobal(const tGlobal&);

+   void operator=(const tGlobal&);

+};

+

+}

+}

+

+#endif // __nFRC_2012_1_6_4_Global_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tInterrupt.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tInterrupt.h
new file mode 100644
index 0000000..40186e5
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tInterrupt.h
@@ -0,0 +1,93 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2012_1_6_4_Interrupt_h__

+#define __nFRC_2012_1_6_4_Interrupt_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2012_1_6_4

+{

+

+class tInterrupt

+{

+public:

+   tInterrupt(){}

+   virtual ~tInterrupt(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tInterrupt* create(unsigned char sys_index, tRioStatusCode *status);

+   virtual unsigned char getSystemIndex() = 0;

+

+

+   typedef enum

+   {

+      kNumSystems = 8,

+   } tIfaceConstants;

+

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned Source_Channel : 4;

+         unsigned Source_Module : 1;

+         unsigned Source_AnalogTrigger : 1;

+         unsigned RisingEdge : 1;

+         unsigned FallingEdge : 1;

+         unsigned WaitForAck : 1;

+#else

+         unsigned WaitForAck : 1;

+         unsigned FallingEdge : 1;

+         unsigned RisingEdge : 1;

+         unsigned Source_AnalogTrigger : 1;

+         unsigned Source_Module : 1;

+         unsigned Source_Channel : 4;

+#endif

+      };

+      struct{

+         unsigned value : 9;

+      };

+   } tConfig;

+

+

+   typedef enum

+   {

+   } tTimeStamp_IfaceConstants;

+

+   virtual unsigned int readTimeStamp(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tConfig_IfaceConstants;

+

+   virtual void writeConfig(tConfig value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Source_Channel(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Source_Module(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_Source_AnalogTrigger(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_RisingEdge(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_FallingEdge(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_WaitForAck(bool value, tRioStatusCode *status) = 0;

+   virtual tConfig readConfig(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_Source_Channel(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_Source_Module(tRioStatusCode *status) = 0;

+   virtual bool readConfig_Source_AnalogTrigger(tRioStatusCode *status) = 0;

+   virtual bool readConfig_RisingEdge(tRioStatusCode *status) = 0;

+   virtual bool readConfig_FallingEdge(tRioStatusCode *status) = 0;

+   virtual bool readConfig_WaitForAck(tRioStatusCode *status) = 0;

+

+

+

+

+

+private:

+   tInterrupt(const tInterrupt&);

+   void operator=(const tInterrupt&);

+};

+

+}

+}

+

+#endif // __nFRC_2012_1_6_4_Interrupt_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tSPI.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tSPI.h
new file mode 100644
index 0000000..45c208c
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tSPI.h
@@ -0,0 +1,228 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2012_1_6_4_SPI_h__

+#define __nFRC_2012_1_6_4_SPI_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2012_1_6_4

+{

+

+class tSPI

+{

+public:

+   tSPI(){}

+   virtual ~tSPI(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tSPI* create(tRioStatusCode *status);

+

+   typedef enum

+   {

+      kNumSystems = 1,

+   } tIfaceConstants;

+

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned ReceivedDataOverflow : 1;

+         unsigned Idle : 1;

+#else

+         unsigned Idle : 1;

+         unsigned ReceivedDataOverflow : 1;

+#endif

+      };

+      struct{

+         unsigned value : 2;

+      };

+   } tStatus;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned BusBitWidth : 8;

+         unsigned ClockHalfPeriodDelay : 8;

+         unsigned MSBfirst : 1;

+         unsigned DataOnFalling : 1;

+         unsigned LatchFirst : 1;

+         unsigned LatchLast : 1;

+         unsigned FramePolarity : 1;

+         unsigned WriteOnly : 1;

+         unsigned ClockPolarity : 1;

+#else

+         unsigned ClockPolarity : 1;

+         unsigned WriteOnly : 1;

+         unsigned FramePolarity : 1;

+         unsigned LatchLast : 1;

+         unsigned LatchFirst : 1;

+         unsigned DataOnFalling : 1;

+         unsigned MSBfirst : 1;

+         unsigned ClockHalfPeriodDelay : 8;

+         unsigned BusBitWidth : 8;

+#endif

+      };

+      struct{

+         unsigned value : 23;

+      };

+   } tConfig;

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned SCLK_Channel : 4;

+         unsigned SCLK_Module : 1;

+         unsigned MOSI_Channel : 4;

+         unsigned MOSI_Module : 1;

+         unsigned MISO_Channel : 4;

+         unsigned MISO_Module : 1;

+         unsigned SS_Channel : 4;

+         unsigned SS_Module : 1;

+#else

+         unsigned SS_Module : 1;

+         unsigned SS_Channel : 4;

+         unsigned MISO_Module : 1;

+         unsigned MISO_Channel : 4;

+         unsigned MOSI_Module : 1;

+         unsigned MOSI_Channel : 4;

+         unsigned SCLK_Module : 1;

+         unsigned SCLK_Channel : 4;

+#endif

+      };

+      struct{

+         unsigned value : 20;

+      };

+   } tChannels;

+

+

+

+   typedef enum

+   {

+   } tStatus_IfaceConstants;

+

+   virtual tStatus readStatus(tRioStatusCode *status) = 0;

+   virtual bool readStatus_ReceivedDataOverflow(tRioStatusCode *status) = 0;

+   virtual bool readStatus_Idle(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tReceivedData_IfaceConstants;

+

+   virtual unsigned int readReceivedData(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tDataToLoad_IfaceConstants;

+

+   virtual void writeDataToLoad(unsigned int value, tRioStatusCode *status) = 0;

+   virtual unsigned int readDataToLoad(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tConfig_IfaceConstants;

+

+   virtual void writeConfig(tConfig value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_BusBitWidth(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_ClockHalfPeriodDelay(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_MSBfirst(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_DataOnFalling(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_LatchFirst(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_LatchLast(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_FramePolarity(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_WriteOnly(bool value, tRioStatusCode *status) = 0;

+   virtual void writeConfig_ClockPolarity(bool value, tRioStatusCode *status) = 0;

+   virtual tConfig readConfig(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_BusBitWidth(tRioStatusCode *status) = 0;

+   virtual unsigned char readConfig_ClockHalfPeriodDelay(tRioStatusCode *status) = 0;

+   virtual bool readConfig_MSBfirst(tRioStatusCode *status) = 0;

+   virtual bool readConfig_DataOnFalling(tRioStatusCode *status) = 0;

+   virtual bool readConfig_LatchFirst(tRioStatusCode *status) = 0;

+   virtual bool readConfig_LatchLast(tRioStatusCode *status) = 0;

+   virtual bool readConfig_FramePolarity(tRioStatusCode *status) = 0;

+   virtual bool readConfig_WriteOnly(tRioStatusCode *status) = 0;

+   virtual bool readConfig_ClockPolarity(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tClearReceivedData_IfaceConstants;

+

+   virtual void strobeClearReceivedData(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tReceivedElements_IfaceConstants;

+

+   virtual unsigned short readReceivedElements(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tLoad_IfaceConstants;

+

+   virtual void strobeLoad(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tReset_IfaceConstants;

+

+   virtual void strobeReset(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tChannels_IfaceConstants;

+

+   virtual void writeChannels(tChannels value, tRioStatusCode *status) = 0;

+   virtual void writeChannels_SCLK_Channel(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeChannels_SCLK_Module(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeChannels_MOSI_Channel(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeChannels_MOSI_Module(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeChannels_MISO_Channel(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeChannels_MISO_Module(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeChannels_SS_Channel(unsigned char value, tRioStatusCode *status) = 0;

+   virtual void writeChannels_SS_Module(unsigned char value, tRioStatusCode *status) = 0;

+   virtual tChannels readChannels(tRioStatusCode *status) = 0;

+   virtual unsigned char readChannels_SCLK_Channel(tRioStatusCode *status) = 0;

+   virtual unsigned char readChannels_SCLK_Module(tRioStatusCode *status) = 0;

+   virtual unsigned char readChannels_MOSI_Channel(tRioStatusCode *status) = 0;

+   virtual unsigned char readChannels_MOSI_Module(tRioStatusCode *status) = 0;

+   virtual unsigned char readChannels_MISO_Channel(tRioStatusCode *status) = 0;

+   virtual unsigned char readChannels_MISO_Module(tRioStatusCode *status) = 0;

+   virtual unsigned char readChannels_SS_Channel(tRioStatusCode *status) = 0;

+   virtual unsigned char readChannels_SS_Module(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tAvailableToLoad_IfaceConstants;

+

+   virtual unsigned short readAvailableToLoad(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tReadReceivedData_IfaceConstants;

+

+   virtual void strobeReadReceivedData(tRioStatusCode *status) = 0;

+

+

+

+

+private:

+   tSPI(const tSPI&);

+   void operator=(const tSPI&);

+};

+

+}

+}

+

+#endif // __nFRC_2012_1_6_4_SPI_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tSolenoid.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tSolenoid.h
new file mode 100644
index 0000000..8627eea
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tSolenoid.h
@@ -0,0 +1,50 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2012_1_6_4_Solenoid_h__

+#define __nFRC_2012_1_6_4_Solenoid_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2012_1_6_4

+{

+

+class tSolenoid

+{

+public:

+   tSolenoid(){}

+   virtual ~tSolenoid(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tSolenoid* create(tRioStatusCode *status);

+

+   typedef enum

+   {

+      kNumSystems = 1,

+   } tIfaceConstants;

+

+

+

+

+   typedef enum

+   {

+      kNumDO7_0Elements = 2,

+   } tDO7_0_IfaceConstants;

+

+   virtual void writeDO7_0(unsigned char bitfield_index, unsigned char value, tRioStatusCode *status) = 0;

+   virtual unsigned char readDO7_0(unsigned char bitfield_index, tRioStatusCode *status) = 0;

+

+

+

+

+private:

+   tSolenoid(const tSolenoid&);

+   void operator=(const tSolenoid&);

+};

+

+}

+}

+

+#endif // __nFRC_2012_1_6_4_Solenoid_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tSysWatchdog.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tSysWatchdog.h
new file mode 100644
index 0000000..2ef01ff
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tSysWatchdog.h
@@ -0,0 +1,71 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2012_1_6_4_SysWatchdog_h__

+#define __nFRC_2012_1_6_4_SysWatchdog_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2012_1_6_4

+{

+

+class tSysWatchdog

+{

+public:

+   tSysWatchdog(){}

+   virtual ~tSysWatchdog(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tSysWatchdog* create(tRioStatusCode *status);

+

+   typedef enum

+   {

+      kNumSystems = 1,

+   } tIfaceConstants;

+

+

+

+

+   typedef enum

+   {

+   } tCommand_IfaceConstants;

+

+   virtual void writeCommand(unsigned short value, tRioStatusCode *status) = 0;

+   virtual unsigned short readCommand(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tChallenge_IfaceConstants;

+

+   virtual unsigned char readChallenge(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tActive_IfaceConstants;

+

+   virtual void writeActive(bool value, tRioStatusCode *status) = 0;

+   virtual bool readActive(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tTimer_IfaceConstants;

+

+   virtual unsigned int readTimer(tRioStatusCode *status) = 0;

+

+

+

+

+private:

+   tSysWatchdog(const tSysWatchdog&);

+   void operator=(const tSysWatchdog&);

+};

+

+}

+}

+

+#endif // __nFRC_2012_1_6_4_SysWatchdog_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tWatchdog.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tWatchdog.h
new file mode 100644
index 0000000..a589eda
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/nRuntimeFPGANamespace/tWatchdog.h
@@ -0,0 +1,108 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+// Do Not Edit... this file is generated!

+

+#ifndef __nFRC_2012_1_6_4_Watchdog_h__

+#define __nFRC_2012_1_6_4_Watchdog_h__

+

+#include "tSystemInterface.h"

+

+namespace nFPGA

+{

+namespace nFRC_2012_1_6_4

+{

+

+class tWatchdog

+{

+public:

+   tWatchdog(){}

+   virtual ~tWatchdog(){}

+

+   virtual tSystemInterface* getSystemInterface() = 0;

+   static tWatchdog* create(tRioStatusCode *status);

+

+   typedef enum

+   {

+      kNumSystems = 1,

+   } tIfaceConstants;

+

+   typedef

+   union{

+      struct{

+#ifdef __vxworks

+         unsigned SystemActive : 1;

+         unsigned Alive : 1;

+         unsigned SysDisableCount : 15;

+         unsigned DisableCount : 15;

+#else

+         unsigned DisableCount : 15;

+         unsigned SysDisableCount : 15;

+         unsigned Alive : 1;

+         unsigned SystemActive : 1;

+#endif

+      };

+      struct{

+         unsigned value : 32;

+      };

+   } tStatus;

+

+

+

+   typedef enum

+   {

+   } tStatus_IfaceConstants;

+

+   virtual tStatus readStatus(tRioStatusCode *status) = 0;

+   virtual bool readStatus_SystemActive(tRioStatusCode *status) = 0;

+   virtual bool readStatus_Alive(tRioStatusCode *status) = 0;

+   virtual unsigned short readStatus_SysDisableCount(tRioStatusCode *status) = 0;

+   virtual unsigned short readStatus_DisableCount(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tKill_IfaceConstants;

+

+   virtual void strobeKill(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tFeed_IfaceConstants;

+

+   virtual void strobeFeed(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tTimer_IfaceConstants;

+

+   virtual unsigned int readTimer(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tExpiration_IfaceConstants;

+

+   virtual void writeExpiration(unsigned int value, tRioStatusCode *status) = 0;

+   virtual unsigned int readExpiration(tRioStatusCode *status) = 0;

+

+

+   typedef enum

+   {

+   } tImmortal_IfaceConstants;

+

+   virtual void writeImmortal(bool value, tRioStatusCode *status) = 0;

+   virtual bool readImmortal(tRioStatusCode *status) = 0;

+

+

+

+

+private:

+   tWatchdog(const tWatchdog&);

+   void operator=(const tWatchdog&);

+};

+

+}

+}

+

+#endif // __nFRC_2012_1_6_4_Watchdog_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/printFpgaVersion.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/printFpgaVersion.h
new file mode 100644
index 0000000..788f1df
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/printFpgaVersion.h
@@ -0,0 +1,42 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+

+#ifndef __printFPGAVersion_h__

+#define __printFPGAVersion_h__

+

+namespace nFPGA

+{

+

+template<typename ttGlobal>

+inline void printFPGAVersion(ttGlobal &global)

+{

+   tRioStatusCode cleanStatus=0;

+   uint32_t hardwareGuid[4];

+   tSystemInterface &system = *global.getSystemInterface();

+   system.getHardwareFpgaSignature(hardwareGuid, &cleanStatus);

+   const uint32_t *softwareGuid = system.getExpectedFPGASignature();

+   printf("FPGA Hardware GUID: 0x");

+   for(int i=0; i<4; i++)

+   {

+      printf("%08X", hardwareGuid[i]);

+   }

+   printf("\n");

+   printf("FPGA Software GUID: 0x");

+   for(int i=0; i<4; i++)

+   {

+      printf("%08X", softwareGuid[i]);

+   }

+   printf("\n");

+   uint16_t fpgaHardwareVersion = global.readVersion(&cleanStatus);

+   uint16_t fpgaSoftwareVersion = system.getExpectedFPGAVersion();

+   printf("FPGA Hardware Version: %X\n", fpgaHardwareVersion);

+   printf("FPGA Software Version: %X\n", fpgaSoftwareVersion);

+   uint32_t fpgaHardwareRevision = global.readRevision(&cleanStatus);

+   uint32_t fpgaSoftwareRevision = system.getExpectedFPGARevision();

+   printf("FPGA Hardware Revision: %X.%X.%X\n", (fpgaHardwareRevision >> 20) & 0xFFF, (fpgaHardwareRevision >> 12) & 0xFF, fpgaHardwareRevision & 0xFFF);

+   printf("FPGA Software Revision: %X.%X.%X\n", (fpgaSoftwareRevision >> 20) & 0xFFF, (fpgaSoftwareRevision >> 12) & 0xFF, fpgaSoftwareRevision & 0xFFF);

+}

+

+}

+

+#endif // __printFPGAVersion_h__

+

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/tDMAChannelDescriptor.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/tDMAChannelDescriptor.h
new file mode 100644
index 0000000..8fa5935
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/tDMAChannelDescriptor.h
@@ -0,0 +1,17 @@
+// Describes the information needed to configure a DMA channel.

+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+

+#include <stdint.h>

+

+#ifndef __tDMAChannelDescriptor_h__

+#define __tDMAChannelDescriptor_h__

+

+struct tDMAChannelDescriptor

+{

+   uint32_t channel;

+   uint32_t baseAddress;

+   uint32_t depth;

+   bool targetToHost;

+};

+

+#endif // __tDMAChannelDescriptor_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/tDMAManager.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/tDMAManager.h
new file mode 100644
index 0000000..cb95203
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/tDMAManager.h
@@ -0,0 +1,41 @@
+// Class for handling DMA transfers.

+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+

+#ifndef __tDMAManager_h__

+#define __tDMAManager_h__

+

+#include "tSystem.h"

+#include <stdint.h>

+

+namespace nFPGA

+{

+class tDMAManager : public tSystem

+{

+public:

+   tDMAManager(uint32_t dmaChannel, uint32_t hostBufferSize, tRioStatusCode *status);

+   ~tDMAManager();

+   void start(tRioStatusCode *status);

+   void stop(tRioStatusCode *status);

+   bool isStarted() {return _started;}

+   void read(

+      uint32_t*      buf,

+      size_t         num,

+      uint32_t       timeout,

+      size_t*        remaining,

+      tRioStatusCode *status);

+   void write(

+      uint32_t*      buf,

+      size_t         num,

+      uint32_t       timeout,

+      size_t*        remaining,

+      tRioStatusCode *status);

+private:

+   bool _started;

+   uint32_t _dmaChannel;

+   uint32_t _hostBufferSize;

+

+};

+

+}

+

+#endif // __tDMAManager_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/tInterruptManager.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/tInterruptManager.h
new file mode 100644
index 0000000..cb6783d
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/tInterruptManager.h
@@ -0,0 +1,61 @@
+// Class for handling interrupts.

+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+

+#ifndef __tInterruptManager_h__

+#define __tInterruptManager_h__

+

+#include "tSystem.h"

+

+namespace ni

+{

+   namespace dsc

+   {

+      namespace osdep

+      {

+         class CriticalSection;

+      }

+   }

+}

+

+namespace nFPGA

+{

+

+typedef void (*tInterruptHandler)(uint32_t interruptAssertedMask, void *param);

+

+class tInterruptManager : public tSystem

+{

+public:

+   tInterruptManager(uint32_t interruptMask, bool watcher, tRioStatusCode *status);

+   ~tInterruptManager();

+   void registerHandler(tInterruptHandler handler, void *param, tRioStatusCode *status);

+   uint32_t watch(int32_t timeoutInMs, bool ignorePrevious, tRioStatusCode *status);

+   void enable(tRioStatusCode *status);

+   void disable(tRioStatusCode *status);

+   bool isEnabled(tRioStatusCode *status);

+private:

+   class tInterruptThread;

+   friend class tInterruptThread;

+   void handler();

+   static int handlerWrapper(tInterruptManager *pInterrupt);

+

+   void acknowledge(tRioStatusCode *status);

+   void reserve(tRioStatusCode *status);

+   void unreserve(tRioStatusCode *status);

+   tInterruptHandler _handler;

+   uint32_t _interruptMask;

+   tInterruptThread *_thread;

+   NiFpga_IrqContext _rioContext;

+   bool _watcher;

+   bool _enabled;

+   void *_userParam;

+

+   // maintain the interrupts that are already dealt with.

+   static uint32_t _globalInterruptMask;

+   static ni::dsc::osdep::CriticalSection *_globalInterruptMaskSemaphore;

+};

+

+}

+

+

+#endif // __tInterruptManager_h__

+

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/tSystem.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/tSystem.h
new file mode 100644
index 0000000..b059e51
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/tSystem.h
@@ -0,0 +1,48 @@
+// Base class for generated chip objects

+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+

+#ifndef __tSystem_h__

+#define __tSystem_h__

+

+#include "fpgainterfacecapi/NiFpga.h"

+typedef NiFpga_Status tRioStatusCode;

+

+#define FRC_FPGA_PRELOAD_BITFILE

+

+typedef uint32_t NiFpga_Session;

+

+namespace nFPGA

+{

+

+class tSystem

+{

+public:

+   tSystem(tRioStatusCode *status);

+   ~tSystem();

+   void getFpgaGuid(uint32_t *guid_ptr, tRioStatusCode *status);

+   void reset(tRioStatusCode *status);

+

+protected:

+   static NiFpga_Session _DeviceHandle;

+

+#ifdef FRC_FPGA_PRELOAD_BITFILE

+   void NiFpga_SharedOpen_common(const char*     bitfile);

+   NiFpga_Status NiFpga_SharedOpen(const char*     bitfile,

+                            const char*     signature,

+                            const char*     resource,

+                            uint32_t        attribute,

+                            NiFpga_Session* session);

+   NiFpga_Status NiFpgaLv_SharedOpen(const char* const     bitfile,

+                            const char* const     apiSignature,

+                            const char* const     resource,

+                            const uint32_t        attribute,

+                            NiFpga_Session* const session);

+private:

+    static char *_FileName;

+    static char *_Bitfile;

+#endif

+};

+

+}

+

+#endif // __tSystem_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/tSystemInterface.h b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/tSystemInterface.h
new file mode 100644
index 0000000..8594187
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/FRC_FPGA_ChipObject/tSystemInterface.h
@@ -0,0 +1,27 @@
+// Copyright (c) National Instruments 2008.  All Rights Reserved.

+

+#ifndef __tSystemInterface_h__

+#define __tSystemInterface_h__

+

+namespace nFPGA

+{

+

+class tSystemInterface

+{

+public:

+   tSystemInterface(){}

+   virtual ~tSystemInterface(){}

+

+   virtual const uint16_t getExpectedFPGAVersion()=0;

+   virtual const uint32_t getExpectedFPGARevision()=0;

+   virtual const uint32_t * const getExpectedFPGASignature()=0;

+   virtual void getHardwareFpgaSignature(uint32_t *guid_ptr, tRioStatusCode *status)=0;

+   virtual uint32_t getLVHandle(tRioStatusCode *status)=0;

+   virtual uint32_t getHandle()=0;

+   virtual void reset(tRioStatusCode *status)=0;

+};

+

+}

+

+#endif // __tSystemInterface_h__

+

diff --git a/aos/externals/allwpilib/hal/lib/Athena/HAL.cpp b/aos/externals/allwpilib/hal/lib/Athena/HAL.cpp
new file mode 100644
index 0000000..7a9f0d5
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/HAL.cpp
@@ -0,0 +1,373 @@
+#include "HAL/HAL.hpp"
+
+#include "Port.h"
+#include "HAL/Errors.hpp"
+#include "ctre/ctre.h"
+#include "visa/visa.h"
+#include "ChipObject.h"
+#include "NetworkCommunication/FRCComm.h"
+#include "NetworkCommunication/UsageReporting.h"
+#include "NetworkCommunication/LoadOut.h"
+#include "NetworkCommunication/CANSessionMux.h"
+#include <fstream>
+#include <iostream>
+#include <unistd.h>
+#include <sys/prctl.h>
+#include <signal.h> // linux for kill
+const uint32_t solenoid_kNumDO7_0Elements = 8;
+const uint32_t dio_kNumSystems = tDIO::kNumSystems;
+const uint32_t interrupt_kNumSystems = tInterrupt::kNumSystems;
+const uint32_t kSystemClockTicksPerMicrosecond = 40;
+
+static tGlobal *global;
+static tSysWatchdog *watchdog;
+
+void* getPort(uint8_t pin)
+{
+	Port* port = new Port();
+	port->pin = pin;
+	port->module = 1;
+	return port;
+}
+
+/**
+ * @deprecated Uses module numbers
+ */
+void* getPortWithModule(uint8_t module, uint8_t pin)
+{
+	Port* port = new Port();
+	port->pin = pin;
+	port->module = module;
+	return port;
+}
+
+const char* getHALErrorMessage(int32_t code)
+{
+	switch(code) {
+		case 0:
+			return "";
+		case CTR_RxTimeout:
+			return CTR_RxTimeout_MESSAGE;
+		case CTR_TxTimeout:
+			return CTR_TxTimeout_MESSAGE;
+		case CTR_InvalidParamValue:
+			return CTR_InvalidParamValue_MESSAGE;
+		case CTR_UnexpectedArbId:
+			return CTR_UnexpectedArbId_MESSAGE;
+		case CTR_TxFailed:
+			return CTR_TxFailed_MESSAGE;
+		case CTR_SigNotUpdated:
+			return CTR_SigNotUpdated_MESSAGE;
+		case NiFpga_Status_FifoTimeout:
+			return NiFpga_Status_FifoTimeout_MESSAGE;
+		case NiFpga_Status_TransferAborted:
+			return NiFpga_Status_TransferAborted_MESSAGE;
+		case NiFpga_Status_MemoryFull: 
+			return NiFpga_Status_MemoryFull_MESSAGE;
+		case NiFpga_Status_SoftwareFault:
+			return NiFpga_Status_SoftwareFault_MESSAGE;
+		case NiFpga_Status_InvalidParameter:
+			return NiFpga_Status_InvalidParameter_MESSAGE;
+		case NiFpga_Status_ResourceNotFound:
+			return NiFpga_Status_ResourceNotFound_MESSAGE; 
+		case NiFpga_Status_ResourceNotInitialized:
+			return NiFpga_Status_ResourceNotInitialized_MESSAGE; 
+		case NiFpga_Status_HardwareFault:
+			return NiFpga_Status_HardwareFault_MESSAGE;
+		case NiFpga_Status_IrqTimeout:
+			return NiFpga_Status_IrqTimeout_MESSAGE;
+		case NiFpga_Status_VersionMismatch:
+			return NiFpga_Status_VersionMismatch_MESSAGE;
+		case SAMPLE_RATE_TOO_HIGH:
+			return SAMPLE_RATE_TOO_HIGH_MESSAGE;
+		case VOLTAGE_OUT_OF_RANGE:
+			return VOLTAGE_OUT_OF_RANGE_MESSAGE;
+		case LOOP_TIMING_ERROR:
+			return LOOP_TIMING_ERROR_MESSAGE;
+		case SPI_WRITE_NO_MOSI:
+			return SPI_WRITE_NO_MOSI_MESSAGE;
+		case SPI_READ_NO_MISO:
+			return SPI_READ_NO_MISO_MESSAGE;
+		case SPI_READ_NO_DATA:
+			return SPI_READ_NO_DATA_MESSAGE;
+		case INCOMPATIBLE_STATE:
+			return INCOMPATIBLE_STATE_MESSAGE;
+		case NO_AVAILABLE_RESOURCES:
+			return NO_AVAILABLE_RESOURCES_MESSAGE;
+		case NULL_PARAMETER:
+			return NULL_PARAMETER_MESSAGE;
+		case ANALOG_TRIGGER_LIMIT_ORDER_ERROR:
+			return ANALOG_TRIGGER_LIMIT_ORDER_ERROR_MESSAGE;
+		case ANALOG_TRIGGER_PULSE_OUTPUT_ERROR:
+			return ANALOG_TRIGGER_PULSE_OUTPUT_ERROR_MESSAGE;
+		case PARAMETER_OUT_OF_RANGE:
+			return PARAMETER_OUT_OF_RANGE_MESSAGE;
+		case ERR_CANSessionMux_InvalidBuffer:
+			return ERR_CANSessionMux_InvalidBuffer_MESSAGE;
+		case ERR_CANSessionMux_MessageNotFound:
+			return ERR_CANSessionMux_MessageNotFound_MESSAGE;
+		case WARN_CANSessionMux_NoToken:
+			return WARN_CANSessionMux_NoToken_MESSAGE;
+		case ERR_CANSessionMux_NotAllowed:
+			return ERR_CANSessionMux_NotAllowed_MESSAGE;
+		case ERR_CANSessionMux_NotInitialized:
+			return ERR_CANSessionMux_NotInitialized_MESSAGE;
+		case VI_ERROR_SYSTEM_ERROR:
+			return VI_ERROR_SYSTEM_ERROR_MESSAGE;
+		case VI_ERROR_INV_OBJECT:
+			return VI_ERROR_INV_OBJECT_MESSAGE;
+		case VI_ERROR_RSRC_LOCKED:
+			return VI_ERROR_RSRC_LOCKED_MESSAGE;
+		case VI_ERROR_RSRC_NFOUND:
+			return VI_ERROR_RSRC_NFOUND_MESSAGE;
+		case VI_ERROR_INV_RSRC_NAME:
+			return VI_ERROR_INV_RSRC_NAME_MESSAGE;
+		case VI_ERROR_QUEUE_OVERFLOW:
+			return VI_ERROR_QUEUE_OVERFLOW_MESSAGE;
+		case VI_ERROR_IO:
+			return VI_ERROR_IO_MESSAGE;
+		case VI_ERROR_ASRL_PARITY:
+			return VI_ERROR_ASRL_PARITY_MESSAGE;
+		case VI_ERROR_ASRL_FRAMING:
+			return VI_ERROR_ASRL_FRAMING_MESSAGE;
+		case VI_ERROR_ASRL_OVERRUN:
+			return VI_ERROR_ASRL_OVERRUN_MESSAGE;
+		case VI_ERROR_RSRC_BUSY:
+			return VI_ERROR_RSRC_BUSY_MESSAGE;
+		case VI_ERROR_INV_PARAMETER:
+			return VI_ERROR_INV_PARAMETER_MESSAGE;
+		default:
+			return "Unknown error status";
+	}
+}
+
+/**
+ * Return the FPGA Version number.
+ * For now, expect this to be competition year.
+ * @return FPGA Version number.
+ */
+uint16_t getFPGAVersion(int32_t *status)
+{
+	return global->readVersion(status);
+}
+
+/**
+ * Return the FPGA Revision number.
+ * The format of the revision is 3 numbers.
+ * The 12 most significant bits are the Major Revision.
+ * the next 8 bits are the Minor Revision.
+ * The 12 least significant bits are the Build Number.
+ * @return FPGA Revision number.
+ */
+uint32_t getFPGARevision(int32_t *status)
+{
+	return global->readRevision(status);
+}
+
+/**
+ * Read the microsecond-resolution timer on the FPGA.
+ *
+ * @return The current time in microseconds according to the FPGA (since FPGA reset).
+ */
+uint32_t getFPGATime(int32_t *status)
+{
+	return global->readLocalTime(status);
+}
+
+/**
+ * Get the state of the "USER" button on the RoboRIO
+ * @return true if the button is currently pressed down
+ */
+bool getFPGAButton(int32_t *status)
+{
+	return global->readUserButton(status);
+}
+
+int HALSetErrorData(const char *errors, int errorsLength, int wait_ms)
+{
+	return setErrorData(errors, errorsLength, wait_ms);
+}
+
+int HALGetControlWord(HALControlWord *data)
+{
+	return FRC_NetworkCommunication_getControlWord((ControlWord_t*) data);
+}
+
+int HALGetAllianceStation(enum HALAllianceStationID *allianceStation)
+{
+	return FRC_NetworkCommunication_getAllianceStation((AllianceStationID_t*) allianceStation);
+}
+
+int HALGetJoystickAxes(uint8_t joystickNum, HALJoystickAxes *axes)
+{
+	return FRC_NetworkCommunication_getJoystickAxes(joystickNum, (JoystickAxes_t*) axes, kMaxJoystickAxes);
+}
+
+int HALGetJoystickPOVs(uint8_t joystickNum, HALJoystickPOVs *povs)
+{
+	return FRC_NetworkCommunication_getJoystickPOVs(joystickNum, (JoystickPOV_t*) povs, kMaxJoystickPOVs);
+}
+
+int HALGetJoystickButtons(uint8_t joystickNum, HALJoystickButtons *buttons)
+{
+	return FRC_NetworkCommunication_getJoystickButtons(joystickNum, &buttons->buttons, &buttons->count);
+}
+
+int HALGetJoystickDescriptor(uint8_t joystickNum, HALJoystickDescriptor *desc)
+{
+	return FRC_NetworkCommunication_getJoystickDesc(joystickNum, &desc->isXbox, &desc->type, (char *)(&desc->name), 
+		&desc->axisCount, &desc->axisTypes, &desc->buttonCount, &desc->povCount);
+}
+
+int HALSetJoystickOutputs(uint8_t joystickNum, uint32_t outputs, uint16_t leftRumble, uint16_t rightRumble)
+{
+	return FRC_NetworkCommunication_setJoystickOutputs(joystickNum, outputs, leftRumble, rightRumble);
+}
+
+int HALGetMatchTime(float *matchTime)
+{
+	return FRC_NetworkCommunication_getMatchTime(matchTime);
+}
+
+void HALSetNewDataSem(MULTIWAIT_ID sem)
+{
+	setNewDataSem(sem);
+}
+
+bool HALGetSystemActive(int32_t *status)
+{
+	return watchdog->readStatus_SystemActive(status);
+}
+	
+bool HALGetBrownedOut(int32_t *status)
+{
+	return !(watchdog->readStatus_PowerAlive(status));
+}
+
+/**
+ * Call this to start up HAL. This is required for robot programs.
+ */
+int HALInitialize(int mode)
+{
+    setlinebuf(stdin);
+    setlinebuf(stdout);
+
+    prctl(PR_SET_PDEATHSIG, SIGTERM);
+
+	FRC_NetworkCommunication_Reserve(nullptr);
+	// image 4; Fixes errors caused by multiple processes. Talk to NI about this
+	nFPGA::nRoboRIO_FPGANamespace::g_currentTargetClass =
+			nLoadOut::kTargetClass_RoboRIO;
+
+	int32_t status;
+	global = tGlobal::create(&status);
+	watchdog = tSysWatchdog::create(&status);
+
+	// Kill any previous robot programs
+	std::fstream fs;
+	// By making this both in/out, it won't give us an error if it doesnt exist
+	fs.open("/var/lock/frc.pid", std::fstream::in | std::fstream::out);
+	if (fs.bad())
+		return 0;
+
+	pid_t pid = 0;
+	if (!fs.eof() && !fs.fail())
+	{
+		fs >> pid;
+		//see if the pid is around, but we don't want to mess with init id=1, or ourselves
+		if (pid >= 2 && kill(pid, 0) == 0 && pid != getpid())
+		{
+			std::cout << "Killing previously running FRC program..."
+					<< std::endl;
+			kill(pid, SIGTERM); // try to kill it
+			delayMillis(100);
+			if (kill(pid, 0) == 0)
+			{
+				// still not successfull
+				if (mode == 0)
+				{
+					std::cout << "FRC pid " << pid
+							<< " did not die within 110ms. Aborting"
+							<< std::endl;
+					return 0; // just fail
+				}
+				else if (mode == 1) // kill -9 it
+					kill(pid, SIGKILL);
+				else
+				{
+					std::cout << "WARNING: FRC pid " << pid
+							<< " did not die within 110ms." << std::endl;
+				}
+			}
+
+		}
+	}
+	fs.close();
+	// we will re-open it write only to truncate the file
+	fs.open("/var/lock/frc.pid", std::fstream::out | std::fstream::trunc);
+	fs.seekp(0);
+	pid = getpid();
+	fs << pid << std::endl;
+	fs.close();
+	return 1;
+}
+
+void HALNetworkCommunicationObserveUserProgramStarting(void)
+{
+	FRC_NetworkCommunication_observeUserProgramStarting();
+}
+
+void HALNetworkCommunicationObserveUserProgramDisabled(void)
+{
+	FRC_NetworkCommunication_observeUserProgramDisabled();
+}
+
+void HALNetworkCommunicationObserveUserProgramAutonomous(void)
+{
+	FRC_NetworkCommunication_observeUserProgramAutonomous();
+}
+
+void HALNetworkCommunicationObserveUserProgramTeleop(void)
+{
+	FRC_NetworkCommunication_observeUserProgramTeleop();
+}
+
+void HALNetworkCommunicationObserveUserProgramTest(void)
+{
+	FRC_NetworkCommunication_observeUserProgramTest();
+}
+
+uint32_t HALReport(uint8_t resource, uint8_t instanceNumber, uint8_t context,
+		const char *feature)
+{
+	if(feature == NULL)
+	{
+		feature = "";
+	}
+
+	return FRC_NetworkCommunication_nUsageReporting_report(resource, instanceNumber, context, feature);
+}
+
+// TODO: HACKS
+void NumericArrayResize()
+{
+}
+void RTSetCleanupProc()
+{
+}
+void EDVR_CreateReference()
+{
+}
+void Occur()
+{
+}
+
+void imaqGetErrorText()
+{
+}
+void imaqGetLastError()
+{
+}
+void niTimestamp64()
+{
+}
diff --git a/aos/externals/allwpilib/hal/lib/Athena/Interrupts.cpp b/aos/externals/allwpilib/hal/lib/Athena/Interrupts.cpp
new file mode 100644
index 0000000..49bd2c9
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/Interrupts.cpp
@@ -0,0 +1,120 @@
+#include "HAL/Interrupts.hpp"
+#include "ChipObject.h"
+
+struct Interrupt // FIXME: why is this internal?
+{
+	tInterrupt *anInterrupt;
+	tInterruptManager *manager;
+};
+
+void* initializeInterrupts(uint32_t interruptIndex, bool watcher, int32_t *status)
+{
+	Interrupt* anInterrupt = new Interrupt();
+	// Expects the calling leaf class to allocate an interrupt index.
+	anInterrupt->anInterrupt = tInterrupt::create(interruptIndex, status);
+	anInterrupt->anInterrupt->writeConfig_WaitForAck(false, status);
+	anInterrupt->manager = new tInterruptManager(
+		(1 << interruptIndex) | (1 << (interruptIndex + 8)), watcher, status);
+	return anInterrupt;
+}
+
+void cleanInterrupts(void* interrupt_pointer, int32_t *status)
+{
+	Interrupt* anInterrupt = (Interrupt*)interrupt_pointer;
+	delete anInterrupt->anInterrupt;
+	delete anInterrupt->manager;
+	anInterrupt->anInterrupt = NULL;
+	anInterrupt->manager = NULL;
+}
+
+/**
+ * In synchronous mode, wait for the defined interrupt to occur.
+ * @param timeout Timeout in seconds
+ * @param ignorePrevious If true, ignore interrupts that happened before
+ * waitForInterrupt was called.
+ * @return The mask of interrupts that fired.
+ */
+uint32_t waitForInterrupt(void* interrupt_pointer, double timeout, bool ignorePrevious, int32_t *status)
+{
+	uint32_t result;
+	Interrupt* anInterrupt = (Interrupt*)interrupt_pointer;
+
+	result = anInterrupt->manager->watch((int32_t)(timeout * 1e3), ignorePrevious, status);
+
+	// Don't report a timeout as an error - the return code is enough to tell
+	// that a timeout happened.
+	if(*status == -NiFpga_Status_IrqTimeout) {
+		*status = NiFpga_Status_Success;
+	}
+
+	return result;
+}
+
+/**
+ * Enable interrupts to occur on this input.
+ * Interrupts are disabled when the RequestInterrupt call is made. This gives time to do the
+ * setup of the other options before starting to field interrupts.
+ */
+void enableInterrupts(void* interrupt_pointer, int32_t *status)
+{
+	Interrupt* anInterrupt = (Interrupt*)interrupt_pointer;
+	anInterrupt->manager->enable(status);
+}
+
+/**
+ * Disable Interrupts without without deallocating structures.
+ */
+void disableInterrupts(void* interrupt_pointer, int32_t *status)
+{
+	Interrupt* anInterrupt = (Interrupt*)interrupt_pointer;
+	anInterrupt->manager->disable(status);
+}
+
+/**
+ * Return the timestamp for the rising interrupt that occurred most recently.
+ * This is in the same time domain as GetClock().
+ * @return Timestamp in seconds since boot.
+ */
+double readRisingTimestamp(void* interrupt_pointer, int32_t *status)
+{
+	Interrupt* anInterrupt = (Interrupt*)interrupt_pointer;
+	uint32_t timestamp = anInterrupt->anInterrupt->readRisingTimeStamp(status);
+	return timestamp * 1e-6;
+}
+
+/**
+* Return the timestamp for the falling interrupt that occurred most recently.
+* This is in the same time domain as GetClock().
+* @return Timestamp in seconds since boot.
+*/
+double readFallingTimestamp(void* interrupt_pointer, int32_t *status)
+{
+	Interrupt* anInterrupt = (Interrupt*)interrupt_pointer;
+	uint32_t timestamp = anInterrupt->anInterrupt->readFallingTimeStamp(status);
+	return timestamp * 1e-6;
+}
+
+void requestInterrupts(void* interrupt_pointer, uint8_t routing_module, uint32_t routing_pin,
+		bool routing_analog_trigger, int32_t *status)
+{
+	Interrupt* anInterrupt = (Interrupt*)interrupt_pointer;
+	anInterrupt->anInterrupt->writeConfig_WaitForAck(false, status);
+	anInterrupt->anInterrupt->writeConfig_Source_AnalogTrigger(routing_analog_trigger, status);
+	anInterrupt->anInterrupt->writeConfig_Source_Channel(routing_pin, status);
+	anInterrupt->anInterrupt->writeConfig_Source_Module(routing_module, status);
+}
+
+void attachInterruptHandler(void* interrupt_pointer, InterruptHandlerFunction handler, void* param,
+		int32_t *status)
+{
+	Interrupt* anInterrupt = (Interrupt*)interrupt_pointer;
+	anInterrupt->manager->registerHandler(handler, param, status);
+}
+
+void setInterruptUpSourceEdge(void* interrupt_pointer, bool risingEdge, bool fallingEdge,
+		int32_t *status)
+{
+	Interrupt* anInterrupt = (Interrupt*)interrupt_pointer;
+	anInterrupt->anInterrupt->writeConfig_RisingEdge(risingEdge, status);
+	anInterrupt->anInterrupt->writeConfig_FallingEdge(fallingEdge, status);
+}
diff --git a/aos/externals/allwpilib/hal/lib/Athena/NetworkCommunication/AICalibration.h b/aos/externals/allwpilib/hal/lib/Athena/NetworkCommunication/AICalibration.h
new file mode 100644
index 0000000..b2f366c
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/NetworkCommunication/AICalibration.h
@@ -0,0 +1,19 @@
+

+#ifndef __AICalibration_h__

+#define __AICalibration_h__

+

+#include <stdint.h>

+

+#ifdef __cplusplus

+extern "C"

+{

+#endif

+

+	uint32_t FRC_NetworkCommunication_nAICalibration_getLSBWeight(const uint32_t aiSystemIndex, const uint32_t channel, int32_t *status);

+	int32_t FRC_NetworkCommunication_nAICalibration_getOffset(const uint32_t aiSystemIndex, const uint32_t channel, int32_t *status);

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif // __AICalibration_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/NetworkCommunication/CANInterfacePlugin.h b/aos/externals/allwpilib/hal/lib/Athena/NetworkCommunication/CANInterfacePlugin.h
new file mode 100644
index 0000000..77d992c
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/NetworkCommunication/CANInterfacePlugin.h
@@ -0,0 +1,82 @@
+// CANInterfacePlugin.h

+//

+//  Defines the API for building a CAN Interface Plugin to support

+//    PWM-cable-free CAN motor control on FRC robots.  This allows you

+//    to connect any CAN interface to the secure Jaguar CAN driver.

+//

+

+#ifndef __CANInterfacePlugin_h__

+#define __CANInterfacePlugin_h__

+

+#include <stdint.h>

+

+#define CAN_IS_FRAME_REMOTE 0x80000000

+#define CAN_IS_FRAME_11BIT  0x40000000

+#define CAN_29BIT_MESSAGE_ID_MASK 0x1FFFFFFF

+#define CAN_11BIT_MESSAGE_ID_MASK 0x000007FF

+

+class CANInterfacePlugin

+{

+public:

+	CANInterfacePlugin() {}

+	virtual ~CANInterfacePlugin() {}

+

+	/**

+	 * This entry-point of the CANInterfacePlugin is passed a message that the driver needs to send to

+	 * a device on the CAN bus.

+	 * 

+	 * This function may be called from multiple contexts and must therefore be reentrant.

+	 * 

+	 * @param messageID The 29-bit CAN message ID in the lsbs.  The msb can indicate a remote frame.

+	 * @param data A pointer to a buffer containing between 0 and 8 bytes to send with the message.  May be NULL if dataSize is 0.

+	 * @param dataSize The number of bytes to send with the message.

+	 * @return Return any error code.  On success return 0.

+	 */

+	virtual int32_t sendMessage(uint32_t messageID, const uint8_t *data, uint8_t dataSize) = 0;

+

+	/**

+	 * This entry-point of the CANInterfacePlugin is passed buffers which should be populated with

+	 * any received messages from devices on the CAN bus.

+	 * 

+	 * This function is always called by a single task in the Jaguar driver, so it need not be reentrant.

+	 * 

+	 * This function is expected to block for some period of time waiting for a message from the CAN bus.

+	 * It may timeout periodically (returning non-zero to indicate no message was populated) to allow for

+	 * shutdown and unloading of the plugin.

+	 * 

+	 * @param messageID A reference to be populated with a received 29-bit CAN message ID in the lsbs.

+	 * @param data A pointer to a buffer of 8 bytes to be populated with data received with the message.

+	 * @param dataSize A reference to be populated with the size of the data received (0 - 8 bytes).

+	 * @return This should return 0 if a message was populated, non-0 if no message was not populated.

+	 */

+	virtual int32_t receiveMessage(uint32_t &messageID, uint8_t *data, uint8_t &dataSize) = 0;

+

+#if defined(__linux)

+	/**

+	 * This entry-point of the CANInterfacePlugin returns status of the CAN bus.

+	 * 

+	 * This function may be called from multiple contexts and must therefore be reentrant.

+	 * 

+	 * This function will return detailed hardware status if available for diagnostics of the CAN interface.

+	 * 

+	 * @param busOffCount The number of times that sendMessage failed with a busOff error indicating that messages

+	 *  are not successfully transmitted on the bus.

+	 * @param txFullCount The number of times that sendMessage failed with a txFifoFull error indicating that messages

+	 *  are not successfully received by any CAN device.

+	 * @param receiveErrorCount The count of receive errors as reported by the CAN driver.

+	 * @param transmitErrorCount The count of transmit errors as reported by the CAN driver.

+	 * @return This should return 0 if all status was retrieved successfully or an error code if not.

+	 */

+	virtual int32_t getStatus(uint32_t &busOffCount, uint32_t &txFullCount, uint32_t &receiveErrorCount, uint32_t &transmitErrorCount) {return 0;}

+#endif

+};

+

+/**

+ * This function allows you to register a CANInterfacePlugin to provide access a CAN bus.

+ * 

+ * @param interface A pointer to an object that inherits from CANInterfacePlugin and implements

+ * the pure virtual interface.  If NULL, unregister the current plugin.

+ */

+void FRC_NetworkCommunication_CANSessionMux_registerInterface(CANInterfacePlugin* interface);

+

+#endif // __CANInterfacePlugin_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/NetworkCommunication/CANSessionMux.h b/aos/externals/allwpilib/hal/lib/Athena/NetworkCommunication/CANSessionMux.h
new file mode 100644
index 0000000..3f8a6f1
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/NetworkCommunication/CANSessionMux.h
@@ -0,0 +1,64 @@
+// CANSessionMux.h

+//

+//  Defines the API for building a CAN Interface Plugin to support

+//    PWM-cable-free CAN motor control on FRC robots.  This allows you

+//    to connect any CAN interface to the secure Jaguar CAN driver.

+//

+

+#ifndef __CANSessionMux_h__

+#define __CANSessionMux_h__

+

+#if defined(__vxworks)

+#include <vxWorks.h>

+#else

+#include <stdint.h>

+#endif

+

+#define CAN_SEND_PERIOD_NO_REPEAT 0

+#define CAN_SEND_PERIOD_STOP_REPEATING -1

+

+/* Flags in the upper bits of the messageID */

+#define CAN_IS_FRAME_REMOTE 0x80000000

+#define CAN_IS_FRAME_11BIT  0x40000000

+

+#define ERR_CANSessionMux_InvalidBuffer   -44086

+#define ERR_CANSessionMux_MessageNotFound -44087

+#define WARN_CANSessionMux_NoToken         44087

+#define ERR_CANSessionMux_NotAllowed      -44088

+#define ERR_CANSessionMux_NotInitialized  -44089

+#define ERR_CANSessionMux_SessionOverrun   44050

+

+struct tCANStreamMessage{

+	uint32_t messageID;

+	uint32_t timeStamp;

+	uint8_t data[8];

+	uint8_t dataSize;

+};

+

+namespace nCANSessionMux

+{

+	void sendMessage_wrapper(uint32_t messageID, const uint8_t *data, uint8_t dataSize, int32_t periodMs, int32_t *status);

+	void receiveMessage_wrapper(uint32_t *messageID, uint32_t messageIDMask, uint8_t *data, uint8_t *dataSize, uint32_t *timeStamp, int32_t *status);

+	void openStreamSession(uint32_t *sessionHandle, uint32_t messageID, uint32_t messageIDMask, uint32_t maxMessages, int32_t *status);

+	void closeStreamSession(uint32_t sessionHandle);

+	void readStreamSession(uint32_t sessionHandle, struct tCANStreamMessage *messages, uint32_t messagesToRead, uint32_t *messagesRead, int32_t *status);

+	void getCANStatus(float *percentBusUtilization, uint32_t *busOffCount, uint32_t *txFullCount, uint32_t *receiveErrorCount, uint32_t *transmitErrorCount, int32_t *status);

+}

+

+#ifdef __cplusplus

+extern "C"

+{

+#endif

+

+	void FRC_NetworkCommunication_CANSessionMux_sendMessage(uint32_t messageID, const uint8_t *data, uint8_t dataSize, int32_t periodMs, int32_t *status);

+	void FRC_NetworkCommunication_CANSessionMux_receiveMessage(uint32_t *messageID, uint32_t messageIDMask, uint8_t *data, uint8_t *dataSize, uint32_t *timeStamp, int32_t *status);

+	void FRC_NetworkCommunication_CANSessionMux_openStreamSession(uint32_t *sessionHandle, uint32_t messageID, uint32_t messageIDMask, uint32_t maxMessages, int32_t *status);

+	void FRC_NetworkCommunication_CANSessionMux_closeStreamSession(uint32_t sessionHandle);

+	void FRC_NetworkCommunication_CANSessionMux_readStreamSession(uint32_t sessionHandle, struct tCANStreamMessage *messages, uint32_t messagesToRead, uint32_t *messagesRead, int32_t *status);

+	void FRC_NetworkCommunication_CANSessionMux_getCANStatus(float *percentBusUtilization, uint32_t *busOffCount, uint32_t *txFullCount, uint32_t *receiveErrorCount, uint32_t *transmitErrorCount, int32_t *status);

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif // __CANSessionMux_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/NetworkCommunication/FRCComm.h b/aos/externals/allwpilib/hal/lib/Athena/NetworkCommunication/FRCComm.h
new file mode 100644
index 0000000..d708136
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/NetworkCommunication/FRCComm.h
@@ -0,0 +1,129 @@
+/*************************************************************

+ * 					NOTICE

+ * 

+ * 	These are the only externally exposed functions to the

+ *   NetworkCommunication library

+ * 

+ * This is an implementation of FRC Spec for Comm Protocol

+ * Revision 4.5, June 30, 2008

+ *

+ * Copyright (c) National Instruments 2008.  All Rights Reserved.

+ * 

+ *************************************************************/

+

+#ifndef __FRC_COMM_H__

+#define __FRC_COMM_H__

+

+#ifdef SIMULATION

+#include <vxWorks_compat.h>

+#ifdef USE_THRIFT

+#define EXPORT_FUNC

+#else

+#define EXPORT_FUNC __declspec(dllexport) __cdecl

+#endif

+#else

+#if defined(__vxworks)

+#include <vxWorks.h>

+#define EXPORT_FUNC

+#else

+#include <stdint.h>

+#include <pthread.h>

+#define EXPORT_FUNC

+#endif

+#endif

+

+#define ERR_FRCSystem_NetCommNotResponding -44049

+#define ERR_FRCSystem_NoDSConnection -44018

+

+enum AllianceStationID_t {

+	kAllianceStationID_red1,

+	kAllianceStationID_red2,

+	kAllianceStationID_red3,

+	kAllianceStationID_blue1,

+	kAllianceStationID_blue2,

+	kAllianceStationID_blue3,

+};

+

+enum MatchType_t {

+	kMatchType_none,

+	kMatchType_practice,

+	kMatchType_qualification,

+	kMatchType_elimination,

+};

+

+struct ControlWord_t {

+#ifndef __vxworks

+	uint32_t enabled : 1;

+	uint32_t autonomous : 1;

+	uint32_t test :1;

+	uint32_t eStop : 1;

+	uint32_t fmsAttached:1;

+	uint32_t dsAttached:1;

+	uint32_t control_reserved : 26;

+#else

+	uint32_t control_reserved : 26;

+	uint32_t dsAttached:1;

+	uint32_t fmsAttached:1;

+	uint32_t eStop : 1;

+	uint32_t test :1;

+	uint32_t autonomous : 1;

+	uint32_t enabled : 1;

+#endif

+};

+

+struct JoystickAxes_t {

+	uint16_t count;

+	int16_t axes[1];

+};

+

+struct JoystickPOV_t {

+	uint16_t count;

+	int16_t povs[1];

+};

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+	int EXPORT_FUNC FRC_NetworkCommunication_Reserve(void *instance);

+#ifndef SIMULATION

+	void EXPORT_FUNC getFPGAHardwareVersion(uint16_t *fpgaVersion, uint32_t *fpgaRevision);

+#endif

+	int EXPORT_FUNC setStatusData(float battery, uint8_t dsDigitalOut, uint8_t updateNumber,

+			const char *userDataHigh, int userDataHighLength,

+			const char *userDataLow, int userDataLowLength, int wait_ms);

+	int EXPORT_FUNC setErrorData(const char *errors, int errorsLength, int wait_ms);

+	

+#ifdef SIMULATION

+	void EXPORT_FUNC setNewDataSem(HANDLE);

+#else

+# if defined (__vxworks)

+	void EXPORT_FUNC setNewDataSem(SEM_ID);

+# else

+	void EXPORT_FUNC setNewDataSem(pthread_cond_t *);

+# endif

+#endif

+

+	// this uint32_t is really a LVRefNum

+	int EXPORT_FUNC setNewDataOccurRef(uint32_t refnum);

+

+	int EXPORT_FUNC FRC_NetworkCommunication_getControlWord(struct ControlWord_t *controlWord);

+	int EXPORT_FUNC FRC_NetworkCommunication_getAllianceStation(enum AllianceStationID_t *allianceStation);

+	int EXPORT_FUNC FRC_NetworkCommunication_getMatchTime(float *matchTime);

+	int EXPORT_FUNC FRC_NetworkCommunication_getJoystickAxes(uint8_t joystickNum, struct JoystickAxes_t *axes, uint8_t maxAxes);

+	int EXPORT_FUNC FRC_NetworkCommunication_getJoystickButtons(uint8_t joystickNum, uint32_t *buttons, uint8_t *count);

+	int EXPORT_FUNC FRC_NetworkCommunication_getJoystickPOVs(uint8_t joystickNum, struct JoystickPOV_t *povs, uint8_t maxPOVs);

+	int EXPORT_FUNC FRC_NetworkCommunication_setJoystickOutputs(uint8_t joystickNum, uint32_t hidOutputs, uint16_t leftRumble, uint16_t rightRumble);

+	int EXPORT_FUNC FRC_NetworkCommunication_getJoystickDesc(uint8_t joystickNum, uint8_t *isXBox, uint8_t *type, char *name,

+		uint8_t *axisCount, uint8_t *axisTypes, uint8_t *buttonCount, uint8_t *povCount);

+

+	void EXPORT_FUNC FRC_NetworkCommunication_getVersionString(char *version);

+	int EXPORT_FUNC FRC_NetworkCommunication_observeUserProgramStarting(void);

+	void EXPORT_FUNC FRC_NetworkCommunication_observeUserProgramDisabled(void);

+	void EXPORT_FUNC FRC_NetworkCommunication_observeUserProgramAutonomous(void);

+	void EXPORT_FUNC FRC_NetworkCommunication_observeUserProgramTeleop(void);

+	void EXPORT_FUNC FRC_NetworkCommunication_observeUserProgramTest(void);

+#ifdef __cplusplus

+}

+#endif

+

+#endif

diff --git a/aos/externals/allwpilib/hal/lib/Athena/NetworkCommunication/LoadOut.h b/aos/externals/allwpilib/hal/lib/Athena/NetworkCommunication/LoadOut.h
new file mode 100644
index 0000000..fce88a2
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/NetworkCommunication/LoadOut.h
@@ -0,0 +1,58 @@
+

+#ifndef __LoadOut_h__

+#define __LoadOut_h__

+

+#ifdef SIMULATION

+#include <vxWorks_compat.h>

+#define EXPORT_FUNC __declspec(dllexport) __cdecl

+#elif defined (__vxworks)

+#include <vxWorks.h>

+#define EXPORT_FUNC

+#else

+#include <stdint.h>

+#define EXPORT_FUNC

+#endif

+

+#define kMaxModuleNumber 2

+namespace nLoadOut

+{

+#if defined(__vxworks) || defined(SIMULATION)

+    typedef enum {

+        kModuleType_Unknown = 0x00,

+        kModuleType_Analog = 0x01,

+        kModuleType_Digital = 0x02,

+        kModuleType_Solenoid = 0x03,

+    } tModuleType;

+    bool EXPORT_FUNC getModulePresence(tModuleType moduleType, uint8_t moduleNumber);

+#endif

+    typedef enum {

+        kTargetClass_Unknown = 0x00,

+        kTargetClass_FRC1 = 0x10,

+        kTargetClass_FRC2 = 0x20,

+        kTargetClass_FRC3 = 0x30,

+        kTargetClass_RoboRIO = 0x40,

+#if defined(__vxworks) || defined(SIMULATION)

+        kTargetClass_FRC2_Analog = kTargetClass_FRC2 | kModuleType_Analog,

+        kTargetClass_FRC2_Digital = kTargetClass_FRC2 | kModuleType_Digital,

+        kTargetClass_FRC2_Solenoid = kTargetClass_FRC2 | kModuleType_Solenoid,

+#endif

+        kTargetClass_FamilyMask = 0xF0,

+        kTargetClass_ModuleMask = 0x0F,

+    } tTargetClass;

+    tTargetClass EXPORT_FUNC getTargetClass();

+}

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+#if defined(__vxworks) || defined(SIMULATION)

+    uint32_t EXPORT_FUNC FRC_NetworkCommunication_nLoadOut_getModulePresence(uint32_t moduleType, uint8_t moduleNumber);

+#endif

+    uint32_t EXPORT_FUNC FRC_NetworkCommunication_nLoadOut_getTargetClass();

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif // __LoadOut_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/NetworkCommunication/UsageReporting.h b/aos/externals/allwpilib/hal/lib/Athena/NetworkCommunication/UsageReporting.h
new file mode 100644
index 0000000..0ec2a3a
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/NetworkCommunication/UsageReporting.h
@@ -0,0 +1,143 @@
+

+#ifndef __UsageReporting_h__

+#define __UsageReporting_h__

+

+#ifdef SIMULATION

+#include <vxWorks_compat.h>

+#define EXPORT_FUNC __declspec(dllexport) __cdecl

+#elif defined (__vxworks)

+#include <vxWorks.h>

+#define EXPORT_FUNC

+#else

+#include <stdint.h>

+#include <stdlib.h>

+#define EXPORT_FUNC

+#endif

+

+#define kUsageReporting_version 1

+

+namespace nUsageReporting

+{

+    typedef enum

+    {

+        kResourceType_Controller,

+        kResourceType_Module,

+        kResourceType_Language,

+        kResourceType_CANPlugin,

+        kResourceType_Accelerometer,

+        kResourceType_ADXL345,

+        kResourceType_AnalogChannel,

+        kResourceType_AnalogTrigger,

+        kResourceType_AnalogTriggerOutput,

+        kResourceType_CANJaguar,

+        kResourceType_Compressor,

+        kResourceType_Counter,

+        kResourceType_Dashboard,

+        kResourceType_DigitalInput,

+        kResourceType_DigitalOutput,

+        kResourceType_DriverStationCIO,

+        kResourceType_DriverStationEIO,

+        kResourceType_DriverStationLCD,

+        kResourceType_Encoder,

+        kResourceType_GearTooth,

+        kResourceType_Gyro,

+        kResourceType_I2C,

+        kResourceType_Framework,

+        kResourceType_Jaguar,

+        kResourceType_Joystick,

+        kResourceType_Kinect,

+        kResourceType_KinectStick,

+        kResourceType_PIDController,

+        kResourceType_Preferences,

+        kResourceType_PWM,

+        kResourceType_Relay,

+        kResourceType_RobotDrive,

+        kResourceType_SerialPort,

+        kResourceType_Servo,

+        kResourceType_Solenoid,

+        kResourceType_SPI,

+        kResourceType_Task,

+        kResourceType_Ultrasonic,

+        kResourceType_Victor,

+        kResourceType_Button,

+        kResourceType_Command,

+        kResourceType_AxisCamera,

+        kResourceType_PCVideoServer,

+        kResourceType_SmartDashboard,

+        kResourceType_Talon,

+        kResourceType_HiTechnicColorSensor,

+        kResourceType_HiTechnicAccel,

+        kResourceType_HiTechnicCompass,

+        kResourceType_SRF08,

+        kResourceType_AnalogOutput,

+        kResourceType_VictorSP,

+        kResourceType_TalonSRX,

+        kResourceType_CANTalonSRX,

+    } tResourceType;

+

+    typedef enum

+    {

+        kLanguage_LabVIEW = 1,

+        kLanguage_CPlusPlus = 2,

+        kLanguage_Java = 3,

+        kLanguage_Python = 4,

+

+        kCANPlugin_BlackJagBridge = 1,

+        kCANPlugin_2CAN = 2,

+

+        kFramework_Iterative = 1,

+        kFramework_Simple = 2,

+

+        kRobotDrive_ArcadeStandard = 1,

+        kRobotDrive_ArcadeButtonSpin = 2,

+        kRobotDrive_ArcadeRatioCurve = 3,

+        kRobotDrive_Tank = 4,

+        kRobotDrive_MecanumPolar = 5,

+        kRobotDrive_MecanumCartesian = 6,

+

+        kDriverStationCIO_Analog = 1,

+        kDriverStationCIO_DigitalIn = 2,

+        kDriverStationCIO_DigitalOut = 3,

+

+        kDriverStationEIO_Acceleration = 1,

+        kDriverStationEIO_AnalogIn = 2,

+        kDriverStationEIO_AnalogOut = 3,

+        kDriverStationEIO_Button = 4,

+        kDriverStationEIO_LED = 5,

+        kDriverStationEIO_DigitalIn = 6,

+        kDriverStationEIO_DigitalOut = 7,

+        kDriverStationEIO_FixedDigitalOut = 8,

+        kDriverStationEIO_PWM = 9,

+        kDriverStationEIO_Encoder = 10,

+        kDriverStationEIO_TouchSlider = 11,

+

+        kADXL345_SPI = 1,

+        kADXL345_I2C = 2,

+

+        kCommand_Scheduler = 1,

+

+        kSmartDashboard_Instance = 1,

+    } tInstances;

+

+    /**

+     * Report the usage of a resource of interest.

+     * 

+     * @param resource one of the values in the tResourceType above (max value 51).

+     * @param instanceNumber an index that identifies the resource instance.

+     * @param context an optional additional context number for some cases (such as module number).  Set to 0 to omit.

+     * @param feature a string to be included describing features in use on a specific resource.  Setting the same resource more than once allows you to change the feature string.

+     */

+    uint32_t EXPORT_FUNC report(tResourceType resource, uint8_t instanceNumber, uint8_t context = 0, const char *feature = NULL);

+}

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+    uint32_t EXPORT_FUNC FRC_NetworkCommunication_nUsageReporting_report(uint8_t resource, uint8_t instanceNumber, uint8_t context, const char *feature);

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif // __UsageReporting_h__

diff --git a/aos/externals/allwpilib/hal/lib/Athena/Notifier.cpp b/aos/externals/allwpilib/hal/lib/Athena/Notifier.cpp
new file mode 100644
index 0000000..c532512
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/Notifier.cpp
@@ -0,0 +1,40 @@
+#include "HAL/Notifier.hpp"
+#include "ChipObject.h"
+
+static const uint32_t kTimerInterruptNumber = 28;
+
+struct Notifier
+{
+	tAlarm *alarm;
+	tInterruptManager *manager;
+};
+
+void* initializeNotifier(void (*ProcessQueue)(uint32_t, void*), int32_t *status)
+{
+	Notifier* notifier = new Notifier();
+	notifier->manager = new tInterruptManager(1 << kTimerInterruptNumber, false, status);
+	notifier->manager->registerHandler(ProcessQueue, NULL, status);
+	notifier->manager->enable(status);
+	notifier->alarm = tAlarm::create(status);
+	return notifier;
+}
+
+void cleanNotifier(void* notifier_pointer, int32_t *status)
+{
+	Notifier* notifier = (Notifier*)notifier_pointer;
+	notifier->alarm->writeEnable(false, status);
+	delete notifier->alarm;
+	notifier->alarm = NULL;
+	notifier->manager->disable(status);
+	delete notifier->manager;
+	notifier->manager = NULL;
+}
+
+void updateNotifierAlarm(void* notifier_pointer, uint32_t triggerTime, int32_t *status)
+{
+	Notifier* notifier = (Notifier*)notifier_pointer;
+	// write the first item in the queue into the trigger time
+	notifier->alarm->writeTriggerTime(triggerTime, status);
+	// Enable the alarm.  The hardware disables itself after each alarm.
+	notifier->alarm->writeEnable(true, status);
+}
diff --git a/aos/externals/allwpilib/hal/lib/Athena/PDP.cpp b/aos/externals/allwpilib/hal/lib/Athena/PDP.cpp
new file mode 100644
index 0000000..6129c06
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/PDP.cpp
@@ -0,0 +1,61 @@
+#include "HAL/PDP.hpp"
+#include "ctre/PDP.h"
+static PDP pdp;
+
+double getPDPTemperature(int32_t *status) {
+	double temperature;
+	
+	*status = pdp.GetTemperature(temperature);
+	
+	return temperature;
+}
+
+double getPDPVoltage(int32_t *status) {
+	double voltage;
+	
+	*status = pdp.GetVoltage(voltage);
+	
+	return voltage;
+}
+
+double getPDPChannelCurrent(uint8_t channel, int32_t *status) {
+	double current;
+	
+	*status = pdp.GetChannelCurrent(channel, current);
+	
+	return current;
+}
+
+double getPDPTotalCurrent(int32_t *status) {
+	double current;
+	
+	*status = pdp.GetTotalCurrent(current);
+	
+	return current;
+}
+
+double getPDPTotalPower(int32_t *status) {
+	double power;
+	
+	*status = pdp.GetTotalPower(power);
+	
+	return power;
+}
+
+double getPDPTotalEnergy(int32_t *status) {
+	double energy;
+	
+	*status = pdp.GetTotalEnergy(energy);
+	
+	return energy;
+}
+
+void resetPDPTotalEnergy(int32_t *status) {
+	*status = pdp.ResetEnergy();
+}
+
+void clearPDPStickyFaults(int32_t *status) {
+	*status = pdp.ClearStickyFaults();
+}
+
+
diff --git a/aos/externals/allwpilib/hal/lib/Athena/Port.h b/aos/externals/allwpilib/hal/lib/Athena/Port.h
new file mode 100644
index 0000000..8679c26
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/Port.h
@@ -0,0 +1,7 @@
+#pragma once
+
+typedef struct port_t
+{
+	uint8_t pin;
+	uint8_t module;
+} Port;
diff --git a/aos/externals/allwpilib/hal/lib/Athena/Power.cpp b/aos/externals/allwpilib/hal/lib/Athena/Power.cpp
new file mode 100644
index 0000000..34db043
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/Power.cpp
@@ -0,0 +1,127 @@
+#include "HAL/Power.hpp"
+#include "ChipObject.h"
+
+static tPower *power = NULL;
+
+static void initializePower(int32_t *status) {
+	if(power == NULL) {
+		power = tPower::create(status);
+	}
+}
+
+/**
+ * Get the roboRIO input voltage
+ */
+float getVinVoltage(int32_t *status) {
+	initializePower(status);
+	return power->readVinVoltage(status) / 4.096f * 0.025733f - 0.029f;
+}
+
+/**
+ * Get the roboRIO input current
+ */
+float getVinCurrent(int32_t *status) {
+	initializePower(status);
+	return power->readVinCurrent(status) / 4.096f * 0.017042 - 0.071f;
+}
+
+/**
+ * Get the 6V rail voltage
+ */
+float getUserVoltage6V(int32_t *status) {
+	initializePower(status);
+	return power->readUserVoltage6V(status) / 4.096f * 0.007019f - 0.014f;
+}
+
+/**
+ * Get the 6V rail current
+ */
+float getUserCurrent6V(int32_t *status) {
+	initializePower(status);
+	return power->readUserCurrent6V(status) / 4.096f * 0.005566f - 0.009f;
+}
+
+/**
+ * Get the active state of the 6V rail
+ */
+bool getUserActive6V(int32_t *status) {
+	initializePower(status);
+	return power->readStatus_User6V(status) == 4;
+}
+
+/**
+ * Get the fault count for the 6V rail
+ */
+int getUserCurrentFaults6V(int32_t *status) {
+	initializePower(status);
+	return (int)power->readOverCurrentFaultCounts_OverCurrentFaultCount6V(status);
+}
+
+/**
+ * Get the 5V rail voltage
+ */
+float getUserVoltage5V(int32_t *status) {
+	initializePower(status);
+	return power->readUserVoltage5V(status) / 4.096f * 0.005962f - 0.013f;
+}
+
+/**
+ * Get the 5V rail current
+ */
+float getUserCurrent5V(int32_t *status) {
+	initializePower(status);
+	return power->readUserCurrent5V(status) / 4.096f * 0.001996f - 0.002f;
+}
+
+/**
+ * Get the active state of the 5V rail
+ */
+bool getUserActive5V(int32_t *status) {
+	initializePower(status);
+	return power->readStatus_User5V(status) == 4;
+}
+
+/**
+ * Get the fault count for the 5V rail
+ */
+int getUserCurrentFaults5V(int32_t *status) {
+	initializePower(status);
+	return (int)power->readOverCurrentFaultCounts_OverCurrentFaultCount5V(status);
+}
+
+unsigned char getUserStatus5V(int32_t *status) {
+	initializePower(status);
+	return power->readStatus_User5V(status);
+}
+
+/**
+ * Get the 3.3V rail voltage
+ */
+float getUserVoltage3V3(int32_t *status) {
+	initializePower(status);
+	return power->readUserVoltage3V3(status) / 4.096f * 0.004902f - 0.01f;
+}
+
+/**
+ * Get the 3.3V rail current
+ */
+float getUserCurrent3V3(int32_t *status) {
+	initializePower(status);
+	return power->readUserCurrent3V3(status) / 4.096f * 0.002486f - 0.003f;
+}
+
+/**
+ * Get the active state of the 3.3V rail
+ */
+bool getUserActive3V3(int32_t *status) {
+	initializePower(status);
+	return power->readStatus_User3V3(status) == 4;
+}
+
+/**
+ * Get the fault count for the 3.3V rail
+ */
+int getUserCurrentFaults3V3(int32_t *status) {
+	initializePower(status);
+	return (int)power->readOverCurrentFaultCounts_OverCurrentFaultCount3V3(status);
+}
diff --git a/aos/externals/allwpilib/hal/lib/Athena/Semaphore.cpp b/aos/externals/allwpilib/hal/lib/Athena/Semaphore.cpp
new file mode 100644
index 0000000..df30f3c
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/Semaphore.cpp
@@ -0,0 +1,150 @@
+#include "HAL/Semaphore.hpp"
+#include "HAL/cpp/Synchronized.hpp"
+
+#include "Log.hpp"
+
+// set the logging level
+TLogLevel semaphoreLogLevel = logDEBUG;
+
+#define SEMAPHORE_LOG(level) \
+    if (level > semaphoreLogLevel) ; \
+    else Log().Get(level)
+
+// See: http://www.vxdev.com/docs/vx55man/vxworks/ref/semMLib.html
+const uint32_t SEMAPHORE_Q_FIFO= 0x01; // TODO: Support
+const uint32_t SEMAPHORE_Q_PRIORITY = 0x01; // TODO: Support
+const uint32_t SEMAPHORE_DELETE_SAFE = 0x04; // TODO: Support
+const uint32_t SEMAPHORE_INVERSION_SAFE = 0x08; // TODO: Support
+
+const int32_t SEMAPHORE_NO_WAIT = 0;
+const int32_t SEMAPHORE_WAIT_FOREVER = -1;
+
+const uint32_t SEMAPHORE_EMPTY = 0;
+const uint32_t SEMAPHORE_FULL = 1;
+
+class MutexInterface {
+ public:
+  virtual void lock() = 0;
+  virtual void unlock() = 0;
+  virtual bool try_lock() = 0;
+  virtual pthread_mutex_t *native_handle() = 0;
+  virtual ~MutexInterface() {}
+};
+
+template <typename MutexType>
+class TemplatedMutexWrapper : public MutexInterface {
+ public:
+  virtual void lock() { m_.lock(); }
+  virtual void unlock() { m_.unlock(); }
+  virtual bool try_lock() { return m_.try_lock(); }
+  pthread_mutex_t *native_handle() { return m_.native_handle(); }
+
+ private:
+  MutexType m_;
+};
+
+MUTEX_ID initializeMutexRecursive()
+{
+  return new TemplatedMutexWrapper<ReentrantMutex>();
+}
+
+MUTEX_ID initializeMutexNormal()
+{
+  return new TemplatedMutexWrapper<Mutex>();
+}
+
+void deleteMutex(MUTEX_ID mutex)
+{
+	delete mutex;
+}
+
+/**
+ * Lock the semaphore, blocking until it's available.
+ * @return 0 for success, -1 for error. If -1, the error will be in errno.
+ */
+int8_t lockMutex(MUTEX_ID mutex)
+{
+    mutex->lock();
+    return 0;
+}
+
+/**
+ * Tries to lock the mutex.
+ * @return 1 if we got the lock, 0 otherwise.
+ */
+int8_t tryLockMutex(MUTEX_ID mutex)
+{
+    return mutex->try_lock();
+}
+
+/**
+ * Unlock the semaphore.
+ * @return 0 for success, -1 for error. If -1, the error will be in errno.
+ */
+int8_t unlockMutex(MUTEX_ID mutex)
+{
+	mutex->unlock();
+  return 0;
+}
+
+SEMAPHORE_ID initializeSemaphore(uint32_t initial_value) {
+  SEMAPHORE_ID sem = new sem_t;
+  sem_init(sem, 0, initial_value);
+  return sem;
+}
+
+void deleteSemaphore(SEMAPHORE_ID sem) {
+  sem_destroy(sem);
+  delete sem;
+}
+
+/**
+ * Lock the semaphore, blocking until it's available.
+ * @return 0 for success, -1 for error. If -1, the error will be in errno.
+ */
+int8_t takeSemaphore(SEMAPHORE_ID sem)
+{
+    return sem_wait(sem);
+}
+
+int8_t tryTakeSemaphore(SEMAPHORE_ID sem)
+{
+    return sem_trywait(sem);
+}
+
+/**
+ * Unlock the semaphore.
+ * @return 0 for success, -1 for error. If -1, the error will be in errno.
+ */
+int8_t giveSemaphore(SEMAPHORE_ID sem)
+{
+  return sem_post(sem);
+}
+
+
+MULTIWAIT_ID initializeMultiWait() {
+  pthread_condattr_t attr;
+  pthread_condattr_init(&attr);
+  MULTIWAIT_ID cond = new pthread_cond_t();
+  pthread_cond_init(cond, &attr);
+  pthread_condattr_destroy(&attr);
+  return cond;
+}
+
+void deleteMultiWait(MULTIWAIT_ID sem) {
+  pthread_cond_destroy(sem);
+  delete sem;
+}
+
+int8_t takeMultiWait(MULTIWAIT_ID sem, MUTEX_ID m, int32_t timeout) {
+  lockMutex(m);
+  int8_t val = pthread_cond_wait(sem, m->native_handle());
+  unlockMutex(m);
+  return val;
+}
+
+int8_t giveMultiWait(MULTIWAIT_ID sem) {
+  return pthread_cond_broadcast(sem);
+}
+
+
diff --git a/aos/externals/allwpilib/hal/lib/Athena/Solenoid.cpp b/aos/externals/allwpilib/hal/lib/Athena/Solenoid.cpp
new file mode 100644
index 0000000..3b8bfaf
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/Solenoid.cpp
@@ -0,0 +1,90 @@
+
+#include "HAL/Solenoid.hpp"
+
+#include "Port.h"
+#include "HAL/Errors.hpp"
+#include "ChipObject.h"
+#include "HAL/cpp/Synchronized.hpp"
+#include "NetworkCommunication/LoadOut.h"
+#include "ctre/PCM.h"
+
+static const int NUM_MODULE_NUMBERS = 63;
+
+PCM *modules[NUM_MODULE_NUMBERS] = { NULL };
+
+struct solenoid_port_t {
+	PCM *module;
+	uint32_t pin;
+};
+
+void initializePCM(int module) {
+	if(!modules[module]) {
+		modules[module] = new PCM(module);
+	}
+}
+
+void* initializeSolenoidPort(void *port_pointer, int32_t *status) {
+	Port* port = (Port*) port_pointer;
+	initializePCM(port->module);
+	
+	solenoid_port_t *solenoid_port = new solenoid_port_t;
+	solenoid_port->module = modules[port->module];
+	solenoid_port->pin = port->pin;
+
+	return solenoid_port;
+}
+
+bool checkSolenoidModule(uint8_t module) {
+	return module < NUM_MODULE_NUMBERS;
+}
+
+bool getSolenoid(void* solenoid_port_pointer, int32_t *status) {
+	solenoid_port_t* port = (solenoid_port_t*) solenoid_port_pointer;
+	bool value;
+
+	*status = port->module->GetSolenoid(port->pin, value);
+
+	return value;
+}
+
+void setSolenoid(void* solenoid_port_pointer, bool value, int32_t *status) {
+	solenoid_port_t* port = (solenoid_port_t*) solenoid_port_pointer;
+
+	port->module->SetSolenoids(1 << port->pin, value ? 0xFF : 0x00);
+}
+
+void setSolenoids(void* solenoid_port_pointer, uint8_t value, uint8_t mask, int32_t *status) {
+	solenoid_port_t* port = (solenoid_port_t*) solenoid_port_pointer;
+
+	port->module->SetSolenoids(value, mask);
+}
+
+int getPCMSolenoidBlackList(void* solenoid_port_pointer, int32_t *status){
+	solenoid_port_t* port = (solenoid_port_t*) solenoid_port_pointer;
+	UINT8 value;
+	
+	*status = port->module->GetSolenoidBlackList(value);
+
+	return value;
+}
+bool getPCMSolenoidVoltageStickyFault(void* solenoid_port_pointer, int32_t *status){
+	solenoid_port_t* port = (solenoid_port_t*) solenoid_port_pointer;
+	bool value;
+
+	*status = port->module->GetSolenoidStickyFault(value);
+
+	return value;
+}
+bool getPCMSolenoidVoltageFault(void* solenoid_port_pointer, int32_t *status){
+	solenoid_port_t* port = (solenoid_port_t*) solenoid_port_pointer;
+	bool value;
+
+	*status = port->module->GetSolenoidFault(value);
+
+	return value;
+}
+void clearAllPCMStickyFaults_sol(void *solenoid_port_pointer, int32_t *status){
+	solenoid_port_t* port = (solenoid_port_t*) solenoid_port_pointer;
+	
+	*status = port->module->ClearStickyFaults();
+}
diff --git a/aos/externals/allwpilib/hal/lib/Athena/Task.cpp b/aos/externals/allwpilib/hal/lib/Athena/Task.cpp
new file mode 100644
index 0000000..2be66f5
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/Task.cpp
@@ -0,0 +1,104 @@
+
+#include "HAL/Task.hpp"
+
+#include <stdio.h>
+#include <signal.h>
+
+#ifndef OK
+#define OK		0
+#endif /* OK */
+#ifndef ERROR
+#define ERROR		(-1)
+#endif /* ERROR */
+
+const uint32_t VXWORKS_FP_TASK = 0x01000000;
+const int32_t HAL_objLib_OBJ_ID_ERROR = -1; // TODO: update to relevant TaskIDError
+const int32_t HAL_objLib_OBJ_DELETED = -1; // TODO: update to relevant TaskDeletedError
+const int32_t HAL_taskLib_ILLEGAL_OPTIONS = -1; // TODO: update to relevant TaskOptionsError
+const int32_t HAL_memLib_NOT_ENOUGH_MEMORY = -1; // TODO: update to relevant TaskMemoryError
+const int32_t HAL_taskLib_ILLEGAL_PRIORITY = -1; // TODO: update to relevant TaskPriorityError
+
+struct TaskArgs {
+	FUNCPTR fun;
+	char* name;
+	pthread_t** task;
+	uint32_t arg0, arg1, arg2, arg3, arg4,
+	         arg5, arg6, arg7, arg8, arg9;
+};
+
+void* startRoutine(void* data) {
+	TaskArgs* args = (TaskArgs*) data;
+	printf("[HAL] Starting task %s...\n", args->name);
+	int val = args->fun(args->arg0, args->arg1, args->arg2, args->arg3, args->arg4,
+			         args->arg5, args->arg6, args->arg7, args->arg8, args->arg9);
+	printf("[HAL] Exited task %s with code %i\n", args->name, val);
+	*args->task = NULL;
+	int* ret = new int(); *ret = val;
+	return ret;
+}
+
+TASK spawnTask(char * name, int priority, int options, int stackSize, 
+		       FUNCPTR entryPt, uint32_t arg0, uint32_t arg1, uint32_t arg2,
+		       uint32_t arg3, uint32_t arg4, uint32_t arg5, uint32_t arg6,
+		       uint32_t arg7, uint32_t arg8, uint32_t arg9) {
+  printf("[HAL] Spawning task %s...\n", name);
+  pthread_t* task = new pthread_t;
+  pthread_attr_t* attr = new pthread_attr_t;
+  pthread_attr_init(attr);
+  TaskArgs* args = new TaskArgs();
+  args->fun = entryPt;
+  args->name = name;
+  args->task = new pthread_t*;
+  *args->task = task;
+  args->arg0 = arg0; args->arg1 = arg1; args->arg2 = arg2; args->arg3 = arg3; args->arg4 = arg4;
+  args->arg5 = arg5; args->arg6 = arg6; args->arg7 = arg7; args->arg8 = arg8; args->arg9 = arg9;
+  if (pthread_create(task, attr, startRoutine, args) == 0) {
+	  printf("[HAL] Success\n");
+	  pthread_detach(*task);
+  } else {
+	  printf("[HAL] Failure\n");
+	  task = NULL;
+  }
+  pthread_attr_destroy(attr);
+  return task;
+}
+
+STATUS restartTask(TASK task) {
+  return ERROR; // TODO: implement;
+}
+
+STATUS deleteTask(TASK task) {
+  return ERROR; // TODO: implement
+}
+
+STATUS isTaskReady(TASK task) {
+  return ERROR; // TODO: implement
+}
+
+STATUS isTaskSuspended(TASK task) {
+  return ERROR; // TODO: implement
+}
+
+STATUS suspendTask(TASK task) {
+  return ERROR; // TODO: implement
+}
+
+STATUS resumeTask(TASK task) {
+  return ERROR; // TODO: implement
+}
+
+STATUS verifyTaskID(TASK task) {
+  if (task != NULL && pthread_kill(*task, 0) == 0) {
+	return OK;
+  } else {
+	return ERROR;
+  }
+}
+
+STATUS setTaskPriority(TASK task, int priority) {
+  return ERROR; // TODO: implement
+}
+
+STATUS getTaskPriority(TASK task, int* priority) {
+  return ERROR; // TODO: implement
+}
diff --git a/aos/externals/allwpilib/hal/lib/Athena/Utilities.cpp b/aos/externals/allwpilib/hal/lib/Athena/Utilities.cpp
new file mode 100644
index 0000000..b34677f
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/Utilities.cpp
@@ -0,0 +1,44 @@
+#include "HAL/Utilities.hpp"
+#include <time.h>
+
+const int32_t HAL_NO_WAIT = 0;
+const int32_t HAL_WAIT_FOREVER = -1;
+
+void delayTicks(int32_t ticks)
+{
+	struct timespec test, remaining;
+	test.tv_sec = 0;
+	test.tv_nsec = ticks * 3;
+
+	/* Sleep until the requested number of ticks has passed, with additional
+		time added if nanosleep is interrupted. */
+	while(nanosleep(&test, &remaining) == -1) {
+		test = remaining;
+	}
+}
+
+void delayMillis(double ms)
+{
+	struct timespec test, remaining;
+	test.tv_sec = ms / 1000;
+	test.tv_nsec = 1000 * (((uint64_t)ms) % 1000000);
+
+	/* Sleep until the requested number of milliseconds has passed, with
+		additional time added if nanosleep is interrupted. */
+	while(nanosleep(&test, &remaining) == -1) {
+		test = remaining;
+	}
+}
+
+void delaySeconds(double s)
+{
+	struct timespec test, remaining;
+	test.tv_sec = (int)s;
+	test.tv_nsec = (s - (int)s) * 1000000000.0;
+
+	/* Sleep until the requested number of seconds has passed, with additional
+		time added if nanosleep is interrupted. */
+	while(nanosleep(&test, &remaining) == -1) {
+		test = remaining;
+	}
+}
diff --git a/aos/externals/allwpilib/hal/lib/Athena/cpp/Resource.cpp b/aos/externals/allwpilib/hal/lib/Athena/cpp/Resource.cpp
new file mode 100644
index 0000000..ceed1b1
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/cpp/Resource.cpp
@@ -0,0 +1,120 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "HAL/cpp/Resource.hpp"
+#include "HAL/Errors.hpp"
+#include <cstddef>
+
+ReentrantMutex Resource::m_createLock;
+
+/**
+ * Allocate storage for a new instance of Resource.
+ * Allocate a bool array of values that will get initialized to indicate that no resources
+ * have been allocated yet. The indicies of the resources are [0 .. elements - 1].
+ */
+Resource::Resource(uint32_t elements)
+{
+	::std::unique_lock<ReentrantMutex> sync(m_createLock);
+	m_size = elements;
+	m_isAllocated = new bool[m_size];
+	for (uint32_t i=0; i < m_size; i++)
+	{
+		m_isAllocated[i] = false;
+	}
+}
+
+/**
+ * Factory method to create a Resource allocation-tracker *if* needed.
+ *
+ * @param r -- address of the caller's Resource pointer. If *r == NULL, this
+ *    will construct a Resource and make *r point to it. If *r != NULL, i.e.
+ *    the caller already has a Resource instance, this won't do anything.
+ * @param elements -- the number of elements for this Resource allocator to
+ *    track, that is, it will allocate resource numbers in the range
+ *    [0 .. elements - 1].
+ */
+/*static*/ void Resource::CreateResourceObject(Resource **r, uint32_t elements)
+{
+	::std::unique_lock<ReentrantMutex> sync(m_createLock);
+	if (*r == NULL)
+	{
+		*r = new Resource(elements);
+	}
+}
+
+/**
+ * Delete the allocated array or resources.
+ * This happens when the module is unloaded (provided it was statically allocated).
+ */
+Resource::~Resource()
+{
+	delete[] m_isAllocated;
+}
+
+/**
+ * Allocate a resource.
+ * When a resource is requested, mark it allocated. In this case, a free resource value
+ * within the range is located and returned after it is marked allocated.
+ */
+uint32_t Resource::Allocate(const char *resourceDesc)
+{
+	::std::unique_lock<ReentrantMutex> sync(m_allocateLock);
+	for (uint32_t i=0; i < m_size; i++)
+	{
+		if (!m_isAllocated[i])
+		{
+			m_isAllocated[i] = true;
+			return i;
+		}
+	}
+	// TODO: wpi_setWPIErrorWithContext(NoAvailableResources, resourceDesc);
+	return ~0ul;
+}
+
+/**
+ * Allocate a specific resource value.
+ * The user requests a specific resource value, i.e. channel number and it is verified
+ * unallocated, then returned.
+ */
+uint32_t Resource::Allocate(uint32_t index, const char *resourceDesc)
+{
+	::std::unique_lock<ReentrantMutex> sync(m_allocateLock);
+	if (index >= m_size)
+	{
+		// TODO: wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, resourceDesc);
+		return ~0ul;
+	}
+	if ( m_isAllocated[index] )
+	{
+		// TODO: wpi_setWPIErrorWithContext(ResourceAlreadyAllocated, resourceDesc);
+		return ~0ul;
+	}
+	m_isAllocated[index] = true;
+	return index;
+}
+
+
+/**
+ * Free an allocated resource.
+ * After a resource is no longer needed, for example a destructor is called for a channel assignment
+ * class, Free will release the resource value so it can be reused somewhere else in the program.
+ */
+void Resource::Free(uint32_t index)
+{
+	::std::unique_lock<ReentrantMutex> sync(m_allocateLock);
+	if (index == ~0ul) return;
+	if (index >= m_size)
+	{
+		// TODO: wpi_setWPIError(NotAllocated);
+		return;
+	}
+	if (!m_isAllocated[index])
+	{
+		// TODO: wpi_setWPIError(NotAllocated);
+		return;
+	}
+	m_isAllocated[index] = false;
+}
diff --git a/aos/externals/allwpilib/hal/lib/Athena/cpp/Synchronized.cpp b/aos/externals/allwpilib/hal/lib/Athena/cpp/Synchronized.cpp
new file mode 100644
index 0000000..cfc2ad5
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/cpp/Synchronized.cpp
@@ -0,0 +1,28 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "HAL/cpp/Synchronized.hpp"
+#include "HAL/Semaphore.hpp"
+
+/**
+ * Synchronized class deals with critical regions.
+ * Declare a Synchronized object at the beginning of a block. That will take the semaphore.
+ * When the code exits from the block it will call the destructor which will give the semaphore.
+ * This ensures that no matter how the block is exited, the semaphore will always be released.
+ * @param semaphore The semaphore controlling this critical region.
+ */
+Synchronized::Synchronized(SEMAPHORE_ID semaphore)
+    : m_semaphore(semaphore) {
+  takeSemaphore(m_semaphore);
+}
+
+/**
+ * This destructor unlocks the semaphore.
+ */
+Synchronized::~Synchronized()
+{
+	giveSemaphore(m_semaphore);
+}
diff --git a/aos/externals/allwpilib/hal/lib/Athena/ctre/CanTalonSRX.cpp b/aos/externals/allwpilib/hal/lib/Athena/ctre/CanTalonSRX.cpp
new file mode 100644
index 0000000..a51099c
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/ctre/CanTalonSRX.cpp
@@ -0,0 +1,1241 @@
+/**

+ * @brief CAN TALON SRX driver.

+ *

+ * The TALON SRX is designed to instrument all runtime signals periodically.  The default periods are chosen to support 16 TALONs

+ * with 10ms update rate for control (throttle or setpoint).  However these can be overridden with SetStatusFrameRate. @see SetStatusFrameRate

+ * The getters for these unsolicited signals are auto generated at the bottom of this module.

+ *

+ * Likewise most control signals are sent periodically using the fire-and-forget CAN API.

+ * The setters for these unsolicited signals are auto generated at the bottom of this module.

+ *

+ * Signals that are not available in an unsolicited fashion are the Close Loop gains.

+ * For teams that have a single profile for their TALON close loop they can use either the webpage to configure their TALONs once

+ * 	or set the PIDF,Izone,CloseLoopRampRate,etc... once in the robot application.  These parameters are saved to flash so once they are

+ * 	loaded in the TALON, they will persist through power cycles and mode changes.

+ *

+ * For teams that have one or two profiles to switch between, they can use the same strategy since there are two slots to choose from

+ * and the ProfileSlotSelect is periodically sent in the 10 ms control frame.

+ *

+ * For teams that require changing gains frequently, they can use the soliciting API to get and set those parameters.  Most likely

+ * they will only need to set them in a periodic fashion as a function of what motion the application is attempting.

+ * If this API is used, be mindful of the CAN utilization reported in the driver station.

+ *

+ * Encoder position is measured in encoder edges.  Every edge is counted (similar to roboRIO 4X mode).

+ * Analog position is 10 bits, meaning 1024 ticks per rotation (0V => 3.3V).

+ * Use SetFeedbackDeviceSelect to select which sensor type you need.  Once you do that you can use GetSensorPosition()

+ * and GetSensorVelocity().  These signals are updated on CANBus every 20ms (by default).

+ * If a relative sensor is selected, you can zero (or change the current value) using SetSensorPosition.

+ *

+ * Analog Input and quadrature position (and velocity) are also explicitly reported in GetEncPosition, GetEncVel, GetAnalogInWithOv, GetAnalogInVel.

+ * These signals are available all the time, regardless of what sensor is selected at a rate of 100ms.  This allows easy instrumentation

+ * for "in the pits" checking of all sensors regardless of modeselect.  The 100ms rate is overridable for teams who want to acquire sensor

+ * data for processing, not just instrumentation.  Or just select the sensor using SetFeedbackDeviceSelect to get it at 20ms.

+ *

+ * Velocity is in position ticks / 100ms.

+ *

+ * All output units are in respect to duty cycle (throttle) which is -1023(full reverse) to +1023 (full forward).

+ *  This includes demand (which specifies duty cycle when in duty cycle mode) and rampRamp, which is in throttle units per 10ms (if nonzero).

+ *

+ * Pos and velocity close loops are calc'd as

+ * 		err = target - posOrVel.

+ * 		iErr += err;

+ * 		if(   (IZone!=0)  and  abs(err) > IZone)

+ * 			ClearIaccum()

+ * 		output = P X err + I X iErr + D X dErr + F X target

+ * 		dErr = err - lastErr

+ *	P, I,and D gains are always positive. F can be negative.

+ *	Motor direction can be reversed using SetRevMotDuringCloseLoopEn if sensor and motor are out of phase.

+ *	Similarly feedback sensor can also be reversed (multiplied by -1) if you prefer the sensor to be inverted.

+ *

+ * P gain is specified in throttle per error tick.  For example, a value of 102 is ~9.9% (which is 102/1023) throttle per 1

+ * 		ADC unit(10bit) or 1 quadrature encoder edge depending on selected sensor.

+ *

+ * I gain is specified in throttle per integrated error. For example, a value of 10 equates to ~0.99% (which is 10/1023)

+ *  	for each accumulated ADC unit(10bit) or 1 quadrature encoder edge depending on selected sensor.

+ *  	Close loop and integral accumulator runs every 1ms.

+ *

+ * D gain is specified in throttle per derivative error. For example a value of 102 equates to ~9.9% (which is 102/1023)

+ * 	per change of 1 unit (ADC or encoder) per ms.

+ *

+ * I Zone is specified in the same units as sensor position (ADC units or quadrature edges).  If pos/vel error is outside of

+ * 		this value, the integrated error will auto-clear...

+ * 		if(   (IZone!=0)  and  abs(err) > IZone)

+ * 			ClearIaccum()

+ * 		...this is very useful in preventing integral windup and is highly recommended if using full PID to keep stability low.

+ *

+ * CloseLoopRampRate is in throttle units per 1ms.  Set to zero to disable ramping.

+ * 		Works the same as RampThrottle but only is in effect when a close loop mode and profile slot is selected.

+ *

+ * auto generated using spreadsheet and WpiClassGen.csproj

+ * @link https://docs.google.com/spreadsheets/d/1OU_ZV7fZLGYUQ-Uhc8sVAmUmWTlT8XBFYK8lfjg_tac/edit#gid=1766046967

+ */

+#include "CanTalonSRX.h"

+#include "NetworkCommunication/CANSessionMux.h"	//CAN Comm

+#include <string.h> // memset

+#include <unistd.h> // usleep

+

+#define STATUS_1  		0x02041400

+#define STATUS_2  		0x02041440

+#define STATUS_3  		0x02041480

+#define STATUS_4  		0x020414C0

+#define STATUS_5  		0x02041500

+#define STATUS_6  		0x02041540

+#define STATUS_7  		0x02041580

+

+#define CONTROL_1 			0x02040000

+#define CONTROL_2 			0x02040040

+#define CONTROL_3 			0x02040080

+

+#define EXPECTED_RESPONSE_TIMEOUT_MS	(200)

+#define GET_STATUS1() CtreCanNode::recMsg<TALON_Status_1_General_10ms_t		> rx = GetRx<TALON_Status_1_General_10ms_t>(STATUS_1	  | GetDeviceNumber(), EXPECTED_RESPONSE_TIMEOUT_MS)

+#define GET_STATUS2() CtreCanNode::recMsg<TALON_Status_2_Feedback_20ms_t	> rx = GetRx<TALON_Status_2_Feedback_20ms_t>(STATUS_2	  | GetDeviceNumber(), EXPECTED_RESPONSE_TIMEOUT_MS)

+#define GET_STATUS3() CtreCanNode::recMsg<TALON_Status_3_Enc_100ms_t		> rx = GetRx<TALON_Status_3_Enc_100ms_t>(STATUS_3		  | GetDeviceNumber(), EXPECTED_RESPONSE_TIMEOUT_MS)

+#define GET_STATUS4() CtreCanNode::recMsg<TALON_Status_4_AinTempVbat_100ms_t> rx = GetRx<TALON_Status_4_AinTempVbat_100ms_t>(STATUS_4 | GetDeviceNumber(), EXPECTED_RESPONSE_TIMEOUT_MS)

+#define GET_STATUS5() CtreCanNode::recMsg<TALON_Status_5_Startup_OneShot_t	> rx = GetRx<TALON_Status_5_Startup_OneShot_t>(STATUS_5	  | GetDeviceNumber(), EXPECTED_RESPONSE_TIMEOUT_MS)

+#define GET_STATUS6() CtreCanNode::recMsg<TALON_Status_6_Eol_t				> rx = GetRx<TALON_Status_6_Eol_t>(STATUS_6				  | GetDeviceNumber(), EXPECTED_RESPONSE_TIMEOUT_MS)

+#define GET_STATUS7() CtreCanNode::recMsg<TALON_Status_7_Debug_200ms_t		> rx = GetRx<TALON_Status_7_Debug_200ms_t>(STATUS_7		  | GetDeviceNumber(), EXPECTED_RESPONSE_TIMEOUT_MS)

+

+#define PARAM_REQUEST 		0x02041800

+#define PARAM_RESPONSE 		0x02041840

+#define PARAM_SET			0x02041880

+

+const int kParamArbIdValue = 	PARAM_RESPONSE;

+const int kParamArbIdMask = 	0xFFFFFFFF;

+

+const double FLOAT_TO_FXP = (double)0x400000;

+const double FXP_TO_FLOAT = 0.0000002384185791015625;

+

+/* encoder/decoders */

+/** control */

+typedef struct _TALON_Control_1_General_10ms_t {

+	unsigned TokenH:8;

+	unsigned TokenL:8;

+	unsigned DemandH:8;

+	unsigned DemandM:8;

+	unsigned DemandL:8;

+	unsigned ProfileSlotSelect:1;

+	unsigned FeedbackDeviceSelect:4;

+	unsigned OverrideLimitSwitchEn:3;

+	unsigned RevFeedbackSensor:1;

+	unsigned RevMotDuringCloseLoopEn:1;

+	unsigned OverrideBrakeType:2;

+	unsigned ModeSelect:4;

+	unsigned RampThrottle:8;

+} TALON_Control_1_General_10ms_t ;

+typedef struct _TALON_Control_2_Rates_OneShot_t {

+	unsigned Status1Ms:8;

+	unsigned Status2Ms:8;

+	unsigned Status3Ms:8;

+	unsigned Status4Ms:8;

+} TALON_Control_2_Rates_OneShot_t ;

+typedef struct _TALON_Control_3_ClearFlags_OneShot_t {

+	unsigned ZeroFeedbackSensor:1;

+	unsigned ClearStickyFaults:1;

+} TALON_Control_3_ClearFlags_OneShot_t ;

+

+/** status */

+typedef struct _TALON_Status_1_General_10ms_t {

+	unsigned CloseLoopErrH:8;

+	unsigned CloseLoopErrM:8;

+	unsigned CloseLoopErrL:8;

+	unsigned AppliedThrottle_h3:3;

+	unsigned Fault_RevSoftLim:1;

+	unsigned Fault_ForSoftLim:1;

+	unsigned TokLocked:1;

+	unsigned LimitSwitchClosedRev:1;

+	unsigned LimitSwitchClosedFor:1;

+	unsigned AppliedThrottle_l8:8;

+	unsigned ModeSelect_h1:1;

+	unsigned FeedbackDeviceSelect:4;

+	unsigned LimitSwitchEn:3;

+	unsigned Fault_HardwareFailure:1;

+	unsigned Fault_RevLim:1;

+	unsigned Fault_ForLim:1;

+	unsigned Fault_UnderVoltage:1;

+	unsigned Fault_OverTemp:1;

+	unsigned ModeSelect_b3:3;

+	unsigned TokenSeed:8;

+} TALON_Status_1_General_10ms_t ;

+typedef struct _TALON_Status_2_Feedback_20ms_t {

+	unsigned SensorPositionH:8;

+	unsigned SensorPositionM:8;

+	unsigned SensorPositionL:8;

+	unsigned SensorVelocityH:8;

+	unsigned SensorVelocityL:8;

+	unsigned Current_h8:8;

+	unsigned StckyFault_RevSoftLim:1;

+	unsigned StckyFault_ForSoftLim:1;

+	unsigned StckyFault_RevLim:1;

+	unsigned StckyFault_ForLim:1;

+	unsigned StckyFault_UnderVoltage:1;

+	unsigned StckyFault_OverTemp:1;

+	unsigned Current_l2:2;

+	unsigned reserved:6;

+	unsigned ProfileSlotSelect:1;

+	unsigned BrakeIsEnabled:1;

+} TALON_Status_2_Feedback_20ms_t ;

+typedef struct _TALON_Status_3_Enc_100ms_t {

+	unsigned EncPositionH:8;

+	unsigned EncPositionM:8;

+	unsigned EncPositionL:8;

+	unsigned EncVelH:8;

+	unsigned EncVelL:8;

+	unsigned EncIndexRiseEventsH:8;

+	unsigned EncIndexRiseEventsL:8;

+	unsigned reserved:5;

+	unsigned QuadIdxpin:1;

+	unsigned QuadBpin:1;

+	unsigned QuadApin:1;

+} TALON_Status_3_Enc_100ms_t ;

+typedef struct _TALON_Status_4_AinTempVbat_100ms_t {

+	unsigned AnalogInWithOvH:8;

+	unsigned AnalogInWithOvM:8;

+	unsigned AnalogInWithOvL:8;

+	unsigned AnalogInVelH:8;

+	unsigned AnalogInVelL:8;

+	unsigned Temp:8;

+	unsigned BatteryV:8;

+	unsigned reserved:8;

+} TALON_Status_4_AinTempVbat_100ms_t ;

+typedef struct _TALON_Status_5_Startup_OneShot_t {

+	unsigned ResetCountH:8;

+	unsigned ResetCountL:8;

+	unsigned ResetFlagsH:8;

+	unsigned ResetFlagsL:8;

+	unsigned FirmVersH:8;

+	unsigned FirmVersL:8;

+} TALON_Status_5_Startup_OneShot_t ;

+typedef struct _TALON_Status_6_Eol_t {

+	unsigned currentAdcUncal_h2:2;

+	unsigned reserved1:5;

+	unsigned SpiCsPin_GadgeteerPin6:1;

+	unsigned currentAdcUncal_l8:8;

+	unsigned tempAdcUncal_h2:2;

+	unsigned reserved2:6;

+	unsigned tempAdcUncal_l8:8;

+	unsigned vbatAdcUncal_h2:2;

+	unsigned reserved3:6;

+	unsigned vbatAdcUncal_l8:8;

+	unsigned analogAdcUncal_h2:2;

+	unsigned reserved4:6;

+	unsigned analogAdcUncal_l8:8;

+} TALON_Status_6_Eol_t ;

+typedef struct _TALON_Status_7_Debug_200ms_t {

+	unsigned TokenizationFails_h8:8;

+	unsigned TokenizationFails_l8:8;

+	unsigned LastFailedToken_h8:8;

+	unsigned LastFailedToken_l8:8;

+	unsigned TokenizationSucceses_h8:8;

+	unsigned TokenizationSucceses_l8:8;

+} TALON_Status_7_Debug_200ms_t ;

+typedef struct _TALON_Param_Request_t {

+	unsigned ParamEnum:8;

+} TALON_Param_Request_t ;

+typedef struct _TALON_Param_Response_t {

+	unsigned ParamEnum:8;

+	unsigned ParamValueL:8;

+	unsigned ParamValueML:8;

+	unsigned ParamValueMH:8;

+	unsigned ParamValueH:8;

+} TALON_Param_Response_t ;

+

+

+CanTalonSRX::CanTalonSRX(int deviceNumber,int controlPeriodMs): CtreCanNode(deviceNumber), _can_h(0), _can_stat(0)

+{

+	/* bound period to be within [1 ms,95 ms] */

+	if(controlPeriodMs < 1)

+		controlPeriodMs = 1;

+	else if(controlPeriodMs > 95)

+		controlPeriodMs = 95;

+	RegisterRx(STATUS_1 | (UINT8)deviceNumber );

+	RegisterRx(STATUS_2 | (UINT8)deviceNumber );

+	RegisterRx(STATUS_3 | (UINT8)deviceNumber );

+	RegisterRx(STATUS_4 | (UINT8)deviceNumber );

+	RegisterRx(STATUS_5 | (UINT8)deviceNumber );

+	RegisterRx(STATUS_6 | (UINT8)deviceNumber );

+	RegisterRx(STATUS_7 | (UINT8)deviceNumber );

+	RegisterTx(CONTROL_1 | (UINT8)deviceNumber, (UINT8)controlPeriodMs);

+	/* default our frame rate table to what firmware defaults to. */

+	_statusRateMs[0] = 10;	/* 	TALON_Status_1_General_10ms_t 		*/

+	_statusRateMs[1] = 20;	/* 	TALON_Status_2_Feedback_20ms_t 		*/

+	_statusRateMs[2] = 100;	/* 	TALON_Status_3_Enc_100ms_t 			*/

+	_statusRateMs[3] = 100;	/* 	TALON_Status_4_AinTempVbat_100ms_t 	*/

+	/* the only default param that is nonzero is limit switch.

+	 * Default to using the flash settings. */

+	SetOverrideLimitSwitchEn(kLimitSwitchOverride_UseDefaultsFromFlash);

+}

+/* CanTalonSRX D'tor

+ */

+CanTalonSRX::~CanTalonSRX()

+{

+	if(_can_h){

+		FRC_NetworkCommunication_CANSessionMux_closeStreamSession(_can_h);

+		_can_h = 0;

+	}

+}

+void CanTalonSRX::OpenSessionIfNeedBe()

+{

+	_can_stat = 0;

+	if (_can_h == 0) {

+		/* bit30 - bit8 must match $000002XX.  Top bit is not masked to get remote frames */

+		FRC_NetworkCommunication_CANSessionMux_openStreamSession(&_can_h,kParamArbIdValue | GetDeviceNumber(), kParamArbIdMask, kMsgCapacity, &_can_stat);

+		if (_can_stat == 0) {

+			/* success */

+		} else {

+			/* something went wrong, try again later */

+			_can_h = 0;

+		}

+	}

+}

+void CanTalonSRX::ProcessStreamMessages()

+{

+	if(0 == _can_h)

+		OpenSessionIfNeedBe();

+	/* process receive messages */

+	uint32_t i;

+	uint32_t messagesToRead = sizeof(_msgBuff) / sizeof(_msgBuff[0]);

+	uint32_t messagesRead = 0;

+	/* read out latest bunch of messages */

+	_can_stat = 0;

+	if (_can_h){

+		FRC_NetworkCommunication_CANSessionMux_readStreamSession(_can_h,_msgBuff, messagesToRead, &messagesRead, &_can_stat);

+	}

+	/* loop thru each message of interest */

+	for (i = 0; i < messagesRead; ++i) {

+		tCANStreamMessage * msg = _msgBuff + i;

+		if(msg->messageID == (PARAM_RESPONSE | GetDeviceNumber()) ){

+			TALON_Param_Response_t * paramResp = (TALON_Param_Response_t*)msg->data;

+			/* decode value */

+			int32_t val = paramResp->ParamValueH;

+			val <<= 8;

+			val |=  paramResp->ParamValueMH;

+			val <<= 8;

+			val |=  paramResp->ParamValueML;

+			val <<= 8;

+			val |=  paramResp->ParamValueL;

+			/* save latest signal */

+			_sigs[paramResp->ParamEnum] = val;

+		}else{

+			int brkpthere = 42;

+			++brkpthere;

+		}

+	}

+}

+void CanTalonSRX::Set(double value)

+{

+	if(value > 1)

+		value = 1;

+	else if(value < -1)

+		value = -1;

+	SetDemand(1023*value); /* must be within [-1023,1023] */

+}

+/*---------------------setters and getters that use the param request/response-------------*/

+/**

+ * Send a one shot frame to set an arbitrary signal.

+ * Most signals are in the control frame so avoid using this API unless you have to.

+ * Use this api for...

+ * -A motor controller profile signal eProfileParam_XXXs.  These are backed up in flash.  If you are gain-scheduling then call this periodically.

+ * -Default brake and limit switch signals... eOnBoot_XXXs.  Avoid doing this, use the override signals in the control frame.

+ * Talon will automatically send a PARAM_RESPONSE after the set, so GetParamResponse will catch the latest value after a couple ms.

+ */

+CTR_Code CanTalonSRX::SetParamRaw(unsigned paramEnum, int rawBits)

+{

+	/* caller is using param API.  Open session if it hasn'T been done. */

+	if(0 == _can_h)

+		OpenSessionIfNeedBe();

+	TALON_Param_Response_t frame;

+	memset(&frame,0,sizeof(frame));

+	frame.ParamEnum = paramEnum;

+	frame.ParamValueH = rawBits >> 0x18;

+	frame.ParamValueMH = rawBits >> 0x10;

+	frame.ParamValueML = rawBits >> 0x08;

+	frame.ParamValueL = rawBits;

+	int32_t status = 0;

+	FRC_NetworkCommunication_CANSessionMux_sendMessage(PARAM_SET | GetDeviceNumber(), (const uint8_t*)&frame, 5, 0, &status);

+	if(status)

+		return CTR_TxFailed;

+	return CTR_OKAY;

+}

+/**

+ * Checks cached CAN frames and updating solicited signals.

+ */

+CTR_Code CanTalonSRX::GetParamResponseRaw(unsigned paramEnum, int & rawBits)

+{

+	CTR_Code retval = CTR_OKAY;

+	/* process received param events. We don't expect many since this API is not used often. */

+	ProcessStreamMessages();

+	/* grab the solicited signal value */

+	sigs_t::iterator i = _sigs.find(paramEnum);

+	if(i == _sigs.end()){

+		retval = CTR_SigNotUpdated;

+	}else{

+		rawBits = i->second;

+	}

+	return retval;

+}

+/**

+ * Asks TALON to immedietely respond with signal value.  This API is only used for signals that are not sent periodically.

+ * This can be useful for reading params that rarely change like Limit Switch settings and PIDF values.

+  * @param param to request.

+ */

+CTR_Code CanTalonSRX::RequestParam(param_t paramEnum)

+{

+	/* process received param events. We don't expect many since this API is not used often. */

+	ProcessStreamMessages();

+	TALON_Param_Request_t frame;

+	memset(&frame,0,sizeof(frame));

+	frame.ParamEnum = paramEnum;

+	int32_t status = 0;

+	FRC_NetworkCommunication_CANSessionMux_sendMessage(PARAM_REQUEST | GetDeviceNumber(), (const uint8_t*)&frame, 1, 0, &status);

+	if(status)

+		return CTR_TxFailed;

+	return CTR_OKAY;

+}

+

+CTR_Code CanTalonSRX::SetParam(param_t paramEnum, double value)

+{

+	int32_t rawbits = 0;

+	switch(paramEnum){

+		case eProfileParamSlot0_P:/* unsigned 10.22 fixed pt value */

+		case eProfileParamSlot0_I:

+		case eProfileParamSlot0_D:

+		case eProfileParamSlot1_P:

+		case eProfileParamSlot1_I:

+		case eProfileParamSlot1_D:

+		{

+			uint32_t urawbits;

+			value = std::min(value,1023.0); /* bounds check doubles that are outside u10.22 */

+			value = std::max(value,0.0);

+			urawbits = value * FLOAT_TO_FXP; /* perform unsign arithmetic */

+			rawbits = urawbits; /* copy bits over.  SetParamRaw just stuffs into CAN frame with no sense of signedness */

+		}	break;

+		case eProfileParamSlot1_F:	/* signed 10.22 fixed pt value */

+		case eProfileParamSlot0_F:

+			value = std::min(value, 512.0); /* bounds check doubles that are outside s10.22 */

+			value = std::max(value,-512.0);

+			rawbits = value * FLOAT_TO_FXP;

+			break;

+		default: /* everything else is integral */

+			rawbits = (int32_t)value;

+			break;

+	}

+	return SetParamRaw(paramEnum,rawbits);

+}

+CTR_Code CanTalonSRX::GetParamResponse(param_t paramEnum, double & value)

+{

+	int32_t rawbits = 0;

+	CTR_Code retval = GetParamResponseRaw(paramEnum,rawbits);

+	switch(paramEnum){

+		case eProfileParamSlot0_P:/* 10.22 fixed pt value */

+		case eProfileParamSlot0_I:

+		case eProfileParamSlot0_D:

+		case eProfileParamSlot0_F:

+		case eProfileParamSlot1_P:

+		case eProfileParamSlot1_I:

+		case eProfileParamSlot1_D:

+		case eProfileParamSlot1_F:

+		case eCurrent:

+		case eTemp:

+		case eBatteryV:

+			value = ((double)rawbits) * FXP_TO_FLOAT;

+			break;

+		default: /* everything else is integral */

+			value = (double)rawbits;

+			break;

+	}

+	return retval;

+}

+CTR_Code CanTalonSRX::GetParamResponseInt32(param_t paramEnum, int & value)

+{

+	double dvalue = 0;

+	CTR_Code retval = GetParamResponse(paramEnum, dvalue);

+	value = (int32_t)dvalue;

+	return retval;

+}

+/*----- getters and setters that use param request/response. These signals are backed up in flash and will survive a power cycle. ---------*/

+/*----- If your application requires changing these values consider using both slots and switch between slot0 <=> slot1. ------------------*/

+/*----- If your application requires changing these signals frequently then it makes sense to leverage this API. --------------------------*/

+/*----- Getters don't block, so it may require several calls to get the latest value. --------------------------*/

+CTR_Code CanTalonSRX::SetPgain(unsigned slotIdx,double gain)

+{

+	if(slotIdx == 0)

+		return SetParam(eProfileParamSlot0_P, gain);

+	return SetParam(eProfileParamSlot1_P, gain);

+}

+CTR_Code CanTalonSRX::SetIgain(unsigned slotIdx,double gain)

+{

+	if(slotIdx == 0)

+		return SetParam(eProfileParamSlot0_I, gain);

+	return SetParam(eProfileParamSlot1_I, gain);

+}

+CTR_Code CanTalonSRX::SetDgain(unsigned slotIdx,double gain)

+{

+	if(slotIdx == 0)

+		return SetParam(eProfileParamSlot0_D, gain);

+	return SetParam(eProfileParamSlot1_D, gain);

+}

+CTR_Code CanTalonSRX::SetFgain(unsigned slotIdx,double gain)

+{

+	if(slotIdx == 0)

+		return SetParam(eProfileParamSlot0_F, gain);

+	return SetParam(eProfileParamSlot1_F, gain);

+}

+CTR_Code CanTalonSRX::SetIzone(unsigned slotIdx,int zone)

+{

+	if(slotIdx == 0)

+		return SetParam(eProfileParamSlot0_IZone, zone);

+	return SetParam(eProfileParamSlot1_IZone, zone);

+}

+CTR_Code CanTalonSRX::SetCloseLoopRampRate(unsigned slotIdx,int closeLoopRampRate)

+{

+	if(slotIdx == 0)

+		return SetParam(eProfileParamSlot0_CloseLoopRampRate, closeLoopRampRate);

+	return SetParam(eProfileParamSlot1_CloseLoopRampRate, closeLoopRampRate);

+}

+CTR_Code CanTalonSRX::GetPgain(unsigned slotIdx,double & gain)

+{

+	if(slotIdx == 0)

+		return GetParamResponse(eProfileParamSlot0_P, gain);

+	return GetParamResponse(eProfileParamSlot1_P, gain);

+}

+CTR_Code CanTalonSRX::GetIgain(unsigned slotIdx,double & gain)

+{

+	if(slotIdx == 0)

+		return GetParamResponse(eProfileParamSlot0_I, gain);

+	return GetParamResponse(eProfileParamSlot1_I, gain);

+}

+CTR_Code CanTalonSRX::GetDgain(unsigned slotIdx,double & gain)

+{

+	if(slotIdx == 0)

+		return GetParamResponse(eProfileParamSlot0_D, gain);

+	return GetParamResponse(eProfileParamSlot1_D, gain);

+}

+CTR_Code CanTalonSRX::GetFgain(unsigned slotIdx,double & gain)

+{

+	if(slotIdx == 0)

+		return GetParamResponse(eProfileParamSlot0_F, gain);

+	return GetParamResponse(eProfileParamSlot1_F, gain);

+}

+CTR_Code CanTalonSRX::GetIzone(unsigned slotIdx,int & zone)

+{

+	if(slotIdx == 0)

+		return GetParamResponseInt32(eProfileParamSlot0_IZone, zone);

+	return GetParamResponseInt32(eProfileParamSlot1_IZone, zone);

+}

+CTR_Code CanTalonSRX::GetCloseLoopRampRate(unsigned slotIdx,int & closeLoopRampRate)

+{

+	if(slotIdx == 0)

+		return GetParamResponseInt32(eProfileParamSlot0_CloseLoopRampRate, closeLoopRampRate);

+	return GetParamResponseInt32(eProfileParamSlot1_CloseLoopRampRate, closeLoopRampRate);

+}

+

+CTR_Code CanTalonSRX::SetSensorPosition(int pos)

+{

+	return SetParam(eSensorPosition, pos);

+}

+CTR_Code CanTalonSRX::SetForwardSoftLimit(int forwardLimit)

+{

+	return SetParam(eProfileParamSoftLimitForThreshold, forwardLimit);

+}

+CTR_Code CanTalonSRX::SetReverseSoftLimit(int reverseLimit)

+{

+	return SetParam(eProfileParamSoftLimitRevThreshold, reverseLimit);

+}

+CTR_Code CanTalonSRX::SetForwardSoftEnable(int enable)

+{

+	return SetParam(eProfileParamSoftLimitForEnable, enable);

+}

+CTR_Code CanTalonSRX::SetReverseSoftEnable(int enable)

+{

+	return SetParam(eProfileParamSoftLimitRevEnable, enable);

+}

+CTR_Code CanTalonSRX::GetForwardSoftLimit(int & forwardLimit)

+{

+	return GetParamResponseInt32(eProfileParamSoftLimitForThreshold, forwardLimit);

+}

+CTR_Code CanTalonSRX::GetReverseSoftLimit(int & reverseLimit)

+{

+	return GetParamResponseInt32(eProfileParamSoftLimitRevThreshold, reverseLimit);

+}

+CTR_Code CanTalonSRX::GetForwardSoftEnable(int & enable)

+{

+	return GetParamResponseInt32(eProfileParamSoftLimitForEnable, enable);

+}

+CTR_Code CanTalonSRX::GetReverseSoftEnable(int & enable)

+{

+	return GetParamResponseInt32(eProfileParamSoftLimitRevEnable, enable);

+}

+/**

+ * Change the periodMs of a TALON's status frame.  See kStatusFrame_* enums for what's available.

+ */

+CTR_Code CanTalonSRX::SetStatusFrameRate(unsigned frameEnum, unsigned periodMs)

+{

+	int32_t status = 0;

+	/* bounds check the period */

+	if(periodMs < 1)

+		periodMs = 1;

+	else if (periodMs > 255)

+		periodMs = 255;

+  uint8_t period = (uint8_t)periodMs;

+	/* tweak just the status messsage rate the caller cares about */

+	switch(frameEnum){

+		case kStatusFrame_General:

+			_statusRateMs[0] = period;

+			break;

+		case kStatusFrame_Feedback:

+			_statusRateMs[1] = period;

+			break;

+		case kStatusFrame_Encoder:

+			_statusRateMs[2] = period;

+			break;

+		case kStatusFrame_AnalogTempVbat:

+			_statusRateMs[3] = period;

+			break;

+	}

+	/* build our request frame */

+	TALON_Control_2_Rates_OneShot_t frame;

+	memset(&frame,0,sizeof(frame));

+	frame.Status1Ms = _statusRateMs[0];

+	frame.Status2Ms = _statusRateMs[1];

+	frame.Status3Ms = _statusRateMs[2];

+	frame.Status4Ms = _statusRateMs[3];

+	FRC_NetworkCommunication_CANSessionMux_sendMessage(CONTROL_2 | GetDeviceNumber(), (const uint8_t*)&frame, sizeof(frame), 0, &status);

+	if(status)

+		return CTR_TxFailed;

+	return CTR_OKAY;

+}

+/**

+ * Clear all sticky faults in TALON.

+ */

+CTR_Code CanTalonSRX::ClearStickyFaults()

+{

+	int32_t status = 0;

+	/* build request frame */

+	TALON_Control_3_ClearFlags_OneShot_t frame;

+	memset(&frame,0,sizeof(frame));

+	frame.ClearStickyFaults = 1;

+	FRC_NetworkCommunication_CANSessionMux_sendMessage(CONTROL_3 | GetDeviceNumber(), (const uint8_t*)&frame, sizeof(frame), 0, &status);

+	if(status)

+		return CTR_TxFailed;

+	return CTR_OKAY;

+}

+/*------------------------ auto generated.  This API is optimal since it uses the fire-and-forget CAN interface ----------------------*/

+/*------------------------ These signals should cover the majority of all use cases. ----------------------------------*/

+CTR_Code CanTalonSRX::GetFault_OverTemp(int &param)

+{

+	GET_STATUS1();

+	param = rx->Fault_OverTemp;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetFault_UnderVoltage(int &param)

+{

+	GET_STATUS1();

+	param = rx->Fault_UnderVoltage;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetFault_ForLim(int &param)

+{

+	GET_STATUS1();

+	param = rx->Fault_ForLim;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetFault_RevLim(int &param)

+{

+	GET_STATUS1();

+	param = rx->Fault_RevLim;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetFault_HardwareFailure(int &param)

+{

+	GET_STATUS1();

+	param = rx->Fault_HardwareFailure;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetFault_ForSoftLim(int &param)

+{

+	GET_STATUS1();

+	param = rx->Fault_ForSoftLim;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetFault_RevSoftLim(int &param)

+{

+	GET_STATUS1();

+	param = rx->Fault_RevSoftLim;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetStckyFault_OverTemp(int &param)

+{

+	GET_STATUS2();

+	param = rx->StckyFault_OverTemp;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetStckyFault_UnderVoltage(int &param)

+{

+	GET_STATUS2();

+	param = rx->StckyFault_UnderVoltage;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetStckyFault_ForLim(int &param)

+{

+	GET_STATUS2();

+	param = rx->StckyFault_ForLim;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetStckyFault_RevLim(int &param)

+{

+	GET_STATUS2();

+	param = rx->StckyFault_RevLim;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetStckyFault_ForSoftLim(int &param)

+{

+	GET_STATUS2();

+	param = rx->StckyFault_ForSoftLim;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetStckyFault_RevSoftLim(int &param)

+{

+	GET_STATUS2();

+	param = rx->StckyFault_RevSoftLim;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetAppliedThrottle(int &param)

+{

+	GET_STATUS1();

+	int32_t raw = 0;

+	raw |= rx->AppliedThrottle_h3;

+	raw <<= 8;

+	raw |= rx->AppliedThrottle_l8;

+	raw <<= (32-11); /* sign extend */

+	raw >>= (32-11); /* sign extend */

+	param = (int)raw;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetCloseLoopErr(int &param)

+{

+	GET_STATUS1();

+	int32_t raw = 0;

+	raw |= rx->CloseLoopErrH;

+	raw <<= 8;

+	raw |= rx->CloseLoopErrM;

+	raw <<= 8;

+	raw |= rx->CloseLoopErrL;

+	raw <<= (32-24); /* sign extend */

+	raw >>= (32-24); /* sign extend */

+	param = (int)raw;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetFeedbackDeviceSelect(int &param)

+{

+	GET_STATUS1();

+	param = rx->FeedbackDeviceSelect;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetModeSelect(int &param)

+{

+	GET_STATUS1();

+	uint32_t raw = 0;

+	raw |= rx->ModeSelect_h1;

+	raw <<= 3;

+	raw |= rx->ModeSelect_b3;

+	param = (int)raw;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetLimitSwitchEn(int &param)

+{

+	GET_STATUS1();

+	param = rx->LimitSwitchEn;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetLimitSwitchClosedFor(int &param)

+{

+	GET_STATUS1();

+	param = rx->LimitSwitchClosedFor;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetLimitSwitchClosedRev(int &param)

+{

+	GET_STATUS1();

+	param = rx->LimitSwitchClosedRev;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetSensorPosition(int &param)

+{

+	GET_STATUS2();

+	int32_t raw = 0;

+	raw |= rx->SensorPositionH;

+	raw <<= 8;

+	raw |= rx->SensorPositionM;

+	raw <<= 8;

+	raw |= rx->SensorPositionL;

+	raw <<= (32-24); /* sign extend */

+	raw >>= (32-24); /* sign extend */

+	param = (int)raw;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetSensorVelocity(int &param)

+{

+	GET_STATUS2();

+	int32_t raw = 0;

+	raw |= rx->SensorVelocityH;

+	raw <<= 8;

+	raw |= rx->SensorVelocityL;

+	raw <<= (32-16); /* sign extend */

+	raw >>= (32-16); /* sign extend */

+	param = (int)raw;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetCurrent(double &param)

+{

+	GET_STATUS2();

+	uint32_t raw = 0;

+	raw |= rx->Current_h8;

+	raw <<= 2;

+	raw |= rx->Current_l2;

+	param = (double)raw * 0.125 + 0;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetBrakeIsEnabled(int &param)

+{

+	GET_STATUS2();

+	param = rx->BrakeIsEnabled;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetEncPosition(int &param)

+{

+	GET_STATUS3();

+	int32_t raw = 0;

+	raw |= rx->EncPositionH;

+	raw <<= 8;

+	raw |= rx->EncPositionM;

+	raw <<= 8;

+	raw |= rx->EncPositionL;

+	raw <<= (32-24); /* sign extend */

+	raw >>= (32-24); /* sign extend */

+	param = (int)raw;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetEncVel(int &param)

+{

+	GET_STATUS3();

+	int32_t raw = 0;

+	raw |= rx->EncVelH;

+	raw <<= 8;

+	raw |= rx->EncVelL;

+	raw <<= (32-16); /* sign extend */

+	raw >>= (32-16); /* sign extend */

+	param = (int)raw;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetEncIndexRiseEvents(int &param)

+{

+	GET_STATUS3();

+	uint32_t raw = 0;

+	raw |= rx->EncIndexRiseEventsH;

+	raw <<= 8;

+	raw |= rx->EncIndexRiseEventsL;

+	param = (int)raw;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetQuadApin(int &param)

+{

+	GET_STATUS3();

+	param = rx->QuadApin;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetQuadBpin(int &param)

+{

+	GET_STATUS3();

+	param = rx->QuadBpin;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetQuadIdxpin(int &param)

+{

+	GET_STATUS3();

+	param = rx->QuadIdxpin;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetAnalogInWithOv(int &param)

+{

+	GET_STATUS4();

+	int32_t raw = 0;

+	raw |= rx->AnalogInWithOvH;

+	raw <<= 8;

+	raw |= rx->AnalogInWithOvM;

+	raw <<= 8;

+	raw |= rx->AnalogInWithOvL;

+	raw <<= (32-24); /* sign extend */

+	raw >>= (32-24); /* sign extend */

+	param = (int)raw;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetAnalogInVel(int &param)

+{

+	GET_STATUS4();

+	int32_t raw = 0;

+	raw |= rx->AnalogInVelH;

+	raw <<= 8;

+	raw |= rx->AnalogInVelL;

+	raw <<= (32-16); /* sign extend */

+	raw >>= (32-16); /* sign extend */

+	param = (int)raw;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetTemp(double &param)

+{

+	GET_STATUS4();

+	uint32_t raw = rx->Temp;

+	param = (double)raw * 0.6451612903 + -50;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetBatteryV(double &param)

+{

+	GET_STATUS4();

+	uint32_t raw = rx->BatteryV;

+	param = (double)raw * 0.05 + 4;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetResetCount(int &param)

+{

+	GET_STATUS5();

+	uint32_t raw = 0;

+	raw |= rx->ResetCountH;

+	raw <<= 8;

+	raw |= rx->ResetCountL;

+	param = (int)raw;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetResetFlags(int &param)

+{

+	GET_STATUS5();

+	uint32_t raw = 0;

+	raw |= rx->ResetFlagsH;

+	raw <<= 8;

+	raw |= rx->ResetFlagsL;

+	param = (int)raw;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::GetFirmVers(int &param)

+{

+	GET_STATUS5();

+	uint32_t raw = 0;

+	raw |= rx->FirmVersH;

+	raw <<= 8;

+	raw |= rx->FirmVersL;

+	param = (int)raw;

+	return rx.err;

+}

+CTR_Code CanTalonSRX::SetDemand(int param)

+{

+	CtreCanNode::txTask<TALON_Control_1_General_10ms_t> toFill = GetTx<TALON_Control_1_General_10ms_t>(CONTROL_1 | GetDeviceNumber());

+	if (toFill.IsEmpty()) return CTR_UnexpectedArbId;

+	toFill->DemandH = param>>16;

+	toFill->DemandM = param>>8;

+	toFill->DemandL = param>>0;

+	FlushTx(toFill);

+	return CTR_OKAY;

+}

+CTR_Code CanTalonSRX::SetOverrideLimitSwitchEn(int param)

+{

+	CtreCanNode::txTask<TALON_Control_1_General_10ms_t> toFill = GetTx<TALON_Control_1_General_10ms_t>(CONTROL_1 | GetDeviceNumber());

+	if (toFill.IsEmpty()) return CTR_UnexpectedArbId;

+	toFill->OverrideLimitSwitchEn = param;

+	FlushTx(toFill);

+	return CTR_OKAY;

+}

+CTR_Code CanTalonSRX::SetFeedbackDeviceSelect(int param)

+{

+	CtreCanNode::txTask<TALON_Control_1_General_10ms_t> toFill = GetTx<TALON_Control_1_General_10ms_t>(CONTROL_1 | GetDeviceNumber());

+	if (toFill.IsEmpty()) return CTR_UnexpectedArbId;

+	toFill->FeedbackDeviceSelect = param;

+	FlushTx(toFill);

+	return CTR_OKAY;

+}

+CTR_Code CanTalonSRX::SetRevMotDuringCloseLoopEn(int param)

+{

+	CtreCanNode::txTask<TALON_Control_1_General_10ms_t> toFill = GetTx<TALON_Control_1_General_10ms_t>(CONTROL_1 | GetDeviceNumber());

+	if (toFill.IsEmpty()) return CTR_UnexpectedArbId;

+	toFill->RevMotDuringCloseLoopEn = param;

+	FlushTx(toFill);

+	return CTR_OKAY;

+}

+CTR_Code CanTalonSRX::SetOverrideBrakeType(int param)

+{

+	CtreCanNode::txTask<TALON_Control_1_General_10ms_t> toFill = GetTx<TALON_Control_1_General_10ms_t>(CONTROL_1 | GetDeviceNumber());

+	if (toFill.IsEmpty()) return CTR_UnexpectedArbId;

+	toFill->OverrideBrakeType = param;

+	FlushTx(toFill);

+	return CTR_OKAY;

+}

+CTR_Code CanTalonSRX::SetModeSelect(int param)

+{

+	CtreCanNode::txTask<TALON_Control_1_General_10ms_t> toFill = GetTx<TALON_Control_1_General_10ms_t>(CONTROL_1 | GetDeviceNumber());

+	if (toFill.IsEmpty()) return CTR_UnexpectedArbId;

+	toFill->ModeSelect = param;

+	FlushTx(toFill);

+	return CTR_OKAY;

+}

+/**

+ * @param modeSelect selects which mode.

+ * @param demand setpt or throttle or masterId to follow.

+ * @return error code, 0 iff successful.

+ * This function has the advantage of atomically setting mode and demand.

+ */

+CTR_Code CanTalonSRX::SetModeSelect(int modeSelect,int demand)

+{

+	CtreCanNode::txTask<TALON_Control_1_General_10ms_t> toFill = GetTx<TALON_Control_1_General_10ms_t>(CONTROL_1 | GetDeviceNumber());

+	if (toFill.IsEmpty()) return CTR_UnexpectedArbId;

+	toFill->ModeSelect = modeSelect;

+	toFill->DemandH = demand>>16;

+	toFill->DemandM = demand>>8;

+	toFill->DemandL = demand>>0;

+	FlushTx(toFill);

+	return CTR_OKAY;

+}

+CTR_Code CanTalonSRX::SetProfileSlotSelect(int param)

+{

+	CtreCanNode::txTask<TALON_Control_1_General_10ms_t> toFill = GetTx<TALON_Control_1_General_10ms_t>(CONTROL_1 | GetDeviceNumber());

+	if (toFill.IsEmpty()) return CTR_UnexpectedArbId;

+	toFill->ProfileSlotSelect = param;

+	FlushTx(toFill);

+	return CTR_OKAY;

+}

+CTR_Code CanTalonSRX::SetRampThrottle(int param)

+{

+	CtreCanNode::txTask<TALON_Control_1_General_10ms_t> toFill = GetTx<TALON_Control_1_General_10ms_t>(CONTROL_1 | GetDeviceNumber());

+	if (toFill.IsEmpty()) return CTR_UnexpectedArbId;

+	toFill->RampThrottle = param;

+	FlushTx(toFill);

+	return CTR_OKAY;

+}

+CTR_Code CanTalonSRX::SetRevFeedbackSensor(int param)

+{

+	CtreCanNode::txTask<TALON_Control_1_General_10ms_t> toFill = GetTx<TALON_Control_1_General_10ms_t>(CONTROL_1 | GetDeviceNumber());

+	if (toFill.IsEmpty()) return CTR_UnexpectedArbId;

+	toFill->RevFeedbackSensor = param ? 1 : 0;

+	FlushTx(toFill);

+	return CTR_OKAY;

+}

+//------------------ C interface --------------------------------------------//

+extern "C" {

+void *c_TalonSRX_Create(int deviceNumber, int controlPeriodMs)

+{

+	return new CanTalonSRX(deviceNumber, controlPeriodMs);

+}

+void c_TalonSRX_Destroy(void *handle)

+{

+	delete (CanTalonSRX*)handle;

+}

+CTR_Code c_TalonSRX_SetParam(void *handle, int paramEnum, double value)

+{

+	return ((CanTalonSRX*)handle)->SetParam((CanTalonSRX::param_t)paramEnum, value);

+}

+CTR_Code c_TalonSRX_RequestParam(void *handle, int paramEnum)

+{

+	return ((CanTalonSRX*)handle)->RequestParam((CanTalonSRX::param_t)paramEnum);

+}

+CTR_Code c_TalonSRX_GetParamResponse(void *handle, int paramEnum, double *value)

+{

+	return ((CanTalonSRX*)handle)->GetParamResponse((CanTalonSRX::param_t)paramEnum, *value);

+}

+CTR_Code c_TalonSRX_GetParamResponseInt32(void *handle, int paramEnum, int *value)

+{

+	return ((CanTalonSRX*)handle)->GetParamResponseInt32((CanTalonSRX::param_t)paramEnum, *value);

+}

+CTR_Code c_TalonSRX_SetStatusFrameRate(void *handle, unsigned frameEnum, unsigned periodMs)

+{

+	return ((CanTalonSRX*)handle)->SetStatusFrameRate(frameEnum, periodMs);

+}

+CTR_Code c_TalonSRX_ClearStickyFaults(void *handle)

+{

+	return ((CanTalonSRX*)handle)->ClearStickyFaults();

+}

+CTR_Code c_TalonSRX_GetFault_OverTemp(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetFault_OverTemp(*param);

+}

+CTR_Code c_TalonSRX_GetFault_UnderVoltage(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetFault_UnderVoltage(*param);

+}

+CTR_Code c_TalonSRX_GetFault_ForLim(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetFault_ForLim(*param);

+}

+CTR_Code c_TalonSRX_GetFault_RevLim(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetFault_RevLim(*param);

+}

+CTR_Code c_TalonSRX_GetFault_HardwareFailure(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetFault_HardwareFailure(*param);

+}

+CTR_Code c_TalonSRX_GetFault_ForSoftLim(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetFault_ForSoftLim(*param);

+}

+CTR_Code c_TalonSRX_GetFault_RevSoftLim(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetFault_RevSoftLim(*param);

+}

+CTR_Code c_TalonSRX_GetStckyFault_OverTemp(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetStckyFault_OverTemp(*param);

+}

+CTR_Code c_TalonSRX_GetStckyFault_UnderVoltage(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetStckyFault_UnderVoltage(*param);

+}

+CTR_Code c_TalonSRX_GetStckyFault_ForLim(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetStckyFault_ForLim(*param);

+}

+CTR_Code c_TalonSRX_GetStckyFault_RevLim(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetStckyFault_RevLim(*param);

+}

+CTR_Code c_TalonSRX_GetStckyFault_ForSoftLim(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetStckyFault_ForSoftLim(*param);

+}

+CTR_Code c_TalonSRX_GetStckyFault_RevSoftLim(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetStckyFault_RevSoftLim(*param);

+}

+CTR_Code c_TalonSRX_GetAppliedThrottle(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetAppliedThrottle(*param);

+}

+CTR_Code c_TalonSRX_GetCloseLoopErr(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetCloseLoopErr(*param);

+}

+CTR_Code c_TalonSRX_GetFeedbackDeviceSelect(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetFeedbackDeviceSelect(*param);

+}

+CTR_Code c_TalonSRX_GetModeSelect(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetModeSelect(*param);

+}

+CTR_Code c_TalonSRX_GetLimitSwitchEn(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetLimitSwitchEn(*param);

+}

+CTR_Code c_TalonSRX_GetLimitSwitchClosedFor(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetLimitSwitchClosedFor(*param);

+}

+CTR_Code c_TalonSRX_GetLimitSwitchClosedRev(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetLimitSwitchClosedRev(*param);

+}

+CTR_Code c_TalonSRX_GetSensorPosition(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetSensorPosition(*param);

+}

+CTR_Code c_TalonSRX_GetSensorVelocity(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetSensorVelocity(*param);

+}

+CTR_Code c_TalonSRX_GetCurrent(void *handle, double *param)

+{

+	return ((CanTalonSRX*)handle)->GetCurrent(*param);

+}

+CTR_Code c_TalonSRX_GetBrakeIsEnabled(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetBrakeIsEnabled(*param);

+}

+CTR_Code c_TalonSRX_GetEncPosition(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetEncPosition(*param);

+}

+CTR_Code c_TalonSRX_GetEncVel(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetEncVel(*param);

+}

+CTR_Code c_TalonSRX_GetEncIndexRiseEvents(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetEncIndexRiseEvents(*param);

+}

+CTR_Code c_TalonSRX_GetQuadApin(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetQuadApin(*param);

+}

+CTR_Code c_TalonSRX_GetQuadBpin(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetQuadBpin(*param);

+}

+CTR_Code c_TalonSRX_GetQuadIdxpin(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetQuadIdxpin(*param);

+}

+CTR_Code c_TalonSRX_GetAnalogInWithOv(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetAnalogInWithOv(*param);

+}

+CTR_Code c_TalonSRX_GetAnalogInVel(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetAnalogInVel(*param);

+}

+CTR_Code c_TalonSRX_GetTemp(void *handle, double *param)

+{

+	return ((CanTalonSRX*)handle)->GetTemp(*param);

+}

+CTR_Code c_TalonSRX_GetBatteryV(void *handle, double *param)

+{

+	return ((CanTalonSRX*)handle)->GetBatteryV(*param);

+}

+CTR_Code c_TalonSRX_GetResetCount(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetResetCount(*param);

+}

+CTR_Code c_TalonSRX_GetResetFlags(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetResetFlags(*param);

+}

+CTR_Code c_TalonSRX_GetFirmVers(void *handle, int *param)

+{

+	return ((CanTalonSRX*)handle)->GetFirmVers(*param);

+}

+CTR_Code c_TalonSRX_SetDemand(void *handle, int param)

+{

+	return ((CanTalonSRX*)handle)->SetDemand(param);

+}

+CTR_Code c_TalonSRX_SetOverrideLimitSwitchEn(void *handle, int param)

+{

+	return ((CanTalonSRX*)handle)->SetOverrideLimitSwitchEn(param);

+}

+CTR_Code c_TalonSRX_SetFeedbackDeviceSelect(void *handle, int param)

+{

+	return ((CanTalonSRX*)handle)->SetFeedbackDeviceSelect(param);

+}

+CTR_Code c_TalonSRX_SetRevMotDuringCloseLoopEn(void *handle, int param)

+{

+	return ((CanTalonSRX*)handle)->SetRevMotDuringCloseLoopEn(param);

+}

+CTR_Code c_TalonSRX_SetOverrideBrakeType(void *handle, int param)

+{

+	return ((CanTalonSRX*)handle)->SetOverrideBrakeType(param);

+}

+CTR_Code c_TalonSRX_SetModeSelect(void *handle, int param)

+{

+	return ((CanTalonSRX*)handle)->SetModeSelect(param);

+}

+CTR_Code c_TalonSRX_SetModeSelect2(void *handle, int modeSelect, int demand)

+{

+	return ((CanTalonSRX*)handle)->SetModeSelect(modeSelect, demand);

+}

+CTR_Code c_TalonSRX_SetProfileSlotSelect(void *handle, int param)

+{

+	return ((CanTalonSRX*)handle)->SetProfileSlotSelect(param);

+}

+CTR_Code c_TalonSRX_SetRampThrottle(void *handle, int param)

+{

+	return ((CanTalonSRX*)handle)->SetRampThrottle(param);

+}

+CTR_Code c_TalonSRX_SetRevFeedbackSensor(void *handle, int param)

+{

+	return ((CanTalonSRX*)handle)->SetRevFeedbackSensor(param);

+}

+}

diff --git a/aos/externals/allwpilib/hal/lib/Athena/ctre/CanTalonSRX.h b/aos/externals/allwpilib/hal/lib/Athena/ctre/CanTalonSRX.h
new file mode 100644
index 0000000..cc2236b
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/ctre/CanTalonSRX.h
@@ -0,0 +1,375 @@
+/**

+ * @brief CAN TALON SRX driver.

+ *

+ * The TALON SRX is designed to instrument all runtime signals periodically.  The default periods are chosen to support 16 TALONs

+ * with 10ms update rate for control (throttle or setpoint).  However these can be overridden with SetStatusFrameRate. @see SetStatusFrameRate

+ * The getters for these unsolicited signals are auto generated at the bottom of this module.

+ *

+ * Likewise most control signals are sent periodically using the fire-and-forget CAN API.

+ * The setters for these unsolicited signals are auto generated at the bottom of this module.

+ *

+ * Signals that are not available in an unsolicited fashion are the Close Loop gains.

+ * For teams that have a single profile for their TALON close loop they can use either the webpage to configure their TALONs once

+ * 	or set the PIDF,Izone,CloseLoopRampRate,etc... once in the robot application.  These parameters are saved to flash so once they are

+ * 	loaded in the TALON, they will persist through power cycles and mode changes.

+ *

+ * For teams that have one or two profiles to switch between, they can use the same strategy since there are two slots to choose from

+ * and the ProfileSlotSelect is periodically sent in the 10 ms control frame.

+ *

+ * For teams that require changing gains frequently, they can use the soliciting API to get and set those parameters.  Most likely

+ * they will only need to set them in a periodic fashion as a function of what motion the application is attempting.

+ * If this API is used, be mindful of the CAN utilization reported in the driver station.

+ *

+ * Encoder position is measured in encoder edges.  Every edge is counted (similar to roboRIO 4X mode).

+ * Analog position is 10 bits, meaning 1024 ticks per rotation (0V => 3.3V).

+ * Use SetFeedbackDeviceSelect to select which sensor type you need.  Once you do that you can use GetSensorPosition()

+ * and GetSensorVelocity().  These signals are updated on CANBus every 20ms (by default).

+ * If a relative sensor is selected, you can zero (or change the current value) using SetSensorPosition.

+ *

+ * Analog Input and quadrature position (and velocity) are also explicitly reported in GetEncPosition, GetEncVel, GetAnalogInWithOv, GetAnalogInVel.

+ * These signals are available all the time, regardless of what sensor is selected at a rate of 100ms.  This allows easy instrumentation

+ * for "in the pits" checking of all sensors regardless of modeselect.  The 100ms rate is overridable for teams who want to acquire sensor

+ * data for processing, not just instrumentation.  Or just select the sensor using SetFeedbackDeviceSelect to get it at 20ms.

+ *

+ * Velocity is in position ticks / 100ms.

+ *

+ * All output units are in respect to duty cycle (throttle) which is -1023(full reverse) to +1023 (full forward).

+ *  This includes demand (which specifies duty cycle when in duty cycle mode) and rampRamp, which is in throttle units per 10ms (if nonzero).

+ *

+ * Pos and velocity close loops are calc'd as

+ * 		err = target - posOrVel.

+ * 		iErr += err;

+ * 		if(   (IZone!=0)  and  abs(err) > IZone)

+ * 			ClearIaccum()

+ * 		output = P X err + I X iErr + D X dErr + F X target

+ * 		dErr = err - lastErr

+ *	P, I,and D gains are always positive. F can be negative.

+ *	Motor direction can be reversed using SetRevMotDuringCloseLoopEn if sensor and motor are out of phase.

+ *	Similarly feedback sensor can also be reversed (multiplied by -1) if you prefer the sensor to be inverted.

+ *

+ * P gain is specified in throttle per error tick.  For example, a value of 102 is ~9.9% (which is 102/1023) throttle per 1

+ * 		ADC unit(10bit) or 1 quadrature encoder edge depending on selected sensor.

+ *

+ * I gain is specified in throttle per integrated error. For example, a value of 10 equates to ~0.99% (which is 10/1023)

+ *  	for each accumulated ADC unit(10bit) or 1 quadrature encoder edge depending on selected sensor.

+ *  	Close loop and integral accumulator runs every 1ms.

+ *

+ * D gain is specified in throttle per derivative error. For example a value of 102 equates to ~9.9% (which is 102/1023)

+ * 	per change of 1 unit (ADC or encoder) per ms.

+ *

+ * I Zone is specified in the same units as sensor position (ADC units or quadrature edges).  If pos/vel error is outside of

+ * 		this value, the integrated error will auto-clear...

+ * 		if(   (IZone!=0)  and  abs(err) > IZone)

+ * 			ClearIaccum()

+ * 		...this is very useful in preventing integral windup and is highly recommended if using full PID to keep stability low.

+ *

+ * CloseLoopRampRate is in throttle units per 1ms.  Set to zero to disable ramping.

+ * 		Works the same as RampThrottle but only is in effect when a close loop mode and profile slot is selected.

+ *

+ * auto generated using spreadsheet and WpiClassGen.csproj

+ * @link https://docs.google.com/spreadsheets/d/1OU_ZV7fZLGYUQ-Uhc8sVAmUmWTlT8XBFYK8lfjg_tac/edit#gid=1766046967

+ */

+#ifndef CanTalonSRX_H_

+#define CanTalonSRX_H_

+#include "ctre.h"				//BIT Defines + Typedefs

+#include "CtreCanNode.h"

+#include <NetworkCommunication/CANSessionMux.h>	//CAN Comm

+#include <map>

+class CanTalonSRX : public CtreCanNode

+{

+private:

+

+	/** just in case user wants to modify periods of certain status frames.

+	 * 	Default the vars to match the firmware default. */

+	uint32_t _statusRateMs[4];

+	//---------------------- Vars for opening a CAN stream if caller needs signals that require soliciting */

+	uint32_t _can_h; 	//!< Session handle for catching response params.

+	int32_t _can_stat; //!< Session handle status.

+	struct tCANStreamMessage _msgBuff[20];

+	static int const kMsgCapacity	= 20;

+	typedef std::map<uint32_t, uint32_t> sigs_t;

+	sigs_t _sigs; //!< Catches signal updates that are solicited.  Expect this to be very few.

+	void OpenSessionIfNeedBe();

+	void ProcessStreamMessages();

+	/**

+	 * Send a one shot frame to set an arbitrary signal.

+	 * Most signals are in the control frame so avoid using this API unless you have to.

+	 * Use this api for...

+	 * -A motor controller profile signal eProfileParam_XXXs.  These are backed up in flash.  If you are gain-scheduling then call this periodically.

+	 * -Default brake and limit switch signals... eOnBoot_XXXs.  Avoid doing this, use the override signals in the control frame.

+	 * Talon will automatically send a PARAM_RESPONSE after the set, so GetParamResponse will catch the latest value after a couple ms.

+	 */

+	CTR_Code SetParamRaw(uint32_t paramEnum, int32_t rawBits);

+	/**

+	 * Checks cached CAN frames and updating solicited signals.

+	 */

+	CTR_Code GetParamResponseRaw(uint32_t paramEnum, int32_t & rawBits);

+public:

+	static const int kDefaultControlPeriodMs = 10; //!< default control update rate is 10ms.

+	CanTalonSRX(int deviceNumber = 0,int controlPeriodMs = kDefaultControlPeriodMs);

+	~CanTalonSRX();

+	void Set(double value);

+	/* mode select enumerations */

+	static const int kMode_DutyCycle = 0; //!< Demand is 11bit signed duty cycle [-1023,1023].

+	static const int kMode_PositionCloseLoop = 1; //!< Position PIDF.

+	static const int kMode_VelocityCloseLoop = 2; //!< Velocity PIDF.

+	static const int kMode_CurrentCloseLoop = 3; //!< Current close loop - not done.

+	static const int kMode_VoltCompen = 4; //!< Voltage Compensation Mode - not done.  Demand is fixed pt target 8.8 volts.

+	static const int kMode_SlaveFollower = 5; //!< Demand is the 6 bit Device ID of the 'master' TALON SRX.

+	static const int kMode_NoDrive = 15; //!< Zero the output (honors brake/coast) regardless of demand.  Might be useful if we need to change modes but can't atomically change all the signals we want in between.

+	/* limit switch enumerations */

+	static const int kLimitSwitchOverride_UseDefaultsFromFlash = 1;

+	static const int kLimitSwitchOverride_DisableFwd_DisableRev = 4;

+	static const int kLimitSwitchOverride_DisableFwd_EnableRev = 5;

+	static const int kLimitSwitchOverride_EnableFwd_DisableRev = 6;

+	static const int kLimitSwitchOverride_EnableFwd_EnableRev = 7;

+	/* brake override enumerations */

+	static const int kBrakeOverride_UseDefaultsFromFlash = 0;

+	static const int kBrakeOverride_OverrideCoast = 1;

+	static const int kBrakeOverride_OverrideBrake = 2;

+	/* feedback device enumerations */

+	static const int kFeedbackDev_DigitalQuadEnc=0;

+	static const int kFeedbackDev_AnalogPot=2;

+	static const int kFeedbackDev_AnalogEncoder=3;

+	static const int kFeedbackDev_CountEveryRisingEdge=4;

+	static const int kFeedbackDev_CountEveryFallingEdge=5;

+	static const int kFeedbackDev_PosIsPulseWidth=8;

+	/* ProfileSlotSelect enumerations*/

+	static const int kProfileSlotSelect_Slot0 = 0;

+	static const int kProfileSlotSelect_Slot1 = 1;

+    /* status frame rate types */

+    static const int kStatusFrame_General = 0;

+    static const int kStatusFrame_Feedback = 1;

+    static const int kStatusFrame_Encoder = 2;

+    static const int kStatusFrame_AnalogTempVbat = 3;

+	/**

+	 * Signal enumeration for generic signal access.

+	 * Although every signal is enumerated, only use this for traffic that must be solicited.

+	 * Use the auto generated getters/setters at bottom of this header as much as possible.

+	 */

+	typedef enum _param_t{

+		eProfileParamSlot0_P=1,

+		eProfileParamSlot0_I=2,

+		eProfileParamSlot0_D=3,

+		eProfileParamSlot0_F=4,

+		eProfileParamSlot0_IZone=5,

+		eProfileParamSlot0_CloseLoopRampRate=6,

+		eProfileParamSlot1_P=11,

+		eProfileParamSlot1_I=12,

+		eProfileParamSlot1_D=13,

+		eProfileParamSlot1_F=14,

+		eProfileParamSlot1_IZone=15,

+		eProfileParamSlot1_CloseLoopRampRate=16,

+		eProfileParamSoftLimitForThreshold=21,

+		eProfileParamSoftLimitRevThreshold=22,

+		eProfileParamSoftLimitForEnable=23,

+		eProfileParamSoftLimitRevEnable=24,

+		eOnBoot_BrakeMode=31,

+		eOnBoot_LimitSwitch_Forward_NormallyClosed=32,

+		eOnBoot_LimitSwitch_Reverse_NormallyClosed=33,

+		eOnBoot_LimitSwitch_Forward_Disable=34,

+		eOnBoot_LimitSwitch_Reverse_Disable=35,

+		eFault_OverTemp=41,

+		eFault_UnderVoltage=42,

+		eFault_ForLim=43,

+		eFault_RevLim=44,

+		eFault_HardwareFailure=45,

+		eFault_ForSoftLim=46,

+		eFault_RevSoftLim=47,

+		eStckyFault_OverTemp=48,

+		eStckyFault_UnderVoltage=49,

+		eStckyFault_ForLim=50,

+		eStckyFault_RevLim=51,

+		eStckyFault_ForSoftLim=52,

+		eStckyFault_RevSoftLim=53,

+		eAppliedThrottle=61,

+		eCloseLoopErr=62,

+		eFeedbackDeviceSelect=63,

+		eRevMotDuringCloseLoopEn=64,

+		eModeSelect=65,

+		eProfileSlotSelect=66,

+		eRampThrottle=67,

+		eRevFeedbackSensor=68,

+		eLimitSwitchEn=69,

+		eLimitSwitchClosedFor=70,

+		eLimitSwitchClosedRev=71,

+		eSensorPosition=73,

+		eSensorVelocity=74,

+		eCurrent=75,

+		eBrakeIsEnabled=76,

+		eEncPosition=77,

+		eEncVel=78,

+		eEncIndexRiseEvents=79,

+		eQuadApin=80,

+		eQuadBpin=81,

+		eQuadIdxpin=82,

+		eAnalogInWithOv=83,

+		eAnalogInVel=84,

+		eTemp=85,

+		eBatteryV=86,

+		eResetCount=87,

+		eResetFlags=88,

+		eFirmVers=89,

+		eSettingsChanged=90,

+		eQuadFilterEn=91,	

+		ePidIaccum=93,

+	}param_t;

+    /*---------------------setters and getters that use the solicated param request/response-------------*//**

+     * Send a one shot frame to set an arbitrary signal.

+     * Most signals are in the control frame so avoid using this API unless you have to.

+     * Use this api for...

+     * -A motor controller profile signal eProfileParam_XXXs.  These are backed up in flash.  If you are gain-scheduling then call this periodically.

+     * -Default brake and limit switch signals... eOnBoot_XXXs.  Avoid doing this, use the override signals in the control frame.

+     * Talon will automatically send a PARAM_RESPONSE after the set, so GetParamResponse will catch the latest value after a couple ms.

+     */

+	CTR_Code SetParam(param_t paramEnum, double value);

+	/**

+	 * Asks TALON to immedietely respond with signal value.  This API is only used for signals that are not sent periodically.

+	 * This can be useful for reading params that rarely change like Limit Switch settings and PIDF values.

+	  * @param param to request.

+	 */

+	CTR_Code RequestParam(param_t paramEnum);

+	CTR_Code GetParamResponse(param_t paramEnum, double & value);

+	CTR_Code GetParamResponseInt32(param_t paramEnum, int & value);

+    /*----- getters and setters that use param request/response. These signals are backed up in flash and will survive a power cycle. ---------*/

+	/*----- If your application requires changing these values consider using both slots and switch between slot0 <=> slot1. ------------------*/

+	/*----- If your application requires changing these signals frequently then it makes sense to leverage this API. --------------------------*/

+	/*----- Getters don't block, so it may require several calls to get the latest value. --------------------------*/

+	CTR_Code SetPgain(unsigned slotIdx,double gain);

+	CTR_Code SetIgain(unsigned slotIdx,double gain);

+	CTR_Code SetDgain(unsigned slotIdx,double gain);

+	CTR_Code SetFgain(unsigned slotIdx,double gain);

+	CTR_Code SetIzone(unsigned slotIdx,int zone);

+	CTR_Code SetCloseLoopRampRate(unsigned slotIdx,int closeLoopRampRate);

+	CTR_Code SetSensorPosition(int pos);

+	CTR_Code SetForwardSoftLimit(int forwardLimit);

+	CTR_Code SetReverseSoftLimit(int reverseLimit);

+	CTR_Code SetForwardSoftEnable(int enable);

+	CTR_Code SetReverseSoftEnable(int enable);

+	CTR_Code GetPgain(unsigned slotIdx,double & gain);

+	CTR_Code GetIgain(unsigned slotIdx,double & gain);

+	CTR_Code GetDgain(unsigned slotIdx,double & gain);

+	CTR_Code GetFgain(unsigned slotIdx,double & gain);

+	CTR_Code GetIzone(unsigned slotIdx,int & zone);

+	CTR_Code GetCloseLoopRampRate(unsigned slotIdx,int & closeLoopRampRate);

+	CTR_Code GetForwardSoftLimit(int & forwardLimit);

+	CTR_Code GetReverseSoftLimit(int & reverseLimit);

+	CTR_Code GetForwardSoftEnable(int & enable);

+	CTR_Code GetReverseSoftEnable(int & enable);

+	/**

+	 * Change the periodMs of a TALON's status frame.  See kStatusFrame_* enums for what's available.

+	 */

+	CTR_Code SetStatusFrameRate(unsigned frameEnum, unsigned periodMs);

+	/**

+	 * Clear all sticky faults in TALON.

+	 */

+	CTR_Code ClearStickyFaults();

+    /*------------------------ auto generated.  This API is optimal since it uses the fire-and-forget CAN interface ----------------------*/

+    /*------------------------ These signals should cover the majority of all use cases. ----------------------------------*/

+	CTR_Code GetFault_OverTemp(int &param);

+	CTR_Code GetFault_UnderVoltage(int &param);

+	CTR_Code GetFault_ForLim(int &param);

+	CTR_Code GetFault_RevLim(int &param);

+	CTR_Code GetFault_HardwareFailure(int &param);

+	CTR_Code GetFault_ForSoftLim(int &param);

+	CTR_Code GetFault_RevSoftLim(int &param);

+	CTR_Code GetStckyFault_OverTemp(int &param);

+	CTR_Code GetStckyFault_UnderVoltage(int &param);

+	CTR_Code GetStckyFault_ForLim(int &param);

+	CTR_Code GetStckyFault_RevLim(int &param);

+	CTR_Code GetStckyFault_ForSoftLim(int &param);

+	CTR_Code GetStckyFault_RevSoftLim(int &param);

+	CTR_Code GetAppliedThrottle(int &param);

+	CTR_Code GetCloseLoopErr(int &param);

+	CTR_Code GetFeedbackDeviceSelect(int &param);

+	CTR_Code GetModeSelect(int &param);

+	CTR_Code GetLimitSwitchEn(int &param);

+	CTR_Code GetLimitSwitchClosedFor(int &param);

+	CTR_Code GetLimitSwitchClosedRev(int &param);

+	CTR_Code GetSensorPosition(int &param);

+	CTR_Code GetSensorVelocity(int &param);

+	CTR_Code GetCurrent(double &param);

+	CTR_Code GetBrakeIsEnabled(int &param);

+	CTR_Code GetEncPosition(int &param);

+	CTR_Code GetEncVel(int &param);

+	CTR_Code GetEncIndexRiseEvents(int &param);

+	CTR_Code GetQuadApin(int &param);

+	CTR_Code GetQuadBpin(int &param);

+	CTR_Code GetQuadIdxpin(int &param);

+	CTR_Code GetAnalogInWithOv(int &param);

+	CTR_Code GetAnalogInVel(int &param);

+	CTR_Code GetTemp(double &param);

+	CTR_Code GetBatteryV(double &param);

+	CTR_Code GetResetCount(int &param);

+	CTR_Code GetResetFlags(int &param);

+	CTR_Code GetFirmVers(int &param);

+	CTR_Code SetDemand(int param);

+	CTR_Code SetOverrideLimitSwitchEn(int param);

+	CTR_Code SetFeedbackDeviceSelect(int param);

+	CTR_Code SetRevMotDuringCloseLoopEn(int param);

+	CTR_Code SetOverrideBrakeType(int param);

+	CTR_Code SetModeSelect(int param);

+	CTR_Code SetModeSelect(int modeSelect,int demand);

+	CTR_Code SetProfileSlotSelect(int param);

+	CTR_Code SetRampThrottle(int param);

+	CTR_Code SetRevFeedbackSensor(int param);

+};

+extern "C" {

+	void *c_TalonSRX_Create(int deviceNumber, int controlPeriodMs);

+	void c_TalonSRX_Destroy(void *handle);

+	CTR_Code c_TalonSRX_SetParam(void *handle, int paramEnum, double value);

+	CTR_Code c_TalonSRX_RequestParam(void *handle, int paramEnum);

+	CTR_Code c_TalonSRX_GetParamResponse(void *handle, int paramEnum, double *value);

+	CTR_Code c_TalonSRX_GetParamResponseInt32(void *handle, int paramEnum, int *value);

+	CTR_Code c_TalonSRX_SetStatusFrameRate(void *handle, unsigned frameEnum, unsigned periodMs);

+	CTR_Code c_TalonSRX_ClearStickyFaults(void *handle);

+	CTR_Code c_TalonSRX_GetFault_OverTemp(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetFault_UnderVoltage(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetFault_ForLim(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetFault_RevLim(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetFault_HardwareFailure(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetFault_ForSoftLim(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetFault_RevSoftLim(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetStckyFault_OverTemp(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetStckyFault_UnderVoltage(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetStckyFault_ForLim(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetStckyFault_RevLim(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetStckyFault_ForSoftLim(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetStckyFault_RevSoftLim(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetAppliedThrottle(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetCloseLoopErr(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetFeedbackDeviceSelect(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetModeSelect(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetLimitSwitchEn(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetLimitSwitchClosedFor(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetLimitSwitchClosedRev(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetSensorPosition(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetSensorVelocity(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetCurrent(void *handle, double *param);

+	CTR_Code c_TalonSRX_GetBrakeIsEnabled(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetEncPosition(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetEncVel(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetEncIndexRiseEvents(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetQuadApin(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetQuadBpin(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetQuadIdxpin(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetAnalogInWithOv(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetAnalogInVel(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetTemp(void *handle, double *param);

+	CTR_Code c_TalonSRX_GetBatteryV(void *handle, double *param);

+	CTR_Code c_TalonSRX_GetResetCount(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetResetFlags(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetFirmVers(void *handle, int *param);

+	CTR_Code c_TalonSRX_SetDemand(void *handle, int param);

+	CTR_Code c_TalonSRX_SetOverrideLimitSwitchEn(void *handle, int param);

+	CTR_Code c_TalonSRX_SetFeedbackDeviceSelect(void *handle, int param);

+	CTR_Code c_TalonSRX_SetRevMotDuringCloseLoopEn(void *handle, int param);

+	CTR_Code c_TalonSRX_SetOverrideBrakeType(void *handle, int param);

+	CTR_Code c_TalonSRX_SetModeSelect(void *handle, int param);

+	CTR_Code c_TalonSRX_SetModeSelect2(void *handle, int modeSelect, int demand);

+	CTR_Code c_TalonSRX_SetProfileSlotSelect(void *handle, int param);

+	CTR_Code c_TalonSRX_SetRampThrottle(void *handle, int param);

+	CTR_Code c_TalonSRX_SetRevFeedbackSensor(void *handle, int param);

+}

+#endif

+

diff --git a/aos/externals/allwpilib/hal/lib/Athena/ctre/CtreCanNode.cpp b/aos/externals/allwpilib/hal/lib/Athena/ctre/CtreCanNode.cpp
new file mode 100644
index 0000000..b2e3620
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/ctre/CtreCanNode.cpp
@@ -0,0 +1,101 @@
+#pragma GCC diagnostic ignored "-Wmissing-field-initializers"

+

+#include "CtreCanNode.h"

+#include "NetworkCommunication/CANSessionMux.h"

+#include <string.h> // memset

+#include <unistd.h> // usleep

+

+static const UINT32 kFullMessageIDMask = 0x1fffffff;

+

+CtreCanNode::CtreCanNode(UINT8 deviceNumber)

+{

+	_deviceNumber = deviceNumber;

+}

+CtreCanNode::~CtreCanNode()

+{

+}

+void CtreCanNode::RegisterRx(uint32_t arbId)

+{

+	/* no need to do anything, we just use new API to poll last received message */

+}

+void CtreCanNode::RegisterTx(uint32_t arbId, uint32_t periodMs)

+{

+	int32_t status = 0;

+

+	txJob_t job = {0};

+	job.arbId = arbId;

+	job.periodMs = periodMs;

+	_txJobs[arbId] = job;

+	FRC_NetworkCommunication_CANSessionMux_sendMessage(	job.arbId,

+														job.toSend,

+														8,

+														job.periodMs,

+														&status);

+}

+timespec diff(const timespec & start, const timespec & end)

+{

+	timespec temp;

+	if ((end.tv_nsec-start.tv_nsec)<0) {

+		temp.tv_sec = end.tv_sec-start.tv_sec-1;

+		temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;

+	} else {

+		temp.tv_sec = end.tv_sec-start.tv_sec;

+		temp.tv_nsec = end.tv_nsec-start.tv_nsec;

+	}

+	return temp;

+}

+CTR_Code CtreCanNode::GetRx(uint32_t arbId,uint8_t * dataBytes, uint32_t timeoutMs)

+{

+	CTR_Code retval = CTR_OKAY;

+	int32_t status = 0;

+	uint8_t len = 0;

+	uint32_t timeStamp;

+	/* cap timeout at 999ms */

+	if(timeoutMs > 999)

+		timeoutMs = 999;

+	FRC_NetworkCommunication_CANSessionMux_receiveMessage(&arbId,kFullMessageIDMask,dataBytes,&len,&timeStamp,&status);

+	if(status == 0){

+		/* fresh update */

+		rxEvent_t & r = _rxRxEvents[arbId]; /* lookup entry or make a default new one with all zeroes */

+		clock_gettime(2,&r.time); 			/* fill in time */

+		memcpy(r.bytes,  dataBytes,  8);	/* fill in databytes */

+	}else{

+		/* did not get the message */

+		rxRxEvents_t::iterator i = _rxRxEvents.find(arbId);

+		if(i == _rxRxEvents.end()){

+			/* we've never gotten this mesage */

+			retval = CTR_RxTimeout;

+			/* fill caller's buffer with zeros */

+			memset(dataBytes,0,8);

+		}else{

+			/* we've gotten this message before but not recently */

+			memcpy(dataBytes,i->second.bytes,8);

+			/* get the time now */

+			struct timespec temp;

+			clock_gettime(2,&temp); /* get now */

+			/* how long has it been? */

+			temp = diff(i->second.time,temp); /* temp = now - last */

+			if(temp.tv_sec > 0){

+				retval = CTR_RxTimeout;

+			}else if(temp.tv_nsec > ((int32_t)timeoutMs*1000*1000)){

+				retval = CTR_RxTimeout;

+			}else {

+				/* our last update was recent enough */

+			}

+		}

+	}

+

+	return retval;

+}

+void CtreCanNode::FlushTx(uint32_t arbId)

+{

+	int32_t status = 0;

+	txJobs_t::iterator iter = _txJobs.find(arbId);

+	if(iter != _txJobs.end())

+		FRC_NetworkCommunication_CANSessionMux_sendMessage(	iter->second.arbId,

+															iter->second.toSend,

+															8,

+															iter->second.periodMs,

+															&status);

+}

+

diff --git a/aos/externals/allwpilib/hal/lib/Athena/ctre/CtreCanNode.h b/aos/externals/allwpilib/hal/lib/Athena/ctre/CtreCanNode.h
new file mode 100644
index 0000000..7a2d690
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/ctre/CtreCanNode.h
@@ -0,0 +1,116 @@
+#ifndef CtreCanNode_H_

+#define CtreCanNode_H_

+#include "ctre.h"				//BIT Defines + Typedefs

+#include <NetworkCommunication/CANSessionMux.h>	//CAN Comm

+#include <pthread.h>

+#include <map>

+#include <string.h> // memcpy

+#include <sys/time.h>

+class CtreCanNode

+{

+public:

+	CtreCanNode(UINT8 deviceNumber);

+    ~CtreCanNode();

+

+	UINT8 GetDeviceNumber()

+	{

+		return _deviceNumber;

+	}

+protected:

+

+

+	template <typename T> class txTask{

+		public:

+			uint32_t arbId;

+			T * toSend;

+			T * operator -> ()

+			{

+				return toSend;

+			}

+			T & operator*()

+			{

+				return *toSend;

+			}

+			bool IsEmpty()

+			{

+				if(toSend == 0)

+					return true;

+				return false;

+			}

+	};

+	template <typename T> class recMsg{

+		public:

+			uint32_t arbId;

+			uint8_t bytes[8];

+			CTR_Code err;

+			T * operator -> ()

+			{

+				return (T *)bytes;

+			}

+			T & operator*()

+			{

+				return *(T *)bytes;

+			}

+	};

+	UINT8 _deviceNumber;

+	void RegisterRx(uint32_t arbId);

+	void RegisterTx(uint32_t arbId, uint32_t periodMs);

+

+	CTR_Code GetRx(uint32_t arbId,uint8_t * dataBytes,uint32_t timeoutMs);

+	void FlushTx(uint32_t arbId);

+

+	template<typename T> txTask<T> GetTx(uint32_t arbId)

+	{

+		txTask<T> retval = {0, nullptr};

+		txJobs_t::iterator i = _txJobs.find(arbId);

+		if(i != _txJobs.end()){

+			retval.arbId = i->second.arbId;

+			retval.toSend = (T*)i->second.toSend;

+		}

+		return retval;

+	}

+	template<class T> void FlushTx(T & par)

+	{

+		FlushTx(par.arbId);

+	}

+

+	template<class T> recMsg<T> GetRx(uint32_t arbId, uint32_t timeoutMs)

+	{

+		recMsg<T> retval;

+		retval.err = GetRx(arbId,retval.bytes, timeoutMs);

+		return retval;

+	}

+

+private:

+

+	class txJob_t {

+		public:

+			uint32_t arbId;

+			uint8_t toSend[8];

+			uint32_t periodMs;

+	};

+

+	class rxEvent_t{

+		public:

+			uint8_t bytes[8];

+			struct timespec time;

+			rxEvent_t()

+			{

+				bytes[0] = 0;

+				bytes[1] = 0;

+				bytes[2] = 0;

+				bytes[3] = 0;

+				bytes[4] = 0;

+				bytes[5] = 0;

+				bytes[6] = 0;

+				bytes[7] = 0;

+			}

+	};

+

+	typedef std::map<uint32_t,txJob_t> txJobs_t;

+	txJobs_t _txJobs;

+

+	typedef std::map<uint32_t,rxEvent_t> rxRxEvents_t;

+	rxRxEvents_t _rxRxEvents;

+};

+#endif

diff --git a/aos/externals/allwpilib/hal/lib/Athena/ctre/PCM.cpp b/aos/externals/allwpilib/hal/lib/Athena/ctre/PCM.cpp
new file mode 100644
index 0000000..fbf6555
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/ctre/PCM.cpp
@@ -0,0 +1,541 @@
+#pragma GCC diagnostic ignored "-Wmissing-field-initializers"

+

+#include "PCM.h"

+#include "NetworkCommunication/CANSessionMux.h"

+#include <string.h> // memset

+#include <unistd.h> // usleep

+/* This can be a constant, as long as nobody needs to updatie solenoids within

+    1/50 of a second. */

+static const INT32 kCANPeriod = 20;

+

+#define STATUS_1  			0x9041400

+#define STATUS_SOL_FAULTS  	0x9041440

+#define STATUS_DEBUG  		0x9041480

+

+#define EXPECTED_RESPONSE_TIMEOUT_MS	(50)

+#define GET_PCM_STATUS()			CtreCanNode::recMsg<PcmStatus_t> 		rx = GetRx<PcmStatus_t>			(STATUS_1,EXPECTED_RESPONSE_TIMEOUT_MS)

+#define GET_PCM_SOL_FAULTS()		CtreCanNode::recMsg<PcmStatusFault_t> 	rx = GetRx<PcmStatusFault_t>	(STATUS_SOL_FAULTS,EXPECTED_RESPONSE_TIMEOUT_MS)

+#define GET_PCM_DEBUG()				CtreCanNode::recMsg<PcmDebug_t> 		rx = GetRx<PcmDebug_t>			(STATUS_DEBUG,EXPECTED_RESPONSE_TIMEOUT_MS)

+

+#define CONTROL_1 			0x09041C00	/* PCM_Control */

+#define CONTROL_2 			0x09041C40	/* PCM_SupplemControl */

+#define CONTROL_3 			0x09041C80	/* PcmControlSetOneShotDur_t */

+

+/* encoder/decoders */

+typedef struct _PcmStatus_t{

+	/* Byte 0 */

+	unsigned SolenoidBits:8;

+	/* Byte 1 */

+	unsigned compressorOn:1;

+	unsigned stickyFaultFuseTripped:1;

+	unsigned stickyFaultCompCurrentTooHigh:1;

+	unsigned faultFuseTripped:1;

+	unsigned faultCompCurrentTooHigh:1;

+	unsigned faultHardwareFailure:1;

+	unsigned isCloseloopEnabled:1;

+	unsigned pressureSwitchEn:1;

+	/* Byte 2*/

+	unsigned battVoltage:8;

+	/* Byte 3 */

+	unsigned solenoidVoltageTop8:8;

+	/* Byte 4 */

+	unsigned compressorCurrentTop6:6;

+	unsigned solenoidVoltageBtm2:2;

+	/* Byte 5 */

+	unsigned StickyFault_dItooHigh :1;

+	unsigned Fault_dItooHigh :1;

+	unsigned moduleEnabled:1;

+	unsigned closedLoopOutput:1;

+	unsigned compressorCurrentBtm4:4;

+	/* Byte 6 */

+	unsigned tokenSeedTop8:8;

+	/* Byte 7 */

+	unsigned tokenSeedBtm8:8;

+}PcmStatus_t;

+

+typedef struct _PcmControl_t{

+	/* Byte 0 */

+	unsigned tokenTop8:8;

+	/* Byte 1 */

+	unsigned tokenBtm8:8;

+	/* Byte 2 */

+	unsigned solenoidBits:8;

+	/* Byte 3*/

+	unsigned reserved:4;

+	unsigned closeLoopOutput:1;

+	unsigned compressorOn:1;

+	unsigned closedLoopEnable:1;

+	unsigned clearStickyFaults:1;

+	/* Byte 4 */

+	unsigned OneShotField_h8:8;

+	/* Byte 5 */

+	unsigned OneShotField_l8:8;

+}PcmControl_t;

+

+typedef struct _PcmControlSetOneShotDur_t{

+	uint8_t sol10MsPerUnit[8];

+}PcmControlSetOneShotDur_t;

+

+typedef struct _PcmStatusFault_t{

+	/* Byte 0 */

+	unsigned SolenoidBlacklist:8;

+	/* Byte 1 */

+	unsigned reserved_bit0 :1;

+	unsigned reserved_bit1 :1;

+	unsigned reserved_bit2 :1;

+	unsigned reserved_bit3 :1;

+	unsigned StickyFault_CompNoCurrent :1;

+	unsigned Fault_CompNoCurrent :1;

+	unsigned StickyFault_SolenoidJumper :1;

+	unsigned Fault_SolenoidJumper :1;

+}PcmStatusFault_t;

+

+typedef struct _PcmDebug_t{

+	unsigned tokFailsTop8:8;

+	unsigned tokFailsBtm8:8;

+	unsigned lastFailedTokTop8:8;

+	unsigned lastFailedTokBtm8:8;

+	unsigned tokSuccessTop8:8;

+	unsigned tokSuccessBtm8:8;

+}PcmDebug_t;

+

+

+/* PCM Constructor - Clears all vars, establishes default settings, starts PCM background process

+ *

+ * @Return	-	void

+ *

+ * @Param 	-	deviceNumber	- 	Device ID of PCM to be controlled

+ */

+PCM::PCM(UINT8 deviceNumber): CtreCanNode(deviceNumber)

+{

+	RegisterRx(STATUS_1 | deviceNumber );

+	RegisterRx(STATUS_SOL_FAULTS | deviceNumber );

+	RegisterRx(STATUS_DEBUG | deviceNumber );

+	RegisterTx(CONTROL_1 | deviceNumber, kCANPeriod);

+	/* enable close loop */

+	SetClosedLoopControl(1);

+}

+/* PCM D'tor

+ */

+PCM::~PCM()

+{

+

+}

+

+/* Set PCM solenoid state

+ *

+ * @Return	-	CTR_Code	-	Error code (if any) for setting solenoid

+ *

+ * @Param 	-	idx			- 	ID of solenoid (0-7)

+ * @Param 	-	en			- 	Enable / Disable identified solenoid

+ */

+CTR_Code PCM::SetSolenoids(uint8_t value, uint8_t mask)

+{

+	CtreCanNode::txTask<PcmControl_t> toFill = GetTx<PcmControl_t>(CONTROL_1 | GetDeviceNumber());

+	if(toFill.IsEmpty())return CTR_UnexpectedArbId;

+	toFill->solenoidBits |= mask & value;

+	toFill->solenoidBits &= ~(mask & ~value);

+	FlushTx(toFill);

+	return CTR_OKAY;

+}

+

+/* Clears PCM sticky faults (indicators of past faults

+ *

+ * @Return	-	CTR_Code	-	Error code (if any) for setting solenoid

+ *

+ * @Param 	-	clr		- 	Clear / do not clear faults

+ */

+CTR_Code PCM::ClearStickyFaults()

+{

+	int32_t status = 0;

+	uint8_t pcmSupplemControl[] = { 0, 0, 0, 0x80 }; /* only bit set is ClearStickyFaults */

+	FRC_NetworkCommunication_CANSessionMux_sendMessage(CONTROL_2  | GetDeviceNumber(), pcmSupplemControl, sizeof(pcmSupplemControl), 0, &status);

+	if(status)

+		return CTR_TxFailed;

+	return CTR_OKAY;

+}

+

+/* Enables PCM Closed Loop Control of Compressor via pressure switch

+ *

+ * @Return	-	CTR_Code	-	Error code (if any) for setting solenoid

+ *

+ * @Param 	-	en		- 	Enable / Disable Closed Loop Control

+ */

+CTR_Code PCM::SetClosedLoopControl(bool en)

+{

+	CtreCanNode::txTask<PcmControl_t> toFill = GetTx<PcmControl_t>(CONTROL_1 | GetDeviceNumber());

+	if(toFill.IsEmpty())return CTR_UnexpectedArbId;

+	toFill->closedLoopEnable = en;

+	FlushTx(toFill);

+	return CTR_OKAY;

+}

+/* Get solenoid Blacklist status

+ * @Return	-	CTR_Code	-	Error code (if any)

+ * @Param	-	idx			-	ID of solenoid [0,7] to fire one shot pulse.

+ */

+CTR_Code PCM::FireOneShotSolenoid(UINT8 idx)

+{

+	CtreCanNode::txTask<PcmControl_t> toFill = GetTx<PcmControl_t>(CONTROL_1 | GetDeviceNumber());

+	if(toFill.IsEmpty())return CTR_UnexpectedArbId;

+	/* grab field as it is now */

+	uint16_t oneShotField;

+	oneShotField = toFill->OneShotField_h8;

+	oneShotField <<= 8;

+	oneShotField |= toFill->OneShotField_l8;

+	/* get the caller's channel */

+	uint16_t shift = 2*idx;

+	uint16_t mask = 3; /* two bits wide */

+	uint8_t chBits = (oneShotField >> shift) & mask;

+	/* flip it */

+	chBits = (chBits)%3 + 1;

+	/* clear out 2bits for this channel*/

+	oneShotField &= ~(mask << shift);

+	/* put new field in */

+	oneShotField |= chBits << shift;

+	/* apply field as it is now */

+	toFill->OneShotField_h8 = oneShotField >> 8;

+	toFill->OneShotField_l8 = oneShotField;

+	FlushTx(toFill);

+	return CTR_OKAY;

+}

+/* Configure the pulse width of a solenoid channel for one-shot pulse.

+ * Preprogrammed pulsewidth is 10ms resolute and can be between 20ms and 5.1s.

+ * @Return	-	CTR_Code	-	Error code (if any)

+ * @Param	-	idx			-	ID of solenoid [0,7] to configure.

+ * @Param	-	durMs		-	pulse width in ms.

+ */

+CTR_Code PCM::SetOneShotDurationMs(UINT8 idx,uint32_t durMs)

+{

+	/* sanity check caller's param */

+	if(idx > 8)

+		return CTR_InvalidParamValue;

+	/* get latest tx frame */

+	CtreCanNode::txTask<PcmControlSetOneShotDur_t> toFill = GetTx<PcmControlSetOneShotDur_t>(CONTROL_3 | GetDeviceNumber());

+	if(toFill.IsEmpty()){

+		/* only send this out if caller wants to do one-shots */

+		RegisterTx(CONTROL_3 | _deviceNumber, kCANPeriod);

+		/* grab it */

+		toFill = GetTx<PcmControlSetOneShotDur_t>(CONTROL_3 | GetDeviceNumber());

+	}

+	toFill->sol10MsPerUnit[idx] = std::min(durMs/10,(uint32_t)0xFF);

+	/* apply the new data bytes */

+	FlushTx(toFill);

+	return CTR_OKAY;

+}

+

+/* Get solenoid state

+ *

+ * @Return	-	True/False	-	True if solenoid enabled, false otherwise

+ *

+ * @Param 	-	idx		- 	ID of solenoid (0-7) to return status of

+ */

+CTR_Code PCM::GetSolenoid(UINT8 idx, bool &status)

+{

+	GET_PCM_STATUS();

+	status = (rx->SolenoidBits & (1ul<<(idx)) ) ? 1 : 0;

+	return rx.err;

+}

+

+/* Get pressure switch state

+ *

+ * @Return	-	True/False	-	True if pressure adequate, false if low

+ */

+CTR_Code PCM::GetPressure(bool &status)

+{

+	GET_PCM_STATUS();

+	status = (rx->pressureSwitchEn ) ? 1 : 0;

+	return rx.err;

+}

+

+/* Get compressor state

+ *

+ * @Return	-	True/False	-	True if enabled, false if otherwise

+ */

+CTR_Code PCM::GetCompressor(bool &status)

+{

+	GET_PCM_STATUS();

+	status = (rx->compressorOn);

+	return rx.err;

+}

+

+/* Get closed loop control state

+ *

+ * @Return	-	True/False	-	True if closed loop enabled, false if otherwise

+ */

+CTR_Code PCM::GetClosedLoopControl(bool &status)

+{

+	GET_PCM_STATUS();

+	status = (rx->isCloseloopEnabled);

+	return rx.err;

+}

+

+/* Get compressor current draw

+ *

+ * @Return	-	Amperes	-	Compressor current

+ */

+CTR_Code PCM::GetCompressorCurrent(float &status)

+{

+	GET_PCM_STATUS();

+	uint32_t temp =(rx->compressorCurrentTop6);

+	temp <<= 4;

+	temp |=  rx->compressorCurrentBtm4;

+	status = temp * 0.03125; /* 5.5 fixed pt value in Amps */

+	return rx.err;

+}

+

+/* Get voltage across solenoid rail

+ *

+ * @Return	-	Volts	-	Voltage across solenoid rail

+ */

+CTR_Code PCM::GetSolenoidVoltage(float &status)

+{

+	GET_PCM_STATUS();

+	uint32_t raw =(rx->solenoidVoltageTop8);

+	raw <<= 2;

+	raw |=  rx->solenoidVoltageBtm2;

+	status = (double) raw * 0.03125; /* 5.5 fixed pt value in Volts */

+	return rx.err;

+}

+

+/* Get hardware fault value

+ *

+ * @Return	-	True/False	-	True if hardware failure detected, false if otherwise

+ */

+CTR_Code PCM::GetHardwareFault(bool &status)

+{

+	GET_PCM_STATUS();

+	status = rx->faultHardwareFailure;

+	return rx.err;

+}

+

+/* Get compressor fault value

+ *

+ * @Return	-	True/False	-	True if shorted compressor detected, false if otherwise

+ */

+CTR_Code PCM::GetCompressorCurrentTooHighFault(bool &status)

+{

+	GET_PCM_STATUS();

+	status = rx->faultCompCurrentTooHigh;

+	return rx.err;

+}

+CTR_Code PCM::GetCompressorShortedStickyFault(bool &status)

+{

+	GET_PCM_STATUS();

+	status = rx->StickyFault_dItooHigh;

+	return rx.err;

+}

+CTR_Code PCM::GetCompressorShortedFault(bool &status)

+{

+	GET_PCM_STATUS();

+	status = rx->Fault_dItooHigh;

+	return rx.err;

+}

+CTR_Code PCM::GetCompressorNotConnectedStickyFault(bool &status)

+{

+	GET_PCM_SOL_FAULTS();

+	status = rx->StickyFault_CompNoCurrent;

+	return rx.err;

+}

+CTR_Code PCM::GetCompressorNotConnectedFault(bool &status)

+{

+	GET_PCM_SOL_FAULTS();

+	status = rx->Fault_CompNoCurrent;

+	return rx.err;

+}

+

+/* Get solenoid fault value

+ *

+ * @Return	-	True/False	-	True if shorted solenoid detected, false if otherwise

+ */

+CTR_Code PCM::GetSolenoidFault(bool &status)

+{

+	GET_PCM_STATUS();

+	status = rx->faultFuseTripped;

+	return rx.err;

+}

+

+/* Get compressor sticky fault value

+ *

+ * @Return	-	True/False	-	True if solenoid had previously been shorted

+ * 								(and sticky fault was not cleared), false if otherwise

+ */

+CTR_Code PCM::GetCompressorCurrentTooHighStickyFault(bool &status)

+{

+	GET_PCM_STATUS();

+	status = rx->stickyFaultCompCurrentTooHigh;

+	return rx.err;

+}

+

+/* Get solenoid sticky fault value

+ *

+ * @Return	-	True/False	-	True if compressor had previously been shorted

+ * 								(and sticky fault was not cleared), false if otherwise

+ */

+CTR_Code PCM::GetSolenoidStickyFault(bool &status)

+{

+	GET_PCM_STATUS();

+	status = rx->stickyFaultFuseTripped;

+	return rx.err;

+}

+/* Get battery voltage

+ *

+ * @Return	-	Volts	-	Voltage across PCM power ports

+ */

+CTR_Code PCM::GetBatteryVoltage(float &status)

+{

+	GET_PCM_STATUS();

+	status = (float)rx->battVoltage * 0.05 + 4.0; /* 50mV per unit plus 4V. */

+	return rx.err;

+}

+/* Return status of module enable/disable

+ *

+ * @Return	-	bool		-	Returns TRUE if PCM is enabled, FALSE if disabled

+ */

+CTR_Code PCM::isModuleEnabled(bool &status)

+{

+	GET_PCM_STATUS();

+	status = rx->moduleEnabled;

+	return rx.err;

+}

+/* Get number of total failed PCM Control Frame

+ *

+ * @Return	-	Failed Control Frames	-	Number of failed control frames (tokenization fails)

+ *

+ * @WARNING	-	Return only valid if [SeekDebugFrames] is enabled

+ * 				See function SeekDebugFrames

+ * 				See function EnableSeekDebugFrames

+ */

+CTR_Code PCM::GetNumberOfFailedControlFrames(UINT16 &status)

+{

+	GET_PCM_DEBUG();

+	status = rx->tokFailsTop8;

+	status <<= 8;

+	status |= rx->tokFailsBtm8;

+	return rx.err;

+}

+/* Get raw Solenoid Blacklist

+ *

+ * @Return	-	BINARY	-	Raw binary breakdown of Solenoid Blacklist

+ * 							BIT7 = Solenoid 1, BIT6 = Solenoid 2, etc.

+ *

+ * @WARNING	-	Return only valid if [SeekStatusFaultFrames] is enabled

+ * 				See function SeekStatusFaultFrames

+ * 				See function EnableSeekStatusFaultFrames

+ */

+CTR_Code PCM::GetSolenoidBlackList(UINT8 &status)

+{

+	GET_PCM_SOL_FAULTS();

+	status = rx->SolenoidBlacklist;

+	return rx.err;

+}

+/* Get solenoid Blacklist status

+ * - Blacklisted solenoids cannot be enabled until PCM is power cycled

+ *

+ * @Return	-	True/False	-	True if Solenoid is blacklisted, false if otherwise

+ *

+ * @Param	-	idx			-	ID of solenoid [0,7]

+ *

+ * @WARNING	-	Return only valid if [SeekStatusFaultFrames] is enabled

+ * 				See function SeekStatusFaultFrames

+ * 				See function EnableSeekStatusFaultFrames

+ */

+CTR_Code PCM::IsSolenoidBlacklisted(UINT8 idx, bool &status)

+{

+	GET_PCM_SOL_FAULTS();

+	status = (rx->SolenoidBlacklist & (1ul<<(idx)) )? 1 : 0;

+	return rx.err;

+}

+//------------------ C interface --------------------------------------------//

+extern "C" {

+	void * c_PCM_Init(void) {

+		return new PCM();

+	}

+	CTR_Code c_SetSolenoid(void * handle, uint8_t value, uint8_t mask) {

+		return ((PCM*) handle)->SetSolenoids(value, mask);

+	}

+	CTR_Code c_SetClosedLoopControl(void * handle, INT8 param) {

+		return ((PCM*) handle)->SetClosedLoopControl(param);

+	}

+	CTR_Code c_ClearStickyFaults(void * handle, INT8 param) {

+		return ((PCM*) handle)->ClearStickyFaults();

+	}

+	CTR_Code c_GetSolenoid(void * handle, UINT8 idx, INT8 * status) {

+		bool bstatus;

+		CTR_Code retval = ((PCM*) handle)->GetSolenoid(idx, bstatus);

+		*status = bstatus;

+		return retval;

+	}

+	CTR_Code c_GetPressure(void * handle, INT8 * status) {

+		bool bstatus;

+		CTR_Code retval = ((PCM*) handle)->GetPressure(bstatus);

+		*status = bstatus;

+		return retval;

+	}

+	CTR_Code c_GetCompressor(void * handle, INT8 * status) {

+		bool bstatus;

+		CTR_Code retval = ((PCM*) handle)->GetCompressor(bstatus);

+		*status = bstatus;

+		return retval;

+	}

+	CTR_Code c_GetClosedLoopControl(void * handle, INT8 * status) {

+		bool bstatus;

+		CTR_Code retval = ((PCM*) handle)->GetClosedLoopControl(bstatus);

+		*status = bstatus;

+		return retval;

+	}

+	CTR_Code c_GetCompressorCurrent(void * handle, float * status) {

+		CTR_Code retval = ((PCM*) handle)->GetCompressorCurrent(*status);

+		return retval;

+	}

+	CTR_Code c_GetSolenoidVoltage(void * handle, float*status) {

+		return ((PCM*) handle)->GetSolenoidVoltage(*status);

+	}

+	CTR_Code c_GetHardwareFault(void * handle, INT8*status) {

+		bool bstatus;

+		CTR_Code retval = ((PCM*) handle)->GetHardwareFault(bstatus);

+		*status = bstatus;

+		return retval;

+	}

+	CTR_Code c_GetCompressorFault(void * handle, INT8*status) {

+		bool bstatus;

+		CTR_Code retval = ((PCM*) handle)->GetCompressorCurrentTooHighFault(bstatus);

+		*status = bstatus;

+		return retval;

+	}

+	CTR_Code c_GetSolenoidFault(void * handle, INT8*status) {

+		bool bstatus;

+		CTR_Code retval = ((PCM*) handle)->GetSolenoidFault(bstatus);

+		*status = bstatus;

+		return retval;

+	}

+	CTR_Code c_GetCompressorStickyFault(void * handle, INT8*status) {

+		bool bstatus;

+		CTR_Code retval = ((PCM*) handle)->GetCompressorCurrentTooHighStickyFault(bstatus);

+		*status = bstatus;

+		return retval;

+	}

+	CTR_Code c_GetSolenoidStickyFault(void * handle, INT8*status) {

+		bool bstatus;

+		CTR_Code retval = ((PCM*) handle)->GetSolenoidStickyFault(bstatus);

+		*status = bstatus;

+		return retval;

+	}

+	CTR_Code c_GetBatteryVoltage(void * handle, float*status) {

+		CTR_Code retval = ((PCM*) handle)->GetBatteryVoltage(*status);

+		return retval;

+	}

+	void c_SetDeviceNumber_PCM(void * handle, UINT8 deviceNumber) {

+	}

+	CTR_Code c_GetNumberOfFailedControlFrames(void * handle, UINT16*status) {

+		return ((PCM*) handle)->GetNumberOfFailedControlFrames(*status);

+	}

+	CTR_Code c_GetSolenoidBlackList(void * handle, UINT8 *status) {

+		return ((PCM*) handle)->GetSolenoidBlackList(*status);

+	}

+	CTR_Code c_IsSolenoidBlacklisted(void * handle, UINT8 idx, INT8*status) {

+		bool bstatus;

+		CTR_Code retval = ((PCM*) handle)->IsSolenoidBlacklisted(idx, bstatus);

+		*status = bstatus;

+		return retval;

+	}

+}

diff --git a/aos/externals/allwpilib/hal/lib/Athena/ctre/PCM.h b/aos/externals/allwpilib/hal/lib/Athena/ctre/PCM.h
new file mode 100644
index 0000000..19dfc54
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/ctre/PCM.h
@@ -0,0 +1,212 @@
+#ifndef PCM_H_

+#define PCM_H_

+#include "ctre.h"				//BIT Defines + Typedefs

+#include <NetworkCommunication/CANSessionMux.h>	//CAN Comm

+#include "CtreCanNode.h"

+#include <pthread.h>

+class PCM : public CtreCanNode

+{

+public:

+    PCM(UINT8 deviceNumber=0);

+    ~PCM();

+    

+    /* Set PCM solenoids state

+     *

+     * @Return	-	CTR_Code	-	Error code (if any) for setting solenoids

+     * @Param 	-	value		- 	Values for specified solenoids

+     * @Param 	-	mask		- 	Mask of solenoids to set

+     */

+    CTR_Code 	SetSolenoids(uint8_t value, uint8_t mask);

+

+    /* Enables PCM Closed Loop Control of Compressor via pressure switch

+     * @Return	-	CTR_Code	-	Error code (if any) for setting solenoid

+     * @Param 	-	en		- 	Enable / Disable Closed Loop Control

+     */

+    CTR_Code 	SetClosedLoopControl(bool en);

+

+    /* Clears PCM sticky faults (indicators of past faults

+     * @Return	-	CTR_Code	-	Error code (if any) for setting solenoid

+     */

+    CTR_Code 	ClearStickyFaults();

+    

+    /* Get solenoid state

+     *

+     * @Return	-	CTR_Code	-	Error code (if any)

+     * @Param 	-	idx		- 	ID of solenoid (0-7) to return if solenoid is on.

+     * @Param	-	status	-	OK if solenoid enabled, false otherwise

+     */

+    CTR_Code 	GetSolenoid(UINT8 idx, bool &status);

+

+    /* Get pressure switch state

+     * @Return	-	CTR_Code	-	Error code (if any)

+     * @Param	-	status		-	True if pressure adequate, false if low

+     */

+    CTR_Code 	GetPressure(bool &status);

+

+    /* Get compressor state

+     * @Return	-	CTR_Code	-	Error code (if any)

+     * @Param	-	status		-	True if compress ouput is on, false if otherwise

+     */

+    CTR_Code	GetCompressor(bool &status);

+

+    /* Get closed loop control state

+     * @Return	-	CTR_Code	-	Error code (if any)

+     * @Param	-	status	-	True if closed loop enabled, false if otherwise

+     */

+    CTR_Code 	GetClosedLoopControl(bool &status);

+

+    /* Get compressor current draw

+     * @Return	-	CTR_Code	-	Error code (if any)

+     * @Param	-	status		-	Compressor current returned in Amperes (A)

+     */

+    CTR_Code 	GetCompressorCurrent(float &status);

+

+    /* Get voltage across solenoid rail

+     * @Return	-	CTR_Code	-	Error code (if any)

+     * @Param	-	status		-	Voltage across solenoid rail in Volts (V)

+     */

+    CTR_Code 	GetSolenoidVoltage(float &status);

+

+    /* Get hardware fault value

+     * @Return	-	CTR_Code	-	Error code (if any)

+     * @Param	-	status		-	True if hardware failure detected, false if otherwise

+     */

+    CTR_Code 	GetHardwareFault(bool &status);

+

+    /* Get compressor fault value

+     * @Return	-	CTR_Code	-	Error code (if any)

+     * @Param	-	status		-	True if abnormally high compressor current detected, false if otherwise

+     */

+    CTR_Code 	GetCompressorCurrentTooHighFault(bool &status);

+

+    /* Get solenoid fault value

+     * @Return	-	CTR_Code	-	Error code (if any)

+     * @Param	-	status		-	True if shorted solenoid detected, false if otherwise

+     */

+    CTR_Code 	GetSolenoidFault(bool &status);

+

+    /* Get compressor sticky fault value

+     * @Return	-	CTR_Code	-	Error code (if any)

+     * @Param	-	status		-	True if solenoid had previously been shorted

+     * 								(and sticky fault was not cleared), false if otherwise

+     */

+    CTR_Code 	GetCompressorCurrentTooHighStickyFault(bool &status);

+    /* Get compressor shorted sticky fault value

+     * @Return	-	CTR_Code	-	Error code (if any)

+     * @Param	-	status		-	True if compressor output is shorted, false if otherwise

+     */

+    CTR_Code 	GetCompressorShortedStickyFault(bool &status);

+    /* Get compressor shorted fault value

+     * @Return	-	CTR_Code	-	Error code (if any)

+     * @Param	-	status		-	True if compressor output is shorted, false if otherwise

+     */

+    CTR_Code 	GetCompressorShortedFault(bool &status);

+    /* Get compressor is not connected sticky fault value

+     * @Return	-	CTR_Code	-	Error code (if any)

+     * @Param	-	status		-	True if compressor current is too low, 

+     * 					indicating compressor is not connected, false if otherwise

+     */

+    CTR_Code 	GetCompressorNotConnectedStickyFault(bool &status);

+    /* Get compressor is not connected fault value

+     * @Return	-	CTR_Code	-	Error code (if any)

+     * @Param	-	status		-	True if compressor current is too low, 

+     * 					indicating compressor is not connected, false if otherwise

+     */

+    CTR_Code 	GetCompressorNotConnectedFault(bool &status);

+

+    /* Get solenoid sticky fault value

+     * @Return	-	CTR_Code	-	Error code (if any)

+     * @Param	-	status		-	True if compressor had previously been shorted

+     * 								(and sticky fault was not cleared), false if otherwise

+     */

+    CTR_Code 	GetSolenoidStickyFault(bool &status);

+

+    /* Get battery voltage

+     * @Return	-	CTR_Code	-	Error code (if any)

+     * @Param	-	status		-	Voltage across PCM power ports in Volts (V)

+     */

+    CTR_Code 	GetBatteryVoltage(float &status);

+    

+    /* Set PCM Device Number and according CAN frame IDs

+     * @Return	-	void

+     * @Param	-	deviceNumber	-	Device number of PCM to control

+     */

+    void	SetDeviceNumber(UINT8 deviceNumber);

+    /* Get number of total failed PCM Control Frame

+     * @Return	-	CTR_Code	-	Error code (if any)

+     * @Param	-	status		-	Number of failed control frames (tokenization fails)

+     * @WARNING	-	Return only valid if [SeekDebugFrames] is enabled

+     * 				See function SeekDebugFrames

+     * 				See function EnableSeekDebugFrames

+     */

+	CTR_Code GetNumberOfFailedControlFrames(UINT16 &status);

+    

+    /* Get raw Solenoid Blacklist

+     * @Return	-	CTR_Code	-	Error code (if any)

+     * @Param	-	status		-	Raw binary breakdown of Solenoid Blacklist

+     * 								BIT7 = Solenoid 1, BIT6 = Solenoid 2, etc.

+     * @WARNING	-	Return only valid if [SeekStatusFaultFrames] is enabled

+     * 				See function SeekStatusFaultFrames

+     * 				See function EnableSeekStatusFaultFrames

+     */

+    CTR_Code 	GetSolenoidBlackList(UINT8 &status);

+

+    /* Get solenoid Blacklist status

+     * - Blacklisted solenoids cannot be enabled until PCM is power cycled

+     * @Return	-	CTR_Code	-	Error code (if any)

+     * @Param	-	idx			-	ID of solenoid [0,7]

+     * @Param	-	status		-	True if Solenoid is blacklisted, false if otherwise

+     * @WARNING	-	Return only valid if [SeekStatusFaultFrames] is enabled

+     * 				See function SeekStatusFaultFrames

+     * 				See function EnableSeekStatusFaultFrames

+     */

+    CTR_Code 	IsSolenoidBlacklisted(UINT8 idx, bool &status);

+

+    /* Return status of module enable/disable

+     * @Return	-	CTR_Code	-	Error code (if any)

+     * @Param	-	status		-	Returns TRUE if PCM is enabled, FALSE if disabled

+     */

+    CTR_Code	isModuleEnabled(bool &status);

+

+    /* Get solenoid Blacklist status

+     * @Return	-	CTR_Code	-	Error code (if any)

+     * @Param	-	idx			-	ID of solenoid [0,7] to fire one shot pulse.

+     */

+    CTR_Code FireOneShotSolenoid(UINT8 idx);

+

+    /* Configure the pulse width of a solenoid channel for one-shot pulse.

+	 * Preprogrammed pulsewidth is 10ms resolute and can be between 20ms and 5.1s.

+     * @Return	-	CTR_Code	-	Error code (if any)

+     * @Param	-	idx			-	ID of solenoid [0,7] to configure.

+     * @Param	-	durMs		-	pulse width in ms.

+     */

+    CTR_Code SetOneShotDurationMs(UINT8 idx,uint32_t durMs);

+

+};

+//------------------ C interface --------------------------------------------//

+extern "C" {

+	void * c_PCM_Init(void);

+	CTR_Code c_SetSolenoids(void * handle,uint8_t value,uint8_t mask);

+	CTR_Code c_SetClosedLoopControl(void * handle,INT8 param);

+	CTR_Code c_ClearStickyFaults(void * handle,INT8 param);

+	CTR_Code c_GetSolenoid(void * handle,UINT8 idx,INT8 * status);

+	CTR_Code c_GetPressure(void * handle,INT8 * status);

+	CTR_Code c_GetCompressor(void * handle,INT8 * status);

+	CTR_Code c_GetClosedLoopControl(void * handle,INT8 * status);

+	CTR_Code c_GetCompressorCurrent(void * handle,float * status);

+	CTR_Code c_GetSolenoidVoltage(void * handle,float*status);

+	CTR_Code c_GetHardwareFault(void * handle,INT8*status);

+	CTR_Code c_GetCompressorFault(void * handle,INT8*status);

+	CTR_Code c_GetSolenoidFault(void * handle,INT8*status);

+	CTR_Code c_GetCompressorStickyFault(void * handle,INT8*status);

+	CTR_Code c_GetSolenoidStickyFault(void * handle,INT8*status);

+	CTR_Code c_GetBatteryVoltage(void * handle,float*status);

+	void c_SetDeviceNumber_PCM(void * handle,UINT8 deviceNumber);

+	void c_EnableSeekStatusFrames(void * handle,INT8 enable);

+	void c_EnableSeekStatusFaultFrames(void * handle,INT8 enable);

+	void c_EnableSeekDebugFrames(void * handle,INT8 enable);

+	CTR_Code c_GetNumberOfFailedControlFrames(void * handle,UINT16*status);

+	CTR_Code c_GetSolenoidBlackList(void * handle,UINT8 *status);

+	CTR_Code c_IsSolenoidBlacklisted(void * handle,UINT8 idx,INT8*status);

+}

+#endif

diff --git a/aos/externals/allwpilib/hal/lib/Athena/ctre/PDP.cpp b/aos/externals/allwpilib/hal/lib/Athena/ctre/PDP.cpp
new file mode 100644
index 0000000..2fb4c8f
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/ctre/PDP.cpp
@@ -0,0 +1,230 @@
+#include "PDP.h"

+#include "NetworkCommunication/CANSessionMux.h"	//CAN Comm

+#include <string.h> // memset

+#include <unistd.h> // usleep

+

+#define STATUS_1  		0x8041400

+#define STATUS_2  		0x8041440

+#define STATUS_3  		0x8041480

+#define STATUS_ENERGY	0x8041740

+

+#define CONTROL_1		0x08041C00	/* PDP_Control_ClearStats */

+

+#define EXPECTED_RESPONSE_TIMEOUT_MS	(50)

+#define GET_STATUS1()		CtreCanNode::recMsg<PdpStatus1_t> rx = GetRx<PdpStatus1_t>(STATUS_1,EXPECTED_RESPONSE_TIMEOUT_MS)

+#define GET_STATUS2()		CtreCanNode::recMsg<PdpStatus2_t> rx = GetRx<PdpStatus2_t>(STATUS_2,EXPECTED_RESPONSE_TIMEOUT_MS)

+#define GET_STATUS3()		CtreCanNode::recMsg<PdpStatus3_t> rx = GetRx<PdpStatus3_t>(STATUS_3,EXPECTED_RESPONSE_TIMEOUT_MS)

+#define GET_STATUS_ENERGY()	CtreCanNode::recMsg<PDP_Status_Energy_t> rx = GetRx<PDP_Status_Energy_t>(STATUS_ENERGY,EXPECTED_RESPONSE_TIMEOUT_MS)

+

+/* encoder/decoders */

+typedef struct _PdpStatus1_t{

+	unsigned chan1_h8:8;

+	unsigned chan2_h6:6;

+	unsigned chan1_l2:2;

+	unsigned chan3_h4:4;

+	unsigned chan2_l4:4;

+	unsigned chan4_h2:2;

+	unsigned chan3_l6:6;

+	unsigned chan4_l8:8;

+	unsigned chan5_h8:8;

+	unsigned chan6_h6:6;

+	unsigned chan5_l2:2;

+	unsigned reserved4:4;

+	unsigned chan6_l4:4;

+}PdpStatus1_t;

+typedef struct _PdpStatus2_t{

+	unsigned chan7_h8:8;

+	unsigned chan8_h6:6;

+	unsigned chan7_l2:2;

+	unsigned chan9_h4:4;

+	unsigned chan8_l4:4;

+	unsigned chan10_h2:2;

+	unsigned chan9_l6:6;

+	unsigned chan10_l8:8;

+	unsigned chan11_h8:8;

+	unsigned chan12_h6:6;

+	unsigned chan11_l2:2;

+	unsigned reserved4:4;

+	unsigned chan12_l4:4;

+}PdpStatus2_t;

+typedef struct _PdpStatus3_t{

+	unsigned chan13_h8:8;

+	unsigned chan14_h6:6;

+	unsigned chan13_l2:2;

+	unsigned chan15_h4:4;

+	unsigned chan14_l4:4;

+	unsigned chan16_h2:2;

+	unsigned chan15_l6:6;

+	unsigned chan16_l8:8;

+	unsigned internalResBattery_mOhms:8;

+	unsigned busVoltage:8;

+	unsigned temp:8;

+}PdpStatus3_t;

+typedef struct _PDP_Status_Energy_t {

+	unsigned TmeasMs_likelywillbe20ms_:8;

+	unsigned TotalCurrent_125mAperunit_h8:8;

+	unsigned Power_125mWperunit_h4:4;

+	unsigned TotalCurrent_125mAperunit_l4:4;

+	unsigned Power_125mWperunit_m8:8;

+	unsigned Energy_125mWPerUnitXTmeas_h4:4;

+	unsigned Power_125mWperunit_l4:4;

+	unsigned Energy_125mWPerUnitXTmeas_mh8:8;

+	unsigned Energy_125mWPerUnitXTmeas_ml8:8;

+	unsigned Energy_125mWPerUnitXTmeas_l8:8;

+} PDP_Status_Energy_t ;

+

+PDP::PDP(UINT8 deviceNumber): CtreCanNode(deviceNumber)

+{

+	RegisterRx(STATUS_1 | deviceNumber );

+	RegisterRx(STATUS_2 | deviceNumber );

+	RegisterRx(STATUS_3 | deviceNumber );

+}

+/* PDP D'tor

+ */

+PDP::~PDP()

+{

+}

+

+CTR_Code PDP::GetChannelCurrent(UINT8 idx, double &current)

+{

+	CTR_Code retval = CTR_InvalidParamValue;

+	uint32_t raw = 0;

+

+	if(idx <= 5){

+		GET_STATUS1();

+	    retval = rx.err;

+		switch(idx){

+			case 0:	raw = ((uint32_t)rx->chan1_h8 << 2) | rx->chan1_l2;	break;

+			case 1:	raw = ((uint32_t)rx->chan2_h6 << 4) | rx->chan2_l4;	break;

+			case 2:	raw = ((uint32_t)rx->chan3_h4 << 6) | rx->chan3_l6;	break;

+			case 3:	raw = ((uint32_t)rx->chan4_h2 << 8) | rx->chan4_l8;	break;

+			case 4:	raw = ((uint32_t)rx->chan5_h8 << 2) | rx->chan5_l2;	break;

+			case 5:	raw = ((uint32_t)rx->chan6_h6 << 4) | rx->chan6_l4;	break;

+			default:	retval = CTR_InvalidParamValue;	break;

+		}

+	}else if(idx <= 11){

+		GET_STATUS2();

+	    retval = rx.err;

+		switch(idx){

+			case  6:	raw = ((uint32_t)rx->chan7_h8  << 2) | rx->chan7_l2;	break;

+			case  7:	raw = ((uint32_t)rx->chan8_h6  << 4) | rx->chan8_l4;	break;

+			case  8:	raw = ((uint32_t)rx->chan9_h4  << 6) | rx->chan9_l6;	break;

+			case  9:	raw = ((uint32_t)rx->chan10_h2 << 8) | rx->chan10_l8;	break;

+			case 10:	raw = ((uint32_t)rx->chan11_h8 << 2) | rx->chan11_l2;	break;

+			case 11:	raw = ((uint32_t)rx->chan12_h6 << 4) | rx->chan12_l4;	break;

+			default:	retval = CTR_InvalidParamValue;	break;

+		}

+	}else if(idx <= 15){

+		GET_STATUS3();

+	    retval = rx.err;

+		switch(idx){

+			case 12:	raw = ((uint32_t)rx->chan13_h8  << 2) | rx->chan13_l2;	break;

+			case 13:	raw = ((uint32_t)rx->chan14_h6  << 4) | rx->chan14_l4;	break;

+			case 14:	raw = ((uint32_t)rx->chan15_h4  << 6) | rx->chan15_l6;	break;

+			case 15:	raw = ((uint32_t)rx->chan16_h2  << 8) | rx->chan16_l8;	break;

+			default:	retval = CTR_InvalidParamValue;	break;

+		}

+	}

+	/* convert to amps */

+	current = (double)raw * 0.125;  /* 7.3 fixed pt value in Amps */

+	/* signal caller with success */

+	return retval;

+}

+CTR_Code PDP::GetVoltage(double &voltage)

+{

+	GET_STATUS3();

+	uint32_t raw = rx->busVoltage;

+	voltage = (double)raw * 0.05 + 4.0; /* 50mV per unit plus 4V. */;

+	return rx.err;

+}

+CTR_Code PDP::GetTemperature(double &tempC)

+{

+	GET_STATUS3();

+	uint32_t raw = rx->temp;

+	tempC =	(double)raw * 1.03250836957542 - 67.8564500484966;

+	return rx.err;

+}

+CTR_Code PDP::GetTotalCurrent(double &currentAmps)

+{

+	GET_STATUS_ENERGY();

+	uint32_t raw;

+	raw = rx->TotalCurrent_125mAperunit_h8;

+	raw <<= 4;

+	raw |=  rx->TotalCurrent_125mAperunit_l4;

+	currentAmps = 0.125 * raw;

+	return rx.err;

+}

+CTR_Code PDP::GetTotalPower(double &powerWatts)

+{

+	GET_STATUS_ENERGY();

+	uint32_t raw;

+	raw = rx->Power_125mWperunit_h4;

+	raw <<= 8;

+	raw |=  rx->Power_125mWperunit_m8;

+	raw <<= 4;

+	raw |=  rx->Power_125mWperunit_l4;

+	powerWatts = 0.125 * raw;

+	return rx.err;

+}

+CTR_Code PDP::GetTotalEnergy(double &energyJoules)

+{

+	GET_STATUS_ENERGY();

+	uint32_t raw;

+	raw = rx->Energy_125mWPerUnitXTmeas_h4;

+	raw <<= 8;

+	raw |=  rx->Energy_125mWPerUnitXTmeas_mh8;

+	raw <<= 8;

+	raw |=  rx->Energy_125mWPerUnitXTmeas_ml8;

+	raw <<= 8;

+	raw |=  rx->Energy_125mWPerUnitXTmeas_l8;

+	energyJoules = 0.125 * raw; 						/* mW integrated every TmeasMs */

+	energyJoules *= rx->TmeasMs_likelywillbe20ms_;	/* multiplied by TmeasMs = joules */

+	return rx.err;

+}

+/* Clear sticky faults.

+ * @Return	-	CTR_Code	-	Error code (if any)

+ */

+CTR_Code PDP::ClearStickyFaults()

+{

+	int32_t status = 0;

+	uint8_t pdpControl[] = { 0x80 }; /* only bit set is ClearStickyFaults */

+	FRC_NetworkCommunication_CANSessionMux_sendMessage(CONTROL_1  | GetDeviceNumber(), pdpControl, sizeof(pdpControl), 0, &status);

+	if(status)

+		return CTR_TxFailed;

+	return CTR_OKAY;

+}

+

+/* Reset Energy Signals

+ * @Return	-	CTR_Code	-	Error code (if any)

+ */

+CTR_Code PDP::ResetEnergy()

+{

+	int32_t status = 0;

+	uint8_t pdpControl[] = { 0x40 }; /* only bit set is ResetEnergy */

+	FRC_NetworkCommunication_CANSessionMux_sendMessage(CONTROL_1  | GetDeviceNumber(), pdpControl, sizeof(pdpControl), 0, &status);

+	if(status)

+		return CTR_TxFailed;

+	return CTR_OKAY;

+}

+//------------------ C interface --------------------------------------------//

+extern "C" {

+	void * c_PDP_Init(void)

+	{

+		return new PDP();

+	}

+	CTR_Code c_GetChannelCurrent(void * handle,UINT8 idx, double *status)

+	{

+		return ((PDP*)handle)-> GetChannelCurrent(idx,*status);

+	}

+	CTR_Code c_GetVoltage(void * handle,double *status)

+	{

+		return ((PDP*)handle)-> GetVoltage(*status);

+	}

+	CTR_Code c_GetTemperature(void * handle,double *status)

+	{

+		return ((PDP*)handle)-> GetTemperature(*status);

+	}

+	void c_SetDeviceNumber_PDP(void * handle,UINT8 deviceNumber)

+	{

+	}

+}

diff --git a/aos/externals/allwpilib/hal/lib/Athena/ctre/PDP.h b/aos/externals/allwpilib/hal/lib/Athena/ctre/PDP.h
new file mode 100644
index 0000000..a289d1a
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/ctre/PDP.h
@@ -0,0 +1,64 @@
+#ifndef PDP_H_

+#define PDP_H_

+#include "ctre.h"				//BIT Defines + Typedefs

+#include <NetworkCommunication/CANSessionMux.h>	//CAN Comm

+#include "CtreCanNode.h"

+#include <pthread.h>

+class PDP : public CtreCanNode

+{

+public:

+    /* Get PDP Channel Current

+     *

+     * @Param	-	deviceNumber	-	Device ID for PDP. Factory default is 60. Function defaults to 60.

+     */

+    PDP(UINT8 deviceNumber=0);

+    ~PDP();

+    /* Get PDP Channel Current

+     *

+     * @Return	-	CTR_Code	-	Error code (if any)

+     *

+     * @Param	-	idx			-	ID of channel to return current for (channels 1-16)

+     *

+     * @Param	-	status		-	Current of channel 'idx' in Amps (A)

+     */

+    CTR_Code GetChannelCurrent(UINT8 idx, double &status);

+

+    /* Get Bus Voltage of PDP

+     *

+     * @Return	-	CTR_Code	- 	Error code (if any)

+     *

+     * @Param	-	status		- 	Voltage (V) across PDP

+     */

+    CTR_Code GetVoltage(double &status);

+

+    /* Get Temperature of PDP

+     *

+     * @Return	-	CTR_Code	-	Error code (if any)

+     *

+     * @Param	-	status		-	Temperature of PDP in Centigrade / Celcius (C)

+     */

+    CTR_Code GetTemperature(double &status);

+

+	CTR_Code GetTotalCurrent(double &currentAmps);

+	CTR_Code GetTotalPower(double &powerWatts);

+	CTR_Code GetTotalEnergy(double &energyJoules);

+    /* Clear sticky faults.

+     * @Return	-	CTR_Code	-	Error code (if any)

+     */

+	CTR_Code ClearStickyFaults();

+

+	/* Reset Energy Signals

+	 * @Return	-	CTR_Code	-	Error code (if any)

+	 */

+	CTR_Code ResetEnergy();

+private:

+    uint64_t ReadCurrents(uint8_t api);

+};

+extern "C" {

+	void * c_PDP_Init();

+	CTR_Code c_GetChannelCurrent(void * handle,UINT8 idx, double *status);

+	CTR_Code c_GetVoltage(void * handle,double *status);

+	CTR_Code c_GetTemperature(void * handle,double *status);

+	void c_SetDeviceNumber_PDP(void * handle,UINT8 deviceNumber);

+}

+#endif /* PDP_H_ */

diff --git a/aos/externals/allwpilib/hal/lib/Athena/ctre/ctre.h b/aos/externals/allwpilib/hal/lib/Athena/ctre/ctre.h
new file mode 100644
index 0000000..c2d3f69
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/ctre/ctre.h
@@ -0,0 +1,50 @@
+#ifndef GLOBAL_H

+#define GLOBAL_H

+

+//Bit Defines

+#define BIT0 0x01

+#define BIT1 0x02

+#define BIT2 0x04

+#define BIT3 0x08

+#define BIT4 0x10

+#define BIT5 0x20

+#define BIT6 0x40

+#define BIT7 0x80

+#define BIT8  0x0100

+#define BIT9  0x0200

+#define BIT10 0x0400

+#define BIT11 0x0800

+#define BIT12 0x1000

+#define BIT13 0x2000

+#define BIT14 0x4000

+#define BIT15 0x8000

+

+//Signed

+typedef	signed char	INT8;

+typedef	signed short	INT16;

+typedef	signed int	INT32;

+typedef	signed long long INT64;

+

+//Unsigned

+typedef	unsigned char	UINT8;

+typedef	unsigned short	UINT16;

+typedef	unsigned int	UINT32;

+typedef	unsigned long long UINT64;

+

+//Other

+typedef	unsigned char	UCHAR;

+typedef unsigned short	USHORT;

+typedef	unsigned int	UINT;

+typedef unsigned long	ULONG;

+

+typedef enum {

+		CTR_OKAY,				//!< No Error - Function executed as expected

+		CTR_RxTimeout,			//!< CAN frame has not been received within specified period of time.

+		CTR_TxTimeout,			//!< Not used.

+		CTR_InvalidParamValue, 	//!< Caller passed an invalid param

+		CTR_UnexpectedArbId,	//!< Specified CAN Id is invalid.

+		CTR_TxFailed,			//!< Could not transmit the CAN frame.

+		CTR_SigNotUpdated,		//!< Have not received an value response for signal.

+}CTR_Code;

+

+#endif

diff --git a/aos/externals/allwpilib/hal/lib/Athena/i2clib/i2c-lib.h b/aos/externals/allwpilib/hal/lib/Athena/i2clib/i2c-lib.h
new file mode 100644
index 0000000..b34cb33
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/i2clib/i2c-lib.h
@@ -0,0 +1,16 @@
+#ifndef __I2C_LIB_H__

+#define __I2C_LIB_H__

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+int i2clib_open(const char *device);

+void i2clib_close(int handle);

+int i2clib_read(int handle, uint8_t dev_addr, char *recv_buf, int32_t recv_size);

+int i2clib_write(int handle, uint8_t dev_addr, const char *send_buf, int32_t send_size);

+int i2clib_writeread(int handle, uint8_t dev_addr, const char *send_buf, int32_t send_size, char *recv_buf, int32_t recv_size);

+#ifdef __cplusplus

+}

+#endif

+

+#endif /* __I2C_LIB_H__ */
\ No newline at end of file
diff --git a/aos/externals/allwpilib/hal/lib/Athena/i2clib/i2clib/environs.h b/aos/externals/allwpilib/hal/lib/Athena/i2clib/i2clib/environs.h
new file mode 100644
index 0000000..d250585
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/i2clib/i2clib/environs.h
@@ -0,0 +1,66 @@
+/*!

+   \file environs.h

+   \brief Defines export symbols and namespace aliases

+*/

+/*

+   Copyright (c) 2014,

+   National Instruments Corporation.

+   All rights reserved.

+

+   File:        $Id: //lvaddon/FIRST/FRC/trunk/2015/tools/frcrti/export/1.0/1.0.0a6/includes/wpilib/i2clib/i2clib/environs.h#1 $

+   Author:      nipg.pl

+   Originated:  Mon Feb 10 10:39:42 2014

+*/

+

+#ifndef ___i2clib_environs_h___

+#define ___i2clib_environs_h___

+

+#include <nibuild/platform.h>

+

+/*

+ * kI2CLIBExportSymbols directs the build to export symbols modified by

+ * the kI2CLIBExport keyword. kI2CLIBNoExportSymbols directs the build to not

+ * import or export symbols modified by the kI2CLIBExport keyword. If

+ * neither of these are defined, the symbols modified by kI2CLIBExport are

+ * imported. These should be defined only when building the component,

+ * so clients do not need to trouble themselves with it.

+ */

+#if defined(kI2CLIBExportSymbols)

+   #define kI2CLIBExport kNIExport

+   #define kI2CLIBExportPre kNIExportPre

+   #define kI2CLIBExportPost kNIExportPost

+   #define kI2CLIBExportInline kNIExportInline

+   #define kI2CLIBExportData kNIExportData

+#elif defined(kI2CLIBNoExportSymbols)

+   #define kI2CLIBExport

+   #define kI2CLIBExportPre

+   #define kI2CLIBExportPost

+   #define kI2CLIBExportInline

+   #define kI2CLIBExportData

+#else

+   #define kI2CLIBExport kNIImport

+   #define kI2CLIBExportPre kNIImportPre

+   #define kI2CLIBExportPost kNIImportPost

+   #define kI2CLIBExportInline kNIImportInline

+   #define kI2CLIBExportData kNIImportData

+#endif

+

+// namespace declarations for aliasing ...

+

+#ifdef __cplusplus

+

+

+/*!

+   \namespace nI2CLIB_1_0

+   \brief i2c user-mode library Release 1.0

+*/

+namespace nI2CLIB_1_0

+{

+   // current versioned namespace aliases used by this package

+

+}

+

+#endif // __cplusplus

+

+#endif // ___i2clib_environs_h___

+

diff --git a/aos/externals/allwpilib/hal/lib/Athena/spilib/spi-lib.h b/aos/externals/allwpilib/hal/lib/Athena/spilib/spi-lib.h
new file mode 100644
index 0000000..b5c2a7a
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/spilib/spi-lib.h
@@ -0,0 +1,19 @@
+#ifndef __SPI_LIB_H__

+#define __SPI_LIB_H__

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+int spilib_open(const char *device);

+void spilib_close(int handle);

+int spilib_setspeed(int handle, uint32_t speed);

+int spilib_setbitsperword(int handle, uint8_t bpw);

+int spilib_setopts(int handle, int msb_first, int sample_on_trailing, int clk_idle_high);

+int spilib_read(int handle, char *recv_buf, int32_t size);

+int spilib_write(int handle, const char *send_buf, int32_t size);

+int spilib_writeread(int handle, const char *send_buf, char *recv_buf, int32_t size);

+#ifdef __cplusplus

+}

+#endif

+

+#endif /* __SPI_LIB_H__ */
\ No newline at end of file
diff --git a/aos/externals/allwpilib/hal/lib/Athena/visa/visa.h b/aos/externals/allwpilib/hal/lib/Athena/visa/visa.h
new file mode 100644
index 0000000..3c6ad30
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/visa/visa.h
@@ -0,0 +1,1064 @@
+/*---------------------------------------------------------------------------*/
+/* Distributed by IVI Foundation Inc.                                        */
+/* Contains National Instruments extensions.                                 */
+/* Do not modify the contents of this file.                                  */
+/*---------------------------------------------------------------------------*/
+/*                                                                           */
+/* Title   : VISA.H                                                          */
+/* Date    : 10-09-2006                                                      */
+/* Purpose : Include file for the VISA Library 4.0 specification             */
+/*                                                                           */
+/*---------------------------------------------------------------------------*/
+/* When using NI-VISA extensions, you must link with the VISA library that   */
+/* comes with NI-VISA.  Currently, the extensions provided by NI-VISA are:   */
+/*                                                                           */
+/* PXI (Compact PCI eXtensions for Instrumentation) and PCI support.  To use */
+/* this, you must define the macro NIVISA_PXI before including this header.  */
+/* You must also create an INF file with the VISA Driver Development Wizard. */
+/*                                                                           */
+/* A fast set of macros for viPeekXX/viPokeXX that guarantees binary         */
+/* compatibility with other implementations of VISA.  To use this, you must  */
+/* define the macro NIVISA_PEEKPOKE before including this header.            */
+/*                                                                           */
+/* Support for USB devices that do not conform to a specific class.  To use  */
+/* this, you must define the macro NIVISA_USB before including this header.  */
+/* You must also create an INF file with the VISA Driver Development Wizard. */
+/*---------------------------------------------------------------------------*/
+
+#ifndef __VISA_HEADER__
+#define __VISA_HEADER__
+
+#include <stdarg.h>
+
+#if !defined(__VISATYPE_HEADER__)
+#include "visatype.h"
+#endif
+
+#define VI_SPEC_VERSION     (0x00400000UL)
+
+#if defined(__cplusplus) || defined(__cplusplus__)
+   extern "C" {
+#endif
+
+#if defined(_CVI_)
+#pragma EnableLibraryRuntimeChecking
+#endif
+
+/*- VISA Types --------------------------------------------------------------*/
+
+typedef ViObject             ViEvent;
+typedef ViEvent      _VI_PTR ViPEvent;
+typedef ViObject             ViFindList;
+typedef ViFindList   _VI_PTR ViPFindList;
+
+#if defined(_VI_INT64_UINT64_DEFINED) && defined(_VISA_ENV_IS_64_BIT)
+typedef ViUInt64             ViBusAddress;
+typedef ViUInt64             ViBusSize;
+typedef ViUInt64             ViAttrState;
+#else
+typedef ViUInt32             ViBusAddress;
+typedef ViUInt32             ViBusSize;
+typedef ViUInt32             ViAttrState;
+#endif
+
+#if defined(_VI_INT64_UINT64_DEFINED)
+typedef ViUInt64             ViBusAddress64;
+typedef ViBusAddress64 _VI_PTR ViPBusAddress64;
+#endif
+
+typedef ViUInt32             ViEventType;
+typedef ViEventType  _VI_PTR ViPEventType;
+typedef ViEventType  _VI_PTR ViAEventType;
+typedef void         _VI_PTR ViPAttrState;
+typedef ViAttr       _VI_PTR ViPAttr;
+typedef ViAttr       _VI_PTR ViAAttr;
+
+typedef ViString             ViKeyId;
+typedef ViPString            ViPKeyId;
+typedef ViUInt32             ViJobId;
+typedef ViJobId      _VI_PTR ViPJobId;
+typedef ViUInt32             ViAccessMode;
+typedef ViAccessMode _VI_PTR ViPAccessMode;
+typedef ViBusAddress _VI_PTR ViPBusAddress;
+typedef ViUInt32             ViEventFilter;
+
+typedef va_list              ViVAList;
+
+typedef ViStatus (_VI_FUNCH _VI_PTR ViHndlr)
+   (ViSession vi, ViEventType eventType, ViEvent event, ViAddr userHandle);
+
+/*- Resource Manager Functions and Operations -------------------------------*/
+
+ViStatus _VI_FUNC  viOpenDefaultRM (ViPSession vi);
+ViStatus _VI_FUNC  viFindRsrc      (ViSession sesn, ViString expr, ViPFindList vi,
+                                    ViPUInt32 retCnt, ViChar _VI_FAR desc[]);
+ViStatus _VI_FUNC  viFindNext      (ViFindList vi, ViChar _VI_FAR desc[]);
+ViStatus _VI_FUNC  viParseRsrc     (ViSession rmSesn, ViRsrc rsrcName,
+                                    ViPUInt16 intfType, ViPUInt16 intfNum);
+ViStatus _VI_FUNC  viParseRsrcEx   (ViSession rmSesn, ViRsrc rsrcName, ViPUInt16 intfType,
+                                    ViPUInt16 intfNum, ViChar _VI_FAR rsrcClass[],
+                                    ViChar _VI_FAR expandedUnaliasedName[],
+                                    ViChar _VI_FAR aliasIfExists[]);
+ViStatus _VI_FUNC  viOpen          (ViSession sesn, ViRsrc name, ViAccessMode mode,
+                                    ViUInt32 timeout, ViPSession vi);
+
+/*- Resource Template Operations --------------------------------------------*/
+
+ViStatus _VI_FUNC  viClose         (ViObject vi);
+ViStatus _VI_FUNC  viSetAttribute  (ViObject vi, ViAttr attrName, ViAttrState attrValue);
+ViStatus _VI_FUNC  viGetAttribute  (ViObject vi, ViAttr attrName, void _VI_PTR attrValue);
+ViStatus _VI_FUNC  viStatusDesc    (ViObject vi, ViStatus status, ViChar _VI_FAR desc[]);
+ViStatus _VI_FUNC  viTerminate     (ViObject vi, ViUInt16 degree, ViJobId jobId);
+
+ViStatus _VI_FUNC  viLock          (ViSession vi, ViAccessMode lockType, ViUInt32 timeout,
+                                    ViKeyId requestedKey, ViChar _VI_FAR accessKey[]);
+ViStatus _VI_FUNC  viUnlock        (ViSession vi);
+ViStatus _VI_FUNC  viEnableEvent   (ViSession vi, ViEventType eventType, ViUInt16 mechanism,
+                                    ViEventFilter context);
+ViStatus _VI_FUNC  viDisableEvent  (ViSession vi, ViEventType eventType, ViUInt16 mechanism);
+ViStatus _VI_FUNC  viDiscardEvents (ViSession vi, ViEventType eventType, ViUInt16 mechanism);
+ViStatus _VI_FUNC  viWaitOnEvent   (ViSession vi, ViEventType inEventType, ViUInt32 timeout,
+                                    ViPEventType outEventType, ViPEvent outContext);
+ViStatus _VI_FUNC  viInstallHandler(ViSession vi, ViEventType eventType, ViHndlr handler,
+                                    ViAddr userHandle);
+ViStatus _VI_FUNC  viUninstallHandler(ViSession vi, ViEventType eventType, ViHndlr handler,
+                                      ViAddr userHandle);
+
+/*- Basic I/O Operations ----------------------------------------------------*/
+
+ViStatus _VI_FUNC  viRead          (ViSession vi, ViPBuf buf, ViUInt32 cnt, ViPUInt32 retCnt);
+ViStatus _VI_FUNC  viReadAsync     (ViSession vi, ViPBuf buf, ViUInt32 cnt, ViPJobId  jobId);
+ViStatus _VI_FUNC  viReadToFile    (ViSession vi, ViConstString filename, ViUInt32 cnt,
+                                    ViPUInt32 retCnt);
+ViStatus _VI_FUNC  viWrite         (ViSession vi, ViBuf  buf, ViUInt32 cnt, ViPUInt32 retCnt);
+ViStatus _VI_FUNC  viWriteAsync    (ViSession vi, ViBuf  buf, ViUInt32 cnt, ViPJobId  jobId);
+ViStatus _VI_FUNC  viWriteFromFile (ViSession vi, ViConstString filename, ViUInt32 cnt,
+                                    ViPUInt32 retCnt);
+ViStatus _VI_FUNC  viAssertTrigger (ViSession vi, ViUInt16 protocol);
+ViStatus _VI_FUNC  viReadSTB       (ViSession vi, ViPUInt16 status);
+ViStatus _VI_FUNC  viClear         (ViSession vi);
+
+/*- Formatted and Buffered I/O Operations -----------------------------------*/
+
+ViStatus _VI_FUNC  viSetBuf        (ViSession vi, ViUInt16 mask, ViUInt32 size);
+ViStatus _VI_FUNC  viFlush         (ViSession vi, ViUInt16 mask);
+
+ViStatus _VI_FUNC  viBufWrite      (ViSession vi, ViBuf  buf, ViUInt32 cnt, ViPUInt32 retCnt);
+ViStatus _VI_FUNC  viBufRead       (ViSession vi, ViPBuf buf, ViUInt32 cnt, ViPUInt32 retCnt);
+
+ViStatus _VI_FUNCC viPrintf        (ViSession vi, ViString writeFmt, ...);
+ViStatus _VI_FUNC  viVPrintf       (ViSession vi, ViString writeFmt, ViVAList params);
+ViStatus _VI_FUNCC viSPrintf       (ViSession vi, ViPBuf buf, ViString writeFmt, ...);
+ViStatus _VI_FUNC  viVSPrintf      (ViSession vi, ViPBuf buf, ViString writeFmt,
+                                    ViVAList parms);
+
+ViStatus _VI_FUNCC viScanf         (ViSession vi, ViString readFmt, ...);
+ViStatus _VI_FUNC  viVScanf        (ViSession vi, ViString readFmt, ViVAList params);
+ViStatus _VI_FUNCC viSScanf        (ViSession vi, ViBuf buf, ViString readFmt, ...);
+ViStatus _VI_FUNC  viVSScanf       (ViSession vi, ViBuf buf, ViString readFmt,
+                                    ViVAList parms);
+
+ViStatus _VI_FUNCC viQueryf        (ViSession vi, ViString writeFmt, ViString readFmt, ...);
+ViStatus _VI_FUNC  viVQueryf       (ViSession vi, ViString writeFmt, ViString readFmt, 
+                                    ViVAList params);
+
+/*- Memory I/O Operations ---------------------------------------------------*/
+
+ViStatus _VI_FUNC  viIn8           (ViSession vi, ViUInt16 space,
+                                    ViBusAddress offset, ViPUInt8  val8);
+ViStatus _VI_FUNC  viOut8          (ViSession vi, ViUInt16 space,
+                                    ViBusAddress offset, ViUInt8   val8);
+ViStatus _VI_FUNC  viIn16          (ViSession vi, ViUInt16 space,
+                                    ViBusAddress offset, ViPUInt16 val16);
+ViStatus _VI_FUNC  viOut16         (ViSession vi, ViUInt16 space,
+                                    ViBusAddress offset, ViUInt16  val16);
+ViStatus _VI_FUNC  viIn32          (ViSession vi, ViUInt16 space,
+                                    ViBusAddress offset, ViPUInt32 val32);
+ViStatus _VI_FUNC  viOut32         (ViSession vi, ViUInt16 space,
+                                    ViBusAddress offset, ViUInt32  val32);
+
+#if defined(_VI_INT64_UINT64_DEFINED)
+ViStatus _VI_FUNC  viIn64          (ViSession vi, ViUInt16 space,
+                                    ViBusAddress offset, ViPUInt64 val64);
+ViStatus _VI_FUNC  viOut64         (ViSession vi, ViUInt16 space,
+                                    ViBusAddress offset, ViUInt64  val64);
+
+ViStatus _VI_FUNC  viIn8Ex         (ViSession vi, ViUInt16 space,
+                                    ViBusAddress64 offset, ViPUInt8  val8);
+ViStatus _VI_FUNC  viOut8Ex        (ViSession vi, ViUInt16 space,
+                                    ViBusAddress64 offset, ViUInt8   val8);
+ViStatus _VI_FUNC  viIn16Ex        (ViSession vi, ViUInt16 space,
+                                    ViBusAddress64 offset, ViPUInt16 val16);
+ViStatus _VI_FUNC  viOut16Ex       (ViSession vi, ViUInt16 space,
+                                    ViBusAddress64 offset, ViUInt16  val16);
+ViStatus _VI_FUNC  viIn32Ex        (ViSession vi, ViUInt16 space,
+                                    ViBusAddress64 offset, ViPUInt32 val32);
+ViStatus _VI_FUNC  viOut32Ex       (ViSession vi, ViUInt16 space,
+                                    ViBusAddress64 offset, ViUInt32  val32);
+ViStatus _VI_FUNC  viIn64Ex        (ViSession vi, ViUInt16 space,
+                                    ViBusAddress64 offset, ViPUInt64 val64);
+ViStatus _VI_FUNC  viOut64Ex       (ViSession vi, ViUInt16 space,
+                                    ViBusAddress64 offset, ViUInt64  val64);
+#endif
+
+ViStatus _VI_FUNC  viMoveIn8       (ViSession vi, ViUInt16 space, ViBusAddress offset,
+                                    ViBusSize length, ViAUInt8  buf8);
+ViStatus _VI_FUNC  viMoveOut8      (ViSession vi, ViUInt16 space, ViBusAddress offset,
+                                    ViBusSize length, ViAUInt8  buf8);
+ViStatus _VI_FUNC  viMoveIn16      (ViSession vi, ViUInt16 space, ViBusAddress offset,
+                                    ViBusSize length, ViAUInt16 buf16);
+ViStatus _VI_FUNC  viMoveOut16     (ViSession vi, ViUInt16 space, ViBusAddress offset,
+                                    ViBusSize length, ViAUInt16 buf16);
+ViStatus _VI_FUNC  viMoveIn32      (ViSession vi, ViUInt16 space, ViBusAddress offset,
+                                    ViBusSize length, ViAUInt32 buf32);
+ViStatus _VI_FUNC  viMoveOut32     (ViSession vi, ViUInt16 space, ViBusAddress offset,
+                                    ViBusSize length, ViAUInt32 buf32);
+
+#if defined(_VI_INT64_UINT64_DEFINED)
+ViStatus _VI_FUNC  viMoveIn64      (ViSession vi, ViUInt16 space, ViBusAddress offset,
+                                    ViBusSize length, ViAUInt64 buf64);
+ViStatus _VI_FUNC  viMoveOut64     (ViSession vi, ViUInt16 space, ViBusAddress offset,
+                                    ViBusSize length, ViAUInt64 buf64);
+
+ViStatus _VI_FUNC  viMoveIn8Ex     (ViSession vi, ViUInt16 space, ViBusAddress64 offset,
+                                    ViBusSize length, ViAUInt8  buf8);
+ViStatus _VI_FUNC  viMoveOut8Ex    (ViSession vi, ViUInt16 space, ViBusAddress64 offset,
+                                    ViBusSize length, ViAUInt8  buf8);
+ViStatus _VI_FUNC  viMoveIn16Ex    (ViSession vi, ViUInt16 space, ViBusAddress64 offset,
+                                    ViBusSize length, ViAUInt16 buf16);
+ViStatus _VI_FUNC  viMoveOut16Ex   (ViSession vi, ViUInt16 space, ViBusAddress64 offset,
+                                    ViBusSize length, ViAUInt16 buf16);
+ViStatus _VI_FUNC  viMoveIn32Ex    (ViSession vi, ViUInt16 space, ViBusAddress64 offset,
+                                    ViBusSize length, ViAUInt32 buf32);
+ViStatus _VI_FUNC  viMoveOut32Ex   (ViSession vi, ViUInt16 space, ViBusAddress64 offset,
+                                    ViBusSize length, ViAUInt32 buf32);
+ViStatus _VI_FUNC  viMoveIn64Ex    (ViSession vi, ViUInt16 space, ViBusAddress64 offset,
+                                    ViBusSize length, ViAUInt64 buf64);
+ViStatus _VI_FUNC  viMoveOut64Ex   (ViSession vi, ViUInt16 space, ViBusAddress64 offset,
+                                    ViBusSize length, ViAUInt64 buf64);
+#endif
+
+ViStatus _VI_FUNC  viMove          (ViSession vi, ViUInt16 srcSpace, ViBusAddress srcOffset,
+                                    ViUInt16 srcWidth, ViUInt16 destSpace, 
+                                    ViBusAddress destOffset, ViUInt16 destWidth, 
+                                    ViBusSize srcLength); 
+ViStatus _VI_FUNC  viMoveAsync     (ViSession vi, ViUInt16 srcSpace, ViBusAddress srcOffset,
+                                    ViUInt16 srcWidth, ViUInt16 destSpace, 
+                                    ViBusAddress destOffset, ViUInt16 destWidth, 
+                                    ViBusSize srcLength, ViPJobId jobId);
+
+#if defined(_VI_INT64_UINT64_DEFINED)
+ViStatus _VI_FUNC  viMoveEx        (ViSession vi, ViUInt16 srcSpace, ViBusAddress64 srcOffset,
+                                    ViUInt16 srcWidth, ViUInt16 destSpace, 
+                                    ViBusAddress64 destOffset, ViUInt16 destWidth, 
+                                    ViBusSize srcLength); 
+ViStatus _VI_FUNC  viMoveAsyncEx   (ViSession vi, ViUInt16 srcSpace, ViBusAddress64 srcOffset,
+                                    ViUInt16 srcWidth, ViUInt16 destSpace, 
+                                    ViBusAddress64 destOffset, ViUInt16 destWidth, 
+                                    ViBusSize srcLength, ViPJobId jobId);
+#endif
+
+ViStatus _VI_FUNC  viMapAddress    (ViSession vi, ViUInt16 mapSpace, ViBusAddress mapOffset,
+                                    ViBusSize mapSize, ViBoolean access,
+                                    ViAddr suggested, ViPAddr address);
+ViStatus _VI_FUNC  viUnmapAddress  (ViSession vi);
+
+#if defined(_VI_INT64_UINT64_DEFINED)
+ViStatus _VI_FUNC  viMapAddressEx  (ViSession vi, ViUInt16 mapSpace, ViBusAddress64 mapOffset,
+                                    ViBusSize mapSize, ViBoolean access,
+                                    ViAddr suggested, ViPAddr address);
+#endif
+
+void     _VI_FUNC  viPeek8         (ViSession vi, ViAddr address, ViPUInt8  val8);
+void     _VI_FUNC  viPoke8         (ViSession vi, ViAddr address, ViUInt8   val8);
+void     _VI_FUNC  viPeek16        (ViSession vi, ViAddr address, ViPUInt16 val16);
+void     _VI_FUNC  viPoke16        (ViSession vi, ViAddr address, ViUInt16  val16);
+void     _VI_FUNC  viPeek32        (ViSession vi, ViAddr address, ViPUInt32 val32);
+void     _VI_FUNC  viPoke32        (ViSession vi, ViAddr address, ViUInt32  val32);
+
+#if defined(_VI_INT64_UINT64_DEFINED)
+void     _VI_FUNC  viPeek64        (ViSession vi, ViAddr address, ViPUInt64 val64);
+void     _VI_FUNC  viPoke64        (ViSession vi, ViAddr address, ViUInt64  val64);
+#endif
+
+/*- Shared Memory Operations ------------------------------------------------*/
+
+ViStatus _VI_FUNC  viMemAlloc      (ViSession vi, ViBusSize size, ViPBusAddress offset);
+ViStatus _VI_FUNC  viMemFree       (ViSession vi, ViBusAddress offset);
+
+#if defined(_VI_INT64_UINT64_DEFINED)
+ViStatus _VI_FUNC  viMemAllocEx    (ViSession vi, ViBusSize size, ViPBusAddress64 offset);
+ViStatus _VI_FUNC  viMemFreeEx     (ViSession vi, ViBusAddress64 offset);
+#endif
+
+/*- Interface Specific Operations -------------------------------------------*/
+
+ViStatus _VI_FUNC  viGpibControlREN(ViSession vi, ViUInt16 mode);
+ViStatus _VI_FUNC  viGpibControlATN(ViSession vi, ViUInt16 mode);
+ViStatus _VI_FUNC  viGpibSendIFC   (ViSession vi);
+ViStatus _VI_FUNC  viGpibCommand   (ViSession vi, ViBuf cmd, ViUInt32 cnt, ViPUInt32 retCnt);
+ViStatus _VI_FUNC  viGpibPassControl(ViSession vi, ViUInt16 primAddr, ViUInt16 secAddr);
+
+ViStatus _VI_FUNC  viVxiCommandQuery(ViSession vi, ViUInt16 mode, ViUInt32 cmd,
+                                     ViPUInt32 response);
+ViStatus _VI_FUNC  viAssertUtilSignal(ViSession vi, ViUInt16 line);
+ViStatus _VI_FUNC  viAssertIntrSignal(ViSession vi, ViInt16 mode, ViUInt32 statusID);
+ViStatus _VI_FUNC  viMapTrigger    (ViSession vi, ViInt16 trigSrc, ViInt16 trigDest, 
+                                    ViUInt16 mode);
+ViStatus _VI_FUNC  viUnmapTrigger  (ViSession vi, ViInt16 trigSrc, ViInt16 trigDest);
+ViStatus _VI_FUNC  viUsbControlOut (ViSession vi, ViInt16 bmRequestType, ViInt16 bRequest,
+                                    ViUInt16 wValue, ViUInt16 wIndex, ViUInt16 wLength,
+                                    ViBuf buf);
+ViStatus _VI_FUNC  viUsbControlIn  (ViSession vi, ViInt16 bmRequestType, ViInt16 bRequest,
+                                    ViUInt16 wValue, ViUInt16 wIndex, ViUInt16 wLength,
+                                    ViPBuf buf, ViPUInt16 retCnt);
+
+/*- Attributes (platform independent size) ----------------------------------*/
+
+#define VI_ATTR_RSRC_CLASS          (0xBFFF0001UL)
+#define VI_ATTR_RSRC_NAME           (0xBFFF0002UL)
+#define VI_ATTR_RSRC_IMPL_VERSION   (0x3FFF0003UL)
+#define VI_ATTR_RSRC_LOCK_STATE     (0x3FFF0004UL)
+#define VI_ATTR_MAX_QUEUE_LENGTH    (0x3FFF0005UL)
+#define VI_ATTR_USER_DATA_32        (0x3FFF0007UL)
+#define VI_ATTR_FDC_CHNL            (0x3FFF000DUL)
+#define VI_ATTR_FDC_MODE            (0x3FFF000FUL)
+#define VI_ATTR_FDC_GEN_SIGNAL_EN   (0x3FFF0011UL)
+#define VI_ATTR_FDC_USE_PAIR        (0x3FFF0013UL)
+#define VI_ATTR_SEND_END_EN         (0x3FFF0016UL)
+#define VI_ATTR_TERMCHAR            (0x3FFF0018UL)
+#define VI_ATTR_TMO_VALUE           (0x3FFF001AUL)
+#define VI_ATTR_GPIB_READDR_EN      (0x3FFF001BUL)
+#define VI_ATTR_IO_PROT             (0x3FFF001CUL)
+#define VI_ATTR_DMA_ALLOW_EN        (0x3FFF001EUL)
+#define VI_ATTR_ASRL_BAUD           (0x3FFF0021UL)
+#define VI_ATTR_ASRL_DATA_BITS      (0x3FFF0022UL)
+#define VI_ATTR_ASRL_PARITY         (0x3FFF0023UL)
+#define VI_ATTR_ASRL_STOP_BITS      (0x3FFF0024UL)
+#define VI_ATTR_ASRL_FLOW_CNTRL     (0x3FFF0025UL)
+#define VI_ATTR_RD_BUF_OPER_MODE    (0x3FFF002AUL)
+#define VI_ATTR_RD_BUF_SIZE         (0x3FFF002BUL)
+#define VI_ATTR_WR_BUF_OPER_MODE    (0x3FFF002DUL)
+#define VI_ATTR_WR_BUF_SIZE         (0x3FFF002EUL)
+#define VI_ATTR_SUPPRESS_END_EN     (0x3FFF0036UL)
+#define VI_ATTR_TERMCHAR_EN         (0x3FFF0038UL)
+#define VI_ATTR_DEST_ACCESS_PRIV    (0x3FFF0039UL)
+#define VI_ATTR_DEST_BYTE_ORDER     (0x3FFF003AUL)
+#define VI_ATTR_SRC_ACCESS_PRIV     (0x3FFF003CUL)
+#define VI_ATTR_SRC_BYTE_ORDER      (0x3FFF003DUL)
+#define VI_ATTR_SRC_INCREMENT       (0x3FFF0040UL)
+#define VI_ATTR_DEST_INCREMENT      (0x3FFF0041UL)
+#define VI_ATTR_WIN_ACCESS_PRIV     (0x3FFF0045UL)
+#define VI_ATTR_WIN_BYTE_ORDER      (0x3FFF0047UL)
+#define VI_ATTR_GPIB_ATN_STATE      (0x3FFF0057UL)
+#define VI_ATTR_GPIB_ADDR_STATE     (0x3FFF005CUL)
+#define VI_ATTR_GPIB_CIC_STATE      (0x3FFF005EUL)
+#define VI_ATTR_GPIB_NDAC_STATE     (0x3FFF0062UL)
+#define VI_ATTR_GPIB_SRQ_STATE      (0x3FFF0067UL)
+#define VI_ATTR_GPIB_SYS_CNTRL_STATE (0x3FFF0068UL)
+#define VI_ATTR_GPIB_HS488_CBL_LEN  (0x3FFF0069UL)
+#define VI_ATTR_CMDR_LA             (0x3FFF006BUL)
+#define VI_ATTR_VXI_DEV_CLASS       (0x3FFF006CUL)
+#define VI_ATTR_MAINFRAME_LA        (0x3FFF0070UL)
+#define VI_ATTR_MANF_NAME           (0xBFFF0072UL)
+#define VI_ATTR_MODEL_NAME          (0xBFFF0077UL)
+#define VI_ATTR_VXI_VME_INTR_STATUS (0x3FFF008BUL)
+#define VI_ATTR_VXI_TRIG_STATUS     (0x3FFF008DUL)
+#define VI_ATTR_VXI_VME_SYSFAIL_STATE (0x3FFF0094UL)
+#define VI_ATTR_WIN_BASE_ADDR_32    (0x3FFF0098UL)
+#define VI_ATTR_WIN_SIZE_32         (0x3FFF009AUL)
+#define VI_ATTR_ASRL_AVAIL_NUM      (0x3FFF00ACUL)
+#define VI_ATTR_MEM_BASE_32         (0x3FFF00ADUL)
+#define VI_ATTR_ASRL_CTS_STATE      (0x3FFF00AEUL)
+#define VI_ATTR_ASRL_DCD_STATE      (0x3FFF00AFUL)
+#define VI_ATTR_ASRL_DSR_STATE      (0x3FFF00B1UL)
+#define VI_ATTR_ASRL_DTR_STATE      (0x3FFF00B2UL)
+#define VI_ATTR_ASRL_END_IN         (0x3FFF00B3UL)
+#define VI_ATTR_ASRL_END_OUT        (0x3FFF00B4UL)
+#define VI_ATTR_ASRL_REPLACE_CHAR   (0x3FFF00BEUL)
+#define VI_ATTR_ASRL_RI_STATE       (0x3FFF00BFUL)
+#define VI_ATTR_ASRL_RTS_STATE      (0x3FFF00C0UL)
+#define VI_ATTR_ASRL_XON_CHAR       (0x3FFF00C1UL)
+#define VI_ATTR_ASRL_XOFF_CHAR      (0x3FFF00C2UL)
+#define VI_ATTR_WIN_ACCESS          (0x3FFF00C3UL)
+#define VI_ATTR_RM_SESSION          (0x3FFF00C4UL)
+#define VI_ATTR_VXI_LA              (0x3FFF00D5UL)
+#define VI_ATTR_MANF_ID             (0x3FFF00D9UL)
+#define VI_ATTR_MEM_SIZE_32         (0x3FFF00DDUL)
+#define VI_ATTR_MEM_SPACE           (0x3FFF00DEUL)
+#define VI_ATTR_MODEL_CODE          (0x3FFF00DFUL)
+#define VI_ATTR_SLOT                (0x3FFF00E8UL)
+#define VI_ATTR_INTF_INST_NAME      (0xBFFF00E9UL)
+#define VI_ATTR_IMMEDIATE_SERV      (0x3FFF0100UL)
+#define VI_ATTR_INTF_PARENT_NUM     (0x3FFF0101UL)
+#define VI_ATTR_RSRC_SPEC_VERSION   (0x3FFF0170UL)
+#define VI_ATTR_INTF_TYPE           (0x3FFF0171UL)
+#define VI_ATTR_GPIB_PRIMARY_ADDR   (0x3FFF0172UL)
+#define VI_ATTR_GPIB_SECONDARY_ADDR (0x3FFF0173UL)
+#define VI_ATTR_RSRC_MANF_NAME      (0xBFFF0174UL)
+#define VI_ATTR_RSRC_MANF_ID        (0x3FFF0175UL)
+#define VI_ATTR_INTF_NUM            (0x3FFF0176UL)
+#define VI_ATTR_TRIG_ID             (0x3FFF0177UL)
+#define VI_ATTR_GPIB_REN_STATE      (0x3FFF0181UL)
+#define VI_ATTR_GPIB_UNADDR_EN      (0x3FFF0184UL)
+#define VI_ATTR_DEV_STATUS_BYTE     (0x3FFF0189UL)
+#define VI_ATTR_FILE_APPEND_EN      (0x3FFF0192UL)
+#define VI_ATTR_VXI_TRIG_SUPPORT    (0x3FFF0194UL)
+#define VI_ATTR_TCPIP_ADDR          (0xBFFF0195UL)
+#define VI_ATTR_TCPIP_HOSTNAME      (0xBFFF0196UL)
+#define VI_ATTR_TCPIP_PORT          (0x3FFF0197UL)
+#define VI_ATTR_TCPIP_DEVICE_NAME   (0xBFFF0199UL)
+#define VI_ATTR_TCPIP_NODELAY       (0x3FFF019AUL)
+#define VI_ATTR_TCPIP_KEEPALIVE     (0x3FFF019BUL)
+#define VI_ATTR_4882_COMPLIANT      (0x3FFF019FUL)
+#define VI_ATTR_USB_SERIAL_NUM      (0xBFFF01A0UL)
+#define VI_ATTR_USB_INTFC_NUM       (0x3FFF01A1UL)
+#define VI_ATTR_USB_PROTOCOL        (0x3FFF01A7UL)
+#define VI_ATTR_USB_MAX_INTR_SIZE   (0x3FFF01AFUL)
+#define VI_ATTR_PXI_DEV_NUM         (0x3FFF0201UL)
+#define VI_ATTR_PXI_FUNC_NUM        (0x3FFF0202UL)
+#define VI_ATTR_PXI_BUS_NUM         (0x3FFF0205UL)
+#define VI_ATTR_PXI_CHASSIS         (0x3FFF0206UL)
+#define VI_ATTR_PXI_SLOTPATH        (0xBFFF0207UL)
+#define VI_ATTR_PXI_SLOT_LBUS_LEFT  (0x3FFF0208UL)
+#define VI_ATTR_PXI_SLOT_LBUS_RIGHT (0x3FFF0209UL)
+#define VI_ATTR_PXI_TRIG_BUS        (0x3FFF020AUL)
+#define VI_ATTR_PXI_STAR_TRIG_BUS   (0x3FFF020BUL)
+#define VI_ATTR_PXI_STAR_TRIG_LINE  (0x3FFF020CUL)
+#define VI_ATTR_PXI_MEM_TYPE_BAR0   (0x3FFF0211UL)
+#define VI_ATTR_PXI_MEM_TYPE_BAR1   (0x3FFF0212UL)
+#define VI_ATTR_PXI_MEM_TYPE_BAR2   (0x3FFF0213UL)
+#define VI_ATTR_PXI_MEM_TYPE_BAR3   (0x3FFF0214UL)
+#define VI_ATTR_PXI_MEM_TYPE_BAR4   (0x3FFF0215UL)
+#define VI_ATTR_PXI_MEM_TYPE_BAR5   (0x3FFF0216UL)
+#define VI_ATTR_PXI_MEM_BASE_BAR0   (0x3FFF0221UL)
+#define VI_ATTR_PXI_MEM_BASE_BAR1   (0x3FFF0222UL)
+#define VI_ATTR_PXI_MEM_BASE_BAR2   (0x3FFF0223UL)
+#define VI_ATTR_PXI_MEM_BASE_BAR3   (0x3FFF0224UL)
+#define VI_ATTR_PXI_MEM_BASE_BAR4   (0x3FFF0225UL)
+#define VI_ATTR_PXI_MEM_BASE_BAR5   (0x3FFF0226UL)
+#define VI_ATTR_PXI_MEM_SIZE_BAR0   (0x3FFF0231UL)
+#define VI_ATTR_PXI_MEM_SIZE_BAR1   (0x3FFF0232UL)
+#define VI_ATTR_PXI_MEM_SIZE_BAR2   (0x3FFF0233UL)
+#define VI_ATTR_PXI_MEM_SIZE_BAR3   (0x3FFF0234UL)
+#define VI_ATTR_PXI_MEM_SIZE_BAR4   (0x3FFF0235UL)
+#define VI_ATTR_PXI_MEM_SIZE_BAR5   (0x3FFF0236UL)
+#define VI_ATTR_PXI_IS_EXPRESS      (0x3FFF0240UL)
+#define VI_ATTR_PXI_SLOT_LWIDTH     (0x3FFF0241UL)
+#define VI_ATTR_PXI_MAX_LWIDTH      (0x3FFF0242UL)
+#define VI_ATTR_PXI_ACTUAL_LWIDTH   (0x3FFF0243UL)
+#define VI_ATTR_PXI_DSTAR_BUS       (0x3FFF0244UL)
+#define VI_ATTR_PXI_DSTAR_SET       (0x3FFF0245UL)
+
+#define VI_ATTR_JOB_ID              (0x3FFF4006UL)
+#define VI_ATTR_EVENT_TYPE          (0x3FFF4010UL)
+#define VI_ATTR_SIGP_STATUS_ID      (0x3FFF4011UL)
+#define VI_ATTR_RECV_TRIG_ID        (0x3FFF4012UL)
+#define VI_ATTR_INTR_STATUS_ID      (0x3FFF4023UL)
+#define VI_ATTR_STATUS              (0x3FFF4025UL)
+#define VI_ATTR_RET_COUNT_32        (0x3FFF4026UL)
+#define VI_ATTR_BUFFER              (0x3FFF4027UL)
+#define VI_ATTR_RECV_INTR_LEVEL     (0x3FFF4041UL)
+#define VI_ATTR_OPER_NAME           (0xBFFF4042UL)
+#define VI_ATTR_GPIB_RECV_CIC_STATE (0x3FFF4193UL)
+#define VI_ATTR_RECV_TCPIP_ADDR     (0xBFFF4198UL)
+#define VI_ATTR_USB_RECV_INTR_SIZE  (0x3FFF41B0UL)
+#define VI_ATTR_USB_RECV_INTR_DATA  (0xBFFF41B1UL)
+
+/*- Attributes (platform dependent size) ------------------------------------*/
+
+#if defined(_VI_INT64_UINT64_DEFINED) && defined(_VISA_ENV_IS_64_BIT)
+#define VI_ATTR_USER_DATA_64        (0x3FFF000AUL)
+#define VI_ATTR_RET_COUNT_64        (0x3FFF4028UL)
+#define VI_ATTR_USER_DATA           (VI_ATTR_USER_DATA_64)
+#define VI_ATTR_RET_COUNT           (VI_ATTR_RET_COUNT_64)
+#else
+#define VI_ATTR_USER_DATA           (VI_ATTR_USER_DATA_32)
+#define VI_ATTR_RET_COUNT           (VI_ATTR_RET_COUNT_32)
+#endif
+
+#if defined(_VI_INT64_UINT64_DEFINED)
+#define VI_ATTR_WIN_BASE_ADDR_64    (0x3FFF009BUL)
+#define VI_ATTR_WIN_SIZE_64         (0x3FFF009CUL)
+#define VI_ATTR_MEM_BASE_64         (0x3FFF00D0UL)
+#define VI_ATTR_MEM_SIZE_64         (0x3FFF00D1UL)
+#endif
+#if defined(_VI_INT64_UINT64_DEFINED) && defined(_VISA_ENV_IS_64_BIT)
+#define VI_ATTR_WIN_BASE_ADDR       (VI_ATTR_WIN_BASE_ADDR_64)
+#define VI_ATTR_WIN_SIZE            (VI_ATTR_WIN_SIZE_64)
+#define VI_ATTR_MEM_BASE            (VI_ATTR_MEM_BASE_64)
+#define VI_ATTR_MEM_SIZE            (VI_ATTR_MEM_SIZE_64)
+#else
+#define VI_ATTR_WIN_BASE_ADDR       (VI_ATTR_WIN_BASE_ADDR_32)
+#define VI_ATTR_WIN_SIZE            (VI_ATTR_WIN_SIZE_32)
+#define VI_ATTR_MEM_BASE            (VI_ATTR_MEM_BASE_32)
+#define VI_ATTR_MEM_SIZE            (VI_ATTR_MEM_SIZE_32)
+#endif
+
+/*- Event Types -------------------------------------------------------------*/
+
+#define VI_EVENT_IO_COMPLETION      (0x3FFF2009UL)
+#define VI_EVENT_TRIG               (0xBFFF200AUL)
+#define VI_EVENT_SERVICE_REQ        (0x3FFF200BUL)
+#define VI_EVENT_CLEAR              (0x3FFF200DUL)
+#define VI_EVENT_EXCEPTION          (0xBFFF200EUL)
+#define VI_EVENT_GPIB_CIC           (0x3FFF2012UL)
+#define VI_EVENT_GPIB_TALK          (0x3FFF2013UL)
+#define VI_EVENT_GPIB_LISTEN        (0x3FFF2014UL)
+#define VI_EVENT_VXI_VME_SYSFAIL    (0x3FFF201DUL)
+#define VI_EVENT_VXI_VME_SYSRESET   (0x3FFF201EUL)
+#define VI_EVENT_VXI_SIGP           (0x3FFF2020UL)
+#define VI_EVENT_VXI_VME_INTR       (0xBFFF2021UL)
+#define VI_EVENT_PXI_INTR           (0x3FFF2022UL)
+#define VI_EVENT_TCPIP_CONNECT      (0x3FFF2036UL)
+#define VI_EVENT_USB_INTR           (0x3FFF2037UL)
+
+#define VI_ALL_ENABLED_EVENTS       (0x3FFF7FFFUL)
+
+/*- Completion and Error Codes ----------------------------------------------*/
+
+#define VI_SUCCESS_EVENT_EN                   (0x3FFF0002L) /* 3FFF0002,  1073676290 */
+#define VI_SUCCESS_EVENT_DIS                  (0x3FFF0003L) /* 3FFF0003,  1073676291 */
+#define VI_SUCCESS_QUEUE_EMPTY                (0x3FFF0004L) /* 3FFF0004,  1073676292 */
+#define VI_SUCCESS_TERM_CHAR                  (0x3FFF0005L) /* 3FFF0005,  1073676293 */
+#define VI_SUCCESS_MAX_CNT                    (0x3FFF0006L) /* 3FFF0006,  1073676294 */
+#define VI_SUCCESS_DEV_NPRESENT               (0x3FFF007DL) /* 3FFF007D,  1073676413 */
+#define VI_SUCCESS_TRIG_MAPPED                (0x3FFF007EL) /* 3FFF007E,  1073676414 */
+#define VI_SUCCESS_QUEUE_NEMPTY               (0x3FFF0080L) /* 3FFF0080,  1073676416 */
+#define VI_SUCCESS_NCHAIN                     (0x3FFF0098L) /* 3FFF0098,  1073676440 */
+#define VI_SUCCESS_NESTED_SHARED              (0x3FFF0099L) /* 3FFF0099,  1073676441 */
+#define VI_SUCCESS_NESTED_EXCLUSIVE           (0x3FFF009AL) /* 3FFF009A,  1073676442 */
+#define VI_SUCCESS_SYNC                       (0x3FFF009BL) /* 3FFF009B,  1073676443 */
+
+#define VI_WARN_QUEUE_OVERFLOW                (0x3FFF000CL) /* 3FFF000C,  1073676300 */
+#define VI_WARN_CONFIG_NLOADED                (0x3FFF0077L) /* 3FFF0077,  1073676407 */
+#define VI_WARN_NULL_OBJECT                   (0x3FFF0082L) /* 3FFF0082,  1073676418 */
+#define VI_WARN_NSUP_ATTR_STATE               (0x3FFF0084L) /* 3FFF0084,  1073676420 */
+#define VI_WARN_UNKNOWN_STATUS                (0x3FFF0085L) /* 3FFF0085,  1073676421 */
+#define VI_WARN_NSUP_BUF                      (0x3FFF0088L) /* 3FFF0088,  1073676424 */
+#define VI_WARN_EXT_FUNC_NIMPL                (0x3FFF00A9L) /* 3FFF00A9,  1073676457 */
+
+#define VI_ERROR_SYSTEM_ERROR       (_VI_ERROR+0x3FFF0000L) /* BFFF0000, -1073807360 */
+#define VI_ERROR_INV_OBJECT         (_VI_ERROR+0x3FFF000EL) /* BFFF000E, -1073807346 */
+#define VI_ERROR_RSRC_LOCKED        (_VI_ERROR+0x3FFF000FL) /* BFFF000F, -1073807345 */
+#define VI_ERROR_INV_EXPR           (_VI_ERROR+0x3FFF0010L) /* BFFF0010, -1073807344 */
+#define VI_ERROR_RSRC_NFOUND        (_VI_ERROR+0x3FFF0011L) /* BFFF0011, -1073807343 */
+#define VI_ERROR_INV_RSRC_NAME      (_VI_ERROR+0x3FFF0012L) /* BFFF0012, -1073807342 */
+#define VI_ERROR_INV_ACC_MODE       (_VI_ERROR+0x3FFF0013L) /* BFFF0013, -1073807341 */
+#define VI_ERROR_TMO                (_VI_ERROR+0x3FFF0015L) /* BFFF0015, -1073807339 */
+#define VI_ERROR_CLOSING_FAILED     (_VI_ERROR+0x3FFF0016L) /* BFFF0016, -1073807338 */
+#define VI_ERROR_INV_DEGREE         (_VI_ERROR+0x3FFF001BL) /* BFFF001B, -1073807333 */
+#define VI_ERROR_INV_JOB_ID         (_VI_ERROR+0x3FFF001CL) /* BFFF001C, -1073807332 */
+#define VI_ERROR_NSUP_ATTR          (_VI_ERROR+0x3FFF001DL) /* BFFF001D, -1073807331 */
+#define VI_ERROR_NSUP_ATTR_STATE    (_VI_ERROR+0x3FFF001EL) /* BFFF001E, -1073807330 */
+#define VI_ERROR_ATTR_READONLY      (_VI_ERROR+0x3FFF001FL) /* BFFF001F, -1073807329 */
+#define VI_ERROR_INV_LOCK_TYPE      (_VI_ERROR+0x3FFF0020L) /* BFFF0020, -1073807328 */
+#define VI_ERROR_INV_ACCESS_KEY     (_VI_ERROR+0x3FFF0021L) /* BFFF0021, -1073807327 */
+#define VI_ERROR_INV_EVENT          (_VI_ERROR+0x3FFF0026L) /* BFFF0026, -1073807322 */
+#define VI_ERROR_INV_MECH           (_VI_ERROR+0x3FFF0027L) /* BFFF0027, -1073807321 */
+#define VI_ERROR_HNDLR_NINSTALLED   (_VI_ERROR+0x3FFF0028L) /* BFFF0028, -1073807320 */
+#define VI_ERROR_INV_HNDLR_REF      (_VI_ERROR+0x3FFF0029L) /* BFFF0029, -1073807319 */
+#define VI_ERROR_INV_CONTEXT        (_VI_ERROR+0x3FFF002AL) /* BFFF002A, -1073807318 */
+#define VI_ERROR_QUEUE_OVERFLOW     (_VI_ERROR+0x3FFF002DL) /* BFFF002D, -1073807315 */
+#define VI_ERROR_NENABLED           (_VI_ERROR+0x3FFF002FL) /* BFFF002F, -1073807313 */
+#define VI_ERROR_ABORT              (_VI_ERROR+0x3FFF0030L) /* BFFF0030, -1073807312 */
+#define VI_ERROR_RAW_WR_PROT_VIOL   (_VI_ERROR+0x3FFF0034L) /* BFFF0034, -1073807308 */
+#define VI_ERROR_RAW_RD_PROT_VIOL   (_VI_ERROR+0x3FFF0035L) /* BFFF0035, -1073807307 */
+#define VI_ERROR_OUTP_PROT_VIOL     (_VI_ERROR+0x3FFF0036L) /* BFFF0036, -1073807306 */
+#define VI_ERROR_INP_PROT_VIOL      (_VI_ERROR+0x3FFF0037L) /* BFFF0037, -1073807305 */
+#define VI_ERROR_BERR               (_VI_ERROR+0x3FFF0038L) /* BFFF0038, -1073807304 */
+#define VI_ERROR_IN_PROGRESS        (_VI_ERROR+0x3FFF0039L) /* BFFF0039, -1073807303 */
+#define VI_ERROR_INV_SETUP          (_VI_ERROR+0x3FFF003AL) /* BFFF003A, -1073807302 */
+#define VI_ERROR_QUEUE_ERROR        (_VI_ERROR+0x3FFF003BL) /* BFFF003B, -1073807301 */
+#define VI_ERROR_ALLOC              (_VI_ERROR+0x3FFF003CL) /* BFFF003C, -1073807300 */
+#define VI_ERROR_INV_MASK           (_VI_ERROR+0x3FFF003DL) /* BFFF003D, -1073807299 */
+#define VI_ERROR_IO                 (_VI_ERROR+0x3FFF003EL) /* BFFF003E, -1073807298 */
+#define VI_ERROR_INV_FMT            (_VI_ERROR+0x3FFF003FL) /* BFFF003F, -1073807297 */
+#define VI_ERROR_NSUP_FMT           (_VI_ERROR+0x3FFF0041L) /* BFFF0041, -1073807295 */
+#define VI_ERROR_LINE_IN_USE        (_VI_ERROR+0x3FFF0042L) /* BFFF0042, -1073807294 */
+#define VI_ERROR_NSUP_MODE          (_VI_ERROR+0x3FFF0046L) /* BFFF0046, -1073807290 */
+#define VI_ERROR_SRQ_NOCCURRED      (_VI_ERROR+0x3FFF004AL) /* BFFF004A, -1073807286 */
+#define VI_ERROR_INV_SPACE          (_VI_ERROR+0x3FFF004EL) /* BFFF004E, -1073807282 */
+#define VI_ERROR_INV_OFFSET         (_VI_ERROR+0x3FFF0051L) /* BFFF0051, -1073807279 */
+#define VI_ERROR_INV_WIDTH          (_VI_ERROR+0x3FFF0052L) /* BFFF0052, -1073807278 */
+#define VI_ERROR_NSUP_OFFSET        (_VI_ERROR+0x3FFF0054L) /* BFFF0054, -1073807276 */
+#define VI_ERROR_NSUP_VAR_WIDTH     (_VI_ERROR+0x3FFF0055L) /* BFFF0055, -1073807275 */
+#define VI_ERROR_WINDOW_NMAPPED     (_VI_ERROR+0x3FFF0057L) /* BFFF0057, -1073807273 */
+#define VI_ERROR_RESP_PENDING       (_VI_ERROR+0x3FFF0059L) /* BFFF0059, -1073807271 */
+#define VI_ERROR_NLISTENERS         (_VI_ERROR+0x3FFF005FL) /* BFFF005F, -1073807265 */
+#define VI_ERROR_NCIC               (_VI_ERROR+0x3FFF0060L) /* BFFF0060, -1073807264 */
+#define VI_ERROR_NSYS_CNTLR         (_VI_ERROR+0x3FFF0061L) /* BFFF0061, -1073807263 */
+#define VI_ERROR_NSUP_OPER          (_VI_ERROR+0x3FFF0067L) /* BFFF0067, -1073807257 */
+#define VI_ERROR_INTR_PENDING       (_VI_ERROR+0x3FFF0068L) /* BFFF0068, -1073807256 */
+#define VI_ERROR_ASRL_PARITY        (_VI_ERROR+0x3FFF006AL) /* BFFF006A, -1073807254 */
+#define VI_ERROR_ASRL_FRAMING       (_VI_ERROR+0x3FFF006BL) /* BFFF006B, -1073807253 */
+#define VI_ERROR_ASRL_OVERRUN       (_VI_ERROR+0x3FFF006CL) /* BFFF006C, -1073807252 */
+#define VI_ERROR_TRIG_NMAPPED       (_VI_ERROR+0x3FFF006EL) /* BFFF006E, -1073807250 */
+#define VI_ERROR_NSUP_ALIGN_OFFSET  (_VI_ERROR+0x3FFF0070L) /* BFFF0070, -1073807248 */
+#define VI_ERROR_USER_BUF           (_VI_ERROR+0x3FFF0071L) /* BFFF0071, -1073807247 */
+#define VI_ERROR_RSRC_BUSY          (_VI_ERROR+0x3FFF0072L) /* BFFF0072, -1073807246 */
+#define VI_ERROR_NSUP_WIDTH         (_VI_ERROR+0x3FFF0076L) /* BFFF0076, -1073807242 */
+#define VI_ERROR_INV_PARAMETER      (_VI_ERROR+0x3FFF0078L) /* BFFF0078, -1073807240 */
+#define VI_ERROR_INV_PROT           (_VI_ERROR+0x3FFF0079L) /* BFFF0079, -1073807239 */
+#define VI_ERROR_INV_SIZE           (_VI_ERROR+0x3FFF007BL) /* BFFF007B, -1073807237 */
+#define VI_ERROR_WINDOW_MAPPED      (_VI_ERROR+0x3FFF0080L) /* BFFF0080, -1073807232 */
+#define VI_ERROR_NIMPL_OPER         (_VI_ERROR+0x3FFF0081L) /* BFFF0081, -1073807231 */
+#define VI_ERROR_INV_LENGTH         (_VI_ERROR+0x3FFF0083L) /* BFFF0083, -1073807229 */
+#define VI_ERROR_INV_MODE           (_VI_ERROR+0x3FFF0091L) /* BFFF0091, -1073807215 */
+#define VI_ERROR_SESN_NLOCKED       (_VI_ERROR+0x3FFF009CL) /* BFFF009C, -1073807204 */
+#define VI_ERROR_MEM_NSHARED        (_VI_ERROR+0x3FFF009DL) /* BFFF009D, -1073807203 */
+#define VI_ERROR_LIBRARY_NFOUND     (_VI_ERROR+0x3FFF009EL) /* BFFF009E, -1073807202 */
+#define VI_ERROR_NSUP_INTR          (_VI_ERROR+0x3FFF009FL) /* BFFF009F, -1073807201 */
+#define VI_ERROR_INV_LINE           (_VI_ERROR+0x3FFF00A0L) /* BFFF00A0, -1073807200 */
+#define VI_ERROR_FILE_ACCESS        (_VI_ERROR+0x3FFF00A1L) /* BFFF00A1, -1073807199 */
+#define VI_ERROR_FILE_IO            (_VI_ERROR+0x3FFF00A2L) /* BFFF00A2, -1073807198 */
+#define VI_ERROR_NSUP_LINE          (_VI_ERROR+0x3FFF00A3L) /* BFFF00A3, -1073807197 */
+#define VI_ERROR_NSUP_MECH          (_VI_ERROR+0x3FFF00A4L) /* BFFF00A4, -1073807196 */
+#define VI_ERROR_INTF_NUM_NCONFIG   (_VI_ERROR+0x3FFF00A5L) /* BFFF00A5, -1073807195 */
+#define VI_ERROR_CONN_LOST          (_VI_ERROR+0x3FFF00A6L) /* BFFF00A6, -1073807194 */
+#define VI_ERROR_MACHINE_NAVAIL     (_VI_ERROR+0x3FFF00A7L) /* BFFF00A7, -1073807193 */
+#define VI_ERROR_NPERMISSION        (_VI_ERROR+0x3FFF00A8L) /* BFFF00A8, -1073807192 */
+
+/*- Other VISA Definitions --------------------------------------------------*/
+
+#define VI_VERSION_MAJOR(ver)       ((((ViVersion)ver) & 0xFFF00000UL) >> 20)
+#define VI_VERSION_MINOR(ver)       ((((ViVersion)ver) & 0x000FFF00UL) >>  8)
+#define VI_VERSION_SUBMINOR(ver)    ((((ViVersion)ver) & 0x000000FFUL)      )
+
+#define VI_FIND_BUFLEN              (256)
+
+#define VI_INTF_GPIB                (1)
+#define VI_INTF_VXI                 (2)
+#define VI_INTF_GPIB_VXI            (3)
+#define VI_INTF_ASRL                (4)
+#define VI_INTF_PXI                 (5)
+#define VI_INTF_TCPIP               (6)
+#define VI_INTF_USB                 (7)
+
+#define VI_PROT_NORMAL              (1)
+#define VI_PROT_FDC                 (2)
+#define VI_PROT_HS488               (3)
+#define VI_PROT_4882_STRS           (4)
+#define VI_PROT_USBTMC_VENDOR       (5)
+
+#define VI_FDC_NORMAL               (1)
+#define VI_FDC_STREAM               (2)
+
+#define VI_LOCAL_SPACE              (0)
+#define VI_A16_SPACE                (1)
+#define VI_A24_SPACE                (2)
+#define VI_A32_SPACE                (3)
+#define VI_A64_SPACE                (4)
+#define VI_PXI_ALLOC_SPACE          (9)
+#define VI_PXI_CFG_SPACE            (10)
+#define VI_PXI_BAR0_SPACE           (11)
+#define VI_PXI_BAR1_SPACE           (12)
+#define VI_PXI_BAR2_SPACE           (13)
+#define VI_PXI_BAR3_SPACE           (14)
+#define VI_PXI_BAR4_SPACE           (15)
+#define VI_PXI_BAR5_SPACE           (16)
+#define VI_OPAQUE_SPACE             (0xFFFF)
+
+#define VI_UNKNOWN_LA               (-1)
+#define VI_UNKNOWN_SLOT             (-1)
+#define VI_UNKNOWN_LEVEL            (-1)
+#define VI_UNKNOWN_CHASSIS          (-1)
+
+#define VI_QUEUE                    (1)
+#define VI_HNDLR                    (2)
+#define VI_SUSPEND_HNDLR            (4)
+#define VI_ALL_MECH                 (0xFFFF)
+
+#define VI_ANY_HNDLR                (0)
+
+#define VI_TRIG_ALL                 (-2)
+#define VI_TRIG_SW                  (-1)
+#define VI_TRIG_TTL0                (0)
+#define VI_TRIG_TTL1                (1)
+#define VI_TRIG_TTL2                (2)
+#define VI_TRIG_TTL3                (3)
+#define VI_TRIG_TTL4                (4)
+#define VI_TRIG_TTL5                (5)
+#define VI_TRIG_TTL6                (6)
+#define VI_TRIG_TTL7                (7)
+#define VI_TRIG_ECL0                (8)
+#define VI_TRIG_ECL1                (9)
+#define VI_TRIG_PANEL_IN            (27)
+#define VI_TRIG_PANEL_OUT           (28)
+
+#define VI_TRIG_PROT_DEFAULT        (0)
+#define VI_TRIG_PROT_ON             (1)
+#define VI_TRIG_PROT_OFF            (2)
+#define VI_TRIG_PROT_SYNC           (5)
+#define VI_TRIG_PROT_RESERVE        (6)
+#define VI_TRIG_PROT_UNRESERVE      (7)
+
+#define VI_READ_BUF                 (1)
+#define VI_WRITE_BUF                (2)
+#define VI_READ_BUF_DISCARD         (4)
+#define VI_WRITE_BUF_DISCARD        (8)
+#define VI_IO_IN_BUF                (16)
+#define VI_IO_OUT_BUF               (32)
+#define VI_IO_IN_BUF_DISCARD        (64)
+#define VI_IO_OUT_BUF_DISCARD       (128)
+
+#define VI_FLUSH_ON_ACCESS          (1)
+#define VI_FLUSH_WHEN_FULL          (2)
+#define VI_FLUSH_DISABLE            (3)
+
+#define VI_NMAPPED                  (1)
+#define VI_USE_OPERS                (2)
+#define VI_DEREF_ADDR               (3)
+#define VI_DEREF_ADDR_BYTE_SWAP     (4)
+
+#define VI_TMO_IMMEDIATE            (0L)
+#define VI_TMO_INFINITE             (0xFFFFFFFFUL)
+
+#define VI_NO_LOCK                  (0)
+#define VI_EXCLUSIVE_LOCK           (1)
+#define VI_SHARED_LOCK              (2)
+#define VI_LOAD_CONFIG              (4)
+
+#define VI_NO_SEC_ADDR              (0xFFFF)
+
+#define VI_ASRL_PAR_NONE            (0)
+#define VI_ASRL_PAR_ODD             (1)
+#define VI_ASRL_PAR_EVEN            (2)
+#define VI_ASRL_PAR_MARK            (3)
+#define VI_ASRL_PAR_SPACE           (4)
+
+#define VI_ASRL_STOP_ONE            (10)
+#define VI_ASRL_STOP_ONE5           (15)
+#define VI_ASRL_STOP_TWO            (20)
+
+#define VI_ASRL_FLOW_NONE           (0)
+#define VI_ASRL_FLOW_XON_XOFF       (1)
+#define VI_ASRL_FLOW_RTS_CTS        (2)
+#define VI_ASRL_FLOW_DTR_DSR        (4)
+
+#define VI_ASRL_END_NONE            (0)
+#define VI_ASRL_END_LAST_BIT        (1)
+#define VI_ASRL_END_TERMCHAR        (2)
+#define VI_ASRL_END_BREAK           (3)
+
+#define VI_STATE_ASSERTED           (1)
+#define VI_STATE_UNASSERTED         (0)
+#define VI_STATE_UNKNOWN            (-1)
+
+#define VI_BIG_ENDIAN               (0)
+#define VI_LITTLE_ENDIAN            (1)
+
+#define VI_DATA_PRIV                (0)
+#define VI_DATA_NPRIV               (1)
+#define VI_PROG_PRIV                (2)
+#define VI_PROG_NPRIV               (3)
+#define VI_BLCK_PRIV                (4)
+#define VI_BLCK_NPRIV               (5)
+#define VI_D64_PRIV                 (6)
+#define VI_D64_NPRIV                (7)
+
+#define VI_WIDTH_8                  (1)
+#define VI_WIDTH_16                 (2)
+#define VI_WIDTH_32                 (4)
+#define VI_WIDTH_64                 (8)
+
+#define VI_GPIB_REN_DEASSERT        (0)
+#define VI_GPIB_REN_ASSERT          (1)
+#define VI_GPIB_REN_DEASSERT_GTL    (2)
+#define VI_GPIB_REN_ASSERT_ADDRESS  (3)
+#define VI_GPIB_REN_ASSERT_LLO      (4)
+#define VI_GPIB_REN_ASSERT_ADDRESS_LLO (5)
+#define VI_GPIB_REN_ADDRESS_GTL     (6)
+
+#define VI_GPIB_ATN_DEASSERT        (0)
+#define VI_GPIB_ATN_ASSERT          (1)
+#define VI_GPIB_ATN_DEASSERT_HANDSHAKE (2)
+#define VI_GPIB_ATN_ASSERT_IMMEDIATE (3)
+
+#define VI_GPIB_HS488_DISABLED      (0)
+#define VI_GPIB_HS488_NIMPL         (-1)
+
+#define VI_GPIB_UNADDRESSED         (0)
+#define VI_GPIB_TALKER              (1)
+#define VI_GPIB_LISTENER            (2)
+
+#define VI_VXI_CMD16                (0x0200)
+#define VI_VXI_CMD16_RESP16         (0x0202)
+#define VI_VXI_RESP16               (0x0002)
+#define VI_VXI_CMD32                (0x0400)
+#define VI_VXI_CMD32_RESP16         (0x0402)
+#define VI_VXI_CMD32_RESP32         (0x0404)
+#define VI_VXI_RESP32               (0x0004)
+
+#define VI_ASSERT_SIGNAL            (-1)
+#define VI_ASSERT_USE_ASSIGNED      (0)
+#define VI_ASSERT_IRQ1              (1)
+#define VI_ASSERT_IRQ2              (2)
+#define VI_ASSERT_IRQ3              (3)
+#define VI_ASSERT_IRQ4              (4)
+#define VI_ASSERT_IRQ5              (5)
+#define VI_ASSERT_IRQ6              (6)
+#define VI_ASSERT_IRQ7              (7)
+
+#define VI_UTIL_ASSERT_SYSRESET     (1)
+#define VI_UTIL_ASSERT_SYSFAIL      (2)
+#define VI_UTIL_DEASSERT_SYSFAIL    (3)
+
+#define VI_VXI_CLASS_MEMORY         (0)
+#define VI_VXI_CLASS_EXTENDED       (1)
+#define VI_VXI_CLASS_MESSAGE        (2)
+#define VI_VXI_CLASS_REGISTER       (3)
+#define VI_VXI_CLASS_OTHER          (4)
+
+#define VI_PXI_ADDR_NONE            (0)
+#define VI_PXI_ADDR_MEM             (1)
+#define VI_PXI_ADDR_IO              (2)
+#define VI_PXI_ADDR_CFG             (3)
+
+#define VI_TRIG_UNKNOWN             (-1)
+
+#define VI_PXI_LBUS_UNKNOWN         (-1)
+#define VI_PXI_LBUS_NONE            (0)
+#define VI_PXI_LBUS_STAR_TRIG_BUS_0 (1000)
+#define VI_PXI_LBUS_STAR_TRIG_BUS_1 (1001)
+#define VI_PXI_LBUS_STAR_TRIG_BUS_2 (1002)
+#define VI_PXI_LBUS_STAR_TRIG_BUS_3 (1003)
+#define VI_PXI_LBUS_STAR_TRIG_BUS_4 (1004)
+#define VI_PXI_LBUS_STAR_TRIG_BUS_5 (1005)
+#define VI_PXI_LBUS_STAR_TRIG_BUS_6 (1006)
+#define VI_PXI_LBUS_STAR_TRIG_BUS_7 (1007)
+#define VI_PXI_LBUS_STAR_TRIG_BUS_8 (1008)
+#define VI_PXI_LBUS_STAR_TRIG_BUS_9 (1009)
+#define VI_PXI_STAR_TRIG_CONTROLLER (1413)
+
+/*- Backward Compatibility Macros -------------------------------------------*/
+
+#define viGetDefaultRM(vi)          viOpenDefaultRM(vi)
+#define VI_ERROR_INV_SESSION        (VI_ERROR_INV_OBJECT)
+#define VI_INFINITE                 (VI_TMO_INFINITE)
+#define VI_NORMAL                   (VI_PROT_NORMAL)
+#define VI_FDC                      (VI_PROT_FDC)
+#define VI_HS488                    (VI_PROT_HS488)
+#define VI_ASRL488                  (VI_PROT_4882_STRS)
+#define VI_ASRL_IN_BUF              (VI_IO_IN_BUF)
+#define VI_ASRL_OUT_BUF             (VI_IO_OUT_BUF)
+#define VI_ASRL_IN_BUF_DISCARD      (VI_IO_IN_BUF_DISCARD)
+#define VI_ASRL_OUT_BUF_DISCARD     (VI_IO_OUT_BUF_DISCARD)
+
+/*- National Instruments ----------------------------------------------------*/
+
+#define VI_INTF_RIO                 (8)
+#define VI_INTF_FIREWIRE            (9) 
+
+#define VI_ATTR_SYNC_MXI_ALLOW_EN   (0x3FFF0161UL) /* ViBoolean, read/write */
+
+/* This is for VXI SERVANT resources */
+
+#define VI_EVENT_VXI_DEV_CMD        (0xBFFF200FUL)
+#define VI_ATTR_VXI_DEV_CMD_TYPE    (0x3FFF4037UL) /* ViInt16, read-only */
+#define VI_ATTR_VXI_DEV_CMD_VALUE   (0x3FFF4038UL) /* ViUInt32, read-only */
+
+#define VI_VXI_DEV_CMD_TYPE_16      (16)
+#define VI_VXI_DEV_CMD_TYPE_32      (32)
+
+ViStatus _VI_FUNC viVxiServantResponse(ViSession vi, ViInt16 mode, ViUInt32 resp);
+/* mode values include VI_VXI_RESP16, VI_VXI_RESP32, and the next 2 values */
+#define VI_VXI_RESP_NONE            (0)
+#define VI_VXI_RESP_PROT_ERROR      (-1)
+
+/* This allows extended Serial support on Win32 and on NI ENET Serial products */
+
+#define VI_ATTR_ASRL_DISCARD_NULL   (0x3FFF00B0UL)
+#define VI_ATTR_ASRL_CONNECTED      (0x3FFF01BBUL)
+#define VI_ATTR_ASRL_BREAK_STATE    (0x3FFF01BCUL)
+#define VI_ATTR_ASRL_BREAK_LEN      (0x3FFF01BDUL)
+#define VI_ATTR_ASRL_ALLOW_TRANSMIT (0x3FFF01BEUL)
+#define VI_ATTR_ASRL_WIRE_MODE      (0x3FFF01BFUL)
+
+#define VI_ASRL_WIRE_485_4          (0)
+#define VI_ASRL_WIRE_485_2_DTR_ECHO (1)
+#define VI_ASRL_WIRE_485_2_DTR_CTRL (2)
+#define VI_ASRL_WIRE_485_2_AUTO     (3)
+#define VI_ASRL_WIRE_232_DTE        (128)
+#define VI_ASRL_WIRE_232_DCE        (129)
+#define VI_ASRL_WIRE_232_AUTO       (130)
+
+#define VI_EVENT_ASRL_BREAK         (0x3FFF2023UL)
+#define VI_EVENT_ASRL_CTS           (0x3FFF2029UL)
+#define VI_EVENT_ASRL_DSR           (0x3FFF202AUL)
+#define VI_EVENT_ASRL_DCD           (0x3FFF202CUL)
+#define VI_EVENT_ASRL_RI            (0x3FFF202EUL)
+#define VI_EVENT_ASRL_CHAR          (0x3FFF2035UL)
+#define VI_EVENT_ASRL_TERMCHAR      (0x3FFF2024UL)
+
+/* This is for fast viPeek/viPoke macros */
+
+#if defined(NIVISA_PEEKPOKE)
+
+#if defined(NIVISA_PEEKPOKE_SUPP)
+#undef NIVISA_PEEKPOKE_SUPP
+#endif
+
+#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)) && !defined(_NI_mswin16_)
+/* This macro is supported for all Win32 compilers, including CVI. */
+#define NIVISA_PEEKPOKE_SUPP
+#elif (defined(_WINDOWS) || defined(_Windows)) && !defined(_CVI_) && !defined(_NI_mswin16_)
+/* This macro is supported for Borland and Microsoft compilers on Win16, but not CVI. */
+#define NIVISA_PEEKPOKE_SUPP
+#elif defined(_CVI_) && defined(_NI_sparc_)
+/* This macro is supported for Solaris 1 and 2, from CVI only. */
+#define NIVISA_PEEKPOKE_SUPP
+#else
+/* This macro is not supported on other platforms. */
+#endif
+
+#if defined(NIVISA_PEEKPOKE_SUPP)
+
+extern ViBoolean NI_viImplVISA1;
+ViStatus _VI_FUNC NI_viOpenDefaultRM (ViPSession vi);
+#define viOpenDefaultRM(vi) NI_viOpenDefaultRM(vi)
+
+#define viPeek8(vi,addr,val)                                                \
+   {                                                                        \
+      if ((NI_viImplVISA1) && (*((ViPUInt32)(vi))))                         \
+      {                                                                     \
+         do (*((ViPUInt8)(val)) = *((volatile ViUInt8 _VI_PTR)(addr)));     \
+         while (**((volatile ViUInt8 _VI_PTR _VI_PTR)(vi)) & 0x10);         \
+      }                                                                     \
+      else                                                                  \
+      {                                                                     \
+         (viPeek8)((vi),(addr),(val));                                      \
+      }                                                                     \
+   }
+
+#define viPoke8(vi,addr,val)                                                \
+   {                                                                        \
+      if ((NI_viImplVISA1) && (*((ViPUInt32)(vi))))                         \
+      {                                                                     \
+         do (*((volatile ViUInt8 _VI_PTR)(addr)) = ((ViUInt8)(val)));       \
+         while (**((volatile ViUInt8 _VI_PTR _VI_PTR)(vi)) & 0x10);         \
+      }                                                                     \
+      else                                                                  \
+      {                                                                     \
+         (viPoke8)((vi),(addr),(val));                                      \
+      }                                                                     \
+   }
+
+#define viPeek16(vi,addr,val)                                               \
+   {                                                                        \
+      if ((NI_viImplVISA1) && (*((ViPUInt32)(vi))))                         \
+      {                                                                     \
+         do (*((ViPUInt16)(val)) = *((volatile ViUInt16 _VI_PTR)(addr)));   \
+         while (**((volatile ViUInt8 _VI_PTR _VI_PTR)(vi)) & 0x10);         \
+      }                                                                     \
+      else                                                                  \
+      {                                                                     \
+         (viPeek16)((vi),(addr),(val));                                     \
+      }                                                                     \
+   }
+
+#define viPoke16(vi,addr,val)                                               \
+   {                                                                        \
+      if ((NI_viImplVISA1) && (*((ViPUInt32)(vi))))                         \
+      {                                                                     \
+         do (*((volatile ViUInt16 _VI_PTR)(addr)) = ((ViUInt16)(val)));     \
+         while (**((volatile ViUInt8 _VI_PTR _VI_PTR)(vi)) & 0x10);         \
+      }                                                                     \
+      else                                                                  \
+      {                                                                     \
+         (viPoke16)((vi),(addr),(val));                                     \
+      }                                                                     \
+   }
+
+#define viPeek32(vi,addr,val)                                               \
+   {                                                                        \
+      if ((NI_viImplVISA1) && (*((ViPUInt32)(vi))))                         \
+      {                                                                     \
+         do (*((ViPUInt32)(val)) = *((volatile ViUInt32 _VI_PTR)(addr)));   \
+         while (**((volatile ViUInt8 _VI_PTR _VI_PTR)(vi)) & 0x10);         \
+      }                                                                     \
+      else                                                                  \
+      {                                                                     \
+         (viPeek32)((vi),(addr),(val));                                     \
+      }                                                                     \
+   }
+
+#define viPoke32(vi,addr,val)                                               \
+   {                                                                        \
+      if ((NI_viImplVISA1) && (*((ViPUInt32)(vi))))                         \
+      {                                                                     \
+         do (*((volatile ViUInt32 _VI_PTR)(addr)) = ((ViUInt32)(val)));     \
+         while (**((volatile ViUInt8 _VI_PTR _VI_PTR)(vi)) & 0x10);         \
+      }                                                                     \
+      else                                                                  \
+      {                                                                     \
+         (viPoke32)((vi),(addr),(val));                                     \
+      }                                                                     \
+   }
+
+#endif
+
+#endif
+
+#if defined(NIVISA_PXI) || defined(PXISAVISA_PXI)
+
+#if 0
+/* The following 2 attributes were incorrectly implemented in earlier
+   versions of NI-VISA.  You should now query VI_ATTR_MANF_ID or
+   VI_ATTR_MODEL_CODE.  Those attributes contain sub-vendor information
+   when it exists.  To get both the actual primary and subvendor codes
+   from the device, you should call viIn16 using VI_PXI_CFG_SPACE. */
+#define VI_ATTR_PXI_SUB_MANF_ID     (0x3FFF0203UL)
+#define VI_ATTR_PXI_SUB_MODEL_CODE  (0x3FFF0204UL)
+#endif
+
+#define VI_ATTR_PXI_SRC_TRIG_BUS    (0x3FFF020DUL)
+#define VI_ATTR_PXI_DEST_TRIG_BUS   (0x3FFF020EUL)
+
+#define VI_ATTR_PXI_RECV_INTR_SEQ   (0x3FFF4240UL)
+#define VI_ATTR_PXI_RECV_INTR_DATA  (0x3FFF4241UL)
+
+#endif
+
+#if defined(NIVISA_USB)
+
+#define VI_ATTR_USB_BULK_OUT_PIPE   (0x3FFF01A2UL)
+#define VI_ATTR_USB_BULK_IN_PIPE    (0x3FFF01A3UL)
+#define VI_ATTR_USB_INTR_IN_PIPE    (0x3FFF01A4UL)
+#define VI_ATTR_USB_CLASS           (0x3FFF01A5UL)
+#define VI_ATTR_USB_SUBCLASS        (0x3FFF01A6UL)
+#define VI_ATTR_USB_ALT_SETTING     (0x3FFF01A8UL)
+#define VI_ATTR_USB_END_IN          (0x3FFF01A9UL)
+#define VI_ATTR_USB_NUM_INTFCS      (0x3FFF01AAUL)
+#define VI_ATTR_USB_NUM_PIPES       (0x3FFF01ABUL)
+#define VI_ATTR_USB_BULK_OUT_STATUS (0x3FFF01ACUL)
+#define VI_ATTR_USB_BULK_IN_STATUS  (0x3FFF01ADUL)
+#define VI_ATTR_USB_INTR_IN_STATUS  (0x3FFF01AEUL)
+#define VI_ATTR_USB_CTRL_PIPE       (0x3FFF01B0UL)
+
+#define VI_USB_PIPE_STATE_UNKNOWN   (-1)
+#define VI_USB_PIPE_READY           (0)
+#define VI_USB_PIPE_STALLED         (1)
+
+#define VI_USB_END_NONE             (0)
+#define VI_USB_END_SHORT            (4)
+#define VI_USB_END_SHORT_OR_COUNT   (5)
+
+#endif
+
+#define VI_ATTR_FIREWIRE_DEST_UPPER_OFFSET (0x3FFF01F0UL)
+#define VI_ATTR_FIREWIRE_SRC_UPPER_OFFSET  (0x3FFF01F1UL)
+#define VI_ATTR_FIREWIRE_WIN_UPPER_OFFSET  (0x3FFF01F2UL)
+#define VI_ATTR_FIREWIRE_VENDOR_ID         (0x3FFF01F3UL)
+#define VI_ATTR_FIREWIRE_LOWER_CHIP_ID     (0x3FFF01F4UL)
+#define VI_ATTR_FIREWIRE_UPPER_CHIP_ID     (0x3FFF01F5UL)
+
+#define VI_FIREWIRE_DFLT_SPACE           (5)
+
+#if defined(__cplusplus) || defined(__cplusplus__)
+   }
+#endif
+
+#endif
+
+/*- The End -----------------------------------------------------------------*/
diff --git a/aos/externals/allwpilib/hal/lib/Athena/visa/visatype.h b/aos/externals/allwpilib/hal/lib/Athena/visa/visatype.h
new file mode 100644
index 0000000..ef089dd
--- /dev/null
+++ b/aos/externals/allwpilib/hal/lib/Athena/visa/visatype.h
@@ -0,0 +1,201 @@
+/*---------------------------------------------------------------------------*/
+/* Distributed by IVI Foundation Inc.                                        */
+/*                                                                           */
+/* Do not modify the contents of this file.                                  */
+/*---------------------------------------------------------------------------*/
+/*                                                                           */
+/* Title   : VISATYPE.H                                                      */
+/* Date    : 04-14-2006                                                      */
+/* Purpose : Fundamental VISA data types and macro definitions               */
+/*                                                                           */
+/*---------------------------------------------------------------------------*/
+
+#ifndef __VISATYPE_HEADER__
+#define __VISATYPE_HEADER__
+
+#if defined(_WIN64)
+#define _VI_FAR
+#define _VI_FUNC            __fastcall
+#define _VI_FUNCC           __fastcall
+#define _VI_FUNCH           __fastcall
+#define _VI_SIGNED          signed
+#elif (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)) && !defined(_NI_mswin16_)
+#define _VI_FAR
+#define _VI_FUNC            __stdcall
+#define _VI_FUNCC           __cdecl
+#define _VI_FUNCH           __stdcall
+#define _VI_SIGNED          signed
+#elif defined(_CVI_) && defined(_NI_i386_)
+#define _VI_FAR
+#define _VI_FUNC            _pascal
+#define _VI_FUNCC
+#define _VI_FUNCH           _pascal
+#define _VI_SIGNED          signed
+#elif (defined(_WINDOWS) || defined(_Windows)) && !defined(_NI_mswin16_)
+#define _VI_FAR             _far
+#define _VI_FUNC            _far _pascal _export
+#define _VI_FUNCC           _far _cdecl  _export
+#define _VI_FUNCH           _far _pascal
+#define _VI_SIGNED          signed
+#elif (defined(hpux) || defined(__hpux)) && (defined(__cplusplus) || defined(__cplusplus__))
+#define _VI_FAR
+#define _VI_FUNC
+#define _VI_FUNCC
+#define _VI_FUNCH
+#define _VI_SIGNED
+#else
+#define _VI_FAR
+#define _VI_FUNC
+#define _VI_FUNCC
+#define _VI_FUNCH
+#define _VI_SIGNED          signed
+#endif
+
+#define _VI_ERROR           (-2147483647L-1)  /* 0x80000000 */
+#define _VI_PTR             _VI_FAR *
+
+/*- VISA Types --------------------------------------------------------------*/
+
+#ifndef _VI_INT64_UINT64_DEFINED
+#if defined(_WIN64) || ((defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)) && !defined(_NI_mswin16_))
+#if (defined(_MSC_VER) && (_MSC_VER >= 1200)) || (defined(_CVI_) && (_CVI_ >= 700)) || (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0520))
+typedef unsigned   __int64  ViUInt64;
+typedef _VI_SIGNED __int64  ViInt64;
+#define _VI_INT64_UINT64_DEFINED
+#if defined(_WIN64)
+#define _VISA_ENV_IS_64_BIT
+#else
+/* This is a 32-bit OS, not a 64-bit OS */
+#endif
+#endif
+#elif defined(__GNUC__) && (__GNUC__ >= 3)
+#include <limits.h>
+#include <sys/types.h>
+typedef u_int64_t           ViUInt64;
+typedef int64_t             ViInt64;
+#define _VI_INT64_UINT64_DEFINED
+#if defined(LONG_MAX) && (LONG_MAX > 0x7FFFFFFFL)
+#define _VISA_ENV_IS_64_BIT
+#else
+/* This is a 32-bit OS, not a 64-bit OS */
+#endif
+#else
+/* This platform does not support 64-bit types */
+#endif
+#endif
+
+#if defined(_VI_INT64_UINT64_DEFINED)
+typedef ViUInt64    _VI_PTR ViPUInt64;
+typedef ViUInt64    _VI_PTR ViAUInt64;
+typedef ViInt64     _VI_PTR ViPInt64;
+typedef ViInt64     _VI_PTR ViAInt64;
+#endif
+
+#if defined(LONG_MAX) && (LONG_MAX > 0x7FFFFFFFL)
+typedef unsigned int        ViUInt32;
+typedef _VI_SIGNED int      ViInt32;
+#else
+typedef unsigned long       ViUInt32;
+typedef _VI_SIGNED long     ViInt32;
+#endif
+
+typedef ViUInt32    _VI_PTR ViPUInt32;
+typedef ViUInt32    _VI_PTR ViAUInt32;
+typedef ViInt32     _VI_PTR ViPInt32;
+typedef ViInt32     _VI_PTR ViAInt32;
+
+typedef unsigned short      ViUInt16;
+typedef ViUInt16    _VI_PTR ViPUInt16;
+typedef ViUInt16    _VI_PTR ViAUInt16;
+
+typedef _VI_SIGNED short    ViInt16;
+typedef ViInt16     _VI_PTR ViPInt16;
+typedef ViInt16     _VI_PTR ViAInt16;
+
+typedef unsigned char       ViUInt8;
+typedef ViUInt8     _VI_PTR ViPUInt8;
+typedef ViUInt8     _VI_PTR ViAUInt8;
+
+typedef _VI_SIGNED char     ViInt8;
+typedef ViInt8      _VI_PTR ViPInt8;
+typedef ViInt8      _VI_PTR ViAInt8;
+
+typedef char                ViChar;
+typedef ViChar      _VI_PTR ViPChar;
+typedef ViChar      _VI_PTR ViAChar;
+
+typedef unsigned char       ViByte;
+typedef ViByte      _VI_PTR ViPByte;
+typedef ViByte      _VI_PTR ViAByte;
+
+typedef void        _VI_PTR ViAddr;
+typedef ViAddr      _VI_PTR ViPAddr;
+typedef ViAddr      _VI_PTR ViAAddr;
+
+typedef float               ViReal32;
+typedef ViReal32    _VI_PTR ViPReal32;
+typedef ViReal32    _VI_PTR ViAReal32;
+
+typedef double              ViReal64;
+typedef ViReal64    _VI_PTR ViPReal64;
+typedef ViReal64    _VI_PTR ViAReal64;
+
+typedef ViPByte             ViBuf;
+typedef ViPByte             ViPBuf;
+typedef ViPByte     _VI_PTR ViABuf;
+
+typedef ViPChar             ViString;
+typedef ViPChar             ViPString;
+typedef ViPChar     _VI_PTR ViAString;
+
+typedef ViString            ViRsrc;
+typedef ViString            ViPRsrc;
+typedef ViString    _VI_PTR ViARsrc;
+
+typedef ViUInt16            ViBoolean;
+typedef ViBoolean   _VI_PTR ViPBoolean;
+typedef ViBoolean   _VI_PTR ViABoolean;
+
+typedef ViInt32             ViStatus;
+typedef ViStatus    _VI_PTR ViPStatus;
+typedef ViStatus    _VI_PTR ViAStatus;
+
+typedef ViUInt32            ViVersion;
+typedef ViVersion   _VI_PTR ViPVersion;
+typedef ViVersion   _VI_PTR ViAVersion;
+
+typedef ViUInt32            ViObject;
+typedef ViObject    _VI_PTR ViPObject;
+typedef ViObject    _VI_PTR ViAObject;
+
+typedef ViObject            ViSession;
+typedef ViSession   _VI_PTR ViPSession;
+typedef ViSession   _VI_PTR ViASession;
+
+typedef ViUInt32             ViAttr;
+
+#ifndef _VI_CONST_STRING_DEFINED
+typedef const ViChar * ViConstString;
+#define _VI_CONST_STRING_DEFINED
+#endif  
+
+/*- Completion and Error Codes ----------------------------------------------*/
+
+#define VI_SUCCESS          (0L)
+
+/*- Other VISA Definitions --------------------------------------------------*/
+
+#define VI_NULL             (0)
+
+#define VI_TRUE             (1)
+#define VI_FALSE            (0)
+
+/*- Backward Compatibility Macros -------------------------------------------*/
+
+#define VISAFN              _VI_FUNC
+#define ViPtr               _VI_PTR
+
+#endif
+
+/*- The End -----------------------------------------------------------------*/
+
diff --git a/aos/externals/allwpilib/ni-libraries/genlinks b/aos/externals/allwpilib/ni-libraries/genlinks
new file mode 100755
index 0000000..6931dbc
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/genlinks
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+# this file should generate symlinks (POSIX, TODO) or LD scripts (POSIX or windows) to enable standard version linking
+
+for lib in lib*.so.*; do
+	libout="${lib%.*}"
+	rm -rf $libout
+	echo "OUTPUT_FORMAT(elf32-littlearm)" > $libout
+	echo "GROUP ( $lib )" >> $libout
+	echo "Generated LD link $libout -> $lib"
+done
diff --git a/aos/externals/allwpilib/ni-libraries/libFRC_NetworkCommunication.so b/aos/externals/allwpilib/ni-libraries/libFRC_NetworkCommunication.so
new file mode 100644
index 0000000..a24218e
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libFRC_NetworkCommunication.so
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libFRC_NetworkCommunication.so.1 )
diff --git a/aos/externals/allwpilib/ni-libraries/libFRC_NetworkCommunication.so.1 b/aos/externals/allwpilib/ni-libraries/libFRC_NetworkCommunication.so.1
new file mode 100644
index 0000000..e1ec38a
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libFRC_NetworkCommunication.so.1
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libFRC_NetworkCommunication.so.1.5 )
diff --git a/aos/externals/allwpilib/ni-libraries/libFRC_NetworkCommunication.so.1.5 b/aos/externals/allwpilib/ni-libraries/libFRC_NetworkCommunication.so.1.5
new file mode 100644
index 0000000..845c759
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libFRC_NetworkCommunication.so.1.5
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libFRC_NetworkCommunication.so.1.5.0 )
diff --git a/aos/externals/allwpilib/ni-libraries/libFRC_NetworkCommunication.so.1.5.0 b/aos/externals/allwpilib/ni-libraries/libFRC_NetworkCommunication.so.1.5.0
new file mode 100755
index 0000000..503911b
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libFRC_NetworkCommunication.so.1.5.0
Binary files differ
diff --git a/aos/externals/allwpilib/ni-libraries/libFRC_NetworkCommunicationLV.so b/aos/externals/allwpilib/ni-libraries/libFRC_NetworkCommunicationLV.so
new file mode 100644
index 0000000..c7c2653
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libFRC_NetworkCommunicationLV.so
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libFRC_NetworkCommunicationLV.so.1 )
diff --git a/aos/externals/allwpilib/ni-libraries/libFRC_NetworkCommunicationLV.so.1 b/aos/externals/allwpilib/ni-libraries/libFRC_NetworkCommunicationLV.so.1
new file mode 100644
index 0000000..1254b6d
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libFRC_NetworkCommunicationLV.so.1
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libFRC_NetworkCommunicationLV.so.1.5 )
diff --git a/aos/externals/allwpilib/ni-libraries/libFRC_NetworkCommunicationLV.so.1.5 b/aos/externals/allwpilib/ni-libraries/libFRC_NetworkCommunicationLV.so.1.5
new file mode 100644
index 0000000..30022db
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libFRC_NetworkCommunicationLV.so.1.5
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libFRC_NetworkCommunicationLV.so.1.5.0 )
diff --git a/aos/externals/allwpilib/ni-libraries/libFRC_NetworkCommunicationLV.so.1.5.0 b/aos/externals/allwpilib/ni-libraries/libFRC_NetworkCommunicationLV.so.1.5.0
new file mode 100755
index 0000000..f54d997
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libFRC_NetworkCommunicationLV.so.1.5.0
Binary files differ
diff --git a/aos/externals/allwpilib/ni-libraries/libGCBase_gcc-4.4-arm_v2_3.so b/aos/externals/allwpilib/ni-libraries/libGCBase_gcc-4.4-arm_v2_3.so
new file mode 100755
index 0000000..3bcda8d
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libGCBase_gcc-4.4-arm_v2_3.so
Binary files differ
diff --git a/aos/externals/allwpilib/ni-libraries/libGenApi_gcc-4.4-arm_v2_3.so b/aos/externals/allwpilib/ni-libraries/libGenApi_gcc-4.4-arm_v2_3.so
new file mode 100755
index 0000000..7e6a6df
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libGenApi_gcc-4.4-arm_v2_3.so
Binary files differ
diff --git a/aos/externals/allwpilib/ni-libraries/libLog_gcc-4.4-arm_v2_3.so b/aos/externals/allwpilib/ni-libraries/libLog_gcc-4.4-arm_v2_3.so
new file mode 100755
index 0000000..6e8719b
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libLog_gcc-4.4-arm_v2_3.so
Binary files differ
diff --git a/aos/externals/allwpilib/ni-libraries/libMathParser_gcc-4.4-arm_v2_3.so b/aos/externals/allwpilib/ni-libraries/libMathParser_gcc-4.4-arm_v2_3.so
new file mode 100755
index 0000000..e4d1279
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libMathParser_gcc-4.4-arm_v2_3.so
Binary files differ
diff --git a/aos/externals/allwpilib/ni-libraries/libNiFpga.so b/aos/externals/allwpilib/ni-libraries/libNiFpga.so
new file mode 100644
index 0000000..c506470
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libNiFpga.so
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libNiFpga.so.14 )
diff --git a/aos/externals/allwpilib/ni-libraries/libNiFpga.so.14 b/aos/externals/allwpilib/ni-libraries/libNiFpga.so.14
new file mode 100644
index 0000000..3b66e3e
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libNiFpga.so.14
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libNiFpga.so.14.0 )
diff --git a/aos/externals/allwpilib/ni-libraries/libNiFpga.so.14.0 b/aos/externals/allwpilib/ni-libraries/libNiFpga.so.14.0
new file mode 100644
index 0000000..aa4e287
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libNiFpga.so.14.0
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libNiFpga.so.14.0.0 )
diff --git a/aos/externals/allwpilib/ni-libraries/libNiFpga.so.14.0.0 b/aos/externals/allwpilib/ni-libraries/libNiFpga.so.14.0.0
new file mode 100755
index 0000000..1f3a237
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libNiFpga.so.14.0.0
Binary files differ
diff --git a/aos/externals/allwpilib/ni-libraries/libNiFpgaLv.so b/aos/externals/allwpilib/ni-libraries/libNiFpgaLv.so
new file mode 100644
index 0000000..88b5a24
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libNiFpgaLv.so
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libNiFpgaLv.so.14 )
diff --git a/aos/externals/allwpilib/ni-libraries/libNiFpgaLv.so.14 b/aos/externals/allwpilib/ni-libraries/libNiFpgaLv.so.14
new file mode 100644
index 0000000..3adae09
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libNiFpgaLv.so.14
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libNiFpgaLv.so.14.0 )
diff --git a/aos/externals/allwpilib/ni-libraries/libNiFpgaLv.so.14.0 b/aos/externals/allwpilib/ni-libraries/libNiFpgaLv.so.14.0
new file mode 100644
index 0000000..db0b28c
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libNiFpgaLv.so.14.0
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libNiFpgaLv.so.14.0.0 )
diff --git a/aos/externals/allwpilib/ni-libraries/libNiFpgaLv.so.14.0.0 b/aos/externals/allwpilib/ni-libraries/libNiFpgaLv.so.14.0.0
new file mode 100755
index 0000000..3efee8f
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libNiFpgaLv.so.14.0.0
Binary files differ
diff --git a/aos/externals/allwpilib/ni-libraries/libNiRioSrv.so b/aos/externals/allwpilib/ni-libraries/libNiRioSrv.so
new file mode 100644
index 0000000..98b55b1
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libNiRioSrv.so
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libNiRioSrv.so.14 )
diff --git a/aos/externals/allwpilib/ni-libraries/libNiRioSrv.so.14 b/aos/externals/allwpilib/ni-libraries/libNiRioSrv.so.14
new file mode 100644
index 0000000..ef98d56
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libNiRioSrv.so.14
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libNiRioSrv.so.14.0 )
diff --git a/aos/externals/allwpilib/ni-libraries/libNiRioSrv.so.14.0 b/aos/externals/allwpilib/ni-libraries/libNiRioSrv.so.14.0
new file mode 100644
index 0000000..7ee207d
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libNiRioSrv.so.14.0
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libNiRioSrv.so.14.0.0 )
diff --git a/aos/externals/allwpilib/ni-libraries/libNiRioSrv.so.14.0.0 b/aos/externals/allwpilib/ni-libraries/libNiRioSrv.so.14.0.0
new file mode 100755
index 0000000..4917af8
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libNiRioSrv.so.14.0.0
Binary files differ
diff --git a/aos/externals/allwpilib/ni-libraries/libRoboRIO_FRC_ChipObject.so b/aos/externals/allwpilib/ni-libraries/libRoboRIO_FRC_ChipObject.so
new file mode 100644
index 0000000..b44dc03
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libRoboRIO_FRC_ChipObject.so
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libRoboRIO_FRC_ChipObject.so.1 )
diff --git a/aos/externals/allwpilib/ni-libraries/libRoboRIO_FRC_ChipObject.so.1 b/aos/externals/allwpilib/ni-libraries/libRoboRIO_FRC_ChipObject.so.1
new file mode 100644
index 0000000..fff4f97
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libRoboRIO_FRC_ChipObject.so.1
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libRoboRIO_FRC_ChipObject.so.1.2 )
diff --git a/aos/externals/allwpilib/ni-libraries/libRoboRIO_FRC_ChipObject.so.1.2 b/aos/externals/allwpilib/ni-libraries/libRoboRIO_FRC_ChipObject.so.1.2
new file mode 100644
index 0000000..467fa0e
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libRoboRIO_FRC_ChipObject.so.1.2
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libRoboRIO_FRC_ChipObject.so.1.2.0 )
diff --git a/aos/externals/allwpilib/ni-libraries/libRoboRIO_FRC_ChipObject.so.1.2.0 b/aos/externals/allwpilib/ni-libraries/libRoboRIO_FRC_ChipObject.so.1.2.0
new file mode 100755
index 0000000..316bdce
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libRoboRIO_FRC_ChipObject.so.1.2.0
Binary files differ
diff --git a/aos/externals/allwpilib/ni-libraries/libi2c.so b/aos/externals/allwpilib/ni-libraries/libi2c.so
new file mode 100644
index 0000000..673ca37
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libi2c.so
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libi2c.so.1 )
diff --git a/aos/externals/allwpilib/ni-libraries/libi2c.so.1 b/aos/externals/allwpilib/ni-libraries/libi2c.so.1
new file mode 100644
index 0000000..e10758b
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libi2c.so.1
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libi2c.so.1.0 )
diff --git a/aos/externals/allwpilib/ni-libraries/libi2c.so.1.0 b/aos/externals/allwpilib/ni-libraries/libi2c.so.1.0
new file mode 100644
index 0000000..68c5890
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libi2c.so.1.0
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libi2c.so.1.0.0 )
diff --git a/aos/externals/allwpilib/ni-libraries/libi2c.so.1.0.0 b/aos/externals/allwpilib/ni-libraries/libi2c.so.1.0.0
new file mode 100755
index 0000000..34740ca
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libi2c.so.1.0.0
Binary files differ
diff --git a/aos/externals/allwpilib/ni-libraries/liblog4cpp_gcc-4.4-arm_v2_3.so b/aos/externals/allwpilib/ni-libraries/liblog4cpp_gcc-4.4-arm_v2_3.so
new file mode 100755
index 0000000..46f6780
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/liblog4cpp_gcc-4.4-arm_v2_3.so
Binary files differ
diff --git a/aos/externals/allwpilib/ni-libraries/libni_emb.so b/aos/externals/allwpilib/ni-libraries/libni_emb.so
new file mode 100644
index 0000000..93678d5
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libni_emb.so
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libni_emb.so.7 )
diff --git a/aos/externals/allwpilib/ni-libraries/libni_emb.so.7 b/aos/externals/allwpilib/ni-libraries/libni_emb.so.7
new file mode 100644
index 0000000..aa703b7
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libni_emb.so.7
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libni_emb.so.7.0 )
diff --git a/aos/externals/allwpilib/ni-libraries/libni_emb.so.7.0 b/aos/externals/allwpilib/ni-libraries/libni_emb.so.7.0
new file mode 100644
index 0000000..da52c36
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libni_emb.so.7.0
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libni_emb.so.7.0.0 )
diff --git a/aos/externals/allwpilib/ni-libraries/libni_emb.so.7.0.0 b/aos/externals/allwpilib/ni-libraries/libni_emb.so.7.0.0
new file mode 100755
index 0000000..363b852
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libni_emb.so.7.0.0
Binary files differ
diff --git a/aos/externals/allwpilib/ni-libraries/libni_rtlog.so b/aos/externals/allwpilib/ni-libraries/libni_rtlog.so
new file mode 100644
index 0000000..3045681
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libni_rtlog.so
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libni_rtlog.so.2 )
diff --git a/aos/externals/allwpilib/ni-libraries/libni_rtlog.so.2 b/aos/externals/allwpilib/ni-libraries/libni_rtlog.so.2
new file mode 100644
index 0000000..f7fc193
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libni_rtlog.so.2
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libni_rtlog.so.2.3 )
diff --git a/aos/externals/allwpilib/ni-libraries/libni_rtlog.so.2.3 b/aos/externals/allwpilib/ni-libraries/libni_rtlog.so.2.3
new file mode 100644
index 0000000..f673867
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libni_rtlog.so.2.3
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libni_rtlog.so.2.3.0 )
diff --git a/aos/externals/allwpilib/ni-libraries/libni_rtlog.so.2.3.0 b/aos/externals/allwpilib/ni-libraries/libni_rtlog.so.2.3.0
new file mode 100755
index 0000000..2d6d6ae
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libni_rtlog.so.2.3.0
Binary files differ
diff --git a/aos/externals/allwpilib/ni-libraries/libniimaqdx.so b/aos/externals/allwpilib/ni-libraries/libniimaqdx.so
new file mode 100644
index 0000000..ed97ce7
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libniimaqdx.so
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libniimaqdx.so.14 )
diff --git a/aos/externals/allwpilib/ni-libraries/libniimaqdx.so.14 b/aos/externals/allwpilib/ni-libraries/libniimaqdx.so.14
new file mode 100644
index 0000000..6edea92
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libniimaqdx.so.14
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libniimaqdx.so.14.0 )
diff --git a/aos/externals/allwpilib/ni-libraries/libniimaqdx.so.14.0 b/aos/externals/allwpilib/ni-libraries/libniimaqdx.so.14.0
new file mode 100644
index 0000000..12b642e
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libniimaqdx.so.14.0
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libniimaqdx.so.14.0.0 )
diff --git a/aos/externals/allwpilib/ni-libraries/libniimaqdx.so.14.0.0 b/aos/externals/allwpilib/ni-libraries/libniimaqdx.so.14.0.0
new file mode 100755
index 0000000..27cd188
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libniimaqdx.so.14.0.0
Binary files differ
diff --git a/aos/externals/allwpilib/ni-libraries/libnirio_emb_can.so b/aos/externals/allwpilib/ni-libraries/libnirio_emb_can.so
new file mode 100644
index 0000000..eeb8133
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libnirio_emb_can.so
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libnirio_emb_can.so.14 )
diff --git a/aos/externals/allwpilib/ni-libraries/libnirio_emb_can.so.14 b/aos/externals/allwpilib/ni-libraries/libnirio_emb_can.so.14
new file mode 100644
index 0000000..c0548d7
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libnirio_emb_can.so.14
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libnirio_emb_can.so.14.0 )
diff --git a/aos/externals/allwpilib/ni-libraries/libnirio_emb_can.so.14.0 b/aos/externals/allwpilib/ni-libraries/libnirio_emb_can.so.14.0
new file mode 100644
index 0000000..b4e836f
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libnirio_emb_can.so.14.0
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libnirio_emb_can.so.14.0.0 )
diff --git a/aos/externals/allwpilib/ni-libraries/libnirio_emb_can.so.14.0.0 b/aos/externals/allwpilib/ni-libraries/libnirio_emb_can.so.14.0.0
new file mode 100755
index 0000000..3e04ea8
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libnirio_emb_can.so.14.0.0
Binary files differ
diff --git a/aos/externals/allwpilib/ni-libraries/libnivision.so b/aos/externals/allwpilib/ni-libraries/libnivision.so
new file mode 100644
index 0000000..67c0c57
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libnivision.so
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libnivision.so.14 )
diff --git a/aos/externals/allwpilib/ni-libraries/libnivision.so.14 b/aos/externals/allwpilib/ni-libraries/libnivision.so.14
new file mode 100644
index 0000000..4306944
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libnivision.so.14
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libnivision.so.14.0 )
diff --git a/aos/externals/allwpilib/ni-libraries/libnivision.so.14.0 b/aos/externals/allwpilib/ni-libraries/libnivision.so.14.0
new file mode 100644
index 0000000..3a4d263
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libnivision.so.14.0
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libnivision.so.14.0.0 )
diff --git a/aos/externals/allwpilib/ni-libraries/libnivision.so.14.0.0 b/aos/externals/allwpilib/ni-libraries/libnivision.so.14.0.0
new file mode 100755
index 0000000..a0a4810
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libnivision.so.14.0.0
Binary files differ
diff --git a/aos/externals/allwpilib/ni-libraries/libnivissvc.so b/aos/externals/allwpilib/ni-libraries/libnivissvc.so
new file mode 100644
index 0000000..e0bbd48
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libnivissvc.so
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libnivissvc.so.14 )
diff --git a/aos/externals/allwpilib/ni-libraries/libnivissvc.so.14 b/aos/externals/allwpilib/ni-libraries/libnivissvc.so.14
new file mode 100644
index 0000000..205cc35
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libnivissvc.so.14
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libnivissvc.so.14.0 )
diff --git a/aos/externals/allwpilib/ni-libraries/libnivissvc.so.14.0 b/aos/externals/allwpilib/ni-libraries/libnivissvc.so.14.0
new file mode 100644
index 0000000..26ffd42
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libnivissvc.so.14.0
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libnivissvc.so.14.0.0 )
diff --git a/aos/externals/allwpilib/ni-libraries/libnivissvc.so.14.0.0 b/aos/externals/allwpilib/ni-libraries/libnivissvc.so.14.0.0
new file mode 100755
index 0000000..480578d
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libnivissvc.so.14.0.0
Binary files differ
diff --git a/aos/externals/allwpilib/ni-libraries/libspi.so b/aos/externals/allwpilib/ni-libraries/libspi.so
new file mode 100644
index 0000000..e77606f
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libspi.so
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libspi.so.1 )
diff --git a/aos/externals/allwpilib/ni-libraries/libspi.so.1 b/aos/externals/allwpilib/ni-libraries/libspi.so.1
new file mode 100644
index 0000000..5aa0632
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libspi.so.1
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libspi.so.1.0 )
diff --git a/aos/externals/allwpilib/ni-libraries/libspi.so.1.0 b/aos/externals/allwpilib/ni-libraries/libspi.so.1.0
new file mode 100644
index 0000000..9f016df
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libspi.so.1.0
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( libspi.so.1.0.0 )
diff --git a/aos/externals/allwpilib/ni-libraries/libspi.so.1.0.0 b/aos/externals/allwpilib/ni-libraries/libspi.so.1.0.0
new file mode 100755
index 0000000..5f69f31
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libspi.so.1.0.0
Binary files differ
diff --git a/aos/externals/allwpilib/ni-libraries/libvisa.so b/aos/externals/allwpilib/ni-libraries/libvisa.so
new file mode 100755
index 0000000..4ca711c
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libvisa.so
Binary files differ
diff --git a/aos/externals/allwpilib/ni-libraries/libwpi.so b/aos/externals/allwpilib/ni-libraries/libwpi.so
new file mode 100644
index 0000000..429ff80
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libwpi.so
@@ -0,0 +1,3 @@
+/* GNU ld script */
+OUTPUT_FORMAT(elf32-littlearm)
+INPUT ( -lwpi_2015 )
diff --git a/aos/externals/allwpilib/ni-libraries/libwpi_2015.so b/aos/externals/allwpilib/ni-libraries/libwpi_2015.so
new file mode 100644
index 0000000..3589af2
--- /dev/null
+++ b/aos/externals/allwpilib/ni-libraries/libwpi_2015.so
@@ -0,0 +1,3 @@
+/* GNU ld script */
+OUTPUT_FORMAT(elf32-littlearm)
+GROUP ( AS_NEEDED ( -lwpilib_nonshared -lHALAthena -lNetworkTables -lFRC_NetworkCommunication -li2c -lni_emb -lNiFpgaLv -lNiFpga -lnirio_emb_can -lNiRioSrv -lni_rtlog -lRoboRIO_FRC_ChipObject -lspi -lvisa -ldl -lpthread -lrt -lGCBase_gcc-4.4-arm_v2_3 -lGenApi_gcc-4.4-arm_v2_3 -lLog_gcc-4.4-arm_v2_3 -lMathParser_gcc-4.4-arm_v2_3 -llog4cpp_gcc-4.4-arm_v2_3 -lniimaqdx -lnivision -lnivissvc ) )
diff --git a/aos/externals/allwpilib/sync.sh b/aos/externals/allwpilib/sync.sh
new file mode 100755
index 0000000..8e05233
--- /dev/null
+++ b/aos/externals/allwpilib/sync.sh
@@ -0,0 +1,20 @@
+#!/bin/bash -e
+
+# This script copies the correct directories over from an allwpilib git
+# repository (which needs to have a working tree).
+# THIS WILL ERASE ANY LOCAL CHANGES TO THE WPILIB SOURCES!
+
+# Takes 1 argument: the folder to copy from.
+
+cd $(dirname $0)
+
+SOURCE=$1
+DIRS="wpilibc hal ni-libraries"
+
+[ -n "${SOURCE}" ] || ( echo "Need a directory to sync from!" ; exit 1 )
+[ -d "${SOURCE}" ] || ( echo "${SOURCE} is not a directory. Aborting!" ; exit 1 )
+
+for dir in ${DIRS}; do
+	[ -d ${dir} ] && rm -r ${dir}
+	cp -r ${SOURCE}/${dir} ./
+done
diff --git a/aos/externals/allwpilib/wpilibc/CMakeLists.txt b/aos/externals/allwpilib/wpilibc/CMakeLists.txt
new file mode 100644
index 0000000..de4a7ef
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8)
+project(WPILibC)
+
+add_subdirectory(wpilibC++)
+add_subdirectory(wpilibC++Devices)
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++/CMakeLists.txt b/aos/externals/allwpilib/wpilibc/wpilibC++/CMakeLists.txt
new file mode 100644
index 0000000..4af3fc9
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8)
+project(WPILibC++)
+
+INSTALL(DIRECTORY include DESTINATION ${CMAKE_INSTALL_PREFIX} COMPONENT headers)
+
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++/include/Base.h b/aos/externals/allwpilib/wpilibc/wpilibC++/include/Base.h
new file mode 100644
index 0000000..74073e8
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++/include/Base.h
@@ -0,0 +1,12 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+// A macro to disallow the copy constructor and operator= functions
+// This should be used in the private: declarations for a class
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+  TypeName(const TypeName&) = delete;      \
+  void operator=(const TypeName&) = delete
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++/include/Controller.h b/aos/externals/allwpilib/wpilibc/wpilibC++/include/Controller.h
new file mode 100644
index 0000000..99eba88
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++/include/Controller.h
@@ -0,0 +1,34 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include <stdint.h>
+#include <cmath>
+#include <pthread.h>
+#include <semaphore.h>
+
+/**
+ * Interface for Controllers
+ * Common interface for controllers. Controllers run control loops, the most common
+ * are PID controllers and their variants, but this includes anything that is controlling
+ * an actuator in a separate thread.
+ */
+class Controller
+{
+public:
+	virtual ~Controller() {};
+	
+	/**
+	 * Allows the control loop to run
+	 */
+	virtual void Enable() = 0;
+	
+	/** 
+	 * Stops the control loop from running until explicitly re-enabled by calling enable()
+	 */
+	virtual void Disable() = 0;
+};
+
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++/include/Error.h b/aos/externals/allwpilib/wpilibc/wpilibC++/include/Error.h
new file mode 100644
index 0000000..4fbe0f0
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++/include/Error.h
@@ -0,0 +1,54 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "Base.h"
+#include <string>
+#include <stdint.h>
+
+//  Forward declarations
+class ErrorBase;
+
+/**
+ * Error object represents a library error.
+ */
+class Error
+{
+public:
+	typedef int32_t Code;
+
+	Error();
+	~Error();
+	void Clone(Error &error);
+	Code GetCode() const;
+	const char *GetMessage() const;
+	const char *GetFilename() const;
+	const char *GetFunction() const;
+	uint32_t GetLineNumber() const;
+	const ErrorBase* GetOriginatingObject() const;
+	double GetTimestamp() const;
+	void Clear();
+	void Set(Code code, const char* contextMessage, const char* filename, const char *function,
+			uint32_t lineNumber, const ErrorBase* originatingObject);
+	static void EnableSuspendOnError(bool enable)
+	{
+		m_suspendOnErrorEnabled = enable;
+	}
+
+private:
+	void Report();
+
+	Code m_code;
+	std::string m_message;
+	std::string m_filename;
+	std::string m_function;
+	uint32_t m_lineNumber;
+	const ErrorBase* m_originatingObject;
+	double m_timestamp;
+
+	static bool m_suspendOnErrorEnabled;
+    DISALLOW_COPY_AND_ASSIGN(Error);
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++/include/ErrorBase.h b/aos/externals/allwpilib/wpilibc/wpilibC++/include/ErrorBase.h
new file mode 100644
index 0000000..94e9164
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++/include/ErrorBase.h
@@ -0,0 +1,64 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "Base.h"
+#include "Error.h"
+#include "HAL/cpp/Synchronized.hpp"
+
+#define wpi_setErrnoErrorWithContext(context)   (this->SetErrnoError((context), __FILE__, __FUNCTION__, __LINE__))
+#define wpi_setErrnoError()   (wpi_setErrnoErrorWithContext(""))
+#define wpi_setImaqErrorWithContext(code, context)   (this->SetImaqError((code), (context), __FILE__, __FUNCTION__, __LINE__))
+#define wpi_setErrorWithContext(code, context)   (this->SetError((code), (context), __FILE__, __FUNCTION__, __LINE__))
+#define wpi_setError(code)   (wpi_setErrorWithContext(code, ""))
+#define wpi_setStaticErrorWithContext(object, code, context)   (object->SetError((code), (context), __FILE__, __FUNCTION__, __LINE__))
+#define wpi_setStaticError(object, code)   (wpi_setStaticErrorWithContext(object, code, ""))
+#define wpi_setGlobalErrorWithContext(code, context)   (ErrorBase::SetGlobalError((code), (context), __FILE__, __FUNCTION__, __LINE__))
+#define wpi_setGlobalError(code)   (wpi_setGlobalErrorWithContext(code, ""))
+#define wpi_setWPIErrorWithContext(error, context)   (this->SetWPIError((wpi_error_s_##error), (wpi_error_value_##error), (context), __FILE__, __FUNCTION__, __LINE__))
+#define wpi_setWPIError(error)   (wpi_setWPIErrorWithContext(error, ""))
+#define wpi_setStaticWPIErrorWithContext(object, error, context)   (object->SetWPIError((wpi_error_s_##error), (context), __FILE__, __FUNCTION__, __LINE__))
+#define wpi_setStaticWPIError(object, error)   (wpi_setStaticWPIErrorWithContext(object, error, ""))
+#define wpi_setGlobalWPIErrorWithContext(error, context)   (ErrorBase::SetGlobalWPIError((wpi_error_s_##error), (context), __FILE__, __FUNCTION__, __LINE__))
+#define wpi_setGlobalWPIError(error)   (wpi_setGlobalWPIErrorWithContext(error, ""))
+
+/**
+ * Base class for most objects.
+ * ErrorBase is the base class for most objects since it holds the generated error
+ * for that object. In addition, there is a single instance of a global error object
+ */
+class ErrorBase
+{
+//TODO: Consider initializing instance variables and cleanup in destructor
+public:
+	virtual ~ErrorBase();
+	virtual Error& GetError();
+	virtual const Error& GetError() const;
+	virtual void SetErrnoError(const char *contextMessage, const char* filename,
+			const char* function, uint32_t lineNumber) const;
+	virtual void SetImaqError(int success, const char *contextMessage, const char* filename,
+			const char* function, uint32_t lineNumber) const;
+	virtual void SetError(Error::Code code, const char *contextMessage, const char* filename,
+			const char* function, uint32_t lineNumber) const;
+	virtual void SetWPIError(const char *errorMessage, Error::Code code, const char *contextMessage,
+			const char* filename, const char* function, uint32_t lineNumber) const;
+	virtual void CloneError(ErrorBase *rhs) const;
+	virtual void ClearError() const;
+	virtual bool StatusIsFatal() const;
+	static void SetGlobalError(Error::Code code, const char *contextMessage, const char* filename,
+			const char* function, uint32_t lineNumber);
+	static void SetGlobalWPIError(const char *errorMessage, const char *contextMessage,
+			const char* filename, const char* function, uint32_t lineNumber);
+	static Error& GetGlobalError();
+protected:
+	mutable Error m_error;
+	// TODO: Replace globalError with a global list of all errors.
+	static Mutex _globalErrorMutex;
+	static Error _globalError;
+	ErrorBase();
+private:
+	DISALLOW_COPY_AND_ASSIGN(ErrorBase);
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++/include/GenericHID.h b/aos/externals/allwpilib/wpilibc/wpilibC++/include/GenericHID.h
new file mode 100644
index 0000000..cb8dfde
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++/include/GenericHID.h
@@ -0,0 +1,38 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include <stdint.h>
+
+/** GenericHID Interface
+ */
+class GenericHID
+{
+public:
+	enum JoystickHand
+	{
+		kLeftHand = 0,
+		kRightHand = 1
+	};
+
+	virtual ~GenericHID()
+	{
+	}
+
+	virtual float GetX(JoystickHand hand = kRightHand) = 0;
+	virtual float GetY(JoystickHand hand = kRightHand) = 0;
+	virtual float GetZ() = 0;
+	virtual float GetTwist() = 0;
+	virtual float GetThrottle() = 0;
+	virtual float GetRawAxis(uint32_t axis) = 0;
+
+	virtual bool GetTrigger(JoystickHand hand = kRightHand) = 0;
+	virtual bool GetTop(JoystickHand hand = kRightHand) = 0;
+	virtual bool GetBumper(JoystickHand hand = kRightHand) = 0;
+	virtual bool GetRawButton(uint32_t button) = 0;
+
+	virtual int GetPOV(uint32_t pov = 0) = 0;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++/include/HLUsageReporting.h b/aos/externals/allwpilib/wpilibc/wpilibC++/include/HLUsageReporting.h
new file mode 100644
index 0000000..359b149
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++/include/HLUsageReporting.h
@@ -0,0 +1,25 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+class HLUsageReportingInterface
+{
+public:
+	virtual ~HLUsageReportingInterface() {};
+	virtual void ReportScheduler() = 0;
+    virtual void ReportSmartDashboard() = 0;
+};
+
+class HLUsageReporting
+{
+private:
+	static HLUsageReportingInterface* impl;
+	
+public:
+	static void SetImplementation(HLUsageReportingInterface* i);
+	static void ReportScheduler();
+    static void ReportSmartDashboard();
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++/include/Notifier.h b/aos/externals/allwpilib/wpilibc/wpilibC++/include/Notifier.h
new file mode 100644
index 0000000..9579e67
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++/include/Notifier.h
@@ -0,0 +1,45 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "ErrorBase.h"
+#include "Task.h"
+#include "HAL/cpp/Synchronized.hpp"
+
+typedef void (*TimerEventHandler)(void *param);
+
+class Notifier : public ErrorBase
+{
+public:
+	Notifier(TimerEventHandler handler, void *param = NULL);
+	virtual ~Notifier();
+	void StartSingle(double delay);
+	void StartPeriodic(double period);
+	void Stop();
+private:
+	static Notifier *timerQueueHead;
+	static ReentrantMutex queueSemaphore;
+	static void* m_notifier;
+	static int refcount;
+
+	static void ProcessQueue(uint32_t mask, void *params); // process the timer queue on a timer event
+	static void UpdateAlarm();			// update the FPGA alarm since the queue has changed
+	void InsertInQueue(bool reschedule);	// insert this Notifier in the timer queue
+	void DeleteFromQueue();				// delete this Notifier from the timer queue
+	TimerEventHandler m_handler;			// address of the handler
+	void *m_param;							// a parameter to pass to the handler
+	double m_period;						// the relative time (either periodic or single)
+	double m_expirationTime;				// absolute expiration time for the current event
+	Notifier *m_nextEvent;					// next Nofifier event
+	bool m_periodic;						// true if this is a periodic event
+	bool m_queued;							// indicates if this entry is queued
+	SEMAPHORE_ID m_handlerSemaphore;		// held by interrupt manager task while handler call is in progress
+
+	DISALLOW_COPY_AND_ASSIGN(Notifier);
+
+	static Task *task;
+	static void Run();
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++/include/PIDOutput.h b/aos/externals/allwpilib/wpilibc/wpilibC++/include/PIDOutput.h
new file mode 100644
index 0000000..a2e2c95
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++/include/PIDOutput.h
@@ -0,0 +1,20 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "Base.h"
+
+/**
+ * PIDOutput interface is a generic output for the PID class.
+ * PWMs use this class.
+ * Users implement this interface to allow for a PIDController to 
+ * read directly from the inputs
+ */
+class PIDOutput
+{
+public:
+	virtual void PIDWrite(float output) = 0;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++/include/PIDSource.h b/aos/externals/allwpilib/wpilibc/wpilibC++/include/PIDSource.h
new file mode 100644
index 0000000..e81bd28
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++/include/PIDSource.h
@@ -0,0 +1,18 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+/**
+ * PIDSource interface is a generic sensor source for the PID class.
+ * All sensors that can be used with the PID class will implement the PIDSource that
+ * returns a standard value that will be used in the PID code.
+ */
+class PIDSource
+{	
+public:
+	enum PIDSourceParameter {kDistance, kRate, kAngle};
+	virtual double PIDGet() = 0;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++/include/Resource.h b/aos/externals/allwpilib/wpilibc/wpilibC++/include/Resource.h
new file mode 100644
index 0000000..4eb9427
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++/include/Resource.h
@@ -0,0 +1,40 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "ErrorBase.h"
+#include "HAL/cpp/Synchronized.hpp"
+#include <stdint.h>
+
+/**
+ * The Resource class is a convenient way to track allocated resources.
+ * It tracks them as indicies in the range [0 .. elements - 1].
+ * E.g. the library uses this to track hardware channel allocation.
+ *
+ * The Resource class does not allocate the hardware channels or other
+ * resources; it just tracks which indices were marked in use by
+ * Allocate and not yet freed by Free.
+ */
+class Resource : public ErrorBase
+{
+public:
+	virtual ~Resource();
+	static void CreateResourceObject(Resource **r, uint32_t elements);
+	uint32_t Allocate(const char *resourceDesc);
+	uint32_t Allocate(uint32_t index, const char *resourceDesc);
+	void Free(uint32_t index);
+
+private:
+	explicit Resource(uint32_t size);
+
+	bool *m_isAllocated;
+	ReentrantMutex m_allocateLock;
+	uint32_t m_size;
+
+	static ReentrantMutex m_createLock;
+
+	DISALLOW_COPY_AND_ASSIGN(Resource);
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++/include/RobotState.h b/aos/externals/allwpilib/wpilibc/wpilibC++/include/RobotState.h
new file mode 100644
index 0000000..ee25493
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++/include/RobotState.h
@@ -0,0 +1,33 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+class RobotStateInterface
+{
+public:
+	virtual ~RobotStateInterface() {};
+    virtual bool IsDisabled() = 0;
+	virtual bool IsEnabled() = 0;
+	virtual bool IsOperatorControl() = 0;
+	virtual bool IsAutonomous() = 0;
+	virtual bool IsTest() = 0;
+};
+
+class RobotState
+{
+private:
+	static RobotStateInterface* impl;
+	
+public:
+	static void SetImplementation(RobotStateInterface* i);
+    static bool IsDisabled();
+	static bool IsEnabled();
+	static bool IsOperatorControl();
+	static bool IsAutonomous();
+	static bool IsTest();
+};
+
+
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++/include/SensorBase.h b/aos/externals/allwpilib/wpilibc/wpilibC++/include/SensorBase.h
new file mode 100644
index 0000000..65e16ec
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++/include/SensorBase.h
@@ -0,0 +1,63 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "ErrorBase.h"
+#include <stdio.h>
+#include "Base.h"
+
+class DigitalGlitchFilter;
+
+/**
+ * Base class for all sensors.
+ * Stores most recent status information as well as containing utility functions for checking
+ * channels and error processing.
+ */
+class SensorBase : public ErrorBase
+{
+public:
+	SensorBase();
+	virtual ~SensorBase();
+	static void DeleteSingletons();
+
+	static uint32_t GetDefaultSolenoidModule()
+	{
+		return 0;
+	}
+
+	static bool CheckSolenoidModule(uint8_t moduleNumber);
+	static bool CheckDigitalChannel(uint32_t channel);
+	static bool CheckRelayChannel(uint32_t channel);
+	static bool CheckPWMChannel(uint32_t channel);
+	static bool CheckAnalogInput(uint32_t channel);
+	static bool CheckAnalogOutput(uint32_t channel);
+	static bool CheckSolenoidChannel(uint32_t channel);
+	static bool CheckPDPChannel(uint32_t channel);
+
+	static const uint32_t kDigitalChannels = 26;
+	static const uint32_t kAnalogInputs = 8;
+	static const uint32_t kAnalogOutputs = 2;
+	static const uint32_t kSolenoidChannels = 8;
+	static const uint32_t kSolenoidModules = 2;
+	static const uint32_t kPwmChannels = 20;
+	static const uint32_t kRelayChannels = 8;
+	static const uint32_t kPDPChannels = 16;
+	static const uint32_t kChassisSlots = 8;
+
+protected:
+	void AddToSingletonList();
+
+	static void* m_digital_ports[kDigitalChannels];
+	static void* m_relay_ports[kRelayChannels];
+	static void* m_pwm_ports[kPwmChannels];
+
+private:
+	DISALLOW_COPY_AND_ASSIGN(SensorBase);
+	static SensorBase *m_singletonList;
+	SensorBase *m_nextSingleton;
+
+  friend class DigitalGlitchFilter;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++/include/Task.h b/aos/externals/allwpilib/wpilibc/wpilibC++/include/Task.h
new file mode 100644
index 0000000..ca1754a
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++/include/Task.h
@@ -0,0 +1,52 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "ErrorBase.h"
+#include "HAL/Task.hpp"
+
+/**
+ * WPI task is a wrapper for the native Task object.
+ * All WPILib tasks are managed by a static task manager for simplified cleanup.
+ **/
+class Task : public ErrorBase
+{
+public:
+	static const uint32_t kDefaultPriority = 101;
+
+	Task(const char* name, FUNCPTR function, int32_t priority = kDefaultPriority,
+			uint32_t stackSize = 20000);
+	virtual ~Task();
+
+	bool Start(uint32_t arg0 = 0, uint32_t arg1 = 0, uint32_t arg2 = 0, uint32_t arg3 = 0,
+			uint32_t arg4 = 0, uint32_t arg5 = 0, uint32_t arg6 = 0, uint32_t arg7 = 0,
+			uint32_t arg8 = 0, uint32_t arg9 = 0);
+	bool Restart();
+	bool Stop();
+
+	bool IsReady();
+	bool IsSuspended();
+
+	bool Suspend();
+	bool Resume();
+
+	bool Verify();
+
+	int32_t GetPriority();
+	bool SetPriority(int32_t priority);
+	const char* GetName();
+	TASK GetID();
+
+private:
+	FUNCPTR m_function;
+	char* m_taskName;
+	TASK m_taskID;
+	uint32_t m_stackSize;
+	int m_priority;
+	bool HandleError(STATUS results);
+	DISALLOW_COPY_AND_ASSIGN(Task);
+};
+
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++/include/Timer.h b/aos/externals/allwpilib/wpilibc/wpilibC++/include/Timer.h
new file mode 100644
index 0000000..fc3f9af
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++/include/Timer.h
@@ -0,0 +1,48 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "HAL/cpp/Synchronized.hpp"
+#include "Base.h"
+
+typedef void (*TimerInterruptHandler)(void *param);
+
+void Wait(double seconds);
+double GetClock();
+double GetTime();
+
+/**
+ * Timer objects measure accumulated time in seconds.
+ * The timer object functions like a stopwatch. It can be started, stopped, and cleared. When the
+ * timer is running its value counts up in seconds. When stopped, the timer holds the current
+ * value. The implementation simply records the time when started and subtracts the current time
+ * whenever the value is requested.
+ */
+class Timer
+{
+public:
+	Timer();
+	virtual ~Timer();
+	double Get();
+	void Reset();
+	void Start();
+	void Stop();
+	bool HasPeriodPassed(double period);
+
+	static double GetFPGATimestamp();
+	static double GetPPCTimestamp();
+    static double GetMatchTime();
+	
+	// The time, in seconds, at which the 32-bit FPGA timestamp rolls over to 0
+	static constexpr double kRolloverTime = (1ll << 32) / 1e6;
+
+private:
+	double m_startTime;
+	double m_accumulatedTime;
+	bool m_running;
+	Mutex m_lock;
+	DISALLOW_COPY_AND_ASSIGN(Timer);
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++/include/Utility.h b/aos/externals/allwpilib/wpilibc/wpilibC++/include/Utility.h
new file mode 100644
index 0000000..f081489
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++/include/Utility.h
@@ -0,0 +1,34 @@
+/*---------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							 */
+/* Open Source Software - may be modified and shared by FRC teams. The code  */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
+/*---------------------------------------------------------------------------*/
+#pragma once
+
+/** @file
+ * Contains global utility functions
+ */
+
+#include <stdint.h>
+#include <string>
+
+#define wpi_assert(condition) wpi_assert_impl(condition, #condition, NULL, __FILE__, __LINE__, __FUNCTION__)
+#define wpi_assertWithMessage(condition, message) wpi_assert_impl(condition, #condition, message, __FILE__, __LINE__, __FUNCTION__)
+
+#define wpi_assertEqual(a, b) wpi_assertEqual_impl(a, b, #a, #b, NULL, __FILE__, __LINE__, __FUNCTION__)
+#define wpi_assertEqualWithMessage(a, b, message) wpi_assertEqual_impl(a, b, #a, #b, message, __FILE__, __LINE__, __FUNCTION__)
+
+#define wpi_assertNotEqual(a, b) wpi_assertNotEqual_impl(a, b, #a, #b, NULL, __FILE__, __LINE__, __FUNCTION__)
+#define wpi_assertNotEqualWithMessage(a, b, message) wpi_assertNotEqual_impl(a, b, #a, #b, message, __FILE__, __LINE__, __FUNCTION__)
+
+bool wpi_assert_impl(bool conditionValue, const char *conditionText, const char *message, const char *fileName, uint32_t lineNumber, const char *funcName);
+bool wpi_assertEqual_impl(int valueA, int valueB, const char *valueAString, const char *valueBString, const char *message, const char *fileName,uint32_t lineNumber, const char *funcName);
+bool wpi_assertNotEqual_impl(int valueA, int valueB, const char *valueAString, const char *valueBString, const char *message, const char *fileName,uint32_t lineNumber, const char *funcName);
+
+void wpi_suspendOnAssertEnabled(bool enabled);
+
+uint16_t GetFPGAVersion();
+uint32_t GetFPGARevision();
+uint32_t GetFPGATime();
+bool GetUserButton();
+std::string GetStackTrace(uint32_t offset);
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++/include/WPIErrors.h b/aos/externals/allwpilib/wpilibc/wpilibC++/include/WPIErrors.h
new file mode 100644
index 0000000..9e37715
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++/include/WPIErrors.h
@@ -0,0 +1,78 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#ifdef WPI_ERRORS_DEFINE_STRINGS
+#define S(label, offset, message) const char *wpi_error_s_##label = message ; \
+	const int32_t wpi_error_value_##label = offset
+#else
+#define S(label, offset, message) extern const char *wpi_error_s_##label ; \
+	const int32_t wpi_error_value_##label = offset
+#endif
+
+/*
+ * Fatal errors
+ */
+S(ModuleIndexOutOfRange, -1, "Allocating module that is out of range or not found");
+S(ChannelIndexOutOfRange, -1, "Allocating channel that is out of range");
+S(NotAllocated, -2, "Attempting to free unallocated resource");
+S(ResourceAlreadyAllocated, -3, "Attempted to reuse an allocated resource");
+S(NoAvailableResources, -4, "No available resources to allocate");
+S(NullParameter, -5, "A pointer parameter to a method is NULL");
+S(Timeout, -6, "A timeout has been exceeded");
+S(CompassManufacturerError, -7, "Compass manufacturer doesn't match HiTechnic");
+S(CompassTypeError, -8, "Compass type doesn't match expected type for HiTechnic compass");
+S(IncompatibleMode, -9, "The object is in an incompatible mode");
+S(AnalogTriggerLimitOrderError, -10, "AnalogTrigger limits error.  Lower limit > Upper Limit");
+S(AnalogTriggerPulseOutputError, -11, "Attempted to read AnalogTrigger pulse output.");
+S(TaskError, -12, "Task can't be started");
+S(TaskIDError, -13, "Task error: Invalid ID.");
+S(TaskDeletedError, -14, "Task error: Task already deleted.");
+S(TaskOptionsError, -15, "Task error: Invalid options.");
+S(TaskMemoryError, -16, "Task can't be started due to insufficient memory.");
+S(TaskPriorityError, -17, "Task error: Invalid priority [1-255].");
+S(DriveUninitialized, -18, "RobotDrive not initialized for the C interface");
+S(CompressorNonMatching, -19, "Compressor slot/channel doesn't match previous instance");
+S(CompressorAlreadyDefined, -20, "Creating a second compressor instance");
+S(CompressorUndefined, -21, "Using compressor functions without defining compressor");
+S(InconsistentArrayValueAdded, -22, "When packing data into an array to the dashboard, not all values added were of the same type.");
+S(MismatchedComplexTypeClose, -23, "When packing data to the dashboard, a Close for a complex type was called without a matching Open.");
+S(DashboardDataOverflow, -24, "When packing data to the dashboard, too much data was packed and the buffer overflowed.");
+S(DashboardDataCollision, -25, "The same buffer was used for packing data and for printing.");
+S(EnhancedIOMissing, -26, "IO is not attached or Enhanced IO is not enabled.");
+S(LineNotOutput, -27, "Cannot SetDigitalOutput for a line not configured for output.");
+S(ParameterOutOfRange, -28, "A parameter is out of range.");
+S(SPIClockRateTooLow, -29, "SPI clock rate was below the minimum supported");
+S(JaguarVersionError, -30, "Jaguar firmware version error");
+S(JaguarMessageNotFound, -31, "Jaguar message not found");
+S(NetworkTablesReadError, -40, "Error reading NetworkTables socket");
+S(NetworkTablesBufferFull, -41, "Buffer full writing to NetworkTables socket");
+S(NetworkTablesWrongType, -42, "The wrong type was read from the NetworkTables entry");
+S(NetworkTablesCorrupt, -43, "NetworkTables data stream is corrupt");
+S(SmartDashboardMissingKey, -43, "SmartDashboard data does not exist");
+S(CommandIllegalUse, -50, "Illegal use of Command");
+S(UnsupportedInSimulation, -80, "Unsupported in simulation");
+
+/*
+ * Warnings
+ */
+S(SampleRateTooHigh, 1, "Analog module sample rate is too high");
+S(VoltageOutOfRange, 2, "Voltage to convert to raw value is out of range [-10; 10]");
+S(CompressorTaskError, 3, "Compressor task won't start");
+S(LoopTimingError, 4, "Digital module loop timing is not the expected value");
+S(NonBinaryDigitalValue, 5, "Digital output value is not 0 or 1");
+S(IncorrectBatteryChannel, 6, "Battery measurement channel is not correct value");
+S(BadJoystickIndex, 7, "Joystick index is out of range, should be 0-3");
+S(BadJoystickAxis, 8, "Joystick axis or POV is out of range");
+S(InvalidMotorIndex, 9, "Motor index is out of range, should be 0-3");
+S(DriverStationTaskError, 10, "Driver Station task won't start");
+S(EnhancedIOPWMPeriodOutOfRange, 11, "Driver Station Enhanced IO PWM Output period out of range.");
+S(SPIWriteNoMOSI, 12, "Cannot write to SPI port with no MOSI output");
+S(SPIReadNoMISO, 13, "Cannot read from SPI port with no MISO input");
+S(SPIReadNoData, 14, "No data available to read from SPI");
+S(IncompatibleState, 15, "Incompatible State: The operation cannot be completed");
+
+#undef S
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++/include/interfaces/Accelerometer.h b/aos/externals/allwpilib/wpilibc/wpilibC++/include/interfaces/Accelerometer.h
new file mode 100644
index 0000000..609e9bc
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++/include/interfaces/Accelerometer.h
@@ -0,0 +1,52 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+/**
+ * Interface for 3-axis accelerometers
+ */
+class Accelerometer
+{
+public:
+	virtual ~Accelerometer() {};
+
+	enum Range
+	{
+		kRange_2G = 0,
+		kRange_4G = 1,
+		kRange_8G = 2,
+		kRange_16G = 3
+	};
+
+	/**
+	 * Common interface for setting the measuring range of an accelerometer.
+	 *
+	 * @param range The maximum acceleration, positive or negative, that the
+	 * accelerometer will measure.  Not all accelerometers support all ranges.
+	 */
+	virtual void SetRange(Range range) = 0;
+
+	/**
+	 * Common interface for getting the x axis acceleration
+	 *
+	 * @return The acceleration along the x axis in g-forces
+	 */
+	virtual double GetX() = 0;
+
+	/**
+	 * Common interface for getting the y axis acceleration
+	 *
+	 * @return The acceleration along the y axis in g-forces
+	 */
+	virtual double GetY() = 0;
+
+	/**
+	 * Common interface for getting the z axis acceleration
+	 *
+	 * @return The acceleration along the z axis in g-forces
+	 */
+	virtual double GetZ() = 0;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++/include/interfaces/Potentiometer.h b/aos/externals/allwpilib/wpilibc/wpilibC++/include/interfaces/Potentiometer.h
new file mode 100644
index 0000000..f5f4567
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++/include/interfaces/Potentiometer.h
@@ -0,0 +1,27 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#ifndef INTERFACES_POTENTIOMETER_H
+#define INTERFACES_POTENTIOMETER_H
+
+#include "PIDSource.h"
+
+/**
+ * Interface for potentiometers.
+ */
+class Potentiometer : public PIDSource
+{
+public:
+	virtual ~Potentiometer() {};
+	/**
+	 * Common interface for getting the current value of a potentiometer.
+	 * 
+	 * @return The current set speed.  Value is between -1.0 and 1.0.
+	 */
+	virtual double Get() = 0;
+};
+
+#endif
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++/src/Error.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++/src/Error.cpp
new file mode 100644
index 0000000..f64c4fe
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++/src/Error.cpp
@@ -0,0 +1,111 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "Error.h"
+
+#include <iostream>
+#include <sstream>
+#include <cstring>
+#include <cstdlib>
+#include <stdint.h>
+#include "HAL/Task.hpp"
+
+#include "DriverStation.h"
+#include "Timer.h"
+#include "Utility.h"
+bool Error::m_suspendOnErrorEnabled = false;
+
+Error::Error()
+	: m_code(0)
+	, m_lineNumber(0)
+	, m_originatingObject(NULL)
+	, m_timestamp (0.0)
+{}
+
+Error::~Error()
+{}
+
+void Error::Clone(Error &error)
+{
+	m_code = error.m_code;
+	m_message = error.m_message;
+	m_filename = error.m_filename;
+	m_function = error.m_function;
+	m_lineNumber = error.m_lineNumber;
+	m_originatingObject = error.m_originatingObject;
+	m_timestamp = error.m_timestamp;
+}
+
+Error::Code Error::GetCode() const
+{	return m_code;  }
+
+const char * Error::GetMessage() const
+{	return m_message.c_str();  }
+
+const char * Error::GetFilename() const
+{	return m_filename.c_str();  }
+
+const char * Error::GetFunction() const
+{	return m_function.c_str();  }
+
+uint32_t Error::GetLineNumber() const
+{	return m_lineNumber;  }
+
+const ErrorBase* Error::GetOriginatingObject() const
+{	return m_originatingObject;  }
+
+double Error::GetTimestamp() const
+{	return m_timestamp;  }
+
+void Error::Set(Code code, const char* contextMessage, const char* filename, const char* function, uint32_t lineNumber, const ErrorBase* originatingObject)
+{
+	bool report = true;
+
+	if(code == m_code && GetTime() - m_timestamp < 1)
+	{
+		report = false;
+	}
+
+	m_code = code;
+	m_message = contextMessage;
+	m_filename = filename;
+	m_function = function;
+	m_lineNumber = lineNumber;
+	m_originatingObject = originatingObject;
+
+	if(report)
+	{
+		m_timestamp = GetTime();
+		Report();
+	}
+
+    if (m_suspendOnErrorEnabled) suspendTask(0);
+}
+
+void Error::Report()
+{
+	std::stringstream errorStream;
+
+	errorStream << "Error on line " << m_lineNumber << " ";
+	errorStream << "of "<< basename(m_filename.c_str()) << ": ";
+	errorStream << m_message << std::endl;
+	errorStream << GetStackTrace(4);
+
+	std::string error = errorStream.str();
+
+	DriverStation::ReportError(error);
+}
+
+void Error::Clear()
+{
+	m_code = 0;
+	m_message = "";
+	m_filename = "";
+	m_function = "";
+	m_lineNumber = 0;
+	m_originatingObject = NULL;
+	m_timestamp = 0.0;
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++/src/ErrorBase.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++/src/ErrorBase.cpp
new file mode 100644
index 0000000..e4dda4b
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++/src/ErrorBase.cpp
@@ -0,0 +1,205 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "ErrorBase.h"
+#include "HAL/cpp/Synchronized.hpp"
+#define WPI_ERRORS_DEFINE_STRINGS
+#include "WPIErrors.h"
+
+#include <errno.h>
+#include <cstring>
+#include <cstdio>
+
+Mutex ErrorBase::_globalErrorMutex;
+Error ErrorBase::_globalError;
+/**
+ * @brief Initialize the instance status to 0 for now.
+ */
+ErrorBase::ErrorBase()
+{}
+
+ErrorBase::~ErrorBase()
+{}
+
+/**
+ * @brief Retrieve the current error.
+ * Get the current error information associated with this sensor.
+ */
+Error& ErrorBase::GetError()
+{
+	return m_error;
+}
+
+const Error& ErrorBase::GetError() const
+{
+	return m_error;
+}
+
+/**
+ * @brief Clear the current error information associated with this sensor.
+ */
+void ErrorBase::ClearError() const
+{
+	m_error.Clear();
+}
+
+/**
+ * @brief Set error information associated with a C library call that set an error to the "errno" global variable.
+ *
+ * @param contextMessage A custom message from the code that set the error.
+ * @param filename Filename of the error source
+ * @param function Function of the error source
+ * @param lineNumber Line number of the error source
+ */
+void ErrorBase::SetErrnoError(const char *contextMessage,
+		const char* filename, const char* function, uint32_t lineNumber) const
+{
+	char err[256];
+	int errNo = errno;
+	if (errNo == 0)
+	{
+		sprintf(err, "OK: %s", contextMessage);
+	}
+	else
+	{
+		snprintf(err, 256, "%s (0x%08X): %s", strerror(errNo), errNo, contextMessage);
+	}
+
+	//  Set the current error information for this object.
+	m_error.Set(-1, err, filename, function, lineNumber, this);
+
+	// Update the global error if there is not one already set.
+	::std::unique_lock<Mutex> mutex(_globalErrorMutex);
+	if (_globalError.GetCode() == 0) {
+		_globalError.Clone(m_error);
+	}
+}
+
+/**
+ * @brief Set the current error information associated from the nivision Imaq API.
+ *
+ * @param success The return from the function
+ * @param contextMessage A custom message from the code that set the error.
+ * @param filename Filename of the error source
+ * @param function Function of the error source
+ * @param lineNumber Line number of the error source
+ */
+void ErrorBase::SetImaqError(int success, const char *contextMessage, const char* filename, const char* function, uint32_t lineNumber) const
+{
+	//  If there was an error
+	if (success <= 0) {
+		char err[256];
+		sprintf(err, "%i: %s", success, contextMessage);
+
+		//  Set the current error information for this object.
+		m_error.Set(success, err, filename, function, lineNumber, this);
+
+		// Update the global error if there is not one already set.
+		::std::unique_lock<Mutex> mutex(_globalErrorMutex);
+		if (_globalError.GetCode() == 0) {
+			_globalError.Clone(m_error);
+		}
+	}
+}
+
+/**
+ * @brief Set the current error information associated with this sensor.
+ *
+ * @param code The error code
+ * @param contextMessage A custom message from the code that set the error.
+ * @param filename Filename of the error source
+ * @param function Function of the error source
+ * @param lineNumber Line number of the error source
+ */
+void ErrorBase::SetError(Error::Code code, const char *contextMessage,
+		const char* filename, const char* function, uint32_t lineNumber) const
+{
+	//  If there was an error
+	if (code != 0) {
+		//  Set the current error information for this object.
+		m_error.Set(code, contextMessage, filename, function, lineNumber, this);
+
+		// Update the global error if there is not one already set.
+		::std::unique_lock<Mutex> mutex(_globalErrorMutex);
+		if (_globalError.GetCode() == 0) {
+			_globalError.Clone(m_error);
+		}
+	}
+}
+
+/**
+ * @brief Set the current error information associated with this sensor.
+ *
+ * @param errorMessage The error message from WPIErrors.h
+ * @param contextMessage A custom message from the code that set the error.
+ * @param filename Filename of the error source
+ * @param function Function of the error source
+ * @param lineNumber Line number of the error source
+ */
+void ErrorBase::SetWPIError(const char *errorMessage, Error::Code code , const char *contextMessage,
+		const char* filename, const char* function, uint32_t lineNumber) const
+{
+	char err[256];
+	sprintf(err, "%s: %s", errorMessage, contextMessage);
+
+	//  Set the current error information for this object.
+	m_error.Set(code, err, filename, function, lineNumber, this);
+
+	// Update the global error if there is not one already set.
+	::std::unique_lock<Mutex> mutex(_globalErrorMutex);
+	if (_globalError.GetCode() == 0) {
+		_globalError.Clone(m_error);
+	}
+}
+
+void ErrorBase::CloneError(ErrorBase *rhs) const
+{
+	m_error.Clone(rhs->GetError());
+}
+
+/**
+@brief Check if the current error code represents a fatal error.
+
+@return true if the current error is fatal.
+*/
+bool ErrorBase::StatusIsFatal() const
+{
+	return m_error.GetCode() < 0;
+}
+
+void ErrorBase::SetGlobalError(Error::Code code, const char *contextMessage,
+		const char* filename, const char* function, uint32_t lineNumber)
+{
+	//  If there was an error
+	if (code != 0) {
+		::std::unique_lock<Mutex> mutex(_globalErrorMutex);
+
+		//  Set the current error information for this object.
+		_globalError.Set(code, contextMessage, filename, function, lineNumber, NULL);
+	}
+}
+
+void ErrorBase::SetGlobalWPIError(const char *errorMessage, const char *contextMessage,
+        const char* filename, const char* function, uint32_t lineNumber)
+{
+	char err[256];
+	sprintf(err, "%s: %s", errorMessage, contextMessage);
+
+	::std::unique_lock<Mutex> mutex(_globalErrorMutex);
+	if (_globalError.GetCode() != 0) {
+		_globalError.Clear();
+	}
+	_globalError.Set(-1, err, filename, function, lineNumber, NULL);
+}
+
+/**
+  * Retrieve the current global error.
+*/
+Error& ErrorBase::GetGlobalError()
+{
+	::std::unique_lock<Mutex> mutex(_globalErrorMutex);
+	return _globalError;
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++/src/HLUsageReporting.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++/src/HLUsageReporting.cpp
new file mode 100644
index 0000000..c003298
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++/src/HLUsageReporting.cpp
@@ -0,0 +1,20 @@
+
+#include "HLUsageReporting.h"
+
+HLUsageReportingInterface* HLUsageReporting::impl = 0;
+
+void HLUsageReporting::SetImplementation(HLUsageReportingInterface* i) {
+    impl = i;
+}
+
+void HLUsageReporting::ReportScheduler() {
+    if (impl != 0) {
+        impl->ReportScheduler();
+    }
+}
+
+void HLUsageReporting::ReportSmartDashboard() {
+    if (impl != 0) {
+        impl->ReportSmartDashboard();
+    }
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++/src/Resource.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++/src/Resource.cpp
new file mode 100644
index 0000000..f582155
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++/src/Resource.cpp
@@ -0,0 +1,120 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "Resource.h"
+#include "WPIErrors.h"
+#include "ErrorBase.h"
+
+ReentrantMutex Resource::m_createLock;
+
+/**
+ * Allocate storage for a new instance of Resource.
+ * Allocate a bool array of values that will get initialized to indicate that no resources
+ * have been allocated yet. The indicies of the resources are [0 .. elements - 1].
+ */
+Resource::Resource(uint32_t elements)
+{
+	::std::unique_lock<ReentrantMutex> sync(m_createLock);
+	m_size = elements;
+	m_isAllocated = new bool[m_size];
+	for (uint32_t i=0; i < m_size; i++)
+	{
+		m_isAllocated[i] = false;
+	}
+}
+
+/**
+ * Factory method to create a Resource allocation-tracker *if* needed.
+ *
+ * @param r -- address of the caller's Resource pointer. If *r == NULL, this
+ *    will construct a Resource and make *r point to it. If *r != NULL, i.e.
+ *    the caller already has a Resource instance, this won't do anything.
+ * @param elements -- the number of elements for this Resource allocator to
+ *    track, that is, it will allocate resource numbers in the range
+ *    [0 .. elements - 1].
+ */
+/*static*/ void Resource::CreateResourceObject(Resource **r, uint32_t elements)
+{
+	::std::unique_lock<ReentrantMutex> sync(m_createLock);
+	if (*r == NULL)
+	{
+		*r = new Resource(elements);
+	}
+}
+
+/**
+ * Delete the allocated array or resources.
+ * This happens when the module is unloaded (provided it was statically allocated).
+ */
+Resource::~Resource()
+{
+	delete[] m_isAllocated;
+}
+
+/**
+ * Allocate a resource.
+ * When a resource is requested, mark it allocated. In this case, a free resource value
+ * within the range is located and returned after it is marked allocated.
+ */
+uint32_t Resource::Allocate(const char *resourceDesc)
+{
+	::std::unique_lock<ReentrantMutex> sync(m_allocateLock);
+	for (uint32_t i=0; i < m_size; i++)
+	{
+		if (!m_isAllocated[i])
+		{
+			m_isAllocated[i] = true;
+			return i;
+		}
+	}
+	wpi_setWPIErrorWithContext(NoAvailableResources, resourceDesc);
+	return ~0ul;
+}
+
+/**
+ * Allocate a specific resource value.
+ * The user requests a specific resource value, i.e. channel number and it is verified
+ * unallocated, then returned.
+ */
+uint32_t Resource::Allocate(uint32_t index, const char *resourceDesc)
+{
+	::std::unique_lock<ReentrantMutex> sync(m_allocateLock);
+	if (index >= m_size)
+	{
+		wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, resourceDesc);
+		return ~0ul;
+	}
+	if ( m_isAllocated[index] )
+	{
+		wpi_setWPIErrorWithContext(ResourceAlreadyAllocated, resourceDesc);
+		return ~0ul;
+	}
+	m_isAllocated[index] = true;
+	return index;
+}
+
+
+/**
+ * Free an allocated resource.
+ * After a resource is no longer needed, for example a destructor is called for a channel assignment
+ * class, Free will release the resource value so it can be reused somewhere else in the program.
+ */
+void Resource::Free(uint32_t index)
+{
+	::std::unique_lock<ReentrantMutex> sync(m_allocateLock);
+	if (index == ~0ul) return;
+	if (index >= m_size)
+	{
+		wpi_setWPIError(NotAllocated);
+		return;
+	}
+	if (!m_isAllocated[index])
+	{
+		wpi_setWPIError(NotAllocated);
+		return;
+	}
+	m_isAllocated[index] = false;
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++/src/RobotState.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++/src/RobotState.cpp
new file mode 100644
index 0000000..747000a
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++/src/RobotState.cpp
@@ -0,0 +1,42 @@
+#include "RobotState.h"
+
+RobotStateInterface* RobotState::impl = 0;
+
+void RobotState::SetImplementation(RobotStateInterface* i) {
+    impl = i;
+}
+
+bool RobotState::IsDisabled() {
+    if (impl != nullptr) {
+        return impl->IsDisabled();
+    }
+    return true;
+}
+
+bool RobotState::IsEnabled() {
+    if (impl != nullptr) {
+        return impl->IsEnabled();
+    }
+    return false;
+}
+
+bool RobotState::IsOperatorControl() {
+    if (impl != nullptr) {
+        return impl->IsOperatorControl();
+    }
+    return true;
+}
+
+bool RobotState::IsAutonomous() {
+    if (impl != nullptr) {
+        return impl->IsAutonomous();
+    }
+    return false;
+}
+
+bool RobotState::IsTest() {
+    if (impl != nullptr) {
+        return impl->IsTest();
+    }
+    return false;
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/CMakeLists.txt b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/CMakeLists.txt
new file mode 100644
index 0000000..f73522c
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/CMakeLists.txt
@@ -0,0 +1,13 @@
+cmake_minimum_required(VERSION 2.8)
+project(WPILibC++Devices)
+
+file(GLOB_RECURSE SRC_FILES src/*.cpp)
+include_directories(include/ ${WPILIB_INCLUDES} ${HAL_API_INCLUDES} ${NWT_API_INCLUDES})
+add_library(wpilib_nonshared STATIC ${SRC_FILES} ${COM_SRC_FILES})
+target_link_libraries(wpilib_nonshared HALAthena NetworkTables ${NI_LIBS})
+INSTALL(TARGETS wpilib_nonshared ARCHIVE DESTINATION lib COMPONENT lib)
+INSTALL(DIRECTORY include DESTINATION ${CMAKE_INSTALL_PREFIX} COMPONENT headers)
+# lib/ c m gcc_s ld-linux
+# usr/lib stdc++
+# ni_emb
+# HAL NWT
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/ADXL345_I2C.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/ADXL345_I2C.h
new file mode 100644
index 0000000..5cff335
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/ADXL345_I2C.h
@@ -0,0 +1,53 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "interfaces/Accelerometer.h"
+#include "I2C.h"
+
+/**
+ * ADXL345 Accelerometer on I2C.
+ *
+ * This class allows access to a Analog Devices ADXL345 3-axis accelerometer on an I2C bus.
+ * This class assumes the default (not alternate) sensor address of 0x1D (7-bit address).
+ */
+class ADXL345_I2C : public Accelerometer, public I2C
+{
+protected:
+	static const uint8_t kAddress = 0x1D;
+	static const uint8_t kPowerCtlRegister = 0x2D;
+	static const uint8_t kDataFormatRegister = 0x31;
+	static const uint8_t kDataRegister = 0x32;
+	static constexpr double kGsPerLSB = 0.00390625;
+	enum PowerCtlFields {kPowerCtl_Link=0x20, kPowerCtl_AutoSleep=0x10, kPowerCtl_Measure=0x08, kPowerCtl_Sleep=0x04};
+	enum DataFormatFields {kDataFormat_SelfTest=0x80, kDataFormat_SPI=0x40, kDataFormat_IntInvert=0x20,
+		kDataFormat_FullRes=0x08, kDataFormat_Justify=0x04};
+
+public:
+	enum Axes {kAxis_X=0x00, kAxis_Y=0x02, kAxis_Z=0x04};
+	struct AllAxes
+	{
+		double XAxis;
+		double YAxis;
+		double ZAxis;
+	};
+
+public:
+	explicit ADXL345_I2C(Port port, Range range = kRange_2G);
+	virtual ~ADXL345_I2C();
+
+	// Accelerometer interface
+	virtual void SetRange(Range range);
+	virtual double GetX();
+	virtual double GetY();
+	virtual double GetZ();
+
+	virtual double GetAcceleration(Axes axis);
+	virtual AllAxes GetAccelerations();
+
+protected:
+	//I2C* m_i2c;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/ADXL345_SPI.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/ADXL345_SPI.h
new file mode 100644
index 0000000..4cfc64e
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/ADXL345_SPI.h
@@ -0,0 +1,60 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "interfaces/Accelerometer.h"
+#include "SensorBase.h"
+#include "SPI.h"
+
+class DigitalInput;
+class DigitalOutput;
+
+/**
+ * ADXL345 Accelerometer on SPI.
+ *
+ * This class allows access to an Analog Devices ADXL345 3-axis accelerometer via SPI.
+ * This class assumes the sensor is wired in 4-wire SPI mode.
+ */
+class ADXL345_SPI : public Accelerometer, public SensorBase
+{
+protected:
+	static const uint8_t kPowerCtlRegister = 0x2D;
+	static const uint8_t kDataFormatRegister = 0x31;
+	static const uint8_t kDataRegister = 0x32;
+	static constexpr double kGsPerLSB = 0.00390625;
+	enum SPIAddressFields {kAddress_Read=0x80, kAddress_MultiByte=0x40};
+	enum PowerCtlFields {kPowerCtl_Link=0x20, kPowerCtl_AutoSleep=0x10, kPowerCtl_Measure=0x08, kPowerCtl_Sleep=0x04};
+	enum DataFormatFields {kDataFormat_SelfTest=0x80, kDataFormat_SPI=0x40, kDataFormat_IntInvert=0x20,
+		kDataFormat_FullRes=0x08, kDataFormat_Justify=0x04};
+
+public:
+	enum Axes {kAxis_X=0x00, kAxis_Y=0x02, kAxis_Z=0x04};
+	struct AllAxes
+	{
+		double XAxis;
+		double YAxis;
+		double ZAxis;
+	};
+
+public:
+	ADXL345_SPI(SPI::Port port, Range range=kRange_2G);
+	virtual ~ADXL345_SPI();
+
+	// Accelerometer interface
+	virtual void SetRange(Range range);
+	virtual double GetX();
+	virtual double GetY();
+	virtual double GetZ();
+
+	virtual double GetAcceleration(Axes axis);
+	virtual AllAxes GetAccelerations();
+
+protected:
+	void Init(Range range);
+
+	SPI* m_spi;
+	SPI::Port m_port;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/AnalogAccelerometer.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/AnalogAccelerometer.h
new file mode 100644
index 0000000..8d7a3f0
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/AnalogAccelerometer.h
@@ -0,0 +1,36 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "AnalogInput.h"
+#include "SensorBase.h"
+#include "PIDSource.h"
+
+/**
+ * Handle operation of an analog accelerometer.
+ * The accelerometer reads acceleration directly through the sensor. Many sensors have
+ * multiple axis and can be treated as multiple devices. Each is calibrated by finding
+ * the center value over a period of time.
+ */
+class AnalogAccelerometer : public SensorBase, public PIDSource {
+public:
+	explicit AnalogAccelerometer(int32_t channel);
+	explicit AnalogAccelerometer(AnalogInput *channel);
+	virtual ~AnalogAccelerometer();
+
+	float GetAcceleration();
+	void SetSensitivity(float sensitivity);
+	void SetZero(float zero);
+	double PIDGet();
+
+private:
+	void InitAccelerometer();
+
+	AnalogInput *m_AnalogInput;
+	float m_voltsPerG;
+	float m_zeroGVoltage;
+	bool m_allocatedChannel;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/AnalogInput.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/AnalogInput.h
new file mode 100644
index 0000000..8e10808
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/AnalogInput.h
@@ -0,0 +1,68 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "HAL/HAL.hpp"
+#include "SensorBase.h"
+#include "PIDSource.h"
+
+/**
+ * Analog input class.
+ *
+ * Connected to each analog channel is an averaging and oversampling engine.  This engine accumulates
+ * the specified ( by SetAverageBits() and SetOversampleBits() ) number of samples before returning a new
+ * value.  This is not a sliding window average.  The only difference between the oversampled samples and
+ * the averaged samples is that the oversampled samples are simply accumulated effectively increasing the
+ * resolution, while the averaged samples are divided by the number of samples to retain the resolution,
+ * but get more stable values.
+ */
+class AnalogInput : public SensorBase, public PIDSource
+{
+public:
+	static const uint8_t kAccumulatorModuleNumber = 1;
+	static const uint32_t kAccumulatorNumChannels = 2;
+	static const uint32_t kAccumulatorChannels[kAccumulatorNumChannels];
+
+	explicit AnalogInput(uint32_t channel);
+	virtual ~AnalogInput();
+
+	int16_t GetValue();
+	int32_t GetAverageValue();
+
+	float GetVoltage();
+	float GetAverageVoltage();
+
+	uint32_t GetChannel();
+
+	void SetAverageBits(uint32_t bits);
+	uint32_t GetAverageBits();
+	void SetOversampleBits(uint32_t bits);
+	uint32_t GetOversampleBits();
+
+	uint32_t GetLSBWeight();
+	int32_t GetOffset();
+
+	bool IsAccumulatorChannel();
+	void InitAccumulator();
+	void SetAccumulatorInitialValue(int64_t value);
+	void ResetAccumulator();
+	void SetAccumulatorCenter(int32_t center);
+	void SetAccumulatorDeadband(int32_t deadband);
+	int64_t GetAccumulatorValue();
+	uint32_t GetAccumulatorCount();
+	void GetAccumulatorOutput(int64_t *value, uint32_t *count);
+
+	static void SetSampleRate(float samplesPerSecond);
+	static float GetSampleRate();
+
+	double PIDGet();
+
+private:
+	void InitAnalogInput(uint32_t channel);
+	uint32_t m_channel;
+	void* m_port;
+	int64_t m_accumulatorOffset;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/AnalogOutput.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/AnalogOutput.h
new file mode 100644
index 0000000..14abcb2
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/AnalogOutput.h
@@ -0,0 +1,29 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "HAL/HAL.hpp"
+#include "SensorBase.h"
+
+/**
+ * MXP analog output class.
+ */
+class AnalogOutput : public SensorBase
+{
+public:
+    explicit AnalogOutput(uint32_t channel);
+    virtual ~AnalogOutput();
+
+    void SetVoltage(float voltage);
+    float GetVoltage();
+
+protected:
+    void InitAnalogOutput(uint32_t channel);
+    uint32_t m_channel;
+    void* m_port;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/AnalogPotentiometer.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/AnalogPotentiometer.h
new file mode 100644
index 0000000..8b8cd76
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/AnalogPotentiometer.h
@@ -0,0 +1,64 @@
+
+#include "AnalogInput.h"
+#include "interfaces/Potentiometer.h"
+
+/**
+ * Class for reading analog potentiometers. Analog potentiometers read
+ * in an analog voltage that corresponds to a position. The position is
+ * in whichever units you choose, by way of the scaling and offset
+ * constants passed to the constructor.
+ *
+ * @author Alex Henning
+ * @author Colby Skeggs (rail voltage)
+ */
+class AnalogPotentiometer : public Potentiometer {
+public:
+    /**
+     * AnalogPotentiometer constructor.
+     *
+     * Use the fullRange and offset values so that the output produces
+     * meaningful values. I.E: you have a 270 degree potentiometer and
+     * you want the output to be degrees with the halfway point as 0
+     * degrees. The fullRange value is 270.0(degrees) and the offset is
+     * -135.0 since the halfway point after scaling is 135 degrees.
+     *
+     * This will calculate the result from the fullRange times the
+     * fraction of the supply voltage, plus the offset.
+     *
+     * @param channel The analog channel this potentiometer is plugged into.
+     * @param fullRange The scaling to multiply the voltage by to get a meaningful unit.
+     * @param offset The offset to add to the scaled value for controlling the zero value
+     */
+    explicit AnalogPotentiometer(int channel, double fullRange = 1.0, double offset = 0.0);
+
+    explicit AnalogPotentiometer(AnalogInput *input, double fullRange = 1.0, double offset = 0.0);
+
+    explicit AnalogPotentiometer(AnalogInput &input, double fullRange = 1.0, double offset = 0.0);
+
+    virtual ~AnalogPotentiometer();
+
+    /**
+     * Get the current reading of the potentiomer.
+     *
+     * @return The current position of the potentiometer.
+     */
+    virtual double Get();
+
+
+    /**
+     * Implement the PIDSource interface.
+     *
+     * @return The current reading.
+     */
+    virtual double PIDGet();
+
+private:
+    double m_fullRange, m_offset;
+    AnalogInput* m_analog_input;
+    bool m_init_analog_input;
+
+    /**
+     * Common initialization code called by all constructors.
+     */
+    void initPot(AnalogInput *input, double fullRange, double offset);
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/AnalogTrigger.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/AnalogTrigger.h
new file mode 100644
index 0000000..9b18a33
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/AnalogTrigger.h
@@ -0,0 +1,36 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "HAL/HAL.hpp"
+#include "AnalogTriggerOutput.h"
+#include "SensorBase.h"
+
+class AnalogInput;
+
+class AnalogTrigger : public SensorBase
+{
+	friend class AnalogTriggerOutput;
+public:
+	explicit AnalogTrigger(int32_t channel);
+	explicit AnalogTrigger(AnalogInput *channel);
+	virtual ~AnalogTrigger();
+
+	void SetLimitsVoltage(float lower, float upper);
+	void SetLimitsRaw(int32_t lower, int32_t upper);
+	void SetAveraged(bool useAveragedValue);
+	void SetFiltered(bool useFilteredValue);
+	uint32_t GetIndex();
+	bool GetInWindow();
+	bool GetTriggerState();
+	AnalogTriggerOutput *CreateOutput(AnalogTriggerType type);
+
+private:
+	void InitTrigger(uint32_t channel);
+
+	uint8_t m_index;
+	void* m_trigger;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/AnalogTriggerOutput.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/AnalogTriggerOutput.h
new file mode 100644
index 0000000..8ab701e
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/AnalogTriggerOutput.h
@@ -0,0 +1,57 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "DigitalSource.h"
+
+class AnalogTrigger;
+
+/**
+ * Class to represent a specific output from an analog trigger.
+ * This class is used to get the current output value and also as a DigitalSource
+ * to provide routing of an output to digital subsystems on the FPGA such as
+ * Counter, Encoder, and Interrupt.
+ *
+ * The TriggerState output indicates the primary output value of the trigger.  If the analog
+ * signal is less than the lower limit, the output is false.  If the analog value is greater
+ * than the upper limit, then the output is true.  If the analog value is in between, then
+ * the trigger output state maintains its most recent value.
+ *
+ * The InWindow output indicates whether or not the analog signal is inside the range defined
+ * by the limits.
+ *
+ * The RisingPulse and FallingPulse outputs detect an instantaneous transition from above the
+ * upper limit to below the lower limit, and vise versa.  These pulses represent a rollover
+ * condition of a sensor and can be routed to an up / down couter or to interrupts.  Because
+ * the outputs generate a pulse, they cannot be read directly.  To help ensure that a rollover
+ * condition is not missed, there is an average rejection filter available that operates on the
+ * upper 8 bits of a 12 bit number and selects the nearest outlyer of 3 samples.  This will reject
+ * a sample that is (due to averaging or sampling) errantly between the two limits.  This filter
+ * will fail if more than one sample in a row is errantly in between the two limits.  You may see
+ * this problem if attempting to use this feature with a mechanical rollover sensor, such as a
+ * 360 degree no-stop potentiometer without signal conditioning, because the rollover transition
+ * is not sharp / clean enough.  Using the averaging engine may help with this, but rotational speeds of
+ * the sensor will then be limited.
+ */
+class AnalogTriggerOutput : public DigitalSource
+{
+	friend class AnalogTrigger;
+public:
+
+	virtual ~AnalogTriggerOutput();
+	virtual bool Get();
+
+	// DigitalSource interface
+	virtual uint32_t GetChannelForRouting();
+	virtual uint32_t GetModuleForRouting();
+	virtual bool GetAnalogTriggerForRouting();
+protected:
+	AnalogTriggerOutput(AnalogTrigger *trigger, AnalogTriggerType outputType);
+
+private:
+	AnalogTrigger *m_trigger;
+	AnalogTriggerType m_outputType;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/BuiltInAccelerometer.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/BuiltInAccelerometer.h
new file mode 100644
index 0000000..563df99
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/BuiltInAccelerometer.h
@@ -0,0 +1,27 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "interfaces/Accelerometer.h"
+#include "SensorBase.h"
+
+/**
+ * Built-in accelerometer.
+ *
+ * This class allows access to the RoboRIO's internal accelerometer.
+ */
+class BuiltInAccelerometer : public Accelerometer, public SensorBase
+{
+public:
+	BuiltInAccelerometer(Range range = kRange_8G);
+        virtual ~BuiltInAccelerometer();
+
+	// Accelerometer interface
+	virtual void SetRange(Range range);
+	virtual double GetX();
+	virtual double GetY();
+	virtual double GetZ();
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/CAN/can_proto.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/CAN/can_proto.h
new file mode 100644
index 0000000..5113b02
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/CAN/can_proto.h
@@ -0,0 +1,428 @@
+//*****************************************************************************
+//
+// can_proto.h - Definitions for the CAN protocol used to communicate with the
+//               BDC motor controller.
+//
+// Copyright (c) 2008 Texas Instruments Incorporated.  All rights reserved.
+// TI Information - Selective Disclosure
+//
+//*****************************************************************************
+
+#ifndef __CAN_PROTO_H__
+#define __CAN_PROTO_H__
+
+//*****************************************************************************
+//
+// The masks of the fields that are used in the message identifier.
+//
+//*****************************************************************************
+#define CAN_MSGID_FULL_M        0x1fffffff
+#define CAN_MSGID_DEVNO_M       0x0000003f
+#define CAN_MSGID_API_M         0x0000ffc0
+#define CAN_MSGID_MFR_M         0x00ff0000
+#define CAN_MSGID_DTYPE_M       0x1f000000
+#define CAN_MSGID_DEVNO_S       0
+#define CAN_MSGID_API_S         6
+#define CAN_MSGID_MFR_S         16
+#define CAN_MSGID_DTYPE_S       24
+
+//*****************************************************************************
+//
+// The Reserved device number values in the Message Id.
+//
+//*****************************************************************************
+#define CAN_MSGID_DEVNO_BCAST   0x00000000
+
+//*****************************************************************************
+//
+// The Reserved system control API numbers in the Message Id.
+//
+//*****************************************************************************
+#define CAN_MSGID_API_SYSHALT   0x00000000
+#define CAN_MSGID_API_SYSRST    0x00000040
+#define CAN_MSGID_API_DEVASSIGN 0x00000080
+#define CAN_MSGID_API_DEVQUERY  0x000000c0
+#define CAN_MSGID_API_HEARTBEAT 0x00000140
+#define CAN_MSGID_API_SYNC      0x00000180
+#define CAN_MSGID_API_UPDATE    0x000001c0
+#define CAN_MSGID_API_FIRMVER   0x00000200
+#define CAN_MSGID_API_ENUMERATE 0x00000240
+#define CAN_MSGID_API_SYSRESUME 0x00000280
+
+//*****************************************************************************
+//
+// The 32 bit values associated with the CAN_MSGID_API_STATUS request.
+//
+//*****************************************************************************
+#define CAN_STATUS_CODE_M       0x0000ffff
+#define CAN_STATUS_MFG_M        0x00ff0000
+#define CAN_STATUS_DTYPE_M      0x1f000000
+#define CAN_STATUS_CODE_S       0
+#define CAN_STATUS_MFG_S        16
+#define CAN_STATUS_DTYPE_S      24
+
+//*****************************************************************************
+//
+// The Reserved manufacturer identifiers in the Message Id.
+//
+//*****************************************************************************
+#define CAN_MSGID_MFR_NI        0x00010000
+#define CAN_MSGID_MFR_LM        0x00020000
+#define CAN_MSGID_MFR_DEKA      0x00030000
+
+//*****************************************************************************
+//
+// The Reserved device type identifiers in the Message Id.
+//
+//*****************************************************************************
+#define CAN_MSGID_DTYPE_BCAST   0x00000000
+#define CAN_MSGID_DTYPE_ROBOT   0x01000000
+#define CAN_MSGID_DTYPE_MOTOR   0x02000000
+#define CAN_MSGID_DTYPE_RELAY   0x03000000
+#define CAN_MSGID_DTYPE_GYRO    0x04000000
+#define CAN_MSGID_DTYPE_ACCEL   0x05000000
+#define CAN_MSGID_DTYPE_USONIC  0x06000000
+#define CAN_MSGID_DTYPE_GEART   0x07000000
+#define CAN_MSGID_DTYPE_UPDATE  0x1f000000
+
+//*****************************************************************************
+//
+// LM Motor Control API Classes API Class and ID masks.
+//
+//*****************************************************************************
+#define CAN_MSGID_API_CLASS_M   0x0000fc00
+#define CAN_MSGID_API_ID_M      0x000003c0
+
+//*****************************************************************************
+//
+// LM Motor Control API Classes in the Message Id for non-broadcast.
+// These are the upper 6 bits of the API field, the lower 4 bits determine
+// the APIId.
+//
+//*****************************************************************************
+#define CAN_API_MC_VOLTAGE      0x00000000
+#define CAN_API_MC_SPD          0x00000400
+#define CAN_API_MC_VCOMP        0x00000800
+#define CAN_API_MC_POS          0x00000c00
+#define CAN_API_MC_ICTRL        0x00001000
+#define CAN_API_MC_STATUS       0x00001400
+#define CAN_API_MC_PSTAT        0x00001800
+#define CAN_API_MC_CFG          0x00001c00
+#define CAN_API_MC_ACK          0x00002000
+
+//*****************************************************************************
+//
+// The Stellaris Motor Class Control Voltage API definitions.
+//
+//*****************************************************************************
+#define LM_API_VOLT             (CAN_MSGID_MFR_LM | CAN_MSGID_DTYPE_MOTOR |   \
+                                 CAN_API_MC_VOLTAGE)
+#define LM_API_VOLT_EN          (LM_API_VOLT | (0 << CAN_MSGID_API_S))
+#define LM_API_VOLT_DIS         (LM_API_VOLT | (1 << CAN_MSGID_API_S))
+#define LM_API_VOLT_SET         (LM_API_VOLT | (2 << CAN_MSGID_API_S))
+#define LM_API_VOLT_SET_RAMP    (LM_API_VOLT | (3 << CAN_MSGID_API_S))
+//##### FIRST BEGIN #####
+#define LM_API_VOLT_T_EN        (LM_API_VOLT | (4 << CAN_MSGID_API_S))
+#define LM_API_VOLT_T_SET       (LM_API_VOLT | (5 << CAN_MSGID_API_S))
+#define LM_API_VOLT_T_SET_NO_ACK                                              \
+                                (LM_API_VOLT | (7 << CAN_MSGID_API_S))
+//##### FIRST END #####
+#define LM_API_VOLT_SET_NO_ACK  (LM_API_VOLT | (8 << CAN_MSGID_API_S))
+
+//*****************************************************************************
+//
+// The Stellaris Motor Class Control API definitions for LM_API_VOLT_SET_RAMP.
+//
+//*****************************************************************************
+#define LM_API_VOLT_RAMP_DIS    0
+
+//*****************************************************************************
+//
+// The Stellaris Motor Class Control API definitions for CAN_MSGID_API_SYNC.
+//
+//*****************************************************************************
+#define LM_API_SYNC_PEND_NOW    0
+
+//*****************************************************************************
+//
+// The Stellaris Motor Class Speed Control API definitions.
+//
+//*****************************************************************************
+#define LM_API_SPD              (CAN_MSGID_MFR_LM | CAN_MSGID_DTYPE_MOTOR |   \
+                                 CAN_API_MC_SPD)
+#define LM_API_SPD_EN           (LM_API_SPD | (0 << CAN_MSGID_API_S))
+#define LM_API_SPD_DIS          (LM_API_SPD | (1 << CAN_MSGID_API_S))
+#define LM_API_SPD_SET          (LM_API_SPD | (2 << CAN_MSGID_API_S))
+#define LM_API_SPD_PC           (LM_API_SPD | (3 << CAN_MSGID_API_S))
+#define LM_API_SPD_IC           (LM_API_SPD | (4 << CAN_MSGID_API_S))
+#define LM_API_SPD_DC           (LM_API_SPD | (5 << CAN_MSGID_API_S))
+#define LM_API_SPD_REF          (LM_API_SPD | (6 << CAN_MSGID_API_S))
+//##### FIRST BEGIN #####
+#define LM_API_SPD_T_EN         (LM_API_SPD | (7 << CAN_MSGID_API_S))
+#define LM_API_SPD_T_SET        (LM_API_SPD | (8 << CAN_MSGID_API_S))
+#define LM_API_SPD_T_SET_NO_ACK (LM_API_SPD | (10 << CAN_MSGID_API_S))
+//##### FIRST END #####
+#define LM_API_SPD_SET_NO_ACK   (LM_API_SPD | (11 << CAN_MSGID_API_S))
+
+//*****************************************************************************
+//
+// The Stellaris Motor Control Voltage Compensation Control API definitions.
+//
+//*****************************************************************************
+#define LM_API_VCOMP            (CAN_MSGID_MFR_LM | CAN_MSGID_DTYPE_MOTOR |   \
+                                 CAN_API_MC_VCOMP)
+#define LM_API_VCOMP_EN         (LM_API_VCOMP | (0 << CAN_MSGID_API_S))
+#define LM_API_VCOMP_DIS        (LM_API_VCOMP | (1 << CAN_MSGID_API_S))
+#define LM_API_VCOMP_SET        (LM_API_VCOMP | (2 << CAN_MSGID_API_S))
+#define LM_API_VCOMP_IN_RAMP    (LM_API_VCOMP | (3 << CAN_MSGID_API_S))
+#define LM_API_VCOMP_COMP_RAMP  (LM_API_VCOMP | (4 << CAN_MSGID_API_S))
+//##### FIRST BEGIN #####
+#define LM_API_VCOMP_T_EN       (LM_API_VCOMP | (5 << CAN_MSGID_API_S))
+#define LM_API_VCOMP_T_SET      (LM_API_VCOMP | (6 << CAN_MSGID_API_S))
+#define LM_API_VCOMP_T_SET_NO_ACK                                             \
+                                (LM_API_VCOMP | (8 << CAN_MSGID_API_S))
+//##### FIRST END #####
+#define LM_API_VCOMP_SET_NO_ACK (LM_API_VCOMP | (9 << CAN_MSGID_API_S))
+
+//*****************************************************************************
+//
+// The Stellaris Motor Class Position Control API definitions.
+//
+//*****************************************************************************
+#define LM_API_POS              (CAN_MSGID_MFR_LM | CAN_MSGID_DTYPE_MOTOR |   \
+                                 CAN_API_MC_POS)
+#define LM_API_POS_EN           (LM_API_POS | (0 << CAN_MSGID_API_S))
+#define LM_API_POS_DIS          (LM_API_POS | (1 << CAN_MSGID_API_S))
+#define LM_API_POS_SET          (LM_API_POS | (2 << CAN_MSGID_API_S))
+#define LM_API_POS_PC           (LM_API_POS | (3 << CAN_MSGID_API_S))
+#define LM_API_POS_IC           (LM_API_POS | (4 << CAN_MSGID_API_S))
+#define LM_API_POS_DC           (LM_API_POS | (5 << CAN_MSGID_API_S))
+#define LM_API_POS_REF          (LM_API_POS | (6 << CAN_MSGID_API_S))
+//##### FIRST BEGIN #####
+#define LM_API_POS_T_EN         (LM_API_POS | (7 << CAN_MSGID_API_S))
+#define LM_API_POS_T_SET        (LM_API_POS | (8 << CAN_MSGID_API_S))
+#define LM_API_POS_T_SET_NO_ACK (LM_API_POS | (10 << CAN_MSGID_API_S))
+//##### FIRST END #####
+#define LM_API_POS_SET_NO_ACK   (LM_API_POS | (11 << CAN_MSGID_API_S))
+
+//*****************************************************************************
+//
+// The Stellaris Motor Class Current Control API definitions.
+//
+//*****************************************************************************
+#define LM_API_ICTRL            (CAN_MSGID_MFR_LM | CAN_MSGID_DTYPE_MOTOR |   \
+                                 CAN_API_MC_ICTRL)
+#define LM_API_ICTRL_EN         (LM_API_ICTRL | (0 << CAN_MSGID_API_S))
+#define LM_API_ICTRL_DIS        (LM_API_ICTRL | (1 << CAN_MSGID_API_S))
+#define LM_API_ICTRL_SET        (LM_API_ICTRL | (2 << CAN_MSGID_API_S))
+#define LM_API_ICTRL_PC         (LM_API_ICTRL | (3 << CAN_MSGID_API_S))
+#define LM_API_ICTRL_IC         (LM_API_ICTRL | (4 << CAN_MSGID_API_S))
+#define LM_API_ICTRL_DC         (LM_API_ICTRL | (5 << CAN_MSGID_API_S))
+//##### FIRST BEGIN #####
+#define LM_API_ICTRL_T_EN       (LM_API_ICTRL | (6 << CAN_MSGID_API_S))
+#define LM_API_ICTRL_T_SET      (LM_API_ICTRL | (7 << CAN_MSGID_API_S))
+#define LM_API_ICTRL_T_SET_NO_ACK                                             \
+                                (LM_API_ICTRL | (9 << CAN_MSGID_API_S))
+//##### FIRST END #####
+#define LM_API_ICTRL_SET_NO_ACK (LM_API_ICTRL | (10 << CAN_MSGID_API_S))
+
+//*****************************************************************************
+//
+// The Stellaris Motor Class Firmware Update API definitions.
+//
+//*****************************************************************************
+#define LM_API_UPD              (CAN_MSGID_MFR_LM | CAN_MSGID_DTYPE_UPDATE)
+#define LM_API_UPD_PING         (LM_API_UPD | (0 << CAN_MSGID_API_S))
+#define LM_API_UPD_DOWNLOAD     (LM_API_UPD | (1 << CAN_MSGID_API_S))
+#define LM_API_UPD_SEND_DATA    (LM_API_UPD | (2 << CAN_MSGID_API_S))
+#define LM_API_UPD_RESET        (LM_API_UPD | (3 << CAN_MSGID_API_S))
+#define LM_API_UPD_ACK          (LM_API_UPD | (4 << CAN_MSGID_API_S))
+#define LM_API_HWVER            (LM_API_UPD | (5 << CAN_MSGID_API_S))
+#define LM_API_UPD_REQUEST      (LM_API_UPD | (6 << CAN_MSGID_API_S))
+//##### FIRST BEGIN #####
+#define LM_API_UNTRUST_EN       (LM_API_UPD | (11 << CAN_MSGID_API_S))
+#define LM_API_TRUST_EN         (LM_API_UPD | (12 << CAN_MSGID_API_S))
+#define LM_API_TRUST_HEARTBEAT  (LM_API_UPD | (13 << CAN_MSGID_API_S))
+//##### FIRST END #####
+
+//*****************************************************************************
+//
+// The Stellaris Motor Class Status API definitions.
+//
+//*****************************************************************************
+#define LM_API_STATUS           (CAN_MSGID_MFR_LM | CAN_MSGID_DTYPE_MOTOR |   \
+                                 CAN_API_MC_STATUS)
+#define LM_API_STATUS_VOLTOUT   (LM_API_STATUS | (0 << CAN_MSGID_API_S))
+#define LM_API_STATUS_VOLTBUS   (LM_API_STATUS | (1 << CAN_MSGID_API_S))
+#define LM_API_STATUS_CURRENT   (LM_API_STATUS | (2 << CAN_MSGID_API_S))
+#define LM_API_STATUS_TEMP      (LM_API_STATUS | (3 << CAN_MSGID_API_S))
+#define LM_API_STATUS_POS       (LM_API_STATUS | (4 << CAN_MSGID_API_S))
+#define LM_API_STATUS_SPD       (LM_API_STATUS | (5 << CAN_MSGID_API_S))
+#define LM_API_STATUS_LIMIT     (LM_API_STATUS | (6 << CAN_MSGID_API_S))
+#define LM_API_STATUS_FAULT     (LM_API_STATUS | (7 << CAN_MSGID_API_S))
+#define LM_API_STATUS_POWER     (LM_API_STATUS | (8 << CAN_MSGID_API_S))
+#define LM_API_STATUS_CMODE     (LM_API_STATUS | (9 << CAN_MSGID_API_S))
+#define LM_API_STATUS_VOUT      (LM_API_STATUS | (10 << CAN_MSGID_API_S))
+#define LM_API_STATUS_STKY_FLT  (LM_API_STATUS | (11 << CAN_MSGID_API_S))
+#define LM_API_STATUS_FLT_COUNT (LM_API_STATUS | (12 << CAN_MSGID_API_S))
+
+//*****************************************************************************
+//
+// These definitions are used with the byte that is returned from
+// the status request for LM_API_STATUS_LIMIT.
+//
+//*****************************************************************************
+#define LM_STATUS_LIMIT_FWD     0x01
+#define LM_STATUS_LIMIT_REV     0x02
+#define LM_STATUS_LIMIT_SFWD    0x04
+#define LM_STATUS_LIMIT_SREV    0x08
+#define LM_STATUS_LIMIT_STKY_FWD                                              \
+                                0x10
+#define LM_STATUS_LIMIT_STKY_REV                                              \
+                                0x20
+#define LM_STATUS_LIMIT_STKY_SFWD                                             \
+                                0x40
+#define LM_STATUS_LIMIT_STKY_SREV                                             \
+                                0x80
+
+//*****************************************************************************
+//
+// LM Motor Control status codes returned due to the CAN_STATUS_CODE_M field.
+//
+//*****************************************************************************
+#define LM_STATUS_FAULT_ILIMIT  0x01
+#define LM_STATUS_FAULT_TLIMIT  0x02
+#define LM_STATUS_FAULT_VLIMIT  0x04
+
+//*****************************************************************************
+//
+// The Stellaris Motor Class Configuration API definitions.
+//
+//*****************************************************************************
+#define LM_API_CFG              (CAN_MSGID_MFR_LM | CAN_MSGID_DTYPE_MOTOR |   \
+                                 CAN_API_MC_CFG)
+#define LM_API_CFG_NUM_BRUSHES  (LM_API_CFG | (0 << CAN_MSGID_API_S))
+#define LM_API_CFG_ENC_LINES    (LM_API_CFG | (1 << CAN_MSGID_API_S))
+#define LM_API_CFG_POT_TURNS    (LM_API_CFG | (2 << CAN_MSGID_API_S))
+#define LM_API_CFG_BRAKE_COAST  (LM_API_CFG | (3 << CAN_MSGID_API_S))
+#define LM_API_CFG_LIMIT_MODE   (LM_API_CFG | (4 << CAN_MSGID_API_S))
+#define LM_API_CFG_LIMIT_FWD    (LM_API_CFG | (5 << CAN_MSGID_API_S))
+#define LM_API_CFG_LIMIT_REV    (LM_API_CFG | (6 << CAN_MSGID_API_S))
+#define LM_API_CFG_MAX_VOUT     (LM_API_CFG | (7 << CAN_MSGID_API_S))
+#define LM_API_CFG_FAULT_TIME   (LM_API_CFG | (8 << CAN_MSGID_API_S))
+
+//*****************************************************************************
+//
+// The Stellaris ACK API definition.
+//
+//*****************************************************************************
+#define LM_API_ACK              (CAN_MSGID_MFR_LM | CAN_MSGID_DTYPE_MOTOR |   \
+                                 CAN_API_MC_ACK)
+
+//*****************************************************************************
+//
+// The 8 bit values that can be returned by a call to LM_API_STATUS_HWVER.
+//
+//*****************************************************************************
+#define LM_HWVER_UNKNOWN        0x00
+#define LM_HWVER_JAG_1_0        0x01
+#define LM_HWVER_JAG_2_0        0x02
+
+//*****************************************************************************
+//
+// The 8 bit values that can be returned by a call to LM_API_STATUS_CMODE.
+//
+//*****************************************************************************
+#define LM_STATUS_CMODE_VOLT    0x00
+#define LM_STATUS_CMODE_CURRENT 0x01
+#define LM_STATUS_CMODE_SPEED   0x02
+#define LM_STATUS_CMODE_POS     0x03
+#define LM_STATUS_CMODE_VCOMP   0x04
+
+//*****************************************************************************
+//
+// The values that can specified as the position or speed reference.  Not all
+// values are valid for each reference; if an invalid reference is set, then
+// none will be selected.
+//
+//*****************************************************************************
+#define LM_REF_ENCODER          0x00
+#define LM_REF_POT              0x01
+#define LM_REF_INV_ENCODER      0x02
+#define LM_REF_QUAD_ENCODER     0x03
+#define LM_REF_NONE             0xff
+
+//*****************************************************************************
+//
+// The flags that are used to indicate the currently active fault sources.
+//
+//*****************************************************************************
+#define LM_FAULT_CURRENT        0x01
+#define LM_FAULT_TEMP           0x02
+#define LM_FAULT_VBUS           0x04
+#define LM_FAULT_GATE_DRIVE     0x08
+#define LM_FAULT_COMM           0x10
+
+//*****************************************************************************
+//
+// The Stellaris Motor Class Periodic Status API definitions.
+//
+//*****************************************************************************
+#define LM_API_PSTAT            (CAN_MSGID_MFR_LM | CAN_MSGID_DTYPE_MOTOR |   \
+                                 CAN_API_MC_PSTAT)
+#define LM_API_PSTAT_PER_EN_S0  (LM_API_PSTAT | (0 << CAN_MSGID_API_S))
+#define LM_API_PSTAT_PER_EN_S1  (LM_API_PSTAT | (1 << CAN_MSGID_API_S))
+#define LM_API_PSTAT_PER_EN_S2  (LM_API_PSTAT | (2 << CAN_MSGID_API_S))
+#define LM_API_PSTAT_PER_EN_S3  (LM_API_PSTAT | (3 << CAN_MSGID_API_S))
+#define LM_API_PSTAT_CFG_S0     (LM_API_PSTAT | (4 << CAN_MSGID_API_S))
+#define LM_API_PSTAT_CFG_S1     (LM_API_PSTAT | (5 << CAN_MSGID_API_S))
+#define LM_API_PSTAT_CFG_S2     (LM_API_PSTAT | (6 << CAN_MSGID_API_S))
+#define LM_API_PSTAT_CFG_S3     (LM_API_PSTAT | (7 << CAN_MSGID_API_S))
+#define LM_API_PSTAT_DATA_S0    (LM_API_PSTAT | (8 << CAN_MSGID_API_S))
+#define LM_API_PSTAT_DATA_S1    (LM_API_PSTAT | (9 << CAN_MSGID_API_S))
+#define LM_API_PSTAT_DATA_S2    (LM_API_PSTAT | (10 << CAN_MSGID_API_S))
+#define LM_API_PSTAT_DATA_S3    (LM_API_PSTAT | (11 << CAN_MSGID_API_S))
+
+//*****************************************************************************
+//
+// The values that can be used to configure the data the Periodic Status
+// Message bytes.  Bytes of a multi-byte data values are encoded as
+// little-endian, therefore B0 is the least significant byte.
+//
+//*****************************************************************************
+#define LM_PSTAT_END            0
+#define LM_PSTAT_VOLTOUT_B0     1
+#define LM_PSTAT_VOLTOUT_B1     2
+#define LM_PSTAT_VOLTBUS_B0     3
+#define LM_PSTAT_VOLTBUS_B1     4
+#define LM_PSTAT_CURRENT_B0     5
+#define LM_PSTAT_CURRENT_B1     6
+#define LM_PSTAT_TEMP_B0        7
+#define LM_PSTAT_TEMP_B1        8
+#define LM_PSTAT_POS_B0         9
+#define LM_PSTAT_POS_B1         10
+#define LM_PSTAT_POS_B2         11
+#define LM_PSTAT_POS_B3         12
+#define LM_PSTAT_SPD_B0         13
+#define LM_PSTAT_SPD_B1         14
+#define LM_PSTAT_SPD_B2         15
+#define LM_PSTAT_SPD_B3         16
+#define LM_PSTAT_LIMIT_NCLR     17
+#define LM_PSTAT_LIMIT_CLR      18
+#define LM_PSTAT_FAULT          19
+#define LM_PSTAT_STKY_FLT_NCLR  20
+#define LM_PSTAT_STKY_FLT_CLR   21
+#define LM_PSTAT_VOUT_B0        22
+#define LM_PSTAT_VOUT_B1        23
+#define LM_PSTAT_FLT_COUNT_CURRENT \
+                                24
+#define LM_PSTAT_FLT_COUNT_TEMP 25
+#define LM_PSTAT_FLT_COUNT_VOLTBUS \
+                                26
+#define LM_PSTAT_FLT_COUNT_GATE 27
+#define LM_PSTAT_FLT_COUNT_COMM 28
+#define LM_PSTAT_CANSTS         29
+#define LM_PSTAT_CANERR_B0      30
+#define LM_PSTAT_CANERR_B1      31
+
+#endif // __CAN_PROTO_H__
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/CANJaguar.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/CANJaguar.h
new file mode 100644
index 0000000..67d6db3
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/CANJaguar.h
@@ -0,0 +1,208 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2009. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "ErrorBase.h"
+#include "MotorSafety.h"
+#include "Resource.h"
+#include "MotorSafetyHelper.h"
+#include "PIDOutput.h"
+#include "CANSpeedController.h"
+#include "HAL/Semaphore.hpp"
+#include "HAL/HAL.hpp"
+#include "NetworkCommunication/CANSessionMux.h"
+
+#include <utility>
+
+/**
+ * Luminary Micro / Vex Robotics Jaguar Speed Control
+ */
+class CANJaguar : public MotorSafety,
+					public CANSpeedController,
+					public ErrorBase
+{
+public:
+	// The internal PID control loop in the Jaguar runs at 1kHz.
+	static const int32_t kControllerRate = 1000;
+	static constexpr double kApproxBusVoltage = 12.0;
+
+	// Control mode tags
+	/** Sets an encoder as the speed reference only. <br> Passed as the "tag" when setting the control mode.*/
+	static const struct EncoderStruct       {} Encoder;
+	/** Sets a quadrature encoder as the position and speed reference. <br> Passed as the "tag" when setting the control mode.*/
+	static const struct QuadEncoderStruct   {} QuadEncoder;
+	/** Sets a potentiometer as the position reference only. <br> Passed as the "tag" when setting the control mode. */
+	static const struct PotentiometerStruct {} Potentiometer;
+
+	explicit CANJaguar(uint8_t deviceNumber);
+	virtual ~CANJaguar();
+
+	uint8_t getDeviceNumber() const;
+	uint8_t GetHardwareVersion();
+
+	// PIDOutput interface
+	virtual void PIDWrite(float output);
+
+	// Control mode methods
+	void EnableControl(double encoderInitialPosition = 0.0);
+	void DisableControl();
+
+	void SetPercentMode();
+	void SetPercentMode(EncoderStruct, uint16_t codesPerRev);
+	void SetPercentMode(QuadEncoderStruct, uint16_t codesPerRev);
+	void SetPercentMode(PotentiometerStruct);
+
+	void SetCurrentMode(double p, double i, double d);
+	void SetCurrentMode(EncoderStruct, uint16_t codesPerRev, double p, double i, double d);
+	void SetCurrentMode(QuadEncoderStruct, uint16_t codesPerRev, double p, double i, double d);
+	void SetCurrentMode(PotentiometerStruct, double p, double i, double d);
+
+	void SetSpeedMode(EncoderStruct, uint16_t codesPerRev, double p, double i, double d);
+	void SetSpeedMode(QuadEncoderStruct, uint16_t codesPerRev, double p, double i, double d);
+
+	void SetPositionMode(QuadEncoderStruct, uint16_t codesPerRev, double p, double i, double d);
+	void SetPositionMode(PotentiometerStruct, double p, double i, double d);
+
+	void SetVoltageMode();
+	void SetVoltageMode(EncoderStruct, uint16_t codesPerRev);
+	void SetVoltageMode(QuadEncoderStruct, uint16_t codesPerRev);
+	void SetVoltageMode(PotentiometerStruct);
+
+	// CANSpeedController interface
+	virtual float Get() override;
+	virtual void Set(float value, uint8_t syncGroup=0) override;
+	virtual void Disable() override;
+	virtual void SetP(double p) override;
+	virtual void SetI(double i) override;
+	virtual void SetD(double d) override;
+	virtual void SetPID(double p, double i, double d) override;
+	virtual double GetP() override;
+	virtual double GetI() override;
+	virtual double GetD() override;
+	virtual float GetBusVoltage() override;
+	virtual float GetOutputVoltage() override;
+	virtual float GetOutputCurrent() override;
+	virtual float GetTemperature() override;
+	virtual double GetPosition() override;
+	virtual double GetSpeed() override;
+	virtual bool GetForwardLimitOK() override;
+	virtual bool GetReverseLimitOK() override;
+	virtual uint16_t GetFaults() override;
+	virtual void SetVoltageRampRate(double rampRate) override;
+	virtual uint32_t GetFirmwareVersion() override;
+	virtual void ConfigNeutralMode(NeutralMode mode) override;
+	virtual void ConfigEncoderCodesPerRev(uint16_t codesPerRev) override;
+	virtual void ConfigPotentiometerTurns(uint16_t turns) override;
+	virtual void ConfigSoftPositionLimits(double forwardLimitPosition, double reverseLimitPosition) override;
+	virtual void DisableSoftPositionLimits() override;
+	virtual void ConfigLimitMode(LimitMode mode) override;
+	virtual void ConfigForwardLimit(double forwardLimitPosition) override;
+	virtual void ConfigReverseLimit(double reverseLimitPosition) override;
+	virtual void ConfigMaxOutputVoltage(double voltage) override;
+	virtual void ConfigFaultTime(float faultTime) override;
+	virtual void SetControlMode(ControlMode mode);
+	virtual ControlMode GetControlMode();
+
+ 	static void UpdateSyncGroup(uint8_t syncGroup);
+
+	void SetExpiration(float timeout);
+	float GetExpiration();
+	bool IsAlive();
+	void StopMotor();
+	bool IsSafetyEnabled();
+	void SetSafetyEnabled(bool enabled);
+	void GetDescription(char *desc);
+	uint8_t GetDeviceID();
+
+protected:
+	// Control mode helpers
+	void SetSpeedReference(uint8_t reference);
+	uint8_t GetSpeedReference();
+
+	void SetPositionReference(uint8_t reference);
+	uint8_t GetPositionReference();
+
+	uint8_t packPercentage(uint8_t *buffer, double value);
+	uint8_t packFXP8_8(uint8_t *buffer, double value);
+	uint8_t packFXP16_16(uint8_t *buffer, double value);
+	uint8_t packint16_t(uint8_t *buffer, int16_t value);
+	uint8_t packint32_t(uint8_t *buffer, int32_t value);
+	double unpackPercentage(uint8_t *buffer);
+	double unpackFXP8_8(uint8_t *buffer);
+	double unpackFXP16_16(uint8_t *buffer);
+	int16_t unpackint16_t(uint8_t *buffer);
+	int32_t unpackint32_t(uint8_t *buffer);
+
+	void sendMessage(uint32_t messageID, const uint8_t *data, uint8_t dataSize, int32_t period = CAN_SEND_PERIOD_NO_REPEAT);
+	void requestMessage(uint32_t messageID, int32_t period = CAN_SEND_PERIOD_NO_REPEAT);
+	bool getMessage(uint32_t messageID, uint32_t mask, uint8_t *data, uint8_t *dataSize);
+
+	void setupPeriodicStatus();
+	void updatePeriodicStatus();
+
+	uint8_t m_deviceNumber;
+	float m_value;
+
+	// Parameters/configuration
+	ControlMode m_controlMode;
+	uint8_t m_speedReference;
+	uint8_t m_positionReference;
+	double m_p;
+	double m_i;
+	double m_d;
+	NeutralMode m_neutralMode;
+	uint16_t m_encoderCodesPerRev;
+	uint16_t m_potentiometerTurns;
+	LimitMode m_limitMode;
+	double m_forwardLimit;
+	double m_reverseLimit;
+	double m_maxOutputVoltage;
+	double m_voltageRampRate;
+	float m_faultTime;
+
+	// Which parameters have been verified since they were last set?
+	bool m_controlModeVerified;
+	bool m_speedRefVerified;
+	bool m_posRefVerified;
+	bool m_pVerified;
+	bool m_iVerified;
+	bool m_dVerified;
+	bool m_neutralModeVerified;
+	bool m_encoderCodesPerRevVerified;
+	bool m_potentiometerTurnsVerified;
+	bool m_forwardLimitVerified;
+	bool m_reverseLimitVerified;
+	bool m_limitModeVerified;
+	bool m_maxOutputVoltageVerified;
+	bool m_voltageRampRateVerified;
+	bool m_faultTimeVerified;
+
+	// Status data
+	float m_busVoltage;
+	float m_outputVoltage;
+	float m_outputCurrent;
+	float m_temperature;
+	double m_position;
+	double m_speed;
+	uint8_t m_limits;
+	uint16_t m_faults;
+	uint32_t m_firmwareVersion;
+	uint8_t m_hardwareVersion;
+
+	// Which periodic status messages have we received at least once?
+	bool m_receivedStatusMessage0;
+	bool m_receivedStatusMessage1;
+	bool m_receivedStatusMessage2;
+
+	bool m_controlEnabled;
+
+	void verify();
+
+	MotorSafetyHelper *m_safetyHelper;
+
+private:
+	void InitCANJaguar();
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/CANSpeedController.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/CANSpeedController.h
new file mode 100644
index 0000000..16d3088
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/CANSpeedController.h
@@ -0,0 +1,97 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "SpeedController.h"
+
+/**
+ * Interface for "smart" CAN-based speed controllers.
+ * @see CANJaguar
+ * @see CANTalon
+ */
+class CANSpeedController : public SpeedController
+{
+public:
+	enum ControlMode {
+		kPercentVbus=0,
+		kCurrent=1,
+		kSpeed=2,
+		kPosition=3,
+		kVoltage=4,
+    kFollower=5 // Not supported in Jaguar.
+	};
+
+	enum Faults {
+		kCurrentFault = 1,
+		kTemperatureFault = 2,
+		kBusVoltageFault = 4,
+		kGateDriverFault = 8,
+		/* SRX extensions */
+		kFwdLimitSwitch = 0x10,
+		kRevLimitSwitch = 0x20,
+		kFwdSoftLimit = 0x40,
+		kRevSoftLimit = 0x80,
+	};
+
+	enum Limits {
+		kForwardLimit = 1,
+		kReverseLimit = 2
+	};
+
+	enum NeutralMode {
+		/** Use the NeutralMode that is set by the jumper wire on the CAN device */
+		kNeutralMode_Jumper = 0,
+		/** Stop the motor's rotation by applying a force. */
+		kNeutralMode_Brake = 1,
+		/** Do not attempt to stop the motor. Instead allow it to coast to a stop without applying resistance. */
+		kNeutralMode_Coast = 2
+	};
+
+	enum LimitMode {
+		/** Only use switches for limits */
+		kLimitMode_SwitchInputsOnly = 0,
+		/** Use both switches and soft limits */
+		kLimitMode_SoftPositionLimits = 1,
+		/* SRX extensions */
+		/** Disable switches and disable soft limits */
+		kLimitMode_SrxDisableSwitchInputs = 2,
+	};
+
+	virtual float Get() = 0;
+	virtual void Set(float value, uint8_t syncGroup=0) = 0;
+	virtual void Disable() = 0;
+	virtual void SetP(double p) = 0;
+	virtual void SetI(double i) = 0;
+	virtual void SetD(double d) = 0;
+	virtual void SetPID(double p, double i, double d) = 0;
+	virtual double GetP() = 0;
+	virtual double GetI() = 0;
+	virtual double GetD() = 0;
+	virtual float GetBusVoltage() = 0;
+	virtual float GetOutputVoltage() = 0;
+	virtual float GetOutputCurrent() = 0;
+	virtual float GetTemperature() = 0;
+	virtual double GetPosition() = 0;
+	virtual double GetSpeed() = 0;
+	virtual bool GetForwardLimitOK() = 0;
+	virtual bool GetReverseLimitOK() = 0;
+	virtual uint16_t GetFaults() = 0;
+	virtual void SetVoltageRampRate(double rampRate) = 0;
+	virtual uint32_t GetFirmwareVersion() = 0;
+	virtual void ConfigNeutralMode(NeutralMode mode) = 0;
+	virtual void ConfigEncoderCodesPerRev(uint16_t codesPerRev) = 0;
+	virtual void ConfigPotentiometerTurns(uint16_t turns) = 0;
+	virtual void ConfigSoftPositionLimits(double forwardLimitPosition, double reverseLimitPosition) = 0;
+	virtual void DisableSoftPositionLimits() = 0;
+	virtual void ConfigLimitMode(LimitMode mode) = 0;
+	virtual void ConfigForwardLimit(double forwardLimitPosition) = 0;
+	virtual void ConfigReverseLimit(double reverseLimitPosition) = 0;
+	virtual void ConfigMaxOutputVoltage(double voltage) = 0;
+	virtual void ConfigFaultTime(float faultTime) = 0;
+  // Hold off on interface until we figure out ControlMode enums.
+//	virtual void SetControlMode(ControlMode mode) = 0;
+//	virtual ControlMode GetControlMode() = 0;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/CANTalon.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/CANTalon.h
new file mode 100644
index 0000000..c720ea0
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/CANTalon.h
@@ -0,0 +1,171 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "SafePWM.h"
+#include "CANSpeedController.h"
+#include "PIDOutput.h"
+#include "MotorSafetyHelper.h"
+
+class CanTalonSRX;
+
+/**
+ * CTRE Talon SRX Speed Controller with CAN Control
+ */
+class CANTalon : public MotorSafety,
+                 public CANSpeedController,
+                 public ErrorBase
+{
+public:
+  enum FeedbackDevice {
+    QuadEncoder=0,
+    AnalogPot=2,
+    AnalogEncoder=3,
+    EncRising=4,
+    EncFalling=5
+  };
+  enum StatusFrameRate {
+    StatusFrameRateGeneral=0,
+    StatusFrameRateFeedback=1,
+    StatusFrameRateQuadEncoder=2,
+    StatusFrameRateAnalogTempVbat=3,
+  };
+	explicit CANTalon(int deviceNumber);
+	explicit CANTalon(int deviceNumber,int controlPeriodMs);
+	virtual ~CANTalon();
+
+	// PIDController interface
+	virtual void PIDWrite(float output) override;
+
+	// MotorSafety interface
+	virtual void SetExpiration(float timeout) override;
+	virtual float GetExpiration() override;
+	virtual bool IsAlive() override;
+	virtual void StopMotor() override;
+	virtual void SetSafetyEnabled(bool enabled) override;
+	virtual bool IsSafetyEnabled() override;
+	virtual void GetDescription(char *desc) override;
+
+	// CANSpeedController interface
+	virtual float Get() override;
+	virtual void Set(float value, uint8_t syncGroup=0) override;
+	virtual void Disable() override;
+  virtual void EnableControl();
+	virtual void SetP(double p) override;
+	virtual void SetI(double i) override;
+	virtual void SetD(double d) override;
+	void SetF(double f);
+	void SetIzone(unsigned iz);
+	virtual void SetPID(double p, double i, double d) override;
+	void SetPID(double p, double i, double d, double f);
+	virtual double GetP() override;
+	virtual double GetI() override;
+	virtual double GetD() override;
+	double GetF();
+	virtual float GetBusVoltage() override;
+	virtual float GetOutputVoltage() override;
+	virtual float GetOutputCurrent() override;
+	virtual float GetTemperature() override;
+	void SetPosition(double pos);
+	virtual double GetPosition() override;
+	virtual double GetSpeed() override;
+  virtual int GetClosedLoopError();
+  virtual int GetAnalogIn();
+  virtual int GetAnalogInRaw();
+  virtual int GetAnalogInVel();
+  virtual int GetEncPosition();
+  virtual int GetEncVel();
+	int GetPinStateQuadA();
+	int GetPinStateQuadB();
+	int GetPinStateQuadIdx();
+	int IsFwdLimitSwitchClosed();
+	int IsRevLimitSwitchClosed();
+	int GetNumberOfQuadIdxRises();
+	void SetNumberOfQuadIdxRises(int rises);
+	virtual bool GetForwardLimitOK() override;
+	virtual bool GetReverseLimitOK() override;
+	virtual uint16_t GetFaults() override;
+	uint16_t GetStickyFaults();
+	void ClearStickyFaults();
+	virtual void SetVoltageRampRate(double rampRate) override;
+	virtual uint32_t GetFirmwareVersion() override;
+	virtual void ConfigNeutralMode(NeutralMode mode) override;
+	virtual void ConfigEncoderCodesPerRev(uint16_t codesPerRev) override;
+	virtual void ConfigPotentiometerTurns(uint16_t turns) override;
+	virtual void ConfigSoftPositionLimits(double forwardLimitPosition, double reverseLimitPosition) override;
+	virtual void DisableSoftPositionLimits() override;
+	virtual void ConfigLimitMode(LimitMode mode) override;
+	virtual void ConfigForwardLimit(double forwardLimitPosition) override;
+	virtual void ConfigReverseLimit(double reverseLimitPosition) override;
+	/**
+	 * Change the fwd limit switch setting to normally open or closed.
+	 * Talon will disable momentarilly if the Talon's current setting
+	 * is dissimilar to the caller's requested setting.
+	 *
+	 * Since Talon saves setting to flash this should only affect
+	 * a given Talon initially during robot install.
+	 *
+	 * @param normallyOpen true for normally open.  false for normally closed.
+	 */
+	void ConfigFwdLimitSwitchNormallyOpen(bool normallyOpen);
+	/**
+	 * Change the rev limit switch setting to normally open or closed.
+	 * Talon will disable momentarilly if the Talon's current setting
+	 * is dissimilar to the caller's requested setting.
+	 *
+	 * Since Talon saves setting to flash this should only affect
+	 * a given Talon initially during robot install.
+	 *
+	 * @param normallyOpen true for normally open.  false for normally closed.
+	 */
+	void ConfigRevLimitSwitchNormallyOpen(bool normallyOpen);
+	virtual void ConfigMaxOutputVoltage(double voltage) override;
+	virtual void ConfigFaultTime(float faultTime) override;
+	virtual void SetControlMode(ControlMode mode);
+  void SetFeedbackDevice(FeedbackDevice device);
+	void SetStatusFrameRateMs(StatusFrameRate stateFrame, int periodMs);
+	virtual ControlMode GetControlMode();
+	void SetSensorDirection(bool reverseSensor);
+	void SetCloseLoopRampRate(double rampRate);
+	void SelectProfileSlot(int slotIdx);
+	int GetIzone();
+	int GetIaccum();
+	void ClearIaccum();
+	int GetBrakeEnableDuringNeutral();
+
+  bool IsControlEnabled();
+  double GetSetpoint();
+private:
+  // Values for various modes as is sent in the CAN packets for the Talon.
+  enum TalonControlMode {
+		kThrottle=0,
+    kFollowerMode=5,
+		kVoltageMode=4,
+		kPositionMode=1,
+		kSpeedMode=2,
+		kCurrentMode=3,
+    kDisabled=15
+  };
+
+	int m_deviceNumber;
+	CanTalonSRX *m_impl;
+	MotorSafetyHelper *m_safetyHelper;
+  int m_profile; // Profile from CANTalon to use. Set to zero until we can actually test this.
+
+  bool m_controlEnabled;
+  ControlMode m_controlMode;
+  TalonControlMode m_sendMode;
+
+  double m_setPoint;
+  static const unsigned int kDelayForSolicitedSignalsUs = 4000;
+  /**
+   * Fixup the sendMode so Set() serializes the correct demand value.
+   * Also fills the modeSelecet in the control frame to disabled.
+   * @param mode Control mode to ultimately enter once user calls Set().
+   * @see Set()
+   */
+  void ApplyControlMode(CANSpeedController::ControlMode mode);
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Compressor.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Compressor.h
new file mode 100644
index 0000000..ffe6e65
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Compressor.h
@@ -0,0 +1,49 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#ifndef Compressor_H_
+#define Compressor_H_
+
+#include "HAL/HAL.hpp"
+#include "SensorBase.h"
+
+/**
+ * PCM compressor
+ */
+class Compressor: public SensorBase {
+public:
+	explicit Compressor(uint8_t pcmID);
+	Compressor();
+	virtual ~Compressor();
+
+	void Start();
+	void Stop();
+	bool Enabled();
+
+	bool GetPressureSwitchValue();
+
+	float GetCompressorCurrent();
+
+	void SetClosedLoopControl(bool on);
+	bool GetClosedLoopControl();
+
+	bool GetCompressorCurrentTooHighFault();
+	bool GetCompressorCurrentTooHighStickyFault();
+	bool GetCompressorShortedStickyFault();
+	bool GetCompressorShortedFault();
+	bool GetCompressorNotConnectedStickyFault();
+	bool GetCompressorNotConnectedFault();
+	void ClearAllPCMStickyFaults();
+
+protected:
+	void *m_pcm_pointer;
+
+private:
+	void InitCompressor(uint8_t module);
+	void SetCompressor(bool on);
+};
+
+#endif /* Compressor_H_ */
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/ControllerPower.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/ControllerPower.h
new file mode 100644
index 0000000..654cfb5
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/ControllerPower.h
@@ -0,0 +1,30 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2011. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#ifndef __CONTROLLER_POWER_H__
+#define __CONTROLLER_POWER_H__
+
+
+
+class ControllerPower
+{
+	public: 
+		static double GetInputVoltage();
+		static double GetInputCurrent();
+		static double GetVoltage3V3();
+		static double GetCurrent3V3();
+		static bool GetEnabled3V3();
+		static int GetFaultCount3V3();
+		static double GetVoltage5V();
+		static double GetCurrent5V();
+		static bool GetEnabled5V();
+		static int GetFaultCount5V();
+		static double GetVoltage6V();
+		static double GetCurrent6V();
+		static bool GetEnabled6V();
+		static int GetFaultCount6V();
+};
+#endif
\ No newline at end of file
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Counter.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Counter.h
new file mode 100644
index 0000000..0eace8c
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Counter.h
@@ -0,0 +1,88 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "HAL/HAL.hpp"
+#include "AnalogTriggerOutput.h"
+#include "CounterBase.h"
+#include "SensorBase.h"
+
+class DigitalGlitchFilter;
+
+/**
+ * Class for counting the number of ticks on a digital input channel.
+ * This is a general purpose class for counting repetitive events. It can return the number
+ * of counts, the period of the most recent cycle, and detect when the signal being counted
+ * has stopped by supplying a maximum cycle time.
+ *
+ * All counters will immediately start counting - Reset() them if you need them
+ * to be zeroed before use.
+ */
+class Counter : public SensorBase, public CounterBase
+{
+public:
+
+	Counter();
+	explicit Counter(int32_t channel);
+	explicit Counter(DigitalSource *source);
+	explicit Counter(DigitalSource &source);
+	explicit Counter(AnalogTrigger *trigger);
+	explicit Counter(AnalogTrigger &trigger);
+	Counter(EncodingType encodingType, DigitalSource *upSource, DigitalSource *downSource,
+			bool inverted);
+	virtual ~Counter();
+
+	void SetUpSource(int32_t channel);
+	void SetUpSource(AnalogTrigger *analogTrigger, AnalogTriggerType triggerType);
+	void SetUpSource(AnalogTrigger &analogTrigger, AnalogTriggerType triggerType);
+	void SetUpSource(DigitalSource *source);
+	void SetUpSource(DigitalSource &source);
+	void SetUpSourceEdge(bool risingEdge, bool fallingEdge);
+	void ClearUpSource();
+
+	void SetDownSource(int32_t channel);
+	void SetDownSource(AnalogTrigger *analogTrigger, AnalogTriggerType triggerType);
+	void SetDownSource(AnalogTrigger &analogTrigger, AnalogTriggerType triggerType);
+	void SetDownSource(DigitalSource *source);
+	void SetDownSource(DigitalSource &source);
+	void SetDownSourceEdge(bool risingEdge, bool fallingEdge);
+	void ClearDownSource();
+
+	void SetUpDownCounterMode();
+	void SetExternalDirectionMode();
+	void SetSemiPeriodMode(bool highSemiPeriod);
+	void SetPulseLengthMode(float threshold);
+
+	void SetReverseDirection(bool reverseDirection);
+
+	// CounterBase interface
+	int32_t Get();
+	void Reset();
+	double GetPeriod();
+	void SetMaxPeriod(double maxPeriod);
+	void SetUpdateWhenEmpty(bool enabled);
+	bool GetStopped();
+	bool GetDirection();
+	void SetSamplesToAverage(int samplesToAverage);
+	int GetSamplesToAverage();
+	uint32_t GetFPGAIndex()
+	{
+		return m_index;
+	}
+
+protected:
+	DigitalSource *m_upSource;		///< What makes the counter count up.
+	DigitalSource *m_downSource;	///< What makes the counter count down.
+	void* m_counter;				///< The FPGA counter object.
+private:
+	void InitCounter(Mode mode = kTwoPulse);
+
+	bool m_allocatedUpSource;		///< Was the upSource allocated locally?
+	bool m_allocatedDownSource;	///< Was the downSource allocated locally?
+	uint32_t m_index;					///< The index of this counter.
+
+  friend class DigitalGlitchFilter;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/CounterBase.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/CounterBase.h
new file mode 100644
index 0000000..f475ddf
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/CounterBase.h
@@ -0,0 +1,35 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include <stdint.h>
+
+/**
+ * Interface for counting the number of ticks on a digital input channel.
+ * Encoders, Gear tooth sensors, and counters should all subclass this so it can
+ * be used to build more advanced classes for control and driving.
+ *
+ * All counters will immediately start counting - Reset() them if you need them
+ * to be zeroed before use.
+ */
+class CounterBase
+{
+public:
+	enum EncodingType
+	{
+		k1X,
+		k2X,
+		k4X
+	};
+
+	virtual ~CounterBase() {}
+	virtual int32_t Get() = 0;
+	virtual void Reset() = 0;
+	virtual double GetPeriod() = 0;
+	virtual void SetMaxPeriod(double maxPeriod) = 0;
+	virtual bool GetStopped() = 0;
+	virtual bool GetDirection() = 0;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/DigitalInput.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/DigitalInput.h
new file mode 100644
index 0000000..928d71e
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/DigitalInput.h
@@ -0,0 +1,119 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include <array>
+
+#include "DigitalSource.h"
+
+class Encoder;
+class Counter;
+class DigitalGlitchFilter;
+
+/**
+ * Class to read a digital input.
+ * This class will read digital inputs and return the current value on the channel. Other devices
+ * such as encoders, gear tooth sensors, etc. that are implemented elsewhere will automatically
+ * allocate digital inputs and outputs as required. This class is only for devices like switches
+ * etc. that aren't implemented anywhere else.
+ */
+class DigitalInput : public DigitalSource
+{
+public:
+	explicit DigitalInput(uint32_t channel);
+	virtual ~DigitalInput();
+	virtual bool Get();
+	uint32_t GetChannel();
+
+	// Digital Source Interface
+	virtual uint32_t GetChannelForRouting();
+	virtual uint32_t GetModuleForRouting();
+	virtual bool GetAnalogTriggerForRouting();
+
+private:
+	void InitDigitalInput(uint32_t channel);
+	uint32_t m_channel;
+	bool m_lastValue;
+
+  friend DigitalGlitchFilter;
+};
+
+/**
+ * Class to enable glitch filtering on a set of digital inputs.
+ * This class will manage adding and removing digital inputs from a FPGA glitch
+ * filter. The filter lets the user configure the time that an input must remain
+ * high or low before it is classified as high or low.
+ */
+class DigitalGlitchFilter : public ErrorBase {
+ public:
+  DigitalGlitchFilter();
+  ~DigitalGlitchFilter();
+
+  /**
+   * Assigns the DigitalSource to this glitch filter.
+   *
+   * @param input The DigitalSource to add.
+   */
+  void Add(DigitalSource *input);
+
+  /**
+   * Assigns the Encoder to this glitch filter.
+   *
+   * @param input The Encoder to add.
+   */
+  void Add(Encoder *input);
+
+  /**
+   * Assigns the Counter to this glitch filter.
+   *
+   * @param input The Counter to add.
+   */
+  void Add(Counter *input);
+
+  /**
+   * Removes a digital input from this filter.
+   *
+   * Removes the DigitalSource from this glitch filter and re-assigns it to the
+   * default filter.
+   *
+   * @param input The DigitalSource to remove.
+   */
+  void Remove(DigitalSource *input);
+  void Remove(Encoder *input);
+  void Remove(Counter *input);
+
+  /**
+   * Sets the number of cycles that the input must not change state for.
+   *
+   * @param fpga_cycles The number of FPGA cycles.
+   */
+  void SetPeriodCycles(uint32_t fpga_cycles);
+
+  /**
+   * Sets the number of nanoseconds that the input must not change state for.
+   *
+   * @param nanoseconds The number of nanoseconds.
+   */
+  void SetPeriodNanoSeconds(uint64_t nanoseconds);
+
+  /**
+   * Gets the number of cycles that the input must not change state for.
+   *
+   * @return The number of cycles.
+   */
+  uint32_t GetPeriodCycles();
+  /**
+   * Gets the number of nanoseconds that the input must not change state for.
+   *
+   * @return The number of nanoseconds.
+   */
+  uint64_t GetPeriodNanoSeconds();
+
+ private:
+  int channel_index_;
+  static Mutex mutex_;
+  static ::std::array<int, 3> filter_allocated_;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/DigitalOutput.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/DigitalOutput.h
new file mode 100644
index 0000000..dc6012b
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/DigitalOutput.h
@@ -0,0 +1,40 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "DigitalSource.h"
+
+/**
+ * Class to write to digital outputs.
+ * Write values to the digital output channels. Other devices implemented elsewhere will allocate
+ * channels automatically so for those devices it shouldn't be done here.
+ */
+class DigitalOutput : public DigitalSource
+{
+public:
+	explicit DigitalOutput(uint32_t channel);
+	virtual ~DigitalOutput();
+	void Set(uint32_t value);
+  virtual bool Get();
+	uint32_t GetChannel();
+	void Pulse(float length);
+	bool IsPulsing();
+	void SetPWMRate(float rate);
+	void EnablePWM(float initialDutyCycle);
+	void DisablePWM();
+	void UpdateDutyCycle(float dutyCycle);
+
+	// Digital Source Interface
+	virtual uint32_t GetChannelForRouting();
+	virtual uint32_t GetModuleForRouting();
+	virtual bool GetAnalogTriggerForRouting();
+
+private:
+	void InitDigitalOutput(uint32_t channel);
+
+	uint32_t m_channel;
+	void *m_pwmGenerator;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/DigitalSource.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/DigitalSource.h
new file mode 100644
index 0000000..066bc63
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/DigitalSource.h
@@ -0,0 +1,25 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "InterruptableSensorBase.h"
+
+/**
+ * DigitalSource Interface.
+ * The DigitalSource represents all the possible inputs for a counter or a quadrature encoder. The source may be
+ * either a digital input or an analog input. If the caller just provides a channel, then a digital input will be
+ * constructed and freed when finished for the source. The source can either be a digital input or analog trigger
+ * but not both.
+ */
+class DigitalSource : public InterruptableSensorBase
+{
+public:
+	virtual ~DigitalSource();
+  virtual bool Get() = 0;
+	virtual uint32_t GetChannelForRouting() = 0;
+	virtual uint32_t GetModuleForRouting() = 0;
+	virtual bool GetAnalogTriggerForRouting() = 0;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/DoubleSolenoid.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/DoubleSolenoid.h
new file mode 100644
index 0000000..5241f89
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/DoubleSolenoid.h
@@ -0,0 +1,42 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "SolenoidBase.h"
+
+/**
+ * DoubleSolenoid class for running 2 channels of high voltage Digital Output
+ * (PCM).
+ *
+ * The DoubleSolenoid class is typically used for pneumatics solenoids that
+ * have two positions controlled by two separate channels.
+ */
+class DoubleSolenoid : public SolenoidBase
+{
+public:
+	enum Value
+	{
+		kOff,
+		kForward,
+		kReverse
+	};
+
+	explicit DoubleSolenoid(uint32_t forwardChannel, uint32_t reverseChannel);
+	DoubleSolenoid(uint8_t moduleNumber, uint32_t forwardChannel, uint32_t reverseChannel);
+	virtual ~DoubleSolenoid();
+	virtual void Set(Value value);
+	virtual Value Get();
+	bool IsFwdSolenoidBlackListed();
+	bool IsRevSolenoidBlackListed();
+
+private:
+	virtual void InitSolenoid();
+
+	uint32_t m_forwardChannel; ///< The forward channel on the module to control.
+	uint32_t m_reverseChannel; ///< The reverse channel on the module to control.
+	uint8_t m_forwardMask; ///< The mask for the forward channel.
+	uint8_t m_reverseMask; ///< The mask for the reverse channel.
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/DriverStation.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/DriverStation.h
new file mode 100644
index 0000000..0397ca3
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/DriverStation.h
@@ -0,0 +1,114 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "SensorBase.h"
+#include "RobotState.h"
+#include "Task.h"
+#include "HAL/HAL.hpp"
+
+struct HALControlWord;
+class AnalogInput;
+
+/**
+ * Provide access to the network communication data to / from the Driver Station.
+ */
+class DriverStation : public SensorBase, public RobotStateInterface
+{
+public:
+	enum Alliance
+	{
+		kRed,
+		kBlue,
+		kInvalid
+	};
+
+	virtual ~DriverStation();
+	static DriverStation *GetInstance();
+	static void ReportError(std::string error);
+
+	static const uint32_t kJoystickPorts = 6;
+
+	float GetStickAxis(uint32_t stick, uint32_t axis);
+	int GetStickPOV(uint32_t stick, uint32_t pov);
+	uint32_t GetStickButtons(uint32_t stick);
+	bool GetStickButton(uint32_t stick, uint8_t button);
+
+	int GetStickAxisCount(uint32_t stick);
+	int GetStickPOVCount(uint32_t stick);
+	int GetStickButtonCount(uint32_t stick);
+
+	bool IsEnabled();
+	bool IsDisabled();
+	bool IsAutonomous();
+	bool IsOperatorControl();
+	bool IsTest();
+	bool IsDSAttached();
+	bool IsNewControlData();
+	bool IsFMSAttached();
+	bool IsSysActive();
+	bool IsSysBrownedOut();
+
+	Alliance GetAlliance();
+	uint32_t GetLocation();
+	void WaitForData();
+	double GetMatchTime();
+	float GetBatteryVoltage();
+
+	/** Only to be used to tell the Driver Station what code you claim to be executing
+	 *   for diagnostic purposes only
+	 * @param entering If true, starting disabled code; if false, leaving disabled code */
+	void InDisabled(bool entering)
+	{
+		m_userInDisabled = entering;
+	}
+	/** Only to be used to tell the Driver Station what code you claim to be executing
+	 *   for diagnostic purposes only
+	 * @param entering If true, starting autonomous code; if false, leaving autonomous code */
+	void InAutonomous(bool entering)
+	{
+		m_userInAutonomous = entering;
+	}
+	/** Only to be used to tell the Driver Station what code you claim to be executing
+	 *   for diagnostic purposes only
+	 * @param entering If true, starting teleop code; if false, leaving teleop code */
+	void InOperatorControl(bool entering)
+	{
+		m_userInTeleop = entering;
+	}
+	/** Only to be used to tell the Driver Station what code you claim to be executing
+	 *   for diagnostic purposes only
+	 * @param entering If true, starting test code; if false, leaving test code */
+	void InTest(bool entering)
+	{
+		m_userInTest = entering;
+	}
+
+protected:
+	DriverStation();
+
+	void GetData();
+private:
+	static void InitTask(DriverStation *ds);
+	static DriverStation *m_instance;
+	void ReportJoystickUnpluggedError(std::string message);
+	void Run();
+
+	HALJoystickAxes m_joystickAxes[kJoystickPorts];
+	HALJoystickPOVs m_joystickPOVs[kJoystickPorts];
+	HALJoystickButtons m_joystickButtons[kJoystickPorts];
+	Task m_task;
+	SEMAPHORE_ID m_newControlData;
+	MULTIWAIT_ID m_packetDataAvailableMultiWait;
+	MUTEX_ID m_packetDataAvailableMutex;
+	MULTIWAIT_ID m_waitForDataSem;
+	MUTEX_ID m_waitForDataMutex;
+	bool m_userInDisabled;
+	bool m_userInAutonomous;
+	bool m_userInTeleop;
+	bool m_userInTest;
+	double m_nextMessageTime;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Encoder.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Encoder.h
new file mode 100644
index 0000000..780d524
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Encoder.h
@@ -0,0 +1,87 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "HAL/HAL.hpp"
+#include "CounterBase.h"
+#include "SensorBase.h"
+#include "Counter.h"
+#include "PIDSource.h"
+
+class DigitalSource;
+class DigitalGlitchFilter;
+
+/**
+ * Class to read quad encoders.
+ * Quadrature encoders are devices that count shaft rotation and can sense direction. The output of
+ * the QuadEncoder class is an integer that can count either up or down, and can go negative for
+ * reverse direction counting. When creating QuadEncoders, a direction is supplied that changes the
+ * sense of the output to make code more readable if the encoder is mounted such that forward movement
+ * generates negative values. Quadrature encoders have two digital outputs, an A Channel and a B Channel
+ * that are out of phase with each other to allow the FPGA to do direction sensing.
+ *
+ * All encoders will immediately start counting - Reset() them if you need them
+ * to be zeroed before use.
+ */
+class Encoder : public SensorBase, public CounterBase, public PIDSource
+{
+public:
+	enum IndexingType { kResetWhileHigh, kResetWhileLow, kResetOnFallingEdge, kResetOnRisingEdge };
+
+	Encoder(uint32_t aChannel, uint32_t bChannel, bool reverseDirection = false,
+			EncodingType encodingType = k4X);
+	Encoder(DigitalSource *aSource, DigitalSource *bSource, bool reverseDirection = false,
+			EncodingType encodingType = k4X);
+	Encoder(DigitalSource &aSource, DigitalSource &bSource, bool reverseDirection = false,
+			EncodingType encodingType = k4X);
+	virtual ~Encoder();
+
+	// CounterBase interface
+	int32_t Get();
+	int32_t GetRaw();
+	int32_t GetEncodingScale();
+	void Reset();
+	double GetPeriod();
+	void SetMaxPeriod(double maxPeriod);
+	bool GetStopped();
+	bool GetDirection();
+	double GetDistance();
+	double GetRate();
+	void SetMinRate(double minRate);
+	void SetDistancePerPulse(double distancePerPulse);
+	void SetReverseDirection(bool reverseDirection);
+	void SetSamplesToAverage(int samplesToAverage);
+	int GetSamplesToAverage();
+	void SetPIDSourceParameter(PIDSourceParameter pidSource);
+	double PIDGet();
+
+	void SetIndexSource(uint32_t channel, IndexingType type = kResetOnRisingEdge);
+	void SetIndexSource(DigitalSource *source, IndexingType type = kResetOnRisingEdge);
+	void SetIndexSource(DigitalSource &source, IndexingType type = kResetOnRisingEdge);
+
+	int32_t GetFPGAIndex()
+	{
+		return m_index;
+	}
+
+private:
+	void InitEncoder(bool _reverseDirection, EncodingType encodingType);
+	double DecodingScaleFactor();
+
+	DigitalSource *m_aSource;		// the A phase of the quad encoder
+	DigitalSource *m_bSource;		// the B phase of the quad encoder
+	bool m_allocatedASource;		// was the A source allocated locally?
+	bool m_allocatedBSource;		// was the B source allocated locally?
+	void* m_encoder;
+	int32_t m_index;				// The encoder's FPGA index.
+	double m_distancePerPulse;		// distance of travel for each encoder tick
+	Counter *m_counter;				// Counter object for 1x and 2x encoding
+	EncodingType m_encodingType;	// Encoding type
+	int32_t m_encodingScale;		// 1x, 2x, or 4x, per the encodingType
+	PIDSourceParameter m_pidSource;	// Encoder parameter that sources a PID controller
+
+  friend class DigitalGlitchFilter;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/GearTooth.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/GearTooth.h
new file mode 100644
index 0000000..a30e50d
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/GearTooth.h
@@ -0,0 +1,26 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "Counter.h"
+
+/**
+ * Alias for counter class.
+ * Implement the gear tooth sensor supplied by FIRST. Currently there is no reverse sensing on
+ * the gear tooth sensor, but in future versions we might implement the necessary timing in the
+ * FPGA to sense direction.
+ */
+class GearTooth : public Counter
+{
+public:
+	/// 55 uSec for threshold
+	static constexpr double kGearToothThreshold = 55e-6;
+	GearTooth(uint32_t channel, bool directionSensitive = false);
+	GearTooth(DigitalSource *source, bool directionSensitive = false);
+	GearTooth(DigitalSource &source, bool directionSensitive = false);
+	virtual ~GearTooth();
+	void EnableDirectionSensing(bool directionSensitive);
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Gyro.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Gyro.h
new file mode 100644
index 0000000..240d983
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Gyro.h
@@ -0,0 +1,56 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "SensorBase.h"
+#include "PIDSource.h"
+
+class AnalogInput;
+
+/**
+ * Use a rate gyro to return the robots heading relative to a starting position.
+ * The Gyro class tracks the robots heading based on the starting position. As the robot
+ * rotates the new heading is computed by integrating the rate of rotation returned
+ * by the sensor. When the class is instantiated, it does a short calibration routine
+ * where it samples the gyro while at rest to determine the default offset. This is
+ * subtracted from each sample to determine the heading. This gyro class must be used
+ * with a channel that is assigned one of the Analog accumulators from the FPGA. See
+ * AnalogInput for the current accumulator assignments.
+ */
+class Gyro : public SensorBase, public PIDSource
+{
+public:
+	static const uint32_t kOversampleBits = 10;
+	static const uint32_t kAverageBits = 0;
+	static constexpr float kSamplesPerSecond = 50.0;
+	static constexpr float kCalibrationSampleTime = 5.0;
+	static constexpr float kDefaultVoltsPerDegreePerSecond = 0.007;
+
+	explicit Gyro(int32_t channel);
+	explicit Gyro(AnalogInput *channel);
+	explicit Gyro(AnalogInput &channel);
+	virtual ~Gyro();
+	virtual float GetAngle();
+	virtual double GetRate();
+	void SetSensitivity(float voltsPerDegreePerSecond);
+	void SetDeadband(float volts);
+	void SetPIDSourceParameter(PIDSourceParameter pidSource);
+	virtual void Reset();
+	void InitGyro();
+
+	// PIDSource interface
+	double PIDGet();
+
+protected:
+	AnalogInput *m_analog;
+
+private:
+	float m_voltsPerDegreePerSecond;
+	float m_offset;
+	bool m_channelAllocated;
+	uint32_t m_center;
+	PIDSourceParameter m_pidSource;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/I2C.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/I2C.h
new file mode 100644
index 0000000..a90e4c6
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/I2C.h
@@ -0,0 +1,38 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "SensorBase.h"
+
+/**
+ * I2C bus interface class.
+ *
+ * This class is intended to be used by sensor (and other I2C device) drivers.
+ * It probably should not be used directly.
+ *
+ */
+class I2C : SensorBase
+{
+public:
+	enum Port {kOnboard, kMXP};
+
+	I2C(Port port, uint8_t deviceAddress);
+	virtual ~I2C();
+
+	bool Transaction(uint8_t *dataToSend, uint8_t sendSize, uint8_t *dataReceived,
+			uint8_t receiveSize);
+	bool AddressOnly();
+	bool Write(uint8_t registerAddress, uint8_t data);
+	bool WriteBulk(uint8_t* data, uint8_t count);
+	bool Read(uint8_t registerAddress, uint8_t count, uint8_t *data);
+	bool ReadOnly(uint8_t count, uint8_t *buffer);
+	void Broadcast(uint8_t registerAddress, uint8_t data);
+	bool VerifySensor(uint8_t registerAddress, uint8_t count, const uint8_t *expected);
+private:
+
+	Port m_port;
+	uint8_t m_deviceAddress;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Internal/HardwareHLReporting.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Internal/HardwareHLReporting.h
new file mode 100644
index 0000000..aa7ebc8
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Internal/HardwareHLReporting.h
@@ -0,0 +1,9 @@
+
+#include "HLUsageReporting.h"
+
+class HardwareHLReporting : public HLUsageReportingInterface
+{
+public:
+    virtual void ReportScheduler();
+    virtual void ReportSmartDashboard();
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/InterruptableSensorBase.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/InterruptableSensorBase.h
new file mode 100644
index 0000000..fb0db4f
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/InterruptableSensorBase.h
@@ -0,0 +1,42 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "HAL/HAL.hpp"
+#include "SensorBase.h"
+#include "Resource.h"
+
+class InterruptableSensorBase : public SensorBase
+{
+public:
+	enum WaitResult {
+		kTimeout = 0x0,
+		kRisingEdge = 0x1,
+		kFallingEdge = 0x100,
+		kBoth = 0x101,
+	};
+
+	InterruptableSensorBase();
+	virtual ~InterruptableSensorBase();
+	virtual uint32_t GetChannelForRouting() = 0;
+	virtual uint32_t GetModuleForRouting() = 0;
+	virtual bool GetAnalogTriggerForRouting() = 0;
+	virtual void RequestInterrupts(InterruptHandlerFunction handler, void *param); ///< Asynchronus handler version.
+	virtual void RequestInterrupts();		///< Synchronus Wait version.
+	virtual void CancelInterrupts();			///< Free up the underlying chipobject functions.
+	virtual WaitResult WaitForInterrupt(float timeout, bool ignorePrevious = true); ///< Synchronus version.
+	virtual void EnableInterrupts();			///< Enable interrupts - after finishing setup.
+	virtual void DisableInterrupts();		///< Disable, but don't deallocate.
+	virtual double ReadRisingTimestamp();///< Return the timestamp for the rising interrupt that occurred.
+	virtual double ReadFallingTimestamp();///< Return the timestamp for the falling interrupt that occurred.
+	virtual void SetUpSourceEdge(bool risingEdge, bool fallingEdge);
+protected:
+	void* m_interrupt;
+	uint32_t m_interruptIndex;
+	void AllocateInterrupts(bool watcher);
+
+	static Resource *m_interrupts;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/IterativeRobot.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/IterativeRobot.h
new file mode 100644
index 0000000..76a1cc0
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/IterativeRobot.h
@@ -0,0 +1,73 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "Timer.h"
+#include "RobotBase.h"
+
+/**
+ * IterativeRobot implements a specific type of Robot Program framework, extending the RobotBase class.
+ * 
+ * The IterativeRobot class is intended to be subclassed by a user creating a robot program.
+ * 
+ * This class is intended to implement the "old style" default code, by providing
+ * the following functions which are called by the main loop, StartCompetition(), at the appropriate times:
+ * 
+ * RobotInit() -- provide for initialization at robot power-on
+ * 
+ * Init() functions -- each of the following functions is called once when the
+ *                     appropriate mode is entered:
+ *  - DisabledInit()   -- called only when first disabled
+ *  - AutonomousInit() -- called each and every time autonomous is entered from another mode
+ *  - TeleopInit()     -- called each and every time teleop is entered from another mode
+ *  - TestInit()       -- called each and every time test is entered from another mode
+ * 
+ * Periodic() functions -- each of these functions is called iteratively at the
+ *                         appropriate periodic rate (aka the "slow loop").  The default period of
+ *                         the iterative robot is synced to the driver station control packets,
+ *                         giving a periodic frequency of about 50Hz (50 times per second).
+ *   - DisabledPeriodic()
+ *   - AutonomousPeriodic()
+ *   - TeleopPeriodic()
+ *   - TestPeriodic()
+ * 
+ */
+
+class IterativeRobot : public RobotBase
+{
+public:
+	/*
+	 * The default period for the periodic function calls (seconds)
+	 * Setting the period to 0.0 will cause the periodic functions to follow
+	 * the Driver Station packet rate of about 50Hz.
+	 */
+	static constexpr double kDefaultPeriod = 0.0;
+
+	virtual void StartCompetition();
+
+	virtual void RobotInit();
+	virtual void DisabledInit();
+	virtual void AutonomousInit();
+	virtual void TeleopInit();
+	virtual void TestInit();
+
+	virtual void DisabledPeriodic();
+	virtual void AutonomousPeriodic();
+	virtual void TeleopPeriodic();
+	virtual void TestPeriodic();
+
+protected:
+	virtual void Prestart();
+
+	virtual ~IterativeRobot();
+	IterativeRobot();
+
+private:
+	bool m_disabledInitialized;
+	bool m_autonomousInitialized;
+	bool m_teleopInitialized;
+	bool m_testInitialized;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Jaguar.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Jaguar.h
new file mode 100644
index 0000000..1cb7b69
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Jaguar.h
@@ -0,0 +1,28 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "SafePWM.h"
+#include "SpeedController.h"
+#include "PIDOutput.h"
+
+/**
+ * Luminary Micro / Vex Robotics Jaguar Speed Controller with PWM control
+ */
+class Jaguar : public SafePWM, public SpeedController
+{
+public:
+	explicit Jaguar(uint32_t channel);
+	virtual ~Jaguar();
+	virtual void Set(float value, uint8_t syncGroup = 0);
+	virtual float Get();
+	virtual void Disable();
+
+	virtual void PIDWrite(float output);
+
+private:
+	void InitJaguar();
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Joystick.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Joystick.h
new file mode 100644
index 0000000..7ee06f6
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Joystick.h
@@ -0,0 +1,93 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#ifndef JOYSTICK_H_
+#define JOYSTICK_H_
+
+#include <cstdint>
+#include "GenericHID.h"
+#include "ErrorBase.h"
+
+class DriverStation;
+
+/**
+ * Handle input from standard Joysticks connected to the Driver Station.
+ * This class handles standard input that comes from the Driver Station. Each time a value is requested
+ * the most recent value is returned. There is a single class instance for each joystick and the mapping
+ * of ports to hardware buttons depends on the code in the driver station.
+ */
+class Joystick : public GenericHID, public ErrorBase
+{
+public:
+	static const uint32_t kDefaultXAxis = 0;
+	static const uint32_t kDefaultYAxis = 1;
+	static const uint32_t kDefaultZAxis = 2;
+	static const uint32_t kDefaultTwistAxis = 2;
+	static const uint32_t kDefaultThrottleAxis = 3;
+	typedef enum
+	{
+		kXAxis, kYAxis, kZAxis, kTwistAxis, kThrottleAxis, kNumAxisTypes
+	} AxisType;
+	static const uint32_t kDefaultTriggerButton = 1;
+	static const uint32_t kDefaultTopButton = 2;
+	typedef enum
+	{
+		kTriggerButton, kTopButton, kNumButtonTypes
+	} ButtonType;
+	typedef enum
+	{
+		kLeftRumble, kRightRumble
+	} RumbleType;
+
+	explicit Joystick(uint32_t port);
+	Joystick(uint32_t port, uint32_t numAxisTypes, uint32_t numButtonTypes);
+	virtual ~Joystick();
+
+	uint32_t GetAxisChannel(AxisType axis);
+	void SetAxisChannel(AxisType axis, uint32_t channel);
+
+	virtual float GetX(JoystickHand hand = kRightHand);
+	virtual float GetY(JoystickHand hand = kRightHand);
+	virtual float GetZ();
+	virtual float GetTwist();
+	virtual float GetThrottle();
+	virtual float GetAxis(AxisType axis);
+	float GetRawAxis(uint32_t axis);
+
+	virtual bool GetTrigger(JoystickHand hand = kRightHand);
+	virtual bool GetTop(JoystickHand hand = kRightHand);
+	virtual bool GetBumper(JoystickHand hand = kRightHand);
+	virtual bool GetRawButton(uint32_t button);
+	virtual int GetPOV(uint32_t pov = 0);
+	bool GetButton(ButtonType button);
+	static Joystick* GetStickForPort(uint32_t port);
+
+	virtual float GetMagnitude();
+	virtual float GetDirectionRadians();
+	virtual float GetDirectionDegrees();
+
+	int GetAxisCount();
+	int GetButtonCount();
+	int GetPOVCount();
+	
+	void SetRumble(RumbleType type, float value);
+	void SetOutput(uint8_t outputNumber, bool value);
+	void SetOutputs(uint32_t value);
+
+private:
+	DISALLOW_COPY_AND_ASSIGN(Joystick);
+	void InitJoystick(uint32_t numAxisTypes, uint32_t numButtonTypes);
+
+	DriverStation *m_ds;
+	uint32_t m_port;
+	uint32_t *m_axes;
+	uint32_t *m_buttons;
+	uint32_t m_outputs;
+	uint16_t m_leftRumble;
+	uint16_t m_rightRumble;
+};
+
+#endif
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/MotorSafety.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/MotorSafety.h
new file mode 100644
index 0000000..ea7dfc4
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/MotorSafety.h
@@ -0,0 +1,20 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#define DEFAULT_SAFETY_EXPIRATION 0.1
+
+class MotorSafety
+{
+public:
+	virtual void SetExpiration(float timeout) = 0;
+	virtual float GetExpiration() = 0;
+	virtual bool IsAlive() = 0;
+	virtual void StopMotor() = 0;
+	virtual void SetSafetyEnabled(bool enabled) = 0;
+	virtual bool IsSafetyEnabled() = 0;
+	virtual void GetDescription(char *desc) = 0;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/MotorSafetyHelper.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/MotorSafetyHelper.h
new file mode 100644
index 0000000..4434263
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/MotorSafetyHelper.h
@@ -0,0 +1,35 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "ErrorBase.h"
+#include "HAL/cpp/Synchronized.hpp"
+
+class MotorSafety;
+
+class MotorSafetyHelper : public ErrorBase
+{
+public:
+	MotorSafetyHelper(MotorSafety *safeObject);
+	~MotorSafetyHelper();
+	void Feed();
+	void SetExpiration(float expirationTime);
+	float GetExpiration();
+	bool IsAlive();
+	void Check();
+	void SetSafetyEnabled(bool enabled);
+	bool IsSafetyEnabled();
+	static void CheckMotors();
+private:
+	double m_expiration;			// the expiration time for this object
+	bool m_enabled;					// true if motor safety is enabled for this motor
+	double m_stopTime; 				// the FPGA clock value when this motor has expired
+	ReentrantMutex m_syncMutex;			// protect accesses to the state for this object
+	MotorSafety *m_safeObject;		// the object that is using the helper
+	MotorSafetyHelper *m_nextHelper; // next object in the list of MotorSafetyHelpers
+	static MotorSafetyHelper *m_headHelper; // the head of the list of MotorSafetyHelper objects
+	static ReentrantMutex m_listMutex;	// protect accesses to the list of helpers
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/NIIMAQdx.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/NIIMAQdx.h
new file mode 100644
index 0000000..4940063
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/NIIMAQdx.h
@@ -0,0 +1,646 @@
+//==============================================================================

+//

+//  Title	  : NIIMAQdx.h

+//  Created	  : 1403685834 seconds after 1/1/1970 12:00:00 UTC 

+//  Copyright : © Copyright 2006, National Instruments Corporation, All rights reserved

+// 	Purpose	  : Include file for NI-IMAQdx library support.

+//

+//==============================================================================

+#ifndef ___niimaqdx_h___

+#define ___niimaqdx_h___

+

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+

+#if !defined(niimaqdx_types)

+#define niimaqdx_types

+

+#ifdef _CVI_

+    #pragma  EnableLibraryRuntimeChecking

+#endif

+

+//==============================================================================

+//  Typedefs

+//==============================================================================

+#ifndef _NI_uInt8_DEFINED_

+    #define _NI_uInt8_DEFINED_

+    typedef unsigned char       uInt8;

+#endif

+

+#ifndef _NI_uInt16_DEFINED_

+    #define _NI_uInt16_DEFINED_

+    typedef unsigned short int  uInt16;

+#endif

+

+#ifndef _NI_uInt32_DEFINED_

+    #define _NI_uInt32_DEFINED_

+    #if defined(_MSC_VER)

+        typedef unsigned long       uInt32;

+    #elif __GNUC__

+        #if __x86_64__

+            typedef unsigned int    uInt32;

+        #else

+            typedef unsigned long   uInt32;

+        #endif

+    #endif

+#endif

+

+#ifndef _NI_uInt64_DEFINED_

+    #define _NI_uInt64_DEFINED_

+    #if defined(_MSC_VER) || _CVI_ >= 700

+        typedef unsigned __int64    uInt64;

+    #elif __GNUC__

+        typedef unsigned long long  uInt64;

+    #endif

+#endif

+

+#ifndef _NI_Int8_DEFINED_

+    #define _NI_Int8_DEFINED_

+    typedef char                Int8;

+#endif

+

+#ifndef _NI_Int16_DEFINED_

+    #define _NI_Int16_DEFINED_

+    typedef short int           Int16;

+#endif

+

+#ifndef _NI_Int32_DEFINED_

+    #define _NI_Int32_DEFINED_

+    #if defined(_MSC_VER)

+        typedef long            Int32;

+    #elif __GNUC__

+        #if __x86_64__

+            typedef int         Int32;

+        #else

+            typedef long        Int32;

+        #endif

+    #endif

+#endif  

+

+#ifndef _NI_Int64_DEFINED_

+    #define _NI_Int64_DEFINED_

+    #if defined(_MSC_VER) || _CVI_ >= 700

+        typedef __int64        Int64;

+    #elif __GNUC__

+        typedef long long int  Int64;

+    #endif

+#endif

+

+#ifndef _NI_float32_DEFINED_

+    #define _NI_float32_DEFINED_

+    typedef float               float32;

+#endif

+

+#ifndef _NI_float64_DEFINED_

+    #define _NI_float64_DEFINED_

+    typedef double              float64;

+#endif

+

+#ifndef TRUE

+    #define TRUE                (1L)

+#endif

+

+#ifndef FALSE

+    #define FALSE               (0L)

+#endif

+

+#ifndef _NI_GUIDHNDL_DEFINED

+    typedef uInt32              GUIHNDL;

+#endif

+

+#if (defined(_MSC_VER) || defined(_CVI_))

+    #ifndef _NI_FUNC_DEFINED

+        #define NI_FUNC         __stdcall

+    #endif

+    

+    #ifndef _NI_FUNCC_DEFINED

+        #define NI_FUNCC        __cdecl

+    #endif

+#elif defined(__GNUC__)

+    #ifndef _NI_FUNC_DEFINED

+        #define NI_FUNC

+    #endif

+    

+    #ifndef _NI_FUNCC_DEFINED

+        #define NI_FUNCC

+    #endif

+#endif

+

+#ifndef _NI_bool32_DEFINED_

+    #define _NI_bool32_DEFINED_

+    typedef uInt32              bool32;

+#endif

+

+#ifndef _NI_IMAQdxSession_DEFINED_

+    #define _NI_IMAQdxSession_DEFINED_

+    typedef uInt32              IMAQdxSession;

+#endif

+

+#define IMAQDX_MAX_API_STRING_LENGTH 512

+

+//==============================================================================

+//  Forward Declare Data Structures

+//==============================================================================

+typedef struct Image_struct Image;

+

+

+//==============================================================================

+//  Error Codes Enumeration

+//==============================================================================

+typedef enum IMAQdxError_enum {

+    IMAQdxErrorSuccess = 0x0,                   // Success

+    IMAQdxErrorSystemMemoryFull = 0xBFF69000,   // Not enough memory

+    IMAQdxErrorInternal,                        // Internal error

+    IMAQdxErrorInvalidParameter,                // Invalid parameter

+    IMAQdxErrorInvalidPointer,                  // Invalid pointer

+    IMAQdxErrorInvalidInterface,                // Invalid camera session

+    IMAQdxErrorInvalidRegistryKey,              // Invalid registry key

+    IMAQdxErrorInvalidAddress,                  // Invalid address

+    IMAQdxErrorInvalidDeviceType,               // Invalid device type

+    IMAQdxErrorNotImplemented,                  // Not implemented

+    IMAQdxErrorCameraNotFound,                  // Camera not found

+    IMAQdxErrorCameraInUse,                     // Camera is already in use.

+    IMAQdxErrorCameraNotInitialized,            // Camera is not initialized.

+    IMAQdxErrorCameraRemoved,                   // Camera has been removed.

+    IMAQdxErrorCameraRunning,                   // Acquisition in progress.

+    IMAQdxErrorCameraNotRunning,                // No acquisition in progress.

+    IMAQdxErrorAttributeNotSupported,           // Attribute not supported by the camera.

+    IMAQdxErrorAttributeNotSettable,            // Unable to set attribute.

+    IMAQdxErrorAttributeNotReadable,            // Unable to get attribute.

+    IMAQdxErrorAttributeOutOfRange,             // Attribute value is out of range.

+    IMAQdxErrorBufferNotAvailable,              // Requested buffer is unavailable.

+    IMAQdxErrorBufferListEmpty,                 // Buffer list is empty. Add one or more buffers.

+    IMAQdxErrorBufferListLocked,                // Buffer list is already locked. Reconfigure acquisition and try again.

+    IMAQdxErrorBufferListNotLocked,             // No buffer list. Reconfigure acquisition and try again.

+    IMAQdxErrorResourcesAllocated,              // Transfer engine resources already allocated. Reconfigure acquisition and try again.

+    IMAQdxErrorResourcesUnavailable,            // Insufficient transfer engine resources.

+    IMAQdxErrorAsyncWrite,                      // Unable to perform asychronous register write.

+    IMAQdxErrorAsyncRead,                       // Unable to perform asychronous register read.

+    IMAQdxErrorTimeout,                         // Timeout.

+    IMAQdxErrorBusReset,                        // Bus reset occurred during a transaction.

+    IMAQdxErrorInvalidXML,                      // Unable to load camera's XML file.

+    IMAQdxErrorFileAccess,                      // Unable to read/write to file.

+    IMAQdxErrorInvalidCameraURLString,          // Camera has malformed URL string.

+    IMAQdxErrorInvalidCameraFile,               // Invalid camera file.

+    IMAQdxErrorGenICamError,                    // Unknown Genicam error.

+    IMAQdxErrorFormat7Parameters,               // For format 7: The combination of speed, image position, image size, and color coding is incorrect.

+    IMAQdxErrorInvalidAttributeType,            // The attribute type is not compatible with the passed variable type.

+    IMAQdxErrorDLLNotFound,                     // The DLL could not be found.

+    IMAQdxErrorFunctionNotFound,                // The function could not be found.

+    IMAQdxErrorLicenseNotActivated,             // License not activated.

+    IMAQdxErrorCameraNotConfiguredForListener,  // The camera is not configured properly to support a listener.

+    IMAQdxErrorCameraMulticastNotAvailable,     // Unable to configure the system for multicast support.

+    IMAQdxErrorBufferHasLostPackets,            // The requested buffer has lost packets and the user requested an error to be generated.

+    IMAQdxErrorGiGEVisionError,                 // Unknown GiGE Vision error.

+    IMAQdxErrorNetworkError,                    // Unknown network error.

+    IMAQdxErrorCameraUnreachable,               // Unable to connect to the camera.

+    IMAQdxErrorHighPerformanceNotSupported,     // High performance acquisition is not supported on the specified network interface. Connect the camera to a network interface running the high performance driver.

+    IMAQdxErrorInterfaceNotRenamed,             // Unable to rename interface. Invalid or duplicate name specified.

+    IMAQdxErrorNoSupportedVideoModes,           // The camera does not have any video modes which are supported.

+    IMAQdxErrorSoftwareTriggerOverrun,          // Software trigger overrun.

+    IMAQdxErrorTestPacketNotReceived,           // The system did not receive a test packet from the camera. The packet size may be too large for the network configuration or a firewall may be enabled.

+    IMAQdxErrorCorruptedImageReceived,          // The camera returned a corrupted image.

+    IMAQdxErrorCameraConfigurationHasChanged,   // The camera did not return an image of the correct type it was configured for previously.

+    IMAQdxErrorCameraInvalidAuthentication,     // The camera is configured with password authentication and either the user name and password were not configured or they are incorrect.

+    IMAQdxErrorUnknownHTTPError,                // The camera returned an unknown HTTP error.

+    IMAQdxErrorKernelDriverUnavailable,         // Unable to attach to the kernel mode driver.

+    IMAQdxErrorPixelFormatDecoderUnavailable,   // No decoder available for selected pixel format.

+    IMAQdxErrorFirmwareUpdateNeeded,            // The acquisition hardware needs a firmware update before it can be used.

+    IMAQdxErrorFirmwareUpdateRebootNeeded,      // The firmware on the acquisition hardware has been updated and the system must be rebooted before use.

+    IMAQdxErrorLightingCurrentOutOfRange,       // The requested current level from the lighting controller is not possible.

+    IMAQdxErrorUSB3VisionError,                 // Unknown USB3 Vision error.

+    IMAQdxErrorInvalidU3VUSBDescriptor,         // The camera has a USB descriptor that is incompatible with the USB3 Vision specification.

+    IMAQdxErrorU3VInvalidControlInterface,      // The USB3 Vision control interface is not implemented or is invalid on this camera.

+    IMAQdxErrorU3VControlInterfaceError,        // There was an error from the control interface of the USB3 Vision camera.

+    IMAQdxErrorU3VInvalidEventInterface,        // The USB3 Vision event interface is not implemented or is invalid on this camera.

+    IMAQdxErrorU3VEventInterfaceError,          // There was an error from the event interface of the USB3 Vision camera.

+    IMAQdxErrorU3VInvalidStreamInterface,       // The USB3 Vision stream interface is not implemented or is invalid on this camera.

+    IMAQdxErrorU3VStreamInterfaceError,         // There was an error from the stream interface of the USB3 Vision camera.

+    IMAQdxErrorU3VUnsupportedConnectionSpeed,   // The USB connection speed is not supported by the camera.  Check whether the camera is plugged into a USB 2.0 port instead of a USB 3.0 port.  If so, verify that the camera supports this use case.       

+    IMAQdxErrorU3VInsufficientPower,            // The USB3 Vision camera requires more current than can be supplied by the USB port in use.

+    IMAQdxErrorU3VInvalidMaxCurrent,            // The U3V_MaximumCurrentUSB20_mA registry value is not valid for the connected USB3 Vision camera.

+    IMAQdxErrorBufferIncompleteData,            // The requested buffer has incomplete data and the user requested an error to be generated.

+    IMAQdxErrorCameraAcquisitionConfigFailed,   // The camera returned an error starting the acquisition.

+    IMAQdxErrorCameraClosePending,              // The camera still has outstanding references and will be closed when these operations complete.

+    IMAQdxErrorSoftwareFault,                   // An unexpected software error occurred.

+    IMAQdxErrorCameraPropertyInvalid,           // The value for an invalid camera property was requested.

+    IMAQdxErrorJumboFramesNotEnabled,           // Jumbo frames are not enabled on the host.  Maximum packet size is 1500 bytes.

+    IMAQdxErrorBayerPixelFormatNotSelected,     // This operation requires that the camera has a Bayer pixel format selected.

+    IMAQdxErrorGuard = 0xFFFFFFFF,

+} IMAQdxError;

+

+

+//==============================================================================

+//  Bus Type Enumeration

+//==============================================================================

+typedef enum IMAQdxBusType_enum {

+    IMAQdxBusTypeFireWire = 0x31333934,

+    IMAQdxBusTypeEthernet = 0x69707634,

+    IMAQdxBusTypeSimulator = 0x2073696D,

+    IMAQdxBusTypeDirectShow = 0x64736877,

+    IMAQdxBusTypeIP = 0x4950636D,

+    IMAQdxBusTypeSmartCam2 = 0x53436132,

+    IMAQdxBusTypeUSB3Vision = 0x55534233,

+    IMAQdxBusTypeUVC = 0x55564320,

+    IMAQdxBusTypeGuard = 0xFFFFFFFF,

+} IMAQdxBusType;

+

+

+//==============================================================================

+//  Camera Control Mode Enumeration

+//==============================================================================

+typedef enum IMAQdxCameraControlMode_enum {

+    IMAQdxCameraControlModeController,

+    IMAQdxCameraControlModeListener,

+    IMAQdxCameraControlModeGuard = 0xFFFFFFFF,

+} IMAQdxCameraControlMode;

+

+

+//==============================================================================

+//  Buffer Number Mode Enumeration

+//==============================================================================

+typedef enum IMAQdxBufferNumberMode_enum {

+    IMAQdxBufferNumberModeNext,

+    IMAQdxBufferNumberModeLast,

+    IMAQdxBufferNumberModeBufferNumber,

+    IMAQdxBufferNumberModeGuard = 0xFFFFFFFF,

+} IMAQdxBufferNumberMode;

+

+

+//==============================================================================

+//  Plug n Play Event Enumeration

+//==============================================================================

+typedef enum IMAQdxPnpEvent_enum {

+    IMAQdxPnpEventCameraAttached,

+    IMAQdxPnpEventCameraDetached,

+    IMAQdxPnpEventBusReset,

+    IMAQdxPnpEventGuard = 0xFFFFFFFF,

+} IMAQdxPnpEvent;

+

+

+//==============================================================================

+//  Bayer Pattern Enumeration

+//==============================================================================

+typedef enum IMAQdxBayerPattern_enum {

+    IMAQdxBayerPatternNone,

+    IMAQdxBayerPatternGB,

+    IMAQdxBayerPatternGR,

+    IMAQdxBayerPatternBG,

+    IMAQdxBayerPatternRG,

+    IMAQdxBayerPatternHardware,

+    IMAQdxBayerPatternGuard = 0xFFFFFFFF,

+} IMAQdxBayerPattern;

+

+

+//==============================================================================

+//  Bayer Decode Algorithm Enumeration

+//==============================================================================

+typedef enum IMAQdxBayerAlgorithm_enum {

+    IMAQdxBayerAlgorithmBilinear,

+    IMAQdxBayerAlgorithmVNG,

+    IMAQdxBayerAlgorithmGuard = 0xFFFFFFFF,

+} IMAQdxBayerAlgorithm;

+

+

+//==============================================================================

+//  Output Image Types -- Values match Vision Development Module image types

+//==============================================================================

+typedef enum IMAQdxOutputImageType_enum {

+    IMAQdxOutputImageTypeU8    = 0,

+    IMAQdxOutputImageTypeI16   = 1,

+    IMAQdxOutputImageTypeU16   = 7,

+    IMAQdxOutputImageTypeRGB32 = 4,

+    IMAQdxOutputImageTypeRGB64 = 6,

+    IMAQdxOutputImageTypeAuto  = 0x7FFFFFFF,

+    IMAQdxOutputImageTypeGuard = 0xFFFFFFFF,

+} IMAQdxOutputImageType;

+

+

+//==============================================================================

+//  Controller Destination Mode Enumeration

+//==============================================================================

+typedef enum IMAQdxDestinationMode_enum {

+    IMAQdxDestinationModeUnicast,

+    IMAQdxDestinationModeBroadcast,

+    IMAQdxDestinationModeMulticast,

+    IMAQdxDestinationModeGuard = 0xFFFFFFFF,

+} IMAQdxDestinationMode;

+

+

+//==============================================================================

+//   Attribute Type Enumeration

+//==============================================================================

+typedef enum IMAQdxAttributeType_enum {    

+    IMAQdxAttributeTypeU32,

+    IMAQdxAttributeTypeI64,

+    IMAQdxAttributeTypeF64,

+    IMAQdxAttributeTypeString,

+    IMAQdxAttributeTypeEnum,

+    IMAQdxAttributeTypeBool,

+    IMAQdxAttributeTypeCommand,

+    IMAQdxAttributeTypeBlob,

+    IMAQdxAttributeTypeGuard = 0xFFFFFFFF,

+} IMAQdxAttributeType;

+

+

+//==============================================================================

+//  Value Type Enumeration

+//==============================================================================

+typedef enum IMAQdxValueType_enum {    

+    IMAQdxValueTypeU32,

+    IMAQdxValueTypeI64,

+    IMAQdxValueTypeF64,

+    IMAQdxValueTypeString,

+    IMAQdxValueTypeEnumItem,

+    IMAQdxValueTypeBool,

+    IMAQdxValueTypeDisposableString,

+    IMAQdxValueTypeGuard = 0xFFFFFFFF,

+} IMAQdxValueType;

+

+

+//==============================================================================

+//  Interface File Flags Enumeration

+//==============================================================================

+typedef enum IMAQdxInterfaceFileFlags_enum {

+    IMAQdxInterfaceFileFlagsConnected = 0x1,

+    IMAQdxInterfaceFileFlagsDirty = 0x2,

+    IMAQdxInterfaceFileFlagsGuard = 0xFFFFFFFF,

+} IMAQdxInterfaceFileFlags;

+

+

+//==============================================================================

+//  Overwrite Mode Enumeration

+//==============================================================================

+typedef enum IMAQdxOverwriteMode_enum {

+    IMAQdxOverwriteModeGetOldest = 0x0,

+    IMAQdxOverwriteModeFail = 0x2,

+    IMAQdxOverwriteModeGetNewest = 0x3,

+    IMAQdxOverwriteModeGuard = 0xFFFFFFFF,

+} IMAQdxOverwriteMode;

+

+

+//==============================================================================

+//  Incomplete Buffer Mode Enumeration

+//==============================================================================

+typedef enum IMAQdxIncompleteBufferMode_enum {

+    IMAQdxIncompleteBufferModeIgnore,

+    IMAQdxIncompleteBufferModeFail,

+    IMAQdxIncompleteBufferModeGuard = 0xFFFFFFFF,

+} IMAQdxIncompleteBufferMode;

+

+

+//==============================================================================

+//  Lost Packet Mode Enumeration

+//==============================================================================

+typedef enum IMAQdxLostPacketMode_enum {

+    IMAQdxLostPacketModeIgnore,

+    IMAQdxLostPacketModeFail,

+    IMAQdxLostPacketModeGuard = 0xFFFFFFFF,

+} IMAQdxLostPacketMode;

+

+

+//==============================================================================

+//  Attribute Visibility Enumeration

+//==============================================================================

+typedef enum IMAQdxAttributeVisibility_enum {

+    IMAQdxAttributeVisibilitySimple = 0x00001000,

+    IMAQdxAttributeVisibilityIntermediate = 0x00002000,

+    IMAQdxAttributeVisibilityAdvanced = 0x00004000,

+    IMAQdxAttributeVisibilityGuard = 0xFFFFFFFF,

+} IMAQdxAttributeVisibility;

+

+

+//==============================================================================

+//  Stream Channel Mode Enumeration

+//==============================================================================

+typedef enum IMAQdxStreamChannelMode_enum {

+    IMAQdxStreamChannelModeAutomatic,

+    IMAQdxStreamChannelModeManual,

+    IMAQdxStreamChannelModeGuard = 0xFFFFFFFF,

+} IMAQdxStreamChannelMode;

+

+

+//==============================================================================

+//  Pixel Signedness Enumeration

+//==============================================================================

+typedef enum IMAQdxPixelSignedness_enum {

+    IMAQdxPixelSignednessUnsigned,

+    IMAQdxPixelSignednessSigned,

+    IMAQdxPixelSignednessHardware,

+    IMAQdxPixelSignednessGuard = 0xFFFFFFFF,

+} IMAQdxPixelSignedness;

+

+

+//==============================================================================

+//  USB Connection Speed Enumeration

+//==============================================================================

+typedef enum IMAQdxUSBConnectionSpeed_enum {

+    IMAQdxUSBConnectionSpeedLow = 1,

+    IMAQdxUSBConnectionSpeedFull = 2,

+    IMAQdxUSBConnectionSpeedHigh = 4,

+    IMAQdxUSBConnectionSpeedSuper = 8,

+    IMAQdxUSBConnectionSpeedGuard = 0xFFFFFFFF,

+} IMAQdxUSBConnectionSpeed;

+

+

+//==============================================================================

+//  CVI Structures

+//==============================================================================

+#pragma pack(push, 4)

+

+

+//==============================================================================

+//  Camera Information Structure

+//==============================================================================

+typedef struct IMAQdxCameraInformation_struct {

+    uInt32 Type;

+    uInt32 Version;

+    uInt32 Flags;

+    uInt32 SerialNumberHi;

+    uInt32 SerialNumberLo;

+    IMAQdxBusType BusType;

+    char InterfaceName[IMAQDX_MAX_API_STRING_LENGTH];

+    char VendorName[IMAQDX_MAX_API_STRING_LENGTH];

+    char ModelName[IMAQDX_MAX_API_STRING_LENGTH];

+    char CameraFileName[IMAQDX_MAX_API_STRING_LENGTH];

+    char CameraAttributeURL[IMAQDX_MAX_API_STRING_LENGTH];

+} IMAQdxCameraInformation;

+

+

+//==============================================================================

+//  Camera File Structure

+//==============================================================================

+typedef struct IMAQdxCameraFile_struct {

+    uInt32 Type;

+    uInt32 Version;

+    char FileName[IMAQDX_MAX_API_STRING_LENGTH];

+} IMAQdxCameraFile;

+

+

+//==============================================================================

+//  Attribute Information Structure

+//==============================================================================

+typedef struct IMAQdxAttributeInformation_struct {

+    IMAQdxAttributeType Type;

+    bool32 Readable;

+    bool32 Writable;

+    char Name[IMAQDX_MAX_API_STRING_LENGTH];

+} IMAQdxAttributeInformation;

+

+

+//==============================================================================

+//  Enumeration Item Structure

+//==============================================================================

+typedef struct IMAQdxEnumItem_struct {

+    uInt32 Value;

+    uInt32 Reserved;

+    char Name[IMAQDX_MAX_API_STRING_LENGTH];

+} IMAQdxEnumItem;

+

+

+//==============================================================================

+//  Camera Information Structure

+//==============================================================================

+typedef IMAQdxEnumItem IMAQdxVideoMode;

+

+

+#pragma pack(pop)

+

+

+//==============================================================================

+//  Callbacks

+//==============================================================================

+typedef     uInt32 (NI_FUNC *FrameDoneEventCallbackPtr)(IMAQdxSession id, uInt32 bufferNumber, void* callbackData);

+typedef     uInt32 (NI_FUNC *PnpEventCallbackPtr)(IMAQdxSession id, IMAQdxPnpEvent pnpEvent, void* callbackData);

+typedef     void (NI_FUNC *AttributeUpdatedEventCallbackPtr)(IMAQdxSession id, const char* name, void* callbackData);

+

+#endif //niimaqdx_types

+//==============================================================================

+//  Attributes

+//==============================================================================

+#define IMAQdxAttributeBaseAddress               "CameraInformation::BaseAddress"         // Read only. Gets the base address of the camera registers.

+#define IMAQdxAttributeBusType                   "CameraInformation::BusType"             // Read only. Gets the bus type of the camera.

+#define IMAQdxAttributeModelName                 "CameraInformation::ModelName"           // Read only. Returns the model name.

+#define IMAQdxAttributeSerialNumberHigh          "CameraInformation::SerialNumberHigh"    // Read only. Gets the upper 32-bits of the camera 64-bit serial number.

+#define IMAQdxAttributeSerialNumberLow           "CameraInformation::SerialNumberLow"     // Read only. Gets the lower 32-bits of the camera 64-bit serial number.

+#define IMAQdxAttributeVendorName                "CameraInformation::VendorName"          // Read only. Returns the vendor name.

+#define IMAQdxAttributeHostIPAddress             "CameraInformation::HostIPAddress"       // Read only. Returns the host adapter IP address.

+#define IMAQdxAttributeIPAddress                 "CameraInformation::IPAddress"           // Read only. Returns the IP address.

+#define IMAQdxAttributePrimaryURLString          "CameraInformation::PrimaryURLString"    // Read only. Gets the camera's primary URL string.

+#define IMAQdxAttributeSecondaryURLString        "CameraInformation::SecondaryURLString"  // Read only. Gets the camera's secondary URL string.

+#define IMAQdxAttributeAcqInProgress             "StatusInformation::AcqInProgress"       // Read only. Gets the current state of the acquisition. TRUE if acquiring; otherwise FALSE.

+#define IMAQdxAttributeLastBufferCount           "StatusInformation::LastBufferCount"     // Read only. Gets the number of transferred buffers.

+#define IMAQdxAttributeLastBufferNumber          "StatusInformation::LastBufferNumber"    // Read only. Gets the last cumulative buffer number transferred.

+#define IMAQdxAttributeLostBufferCount           "StatusInformation::LostBufferCount"     // Read only. Gets the number of lost buffers during an acquisition session.

+#define IMAQdxAttributeLostPacketCount           "StatusInformation::LostPacketCount"     // Read only. Gets the number of lost packets during an acquisition session.

+#define IMAQdxAttributeRequestedResendPackets    "StatusInformation::RequestedResendPacketCount" // Read only. Gets the number of packets requested to be resent during an acquisition session.

+#define IMAQdxAttributeReceivedResendPackets     "StatusInformation::ReceivedResendPackets" // Read only. Gets the number of packets that were requested to be resent during an acquisition session and were completed.

+#define IMAQdxAttributeHandledEventCount         "StatusInformation::HandledEventCount"   // Read only. Gets the number of handled events during an acquisition session.

+#define IMAQdxAttributeLostEventCount            "StatusInformation::LostEventCount"      // Read only. Gets the number of lost events during an acquisition session.

+#define IMAQdxAttributeBayerGainB                "AcquisitionAttributes::Bayer::GainB"    // Sets/gets the white balance gain for the blue component of the Bayer conversion.

+#define IMAQdxAttributeBayerGainG                "AcquisitionAttributes::Bayer::GainG"    // Sets/gets the white balance gain for the green component of the Bayer conversion.

+#define IMAQdxAttributeBayerGainR                "AcquisitionAttributes::Bayer::GainR"    // Sets/gets the white balance gain for the red component of the Bayer conversion.

+#define IMAQdxAttributeBayerPattern              "AcquisitionAttributes::Bayer::Pattern"  // Sets/gets the Bayer pattern to use.

+#define IMAQdxAttributeStreamChannelMode         "AcquisitionAttributes::Controller::StreamChannelMode" // Gets/sets the mode for allocating a FireWire stream channel.

+#define IMAQdxAttributeDesiredStreamChannel      "AcquisitionAttributes::Controller::DesiredStreamChannel" // Gets/sets the stream channel to manually allocate.

+#define IMAQdxAttributeFrameInterval             "AcquisitionAttributes::FrameInterval"   // Read only. Gets the duration in milliseconds between successive frames.

+#define IMAQdxAttributeIgnoreFirstFrame          "AcquisitionAttributes::IgnoreFirstFrame" // Gets/sets the video delay of one frame between starting the camera and receiving the video feed.

+#define IMAQdxAttributeOffsetX                   "OffsetX"                                // Gets/sets the left offset of the image.

+#define IMAQdxAttributeOffsetY                   "OffsetY"                                // Gets/sets the top offset of the image.

+#define IMAQdxAttributeWidth                     "Width"                                  // Gets/sets the width of the image.

+#define IMAQdxAttributeHeight                    "Height"                                 // Gets/sets the height of the image.

+#define IMAQdxAttributePixelFormat               "PixelFormat"                            // Gets/sets the pixel format of the source sensor.

+#define IMAQdxAttributePacketSize                "PacketSize"                             // Gets/sets the packet size in bytes.

+#define IMAQdxAttributePayloadSize               "PayloadSize"                            // Gets/sets the frame size in bytes.

+#define IMAQdxAttributeSpeed                     "AcquisitionAttributes::Speed"           // Gets/sets the transfer speed in Mbps for a FireWire packet.

+#define IMAQdxAttributeShiftPixelBits            "AcquisitionAttributes::ShiftPixelBits"  // Gets/sets the alignment of 16-bit cameras. Downshift the pixel bits if the camera returns most significant bit-aligned data.

+#define IMAQdxAttributeSwapPixelBytes            "AcquisitionAttributes::SwapPixelBytes"  // Gets/sets the endianness of 16-bit cameras. Swap the pixel bytes if the camera returns little endian data.

+#define IMAQdxAttributeOverwriteMode             "AcquisitionAttributes::OverwriteMode"   // Gets/sets the overwrite mode, used to determine acquisition when an image transfer cannot be completed due to an overwritten internal buffer.

+#define IMAQdxAttributeTimeout                   "AcquisitionAttributes::Timeout"         // Gets/sets the timeout value in milliseconds, used to abort an acquisition when the image transfer cannot be completed within the delay.

+#define IMAQdxAttributeVideoMode                 "AcquisitionAttributes::VideoMode"       // Gets/sets the video mode for a camera.

+#define IMAQdxAttributeBitsPerPixel              "AcquisitionAttributes::BitsPerPixel"    // Gets/sets the actual bits per pixel. For 16-bit components, this represents the actual bit depth (10-, 12-, 14-, or 16-bit).

+#define IMAQdxAttributePixelSignedness           "AcquisitionAttributes::PixelSignedness" // Gets/sets the signedness of the pixel. For 16-bit components, this represents the actual pixel signedness (Signed, or Unsigned).

+#define IMAQdxAttributeReserveDualPackets        "AcquisitionAttributes::ReserveDualPackets" // Gets/sets if dual packets will be reserved for a very large FireWire packet.

+#define IMAQdxAttributeReceiveTimestampMode      "AcquisitionAttributes::ReceiveTimestampMode" // Gets/sets the mode for timestamping images received by the driver.

+#define IMAQdxAttributeActualPeakBandwidth       "AcquisitionAttributes::AdvancedEthernet::BandwidthControl::ActualPeakBandwidth" // Read only. Returns the actual maximum peak bandwidth the camera will be configured to use.

+#define IMAQdxAttributeDesiredPeakBandwidth      "AcquisitionAttributes::AdvancedEthernet::BandwidthControl::DesiredPeakBandwidth" // Gets/sets the desired maximum peak bandwidth the camera should use.

+#define IMAQdxAttributeDestinationMode           "AcquisitionAttributes::AdvancedEthernet::Controller::DestinationMode" // Gets/Sets where the camera is instructed to send the image stream.

+#define IMAQdxAttributeDestinationMulticastAddress "AcquisitionAttributes::AdvancedEthernet::Controller::DestinationMulticastAddress" // Gets/Sets the multicast address the camera should send data in multicast mode.

+#define IMAQdxAttributeEventsEnabled             "AcquisitionAttributes::AdvancedEthernet::EventParameters::EventsEnabled" // Gets/Sets if events will be handled.

+#define IMAQdxAttributeMaxOutstandingEvents      "AcquisitionAttributes::AdvancedEthernet::EventParameters::MaxOutstandingEvents" // Gets/Sets the maximum number of outstanding events to queue.

+#define IMAQdxAttributeTestPacketEnabled         "AcquisitionAttributes::AdvancedEthernet::TestPacketParameters::TestPacketEnabled" // Gets/Sets whether the driver will validate the image streaming settings using test packets prior to an acquisition

+#define IMAQdxAttributeTestPacketTimeout         "AcquisitionAttributes::AdvancedEthernet::TestPacketParameters::TestPacketTimeout" // Gets/Sets the timeout for validating test packet reception (if enabled)

+#define IMAQdxAttributeMaxTestPacketRetries      "AcquisitionAttributes::AdvancedEthernet::TestPacketParameters::MaxTestPacketRetries" // Gets/Sets the number of retries for validating test packet reception (if enabled)

+#define IMAQdxAttributeChunkDataDecodingEnabled  "AcquisitionAttributes::ChunkDataDecoding::ChunkDataDecodingEnabled" // Gets/Sets whether the driver will decode any chunk data in the image stream

+#define IMAQdxAttributeChunkDataDecodingMaxElementSize "AcquisitionAttributes::ChunkDataDecoding::MaximumChunkCopySize" // Gets/Sets the maximum size of any single chunk data element that will be made available

+#define IMAQdxAttributeLostPacketMode            "AcquisitionAttributes::AdvancedEthernet::LostPacketMode" // Gets/sets the behavior when the user extracts a buffer that has missing packets.

+#define IMAQdxAttributeMemoryWindowSize          "AcquisitionAttributes::AdvancedEthernet::ResendParameters::MemoryWindowSize" // Gets/sets the size of the memory window of the camera in kilobytes. Should match the camera's internal buffer size.

+#define IMAQdxAttributeResendsEnabled            "AcquisitionAttributes::AdvancedEthernet::ResendParameters::ResendsEnabled" // Gets/sets if resends will be issued for missing packets.

+#define IMAQdxAttributeResendThresholdPercentage "AcquisitionAttributes::AdvancedEthernet::ResendParameters::ResendThresholdPercentage" // Gets/sets the threshold of the packet processing window that will trigger packets to be resent.

+#define IMAQdxAttributeResendBatchingPercentage  "AcquisitionAttributes::AdvancedEthernet::ResendParameters::ResendBatchingPercentage" // Gets/sets the percent of the packet resend threshold that will be issued as one group past the initial threshold sent in a single request.

+#define IMAQdxAttributeMaxResendsPerPacket       "AcquisitionAttributes::AdvancedEthernet::ResendParameters::MaxResendsPerPacket" // Gets/sets the maximum number of resend requests that will be issued for a missing packet.

+#define IMAQdxAttributeResendResponseTimeout     "AcquisitionAttributes::AdvancedEthernet::ResendParameters::ResendResponseTimeout" // Gets/sets the time to wait for a resend request to be satisfied before sending another.

+#define IMAQdxAttributeNewPacketTimeout          "AcquisitionAttributes::AdvancedEthernet::ResendParameters::NewPacketTimeout" // Gets/sets the time to wait for new packets to arrive in a partially completed image before assuming the rest of the image was lost.

+#define IMAQdxAttributeMissingPacketTimeout      "AcquisitionAttributes::AdvancedEthernet::ResendParameters::MissingPacketTimeout" // Gets/sets the time to wait for a missing packet before issuing a resend.

+#define IMAQdxAttributeResendTimerResolution     "AcquisitionAttributes::AdvancedEthernet::ResendParameters::ResendTimerResolution" // Gets/sets the resolution of the packet processing system that is used for all packet-related timeouts.

+

+

+//==============================================================================

+//  Functions

+//==============================================================================

+IMAQdxError NI_FUNC IMAQdxSnap(IMAQdxSession id, Image* image);

+IMAQdxError NI_FUNC IMAQdxConfigureGrab(IMAQdxSession id);

+IMAQdxError NI_FUNC IMAQdxGrab(IMAQdxSession id, Image* image, bool32 waitForNextBuffer, uInt32* actualBufferNumber);

+IMAQdxError NI_FUNC IMAQdxSequence(IMAQdxSession id, Image* images[], uInt32 count);

+IMAQdxError NI_FUNC IMAQdxDiscoverEthernetCameras(const char* address, uInt32 timeout);

+IMAQdxError NI_FUNC IMAQdxEnumerateCameras(IMAQdxCameraInformation cameraInformationArray[], uInt32* count, bool32 connectedOnly);

+IMAQdxError NI_FUNC IMAQdxResetCamera(const char* name, bool32 resetAll);

+IMAQdxError NI_FUNC IMAQdxOpenCamera(const char* name, IMAQdxCameraControlMode mode, IMAQdxSession* id);

+IMAQdxError NI_FUNC IMAQdxCloseCamera(IMAQdxSession id);

+IMAQdxError NI_FUNC IMAQdxConfigureAcquisition(IMAQdxSession id, bool32 continuous, uInt32 bufferCount);

+IMAQdxError NI_FUNC IMAQdxStartAcquisition(IMAQdxSession id);

+IMAQdxError NI_FUNC IMAQdxGetImage(IMAQdxSession id, Image* image, IMAQdxBufferNumberMode mode, uInt32 desiredBufferNumber, uInt32* actualBufferNumber);

+IMAQdxError NI_FUNC IMAQdxGetImageData(IMAQdxSession id, void* buffer, uInt32 bufferSize, IMAQdxBufferNumberMode mode, uInt32 desiredBufferNumber, uInt32* actualBufferNumber);

+IMAQdxError NI_FUNC IMAQdxStopAcquisition(IMAQdxSession id);

+IMAQdxError NI_FUNC IMAQdxUnconfigureAcquisition(IMAQdxSession id);

+IMAQdxError NI_FUNC IMAQdxEnumerateVideoModes(IMAQdxSession id, IMAQdxVideoMode videoModeArray[], uInt32* count, uInt32* currentMode);

+IMAQdxError NI_FUNC IMAQdxEnumerateAttributes(IMAQdxSession id, IMAQdxAttributeInformation attributeInformationArray[], uInt32* count, const char* root);

+IMAQdxError NI_FUNC IMAQdxGetAttribute(IMAQdxSession id, const char* name, IMAQdxValueType type, void* value);

+IMAQdxError NI_FUNCC IMAQdxSetAttribute(IMAQdxSession id, const char* name, IMAQdxValueType type, ...);

+IMAQdxError NI_FUNC IMAQdxGetAttributeMinimum(IMAQdxSession id, const char* name, IMAQdxValueType type, void* value);

+IMAQdxError NI_FUNC IMAQdxGetAttributeMaximum(IMAQdxSession id, const char* name, IMAQdxValueType type, void* value);

+IMAQdxError NI_FUNC IMAQdxGetAttributeIncrement(IMAQdxSession id, const char* name, IMAQdxValueType type, void* value);

+IMAQdxError NI_FUNC IMAQdxGetAttributeType(IMAQdxSession id, const char* name, IMAQdxAttributeType* type);

+IMAQdxError NI_FUNC IMAQdxIsAttributeReadable(IMAQdxSession id, const char* name, bool32* readable);

+IMAQdxError NI_FUNC IMAQdxIsAttributeWritable(IMAQdxSession id, const char* name, bool32* writable);

+IMAQdxError NI_FUNC IMAQdxEnumerateAttributeValues(IMAQdxSession id, const char* name, IMAQdxEnumItem list[], uInt32* size);

+IMAQdxError NI_FUNC IMAQdxGetAttributeTooltip(IMAQdxSession id, const char* name, char* tooltip, uInt32 length);

+IMAQdxError NI_FUNC IMAQdxGetAttributeUnits(IMAQdxSession id, const char* name, char* units, uInt32 length);

+IMAQdxError NI_FUNC IMAQdxRegisterFrameDoneEvent(IMAQdxSession id, uInt32 bufferInterval, FrameDoneEventCallbackPtr callbackFunction, void* callbackData);

+IMAQdxError NI_FUNC IMAQdxRegisterPnpEvent(IMAQdxSession id, IMAQdxPnpEvent event, PnpEventCallbackPtr callbackFunction, void* callbackData);

+IMAQdxError NI_FUNC IMAQdxWriteRegister(IMAQdxSession id, uInt32 offset, uInt32 value);

+IMAQdxError NI_FUNC IMAQdxReadRegister(IMAQdxSession id, uInt32 offset, uInt32* value);

+IMAQdxError NI_FUNC IMAQdxWriteMemory(IMAQdxSession id, uInt32 offset, const char* values, uInt32 count);

+IMAQdxError NI_FUNC IMAQdxReadMemory(IMAQdxSession id, uInt32 offset, char* values, uInt32 count);

+IMAQdxError NI_FUNC IMAQdxGetErrorString(IMAQdxError error, char* message, uInt32 messageLength);

+IMAQdxError NI_FUNC IMAQdxWriteAttributes(IMAQdxSession id, const char* filename);

+IMAQdxError NI_FUNC IMAQdxReadAttributes(IMAQdxSession id, const char* filename);

+IMAQdxError NI_FUNC IMAQdxResetEthernetCameraAddress(const char* name, const char* address, const char* subnet, const char* gateway, uInt32 timeout);

+IMAQdxError NI_FUNC IMAQdxEnumerateAttributes2(IMAQdxSession id, IMAQdxAttributeInformation attributeInformationArray[], uInt32* count, const char* root, IMAQdxAttributeVisibility visibility);

+IMAQdxError NI_FUNC IMAQdxGetAttributeVisibility(IMAQdxSession id, const char* name, IMAQdxAttributeVisibility* visibility);

+IMAQdxError NI_FUNC IMAQdxGetAttributeDescription(IMAQdxSession id, const char* name, char* description, uInt32 length);

+IMAQdxError NI_FUNC IMAQdxGetAttributeDisplayName(IMAQdxSession id, const char* name, char* displayName, uInt32 length);

+IMAQdxError NI_FUNC IMAQdxDispose(void* buffer);

+IMAQdxError NI_FUNC IMAQdxRegisterAttributeUpdatedEvent(IMAQdxSession id, const char* name, AttributeUpdatedEventCallbackPtr callbackFunction, void* callbackData);

+IMAQdxError NI_FUNC IMAQdxEnumerateAttributes3(IMAQdxSession id, IMAQdxAttributeInformation attributeInformationArray[], uInt32* count, const char* root, IMAQdxAttributeVisibility visibility);

+

+

+#ifdef __cplusplus

+}

+#endif

+

+

+#endif // ___niimaqdx_h___

diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/NetworkCommunication/AICalibration.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/NetworkCommunication/AICalibration.h
new file mode 100644
index 0000000..b2f366c
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/NetworkCommunication/AICalibration.h
@@ -0,0 +1,19 @@
+

+#ifndef __AICalibration_h__

+#define __AICalibration_h__

+

+#include <stdint.h>

+

+#ifdef __cplusplus

+extern "C"

+{

+#endif

+

+	uint32_t FRC_NetworkCommunication_nAICalibration_getLSBWeight(const uint32_t aiSystemIndex, const uint32_t channel, int32_t *status);

+	int32_t FRC_NetworkCommunication_nAICalibration_getOffset(const uint32_t aiSystemIndex, const uint32_t channel, int32_t *status);

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif // __AICalibration_h__

diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/NetworkCommunication/CANInterfacePlugin.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/NetworkCommunication/CANInterfacePlugin.h
new file mode 100644
index 0000000..f4c4064
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/NetworkCommunication/CANInterfacePlugin.h
@@ -0,0 +1,80 @@
+// CANInterfacePlugin.h

+//

+//  Defines the API for building a CAN Interface Plugin to support

+//    PWM-cable-free CAN motor control on FRC robots.  This allows you

+//    to connect any CAN interface to the secure Jaguar CAN driver.

+//

+

+#ifndef __CANInterfacePlugin_h__

+#define __CANInterfacePlugin_h__

+

+#include <stdint.h>

+

+#define CAN_IS_FRAME_REMOTE 0x80000000

+#define CAN_IS_FRAME_11BIT  0x40000000

+#define CAN_29BIT_MESSAGE_ID_MASK 0x1FFFFFFF

+#define CAN_11BIT_MESSAGE_ID_MASK 0x000007FF

+

+class CANInterfacePlugin

+{

+public:

+	CANInterfacePlugin() {}

+	virtual ~CANInterfacePlugin() {}

+

+	/**

+	 * This entry-point of the CANInterfacePlugin is passed a message that the driver needs to send to

+	 * a device on the CAN bus.

+	 * 

+	 * This function may be called from multiple contexts and must therefore be reentrant.

+	 * 

+	 * @param messageID The 29-bit CAN message ID in the lsbs.  The msb can indicate a remote frame.

+	 * @param data A pointer to a buffer containing between 0 and 8 bytes to send with the message.  May be NULL if dataSize is 0.

+	 * @param dataSize The number of bytes to send with the message.

+	 * @return Return any error code.  On success return 0.

+	 */

+	virtual int32_t sendMessage(uint32_t messageID, const uint8_t *data, uint8_t dataSize) = 0;

+

+	/**

+	 * This entry-point of the CANInterfacePlugin is passed buffers which should be populated with

+	 * any received messages from devices on the CAN bus.

+	 * 

+	 * This function is always called by a single task in the Jaguar driver, so it need not be reentrant.

+	 * 

+	 * This function is expected to block for some period of time waiting for a message from the CAN bus.

+	 * It may timeout periodically (returning non-zero to indicate no message was populated) to allow for

+	 * shutdown and unloading of the plugin.

+	 * 

+	 * @param messageID A reference to be populated with a received 29-bit CAN message ID in the lsbs.

+	 * @param data A pointer to a buffer of 8 bytes to be populated with data received with the message.

+	 * @param dataSize A reference to be populated with the size of the data received (0 - 8 bytes).

+	 * @return This should return 0 if a message was populated, non-0 if no message was not populated.

+	 */

+	virtual int32_t receiveMessage(uint32_t &messageID, uint8_t *data, uint8_t &dataSize) = 0;

+

+	/**

+	 * This entry-point of the CANInterfacePlugin returns status of the CAN bus.

+	 * 

+	 * This function may be called from multiple contexts and must therefore be reentrant.

+	 * 

+	 * This function will return detailed hardware status if available for diagnostics of the CAN interface.

+	 * 

+	 * @param busOffCount The number of times that sendMessage failed with a busOff error indicating that messages

+	 *  are not successfully transmitted on the bus.

+	 * @param txFullCount The number of times that sendMessage failed with a txFifoFull error indicating that messages

+	 *  are not successfully received by any CAN device.

+	 * @param receiveErrorCount The count of receive errors as reported by the CAN driver.

+	 * @param transmitErrorCount The count of transmit errors as reported by the CAN driver.

+	 * @return This should return 0 if all status was retrieved successfully or an error code if not.

+	 */

+	virtual int32_t getStatus(uint32_t &busOffCount, uint32_t &txFullCount, uint32_t &receiveErrorCount, uint32_t &transmitErrorCount) {return 0;}

+};

+

+/**

+ * This function allows you to register a CANInterfacePlugin to provide access a CAN bus.

+ * 

+ * @param interface A pointer to an object that inherits from CANInterfacePlugin and implements

+ * the pure virtual interface.  If NULL, unregister the current plugin.

+ */

+void FRC_NetworkCommunication_CANSessionMux_registerInterface(CANInterfacePlugin* interface);

+

+#endif // __CANInterfacePlugin_h__

diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/NetworkCommunication/CANSessionMux.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/NetworkCommunication/CANSessionMux.h
new file mode 100644
index 0000000..81f63c5
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/NetworkCommunication/CANSessionMux.h
@@ -0,0 +1,63 @@
+// CANSessionMux.h

+//

+//  Defines the API for building a CAN Interface Plugin to support

+//    PWM-cable-free CAN motor control on FRC robots.  This allows you

+//    to connect any CAN interface to the secure Jaguar CAN driver.

+//

+

+#ifndef __CANSessionMux_h__

+#define __CANSessionMux_h__

+

+#if defined(__vxworks)

+#include <vxWorks.h>

+#else

+#include <stdint.h>

+#endif

+

+#define CAN_SEND_PERIOD_NO_REPEAT 0

+#define CAN_SEND_PERIOD_STOP_REPEATING -1

+

+/* Flags in the upper bits of the messageID */

+#define CAN_IS_FRAME_REMOTE 0x80000000

+#define CAN_IS_FRAME_11BIT  0x40000000

+

+#define ERR_CANSessionMux_InvalidBuffer   -44086

+#define ERR_CANSessionMux_MessageNotFound -44087

+#define WARN_CANSessionMux_NoToken         44087

+#define ERR_CANSessionMux_NotAllowed      -44088

+#define ERR_CANSessionMux_NotInitialized  -44089

+

+struct tCANStreamMessage{

+	uint32_t messageID;

+	uint32_t timeStamp;

+	uint8_t data[8];

+	uint8_t dataSize;

+};

+

+namespace nCANSessionMux

+{

+	void sendMessage_wrapper(uint32_t messageID, const uint8_t *data, uint8_t dataSize, int32_t periodMs, int32_t *status);

+	void receiveMessage_wrapper(uint32_t *messageID, uint32_t messageIDMask, uint8_t *data, uint8_t *dataSize, uint32_t *timeStamp, int32_t *status);

+	void openStreamSession(uint32_t *sessionHandle, uint32_t messageID, uint32_t messageIDMask, uint32_t maxMessages, int32_t *status);

+	void closeStreamSession(uint32_t sessionHandle);

+	void readStreamSession(uint32_t sessionHandle, struct tCANStreamMessage *messages, uint32_t messagesToRead, uint32_t *messagesRead, int32_t *status);

+	void getCANStatus(float *percentBusUtilization, uint32_t *busOffCount, uint32_t *txFullCount, uint32_t *receiveErrorCount, uint32_t *transmitErrorCount, int32_t *status);

+}

+

+#ifdef __cplusplus

+extern "C"

+{

+#endif

+

+	void FRC_NetworkCommunication_CANSessionMux_sendMessage(uint32_t messageID, const uint8_t *data, uint8_t dataSize, int32_t periodMs, int32_t *status);

+	void FRC_NetworkCommunication_CANSessionMux_receiveMessage(uint32_t *messageID, uint32_t messageIDMask, uint8_t *data, uint8_t *dataSize, uint32_t *timeStamp, int32_t *status);

+	void FRC_NetworkCommunication_CANSessionMux_openStreamSession(uint32_t *sessionHandle, uint32_t messageID, uint32_t messageIDMask, uint32_t maxMessages, int32_t *status);

+	void FRC_NetworkCommunication_CANSessionMux_closeStreamSession(uint32_t sessionHandle);

+	void FRC_NetworkCommunication_CANSessionMux_readStreamSession(uint32_t sessionHandle, struct tCANStreamMessage *messages, uint32_t messagesToRead, uint32_t *messagesRead, int32_t *status);

+	void FRC_NetworkCommunication_CANSessionMux_getCANStatus(float *percentBusUtilization, uint32_t *busOffCount, uint32_t *txFullCount, uint32_t *receiveErrorCount, uint32_t *transmitErrorCount, int32_t *status);

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif // __CANSessionMux_h__

diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/NetworkCommunication/FRCComm.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/NetworkCommunication/FRCComm.h
new file mode 100644
index 0000000..d542eca
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/NetworkCommunication/FRCComm.h
@@ -0,0 +1,121 @@
+/*************************************************************

+ * 					NOTICE

+ * 

+ * 	These are the only externally exposed functions to the

+ *   NetworkCommunication library

+ * 

+ * This is an implementation of FRC Spec for Comm Protocol

+ * Revision 4.5, June 30, 2008

+ *

+ * Copyright (c) National Instruments 2008.  All Rights Reserved.

+ * 

+ *************************************************************/

+

+#ifndef __FRC_COMM_H__

+#define __FRC_COMM_H__

+

+#ifdef SIMULATION

+#include <vxWorks_compat.h>

+#ifdef USE_THRIFT

+#define EXPORT_FUNC

+#else

+#define EXPORT_FUNC __declspec(dllexport) __cdecl

+#endif

+#else

+#if defined(__vxworks)

+#include <vxWorks.h>

+#define EXPORT_FUNC

+#else

+#include <stdint.h>

+#include <pthread.h>

+#define EXPORT_FUNC

+#endif

+#endif

+

+#define ERR_FRCSystem_NetCommNotResponding -44049

+

+enum AllianceStationID_t {

+	kAllianceStationID_red1,

+	kAllianceStationID_red2,

+	kAllianceStationID_red3,

+	kAllianceStationID_blue1,

+	kAllianceStationID_blue2,

+	kAllianceStationID_blue3,

+};

+

+struct ControlWord_t {

+#ifndef __vxworks

+	uint32_t enabled : 1;

+	uint32_t autonomous : 1;

+	uint32_t test :1;

+	uint32_t eStop : 1;

+	uint32_t fmsAttached:1;

+	uint32_t dsAttached:1;

+	uint32_t control_reserved : 26;

+#else

+	uint32_t control_reserved : 26;

+	uint32_t dsAttached:1;

+	uint32_t fmsAttached:1;

+	uint32_t eStop : 1;

+	uint32_t test :1;

+	uint32_t autonomous : 1;

+	uint32_t enabled : 1;

+#endif

+};

+

+struct JoystickAxes_t {

+	uint16_t count;

+	int16_t axes[1];

+};

+

+struct JoystickPOV_t {

+	uint16_t count;

+	int16_t povs[1];

+};

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+	int EXPORT_FUNC FRC_NetworkCommunication_Reserve(void *instance);

+#ifndef SIMULATION

+	void EXPORT_FUNC getFPGAHardwareVersion(uint16_t *fpgaVersion, uint32_t *fpgaRevision);

+#endif

+	int EXPORT_FUNC setStatusData(float battery, uint8_t dsDigitalOut, uint8_t updateNumber,

+			const char *userDataHigh, int userDataHighLength,

+			const char *userDataLow, int userDataLowLength, int wait_ms);

+	int EXPORT_FUNC setErrorData(const char *errors, int errorsLength, int wait_ms);

+	

+#ifdef SIMULATION

+	void EXPORT_FUNC setNewDataSem(HANDLE);

+#else

+# if defined (__vxworks)

+	void EXPORT_FUNC setNewDataSem(SEM_ID);

+# else

+	void EXPORT_FUNC setNewDataSem(pthread_mutex_t *);

+# endif

+#endif

+

+	// this uint32_t is really a LVRefNum

+	int EXPORT_FUNC setNewDataOccurRef(uint32_t refnum);

+

+	int EXPORT_FUNC FRC_NetworkCommunication_getControlWord(struct ControlWord_t *controlWord);

+	int EXPORT_FUNC FRC_NetworkCommunication_getAllianceStation(enum AllianceStationID_t *allianceStation);

+	int EXPORT_FUNC FRC_NetworkCommunication_getMatchTime(float *matchTime);

+	int EXPORT_FUNC FRC_NetworkCommunication_getJoystickAxes(uint8_t joystickNum, struct JoystickAxes_t *axes, uint8_t maxAxes);

+	int EXPORT_FUNC FRC_NetworkCommunication_getJoystickButtons(uint8_t joystickNum, uint32_t *buttons, uint8_t *count);

+	int EXPORT_FUNC FRC_NetworkCommunication_getJoystickPOVs(uint8_t joystickNum, struct JoystickPOV_t *povs, uint8_t maxPOVs);

+	int EXPORT_FUNC FRC_NetworkCommunication_setJoystickOutputs(uint8_t joystickNum, uint32_t hidOutputs, uint16_t leftRumble, uint16_t rightRumble);

+	int EXPORT_FUNC FRC_NetworkCommunication_getJoystickDesc(uint8_t joystickNum, uint8_t *isXBox, uint8_t *type, char *name,

+		uint8_t *axisCount, uint8_t *axisTypes, uint8_t *buttonCount, uint8_t *povCount);

+

+	void EXPORT_FUNC FRC_NetworkCommunication_getVersionString(char *version);

+	int EXPORT_FUNC FRC_NetworkCommunication_observeUserProgramStarting(void);

+	void EXPORT_FUNC FRC_NetworkCommunication_observeUserProgramDisabled(void);

+	void EXPORT_FUNC FRC_NetworkCommunication_observeUserProgramAutonomous(void);

+	void EXPORT_FUNC FRC_NetworkCommunication_observeUserProgramTeleop(void);

+	void EXPORT_FUNC FRC_NetworkCommunication_observeUserProgramTest(void);

+#ifdef __cplusplus

+}

+#endif

+

+#endif

diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/NetworkCommunication/LoadOut.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/NetworkCommunication/LoadOut.h
new file mode 100644
index 0000000..fce88a2
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/NetworkCommunication/LoadOut.h
@@ -0,0 +1,58 @@
+

+#ifndef __LoadOut_h__

+#define __LoadOut_h__

+

+#ifdef SIMULATION

+#include <vxWorks_compat.h>

+#define EXPORT_FUNC __declspec(dllexport) __cdecl

+#elif defined (__vxworks)

+#include <vxWorks.h>

+#define EXPORT_FUNC

+#else

+#include <stdint.h>

+#define EXPORT_FUNC

+#endif

+

+#define kMaxModuleNumber 2

+namespace nLoadOut

+{

+#if defined(__vxworks) || defined(SIMULATION)

+    typedef enum {

+        kModuleType_Unknown = 0x00,

+        kModuleType_Analog = 0x01,

+        kModuleType_Digital = 0x02,

+        kModuleType_Solenoid = 0x03,

+    } tModuleType;

+    bool EXPORT_FUNC getModulePresence(tModuleType moduleType, uint8_t moduleNumber);

+#endif

+    typedef enum {

+        kTargetClass_Unknown = 0x00,

+        kTargetClass_FRC1 = 0x10,

+        kTargetClass_FRC2 = 0x20,

+        kTargetClass_FRC3 = 0x30,

+        kTargetClass_RoboRIO = 0x40,

+#if defined(__vxworks) || defined(SIMULATION)

+        kTargetClass_FRC2_Analog = kTargetClass_FRC2 | kModuleType_Analog,

+        kTargetClass_FRC2_Digital = kTargetClass_FRC2 | kModuleType_Digital,

+        kTargetClass_FRC2_Solenoid = kTargetClass_FRC2 | kModuleType_Solenoid,

+#endif

+        kTargetClass_FamilyMask = 0xF0,

+        kTargetClass_ModuleMask = 0x0F,

+    } tTargetClass;

+    tTargetClass EXPORT_FUNC getTargetClass();

+}

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+#if defined(__vxworks) || defined(SIMULATION)

+    uint32_t EXPORT_FUNC FRC_NetworkCommunication_nLoadOut_getModulePresence(uint32_t moduleType, uint8_t moduleNumber);

+#endif

+    uint32_t EXPORT_FUNC FRC_NetworkCommunication_nLoadOut_getTargetClass();

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif // __LoadOut_h__

diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/NetworkCommunication/UsageReporting.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/NetworkCommunication/UsageReporting.h
new file mode 100644
index 0000000..918ac5a
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/NetworkCommunication/UsageReporting.h
@@ -0,0 +1,139 @@
+

+#ifndef __UsageReporting_h__

+#define __UsageReporting_h__

+

+#ifdef SIMULATION

+#include <vxWorks_compat.h>

+#define EXPORT_FUNC __declspec(dllexport) __cdecl

+#elif defined (__vxworks)

+#include <vxWorks.h>

+#define EXPORT_FUNC

+#else

+#include <stdint.h>

+#include <stdlib.h>

+#define EXPORT_FUNC

+#endif

+

+#define kUsageReporting_version 1

+

+namespace nUsageReporting

+{

+    typedef enum

+    {

+        kResourceType_Controller,

+        kResourceType_Module,

+        kResourceType_Language,

+        kResourceType_CANPlugin,

+        kResourceType_Accelerometer,

+        kResourceType_ADXL345,

+        kResourceType_AnalogChannel,

+        kResourceType_AnalogTrigger,

+        kResourceType_AnalogTriggerOutput,

+        kResourceType_CANJaguar,

+        kResourceType_Compressor,

+        kResourceType_Counter,

+        kResourceType_Dashboard,

+        kResourceType_DigitalInput,

+        kResourceType_DigitalOutput,

+        kResourceType_DriverStationCIO,

+        kResourceType_DriverStationEIO,

+        kResourceType_DriverStationLCD,

+        kResourceType_Encoder,

+        kResourceType_GearTooth,

+        kResourceType_Gyro,

+        kResourceType_I2C,

+        kResourceType_Framework,

+        kResourceType_Jaguar,

+        kResourceType_Joystick,

+        kResourceType_Kinect,

+        kResourceType_KinectStick,

+        kResourceType_PIDController,

+        kResourceType_Preferences,

+        kResourceType_PWM,

+        kResourceType_Relay,

+        kResourceType_RobotDrive,

+        kResourceType_SerialPort,

+        kResourceType_Servo,

+        kResourceType_Solenoid,

+        kResourceType_SPI,

+        kResourceType_Task,

+        kResourceType_Ultrasonic,

+        kResourceType_Victor,

+        kResourceType_Button,

+        kResourceType_Command,

+        kResourceType_AxisCamera,

+        kResourceType_PCVideoServer,

+        kResourceType_SmartDashboard,

+        kResourceType_Talon,

+        kResourceType_HiTechnicColorSensor,

+        kResourceType_HiTechnicAccel,

+        kResourceType_HiTechnicCompass,

+		kResourceType_SRF08,

+    } tResourceType;

+

+    typedef enum

+    {

+        kLanguage_LabVIEW = 1,

+        kLanguage_CPlusPlus = 2,

+        kLanguage_Java = 3,

+        kLanguage_Python = 4,

+

+        kCANPlugin_BlackJagBridge = 1,

+        kCANPlugin_2CAN = 2,

+

+        kFramework_Iterative = 1,

+        kFramework_Simple = 2,

+

+        kRobotDrive_ArcadeStandard = 1,

+        kRobotDrive_ArcadeButtonSpin = 2,

+        kRobotDrive_ArcadeRatioCurve = 3,

+        kRobotDrive_Tank = 4,

+        kRobotDrive_MecanumPolar = 5,

+        kRobotDrive_MecanumCartesian = 6,

+

+        kDriverStationCIO_Analog = 1,

+        kDriverStationCIO_DigitalIn = 2,

+        kDriverStationCIO_DigitalOut = 3,

+

+        kDriverStationEIO_Acceleration = 1,

+        kDriverStationEIO_AnalogIn = 2,

+        kDriverStationEIO_AnalogOut = 3,

+        kDriverStationEIO_Button = 4,

+        kDriverStationEIO_LED = 5,

+        kDriverStationEIO_DigitalIn = 6,

+        kDriverStationEIO_DigitalOut = 7,

+        kDriverStationEIO_FixedDigitalOut = 8,

+        kDriverStationEIO_PWM = 9,

+        kDriverStationEIO_Encoder = 10,

+        kDriverStationEIO_TouchSlider = 11,

+

+        kADXL345_SPI = 1,

+        kADXL345_I2C = 2,

+

+        kCommand_Scheduler = 1,

+

+        kSmartDashboard_Instance = 1,

+    } tInstances;

+

+    /**

+     * Report the usage of a resource of interest.

+     * 

+     * @param resource one of the values in the tResourceType above (max value 51).

+     * @param instanceNumber an index that identifies the resource instance.

+     * @param context an optional additional context number for some cases (such as module number).  Set to 0 to omit.

+     * @param feature a string to be included describing features in use on a specific resource.  Setting the same resource more than once allows you to change the feature string.

+     */

+    uint32_t EXPORT_FUNC report(tResourceType resource, uint8_t instanceNumber, uint8_t context = 0, const char *feature = NULL);

+}

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+    uint32_t EXPORT_FUNC FRC_NetworkCommunication_nUsageReporting_report(uint8_t resource, uint8_t instanceNumber, uint8_t context, const char *feature);

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif // __UsageReporting_h__

diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/NetworkCommunication/symModuleLink.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/NetworkCommunication/symModuleLink.h
new file mode 100644
index 0000000..00867a5
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/NetworkCommunication/symModuleLink.h
@@ -0,0 +1,21 @@
+#ifndef __SYM_MODULE_LINK_H__
+#define __SYM_MODULE_LINK_H__
+
+#include "HAL/HAL.hpp"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern STATUS    moduleNameFindBySymbolName
+    (
+        const char *    symbol,        /* symbol name to look for */
+        char * module        /* where to return module name */
+    );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/PWM.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/PWM.h
new file mode 100644
index 0000000..93785bb
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/PWM.h
@@ -0,0 +1,126 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "SensorBase.h"
+
+/**
+ * Class implements the PWM generation in the FPGA.
+ *
+ * The values supplied as arguments for PWM outputs range from -1.0 to 1.0. They are mapped
+ * to the hardware dependent values, in this case 0-2000 for the FPGA.
+ * Changes are immediately sent to the FPGA, and the update occurs at the next
+ * FPGA cycle. There is no delay.
+ *
+ * As of revision 0.1.10 of the FPGA, the FPGA interprets the 0-2000 values as follows:
+ *   - 2000 = maximum pulse width
+ *   - 1999 to 1001 = linear scaling from "full forward" to "center"
+ *   - 1000 = center value
+ *   - 999 to 2 = linear scaling from "center" to "full reverse"
+ *   - 1 = minimum pulse width (currently .5ms)
+ *   - 0 = disabled (i.e. PWM output is held low)
+ */
+class PWM : public SensorBase
+{
+public:
+	enum PeriodMultiplier
+	{
+		kPeriodMultiplier_1X = 1,
+		kPeriodMultiplier_2X = 2,
+		kPeriodMultiplier_4X = 4
+	};
+
+	explicit PWM(uint32_t channel);
+	virtual ~PWM();
+	virtual void SetRaw(unsigned short value);
+	virtual unsigned short GetRaw();
+	void SetPeriodMultiplier(PeriodMultiplier mult);
+	void SetZeroLatch();
+	void EnableDeadbandElimination(bool eliminateDeadband);
+	void SetBounds(int32_t max, int32_t deadbandMax, int32_t center, int32_t deadbandMin,
+			int32_t min);
+	void SetBounds(double max, double deadbandMax, double center, double deadbandMin, double min);
+	uint32_t GetChannel()
+	{
+		return m_channel;
+	}
+
+protected:
+	/**
+	 * kDefaultPwmPeriod is in ms
+	 *
+	 * - 20ms periods (50 Hz) are the "safest" setting in that this works for all devices
+	 * - 20ms periods seem to be desirable for Vex Motors
+	 * - 20ms periods are the specified period for HS-322HD servos, but work reliably down
+	 *      to 10.0 ms; starting at about 8.5ms, the servo sometimes hums and get hot;
+	 *      by 5.0ms the hum is nearly continuous
+	 * - 10ms periods work well for Victor 884
+	 * - 5ms periods allows higher update rates for Luminary Micro Jaguar speed controllers.
+	 *      Due to the shipping firmware on the Jaguar, we can't run the update period less
+	 *      than 5.05 ms.
+	 *
+	 * kDefaultPwmPeriod is the 1x period (5.05 ms).  In hardware, the period scaling is implemented as an
+	 * output squelch to get longer periods for old devices.
+	 */
+	static constexpr float kDefaultPwmPeriod = 5.05;
+	/**
+	 * kDefaultPwmCenter is the PWM range center in ms
+	 */
+	static constexpr float kDefaultPwmCenter = 1.5;
+	/**
+	 * kDefaultPWMStepsDown is the number of PWM steps below the centerpoint
+	 */
+	static const int32_t kDefaultPwmStepsDown = 1000;
+	static const int32_t kPwmDisabled = 0;
+
+	virtual void SetPosition(float pos);
+	virtual float GetPosition();
+	virtual void SetSpeed(float speed);
+	virtual float GetSpeed();
+
+	bool m_eliminateDeadband;
+	int32_t m_maxPwm;
+	int32_t m_deadbandMaxPwm;
+	int32_t m_centerPwm;
+	int32_t m_deadbandMinPwm;
+	int32_t m_minPwm;
+
+private:
+	void InitPWM(uint32_t channel);
+	uint32_t m_channel;
+	int32_t GetMaxPositivePwm()
+	{
+		return m_maxPwm;
+	}
+	int32_t GetMinPositivePwm()
+	{
+		return m_eliminateDeadband ? m_deadbandMaxPwm : m_centerPwm + 1;
+	}
+	int32_t GetCenterPwm()
+	{
+		return m_centerPwm;
+	}
+	int32_t GetMaxNegativePwm()
+	{
+		return m_eliminateDeadband ? m_deadbandMinPwm : m_centerPwm - 1;
+	}
+	int32_t GetMinNegativePwm()
+	{
+		return m_minPwm;
+	}
+	int32_t GetPositiveScaleFactor()
+	{
+		return GetMaxPositivePwm() - GetMinPositivePwm();
+	} ///< The scale for positive speeds.
+	int32_t GetNegativeScaleFactor()
+	{
+		return GetMaxNegativePwm() - GetMinNegativePwm();
+	} ///< The scale for negative speeds.
+	int32_t GetFullRangeScaleFactor()
+	{
+		return GetMaxPositivePwm() - GetMinNegativePwm();
+	} ///< The scale for positions.
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/PowerDistributionPanel.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/PowerDistributionPanel.h
new file mode 100644
index 0000000..2094e08
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/PowerDistributionPanel.h
@@ -0,0 +1,33 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+#ifndef __WPILIB_POWER_DISTRIBUTION_PANEL_H__
+#define __WPILIB_POWER_DISTRIBUTION_PANEL_H__
+
+#include "SensorBase.h"
+
+/**
+ * Class for getting voltage, current, temperature, power and energy from the CAN PDP.
+ * The PDP must be at CAN Address 0.
+ * @author Thomas Clark
+ */
+class PowerDistributionPanel : public SensorBase {
+	public:
+		PowerDistributionPanel();
+		
+		double GetVoltage();
+		double GetTemperature();
+		double GetCurrent(uint8_t channel);
+		double GetTotalCurrent();
+		double GetTotalPower();
+		double GetTotalEnergy();
+		void ResetTotalEnergy();
+		void ClearStickyFaults();
+};
+
+#endif /* __WPILIB_POWER_DISTRIBUTION_PANEL_H__ */
+
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Relay.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Relay.h
new file mode 100644
index 0000000..7dc9cc9
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Relay.h
@@ -0,0 +1,47 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "SensorBase.h"
+
+/**
+ * Class for Spike style relay outputs.
+ * Relays are intended to be connected to spikes or similar relays. The relay channels controls
+ * a pair of pins that are either both off, one on, the other on, or both on. This translates into
+ * two spike outputs at 0v, one at 12v and one at 0v, one at 0v and the other at 12v, or two
+ * spike outputs at 12V. This allows off, full forward, or full reverse control of motors without
+ * variable speed.  It also allows the two channels (forward and reverse) to be used independently
+ * for something that does not care about voltage polatiry (like a solenoid).
+ */
+class Relay : public SensorBase
+{
+public:
+	enum Value
+	{
+		kOff,
+		kOn,
+		kForward,
+		kReverse
+	};
+	enum Direction
+	{
+		kBothDirections,
+		kForwardOnly,
+		kReverseOnly
+	};
+
+	Relay(uint32_t channel, Direction direction = kBothDirections);
+	virtual ~Relay();
+
+	void Set(Value value);
+	Value Get();
+
+private:
+	void InitRelay();
+
+	uint32_t m_channel;
+	Direction m_direction;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/RobotBase.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/RobotBase.h
new file mode 100644
index 0000000..90530be
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/RobotBase.h
@@ -0,0 +1,63 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "Base.h"
+#include "Task.h"
+
+class DriverStation;
+
+#define START_ROBOT_CLASS(_ClassName_) \
+	int main() \
+	{ \
+		if (!HALInitialize()){std::cerr<<"FATAL ERROR: HAL could not be initialized"<<std::endl;return -1;}	\
+		HALReport(HALUsageReporting::kResourceType_Language, HALUsageReporting::kLanguage_CPlusPlus); \
+		_ClassName_ *robot = new _ClassName_(); \
+		RobotBase::robotSetup(robot); \
+		return 0; \
+	}
+
+/**
+ * Implement a Robot Program framework.
+ * The RobotBase class is intended to be subclassed by a user creating a robot program.
+ * Overridden Autonomous() and OperatorControl() methods are called at the appropriate time
+ * as the match proceeds. In the current implementation, the Autonomous code will run to
+ * completion before the OperatorControl code could start. In the future the Autonomous code
+ * might be spawned as a task, then killed at the end of the Autonomous period.
+ */
+class RobotBase
+{
+	friend class RobotDeleter;
+public:
+	static RobotBase &getInstance();
+	static void setInstance(RobotBase* robot);
+
+	bool IsEnabled();
+	bool IsDisabled();
+	bool IsAutonomous();
+	bool IsOperatorControl();
+	bool IsTest();
+	bool IsNewDataAvailable();
+	static void startRobotTask(FUNCPTR factory);
+	static void robotTask(FUNCPTR factory, Task *task);
+	virtual void StartCompetition() = 0;
+	
+	static void robotSetup(RobotBase *robot);
+
+protected:
+	virtual ~RobotBase();
+	RobotBase();
+
+	virtual void Prestart();
+
+	Task *m_task;
+	DriverStation *m_ds;
+
+private:
+	static RobotBase *m_instance;
+
+	DISALLOW_COPY_AND_ASSIGN(RobotBase);
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/RobotDrive.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/RobotDrive.h
new file mode 100644
index 0000000..7286331
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/RobotDrive.h
@@ -0,0 +1,114 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "ErrorBase.h"
+#include <stdlib.h>
+#include "HAL/HAL.hpp"
+#include "MotorSafety.h"
+#include "MotorSafetyHelper.h"
+
+class SpeedController;
+class GenericHID;
+
+/**
+ * Utility class for handling Robot drive based on a definition of the motor configuration.
+ * The robot drive class handles basic driving for a robot. Currently, 2 and 4 motor tank and
+ * mecanum drive trains are supported. In the future other drive types like swerve might be
+ * implemented. Motor channel numbers are passed supplied on creation of the class. Those
+ * are used for either the Drive function (intended for hand created drive code, such as
+ * autonomous) or with the Tank/Arcade functions intended to be used for Operator Control
+ * driving.
+ */
+class RobotDrive : public MotorSafety, public ErrorBase
+{
+public:
+	enum MotorType
+	{
+		kFrontLeftMotor = 0,
+		kFrontRightMotor = 1,
+		kRearLeftMotor = 2,
+		kRearRightMotor = 3
+	};
+
+	RobotDrive(uint32_t leftMotorChannel, uint32_t rightMotorChannel);
+	RobotDrive(uint32_t frontLeftMotorChannel, uint32_t rearLeftMotorChannel,
+			uint32_t frontRightMotorChannel, uint32_t rearRightMotorChannel);
+	RobotDrive(SpeedController *leftMotor, SpeedController *rightMotor);
+	RobotDrive(SpeedController &leftMotor, SpeedController &rightMotor);
+	RobotDrive(SpeedController *frontLeftMotor, SpeedController *rearLeftMotor,
+			SpeedController *frontRightMotor, SpeedController *rearRightMotor);
+	RobotDrive(SpeedController &frontLeftMotor, SpeedController &rearLeftMotor,
+			SpeedController &frontRightMotor, SpeedController &rearRightMotor);
+	virtual ~RobotDrive();
+
+	void Drive(float outputMagnitude, float curve);
+	void TankDrive(GenericHID *leftStick, GenericHID *rightStick, bool squaredInputs = true);
+	void TankDrive(GenericHID &leftStick, GenericHID &rightStick, bool squaredInputs = true);
+	void TankDrive(GenericHID *leftStick, uint32_t leftAxis, GenericHID *rightStick,
+			uint32_t rightAxis, bool squaredInputs = true);
+	void TankDrive(GenericHID &leftStick, uint32_t leftAxis, GenericHID &rightStick,
+			uint32_t rightAxis, bool squaredInputs = true);
+	void TankDrive(float leftValue, float rightValue, bool squaredInputs = true);
+	void ArcadeDrive(GenericHID *stick, bool squaredInputs = true);
+	void ArcadeDrive(GenericHID &stick, bool squaredInputs = true);
+	void ArcadeDrive(GenericHID *moveStick, uint32_t moveChannel, GenericHID *rotateStick,
+			uint32_t rotateChannel, bool squaredInputs = true);
+	void ArcadeDrive(GenericHID &moveStick, uint32_t moveChannel, GenericHID &rotateStick,
+			uint32_t rotateChannel, bool squaredInputs = true);
+	void ArcadeDrive(float moveValue, float rotateValue, bool squaredInputs = true);
+	void MecanumDrive_Cartesian(float x, float y, float rotation, float gyroAngle = 0.0);
+	void MecanumDrive_Polar(float magnitude, float direction, float rotation);
+	void HolonomicDrive(float magnitude, float direction, float rotation);
+	virtual void SetLeftRightMotorOutputs(float leftOutput, float rightOutput);
+	void SetInvertedMotor(MotorType motor, bool isInverted);
+	void SetSensitivity(float sensitivity);
+	void SetMaxOutput(double maxOutput);
+	void SetCANJaguarSyncGroup(uint8_t syncGroup);
+
+	void SetExpiration(float timeout);
+	float GetExpiration();
+	bool IsAlive();
+	void StopMotor();
+	bool IsSafetyEnabled();
+	void SetSafetyEnabled(bool enabled);
+	void GetDescription(char *desc);
+
+protected:
+	void InitRobotDrive();
+	float Limit(float num);
+	void Normalize(double *wheelSpeeds);
+	void RotateVector(double &x, double &y, double angle);
+
+	static const int32_t kMaxNumberOfMotors = 4;
+
+	int32_t m_invertedMotors[kMaxNumberOfMotors];
+	float m_sensitivity;
+	double m_maxOutput;
+	bool m_deleteSpeedControllers;
+	SpeedController *m_frontLeftMotor;
+	SpeedController *m_frontRightMotor;
+	SpeedController *m_rearLeftMotor;
+	SpeedController *m_rearRightMotor;
+	MotorSafetyHelper *m_safetyHelper;
+	uint8_t m_syncGroup;
+
+private:
+	int32_t GetNumMotors()
+	{
+		int motors = 0;
+		if (m_frontLeftMotor)
+			motors++;
+		if (m_frontRightMotor)
+			motors++;
+		if (m_rearLeftMotor)
+			motors++;
+		if (m_rearRightMotor)
+			motors++;
+		return motors;
+	}
+	DISALLOW_COPY_AND_ASSIGN(RobotDrive);
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/SPI.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/SPI.h
new file mode 100644
index 0000000..7c6d61f
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/SPI.h
@@ -0,0 +1,58 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "HAL/HAL.hpp"
+#include "SensorBase.h"
+
+class DigitalOutput;
+class DigitalInput;
+
+/**
+ * SPI bus interface class.
+ *
+ * This class is intended to be used by sensor (and other SPI device) drivers.
+ * It probably should not be used directly.
+ *
+ */
+class SPI : public SensorBase
+{
+public:
+	enum Port {kOnboardCS0, kOnboardCS1, kOnboardCS2, kOnboardCS3, kMXP};
+	SPI(Port SPIport);
+	virtual ~SPI();
+
+	void SetClockRate(double hz);
+
+	void SetMSBFirst();
+	void SetLSBFirst();
+
+	void SetSampleDataOnFalling();
+	void SetSampleDataOnRising();
+
+
+	void SetClockActiveLow();
+	void SetClockActiveHigh();
+
+	void SetChipSelectActiveHigh();
+	void SetChipSelectActiveLow();
+
+	virtual int32_t Write(uint8_t* data, uint8_t size);
+	virtual int32_t Read(bool initiate, uint8_t* dataReceived, uint8_t size);
+	virtual int32_t Transaction(uint8_t* dataToSend, uint8_t* dataReceived, uint8_t size);
+
+
+protected:
+	uint8_t m_port;
+	bool m_msbFirst;
+	bool m_sampleOnTrailing;
+	bool m_clk_idle_high;
+
+private:
+	void Init();
+
+	DISALLOW_COPY_AND_ASSIGN(SPI);
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/SafePWM.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/SafePWM.h
new file mode 100644
index 0000000..bed5c21
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/SafePWM.h
@@ -0,0 +1,38 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "MotorSafety.h"
+#include "PWM.h"
+
+class MotorSafetyHelper;
+
+/**
+ * A safe version of the PWM class.
+ * It is safe because it implements the MotorSafety interface that provides timeouts
+ * in the event that the motor value is not updated before the expiration time.
+ * This delegates the actual work to a MotorSafetyHelper object that is used for all
+ * objects that implement MotorSafety.
+ */
+class SafePWM : public PWM, public MotorSafety
+{
+public:
+	explicit SafePWM(uint32_t channel);
+	~SafePWM();
+
+	void SetExpiration(float timeout);
+	float GetExpiration();
+	bool IsAlive();
+	void StopMotor();
+	bool IsSafetyEnabled();
+	void SetSafetyEnabled(bool enabled);
+	void GetDescription(char *desc);
+
+	virtual void SetSpeed(float speed);
+private:
+	void InitSafePWM();
+	MotorSafetyHelper *m_safetyHelper;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/SampleRobot.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/SampleRobot.h
new file mode 100644
index 0000000..66842b6
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/SampleRobot.h
@@ -0,0 +1,25 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "RobotBase.h"
+
+class SampleRobot : public RobotBase
+{
+public:
+	SampleRobot();
+	virtual ~SampleRobot() {}
+	virtual void RobotInit();
+	virtual void Disabled();
+	virtual void Autonomous();
+	virtual void OperatorControl();
+	virtual void Test();
+	virtual void RobotMain();
+	void StartCompetition();
+
+private:
+	bool m_robotMainOverridden;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Servo.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Servo.h
new file mode 100644
index 0000000..25cfe1f
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Servo.h
@@ -0,0 +1,48 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "SafePWM.h"
+#include "SpeedController.h"
+
+/**
+ * Standard hobby style servo.
+ *
+ * The range parameters default to the appropriate values for the Hitec HS-322HD servo provided
+ * in the FIRST Kit of Parts in 2008.
+ */
+class Servo : public SafePWM
+{
+public:
+	explicit Servo(uint32_t channel);
+	virtual ~Servo();
+	void Set(float value);
+	void SetOffline();
+	float Get();
+	void SetAngle(float angle);
+	float GetAngle();
+	static float GetMaxAngle()
+	{
+		return kMaxServoAngle;
+	}
+	static float GetMinAngle()
+	{
+		return kMinServoAngle;
+	}
+
+private:
+	void InitServo();
+	float GetServoAngleRange()
+	{
+		return kMaxServoAngle - kMinServoAngle;
+	}
+
+	static constexpr float kMaxServoAngle = 180.0;
+	static constexpr float kMinServoAngle = 0.0;
+
+	static constexpr float kDefaultMaxServoPWM = 2.4;
+	static constexpr float kDefaultMinServoPWM = .6;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Solenoid.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Solenoid.h
new file mode 100644
index 0000000..fe54ea2
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Solenoid.h
@@ -0,0 +1,30 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "SolenoidBase.h"
+
+/**
+ * Solenoid class for running high voltage Digital Output (PCM).
+ * 
+ * The Solenoid class is typically used for pneumatics solenoids, but could be used
+ * for any device within the current spec of the PCM.
+ */
+class Solenoid : public SolenoidBase
+{
+public:
+	explicit Solenoid(uint32_t channel);
+	Solenoid(uint8_t moduleNumber, uint32_t channel);
+	virtual ~Solenoid();
+	virtual void Set(bool on);
+	virtual bool Get();
+	bool IsBlackListed();
+
+private:
+	void InitSolenoid();
+
+	uint32_t m_channel; ///< The channel on the module to control.
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/SolenoidBase.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/SolenoidBase.h
new file mode 100644
index 0000000..d70823f
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/SolenoidBase.h
@@ -0,0 +1,37 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "Resource.h"
+#include "SensorBase.h"
+#include "HAL/HAL.hpp"
+#include "HAL/cpp/Synchronized.hpp"
+
+/**
+ * SolenoidBase class is the common base class for the Solenoid and
+ * DoubleSolenoid classes.
+ */
+class SolenoidBase : public SensorBase
+{
+public:
+	virtual ~SolenoidBase();
+	uint8_t GetAll();
+
+	uint8_t GetPCMSolenoidBlackList();
+	bool GetPCMSolenoidVoltageStickyFault();
+	bool GetPCMSolenoidVoltageFault();
+	void ClearAllPCMStickyFaults();
+protected:
+	explicit SolenoidBase(uint8_t pcmID);
+	void Set(uint8_t value, uint8_t mask);
+	virtual void InitSolenoid() = 0;
+
+	uint32_t m_moduleNumber; ///< Slot number where the module is plugged into the chassis.
+	static Resource *m_allocated;
+
+private:
+	void* m_ports[kSolenoidChannels];
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/SpeedController.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/SpeedController.h
new file mode 100644
index 0000000..96d9266
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/SpeedController.h
@@ -0,0 +1,35 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "HAL/HAL.hpp"
+#include "PIDOutput.h"
+
+/**
+ * Interface for speed controlling devices.
+ */
+class SpeedController : public PIDOutput
+{
+public:
+	virtual ~SpeedController() {}
+	/**
+	 * Common interface for setting the speed of a speed controller.
+	 * 
+	 * @param speed The speed to set.  Value should be between -1.0 and 1.0.
+	 * @param syncGroup The update group to add this Set() to, pending UpdateSyncGroup().  If 0, update immediately.
+	 */
+	virtual void Set(float speed, uint8_t syncGroup = 0) = 0;
+	/**
+	 * Common interface for getting the current set speed of a speed controller.
+	 * 
+	 * @return The current set speed.  Value is between -1.0 and 1.0.
+	 */
+	virtual float Get() = 0;
+	/**
+	 * Common interface for disabling a motor.
+	 */
+	virtual void Disable() = 0;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Talon.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Talon.h
new file mode 100644
index 0000000..6e11ccd
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Talon.h
@@ -0,0 +1,28 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "SafePWM.h"
+#include "SpeedController.h"
+#include "PIDOutput.h"
+
+/**
+ * Cross the Road Electronics (CTRE) Talon and Talon SR Speed Controller
+ */
+class Talon : public SafePWM, public SpeedController
+{
+public:
+	explicit Talon(uint32_t channel);
+	virtual ~Talon();
+	virtual void Set(float value, uint8_t syncGroup = 0);
+	virtual float Get();
+	virtual void Disable();
+
+	virtual void PIDWrite(float output);
+
+private:
+	void InitTalon();
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/TalonSRX.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/TalonSRX.h
new file mode 100644
index 0000000..fe36b45
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/TalonSRX.h
@@ -0,0 +1,29 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "SafePWM.h"
+#include "SpeedController.h"
+#include "PIDOutput.h"
+
+/**
+ * Cross the Road Electronics (CTRE) Talon SRX Speed Controller with PWM control
+ * @see CANTalon for CAN control
+ */
+class TalonSRX : public SafePWM, public SpeedController
+{
+public:
+	explicit TalonSRX(uint32_t channel);
+	virtual ~TalonSRX();
+	virtual void Set(float value, uint8_t syncGroup = 0);
+	virtual float Get();
+	virtual void Disable();
+
+	virtual void PIDWrite(float output);
+
+private:
+	void InitTalonSRX();
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/USBCamera.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/USBCamera.h
new file mode 100644
index 0000000..ac8bfe4
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/USBCamera.h
@@ -0,0 +1,111 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "ErrorBase.h"
+#include "nivision.h"
+#include "NIIMAQdx.h"
+
+#include <mutex>
+#include <string>
+
+typedef enum whiteBalance_enum {
+  kFixedIndoor = 3000,
+  kFixedOutdoor1 = 4000,
+  kFixedOutdoor2 = 5000,
+  kFixedFluorescent1 = 5100,
+  kFixedFlourescent2 = 5200
+} whiteBalance;
+
+class USBCamera : public ErrorBase {
+ private:
+  static constexpr char const *ATTR_WB_MODE = "CameraAttributes::WhiteBalance::Mode";
+  static constexpr char const *ATTR_WB_VALUE = "CameraAttributes::WhiteBalance::Value";
+  static constexpr char const *ATTR_EX_MODE = "CameraAttributes::Exposure::Mode";
+  static constexpr char const *ATTR_EX_VALUE = "CameraAttributes::Exposure::Value";
+  static constexpr char const *ATTR_BR_MODE = "CameraAttributes::Brightness::Mode";
+  static constexpr char const *ATTR_BR_VALUE = "CameraAttributes::Brightness::Value";
+
+ protected:
+  IMAQdxSession m_id;
+  std::string m_name;
+  bool m_useJpeg;
+  bool m_active;
+  bool m_open;
+
+  std::recursive_mutex m_mutex;
+
+  unsigned int m_width;
+  unsigned int m_height;
+  double m_fps;
+  std::string m_whiteBalance;
+  unsigned int m_whiteBalanceValue;
+  bool m_whiteBalanceValuePresent;
+  std::string m_exposure;
+  unsigned int m_exposureValue;
+  bool m_exposureValuePresent;
+  unsigned int m_brightness;
+  bool m_needSettingsUpdate;
+
+  unsigned int GetJpegSize(void* buffer, unsigned int buffSize);
+
+ public:
+  static constexpr char const *kDefaultCameraName = "cam0";
+
+  USBCamera(std::string name, bool useJpeg);
+  
+  void OpenCamera();
+  void CloseCamera();
+  void StartCapture();
+  void StopCapture();
+  void SetFPS(double fps);
+  void SetSize(unsigned int width, unsigned int height);
+
+  void UpdateSettings();
+  /**
+   * Set the brightness, as a percentage (0-100).
+   */
+  void SetBrightness(unsigned int brightness);
+
+  /**
+   * Get the brightness, as a percentage (0-100).
+   */
+  unsigned int GetBrightness();
+
+  /**
+   * Set the white balance to auto
+   */
+  void SetWhiteBalanceAuto();
+
+  /**
+   * Set the white balance to hold current
+   */
+  void SetWhiteBalanceHoldCurrent();
+
+  /**
+   * Set the white balance to manual, with specified color temperature
+   */
+  void SetWhiteBalanceManual(unsigned int wbValue);
+
+  /**
+   * Set the exposure to auto exposure
+   */
+  void SetExposureAuto();
+
+  /**
+   * Set the exposure to hold current
+   */
+  void SetExposureHoldCurrent();
+
+  /**
+   * Set the exposure to manual, with a given percentage (0-100)
+   */
+  void SetExposureManual(unsigned int expValue);
+  
+  void GetImage(Image* image);
+  unsigned int GetImageData(void* buffer, unsigned int bufferSize);
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Ultrasonic.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Ultrasonic.h
new file mode 100644
index 0000000..e84e4ca
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Ultrasonic.h
@@ -0,0 +1,80 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "SensorBase.h"
+#include "Task.h"
+#include "PIDSource.h"
+
+class Counter;
+class DigitalInput;
+class DigitalOutput;
+
+/**
+ * Ultrasonic rangefinder class.
+ * The Ultrasonic rangefinder measures absolute distance based on the round-trip time
+ * of a ping generated by the controller. These sensors use two transducers, a speaker and
+ * a microphone both tuned to the ultrasonic range. A common ultrasonic sensor, the Daventech SRF04
+ * requires a short pulse to be generated on a digital channel. This causes the chirp to be
+ * emmitted. A second line becomes high as the ping is transmitted and goes low when
+ * the echo is received. The time that the line is high determines the round trip distance
+ * (time of flight).
+ */
+class Ultrasonic : public SensorBase, public PIDSource
+{
+public:
+	enum DistanceUnit
+	{
+		kInches = 0,
+		kMilliMeters = 1
+	};
+
+	Ultrasonic(DigitalOutput *pingChannel, DigitalInput *echoChannel, DistanceUnit units = kInches);
+	Ultrasonic(DigitalOutput &pingChannel, DigitalInput &echoChannel, DistanceUnit units = kInches);
+	Ultrasonic(uint32_t pingChannel, uint32_t echoChannel, DistanceUnit units = kInches);
+	virtual ~Ultrasonic();
+
+	void Ping();
+	bool IsRangeValid();
+	static void SetAutomaticMode(bool enabling);
+	double GetRangeInches();
+	double GetRangeMM();
+	bool IsEnabled()
+	{
+		return m_enabled;
+	}
+	void SetEnabled(bool enable)
+	{
+		m_enabled = enable;
+	}
+
+	double PIDGet();
+	void SetDistanceUnits(DistanceUnit units);
+	DistanceUnit GetDistanceUnits();
+
+private:
+	void Initialize();
+
+	static void UltrasonicChecker();
+
+	static constexpr double kPingTime = 10 * 1e-6;	///< Time (sec) for the ping trigger pulse.
+	static const uint32_t kPriority = 90;	///< Priority that the ultrasonic round robin task runs.
+	static constexpr double kMaxUltrasonicTime = 0.1;	///< Max time (ms) between readings.
+	static constexpr double kSpeedOfSoundInchesPerSec = 1130.0 * 12.0;
+
+	static Task m_task; // task doing the round-robin automatic sensing
+	static Ultrasonic *m_firstSensor; // head of the ultrasonic sensor list
+	static bool m_automaticEnabled; // automatic round robin mode
+	static SEMAPHORE_ID m_semaphore; // synchronize access to the list of sensors
+
+	DigitalInput *m_echoChannel;
+	DigitalOutput *m_pingChannel;
+	bool m_allocatedChannels;
+	bool m_enabled;
+	Counter *m_counter;
+	Ultrasonic *m_nextSensor;
+	DistanceUnit m_units;
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Victor.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Victor.h
new file mode 100644
index 0000000..9a83519
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Victor.h
@@ -0,0 +1,31 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "SafePWM.h"
+#include "SpeedController.h"
+#include "PIDOutput.h"
+
+/**
+ * Vex Robotics Victor 888 Speed Controller
+ *
+ * The Vex Robotics Victor 884 Speed Controller can also be used with this
+ * class but may need to be calibrated per the Victor 884 user manual.
+ */
+class Victor : public SafePWM, public SpeedController
+{
+public:
+	explicit Victor(uint32_t channel);
+	virtual ~Victor();
+	virtual void Set(float value, uint8_t syncGroup = 0);
+	virtual float Get();
+	virtual void Disable();
+
+	virtual void PIDWrite(float output);
+
+private:
+	void InitVictor();
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/VictorSP.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/VictorSP.h
new file mode 100644
index 0000000..e2ba4dc
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/VictorSP.h
@@ -0,0 +1,28 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#include "SafePWM.h"
+#include "SpeedController.h"
+#include "PIDOutput.h"
+
+/**
+ * Vex Robotics Victor SP Speed Controller
+ */
+class VictorSP : public SafePWM, public SpeedController
+{
+public:
+	explicit VictorSP(uint32_t channel);
+	virtual ~VictorSP();
+	virtual void Set(float value, uint8_t syncGroup = 0);
+	virtual float Get();
+	virtual void Disable();
+
+	virtual void PIDWrite(float output);
+
+private:
+	void InitVictorSP();
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/AxisCamera.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/AxisCamera.h
new file mode 100644
index 0000000..9792093
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/AxisCamera.h
@@ -0,0 +1,127 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <thread>
+#include <string>
+#include <mutex>
+
+#include "ErrorBase.h"
+#include "Vision/ColorImage.h"
+#include "Vision/HSLImage.h"
+#include "nivision.h"
+
+/**
+ * Axis M1011 network camera
+ */
+class AxisCamera: public ErrorBase
+{
+public:
+	enum WhiteBalance
+	{
+		kWhiteBalance_Automatic,
+		kWhiteBalance_Hold,
+		kWhiteBalance_FixedOutdoor1,
+		kWhiteBalance_FixedOutdoor2,
+		kWhiteBalance_FixedIndoor,
+		kWhiteBalance_FixedFluorescent1,
+		kWhiteBalance_FixedFluorescent2
+	};
+
+	enum ExposureControl
+	{
+		kExposureControl_Automatic,
+		kExposureControl_Hold,
+		kExposureControl_FlickerFree50Hz,
+		kExposureControl_FlickerFree60Hz
+	};
+
+	enum Resolution
+	{
+		kResolution_640x480,
+		kResolution_480x360,
+		kResolution_320x240,
+		kResolution_240x180,
+		kResolution_176x144,
+		kResolution_160x120,
+	};
+
+	enum Rotation
+	{
+		kRotation_0, kRotation_180
+	};
+
+	explicit AxisCamera(std::string const& cameraHost);
+	virtual ~AxisCamera();
+
+	bool IsFreshImage() const;
+
+	int GetImage(Image *image);
+	int GetImage(ColorImage *image);
+	HSLImage *GetImage();
+	int CopyJPEG(char **destImage, unsigned int &destImageSize, unsigned int &destImageBufferSize);
+
+	void WriteBrightness(int brightness);
+	int GetBrightness();
+
+	void WriteWhiteBalance(WhiteBalance whiteBalance);
+	WhiteBalance GetWhiteBalance();
+
+	void WriteColorLevel(int colorLevel);
+	int GetColorLevel();
+
+	void WriteExposureControl(ExposureControl exposureControl);
+	ExposureControl GetExposureControl();
+
+	void WriteExposurePriority(int exposurePriority);
+	int GetExposurePriority();
+
+	void WriteMaxFPS(int maxFPS);
+	int GetMaxFPS();
+
+	void WriteResolution(Resolution resolution);
+	Resolution GetResolution();
+
+	void WriteCompression(int compression);
+	int GetCompression();
+
+	void WriteRotation(Rotation rotation);
+	Rotation GetRotation();
+
+private:
+	std::thread m_captureThread;
+	std::string m_cameraHost;
+	int m_cameraSocket;
+	std::mutex m_captureMutex;
+
+	std::mutex m_imageDataMutex;
+	std::vector<uint8_t> m_imageData;
+	bool m_freshImage;
+
+	int m_brightness;
+	WhiteBalance m_whiteBalance;
+	int m_colorLevel;
+	ExposureControl m_exposureControl;
+	int m_exposurePriority;
+	int m_maxFPS;
+	Resolution m_resolution;
+	int m_compression;
+	Rotation m_rotation;
+	bool m_parametersDirty;
+	bool m_streamDirty;
+	std::mutex m_parametersMutex;
+
+	bool m_done;
+
+	void Capture();
+	void ReadImagesFromCamera();
+	bool WriteParameters();
+
+	int CreateCameraSocket(std::string const& requestString, bool setError);
+
+	DISALLOW_COPY_AND_ASSIGN(AxisCamera);
+};
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/BaeUtilities.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/BaeUtilities.h
new file mode 100644
index 0000000..a684b07
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/BaeUtilities.h
@@ -0,0 +1,57 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+/*  Constants */
+#define LOG_DEBUG    __FILE__,__FUNCTION__,__LINE__,DEBUG_TYPE
+#define LOG_INFO     __FILE__,__FUNCTION__,__LINE__,INFO_TYPE
+#define LOG_ERROR    __FILE__,__FUNCTION__,__LINE__,ERROR_TYPE
+#define LOG_CRITICAL __FILE__,__FUNCTION__,__LINE__,CRITICAL_TYPE
+#define LOG_FATAL    __FILE__,__FUNCTION__,__LINE__,FATAL_TYPE
+#define LOG_DEBUG    __FILE__,__FUNCTION__,__LINE__,DEBUG_TYPE
+
+/*   Enumerated Types */
+
+/** debug levels */
+enum dprint_type {DEBUG_TYPE, INFO_TYPE, ERROR_TYPE, CRITICAL_TYPE, FATAL_TYPE};
+
+/** debug output setting */
+typedef enum DebugOutputType_enum { 
+	DEBUG_OFF, DEBUG_MOSTLY_OFF, DEBUG_SCREEN_ONLY, DEBUG_FILE_ONLY, DEBUG_SCREEN_AND_FILE
+}DebugOutputType;
+
+/*  Enumerated Types */
+
+/* Utility functions */
+
+/* debug */
+void SetDebugFlag ( DebugOutputType flag  ); 
+void dprintf ( const char * tempString, ...  );  /* Variable argument list */
+
+/* set FRC ranges for drive */
+double RangeToNormalized(double pixel, int range);
+/* change normalized value to any range - used for servo */
+float NormalizeToRange(float normalizedValue, float minRange, float maxRange);
+float NormalizeToRange(float normalizedValue);
+
+/* system utilities */
+void ShowActivity (char *fmt, ...);
+double ElapsedTime (double startTime);
+
+/* servo panning utilities */
+class Servo;
+double SinPosition (double *period, double sinStart);
+void panInit();
+void panInit(double period);
+void panForTarget(Servo *panServo);
+void panForTarget(Servo *panServo, double sinStart);
+
+/* config file read utilities */
+int processFile(char *inputFile, char *outputString, int lineNumber);
+int emptyString(char *string);
+void stripString(char *string);
+
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/BinaryImage.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/BinaryImage.h
new file mode 100644
index 0000000..7c33f54
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/BinaryImage.h
@@ -0,0 +1,39 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "MonoImage.h"
+/**
+ * Included for ParticleAnalysisReport definition
+ * TODO: Eliminate this dependency! 
+ */
+#include "Vision/VisionAPI.h"
+
+#include <vector>
+#include <algorithm>
+
+class BinaryImage : public MonoImage
+{
+public:
+	BinaryImage();
+	virtual ~BinaryImage();
+	int GetNumberParticles();
+	ParticleAnalysisReport GetParticleAnalysisReport(int particleNumber);
+	void GetParticleAnalysisReport(int particleNumber, ParticleAnalysisReport *par);
+	std::vector<ParticleAnalysisReport>* GetOrderedParticleAnalysisReports();
+	BinaryImage *RemoveSmallObjects(bool connectivity8, int erosions);
+	BinaryImage *RemoveLargeObjects(bool connectivity8, int erosions);
+	BinaryImage *ConvexHull(bool connectivity8);
+	BinaryImage *ParticleFilter(ParticleFilterCriteria2 *criteria, int criteriaCount);
+	virtual void Write(const char *fileName);
+private:
+	bool ParticleMeasurement(int particleNumber, MeasurementType whatToMeasure, int *result);
+	bool ParticleMeasurement(int particleNumber, MeasurementType whatToMeasure, double *result);
+	static double NormalizeFromRange(double position, int range);
+	static bool CompareParticleSizes(ParticleAnalysisReport particle1, ParticleAnalysisReport particle2);
+};
+
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/ColorImage.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/ColorImage.h
new file mode 100644
index 0000000..595ed83
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/ColorImage.h
@@ -0,0 +1,65 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "ImageBase.h"
+#include "BinaryImage.h"
+#include "Threshold.h"
+
+class ColorImage : public ImageBase
+{
+public:
+	ColorImage(ImageType type);
+	virtual ~ColorImage();
+	BinaryImage *ThresholdRGB(int redLow, int redHigh, int greenLow, int greenHigh, int blueLow, int blueHigh);
+	BinaryImage *ThresholdHSL(int hueLow, int hueHigh, int saturationLow, int saturationHigh, int luminenceLow, int luminenceHigh);
+	BinaryImage *ThresholdHSV(int hueLow, int hueHigh, int saturationLow, int saturationHigh, int valueHigh, int valueLow);
+	BinaryImage *ThresholdHSI(int hueLow, int hueHigh, int saturationLow, int saturationHigh, int intensityLow, int intensityHigh);
+	BinaryImage *ThresholdRGB(Threshold &threshold);
+	BinaryImage *ThresholdHSL(Threshold &threshold);
+	BinaryImage *ThresholdHSV(Threshold &threshold);
+	BinaryImage *ThresholdHSI(Threshold &threshold);
+	MonoImage *GetRedPlane();
+	MonoImage *GetGreenPlane();
+	MonoImage *GetBluePlane();
+	MonoImage *GetHSLHuePlane();
+	MonoImage *GetHSVHuePlane();
+	MonoImage *GetHSIHuePlane();
+	MonoImage *GetHSLSaturationPlane();
+	MonoImage *GetHSVSaturationPlane();
+	MonoImage *GetHSISaturationPlane();
+	MonoImage *GetLuminancePlane();
+	MonoImage *GetValuePlane();
+	MonoImage *GetIntensityPlane();
+	void ReplaceRedPlane(MonoImage *plane);
+	void ReplaceGreenPlane(MonoImage *plane);
+	void ReplaceBluePlane(MonoImage *plane);
+	void ReplaceHSLHuePlane(MonoImage *plane);
+	void ReplaceHSVHuePlane(MonoImage *plane);
+	void ReplaceHSIHuePlane(MonoImage *plane);
+	void ReplaceHSLSaturationPlane(MonoImage *plane);
+	void ReplaceHSVSaturationPlane(MonoImage *plane);
+	void ReplaceHSISaturationPlane(MonoImage *plane);
+	void ReplaceLuminancePlane(MonoImage *plane);
+	void ReplaceValuePlane(MonoImage *plane);
+	void ReplaceIntensityPlane(MonoImage *plane);
+	void ColorEqualize();
+	void LuminanceEqualize();
+	
+private:
+	BinaryImage *ComputeThreshold(ColorMode colorMode, int low1, int high1, int low2, int high2, int low3, int high3);
+	void Equalize(bool allPlanes);
+	MonoImage * ExtractColorPlane(ColorMode mode, int planeNumber);
+	MonoImage * ExtractFirstColorPlane(ColorMode mode);
+	MonoImage * ExtractSecondColorPlane(ColorMode mode);
+	MonoImage * ExtractThirdColorPlane(ColorMode mode);
+	void ReplacePlane(ColorMode mode, MonoImage *plane, int planeNumber);
+	void ReplaceFirstColorPlane(ColorMode mode, MonoImage *plane);
+	void ReplaceSecondColorPlane(ColorMode mode, MonoImage *plane);
+	void ReplaceThirdColorPlane(ColorMode mode, MonoImage *plane);
+};
+
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/FrcError.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/FrcError.h
new file mode 100644
index 0000000..9bd47f4
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/FrcError.h
@@ -0,0 +1,30 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+/* Error Codes */
+#define ERR_VISION_GENERAL_ERROR			166000	// 
+#define ERR_COLOR_NOT_FOUND					166100	// TrackAPI.cpp
+#define ERR_PARTICLE_TOO_SMALL				166101	// TrackAPI.cpp
+
+#define ERR_CAMERA_FAILURE					166200	// AxisCamera.cpp
+#define ERR_CAMERA_SOCKET_CREATE_FAILED		166201	// AxisCamera.cpp
+#define ERR_CAMERA_CONNECT_FAILED			166202	// AxisCamera.cpp
+#define ERR_CAMERA_STALE_IMAGE				166203	// AxisCamera.cpp
+#define ERR_CAMERA_NOT_INITIALIZED			166204	// AxisCamera.cpp
+#define ERR_CAMERA_NO_BUFFER_AVAILABLE		166205	// AxisCamera.cpp
+#define ERR_CAMERA_HEADER_ERROR				166206	// AxisCamera.cpp
+#define ERR_CAMERA_BLOCKING_TIMEOUT			166207	// AxisCamera.cpp
+#define ERR_CAMERA_AUTHORIZATION_FAILED		166208	// AxisCamera.cpp
+#define ERR_CAMERA_TASK_SPAWN_FAILED		166209	// AxisCamera.cpp
+#define ERR_CAMERA_TASK_INPUT_OUT_OF_RANGE	166210	// AxisCamera.cpp
+#define ERR_CAMERA_COMMAND_FAILURE			166211	// AxisCamera.cpp
+
+/* error handling functions */
+int GetLastVisionError();
+const char* GetVisionErrorText(int errorCode);
+
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/HSLImage.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/HSLImage.h
new file mode 100644
index 0000000..71428aa
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/HSLImage.h
@@ -0,0 +1,22 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "ColorImage.h"
+
+/**
+ * A color image represented in HSL color space at 3 bytes per pixel.
+ */
+class HSLImage : public ColorImage
+{
+public:
+    HSLImage();
+    HSLImage(const char *fileName);
+    virtual ~HSLImage();
+};
+
+
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/ImageBase.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/ImageBase.h
new file mode 100644
index 0000000..ee5e895
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/ImageBase.h
@@ -0,0 +1,27 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <stdio.h>
+#include "nivision.h"
+#include "ErrorBase.h"
+
+#define DEFAULT_BORDER_SIZE 3
+
+class ImageBase : public ErrorBase
+{
+public:
+	ImageBase(ImageType type);
+	virtual ~ImageBase();
+	virtual void Write(const char *fileName);
+	int GetHeight();
+	int GetWidth();
+	Image *GetImaqImage();
+protected:
+	Image *m_imaqImage;
+};
+
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/MonoImage.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/MonoImage.h
new file mode 100644
index 0000000..e0e35eb
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/MonoImage.h
@@ -0,0 +1,25 @@
+/*----------------------------------------------------------------------------*/

+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */

+/* Open Source Software - may be modified and shared by FRC teams. The code   */

+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */

+/*----------------------------------------------------------------------------*/

+

+#pragma once

+

+#include "ImageBase.h"

+

+#include <vector>

+

+class MonoImage : public ImageBase

+{

+public:

+	MonoImage();

+	virtual ~MonoImage();

+

+	std::vector<EllipseMatch> *DetectEllipses(EllipseDescriptor *ellipseDescriptor,

+	                                          CurveOptions *curveOptions,

+	                                          ShapeDetectionOptions *shapeDetectionOptions,

+	                                          ROI *roi);

+	std::vector<EllipseMatch> * DetectEllipses(EllipseDescriptor *ellipseDescriptor);

+};

+

diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/RGBImage.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/RGBImage.h
new file mode 100644
index 0000000..0ef2d72
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/RGBImage.h
@@ -0,0 +1,21 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "ColorImage.h"
+
+/**
+ * A color image represented in RGB color space at 3 bytes per pixel.
+ */
+class RGBImage : public ColorImage
+{
+public:
+    RGBImage();
+    RGBImage(const char *fileName);
+    virtual ~RGBImage();
+};
+
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/Threshold.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/Threshold.h
new file mode 100644
index 0000000..9070cbf
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/Threshold.h
@@ -0,0 +1,28 @@
+/*----------------------------------------------------------------------------*/

+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */

+/* Open Source Software - may be modified and shared by FRC teams. The code   */

+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */

+/*----------------------------------------------------------------------------*/

+

+#pragma once

+

+/**

+ * Color threshold values.

+ * This object represnts the threshold values for any type of color object

+ * that is used in a threshhold operation. It simplifies passing values

+ * around in a program for color detection.

+ */

+class Threshold 

+{

+public:

+	int plane1Low;

+	int plane1High;

+	int plane2Low;

+	int plane2High;

+	int plane3Low;

+	int plane3High;

+	Threshold(int plane1Low, int plane1High,

+	          int plane2Low, int plane2High,

+	          int plane3Low, int plane3High);

+};

+

diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/VisionAPI.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/VisionAPI.h
new file mode 100644
index 0000000..ce291bf
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/Vision/VisionAPI.h
@@ -0,0 +1,148 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "nivision.h" 
+
+/*   Constants */
+
+#define DEFAULT_BORDER_SIZE				3		//VisionAPI.frcCreateImage
+#define DEFAULT_SATURATION_THRESHOLD	40		//TrackAPI.FindColor
+
+/*   Forward Declare Data Structures */
+typedef struct FindEdgeOptions_struct FindEdgeOptions;
+typedef struct CircularEdgeReport_struct CircularEdgeReport;
+
+/*   Data Structures */
+
+/**  frcParticleAnalysis returns this structure */
+typedef struct ParticleAnalysisReport_struct {
+	int 	imageHeight;
+	int 	imageWidth;
+	double 	imageTimestamp;				
+	int		particleIndex;				// the particle index analyzed
+	/* X-coordinate of the point representing the average position of the 
+	 * total particle mass, assuming every point in the particle has a constant density */
+	int 	center_mass_x;  			// MeasurementType: IMAQ_MT_CENTER_OF_MASS_X 
+	/* Y-coordinate of the point representing the average position of the 
+	 * total particle mass, assuming every point in the particle has a constant density */
+	int 	center_mass_y;  			// MeasurementType: IMAQ_MT_CENTER_OF_MASS_Y 
+	double 	center_mass_x_normalized;  	//Center of mass x value normalized to -1.0 to +1.0 range
+	double 	center_mass_y_normalized;  	//Center of mass y value normalized to -1.0 to +1.0 range
+	/* Area of the particle */
+	double 	particleArea;				// MeasurementType: IMAQ_MT_AREA
+	/* Bounding Rectangle */
+	Rect 	boundingRect;				// left/top/width/height
+	/* Percentage of the particle Area covering the Image Area. */
+	double 	particleToImagePercent;		// MeasurementType: IMAQ_MT_AREA_BY_IMAGE_AREA
+	/* Percentage of the particle Area in relation to its Particle and Holes Area */
+	double 	particleQuality;			// MeasurementType: IMAQ_MT_AREA_BY_PARTICLE_AND_HOLES_AREA
+} ParticleAnalysisReport;
+
+/** Tracking functions return this structure */
+typedef struct ColorReport_struct {
+	int		numberParticlesFound;				// Number of particles found for this color
+	int 	largestParticleNumber;				// The particle index of the largest particle
+	/* Color information */
+	float 	particleHueMax;				// HistogramReport: hue max
+	float 	particleHueMin;				// HistogramReport: hue max
+	float 	particleHueMean;			// HistogramReport: hue mean
+	float 	particleSatMax;				// HistogramReport: saturation max
+	float 	particleSatMin;				// HistogramReport: saturation max
+	float 	particleSatMean;			// HistogramReport: saturation mean
+	float 	particleLumMax;				// HistogramReport: luminance max
+	float 	particleLumMin;				// HistogramReport: luminance  max
+	float 	particleLumMean;			// HistogramReport: luminance mean
+} ColorReport;
+
+
+/*   Image Management functions */
+
+/* Create: calls imaqCreateImage. Border size is set to some default value */
+Image* frcCreateImage( ImageType type );
+
+/* Dispose: calls imaqDispose */
+int frcDispose( void* object );
+int frcDispose( const char* filename, ... ) ;
+
+/* Copy: calls imaqDuplicateImage */
+int frcCopyImage( Image* dest, const Image* source );
+
+/* Image Extraction: Crop: calls imaqScale */
+int frcCrop( Image* dest, const Image* source, Rect rect );
+
+/* Image Extraction: Scale: calls imaqScale.  Scales entire image */
+int frcScale(Image* dest, const Image* source, int xScale, int yScale, ScalingMode scaleMode );
+
+/* Read Image : calls imaqReadFile */
+int frcReadImage( Image* image, const char* fileName );
+/* Write Image : calls imaqWriteFile */
+int frcWriteImage( const Image* image, const char* fileName);
+
+/*   Measure Intensity functions */
+
+/* Histogram: calls imaqHistogram */
+HistogramReport* frcHistogram( const Image* image, int numClasses, float min, float max, Rect rect );
+/* Color Histogram: calls imaqColorHistogram2 */
+ColorHistogramReport* frcColorHistogram(const Image* image, int numClasses, ColorMode mode, Image* mask);
+
+/* Get Pixel Value: calls imaqGetPixel */
+int frcGetPixelValue( const Image* image, Point pixel, PixelValue* value );
+
+/*   Particle Analysis functions */
+
+/* Particle Filter: calls imaqParticleFilter3 */
+int frcParticleFilter(Image* dest, Image* source, const ParticleFilterCriteria2* criteria, 
+		int criteriaCount, const ParticleFilterOptions* options, Rect rect, int* numParticles);
+int frcParticleFilter(Image* dest, Image* source, const ParticleFilterCriteria2* criteria, 
+		int criteriaCount, const ParticleFilterOptions* options, int* numParticles);
+/* Morphology: calls imaqMorphology */
+int frcMorphology(Image* dest, Image* source, MorphologyMethod method);
+int frcMorphology(Image* dest, Image* source, MorphologyMethod method, const StructuringElement* structuringElement);
+/* Reject Border: calls imaqRejectBorder */
+int frcRejectBorder(Image* dest, Image* source);
+int frcRejectBorder(Image* dest, Image* source, int connectivity8);
+/* Count Particles: calls imaqCountParticles */
+int frcCountParticles(Image* image, int* numParticles);
+/* Particle Analysis Report: calls imaqMeasureParticle */
+int frcParticleAnalysis(Image* image, int particleNumber, ParticleAnalysisReport* par);
+
+/*   Image Enhancement functions */
+
+/* Equalize: calls imaqEqualize */
+int frcEqualize(Image* dest, const Image* source, float min, float max);
+int frcEqualize(Image* dest, const Image* source, float min, float max, const Image* mask);
+
+/* Color Equalize: calls imaqColorEqualize */
+int frcColorEqualize(Image* dest, const Image* source);
+int frcColorEqualize(Image* dest, const Image* source, int colorEqualization);
+
+/*   Image Thresholding & Conversion functions */
+
+/* Smart Threshold: calls imaqLocalThreshold */
+int frcSmartThreshold(Image* dest, const Image* source, unsigned int windowWidth, unsigned int windowHeight, 
+		LocalThresholdMethod method, double deviationWeight, ObjectType type);
+int frcSmartThreshold(Image* dest, const Image* source, unsigned int windowWidth, unsigned int windowHeight, 
+		LocalThresholdMethod method, double deviationWeight, ObjectType type, float replaceValue);
+
+/* Simple Threshold: calls imaqThreshold */
+int frcSimpleThreshold(Image* dest, const Image* source, float rangeMin, float rangeMax, float newValue);
+int frcSimpleThreshold(Image* dest, const Image* source, float rangeMin, float rangeMax);
+
+/* Color/Hue Threshold: calls imaqColorThreshold */
+int frcColorThreshold(Image* dest, const Image* source, ColorMode mode, 
+		const Range* plane1Range, const Range* plane2Range, const Range* plane3Range);
+int frcColorThreshold(Image* dest, const Image* source, int replaceValue, ColorMode mode, 
+		const Range* plane1Range, const Range* plane2Range, const Range* plane3Range);
+int frcHueThreshold(Image* dest, const Image* source, const Range* hueRange);
+int frcHueThreshold(Image* dest, const Image* source, const Range* hueRange, int minSaturation);
+
+/* Extract ColorHue Plane: calls imaqExtractColorPlanes */
+int frcExtractColorPlanes(const Image* image, ColorMode mode, Image* plane1, Image* plane2, Image* plane3);
+int frcExtractHuePlane(const Image* image, Image* huePlane);
+int frcExtractHuePlane(const Image* image, Image* huePlane, int minSaturation);
+
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/WPILib.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/WPILib.h
new file mode 100644
index 0000000..5af18c9
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/WPILib.h
@@ -0,0 +1,77 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#pragma once
+
+#define REAL
+
+#include "string.h"
+#include <iostream>
+
+#include "ADXL345_I2C.h"
+#include "ADXL345_SPI.h"
+#include "AnalogAccelerometer.h"
+#include "AnalogInput.h"
+#include "AnalogOutput.h"
+#include "AnalogPotentiometer.h"
+#include "AnalogTrigger.h"
+#include "AnalogTriggerOutput.h"
+#include "BuiltInAccelerometer.h"
+#include "CANJaguar.h"
+#include "CANTalon.h"
+#include "Compressor.h"
+#include "ControllerPower.h"
+#include "Counter.h"
+#include "DigitalInput.h"
+#include "DigitalOutput.h"
+#include "DigitalSource.h"
+#include "DoubleSolenoid.h"
+#include "DriverStation.h"
+#include "Encoder.h"
+#include "ErrorBase.h"
+#include "GearTooth.h"
+#include "GenericHID.h"
+#include "Gyro.h"
+#include "interfaces/Accelerometer.h"
+#include "interfaces/Potentiometer.h"
+#include "I2C.h"
+#include "IterativeRobot.h"
+#include "InterruptableSensorBase.h"
+#include "Jaguar.h"
+#include "Joystick.h"
+#include "Notifier.h"
+#include "PIDOutput.h"
+#include "PIDSource.h"
+#include "PowerDistributionPanel.h"
+#include "PWM.h"
+#include "Relay.h"
+#include "Resource.h"
+#include "RobotBase.h"
+#include "RobotDrive.h"
+#include "SensorBase.h"
+#include "Servo.h"
+#include "SampleRobot.h"
+#include "Solenoid.h"
+#include "SpeedController.h"
+#include "SPI.h"
+#include "HAL/cpp/Synchronized.hpp"
+#include "Talon.h"
+#include "TalonSRX.h"
+#include "Task.h"
+#include "Timer.h"
+#include "Ultrasonic.h"
+#include "Utility.h"
+#include "Victor.h"
+#include "VictorSP.h"
+#include "Vision/AxisCamera.h"
+#include "Vision/BinaryImage.h"
+#include "Vision/ColorImage.h"
+#include "Vision/HSLImage.h"
+#include "Vision/ImageBase.h"
+#include "Vision/MonoImage.h"
+#include "Vision/RGBImage.h"
+#include "Vision/Threshold.h"
+// XXX: #include "Vision/AxisCamera.h"
+#include "WPIErrors.h"
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/ctre/CanTalonSRX.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/ctre/CanTalonSRX.h
new file mode 100644
index 0000000..37bd5e4
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/ctre/CanTalonSRX.h
@@ -0,0 +1,374 @@
+/**

+ * @brief CAN TALON SRX driver.

+ *

+ * The TALON SRX is designed to instrument all runtime signals periodically.  The default periods are chosen to support 16 TALONs

+ * with 10ms update rate for control (throttle or setpoint).  However these can be overridden with SetStatusFrameRate. @see SetStatusFrameRate

+ * The getters for these unsolicited signals are auto generated at the bottom of this module.

+ *

+ * Likewise most control signals are sent periodically using the fire-and-forget CAN API.

+ * The setters for these unsolicited signals are auto generated at the bottom of this module.

+ *

+ * Signals that are not available in an unsolicited fashion are the Close Loop gains.

+ * For teams that have a single profile for their TALON close loop they can use either the webpage to configure their TALONs once

+ * 	or set the PIDF,Izone,CloseLoopRampRate,etc... once in the robot application.  These parameters are saved to flash so once they are

+ * 	loaded in the TALON, they will persist through power cycles and mode changes.

+ *

+ * For teams that have one or two profiles to switch between, they can use the same strategy since there are two slots to choose from

+ * and the ProfileSlotSelect is periodically sent in the 10 ms control frame.

+ *

+ * For teams that require changing gains frequently, they can use the soliciting API to get and set those parameters.  Most likely

+ * they will only need to set them in a periodic fashion as a function of what motion the application is attempting.

+ * If this API is used, be mindful of the CAN utilization reported in the driver station.

+ *

+ * Encoder position is measured in encoder edges.  Every edge is counted (similar to roboRIO 4X mode).

+ * Analog position is 10 bits, meaning 1024 ticks per rotation (0V => 3.3V).

+ * Use SetFeedbackDeviceSelect to select which sensor type you need.  Once you do that you can use GetSensorPosition()

+ * and GetSensorVelocity().  These signals are updated on CANBus every 20ms (by default).

+ * If a relative sensor is selected, you can zero (or change the current value) using SetSensorPosition.

+ *

+ * Analog Input and quadrature position (and velocity) are also explicitly reported in GetEncPosition, GetEncVel, GetAnalogInWithOv, GetAnalogInVel.

+ * These signals are available all the time, regardless of what sensor is selected at a rate of 100ms.  This allows easy instrumentation

+ * for "in the pits" checking of all sensors regardless of modeselect.  The 100ms rate is overridable for teams who want to acquire sensor

+ * data for processing, not just instrumentation.  Or just select the sensor using SetFeedbackDeviceSelect to get it at 20ms.

+ *

+ * Velocity is in position ticks / 100ms.

+ *

+ * All output units are in respect to duty cycle (throttle) which is -1023(full reverse) to +1023 (full forward).

+ *  This includes demand (which specifies duty cycle when in duty cycle mode) and rampRamp, which is in throttle units per 10ms (if nonzero).

+ *

+ * Pos and velocity close loops are calc'd as

+ * 		err = target - posOrVel.

+ * 		iErr += err;

+ * 		if(   (IZone!=0)  and  abs(err) > IZone)

+ * 			ClearIaccum()

+ * 		output = P X err + I X iErr + D X dErr + F X target

+ * 		dErr = err - lastErr

+ *	P, I,and D gains are always positive. F can be negative.

+ *	Motor direction can be reversed using SetRevMotDuringCloseLoopEn if sensor and motor are out of phase.

+ *	Similarly feedback sensor can also be reversed (multiplied by -1) if you prefer the sensor to be inverted.

+ *

+ * P gain is specified in throttle per error tick.  For example, a value of 102 is ~9.9% (which is 102/1023) throttle per 1

+ * 		ADC unit(10bit) or 1 quadrature encoder edge depending on selected sensor.

+ *

+ * I gain is specified in throttle per integrated error. For example, a value of 10 equates to ~0.99% (which is 10/1023)

+ *  	for each accumulated ADC unit(10bit) or 1 quadrature encoder edge depending on selected sensor.

+ *  	Close loop and integral accumulator runs every 1ms.

+ *

+ * D gain is specified in throttle per derivative error. For example a value of 102 equates to ~9.9% (which is 102/1023)

+ * 	per change of 1 unit (ADC or encoder) per ms.

+ *

+ * I Zone is specified in the same units as sensor position (ADC units or quadrature edges).  If pos/vel error is outside of

+ * 		this value, the integrated error will auto-clear...

+ * 		if(   (IZone!=0)  and  abs(err) > IZone)

+ * 			ClearIaccum()

+ * 		...this is very useful in preventing integral windup and is highly recommended if using full PID to keep stability low.

+ *

+ * CloseLoopRampRate is in throttle units per 1ms.  Set to zero to disable ramping.

+ * 		Works the same as RampThrottle but only is in effect when a close loop mode and profile slot is selected.

+ *

+ * auto generated using spreadsheet and WpiClassGen.csproj

+ * @link https://docs.google.com/spreadsheets/d/1OU_ZV7fZLGYUQ-Uhc8sVAmUmWTlT8XBFYK8lfjg_tac/edit#gid=1766046967

+ */

+#ifndef CanTalonSRX_H_

+#define CanTalonSRX_H_

+#include "ctre.h"				//BIT Defines + Typedefs

+#include "CtreCanNode.h"

+#include <NetworkCommunication/CANSessionMux.h>	//CAN Comm

+#include <map>

+class CanTalonSRX : public CtreCanNode

+{

+private:

+

+	/** just in case user wants to modify periods of certain status frames.

+	 * 	Default the vars to match the firmware default. */

+	uint32_t _statusRateMs[4];

+	//---------------------- Vars for opening a CAN stream if caller needs signals that require soliciting */

+	uint32_t _can_h; 	//!< Session handle for catching response params.

+	int32_t _can_stat; //!< Session handle status.

+	struct tCANStreamMessage _msgBuff[20];

+	static int const kMsgCapacity	= 20;

+	typedef std::map<uint32_t, uint32_t> sigs_t;

+	sigs_t _sigs; //!< Catches signal updates that are solicited.  Expect this to be very few.

+	void OpenSessionIfNeedBe();

+	void ProcessStreamMessages();

+	/**

+	 * Send a one shot frame to set an arbitrary signal.

+	 * Most signals are in the control frame so avoid using this API unless you have to.

+	 * Use this api for...

+	 * -A motor controller profile signal eProfileParam_XXXs.  These are backed up in flash.  If you are gain-scheduling then call this periodically.

+	 * -Default brake and limit switch signals... eOnBoot_XXXs.  Avoid doing this, use the override signals in the control frame.

+	 * Talon will automatically send a PARAM_RESPONSE after the set, so GetParamResponse will catch the latest value after a couple ms.

+	 */

+	CTR_Code SetParamRaw(uint32_t paramEnum, int32_t rawBits);

+	/**

+	 * Checks cached CAN frames and updating solicited signals.

+	 */

+	CTR_Code GetParamResponseRaw(uint32_t paramEnum, int32_t & rawBits);

+public:

+	static const int kDefaultControlPeriodMs = 10; //!< default control update rate is 10ms.

+	CanTalonSRX(int deviceNumber = 0,int controlPeriodMs = kDefaultControlPeriodMs);

+	~CanTalonSRX();

+	void Set(double value);

+	/* mode select enumerations */

+	static const int kMode_DutyCycle = 0; //!< Demand is 11bit signed duty cycle [-1023,1023].

+	static const int kMode_PositionCloseLoop = 1; //!< Position PIDF.

+	static const int kMode_VelocityCloseLoop = 2; //!< Velocity PIDF.

+	static const int kMode_CurrentCloseLoop = 3; //!< Current close loop - not done.

+	static const int kMode_VoltCompen = 4; //!< Voltage Compensation Mode - not done.  Demand is fixed pt target 8.8 volts.

+	static const int kMode_SlaveFollower = 5; //!< Demand is the 6 bit Device ID of the 'master' TALON SRX.

+	static const int kMode_NoDrive = 15; //!< Zero the output (honors brake/coast) regardless of demand.  Might be useful if we need to change modes but can't atomically change all the signals we want in between.

+	/* limit switch enumerations */

+	static const int kLimitSwitchOverride_UseDefaultsFromFlash = 1;

+	static const int kLimitSwitchOverride_DisableFwd_DisableRev = 4;

+	static const int kLimitSwitchOverride_DisableFwd_EnableRev = 5;

+	static const int kLimitSwitchOverride_EnableFwd_DisableRev = 6;

+	static const int kLimitSwitchOverride_EnableFwd_EnableRev = 7;

+	/* brake override enumerations */

+	static const int kBrakeOverride_UseDefaultsFromFlash = 0;

+	static const int kBrakeOverride_OverrideCoast = 1;

+	static const int kBrakeOverride_OverrideBrake = 2;

+	/* feedback device enumerations */

+	static const int kFeedbackDev_DigitalQuadEnc=0;

+	static const int kFeedbackDev_AnalogPot=2;

+	static const int kFeedbackDev_AnalogEncoder=3;

+	static const int kFeedbackDev_CountEveryRisingEdge=4;

+	static const int kFeedbackDev_CountEveryFallingEdge=5;

+	static const int kFeedbackDev_PosIsPulseWidth=8;

+	/* ProfileSlotSelect enumerations*/

+	static const int kProfileSlotSelect_Slot0 = 0;

+	static const int kProfileSlotSelect_Slot1 = 1;

+    /* status frame rate types */

+    static const int kStatusFrame_General = 0;

+    static const int kStatusFrame_Feedback = 1;

+    static const int kStatusFrame_Encoder = 2;

+    static const int kStatusFrame_AnalogTempVbat = 3;

+	/**

+	 * Signal enumeration for generic signal access.

+	 * Although every signal is enumerated, only use this for traffic that must be solicited.

+	 * Use the auto generated getters/setters at bottom of this header as much as possible.

+	 */

+	typedef enum _param_t{

+		eProfileParamSlot0_P=1,

+		eProfileParamSlot0_I=2,

+		eProfileParamSlot0_D=3,

+		eProfileParamSlot0_F=4,

+		eProfileParamSlot0_IZone=5,

+		eProfileParamSlot0_CloseLoopRampRate=6,

+		eProfileParamSlot1_P=11,

+		eProfileParamSlot1_I=12,

+		eProfileParamSlot1_D=13,

+		eProfileParamSlot1_F=14,

+		eProfileParamSlot1_IZone=15,

+		eProfileParamSlot1_CloseLoopRampRate=16,

+		eProfileParamSoftLimitForThreshold=21,

+		eProfileParamSoftLimitRevThreshold=22,

+		eProfileParamSoftLimitForEnable=23,

+		eProfileParamSoftLimitRevEnable=24,

+		eOnBoot_BrakeMode=31,

+		eOnBoot_LimitSwitch_Forward_NormallyClosed=32,

+		eOnBoot_LimitSwitch_Reverse_NormallyClosed=33,

+		eOnBoot_LimitSwitch_Forward_Disable=34,

+		eOnBoot_LimitSwitch_Reverse_Disable=35,

+		eFault_OverTemp=41,

+		eFault_UnderVoltage=42,

+		eFault_ForLim=43,

+		eFault_RevLim=44,

+		eFault_HardwareFailure=45,

+		eFault_ForSoftLim=46,

+		eFault_RevSoftLim=47,

+		eStckyFault_OverTemp=48,

+		eStckyFault_UnderVoltage=49,

+		eStckyFault_ForLim=50,

+		eStckyFault_RevLim=51,

+		eStckyFault_ForSoftLim=52,

+		eStckyFault_RevSoftLim=53,

+		eAppliedThrottle=61,

+		eCloseLoopErr=62,

+		eFeedbackDeviceSelect=63,

+		eRevMotDuringCloseLoopEn=64,

+		eModeSelect=65,

+		eProfileSlotSelect=66,

+		eRampThrottle=67,

+		eRevFeedbackSensor=68,

+		eLimitSwitchEn=69,

+		eLimitSwitchClosedFor=70,

+		eLimitSwitchClosedRev=71,

+		eSensorPosition=73,

+		eSensorVelocity=74,

+		eCurrent=75,

+		eBrakeIsEnabled=76,

+		eEncPosition=77,

+		eEncVel=78,

+		eEncIndexRiseEvents=79,

+		eQuadApin=80,

+		eQuadBpin=81,

+		eQuadIdxpin=82,

+		eAnalogInWithOv=83,

+		eAnalogInVel=84,

+		eTemp=85,

+		eBatteryV=86,

+		eResetCount=87,

+		eResetFlags=88,

+		eFirmVers=89,

+		eSettingsChanged=90,

+		eQuadFilterEn=91,	

+		ePidIaccum=93,

+	}param_t;

+    /*---------------------setters and getters that use the solicated param request/response-------------*//**

+     * Send a one shot frame to set an arbitrary signal.

+     * Most signals are in the control frame so avoid using this API unless you have to.

+     * Use this api for...

+     * -A motor controller profile signal eProfileParam_XXXs.  These are backed up in flash.  If you are gain-scheduling then call this periodically.

+     * -Default brake and limit switch signals... eOnBoot_XXXs.  Avoid doing this, use the override signals in the control frame.

+     * Talon will automatically send a PARAM_RESPONSE after the set, so GetParamResponse will catch the latest value after a couple ms.

+     */

+	CTR_Code SetParam(param_t paramEnum, double value);

+	/**

+	 * Asks TALON to immedietely respond with signal value.  This API is only used for signals that are not sent periodically.

+	 * This can be useful for reading params that rarely change like Limit Switch settings and PIDF values.

+	  * @param param to request.

+	 */

+	CTR_Code RequestParam(param_t paramEnum);

+	CTR_Code GetParamResponse(param_t paramEnum, double & value);

+	CTR_Code GetParamResponseInt32(param_t paramEnum, int & value);

+    /*----- getters and setters that use param request/response. These signals are backed up in flash and will survive a power cycle. ---------*/

+	/*----- If your application requires changing these values consider using both slots and switch between slot0 <=> slot1. ------------------*/

+	/*----- If your application requires changing these signals frequently then it makes sense to leverage this API. --------------------------*/

+	/*----- Getters don't block, so it may require several calls to get the latest value. --------------------------*/

+	CTR_Code SetPgain(unsigned slotIdx,double gain);

+	CTR_Code SetIgain(unsigned slotIdx,double gain);

+	CTR_Code SetDgain(unsigned slotIdx,double gain);

+	CTR_Code SetFgain(unsigned slotIdx,double gain);

+	CTR_Code SetIzone(unsigned slotIdx,int zone);

+	CTR_Code SetCloseLoopRampRate(unsigned slotIdx,int closeLoopRampRate);

+	CTR_Code SetSensorPosition(int pos);

+	CTR_Code SetForwardSoftLimit(int forwardLimit);

+	CTR_Code SetReverseSoftLimit(int reverseLimit);

+	CTR_Code SetForwardSoftEnable(int enable);

+	CTR_Code SetReverseSoftEnable(int enable);

+	CTR_Code GetPgain(unsigned slotIdx,double & gain);

+	CTR_Code GetIgain(unsigned slotIdx,double & gain);

+	CTR_Code GetDgain(unsigned slotIdx,double & gain);

+	CTR_Code GetFgain(unsigned slotIdx,double & gain);

+	CTR_Code GetIzone(unsigned slotIdx,int & zone);

+	CTR_Code GetCloseLoopRampRate(unsigned slotIdx,int & closeLoopRampRate);

+	CTR_Code GetForwardSoftLimit(int & forwardLimit);

+	CTR_Code GetReverseSoftLimit(int & reverseLimit);

+	CTR_Code GetForwardSoftEnable(int & enable);

+	CTR_Code GetReverseSoftEnable(int & enable);

+	/**

+	 * Change the periodMs of a TALON's status frame.  See kStatusFrame_* enums for what's available.

+	 */

+	CTR_Code SetStatusFrameRate(unsigned frameEnum, unsigned periodMs);

+	/**

+	 * Clear all sticky faults in TALON.

+	 */

+	CTR_Code ClearStickyFaults();

+    /*------------------------ auto generated.  This API is optimal since it uses the fire-and-forget CAN interface ----------------------*/

+    /*------------------------ These signals should cover the majority of all use cases. ----------------------------------*/

+	CTR_Code GetFault_OverTemp(int &param);

+	CTR_Code GetFault_UnderVoltage(int &param);

+	CTR_Code GetFault_ForLim(int &param);

+	CTR_Code GetFault_RevLim(int &param);

+	CTR_Code GetFault_HardwareFailure(int &param);

+	CTR_Code GetFault_ForSoftLim(int &param);

+	CTR_Code GetFault_RevSoftLim(int &param);

+	CTR_Code GetStckyFault_OverTemp(int &param);

+	CTR_Code GetStckyFault_UnderVoltage(int &param);

+	CTR_Code GetStckyFault_ForLim(int &param);

+	CTR_Code GetStckyFault_RevLim(int &param);

+	CTR_Code GetStckyFault_ForSoftLim(int &param);

+	CTR_Code GetStckyFault_RevSoftLim(int &param);

+	CTR_Code GetAppliedThrottle(int &param);

+	CTR_Code GetCloseLoopErr(int &param);

+	CTR_Code GetFeedbackDeviceSelect(int &param);

+	CTR_Code GetModeSelect(int &param);

+	CTR_Code GetLimitSwitchEn(int &param);

+	CTR_Code GetLimitSwitchClosedFor(int &param);

+	CTR_Code GetLimitSwitchClosedRev(int &param);

+	CTR_Code GetSensorPosition(int &param);

+	CTR_Code GetSensorVelocity(int &param);

+	CTR_Code GetCurrent(double &param);

+	CTR_Code GetBrakeIsEnabled(int &param);

+	CTR_Code GetEncPosition(int &param);

+	CTR_Code GetEncVel(int &param);

+	CTR_Code GetEncIndexRiseEvents(int &param);

+	CTR_Code GetQuadApin(int &param);

+	CTR_Code GetQuadBpin(int &param);

+	CTR_Code GetQuadIdxpin(int &param);

+	CTR_Code GetAnalogInWithOv(int &param);

+	CTR_Code GetAnalogInVel(int &param);

+	CTR_Code GetTemp(double &param);

+	CTR_Code GetBatteryV(double &param);

+	CTR_Code GetResetCount(int &param);

+	CTR_Code GetResetFlags(int &param);

+	CTR_Code GetFirmVers(int &param);

+	CTR_Code SetDemand(int param);

+	CTR_Code SetOverrideLimitSwitchEn(int param);

+	CTR_Code SetFeedbackDeviceSelect(int param);

+	CTR_Code SetRevMotDuringCloseLoopEn(int param);

+	CTR_Code SetOverrideBrakeType(int param);

+	CTR_Code SetModeSelect(int param);

+	CTR_Code SetModeSelect(int modeSelect,int demand);

+	CTR_Code SetProfileSlotSelect(int param);

+	CTR_Code SetRampThrottle(int param);

+	CTR_Code SetRevFeedbackSensor(int param);

+};

+extern "C" {

+	void *c_TalonSRX_Create(int deviceNumber, int controlPeriodMs);

+	void c_TalonSRX_Destroy(void *handle);

+	CTR_Code c_TalonSRX_SetParam(void *handle, int paramEnum, double value);

+	CTR_Code c_TalonSRX_RequestParam(void *handle, int paramEnum);

+	CTR_Code c_TalonSRX_GetParamResponse(void *handle, int paramEnum, double *value);

+	CTR_Code c_TalonSRX_GetParamResponseInt32(void *handle, int paramEnum, int *value);

+	CTR_Code c_TalonSRX_SetStatusFrameRate(void *handle, unsigned frameEnum, unsigned periodMs);

+	CTR_Code c_TalonSRX_ClearStickyFaults(void *handle);

+	CTR_Code c_TalonSRX_GetFault_OverTemp(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetFault_UnderVoltage(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetFault_ForLim(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetFault_RevLim(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetFault_HardwareFailure(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetFault_ForSoftLim(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetFault_RevSoftLim(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetStckyFault_OverTemp(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetStckyFault_UnderVoltage(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetStckyFault_ForLim(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetStckyFault_RevLim(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetStckyFault_ForSoftLim(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetStckyFault_RevSoftLim(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetAppliedThrottle(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetCloseLoopErr(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetFeedbackDeviceSelect(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetModeSelect(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetLimitSwitchEn(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetLimitSwitchClosedFor(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetLimitSwitchClosedRev(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetSensorPosition(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetSensorVelocity(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetCurrent(void *handle, double *param);

+	CTR_Code c_TalonSRX_GetBrakeIsEnabled(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetEncPosition(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetEncVel(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetEncIndexRiseEvents(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetQuadApin(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetQuadBpin(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetQuadIdxpin(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetAnalogInWithOv(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetAnalogInVel(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetTemp(void *handle, double *param);

+	CTR_Code c_TalonSRX_GetBatteryV(void *handle, double *param);

+	CTR_Code c_TalonSRX_GetResetCount(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetResetFlags(void *handle, int *param);

+	CTR_Code c_TalonSRX_GetFirmVers(void *handle, int *param);

+	CTR_Code c_TalonSRX_SetDemand(void *handle, int param);

+	CTR_Code c_TalonSRX_SetOverrideLimitSwitchEn(void *handle, int param);

+	CTR_Code c_TalonSRX_SetFeedbackDeviceSelect(void *handle, int param);

+	CTR_Code c_TalonSRX_SetRevMotDuringCloseLoopEn(void *handle, int param);

+	CTR_Code c_TalonSRX_SetOverrideBrakeType(void *handle, int param);

+	CTR_Code c_TalonSRX_SetModeSelect(void *handle, int param);

+	CTR_Code c_TalonSRX_SetProfileSlotSelect(void *handle, int param);

+	CTR_Code c_TalonSRX_SetRampThrottle(void *handle, int param);

+	CTR_Code c_TalonSRX_SetRevFeedbackSensor(void *handle, int param);

+}

+#endif

+

diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/ctre/CtreCanNode.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/ctre/CtreCanNode.h
new file mode 100644
index 0000000..59e0939
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/ctre/CtreCanNode.h
@@ -0,0 +1,116 @@
+#ifndef CtreCanNode_H_

+#define CtreCanNode_H_

+#include "ctre.h"				//BIT Defines + Typedefs

+#include <NetworkCommunication/CANSessionMux.h>	//CAN Comm

+#include <pthread.h>

+#include <map>

+#include <string.h> // memcpy

+#include <sys/time.h>

+class CtreCanNode

+{

+public:

+	CtreCanNode(UINT8 deviceNumber);

+    ~CtreCanNode();

+

+	UINT8 GetDeviceNumber()

+	{

+		return _deviceNumber;

+	}

+protected:

+

+

+	template <typename T> class txTask{

+		public:

+			uint32_t arbId;

+			T * toSend;

+			T * operator -> ()

+			{

+				return toSend;

+			}

+			T & operator*()

+			{

+				return *toSend;

+			}

+			bool IsEmpty()

+			{

+				if(toSend == 0)

+					return true;

+				return false;

+			}

+	};

+	template <typename T> class recMsg{

+		public:

+			uint32_t arbId;

+			uint8_t bytes[8];

+			CTR_Code err;

+			T * operator -> ()

+			{

+				return (T *)bytes;

+			}

+			T & operator*()

+			{

+				return *(T *)bytes;

+			}

+	};

+	UINT8 _deviceNumber;

+	void RegisterRx(uint32_t arbId);

+	void RegisterTx(uint32_t arbId, uint32_t periodMs);

+

+	CTR_Code GetRx(uint32_t arbId,uint8_t * dataBytes,uint32_t timeoutMs);

+	void FlushTx(uint32_t arbId);

+

+	template<typename T> txTask<T> GetTx(uint32_t arbId)

+	{

+		txTask<T> retval = {0};

+		txJobs_t::iterator i = _txJobs.find(arbId);

+		if(i != _txJobs.end()){

+			retval.arbId = i->second.arbId;

+			retval.toSend = (T*)i->second.toSend;

+		}

+		return retval;

+	}

+	template<class T> void FlushTx(T & par)

+	{

+		FlushTx(par.arbId);

+	}

+

+	template<class T> recMsg<T> GetRx(uint32_t arbId, uint32_t timeoutMs)

+	{

+		recMsg<T> retval;

+		retval.err = GetRx(arbId,retval.bytes, timeoutMs);

+		return retval;

+	}

+

+private:

+

+	class txJob_t {

+		public:

+			uint32_t arbId;

+			uint8_t toSend[8];

+			uint32_t periodMs;

+	};

+

+	class rxEvent_t{

+		public:

+			uint8_t bytes[8];

+			struct timespec time;

+			rxEvent_t()

+			{

+				bytes[0] = 0;

+				bytes[1] = 0;

+				bytes[2] = 0;

+				bytes[3] = 0;

+				bytes[4] = 0;

+				bytes[5] = 0;

+				bytes[6] = 0;

+				bytes[7] = 0;

+			}

+	};

+

+	typedef std::map<uint32_t,txJob_t> txJobs_t;

+	txJobs_t _txJobs;

+

+	typedef std::map<uint32_t,rxEvent_t> rxRxEvents_t;

+	rxRxEvents_t _rxRxEvents;

+};

+#endif

diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/ctre/ctre.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/ctre/ctre.h
new file mode 100644
index 0000000..c2d3f69
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/ctre/ctre.h
@@ -0,0 +1,50 @@
+#ifndef GLOBAL_H

+#define GLOBAL_H

+

+//Bit Defines

+#define BIT0 0x01

+#define BIT1 0x02

+#define BIT2 0x04

+#define BIT3 0x08

+#define BIT4 0x10

+#define BIT5 0x20

+#define BIT6 0x40

+#define BIT7 0x80

+#define BIT8  0x0100

+#define BIT9  0x0200

+#define BIT10 0x0400

+#define BIT11 0x0800

+#define BIT12 0x1000

+#define BIT13 0x2000

+#define BIT14 0x4000

+#define BIT15 0x8000

+

+//Signed

+typedef	signed char	INT8;

+typedef	signed short	INT16;

+typedef	signed int	INT32;

+typedef	signed long long INT64;

+

+//Unsigned

+typedef	unsigned char	UINT8;

+typedef	unsigned short	UINT16;

+typedef	unsigned int	UINT32;

+typedef	unsigned long long UINT64;

+

+//Other

+typedef	unsigned char	UCHAR;

+typedef unsigned short	USHORT;

+typedef	unsigned int	UINT;

+typedef unsigned long	ULONG;

+

+typedef enum {

+		CTR_OKAY,				//!< No Error - Function executed as expected

+		CTR_RxTimeout,			//!< CAN frame has not been received within specified period of time.

+		CTR_TxTimeout,			//!< Not used.

+		CTR_InvalidParamValue, 	//!< Caller passed an invalid param

+		CTR_UnexpectedArbId,	//!< Specified CAN Id is invalid.

+		CTR_TxFailed,			//!< Could not transmit the CAN frame.

+		CTR_SigNotUpdated,		//!< Have not received an value response for signal.

+}CTR_Code;

+

+#endif

diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/nivision.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/nivision.h
new file mode 100644
index 0000000..09bb984
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/nivision.h
@@ -0,0 +1,5345 @@
+/*============================================================================*/
+/*                        IMAQ Vision                                         */
+/*----------------------------------------------------------------------------*/
+/*    Copyright (c) National Instruments 2001.  All Rights Reserved.          */
+/*----------------------------------------------------------------------------*/
+/*                                                                            */
+/* Title:       NIVision.h                                                    */
+/*                                                                            */
+/*============================================================================*/
+#if !defined(NiVision_h)
+#define NiVision_h
+
+//============================================================================
+//  Includes
+//============================================================================
+#include <stddef.h>
+
+
+//============================================================================
+//  Control Defines
+//============================================================================
+#if !defined(IMAQ_IMPORT)
+	#ifndef __GNUC__
+		#define IMAQ_IMPORT __declspec(dllimport)
+	#else
+		#define IMAQ_IMPORT
+	#endif
+#endif
+
+#if !defined(IMAQ_FUNC)
+    #if !defined(__cplusplus)
+        #define IMAQ_FUNC IMAQ_IMPORT
+    #else
+        #define IMAQ_FUNC extern "C" IMAQ_IMPORT
+    #endif
+#endif
+
+#if !defined(IMAQ_STDCALL)
+	#ifndef __GNUC__
+		#define IMAQ_STDCALL __stdcall
+	#else
+		#define IMAQ_STDCALL 
+	#endif
+#endif
+
+#ifdef _CVI_
+#pragma EnableLibraryRuntimeChecking
+#include <ansi_c.h>
+#endif
+
+#define IMAQ_CALLBACK __cdecl
+
+//============================================================================
+//  Manifest Constants
+//============================================================================
+#ifndef NULL
+    #ifdef __cplusplus
+        #define NULL    0
+    #else
+        #define NULL    ((void *)0)
+    #endif
+#endif
+
+#ifndef FALSE
+    #define FALSE               0
+#endif
+
+#ifndef TRUE
+    #define TRUE                1
+#endif
+
+#define IMAQ_DEFAULT_SHOW_COORDINATES TRUE
+#define IMAQ_DEFAULT_MAX_ICONS_PER_LINE 4
+#define IMAQ_DEFAULT_LEARNING_MODE IMAQ_LEARN_SHIFT_INFORMATION
+#define IMAQ_DEFAULT_BMP_COMPRESS FALSE
+#define IMAQ_DEFAULT_PNG_QUALITY 750
+#define IMAQ_DEFAULT_JPEG_QUALITY 750
+#define IMAQ_ALL_CONTOURS -1
+#define IMAQ_ALL_WINDOWS -1
+#define IMAQ_SHIFT      1
+#define IMAQ_ALT        2
+#define IMAQ_CTRL       4
+#define IMAQ_CAPS_LOCK  8
+#define IMAQ_MODAL_DIALOG -1
+#define IMAQ_INIT_RGB_TRANSPARENT {   0,   0,   0, 1 }
+#define IMAQ_INIT_RGB_RED         {   0,   0, 255, 0 }
+#define IMAQ_INIT_RGB_BLUE        { 255,   0,   0, 0 }
+#define IMAQ_INIT_RGB_GREEN       {   0, 255,   0, 0 }
+#define IMAQ_INIT_RGB_YELLOW      {   0, 255, 255, 0 }
+#define IMAQ_INIT_RGB_WHITE       { 255, 255, 255, 0 }
+#define IMAQ_INIT_RGB_BLACK       {   0,   0,   0, 0 }
+#define IMAQ_USE_DEFAULT_QUALITY  -1
+#define IMAQ_ALL_SAMPLES          -1
+#define IMAQ_ALL_OBJECTS          -1
+#define IMAQ_ALL_CHARACTERS       -1
+
+//============================================================================
+//  Predefined Valid Characters
+//============================================================================
+#define IMAQ_ANY_CHARACTER          ""                                                                  //Any Character
+#define IMAQ_ALPHABETIC             "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"              //Alphabetic
+#define IMAQ_ALPHANUMERIC           "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"    //Alphanumeric
+#define IMAQ_UPPERCASE_LETTERS      "ABCDEFGHIJKLMNOPQRSTUVWXYZ"                                        //Uppercase Letters
+#define IMAQ_LOWERCASE_LETTERS      "abcdefghijklmnopqrstuvwxyz"                                        //Lowercase Letters
+#define IMAQ_DECIMAL_DIGITS         "0123456789"                                                        //Decimal Digits
+#define IMAQ_HEXADECIMAL_DIGITS     "0123456789ABCDEFabcdef"                                            //Hexadecimal Digits
+#define IMAQ_PATTERN                "\xFF"                                                              //Pattern (A single character string with the character value set to 255)
+#define IMAQ_FORCE_SPACE            " "                                                                 //Force Space
+
+//============================================================================
+//  Macros
+//============================================================================
+#define IMAQ_NO_RECT imaqMakeRect( 0, 0, 0x7FFFFFFF, 0x7FFFFFFF)
+#define IMAQ_NO_ROTATED_RECT imaqMakeRotatedRect( 0, 0, 0x7FFFFFFF, 0x7FFFFFFF, 0)
+#define IMAQ_NO_POINT imaqMakePoint( -1, -1)
+#define IMAQ_NO_POINT_FLOAT imaqMakePointFloat( -1.0, -1.0 )
+#define IMAQ_NO_OFFSET imaqMakePointFloat( 0.0, 0.0 )
+
+
+
+//============================================================================
+//  When in Borland, some functions must be mapped to different names.
+//  This accomplishes said task.
+//============================================================================
+#if defined(__BORLANDC__) || (defined(_CVI_) && defined(_NI_BC_))
+    #define imaqMakePoint imaqMakePoint_BC
+    #define imaqMakePointFloat imaqMakePointFloat_BC
+#endif
+
+
+//============================================================================
+//  When in Watcom, some functions must be mapped to different names.
+//  This accomplishes said task.
+//============================================================================
+#if defined(__WATCOMC__) || (defined(_CVI_) && defined(_NI_WC_))
+    #define imaqMakePoint imaqMakePoint_BC
+    #define imaqMakePointFloat imaqMakePointFloat_BC
+#endif
+
+//============================================================================
+//  If using Visual C++, force startup & shutdown code to run.
+//============================================================================
+#if defined(_MSC_VER) && !defined(_CVI_) && !defined(__BORLANDC__)
+    #pragma comment(linker, "/INCLUDE:_nivision_startup_shutdown")
+    #pragma comment(linker, "/DEFAULTLIB:nivision.lib")
+#endif
+
+//============================================================================
+//  Error Codes
+//============================================================================
+#define ERR_SUCCESS                                                  0 // No error.
+#define ERR_SYSTEM_ERROR                                             -1074396160 // System error.
+#define ERR_OUT_OF_MEMORY                                            -1074396159 // Not enough memory for requested operation.
+#define ERR_MEMORY_ERROR                                             -1074396158 // Memory error.
+#define ERR_UNREGISTERED                                             -1074396157 // Unlicensed copy of NI Vision.
+#define ERR_NEED_FULL_VERSION                                        -1074396156 // The function requires an NI Vision 5.0 Advanced license.
+#define ERR_UNINIT                                                   -1074396155 // NI Vision did not initialize properly.
+#define ERR_IMAGE_TOO_SMALL                                          -1074396154 // The image is not large enough for the operation.
+#define ERR_BARCODE_CODABAR                                          -1074396153 // The barcode is not a valid Codabar barcode.
+#define ERR_BARCODE_CODE39                                           -1074396152 // The barcode is not a valid Code 3 of 9 barcode.
+#define ERR_BARCODE_CODE93                                           -1074396151 // The barcode is not a valid Code93 barcode.
+#define ERR_BARCODE_CODE128                                          -1074396150 // The barcode is not a valid Code128 barcode.
+#define ERR_BARCODE_EAN8                                             -1074396149 // The barcode is not a valid EAN8 barcode.
+#define ERR_BARCODE_EAN13                                            -1074396148 // The barcode is not a valid EAN13 barcode.
+#define ERR_BARCODE_I25                                              -1074396147 // The barcode is not a valid Interleaved 2 of 5 barcode.
+#define ERR_BARCODE_MSI                                              -1074396146 // The barcode is not a valid MSI barcode.
+#define ERR_BARCODE_UPCA                                             -1074396145 // The barcode is not a valid UPCA barcode.
+#define ERR_BARCODE_CODE93_SHIFT                                     -1074396144 // The Code93 barcode contains invalid shift encoding.
+#define ERR_BARCODE_TYPE                                             -1074396143 // The barcode type is invalid.
+#define ERR_BARCODE_INVALID                                          -1074396142 // The image does not represent a valid linear barcode.
+#define ERR_BARCODE_CODE128_FNC                                      -1074396141 // The FNC value in the Code128 barcode is not located before the first data value.
+#define ERR_BARCODE_CODE128_SET                                      -1074396140 // The starting code set in the Code128 barcode is not valid.
+#define ERR_ROLLBACK_RESOURCE_OUT_OF_MEMORY                          -1074396139 // Not enough reserved memory in the timed environment for the requested operation.
+#define ERR_ROLLBACK_NOT_SUPPORTED                                   -1074396138 // The function is not supported when a time limit is active.
+#define ERR_DIRECTX_DLL_NOT_FOUND                                    -1074396137 // Quartz.dll not found.  Install DirectX 8.1 or later.
+#define ERR_DIRECTX_INVALID_FILTER_QUALITY                           -1074396136 // The filter quality you provided is invalid. Valid quality values range from -1 to 1000.
+#define ERR_INVALID_BUTTON_LABEL                                     -1074396135 // Invalid button label.
+#define ERR_THREAD_INITIALIZING                                      -1074396134 // Could not execute the function in the separate thread because the thread has not completed initialization.
+#define ERR_THREAD_COULD_NOT_INITIALIZE                              -1074396133 // Could not execute the function in the separate thread because the thread could not initialize.
+#define ERR_MASK_NOT_TEMPLATE_SIZE                                   -1074396132 // The mask must be the same size as the template.
+#define ERR_NOT_RECT_OR_ROTATED_RECT                                 -1074396130 // The ROI must only have either a single Rectangle contour or a single Rotated Rectangle contour.
+#define ERR_ROLLBACK_UNBOUNDED_INTERFACE                             -1074396129 // During timed execution, you must use the preallocated version of this operation.
+#define ERR_ROLLBACK_RESOURCE_CONFLICT_3                             -1074396128 // An image being modified by one process cannot be requested by another process while a time limit is active.
+#define ERR_ROLLBACK_RESOURCE_CONFLICT_2                             -1074396127 // An image with pattern matching, calibration, or overlay information cannot be manipulated while a time limit is active.
+#define ERR_ROLLBACK_RESOURCE_CONFLICT_1                             -1074396126 // An image created before a time limit is started cannot be resized while a time limit is active.
+#define ERR_INVALID_CONTRAST_THRESHOLD                               -1074396125 // Invalid contrast threshold. The threshold value must be greater than 0. 
+#define ERR_INVALID_CALIBRATION_ROI_MODE                             -1074396124 // NI Vision does not support the calibration ROI mode you supplied.
+#define ERR_INVALID_CALIBRATION_MODE                                 -1074396123 // NI Vision does not support the calibration mode you supplied.
+#define ERR_DRAWTEXT_COLOR_MUST_BE_GRAYSCALE                         -1074396122 // Set the foreground and background text colors to grayscale to draw on a U8 image.
+#define ERR_SATURATION_THRESHOLD_OUT_OF_RANGE                        -1074396121 // The value of the saturation threshold must be from 0 to 255.
+#define ERR_NOT_IMAGE                                                -1074396120 // Not an image.
+#define ERR_CUSTOMDATA_INVALID_KEY                                   -1074396119 // They custom data key you supplied is invalid. The only valid character values are decimal 32-126 and 161-255. There must also be no repeated, leading, or trailing spaces.
+#define ERR_INVALID_STEP_SIZE                                        -1074396118 // Step size must be greater than zero and less than Image size
+#define ERR_MATRIX_SIZE                                              -1074396117 // Invalid matrix size in the structuring element.
+#define ERR_CALIBRATION_INSF_POINTS                                  -1074396116 // Insufficient number of calibration feature points.
+#define ERR_CALIBRATION_IMAGE_CORRECTED                              -1074396115 // The operation is invalid in a corrected image.
+#define ERR_CALIBRATION_INVALID_ROI                                  -1074396114 // The ROI contains an invalid contour type or is not contained in the ROI learned for calibration.
+#define ERR_CALIBRATION_IMAGE_UNCALIBRATED                           -1074396113 // The source/input image has not been calibrated.
+#define ERR_INCOMP_MATRIX_SIZE                                       -1074396112 // The number of pixel and real-world coordinates must be equal.
+#define ERR_CALIBRATION_FAILED_TO_FIND_GRID                          -1074396111 // Unable to automatically detect grid because the image is too distorted.
+#define ERR_CALIBRATION_INFO_VERSION                                 -1074396110 // Invalid calibration information version.
+#define ERR_CALIBRATION_INVALID_SCALING_FACTOR                       -1074396109 // Invalid calibration scaling factor.
+#define ERR_CALIBRATION_ERRORMAP                                     -1074396108 // The calibration error map cannot be computed.
+#define ERR_CALIBRATION_INFO_1                                       -1074396107 // Invalid calibration template image.
+#define ERR_CALIBRATION_INFO_2                                       -1074396106 // Invalid calibration template image.
+#define ERR_CALIBRATION_INFO_3                                       -1074396105 // Invalid calibration template image.
+#define ERR_CALIBRATION_INFO_4                                       -1074396104 // Invalid calibration template image.
+#define ERR_CALIBRATION_INFO_5                                       -1074396103 // Invalid calibration template image.
+#define ERR_CALIBRATION_INFO_6                                       -1074396102 // Invalid calibration template image.
+#define ERR_CALIBRATION_INFO_MICRO_PLANE                             -1074396101 // Invalid calibration template image.
+#define ERR_CALIBRATION_INFO_PERSPECTIVE_PROJECTION                  -1074396100 // Invalid calibration template image.
+#define ERR_CALIBRATION_INFO_SIMPLE_TRANSFORM                        -1074396099 // Invalid calibration template image.
+#define ERR_RESERVED_MUST_BE_NULL                                    -1074396098 // You must pass NULL for the reserved parameter.
+#define ERR_INVALID_PARTICLE_PARAMETER_VALUE                         -1074396097 // You entered an invalid selection in the particle parameter.
+#define ERR_NOT_AN_OBJECT                                            -1074396096 // Not an object.
+#define ERR_CALIBRATION_DUPLICATE_REFERENCE_POINT                    -1074396095 // The reference points passed are inconsistent.  At least two similar pixel coordinates correspond to different real-world coordinates.
+#define ERR_ROLLBACK_RESOURCE_CANNOT_UNLOCK                          -1074396094 // A resource conflict occurred in the timed environment. Two processes cannot manage the same resource and be time bounded.
+#define ERR_ROLLBACK_RESOURCE_LOCKED                                 -1074396093 // A resource conflict occurred in the timed environment. Two processes cannot access the same resource and be time bounded.
+#define ERR_ROLLBACK_RESOURCE_NON_EMPTY_INITIALIZE                   -1074396092 // Multiple timed environments are not supported.
+#define ERR_ROLLBACK_RESOURCE_UNINITIALIZED_ENABLE                   -1074396091 // A time limit cannot be started until the timed environment is initialized.
+#define ERR_ROLLBACK_RESOURCE_ENABLED                                -1074396090 // Multiple timed environments are not supported.
+#define ERR_ROLLBACK_RESOURCE_REINITIALIZE                           -1074396089 // The timed environment is already initialized.
+#define ERR_ROLLBACK_RESIZE                                          -1074396088 // The results of the operation exceeded the size limits on the output data arrays.
+#define ERR_ROLLBACK_STOP_TIMER                                      -1074396087 // No time limit is available to stop.
+#define ERR_ROLLBACK_START_TIMER                                     -1074396086 // A time limit could not be set.
+#define ERR_ROLLBACK_INIT_TIMER                                      -1074396085 // The timed environment could not be initialized.
+#define ERR_ROLLBACK_DELETE_TIMER                                    -1074396084 // No initialized timed environment is available to close.
+#define ERR_ROLLBACK_TIMEOUT                                         -1074396083 // The time limit has expired.
+#define ERR_PALETTE_NOT_SUPPORTED                                    -1074396082 // Only 8-bit images support the use of palettes.  Either do not use a palette, or convert your image to an 8-bit image before using a palette.
+#define ERR_BAD_PASSWORD                                             -1074396081 // Incorrect password.
+#define ERR_INVALID_IMAGE_TYPE                                       -1074396080 // Invalid image type.
+#define ERR_INVALID_METAFILE_HANDLE                                  -1074396079 // Invalid metafile handle.
+#define ERR_INCOMP_TYPE                                              -1074396077 // Incompatible image type.
+#define ERR_COORD_SYS_FIRST_AXIS                                     -1074396076 // Unable to fit a line for the primary axis.
+#define ERR_COORD_SYS_SECOND_AXIS                                    -1074396075 // Unable to fit a line for the secondary axis.
+#define ERR_INCOMP_SIZE                                              -1074396074 // Incompatible image size.
+#define ERR_MASK_OUTSIDE_IMAGE                                       -1074396073 // When the mask's offset was applied, the mask was entirely outside of the image.
+#define ERR_INVALID_BORDER                                           -1074396072 // Invalid image border.
+#define ERR_INVALID_SCAN_DIRECTION                                   -1074396071 // Invalid scan direction.
+#define ERR_INVALID_FUNCTION                                         -1074396070 // Unsupported function.
+#define ERR_INVALID_COLOR_MODE                                       -1074396069 // NI Vision does not support the color mode you specified.
+#define ERR_INVALID_ACTION                                           -1074396068 // The function does not support the requested action.
+#define ERR_IMAGES_NOT_DIFF                                          -1074396067 // The source image and destination image must be different.
+#define ERR_INVALID_POINTSYMBOL                                      -1074396066 // Invalid point symbol.
+#define ERR_CANT_RESIZE_EXTERNAL                                     -1074396065 // Cannot resize an image in an acquisition buffer.
+#define ERR_EXTERNAL_NOT_SUPPORTED                                   -1074396064 // This operation is not supported for images in an acquisition buffer.
+#define ERR_EXTERNAL_ALIGNMENT                                       -1074396063 // The external buffer must be aligned on a 4-byte boundary. The line width and border pixels must be 4-byte aligned, as well.
+#define ERR_INVALID_TOLERANCE                                        -1074396062 // The tolerance parameter must be greater than or equal to 0.
+#define ERR_INVALID_WINDOW_SIZE                                      -1074396061 // The size of each dimension of the window must be greater than 2 and less than or equal to the size of the image in the corresponding dimension.
+#define ERR_JPEG2000_LOSSLESS_WITH_FLOATING_POINT                    -1074396060 // Lossless compression cannot be used with the floating point wavelet transform mode. Either set the wavelet transform mode to integer, or use lossy compression.
+#define ERR_INVALID_MAX_ITERATIONS                                   -1074396059 // Invalid maximum number of iterations. Maximum number of iterations must be greater than zero.
+#define ERR_INVALID_ROTATION_MODE                                    -1074396058 // Invalid rotation mode.
+#define ERR_INVALID_SEARCH_VECTOR_WIDTH                              -1074396057 // Invalid search vector width. The width must be an odd number greater than zero.
+#define ERR_INVALID_MATRIX_MIRROR_MODE                               -1074396056 // Invalid matrix mirror mode.
+#define ERR_INVALID_ASPECT_RATIO                                     -1074396055 // Invalid aspect ratio. Valid aspect ratios must be greater than or equal to zero.
+#define ERR_INVALID_CELL_FILL_TYPE                                   -1074396054 // Invalid cell fill type.
+#define ERR_INVALID_BORDER_INTEGRITY                                 -1074396053 // Invalid border integrity. Valid values range from 0 to 100.
+#define ERR_INVALID_DEMODULATION_MODE                                -1074396052 // Invalid demodulation mode.
+#define ERR_INVALID_CELL_FILTER_MODE                                 -1074396051 // Invalid cell filter mode.
+#define ERR_INVALID_ECC_TYPE                                         -1074396050 // Invalid ECC type.
+#define ERR_INVALID_MATRIX_POLARITY                                  -1074396049 // Invalid matrix polarity.
+#define ERR_INVALID_CELL_SAMPLE_SIZE                                 -1074396048 // Invalid cell sample size.
+#define ERR_INVALID_LINEAR_AVERAGE_MODE                              -1074396047 // Invalid linear average mode.
+#define ERR_INVALID_2D_BARCODE_CONTRAST_FOR_ROI                      -1074396046 // When using a region of interest that is not a rectangle, you must specify the contrast mode of the barcode as either black on white or white on black.
+#define ERR_INVALID_2D_BARCODE_SUBTYPE                               -1074396045 // Invalid 2-D barcode Data Matrix subtype.
+#define ERR_INVALID_2D_BARCODE_SHAPE                                 -1074396044 // Invalid 2-D barcode shape.
+#define ERR_INVALID_2D_BARCODE_CELL_SHAPE                            -1074396043 // Invalid 2-D barcode cell shape.
+#define ERR_INVALID_2D_BARCODE_CONTRAST                              -1074396042 // Invalid 2-D barcode contrast.
+#define ERR_INVALID_2D_BARCODE_TYPE                                  -1074396041 // Invalid 2-D barcode type.
+#define ERR_DRIVER                                                   -1074396040 // Cannot access NI-IMAQ driver.
+#define ERR_IO_ERROR                                                 -1074396039 // I/O error.
+#define ERR_FIND_COORDSYS_MORE_THAN_ONE_EDGE                         -1074396038 // When searching for a coordinate system, the number of lines to fit must be 1.
+#define ERR_TIMEOUT                                                  -1074396037 // Trigger timeout.
+#define ERR_INVALID_SKELETONMODE                                     -1074396036 // The Skeleton mode you specified is invalid.
+#define ERR_TEMPLATEIMAGE_NOCIRCLE                                   -1074396035 // The template image does not contain enough information for learning the aggressive search strategy.
+#define ERR_TEMPLATEIMAGE_EDGEINFO                                   -1074396034 // The template image does not contain enough edge information for the sample size(s) requested.
+#define ERR_TEMPLATEDESCRIPTOR_LEARNSETUPDATA                        -1074396033 // Invalid template descriptor.
+#define ERR_TEMPLATEDESCRIPTOR_ROTATION_SEARCHSTRATEGY               -1074396032 // The template descriptor does not contain data required for the requested search strategy in rotation-invariant matching.
+#define ERR_INVALID_TETRAGON                                         -1074396031 // The input tetragon must have four points. The points are specified clockwise starting with the top left point. 
+#define ERR_TOO_MANY_CLASSIFICATION_SESSIONS                         -1074396030 // There are too many classification sessions open.  You must close a session before you can open another one.
+#define ERR_TIME_BOUNDED_EXECUTION_NOT_SUPPORTED                     -1074396028 // NI Vision no longer supports time-bounded execution.
+#define ERR_INVALID_COLOR_RESOLUTION                                 -1074396027 // Invalid Color Resolution for the Color Classifier
+#define ERR_INVALID_PROCESS_TYPE_FOR_EDGE_DETECTION                  -1074396026 // Invalid process type for edge detection.
+#define ERR_INVALID_ANGLE_RANGE_FOR_STRAIGHT_EDGE                    -1074396025 // Angle range value should be equal to or greater than zero.
+#define ERR_INVALID_MIN_COVERAGE_FOR_STRAIGHT_EDGE                   -1074396024 // Minimum coverage value should be greater than zero.
+#define ERR_INVALID_ANGLE_TOL_FOR_STRAIGHT_EDGE                      -1074396023 // The angle tolerance should be equal to or greater than 0.001.
+#define ERR_INVALID_SEARCH_MODE_FOR_STRAIGHT_EDGE                    -1074396022 // Invalid search mode for detecting straight edges
+#define ERR_INVALID_KERNEL_SIZE_FOR_EDGE_DETECTION                   -1074396021 // Invalid kernel size for edge detection. The minimum kernel size is 3, the maximum kernel size is 1073741823 and the kernel size must be odd.
+#define ERR_INVALID_GRADING_MODE                                     -1074396020 // Invalid grading mode.
+#define ERR_INVALID_THRESHOLD_PERCENTAGE                             -1074396019 // Invalid threshold percentage. Valid values range from 0 to 100.
+#define ERR_INVALID_EDGE_POLARITY_SEARCH_MODE                        -1074396018 // Invalid edge polarity search mode.
+#define ERR_OPENING_NEWER_AIM_GRADING_DATA                           -1074396017 // The AIM grading data attached to the image you tried to open was created with a newer version of NI Vision. Upgrade to the latest version of NI Vision to read this file.
+#define ERR_NO_VIDEO_DRIVER                                          -1074396016 // No video driver is installed.
+#define ERR_RPC_EXECUTE_IVB                                          -1074396015 // Unable to establish network connection with remote system.
+#define ERR_INVALID_VIDEO_BLIT                                       -1074396014 // RT Video Out does not support displaying the supplied image type at the selected color depth.
+#define ERR_INVALID_VIDEO_MODE                                       -1074396013 // Invalid video mode.
+#define ERR_RPC_EXECUTE                                              -1074396012 // Unable to display remote image on network connection.
+#define ERR_RPC_BIND                                                 -1074396011 // Unable to establish network connection.
+#define ERR_INVALID_FRAME_NUMBER                                     -1074396010 // Invalid frame number.
+#define ERR_DIRECTX                                                  -1074396009 // An internal DirectX error has occurred.  Try upgrading to the latest version of DirectX.
+#define ERR_DIRECTX_NO_FILTER                                        -1074396008 // An appropriate DirectX filter to process this file could not be found.  Install the filter that was used to create this AVI. Upgrading to the latest version of DirectX may correct this error.  NI Vision requires DirectX 8.1 or higher.
+#define ERR_DIRECTX_INCOMPATIBLE_COMPRESSION_FILTER                  -1074396007 // Incompatible compression filter.
+#define ERR_DIRECTX_UNKNOWN_COMPRESSION_FILTER                       -1074396006 // Unknown compression filter.
+#define ERR_INVALID_AVI_SESSION                                      -1074396005 // Invalid AVI session.
+#define ERR_DIRECTX_CERTIFICATION_FAILURE                            -1074396004 // A software key is restricting the use of this compression filter.
+#define ERR_AVI_DATA_EXCEEDS_BUFFER_SIZE                             -1074396003 // The data for this frame exceeds the data buffer size specified when creating the AVI file.
+#define ERR_INVALID_LINEGAUGEMETHOD                                  -1074396002 // Invalid line gauge method.
+#define ERR_TOO_MANY_AVI_SESSIONS                                    -1074396001 // There are too many AVI sessions open.  You must close a session before you can open another one.
+#define ERR_FILE_FILE_HEADER                                         -1074396000 // Invalid file header.
+#define ERR_FILE_FILE_TYPE                                           -1074395999 // Invalid file type.
+#define ERR_FILE_COLOR_TABLE                                         -1074395998 // Invalid color table.
+#define ERR_FILE_ARGERR                                              -1074395997 // Invalid parameter.
+#define ERR_FILE_OPEN                                                -1074395996 // File is already open for writing.
+#define ERR_FILE_NOT_FOUND                                           -1074395995 // File not found.
+#define ERR_FILE_TOO_MANY_OPEN                                       -1074395994 // Too many files open.
+#define ERR_FILE_IO_ERR                                              -1074395993 // File I/O error.
+#define ERR_FILE_PERMISSION                                          -1074395992 // File access denied.
+#define ERR_FILE_INVALID_TYPE                                        -1074395991 // NI Vision does not support the file type you specified.
+#define ERR_FILE_GET_INFO                                            -1074395990 // Could not read Vision info from file.
+#define ERR_FILE_READ                                                -1074395989 // Unable to read data.
+#define ERR_FILE_WRITE                                               -1074395988 // Unable to write data.
+#define ERR_FILE_EOF                                                 -1074395987 // Premature end of file.
+#define ERR_FILE_FORMAT                                              -1074395986 // Invalid file format.
+#define ERR_FILE_OPERATION                                           -1074395985 // Invalid file operation.
+#define ERR_FILE_INVALID_DATA_TYPE                                   -1074395984 // NI Vision does not support the file data type you specified.
+#define ERR_FILE_NO_SPACE                                            -1074395983 // Disk full.
+#define ERR_INVALID_FRAMES_PER_SECOND                                -1074395982 // The frames per second in an AVI must be greater than zero.
+#define ERR_INSUFFICIENT_BUFFER_SIZE                                 -1074395981 // The buffer that was passed in is not big enough to hold all of the data.
+#define ERR_COM_INITIALIZE                                           -1074395980 // Error initializing COM.
+#define ERR_INVALID_PARTICLE_INFO                                    -1074395979 // The image has invalid particle information.  Call imaqCountParticles on the image to create particle information.
+#define ERR_INVALID_PARTICLE_NUMBER                                  -1074395978 // Invalid particle number.
+#define ERR_AVI_VERSION                                              -1074395977 // The AVI file was created in a newer version of NI Vision. Upgrade to the latest version of NI Vision to read this AVI file.
+#define ERR_NUMBER_OF_PALETTE_COLORS                                 -1074395976 // The color palette must have exactly 0 or 256 entries.
+#define ERR_AVI_TIMEOUT                                              -1074395975 // DirectX has timed out reading or writing the AVI file.  When closing an AVI file, try adding an additional delay.  When reading an AVI file, try reducing CPU and disk load.
+#define ERR_UNSUPPORTED_JPEG2000_COLORSPACE_METHOD                   -1074395974 // NI Vision does not support reading JPEG2000 files with this colorspace method.
+#define ERR_JPEG2000_UNSUPPORTED_MULTIPLE_LAYERS                     -1074395973 // NI Vision does not support reading JPEG2000 files with more than one layer.
+#define ERR_DIRECTX_ENUMERATE_FILTERS                                -1074395972 // DirectX is unable to enumerate the compression filters. This is caused by a third-party compression filter that is either improperly installed or is preventing itself from being enumerated. Remove any recently installed compression filters and try again.
+#define ERR_INVALID_OFFSET                                           -1074395971 // The offset you specified must be size 2.
+#define ERR_INIT                                                     -1074395960 // Initialization error.
+#define ERR_CREATE_WINDOW                                            -1074395959 // Unable to create window.
+#define ERR_WINDOW_ID                                                -1074395958 // Invalid window ID.
+#define ERR_ARRAY_SIZE_MISMATCH                                      -1074395957 // The array sizes are not compatible.
+#define ERR_INVALID_QUALITY                                          -1074395956 // The quality you provided is invalid. Valid quality values range from -1 to 1000.
+#define ERR_INVALID_MAX_WAVELET_TRANSFORM_LEVEL                      -1074395955 // Invalid maximum wavelet transform level.  Valid values range from 0 to 255.
+#define ERR_INVALID_QUANTIZATION_STEP_SIZE                           -1074395954 // The quantization step size must be greater than or equal to 0.
+#define ERR_INVALID_WAVELET_TRANSFORM_MODE                           -1074395953 // Invalid wavelet transform mode.
+#define ERR_ROI_NOT_POINT                                            -1074395952 // The ROI must only have a single Point contour.
+#define ERR_ROI_NOT_POINTS                                           -1074395951 // The ROI must only have Point contours.
+#define ERR_ROI_NOT_LINE                                             -1074395950 // The ROI must only have a single Line contour.
+#define ERR_ROI_NOT_ANNULUS                                          -1074395949 // The ROI must only have a single Annulus contour.
+#define ERR_INVALID_MEASURE_PARTICLES_CALIBRATION_MODE               -1074395948 // Invalid measure particles calibration mode.
+#define ERR_INVALID_PARTICLE_CLASSIFIER_THRESHOLD_TYPE               -1074395947 // Invalid particle classifier threshold type.
+#define ERR_INVALID_DISTANCE                                         -1074395946 // Invalid Color Segmentation Distance
+#define ERR_INVALID_PARTICLE_AREA                                    -1074395945 // Invalid Color Segmenation Particle Area
+#define ERR_CLASS_NAME_NOT_FOUND                                     -1074395944 // Required Class name is not found in trained labels/Class names
+#define ERR_NUMBER_LABEL_LIMIT_EXCEEDED                              -1074395943 // Number of Labels exceeded limit of label Image type
+#define ERR_INVALID_DISTANCE_LEVEL                                   -1074395942 // Invalid Color Segmentation distance level
+#define ERR_INVALID_SVM_TYPE                                         -1074395941 // Invalid SVM model type
+#define ERR_INVALID_SVM_KERNEL                                       -1074395940 // Invalid SVM kernel type
+#define ERR_NO_SUPPORT_VECTOR_FOUND                                  -1074395939 // No Support Vector is found at SVM training
+#define ERR_COST_LABEL_NOT_FOUND                                     -1074395938 // Label name is not found in added samples
+#define ERR_EXCEEDED_SVM_MAX_ITERATION                               -1074395937 // SVM training exceeded maximim Iteration limit
+#define ERR_INVALID_SVM_PARAMETER                                    -1074395936 // Invalid SVM Parameter
+#define ERR_INVALID_IDENTIFICATION_SCORE                             -1074395935 // Invalid Identification score. Must be between 0-1000.
+#define ERR_INVALID_TEXTURE_FEATURE                                  -1074395934 // Requested for invalid texture feature
+#define ERR_INVALID_COOCCURRENCE_LEVEL                               -1074395933 // The coOccurrence Level must lie between 1 and the maximum pixel value of an image (255 for U8 image)
+#define ERR_INVALID_WAVELET_SUBBAND                                  -1074395932 // Request for invalid wavelet subBand
+#define ERR_INVALID_FINAL_STEP_SIZE                                  -1074395931 // The final step size must be lesser than the initial step size
+#define ERR_INVALID_ENERGY                                           -1074395930 // Minimum Energy should lie between 0 and 100
+#define ERR_INVALID_TEXTURE_LABEL                                    -1074395929 // The classification label must be texture or defect for texture defect classifier
+#define ERR_INVALID_WAVELET_TYPE                                     -1074395928 // The wavelet type is invalid
+#define ERR_SAME_WAVELET_BANDS_SELECTED                              -1074395927 // Same Wavelet band is selected multiple times
+#define ERR_IMAGE_SIZE_MISMATCH                                      -1074395926 // The two input image sizes are different 
+#define ERR_NUMBER_CLASS                                             -1074395920 // Invalid number of classes.
+#define ERR_INVALID_LUCAS_KANADE_WINDOW_SIZE                         -1074395888 // Both dimensions of the window size should be odd, greater than 2 and less than 16.
+#define ERR_INVALID_MATRIX_TYPE                                      -1074395887 // The type of matrix supplied to the function is not supported.
+#define ERR_INVALID_OPTICAL_FLOW_TERMINATION_CRITERIA_TYPE           -1074395886 // An invalid termination criteria was specified for the optical flow computation.
+#define ERR_LKP_NULL_PYRAMID                                         -1074395885 // The pyramid levels where not properly allocated.
+#define ERR_INVALID_PYRAMID_LEVEL                                    -1074395884 // The pyramid level specified cannot be negative
+#define ERR_INVALID_LKP_KERNEL                                       -1074395883 // The kernel must be symmetric  with non-zero coefficients and of odd size
+#define ERR_INVALID_HORN_SCHUNCK_LAMBDA                              -1074395882 // Invalid smoothing parameter in Horn Schunck operation.
+#define ERR_INVALID_HORN_SCHUNCK_TYPE                                -1074395881 // Invalid stopping criteria type for Horn Schunck optical flow.
+#define ERR_PARTICLE                                                 -1074395880 // Invalid particle.
+#define ERR_BAD_MEASURE                                              -1074395879 // Invalid measure number.
+#define ERR_PROP_NODE_WRITE_NOT_SUPPORTED                            -1074395878 // The Image Display control does not support writing this property node.
+#define ERR_COLORMODE_REQUIRES_CHANGECOLORSPACE2                     -1074395877 // The specified color mode requires the use of imaqChangeColorSpace2.
+#define ERR_UNSUPPORTED_COLOR_MODE                                   -1074395876 // This function does not currently support the color mode you specified.
+#define ERR_BARCODE_PHARMACODE                                       -1074395875 // The barcode is not a valid Pharmacode symbol
+#define ERR_BAD_INDEX                                                -1074395840 // Invalid handle table index.
+#define ERR_INVALID_COMPRESSION_RATIO                                -1074395837 // The compression ratio must be greater than or equal to 1.
+#define ERR_TOO_MANY_CONTOURS                                        -1074395801 // The ROI contains too many contours.
+#define ERR_PROTECTION                                               -1074395800 // Protection error.
+#define ERR_INTERNAL                                                 -1074395799 // Internal error.
+#define ERR_INVALID_CUSTOM_SAMPLE                                    -1074395798 // The size of the feature vector in the custom sample must match the size of those you have already added.
+#define ERR_INVALID_CLASSIFIER_SESSION                               -1074395797 // Not a valid classifier session.
+#define ERR_INVALID_KNN_METHOD                                       -1074395796 // You requested an invalid Nearest Neighbor classifier method.
+#define ERR_K_TOO_LOW                                                -1074395795 // The k parameter must be greater than two.
+#define ERR_K_TOO_HIGH                                               -1074395794 // The k parameter must be <= the number of samples in each class.
+#define ERR_INVALID_OPERATION_ON_COMPACT_SESSION_ATTEMPTED           -1074395793 // This classifier session is compact. Only the Classify and Dispose functions may be called on a compact classifier session.
+#define ERR_CLASSIFIER_SESSION_NOT_TRAINED                           -1074395792 // This classifier session is not trained. You may only call this function on a trained classifier session.
+#define ERR_CLASSIFIER_INVALID_SESSION_TYPE                          -1074395791 // This classifier function cannot be called on this type of classifier session.
+#define ERR_INVALID_DISTANCE_METRIC                                  -1074395790 // You requested an invalid distance metric.
+#define ERR_OPENING_NEWER_CLASSIFIER_SESSION                         -1074395789 // The classifier session you tried to open was created with a newer version of NI Vision. Upgrade to the latest version of NI Vision to read this file.
+#define ERR_NO_SAMPLES                                               -1074395788 // This operation cannot be performed because you have not added any samples.
+#define ERR_INVALID_CLASSIFIER_TYPE                                  -1074395787 // You requested an invalid classifier type.
+#define ERR_INVALID_PARTICLE_OPTIONS                                 -1074395786 // The sum of Scale Dependence and Symmetry Dependence must be less than 1000.
+#define ERR_NO_PARTICLE                                              -1074395785 // The image yielded no particles.
+#define ERR_INVALID_LIMITS                                           -1074395784 // The limits you supplied are not valid.
+#define ERR_BAD_SAMPLE_INDEX                                         -1074395783 // The Sample Index fell outside the range of Samples.
+#define ERR_DESCRIPTION_TOO_LONG                                     -1074395782 // The description must be <= 255 characters.
+#define ERR_CLASSIFIER_INVALID_ENGINE_TYPE                           -1074395781 // The engine for this classifier session does not support this operation.
+#define ERR_INVALID_PARTICLE_TYPE                                    -1074395780 // You requested an invalid particle type.
+#define ERR_CANNOT_COMPACT_UNTRAINED                                 -1074395779 // You may only save a session in compact form if it is trained.
+#define ERR_INVALID_KERNEL_SIZE                                      -1074395778 // The Kernel size must be smaller than the image size.
+#define ERR_INCOMPATIBLE_CLASSIFIER_TYPES                            -1074395777 // The session you read from file must be the same type as the session you passed in.
+#define ERR_INVALID_USE_OF_COMPACT_SESSION_FILE                      -1074395776 // You can not use a compact classification file with read options other than Read All.
+#define ERR_ROI_HAS_OPEN_CONTOURS                                    -1074395775 // The ROI you passed in may only contain closed contours.
+#define ERR_NO_LABEL                                                 -1074395774 // You must pass in a label.
+#define ERR_NO_DEST_IMAGE                                            -1074395773 // You must provide a destination image.
+#define ERR_INVALID_REGISTRATION_METHOD                              -1074395772 // You provided an invalid registration method.
+#define ERR_OPENING_NEWER_INSPECTION_TEMPLATE                        -1074395771 // The golden template you tried to open was created with a newer version of NI Vision. Upgrade to the latest version of NI Vision to read this file.
+#define ERR_INVALID_INSPECTION_TEMPLATE                              -1074395770 // Invalid golden template.
+#define ERR_INVALID_EDGE_THICKNESS                                   -1074395769 // Edge Thickness to Ignore must be greater than zero.
+#define ERR_INVALID_SCALE                                            -1074395768 // Scale must be greater than zero.
+#define ERR_INVALID_ALIGNMENT                                        -1074395767 // The supplied scale is invalid for your template.
+#define ERR_DEPRECATED_FUNCTION                                      -1074395766 // This backwards-compatibility function can not be used with this session. Use newer, supported functions instead.
+#define ERR_INVALID_NORMALIZATION_METHOD                             -1074395763 // You must provide a valid normalization method.
+#define ERR_INVALID_NIBLACK_DEVIATION_FACTOR                         -1074395762 // The deviation factor for Niblack local threshold must be between 0 and 1.
+#define ERR_BOARD_NOT_FOUND                                          -1074395760 // Board not found.
+#define ERR_BOARD_NOT_OPEN                                           -1074395758 // Board not opened.
+#define ERR_DLL_NOT_FOUND                                            -1074395757 // DLL not found.
+#define ERR_DLL_FUNCTION_NOT_FOUND                                   -1074395756 // DLL function not found.
+#define ERR_TRIG_TIMEOUT                                             -1074395754 // Trigger timeout.
+#define ERR_CONTOUR_INVALID_REFINEMENTS                              -1074395746 // Invalid number specified for maximum contour refinements.
+#define ERR_TOO_MANY_CURVES                                          -1074395745 // Too many curves extracted from image. Raise the edge threshold or reduce the ROI.
+#define ERR_CONTOUR_INVALID_KERNEL_FOR_SMOOTHING                     -1074395744 // Invalid kernel for contour smoothing. Zero indicates no smoothing, otherwise value must be odd. 
+#define ERR_CONTOUR_LINE_INVALID                                     -1074395743 // The contour line fit is invalid. Line segment start and stop must differ.
+#define ERR_CONTOUR_TEMPLATE_IMAGE_INVALID                           -1074395742 // The template image must be trained with IMAQ Learn Contour Pattern or be the same size as the target image.
+#define ERR_CONTOUR_GPM_FAIL                                         -1074395741 // Matching failed to align the template and target contours.
+#define ERR_CONTOUR_OPENING_NEWER_VERSION                            -1074395740 // The contour you tried to open was created with a newer version of NI Vision. Upgrade to the latest version of NI Vision to read this file. 
+#define ERR_CONTOUR_CONNECT_DUPLICATE                                -1074395739 // Only one range is allowed per curve connection constraint type. 
+#define ERR_CONTOUR_CONNECT_TYPE                                     -1074395738 // Invalid contour connection constraint type. 
+#define ERR_CONTOUR_MATCH_STR_NOT_APPLICABLE                         -1074395737 // In order to use contour matching, you must provide a template image that has been trained with IMAQ Learn Contour Pattern
+#define ERR_CONTOUR_CURVATURE_KERNEL                                 -1074395736 // Invalid kernel width for curvature calculation. Must be an odd value greater than 1. 
+#define ERR_CONTOUR_EXTRACT_SELECTION                                -1074395735 // Invalid Contour Selection method for contour extraction. 
+#define ERR_CONTOUR_EXTRACT_DIRECTION                                -1074395734 // Invalid Search Direction for contour extraction. 
+#define ERR_CONTOUR_EXTRACT_ROI                                      -1074395733 // Invalid ROI for contour extraction. The ROI must contain an annulus, rectangle or rotated rectangle. 
+#define ERR_CONTOUR_NO_CURVES                                        -1074395732 // No curves were found in the image.
+#define ERR_CONTOUR_COMPARE_KERNEL                                   -1074395731 // Invalid Smoothing Kernel width for contour comparison. Must be zero or an odd positive integer. 
+#define ERR_CONTOUR_COMPARE_SINGLE_IMAGE                             -1074395730 // If no template image is provided, the target image must contain both a contour with extracted points and a fitted equation.
+#define ERR_CONTOUR_INVALID                                          -1074395729 // Invalid contour image.
+#define ERR_INVALID_2D_BARCODE_SEARCH_MODE                           -1074395728 // NI Vision does not support the search mode you provided.
+#define ERR_UNSUPPORTED_2D_BARCODE_SEARCH_MODE                       -1074395727 // NI Vision does not support the search mode you provided for the type of 2D barcode for which you are searching.
+#define ERR_MATCHFACTOR_OBSOLETE                                     -1074395726 // matchFactor has been obsoleted. Instead, set the initialMatchListLength and matchListReductionFactor in the MatchPatternAdvancedOptions structure.
+#define ERR_DATA_VERSION                                             -1074395725 // The data was stored with a newer version of NI Vision. Upgrade to the latest version of NI Vision to read this data.
+#define ERR_CUSTOMDATA_INVALID_SIZE                                  -1074395724 // The size you specified is out of the valid range.
+#define ERR_CUSTOMDATA_KEY_NOT_FOUND                                 -1074395723 // The key you specified cannot be found in the image.
+#define ERR_CLASSIFIER_CLASSIFY_IMAGE_WITH_CUSTOM_SESSION            -1074395722 // Custom classifier sessions only classify feature vectors. They do not support classifying images.
+#define ERR_INVALID_BIT_DEPTH                                        -1074395721 // NI Vision does not support the bit depth you supplied for the image you supplied.
+#define ERR_BAD_ROI                                                  -1074395720 // Invalid ROI.
+#define ERR_BAD_ROI_BOX                                              -1074395719 // Invalid ROI global rectangle.
+#define ERR_LAB_VERSION                                              -1074395718 // The version of LabVIEW or BridgeVIEW you are running does not support this operation.
+#define ERR_INVALID_RANGE                                            -1074395717 // The range you supplied is invalid.
+#define ERR_INVALID_SCALING_METHOD                                   -1074395716 // NI Vision does not support the scaling method you provided.
+#define ERR_INVALID_CALIBRATION_UNIT                                 -1074395715 // NI Vision does not support the calibration unit you supplied.
+#define ERR_INVALID_AXIS_ORIENTATION                                 -1074395714 // NI Vision does not support the axis orientation you supplied.
+#define ERR_VALUE_NOT_IN_ENUM                                        -1074395713 // Value not in enumeration.
+#define ERR_WRONG_REGION_TYPE                                        -1074395712 // You selected a region that is not of the right type.
+#define ERR_NOT_ENOUGH_REGIONS                                       -1074395711 // You specified a viewer that does not contain enough regions.
+#define ERR_TOO_MANY_PARTICLES                                       -1074395710 // The image has too many particles for this process.
+#define ERR_AVI_UNOPENED_SESSION                                     -1074395709 // The AVI session has not been opened.
+#define ERR_AVI_READ_SESSION_REQUIRED                                -1074395708 // The AVI session is a write session, but this operation requires a read session.
+#define ERR_AVI_WRITE_SESSION_REQUIRED                               -1074395707 // The AVI session is a read session, but this operation requires a write session.
+#define ERR_AVI_SESSION_ALREADY_OPEN                                 -1074395706 // This AVI session is already open. You must close it before calling the Create or Open functions.
+#define ERR_DATA_CORRUPTED                                           -1074395705 // The data is corrupted and cannot be read.
+#define ERR_INVALID_COMPRESSION_TYPE                                 -1074395704 // Invalid compression type.
+#define ERR_INVALID_TYPE_OF_FLATTEN                                  -1074395703 // Invalid type of flatten.
+#define ERR_INVALID_LENGTH                                           -1074395702 // The length of the edge detection line must be greater than zero.
+#define ERR_INVALID_MATRIX_SIZE_RANGE                                -1074395701 // The maximum Data Matrix barcode size must be equal to or greater than the minimum Data Matrix barcode size.
+#define ERR_REQUIRES_WIN2000_OR_NEWER                                -1074395700 // The function requires the operating system to be Microsoft Windows 2000 or newer.
+#define ERR_INVALID_CALIBRATION_METHOD                               -1074395662 // Invalid calibration method requested
+#define ERR_INVALID_OPERATION_ON_COMPACT_CALIBRATION_ATTEMPTED       -1074395661 // This calibration is compact. Re-Learning calibration and retrieving thumbnails are not possible with this calibration
+#define ERR_INVALID_POLYNOMIAL_MODEL_K_COUNT                         -1074395660 // Invalid number of K values 
+#define ERR_INVALID_DISTORTION_MODEL                                 -1074395659 // Invalid distortion model type
+#define ERR_CAMERA_MODEL_NOT_AVAILABLE                               -1074395658 // Camera Model is not learned
+#define ERR_INVALID_THUMBNAIL_INDEX                                  -1074395657 // Supplied thumbnail index is invalid
+#define ERR_SMOOTH_CONTOURS_MUST_BE_SAME                             -1074395656 // You must specify the same value for the smooth contours advanced match option for all templates you want to match.
+#define ERR_ENABLE_CALIBRATION_SUPPORT_MUST_BE_SAME                  -1074395655 // You must specify the same value for the enable calibration support advanced match option for all templates you want to match.
+#define ERR_GRADING_INFORMATION_NOT_FOUND                            -1074395654 // The source image does not contain grading information. You must prepare the source image for grading when reading the Data Matrix, and you cannot change the contents of the source image between reading and grading the Data Matrix.
+#define ERR_OPENING_NEWER_MULTIPLE_GEOMETRIC_TEMPLATE                -1074395653 // The multiple geometric matching template you tried to open was created with a newer version of NI Vision. Upgrade to the latest version of NI Vision to read this file.
+#define ERR_OPENING_NEWER_GEOMETRIC_MATCHING_TEMPLATE                -1074395652 // The geometric matching template you tried to open was created with a newer version of NI Vision. Upgrade to the latest version of NI Vision to read this file.
+#define ERR_EDGE_FILTER_SIZE_MUST_BE_SAME                            -1074395651 // You must specify the same edge filter size for all the templates you want to match.
+#define ERR_CURVE_EXTRACTION_MODE_MUST_BE_SAME                       -1074395650 // You must specify the same curve extraction mode for all the templates you want to match.
+#define ERR_INVALID_GEOMETRIC_FEATURE_TYPE                           -1074395649 // The geometric feature type specified is invalid.
+#define ERR_TEMPLATE_NOT_LEARNED                                     -1074395648 // You supplied a template that was not learned.
+#define ERR_INVALID_MULTIPLE_GEOMETRIC_TEMPLATE                      -1074395647 // Invalid multiple geometric template.
+#define ERR_NO_TEMPLATE_TO_LEARN                                     -1074395646 // Need at least one template to learn.
+#define ERR_INVALID_NUMBER_OF_LABELS                                 -1074395645 // You supplied an invalid number of labels.
+#define ERR_LABEL_TOO_LONG                                           -1074395644 // Labels must be <= 255 characters.
+#define ERR_INVALID_NUMBER_OF_MATCH_OPTIONS                          -1074395643 // You supplied an invalid number of match options.
+#define ERR_LABEL_NOT_FOUND                                          -1074395642 // Cannot find a label that matches the one you specified.
+#define ERR_DUPLICATE_LABEL                                          -1074395641 // Duplicate labels are not allowed.
+#define ERR_TOO_MANY_ZONES                                           -1074395640 // The number of zones found exceeded the capacity of the algorithm.
+#define ERR_INVALID_HATCH_STYLE                                      -1074395639 // The hatch style for the window background is invalid.
+#define ERR_INVALID_FILL_STYLE                                       -1074395638 // The fill style for the window background is invalid.
+#define ERR_HARDWARE_DOESNT_SUPPORT_NONTEARING                       -1074395637 // Your hardware is not supported by DirectX and cannot be put into NonTearing mode.
+#define ERR_DIRECTX_NOT_FOUND                                        -1074395636 // DirectX is required for this feature.  Please install the latest version..
+#define ERR_INVALID_SHAPE_DESCRIPTOR                                 -1074395635 // The passed shape descriptor is invalid.
+#define ERR_INVALID_MAX_MATCH_OVERLAP                                -1074395634 // Invalid max match overlap.  Values must be between -1 and 100.
+#define ERR_INVALID_MIN_MATCH_SEPARATION_SCALE                       -1074395633 // Invalid minimum match separation scale.  Values must be greater than or equal to -1.
+#define ERR_INVALID_MIN_MATCH_SEPARATION_ANGLE                       -1074395632 // Invalid minimum match separation angle.  Values must be between -1 and 360.
+#define ERR_INVALID_MIN_MATCH_SEPARATION_DISTANCE                    -1074395631 // Invalid minimum match separation distance.  Values must be greater than or equal to -1.
+#define ERR_INVALID_MAXIMUM_FEATURES_LEARNED                         -1074395630 // Invalid maximum number of features learn. Values must be integers greater than zero.
+#define ERR_INVALID_MAXIMUM_PIXEL_DISTANCE_FROM_LINE                 -1074395629 // Invalid maximum pixel distance from line. Values must be positive real numbers.
+#define ERR_INVALID_GEOMETRIC_MATCHING_TEMPLATE                      -1074395628 // Invalid geometric matching template image.
+#define ERR_NOT_ENOUGH_TEMPLATE_FEATURES_1                           -1074395627 // The template does not contain enough features for geometric matching.
+#define ERR_NOT_ENOUGH_TEMPLATE_FEATURES                             -1074395626 // The template does not contain enough features for geometric matching.
+#define ERR_INVALID_MATCH_CONSTRAINT_TYPE                            -1074395625 // You specified an invalid value for the match constraint value of the  range settings.
+#define ERR_INVALID_OCCLUSION_RANGE                                  -1074395624 // Invalid occlusion range. Valid values for the bounds range from 0 to 100 and the upper bound must be greater than or equal to the lower bound.
+#define ERR_INVALID_SCALE_RANGE                                      -1074395623 // Invalid scale range. Values for the lower bound must be a positive real numbers and the upper bound must be greater than or equal to the lower bound.
+#define ERR_INVALID_MATCH_GEOMETRIC_PATTERN_SETUP_DATA               -1074395622 // Invalid match geometric pattern setup data.
+#define ERR_INVALID_LEARN_GEOMETRIC_PATTERN_SETUP_DATA               -1074395621 // Invalid learn geometric pattern setup data.
+#define ERR_INVALID_CURVE_EXTRACTION_MODE                            -1074395620 // Invalid curve extraction mode.
+#define ERR_TOO_MANY_OCCLUSION_RANGES                                -1074395619 // You can specify only one occlusion range.
+#define ERR_TOO_MANY_SCALE_RANGES                                    -1074395618 // You can specify only one scale range.
+#define ERR_INVALID_NUMBER_OF_FEATURES_RANGE                         -1074395617 // The minimum number of features must be less than or equal to the maximum number of features.
+#define ERR_INVALID_EDGE_FILTER_SIZE                                 -1074395616 // Invalid edge filter size.
+#define ERR_INVALID_MINIMUM_FEATURE_STRENGTH                         -1074395615 // Invalid minimum strength for features. Values must be positive real numbers.
+#define ERR_INVALID_MINIMUM_FEATURE_ASPECT_RATIO                     -1074395614 // Invalid aspect ratio for rectangular features. Values must be positive real numbers in the range 0.01 to 1.0.
+#define ERR_INVALID_MINIMUM_FEATURE_LENGTH                           -1074395613 // Invalid minimum length for linear features. Values must be integers greater than 0.
+#define ERR_INVALID_MINIMUM_FEATURE_RADIUS                           -1074395612 // Invalid minimum radius for circular features. Values must be integers greater than 0.
+#define ERR_INVALID_MINIMUM_RECTANGLE_DIMENSION                      -1074395611 // Invalid minimum rectangle dimension. Values must be integers greater than 0.
+#define ERR_INVALID_INITIAL_MATCH_LIST_LENGTH                        -1074395610 // Invalid initial match list length. Values must be integers greater than 5.
+#define ERR_INVALID_SUBPIXEL_TOLERANCE                               -1074395609 // Invalid subpixel tolerance. Values must be positive real numbers.
+#define ERR_INVALID_SUBPIXEL_ITERATIONS                              -1074395608 // Invalid number of subpixel iterations. Values must be integers greater 10.
+#define ERR_INVALID_MAXIMUM_FEATURES_PER_MATCH                       -1074395607 // Invalid maximum number of features used per match. Values must be integers greater than or equal to zero.
+#define ERR_INVALID_MINIMUM_FEATURES_TO_MATCH                        -1074395606 // Invalid minimum number of features used for matching. Values must be integers greater than zero.
+#define ERR_INVALID_MAXIMUM_END_POINT_GAP                            -1074395605 // Invalid maximum end point gap. Valid values range from 0 to 32767.
+#define ERR_INVALID_COLUMN_STEP                                      -1074395604 // Invalid column step. Valid range is 1 to 255.
+#define ERR_INVALID_ROW_STEP                                         -1074395603 // Invalid row step. Valid range is 1 to 255.
+#define ERR_INVALID_MINIMUM_CURVE_LENGTH                             -1074395602 // Invalid minimum length. Valid values must be greater than or equal to zero.
+#define ERR_INVALID_EDGE_THRESHOLD                                   -1074395601 // Invalid edge threshold. Valid values range from 1 to 360.
+#define ERR_INFO_NOT_FOUND                                           -1074395600 // You must provide information about the subimage within the browser.
+#define ERR_NIOCR_INVALID_ACCEPTANCE_LEVEL                           -1074395598 // The acceptance level is outside the valid range of  0 to 1000.
+#define ERR_NIOCR_NOT_A_VALID_SESSION                                -1074395597 // Not a valid OCR session.
+#define ERR_NIOCR_INVALID_CHARACTER_SIZE                             -1074395596 // Invalid character size. Character size must be >= 1.
+#define ERR_NIOCR_INVALID_THRESHOLD_MODE                             -1074395595 // Invalid threshold mode value.
+#define ERR_NIOCR_INVALID_SUBSTITUTION_CHARACTER                     -1074395594 // Invalid substitution character. Valid substitution characters are ASCII values that range from 1 to 254.
+#define ERR_NIOCR_INVALID_NUMBER_OF_BLOCKS                           -1074395593 // Invalid number of blocks. Number of blocks must be >= 4 and <= 50.
+#define ERR_NIOCR_INVALID_READ_STRATEGY                              -1074395592 // Invalid read strategy.
+#define ERR_NIOCR_INVALID_CHARACTER_INDEX                            -1074395591 // Invalid character index.
+#define ERR_NIOCR_INVALID_NUMBER_OF_VALID_CHARACTER_POSITIONS        -1074395590 // Invalid number of character positions. Valid values range from 0 to 255.
+#define ERR_NIOCR_INVALID_LOW_THRESHOLD_VALUE                        -1074395589 // Invalid low threshold value. Valid threshold values range from 0 to 255.
+#define ERR_NIOCR_INVALID_HIGH_THRESHOLD_VALUE                       -1074395588 // Invalid high threshold value. Valid threshold values range from 0 to 255.
+#define ERR_NIOCR_INVALID_THRESHOLD_RANGE                            -1074395587 // The low threshold must be less than the high threshold.
+#define ERR_NIOCR_INVALID_LOWER_THRESHOLD_LIMIT                      -1074395586 // Invalid lower threshold limit. Valid lower threshold limits range from 0 to 255.
+#define ERR_NIOCR_INVALID_UPPER_THRESHOLD_LIMIT                      -1074395585 // Invalid upper threshold limit. Valid upper threshold limits range from 0 to 255.
+#define ERR_NIOCR_INVALID_THRESHOLD_LIMITS                           -1074395584 // The lower threshold limit must be less than the upper threshold limit.
+#define ERR_NIOCR_INVALID_MIN_CHAR_SPACING                           -1074395583 // Invalid minimum character spacing value. Character spacing must be >= 1 pixel.
+#define ERR_NIOCR_INVALID_MAX_HORIZ_ELEMENT_SPACING                  -1074395582 // Invalid maximum horizontal element spacing value. Maximum horizontal element spacing must be >= 0.
+#define ERR_NIOCR_INVALID_MAX_VERT_ELEMENT_SPACING                   -1074395581 // Invalid maximum vertical element spacing value. Maximum vertical element spacing must be >= 0.
+#define ERR_NIOCR_INVALID_MIN_BOUNDING_RECT_WIDTH                    -1074395580 // Invalid minimum bounding rectangle width. Minimum bounding rectangle width must be >= 1.
+#define ERR_NIOCR_INVALID_ASPECT_RATIO                               -1074395579 // Invalid aspect ratio value. The aspect ratio must be zero or >= 100.
+#define ERR_NIOCR_INVALID_CHARACTER_SET_FILE                         -1074395578 // Invalid or corrupt character set file.
+#define ERR_NIOCR_CHARACTER_VALUE_CANNOT_BE_EMPTYSTRING              -1074395577 // The character value must not be an empty string.
+#define ERR_NIOCR_CHARACTER_VALUE_TOO_LONG                           -1074395576 // Character values must be <=255 characters.
+#define ERR_NIOCR_INVALID_NUMBER_OF_EROSIONS                         -1074395575 // Invalid number of erosions. The number of erosions must be >= 0.
+#define ERR_NIOCR_CHARACTER_SET_DESCRIPTION_TOO_LONG                 -1074395574 // The character set description must be <=255 characters.
+#define ERR_NIOCR_INVALID_CHARACTER_SET_FILE_VERSION                 -1074395573 // The character set file was created by a newer version of NI Vision. Upgrade to the latest version of NI Vision to read the character set file.
+#define ERR_NIOCR_INTEGER_VALUE_FOR_STRING_ATTRIBUTE                 -1074395572 // You must specify characters for a string. A string cannot contain integers.
+#define ERR_NIOCR_GET_ONLY_ATTRIBUTE                                 -1074395571 // This attribute is read-only.
+#define ERR_NIOCR_INTEGER_VALUE_FOR_BOOLEAN_ATTRIBUTE                -1074395570 // This attribute requires a Boolean value.
+#define ERR_NIOCR_INVALID_ATTRIBUTE                                  -1074395569 // Invalid attribute.
+#define ERR_NIOCR_STRING_VALUE_FOR_INTEGER_ATTRIBUTE                 -1074395568 // This attribute requires integer values.
+#define ERR_NIOCR_STRING_VALUE_FOR_BOOLEAN_ATTRIBUTE                 -1074395567 // String values are invalid for this attribute. Enter a boolean value.
+#define ERR_NIOCR_BOOLEAN_VALUE_FOR_INTEGER_ATTRIBUTE                -1074395566 // Boolean values are not valid for this attribute. Enter an integer value.
+#define ERR_NIOCR_MUST_BE_SINGLE_CHARACTER                           -1074395565 // Requires a single-character string.
+#define ERR_NIOCR_INVALID_PREDEFINED_CHARACTER                       -1074395564 // Invalid predefined character value.
+#define ERR_NIOCR_UNLICENSED                                         -1074395563 // This copy of NI OCR is unlicensed.
+#define ERR_NIOCR_BOOLEAN_VALUE_FOR_STRING_ATTRIBUTE                 -1074395562 // String values are not valid for this attribute. Enter a Boolean value.
+#define ERR_NIOCR_INVALID_NUMBER_OF_CHARACTERS                       -1074395561 // The number of characters in the character value must match the number of objects in the image.
+#define ERR_NIOCR_INVALID_OBJECT_INDEX                               -1074395560 // Invalid object index.
+#define ERR_NIOCR_INVALID_READ_OPTION                                -1074395559 // Invalid read option.
+#define ERR_NIOCR_INVALID_CHARACTER_SIZE_RANGE                       -1074395558 // The minimum character size must be less than the maximum character size.
+#define ERR_NIOCR_INVALID_BOUNDING_RECT_WIDTH_RANGE                  -1074395557 // The minimum character bounding rectangle width must be less than the maximum character bounding rectangle width.
+#define ERR_NIOCR_INVALID_BOUNDING_RECT_HEIGHT_RANGE                 -1074395556 // The minimum character bounding rectangle height must be less than the maximum character bounding rectangle height.
+#define ERR_NIOCR_INVALID_SPACING_RANGE                              -1074395555 // The maximum horizontal element spacing value must not exceed the minimum character spacing value.
+#define ERR_NIOCR_INVALID_READ_RESOLUTION                            -1074395554 // Invalid read resolution.
+#define ERR_NIOCR_INVALID_MIN_BOUNDING_RECT_HEIGHT                   -1074395553 // Invalid minimum bounding rectangle height. The minimum bounding rectangle height must be >= 1.
+#define ERR_NIOCR_NOT_A_VALID_CHARACTER_SET                          -1074395552 // Not a valid character set.
+#define ERR_NIOCR_RENAME_REFCHAR                                     -1074395551 // A trained OCR character cannot be renamed while it is a reference character.
+#define ERR_NIOCR_INVALID_CHARACTER_VALUE                            -1074395550 // A character cannot have an ASCII value of 255.
+#define ERR_NIOCR_INVALID_NUMBER_OF_OBJECTS_TO_VERIFY                -1074395549 // The number of objects found does not match the number of expected characters or patterns to verify.
+#define ERR_INVALID_STEREO_BLOCKMATCHING_PREFILTER_CAP               -1074395421 // The specified value for the filter cap for block matching is invalid.
+#define ERR_INVALID_STEREO_BLOCKMATCHING_PREFILTER_SIZE              -1074395420 // The specified prefilter size for block matching is invalid.
+#define ERR_INVALID_STEREO_BLOCKMATCHING_PREFILTER_TYPE              -1074395419 // The specified prefilter type for block matching is invalid.
+#define ERR_INVALID_STEREO_BLOCKMATCHING_NUMDISPARITIES              -1074395418 // The specifed value for number of disparities is invalid.
+#define ERR_INVALID_STEREO_BLOCKMATCHING_WINDOW_SIZE                 -1074395417 // The specified window size for block matching is invalid.
+#define ERR_3DVISION_INVALID_SESSION_TYPE                            -1074395416 // This 3D vision function cannot be called on this type of 3d vision session.
+#define ERR_TOO_MANY_3DVISION_SESSIONS                               -1074395415 // There are too many 3D vision sessions open.  You must close a session before you can open another one.
+#define ERR_OPENING_NEWER_3DVISION_SESSION                           -1074395414 // The 3D vision session you tried to open was created with a newer version of NI Vision. Upgrade to the latest version of NI Vision to read this file.
+#define ERR_INVALID_STEREO_BLOCKMATCHING_FILTERTYPE                  -1074395413 // You have specified an invalid filter type for block matching.
+#define ERR_INVALID_STEREO_CAMERA_POSITION                           -1074395412 // You have requested results at an invalid camera position in the stereo setup.
+#define ERR_INVALID_3DVISION_SESSION                                 -1074395411 // Not a valid 3D Vision session.
+#define ERR_INVALID_ICONS_PER_LINE                                   -1074395410 // NI Vision does not support less than one icon per line.
+#define ERR_INVALID_SUBPIXEL_DIVISIONS                               -1074395409 // Invalid subpixel divisions.
+#define ERR_INVALID_DETECTION_MODE                                   -1074395408 // Invalid detection mode.
+#define ERR_INVALID_CONTRAST                                         -1074395407 // Invalid contrast value. Valid contrast values range from 0 to 255.
+#define ERR_COORDSYS_NOT_FOUND                                       -1074395406 // The coordinate system could not be found on this image.
+#define ERR_INVALID_TEXTORIENTATION                                  -1074395405 // NI Vision does not support the text orientation value you supplied.
+#define ERR_INVALID_INTERPOLATIONMETHOD_FOR_UNWRAP                   -1074395404 // UnwrapImage does not support the interpolation method value you supplied.  Valid interpolation methods are zero order and bilinear. 
+#define ERR_EXTRAINFO_VERSION                                        -1074395403 // The image was created in a newer version of NI Vision. Upgrade to the latest version of NI Vision to use this image.
+#define ERR_INVALID_MAXPOINTS                                        -1074395402 // The function does not support the maximum number of points that you specified.
+#define ERR_INVALID_MATCHFACTOR                                      -1074395401 // The function does not support the matchFactor that you specified.
+#define ERR_MULTICORE_OPERATION                                      -1074395400 // The operation you have given Multicore Options is invalid. Please see the available enumeration values for Multicore Operation.
+#define ERR_MULTICORE_INVALID_ARGUMENT                               -1074395399 // You have given Multicore Options an invalid argument.
+#define ERR_COMPLEX_IMAGE_REQUIRED                                   -1074395397 // A complex image is required.
+#define ERR_COLOR_IMAGE_REQUIRED                                     -1074395395 // The input image must be a color image.
+#define ERR_COLOR_SPECTRUM_MASK                                      -1074395394 // The color mask removes too much color information.
+#define ERR_COLOR_TEMPLATE_IMAGE_TOO_SMALL                           -1074395393 // The color template image is too small.
+#define ERR_COLOR_TEMPLATE_IMAGE_TOO_LARGE                           -1074395392 // The color template image is too large.
+#define ERR_COLOR_TEMPLATE_IMAGE_HUE_CONTRAST_TOO_LOW                -1074395391 // The contrast in the hue plane of the image is too low for learning shape features.
+#define ERR_COLOR_TEMPLATE_IMAGE_LUMINANCE_CONTRAST_TOO_LOW          -1074395390 // The contrast in the luminance plane of the image is too low to learn shape features.
+#define ERR_COLOR_LEARN_SETUP_DATA                                   -1074395389 // Invalid color learn setup data.
+#define ERR_COLOR_LEARN_SETUP_DATA_SHAPE                             -1074395388 // Invalid color learn setup data.
+#define ERR_COLOR_MATCH_SETUP_DATA                                   -1074395387 // Invalid color match setup data.
+#define ERR_COLOR_MATCH_SETUP_DATA_SHAPE                             -1074395386 // Invalid color match setup data.
+#define ERR_COLOR_ROTATION_REQUIRES_SHAPE_FEATURE                    -1074395385 // Rotation-invariant color pattern matching requires a feature mode including shape.
+#define ERR_COLOR_TEMPLATE_DESCRIPTOR                                -1074395384 // Invalid color template image.
+#define ERR_COLOR_TEMPLATE_DESCRIPTOR_1                              -1074395383 // Invalid color template image.
+#define ERR_COLOR_TEMPLATE_DESCRIPTOR_2                              -1074395382 // Invalid color template image.
+#define ERR_COLOR_TEMPLATE_DESCRIPTOR_3                              -1074395381 // Invalid color template image.
+#define ERR_COLOR_TEMPLATE_DESCRIPTOR_4                              -1074395380 // Invalid color template image.
+#define ERR_COLOR_TEMPLATE_DESCRIPTOR_5                              -1074395379 // Invalid color template image.
+#define ERR_COLOR_TEMPLATE_DESCRIPTOR_6                              -1074395378 // Invalid color template image.
+#define ERR_COLOR_TEMPLATE_DESCRIPTOR_SHIFT                          -1074395377 // Invalid color template image.
+#define ERR_COLOR_TEMPLATE_DESCRIPTOR_NOSHIFT                        -1074395376 // The color template image does not contain data required for shift-invariant color matching.
+#define ERR_COLOR_TEMPLATE_DESCRIPTOR_SHIFT_1                        -1074395375 // Invalid color template image.
+#define ERR_COLOR_TEMPLATE_DESCRIPTOR_SHIFT_2                        -1074395374 // Invalid color template image.
+#define ERR_COLOR_TEMPLATE_DESCRIPTOR_ROTATION                       -1074395373 // Invalid color template image.
+#define ERR_COLOR_TEMPLATE_DESCRIPTOR_NOROTATION                     -1074395372 // The color template image does not contain data required for rotation-invariant color matching.
+#define ERR_COLOR_TEMPLATE_DESCRIPTOR_ROTATION_1                     -1074395371 // Invalid color template image.
+#define ERR_COLOR_TEMPLATE_DESCRIPTOR_ROTATION_2                     -1074395370 // Invalid color template image.
+#define ERR_COLOR_TEMPLATE_DESCRIPTOR_ROTATION_3                     -1074395369 // Invalid color template image.
+#define ERR_COLOR_TEMPLATE_DESCRIPTOR_ROTATION_4                     -1074395368 // Invalid color template image.
+#define ERR_COLOR_TEMPLATE_DESCRIPTOR_ROTATION_5                     -1074395367 // Invalid color template image.
+#define ERR_COLOR_TEMPLATE_DESCRIPTOR_NOSHAPE                        -1074395366 // The color template image does not contain data required for color matching in shape feature mode.
+#define ERR_COLOR_TEMPLATE_DESCRIPTOR_NOSPECTRUM                     -1074395365 // The color template image does not contain data required for color matching in color feature mode.
+#define ERR_IGNORE_COLOR_SPECTRUM_SET                                -1074395364 // The ignore color spectra array is invalid.
+#define ERR_INVALID_SUBSAMPLING_RATIO                                -1074395363 // Invalid subsampling ratio.
+#define ERR_INVALID_WIDTH                                            -1074395362 // Invalid pixel width.
+#define ERR_INVALID_STEEPNESS                                        -1074395361 // Invalid steepness.
+#define ERR_COMPLEX_PLANE                                            -1074395360 // Invalid complex plane.
+#define ERR_INVALID_COLOR_IGNORE_MODE                                -1074395357 // Invalid color ignore mode.
+#define ERR_INVALID_MIN_MATCH_SCORE                                  -1074395356 // Invalid minimum match score. Acceptable values range from 0 to 1000.
+#define ERR_INVALID_NUM_MATCHES_REQUESTED                            -1074395355 // Invalid number of matches requested. You must request a minimum of one match.
+#define ERR_INVALID_COLOR_WEIGHT                                     -1074395354 // Invalid color weight. Acceptable values range from 0 to 1000.
+#define ERR_INVALID_SEARCH_STRATEGY                                  -1074395353 // Invalid search strategy.
+#define ERR_INVALID_FEATURE_MODE                                     -1074395352 // Invalid feature mode.
+#define ERR_INVALID_RECT                                             -1074395351 // NI Vision does not support rectangles with negative widths or negative heights.
+#define ERR_INVALID_VISION_INFO                                      -1074395350 // NI Vision does not support the vision information type you supplied.
+#define ERR_INVALID_SKELETONMETHOD                                   -1074395349 // NI Vision does not support the SkeletonMethod value you supplied.
+#define ERR_INVALID_3DPLANE                                          -1074395348 // NI Vision does not support the 3DPlane value you supplied.
+#define ERR_INVALID_3DDIRECTION                                      -1074395347 // NI Vision does not support the 3DDirection value you supplied.
+#define ERR_INVALID_INTERPOLATIONMETHOD_FOR_ROTATE                   -1074395346 // imaqRotate does not support the InterpolationMethod value you supplied.
+#define ERR_INVALID_FLIPAXIS                                         -1074395345 // NI Vision does not support the axis of symmetry you supplied.
+#define ERR_FILE_FILENAME_NULL                                       -1074395343 // You must pass a valid file name. Do not pass in NULL.
+#define ERR_INVALID_SIZETYPE                                         -1074395340 // NI Vision does not support the SizeType value you supplied.
+#define ERR_UNKNOWN_ALGORITHM                                        -1074395336 // You specified the dispatch status of an unknown algorithm.
+#define ERR_DISPATCH_STATUS_CONFLICT                                 -1074395335 // You are attempting to set the same algorithm to dispatch and to not dispatch. Remove one of the conflicting settings.
+#define ERR_INVALID_CONVERSIONSTYLE                                  -1074395334 // NI Vision does not support the Conversion Method value you supplied.
+#define ERR_INVALID_VERTICAL_TEXT_ALIGNMENT                          -1074395333 // NI Vision does not support the VerticalTextAlignment value you supplied.
+#define ERR_INVALID_COMPAREFUNCTION                                  -1074395332 // NI Vision does not support the CompareFunction value you supplied.
+#define ERR_INVALID_BORDERMETHOD                                     -1074395331 // NI Vision does not support the BorderMethod value you supplied.
+#define ERR_INVALID_BORDER_SIZE                                      -1074395330 // Invalid border size. Acceptable values range from 0 to 50.
+#define ERR_INVALID_OUTLINEMETHOD                                    -1074395329 // NI Vision does not support the OutlineMethod value you supplied.
+#define ERR_INVALID_INTERPOLATIONMETHOD                              -1074395328 // NI Vision does not support the InterpolationMethod value you supplied.
+#define ERR_INVALID_SCALINGMODE                                      -1074395327 // NI Vision does not support the ScalingMode value you supplied.
+#define ERR_INVALID_DRAWMODE_FOR_LINE                                -1074395326 // imaqDrawLineOnImage does not support the DrawMode value you supplied.
+#define ERR_INVALID_DRAWMODE                                         -1074395325 // NI Vision does not support the DrawMode value you supplied.
+#define ERR_INVALID_SHAPEMODE                                        -1074395324 // NI Vision does not support the ShapeMode value you supplied.
+#define ERR_INVALID_FONTCOLOR                                        -1074395323 // NI Vision does not support the FontColor value you supplied.
+#define ERR_INVALID_TEXTALIGNMENT                                    -1074395322 // NI Vision does not support the TextAlignment value you supplied.
+#define ERR_INVALID_MORPHOLOGYMETHOD                                 -1074395321 // NI Vision does not support the MorphologyMethod value you supplied.
+#define ERR_TEMPLATE_EMPTY                                           -1074395320 // The template image is empty.
+#define ERR_INVALID_SUBPIX_TYPE                                      -1074395319 // NI Vision does not support the interpolation type you supplied.
+#define ERR_INSF_POINTS                                              -1074395318 // You supplied an insufficient number of points to perform this operation.
+#define ERR_UNDEF_POINT                                              -1074395317 // You specified a point that lies outside the image.
+#define ERR_INVALID_KERNEL_CODE                                      -1074395316 // Invalid kernel code.
+#define ERR_INEFFICIENT_POINTS                                       -1074395315 // You supplied an inefficient set of points to match the minimum score.
+#define ERR_WRITE_FILE_NOT_SUPPORTED                                 -1074395313 // Writing files is not supported on this device.
+#define ERR_LCD_CALIBRATE                                            -1074395312 // The input image does not seem to be a valid LCD or LED calibration image.
+#define ERR_INVALID_COLOR_SPECTRUM                                   -1074395311 // The color spectrum array you provided has an invalid number of elements or contains an element set to not-a-number (NaN).
+#define ERR_INVALID_PALETTE_TYPE                                     -1074395310 // NI Vision does not support the PaletteType value you supplied.
+#define ERR_INVALID_WINDOW_THREAD_POLICY                             -1074395309 // NI Vision does not support the WindowThreadPolicy value you supplied.
+#define ERR_INVALID_COLORSENSITIVITY                                 -1074395308 // NI Vision does not support the ColorSensitivity value you supplied.
+#define ERR_PRECISION_NOT_GTR_THAN_0                                 -1074395307 // The precision parameter must be greater than 0.
+#define ERR_INVALID_TOOL                                             -1074395306 // NI Vision does not support the Tool value you supplied.
+#define ERR_INVALID_REFERENCEMODE                                    -1074395305 // NI Vision does not support the ReferenceMode value you supplied.
+#define ERR_INVALID_MATHTRANSFORMMETHOD                              -1074395304 // NI Vision does not support the MathTransformMethod value you supplied.
+#define ERR_INVALID_NUM_OF_CLASSES                                   -1074395303 // Invalid number of classes for auto threshold. Acceptable values range from 2 to 256.
+#define ERR_INVALID_THRESHOLDMETHOD                                  -1074395302 // NI Vision does not support the threshold method value you supplied.
+#define ERR_ROI_NOT_2_LINES                                          -1074395301 // The ROI you passed into imaqGetMeterArc must consist of two lines.
+#define ERR_INVALID_METERARCMODE                                     -1074395300 // NI Vision does not support the MeterArcMode value you supplied.
+#define ERR_INVALID_COMPLEXPLANE                                     -1074395299 // NI Vision does not support the ComplexPlane value you supplied.
+#define ERR_COMPLEXPLANE_NOT_REAL_OR_IMAGINARY                       -1074395298 // You can perform this operation on a real or an imaginary ComplexPlane only.
+#define ERR_INVALID_PARTICLEINFOMODE                                 -1074395297 // NI Vision does not support the ParticleInfoMode value you supplied.
+#define ERR_INVALID_BARCODETYPE                                      -1074395296 // NI Vision does not support the BarcodeType value you supplied.
+#define ERR_INVALID_INTERPOLATIONMETHOD_INTERPOLATEPOINTS            -1074395295 // imaqInterpolatePoints does not support the InterpolationMethod value you supplied.
+#define ERR_CONTOUR_INDEX_OUT_OF_RANGE                               -1074395294 // The contour index you supplied is larger than the number of contours in the ROI.
+#define ERR_CONTOURID_NOT_FOUND                                      -1074395293 // The supplied ContourID did not correlate to a contour inside the ROI.
+#define ERR_POINTS_ARE_COLLINEAR                                     -1074395292 // Do not supply collinear points for this operation.
+#define ERR_SHAPEMATCH_BADIMAGEDATA                                  -1074395291 // Shape Match requires the image to contain only pixel values of 0 or 1.
+#define ERR_SHAPEMATCH_BADTEMPLATE                                   -1074395290 // The template you supplied for ShapeMatch contains no shape information.
+#define ERR_CONTAINER_CAPACITY_EXCEEDED_UINT_MAX                     -1074395289 // The operation would have exceeded the capacity of an internal container, which is limited to 4294967296 unique elements.
+#define ERR_CONTAINER_CAPACITY_EXCEEDED_INT_MAX                      -1074395288 // The operation would have exceeded the capacity of an internal container, which is limited to 2147483648 unique elements.
+#define ERR_INVALID_LINE                                             -1074395287 // The line you provided contains two identical points, or one of the coordinate locations for the line is not a number (NaN).
+#define ERR_INVALID_CONCENTRIC_RAKE_DIRECTION                        -1074395286 // Invalid concentric rake direction.
+#define ERR_INVALID_SPOKE_DIRECTION                                  -1074395285 // Invalid spoke direction.
+#define ERR_INVALID_EDGE_PROCESS                                     -1074395284 // Invalid edge process.
+#define ERR_INVALID_RAKE_DIRECTION                                   -1074395283 // Invalid rake direction.
+#define ERR_CANT_DRAW_INTO_VIEWER                                    -1074395282 // Unable to draw to viewer. You must have the latest version of the control.
+#define ERR_IMAGE_SMALLER_THAN_BORDER                                -1074395281 // Your image must be larger than its border size for this operation.
+#define ERR_ROI_NOT_RECT                                             -1074395280 // The ROI must only have a single Rectangle contour.
+#define ERR_ROI_NOT_POLYGON                                          -1074395279 // ROI is not a polygon.
+#define ERR_LCD_NOT_NUMERIC                                          -1074395278 // LCD image is not a number.
+#define ERR_BARCODE_CHECKSUM                                         -1074395277 // The decoded barcode information did not pass the checksum test.
+#define ERR_LINES_PARALLEL                                           -1074395276 // You specified parallel lines for the meter ROI.
+#define ERR_INVALID_BROWSER_IMAGE                                    -1074395275 // Invalid browser image.
+#define ERR_DIV_BY_ZERO                                              -1074395270 // Cannot divide by zero.
+#define ERR_NULL_POINTER                                             -1074395269 // Null pointer.
+#define ERR_LINEAR_COEFF                                             -1074395268 // The linear equations are not independent.
+#define ERR_COMPLEX_ROOT                                             -1074395267 // The roots of the equation are complex.
+#define ERR_BARCODE                                                  -1074395265 // The barcode does not match the type you specified.
+#define ERR_LCD_NO_SEGMENTS                                          -1074395263 // No lit segment.
+#define ERR_LCD_BAD_MATCH                                            -1074395262 // The LCD does not form a known digit.
+#define ERR_GIP_RANGE                                                -1074395261 // An internal error occurred while attempting to access an invalid coordinate on an image.
+#define ERR_HEAP_TRASHED                                             -1074395260 // An internal memory error occurred.
+#define ERR_BAD_FILTER_WIDTH                                         -1074395258 // The filter width must be odd for the Canny operator.
+#define ERR_INVALID_EDGE_DIR                                         -1074395257 // You supplied an invalid edge direction in the Canny operator.
+#define ERR_EVEN_WINDOW_SIZE                                         -1074395256 // The window size must be odd for the Canny operator.
+#define ERR_INVALID_LEARN_MODE                                       -1074395253 // Invalid learn mode.
+#define ERR_LEARN_SETUP_DATA                                         -1074395252 // Invalid learn setup data.
+#define ERR_INVALID_MATCH_MODE                                       -1074395251 // Invalid match mode.
+#define ERR_MATCH_SETUP_DATA                                         -1074395250 // Invalid match setup data.
+#define ERR_ROTATION_ANGLE_RANGE_TOO_LARGE                           -1074395249 // At least one range in the array of rotation angle ranges exceeds 360 degrees.
+#define ERR_TOO_MANY_ROTATION_ANGLE_RANGES                           -1074395248 // The array of rotation angle ranges contains too many ranges.
+#define ERR_TEMPLATE_DESCRIPTOR                                      -1074395247 // Invalid template descriptor.
+#define ERR_TEMPLATE_DESCRIPTOR_1                                    -1074395246 // Invalid template descriptor.
+#define ERR_TEMPLATE_DESCRIPTOR_2                                    -1074395245 // Invalid template descriptor.
+#define ERR_TEMPLATE_DESCRIPTOR_3                                    -1074395244 // Invalid template descriptor.
+#define ERR_TEMPLATE_DESCRIPTOR_4                                    -1074395243 // The template descriptor was created with a newer version of NI Vision. Upgrade to the latest version of NI Vision to use this template.
+#define ERR_TEMPLATE_DESCRIPTOR_ROTATION                             -1074395242 // Invalid template descriptor.
+#define ERR_TEMPLATE_DESCRIPTOR_NOROTATION                           -1074395241 // The template descriptor does not contain data required for rotation-invariant matching.
+#define ERR_TEMPLATE_DESCRIPTOR_ROTATION_1                           -1074395240 // Invalid template descriptor.
+#define ERR_TEMPLATE_DESCRIPTOR_SHIFT                                -1074395239 // Invalid template descriptor.
+#define ERR_TEMPLATE_DESCRIPTOR_NOSHIFT                              -1074395238 // The template descriptor does not contain data required for shift-invariant matching.
+#define ERR_TEMPLATE_DESCRIPTOR_SHIFT_1                              -1074395237 // Invalid template descriptor.
+#define ERR_TEMPLATE_DESCRIPTOR_NOSCALE                              -1074395236 // The template descriptor does not contain data required for scale-invariant matching.
+#define ERR_TEMPLATE_IMAGE_CONTRAST_TOO_LOW                          -1074395235 // The template image does not contain enough contrast.
+#define ERR_TEMPLATE_IMAGE_TOO_SMALL                                 -1074395234 // The template image is too small.
+#define ERR_TEMPLATE_IMAGE_TOO_LARGE                                 -1074395233 // The template image is too large.
+#define ERR_TOO_MANY_OCR_SESSIONS                                    -1074395214 // There are too many OCR sessions open.  You must close a session before you can open another one.
+#define ERR_OCR_TEMPLATE_WRONG_SIZE                                  -1074395212 // The size of the template string must match the size of the string you are trying to correct.
+#define ERR_OCR_BAD_TEXT_TEMPLATE                                    -1074395211 // The supplied text template contains nonstandard characters that cannot be generated by OCR.
+#define ERR_OCR_CANNOT_MATCH_TEXT_TEMPLATE                           -1074395210 // At least one character in the text template was of a lexical class that did not match the supplied character reports.
+#define ERR_OCR_LIB_INIT                                             -1074395203 // The OCR library cannot be initialized correctly.
+#define ERR_OCR_LOAD_LIBRARY                                         -1074395201 // There was a failure when loading one of the internal OCR engine or LabView libraries.
+#define ERR_OCR_INVALID_PARAMETER                                    -1074395200 // One of the parameters supplied to the OCR function that generated this error is invalid.
+#define ERR_MARKER_INFORMATION_NOT_SUPPLIED                          -1074395199 // Marker image and points are not supplied
+#define ERR_INCOMPATIBLE_MARKER_IMAGE_SIZE                           -1074395198 // Source Image and Marker Image should be of same size.
+#define ERR_BOTH_MARKER_INPUTS_SUPPLIED                              -1074395197 // Both Marker Image and Points are supplied.
+#define ERR_INVALID_MORPHOLOGICAL_OPERATION                          -1074395196 // Invalid Morphological Operation.
+#define ERR_IMAGE_CONTAINS_NAN_VALUES                                -1074395195 // Float image contains NaN values
+#define ERR_OVERLAY_EXTRAINFO_OPENING_NEW_VERSION                    -1074395194 // The overlay information you tried to open was created with a newer version of NI Vision. Upgrade to the latest version of NI Vision to read this file.
+#define ERR_NO_CLAMP_FOUND                                           -1074395193 // No valid clamp was found with the current configuration
+#define ERR_NO_CLAMP_WITHIN_ANGLE_RANGE                              -1074395192 // Supplied angle range for clamp is insufficient
+#define ERR_GHT_INVALID_USE_ALL_CURVES_VALUE                         -1074395188 // The use all curves advanced option specified during learn is not supported
+#define ERR_INVALID_GAUSS_SIGMA_VALUE                                -1074395187 // The sigma value specified for the Gaussian filter is too small.
+#define ERR_INVALID_GAUSS_FILTER_TYPE                                -1074395186 // The specified Gaussian filter type is not supported.
+#define ERR_INVALID_CONTRAST_REVERSAL_MODE                           -1074395185 // The contrast reversal mode specified during matching is invalid.
+#define ERR_INVALID_ROTATION_RANGE                                   -1074395184 // Invalid roation angle range. The upper bound must be greater than or equal to the lower bound.
+#define ERR_GHT_INVALID_MINIMUM_LEARN_ANGLE_VALUE                    -1074395183 // The minimum rotation angle value specifed during learning of the template is not supported.
+#define ERR_GHT_INVALID_MAXIMUM_LEARN_ANGLE_VALUE                    -1074395182 // The maximum rotation angle value specifed during learning of the template is not supported.
+#define ERR_GHT_INVALID_MAXIMUM_LEARN_SCALE_FACTOR                   -1074395181 // The maximum scale factor specifed during learning of the template is not supported.
+#define ERR_GHT_INVALID_MINIMUM_LEARN_SCALE_FACTOR                   -1074395180 // The minimum scale factor specifed during learning of the template is not supported.
+#define ERR_OCR_PREPROCESSING_FAILED                                 -1074395179 // The OCR engine failed during the preprocessing stage.
+#define ERR_OCR_RECOGNITION_FAILED                                   -1074395178 // The OCR engine failed during the recognition stage.
+#define ERR_OCR_BAD_USER_DICTIONARY                                  -1074395175 // The provided filename is not valid user dictionary filename.
+#define ERR_OCR_INVALID_AUTOORIENTMODE                               -1074395174 // NI Vision does not support the AutoOrientMode value you supplied.
+#define ERR_OCR_INVALID_LANGUAGE                                     -1074395173 // NI Vision does not support the Language value you supplied.
+#define ERR_OCR_INVALID_CHARACTERSET                                 -1074395172 // NI Vision does not support the CharacterSet value you supplied.
+#define ERR_OCR_INI_FILE_NOT_FOUND                                   -1074395171 // The system could not locate the initialization file required for OCR initialization.
+#define ERR_OCR_INVALID_CHARACTERTYPE                                -1074395170 // NI Vision does not support the CharacterType value you supplied.
+#define ERR_OCR_INVALID_RECOGNITIONMODE                              -1074395169 // NI Vision does not support the RecognitionMode value you supplied.
+#define ERR_OCR_INVALID_AUTOCORRECTIONMODE                           -1074395168 // NI Vision does not support the AutoCorrectionMode value you supplied.
+#define ERR_OCR_INVALID_OUTPUTDELIMITER                              -1074395167 // NI Vision does not support the OutputDelimiter value you supplied.
+#define ERR_OCR_BIN_DIR_NOT_FOUND                                    -1074395166 // The system could not locate the OCR binary directory required for OCR initialization.
+#define ERR_OCR_WTS_DIR_NOT_FOUND                                    -1074395165 // The system could not locate the OCR weights directory required for OCR initialization.
+#define ERR_OCR_ADD_WORD_FAILED                                      -1074395164 // The supplied word could not be added to the user dictionary.
+#define ERR_OCR_INVALID_CHARACTERPREFERENCE                          -1074395163 // NI Vision does not support the CharacterPreference value you supplied.
+#define ERR_OCR_INVALID_CORRECTIONMODE                               -1074395162 // NI Vision does not support the CorrectionMethod value you supplied.
+#define ERR_OCR_INVALID_CORRECTIONLEVEL                              -1074395161 // NI Vision does not support the CorrectionLevel value you supplied.
+#define ERR_OCR_INVALID_MAXPOINTSIZE                                 -1074395160 // NI Vision does not support the maximum point size you supplied.  Valid values range from 4 to 72.
+#define ERR_OCR_INVALID_TOLERANCE                                    -1074395159 // NI Vision does not support the tolerance value you supplied.  Valid values are non-negative.
+#define ERR_OCR_INVALID_CONTRASTMODE                                 -1074395158 // NI Vision does not support the ContrastMode value you supplied.
+#define ERR_OCR_SKEW_DETECT_FAILED                                   -1074395156 // The OCR attempted to detected the text skew and failed.
+#define ERR_OCR_ORIENT_DETECT_FAILED                                 -1074395155 // The OCR attempted to detected the text orientation and failed.
+#define ERR_FONT_FILE_FORMAT                                         -1074395153 // Invalid font file format.
+#define ERR_FONT_FILE_NOT_FOUND                                      -1074395152 // Font file not found.
+#define ERR_OCR_CORRECTION_FAILED                                    -1074395151 // The OCR engine failed during the correction stage.
+#define ERR_INVALID_ROUNDING_MODE                                    -1074395150 // NI Vision does not support the RoundingMode value you supplied.
+#define ERR_DUPLICATE_TRANSFORM_TYPE                                 -1074395149 // Found a duplicate transform type in the properties array. Each properties array may only contain one behavior for each transform type.
+#define ERR_OVERLAY_GROUP_NOT_FOUND                                  -1074395148 // Overlay Group Not Found.
+#define ERR_BARCODE_RSSLIMITED                                       -1074395147 // The barcode is not a valid RSS Limited symbol
+#define ERR_QR_DETECTION_VERSION                                     -1074395146 // Couldn't determine the correct version of the QR code.
+#define ERR_QR_INVALID_READ                                          -1074395145 // Invalid read of the QR code.
+#define ERR_QR_INVALID_BARCODE                                       -1074395144 // The barcode that was read contains invalid parameters.
+#define ERR_QR_DETECTION_MODE                                        -1074395143 // The data stream that was demodulated could not be read because the mode was not detected.
+#define ERR_QR_DETECTION_MODELTYPE                                   -1074395142 // Couldn't determine the correct model of the QR code.
+#define ERR_OCR_NO_TEXT_FOUND                                        -1074395141 // The OCR engine could not find any text in the supplied region.
+#define ERR_OCR_CHAR_REPORT_CORRUPTED                                -1074395140 // One of the character reports is no longer usable by the system.
+#define ERR_IMAQ_QR_DIMENSION_INVALID                                -1074395139 // Invalid Dimensions.
+#define ERR_OCR_REGION_TOO_SMALL                                     -1074395138 // The OCR region provided was too small to have contained any characters.
+#define _FIRST_ERR  ERR_SYSTEM_ERROR
+#define _LAST_ERR   ERR_OCR_REGION_TOO_SMALL
+
+//============================================================================
+//  Enumerated Types
+//============================================================================
+typedef enum PointSymbol_enum {
+    IMAQ_POINT_AS_PIXEL          = 0,           //A single pixel represents a point in the overlay.
+    IMAQ_POINT_AS_CROSS          = 1,           //A cross represents a point in the overlay.
+    IMAQ_POINT_USER_DEFINED      = 2,           //The pattern supplied by the user represents a point in the overlay.
+    IMAQ_POINT_SYMBOL_SIZE_GUARD = 0xFFFFFFFF   
+} PointSymbol;
+
+typedef enum MeasurementValue_enum {
+    IMAQ_AREA                         = 0,           //Surface area of the particle in pixels.
+    IMAQ_AREA_CALIBRATED              = 1,           //Surface area of the particle in calibrated units.
+    IMAQ_NUM_HOLES                    = 2,           //Number of holes in the particle.
+    IMAQ_AREA_OF_HOLES                = 3,           //Surface area of the holes in calibrated units.
+    IMAQ_TOTAL_AREA                   = 4,           //Total surface area (holes and particle) in calibrated units.
+    IMAQ_IMAGE_AREA                   = 5,           //Surface area of the entire image in calibrated units.
+    IMAQ_PARTICLE_TO_IMAGE            = 6,           //Ratio, expressed as a percentage, of the surface area of a particle in relation to the total area of the particle.
+    IMAQ_PARTICLE_TO_TOTAL            = 7,           //Ratio, expressed as a percentage, of the surface area of a particle in relation to the total area of the particle.
+    IMAQ_CENTER_MASS_X                = 8,           //X-coordinate of the center of mass.
+    IMAQ_CENTER_MASS_Y                = 9,           //Y-coordinate of the center of mass.
+    IMAQ_LEFT_COLUMN                  = 10,          //Left edge of the bounding rectangle.
+    IMAQ_TOP_ROW                      = 11,          //Top edge of the bounding rectangle.
+    IMAQ_RIGHT_COLUMN                 = 12,          //Right edge of the bounding rectangle.
+    IMAQ_BOTTOM_ROW                   = 13,          //Bottom edge of bounding rectangle.
+    IMAQ_WIDTH                        = 14,          //Width of bounding rectangle in calibrated units.
+    IMAQ_HEIGHT                       = 15,          //Height of bounding rectangle in calibrated units.
+    IMAQ_MAX_SEGMENT_LENGTH           = 16,          //Length of longest horizontal line segment.
+    IMAQ_MAX_SEGMENT_LEFT_COLUMN      = 17,          //Leftmost x-coordinate of longest horizontal line segment.
+    IMAQ_MAX_SEGMENT_TOP_ROW          = 18,          //Y-coordinate of longest horizontal line segment.
+    IMAQ_PERIMETER                    = 19,          //Outer perimeter of the particle.
+    IMAQ_PERIMETER_OF_HOLES           = 20,          //Perimeter of all holes within the particle.
+    IMAQ_SIGMA_X                      = 21,          //Sum of the particle pixels on the x-axis.
+    IMAQ_SIGMA_Y                      = 22,          //Sum of the particle pixels on the y-axis.
+    IMAQ_SIGMA_XX                     = 23,          //Sum of the particle pixels on the x-axis squared.
+    IMAQ_SIGMA_YY                     = 24,          //Sum of the particle pixels on the y-axis squared.
+    IMAQ_SIGMA_XY                     = 25,          //Sum of the particle pixels on the x-axis and y-axis.
+    IMAQ_PROJ_X                       = 26,          //Projection corrected in X.
+    IMAQ_PROJ_Y                       = 27,          //Projection corrected in Y.
+    IMAQ_INERTIA_XX                   = 28,          //Inertia matrix coefficient in XX.
+    IMAQ_INERTIA_YY                   = 29,          //Inertia matrix coefficient in YY.
+    IMAQ_INERTIA_XY                   = 30,          //Inertia matrix coefficient in XY.
+    IMAQ_MEAN_H                       = 31,          //Mean length of horizontal segments.
+    IMAQ_MEAN_V                       = 32,          //Mean length of vertical segments.
+    IMAQ_MAX_INTERCEPT                = 33,          //Length of longest segment of the convex hull.
+    IMAQ_MEAN_INTERCEPT               = 34,          //Mean length of the chords in an object perpendicular to its max intercept.
+    IMAQ_ORIENTATION                  = 35,          //The orientation based on the inertia of the pixels in the particle.
+    IMAQ_EQUIV_ELLIPSE_MINOR          = 36,          //Total length of the axis of the ellipse having the same area as the particle and a major axis equal to half the max intercept.
+    IMAQ_ELLIPSE_MAJOR                = 37,          //Total length of major axis having the same area and perimeter as the particle in calibrated units.
+    IMAQ_ELLIPSE_MINOR                = 38,          //Total length of minor axis having the same area and perimeter as the particle in calibrated units.
+    IMAQ_ELLIPSE_RATIO                = 39,          //Fraction of major axis to minor axis.
+    IMAQ_RECT_LONG_SIDE               = 40,          //Length of the long side of a rectangle having the same area and perimeter as the particle in calibrated units.
+    IMAQ_RECT_SHORT_SIDE              = 41,          //Length of the short side of a rectangle having the same area and perimeter as the particle in calibrated units.
+    IMAQ_RECT_RATIO                   = 42,          //Ratio of rectangle long side to rectangle short side.
+    IMAQ_ELONGATION                   = 43,          //Max intercept/mean perpendicular intercept.
+    IMAQ_COMPACTNESS                  = 44,          //Particle area/(height x width).
+    IMAQ_HEYWOOD                      = 45,          //Particle perimeter/perimeter of the circle having the same area as the particle.
+    IMAQ_TYPE_FACTOR                  = 46,          //A complex factor relating the surface area to the moment of inertia.
+    IMAQ_HYDRAULIC                    = 47,          //Particle area/particle perimeter.
+    IMAQ_WADDLE_DISK                  = 48,          //Diameter of the disk having the same area as the particle in user units.
+    IMAQ_DIAGONAL                     = 49,          //Diagonal of an equivalent rectangle in user units.
+    IMAQ_MEASUREMENT_VALUE_SIZE_GUARD = 0xFFFFFFFF   
+} MeasurementValue;
+
+typedef enum ScalingMode_enum {
+    IMAQ_SCALE_LARGER            = 0,           //The function duplicates pixels to make the image larger.
+    IMAQ_SCALE_SMALLER           = 1,           //The function subsamples pixels to make the image smaller.
+    IMAQ_SCALING_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} ScalingMode;
+
+typedef enum ScalingMethod_enum {
+    IMAQ_SCALE_TO_PRESERVE_AREA    = 0,           //Correction functions scale the image such that the features in the corrected image have the same area as the features in the input image.
+    IMAQ_SCALE_TO_FIT              = 1,           //Correction functions scale the image such that the corrected image is the same size as the input image.
+    IMAQ_SCALING_METHOD_SIZE_GUARD = 0xFFFFFFFF   
+} ScalingMethod;
+
+typedef enum ReferenceMode_enum {
+    IMAQ_COORD_X_Y                 = 0,           //This method requires three elements in the points array.
+    IMAQ_COORD_ORIGIN_X            = 1,           //This method requires two elements in the points array.
+    IMAQ_REFERENCE_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} ReferenceMode;
+
+typedef enum RectOrientation_enum {
+    IMAQ_BASE_INSIDE                 = 0,           //Specifies that the base of the rectangular image lies along the inside edge of the annulus.
+    IMAQ_BASE_OUTSIDE                = 1,           //Specifies that the base of the rectangular image lies along the outside edge of the annulus.
+    IMAQ_TEXT_ORIENTATION_SIZE_GUARD = 0xFFFFFFFF   
+} RectOrientation;
+
+typedef enum ShapeMode_enum {
+    IMAQ_SHAPE_RECT            = 1,           //The function draws a rectangle.
+    IMAQ_SHAPE_OVAL            = 2,           //The function draws an oval.
+    IMAQ_SHAPE_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} ShapeMode;
+
+typedef enum PolarityType_enum {
+    IMAQ_EDGE_RISING              = 1,           //The edge is a rising edge.
+    IMAQ_EDGE_FALLING             = -1,          //The edge is a falling edge.
+    IMAQ_POLARITY_TYPE_SIZE_GUARD = 0xFFFFFFFF   
+} PolarityType;
+
+typedef enum SizeType_enum {
+    IMAQ_KEEP_LARGE           = 0,           //The function keeps large particles remaining after the erosion.
+    IMAQ_KEEP_SMALL           = 1,           //The function keeps small particles eliminated by the erosion.
+    IMAQ_SIZE_TYPE_SIZE_GUARD = 0xFFFFFFFF   
+} SizeType;
+
+typedef enum Plane3D_enum {
+    IMAQ_3D_REAL             = 0,           //The function shows the real part of complex images.
+    IMAQ_3D_IMAGINARY        = 1,           //The function shows the imaginary part of complex images.
+    IMAQ_3D_MAGNITUDE        = 2,           //The function shows the magnitude part of complex images.
+    IMAQ_3D_PHASE            = 3,           //The function shows the phase part of complex images.
+    IMAQ_PLANE_3D_SIZE_GUARD = 0xFFFFFFFF   
+} Plane3D;
+
+typedef enum PhotometricMode_enum {
+    IMAQ_WHITE_IS_ZERO               = 0,           //The function interprets zero-value pixels as white.
+    IMAQ_BLACK_IS_ZERO               = 1,           //The function interprets zero-value pixels as black.
+    IMAQ_PHOTOMETRIC_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} PhotometricMode;
+
+typedef enum ParticleInfoMode_enum {
+    IMAQ_BASIC_INFO                    = 0,           //The function returns only the following elements of each report: area, calibratedArea, boundingRect.
+    IMAQ_ALL_INFO                      = 1,           //The function returns all the information about each particle.
+    IMAQ_PARTICLE_INFO_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} ParticleInfoMode;
+
+typedef enum OutlineMethod_enum {
+    IMAQ_EDGE_DIFFERENCE           = 0,           //The function uses a method that produces continuous contours by highlighting each pixel where an intensity variation occurs between itself and its three upper-left neighbors.
+    IMAQ_EDGE_GRADIENT             = 1,           //The function uses a method that outlines contours where an intensity variation occurs along the vertical axis.
+    IMAQ_EDGE_PREWITT              = 2,           //The function uses a method that extracts the outer contours of objects.
+    IMAQ_EDGE_ROBERTS              = 3,           //The function uses a method that outlines the contours that highlight pixels where an intensity variation occurs along the diagonal axes.
+    IMAQ_EDGE_SIGMA                = 4,           //The function uses a method that outlines contours and details by setting pixels to the mean value found in their neighborhood, if their deviation from this value is not significant.
+    IMAQ_EDGE_SOBEL                = 5,           //The function uses a method that extracts the outer contours of objects.
+    IMAQ_OUTLINE_METHOD_SIZE_GUARD = 0xFFFFFFFF   
+} OutlineMethod;
+
+typedef enum MorphologyMethod_enum {
+    IMAQ_AUTOM                        = 0,           //The function uses a transformation that generates simpler particles that contain fewer details.
+    IMAQ_CLOSE                        = 1,           //The function uses a transformation that fills tiny holes and smooths boundaries.
+    IMAQ_DILATE                       = 2,           //The function uses a transformation that eliminates tiny holes isolated in particles and expands the contour of the particles according to the template defined by the structuring element.
+    IMAQ_ERODE                        = 3,           //The function uses a transformation that eliminates pixels isolated in the background and erodes the contour of particles according to the template defined by the structuring element.
+    IMAQ_GRADIENT                     = 4,           //The function uses a transformation that leaves only the pixels that would be added by the dilation process or eliminated by the erosion process.
+    IMAQ_GRADIENTOUT                  = 5,           //The function uses a transformation that leaves only the pixels that would be added by the dilation process.
+    IMAQ_GRADIENTIN                   = 6,           //The function uses a transformation that leaves only the pixels that would be eliminated by the erosion process.
+    IMAQ_HITMISS                      = 7,           //The function uses a transformation that extracts each pixel located in a neighborhood exactly matching the template defined by the structuring element.
+    IMAQ_OPEN                         = 8,           //The function uses a transformation that removes small particles and smooths boundaries.
+    IMAQ_PCLOSE                       = 9,           //The function uses a transformation that fills tiny holes and smooths the inner contour of particles according to the template defined by the structuring element.
+    IMAQ_POPEN                        = 10,          //The function uses a transformation that removes small particles and smooths the contour of particles according to the template defined by the structuring element.
+    IMAQ_THICK                        = 11,          //The function uses a transformation that adds to an image those pixels located in a neighborhood that matches a template specified by the structuring element.
+    IMAQ_THIN                         = 12,          //The function uses a transformation that eliminates pixels that are located in a neighborhood matching a template specified by the structuring element.
+    IMAQ_MORPHOLOGY_METHOD_SIZE_GUARD = 0xFFFFFFFF   
+} MorphologyMethod;
+
+typedef enum MeterArcMode_enum {
+    IMAQ_METER_ARC_ROI             = 0,           //The function uses the roi parameter and ignores the base, start, and end parameters.
+    IMAQ_METER_ARC_POINTS          = 1,           //The function uses the base,start, and end parameters and ignores the roi parameter.
+    IMAQ_METER_ARC_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} MeterArcMode;
+
+typedef enum RakeDirection_enum {
+    IMAQ_LEFT_TO_RIGHT             = 0,           //The function searches from the left side of the search area to the right side of the search area.
+    IMAQ_RIGHT_TO_LEFT             = 1,           //The function searches from the right side of the search area to the left side of the search area.
+    IMAQ_TOP_TO_BOTTOM             = 2,           //The function searches from the top side of the search area to the bottom side of the search area.
+    IMAQ_BOTTOM_TO_TOP             = 3,           //The function searches from the bottom side of the search area to the top side of the search area.
+    IMAQ_RAKE_DIRECTION_SIZE_GUARD = 0xFFFFFFFF   
+} RakeDirection;
+
+typedef enum TruncateMode_enum {
+    IMAQ_TRUNCATE_LOW             = 0,           //The function truncates low frequencies.
+    IMAQ_TRUNCATE_HIGH            = 1,           //The function truncates high frequencies.
+    IMAQ_TRUNCATE_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} TruncateMode;
+
+typedef enum AttenuateMode_enum {
+    IMAQ_ATTENUATE_LOW             = 0,           //The function attenuates low frequencies.
+    IMAQ_ATTENUATE_HIGH            = 1,           //The function attenuates high frequencies.
+    IMAQ_ATTENUATE_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} AttenuateMode;
+
+typedef enum WindowThreadPolicy_enum {
+    IMAQ_CALLING_THREAD                  = 0,           //Using this policy, NI Vision creates windows in the thread that makes the first display function call for a given window number.
+    IMAQ_SEPARATE_THREAD                 = 1,           //Using this policy, NI Vision creates windows in a separate thread and processes messages for the windows automatically.
+    IMAQ_WINDOW_THREAD_POLICY_SIZE_GUARD = 0xFFFFFFFF   
+} WindowThreadPolicy;
+
+typedef enum WindowOptions_enum {
+    IMAQ_WIND_RESIZABLE            = 1,           //When present, the user may resize the window interactively.
+    IMAQ_WIND_TITLEBAR             = 2,           //When present, the title bar on the window is visible.
+    IMAQ_WIND_CLOSEABLE            = 4,           //When present, the close box is available.
+    IMAQ_WIND_TOPMOST              = 8,           //When present, the window is always on top.
+    IMAQ_WINDOW_OPTIONS_SIZE_GUARD = 0xFFFFFFFF   
+} WindowOptions;
+
+typedef enum WindowEventType_enum {
+    IMAQ_NO_EVENT                     = 0,           //No event occurred since the last call to imaqGetLastEvent().
+    IMAQ_CLICK_EVENT                  = 1,           //The user clicked on a window.
+    IMAQ_DRAW_EVENT                   = 2,           //The user drew an ROI in a window.
+    IMAQ_MOVE_EVENT                   = 3,           //The user moved a window.
+    IMAQ_SIZE_EVENT                   = 4,           //The user sized a window.
+    IMAQ_SCROLL_EVENT                 = 5,           //The user scrolled a window.
+    IMAQ_ACTIVATE_EVENT               = 6,           //The user activated a window.
+    IMAQ_CLOSE_EVENT                  = 7,           //The user closed a window.
+    IMAQ_DOUBLE_CLICK_EVENT           = 8,           //The user double-clicked in a window.
+    IMAQ_WINDOW_EVENT_TYPE_SIZE_GUARD = 0xFFFFFFFF   
+} WindowEventType;
+
+typedef enum VisionInfoType_enum {
+    IMAQ_ANY_VISION_INFO             = 0,           //The function checks if any extra vision information is associated with the image.
+    IMAQ_PATTERN_MATCHING_INFO       = 1,           //The function checks if any pattern matching template information is associated with the image.
+    IMAQ_CALIBRATION_INFO            = 2,           //The function checks if any calibration information is associated with the image.
+    IMAQ_OVERLAY_INFO                = 3,           //The function checks if any overlay information is associated with the image.
+    IMAQ_VISION_INFO_TYPE_SIZE_GUARD = 0xFFFFFFFF   
+} VisionInfoType;
+
+typedef enum SearchStrategy_enum {
+    IMAQ_CONSERVATIVE               = 1,           //Instructs the pattern matching algorithm to use the largest possible amount of information from the image at the expense of slowing down the speed of the algorithm.
+    IMAQ_BALANCED                   = 2,           //Instructs the pattern matching algorithm to balance the amount of information from the image it uses with the speed of the algorithm.
+    IMAQ_AGGRESSIVE                 = 3,           //Instructs the pattern matching algorithm to use a lower amount of information from the image, which allows the algorithm to run quickly but at the expense of accuracy.
+    IMAQ_VERY_AGGRESSIVE            = 4,           //Instructs the pattern matching algorithm to use the smallest possible amount of information from the image, which allows the algorithm to run at the highest speed possible but at the expense of accuracy.
+    IMAQ_SEARCH_STRATEGY_SIZE_GUARD = 0xFFFFFFFF   
+} SearchStrategy;
+
+typedef enum TwoEdgePolarityType_enum {
+    IMAQ_NONE                              = 0,           //The function ignores the polarity of the edges.
+    IMAQ_RISING_FALLING                    = 1,           //The polarity of the first edge is rising (dark to light) and the polarity of the second edge is falling (light to dark).
+    IMAQ_FALLING_RISING                    = 2,           //The polarity of the first edge is falling (light to dark) and the polarity of the second edge is rising (dark to light).
+    IMAQ_RISING_RISING                     = 3,           //The polarity of the first edge is rising (dark to light) and the polarity of the second edge is rising (dark to light).
+    IMAQ_FALLING_FALLING                   = 4,           //The polarity of the first edge is falling (light to dark) and the polarity of the second edge is falling (light to dark).
+    IMAQ_TWO_EDGE_POLARITY_TYPE_SIZE_GUARD = 0xFFFFFFFF   
+} TwoEdgePolarityType;
+
+typedef enum ObjectType_enum {
+    IMAQ_BRIGHT_OBJECTS         = 0,           //The function detects bright objects.
+    IMAQ_DARK_OBJECTS           = 1,           //The function detects dark objects.
+    IMAQ_OBJECT_TYPE_SIZE_GUARD = 0xFFFFFFFF   
+} ObjectType;
+
+typedef enum Tool_enum {
+    IMAQ_NO_TOOL              = -1,          //No tool is in the selected state.
+    IMAQ_SELECTION_TOOL       = 0,           //The selection tool selects an existing ROI in an image.
+    IMAQ_POINT_TOOL           = 1,           //The point tool draws a point on the image.
+    IMAQ_LINE_TOOL            = 2,           //The line tool draws a line on the image.
+    IMAQ_RECTANGLE_TOOL       = 3,           //The rectangle tool draws a rectangle on the image.
+    IMAQ_OVAL_TOOL            = 4,           //The oval tool draws an oval on the image.
+    IMAQ_POLYGON_TOOL         = 5,           //The polygon tool draws a polygon on the image.
+    IMAQ_CLOSED_FREEHAND_TOOL = 6,           //The closed freehand tool draws closed freehand shapes on the image.
+    IMAQ_ANNULUS_TOOL         = 7,           //The annulus tool draws annuluses on the image.
+    IMAQ_ZOOM_TOOL            = 8,           //The zoom tool controls the zoom of an image.
+    IMAQ_PAN_TOOL             = 9,           //The pan tool shifts the view of the image.
+    IMAQ_POLYLINE_TOOL        = 10,          //The polyline tool draws a series of connected straight lines on the image.
+    IMAQ_FREEHAND_TOOL        = 11,          //The freehand tool draws freehand lines on the image.
+    IMAQ_ROTATED_RECT_TOOL    = 12,          //The rotated rectangle tool draws rotated rectangles on the image.
+    IMAQ_ZOOM_OUT_TOOL        = 13,          //The zoom out tool controls the zoom of an image.
+    IMAQ_TOOL_SIZE_GUARD      = 0xFFFFFFFF   
+} Tool;
+
+typedef enum TIFFCompressionType_enum {
+    IMAQ_NO_COMPRESSION                   = 0,           //The function does not compress the TIFF file.
+    IMAQ_JPEG                             = 1,           //The function uses the JPEG compression algorithm to compress the TIFF file.
+    IMAQ_RUN_LENGTH                       = 2,           //The function uses a run length compression algorithm to compress the TIFF file.
+    IMAQ_ZIP                              = 3,           //The function uses the ZIP compression algorithm to compress the TIFF file.
+    IMAQ_TIFF_COMPRESSION_TYPE_SIZE_GUARD = 0xFFFFFFFF   
+} TIFFCompressionType;
+
+typedef enum ThresholdMethod_enum {
+    IMAQ_THRESH_CLUSTERING           = 0,           //The function uses a method that sorts the histogram of the image within a discrete number of classes corresponding to the number of phases perceived in an image.
+    IMAQ_THRESH_ENTROPY              = 1,           //The function uses a method that is best for detecting particles that are present in minuscule proportions on the image.
+    IMAQ_THRESH_METRIC               = 2,           //The function uses a method that is well-suited for images in which classes are not too disproportionate.
+    IMAQ_THRESH_MOMENTS              = 3,           //The function uses a method that is suited for images that have poor contrast.
+    IMAQ_THRESH_INTERCLASS           = 4,           //The function uses a method that is well-suited for images in which classes have well separated pixel value distributions.
+    IMAQ_THRESHOLD_METHOD_SIZE_GUARD = 0xFFFFFFFF   
+} ThresholdMethod;
+
+typedef enum TextAlignment_enum {
+    IMAQ_LEFT                      = 0,           //Left aligns the text at the reference point.
+    IMAQ_CENTER                    = 1,           //Centers the text around the reference point.
+    IMAQ_RIGHT                     = 2,           //Right aligns the text at the reference point.
+    IMAQ_TEXT_ALIGNMENT_SIZE_GUARD = 0xFFFFFFFF   
+} TextAlignment;
+
+typedef enum SpokeDirection_enum {
+    IMAQ_OUTSIDE_TO_INSIDE          = 0,           //The function searches from the outside of the search area to the inside of the search area.
+    IMAQ_INSIDE_TO_OUTSIDE          = 1,           //The function searches from the inside of the search area to the outside of the search area.
+    IMAQ_SPOKE_DIRECTION_SIZE_GUARD = 0xFFFFFFFF   
+} SpokeDirection;
+
+typedef enum SkeletonMethod_enum {
+    IMAQ_SKELETON_L                 = 0,           //Uses an L-shaped structuring element in the skeleton function.
+    IMAQ_SKELETON_M                 = 1,           //Uses an M-shaped structuring element in the skeleton function.
+    IMAQ_SKELETON_INVERSE           = 2,           //Uses an L-shaped structuring element on an inverse of the image in the skeleton function.
+    IMAQ_SKELETON_METHOD_SIZE_GUARD = 0xFFFFFFFF   
+} SkeletonMethod;
+
+typedef enum VerticalTextAlignment_enum {
+    IMAQ_BOTTOM                             = 0,           //Aligns the bottom of the text at the reference point.
+    IMAQ_TOP                                = 1,           //Aligns the top of the text at the reference point.
+    IMAQ_BASELINE                           = 2,           //Aligns the baseline of the text at the reference point.
+    IMAQ_VERTICAL_TEXT_ALIGNMENT_SIZE_GUARD = 0xFFFFFFFF   
+} VerticalTextAlignment;
+
+typedef enum CalibrationROI_enum {
+    IMAQ_FULL_IMAGE                 = 0,           //The correction function corrects the whole image, regardless of the user-defined or calibration-defined ROIs.
+    IMAQ_CALIBRATION_ROI            = 1,           //The correction function corrects the area defined by the calibration ROI.
+    IMAQ_USER_ROI                   = 2,           //The correction function corrects the area defined by the user-defined ROI.
+    IMAQ_CALIBRATION_AND_USER_ROI   = 3,           //The correction function corrects the area defined by the intersection of the user-defined ROI and the calibration ROI.
+    IMAQ_CALIBRATION_OR_USER_ROI    = 4,           //The correction function corrects the area defined by the union of the user-defined ROI and the calibration ROI.
+    IMAQ_CALIBRATION_ROI_SIZE_GUARD = 0xFFFFFFFF   
+} CalibrationROI;
+
+typedef enum ContourType_enum {
+    IMAQ_EMPTY_CONTOUR           = 0,           //The contour is empty.
+    IMAQ_POINT                   = 1,           //The contour represents a point.
+    IMAQ_LINE                    = 2,           //The contour represents a line.
+    IMAQ_RECT                    = 3,           //The contour represents a rectangle.
+    IMAQ_OVAL                    = 4,           //The contour represents an oval.
+    IMAQ_CLOSED_CONTOUR          = 5,           //The contour represents a series of connected points where the last point connects to the first.
+    IMAQ_OPEN_CONTOUR            = 6,           //The contour represents a series of connected points where the last point does not connect to the first.
+    IMAQ_ANNULUS                 = 7,           //The contour represents an annulus.
+    IMAQ_ROTATED_RECT            = 8,           //The contour represents a rotated rectangle.
+    IMAQ_CONTOUR_TYPE_SIZE_GUARD = 0xFFFFFFFF   
+} ContourType;
+
+typedef enum MathTransformMethod_enum {
+    IMAQ_TRANSFORM_LINEAR                 = 0,           //The function uses linear remapping.
+    IMAQ_TRANSFORM_LOG                    = 1,           //The function uses logarithmic remapping.
+    IMAQ_TRANSFORM_EXP                    = 2,           //The function uses exponential remapping.
+    IMAQ_TRANSFORM_SQR                    = 3,           //The function uses square remapping.
+    IMAQ_TRANSFORM_SQRT                   = 4,           //The function uses square root remapping.
+    IMAQ_TRANSFORM_POWX                   = 5,           //The function uses power X remapping.
+    IMAQ_TRANSFORM_POW1X                  = 6,           //The function uses power 1/X remapping.
+    IMAQ_MATH_TRANSFORM_METHOD_SIZE_GUARD = 0xFFFFFFFF   
+} MathTransformMethod;
+
+typedef enum ComplexPlane_enum {
+    IMAQ_REAL                     = 0,           //The function operates on the real plane of the complex image.
+    IMAQ_IMAGINARY                = 1,           //The function operates on the imaginary plane of the complex image.
+    IMAQ_MAGNITUDE                = 2,           //The function operates on the magnitude plane of the complex image.
+    IMAQ_PHASE                    = 3,           //The function operates on the phase plane of the complex image.
+    IMAQ_COMPLEX_PLANE_SIZE_GUARD = 0xFFFFFFFF   
+} ComplexPlane;
+
+typedef enum PaletteType_enum {
+    IMAQ_PALETTE_GRAY            = 0,           //The function uses a palette that has a gradual gray-level variation from black to white.
+    IMAQ_PALETTE_BINARY          = 1,           //The function uses a palette of 16 cycles of 16 different colors that is useful with binary images.
+    IMAQ_PALETTE_GRADIENT        = 2,           //The function uses a palette that has a gradation from red to white with a prominent range of light blue in the upper value range.
+    IMAQ_PALETTE_RAINBOW         = 3,           //The function uses a palette that has a gradation from blue to red with a prominent range of greens in the middle value range.
+    IMAQ_PALETTE_TEMPERATURE     = 4,           //The function uses a palette that has a gradation from light brown to dark brown.
+    IMAQ_PALETTE_USER            = 5,           //The function uses a palette defined by the user.
+    IMAQ_PALETTE_TYPE_SIZE_GUARD = 0xFFFFFFFF   
+} PaletteType;
+
+typedef enum ColorSensitivity_enum {
+    IMAQ_SENSITIVITY_LOW              = 0,           //Instructs the algorithm to divide the hue plane into a low number of sectors, allowing for simple color analysis.
+    IMAQ_SENSITIVITY_MED              = 1,           //Instructs the algorithm to divide the hue plane into a medium number of sectors, allowing for color analysis that balances sensitivity and complexity.
+    IMAQ_SENSITIVITY_HIGH             = 2,           //Instructs the algorithm to divide the hue plane into a high number of sectors, allowing for complex, sensitive color analysis.
+    IMAQ_COLOR_SENSITIVITY_SIZE_GUARD = 0xFFFFFFFF   
+} ColorSensitivity;
+
+typedef enum ColorMode_enum {
+    IMAQ_RGB                   = 0,           //The function operates in the RGB (Red, Blue, Green) color space.
+    IMAQ_HSL                   = 1,           //The function operates in the HSL (Hue, Saturation, Luminance) color space.
+    IMAQ_HSV                   = 2,           //The function operates in the HSV (Hue, Saturation, Value) color space.
+    IMAQ_HSI                   = 3,           //The function operates in the HSI (Hue, Saturation, Intensity) color space.
+    IMAQ_CIE                   = 4,           //The function operates in the CIE L*a*b* color space.
+    IMAQ_CIEXYZ                = 5,           //The function operates in the CIE XYZ color space.
+    IMAQ_COLOR_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} ColorMode;
+
+typedef enum DetectionMode_enum {
+    IMAQ_DETECT_PEAKS              = 0,           //The function detects peaks.
+    IMAQ_DETECT_VALLEYS            = 1,           //The function detects valleys.
+    IMAQ_DETECTION_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} DetectionMode;
+
+typedef enum CalibrationUnit_enum {
+    IMAQ_UNDEFINED                   = 0,           //The image does not have a defined unit of measurement.
+    IMAQ_ANGSTROM                    = 1,           //The unit of measure for the image is angstroms.
+    IMAQ_MICROMETER                  = 2,           //The unit of measure for the image is micrometers.
+    IMAQ_MILLIMETER                  = 3,           //The unit of measure for the image is millimeters.
+    IMAQ_CENTIMETER                  = 4,           //The unit of measure for the image is centimeters.
+    IMAQ_METER                       = 5,           //The unit of measure for the image is meters.
+    IMAQ_KILOMETER                   = 6,           //The unit of measure for the image is kilometers.
+    IMAQ_MICROINCH                   = 7,           //The unit of measure for the image is microinches.
+    IMAQ_INCH                        = 8,           //The unit of measure for the image is inches.
+    IMAQ_FOOT                        = 9,           //The unit of measure for the image is feet.
+    IMAQ_NAUTICMILE                  = 10,          //The unit of measure for the image is nautical miles.
+    IMAQ_GROUNDMILE                  = 11,          //The unit of measure for the image is ground miles.
+    IMAQ_STEP                        = 12,          //The unit of measure for the image is steps.
+    IMAQ_CALIBRATION_UNIT_SIZE_GUARD = 0xFFFFFFFF   
+} CalibrationUnit;
+
+typedef enum ConcentricRakeDirection_enum {
+    IMAQ_COUNTER_CLOCKWISE                    = 0,           //The function searches the search area in a counter-clockwise direction.
+    IMAQ_CLOCKWISE                            = 1,           //The function searches the search area in a clockwise direction.
+    IMAQ_CONCENTRIC_RAKE_DIRECTION_SIZE_GUARD = 0xFFFFFFFF   
+} ConcentricRakeDirection;
+
+typedef enum CalibrationMode_enum {
+    IMAQ_PERSPECTIVE                 = 0,           //Functions correct for distortion caused by the camera's perspective.
+    IMAQ_NONLINEAR                   = 1,           //Functions correct for distortion caused by the camera's lens.
+    IMAQ_SIMPLE_CALIBRATION          = 2,           //Functions do not correct for distortion.
+    IMAQ_CORRECTED_IMAGE             = 3,           //The image is already corrected.
+    IMAQ_CALIBRATION_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} CalibrationMode;
+
+typedef enum BrowserLocation_enum {
+    IMAQ_INSERT_FIRST_FREE           = 0,           //Inserts the thumbnail in the first available cell.
+    IMAQ_INSERT_END                  = 1,           //Inserts the thumbnail after the last occupied cell.
+    IMAQ_BROWSER_LOCATION_SIZE_GUARD = 0xFFFFFFFF   
+} BrowserLocation;
+
+typedef enum BrowserFrameStyle_enum {
+    IMAQ_RAISED_FRAME                   = 0,           //Each thumbnail has a raised frame.
+    IMAQ_BEVELLED_FRAME                 = 1,           //Each thumbnail has a beveled frame.
+    IMAQ_OUTLINE_FRAME                  = 2,           //Each thumbnail has an outlined frame.
+    IMAQ_HIDDEN_FRAME                   = 3,           //Each thumbnail has a hidden frame.
+    IMAQ_STEP_FRAME                     = 4,           //Each thumbnail has a stepped frame.
+    IMAQ_RAISED_OUTLINE_FRAME           = 5,           //Each thumbnail has a raised, outlined frame.
+    IMAQ_BROWSER_FRAME_STYLE_SIZE_GUARD = 0xFFFFFFFF   
+} BrowserFrameStyle;
+
+typedef enum BorderMethod_enum {
+    IMAQ_BORDER_MIRROR            = 0,           //Symmetrically copies pixel values from the image into the border.
+    IMAQ_BORDER_COPY              = 1,           //Copies the value of the pixel closest to the edge of the image into the border.
+    IMAQ_BORDER_CLEAR             = 2,           //Sets all pixels in the border to 0.
+    IMAQ_BORDER_METHOD_SIZE_GUARD = 0xFFFFFFFF   
+} BorderMethod;
+
+typedef enum BarcodeType_enum {
+    IMAQ_INVALID                 = -1,          //The barcode is not of a type known by NI Vision.
+    IMAQ_CODABAR                 = 1,           //The barcode is of type Codabar.
+    IMAQ_CODE39                  = 2,           //The barcode is of type Code 39.
+    IMAQ_CODE93                  = 4,           //The barcode is of type Code 93.
+    IMAQ_CODE128                 = 8,           //The barcode is of type Code 128.
+    IMAQ_EAN8                    = 16,          //The barcode is of type EAN 8.
+    IMAQ_EAN13                   = 32,          //The barcode is of type EAN 13.
+    IMAQ_I2_OF_5                 = 64,          //The barcode is of type Code 25.
+    IMAQ_MSI                     = 128,         //The barcode is of type MSI code.
+    IMAQ_UPCA                    = 256,         //The barcode is of type UPC A.
+    IMAQ_PHARMACODE              = 512,         //The barcode is of type Pharmacode.
+    IMAQ_RSS_LIMITED             = 1024,        //The barcode is of type RSS Limited.
+    IMAQ_BARCODE_TYPE_SIZE_GUARD = 0xFFFFFFFF   
+} BarcodeType;
+
+typedef enum AxisOrientation_enum {
+    IMAQ_DIRECT                      = 0,           //The y-axis direction corresponds to the y-axis direction of the Cartesian coordinate system.
+    IMAQ_INDIRECT                    = 1,           //The y-axis direction corresponds to the y-axis direction of an image.
+    IMAQ_AXIS_ORIENTATION_SIZE_GUARD = 0xFFFFFFFF   
+} AxisOrientation;
+
+typedef enum ColorIgnoreMode_enum {
+    IMAQ_IGNORE_NONE                        = 0,           //Specifies that the function does not ignore any pixels.
+    IMAQ_IGNORE_BLACK                       = 1,           //Specifies that the function ignores black pixels.
+    IMAQ_IGNORE_WHITE                       = 2,           //Specifies that the function ignores white pixels.
+    IMAQ_IGNORE_BLACK_AND_WHITE             = 3,           //Specifies that the function ignores black pixels and white pixels.
+    IMAQ_BLACK_WHITE_IGNORE_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} ColorIgnoreMode;
+
+typedef enum LevelType_enum {
+    IMAQ_ABSOLUTE              = 0,           //The function evaluates the threshold and hysteresis values as absolute values.
+    IMAQ_RELATIVE              = 1,           //The function evaluates the threshold and hysteresis values relative to the dynamic range of the given path.
+    IMAQ_LEVEL_TYPE_SIZE_GUARD = 0xFFFFFFFF   
+} LevelType;
+
+typedef enum MatchingMode_enum {
+    IMAQ_MATCH_SHIFT_INVARIANT    = 1,           //Searches for occurrences of the template image anywhere in the searchRect, assuming that the pattern is not rotated more than plus or minus 4 degrees.
+    IMAQ_MATCH_ROTATION_INVARIANT = 2,           //Searches for occurrences of the pattern in the image with no restriction on the rotation of the pattern.
+    IMAQ_MATCHING_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} MatchingMode;
+
+typedef enum MappingMethod_enum {
+    IMAQ_FULL_DYNAMIC              = 0,           //(Obsolete) When the image bit depth is 0, the function maps the full dynamic range of the 16-bit image to an 8-bit scale.
+    IMAQ_DOWNSHIFT                 = 1,           //(Obsolete) When the image bit depth is 0, the function shifts the 16-bit image pixels to the right the number of times specified by the shiftCount element of the DisplayMapping structure.
+    IMAQ_RANGE                     = 2,           //(Obsolete) When the image bit depth is 0, the function maps the pixel values in the range specified by the minimumValue and maximumValue elements of the DisplayMapping structure to an 8-bit scale.
+    IMAQ_90_PCT_DYNAMIC            = 3,           //(Obsolete) When the image bit depth to 0, the function maps the dynamic range containing the middle 90 percent of the cumulated histogram of the image to an 8-bit (256 grayscale values) scale.
+    IMAQ_PERCENT_RANGE             = 4,           //(Obsolete) When the image bit depth is 0, the function maps the pixel values in the relative percentage range (0 to 100) of the cumulated histogram specified by minimumValue and maximumValue to an 8-bit scale.
+    IMAQ_DEFAULT_MAPPING           = 10,          //If the bit depth is 0, the function maps the 16-bit image to 8 bits by following the IMAQ_FULL_DYNAMIC_ALWAYS behavior; otherwise, the function shifts the image data to the right according to the IMAQ_MOST_SIGNIFICANT behavior.
+    IMAQ_MOST_SIGNIFICANT          = 11,          //The function shifts the 16-bit image pixels to the right until the 8 most significant bits of the image data are remaining.
+    IMAQ_FULL_DYNAMIC_ALWAYS       = 12,          //The function maps the full dynamic range of the 16-bit image to an 8-bit scale.
+    IMAQ_DOWNSHIFT_ALWAYS          = 13,          //The function shifts the 16-bit image pixels to the right the number of times specified by the shiftCount element of the DisplayMapping structure.
+    IMAQ_RANGE_ALWAYS              = 14,          //The function maps the pixel values in the range specified by the minimumValue and maximumValue elements of the DisplayMapping structure to an 8-bit scale.
+    IMAQ_90_PCT_DYNAMIC_ALWAYS     = 15,          //The function maps the dynamic range containing the middle 90 percent of the cumulated histogram of the image to an 8-bit (256 grayscale values) scale.
+    IMAQ_PERCENT_RANGE_ALWAYS      = 16,          //The function maps the pixel values in the relative percentage range (0 to 100) of the cumulated histogram specified by minimumValue and maximumValue to an 8-bit scale.
+    IMAQ_MAPPING_METHOD_SIZE_GUARD = 0xFFFFFFFF   
+} MappingMethod;
+
+typedef enum ComparisonFunction_enum {
+    IMAQ_CLEAR_LESS                  = 0,           //The comparison is true if the source pixel value is less than the comparison image pixel value.
+    IMAQ_CLEAR_LESS_OR_EQUAL         = 1,           //The comparison is true if the source pixel value is less than or equal to the comparison image pixel value.
+    IMAQ_CLEAR_EQUAL                 = 2,           //The comparison is true if the source pixel value is equal to the comparison image pixel value.
+    IMAQ_CLEAR_GREATER_OR_EQUAL      = 3,           //The comparison is true if the source pixel value is greater than or equal to the comparison image pixel value.
+    IMAQ_CLEAR_GREATER               = 4,           //The comparison is true if the source pixel value is greater than the comparison image pixel value.
+    IMAQ_COMPARE_FUNCTION_SIZE_GUARD = 0xFFFFFFFF   
+} ComparisonFunction;
+
+typedef enum LineGaugeMethod_enum {
+    IMAQ_EDGE_TO_EDGE                 = 0,           //Measures from the first edge on the line to the last edge on the line.
+    IMAQ_EDGE_TO_POINT                = 1,           //Measures from the first edge on the line to the end point of the line.
+    IMAQ_POINT_TO_EDGE                = 2,           //Measures from the start point of the line to the first edge on the line.
+    IMAQ_POINT_TO_POINT               = 3,           //Measures from the start point of the line to the end point of the line.
+    IMAQ_LINE_GAUGE_METHOD_SIZE_GUARD = 0xFFFFFFFF   
+} LineGaugeMethod;
+
+typedef enum Direction3D_enum {
+    IMAQ_3D_NW                   = 0,           //The viewing angle for the 3D image is from the northwest.
+    IMAQ_3D_SW                   = 1,           //The viewing angle for the 3D image is from the southwest.
+    IMAQ_3D_SE                   = 2,           //The viewing angle for the 3D image is from the southeast.
+    IMAQ_3D_NE                   = 3,           //The viewing angle for the 3D image is from the northeast.
+    IMAQ_DIRECTION_3D_SIZE_GUARD = 0xFFFFFFFF   
+} Direction3D;
+
+typedef enum LearningMode_enum {
+    IMAQ_LEARN_ALL                  = 0,           //The function extracts information for shift- and rotation-invariant matching.
+    IMAQ_LEARN_SHIFT_INFORMATION    = 1,           //The function extracts information for shift-invariant matching.
+    IMAQ_LEARN_ROTATION_INFORMATION = 2,           //The function extracts information for rotation-invariant matching.
+    IMAQ_LEARNING_MODE_SIZE_GUARD   = 0xFFFFFFFF   
+} LearningMode;
+
+typedef enum KernelFamily_enum {
+    IMAQ_GRADIENT_FAMILY          = 0,           //The kernel is in the gradient family.
+    IMAQ_LAPLACIAN_FAMILY         = 1,           //The kernel is in the Laplacian family.
+    IMAQ_SMOOTHING_FAMILY         = 2,           //The kernel is in the smoothing family.
+    IMAQ_GAUSSIAN_FAMILY          = 3,           //The kernel is in the Gaussian family.
+    IMAQ_KERNEL_FAMILY_SIZE_GUARD = 0xFFFFFFFF   
+} KernelFamily;
+
+typedef enum InterpolationMethod_enum {
+    IMAQ_ZERO_ORDER                      = 0,           //The function uses an interpolation method that interpolates new pixel values using the nearest valid neighboring pixel.
+    IMAQ_BILINEAR                        = 1,           //The function uses an interpolation method that interpolates new pixel values using a bidirectional average of the neighboring pixels.
+    IMAQ_QUADRATIC                       = 2,           //The function uses an interpolation method that interpolates new pixel values using a quadratic approximating polynomial.
+    IMAQ_CUBIC_SPLINE                    = 3,           //The function uses an interpolation method that interpolates new pixel values by fitting them to a cubic spline curve, where the curve is based on known pixel values from the image.
+    IMAQ_BILINEAR_FIXED                  = 4,           //The function uses an interpolation method that interpolates new pixel values using a bidirectional average of the neighboring pixels.
+    IMAQ_INTERPOLATION_METHOD_SIZE_GUARD = 0xFFFFFFFF   
+} InterpolationMethod;
+
+typedef enum ImageType_enum {
+    IMAQ_IMAGE_U8              = 0,           //The image type is 8-bit unsigned integer grayscale.
+    IMAQ_IMAGE_U16             = 7,           //The image type is 16-bit unsigned integer grayscale.
+    IMAQ_IMAGE_I16             = 1,           //The image type is 16-bit signed integer grayscale.
+    IMAQ_IMAGE_SGL             = 2,           //The image type is 32-bit floating-point grayscale.
+    IMAQ_IMAGE_COMPLEX         = 3,           //The image type is complex.
+    IMAQ_IMAGE_RGB             = 4,           //The image type is RGB color.
+    IMAQ_IMAGE_HSL             = 5,           //The image type is HSL color.
+    IMAQ_IMAGE_RGB_U64         = 6,           //The image type is 64-bit unsigned RGB color.
+    IMAQ_IMAGE_TYPE_SIZE_GUARD = 0xFFFFFFFF   
+} ImageType;
+
+typedef enum ImageFeatureMode_enum {
+    IMAQ_COLOR_AND_SHAPE_FEATURES = 0,           //Instructs the function to use the color and the shape features of the color pattern.
+    IMAQ_COLOR_FEATURES           = 1,           //Instructs the function to use the color features of the color pattern.
+    IMAQ_SHAPE_FEATURES           = 2,           //Instructs the function to use the shape features of the color pattern.
+    IMAQ_FEATURE_MODE_SIZE_GUARD  = 0xFFFFFFFF   
+} ImageFeatureMode;
+
+typedef enum FontColor_enum {
+    IMAQ_WHITE                 = 0,           //Draws text in white.
+    IMAQ_BLACK                 = 1,           //Draws text in black.
+    IMAQ_INVERT                = 2,           //Inverts the text pixels.
+    IMAQ_BLACK_ON_WHITE        = 3,           //Draws text in black with a white background.
+    IMAQ_WHITE_ON_BLACK        = 4,           //Draws text in white with a black background.
+    IMAQ_FONT_COLOR_SIZE_GUARD = 0xFFFFFFFF   
+} FontColor;
+
+typedef enum FlipAxis_enum {
+    IMAQ_HORIZONTAL_AXIS      = 0,           //Flips the image over the central horizontal axis.
+    IMAQ_VERTICAL_AXIS        = 1,           //Flips the image over the central vertical axis.
+    IMAQ_CENTER_AXIS          = 2,           //Flips the image over both the central vertical and horizontal axes.
+    IMAQ_DIAG_L_TO_R_AXIS     = 3,           //Flips the image over an axis from the upper left corner to lower right corner.
+    IMAQ_DIAG_R_TO_L_AXIS     = 4,           //Flips the image over an axis from the upper right corner to lower left corner.
+    IMAQ_FLIP_AXIS_SIZE_GUARD = 0xFFFFFFFF   
+} FlipAxis;
+
+typedef enum EdgeProcess_enum {
+    IMAQ_FIRST                   = 0,           //The function looks for the first edge.
+    IMAQ_FIRST_AND_LAST          = 1,           //The function looks for the first and last edge.
+    IMAQ_ALL                     = 2,           //The function looks for all edges.
+    IMAQ_BEST                    = 3,           //The function looks for the best edge.
+    IMAQ_EDGE_PROCESS_SIZE_GUARD = 0xFFFFFFFF   
+} EdgeProcess;
+
+typedef enum DrawMode_enum {
+    IMAQ_DRAW_VALUE           = 0,           //Draws the boundary of the object with the specified pixel value.
+    IMAQ_DRAW_INVERT          = 2,           //Inverts the pixel values of the boundary of the object.
+    IMAQ_PAINT_VALUE          = 1,           //Fills the object with the given pixel value.
+    IMAQ_PAINT_INVERT         = 3,           //Inverts the pixel values of the object.
+    IMAQ_HIGHLIGHT_VALUE      = 4,           //The function fills the object by highlighting the enclosed pixels with the color of the object.
+    IMAQ_DRAW_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} DrawMode;
+
+typedef enum NearestNeighborMetric_enum {
+    IMAQ_METRIC_MAXIMUM                     = 0,           //The maximum metric.
+    IMAQ_METRIC_SUM                         = 1,           //The sum metric.
+    IMAQ_METRIC_EUCLIDEAN                   = 2,           //The Euclidean metric.
+    IMAQ_NEAREST_NEIGHBOR_METRIC_SIZE_GUARD = 0xFFFFFFFF   
+} NearestNeighborMetric;
+
+typedef enum ReadResolution_enum {
+    IMAQ_LOW_RESOLUTION             = 0,           //Configures NI Vision to use low resolution during the read process.
+    IMAQ_MEDIUM_RESOLUTION          = 1,           //Configures NI Vision to use medium resolution during the read process.
+    IMAQ_HIGH_RESOLUTION            = 2,           //Configures NI Vision to use high resolution during the read process.
+    IMAQ_READ_RESOLUTION_SIZE_GUARD = 0xFFFFFFFF   
+} ReadResolution;
+
+typedef enum ThresholdMode_enum {
+    IMAQ_FIXED_RANGE               = 0,           //Performs thresholding using the values you provide in the lowThreshold and highThreshold elements of OCRProcessingOptions.
+    IMAQ_COMPUTED_UNIFORM          = 1,           //Calculates a single threshold value for the entire ROI.
+    IMAQ_COMPUTED_LINEAR           = 2,           //Calculates a value on the left side of the ROI, calculates a value on the right side of the ROI, and linearly fills the middle values from left to right.
+    IMAQ_COMPUTED_NONLINEAR        = 3,           //Divides the ROI into the number of blocks specified by the blockCount element of OCRProcessingOptions and calculates a threshold value for each block.
+    IMAQ_THRESHOLD_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} ThresholdMode;
+
+typedef enum ReadStrategy_enum {
+    IMAQ_READ_AGGRESSIVE          = 0,           //Configures NI Vision to perform fewer checks when analyzing objects to determine if they match trained characters.
+    IMAQ_READ_CONSERVATIVE        = 1,           //Configures NI Vision to perform more checks to determine if an object matches a trained character.
+    IMAQ_READ_STRATEGY_SIZE_GUARD = 0xFFFFFFFF   
+} ReadStrategy;
+
+typedef enum MeasurementType_enum {
+    IMAQ_MT_CENTER_OF_MASS_X                    = 0,           //X-coordinate of the point representing the average position of the total particle mass, assuming every point in the particle has a constant density.
+    IMAQ_MT_CENTER_OF_MASS_Y                    = 1,           //Y-coordinate of the point representing the average position of the total particle mass, assuming every point in the particle has a constant density.
+    IMAQ_MT_FIRST_PIXEL_X                       = 2,           //X-coordinate of the highest, leftmost particle pixel.
+    IMAQ_MT_FIRST_PIXEL_Y                       = 3,           //Y-coordinate of the highest, leftmost particle pixel.
+    IMAQ_MT_BOUNDING_RECT_LEFT                  = 4,           //X-coordinate of the leftmost particle point.
+    IMAQ_MT_BOUNDING_RECT_TOP                   = 5,           //Y-coordinate of highest particle point.
+    IMAQ_MT_BOUNDING_RECT_RIGHT                 = 6,           //X-coordinate of the rightmost particle point.
+    IMAQ_MT_BOUNDING_RECT_BOTTOM                = 7,           //Y-coordinate of the lowest particle point.
+    IMAQ_MT_MAX_FERET_DIAMETER_START_X          = 8,           //X-coordinate of the start of the line segment connecting the two perimeter points that are the furthest apart.
+    IMAQ_MT_MAX_FERET_DIAMETER_START_Y          = 9,           //Y-coordinate of the start of the line segment connecting the two perimeter points that are the furthest apart.
+    IMAQ_MT_MAX_FERET_DIAMETER_END_X            = 10,          //X-coordinate of the end of the line segment connecting the two perimeter points that are the furthest apart.
+    IMAQ_MT_MAX_FERET_DIAMETER_END_Y            = 11,          //Y-coordinate of the end of the line segment connecting the two perimeter points that are the furthest apart.
+    IMAQ_MT_MAX_HORIZ_SEGMENT_LENGTH_LEFT       = 12,          //X-coordinate of the leftmost pixel in the longest row of contiguous pixels in the particle.
+    IMAQ_MT_MAX_HORIZ_SEGMENT_LENGTH_RIGHT      = 13,          //X-coordinate of the rightmost pixel in the longest row of contiguous pixels in the particle.
+    IMAQ_MT_MAX_HORIZ_SEGMENT_LENGTH_ROW        = 14,          //Y-coordinate of all of the pixels in the longest row of contiguous pixels in the particle.
+    IMAQ_MT_BOUNDING_RECT_WIDTH                 = 16,          //Distance between the x-coordinate of the leftmost particle point and the x-coordinate of the rightmost particle point.
+    IMAQ_MT_BOUNDING_RECT_HEIGHT                = 17,          //Distance between the y-coordinate of highest particle point and the y-coordinate of the lowest particle point.
+    IMAQ_MT_BOUNDING_RECT_DIAGONAL              = 18,          //Distance between opposite corners of the bounding rectangle.
+    IMAQ_MT_PERIMETER                           = 19,          //Length of the outer boundary of the particle.
+    IMAQ_MT_CONVEX_HULL_PERIMETER               = 20,          //Perimeter of the smallest convex polygon containing all points in the particle.
+    IMAQ_MT_HOLES_PERIMETER                     = 21,          //Sum of the perimeters of each hole in the particle.
+    IMAQ_MT_MAX_FERET_DIAMETER                  = 22,          //Distance between the start and end of the line segment connecting the two perimeter points that are the furthest apart.
+    IMAQ_MT_EQUIVALENT_ELLIPSE_MAJOR_AXIS       = 23,          //Length of the major axis of the ellipse with the same perimeter and area as the particle.
+    IMAQ_MT_EQUIVALENT_ELLIPSE_MINOR_AXIS       = 24,          //Length of the minor axis of the ellipse with the same perimeter and area as the particle.
+    IMAQ_MT_EQUIVALENT_ELLIPSE_MINOR_AXIS_FERET = 25,          //Length of the minor axis of the ellipse with the same area as the particle, and Major Axis equal in length to the Max Feret Diameter.
+    IMAQ_MT_EQUIVALENT_RECT_LONG_SIDE           = 26,          //Longest side of the rectangle with the same perimeter and area as the particle.
+    IMAQ_MT_EQUIVALENT_RECT_SHORT_SIDE          = 27,          //Shortest side of the rectangle with the same perimeter and area as the particle.
+    IMAQ_MT_EQUIVALENT_RECT_DIAGONAL            = 28,          //Distance between opposite corners of the rectangle with the same perimeter and area as the particle.
+    IMAQ_MT_EQUIVALENT_RECT_SHORT_SIDE_FERET    = 29,          //Shortest side of the rectangle with the same area as the particle, and longest side equal in length to the Max Feret Diameter.
+    IMAQ_MT_AVERAGE_HORIZ_SEGMENT_LENGTH        = 30,          //Average length of a horizontal segment in the particle.
+    IMAQ_MT_AVERAGE_VERT_SEGMENT_LENGTH         = 31,          //Average length of a vertical segment in the particle.
+    IMAQ_MT_HYDRAULIC_RADIUS                    = 32,          //The particle area divided by the particle perimeter.
+    IMAQ_MT_WADDEL_DISK_DIAMETER                = 33,          //Diameter of a disk with the same area as the particle.
+    IMAQ_MT_AREA                                = 35,          //Area of the particle.
+    IMAQ_MT_HOLES_AREA                          = 36,          //Sum of the areas of each hole in the particle.
+    IMAQ_MT_PARTICLE_AND_HOLES_AREA             = 37,          //Area of a particle that completely covers the image.
+    IMAQ_MT_CONVEX_HULL_AREA                    = 38,          //Area of the smallest convex polygon containing all points in the particle.
+    IMAQ_MT_IMAGE_AREA                          = 39,          //Area of the image.
+    IMAQ_MT_NUMBER_OF_HOLES                     = 41,          //Number of holes in the particle.
+    IMAQ_MT_NUMBER_OF_HORIZ_SEGMENTS            = 42,          //Number of horizontal segments in the particle.
+    IMAQ_MT_NUMBER_OF_VERT_SEGMENTS             = 43,          //Number of vertical segments in the particle.
+    IMAQ_MT_ORIENTATION                         = 45,          //The angle of the line that passes through the particle Center of Mass about which the particle has the lowest moment of inertia.
+    IMAQ_MT_MAX_FERET_DIAMETER_ORIENTATION      = 46,          //The angle of the line segment connecting the two perimeter points that are the furthest apart.
+    IMAQ_MT_AREA_BY_IMAGE_AREA                  = 48,          //Percentage of the particle Area covering the Image Area.
+    IMAQ_MT_AREA_BY_PARTICLE_AND_HOLES_AREA     = 49,          //Percentage of the particle Area in relation to its Particle and Holes Area.
+    IMAQ_MT_RATIO_OF_EQUIVALENT_ELLIPSE_AXES    = 50,          //Equivalent Ellipse Major Axis divided by Equivalent Ellipse Minor Axis.
+    IMAQ_MT_RATIO_OF_EQUIVALENT_RECT_SIDES      = 51,          //Equivalent Rect Long Side divided by Equivalent Rect Short Side.
+    IMAQ_MT_ELONGATION_FACTOR                   = 53,          //Max Feret Diameter divided by Equivalent Rect Short Side (Feret).
+    IMAQ_MT_COMPACTNESS_FACTOR                  = 54,          //Area divided by the product of Bounding Rect Width and Bounding Rect Height.
+    IMAQ_MT_HEYWOOD_CIRCULARITY_FACTOR          = 55,          //Perimeter divided by the circumference of a circle with the same area.
+    IMAQ_MT_TYPE_FACTOR                         = 56,          //Factor relating area to moment of inertia.
+    IMAQ_MT_SUM_X                               = 58,          //The sum of all x-coordinates in the particle.
+    IMAQ_MT_SUM_Y                               = 59,          //The sum of all y-coordinates in the particle.
+    IMAQ_MT_SUM_XX                              = 60,          //The sum of all x-coordinates squared in the particle.
+    IMAQ_MT_SUM_XY                              = 61,          //The sum of all x-coordinates times y-coordinates in the particle.
+    IMAQ_MT_SUM_YY                              = 62,          //The sum of all y-coordinates squared in the particle.
+    IMAQ_MT_SUM_XXX                             = 63,          //The sum of all x-coordinates cubed in the particle.
+    IMAQ_MT_SUM_XXY                             = 64,          //The sum of all x-coordinates squared times y-coordinates in the particle.
+    IMAQ_MT_SUM_XYY                             = 65,          //The sum of all x-coordinates times y-coordinates squared in the particle.
+    IMAQ_MT_SUM_YYY                             = 66,          //The sum of all y-coordinates cubed in the particle.
+    IMAQ_MT_MOMENT_OF_INERTIA_XX                = 68,          //The moment of inertia in the x-direction twice.
+    IMAQ_MT_MOMENT_OF_INERTIA_XY                = 69,          //The moment of inertia in the x and y directions.
+    IMAQ_MT_MOMENT_OF_INERTIA_YY                = 70,          //The moment of inertia in the y-direction twice.
+    IMAQ_MT_MOMENT_OF_INERTIA_XXX               = 71,          //The moment of inertia in the x-direction three times.
+    IMAQ_MT_MOMENT_OF_INERTIA_XXY               = 72,          //The moment of inertia in the x-direction twice and the y-direction once.
+    IMAQ_MT_MOMENT_OF_INERTIA_XYY               = 73,          //The moment of inertia in the x-direction once and the y-direction twice.
+    IMAQ_MT_MOMENT_OF_INERTIA_YYY               = 74,          //The moment of inertia in the y-direction three times.
+    IMAQ_MT_NORM_MOMENT_OF_INERTIA_XX           = 75,          //The normalized moment of inertia in the x-direction twice.
+    IMAQ_MT_NORM_MOMENT_OF_INERTIA_XY           = 76,          //The normalized moment of inertia in the x- and y-directions.
+    IMAQ_MT_NORM_MOMENT_OF_INERTIA_YY           = 77,          //The normalized moment of inertia in the y-direction twice.
+    IMAQ_MT_NORM_MOMENT_OF_INERTIA_XXX          = 78,          //The normalized moment of inertia in the x-direction three times.
+    IMAQ_MT_NORM_MOMENT_OF_INERTIA_XXY          = 79,          //The normalized moment of inertia in the x-direction twice and the y-direction once.
+    IMAQ_MT_NORM_MOMENT_OF_INERTIA_XYY          = 80,          //The normalized moment of inertia in the x-direction once and the y-direction twice.
+    IMAQ_MT_NORM_MOMENT_OF_INERTIA_YYY          = 81,          //The normalized moment of inertia in the y-direction three times.
+    IMAQ_MT_HU_MOMENT_1                         = 82,          //The first Hu moment.
+    IMAQ_MT_HU_MOMENT_2                         = 83,          //The second Hu moment.
+    IMAQ_MT_HU_MOMENT_3                         = 84,          //The third Hu moment.
+    IMAQ_MT_HU_MOMENT_4                         = 85,          //The fourth Hu moment.
+    IMAQ_MT_HU_MOMENT_5                         = 86,          //The fifth Hu moment.
+    IMAQ_MT_HU_MOMENT_6                         = 87,          //The sixth Hu moment.
+    IMAQ_MT_HU_MOMENT_7                         = 88,          //The seventh Hu moment.
+    IMAQ_MEASUREMENT_TYPE_SIZE_GUARD            = 0xFFFFFFFF   
+} MeasurementType;
+
+typedef enum GeometricMatchingMode_enum {
+    IMAQ_GEOMETRIC_MATCH_SHIFT_INVARIANT     = 0,           //Searches for occurrences of the pattern in the image, assuming that the pattern is not rotated more than plus or minus 5 degrees.
+    IMAQ_GEOMETRIC_MATCH_ROTATION_INVARIANT  = 1,           //Searches for occurrences of the pattern in the image with reduced restriction on the rotation of the pattern.
+    IMAQ_GEOMETRIC_MATCH_SCALE_INVARIANT     = 2,           //Searches for occurrences of the pattern in the image with reduced restriction on the size of the pattern.
+    IMAQ_GEOMETRIC_MATCH_OCCLUSION_INVARIANT = 4,           //Searches for occurrences of the pattern in the image, allowing for a specified percentage of the pattern to be occluded.
+    IMAQ_GEOMETRIC_MATCHING_MODE_SIZE_GUARD  = 0xFFFFFFFF   
+} GeometricMatchingMode;
+
+typedef enum ButtonLabel_enum {
+    IMAQ_BUTTON_OK               = 0,           //The label "OK".
+    IMAQ_BUTTON_SAVE             = 1,           //The label "Save".
+    IMAQ_BUTTON_SELECT           = 2,           //The label "Select".
+    IMAQ_BUTTON_LOAD             = 3,           //The label "Load".
+    IMAQ_BUTTON_LABEL_SIZE_GUARD = 0xFFFFFFFF   
+} ButtonLabel;
+
+typedef enum NearestNeighborMethod_enum {
+    IMAQ_MINIMUM_MEAN_DISTANCE              = 0,           //The minimum mean distance method.
+    IMAQ_K_NEAREST_NEIGHBOR                 = 1,           //The k-nearest neighbor method.
+    IMAQ_NEAREST_PROTOTYPE                  = 2,           //The nearest prototype method.
+    IMAQ_NEAREST_NEIGHBOR_METHOD_SIZE_GUARD = 0xFFFFFFFF   
+} NearestNeighborMethod;
+
+typedef enum QRMirrorMode_enum {
+    IMAQ_QR_MIRROR_MODE_AUTO_DETECT = -2,          //The function should determine if the QR code is mirrored.
+    IMAQ_QR_MIRROR_MODE_MIRRORED    = 1,           //The function should expect the QR code to appear mirrored.
+    IMAQ_QR_MIRROR_MODE_NORMAL      = 0,           //The function should expect the QR code to appear normal.
+    IMAQ_QR_MIRROR_MODE_SIZE_GUARD  = 0xFFFFFFFF   
+} QRMirrorMode;
+
+typedef enum ColumnProcessingMode_enum {
+    IMAQ_AVERAGE_COLUMNS                   = 0,           //Averages the data extracted for edge detection.
+    IMAQ_MEDIAN_COLUMNS                    = 1,           //Takes the median of the data extracted for edge detection.
+    IMAQ_COLUMN_PROCESSING_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} ColumnProcessingMode;
+
+typedef enum FindReferenceDirection_enum {
+    IMAQ_LEFT_TO_RIGHT_DIRECT          = 0,           //Searches from the left side of the search area to the right side of the search area for a direct axis.
+    IMAQ_LEFT_TO_RIGHT_INDIRECT        = 1,           //Searches from the left side of the search area to the right side of the search area for an indirect axis.
+    IMAQ_TOP_TO_BOTTOM_DIRECT          = 2,           //Searches from the top of the search area to the bottom of the search area for a direct axis.
+    IMAQ_TOP_TO_BOTTOM_INDIRECT        = 3,           //Searches from the top of the search area to the bottom of the search area for an indirect axis.
+    IMAQ_RIGHT_TO_LEFT_DIRECT          = 4,           //Searches from the right side of the search area to the left side of the search area for a direct axis.
+    IMAQ_RIGHT_TO_LEFT_INDIRECT        = 5,           //Searches from the right side of the search area to the left side of the search area for an indirect axis.
+    IMAQ_BOTTOM_TO_TOP_DIRECT          = 6,           //Searches from the bottom of the search area to the top of the search area for a direct axis.
+    IMAQ_BOTTOM_TO_TOP_INDIRECT        = 7,           //Searches from the bottom of the search area to the top of the search area for an indirect axis.
+    IMAQ_FIND_COORD_SYS_DIR_SIZE_GUARD = 0xFFFFFFFF   
+} FindReferenceDirection;
+
+typedef enum MulticoreOperation_enum {
+    IMAQ_GET_CORES                      = 0,           //The number of processor cores NI Vision is currently using.
+    IMAQ_SET_CORES                      = 1,           //The number of processor cores for NI Vision to use.
+    IMAQ_USE_MAX_AVAILABLE              = 2,           //Use the maximum number of available processor cores.
+    IMAQ_MULTICORE_OPERATION_SIZE_GUARD = 0xFFFFFFFF   
+} MulticoreOperation;
+
+typedef enum GroupBehavior_enum {
+    IMAQ_GROUP_CLEAR               = 0,           //Sets the behavior of the overlay group to clear the current settings when an image is transformed.
+    IMAQ_GROUP_KEEP                = 1,           //Sets the behavior of the overlay group to keep the current settings when an image is transformed.
+    IMAQ_GROUP_TRANSFORM           = 2,           //Sets the behavior of the overlay group to transform with the image.
+    IMAQ_GROUP_BEHAVIOR_SIZE_GUARD = 0xFFFFFFFF   
+} GroupBehavior;
+
+typedef enum QRDimensions_enum {
+    IMAQ_QR_DIMENSIONS_AUTO_DETECT = 0,           //The function will automatically determine the dimensions of the QR code.
+    IMAQ_QR_DIMENSIONS_11x11       = 11,          //Specifies the dimensions of the QR code as 11 x 11.
+    IMAQ_QR_DIMENSIONS_13x13       = 13,          //Specifies the dimensions of the QR code as 13 x 13.
+    IMAQ_QR_DIMENSIONS_15x15       = 15,          //Specifies the dimensions of the QR code as 15 x 15.
+    IMAQ_QR_DIMENSIONS_17x17       = 17,          //Specifies the dimensions of the QR code as 17 x 17.
+    IMAQ_QR_DIMENSIONS_21x21       = 21,          //Specifies the dimensions of the QR code as 21 x 21.
+    IMAQ_QR_DIMENSIONS_25x25       = 25,          //Specifies the dimensions of the QR code as 25 x 25.
+    IMAQ_QR_DIMENSIONS_29x29       = 29,          //Specifies the dimensions of the QR code as 29 x 29.
+    IMAQ_QR_DIMENSIONS_33x33       = 33,          //Specifies the dimensions of the QR code as 33 x 33.
+    IMAQ_QR_DIMENSIONS_37x37       = 37,          //Specifies the dimensions of the QR code as 37 x 37.
+    IMAQ_QR_DIMENSIONS_41x41       = 41,          //Specifies the dimensions of the QR code as 41 x 41.
+    IMAQ_QR_DIMENSIONS_45x45       = 45,          //Specifies the dimensions of the QR code as 45 x 45.
+    IMAQ_QR_DIMENSIONS_49x49       = 49,          //Specifies the dimensions of the QR code as 49 x 49.
+    IMAQ_QR_DIMENSIONS_53x53       = 53,          //Specifies the dimensions of the QR code as 53 x 53.
+    IMAQ_QR_DIMENSIONS_57x57       = 57,          //Specifies the dimensions of the QR code as 57 x 57.
+    IMAQ_QR_DIMENSIONS_61x61       = 61,          //Specifies the dimensions of the QR code as 61 x 61.
+    IMAQ_QR_DIMENSIONS_65x65       = 65,          //Specifies the dimensions of the QR code as 65 x 65.
+    IMAQ_QR_DIMENSIONS_69x69       = 69,          //Specifies the dimensions of the QR code as 69 x 69.
+    IMAQ_QR_DIMENSIONS_73x73       = 73,          //Specifies the dimensions of the QR code as 73 x 73.
+    IMAQ_QR_DIMENSIONS_77x77       = 77,          //Specifies the dimensions of the QR code as 77 x 77.
+    IMAQ_QR_DIMENSIONS_81x81       = 81,          //Specifies the dimensions of the QR code as 81 x 81.
+    IMAQ_QR_DIMENSIONS_85x85       = 85,          //Specifies the dimensions of the QR code as 85 x 85.
+    IMAQ_QR_DIMENSIONS_89x89       = 89,          //Specifies the dimensions of the QR code as 89 x 89.
+    IMAQ_QR_DIMENSIONS_93x93       = 93,          //Specifies the dimensions of the QR code as 93 x 93.
+    IMAQ_QR_DIMENSIONS_97x97       = 97,          //Specifies the dimensions of the QR code as 97 x 97.
+    IMAQ_QR_DIMENSIONS_101x101     = 101,         //Specifies the dimensions of the QR code as 101 x 101.
+    IMAQ_QR_DIMENSIONS_105x105     = 105,         //Specifies the dimensions of the QR code as 105 x 105.
+    IMAQ_QR_DIMENSIONS_109x109     = 109,         //Specifies the dimensions of the QR code as 109 x 109.
+    IMAQ_QR_DIMENSIONS_113x113     = 113,         //Specifies the dimensions of the QR code as 113 x 113.
+    IMAQ_QR_DIMENSIONS_117x117     = 117,         //Specifies the dimensions of the QR code as 117 x 117.
+    IMAQ_QR_DIMENSIONS_121x121     = 121,         //Specifies the dimensions of the QR code as 121 x 121.
+    IMAQ_QR_DIMENSIONS_125x125     = 125,         //Specifies the dimensions of the QR code as 125 x 125.
+    IMAQ_QR_DIMENSIONS_129x129     = 129,         //Specifies the dimensions of the QR code as 129 x 129.
+    IMAQ_QR_DIMENSIONS_133x133     = 133,         //Specifies the dimensions of the QR code as 133 x 133.
+    IMAQ_QR_DIMENSIONS_137x137     = 137,         //Specifies the dimensions of the QR code as 137 x 137.
+    IMAQ_QR_DIMENSIONS_141x141     = 141,         //Specifies the dimensions of the QR code as 141 x 141.
+    IMAQ_QR_DIMENSIONS_145x145     = 145,         //Specifies the dimensions of the QR code as 145 x 145.
+    IMAQ_QR_DIMENSIONS_149x149     = 149,         //Specifies the dimensions of the QR code as 149 x 149.
+    IMAQ_QR_DIMENSIONS_153x153     = 153,         //Specifies the dimensions of the QR code as 153 x 153.
+    IMAQ_QR_DIMENSIONS_157x157     = 157,         //Specifies the dimensions of the QR code as 157 x 1537.
+    IMAQ_QR_DIMENSIONS_161x161     = 161,         //Specifies the dimensions of the QR code as 161 x 161.
+    IMAQ_QR_DIMENSIONS_165x165     = 165,         //Specifies the dimensions of the QR code as 165 x 165.
+    IMAQ_QR_DIMENSIONS_169x169     = 169,         //Specifies the dimensions of the QR code as 169 x 169.
+    IMAQ_QR_DIMENSIONS_173x173     = 173,         //Specifies the dimensions of the QR code as 173 x 173.
+    IMAQ_QR_DIMENSIONS_177x177     = 177,         //Specifies the dimensions of the QR code as 177 x 177.
+    IMAQ_QR_DIMENSIONS_SIZE_GUARD  = 0xFFFFFFFF   
+} QRDimensions;
+
+typedef enum QRCellFilterMode_enum {
+    IMAQ_QR_CELL_FILTER_MODE_AUTO_DETECT       = -2,          //The function will try all filter modes and uses the one that decodes the QR code within the fewest iterations and utilizing the least amount of error correction.
+    IMAQ_QR_CELL_FILTER_MODE_AVERAGE           = 0,           //The function sets the pixel value for the cell to the average of the sampled pixels.
+    IMAQ_QR_CELL_FILTER_MODE_MEDIAN            = 1,           //The function sets the pixel value for the cell to the median of the sampled pixels.
+    IMAQ_QR_CELL_FILTER_MODE_CENTRAL_AVERAGE   = 2,           //The function sets the pixel value for the cell to the average of the pixels in the center of the cell sample.
+    IMAQ_QR_CELL_FILTER_MODE_HIGH_AVERAGE      = 3,           //The function sets the pixel value for the cell to the average value of the half of the sampled pixels with the highest pixel values.
+    IMAQ_QR_CELL_FILTER_MODE_LOW_AVERAGE       = 4,           //The function sets the pixel value for the cell to the average value of the half of the sampled pixels with the lowest pixel values.
+    IMAQ_QR_CELL_FILTER_MODE_VERY_HIGH_AVERAGE = 5,           //The function sets the pixel value for the cell to the average value of the ninth of the sampled pixels with the highest pixel values.
+    IMAQ_QR_CELL_FILTER_MODE_VERY_LOW_AVERAGE  = 6,           //The function sets the pixel value for the cell to the average value of the ninth of the sampled pixels with the lowest pixel values.
+    IMAQ_QR_CELL_FILTER_MODE_ALL               = 8,           //The function tries each filter mode, starting with IMAQ_QR_CELL_FILTER_MODE_AVERAGE and ending with IMAQ_QR_CELL_FILTER_MODE_VERY_LOW_AVERAGE, stopping once a filter mode decodes correctly.
+    IMAQ_QR_CELL_FILTER_MODE_SIZE_GUARD        = 0xFFFFFFFF   
+} QRCellFilterMode;
+
+typedef enum RoundingMode_enum {
+    IMAQ_ROUNDING_MODE_OPTIMIZE   = 0,           //Rounds the result of a division using the best available method.
+    IMAQ_ROUNDING_MODE_TRUNCATE   = 1,           //Truncates the result of a division.
+    IMAQ_ROUNDING_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} RoundingMode;
+
+typedef enum QRDemodulationMode_enum {
+    IMAQ_QR_DEMODULATION_MODE_AUTO_DETECT    = -2,          //The function will try each demodulation mode and use the one which decodes the QR code within the fewest iterations and utilizing the least amount of error correction.
+    IMAQ_QR_DEMODULATION_MODE_HISTOGRAM      = 0,           //The function uses a histogram of all of the QR cells to calculate a threshold.
+    IMAQ_QR_DEMODULATION_MODE_LOCAL_CONTRAST = 1,           //The function examines each of the cell's neighbors to determine if the cell is on or off.
+    IMAQ_QR_DEMODULATION_MODE_COMBINED       = 2,           //The function uses the histogram of the QR code to calculate a threshold.
+    IMAQ_QR_DEMODULATION_MODE_ALL            = 3,           //The function tries IMAQ_QR_DEMODULATION_MODE_HISTOGRAM, then IMAQ_QR_DEMODULATION_MODE_LOCAL_CONTRAST and then IMAQ_QR_DEMODULATION_MODE_COMBINED, stopping once one mode is successful.
+    IMAQ_QR_DEMODULATION_MODE_SIZE_GUARD     = 0xFFFFFFFF   
+} QRDemodulationMode;
+
+typedef enum ContrastMode_enum {
+    IMAQ_ORIGINAL_CONTRAST = 0,  //Instructs the geometric matching algorithm to find matches with the same contrast as the template.
+    IMAQ_REVERSED_CONTRAST = 1,  //Instructs the geometric matching algorithm to find matches with the inverted contrast of the template.
+    IMAQ_BOTH_CONTRASTS    = 2,  //Instructs the geometric matching algorithm to find matches with the same and inverted contrast of the template.
+} ContrastMode;
+
+typedef enum QRPolarities_enum {
+    IMAQ_QR_POLARITY_AUTO_DETECT     = -2,          //The function should determine the polarity of the QR code.
+    IMAQ_QR_POLARITY_BLACK_ON_WHITE  = 0,           //The function should search for a QR code with dark data on a bright background.
+    IMAQ_QR_POLARITY_WHITE_ON_BLACK  = 1,           //The function should search for a QR code with bright data on a dark background.
+    IMAQ_QR_POLARITY_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} QRPolarities;
+
+typedef enum QRRotationMode_enum {
+    IMAQ_QR_ROTATION_MODE_UNLIMITED   = 0,           //The function allows for unlimited rotation.
+    IMAQ_QR_ROTATION_MODE_0_DEGREES   = 1,           //The function allows for ??? 5 degrees of rotation.
+    IMAQ_QR_ROTATION_MODE_90_DEGREES  = 2,           //The function allows for between 85 and 95 degrees of rotation.
+    IMAQ_QR_ROTATION_MODE_180_DEGREES = 3,           //The function allows for between 175 and 185 degrees of rotation.
+    IMAQ_QR_ROTATION_MODE_270_DEGREES = 4,           //The function allows for between 265 and 275 degrees of rotation.
+    IMAQ_QR_ROTATION_MODE_SIZE_GUARD  = 0xFFFFFFFF   
+} QRRotationMode;
+
+typedef enum QRGradingMode_enum {
+    IMAQ_QR_NO_GRADING              = 0,           //The function does not make any preparatory calculations.
+    IMAQ_QR_GRADING_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} QRGradingMode;
+
+typedef enum StraightEdgeSearchMode_enum {
+    IMAQ_USE_FIRST_RAKE_EDGES            = 0,           //Fits a straight edge on the first points detected using a rake.
+    IMAQ_USE_BEST_RAKE_EDGES             = 1,           //Fits a straight edge on the best points detected using a rake.
+    IMAQ_USE_BEST_HOUGH_LINE             = 2,           //Finds the strongest straight edge using all points detected on a rake.
+    IMAQ_USE_FIRST_PROJECTION_EDGE       = 3,           //Uses the location of the first projected edge as the straight edge.
+    IMAQ_USE_BEST_PROJECTION_EDGE        = 4,           //Finds the strongest projected edge location to determine the straight edge.
+    IMAQ_STRAIGHT_EDGE_SEARCH_SIZE_GUARD = 0xFFFFFFFF   
+} StraightEdgeSearchMode;
+
+typedef enum SearchDirection_enum {
+    IMAQ_SEARCH_DIRECTION_LEFT_TO_RIGHT = 0,           //Searches from the left side of the search area to the right side of the search area.
+    IMAQ_SEARCH_DIRECTION_RIGHT_TO_LEFT = 1,           //Searches from the right side of the search area to the left side of the search area.
+    IMAQ_SEARCH_DIRECTION_TOP_TO_BOTTOM = 2,           //Searches from the top side of the search area to the bottom side of the search area.
+    IMAQ_SEARCH_DIRECTION_BOTTOM_TO_TOP = 3,           //Searches from the bottom side of the search area to the top side of the search area.
+    IMAQ_SEARCH_DIRECTION_SIZE_GUARD    = 0xFFFFFFFF   
+} SearchDirection;
+
+typedef enum QRStreamMode_enum {
+    IMAQ_QR_MODE_NUMERIC      = 0,           //Specifies that the data was encoded using numeric mode.
+    IMAQ_QR_MODE_ALPHANUMERIC = 1,           //Specifies that the data was encoded using alpha-numeric mode.
+    IMAQ_QR_MODE_RAW_BYTE     = 2,           //Specifies that the data was not encoded but is only raw binary bytes, or encoded in JIS-8.
+    IMAQ_QR_MODE_EAN128_TOKEN = 3,           //Specifies that the data has a special meaning represented by the application ID.
+    IMAQ_QR_MODE_EAN128_DATA  = 4,           //Specifies that the data has a special meaning represented by the application ID.
+    IMAQ_QR_MODE_ECI          = 5,           //Specifies that the data was meant to be read using the language represented in the language ID.
+    IMAQ_QR_MODE_KANJI        = 6,           //Specifies that the data was encoded in Shift-JIS16 Japanese.
+    IMAQ_QR_MODE_SIZE_GUARD   = 0xFFFFFFFF   
+} QRStreamMode;
+
+typedef enum ParticleClassifierType_enum {
+    IMAQ_PARTICLE_LARGEST                    = 0,           //Use only the largest particle in the image.
+    IMAQ_PARTICLE_ALL                        = 1,           //Use all particles in the image.
+    IMAQ_PARTICLE_CLASSIFIER_TYPE_SIZE_GUARD = 0xFFFFFFFF   
+} ParticleClassifierType;
+
+typedef enum QRCellSampleSize_enum {
+    IMAQ_QR_CELL_SAMPLE_SIZE_AUTO_DETECT = -2,          //The function will try each sample size and use the one which decodes the QR code within the fewest iterations and utilizing the least amount of error correction.
+    IMAQ_QR_CELL_SAMPLE_SIZE1X1          = 1,           //The function will use a 1x1 sized sample from each cell.
+    IMAQ_QR_CELL_SAMPLE_SIZE2X2          = 2,           //The function will use a 2x2 sized sample from each cell.
+    IMAQ_QR_CELL_SAMPLE_SIZE3X3          = 3,           //The function will use a 3x3 sized sample from each cell.
+    IMAQ_QR_CELL_SAMPLE_SIZE4X4          = 4,           //The function will use a 4x4 sized sample from each cell.
+    IMAQ_QR_CELL_SAMPLE_SIZE5X5          = 5,           //The function will use a 5x5 sized sample from each cell.
+    IMAQ_QR_CELL_SAMPLE_SIZE6X6          = 6,           //The function will use a 6x6 sized sample from each cell.
+    IMAQ_QR_CELL_SAMPLE_SIZE7X7          = 7,           //The function will use a 7x7 sized sample from each cell.
+    IMAQ_QR_CELL_SAMPLE_TYPE_SIZE_GUARD  = 0xFFFFFFFF   
+} QRCellSampleSize;
+
+typedef enum RakeProcessType_enum {
+    IMAQ_GET_FIRST_EDGES              = 0,           
+    IMAQ_GET_FIRST_AND_LAST_EDGES     = 1,           
+    IMAQ_GET_ALL_EDGES                = 2,           
+    IMAQ_GET_BEST_EDGES               = 3,           
+    IMAQ_RAKE_PROCESS_TYPE_SIZE_GUARD = 0xFFFFFFFF   
+} RakeProcessType;
+
+typedef enum GeometricSetupDataItem_enum {
+    IMAQ_CURVE_EXTRACTION_MODE             = 0,   //Specifies how the function identifies curves in the image.
+    IMAQ_CURVE_EDGE_THRSHOLD               = 1,   //Specifies the minimum contrast an edge pixel must have for it to be considered part of a curve.
+    IMAQ_CURVE_EDGE_FILTER                 = 2,   //Specifies the width of the edge filter that the function uses to identify curves in the image.
+    IMAQ_MINIMUM_CURVE_LENGTH              = 3,   //Specifies the length, in pixels, of the smallest curve that you want the function to identify.
+    IMAQ_CURVE_ROW_SEARCH_STEP_SIZE        = 4,   //Specifies the distance, in the y direction, between the image rows that the algorithm inspects for curve seed points.
+    IMAQ_CURVE_COL_SEARCH_STEP_SIZE        = 5,   //Specifies the distance, in the x direction, between the image columns that the algorithm inspects for curve seed points.
+    IMAQ_CURVE_MAX_END_POINT_GAP           = 6,   //Specifies the maximum gap, in pixels, between the endpoints of a curve that the function identifies as a closed curve.
+    IMAQ_EXTRACT_CLOSED_CURVES             = 7,   //Specifies whether to identify only closed curves in the image.
+    IMAQ_ENABLE_SUBPIXEL_CURVE_EXTRACTION  = 8,   //The function ignores this option.
+    IMAQ_ENABLE_CORRELATION_SCORE          = 9,   //Specifies that the function should calculate the Correlation Score and return it for each match result.
+    IMAQ_ENABLE_SUBPIXEL_ACCURACY          = 10,  //Determines whether to return the match results with subpixel accuracy.
+    IMAQ_SUBPIXEL_ITERATIONS               = 11,  //Specifies the maximum number of incremental improvements used to refine matches using subpixel information.
+    IMAQ_SUBPIXEL_TOLERANCE                = 12,  //Specifies the maximum amount of change, in pixels, between consecutive incremental improvements in the match position before the function stops refining the match position.
+    IMAQ_INITIAL_MATCH_LIST_LENGTH         = 13,  //Specifies the maximum size of the match list.
+    IMAQ_ENABLE_TARGET_TEMPLATE_CURVESCORE = 14,  //Specifies whether the function should calculate the match curve to template curve score and return it for each match result.
+    IMAQ_MINIMUM_MATCH_SEPARATION_DISTANCE = 15,  //Specifies the minimum separation distance, in pixels, between the origins of two matches that have unique positions.
+    IMAQ_MINIMUM_MATCH_SEPARATION_ANGLE    = 16,  //Specifies the minimum angular difference, in degrees, between two matches that have unique angles.
+    IMAQ_MINIMUM_MATCH_SEPARATION_SCALE    = 17,  //Specifies the minimum difference in scale, expressed as a percentage, between two matches that have unique scales.
+    IMAQ_MAXIMUM_MATCH_OVERLAP             = 18,  //Specifies whether you want the algorithm to spend less time accurately estimating the location of a match.
+    IMAQ_ENABLE_COARSE_RESULT              = 19,  //Specifies whether you want the algorithm to spend less time accurately estimating the location of a match.
+    IMAQ_ENABLE_CALIBRATION_SUPPORT        = 20,  //Specifies whether or not the algorithm treat the inspection image as a calibrated image.
+    IMAQ_ENABLE_CONTRAST_REVERSAL          = 21,  //Specifies the contrast of the matches to search for.
+    IMAQ_SEARCH_STRATEGY                   = 22,  //Specifies the aggressiveness of the strategy used to find matches in the image.
+    IMAQ_REFINEMENT_MATCH_FACTOR           = 23,  //Specifies the factor applied to the number of matches requested to determine how many matches are refined in the pyramid stage.
+    IMAQ_SUBPIXEL_MATCH_FACTOR             = 24,  //Specifies the factor applied to the number for matches requested to determine how many matches are used for the final (subpixel) stage.
+    IMAQ_MAX_REFINEMENT_ITERATIONS         = 25,  //Specifies maximum refinement iteration.
+} GeometricSetupDataItem;
+
+typedef enum DistortionModel_enum {
+    IMAQ_POLYNOMIAL_MODEL    = 0,   //Polynomial model.
+    IMAQ_DIVISION_MODEL      = 1,   //Division Model.
+    IMAQ_NO_DISTORTION_MODEL = -1,  //Not a distortion model.
+} DistortionModel;
+
+typedef enum CalibrationThumbnailType_enum {
+    IMAQ_CAMARA_MODEL_TYPE                     = 0,           //Camara model thumbnail type.
+    IMAQ_PERSPECTIVE_TYPE                      = 1,           //Perspective thumbnail type.
+    IMAQ_MICRO_PLANE_TYPE                      = 2,           //Micro Plane thumbnail type.
+    IMAQ_CALIBRATION_THUMBNAIL_TYPE_SIZE_GUARD = 0xFFFFFFFF   
+} CalibrationThumbnailType;
+
+typedef enum SettingType_enum {
+    IMAQ_ROTATION_ANGLE_RANGE    = 0,           //Set a range for this option to specify the angles at which you expect the Function to find template matches in the inspection image.
+    IMAQ_SCALE_RANGE             = 1,           //Set a range for this option to specify the sizes at which you expect the Function to find template matches in the inspection image.
+    IMAQ_OCCLUSION_RANGE         = 2,           //Set a range for this option to specify the amount of occlusion you expect for a match in the inspection image.
+    IMAQ_SETTING_TYPE_SIZE_GUARD = 0xFFFFFFFF   
+} SettingType;
+
+typedef enum SegmentationDistanceLevel_enum {
+    IMAQ_SEGMENTATION_LEVEL_CONSERVATIVE = 0,           //Uses extensive criteria to determine the Maximum Distance.
+    IMAQ_SEGMENTATION_LEVEL_AGGRESSIVE   = 1,           //Uses few criteria to determine the Maximum Distance.
+    IMAQ_SEGMENTATION_LEVEL_SIZE_GUARD   = 0xFFFFFFFF   
+} SegmentationDistanceLevel;
+
+typedef enum ExtractContourSelection_enum {
+    IMAQ_CLOSEST                              = 0,           //Selects the curve closest to the ROI.
+    IMAQ_LONGEST                              = 1,           //Selects the longest curve.
+    IMAQ_STRONGEST                            = 2,           //Selects the curve with the highest edge strength averaged from each point on the curve.
+    IMAQ_EXTRACT_CONTOUR_SELECTION_SIZE_GUARD = 0xFFFFFFFF   
+} ExtractContourSelection;
+
+typedef enum FindTransformMode_enum {
+    IMAQ_FIND_REFERENCE                 = 0,           //Update both parts of the coordinate system.
+    IMAQ_UPDATE_TRANSFORM               = 1,           //Update only the new reference system.
+    IMAQ_FIND_TRANSFORM_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} FindTransformMode;
+
+typedef enum ExtractContourDirection_enum {
+    IMAQ_RECT_LEFT_RIGHT                      = 0,           //Searches the ROI from left to right.
+    IMAQ_RECT_RIGHT_LEFT                      = 1,           //Searches the ROI from right to left.
+    IMAQ_RECT_TOP_BOTTOM                      = 2,           //Searches the ROI from top to bottom.
+    IMAQ_RECT_BOTTOM_TOP                      = 3,           //Searches the ROI from bottom to top.
+    IMAQ_ANNULUS_INNER_OUTER                  = 4,           //Searches the ROI from the inner radius to the outer radius.
+    IMAQ_ANNULUS_OUTER_INNER                  = 5,           //Searches the ROI from the outer radius to the inner radius.
+    IMAQ_ANNULUS_START_STOP                   = 6,           //Searches the ROI from start angle to end angle.
+    IMAQ_ANNULUS_STOP_START                   = 7,           //Searches the ROI from end angle to start angle.
+    IMAQ_EXTRACT_CONTOUR_DIRECTION_SIZE_GUARD = 0xFFFFFFFF   
+} ExtractContourDirection;
+
+typedef enum EdgePolaritySearchMode_enum {
+    IMAQ_SEARCH_FOR_ALL_EDGES          = 0,           //Searches for all edges.
+    IMAQ_SEARCH_FOR_RISING_EDGES       = 1,           //Searches for rising edges only.
+    IMAQ_SEARCH_FOR_FALLING_EDGES      = 2,           //Searches for falling edges only.
+    IMAQ_EDGE_POLARITY_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} EdgePolaritySearchMode;
+
+typedef enum Connectivity_enum {
+    IMAQ_FOUR_CONNECTED          = 0,           //Morphological reconstruction is performed in connectivity mode 4.
+    IMAQ_EIGHT_CONNECTED         = 1,           //Morphological reconstruction is performed in connectivity mode 8.
+    IMAQ_CONNECTIVITY_SIZE_GUARD = 0xFFFFFFFF   
+} Connectivity;
+
+typedef enum MorphologyReconstructOperation_enum {
+    IMAQ_DILATE_RECONSTRUCT                          = 0,           //Performs Reconstruction by dilation.
+    IMAQ_ERODE_RECONSTRUCT                           = 1,           //Performs Reconstruction by erosion.
+    IMAQ_MORPHOLOGY_RECONSTRUCT_OPERATION_SIZE_GUARD = 0xFFFFFFFF   
+} MorphologyReconstructOperation;
+
+typedef enum WaveletType_enum {
+    IMAQ_DB02                 = 0,           
+    IMAQ_DB03                 = 1,           
+    IMAQ_DB04                 = 2,           //Specifies the Wavelet Type as DB02.
+    IMAQ_DB05                 = 3,           
+    IMAQ_DB06                 = 4,           
+    IMAQ_DB07                 = 5,           
+    IMAQ_DB08                 = 6,           
+    IMAQ_DB09                 = 7,           
+    IMAQ_DB10                 = 8,           
+    IMAQ_DB11                 = 9,           
+    IMAQ_DB12                 = 10,          
+    IMAQ_DB13                 = 11,          
+    IMAQ_DB14                 = 12,          
+    IMAQ_HAAR                 = 13,          
+    IMAQ_BIOR1_3              = 14,          
+    IMAQ_BIOR1_5              = 15,          
+    IMAQ_BIOR2_2              = 16,          
+    IMAQ_BIOR2_4              = 17,          
+    IMAQ_BIOR2_6              = 18,          
+    IMAQ_BIOR2_8              = 19,          
+    IMAQ_BIOR3_1              = 20,          
+    IMAQ_BIOR3_3              = 21,          
+    IMAQ_BIOR3_5              = 22,          
+    IMAQ_BIOR3_7              = 23,          
+    IMAQ_BIOR3_9              = 24,          
+    IMAQ_BIOR4_4              = 25,          
+    IMAQ_COIF1                = 26,          
+    IMAQ_COIF2                = 27,          
+    IMAQ_COIF3                = 28,          
+    IMAQ_COIF4                = 29,          
+    IMAQ_COIF5                = 30,          
+    IMAQ_SYM2                 = 31,          
+    IMAQ_SYM3                 = 32,          
+    IMAQ_SYM4                 = 33,          
+    IMAQ_SYM5                 = 34,          
+    IMAQ_SYM6                 = 35,          
+    IMAQ_SYM7                 = 36,          
+    IMAQ_SYM8                 = 37,          
+    IMAQ_BIOR5_5              = 38,          
+    IMAQ_BIOR6_8              = 39,          
+    IMAQ_WAVE_TYPE_SIZE_GUARD = 0xFFFFFFFF   
+} WaveletType;
+
+typedef enum ParticleClassifierThresholdType_enum {
+    IMAQ_THRESHOLD_MANUAL = 0,  //The classifier performs a manual threshold on the image during preprocessing.
+    IMAQ_THRESHOLD_AUTO   = 1,  //The classifier performs an auto threshold on the image during preprocessing.
+    IMAQ_THRESHOLD_LOCAL  = 2,  //The classifier performs a local threshold on the image during preprocessing.
+} ParticleClassifierThresholdType;
+
+typedef enum MeasureParticlesCalibrationMode_enum {
+    IMAQ_CALIBRATION_MODE_PIXEL                        = 0,           //The function takes only pixel measurements on the particles in the image.
+    IMAQ_CALIBRATION_MODE_CALIBRATED                   = 1,           //The function takes only calibrated measurements on the particles in the image.
+    IMAQ_CALIBRATION_MODE_BOTH                         = 2,           //The function takes both pixel and calibrated measurements on the particles in the image.
+    IMAQ_MEASURE_PARTICLES_CALIBRATION_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} MeasureParticlesCalibrationMode;
+
+typedef enum GeometricMatchingSearchStrategy_enum {
+    IMAQ_GEOMETRIC_MATCHING_CONSERVATIVE               = 0,           //Instructs the pattern matching algorithm to use the largest possible amount of information from the image at the expense of slowing down the speed of the algorithm.
+    IMAQ_GEOMETRIC_MATCHING_BALANCED                   = 1,           //Instructs the pattern matching algorithm to balance the amount of information from the image it uses with the speed of the algorithm.
+    IMAQ_GEOMETRIC_MATCHING_AGGRESSIVE                 = 2,           //Instructs the pattern matching algorithm to use a lower amount of information from the image, which allows the algorithm to run quickly but at the expense of accuracy.
+    IMAQ_GEOMETRIC_MATCHING_SEARCH_STRATEGY_SIZE_GUARD = 0xFFFFFFFF   
+} GeometricMatchingSearchStrategy;
+
+typedef enum ColorClassificationResolution_enum {
+    IMAQ_CLASSIFIER_LOW_RESOLUTION        = 0,           //Low resolution version of the color classifier.
+    IMAQ_CLASSIFIER_MEDIUM_RESOLUTION     = 1,           //Medium resolution version of the color classifier.
+    IMAQ_CLASSIFIER_HIGH_RESOLUTION       = 2,           //High resolution version of the color classifier.
+    IMAQ_CLASSIFIER_RESOLUTION_SIZE_GUARD = 0xFFFFFFFF   
+} ColorClassificationResolution;
+
+typedef enum ConnectionConstraintType_enum {
+    IMAQ_DISTANCE_CONSTRAINT              = 0,           //Specifies the distance, in pixels, within which the end points of two curves must lie in order to be considered part of a contour.
+    IMAQ_ANGLE_CONSTRAINT                 = 1,           //Specifies the range, in degrees, within which the difference between the angle of two curves, measured at the end points, must lie in order for the two curves to be considered part of a contour.
+    IMAQ_CONNECTIVITY_CONSTRAINT          = 2,           //Specifies the distance, in pixels, within which a line extended from the end point of a curve must pass the end point of another curve in order for the two curves to be considered part of a contour.
+    IMAQ_GRADIENT_CONSTRAINT              = 3,           //Specifies the range, in degrees, within which the gradient angles of two curves, measured at the end points, must lie in order for the two curves to be considered part of a contour.
+    IMAQ_NUM_CONNECTION_CONSTRAINT_TYPES  = 4,           //.
+    IMAQ_CONNECTION_CONSTRAINT_SIZE_GUARD = 0xFFFFFFFF   
+} ConnectionConstraintType;
+
+typedef enum Barcode2DContrast_enum {
+    IMAQ_ALL_BARCODE_2D_CONTRASTS       = 0,           //The function searches for barcodes of each contrast type.
+    IMAQ_BLACK_ON_WHITE_BARCODE_2D      = 1,           //The function searches for 2D barcodes containing black data on a white background.
+    IMAQ_WHITE_ON_BLACK_BARCODE_2D      = 2,           //The function searches for 2D barcodes containing white data on a black background.
+    IMAQ_BARCODE_2D_CONTRAST_SIZE_GUARD = 0xFFFFFFFF   
+} Barcode2DContrast;
+
+typedef enum QRModelType_enum {
+    IMAQ_QR_MODELTYPE_AUTO_DETECT = 0,           //Specifies that the function will auto-detect the type of QR code.
+    IMAQ_QR_MODELTYPE_MICRO       = 1,           //Specifies the QR code is of a micro type.
+    IMAQ_QR_MODELTYPE_MODEL1      = 2,           //Specifies the QR code is of a model1 type.
+    IMAQ_QR_MODELTYPE_MODEL2      = 3,           //Specifies the QR code is of a model2 type.
+    IMAQ_QR_MODEL_TYPE_SIZE_GUARD = 0xFFFFFFFF   
+} QRModelType;
+
+typedef enum WindowBackgroundFillStyle_enum {
+    IMAQ_FILL_STYLE_SOLID      = 0,           //Fill the display window with a solid color.
+    IMAQ_FILL_STYLE_HATCH      = 2,           //Fill the display window with a pattern defined by WindowBackgroundHatchStyle.
+    IMAQ_FILL_STYLE_DEFAULT    = 3,           //Fill the display window with the NI Vision default pattern.
+    IMAQ_FILL_STYLE_SIZE_GUARD = 0xFFFFFFFF   
+} WindowBackgroundFillStyle;
+
+typedef enum ExtractionMode_enum {
+    IMAQ_NORMAL_IMAGE               = 0,           //Specifies that the function makes no assumptions about the uniformity of objects in the image or the image background.
+    IMAQ_UNIFORM_REGIONS            = 1,           //Specifies that the function assumes that either the objects in the image or the image background consists of uniform pixel values.
+    IMAQ_EXTRACTION_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} ExtractionMode;
+
+typedef enum EdgeFilterSize_enum {
+    IMAQ_FINE                        = 0,           //Specifies that the function uses a fine (narrow) edge filter.
+    IMAQ_NORMAL                      = 1,           //Specifies that the function uses a normal edge filter.
+    IMAQ_CONTOUR_TRACING             = 2,           //Sets the Edge Filter Size to contour tracing, which provides the best results for contour extraction but increases the time required to process the image.
+    IMAQ_EDGE_FILTER_SIZE_SIZE_GUARD = 0xFFFFFFFF   
+} EdgeFilterSize;
+
+typedef enum Barcode2DSearchMode_enum {
+    IMAQ_SEARCH_MULTIPLE                   = 0,           //The function searches for multiple 2D barcodes.
+    IMAQ_SEARCH_SINGLE_CONSERVATIVE        = 1,           //The function searches for 2D barcodes using the same searching algorithm as IMAQ_SEARCH_MULTIPLE but stops searching after locating one valid barcode.
+    IMAQ_SEARCH_SINGLE_AGGRESSIVE          = 2,           //The function searches for a single 2D barcode using a method that assumes the barcode occupies a majority of the search region.
+    IMAQ_BARCODE_2D_SEARCH_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} Barcode2DSearchMode;
+
+typedef enum DataMatrixSubtype_enum {
+    IMAQ_ALL_DATA_MATRIX_SUBTYPES             = 0,           //The function searches for Data Matrix barcodes of all subtypes.
+    IMAQ_DATA_MATRIX_SUBTYPES_ECC_000_ECC_140 = 1,           //The function searches for Data Matrix barcodes of subtypes ECC 000, ECC 050, ECC 080, ECC 100 and ECC 140.
+    IMAQ_DATA_MATRIX_SUBTYPE_ECC_200          = 2,           //The function searches for Data Matrix ECC 200 barcodes.
+    IMAQ_DATA_MATRIX_SUBTYPE_SIZE_GUARD       = 0xFFFFFFFF   
+} DataMatrixSubtype;
+
+typedef enum FeatureType_enum {
+    IMAQ_NOT_FOUND_FEATURE                   = 0,           //Specifies the feature is not found.
+    IMAQ_CIRCLE_FEATURE                      = 1,           //Specifies the feature is a circle.
+    IMAQ_ELLIPSE_FEATURE                     = 2,           //Specifies the feature is an ellipse.
+    IMAQ_CONST_CURVE_FEATURE                 = 3,           //Specifies the features is a constant curve.
+    IMAQ_RECTANGLE_FEATURE                   = 4,           //Specifies the feature is a rectangle.
+    IMAQ_LEG_FEATURE                         = 5,           //Specifies the feature is a leg.
+    IMAQ_CORNER_FEATURE                      = 6,           //Specifies the feature is a corner.
+    IMAQ_PARALLEL_LINE_PAIR_FEATURE          = 7,           //Specifies the feature is a parallel line pair.
+    IMAQ_PAIR_OF_PARALLEL_LINE_PAIRS_FEATURE = 8,           //Specifies the feature is a pair of parallel line pairs.
+    IMAQ_LINE_FEATURE                        = 9,           //Specifies the feature is a line.
+    IMAQ_CLOSED_CURVE_FEATURE                = 10,          //Specifies the feature is a closed curve.
+    IMAQ_FEATURE_TYPE_SIZE_GUARD             = 0xFFFFFFFF   
+} FeatureType;
+
+typedef enum Barcode2DCellShape_enum {
+    IMAQ_SQUARE_CELLS                     = 0,           //The function uses an algorithm for decoding the 2D barcode that works with square data cells.
+    IMAQ_ROUND_CELLS                      = 1,           //The function uses an algorithm for decoding the 2D barcode that works with round data cells.
+    IMAQ_BARCODE_2D_CELL_SHAPE_SIZE_GUARD = 0xFFFFFFFF   
+} Barcode2DCellShape;
+
+typedef enum LocalThresholdMethod_enum {
+    IMAQ_NIBLACK                           = 0,           //The function computes thresholds for each pixel based on its local statistics using the Niblack local thresholding algorithm.
+    IMAQ_BACKGROUND_CORRECTION             = 1,           //The function performs background correction first to eliminate non-uniform lighting effects, then performs thresholding using the Otsu thresholding algorithm.
+    IMAQ_LOCAL_THRESHOLD_METHOD_SIZE_GUARD = 0xFFFFFFFF   
+} LocalThresholdMethod;
+
+typedef enum Barcode2DType_enum {
+    IMAQ_PDF417                     = 0,           //The 2D barcode is of type PDF417.
+    IMAQ_DATA_MATRIX_ECC_000        = 1,           //The 2D barcode is of type Data Matrix ECC 000.
+    IMAQ_DATA_MATRIX_ECC_050        = 2,           //The 2D barcode is of type Data Matrix ECC 050.
+    IMAQ_DATA_MATRIX_ECC_080        = 3,           //The 2D barcode is of type Data Matrix ECC 080.
+    IMAQ_DATA_MATRIX_ECC_100        = 4,           //The 2D barcode is of type Data Matrix ECC 100.
+    IMAQ_DATA_MATRIX_ECC_140        = 5,           //The 2D barcode is of type Data Matrix ECC 140.
+    IMAQ_DATA_MATRIX_ECC_200        = 6,           //The 2D barcode is of type Data Matrix ECC 200.
+    IMAQ_BARCODE_2D_TYPE_SIZE_GUARD = 0xFFFFFFFF   
+} Barcode2DType;
+
+typedef enum ClassifierEngineType_enum {
+    IMAQ_ENGINE_NONE                       = 0,           //No engine has been set on this classifier session.
+    IMAQ_ENGINE_NEAREST_NEIGHBOR           = 1,           //Nearest neighbor engine.
+    IMAQ_ENGINE_SUPPORT_VECTOR_MACHINE     = 2,           
+    IMAQ_CLASSIFIER_ENGINE_TYPE_SIZE_GUARD = 0xFFFFFFFF   
+} ClassifierEngineType;
+
+typedef enum ClassifierType_enum {
+    IMAQ_CLASSIFIER_CUSTOM          = 0,           //The classifier session classifies vectors of doubles.
+    IMAQ_CLASSIFIER_PARTICLE        = 1,           //The classifier session classifies particles in binary images.
+    IMAQ_CLASSIFIER_COLOR           = 2,           //The classifier session classifies an image based on its color.
+    IMAQ_CLASSIFIER_TEXTURE         = 3,           //The classifier session classifies an image based on its texture.
+    IMAQ_CLASSIFIER_TYPE_SIZE_GUARD = 0xFFFFFFFF   
+} ClassifierType;
+
+typedef enum ParticleType_enum {
+    IMAQ_PARTICLE_BRIGHT          = 0,           //Bright particles.
+    IMAQ_PARTICLE_DARK            = 1,           //Dark particles.
+    IMAQ_PARTICLE_TYPE_SIZE_GUARD = 0xFFFFFFFF   
+} ParticleType;
+
+typedef enum VisionInfoType2_enum {
+    IMAQ_VISIONINFO_CALIBRATION        = 0x01,        //Used to indicate interaction with the Calibration information in an image.
+    IMAQ_VISIONINFO_OVERLAY            = 0x02,        //Used to indicate interaction with the Overlay information in an image.
+    IMAQ_VISIONINFO_GRAYTEMPLATE       = 0x04,        //Used to indicate interaction with the grayscale template information in an image.
+    IMAQ_VISIONINFO_COLORTEMPLATE      = 0x08,        //Used to indicate interaction with the color template information in an image.
+    IMAQ_VISIONINFO_GEOMETRICTEMPLATE  = 0x10,        //Used to indicate interaction with the geometric template information in an image.
+    IMAQ_VISIONINFO_CUSTOMDATA         = 0x20,        //Used to indicate interaction with the binary or text Custom Data in an image.
+    IMAQ_VISIONINFO_GOLDENTEMPLATE     = 0x40,        //Used to indicate interaction with the golden template information in an image.
+    IMAQ_VISIONINFO_GEOMETRICTEMPLATE2 = 0x80,        //Used to indicate interaction with the geometric template 2 information in an image.
+    IMAQ_VISIONINFO_ALL                = 0xFFFFFFFF,  //Removes, checks for, or indicates the presence of all types of extra information in an image.
+} VisionInfoType2;
+
+typedef enum ReadClassifierFileMode_enum {
+    IMAQ_CLASSIFIER_READ_ALL                   = 0,           //Read all information from the classifier file.
+    IMAQ_CLASSIFIER_READ_SAMPLES               = 1,           //Read only the samples from the classifier file.
+    IMAQ_CLASSIFIER_READ_PROPERTIES            = 2,           //Read only the properties from the classifier file.
+    IMAQ_READ_CLASSIFIER_FILE_MODES_SIZE_GUARD = 0xFFFFFFFF   
+} ReadClassifierFileMode;
+
+typedef enum WriteClassifierFileMode_enum {
+    IMAQ_CLASSIFIER_WRITE_ALL                   = 0,           //Writes all information to the classifier file.
+    IMAQ_CLASSIFIER_WRITE_CLASSIFY_ONLY         = 1,           //Write only the information needed to classify to the classifier file.
+    IMAQ_WRITE_CLASSIFIER_FILE_MODES_SIZE_GUARD = 0xFFFFFFFF   
+} WriteClassifierFileMode;
+
+typedef enum Barcode2DShape_enum {
+    IMAQ_SQUARE_BARCODE_2D           = 0,           //The function searches for square 2D barcodes.
+    IMAQ_RECTANGULAR_BARCODE_2D      = 1,           //The function searches for rectangular 2D barcodes.
+    IMAQ_BARCODE_2D_SHAPE_SIZE_GUARD = 0xFFFFFFFF   
+} Barcode2DShape;
+
+typedef enum DataMatrixRotationMode_enum {
+    IMAQ_UNLIMITED_ROTATION                   = 0,           //The function allows for unlimited rotation.
+    IMAQ_0_DEGREES                            = 1,           //The function allows for between -5 and 5 degrees of rotation.
+    IMAQ_90_DEGREES                           = 2,           //The function allows for between 85 and 95 degrees of rotation.
+    IMAQ_180_DEGREES                          = 3,           //The function allows for between 175 and 185 degrees of rotation.
+    IMAQ_270_DEGREES                          = 4,           //The function allows for between 265 and 275 degrees of rotation.
+    IMAQ_DATA_MATRIX_ROTATION_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} DataMatrixRotationMode;
+
+typedef enum AIMGrade_enum {
+    IMAQ_AIM_GRADE_F                      = 0,           //The Data Matrix barcode received a grade of F.
+    IMAQ_AIM_GRADE_D                      = 1,           //The Data Matrix barcode received a grade of D.
+    IMAQ_AIM_GRADE_C                      = 2,           //The Data Matrix barcode received a grade of C.
+    IMAQ_AIM_GRADE_B                      = 3,           //The Data Matrix barcode received a grade of B.
+    IMAQ_AIM_GRADE_A                      = 4,           //The Data Matrix barcode received a grade of A.
+    IMAQ_DATA_MATRIX_AIM_GRADE_SIZE_GUARD = 0xFFFFFFFF   
+} AIMGrade;
+
+typedef enum DataMatrixCellFillMode_enum {
+    IMAQ_AUTO_DETECT_CELL_FILL_MODE            = -2,          //Sets the function to determine the Data Matrix barcode cell fill percentage automatically.
+    IMAQ_LOW_FILL                              = 0,           //Sets the function to read Data Matrix barcodes with a cell fill percentage of less than 30 percent.
+    IMAQ_NORMAL_FILL                           = 1,           //Sets the function to read Data Matrix barcodes with a cell fill percentage greater than or equal to 30 percent.
+    IMAQ_DATA_MATRIX_CELL_FILL_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} DataMatrixCellFillMode;
+
+typedef enum DataMatrixDemodulationMode_enum {
+    IMAQ_AUTO_DETECT_DEMODULATION_MODE            = -2,          //The function will try each demodulation mode and use the one which decodes the Data Matrix barcode within the fewest iterations and utilizing the least amount of error correction.
+    IMAQ_HISTOGRAM                                = 0,           //The function uses a histogram of all of the Data Matrix cells to calculate a threshold.
+    IMAQ_LOCAL_CONTRAST                           = 1,           //The function examines each of the cell's neighbors to determine if the cell is on or off.
+    IMAQ_COMBINED                                 = 2,           //The function uses the histogram of the Data Matrix barcode to calculate a threshold.
+    IMAQ_ALL_DEMODULATION_MODES                   = 3,           //The function tries IMAQ_HISTOGRAM, then IMAQ_LOCAL_CONTRAST and then IMAQ_COMBINATION, stopping once one mode is successful.
+    IMAQ_DATA_MATRIX_DEMODULATION_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} DataMatrixDemodulationMode;
+
+typedef enum DataMatrixECC_enum {
+    IMAQ_AUTO_DETECT_ECC            = -2,          //Sets the function to determine the Data Matrix barcode ECC automatically.
+    IMAQ_ECC_000                    = 0,           //Sets the function to read Data Matrix barcodes of ECC 000 only.
+    IMAQ_ECC_050                    = 50,          //Sets the function to read Data Matrix barcodes of ECC 050 only.
+    IMAQ_ECC_080                    = 80,          //Sets the function to read Data Matrix barcodes of ECC 080 only.
+    IMAQ_ECC_100                    = 100,         //Sets the function to read Data Matrix barcodes of ECC 100 only.
+    IMAQ_ECC_140                    = 140,         //Sets the function to read Data Matrix barcodes of ECC 140 only.
+    IMAQ_ECC_000_140                = 190,         //Sets the function to read Data Matrix barcodes of ECC 000, ECC 050, ECC 080, ECC 100, and ECC 140 only.
+    IMAQ_ECC_200                    = 200,         //Sets the function to read Data Matrix barcodes of ECC 200 only.
+    IMAQ_DATA_MATRIX_ECC_SIZE_GUARD = 0xFFFFFFFF   
+} DataMatrixECC;
+
+typedef enum DataMatrixPolarity_enum {
+    IMAQ_AUTO_DETECT_POLARITY            = -2,          //Sets the function to determine the Data Matrix barcode polarity automatically.
+    IMAQ_BLACK_DATA_ON_WHITE_BACKGROUND  = 0,           //Sets the function to read Data Matrix barcodes with dark data on a bright background.
+    IMAQ_WHITE_DATA_ON_BLACK_BACKGROUND  = 1,           //Sets the function to read Data Matrix barcodes with bright data on a dark background.
+    IMAQ_DATA_MATRIX_POLARITY_SIZE_GUARD = 0xFFFFFFFF   
+} DataMatrixPolarity;
+
+typedef enum DataMatrixCellFilterMode_enum {
+    IMAQ_AUTO_DETECT_CELL_FILTER_MODE            = -2,          //The function will try all filter modes and uses the one that decodes the Data Matrix barcode within the fewest iterations and utilizing the least amount of error correction.
+    IMAQ_AVERAGE_FILTER                          = 0,           //The function sets the pixel value for the cell to the average of the sampled pixels.
+    IMAQ_MEDIAN_FILTER                           = 1,           //The function sets the pixel value for the cell to the median of the sampled pixels.
+    IMAQ_CENTRAL_AVERAGE_FILTER                  = 2,           //The function sets the pixel value for the cell to the average of the pixels in the center of the cell sample.
+    IMAQ_HIGH_AVERAGE_FILTER                     = 3,           //The function sets the pixel value for the cell to the average value of the half of the sampled pixels with the highest pixel values.
+    IMAQ_LOW_AVERAGE_FILTER                      = 4,           //The function sets the pixel value for the cell to the average value of the half of the sampled pixels with the lowest pixel values.
+    IMAQ_VERY_HIGH_AVERAGE_FILTER                = 5,           //The function sets the pixel value for the cell to the average value of the ninth of the sampled pixels with the highest pixel values.
+    IMAQ_VERY_LOW_AVERAGE_FILTER                 = 6,           //The function sets the pixel value for the cell to the average value of the ninth of the sampled pixels with the lowest pixel values.
+    IMAQ_ALL_CELL_FILTERS                        = 8,           //The function tries each filter mode, starting with IMAQ_AVERAGE_FILTER and ending with IMAQ_VERY_LOW_AVERAGE_FILTER, stopping once a filter mode decodes correctly.
+    IMAQ_DATA_MATRIX_CELL_FILTER_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} DataMatrixCellFilterMode;
+
+typedef enum WindowBackgroundHatchStyle_enum {
+    IMAQ_HATCH_STYLE_HORIZONTAL        = 0,           //The background of the display window will be horizontal bars.
+    IMAQ_HATCH_STYLE_VERTICAL          = 1,           //The background of the display window will be vertical bars.
+    IMAQ_HATCH_STYLE_FORWARD_DIAGONAL  = 2,           //The background of the display window will be diagonal bars.
+    IMAQ_HATCH_STYLE_BACKWARD_DIAGONAL = 3,           //The background of the display window will be diagonal bars.
+    IMAQ_HATCH_STYLE_CROSS             = 4,           //The background of the display window will be intersecting horizontal and vertical bars.
+    IMAQ_HATCH_STYLE_CROSS_HATCH       = 5,           //The background of the display window will be intersecting forward and backward diagonal bars.
+    IMAQ_HATCH_STYLE_SIZE_GUARD        = 0xFFFFFFFF   
+} WindowBackgroundHatchStyle;
+
+typedef enum DataMatrixMirrorMode_enum {
+    IMAQ_AUTO_DETECT_MIRROR                 = -2,          //Specifies that the function should determine if the Data Matrix barcode is mirrored.
+    IMAQ_APPEARS_NORMAL                     = 0,           //Specifies that the function should expect the Data Matrix barcode to appear normal.
+    IMAQ_APPEARS_MIRRORED                   = 1,           //Specifies that the function should expect the Data Matrix barcode to appear mirrored.
+    IMAQ_DATA_MATRIX_MIRROR_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} DataMatrixMirrorMode;
+
+typedef enum CalibrationMode2_enum {
+    IMAQ_PERSPECTIVE_MODE             = 0,           //Functions correct for distortion caused by the camera's perspective.
+    IMAQ_MICROPLANE_MODE              = 1,           //Functions correct for distortion caused by the camera's lens.
+    IMAQ_SIMPLE_CALIBRATION_MODE      = 2,           //Functions do not correct for distortion.
+    IMAQ_CORRECTED_IMAGE_MODE         = 3,           //The image is already corrected.
+    IMAQ_NO_CALIBRATION_MODE          = 4,           //Image with No calibration.
+    IMAQ_CALIBRATION_MODE2_SIZE_GUARD = 0xFFFFFFFF   
+} CalibrationMode2;
+
+typedef enum DataMatrixGradingMode_enum {
+    IMAQ_NO_GRADING                          = 0,           //The function does not make any preparatory calculations.
+    IMAQ_PREPARE_FOR_AIM                     = 1,           //The function prepares the image for grading using the AIM Print Quality metrics.
+    IMAQ_DATA_MATRIX_GRADING_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} DataMatrixGradingMode;
+
+typedef enum WaveletTransformMode_enum {
+    IMAQ_WAVELET_TRANSFORM_INTEGER         = 0,           //Uses a 5-3 reversible integer transform.
+    IMAQ_WAVELET_TRANSFORM_FLOATING_POINT  = 1,           //Performs a 9-7 irreversible floating-point transform.
+    IMAQ_WAVELET_TRANSFORM_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} WaveletTransformMode;
+
+typedef enum NormalizationMethod_enum {
+    IMAQ_NORMALIZATION_NONE               = 0,           //No normalization.
+    IMAQ_NORMALIZATION_HISTOGRAM_MATCHING = 1,           //Adjust image so its histogram is similar to the golden template's histogram.
+    IMAQ_NORMALIZATION_AVERAGE_MATCHING   = 2,           //Adjust image so its mean pixel value equals the golden template's mean pixel value.
+    IMAQ_NORMALIZATION_SIZE_GUARD         = 0xFFFFFFFF   
+} NormalizationMethod;
+
+typedef enum RegistrationMethod_enum {
+    IMAQ_REGISTRATION_NONE        = 0,           //No registration.
+    IMAQ_REGISTRATION_PERSPECTIVE = 1,           //Adjust image to correct for minor variations in alignment or perspective.
+    IMAQ_REGISTRATION_SIZE_GUARD  = 0xFFFFFFFF   
+} RegistrationMethod;
+
+typedef enum LinearAveragesMode_enum {
+    IMAQ_COLUMN_AVERAGES                 = 1,           //Specifies that the function calculates the mean pixel value of each column.
+    IMAQ_ROW_AVERAGES                    = 2,           //Specifies that the function calculates the mean pixel value of each row.
+    IMAQ_RISING_DIAGONAL_AVERAGES        = 4,           //Specifies that the function calculates the mean pixel value of each diagonal running from the lower left to the upper right of the inspected area of the image.
+    IMAQ_FALLING_DIAGONAL_AVERAGES       = 8,           //Specifies that the function calculates the mean pixel value of each diagonal running from the upper left to the lower right of the inspected area of the image.
+    IMAQ_ALL_LINEAR_AVERAGES             = 15,          //Specifies that the function calculates all four linear mean pixel values.
+    IMAQ_LINEAR_AVERAGES_MODE_SIZE_GUARD = 0xFFFFFFFF   
+} LinearAveragesMode;
+
+typedef enum CompressionType_enum {
+    IMAQ_COMPRESSION_NONE            = 0,           //Specifies that the function should not compress the image.
+    IMAQ_COMPRESSION_JPEG            = 1,           //Specifies that the function should use lossy JPEG compression on the image.
+    IMAQ_COMPRESSION_PACKED_BINARY   = 2,           //Specifies that the function should use lossless binary packing on the image.
+    IMAQ_COMPRESSION_TYPE_SIZE_GUARD = 0xFFFFFFFF   
+} CompressionType;
+
+typedef enum FlattenType_enum {
+    IMAQ_FLATTEN_IMAGE                 = 0,           //Flattens just the image data.
+    IMAQ_FLATTEN_IMAGE_AND_VISION_INFO = 1,           //Flattens the image data and any Vision information associated with the image.
+    IMAQ_FLATTEN_TYPE_SIZE_GUARD       = 0xFFFFFFFF   
+} FlattenType;
+
+typedef enum DataMatrixCellSampleSize_enum {
+    IMAQ_AUTO_DETECT_CELL_SAMPLE_SIZE            = -2,          //The function will try each sample size and use the one which decodes the Data Matrix barcode within the fewest iterations and utilizing the least amount of error correction.
+    IMAQ_1x1                                     = 1,           //The function will use a 1x1 sized sample from each cell.
+    IMAQ_2x2                                     = 2,           //The function will use a 2x2 sized sample from each cell.
+    IMAQ_3x3                                     = 3,           //The function will use a 3x3 sized sample from each cell.
+    IMAQ_4x4                                     = 4,           //The function will use a 4x4 sized sample from each cell.
+    IMAQ_5x5                                     = 5,           //The function will use a 5x5 sized sample from each cell.
+    IMAQ_6x6                                     = 6,           //The function will use a 6x6 sized sample from each cell.
+    IMAQ_7x7                                     = 7,           //The function will use a 7x7 sized sample from each cell.
+    IMAQ_DATA_MATRIX_CELL_SAMPLE_SIZE_SIZE_GUARD = 0xFFFFFFFF   
+} DataMatrixCellSampleSize;
+
+
+//============================================================================
+//  Forward Declare Data Structures
+//============================================================================
+typedef struct Image_struct Image;
+typedef struct ROI_struct ROI;
+typedef struct Overlay_struct Overlay;
+typedef struct ClassifierSession_struct ClassifierSession;
+typedef struct MultipleGeometricPattern_struct MultipleGeometricPattern;
+typedef int ContourID;
+typedef unsigned long SESSION_ID;
+typedef int	AVISession;
+typedef char* FilterName;
+typedef char String255[256];
+typedef struct CharSet_struct CharSet;
+typedef struct OCRSpacingOptions_struct OCRSpacingOptions;
+typedef struct OCRProcessingOptions_struct OCRProcessingOptions;
+typedef struct ReadTextOptions_struct ReadTextOptions;
+typedef struct CharInfo_struct CharInfo;
+typedef struct CharReport_struct CharReport;
+typedef struct ReadTextReport_struct ReadTextReport;
+typedef struct DivisionModel_struct DivisionModel;
+typedef struct FocalLength_struct FocalLength;
+typedef struct PolyModel_struct PolyModel;
+typedef struct DistortionModelParams_struct DistortionModelParams;
+typedef struct PointFloat_struct PointFloat;
+typedef struct InternalParameters_struct InternalParameters;
+typedef struct MaxGridSize_struct MaxGridSize;
+typedef struct ImageSize_struct ImageSize;
+typedef struct CalibrationReferencePoints_struct CalibrationReferencePoints;
+typedef struct GetCameraParametersReport_struct GetCameraParametersReport;
+typedef struct CalibrationAxisInfo_struct CalibrationAxisInfo;
+typedef struct CalibrationLearnSetupInfo_struct CalibrationLearnSetupInfo;
+typedef struct GridDescriptor_struct GridDescriptor;
+typedef struct ErrorStatistics_struct ErrorStatistics;
+typedef struct GetCalibrationInfoReport_struct GetCalibrationInfoReport;
+typedef struct EdgePolarity_struct EdgePolarity;
+typedef struct ClampSettings_struct ClampSettings;
+typedef struct PointDouble_struct PointDouble;
+typedef struct PointDoublePair_struct PointDoublePair;
+typedef struct ClampResults_struct ClampResults;
+typedef struct ClampPoints_struct ClampPoints;
+typedef struct RGBValue_struct RGBValue;
+typedef struct ClampOverlaySettings_struct ClampOverlaySettings;
+typedef struct ClampMax2Report_struct ClampMax2Report;
+typedef struct ContourFitSplineReport_struct ContourFitSplineReport;
+typedef struct LineFloat_struct LineFloat;
+typedef struct LineEquation_struct LineEquation;
+typedef struct ContourFitLineReport_struct ContourFitLineReport;
+typedef struct ContourFitPolynomialReport_struct ContourFitPolynomialReport;
+typedef struct PartialCircle_struct PartialCircle;
+typedef struct PartialEllipse_struct PartialEllipse;
+typedef struct SetupMatchPatternData_struct SetupMatchPatternData;
+typedef struct RangeSettingDouble_struct RangeSettingDouble;
+typedef struct GeometricAdvancedSetupDataOption_struct GeometricAdvancedSetupDataOption;
+typedef struct ContourInfoReport_struct ContourInfoReport;
+typedef struct ROILabel_struct ROILabel;
+typedef struct SupervisedColorSegmentationReport_struct SupervisedColorSegmentationReport;
+typedef struct LabelToROIReport_struct LabelToROIReport;
+typedef struct ColorSegmenationOptions_struct ColorSegmenationOptions;
+typedef struct ClassifiedCurve_struct ClassifiedCurve;
+typedef struct RangeDouble_struct RangeDouble;
+typedef struct RangeLabel_struct RangeLabel;
+typedef struct CurvatureAnalysisReport_struct CurvatureAnalysisReport;
+typedef struct Disparity_struct Disparity;
+typedef struct ComputeDistancesReport_struct ComputeDistancesReport;
+typedef struct MatchMode_struct MatchMode;
+typedef struct ClassifiedDisparity_struct ClassifiedDisparity;
+typedef struct ClassifyDistancesReport_struct ClassifyDistancesReport;
+typedef struct ContourComputeCurvatureReport_struct ContourComputeCurvatureReport;
+typedef struct ContourOverlaySettings_struct ContourOverlaySettings;
+typedef struct CurveParameters_struct CurveParameters;
+typedef struct ExtractContourReport_struct ExtractContourReport;
+typedef struct ConnectionConstraint_struct ConnectionConstraint;
+typedef struct ExtractTextureFeaturesReport_struct ExtractTextureFeaturesReport;
+typedef struct WaveletBandsReport_struct WaveletBandsReport;
+typedef struct CircleFitOptions_struct CircleFitOptions;
+typedef struct EdgeOptions2_struct EdgeOptions2;
+typedef struct FindCircularEdgeOptions_struct FindCircularEdgeOptions;
+typedef struct FindConcentricEdgeOptions_struct FindConcentricEdgeOptions;
+typedef struct ConcentricEdgeFitOptions_struct ConcentricEdgeFitOptions;
+typedef struct FindConcentricEdgeReport_struct FindConcentricEdgeReport;
+typedef struct FindCircularEdgeReport_struct FindCircularEdgeReport;
+typedef struct WindowSize_struct WindowSize;
+typedef struct DisplacementVector_struct DisplacementVector;
+typedef struct WaveletOptions_struct WaveletOptions;
+typedef struct CooccurrenceOptions_struct CooccurrenceOptions;
+typedef struct ParticleClassifierLocalThresholdOptions_struct ParticleClassifierLocalThresholdOptions;
+typedef struct RangeFloat_struct RangeFloat;
+typedef struct ParticleClassifierAutoThresholdOptions_struct ParticleClassifierAutoThresholdOptions;
+typedef struct ParticleClassifierPreprocessingOptions2_struct ParticleClassifierPreprocessingOptions2;
+typedef struct MeasureParticlesReport_struct MeasureParticlesReport;
+typedef struct GeometricPatternMatch3_struct GeometricPatternMatch3;
+typedef struct MatchGeometricPatternAdvancedOptions3_struct MatchGeometricPatternAdvancedOptions3;
+typedef struct ColorOptions_struct ColorOptions;
+typedef struct SampleScore_struct SampleScore;
+typedef struct ClassifierReportAdvanced_struct ClassifierReportAdvanced;
+typedef struct LearnGeometricPatternAdvancedOptions2_struct LearnGeometricPatternAdvancedOptions2;
+typedef struct ParticleFilterOptions2_struct ParticleFilterOptions2;
+typedef struct FindEdgeOptions2_struct FindEdgeOptions2;
+typedef struct FindEdgeReport_struct FindEdgeReport;
+typedef struct FindTransformRectOptions2_struct FindTransformRectOptions2;
+typedef struct FindTransformRectsOptions2_struct FindTransformRectsOptions2;
+typedef struct ReadTextReport3_struct ReadTextReport3;
+typedef struct CharacterStatistics_struct CharacterStatistics;
+typedef struct CharReport3_struct CharReport3;
+typedef struct ArcInfo2_struct ArcInfo2;
+typedef struct EdgeReport2_struct EdgeReport2;
+typedef struct SearchArcInfo_struct SearchArcInfo;
+typedef struct ConcentricRakeReport2_struct ConcentricRakeReport2;
+typedef struct SpokeReport2_struct SpokeReport2;
+typedef struct EdgeInfo_struct EdgeInfo;
+typedef struct SearchLineInfo_struct SearchLineInfo;
+typedef struct RakeReport2_struct RakeReport2;
+typedef struct TransformBehaviors_struct TransformBehaviors;
+typedef struct QRCodeDataToken_struct QRCodeDataToken;
+typedef struct ParticleFilterOptions_struct ParticleFilterOptions;
+typedef struct StraightEdgeReport2_struct StraightEdgeReport2;
+typedef struct StraightEdgeOptions_struct StraightEdgeOptions;
+typedef struct StraightEdge_struct StraightEdge;
+typedef struct QRCodeSearchOptions_struct QRCodeSearchOptions;
+typedef struct QRCodeSizeOptions_struct QRCodeSizeOptions;
+typedef struct QRCodeDescriptionOptions_struct QRCodeDescriptionOptions;
+typedef struct QRCodeReport_struct QRCodeReport;
+typedef struct AIMGradeReport_struct AIMGradeReport;
+typedef struct DataMatrixSizeOptions_struct DataMatrixSizeOptions;
+typedef struct DataMatrixDescriptionOptions_struct DataMatrixDescriptionOptions;
+typedef struct DataMatrixSearchOptions_struct DataMatrixSearchOptions;
+typedef struct DataMatrixReport_struct DataMatrixReport;
+typedef struct JPEG2000FileAdvancedOptions_struct JPEG2000FileAdvancedOptions;
+typedef struct MatchGeometricPatternAdvancedOptions2_struct MatchGeometricPatternAdvancedOptions2;
+typedef struct InspectionAlignment_struct InspectionAlignment;
+typedef struct InspectionOptions_struct InspectionOptions;
+typedef struct CharReport2_struct CharReport2;
+typedef struct CharInfo2_struct CharInfo2;
+typedef struct ReadTextReport2_struct ReadTextReport2;
+typedef struct EllipseFeature_struct EllipseFeature;
+typedef struct CircleFeature_struct CircleFeature;
+typedef struct ConstCurveFeature_struct ConstCurveFeature;
+typedef struct RectangleFeature_struct RectangleFeature;
+typedef struct LegFeature_struct LegFeature;
+typedef struct CornerFeature_struct CornerFeature;
+typedef struct LineFeature_struct LineFeature;
+typedef struct ParallelLinePairFeature_struct ParallelLinePairFeature;
+typedef struct PairOfParallelLinePairsFeature_struct PairOfParallelLinePairsFeature;
+typedef union GeometricFeature_union GeometricFeature;
+typedef struct FeatureData_struct FeatureData;
+typedef struct GeometricPatternMatch2_struct GeometricPatternMatch2;
+typedef struct ClosedCurveFeature_struct ClosedCurveFeature;
+typedef struct LineMatch_struct LineMatch;
+typedef struct LineDescriptor_struct LineDescriptor;
+typedef struct RectangleDescriptor_struct RectangleDescriptor;
+typedef struct RectangleMatch_struct RectangleMatch;
+typedef struct EllipseDescriptor_struct EllipseDescriptor;
+typedef struct EllipseMatch_struct EllipseMatch;
+typedef struct CircleMatch_struct CircleMatch;
+typedef struct CircleDescriptor_struct CircleDescriptor;
+typedef struct ShapeDetectionOptions_struct ShapeDetectionOptions;
+typedef struct Curve_struct Curve;
+typedef struct CurveOptions_struct CurveOptions;
+typedef struct Barcode2DInfo_struct Barcode2DInfo;
+typedef struct DataMatrixOptions_struct DataMatrixOptions;
+typedef struct ClassifierAccuracyReport_struct ClassifierAccuracyReport;
+typedef struct NearestNeighborClassResult_struct NearestNeighborClassResult;
+typedef struct NearestNeighborTrainingReport_struct NearestNeighborTrainingReport;
+typedef struct ParticleClassifierPreprocessingOptions_struct ParticleClassifierPreprocessingOptions;
+typedef struct ClassifierSampleInfo_struct ClassifierSampleInfo;
+typedef struct ClassScore_struct ClassScore;
+typedef struct ClassifierReport_struct ClassifierReport;
+typedef struct NearestNeighborOptions_struct NearestNeighborOptions;
+typedef struct ParticleClassifierOptions_struct ParticleClassifierOptions;
+typedef struct RGBU64Value_struct RGBU64Value;
+typedef struct GeometricPatternMatch_struct GeometricPatternMatch;
+typedef struct MatchGeometricPatternAdvancedOptions_struct MatchGeometricPatternAdvancedOptions;
+typedef struct MatchGeometricPatternOptions_struct MatchGeometricPatternOptions;
+typedef struct LearnGeometricPatternAdvancedOptions_struct LearnGeometricPatternAdvancedOptions;
+typedef struct FitEllipseOptions_struct FitEllipseOptions;
+typedef struct FitCircleOptions_struct FitCircleOptions;
+typedef struct ConstructROIOptions2_struct ConstructROIOptions2;
+typedef struct HSLValue_struct HSLValue;
+typedef struct HSVValue_struct HSVValue;
+typedef struct HSIValue_struct HSIValue;
+typedef struct CIELabValue_struct CIELabValue;
+typedef struct CIEXYZValue_struct CIEXYZValue;
+typedef union Color2_union Color2;
+typedef struct BestEllipse2_struct BestEllipse2;
+typedef struct LearnPatternAdvancedOptions_struct LearnPatternAdvancedOptions;
+typedef struct AVIInfo_struct AVIInfo;
+typedef struct LearnPatternAdvancedShiftOptions_struct LearnPatternAdvancedShiftOptions;
+typedef struct LearnPatternAdvancedRotationOptions_struct LearnPatternAdvancedRotationOptions;
+typedef struct MatchPatternAdvancedOptions_struct MatchPatternAdvancedOptions;
+typedef struct ParticleFilterCriteria2_struct ParticleFilterCriteria2;
+typedef struct BestCircle2_struct BestCircle2;
+typedef struct OCRSpacingOptions_struct OCRSpacingOptions;
+typedef struct OCRProcessingOptions_struct OCRProcessingOptions;
+typedef struct ReadTextOptions_struct ReadTextOptions;
+typedef struct CharInfo_struct CharInfo;
+#if !defined(USERINT_HEADER) && !defined(_CVI_RECT_DEFINED)
+typedef struct Rect_struct Rect;
+#endif
+typedef struct CharReport_struct CharReport;
+typedef struct ReadTextReport_struct ReadTextReport;
+#if !defined(USERINT_HEADER) && !defined(_CVI_POINT_DEFINED)
+typedef struct Point_struct Point;
+#endif
+typedef struct Annulus_struct Annulus;
+typedef struct EdgeLocationReport_struct EdgeLocationReport;
+typedef struct EdgeOptions_struct EdgeOptions;
+typedef struct EdgeReport_struct EdgeReport;
+typedef struct ExtremeReport_struct ExtremeReport;
+typedef struct FitLineOptions_struct FitLineOptions;
+typedef struct DisplayMapping_struct DisplayMapping;
+typedef struct DetectExtremesOptions_struct DetectExtremesOptions;
+typedef struct ImageInfo_struct ImageInfo;
+typedef struct LCDOptions_struct LCDOptions;
+typedef struct LCDReport_struct LCDReport;
+typedef struct LCDSegments_struct LCDSegments;
+typedef struct LearnCalibrationOptions_struct LearnCalibrationOptions;
+typedef struct LearnColorPatternOptions_struct LearnColorPatternOptions;
+typedef struct Line_struct Line;
+typedef struct LinearAverages_struct LinearAverages;
+typedef struct LineProfile_struct LineProfile;
+typedef struct MatchColorPatternOptions_struct MatchColorPatternOptions;
+typedef struct HistogramReport_struct HistogramReport;
+typedef struct ArcInfo_struct ArcInfo;
+typedef struct AxisReport_struct AxisReport;
+typedef struct BarcodeInfo_struct BarcodeInfo;
+typedef struct BCGOptions_struct BCGOptions;
+typedef struct BestCircle_struct BestCircle;
+typedef struct BestEllipse_struct BestEllipse;
+typedef struct BestLine_struct BestLine;
+typedef struct BrowserOptions_struct BrowserOptions;
+typedef struct CoordinateSystem_struct CoordinateSystem;
+typedef struct CalibrationInfo_struct CalibrationInfo;
+typedef struct CalibrationPoints_struct CalibrationPoints;
+typedef struct CaliperOptions_struct CaliperOptions;
+typedef struct CaliperReport_struct CaliperReport;
+typedef struct DrawTextOptions_struct DrawTextOptions;
+typedef struct CircleReport_struct CircleReport;
+typedef struct ClosedContour_struct ClosedContour;
+typedef struct ColorHistogramReport_struct ColorHistogramReport;
+typedef struct ColorInformation_struct ColorInformation;
+typedef struct Complex_struct Complex;
+typedef struct ConcentricRakeReport_struct ConcentricRakeReport;
+typedef struct ConstructROIOptions_struct ConstructROIOptions;
+typedef struct ContourInfo_struct ContourInfo;
+typedef union ContourUnion_union ContourUnion;
+typedef struct ContourInfo2_struct ContourInfo2;
+typedef struct ContourPoint_struct ContourPoint;
+typedef struct CoordinateTransform_struct CoordinateTransform;
+typedef struct CoordinateTransform2_struct CoordinateTransform2;
+typedef struct CannyOptions_struct CannyOptions;
+typedef struct Range_struct Range;
+typedef struct UserPointSymbol_struct UserPointSymbol;
+typedef struct View3DOptions_struct View3DOptions;
+typedef struct MatchPatternOptions_struct MatchPatternOptions;
+typedef struct TIFFFileOptions_struct TIFFFileOptions;
+typedef union Color_union Color;
+typedef union PixelValue_union PixelValue;
+typedef struct OpenContour_struct OpenContour;
+typedef struct OverlayTextOptions_struct OverlayTextOptions;
+typedef struct ParticleFilterCriteria_struct ParticleFilterCriteria;
+typedef struct ParticleReport_struct ParticleReport;
+typedef struct PatternMatch_struct PatternMatch;
+typedef struct QuantifyData_struct QuantifyData;
+typedef struct QuantifyReport_struct QuantifyReport;
+typedef struct RakeOptions_struct RakeOptions;
+typedef struct RakeReport_struct RakeReport;
+typedef struct TransformReport_struct TransformReport;
+typedef struct ShapeReport_struct ShapeReport;
+typedef struct MeterArc_struct MeterArc;
+typedef struct ThresholdData_struct ThresholdData;
+typedef struct StructuringElement_struct StructuringElement;
+typedef struct SpokeReport_struct SpokeReport;
+typedef struct SimpleEdgeOptions_struct SimpleEdgeOptions;
+typedef struct SelectParticleCriteria_struct SelectParticleCriteria;
+typedef struct SegmentInfo_struct SegmentInfo;
+typedef struct RotationAngleRange_struct RotationAngleRange;
+typedef struct RotatedRect_struct RotatedRect;
+typedef struct ROIProfile_struct ROIProfile;
+typedef struct ToolWindowOptions_struct ToolWindowOptions;
+typedef struct SpokeOptions_struct SpokeOptions;
+
+//============================================================================
+// Data Structures
+//============================================================================
+#if !defined __GNUC__ && !defined _M_X64
+#pragma pack(push,1)
+#endif
+typedef struct DivisionModel_struct {
+    float kappa; //The learned kappa coefficient of division model.
+} DivisionModel;
+
+typedef struct FocalLength_struct {
+    float fx; //Focal length in X direction.
+    float fy; //Focal length in Y direction.
+} FocalLength;
+
+typedef struct PolyModel_struct {
+    float*       kCoeffs;    //The learned radial coefficients of polynomial model.
+    unsigned int numKCoeffs; //Number of K coefficients.
+    float        p1;         //The P1(learned tangential coefficients of polynomial model).
+    float        p2;         //The P2(learned tangential coefficients of polynomial model).
+} PolyModel;
+
+typedef struct DistortionModelParams_struct {
+    DistortionModel distortionModel; //Type of learned distortion model.
+    PolyModel       polyModel;       //The learned coefficients of polynomial model.
+    DivisionModel   divisionModel;   //The learned coefficient of division model.
+} DistortionModelParams;
+
+typedef struct PointFloat_struct {
+    float x; //The x-coordinate of the point.
+    float y; //The y-coordinate of the point.
+} PointFloat;
+
+typedef struct InternalParameters_struct {
+    char        isInsufficientData; 
+    FocalLength focalLength;        
+    PointFloat  opticalCenter;      
+} InternalParameters;
+
+typedef struct MaxGridSize_struct {
+    unsigned int xMax; //Maximum x limit for the grid size.
+    unsigned int yMax; //Maximum y limit for the grid size.
+} MaxGridSize;
+
+typedef struct ImageSize_struct {
+    unsigned int xRes; //X resolution of the image.
+    unsigned int yRes; //Y resolution of the image.
+} ImageSize;
+
+typedef struct CalibrationReferencePoints_struct {
+    PointDouble*    pixelCoords;    //Specifies the coordinates of the pixel reference points.
+    unsigned int    numPixelCoords; //Number of pixel coordinates.
+    PointDouble*    realCoords;     //Specifies the measuring unit associated with the image.
+    unsigned int    numRealCoords;  //Number of real coordinates.
+    CalibrationUnit units;          //Specifies the units of X Step and Y Step.
+    ImageSize       imageSize;      //Specifies the size of calibration template image.
+} CalibrationReferencePoints;
+
+typedef struct GetCameraParametersReport_struct {
+    double*               projectionMatrix;     //The projection(homography) matrix of working plane.
+    unsigned int          projectionMatrixRows; //Number of rows in projection matrix.
+    unsigned int          projectionMatrixCols; //Number of columns in projection matrix.
+    DistortionModelParams distortion;           //Distortion model Coefficients.
+    InternalParameters    internalParams;       //The learned internal paramters of camera model such as focal length and optical center.
+} GetCameraParametersReport;
+
+typedef struct CalibrationAxisInfo_struct {
+    PointFloat      center;        //The origin of the reference coordinate system, expressed in pixel units.
+    float           rotationAngle; //The angle of the x-axis of the real-world coordinate system, in relation to the horizontal.
+    AxisOrientation axisDirection; //Specifies the direction of the calibraiton axis which is either Direct or Indirect.
+} CalibrationAxisInfo;
+
+typedef struct CalibrationLearnSetupInfo_struct {
+    CalibrationMode2 calibrationMethod;    //Type of calibration method used.
+    DistortionModel  distortionModel;      //Type of learned distortion model.
+    ScalingMethod    scaleMode;            //The aspect scaling to use when correcting an image.
+    CalibrationROI   roiMode;              //The ROI to use when correcting an image.
+    char             learnCorrectionTable; //Set this input to true value if you want the correction table to be determined and stored.
+} CalibrationLearnSetupInfo;
+
+typedef struct GridDescriptor_struct {
+    float           xStep; //The distance in the x direction between two adjacent pixels in units specified by unit.
+    float           yStep; //The distance in the y direction between two adjacent pixels in units specified by unit.
+    CalibrationUnit unit;  //The unit of measure for the image.
+} GridDescriptor;
+
+typedef struct ErrorStatistics_struct {
+    double mean;              //Mean error statistics value.
+    double maximum;           //Maximum value of error.
+    double standardDeviation; //The standard deviation error statistiscs value.
+    double distortion;        //The distortion error statistics value.
+} ErrorStatistics;
+
+typedef struct GetCalibrationInfoReport_struct {
+    ROI*                      userRoi;         //Specifies the ROI the user provided when learning the calibration.
+    ROI*                      calibrationRoi;  //Specifies the ROI that corresponds to the region of the image where the calibration information is accurate.
+    CalibrationAxisInfo       axisInfo;        //Reference Coordinate System for the real-world coordinates.
+    CalibrationLearnSetupInfo learnSetupInfo;  //Calibration learn setup information.
+    GridDescriptor            gridDescriptor;  //Specifies scaling constants used to calibrate the image.
+    float*                    errorMap;        //The the error map of calibration template image.
+    unsigned int              errorMapRows;    //Number of rows in error map.
+    unsigned int              errorMapCols;    //Number of Columns in error map.
+    ErrorStatistics           errorStatistics; //Error statistics of the calibration.
+} GetCalibrationInfoReport;
+
+typedef struct EdgePolarity_struct {
+    EdgePolaritySearchMode start; 
+    EdgePolaritySearchMode end;   
+} EdgePolarity;
+
+typedef struct ClampSettings_struct {
+    double       angleRange;   //Specifies the angle range.
+    EdgePolarity edgePolarity; //Specifies the edge polarity.
+} ClampSettings;
+
+typedef struct PointDouble_struct {
+    double x; //The x-coordinate of the point.
+    double y; //The y-coordinate of the point.
+} PointDouble;
+
+typedef struct PointDoublePair_struct {
+    PointDouble start; //The Start co-ordinate of the pair.
+    PointDouble end;   //The End co-ordinate of the pair.
+} PointDoublePair;
+
+typedef struct ClampResults_struct {
+    double distancePix;       //Defines the Pixel world distance.
+    double distanceRealWorld; //Defines the real world distance.
+    double angleAbs;          //Defines the absolute angle.
+    double angleRelative;     //Defines the relative angle.
+} ClampResults;
+
+typedef struct ClampPoints_struct {
+    PointDoublePair pixel;     //Specifies the pixel world point pair for clamp.
+    PointDoublePair realWorld; //Specifies the real world point pair for clamp.
+} ClampPoints;
+
+typedef struct RGBValue_struct {
+    unsigned char B;     //The blue value of the color.
+    unsigned char G;     //The green value of the color.
+    unsigned char R;     //The red value of the color.
+    unsigned char alpha; //The alpha value of the color, which represents extra information about a color image, such as gamma correction.
+} RGBValue;
+
+typedef struct ClampOverlaySettings_struct {
+    int      showSearchArea;      //If TRUE, the function overlays the search area on the image.
+    int      showCurves;          //If TRUE, the function overlays the curves on the image.
+    int      showClampLocation;   //If TRUE, the function overlays the clamp location on the image.
+    int      showResult;          //If TRUE, the function overlays the hit lines to the object and the edge used to generate the hit line on the result image.
+    RGBValue searchAreaColor;     //Specifies the RGB color value to use to overlay the search area.
+    RGBValue curvesColor;         //Specifies the RGB color value to use to overlay the curves.
+    RGBValue clampLocationsColor; //Specifies the RGB color value to use to overlay the clamp locations.
+    RGBValue resultColor;         //Specifies the RGB color value to use to overlay the results.
+    char*    overlayGroupName;    //Specifies the group overlay name for the step overlays.
+} ClampOverlaySettings;
+
+typedef struct ClampMax2Report_struct {
+    ClampResults clampResults;     //Specifies the Clamp results information returned by the function.
+    ClampPoints  clampPoints;      //Specifies the clamp points information returned by the function.
+    unsigned int calibrationValid; //Specifies if the calibration information is valid or not.
+} ClampMax2Report;
+
+typedef struct ContourFitSplineReport_struct {
+    PointDouble* points;         //It returns the points of the best-fit B-spline curve.
+    int          numberOfPoints; //Number of Best fit points returned.
+} ContourFitSplineReport;
+
+typedef struct LineFloat_struct {
+    PointFloat start; //The coordinate location of the start of the line.
+    PointFloat end;   //The coordinate location of the end of the line.
+} LineFloat;
+
+typedef struct LineEquation_struct {
+    double a; //The a coefficient of the line equation.
+    double b; //The b coefficient of the line equation.
+    double c; //The c coefficient of the line equation.
+} LineEquation;
+
+typedef struct ContourFitLineReport_struct {
+    LineFloat    lineSegment;  //Line Segment represents the intersection of the line equation and the contour.
+    LineEquation lineEquation; //Line Equation is a structure of three coefficients A, B, and C of the equation in the normal form (Ax + By + C=0) of the best fit line.
+} ContourFitLineReport;
+
+typedef struct ContourFitPolynomialReport_struct {
+    PointDouble* bestFit;                //It returns the points of the best-fit polynomial.
+    int          numberOfPoints;         //Number of Best fit points returned.
+    double*      polynomialCoefficients; //Polynomial Coefficients returns the coefficients of the polynomial equation.
+    int          numberOfCoefficients;   //Number of Coefficients returned in the polynomial coefficients array.
+} ContourFitPolynomialReport;
+
+typedef struct PartialCircle_struct {
+    PointFloat center;     //Center of the circle.
+    double     radius;     //Radius of the circle.
+    double     startAngle; //Start angle of the fitted structure.
+    double     endAngle;   //End angle of the fitted structure.
+} PartialCircle;
+
+typedef struct PartialEllipse_struct {
+    PointFloat center;      //Center of the Ellipse.
+    double     angle;       //Angle of the ellipse.
+    double     majorRadius; //The length of the semi-major axis of the ellipse.
+    double     minorRadius; //The length of the semi-minor axis of the ellipse.
+    double     startAngle;  //Start angle of the fitted structure.
+    double     endAngle;    //End angle of the fitted structure.
+} PartialEllipse;
+
+typedef struct SetupMatchPatternData_struct {
+    unsigned char* matchSetupData;    //String containing the match setup data.
+    int            numMatchSetupData; //Number of match setup data.
+} SetupMatchPatternData;
+
+typedef struct RangeSettingDouble_struct {
+    SettingType settingType; //Match Constraints specifies the match option whose values you want to constrain by the given range.
+    double      min;         //Min is the minimum value of the range for a given Match Constraint.
+    double      max;         //Max is the maximum value of the range for a given Match Constraint.
+} RangeSettingDouble;
+
+typedef struct GeometricAdvancedSetupDataOption_struct {
+    GeometricSetupDataItem type;  //It determines the option you want to use during the matching phase.
+    double                 value; //Value is the value for the option you want to use during the matching phase.
+} GeometricAdvancedSetupDataOption;
+
+typedef struct ContourInfoReport_struct {
+    PointDouble* pointsPixel;       //Points (pixel) specifies the location of every point detected on the curve, in pixels.
+    unsigned int numPointsPixel;    //Number of points pixel elements.
+    PointDouble* pointsReal;        //Points (real) specifies the location of every point detected on the curve, in calibrated units.
+    unsigned int numPointsReal;     //Number of points real elements.
+    double*      curvaturePixel;    //Curvature Pixel displays the curvature profile for the selected contour, in pixels.
+    unsigned int numCurvaturePixel; //Number of curvature pixels.
+    double*      curvatureReal;     //Curvature Real displays the curvature profile for the selected contour, in calibrated units.
+    unsigned int numCurvatureReal;  //Number of curvature Real elements.
+    double       length;            //Length (pixel) specifies the length, in pixels, of the curves in the image.
+    double       lengthReal;        //Length (real) specifies the length, in calibrated units, of the curves within the curvature range.
+    unsigned int hasEquation;       //Has Equation specifies whether the contour has a fitted equation.
+} ContourInfoReport;
+
+typedef struct ROILabel_struct {
+    char*        className; //Specifies the classname you want to segment.
+    unsigned int label;     //Label is the label number associated with the Class Name.
+} ROILabel;
+
+typedef struct SupervisedColorSegmentationReport_struct {
+    ROILabel*    labelOut;    //The Roi labels array.
+    unsigned int numLabelOut; //The number of elements in labelOut array.
+} SupervisedColorSegmentationReport;
+
+typedef struct LabelToROIReport_struct {
+    ROI**         roiArray;                  //Array of ROIs.
+    unsigned int  numOfROIs;                 //Number of ROIs in the roiArray.
+    unsigned int* labelsOutArray;            //Array of labels.
+    unsigned int  numOfLabels;               //Number of labels.
+    int*          isTooManyVectorsArray;     //isTooManyVectorsArray array.
+    unsigned int  isTooManyVectorsArraySize; //Number of elements in isTooManyVectorsArray.
+} LabelToROIReport;
+
+typedef struct ColorSegmenationOptions_struct {
+    unsigned int windowX;         //X is the window size in x direction.
+    unsigned int windowY;         //Y is the window size in y direction.
+    unsigned int stepSize;        //Step Size is the distance between two windows.
+    unsigned int minParticleArea; //Min Particle Area is the minimum number of allowed pixels.
+    unsigned int maxParticleArea; //Max Particle Area is the maximum number of allowed pixels.
+    short        isFineSegment;   //When enabled, the step processes the boundary pixels of each segmentation cluster using a step size of 1.
+} ColorSegmenationOptions;
+
+typedef struct ClassifiedCurve_struct {
+    double       length;           //Specifies the length, in pixels, of the curves within the curvature range.
+    double       lengthReal;       //specifies the length, in calibrated units, of the curves within the curvature range.
+    double       maxCurvature;     //specifies the maximum curvature, in pixels, for the selected curvature range.
+    double       maxCurvatureReal; //specifies the maximum curvature, in calibrated units, for the selected curvature range.
+    unsigned int label;            //specifies the class to which the the sample belongs.
+    PointDouble* curvePoints;      //Curve Points is a point-coordinate cluster that defines the points of the curve.
+    unsigned int numCurvePoints;   //Number of curve points.
+} ClassifiedCurve;
+
+typedef struct RangeDouble_struct {
+    double minValue; //The minimum value of the range.
+    double maxValue; //The maximum value of the range.
+} RangeDouble;
+
+typedef struct RangeLabel_struct {
+    RangeDouble  range; //Specifies the range of curvature values.
+    unsigned int label; //Class Label specifies the class to which the the sample belongs.
+} RangeLabel;
+
+typedef struct CurvatureAnalysisReport_struct {
+    ClassifiedCurve* curves;    
+    unsigned int     numCurves; 
+} CurvatureAnalysisReport;
+
+typedef struct Disparity_struct {
+    PointDouble current;   //Current is a array of points that defines the target contour.
+    PointDouble reference; //reference is a array of points that defines the template contour.
+    double      distance;  //Specifies the distance, in pixels, between the template contour point and the target contour point.
+} Disparity;
+
+typedef struct ComputeDistancesReport_struct {
+    Disparity*   distances;        //Distances is an array containing the computed distances.
+    unsigned int numDistances;     //Number elements in the distances array.
+    Disparity*   distancesReal;    //Distances Real is an array containing the computed distances in calibrated units.
+    unsigned int numDistancesReal; //Number of elements in real distances array.
+} ComputeDistancesReport;
+
+typedef struct MatchMode_struct {
+    unsigned int rotation;  //Rotation When enabled, the Function searches for occurrences of the template in the inspection image, allowing for template matches to be rotated.
+    unsigned int scale;     //Rotation When enabled, the Function searches for occurrences of the template in the inspection image, allowing for template matches to be rotated.
+    unsigned int occlusion; //Occlusion specifies whether or not to search for occluded versions of the shape.
+} MatchMode;
+
+typedef struct ClassifiedDisparity_struct {
+    double       length;                //Length (pixel) specifies the length, in pixels, of the curves within the curvature range.
+    double       lengthReal;            //Length (real) specifies the length, in calibrated units, of the curves within the curvature range.
+    double       maxDistance;           //Maximum Distance (pixel) specifies the maximum distance, in pixels, between points along the selected contour and the template contour.
+    double       maxDistanceReal;       //Maximum Distance (real) specifies the maximum distance, in calibrated units, between points along the selected contour and the template contour.
+    unsigned int label;                 //Class Label specifies the class to which the the sample belongs.
+    PointDouble* templateSubsection;    //Template subsection points is an array of points that defines the boundary of the template.
+    unsigned int numTemplateSubsection; //Number of reference points.
+    PointDouble* targetSubsection;      //Current Points(Target subsection points) is an array of points that defines the boundary of the target.
+    unsigned int numTargetSubsection;   //Number of current points.
+} ClassifiedDisparity;
+
+typedef struct ClassifyDistancesReport_struct {
+    ClassifiedDisparity* classifiedDistances;    //Disparity array containing the classified distances.
+    unsigned int         numClassifiedDistances; //Number of elements in the disparity array.
+} ClassifyDistancesReport;
+
+typedef struct ContourComputeCurvatureReport_struct {
+    double*      curvaturePixel;    //Curvature Pixel displays the curvature profile for the selected contour, in pixels.
+    unsigned int numCurvaturePixel; //Number of curvature pixels.
+    double*      curvatureReal;     //Curvature Real displays the curvature profile for the selected contour, in calibrated units.
+    unsigned int numCurvatureReal;  //Number of curvature Real elements.
+} ContourComputeCurvatureReport;
+
+typedef struct ContourOverlaySettings_struct {
+    unsigned int overlay;       //Overlay specifies whether to display the overlay on the image.
+    RGBValue     color;         //Color is the color of the overlay.
+    unsigned int width;         //Width specifies the width of the overlay in pixels.
+    unsigned int maintainWidth; //Maintain Width? specifies whether you want the overlay measured in screen pixels or image pixels.
+} ContourOverlaySettings;
+
+typedef struct CurveParameters_struct {
+    ExtractionMode extractionMode; //Specifies the method the function uses to identify curves in the image.
+    int            threshold;      //Specifies the minimum contrast a seed point must have in order to begin a curve.
+    EdgeFilterSize filterSize;     //Specifies the width of the edge filter the function uses to identify curves in the image.
+    int            minLength;      //Specifies the length, in pixels, of the smallest curve the function will extract.
+    int            searchStep;     //Search Step Size specifies the distance, in the y direction, between the image rows that the algorithm inspects for curve seed points.
+    int            maxEndPointGap; //Specifies the maximum gap, in pixels, between the endpoints of a curve that the function identifies as a closed curve.
+    int            subpixel;       //Subpixel specifies whether to detect curve points with subpixel accuracy.
+} CurveParameters;
+
+typedef struct ExtractContourReport_struct {
+    PointDouble* contourPoints;    //Contour Points specifies every point found on the contour.
+    int          numContourPoints; //Number of contour points.
+    PointDouble* sourcePoints;     //Source Image Points specifies every point found on the contour in the source image.
+    int          numSourcePoints;  //Number of source points.
+} ExtractContourReport;
+
+typedef struct ConnectionConstraint_struct {
+    ConnectionConstraintType constraintType; //Constraint Type specifies what criteria to use to consider two curves part of a contour.
+    RangeDouble              range;          //Specifies range for a given Match Constraint.
+} ConnectionConstraint;
+
+typedef struct ExtractTextureFeaturesReport_struct {
+    int*     waveletBands;        //The array having all the Wavelet Banks used for extraction.
+    int      numWaveletBands;     //Number of wavelet banks in the Array.
+    double** textureFeatures;     //2-D array to store all the Texture features extracted.
+    int      textureFeaturesRows; //Number of Rows in the Texture Features array.
+    int      textureFeaturesCols; //Number of Cols in Texture Features array.
+} ExtractTextureFeaturesReport;
+
+typedef struct WaveletBandsReport_struct {
+    float** LLBand;  //2-D array for LL Band.
+    float** LHBand;  //2-D array for LH Band.
+    float** HLBand;  //2-D array for HL Band.
+    float** HHBand;  //2-D array for HH Band.
+    float** LLLBand; //2-D array for LLL Band.
+    float** LLHBand; //2-D array for LLH Band.
+    float   LHLBand; //2-D array for LHL Band.
+    float** LHHBand; //2-D array for LHH Band.
+    int     rows;    //Number of Rows for each of the 2-D arrays.
+    int     cols;    //Number of Columns for each of the 2-D arrays.
+} WaveletBandsReport;
+
+typedef struct CircleFitOptions_struct {
+    int             maxRadius;   //Specifies the acceptable distance, in pixels, that a point determined to belong to the circle can be from the perimeter of the circle.
+    double          stepSize;    //Step Size is the angle, in degrees, between each radial line in the annular region.
+    RakeProcessType processType; //Method used to process the data extracted for edge detection.
+} CircleFitOptions;
+
+typedef struct EdgeOptions2_struct {
+    EdgePolaritySearchMode polarity;             //Specifies the polarity of the edges to be found.
+    unsigned int           kernelSize;           //Specifies the size of the edge detection kernel.
+    unsigned int           width;                //Specifies the number of pixels averaged perpendicular to the search direction to compute the edge profile strength at each point along the search ROI.
+    float                  minThreshold;         //Specifies the minimum edge strength (gradient magnitude) required for a detected edge.
+    InterpolationMethod    interpolationType;    //Specifies the interpolation method used to locate the edge position.
+    ColumnProcessingMode   columnProcessingMode; //Specifies the method used to find the straight edge.
+} EdgeOptions2;
+
+typedef struct FindCircularEdgeOptions_struct {
+    SpokeDirection direction;        //Specifies the Spoke direction to search in the ROI.
+    int            showSearchArea;   //If TRUE, the function overlays the search area on the image.
+    int            showSearchLines;  //If TRUE, the function overlays the search lines used to locate the edges on the image.
+    int            showEdgesFound;   //If TRUE, the function overlays the locations of the edges found on the image.
+    int            showResult;       //If TRUE, the function overlays the hit lines to the object and the edge used to generate the hit line on the result image.
+    RGBValue       searchAreaColor;  //Specifies the RGB color value to use to overlay the search area.
+    RGBValue       searchLinesColor; //Specifies the RGB color value to use to overlay the search lines.
+    RGBValue       searchEdgesColor; //Specifies the RGB color value to use to overlay the search edges.
+    RGBValue       resultColor;      //Specifies the RGB color value to use to overlay the results.
+    char*          overlayGroupName; //Specifies the overlay group name to assign to the overlays.
+    EdgeOptions2   edgeOptions;      //Specifies the edge detection options along a single search line.
+} FindCircularEdgeOptions;
+
+typedef struct FindConcentricEdgeOptions_struct {
+    ConcentricRakeDirection direction;        //Specifies the Concentric Rake direction.
+    int                     showSearchArea;   //If TRUE, the function overlays the search area on the image.
+    int                     showSearchLines;  //If TRUE, the function overlays the search lines used to locate the edges on the image.
+    int                     showEdgesFound;   //If TRUE, the function overlays the locations of the edges found on the image.
+    int                     showResult;       //If TRUE, the function overlays the hit lines to the object and the edge used to generate the hit line on the result image.
+    RGBValue                searchAreaColor;  //Specifies the RGB color value to use to overlay the search area.
+    RGBValue                searchLinesColor; //Specifies the RGB color value to use to overlay the search lines.
+    RGBValue                searchEdgesColor; //Specifies the RGB color value to use to overlay the search edges.
+    RGBValue                resultColor;      //Specifies the RGB color value to use to overlay the results.
+    char*                   overlayGroupName; //Specifies the overlay group name to assign to the overlays.
+    EdgeOptions2            edgeOptions;      //Specifies the edge detection options along a single search line.
+} FindConcentricEdgeOptions;
+
+typedef struct ConcentricEdgeFitOptions_struct {
+    int             maxRadius;   //Specifies the acceptable distance, in pixels, that a point determined to belong to the circle can be from the perimeter of the circle.
+    double          stepSize;    //The sampling factor that determines the gap between the rake lines.
+    RakeProcessType processType; //Method used to process the data extracted for edge detection.
+} ConcentricEdgeFitOptions;
+
+typedef struct FindConcentricEdgeReport_struct {
+    PointFloat startPt;           //Pixel Coordinates for starting point of the edge.
+    PointFloat endPt;             //Pixel Coordinates for end point of the edge.
+    PointFloat startPtCalibrated; //Real world Coordinates for starting point of the edge.
+    PointFloat endPtCalibrated;   //Real world Coordinates for end point of the edge.
+    double     angle;             //Angle of the edge found.
+    double     angleCalibrated;   //Calibrated angle of the edge found.
+    double     straightness;      //The straightness value of the detected straight edge.
+    double     avgStrength;       //Average strength of the egde found.
+    double     avgSNR;            //Average SNR(Signal to Noise Ratio) for the edge found.
+    int        lineFound;         //If the edge is found or not.
+} FindConcentricEdgeReport;
+
+typedef struct FindCircularEdgeReport_struct {
+    PointFloat centerCalibrated; //Real world Coordinates of the Center.
+    double     radiusCalibrated; //Real world radius of the Circular Edge found.
+    PointFloat center;           //Pixel Coordinates of the Center.
+    double     radius;           //Radius in pixels of the Circular Edge found.
+    double     roundness;        //The roundness of the calculated circular edge.
+    double     avgStrength;      //Average strength of the egde found.
+    double     avgSNR;           //Average SNR(Signal to Noise Ratio) for the edge found.
+    int        circleFound;      //If the circlular edge is found or not.
+} FindCircularEdgeReport;
+
+typedef struct WindowSize_struct {
+    int x;        //Window lenght on X direction.
+    int y;        //Window lenght on Y direction.
+    int stepSize; //Distance between windows.
+} WindowSize;
+
+typedef struct DisplacementVector_struct {
+    int x; //length on X direction.
+    int y; //length on Y direction.
+} DisplacementVector;
+
+typedef struct WaveletOptions_struct {
+    WaveletType typeOfWavelet; //Type of wavelet(db, bior.
+    float       minEnergy;     //Minimum Energy in the bands to consider for texture defect detection.
+} WaveletOptions;
+
+typedef struct CooccurrenceOptions_struct {
+    int                level;        //Level/size of matrix.
+    DisplacementVector displacement; //Displacemnet between pixels to accumulate the matrix.
+} CooccurrenceOptions;
+
+typedef struct ParticleClassifierLocalThresholdOptions_struct {
+    LocalThresholdMethod method;          //Specifies the local thresholding method the function uses.
+    ParticleType         particleType;    //Specifies what kind of particles to look for.
+    unsigned int         windowWidth;     //The width of the rectangular window around the pixel on which the function performs the local threshold.
+    unsigned int         windowHeight;    //The height of the rectangular window around the pixel on which the function performs the local threshold.
+    double               deviationWeight; //Specifies the k constant used in the Niblack local thresholding algorithm, which determines the weight applied to the variance calculation.
+} ParticleClassifierLocalThresholdOptions;
+
+typedef struct RangeFloat_struct {
+    float minValue; //The minimum value of the range.
+    float maxValue; //The maximum value of the range.
+} RangeFloat;
+
+typedef struct ParticleClassifierAutoThresholdOptions_struct {
+    ThresholdMethod method;       //The method for binary thresholding, which specifies how to calculate the classes.
+    ParticleType    particleType; //Specifies what kind of particles to look for.
+    RangeFloat      limits;       //The limits on the automatic threshold range.
+} ParticleClassifierAutoThresholdOptions;
+
+typedef struct ParticleClassifierPreprocessingOptions2_struct {
+    ParticleClassifierThresholdType         thresholdType;         //The type of threshold to perform on the image.
+    RangeFloat                              manualThresholdRange;  //The range of pixels to keep if manually thresholding the image.
+    ParticleClassifierAutoThresholdOptions  autoThresholdOptions;  //The options used to auto threshold the image.
+    ParticleClassifierLocalThresholdOptions localThresholdOptions; //The options used to local threshold the image.
+    int                                     rejectBorder;          //Set this element to TRUE to reject border particles.
+    int                                     numErosions;           //The number of erosions to perform.
+} ParticleClassifierPreprocessingOptions2;
+
+typedef struct MeasureParticlesReport_struct {
+    double** pixelMeasurements;      //The measurements on the particles in the image, in pixel coordinates.
+    double** calibratedMeasurements; //The measurements on the particles in the image, in real-world coordinates.
+    size_t   numParticles;           //The number of particles on which measurements were taken.
+    size_t   numMeasurements;        //The number of measurements taken.
+} MeasureParticlesReport;
+
+typedef struct GeometricPatternMatch3_struct {
+    PointFloat position;                //The location of the origin of the template in the match.
+    float      rotation;                //The rotation of the match relative to the template image, in degrees.
+    float      scale;                   //The size of the match relative to the size of the template image, expressed as a percentage.
+    float      score;                   //The accuracy of the match.
+    PointFloat corner[4];               //An array of four points describing the rectangle surrounding the template image.
+    int        inverse;                 //This element is TRUE if the match is an inverse of the template image.
+    float      occlusion;               //The percentage of the match that is occluded.
+    float      templateMatchCurveScore; //The accuracy of the match obtained by comparing the template curves to the curves in the match region.
+    float      matchTemplateCurveScore; //The accuracy of the match obtained by comparing the curves in the match region to the template curves.
+    float      correlationScore;        //The accuracy of the match obtained by comparing the template image to the match region using a correlation metric that compares the two regions as a function of their pixel values.
+    PointFloat calibratedPosition;      //The location of the origin of the template in the match.
+    float      calibratedRotation;      //The rotation of the match relative to the template image, in degrees.
+    PointFloat calibratedCorner[4];     //An array of four points describing the rectangle surrounding the template image.
+} GeometricPatternMatch3;
+
+typedef struct MatchGeometricPatternAdvancedOptions3_struct {
+    unsigned int                    subpixelIterations;         //Specifies the maximum number of incremental improvements used to refine matches with subpixel information.
+    double                          subpixelTolerance;          //Specifies the maximum amount of change, in pixels, between consecutive incremental improvements in the match position before the function stops refining the match position.
+    unsigned int                    initialMatchListLength;     //Specifies the maximum size of the match list.
+    int                             targetTemplateCurveScore;   //Set this element to TRUE to specify that the function should calculate the match curve to template curve score and return it for each match result.
+    int                             correlationScore;           //Set this element to TRUE to specify that the function should calculate the correlation score and return it for each match result.
+    double                          minMatchSeparationDistance; //Specifies the minimum separation distance, in pixels, between the origins of two matches that have unique positions.
+    double                          minMatchSeparationAngle;    //Specifies the minimum angular difference, in degrees, between two matches that have unique angles.
+    double                          minMatchSeparationScale;    //Specifies the minimum difference in scale, expressed as a percentage, between two matches that have unique scales.
+    double                          maxMatchOverlap;            //Specifies the maximum amount of overlap, expressed as a percentage, allowed between the bounding rectangles of two unique matches.
+    int                             coarseResult;               //Specifies whether you want the function to spend less time accurately estimating the location of a match.
+    int                             enableCalibrationSupport;   //Set this element to TRUE to specify the algorithm treat the inspection image as a calibrated image.
+    ContrastMode                    enableContrastReversal;     //Use this element to specify the contrast of the matches to search for in the image.
+    GeometricMatchingSearchStrategy matchStrategy;              //Specifies the aggressiveness of the search strategy.
+    unsigned int                    refineMatchFactor;          //Specifies the factor that is applied to the number of matches requested by the user to determine the number of matches that are refined at the initial matching stage.
+    unsigned int                    subpixelMatchFactor;        //Specifies the factor that is applied to the number of matches requested by the user to determine the number of matches that are evaluated at the final subpixel matching stage.
+} MatchGeometricPatternAdvancedOptions3;
+
+typedef struct ColorOptions_struct {
+    ColorClassificationResolution colorClassificationResolution; //Specifies the color resolution of the classifier.
+    unsigned int                  useLuminance;                  //Specifies if the luminance band is going to be used in the feature vector.
+    ColorMode                     colorMode;                     //Specifies the color mode of the classifier.
+} ColorOptions;
+
+typedef struct SampleScore_struct {
+    char*        className; //The name of the class.
+    float        distance;  //The distance from the item to this class.
+    unsigned int index;     //index of this sample.
+} SampleScore;
+
+typedef struct ClassifierReportAdvanced_struct {
+    char*        bestClassName;       //The name of the best class for the sample.
+    float        classificationScore; //The similarity of the sample and the two closest classes in the classifier.
+    float        identificationScore; //The similarity of the sample and the assigned class.
+    ClassScore*  allScores;           //All classes and their scores.
+    int          allScoresSize;       //The number of entries in allScores.
+    SampleScore* sampleScores;        //All samples and their scores.
+    int          sampleScoresSize;    //The number of entries in sampleScores.
+} ClassifierReportAdvanced;
+
+typedef struct LearnGeometricPatternAdvancedOptions2_struct {
+    double       minScaleFactor;        //Specifies the minimum scale factor that the template is learned for.
+    double       maxScaleFactor;        //Specifies the maximum scale factor the template is learned for.
+    double       minRotationAngleValue; //Specifies the minimum rotation angle the template is learned for.
+    double       maxRotationAngleValue; //Specifies the maximum rotation angle the template is learned for.
+    unsigned int imageSamplingFactor;   //Specifies the factor that is used to subsample the template and the image for the initial matching phase.
+} LearnGeometricPatternAdvancedOptions2;
+
+typedef struct ParticleFilterOptions2_struct {
+    int rejectMatches; //Set this parameter to TRUE to transfer only those particles that do not meet all the criteria.
+    int rejectBorder;  //Set this element to TRUE to reject border particles.
+    int fillHoles;     //Set this element to TRUE to fill holes in particles.
+    int connectivity8; //Set this parameter to TRUE to use connectivity-8 to determine whether particles are touching.
+} ParticleFilterOptions2;
+
+typedef struct FindEdgeOptions2_struct {
+    RakeDirection direction;        //The direction to search in the ROI.
+    int           showSearchArea;   //If TRUE, the function overlays the search area on the image.
+    int           showSearchLines;  //If TRUE, the function overlays the search lines used to locate the edges on the image.
+    int           showEdgesFound;   //If TRUE, the function overlays the locations of the edges found on the image.
+    int           showResult;       //If TRUE, the function overlays the hit lines to the object and the edge used to generate the hit line on the result image.
+    RGBValue      searchAreaColor;  //Specifies the RGB color value to use to overlay the search area.
+    RGBValue      searchLinesColor; //Specifies the RGB color value to use to overlay the search lines.
+    RGBValue      searchEdgesColor; //Specifies the RGB color value to use to overlay the search edges.
+    RGBValue      resultColor;      //Specifies the RGB color value to use to overlay the results.
+    char*         overlayGroupName; //Specifies the overlay group name to assign to the overlays.
+    EdgeOptions2  edgeOptions;      //Specifies the edge detection options along a single search line.
+} FindEdgeOptions2;
+
+typedef struct FindEdgeReport_struct {
+    StraightEdge* straightEdges;    //An array of straight edges detected.
+    unsigned int  numStraightEdges; //Indicates the number of straight edges found.
+} FindEdgeReport;
+
+typedef struct FindTransformRectOptions2_struct {
+    FindReferenceDirection direction;        //Specifies the direction and orientation in which the function searches for the primary axis.
+    int                    showSearchArea;   //If TRUE, the function overlays the search area on the image.
+    int                    showSearchLines;  //If TRUE, the function overlays the search lines used to locate the edges on the image.
+    int                    showEdgesFound;   //If TRUE, the function overlays the locations of the edges found on the image.
+    int                    showResult;       //If TRUE, the function overlays the hit lines to the object and the edge used to generate the hit line on the result image.
+    RGBValue               searchAreaColor;  //Specifies the RGB color value to use to overlay the search area.
+    RGBValue               searchLinesColor; //Specifies the RGB color value to use to overlay the search lines.
+    RGBValue               searchEdgesColor; //Specifies the RGB color value to use to overlay the search edges.
+    RGBValue               resultColor;      //Specifies the RGB color value to use to overlay the results.
+    char*                  overlayGroupName; //Specifies the overlay group name to assign to the overlays.
+    EdgeOptions2           edgeOptions;      //Specifies the edge detection options along a single search line.
+} FindTransformRectOptions2;
+
+typedef struct FindTransformRectsOptions2_struct {
+    FindReferenceDirection direction;            //Specifies the direction and orientation in which the function searches for the primary axis.
+    int                    showSearchArea;       //If TRUE, the function overlays the search area on the image.
+    int                    showSearchLines;      //If TRUE, the function overlays the search lines used to locate the edges on the image.
+    int                    showEdgesFound;       //If TRUE, the function overlays the locations of the edges found on the image.
+    int                    showResult;           //If TRUE, the function overlays the hit lines to the object and the edge used to generate the hit line on the result image.
+    RGBValue               searchAreaColor;      //Specifies the RGB color value to use to overlay the search area.
+    RGBValue               searchLinesColor;     //Specifies the RGB color value to use to overlay the search lines.
+    RGBValue               searchEdgesColor;     //Specifies the RGB color value to use to overlay the search edges.
+    RGBValue               resultColor;          //Specifies the RGB color value to use to overlay the results.
+    char*                  overlayGroupName;     //Specifies the overlay group name to assign to the overlays.
+    EdgeOptions2           primaryEdgeOptions;   //Specifies the parameters used to compute the edge gradient information and detect the edges for the primary ROI.
+    EdgeOptions2           secondaryEdgeOptions; //Specifies the parameters used to compute the edge gradient information and detect the edges for the secondary ROI.
+} FindTransformRectsOptions2;
+
+typedef struct ReadTextReport3_struct {
+    const char*  readString;            //The read string.
+    CharReport3* characterReport;       //An array of reports describing the properties of each identified character.
+    int          numCharacterReports;   //The number of identified characters.
+    ROI*         roiBoundingCharacters; //An array specifying the coordinates of the character bounding ROI.
+} ReadTextReport3;
+
+typedef struct CharacterStatistics_struct {
+    int left;          //The left offset of the character bounding rectangles in the current ROI.
+    int top;           //The top offset of the character bounding rectangles in the current ROI.
+    int width;         //The width of each of the characters you trained in the current ROI.
+    int height;        //The height of each trained character in the current ROI.
+    int characterSize; //The size of the character in pixels.
+} CharacterStatistics;
+
+typedef struct CharReport3_struct {
+    const char*         character;           //The character value.
+    int                 classificationScore; //The degree to which the assigned character class represents the object better than the other character classes in the character set.
+    int                 verificationScore;   //The similarity of the character and the reference character for the character class.
+    int                 verified;            //This element is TRUE if a reference character was found for the character class and FALSE if a reference character was not found.
+    int                 lowThreshold;        //The minimum value of the threshold range used for this character.
+    int                 highThreshold;       //The maximum value of the threshold range used for this character.
+    CharacterStatistics characterStats;      //Describes the characters segmented in the ROI.
+} CharReport3;
+
+typedef struct ArcInfo2_struct {
+    PointFloat center;     //The center point of the arc.
+    double     radius;     //The radius of the arc.
+    double     startAngle; //The starting angle of the arc, specified counter-clockwise from the x-axis.
+    double     endAngle;   //The ending angle of the arc, specified counter-clockwise from the x-axis.
+} ArcInfo2;
+
+typedef struct EdgeReport2_struct {
+    EdgeInfo*    edges;            //An array of edges detected.
+    unsigned int numEdges;         //Indicates the number of edges detected.
+    double*      gradientInfo;     //An array that contains the calculated edge strengths along the user-defined search area.
+    unsigned int numGradientInfo;  //Indicates the number of elements contained in gradientInfo.
+    int          calibrationValid; //Indicates if the calibration data corresponding to the location of the edges is correct.
+} EdgeReport2;
+
+typedef struct SearchArcInfo_struct {
+    ArcInfo2    arcCoordinates; //Describes the arc used for edge detection.
+    EdgeReport2 edgeReport;     //Describes the edges found in this search line.
+} SearchArcInfo;
+
+typedef struct ConcentricRakeReport2_struct {
+    EdgeInfo*      firstEdges;    //The first edge point detected along each search line in the ROI.
+    unsigned int   numFirstEdges; //The number of points in the firstEdges array.
+    EdgeInfo*      lastEdges;     //The last edge point detected along each search line in the ROI.
+    unsigned int   numLastEdges;  //The number of points in the lastEdges array.
+    SearchArcInfo* searchArcs;    //Contains the arcs used for edge detection and the edge information for each arc.
+    unsigned int   numSearchArcs; //The number of arcs in the searchArcs array.
+} ConcentricRakeReport2;
+
+typedef struct SpokeReport2_struct {
+    EdgeInfo*       firstEdges;     //The first edge point detected along each search line in the ROI.
+    unsigned int    numFirstEdges;  //The number of points in the firstEdges array.
+    EdgeInfo*       lastEdges;      //The last edge point detected along each search line in the ROI.
+    unsigned int    numLastEdges;   //The number of points in the lastEdges array.
+    SearchLineInfo* searchLines;    //The search lines used for edge detection.
+    unsigned int    numSearchLines; //The number of search lines used in the edge detection.
+} SpokeReport2;
+
+typedef struct EdgeInfo_struct {
+    PointFloat position;           //The location of the edge in the image.
+    PointFloat calibratedPosition; //The position of the edge in the image in real-world coordinates.
+    double     distance;           //The location of the edge from the first point along the boundary of the input ROI.
+    double     calibratedDistance; //The location of the edge from the first point along the boundary of the input ROI in real-world coordinates.
+    double     magnitude;          //The intensity contrast at the edge.
+    double     noisePeak;          //The strength of the noise associated with the current edge.
+    int        rising;             //Indicates the polarity of the edge.
+} EdgeInfo;
+
+typedef struct SearchLineInfo_struct {
+    LineFloat   lineCoordinates; //The endpoints of the search line.
+    EdgeReport2 edgeReport;      //Describes the edges found in this search line.
+} SearchLineInfo;
+
+typedef struct RakeReport2_struct {
+    EdgeInfo*       firstEdges;     //The first edge point detected along each search line in the ROI.
+    unsigned int    numFirstEdges;  //The number of points in the firstEdges array.
+    EdgeInfo*       lastEdges;      //The last edge point detected along each search line in the ROI.
+    unsigned int    numLastEdges;   //The number of points in the lastEdges array.
+    SearchLineInfo* searchLines;    //The search lines used for edge detection.
+    unsigned int    numSearchLines; //The number of search lines used in the edge detection.
+} RakeReport2;
+
+typedef struct TransformBehaviors_struct {
+    GroupBehavior ShiftBehavior;    //Specifies the behavior of an overlay group when a shift operation is applied to an image.
+    GroupBehavior ScaleBehavior;    //Specifies the behavior of an overlay group when a scale operation is applied to an image.
+    GroupBehavior RotateBehavior;   //Specifies the behavior of an overlay group when a rotate operation is applied to an image.
+    GroupBehavior SymmetryBehavior; //Specifies the behavior of an overlay group when a symmetry operation is applied to an image.
+} TransformBehaviors;
+
+typedef struct QRCodeDataToken_struct {
+    QRStreamMode   mode;       //Specifies the stream mode or the format of the data that is encoded in the QR code.
+    unsigned int   modeData;   //Indicates specifiers used by the user to postprocess the data if it requires it.
+    unsigned char* data;       //Shows the encoded data in the QR code.
+    unsigned int   dataLength; //Specifies the length of the data found in the QR code.
+} QRCodeDataToken;
+
+typedef struct ParticleFilterOptions_struct {
+    int rejectMatches; //Set this parameter to TRUE to transfer only those particles that do not meet all the criteria.
+    int rejectBorder;  //Set this element to TRUE to reject border particles.
+    int connectivity8; //Set this parameter to TRUE to use connectivity-8 to determine whether particles are touching.
+} ParticleFilterOptions;
+
+typedef struct StraightEdgeReport2_struct {
+    StraightEdge*   straightEdges;    //Contains an array of found straight edges.
+    unsigned int    numStraightEdges; //Indicates the number of straight edges found.
+    SearchLineInfo* searchLines;      //Contains an array of all search lines used in the detection.
+    unsigned int    numSearchLines;   //The number of search lines used in the edge detection.
+} StraightEdgeReport2;
+
+typedef struct StraightEdgeOptions_struct {
+    unsigned int           numLines;              //Specifies the number of straight edges to find.
+    StraightEdgeSearchMode searchMode;            //Specifies the method used to find the straight edge.
+    double                 minScore;              //Specifies the minimum score of a detected straight edge.
+    double                 maxScore;              //Specifies the maximum score of a detected edge.
+    double                 orientation;           //Specifies the angle at which the straight edge is expected to be found.
+    double                 angleRange;            //Specifies the +/- range around the orientation within which the straight edge is expected to be found.
+    double                 angleTolerance;        //Specifies the expected angular accuracy of the straight edge.
+    unsigned int           stepSize;              //Specifies the gap in pixels between the search lines used with the rake-based methods.
+    double                 minSignalToNoiseRatio; //Specifies the minimum signal to noise ratio (SNR) of the edge points used to fit the straight edge.
+    double                 minCoverage;           //Specifies the minimum number of points as a percentage of the number of search lines that need to be included in the detected straight edge.
+    unsigned int           houghIterations;       //Specifies the number of iterations used in the Hough-based method.
+} StraightEdgeOptions;
+
+typedef struct StraightEdge_struct {
+    LineFloat    straightEdgeCoordinates;           //End points of the detected straight edge in pixel coordinates.
+    LineFloat    calibratedStraightEdgeCoordinates; //End points of the detected straight edge in real-world coordinates.
+    double       angle;                             //Angle of the found edge using the pixel coordinates.
+    double       calibratedAngle;                   //Angle of the found edge using the real-world coordinates.
+    double       score;                             //Describes the score of the detected edge.
+    double       straightness;                      //The straightness value of the detected straight edge.
+    double       averageSignalToNoiseRatio;         //Describes the average signal to noise ratio (SNR) of the detected edge.
+    int          calibrationValid;                  //Indicates if the calibration data for the straight edge is valid.
+    EdgeInfo*    usedEdges;                         //An array of edges that were used to determine this straight line.
+    unsigned int numUsedEdges;                      //Indicates the number of edges in the usedEdges array.
+} StraightEdge;
+
+typedef struct QRCodeSearchOptions_struct {
+    QRRotationMode     rotationMode;       //Specifies the amount of QR code rotation the function should allow for.
+    unsigned int       skipLocation;       //If set to TRUE, specifies that the function should assume that the QR code occupies the entire image (or the entire search region).
+    unsigned int       edgeThreshold;      //The strength of the weakest edge the function uses to find the coarse location of the QR code in the image.
+    QRDemodulationMode demodulationMode;   //The demodulation mode the function uses to locate the QR code.
+    QRCellSampleSize   cellSampleSize;     //The cell sample size the function uses to locate the QR code.
+    QRCellFilterMode   cellFilterMode;     //The cell filter mode the function uses to locate the QR code.
+    unsigned int       skewDegreesAllowed; //Specifies the amount of skew in the QR code the function should allow for.
+} QRCodeSearchOptions;
+
+typedef struct QRCodeSizeOptions_struct {
+    unsigned int minSize; //Specifies the minimum size (in pixels) of the QR code in the image.
+    unsigned int maxSize; //Specifies the maximum size (in pixels) of the QR code in the image.
+} QRCodeSizeOptions;
+
+typedef struct QRCodeDescriptionOptions_struct {
+    QRDimensions dimensions; //The number of rows and columns that are populated for the QR code, measured in cells.
+    QRPolarities polarity;   //The polarity of the QR code.
+    QRMirrorMode mirror;     //This element is TRUE if the QR code appears mirrored in the image and FALSE if the QR code appears normally in the image.
+    QRModelType  modelType;  //This option allows you to specify the type of QR code.
+} QRCodeDescriptionOptions;
+
+typedef struct QRCodeReport_struct {
+    unsigned int       found;                    //This element is TRUE if the function located and decoded a QR code and FALSE if the function failed to locate and decode a QR code.
+    unsigned char*     data;                     //The data encoded in the QR code.
+    unsigned int       dataLength;               //The length of the data array.
+    PointFloat         boundingBox[4];           //An array of four points describing the rectangle surrounding the QR code.
+    QRCodeDataToken*   tokenizedData;            //Contains the data tokenized in exactly the way it was encoded in the code.
+    unsigned int       sizeOfTokenizedData;      //Size of the tokenized data.
+    unsigned int       numErrorsCorrected;       //The number of errors the function corrected when decoding the QR code.
+    unsigned int       dimensions;               //The number of rows and columns that are populated for the QR code, measured in cells.
+    unsigned int       version;                  //The version of the QR code.
+    QRModelType        modelType;                //This option allows you to specify what type of QR code this is.
+    QRStreamMode       streamMode;               //The format of the data encoded in the stream.
+    QRPolarities       matrixPolarity;           //The polarity of the QR code.
+    unsigned int       mirrored;                 //This element is TRUE if the QR code appears mirrored in the image and FALSE if the QR code appears normally in the image.
+    unsigned int       positionInAppendStream;   //Indicates what position the QR code is in with respect to the stream of data in all codes.
+    unsigned int       sizeOfAppendStream;       //Specifies how many QR codes are part of a larger array of codes.
+    int                firstEAN128ApplicationID; //The first EAN-128 Application ID encountered in the stream.
+    int                firstECIDesignator;       //The first Regional Language Designator encountered in the stream.
+    unsigned int       appendStreamIdentifier;   //Specifies what stream the QR code is in relation to when the code is part of a larger array of codes.
+    unsigned int       minimumEdgeStrength;      //The strength of the weakest edge the function used to find the coarse location of the QR code in the image.
+    QRDemodulationMode demodulationMode;         //The demodulation mode the function used to locate the QR code.
+    QRCellSampleSize   cellSampleSize;           //The cell sample size the function used to locate the QR code.
+    QRCellFilterMode   cellFilterMode;           //The cell filter mode the function used to locate the QR code.
+} QRCodeReport;
+
+typedef struct AIMGradeReport_struct {
+    AIMGrade overallGrade;               //The overall letter grade, which is equal to the lowest of the other five letter grades.
+    AIMGrade decodingGrade;              //The letter grade assigned to a Data Matrix barcode based on the success of the function in decoding the Data Matrix barcode.
+    AIMGrade symbolContrastGrade;        //The letter grade assigned to a Data Matrix barcode based on the symbol contrast raw score.
+    float    symbolContrast;             //The symbol contrast raw score representing the percentage difference between the mean of the reflectance of the darkest 10 percent and lightest 10 percent of the Data Matrix barcode.
+    AIMGrade printGrowthGrade;           //The print growth letter grade for the Data Matrix barcode.
+    float    printGrowth;                //The print growth raw score for the barcode, which is based on the extent to which dark or light markings appropriately fill their module boundaries.
+    AIMGrade axialNonuniformityGrade;    //The axial nonuniformity grade for the Data Matrix barcode.
+    float    axialNonuniformity;         //The axial nonuniformity raw score for the barcode, which is based on how much the sampling point spacing differs from one axis to another.
+    AIMGrade unusedErrorCorrectionGrade; //The unused error correction letter grade for the Data Matrix barcode.
+    float    unusedErrorCorrection;      //The unused error correction raw score for the Data Matrix barcode, which is based on the extent to which regional or spot damage in the Data Matrix barcode has eroded the reading safety margin provided by the error correction.
+} AIMGradeReport;
+
+typedef struct DataMatrixSizeOptions_struct {
+    unsigned int minSize;        //Specifies the minimum size (in pixels) of the Data Matrix barcode in the image.
+    unsigned int maxSize;        //Specifies the maximum size (in pixels) of the Data Matrix barcode in the image.
+    unsigned int quietZoneWidth; //Specifies the expected minimum size of the quiet zone, in pixels.
+} DataMatrixSizeOptions;
+
+typedef struct DataMatrixDescriptionOptions_struct {
+    float                  aspectRatio;        //Specifies the ratio of the width of each Data Matrix barcode cell (in pixels) to the height of the Data Matrix barcode (in pixels).
+    unsigned int           rows;               //Specifies the number of rows in the Data Matrix barcode.
+    unsigned int           columns;            //Specifies the number of columns in the Data Matrix barcode.
+    int                    rectangle;          //Set this element to TRUE to specify that the Data Matrix barcode is rectangular.
+    DataMatrixECC          ecc;                //Specifies the ECC used for this Data Matrix barcode.
+    DataMatrixPolarity     polarity;           //Specifies the data-to-background contrast for the Data Matrix barcode.
+    DataMatrixCellFillMode cellFill;           //Specifies the fill percentage for a cell of the Data Matrix barcode that is in the "ON" state.
+    float                  minBorderIntegrity; //Specifies the minimum percentage of the border (locator pattern and timing pattern) the function should expect in the Data Matrix barcode.
+    DataMatrixMirrorMode   mirrorMode;         //Specifies if the Data Matrix barcode appears normally in the image or if the barcode appears mirrored in the image.
+} DataMatrixDescriptionOptions;
+
+typedef struct DataMatrixSearchOptions_struct {
+    DataMatrixRotationMode     rotationMode;             //Specifies the amount of Data Matrix barcode rotation the function should allow for.
+    int                        skipLocation;             //If set to TRUE, specifies that the function should assume that the Data Matrix barcode occupies the entire image (or the entire search region).
+    unsigned int               edgeThreshold;            //Specifies the minimum contrast a pixel must have in order to be considered part of a matrix cell edge.
+    DataMatrixDemodulationMode demodulationMode;         //Specifies the mode the function should use to demodulate (determine which cells are on and which cells are off) the Data Matrix barcode.
+    DataMatrixCellSampleSize   cellSampleSize;           //Specifies the sample size, in pixels, the function should take to determine if each cell is on or off.
+    DataMatrixCellFilterMode   cellFilterMode;           //Specifies the mode the function uses to determine the pixel value for each cell.
+    unsigned int               skewDegreesAllowed;       //Specifies the amount of skew in the Data Matrix barcode the function should allow for.
+    unsigned int               maxIterations;            //Specifies the maximum number of iterations before the function stops looking for the Data Matrix barcode.
+    unsigned int               initialSearchVectorWidth; //Specifies the number of pixels the function should average together to determine the location of an edge.
+} DataMatrixSearchOptions;
+
+typedef struct DataMatrixReport_struct {
+    int                        found;                //This element is TRUE if the function located and decoded a Data Matrix barcode and FALSE if the function failed to locate and decode a Data Matrix barcode.
+    int                        binary;               //This element is TRUE if the Data Matrix barcode contains binary data and FALSE if the Data Matrix barcode contains text data.
+    unsigned char*             data;                 //The data encoded in the Data Matrix barcode.
+    unsigned int               dataLength;           //The length of the data array.
+    PointFloat                 boundingBox[4];       //An array of four points describing the rectangle surrounding the Data Matrix barcode.
+    unsigned int               numErrorsCorrected;   //The number of errors the function corrected when decoding the Data Matrix barcode.
+    unsigned int               numErasuresCorrected; //The number of erasures the function corrected when decoding the Data Matrix barcode.
+    float                      aspectRatio;          //Specifies the aspect ratio of the Data Matrix barcode in the image, which equals the ratio of the width of a Data Matrix barcode cell (in pixels) to the height of a Data Matrix barcode cell (in pixels).
+    unsigned int               rows;                 //The number of rows in the Data Matrix barcode.
+    unsigned int               columns;              //The number of columns in the Data Matrix barcode.
+    DataMatrixECC              ecc;                  //The Error Correction Code (ECC) used by the Data Matrix barcode.
+    DataMatrixPolarity         polarity;             //The polarity of the Data Matrix barcode.
+    DataMatrixCellFillMode     cellFill;             //The cell fill percentage of the Data Matrix barcode.
+    float                      borderIntegrity;      //The percentage of the Data Matrix barcode border that appears correctly in the image.
+    int                        mirrored;             //This element is TRUE if the Data Matrix barcode appears mirrored in the image and FALSE if the Data Matrix barcode appears normally in the image.
+    unsigned int               minimumEdgeStrength;  //The strength of the weakest edge the function used to find the coarse location of the Data Matrix barcode in the image.
+    DataMatrixDemodulationMode demodulationMode;     //The demodulation mode the function used to locate the Data Matrix barcode.
+    DataMatrixCellSampleSize   cellSampleSize;       //The cell sample size the function used to locate the Data Matrix barcode.
+    DataMatrixCellFilterMode   cellFilterMode;       //The cell filter mode the function used to locate the Data Matrix barcode.
+    unsigned int               iterations;           //The number of iterations the function took in attempting to locate the Data Matrix barcode.
+} DataMatrixReport;
+
+typedef struct JPEG2000FileAdvancedOptions_struct {
+    WaveletTransformMode waveletMode;                //Determines which wavelet transform to use when writing the file.
+    int                  useMultiComponentTransform; //Set this parameter to TRUE to use an additional transform on RGB images.
+    unsigned int         maxWaveletTransformLevel;   //Specifies the maximum allowed level of wavelet transform.
+    float                quantizationStepSize;       //Specifies the absolute base quantization step size for derived quantization mode.
+} JPEG2000FileAdvancedOptions;
+
+typedef struct MatchGeometricPatternAdvancedOptions2_struct {
+    int    minFeaturesUsed;            //Specifies the minimum number of features the function uses when matching.
+    int    maxFeaturesUsed;            //Specifies the maximum number of features the function uses when matching.
+    int    subpixelIterations;         //Specifies the maximum number of incremental improvements used to refine matches with subpixel information.
+    double subpixelTolerance;          //Specifies the maximum amount of change, in pixels, between consecutive incremental improvements in the match position before the function stops refining the match position.
+    int    initialMatchListLength;     //Specifies the maximum size of the match list.
+    float  matchTemplateCurveScore;    //Set this element to TRUE to specify that the function should calculate the match curve to template curve score and return it for each match result.
+    int    correlationScore;           //Set this element to TRUE to specify that the function should calculate the correlation score and return it for each match result.
+    double minMatchSeparationDistance; //Specifies the minimum separation distance, in pixels, between the origins of two matches that have unique positions.
+    double minMatchSeparationAngle;    //Specifies the minimum angular difference, in degrees, between two matches that have unique angles.
+    double minMatchSeparationScale;    //Specifies the minimum difference in scale, expressed as a percentage, between two matches that have unique scales.
+    double maxMatchOverlap;            //Specifies the maximum amount of overlap, expressed as a percentage, allowed between the bounding rectangles of two unique matches.
+    int    coarseResult;               //Specifies whether you want the function to spend less time accurately estimating the location of a match.
+    int    smoothContours;             //Set this element to TRUE to specify smoothing be done on the contours of the inspection image before feature extraction.
+    int    enableCalibrationSupport;   //Set this element to TRUE to specify the algorithm treat the inspection image as a calibrated image.
+} MatchGeometricPatternAdvancedOptions2;
+
+typedef struct InspectionAlignment_struct {
+    PointFloat position; //The location of the center of the golden template in the image under inspection.
+    float      rotation; //The rotation of the golden template in the image under inspection, in degrees.
+    float      scale;    //The percentage of the size of the area under inspection compared to the size of the golden template.
+} InspectionAlignment;
+
+typedef struct InspectionOptions_struct {
+    RegistrationMethod  registrationMethod;    //Specifies how the function registers the golden template and the target image.
+    NormalizationMethod normalizationMethod;   //Specifies how the function normalizes the golden template to the target image.
+    int                 edgeThicknessToIgnore; //Specifies desired thickness of edges to be ignored.
+    float               brightThreshold;       //Specifies the threshold for areas where the target image is brighter than the golden template.
+    float               darkThreshold;         //Specifies the threshold for areas where the target image is darker than the golden template.
+    int                 binary;                //Specifies whether the function should return a binary image giving the location of defects, or a grayscale image giving the intensity of defects.
+} InspectionOptions;
+
+typedef struct CharReport2_struct {
+    const char* character;           //The character value.
+    PointFloat  corner[4];           //An array of four points that describes the rectangle that surrounds the character.
+    int         lowThreshold;        //The minimum value of the threshold range used for this character.
+    int         highThreshold;       //The maximum value of the threshold range used for this character.
+    int         classificationScore; //The degree to which the assigned character class represents the object better than the other character classes in the character set.
+    int         verificationScore;   //The similarity of the character and the reference character for the character class.
+    int         verified;            //This element is TRUE if a reference character was found for the character class and FALSE if a reference character was not found.
+} CharReport2;
+
+typedef struct CharInfo2_struct {
+    const char*  charValue;       //Retrieves the character value of the corresponding character in the character set.
+    const Image* charImage;       //The image you used to train this character.
+    const Image* internalImage;   //The internal representation that NI Vision uses to match objects to this character.
+    int          isReferenceChar; //This element is TRUE if the character is the reference character for the character class.
+} CharInfo2;
+
+typedef struct ReadTextReport2_struct {
+    const char*  readString;          //The read string.
+    CharReport2* characterReport;     //An array of reports describing the properties of each identified character.
+    int          numCharacterReports; //The number of identified characters.
+} ReadTextReport2;
+
+typedef struct EllipseFeature_struct {
+    PointFloat position;    //The location of the center of the ellipse.
+    double     rotation;    //The orientation of the semi-major axis of the ellipse with respect to the horizontal.
+    double     minorRadius; //The length of the semi-minor axis of the ellipse.
+    double     majorRadius; //The length of the semi-major axis of the ellipse.
+} EllipseFeature;
+
+typedef struct CircleFeature_struct {
+    PointFloat position; //The location of the center of the circle.
+    double     radius;   //The radius of the circle.
+} CircleFeature;
+
+typedef struct ConstCurveFeature_struct {
+    PointFloat position;   //The center of the circle that this constant curve lies upon.
+    double     radius;     //The radius of the circle that this constant curve lies upon.
+    double     startAngle; //When traveling along the constant curve from one endpoint to the next in a counterclockwise manner, this is the angular component of the vector originating at the center of the constant curve and pointing towards the first endpoint of the constant curve.
+    double     endAngle;   //When traveling along the constant curve from one endpoint to the next in a counterclockwise manner, this is the angular component of the vector originating at the center of the constant curve and pointing towards the second endpoint of the constant curve.
+} ConstCurveFeature;
+
+typedef struct RectangleFeature_struct {
+    PointFloat position;  //The center of the rectangle.
+    PointFloat corner[4]; //The four corners of the rectangle.
+    double     rotation;  //The orientation of the rectangle with respect to the horizontal.
+    double     width;     //The width of the rectangle.
+    double     height;    //The height of the rectangle.
+} RectangleFeature;
+
+typedef struct LegFeature_struct {
+    PointFloat position;  //The location of the leg feature.
+    PointFloat corner[4]; //The four corners of the leg feature.
+    double     rotation;  //The orientation of the leg with respect to the horizontal.
+    double     width;     //The width of the leg.
+    double     height;    //The height of the leg.
+} LegFeature;
+
+typedef struct CornerFeature_struct {
+    PointFloat position;      //The location of the corner feature.
+    double     rotation;      //The angular component of the vector bisecting the corner from position.
+    double     enclosedAngle; //The measure of the enclosed angle of the corner.
+    int        isVirtual;     
+} CornerFeature;
+
+typedef struct LineFeature_struct {
+    PointFloat startPoint; //The starting point of the line.
+    PointFloat endPoint;   //The ending point of the line.
+    double     length;     //The length of the line measured in pixels from the start point to the end point.
+    double     rotation;   //The orientation of the line with respect to the horizontal.
+} LineFeature;
+
+typedef struct ParallelLinePairFeature_struct {
+    PointFloat firstStartPoint;  //The starting point of the first line of the pair.
+    PointFloat firstEndPoint;    //The ending point of the first line of the pair.
+    PointFloat secondStartPoint; //The starting point of the second line of the pair.
+    PointFloat secondEndPoint;   //The ending point of the second line of the pair.
+    double     rotation;         //The orientation of the feature with respect to the horizontal.
+    double     distance;         //The distance from the first line to the second line.
+} ParallelLinePairFeature;
+
+typedef struct PairOfParallelLinePairsFeature_struct {
+    ParallelLinePairFeature firstParallelLinePair;  //The first parallel line pair.
+    ParallelLinePairFeature secondParallelLinePair; //The second parallel line pair.
+    double                  rotation;               //The orientation of the feature with respect to the horizontal.
+    double                  distance;               //The distance from the midline of the first parallel line pair to the midline of the second parallel line pair.
+} PairOfParallelLinePairsFeature;
+
+typedef union GeometricFeature_union {
+    CircleFeature*                  circle;                  //A pointer to a CircleFeature.
+    EllipseFeature*                 ellipse;                 //A pointer to an EllipseFeature.
+    ConstCurveFeature*              constCurve;              //A pointer to a ConstCurveFeature.
+    RectangleFeature*               rectangle;               //A pointer to a RectangleFeature.
+    LegFeature*                     leg;                     //A pointer to a LegFeature.
+    CornerFeature*                  corner;                  //A pointer to a CornerFeature.
+    ParallelLinePairFeature*        parallelLinePair;        //A pointer to a ParallelLinePairFeature.
+    PairOfParallelLinePairsFeature* pairOfParallelLinePairs; //A pointer to a PairOfParallelLinePairsFeature.
+    LineFeature*                    line;                    //A pointer to a LineFeature.
+    ClosedCurveFeature*             closedCurve;             //A pointer to a ClosedCurveFeature.
+} GeometricFeature;
+
+typedef struct FeatureData_struct {
+    FeatureType      type;             //An enumeration representing the type of the feature.
+    PointFloat*      contourPoints;    //A set of points describing the contour of the feature.
+    int              numContourPoints; //The number of points in the contourPoints array.
+    GeometricFeature feature;          //The feature data specific to this type of feature.
+} FeatureData;
+
+typedef struct GeometricPatternMatch2_struct {
+    PointFloat   position;                //The location of the origin of the template in the match.
+    float        rotation;                //The rotation of the match relative to the template image, in degrees.
+    float        scale;                   //The size of the match relative to the size of the template image, expressed as a percentage.
+    float        score;                   //The accuracy of the match.
+    PointFloat   corner[4];               //An array of four points describing the rectangle surrounding the template image.
+    int          inverse;                 //This element is TRUE if the match is an inverse of the template image.
+    float        occlusion;               //The percentage of the match that is occluded.
+    float        templateMatchCurveScore; //The accuracy of the match obtained by comparing the template curves to the curves in the match region.
+    float        matchTemplateCurveScore; //The accuracy of the match obtained by comparing the curves in the match region to the template curves.
+    float        correlationScore;        //The accuracy of the match obtained by comparing the template image to the match region using a correlation metric that compares the two regions as a function of their pixel values.
+    String255    label;                   //The label corresponding to this match when the match is returned by imaqMatchMultipleGeometricPatterns().
+    FeatureData* featureData;             //The features used in this match.
+    int          numFeatureData;          //The size of the featureData array.
+    PointFloat   calibratedPosition;      //The location of the origin of the template in the match.
+    float        calibratedRotation;      //The rotation of the match relative to the template image, in degrees.
+    PointFloat   calibratedCorner[4];     //An array of four points describing the rectangle surrounding the template image.
+} GeometricPatternMatch2;
+
+typedef struct ClosedCurveFeature_struct {
+    PointFloat position;  //The center of the closed curve feature.
+    double     arcLength; //The arc length of the closed curve feature.
+} ClosedCurveFeature;
+
+typedef struct LineMatch_struct {
+    PointFloat startPoint; //The starting point of the matched line.
+    PointFloat endPoint;   //The ending point of the matched line.
+    double     length;     //The length of the line measured in pixels from the start point to the end point.
+    double     rotation;   //The orientation of the matched line.
+    double     score;      //The score of the matched line.
+} LineMatch;
+
+typedef struct LineDescriptor_struct {
+    double minLength; //Specifies the minimum length of a line the function will return.
+    double maxLength; //Specifies the maximum length of a line the function will return.
+} LineDescriptor;
+
+typedef struct RectangleDescriptor_struct {
+    double minWidth;  //Specifies the minimum width of a rectangle the algorithm will return.
+    double maxWidth;  //Specifies the maximum width of a rectangle the algorithm will return.
+    double minHeight; //Specifies the minimum height of a rectangle the algorithm will return.
+    double maxHeight; //Specifies the maximum height of a rectangle the algorithm will return.
+} RectangleDescriptor;
+
+typedef struct RectangleMatch_struct {
+    PointFloat corner[4]; //The corners of the matched rectangle.
+    double     rotation;  //The orientation of the matched rectangle.
+    double     width;     //The width of the matched rectangle.
+    double     height;    //The height of the matched rectangle.
+    double     score;     //The score of the matched rectangle.
+} RectangleMatch;
+
+typedef struct EllipseDescriptor_struct {
+    double minMajorRadius; //Specifies the minimum length of the semi-major axis of an ellipse the function will return.
+    double maxMajorRadius; //Specifies the maximum length of the semi-major axis of an ellipse the function will return.
+    double minMinorRadius; //Specifies the minimum length of the semi-minor axis of an ellipse the function will return.
+    double maxMinorRadius; //Specifies the maximum length of the semi-minor axis of an ellipse the function will return.
+} EllipseDescriptor;
+
+typedef struct EllipseMatch_struct {
+    PointFloat position;    //The location of the center of the matched ellipse.
+    double     rotation;    //The orientation of the matched ellipse.
+    double     majorRadius; //The length of the semi-major axis of the matched ellipse.
+    double     minorRadius; //The length of the semi-minor axis of the matched ellipse.
+    double     score;       //The score of the matched ellipse.
+} EllipseMatch;
+
+typedef struct CircleMatch_struct {
+    PointFloat position; //The location of the center of the matched circle.
+    double     radius;   //The radius of the matched circle.
+    double     score;    //The score of the matched circle.
+} CircleMatch;
+
+typedef struct CircleDescriptor_struct {
+    double minRadius; //Specifies the minimum radius of a circle the function will return.
+    double maxRadius; //Specifies the maximum radius of a circle the function will return.
+} CircleDescriptor;
+
+typedef struct ShapeDetectionOptions_struct {
+    unsigned int mode;           //Specifies the method used when looking for the shape in the image.
+    RangeFloat*  angleRanges;    //An array of angle ranges, in degrees, where each range specifies how much you expect the shape to be rotated in the image.
+    int          numAngleRanges; //The size of the orientationRanges array.
+    RangeFloat   scaleRange;     //A range that specifies the sizes of the shapes you expect to be in the image, expressed as a ratio percentage representing the size of the pattern in the image divided by size of the original pattern multiplied by 100.
+    double       minMatchScore;  
+} ShapeDetectionOptions;
+
+typedef struct Curve_struct {
+    PointFloat*  points;              //The points on the curve.
+    unsigned int numPoints;           //The number of points in the curve.
+    int          closed;              //This element is TRUE if the curve is closed and FALSE if the curve is open.
+    double       curveLength;         //The length of the curve.
+    double       minEdgeStrength;     //The lowest edge strength detected on the curve.
+    double       maxEdgeStrength;     //The highest edge strength detected on the curve.
+    double       averageEdgeStrength; //The average of all edge strengths detected on the curve.
+} Curve;
+
+typedef struct CurveOptions_struct {
+    ExtractionMode extractionMode;   //Specifies the method the function uses to identify curves in the image.
+    int            threshold;        //Specifies the minimum contrast a seed point must have in order to begin a curve.
+    EdgeFilterSize filterSize;       //Specifies the width of the edge filter the function uses to identify curves in the image.
+    int            minLength;        //Specifies the length, in pixels, of the smallest curve the function will extract.
+    int            rowStepSize;      //Specifies the distance, in the y direction, between lines the function inspects for curve seed points.
+    int            columnStepSize;   //Specifies the distance, in the x direction, between columns the function inspects for curve seed points.
+    int            maxEndPointGap;   //Specifies the maximum gap, in pixels, between the endpoints of a curve that the function identifies as a closed curve.
+    int            onlyClosed;       //Set this element to TRUE to specify that the function should only identify closed curves in the image.
+    int            subpixelAccuracy; //Set this element to TRUE to specify that the function identifies the location of curves with subpixel accuracy by interpolating between points to find the crossing of threshold.
+} CurveOptions;
+
+typedef struct Barcode2DInfo_struct {
+    Barcode2DType  type;                 //The type of the 2D barcode.
+    int            binary;               //This element is TRUE if the 2D barcode contains binary data and FALSE if the 2D barcode contains text data.
+    unsigned char* data;                 //The data encoded in the 2D barcode.
+    unsigned int   dataLength;           //The length of the data array.
+    PointFloat     boundingBox[4];       //An array of four points describing the rectangle surrounding the 2D barcode.
+    unsigned int   numErrorsCorrected;   //The number of errors the function corrected when decoding the 2D barcode.
+    unsigned int   numErasuresCorrected; //The number of erasures the function corrected when decoding the 2D barcode.
+    unsigned int   rows;                 //The number of rows in the 2D barcode.
+    unsigned int   columns;              //The number of columns in the 2D barcode.
+} Barcode2DInfo;
+
+typedef struct DataMatrixOptions_struct {
+    Barcode2DSearchMode searchMode;   //Specifies the mode the function uses to search for barcodes.
+    Barcode2DContrast   contrast;     //Specifies the contrast of the barcodes that the function searches for.
+    Barcode2DCellShape  cellShape;    //Specifies the shape of the barcode data cells, which affects how the function decodes the barcode.
+    Barcode2DShape      barcodeShape; //Specifies the shape of the barcodes that the function searches for.
+    DataMatrixSubtype   subtype;      //Specifies the Data Matrix subtypes of the barcodes that the function searches for.
+} DataMatrixOptions;
+
+typedef struct ClassifierAccuracyReport_struct {
+    int     size;                       //The size of the arrays in this structure.
+    float   accuracy;                   //The overall accuracy of the classifier, from 0 to 1000.
+    char**  classNames;                 //The names of the classes of this classifier.
+    double* classAccuracy;              //An array of size elements that contains accuracy information for each class.
+    double* classPredictiveValue;       //An array containing size elements that contains the predictive values of each class.
+    int**   classificationDistribution; //A two-dimensional array containing information about how the classifier classifies its samples.
+} ClassifierAccuracyReport;
+
+typedef struct NearestNeighborClassResult_struct {
+    char* className;         //The name of the class.
+    float standardDeviation; //The standard deviation of the members of this class.
+    int   count;             //The number of samples in this class.
+} NearestNeighborClassResult;
+
+typedef struct NearestNeighborTrainingReport_struct {
+    float**                     classDistancesTable; //The confidence in the training.
+    NearestNeighborClassResult* allScores;           //All classes and their scores.
+    int                         allScoresSize;       //The number of entries in allScores.
+} NearestNeighborTrainingReport;
+
+typedef struct ParticleClassifierPreprocessingOptions_struct {
+    int             manualThreshold;      //Set this element to TRUE to specify the threshold range manually.
+    RangeFloat      manualThresholdRange; //If a manual threshold is being done, the range of pixels to keep.
+    ThresholdMethod autoThresholdMethod;  //If an automatic threshold is being done, the method used to calculate the threshold range.
+    RangeFloat      limits;               //The limits on the automatic threshold range.
+    ParticleType    particleType;         //Specifies what kind of particles to look for.
+    int             rejectBorder;         //Set this element to TRUE to reject border particles.
+    int             numErosions;          //The number of erosions to perform.
+} ParticleClassifierPreprocessingOptions;
+
+typedef struct ClassifierSampleInfo_struct {
+    char*   className;         //The name of the class this sample is in.
+    double* featureVector;     //The feature vector of this sample, or NULL if this is not a custom classifier session.
+    int     featureVectorSize; //The number of elements in the feature vector.
+    Image*  thumbnail;         //A thumbnail image of this sample, or NULL if no image was specified.
+} ClassifierSampleInfo;
+
+typedef struct ClassScore_struct {
+    char* className; //The name of the class.
+    float distance;  //The distance from the item to this class.
+} ClassScore;
+
+typedef struct ClassifierReport_struct {
+    char*       bestClassName;       //The name of the best class for the sample.
+    float       classificationScore; //The similarity of the sample and the two closest classes in the classifier.
+    float       identificationScore; //The similarity of the sample and the assigned class.
+    ClassScore* allScores;           //All classes and their scores.
+    int         allScoresSize;       //The number of entries in allScores.
+} ClassifierReport;
+
+typedef struct NearestNeighborOptions_struct {
+    NearestNeighborMethod method; //The method to use.
+    NearestNeighborMetric metric; //The metric to use.
+    int                   k;      //The value of k, if the IMAQ_K_NEAREST_NEIGHBOR method is used.
+} NearestNeighborOptions;
+
+typedef struct ParticleClassifierOptions_struct {
+    float scaleDependence;  //The relative importance of scale when classifying particles.
+    float mirrorDependence; //The relative importance of mirror symmetry when classifying particles.
+} ParticleClassifierOptions;
+
+typedef struct RGBU64Value_struct {
+    unsigned short B;     //The blue value of the color.
+    unsigned short G;     //The green value of the color.
+    unsigned short R;     //The red value of the color.
+    unsigned short alpha; //The alpha value of the color, which represents extra information about a color image, such as gamma correction.
+} RGBU64Value;
+
+typedef struct GeometricPatternMatch_struct {
+    PointFloat position;                //The location of the origin of the template in the match.
+    float      rotation;                //The rotation of the match relative to the template image, in degrees.
+    float      scale;                   //The size of the match relative to the size of the template image, expressed as a percentage.
+    float      score;                   //The accuracy of the match.
+    PointFloat corner[4];               //An array of four points describing the rectangle surrounding the template image.
+    int        inverse;                 //This element is TRUE if the match is an inverse of the template image.
+    float      occlusion;               //The percentage of the match that is occluded.
+    float      templateMatchCurveScore; //The accuracy of the match obtained by comparing the template curves to the curves in the match region.
+    float      matchTemplateCurveScore; //The accuracy of the match obtained by comparing the curves in the match region to the template curves.
+    float      correlationScore;        //The accuracy of the match obtained by comparing the template image to the match region using a correlation metric that compares the two regions as a function of their pixel values.
+} GeometricPatternMatch;
+
+typedef struct MatchGeometricPatternAdvancedOptions_struct {
+    int    minFeaturesUsed;            //Specifies the minimum number of features the function uses when matching.
+    int    maxFeaturesUsed;            //Specifies the maximum number of features the function uses when matching.
+    int    subpixelIterations;         //Specifies the maximum number of incremental improvements used to refine matches with subpixel information.
+    double subpixelTolerance;          //Specifies the maximum amount of change, in pixels, between consecutive incremental improvements in the match position before the function stops refining the match position.
+    int    initialMatchListLength;     //Specifies the maximum size of the match list.
+    int    matchTemplateCurveScore;    //Set this element to TRUE to specify that the function should calculate the match curve to template curve score and return it for each match result.
+    int    correlationScore;           //Set this element to TRUE to specify that the function should calculate the correlation score and return it for each match result.
+    double minMatchSeparationDistance; //Specifies the minimum separation distance, in pixels, between the origins of two matches that have unique positions.
+    double minMatchSeparationAngle;    //Specifies the minimum angular difference, in degrees, between two matches that have unique angles.
+    double minMatchSeparationScale;    //Specifies the minimum difference in scale, expressed as a percentage, between two matches that have unique scales.
+    double maxMatchOverlap;            //Specifies the maximum amount of overlap, expressed as a percentage, allowed between the bounding rectangles of two unique matches.
+    int    coarseResult;               //Specifies whether you want the function to spend less time accurately estimating the location of a match.
+} MatchGeometricPatternAdvancedOptions;
+
+typedef struct MatchGeometricPatternOptions_struct {
+    unsigned int mode;                //Specifies the method imaqMatchGeometricPattern() uses when looking for the pattern in the image.
+    int          subpixelAccuracy;    //Set this element to TRUE to specify that the function should calculate match locations with subpixel accuracy.
+    RangeFloat*  angleRanges;         //An array of angle ranges, in degrees, where each range specifies how much you expect the template to be rotated in the image.
+    int          numAngleRanges;      //Number of angle ranges in the angleRanges array.
+    RangeFloat   scaleRange;          //A range that specifies the sizes of the pattern you expect to be in the image, expressed as a ratio percentage representing the size of the pattern in the image divided by size of the original pattern multiplied by 100.
+    RangeFloat   occlusionRange;      //A range that specifies the percentage of the pattern you expect to be occluded in the image.
+    int          numMatchesRequested; //Number of valid matches expected.
+    float        minMatchScore;       //The minimum score a match can have for the function to consider the match valid.
+} MatchGeometricPatternOptions;
+
+typedef struct LearnGeometricPatternAdvancedOptions_struct {
+    int    minRectLength;            //Specifies the minimum length for each side of a rectangular feature.
+    double minRectAspectRatio;       //Specifies the minimum aspect ratio of a rectangular feature.
+    int    minRadius;                //Specifies the minimum radius for a circular feature.
+    int    minLineLength;            //Specifies the minimum length for a linear feature.
+    double minFeatureStrength;       //Specifies the minimum strength for a feature.
+    int    maxFeaturesUsed;          //Specifies the maximum number of features the function uses when learning.
+    int    maxPixelDistanceFromLine; //Specifies the maximum number of pixels between an edge pixel and a linear feature for the function to consider that edge pixel as part of the linear feature.
+} LearnGeometricPatternAdvancedOptions;
+
+typedef struct FitEllipseOptions_struct {
+    int    rejectOutliers; //Whether to use every given point or only a subset of the points to fit the ellipse.
+    double minScore;       //Specifies the required quality of the fitted ellipse.
+    double pixelRadius;    //The acceptable distance, in pixels, that a point determined to belong to the ellipse can be from the circumference of the ellipse.
+    int    maxIterations;  //Specifies the number of refinement iterations you allow the function to perform on the initial subset of points.
+} FitEllipseOptions;
+
+typedef struct FitCircleOptions_struct {
+    int    rejectOutliers; //Whether to use every given point or only a subset of the points to fit the circle.
+    double minScore;       //Specifies the required quality of the fitted circle.
+    double pixelRadius;    //The acceptable distance, in pixels, that a point determined to belong to the circle can be from the circumference of the circle.
+    int    maxIterations;  //Specifies the number of refinement iterations you allow the function to perform on the initial subset of points.
+} FitCircleOptions;
+
+typedef struct ConstructROIOptions2_struct {
+    int          windowNumber; //The window number of the image window.
+    const char*  windowTitle;  //Specifies the message string that the function displays in the title bar of the window.
+    PaletteType  type;         //The palette type to use.
+    RGBValue*    palette;      //If type is IMAQ_PALETTE_USER, this array is the palette of colors to use with the window.
+    int          numColors;    //If type is IMAQ_PALETTE_USER, this element is the number of colors in the palette array.
+    unsigned int maxContours;  //The maximum number of contours the user will be able to select.
+} ConstructROIOptions2;
+
+typedef struct HSLValue_struct {
+    unsigned char L;     //The color luminance.
+    unsigned char S;     //The color saturation.
+    unsigned char H;     //The color hue.
+    unsigned char alpha; //The alpha value of the color, which represents extra information about a color image, such as gamma correction.
+} HSLValue;
+
+typedef struct HSVValue_struct {
+    unsigned char V;     //The color value.
+    unsigned char S;     //The color saturation.
+    unsigned char H;     //The color hue.
+    unsigned char alpha; //The alpha value of the color, which represents extra information about a color image, such as gamma correction.
+} HSVValue;
+
+typedef struct HSIValue_struct {
+    unsigned char I;     //The color intensity.
+    unsigned char S;     //The color saturation.
+    unsigned char H;     //The color hue.
+    unsigned char alpha; //The alpha value of the color, which represents extra information about a color image, such as gamma correction.
+} HSIValue;
+
+typedef struct CIELabValue_struct {
+    double        b;     //The yellow/blue information of the color.
+    double        a;     //The red/green information of the color.
+    double        L;     //The color lightness.
+    unsigned char alpha; //The alpha value of the color, which represents extra information about a color image, such as gamma correction.
+} CIELabValue;
+
+typedef struct CIEXYZValue_struct {
+    double        Z;     //The Z color information.
+    double        Y;     //The color luminance.
+    double        X;     //The X color information.
+    unsigned char alpha; //The alpha value of the color, which represents extra information about a color image, such as gamma correction.
+} CIEXYZValue;
+
+typedef union Color2_union {
+    RGBValue    rgb;      //The information needed to describe a color in the RGB (Red, Green, and Blue) color space.
+    HSLValue    hsl;      //The information needed to describe a color in the HSL (Hue, Saturation, and Luminance) color space.
+    HSVValue    hsv;      //The information needed to describe a color in the HSI (Hue, Saturation, and Value) color space.
+    HSIValue    hsi;      //The information needed to describe a color in the HSI (Hue, Saturation, and Intensity) color space.
+    CIELabValue cieLab;   //The information needed to describe a color in the CIE L*a*b* (L, a, b) color space.
+    CIEXYZValue cieXYZ;   //The information needed to describe a color in the CIE XYZ (X, Y, Z) color space.
+    int         rawValue; //The integer value for the data in the color union.
+} Color2;
+
+typedef struct BestEllipse2_struct {
+    PointFloat center;         //The coordinate location of the center of the ellipse.
+    PointFloat majorAxisStart; //The coordinate location of the start of the major axis of the ellipse.
+    PointFloat majorAxisEnd;   //The coordinate location of the end of the major axis of the ellipse.
+    PointFloat minorAxisStart; //The coordinate location of the start of the minor axis of the ellipse.
+    PointFloat minorAxisEnd;   //The coordinate location of the end of the minor axis of the ellipse.
+    double     area;           //The area of the ellipse.
+    double     perimeter;      //The length of the perimeter of the ellipse.
+    double     error;          //Represents the least square error of the fitted ellipse to the entire set of points.
+    int        valid;          //This element is TRUE if the function achieved the minimum score within the number of allowed refinement iterations and FALSE if the function did not achieve the minimum score.
+    int*       pointsUsed;     //An array of the indexes for the points array indicating which points the function used to fit the ellipse.
+    int        numPointsUsed;  //The number of points the function used to fit the ellipse.
+} BestEllipse2;
+
+typedef struct LearnPatternAdvancedOptions_struct {
+    LearnPatternAdvancedShiftOptions*    shiftOptions;    //Use this element to control the behavior of imaqLearnPattern2() during the shift-invariant learning phase.
+    LearnPatternAdvancedRotationOptions* rotationOptions; //Use this element to control the behavior of imaqLearnPattern2()during the rotation-invariant learning phase.
+} LearnPatternAdvancedOptions;
+
+typedef struct AVIInfo_struct {
+    unsigned int width;           //The width of each frame.
+    unsigned int height;          //The height of each frame.
+    ImageType    imageType;       //The type of images this AVI contains.
+    unsigned int numFrames;       //The number of frames in the AVI.
+    unsigned int framesPerSecond; //The number of frames per second this AVI should be shown at.
+    char*        filterName;      //The name of the compression filter used to create this AVI.
+    int          hasData;         //Specifies whether this AVI has data attached to each frame or not.
+    unsigned int maxDataSize;     //If this AVI has data, the maximum size of the data in each frame.
+} AVIInfo;
+
+typedef struct LearnPatternAdvancedShiftOptions_struct {
+    int    initialStepSize;          //The largest number of image pixels to shift the sample across the inspection image during the initial phase of shift-invariant matching.
+    int    initialSampleSize;        //Specifies the number of template pixels that you want to include in a sample for the initial phase of shift-invariant matching.
+    double initialSampleSizeFactor;  //Specifies the size of the sample for the initial phase of shift-invariant matching as a percent of the template size, in pixels.
+    int    finalSampleSize;          //Specifies the number of template pixels you want to add to initialSampleSize for the final phase of shift-invariant matching.
+    double finalSampleSizeFactor;    //Specifies the size of the sample for the final phase of shift-invariant matching as a percent of the edge points in the template, in pixels.
+    int    subpixelSampleSize;       //Specifies the number of template pixels that you want to include in a sample for the subpixel phase of shift-invariant matching.
+    double subpixelSampleSizeFactor; //Specifies the size of the sample for the subpixel phase of shift-invariant matching as a percent of the template size, in pixels.
+} LearnPatternAdvancedShiftOptions;
+
+typedef struct LearnPatternAdvancedRotationOptions_struct {
+    SearchStrategy searchStrategySupport;    //Specifies the aggressiveness of the rotation search strategy available during the matching phase.
+    int            initialStepSize;          //The largest number of image pixels to shift the sample across the inspection image during the initial phase of matching.
+    int            initialSampleSize;        //Specifies the number of template pixels that you want to include in a sample for the initial phase of rotation-invariant matching.
+    double         initialSampleSizeFactor;  //Specifies the size of the sample for the initial phase of rotation-invariant matching as a percent of the template size, in pixels.
+    int            initialAngularAccuracy;   //Sets the angle accuracy, in degrees, to use during the initial phase of rotation-invariant matching.
+    int            finalSampleSize;          //Specifies the number of template pixels you want to add to initialSampleSize for the final phase of rotation-invariant matching.
+    double         finalSampleSizeFactor;    //Specifies the size of the sample for the final phase of rotation-invariant matching as a percent of the edge points in the template, in pixels.
+    int            finalAngularAccuracy;     //Sets the angle accuracy, in degrees, to use during the final phase of the rotation-invariant matching.
+    int            subpixelSampleSize;       //Specifies the number of template pixels that you want to include in a sample for the subpixel phase of rotation-invariant matching.
+    double         subpixelSampleSizeFactor; //Specifies the size of the sample for the subpixel phase of rotation-invariant matching as a percent of the template size, in pixels.
+} LearnPatternAdvancedRotationOptions;
+
+typedef struct MatchPatternAdvancedOptions_struct {
+    int            subpixelIterations;          //Defines the maximum number of incremental improvements used to refine matching using subpixel information.
+    double         subpixelTolerance;           //Defines the maximum amount of change, in pixels, between consecutive incremental improvements in the match position that you want to trigger the end of the refinement process.
+    int            initialMatchListLength;      //Specifies the maximum size of the match list.
+    int            matchListReductionFactor;    //Specifies the reduction of the match list as matches are refined.
+    int            initialStepSize;             //Specifies the number of pixels to shift the sample across the inspection image during the initial phase of shift-invariant matching.
+    SearchStrategy searchStrategy;              //Specifies the aggressiveness of the rotation search strategy.
+    int            intermediateAngularAccuracy; //Specifies the accuracy to use during the intermediate phase of rotation-invariant matching.
+} MatchPatternAdvancedOptions;
+
+typedef struct ParticleFilterCriteria2_struct {
+    MeasurementType parameter;  //The morphological measurement that the function uses for filtering.
+    float           lower;      //The lower bound of the criteria range.
+    float           upper;      //The upper bound of the criteria range.
+    int             calibrated; //Set this element to TRUE to take calibrated measurements.
+    int             exclude;    //Set this element to TRUE to indicate that a match occurs when the measurement is outside the criteria range.
+} ParticleFilterCriteria2;
+
+typedef struct BestCircle2_struct {
+    PointFloat center;        //The coordinate location of the center of the circle.
+    double     radius;        //The radius of the circle.
+    double     area;          //The area of the circle.
+    double     perimeter;     //The length of the perimeter of the circle.
+    double     error;         //Represents the least square error of the fitted circle to the entire set of points.
+    int        valid;         //This element is TRUE if the function achieved the minimum score within the number of allowed refinement iterations and FALSE if the function did not achieve the minimum score.
+    int*       pointsUsed;    //An array of the indexes for the points array indicating which points the function used to fit the circle.
+    int        numPointsUsed; //The number of points the function used to fit the circle.
+} BestCircle2;
+
+typedef struct OCRSpacingOptions_struct {
+    int minCharSpacing;              //The minimum number of pixels that must be between two characters for NI Vision to train or read the characters separately.
+    int minCharSize;                 //The minimum number of pixels required for an object to be a potentially identifiable character.
+    int maxCharSize;                 //The maximum number of pixels required for an object to be a potentially identifiable character.
+    int maxHorizontalElementSpacing; //The maximum horizontal spacing, in pixels, allowed between character elements to train or read the character elements as a single character.
+    int maxVerticalElementSpacing;   //The maximum vertical element spacing in pixels.
+    int minBoundingRectWidth;        //The minimum possible width, in pixels, for a character bounding rectangle.
+    int maxBoundingRectWidth;        //The maximum possible width, in pixels, for a character bounding rectangle.
+    int minBoundingRectHeight;       //The minimum possible height, in pixels, for a character bounding rectangle.
+    int maxBoundingRectHeight;       //The maximum possible height, in pixels, for a character bounding rectangle.
+    int autoSplit;                   //Set this element to TRUE to automatically adjust the location of the character bounding rectangle when characters overlap vertically.
+} OCRSpacingOptions;
+
+typedef struct OCRProcessingOptions_struct {
+    ThresholdMode mode;                       //The thresholding mode.
+    int           lowThreshold;               //The low threshold value when you set mode to IMAQ_FIXED_RANGE.
+    int           highThreshold;              //The high threshold value when you set mode to IMAQ_FIXED_RANGE.
+    int           blockCount;                 //The number of blocks for threshold calculation algorithms that require blocks.
+    int           fastThreshold;              //Set this element to TRUE to use a faster, less accurate threshold calculation algorithm.
+    int           biModalCalculation;         //Set this element to TRUE to calculate both the low and high threshold values when using the fast thresholding method.
+    int           darkCharacters;             //Set this element to TRUE to read or train dark characters on a light background.
+    int           removeParticlesTouchingROI; //Set this element to TRUE to remove the particles touching the ROI.
+    int           erosionCount;               //The number of erosions to perform.
+} OCRProcessingOptions;
+
+typedef struct ReadTextOptions_struct {
+    String255      validChars[255];  //An array of strings that specifies the valid characters.
+    int            numValidChars;    //The number of strings in the validChars array that you have initialized.
+    char           substitutionChar; //The character to substitute for objects that the function cannot match with any of the trained characters.
+    ReadStrategy   readStrategy;     //The read strategy, which determines how closely the function analyzes images in the reading process to match objects with trained characters.
+    int            acceptanceLevel;  //The minimum acceptance level at which an object is considered a trained character.
+    int            aspectRatio;      //The maximum aspect ratio variance percentage for valid characters.
+    ReadResolution readResolution;   //The read resolution, which determines how much of the trained character data the function uses to match objects to trained characters.
+} ReadTextOptions;
+
+typedef struct CharInfo_struct {
+    const char*  charValue;     //Retrieves the character value of the corresponding character in the character set.
+    const Image* charImage;     //The image you used to train this character.
+    const Image* internalImage; //The internal representation that NI Vision uses to match objects to this character.
+} CharInfo;
+
+#if !defined(USERINT_HEADER) && !defined(_CVI_RECT_DEFINED)
+typedef struct Rect_struct {
+    int top;    //Location of the top edge of the rectangle.
+    int left;   //Location of the left edge of the rectangle.
+    int height; //Height of the rectangle.
+    int width;  //Width of the rectangle.
+} Rect;
+#define _CVI_RECT_DEFINED
+#endif
+
+typedef struct CharReport_struct {
+    const char* character;     //The character value.
+    PointFloat  corner[4];     //An array of four points that describes the rectangle that surrounds the character.
+    int         reserved;      //This element is reserved.
+    int         lowThreshold;  //The minimum value of the threshold range used for this character.
+    int         highThreshold; //The maximum value of the threshold range used for this character.
+} CharReport;
+
+typedef struct ReadTextReport_struct {
+    const char*       readString;          //The read string.
+    const CharReport* characterReport;     //An array of reports describing the properties of each identified character.
+    int               numCharacterReports; //The number of identified characters.
+} ReadTextReport;
+
+#if !defined(USERINT_HEADER) && !defined(_CVI_POINT_DEFINED)
+typedef struct Point_struct {
+    int x; //The x-coordinate of the point.
+    int y; //The y-coordinate of the point.
+} Point;
+#define _CVI_POINT_DEFINED
+#endif
+
+typedef struct Annulus_struct {
+    Point  center;      //The coordinate location of the center of the annulus.
+    int    innerRadius; //The internal radius of the annulus.
+    int    outerRadius; //The external radius of the annulus.
+    double startAngle;  //The start angle, in degrees, of the annulus.
+    double endAngle;    //The end angle, in degrees, of the annulus.
+} Annulus;
+
+typedef struct EdgeLocationReport_struct {
+    PointFloat* edges;    //The coordinate location of all edges detected by the search line.
+    int         numEdges; //The number of points in the edges array.
+} EdgeLocationReport;
+
+typedef struct EdgeOptions_struct {
+    unsigned            threshold;         //Specifies the threshold value for the contrast of the edge.
+    unsigned            width;             //The number of pixels that the function averages to find the contrast at either side of the edge.
+    unsigned            steepness;         //The span, in pixels, of the slope of the edge projected along the path specified by the input points.
+    InterpolationMethod subpixelType;      //The method for interpolating.
+    unsigned            subpixelDivisions; //The number of samples the function obtains from a pixel.
+} EdgeOptions;
+
+typedef struct EdgeReport_struct {
+    float        location;   //The location of the edge from the first point in the points array.
+    float        contrast;   //The contrast at the edge.
+    PolarityType polarity;   //The polarity of the edge.
+    float        reserved;   //This element is reserved.
+    PointFloat   coordinate; //The coordinates of the edge.
+} EdgeReport;
+
+typedef struct ExtremeReport_struct {
+    double location;         //The locations of the extreme.
+    double amplitude;        //The amplitude of the extreme.
+    double secondDerivative; //The second derivative of the extreme.
+} ExtremeReport;
+
+typedef struct FitLineOptions_struct {
+    float minScore;       //Specifies the required quality of the fitted line.
+    float pixelRadius;    //Specifies the neighborhood pixel relationship for the initial subset of points being used.
+    int   numRefinements; //Specifies the number of refinement iterations you allow the function to perform on the initial subset of points.
+} FitLineOptions;
+
+typedef struct DisplayMapping_struct {
+    MappingMethod method;       //Describes the method for converting 16-bit pixels to 8-bit pixels.
+    int           minimumValue; //When method is IMAQ_RANGE, minimumValue represents the value that is mapped to 0.
+    int           maximumValue; //When method is IMAQ_RANGE, maximumValue represents the value that is mapped to 255.
+    int           shiftCount;   //When method is IMAQ_DOWNSHIFT, shiftCount represents the number of bits the function right-shifts the 16-bit pixel values.
+} DisplayMapping;
+
+typedef struct DetectExtremesOptions_struct {
+    double threshold; //Defines which extremes are too small.
+    int    width;     //Specifies the number of consecutive data points the function uses in the quadratic least-squares fit.
+} DetectExtremesOptions;
+
+typedef struct ImageInfo_struct {
+    CalibrationUnit imageUnit;     //If you set calibration information with imaqSetSimpleCalibrationInfo(), imageUnit is the calibration unit.
+    float           stepX;         //If you set calibration information with imaqSetCalibrationInfo(), stepX is the distance in the calibration unit between two pixels in the x direction.
+    float           stepY;         //If you set calibration information with imaqSetCalibrationInfo(), stepY is the distance in the calibration unit between two pixels in the y direction.
+    ImageType       imageType;     //The type of the image.
+    int             xRes;          //The number of columns in the image.
+    int             yRes;          //The number of rows in the image.
+    int             xOffset;       //If you set mask offset information with imaqSetMaskOffset(), xOffset is the offset of the mask origin in the x direction.
+    int             yOffset;       //If you set mask offset information with imaqSetMaskOffset(), yOffset is the offset of the mask origin in the y direction.
+    int             border;        //The number of border pixels around the image.
+    int             pixelsPerLine; //The number of pixels stored for each line of the image.
+    void*           reserved0;     //This element is reserved.
+    void*           reserved1;     //This element is reserved.
+    void*           imageStart;    //A pointer to pixel (0,0).
+} ImageInfo;
+
+typedef struct LCDOptions_struct {
+    int   litSegments;  //Set this parameter to TRUE if the segments are brighter than the background.
+    float threshold;    //Determines whether a segment is ON or OFF.
+    int   sign;         //Indicates whether the function must read the sign of the indicator.
+    int   decimalPoint; //Determines whether to look for a decimal separator after each digit.
+} LCDOptions;
+
+typedef struct LCDReport_struct {
+    const char*  text;          //A string of the characters of the LCD.
+    LCDSegments* segmentInfo;   //An array of LCDSegment structures describing which segments of each digit are on.
+    int          numCharacters; //The number of characters that the function reads.
+    int          reserved;      //This element is reserved.
+} LCDReport;
+
+typedef struct LCDSegments_struct {
+    unsigned a:1;         //True if the a segment is on.
+    unsigned b:1;         //True if the b segment is on.
+    unsigned c:1;         //True if the c segment is on.
+    unsigned d:1;         //True if the d segment is on.
+    unsigned e:1;         //True if the e segment is on.
+    unsigned f:1;         //True if the f segment is on.
+    unsigned g:1;         //True if the g segment is on.
+    unsigned reserved:25; //This element is reserved.
+} LCDSegments;
+
+typedef struct LearnCalibrationOptions_struct {
+    CalibrationMode mode;       //Specifies the type of algorithm you want to use to reduce distortion in your image.
+    ScalingMethod   method;     //Defines the scaling method correction functions use to correct the image.
+    CalibrationROI  roi;        //Specifies the ROI correction functions use when correcting an image.
+    int             learnMap;   //Set this element to TRUE if you want the function to calculate and store an error map during the learning process.
+    int             learnTable; //Set this element to TRUE if you want the function to calculate and store the correction table.
+} LearnCalibrationOptions;
+
+typedef struct LearnColorPatternOptions_struct {
+    LearningMode      learnMode;         //Specifies the invariance mode the function uses when learning the pattern.
+    ImageFeatureMode  featureMode;       //Specifies the features the function uses when learning the color pattern.
+    int               threshold;         //Specifies the saturation threshold the function uses to distinguish between two colors that have the same hue values.
+    ColorIgnoreMode   ignoreMode;        //Specifies whether the function excludes certain colors from the color features of the template image.
+    ColorInformation* colorsToIgnore;    //An array of ColorInformation structures providing a set of colors to exclude from the color features of the template image.
+    int               numColorsToIgnore; //The number of ColorInformation structures in the colorsToIgnore array.
+} LearnColorPatternOptions;
+
+typedef struct Line_struct {
+    Point start; //The coordinate location of the start of the line.
+    Point end;   //The coordinate location of the end of the line.
+} Line;
+
+typedef struct LinearAverages_struct {
+    float* columnAverages;      //An array containing the mean pixel value of each column.
+    int    columnCount;         //The number of elements in the columnAverages array.
+    float* rowAverages;         //An array containing the mean pixel value of each row.
+    int    rowCount;            //The number of elements in the rowAverages array.
+    float* risingDiagAverages;  //An array containing the mean pixel value of each diagonal running from the lower left to the upper right of the inspected area of the image.
+    int    risingDiagCount;     //The number of elements in the risingDiagAverages array.
+    float* fallingDiagAverages; //An array containing the mean pixel value of each diagonal running from the upper left to the lower right of the inspected area of the image.
+    int    fallingDiagCount;    //The number of elements in the fallingDiagAverages array.
+} LinearAverages;
+
+typedef struct LineProfile_struct {
+    float* profileData; //An array containing the value of each pixel in the line.
+    Rect   boundingBox; //The bounding rectangle of the line.
+    float  min;         //The smallest pixel value in the line profile.
+    float  max;         //The largest pixel value in the line profile.
+    float  mean;        //The mean value of the pixels in the line profile.
+    float  stdDev;      //The standard deviation of the line profile.
+    int    dataCount;   //The size of the profileData array.
+} LineProfile;
+
+typedef struct MatchColorPatternOptions_struct {
+    MatchingMode        matchMode;           //Specifies the method to use when looking for the color pattern in the image.
+    ImageFeatureMode    featureMode;         //Specifies the features to use when looking for the color pattern in the image.
+    int                 minContrast;         //Specifies the minimum contrast expected in the image.
+    int                 subpixelAccuracy;    //Set this parameter to TRUE to return areas in the image that match the pattern area with subpixel accuracy.
+    RotationAngleRange* angleRanges;         //An array of angle ranges, in degrees, where each range specifies how much you expect the pattern to be rotated in the image.
+    int                 numRanges;           //Number of angle ranges in the angleRanges array.
+    double              colorWeight;         //Determines the percent contribution of the color score to the final color pattern matching score.
+    ColorSensitivity    sensitivity;         //Specifies the sensitivity of the color information in the image.
+    SearchStrategy      strategy;            //Specifies how the color features of the image are used during the search phase.
+    int                 numMatchesRequested; //Number of valid matches expected.
+    float               minMatchScore;       //The minimum score a match can have for the function to consider the match valid.
+} MatchColorPatternOptions;
+
+typedef struct HistogramReport_struct {
+    int*  histogram;      //An array describing the number of pixels that fell into each class.
+    int   histogramCount; //The number of elements in the histogram array.
+    float min;            //The smallest pixel value that the function classified.
+    float max;            //The largest pixel value that the function classified.
+    float start;          //The smallest pixel value that fell into the first class.
+    float width;          //The size of each class.
+    float mean;           //The mean value of the pixels that the function classified.
+    float stdDev;         //The standard deviation of the pixels that the function classified.
+    int   numPixels;      //The number of pixels that the function classified.
+} HistogramReport;
+
+typedef struct ArcInfo_struct {
+    Rect   boundingBox; //The coordinate location of the bounding box of the arc.
+    double startAngle;  //The counterclockwise angle from the x-axis in degrees to the start of the arc.
+    double endAngle;    //The counterclockwise angle from the x-axis in degrees to the end of the arc.
+} ArcInfo;
+
+typedef struct AxisReport_struct {
+    PointFloat origin;           //The origin of the coordinate system, which is the intersection of the two axes of the coordinate system.
+    PointFloat mainAxisEnd;      //The end of the main axis, which is the result of the computation of the intersection of the main axis with the rectangular search area.
+    PointFloat secondaryAxisEnd; //The end of the secondary axis, which is the result of the computation of the intersection of the secondary axis with the rectangular search area.
+} AxisReport;
+
+typedef struct BarcodeInfo_struct {
+    const char* outputString;    //A string containing the decoded barcode data.
+    int         size;            //The size of the output string.
+    char        outputChar1;     //The contents of this character depend on the barcode type.
+    char        outputChar2;     //The contents of this character depend on the barcode type.
+    double      confidenceLevel; //A quality measure of the decoded barcode ranging from 0 to 100, with 100 being the best.
+    BarcodeType type;            //The type of barcode.
+} BarcodeInfo;
+
+typedef struct BCGOptions_struct {
+    float brightness; //Adjusts the brightness of the image.
+    float contrast;   //Adjusts the contrast of the image.
+    float gamma;      //Performs gamma correction.
+} BCGOptions;
+
+typedef struct BestCircle_struct {
+    PointFloat center;    //The coordinate location of the center of the circle.
+    double     radius;    //The radius of the circle.
+    double     area;      //The area of the circle.
+    double     perimeter; //The length of the perimeter of the circle.
+    double     error;     //Represents the least square error of the fitted circle to the entire set of points.
+} BestCircle;
+
+typedef struct BestEllipse_struct {
+    PointFloat center;         //The coordinate location of the center of the ellipse.
+    PointFloat majorAxisStart; //The coordinate location of the start of the major axis of the ellipse.
+    PointFloat majorAxisEnd;   //The coordinate location of the end of the major axis of the ellipse.
+    PointFloat minorAxisStart; //The coordinate location of the start of the minor axis of the ellipse.
+    PointFloat minorAxisEnd;   //The coordinate location of the end of the minor axis of the ellipse.
+    double     area;           //The area of the ellipse.
+    double     perimeter;      //The length of the perimeter of the ellipse.
+} BestEllipse;
+
+typedef struct BestLine_struct {
+    PointFloat   start;         //The coordinate location of the start of the line.
+    PointFloat   end;           //The coordinate location of the end of the line.
+    LineEquation equation;      //Defines the three coefficients of the equation of the best fit line.
+    int          valid;         //This element is TRUE if the function achieved the minimum score within the number of allowed refinement iterations and FALSE if the function did not achieve the minimum score.
+    double       error;         //Represents the least square error of the fitted line to the entire set of points.
+    int*         pointsUsed;    //An array of the indexes for the points array indicating which points the function used to fit the line.
+    int          numPointsUsed; //The number of points the function used to fit the line.
+} BestLine;
+
+typedef struct BrowserOptions_struct {
+    int               width;           //The width to make the browser.
+    int               height;          //The height to make the browser image.
+    int               imagesPerLine;   //The number of images to place on a single line.
+    RGBValue          backgroundColor; //The background color of the browser.
+    int               frameSize;       //Specifies the number of pixels with which to border each thumbnail.
+    BrowserFrameStyle style;           //The style for the frame around each thumbnail.
+    float             ratio;           //Specifies the width to height ratio of each thumbnail.
+    RGBValue          focusColor;      //The color to use to display focused cells.
+} BrowserOptions;
+
+typedef struct CoordinateSystem_struct {
+    PointFloat      origin;          //The origin of the coordinate system.
+    float           angle;           //The angle, in degrees, of the x-axis of the coordinate system relative to the image x-axis.
+    AxisOrientation axisOrientation; //The direction of the y-axis of the coordinate reference system.
+} CoordinateSystem;
+
+typedef struct CalibrationInfo_struct {
+    float*                  errorMap;       //The error map for the calibration.
+    int                     mapColumns;     //The number of columns in the error map.
+    int                     mapRows;        //The number of rows in the error map.
+    ROI*                    userRoi;        //Specifies the ROI the user provided when learning the calibration.
+    ROI*                    calibrationRoi; //Specifies the ROI that corresponds to the region of the image where the calibration information is accurate.
+    LearnCalibrationOptions options;        //Specifies the calibration options the user provided when learning the calibration.
+    GridDescriptor          grid;           //Specifies the scaling constants for the image.
+    CoordinateSystem        system;         //Specifies the coordinate system for the real world coordinates.
+    RangeFloat              range;          //The range of the grayscale the function used to represent the circles in the grid image.
+    float                   quality;        //The quality score of the learning process, which is a value between 0-1000.
+} CalibrationInfo;
+
+typedef struct CalibrationPoints_struct {
+    PointFloat* pixelCoordinates;     //The array of pixel coordinates.
+    PointFloat* realWorldCoordinates; //The array of corresponding real-world coordinates.
+    int         numCoordinates;       //The number of coordinates in both of the arrays.
+} CalibrationPoints;
+
+typedef struct CaliperOptions_struct {
+    TwoEdgePolarityType polarity;            //Specifies the edge polarity of the edge pairs.
+    float               separation;          //The distance between edge pairs.
+    float               separationDeviation; //Sets the range around the separation value.
+} CaliperOptions;
+
+typedef struct CaliperReport_struct {
+    float      edge1Contrast; //The contrast of the first edge.
+    PointFloat edge1Coord;    //The coordinates of the first edge.
+    float      edge2Contrast; //The contrast of the second edge.
+    PointFloat edge2Coord;    //The coordinates of the second edge.
+    float      separation;    //The distance between the two edges.
+    float      reserved;      //This element is reserved.
+} CaliperReport;
+
+typedef struct DrawTextOptions_struct {
+    char          fontName[32];  //The font name to use.
+    int           fontSize;      //The size of the font.
+    int           bold;          //Set this parameter to TRUE to bold text.
+    int           italic;        //Set this parameter to TRUE to italicize text.
+    int           underline;     //Set this parameter to TRUE to underline text.
+    int           strikeout;     //Set this parameter to TRUE to strikeout text.
+    TextAlignment textAlignment; //Sets the alignment of text.
+    FontColor     fontColor;     //Sets the font color.
+} DrawTextOptions;
+
+typedef struct CircleReport_struct {
+    Point center; //The coordinate point of the center of the circle.
+    int   radius; //The radius of the circle, in pixels.
+    int   area;   //The area of the circle, in pixels.
+} CircleReport;
+
+typedef struct ClosedContour_struct {
+    Point* points;    //The points that make up the closed contour.
+    int    numPoints; //The number of points in the array.
+} ClosedContour;
+
+typedef struct ColorHistogramReport_struct {
+    HistogramReport plane1; //The histogram report of the first color plane.
+    HistogramReport plane2; //The histogram report of the second plane.
+    HistogramReport plane3; //The histogram report of the third plane.
+} ColorHistogramReport;
+
+typedef struct ColorInformation_struct {
+    int     infoCount;  //The size of the info array.
+    int     saturation; //The saturation level the function uses to learn the color information.
+    double* info;       //An array of color information that represents the color spectrum analysis of a region of an image in a compact form.
+} ColorInformation;
+
+typedef struct Complex_struct {
+    float r; //The real part of the value.
+    float i; //The imaginary part of the value.
+} Complex;
+
+typedef struct ConcentricRakeReport_struct {
+    ArcInfo*            rakeArcs;          //An array containing the location of each concentric arc line used for edge detection.
+    int                 numArcs;           //The number of arc lines in the rakeArcs array.
+    PointFloat*         firstEdges;        //The coordinate location of all edges detected as first edges.
+    int                 numFirstEdges;     //The number of points in the first edges array.
+    PointFloat*         lastEdges;         //The coordinate location of all edges detected as last edges.
+    int                 numLastEdges;      //The number of points in the last edges array.
+    EdgeLocationReport* allEdges;          //An array of reports describing the location of the edges located by each concentric rake arc line.
+    int*                linesWithEdges;    //An array of indices into the rakeArcs array indicating the concentric rake arc lines on which the function detected at least one edge.
+    int                 numLinesWithEdges; //The number of concentric rake arc lines along which the function detected edges.
+} ConcentricRakeReport;
+
+typedef struct ConstructROIOptions_struct {
+    int         windowNumber; //The window number of the image window.
+    const char* windowTitle;  //Specifies the message string that the function displays in the title bar of the window.
+    PaletteType type;         //The palette type to use.
+    RGBValue*   palette;      //If type is IMAQ_PALETTE_USER, this array is the palette of colors to use with the window.
+    int         numColors;    //If type is IMAQ_PALETTE_USER, this element is the number of colors in the palette array.
+} ConstructROIOptions;
+
+typedef struct ContourInfo_struct {
+    ContourType type;         //The contour type.
+    unsigned    numPoints;    //The number of points that make up the contour.
+    Point*      points;       //The points describing the contour.
+    RGBValue    contourColor; //The contour color.
+} ContourInfo;
+
+typedef union ContourUnion_union {
+    Point*         point;           //Use this member when the contour is of type IMAQ_POINT.
+    Line*          line;            //Use this member when the contour is of type IMAQ_LINE.
+    Rect*          rect;            //Use this member when the contour is of type IMAQ_RECT.
+    Rect*          ovalBoundingBox; //Use this member when the contour is of type IMAQ_OVAL.
+    ClosedContour* closedContour;   //Use this member when the contour is of type IMAQ_CLOSED_CONTOUR.
+    OpenContour*   openContour;     //Use this member when the contour is of type IMAQ_OPEN_CONTOUR.
+    Annulus*       annulus;         //Use this member when the contour is of type IMAQ_ANNULUS.
+    RotatedRect*   rotatedRect;     //Use this member when the contour is of type IMAQ_ROTATED_RECT.
+} ContourUnion;
+
+typedef struct ContourInfo2_struct {
+    ContourType  type;      //The contour type.
+    RGBValue     color;     //The contour color.
+    ContourUnion structure; //The information necessary to describe the contour in coordinate space.
+} ContourInfo2;
+
+typedef struct ContourPoint_struct {
+    double x;             //The x-coordinate value in the image.
+    double y;             //The y-coordinate value in the image.
+    double curvature;     //The change in slope at this edge point of the segment.
+    double xDisplacement; //The x displacement of the current edge pixel from a cubic spline fit of the current edge segment.
+    double yDisplacement; //The y displacement of the current edge pixel from a cubic spline fit of the current edge segment.
+} ContourPoint;
+
+typedef struct CoordinateTransform_struct {
+    Point initialOrigin; //The origin of the initial coordinate system.
+    float initialAngle;  //The angle, in degrees, of the x-axis of the initial coordinate system relative to the image x-axis.
+    Point finalOrigin;   //The origin of the final coordinate system.
+    float finalAngle;    //The angle, in degrees, of the x-axis of the final coordinate system relative to the image x-axis.
+} CoordinateTransform;
+
+typedef struct CoordinateTransform2_struct {
+    CoordinateSystem referenceSystem;   //Defines the coordinate system for input coordinates.
+    CoordinateSystem measurementSystem; //Defines the coordinate system in which the function should perform measurements.
+} CoordinateTransform2;
+
+typedef struct CannyOptions_struct {
+    float sigma;          //The sigma of the Gaussian smoothing filter that the function applies to the image before edge detection.
+    float upperThreshold; //The upper fraction of pixel values in the image from which the function chooses a seed or starting point of an edge segment.
+    float lowerThreshold; //The function multiplies this value by upperThreshold to determine the lower threshold for all the pixels in an edge segment.
+    int   windowSize;     //The window size of the Gaussian filter that the function applies to the image.
+} CannyOptions;
+
+typedef struct Range_struct {
+    int minValue; //The minimum value of the range.
+    int maxValue; //The maximum value of the range.
+} Range;
+
+typedef struct UserPointSymbol_struct {
+    int  cols;   //Number of columns in the symbol.
+    int  rows;   //Number of rows in the symbol.
+    int* pixels; //The pixels of the symbol.
+} UserPointSymbol;
+
+typedef struct View3DOptions_struct {
+    int         sizeReduction; //A divisor the function uses when determining the final height and width of the 3D image.
+    int         maxHeight;     //Defines the maximum height of a pixel from the image source drawn in 3D.
+    Direction3D direction;     //Defines the 3D orientation.
+    float       alpha;         //Determines the angle between the horizontal and the baseline.
+    float       beta;          //Determines the angle between the horizontal and the second baseline.
+    int         border;        //Defines the border size.
+    int         background;    //Defines the background color.
+    Plane3D     plane;         //Indicates the view a function uses to show complex images.
+} View3DOptions;
+
+typedef struct MatchPatternOptions_struct {
+    MatchingMode        mode;                //Specifies the method to use when looking for the pattern in the image.
+    int                 minContrast;         //Specifies the minimum contrast expected in the image.
+    int                 subpixelAccuracy;    //Set this element to TRUE to return areas in the image that match the pattern area with subpixel accuracy.
+    RotationAngleRange* angleRanges;         //An array of angle ranges, in degrees, where each range specifies how much you expect the pattern to be rotated in the image.
+    int                 numRanges;           //Number of angle ranges in the angleRanges array.
+    int                 numMatchesRequested; //Number of valid matches expected.
+    int                 matchFactor;         //Controls the number of potential matches that the function examines.
+    float               minMatchScore;       //The minimum score a match can have for the function to consider the match valid.
+} MatchPatternOptions;
+
+typedef struct TIFFFileOptions_struct {
+    int                 rowsPerStrip;    //Indicates the number of rows that the function writes per strip.
+    PhotometricMode     photoInterp;     //Designates which photometric interpretation to use.
+    TIFFCompressionType compressionType; //Indicates the type of compression to use on the TIFF file.
+} TIFFFileOptions;
+
+typedef union Color_union {
+    RGBValue rgb;      //The information needed to describe a color in the RGB (Red, Green, and Blue) color space.
+    HSLValue hsl;      //The information needed to describe a color in the HSL (Hue, Saturation, and Luminance) color space.
+    HSVValue hsv;      //The information needed to describe a color in the HSI (Hue, Saturation, and Value) color space.
+    HSIValue hsi;      //The information needed to describe a color in the HSI (Hue, Saturation, and Intensity) color space.
+    int      rawValue; //The integer value for the data in the color union.
+} Color;
+
+typedef union PixelValue_union {
+    float       grayscale; //A grayscale pixel value.
+    RGBValue    rgb;       //A RGB pixel value.
+    HSLValue    hsl;       //A HSL pixel value.
+    Complex     complex;   //A complex pixel value.
+    RGBU64Value rgbu64;    //An unsigned 64-bit RGB pixel value.
+} PixelValue;
+
+typedef struct OpenContour_struct {
+    Point* points;    //The points that make up the open contour.
+    int    numPoints; //The number of points in the array.
+} OpenContour;
+
+typedef struct OverlayTextOptions_struct {
+    const char*           fontName;                //The name of the font to use.
+    int                   fontSize;                //The size of the font.
+    int                   bold;                    //Set this element to TRUE to bold the text.
+    int                   italic;                  //Set this element to TRUE to italicize the text.
+    int                   underline;               //Set this element to TRUE to underline the text.
+    int                   strikeout;               //Set this element to TRUE to strikeout the text.
+    TextAlignment         horizontalTextAlignment; //Sets the alignment of the text.
+    VerticalTextAlignment verticalTextAlignment;   //Sets the vertical alignment for the text.
+    RGBValue              backgroundColor;         //Sets the color for the text background pixels.
+    double                angle;                   //The counterclockwise angle, in degrees, of the text relative to the x-axis.
+} OverlayTextOptions;
+
+typedef struct ParticleFilterCriteria_struct {
+    MeasurementValue parameter; //The morphological measurement that the function uses for filtering.
+    float            lower;     //The lower bound of the criteria range.
+    float            upper;     //The upper bound of the criteria range.
+    int              exclude;   //Set this element to TRUE to indicate that a match occurs when the value is outside the criteria range.
+} ParticleFilterCriteria;
+
+typedef struct ParticleReport_struct {
+    int   area;             //The number of pixels in the particle.
+    float calibratedArea;   //The size of the particle, calibrated to the calibration information of the image.
+    float perimeter;        //The length of the perimeter, calibrated to the calibration information of the image.
+    int   numHoles;         //The number of holes in the particle.
+    int   areaOfHoles;      //The total surface area, in pixels, of all the holes in a particle.
+    float perimeterOfHoles; //The length of the perimeter of all the holes in the particle calibrated to the calibration information of the image.
+    Rect  boundingBox;      //The smallest rectangle that encloses the particle.
+    float sigmaX;           //The sum of the particle pixels on the x-axis.
+    float sigmaY;           //The sum of the particle pixels on the y-axis.
+    float sigmaXX;          //The sum of the particle pixels on the x-axis, squared.
+    float sigmaYY;          //The sum of the particle pixels on the y-axis, squared.
+    float sigmaXY;          //The sum of the particle pixels on the x-axis and y-axis.
+    int   longestLength;    //The length of the longest horizontal line segment.
+    Point longestPoint;     //The location of the leftmost pixel of the longest segment in the particle.
+    int   projectionX;      //The length of the particle when projected onto the x-axis.
+    int   projectionY;      //The length of the particle when projected onto the y-axis.
+    int   connect8;         //This element is TRUE if the function used connectivity-8 to determine if particles are touching.
+} ParticleReport;
+
+typedef struct PatternMatch_struct {
+    PointFloat position;  //The location of the center of the match.
+    float      rotation;  //The rotation of the match relative to the template image, in degrees.
+    float      scale;     //The size of the match relative to the size of the template image, expressed as a percentage.
+    float      score;     //The accuracy of the match.
+    PointFloat corner[4]; //An array of four points describing the rectangle surrounding the template image.
+} PatternMatch;
+
+typedef struct QuantifyData_struct {
+    float mean;           //The mean value of the pixel values.
+    float stdDev;         //The standard deviation of the pixel values.
+    float min;            //The smallest pixel value.
+    float max;            //The largest pixel value.
+    float calibratedArea; //The area, calibrated to the calibration information of the image.
+    int   pixelArea;      //The area, in number of pixels.
+    float relativeSize;   //The proportion, expressed as a percentage, of the associated region relative to the whole image.
+} QuantifyData;
+
+typedef struct QuantifyReport_struct {
+    QuantifyData  global;      //Statistical data of the whole image.
+    QuantifyData* regions;     //An array of QuantifyData structures containing statistical data of each region of the image.
+    int           regionCount; //The number of regions.
+} QuantifyReport;
+
+typedef struct RakeOptions_struct {
+    int                 threshold;         //Specifies the threshold value for the contrast of the edge.
+    int                 width;             //The number of pixels that the function averages to find the contrast at either side of the edge.
+    int                 steepness;         //The span, in pixels, of the slope of the edge projected along the path specified by the input points.
+    int                 subsamplingRatio;  //Specifies the number of pixels that separate two consecutive search lines.
+    InterpolationMethod subpixelType;      //The method for interpolating.
+    int                 subpixelDivisions; //The number of samples the function obtains from a pixel.
+} RakeOptions;
+
+typedef struct RakeReport_struct {
+    LineFloat*          rakeLines;         //The coordinate location of each of the rake lines used by the function.
+    int                 numRakeLines;      //The number of lines in the rakeLines array.
+    PointFloat*         firstEdges;        //The coordinate location of all edges detected as first edges.
+    unsigned int        numFirstEdges;     //The number of points in the firstEdges array.
+    PointFloat*         lastEdges;         //The coordinate location of all edges detected as last edges.
+    unsigned int        numLastEdges;      //The number of points in the lastEdges array.
+    EdgeLocationReport* allEdges;          //An array of reports describing the location of the edges located by each rake line.
+    int*                linesWithEdges;    //An array of indices into the rakeLines array indicating the rake lines on which the function detected at least one edge.
+    int                 numLinesWithEdges; //The number of rake lines along which the function detected edges.
+} RakeReport;
+
+typedef struct TransformReport_struct {
+    PointFloat* points;      //An array of transformed coordinates.
+    int*        validPoints; //An array of values that describe the validity of each of the coordinates according to the region of interest you calibrated using either imaqLearnCalibrationGrid() or imaqLearnCalibrationPoints().
+    int         numPoints;   //The length of both the points array and the validPoints array.
+} TransformReport;
+
+typedef struct ShapeReport_struct {
+    Rect   coordinates; //The bounding rectangle of the object.
+    Point  centroid;    //The coordinate location of the centroid of the object.
+    int    size;        //The size, in pixels, of the object.
+    double score;       //A value ranging between 1 and 1,000 that specifies how similar the object in the image is to the template.
+} ShapeReport;
+
+typedef struct MeterArc_struct {
+    PointFloat  needleBase;          //The coordinate location of the base of the meter needle.
+    PointFloat* arcCoordPoints;      //An array of points describing the coordinate location of the meter arc.
+    int         numOfArcCoordPoints; //The number of points in the arcCoordPoints array.
+    int         needleColor;         //This element is TRUE when the meter has a light-colored needle on a dark background.
+} MeterArc;
+
+typedef struct ThresholdData_struct {
+    float rangeMin;    //The lower boundary of the range to keep.
+    float rangeMax;    //The upper boundary of the range to keep.
+    float newValue;    //If useNewValue is TRUE, newValue is the replacement value for pixels within the range.
+    int   useNewValue; //If TRUE, the function sets pixel values within [rangeMin, rangeMax] to the value specified in newValue.
+} ThresholdData;
+
+typedef struct StructuringElement_struct {
+    int  matrixCols; //Number of columns in the matrix.
+    int  matrixRows; //Number of rows in the matrix.
+    int  hexa;       //Set this element to TRUE if you specify a hexagonal structuring element in kernel.
+    int* kernel;     //The values of the structuring element.
+} StructuringElement;
+
+typedef struct SpokeReport_struct {
+    LineFloat*          spokeLines;        //The coordinate location of each of the spoke lines used by the function.
+    int                 numSpokeLines;     //The number of lines in the spokeLines array.
+    PointFloat*         firstEdges;        //The coordinate location of all edges detected as first edges.
+    int                 numFirstEdges;     //The number of points in the firstEdges array.
+    PointFloat*         lastEdges;         //The coordinate location of all edges detected as last edges.
+    int                 numLastEdges;      //The number of points in the lastEdges array.
+    EdgeLocationReport* allEdges;          //An array of reports describing the location of the edges located by each spoke line.
+    int*                linesWithEdges;    //An array of indices into the spokeLines array indicating the rake lines on which the function detected at least one edge.
+    int                 numLinesWithEdges; //The number of spoke lines along which the function detects edges.
+} SpokeReport;
+
+typedef struct SimpleEdgeOptions_struct {
+    LevelType   type;       //Determines how the function evaluates the threshold and hysteresis values.
+    int         threshold;  //The pixel value at which an edge occurs.
+    int         hysteresis; //A value that helps determine edges in noisy images.
+    EdgeProcess process;    //Determines which edges the function looks for.
+    int         subpixel;   //Set this element to TRUE to find edges with subpixel accuracy by interpolating between points to find the crossing of the given threshold.
+} SimpleEdgeOptions;
+
+typedef struct SelectParticleCriteria_struct {
+    MeasurementValue parameter; //The morphological measurement that the function uses for filtering.
+    float            lower;     //The lower boundary of the criteria range.
+    float            upper;     //The upper boundary of the criteria range.
+} SelectParticleCriteria;
+
+typedef struct SegmentInfo_struct {
+    int           numberOfPoints; //The number of points in the segment.
+    int           isOpen;         //If TRUE, the contour is open.
+    double        weight;         //The significance of the edge in terms of the gray values that constitute the edge.
+    ContourPoint* points;         //The points of the segment.
+} SegmentInfo;
+
+typedef struct RotationAngleRange_struct {
+    float lower; //The lowest amount of rotation, in degrees, a valid pattern can have.
+    float upper; //The highest amount of rotation, in degrees, a valid pattern can have.
+} RotationAngleRange;
+
+typedef struct RotatedRect_struct {
+    int    top;    //Location of the top edge of the rectangle before rotation.
+    int    left;   //Location of the left edge of the rectangle before rotation.
+    int    height; //Height of the rectangle.
+    int    width;  //Width of the rectangle.
+    double angle;  //The rotation, in degrees, of the rectangle.
+} RotatedRect;
+
+typedef struct ROIProfile_struct {
+    LineProfile report; //Quantifying information about the points along the edge of each contour in the ROI.
+    Point*      pixels; //An array of the points along the edge of each contour in the ROI.
+} ROIProfile;
+
+typedef struct ToolWindowOptions_struct {
+    int showSelectionTool;        //If TRUE, the selection tool becomes visible.
+    int showZoomTool;             //If TRUE, the zoom tool becomes visible.
+    int showPointTool;            //If TRUE, the point tool becomes visible.
+    int showLineTool;             //If TRUE, the line tool becomes visible.
+    int showRectangleTool;        //If TRUE, the rectangle tool becomes visible.
+    int showOvalTool;             //If TRUE, the oval tool becomes visible.
+    int showPolygonTool;          //If TRUE, the polygon tool becomes visible.
+    int showClosedFreehandTool;   //If TRUE, the closed freehand tool becomes visible.
+    int showPolyLineTool;         //If TRUE, the polyline tool becomes visible.
+    int showFreehandTool;         //If TRUE, the freehand tool becomes visible.
+    int showAnnulusTool;          //If TRUE, the annulus becomes visible.
+    int showRotatedRectangleTool; //If TRUE, the rotated rectangle tool becomes visible.
+    int showPanTool;              //If TRUE, the pan tool becomes visible.
+    int showZoomOutTool;          //If TRUE, the zoom out tool becomes visible.
+    int reserved2;                //This element is reserved and should be set to FALSE.
+    int reserved3;                //This element is reserved and should be set to FALSE.
+    int reserved4;                //This element is reserved and should be set to FALSE.
+} ToolWindowOptions;
+
+typedef struct SpokeOptions_struct {
+    int                 threshold;         //Specifies the threshold value for the contrast of the edge.
+    int                 width;             //The number of pixels that the function averages to find the contrast at either side of the edge.
+    int                 steepness;         //The span, in pixels, of the slope of the edge projected along the path specified by the input points.
+    double              subsamplingRatio;  //The angle, in degrees, between each radial search line in the spoke.
+    InterpolationMethod subpixelType;      //The method for interpolating.
+    int                 subpixelDivisions; //The number of samples the function obtains from a pixel.
+} SpokeOptions;
+
+#if !defined __GNUC__ && !defined _M_X64
+#pragma pack(pop)
+#endif
+
+//============================================================================
+// Callback Function Type
+//============================================================================
+#ifndef __GNUC__
+typedef void (IMAQ_CALLBACK* EventCallback)(WindowEventType event, int windowNumber, Tool tool, Rect rect);
+#endif
+
+//============================================================================
+//  Globals
+//============================================================================
+#ifndef __GNUC__
+#pragma const_seg("IMAQVisionColorConstants")
+#endif
+static const RGBValue IMAQ_RGB_TRANSPARENT = {   0,   0,   0, 1 };
+static const RGBValue IMAQ_RGB_RED         = {   0,   0, 255, 0 };
+static const RGBValue IMAQ_RGB_BLUE        = { 255,   0,   0, 0 };
+static const RGBValue IMAQ_RGB_GREEN       = {   0, 255,   0, 0 };
+static const RGBValue IMAQ_RGB_YELLOW      = {   0, 255, 255, 0 };
+static const RGBValue IMAQ_RGB_WHITE       = { 255, 255, 255, 0 };
+static const RGBValue IMAQ_RGB_BLACK       = {   0,   0,   0, 0 };
+#ifndef __GNUC__
+#pragma const_seg()
+#endif
+
+//============================================================================
+//  Backwards Compatibility
+//============================================================================
+typedef ColorSensitivity 		ColorComplexity;
+#define IMAQ_COMPLEXITY_LOW 		IMAQ_SENSITIVITY_LOW
+#define IMAQ_COMPLEXITY_MED 		IMAQ_SENSITIVITY_MED     
+#define IMAQ_COMPLEXITY_HIGH 		IMAQ_SENSITIVITY_HIGH
+#define ERR_INVALID_COLORCOMPLEXITY 	ERR_INVALID_COLORSENSITIVITY
+
+//============================================================================
+//  Logical functions
+//============================================================================
+IMAQ_FUNC int IMAQ_STDCALL imaqAnd(Image* dest, const Image* sourceA, const Image* sourceB);
+IMAQ_FUNC int IMAQ_STDCALL imaqAndConstant(Image* dest, const Image* source, PixelValue value);
+IMAQ_FUNC int IMAQ_STDCALL imaqCompare(Image* dest, const Image* source, const Image* compareImage, ComparisonFunction compare);
+IMAQ_FUNC int IMAQ_STDCALL imaqCompareConstant(Image* dest, const Image* source, PixelValue value, ComparisonFunction compare);
+IMAQ_FUNC int IMAQ_STDCALL imaqLogicalDifference(Image* dest, const Image* sourceA, const Image* sourceB);
+IMAQ_FUNC int IMAQ_STDCALL imaqLogicalDifferenceConstant(Image* dest, const Image* source, PixelValue value);
+IMAQ_FUNC int IMAQ_STDCALL imaqNand(Image* dest, const Image* sourceA, const Image* sourceB);
+IMAQ_FUNC int IMAQ_STDCALL imaqNandConstant(Image* dest, const Image* source, PixelValue value);
+IMAQ_FUNC int IMAQ_STDCALL imaqNor(Image* dest, const Image* sourceA, const Image* sourceB);
+IMAQ_FUNC int IMAQ_STDCALL imaqNorConstant(Image* dest, const Image* source, PixelValue value);
+IMAQ_FUNC int IMAQ_STDCALL imaqOr(Image* dest, const Image* sourceA, const Image* sourceB);
+IMAQ_FUNC int IMAQ_STDCALL imaqOrConstant(Image* dest, const Image* source, PixelValue value);
+IMAQ_FUNC int IMAQ_STDCALL imaqXnor(Image* dest, const Image* sourceA, const Image* sourceB);
+IMAQ_FUNC int IMAQ_STDCALL imaqXnorConstant(Image* dest, const Image* source, PixelValue value);
+IMAQ_FUNC int IMAQ_STDCALL imaqXor(Image* dest, const Image* sourceA, const Image* sourceB);
+IMAQ_FUNC int IMAQ_STDCALL imaqXorConstant(Image* dest, const Image* source, PixelValue value);
+
+//============================================================================
+//  Particle Analysis functions
+//============================================================================
+IMAQ_FUNC int                     IMAQ_STDCALL imaqCountParticles(Image* image, int connectivity8, int* numParticles);
+IMAQ_FUNC int                     IMAQ_STDCALL imaqMeasureParticle(Image* image, int particleNumber, int calibrated, MeasurementType measurement, double* value);
+IMAQ_FUNC MeasureParticlesReport* IMAQ_STDCALL imaqMeasureParticles(Image* image, MeasureParticlesCalibrationMode calibrationMode, const MeasurementType* measurements, size_t numMeasurements);
+IMAQ_FUNC int                     IMAQ_STDCALL imaqParticleFilter4(Image* dest, Image* source, const ParticleFilterCriteria2* criteria, int criteriaCount, const ParticleFilterOptions2* options, const ROI* roi, int* numParticles);
+
+//============================================================================
+//  Morphology functions
+//============================================================================
+IMAQ_FUNC int           IMAQ_STDCALL imaqConvexHull(Image* dest, Image* source, int connectivity8);
+IMAQ_FUNC int           IMAQ_STDCALL imaqDanielssonDistance(Image* dest, Image* source);
+IMAQ_FUNC int           IMAQ_STDCALL imaqFillHoles(Image* dest, const Image* source, int connectivity8);
+IMAQ_FUNC CircleReport* IMAQ_STDCALL imaqFindCircles(Image* dest, Image* source, float minRadius, float maxRadius, int* numCircles);
+IMAQ_FUNC int           IMAQ_STDCALL imaqLabel2(Image* dest, Image* source, int connectivity8, int* particleCount);
+IMAQ_FUNC int           IMAQ_STDCALL imaqMorphology(Image* dest, Image* source, MorphologyMethod method, const StructuringElement* structuringElement);
+IMAQ_FUNC int           IMAQ_STDCALL imaqRejectBorder(Image* dest, Image* source, int connectivity8);
+IMAQ_FUNC int           IMAQ_STDCALL imaqSegmentation(Image* dest, Image* source);
+IMAQ_FUNC int           IMAQ_STDCALL imaqSeparation(Image* dest, Image* source, int erosions, const StructuringElement* structuringElement);
+IMAQ_FUNC int           IMAQ_STDCALL imaqSimpleDistance(Image* dest, Image* source, const StructuringElement* structuringElement);
+IMAQ_FUNC int           IMAQ_STDCALL imaqSizeFilter(Image* dest, Image* source, int connectivity8, int erosions, SizeType keepSize, const StructuringElement* structuringElement);
+IMAQ_FUNC int           IMAQ_STDCALL imaqSkeleton(Image* dest, Image* source, SkeletonMethod method);
+
+
+//============================================================================
+//  Acquisition functions
+//============================================================================
+IMAQ_FUNC Image* IMAQ_STDCALL imaqCopyFromRing(SESSION_ID sessionID, Image* image, int imageToCopy, int* imageNumber, Rect rect);
+IMAQ_FUNC Image* IMAQ_STDCALL imaqEasyAcquire(const char* interfaceName);
+IMAQ_FUNC Image* IMAQ_STDCALL imaqExtractFromRing(SESSION_ID sessionID, int imageToExtract, int* imageNumber);
+IMAQ_FUNC Image* IMAQ_STDCALL imaqGrab(SESSION_ID sessionID, Image* image, int immediate);
+IMAQ_FUNC int    IMAQ_STDCALL imaqReleaseImage(SESSION_ID sessionID);
+IMAQ_FUNC int    IMAQ_STDCALL imaqSetupGrab(SESSION_ID sessionID, Rect rect);
+IMAQ_FUNC int    IMAQ_STDCALL imaqSetupRing(SESSION_ID sessionID, Image** images, int numImages, int skipCount, Rect rect);
+IMAQ_FUNC int    IMAQ_STDCALL imaqSetupSequence(SESSION_ID sessionID, Image** images, int numImages, int skipCount, Rect rect);
+IMAQ_FUNC Image* IMAQ_STDCALL imaqSnap(SESSION_ID sessionID, Image* image, Rect rect);
+IMAQ_FUNC int    IMAQ_STDCALL imaqStartAcquisition(SESSION_ID sessionID);
+IMAQ_FUNC int    IMAQ_STDCALL imaqStopAcquisition(SESSION_ID sessionID);
+
+//============================================================================
+//  Arithmetic functions
+//============================================================================
+IMAQ_FUNC int IMAQ_STDCALL imaqAbsoluteDifference(Image* dest, const Image* sourceA, const Image* sourceB);
+IMAQ_FUNC int IMAQ_STDCALL imaqAbsoluteDifferenceConstant(Image* dest, const Image* source, PixelValue value);
+IMAQ_FUNC int IMAQ_STDCALL imaqAdd(Image* dest, const Image* sourceA, const Image* sourceB);
+IMAQ_FUNC int IMAQ_STDCALL imaqAddConstant(Image* dest, const Image* source, PixelValue value);
+IMAQ_FUNC int IMAQ_STDCALL imaqAverage(Image* dest, const Image* sourceA, const Image* sourceB);
+IMAQ_FUNC int IMAQ_STDCALL imaqAverageConstant(Image* dest, const Image* source, PixelValue value);
+IMAQ_FUNC int IMAQ_STDCALL imaqDivide2(Image* dest, const Image* sourceA, const Image* sourceB, RoundingMode roundingMode);
+IMAQ_FUNC int IMAQ_STDCALL imaqDivideConstant2(Image* dest, const Image* source, PixelValue value, RoundingMode roundingMode);
+IMAQ_FUNC int IMAQ_STDCALL imaqMax(Image* dest, const Image* sourceA, const Image* sourceB);
+IMAQ_FUNC int IMAQ_STDCALL imaqMaxConstant(Image* dest, const Image* source, PixelValue value);
+IMAQ_FUNC int IMAQ_STDCALL imaqMin(Image* dest, const Image* sourceA, const Image* sourceB);
+IMAQ_FUNC int IMAQ_STDCALL imaqMinConstant(Image* dest, const Image* source, PixelValue value);
+IMAQ_FUNC int IMAQ_STDCALL imaqModulo(Image* dest, const Image* sourceA, const Image* sourceB);
+IMAQ_FUNC int IMAQ_STDCALL imaqModuloConstant(Image* dest, const Image* source, PixelValue value);
+IMAQ_FUNC int IMAQ_STDCALL imaqMulDiv(Image* dest, const Image* sourceA, const Image* sourceB, float value);
+IMAQ_FUNC int IMAQ_STDCALL imaqMultiply(Image* dest, const Image* sourceA, const Image* sourceB);
+IMAQ_FUNC int IMAQ_STDCALL imaqMultiplyConstant(Image* dest, const Image* source, PixelValue value);
+IMAQ_FUNC int IMAQ_STDCALL imaqSubtract(Image* dest, const Image* sourceA, const Image* sourceB);
+IMAQ_FUNC int IMAQ_STDCALL imaqSubtractConstant(Image* dest, const Image* source, PixelValue value);
+
+//============================================================================
+//  Caliper functions
+//============================================================================
+IMAQ_FUNC CaliperReport*         IMAQ_STDCALL imaqCaliperTool(const Image* image, const Point* points, int numPoints, const EdgeOptions* edgeOptions, const CaliperOptions* caliperOptions, int* numEdgePairs);
+IMAQ_FUNC ConcentricRakeReport2* IMAQ_STDCALL imaqConcentricRake2(Image* image, ROI* roi, ConcentricRakeDirection direction, EdgeProcess process, int stepSize, EdgeOptions2* edgeOptions);
+IMAQ_FUNC ExtremeReport*         IMAQ_STDCALL imaqDetectExtremes(const double* pixels, int numPixels, DetectionMode mode, const DetectExtremesOptions* options, int* numExtremes);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqDetectRotation(const Image* referenceImage, const Image* testImage, PointFloat referenceCenter, PointFloat testCenter, int radius, float precision, double* angle);
+IMAQ_FUNC EdgeReport2*           IMAQ_STDCALL imaqEdgeTool4(Image* image, ROI* roi, EdgeProcess processType, EdgeOptions2* edgeOptions, const unsigned int reverseDirection);
+IMAQ_FUNC FindEdgeReport*        IMAQ_STDCALL imaqFindEdge2(Image* image, const ROI* roi, const CoordinateSystem* baseSystem, const CoordinateSystem* newSystem, const FindEdgeOptions2* findEdgeOptions, const StraightEdgeOptions* straightEdgeOptions);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqFindTransformRect2(Image* image, const ROI* roi, FindTransformMode mode, CoordinateSystem* baseSystem, CoordinateSystem* newSystem, const FindTransformRectOptions2* findTransformOptions, const StraightEdgeOptions* straightEdgeOptions, AxisReport* axisReport);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqFindTransformRects2(Image* image, const ROI* primaryROI, const ROI* secondaryROI, FindTransformMode mode, CoordinateSystem* baseSystem, CoordinateSystem* newSystem, const FindTransformRectsOptions2* findTransformOptions, const StraightEdgeOptions* primaryStraightEdgeOptions, const StraightEdgeOptions* secondaryStraightEdgeOptions, AxisReport* axisReport);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqLineGaugeTool2(const Image* image, Point start, Point end, LineGaugeMethod method, const EdgeOptions* edgeOptions, const CoordinateTransform2* transform, float* distance);
+IMAQ_FUNC RakeReport2*           IMAQ_STDCALL imaqRake2(Image* image, ROI* roi, RakeDirection direction, EdgeProcess process, int stepSize, EdgeOptions2* edgeOptions);
+IMAQ_FUNC PointFloat*            IMAQ_STDCALL imaqSimpleEdge(const Image* image, const Point* points, int numPoints, const SimpleEdgeOptions* options, int* numEdges);
+IMAQ_FUNC SpokeReport2*          IMAQ_STDCALL imaqSpoke2(Image* image, ROI* roi, SpokeDirection direction, EdgeProcess process, int stepSize, EdgeOptions2* edgeOptions);
+IMAQ_FUNC StraightEdgeReport2*   IMAQ_STDCALL imaqStraightEdge(const Image* image, const ROI* roi, SearchDirection searchDirection, const EdgeOptions2* edgeOptions, const StraightEdgeOptions* straightEdgeOptions);
+IMAQ_FUNC StraightEdgeReport2*   IMAQ_STDCALL imaqStraightEdge2(const Image* image, const ROI* roi, SearchDirection searchDirection, const EdgeOptions2* edgeOptions, const StraightEdgeOptions* straightEdgeOptions, unsigned int optimizedMode);
+
+//============================================================================
+//  Spatial Filters functions
+//============================================================================
+IMAQ_FUNC int IMAQ_STDCALL imaqCannyEdgeFilter(Image* dest, const Image* source, const CannyOptions* options);
+IMAQ_FUNC int IMAQ_STDCALL imaqConvolve2(Image* dest, Image* source, float* kernel, int matrixRows, int matrixCols, float normalize, Image* mask, RoundingMode roundingMode);
+IMAQ_FUNC int IMAQ_STDCALL imaqCorrelate(Image* dest, Image* source, const Image* templateImage, Rect rect);
+IMAQ_FUNC int IMAQ_STDCALL imaqEdgeFilter(Image* dest, Image* source, OutlineMethod method, const Image* mask);
+IMAQ_FUNC int IMAQ_STDCALL imaqLowPass(Image* dest, Image* source, int width, int height, float tolerance, const Image* mask);
+IMAQ_FUNC int IMAQ_STDCALL imaqMedianFilter(Image* dest, Image* source, int width, int height, const Image* mask);
+IMAQ_FUNC int IMAQ_STDCALL imaqNthOrderFilter(Image* dest, Image* source, int width, int height, int n, const Image* mask);
+
+//============================================================================
+//  Drawing functions
+//============================================================================
+IMAQ_FUNC int IMAQ_STDCALL imaqDrawLineOnImage(Image* dest, const Image* source, DrawMode mode, Point start, Point end, float newPixelValue);
+IMAQ_FUNC int IMAQ_STDCALL imaqDrawShapeOnImage(Image* dest, const Image* source, Rect rect, DrawMode mode, ShapeMode shape, float newPixelValue);
+IMAQ_FUNC int IMAQ_STDCALL imaqDrawTextOnImage(Image* dest, const Image* source, Point coord, const char* text, const DrawTextOptions* options, int* fontNameUsed);
+
+//============================================================================
+//  Interlacing functions
+//============================================================================
+IMAQ_FUNC int IMAQ_STDCALL imaqInterlaceCombine(Image* frame, const Image* odd, const Image* even);
+IMAQ_FUNC int IMAQ_STDCALL imaqInterlaceSeparate(const Image* frame, Image* odd, Image* even);
+
+//============================================================================
+//  Image Information functions
+//============================================================================
+IMAQ_FUNC char** IMAQ_STDCALL imaqEnumerateCustomKeys(const Image* image, unsigned int* size);
+IMAQ_FUNC int    IMAQ_STDCALL imaqGetBitDepth(const Image* image, unsigned int* bitDepth);
+IMAQ_FUNC int    IMAQ_STDCALL imaqGetBytesPerPixel(const Image* image, int* byteCount);
+IMAQ_FUNC int    IMAQ_STDCALL imaqGetImageInfo(const Image* image, ImageInfo* info);
+IMAQ_FUNC int    IMAQ_STDCALL imaqGetImageSize(const Image* image, int* width, int* height);
+IMAQ_FUNC int    IMAQ_STDCALL imaqGetImageType(const Image* image, ImageType* type);
+IMAQ_FUNC int    IMAQ_STDCALL imaqGetMaskOffset(const Image* image, Point* offset);
+IMAQ_FUNC void*  IMAQ_STDCALL imaqGetPixelAddress(const Image* image, Point pixel);
+IMAQ_FUNC int    IMAQ_STDCALL imaqGetVisionInfoTypes(const Image* image, unsigned int* present);
+IMAQ_FUNC int    IMAQ_STDCALL imaqIsImageEmpty(const Image* image, int* empty);
+IMAQ_FUNC void*  IMAQ_STDCALL imaqReadCustomData(const Image* image, const char* key, unsigned int* size);
+IMAQ_FUNC int    IMAQ_STDCALL imaqRemoveCustomData(Image* image, const char* key);
+IMAQ_FUNC int    IMAQ_STDCALL imaqRemoveVisionInfo2(const Image* image, unsigned int info);
+IMAQ_FUNC int    IMAQ_STDCALL imaqSetBitDepth(Image* image, unsigned int bitDepth);
+IMAQ_FUNC int    IMAQ_STDCALL imaqSetImageSize(Image* image, int width, int height);
+IMAQ_FUNC int    IMAQ_STDCALL imaqSetMaskOffset(Image* image, Point offset);
+IMAQ_FUNC int    IMAQ_STDCALL imaqWriteCustomData(Image* image, const char* key, const void* data, unsigned int size);
+
+//============================================================================
+//  Display functions
+//============================================================================
+IMAQ_FUNC int   IMAQ_STDCALL imaqAreToolsContextSensitive(int* sensitive);
+IMAQ_FUNC int   IMAQ_STDCALL imaqCloseWindow(int windowNumber);
+IMAQ_FUNC int   IMAQ_STDCALL imaqDisplayImage(const Image* image, int windowNumber, int resize);
+IMAQ_FUNC int   IMAQ_STDCALL imaqGetLastKey(char* keyPressed, int* windowNumber, int* modifiers);
+IMAQ_FUNC void* IMAQ_STDCALL imaqGetSystemWindowHandle(int windowNumber);
+IMAQ_FUNC int   IMAQ_STDCALL imaqGetWindowCenterPos(int windowNumber, Point* centerPosition);
+IMAQ_FUNC int   IMAQ_STDCALL imaqSetToolContextSensitivity(int sensitive);
+IMAQ_FUNC int   IMAQ_STDCALL imaqShowWindow(int windowNumber, int visible);
+
+//============================================================================
+//  Image Manipulation functions
+//============================================================================
+IMAQ_FUNC int   IMAQ_STDCALL imaqCast(Image* dest, const Image* source, ImageType type, const float* lookup, int shift);
+IMAQ_FUNC int   IMAQ_STDCALL imaqCopyRect(Image* dest, const Image* source, Rect rect, Point destLoc);
+IMAQ_FUNC int   IMAQ_STDCALL imaqDuplicate(Image* dest, const Image* source);
+IMAQ_FUNC void* IMAQ_STDCALL imaqFlatten(const Image* image, FlattenType type, CompressionType compression, int quality, unsigned int* size);
+IMAQ_FUNC int   IMAQ_STDCALL imaqFlip(Image* dest, const Image* source, FlipAxis axis);
+IMAQ_FUNC int   IMAQ_STDCALL imaqMask(Image* dest, const Image* source, const Image* mask);
+IMAQ_FUNC int   IMAQ_STDCALL imaqResample(Image* dest, const Image* source, int newWidth, int newHeight, InterpolationMethod method, Rect rect);
+IMAQ_FUNC int   IMAQ_STDCALL imaqRotate2(Image* dest, const Image* source, float angle, PixelValue fill, InterpolationMethod method, int maintainSize);
+IMAQ_FUNC int   IMAQ_STDCALL imaqScale(Image* dest, const Image* source, int xScale, int yScale, ScalingMode scaleMode, Rect rect);
+IMAQ_FUNC int   IMAQ_STDCALL imaqShift(Image* dest, const Image* source, int shiftX, int shiftY, PixelValue fill);
+IMAQ_FUNC int   IMAQ_STDCALL imaqTranspose(Image* dest, const Image* source);
+IMAQ_FUNC int   IMAQ_STDCALL imaqUnflatten(Image* image, const void* data, unsigned int size);
+IMAQ_FUNC int   IMAQ_STDCALL imaqUnwrapImage(Image* dest, const Image* source, Annulus annulus, RectOrientation orientation, InterpolationMethod method);
+IMAQ_FUNC int   IMAQ_STDCALL imaqView3D(Image* dest, Image* source, const View3DOptions* options);
+
+//============================================================================
+//  File I/O functions
+//============================================================================
+IMAQ_FUNC int         IMAQ_STDCALL imaqCloseAVI(AVISession session);
+IMAQ_FUNC AVISession  IMAQ_STDCALL imaqCreateAVI(const char* fileName, const char* compressionFilter, int quality, unsigned int framesPerSecond, unsigned int maxDataSize);
+IMAQ_FUNC int         IMAQ_STDCALL imaqGetAVIInfo(AVISession session, AVIInfo* info);
+IMAQ_FUNC int         IMAQ_STDCALL imaqGetFileInfo(const char* fileName, CalibrationUnit* calibrationUnit, float* calibrationX, float* calibrationY, int* width, int* height, ImageType* imageType);
+IMAQ_FUNC FilterName* IMAQ_STDCALL imaqGetFilterNames(int* numFilters);
+IMAQ_FUNC char**      IMAQ_STDCALL imaqLoadImagePopup(const char* defaultDirectory, const char* defaultFileSpec, const char* fileTypeList, const char* title, int allowMultiplePaths, ButtonLabel buttonLabel, int restrictDirectory, int restrictExtension, int allowCancel, int allowMakeDirectory, int* cancelled, int* numPaths);
+IMAQ_FUNC AVISession  IMAQ_STDCALL imaqOpenAVI(const char* fileName);
+IMAQ_FUNC int         IMAQ_STDCALL imaqReadAVIFrame(Image* image, AVISession session, unsigned int frameNum, void* data, unsigned int* dataSize);
+IMAQ_FUNC int         IMAQ_STDCALL imaqReadFile(Image* image, const char* fileName, RGBValue* colorTable, int* numColors);
+IMAQ_FUNC int         IMAQ_STDCALL imaqReadVisionFile(Image* image, const char* fileName, RGBValue* colorTable, int* numColors);
+IMAQ_FUNC int         IMAQ_STDCALL imaqWriteAVIFrame(Image* image, AVISession session, const void* data, unsigned int dataLength);
+IMAQ_FUNC int         IMAQ_STDCALL imaqWriteBMPFile(const Image* image, const char* fileName, int compress, const RGBValue* colorTable);
+IMAQ_FUNC int         IMAQ_STDCALL imaqWriteFile(const Image* image, const char* fileName, const RGBValue* colorTable);
+IMAQ_FUNC int         IMAQ_STDCALL imaqWriteJPEGFile(const Image* image, const char* fileName, unsigned int quality, void* colorTable);
+IMAQ_FUNC int         IMAQ_STDCALL imaqWriteJPEG2000File(const Image* image, const char* fileName, int lossless, float compressionRatio, const JPEG2000FileAdvancedOptions* advancedOptions, const RGBValue* colorTable);
+IMAQ_FUNC int         IMAQ_STDCALL imaqWritePNGFile2(const Image* image, const char* fileName, unsigned int compressionSpeed, const RGBValue* colorTable, int useBitDepth);
+IMAQ_FUNC int         IMAQ_STDCALL imaqWriteTIFFFile(const Image* image, const char* fileName, const TIFFFileOptions* options, const RGBValue* colorTable);
+IMAQ_FUNC int         IMAQ_STDCALL imaqWriteVisionFile(const Image* image, const char* fileName, const RGBValue* colorTable);
+
+
+//============================================================================
+//  Analytic Geometry functions
+//============================================================================
+IMAQ_FUNC int           IMAQ_STDCALL imaqBuildCoordinateSystem(const Point* points, ReferenceMode mode, AxisOrientation orientation, CoordinateSystem* system);
+IMAQ_FUNC BestCircle2*  IMAQ_STDCALL imaqFitCircle2(const PointFloat* points, int numPoints, const FitCircleOptions* options);
+IMAQ_FUNC BestEllipse2* IMAQ_STDCALL imaqFitEllipse2(const PointFloat* points, int numPoints, const FitEllipseOptions* options);
+IMAQ_FUNC BestLine*     IMAQ_STDCALL imaqFitLine(const PointFloat* points, int numPoints, const FitLineOptions* options);
+IMAQ_FUNC int           IMAQ_STDCALL imaqGetAngle(PointFloat start1, PointFloat end1, PointFloat start2, PointFloat end2, float* angle);
+IMAQ_FUNC int           IMAQ_STDCALL imaqGetBisectingLine(PointFloat start1, PointFloat end1, PointFloat start2, PointFloat end2, PointFloat* bisectStart, PointFloat* bisectEnd);
+IMAQ_FUNC int           IMAQ_STDCALL imaqGetDistance(PointFloat point1, PointFloat point2, float* distance);
+IMAQ_FUNC int           IMAQ_STDCALL imaqGetIntersection(PointFloat start1, PointFloat end1, PointFloat start2, PointFloat end2, PointFloat* intersection);
+IMAQ_FUNC int           IMAQ_STDCALL imaqGetMidLine(PointFloat refLineStart, PointFloat refLineEnd, PointFloat point, PointFloat* midLineStart, PointFloat* midLineEnd);
+IMAQ_FUNC int           IMAQ_STDCALL imaqGetPerpendicularLine(PointFloat refLineStart, PointFloat refLineEnd, PointFloat point, PointFloat* perpLineStart, PointFloat* perpLineEnd, double* distance);
+IMAQ_FUNC SegmentInfo*  IMAQ_STDCALL imaqGetPointsOnContour(const Image* image, int* numSegments);
+IMAQ_FUNC Point*        IMAQ_STDCALL imaqGetPointsOnLine(Point start, Point end, int* numPoints);
+IMAQ_FUNC int           IMAQ_STDCALL imaqGetPolygonArea(const PointFloat* points, int numPoints, float* area);
+IMAQ_FUNC float*        IMAQ_STDCALL imaqInterpolatePoints(const Image* image, const Point* points, int numPoints, InterpolationMethod method, int subpixel, int* interpCount);
+
+//============================================================================
+//  Clipboard functions
+//============================================================================
+IMAQ_FUNC int IMAQ_STDCALL imaqClipboardToImage(Image* dest, RGBValue* palette);
+IMAQ_FUNC int IMAQ_STDCALL imaqImageToClipboard(const Image* image, const RGBValue* palette);
+
+//============================================================================
+//  Border functions
+//============================================================================
+IMAQ_FUNC int IMAQ_STDCALL imaqFillBorder(Image* image, BorderMethod method);
+IMAQ_FUNC int IMAQ_STDCALL imaqGetBorderSize(const Image* image, int* borderSize);
+IMAQ_FUNC int IMAQ_STDCALL imaqSetBorderSize(Image* image, int size);
+
+//============================================================================
+//  Image Management functions
+//============================================================================
+IMAQ_FUNC int    IMAQ_STDCALL imaqArrayToImage(Image* image, const void* array, int numCols, int numRows);
+IMAQ_FUNC Image* IMAQ_STDCALL imaqCreateImage(ImageType type, int borderSize);
+IMAQ_FUNC void*  IMAQ_STDCALL imaqImageToArray(const Image* image, Rect rect, int* columns, int* rows);
+
+//============================================================================
+//  Color Processing functions
+//============================================================================
+IMAQ_FUNC Color2                             IMAQ_STDCALL imaqChangeColorSpace2(const Color2* sourceColor, ColorMode sourceSpace, ColorMode destSpace, double offset, const CIEXYZValue* whiteReference);
+IMAQ_FUNC int                                IMAQ_STDCALL imaqColorBCGTransform(Image* dest, const Image* source, const BCGOptions* redOptions, const BCGOptions* greenOptions, const BCGOptions* blueOptions, const Image* mask);
+IMAQ_FUNC int                                IMAQ_STDCALL imaqColorEqualize(Image* dest, const Image* source, int colorEqualization);
+IMAQ_FUNC ColorHistogramReport*              IMAQ_STDCALL imaqColorHistogram2(Image* image, int numClasses, ColorMode mode, const CIEXYZValue* whiteReference, Image* mask);
+IMAQ_FUNC int                                IMAQ_STDCALL imaqColorLookup(Image* dest, const Image* source, ColorMode mode, const Image* mask, const short* plane1, const short* plane2, const short* plane3);
+IMAQ_FUNC int                                IMAQ_STDCALL imaqColorThreshold(Image* dest, const Image* source, int replaceValue, ColorMode mode, const Range* plane1Range, const Range* plane2Range, const Range* plane3Range);
+IMAQ_FUNC SupervisedColorSegmentationReport* IMAQ_STDCALL imaqSupervisedColorSegmentation(ClassifierSession* session, Image* labelImage, const Image* srcImage, const ROI* roi, const ROILabel* labelIn, unsigned int numLabelIn, int maxDistance, int minIdentificationScore, const ColorSegmenationOptions* segmentOptions);
+IMAQ_FUNC int                                IMAQ_STDCALL imaqGetColorSegmentationMaxDistance(ClassifierSession* session, const ColorSegmenationOptions* segmentOptions, SegmentationDistanceLevel distLevel, int* maxDistance);
+
+//============================================================================
+//  Transform functions
+//============================================================================
+IMAQ_FUNC int IMAQ_STDCALL imaqBCGTransform(Image* dest, const Image* source, const BCGOptions* options, const Image* mask);
+IMAQ_FUNC int IMAQ_STDCALL imaqEqualize(Image* dest, const Image* source, float min, float max, const Image* mask);
+IMAQ_FUNC int IMAQ_STDCALL imaqInverse(Image* dest, const Image* source, const Image* mask);
+IMAQ_FUNC int IMAQ_STDCALL imaqMathTransform(Image* dest, const Image* source, MathTransformMethod method, float rangeMin, float rangeMax, float power, const Image* mask);
+IMAQ_FUNC int IMAQ_STDCALL imaqWatershedTransform(Image* dest, const Image* source, int connectivity8, int* zoneCount);
+IMAQ_FUNC int IMAQ_STDCALL imaqLookup2(Image* dest, const Image* source, const int* table, const Image* mask);
+
+
+//============================================================================
+//  Window Management functions
+//============================================================================
+IMAQ_FUNC int   IMAQ_STDCALL imaqAreScrollbarsVisible(int windowNumber, int* visible);
+IMAQ_FUNC int   IMAQ_STDCALL imaqBringWindowToTop(int windowNumber);
+IMAQ_FUNC int   IMAQ_STDCALL imaqGetMousePos(Point* position, int* windowNumber);
+IMAQ_FUNC int   IMAQ_STDCALL imaqGetWindowBackground(int windowNumber, WindowBackgroundFillStyle* fillStyle, WindowBackgroundHatchStyle* hatchStyle, RGBValue* fillColor, RGBValue* backgroundColor);
+IMAQ_FUNC int   IMAQ_STDCALL imaqGetWindowDisplayMapping(int windowNum, DisplayMapping* mapping);
+IMAQ_FUNC int   IMAQ_STDCALL imaqGetWindowGrid(int windowNumber, int* xResolution, int* yResolution);
+IMAQ_FUNC int   IMAQ_STDCALL imaqGetWindowHandle(int* handle);
+IMAQ_FUNC int   IMAQ_STDCALL imaqGetWindowPos(int windowNumber, Point* position);
+IMAQ_FUNC int   IMAQ_STDCALL imaqGetWindowSize(int windowNumber, int* width, int* height);
+IMAQ_FUNC char* IMAQ_STDCALL imaqGetWindowTitle(int windowNumber);
+IMAQ_FUNC int   IMAQ_STDCALL imaqGetWindowZoom2(int windowNumber, float* xZoom, float* yZoom);
+IMAQ_FUNC int   IMAQ_STDCALL imaqIsWindowNonTearing(int windowNumber, int* nonTearing);
+IMAQ_FUNC int   IMAQ_STDCALL imaqIsWindowVisible(int windowNumber, int* visible);
+IMAQ_FUNC int   IMAQ_STDCALL imaqMoveWindow(int windowNumber, Point position);
+IMAQ_FUNC int   IMAQ_STDCALL imaqSetupWindow(int windowNumber, int configuration);
+IMAQ_FUNC int   IMAQ_STDCALL imaqSetWindowBackground(int windowNumber, WindowBackgroundFillStyle fillStyle, WindowBackgroundHatchStyle hatchStyle, const RGBValue* fillColor, const RGBValue* backgroundColor);
+IMAQ_FUNC int   IMAQ_STDCALL imaqSetWindowDisplayMapping(int windowNumber, const DisplayMapping* mapping);
+IMAQ_FUNC int   IMAQ_STDCALL imaqSetWindowGrid(int windowNumber, int xResolution, int yResolution);
+IMAQ_FUNC int   IMAQ_STDCALL imaqSetWindowMaxContourCount(int windowNumber, unsigned int maxContourCount);
+IMAQ_FUNC int   IMAQ_STDCALL imaqSetWindowNonTearing(int windowNumber, int nonTearing);
+IMAQ_FUNC int   IMAQ_STDCALL imaqSetWindowPalette(int windowNumber, PaletteType type, const RGBValue* palette, int numColors);
+IMAQ_FUNC int   IMAQ_STDCALL imaqSetWindowSize(int windowNumber, int width, int height);
+IMAQ_FUNC int   IMAQ_STDCALL imaqSetWindowThreadPolicy(WindowThreadPolicy policy);
+IMAQ_FUNC int   IMAQ_STDCALL imaqSetWindowTitle(int windowNumber, const char* title);
+IMAQ_FUNC int   IMAQ_STDCALL imaqSetWindowZoomToFit(int windowNumber, int zoomToFit);
+IMAQ_FUNC int   IMAQ_STDCALL imaqShowScrollbars(int windowNumber, int visible);
+IMAQ_FUNC int   IMAQ_STDCALL imaqZoomWindow2(int windowNumber, float xZoom, float yZoom, Point center);
+
+//============================================================================
+//  Utilities functions
+//============================================================================
+IMAQ_FUNC const float* IMAQ_STDCALL imaqGetKernel(KernelFamily family, int size, int number);
+IMAQ_FUNC Annulus      IMAQ_STDCALL imaqMakeAnnulus(Point center, int innerRadius, int outerRadius, double startAngle, double endAngle);
+IMAQ_FUNC Point        IMAQ_STDCALL imaqMakePoint(int xCoordinate, int yCoordinate);
+IMAQ_FUNC PointFloat   IMAQ_STDCALL imaqMakePointFloat(float xCoordinate, float yCoordinate);
+IMAQ_FUNC Rect         IMAQ_STDCALL imaqMakeRect(int top, int left, int height, int width);
+IMAQ_FUNC Rect         IMAQ_STDCALL imaqMakeRectFromRotatedRect(RotatedRect rotatedRect);
+IMAQ_FUNC RotatedRect  IMAQ_STDCALL imaqMakeRotatedRect(int top, int left, int height, int width, double angle);
+IMAQ_FUNC RotatedRect  IMAQ_STDCALL imaqMakeRotatedRectFromRect(Rect rect);
+IMAQ_FUNC int          IMAQ_STDCALL imaqMulticoreOptions(MulticoreOperation operation, unsigned int* customNumCores);
+
+//============================================================================
+//  Tool Window functions
+//============================================================================
+IMAQ_FUNC int   IMAQ_STDCALL imaqCloseToolWindow(void);
+IMAQ_FUNC int   IMAQ_STDCALL imaqGetCurrentTool(Tool* currentTool);
+IMAQ_FUNC int   IMAQ_STDCALL imaqGetLastEvent(WindowEventType* type, int* windowNumber, Tool* tool, Rect* rect);
+IMAQ_FUNC void* IMAQ_STDCALL imaqGetToolWindowHandle(void);
+IMAQ_FUNC int   IMAQ_STDCALL imaqGetToolWindowPos(Point* position);
+IMAQ_FUNC int   IMAQ_STDCALL imaqIsToolWindowVisible(int* visible);
+IMAQ_FUNC int   IMAQ_STDCALL imaqMoveToolWindow(Point position);
+IMAQ_FUNC int   IMAQ_STDCALL imaqSetCurrentTool(Tool currentTool);
+#ifndef __GNUC__
+IMAQ_FUNC int   IMAQ_STDCALL imaqSetEventCallback(EventCallback callback, int synchronous);
+#endif
+IMAQ_FUNC int   IMAQ_STDCALL imaqSetToolColor(const RGBValue* color);
+IMAQ_FUNC int   IMAQ_STDCALL imaqSetupToolWindow(int showCoordinates, int maxIconsPerLine, const ToolWindowOptions* options);
+IMAQ_FUNC int   IMAQ_STDCALL imaqShowToolWindow(int visible);
+
+//============================================================================
+//  Meter functions
+//============================================================================
+IMAQ_FUNC MeterArc* IMAQ_STDCALL imaqGetMeterArc(int lightNeedle, MeterArcMode mode, const ROI* roi, PointFloat base, PointFloat start, PointFloat end);
+IMAQ_FUNC int       IMAQ_STDCALL imaqReadMeter(const Image* image, const MeterArc* arcInfo, double* percentage, PointFloat* endOfNeedle);
+
+//============================================================================
+//  Calibration functions
+//============================================================================
+IMAQ_FUNC int                        IMAQ_STDCALL imaqCopyCalibrationInfo2(Image* dest, Image* source, Point offset);
+IMAQ_FUNC int                        IMAQ_STDCALL imaqCorrectCalibratedImage(Image* dest, const Image* source, PixelValue fill, InterpolationMethod method, const ROI* roi);
+IMAQ_FUNC CalibrationInfo*           IMAQ_STDCALL imaqGetCalibrationInfo2(const Image* image);
+IMAQ_FUNC CalibrationInfo*           IMAQ_STDCALL imaqGetCalibrationInfo3(Image* image, unsigned int isGetErrorMap);
+IMAQ_FUNC int                        IMAQ_STDCALL imaqLearnCalibrationGrid(Image* image, const ROI* roi, const LearnCalibrationOptions* options, const GridDescriptor* grid, const CoordinateSystem* system, const RangeFloat* range, float* quality);
+IMAQ_FUNC int                        IMAQ_STDCALL imaqLearnCalibrationPoints(Image* image, const CalibrationPoints* points, const ROI* roi, const LearnCalibrationOptions* options, const GridDescriptor* grid, const CoordinateSystem* system, float* quality);
+IMAQ_FUNC int                        IMAQ_STDCALL imaqSetCoordinateSystem(Image* image, const CoordinateSystem* system);
+IMAQ_FUNC int                        IMAQ_STDCALL imaqSetSimpleCalibration(Image* image, ScalingMethod method, int learnTable, const GridDescriptor* grid, const CoordinateSystem* system);
+IMAQ_FUNC TransformReport*           IMAQ_STDCALL imaqTransformPixelToRealWorld(const Image* image, const PointFloat* pixelCoordinates, int numCoordinates);
+IMAQ_FUNC TransformReport*           IMAQ_STDCALL imaqTransformRealWorldToPixel(const Image* image, const PointFloat* realWorldCoordinates, int numCoordinates);
+IMAQ_FUNC int                        IMAQ_STDCALL imaqSetSimpleCalibration2(Image* image, const GridDescriptor* gridDescriptor);
+IMAQ_FUNC int                        IMAQ_STDCALL imaqCalibrationSetAxisInfo(Image* image, CoordinateSystem* axisInfo);
+IMAQ_FUNC int                        IMAQ_STDCALL imaqCalibrationGetThumbnailImage(Image* templateImage, Image* image, CalibrationThumbnailType type, unsigned int index);
+IMAQ_FUNC GetCalibrationInfoReport*  IMAQ_STDCALL imaqCalibrationGetCalibrationInfo(Image* image, unsigned int isGetErrorMap);
+IMAQ_FUNC GetCameraParametersReport* IMAQ_STDCALL imaqCalibrationGetCameraParameters(Image* templateImage);
+IMAQ_FUNC int                        IMAQ_STDCALL imaqCalibrationCompactInformation(Image* image);
+
+//============================================================================
+//  Pixel Manipulation functions
+//============================================================================
+IMAQ_FUNC int    IMAQ_STDCALL imaqArrayToComplexPlane(Image* dest, const Image* source, const float* newPixels, ComplexPlane plane);
+IMAQ_FUNC float* IMAQ_STDCALL imaqComplexPlaneToArray(const Image* image, ComplexPlane plane, Rect rect, int* rows, int* columns);
+IMAQ_FUNC int    IMAQ_STDCALL imaqExtractColorPlanes(const Image* image, ColorMode mode, Image* plane1, Image* plane2, Image* plane3);
+IMAQ_FUNC int    IMAQ_STDCALL imaqExtractComplexPlane(Image* dest, const Image* source, ComplexPlane plane);
+IMAQ_FUNC int    IMAQ_STDCALL imaqFillImage(Image* image, PixelValue value, const Image* mask);
+IMAQ_FUNC void*  IMAQ_STDCALL imaqGetLine(const Image* image, Point start, Point end, int* numPoints);
+IMAQ_FUNC int    IMAQ_STDCALL imaqGetPixel(const Image* image, Point pixel, PixelValue* value);
+IMAQ_FUNC int    IMAQ_STDCALL imaqReplaceColorPlanes(Image* dest, const Image* source, ColorMode mode, const Image* plane1, const Image* plane2, const Image* plane3);
+IMAQ_FUNC int    IMAQ_STDCALL imaqReplaceComplexPlane(Image* dest, const Image* source, const Image* newValues, ComplexPlane plane);
+IMAQ_FUNC int    IMAQ_STDCALL imaqSetLine(Image* image, const void* array, int arraySize, Point start, Point end);
+IMAQ_FUNC int    IMAQ_STDCALL imaqSetPixel(Image* image, Point coord, PixelValue value);
+
+//============================================================================
+//  Color Matching functions
+//============================================================================
+IMAQ_FUNC ColorInformation* IMAQ_STDCALL imaqLearnColor(const Image* image, const ROI* roi, ColorSensitivity sensitivity, int saturation);
+IMAQ_FUNC int*              IMAQ_STDCALL imaqMatchColor(const Image* image, const ColorInformation* info, const ROI* roi, int* numScores);
+
+//============================================================================
+//  Frequency Domain Analysis functions
+//============================================================================
+IMAQ_FUNC int IMAQ_STDCALL imaqAttenuate(Image* dest, const Image* source, AttenuateMode highlow);
+IMAQ_FUNC int IMAQ_STDCALL imaqConjugate(Image* dest, const Image* source);
+IMAQ_FUNC int IMAQ_STDCALL imaqFFT(Image* dest, const Image* source);
+IMAQ_FUNC int IMAQ_STDCALL imaqFlipFrequencies(Image* dest, const Image* source);
+IMAQ_FUNC int IMAQ_STDCALL imaqInverseFFT(Image* dest, const Image* source);
+IMAQ_FUNC int IMAQ_STDCALL imaqTruncate(Image* dest, const Image* source, TruncateMode highlow, float ratioToKeep);
+
+//============================================================================
+//  Barcode I/O functions
+//============================================================================
+IMAQ_FUNC int               IMAQ_STDCALL imaqGradeDataMatrixBarcodeAIM(const Image* image, AIMGradeReport* report);
+IMAQ_FUNC BarcodeInfo*      IMAQ_STDCALL imaqReadBarcode(const Image* image, BarcodeType type, const ROI* roi, int validate);
+IMAQ_FUNC DataMatrixReport* IMAQ_STDCALL imaqReadDataMatrixBarcode2(Image* image, const ROI* roi, DataMatrixGradingMode prepareForGrading, const DataMatrixDescriptionOptions* descriptionOptions, const DataMatrixSizeOptions* sizeOptions, const DataMatrixSearchOptions* searchOptions);
+IMAQ_FUNC Barcode2DInfo*    IMAQ_STDCALL imaqReadPDF417Barcode(const Image* image, const ROI* roi, Barcode2DSearchMode searchMode, unsigned int* numBarcodes);
+IMAQ_FUNC QRCodeReport*     IMAQ_STDCALL imaqReadQRCode(Image* image, const ROI* roi, QRGradingMode reserved, const QRCodeDescriptionOptions* descriptionOptions, const QRCodeSizeOptions* sizeOptions, const QRCodeSearchOptions* searchOptions);
+
+//============================================================================
+//  LCD functions
+//============================================================================
+IMAQ_FUNC int        IMAQ_STDCALL imaqFindLCDSegments(ROI* roi, const Image* image, const LCDOptions* options);
+IMAQ_FUNC LCDReport* IMAQ_STDCALL imaqReadLCD(const Image* image, const ROI* roi, const LCDOptions* options);
+
+//============================================================================
+//  Shape Matching functions
+//============================================================================
+IMAQ_FUNC ShapeReport* IMAQ_STDCALL imaqMatchShape(Image* dest, Image* source, const Image* templateImage, int scaleInvariant, int connectivity8, double tolerance, int* numMatches);
+
+//============================================================================
+//  Contours functions
+//============================================================================
+IMAQ_FUNC ContourID     IMAQ_STDCALL imaqAddAnnulusContour(ROI* roi, Annulus annulus);
+IMAQ_FUNC ContourID     IMAQ_STDCALL imaqAddClosedContour(ROI* roi, const Point* points, int numPoints);
+IMAQ_FUNC ContourID     IMAQ_STDCALL imaqAddLineContour(ROI* roi, Point start, Point end);
+IMAQ_FUNC ContourID     IMAQ_STDCALL imaqAddOpenContour(ROI* roi, const Point* points, int numPoints);
+IMAQ_FUNC ContourID     IMAQ_STDCALL imaqAddOvalContour(ROI* roi, Rect boundingBox);
+IMAQ_FUNC ContourID     IMAQ_STDCALL imaqAddPointContour(ROI* roi, Point point);
+IMAQ_FUNC ContourID     IMAQ_STDCALL imaqAddRectContour(ROI* roi, Rect rect);
+IMAQ_FUNC ContourID     IMAQ_STDCALL imaqAddRotatedRectContour2(ROI* roi, RotatedRect rect);
+IMAQ_FUNC ContourID     IMAQ_STDCALL imaqCopyContour(ROI* destRoi, const ROI* sourceRoi, ContourID id);
+IMAQ_FUNC ContourID     IMAQ_STDCALL imaqGetContour(const ROI* roi, unsigned int index);
+IMAQ_FUNC int           IMAQ_STDCALL imaqGetContourColor(const ROI* roi, ContourID id, RGBValue* contourColor);
+IMAQ_FUNC int           IMAQ_STDCALL imaqGetContourCount(const ROI* roi);
+IMAQ_FUNC ContourInfo2* IMAQ_STDCALL imaqGetContourInfo2(const ROI* roi, ContourID id);
+IMAQ_FUNC int           IMAQ_STDCALL imaqMoveContour(ROI* roi, ContourID id, int deltaX, int deltaY);
+IMAQ_FUNC int           IMAQ_STDCALL imaqRemoveContour(ROI* roi, ContourID id);
+IMAQ_FUNC int           IMAQ_STDCALL imaqSetContourColor(ROI* roi, ContourID id, const RGBValue* color);
+
+//============================================================================
+//  Regions of Interest functions
+//============================================================================
+IMAQ_FUNC int  IMAQ_STDCALL imaqConstructROI2(const Image* image, ROI* roi, Tool initialTool, const ToolWindowOptions* tools, const ConstructROIOptions2* options, int* okay);
+IMAQ_FUNC ROI* IMAQ_STDCALL imaqCreateROI(void);
+IMAQ_FUNC int  IMAQ_STDCALL imaqGetROIBoundingBox(const ROI* roi, Rect* boundingBox);
+IMAQ_FUNC int  IMAQ_STDCALL imaqGetROIColor(const ROI* roi, RGBValue* roiColor);
+IMAQ_FUNC ROI* IMAQ_STDCALL imaqGetWindowROI(int windowNumber);
+IMAQ_FUNC int  IMAQ_STDCALL imaqSetROIColor(ROI* roi, const RGBValue* color);
+IMAQ_FUNC int  IMAQ_STDCALL imaqSetWindowROI(int windowNumber, const ROI* roi);
+
+//============================================================================
+//  Image Analysis functions
+//============================================================================
+IMAQ_FUNC int              IMAQ_STDCALL imaqCentroid(const Image* image, PointFloat* centroid, const Image* mask);
+IMAQ_FUNC Curve*           IMAQ_STDCALL imaqExtractCurves(const Image* image, const ROI* roi, const CurveOptions* curveOptions, unsigned int* numCurves);
+IMAQ_FUNC HistogramReport* IMAQ_STDCALL imaqHistogram(const Image* image, int numClasses, float min, float max, const Image* mask);
+IMAQ_FUNC LinearAverages*  IMAQ_STDCALL imaqLinearAverages2(Image* image, LinearAveragesMode mode, Rect rect);
+IMAQ_FUNC LineProfile*     IMAQ_STDCALL imaqLineProfile(const Image* image, Point start, Point end);
+IMAQ_FUNC QuantifyReport*  IMAQ_STDCALL imaqQuantify(const Image* image, const Image* mask);
+
+//============================================================================
+//  Error Management functions
+//============================================================================
+IMAQ_FUNC int         IMAQ_STDCALL imaqClearError(void);
+IMAQ_FUNC char*       IMAQ_STDCALL imaqGetErrorText(int errorCode);
+IMAQ_FUNC int         IMAQ_STDCALL imaqGetLastError(void);
+IMAQ_FUNC const char* IMAQ_STDCALL imaqGetLastErrorFunc(void);
+IMAQ_FUNC int         IMAQ_STDCALL imaqSetError(int errorCode, const char* function);
+
+//============================================================================
+//  Threshold functions
+//============================================================================
+IMAQ_FUNC ThresholdData* IMAQ_STDCALL imaqAutoThreshold2(Image* dest, const Image* source, int numClasses, ThresholdMethod method, const Image* mask);
+IMAQ_FUNC int            IMAQ_STDCALL imaqLocalThreshold(Image* dest, const Image* source, unsigned int windowWidth, unsigned int windowHeight, LocalThresholdMethod method, double deviationWeight, ObjectType type, float replaceValue);
+IMAQ_FUNC int            IMAQ_STDCALL imaqMagicWand(Image* dest, const Image* source, Point coord, float tolerance, int connectivity8, float replaceValue);
+IMAQ_FUNC int            IMAQ_STDCALL imaqMultithreshold(Image* dest, const Image* source, const ThresholdData* ranges, int numRanges);
+IMAQ_FUNC int            IMAQ_STDCALL imaqThreshold(Image* dest, const Image* source, float rangeMin, float rangeMax, int useNewValue, float newValue);
+
+//============================================================================
+//  Memory Management functions
+//============================================================================
+IMAQ_FUNC int IMAQ_STDCALL imaqDispose(void* object);
+
+//============================================================================
+//  Pattern Matching functions
+//============================================================================
+IMAQ_FUNC CircleMatch*              IMAQ_STDCALL imaqDetectCircles(const Image* image, const CircleDescriptor* circleDescriptor, const CurveOptions* curveOptions, const ShapeDetectionOptions* shapeDetectionOptions, const ROI* roi, int* numMatchesReturned);
+IMAQ_FUNC EllipseMatch*             IMAQ_STDCALL imaqDetectEllipses(const Image* image, const EllipseDescriptor* ellipseDescriptor, const CurveOptions* curveOptions, const ShapeDetectionOptions* shapeDetectionOptions, const ROI* roi, int* numMatchesReturned);
+IMAQ_FUNC LineMatch*                IMAQ_STDCALL imaqDetectLines(const Image* image, const LineDescriptor* lineDescriptor, const CurveOptions* curveOptions, const ShapeDetectionOptions* shapeDetectionOptions, const ROI* roi, int* numMatchesReturned);
+IMAQ_FUNC RectangleMatch*           IMAQ_STDCALL imaqDetectRectangles(const Image* image, const RectangleDescriptor* rectangleDescriptor, const CurveOptions* curveOptions, const ShapeDetectionOptions* shapeDetectionOptions, const ROI* roi, int* numMatchesReturned);
+IMAQ_FUNC FeatureData*              IMAQ_STDCALL imaqGetGeometricFeaturesFromCurves(const Curve* curves, unsigned int numCurves, const FeatureType* featureTypes, unsigned int numFeatureTypes, unsigned int* numFeatures);
+IMAQ_FUNC FeatureData*              IMAQ_STDCALL imaqGetGeometricTemplateFeatureInfo(const Image* pattern, unsigned int* numFeatures);
+IMAQ_FUNC int                       IMAQ_STDCALL imaqLearnColorPattern(Image* image, const LearnColorPatternOptions* options);
+IMAQ_FUNC int                       IMAQ_STDCALL imaqLearnGeometricPattern(Image* image, PointFloat originOffset, const CurveOptions* curveOptions, const LearnGeometricPatternAdvancedOptions* advancedLearnOptions, const Image* mask);
+IMAQ_FUNC MultipleGeometricPattern* IMAQ_STDCALL imaqLearnMultipleGeometricPatterns(const Image** patterns, unsigned int numberOfPatterns, const String255* labels);
+IMAQ_FUNC int                       IMAQ_STDCALL imaqLearnPattern3(Image* image, LearningMode learningMode, LearnPatternAdvancedOptions* advancedOptions, const Image* mask);
+IMAQ_FUNC PatternMatch*             IMAQ_STDCALL imaqMatchColorPattern(const Image* image, Image* pattern, const MatchColorPatternOptions* options, Rect searchRect, int* numMatches);
+IMAQ_FUNC GeometricPatternMatch2*   IMAQ_STDCALL imaqMatchGeometricPattern2(const Image* image, const Image* pattern, const CurveOptions* curveOptions, const MatchGeometricPatternOptions* matchOptions, const MatchGeometricPatternAdvancedOptions2* advancedMatchOptions, const ROI* roi, int* numMatches);
+IMAQ_FUNC GeometricPatternMatch2*   IMAQ_STDCALL imaqMatchMultipleGeometricPatterns(const Image* image, const MultipleGeometricPattern* multiplePattern, const ROI* roi, int* numMatches);
+IMAQ_FUNC MultipleGeometricPattern* IMAQ_STDCALL imaqReadMultipleGeometricPatternFile(const char* fileName, String255 description);
+IMAQ_FUNC PatternMatch*             IMAQ_STDCALL imaqRefineMatches(const Image* image, const Image* pattern, const PatternMatch* candidatesIn, int numCandidatesIn, MatchPatternOptions* options, MatchPatternAdvancedOptions* advancedOptions, int* numCandidatesOut);
+IMAQ_FUNC int                       IMAQ_STDCALL imaqSetMultipleGeometricPatternsOptions(MultipleGeometricPattern* multiplePattern, const char* label, const CurveOptions* curveOptions, const MatchGeometricPatternOptions* matchOptions, const MatchGeometricPatternAdvancedOptions2* advancedMatchOptions);
+IMAQ_FUNC int                       IMAQ_STDCALL imaqWriteMultipleGeometricPatternFile(const MultipleGeometricPattern* multiplePattern, const char* fileName, const char* description);
+IMAQ_FUNC GeometricPatternMatch3*   IMAQ_STDCALL imaqMatchGeometricPattern3(const Image* image, const Image* pattern, const CurveOptions* curveOptions, const MatchGeometricPatternOptions* matchOptions, const MatchGeometricPatternAdvancedOptions3* advancedMatchOptions, const ROI* roi, size_t* numMatches);
+IMAQ_FUNC int                       IMAQ_STDCALL imaqLearnGeometricPattern2(Image* image, PointFloat originOffset, double angleOffset, const CurveOptions* curveOptions, const LearnGeometricPatternAdvancedOptions2* advancedLearnOptions, const Image* mask);
+IMAQ_FUNC PatternMatch*             IMAQ_STDCALL imaqMatchPattern3(const Image* image, const Image* pattern, const MatchPatternOptions* options, const MatchPatternAdvancedOptions* advancedOptions, const ROI* roi, int* numMatches);
+
+//============================================================================
+//  Overlay functions
+//============================================================================
+IMAQ_FUNC int IMAQ_STDCALL imaqClearOverlay(Image* image, const char* group);
+IMAQ_FUNC int IMAQ_STDCALL imaqCopyOverlay(Image* dest, const Image* source, const char* group);
+IMAQ_FUNC int IMAQ_STDCALL imaqGetOverlayProperties(const Image* image, const char* group, TransformBehaviors* transformBehaviors);
+IMAQ_FUNC int IMAQ_STDCALL imaqMergeOverlay(Image* dest, const Image* source, const RGBValue* palette, unsigned int numColors, const char* group);
+IMAQ_FUNC int IMAQ_STDCALL imaqOverlayArc(Image* image, const ArcInfo* arc, const RGBValue* color, DrawMode drawMode, const char* group);
+IMAQ_FUNC int IMAQ_STDCALL imaqOverlayBitmap(Image* image, Point destLoc, const RGBValue* bitmap, unsigned int numCols, unsigned int numRows, const char* group);
+IMAQ_FUNC int IMAQ_STDCALL imaqOverlayClosedContour(Image* image, const Point* points, int numPoints, const RGBValue* color, DrawMode drawMode, const char* group);
+IMAQ_FUNC int IMAQ_STDCALL imaqOverlayLine(Image* image, Point start, Point end, const RGBValue* color, const char* group);
+IMAQ_FUNC int IMAQ_STDCALL imaqOverlayMetafile(Image* image, const void* metafile, Rect rect, const char* group);
+IMAQ_FUNC int IMAQ_STDCALL imaqOverlayOpenContour(Image* image, const Point* points, int numPoints, const RGBValue* color, const char* group);
+IMAQ_FUNC int IMAQ_STDCALL imaqOverlayOval(Image* image, Rect boundingBox, const RGBValue* color, DrawMode drawMode, char* group);
+IMAQ_FUNC int IMAQ_STDCALL imaqOverlayPoints(Image* image, const Point* points, int numPoints, const RGBValue* colors, int numColors, PointSymbol symbol, const UserPointSymbol* userSymbol, const char* group);
+IMAQ_FUNC int IMAQ_STDCALL imaqOverlayRect(Image* image, Rect rect, const RGBValue* color, DrawMode drawMode, const char* group);
+IMAQ_FUNC int IMAQ_STDCALL imaqOverlayROI(Image* image, const ROI* roi, PointSymbol symbol, const UserPointSymbol* userSymbol, const char* group);
+IMAQ_FUNC int IMAQ_STDCALL imaqOverlayText(Image* image, Point origin, const char* text, const RGBValue* color, const OverlayTextOptions* options, const char* group);
+IMAQ_FUNC int IMAQ_STDCALL imaqSetOverlayProperties(Image* image, const char* group, TransformBehaviors* transformBehaviors);
+
+//============================================================================
+//  OCR functions
+//============================================================================
+IMAQ_FUNC CharSet*         IMAQ_STDCALL imaqCreateCharSet(void);
+IMAQ_FUNC int              IMAQ_STDCALL imaqDeleteChar(CharSet* set, int index);
+IMAQ_FUNC int              IMAQ_STDCALL imaqGetCharCount(const CharSet* set);
+IMAQ_FUNC CharInfo2*       IMAQ_STDCALL imaqGetCharInfo2(const CharSet* set, int index);
+IMAQ_FUNC int              IMAQ_STDCALL imaqReadOCRFile(const char* fileName, CharSet* set, String255 setDescription, ReadTextOptions* readOptions, OCRProcessingOptions* processingOptions, OCRSpacingOptions* spacingOptions);
+IMAQ_FUNC ReadTextReport3* IMAQ_STDCALL imaqReadText3(const Image* image, const CharSet* set, const ROI* roi, const ReadTextOptions* readOptions, const OCRProcessingOptions* processingOptions, const OCRSpacingOptions* spacingOptions);
+IMAQ_FUNC int              IMAQ_STDCALL imaqRenameChar(CharSet* set, int index, const char* newCharValue);
+IMAQ_FUNC int              IMAQ_STDCALL imaqSetReferenceChar(const CharSet* set, int index, int isReferenceChar);
+IMAQ_FUNC int              IMAQ_STDCALL imaqTrainChars(const Image* image, CharSet* set, int index, const char* charValue, const ROI* roi, const OCRProcessingOptions* processingOptions, const OCRSpacingOptions* spacingOptions);
+IMAQ_FUNC int*             IMAQ_STDCALL imaqVerifyPatterns(const Image* image, const CharSet* set, const String255* expectedPatterns, int patternCount, const ROI* roi, int* numScores);
+IMAQ_FUNC int*             IMAQ_STDCALL imaqVerifyText(const Image* image, const CharSet* set, const char* expectedString, const ROI* roi, int* numScores);
+IMAQ_FUNC int              IMAQ_STDCALL imaqWriteOCRFile(const char* fileName, const CharSet* set, const char* setDescription, const ReadTextOptions* readOptions, const OCRProcessingOptions* processingOptions, const OCRSpacingOptions* spacingOptions);
+
+//============================================================================
+//  Geometric Matching functions
+//============================================================================
+IMAQ_FUNC ExtractContourReport*          IMAQ_STDCALL imaqExtractContour(Image* image, const ROI* roi, ExtractContourDirection direction, CurveParameters* curveParams, const ConnectionConstraint* connectionConstraintParams, unsigned int numOfConstraints, ExtractContourSelection selection, Image* contourImage);
+IMAQ_FUNC int                            IMAQ_STDCALL imaqContourOverlay(Image* image, const Image* contourImage, const ContourOverlaySettings* pointsSettings, const ContourOverlaySettings* eqnSettings, const char* groupName);
+IMAQ_FUNC ContourComputeCurvatureReport* IMAQ_STDCALL imaqContourComputeCurvature(const Image* contourImage, unsigned int kernel);
+IMAQ_FUNC CurvatureAnalysisReport*       IMAQ_STDCALL imaqContourClassifyCurvature(const Image* contourImage, unsigned int kernel, RangeLabel* curvatureClasses, unsigned int numCurvatureClasses);
+IMAQ_FUNC ComputeDistancesReport*        IMAQ_STDCALL imaqContourComputeDistances(const Image* targetImage, const Image* templateImage, const SetupMatchPatternData* matchSetupData, unsigned int smoothingKernel);
+IMAQ_FUNC ClassifyDistancesReport*       IMAQ_STDCALL imaqContourClassifyDistances(const Image* targetImage, const Image* templateImage, const SetupMatchPatternData* matchSetupData, unsigned int smoothingKernel, const RangeLabel* distanceRanges, unsigned int numDistanceRanges);
+IMAQ_FUNC ContourInfoReport*             IMAQ_STDCALL imaqContourInfo(const Image* contourImage);
+IMAQ_FUNC SetupMatchPatternData*         IMAQ_STDCALL imaqContourSetupMatchPattern(MatchMode* matchMode, unsigned int enableSubPixelAccuracy, CurveParameters* curveParams, unsigned int useLearnCurveParameters, const RangeSettingDouble* rangeSettings, unsigned int numRangeSettings);
+IMAQ_FUNC int                            IMAQ_STDCALL imaqContourAdvancedSetupMatchPattern(SetupMatchPatternData* matchSetupData, GeometricAdvancedSetupDataOption* geometricOptions, unsigned int numGeometricOptions);
+IMAQ_FUNC ContourFitLineReport*          IMAQ_STDCALL imaqContourFitLine(Image* image, double pixelRadius);
+IMAQ_FUNC PartialCircle*                 IMAQ_STDCALL imaqContourFitCircle(Image* image, double pixelRadius, int rejectOutliers);
+IMAQ_FUNC PartialEllipse*                IMAQ_STDCALL imaqContourFitEllipse(Image* image, double pixelRadius, int rejectOutliers);
+IMAQ_FUNC ContourFitSplineReport*        IMAQ_STDCALL imaqContourFitSpline(Image* image, int degree, int numberOfControlPoints);
+IMAQ_FUNC ContourFitPolynomialReport*    IMAQ_STDCALL imaqContourFitPolynomial(Image* image, int order);
+
+//============================================================================
+//  Edge Detection functions
+//============================================================================
+IMAQ_FUNC FindCircularEdgeReport*   IMAQ_STDCALL imaqFindCircularEdge2(Image* image, const ROI* roi, const CoordinateSystem* baseSystem, const CoordinateSystem* newSystem, const FindCircularEdgeOptions* edgeOptions, const CircleFitOptions* circleFitOptions);
+IMAQ_FUNC FindConcentricEdgeReport* IMAQ_STDCALL imaqFindConcentricEdge2(Image* image, const ROI* roi, const CoordinateSystem* baseSystem, const CoordinateSystem* newSystem, const FindConcentricEdgeOptions* edgeOptions, const ConcentricEdgeFitOptions* concentricEdgeFitOptions);
+
+//============================================================================
+//  Morphology Reconstruction functions
+//============================================================================
+IMAQ_FUNC int IMAQ_STDCALL imaqGrayMorphologyReconstruct(Image* dstImage, Image* srcImage, const Image* markerImage, PointFloat* points, int numOfPoints, MorphologyReconstructOperation operation, const StructuringElement* structuringElement, const ROI* roi);
+IMAQ_FUNC int IMAQ_STDCALL imaqMorphologyReconstruct(Image* dstImage, Image* srcImage, const Image* markerImage, PointFloat* points, int numOfPoints, MorphologyReconstructOperation operation, Connectivity connectivity, const ROI* roi);
+
+//============================================================================
+//  Texture functions
+//============================================================================
+IMAQ_FUNC int                           IMAQ_STDCALL imaqDetectTextureDefect(ClassifierSession* session, Image* destImage, const Image* srcImage, const ROI* roi, int initialStepSize, int finalStepSize, unsigned char defectPixelValue, double minClassificationScore);
+IMAQ_FUNC int                           IMAQ_STDCALL imaqClassificationTextureDefectOptions(ClassifierSession* session, WindowSize* windowOptions, WaveletOptions* waveletOptions, void** bandsUsed, int* numBandsUsed, CooccurrenceOptions* cooccurrenceOptions, unsigned char setOperation);
+IMAQ_FUNC int                           IMAQ_STDCALL imaqCooccurrenceMatrix(const Image* srcImage, const ROI* roi, int levelPixel, const DisplacementVector* displacementVec, void* featureOptionArray, unsigned int featureOptionArraySize, void** cooccurrenceMatrixArray, int* coocurrenceMatrixRows, int* coocurrenceMatrixCols, void** featureVectorArray, int* featureVectorArraySize);
+IMAQ_FUNC ExtractTextureFeaturesReport* IMAQ_STDCALL imaqExtractTextureFeatures(const Image* srcImage, const ROI* roi, const WindowSize* windowOptions, const WaveletOptions* waveletOptions, void* waveletBands, unsigned int numWaveletBands, const CooccurrenceOptions* cooccurrenceOptions, unsigned char useWindow);
+IMAQ_FUNC WaveletBandsReport*           IMAQ_STDCALL imaqExtractWaveletBands(const Image* srcImage, const WaveletOptions* waveletOptions, void* waveletBands, unsigned int numWaveletBands);
+
+//============================================================================
+//  Regions of Interest Manipulation functions
+//============================================================================
+IMAQ_FUNC ROI*              IMAQ_STDCALL imaqMaskToROI(const Image* mask, int* withinLimit);
+IMAQ_FUNC ROIProfile*       IMAQ_STDCALL imaqROIProfile(const Image* image, const ROI* roi);
+IMAQ_FUNC int               IMAQ_STDCALL imaqROIToMask(Image* mask, const ROI* roi, int fillValue, const Image* imageModel, int* inSpace);
+IMAQ_FUNC int               IMAQ_STDCALL imaqTransformROI2(ROI* roi, const CoordinateSystem* baseSystem, const CoordinateSystem* newSystem);
+IMAQ_FUNC LabelToROIReport* IMAQ_STDCALL imaqLabelToROI(const Image* image, const unsigned int* labelsIn, unsigned int numLabelsIn, int maxNumVectors, int isExternelEdges);
+
+//============================================================================
+//  Morphology functions
+//============================================================================
+IMAQ_FUNC int IMAQ_STDCALL imaqGrayMorphology(Image* dest, Image* source, MorphologyMethod method, const StructuringElement* structuringElement);
+
+//============================================================================
+//  Classification functions
+//============================================================================
+IMAQ_FUNC int                            IMAQ_STDCALL imaqAddClassifierSample(Image* image, ClassifierSession* session, const ROI* roi, const char* sampleClass, double* featureVector, unsigned int vectorSize);
+IMAQ_FUNC ClassifierReportAdvanced*      IMAQ_STDCALL imaqAdvanceClassify(Image* image, const ClassifierSession* session, const ROI* roi, double* featureVector, unsigned int vectorSize);
+IMAQ_FUNC ClassifierReport*              IMAQ_STDCALL imaqClassify(Image* image, const ClassifierSession* session, const ROI* roi, double* featureVector, unsigned int vectorSize);
+IMAQ_FUNC ClassifierSession*             IMAQ_STDCALL imaqCreateClassifier(ClassifierType type);
+IMAQ_FUNC int                            IMAQ_STDCALL imaqDeleteClassifierSample(ClassifierSession* session, int index);
+IMAQ_FUNC ClassifierAccuracyReport*      IMAQ_STDCALL imaqGetClassifierAccuracy(const ClassifierSession* session);
+IMAQ_FUNC ClassifierSampleInfo*          IMAQ_STDCALL imaqGetClassifierSampleInfo(const ClassifierSession* session, int index, int* numSamples);
+IMAQ_FUNC int                            IMAQ_STDCALL imaqGetColorClassifierOptions(const ClassifierSession* session, ColorOptions* options);
+IMAQ_FUNC int                            IMAQ_STDCALL imaqGetNearestNeighborOptions(const ClassifierSession* session, NearestNeighborOptions* options);
+IMAQ_FUNC int                            IMAQ_STDCALL imaqGetParticleClassifierOptions2(const ClassifierSession* session, ParticleClassifierPreprocessingOptions2* preprocessingOptions, ParticleClassifierOptions* options);
+IMAQ_FUNC ClassifierSession*             IMAQ_STDCALL imaqReadClassifierFile(ClassifierSession* session, const char* fileName, ReadClassifierFileMode mode, ClassifierType* type, ClassifierEngineType* engine, String255 description);
+IMAQ_FUNC int                            IMAQ_STDCALL imaqRelabelClassifierSample(ClassifierSession* session, int index, const char* newClass);
+IMAQ_FUNC int                            IMAQ_STDCALL imaqSetParticleClassifierOptions2(ClassifierSession* session, const ParticleClassifierPreprocessingOptions2* preprocessingOptions, const ParticleClassifierOptions* options);
+IMAQ_FUNC int                            IMAQ_STDCALL imaqSetColorClassifierOptions(ClassifierSession* session, const ColorOptions* options);
+IMAQ_FUNC NearestNeighborTrainingReport* IMAQ_STDCALL imaqTrainNearestNeighborClassifier(ClassifierSession* session, const NearestNeighborOptions* options);
+IMAQ_FUNC int                            IMAQ_STDCALL imaqWriteClassifierFile(const ClassifierSession* session, const char* fileName, WriteClassifierFileMode mode, const String255 description);
+
+//============================================================================
+//  Measure Distances functions
+//============================================================================
+IMAQ_FUNC ClampMax2Report* IMAQ_STDCALL imaqClampMax2(Image* image, const ROI* roi, const CoordinateSystem* baseSystem, const CoordinateSystem* newSystem, const CurveOptions* curveSettings, const ClampSettings* clampSettings, const ClampOverlaySettings* clampOverlaySettings);
+
+//============================================================================
+//  Inspection functions
+//============================================================================
+IMAQ_FUNC int IMAQ_STDCALL imaqCompareGoldenTemplate(const Image* image, const Image* goldenTemplate, Image* brightDefects, Image* darkDefects, const InspectionAlignment* alignment, const InspectionOptions* options);
+IMAQ_FUNC int IMAQ_STDCALL imaqLearnGoldenTemplate(Image* goldenTemplate, PointFloat originOffset, const Image* mask);
+//============================================================================
+//  Obsolete functions
+//============================================================================
+IMAQ_FUNC int                    IMAQ_STDCALL imaqRotate(Image* dest, const Image* source, float angle, PixelValue fill, InterpolationMethod method);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqWritePNGFile(const Image* image, const char* fileName, unsigned int compressionSpeed, const RGBValue* colorTable);
+IMAQ_FUNC ParticleReport*        IMAQ_STDCALL imaqSelectParticles(const Image* image, const ParticleReport* reports, int reportCount, int rejectBorder, const SelectParticleCriteria* criteria, int criteriaCount, int* selectedCount);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqParticleFilter(Image* dest, Image* source, const ParticleFilterCriteria* criteria, int criteriaCount, int rejectMatches, int connectivity8);
+IMAQ_FUNC ParticleReport*        IMAQ_STDCALL imaqGetParticleInfo(Image* image, int connectivity8, ParticleInfoMode mode, int* reportCount);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqCalcCoeff(const Image* image, const ParticleReport* report, MeasurementValue parameter, float* coefficient);
+IMAQ_FUNC EdgeReport*            IMAQ_STDCALL imaqEdgeTool(const Image* image, const Point* points, int numPoints, const EdgeOptions* options, int* numEdges);
+IMAQ_FUNC CircleReport*          IMAQ_STDCALL imaqCircles(Image* dest, const Image* source, float minRadius, float maxRadius, int* numCircles);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqLabel(Image* dest, Image* source, int connectivity8, int* particleCount);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqFitEllipse(const PointFloat* points, int numPoints, BestEllipse* ellipse);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqFitCircle(const PointFloat* points, int numPoints, BestCircle* circle);
+IMAQ_FUNC Color                  IMAQ_STDCALL imaqChangeColorSpace(const Color* sourceColor, ColorMode sourceSpace, ColorMode destSpace);
+IMAQ_FUNC PatternMatch*          IMAQ_STDCALL imaqMatchPattern(const Image* image, Image* pattern, const MatchPatternOptions* options, Rect searchRect, int* numMatches);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqConvex(Image* dest, const Image* source);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqIsVisionInfoPresent(const Image* image, VisionInfoType type, int* present);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqLineGaugeTool(const Image* image, Point start, Point end, LineGaugeMethod method, const EdgeOptions* edgeOptions, const CoordinateTransform* reference, float* distance);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqBestCircle(const PointFloat* points, int numPoints, PointFloat* center, double* radius);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqSavePattern(const Image* pattern, const char* fileName);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqLoadPattern(Image* pattern, const char* fileName);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqTransformROI(ROI* roi, Point originStart, float angleStart, Point originFinal, float angleFinal);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqCoordinateReference(const Point* points, ReferenceMode mode, Point* origin, float* angle);
+IMAQ_FUNC ContourInfo*           IMAQ_STDCALL imaqGetContourInfo(const ROI* roi, ContourID id);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqSetWindowOverlay(int windowNumber, const Overlay* overlay);
+IMAQ_FUNC Overlay*               IMAQ_STDCALL imaqCreateOverlayFromROI(const ROI* roi);
+IMAQ_FUNC Overlay*               IMAQ_STDCALL imaqCreateOverlayFromMetafile(const void* metafile);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqSetCalibrationInfo(Image* image, CalibrationUnit unit, float xDistance, float yDistance);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqGetCalibrationInfo(const Image* image, CalibrationUnit* unit, float* xDistance, float* yDistance);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqConstructROI(const Image* image, ROI* roi, Tool initialTool, const ToolWindowOptions* tools, const ConstructROIOptions* options, int* okay);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqGetParticleClassifierOptions(const ClassifierSession* session, ParticleClassifierPreprocessingOptions* preprocessingOptions, ParticleClassifierOptions* options);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqZoomWindow(int windowNumber, int xZoom, int yZoom, Point center);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqGetWindowZoom(int windowNumber, int* xZoom, int* yZoom);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqParticleFilter3(Image* dest, Image* source, const ParticleFilterCriteria2* criteria, int criteriaCount, const ParticleFilterOptions* options, const ROI* roi, int* numParticles);
+IMAQ_FUNC ReadTextReport2*       IMAQ_STDCALL imaqReadText2(const Image* image, const CharSet* set, const ROI* roi, const ReadTextOptions* readOptions, const OCRProcessingOptions* processingOptions, const OCRSpacingOptions* spacingOptions);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqLearnPattern2(Image* image, LearningMode learningMode, LearnPatternAdvancedOptions* advancedOptions);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqConvolve(Image* dest, Image* source, const float* kernel, int matrixRows, int matrixCols, float normalize, const Image* mask);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqDivideConstant(Image* dest, const Image* source, PixelValue value);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqDivide(Image* dest, const Image* sourceA, const Image* sourceB);
+IMAQ_FUNC EdgeReport2*           IMAQ_STDCALL imaqEdgeTool3(const Image* image, const ROI* roi, EdgeProcess processType, const EdgeOptions2* edgeOptions);
+IMAQ_FUNC ConcentricRakeReport*  IMAQ_STDCALL imaqConcentricRake(const Image* image, const ROI* roi, ConcentricRakeDirection direction, EdgeProcess process, const RakeOptions* options);
+IMAQ_FUNC SpokeReport*           IMAQ_STDCALL imaqSpoke(const Image* image, const ROI* roi, SpokeDirection direction, EdgeProcess process, const SpokeOptions* options);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqLearnPattern(Image* image, LearningMode learningMode);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqLookup(Image* dest, const Image* source, const short* table, const Image* mask);
+IMAQ_FUNC PatternMatch*          IMAQ_STDCALL imaqMatchPattern2(const Image* image, const Image* pattern, const MatchPatternOptions* options, const MatchPatternAdvancedOptions* advancedOptions, Rect searchRect, int* numMatches);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqSetParticleClassifierOptions(ClassifierSession* session, const ParticleClassifierPreprocessingOptions* preprocessingOptions, const ParticleClassifierOptions* options);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqCopyCalibrationInfo(Image* dest, const Image* source);
+IMAQ_FUNC int                    IMAQ_STDCALL imaqParticleFilter2(Image* dest, Image* source, const ParticleFilterCriteria2* criteria, int criteriaCount, int rejectMatches, int connectivity8, int* numParticles);
+IMAQ_FUNC EdgeReport*            IMAQ_STDCALL imaqEdgeTool2(const Image* image, const Point* points, int numPoints, EdgeProcess process, const EdgeOptions* options, int* numEdges);
+IMAQ_FUNC ContourID              IMAQ_STDCALL imaqAddRotatedRectContour(ROI* roi, RotatedRect rect);
+IMAQ_FUNC Barcode2DInfo*         IMAQ_STDCALL imaqReadDataMatrixBarcode(const Image* image, const ROI* roi, const DataMatrixOptions* options, unsigned int* numBarcodes);
+IMAQ_FUNC LinearAverages*        IMAQ_STDCALL imaqLinearAverages(const Image* image, Rect rect);
+IMAQ_FUNC GeometricPatternMatch* IMAQ_STDCALL imaqMatchGeometricPattern(const Image* image, const Image* pattern, const CurveOptions* curveOptions, const MatchGeometricPatternOptions* matchOptions, const MatchGeometricPatternAdvancedOptions* advancedMatchOptions, const ROI* roi, int* numMatches);
+IMAQ_FUNC CharInfo*              IMAQ_STDCALL imaqGetCharInfo(const CharSet* set, int index);
+IMAQ_FUNC ReadTextReport*        IMAQ_STDCALL imaqReadText(const Image* image, const CharSet* set, const ROI* roi, const ReadTextOptions* readOptions, const OCRProcessingOptions* processingOptions, const OCRSpacingOptions* spacingOptions);
+IMAQ_FUNC ThresholdData*         IMAQ_STDCALL imaqAutoThreshold(Image* dest, Image* source, int numClasses, ThresholdMethod method);
+IMAQ_FUNC ColorHistogramReport*  IMAQ_STDCALL imaqColorHistogram(Image* image, int numClasses, ColorMode mode, const Image* mask);
+IMAQ_FUNC RakeReport*            IMAQ_STDCALL imaqRake(const Image* image, const ROI* roi, RakeDirection direction, EdgeProcess process, const RakeOptions* options);
+
+IMAQ_FUNC int                    IMAQ_STDCALL Priv_ReadJPEGString_C(Image* image, const unsigned char* string, unsigned int stringLength);
+#endif
+
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/pcre.h b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/pcre.h
new file mode 100644
index 0000000..f8ddcbf
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/include/pcre.h
@@ -0,0 +1,338 @@
+/*************************************************
+*       Perl-Compatible Regular Expressions      *
+*************************************************/
+
+/* This is the public header file for the PCRE library, to be #included by
+applications that call the PCRE functions.
+
+           Copyright (c) 1997-2008 University of Cambridge
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+    * Neither the name of the University of Cambridge nor the names of its
+      contributors may be used to endorse or promote products derived from
+      this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#ifndef _PCRE_H
+#define _PCRE_H
+
+/* The current PCRE version information. */
+
+#define PCRE_MAJOR          7
+#define PCRE_MINOR          8
+#define PCRE_PRERELEASE     
+#define PCRE_DATE           2008-09-05
+
+/* When an application links to a PCRE DLL in Windows, the symbols that are
+imported have to be identified as such. When building PCRE, the appropriate
+export setting is defined in pcre_internal.h, which includes this file. So we
+don't change existing definitions of PCRE_EXP_DECL and PCRECPP_EXP_DECL. */
+
+/**
+ * NI CHANGE
+ *
+ * We don't build the DLL version. We only build the static lib version.
+ * Since we don't want to have to #define PCRE_STATIC in every component that
+ * includes pcre.h, we're just going to go ahead and define it here.
+ *
+ * Adam Kemp, 12/15/2008
+*/
+#define PCRE_STATIC
+
+#if defined(_WIN32) && !defined(PCRE_STATIC)
+#  ifndef PCRE_EXP_DECL
+#    define PCRE_EXP_DECL  extern __declspec(dllimport)
+#  endif
+#  ifdef __cplusplus
+#    ifndef PCRECPP_EXP_DECL
+#      define PCRECPP_EXP_DECL  extern __declspec(dllimport)
+#    endif
+#    ifndef PCRECPP_EXP_DEFN
+#      define PCRECPP_EXP_DEFN  __declspec(dllimport)
+#    endif
+#  endif
+#endif
+
+/* By default, we use the standard "extern" declarations. */
+
+#ifndef PCRE_EXP_DECL
+#  ifdef __cplusplus
+#    define PCRE_EXP_DECL  extern "C"
+#  else
+#    define PCRE_EXP_DECL  extern
+#  endif
+#endif
+
+#ifdef __cplusplus
+#  ifndef PCRECPP_EXP_DECL
+#    define PCRECPP_EXP_DECL  extern
+#  endif
+#  ifndef PCRECPP_EXP_DEFN
+#    define PCRECPP_EXP_DEFN
+#  endif
+#endif
+
+/**
+ * NI CHANGE
+ *
+ * We use __cdecl on win32 and the default calling convention elsewhere.
+ *
+ * Originall this macro did not appear in this file, but it was used in
+ * internal headers. I consider it an oversight on the part of the pcre
+ * developers that * it was not used in this file. If these functions use
+ * specific calling conventions then their prototypes should include that
+ * calling convention in case some other project uses a different default.
+ *
+ * Adam Kemp 12/15/2008
+*/
+#ifndef PCRE_CALL_CONVENTION
+#  if defined(_WIN32) /* 32-bit and 64-bit */
+#    define PCRE_CALL_CONVENTION __cdecl
+#  else
+#    define PCRE_CALL_CONVENTION
+#  endif
+#else
+#  define PCRE_CALL_CONVENTION
+#endif
+
+/* Have to include stdlib.h in order to ensure that size_t is defined;
+it is needed here for malloc. */
+
+#include <stdlib.h>
+
+/* Allow for C++ users */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Options */
+
+#define PCRE_CASELESS           0x00000001
+#define PCRE_MULTILINE          0x00000002
+#define PCRE_DOTALL             0x00000004
+#define PCRE_EXTENDED           0x00000008
+#define PCRE_ANCHORED           0x00000010
+#define PCRE_DOLLAR_ENDONLY     0x00000020
+#define PCRE_EXTRA              0x00000040
+#define PCRE_NOTBOL             0x00000080
+#define PCRE_NOTEOL             0x00000100
+#define PCRE_UNGREEDY           0x00000200
+#define PCRE_NOTEMPTY           0x00000400
+#define PCRE_UTF8               0x00000800
+#define PCRE_NO_AUTO_CAPTURE    0x00001000
+#define PCRE_NO_UTF8_CHECK      0x00002000
+#define PCRE_AUTO_CALLOUT       0x00004000
+#define PCRE_PARTIAL            0x00008000
+#define PCRE_DFA_SHORTEST       0x00010000
+#define PCRE_DFA_RESTART        0x00020000
+#define PCRE_FIRSTLINE          0x00040000
+#define PCRE_DUPNAMES           0x00080000
+#define PCRE_NEWLINE_CR         0x00100000
+#define PCRE_NEWLINE_LF         0x00200000
+#define PCRE_NEWLINE_CRLF       0x00300000
+#define PCRE_NEWLINE_ANY        0x00400000
+#define PCRE_NEWLINE_ANYCRLF    0x00500000
+#define PCRE_BSR_ANYCRLF        0x00800000
+#define PCRE_BSR_UNICODE        0x01000000
+#define PCRE_JAVASCRIPT_COMPAT  0x02000000
+
+/* Exec-time and get/set-time error codes */
+
+#define PCRE_ERROR_NOMATCH         (-1)
+#define PCRE_ERROR_NULL            (-2)
+#define PCRE_ERROR_BADOPTION       (-3)
+#define PCRE_ERROR_BADMAGIC        (-4)
+#define PCRE_ERROR_UNKNOWN_OPCODE  (-5)
+#define PCRE_ERROR_UNKNOWN_NODE    (-5)  /* For backward compatibility */
+#define PCRE_ERROR_NOMEMORY        (-6)
+#define PCRE_ERROR_NOSUBSTRING     (-7)
+#define PCRE_ERROR_MATCHLIMIT      (-8)
+#define PCRE_ERROR_CALLOUT         (-9)  /* Never used by PCRE itself */
+#define PCRE_ERROR_BADUTF8        (-10)
+#define PCRE_ERROR_BADUTF8_OFFSET (-11)
+#define PCRE_ERROR_PARTIAL        (-12)
+#define PCRE_ERROR_BADPARTIAL     (-13)
+#define PCRE_ERROR_INTERNAL       (-14)
+#define PCRE_ERROR_BADCOUNT       (-15)
+#define PCRE_ERROR_DFA_UITEM      (-16)
+#define PCRE_ERROR_DFA_UCOND      (-17)
+#define PCRE_ERROR_DFA_UMLIMIT    (-18)
+#define PCRE_ERROR_DFA_WSSIZE     (-19)
+#define PCRE_ERROR_DFA_RECURSE    (-20)
+#define PCRE_ERROR_RECURSIONLIMIT (-21)
+#define PCRE_ERROR_NULLWSLIMIT    (-22)  /* No longer actually used */
+#define PCRE_ERROR_BADNEWLINE     (-23)
+
+/* Request types for pcre_fullinfo() */
+
+#define PCRE_INFO_OPTIONS            0
+#define PCRE_INFO_SIZE               1
+#define PCRE_INFO_CAPTURECOUNT       2
+#define PCRE_INFO_BACKREFMAX         3
+#define PCRE_INFO_FIRSTBYTE          4
+#define PCRE_INFO_FIRSTCHAR          4  /* For backwards compatibility */
+#define PCRE_INFO_FIRSTTABLE         5
+#define PCRE_INFO_LASTLITERAL        6
+#define PCRE_INFO_NAMEENTRYSIZE      7
+#define PCRE_INFO_NAMECOUNT          8
+#define PCRE_INFO_NAMETABLE          9
+#define PCRE_INFO_STUDYSIZE         10
+#define PCRE_INFO_DEFAULT_TABLES    11
+#define PCRE_INFO_OKPARTIAL         12
+#define PCRE_INFO_JCHANGED          13
+#define PCRE_INFO_HASCRORLF         14
+
+/* Request types for pcre_config(). Do not re-arrange, in order to remain
+compatible. */
+
+#define PCRE_CONFIG_UTF8                    0
+#define PCRE_CONFIG_NEWLINE                 1
+#define PCRE_CONFIG_LINK_SIZE               2
+#define PCRE_CONFIG_POSIX_MALLOC_THRESHOLD  3
+#define PCRE_CONFIG_MATCH_LIMIT             4
+#define PCRE_CONFIG_STACKRECURSE            5
+#define PCRE_CONFIG_UNICODE_PROPERTIES      6
+#define PCRE_CONFIG_MATCH_LIMIT_RECURSION   7
+#define PCRE_CONFIG_BSR                     8
+
+/* Bit flags for the pcre_extra structure. Do not re-arrange or redefine
+these bits, just add new ones on the end, in order to remain compatible. */
+
+#define PCRE_EXTRA_STUDY_DATA             0x0001
+#define PCRE_EXTRA_MATCH_LIMIT            0x0002
+#define PCRE_EXTRA_CALLOUT_DATA           0x0004
+#define PCRE_EXTRA_TABLES                 0x0008
+#define PCRE_EXTRA_MATCH_LIMIT_RECURSION  0x0010
+
+/* Types */
+
+struct real_pcre;                 /* declaration; the definition is private  */
+typedef struct real_pcre pcre;
+
+/* When PCRE is compiled as a C++ library, the subject pointer type can be
+replaced with a custom type. For conventional use, the public interface is a
+const char *. */
+
+#ifndef PCRE_SPTR
+#define PCRE_SPTR const char *
+#endif
+
+/* The structure for passing additional data to pcre_exec(). This is defined in
+such as way as to be extensible. Always add new fields at the end, in order to
+remain compatible. */
+
+typedef struct pcre_extra {
+  unsigned long int flags;        /* Bits for which fields are set */
+  void *study_data;               /* Opaque data from pcre_study() */
+  unsigned long int match_limit;  /* Maximum number of calls to match() */
+  void *callout_data;             /* Data passed back in callouts */
+  const unsigned char *tables;    /* Pointer to character tables */
+  unsigned long int match_limit_recursion; /* Max recursive calls to match() */
+} pcre_extra;
+
+/* The structure for passing out data via the pcre_callout_function. We use a
+structure so that new fields can be added on the end in future versions,
+without changing the API of the function, thereby allowing old clients to work
+without modification. */
+
+typedef struct pcre_callout_block {
+  int          version;           /* Identifies version of block */
+  /* ------------------------ Version 0 ------------------------------- */
+  int          callout_number;    /* Number compiled into pattern */
+  int         *offset_vector;     /* The offset vector */
+  PCRE_SPTR    subject;           /* The subject being matched */
+  int          subject_length;    /* The length of the subject */
+  int          start_match;       /* Offset to start of this match attempt */
+  int          current_position;  /* Where we currently are in the subject */
+  int          capture_top;       /* Max current capture */
+  int          capture_last;      /* Most recently closed capture */
+  void        *callout_data;      /* Data passed in with the call */
+  /* ------------------- Added for Version 1 -------------------------- */
+  int          pattern_position;  /* Offset to next item in the pattern */
+  int          next_item_length;  /* Length of next item in the pattern */
+  /* ------------------------------------------------------------------ */
+} pcre_callout_block;
+
+/* Indirection for store get and free functions. These can be set to
+alternative malloc/free functions if required. Special ones are used in the
+non-recursive case for "frames". There is also an optional callout function
+that is triggered by the (?) regex item. For Virtual Pascal, these definitions
+have to take another form. */
+
+#ifndef VPCOMPAT
+PCRE_EXP_DECL void* (PCRE_CALL_CONVENTION *pcre_malloc)(size_t);
+PCRE_EXP_DECL void  (PCRE_CALL_CONVENTION *pcre_free)(void *);
+PCRE_EXP_DECL void* (PCRE_CALL_CONVENTION *pcre_stack_malloc)(size_t);
+PCRE_EXP_DECL void  (PCRE_CALL_CONVENTION *pcre_stack_free)(void *);
+PCRE_EXP_DECL int   (PCRE_CALL_CONVENTION *pcre_callout)(pcre_callout_block *);
+#else   /* VPCOMPAT */
+PCRE_EXP_DECL void* PCRE_CALL_CONVENTION pcre_malloc(size_t);
+PCRE_EXP_DECL void  PCRE_CALL_CONVENTION pcre_free(void *);
+PCRE_EXP_DECL void* PCRE_CALL_CONVENTION pcre_stack_malloc(size_t);
+PCRE_EXP_DECL void  PCRE_CALL_CONVENTION pcre_stack_free(void *);
+PCRE_EXP_DECL int   PCRE_CALL_CONVENTION pcre_callout(pcre_callout_block *);
+#endif  /* VPCOMPAT */
+
+/* Exported PCRE functions */
+
+PCRE_EXP_DECL pcre* PCRE_CALL_CONVENTION pcre_compile(const char *, int, const char **, int *,
+                  const unsigned char *);
+PCRE_EXP_DECL pcre* PCRE_CALL_CONVENTION pcre_compile2(const char *, int, int *, const char **,
+                  int *, const unsigned char *);
+PCRE_EXP_DECL int  PCRE_CALL_CONVENTION pcre_config(int, void *);
+PCRE_EXP_DECL int  PCRE_CALL_CONVENTION pcre_copy_named_substring(const pcre *, const char *,
+                  int *, int, const char *, char *, int);
+PCRE_EXP_DECL int  PCRE_CALL_CONVENTION pcre_copy_substring(const char *, int *, int, int, char *,
+                  int);
+PCRE_EXP_DECL int  PCRE_CALL_CONVENTION pcre_dfa_exec(const pcre *, const pcre_extra *,
+                  const char *, int, int, int, int *, int , int *, int);
+PCRE_EXP_DECL int  PCRE_CALL_CONVENTION pcre_exec(const pcre *, const pcre_extra *, PCRE_SPTR,
+                   int, int, int, int *, int);
+PCRE_EXP_DECL void PCRE_CALL_CONVENTION pcre_free_substring(const char *);
+PCRE_EXP_DECL void PCRE_CALL_CONVENTION pcre_free_substring_list(const char **);
+PCRE_EXP_DECL int  PCRE_CALL_CONVENTION pcre_fullinfo(const pcre *, const pcre_extra *, int,
+                  void *);
+PCRE_EXP_DECL int  PCRE_CALL_CONVENTION pcre_get_named_substring(const pcre *, const char *,
+                  int *, int, const char *, const char **);
+PCRE_EXP_DECL int  PCRE_CALL_CONVENTION pcre_get_stringnumber(const pcre *, const char *);
+PCRE_EXP_DECL int  PCRE_CALL_CONVENTION pcre_get_stringtable_entries(const pcre *, const char *,
+                  char **, char **);
+PCRE_EXP_DECL int  PCRE_CALL_CONVENTION pcre_get_substring(const char *, int *, int, int,
+                  const char **);
+PCRE_EXP_DECL int  PCRE_CALL_CONVENTION pcre_get_substring_list(const char *, int *, int,
+                  const char ***);
+PCRE_EXP_DECL int  PCRE_CALL_CONVENTION pcre_info(const pcre *, int *, int *);
+PCRE_EXP_DECL const unsigned char* PCRE_CALL_CONVENTION pcre_maketables(void);
+PCRE_EXP_DECL int  PCRE_CALL_CONVENTION pcre_refcount(pcre *, int);
+PCRE_EXP_DECL pcre_extra* PCRE_CALL_CONVENTION pcre_study(const pcre *, int, const char **);
+PCRE_EXP_DECL const char* PCRE_CALL_CONVENTION pcre_version(void);
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif /* End of pcre.h */
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/ADXL345_I2C.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/ADXL345_I2C.cpp
new file mode 100644
index 0000000..997cf59
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/ADXL345_I2C.cpp
@@ -0,0 +1,103 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "ADXL345_I2C.h"
+#include "I2C.h"
+#include "HAL/HAL.hpp"
+
+const uint8_t ADXL345_I2C::kAddress;
+const uint8_t ADXL345_I2C::kPowerCtlRegister;
+const uint8_t ADXL345_I2C::kDataFormatRegister;
+const uint8_t ADXL345_I2C::kDataRegister;
+constexpr double ADXL345_I2C::kGsPerLSB;
+
+/**
+ * Constructor.
+ *
+ * @param port The I2C port the accelerometer is attached to
+ * @param range The range (+ or -) that the accelerometer will measure.
+ */
+ADXL345_I2C::ADXL345_I2C(Port port, Range range):
+		I2C(port, kAddress)
+{
+		//m_i2c = new I2C((I2C::Port)port, kAddress);
+
+		// Turn on the measurements
+		Write(kPowerCtlRegister, kPowerCtl_Measure);
+		// Specify the data format to read
+		SetRange(range);
+
+		HALReport(HALUsageReporting::kResourceType_ADXL345, HALUsageReporting::kADXL345_I2C, 0);
+}
+
+/**
+ * Destructor.
+ */
+ADXL345_I2C::~ADXL345_I2C()
+{
+	//delete m_i2c;
+	//m_i2c = NULL;
+}
+
+/** {@inheritdoc} */
+void ADXL345_I2C::SetRange(Range range)
+{
+	Write(kDataFormatRegister, kDataFormat_FullRes | (uint8_t)range);
+}
+
+/** {@inheritdoc} */
+double ADXL345_I2C::GetX()
+{
+	return GetAcceleration(kAxis_X);
+}
+
+/** {@inheritdoc} */
+double ADXL345_I2C::GetY()
+{
+	return GetAcceleration(kAxis_Y);
+}
+
+/** {@inheritdoc} */
+double ADXL345_I2C::GetZ()
+{
+	return GetAcceleration(kAxis_Z);
+}
+
+/**
+ * Get the acceleration of one axis in Gs.
+ *
+ * @param axis The axis to read from.
+ * @return Acceleration of the ADXL345 in Gs.
+ */
+double ADXL345_I2C::GetAcceleration(ADXL345_I2C::Axes axis)
+{
+	int16_t rawAccel = 0;
+	//if(m_i2c)
+	//{
+		Read(kDataRegister + (uint8_t)axis, sizeof(rawAccel), (uint8_t *)&rawAccel);
+	//}
+	return rawAccel * kGsPerLSB;
+}
+
+/**
+ * Get the acceleration of all axes in Gs.
+ *
+ * @return An object containing the acceleration measured on each axis of the ADXL345 in Gs.
+ */
+ADXL345_I2C::AllAxes ADXL345_I2C::GetAccelerations()
+{
+	AllAxes data = AllAxes();
+	int16_t rawData[3];
+	//if (m_i2c)
+	//{
+		Read(kDataRegister, sizeof(rawData), (uint8_t*)rawData);
+
+		data.XAxis = rawData[0] * kGsPerLSB;
+		data.YAxis = rawData[1] * kGsPerLSB;
+		data.ZAxis = rawData[2] * kGsPerLSB;
+	//}
+	return data;
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/ADXL345_SPI.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/ADXL345_SPI.cpp
new file mode 100644
index 0000000..77c793d
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/ADXL345_SPI.cpp
@@ -0,0 +1,140 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "ADXL345_SPI.h"
+#include "DigitalInput.h"
+#include "DigitalOutput.h"
+#include "SPI.h"
+
+const uint8_t ADXL345_SPI::kPowerCtlRegister;
+const uint8_t ADXL345_SPI::kDataFormatRegister;
+const uint8_t ADXL345_SPI::kDataRegister;
+constexpr double ADXL345_SPI::kGsPerLSB;
+
+
+/**
+ * Constructor.
+ *
+ * @param port The SPI port the accelerometer is attached to
+ * @param range The range (+ or -) that the accelerometer will measure.
+ */
+ADXL345_SPI::ADXL345_SPI(SPI::Port port, ADXL345_SPI::Range range)
+{
+	m_port = port;
+	Init(range);
+}
+
+/**
+ * Internal common init function.
+ */
+void ADXL345_SPI::Init(Range range)
+{
+		m_spi = new SPI(m_port);
+		m_spi->SetClockRate(500000);
+		m_spi->SetMSBFirst();
+		m_spi->SetSampleDataOnFalling();
+		m_spi->SetClockActiveLow();
+		m_spi->SetChipSelectActiveHigh();
+
+		uint8_t commands[2];
+		// Turn on the measurements
+		commands[0] = kPowerCtlRegister;
+		commands[1] = kPowerCtl_Measure;
+		m_spi->Transaction(commands, commands, 2);
+
+		SetRange(range);
+
+		HALReport(HALUsageReporting::kResourceType_ADXL345, HALUsageReporting::kADXL345_SPI);
+}
+
+/**
+ * Destructor.
+ */
+ADXL345_SPI::~ADXL345_SPI()
+{
+	delete m_spi;
+	m_spi = NULL;
+}
+
+/** {@inheritdoc} */
+void ADXL345_SPI::SetRange(Range range)
+{
+	uint8_t commands[2];
+	
+	// Specify the data format to read
+	commands[0] = kDataFormatRegister;
+	commands[1] = kDataFormat_FullRes| (uint8_t)(range & 0x03);
+	m_spi->Transaction(commands, commands, 2);
+}
+
+/** {@inheritdoc} */
+double ADXL345_SPI::GetX()
+{
+	return GetAcceleration(kAxis_X);
+}
+
+/** {@inheritdoc} */
+double ADXL345_SPI::GetY()
+{
+	return GetAcceleration(kAxis_Y);
+}
+
+/** {@inheritdoc} */
+double ADXL345_SPI::GetZ()
+{
+	return GetAcceleration(kAxis_Z);
+}
+
+/**
+ * Get the acceleration of one axis in Gs.
+ *
+ * @param axis The axis to read from.
+ * @return Acceleration of the ADXL345 in Gs.
+ */
+double ADXL345_SPI::GetAcceleration(ADXL345_SPI::Axes axis)
+{
+	int16_t rawAccel = 0;
+	if(m_spi)
+	{
+		uint8_t buffer[3];
+		uint8_t command[3] = {0,0,0};
+		command[0] = (kAddress_Read | kAddress_MultiByte | kDataRegister) + (uint8_t)axis;
+		m_spi->Transaction(command, buffer, 3);
+
+		// Sensor is little endian... swap bytes
+		rawAccel = buffer[2]<<8 | buffer[1];
+	}
+	return rawAccel * kGsPerLSB;
+}
+
+/**
+ * Get the acceleration of all axes in Gs.
+ *
+ * @return An object containing the acceleration measured on each axis of the ADXL345 in Gs.
+ */
+ADXL345_SPI::AllAxes ADXL345_SPI::GetAccelerations()
+{
+	AllAxes data = AllAxes();
+	uint8_t dataBuffer[7] = {0,0,0,0,0,0,0};
+	int16_t rawData[3];
+	if (m_spi)
+	{
+		// Select the data address.
+		dataBuffer[0] = (kAddress_Read | kAddress_MultiByte | kDataRegister);
+		m_spi->Transaction(dataBuffer, dataBuffer, 7);
+
+		for (int32_t i=0; i<3; i++)
+		{
+			// Sensor is little endian... swap bytes
+			rawData[i] = dataBuffer[i*2+2] << 8 | dataBuffer[i*2+1];
+		}
+
+		data.XAxis = rawData[0] * kGsPerLSB;
+		data.YAxis = rawData[1] * kGsPerLSB;
+		data.ZAxis = rawData[2] * kGsPerLSB;
+	}
+	return data;
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/AnalogAccelerometer.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/AnalogAccelerometer.cpp
new file mode 100644
index 0000000..15edf4b
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/AnalogAccelerometer.cpp
@@ -0,0 +1,110 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "AnalogAccelerometer.h"
+//#include "NetworkCommunication/UsageReporting.h"
+#include "WPIErrors.h"
+
+/**
+ * Common function for initializing the accelerometer.
+ */
+void AnalogAccelerometer::InitAccelerometer()
+{
+	m_voltsPerG = 1.0;
+	m_zeroGVoltage = 2.5;
+	HALReport(HALUsageReporting::kResourceType_Accelerometer, m_AnalogInput->GetChannel());
+}
+
+/**
+ * Create a new instance of an accelerometer.
+ * The constructor allocates desired analog input.
+ * @param channel The channel number for the analog input the accelerometer is connected to
+ */
+AnalogAccelerometer::AnalogAccelerometer(int32_t channel)
+{
+	m_AnalogInput = new AnalogInput(channel);
+	m_allocatedChannel = true;
+	InitAccelerometer();
+}
+
+/**
+ * Create a new instance of Accelerometer from an existing AnalogInput.
+ * Make a new instance of accelerometer given an AnalogInput. This is particularly
+ * useful if the port is going to be read as an analog channel as well as through
+ * the Accelerometer class.
+ * @param channel The existing AnalogInput object for the analog input the accelerometer is connected to
+ */
+AnalogAccelerometer::AnalogAccelerometer(AnalogInput *channel)
+{
+	if (channel == NULL)
+	{
+		wpi_setWPIError(NullParameter);
+	}
+	else
+	{
+		m_AnalogInput = channel;
+		InitAccelerometer();
+	}
+	m_allocatedChannel = false;
+}
+
+/**
+ * Delete the analog components used for the accelerometer.
+ */
+AnalogAccelerometer::~AnalogAccelerometer()
+{
+	if (m_allocatedChannel)
+	{
+		delete m_AnalogInput;
+	}
+}
+
+/**
+ * Return the acceleration in Gs.
+ *
+ * The acceleration is returned units of Gs.
+ *
+ * @return The current acceleration of the sensor in Gs.
+ */
+float AnalogAccelerometer::GetAcceleration()
+{
+	return (m_AnalogInput->GetAverageVoltage() - m_zeroGVoltage) / m_voltsPerG;
+}
+
+/**
+ * Set the accelerometer sensitivity.
+ *
+ * This sets the sensitivity of the accelerometer used for calculating the acceleration.
+ * The sensitivity varies by accelerometer model. There are constants defined for various models.
+ *
+ * @param sensitivity The sensitivity of accelerometer in Volts per G.
+ */
+void AnalogAccelerometer::SetSensitivity(float sensitivity)
+{
+	m_voltsPerG = sensitivity;
+}
+
+/**
+ * Set the voltage that corresponds to 0 G.
+ *
+ * The zero G voltage varies by accelerometer model. There are constants defined for various models.
+ *
+ * @param zero The zero G voltage.
+ */
+void AnalogAccelerometer::SetZero(float zero)
+{
+	m_zeroGVoltage = zero;
+}
+
+/**
+ * Get the Acceleration for the PID Source parent.
+ *
+ * @return The current acceleration in Gs.
+ */
+double AnalogAccelerometer::PIDGet()
+{
+	return GetAcceleration();
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/AnalogInput.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/AnalogInput.cpp
new file mode 100644
index 0000000..bf19a9c
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/AnalogInput.cpp
@@ -0,0 +1,414 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "AnalogInput.h"
+//#include "NetworkCommunication/UsageReporting.h"
+#include "Resource.h"
+#include "Timer.h"
+#include "WPIErrors.h"
+
+static Resource *inputs = NULL;
+
+const uint8_t AnalogInput::kAccumulatorModuleNumber;
+const uint32_t AnalogInput::kAccumulatorNumChannels;
+const uint32_t AnalogInput::kAccumulatorChannels[] = {0, 1};
+
+/**
+ * Common initialization.
+ */
+void AnalogInput::InitAnalogInput(uint32_t channel)
+{
+	char buf[64];
+	Resource::CreateResourceObject(&inputs, kAnalogInputs);
+
+	if (!checkAnalogInputChannel(channel))
+	{
+		snprintf(buf, 64, "analog input %d", channel);
+		wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf);
+		return;
+	}
+
+	snprintf(buf, 64, "Analog Input %d", channel);
+	if (inputs->Allocate(channel, buf) == ~0ul)
+	{
+		CloneError(inputs);
+		return;
+	}
+
+	m_channel = channel;
+
+	void* port = getPort(channel);
+	int32_t status = 0;
+	m_port = initializeAnalogInputPort(port, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+	HALReport(HALUsageReporting::kResourceType_AnalogChannel, channel);
+}
+
+/**
+ * Construct an analog input.
+ *
+ * @param channel The channel number on the roboRIO to represent. 0-3 are on-board 4-7 are on the MXP port.
+ */
+AnalogInput::AnalogInput(uint32_t channel)
+{
+	InitAnalogInput(channel);
+}
+
+/**
+ * Channel destructor.
+ */
+AnalogInput::~AnalogInput()
+{
+	inputs->Free(m_channel);
+}
+
+/**
+ * Get a sample straight from this channel.
+ * The sample is a 12-bit value representing the 0V to 5V range of the A/D converter in the module.
+ * The units are in A/D converter codes.  Use GetVoltage() to get the analog value in calibrated units.
+ * @return A sample straight from this channel.
+ */
+int16_t AnalogInput::GetValue()
+{
+	if (StatusIsFatal()) return 0;
+	int32_t status = 0;
+	int16_t value = getAnalogValue(m_port, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	return value;
+}
+
+/**
+ * Get a sample from the output of the oversample and average engine for this channel.
+ * The sample is 12-bit + the bits configured in SetOversampleBits().
+ * The value configured in SetAverageBits() will cause this value to be averaged 2**bits number of samples.
+ * This is not a sliding window.  The sample will not change until 2**(OversampleBits + AverageBits) samples
+ * have been acquired from the module on this channel.
+ * Use GetAverageVoltage() to get the analog value in calibrated units.
+ * @return A sample from the oversample and average engine for this channel.
+ */
+int32_t AnalogInput::GetAverageValue()
+{
+	if (StatusIsFatal()) return 0;
+	int32_t status = 0;
+	int32_t value = getAnalogAverageValue(m_port, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	return value;
+}
+
+/**
+ * Get a scaled sample straight from this channel.
+ * The value is scaled to units of Volts using the calibrated scaling data from GetLSBWeight() and GetOffset().
+ * @return A scaled sample straight from this channel.
+ */
+float AnalogInput::GetVoltage()
+{
+	if (StatusIsFatal()) return 0.0f;
+	int32_t status = 0;
+	float voltage = getAnalogVoltage(m_port, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	return voltage;
+}
+
+/**
+ * Get a scaled sample from the output of the oversample and average engine for this channel.
+ * The value is scaled to units of Volts using the calibrated scaling data from GetLSBWeight() and GetOffset().
+ * Using oversampling will cause this value to be higher resolution, but it will update more slowly.
+ * Using averaging will cause this value to be more stable, but it will update more slowly.
+ * @return A scaled sample from the output of the oversample and average engine for this channel.
+ */
+float AnalogInput::GetAverageVoltage()
+{
+	if (StatusIsFatal()) return 0.0f;
+	int32_t status = 0;
+	float voltage = getAnalogAverageVoltage(m_port, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	return voltage;
+}
+
+/**
+ * Get the factory scaling least significant bit weight constant.
+ *
+ * Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9)
+ *
+ * @return Least significant bit weight.
+ */
+uint32_t AnalogInput::GetLSBWeight()
+{
+	if (StatusIsFatal()) return 0;
+	int32_t status = 0;
+	int32_t lsbWeight = getAnalogLSBWeight(m_port, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	return lsbWeight;
+}
+
+/**
+ * Get the factory scaling offset constant.
+ *
+ * Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9)
+ *
+ * @return Offset constant.
+ */
+int32_t AnalogInput::GetOffset()
+{
+	if (StatusIsFatal()) return 0;
+	int32_t status = 0;
+	int32_t offset = getAnalogOffset(m_port, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	return offset;
+}
+
+/**
+ * Get the channel number.
+ * @return The channel number.
+ */
+uint32_t AnalogInput::GetChannel()
+{
+	if (StatusIsFatal()) return 0;
+	return m_channel;
+}
+
+/**
+ * Set the number of averaging bits.
+ * This sets the number of averaging bits. The actual number of averaged samples is 2^bits.
+ * Use averaging to improve the stability of your measurement at the expense of sampling rate.
+ * The averaging is done automatically in the FPGA.
+ *
+ * @param bits Number of bits of averaging.
+ */
+void AnalogInput::SetAverageBits(uint32_t bits)
+{
+	if (StatusIsFatal()) return;
+	int32_t status = 0;
+	setAnalogAverageBits(m_port, bits, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Get the number of averaging bits previously configured.
+ * This gets the number of averaging bits from the FPGA. The actual number of averaged samples is 2^bits.
+ * The averaging is done automatically in the FPGA.
+ *
+ * @return Number of bits of averaging previously configured.
+ */
+uint32_t AnalogInput::GetAverageBits()
+{
+	int32_t status = 0;
+	int32_t averageBits = getAnalogAverageBits(m_port, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	return averageBits;
+}
+
+/**
+ * Set the number of oversample bits.
+ * This sets the number of oversample bits. The actual number of oversampled values is 2^bits.
+ * Use oversampling to improve the resolution of your measurements at the expense of sampling rate.
+ * The oversampling is done automatically in the FPGA.
+ *
+ * @param bits Number of bits of oversampling.
+ */
+void AnalogInput::SetOversampleBits(uint32_t bits)
+{
+	if (StatusIsFatal()) return;
+	int32_t status = 0;
+	setAnalogOversampleBits(m_port, bits, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Get the number of oversample bits previously configured.
+ * This gets the number of oversample bits from the FPGA. The actual number of oversampled values is
+ * 2^bits. The oversampling is done automatically in the FPGA.
+ *
+ * @return Number of bits of oversampling previously configured.
+ */
+uint32_t AnalogInput::GetOversampleBits()
+{
+	if (StatusIsFatal()) return 0;
+	int32_t status = 0;
+	int32_t oversampleBits = getAnalogOversampleBits(m_port, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	return oversampleBits;
+}
+
+/**
+ * Is the channel attached to an accumulator.
+ *
+ * @return The analog input is attached to an accumulator.
+ */
+bool AnalogInput::IsAccumulatorChannel()
+{
+	if (StatusIsFatal()) return false;
+	int32_t status = 0;
+	bool isAccum = isAccumulatorChannel(m_port, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	return isAccum;
+}
+
+/**
+ * Initialize the accumulator.
+ */
+void AnalogInput::InitAccumulator()
+{
+	if (StatusIsFatal()) return;
+	m_accumulatorOffset = 0;
+	int32_t status = 0;
+	initAccumulator(m_port, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+
+/**
+ * Set an initial value for the accumulator.
+ *
+ * This will be added to all values returned to the user.
+ * @param initialValue The value that the accumulator should start from when reset.
+ */
+void AnalogInput::SetAccumulatorInitialValue(int64_t initialValue)
+{
+	if (StatusIsFatal()) return;
+	m_accumulatorOffset = initialValue;
+}
+
+/**
+ * Resets the accumulator to the initial value.
+ */
+void AnalogInput::ResetAccumulator()
+{
+	if (StatusIsFatal()) return;
+	int32_t status = 0;
+	resetAccumulator(m_port, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+	if(!StatusIsFatal())
+	{
+		// Wait until the next sample, so the next call to GetAccumulator*()
+		// won't have old values.
+		const float sampleTime = 1.0f / GetSampleRate();
+		const float overSamples = 1 << GetOversampleBits();
+		const float averageSamples = 1 << GetAverageBits();
+		Wait(sampleTime * overSamples * averageSamples);
+	}
+}
+
+/**
+ * Set the center value of the accumulator.
+ *
+ * The center value is subtracted from each A/D value before it is added to the accumulator. This
+ * is used for the center value of devices like gyros and accelerometers to 
+ * take the device offset into account when integrating.
+ *
+ * This center value is based on the output of the oversampled and averaged source from the accumulator
+ * channel. Because of this, any non-zero oversample bits will affect the size of the value for this field.
+ */
+void AnalogInput::SetAccumulatorCenter(int32_t center)
+{
+	if (StatusIsFatal()) return;
+	int32_t status = 0;
+	setAccumulatorCenter(m_port, center, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Set the accumulator's deadband.
+ * @param 
+ */
+void AnalogInput::SetAccumulatorDeadband(int32_t deadband)
+{
+	if (StatusIsFatal()) return;
+	int32_t status = 0;
+	setAccumulatorDeadband(m_port, deadband, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Read the accumulated value.
+ *
+ * Read the value that has been accumulating.
+ * The accumulator is attached after the oversample and average engine.
+ *
+ * @return The 64-bit value accumulated since the last Reset().
+ */
+int64_t AnalogInput::GetAccumulatorValue()
+{
+	if (StatusIsFatal()) return 0;
+	int32_t status = 0;
+	int64_t value = getAccumulatorValue(m_port, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	return value + m_accumulatorOffset;
+}
+
+/**
+ * Read the number of accumulated values.
+ *
+ * Read the count of the accumulated values since the accumulator was last Reset().
+ *
+ * @return The number of times samples from the channel were accumulated.
+ */
+uint32_t AnalogInput::GetAccumulatorCount()
+{
+	if (StatusIsFatal()) return 0;
+	int32_t status = 0;
+	uint32_t count = getAccumulatorCount(m_port, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	return count;
+}
+
+
+/**
+ * Read the accumulated value and the number of accumulated values atomically.
+ *
+ * This function reads the value and count from the FPGA atomically.
+ * This can be used for averaging.
+ *
+ * @param value Pointer to the 64-bit accumulated output.
+ * @param count Pointer to the number of accumulation cycles.
+ */
+void AnalogInput::GetAccumulatorOutput(int64_t *value, uint32_t *count)
+{
+	if (StatusIsFatal()) return;
+	int32_t status = 0;
+	getAccumulatorOutput(m_port, value, count, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	*value += m_accumulatorOffset;
+}
+
+/**
+ * Set the sample rate per channel for all analog channels.
+ * The maximum rate is 500kS/s divided by the number of channels in use.
+ * This is 62500 samples/s per channel.
+ * @param samplesPerSecond The number of samples per second.
+ */
+void AnalogInput::SetSampleRate(float samplesPerSecond)
+{
+	int32_t status = 0;
+	setAnalogSampleRate(samplesPerSecond, &status);
+	wpi_setGlobalErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Get the current sample rate for all channels
+ *
+ * @return Sample rate.
+ */
+float AnalogInput::GetSampleRate()
+{
+	int32_t status = 0;
+	float sampleRate = getAnalogSampleRate(&status);
+	wpi_setGlobalErrorWithContext(status, getHALErrorMessage(status));
+	return sampleRate;
+}
+
+/**
+ * Get the Average value for the PID Source base object.
+ *
+ * @return The average voltage.
+ */
+double AnalogInput::PIDGet()
+{
+	if (StatusIsFatal()) return 0.0;
+	return GetAverageVoltage();
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/AnalogOutput.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/AnalogOutput.cpp
new file mode 100644
index 0000000..6cdfaa6
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/AnalogOutput.cpp
@@ -0,0 +1,82 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+#include "AnalogOutput.h"
+#include "Resource.h"
+#include "WPIErrors.h"
+
+static Resource *outputs = NULL;
+
+void AnalogOutput::InitAnalogOutput(uint32_t channel) {
+    Resource::CreateResourceObject(&outputs, kAnalogOutputs);
+
+    char buf[64];
+
+    if(!checkAnalogOutputChannel(channel))
+    {
+        snprintf(buf, 64, "analog input %d", channel);
+        wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf);
+        return;
+    }
+
+    if(outputs->Allocate(channel, buf) == ~0ul)
+    {
+        CloneError(outputs);
+        return;
+    }
+
+    m_channel = channel;
+
+    void* port = getPort(m_channel);
+    int32_t status = 0;
+    m_port = initializeAnalogOutputPort(port, &status);
+    wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+    HALReport(HALUsageReporting::kResourceType_AnalogChannel, m_channel, 0);
+}
+
+/**
+ * Construct an analog output on the given channel.
+ * All analog outputs are located on the MXP port.
+ * @param The channel number on the roboRIO to represent.
+ */
+AnalogOutput::AnalogOutput(uint32_t channel) {
+    InitAnalogOutput(channel);
+}
+
+/**
+ * Destructor. Frees analog output resource
+ */
+AnalogOutput::~AnalogOutput() {
+    outputs->Free(m_channel);
+}
+
+/**
+ * Set the value of the analog output
+ *
+ * @param voltage The output value in Volts, from 0.0 to +5.0
+ */
+void AnalogOutput::SetVoltage(float voltage) {
+    int32_t status = 0;
+    setAnalogOutput(m_port, voltage, &status);
+
+    wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Get the voltage of the analog output
+ *
+ * @return The value in Volts, from 0.0 to +5.0
+ */
+float AnalogOutput::GetVoltage() {
+    int32_t status = 0;
+    float voltage = getAnalogOutput(m_port, &status);
+
+    wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+    return voltage;
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/AnalogPotentiometer.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/AnalogPotentiometer.cpp
new file mode 100644
index 0000000..0ba7dbd
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/AnalogPotentiometer.cpp
@@ -0,0 +1,73 @@
+
+#include "AnalogPotentiometer.h"
+#include "ControllerPower.h"
+
+/**
+ * Common initialization code called by all constructors.
+ */
+void AnalogPotentiometer::initPot(AnalogInput *input, double fullRange, double offset) {
+    m_fullRange = fullRange;
+    m_offset = offset;
+    m_analog_input = input;
+}
+
+/**
+ * Construct an Analog Potentiometer object from a channel number.
+ * @param channel The channel number on the roboRIO to represent. 0-3 are on-board 4-7 are on the MXP port.
+ * @param fullRange The angular value (in desired units) representing the full 0-5V range of the input.
+ * @param offset The angular value (in desired units) representing the angular output at 0V.
+ */
+AnalogPotentiometer::AnalogPotentiometer(int channel, double fullRange, double offset) {
+    m_init_analog_input = true;
+    initPot(new AnalogInput(channel), fullRange, offset);
+}
+
+/**
+ * Construct an Analog Potentiometer object from an existing Analog Input pointer.
+ * @param channel The existing Analog Input pointer 
+ * @param fullRange The angular value (in desired units) representing the full 0-5V range of the input.
+ * @param offset The angular value (in desired units) representing the angular output at 0V.
+ */
+AnalogPotentiometer::AnalogPotentiometer(AnalogInput *input, double fullRange, double offset) {
+    m_init_analog_input = false;
+    initPot(input, fullRange, offset);
+}
+
+/**
+ * Construct an Analog Potentiometer object from an existing Analog Input reference.
+ * @param channel The existing Analog Input reference 
+ * @param fullRange The angular value (in desired units) representing the full 0-5V range of the input.
+ * @param offset The angular value (in desired units) representing the angular output at 0V.
+ */
+AnalogPotentiometer::AnalogPotentiometer(AnalogInput &input, double fullRange, double offset) {
+    m_init_analog_input = false;
+    initPot(&input, fullRange, offset);
+}
+
+/**
+ * Destructor. Releases the Analog Input resource if it was allocated by this object
+ */
+AnalogPotentiometer::~AnalogPotentiometer() {
+  if(m_init_analog_input){
+    delete m_analog_input;
+    m_init_analog_input = false;
+  }
+}
+
+/**
+ * Get the current reading of the potentiometer.
+ *
+ * @return The current position of the potentiometer (in the units used for fullRaneg and offset).
+ */
+double AnalogPotentiometer::Get() {
+    return (m_analog_input->GetVoltage() / ControllerPower::GetVoltage5V()) * m_fullRange + m_offset;
+}
+
+/**
+ * Implement the PIDSource interface.
+ *
+ * @return The current reading.
+ */
+double AnalogPotentiometer::PIDGet() {
+    return Get();
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/AnalogTrigger.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/AnalogTrigger.cpp
new file mode 100644
index 0000000..61cd014
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/AnalogTrigger.cpp
@@ -0,0 +1,166 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "AnalogTrigger.h"
+
+#include "AnalogInput.h"
+//#include "NetworkCommunication/UsageReporting.h"
+#include "Resource.h"
+#include "WPIErrors.h"
+
+/**
+ * Initialize an analog trigger from a channel.
+ */
+void AnalogTrigger::InitTrigger(uint32_t channel)
+{
+	void* port = getPort(channel);
+	int32_t status = 0;
+	uint32_t index = 0;
+	m_trigger = initializeAnalogTrigger(port, &index, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	m_index = index;
+
+	HALReport(HALUsageReporting::kResourceType_AnalogTrigger, channel);
+}
+
+/**
+ * Constructor for an analog trigger given a channel number.
+ *
+ * @param channel The channel number on the roboRIO to represent. 0-3 are on-board 4-7 are on the MXP port.
+ */
+AnalogTrigger::AnalogTrigger(int32_t channel)
+{
+	InitTrigger(channel);
+}
+
+/**
+ * Construct an analog trigger given an analog input.
+ * This should be used in the case of sharing an analog channel between the
+ * trigger and an analog input object.
+ * @param channel The pointer to the existing AnalogInput object
+ */
+AnalogTrigger::AnalogTrigger(AnalogInput *input)
+{
+	InitTrigger(input->GetChannel());
+}
+
+AnalogTrigger::~AnalogTrigger()
+{
+	int32_t status = 0;
+	cleanAnalogTrigger(m_trigger, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Set the upper and lower limits of the analog trigger.
+ * The limits are given in ADC codes.  If oversampling is used, the units must be scaled
+ * appropriately.
+ * @param lower The lower limit of the trigger in ADC codes (12-bit values).
+ * @param upper The upper limit of the trigger in ADC codes (12-bit values).
+ */
+void AnalogTrigger::SetLimitsRaw(int32_t lower, int32_t upper)
+{
+	if (StatusIsFatal()) return;
+	int32_t status = 0;
+	setAnalogTriggerLimitsRaw(m_trigger, lower, upper, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Set the upper and lower limits of the analog trigger.
+ * The limits are given as floating point voltage values.
+ * @param lower The lower limit of the trigger in Volts.
+ * @param upper The upper limit of the trigger in Volts.
+ */
+void AnalogTrigger::SetLimitsVoltage(float lower, float upper)
+{
+	if (StatusIsFatal()) return;
+	int32_t status = 0;
+	setAnalogTriggerLimitsVoltage(m_trigger, lower, upper, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Configure the analog trigger to use the averaged vs. raw values.
+ * If the value is true, then the averaged value is selected for the analog trigger, otherwise
+ * the immediate value is used.
+ * @param useAveragedValue If true, use the Averaged value, otherwise use the instantaneous reading
+ */
+void AnalogTrigger::SetAveraged(bool useAveragedValue)
+{
+	if (StatusIsFatal()) return;
+	int32_t status = 0;
+	setAnalogTriggerAveraged(m_trigger, useAveragedValue, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Configure the analog trigger to use a filtered value.
+ * The analog trigger will operate with a 3 point average rejection filter. This is designed to
+ * help with 360 degree pot applications for the period where the pot crosses through zero.
+ * @param useFilteredValue If true, use the 3 point rejection filter, otherwise use the unfiltered value
+ */
+void AnalogTrigger::SetFiltered(bool useFilteredValue)
+{
+	if (StatusIsFatal()) return;
+	int32_t status = 0;
+	setAnalogTriggerFiltered(m_trigger, useFilteredValue, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Return the index of the analog trigger.
+ * This is the FPGA index of this analog trigger instance.
+ * @return The index of the analog trigger.
+ */
+uint32_t AnalogTrigger::GetIndex()
+{
+	if (StatusIsFatal()) return ~0ul;
+	return m_index;
+}
+
+/**
+ * Return the InWindow output of the analog trigger.
+ * True if the analog input is between the upper and lower limits.
+ * @return True if the analog input is between the upper and lower limits.
+ */
+bool AnalogTrigger::GetInWindow()
+{
+	if (StatusIsFatal()) return false;
+	int32_t status = 0;
+	bool result = getAnalogTriggerInWindow(m_trigger, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	return result;
+}
+
+/**
+ * Return the TriggerState output of the analog trigger.
+ * True if above upper limit.
+ * False if below lower limit.
+ * If in Hysteresis, maintain previous state.
+ * @return True if above upper limit. False if below lower limit. If in Hysteresis, maintain previous state.
+ */
+bool AnalogTrigger::GetTriggerState()
+{
+	if (StatusIsFatal()) return false;
+	int32_t status = 0;
+	bool result = getAnalogTriggerTriggerState(m_trigger, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	return result;
+}
+
+/**
+ * Creates an AnalogTriggerOutput object.
+ * Gets an output object that can be used for routing.
+ * Caller is responsible for deleting the AnalogTriggerOutput object.
+ * @param type An enum of the type of output object to create.
+ * @return A pointer to a new AnalogTriggerOutput object.
+ */
+AnalogTriggerOutput *AnalogTrigger::CreateOutput(AnalogTriggerType type)
+{
+	if (StatusIsFatal()) return NULL;
+	return new AnalogTriggerOutput(this, type);
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/AnalogTriggerOutput.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/AnalogTriggerOutput.cpp
new file mode 100644
index 0000000..65febfa
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/AnalogTriggerOutput.cpp
@@ -0,0 +1,74 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "AnalogTriggerOutput.h"
+#include "AnalogTrigger.h"
+//#include "NetworkCommunication/UsageReporting.h"
+#include "WPIErrors.h"
+
+/**
+ * Create an object that represents one of the four outputs from an analog trigger.
+ *
+ * Because this class derives from DigitalSource, it can be passed into routing functions
+ * for Counter, Encoder, etc.
+ *
+ * @param trigger A pointer to the trigger for which this is an output.
+ * @param outputType An enum that specifies the output on the trigger to represent.
+ */
+AnalogTriggerOutput::AnalogTriggerOutput(AnalogTrigger *trigger, AnalogTriggerType outputType)
+	: m_trigger (trigger)
+	, m_outputType (outputType)
+{
+	HALReport(HALUsageReporting::kResourceType_AnalogTriggerOutput, trigger->GetIndex(), outputType);
+}
+
+AnalogTriggerOutput::~AnalogTriggerOutput()
+{
+	if (m_interrupt != NULL)
+	{
+		int32_t status = 0;
+		cleanInterrupts(m_interrupt, &status);
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+		m_interrupt = NULL;
+		m_interrupts->Free(m_interruptIndex);
+	}
+}
+
+/**
+ * Get the state of the analog trigger output.
+ * @return The state of the analog trigger output.
+ */
+bool AnalogTriggerOutput::Get()
+{
+  int32_t status = 0;
+  bool result = getAnalogTriggerOutput(m_trigger->m_trigger, m_outputType, &status);
+  wpi_setErrorWithContext(status, getHALErrorMessage(status));
+  return result;
+}
+
+/**
+ * @return The value to be written to the channel field of a routing mux.
+ */
+uint32_t AnalogTriggerOutput::GetChannelForRouting()
+{
+	return (m_trigger->m_index << 2) + m_outputType;
+}
+
+/**
+ * @return The value to be written to the module field of a routing mux.
+ */
+uint32_t AnalogTriggerOutput::GetModuleForRouting()
+{
+	return 0;
+}
+
+/**
+ * @return The value to be written to the module field of a routing mux.
+ */
+bool AnalogTriggerOutput::GetAnalogTriggerForRouting()
+{
+	return true;
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/BuiltInAccelerometer.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/BuiltInAccelerometer.cpp
new file mode 100644
index 0000000..57f7b57
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/BuiltInAccelerometer.cpp
@@ -0,0 +1,61 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "BuiltInAccelerometer.h"
+#include "HAL/HAL.hpp"
+#include "WPIErrors.h"
+
+/**
+ * Constructor.
+ * @param range The range the accelerometer will measure
+ */
+BuiltInAccelerometer::BuiltInAccelerometer(Range range)
+{
+	SetRange(range);
+
+	HALReport(HALUsageReporting::kResourceType_Accelerometer, 0, 0, "Built-in accelerometer");
+}
+
+BuiltInAccelerometer::~BuiltInAccelerometer()
+{
+}
+
+/** {@inheritdoc} */
+void BuiltInAccelerometer::SetRange(Range range)
+{
+	if(range == kRange_16G)
+	{
+		wpi_setWPIErrorWithContext(ParameterOutOfRange, "16G range not supported (use k2G, k4G, or k8G)");
+	}
+
+	setAccelerometerActive(false);
+	setAccelerometerRange((AccelerometerRange)range);
+	setAccelerometerActive(true);
+}
+
+/**
+ * @return The acceleration of the RoboRIO along the X axis in g-forces
+ */
+double BuiltInAccelerometer::GetX()
+{
+	return getAccelerometerX();
+}
+
+/**
+ * @return The acceleration of the RoboRIO along the Y axis in g-forces
+ */
+double BuiltInAccelerometer::GetY()
+{
+	return getAccelerometerY();
+}
+
+/**
+ * @return The acceleration of the RoboRIO along the Z axis in g-forces
+ */
+double BuiltInAccelerometer::GetZ()
+{
+	return getAccelerometerZ();
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/CANJaguar.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/CANJaguar.cpp
new file mode 100644
index 0000000..909fec5
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/CANJaguar.cpp
@@ -0,0 +1,2061 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2009. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "CANJaguar.h"
+#include "Timer.h"
+#define tNIRIO_i32 int
+#include "NetworkCommunication/CANSessionMux.h"
+#include "CAN/can_proto.h"
+//#include "NetworkCommunication/UsageReporting.h"
+#include "WPIErrors.h"
+#include <cstdio>
+#include <cassert>
+
+/* we are on ARM-LE now, not Freescale so no need to swap */
+#define swap16(x)	(x)
+#define swap32(x)	(x)
+
+/* Compare floats for equality as fixed point numbers */
+#define FXP8_EQ(a,b) ((int16_t)((a)*256.0)==(int16_t)((b)*256.0))
+#define FXP16_EQ(a,b) ((int32_t)((a)*65536.0)==(int32_t)((b)*65536.0))
+
+const int32_t CANJaguar::kControllerRate;
+constexpr double CANJaguar::kApproxBusVoltage;
+
+static const int32_t kSendMessagePeriod = 20;
+static const uint32_t kFullMessageIDMask = (CAN_MSGID_API_M | CAN_MSGID_MFR_M | CAN_MSGID_DTYPE_M);
+
+static const int32_t kReceiveStatusAttempts = 50;
+
+static Resource *allocated = NULL;
+
+static int32_t sendMessageHelper(uint32_t messageID, const uint8_t *data, uint8_t dataSize, int32_t period)
+{
+	static const uint32_t kTrustedMessages[] = {
+			LM_API_VOLT_T_EN, LM_API_VOLT_T_SET, LM_API_SPD_T_EN, LM_API_SPD_T_SET,
+			LM_API_VCOMP_T_EN, LM_API_VCOMP_T_SET, LM_API_POS_T_EN, LM_API_POS_T_SET,
+			LM_API_ICTRL_T_EN, LM_API_ICTRL_T_SET};
+
+	int32_t status=0;
+
+	for (uint8_t i=0; i<(sizeof(kTrustedMessages)/sizeof(kTrustedMessages[0])); i++)
+	{
+		if ((kFullMessageIDMask & messageID) == kTrustedMessages[i])
+		{
+			uint8_t dataBuffer[8];
+			dataBuffer[0] = 0;
+			dataBuffer[1] = 0;
+
+			// Make sure the data will still fit after adjusting for the token.
+			assert(dataSize <= 6);
+
+			for (uint8_t j=0; j < dataSize; j++)
+			{
+				dataBuffer[j + 2] = data[j];
+			}
+
+			FRC_NetworkCommunication_CANSessionMux_sendMessage(messageID, dataBuffer, dataSize + 2, period, &status);
+
+			return status;
+		}
+	}
+
+	FRC_NetworkCommunication_CANSessionMux_sendMessage(messageID, data, dataSize, period, &status);
+
+	return status;
+}
+
+/**
+ * Common initialization code called by all constructors.
+ */
+void CANJaguar::InitCANJaguar()
+{
+	m_safetyHelper = new MotorSafetyHelper(this);
+
+	m_value = 0.0f;
+	m_speedReference = LM_REF_NONE;
+	m_positionReference = LM_REF_NONE;
+	m_p = 0.0;
+	m_i = 0.0;
+	m_d = 0.0;
+	m_busVoltage = 0.0f;
+	m_outputVoltage = 0.0f;
+	m_outputCurrent = 0.0f;
+	m_temperature = 0.0f;
+	m_position = 0.0;
+	m_speed = 0.0;
+	m_limits = 0x00;
+	m_faults = 0x0000;
+	m_firmwareVersion = 0;
+	m_hardwareVersion = 0;
+	m_neutralMode = kNeutralMode_Jumper;
+	m_encoderCodesPerRev = 0;
+	m_potentiometerTurns = 0;
+	m_limitMode = kLimitMode_SwitchInputsOnly;
+	m_forwardLimit = 0.0;
+	m_reverseLimit = 0.0;
+	m_maxOutputVoltage = 30.0;
+	m_voltageRampRate = 0.0;
+	m_faultTime = 0.0f;
+
+	// Parameters only need to be verified if they are set
+	m_controlModeVerified = false; // Needs to be verified because it's set in the constructor
+	m_speedRefVerified = true;
+	m_posRefVerified = true;
+	m_pVerified = true;
+	m_iVerified = true;
+	m_dVerified = true;
+	m_neutralModeVerified = true;
+	m_encoderCodesPerRevVerified = true;
+	m_potentiometerTurnsVerified = true;
+	m_limitModeVerified = true;
+	m_forwardLimitVerified = true;
+	m_reverseLimitVerified = true;
+	m_maxOutputVoltageVerified = true;
+	m_voltageRampRateVerified = true;
+	m_faultTimeVerified = true;
+
+	m_receivedStatusMessage0 = false;
+	m_receivedStatusMessage1 = false;
+	m_receivedStatusMessage2 = false;
+
+	bool receivedFirmwareVersion = false;
+	uint8_t dataBuffer[8];
+	uint8_t dataSize;
+
+	// Request firmware and hardware version only once
+	requestMessage(CAN_IS_FRAME_REMOTE | CAN_MSGID_API_FIRMVER);
+	requestMessage(LM_API_HWVER);
+
+	// Wait until we've gotten all of the status data at least once.
+	for(int i = 0; i < kReceiveStatusAttempts; i++)
+	{
+		Wait(0.001);
+
+		setupPeriodicStatus();
+		updatePeriodicStatus();
+
+		if(!receivedFirmwareVersion &&
+		   getMessage(CAN_MSGID_API_FIRMVER, CAN_MSGID_FULL_M, dataBuffer, &dataSize))
+		{
+			m_firmwareVersion = unpackint32_t(dataBuffer);
+			receivedFirmwareVersion = true;
+		}
+
+		if(m_receivedStatusMessage0 &&
+		   m_receivedStatusMessage1 &&
+		   m_receivedStatusMessage2 &&
+		   receivedFirmwareVersion)
+		{
+			break;
+		}
+	}
+
+	if(!m_receivedStatusMessage0 ||
+	   !m_receivedStatusMessage1 ||
+	   !m_receivedStatusMessage2 ||
+	   !receivedFirmwareVersion)
+	{
+		wpi_setWPIErrorWithContext(JaguarMessageNotFound, "Status data not found");
+	}
+
+	if(getMessage(LM_API_HWVER, CAN_MSGID_FULL_M, dataBuffer, &dataSize))
+		m_hardwareVersion = dataBuffer[0];
+
+	if (m_deviceNumber < 1 || m_deviceNumber > 63)
+	{
+		char buf[256];
+		snprintf(buf, 256, "device number \"%d\" must be between 1 and 63", m_deviceNumber);
+		wpi_setWPIErrorWithContext(ParameterOutOfRange, buf);
+		return;
+	}
+
+	if (StatusIsFatal())
+		return;
+
+	// 3330 was the first shipping RDK firmware version for the Jaguar
+	if (m_firmwareVersion >= 3330 || m_firmwareVersion < 108)
+	{
+		char buf[256];
+		if (m_firmwareVersion < 3330)
+		{
+			snprintf(buf, 256, "Jag #%d firmware (%d) is too old (must be at least version 108 of the FIRST approved firmware)", m_deviceNumber, m_firmwareVersion);
+		}
+		else
+		{
+			snprintf(buf, 256, "Jag #%d firmware (%d) is not FIRST approved (must be at least version 108 of the FIRST approved firmware)", m_deviceNumber, m_firmwareVersion);
+		}
+		wpi_setWPIErrorWithContext(JaguarVersionError, buf);
+		return;
+	}
+
+	switch (m_controlMode)
+	{
+	case kPercentVbus:
+	case kVoltage:
+		// No additional configuration required... start enabled.
+		EnableControl();
+		break;
+	default:
+		break;
+	}
+
+	HALReport(HALUsageReporting::kResourceType_CANJaguar, m_deviceNumber, m_controlMode);
+}
+
+/**
+ * Constructor for the CANJaguar device.<br>
+ * By default the device is configured in Percent mode.
+ * The control mode can be changed by calling one of the control modes listed below.
+ *
+ * @param deviceNumber The address of the Jaguar on the CAN bus.
+ * @see CANJaguar#SetCurrentMode(double, double, double)
+ * @see CANJaguar#SetCurrentMode(PotentiometerTag, double, double, double)
+ * @see CANJaguar#SetCurrentMode(EncoderTag, int, double, double, double)
+ * @see CANJaguar#SetCurrentMode(QuadEncoderTag, int, double, double, double)
+ * @see CANJaguar#SetPercentMode()
+ * @see CANJaguar#SetPercentMode(PotentiometerTag)
+ * @see CANJaguar#SetPercentMode(EncoderTag, int)
+ * @see CANJaguar#SetPercentMode(QuadEncoderTag, int)
+ * @see CANJaguar#SetPositionMode(PotentiometerTag, double, double, double)
+ * @see CANJaguar#SetPositionMode(QuadEncoderTag, int, double, double, double)
+ * @see CANJaguar#SetSpeedMode(EncoderTag, int, double, double, double)
+ * @see CANJaguar#SetSpeedMode(QuadEncoderTag, int, double, double, double)
+ * @see CANJaguar#SetVoltageMode()
+ * @see CANJaguar#SetVoltageMode(PotentiometerTag)
+ * @see CANJaguar#SetVoltageMode(EncoderTag, int)
+ * @see CANJaguar#SetVoltageMode(QuadEncoderTag, int)
+ */
+CANJaguar::CANJaguar(uint8_t deviceNumber)
+	: m_deviceNumber (deviceNumber)
+	, m_maxOutputVoltage (kApproxBusVoltage)
+	, m_safetyHelper (NULL)
+{
+	char buf[64];
+	snprintf(buf, 64, "CANJaguar device number %d", m_deviceNumber);
+	Resource::CreateResourceObject(&allocated, 63);
+
+	if (allocated->Allocate(m_deviceNumber-1, buf) == ~0ul)
+	{
+		CloneError(allocated);
+		return;
+	}
+
+	SetPercentMode();
+	InitCANJaguar();
+	ConfigMaxOutputVoltage(kApproxBusVoltage);
+}
+
+CANJaguar::~CANJaguar()
+{
+	allocated->Free(m_deviceNumber-1);
+
+	int32_t status;
+
+	// Disable periodic setpoints
+	if(m_controlMode == kPercentVbus)
+		FRC_NetworkCommunication_CANSessionMux_sendMessage(m_deviceNumber | LM_API_VOLT_T_SET, NULL, 0, CAN_SEND_PERIOD_STOP_REPEATING, &status);
+	else if(m_controlMode == kSpeed)
+		FRC_NetworkCommunication_CANSessionMux_sendMessage(m_deviceNumber | LM_API_SPD_T_SET, NULL, 0, CAN_SEND_PERIOD_STOP_REPEATING, &status);
+	else if(m_controlMode == kPosition)
+		FRC_NetworkCommunication_CANSessionMux_sendMessage(m_deviceNumber | LM_API_POS_T_SET, NULL, 0, CAN_SEND_PERIOD_STOP_REPEATING, &status);
+	else if(m_controlMode == kCurrent)
+		FRC_NetworkCommunication_CANSessionMux_sendMessage(m_deviceNumber | LM_API_ICTRL_T_SET, NULL, 0, CAN_SEND_PERIOD_STOP_REPEATING, &status);
+	else if(m_controlMode == kVoltage)
+		FRC_NetworkCommunication_CANSessionMux_sendMessage(m_deviceNumber | LM_API_VCOMP_T_SET, NULL, 0, CAN_SEND_PERIOD_STOP_REPEATING, &status);
+
+	delete m_safetyHelper;
+	m_safetyHelper = NULL;
+}
+
+/**
+ * @return The CAN ID passed in the constructor
+ */
+uint8_t CANJaguar::getDeviceNumber() const
+{
+	return m_deviceNumber;
+}
+
+/**
+ * Sets the output set-point value.
+ *
+ * The scale and the units depend on the mode the Jaguar is in.<br>
+ * In percentVbus Mode, the outputValue is from -1.0 to 1.0 (same as PWM Jaguar).<br>
+ * In voltage Mode, the outputValue is in volts. <br>
+ * In current Mode, the outputValue is in amps. <br>
+ * In speed Mode, the outputValue is in rotations/minute.<br>
+ * In position Mode, the outputValue is in rotations.
+ *
+ * @param outputValue The set-point to sent to the motor controller.
+ * @param syncGroup The update group to add this Set() to, pending UpdateSyncGroup().  If 0, update immediately.
+ */
+void CANJaguar::Set(float outputValue, uint8_t syncGroup)
+{
+	uint32_t messageID;
+	uint8_t dataBuffer[8];
+	uint8_t dataSize;
+
+	if(m_safetyHelper && !m_safetyHelper->IsAlive() && m_controlEnabled)
+	{
+		EnableControl();
+	}
+
+	if(m_controlEnabled)
+	{
+		switch(m_controlMode)
+		{
+		case kPercentVbus:
+			{
+				messageID = LM_API_VOLT_T_SET;
+				if (outputValue > 1.0) outputValue = 1.0;
+				if (outputValue < -1.0) outputValue = -1.0;
+				dataSize = packPercentage(dataBuffer, outputValue);
+			}
+			break;
+		case kSpeed:
+			{
+				messageID = LM_API_SPD_T_SET;
+				dataSize = packFXP16_16(dataBuffer, outputValue);
+			}
+			break;
+		case kPosition:
+			{
+				messageID = LM_API_POS_T_SET;
+				dataSize = packFXP16_16(dataBuffer, outputValue);
+			}
+			break;
+		case kCurrent:
+			{
+				messageID = LM_API_ICTRL_T_SET;
+				dataSize = packFXP8_8(dataBuffer, outputValue);
+			}
+			break;
+		case kVoltage:
+			{
+				messageID = LM_API_VCOMP_T_SET;
+				dataSize = packFXP8_8(dataBuffer, outputValue);
+			}
+			break;
+    default:
+      wpi_setWPIErrorWithContext(IncompatibleMode, "The Jaguar only supports Current, Voltage, Position, Speed, and Percent (Throttle) modes.");
+      return;
+		}
+		if (syncGroup != 0)
+		{
+			dataBuffer[dataSize] = syncGroup;
+			dataSize++;
+		}
+
+		sendMessage(messageID, dataBuffer, dataSize, kSendMessagePeriod);
+
+		if (m_safetyHelper) m_safetyHelper->Feed();
+	}
+
+	m_value = outputValue;
+
+	verify();
+}
+
+/**
+ * Get the recently set outputValue setpoint.
+ *
+ * The scale and the units depend on the mode the Jaguar is in.<br>
+ * In percentVbus Mode, the outputValue is from -1.0 to 1.0 (same as PWM Jaguar).<br>
+ * In voltage Mode, the outputValue is in volts.<br>
+ * In current Mode, the outputValue is in amps.<br>
+ * In speed Mode, the outputValue is in rotations/minute.<br>
+ * In position Mode, the outputValue is in rotations.<br>
+ *
+ * @return The most recently set outputValue setpoint.
+ */
+float CANJaguar::Get()
+{
+	return m_value;
+}
+
+/**
+* Common interface for disabling a motor.
+*
+* @deprecated Call {@link #DisableControl()} instead.
+*/
+void CANJaguar::Disable()
+{
+	DisableControl();
+}
+
+/**
+ * Write out the PID value as seen in the PIDOutput base object.
+ *
+ * @deprecated Call Set instead.
+ *
+ * @param output Write out the PercentVbus value as was computed by the PIDController
+ */
+void CANJaguar::PIDWrite(float output)
+{
+	if (m_controlMode == kPercentVbus)
+	{
+		Set(output);
+	}
+	else
+	{
+		wpi_setWPIErrorWithContext(IncompatibleMode, "PID only supported in PercentVbus mode");
+	}
+}
+
+uint8_t CANJaguar::packPercentage(uint8_t *buffer, double value)
+{
+	int16_t intValue = (int16_t)(value * 32767.0);
+	*((int16_t*)buffer) = swap16(intValue);
+	return sizeof(int16_t);
+}
+
+uint8_t CANJaguar::packFXP8_8(uint8_t *buffer, double value)
+{
+	int16_t intValue = (int16_t)(value * 256.0);
+	*((int16_t*)buffer) = swap16(intValue);
+	return sizeof(int16_t);
+}
+
+uint8_t CANJaguar::packFXP16_16(uint8_t *buffer, double value)
+{
+	int32_t intValue = (int32_t)(value * 65536.0);
+	*((int32_t*)buffer) = swap32(intValue);
+	return sizeof(int32_t);
+}
+
+uint8_t CANJaguar::packint16_t(uint8_t *buffer, int16_t value)
+{
+	*((int16_t*)buffer) = swap16(value);
+	return sizeof(int16_t);
+}
+
+uint8_t CANJaguar::packint32_t(uint8_t *buffer, int32_t value)
+{
+	*((int32_t*)buffer) = swap32(value);
+	return sizeof(int32_t);
+}
+
+double CANJaguar::unpackPercentage(uint8_t *buffer)
+{
+	int16_t value = *((int16_t*)buffer);
+	value = swap16(value);
+	return value / 32767.0;
+}
+
+double CANJaguar::unpackFXP8_8(uint8_t *buffer)
+{
+	int16_t value = *((int16_t*)buffer);
+	value = swap16(value);
+	return value / 256.0;
+}
+
+double CANJaguar::unpackFXP16_16(uint8_t *buffer)
+{
+	int32_t value = *((int32_t*)buffer);
+	value = swap32(value);
+	return value / 65536.0;
+}
+
+int16_t CANJaguar::unpackint16_t(uint8_t *buffer)
+{
+	int16_t value = *((int16_t*)buffer);
+	return swap16(value);
+}
+
+int32_t CANJaguar::unpackint32_t(uint8_t *buffer)
+{
+	int32_t value = *((int32_t*)buffer);
+	return swap32(value);
+}
+
+/**
+ * Send a message to the Jaguar.
+ *
+ * @param messageID The messageID to be used on the CAN bus (device number is added internally)
+ * @param data The up to 8 bytes of data to be sent with the message
+ * @param dataSize Specify how much of the data in "data" to send
+ * @param periodic If positive, tell Network Communications to send the message
+ * 	every "period" milliseconds.
+ */
+void CANJaguar::sendMessage(uint32_t messageID, const uint8_t *data, uint8_t dataSize, int32_t period)
+{
+	int32_t localStatus = sendMessageHelper(messageID | m_deviceNumber, data, dataSize, period);
+
+	if(localStatus < 0)
+	{
+		wpi_setErrorWithContext(localStatus, "sendMessage");
+	}
+}
+
+/**
+ * Request a message from the Jaguar, but don't wait for it to arrive.
+ *
+ * @param messageID The message to request
+ * @param periodic If positive, tell Network Communications to send the message
+ * 	every "period" milliseconds.
+ */
+void CANJaguar::requestMessage(uint32_t messageID, int32_t period)
+{
+	sendMessageHelper(messageID | m_deviceNumber, NULL, 0, period);
+}
+
+/**
+ * Get a previously requested message.
+ *
+ * Jaguar always generates a message with the same message ID when replying.
+ *
+ * @param messageID The messageID to read from the CAN bus (device number is added internally)
+ * @param data The up to 8 bytes of data that was received with the message
+ * @param dataSize Indicates how much data was received
+ *
+ * @return true if the message was found.  Otherwise, no new message is available.
+ */
+bool CANJaguar::getMessage(uint32_t messageID, uint32_t messageMask, uint8_t *data, uint8_t *dataSize)
+{
+	uint32_t targetedMessageID = messageID | m_deviceNumber;
+	int32_t status = 0;
+	uint32_t timeStamp;
+
+	// Caller may have set bit31 for remote frame transmission so clear invalid bits[31-29]
+	targetedMessageID &= CAN_MSGID_FULL_M;
+
+	// Get the data.
+	FRC_NetworkCommunication_CANSessionMux_receiveMessage(&targetedMessageID, messageMask, data, dataSize, &timeStamp, &status);
+
+	// Do we already have the most recent value?
+	if(status == ERR_CANSessionMux_MessageNotFound)
+		return false;
+	else
+		wpi_setErrorWithContext(status, "receiveMessage");
+
+	return true;
+}
+
+/**
+ * Enables periodic status updates from the Jaguar.
+ */
+void CANJaguar::setupPeriodicStatus() {
+	uint8_t data[8];
+	uint8_t dataSize;
+
+	// Message 0 returns bus voltage, output voltage, output current, and
+	// temperature.
+	static const uint8_t kMessage0Data[] = {
+		LM_PSTAT_VOLTBUS_B0, LM_PSTAT_VOLTBUS_B1,
+		LM_PSTAT_VOLTOUT_B0, LM_PSTAT_VOLTOUT_B1,
+		LM_PSTAT_CURRENT_B0, LM_PSTAT_CURRENT_B1,
+		LM_PSTAT_TEMP_B0, LM_PSTAT_TEMP_B1
+	};
+
+	// Message 1 returns position and speed
+	static const uint8_t kMessage1Data[] = {
+		LM_PSTAT_POS_B0, LM_PSTAT_POS_B1, LM_PSTAT_POS_B2, LM_PSTAT_POS_B3,
+		LM_PSTAT_SPD_B0, LM_PSTAT_SPD_B1, LM_PSTAT_SPD_B2, LM_PSTAT_SPD_B3
+	};
+
+	// Message 2 returns limits and faults
+	static const uint8_t kMessage2Data[] = {
+		LM_PSTAT_LIMIT_CLR,
+		LM_PSTAT_FAULT,
+		LM_PSTAT_END
+	};
+
+	dataSize = packint16_t(data, kSendMessagePeriod);
+	sendMessage(LM_API_PSTAT_PER_EN_S0, data, dataSize);
+	sendMessage(LM_API_PSTAT_PER_EN_S1, data, dataSize);
+	sendMessage(LM_API_PSTAT_PER_EN_S2, data, dataSize);
+
+	dataSize = 8;
+	sendMessage(LM_API_PSTAT_CFG_S0, kMessage0Data, dataSize);
+	sendMessage(LM_API_PSTAT_CFG_S1, kMessage1Data, dataSize);
+	sendMessage(LM_API_PSTAT_CFG_S2, kMessage2Data, dataSize);
+}
+
+/**
+ * Check for new periodic status updates and unpack them into local variables
+ */
+void CANJaguar::updatePeriodicStatus() {
+	uint8_t data[8];
+	uint8_t dataSize;
+
+	// Check if a new bus voltage/output voltage/current/temperature message
+	// has arrived and unpack the values into the cached member variables
+	if(getMessage(LM_API_PSTAT_DATA_S0, CAN_MSGID_FULL_M, data, &dataSize)) {
+		m_busVoltage    = unpackFXP8_8(data);
+		m_outputVoltage = unpackPercentage(data + 2) * m_busVoltage;
+		m_outputCurrent = unpackFXP8_8(data + 4);
+		m_temperature   = unpackFXP8_8(data + 6);
+
+		m_receivedStatusMessage0 = true;
+	}
+
+	// Check if a new position/speed message has arrived and do the same
+	if(getMessage(LM_API_PSTAT_DATA_S1, CAN_MSGID_FULL_M, data, &dataSize)) {
+		m_position = unpackFXP16_16(data);
+		m_speed    = unpackFXP16_16(data + 4);
+
+		m_receivedStatusMessage1 = true;
+	}
+
+	// Check if a new limits/faults message has arrived and do the same
+	if(getMessage(LM_API_PSTAT_DATA_S2, CAN_MSGID_FULL_M, data, &dataSize)) {
+		m_limits = data[0];
+		m_faults = data[1];
+
+		m_receivedStatusMessage2 = true;
+	}
+}
+
+/**
+ * Check all unverified params and make sure they're equal to their local
+ * cached versions. If a value isn't available, it gets requested.  If a value
+ * doesn't match up, it gets set again.
+ */
+void CANJaguar::verify()
+{
+	uint8_t dataBuffer[8];
+	uint8_t dataSize;
+
+	// If the Jaguar lost power, everything should be considered unverified.
+	if(getMessage(LM_API_STATUS_POWER, CAN_MSGID_FULL_M, dataBuffer, &dataSize))
+	{
+		bool powerCycled = (bool)dataBuffer[0];
+
+		if(powerCycled)
+		{
+			// Clear the power cycled bit
+			dataBuffer[0] = 1;
+			sendMessage(LM_API_STATUS_POWER, dataBuffer, sizeof(uint8_t));
+
+			// Mark everything as unverified
+			m_controlModeVerified = false;
+			m_speedRefVerified = false;
+			m_posRefVerified = false;
+			m_neutralModeVerified = false;
+			m_encoderCodesPerRevVerified = false;
+			m_potentiometerTurnsVerified = false;
+			m_forwardLimitVerified = false;
+			m_reverseLimitVerified = false;
+			m_limitModeVerified = false;
+			m_maxOutputVoltageVerified = false;
+			m_faultTimeVerified = false;
+
+			if(m_controlMode == kPercentVbus || m_controlMode == kVoltage)
+			{
+				m_voltageRampRateVerified = false;
+			}
+			else
+			{
+				m_pVerified = false;
+				m_iVerified = false;
+				m_dVerified = false;
+			}
+
+			// Verify periodic status messages again
+			m_receivedStatusMessage0 = false;
+			m_receivedStatusMessage1 = false;
+			m_receivedStatusMessage2 = false;
+
+			// Remove any old values from netcomms. Otherwise, parameters are
+			// incorrectly marked as verified based on stale messages.
+			getMessage(LM_API_SPD_REF, CAN_MSGID_FULL_M, dataBuffer, &dataSize);
+			getMessage(LM_API_POS_REF, CAN_MSGID_FULL_M, dataBuffer, &dataSize);
+			getMessage(LM_API_SPD_PC, CAN_MSGID_FULL_M, dataBuffer, &dataSize);
+			getMessage(LM_API_POS_PC, CAN_MSGID_FULL_M, dataBuffer, &dataSize);
+			getMessage(LM_API_ICTRL_PC, CAN_MSGID_FULL_M, dataBuffer, &dataSize);
+			getMessage(LM_API_SPD_IC, CAN_MSGID_FULL_M, dataBuffer, &dataSize);
+			getMessage(LM_API_POS_IC, CAN_MSGID_FULL_M, dataBuffer, &dataSize);
+			getMessage(LM_API_ICTRL_IC, CAN_MSGID_FULL_M, dataBuffer, &dataSize);
+			getMessage(LM_API_SPD_DC, CAN_MSGID_FULL_M, dataBuffer, &dataSize);
+			getMessage(LM_API_POS_DC, CAN_MSGID_FULL_M, dataBuffer, &dataSize);
+			getMessage(LM_API_ICTRL_DC, CAN_MSGID_FULL_M, dataBuffer, &dataSize);
+			getMessage(LM_API_CFG_BRAKE_COAST, CAN_MSGID_FULL_M, dataBuffer, &dataSize);
+			getMessage(LM_API_CFG_ENC_LINES, CAN_MSGID_FULL_M, dataBuffer, &dataSize);
+			getMessage(LM_API_CFG_POT_TURNS, CAN_MSGID_FULL_M, dataBuffer, &dataSize);
+			getMessage(LM_API_CFG_LIMIT_MODE, CAN_MSGID_FULL_M, dataBuffer, &dataSize);
+			getMessage(LM_API_CFG_LIMIT_FWD, CAN_MSGID_FULL_M, dataBuffer, &dataSize);
+			getMessage(LM_API_CFG_LIMIT_REV, CAN_MSGID_FULL_M, dataBuffer, &dataSize);
+			getMessage(LM_API_CFG_MAX_VOUT, CAN_MSGID_FULL_M, dataBuffer, &dataSize);
+			getMessage(LM_API_VOLT_SET_RAMP, CAN_MSGID_FULL_M, dataBuffer, &dataSize);
+			getMessage(LM_API_VCOMP_COMP_RAMP, CAN_MSGID_FULL_M, dataBuffer, &dataSize);
+			getMessage(LM_API_CFG_FAULT_TIME, CAN_MSGID_FULL_M, dataBuffer, &dataSize);
+		}
+	}
+	else
+	{
+		requestMessage(LM_API_STATUS_POWER);
+	}
+
+	// Verify that any recently set parameters are correct
+	if(!m_controlModeVerified && m_controlEnabled)
+	{
+		if(getMessage(LM_API_STATUS_CMODE, CAN_MSGID_FULL_M, dataBuffer, &dataSize))
+		{
+			ControlMode mode = (ControlMode)dataBuffer[0];
+
+			if(m_controlMode == mode)
+				m_controlModeVerified = true;
+			else
+				// Enable control again to resend the control mode
+				EnableControl();
+		}
+		else
+		{
+			// Verification is needed but not available - request it again.
+			requestMessage(LM_API_STATUS_CMODE);
+		}
+	}
+
+	if(!m_speedRefVerified)
+	{
+		if(getMessage(LM_API_SPD_REF, CAN_MSGID_FULL_M, dataBuffer, &dataSize))
+		{
+			uint8_t speedRef = dataBuffer[0];
+
+			if(m_speedReference == speedRef)
+				m_speedRefVerified = true;
+			else
+				// It's wrong - set it again
+				SetSpeedReference(m_speedReference);
+		}
+		else
+		{
+			// Verification is needed but not available - request it again.
+			requestMessage(LM_API_SPD_REF);
+		}
+	}
+
+	if(!m_posRefVerified)
+	{
+		if(getMessage(LM_API_POS_REF, CAN_MSGID_FULL_M, dataBuffer, &dataSize))
+		{
+			uint8_t posRef = dataBuffer[0];
+
+			if(m_positionReference == posRef)
+				m_posRefVerified = true;
+			else
+				// It's wrong - set it again
+				SetPositionReference(m_positionReference);
+		}
+		else
+		{
+			// Verification is needed but not available - request it again.
+			requestMessage(LM_API_POS_REF);
+		}
+	}
+
+	if(!m_pVerified)
+	{
+		uint32_t message;
+
+		if(m_controlMode == kSpeed)
+			message = LM_API_SPD_PC;
+		else if(m_controlMode == kPosition)
+			message = LM_API_POS_PC;
+		else if(m_controlMode == kCurrent)
+			message = LM_API_ICTRL_PC;
+
+		if(getMessage(message, CAN_MSGID_FULL_M, dataBuffer, &dataSize))
+		{
+			double p = unpackFXP16_16(dataBuffer);
+
+			if(FXP16_EQ(m_p, p))
+				m_pVerified = true;
+			else
+				// It's wrong - set it again
+				SetP(m_p);
+		}
+		else
+		{
+			// Verification is needed but not available - request it again.
+			requestMessage(message);
+		}
+	}
+
+	if(!m_iVerified)
+	{
+		uint32_t message;
+
+		if(m_controlMode == kSpeed)
+			message = LM_API_SPD_IC;
+		else if(m_controlMode == kPosition)
+			message = LM_API_POS_IC;
+		else if(m_controlMode == kCurrent)
+			message = LM_API_ICTRL_IC;
+
+		if(getMessage(message, CAN_MSGID_FULL_M, dataBuffer, &dataSize))
+		{
+			double i = unpackFXP16_16(dataBuffer);
+
+			if(FXP16_EQ(m_i, i))
+				m_iVerified = true;
+			else
+				// It's wrong - set it again
+				SetI(m_i);
+		}
+		else
+		{
+			// Verification is needed but not available - request it again.
+			requestMessage(message);
+		}
+	}
+
+	if(!m_dVerified)
+	{
+		uint32_t message;
+
+		if(m_controlMode == kSpeed)
+			message = LM_API_SPD_DC;
+		else if(m_controlMode == kPosition)
+			message = LM_API_POS_DC;
+		else if(m_controlMode == kCurrent)
+			message = LM_API_ICTRL_DC;
+
+		if(getMessage(message, CAN_MSGID_FULL_M, dataBuffer, &dataSize))
+		{
+			double d = unpackFXP16_16(dataBuffer);
+
+			if(FXP16_EQ(m_d, d))
+				m_dVerified = true;
+			else
+				// It's wrong - set it again
+				SetD(m_d);
+		}
+		else
+		{
+			// Verification is needed but not available - request it again.
+			requestMessage(message);
+		}
+	}
+
+	if(!m_neutralModeVerified)
+	{
+		if(getMessage(LM_API_CFG_BRAKE_COAST, CAN_MSGID_FULL_M, dataBuffer, &dataSize))
+		{
+			NeutralMode mode = (NeutralMode)dataBuffer[0];
+
+			if(mode == m_neutralMode)
+				m_neutralModeVerified = true;
+			else
+				// It's wrong - set it again
+				ConfigNeutralMode(m_neutralMode);
+		}
+		else
+		{
+			// Verification is needed but not available - request it again.
+			requestMessage(LM_API_CFG_BRAKE_COAST);
+		}
+	}
+
+	if(!m_encoderCodesPerRevVerified)
+	{
+		if(getMessage(LM_API_CFG_ENC_LINES, CAN_MSGID_FULL_M, dataBuffer, &dataSize))
+		{
+			uint16_t codes = unpackint16_t(dataBuffer);
+
+			if(codes == m_encoderCodesPerRev)
+				m_encoderCodesPerRevVerified = true;
+			else
+				// It's wrong - set it again
+				ConfigEncoderCodesPerRev(m_encoderCodesPerRev);
+		}
+		else
+		{
+			// Verification is needed but not available - request it again.
+			requestMessage(LM_API_CFG_ENC_LINES);
+		}
+	}
+
+	if(!m_potentiometerTurnsVerified)
+	{
+		if(getMessage(LM_API_CFG_POT_TURNS, CAN_MSGID_FULL_M, dataBuffer, &dataSize))
+		{
+			uint16_t turns = unpackint16_t(dataBuffer);
+
+			if(turns == m_potentiometerTurns)
+				m_potentiometerTurnsVerified = true;
+			else
+				// It's wrong - set it again
+				ConfigPotentiometerTurns(m_potentiometerTurns);
+		}
+		else
+		{
+			// Verification is needed but not available - request it again.
+			requestMessage(LM_API_CFG_POT_TURNS);
+		}
+	}
+
+	if(!m_limitModeVerified)
+	{
+		if(getMessage(LM_API_CFG_LIMIT_MODE, CAN_MSGID_FULL_M, dataBuffer, &dataSize))
+		{
+			LimitMode mode = (LimitMode)dataBuffer[0];
+
+			if(mode == m_limitMode)
+				m_limitModeVerified = true;
+			else
+			{
+				// It's wrong - set it again
+				ConfigLimitMode(m_limitMode);
+			}
+		}
+		else
+		{
+			// Verification is needed but not available - request it again.
+			requestMessage(LM_API_CFG_LIMIT_MODE);
+		}
+	}
+
+	if(!m_forwardLimitVerified)
+	{
+		if(getMessage(LM_API_CFG_LIMIT_FWD, CAN_MSGID_FULL_M, dataBuffer, &dataSize))
+		{
+			double limit = unpackFXP16_16(dataBuffer);
+
+			if(FXP16_EQ(limit, m_forwardLimit))
+				m_forwardLimitVerified = true;
+			else
+			{
+				// It's wrong - set it again
+				ConfigForwardLimit(m_forwardLimit);
+			}
+		}
+		else
+		{
+			// Verification is needed but not available - request it again.
+			requestMessage(LM_API_CFG_LIMIT_FWD);
+		}
+	}
+
+	if(!m_reverseLimitVerified)
+	{
+		if(getMessage(LM_API_CFG_LIMIT_REV, CAN_MSGID_FULL_M, dataBuffer, &dataSize))
+		{
+			double limit = unpackFXP16_16(dataBuffer);
+
+			if(FXP16_EQ(limit, m_reverseLimit))
+				m_reverseLimitVerified = true;
+			else
+			{
+				// It's wrong - set it again
+				ConfigReverseLimit(m_reverseLimit);
+			}
+		}
+		else
+		{
+			// Verification is needed but not available - request it again.
+			requestMessage(LM_API_CFG_LIMIT_REV);
+		}
+	}
+
+	if(!m_maxOutputVoltageVerified)
+	{
+		if(getMessage(LM_API_CFG_MAX_VOUT, CAN_MSGID_FULL_M, dataBuffer, &dataSize))
+		{
+			double voltage = unpackFXP8_8(dataBuffer);
+
+			// The returned max output voltage is sometimes slightly higher or
+			// lower than what was sent.  This should not trigger resending
+			// the message.
+			if(std::abs(voltage - m_maxOutputVoltage) < 0.1)
+				m_maxOutputVoltageVerified = true;
+			else
+			{
+				// It's wrong - set it again
+				ConfigMaxOutputVoltage(m_maxOutputVoltage);
+			}
+		}
+		else
+		{
+			// Verification is needed but not available - request it again.
+			requestMessage(LM_API_CFG_MAX_VOUT);
+		}
+	}
+
+	if(!m_voltageRampRateVerified)
+	{
+		if(m_controlMode == kPercentVbus)
+		{
+			if(getMessage(LM_API_VOLT_SET_RAMP, CAN_MSGID_FULL_M, dataBuffer, &dataSize))
+			{
+				double rate = unpackPercentage(dataBuffer);
+
+				if(FXP16_EQ(rate, m_voltageRampRate))
+					m_voltageRampRateVerified = true;
+				else
+				{
+					// It's wrong - set it again
+					SetVoltageRampRate(m_voltageRampRate);
+				}
+			}
+			else
+			{
+				// Verification is needed but not available - request it again.
+				requestMessage(LM_API_VOLT_SET_RAMP);
+			}
+		}
+		else if(m_controlMode == kVoltage)
+		{
+			if(getMessage(LM_API_VCOMP_COMP_RAMP, CAN_MSGID_FULL_M, dataBuffer, &dataSize))
+			{
+				double rate = unpackFXP8_8(dataBuffer);
+
+				if(FXP8_EQ(rate, m_voltageRampRate))
+					m_voltageRampRateVerified = true;
+				else
+				{
+					// It's wrong - set it again
+					SetVoltageRampRate(m_voltageRampRate);
+				}
+			}
+			else
+			{
+				// Verification is needed but not available - request it again.
+				requestMessage(LM_API_VCOMP_COMP_RAMP);
+			}
+		}
+	}
+
+	if(!m_faultTimeVerified)
+	{
+		if(getMessage(LM_API_CFG_FAULT_TIME, CAN_MSGID_FULL_M, dataBuffer, &dataSize))
+		{
+			uint16_t faultTime = unpackint16_t(dataBuffer);
+
+			if((uint16_t)(m_faultTime * 1000.0) == faultTime)
+				m_faultTimeVerified = true;
+			else
+			{
+				// It's wrong - set it again
+				ConfigFaultTime(m_faultTime);
+			}
+		}
+		else
+		{
+			// Verification is needed but not available - request it again.
+			requestMessage(LM_API_CFG_FAULT_TIME);
+		}
+	}
+
+	if(!m_receivedStatusMessage0 ||
+			!m_receivedStatusMessage1 ||
+			!m_receivedStatusMessage2)
+	{
+		// If the periodic status messages haven't been verified as received,
+		// request periodic status messages again and attempt to unpack any
+		// available ones.
+		setupPeriodicStatus();
+		GetTemperature();
+		GetPosition();
+		GetFaults();
+	}
+}
+
+/**
+ * Set the reference source device for speed controller mode.
+ *
+ * Choose encoder as the source of speed feedback when in speed control mode.
+ *
+ * @param reference Specify a speed reference.
+ */
+void CANJaguar::SetSpeedReference(uint8_t reference)
+{
+	uint8_t dataBuffer[8];
+
+	// Send the speed reference parameter
+	dataBuffer[0] = reference;
+	sendMessage(LM_API_SPD_REF, dataBuffer, sizeof(uint8_t));
+
+	m_speedReference = reference;
+	m_speedRefVerified = false;
+}
+
+/**
+ * Get the reference source device for speed controller mode.
+ *
+ * @return A speed reference indicating the currently selected reference device
+ * for speed controller mode.
+ */
+uint8_t CANJaguar::GetSpeedReference()
+{
+	return m_speedReference;
+}
+
+/**
+ * Set the reference source device for position controller mode.
+ *
+ * Choose between using and encoder and using a potentiometer
+ * as the source of position feedback when in position control mode.
+ *
+ * @param reference Specify a PositionReference.
+ */
+void CANJaguar::SetPositionReference(uint8_t reference)
+{
+	uint8_t dataBuffer[8];
+
+	// Send the position reference parameter
+	dataBuffer[0] = reference;
+	sendMessage(LM_API_POS_REF, dataBuffer, sizeof(uint8_t));
+
+	m_positionReference = reference;
+	m_posRefVerified = false;
+}
+
+/**
+ * Get the reference source device for position controller mode.
+ *
+ * @return A PositionReference indicating the currently selected reference device for position controller mode.
+ */
+uint8_t CANJaguar::GetPositionReference()
+{
+	return m_positionReference;
+}
+
+/**
+ * Set the P, I, and D constants for the closed loop modes.
+ *
+ * @param p The proportional gain of the Jaguar's PID controller.
+ * @param i The integral gain of the Jaguar's PID controller.
+ * @param d The differential gain of the Jaguar's PID controller.
+ */
+void CANJaguar::SetPID(double p, double i, double d)
+{
+	SetP(p);
+	SetI(i);
+	SetD(d);
+}
+
+/**
+ * Set the P constant for the closed loop modes.
+ *
+ * @param p The proportional gain of the Jaguar's PID controller.
+ */
+void CANJaguar::SetP(double p)
+{
+	uint8_t dataBuffer[8];
+	uint8_t dataSize;
+
+	switch(m_controlMode)
+	{
+	case kPercentVbus:
+	case kVoltage:
+  case kFollower:
+		wpi_setWPIErrorWithContext(IncompatibleMode, "PID constants only apply in Speed, Position, and Current mode");
+		break;
+	case kSpeed:
+		dataSize = packFXP16_16(dataBuffer, p);
+		sendMessage(LM_API_SPD_PC, dataBuffer, dataSize);
+		break;
+	case kPosition:
+		dataSize = packFXP16_16(dataBuffer, p);
+		sendMessage(LM_API_POS_PC, dataBuffer, dataSize);
+		break;
+	case kCurrent:
+		dataSize = packFXP16_16(dataBuffer, p);
+		sendMessage(LM_API_ICTRL_PC, dataBuffer, dataSize);
+		break;
+	}
+
+	m_p = p;
+	m_pVerified = false;
+}
+
+/**
+ * Set the I constant for the closed loop modes.
+ *
+ * @param i The integral gain of the Jaguar's PID controller.
+ */
+void CANJaguar::SetI(double i)
+{
+	uint8_t dataBuffer[8];
+	uint8_t dataSize;
+
+	switch(m_controlMode)
+	{
+	case kPercentVbus:
+	case kVoltage:
+  case kFollower:
+		wpi_setWPIErrorWithContext(IncompatibleMode, "PID constants only apply in Speed, Position, and Current mode");
+		break;
+	case kSpeed:
+		dataSize = packFXP16_16(dataBuffer, i);
+		sendMessage(LM_API_SPD_IC, dataBuffer, dataSize);
+		break;
+	case kPosition:
+		dataSize = packFXP16_16(dataBuffer, i);
+		sendMessage(LM_API_POS_IC, dataBuffer, dataSize);
+		break;
+	case kCurrent:
+		dataSize = packFXP16_16(dataBuffer, i);
+		sendMessage(LM_API_ICTRL_IC, dataBuffer, dataSize);
+		break;
+	}
+
+	m_i = i;
+	m_iVerified = false;
+}
+
+/**
+ * Set the D constant for the closed loop modes.
+ *
+ * @param d The derivative gain of the Jaguar's PID controller.
+ */
+void CANJaguar::SetD(double d)
+{
+	uint8_t dataBuffer[8];
+	uint8_t dataSize;
+
+	switch(m_controlMode)
+	{
+	case kPercentVbus:
+	case kVoltage:
+  case kFollower:
+		wpi_setWPIErrorWithContext(IncompatibleMode, "PID constants only apply in Speed, Position, and Current mode");
+		break;
+	case kSpeed:
+		dataSize = packFXP16_16(dataBuffer, d);
+		sendMessage(LM_API_SPD_DC, dataBuffer, dataSize);
+		break;
+	case kPosition:
+		dataSize = packFXP16_16(dataBuffer, d);
+		sendMessage(LM_API_POS_DC, dataBuffer, dataSize);
+		break;
+	case kCurrent:
+		dataSize = packFXP16_16(dataBuffer, d);
+		sendMessage(LM_API_ICTRL_DC, dataBuffer, dataSize);
+		break;
+	}
+
+	m_d = d;
+	m_dVerified = false;
+}
+
+/**
+ * Get the Proportional gain of the controller.
+ *
+ * @return The proportional gain.
+ */
+double CANJaguar::GetP()
+{
+	if(m_controlMode == kPercentVbus || m_controlMode == kVoltage)
+	{
+		wpi_setWPIErrorWithContext(IncompatibleMode, "PID constants only apply in Speed, Position, and Current mode");
+		return 0.0;
+	}
+
+	return m_p;
+}
+
+/**
+ * Get the Intregral gain of the controller.
+ *
+ * @return The integral gain.
+ */
+double CANJaguar::GetI()
+{
+	if(m_controlMode == kPercentVbus || m_controlMode == kVoltage)
+	{
+		wpi_setWPIErrorWithContext(IncompatibleMode, "PID constants only apply in Speed, Position, and Current mode");
+		return 0.0;
+	}
+
+	return m_i;
+}
+
+/**
+ * Get the Differential gain of the controller.
+ *
+ * @return The differential gain.
+ */
+double CANJaguar::GetD()
+{
+	if(m_controlMode == kPercentVbus || m_controlMode == kVoltage)
+	{
+		wpi_setWPIErrorWithContext(IncompatibleMode, "PID constants only apply in Speed, Position, and Current mode");
+		return 0.0;
+	}
+
+	return m_d;
+}
+
+/**
+ * Enable the closed loop controller.
+ *
+ * Start actually controlling the output based on the feedback.
+ * If starting a position controller with an encoder reference,
+ * use the encoderInitialPosition parameter to initialize the
+ * encoder state.
+ *
+ * @param encoderInitialPosition Encoder position to set if position with encoder reference.  Ignored otherwise.
+ */
+void CANJaguar::EnableControl(double encoderInitialPosition)
+{
+	uint8_t dataBuffer[8];
+	uint8_t dataSize = 0;
+
+	switch(m_controlMode)
+	{
+	case kPercentVbus:
+		sendMessage(LM_API_VOLT_T_EN, dataBuffer, dataSize);
+		break;
+	case kSpeed:
+		sendMessage(LM_API_SPD_T_EN, dataBuffer, dataSize);
+		break;
+	case kPosition:
+		dataSize = packFXP16_16(dataBuffer, encoderInitialPosition);
+		sendMessage(LM_API_POS_T_EN, dataBuffer, dataSize);
+		break;
+	case kCurrent:
+		sendMessage(LM_API_ICTRL_T_EN, dataBuffer, dataSize);
+		break;
+	case kVoltage:
+		sendMessage(LM_API_VCOMP_T_EN, dataBuffer, dataSize);
+		break;
+  default:
+    wpi_setWPIErrorWithContext(IncompatibleMode, "The Jaguar only supports Current, Voltage, Position, Speed, and Percent (Throttle) modes.");
+    return;
+	}
+
+	m_controlEnabled = true;
+	m_controlModeVerified = false;
+}
+
+/**
+ * Disable the closed loop controller.
+ *
+ * Stop driving the output based on the feedback.
+ */
+void CANJaguar::DisableControl()
+{
+	uint8_t dataBuffer[8];
+	uint8_t dataSize = 0;
+
+	// Disable all control
+	sendMessage(LM_API_VOLT_DIS, dataBuffer, dataSize);
+	sendMessage(LM_API_SPD_DIS, dataBuffer, dataSize);
+	sendMessage(LM_API_POS_DIS, dataBuffer, dataSize);
+	sendMessage(LM_API_ICTRL_DIS, dataBuffer, dataSize);
+	sendMessage(LM_API_VCOMP_DIS, dataBuffer, dataSize);
+
+	// Stop all periodic setpoints
+	sendMessage(LM_API_VOLT_T_SET, dataBuffer, dataSize, CAN_SEND_PERIOD_STOP_REPEATING);
+	sendMessage(LM_API_SPD_T_SET, dataBuffer, dataSize, CAN_SEND_PERIOD_STOP_REPEATING);
+	sendMessage(LM_API_POS_T_SET, dataBuffer, dataSize, CAN_SEND_PERIOD_STOP_REPEATING);
+	sendMessage(LM_API_ICTRL_T_SET, dataBuffer, dataSize, CAN_SEND_PERIOD_STOP_REPEATING);
+	sendMessage(LM_API_VCOMP_T_SET, dataBuffer, dataSize, CAN_SEND_PERIOD_STOP_REPEATING);
+
+	m_controlEnabled = false;
+}
+
+/**
+ * Enable controlling the motor voltage as a percentage of the bus voltage
+ * without any position or speed feedback.<br>
+ * After calling this you must call {@link CANJaguar#EnableControl()} or {@link CANJaguar#EnableControl(double)} to enable the device.
+ */
+void CANJaguar::SetPercentMode()
+{
+	SetControlMode(kPercentVbus);
+	SetPositionReference(LM_REF_NONE);
+	SetSpeedReference(LM_REF_NONE);
+}
+
+/**
+ * Enable controlling the motor voltage as a percentage of the bus voltage,
+ * and enable speed sensing from a non-quadrature encoder.<br>
+ * After calling this you must call {@link CANJaguar#EnableControl()} or {@link CANJaguar#EnableControl(double)} to enable the device.
+ *
+ * @param tag The constant CANJaguar::Encoder
+ * @param codesPerRev The counts per revolution on the encoder
+ */
+void CANJaguar::SetPercentMode(CANJaguar::EncoderStruct, uint16_t codesPerRev)
+{
+	SetControlMode(kPercentVbus);
+	SetPositionReference(LM_REF_NONE);
+	SetSpeedReference(LM_REF_ENCODER);
+	ConfigEncoderCodesPerRev(codesPerRev);
+}
+
+/**
+ * Enable controlling the motor voltage as a percentage of the bus voltage,
+ * and enable speed sensing from a non-quadrature encoder.<br>
+ * After calling this you must call {@link CANJaguar#EnableControl()} or {@link CANJaguar#EnableControl(double)} to enable the device.
+ *
+ * @param tag The constant CANJaguar::QuadEncoder
+ * @param codesPerRev The counts per revolution on the encoder
+ */
+void CANJaguar::SetPercentMode(CANJaguar::QuadEncoderStruct, uint16_t codesPerRev)
+{
+	SetControlMode(kPercentVbus);
+	SetPositionReference(LM_REF_ENCODER);
+	SetSpeedReference(LM_REF_QUAD_ENCODER);
+	ConfigEncoderCodesPerRev(codesPerRev);
+}
+
+/**
+* Enable controlling the motor voltage as a percentage of the bus voltage,
+* and enable position sensing from a potentiometer and no speed feedback.<br>
+* After calling this you must call {@link CANJaguar#EnableControl()} or {@link CANJaguar#EnableControl(double)} to enable the device.
+*
+* @param potentiometer The constant CANJaguar::Potentiometer
+*/
+void CANJaguar::SetPercentMode(CANJaguar::PotentiometerStruct)
+{
+	SetControlMode(kPercentVbus);
+	SetPositionReference(LM_REF_POT);
+	SetSpeedReference(LM_REF_NONE);
+	ConfigPotentiometerTurns(1);
+}
+
+/**
+ * Enable controlling the motor current with a PID loop.<br>
+ * After calling this you must call {@link CANJaguar#EnableControl()} or {@link CANJaguar#EnableControl(double)} to enable the device.
+ *
+ * @param p The proportional gain of the Jaguar's PID controller.
+ * @param i The integral gain of the Jaguar's PID controller.
+ * @param d The differential gain of the Jaguar's PID controller.
+ */
+void CANJaguar::SetCurrentMode(double p, double i, double d)
+{
+	SetControlMode(kCurrent);
+	SetPositionReference(LM_REF_NONE);
+	SetSpeedReference(LM_REF_NONE);
+	SetPID(p, i, d);
+}
+
+/**
+* Enable controlling the motor current with a PID loop, and enable speed
+* sensing from a non-quadrature encoder.<br>
+* After calling this you must call {@link CANJaguar#EnableControl()} or {@link CANJaguar#EnableControl(double)} to enable the device.
+*
+* @param encoder The constant CANJaguar::Encoder
+* @param p The proportional gain of the Jaguar's PID controller.
+* @param i The integral gain of the Jaguar's PID controller.
+* @param d The differential gain of the Jaguar's PID controller.
+*/
+void CANJaguar::SetCurrentMode(CANJaguar::EncoderStruct, uint16_t codesPerRev, double p, double i, double d)
+{
+	SetControlMode(kCurrent);
+	SetPositionReference(LM_REF_NONE);
+	SetSpeedReference(LM_REF_NONE);
+	ConfigEncoderCodesPerRev(codesPerRev);
+	SetPID(p, i, d);
+}
+
+/**
+* Enable controlling the motor current with a PID loop, and enable speed and
+* position sensing from a quadrature encoder.<br>
+* After calling this you must call {@link CANJaguar#EnableControl()} or {@link CANJaguar#EnableControl(double)} to enable the device.
+*
+* @param endoer The constant CANJaguar::QuadEncoder
+* @param p The proportional gain of the Jaguar's PID controller.
+* @param i The integral gain of the Jaguar's PID controller.
+* @param d The differential gain of the Jaguar's PID controller.
+*/
+void CANJaguar::SetCurrentMode(CANJaguar::QuadEncoderStruct, uint16_t codesPerRev, double p, double i, double d)
+{
+	SetControlMode(kCurrent);
+	SetPositionReference(LM_REF_ENCODER);
+	SetSpeedReference(LM_REF_QUAD_ENCODER);
+	ConfigEncoderCodesPerRev(codesPerRev);
+	SetPID(p, i, d);
+}
+
+/**
+* Enable controlling the motor current with a PID loop, and enable position
+* sensing from a potentiometer.<br>
+* After calling this you must call {@link CANJaguar#EnableControl()} or {@link CANJaguar#EnableControl(double)} to enable the device.
+*
+* @param potentiometer The constant CANJaguar::Potentiometer
+* @param p The proportional gain of the Jaguar's PID controller.
+* @param i The integral gain of the Jaguar's PID controller.
+* @param d The differential gain of the Jaguar's PID controller.
+*/
+void CANJaguar::SetCurrentMode(CANJaguar::PotentiometerStruct, double p, double i, double d)
+{
+	SetControlMode(kCurrent);
+	SetPositionReference(LM_REF_POT);
+	SetSpeedReference(LM_REF_NONE);
+	ConfigPotentiometerTurns(1);
+	SetPID(p, i, d);
+}
+
+/**
+ * Enable controlling the speed with a feedback loop from a non-quadrature
+ * encoder.<br>
+ * After calling this you must call {@link CANJaguar#EnableControl()} or {@link CANJaguar#EnableControl(double)} to enable the device.
+ *
+ * @param encoder The constant CANJaguar::Encoder
+ * @param codesPerRev The counts per revolution on the encoder.
+ * @param p The proportional gain of the Jaguar's PID controller.
+ * @param i The integral gain of the Jaguar's PID controller.
+ * @param d The differential gain of the Jaguar's PID controller.
+ */
+void CANJaguar::SetSpeedMode(CANJaguar::EncoderStruct, uint16_t codesPerRev, double p, double i, double d)
+{
+	SetControlMode(kSpeed);
+	SetPositionReference(LM_REF_NONE);
+	SetSpeedReference(LM_REF_ENCODER);
+	ConfigEncoderCodesPerRev(codesPerRev);
+	SetPID(p, i, d);
+}
+
+/**
+* Enable controlling the speed with a feedback loop from a quadrature encoder.<br>
+* After calling this you must call {@link CANJaguar#EnableControl()} or {@link CANJaguar#EnableControl(double)} to enable the device.
+*
+* @param encoder The constant CANJaguar::QuadEncoder
+* @param codesPerRev The counts per revolution on the encoder.
+* @param p The proportional gain of the Jaguar's PID controller.
+* @param i The integral gain of the Jaguar's PID controller.
+* @param d The differential gain of the Jaguar's PID controller.
+*/
+void CANJaguar::SetSpeedMode(CANJaguar::QuadEncoderStruct, uint16_t codesPerRev, double p, double i, double d)
+{
+	SetControlMode(kSpeed);
+	SetPositionReference(LM_REF_ENCODER);
+	SetSpeedReference(LM_REF_QUAD_ENCODER);
+	ConfigEncoderCodesPerRev(codesPerRev);
+	SetPID(p, i, d);
+}
+
+/**
+ * Enable controlling the position with a feedback loop using an encoder.<br>
+ * After calling this you must call {@link CANJaguar#EnableControl()} or {@link CANJaguar#EnableControl(double)} to enable the device.
+ *
+ * @param encoder The constant CANJaguar::QuadEncoder
+ * @param codesPerRev The counts per revolution on the encoder.
+ * @param p The proportional gain of the Jaguar's PID controller.
+ * @param i The integral gain of the Jaguar's PID controller.
+ * @param d The differential gain of the Jaguar's PID controller.
+ *
+ */
+void CANJaguar::SetPositionMode(CANJaguar::QuadEncoderStruct, uint16_t codesPerRev, double p, double i, double d)
+{
+	SetControlMode(kPosition);
+	SetPositionReference(LM_REF_ENCODER);
+	ConfigEncoderCodesPerRev(codesPerRev);
+	SetPID(p, i, d);
+}
+
+/**
+* Enable controlling the position with a feedback loop using a potentiometer.<br>
+* After calling this you must call {@link CANJaguar#EnableControl()} or {@link CANJaguar#EnableControl(double)} to enable the device.
+* @param p The proportional gain of the Jaguar's PID controller.
+* @param i The integral gain of the Jaguar's PID controller.
+* @param d The differential gain of the Jaguar's PID controller.
+*/
+void CANJaguar::SetPositionMode(CANJaguar::PotentiometerStruct, double p, double i, double d)
+{
+	SetControlMode(kPosition);
+	SetPositionReference(LM_REF_POT);
+	ConfigPotentiometerTurns(1);
+	SetPID(p, i, d);
+}
+
+/**
+* Enable controlling the motor voltage without any position or speed feedback.<br>
+* After calling this you must call {@link CANJaguar#EnableControl()} or {@link CANJaguar#EnableControl(double)} to enable the device.
+*/
+void CANJaguar::SetVoltageMode()
+{
+	SetControlMode(kVoltage);
+	SetPositionReference(LM_REF_NONE);
+	SetSpeedReference(LM_REF_NONE);
+}
+
+/**
+* Enable controlling the motor voltage with speed feedback from a
+* non-quadrature encoder and no position feedback.<br>
+* After calling this you must call {@link CANJaguar#EnableControl()} or {@link CANJaguar#EnableControl(double)} to enable the device.
+*
+* @param encoder The constant CANJaguar::Encoder
+* @param codesPerRev The counts per revolution on the encoder
+*/
+void CANJaguar::SetVoltageMode(CANJaguar::EncoderStruct, uint16_t codesPerRev)
+{
+	SetControlMode(kVoltage);
+	SetPositionReference(LM_REF_NONE);
+	SetSpeedReference(LM_REF_ENCODER);
+	ConfigEncoderCodesPerRev(codesPerRev);
+}
+
+/**
+* Enable controlling the motor voltage with position and speed feedback from a
+* quadrature encoder.<br>
+* After calling this you must call {@link CANJaguar#EnableControl()} or {@link CANJaguar#EnableControl(double)} to enable the device.
+*
+* @param encoder The constant CANJaguar::QuadEncoder
+* @param codesPerRev The counts per revolution on the encoder
+*/
+void CANJaguar::SetVoltageMode(CANJaguar::QuadEncoderStruct, uint16_t codesPerRev)
+{
+	SetControlMode(kVoltage);
+	SetPositionReference(LM_REF_ENCODER);
+	SetSpeedReference(LM_REF_QUAD_ENCODER);
+	ConfigEncoderCodesPerRev(codesPerRev);
+}
+
+/**
+* Enable controlling the motor voltage with position feedback from a
+* potentiometer and no speed feedback.<br>
+* After calling this you must call {@link CANJaguar#EnableControl()} or {@link CANJaguar#EnableControl(double)} to enable the device.
+*
+* @param potentiometer The constant CANJaguar::Potentiometer
+*/
+void CANJaguar::SetVoltageMode(CANJaguar::PotentiometerStruct)
+{
+	SetControlMode(kVoltage);
+	SetPositionReference(LM_REF_POT);
+	SetSpeedReference(LM_REF_NONE);
+	ConfigPotentiometerTurns(1);
+}
+
+/**
+ * Used internally. In order to set the control mode see the methods listed below.
+ * Change the control mode of this Jaguar object.
+ *
+ * After changing modes, configure any PID constants or other settings needed
+ * and then EnableControl() to actually change the mode on the Jaguar.
+ *
+ * @param controlMode The new mode.
+ */
+void CANJaguar::SetControlMode(ControlMode controlMode)
+{
+	// Disable the previous mode
+	DisableControl();
+
+  if (controlMode == kFollower)
+    wpi_setWPIErrorWithContext(IncompatibleMode, "The Jaguar only supports Current, Voltage, Position, Speed, and Percent (Throttle) modes.");
+
+	// Update the local mode
+	m_controlMode = controlMode;
+	m_controlModeVerified = false;
+
+	HALReport(HALUsageReporting::kResourceType_CANJaguar, m_deviceNumber, m_controlMode);
+}
+
+/**
+ * Get the active control mode from the Jaguar.
+ *
+ * Ask the Jag what mode it is in.
+ *
+ * @return ControlMode that the Jag is in.
+ */
+CANJaguar::ControlMode CANJaguar::GetControlMode()
+{
+	return m_controlMode;
+}
+
+/**
+ * Get the voltage at the battery input terminals of the Jaguar.
+ *
+ * @return The bus voltage in volts.
+ */
+float CANJaguar::GetBusVoltage()
+{
+	updatePeriodicStatus();
+
+	return m_busVoltage;
+}
+
+/**
+ * Get the voltage being output from the motor terminals of the Jaguar.
+ *
+ * @return The output voltage in volts.
+ */
+float CANJaguar::GetOutputVoltage()
+{
+	updatePeriodicStatus();
+
+	return m_outputVoltage;
+}
+
+/**
+ * Get the current through the motor terminals of the Jaguar.
+ *
+ * @return The output current in amps.
+ */
+float CANJaguar::GetOutputCurrent()
+{
+	updatePeriodicStatus();
+
+	return m_outputCurrent;
+}
+
+/**
+ * Get the internal temperature of the Jaguar.
+ *
+ * @return The temperature of the Jaguar in degrees Celsius.
+ */
+float CANJaguar::GetTemperature()
+{
+	updatePeriodicStatus();
+
+	return m_temperature;
+}
+
+/**
+ * Get the position of the encoder or potentiometer.
+ *
+ * @return The position of the motor in rotations based on the configured feedback.
+ * @see CANJaguar#ConfigPotentiometerTurns(int)
+ * @see CANJaguar#ConfigEncoderCodesPerRev(int)
+ */
+double CANJaguar::GetPosition()
+{
+	updatePeriodicStatus();
+
+	return m_position;
+}
+
+/**
+ * Get the speed of the encoder.
+ *
+ * @return The speed of the motor in RPM based on the configured feedback.
+ */
+double CANJaguar::GetSpeed()
+{
+	updatePeriodicStatus();
+
+	return m_speed;
+}
+
+/**
+ * Get the status of the forward limit switch.
+ *
+ * @return The motor is allowed to turn in the forward direction when true.
+ */
+bool CANJaguar::GetForwardLimitOK()
+{
+	updatePeriodicStatus();
+
+	return m_limits & kForwardLimit;
+}
+
+/**
+ * Get the status of the reverse limit switch.
+ *
+ * @return The motor is allowed to turn in the reverse direction when true.
+ */
+bool CANJaguar::GetReverseLimitOK()
+{
+	updatePeriodicStatus();
+
+	return m_limits & kReverseLimit;
+}
+
+/**
+ * Get the status of any faults the Jaguar has detected.
+ *
+ * @return A bit-mask of faults defined by the "Faults" enum.
+ * @see #kCurrentFault
+ * @see #kBusVoltageFault
+ * @see #kTemperatureFault
+ * @see #kGateDriverFault
+ */
+uint16_t CANJaguar::GetFaults()
+{
+	updatePeriodicStatus();
+
+	return m_faults;
+}
+
+/**
+ * Set the maximum voltage change rate.
+ *
+ * When in PercentVbus or Voltage output mode, the rate at which the voltage changes can
+ * be limited to reduce current spikes.  Set this to 0.0 to disable rate limiting.
+ *
+ * @param rampRate The maximum rate of voltage change in Percent Voltage mode in V/s.
+ */
+void CANJaguar::SetVoltageRampRate(double rampRate)
+{
+	uint8_t dataBuffer[8];
+	uint8_t dataSize;
+	uint32_t message;
+
+	switch(m_controlMode)
+	{
+	case kPercentVbus:
+		dataSize = packPercentage(dataBuffer, rampRate / (m_maxOutputVoltage * kControllerRate));
+		message = LM_API_VOLT_SET_RAMP;
+		break;
+	case kVoltage:
+		dataSize = packFXP8_8(dataBuffer, rampRate / kControllerRate);
+		message = LM_API_VCOMP_COMP_RAMP;
+		break;
+	default:
+		wpi_setWPIErrorWithContext(IncompatibleMode, "SetVoltageRampRate only applies in Voltage and Percent mode");
+		return;
+	}
+
+	sendMessage(message, dataBuffer, dataSize);
+
+	m_voltageRampRate = rampRate;
+	m_voltageRampRateVerified = false;
+}
+
+/**
+ * Get the version of the firmware running on the Jaguar.
+ *
+ * @return The firmware version.  0 if the device did not respond.
+ */
+uint32_t CANJaguar::GetFirmwareVersion()
+{
+	return m_firmwareVersion;
+}
+
+/**
+ * Get the version of the Jaguar hardware.
+ *
+ * @return The hardware version. 1: Jaguar,  2: Black Jaguar
+ */
+uint8_t CANJaguar::GetHardwareVersion()
+{
+	return m_hardwareVersion;
+}
+
+/**
+ * Configure what the controller does to the H-Bridge when neutral (not driving the output).
+ *
+ * This allows you to override the jumper configuration for brake or coast.
+ *
+ * @param mode Select to use the jumper setting or to override it to coast or brake.
+ */
+void CANJaguar::ConfigNeutralMode(NeutralMode mode)
+{
+	uint8_t dataBuffer[8];
+
+	// Set the neutral mode
+	sendMessage(LM_API_CFG_BRAKE_COAST, dataBuffer, sizeof(uint8_t));
+
+	m_neutralMode = mode;
+	m_neutralModeVerified = false;
+}
+
+/**
+ * Configure how many codes per revolution are generated by your encoder.
+ *
+ * @param codesPerRev The number of counts per revolution in 1X mode.
+ */
+void CANJaguar::ConfigEncoderCodesPerRev(uint16_t codesPerRev)
+{
+	uint8_t dataBuffer[8];
+	uint8_t dataSize;
+
+	// Set the codes per revolution mode
+	dataSize = packint16_t(dataBuffer, codesPerRev);
+	sendMessage(LM_API_CFG_ENC_LINES, dataBuffer, dataSize);
+
+	m_encoderCodesPerRev = codesPerRev;
+	m_encoderCodesPerRevVerified = false;
+}
+
+/**
+ * Configure the number of turns on the potentiometer.
+ *
+ * There is no special support for continuous turn potentiometers.
+ * Only integer numbers of turns are supported.
+ *
+ * @param turns The number of turns of the potentiometer.
+ */
+void CANJaguar::ConfigPotentiometerTurns(uint16_t turns)
+{
+	uint8_t dataBuffer[8];
+	uint8_t dataSize;
+
+	// Set the pot turns
+	dataSize = packint16_t(dataBuffer, turns);
+	sendMessage(LM_API_CFG_POT_TURNS, dataBuffer, dataSize);
+
+	m_potentiometerTurns = turns;
+	m_potentiometerTurnsVerified = false;
+}
+
+/**
+ * Configure Soft Position Limits when in Position Controller mode.
+ *
+ * When controlling position, you can add additional limits on top of the limit switch inputs
+ * that are based on the position feedback.  If the position limit is reached or the
+ * switch is opened, that direction will be disabled.
+ *
+
+ * @param forwardLimitPosition The position that if exceeded will disable the forward direction.
+ * @param reverseLimitPosition The position that if exceeded will disable the reverse direction.
+ */
+void CANJaguar::ConfigSoftPositionLimits(double forwardLimitPosition, double reverseLimitPosition)
+{
+	ConfigLimitMode(kLimitMode_SoftPositionLimits);
+	ConfigForwardLimit(forwardLimitPosition);
+	ConfigReverseLimit(reverseLimitPosition);
+}
+
+/**
+ * Disable Soft Position Limits if previously enabled.
+ *
+ * Soft Position Limits are disabled by default.
+ */
+void CANJaguar::DisableSoftPositionLimits()
+{
+	ConfigLimitMode(kLimitMode_SwitchInputsOnly);
+}
+
+/**
+ * Set the limit mode for position control mode.
+ *
+ * Use ConfigSoftPositionLimits or DisableSoftPositionLimits to set this
+ * automatically.
+ */
+void CANJaguar::ConfigLimitMode(LimitMode mode)
+{
+	uint8_t dataBuffer[8];
+
+	dataBuffer[0] = mode;
+	sendMessage(LM_API_CFG_LIMIT_MODE, dataBuffer, sizeof(uint8_t));
+
+	m_limitMode = mode;
+	m_limitModeVerified = false;
+}
+
+/**
+* Set the position that if exceeded will disable the forward direction.
+*
+* Use ConfigSoftPositionLimits to set this and the limit mode automatically.
+*/
+void CANJaguar::ConfigForwardLimit(double forwardLimitPosition)
+{
+	uint8_t dataBuffer[8];
+	uint8_t dataSize;
+
+	dataSize = packFXP16_16(dataBuffer, forwardLimitPosition);
+	dataBuffer[dataSize++] = 1;
+	sendMessage(LM_API_CFG_LIMIT_FWD, dataBuffer, dataSize);
+
+	m_forwardLimit = forwardLimitPosition;
+	m_forwardLimitVerified = false;
+}
+
+/**
+* Set the position that if exceeded will disable the reverse direction.
+*
+* Use ConfigSoftPositionLimits to set this and the limit mode automatically.
+*/
+void CANJaguar::ConfigReverseLimit(double reverseLimitPosition)
+{
+	uint8_t dataBuffer[8];
+	uint8_t dataSize;
+
+	dataSize = packFXP16_16(dataBuffer, reverseLimitPosition);
+	dataBuffer[dataSize++] = 0;
+	sendMessage(LM_API_CFG_LIMIT_REV, dataBuffer, dataSize);
+
+	m_reverseLimit = reverseLimitPosition;
+	m_reverseLimitVerified = false;
+}
+
+/**
+ * Configure the maximum voltage that the Jaguar will ever output.
+ *
+ * This can be used to limit the maximum output voltage in all modes so that
+ * motors which cannot withstand full bus voltage can be used safely.
+ *
+ * @param voltage The maximum voltage output by the Jaguar.
+ */
+void CANJaguar::ConfigMaxOutputVoltage(double voltage)
+{
+	uint8_t dataBuffer[8];
+	uint8_t dataSize;
+
+	dataSize = packFXP8_8(dataBuffer, voltage);
+	sendMessage(LM_API_CFG_MAX_VOUT, dataBuffer, dataSize);
+
+	m_maxOutputVoltage = voltage;
+	m_maxOutputVoltageVerified = false;
+}
+
+/**
+ * Configure how long the Jaguar waits in the case of a fault before resuming operation.
+ *
+ * Faults include over temerature, over current, and bus under voltage.
+ * The default is 3.0 seconds, but can be reduced to as low as 0.5 seconds.
+ *
+ * @param faultTime The time to wait before resuming operation, in seconds.
+ */
+void CANJaguar::ConfigFaultTime(float faultTime)
+{
+	uint8_t dataBuffer[8];
+	uint8_t dataSize;
+
+	if(faultTime < 0.5) faultTime = 0.5;
+	else if(faultTime > 3.0) faultTime = 3.0;
+
+	// Message takes ms
+	dataSize = packint16_t(dataBuffer, (int16_t)(faultTime * 1000.0));
+	sendMessage(LM_API_CFG_FAULT_TIME, dataBuffer, dataSize);
+
+	m_faultTime = faultTime;
+	m_faultTimeVerified = false;
+}
+
+/**
+ * Update all the motors that have pending sets in the syncGroup.
+ *
+ * @param syncGroup A bitmask of groups to generate synchronous output.
+ */
+void CANJaguar::UpdateSyncGroup(uint8_t syncGroup)
+{
+	sendMessageHelper(CAN_MSGID_API_SYNC, &syncGroup, sizeof(syncGroup), CAN_SEND_PERIOD_NO_REPEAT);
+}
+
+
+void CANJaguar::SetExpiration(float timeout)
+{
+	if (m_safetyHelper) m_safetyHelper->SetExpiration(timeout);
+}
+
+float CANJaguar::GetExpiration()
+{
+	if (!m_safetyHelper) return 0.0;
+	return m_safetyHelper->GetExpiration();
+}
+
+bool CANJaguar::IsAlive()
+{
+	if (!m_safetyHelper) return false;
+	return m_safetyHelper->IsAlive();
+}
+
+bool CANJaguar::IsSafetyEnabled()
+{
+	if (!m_safetyHelper) return false;
+	return m_safetyHelper->IsSafetyEnabled();
+}
+
+void CANJaguar::SetSafetyEnabled(bool enabled)
+{
+	if (m_safetyHelper) m_safetyHelper->SetSafetyEnabled(enabled);
+}
+
+void CANJaguar::GetDescription(char *desc)
+{
+	sprintf(desc, "CANJaguar ID %d", m_deviceNumber);
+}
+
+uint8_t CANJaguar::GetDeviceID()
+{
+	return m_deviceNumber;
+}
+
+/**
+ * Common interface for stopping the motor
+ * Part of the MotorSafety interface
+ *
+ * @deprecated Call DisableControl instead.
+ */
+void CANJaguar::StopMotor()
+{
+	DisableControl();
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/CANTalon.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/CANTalon.cpp
new file mode 100644
index 0000000..1dd7b7e
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/CANTalon.cpp
@@ -0,0 +1,1259 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "CANTalon.h"
+#include "WPIErrors.h"
+#include "ctre/CanTalonSRX.h"
+#include <unistd.h> // usleep
+/**
+ * Constructor for the CANTalon device.
+ * @param deviceNumber The CAN ID of the Talon SRX
+ */
+CANTalon::CANTalon(int deviceNumber)
+	: m_deviceNumber(deviceNumber)
+	, m_impl(new CanTalonSRX(deviceNumber))
+	, m_safetyHelper(new MotorSafetyHelper(this))
+  , m_profile(0)
+  , m_controlEnabled(true)
+  , m_controlMode(kPercentVbus)
+  , m_setPoint(0)
+{
+  ApplyControlMode(m_controlMode);
+  m_impl->SetProfileSlotSelect(m_profile);
+}
+/**
+ * Constructor for the CANTalon device.
+ * @param deviceNumber The CAN ID of the Talon SRX
+ * @param controlPeriodMs The period in ms to send the CAN control frame.
+ *							Period is bounded to [1ms, 95ms].
+ */
+CANTalon::CANTalon(int deviceNumber,int controlPeriodMs)
+	: m_deviceNumber(deviceNumber)
+	, m_impl(new CanTalonSRX(deviceNumber,controlPeriodMs)) /* bounded underneath to be within [1 ms,95 ms] */
+	, m_safetyHelper(new MotorSafetyHelper(this))
+  , m_profile(0)
+  , m_controlEnabled(true)
+  , m_controlMode(kPercentVbus)
+  , m_setPoint(0)
+{
+  ApplyControlMode(m_controlMode);
+  m_impl->SetProfileSlotSelect(m_profile);
+}
+CANTalon::~CANTalon() {
+	delete m_impl;
+	delete m_safetyHelper;
+}
+
+/**
+* Write out the PID value as seen in the PIDOutput base object.
+*
+* @deprecated Call Set instead.
+*
+* @param output Write out the PercentVbus value as was computed by the PIDController
+*/
+void CANTalon::PIDWrite(float output)
+{
+	if (GetControlMode() == kPercentVbus)
+	{
+		Set(output);
+	}
+	else
+	{
+		wpi_setWPIErrorWithContext(IncompatibleMode, "PID only supported in PercentVbus mode");
+	}
+}
+
+  /**
+   * Gets the current status of the Talon (usually a sensor value).
+   *
+   * In Current mode: returns output current.
+   * In Speed mode: returns current speed.
+   * In Position mode: returns current sensor position.
+   * In PercentVbus and Follower modes: returns current applied throttle.
+   *
+   * @return The current sensor value of the Talon.
+   */
+float CANTalon::Get()
+{
+  int value;
+  switch(m_controlMode) {
+    case kVoltage:
+      return GetOutputVoltage();
+    case kCurrent:
+      return GetOutputCurrent();
+    case kSpeed:
+      m_impl->GetSensorVelocity(value);
+      return value;
+    case kPosition:
+      m_impl->GetSensorPosition(value);
+      return value;
+    case kPercentVbus:
+    default:
+      m_impl->GetAppliedThrottle(value);
+      return (float)value / 1023.0;
+  }
+}
+
+/**
+ * Sets the appropriate output on the talon, depending on the mode.
+ *
+ * In PercentVbus, the output is between -1.0 and 1.0, with 0.0 as stopped.
+ * In Voltage mode, output value is in volts.
+ * In Current mode, output value is in amperes.
+ * In Speed mode, output value is in position change / 10ms.
+ * In Position mode, output value is in encoder ticks or an analog value,
+ *   depending on the sensor.
+ * In Follower mode, the output value is the integer device ID of the talon to duplicate.
+ *
+ * @param outputValue The setpoint value, as described above.
+ * @see SelectProfileSlot to choose between the two sets of gains.
+ */
+void CANTalon::Set(float value, uint8_t syncGroup)
+{
+  /* feed safety helper since caller just updated our output */
+  m_safetyHelper->Feed();
+  if(m_controlEnabled) {
+    m_setPoint = value;
+    CTR_Code status;
+    switch(m_controlMode) {
+      case CANSpeedController::kPercentVbus:
+        {
+          m_impl->Set(value);
+          status = CTR_OKAY;
+        }
+        break;
+      case CANSpeedController::kFollower:
+        {
+          status = m_impl->SetDemand((int)value);
+        }
+        break;
+      case CANSpeedController::kVoltage:
+        {
+          // Voltage is an 8.8 fixed point number.
+          int volts = int(value * 256);
+          status = m_impl->SetDemand(volts);
+        }
+        break;
+      case CANSpeedController::kSpeed:
+        status = m_impl->SetDemand(value);
+        break;
+      case CANSpeedController::kPosition:
+        status = m_impl->SetDemand(value);
+        break;
+      default:
+        break;
+    }
+    if (status != CTR_OKAY) {
+      wpi_setErrorWithContext(status, getHALErrorMessage(status));
+    }
+
+    status = m_impl->SetModeSelect(m_sendMode);
+
+    if (status != CTR_OKAY) {
+      wpi_setErrorWithContext(status, getHALErrorMessage(status));
+    }
+
+  }
+}
+
+/**
+ * TODO documentation (see CANJaguar.cpp)
+ */
+void CANTalon::Disable()
+{
+  // Until Modes other than throttle work, just disable by setting throttle to 0.0.
+  m_impl->SetModeSelect((int)CANTalon::kDisabled);
+  m_controlEnabled = false;
+}
+
+/**
+ * TODO documentation (see CANJaguar.cpp)
+ */
+void CANTalon::EnableControl() {
+  SetControlMode(m_controlMode);
+  m_controlEnabled = true;
+}
+
+/**
+ * @return Whether the Talon is currently enabled.
+ */
+bool CANTalon::IsControlEnabled() {
+  return m_controlEnabled;
+}
+
+/**
+ * @param p Proportional constant to use in PID loop.
+ * @see SelectProfileSlot to choose between the two sets of gains.
+ */
+void CANTalon::SetP(double p)
+{
+  CTR_Code status = m_impl->SetPgain(m_profile, p);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+}
+
+ /**
+  * Set the integration constant of the currently selected profile.
+  *
+  * @param i Integration constant for the currently selected PID profile.
+  * @see SelectProfileSlot to choose between the two sets of gains.
+  */
+void CANTalon::SetI(double i)
+{
+  CTR_Code status = m_impl->SetIgain(m_profile, i);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+}
+
+/**
+ * Set the derivative constant of the currently selected profile.
+ *
+ * @param d Derivative constant for the currently selected PID profile.
+ * @see SelectProfileSlot to choose between the two sets of gains.
+ */
+void CANTalon::SetD(double d)
+{
+  CTR_Code status = m_impl->SetDgain(m_profile, d);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+}
+/**
+ * Set the feedforward value of the currently selected profile.
+ *
+ * @param f Feedforward constant for the currently selected PID profile.
+ * @see SelectProfileSlot to choose between the two sets of gains.
+ */
+void CANTalon::SetF(double f)
+{
+  CTR_Code status = m_impl->SetFgain(m_profile, f);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+}
+/**
+ * Set the Izone to a nonzero value to auto clear the integral accumulator
+ *		when the absolute value of CloseLoopError exceeds Izone.
+ *
+ * @see SelectProfileSlot to choose between the two sets of gains.
+ */
+void CANTalon::SetIzone(unsigned iz)
+{
+  CTR_Code status = m_impl->SetIzone(m_profile, iz);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+}
+/**
+ * SRX has two available slots for PID.
+ * @param slotIdx one or zero depending on which slot caller wants.
+ */
+void CANTalon::SelectProfileSlot(int slotIdx)
+{
+	m_profile = (slotIdx == 0) ? 0 : 1; /* only get two slots for now */
+	CTR_Code status = m_impl->SetProfileSlotSelect(m_profile);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+}
+/**
+ * Sets control values for closed loop control.
+ *
+ * @param p Proportional constant.
+ * @param i Integration constant.
+ * @param d Differential constant.
+ * This function does not modify F-gain.  Considerable passing a zero for f using
+ * the four-parameter function.
+ */
+void CANTalon::SetPID(double p, double i, double d)
+{
+	SetP(p);
+	SetI(i);
+	SetD(d);
+}
+/**
+ * Sets control values for closed loop control.
+ *
+ * @param p Proportional constant.
+ * @param i Integration constant.
+ * @param d Differential constant.
+ * @param f Feedforward constant.
+ */
+void CANTalon::SetPID(double p, double i, double d, double f)
+{
+	SetP(p);
+	SetI(i);
+	SetD(d);
+	SetF(f);
+}
+/**
+ * Select the feedback device to use in closed-loop
+ */
+void CANTalon::SetFeedbackDevice(FeedbackDevice device)
+{
+	CTR_Code status = m_impl->SetFeedbackDeviceSelect((int)device);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+}
+/**
+ * Select the feedback device to use in closed-loop
+ */
+void CANTalon::SetStatusFrameRateMs(StatusFrameRate stateFrame, int periodMs)
+{
+	CTR_Code status = m_impl->SetStatusFrameRate((int)stateFrame,periodMs);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+}
+
+/**
+ * Get the current proportional constant.
+ *
+ * @return double proportional constant for current profile.
+ * @see SelectProfileSlot to choose between the two sets of gains.
+ */
+double CANTalon::GetP()
+{
+  CanTalonSRX::param_t param = m_profile ? CanTalonSRX::eProfileParamSlot1_P : CanTalonSRX::eProfileParamSlot0_P;
+  // Update the info in m_impl.
+  CTR_Code status = m_impl->RequestParam(param);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+  }
+  usleep(kDelayForSolicitedSignalsUs); /* small yield for getting response */
+  double p;
+  status = m_impl->GetPgain(m_profile, p);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+	return p;
+}
+
+/**
+ * TODO documentation (see CANJaguar.cpp)
+ * @see SelectProfileSlot to choose between the two sets of gains.
+ */
+double CANTalon::GetI()
+{
+  CanTalonSRX::param_t param = m_profile ? CanTalonSRX::eProfileParamSlot1_I : CanTalonSRX::eProfileParamSlot0_I;
+  // Update the info in m_impl.
+  CTR_Code status = m_impl->RequestParam(param);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+  }
+	usleep(kDelayForSolicitedSignalsUs); /* small yield for getting response */
+
+  double i;
+  status = m_impl->GetIgain(m_profile, i);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+	return i;
+}
+
+/**
+ * TODO documentation (see CANJaguar.cpp)
+ * @see SelectProfileSlot to choose between the two sets of gains.
+ */
+double CANTalon::GetD()
+{
+  CanTalonSRX::param_t param = m_profile ? CanTalonSRX::eProfileParamSlot1_D : CanTalonSRX::eProfileParamSlot0_D;
+  // Update the info in m_impl.
+  CTR_Code status = m_impl->RequestParam(param);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+  }
+	usleep(kDelayForSolicitedSignalsUs); /* small yield for getting response */
+
+  double d;
+  status = m_impl->GetDgain(m_profile, d);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+	return d;
+}
+/**
+ *
+ * @see SelectProfileSlot to choose between the two sets of gains.
+ */
+double CANTalon::GetF()
+{
+  CanTalonSRX::param_t param = m_profile ? CanTalonSRX::eProfileParamSlot1_F : CanTalonSRX::eProfileParamSlot0_F;
+  // Update the info in m_impl.
+  CTR_Code status = m_impl->RequestParam(param);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+  }
+
+	usleep(kDelayForSolicitedSignalsUs);  /* small yield for getting response */
+  double f;
+  status = m_impl->GetFgain(m_profile, f);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+	return f;
+}
+/**
+ * @see SelectProfileSlot to choose between the two sets of gains.
+ */
+int CANTalon::GetIzone()
+{
+  CanTalonSRX::param_t param = m_profile ? CanTalonSRX::eProfileParamSlot1_IZone: CanTalonSRX::eProfileParamSlot0_IZone;
+ // Update the info in m_impl.
+ CTR_Code status = m_impl->RequestParam(param);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+ }
+	usleep(kDelayForSolicitedSignalsUs);
+
+ int iz;
+ status = m_impl->GetIzone(m_profile, iz);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+	return iz;
+}
+
+/**
+ * @return the current setpoint; ie, whatever was last passed to Set().
+ */
+double CANTalon::GetSetpoint() {
+  return m_setPoint;
+}
+
+/**
+ * Returns the voltage coming in from the battery.
+ *
+ * @return The input voltage in volts.
+ */
+float CANTalon::GetBusVoltage()
+{
+  double voltage;
+  CTR_Code status = m_impl->GetBatteryV(voltage);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+  return voltage;
+}
+
+/**
+ * @return The voltage being output by the Talon, in Volts.
+ */
+float CANTalon::GetOutputVoltage()
+{
+  int throttle11;
+  CTR_Code status = m_impl->GetAppliedThrottle(throttle11);
+  float voltage = GetBusVoltage() * (float(throttle11) / 1023.0);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+	return voltage;
+}
+
+
+/**
+ *  Returns the current going through the Talon, in Amperes.
+ */
+float CANTalon::GetOutputCurrent()
+{
+  double current;
+
+  CTR_Code status = m_impl->GetCurrent(current);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+
+	return current;
+}
+
+  /**
+   *  Returns temperature of Talon, in degrees Celsius.
+   */
+float CANTalon::GetTemperature()
+{
+  double temp;
+
+  CTR_Code status = m_impl->GetTemp(temp);
+	if(temp != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+	return temp;
+}
+/**
+ * Set the position value of the selected sensor.  This is useful for zero-ing quadrature encoders.
+ * Continuous sensors (like analog encoderes) can also partially be set (the portion of the postion based on overflows).
+ */
+void CANTalon::SetPosition(double pos)
+{
+	m_impl->SetSensorPosition(pos);
+}
+/**
+ * TODO documentation (see CANJaguar.cpp)
+ *
+ * @return The position of the sensor currently providing feedback.
+ * 			When using analog sensors, 0 units corresponds to 0V, 1023 units corresponds to 3.3V
+ * 			When using an analog encoder (wrapping around 1023 => 0 is possible) the units are still 3.3V per 1023 units.
+ * 			When using quadrature, each unit is a quadrature edge (4X) mode.
+ */
+double CANTalon::GetPosition()
+{
+  int postition;
+
+  CTR_Code status = m_impl->GetSensorPosition(postition);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+	return (double)postition;
+}
+/**
+ * If sensor and motor are out of phase, sensor can be inverted 
+ * (position and velocity multiplied by -1).
+ * @see GetPosition and @see GetSpeed.
+ */
+void CANTalon::SetSensorDirection(bool reverseSensor)
+{
+  CTR_Code status = m_impl->SetRevFeedbackSensor(reverseSensor ? 1 : 0);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+}
+
+/**
+ * Returns the current error in the controller.
+ *
+ * @return the difference between the setpoint and the sensor value.
+ */
+int CANTalon::GetClosedLoopError() {
+  int error;
+  CTR_Code status = m_impl->GetCloseLoopErr(error);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+  return error;
+}
+
+/**
+ * TODO documentation (see CANJaguar.cpp)
+ *
+ * @returns The speed of the sensor currently providing feedback.
+ *
+ * The speed units will be in the sensor's native ticks per 100ms.
+ *
+ * For analog sensors, 3.3V corresponds to 1023 units.
+ * 		So a speed of 200 equates to ~0.645 dV per 100ms or 6.451 dV per second.
+ * 		If this is an analog encoder, that likely means 1.9548 rotations per sec.
+ * For quadrature encoders, each unit corresponds a quadrature edge (4X).
+ * 		So a 250 count encoder will produce 1000 edge events per rotation.
+ * 		An example speed of 200 would then equate to 20% of a rotation per 100ms,
+ * 		or 10 rotations per second.
+ */
+double CANTalon::GetSpeed()
+{
+  int speed;
+  // TODO convert from int to appropriate units (or at least document it).
+
+  CTR_Code status = m_impl->GetSensorVelocity(speed);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+	return (double)speed;
+}
+
+/**
+ * Get the position of whatever is in the analog pin of the Talon, regardless of
+ * whether it is actually being used for feedback.
+ *
+ * @returns The 24bit analog value.  The bottom ten bits is the ADC (0 - 1023) on 
+ *								the analog pin of the Talon. The upper 14 bits
+ *								tracks the overflows and underflows (continuous sensor).
+ */
+int CANTalon::GetAnalogIn()
+{
+  int position;
+  CTR_Code status = m_impl->GetAnalogInWithOv(position);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+  return position;
+}
+/**
+ * Get the position of whatever is in the analog pin of the Talon, regardless of
+ * whether it is actually being used for feedback.
+ *
+ * @returns The ADC (0 - 1023) on analog pin of the Talon.
+ */
+int CANTalon::GetAnalogInRaw()
+{
+    return GetAnalogIn() & 0x3FF;
+}
+/**
+ * Get the position of whatever is in the analog pin of the Talon, regardless of
+ * whether it is actually being used for feedback.
+ *
+ * @returns The value (0 - 1023) on the analog pin of the Talon.
+ */
+int CANTalon::GetAnalogInVel()
+{
+  int vel;
+  CTR_Code status = m_impl->GetAnalogInVel(vel);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+  return vel;
+}
+
+/**
+ * Get the position of whatever is in the analog pin of the Talon, regardless of
+ * whether it is actually being used for feedback.
+ *
+ * @returns The value (0 - 1023) on the analog pin of the Talon.
+ */
+int CANTalon::GetEncPosition()
+{
+  int position;
+  CTR_Code status = m_impl->GetEncPosition(position);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+  return position;
+}
+
+/**
+ * Get the position of whatever is in the analog pin of the Talon, regardless of
+ * whether it is actually being used for feedback.
+ *
+ * @returns The value (0 - 1023) on the analog pin of the Talon.
+ */
+int CANTalon::GetEncVel()
+{
+  int vel;
+  CTR_Code status = m_impl->GetEncVel(vel);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+  return vel;
+}
+/**
+ * @return IO level of QUADA pin.
+ */
+int CANTalon::GetPinStateQuadA()
+{
+	int retval;
+	CTR_Code status = m_impl->GetQuadApin(retval);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+	return retval;
+}
+/**
+ * @return IO level of QUADB pin.
+ */
+int CANTalon::GetPinStateQuadB()
+{
+	int retval;
+	CTR_Code status = m_impl->GetQuadBpin(retval);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+	return retval;
+}
+/**
+ * @return IO level of QUAD Index pin.
+ */
+int CANTalon::GetPinStateQuadIdx()
+{
+	int retval;
+	CTR_Code status = m_impl->GetQuadIdxpin(retval);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+	return retval;
+}
+/**
+ * @return '1' iff forward limit switch is closed, 0 iff switch is open.
+ * This function works regardless if limit switch feature is enabled.
+ */
+int CANTalon::IsFwdLimitSwitchClosed()
+{
+	int retval;
+	CTR_Code status = m_impl->GetLimitSwitchClosedFor(retval); /* rename this func, '1' => open, '0' => closed */
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+	return retval ? 0 : 1;
+}
+/**
+ * @return '1' iff reverse limit switch is closed, 0 iff switch is open.
+ * This function works regardless if limit switch feature is enabled.
+ */
+int CANTalon::IsRevLimitSwitchClosed()
+{
+	int retval;
+	CTR_Code status = m_impl->GetLimitSwitchClosedRev(retval); /* rename this func, '1' => open, '0' => closed */
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+	return retval ? 0 : 1;
+}
+/*
+ * Simple accessor for tracked rise eventso index pin.
+ * @return number of rising edges on idx pin.
+ */
+int CANTalon::GetNumberOfQuadIdxRises()
+{
+	int rises;
+	CTR_Code status = m_impl->GetEncIndexRiseEvents(rises); /* rename this func, '1' => open, '0' => closed */
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+	return rises;
+}
+/*
+ * @param rises integral value to set into index-rises register.  Great way to zero the index count.
+ */
+void CANTalon::SetNumberOfQuadIdxRises(int rises)
+{
+	CTR_Code status = m_impl->SetParam(CanTalonSRX::eEncIndexRiseEvents, rises); /* rename this func, '1' => open, '0' => closed */
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+}
+/**
+ * TODO documentation (see CANJaguar.cpp)
+ */
+bool CANTalon::GetForwardLimitOK()
+{
+	int limSwit=0;
+	int softLim=0;
+	CTR_Code status;
+	status = m_impl->GetFault_ForSoftLim(softLim);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+	status = m_impl->GetFault_ForLim(limSwit);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+	/* If either fault is asserted, signal caller we are disabled (with false?) */
+	return (softLim | limSwit) ? false : true;
+}
+
+/**
+ * TODO documentation (see CANJaguar.cpp)
+ */
+bool CANTalon::GetReverseLimitOK()
+{
+	int limSwit=0;
+	int softLim=0;
+	CTR_Code status;
+	status = m_impl->GetFault_RevSoftLim(softLim);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+	status = m_impl->GetFault_RevLim(limSwit);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+	/* If either fault is asserted, signal caller we are disabled (with false?) */
+	return (softLim | limSwit) ? false : true;
+}
+
+/**
+ * TODO documentation (see CANJaguar.cpp)
+ */
+uint16_t CANTalon::GetFaults()
+{
+	uint16_t retval = 0;
+	int val;
+	CTR_Code status;
+
+	/* temperature */
+	val = 0;
+	status = m_impl->GetFault_OverTemp(val);
+	if(status != CTR_OKAY)
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	retval |= (val) ? CANSpeedController::kTemperatureFault : 0;
+
+	/* voltage */
+	val = 0;
+	status = m_impl->GetFault_UnderVoltage(val);
+	if(status != CTR_OKAY)
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	retval |= (val) ? CANSpeedController::kBusVoltageFault : 0;
+
+	/* fwd-limit-switch */
+	val = 0;
+	status = m_impl->GetFault_ForLim(val);
+	if(status != CTR_OKAY)
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	retval |= (val) ? CANSpeedController::kFwdLimitSwitch : 0;
+
+	/* rev-limit-switch */
+	val = 0;
+	status = m_impl->GetFault_RevLim(val);
+	if(status != CTR_OKAY)
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	retval |= (val) ? CANSpeedController::kRevLimitSwitch : 0;
+
+	/* fwd-soft-limit */
+	val = 0;
+	status = m_impl->GetFault_ForSoftLim(val);
+	if(status != CTR_OKAY)
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	retval |= (val) ? CANSpeedController::kFwdSoftLimit : 0;
+
+	/* rev-soft-limit */
+	val = 0;
+	status = m_impl->GetFault_RevSoftLim(val);
+	if(status != CTR_OKAY)
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	retval |= (val) ? CANSpeedController::kRevSoftLimit : 0;
+
+	return retval;
+}
+uint16_t CANTalon::GetStickyFaults()
+{
+	uint16_t retval = 0;
+	int val;
+	CTR_Code status;
+
+	/* temperature */
+	val = 0;
+	status = m_impl->GetStckyFault_OverTemp(val);
+	if(status != CTR_OKAY)
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	retval |= (val) ? CANSpeedController::kTemperatureFault : 0;
+
+	/* voltage */
+	val = 0;
+	status = m_impl->GetStckyFault_UnderVoltage(val);
+	if(status != CTR_OKAY)
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	retval |= (val) ? CANSpeedController::kBusVoltageFault : 0;
+
+	/* fwd-limit-switch */
+	val = 0;
+	status = m_impl->GetStckyFault_ForLim(val);
+	if(status != CTR_OKAY)
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	retval |= (val) ? CANSpeedController::kFwdLimitSwitch : 0;
+
+	/* rev-limit-switch */
+	val = 0;
+	status = m_impl->GetStckyFault_RevLim(val);
+	if(status != CTR_OKAY)
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	retval |= (val) ? CANSpeedController::kRevLimitSwitch : 0;
+
+	/* fwd-soft-limit */
+	val = 0;
+	status = m_impl->GetStckyFault_ForSoftLim(val);
+	if(status != CTR_OKAY)
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	retval |= (val) ? CANSpeedController::kFwdSoftLimit : 0;
+
+	/* rev-soft-limit */
+	val = 0;
+	status = m_impl->GetStckyFault_RevSoftLim(val);
+	if(status != CTR_OKAY)
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	retval |= (val) ? CANSpeedController::kRevSoftLimit : 0;
+
+	return retval;
+}
+void CANTalon::ClearStickyFaults()
+{
+	CTR_Code status = m_impl->ClearStickyFaults();
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Set the maximum voltage change rate.  This ramp rate is in affect regardless of which control mode
+ * the TALON is in.
+ *
+ * When in PercentVbus or Voltage output mode, the rate at which the voltage changes can
+ * be limited to reduce current spikes.  Set this to 0.0 to disable rate limiting.
+ *
+ * @param rampRate The maximum rate of voltage change in Percent Voltage mode in V/s.
+ */
+void CANTalon::SetVoltageRampRate(double rampRate)
+{
+	/* Caller is expressing ramp as Voltage per sec, assuming 12V is full.
+		Talon's throttle ramp is in dThrot/d10ms.  1023 is full fwd, -1023 is full rev. */
+	double rampRatedThrotPer10ms = (rampRate*1023.0/12.0) / 100;
+	CTR_Code status = m_impl->SetRampThrottle((int)rampRatedThrotPer10ms);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+}
+/**
+ * Sets a voltage change rate that applies only when a close loop contorl mode is enabled.
+ * This allows close loop specific ramp behavior.
+ *
+ * @param rampRate The maximum rate of voltage change in Percent Voltage mode in V/s.
+ */
+void CANTalon::SetCloseLoopRampRate(double rampRate)
+{
+	  CTR_Code status = m_impl->SetCloseLoopRampRate(m_profile,rampRate * 1023.0 / 12.0 / 1000.0);
+		if(status != CTR_OKAY) {
+			wpi_setErrorWithContext(status, getHALErrorMessage(status));
+		}
+}
+
+/**
+ * @return The version of the firmware running on the Talon
+ */
+uint32_t CANTalon::GetFirmwareVersion()
+{
+	int firmwareVersion;
+	CTR_Code status = m_impl->RequestParam(CanTalonSRX::eFirmVers);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+	usleep(kDelayForSolicitedSignalsUs);
+	status = m_impl->GetParamResponseInt32(CanTalonSRX::eFirmVers,firmwareVersion);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+
+	/* only sent once on boot */
+	//CTR_Code status = m_impl->GetFirmVers(firmwareVersion);
+	//if(status != CTR_OKAY) {
+	//	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	//}
+
+	return firmwareVersion;
+}
+/**
+ * @return The accumulator for I gain.
+ */
+int CANTalon::GetIaccum()
+{
+	CTR_Code status = m_impl->RequestParam(CanTalonSRX::ePidIaccum);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+	usleep(kDelayForSolicitedSignalsUs); /* small yield for getting response */
+	int iaccum;
+	status = m_impl->GetParamResponseInt32(CanTalonSRX::ePidIaccum,iaccum);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+	return iaccum;
+}
+/**
+ * Clear the accumulator for I gain.
+ */
+void CANTalon::ClearIaccum()
+{
+	CTR_Code status = m_impl->SetParam(CanTalonSRX::ePidIaccum, 0);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+}
+
+/**
+ * TODO documentation (see CANJaguar.cpp)
+ */
+void CANTalon::ConfigNeutralMode(NeutralMode mode)
+{
+	CTR_Code status;
+	switch(mode){
+		default:
+		case kNeutralMode_Jumper: /* use default setting in flash based on webdash/BrakeCal button selection */
+			status = m_impl->SetOverrideBrakeType(CanTalonSRX::kBrakeOverride_UseDefaultsFromFlash);
+			break;
+		case kNeutralMode_Brake:
+			status = m_impl->SetOverrideBrakeType(CanTalonSRX::kBrakeOverride_OverrideBrake);
+			break;
+		case kNeutralMode_Coast:
+			status = m_impl->SetOverrideBrakeType(CanTalonSRX::kBrakeOverride_OverrideCoast);
+			break;
+	}
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+}
+/**
+ * @return nonzero if brake is enabled during neutral.  Zero if coast is enabled during neutral.
+ */
+int CANTalon::GetBrakeEnableDuringNeutral()
+{
+  int brakeEn = 0;
+  CTR_Code status = m_impl->GetBrakeIsEnabled(brakeEn);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+	return brakeEn;
+}
+/**
+ * @deprecated not implemented
+ */
+void CANTalon::ConfigEncoderCodesPerRev(uint16_t codesPerRev)
+{
+	/* TALON SRX does not scale units, they are raw from the sensor.  Unit scaling can be done in API or by caller */
+}
+
+/**
+ * @deprecated not implemented
+ */
+void CANTalon::ConfigPotentiometerTurns(uint16_t turns)
+{
+	/* TALON SRX does not scale units, they are raw from the sensor.  Unit scaling can be done in API or by caller */
+}
+
+/**
+ * @deprecated not implemented
+ */
+void CANTalon::ConfigSoftPositionLimits(double forwardLimitPosition, double reverseLimitPosition)
+{
+	ConfigLimitMode(kLimitMode_SoftPositionLimits);
+	ConfigForwardLimit(forwardLimitPosition);
+	ConfigReverseLimit(reverseLimitPosition);
+}
+
+/**
+ * TODO documentation (see CANJaguar.cpp)
+ */
+void CANTalon::DisableSoftPositionLimits()
+{
+	ConfigLimitMode(kLimitMode_SwitchInputsOnly);
+}
+
+/**
+ * TODO documentation (see CANJaguar.cpp)
+ * Configures the soft limit enable (wear leveled persistent memory).
+ * Also sets the limit switch overrides.
+ */
+void CANTalon::ConfigLimitMode(LimitMode mode)
+{
+	CTR_Code status;
+	switch(mode){
+		case kLimitMode_SwitchInputsOnly: 	/** Only use switches for limits */
+			/* turn OFF both limits. SRX has individual enables and polarity for each limit switch.*/
+			status = m_impl->SetForwardSoftEnable(false);
+			if(status != CTR_OKAY) {
+				wpi_setErrorWithContext(status, getHALErrorMessage(status));
+			}
+			status = m_impl->SetReverseSoftEnable(false);
+			if(status != CTR_OKAY) {
+				wpi_setErrorWithContext(status, getHALErrorMessage(status));
+			}
+			/* override enable the limit switches, this circumvents the webdash */
+			status = m_impl->SetOverrideLimitSwitchEn(CanTalonSRX::kLimitSwitchOverride_EnableFwd_EnableRev);
+			if(status != CTR_OKAY) {
+				wpi_setErrorWithContext(status, getHALErrorMessage(status));
+			}
+			break;
+		case kLimitMode_SoftPositionLimits: /** Use both switches and soft limits */
+			/* turn on both limits. SRX has individual enables and polarity for each limit switch.*/
+			status = m_impl->SetForwardSoftEnable(true);
+			if(status != CTR_OKAY) {
+				wpi_setErrorWithContext(status, getHALErrorMessage(status));
+			}
+			status = m_impl->SetReverseSoftEnable(true);
+			if(status != CTR_OKAY) {
+				wpi_setErrorWithContext(status, getHALErrorMessage(status));
+			}
+			/* override enable the limit switches, this circumvents the webdash */
+			status = m_impl->SetOverrideLimitSwitchEn(CanTalonSRX::kLimitSwitchOverride_EnableFwd_EnableRev);
+			if(status != CTR_OKAY) {
+				wpi_setErrorWithContext(status, getHALErrorMessage(status));
+			}
+			break;
+			
+		case kLimitMode_SrxDisableSwitchInputs: /** disable both limit switches and soft limits */
+			/* turn on both limits. SRX has individual enables and polarity for each limit switch.*/
+			status = m_impl->SetForwardSoftEnable(false);
+			if(status != CTR_OKAY) {
+				wpi_setErrorWithContext(status, getHALErrorMessage(status));
+			}
+			status = m_impl->SetReverseSoftEnable(false);
+			if(status != CTR_OKAY) {
+				wpi_setErrorWithContext(status, getHALErrorMessage(status));
+			}
+			/* override enable the limit switches, this circumvents the webdash */
+			status = m_impl->SetOverrideLimitSwitchEn(CanTalonSRX::kLimitSwitchOverride_DisableFwd_DisableRev);
+			if(status != CTR_OKAY) {
+				wpi_setErrorWithContext(status, getHALErrorMessage(status));
+			}
+			break;
+	}
+}
+
+/**
+ * TODO documentation (see CANJaguar.cpp)
+ */
+void CANTalon::ConfigForwardLimit(double forwardLimitPosition)
+{
+	CTR_Code status;
+	status = m_impl->SetForwardSoftLimit(forwardLimitPosition);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+}
+/**
+ * Change the fwd limit switch setting to normally open or closed.
+ * Talon will disable momentarilly if the Talon's current setting
+ * is dissimilar to the caller's requested setting.
+ *
+ * Since Talon saves setting to flash this should only affect
+ * a given Talon initially during robot install.
+ *
+ * @param normallyOpen true for normally open.  false for normally closed.
+ */
+void CANTalon::ConfigFwdLimitSwitchNormallyOpen(bool normallyOpen)
+{
+	CTR_Code status = m_impl->SetParam(CanTalonSRX::eOnBoot_LimitSwitch_Forward_NormallyClosed, normallyOpen ? 0 : 1);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+}
+/**
+ * Change the rev limit switch setting to normally open or closed.
+ * Talon will disable momentarilly if the Talon's current setting
+ * is dissimilar to the caller's requested setting.
+ *
+ * Since Talon saves setting to flash this should only affect
+ * a given Talon initially during robot install.
+ *
+ * @param normallyOpen true for normally open.  false for normally closed.
+ */
+void CANTalon::ConfigRevLimitSwitchNormallyOpen(bool normallyOpen)
+{
+	CTR_Code status = m_impl->SetParam(CanTalonSRX::eOnBoot_LimitSwitch_Reverse_NormallyClosed, normallyOpen ? 0 : 1);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+}
+/**
+ * TODO documentation (see CANJaguar.cpp)
+ */
+void CANTalon::ConfigReverseLimit(double reverseLimitPosition)
+{
+	CTR_Code status;
+	status = m_impl->SetReverseSoftLimit(reverseLimitPosition);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+}
+
+/**
+ * TODO documentation (see CANJaguar.cpp)
+ */
+void CANTalon::ConfigMaxOutputVoltage(double voltage)
+{
+	/* SRX does not support max output  */
+	wpi_setWPIErrorWithContext(IncompatibleMode, "MaxOutputVoltage not supported.");
+}
+
+/**
+ * TODO documentation (see CANJaguar.cpp)
+ */
+void CANTalon::ConfigFaultTime(float faultTime)
+{
+	/* SRX does not have fault time.  SRX motor drive is only disabled for soft limits and limit-switch faults. */
+	wpi_setWPIErrorWithContext(IncompatibleMode, "Fault Time not supported.");
+}
+
+/**
+ * Fixup the sendMode so Set() serializes the correct demand value.
+ * Also fills the modeSelecet in the control frame to disabled.
+ * @param mode Control mode to ultimately enter once user calls Set().
+ * @see Set()
+ */
+void CANTalon::ApplyControlMode(CANSpeedController::ControlMode mode)
+{
+  m_controlMode = mode;
+  switch (mode) {
+    case kPercentVbus:
+      m_sendMode = kThrottle;
+      break;
+    case kCurrent:
+      m_sendMode = kCurrentMode;
+      break;
+    case kSpeed:
+      m_sendMode = kSpeedMode;
+      break;
+    case kPosition:
+      m_sendMode = kPositionMode;
+      break;
+    case kVoltage:
+      m_sendMode = kVoltageMode;
+      break;
+    case kFollower:
+      m_sendMode = kFollowerMode;
+      break;
+  }
+  // Keep the talon disabled until Set() is called.
+  CTR_Code status = m_impl->SetModeSelect((int)kDisabled);
+	if(status != CTR_OKAY) {
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+}
+/**
+ * TODO documentation (see CANJaguar.cpp)
+ */
+void CANTalon::SetControlMode(CANSpeedController::ControlMode mode)
+{
+  if(m_controlMode == mode){
+    /* we already are in this mode, don't perform disable workaround */
+  }else{
+    ApplyControlMode(mode);
+  }
+}
+
+/**
+ * TODO documentation (see CANJaguar.cpp)
+ */
+CANSpeedController::ControlMode CANTalon::GetControlMode()
+{
+  return m_controlMode;
+}
+
+void CANTalon::SetExpiration(float timeout)
+{
+	m_safetyHelper->SetExpiration(timeout);
+}
+
+float CANTalon::GetExpiration()
+{
+	return m_safetyHelper->GetExpiration();
+}
+
+bool CANTalon::IsAlive()
+{
+	return m_safetyHelper->IsAlive();
+}
+
+bool CANTalon::IsSafetyEnabled()
+{
+	return m_safetyHelper->IsSafetyEnabled();
+}
+
+void CANTalon::SetSafetyEnabled(bool enabled)
+{
+	m_safetyHelper->SetSafetyEnabled(enabled);
+}
+
+void CANTalon::GetDescription(char *desc)
+{
+	sprintf(desc, "CANTalon ID %d", m_deviceNumber);
+}
+
+/**
+ * Common interface for stopping the motor
+ * Part of the MotorSafety interface
+ *
+ * @deprecated Call Disable instead.
+*/
+void CANTalon::StopMotor()
+{
+  Disable();
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Compressor.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Compressor.cpp
new file mode 100644
index 0000000..430eab1
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Compressor.cpp
@@ -0,0 +1,261 @@
+/*
+ * Compressor.cpp
+ */
+
+#include "Compressor.h"
+#include "WPIErrors.h"
+
+void Compressor::InitCompressor(uint8_t pcmID) {
+	m_pcm_pointer = initializeCompressor(pcmID);
+
+	SetClosedLoopControl(true);
+}
+
+/**
+ * Constructor
+ *
+ * Uses the default PCM ID (0)
+ */
+Compressor::Compressor() {
+	InitCompressor(GetDefaultSolenoidModule());
+}
+
+/**
+ * Constructor
+ *
+ * @param module The PCM ID to use (0-62)
+ */
+Compressor::Compressor(uint8_t pcmID) {
+	InitCompressor(pcmID);
+}
+
+Compressor::~Compressor() {
+
+}
+
+/**
+ *  Starts closed-loop control. Note that closed loop control is enabled by default.
+ */
+void Compressor::Start() {
+	SetClosedLoopControl(true);
+}
+
+/**
+ *  Stops closed-loop control. Note that closed loop control is enabled by default.
+ */
+void Compressor::Stop() {
+	SetClosedLoopControl(false);
+}
+
+/**
+ * Check if compressor output is active
+ * @return true if the compressor is on
+ */
+bool Compressor::Enabled() {
+	int32_t status = 0;
+	bool value;
+
+	value = getCompressor(m_pcm_pointer, &status);
+
+	if(status) {
+		wpi_setWPIError(Timeout);
+	}
+
+	return value;
+}
+
+/**
+ * Check if the pressure switch is triggered
+ * @return true if pressure is low
+ */
+bool Compressor::GetPressureSwitchValue() {
+	int32_t status = 0;
+	bool value;
+
+	value = getPressureSwitch(m_pcm_pointer, &status);
+
+	if(status) {
+		wpi_setWPIError(Timeout);
+	}
+
+	return value;
+}
+
+
+/**
+ * Query how much current the compressor is drawing
+ * @return The current through the compressor, in amps
+ */
+float Compressor::GetCompressorCurrent() {
+	int32_t status = 0;
+	float value;
+
+	value = getCompressorCurrent(m_pcm_pointer, &status);
+
+	if(status) {
+		wpi_setWPIError(Timeout);
+	}
+
+	return value;
+}
+
+
+/**
+ * Enables or disables automatically turning the compressor on when the
+ * pressure is low.
+ * @param on Set to true to enable closed loop control of the compressor. False to disable.
+ */
+void Compressor::SetClosedLoopControl(bool on) {
+	int32_t status = 0;
+
+	setClosedLoopControl(m_pcm_pointer, on, &status);
+
+	if(status) {
+		wpi_setWPIError(Timeout);
+	}
+}
+
+/**
+ * Returns true if the compressor will automatically turn on when the
+ * pressure is low.
+ * @return True if closed loop control of the compressor is enabled. False if disabled.
+ */
+bool Compressor::GetClosedLoopControl() {
+	int32_t status = 0;
+	bool value;
+
+	value = getClosedLoopControl(m_pcm_pointer, &status);
+
+	if(status) {
+		wpi_setWPIError(Timeout);
+	}
+
+	return value;
+}
+
+/**
+ * Query if the compressor output has been disabled due to high current draw.
+ * @return true if PCM is in fault state : Compressor Drive is 
+ *			disabled due to compressor current being too high.
+ */
+bool Compressor::GetCompressorCurrentTooHighFault() {
+	int32_t status = 0;
+	bool value;
+
+	value = getCompressorCurrentTooHighFault(m_pcm_pointer, &status);
+
+	if(status) {
+		wpi_setWPIError(Timeout);
+	}
+
+	return value;
+}
+/**
+ * Query if the compressor output has been disabled due to high current draw (sticky).
+ * A sticky fault will not clear on device reboot, it must be cleared through code or the webdash.
+ * @return true if PCM sticky fault is set : Compressor Drive is 
+ *			disabled due to compressor current being too high.
+ */
+bool Compressor::GetCompressorCurrentTooHighStickyFault() {
+	int32_t status = 0;
+	bool value;
+
+	value = getCompressorCurrentTooHighStickyFault(m_pcm_pointer, &status);
+
+	if(status) {
+		wpi_setWPIError(Timeout);
+	}
+
+	return value;
+}
+/**
+ * Query if the compressor output has been disabled due to a short circuit (sticky).
+ * A sticky fault will not clear on device reboot, it must be cleared through code or the webdash.
+ * @return true if PCM sticky fault is set : Compressor output 
+ *			appears to be shorted.
+ */
+bool Compressor::GetCompressorShortedStickyFault() {
+	int32_t status = 0;
+	bool value;
+
+	value = getCompressorShortedStickyFault(m_pcm_pointer, &status);
+
+	if(status) {
+		wpi_setWPIError(Timeout);
+	}
+
+	return value;
+}
+/**
+ * Query if the compressor output has been disabled due to a short circuit.
+ * @return true if PCM is in fault state : Compressor output 
+ *			appears to be shorted.
+ */
+bool Compressor::GetCompressorShortedFault() {
+	int32_t status = 0;
+	bool value;
+
+	value = getCompressorShortedFault(m_pcm_pointer, &status);
+
+	if(status) {
+		wpi_setWPIError(Timeout);
+	}
+
+	return value;
+}
+/**
+ * Query if the compressor output does not appear to be wired (sticky).
+ * A sticky fault will not clear on device reboot, it must be cleared through code or the webdash.
+ * @return true if PCM sticky fault is set : Compressor does not 
+ *			appear to be wired, i.e. compressor is
+ * 			not drawing enough current.
+ */
+bool Compressor::GetCompressorNotConnectedStickyFault() {
+	int32_t status = 0;
+	bool value;
+
+	value = getCompressorNotConnectedStickyFault(m_pcm_pointer, &status);
+
+	if(status) {
+		wpi_setWPIError(Timeout);
+	}
+
+	return value;
+}
+/**
+ * Query if the compressor output does not appear to be wired.
+ * @return true if PCM is in fault state : Compressor does not 
+ *			appear to be wired, i.e. compressor is
+ * 			not drawing enough current.
+ */
+bool Compressor::GetCompressorNotConnectedFault() {
+	int32_t status = 0;
+	bool value;
+
+	value = getCompressorNotConnectedFault(m_pcm_pointer, &status);
+
+	if(status) {
+		wpi_setWPIError(Timeout);
+	}
+
+	return value;
+}
+/**
+ * Clear ALL sticky faults inside PCM that Compressor is wired to.
+ *
+ * If a sticky fault is set, then it will be persistently cleared.  Compressor drive
+ *		maybe momentarily disable while flags are being cleared. Care should be 
+ *		taken to not call this too frequently, otherwise normal compressor 
+ *		functionality may be prevented.
+ *
+ * If no sticky faults are set then this call will have no effect.
+ */
+void Compressor::ClearAllPCMStickyFaults() {
+	int32_t status = 0;
+
+	clearAllPCMStickyFaults(m_pcm_pointer, &status);
+
+	if(status) {
+		wpi_setWPIError(Timeout);
+	}
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/ControllerPower.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/ControllerPower.cpp
new file mode 100644
index 0000000..157929b
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/ControllerPower.cpp
@@ -0,0 +1,170 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2011. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "ControllerPower.h"
+
+#include <stdint.h>
+#include <HAL/Power.hpp>
+#include <HAL/HAL.hpp>
+#include "ErrorBase.h"
+
+/**
+ * Get the input voltage to the robot controller
+ * @return The controller input voltage value in Volts
+ */
+double ControllerPower::GetInputVoltage() {
+	int32_t status = 0;
+	double retVal = getVinVoltage(&status);
+	wpi_setGlobalErrorWithContext(status, getHALErrorMessage(status));
+	return retVal;
+}
+
+/**
+ * Get the input current to the robot controller
+ * @return The controller input current value in Amps
+ */
+double ControllerPower::GetInputCurrent() {
+	int32_t status = 0;
+	double retVal = getVinCurrent(&status);
+	wpi_setGlobalErrorWithContext(status, getHALErrorMessage(status));
+	return retVal;
+}
+
+/**
+ * Get the voltage of the 6V rail
+ * @return The controller 6V rail voltage value in Volts
+ */
+double ControllerPower::GetVoltage6V() {
+	int32_t status = 0;
+	double retVal = getUserVoltage6V(&status);
+	wpi_setGlobalErrorWithContext(status, getHALErrorMessage(status));
+	return retVal;
+}
+
+/**
+ * Get the current output of the 6V rail
+ * @return The controller 6V rail output current value in Amps
+ */
+double ControllerPower::GetCurrent6V() {
+	int32_t status = 0;
+	double retVal = getUserCurrent6V(&status);
+	wpi_setGlobalErrorWithContext(status, getHALErrorMessage(status));
+	return retVal;
+}
+
+/**
+ * Get the enabled state of the 6V rail. The rail may be disabled due to a controller
+ * brownout, a short circuit on the rail, or controller over-voltage
+ * @return The controller 6V rail enabled value. True for enabled.
+ */
+bool ControllerPower::GetEnabled6V() {
+	int32_t status = 0;
+	bool retVal = getUserActive6V(&status);
+	wpi_setGlobalErrorWithContext(status, getHALErrorMessage(status));
+	return retVal;
+}
+
+/**
+ * Get the count of the total current faults on the 6V rail since the controller has booted
+ * @return The number of faults.
+ */
+int ControllerPower::GetFaultCount6V() {
+	int32_t status = 0;
+	int retVal = getUserCurrentFaults6V(&status);
+	wpi_setGlobalErrorWithContext(status, getHALErrorMessage(status));
+	return retVal;
+}
+
+/**
+ * Get the voltage of the 5V rail
+ * @return The controller 5V rail voltage value in Volts
+ */
+double ControllerPower::GetVoltage5V() {
+	int32_t status = 0;
+	double retVal = getUserVoltage5V(&status);
+	wpi_setGlobalErrorWithContext(status, getHALErrorMessage(status));
+	return retVal;
+}
+
+/**
+ * Get the current output of the 5V rail
+ * @return The controller 5V rail output current value in Amps
+ */
+double ControllerPower::GetCurrent5V() {
+	int32_t status = 0;
+	double retVal = getUserCurrent5V(&status);
+	wpi_setGlobalErrorWithContext(status, getHALErrorMessage(status));
+	return retVal;
+}
+
+/**
+ * Get the enabled state of the 5V rail. The rail may be disabled due to a controller
+ * brownout, a short circuit on the rail, or controller over-voltage
+ * @return The controller 5V rail enabled value. True for enabled.
+ */
+bool ControllerPower::GetEnabled5V() {
+	int32_t status = 0;
+	bool retVal = getUserActive5V(&status);
+	wpi_setGlobalErrorWithContext(status, getHALErrorMessage(status));
+	return retVal;
+}
+
+/**
+ * Get the count of the total current faults on the 5V rail since the controller has booted
+ * @return The number of faults
+ */
+int ControllerPower::GetFaultCount5V() {
+	int32_t status = 0;
+	int retVal = getUserCurrentFaults5V(&status);
+	wpi_setGlobalErrorWithContext(status, getHALErrorMessage(status));
+	return retVal;
+}
+
+/**
+ * Get the voltage of the 3.3V rail
+ * @return The controller 3.3V rail voltage value in Volts
+ */
+double ControllerPower::GetVoltage3V3() {
+	int32_t status = 0;
+	double retVal = getUserVoltage3V3(&status);
+	wpi_setGlobalErrorWithContext(status, getHALErrorMessage(status));
+	return retVal;
+}
+
+/**
+ * Get the current output of the 3.3V rail
+ * @return The controller 3.3V rail output current value in Amps
+ */
+double ControllerPower::GetCurrent3V3() {
+	int32_t status = 0;
+	double retVal = getUserCurrent3V3(&status);
+	wpi_setGlobalErrorWithContext(status, getHALErrorMessage(status));
+	return retVal;
+}
+
+
+/**
+ * Get the enabled state of the 3.3V rail. The rail may be disabled due to a controller
+ * brownout, a short circuit on the rail, or controller over-voltage
+ * @return The controller 3.3V rail enabled value. True for enabled.
+ */
+bool ControllerPower::GetEnabled3V3() {
+	int32_t status = 0;
+	bool retVal = getUserActive3V3(&status);
+	wpi_setGlobalErrorWithContext(status, getHALErrorMessage(status));
+	return retVal;
+}
+
+/**
+ * Get the count of the total current faults on the 3.3V rail since the controller has booted
+ * @return The number of faults
+ */
+int ControllerPower::GetFaultCount3V3() {
+	int32_t status = 0;
+	int retVal = getUserCurrentFaults3V3(&status);
+	wpi_setGlobalErrorWithContext(status, getHALErrorMessage(status));
+	return retVal;
+}
\ No newline at end of file
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Counter.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Counter.cpp
new file mode 100644
index 0000000..964b774
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Counter.cpp
@@ -0,0 +1,619 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "Counter.h"
+#include "AnalogTrigger.h"
+#include "DigitalInput.h"
+//#include "NetworkCommunication/UsageReporting.h"
+#include "Resource.h"
+#include "WPIErrors.h"
+
+/**
+ * Create an instance of a counter object.
+ * This creates a ChipObject counter and initializes status variables appropriately
+ *
+ * The counter will start counting immediately.
+ * @param mode The counter mode
+ */
+void Counter::InitCounter(Mode mode)
+{
+	int32_t status = 0;
+	m_index = 0;
+	m_counter = initializeCounter(mode, &m_index, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+	m_upSource = NULL;
+	m_downSource = NULL;
+	m_allocatedUpSource = false;
+	m_allocatedDownSource = false;
+
+	SetMaxPeriod(.5);
+
+	HALReport(HALUsageReporting::kResourceType_Counter, m_index, mode);
+}
+
+/**
+ * Create an instance of a counter where no sources are selected.
+ * They all must be selected by calling functions to specify the upsource and the downsource
+ * independently.
+ *
+ * The counter will start counting immediately.
+ */
+Counter::Counter() :
+	m_upSource(NULL),
+	m_downSource(NULL),
+	m_counter(NULL)
+{
+	InitCounter();
+}
+
+/**
+ * Create an instance of a counter from a Digital Source (such as a Digital Input).
+ * This is used if an existing digital input is to be shared by multiple other objects such
+ * as encoders or if the Digital Source is not a Digital Input channel (such as an Analog Trigger).
+ *
+ * The counter will start counting immediately.
+ * @param source A pointer to the existing DigitalSource object. It will be set as the Up Source.
+ */
+Counter::Counter(DigitalSource *source) :
+	m_upSource(NULL),
+	m_downSource(NULL),
+	m_counter(NULL)
+{
+	InitCounter();
+	SetUpSource(source);
+	ClearDownSource();
+}
+
+/**
+ * Create an instance of a counter from a Digital Source (such as a Digital Input).
+ * This is used if an existing digital input is to be shared by multiple other objects such
+ * as encoders or if the Digital Source is not a Digital Input channel (such as an Analog Trigger).
+ *
+ * The counter will start counting immediately.
+ * @param source A reference to the existing DigitalSource object. It will be set as the Up Source.
+ */
+Counter::Counter(DigitalSource &source) :
+	m_upSource(NULL),
+	m_downSource(NULL),
+	m_counter(NULL)
+{
+	InitCounter();
+	SetUpSource(&source);
+	ClearDownSource();
+}
+
+/**
+ * Create an instance of a Counter object.
+ * Create an up-Counter instance given a channel.
+ *
+ * The counter will start counting immediately.
+ * @param channel The DIO channel to use as the up source. 0-9 are on-board, 10-25 are on the MXP 
+ */
+Counter::Counter(int32_t channel) :
+	m_upSource(NULL),
+	m_downSource(NULL),
+	m_counter(NULL)
+{
+	InitCounter();
+	SetUpSource(channel);
+	ClearDownSource();
+}
+
+/**
+ * Create an instance of a Counter object.
+ * Create an instance of a simple up-Counter given an analog trigger.
+ * Use the trigger state output from the analog trigger.
+ *
+ * The counter will start counting immediately.
+ * @param trigger The pointer to the existing AnalogTrigger object.
+ */
+Counter::Counter(AnalogTrigger *trigger) :
+	m_upSource(NULL),
+	m_downSource(NULL),
+	m_counter(NULL)
+{
+	InitCounter();
+	SetUpSource(trigger->CreateOutput(kState));
+	ClearDownSource();
+	m_allocatedUpSource = true;
+}
+
+/**
+ * Create an instance of a Counter object.
+ * Create an instance of a simple up-Counter given an analog trigger.
+ * Use the trigger state output from the analog trigger.
+ *
+ * The counter will start counting immediately.
+ * @param trigger The reference to the existing AnalogTrigger object.
+ */
+Counter::Counter(AnalogTrigger &trigger) :
+	m_upSource(NULL),
+	m_downSource(NULL),
+	m_counter(NULL)
+{
+	InitCounter();
+	SetUpSource(trigger.CreateOutput(kState));
+	ClearDownSource();
+	m_allocatedUpSource = true;
+}
+
+/**
+ * Create an instance of a Counter object.
+ * Creates a full up-down counter given two Digital Sources
+ * @param encodingType The quadrature decoding mode (1x or 2x)
+ * @param upSource The pointer to the DigitalSource to set as the up source
+ * @param downSource The pointer to the DigitalSource to set as the down source
+ * @param inverted True to invert the output (reverse the direction)
+ */
+	
+Counter::Counter(EncodingType encodingType, DigitalSource *upSource, DigitalSource *downSource, bool inverted) :
+	m_upSource(NULL),
+	m_downSource(NULL),
+	m_counter(NULL)
+{
+	if (encodingType != k1X && encodingType != k2X)
+	{
+		wpi_setWPIErrorWithContext(ParameterOutOfRange, "Counter only supports 1X and 2X quadrature decoding.");
+		return;
+	}
+	InitCounter(kExternalDirection);
+	SetUpSource(upSource);
+	SetDownSource(downSource);
+	int32_t status = 0;
+
+	if (encodingType == k1X)
+	{
+		SetUpSourceEdge(true, false);
+		setCounterAverageSize(m_counter, 1, &status);
+	}
+	else
+	{
+		SetUpSourceEdge(true, true);
+		setCounterAverageSize(m_counter, 2, &status);
+	}
+
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	SetDownSourceEdge(inverted, true);
+}
+
+/**
+ * Delete the Counter object.
+ */
+Counter::~Counter()
+{
+	SetUpdateWhenEmpty(true);
+	if (m_allocatedUpSource)
+	{
+		delete m_upSource;
+		m_upSource = NULL;
+	}
+	if (m_allocatedDownSource)
+	{
+		delete m_downSource;
+		m_downSource = NULL;
+	}
+
+	int32_t status = 0;
+	freeCounter(m_counter, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	m_counter = NULL;
+}
+
+/**
+ * Set the upsource for the counter as a digital input channel.
+ * @param channel The DIO channel to use as the up source. 0-9 are on-board, 10-25 are on the MXP 
+ */
+void Counter::SetUpSource(int32_t channel)
+{
+    if (StatusIsFatal()) return;
+    SetUpSource(new DigitalInput(channel));
+    m_allocatedUpSource = true;
+}
+
+/**
+ * Set the up counting source to be an analog trigger.
+ * @param analogTrigger The analog trigger object that is used for the Up Source
+ * @param triggerType The analog trigger output that will trigger the counter.
+ */
+void Counter::SetUpSource(AnalogTrigger *analogTrigger, AnalogTriggerType triggerType)
+{
+	if (StatusIsFatal()) return;
+	SetUpSource(analogTrigger->CreateOutput(triggerType));
+	m_allocatedUpSource = true;
+}
+
+/**
+ * Set the up counting source to be an analog trigger.
+ * @param analogTrigger The analog trigger object that is used for the Up Source
+ * @param triggerType The analog trigger output that will trigger the counter.
+ */
+void Counter::SetUpSource(AnalogTrigger &analogTrigger, AnalogTriggerType triggerType)
+{
+	SetUpSource(&analogTrigger, triggerType);
+}
+
+/**
+ * Set the source object that causes the counter to count up.
+ * Set the up counting DigitalSource.
+ * @param source Pointer to the DigitalSource object to set as the up source
+ */
+void Counter::SetUpSource(DigitalSource *source)
+{
+	if (StatusIsFatal()) return;
+	if (m_allocatedUpSource)
+	{
+		delete m_upSource;
+		m_upSource = NULL;
+		m_allocatedUpSource = false;
+	}
+	m_upSource = source;
+	if (m_upSource->StatusIsFatal())
+	{
+		CloneError(m_upSource);
+	}
+	else
+	{
+		int32_t status = 0;
+		setCounterUpSource(m_counter, source->GetChannelForRouting(),
+		                   source->GetAnalogTriggerForRouting(), &status);
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+}
+
+/**
+ * Set the source object that causes the counter to count up.
+ * Set the up counting DigitalSource.
+ * @param source Reference to the DigitalSource object to set as the up source
+ */
+void Counter::SetUpSource(DigitalSource &source)
+{
+	SetUpSource(&source);
+}
+
+/**
+ * Set the edge sensitivity on an up counting source.
+ * Set the up source to either detect rising edges or falling edges or both.
+ * @param risingEdge True to trigger on rising edges
+ * @param fallingEdge True to trigger on falling edges
+ */
+void Counter::SetUpSourceEdge(bool risingEdge, bool fallingEdge)
+{
+	if (StatusIsFatal()) return;
+	if (m_upSource == NULL)
+	{
+		wpi_setWPIErrorWithContext(NullParameter, "Must set non-NULL UpSource before setting UpSourceEdge");
+	}
+	int32_t status = 0;
+	setCounterUpSourceEdge(m_counter, risingEdge, fallingEdge, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Disable the up counting source to the counter.
+ */
+void Counter::ClearUpSource()
+{
+	if (StatusIsFatal()) return;
+	if (m_allocatedUpSource)
+	{
+		delete m_upSource;
+		m_upSource = NULL;
+		m_allocatedUpSource = false;
+	}
+	int32_t status = 0;
+	clearCounterUpSource(m_counter, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Set the down counting source to be a digital input channel.
+ * @param channel The DIO channel to use as the up source. 0-9 are on-board, 10-25 are on the MXP 
+ */
+void Counter::SetDownSource(int32_t channel)
+{
+	if (StatusIsFatal()) return;
+	SetDownSource(new DigitalInput(channel));
+	m_allocatedDownSource = true;
+}
+
+/**
+ * Set the down counting source to be an analog trigger.
+ * @param analogTrigger The analog trigger object that is used for the Down Source
+ * @param triggerType The analog trigger output that will trigger the counter.
+ */
+void Counter::SetDownSource(AnalogTrigger *analogTrigger, AnalogTriggerType triggerType)
+{
+	if (StatusIsFatal()) return;
+	SetDownSource(analogTrigger->CreateOutput(triggerType));
+	m_allocatedDownSource = true;
+}
+
+/**
+ * Set the down counting source to be an analog trigger.
+ * @param analogTrigger The analog trigger object that is used for the Down Source
+ * @param triggerType The analog trigger output that will trigger the counter.
+ */
+void Counter::SetDownSource(AnalogTrigger &analogTrigger, AnalogTriggerType triggerType)
+{
+	SetDownSource(&analogTrigger, triggerType);
+}
+
+/**
+ * Set the source object that causes the counter to count down.
+ * Set the down counting DigitalSource.
+ * @param source Pointer to the DigitalSource object to set as the down source
+ */
+void Counter::SetDownSource(DigitalSource *source)
+{
+	if (StatusIsFatal()) return;
+	if (m_allocatedDownSource)
+	{
+		delete m_downSource;
+		m_downSource = NULL;
+		m_allocatedDownSource = false;
+	}
+	m_downSource = source;
+	if (m_downSource->StatusIsFatal())
+	{
+		CloneError(m_downSource);
+	}
+	else
+	{
+		int32_t status = 0;
+		setCounterDownSource(m_counter, source->GetChannelForRouting(),
+		                     source->GetAnalogTriggerForRouting(), &status);
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+}
+
+/**
+ * Set the source object that causes the counter to count down.
+ * Set the down counting DigitalSource.
+ * @param source Reference to the DigitalSource object to set as the down source
+ */
+void Counter::SetDownSource(DigitalSource &source)
+{
+	SetDownSource(&source);
+}
+
+/**
+ * Set the edge sensitivity on a down counting source.
+ * Set the down source to either detect rising edges or falling edges.
+ * @param risingEdge True to trigger on rising edges
+ * @param fallingEdge True to trigger on falling edges
+ */
+void Counter::SetDownSourceEdge(bool risingEdge, bool fallingEdge)
+{
+	if (StatusIsFatal()) return;
+	if (m_downSource == NULL)
+	{
+		wpi_setWPIErrorWithContext(NullParameter, "Must set non-NULL DownSource before setting DownSourceEdge");
+	}
+	int32_t status = 0;
+	setCounterDownSourceEdge(m_counter, risingEdge, fallingEdge, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Disable the down counting source to the counter.
+ */
+void Counter::ClearDownSource()
+{
+	if (StatusIsFatal()) return;
+	if (m_allocatedDownSource)
+	{
+		delete m_downSource;
+		m_downSource = NULL;
+		m_allocatedDownSource = false;
+	}
+	int32_t status = 0;
+	clearCounterDownSource(m_counter, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Set standard up / down counting mode on this counter.
+ * Up and down counts are sourced independently from two inputs.
+ */
+void Counter::SetUpDownCounterMode()
+{
+	if (StatusIsFatal()) return;
+	int32_t status = 0;
+	setCounterUpDownMode(m_counter, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Set external direction mode on this counter.
+ * Counts are sourced on the Up counter input.
+ * The Down counter input represents the direction to count.
+ */
+void Counter::SetExternalDirectionMode()
+{
+	if (StatusIsFatal()) return;
+	int32_t status = 0;
+	setCounterExternalDirectionMode(m_counter, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Set Semi-period mode on this counter.
+ * Counts up on both rising and falling edges.
+ */
+void Counter::SetSemiPeriodMode(bool highSemiPeriod)
+{
+	if (StatusIsFatal()) return;
+	int32_t status = 0;
+	setCounterSemiPeriodMode(m_counter, highSemiPeriod, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Configure the counter to count in up or down based on the length of the input pulse.
+ * This mode is most useful for direction sensitive gear tooth sensors.
+ * @param threshold The pulse length beyond which the counter counts the opposite direction.  Units are seconds.
+ */
+void Counter::SetPulseLengthMode(float threshold)
+{
+	if (StatusIsFatal()) return;
+	int32_t status = 0;
+	setCounterPulseLengthMode(m_counter, threshold, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+
+/**
+ * Get the Samples to Average which specifies the number of samples of the timer to
+ * average when calculating the period. Perform averaging to account for
+ * mechanical imperfections or as oversampling to increase resolution.
+ * @return SamplesToAverage The number of samples being averaged (from 1 to 127)
+ */
+int Counter::GetSamplesToAverage()
+{
+	int32_t status = 0;
+	int32_t samples = getCounterSamplesToAverage(m_counter, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	return samples;
+}
+
+/**
+ * Set the Samples to Average which specifies the number of samples of the timer to
+ * average when calculating the period. Perform averaging to account for
+ * mechanical imperfections or as oversampling to increase resolution.
+ * @param samplesToAverage The number of samples to average from 1 to 127.
+ */
+void Counter::SetSamplesToAverage (int samplesToAverage) {
+	if (samplesToAverage < 1 || samplesToAverage > 127)
+	{
+		wpi_setWPIErrorWithContext(ParameterOutOfRange, "Average counter values must be between 1 and 127");
+	}
+	int32_t status = 0;
+	setCounterSamplesToAverage(m_counter, samplesToAverage, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Read the current counter value.
+ * Read the value at this instant. It may still be running, so it reflects the current value. Next
+ * time it is read, it might have a different value.
+ */
+int32_t Counter::Get()
+{
+	if (StatusIsFatal()) return 0;
+	int32_t status = 0;
+	int32_t value = getCounter(m_counter, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	return value;
+}
+
+/**
+ * Reset the Counter to zero.
+ * Set the counter value to zero. This doesn't effect the running state of the counter, just sets
+ * the current value to zero.
+ */
+void Counter::Reset()
+{
+	if (StatusIsFatal()) return;
+	int32_t status = 0;
+	resetCounter(m_counter, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Get the Period of the most recent count.
+ * Returns the time interval of the most recent count. This can be used for velocity calculations
+ * to determine shaft speed.
+ * @returns The period between the last two pulses in units of seconds.
+ */
+double Counter::GetPeriod()
+{
+	if (StatusIsFatal()) return 0.0;
+	int32_t status = 0;
+	double value = getCounterPeriod(m_counter, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	return value;
+}
+
+/**
+ * Set the maximum period where the device is still considered "moving".
+ * Sets the maximum period where the device is considered moving. This value is used to determine
+ * the "stopped" state of the counter using the GetStopped method.
+ * @param maxPeriod The maximum period where the counted device is considered moving in
+ * seconds.
+ */
+void Counter::SetMaxPeriod(double maxPeriod)
+{
+	if (StatusIsFatal()) return;
+	int32_t status = 0;
+	setCounterMaxPeriod(m_counter, maxPeriod, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Select whether you want to continue updating the event timer output when there are no samples captured.
+ * The output of the event timer has a buffer of periods that are averaged and posted to
+ * a register on the FPGA.  When the timer detects that the event source has stopped
+ * (based on the MaxPeriod) the buffer of samples to be averaged is emptied.  If you
+ * enable the update when empty, you will be notified of the stopped source and the event
+ * time will report 0 samples.  If you disable update when empty, the most recent average
+ * will remain on the output until a new sample is acquired.  You will never see 0 samples
+ * output (except when there have been no events since an FPGA reset) and you will likely not
+ * see the stopped bit become true (since it is updated at the end of an average and there are
+ * no samples to average).
+ * @param enabled True to enable update when empty
+ */
+void Counter::SetUpdateWhenEmpty(bool enabled)
+{
+	if (StatusIsFatal()) return;
+	int32_t status = 0;
+	setCounterUpdateWhenEmpty(m_counter, enabled, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Determine if the clock is stopped.
+ * Determine if the clocked input is stopped based on the MaxPeriod value set using the
+ * SetMaxPeriod method. If the clock exceeds the MaxPeriod, then the device (and counter) are
+ * assumed to be stopped and it returns true.
+ * @return Returns true if the most recent counter period exceeds the MaxPeriod value set by
+ * SetMaxPeriod.
+ */
+bool Counter::GetStopped()
+{
+	if (StatusIsFatal()) return false;
+	int32_t status = 0;
+	bool value = getCounterStopped(m_counter, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	return value;
+}
+
+/**
+ * The last direction the counter value changed.
+ * @return The last direction the counter value changed.
+ */
+bool Counter::GetDirection()
+{
+	if (StatusIsFatal()) return false;
+	int32_t status = 0;
+	bool value = getCounterDirection(m_counter, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	return value;
+}
+
+/**
+ * Set the Counter to return reversed sensing on the direction.
+ * This allows counters to change the direction they are counting in the case of 1X and 2X
+ * quadrature encoding only. Any other counter mode isn't supported.
+ * @param reverseDirection true if the value counted should be negated.
+ */
+void Counter::SetReverseDirection(bool reverseDirection)
+{
+	if (StatusIsFatal()) return;
+	int32_t status = 0;
+	setCounterReverseDirection(m_counter, reverseDirection, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/DigitalInput.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/DigitalInput.cpp
new file mode 100644
index 0000000..4ce8e72
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/DigitalInput.cpp
@@ -0,0 +1,227 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include <algorithm>
+#include <array>
+
+#include "DigitalInput.h"
+//#include "NetworkCommunication/UsageReporting.h"
+#include "Resource.h"
+#include "WPIErrors.h"
+#include "Encoder.h"
+#include "Counter.h"
+
+::std::array<int, 3> DigitalGlitchFilter::filter_allocated_ = {
+    {false, false, false}};
+Mutex DigitalGlitchFilter::mutex_;
+
+/**
+ * Create an instance of a DigitalInput.
+ * Creates a digital input given a channel. Common creation routine for all
+ * constructors.
+ */
+void DigitalInput::InitDigitalInput(uint32_t channel)
+{
+	char buf[64];
+
+	if (!CheckDigitalChannel(channel))
+	{
+		snprintf(buf, 64, "Digital Channel %d", channel);
+		wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf);
+		return;
+	}
+	m_channel = channel;
+
+	int32_t status = 0;
+	allocateDIO(m_digital_ports[channel], true, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+	HALReport(HALUsageReporting::kResourceType_DigitalInput, channel);
+}
+
+/**
+ * Create an instance of a Digital Input class.
+ * Creates a digital input given a channel.
+ *
+ * @param channel The DIO channel 0-9 are on-board, 10-25 are on the MXP port
+ */
+DigitalInput::DigitalInput(uint32_t channel)
+{
+	InitDigitalInput(channel);
+}
+
+/**
+ * Free resources associated with the Digital Input class.
+ */
+DigitalInput::~DigitalInput()
+{
+	if (StatusIsFatal()) return;
+	if (m_interrupt != NULL)
+	{
+		int32_t status = 0;
+		cleanInterrupts(m_interrupt, &status);
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+		m_interrupt = NULL;
+		m_interrupts->Free(m_interruptIndex);
+	}
+
+	int32_t status = 0;
+	freeDIO(m_digital_ports[m_channel], &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Get the value from a digital input channel.
+ * Retrieve the value of a single digital input channel from the FPGA.
+ */
+bool DigitalInput::Get()
+{
+	int32_t status = 0;
+	bool value = getDIO(m_digital_ports[m_channel], &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	return value;
+}
+
+/**
+ * @return The GPIO channel number that this object represents.
+ */
+uint32_t DigitalInput::GetChannel()
+{
+	return m_channel;
+}
+
+/**
+ * @return The value to be written to the channel field of a routing mux.
+ */
+uint32_t DigitalInput::GetChannelForRouting()
+{
+	return GetChannel();
+}
+
+/**
+ * @return The value to be written to the module field of a routing mux.
+ */
+uint32_t DigitalInput::GetModuleForRouting()
+{
+	return 0;
+}
+
+/**
+ * @return The value to be written to the analog trigger field of a routing mux.
+ */
+bool DigitalInput::GetAnalogTriggerForRouting()
+{
+	return false;
+}
+
+DigitalGlitchFilter::DigitalGlitchFilter() : channel_index_(-1) {
+  ::std::unique_lock<Mutex> sync(DigitalGlitchFilter::mutex_);
+  auto index =
+      ::std::find(filter_allocated_.begin(), filter_allocated_.end(), false);
+  if (index != filter_allocated_.end()) {
+    channel_index_ = index - filter_allocated_.begin();
+    *index = true;
+  }
+}
+
+DigitalGlitchFilter::~DigitalGlitchFilter() {
+  ::std::unique_lock<Mutex> sync(DigitalGlitchFilter::mutex_);
+  filter_allocated_[channel_index_] = false;
+}
+
+void DigitalGlitchFilter::Add(DigitalSource *input) {
+  int32_t status = 0;
+  setFilterSelect(input->m_digital_ports[input->GetChannelForRouting()],
+                  channel_index_ + 1, &status);
+  wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+  HALReport(HALUsageReporting::kResourceType_DigitalInput,
+            input->GetChannelForRouting());
+}
+
+void DigitalGlitchFilter::Remove(DigitalSource *input) {
+	int32_t status = 0;
+	setFilterSelect(input->m_digital_ports[input->GetChannelForRouting()], 0, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+	HALReport(HALUsageReporting::kResourceType_DigitalInput, input->GetChannelForRouting());
+}
+
+void DigitalGlitchFilter::SetPeriodCycles(uint32_t fpga_cycles) {
+  int32_t status = 0;
+  setFilterPeriod(channel_index_, fpga_cycles, &status);
+  wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+  HALReport(HALUsageReporting::kResourceType_DigitalGlitchFilter,
+            channel_index_);
+}
+
+void DigitalGlitchFilter::SetPeriodNanoSeconds(uint64_t nanoseconds) {
+  int32_t status = 0;
+  uint32_t fpga_cycles =
+      nanoseconds * kSystemClockTicksPerMicrosecond / 4 / 1000;
+  setFilterPeriod(channel_index_, fpga_cycles, &status);
+
+  wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+  HALReport(HALUsageReporting::kResourceType_DigitalGlitchFilter,
+            channel_index_);
+}
+
+uint32_t DigitalGlitchFilter::GetPeriodCycles() {
+  int32_t status = 0;
+  uint32_t fpga_cycles = getFilterPeriod(channel_index_, &status);
+
+  wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+  HALReport(HALUsageReporting::kResourceType_DigitalGlitchFilter,
+            channel_index_);
+  return fpga_cycles;
+}
+
+uint64_t DigitalGlitchFilter::GetPeriodNanoSeconds() {
+  int32_t status = 0;
+  uint32_t fpga_cycles = getFilterPeriod(channel_index_, &status);
+
+  wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+  HALReport(HALUsageReporting::kResourceType_DigitalGlitchFilter,
+            channel_index_);
+  return static_cast<uint64_t>(fpga_cycles) * 1000l /
+         static_cast<uint64_t>(kSystemClockTicksPerMicrosecond / 4);
+}
+
+void DigitalGlitchFilter::Add(Encoder *input) {
+  Add(input->m_aSource);
+  if (StatusIsFatal()) {
+    return;
+  }
+  Add(input->m_bSource);
+}
+
+void DigitalGlitchFilter::Add(Counter *input) {
+  Add(input->m_upSource);
+  if (StatusIsFatal()) {
+    return;
+  }
+  Add(input->m_downSource);
+}
+
+void DigitalGlitchFilter::Remove(Encoder *input) {
+  Remove(input->m_aSource);
+  if (StatusIsFatal()) {
+    return;
+  }
+  Remove(input->m_bSource);
+}
+
+void DigitalGlitchFilter::Remove(Counter *input) {
+  Remove(input->m_upSource);
+  if (StatusIsFatal()) {
+    return;
+  }
+  Remove(input->m_downSource);
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/DigitalOutput.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/DigitalOutput.cpp
new file mode 100644
index 0000000..aeeab8a
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/DigitalOutput.cpp
@@ -0,0 +1,235 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "DigitalOutput.h"
+//#include "NetworkCommunication/UsageReporting.h"
+#include "Resource.h"
+#include "WPIErrors.h"
+
+/**
+ * Create an instance of a DigitalOutput.
+ * Creates a digital output given a channel. Common creation routine for all
+ * constructors.
+ */
+void DigitalOutput::InitDigitalOutput(uint32_t channel)
+{
+	char buf[64];
+
+	if (!CheckDigitalChannel(channel))
+	{
+		snprintf(buf, 64, "Digital Channel %d", channel);
+		wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf);
+		return;
+	}
+	m_channel = channel;
+	m_pwmGenerator = (void *)~0ul;
+
+	int32_t status = 0;
+	allocateDIO(m_digital_ports[channel], false, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+	HALReport(HALUsageReporting::kResourceType_DigitalOutput, channel);
+}
+
+/**
+ * Create an instance of a digital output.
+ * Create a digital output given a channel.
+ *
+ * @param channel The digital channel 0-9 are on-board, 10-25 are on the MXP port
+ */
+DigitalOutput::DigitalOutput(uint32_t channel)
+{
+	InitDigitalOutput(channel);
+}
+
+/**
+ * Free the resources associated with a digital output.
+ */
+DigitalOutput::~DigitalOutput()
+{
+	if (StatusIsFatal()) return;
+	// Disable the PWM in case it was running.
+	DisablePWM();
+
+	int32_t status = 0;
+	freeDIO(m_digital_ports[m_channel], &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Set the value of a digital output.
+ * Set the value of a digital output to either one (true) or zero (false).
+ * @param value 1 (true) for high, 0 (false) for disabled
+ */
+void DigitalOutput::Set(uint32_t value)
+{
+	if (StatusIsFatal()) return;
+
+	int32_t status = 0;
+	setDIO(m_digital_ports[m_channel], value, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Get the value from a digital output channel.
+ * Retrieve the value of a single digital output channel from the FPGA.
+ */
+bool DigitalOutput::Get()
+{
+	int32_t status = 0;
+	bool value = getDIO(m_digital_ports[m_channel], &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	return value;
+}
+
+/**
+ * @return The GPIO channel number that this object represents.
+ */
+uint32_t DigitalOutput::GetChannel()
+{
+	return m_channel;
+}
+
+/**
+ * Output a single pulse on the digital output line.
+ * Send a single pulse on the digital output line where the pulse duration is specified in seconds.
+ * Maximum pulse length is 0.0016 seconds.
+ * @param length The pulselength in seconds
+ */
+void DigitalOutput::Pulse(float length)
+{
+	if (StatusIsFatal()) return;
+
+	int32_t status = 0;
+	pulse(m_digital_ports[m_channel], length, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Determine if the pulse is still going.
+ * Determine if a previously started pulse is still going.
+ */
+bool DigitalOutput::IsPulsing()
+{
+	if (StatusIsFatal()) return false;
+
+	int32_t status = 0;
+	bool value = isPulsing(m_digital_ports[m_channel], &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	return value;
+}
+
+/**
+ * Change the PWM frequency of the PWM output on a Digital Output line.
+ *
+ * The valid range is from 0.6 Hz to 19 kHz.  The frequency resolution is logarithmic.
+ *
+ * There is only one PWM frequency for all digital channels.
+ *
+ * @param rate The frequency to output all digital output PWM signals.
+ */
+void DigitalOutput::SetPWMRate(float rate)
+{
+	if (StatusIsFatal()) return;
+
+	int32_t status = 0;
+	setPWMRate(rate, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Enable a PWM Output on this line.
+ *
+ * Allocate one of the 6 DO PWM generator resources from this module.
+ *
+ * Supply the initial duty-cycle to output so as to avoid a glitch when first starting.
+ *
+ * The resolution of the duty cycle is 8-bit for low frequencies (1kHz or less)
+ * but is reduced the higher the frequency of the PWM signal is.
+ *
+ * @param initialDutyCycle The duty-cycle to start generating. [0..1]
+ */
+void DigitalOutput::EnablePWM(float initialDutyCycle)
+{
+	if(m_pwmGenerator != (void *)~0ul) return;
+
+	int32_t status = 0;
+
+	if(StatusIsFatal()) return;
+	m_pwmGenerator = allocatePWM(&status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+	if(StatusIsFatal()) return;
+	setPWMDutyCycle(m_pwmGenerator, initialDutyCycle, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+	if(StatusIsFatal()) return;
+	setPWMOutputChannel(m_pwmGenerator, m_channel, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Change this line from a PWM output back to a static Digital Output line.
+ *
+ * Free up one of the 6 DO PWM generator resources that were in use.
+ */
+void DigitalOutput::DisablePWM()
+{
+	if (StatusIsFatal()) return;
+	if(m_pwmGenerator == (void *)~0ul) return;
+
+	int32_t status = 0;
+
+	// Disable the output by routing to a dead bit.
+	setPWMOutputChannel(m_pwmGenerator, kDigitalChannels, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+	freePWM(m_pwmGenerator, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+	m_pwmGenerator = (void *)~0ul;
+}
+
+/**
+ * Change the duty-cycle that is being generated on the line.
+ *
+ * The resolution of the duty cycle is 8-bit for low frequencies (1kHz or less)
+ * but is reduced the higher the frequency of the PWM signal is.
+ *
+ * @param dutyCycle The duty-cycle to change to. [0..1]
+ */
+void DigitalOutput::UpdateDutyCycle(float dutyCycle)
+{
+	if (StatusIsFatal()) return;
+
+	int32_t status = 0;
+	setPWMDutyCycle(m_pwmGenerator, dutyCycle, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * @return The value to be written to the channel field of a routing mux.
+ */
+uint32_t DigitalOutput::GetChannelForRouting()
+{
+	return GetChannel();
+}
+
+/**
+ * @return The value to be written to the module field of a routing mux.
+ */
+uint32_t DigitalOutput::GetModuleForRouting()
+{
+	return 0;
+}
+
+/**
+ * @return The value to be written to the analog trigger field of a routing mux.
+ */
+bool DigitalOutput::GetAnalogTriggerForRouting()
+{
+	return false;
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/DigitalSource.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/DigitalSource.cpp
new file mode 100644
index 0000000..40cc75c
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/DigitalSource.cpp
@@ -0,0 +1,14 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "DigitalSource.h"
+
+/**
+ * DigitalSource destructor.
+ */
+DigitalSource::~DigitalSource()
+{
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/DoubleSolenoid.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/DoubleSolenoid.cpp
new file mode 100644
index 0000000..091bae4
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/DoubleSolenoid.cpp
@@ -0,0 +1,163 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "DoubleSolenoid.h"
+//#include "NetworkCommunication/UsageReporting.h"
+#include "WPIErrors.h"
+
+/**
+ * Common function to implement constructor behaviour.
+ */
+void DoubleSolenoid::InitSolenoid()
+{
+	char buf[64];
+	if (!CheckSolenoidModule(m_moduleNumber))
+	{
+		snprintf(buf, 64, "Solenoid Module %d", m_moduleNumber);
+		wpi_setWPIErrorWithContext(ModuleIndexOutOfRange, buf);
+		return;
+	}
+	if (!CheckSolenoidChannel(m_forwardChannel))
+	{
+		snprintf(buf, 64, "Solenoid Channel %d", m_forwardChannel);
+		wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf);
+		return;
+	}
+	if (!CheckSolenoidChannel(m_reverseChannel))
+	{
+		snprintf(buf, 64, "Solenoid Channel %d", m_reverseChannel);
+		wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf);
+		return;
+	}
+	Resource::CreateResourceObject(&m_allocated, solenoid_kNumDO7_0Elements * kSolenoidChannels);
+
+	snprintf(buf, 64, "Solenoid %d (Module: %d)", m_forwardChannel, m_moduleNumber);
+	if (m_allocated->Allocate(m_moduleNumber * kSolenoidChannels + m_forwardChannel, buf) == ~0ul)
+	{
+		CloneError(m_allocated);
+		return;
+	}
+
+	snprintf(buf, 64, "Solenoid %d (Module: %d)", m_reverseChannel, m_moduleNumber);
+	if (m_allocated->Allocate(m_moduleNumber * kSolenoidChannels + m_reverseChannel, buf) == ~0ul)
+	{
+		CloneError(m_allocated);
+		return;
+	}
+    
+	m_forwardMask = 1 << m_forwardChannel;
+	m_reverseMask = 1 << m_reverseChannel;
+	HALReport(HALUsageReporting::kResourceType_Solenoid, m_forwardChannel, m_moduleNumber);
+	HALReport(HALUsageReporting::kResourceType_Solenoid, m_reverseChannel, m_moduleNumber);
+}
+
+/**
+ * Constructor.
+ * Uses the default PCM ID of 0
+ * @param forwardChannel The forward channel number on the PCM (0..7).
+ * @param reverseChannel The reverse channel number on the PCM (0..7).
+ */
+DoubleSolenoid::DoubleSolenoid(uint32_t forwardChannel, uint32_t reverseChannel)
+	: SolenoidBase (GetDefaultSolenoidModule())
+	, m_forwardChannel (forwardChannel)
+	, m_reverseChannel (reverseChannel)
+{
+	InitSolenoid();
+}
+
+/**
+ * Constructor.
+ *
+ * @param moduleNumber The CAN ID of the PCM.
+ * @param forwardChannel The forward channel on the PCM to control (0..7).
+ * @param reverseChannel The reverse channel on the PCM to control (0..7).
+ */
+DoubleSolenoid::DoubleSolenoid(uint8_t moduleNumber, uint32_t forwardChannel, uint32_t reverseChannel)
+	: SolenoidBase (moduleNumber)
+	, m_forwardChannel (forwardChannel)
+	, m_reverseChannel (reverseChannel)
+{
+	InitSolenoid();
+}
+
+/**
+ * Destructor.
+ */
+DoubleSolenoid::~DoubleSolenoid()
+{
+	if (CheckSolenoidModule(m_moduleNumber))
+	{
+		m_allocated->Free(m_moduleNumber * kSolenoidChannels + m_forwardChannel);
+		m_allocated->Free(m_moduleNumber * kSolenoidChannels + m_reverseChannel);
+	}
+}
+
+/**
+ * Set the value of a solenoid.
+ *
+ * @param value The value to set (Off, Forward or Reverse)
+ */
+void DoubleSolenoid::Set(Value value)
+{
+	if (StatusIsFatal()) return;
+	uint8_t rawValue = 0x00;
+
+	switch(value)
+	{
+	case kOff:
+		rawValue = 0x00;
+		break;
+	case kForward:
+		rawValue = m_forwardMask;
+		break;
+	case kReverse:
+		rawValue = m_reverseMask;
+		break;
+	}
+
+	SolenoidBase::Set(rawValue, m_forwardMask | m_reverseMask);
+}
+
+/**
+ * Read the current value of the solenoid.
+ *
+ * @return The current value of the solenoid.
+ */
+DoubleSolenoid::Value DoubleSolenoid::Get()
+{
+	if (StatusIsFatal()) return kOff;
+	uint8_t value = GetAll();
+
+	if (value & m_forwardMask) return kForward;
+	if (value & m_reverseMask) return kReverse;
+	return kOff;
+}
+/**
+ * Check if the forward solenoid is blacklisted.
+ *		If a solenoid is shorted, it is added to the blacklist and
+ *		disabled until power cycle, or until faults are cleared.
+ *		@see ClearAllPCMStickyFaults()
+ *
+ * @return If solenoid is disabled due to short.
+ */
+bool DoubleSolenoid::IsFwdSolenoidBlackListed()
+{
+	int blackList = GetPCMSolenoidBlackList();
+	return (blackList & m_forwardMask) ? 1 : 0;
+}
+/**
+ * Check if the reverse solenoid is blacklisted.
+ *		If a solenoid is shorted, it is added to the blacklist and
+ *		disabled until power cycle, or until faults are cleared.
+ *		@see ClearAllPCMStickyFaults()
+ *
+ * @return If solenoid is disabled due to short.
+ */
+bool DoubleSolenoid::IsRevSolenoidBlackListed()
+{
+	int blackList = GetPCMSolenoidBlackList();
+	return (blackList & m_reverseMask) ? 1 : 0;
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/DriverStation.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/DriverStation.cpp
new file mode 100644
index 0000000..bcd3063
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/DriverStation.cpp
@@ -0,0 +1,534 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "DriverStation.h"
+#include "AnalogInput.h"
+#include "HAL/cpp/Synchronized.hpp"
+#include "Timer.h"
+#include "NetworkCommunication/FRCComm.h"
+#include "NetworkCommunication/UsageReporting.h"
+#include "MotorSafetyHelper.h"
+#include "Utility.h"
+#include "WPIErrors.h"
+#include <string.h>
+#include "Log.hpp"
+
+// set the logging level
+TLogLevel dsLogLevel = logDEBUG;
+const double JOYSTICK_UNPLUGGED_MESSAGE_INTERVAL = 1.0;
+
+#define DS_LOG(level) \
+	if (level > dsLogLevel) ; \
+	else Log().Get(level)
+
+const uint32_t DriverStation::kJoystickPorts;
+DriverStation* DriverStation::m_instance = NULL;
+
+/**
+ * DriverStation constructor.
+ *
+ * This is only called once the first time GetInstance() is called
+ */
+DriverStation::DriverStation()
+	: m_task ("DriverStation", (FUNCPTR)DriverStation::InitTask)
+	, m_newControlData(0)
+	, m_packetDataAvailableMultiWait(0)
+	, m_waitForDataSem(0)
+	, m_userInDisabled(false)
+	, m_userInAutonomous(false)
+	, m_userInTeleop(false)
+	, m_userInTest(false)
+	, m_nextMessageTime(0)
+{
+	// All joysticks should default to having zero axes, povs and buttons, so
+	// uninitialized memory doesn't get sent to speed controllers.
+	for(unsigned int i = 0; i < kJoystickPorts; i++) {
+		m_joystickAxes[i].count = 0;
+		m_joystickPOVs[i].count = 0;
+		m_joystickButtons[i].count = 0;
+	}
+	// Create a new semaphore
+	m_packetDataAvailableMultiWait = initializeMultiWait();
+	m_newControlData = initializeSemaphore(SEMAPHORE_EMPTY);
+
+	m_waitForDataSem = initializeMultiWait();
+	m_waitForDataMutex = initializeMutexNormal();
+
+	m_packetDataAvailableMultiWait = initializeMultiWait();
+	m_packetDataAvailableMutex = initializeMutexNormal();
+
+	// Register that semaphore with the network communications task.
+	// It will signal when new packet data is available.
+	HALSetNewDataSem(m_packetDataAvailableMultiWait);
+
+	AddToSingletonList();
+
+	if (!m_task.Start((int32_t)this))
+	{
+		wpi_setWPIError(DriverStationTaskError);
+	}
+}
+
+DriverStation::~DriverStation()
+{
+	m_task.Stop();
+	m_instance = NULL;
+	deleteMultiWait(m_waitForDataSem);
+	// Unregister our semaphore.
+	HALSetNewDataSem(NULL);
+	deleteMultiWait(m_packetDataAvailableMultiWait);
+	deleteMutex(m_packetDataAvailableMutex);
+	deleteMutex(m_waitForDataMutex);
+}
+
+void DriverStation::InitTask(DriverStation *ds)
+{
+	ds->Run();
+}
+
+void DriverStation::Run()
+{
+	int period = 0;
+	while (true)
+	{
+		takeMultiWait(m_packetDataAvailableMultiWait, m_packetDataAvailableMutex, 0);
+		GetData();
+		giveMultiWait(m_waitForDataSem);
+
+		if (++period >= 4)
+		{
+			MotorSafetyHelper::CheckMotors();
+			period = 0;
+		}
+		if (m_userInDisabled)
+			HALNetworkCommunicationObserveUserProgramDisabled();
+		if (m_userInAutonomous)
+			HALNetworkCommunicationObserveUserProgramAutonomous();
+		if (m_userInTeleop)
+			HALNetworkCommunicationObserveUserProgramTeleop();
+		if (m_userInTest)
+			HALNetworkCommunicationObserveUserProgramTest();
+	}
+}
+
+/**
+ * Return a pointer to the singleton DriverStation.
+ * @return Pointer to the DS instance
+ */
+DriverStation* DriverStation::GetInstance()
+{
+	if (m_instance == NULL)
+	{
+		m_instance = new DriverStation();
+	}
+	return m_instance;
+}
+
+/**
+ * Copy data from the DS task for the user.
+ * If no new data exists, it will just be returned, otherwise
+ * the data will be copied from the DS polling loop.
+ */
+void DriverStation::GetData()
+{
+
+	// Get the status of all of the joysticks
+	for(uint8_t stick = 0; stick < 4; stick++) {
+		HALGetJoystickAxes(stick, &m_joystickAxes[stick]);
+		HALGetJoystickButtons(stick, &m_joystickButtons[stick]);
+	  HALGetJoystickPOVs(stick, &m_joystickPOVs[stick]);
+	}
+	giveSemaphore(m_newControlData);
+}
+
+/**
+ * Read the battery voltage.
+ *
+ * @return The battery voltage in Volts.
+ */
+float DriverStation::GetBatteryVoltage()
+{
+	int32_t status = 0;
+	float voltage = getVinVoltage(&status);
+	wpi_setErrorWithContext(status, "getVinVoltage");
+
+	return voltage;
+}
+
+/**
+ * Reports errors related to unplugged joysticks
+ * Throttles the errors so that they don't overwhelm the DS
+ */
+void DriverStation::ReportJoystickUnpluggedError(std::string message) {
+	double currentTime = Timer::GetFPGATimestamp();
+	if (currentTime > m_nextMessageTime) {
+		ReportError(message);
+		m_nextMessageTime = currentTime + JOYSTICK_UNPLUGGED_MESSAGE_INTERVAL;
+	}
+}
+
+/**	
+ * Returns the number of axes on a given joystick port
+ *
+ * @param stick The joystick port number
+ * @return The number of axes on the indicated joystick
+ */
+int DriverStation::GetStickAxisCount(uint32_t stick)
+{
+    if (stick >= kJoystickPorts)
+    {
+        wpi_setWPIError(BadJoystickIndex);
+        return 0;
+    }
+   	HALJoystickAxes joystickAxes;
+   	HALGetJoystickAxes(stick, &joystickAxes);
+   	return joystickAxes.count;
+}
+
+/**	
+ * Returns the number of POVs on a given joystick port
+ *
+ * @param stick The joystick port number
+ * @return The number of POVs on the indicated joystick
+ */
+int DriverStation::GetStickPOVCount(uint32_t stick)
+{
+    if (stick >= kJoystickPorts)
+    {
+        wpi_setWPIError(BadJoystickIndex);
+        return 0;
+    }
+	HALJoystickPOVs joystickPOVs;
+	HALGetJoystickPOVs(stick, &joystickPOVs);
+   	return joystickPOVs.count;
+}
+
+/**	
+ * Returns the number of buttons on a given joystick port
+ *
+ * @param stick The joystick port number
+ * @return The number of buttons on the indicated joystick
+ */
+int DriverStation::GetStickButtonCount(uint32_t stick)
+{
+    if (stick >= kJoystickPorts)
+    {
+        wpi_setWPIError(BadJoystickIndex);
+        return 0;
+    }
+	HALJoystickButtons joystickButtons;
+	HALGetJoystickButtons(stick, &joystickButtons);
+   	return joystickButtons.count;
+}
+
+/**
+ * Get the value of the axis on a joystick.
+ * This depends on the mapping of the joystick connected to the specified port.
+ *
+ * @param stick The joystick to read.
+ * @param axis The analog axis value to read from the joystick.
+ * @return The value of the axis on the joystick.
+ */
+float DriverStation::GetStickAxis(uint32_t stick, uint32_t axis)
+{
+	if (stick >= kJoystickPorts)
+	{
+		wpi_setWPIError(BadJoystickIndex);
+		return 0;
+	}
+
+	if (axis >= m_joystickAxes[stick].count)
+	{
+		if (axis >= kMaxJoystickAxes)
+			wpi_setWPIError(BadJoystickAxis);
+		//else
+			//ReportJoystickUnpluggedError("WARNING: Joystick Axis missing, check if all controllers are plugged in\n");
+		return 0.0f;
+	}
+
+	int8_t value = m_joystickAxes[stick].axes[axis];
+
+	if(value < 0)
+	{
+		return value / 128.0f;
+	}
+	else
+	{
+		return value / 127.0f;
+	}
+}
+
+/**
+ * Get the state of a POV on the joystick.
+ *
+ * @return the angle of the POV in degrees, or -1 if the POV is not pressed.
+ */
+int DriverStation::GetStickPOV(uint32_t stick, uint32_t pov) {
+	if (stick >= kJoystickPorts)
+	{
+		wpi_setWPIError(BadJoystickIndex);
+		return 0;
+	}
+
+	if (pov >= m_joystickPOVs[stick].count)
+	{
+		if (pov >= kMaxJoystickPOVs)
+			wpi_setWPIError(BadJoystickAxis);
+		//else
+			//ReportJoystickUnpluggedError("WARNING: Joystick POV missing, check if all controllers are plugged in\n");
+		return 0;
+	}
+
+	return m_joystickPOVs[stick].povs[pov];
+}
+
+/**
+ * The state of the buttons on the joystick.
+ *
+ * @param stick The joystick to read.
+ * @return The state of the buttons on the joystick.
+ */
+uint32_t DriverStation::GetStickButtons(uint32_t stick)
+{
+	if (stick >= kJoystickPorts)
+	{
+		wpi_setWPIError(BadJoystickIndex);
+		return 0;
+	}
+
+	return m_joystickButtons[stick].buttons;
+}
+
+/**
+ * The state of one joystick button. Button indexes begin at 1.
+ *
+ * @param stick The joystick to read.
+ * @param button The button index, beginning at 1.
+ * @return The state of the joystick button.
+ */
+bool DriverStation::GetStickButton(uint32_t stick, uint8_t button)
+{
+	if (stick >= kJoystickPorts)
+	{
+		wpi_setWPIError(BadJoystickIndex);
+		return false;
+	}
+	
+	if(button > m_joystickButtons[stick].count)
+	{
+		//ReportJoystickUnpluggedError("WARNING: Joystick Button missing, check if all controllers are plugged in\n");
+		return false;
+	}
+	if(button == 0)
+	{
+		//ReportJoystickUnpluggedError("ERROR: Button indexes begin at 1 in WPILib for C++ and Java");
+		return false;
+	}
+	return ((0x1 << (button-1)) & m_joystickButtons[stick].buttons) !=0;
+}
+
+/**
+ * Check if the DS has enabled the robot
+ * @return True if the robot is enabled and the DS is connected
+ */
+bool DriverStation::IsEnabled()
+{
+	HALControlWord controlWord;
+    memset(&controlWord, 0, sizeof(controlWord));
+	HALGetControlWord(&controlWord);
+	return controlWord.enabled && controlWord.dsAttached;
+}
+
+/**
+ * Check if the robot is disabled
+ * @return True if the robot is explicitly disabled or the DS is not connected
+ */
+bool DriverStation::IsDisabled()
+{
+	HALControlWord controlWord;
+    memset(&controlWord, 0, sizeof(controlWord));
+	HALGetControlWord(&controlWord);
+	return !(controlWord.enabled && controlWord.dsAttached);
+}
+
+/**
+ * Check if the DS is commanding autonomous mode
+ * @return True if the robot is being commanded to be in autonomous mode
+ */
+bool DriverStation::IsAutonomous()
+{
+	HALControlWord controlWord;
+    memset(&controlWord, 0, sizeof(controlWord));
+	HALGetControlWord(&controlWord);
+	return controlWord.autonomous;
+}
+
+/**
+ * Check if the DS is commanding teleop mode
+ * @return True if the robot is being commanded to be in teleop mode
+ */
+bool DriverStation::IsOperatorControl()
+{
+	HALControlWord controlWord;
+    memset(&controlWord, 0, sizeof(controlWord));
+	HALGetControlWord(&controlWord);
+	return !(controlWord.autonomous || controlWord.test);
+}
+
+/**
+ * Check if the DS is commanding test mode
+ * @return True if the robot is being commanded to be in test mode
+ */
+bool DriverStation::IsTest()
+{
+	HALControlWord controlWord;
+	HALGetControlWord(&controlWord);
+	return controlWord.test;
+}
+
+/**
+ * Check if the DS is attached
+ * @return True if the DS is connected to the robot
+ */
+bool DriverStation::IsDSAttached()
+{
+	HALControlWord controlWord;
+    memset(&controlWord, 0, sizeof(controlWord));
+	HALGetControlWord(&controlWord);
+	return controlWord.dsAttached;
+}
+
+/**
+ * Check if the FPGA outputs are enabled. The outputs may be disabled if the robot is disabled
+ * or e-stopped, the watchdog has expired, or if the roboRIO browns out.
+ * @return True if the FPGA outputs are enabled.
+ */
+bool DriverStation::IsSysActive()
+{
+	int32_t status = 0;
+	bool retVal = HALGetSystemActive(&status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	return retVal;
+}
+
+/**
+ * Check if the system is browned out.
+ * @return True if the system is browned out
+ */
+bool DriverStation::IsSysBrownedOut()
+{
+	int32_t status = 0;
+	bool retVal = HALGetBrownedOut(&status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	return retVal;
+}
+
+/**
+ * Has a new control packet from the driver station arrived since the last time this function was called?
+ * Warning: If you call this function from more than one place at the same time,
+ * you will not get the get the intended behaviour.
+ * @return True if the control data has been updated since the last call.
+ */
+bool DriverStation::IsNewControlData()
+{
+	return tryTakeSemaphore(m_newControlData) == 0;
+}
+
+/**
+ * Is the driver station attached to a Field Management System?
+ * @return True if the robot is competing on a field being controlled by a Field Management System
+ */
+bool DriverStation::IsFMSAttached()
+{
+	HALControlWord controlWord;
+	HALGetControlWord(&controlWord);
+	return controlWord.fmsAttached;
+}
+
+/**
+ * Return the alliance that the driver station says it is on.
+ * This could return kRed or kBlue
+ * @return The Alliance enum (kRed, kBlue or kInvalid)
+ */
+DriverStation::Alliance DriverStation::GetAlliance()
+{
+	HALAllianceStationID allianceStationID;
+	HALGetAllianceStation(&allianceStationID);
+	switch(allianceStationID)
+	{
+	case kHALAllianceStationID_red1:
+	case kHALAllianceStationID_red2:
+	case kHALAllianceStationID_red3:
+		return kRed;
+	case kHALAllianceStationID_blue1:
+	case kHALAllianceStationID_blue2:
+	case kHALAllianceStationID_blue3:
+		return kBlue;
+	default:
+		return kInvalid;
+	}
+}
+
+/**
+ * Return the driver station location on the field
+ * This could return 1, 2, or 3
+ * @return The location of the driver station (1-3, 0 for invalid)
+ */
+uint32_t DriverStation::GetLocation()
+{
+	HALAllianceStationID allianceStationID;
+	HALGetAllianceStation(&allianceStationID);
+	switch(allianceStationID)
+	{
+	case kHALAllianceStationID_red1:
+	case kHALAllianceStationID_blue1:
+		return 1;
+	case kHALAllianceStationID_red2:
+	case kHALAllianceStationID_blue2:
+		return 2;
+	case kHALAllianceStationID_red3:
+	case kHALAllianceStationID_blue3:
+		return 3;
+	default:
+		return 0;
+	}
+}
+
+/**
+ * Wait until a new packet comes from the driver station
+ * This blocks on a semaphore, so the waiting is efficient.
+ * This is a good way to delay processing until there is new driver station data to act on
+ */
+void DriverStation::WaitForData()
+{
+	takeMultiWait(m_waitForDataSem, m_waitForDataMutex, SEMAPHORE_WAIT_FOREVER);
+}
+
+/**
+ * Return the approximate match time
+ * The FMS does not send an official match time to the robots, but does send an approximate match time.
+ * The value will count down the time remaining in the current period (auto or teleop).
+ * Warning: This is not an official time (so it cannot be used to dispute ref calls or guarantee that a function
+ * will trigger before the match ends)
+ * The Practice Match function of the DS approximates the behaviour seen on the field.
+ * @return Time remaining in current match period (auto or teleop)
+ */
+double DriverStation::GetMatchTime()
+{
+	float matchTime;
+	HALGetMatchTime(&matchTime);
+	return (double)matchTime;
+}
+
+/**
+ * Report an error to the DriverStation messages window.
+ * The error is also printed to the program console.
+ */
+void DriverStation::ReportError(std::string error)
+{
+	std::cout << error << std::endl;
+    HALSetErrorData(error.c_str(), error.size(), 0);
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Encoder.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Encoder.cpp
new file mode 100644
index 0000000..4a2afb1
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Encoder.cpp
@@ -0,0 +1,546 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "Encoder.h"
+#include "DigitalInput.h"
+//#include "NetworkCommunication/UsageReporting.h"
+#include "Resource.h"
+#include "WPIErrors.h"
+
+/**
+ * Common initialization code for Encoders.
+ * This code allocates resources for Encoders and is common to all constructors.
+ *
+ * The counter will start counting immediately.
+ *
+ * @param reverseDirection If true, counts down instead of up (this is all relative)
+ * @param encodingType either k1X, k2X, or k4X to indicate 1X, 2X or 4X decoding. If 4X is
+ * selected, then an encoder FPGA object is used and the returned counts will be 4x the encoder
+ * spec'd value since all rising and falling edges are counted. If 1X or 2X are selected then
+ * a counter object will be used and the returned value will either exactly match the spec'd count
+ * or be double (2x) the spec'd count.
+ */
+void Encoder::InitEncoder(bool reverseDirection, EncodingType encodingType)
+{
+	m_encodingType = encodingType;
+	m_index = 0;
+	switch (encodingType)
+	{
+		case k4X:
+		{
+			m_encodingScale = 4;
+			if (m_aSource->StatusIsFatal())
+			{
+				CloneError(m_aSource);
+				return;
+			}
+			if (m_bSource->StatusIsFatal())
+			{
+				CloneError(m_bSource);
+				return;
+			}
+			int32_t status = 0;
+			m_encoder =  initializeEncoder(m_aSource->GetModuleForRouting(), m_aSource->GetChannelForRouting(),
+										   m_aSource->GetAnalogTriggerForRouting(),
+										   m_bSource->GetModuleForRouting(), m_bSource->GetChannelForRouting(),
+										   m_bSource->GetAnalogTriggerForRouting(),
+										   reverseDirection, &m_index, &status);
+			  wpi_setErrorWithContext(status, getHALErrorMessage(status));
+			m_counter = NULL;
+			SetMaxPeriod(.5);
+			break;
+		}
+		case k1X:
+		case k2X:
+		{
+			m_encodingScale = encodingType == k1X ? 1 : 2;
+			m_counter = new Counter(m_encodingType, m_aSource, m_bSource, reverseDirection);
+			m_index = m_counter->GetFPGAIndex();
+			break;
+		}
+		default:
+			wpi_setErrorWithContext(-1, "Invalid encodingType argument");
+			break;
+	}
+	m_distancePerPulse = 1.0;
+	m_pidSource = kDistance;
+
+	HALReport(HALUsageReporting::kResourceType_Encoder, m_index, encodingType);
+}
+
+/**
+ * Encoder constructor.
+ * Construct a Encoder given a and b channels.
+ *
+ * The counter will start counting immediately.
+ *
+ * @param aChannel The a channel DIO channel. 0-9 are on-board, 10-25 are on the MXP port
+ * @param bChannel The b channel DIO channel. 0-9 are on-board, 10-25 are on the MXP port
+ * @param reverseDirection represents the orientation of the encoder and inverts the output values
+ * if necessary so forward represents positive values.
+ * @param encodingType either k1X, k2X, or k4X to indicate 1X, 2X or 4X decoding. If 4X is
+ * selected, then an encoder FPGA object is used and the returned counts will be 4x the encoder
+ * spec'd value since all rising and falling edges are counted. If 1X or 2X are selected then
+ * a counter object will be used and the returned value will either exactly match the spec'd count
+ * or be double (2x) the spec'd count.
+ */
+Encoder::Encoder(uint32_t aChannel, uint32_t bChannel, bool reverseDirection, EncodingType encodingType) :
+	m_encoder(NULL),
+	m_counter(NULL)
+{
+	m_aSource = new DigitalInput(aChannel);
+	m_bSource = new DigitalInput(bChannel);
+	InitEncoder(reverseDirection, encodingType);
+	m_allocatedASource = true;
+	m_allocatedBSource = true;
+}
+
+/**
+ * Encoder constructor.
+ * Construct a Encoder given a and b channels as digital inputs. This is used in the case
+ * where the digital inputs are shared. The Encoder class will not allocate the digital inputs
+ * and assume that they already are counted.
+ *
+ * The counter will start counting immediately.
+ *
+ * @param aSource The source that should be used for the a channel.
+ * @param bSource the source that should be used for the b channel.
+ * @param reverseDirection represents the orientation of the encoder and inverts the output values
+ * if necessary so forward represents positive values.
+ * @param encodingType either k1X, k2X, or k4X to indicate 1X, 2X or 4X decoding. If 4X is
+ * selected, then an encoder FPGA object is used and the returned counts will be 4x the encoder
+ * spec'd value since all rising and falling edges are counted. If 1X or 2X are selected then
+ * a counter object will be used and the returned value will either exactly match the spec'd count
+ * or be double (2x) the spec'd count.
+ */
+Encoder::Encoder(DigitalSource *aSource, DigitalSource *bSource, bool reverseDirection, EncodingType encodingType) :
+	m_encoder(NULL),
+	m_counter(NULL)
+{
+	m_aSource = aSource;
+	m_bSource = bSource;
+	m_allocatedASource = false;
+	m_allocatedBSource = false;
+	if (m_aSource == NULL || m_bSource == NULL)
+		wpi_setWPIError(NullParameter);
+	else
+		InitEncoder(reverseDirection, encodingType);
+}
+
+/**
+ * Encoder constructor.
+ * Construct a Encoder given a and b channels as digital inputs. This is used in the case
+ * where the digital inputs are shared. The Encoder class will not allocate the digital inputs
+ * and assume that they already are counted.
+ *
+ * The counter will start counting immediately.
+ *
+ * @param aSource The source that should be used for the a channel.
+ * @param bSource the source that should be used for the b channel.
+ * @param reverseDirection represents the orientation of the encoder and inverts the output values
+ * if necessary so forward represents positive values.
+ * @param encodingType either k1X, k2X, or k4X to indicate 1X, 2X or 4X decoding. If 4X is
+ * selected, then an encoder FPGA object is used and the returned counts will be 4x the encoder
+ * spec'd value since all rising and falling edges are counted. If 1X or 2X are selected then
+ * a counter object will be used and the returned value will either exactly match the spec'd count
+ * or be double (2x) the spec'd count.
+ */
+Encoder::Encoder(DigitalSource &aSource, DigitalSource &bSource, bool reverseDirection, EncodingType encodingType) :
+	m_encoder(NULL),
+	m_counter(NULL)
+{
+	m_aSource = &aSource;
+	m_bSource = &bSource;
+	m_allocatedASource = false;
+	m_allocatedBSource = false;
+	InitEncoder(reverseDirection, encodingType);
+}
+
+/**
+ * Free the resources for an Encoder.
+ * Frees the FPGA resources associated with an Encoder.
+ */
+Encoder::~Encoder()
+{
+	if (m_allocatedASource) delete m_aSource;
+	if (m_allocatedBSource) delete m_bSource;
+	if (m_counter)
+	{
+		delete m_counter;
+	}
+	else
+	{
+	  	int32_t status = 0;
+		freeEncoder(m_encoder, &status);
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+}
+
+/**
+ * The encoding scale factor 1x, 2x, or 4x, per the requested encodingType.
+ * Used to divide raw edge counts down to spec'd counts.
+ */
+int32_t Encoder::GetEncodingScale() { return m_encodingScale; }
+
+/**
+ * Gets the raw value from the encoder.
+ * The raw value is the actual count unscaled by the 1x, 2x, or 4x scale
+ * factor.
+ * @return Current raw count from the encoder
+ */
+int32_t Encoder::GetRaw()
+{
+	if (StatusIsFatal()) return 0;
+	int32_t value;
+	if (m_counter)
+		value = m_counter->Get();
+	else
+	{
+		int32_t status = 0;
+		value = getEncoder(m_encoder, &status);
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+	return value;
+}
+
+/**
+ * Gets the current count.
+ * Returns the current count on the Encoder.
+ * This method compensates for the decoding type.
+ *
+ * @return Current count from the Encoder adjusted for the 1x, 2x, or 4x scale factor.
+ */
+int32_t Encoder::Get()
+{
+	if (StatusIsFatal()) return 0;
+	return (int32_t) (GetRaw() * DecodingScaleFactor());
+}
+
+/**
+ * Reset the Encoder distance to zero.
+ * Resets the current count to zero on the encoder.
+ */
+void Encoder::Reset()
+{
+	if (StatusIsFatal()) return;
+	if (m_counter)
+		m_counter->Reset();
+	else
+	{
+		int32_t status = 0;
+		resetEncoder(m_encoder, &status);
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+}
+
+/**
+ * Returns the period of the most recent pulse.
+ * Returns the period of the most recent Encoder pulse in seconds.
+ * This method compensates for the decoding type.
+ *
+ * @deprecated Use GetRate() in favor of this method.  This returns unscaled periods and GetRate() scales using value from SetDistancePerPulse().
+ *
+ * @return Period in seconds of the most recent pulse.
+ */
+double Encoder::GetPeriod()
+{
+	if (StatusIsFatal()) return 0.0;
+	if (m_counter)
+	{
+		return m_counter->GetPeriod() / DecodingScaleFactor();
+	}
+	else
+	{
+		int32_t status = 0;
+		double period = getEncoderPeriod(m_encoder, &status);
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+		return period;
+	}
+
+}
+
+/**
+ * Sets the maximum period for stopped detection.
+ * Sets the value that represents the maximum period of the Encoder before it will assume
+ * that the attached device is stopped. This timeout allows users to determine if the wheels or
+ * other shaft has stopped rotating.
+ * This method compensates for the decoding type.
+ *
+ * @deprecated Use SetMinRate() in favor of this method.  This takes unscaled periods and SetMinRate() scales using value from SetDistancePerPulse().
+ *
+ * @param maxPeriod The maximum time between rising and falling edges before the FPGA will
+ * report the device stopped. This is expressed in seconds.
+ */
+void Encoder::SetMaxPeriod(double maxPeriod)
+{
+	if (StatusIsFatal()) return;
+	if (m_counter)
+	{
+		m_counter->SetMaxPeriod(maxPeriod * DecodingScaleFactor());
+	}
+	else
+	{
+		int32_t status = 0;
+		setEncoderMaxPeriod(m_encoder, maxPeriod, &status);
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+}
+
+/**
+ * Determine if the encoder is stopped.
+ * Using the MaxPeriod value, a boolean is returned that is true if the encoder is considered
+ * stopped and false if it is still moving. A stopped encoder is one where the most recent pulse
+ * width exceeds the MaxPeriod.
+ * @return True if the encoder is considered stopped.
+ */
+bool Encoder::GetStopped()
+{
+	if (StatusIsFatal()) return true;
+	if (m_counter)
+	{
+		return m_counter->GetStopped();
+	}
+	else
+	{
+		int32_t status = 0;
+		bool value = getEncoderStopped(m_encoder, &status);
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+		return value;
+	}
+}
+
+/**
+ * The last direction the encoder value changed.
+ * @return The last direction the encoder value changed.
+ */
+bool Encoder::GetDirection()
+{
+	if (StatusIsFatal()) return false;
+	if (m_counter)
+	{
+		return m_counter->GetDirection();
+	}
+	else
+	{
+		int32_t status = 0;
+		bool value = getEncoderDirection(m_encoder, &status);
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+		return value;
+	}
+}
+
+/**
+ * The scale needed to convert a raw counter value into a number of encoder pulses.
+ */
+double Encoder::DecodingScaleFactor()
+{
+	if (StatusIsFatal()) return 0.0;
+	switch (m_encodingType)
+	{
+	case k1X:
+		return 1.0;
+	case k2X:
+		return 0.5;
+	case k4X:
+		return 0.25;
+	default:
+		return 0.0;
+	}
+}
+
+/**
+ * Get the distance the robot has driven since the last reset.
+ *
+ * @return The distance driven since the last reset as scaled by the value from SetDistancePerPulse().
+ */
+double Encoder::GetDistance()
+{
+	if (StatusIsFatal()) return 0.0;
+	return GetRaw() * DecodingScaleFactor() * m_distancePerPulse;
+}
+
+/**
+ * Get the current rate of the encoder.
+ * Units are distance per second as scaled by the value from SetDistancePerPulse().
+ *
+ * @return The current rate of the encoder.
+ */
+double Encoder::GetRate()
+{
+	if (StatusIsFatal()) return 0.0;
+	return (m_distancePerPulse / GetPeriod());
+}
+
+/**
+ * Set the minimum rate of the device before the hardware reports it stopped.
+ *
+ * @param minRate The minimum rate.  The units are in distance per second as scaled by the value from SetDistancePerPulse().
+ */
+void Encoder::SetMinRate(double minRate)
+{
+	if (StatusIsFatal()) return;
+	SetMaxPeriod(m_distancePerPulse / minRate);
+}
+
+/**
+ * Set the distance per pulse for this encoder.
+ * This sets the multiplier used to determine the distance driven based on the count value
+ * from the encoder.
+ * Do not include the decoding type in this scale.  The library already compensates for the decoding type.
+ * Set this value based on the encoder's rated Pulses per Revolution and
+ * factor in gearing reductions following the encoder shaft.
+ * This distance can be in any units you like, linear or angular.
+ *
+ * @param distancePerPulse The scale factor that will be used to convert pulses to useful units.
+ */
+void Encoder::SetDistancePerPulse(double distancePerPulse)
+{
+	if (StatusIsFatal()) return;
+	m_distancePerPulse = distancePerPulse;
+}
+
+/**
+ * Set the direction sensing for this encoder.
+ * This sets the direction sensing on the encoder so that it could count in the correct
+ * software direction regardless of the mounting.
+ * @param reverseDirection true if the encoder direction should be reversed
+ */
+void Encoder::SetReverseDirection(bool reverseDirection)
+{
+	if (StatusIsFatal()) return;
+	if (m_counter)
+	{
+		m_counter->SetReverseDirection(reverseDirection);
+	}
+	else
+	{
+		int32_t status = 0;
+		setEncoderReverseDirection(m_encoder, reverseDirection, &status);
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+}
+
+
+/**
+ * Set the Samples to Average which specifies the number of samples of the timer to
+ * average when calculating the period. Perform averaging to account for
+ * mechanical imperfections or as oversampling to increase resolution.
+ * @param samplesToAverage The number of samples to average from 1 to 127.
+ */
+void Encoder::SetSamplesToAverage(int samplesToAverage)
+{
+	if (samplesToAverage < 1 || samplesToAverage > 127)
+	{
+		wpi_setWPIErrorWithContext(ParameterOutOfRange, "Average counter values must be between 1 and 127");
+	}
+	int32_t status = 0;
+	switch (m_encodingType) {
+		case k4X:
+			setEncoderSamplesToAverage(m_encoder, samplesToAverage, &status);
+			wpi_setErrorWithContext(status, getHALErrorMessage(status));
+			break;
+		case k1X:
+		case k2X:
+			m_counter->SetSamplesToAverage(samplesToAverage);
+			break;
+	}
+}
+
+/**
+ * Get the Samples to Average which specifies the number of samples of the timer to
+ * average when calculating the period. Perform averaging to account for
+ * mechanical imperfections or as oversampling to increase resolution.
+ * @return SamplesToAverage The number of samples being averaged (from 1 to 127)
+ */
+int Encoder::GetSamplesToAverage()
+{
+	int result = 1;
+	int32_t status = 0;
+	switch (m_encodingType) {
+		case k4X:
+			result = getEncoderSamplesToAverage(m_encoder, &status);
+			wpi_setErrorWithContext(status, getHALErrorMessage(status));
+			break;
+		case k1X:
+		case k2X:
+			result = m_counter->GetSamplesToAverage();
+			break;
+	}
+	return result;
+}
+
+
+
+/**
+ * Set which parameter of the encoder you are using as a process control variable.
+ *
+ * @param pidSource An enum to select the parameter.
+ */
+void Encoder::SetPIDSourceParameter(PIDSourceParameter pidSource)
+{
+	if (StatusIsFatal()) return;
+	m_pidSource = pidSource;
+}
+
+/**
+ * Implement the PIDSource interface.
+ *
+ * @return The current value of the selected source parameter.
+ */
+double Encoder::PIDGet()
+{
+	if (StatusIsFatal()) return 0.0;
+	switch (m_pidSource)
+	{
+	case kDistance:
+		return GetDistance();
+	case kRate:
+		return GetRate();
+	default:
+		return 0.0;
+	}
+}
+
+/**
+ * Set the index source for the encoder.  When this source is activated, the encoder count automatically resets.
+ *
+ * @param channel A DIO channel to set as the encoder index
+ * @param type The state that will cause the encoder to reset
+ */
+void Encoder::SetIndexSource(uint32_t channel, Encoder::IndexingType type) {
+	int32_t status = 0;
+	bool activeHigh = (type == kResetWhileHigh) || (type == kResetOnRisingEdge);
+	bool edgeSensitive = (type == kResetOnFallingEdge) || (type == kResetOnRisingEdge);
+
+  setEncoderIndexSource(m_encoder, channel, false, activeHigh, edgeSensitive, &status);
+  wpi_setGlobalErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Set the index source for the encoder.  When this source is activated, the encoder count automatically resets.
+ *
+ * @param channel A digital source to set as the encoder index
+ * @param type The state that will cause the encoder to reset
+ */
+void Encoder::SetIndexSource(DigitalSource *source, Encoder::IndexingType type) {
+	int32_t status = 0;
+	bool activeHigh = (type == kResetWhileHigh) || (type == kResetOnRisingEdge);
+	bool edgeSensitive = (type == kResetOnFallingEdge) || (type == kResetOnRisingEdge);
+
+  setEncoderIndexSource(m_encoder, source->GetChannelForRouting(), source->GetAnalogTriggerForRouting(), activeHigh,
+  		edgeSensitive, &status);
+  wpi_setGlobalErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Set the index source for the encoder.  When this source is activated, the encoder count automatically resets.
+ *
+ * @param channel A digital source to set as the encoder index
+ * @param type The state that will cause the encoder to reset
+ */
+void Encoder::SetIndexSource(DigitalSource &source, Encoder::IndexingType type) {
+	SetIndexSource(&source, type);
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/GearTooth.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/GearTooth.cpp
new file mode 100644
index 0000000..8e8f25d
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/GearTooth.cpp
@@ -0,0 +1,64 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "GearTooth.h"
+
+constexpr double GearTooth::kGearToothThreshold;
+
+/**
+ * Common code called by the constructors.
+ */
+void GearTooth::EnableDirectionSensing(bool directionSensitive)
+{
+	if (directionSensitive)
+	{
+		SetPulseLengthMode(kGearToothThreshold);
+	}
+}
+
+/**
+ * Construct a GearTooth sensor given a channel.
+ *
+ * @param channel The DIO channel that the sensor is connected to. 0-9 are on-board, 10-25 are on the MXP.
+ * @param directionSensitive True to enable the pulse length decoding in hardware to specify count direction.
+ */
+GearTooth::GearTooth(uint32_t channel, bool directionSensitive)
+	: Counter(channel)
+{
+	EnableDirectionSensing(directionSensitive);
+}
+
+/**
+ * Construct a GearTooth sensor given a digital input.
+ * This should be used when sharing digital inputs.
+ *
+ * @param source A pointer to the existing DigitalSource object (such as a DigitalInput)
+ * @param directionSensitive True to enable the pulse length decoding in hardware to specify count direction.
+ */
+GearTooth::GearTooth(DigitalSource *source, bool directionSensitive)
+	: Counter(source)
+{
+	EnableDirectionSensing(directionSensitive);
+}
+
+/**
+ * Construct a GearTooth sensor given a digital input.
+ * This should be used when sharing digital inputs.
+ *
+ * @param source A reference to the existing DigitalSource object (such as a DigitalInput)
+ * @param directionSensitive True to enable the pulse length decoding in hardware to specify count direction.
+ */
+GearTooth::GearTooth(DigitalSource &source, bool directionSensitive): Counter(source)
+{
+	EnableDirectionSensing(directionSensitive);
+}
+
+/**
+ * Free the resources associated with a gear tooth sensor.
+ */
+GearTooth::~GearTooth()
+{
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Gyro.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Gyro.cpp
new file mode 100644
index 0000000..b1650de
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Gyro.cpp
@@ -0,0 +1,230 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "Gyro.h"
+#include "AnalogInput.h"
+//#include "NetworkCommunication/UsageReporting.h"
+#include "Timer.h"
+#include "WPIErrors.h"
+#include <climits>
+const uint32_t Gyro::kOversampleBits;
+const uint32_t Gyro::kAverageBits;
+constexpr float Gyro::kSamplesPerSecond;
+constexpr float Gyro::kCalibrationSampleTime;
+constexpr float Gyro::kDefaultVoltsPerDegreePerSecond;
+
+/**
+ * Initialize the gyro.
+ * Calibrate the gyro by running for a number of samples and computing the center value. 
+ * Then use the center value as the Accumulator center value for subsequent measurements.
+ * It's important to make sure that the robot is not moving while the centering calculations are
+ * in progress, this is typically done when the robot is first turned on while it's sitting at
+ * rest before the competition starts.
+ */
+void Gyro::InitGyro()
+{
+	if (!m_analog->IsAccumulatorChannel())
+	{
+		wpi_setWPIErrorWithContext(ParameterOutOfRange,
+            " channel (must be accumulator channel)");
+		if (m_channelAllocated)
+		{
+			delete m_analog;
+			m_analog = NULL;
+		}
+		return;
+	}
+
+	m_voltsPerDegreePerSecond = kDefaultVoltsPerDegreePerSecond;
+	m_analog->SetAverageBits(kAverageBits);
+	m_analog->SetOversampleBits(kOversampleBits);
+	float sampleRate = kSamplesPerSecond *
+		(1 << (kAverageBits + kOversampleBits));
+	m_analog->SetSampleRate(sampleRate);
+	Wait(1.0);
+
+	m_analog->InitAccumulator();
+
+	Wait(kCalibrationSampleTime);
+
+	int64_t value;
+	uint32_t count;
+	m_analog->GetAccumulatorOutput(&value, &count);
+
+	m_center = (uint32_t)((float)value / (float)count + .5);
+
+	m_offset = ((float)value / (float)count) - (float)m_center;
+	m_analog->SetAccumulatorCenter(m_center);
+	m_analog->ResetAccumulator();
+
+	SetDeadband(0.0f);
+
+	SetPIDSourceParameter(kAngle);
+
+	HALReport(HALUsageReporting::kResourceType_Gyro, m_analog->GetChannel());
+}
+
+/**
+ * Gyro constructor using the Analog Input channel number.
+ *
+ * @param channel The analog channel the gyro is connected to. Gyros 
+	              can only be used on on-board Analog Inputs 0-1.
+ */
+Gyro::Gyro(int32_t channel)
+{
+	m_analog = new AnalogInput(channel);
+	m_channelAllocated = true;
+	InitGyro();
+}
+
+/**
+ * Gyro constructor with a precreated AnalogInput object.
+ * Use this constructor when the analog channel needs to be shared.
+ * This object will not clean up the AnalogInput object when using this constructor. 
+ * Gyros can only be used on on-board channels 0-1.
+ * @param channel A pointer to the AnalogInput object that the gyro is connected to.
+ */
+Gyro::Gyro(AnalogInput *channel)
+{
+	m_analog = channel;
+	m_channelAllocated = false;
+	if (channel == NULL)
+	{
+		wpi_setWPIError(NullParameter);
+	}
+	else
+	{
+		InitGyro();
+	}
+}
+
+/**
+ * Gyro constructor with a precreated AnalogInput object.
+ * Use this constructor when the analog channel needs to be shared.
+ * This object will not clean up the AnalogInput object when using this constructor
+ * @param channel A reference to the AnalogInput object that the gyro is connected to.
+ */
+Gyro::Gyro(AnalogInput &channel)
+{
+	m_analog = &channel;
+	m_channelAllocated = false;
+	InitGyro();
+}
+
+/**
+ * Reset the gyro.
+ * Resets the gyro to a heading of zero. This can be used if there is significant
+ * drift in the gyro and it needs to be recalibrated after it has been running.
+ */
+void Gyro::Reset()
+{
+	m_analog->ResetAccumulator();
+}
+
+/**
+ * Delete (free) the accumulator and the analog components used for the gyro.
+ */
+Gyro::~Gyro()
+{
+	if (m_channelAllocated)
+		delete m_analog;
+}
+
+/**
+ * Return the actual angle in degrees that the robot is currently facing.
+ *
+ * The angle is based on the current accumulator value corrected by the oversampling rate, the
+ * gyro type and the A/D calibration values.
+ * The angle is continuous, that is it will continue from 360->361 degrees. This allows algorithms that wouldn't
+ * want to see a discontinuity in the gyro output as it sweeps from 360 to 0 on the second time around.
+ *
+ * @return the current heading of the robot in degrees. This heading is based on integration
+ * of the returned rate from the gyro.
+ */
+float Gyro::GetAngle( void )
+{
+	int64_t rawValue;
+	uint32_t count;
+	m_analog->GetAccumulatorOutput(&rawValue, &count);
+
+	int64_t value = rawValue - (int64_t)((float)count * m_offset);
+
+	double scaledValue = value * 1e-9 * (double)m_analog->GetLSBWeight() * (double)(1 << m_analog->GetAverageBits()) /
+		(m_analog->GetSampleRate() * m_voltsPerDegreePerSecond);
+
+	return (float)scaledValue;
+}
+
+
+/**
+ * Return the rate of rotation of the gyro
+ *
+ * The rate is based on the most recent reading of the gyro analog value
+ *
+ * @return the current rate in degrees per second
+ */
+double Gyro::GetRate( void )
+{
+	return (m_analog->GetAverageValue() - ((double)m_center + m_offset)) * 1e-9 * m_analog->GetLSBWeight()
+			/ ((1 << m_analog->GetOversampleBits()) * m_voltsPerDegreePerSecond);
+}
+
+
+/**
+ * Set the gyro sensitivity.
+ * This takes the number of volts/degree/second sensitivity of the gyro and uses it in subsequent
+ * calculations to allow the code to work with multiple gyros. This value is typically found in 
+ * the gyro datasheet.
+ *
+ * @param voltsPerDegreePerSecond The sensitivity in Volts/degree/second
+ */
+void Gyro::SetSensitivity( float voltsPerDegreePerSecond )
+{
+	m_voltsPerDegreePerSecond = voltsPerDegreePerSecond;
+}
+
+/**
+ * Set the size of the neutral zone.  Any voltage from the gyro less than this
+ * amount from the center is considered stationary.  Setting a deadband will
+ * decrease the amount of drift when the gyro isn't rotating, but will make it
+ * less accurate.
+ *
+ * @param volts The size of the deadband in volts
+ */
+void Gyro::SetDeadband( float volts ) {
+	int32_t deadband = volts * 1e9 / m_analog->GetLSBWeight() * (1 << m_analog->GetOversampleBits());
+	m_analog->SetAccumulatorDeadband(deadband);
+}
+
+
+/**
+ * Sets the type of output to use with the WPILib PID class
+ * The gyro supports using either rate or angle for PID calculations
+ */
+void Gyro::SetPIDSourceParameter(PIDSourceParameter pidSource)
+{
+	if(pidSource == 0 || pidSource > 2)
+		wpi_setWPIErrorWithContext(ParameterOutOfRange, "Gyro pidSource");
+    m_pidSource = pidSource;
+}
+
+/**
+ * Get the PIDOutput for the PIDSource base object. Can be set to return
+ * angle or rate using SetPIDSourceParameter(). Defaults to angle.
+ *
+ * @return The PIDOutput (angle or rate, defaults to angle)
+ */
+double Gyro::PIDGet()
+{
+	switch(m_pidSource){
+	case kRate:
+		return GetRate();
+	case kAngle:
+		return GetAngle();
+	default:
+		return 0;
+	}
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/I2C.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/I2C.cpp
new file mode 100644
index 0000000..19e3f4f
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/I2C.cpp
@@ -0,0 +1,221 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "I2C.h"
+#include "HAL/HAL.hpp"
+#include "HAL/Digital.hpp"
+#include "WPIErrors.h"
+
+/**
+ * Constructor.
+ *
+ * @param port The I2C port to which the device is connected.
+ * @param deviceAddress The address of the device on the I2C bus.
+ */
+I2C::I2C(Port port, uint8_t deviceAddress) :
+	m_port (port)
+	, m_deviceAddress (deviceAddress)
+{
+	int32_t status = 0;
+	i2CInitialize(m_port, &status);
+	//wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+	HALReport(HALUsageReporting::kResourceType_I2C, deviceAddress);
+}
+
+/**
+ * Destructor.
+ */
+I2C::~I2C()
+{
+	i2CClose(m_port);
+}
+
+/**
+ * Generic transaction.
+ *
+ * This is a lower-level interface to the I2C hardware giving you more control over each transaction.
+ *
+ * @param dataToSend Buffer of data to send as part of the transaction.
+ * @param sendSize Number of bytes to send as part of the transaction. [0..6]
+ * @param dataReceived Buffer to read data into.
+ * @param receiveSize Number of bytes to read from the device. [0..7]
+ * @return Transfer Aborted... false for success, true for aborted.
+ */
+bool I2C::Transaction(uint8_t *dataToSend, uint8_t sendSize, uint8_t *dataReceived, uint8_t receiveSize)
+{
+	if (sendSize > 6) // Optional, provides better error message.
+	{
+		wpi_setWPIErrorWithContext(ParameterOutOfRange, "sendSize");
+		return true;
+	}
+	if (receiveSize > 7) // Optional, provides better error message.
+	{
+		wpi_setWPIErrorWithContext(ParameterOutOfRange, "receiveSize");
+		return true;
+	}
+
+	int32_t status = 0;
+	status = i2CTransaction(m_port, m_deviceAddress,
+											dataToSend, sendSize, dataReceived, receiveSize);
+	//wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	return status < 0;
+}
+
+/**
+ * Attempt to address a device on the I2C bus.
+ *
+ * This allows you to figure out if there is a device on the I2C bus that
+ * responds to the address specified in the constructor.
+ *
+ * @return Transfer Aborted... false for success, true for aborted.
+ */
+bool I2C::AddressOnly()
+{
+	int32_t status = 0;
+	status = Transaction(NULL, 0, NULL, 0);
+	return status < 0;
+}
+
+/**
+ * Execute a write transaction with the device.
+ *
+ * Write a single byte to a register on a device and wait until the
+ *   transaction is complete.
+ *
+ * @param registerAddress The address of the register on the device to be written.
+ * @param data The byte to write to the register on the device.
+ * @return Transfer Aborted... false for success, true for aborted.
+ */
+bool I2C::Write(uint8_t registerAddress, uint8_t data)
+{
+	uint8_t buffer[2];
+	buffer[0] = registerAddress;
+	buffer[1] = data;
+	int32_t status = 0;
+	status = i2CWrite(m_port, m_deviceAddress, buffer, sizeof(buffer));
+	return status < 0;
+}
+
+/**
+ * Execute a bulk write transaction with the device.
+ *
+ * Write multiple bytes to a device and wait until the
+ *   transaction is complete.
+ *
+ * @param data The data to write to the register on the device.
+ * @param count The number of bytes to be written.
+ * @return Transfer Aborted... false for success, true for aborted.
+ */
+bool I2C::WriteBulk(uint8_t* data, uint8_t count)
+{
+	int32_t status = 0;
+	status = i2CWrite(m_port, m_deviceAddress, data, count);
+	return status < 0;
+}
+
+/**
+ * Execute a read transaction with the device.
+ *
+ * Read 1 to 7 bytes from a device.
+ * Most I2C devices will auto-increment the register pointer internally
+ *   allowing you to read up to 7 consecutive registers on a device in a
+ *   single transaction.
+ *
+ * @param registerAddress The register to read first in the transaction.
+ * @param count The number of bytes to read in the transaction. [1..7]
+ * @param buffer A pointer to the array of bytes to store the data read from the device.
+ * @return Transfer Aborted... false for success, true for aborted.
+ */
+bool I2C::Read(uint8_t registerAddress, uint8_t count, uint8_t *buffer)
+{
+	if (count < 1 || count > 7)
+	{
+		wpi_setWPIErrorWithContext(ParameterOutOfRange, "count");
+		return true;
+	}
+	if (buffer == NULL)
+	{
+		wpi_setWPIErrorWithContext(NullParameter, "buffer");
+		return true;
+	}
+	int32_t status = 0;
+	status = Transaction(&registerAddress, sizeof(registerAddress), buffer, count);
+	return status < 0;
+}
+
+/**
+ * Execute a read only transaction with the device.
+ *
+ * Read 1 to 7 bytes from a device. This method does not write any data to prompt
+ * the device.
+ *
+ * @param buffer
+ *            A pointer to the array of bytes to store the data read from
+ *            the device.
+ * @param count
+ *            The number of bytes to read in the transaction. [1..7]
+ * @return Transfer Aborted... false for success, true for aborted.
+ */
+bool I2C::ReadOnly(uint8_t count, uint8_t *buffer)
+{
+	if (count < 1 || count > 7)
+	{
+		wpi_setWPIErrorWithContext(ParameterOutOfRange, "count");
+		return true;
+	}
+	if (buffer == NULL)
+	{
+		wpi_setWPIErrorWithContext(NullParameter, "buffer");
+		return true;
+	}
+	int32_t status = 0;
+	status = i2CRead(m_port, m_deviceAddress, buffer, count);
+	return status < 0;
+}
+
+/**
+ * Send a broadcast write to all devices on the I2C bus.
+ *
+ * This is not currently implemented!
+ *
+ * @param registerAddress The register to write on all devices on the bus.
+ * @param data The value to write to the devices.
+ */
+void I2C::Broadcast(uint8_t registerAddress, uint8_t data)
+{
+}
+
+/**
+ * Verify that a device's registers contain expected values.
+ *
+ * Most devices will have a set of registers that contain a known value that
+ *   can be used to identify them.  This allows an I2C device driver to easily
+ *   verify that the device contains the expected value.
+ *
+ * @pre The device must support and be configured to use register auto-increment.
+ *
+ * @param registerAddress The base register to start reading from the device.
+ * @param count The size of the field to be verified.
+ * @param expected A buffer containing the values expected from the device.
+ */
+bool I2C::VerifySensor(uint8_t registerAddress, uint8_t count, const uint8_t *expected)
+{
+	// TODO: Make use of all 7 read bytes
+	uint8_t deviceData[4];
+	for (uint8_t i=0, curRegisterAddress = registerAddress; i < count; i+=4, curRegisterAddress+=4)
+	{
+		uint8_t toRead = count - i < 4 ? count - i : 4;
+		// Read the chunk of data.  Return false if the sensor does not respond.
+		if (Read(curRegisterAddress, toRead, deviceData)) return false;
+
+		for (uint8_t j=0; j<toRead; j++)
+		{
+			if(deviceData[j] != expected[i + j]) return false;
+		}
+	}
+	return true;
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Internal/HardwareHLReporting.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Internal/HardwareHLReporting.cpp
new file mode 100644
index 0000000..9c21b7a
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Internal/HardwareHLReporting.cpp
@@ -0,0 +1,12 @@
+
+#include "Internal/HardwareHLReporting.h"
+#include "HAL/HAL.hpp"
+
+void HardwareHLReporting::ReportScheduler() {
+    HALReport(HALUsageReporting::kResourceType_Command,
+              HALUsageReporting::kCommand_Scheduler);
+}
+
+void HardwareHLReporting::ReportSmartDashboard() {
+    HALReport(HALUsageReporting::kResourceType_SmartDashboard, 0);
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/InterruptableSensorBase.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/InterruptableSensorBase.cpp
new file mode 100644
index 0000000..512c567
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/InterruptableSensorBase.cpp
@@ -0,0 +1,207 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "InterruptableSensorBase.h"
+#include "Utility.h"
+#include "WPIErrors.h"
+
+Resource *InterruptableSensorBase::m_interrupts = NULL;
+
+InterruptableSensorBase::InterruptableSensorBase()
+{
+	m_interrupt = NULL;
+	Resource::CreateResourceObject(&m_interrupts, interrupt_kNumSystems);
+}
+
+InterruptableSensorBase::~InterruptableSensorBase()
+{
+
+}
+
+/**
+* Request one of the 8 interrupts asynchronously on this digital input.
+* Request interrupts in asynchronous mode where the user's interrupt handler will be
+* called when the interrupt fires. Users that want control over the thread priority
+* should use the synchronous method with their own spawned thread.
+* The default is interrupt on rising edges only.
+*/
+void InterruptableSensorBase::RequestInterrupts(InterruptHandlerFunction handler, void *param)
+{
+	if (StatusIsFatal()) return;
+	uint32_t index = m_interrupts->Allocate("Async Interrupt");
+	if (index == ~0ul)
+	{
+		CloneError(m_interrupts);
+		return;
+	}
+	m_interruptIndex = index;
+
+	// Creates a manager too
+	AllocateInterrupts(false);
+
+	int32_t status = 0;
+	requestInterrupts(m_interrupt, GetModuleForRouting(), GetChannelForRouting(),
+					GetAnalogTriggerForRouting(), &status);
+	SetUpSourceEdge(true, false);
+	attachInterruptHandler(m_interrupt, handler, param, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+* Request one of the 8 interrupts synchronously on this digital input.
+* Request interrupts in synchronous mode where the user program will have to explicitly
+* wait for the interrupt to occur using WaitForInterrupt.
+* The default is interrupt on rising edges only.
+*/
+void InterruptableSensorBase::RequestInterrupts()
+{
+	if (StatusIsFatal()) return;
+	uint32_t index = m_interrupts->Allocate("Sync Interrupt");
+	if (index == ~0ul)
+	{
+		CloneError(m_interrupts);
+		return;
+	}
+	m_interruptIndex = index;
+
+	AllocateInterrupts(true);
+
+	int32_t status = 0;
+	requestInterrupts(m_interrupt, GetModuleForRouting(), GetChannelForRouting(),
+					GetAnalogTriggerForRouting(), &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	SetUpSourceEdge(true, false);
+}
+
+void InterruptableSensorBase::AllocateInterrupts(bool watcher)
+{
+	wpi_assert(m_interrupt == NULL);
+	// Expects the calling leaf class to allocate an interrupt index.
+	int32_t status = 0;
+	m_interrupt = initializeInterrupts(m_interruptIndex, watcher, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Cancel interrupts on this device.
+ * This deallocates all the chipobject structures and disables any interrupts.
+ */
+void InterruptableSensorBase::CancelInterrupts()
+{
+	if (StatusIsFatal()) return;
+	wpi_assert(m_interrupt != NULL);
+	int32_t status = 0;
+	cleanInterrupts(m_interrupt, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	m_interrupt = NULL;
+	m_interrupts->Free(m_interruptIndex);
+}
+
+/**
+ * In synchronous mode, wait for the defined interrupt to occur. You should <b>NOT</b> attempt to read the
+ * sensor from another thread while waiting for an interrupt. This is not threadsafe, and can cause 
+ * memory corruption
+ * @param timeout Timeout in seconds
+ * @param ignorePrevious If true, ignore interrupts that happened before
+ * WaitForInterrupt was called.
+ * @return What interrupts fired
+ */
+InterruptableSensorBase::WaitResult InterruptableSensorBase::WaitForInterrupt(float timeout, bool ignorePrevious)
+{
+	if (StatusIsFatal()) return InterruptableSensorBase::kTimeout;
+	wpi_assert(m_interrupt != NULL);
+	int32_t status = 0;
+	uint32_t result;
+
+	result = waitForInterrupt(m_interrupt, timeout, ignorePrevious, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+	return static_cast<WaitResult>(result);
+}
+
+/**
+ * Enable interrupts to occur on this input.
+ * Interrupts are disabled when the RequestInterrupt call is made. This gives time to do the
+ * setup of the other options before starting to field interrupts.
+ */
+void InterruptableSensorBase::EnableInterrupts()
+{
+	if (StatusIsFatal()) return;
+	wpi_assert(m_interrupt != NULL);
+	int32_t status = 0;
+	enableInterrupts(m_interrupt, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Disable Interrupts without without deallocating structures.
+ */
+void InterruptableSensorBase::DisableInterrupts()
+{
+	if (StatusIsFatal()) return;
+	wpi_assert(m_interrupt != NULL);
+	int32_t status = 0;
+	disableInterrupts(m_interrupt, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Return the timestamp for the rising interrupt that occurred most recently.
+ * This is in the same time domain as GetClock().
+ * The rising-edge interrupt should be enabled with
+ * {@link #DigitalInput.SetUpSourceEdge}
+ * @return Timestamp in seconds since boot.
+ */
+double InterruptableSensorBase::ReadRisingTimestamp()
+{
+	if (StatusIsFatal()) return 0.0;
+	wpi_assert(m_interrupt != NULL);
+	int32_t status = 0;
+	double timestamp = readRisingTimestamp(m_interrupt, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	return timestamp;
+}
+
+/**
+ * Return the timestamp for the falling interrupt that occurred most recently.
+ * This is in the same time domain as GetClock().
+ * The falling-edge interrupt should be enabled with
+ * {@link #DigitalInput.SetUpSourceEdge}
+ * @return Timestamp in seconds since boot.
+*/
+double InterruptableSensorBase::ReadFallingTimestamp()
+{
+	if (StatusIsFatal()) return 0.0;
+	wpi_assert(m_interrupt != NULL);
+	int32_t status = 0;
+	double timestamp = readFallingTimestamp(m_interrupt, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	return timestamp;
+}
+
+/**
+ * Set which edge to trigger interrupts on
+ *
+ * @param risingEdge
+ *            true to interrupt on rising edge
+ * @param fallingEdge
+ *            true to interrupt on falling edge
+ */
+void InterruptableSensorBase::SetUpSourceEdge(bool risingEdge, bool fallingEdge)
+{
+	if (StatusIsFatal()) return;
+	if (m_interrupt == NULL)
+	{
+		wpi_setWPIErrorWithContext(NullParameter, "You must call RequestInterrupts before SetUpSourceEdge");
+		return;
+	}
+	if (m_interrupt != NULL)
+	{
+		int32_t status = 0;
+		setInterruptUpSourceEdge(m_interrupt, risingEdge, fallingEdge, &status);
+		wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Jaguar.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Jaguar.cpp
new file mode 100644
index 0000000..ebc9ae2
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Jaguar.cpp
@@ -0,0 +1,86 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+
+#include "Jaguar.h"
+//#include "NetworkCommunication/UsageReporting.h"
+
+/**
+ * Common initialization code called by all constructors.
+ */
+void Jaguar::InitJaguar()
+{
+	/**
+	 * Input profile defined by Luminary Micro.
+	 *
+	 * Full reverse ranges from 0.671325ms to 0.6972211ms
+	 * Proportional reverse ranges from 0.6972211ms to 1.4482078ms
+	 * Neutral ranges from 1.4482078ms to 1.5517922ms
+	 * Proportional forward ranges from 1.5517922ms to 2.3027789ms
+	 * Full forward ranges from 2.3027789ms to 2.328675ms
+	 */
+	SetBounds(2.31, 1.55, 1.507, 1.454, .697);
+	SetPeriodMultiplier(kPeriodMultiplier_1X);
+	SetRaw(m_centerPwm);
+	SetZeroLatch();
+
+	HALReport(HALUsageReporting::kResourceType_Jaguar, GetChannel());
+}
+
+/**
+ * Constructor for a Jaguar connected via PWM
+ * @param channel The PWM channel that the Jaguar is attached to. 0-9 are on-board, 10-19 are on the MXP port
+ */
+Jaguar::Jaguar(uint32_t channel) : SafePWM(channel)
+{
+	InitJaguar();
+}
+
+Jaguar::~Jaguar()
+{
+}
+
+/**
+ * Set the PWM value.
+ *
+ * The PWM value is set using a range of -1.0 to 1.0, appropriately
+ * scaling the value for the FPGA.
+ *
+ * @param speed The speed value between -1.0 and 1.0 to set.
+ * @param syncGroup Unused interface.
+ */
+void Jaguar::Set(float speed, uint8_t syncGroup)
+{
+	SetSpeed(speed);
+}
+
+/**
+ * Get the recently set value of the PWM.
+ *
+ * @return The most recently set value for the PWM between -1.0 and 1.0.
+ */
+float Jaguar::Get()
+{
+	return GetSpeed();
+}
+
+/**
+ * Common interface for disabling a motor.
+ */
+void Jaguar::Disable()
+{
+	SetRaw(kPwmDisabled);
+}
+
+/**
+ * Write out the PID value as seen in the PIDOutput base object.
+ *
+ * @param output Write out the PWM value as was found in the PIDController
+ */
+void Jaguar::PIDWrite(float output)
+{
+	Set(output);
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Joystick.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Joystick.cpp
new file mode 100644
index 0000000..790f0d7
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Joystick.cpp
@@ -0,0 +1,389 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "Joystick.h"
+#include "DriverStation.h"
+//#include "NetworkCommunication/UsageReporting.h"
+#include "WPIErrors.h"
+#include <math.h>
+
+const uint32_t Joystick::kDefaultXAxis;
+const uint32_t Joystick::kDefaultYAxis;
+const uint32_t Joystick::kDefaultZAxis;
+const uint32_t Joystick::kDefaultTwistAxis;
+const uint32_t Joystick::kDefaultThrottleAxis;
+const uint32_t Joystick::kDefaultTriggerButton;
+const uint32_t Joystick::kDefaultTopButton;
+static Joystick *joysticks[DriverStation::kJoystickPorts];
+static bool joySticksInitialized = false;
+
+/**
+ * Construct an instance of a joystick.
+ * The joystick index is the usb port on the drivers station.
+ *
+ * @param port The port on the driver station that the joystick is plugged into (0-5).
+ */
+Joystick::Joystick(uint32_t port)
+	: m_ds (NULL)
+	, m_port (port)
+	, m_axes (NULL)
+	, m_buttons (NULL)
+	, m_outputs (0)
+	, m_leftRumble (0)
+	, m_rightRumble (0)
+{
+	InitJoystick(kNumAxisTypes, kNumButtonTypes);
+
+	m_axes[kXAxis] = kDefaultXAxis;
+	m_axes[kYAxis] = kDefaultYAxis;
+	m_axes[kZAxis] = kDefaultZAxis;
+	m_axes[kTwistAxis] = kDefaultTwistAxis;
+	m_axes[kThrottleAxis] = kDefaultThrottleAxis;
+
+	m_buttons[kTriggerButton] = kDefaultTriggerButton;
+	m_buttons[kTopButton] = kDefaultTopButton;
+
+	HALReport(HALUsageReporting::kResourceType_Joystick, port);
+}
+
+/**
+ * Version of the constructor to be called by sub-classes.
+ *
+ * This constructor allows the subclass to configure the number of constants
+ * for axes and buttons.
+ *
+ * @param port The port on the driver station that the joystick is plugged into.
+ * @param numAxisTypes The number of axis types in the enum.
+ * @param numButtonTypes The number of button types in the enum.
+ */
+Joystick::Joystick(uint32_t port, uint32_t numAxisTypes, uint32_t numButtonTypes)
+	: m_ds (NULL)
+	, m_port (port)
+	, m_axes (NULL)
+	, m_buttons (NULL)
+{
+	InitJoystick(numAxisTypes, numButtonTypes);
+}
+
+void Joystick::InitJoystick(uint32_t numAxisTypes, uint32_t numButtonTypes)
+{
+	if ( !joySticksInitialized )
+	{
+		for (unsigned i = 0; i < DriverStation::kJoystickPorts; i++)
+			joysticks[i] = NULL;
+		joySticksInitialized = true;
+	}
+	if (m_port >= DriverStation::kJoystickPorts) {
+		wpi_setWPIError(BadJoystickIndex);
+	} else {
+		joysticks[m_port] = this;
+	}
+
+	m_ds = DriverStation::GetInstance();
+	m_axes = new uint32_t[numAxisTypes];
+	m_buttons = new uint32_t[numButtonTypes];
+}
+
+Joystick * Joystick::GetStickForPort(uint32_t port)
+{
+	Joystick *stick = joysticks[port];
+	if (stick == NULL)
+	{
+		stick = new Joystick(port);
+		joysticks[port] = stick;
+	}
+	return stick;
+}
+
+Joystick::~Joystick()
+{
+	delete [] m_buttons;
+	delete [] m_axes;
+}
+
+/**
+ * Get the X value of the joystick.
+ * This depends on the mapping of the joystick connected to the current port.
+ */
+float Joystick::GetX(JoystickHand hand)
+{
+	return GetRawAxis(m_axes[kXAxis]);
+}
+
+/**
+ * Get the Y value of the joystick.
+ * This depends on the mapping of the joystick connected to the current port.
+ */
+float Joystick::GetY(JoystickHand hand)
+{
+	return GetRawAxis(m_axes[kYAxis]);
+}
+
+/**
+ * Get the Z value of the current joystick.
+ * This depends on the mapping of the joystick connected to the current port.
+ */
+float Joystick::GetZ()
+{
+	return GetRawAxis(m_axes[kZAxis]);
+}
+
+/**
+ * Get the twist value of the current joystick.
+ * This depends on the mapping of the joystick connected to the current port.
+ */
+float Joystick::GetTwist()
+{
+	return GetRawAxis(m_axes[kTwistAxis]);
+}
+
+/**
+ * Get the throttle value of the current joystick.
+ * This depends on the mapping of the joystick connected to the current port.
+ */
+float Joystick::GetThrottle()
+{
+	return GetRawAxis(m_axes[kThrottleAxis]);
+}
+
+/**
+ * Get the value of the axis.
+ *
+ * @param axis The axis to read, starting at 0.
+ * @return The value of the axis.
+ */
+float Joystick::GetRawAxis(uint32_t axis)
+{
+	return m_ds->GetStickAxis(m_port, axis);
+}
+
+/**
+ * For the current joystick, return the axis determined by the argument.
+ *
+ * This is for cases where the joystick axis is returned programatically, otherwise one of the
+ * previous functions would be preferable (for example GetX()).
+ *
+ * @param axis The axis to read.
+ * @return The value of the axis.
+ */
+float Joystick::GetAxis(AxisType axis)
+{
+	switch(axis)
+	{
+		case kXAxis: return this->GetX();
+		case kYAxis: return this->GetY();
+		case kZAxis: return this->GetZ();
+		case kTwistAxis: return this->GetTwist();
+		case kThrottleAxis: return this->GetThrottle();
+		default:
+			wpi_setWPIError(BadJoystickAxis);
+			return 0.0;
+	}
+}
+
+/**
+ * Read the state of the trigger on the joystick.
+ *
+ * Look up which button has been assigned to the trigger and read its state.
+ *
+ * @param hand This parameter is ignored for the Joystick class and is only here to complete the GenericHID interface.
+ * @return The state of the trigger.
+ */
+bool Joystick::GetTrigger(JoystickHand hand)
+{
+	return GetRawButton(m_buttons[kTriggerButton]);
+}
+
+/**
+ * Read the state of the top button on the joystick.
+ *
+ * Look up which button has been assigned to the top and read its state.
+ *
+ * @param hand This parameter is ignored for the Joystick class and is only here to complete the GenericHID interface.
+ * @return The state of the top button.
+ */
+bool Joystick::GetTop(JoystickHand hand)
+{
+	return GetRawButton(m_buttons[kTopButton]);
+}
+
+/**
+ * This is not supported for the Joystick.
+ * This method is only here to complete the GenericHID interface.
+ */
+bool Joystick::GetBumper(JoystickHand hand)
+{
+	// Joysticks don't have bumpers.
+	return false;
+}
+
+/**
+ * Get the button value (starting at button 1)
+ *
+ * The buttons are returned in a single 16 bit value with one bit representing the state
+ * of each button. The appropriate button is returned as a boolean value.
+ *
+ * @param button The button number to be read (starting at 1)
+ * @return The state of the button.
+ **/
+bool Joystick::GetRawButton(uint32_t button)
+{
+	return m_ds->GetStickButton(m_port, button);
+}
+
+/**
+ * Get the state of a POV on the joystick.
+ *
+ * @param pov The index of the POV to read (starting at 0)
+ * @return the angle of the POV in degrees, or -1 if the POV is not pressed.
+ */
+int Joystick::GetPOV(uint32_t pov) {
+	return m_ds->GetStickPOV(m_port, pov);
+}
+
+/**
+ * Get buttons based on an enumerated type.
+ *
+ * The button type will be looked up in the list of buttons and then read.
+ *
+ * @param button The type of button to read.
+ * @return The state of the button.
+ */
+bool Joystick::GetButton(ButtonType button)
+{
+	switch (button)
+	{
+	case kTriggerButton: return GetTrigger();
+	case kTopButton: return GetTop();
+	default:
+		return false;
+	}
+}
+
+/**
+ * Get the number of axis for a joystick
+ *
+ * @return the number of axis for the current joystick
+ */
+int Joystick::GetAxisCount()
+{
+    return m_ds->GetStickAxisCount(m_port);
+}
+
+/**
+  * Get the number of axis for a joystick
+  *
+* @return the number of buttons on the current joystick
+ */
+int Joystick::GetButtonCount()
+{
+    return m_ds->GetStickButtonCount(m_port);
+}
+
+/**
+ * Get the number of axis for a joystick
+ *
+ * @return then umber of POVs for the current joystick
+ */
+int Joystick::GetPOVCount()
+{
+    return m_ds->GetStickPOVCount(m_port);
+}
+
+
+/**
+ * Get the channel currently associated with the specified axis.
+ *
+ * @param axis The axis to look up the channel for.
+ * @return The channel fr the axis.
+ */
+uint32_t Joystick::GetAxisChannel(AxisType axis)
+{
+	return m_axes[axis];
+}
+
+/**
+ * Set the channel associated with a specified axis.
+ *
+ * @param axis The axis to set the channel for.
+ * @param channel The channel to set the axis to.
+ */
+void Joystick::SetAxisChannel(AxisType axis, uint32_t channel)
+{
+	m_axes[axis] = channel;
+}
+
+/**
+ * Get the magnitude of the direction vector formed by the joystick's
+ * current position relative to its origin
+ *
+ * @return The magnitude of the direction vector
+ */
+float Joystick::GetMagnitude(){
+	return sqrt(pow(GetX(),2) + pow(GetY(),2) );
+}
+
+/**
+ * Get the direction of the vector formed by the joystick and its origin
+ * in radians
+ *
+ * @return The direction of the vector in radians
+ */
+float Joystick::GetDirectionRadians(){
+	return atan2(GetX(), -GetY());
+}
+
+/**
+ * Get the direction of the vector formed by the joystick and its origin
+ * in degrees
+ *
+ * uses acos(-1) to represent Pi due to absence of readily accessible Pi
+ * constant in C++
+ *
+ * @return The direction of the vector in degrees
+ */
+float Joystick::GetDirectionDegrees(){
+	return (180/acos(-1))*GetDirectionRadians();
+}
+
+/**
+ * Set the rumble output for the joystick. The DS currently supports 2 rumble values,
+ * left rumble and right rumble
+ * @param type Which rumble value to set
+ * @param value The normalized value (0 to 1) to set the rumble to
+ */
+void Joystick::SetRumble(RumbleType type, float value) {
+	if (value < 0)
+		value = 0;
+	else if (value > 1)
+		value = 1;
+	if (type == kLeftRumble)
+		m_leftRumble = value*65535;
+	else
+		m_rightRumble = value*65535;
+	HALSetJoystickOutputs(m_port, m_outputs, m_leftRumble, m_rightRumble);
+}
+
+/**
+ * Set a single HID output value for the joystick.
+ * @param outputNumber The index of the output to set (1-32)
+ * @param value The value to set the output to
+ */
+	
+void Joystick::SetOutput(uint8_t outputNumber, bool value) {
+	m_outputs = (m_outputs & ~(1 << (outputNumber-1))) | (value << (outputNumber-1));
+
+	HALSetJoystickOutputs(m_port, m_outputs, m_leftRumble, m_rightRumble);
+}
+
+/**
+ * Set all HID output values for the joystick.
+ * @param value The 32 bit output value (1 bit for each output)
+ */
+void Joystick::SetOutputs(uint32_t value) {
+	m_outputs = value;
+	HALSetJoystickOutputs(m_port, m_outputs, m_leftRumble, m_rightRumble);
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/MotorSafetyHelper.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/MotorSafetyHelper.cpp
new file mode 100644
index 0000000..6bb7f48
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/MotorSafetyHelper.cpp
@@ -0,0 +1,156 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "MotorSafetyHelper.h"
+
+#include "DriverStation.h"
+#include "MotorSafety.h"
+#include "Timer.h"
+#include "WPIErrors.h"
+
+#include <stdio.h>
+
+MotorSafetyHelper *MotorSafetyHelper::m_headHelper = NULL;
+ReentrantMutex MotorSafetyHelper::m_listMutex;
+
+/**
+ * The constructor for a MotorSafetyHelper object.
+ * The helper object is constructed for every object that wants to implement the Motor
+ * Safety protocol. The helper object has the code to actually do the timing and call the
+ * motors Stop() method when the timeout expires. The motor object is expected to call the
+ * Feed() method whenever the motors value is updated.
+ * @param safeObject a pointer to the motor object implementing MotorSafety. This is used
+ * to call the Stop() method on the motor.
+ */
+MotorSafetyHelper::MotorSafetyHelper(MotorSafety *safeObject)
+{
+	m_safeObject = safeObject;
+	m_enabled = false;
+	m_expiration = DEFAULT_SAFETY_EXPIRATION;
+	m_stopTime = Timer::GetFPGATimestamp();
+
+	::std::unique_lock<ReentrantMutex> sync(m_listMutex);
+	m_nextHelper = m_headHelper;
+	m_headHelper = this;
+}
+
+
+MotorSafetyHelper::~MotorSafetyHelper()
+{
+	::std::unique_lock<ReentrantMutex> sync(m_listMutex);
+	if (m_headHelper == this)
+	{
+		m_headHelper = m_nextHelper;
+	}
+	else
+	{
+		MotorSafetyHelper *prev = NULL;
+		MotorSafetyHelper *cur = m_headHelper;
+		while (cur != this && cur != NULL)
+			prev = cur, cur = cur->m_nextHelper;
+		if (cur == this)
+			prev->m_nextHelper = cur->m_nextHelper;
+	}
+}
+
+/**
+ * Feed the motor safety object.
+ * Resets the timer on this object that is used to do the timeouts.
+ */
+void MotorSafetyHelper::Feed()
+{
+	::std::unique_lock<ReentrantMutex> sync(m_syncMutex);
+	m_stopTime = Timer::GetFPGATimestamp() + m_expiration;
+}
+
+/**
+ * Set the expiration time for the corresponding motor safety object.
+ * @param expirationTime The timeout value in seconds.
+ */
+void MotorSafetyHelper::SetExpiration(float expirationTime)
+{
+	::std::unique_lock<ReentrantMutex> sync(m_syncMutex);
+	m_expiration = expirationTime;
+}
+
+/**
+ * Retrieve the timeout value for the corresponding motor safety object.
+ * @return the timeout value in seconds.
+ */
+float MotorSafetyHelper::GetExpiration()
+{
+	::std::unique_lock<ReentrantMutex> sync(m_syncMutex);
+	return m_expiration;
+}
+
+/**
+ * Determine if the motor is still operating or has timed out.
+ * @return a true value if the motor is still operating normally and hasn't timed out.
+ */
+bool MotorSafetyHelper::IsAlive()
+{
+	::std::unique_lock<ReentrantMutex> sync(m_syncMutex);
+	return !m_enabled || m_stopTime > Timer::GetFPGATimestamp();
+}
+
+/**
+ * Check if this motor has exceeded its timeout.
+ * This method is called periodically to determine if this motor has exceeded its timeout
+ * value. If it has, the stop method is called, and the motor is shut down until its value is
+ * updated again.
+ */
+void MotorSafetyHelper::Check()
+{
+	DriverStation *ds = DriverStation::GetInstance();
+	if (!m_enabled || ds->IsDisabled() || ds->IsTest()) return;
+
+	::std::unique_lock<ReentrantMutex> sync(m_syncMutex);
+	if (m_stopTime < Timer::GetFPGATimestamp())
+	{
+		char buf[128];
+		char desc[64];
+		m_safeObject->GetDescription(desc);
+		snprintf(buf, 128, "%s... Output not updated often enough.", desc);
+		wpi_setWPIErrorWithContext(Timeout, buf);
+		m_safeObject->StopMotor();
+	}
+}
+
+/**
+ * Enable/disable motor safety for this device
+ * Turn on and off the motor safety option for this PWM object.
+ * @param enabled True if motor safety is enforced for this object
+ */
+void MotorSafetyHelper::SetSafetyEnabled(bool enabled)
+{
+	::std::unique_lock<ReentrantMutex> sync(m_syncMutex);
+	m_enabled = enabled;
+}
+
+/**
+ * Return the state of the motor safety enabled flag
+ * Return if the motor safety is currently enabled for this devicce.
+ * @return True if motor safety is enforced for this device
+ */
+bool MotorSafetyHelper::IsSafetyEnabled()
+{
+	::std::unique_lock<ReentrantMutex> sync(m_syncMutex);
+	return m_enabled;
+}
+
+/**
+ * Check the motors to see if any have timed out.
+ * This static  method is called periodically to poll all the motors and stop any that have
+ * timed out.
+ */
+void MotorSafetyHelper::CheckMotors()
+{
+	::std::unique_lock<ReentrantMutex> sync(m_listMutex);
+	for (MotorSafetyHelper *msh = m_headHelper; msh != NULL; msh = msh->m_nextHelper)
+	{
+		msh->Check();
+	}
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Notifier.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Notifier.cpp
new file mode 100644
index 0000000..70d6bf5
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Notifier.cpp
@@ -0,0 +1,265 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "Notifier.h"
+#include "Timer.h"
+#include "Utility.h"
+#include "WPIErrors.h"
+#include "HAL/HAL.hpp"
+
+Notifier *Notifier::timerQueueHead = NULL;
+ReentrantMutex Notifier::queueSemaphore;
+void* Notifier::m_notifier = NULL;
+int Notifier::refcount = 0;
+
+/**
+ * Create a Notifier for timer event notification.
+ * @param handler The handler is called at the notification time which is set
+ * using StartSingle or StartPeriodic.
+ */
+Notifier::Notifier(TimerEventHandler handler, void *param)
+{
+	if (handler == NULL)
+		wpi_setWPIErrorWithContext(NullParameter, "handler must not be NULL");
+	m_handler = handler;
+	m_param = param;
+	m_periodic = false;
+	m_expirationTime = 0;
+	m_period = 0;
+	m_nextEvent = NULL;
+	m_queued = false;
+	m_handlerSemaphore = initializeSemaphore(SEMAPHORE_FULL);
+	{
+		::std::unique_lock<ReentrantMutex> sync(queueSemaphore);
+		// do the first time intialization of static variables
+		if (refcount == 0)
+		{
+			int32_t status = 0;
+			m_notifier = initializeNotifier(ProcessQueue, &status);
+			wpi_setErrorWithContext(status, getHALErrorMessage(status));
+		}
+		refcount++;
+	}
+}
+
+/**
+ * Free the resources for a timer event.
+ * All resources will be freed and the timer event will be removed from the
+ * queue if necessary.
+ */
+Notifier::~Notifier()
+{
+	{
+		::std::unique_lock<ReentrantMutex> sync(queueSemaphore);
+		DeleteFromQueue();
+
+		// Delete the static variables when the last one is going away
+		if (!(--refcount))
+		{
+			int32_t status = 0;
+			cleanNotifier(m_notifier, &status);
+			wpi_setErrorWithContext(status, getHALErrorMessage(status));
+		}
+	}
+
+	// Acquire the semaphore; this makes certain that the handler is 
+	// not being executed by the interrupt manager.
+	takeSemaphore(m_handlerSemaphore);
+	// Delete while holding the semaphore so there can be no race.
+	deleteSemaphore(m_handlerSemaphore);
+}
+
+/**
+ * Update the alarm hardware to reflect the current first element in the queue.
+ * Compute the time the next alarm should occur based on the current time and the
+ * period for the first element in the timer queue.
+ * WARNING: this method does not do synchronization! It must be called from somewhere
+ * that is taking care of synchronizing access to the queue.
+ */
+void Notifier::UpdateAlarm()
+{
+	if (timerQueueHead != NULL)
+	{
+		int32_t status = 0;
+		updateNotifierAlarm(m_notifier, (uint32_t)(timerQueueHead->m_expirationTime * 1e6), &status);
+		wpi_setStaticErrorWithContext(timerQueueHead, status, getHALErrorMessage(status));
+	}
+}
+
+/**
+ * ProcessQueue is called whenever there is a timer interrupt.
+ * We need to wake up and process the current top item in the timer queue as long
+ * as its scheduled time is after the current time. Then the item is removed or 
+ * rescheduled (repetitive events) in the queue.
+ */
+void Notifier::ProcessQueue(uint32_t mask, void *params)
+{
+	Notifier *current;
+	while (true)				// keep processing past events until no more
+	{
+		{
+			::std::unique_lock<ReentrantMutex> sync(queueSemaphore);
+			double currentTime = GetClock();
+			current = timerQueueHead;
+			if (current == NULL || current->m_expirationTime > currentTime)
+			{
+				break;		// no more timer events to process
+			}
+			// need to process this entry
+			timerQueueHead = current->m_nextEvent;
+			if (current->m_periodic)
+			{
+				// if periodic, requeue the event
+				// compute when to put into queue
+				current->InsertInQueue(true);
+			}
+			else
+			{
+				// not periodic; removed from queue
+				current->m_queued = false;
+			}
+			// Take handler semaphore while holding queue semaphore to make sure
+			//  the handler will execute to completion in case we are being deleted.
+			takeSemaphore(current->m_handlerSemaphore);
+		}
+
+		current->m_handler(current->m_param);	// call the event handler
+		giveSemaphore(current->m_handlerSemaphore);
+	}
+	// reschedule the first item in the queue
+	::std::unique_lock<ReentrantMutex> sync(queueSemaphore);
+	UpdateAlarm();
+}
+
+/**
+ * Insert this Notifier into the timer queue in right place.
+ * WARNING: this method does not do synchronization! It must be called from somewhere
+ * that is taking care of synchronizing access to the queue.
+ * @param reschedule If false, the scheduled alarm is based on the current time and UpdateAlarm
+ * method is called which will enable the alarm if necessary.
+ * If true, update the time by adding the period (no drift) when rescheduled periodic from ProcessQueue.
+ * This ensures that the public methods only update the queue after finishing inserting.
+ */
+void Notifier::InsertInQueue(bool reschedule)
+{
+	if (reschedule)
+	{
+		m_expirationTime += m_period;
+	}
+	else
+	{
+		m_expirationTime = GetClock() + m_period;
+	}
+	if (m_expirationTime > Timer::kRolloverTime)
+	{
+		m_expirationTime -= Timer::kRolloverTime;
+	}
+	if (timerQueueHead == NULL || timerQueueHead->m_expirationTime >= this->m_expirationTime)
+	{
+		// the queue is empty or greater than the new entry
+		// the new entry becomes the first element
+		this->m_nextEvent = timerQueueHead;
+		timerQueueHead = this;
+		if (!reschedule)
+		{
+			// since the first element changed, update alarm, unless we already plan to
+			UpdateAlarm();
+		}
+	}
+	else
+	{
+		for (Notifier **npp = &(timerQueueHead->m_nextEvent); ; npp = &(*npp)->m_nextEvent)
+		{
+			Notifier *n = *npp;
+			if (n == NULL || n->m_expirationTime > this->m_expirationTime)
+			{
+				*npp = this;
+				this->m_nextEvent = n;
+				break;
+			}
+		}
+	}
+	m_queued = true;
+}
+
+/**
+ * Delete this Notifier from the timer queue.
+ * WARNING: this method does not do synchronization! It must be called from somewhere
+ * that is taking care of synchronizing access to the queue.
+ * Remove this Notifier from the timer queue and adjust the next interrupt time to reflect
+ * the current top of the queue.
+ */
+void Notifier::DeleteFromQueue()
+{
+	if (m_queued)
+	{
+		m_queued = false;
+		wpi_assert(timerQueueHead != NULL);
+		if (timerQueueHead == this)
+		{
+			// remove the first item in the list - update the alarm
+			timerQueueHead = this->m_nextEvent;
+			UpdateAlarm();
+		}
+		else
+		{
+			for (Notifier *n = timerQueueHead; n != NULL; n = n->m_nextEvent)
+			{
+				if (n->m_nextEvent == this)
+				{
+					// this element is the next element from *n from the queue
+					n->m_nextEvent = this->m_nextEvent;	// point around this one
+				}
+			}
+		}
+	}
+}
+
+/**
+ * Register for single event notification.
+ * A timer event is queued for a single event after the specified delay.
+ * @param delay Seconds to wait before the handler is called.
+ */
+void Notifier::StartSingle(double delay)
+{
+	::std::unique_lock<ReentrantMutex> sync(queueSemaphore);
+	m_periodic = false;
+	m_period = delay;
+	DeleteFromQueue();
+	InsertInQueue(false);
+}
+
+/**
+ * Register for periodic event notification.
+ * A timer event is queued for periodic event notification. Each time the interrupt
+ * occurs, the event will be immediately requeued for the same time interval.
+ * @param period Period in seconds to call the handler starting one period after the call to this method.
+ */
+void Notifier::StartPeriodic(double period)
+{
+	::std::unique_lock<ReentrantMutex> sync(queueSemaphore);
+	m_periodic = true;
+	m_period = period;
+	DeleteFromQueue();
+	InsertInQueue(false);
+}
+
+/**
+ * Stop timer events from occuring.
+ * Stop any repeating timer events from occuring. This will also remove any single
+ * notification events from the queue.
+ * If a timer-based call to the registered handler is in progress, this function will
+ * block until the handler call is complete.
+ */
+void Notifier::Stop()
+{
+	{
+		::std::unique_lock<ReentrantMutex> sync(queueSemaphore);
+		DeleteFromQueue();
+	}
+	// Wait for a currently executing handler to complete before returning from Stop()
+	Synchronized sync(m_handlerSemaphore);
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/PWM.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/PWM.cpp
new file mode 100644
index 0000000..8bb0f47
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/PWM.cpp
@@ -0,0 +1,363 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "PWM.h"
+
+//#include "NetworkCommunication/UsageReporting.h"
+#include "Resource.h"
+#include "Utility.h"
+#include "WPIErrors.h"
+#include "HAL/HAL.hpp"
+
+constexpr float PWM::kDefaultPwmPeriod;
+constexpr float PWM::kDefaultPwmCenter;
+const int32_t PWM::kDefaultPwmStepsDown;
+const int32_t PWM::kPwmDisabled;
+
+/**
+ * Initialize PWMs given a channel.
+ *
+ * This method is private and is the common path for all the constructors for creating PWM
+ * instances. Checks channel value range and allocates the appropriate channel.
+ * The allocation is only done to help users ensure that they don't double assign channels.
+ * @param channel The PWM channel number. 0-9 are on-board, 10-19 are on the MXP port
+ */
+void PWM::InitPWM(uint32_t channel)
+{
+	char buf[64];
+
+	if (!CheckPWMChannel(channel))
+	{
+		snprintf(buf, 64, "PWM Channel %d", channel);
+		wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf);
+		return;
+	}
+
+	int32_t status = 0;
+	allocatePWMChannel(m_pwm_ports[channel], &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+	m_channel = channel;
+
+	setPWM(m_pwm_ports[m_channel], kPwmDisabled, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+	m_eliminateDeadband = false;
+
+	HALReport(HALUsageReporting::kResourceType_PWM, channel);
+}
+
+/**
+ * Allocate a PWM given a channel number.
+ *
+ * @param channel The PWM channel.
+ */
+PWM::PWM(uint32_t channel)
+{
+	InitPWM(channel);
+}
+
+/**
+ * Free the PWM channel.
+ *
+ * Free the resource associated with the PWM channel and set the value to 0.
+ */
+PWM::~PWM()
+{
+	int32_t status = 0;
+
+	setPWM(m_pwm_ports[m_channel], kPwmDisabled, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+	freePWMChannel(m_pwm_ports[m_channel], &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Optionally eliminate the deadband from a speed controller.
+ * @param eliminateDeadband If true, set the motor curve on the Jaguar to eliminate
+ * the deadband in the middle of the range. Otherwise, keep the full range without
+ * modifying any values.
+ */
+void PWM::EnableDeadbandElimination(bool eliminateDeadband)
+{
+	if (StatusIsFatal()) return;
+	m_eliminateDeadband = eliminateDeadband;
+}
+
+/**
+ * Set the bounds on the PWM values.
+ * This sets the bounds on the PWM values for a particular each type of controller. The values
+ * determine the upper and lower speeds as well as the deadband bracket.
+ * @param max The Minimum pwm value
+ * @param deadbandMax The high end of the deadband range
+ * @param center The center speed (off)
+ * @param deadbandMin The low end of the deadband range
+ * @param min The minimum pwm value
+ */
+void PWM::SetBounds(int32_t max, int32_t deadbandMax, int32_t center, int32_t deadbandMin, int32_t min)
+{
+	if (StatusIsFatal()) return;
+	m_maxPwm = max;
+	m_deadbandMaxPwm = deadbandMax;
+	m_centerPwm = center;
+	m_deadbandMinPwm = deadbandMin;
+	m_minPwm = min;
+}
+
+
+/**
+ * Set the bounds on the PWM pulse widths.
+ * This sets the bounds on the PWM values for a particular type of controller. The values
+ * determine the upper and lower speeds as well as the deadband bracket.
+ * @param max The max PWM pulse width in ms
+ * @param deadbandMax The high end of the deadband range pulse width in ms
+ * @param center The center (off) pulse width in ms
+ * @param deadbandMin The low end of the deadband pulse width in ms
+ * @param min The minimum pulse width in ms
+ */
+void PWM::SetBounds(double max, double deadbandMax, double center, double deadbandMin, double min)
+{
+	// calculate the loop time in milliseconds
+	int32_t status = 0;
+	double loopTime = getLoopTiming(&status)/(kSystemClockTicksPerMicrosecond*1e3);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+	if (StatusIsFatal()) return;
+
+	m_maxPwm = (int32_t)((max-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
+	m_deadbandMaxPwm = (int32_t)((deadbandMax-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
+	m_centerPwm = (int32_t)((center-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
+	m_deadbandMinPwm = (int32_t)((deadbandMin-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
+	m_minPwm = (int32_t)((min-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
+}
+
+/**
+ * Set the PWM value based on a position.
+ *
+ * This is intended to be used by servos.
+ *
+ * @pre SetMaxPositivePwm() called.
+ * @pre SetMinNegativePwm() called.
+ *
+ * @param pos The position to set the servo between 0.0 and 1.0.
+ */
+void PWM::SetPosition(float pos)
+{
+	if (StatusIsFatal()) return;
+	if (pos < 0.0)
+	{
+		pos = 0.0;
+	}
+	else if (pos > 1.0)
+	{
+		pos = 1.0;
+	}
+
+	// note, need to perform the multiplication below as floating point before converting to int
+	unsigned short rawValue = (int32_t)( (pos * (float) GetFullRangeScaleFactor()) + GetMinNegativePwm());
+//	printf("MinNegPWM: %d FullRangeScaleFactor: %d Raw value: %5d   Input value: %4.4f\n", GetMinNegativePwm(), GetFullRangeScaleFactor(), rawValue, pos);
+
+//	wpi_assert((rawValue >= GetMinNegativePwm()) && (rawValue <= GetMaxPositivePwm()));
+	wpi_assert(rawValue != kPwmDisabled);
+
+	// send the computed pwm value to the FPGA
+	SetRaw((unsigned short)rawValue);
+}
+
+/**
+ * Get the PWM value in terms of a position.
+ *
+ * This is intended to be used by servos.
+ *
+ * @pre SetMaxPositivePwm() called.
+ * @pre SetMinNegativePwm() called.
+ *
+ * @return The position the servo is set to between 0.0 and 1.0.
+ */
+float PWM::GetPosition()
+{
+	if (StatusIsFatal()) return 0.0;
+	int32_t value = GetRaw();
+	if (value < GetMinNegativePwm())
+	{
+		return 0.0;
+	}
+	else if (value > GetMaxPositivePwm())
+	{
+		return 1.0;
+	}
+	else
+	{
+		return (float)(value - GetMinNegativePwm()) / (float)GetFullRangeScaleFactor();
+	}
+}
+
+/**
+ * Set the PWM value based on a speed.
+ *
+ * This is intended to be used by speed controllers.
+ *
+ * @pre SetMaxPositivePwm() called.
+ * @pre SetMinPositivePwm() called.
+ * @pre SetCenterPwm() called.
+ * @pre SetMaxNegativePwm() called.
+ * @pre SetMinNegativePwm() called.
+ *
+ * @param speed The speed to set the speed controller between -1.0 and 1.0.
+ */
+void PWM::SetSpeed(float speed)
+{
+	if (StatusIsFatal()) return;
+	// clamp speed to be in the range 1.0 >= speed >= -1.0
+	if (speed < -1.0)
+	{
+		speed = -1.0;
+	}
+	else if (speed > 1.0)
+	{
+		speed = 1.0;
+	}
+
+	// calculate the desired output pwm value by scaling the speed appropriately
+	int32_t rawValue;
+	if (speed == 0.0)
+	{
+		rawValue = GetCenterPwm();
+	}
+	else if (speed > 0.0)
+	{
+		rawValue = (int32_t)(speed * ((float)GetPositiveScaleFactor()) +
+									((float) GetMinPositivePwm()) + 0.5);
+	}
+	else
+	{
+		rawValue = (int32_t)(speed * ((float)GetNegativeScaleFactor()) +
+									((float) GetMaxNegativePwm()) + 0.5);
+	}
+
+	// the above should result in a pwm_value in the valid range
+	wpi_assert((rawValue >= GetMinNegativePwm()) && (rawValue <= GetMaxPositivePwm()));
+	wpi_assert(rawValue != kPwmDisabled);
+
+	// send the computed pwm value to the FPGA
+	SetRaw(rawValue);
+}
+
+/**
+ * Get the PWM value in terms of speed.
+ *
+ * This is intended to be used by speed controllers.
+ *
+ * @pre SetMaxPositivePwm() called.
+ * @pre SetMinPositivePwm() called.
+ * @pre SetMaxNegativePwm() called.
+ * @pre SetMinNegativePwm() called.
+ *
+ * @return The most recently set speed between -1.0 and 1.0.
+ */
+float PWM::GetSpeed()
+{
+	if (StatusIsFatal()) return 0.0;
+	int32_t value = GetRaw();
+	if (value == PWM::kPwmDisabled)
+	{
+		return 0.0;
+	}
+	else if (value > GetMaxPositivePwm())
+	{
+		return 1.0;
+	}
+	else if (value < GetMinNegativePwm())
+	{
+		return -1.0;
+	}
+	else if (value > GetMinPositivePwm())
+	{
+		return (float)(value - GetMinPositivePwm()) / (float)GetPositiveScaleFactor();
+	}
+	else if (value < GetMaxNegativePwm())
+	{
+		return (float)(value - GetMaxNegativePwm()) / (float)GetNegativeScaleFactor();
+	}
+	else
+	{
+		return 0.0;
+	}
+}
+
+/**
+ * Set the PWM value directly to the hardware.
+ *
+ * Write a raw value to a PWM channel.
+ *
+ * @param value Raw PWM value.
+ */
+void PWM::SetRaw(unsigned short value)
+{
+	if (StatusIsFatal()) return;
+
+	int32_t status = 0;
+	setPWM(m_pwm_ports[m_channel], value, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Get the PWM value directly from the hardware.
+ *
+ * Read a raw value from a PWM channel.
+ *
+ * @return Raw PWM control value.
+ */
+unsigned short PWM::GetRaw()
+{
+	if (StatusIsFatal()) return 0;
+
+	int32_t status = 0;
+	unsigned short value = getPWM(m_pwm_ports[m_channel], &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+	return value;
+}
+
+/**
+ * Slow down the PWM signal for old devices.
+ *
+ * @param mult The period multiplier to apply to this channel
+ */
+void PWM::SetPeriodMultiplier(PeriodMultiplier mult)
+{
+	if (StatusIsFatal()) return;
+
+	int32_t status = 0;
+
+	switch(mult)
+	{
+	case kPeriodMultiplier_4X:
+		setPWMPeriodScale(m_pwm_ports[m_channel], 3, &status); // Squelch 3 out of 4 outputs
+		break;
+	case kPeriodMultiplier_2X:
+		setPWMPeriodScale(m_pwm_ports[m_channel], 1, &status); // Squelch 1 out of 2 outputs
+		break;
+	case kPeriodMultiplier_1X:
+		setPWMPeriodScale(m_pwm_ports[m_channel], 0, &status); // Don't squelch any outputs
+		break;
+	default:
+		wpi_assert(false);
+	}
+
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+void PWM::SetZeroLatch()
+{
+	if (StatusIsFatal()) return;
+	
+	int32_t status = 0;
+	
+	latchPWMZero(m_pwm_ports[m_channel], &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/PowerDistributionPanel.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/PowerDistributionPanel.cpp
new file mode 100644
index 0000000..a7c40b3
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/PowerDistributionPanel.cpp
@@ -0,0 +1,153 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "PowerDistributionPanel.h"
+#include "WPIErrors.h"
+#include "HAL/PDP.hpp"
+
+/**
+ * Initialize the PDP.
+ */
+PowerDistributionPanel::PowerDistributionPanel() {
+}
+
+/**
+ * Query the input voltage of the PDP
+ * @return The voltage of the PDP in volts
+ */
+double
+PowerDistributionPanel::GetVoltage() {
+	int32_t status = 0;
+	
+	double voltage = getPDPVoltage(&status);
+	
+	if(status) {
+		wpi_setWPIErrorWithContext(Timeout, "");
+	}
+	
+	return voltage;
+}
+
+/**
+ * Query the temperature of the PDP
+ * @return The temperature of the PDP in degrees Celsius
+ */
+double
+PowerDistributionPanel::GetTemperature() {
+	int32_t status = 0;
+	
+	double temperature = getPDPTemperature(&status);
+	
+	if(status) {
+		wpi_setWPIErrorWithContext(Timeout, "");
+	}
+	
+	return temperature;
+}
+
+/**
+ * Query the current of a single channel of the PDP
+ * @return The current of one of the PDP channels (channels 0-15) in Amperes
+ */
+double
+PowerDistributionPanel::GetCurrent(uint8_t channel) {
+	int32_t status = 0;
+	
+	if(!CheckPDPChannel(channel))
+	{
+		char buf[64];
+		snprintf(buf, 64, "PDP Channel %d", channel);
+		wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf);
+	}
+	
+	double current = getPDPChannelCurrent(channel, &status);
+	
+	if(status) {
+		wpi_setWPIErrorWithContext(Timeout, "");
+	}
+	
+	return current;
+}
+
+/**
+ * Query the total current of all monitored PDP channels (0-15)
+ * @return The the total current drawn from the PDP channels in Amperes
+ */
+double
+PowerDistributionPanel::GetTotalCurrent() {
+	int32_t status = 0;
+	
+	double current = getPDPTotalCurrent(&status);
+	
+	if(status) {
+		wpi_setWPIErrorWithContext(Timeout, "");
+	}
+	
+	return current;
+}
+
+/**
+ * Query the total power drawn from the monitored PDP channels
+ * @return The the total power drawn from the PDP channels in Watts
+ */
+double
+PowerDistributionPanel::GetTotalPower() {
+	int32_t status = 0;
+	
+	double power = getPDPTotalPower(&status);
+	
+	if(status) {
+		wpi_setWPIErrorWithContext(Timeout, "");
+	}
+	
+	return power;
+}
+
+/**
+ * Query the total energy drawn from the monitored PDP channels
+ * @return The the total energy drawn from the PDP channels in Joules
+ */
+double
+PowerDistributionPanel::GetTotalEnergy() {
+	int32_t status = 0;
+	
+	double energy = getPDPTotalEnergy(&status);
+	
+	if(status) {
+		wpi_setWPIErrorWithContext(Timeout, "");
+	}
+	
+	return energy;
+}
+
+/**
+ * Reset the total energy drawn from the PDP
+ * @see PowerDistributionPanel#GetTotalEnergy
+ */
+void
+PowerDistributionPanel::ResetTotalEnergy() { 
+	int32_t status = 0;
+	
+	resetPDPTotalEnergy(&status);
+	
+	if(status) {
+		wpi_setWPIErrorWithContext(Timeout, "");
+	}
+}
+
+/**
+ * Remove all of the fault flags on the PDP
+ */
+void
+PowerDistributionPanel::ClearStickyFaults() {
+	int32_t status = 0;
+	
+	clearPDPStickyFaults(&status);
+	
+	if(status) {
+		wpi_setWPIErrorWithContext(Timeout, "");
+	}
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Relay.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Relay.cpp
new file mode 100644
index 0000000..6b3b50c
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Relay.cpp
@@ -0,0 +1,210 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code	*/
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "Relay.h"
+
+//#include "NetworkCommunication/UsageReporting.h"
+#include "Resource.h"
+#include "WPIErrors.h"
+#include "HAL/HAL.hpp"
+
+// Allocate each direction separately.
+static Resource *relayChannels = NULL;
+
+/**
+ * Common relay initialization method.
+ * This code is common to all Relay constructors and initializes the relay and reserves
+ * all resources that need to be locked. Initially the relay is set to both lines at 0v.
+ */
+void Relay::InitRelay()
+{
+	char buf[64];
+	Resource::CreateResourceObject(&relayChannels, dio_kNumSystems * kRelayChannels * 2);
+	if (!SensorBase::CheckRelayChannel(m_channel))
+	{
+		snprintf(buf, 64, "Relay Channel %d", m_channel);
+		wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf);
+		return;
+	}
+
+	if (m_direction == kBothDirections || m_direction == kForwardOnly)
+	{
+		snprintf(buf, 64, "Forward Relay %d", m_channel);
+		if (relayChannels->Allocate(m_channel * 2, buf) == ~0ul)
+		{
+			CloneError(relayChannels);
+			return;
+		}
+
+		HALReport(HALUsageReporting::kResourceType_Relay, m_channel);
+	}
+	if (m_direction == kBothDirections || m_direction == kReverseOnly)
+	{
+		snprintf(buf, 64, "Reverse Relay %d", m_channel);
+		if (relayChannels->Allocate(m_channel * 2 + 1, buf) == ~0ul)
+		{
+			CloneError(relayChannels);
+			return;
+		}
+
+		HALReport(HALUsageReporting::kResourceType_Relay, m_channel + 128);
+	}
+
+	int32_t status = 0;
+	setRelayForward(m_relay_ports[m_channel], false, &status);
+	setRelayReverse(m_relay_ports[m_channel], false, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+}
+
+/**
+ * Relay constructor given a channel.
+ * @param channel The channel number (0-3).
+ * @param direction The direction that the Relay object will control.
+ */
+Relay::Relay(uint32_t channel, Relay::Direction direction)
+	: m_channel (channel)
+	, m_direction (direction)
+{
+	InitRelay();
+}
+
+/**
+ * Free the resource associated with a relay.
+ * The relay channels are set to free and the relay output is turned off.
+ */
+Relay::~Relay()
+{
+
+	int32_t status = 0;
+	setRelayForward(m_relay_ports[m_channel], false, &status);
+	setRelayReverse(m_relay_ports[m_channel], false, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+	if (m_direction == kBothDirections || m_direction == kForwardOnly)
+	{
+		relayChannels->Free(m_channel * 2);
+	}
+	if (m_direction == kBothDirections || m_direction == kReverseOnly)
+	{
+		relayChannels->Free(m_channel * 2 + 1);
+	}
+}
+
+/**
+ * Set the relay state.
+ *
+ * Valid values depend on which directions of the relay are controlled by the object.
+ *
+ * When set to kBothDirections, the relay can be any of the four states:
+ *	 0v-0v, 0v-12v, 12v-0v, 12v-12v
+ *
+ * When set to kForwardOnly or kReverseOnly, you can specify the constant for the
+ *	 direction or you can simply specify kOff and kOn.  Using only kOff and kOn is
+ *	 recommended.
+ *
+ * @param value The state to set the relay.
+ */
+void Relay::Set(Relay::Value value)
+{
+	if (StatusIsFatal()) return;
+
+	int32_t status = 0;
+
+	switch (value)
+	{
+	case kOff:
+		if (m_direction == kBothDirections || m_direction == kForwardOnly)
+		{
+			setRelayForward(m_relay_ports[m_channel], false, &status);
+		}
+		if (m_direction == kBothDirections || m_direction == kReverseOnly)
+		{
+			setRelayReverse(m_relay_ports[m_channel], false, &status);
+		}
+		break;
+	case kOn:
+		if (m_direction == kBothDirections || m_direction == kForwardOnly)
+		{
+			setRelayForward(m_relay_ports[m_channel], true, &status);
+		}
+		if (m_direction == kBothDirections || m_direction == kReverseOnly)
+		{
+			setRelayReverse(m_relay_ports[m_channel], true, &status);
+		}
+		break;
+	case kForward:
+		if (m_direction == kReverseOnly)
+		{
+			wpi_setWPIError(IncompatibleMode);
+			break;
+		}
+		if (m_direction == kBothDirections || m_direction == kForwardOnly)
+		{
+			setRelayForward(m_relay_ports[m_channel], true, &status);
+		}
+		if (m_direction == kBothDirections)
+		{
+			setRelayReverse(m_relay_ports[m_channel], false, &status);
+		}
+		break;
+	case kReverse:
+		if (m_direction == kForwardOnly)
+		{
+			wpi_setWPIError(IncompatibleMode);
+			break;
+		}
+		if (m_direction == kBothDirections)
+		{
+			setRelayForward(m_relay_ports[m_channel], false, &status);
+		}
+		if (m_direction == kBothDirections || m_direction == kReverseOnly)
+		{
+			setRelayReverse(m_relay_ports[m_channel], true, &status);
+		}
+		break;
+	}
+
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Get the Relay State
+ *
+ * Gets the current state of the relay.
+ *
+ * When set to kForwardOnly or kReverseOnly, value is returned as kOn/kOff not
+ * kForward/kReverse (per the recommendation in Set)
+ *
+ * @return The current state of the relay as a Relay::Value
+ */
+Relay::Value Relay::Get() {
+	int32_t status;
+
+	if(getRelayForward(m_relay_ports[m_channel], &status)) {
+		if(getRelayReverse(m_relay_ports[m_channel], &status)) {
+			return kOn;
+		} else {
+			if(m_direction == kForwardOnly) {
+				return kOn;
+			} else {
+			return kForward;
+			}
+		}
+	} else {
+		if(getRelayReverse(m_relay_ports[m_channel], &status)) {
+			if(m_direction == kReverseOnly) {
+				return kOn;
+			} else {
+			return kReverse;
+			}
+		} else {
+			return kOff;
+		}
+	}
+
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/RobotBase.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/RobotBase.cpp
new file mode 100644
index 0000000..4b2c435
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/RobotBase.cpp
@@ -0,0 +1,166 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "RobotBase.h"
+
+#include "DriverStation.h"
+//#include "NetworkCommunication/FRCComm.h"
+//#include "NetworkCommunication/symModuleLink.h"
+//#include "NetworkCommunication/UsageReporting.h"
+#include "RobotState.h"
+#include "HLUsageReporting.h"
+#include "Internal/HardwareHLReporting.h"
+#include "Utility.h"
+#include <cstring>
+#include "HAL/HAL.hpp"
+#include <cstdio>
+
+#ifdef __vxworks
+// VXWorks needs som special unloading code
+#include <moduleLib.h>
+#include <unldLib.h>
+#include <taskLib.h>
+#endif
+
+RobotBase* RobotBase::m_instance = NULL;
+
+void RobotBase::setInstance(RobotBase* robot)
+{
+	wpi_assert(m_instance == NULL);
+	m_instance = robot;
+}
+
+RobotBase &RobotBase::getInstance()
+{
+	return *m_instance;
+}
+
+void RobotBase::robotSetup(RobotBase *robot)
+{
+	robot->Prestart();
+	robot->StartCompetition();
+}
+
+/**
+ * Constructor for a generic robot program.
+ * User code should be placed in the constructor that runs before the Autonomous or Operator
+ * Control period starts. The constructor will run to completion before Autonomous is entered.
+ *
+ * This must be used to ensure that the communications code starts. In the future it would be
+ * nice to put this code into it's own task that loads on boot so ensure that it runs.
+ */
+RobotBase::RobotBase()
+	: m_task (NULL)
+	, m_ds (NULL)
+{
+	m_ds = DriverStation::GetInstance();
+	RobotState::SetImplementation(DriverStation::GetInstance()); \
+	HLUsageReporting::SetImplementation(new HardwareHLReporting()); \
+
+	RobotBase::setInstance(this);
+	
+	FILE *file = NULL;
+	file = fopen("/tmp/frc_versions/FRC_Lib_Version.ini", "w");
+
+	fputs("2015 C++ 1.0.0 - modified by FRC Team 971 Spartan Robotics", file);
+	if (file != NULL)
+	fclose(file);
+}
+
+/**
+ * Free the resources for a RobotBase class.
+ * This includes deleting all classes that might have been allocated as Singletons to they
+ * would never be deleted except here.
+ */
+RobotBase::~RobotBase()
+{
+	SensorBase::DeleteSingletons();
+	delete m_task;
+	m_task = NULL;
+	m_instance = NULL;
+}
+
+/**
+ * Determine if the Robot is currently enabled.
+ * @return True if the Robot is currently enabled by the field controls.
+ */
+bool RobotBase::IsEnabled()
+{
+	return m_ds->IsEnabled();
+}
+
+/**
+ * Determine if the Robot is currently disabled.
+ * @return True if the Robot is currently disabled by the field controls.
+ */
+bool RobotBase::IsDisabled()
+{
+	return m_ds->IsDisabled();
+}
+
+/**
+ * Determine if the robot is currently in Autonomous mode.
+ * @return True if the robot is currently operating Autonomously as determined by the field controls.
+ */
+bool RobotBase::IsAutonomous()
+{
+	return m_ds->IsAutonomous();
+}
+
+/**
+ * Determine if the robot is currently in Operator Control mode.
+ * @return True if the robot is currently operating in Tele-Op mode as determined by the field controls.
+ */
+bool RobotBase::IsOperatorControl()
+{
+	return m_ds->IsOperatorControl();
+}
+
+/**
+ * Determine if the robot is currently in Test mode.
+ * @return True if the robot is currently running tests as determined by the field controls.
+ */
+bool RobotBase::IsTest()
+{
+    return m_ds->IsTest();
+}
+
+/**
+ * This hook is called right before startCompetition(). By default, tell the DS that the robot is now ready to
+ * be enabled. If you don't want for the robot to be enabled yet, you can override this method to do nothing.
+ * If you do so, you will need to call HALNetworkCommunicationObserveUserProgramStarting() from your code when
+ * you are ready for the robot to be enabled.
+ */
+void RobotBase::Prestart()
+{
+	HALNetworkCommunicationObserveUserProgramStarting();
+}
+
+/**
+ * Indicates if new data is available from the driver station.
+ * @return Has new data arrived over the network since the last time this function was called?
+ */
+bool RobotBase::IsNewDataAvailable()
+{
+	return m_ds->IsNewControlData();
+}
+
+/**
+ * This class exists for the sole purpose of getting its destructor called when the module unloads.
+ * Before the module is done unloading, we need to delete the RobotBase derived singleton.  This should delete
+ * the other remaining singletons that were registered.  This should also stop all tasks that are using
+ * the Task class.
+ */
+class RobotDeleter
+{
+public:
+	RobotDeleter() {}
+	~RobotDeleter()
+	{
+		delete &RobotBase::getInstance();
+	}
+};
+static RobotDeleter g_robotDeleter;
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/RobotDrive.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/RobotDrive.cpp
new file mode 100644
index 0000000..3eb90ff
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/RobotDrive.cpp
@@ -0,0 +1,752 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "RobotDrive.h"
+
+#include "CANJaguar.h"
+#include "GenericHID.h"
+#include "Joystick.h"
+#include "Talon.h"
+//#include "NetworkCommunication/UsageReporting.h"
+#include "Utility.h"
+#include "WPIErrors.h"
+#include <math.h>
+
+#undef max
+#include <algorithm>
+
+const int32_t RobotDrive::kMaxNumberOfMotors;
+
+/*
+ * Driving functions
+ * These functions provide an interface to multiple motors that is used for C programming
+ * The Drive(speed, direction) function is the main part of the set that makes it easy
+ * to set speeds and direction independently in one call.
+ */
+
+/**
+ * Common function to initialize all the robot drive constructors.
+ * Create a motor safety object (the real reason for the common code) and
+ * initialize all the motor assignments. The default timeout is set for the robot drive.
+ */
+void RobotDrive::InitRobotDrive() {
+	m_frontLeftMotor = NULL;
+	m_frontRightMotor = NULL;
+	m_rearRightMotor = NULL;
+	m_rearLeftMotor = NULL;
+	m_sensitivity = 0.5;
+	m_maxOutput = 1.0;
+	m_safetyHelper = new MotorSafetyHelper(this);
+	m_safetyHelper->SetSafetyEnabled(true);
+	m_syncGroup = 0;
+}
+
+/** 
+ * Constructor for RobotDrive with 2 motors specified with channel numbers.
+ * Set up parameters for a two wheel drive system where the
+ * left and right motor pwm channels are specified in the call.
+ * This call assumes Talons for controlling the motors.
+ * @param leftMotorChannel The PWM channel number that drives the left motor. 0-9 are on-board, 10-19 are on the MXP port
+ * @param rightMotorChannel The PWM channel number that drives the right motor. 0-9 are on-board, 10-19 are on the MXP port
+ */
+RobotDrive::RobotDrive(uint32_t leftMotorChannel, uint32_t rightMotorChannel)
+{
+	InitRobotDrive();
+	m_rearLeftMotor = new Talon(leftMotorChannel);
+	m_rearRightMotor = new Talon(rightMotorChannel);
+	for (int32_t i=0; i < kMaxNumberOfMotors; i++)
+	{
+		m_invertedMotors[i] = 1;
+	}
+	SetLeftRightMotorOutputs(0.0, 0.0);
+	m_deleteSpeedControllers = true;
+}
+
+/**
+ * Constructor for RobotDrive with 4 motors specified with channel numbers.
+ * Set up parameters for a four wheel drive system where all four motor
+ * pwm channels are specified in the call.
+ * This call assumes Talons for controlling the motors.
+ * @param frontLeftMotor Front left motor channel number. 0-9 are on-board, 10-19 are on the MXP port
+ * @param rearLeftMotor Rear Left motor channel number. 0-9 are on-board, 10-19 are on the MXP port
+ * @param frontRightMotor Front right motor channel number. 0-9 are on-board, 10-19 are on the MXP port
+ * @param rearRightMotor Rear Right motor channel number. 0-9 are on-board, 10-19 are on the MXP port
+ */
+RobotDrive::RobotDrive(uint32_t frontLeftMotor, uint32_t rearLeftMotor,
+		uint32_t frontRightMotor, uint32_t rearRightMotor)
+{
+	InitRobotDrive();
+	m_rearLeftMotor = new Talon(rearLeftMotor);
+	m_rearRightMotor = new Talon(rearRightMotor);
+	m_frontLeftMotor = new Talon(frontLeftMotor);
+	m_frontRightMotor = new Talon(frontRightMotor);
+	for (int32_t i=0; i < kMaxNumberOfMotors; i++)
+	{
+		m_invertedMotors[i] = 1;
+	}
+	SetLeftRightMotorOutputs(0.0, 0.0);
+	m_deleteSpeedControllers = true;
+}
+
+/**
+ * Constructor for RobotDrive with 2 motors specified as SpeedController objects.
+ * The SpeedController version of the constructor enables programs to use the RobotDrive classes with
+ * subclasses of the SpeedController objects, for example, versions with ramping or reshaping of
+ * the curve to suit motor bias or deadband elimination.
+ * @param leftMotor The left SpeedController object used to drive the robot. 
+ * @param rightMotor the right SpeedController object used to drive the robot.
+ */
+RobotDrive::RobotDrive(SpeedController *leftMotor, SpeedController *rightMotor)
+{
+	InitRobotDrive();
+	if (leftMotor == NULL || rightMotor == NULL)
+	{
+		wpi_setWPIError(NullParameter);
+		m_rearLeftMotor = m_rearRightMotor = NULL;
+		return;
+	}
+	m_rearLeftMotor = leftMotor;
+	m_rearRightMotor = rightMotor;
+	for (int32_t i=0; i < kMaxNumberOfMotors; i++)
+	{
+		m_invertedMotors[i] = 1;
+	}
+	m_deleteSpeedControllers = false;
+}
+
+RobotDrive::RobotDrive(SpeedController &leftMotor, SpeedController &rightMotor)
+{
+	InitRobotDrive();
+	m_rearLeftMotor = &leftMotor;
+	m_rearRightMotor = &rightMotor;
+	for (int32_t i=0; i < kMaxNumberOfMotors; i++)
+	{
+		m_invertedMotors[i] = 1;
+	}
+	m_deleteSpeedControllers = false;
+}
+
+/**
+ * Constructor for RobotDrive with 4 motors specified as SpeedController objects.
+ * Speed controller input version of RobotDrive (see previous comments).
+ * @param rearLeftMotor The back left SpeedController object used to drive the robot.
+ * @param frontLeftMotor The front left SpeedController object used to drive the robot
+ * @param rearRightMotor The back right SpeedController object used to drive the robot.
+ * @param frontRightMotor The front right SpeedController object used to drive the robot.
+ */
+RobotDrive::RobotDrive(SpeedController *frontLeftMotor, SpeedController *rearLeftMotor,
+						SpeedController *frontRightMotor, SpeedController *rearRightMotor)
+{
+	InitRobotDrive();
+	if (frontLeftMotor == NULL || rearLeftMotor == NULL || frontRightMotor == NULL || rearRightMotor == NULL)
+	{
+		wpi_setWPIError(NullParameter);
+		return;
+	}
+	m_frontLeftMotor = frontLeftMotor;
+	m_rearLeftMotor = rearLeftMotor;
+	m_frontRightMotor = frontRightMotor;
+	m_rearRightMotor = rearRightMotor;
+	for (int32_t i=0; i < kMaxNumberOfMotors; i++)
+	{
+		m_invertedMotors[i] = 1;
+	}
+	m_deleteSpeedControllers = false;
+}
+
+RobotDrive::RobotDrive(SpeedController &frontLeftMotor, SpeedController &rearLeftMotor,
+						SpeedController &frontRightMotor, SpeedController &rearRightMotor)
+{
+	InitRobotDrive();
+	m_frontLeftMotor = &frontLeftMotor;
+	m_rearLeftMotor = &rearLeftMotor;
+	m_frontRightMotor = &frontRightMotor;
+	m_rearRightMotor = &rearRightMotor;
+	for (int32_t i=0; i < kMaxNumberOfMotors; i++)
+	{
+		m_invertedMotors[i] = 1;
+	}
+	m_deleteSpeedControllers = false;
+}
+
+/**
+ * RobotDrive destructor.
+ * Deletes motor objects that were not passed in and created internally only.
+ **/
+RobotDrive::~RobotDrive()
+{
+	if (m_deleteSpeedControllers)
+	{
+		delete m_frontLeftMotor;
+		delete m_rearLeftMotor;
+		delete m_frontRightMotor;
+		delete m_rearRightMotor;
+	}
+	delete m_safetyHelper;
+}
+
+/**
+ * Drive the motors at "speed" and "curve".
+ *
+ * The speed and curve are -1.0 to +1.0 values where 0.0 represents stopped and
+ * not turning. The algorithm for adding in the direction attempts to provide a constant
+ * turn radius for differing speeds.
+ *
+ * This function will most likely be used in an autonomous routine.
+ *
+ * @param outputMagnitude The forward component of the output magnitude to send to the motors.
+ * @param curve The rate of turn, constant for different forward speeds.
+ */
+void RobotDrive::Drive(float outputMagnitude, float curve)
+{
+	float leftOutput, rightOutput;
+	static bool reported = false;
+	if (!reported)
+	{
+		HALReport(HALUsageReporting::kResourceType_RobotDrive, GetNumMotors(), HALUsageReporting::kRobotDrive_ArcadeRatioCurve);
+		reported = true;
+	}
+
+	if (curve < 0)
+	{
+		float value = log(-curve);
+		float ratio = (value - m_sensitivity)/(value + m_sensitivity);
+		if (ratio == 0) ratio =.0000000001;
+		leftOutput = outputMagnitude / ratio;
+		rightOutput = outputMagnitude;
+	}
+	else if (curve > 0)
+	{
+		float value = log(curve);
+		float ratio = (value - m_sensitivity)/(value + m_sensitivity);
+		if (ratio == 0) ratio =.0000000001;
+		leftOutput = outputMagnitude;
+		rightOutput = outputMagnitude / ratio;
+	}
+	else
+	{
+		leftOutput = outputMagnitude;
+		rightOutput = outputMagnitude;
+	}
+	SetLeftRightMotorOutputs(leftOutput, rightOutput);
+}
+
+/**
+ * Provide tank steering using the stored robot configuration.
+ * Drive the robot using two joystick inputs. The Y-axis will be selected from
+ * each Joystick object.
+ * @param leftStick The joystick to control the left side of the robot.
+ * @param rightStick The joystick to control the right side of the robot.
+ */
+void RobotDrive::TankDrive(GenericHID *leftStick, GenericHID *rightStick, bool squaredInputs)
+{
+	if (leftStick == NULL || rightStick == NULL)
+	{
+		wpi_setWPIError(NullParameter);
+		return;
+	}
+	TankDrive(leftStick->GetY(), rightStick->GetY(), squaredInputs);
+}
+
+void RobotDrive::TankDrive(GenericHID &leftStick, GenericHID &rightStick, bool squaredInputs)
+{
+	TankDrive(leftStick.GetY(), rightStick.GetY(), squaredInputs);
+}
+
+/**
+ * Provide tank steering using the stored robot configuration.
+ * This function lets you pick the axis to be used on each Joystick object for the left
+ * and right sides of the robot.
+ * @param leftStick The Joystick object to use for the left side of the robot.
+ * @param leftAxis The axis to select on the left side Joystick object.
+ * @param rightStick The Joystick object to use for the right side of the robot.
+ * @param rightAxis The axis to select on the right side Joystick object.
+ */
+void RobotDrive::TankDrive(GenericHID *leftStick, uint32_t leftAxis,
+		GenericHID *rightStick, uint32_t rightAxis, bool squaredInputs)
+{
+	if (leftStick == NULL || rightStick == NULL)
+	{
+		wpi_setWPIError(NullParameter);
+		return;
+	}
+	TankDrive(leftStick->GetRawAxis(leftAxis), rightStick->GetRawAxis(rightAxis), squaredInputs);
+}
+
+void RobotDrive::TankDrive(GenericHID &leftStick, uint32_t leftAxis,
+		GenericHID &rightStick, uint32_t rightAxis, bool squaredInputs)
+{
+	TankDrive(leftStick.GetRawAxis(leftAxis), rightStick.GetRawAxis(rightAxis), squaredInputs);
+}
+
+
+/**
+ * Provide tank steering using the stored robot configuration.
+ * This function lets you directly provide joystick values from any source.
+ * @param leftValue The value of the left stick.
+ * @param rightValue The value of the right stick.
+ */
+void RobotDrive::TankDrive(float leftValue, float rightValue, bool squaredInputs)
+{
+	static bool reported = false;
+	if (!reported)
+	{
+		HALReport(HALUsageReporting::kResourceType_RobotDrive, GetNumMotors(), HALUsageReporting::kRobotDrive_Tank);
+		reported = true;
+	}
+
+	// square the inputs (while preserving the sign) to increase fine control while permitting full power
+	leftValue = Limit(leftValue);
+	rightValue = Limit(rightValue);
+	if(squaredInputs)
+	{
+		if (leftValue >= 0.0)
+		{
+			leftValue = (leftValue * leftValue);
+		}
+		else
+		{
+			leftValue = -(leftValue * leftValue);
+		}
+		if (rightValue >= 0.0)
+		{
+			rightValue = (rightValue * rightValue);
+		}
+		else
+		{
+			rightValue = -(rightValue * rightValue);
+		}
+	}
+
+	SetLeftRightMotorOutputs(leftValue, rightValue);
+}
+
+/**
+ * Arcade drive implements single stick driving.
+ * Given a single Joystick, the class assumes the Y axis for the move value and the X axis
+ * for the rotate value.
+ * (Should add more information here regarding the way that arcade drive works.)
+ * @param stick The joystick to use for Arcade single-stick driving. The Y-axis will be selected
+ * for forwards/backwards and the X-axis will be selected for rotation rate.
+ * @param squaredInputs If true, the sensitivity will be increased for small values
+ */
+void RobotDrive::ArcadeDrive(GenericHID *stick, bool squaredInputs)
+{
+	// simply call the full-featured ArcadeDrive with the appropriate values
+	ArcadeDrive(stick->GetY(), stick->GetX(), squaredInputs);
+}
+
+/**
+ * Arcade drive implements single stick driving.
+ * Given a single Joystick, the class assumes the Y axis for the move value and the X axis
+ * for the rotate value.
+ * (Should add more information here regarding the way that arcade drive works.)
+ * @param stick The joystick to use for Arcade single-stick driving. The Y-axis will be selected
+ * for forwards/backwards and the X-axis will be selected for rotation rate.
+ * @param squaredInputs If true, the sensitivity will be increased for small values
+ */
+void RobotDrive::ArcadeDrive(GenericHID &stick, bool squaredInputs)
+{
+	// simply call the full-featured ArcadeDrive with the appropriate values
+	ArcadeDrive(stick.GetY(), stick.GetX(), squaredInputs);
+}
+
+/**
+ * Arcade drive implements single stick driving.
+ * Given two joystick instances and two axis, compute the values to send to either two
+ * or four motors.
+ * @param moveStick The Joystick object that represents the forward/backward direction
+ * @param moveAxis The axis on the moveStick object to use for fowards/backwards (typically Y_AXIS)
+ * @param rotateStick The Joystick object that represents the rotation value
+ * @param rotateAxis The axis on the rotation object to use for the rotate right/left (typically X_AXIS)
+ * @param squaredInputs Setting this parameter to true increases the sensitivity at lower speeds
+ */
+void RobotDrive::ArcadeDrive(GenericHID* moveStick, uint32_t moveAxis,
+								GenericHID* rotateStick, uint32_t rotateAxis,
+								bool squaredInputs)
+{
+	float moveValue = moveStick->GetRawAxis(moveAxis);
+	float rotateValue = rotateStick->GetRawAxis(rotateAxis);
+
+	ArcadeDrive(moveValue, rotateValue, squaredInputs);
+}
+
+/**
+ * Arcade drive implements single stick driving.
+ * Given two joystick instances and two axis, compute the values to send to either two
+ * or four motors.
+ * @param moveStick The Joystick object that represents the forward/backward direction
+ * @param moveAxis The axis on the moveStick object to use for fowards/backwards (typically Y_AXIS)
+ * @param rotateStick The Joystick object that represents the rotation value
+ * @param rotateAxis The axis on the rotation object to use for the rotate right/left (typically X_AXIS)
+ * @param squaredInputs Setting this parameter to true increases the sensitivity at lower speeds
+ */
+
+void RobotDrive::ArcadeDrive(GenericHID &moveStick, uint32_t moveAxis,
+								GenericHID &rotateStick, uint32_t rotateAxis,
+								bool squaredInputs)
+{
+	float moveValue = moveStick.GetRawAxis(moveAxis);
+	float rotateValue = rotateStick.GetRawAxis(rotateAxis);
+
+	ArcadeDrive(moveValue, rotateValue, squaredInputs);
+}
+
+/**
+ * Arcade drive implements single stick driving.
+ * This function lets you directly provide joystick values from any source.
+ * @param moveValue The value to use for fowards/backwards
+ * @param rotateValue The value to use for the rotate right/left
+ * @param squaredInputs If set, increases the sensitivity at low speeds
+ */
+void RobotDrive::ArcadeDrive(float moveValue, float rotateValue, bool squaredInputs)
+{
+	static bool reported = false;
+	if (!reported)
+	{
+		HALReport(HALUsageReporting::kResourceType_RobotDrive, GetNumMotors(), HALUsageReporting::kRobotDrive_ArcadeStandard);
+		reported = true;
+	}
+
+	// local variables to hold the computed PWM values for the motors
+	float leftMotorOutput;
+	float rightMotorOutput;
+
+	moveValue = Limit(moveValue);
+	rotateValue = Limit(rotateValue);
+
+	if (squaredInputs)
+	{
+		// square the inputs (while preserving the sign) to increase fine control while permitting full power
+		if (moveValue >= 0.0)
+		{
+			moveValue = (moveValue * moveValue);
+		}
+		else
+		{
+			moveValue = -(moveValue * moveValue);
+		}
+		if (rotateValue >= 0.0)
+		{
+			rotateValue = (rotateValue * rotateValue);
+		}
+		else
+		{
+			rotateValue = -(rotateValue * rotateValue);
+		}
+	}
+
+	if (moveValue > 0.0)
+	{
+		if (rotateValue > 0.0)
+		{
+			leftMotorOutput = moveValue - rotateValue;
+			rightMotorOutput = std::max(moveValue, rotateValue);
+		}
+		else
+		{
+			leftMotorOutput = std::max(moveValue, -rotateValue);
+			rightMotorOutput = moveValue + rotateValue;
+		}
+	}
+	else
+	{
+		if (rotateValue > 0.0)
+		{
+			leftMotorOutput = - std::max(-moveValue, rotateValue);
+			rightMotorOutput = moveValue + rotateValue;
+		}
+		else
+		{
+			leftMotorOutput = moveValue - rotateValue;
+			rightMotorOutput = - std::max(-moveValue, -rotateValue);
+		}
+	}
+	SetLeftRightMotorOutputs(leftMotorOutput, rightMotorOutput);
+}
+
+/**
+ * Drive method for Mecanum wheeled robots.
+ *
+ * A method for driving with Mecanum wheeled robots. There are 4 wheels
+ * on the robot, arranged so that the front and back wheels are toed in 45 degrees.
+ * When looking at the wheels from the top, the roller axles should form an X across the robot.
+ *
+ * This is designed to be directly driven by joystick axes.
+ *
+ * @param x The speed that the robot should drive in the X direction. [-1.0..1.0]
+ * @param y The speed that the robot should drive in the Y direction.
+ * This input is inverted to match the forward == -1.0 that joysticks produce. [-1.0..1.0]
+ * @param rotation The rate of rotation for the robot that is completely independent of
+ * the translation. [-1.0..1.0]
+ * @param gyroAngle The current angle reading from the gyro.  Use this to implement field-oriented controls.
+ */
+void RobotDrive::MecanumDrive_Cartesian(float x, float y, float rotation, float gyroAngle)
+{
+	static bool reported = false;
+	if (!reported)
+	{
+		HALReport(HALUsageReporting::kResourceType_RobotDrive, GetNumMotors(), HALUsageReporting::kRobotDrive_MecanumCartesian);
+		reported = true;
+	}
+
+	double xIn = x;
+	double yIn = y;
+	// Negate y for the joystick.
+	yIn = -yIn;
+	// Compenstate for gyro angle.
+	RotateVector(xIn, yIn, gyroAngle);
+
+	double wheelSpeeds[kMaxNumberOfMotors];
+	wheelSpeeds[kFrontLeftMotor] = xIn + yIn + rotation;
+	wheelSpeeds[kFrontRightMotor] = -xIn + yIn - rotation;
+	wheelSpeeds[kRearLeftMotor] = -xIn + yIn + rotation;
+	wheelSpeeds[kRearRightMotor] = xIn + yIn - rotation;
+
+	Normalize(wheelSpeeds);
+
+	m_frontLeftMotor->Set(wheelSpeeds[kFrontLeftMotor] * m_invertedMotors[kFrontLeftMotor] * m_maxOutput, m_syncGroup);
+	m_frontRightMotor->Set(wheelSpeeds[kFrontRightMotor] * m_invertedMotors[kFrontRightMotor] * m_maxOutput, m_syncGroup);
+	m_rearLeftMotor->Set(wheelSpeeds[kRearLeftMotor] * m_invertedMotors[kRearLeftMotor] * m_maxOutput, m_syncGroup);
+	m_rearRightMotor->Set(wheelSpeeds[kRearRightMotor] * m_invertedMotors[kRearRightMotor] * m_maxOutput, m_syncGroup);
+
+	if (m_syncGroup != 0)
+	{
+		CANJaguar::UpdateSyncGroup(m_syncGroup);
+	}
+
+	m_safetyHelper->Feed();
+}
+
+/**
+ * Drive method for Mecanum wheeled robots.
+ *
+ * A method for driving with Mecanum wheeled robots. There are 4 wheels
+ * on the robot, arranged so that the front and back wheels are toed in 45 degrees.
+ * When looking at the wheels from the top, the roller axles should form an X across the robot.
+ *
+ * @param magnitude The speed that the robot should drive in a given direction. [-1.0..1.0]
+ * @param direction The direction the robot should drive in degrees. The direction and maginitute are
+ * independent of the rotation rate.
+ * @param rotation The rate of rotation for the robot that is completely independent of
+ * the magnitute or direction. [-1.0..1.0]
+ */
+void RobotDrive::MecanumDrive_Polar(float magnitude, float direction, float rotation)
+{
+	static bool reported = false;
+	if (!reported)
+	{
+		HALReport(HALUsageReporting::kResourceType_RobotDrive, GetNumMotors(), HALUsageReporting::kRobotDrive_MecanumPolar);
+		reported = true;
+	}
+
+	// Normalized for full power along the Cartesian axes.
+	magnitude = Limit(magnitude) * sqrt(2.0);
+	// The rollers are at 45 degree angles.
+	double dirInRad = (direction + 45.0) * 3.14159 / 180.0;
+	double cosD = cos(dirInRad);
+	double sinD = sin(dirInRad);
+
+	double wheelSpeeds[kMaxNumberOfMotors];
+	wheelSpeeds[kFrontLeftMotor] = sinD * magnitude + rotation;
+	wheelSpeeds[kFrontRightMotor] = cosD * magnitude - rotation;
+	wheelSpeeds[kRearLeftMotor] = cosD * magnitude + rotation;
+	wheelSpeeds[kRearRightMotor] = sinD * magnitude - rotation;
+
+	Normalize(wheelSpeeds);
+
+	m_frontLeftMotor->Set(wheelSpeeds[kFrontLeftMotor] * m_invertedMotors[kFrontLeftMotor] * m_maxOutput, m_syncGroup);
+	m_frontRightMotor->Set(wheelSpeeds[kFrontRightMotor] * m_invertedMotors[kFrontRightMotor] * m_maxOutput, m_syncGroup);
+	m_rearLeftMotor->Set(wheelSpeeds[kRearLeftMotor] * m_invertedMotors[kRearLeftMotor] * m_maxOutput, m_syncGroup);
+	m_rearRightMotor->Set(wheelSpeeds[kRearRightMotor] * m_invertedMotors[kRearRightMotor] * m_maxOutput, m_syncGroup);
+
+	if (m_syncGroup != 0)
+	{
+		CANJaguar::UpdateSyncGroup(m_syncGroup);
+	}
+
+	m_safetyHelper->Feed();
+}
+
+/**
+ * Holonomic Drive method for Mecanum wheeled robots.
+ *
+ * This is an alias to MecanumDrive_Polar() for backward compatability
+ *
+ * @param magnitude The speed that the robot should drive in a given direction.  [-1.0..1.0]
+ * @param direction The direction the robot should drive. The direction and maginitute are
+ * independent of the rotation rate.
+ * @param rotation The rate of rotation for the robot that is completely independent of
+ * the magnitute or direction.  [-1.0..1.0]
+ */
+void RobotDrive::HolonomicDrive(float magnitude, float direction, float rotation)
+{
+	MecanumDrive_Polar(magnitude, direction, rotation);
+}
+
+/** Set the speed of the right and left motors.
+ * This is used once an appropriate drive setup function is called such as
+ * TwoWheelDrive(). The motors are set to "leftOutput" and "rightOutput"
+ * and includes flipping the direction of one side for opposing motors.
+ * @param leftOutput The speed to send to the left side of the robot.
+ * @param rightOutput The speed to send to the right side of the robot.
+ */
+void RobotDrive::SetLeftRightMotorOutputs(float leftOutput, float rightOutput)
+{
+	wpi_assert(m_rearLeftMotor != NULL && m_rearRightMotor != NULL);
+
+	if (m_frontLeftMotor != NULL)
+		m_frontLeftMotor->Set(Limit(leftOutput) * m_invertedMotors[kFrontLeftMotor] * m_maxOutput, m_syncGroup);
+	m_rearLeftMotor->Set(Limit(leftOutput) * m_invertedMotors[kRearLeftMotor] * m_maxOutput, m_syncGroup);
+
+	if (m_frontRightMotor != NULL)
+		m_frontRightMotor->Set(-Limit(rightOutput) * m_invertedMotors[kFrontRightMotor] * m_maxOutput, m_syncGroup);
+	m_rearRightMotor->Set(-Limit(rightOutput) * m_invertedMotors[kRearRightMotor] * m_maxOutput, m_syncGroup);
+
+	if (m_syncGroup != 0)
+	{
+		CANJaguar::UpdateSyncGroup(m_syncGroup);
+	}
+
+	m_safetyHelper->Feed();
+}
+
+/**
+ * Limit motor values to the -1.0 to +1.0 range.
+ */
+float RobotDrive::Limit(float num)
+{
+	if (num > 1.0)
+	{
+		return 1.0;
+	}
+	if (num < -1.0)
+	{
+		return -1.0;
+	}
+	return num;
+}
+
+/**
+ * Normalize all wheel speeds if the magnitude of any wheel is greater than 1.0.
+ */
+void RobotDrive::Normalize(double *wheelSpeeds)
+{
+	double maxMagnitude = fabs(wheelSpeeds[0]);
+	int32_t i;
+	for (i=1; i<kMaxNumberOfMotors; i++)
+	{
+		double temp = fabs(wheelSpeeds[i]);
+		if (maxMagnitude < temp) maxMagnitude = temp;
+	}
+	if (maxMagnitude > 1.0)
+	{
+		for (i=0; i<kMaxNumberOfMotors; i++)
+		{
+			wheelSpeeds[i] = wheelSpeeds[i] / maxMagnitude;
+		}
+	}
+}
+
+/**
+ * Rotate a vector in Cartesian space.
+ */
+void RobotDrive::RotateVector(double &x, double &y, double angle)
+{
+	double cosA = cos(angle * (3.14159 / 180.0));
+	double sinA = sin(angle * (3.14159 / 180.0));
+	double xOut = x * cosA - y * sinA;
+	double yOut = x * sinA + y * cosA;
+	x = xOut;
+	y = yOut;
+}
+
+/*
+ * Invert a motor direction.
+ * This is used when a motor should run in the opposite direction as the drive
+ * code would normally run it. Motors that are direct drive would be inverted, the
+ * Drive code assumes that the motors are geared with one reversal.
+ * @param motor The motor index to invert.
+ * @param isInverted True if the motor should be inverted when operated.
+ */
+void RobotDrive::SetInvertedMotor(MotorType motor, bool isInverted)
+{
+	if (motor < 0 || motor > 3)
+	{
+		wpi_setWPIError(InvalidMotorIndex);
+		return;
+	}
+	m_invertedMotors[motor] = isInverted ? -1 : 1;
+}
+
+/**
+ * Set the turning sensitivity.
+ *
+ * This only impacts the Drive() entry-point.
+ * @param sensitivity Effectively sets the turning sensitivity (or turn radius for a given value)
+ */
+void RobotDrive::SetSensitivity(float sensitivity)
+{
+	m_sensitivity = sensitivity;
+}
+
+/**
+ * Configure the scaling factor for using RobotDrive with motor controllers in a mode other than PercentVbus.
+ * @param maxOutput Multiplied with the output percentage computed by the drive functions.
+ */
+void RobotDrive::SetMaxOutput(double maxOutput)
+{
+	m_maxOutput = maxOutput;
+}
+
+/**
+ * Set the number of the sync group for the motor controllers.  If the motor controllers are {@link CANJaguar}s,
+ * then they will all be added to this sync group, causing them to update their values at the same time.
+ *
+ * @param syncGroup the update group to add the motor controllers to
+ */
+void RobotDrive::SetCANJaguarSyncGroup(uint8_t syncGroup) {
+	m_syncGroup = syncGroup;
+}
+
+void RobotDrive::SetExpiration(float timeout)
+{
+	m_safetyHelper->SetExpiration(timeout);
+}
+
+float RobotDrive::GetExpiration()
+{
+	return m_safetyHelper->GetExpiration();
+}
+
+bool RobotDrive::IsAlive()
+{
+	return m_safetyHelper->IsAlive();
+}
+
+bool RobotDrive::IsSafetyEnabled()
+{
+	return m_safetyHelper->IsSafetyEnabled();
+}
+
+void RobotDrive::SetSafetyEnabled(bool enabled)
+{
+	m_safetyHelper->SetSafetyEnabled(enabled);
+}
+
+void RobotDrive::GetDescription(char *desc)
+{
+	sprintf(desc, "RobotDrive");
+}
+
+void RobotDrive::StopMotor()
+{
+	if (m_frontLeftMotor != NULL) m_frontLeftMotor->Disable();
+	if (m_frontRightMotor != NULL) m_frontRightMotor->Disable();
+	if (m_rearLeftMotor != NULL) m_rearLeftMotor->Disable();
+	if (m_rearRightMotor != NULL) m_rearRightMotor->Disable();
+	m_safetyHelper->Feed();
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/SPI.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/SPI.cpp
new file mode 100644
index 0000000..4878dd9
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/SPI.cpp
@@ -0,0 +1,185 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "SPI.h"
+
+#include "WPIErrors.h"
+#include "HAL/Digital.hpp"
+
+#include <string.h>
+
+
+/**
+ * Constructor
+ *
+ * @param SPIport the physical SPI port
+ */
+SPI::SPI(Port SPIport)
+{
+	m_port = SPIport;
+  	int32_t status = 0;
+  	spiInitialize(m_port, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+
+	static int32_t instances = 0;
+	instances++;
+	HALReport(HALUsageReporting::kResourceType_SPI, instances);
+}
+
+/**
+ * Destructor.
+ */
+SPI::~SPI()
+{
+	spiClose(m_port);
+}
+
+/**
+ * Configure the rate of the generated clock signal.
+ * 
+ * The default value is 500,000Hz.
+ * The maximum value is 4,000,000Hz.
+ *
+ * @param hz	The clock rate in Hertz.
+ */
+void SPI::SetClockRate(double hz)
+{
+	spiSetSpeed(m_port, hz);
+}
+
+/**
+ * Configure the order that bits are sent and received on the wire
+ * to be most significant bit first.
+ */
+void SPI::SetMSBFirst()
+{
+	m_msbFirst = true;
+	spiSetOpts(m_port, (int) m_msbFirst, (int) m_sampleOnTrailing, (int) m_clk_idle_high);
+}
+
+/**
+ * Configure the order that bits are sent and received on the wire
+ * to be least significant bit first.
+ */
+void SPI::SetLSBFirst()
+{
+	m_msbFirst = false;
+	spiSetOpts(m_port, (int) m_msbFirst, (int) m_sampleOnTrailing, (int) m_clk_idle_high);
+}
+
+/**
+ * Configure that the data is stable on the falling edge and the data
+ * changes on the rising edge.
+ */
+void SPI::SetSampleDataOnFalling()
+{
+	m_sampleOnTrailing = true;
+	spiSetOpts(m_port, (int) m_msbFirst, (int) m_sampleOnTrailing, (int) m_clk_idle_high);
+}
+
+/**
+ * Configure that the data is stable on the rising edge and the data
+ * changes on the falling edge.
+ */
+void SPI::SetSampleDataOnRising()
+{
+	m_sampleOnTrailing = false;
+	spiSetOpts(m_port, (int) m_msbFirst, (int) m_sampleOnTrailing, (int) m_clk_idle_high);
+}
+
+/**
+ * Configure the clock output line to be active low.
+ * This is sometimes called clock polarity high or clock idle high.
+ */
+void SPI::SetClockActiveLow()
+{
+	m_clk_idle_high = true;
+	spiSetOpts(m_port, (int) m_msbFirst, (int) m_sampleOnTrailing, (int) m_clk_idle_high);
+}
+
+/**
+ * Configure the clock output line to be active high.
+ * This is sometimes called clock polarity low or clock idle low.
+ */
+void SPI::SetClockActiveHigh()
+{
+	m_clk_idle_high = false;
+	spiSetOpts(m_port, (int) m_msbFirst, (int) m_sampleOnTrailing, (int) m_clk_idle_high);
+}
+
+/**
+ * Configure the chip select line to be active high.
+ */
+void SPI::SetChipSelectActiveHigh()
+{
+	int32_t status = 0;
+	spiSetChipSelectActiveHigh(m_port, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Configure the chip select line to be active low.
+ */
+void SPI::SetChipSelectActiveLow()
+{
+	int32_t status = 0;
+	spiSetChipSelectActiveLow(m_port, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+
+/**
+ * Write data to the slave device.  Blocks until there is space in the
+ * output FIFO.
+ *
+ * If not running in output only mode, also saves the data received
+ * on the MISO input during the transfer into the receive FIFO.
+ */
+int32_t SPI::Write(uint8_t* data, uint8_t size)
+{
+	int32_t retVal = 0;
+	retVal = spiWrite(m_port, data, size);
+	return retVal;
+}
+
+/**
+ * Read a word from the receive FIFO.
+ *
+ * Waits for the current transfer to complete if the receive FIFO is empty.
+ *
+ * If the receive FIFO is empty, there is no active transfer, and initiate
+ * is false, errors.
+ *
+ * @param initiate	If true, this function pushes "0" into the
+ *				    transmit buffer and initiates a transfer.
+ *				    If false, this function assumes that data is
+ *				    already in the receive FIFO from a previous write.
+ */
+int32_t SPI::Read(bool initiate, uint8_t* dataReceived, uint8_t size)
+{
+	int32_t retVal = 0;
+	if(initiate){
+		uint8_t* dataToSend = new uint8_t[size];
+		memset(dataToSend, 0, size);
+		retVal = spiTransaction(m_port, dataToSend, dataReceived, size);
+	}
+	else
+		retVal = spiRead(m_port, dataReceived, size);
+	return retVal;
+}
+
+/**
+ * Perform a simultaneous read/write transaction with the device
+ *
+ * @param dataToSend The data to be written out to the device
+ * @param dataReceived Buffer to receive data from the device
+ * @param size The length of the transaction, in bytes
+ */
+int32_t SPI::Transaction(uint8_t* dataToSend, uint8_t* dataReceived, uint8_t size){
+	int32_t retVal = 0;
+	retVal = spiTransaction(m_port, dataToSend, dataReceived, size);
+	return retVal;
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/SafePWM.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/SafePWM.cpp
new file mode 100644
index 0000000..289d5fe
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/SafePWM.cpp
@@ -0,0 +1,106 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "SafePWM.h"
+
+#include "MotorSafetyHelper.h"
+
+/**
+ * Initialize a SafePWM object by setting defaults
+ */
+void SafePWM::InitSafePWM()
+{
+	m_safetyHelper = new MotorSafetyHelper(this);
+	m_safetyHelper->SetSafetyEnabled(false);
+}
+
+/**
+ * Constructor for a SafePWM object taking a channel number.
+ * @param channel The PWM channel number 0-9 are on-board, 10-19 are on the MXP port
+ */
+SafePWM::SafePWM(uint32_t channel): PWM(channel)
+{
+	InitSafePWM();
+}
+
+SafePWM::~SafePWM()
+{
+	delete m_safetyHelper;
+}
+
+/**
+ * Set the expiration time for the PWM object
+ * @param timeout The timeout (in seconds) for this motor object
+ */
+void SafePWM::SetExpiration(float timeout)
+{
+	m_safetyHelper->SetExpiration(timeout);
+}
+
+/**
+ * Return the expiration time for the PWM object.
+ * @returns The expiration time value.
+ */
+float SafePWM::GetExpiration()
+{
+	return m_safetyHelper->GetExpiration();
+}
+
+/**
+ * Check if the PWM object is currently alive or stopped due to a timeout.
+ * @returns a bool value that is true if the motor has NOT timed out and should still
+ * be running.
+ */
+bool SafePWM::IsAlive()
+{
+	return m_safetyHelper->IsAlive();
+}
+
+/**
+ * Stop the motor associated with this PWM object.
+ * This is called by the MotorSafetyHelper object when it has a timeout for this PWM and needs to
+ * stop it from running.
+ */
+void SafePWM::StopMotor()
+{
+	SetRaw(kPwmDisabled);
+}
+
+/**
+ * Enable/disable motor safety for this device
+ * Turn on and off the motor safety option for this PWM object.
+ * @param enabled True if motor safety is enforced for this object
+ */
+void SafePWM::SetSafetyEnabled(bool enabled)
+{
+	m_safetyHelper->SetSafetyEnabled(enabled);
+}
+
+/**
+ * Check if motor safety is enabled for this object
+ * @returns True if motor safety is enforced for this object
+ */
+bool SafePWM::IsSafetyEnabled()
+{
+	return m_safetyHelper->IsSafetyEnabled();
+}
+
+void SafePWM::GetDescription(char *desc)
+{
+	sprintf(desc, "PWM %d", GetChannel());
+}
+
+/**
+ * Feed the MotorSafety timer when setting the speed.
+ * This method is called by the subclass motor whenever it updates its speed, thereby reseting
+ * the timeout value.
+ * @param speed Value to pass to the PWM class
+ */
+void SafePWM::SetSpeed(float speed)
+{
+	PWM::SetSpeed(speed);
+	m_safetyHelper->Feed();
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/SensorBase.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/SensorBase.cpp
new file mode 100644
index 0000000..d403b14
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/SensorBase.cpp
@@ -0,0 +1,202 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "SensorBase.h"
+
+#include "NetworkCommunication/LoadOut.h"
+#include "WPIErrors.h"
+#include "HAL/HAL.hpp"
+
+const uint32_t SensorBase::kDigitalChannels;
+const uint32_t SensorBase::kAnalogInputs;
+const uint32_t SensorBase::kSolenoidChannels;
+const uint32_t SensorBase::kSolenoidModules;
+const uint32_t SensorBase::kPwmChannels;
+const uint32_t SensorBase::kRelayChannels;
+const uint32_t SensorBase::kPDPChannels;
+const uint32_t SensorBase::kChassisSlots;
+SensorBase *SensorBase::m_singletonList = NULL;
+
+static bool portsInitialized = false;
+void* SensorBase::m_digital_ports[kDigitalChannels];
+void* SensorBase::m_relay_ports[kRelayChannels];
+void* SensorBase::m_pwm_ports[kPwmChannels];
+
+/**
+ * Creates an instance of the sensor base and gets an FPGA handle
+ */
+SensorBase::SensorBase()
+{
+	if(!portsInitialized) {
+		for (uint32_t i = 0; i < kDigitalChannels; i++)
+		{
+			void* port = getPort(i);
+			int32_t status = 0;
+			m_digital_ports[i] = initializeDigitalPort(port, &status);
+			wpi_setErrorWithContext(status, getHALErrorMessage(status));
+		}
+
+		for (uint32_t i = 0; i < kRelayChannels; i++)
+		{
+			void* port = getPort(i);
+			int32_t status = 0;
+			m_relay_ports[i] = initializeDigitalPort(port, &status);
+			wpi_setErrorWithContext(status, getHALErrorMessage(status));
+		}
+
+		for (uint32_t i = 0; i < kPwmChannels; i++)
+		{
+			void* port = getPort(i);
+			int32_t status = 0;
+			m_pwm_ports[i] = initializeDigitalPort(port, &status);
+			wpi_setErrorWithContext(status, getHALErrorMessage(status));
+		}
+	}
+}
+
+/**
+ * Frees the resources for a SensorBase.
+ */
+SensorBase::~SensorBase()
+{
+}
+
+/**
+ * Add sensor to the singleton list.
+ * Add this sensor to the list of singletons that need to be deleted when
+ * the robot program exits. Each of the sensors on this list are singletons,
+ * that is they aren't allocated directly with new, but instead are allocated
+ * by the static GetInstance method. As a result, they are never deleted when
+ * the program exits. Consequently these sensors may still be holding onto
+ * resources and need to have their destructors called at the end of the program.
+ */
+void SensorBase::AddToSingletonList()
+{
+	m_nextSingleton = m_singletonList;
+	m_singletonList = this;
+}
+
+/**
+ * Delete all the singleton classes on the list.
+ * All the classes that were allocated as singletons need to be deleted so
+ * their resources can be freed.
+ */
+void SensorBase::DeleteSingletons()
+{
+	for (SensorBase *next = m_singletonList; next != NULL;)
+	{
+		SensorBase *tmp = next;
+		next = next->m_nextSingleton;
+		delete tmp;
+	}
+	m_singletonList = NULL;
+}
+
+/**
+ * Check that the solenoid module number is valid.
+ *
+ * @return Solenoid module is valid and present
+ */
+bool SensorBase::CheckSolenoidModule(uint8_t moduleNumber)
+{
+	if (moduleNumber < 64)
+		return true;
+	return false;
+}
+
+/**
+ * Check that the digital channel number is valid.
+ * Verify that the channel number is one of the legal channel numbers. Channel numbers are
+ * 1-based.
+ *
+ * @return Digital channel is valid
+ */
+bool SensorBase::CheckDigitalChannel(uint32_t channel)
+{
+	if (channel < kDigitalChannels)
+		return true;
+	return false;
+}
+
+/**
+ * Check that the digital channel number is valid.
+ * Verify that the channel number is one of the legal channel numbers. Channel numbers are
+ * 1-based.
+ *
+ * @return Relay channel is valid
+ */
+bool SensorBase::CheckRelayChannel(uint32_t channel)
+{
+	if (channel < kRelayChannels)
+		return true;
+	return false;
+}
+
+/**
+ * Check that the digital channel number is valid.
+ * Verify that the channel number is one of the legal channel numbers. Channel numbers are
+ * 1-based.
+ *
+ * @return PWM channel is valid
+ */
+bool SensorBase::CheckPWMChannel(uint32_t channel)
+{
+	if (channel < kPwmChannels)
+		return true;
+	return false;
+}
+
+/**
+ * Check that the analog input number is value.
+ * Verify that the analog input number is one of the legal channel numbers. Channel numbers
+ * are 0-based.
+ *
+ * @return Analog channel is valid
+ */
+bool SensorBase::CheckAnalogInput(uint32_t channel)
+{
+	if (channel < kAnalogInputs)
+		return true;
+	return false;
+}
+
+/**
+ * Check that the analog output number is valid.
+ * Verify that the analog output number is one of the legal channel numbers. Channel numbers
+ * are 0-based.
+ *
+ * @return Analog channel is valid
+ */
+bool SensorBase::CheckAnalogOutput(uint32_t channel)
+{
+	if (channel < kAnalogOutputs)
+		return true;
+	return false;
+}
+
+/**
+ * Verify that the solenoid channel number is within limits.
+ *
+ * @return Solenoid channel is valid
+ */
+bool SensorBase::CheckSolenoidChannel(uint32_t channel)
+{
+	if (channel < kSolenoidChannels)
+		return true;
+	return false;
+}
+
+/**
+ * Verify that the power distribution channel number is within limits.
+ *
+ * @return PDP channel is valid
+ */
+bool SensorBase::CheckPDPChannel(uint32_t channel)
+{
+	if (channel < kPDPChannels)
+		return true;
+	return false;
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Servo.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Servo.cpp
new file mode 100644
index 0000000..d9a3dcd
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Servo.cpp
@@ -0,0 +1,111 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "Servo.h"
+
+//#include "NetworkCommunication/UsageReporting.h"
+
+constexpr float Servo::kMaxServoAngle;
+constexpr float Servo::kMinServoAngle;
+
+constexpr float Servo::kDefaultMaxServoPWM;
+constexpr float Servo::kDefaultMinServoPWM;
+
+/**
+ * Common initialization code called by all constructors.
+ *
+ * InitServo() assigns defaults for the period multiplier for the servo PWM control signal, as
+ * well as the minimum and maximum PWM values supported by the servo.
+ */
+void Servo::InitServo()
+{
+	SetBounds(kDefaultMaxServoPWM, 0.0, 0.0, 0.0, kDefaultMinServoPWM);
+	SetPeriodMultiplier(kPeriodMultiplier_4X);
+
+	HALReport(HALUsageReporting::kResourceType_Servo, GetChannel());
+}
+
+/**
+ * @param channel The PWM channel to which the servo is attached. 0-9 are on-board, 10-19 are on the MXP port
+ */
+Servo::Servo(uint32_t channel) : SafePWM(channel)
+{
+	InitServo();
+//	printf("Done initializing servo %d\n", channel);
+}
+
+Servo::~Servo()
+{
+}
+
+/**
+ * Set the servo position.
+ *
+ * Servo values range from 0.0 to 1.0 corresponding to the range of full left to full right.
+ *
+ * @param value Position from 0.0 to 1.0.
+ */
+void Servo::Set(float value)
+{
+	SetPosition(value);
+}
+
+/**
+ * Set the servo to offline.
+ *
+ * Set the servo raw value to 0 (undriven)
+ */
+void Servo::SetOffline() {
+	SetRaw(0);
+}
+
+/**
+ * Get the servo position.
+ *
+ * Servo values range from 0.0 to 1.0 corresponding to the range of full left to full right.
+ *
+ * @return Position from 0.0 to 1.0.
+ */
+float Servo::Get()
+{
+	return GetPosition();
+}
+
+/**
+ * Set the servo angle.
+ *
+ * Assume that the servo angle is linear with respect to the PWM value (big assumption, need to test).
+ *
+ * Servo angles that are out of the supported range of the servo simply "saturate" in that direction
+ * In other words, if the servo has a range of (X degrees to Y degrees) than angles of less than X
+ * result in an angle of X being set and angles of more than Y degrees result in an angle of Y being set.
+ *
+ * @param degrees The angle in degrees to set the servo.
+ */
+void Servo::SetAngle(float degrees)
+{
+	if (degrees < kMinServoAngle)
+	{
+		degrees = kMinServoAngle;
+	}
+	else if (degrees > kMaxServoAngle)
+	{
+		degrees = kMaxServoAngle;
+	}
+
+	SetPosition(((float) (degrees - kMinServoAngle)) / GetServoAngleRange());
+}
+
+/**
+ * Get the servo angle.
+ *
+ * Assume that the servo angle is linear with respect to the PWM value (big assumption, need to test).
+ * @return The angle in degrees to which the servo is set.
+ */
+float Servo::GetAngle()
+{
+	return (float)GetPosition() * GetServoAngleRange() + kMinServoAngle;
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Solenoid.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Solenoid.cpp
new file mode 100644
index 0000000..1ef3d7a
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Solenoid.cpp
@@ -0,0 +1,115 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "Solenoid.h"
+//#include "NetworkCommunication/UsageReporting.h"
+#include "WPIErrors.h"
+
+/**
+ * Common function to implement constructor behavior.
+ */
+void Solenoid::InitSolenoid()
+{
+	char buf[64];
+	if (!CheckSolenoidModule(m_moduleNumber))
+	{
+		snprintf(buf, 64, "Solenoid Module %d", m_moduleNumber);
+		wpi_setWPIErrorWithContext(ModuleIndexOutOfRange, buf);
+		return;
+	}
+	if (!CheckSolenoidChannel(m_channel))
+	{
+		snprintf(buf, 64, "Solenoid Channel %d", m_channel);
+		wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf);
+		return;
+	}
+	Resource::CreateResourceObject(&m_allocated, kSolenoidChannels * 63);
+
+	snprintf(buf, 64, "Solenoid %d (Module: %d)", m_channel, m_moduleNumber);
+	if (m_allocated->Allocate(m_moduleNumber * kSolenoidChannels + m_channel, buf) == ~0ul)
+	{
+		CloneError(m_allocated);
+		return;
+	}
+
+	HALReport(HALUsageReporting::kResourceType_Solenoid, m_channel, m_moduleNumber);
+}
+
+/**
+ * Constructor using the default PCM ID (0).
+ *
+ * @param channel The channel on the PCM to control (0..7).
+ */
+Solenoid::Solenoid(uint32_t channel)
+	: SolenoidBase (GetDefaultSolenoidModule())
+	, m_channel (channel)
+{
+	InitSolenoid();
+}
+
+/**
+ * Constructor.
+ *
+ * @param moduleNumber The CAN ID of the PCM the solenoid is attached to
+ * @param channel The channel on the PCM to control (0..7).
+ */
+Solenoid::Solenoid(uint8_t moduleNumber, uint32_t channel)
+	: SolenoidBase (moduleNumber)
+	, m_channel (channel)
+{
+	InitSolenoid();
+}
+
+/**
+ * Destructor.
+ */
+Solenoid::~Solenoid()
+{
+	if (CheckSolenoidModule(m_moduleNumber))
+	{
+		m_allocated->Free(m_moduleNumber * kSolenoidChannels + m_channel);
+	}
+}
+
+/**
+ * Set the value of a solenoid.
+ *
+ * @param on Turn the solenoid output off or on.
+ */
+void Solenoid::Set(bool on)
+{
+	if (StatusIsFatal()) return;
+	uint8_t value = on ? 0xFF : 0x00;
+	uint8_t mask = 1 << m_channel;
+
+	SolenoidBase::Set(value, mask);
+}
+
+/**
+ * Read the current value of the solenoid.
+ *
+ * @return The current value of the solenoid.
+ */
+bool Solenoid::Get()
+{
+	if (StatusIsFatal()) return false;
+	uint8_t value = GetAll() & ( 1 << m_channel);
+	return (value != 0);
+}
+
+/**
+ * Check if solenoid is blacklisted.
+ *		If a solenoid is shorted, it is added to the blacklist and
+ *		disabled until power cycle, or until faults are cleared.
+ *		@see ClearAllPCMStickyFaults()
+ *
+ * @return If solenoid is disabled due to short.
+ */
+bool Solenoid::IsBlackListed()
+{
+	int value = GetPCMSolenoidBlackList() & ( 1 << m_channel);
+	return (value != 0);
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/SolenoidBase.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/SolenoidBase.cpp
new file mode 100644
index 0000000..f1b46d6
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/SolenoidBase.cpp
@@ -0,0 +1,111 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "SolenoidBase.h"
+
+// Needs to be global since the protected resource spans all Solenoid objects.
+Resource *SolenoidBase::m_allocated = NULL;
+
+/**
+ * Constructor
+ * 
+ * @param moduleNumber The CAN PCM ID.
+ */
+SolenoidBase::SolenoidBase(uint8_t moduleNumber)
+	: m_moduleNumber (moduleNumber)
+{
+  	for (uint32_t i = 0; i < kSolenoidChannels; i++)
+	{
+	  void* port = getPortWithModule(moduleNumber, i);
+	  int32_t status = 0;
+	  m_ports[i] = initializeSolenoidPort(port, &status);
+	  wpi_setErrorWithContext(status, getHALErrorMessage(status));
+	}
+}
+
+/**
+ * Destructor.
+ */
+SolenoidBase::~SolenoidBase()
+{
+}
+
+/**
+ * Set the value of a solenoid.
+ * 
+ * @param value The value you want to set on the module.
+ * @param mask The channels you want to be affected.
+ */
+void SolenoidBase::Set(uint8_t value, uint8_t mask)
+{
+  	int32_t status = 0;
+		setSolenoids(m_ports[0], value, mask, &status);
+	wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+/**
+ * Read all 8 solenoids as a single byte
+ * 
+ * @return The current value of all 8 solenoids on the module.
+ */
+uint8_t SolenoidBase::GetAll()
+{
+  	uint8_t value = 0;
+  	int32_t status = 0;
+	for (int i = 0; i < 8; i++) { // XXX: Unhardcode
+	  value |= getSolenoid(m_ports[i], &status) << i;
+	}
+	return value;
+}
+/**
+ * Reads complete solenoid blacklist for all 8 solenoids as a single byte.
+ * 
+ *		If a solenoid is shorted, it is added to the blacklist and
+ *		disabled until power cycle, or until faults are cleared.
+ *		@see ClearAllPCMStickyFaults()
+ * 
+ * @return The solenoid blacklist of all 8 solenoids on the module.
+ */
+uint8_t SolenoidBase::GetPCMSolenoidBlackList()
+{
+	int32_t status = 0;
+	return getPCMSolenoidBlackList(m_ports[0], &status);
+}
+/**
+ * @return true if PCM sticky fault is set : The common 
+ *			highside solenoid voltage rail is too low,
+ *	 		most likely a solenoid channel is shorted.
+ */
+bool SolenoidBase::GetPCMSolenoidVoltageStickyFault()
+{
+	int32_t status = 0;
+	return getPCMSolenoidVoltageStickyFault(m_ports[0], &status);
+}
+/**
+ * @return true if PCM is in fault state : The common 
+ *			highside solenoid voltage rail is too low,
+ *	 		most likely a solenoid channel is shorted.
+ */
+bool SolenoidBase::GetPCMSolenoidVoltageFault()
+{
+	int32_t status = 0;
+	return getPCMSolenoidVoltageFault(m_ports[0], &status);
+}
+/**
+ * Clear ALL sticky faults inside PCM that Compressor is wired to.
+ *
+ * If a sticky fault is set, then it will be persistently cleared.  Compressor drive
+ *		maybe momentarily disable while flags are being cleared. Care should be 
+ *		taken to not call this too frequently, otherwise normal compressor 
+ *		functionality may be prevented.
+ *
+ * If no sticky faults are set then this call will have no effect.
+ */
+void SolenoidBase::ClearAllPCMStickyFaults()
+{
+	int32_t status = 0;
+	return clearAllPCMStickyFaults_sol(m_ports[0], &status);
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Talon.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Talon.cpp
new file mode 100644
index 0000000..a2eb396
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Talon.cpp
@@ -0,0 +1,87 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "Talon.h"
+
+//#include "NetworkCommunication/UsageReporting.h"
+
+/**
+ * Common initialization code called by all constructors.
+ *
+ * Note that the Talon uses the following bounds for PWM values. These values should work reasonably well for
+ * most controllers, but if users experience issues such as asymmetric behavior around
+ * the deadband or inability to saturate the controller in either direction, calibration is recommended.
+ * The calibration procedure can be found in the Talon User Manual available from CTRE.
+ *
+ *   2.037ms = full "forward"
+ *   1.539ms = the "high end" of the deadband range
+ *   1.513ms = center of the deadband range (off)
+ *   1.487ms = the "low end" of the deadband range
+ *   0.989ms = full "reverse"
+ */
+void Talon::InitTalon() {
+	SetBounds(2.037, 1.539, 1.513, 1.487, .989);
+	SetPeriodMultiplier(kPeriodMultiplier_1X);
+	SetRaw(m_centerPwm);
+	SetZeroLatch();
+
+	HALReport(HALUsageReporting::kResourceType_Talon, GetChannel());
+}
+
+/**
+ * Constructor for a Talon (original or Talon SR)
+ * @param channel The PWM channel number that the Talon is attached to. 0-9 are on-board, 10-19 are on the MXP port
+ */
+Talon::Talon(uint32_t channel) : SafePWM(channel)
+{
+	InitTalon();
+}
+
+Talon::~Talon()
+{
+}
+
+/**
+ * Set the PWM value.
+ *
+ * The PWM value is set using a range of -1.0 to 1.0, appropriately
+ * scaling the value for the FPGA.
+ *
+ * @param speed The speed value between -1.0 and 1.0 to set.
+ * @param syncGroup Unused interface.
+ */
+void Talon::Set(float speed, uint8_t syncGroup)
+{
+	SetSpeed(speed);
+}
+
+/**
+ * Get the recently set value of the PWM.
+ *
+ * @return The most recently set value for the PWM between -1.0 and 1.0.
+ */
+float Talon::Get()
+{
+	return GetSpeed();
+}
+
+/**
+ * Common interface for disabling a motor.
+ */
+void Talon::Disable()
+{
+	SetRaw(kPwmDisabled);
+}
+
+/**
+ * Write out the PID value as seen in the PIDOutput base object.
+ *
+ * @param output Write out the PWM value as was found in the PIDController
+ */
+void Talon::PIDWrite(float output)
+{
+	Set(output);
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/TalonSRX.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/TalonSRX.cpp
new file mode 100644
index 0000000..d0f9ce6
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/TalonSRX.cpp
@@ -0,0 +1,86 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "TalonSRX.h"
+
+//#include "NetworkCommunication/UsageReporting.h"
+
+/**
+ * Common initialization code called by all constructors.
+ *
+ * Note that the TalonSRX uses the following bounds for PWM values. These values should work reasonably well for
+ * most controllers, but if users experience issues such as asymmetric behaviour around
+ * the deadband or inability to saturate the controller in either direction, calibration is recommended.
+ * The calibration procedure can be found in the TalonSRX User Manual available from Cross The Road Electronics.
+ *   2.004ms = full "forward"
+ *   1.52ms = the "high end" of the deadband range
+ *   1.50ms = center of the deadband range (off)
+ *   1.48ms = the "low end" of the deadband range
+ *   0.997ms = full "reverse"
+ */
+void TalonSRX::InitTalonSRX() {
+	SetBounds(2.004, 1.52, 1.50, 1.48, .997);
+	SetPeriodMultiplier(kPeriodMultiplier_1X);
+	SetRaw(m_centerPwm);
+	SetZeroLatch();
+
+	HALReport(HALUsageReporting::kResourceType_Talon, GetChannel());
+}
+
+/**
+ * Construct a TalonSRX connected via PWM
+ * @param channel The PWM channel that the TalonSRX is attached to. 0-9 are on-board, 10-19 are on the MXP port
+ */
+TalonSRX::TalonSRX(uint32_t channel) : SafePWM(channel)
+{
+	InitTalonSRX();
+}
+
+TalonSRX::~TalonSRX()
+{
+}
+
+/**
+ * Set the PWM value.
+ *
+ * The PWM value is set using a range of -1.0 to 1.0, appropriately
+ * scaling the value for the FPGA.
+ *
+ * @param speed The speed value between -1.0 and 1.0 to set.
+ * @param syncGroup Unused interface.
+ */
+void TalonSRX::Set(float speed, uint8_t syncGroup)
+{
+	SetSpeed(speed);
+}
+
+/**
+ * Get the recently set value of the PWM.
+ *
+ * @return The most recently set value for the PWM between -1.0 and 1.0.
+ */
+float TalonSRX::Get()
+{
+	return GetSpeed();
+}
+
+/**
+ * Common interface for disabling a motor.
+ */
+void TalonSRX::Disable()
+{
+	SetRaw(kPwmDisabled);
+}
+
+/**
+ * Write out the PID value as seen in the PIDOutput base object.
+ *
+ * @param output Write out the PWM value as was found in the PIDController
+ */
+void TalonSRX::PIDWrite(float output)
+{
+	Set(output);
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Task.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Task.cpp
new file mode 100644
index 0000000..4b80142
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Task.cpp
@@ -0,0 +1,213 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "Task.h"
+
+//#include "NetworkCommunication/UsageReporting.h"
+#include "WPIErrors.h"
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include "HAL/HAL.hpp"
+
+#ifndef OK
+#define OK		0
+#endif /* OK */
+#ifndef ERROR
+#define ERROR		(-1)
+#endif /* ERROR */
+
+const uint32_t Task::kDefaultPriority;
+
+/**
+ * Create but don't launch a task.
+ * @param name The name of the task.  "FRC_" will be prepended to the task name.
+ * @param function The address of the function to run as the new task.
+ * @param priority The VxWorks priority for the task.
+ * @param stackSize The size of the stack for the task
+ */
+Task::Task(const char* name, FUNCPTR function, int32_t priority, uint32_t stackSize)
+{
+	m_taskID = NULL_TASK;
+	m_function = function;
+	m_priority = priority;
+	m_stackSize = stackSize;
+	m_taskName = new char[strlen(name) + 5];
+	strcpy(m_taskName, "FRC_");
+	strcpy(m_taskName+4, name);
+
+	static int32_t instances = 0;
+	instances++;
+	HALReport(HALUsageReporting::kResourceType_Task, instances, 0, m_taskName);
+}
+
+Task::~Task()
+{
+	if (m_taskID != NULL_TASK) Stop();
+	delete [] m_taskName;
+	m_taskName = NULL;
+}
+
+/**
+ * Starts this task.
+ * If it is already running or unable to start, it fails and returns false.
+ */
+bool Task::Start(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, 
+		uint32_t arg5, uint32_t arg6, uint32_t arg7, uint32_t arg8, uint32_t arg9)
+{
+	m_taskID = spawnTask(m_taskName,
+						m_priority,
+						VXWORKS_FP_TASK,							// options
+						m_stackSize,						// stack size
+						m_function,							// function to start
+						arg0, arg1, arg2, arg3, arg4,	// parameter 1 - pointer to this class
+						arg5, arg6, arg7, arg8, arg9);// additional unused parameters
+	if (m_taskID == NULL_TASK) {
+		HandleError(ERROR);
+		return false;
+	}
+	return true;
+}
+
+/**
+ * Restarts a running task.
+ * If the task isn't started, it starts it.
+ * @return false if the task is running and we are unable to kill the previous instance
+ */
+bool Task::Restart()
+{
+	return HandleError(restartTask(m_taskID));
+}
+
+/**
+ * Kills the running task.
+ * @returns true on success false if the task doesn't exist or we are unable to kill it.
+ */
+bool Task::Stop()
+{
+	bool ok = true;
+	if (Verify())
+	{
+		ok = HandleError(deleteTask(m_taskID));
+	}
+	m_taskID = NULL_TASK;
+	return ok;
+}
+
+/**
+ * Returns true if the task is ready to execute (i.e. not suspended, delayed, or blocked).
+ * @return true if ready, false if not ready.
+ */
+bool Task::IsReady()
+{
+	return isTaskReady(m_taskID);
+}
+
+/**
+ * Returns true if the task was explicitly suspended by calling Suspend()
+ * @return true if suspended, false if not suspended.
+ */
+bool Task::IsSuspended()
+{
+	return isTaskSuspended(m_taskID);
+}
+
+/**
+ * Pauses a running task.
+ * Returns true on success, false if unable to pause or the task isn't running.
+ */
+bool Task::Suspend()
+{
+	return HandleError(suspendTask(m_taskID));
+}
+
+/**
+ * Resumes a paused task.
+ * Returns true on success, false if unable to resume or if the task isn't running/paused.
+ */
+bool Task::Resume()
+{
+	return HandleError(resumeTask(m_taskID));
+}
+
+/**
+ * Verifies a task still exists.
+ * @returns true on success.
+ */
+bool Task::Verify()
+{
+	return verifyTaskID(m_taskID) == OK;
+}
+
+/**
+ * Gets the priority of a task.
+ * @returns task priority or 0 if an error occured
+ */
+int32_t Task::GetPriority()
+{
+	if (HandleError(getTaskPriority(m_taskID, &m_priority)))
+		return m_priority;
+	else
+		return 0;
+}
+
+/**
+ * This routine changes a task's priority to a specified priority.
+ * Priorities range from 0, the highest priority, to 255, the lowest priority.
+ * Default task priority is 100.
+ * @param priority The priority the task should run at.
+ * @returns true on success.
+ */
+bool Task::SetPriority(int32_t priority)
+{
+	m_priority = priority;
+	return HandleError(setTaskPriority(m_taskID, m_priority));
+}
+
+/**
+ * Returns the name of the task.
+ * @returns Pointer to the name of the task or NULL if not allocated
+ */
+const char* Task::GetName()
+{
+	return m_taskName;
+}
+
+/**
+ * Get the ID of a task
+ * @returns Task ID of this task.  Task::kInvalidTaskID (-1) if the task has not been started or has already exited.
+ */
+TASK Task::GetID()
+{
+	if (Verify())
+		return m_taskID;
+	return NULL_TASK;
+}
+
+/**
+ * Handles errors generated by task related code.
+ */
+bool Task::HandleError(STATUS results)
+{
+	if (results != ERROR) return true;
+	int errsv = errno;
+	if (errsv == HAL_objLib_OBJ_ID_ERROR) {
+		wpi_setWPIErrorWithContext(TaskIDError, m_taskName);
+	} else if (errsv == HAL_objLib_OBJ_DELETED) {
+		wpi_setWPIErrorWithContext(TaskDeletedError, m_taskName);
+	} else if (errsv == HAL_taskLib_ILLEGAL_OPTIONS) {
+		wpi_setWPIErrorWithContext(TaskOptionsError, m_taskName);
+	} else if (errsv == HAL_memLib_NOT_ENOUGH_MEMORY) {
+		wpi_setWPIErrorWithContext(TaskMemoryError, m_taskName);
+	} else if (errsv == HAL_taskLib_ILLEGAL_PRIORITY) {
+		wpi_setWPIErrorWithContext(TaskPriorityError, m_taskName);
+	} else {
+		printf("ERROR: errno=%i", errsv);
+		wpi_setWPIErrorWithContext(TaskError, m_taskName);
+	}
+	return false;
+}
+
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Timer.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Timer.cpp
new file mode 100644
index 0000000..e13737c
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Timer.cpp
@@ -0,0 +1,191 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "Timer.h"
+
+#include <time.h>
+
+#include "HAL/HAL.hpp"
+#include "HAL/cpp/Synchronized.hpp"
+#include "Utility.h"
+#include <iostream>
+
+/**
+ * Pause the task for a specified time.
+ *
+ * Pause the execution of the program for a specified period of time given in seconds.
+ * Motors will continue to run at their last assigned values, and sensors will continue to
+ * update. Only the task containing the wait will pause until the wait time is expired.
+ *
+ * @param seconds Length of time to pause, in seconds.
+ */
+void Wait(double seconds)
+{
+	if (seconds < 0.0) return;
+	delaySeconds(seconds);
+}
+
+/**
+ * Return the FPGA system clock time in seconds.
+ * This is deprecated and just forwards to Timer::GetFPGATimestamp().
+ * @return Robot running time in seconds.
+ */
+double GetClock()
+{
+	return Timer::GetFPGATimestamp();
+}
+
+/**
+ * @brief Gives real-time clock system time with nanosecond resolution
+ * @return The time, just in case you want the robot to start autonomous at 8pm on Saturday.
+*/
+double GetTime()
+{
+	struct timespec tp;
+
+	clock_gettime(CLOCK_REALTIME,&tp);
+	double realTime = (double)tp.tv_sec + (double)((double)tp.tv_nsec*1e-9);
+
+	return (realTime);
+}
+
+/**
+ * Create a new timer object.
+ *
+ * Create a new timer object and reset the time to zero. The timer is initially not running and
+ * must be started.
+ */
+Timer::Timer()
+	: m_startTime (0.0)
+	, m_accumulatedTime (0.0)
+	, m_running (false)
+{
+	//Creates a semaphore to control access to critical regions.
+	//Initially 'open'
+	Reset();
+}
+
+Timer::~Timer() {}
+
+/**
+ * Get the current time from the timer. If the clock is running it is derived from
+ * the current system clock the start time stored in the timer class. If the clock
+ * is not running, then return the time when it was last stopped.
+ *
+ * @return Current time value for this timer in seconds
+ */
+double Timer::Get()
+{
+	double result;
+	double currentTime = GetFPGATimestamp();
+
+	::std::unique_lock<Mutex> sync(m_lock);
+	if(m_running)
+	{
+		// If the current time is before the start time, then the FPGA clock
+		// rolled over.  Compensate by adding the ~71 minutes that it takes
+		// to roll over to the current time.
+		if(currentTime < m_startTime) {
+			currentTime += kRolloverTime;
+		}
+
+		result = (currentTime - m_startTime) + m_accumulatedTime;
+	}
+	else
+	{
+		result = m_accumulatedTime;
+	}
+
+	return result;
+}
+
+/**
+ * Reset the timer by setting the time to 0.
+ *
+ * Make the timer startTime the current time so new requests will be relative to now
+ */
+void Timer::Reset()
+{
+	::std::unique_lock<Mutex> sync(m_lock);
+	m_accumulatedTime = 0;
+	m_startTime = GetFPGATimestamp();
+}
+
+/**
+ * Start the timer running.
+ * Just set the running flag to true indicating that all time requests should be
+ * relative to the system clock.
+ */
+void Timer::Start()
+{
+	::std::unique_lock<Mutex> sync(m_lock);
+	if (!m_running)
+	{
+		m_startTime = GetFPGATimestamp();
+		m_running = true;
+	}
+}
+
+/**
+ * Stop the timer.
+ * This computes the time as of now and clears the running flag, causing all
+ * subsequent time requests to be read from the accumulated time rather than
+ * looking at the system clock.
+ */
+void Timer::Stop()
+{
+	double temp = Get();
+
+	::std::unique_lock<Mutex> sync(m_lock);
+	if (m_running)
+	{
+		m_accumulatedTime = temp;
+		m_running = false;
+	}
+}
+
+/**
+ * Check if the period specified has passed and if it has, advance the start
+ * time by that period. This is useful to decide if it's time to do periodic
+ * work without drifting later by the time it took to get around to checking.
+ *
+ * @param period The period to check for (in seconds).
+ * @return True if the period has passed.
+ */
+bool Timer::HasPeriodPassed(double period)
+{
+	if (Get() > period)
+	{
+		::std::unique_lock<Mutex> sync(m_lock);
+		// Advance the start time by the period.
+		m_startTime += period;
+		// Don't set it to the current time... we want to avoid drift.
+		return true;
+	}
+	return false;
+}
+
+/**
+ * Return the FPGA system clock time in seconds.
+ *
+ * Return the time from the FPGA hardware clock in seconds since the FPGA
+ * started.
+ * Rolls over after 71 minutes.
+ * @returns Robot running time in seconds.
+ */
+double Timer::GetFPGATimestamp()
+{
+	// FPGA returns the timestamp in microseconds
+	// Call the helper GetFPGATime() in Utility.cpp
+	return GetFPGATime() * 1.0e-6;
+}
+
+// Internal function that reads the PPC timestamp counter.
+extern "C"
+{
+	uint32_t niTimestamp32(void);
+	uint64_t niTimestamp64(void);
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/USBCamera.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/USBCamera.cpp
new file mode 100644
index 0000000..8d36be1
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/USBCamera.cpp
@@ -0,0 +1,328 @@
+#include "USBCamera.h"
+
+#include "Utility.h"
+
+#include <regex>
+#include <chrono>
+#include <thread>
+#include <iostream>
+#include <iomanip>
+
+// This macro expands the given imaq function to ensure that it is called and
+// properly checked for an error, calling the wpi_setImaqErrorWithContext
+// macro
+// To call it, just give the name of the function and the arguments
+#define SAFE_IMAQ_CALL(funName, ...) { \
+    unsigned int error = funName(__VA_ARGS__); \
+    if (error != IMAQdxErrorSuccess) \
+      wpi_setImaqErrorWithContext(error, #funName); \
+  }
+
+// Constants for the manual and auto types
+static const std::string AUTO = "Auto";
+static const std::string MANUAL = "Manual";
+
+/**
+ * Helper function to determine the size of a jpeg. The general structure of
+ * how to parse a jpeg for length can be found in this stackoverflow article:
+ * http://stackoverflow.com/a/1602428. Be sure to also read the comments for
+ * the SOS flag explanation.
+ */
+unsigned int USBCamera::GetJpegSize(void* buffer, unsigned int buffSize) {
+  uint8_t* data = (uint8_t*) buffer;
+  if (!wpi_assert(data[0] == 0xff && data[1] == 0xd8)) return 0;
+  unsigned int pos = 2;
+  while (pos < buffSize) {
+    // All control markers start with 0xff, so if this isn't present,
+    // the JPEG is not valid
+    if (!wpi_assert(data[pos] == 0xff)) return 0;
+    unsigned char t = data[pos+1];
+    // These are RST markers. We just skip them and move onto the next marker
+    if (t == 0x01 || (t >= 0xd0 && t <= 0xd7)) {
+      pos += 2;
+    } else if (t == 0xd9) {
+      // End of Image, add 2 for this and 0-indexed
+      return pos + 2;
+    } else if (!wpi_assert(t != 0xd8))  {
+      // Another start of image, invalid image
+      return 0;
+    } else if (t == 0xda) {
+      // SOS marker. The next two bytes are a 16-bit big-endian int that is
+      // the length of the SOS header, skip that
+      unsigned int len = (((unsigned int) (data[pos+2] & 0xff)) << 8 | ((unsigned int) data[pos+3] & 0xff));
+      pos += len + 2;
+      // The next marker is the first marker that is 0xff followed by a non-RST
+      // element. 0xff followed by 0x00 is an escaped 0xff. 0xd0-0xd7 are RST
+      // markers
+      while (data[pos] != 0xff || data[pos+1] == 0x00 || (data[pos+1] >= 0xd0 && data[pos+1] <= 0xd7)) {
+        pos += 1;
+        if (pos >= buffSize) return 0;
+      }
+    } else {
+      // This is one of several possible markers. The next two bytes are a 16-bit
+      // big-endian int with the length of the marker header, skip that then
+      // continue searching
+      unsigned int len = (((unsigned int) (data[pos+2] & 0xff)) << 8 | ((unsigned int) data[pos+3] & 0xff));
+      pos += len + 2;
+    }
+  }
+
+  return 0;
+}
+
+USBCamera::USBCamera(std::string name, bool useJpeg) :
+  m_id(0),
+  m_name(name),
+  m_useJpeg(useJpeg),
+  m_active(false),
+  m_open(false),
+  m_mutex(),
+  m_width(320),
+  m_height(240),
+  m_fps(30),
+  m_whiteBalance(AUTO),
+  m_whiteBalanceValue(0),
+  m_whiteBalanceValuePresent(false),
+  m_exposure(MANUAL),
+  m_exposureValue(50),
+  m_exposureValuePresent(false),
+  m_brightness(80),
+  m_needSettingsUpdate(true) {
+}
+
+void USBCamera::OpenCamera() {
+  std::unique_lock<std::recursive_mutex> lock(m_mutex);
+  for (unsigned int i = 0; i < 3; i++) {
+    uInt32 id = 0;
+    // Can't use SAFE_IMAQ_CALL here because we only error on the third time
+    IMAQdxError error = IMAQdxOpenCamera(m_name.c_str(), IMAQdxCameraControlModeController, &id);
+    if (error != IMAQdxErrorSuccess) {
+      // Only error on the 3rd try
+      if (i >= 2)
+        wpi_setImaqErrorWithContext(error, "IMAQdxOpenCamera");
+      // Sleep for a few seconds to ensure the error has been dealt with
+      std::this_thread::sleep_for(std::chrono::milliseconds(2000));
+    } else {
+      m_id = id;
+      m_open = true;
+      return;
+    }
+  }
+}
+
+void USBCamera::CloseCamera() {
+  std::unique_lock<std::recursive_mutex> lock(m_mutex);
+  if (!m_open) return;
+  SAFE_IMAQ_CALL(IMAQdxCloseCamera, m_id);
+  m_id = 0;
+  m_open = false;
+}
+
+void USBCamera::StartCapture() {
+  std::unique_lock<std::recursive_mutex> lock(m_mutex);
+  if (!m_open || m_active) return;
+  SAFE_IMAQ_CALL(IMAQdxConfigureGrab, m_id);
+  SAFE_IMAQ_CALL(IMAQdxStartAcquisition, m_id);
+  m_active = true;
+}
+
+void USBCamera::StopCapture() {
+  std::unique_lock<std::recursive_mutex> lock(m_mutex);
+  if (!m_open || !m_active) return;
+  SAFE_IMAQ_CALL(IMAQdxStopAcquisition, m_id);
+  SAFE_IMAQ_CALL(IMAQdxUnconfigureAcquisition, m_id);
+  m_active = false;
+}
+
+void USBCamera::UpdateSettings() {
+  std::unique_lock<std::recursive_mutex> lock(m_mutex);
+  bool wasActive = m_active;
+
+  if (wasActive)
+    StopCapture();
+  if (m_open)
+    CloseCamera();
+  OpenCamera();
+
+  uInt32 count = 0;
+  uInt32 currentMode = 0;
+  SAFE_IMAQ_CALL(IMAQdxEnumerateVideoModes, m_id, NULL, &count, &currentMode);
+  IMAQdxVideoMode modes[count];
+  SAFE_IMAQ_CALL(IMAQdxEnumerateVideoModes, m_id, modes, &count, &currentMode);
+
+  // Groups are:
+  //   0 - width
+  //   1 - height
+  //   2 - format
+  //   3 - fps
+  std::regex reMode("([0-9]+)\\s*x\\s*([0-9]+)\\s+(.*?)\\s+([0-9.]+)\\s*fps");
+  IMAQdxVideoMode* foundMode = nullptr;
+  IMAQdxVideoMode* currentModePtr = &modes[currentMode];
+  double foundFps = 1000.0;
+
+  // Loop through the modes, and find the match with the lowest fps
+  for (unsigned int i = 0; i < count; i++) {
+    std::cmatch m;
+    if (!std::regex_match(modes[i].Name, m, reMode))
+      continue;
+    unsigned int width = (unsigned int) std::stoul(m[1].str());
+    unsigned int height = (unsigned int) std::stoul(m[2].str());
+    if (width != m_width)
+      continue;
+    if (height != m_height)
+      continue;
+    double fps = atof(m[4].str().c_str());
+    if (fps < m_fps)
+      continue;
+    if (fps > foundFps)
+      continue;
+    bool isJpeg = m[3].str().compare("jpeg") == 0 || m[3].str().compare("JPEG") == 0;
+    if ((m_useJpeg && !isJpeg) || (!m_useJpeg && isJpeg))
+      continue;
+    foundMode = &modes[i];
+    foundFps = fps;
+  }
+  if (foundMode != nullptr) {
+    if (foundMode->Value != currentModePtr->Value) {
+      SAFE_IMAQ_CALL(IMAQdxSetAttribute, m_id, IMAQdxAttributeVideoMode, IMAQdxValueTypeU32, foundMode->Value);
+    }
+  } 
+
+  if (m_whiteBalance.compare(AUTO) == 0) {
+    SAFE_IMAQ_CALL(IMAQdxSetAttribute, m_id, ATTR_WB_MODE, IMAQdxValueTypeString, AUTO.c_str());
+  } else {
+    SAFE_IMAQ_CALL(IMAQdxSetAttribute, m_id, ATTR_WB_MODE, IMAQdxValueTypeString, MANUAL.c_str());
+    if (m_whiteBalanceValuePresent)
+      SAFE_IMAQ_CALL(IMAQdxSetAttribute, m_id, ATTR_WB_VALUE, IMAQdxValueTypeU32, m_whiteBalanceValue);
+  }
+
+  if (m_exposure.compare(AUTO) == 0) {
+    SAFE_IMAQ_CALL(IMAQdxSetAttribute, m_id, ATTR_EX_MODE, IMAQdxValueTypeString, std::string("AutoAperaturePriority").c_str());
+  } else {
+    SAFE_IMAQ_CALL(IMAQdxSetAttribute, m_id, ATTR_EX_MODE, IMAQdxValueTypeString, MANUAL.c_str());
+    if (m_exposureValuePresent) {
+      double minv = 0.0;
+      double maxv = 0.0;
+      SAFE_IMAQ_CALL(IMAQdxGetAttributeMinimum, m_id, ATTR_EX_VALUE, IMAQdxValueTypeF64, &minv);
+      SAFE_IMAQ_CALL(IMAQdxGetAttributeMaximum, m_id, ATTR_EX_VALUE, IMAQdxValueTypeF64, &maxv);
+      double val = minv + ((maxv - minv) * ((double) m_exposureValue / 100.0));
+      SAFE_IMAQ_CALL(IMAQdxSetAttribute, m_id, ATTR_EX_VALUE, IMAQdxValueTypeF64, val);
+    }
+  }
+
+  SAFE_IMAQ_CALL(IMAQdxSetAttribute, m_id, ATTR_BR_MODE, IMAQdxValueTypeString, MANUAL.c_str());
+  double minv = 0.0;
+  double maxv = 0.0;
+  SAFE_IMAQ_CALL(IMAQdxGetAttributeMinimum, m_id, ATTR_BR_VALUE, IMAQdxValueTypeF64, &minv);
+  SAFE_IMAQ_CALL(IMAQdxGetAttributeMaximum, m_id, ATTR_BR_VALUE, IMAQdxValueTypeF64, &maxv);
+  double val = minv + ((maxv - minv) * ((double) m_brightness / 100.0));
+  SAFE_IMAQ_CALL(IMAQdxSetAttribute, m_id, ATTR_BR_VALUE, IMAQdxValueTypeF64, val);
+
+  if (wasActive)
+    StartCapture();
+}
+
+void USBCamera::SetFPS(double fps) {
+  std::unique_lock<std::recursive_mutex> lock(m_mutex);
+  if (m_fps != fps) {
+    m_needSettingsUpdate = true;
+    m_fps = fps;
+  }
+}
+
+void USBCamera::SetSize(unsigned int width, unsigned int height) {
+  std::unique_lock<std::recursive_mutex> lock(m_mutex);
+  if (m_width != width || m_height != height) {
+    m_needSettingsUpdate = true;
+    m_width = width;
+    m_height = height;
+  }
+}
+
+void USBCamera::SetBrightness(unsigned int brightness) {
+  std::unique_lock<std::recursive_mutex> lock(m_mutex);
+  if (m_brightness != brightness) {
+    m_needSettingsUpdate = true;
+    m_brightness = brightness;
+  }
+}
+
+unsigned int USBCamera::GetBrightness() {
+  std::unique_lock<std::recursive_mutex> lock(m_mutex);
+  return m_brightness;
+}
+
+void USBCamera::SetWhiteBalanceAuto() {
+  std::unique_lock<std::recursive_mutex> lock(m_mutex);
+  m_whiteBalance = AUTO;
+  m_whiteBalanceValue = 0;
+  m_whiteBalanceValuePresent = false;
+  m_needSettingsUpdate = true;
+}
+
+void USBCamera::SetWhiteBalanceHoldCurrent() {
+  std::unique_lock<std::recursive_mutex> lock(m_mutex);
+  m_whiteBalance = MANUAL;
+  m_whiteBalanceValue = 0;
+  m_whiteBalanceValuePresent = false;
+  m_needSettingsUpdate = true;
+}
+
+void USBCamera::SetWhiteBalanceManual(unsigned int whiteBalance) {
+  std::unique_lock<std::recursive_mutex> lock(m_mutex);
+  m_whiteBalance = MANUAL;
+  m_whiteBalanceValue = whiteBalance;
+  m_whiteBalanceValuePresent = true;
+  m_needSettingsUpdate = true;
+}
+
+void USBCamera::SetExposureAuto() {
+  std::unique_lock<std::recursive_mutex> lock(m_mutex);
+  m_exposure = AUTO;
+  m_exposureValue = 0;
+  m_exposureValuePresent = false;
+  m_needSettingsUpdate = true;
+}
+
+void USBCamera::SetExposureHoldCurrent() {
+  std::unique_lock<std::recursive_mutex> lock(m_mutex);
+  m_exposure = MANUAL;
+  m_exposureValue = 0;
+  m_exposureValuePresent = false;
+  m_needSettingsUpdate = true;
+}
+
+void USBCamera::SetExposureManual(unsigned int level) {
+  std::unique_lock<std::recursive_mutex> lock(m_mutex);
+  m_exposure = MANUAL;
+  if (level > 100) m_exposureValue = 100;
+  else m_exposureValue = level;
+  m_exposureValuePresent = true;
+  m_needSettingsUpdate = true;
+}
+
+void USBCamera::GetImage(Image* image) {
+  std::unique_lock<std::recursive_mutex> lock(m_mutex);
+  if (m_needSettingsUpdate || m_useJpeg) {
+    m_needSettingsUpdate = false;
+    m_useJpeg = false;
+    UpdateSettings();
+  }
+  // BufNum is not actually used for anything at our level, since we are
+  // waiting until the next image is ready anyway
+  uInt32 bufNum;
+  SAFE_IMAQ_CALL(IMAQdxGrab, m_id, image, 1, &bufNum);
+}
+
+unsigned int USBCamera::GetImageData(void* buffer, unsigned int bufferSize) {
+  std::unique_lock<std::recursive_mutex> lock(m_mutex);
+  if (m_needSettingsUpdate || !m_useJpeg) {
+    m_needSettingsUpdate = false;
+    m_useJpeg = true;
+    UpdateSettings();
+  }
+  // BufNum is not actually used for anything at our level
+  uInt32 bufNum;
+  SAFE_IMAQ_CALL(IMAQdxGetImageData, m_id, buffer, bufferSize, IMAQdxBufferNumberModeLast, 0, &bufNum);
+  return GetJpegSize(buffer, bufferSize);
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Ultrasonic.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Ultrasonic.cpp
new file mode 100644
index 0000000..339ff7c
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Ultrasonic.cpp
@@ -0,0 +1,304 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "Ultrasonic.h"
+
+#include "Counter.h"
+#include "DigitalInput.h"
+#include "DigitalOutput.h"
+//#include "NetworkCommunication/UsageReporting.h"
+#include "Timer.h"
+#include "Utility.h"
+#include "WPIErrors.h"
+
+constexpr double Ultrasonic::kPingTime;	///< Time (sec) for the ping trigger pulse.
+const uint32_t Ultrasonic::kPriority;	///< Priority that the ultrasonic round robin task runs.
+constexpr double Ultrasonic::kMaxUltrasonicTime;	///< Max time (ms) between readings.
+constexpr double Ultrasonic::kSpeedOfSoundInchesPerSec;
+Task Ultrasonic::m_task("UltrasonicChecker", (FUNCPTR)UltrasonicChecker); // task doing the round-robin automatic sensing
+Ultrasonic *Ultrasonic::m_firstSensor = NULL; // head of the ultrasonic sensor list
+bool Ultrasonic::m_automaticEnabled = false; // automatic round robin mode
+SEMAPHORE_ID Ultrasonic::m_semaphore = 0;
+
+/**
+ * Background task that goes through the list of ultrasonic sensors and pings each one in turn. The counter
+ * is configured to read the timing of the returned echo pulse.
+ *
+ * DANGER WILL ROBINSON, DANGER WILL ROBINSON:
+ * This code runs as a task and assumes that none of the ultrasonic sensors will change while it's
+ * running. If one does, then this will certainly break. Make sure to disable automatic mode before changing
+ * anything with the sensors!!
+ */
+void Ultrasonic::UltrasonicChecker()
+{
+	Ultrasonic *u = NULL;
+	while (m_automaticEnabled)
+	{
+		if (u == NULL) u = m_firstSensor;
+		if (u == NULL) return;
+		if (u->IsEnabled())
+			u->m_pingChannel->Pulse(kPingTime);	// do the ping
+		u = u->m_nextSensor;
+		Wait(0.1);							// wait for ping to return
+	}
+}
+
+/**
+ * Initialize the Ultrasonic Sensor.
+ * This is the common code that initializes the ultrasonic sensor given that there
+ * are two digital I/O channels allocated. If the system was running in automatic mode (round robin)
+ * when the new sensor is added, it is stopped, the sensor is added, then automatic mode is
+ * restored.
+ */
+void Ultrasonic::Initialize()
+{
+	bool originalMode = m_automaticEnabled;
+	if (m_semaphore == 0) m_semaphore = initializeSemaphore(SEMAPHORE_FULL);
+	SetAutomaticMode(false); // kill task when adding a new sensor
+	takeSemaphore(m_semaphore); // link this instance on the list
+	{
+		m_nextSensor = m_firstSensor;
+		m_firstSensor = this;
+	}
+	giveSemaphore(m_semaphore);
+
+	m_counter = new Counter(m_echoChannel); // set up counter for this sensor
+	m_counter->SetMaxPeriod(1.0);
+	m_counter->SetSemiPeriodMode(true);
+	m_counter->Reset();
+	m_enabled = true; // make it available for round robin scheduling
+	SetAutomaticMode(originalMode);
+
+	static int instances = 0;
+	instances++;
+	HALReport(HALUsageReporting::kResourceType_Ultrasonic, instances);
+}
+
+/**
+ * Create an instance of the Ultrasonic Sensor
+ * This is designed to supchannel the Daventech SRF04 and Vex ultrasonic sensors.
+ * @param pingChannel The digital output channel that sends the pulse to initiate the sensor sending
+ * the ping.
+ * @param echoChannel The digital input channel that receives the echo. The length of time that the
+ * echo is high represents the round trip time of the ping, and the distance.
+ * @param units The units returned in either kInches or kMilliMeters
+ */
+Ultrasonic::Ultrasonic(uint32_t pingChannel, uint32_t echoChannel, DistanceUnit units)
+{
+	m_pingChannel = new DigitalOutput(pingChannel);
+	m_echoChannel = new DigitalInput(echoChannel);
+	m_allocatedChannels = true;
+	m_units = units;
+	Initialize();
+}
+
+/**
+ * Create an instance of an Ultrasonic Sensor from a DigitalInput for the echo channel and a DigitalOutput
+ * for the ping channel.
+ * @param pingChannel The digital output object that starts the sensor doing a ping. Requires a 10uS pulse to start.
+ * @param echoChannel The digital input object that times the return pulse to determine the range.
+ * @param units The units returned in either kInches or kMilliMeters
+ */
+Ultrasonic::Ultrasonic(DigitalOutput *pingChannel, DigitalInput *echoChannel, DistanceUnit units)
+{
+	if (pingChannel == NULL || echoChannel == NULL)
+	{
+		wpi_setWPIError(NullParameter);
+		return;
+	}
+	m_allocatedChannels = false;
+	m_pingChannel = pingChannel;
+	m_echoChannel = echoChannel;
+	m_units = units;
+	Initialize();
+}
+
+/**
+ * Create an instance of an Ultrasonic Sensor from a DigitalInput for the echo channel and a DigitalOutput
+ * for the ping channel.
+ * @param pingChannel The digital output object that starts the sensor doing a ping. Requires a 10uS pulse to start.
+ * @param echoChannel The digital input object that times the return pulse to determine the range.
+ * @param units The units returned in either kInches or kMilliMeters
+ */
+Ultrasonic::Ultrasonic(DigitalOutput &pingChannel, DigitalInput &echoChannel, DistanceUnit units)
+{
+	m_allocatedChannels = false;
+	m_pingChannel = &pingChannel;
+	m_echoChannel = &echoChannel;
+	m_units = units;
+	Initialize();
+}
+
+/**
+ * Destructor for the ultrasonic sensor.
+ * Delete the instance of the ultrasonic sensor by freeing the allocated digital channels.
+ * If the system was in automatic mode (round robin), then it is stopped, then started again
+ * after this sensor is removed (provided this wasn't the last sensor).
+ */
+Ultrasonic::~Ultrasonic()
+{
+	bool wasAutomaticMode = m_automaticEnabled;
+	SetAutomaticMode(false);
+	if (m_allocatedChannels)
+	{
+		delete m_pingChannel;
+		delete m_echoChannel;
+	}
+	wpi_assert(m_firstSensor != NULL);
+
+	takeSemaphore(m_semaphore);
+	{
+		if (this == m_firstSensor)
+		{
+			m_firstSensor = m_nextSensor;
+			if (m_firstSensor == NULL)
+			{
+				SetAutomaticMode(false);
+			}
+		}
+		else
+		{
+			wpi_assert(m_firstSensor->m_nextSensor != NULL);
+			for (Ultrasonic *s = m_firstSensor; s != NULL; s = s->m_nextSensor)
+			{
+				if (this == s->m_nextSensor)
+				{
+					s->m_nextSensor = s->m_nextSensor->m_nextSensor;
+					break;
+				}
+			}
+		}
+	}
+	giveSemaphore(m_semaphore);
+	if (m_firstSensor != NULL && wasAutomaticMode)
+		SetAutomaticMode(true);
+}
+
+/**
+ * Turn Automatic mode on/off.
+ * When in Automatic mode, all sensors will fire in round robin, waiting a set
+ * time between each sensor.
+ * @param enabling Set to true if round robin scheduling should start for all the ultrasonic sensors. This
+ * scheduling method assures that the sensors are non-interfering because no two sensors fire at the same time.
+ * If another scheduling algorithm is preffered, it can be implemented by pinging the sensors manually and waiting
+ * for the results to come back.
+ */
+void Ultrasonic::SetAutomaticMode(bool enabling)
+{
+	if (enabling == m_automaticEnabled)
+		return; // ignore the case of no change
+
+	m_automaticEnabled = enabling;
+	if (enabling)
+	{
+		// enabling automatic mode.
+		// Clear all the counters so no data is valid
+		for (Ultrasonic *u = m_firstSensor; u != NULL; u = u->m_nextSensor)
+		{
+			u->m_counter->Reset();
+		}
+		// Start round robin task
+		wpi_assert(m_task.Verify() == false);	// should be false since was previously disabled
+		m_task.Start();
+	}
+	else
+	{
+		// disabling automatic mode. Wait for background task to stop running.
+		while (m_task.Verify())
+			Wait(0.15);	// just a little longer than the ping time for round-robin to stop
+
+		// clear all the counters (data now invalid) since automatic mode is stopped
+		for (Ultrasonic *u = m_firstSensor; u != NULL; u = u->m_nextSensor)
+		{
+			u->m_counter->Reset();
+		}
+		m_task.Stop();
+	}
+}
+
+/**
+ * Single ping to ultrasonic sensor.
+ * Send out a single ping to the ultrasonic sensor. This only works if automatic (round robin)
+ * mode is disabled. A single ping is sent out, and the counter should count the semi-period
+ * when it comes in. The counter is reset to make the current value invalid.
+ */
+void Ultrasonic::Ping()
+{
+	wpi_assert(!m_automaticEnabled);
+	m_counter->Reset(); // reset the counter to zero (invalid data now)
+	m_pingChannel->Pulse(kPingTime); // do the ping to start getting a single range
+}
+
+/**
+ * Check if there is a valid range measurement.
+ * The ranges are accumulated in a counter that will increment on each edge of the echo (return)
+ * signal. If the count is not at least 2, then the range has not yet been measured, and is invalid.
+ */
+bool Ultrasonic::IsRangeValid()
+{
+	return m_counter->Get() > 1;
+}
+
+/**
+ * Get the range in inches from the ultrasonic sensor.
+ * @return double Range in inches of the target returned from the ultrasonic sensor. If there is
+ * no valid value yet, i.e. at least one measurement hasn't completed, then return 0.
+ */
+double Ultrasonic::GetRangeInches()
+{
+	if (IsRangeValid())
+		return m_counter->GetPeriod() * kSpeedOfSoundInchesPerSec / 2.0;
+	else
+		return 0;
+}
+
+/**
+ * Get the range in millimeters from the ultrasonic sensor.
+ * @return double Range in millimeters of the target returned by the ultrasonic sensor.
+ * If there is no valid value yet, i.e. at least one measurement hasn't complted, then return 0.
+ */
+double Ultrasonic::GetRangeMM()
+{
+	return GetRangeInches() * 25.4;
+}
+
+/**
+ * Get the range in the current DistanceUnit for the PIDSource base object.
+ *
+ * @return The range in DistanceUnit
+ */
+double Ultrasonic::PIDGet()
+{
+	switch(m_units)
+	{
+	case Ultrasonic::kInches:
+		return GetRangeInches();
+	case Ultrasonic::kMilliMeters:
+		return GetRangeMM();
+	default:
+		return 0.0;
+	}
+}
+
+/**
+ * Set the current DistanceUnit that should be used for the PIDSource base object.
+ *
+ * @param units The DistanceUnit that should be used.
+ */
+void Ultrasonic::SetDistanceUnits(DistanceUnit units)
+{
+	m_units = units;
+}
+
+/**
+ * Get the current DistanceUnit that is used for the PIDSource base object.
+ *
+ * @return The type of DistanceUnit that is being used.
+ */
+Ultrasonic::DistanceUnit Ultrasonic::GetDistanceUnits()
+{
+	return m_units;
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Utility.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Utility.cpp
new file mode 100644
index 0000000..d94472b
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Utility.cpp
@@ -0,0 +1,271 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "Utility.h"
+
+//#include "NetworkCommunication/FRCComm.h"
+#include "HAL/HAL.hpp"
+#include "Task.h"
+#include <iostream>
+#include <sstream>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <execinfo.h>
+#include <cxxabi.h>
+#include "nivision.h"
+
+static bool suspendOnAssertEnabled = false;
+
+/**
+ * Enable suspend on assert.
+ * If enabled, the user task will be suspended whenever an assert fails. This
+ * will allow the user to attach to the task with the debugger and examine variables
+ * around the failure.
+ */
+void wpi_suspendOnAssertEnabled(bool enabled)
+{
+	suspendOnAssertEnabled = enabled;
+}
+
+/**
+ * Assert implementation.
+ * This allows breakpoints to be set on an assert.
+ * The users don't call this, but instead use the wpi_assert macros in Utility.h.
+ */
+bool wpi_assert_impl(bool conditionValue,
+                     const char *conditionText,
+                     const char *message,
+                     const char *fileName,
+                     uint32_t lineNumber,
+                     const char *funcName)
+{
+	if(!conditionValue)
+	{
+		std::stringstream errorStream;
+
+		errorStream << "Assertion \"" << conditionText << "\" ";
+		errorStream << "on line " << lineNumber << " ";
+		errorStream << "of "<< basename(fileName) << " ";
+
+		if(message)
+		{
+			errorStream << "failed: " << message << std::endl;
+		}
+		else
+		{
+			errorStream << "failed." << std::endl;
+		}
+
+		errorStream << GetStackTrace(2);
+
+		std::string error = errorStream.str();
+
+		// Print the error and send it to the DriverStation
+		std::cout << error << std::endl;
+		HALSetErrorData(error.c_str(), error.size(), 100);
+
+		if (suspendOnAssertEnabled) suspendTask(0);
+	}
+
+	return conditionValue;
+}
+
+/**
+ * Common error routines for wpi_assertEqual_impl and wpi_assertNotEqual_impl
+ * This should not be called directly; it should only be used by wpi_assertEqual_impl
+ * and wpi_assertNotEqual_impl.
+ */
+void wpi_assertEqual_common_impl(const char *valueA,
+                                 const char *valueB,
+                                 const char *equalityType,
+                                 const char *message,
+                                 const char *fileName,
+                                 uint32_t lineNumber,
+                                 const char *funcName)
+{
+	std::stringstream errorStream;
+
+	errorStream << "Assertion \"" << valueA << " " << equalityType << " " << valueB << "\" ";
+	errorStream << "on line " << lineNumber << " ";
+	errorStream << "of "<< basename(fileName) << " ";
+
+	if(message)
+	{
+		errorStream << "failed: " << message << std::endl;
+	}
+	else
+	{
+		errorStream << "failed." << std::endl;
+	}
+
+	errorStream << GetStackTrace(3);
+
+	std::string error = errorStream.str();
+
+	// Print the error and send it to the DriverStation
+	std::cout << error << std::endl;
+	HALSetErrorData(error.c_str(), error.size(), 100);
+
+	if (suspendOnAssertEnabled) suspendTask(0);
+}
+
+/**
+ * Assert equal implementation.
+ * This determines whether the two given integers are equal. If not,
+ * the value of each is printed along with an optional message string.
+ * The users don't call this, but instead use the wpi_assertEqual macros in Utility.h.
+ */
+bool wpi_assertEqual_impl(int valueA,
+                          int valueB,
+                          const char *valueAString,
+                          const char *valueBString,
+                          const char *message,
+                          const char *fileName,
+                          uint32_t lineNumber,
+                          const char *funcName)
+{
+	if(!(valueA == valueB))
+	{
+		wpi_assertEqual_common_impl(valueAString, valueBString,
+			"==", message, fileName, lineNumber, funcName);
+	}
+	return valueA == valueB;
+}
+
+/**
+ * Assert not equal implementation.
+ * This determines whether the two given integers are equal. If so,
+ * the value of each is printed along with an optional message string.
+ * The users don't call this, but instead use the wpi_assertNotEqual macros in Utility.h.
+ */
+bool wpi_assertNotEqual_impl(int valueA,
+                             int valueB,
+                             const char *valueAString,
+                             const char *valueBString,
+                             const char *message,
+                             const char *fileName,
+                             uint32_t lineNumber,
+                             const char *funcName)
+{
+	if(!(valueA != valueB))
+	{
+		wpi_assertEqual_common_impl(valueAString, valueBString,
+			"!=", message, fileName, lineNumber, funcName);
+	}
+	return valueA != valueB;
+}
+
+
+/**
+ * Return the FPGA Version number.
+ * For now, expect this to be competition year.
+ * @return FPGA Version number.
+ */
+uint16_t GetFPGAVersion()
+{
+	int32_t status = 0;
+	uint16_t version = getFPGAVersion(&status);
+	wpi_setGlobalErrorWithContext(status, getHALErrorMessage(status));
+	return version;
+}
+
+/**
+ * Return the FPGA Revision number.
+ * The format of the revision is 3 numbers.
+ * The 12 most significant bits are the Major Revision.
+ * the next 8 bits are the Minor Revision.
+ * The 12 least significant bits are the Build Number.
+ * @return FPGA Revision number.
+ */
+uint32_t GetFPGARevision()
+{
+	int32_t status = 0;
+	uint32_t revision = getFPGARevision(&status);
+	wpi_setGlobalErrorWithContext(status, getHALErrorMessage(status));
+	return revision;
+}
+
+/**
+ * Read the microsecond-resolution timer on the FPGA.
+ *
+ * @return The current time in microseconds according to the FPGA (since FPGA reset).
+ */
+uint32_t GetFPGATime()
+{
+	int32_t status = 0;
+	uint32_t time = getFPGATime(&status);
+	wpi_setGlobalErrorWithContext(status, getHALErrorMessage(status));
+	return time;
+}
+
+/**
+ * Get the state of the "USER" button on the RoboRIO
+ * @return True if the button is currently pressed down
+ */
+bool GetUserButton()
+{
+	int32_t status = 0;
+
+	bool value = getFPGAButton(&status);
+	wpi_setGlobalError(status);
+
+	return value;
+}
+
+/**
+ * Demangle a C++ symbol, used for printing stack traces.
+ */
+static std::string demangle(char const *mangledSymbol)
+{
+	char buffer[256];
+	size_t length;
+	int status;
+
+
+	if(sscanf(mangledSymbol, "%*[^(]%*[(]%255[^)+]", buffer))
+	{
+		char *symbol = abi::__cxa_demangle(buffer, NULL, &length, &status);
+		if(status == 0)
+		{
+			return symbol;
+		}
+		else
+		{
+			// If the symbol couldn't be demangled, it's probably a C function,
+			// so just return it as-is.
+			return buffer;
+		}
+	}
+
+	// If everything else failed, just return the mangled symbol
+	return mangledSymbol;
+}
+
+/**
+ * Get a stack trace, ignoring the first "offset" symbols.
+ * @param offset The number of symbols at the top of the stack to ignore
+ */
+std::string GetStackTrace(uint32_t offset)
+{
+	void *stackTrace[128];
+	int stackSize = backtrace(stackTrace, 128);
+	char **mangledSymbols = backtrace_symbols(stackTrace, stackSize);
+	std::stringstream trace;
+
+	for(int i = offset; i < stackSize; i++)
+	{
+		// Only print recursive functions once in a row.
+		if(i == 0 ||stackTrace[i] != stackTrace[i - 1])
+		{
+			trace << "\tat " << demangle(mangledSymbols[i]) << std::endl;
+		}
+	}
+
+	free(mangledSymbols);
+
+	return trace.str();
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Victor.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Victor.cpp
new file mode 100644
index 0000000..c1cfb71
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Victor.cpp
@@ -0,0 +1,89 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "Victor.h"
+
+//#include "NetworkCommunication/UsageReporting.h"
+
+/**
+ * Common initialization code called by all constructors.
+ *
+ * Note that the Victor uses the following bounds for PWM values.  These values were determined
+ * empirically and optimized for the Victor 888. These values should work reasonably well for
+ * Victor 884 controllers as well but if users experience issues such as asymmetric behaviour around
+ * the deadband or inability to saturate the controller in either direction, calibration is recommended.
+ * The calibration procedure can be found in the Victor 884 User Manual available from IFI.
+ *
+ *   2.027ms = full "forward"
+ *   1.525ms = the "high end" of the deadband range
+ *   1.507ms = center of the deadband range (off)
+ *   1.49ms = the "low end" of the deadband range
+ *   1.026ms = full "reverse"
+ */
+void Victor::InitVictor() {
+	SetBounds(2.027, 1.525, 1.507, 1.49, 1.026);
+
+	SetPeriodMultiplier(kPeriodMultiplier_2X);
+	SetRaw(m_centerPwm);
+	SetZeroLatch();
+
+	HALReport(HALUsageReporting::kResourceType_Victor, GetChannel());
+}
+
+/**
+ * Constructor for a Victor
+ * @param channel The PWM channel number that the Victor is attached to. 0-9 are on-board, 10-19 are on the MXP port
+ */
+Victor::Victor(uint32_t channel) : SafePWM(channel)
+{
+	InitVictor();
+}
+
+Victor::~Victor()
+{
+}
+
+/**
+ * Set the PWM value.
+ *
+ * The PWM value is set using a range of -1.0 to 1.0, appropriately
+ * scaling the value for the FPGA.
+ *
+ * @param speed The speed value between -1.0 and 1.0 to set.
+ * @param syncGroup Unused interface.
+ */
+void Victor::Set(float speed, uint8_t syncGroup)
+{
+	SetSpeed(speed);
+}
+
+/**
+ * Get the recently set value of the PWM.
+ *
+ * @return The most recently set value for the PWM between -1.0 and 1.0.
+ */
+float Victor::Get()
+{
+	return GetSpeed();
+}
+
+/**
+ * Common interface for disabling a motor.
+ */
+void Victor::Disable()
+{
+	SetRaw(kPwmDisabled);
+}
+
+/**
+ * Write out the PID value as seen in the PIDOutput base object.
+ *
+ * @param output Write out the PWM value as was found in the PIDController
+ */
+void Victor::PIDWrite(float output)
+{
+	Set(output);
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/VictorSP.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/VictorSP.cpp
new file mode 100644
index 0000000..39cdda6
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/VictorSP.cpp
@@ -0,0 +1,87 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "VictorSP.h"
+
+//#include "NetworkCommunication/UsageReporting.h"
+
+/**
+ * Common initialization code called by all constructors.
+ *
+ * Note that the VictorSP uses the following bounds for PWM values. These values should work reasonably well for
+ * most controllers, but if users experience issues such as asymmetric behavior around
+ * the deadband or inability to saturate the controller in either direction, calibration is recommended.
+ * The calibration procedure can be found in the VictorSP User Manual available from Vex.
+ *
+ *   2.004ms = full "forward"
+ *   1.52ms = the "high end" of the deadband range
+ *   1.50ms = center of the deadband range (off)
+ *   1.48ms = the "low end" of the deadband range
+ *   0.997ms = full "reverse"
+ */
+void VictorSP::InitVictorSP() {
+	SetBounds(2.004, 1.52, 1.50, 1.48, .997);
+	SetPeriodMultiplier(kPeriodMultiplier_1X);
+	SetRaw(m_centerPwm);
+	SetZeroLatch();
+
+	HALReport(HALUsageReporting::kResourceType_Talon, GetChannel());
+}
+
+/**
+ * Constructor for a VictorSP 
+ * @param channel The PWM channel that the VictorSP is attached to. 0-9 are on-board, 10-19 are on the MXP port
+ */
+VictorSP::VictorSP(uint32_t channel) : SafePWM(channel)
+{
+	InitVictorSP();
+}
+
+VictorSP::~VictorSP()
+{
+}
+
+/**
+ * Set the PWM value.
+ *
+ * The PWM value is set using a range of -1.0 to 1.0, appropriately
+ * scaling the value for the FPGA.
+ *
+ * @param speed The speed value between -1.0 and 1.0 to set.
+ * @param syncGroup Unused interface.
+ */
+void VictorSP::Set(float speed, uint8_t syncGroup)
+{
+	SetSpeed(speed);
+}
+
+/**
+ * Get the recently set value of the PWM.
+ *
+ * @return The most recently set value for the PWM between -1.0 and 1.0.
+ */
+float VictorSP::Get()
+{
+	return GetSpeed();
+}
+
+/**
+ * Common interface for disabling a motor.
+ */
+void VictorSP::Disable()
+{
+	SetRaw(kPwmDisabled);
+}
+
+/**
+ * Write out the PID value as seen in the PIDOutput base object.
+ *
+ * @param output Write out the PWM value as was found in the PIDController
+ */
+void VictorSP::PIDWrite(float output)
+{
+	Set(output);
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/AxisCamera.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/AxisCamera.cpp
new file mode 100644
index 0000000..47658d0
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/AxisCamera.cpp
@@ -0,0 +1,645 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "Vision/AxisCamera.h"
+
+#include "WPIErrors.h"
+
+#include <cstring>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <Timer.h>
+#include <iostream>
+#include <sstream>
+
+static const unsigned int kMaxPacketSize = 1536;
+static const unsigned int kImageBufferAllocationIncrement = 1000;
+
+static const std::string kWhiteBalanceStrings[] =
+{ "auto", "hold", "fixed_outdoor1", "fixed_outdoor2", "fixed_indoor",
+		"fixed_fluor1", "fixed_fluor2", };
+
+static const std::string kExposureControlStrings[] =
+{ "auto", "hold", "flickerfree50", "flickerfree60", };
+
+static const std::string kResolutionStrings[] =
+{ "640x480", "480x360", "320x240", "240x180", "176x144", "160x120", };
+
+static const std::string kRotationStrings[] =
+{ "0", "180", };
+
+/**
+ * AxisCamera constructor
+ * @param cameraHost The host to find the camera at, typically an IP address
+ */
+AxisCamera::AxisCamera(std::string const& cameraHost)
+		: m_cameraHost(cameraHost)
+		, m_cameraSocket(-1)
+		, m_freshImage(false)
+		, m_brightness(50)
+		, m_whiteBalance(kWhiteBalance_Automatic)
+		, m_colorLevel(50)
+		, m_exposureControl(kExposureControl_Automatic)
+		, m_exposurePriority(50)
+		, m_maxFPS(0)
+		, m_resolution(kResolution_640x480)
+		, m_compression(50)
+		, m_rotation(kRotation_0)
+		, m_parametersDirty(true)
+		, m_streamDirty(true)
+		, m_done(false)
+{
+	m_captureThread = std::thread(&AxisCamera::Capture, this);
+}
+
+AxisCamera::~AxisCamera()
+{
+	m_done = true;
+	m_captureThread.join();
+}
+
+/*
+ * Return true if the latest image from the camera has not been retrieved by calling GetImage() yet.
+ * @return true if the image has not been retrieved yet.
+ */
+bool AxisCamera::IsFreshImage() const
+{
+	return m_freshImage;
+}
+
+/**
+ * Get an image from the camera and store it in the provided image.
+ * @param image The imaq image to store the result in. This must be an HSL or RGB image.
+ * @return 1 upon success, zero on a failure
+ */
+int AxisCamera::GetImage(Image *image)
+{
+	if (m_imageData.size() == 0)
+	{
+		return 0;
+	}
+
+	std::lock_guard<std::mutex> lock(m_imageDataMutex);
+
+	Priv_ReadJPEGString_C(image, m_imageData.data(), m_imageData.size());
+
+	m_freshImage = false;
+
+	return 1;
+}
+
+/**
+ * Get an image from the camera and store it in the provided image.
+ * @param image The image to store the result in. This must be an HSL or RGB image
+ * @return 1 upon success, zero on a failure
+ */
+int AxisCamera::GetImage(ColorImage *image)
+{
+	return GetImage(image->GetImaqImage());
+}
+
+/**
+ * Instantiate a new image object and fill it with the latest image from the camera.
+ *
+ * The returned pointer is owned by the caller and is their responsibility to delete.
+ * @return a pointer to an HSLImage object
+ */
+HSLImage *AxisCamera::GetImage()
+{
+	HSLImage *image = new HSLImage();
+	GetImage(image);
+	return image;
+}
+
+/**
+ * Copy an image into an existing buffer.
+ * This copies an image into an existing buffer rather than creating a new image
+ * in memory. That way a new image is only allocated when the image being copied is
+ * larger than the destination.
+ * This method is called by the PCVideoServer class.
+ * @param imageData The destination image.
+ * @param numBytes The size of the destination image.
+ * @return 0 if failed (no source image or no memory), 1 if success.
+ */
+int AxisCamera::CopyJPEG(char **destImage, unsigned int &destImageSize, unsigned int &destImageBufferSize)
+{
+	std::lock_guard<std::mutex> lock(m_imageDataMutex);
+	if (destImage == NULL)
+		wpi_setWPIErrorWithContext(NullParameter, "destImage must not be NULL");
+
+	if (m_imageData.size() == 0)
+		return 0; // if no source image
+
+	if (destImageBufferSize < m_imageData.size()) // if current destination buffer too small
+	{
+		if (*destImage != NULL) delete [] *destImage;
+		destImageBufferSize = m_imageData.size() + kImageBufferAllocationIncrement;
+		*destImage = new char[destImageBufferSize];
+		if (*destImage == NULL) return 0;
+	}
+	// copy this image into destination buffer
+	if (*destImage == NULL)
+	{
+		wpi_setWPIErrorWithContext(NullParameter, "*destImage must not be NULL");
+	}
+	
+	std::copy(m_imageData.begin(), m_imageData.end(), *destImage);
+	destImageSize = m_imageData.size();;
+	return 1;
+}
+
+/**
+ * Request a change in the brightness of the camera images.
+ * @param brightness valid values 0 .. 100
+ */
+void AxisCamera::WriteBrightness(int brightness)
+{
+	if (brightness < 0 || brightness > 100)
+	{
+		wpi_setWPIErrorWithContext(ParameterOutOfRange,
+				"Brightness must be from 0 to 100");
+		return;
+	}
+
+	std::lock_guard<std::mutex> lock(m_parametersMutex);
+
+	if (m_brightness != brightness)
+	{
+		m_brightness = brightness;
+		m_parametersDirty = true;
+	}
+}
+
+/**
+ * @return The configured brightness of the camera images
+ */
+int AxisCamera::GetBrightness()
+{
+	std::lock_guard<std::mutex> lock(m_parametersMutex);
+	return m_brightness;
+}
+
+/**
+ * Request a change in the white balance on the camera.
+ * @param whiteBalance Valid values from the <code>WhiteBalance</code> enum.
+ */
+void AxisCamera::WriteWhiteBalance(AxisCamera::WhiteBalance whiteBalance)
+{
+	std::lock_guard<std::mutex> lock(m_parametersMutex);
+
+	if (m_whiteBalance != whiteBalance)
+	{
+		m_whiteBalance = whiteBalance;
+		m_parametersDirty = true;
+	}
+}
+
+/**
+ * @return The configured white balances of the camera images
+ */
+AxisCamera::WhiteBalance AxisCamera::GetWhiteBalance()
+{
+	std::lock_guard<std::mutex> lock(m_parametersMutex);
+	return m_whiteBalance;
+}
+
+/**
+ * Request a change in the color level of the camera images.
+ * @param colorLevel valid values are 0 .. 100
+ */
+void AxisCamera::WriteColorLevel(int colorLevel)
+{
+	if (colorLevel < 0 || colorLevel > 100)
+	{
+		wpi_setWPIErrorWithContext(ParameterOutOfRange,
+				"Color level must be from 0 to 100");
+		return;
+	}
+
+	std::lock_guard<std::mutex> lock(m_parametersMutex);
+
+	if (m_colorLevel != colorLevel)
+	{
+		m_colorLevel = colorLevel;
+		m_parametersDirty = true;
+	}
+}
+
+/**
+ * @return The configured color level of the camera images
+ */
+int AxisCamera::GetColorLevel()
+{
+	std::lock_guard<std::mutex> lock(m_parametersMutex);
+	return m_colorLevel;
+}
+
+/**
+ * Request a change in the camera's exposure mode.
+ * @param exposureControl A mode to write in the <code>Exposure</code> enum.
+ */
+void AxisCamera::WriteExposureControl(
+		AxisCamera::ExposureControl exposureControl)
+{
+	std::lock_guard<std::mutex> lock(m_parametersMutex);
+
+	if (m_exposureControl != exposureControl)
+	{
+		m_exposureControl = exposureControl;
+		m_parametersDirty = true;
+	}
+}
+
+/**
+ * @return The configured exposure control mode of the camera
+ */
+AxisCamera::ExposureControl AxisCamera::GetExposureControl()
+{
+	std::lock_guard<std::mutex> lock(m_parametersMutex);
+	return m_exposureControl;
+}
+
+/**
+ * Request a change in the exposure priority of the camera.
+ * @param exposurePriority Valid values are 0, 50, 100.
+ * 0 = Prioritize image quality
+ * 50 = None
+ * 100 = Prioritize frame rate
+ */
+void AxisCamera::WriteExposurePriority(int exposurePriority)
+{
+	if (exposurePriority != 0 && exposurePriority != 50
+			&& exposurePriority != 100)
+	{
+		wpi_setWPIErrorWithContext(ParameterOutOfRange,
+				"Exposure priority must be from 0, 50, or 100");
+		return;
+	}
+
+	std::lock_guard<std::mutex> lock(m_parametersMutex);
+
+	if (m_exposurePriority != exposurePriority)
+	{
+		m_exposurePriority = exposurePriority;
+		m_parametersDirty = true;
+	}
+}
+
+/**
+ * @return The configured exposure priority of the camera
+ */
+int AxisCamera::GetExposurePriority()
+{
+	std::lock_guard<std::mutex> lock(m_parametersMutex);
+	return m_exposurePriority;
+}
+
+/**
+ * Write the maximum frames per second that the camera should send
+ * Write 0 to send as many as possible.
+ * @param maxFPS The number of frames the camera should send in a second, exposure permitting.
+ */
+void AxisCamera::WriteMaxFPS(int maxFPS)
+{
+	std::lock_guard<std::mutex> lock(m_parametersMutex);
+
+	if (m_maxFPS != maxFPS)
+	{
+		m_maxFPS = maxFPS;
+		m_parametersDirty = true;
+		m_streamDirty = true;
+	}
+}
+
+/**
+ * @return The configured maximum FPS of the camera
+ */
+int AxisCamera::GetMaxFPS()
+{
+	std::lock_guard<std::mutex> lock(m_parametersMutex);
+	return m_maxFPS;
+}
+
+/**
+ * Write resolution value to camera.
+ * @param resolution The camera resolution value to write to the camera.
+ */
+void AxisCamera::WriteResolution(AxisCamera::Resolution resolution)
+{
+	std::lock_guard<std::mutex> lock(m_parametersMutex);
+
+	if (m_resolution != resolution)
+	{
+		m_resolution = resolution;
+		m_parametersDirty = true;
+		m_streamDirty = true;
+	}
+}
+
+/**
+ * @return The configured resolution of the camera (not necessarily the same
+ * resolution as the most recent image, if it was changed recently.)
+ */
+AxisCamera::Resolution AxisCamera::GetResolution()
+{
+	std::lock_guard<std::mutex> lock(m_parametersMutex);
+	return m_resolution;
+}
+
+/**
+ * Write the rotation value to the camera.
+ * If you mount your camera upside down, use this to adjust the image for you.
+ * @param rotation The angle to rotate the camera (<code>AxisCamera::Rotation::k0</code>
+ * or <code>AxisCamera::Rotation::k180</code>)
+ */
+void AxisCamera::WriteRotation(AxisCamera::Rotation rotation)
+{
+	std::lock_guard<std::mutex> lock(m_parametersMutex);
+
+	if (m_rotation != rotation)
+	{
+		m_rotation = rotation;
+		m_parametersDirty = true;
+		m_streamDirty = true;
+	}
+}
+
+/**
+ * @return The configured rotation mode of the camera
+ */
+AxisCamera::Rotation AxisCamera::GetRotation()
+{
+	std::lock_guard<std::mutex> lock(m_parametersMutex);
+	return m_rotation;
+}
+
+/**
+ * Write the compression value to the camera.
+ * @param compression Values between 0 and 100.
+ */
+void AxisCamera::WriteCompression(int compression)
+{
+	if (compression < 0 || compression > 100)
+	{
+		wpi_setWPIErrorWithContext(ParameterOutOfRange,
+				"Compression must be from 0 to 100");
+		return;
+	}
+
+	std::lock_guard<std::mutex> lock(m_parametersMutex);
+
+	if (m_compression != compression)
+	{
+		m_compression = compression;
+		m_parametersDirty = true;
+		m_streamDirty = true;
+	}
+}
+
+/**
+ * @return The configured compression level of the camera
+ */
+int AxisCamera::GetCompression()
+{
+	std::lock_guard<std::mutex> lock(m_parametersMutex);
+	return m_compression;
+}
+
+/**
+ * Method called in the capture thread to receive images from the camera
+ */
+void AxisCamera::Capture()
+{
+	int consecutiveErrors = 0;
+
+	// Loop on trying to setup the camera connection. This happens in a background
+	// thread so it shouldn't effect the operation of user programs.
+	while (!m_done)
+	{
+		std::string requestString = "GET /mjpg/video.mjpg HTTP/1.1\n"
+				"User-Agent: HTTPStreamClient\n"
+				"Connection: Keep-Alive\n"
+				"Cache-Control: no-cache\n"
+				"Authorization: Basic RlJDOkZSQw==\n\n";
+		m_captureMutex.lock();
+		m_cameraSocket = CreateCameraSocket(requestString, consecutiveErrors > 5);
+		if (m_cameraSocket != -1)
+		{
+			ReadImagesFromCamera();
+			consecutiveErrors = 0;
+		}
+		else
+		{
+			consecutiveErrors++;
+		}
+		m_captureMutex.unlock();
+		Wait(0.5);
+	}
+}
+
+/**
+ * This function actually reads the images from the camera.
+ */
+void AxisCamera::ReadImagesFromCamera()
+{
+	char *imgBuffer = NULL;
+	int imgBufferLength = 0;
+
+	// TODO: these recv calls must be non-blocking. Otherwise if the camera
+	// fails during a read, the code hangs and never retries when the camera comes
+	// back up.
+
+	int counter = 2;
+	while (!m_done)
+	{
+		char initialReadBuffer[kMaxPacketSize] = "";
+		char intermediateBuffer[1];
+		char *trailingPtr = initialReadBuffer;
+		int trailingCounter = 0;
+		while (counter)
+		{
+			// TODO: fix me... this cannot be the most efficient way to approach this, reading one byte at a time.
+			if (recv(m_cameraSocket, intermediateBuffer, 1, 0) == -1)
+			{
+				wpi_setErrnoErrorWithContext("Failed to read image header");
+				close(m_cameraSocket);
+				return;
+			}
+			strncat(initialReadBuffer, intermediateBuffer, 1);
+			// trailingCounter ensures that we start looking for the 4 byte string after
+			// there is at least 4 bytes total. Kind of obscure.
+			// look for 2 blank lines (\r\n)
+			if (NULL != strstr(trailingPtr, "\r\n\r\n"))
+			{
+				--counter;
+			}
+			if (++trailingCounter >= 4)
+			{
+				trailingPtr++;
+			}
+		}
+		counter = 1;
+		char *contentLength = strstr(initialReadBuffer, "Content-Length: ");
+		if (contentLength == NULL)
+		{
+			wpi_setWPIErrorWithContext(IncompatibleMode,
+					"No content-length token found in packet");
+			close(m_cameraSocket);
+			return;
+		}
+		contentLength = contentLength + 16; // skip past "content length"
+		int readLength = atol(contentLength); // get the image byte count
+
+		// Make sure buffer is large enough
+		if (imgBufferLength < readLength)
+		{
+			if (imgBuffer)
+				delete[] imgBuffer;
+			imgBufferLength = readLength + kImageBufferAllocationIncrement;
+			imgBuffer = new char[imgBufferLength];
+			if (imgBuffer == NULL)
+			{
+				imgBufferLength = 0;
+				continue;
+			}
+		}
+
+		// Read the image data for "Content-Length" bytes
+		int bytesRead = 0;
+		int remaining = readLength;
+		while (bytesRead < readLength)
+		{
+			int bytesThisRecv = recv(m_cameraSocket, &imgBuffer[bytesRead],
+					remaining, 0);
+			bytesRead += bytesThisRecv;
+			remaining -= bytesThisRecv;
+		}
+
+		// Update image
+		{
+			std::lock_guard<std::mutex> lock(m_imageDataMutex);
+
+			m_imageData.assign(imgBuffer, imgBuffer + imgBufferLength);
+			m_freshImage = true;
+		}
+
+		if (WriteParameters())
+		{
+			break;
+		}
+	}
+
+	close(m_cameraSocket);
+}
+
+/**
+ * Send a request to the camera to set all of the parameters.  This is called
+ * in the capture thread between each frame. This strategy avoids making lots
+ * of redundant HTTP requests, accounts for failed initial requests, and
+ * avoids blocking calls in the main thread unless necessary.
+ *
+ * This method does nothing if no parameters have been modified since it last
+ * completely successfully.
+ *
+ * @return <code>true</code> if the stream should be restarted due to a
+ * parameter changing.
+ */
+bool AxisCamera::WriteParameters()
+{
+	if (m_parametersDirty)
+	{
+		std::stringstream request;
+		request << "GET /axis-cgi/admin/param.cgi?action=update";
+
+		m_parametersMutex.lock();
+		request << "&ImageSource.I0.Sensor.Brightness=" << m_brightness;
+		request << "&ImageSource.I0.Sensor.WhiteBalance=" << kWhiteBalanceStrings[m_whiteBalance];
+		request << "&ImageSource.I0.Sensor.ColorLevel=" << m_colorLevel;
+		request << "&ImageSource.I0.Sensor.Exposure=" << kExposureControlStrings[m_exposureControl];
+		request << "&ImageSource.I0.Sensor.ExposurePriority=" << m_exposurePriority;
+		request << "&Image.I0.Stream.FPS=" << m_maxFPS;
+		request << "&Image.I0.Appearance.Resolution=" << kResolutionStrings[m_resolution];
+		request << "&Image.I0.Appearance.Compression=" << m_compression;
+		request << "&Image.I0.Appearance.Rotation=" << kRotationStrings[m_rotation];
+		m_parametersMutex.unlock();
+
+		request << " HTTP/1.1" << std::endl;
+		request << "User-Agent: HTTPStreamClient" << std::endl;
+		request << "Connection: Keep-Alive" << std::endl;
+		request << "Cache-Control: no-cache" << std::endl;
+		request << "Authorization: Basic RlJDOkZSQw==" << std::endl;
+		request << std::endl;
+
+		int socket = CreateCameraSocket(request.str(), false);
+		if (socket == -1)
+		{
+			wpi_setErrnoErrorWithContext("Error setting camera parameters");
+		}
+		else
+		{
+			close(socket);
+			m_parametersDirty = false;
+
+			if (m_streamDirty)
+			{
+				m_streamDirty = false;
+				return true;
+			}
+		}
+	}
+
+	return false;
+}
+
+/**
+ * Create a socket connected to camera
+ * Used to create a connection to the camera for both capturing images and setting parameters.
+ * @param requestString The initial request string to send upon successful connection.
+ * @param setError If true, rais an error if there's a problem creating the connection.
+ * This is only enabled after several unsucessful connections, so a single one doesn't
+ * cause an error message to be printed if it immediately recovers.
+ * @return -1 if failed, socket handle if successful.
+ */
+int AxisCamera::CreateCameraSocket(std::string const& requestString, bool setError)
+{
+	struct addrinfo *address = 0;
+	int camSocket;
+
+	/* create socket */
+	if ((camSocket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+	{
+		if (setError) wpi_setErrnoErrorWithContext("Failed to create the camera socket");
+		return -1;
+	}
+
+	if (getaddrinfo(m_cameraHost.c_str(), "80", 0, &address) == -1)
+	{
+		if (setError) wpi_setErrnoErrorWithContext("Failed to create the camera socket");
+		return -1;
+	}
+
+	/* connect to server */
+	if (connect(camSocket, address->ai_addr, address->ai_addrlen) == -1)
+	{
+		if (setError) wpi_setErrnoErrorWithContext("Failed to connect to the camera");
+		close(camSocket);
+		return -1;
+	}
+
+	int sent = send(camSocket, requestString.c_str(), requestString.size(), 0);
+	if (sent == -1)
+	{
+		if (setError) wpi_setErrnoErrorWithContext("Failed to send a request to the camera");
+		close(camSocket);
+		return -1;
+	}
+
+	return camSocket;
+}
+
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/BaeUtilities.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/BaeUtilities.cpp
new file mode 100644
index 0000000..278fa59
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/BaeUtilities.cpp
@@ -0,0 +1,385 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <math.h>
+#include <stdlib.h> 
+#include <stdarg.h> 
+ 
+#include "Vision/BaeUtilities.h"
+#include "Servo.h"
+#include "Timer.h"
+
+/** @file
+ *   Utility functions 
+ */
+
+/**
+ * debug output flag options:
+ * DEBUG_OFF, DEBUG_MOSTLY_OFF, DEBUG_SCREEN_ONLY, DEBUG_FILE_ONLY, DEBUG_SCREEN_AND_FILE
+ */
+static DebugOutputType	dprintfFlag = DEBUG_OFF;  
+
+/**
+ * Set the debug flag to print to screen, file on cRIO, both or neither
+ * @param tempString The format string.
+ */
+void SetDebugFlag ( DebugOutputType flag  )  
+{ dprintfFlag = flag; }
+
+/**
+ * Debug print to a file and/or a terminal window.
+ * Call like you would call printf.
+ * Set functionName in the function if you want the correct function name to print out.
+ * The file line number will also be printed.
+ * @param tempString The format string.
+ */
+void dprintf ( const char * tempString, ...  )  /* Variable argument list */
+{
+  va_list		args;			  /* Input argument list */
+  int			line_number;      /* Line number passed in argument */
+  int			type;
+  const char	*functionName;    /* Format passed in argument */
+  const char	*fmt;             /* Format passed in argument */
+  char			text[512];   	  /* Text string */
+  char			outtext[512];     /* Text string */
+  FILE			*outfile_fd;      /* Output file pointer */
+  char			filepath[128];    /* Text string */
+  int			fatalFlag=0;
+  const char	*filename;
+  int			index;
+  int			tempStringLen;
+
+  if (dprintfFlag == DEBUG_OFF) { return; }
+  
+  va_start (args, tempString);
+  
+  tempStringLen = strlen(tempString);
+  filename = tempString;
+  for (index=0;index<tempStringLen;index++){
+	  if (tempString[index] == ' ') {
+		  printf( "ERROR in dprintf: malformed calling sequence (%s)\n",tempString);return;
+	  	}
+	  if (tempString[index] == '\\' || tempString[index] == '/')
+		  filename = tempString + index + 1;
+  }
+  
+  /* Extract function name */
+  functionName = va_arg (args, const char *);
+ 
+ /* Extract line number from argument list */
+  line_number = va_arg (args, int);
+
+ /* Extract information type from argument list */
+  type = va_arg (args, int);
+
+ /* Extract format from argument list */
+  fmt = va_arg (args, const char *);
+
+  vsprintf (text, fmt, args);
+
+  va_end (args);
+
+  /* Format output statement */
+  switch (type)
+   {
+   case DEBUG_TYPE:
+     sprintf (outtext, "[%s:%s@%04d] DEBUG %s\n",
+              filename, functionName, line_number, text);
+     break;
+   case INFO_TYPE:
+     sprintf (outtext, "[%s:%s@%04d] INFO %s\n",
+              filename, functionName, line_number, text);
+     break;
+   case ERROR_TYPE:
+     sprintf (outtext, "[%s:%s@%04d] ERROR %s\n",
+              filename, functionName, line_number, text);
+     break;
+   case CRITICAL_TYPE:
+     sprintf (outtext, "[%s:%s@%04d] CRITICAL %s\n",
+              filename, functionName, line_number, text);
+     break;
+   case FATAL_TYPE:
+     fatalFlag = 1;
+     sprintf (outtext, "[%s:%s@%04d] FATAL %s\n",
+              filename, functionName, line_number, text);
+     break;
+   default:
+     printf( "ERROR in dprintf: malformed calling sequence\n");
+     return;
+     break;
+   }
+
+  sprintf (filepath, "%s.debug", filename);
+
+  /* Write output statement */
+  switch (dprintfFlag)
+  {
+  default:
+  case DEBUG_OFF: 
+  	break;
+  case DEBUG_MOSTLY_OFF: 
+  	if (fatalFlag)	{
+	  if ((outfile_fd = fopen (filepath, "a+")) != NULL)	  {
+	    fwrite (outtext, sizeof (char), strlen (outtext), outfile_fd);
+	    fclose (outfile_fd);
+	  }
+	}
+  	break;
+  case DEBUG_SCREEN_ONLY: 
+  	printf ("%s", outtext);
+  	break;
+  case DEBUG_FILE_ONLY: 
+	if ((outfile_fd = fopen (filepath, "a+")) != NULL)	{
+	  fwrite (outtext, sizeof (char), strlen (outtext), outfile_fd);
+	  fclose (outfile_fd);
+	}
+  	break;
+  case DEBUG_SCREEN_AND_FILE: // BOTH
+  	printf ("%s", outtext);
+	if ((outfile_fd = fopen (filepath, "a+")) != NULL)	{
+	  fwrite (outtext, sizeof (char), strlen (outtext), outfile_fd);
+	  fclose (outfile_fd);
+	}
+  	break;
+  }
+}
+
+/**
+ * @brief Normalizes a value in a range, used for drive input
+ * @param position The position in the range, starting at 0
+ * @param range The size of the range that position is in
+ * @return The normalized position from -1 to +1
+ */
+double RangeToNormalized(double position, int range){
+	return(((position*2.0)/(double)range)-1.0);
+}
+
+/**
+ * @brief Convert a normalized value to the corresponding value in a range.
+ * This is used to convert normalized values to the servo command range.
+ * @param normalizedValue The normalized value (in the -1 to +1 range)
+ * @param minRange The minimum of the range (0 is default)
+ * @param maxRange The maximum of the range (1 is default)
+ * @return The value in the range corresponding to the input normalized value
+ */
+float NormalizeToRange(float normalizedValue, float minRange, float maxRange) {
+	float range = maxRange-minRange;
+	float temp = (float)((normalizedValue / 2.0)+ 0.5)*range;
+	return (temp + minRange);
+}	
+float NormalizeToRange(float normalizedValue) {
+	return (float)((normalizedValue / 2.0) + 0.5);
+}	
+
+/**
+ * @brief Displays an activity indicator to console. 
+ * Call this function like you would call printf.
+ * @param fmt The format string
+*/
+void ShowActivity (char *fmt, ...)
+{
+  static char   activity_indication_string[] = "|/-\\";
+  static int    ai = 3;
+  va_list       args;
+  char          text[1024];
+
+  va_start (args, fmt);
+
+  vsprintf (text, fmt, args);
+
+  ai = ai == 3 ? 0 : ai + 1;
+
+  printf ("%c %s \r", activity_indication_string[ai], text);
+  fflush (stdout);
+
+  va_end (args);
+}
+
+#define PI 3.14159265358979
+/**
+ * @brief Calculate sine wave increments (-1.0 to 1.0). 
+ * The first time this is called, it sets up the time increment. Subsequent calls
+ * will give values along the sine wave depending on current time. If the wave is
+ * stopped and restarted, it must be reinitialized with a new "first call".
+ * 
+ * @param period length of time to complete a complete wave
+ * @param sinStart Where to start the sine wave (0.0 = 2 pi, pi/2 = 1.0, etc.)
+ */
+double SinPosition (double *period, double sinStart)
+{
+  double rtnVal;
+  static double sinePeriod=0.0;
+  static double timestamp;
+  double sinArg;
+
+  //1st call
+  if (period != NULL) {
+    sinePeriod = *period;
+	timestamp = GetTime();
+	return 0.0;
+  }
+
+  //Multiplying by 2*pi to the time difference makes sinePeriod work if it's measured in seconds.
+  //Adding sinStart to the part multiplied by PI, but not by 2, allows it to work as described in the comments.
+  sinArg = PI *((2.0 * (GetTime() - timestamp)) + sinStart) / sinePeriod;
+  rtnVal = sin (sinArg);  
+  return (rtnVal);
+}
+
+
+/**
+ * @brief Find the elapsed time since a specified time.
+ * @param startTime The starting time
+ * @return How long it has been since the starting time
+ */
+double ElapsedTime ( double startTime )  
+{
+	double realTime = GetTime();	
+	return (realTime-startTime);
+}
+
+/**
+ * @brief Initialize pan parameters
+ * @param period The number of seconds to complete one pan
+ */
+void panInit()	{
+	double period = 3.0;  	// number of seconds for one complete pan
+	SinPosition(&period, 0.0);	// initial call to set up time
+}
+
+void panInit(double period)	{
+	if (period < 0.0) period=3.0;
+	SinPosition(&period, 0.0);	// initial call to set up time
+}
+
+/**
+ * @brief Move the horizontal servo back and forth.
+ * @param panServo The servo object to move
+ * @param sinStart The position on the sine wave to begin the pan
+ */
+void panForTarget(Servo *panServo)	{ panForTarget(panServo, 0.0); }
+
+void panForTarget(Servo *panServo, double sinStart)	{
+	float normalizedSinPosition = (float)SinPosition(NULL, sinStart);
+	float newServoPosition = NormalizeToRange(normalizedSinPosition);
+	panServo->Set( newServoPosition );
+	//ShowActivity ("pan x: normalized %f newServoPosition = %f" , 
+	//		normalizedSinPosition, newServoPosition );
+}
+
+
+/** @brief Read a file and return non-comment output string 
+
+Call the first time with 0 lineNumber to get the number of lines to read
+Then call with each lineNumber to get one camera parameter. There should
+be one property=value entry on each line, i.e. "exposure=auto"
+
+ * @param inputFile filename to read
+ * @param outputString one string
+ * @param lineNumber if 0, return number of lines; else return that line number
+ * @return int number of lines or -1 if error
+ **/
+int processFile(char *inputFile, char *outputString, int lineNumber)
+{
+	FILE *infile;
+	int stringSize = 80;		// max size of one line in file 
+	char inputStr[stringSize];
+	int lineCount=0;
+	  
+	if (lineNumber < 0)
+		  return (-1);
+
+	if ((infile = fopen (inputFile, "r")) == NULL) {
+	    printf ("Fatal error opening file %s\n",inputFile);
+	    return (0);
+	}
+
+  while (!feof(infile)) {
+    if (fgets (inputStr, stringSize, infile) != NULL) {
+      // Skip empty lines
+      if (emptyString(inputStr))
+        continue;
+      // Skip comment lines
+      if (inputStr[0] == '#' || inputStr[0] == '!')
+        continue;
+
+      lineCount++;
+      if (lineNumber == 0)
+        continue;
+      else
+      {
+    	  if (lineCount == lineNumber)
+    		  break;
+      }
+    }
+  }
+
+  // close file 
+  fclose (infile);
+  // if number lines requested return the count
+  if (lineNumber == 0)
+	  return (lineCount);
+  // check for input out of range
+  if (lineNumber > lineCount)
+	  return (-1);
+  // return the line selected
+  if (lineCount) {
+    stripString(inputStr);
+    strcpy(outputString, inputStr);
+    return(lineCount);
+  } 
+  else {
+    return(-1);
+  }
+}
+
+/** Ignore empty string 
+ * @param string to check if empty
+ **/
+int emptyString(char *string)
+{
+  int i,len;
+
+  if(string == NULL)
+    return(1);
+
+  len = strlen(string);
+  for(i=0; i<len; i++) {
+    // Ignore the following characters
+    if (string[i] == '\n' || string[i] == '\r' ||
+        string[i] == '\t' || string[i] == ' ')
+      continue;
+    return(0);
+  }
+  return(1);
+}
+
+/** Remove special characters from string 
+ * @param string to process
+ **/
+void stripString(char *string)
+{
+  int i,j,len;
+
+  if(string == NULL)
+    return;
+
+  len = strlen(string);
+  for(i=0,j=0; i<len; i++) {
+    // Remove the following characters from the string
+    if (string[i] == '\n' || string[i] == '\r' || string[i] == '\"')
+      continue;
+    // Copy anything else
+    string[j++] = string[i];
+  }
+  string[j] = '\0'; 
+}
+
+
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/BinaryImage.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/BinaryImage.cpp
new file mode 100644
index 0000000..b6b0ced
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/BinaryImage.cpp
@@ -0,0 +1,222 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.							  */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "Vision/BinaryImage.h"
+#include "WPIErrors.h"
+#include <cstring>
+
+using namespace std;
+
+
+BinaryImage::BinaryImage() : MonoImage()
+{
+}
+
+BinaryImage::~BinaryImage()
+{
+}
+
+/**
+ * Get then number of particles for the image.
+ * @returns the number of particles found for the image.
+ */
+int BinaryImage::GetNumberParticles()
+{
+	int numParticles = 0;
+	int success = imaqCountParticles(m_imaqImage, 1, &numParticles);
+	wpi_setImaqErrorWithContext(success, "Error counting particles");
+	return numParticles;
+}
+
+/**
+ * Get a single particle analysis report.
+ * Get one (of possibly many) particle analysis reports for an image.
+ * @param particleNumber Which particle analysis report to return.
+ * @returns the selected particle analysis report
+ */
+ParticleAnalysisReport BinaryImage::GetParticleAnalysisReport(int particleNumber)
+{
+	ParticleAnalysisReport par;
+	GetParticleAnalysisReport(particleNumber, &par);
+	return par;
+}
+
+/**
+ * Get a single particle analysis report.
+ * Get one (of possibly many) particle analysis reports for an image.
+ * This version could be more efficient when copying many reports.
+ * @param particleNumber Which particle analysis report to return.
+ * @param par the selected particle analysis report
+ */
+void BinaryImage::GetParticleAnalysisReport(int particleNumber, ParticleAnalysisReport *par)
+{
+	int success;
+	int numParticles = 0;
+
+	success = imaqGetImageSize(m_imaqImage, &par->imageWidth, &par->imageHeight);
+	wpi_setImaqErrorWithContext(success, "Error getting image size");
+	if (StatusIsFatal())
+		return;
+
+	success = imaqCountParticles(m_imaqImage, 1, &numParticles);
+	wpi_setImaqErrorWithContext(success, "Error counting particles");
+	if (StatusIsFatal())
+		return;
+
+	if (particleNumber >= numParticles)
+	{
+		wpi_setWPIErrorWithContext(ParameterOutOfRange, "particleNumber");
+		return;
+	}
+
+	par->particleIndex = particleNumber;
+	// Don't bother measuring the rest of the particle if one fails
+	bool good = ParticleMeasurement(particleNumber, IMAQ_MT_CENTER_OF_MASS_X, &par->center_mass_x);
+	good = good && ParticleMeasurement(particleNumber, IMAQ_MT_CENTER_OF_MASS_Y, &par->center_mass_y);
+	good = good && ParticleMeasurement(particleNumber, IMAQ_MT_AREA, &par->particleArea);
+	good = good && ParticleMeasurement(particleNumber, IMAQ_MT_BOUNDING_RECT_TOP, &par->boundingRect.top);
+	good = good && ParticleMeasurement(particleNumber, IMAQ_MT_BOUNDING_RECT_LEFT, &par->boundingRect.left);
+	good = good && ParticleMeasurement(particleNumber, IMAQ_MT_BOUNDING_RECT_HEIGHT, &par->boundingRect.height);
+	good = good && ParticleMeasurement(particleNumber, IMAQ_MT_BOUNDING_RECT_WIDTH, &par->boundingRect.width);
+	good = good && ParticleMeasurement(particleNumber, IMAQ_MT_AREA_BY_IMAGE_AREA, &par->particleToImagePercent);
+	good = good && ParticleMeasurement(particleNumber, IMAQ_MT_AREA_BY_PARTICLE_AND_HOLES_AREA, &par->particleQuality);
+
+	if (good)
+	{
+		/* normalized position (-1 to 1) */
+		par->center_mass_x_normalized = NormalizeFromRange(par->center_mass_x, par->imageWidth);
+		par->center_mass_y_normalized = NormalizeFromRange(par->center_mass_y, par->imageHeight);
+	}
+}
+
+
+/**
+ * Get an ordered vector of particles for the image.
+ * Create a vector of particle analysis reports sorted by size for an image.
+ * The vector contains the actual report structures.
+ * @returns a pointer to the vector of particle analysis reports. The caller must delete the
+ * vector when finished using it.
+ */
+vector<ParticleAnalysisReport>* BinaryImage::GetOrderedParticleAnalysisReports()
+{
+	vector<ParticleAnalysisReport>* particles = new vector<ParticleAnalysisReport>;
+	int particleCount = GetNumberParticles();
+	for(int particleIndex = 0; particleIndex < particleCount; particleIndex++)
+	{
+		particles->push_back(GetParticleAnalysisReport(particleIndex));
+	}
+	// TODO: This is pretty inefficient since each compare in the sort copies
+	//   both reports being compared... do it manually instead... while we're
+	//   at it, we should provide a version that allows a preallocated buffer of
+	//   ParticleAnalysisReport structures
+	sort(particles->begin(), particles->end(), CompareParticleSizes);
+	return particles;
+}
+
+/**
+ * Write a binary image to flash.
+ * Writes the binary image to flash on the cRIO for later inspection.
+ * @param fileName the name of the image file written to the flash.
+ */
+void BinaryImage::Write(const char *fileName)
+{
+	RGBValue colorTable[256];
+	memset(colorTable, 0, sizeof(colorTable));
+	colorTable[0].R = 0;
+	colorTable[1].R = 255;
+	colorTable[0].G = colorTable[1].G = 0;
+	colorTable[0].B = colorTable[1].B = 0;
+	colorTable[0].alpha = colorTable[1].alpha = 0;
+	imaqWriteFile(m_imaqImage, fileName, colorTable);
+}
+
+/**
+ * Measure a single parameter for an image.
+ * Get the measurement for a single parameter about an image by calling the imaqMeasureParticle
+ * function for the selected parameter.
+ * @param particleNumber which particle in the set of particles
+ * @param whatToMeasure the imaq MeasurementType (what to measure)
+ * @param result the value of the measurement
+ * @returns false on failure, true on success
+ */
+bool BinaryImage::ParticleMeasurement(int particleNumber, MeasurementType whatToMeasure, int *result)
+{
+	double resultDouble;
+	bool success = ParticleMeasurement(particleNumber, whatToMeasure, &resultDouble);
+	*result = (int)resultDouble;
+	return success;
+}
+
+/**
+ * Measure a single parameter for an image.
+ * Get the measurement for a single parameter about an image by calling the imaqMeasureParticle
+ * function for the selected parameter.
+ * @param particleNumber which particle in the set of particles
+ * @param whatToMeasure the imaq MeasurementType (what to measure)
+ * @param result the value of the measurement
+ * @returns true on failure, false on success
+ */
+bool BinaryImage::ParticleMeasurement(int particleNumber, MeasurementType whatToMeasure, double *result)
+{
+	int success;
+	success = imaqMeasureParticle(m_imaqImage, particleNumber, 0, whatToMeasure, result);
+	wpi_setImaqErrorWithContext(success, "Error measuring particle");
+	return !StatusIsFatal();
+}
+
+//Normalizes to [-1,1]
+double BinaryImage::NormalizeFromRange(double position, int range)
+{
+	return (position * 2.0 / (double)range) - 1.0;
+}
+
+/**
+ * The compare helper function for sort.
+ * This function compares two particle analysis reports as a helper for the sort function.
+ * @param particle1 The first particle to compare
+ * @param particle2 the second particle to compare
+ * @returns true if particle1 is greater than particle2
+ */
+bool BinaryImage::CompareParticleSizes(ParticleAnalysisReport particle1, ParticleAnalysisReport particle2)
+{
+	//we want descending sort order
+	return particle1.particleToImagePercent > particle2.particleToImagePercent;
+}
+
+BinaryImage *BinaryImage::RemoveSmallObjects(bool connectivity8, int erosions)
+{
+	BinaryImage *result = new BinaryImage();
+	int success = imaqSizeFilter(result->GetImaqImage(), m_imaqImage, connectivity8, erosions, IMAQ_KEEP_LARGE, NULL);
+	wpi_setImaqErrorWithContext(success, "Error in RemoveSmallObjects");
+	return result;
+}
+
+BinaryImage *BinaryImage::RemoveLargeObjects(bool connectivity8, int erosions)
+{
+	BinaryImage *result = new BinaryImage();
+	int success = imaqSizeFilter(result->GetImaqImage(), m_imaqImage, connectivity8, erosions, IMAQ_KEEP_SMALL, NULL);
+	wpi_setImaqErrorWithContext(success, "Error in RemoveLargeObjects");
+	return result;
+}
+
+BinaryImage *BinaryImage::ConvexHull(bool connectivity8)
+{
+	BinaryImage *result = new BinaryImage();
+	int success = imaqConvexHull(result->GetImaqImage(), m_imaqImage, connectivity8);
+	wpi_setImaqErrorWithContext(success, "Error in convex hull operation");
+	return result;
+}
+
+BinaryImage *BinaryImage::ParticleFilter(ParticleFilterCriteria2 *criteria, int criteriaCount)
+{
+	BinaryImage *result = new BinaryImage();
+	int numParticles;
+	ParticleFilterOptions2 filterOptions = {0, 0, 0, 1};
+	int success = imaqParticleFilter4(result->GetImaqImage(), m_imaqImage, criteria, criteriaCount, &filterOptions, NULL, &numParticles);
+	wpi_setImaqErrorWithContext(success, "Error in particle filter operation");
+	return result;
+}
+
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/ColorImage.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/ColorImage.cpp
new file mode 100644
index 0000000..aa72da3
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/ColorImage.cpp
@@ -0,0 +1,465 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "Vision/ColorImage.h"
+
+#include "WPIErrors.h"
+
+ColorImage::ColorImage(ImageType type) : ImageBase(type)
+{
+}
+
+ColorImage::~ColorImage()
+{
+}
+
+/**
+ * Perform a threshold operation on a ColorImage.
+ * Perform a threshold operation on a ColorImage using the ColorMode supplied
+ * as a parameter.
+ * @param colorMode The type of colorspace this operation should be performed in
+ * @returns a pointer to a binary image
+ */
+BinaryImage *ColorImage::ComputeThreshold(ColorMode colorMode,
+		int low1, int high1,
+		int low2, int high2,
+		int low3, int high3)
+{
+	BinaryImage *result = new BinaryImage();
+	Range range1 = {low1, high1},
+		range2 = {low2, high2},
+		range3 = {low3, high3};
+	
+	int success = imaqColorThreshold(result->GetImaqImage(), m_imaqImage, 1, colorMode, &range1, &range2, &range3);
+	wpi_setImaqErrorWithContext(success, "ImaqThreshold error");
+	return result;
+}
+
+/**
+ * Perform a threshold in RGB space.
+ * @param redLow Red low value
+ * @param redHigh Red high value
+ * @param greenLow Green low value
+ * @param greenHigh Green high value
+ * @param blueLow Blue low value
+ * @param blueHigh Blue high value
+ * @returns A pointer to a BinaryImage that represents the result of the threshold operation.
+ */
+BinaryImage *ColorImage::ThresholdRGB(int redLow, int redHigh, int greenLow, int greenHigh, int blueLow, int blueHigh)
+{
+	return ComputeThreshold(IMAQ_RGB, redLow, redHigh, greenLow, greenHigh, blueLow, blueHigh);
+}
+
+/**
+ * Perform a threshold in RGB space.
+ * @param threshold a reference to the Threshold object to use.
+ * @returns A pointer to a BinaryImage that represents the result of the threshold operation.
+ */
+BinaryImage *ColorImage::ThresholdRGB(Threshold &t)
+{
+	return ComputeThreshold(IMAQ_RGB, t.plane1Low, t.plane1High,
+								t.plane2Low, t.plane2High,
+								t.plane3Low, t.plane3High);
+}
+
+/**
+ * Perform a threshold in HSL space.
+ * @param hueLow Low value for hue
+ * @param hueHigh High value for hue
+ * @param saturationLow Low value for saturation
+ * @param saturationHigh High value for saturation
+ * @param luminenceLow Low value for luminence
+ * @param luminenceHigh High value for luminence
+ * @returns a pointer to a BinaryImage that represents the result of the threshold operation.
+ */
+BinaryImage *ColorImage::ThresholdHSL(int hueLow, int hueHigh, int saturationLow, int saturationHigh, int luminenceLow, int luminenceHigh)
+{
+	return ComputeThreshold(IMAQ_HSL, hueLow, hueHigh, saturationLow, saturationHigh, luminenceLow, luminenceHigh);
+}
+
+/**
+ * Perform a threshold in HSL space.
+ * @param threshold a reference to the Threshold object to use.
+ * @returns A pointer to a BinaryImage that represents the result of the threshold operation.
+ */
+BinaryImage *ColorImage::ThresholdHSL(Threshold &t)
+{
+	return ComputeThreshold(IMAQ_HSL, t.plane1Low, t.plane1High,
+								t.plane2Low, t.plane2High,
+								t.plane3Low, t.plane3High);
+}
+
+/**
+ * Perform a threshold in HSV space.
+ * @param hueLow Low value for hue
+ * @param hueHigh High value for hue
+ * @param saturationLow Low value for saturation
+ * @param saturationHigh High value for saturation
+ * @param valueLow Low value
+ * @param valueHigh High value
+ * @returns a pointer to a BinaryImage that represents the result of the threshold operation.
+ */
+BinaryImage *ColorImage::ThresholdHSV(int hueLow, int hueHigh, int saturationLow, int saturationHigh, int valueLow, int valueHigh)
+{
+	return ComputeThreshold(IMAQ_HSV, hueLow, hueHigh, saturationLow, saturationHigh, valueLow, valueHigh);
+}
+
+/**
+ * Perform a threshold in HSV space.
+ * @param threshold a reference to the Threshold object to use.
+ * @returns A pointer to a BinaryImage that represents the result of the threshold operation.
+ */
+BinaryImage *ColorImage::ThresholdHSV(Threshold &t)
+{
+	return ComputeThreshold(IMAQ_HSV, t.plane1Low, t.plane1High,
+								t.plane2Low, t.plane2High,
+								t.plane3Low, t.plane3High);
+}
+
+/**
+ * Perform a threshold in HSI space.
+ * @param hueLow Low value for hue
+ * @param hueHigh High value for hue
+ * @param saturationLow Low value for saturation
+ * @param saturationHigh High value for saturation
+ * @param valueLow Low intensity
+ * @param valueHigh High intensity
+ * @returns a pointer to a BinaryImage that represents the result of the threshold operation.
+ */
+BinaryImage *ColorImage::ThresholdHSI(int hueLow, int hueHigh, int saturationLow, int saturationHigh, int intensityLow, int intensityHigh)
+{
+	return ComputeThreshold(IMAQ_HSI, hueLow, hueHigh, saturationLow, saturationHigh, intensityLow, intensityHigh);
+}
+
+/**
+ * Perform a threshold in HSI space.
+ * @param threshold a reference to the Threshold object to use.
+ * @returns A pointer to a BinaryImage that represents the result of the threshold operation.
+ */
+BinaryImage *ColorImage::ThresholdHSI(Threshold &t)
+{
+	return ComputeThreshold(IMAQ_HSI, t.plane1Low, t.plane1High,
+								t.plane2Low, t.plane2High,
+								t.plane3Low, t.plane3High);
+}
+
+/**
+ * Extract a color plane from the image
+ * @param mode The ColorMode to use for the plane extraction
+ * @param planeNumber Which plane is to be extracted
+ * @returns A pointer to a MonoImage that represents the extracted plane.
+ */
+MonoImage *ColorImage::ExtractColorPlane(ColorMode mode, int planeNumber)
+{
+	MonoImage *result = new MonoImage();
+	if (m_imaqImage == NULL)
+		wpi_setWPIError(NullParameter);
+	int success = imaqExtractColorPlanes(m_imaqImage, 
+										 mode, 
+										 (planeNumber == 1) ? result->GetImaqImage() : NULL, 
+										 (planeNumber == 2) ? result->GetImaqImage() : NULL, 
+										 (planeNumber == 3) ? result->GetImaqImage() : NULL);
+	wpi_setImaqErrorWithContext(success, "Imaq ExtractColorPlanes failed");
+	return result;
+}
+
+/*
+ * Extract the first color plane for an image.
+ * @param mode The color mode in which to operate
+ * @returns a pointer to a MonoImage that is the extracted plane.
+ */
+MonoImage *ColorImage::ExtractFirstColorPlane(ColorMode mode)
+{
+	return ExtractColorPlane(mode, 1);
+}
+
+/*
+ * Extract the second color plane for an image.
+ * @param mode The color mode in which to operate
+ * @returns a pointer to a MonoImage that is the extracted plane.
+ */
+MonoImage *ColorImage::ExtractSecondColorPlane(ColorMode mode)
+{
+	return ExtractColorPlane(mode, 2);
+}
+
+/*
+ * Extract the third color plane for an image.
+ * @param mode The color mode in which to operate
+ * @returns a pointer to a MonoImage that is the extracted plane.
+ */
+MonoImage *ColorImage::ExtractThirdColorPlane(ColorMode mode)
+{
+	return ExtractColorPlane(mode, 3);
+}
+
+/*
+ * Extract the red plane from an RGB image.
+ * @returns a pointer to a MonoImage that is the extraced plane.
+ */
+MonoImage *ColorImage::GetRedPlane()
+{
+	return ExtractFirstColorPlane(IMAQ_RGB);
+}
+
+/*
+ * Extract the green plane from an RGB image.
+ * @returns a pointer to a MonoImage that is the extraced plane.
+ */
+MonoImage *ColorImage::GetGreenPlane()
+{
+    return ExtractSecondColorPlane(IMAQ_RGB);
+}
+
+/*
+ * Extract the blue plane from an RGB image.
+ * @returns a pointer to a MonoImage that is the extraced plane.
+ */
+MonoImage *ColorImage::GetBluePlane()
+{
+    return ExtractThirdColorPlane(IMAQ_RGB);
+}
+
+/*
+ * Extract the Hue plane from an HSL image.
+ * @returns a pointer to a MonoImage that is the extraced plane.
+ */
+MonoImage *ColorImage::GetHSLHuePlane()
+{
+	return ExtractFirstColorPlane(IMAQ_HSL);
+}
+
+/*
+ * Extract the Hue plane from an HSV image.
+ * @returns a pointer to a MonoImage that is the extraced plane.
+ */
+MonoImage *ColorImage::GetHSVHuePlane()
+{
+	return ExtractFirstColorPlane(IMAQ_HSV);
+}
+
+/*
+ * Extract the Hue plane from an HSI image.
+ * @returns a pointer to a MonoImage that is the extraced plane.
+ */
+MonoImage *ColorImage::GetHSIHuePlane()
+{
+	return ExtractFirstColorPlane(IMAQ_HSI);
+}
+
+/*
+ * Extract the Luminance plane from an HSL image.
+ * @returns a pointer to a MonoImage that is the extraced plane.
+ */
+MonoImage *ColorImage::GetLuminancePlane()
+{
+	return ExtractThirdColorPlane(IMAQ_HSL);
+}
+
+/*
+ * Extract the Value plane from an HSV image.
+ * @returns a pointer to a MonoImage that is the extraced plane.
+ */
+MonoImage *ColorImage::GetValuePlane()
+{
+	return ExtractThirdColorPlane(IMAQ_HSV);
+}
+
+/*
+ * Extract the Intensity plane from an HSI image.
+ * @returns a pointer to a MonoImage that is the extraced plane.
+ */
+MonoImage *ColorImage::GetIntensityPlane()
+{
+	return ExtractThirdColorPlane(IMAQ_HSI);
+}
+
+/**
+ * Replace a plane in the ColorImage with a MonoImage
+ * Replaces a single plane in the image with a MonoImage
+ * @param mode The ColorMode in which to operate
+ * @param plane The pointer to the replacement plane as a MonoImage
+ * @param planeNumber The plane number (1, 2, 3) to replace
+ */
+void ColorImage::ReplacePlane(ColorMode mode, MonoImage *plane, int planeNumber) {
+	int success = imaqReplaceColorPlanes(m_imaqImage, 
+										 (const Image*) m_imaqImage, 
+									     mode, 
+									     (planeNumber == 1) ? plane->GetImaqImage() : NULL, 
+									     (planeNumber == 2) ? plane->GetImaqImage() : NULL, 
+									     (planeNumber == 3) ? plane->GetImaqImage() : NULL);
+	wpi_setImaqErrorWithContext(success, "Imaq ReplaceColorPlanes failed");
+}
+
+/**
+ * Replace the first color plane with a MonoImage.
+ * @param mode The color mode in which to operate.
+ * @param plane A pointer to a MonoImage that will replace the specified color plane.
+ */
+void ColorImage::ReplaceFirstColorPlane(ColorMode mode, MonoImage *plane)
+{
+	ReplacePlane(mode, plane, 1);
+}
+
+/**
+ * Replace the second color plane with a MonoImage.
+ * @param mode The color mode in which to operate.
+ * @param plane A pointer to a MonoImage that will replace the specified color plane.
+ */
+void ColorImage::ReplaceSecondColorPlane(ColorMode mode, MonoImage *plane)
+{
+	ReplacePlane(mode, plane, 2);
+}
+
+/**
+ * Replace the third color plane with a MonoImage.
+ * @param mode The color mode in which to operate.
+ * @param plane A pointer to a MonoImage that will replace the specified color plane.
+ */
+void ColorImage::ReplaceThirdColorPlane(ColorMode mode, MonoImage *plane)
+{ 
+	ReplacePlane(mode, plane, 3);
+}
+
+/**
+ * Replace the red color plane with a MonoImage.
+ * @param mode The color mode in which to operate.
+ * @param plane A pointer to a MonoImage that will replace the specified color plane.
+ */
+void ColorImage::ReplaceRedPlane(MonoImage *plane)
+{
+	ReplaceFirstColorPlane(IMAQ_RGB, plane);
+}
+
+/**
+ * Replace the green color plane with a MonoImage.
+ * @param mode The color mode in which to operate.
+ * @param plane A pointer to a MonoImage that will replace the specified color plane.
+ */
+void ColorImage::ReplaceGreenPlane(MonoImage *plane)
+{
+	ReplaceSecondColorPlane(IMAQ_RGB, plane);
+}
+
+/**
+ * Replace the blue color plane with a MonoImage.
+ * @param mode The color mode in which to operate.
+ * @param plane A pointer to a MonoImage that will replace the specified color plane.
+ */
+void ColorImage::ReplaceBluePlane(MonoImage *plane)
+{
+	ReplaceThirdColorPlane(IMAQ_RGB, plane);
+}
+
+
+/**
+ * Replace the Hue color plane in a HSL image with a MonoImage.
+ * @param mode The color mode in which to operate.
+ * @param plane A pointer to a MonoImage that will replace the specified color plane.
+ */
+void ColorImage::ReplaceHSLHuePlane(MonoImage *plane)
+{
+	return ReplaceFirstColorPlane(IMAQ_HSL, plane);
+}
+
+/**
+ * Replace the Hue color plane in a HSV image with a MonoImage.
+ * @param mode The color mode in which to operate.
+ * @param plane A pointer to a MonoImage that will replace the specified color plane.
+ */
+void ColorImage::ReplaceHSVHuePlane(MonoImage *plane)
+{
+	return ReplaceFirstColorPlane(IMAQ_HSV, plane);
+}
+
+/**
+ * Replace the first Hue plane in a HSI image with a MonoImage.
+ * @param mode The color mode in which to operate.
+ * @param plane A pointer to a MonoImage that will replace the specified color plane.
+ */
+void ColorImage::ReplaceHSIHuePlane(MonoImage *plane)
+{
+	return ReplaceFirstColorPlane(IMAQ_HSI, plane);
+}
+
+/**
+ * Replace the Saturation color plane in an HSL image with a MonoImage.
+ * @param mode The color mode in which to operate.
+ * @param plane A pointer to a MonoImage that will replace the specified color plane.
+ */
+void ColorImage::ReplaceHSLSaturationPlane(MonoImage *plane)
+{
+	return ReplaceSecondColorPlane(IMAQ_HSL, plane);
+}
+
+/**
+ * Replace the Saturation color plane in a HSV image with a MonoImage.
+ * @param mode The color mode in which to operate.
+ * @param plane A pointer to a MonoImage that will replace the specified color plane.
+ */
+void ColorImage::ReplaceHSVSaturationPlane(MonoImage *plane)
+{
+	return ReplaceSecondColorPlane(IMAQ_HSV, plane);
+}
+
+/**
+ * Replace the Saturation color plane in a HSI image with a MonoImage.
+ * @param mode The color mode in which to operate.
+ * @param plane A pointer to a MonoImage that will replace the specified color plane.
+ */
+void ColorImage::ReplaceHSISaturationPlane(MonoImage *plane)
+{
+	return ReplaceSecondColorPlane(IMAQ_HSI, plane);
+}
+
+/**
+ * Replace the Luminance color plane in an HSL image with a MonoImage.
+ * @param mode The color mode in which to operate.
+ * @param plane A pointer to a MonoImage that will replace the specified color plane.
+ */
+void ColorImage::ReplaceLuminancePlane(MonoImage *plane)
+{
+	return ReplaceThirdColorPlane(IMAQ_HSL, plane);
+}
+
+/**
+ * Replace the Value color plane in an HSV with a MonoImage.
+ * @param mode The color mode in which to operate.
+ * @param plane A pointer to a MonoImage that will replace the specified color plane.
+ */
+void ColorImage::ReplaceValuePlane(MonoImage *plane)
+{
+	return ReplaceThirdColorPlane(IMAQ_HSV, plane);
+}
+
+/**
+ * Replace the Intensity color plane in a HSI image with a MonoImage.
+ * @param mode The color mode in which to operate.
+ * @param plane A pointer to a MonoImage that will replace the specified color plane.
+ */
+void ColorImage::ReplaceIntensityPlane(MonoImage *plane)
+{
+	return ReplaceThirdColorPlane(IMAQ_HSI, plane);
+}
+
+//TODO: frcColorEqualize(Image* dest, const Image* source, int colorEqualization) needs to be modified
+//The colorEqualization parameter is discarded and is set to TRUE in the call to imaqColorEqualize.
+void ColorImage::Equalize(bool allPlanes)
+{
+	// Note that this call uses NI-defined TRUE and FALSE
+	int success = imaqColorEqualize(m_imaqImage, (const Image*) m_imaqImage, (allPlanes) ? TRUE : FALSE);
+	wpi_setImaqErrorWithContext(success, "Imaq ColorEqualize error");
+}
+
+void ColorImage::ColorEqualize()
+{
+	Equalize(true);
+}
+
+void ColorImage::LuminanceEqualize()
+{
+	Equalize(false);
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/FrcError.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/FrcError.cpp
new file mode 100644
index 0000000..109dea6
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/FrcError.cpp
@@ -0,0 +1,1227 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+ 
+#include "nivision.h" 
+#include "Vision/FrcError.h" 
+
+/**
+ * Get the error code returned from the NI Vision library
+ * @return The last error code.
+ */
+int GetLastVisionError()
+{
+	//int errorCode = imaqGetLastVisionError();     // error code: 0 = no error	
+	//char* errorText = GetVisionErrorText(errorCode);
+	//dprintf (LOG_DEBUG, "Error = %i  %s ", errorCode, errorText);
+	return imaqGetLastError();
+}
+	
+/**
+* Get the error text for an NI Vision error code.
+* Note: imaqGetErrorText() is not supported on real time system, so
+* so relevant strings are hardcoded here - the maintained version is
+* in the LabWindows/CVI help file.
+* @param errorCode The error code to find the text for.
+* @return The error text
+*/
+const char* GetVisionErrorText(int errorCode)
+{
+	const char* errorText;
+
+	switch (errorCode)
+	{
+		default:
+			{ errorText = "UNKNOWN_ERROR";break;}
+		case -1074395138:
+			{ errorText = "ERR_OCR_REGION_TOO_SMALL";break;}
+		case -1074395139:
+			{ errorText = "ERR_IMAQ_QR_DIMENSION_INVALID";break;}
+		case -1074395140:
+			{ errorText = "ERR_OCR_CHAR_REPORT_CORRUPTED";break;}
+		case -1074395141:
+			{ errorText = "ERR_OCR_NO_TEXT_FOUND";break;}
+		case -1074395142:
+			{ errorText = "ERR_QR_DETECTION_MODELTYPE";break;}
+		case -1074395143:
+			{ errorText = "ERR_QR_DETECTION_MODE";break;}
+		case -1074395144:
+			{ errorText = "ERR_QR_INVALID_BARCODE";break;}
+		case -1074395145:
+			{ errorText = "ERR_QR_INVALID_READ";break;}
+		case -1074395146:
+			{ errorText = "ERR_QR_DETECTION_VERSION";break;}
+		case -1074395147:
+			{ errorText = "ERR_BARCODE_RSSLIMITED";break;}
+		case -1074395148:
+			{ errorText = "ERR_OVERLAY_GROUP_NOT_FOUND";break;}
+		case -1074395149:
+			{ errorText = "ERR_DUPLICATE_TRANSFORM_TYPE";break;}
+		case -1074395151:
+			{ errorText = "ERR_OCR_CORRECTION_FAILED";break;}
+		case -1074395155:
+			{ errorText = "ERR_OCR_ORIENT_DETECT_FAILED";break;}
+		case -1074395156:
+			{ errorText = "ERR_OCR_SKEW_DETECT_FAILED";break;}
+		case -1074395158:
+			{ errorText = "ERR_OCR_INVALID_CONTRASTMODE";break;}
+		case -1074395159:
+			{ errorText = "ERR_OCR_INVALID_TOLERANCE";break;}
+		case -1074395160:
+			{ errorText = "ERR_OCR_INVALID_MAXPOINTSIZE";break;}
+		case -1074395161:
+			{ errorText = "ERR_OCR_INVALID_CORRECTIONLEVEL";break;}
+		case -1074395162:
+			{ errorText = "ERR_OCR_INVALID_CORRECTIONMODE";break;}
+		case -1074395163:
+			{ errorText = "ERR_OCR_INVALID_CHARACTERPREFERENCE";break;}
+		case -1074395164:
+			{ errorText = "ERR_OCR_ADD_WORD_FAILED";break;}
+		case -1074395165:
+			{ errorText = "ERR_OCR_WTS_DIR_NOT_FOUND";break;}
+		case -1074395166:
+			{ errorText = "ERR_OCR_BIN_DIR_NOT_FOUND";break;}
+		case -1074395167:
+			{ errorText = "ERR_OCR_INVALID_OUTPUTDELIMITER";break;}
+		case -1074395168:
+			{ errorText = "ERR_OCR_INVALID_AUTOCORRECTIONMODE";break;}
+		case -1074395169:
+			{ errorText = "ERR_OCR_INVALID_RECOGNITIONMODE";break;}
+		case -1074395170:
+			{ errorText = "ERR_OCR_INVALID_CHARACTERTYPE";break;}
+		case -1074395171:
+			{ errorText = "ERR_OCR_INI_FILE_NOT_FOUND";break;}
+		case -1074395172:
+			{ errorText = "ERR_OCR_INVALID_CHARACTERSET";break;}
+		case -1074395173:
+			{ errorText = "ERR_OCR_INVALID_LANGUAGE";break;}
+		case -1074395174:
+			{ errorText = "ERR_OCR_INVALID_AUTOORIENTMODE";break;}
+		case -1074395175:
+			{ errorText = "ERR_OCR_BAD_USER_DICTIONARY";break;}
+		case -1074395178:
+			{ errorText = "ERR_OCR_RECOGNITION_FAILED";break;}
+		case -1074395179:
+			{ errorText = "ERR_OCR_PREPROCESSING_FAILED";break;}
+		case -1074395200:
+			{ errorText = "ERR_OCR_INVALID_PARAMETER";break;}
+		case -1074395201:
+			{ errorText = "ERR_OCR_LOAD_LIBRARY";break;}
+		case -1074395203:
+			{ errorText = "ERR_OCR_LIB_INIT";break;}
+		case -1074395210:
+			{ errorText = "ERR_OCR_CANNOT_MATCH_TEXT_TEMPLATE";break;}
+		case -1074395211:
+			{ errorText = "ERR_OCR_BAD_TEXT_TEMPLATE";break;}
+		case -1074395212:
+			{ errorText = "ERR_OCR_TEMPLATE_WRONG_SIZE";break;}
+		case -1074395233:
+			{ errorText = "ERR_TEMPLATE_IMAGE_TOO_LARGE";break;}
+		case -1074395234:
+			{ errorText = "ERR_TEMPLATE_IMAGE_TOO_SMALL";break;}
+		case -1074395235:
+			{ errorText = "ERR_TEMPLATE_IMAGE_CONTRAST_TOO_LOW";break;}
+		case -1074395237:
+			{ errorText = "ERR_TEMPLATE_DESCRIPTOR_SHIFT_1";break;}
+		case -1074395238:
+			{ errorText = "ERR_TEMPLATE_DESCRIPTOR_NOSHIFT";break;}
+		case -1074395239:
+			{ errorText = "ERR_TEMPLATE_DESCRIPTOR_SHIFT";break;}
+		case -1074395240:
+			{ errorText = "ERR_TEMPLATE_DESCRIPTOR_ROTATION_1";break;}
+		case -1074395241:
+			{ errorText = "ERR_TEMPLATE_DESCRIPTOR_NOROTATION";break;}
+		case -1074395242:
+			{ errorText = "ERR_TEMPLATE_DESCRIPTOR_ROTATION";break;}
+		case -1074395243:
+			{ errorText = "ERR_TEMPLATE_DESCRIPTOR_4";break;}
+		case -1074395244:
+			{ errorText = "ERR_TEMPLATE_DESCRIPTOR_3";break;}
+		case -1074395245:
+			{ errorText = "ERR_TEMPLATE_DESCRIPTOR_2";break;}
+		case -1074395246:
+			{ errorText = "ERR_TEMPLATE_DESCRIPTOR_1";break;}
+		case -1074395247:
+			{ errorText = "ERR_TEMPLATE_DESCRIPTOR";break;}
+		case -1074395248:
+			{ errorText = "ERR_TOO_MANY_ROTATION_ANGLE_RANGES";break;}
+		case -1074395249:
+			{ errorText = "ERR_ROTATION_ANGLE_RANGE_TOO_LARGE";break;}
+		case -1074395250:
+			{ errorText = "ERR_MATCH_SETUP_DATA";break;}
+		case -1074395251:
+			{ errorText = "ERR_INVALID_MATCH_MODE";break;}
+		case -1074395252:
+			{ errorText = "ERR_LEARN_SETUP_DATA";break;}
+		case -1074395253:
+			{ errorText = "ERR_INVALID_LEARN_MODE";break;}
+		case -1074395256:
+			{ errorText = "ERR_EVEN_WINDOW_SIZE";break;}
+		case -1074395257:
+			{ errorText = "ERR_INVALID_EDGE_DIR";break;}
+		case -1074395258:
+			{ errorText = "ERR_BAD_FILTER_WIDTH";break;}
+		case -1074395260:
+			{ errorText = "ERR_HEAP_TRASHED";break;}
+		case -1074395261:
+			{ errorText = "ERR_GIP_RANGE";break;}
+		case -1074395262:
+			{ errorText = "ERR_LCD_BAD_MATCH";break;}
+		case -1074395263:
+			{ errorText = "ERR_LCD_NO_SEGMENTS";break;}
+		case -1074395265:
+			{ errorText = "ERR_BARCODE";break;}
+		case -1074395267:
+			{ errorText = "ERR_COMPLEX_ROOT";break;}
+		case -1074395268:
+			{ errorText = "ERR_LINEAR_COEFF";break;}
+		case -1074395269:
+			{ errorText = "ERR_NULL_POINTER";break;}
+		case -1074395270:
+			{ errorText = "ERR_DIV_BY_ZERO";break;}
+		case -1074395275:
+			{ errorText = "ERR_INVALID_BROWSER_IMAGE";break;}
+		case -1074395276:
+			{ errorText = "ERR_LINES_PARALLEL";break;}
+		case -1074395277:
+			{ errorText = "ERR_BARCODE_CHECKSUM";break;}
+		case -1074395278:
+			{ errorText = "ERR_LCD_NOT_NUMERIC";break;}
+		case -1074395279:
+			{ errorText = "ERR_ROI_NOT_POLYGON";break;}
+		case -1074395280:
+			{ errorText = "ERR_ROI_NOT_RECT";break;}
+		case -1074395281:
+			{ errorText = "ERR_IMAGE_SMALLER_THAN_BORDER";break;}
+		case -1074395282:
+			{ errorText = "ERR_CANT_DRAW_INTO_VIEWER";break;}
+		case -1074395283:
+			{ errorText = "ERR_INVALID_RAKE_DIRECTION";break;}
+		case -1074395284:
+			{ errorText = "ERR_INVALID_EDGE_PROCESS";break;}
+		case -1074395285:
+			{ errorText = "ERR_INVALID_SPOKE_DIRECTION";break;}
+		case -1074395286:
+			{ errorText = "ERR_INVALID_CONCENTRIC_RAKE_DIRECTION";break;}
+		case -1074395287:
+			{ errorText = "ERR_INVALID_LINE";break;}
+		case -1074395290:
+			{ errorText = "ERR_SHAPEMATCH_BADTEMPLATE";break;}
+		case -1074395291:
+			{ errorText = "ERR_SHAPEMATCH_BADIMAGEDATA";break;}
+		case -1074395292:
+			{ errorText = "ERR_POINTS_ARE_COLLINEAR";break;}
+		case -1074395293:
+			{ errorText = "ERR_CONTOURID_NOT_FOUND";break;}
+		case -1074395294:
+			{ errorText = "ERR_CONTOUR_INDEX_OUT_OF_RANGE";break;}
+		case -1074395295:
+			{ errorText = "ERR_INVALID_INTERPOLATIONMETHOD_INTERPOLATEPOINTS";break;}
+		case -1074395296:
+			{ errorText = "ERR_INVALID_BARCODETYPE";break;}
+		case -1074395297:
+			{ errorText = "ERR_INVALID_PARTICLEINFOMODE";break;}
+		case -1074395298:
+			{ errorText = "ERR_COMPLEXPLANE_NOT_REAL_OR_IMAGINARY";break;}
+		case -1074395299:
+			{ errorText = "ERR_INVALID_COMPLEXPLANE";break;}
+		case -1074395300:
+			{ errorText = "ERR_INVALID_METERARCMODE";break;}
+		case -1074395301:
+			{ errorText = "ERR_ROI_NOT_2_LINES";break;}
+		case -1074395302:
+			{ errorText = "ERR_INVALID_THRESHOLDMETHOD";break;}
+		case -1074395303:
+			{ errorText = "ERR_INVALID_NUM_OF_CLASSES";break;}
+		case -1074395304:
+			{ errorText = "ERR_INVALID_MATHTRANSFORMMETHOD";break;}
+		case -1074395305:
+			{ errorText = "ERR_INVALID_REFERENCEMODE";break;}
+		case -1074395306:
+			{ errorText = "ERR_INVALID_TOOL";break;}
+		case -1074395307:
+			{ errorText = "ERR_PRECISION_NOT_GTR_THAN_0";break;}
+		case -1074395308:
+			{ errorText = "ERR_INVALID_COLORSENSITIVITY";break;}
+		case -1074395309:
+			{ errorText = "ERR_INVALID_WINDOW_THREAD_POLICY";break;}
+		case -1074395310:
+			{ errorText = "ERR_INVALID_PALETTE_TYPE";break;}
+		case -1074395311:
+			{ errorText = "ERR_INVALID_COLOR_SPECTRUM";break;}
+		case -1074395312:
+			{ errorText = "ERR_LCD_CALIBRATE";break;}
+		case -1074395313:
+			{ errorText = "ERR_WRITE_FILE_NOT_SUPPORTED";break;}
+		case -1074395316:
+			{ errorText = "ERR_INVALID_KERNEL_CODE";break;}
+		case -1074395317:
+			{ errorText = "ERR_UNDEF_POINT";break;}
+		case -1074395318:
+			{ errorText = "ERR_INSF_POINTS";break;}
+		case -1074395319:
+			{ errorText = "ERR_INVALID_SUBPIX_TYPE";break;}
+		case -1074395320:
+			{ errorText = "ERR_TEMPLATE_EMPTY";break;}
+		case -1074395321:
+			{ errorText = "ERR_INVALID_MORPHOLOGYMETHOD";break;}
+		case -1074395322:
+			{ errorText = "ERR_INVALID_TEXTALIGNMENT";break;}
+		case -1074395323:
+			{ errorText = "ERR_INVALID_FONTCOLOR";break;}
+		case -1074395324:
+			{ errorText = "ERR_INVALID_SHAPEMODE";break;}
+		case -1074395325:
+			{ errorText = "ERR_INVALID_DRAWMODE";break;}
+		case -1074395326:
+			{ errorText = "ERR_INVALID_DRAWMODE_FOR_LINE";break;}
+		case -1074395327:
+			{ errorText = "ERR_INVALID_SCALINGMODE";break;}
+		case -1074395328:
+			{ errorText = "ERR_INVALID_INTERPOLATIONMETHOD";break;}
+		case -1074395329:
+			{ errorText = "ERR_INVALID_OUTLINEMETHOD";break;}
+		case -1074395330:
+			{ errorText = "ERR_INVALID_BORDER_SIZE";break;}
+		case -1074395331:
+			{ errorText = "ERR_INVALID_BORDERMETHOD";break;}
+		case -1074395332:
+			{ errorText = "ERR_INVALID_COMPAREFUNCTION";break;}
+		case -1074395333:
+			{ errorText = "ERR_INVALID_VERTICAL_TEXT_ALIGNMENT";break;}
+		case -1074395334:
+			{ errorText = "ERR_INVALID_CONVERSIONSTYLE";break;}
+		case -1074395335:
+			{ errorText = "ERR_DISPATCH_STATUS_CONFLICT";break;}
+		case -1074395336:
+			{ errorText = "ERR_UNKNOWN_ALGORITHM";break;}
+		case -1074395340:
+			{ errorText = "ERR_INVALID_SIZETYPE";break;}
+		case -1074395343:
+			{ errorText = "ERR_FILE_FILENAME_NULL";break;}
+		case -1074395345:
+			{ errorText = "ERR_INVALID_FLIPAXIS";break;}
+		case -1074395346:
+			{ errorText = "ERR_INVALID_INTERPOLATIONMETHOD_FOR_ROTATE";break;}
+		case -1074395347:
+			{ errorText = "ERR_INVALID_3DDIRECTION";break;}
+		case -1074395348:
+			{ errorText = "ERR_INVALID_3DPLANE";break;}
+		case -1074395349:
+			{ errorText = "ERR_INVALID_SKELETONMETHOD";break;}
+		case -1074395350:
+			{ errorText = "ERR_INVALID_VISION_INFO";break;}
+		case -1074395351:
+			{ errorText = "ERR_INVALID_RECT";break;}
+		case -1074395352:
+			{ errorText = "ERR_INVALID_FEATURE_MODE";break;}
+		case -1074395353:
+			{ errorText = "ERR_INVALID_SEARCH_STRATEGY";break;}
+		case -1074395354:
+			{ errorText = "ERR_INVALID_COLOR_WEIGHT";break;}
+		case -1074395355:
+			{ errorText = "ERR_INVALID_NUM_MATCHES_REQUESTED";break;}
+		case -1074395356:
+			{ errorText = "ERR_INVALID_MIN_MATCH_SCORE";break;}
+		case -1074395357:
+			{ errorText = "ERR_INVALID_COLOR_IGNORE_MODE";break;}
+		case -1074395360:
+			{ errorText = "ERR_COMPLEX_PLANE";break;}
+		case -1074395361:
+			{ errorText = "ERR_INVALID_STEEPNESS";break;}
+		case -1074395362:
+			{ errorText = "ERR_INVALID_WIDTH";break;}
+		case -1074395363:
+			{ errorText = "ERR_INVALID_SUBSAMPLING_RATIO";break;}
+		case -1074395364:
+			{ errorText = "ERR_IGNORE_COLOR_SPECTRUM_SET";break;}
+		case -1074395365:
+			{ errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_NOSPECTRUM";break;}
+		case -1074395366:
+			{ errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_NOSHAPE";break;}
+		case -1074395367:
+			{ errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_ROTATION_5";break;}
+		case -1074395368:
+			{ errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_ROTATION_4";break;}
+		case -1074395369:
+			{ errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_ROTATION_3";break;}
+		case -1074395370:
+			{ errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_ROTATION_2";break;}
+		case -1074395371:
+			{ errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_ROTATION_1";break;}
+		case -1074395372:
+			{ errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_NOROTATION";break;}
+		case -1074395373:
+			{ errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_ROTATION";break;}
+		case -1074395374:
+			{ errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_SHIFT_2";break;}
+		case -1074395375:
+			{ errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_SHIFT_1";break;}
+		case -1074395376:
+			{ errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_NOSHIFT";break;}
+		case -1074395377:
+			{ errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_SHIFT";break;}
+		case -1074395378:
+			{ errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_6";break;}
+		case -1074395379:
+			{ errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_5";break;}
+		case -1074395380:
+			{ errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_4";break;}
+		case -1074395381:
+			{ errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_3";break;}
+		case -1074395382:
+			{ errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_2";break;}
+		case -1074395383:
+			{ errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_1";break;}
+		case -1074395384:
+			{ errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR";break;}
+		case -1074395385:
+			{ errorText = "ERR_COLOR_ROTATION_REQUIRES_SHAPE_FEATURE";break;}
+		case -1074395386:
+			{ errorText = "ERR_COLOR_MATCH_SETUP_DATA_SHAPE";break;}
+		case -1074395387:
+			{ errorText = "ERR_COLOR_MATCH_SETUP_DATA";break;}
+		case -1074395388:
+			{ errorText = "ERR_COLOR_LEARN_SETUP_DATA_SHAPE";break;}
+		case -1074395389:
+			{ errorText = "ERR_COLOR_LEARN_SETUP_DATA";break;}
+		case -1074395390:
+			{ errorText = "ERR_COLOR_TEMPLATE_IMAGE_LUMINANCE_CONTRAST_TOO_LOW";break;}
+		case -1074395391:
+			{ errorText = "ERR_COLOR_TEMPLATE_IMAGE_HUE_CONTRAST_TOO_LOW";break;}
+		case -1074395392:
+			{ errorText = "ERR_COLOR_TEMPLATE_IMAGE_TOO_LARGE";break;}
+		case -1074395393:
+			{ errorText = "ERR_COLOR_TEMPLATE_IMAGE_TOO_SMALL";break;}
+		case -1074395394:
+			{ errorText = "ERR_COLOR_SPECTRUM_MASK";break;}
+		case -1074395395:
+			{ errorText = "ERR_COLOR_IMAGE_REQUIRED";break;}
+		case -1074395397:
+			{ errorText = "ERR_COMPLEX_IMAGE_REQUIRED";break;}
+		case -1074395399:
+			{ errorText = "ERR_MULTICORE_INVALID_ARGUMENT";break;}
+		case -1074395400:
+			{ errorText = "ERR_MULTICORE_OPERATION";break;}
+		case -1074395401:
+			{ errorText = "ERR_INVALID_MATCHFACTOR";break;}
+		case -1074395402:
+			{ errorText = "ERR_INVALID_MAXPOINTS";break;}
+		case -1074395403:
+			{ errorText = "ERR_EXTRAINFO_VERSION";break;}
+		case -1074395404:
+			{ errorText = "ERR_INVALID_INTERPOLATIONMETHOD_FOR_UNWRAP";break;}
+		case -1074395405:
+			{ errorText = "ERR_INVALID_TEXTORIENTATION";break;}
+		case -1074395406:
+			{ errorText = "ERR_COORDSYS_NOT_FOUND";break;}
+		case -1074395407:
+			{ errorText = "ERR_INVALID_CONTRAST";break;}
+		case -1074395408:
+			{ errorText = "ERR_INVALID_DETECTION_MODE";break;}
+		case -1074395409:
+			{ errorText = "ERR_INVALID_SUBPIXEL_DIVISIONS";break;}
+		case -1074395410:
+			{ errorText = "ERR_INVALID_ICONS_PER_LINE";break;}
+		case -1074395549:
+			{ errorText = "ERR_NIOCR_INVALID_NUMBER_OF_OBJECTS_TO_VERIFY";break;}
+		case -1074395550:
+			{ errorText = "ERR_NIOCR_INVALID_CHARACTER_VALUE";break;}
+		case -1074395551:
+			{ errorText = "ERR_NIOCR_RENAME_REFCHAR";break;}
+		case -1074395552:
+			{ errorText = "ERR_NIOCR_NOT_A_VALID_CHARACTER_SET";break;}
+		case -1074395553:
+			{ errorText = "ERR_NIOCR_INVALID_MIN_BOUNDING_RECT_HEIGHT";break;}
+		case -1074395554:
+			{ errorText = "ERR_NIOCR_INVALID_READ_RESOLUTION";break;}
+		case -1074395555:
+			{ errorText = "ERR_NIOCR_INVALID_SPACING_RANGE";break;}
+		case -1074395556:
+			{ errorText = "ERR_NIOCR_INVALID_BOUNDING_RECT_HEIGHT_RANGE";break;}
+		case -1074395557:
+			{ errorText = "ERR_NIOCR_INVALID_BOUNDING_RECT_WIDTH_RANGE";break;}
+		case -1074395558:
+			{ errorText = "ERR_NIOCR_INVALID_CHARACTER_SIZE_RANGE";break;}
+		case -1074395559:
+			{ errorText = "ERR_NIOCR_INVALID_READ_OPTION";break;}
+		case -1074395560:
+			{ errorText = "ERR_NIOCR_INVALID_OBJECT_INDEX";break;}
+		case -1074395561:
+			{ errorText = "ERR_NIOCR_INVALID_NUMBER_OF_CHARACTERS";break;}
+		case -1074395562:
+			{ errorText = "ERR_NIOCR_BOOLEAN_VALUE_FOR_STRING_ATTRIBUTE";break;}
+		case -1074395563:
+			{ errorText = "ERR_NIOCR_UNLICENSED";break;}
+		case -1074395564:
+			{ errorText = "ERR_NIOCR_INVALID_PREDEFINED_CHARACTER";break;}
+		case -1074395565:
+			{ errorText = "ERR_NIOCR_MUST_BE_SINGLE_CHARACTER";break;}
+		case -1074395566:
+			{ errorText = "ERR_NIOCR_BOOLEAN_VALUE_FOR_INTEGER_ATTRIBUTE";break;}
+		case -1074395567:
+			{ errorText = "ERR_NIOCR_STRING_VALUE_FOR_BOOLEAN_ATTRIBUTE";break;}
+		case -1074395568:
+			{ errorText = "ERR_NIOCR_STRING_VALUE_FOR_INTEGER_ATTRIBUTE";break;}
+		case -1074395569:
+			{ errorText = "ERR_NIOCR_INVALID_ATTRIBUTE";break;}
+		case -1074395570:
+			{ errorText = "ERR_NIOCR_INTEGER_VALUE_FOR_BOOLEAN_ATTRIBUTE";break;}
+		case -1074395571:
+			{ errorText = "ERR_NIOCR_GET_ONLY_ATTRIBUTE";break;}
+		case -1074395572:
+			{ errorText = "ERR_NIOCR_INTEGER_VALUE_FOR_STRING_ATTRIBUTE";break;}
+		case -1074395573:
+			{ errorText = "ERR_NIOCR_INVALID_CHARACTER_SET_FILE_VERSION";break;}
+		case -1074395574:
+			{ errorText = "ERR_NIOCR_CHARACTER_SET_DESCRIPTION_TOO_LONG";break;}
+		case -1074395575:
+			{ errorText = "ERR_NIOCR_INVALID_NUMBER_OF_EROSIONS";break;}
+		case -1074395576:
+			{ errorText = "ERR_NIOCR_CHARACTER_VALUE_TOO_LONG";break;}
+		case -1074395577:
+			{ errorText = "ERR_NIOCR_CHARACTER_VALUE_CANNOT_BE_EMPTYSTRING";break;}
+		case -1074395578:
+			{ errorText = "ERR_NIOCR_INVALID_CHARACTER_SET_FILE";break;}
+		case -1074395579:
+			{ errorText = "ERR_NIOCR_INVALID_ASPECT_RATIO";break;}
+		case -1074395580:
+			{ errorText = "ERR_NIOCR_INVALID_MIN_BOUNDING_RECT_WIDTH";break;}
+		case -1074395581:
+			{ errorText = "ERR_NIOCR_INVALID_MAX_VERT_ELEMENT_SPACING";break;}
+		case -1074395582:
+			{ errorText = "ERR_NIOCR_INVALID_MAX_HORIZ_ELEMENT_SPACING";break;}
+		case -1074395583:
+			{ errorText = "ERR_NIOCR_INVALID_MIN_CHAR_SPACING";break;}
+		case -1074395584:
+			{ errorText = "ERR_NIOCR_INVALID_THRESHOLD_LIMITS";break;}
+		case -1074395585:
+			{ errorText = "ERR_NIOCR_INVALID_UPPER_THRESHOLD_LIMIT";break;}
+		case -1074395586:
+			{ errorText = "ERR_NIOCR_INVALID_LOWER_THRESHOLD_LIMIT";break;}
+		case -1074395587:
+			{ errorText = "ERR_NIOCR_INVALID_THRESHOLD_RANGE";break;}
+		case -1074395588:
+			{ errorText = "ERR_NIOCR_INVALID_HIGH_THRESHOLD_VALUE";break;}
+		case -1074395589:
+			{ errorText = "ERR_NIOCR_INVALID_LOW_THRESHOLD_VALUE";break;}
+		case -1074395590:
+			{ errorText = "ERR_NIOCR_INVALID_NUMBER_OF_VALID_CHARACTER_POSITIONS";break;}
+		case -1074395591:
+			{ errorText = "ERR_NIOCR_INVALID_CHARACTER_INDEX";break;}
+		case -1074395592:
+			{ errorText = "ERR_NIOCR_INVALID_READ_STRATEGY";break;}
+		case -1074395593:
+			{ errorText = "ERR_NIOCR_INVALID_NUMBER_OF_BLOCKS";break;}
+		case -1074395594:
+			{ errorText = "ERR_NIOCR_INVALID_SUBSTITUTION_CHARACTER";break;}
+		case -1074395595:
+			{ errorText = "ERR_NIOCR_INVALID_THRESHOLD_MODE";break;}
+		case -1074395596:
+			{ errorText = "ERR_NIOCR_INVALID_CHARACTER_SIZE";break;}
+		case -1074395597:
+			{ errorText = "ERR_NIOCR_NOT_A_VALID_SESSION";break;}
+		case -1074395598:
+			{ errorText = "ERR_NIOCR_INVALID_ACCEPTANCE_LEVEL";break;}
+		case -1074395600:
+			{ errorText = "ERR_INFO_NOT_FOUND";break;}
+		case -1074395601:
+			{ errorText = "ERR_INVALID_EDGE_THRESHOLD";break;}
+		case -1074395602:
+			{ errorText = "ERR_INVALID_MINIMUM_CURVE_LENGTH";break;}
+		case -1074395603:
+			{ errorText = "ERR_INVALID_ROW_STEP";break;}
+		case -1074395604:
+			{ errorText = "ERR_INVALID_COLUMN_STEP";break;}
+		case -1074395605:
+			{ errorText = "ERR_INVALID_MAXIMUM_END_POINT_GAP";break;}
+		case -1074395606:
+			{ errorText = "ERR_INVALID_MINIMUM_FEATURES_TO_MATCH";break;}
+		case -1074395607:
+			{ errorText = "ERR_INVALID_MAXIMUM_FEATURES_PER_MATCH";break;}
+		case -1074395608:
+			{ errorText = "ERR_INVALID_SUBPIXEL_ITERATIONS";break;}
+		case -1074395609:
+			{ errorText = "ERR_INVALID_SUBPIXEL_TOLERANCE";break;}
+		case -1074395610:
+			{ errorText = "ERR_INVALID_INITIAL_MATCH_LIST_LENGTH";break;}
+		case -1074395611:
+			{ errorText = "ERR_INVALID_MINIMUM_RECTANGLE_DIMENSION";break;}
+		case -1074395612:
+			{ errorText = "ERR_INVALID_MINIMUM_FEATURE_RADIUS";break;}
+		case -1074395613:
+			{ errorText = "ERR_INVALID_MINIMUM_FEATURE_LENGTH";break;}
+		case -1074395614:
+			{ errorText = "ERR_INVALID_MINIMUM_FEATURE_ASPECT_RATIO";break;}
+		case -1074395615:
+			{ errorText = "ERR_INVALID_MINIMUM_FEATURE_STRENGTH";break;}
+		case -1074395616:
+			{ errorText = "ERR_INVALID_EDGE_FILTER_SIZE";break;}
+		case -1074395617:
+			{ errorText = "ERR_INVALID_NUMBER_OF_FEATURES_RANGE";break;}
+		case -1074395618:
+			{ errorText = "ERR_TOO_MANY_SCALE_RANGES";break;}
+		case -1074395619:
+			{ errorText = "ERR_TOO_MANY_OCCLUSION_RANGES";break;}
+		case -1074395620:
+			{ errorText = "ERR_INVALID_CURVE_EXTRACTION_MODE";break;}
+		case -1074395621:
+			{ errorText = "ERR_INVALID_LEARN_GEOMETRIC_PATTERN_SETUP_DATA";break;}
+		case -1074395622:
+			{ errorText = "ERR_INVALID_MATCH_GEOMETRIC_PATTERN_SETUP_DATA";break;}
+		case -1074395623:
+			{ errorText = "ERR_INVALID_SCALE_RANGE";break;}
+		case -1074395624:
+			{ errorText = "ERR_INVALID_OCCLUSION_RANGE";break;}
+		case -1074395625:
+			{ errorText = "ERR_INVALID_MATCH_CONSTRAINT_TYPE";break;}
+		case -1074395626:
+			{ errorText = "ERR_NOT_ENOUGH_TEMPLATE_FEATURES";break;}
+		case -1074395627:
+			{ errorText = "ERR_NOT_ENOUGH_TEMPLATE_FEATURES_1";break;}
+		case -1074395628:
+			{ errorText = "ERR_INVALID_GEOMETRIC_MATCHING_TEMPLATE";break;}
+		case -1074395629:
+			{ errorText = "ERR_INVALID_MAXIMUM_PIXEL_DISTANCE_FROM_LINE";break;}
+		case -1074395630:
+			{ errorText = "ERR_INVALID_MAXIMUM_FEATURES_LEARNED";break;}
+		case -1074395631:
+			{ errorText = "ERR_INVALID_MIN_MATCH_SEPARATION_DISTANCE";break;}
+		case -1074395632:
+			{ errorText = "ERR_INVALID_MIN_MATCH_SEPARATION_ANGLE";break;}
+		case -1074395633:
+			{ errorText = "ERR_INVALID_MIN_MATCH_SEPARATION_SCALE";break;}
+		case -1074395634:
+			{ errorText = "ERR_INVALID_MAX_MATCH_OVERLAP";break;}
+		case -1074395635:
+			{ errorText = "ERR_INVALID_SHAPE_DESCRIPTOR";break;}
+		case -1074395636:
+			{ errorText = "ERR_DIRECTX_NOT_FOUND";break;}
+		case -1074395637:
+			{ errorText = "ERR_HARDWARE_DOESNT_SUPPORT_NONTEARING";break;}
+		case -1074395638:
+			{ errorText = "ERR_INVALID_FILL_STYLE";break;}
+		case -1074395639:
+			{ errorText = "ERR_INVALID_HATCH_STYLE";break;}
+		case -1074395640:
+			{ errorText = "ERR_TOO_MANY_ZONES";break;}
+		case -1074395641:
+			{ errorText = "ERR_DUPLICATE_LABEL";break;}
+		case -1074395642:
+			{ errorText = "ERR_LABEL_NOT_FOUND";break;}
+		case -1074395643:
+			{ errorText = "ERR_INVALID_NUMBER_OF_MATCH_OPTIONS";break;}
+		case -1074395644:
+			{ errorText = "ERR_LABEL_TOO_LONG";break;}
+		case -1074395645:
+			{ errorText = "ERR_INVALID_NUMBER_OF_LABELS";break;}
+		case -1074395646:
+			{ errorText = "ERR_NO_TEMPLATE_TO_LEARN";break;}
+		case -1074395647:
+			{ errorText = "ERR_INVALID_MULTIPLE_GEOMETRIC_TEMPLATE";break;}
+		case -1074395648:
+			{ errorText = "ERR_TEMPLATE_NOT_LEARNED";break;}
+		case -1074395649:
+			{ errorText = "ERR_INVALID_GEOMETRIC_FEATURE_TYPE";break;}
+		case -1074395650:
+			{ errorText = "ERR_CURVE_EXTRACTION_MODE_MUST_BE_SAME";break;}
+		case -1074395651:
+			{ errorText = "ERR_EDGE_FILTER_SIZE_MUST_BE_SAME";break;}
+		case -1074395652:
+			{ errorText = "ERR_OPENING_NEWER_GEOMETRIC_MATCHING_TEMPLATE";break;}
+		case -1074395653:
+			{ errorText = "ERR_OPENING_NEWER_MULTIPLE_GEOMETRIC_TEMPLATE";break;}
+		case -1074395654:
+			{ errorText = "ERR_GRADING_INFORMATION_NOT_FOUND";break;}
+		case -1074395655:
+			{ errorText = "ERR_ENABLE_CALIBRATION_SUPPORT_MUST_BE_SAME";break;}
+		case -1074395656:
+			{ errorText = "ERR_SMOOTH_CONTOURS_MUST_BE_SAME";break;}
+		case -1074395700:
+			{ errorText = "ERR_REQUIRES_WIN2000_OR_NEWER";break;}
+		case -1074395701:
+			{ errorText = "ERR_INVALID_MATRIX_SIZE_RANGE";break;}
+		case -1074395702:
+			{ errorText = "ERR_INVALID_LENGTH";break;}
+		case -1074395703:
+			{ errorText = "ERR_INVALID_TYPE_OF_FLATTEN";break;}
+		case -1074395704:
+			{ errorText = "ERR_INVALID_COMPRESSION_TYPE";break;}
+		case -1074395705:
+			{ errorText = "ERR_DATA_CORRUPTED";break;}
+		case -1074395706:
+			{ errorText = "ERR_AVI_SESSION_ALREADY_OPEN";break;}
+		case -1074395707:
+			{ errorText = "ERR_AVI_WRITE_SESSION_REQUIRED";break;}
+		case -1074395708:
+			{ errorText = "ERR_AVI_READ_SESSION_REQUIRED";break;}
+		case -1074395709:
+			{ errorText = "ERR_AVI_UNOPENED_SESSION";break;}
+		case -1074395710:
+			{ errorText = "ERR_TOO_MANY_PARTICLES";break;}
+		case -1074395711:
+			{ errorText = "ERR_NOT_ENOUGH_REGIONS";break;}
+		case -1074395712:
+			{ errorText = "ERR_WRONG_REGION_TYPE";break;}
+		case -1074395713:
+			{ errorText = "ERR_VALUE_NOT_IN_ENUM";break;}
+		case -1074395714:
+			{ errorText = "ERR_INVALID_AXIS_ORIENTATION";break;}
+		case -1074395715:
+			{ errorText = "ERR_INVALID_CALIBRATION_UNIT";break;}
+		case -1074395716:
+			{ errorText = "ERR_INVALID_SCALING_METHOD";break;}
+		case -1074395717:
+			{ errorText = "ERR_INVALID_RANGE";break;}
+		case -1074395718:
+			{ errorText = "ERR_LAB_VERSION";break;}
+		case -1074395719:
+			{ errorText = "ERR_BAD_ROI_BOX";break;}
+		case -1074395720:
+			{ errorText = "ERR_BAD_ROI";break;}
+		case -1074395721:
+			{ errorText = "ERR_INVALID_BIT_DEPTH";break;}
+		case -1074395722:
+			{ errorText = "ERR_CLASSIFIER_CLASSIFY_IMAGE_WITH_CUSTOM_SESSION";break;}
+		case -1074395723:
+			{ errorText = "ERR_CUSTOMDATA_KEY_NOT_FOUND";break;}
+		case -1074395724:
+			{ errorText = "ERR_CUSTOMDATA_INVALID_SIZE";break;}
+		case -1074395725:
+			{ errorText = "ERR_DATA_VERSION";break;}
+		case -1074395726:
+			{ errorText = "ERR_MATCHFACTOR_OBSOLETE";break;}
+		case -1074395727:
+			{ errorText = "ERR_UNSUPPORTED_2D_BARCODE_SEARCH_MODE";break;}
+		case -1074395728:
+			{ errorText = "ERR_INVALID_2D_BARCODE_SEARCH_MODE";break;}
+		case -1074395754:
+			{ errorText = "ERR_TRIG_TIMEOUT";break;}
+		case -1074395756:
+			{ errorText = "ERR_DLL_FUNCTION_NOT_FOUND";break;}
+		case -1074395757:
+			{ errorText = "ERR_DLL_NOT_FOUND";break;}
+		case -1074395758:
+			{ errorText = "ERR_BOARD_NOT_OPEN";break;}
+		case -1074395760:
+			{ errorText = "ERR_BOARD_NOT_FOUND";break;}
+		case -1074395762:
+			{ errorText = "ERR_INVALID_NIBLACK_DEVIATION_FACTOR";break;}
+		case -1074395763:
+			{ errorText = "ERR_INVALID_NORMALIZATION_METHOD";break;}
+		case -1074395766:
+			{ errorText = "ERR_DEPRECATED_FUNCTION";break;}
+		case -1074395767:
+			{ errorText = "ERR_INVALID_ALIGNMENT";break;}
+		case -1074395768:
+			{ errorText = "ERR_INVALID_SCALE";break;}
+		case -1074395769:
+			{ errorText = "ERR_INVALID_EDGE_THICKNESS";break;}
+		case -1074395770:
+			{ errorText = "ERR_INVALID_INSPECTION_TEMPLATE";break;}
+		case -1074395771:
+			{ errorText = "ERR_OPENING_NEWER_INSPECTION_TEMPLATE";break;}
+		case -1074395772:
+			{ errorText = "ERR_INVALID_REGISTRATION_METHOD";break;}
+		case -1074395773:
+			{ errorText = "ERR_NO_DEST_IMAGE";break;}
+		case -1074395774:
+			{ errorText = "ERR_NO_LABEL";break;}
+		case -1074395775:
+			{ errorText = "ERR_ROI_HAS_OPEN_CONTOURS";break;}
+		case -1074395776:
+			{ errorText = "ERR_INVALID_USE_OF_COMPACT_SESSION_FILE";break;}
+		case -1074395777:
+			{ errorText = "ERR_INCOMPATIBLE_CLASSIFIER_TYPES";break;}
+		case -1074395778:
+			{ errorText = "ERR_INVALID_KERNEL_SIZE";break;}
+		case -1074395779:
+			{ errorText = "ERR_CANNOT_COMPACT_UNTRAINED";break;}
+		case -1074395780:
+			{ errorText = "ERR_INVALID_PARTICLE_TYPE";break;}
+		case -1074395781:
+			{ errorText = "ERR_CLASSIFIER_INVALID_ENGINE_TYPE";break;}
+		case -1074395782:
+			{ errorText = "ERR_DESCRIPTION_TOO_LONG";break;}
+		case -1074395783:
+			{ errorText = "ERR_BAD_SAMPLE_INDEX";break;}
+		case -1074395784:
+			{ errorText = "ERR_INVALID_LIMITS";break;}
+		case -1074395785:
+			{ errorText = "ERR_NO_PARTICLE";break;}
+		case -1074395786:
+			{ errorText = "ERR_INVALID_PARTICLE_OPTIONS";break;}
+		case -1074395787:
+			{ errorText = "ERR_INVALID_CLASSIFIER_TYPE";break;}
+		case -1074395788:
+			{ errorText = "ERR_NO_SAMPLES";break;}
+		case -1074395789:
+			{ errorText = "ERR_OPENING_NEWER_CLASSIFIER_SESSION";break;}
+		case -1074395790:
+			{ errorText = "ERR_INVALID_DISTANCE_METRIC";break;}
+		case -1074395791:
+			{ errorText = "ERR_CLASSIFIER_INVALID_SESSION_TYPE";break;}
+		case -1074395792:
+			{ errorText = "ERR_CLASSIFIER_SESSION_NOT_TRAINED";break;}
+		case -1074395793:
+			{ errorText = "ERR_INVALID_OPERATION_ON_COMPACT_SESSION_ATTEMPTED";break;}
+		case -1074395794:
+			{ errorText = "ERR_K_TOO_HIGH";break;}
+		case -1074395795:
+			{ errorText = "ERR_K_TOO_LOW";break;}
+		case -1074395796:
+			{ errorText = "ERR_INVALID_KNN_METHOD";break;}
+		case -1074395797:
+			{ errorText = "ERR_INVALID_CLASSIFIER_SESSION";break;}
+		case -1074395798:
+			{ errorText = "ERR_INVALID_CUSTOM_SAMPLE";break;}
+		case -1074395799:
+			{ errorText = "ERR_INTERNAL";break;}
+		case -1074395800:
+			{ errorText = "ERR_PROTECTION";break;}
+		case -1074395801:
+			{ errorText = "ERR_TOO_MANY_CONTOURS";break;}
+		case -1074395837:
+			{ errorText = "ERR_INVALID_COMPRESSION_RATIO";break;}
+		case -1074395840:
+			{ errorText = "ERR_BAD_INDEX";break;}
+		case -1074395875:
+			{ errorText = "ERR_BARCODE_PHARMACODE";break;}
+		case -1074395876:
+			{ errorText = "ERR_UNSUPPORTED_COLOR_MODE";break;}
+		case -1074395877:
+			{ errorText = "ERR_COLORMODE_REQUIRES_CHANGECOLORSPACE2";break;}
+		case -1074395878:
+			{ errorText = "ERR_PROP_NODE_WRITE_NOT_SUPPORTED";break;}
+		case -1074395879:
+			{ errorText = "ERR_BAD_MEASURE";break;}
+		case -1074395880:
+			{ errorText = "ERR_PARTICLE";break;}
+		case -1074395920:
+			{ errorText = "ERR_NUMBER_CLASS";break;}
+		case -1074395953:
+			{ errorText = "ERR_INVALID_WAVELET_TRANSFORM_MODE";break;}
+		case -1074395954:
+			{ errorText = "ERR_INVALID_QUANTIZATION_STEP_SIZE";break;}
+		case -1074395955:
+			{ errorText = "ERR_INVALID_MAX_WAVELET_TRANSFORM_LEVEL";break;}
+		case -1074395956:
+			{ errorText = "ERR_INVALID_QUALITY";break;}
+		case -1074395957:
+			{ errorText = "ERR_ARRAY_SIZE_MISMATCH";break;}
+		case -1074395958:
+			{ errorText = "ERR_WINDOW_ID";break;}
+		case -1074395959:
+			{ errorText = "ERR_CREATE_WINDOW";break;}
+		case -1074395960:
+			{ errorText = "ERR_INIT";break;}
+		case -1074395971:
+			{ errorText = "ERR_INVALID_OFFSET";break;}
+		case -1074395972:
+			{ errorText = "ERR_DIRECTX_ENUMERATE_FILTERS";break;}
+		case -1074395973:
+			{ errorText = "ERR_JPEG2000_UNSUPPORTED_MULTIPLE_LAYERS";break;}
+		case -1074395974:
+			{ errorText = "ERR_UNSUPPORTED_JPEG2000_COLORSPACE_METHOD";break;}
+		case -1074395975:
+			{ errorText = "ERR_AVI_TIMEOUT";break;}
+		case -1074395976:
+			{ errorText = "ERR_NUMBER_OF_PALETTE_COLORS";break;}
+		case -1074395977:
+			{ errorText = "ERR_AVI_VERSION";break;}
+		case -1074395978:
+			{ errorText = "ERR_INVALID_PARTICLE_NUMBER";break;}
+		case -1074395979:
+			{ errorText = "ERR_INVALID_PARTICLE_INFO";break;}
+		case -1074395980:
+			{ errorText = "ERR_COM_INITIALIZE";break;}
+		case -1074395981:
+			{ errorText = "ERR_INSUFFICIENT_BUFFER_SIZE";break;}
+		case -1074395982:
+			{ errorText = "ERR_INVALID_FRAMES_PER_SECOND";break;}
+		case -1074395983:
+			{ errorText = "ERR_FILE_NO_SPACE";break;}
+		case -1074395984:
+			{ errorText = "ERR_FILE_INVALID_DATA_TYPE";break;}
+		case -1074395985:
+			{ errorText = "ERR_FILE_OPERATION";break;}
+		case -1074395986:
+			{ errorText = "ERR_FILE_FORMAT";break;}
+		case -1074395987:
+			{ errorText = "ERR_FILE_EOF";break;}
+		case -1074395988:
+			{ errorText = "ERR_FILE_WRITE";break;}
+		case -1074395989:
+			{ errorText = "ERR_FILE_READ";break;}
+		case -1074395990:
+			{ errorText = "ERR_FILE_GET_INFO";break;}
+		case -1074395991:
+			{ errorText = "ERR_FILE_INVALID_TYPE";break;}
+		case -1074395992:
+			{ errorText = "ERR_FILE_PERMISSION";break;}
+		case -1074395993:
+			{ errorText = "ERR_FILE_IO_ERR";break;}
+		case -1074395994:
+			{ errorText = "ERR_FILE_TOO_MANY_OPEN";break;}
+		case -1074395995:
+			{ errorText = "ERR_FILE_NOT_FOUND";break;}
+		case -1074395996:
+			{ errorText = "ERR_FILE_OPEN";break;}
+		case -1074395997:
+			{ errorText = "ERR_FILE_ARGERR";break;}
+		case -1074395998:
+			{ errorText = "ERR_FILE_COLOR_TABLE";break;}
+		case -1074395999:
+			{ errorText = "ERR_FILE_FILE_TYPE";break;}
+		case -1074396000:
+			{ errorText = "ERR_FILE_FILE_HEADER";break;}
+		case -1074396001:
+			{ errorText = "ERR_TOO_MANY_AVI_SESSIONS";break;}
+		case -1074396002:
+			{ errorText = "ERR_INVALID_LINEGAUGEMETHOD";break;}
+		case -1074396003:
+			{ errorText = "ERR_AVI_DATA_EXCEEDS_BUFFER_SIZE";break;}
+		case -1074396004:
+			{ errorText = "ERR_DIRECTX_CERTIFICATION_FAILURE";break;}
+		case -1074396005:
+			{ errorText = "ERR_INVALID_AVI_SESSION";break;}
+		case -1074396006:
+			{ errorText = "ERR_DIRECTX_UNKNOWN_COMPRESSION_FILTER";break;}
+		case -1074396007:
+			{ errorText = "ERR_DIRECTX_INCOMPATIBLE_COMPRESSION_FILTER";break;}
+		case -1074396008:
+			{ errorText = "ERR_DIRECTX_NO_FILTER";break;}
+		case -1074396009:
+			{ errorText = "ERR_DIRECTX";break;}
+		case -1074396010:
+			{ errorText = "ERR_INVALID_FRAME_NUMBER";break;}
+		case -1074396011:
+			{ errorText = "ERR_RPC_BIND";break;}
+		case -1074396012:
+			{ errorText = "ERR_RPC_EXECUTE";break;}
+		case -1074396013:
+			{ errorText = "ERR_INVALID_VIDEO_MODE";break;}
+		case -1074396014:
+			{ errorText = "ERR_INVALID_VIDEO_BLIT";break;}
+		case -1074396015:
+			{ errorText = "ERR_RPC_EXECUTE_IVB";break;}
+		case -1074396016:
+			{ errorText = "ERR_NO_VIDEO_DRIVER";break;}
+		case -1074396017:
+			{ errorText = "ERR_OPENING_NEWER_AIM_GRADING_DATA";break;}
+		case -1074396018:
+			{ errorText = "ERR_INVALID_EDGE_POLARITY_SEARCH_MODE";break;}
+		case -1074396019:
+			{ errorText = "ERR_INVALID_THRESHOLD_PERCENTAGE";break;}
+		case -1074396020:
+			{ errorText = "ERR_INVALID_GRADING_MODE";break;}
+		case -1074396021:
+			{ errorText = "ERR_INVALID_KERNEL_SIZE_FOR_EDGE_DETECTION";break;}
+		case -1074396022:
+			{ errorText = "ERR_INVALID_SEARCH_MODE_FOR_STRAIGHT_EDGE";break;}
+		case -1074396023:
+			{ errorText = "ERR_INVALID_ANGLE_TOL_FOR_STRAIGHT_EDGE";break;}
+		case -1074396024:
+			{ errorText = "ERR_INVALID_MIN_COVERAGE_FOR_STRAIGHT_EDGE";break;}
+		case -1074396025:
+			{ errorText = "ERR_INVALID_ANGLE_RANGE_FOR_STRAIGHT_EDGE";break;}
+		case -1074396026:
+			{ errorText = "ERR_INVALID_PROCESS_TYPE_FOR_EDGE_DETECTION";break;}
+		case -1074396032:
+			{ errorText = "ERR_TEMPLATEDESCRIPTOR_ROTATION_SEARCHSTRATEGY";break;}
+		case -1074396033:
+			{ errorText = "ERR_TEMPLATEDESCRIPTOR_LEARNSETUPDATA";break;}
+		case -1074396034:
+			{ errorText = "ERR_TEMPLATEIMAGE_EDGEINFO";break;}
+		case -1074396035:
+			{ errorText = "ERR_TEMPLATEIMAGE_NOCIRCLE";break;}
+		case -1074396036:
+			{ errorText = "ERR_INVALID_SKELETONMODE";break;}
+		case -1074396037:
+			{ errorText = "ERR_TIMEOUT";break;}
+		case -1074396038:
+			{ errorText = "ERR_FIND_COORDSYS_MORE_THAN_ONE_EDGE";break;}
+		case -1074396039:
+			{ errorText = "ERR_IO_ERROR";break;}
+		case -1074396040:
+			{ errorText = "ERR_DRIVER";break;}
+		case -1074396041:
+			{ errorText = "ERR_INVALID_2D_BARCODE_TYPE";break;}
+		case -1074396042:
+			{ errorText = "ERR_INVALID_2D_BARCODE_CONTRAST";break;}
+		case -1074396043:
+			{ errorText = "ERR_INVALID_2D_BARCODE_CELL_SHAPE";break;}
+		case -1074396044:
+			{ errorText = "ERR_INVALID_2D_BARCODE_SHAPE";break;}
+		case -1074396045:
+			{ errorText = "ERR_INVALID_2D_BARCODE_SUBTYPE";break;}
+		case -1074396046:
+			{ errorText = "ERR_INVALID_2D_BARCODE_CONTRAST_FOR_ROI";break;}
+		case -1074396047:
+			{ errorText = "ERR_INVALID_LINEAR_AVERAGE_MODE";break;}
+		case -1074396048:
+			{ errorText = "ERR_INVALID_CELL_SAMPLE_SIZE";break;}
+		case -1074396049:
+			{ errorText = "ERR_INVALID_MATRIX_POLARITY";break;}
+		case -1074396050:
+			{ errorText = "ERR_INVALID_ECC_TYPE";break;}
+		case -1074396051:
+			{ errorText = "ERR_INVALID_CELL_FILTER_MODE";break;}
+		case -1074396052:
+			{ errorText = "ERR_INVALID_DEMODULATION_MODE";break;}
+		case -1074396053:
+			{ errorText = "ERR_INVALID_BORDER_INTEGRITY";break;}
+		case -1074396054:
+			{ errorText = "ERR_INVALID_CELL_FILL_TYPE";break;}
+		case -1074396055:
+			{ errorText = "ERR_INVALID_ASPECT_RATIO";break;}
+		case -1074396056:
+			{ errorText = "ERR_INVALID_MATRIX_MIRROR_MODE";break;}
+		case -1074396057:
+			{ errorText = "ERR_INVALID_SEARCH_VECTOR_WIDTH";break;}
+		case -1074396058:
+			{ errorText = "ERR_INVALID_ROTATION_MODE";break;}
+		case -1074396059:
+			{ errorText = "ERR_INVALID_MAX_ITERATIONS";break;}
+		case -1074396060:
+			{ errorText = "ERR_JPEG2000_LOSSLESS_WITH_FLOATING_POINT";break;}
+		case -1074396061:
+			{ errorText = "ERR_INVALID_WINDOW_SIZE";break;}
+		case -1074396062:
+			{ errorText = "ERR_INVALID_TOLERANCE";break;}
+		case -1074396063:
+			{ errorText = "ERR_EXTERNAL_ALIGNMENT";break;}
+		case -1074396064:
+			{ errorText = "ERR_EXTERNAL_NOT_SUPPORTED";break;}
+		case -1074396065:
+			{ errorText = "ERR_CANT_RESIZE_EXTERNAL";break;}
+		case -1074396066:
+			{ errorText = "ERR_INVALID_POINTSYMBOL";break;}
+		case -1074396067:
+			{ errorText = "ERR_IMAGES_NOT_DIFF";break;}
+		case -1074396068:
+			{ errorText = "ERR_INVALID_ACTION";break;}
+		case -1074396069:
+			{ errorText = "ERR_INVALID_COLOR_MODE";break;}
+		case -1074396070:
+			{ errorText = "ERR_INVALID_FUNCTION";break;}
+		case -1074396071:
+			{ errorText = "ERR_INVALID_SCAN_DIRECTION";break;}
+		case -1074396072:
+			{ errorText = "ERR_INVALID_BORDER";break;}
+		case -1074396073:
+			{ errorText = "ERR_MASK_OUTSIDE_IMAGE";break;}
+		case -1074396074:
+			{ errorText = "ERR_INCOMP_SIZE";break;}
+		case -1074396075:
+			{ errorText = "ERR_COORD_SYS_SECOND_AXIS";break;}
+		case -1074396076:
+			{ errorText = "ERR_COORD_SYS_FIRST_AXIS";break;}
+		case -1074396077:
+			{ errorText = "ERR_INCOMP_TYPE";break;}
+		case -1074396079:
+			{ errorText = "ERR_INVALID_METAFILE_HANDLE";break;}
+		case -1074396080:
+			{ errorText = "ERR_INVALID_IMAGE_TYPE";break;}
+		case -1074396081:
+			{ errorText = "ERR_BAD_PASSWORD";break;}
+		case -1074396082:
+			{ errorText = "ERR_PALETTE_NOT_SUPPORTED";break;}
+		case -1074396083:
+			{ errorText = "ERR_ROLLBACK_TIMEOUT";break;}
+		case -1074396084:
+			{ errorText = "ERR_ROLLBACK_DELETE_TIMER";break;}
+		case -1074396085:
+			{ errorText = "ERR_ROLLBACK_INIT_TIMER";break;}
+		case -1074396086:
+			{ errorText = "ERR_ROLLBACK_START_TIMER";break;}
+		case -1074396087:
+			{ errorText = "ERR_ROLLBACK_STOP_TIMER";break;}
+		case -1074396088:
+			{ errorText = "ERR_ROLLBACK_RESIZE";break;}
+		case -1074396089:
+			{ errorText = "ERR_ROLLBACK_RESOURCE_REINITIALIZE";break;}
+		case -1074396090:
+			{ errorText = "ERR_ROLLBACK_RESOURCE_ENABLED";break;}
+		case -1074396091:
+			{ errorText = "ERR_ROLLBACK_RESOURCE_UNINITIALIZED_ENABLE";break;}
+		case -1074396092:
+			{ errorText = "ERR_ROLLBACK_RESOURCE_NON_EMPTY_INITIALIZE";break;}
+		case -1074396093:
+			{ errorText = "ERR_ROLLBACK_RESOURCE_LOCKED";break;}
+		case -1074396094:
+			{ errorText = "ERR_ROLLBACK_RESOURCE_CANNOT_UNLOCK";break;}
+		case -1074396095:
+			{ errorText = "ERR_CALIBRATION_DUPLICATE_REFERENCE_POINT";break;}
+		case -1074396096:
+			{ errorText = "ERR_NOT_AN_OBJECT";break;}
+		case -1074396097:
+			{ errorText = "ERR_INVALID_PARTICLE_PARAMETER_VALUE";break;}
+		case -1074396098:
+			{ errorText = "ERR_RESERVED_MUST_BE_NULL";break;}
+		case -1074396099:
+			{ errorText = "ERR_CALIBRATION_INFO_SIMPLE_TRANSFORM";break;}
+		case -1074396100:
+			{ errorText = "ERR_CALIBRATION_INFO_PERSPECTIVE_PROJECTION";break;}
+		case -1074396101:
+			{ errorText = "ERR_CALIBRATION_INFO_MICRO_PLANE";break;}
+		case -1074396102:
+			{ errorText = "ERR_CALIBRATION_INFO_6";break;}
+		case -1074396103:
+			{ errorText = "ERR_CALIBRATION_INFO_5";break;}
+		case -1074396104:
+			{ errorText = "ERR_CALIBRATION_INFO_4";break;}
+		case -1074396105:
+			{ errorText = "ERR_CALIBRATION_INFO_3";break;}
+		case -1074396106:
+			{ errorText = "ERR_CALIBRATION_INFO_2";break;}
+		case -1074396107:
+			{ errorText = "ERR_CALIBRATION_INFO_1";break;}
+		case -1074396108:
+			{ errorText = "ERR_CALIBRATION_ERRORMAP";break;}
+		case -1074396109:
+			{ errorText = "ERR_CALIBRATION_INVALID_SCALING_FACTOR";break;}
+		case -1074396110:
+			{ errorText = "ERR_CALIBRATION_INFO_VERSION";break;}
+		case -1074396111:
+			{ errorText = "ERR_CALIBRATION_FAILED_TO_FIND_GRID";break;}
+		case -1074396112:
+			{ errorText = "ERR_INCOMP_MATRIX_SIZE";break;}
+		case -1074396113:
+			{ errorText = "ERR_CALIBRATION_IMAGE_UNCALIBRATED";break;}
+		case -1074396114:
+			{ errorText = "ERR_CALIBRATION_INVALID_ROI";break;}
+		case -1074396115:
+			{ errorText = "ERR_CALIBRATION_IMAGE_CORRECTED";break;}
+		case -1074396116:
+			{ errorText = "ERR_CALIBRATION_INSF_POINTS";break;}
+		case -1074396117:
+			{ errorText = "ERR_MATRIX_SIZE";break;}
+		case -1074396118:
+			{ errorText = "ERR_INVALID_STEP_SIZE";break;}
+		case -1074396119:
+			{ errorText = "ERR_CUSTOMDATA_INVALID_KEY";break;}
+		case -1074396120:
+			{ errorText = "ERR_NOT_IMAGE";break;}
+		case -1074396121:
+			{ errorText = "ERR_SATURATION_THRESHOLD_OUT_OF_RANGE";break;}
+		case -1074396122:
+			{ errorText = "ERR_DRAWTEXT_COLOR_MUST_BE_GRAYSCALE";break;}
+		case -1074396123:
+			{ errorText = "ERR_INVALID_CALIBRATION_MODE";break;}
+		case -1074396124:
+			{ errorText = "ERR_INVALID_CALIBRATION_ROI_MODE";break;}
+		case -1074396125:
+			{ errorText = "ERR_INVALID_CONTRAST_THRESHOLD";break;}
+		case -1074396126:
+			{ errorText = "ERR_ROLLBACK_RESOURCE_CONFLICT_1";break;}
+		case -1074396127:
+			{ errorText = "ERR_ROLLBACK_RESOURCE_CONFLICT_2";break;}
+		case -1074396128:
+			{ errorText = "ERR_ROLLBACK_RESOURCE_CONFLICT_3";break;}
+		case -1074396129:
+			{ errorText = "ERR_ROLLBACK_UNBOUNDED_INTERFACE";break;}
+		case -1074396130:
+			{ errorText = "ERR_NOT_RECT_OR_ROTATED_RECT";break;}
+		case -1074396132:
+			{ errorText = "ERR_MASK_NOT_TEMPLATE_SIZE";break;}
+		case -1074396133:
+			{ errorText = "ERR_THREAD_COULD_NOT_INITIALIZE";break;}
+		case -1074396134:
+			{ errorText = "ERR_THREAD_INITIALIZING";break;}
+		case -1074396135:
+			{ errorText = "ERR_INVALID_BUTTON_LABEL";break;}
+		case -1074396136:
+			{ errorText = "ERR_DIRECTX_INVALID_FILTER_QUALITY";break;}
+		case -1074396137:
+			{ errorText = "ERR_DIRECTX_DLL_NOT_FOUND";break;}
+		case -1074396138:
+			{ errorText = "ERR_ROLLBACK_NOT_SUPPORTED";break;}
+		case -1074396139:
+			{ errorText = "ERR_ROLLBACK_RESOURCE_OUT_OF_MEMORY";break;}
+		case -1074396140:
+			{ errorText = "ERR_BARCODE_CODE128_SET";break;}
+		case -1074396141:
+			{ errorText = "ERR_BARCODE_CODE128_FNC";break;}
+		case -1074396142:
+			{ errorText = "ERR_BARCODE_INVALID";break;}
+		case -1074396143:
+			{ errorText = "ERR_BARCODE_TYPE";break;}
+		case -1074396144:
+			{ errorText = "ERR_BARCODE_CODE93_SHIFT";break;}
+		case -1074396145:
+			{ errorText = "ERR_BARCODE_UPCA";break;}
+		case -1074396146:
+			{ errorText = "ERR_BARCODE_MSI";break;}
+		case -1074396147:
+			{ errorText = "ERR_BARCODE_I25";break;}
+		case -1074396148:
+			{ errorText = "ERR_BARCODE_EAN13";break;}
+		case -1074396149:
+			{ errorText = "ERR_BARCODE_EAN8";break;}
+		case -1074396150:
+			{ errorText = "ERR_BARCODE_CODE128";break;}
+		case -1074396151:
+			{ errorText = "ERR_BARCODE_CODE93";break;}
+		case -1074396152:
+			{ errorText = "ERR_BARCODE_CODE39";break;}
+		case -1074396153:
+			{ errorText = "ERR_BARCODE_CODABAR";break;}
+		case -1074396154:
+			{ errorText = "ERR_IMAGE_TOO_SMALL";break;}
+		case -1074396155:
+			{ errorText = "ERR_UNINIT";break;}
+		case -1074396156:
+			{ errorText = "ERR_NEED_FULL_VERSION";break;}
+		case -1074396157:
+			{ errorText = "ERR_UNREGISTERED";break;}
+		case -1074396158:
+			{ errorText = "ERR_MEMORY_ERROR";break;}
+		case -1074396159:
+			{ errorText = "ERR_OUT_OF_MEMORY";break;}
+		case -1074396160:
+			{ errorText = "ERR_SYSTEM_ERROR";break;}
+		case 0:
+			{ errorText = "ERR_SUCCESS";break;}
+		// end National Instruments defined errors
+			
+		// begin BAE defined errors
+		case ERR_VISION_GENERAL_ERROR:
+			{ errorText = "ERR_VISION_GENERAL_ERROR";break;}
+		case ERR_COLOR_NOT_FOUND:
+			{ errorText = "ERR_COLOR_NOT_FOUND";break;}
+		case ERR_PARTICLE_TOO_SMALL:
+			{ errorText = "ERR_PARTICLE_TOO_SMALL";break;}
+		case ERR_CAMERA_FAILURE:
+			{ errorText = "ERR_CAMERA_FAILURE";break;}
+		case ERR_CAMERA_SOCKET_CREATE_FAILED:
+			{ errorText = "ERR_CAMERA_SOCKET_CREATE_FAILED";break;}
+		case ERR_CAMERA_CONNECT_FAILED:
+			{ errorText = "ERR_CAMERA_CONNECT_FAILED";break;}
+		case ERR_CAMERA_STALE_IMAGE:
+			{ errorText = "ERR_CAMERA_STALE_IMAGE";break;}
+		case ERR_CAMERA_NOT_INITIALIZED:
+			{ errorText = "ERR_CAMERA_NOT_INITIALIZED";break;}
+		case ERR_CAMERA_NO_BUFFER_AVAILABLE:
+			{ errorText = "ERR_CAMERA_NO_BUFFER_AVAILABLE";break;}
+		case ERR_CAMERA_HEADER_ERROR:
+			{ errorText = "ERR_CAMERA_HEADER_ERROR";break;}
+		case ERR_CAMERA_BLOCKING_TIMEOUT:
+			{ errorText = "ERR_CAMERA_BLOCKING_TIMEOUT";break;}
+		case ERR_CAMERA_AUTHORIZATION_FAILED:
+			{ errorText = "ERR_CAMERA_AUTHORIZATION_FAILED";break;}
+		case ERR_CAMERA_TASK_SPAWN_FAILED:
+			{ errorText = "ERR_CAMERA_TASK_SPAWN_FAILED";break;}
+		case ERR_CAMERA_TASK_INPUT_OUT_OF_RANGE:
+			{ errorText = "ERR_CAMERA_TASK_INPUT_OUT_OF_RANGE";break;}
+		case ERR_CAMERA_COMMAND_FAILURE:
+			{ errorText = "ERR_CAMERA_COMMAND_FAILURE";break;}
+	}
+	
+	return errorText;
+}
+
+
+
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/HSLImage.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/HSLImage.cpp
new file mode 100644
index 0000000..1a66949
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/HSLImage.cpp
@@ -0,0 +1,28 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "Vision/HSLImage.h"
+
+/**
+ * Create a new image that uses the Hue, Saturation, and Luminance planes.
+ */
+HSLImage::HSLImage() : ColorImage(IMAQ_IMAGE_HSL)
+{
+}
+
+/**
+ * Create a new image by loading a file.
+ * @param fileName The path of the file to load.
+ */
+HSLImage::HSLImage(const char *fileName) : ColorImage(IMAQ_IMAGE_HSL)
+{
+	int success = imaqReadFile(m_imaqImage, fileName, NULL, NULL);
+	wpi_setImaqErrorWithContext(success, "Imaq ReadFile error");
+}
+
+HSLImage::~HSLImage()
+{
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/ImageBase.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/ImageBase.cpp
new file mode 100644
index 0000000..ba549b6
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/ImageBase.cpp
@@ -0,0 +1,73 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "Vision/ImageBase.h"
+#include "nivision.h"
+
+/**
+ * Create a new instance of an ImageBase.
+ * Imagebase is the base of all the other image classes. The constructor
+ * creates any type of image and stores the pointer to it in the class.
+ * @param type The type of image to create
+ */
+ImageBase::ImageBase(ImageType type)
+{
+	m_imaqImage = imaqCreateImage(type, DEFAULT_BORDER_SIZE);
+}
+
+/**
+ * Frees memory associated with an ImageBase.
+ * Destructor frees the imaq image allocated with the class.
+ */
+ImageBase::~ImageBase()
+{
+	if(m_imaqImage)
+		imaqDispose(m_imaqImage);
+}
+
+/**
+ * Writes an image to a file with the given filename.
+ * Write the image to a file in the flash on the cRIO.
+ * @param fileName The name of the file to write
+ */
+void ImageBase::Write(const char *fileName)
+{
+	int success = imaqWriteFile(m_imaqImage, fileName, NULL);
+	wpi_setImaqErrorWithContext(success, "Imaq Image writeFile error");
+}
+
+/**
+ * Gets the height of an image.
+ * @return The height of the image in pixels.
+ */
+int ImageBase::GetHeight()
+{
+	int height;
+	imaqGetImageSize(m_imaqImage, NULL, &height);
+	return height;
+}
+
+/**
+ * Gets the width of an image.
+ * @return The width of the image in pixels.
+ */
+int ImageBase::GetWidth()
+{
+	int width;
+	imaqGetImageSize(m_imaqImage, &width, NULL);
+	return width;
+}
+
+/**
+ * Access the internal IMAQ Image data structure.
+ * 
+ * @return A pointer to the internal IMAQ Image data structure.
+ */
+Image *ImageBase::GetImaqImage()
+{
+	return m_imaqImage;
+}
+
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/MonoImage.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/MonoImage.cpp
new file mode 100644
index 0000000..17efe20
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/MonoImage.cpp
@@ -0,0 +1,55 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "Vision/MonoImage.h"
+#include "nivision.h"
+
+using namespace std;
+
+MonoImage::MonoImage() : ImageBase(IMAQ_IMAGE_U8)
+{
+}
+
+MonoImage::~MonoImage()
+{
+}
+
+/**
+ * Look for ellipses in an image.
+ * Given some input parameters, look for any number of ellipses in an image.
+ * @param ellipseDescriptor Ellipse descriptor
+ * @param curveOptions Curve options
+ * @param shapeDetectionOptions Shape detection options
+ * @param roi Region of Interest
+ * @returns a vector of EllipseMatch structures (0 length vector on no match)
+ */
+vector<EllipseMatch> * MonoImage::DetectEllipses(
+		EllipseDescriptor *ellipseDescriptor, CurveOptions *curveOptions,
+		ShapeDetectionOptions *shapeDetectionOptions, ROI *roi)
+{
+	int numberOfMatches;
+	EllipseMatch *e = imaqDetectEllipses(m_imaqImage, ellipseDescriptor,
+										curveOptions, shapeDetectionOptions, roi, &numberOfMatches);
+	vector<EllipseMatch> *ellipses = new vector<EllipseMatch>;
+	if (e == NULL)
+	{
+		return ellipses;
+	}
+	for (int i = 0; i < numberOfMatches; i++)
+	{
+		ellipses->push_back(e[i]);
+	}
+	imaqDispose(e);
+	return ellipses;
+}
+
+vector<EllipseMatch> * MonoImage::DetectEllipses(
+		EllipseDescriptor *ellipseDescriptor)
+{
+	vector<EllipseMatch> *ellipses = DetectEllipses(ellipseDescriptor, NULL,
+			NULL, NULL);
+	return ellipses;
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/RGBImage.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/RGBImage.cpp
new file mode 100644
index 0000000..a34212e
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/RGBImage.cpp
@@ -0,0 +1,28 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "Vision/RGBImage.h"
+
+/**
+ * Create a new image that uses Red, Green, and Blue planes.
+ */
+RGBImage::RGBImage() : ColorImage(IMAQ_IMAGE_RGB)
+{
+}
+
+/**
+ * Create a new image by loading a file.
+ * @param fileName The path of the file to load.
+ */
+RGBImage::RGBImage(const char *fileName) : ColorImage(IMAQ_IMAGE_RGB)
+{
+	int success = imaqReadFile(m_imaqImage, fileName, NULL, NULL);
+	wpi_setImaqErrorWithContext(success, "Imaq ReadFile error");
+}
+
+RGBImage::~RGBImage()
+{
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/Threshold.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/Threshold.cpp
new file mode 100644
index 0000000..1d81b38
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/Threshold.cpp
@@ -0,0 +1,18 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "Vision/Threshold.h"
+
+Threshold::Threshold(int new_plane1Low, int new_plane1High, int new_plane2Low,
+		int new_plane2High, int new_plane3Low, int new_plane3High)
+{
+	plane1Low = new_plane1Low;
+	plane1High = new_plane1High;
+	plane2Low = new_plane2Low;
+	plane2High = new_plane2High;
+	plane3Low = new_plane3Low;
+	plane3High = new_plane3High;
+}
diff --git a/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/VisionAPI.cpp b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/VisionAPI.cpp
new file mode 100644
index 0000000..c72b321
--- /dev/null
+++ b/aos/externals/allwpilib/wpilibc/wpilibC++Devices/src/Vision/VisionAPI.cpp
@@ -0,0 +1,667 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2014. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include <stdlib.h> 
+#include <stdarg.h> 
+
+#include "Vision/BaeUtilities.h"
+#include "Vision/FrcError.h"
+#include "Vision/VisionAPI.h" 
+
+int VisionAPI_debugFlag = 1;
+#define DPRINTF if(VisionAPI_debugFlag)dprintf
+
+/** @file
+ *    Image Management functions
+ */
+
+/**
+* @brief Create an image object
+* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL, IMAQ_IMAGE_COMPLEX, IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL, IMAQ_IMAGE_RGB_U64          
+* The border size is defaulted to 3 so that convolutional algorithms work at the edges. 
+* When you are finished with the created image, dispose of it by calling frcDispose(). 
+* To get extended error information, call GetLastError().   
+*           
+* @param type Type of image to create
+* @return Image* On success, this function returns the created image. On failure, it returns NULL.
+*/
+Image* frcCreateImage(ImageType type) { return imaqCreateImage(type, DEFAULT_BORDER_SIZE); }
+
+/**
+* @brief Dispose of one object. Supports any object created on the heap.
+* 
+* @param object object to dispose of
+* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
+*/
+int frcDispose(void* object)  { return imaqDispose(object);	}
+/**
+* @brief Dispose of a list of objects. Supports any object created on the heap.
+* 
+* @param functionName The name of the function
+* @param ... A list of pointers to structures that need to be disposed of. 
+* The last pointer in the list should always be set to NULL.
+* 
+* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
+*/
+int frcDispose( const char* functionName, ... ) /* Variable argument list */
+{
+    va_list disposalPtrList;   /* Input argument list */
+    void* disposalPtr;         /* For iteration */
+    int success, returnValue = 1;
+    
+    va_start( disposalPtrList, functionName );  /* start of variable list */
+    disposalPtr = va_arg( disposalPtrList, void* );
+    while( disposalPtr != NULL )     {
+    	success = imaqDispose(disposalPtr);
+        if (!success) {returnValue = 0;}
+        disposalPtr = va_arg( disposalPtrList, void* );
+    }
+    return returnValue;
+}
+
+/**
+* @brief Copy an image object. 
+* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL, IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL.          
+* 
+* @param dest Copy of image. On failure, dest is NULL. Must have already been created using frcCreateImage().
+* When you are finished with the created image, dispose of it by calling frcDispose().
+* @param source Image to copy      
+* 
+* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
+*/
+int frcCopyImage(Image* dest, const Image* source) { return imaqDuplicate(dest, source);  }
+
+/**
+* @brief Crop image without changing the scale. 
+* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL, IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL.
+* 
+* @param dest Modified image
+* @param source Image to crop
+* @param rect region to process, or IMAQ_NO_RECT
+* 
+* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
+*/
+int frcCrop(Image* dest, const Image* source, Rect rect)
+{	
+	return imaqScale(dest, source, 1, 1, IMAQ_SCALE_LARGER, rect);
+}
+
+
+/**
+* @brief Scales the entire image larger or smaller. 
+* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL, IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL.
+*     
+* @param dest Modified image
+* @param source Image to scale
+* @param xScale the horizontal reduction ratio
+* @param yScale the vertical reduction ratio 
+* @param scaleMode IMAQ_SCALE_LARGER or IMAQ_SCALE_SMALLER  
+* 
+* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
+*/
+int frcScale(Image* dest, const Image* source, int xScale, int yScale, ScalingMode scaleMode)
+{	
+	Rect rect = IMAQ_NO_RECT;
+	return imaqScale(dest, source, xScale, yScale, scaleMode, rect);	
+}
+  
+/**
+ * @brief Creates image object from the information in a file. The file can be in one of the following formats: 
+ * PNG, JPEG, JPEG2000, TIFF, AIPD, or BMP. 
+ * Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL, IMAQ_IMAGE_COMPLEX, IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL, IMAQ_IMAGE_RGB_U64.
+ * 
+ * @param image Image read in
+ * @param fileName File to read. Cannot be NULL
+ * 
+ * @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
+ */
+ int frcReadImage(Image* image, const char* fileName)
+ {
+	 return imaqReadFile(image, fileName, NULL, NULL);
+ }
+
+
+ /**
+ * @brief Write image to a file. 
+ * Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL, IMAQ_IMAGE_COMPLEX, IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL, IMAQ_IMAGE_RGB_U64.
+ * 
+ * The file type is determined by the extension, as follows:
+ *
+ *		Extension 					File Type 
+ *		aipd or .apd 				AIPD 
+ *		.bmp 						BMP 
+ *		.jpg or .jpeg 				JPEG 
+ *		.jp2 						JPEG2000 
+ *		.png 						PNG 
+ *		.tif or .tiff 				TIFF 
+ * 
+ * 
+ *The following are the supported image types for each file type:
+ *
+ *		File Types 					Image Types 
+ *		AIPD 						all image types 
+ *		BMP, JPEG 					8-bit, RGB 
+ *		PNG, TIFF, JPEG2000 		8-bit, 16-bit, RGB, RGBU64 		
+ * 			    
+ * @param image Image to write
+ * @param fileName File to read. Cannot be NULL. The extension determines the file format that is written.
+ * 
+ * @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
+ */
+int frcWriteImage(const Image* image, const char* fileName)
+{	
+	RGBValue* colorTable = NULL;
+	return imaqWriteFile(image, fileName, colorTable);
+}
+
+
+/*  Measure Intensity functions */
+
+/**
+* @brief Measures the pixel intensities in a rectangle of an image. 
+* Outputs intensity based statistics about an image such as Max, Min, Mean and Std Dev of pixel value. 
+* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL.
+*
+*  Parameter Discussion	: 
+*		Relevant parameters of the HistogramReport include:
+* 			min, max, mean and stdDev      
+*		min/max —Setting both min and max to 0 causes the function to set min to 0 
+* 			and the max to 255 for 8-bit images and to the actual minimum value and
+* 			maximum value of the image for all other image types.
+*		max—Setting both min and max to 0 causes the function to set max to 255 
+* 			for 8-bit images and to the actual maximum value of the image for 
+* 			all other image types.
+*
+* @param image Image whose histogram the function calculates.
+* @param numClasses The number of classes into which the function separates the pixels. 
+* Determines the number of elements in the histogram array returned
+* @param min The minimum pixel value to consider for the histogram. 
+* The function does not count pixels with values less than min.
+* @param max The maximum pixel value to consider for the histogram. 
+* The function does not count pixels with values greater than max.
+* @param rect Region of interest in the image. If not included, the entire image is used. 
+* @return On success, this function returns a report describing the pixel value classification.    
+* When you are finished with the report, dispose of it by calling frcDispose(). 
+* On failure, this function returns NULL. To get extended error information, call GetLastError().            
+* 
+*/
+HistogramReport* frcHistogram(const Image* image, int numClasses, float min, float max)
+{
+	Rect rect = IMAQ_NO_RECT;
+	return frcHistogram(image, numClasses, min, max, rect);		
+}
+HistogramReport* frcHistogram(const Image* image, int numClasses, float min, float max, Rect rect)
+{
+	int success; 
+	int fillValue = 1;
+	
+	/* create the region of interest */
+	ROI* pRoi = imaqCreateROI();
+	success = imaqAddRectContour(pRoi, rect); 
+	if ( !success )	{ GetLastVisionError(); return NULL; }	
+
+	/* make a mask from the ROI */
+	Image* pMask = frcCreateImage(IMAQ_IMAGE_U8);
+	success = imaqROIToMask(pMask, pRoi, fillValue, NULL, NULL);
+	if ( !success )	{ 
+		GetLastVisionError(); 
+		frcDispose(__FUNCTION__, pRoi, NULL); 
+		return NULL; 
+	}	
+	
+	/* get a histogram report */
+	HistogramReport* pHr = NULL;
+	pHr = imaqHistogram(image, numClasses, min, max, pMask); 
+	
+	/* clean up */
+	frcDispose(__FUNCTION__, pRoi, pMask, NULL); 
+	
+	return pHr;
+}
+
+/**
+* @brief Calculates the histogram, or pixel distribution, of a color image. 
+* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL.
+*            
+* @param image Image whose histogram the function calculates.
+* @param numClasses The number of classes into which the function separates the pixels. 
+* Determines the number of elements in the histogram array returned
+* @param mode The color space in which to perform the histogram. Possible values include IMAQ_RGB and IMAQ_HSL. 
+* @param mask An optional mask image. This image must be an IMAQ_IMAGE_U8 image. 
+* The function calculates the histogram using only those pixels in the image whose 
+* corresponding pixels in the mask are non-zero. Set this parameter to NULL to calculate 
+* the histogram of the entire image, or use the simplified call.
+* 
+* @return On success, this function returns a report describing the classification  
+* of each plane in a HistogramReport. 
+* When you are finished with the report, dispose of it by calling frcDispose(). 
+* On failure, this function returns NULL.  
+* To get extended error information, call imaqGetLastError(). 
+*/
+ColorHistogramReport* frcColorHistogram(const Image* image, int numClasses, ColorMode mode)
+{	
+	return frcColorHistogram(image, numClasses, mode, NULL);
+}
+
+ColorHistogramReport* frcColorHistogram(const Image* image, int numClasses, ColorMode mode, Image* mask)
+{
+	return imaqColorHistogram2((Image*)image, numClasses, mode, NULL, mask);
+}
+
+
+/**
+* @brief Measures the pixel intensities in a rectangle of an image. 
+* Outputs intensity based statistics about an image such as Max, Min, Mean and Std Dev of pixel value. 
+* Supports IMAQ_IMAGE_U8 (grayscale) IMAQ_IMAGE_RGB (color) IMAQ_IMAGE_HSL (color-HSL).
+* 
+* @param image The image whose pixel value the function queries
+* @param pixel The coordinates of the pixel that the function queries
+* @param value On return, the value of the specified image pixel. This parameter cannot be NULL.
+* This data structure contains either grayscale, RGB, HSL, Complex or RGBU64Value depending on the type of image.
+* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
+*/
+int frcGetPixelValue(const Image* image, Point pixel, PixelValue* value)
+{	
+	return imaqGetPixel(image, pixel, value);
+}
+
+
+/*   Particle Analysis functions */
+
+/**
+* @brief Filters particles out of an image based on their measurements. 
+* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL.
+* 
+* @param dest The destination image. If dest is used, it must be the same size as the Source image. It will contain only the filtered particles.
+* @param source The image containing the particles to filter. 
+* @param criteria An array of criteria to apply to the particles in the source image. This array cannot be NULL.
+* See the NIVisionCVI.chm help file for definitions of criteria. 
+* @param criteriaCount The number of elements in the criteria array.
+* @param options Binary filter options, including rejectMatches, rejectBorder, and connectivity8.
+* @param rect Area of image to filter. If omitted, the default is entire image.
+* @param numParticles On return, the number of particles left in the image
+* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
+*/
+int frcParticleFilter(Image* dest, Image* source, const ParticleFilterCriteria2* criteria, 
+		int criteriaCount, const ParticleFilterOptions* options, int* numParticles)
+{
+	Rect rect = IMAQ_NO_RECT;
+	return frcParticleFilter(dest, source, criteria, criteriaCount, options, rect, numParticles);
+}
+
+int frcParticleFilter(Image* dest, Image* source, const ParticleFilterCriteria2* criteria, 
+		int criteriaCount, const ParticleFilterOptions* options, Rect rect, int* numParticles)
+{
+	ROI* roi = imaqCreateROI();
+	imaqAddRectContour(roi, rect);
+	return imaqParticleFilter3(dest, source, criteria, criteriaCount, options, roi, numParticles);
+}
+
+
+/**
+* @brief Performs morphological transformations on binary images. 
+* Supports IMAQ_IMAGE_U8. 
+*
+* @param dest The destination image. The border size of the destination image is not important.
+* @param source The image on which the function performs the morphological operations. The calculation 
+* modifies the border of the source image. The border must be at least half as large as the larger 
+* dimension  of the structuring element.  The connected source image for a morphological transformation 
+* must have been created with a border capable of supporting the size of the structuring element. 
+* A 3 by 3 structuring element requires a minimal border of 1, a 5 by 5 structuring element requires a minimal border of 2, and so on.
+* @param method The morphological transform to apply. 
+* @param structuringElement The structuring element used in the operation. Omit this parameter if you do not want a custom structuring element. 
+* @return On success: 1. On failure: 0. To get extended error information, call GetLastError(). 
+*/
+int frcMorphology(Image* dest, Image* source, MorphologyMethod method)
+{	
+	return imaqMorphology(dest, source, method, NULL);
+}
+
+int frcMorphology(Image* dest, Image* source, MorphologyMethod method, const StructuringElement* structuringElement)
+{	
+	return imaqMorphology(dest, source, method, structuringElement); 
+}
+
+/**
+* @brief Eliminates particles that touch the border of the image. 
+* Supports IMAQ_IMAGE_U8.
+*
+* @param dest The destination image.
+* @param source The source image. If the image has a border, the function sets all border pixel values to 0.
+* @param connectivity8 specifies the type of connectivity used by the algorithm for particle detection. 
+* The connectivity mode directly determines whether an adjacent pixel belongs to the same particle or a 
+* different particle. Set to TRUE to use connectivity-8 to determine whether particles are touching 
+* Set to FALSE to use connectivity-4 to determine whether particles are touching. 
+* The default setting for the simplified call is TRUE
+* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
+*/
+int frcRejectBorder(Image* dest, Image* source)
+{	return imaqRejectBorder(dest, source, TRUE); }
+
+int frcRejectBorder(Image* dest, Image* source, int connectivity8)
+{	
+	return imaqRejectBorder(dest, source, connectivity8);
+}
+
+
+/**
+* @brief Counts the number of particles in a binary image. 
+* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL.
+* @param image binary (thresholded) image 	
+* @param numParticles On return, the number of particles.
+* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().    
+*/
+int frcCountParticles(Image* image, int* numParticles)				
+{	
+	return imaqCountParticles(image, 1, numParticles);
+}
+
+
+/**
+* @brief Conduct measurements for a single particle in an images. 
+* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL.
+* 
+* @param image image with the particle to analyze. This function modifies the source image. 
+* If you need the original image, create a copy of the image using frcCopy() before using this function.
+* @param particleNumber The number of the particle to get information on
+* @param par on return, a particle analysis report containing information about the particle. This structure must be created by the caller.
+* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
+*/
+int frcParticleAnalysis(Image* image, int particleNumber, ParticleAnalysisReport* par)				
+{
+	int success = 0;
+
+	/* image information */
+	int height, width;
+	if ( ! imaqGetImageSize(image, &width, &height) ) 	{ return success; }	
+	par->imageWidth = width;	
+	par->imageHeight = height;	
+	par->particleIndex = particleNumber;		
+
+	/* center of mass point of the largest particle	*/
+	double returnDouble;
+	success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_CENTER_OF_MASS_X, &returnDouble);
+	if ( !success )	{ return success; }
+	par->center_mass_x = (int)returnDouble;						// pixel	
+
+	success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_CENTER_OF_MASS_Y, &returnDouble);	
+	if ( !success )	{ return success; }
+	par->center_mass_y = (int)returnDouble;						// pixel		
+	
+	/* particle size statistics */ 
+	success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_AREA, &returnDouble);	
+	if ( !success )	{ return success; }
+	par->particleArea = returnDouble;	
+	
+	success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_BOUNDING_RECT_TOP, &returnDouble);	
+	if ( !success )	{ return success; }
+	par->boundingRect.top = (int)returnDouble;
+	
+	success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_BOUNDING_RECT_LEFT, &returnDouble);	
+	if ( !success )	{ return success; }
+	par->boundingRect.left = (int)returnDouble;
+	
+	success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_BOUNDING_RECT_HEIGHT, &returnDouble);	
+	if ( !success )	{ return success; }
+	par->boundingRect.height = (int)returnDouble;	
+
+	success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_BOUNDING_RECT_WIDTH, &returnDouble);	
+	if ( !success )	{ return success; }
+	par->boundingRect.width = (int)returnDouble;	
+	
+	/* particle quality statistics */ 
+	success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_AREA_BY_IMAGE_AREA, &returnDouble);	
+	if ( !success )	{ return success; }
+	par->particleToImagePercent = returnDouble;
+
+	success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_AREA_BY_PARTICLE_AND_HOLES_AREA, &returnDouble);	
+	if ( !success )	{ return success; }
+	par->particleQuality = returnDouble;
+		
+	/* normalized position (-1 to 1) */
+	par->center_mass_x_normalized = RangeToNormalized(par->center_mass_x, width);
+	par->center_mass_y_normalized = RangeToNormalized(par->center_mass_y, height);	
+	
+	return success;
+}
+
+
+/*   Image Enhancement functions */
+
+/**
+* @brief Improves contrast on a grayscale image. 
+* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16.
+* @param dest The destination image.
+* @param source The image to equalize 
+* @param min the smallest value used for processing. After processing, all pixel values that are less than or equal to the Minimum in the original image are set to 0 for an 8-bit image. In 16-bit and floating-point images, these pixel values are set to the smallest pixel value found in the original image. 
+* @param max the largest value used for processing. After processing, all pixel values that are greater than or equal to the Maximum in the original image are set to 255 for an 8-bit image. In 16-bit and floating-point images, these pixel values are set to the largest pixel value found in the original image. 
+* @param mask an 8-bit image that specifies the region of the small image that will be copied. Only those pixels in the Image Src (Small) image that correspond to an equivalent non-zero pixel in the mask image are copied. All other pixels keep their original values. The entire image is processed if Image Mask is NULL or this parameter is omitted.
+* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
+*
+*  option defaults:
+*       searchRect = IMAQ_NO_RECT
+* 		minMatchScore = DEFAULT_MINMAX_SCORE (800)  
+*/
+int frcEqualize(Image* dest, const Image* source, float min, float max)
+{	return frcEqualize(dest, source, min, max, NULL);  }
+
+int frcEqualize(Image* dest, const Image* source, float min, float max, const Image* mask)
+{
+	return imaqEqualize(dest, source, min, max, mask);
+}
+
+/**
+* @brief Improves contrast on a color image. 
+* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL
+* 
+* option defaults: colorEqualization = TRUE to equalize all three planes of the image         
+* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().    
+* @param dest The destination image.
+* @param source The image to equalize 
+* @param colorEqualization Set this parameter to TRUE to equalize all three planes of the image (the default). Set this parameter to FALSE to equalize only the luminance plane.
+*/
+int frcColorEqualize(Image* dest, const Image* source)
+{
+	return imaqColorEqualize(dest, source, TRUE);
+}
+
+int frcColorEqualize(Image* dest, const Image* source, int colorEqualization)
+{
+	return imaqColorEqualize(dest, source, TRUE);
+}
+
+/*   Image Conversion functions */
+
+/**
+* @brief Automatically thresholds a grayscale image into a binary image for Particle Analysis based on a smart threshold. 
+* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_I16
+* @param dest The destination image.
+* @param source The image to threshold 
+* @param windowWidth The width of the rectangular window around the pixel on which the function
+*  performs the local threshold. This number must be at least 3 and cannot be larger than the width of source
+* @param windowHeight The height of the rectangular window around the pixel on which the function 
+* performs the local threshold. This number must be at least 3 and cannot be larger than the height of source
+* @param method Specifies the local thresholding method the function uses. Value can be IMAQ_NIBLACK 
+* (which computes thresholds for each pixel based on its local statistics using the Niblack local thresholding
+* algorithm.), or IMAQ_BACKGROUND_CORRECTION (which does background correction first to eliminate non-uniform 
+* lighting effects, then performs thresholding using the Otsu thresholding algorithm)
+* @param deviationWeight Specifies the k constant used in the Niblack local thresholding algorithm, which 
+* determines the weight applied to the variance calculation. Valid k constants range from 0 to 1. Setting 
+* this value to 0 will increase the performance of the function because the function will not calculate the 
+* variance for any of the pixels. The function ignores this value if method is not set to IMAQ_NIBLACK
+* @param type Specifies the type of objects for which you want to look. Values can be IMAQ_BRIGHT_OBJECTS 
+* or IMAQ_DARK_OBJECTS.
+* @param replaceValue Specifies the replacement value the function uses for the pixels of the kept objects 
+* in the destination image.
+* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
+*/
+int frcSmartThreshold(Image* dest, const Image* source, 
+		unsigned int windowWidth, unsigned int windowHeight, LocalThresholdMethod method, 
+		double deviationWeight, ObjectType type)
+{
+	float replaceValue = 1.0;
+	return imaqLocalThreshold(dest, source, windowWidth, windowHeight, method, 
+			deviationWeight, type, replaceValue);
+}
+
+int frcSmartThreshold(Image* dest, const Image* source, 
+		unsigned int windowWidth, unsigned int windowHeight, LocalThresholdMethod method, 
+		double deviationWeight, ObjectType type, float replaceValue)
+{
+	return imaqLocalThreshold(dest, source, windowWidth, windowHeight, method, 
+			deviationWeight, type, replaceValue);
+}
+
+/**
+* @brief Converts a grayscale image to a binary image for Particle Analysis based on a fixed threshold. 
+* The function sets pixels values outside of the given range to 0. The function sets pixel values 
+* within the range to a given value or leaves the values unchanged. 
+* Use the simplified call to leave pixel values unchanged.
+* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_I16.
+* 
+* @param dest The destination image.
+* @param source The image to threshold 
+* @param rangeMin The lower boundary of the range of pixel values to keep
+* @param rangeMax The upper boundary of the range of pixel values to keep.
+* 
+* @return int - error code: 0 = error. To get extended error information, call GetLastError().
+*/
+int frcSimpleThreshold(Image* dest, const Image* source, float rangeMin, float rangeMax)
+{
+	int newValue = 255;
+	return frcSimpleThreshold(dest, source, rangeMin, rangeMax, newValue);
+}
+
+/**
+* @brief Converts a grayscale image to a binary image for Particle Analysis based on a fixed threshold. 
+* The function sets pixels values outside of the given range to 0. The function sets 
+* pixel values within the range to the given value. 
+* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_I16.
+* 
+* @param dest The destination image.
+* @param source The image to threshold 
+* @param rangeMin The lower boundary of the range of pixel values to keep
+* @param rangeMax The upper boundary of the range of pixel values to keep.
+* @param newValue The replacement value for pixels within the range. Use the simplified call to leave the pixel values unchanged 
+* 
+* @return int - error code: 0 = error. To get extended error information, call GetLastError().
+*/
+int frcSimpleThreshold(Image* dest, const Image* source, float rangeMin, float rangeMax, float newValue)
+{
+	int useNewValue = TRUE;
+	return imaqThreshold(dest, source, rangeMin, rangeMax, useNewValue, newValue);
+}
+
+/**
+* @brief Applies a threshold to the Red, Green, and Blue values of a RGB image or the Hue, 
+* Saturation, Luminance values for a HSL image. 
+* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL.
+* This simpler version filters based on a hue range in the HSL mode.
+* 
+* @param dest The destination image. This must be a IMAQ_IMAGE_U8 image.
+* @param source The image to threshold 
+* @param mode The color space to perform the threshold in. valid values are: IMAQ_RGB, IMAQ_HSL.
+* @param plane1Range The selection range for the first plane of the image. Set this parameter to NULL to use a selection range from 0 to 255.
+* @param plane2Range The selection range for the second plane of the image. Set this parameter to NULL to use a selection range from 0 to 255.
+* @param plane3Range The selection range for the third plane of the image. Set this parameter to NULL to use a selection range from 0 to 255.
+* 
+* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
+* */
+int frcColorThreshold(Image* dest, const Image* source, ColorMode mode, 
+		const Range* plane1Range, const Range* plane2Range, const Range* plane3Range)
+{
+	int replaceValue = 1;
+	return imaqColorThreshold(dest, source, replaceValue, mode, plane1Range, plane2Range, plane3Range);
+}
+
+/**
+* @brief Applies a threshold to the Red, Green, and Blue values of a RGB image or the Hue, 
+* Saturation, Luminance values for a HSL image. 
+* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL.
+* The simpler version filters based on a hue range in the HSL mode.
+* 
+* @param dest The destination image. This must be a IMAQ_IMAGE_U8 image.
+* @param source The image to threshold 
+* @param replaceValue Value to assign to selected pixels. Defaults to 1 if simplified call is used.
+* @param mode The color space to perform the threshold in. valid values are: IMAQ_RGB, IMAQ_HSL.
+* @param plane1Range The selection range for the first plane of the image. Set this parameter to NULL to use a selection range from 0 to 255.
+* @param plane2Range The selection range for the second plane of the image. Set this parameter to NULL to use a selection range from 0 to 255.
+* @param plane3Range The selection range for the third plane of the image. Set this parameter to NULL to use a selection range from 0 to 255.
+* 
+* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
+*/
+int frcColorThreshold(Image* dest, const Image* source, int replaceValue, ColorMode mode, 
+		const Range* plane1Range, const Range* plane2Range, const Range* plane3Range)
+{	return imaqColorThreshold(dest, source, replaceValue, mode, plane1Range, plane2Range, plane3Range);}
+
+
+/**
+* @brief A simpler version of ColorThreshold that thresholds hue range in the HSL mode. Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL.
+* @param dest The destination image.
+* @param source The image to threshold 
+* @param hueRange The selection range for the hue (color). 
+* @param minSaturation The minimum saturation value (1-255).  If not used, DEFAULT_SATURATION_THRESHOLD is the default.
+* 
+* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().
+*/
+int frcHueThreshold(Image* dest, const Image* source, const Range* hueRange)
+{ return frcHueThreshold(dest, source, hueRange, DEFAULT_SATURATION_THRESHOLD); }
+
+int frcHueThreshold(Image* dest, const Image* source, const Range* hueRange, int minSaturation)
+{
+	// assume HSL mode
+	ColorMode mode = IMAQ_HSL;  
+	// Set saturation 100 - 255
+	Range satRange;  satRange.minValue = minSaturation; satRange.maxValue = 255;
+	// Set luminance 100 - 255
+	Range lumRange;  lumRange.minValue = 100; lumRange.maxValue = 255;
+	// Replace pixels with 1 if pass threshold filter
+	int replaceValue = 1;
+	return imaqColorThreshold(dest, source, replaceValue, mode, hueRange, &satRange, &lumRange);
+}
+
+/**
+* @brief Extracts the Red, Green, Blue, or Hue, Saturation or Luminance information from a color image. 
+* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL, IMAQ_IMAGE_RGB_U64.
+* 
+* @param image The source image that the function extracts the planes from.
+* @param mode The color space that the function extracts the planes from. Valid values are IMAQ_RGB, IMAQ_HSL, IMAQ_HSV, IMAQ_HSI.
+* @param plane1 On return, the first extracted plane. Set this parameter to NULL if you do not need this information. RGB-Red, HSL/HSV/HSI-Hue.
+* @param plane2 On return, the second extracted plane. Set this parameter to NULL if you do not need this information. RGB-Green, HSL/HSV/HSI-Saturation.
+* @param plane3 On return, the third extracted plane. Set this parameter to NULL if you do not need this information. RGB-Blue, HSL-Luminance, HSV-Value, HSI-Intensity.
+*
+* @return error code: 0 = error. To get extended error information, call GetLastError().
+*/
+int frcExtractColorPlanes(const Image* image, ColorMode mode, 
+		Image* plane1, Image* plane2, Image* plane3)
+{	return imaqExtractColorPlanes(image, mode, plane1, plane2, plane3); }
+
+/**
+* @brief Extracts the Hue information from a color image. Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL, IMAQ_IMAGE_RGB_U64 
+* 
+* @param image The source image that the function extracts the plane from.
+* @param huePlane On return, the extracted hue plane. 
+* @param minSaturation the minimum saturation level required 0-255 (try 50)  
+*          
+* @return On success: 1. On failure: 0. To get extended error information, call GetLastError().     
+*/
+int frcExtractHuePlane(const Image* image, Image* huePlane)
+{
+	return frcExtractHuePlane(image, huePlane, DEFAULT_SATURATION_THRESHOLD);
+}
+
+int frcExtractHuePlane(const Image* image, Image* huePlane, int minSaturation)
+{
+	return frcExtractColorPlanes(image, IMAQ_HSL, huePlane, NULL, NULL);
+}
+
+
+
+
+
+
+
+
diff --git a/aos/externals/forwpilib/README b/aos/externals/forwpilib/README
new file mode 100644
index 0000000..faa1a78
--- /dev/null
+++ b/aos/externals/forwpilib/README
@@ -0,0 +1,4 @@
+This directory contains files that we plan to eventually push to upstream
+WPILib but haven't yet.
+
+The canonical location for dma.* is robotics.mvla.net:/www/https/git/frc971/jerry/dma.git.
diff --git a/aos/externals/forwpilib/dma.cc b/aos/externals/forwpilib/dma.cc
new file mode 100644
index 0000000..148ff29
--- /dev/null
+++ b/aos/externals/forwpilib/dma.cc
@@ -0,0 +1,458 @@
+#include "dma.h"
+
+#include <string.h>
+
+#include <algorithm>
+#include <type_traits>
+
+#include "DigitalSource.h"
+#include "AnalogInput.h"
+#include "Encoder.h"
+
+
+// Interface to the roboRIO FPGA's DMA features.
+
+// Like tEncoder::tOutput with the bitfields reversed.
+typedef union {
+  struct {
+    unsigned Direction: 1;
+    signed Value: 31;
+  };
+  struct {
+    unsigned value: 32;
+  };
+} t1Output;
+
+static const uint32_t kNumHeaders = 10;
+
+static constexpr ssize_t kChannelSize[18] = {2, 2, 4, 4, 2, 2, 4, 4, 3,
+                                             3, 2, 1, 4, 4, 4, 4, 4, 4};
+
+enum DMAOffsetConstants {
+  kEnable_AI0_Low = 0,
+  kEnable_AI0_High = 1,
+  kEnable_AIAveraged0_Low = 2,
+  kEnable_AIAveraged0_High = 3,
+  kEnable_AI1_Low = 4,
+  kEnable_AI1_High = 5,
+  kEnable_AIAveraged1_Low = 6,
+  kEnable_AIAveraged1_High = 7,
+  kEnable_Accumulator0 = 8,
+  kEnable_Accumulator1 = 9,
+  kEnable_DI = 10,
+  kEnable_AnalogTriggers = 11,
+  kEnable_Counters_Low = 12,
+  kEnable_Counters_High = 13,
+  kEnable_CounterTimers_Low = 14,
+  kEnable_CounterTimers_High = 15,
+  kEnable_Encoders = 16,
+  kEnable_EncoderTimers = 17,
+};
+
+DMA::DMA() {
+  tRioStatusCode status = 0;
+  tdma_config_ = tDMA::create(&status);
+  tdma_config_->writeConfig_ExternalClock(false, &status);
+  wpi_setErrorWithContext(status, getHALErrorMessage(status));
+  NiFpga_WriteU32(0x10000, 0x1832c, 0x0);
+  if (status != 0) {
+    return;
+  }
+  SetRate(1);
+  SetPause(false);
+}
+
+DMA::~DMA() {
+  tRioStatusCode status = 0;
+
+  manager_->stop(&status);
+  delete tdma_config_;
+}
+
+void DMA::SetPause(bool pause) {
+  tRioStatusCode status = 0;
+  tdma_config_->writeConfig_Pause(pause, &status);
+  wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+void DMA::SetRate(uint32_t cycles) {
+  if (cycles < 1) {
+    cycles = 1;
+  }
+  tRioStatusCode status = 0;
+  tdma_config_->writeRate(cycles, &status);
+  wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+void DMA::Add(Encoder *encoder) {
+  tRioStatusCode status = 0;
+
+  if (manager_) {
+    wpi_setErrorWithContext(NiFpga_Status_InvalidParameter,
+        "DMA::Add() only works before DMA::Start()");
+    return;
+  }
+  if (encoder->GetFPGAIndex() >= 4) {
+    wpi_setErrorWithContext(
+        NiFpga_Status_InvalidParameter,
+        "FPGA encoder index is not in the 4 that get logged.");
+  }
+
+  // TODO(austin): Encoder uses a Counter for 1x or 2x; quad for 4x...
+  tdma_config_->writeConfig_Enable_Encoders(true, &status);
+  wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+void DMA::Add(DigitalSource * /*input*/) {
+  tRioStatusCode status = 0;
+
+  if (manager_) {
+    wpi_setErrorWithContext(NiFpga_Status_InvalidParameter,
+        "DMA::Add() only works before DMA::Start()");
+    return;
+  }
+
+  tdma_config_->writeConfig_Enable_DI(true, &status);
+  wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+void DMA::Add(AnalogInput *input) {
+  tRioStatusCode status = 0;
+
+  if (manager_) {
+    wpi_setErrorWithContext(NiFpga_Status_InvalidParameter,
+        "DMA::Add() only works before DMA::Start()");
+    return;
+  }
+
+  if (input->GetChannel() <= 3) {
+    tdma_config_->writeConfig_Enable_AI0_Low(true, &status);
+  } else {
+    tdma_config_->writeConfig_Enable_AI0_High(true, &status);
+  }
+  wpi_setErrorWithContext(status, getHALErrorMessage(status));
+}
+
+void DMA::SetExternalTrigger(DigitalSource *input, bool rising, bool falling) {
+  tRioStatusCode status = 0;
+
+  if (manager_) {
+    wpi_setErrorWithContext(NiFpga_Status_InvalidParameter,
+        "DMA::SetExternalTrigger() only works before DMA::Start()");
+    return;
+  }
+
+  auto index =
+      ::std::find(trigger_channels_.begin(), trigger_channels_.end(), false);
+  if (index == trigger_channels_.end()) {
+    wpi_setErrorWithContext(NiFpga_Status_InvalidParameter,
+                            "DMA: No channels left");
+    return;
+  }
+  *index = true;
+
+  const int channel_index = index - trigger_channels_.begin();
+  /*
+  printf(
+      "Allocating trigger on index %d, routing module %d, routing channel %d, "
+      "is analog %d\n",
+      channel_index, input->GetModuleForRouting(),
+      input->GetChannelForRouting(), input->GetAnalogTriggerForRouting());
+  */
+
+  const bool is_external_clock =
+      tdma_config_->readConfig_ExternalClock(&status);
+  if (status == 0) {
+    if (!is_external_clock) {
+      tdma_config_->writeConfig_ExternalClock(true, &status);
+      wpi_setErrorWithContext(status, getHALErrorMessage(status));
+      if (status != 0) {
+        return;
+      }
+    }
+  } else {
+    wpi_setErrorWithContext(status, getHALErrorMessage(status));
+    return;
+  }
+
+  nFPGA::nFRC_2015_1_0_A::tDMA::tExternalTriggers new_trigger;
+
+  new_trigger.FallingEdge = falling;
+  new_trigger.RisingEdge = rising;
+  new_trigger.ExternalClockSource_AnalogTrigger =
+      input->GetAnalogTriggerForRouting();
+  new_trigger.ExternalClockSource_AnalogTrigger = false;
+  new_trigger.ExternalClockSource_Module = input->GetModuleForRouting();
+  new_trigger.ExternalClockSource_Channel = input->GetChannelForRouting();
+
+  // Configures the trigger to be external, not off the FPGA clock.
+  /*
+  tdma_config_->writeExternalTriggers(channel_index, new_trigger, &status);
+  wpi_setErrorWithContext(status, getHALErrorMessage(status));
+  */
+
+  uint32_t current_triggers;
+  tRioStatusCode register_status = NiFpga_ReadU32(0x10000, 0x1832c, &current_triggers);
+  if (register_status != 0) {
+    wpi_setErrorWithContext(register_status, getHALErrorMessage(status));
+    return;
+  }
+  current_triggers = (current_triggers & ~(0xff << (channel_index * 8))) |
+                     (new_trigger.value << (channel_index * 8));
+  register_status = NiFpga_WriteU32(0x10000, 0x1832c, current_triggers);
+  if (register_status != 0) {
+    wpi_setErrorWithContext(register_status, getHALErrorMessage(status));
+    return;
+  }
+}
+
+DMA::ReadStatus DMA::Read(DMASample *sample, uint32_t timeout_ms,
+                          size_t *remaining_out) {
+  tRioStatusCode status = 0;
+  size_t remainingBytes = 0;
+  *remaining_out = 0;
+
+  if (!manager_.get()) {
+    wpi_setErrorWithContext(NiFpga_Status_InvalidParameter,
+        "DMA::Read() only works after DMA::Start()");
+    return STATUS_ERROR;
+  }
+
+  sample->dma_ = this;
+  // memset(&sample->read_buffer_, 0, sizeof(sample->read_buffer_));
+  manager_->read(sample->read_buffer_, capture_size_, timeout_ms,
+                 &remainingBytes, &status);
+
+  if (0) { // DEBUG
+    printf("buf[] = ");
+    for (size_t i = 0;
+         i < sizeof(sample->read_buffer_) / sizeof(sample->read_buffer_[0]);
+         ++i) {
+      if (i != 0) {
+        printf(" ");
+      }
+      printf("0x%.8x", sample->read_buffer_[i]);
+    }
+    printf("\n");
+  }
+
+  // TODO(jerry): Do this only if status == 0?
+  *remaining_out = remainingBytes / capture_size_;
+
+  if (0) { // DEBUG
+    printf("Remaining samples = %d\n", *remaining_out);
+  }
+
+  // TODO(austin): Check that *remainingBytes % capture_size_ == 0 and deal
+  // with it if it isn't.  Probably meant that we overflowed?
+  if (status == 0) {
+    return STATUS_OK;
+  } else if (status == NiFpga_Status_FifoTimeout) {
+    return STATUS_TIMEOUT;
+  } else {
+    wpi_setErrorWithContext(status, getHALErrorMessage(status));
+    return STATUS_ERROR;
+  }
+}
+
+const char *DMA::NameOfReadStatus(ReadStatus s) {
+  switch (s) {
+    case STATUS_OK:      return "OK";
+    case STATUS_TIMEOUT: return "TIMEOUT";
+    case STATUS_ERROR:   return "ERROR";
+    default:             return "(bad ReadStatus code)";
+  }
+}
+
+void DMA::Start(size_t queue_depth) {
+  tRioStatusCode status = 0;
+  tconfig_ = tdma_config_->readConfig(&status);
+  wpi_setErrorWithContext(status, getHALErrorMessage(status));
+  if (status != 0) {
+    return;
+  }
+
+  {
+    size_t accum_size = 0;
+#define SET_SIZE(bit)                      \
+  if (tconfig_.bit) {                      \
+    channel_offsets_[k##bit] = accum_size; \
+    accum_size += kChannelSize[k##bit];    \
+  } else {                                 \
+    channel_offsets_[k##bit] = -1;         \
+  }
+
+    SET_SIZE(Enable_AI0_Low);
+    SET_SIZE(Enable_AI0_High);
+    SET_SIZE(Enable_AIAveraged0_Low);
+    SET_SIZE(Enable_AIAveraged0_High);
+    SET_SIZE(Enable_AI1_Low);
+    SET_SIZE(Enable_AI1_High);
+    SET_SIZE(Enable_AIAveraged1_Low);
+    SET_SIZE(Enable_AIAveraged1_High);
+    SET_SIZE(Enable_Accumulator0);
+    SET_SIZE(Enable_Accumulator1);
+    SET_SIZE(Enable_DI);
+    SET_SIZE(Enable_AnalogTriggers);
+    SET_SIZE(Enable_Counters_Low);
+    SET_SIZE(Enable_Counters_High);
+    SET_SIZE(Enable_CounterTimers_Low);
+    SET_SIZE(Enable_CounterTimers_High);
+    SET_SIZE(Enable_Encoders);
+    SET_SIZE(Enable_EncoderTimers);
+#undef SET_SIZE
+    capture_size_ = accum_size + 1;
+  }
+
+  manager_.reset(
+      new nFPGA::tDMAManager(0, queue_depth * capture_size_, &status));
+
+  if (0) {
+    for (int i = 0; i < 4; ++i) {
+      tRioStatusCode status = 0;
+      auto x = tdma_config_->readExternalTriggers(i, &status);
+      printf(
+          "index %d, FallingEdge: %d, RisingEdge: %d, "
+          "ExternalClockSource_AnalogTrigger: %d, ExternalClockSource_Module: "
+          "%d, ExternalClockSource_Channel: %d\n",
+          i, x.FallingEdge, x.RisingEdge, x.ExternalClockSource_AnalogTrigger,
+          x.ExternalClockSource_Module, x.ExternalClockSource_Channel);
+      if (status != 0) {
+        wpi_setErrorWithContext(status, getHALErrorMessage(status));
+      }
+    }
+  }
+
+  wpi_setErrorWithContext(status, getHALErrorMessage(status));
+  if (status != 0) {
+    return;
+  }
+  // Start, stop, start to clear the buffer.
+  manager_->start(&status);
+  wpi_setErrorWithContext(status, getHALErrorMessage(status));
+  if (status != 0) {
+    return;
+  }
+  manager_->stop(&status);
+  wpi_setErrorWithContext(status, getHALErrorMessage(status));
+  if (status != 0) {
+    return;
+  }
+  manager_->start(&status);
+  wpi_setErrorWithContext(status, getHALErrorMessage(status));
+  if (status != 0) {
+    return;
+  }
+
+}
+
+static_assert(::std::is_pod<DMASample>::value, "DMASample needs to be POD");
+
+ssize_t DMASample::offset(int index) const { return dma_->channel_offsets_[index]; }
+
+double DMASample::GetTimestamp() const {
+  return static_cast<double>(read_buffer_[dma_->capture_size_ - 1]) * 0.000001;
+}
+
+bool DMASample::Get(DigitalSource *input) const {
+  if (offset(kEnable_DI) == -1) {
+    wpi_setStaticErrorWithContext(dma_,
+        NiFpga_Status_ResourceNotFound,
+        getHALErrorMessage(NiFpga_Status_ResourceNotFound));
+    return false;
+  }
+  if (input->GetChannelForRouting() < kNumHeaders) {
+    return (read_buffer_[offset(kEnable_DI)] >>
+            input->GetChannelForRouting()) &
+           0x1;
+  } else {
+    return (read_buffer_[offset(kEnable_DI)] >>
+            (input->GetChannelForRouting() + 6)) &
+           0x1;
+  }
+}
+
+int32_t DMASample::GetRaw(Encoder *input) const {
+  if (offset(kEnable_Encoders) == -1) {
+    wpi_setStaticErrorWithContext(dma_,
+        NiFpga_Status_ResourceNotFound,
+        getHALErrorMessage(NiFpga_Status_ResourceNotFound));
+    return -1;
+  }
+
+  if (input->GetFPGAIndex() >= 4) {
+    wpi_setStaticErrorWithContext(dma_,
+        NiFpga_Status_ResourceNotFound,
+        getHALErrorMessage(NiFpga_Status_ResourceNotFound));
+  }
+
+  uint32_t dmaWord =
+      read_buffer_[offset(kEnable_Encoders) + input->GetFPGAIndex()];
+  int32_t result = 0;
+
+  if (1) {
+    // Extract the 31-bit signed tEncoder::tOutput Value using a struct with the
+    // reverse packed field order of tOutput. This gets Value from the high
+    // order 31 bits of output on little-endian ARM using gcc. This works
+    // even though C/C++ doesn't guarantee bitfield order.
+    t1Output output;
+
+    output.value = dmaWord;
+    result = output.Value;
+  } else if (1) {
+    // Extract the 31-bit signed tEncoder::tOutput Value using right-shift.
+    // This works even though C/C++ doesn't guarantee whether signed >> does
+    // arithmetic or logical shift. (dmaWord / 2) would fix that but it rounds.
+    result = static_cast<int32_t>(dmaWord) >> 1;
+  }
+#if 0  // This approach was recommended but it doesn't return the right value.
+  else {
+    // Byte-reverse the DMA word (big-endian value from the FPGA) then extract
+    // the 31-bit tEncoder::tOutput. This does not return the right Value.
+    tEncoder::tOutput encoderData;
+
+    encoderData.value = __builtin_bswap32(dmaWord);
+    result = encoderData.Value;
+  }
+#endif
+
+  return result;
+}
+
+int32_t DMASample::Get(Encoder *input) const {
+  int32_t raw = GetRaw(input);
+
+  return raw / input->GetEncodingScale();
+}
+
+uint16_t DMASample::GetValue(AnalogInput *input) const {
+  if (offset(kEnable_Encoders) == -1) {
+    wpi_setStaticErrorWithContext(dma_,
+        NiFpga_Status_ResourceNotFound,
+        getHALErrorMessage(NiFpga_Status_ResourceNotFound));
+    return 0xffff;
+  }
+
+  uint32_t dmaWord;
+  uint32_t channel = input->GetChannel();
+  if (channel <= 3) {
+    dmaWord = read_buffer_[offset(kEnable_AI0_Low) + channel / 2];
+  } else {
+    dmaWord = read_buffer_[offset(kEnable_AI0_High) + (channel - 4) / 2];
+  }
+  if (channel % 2) {
+    return (dmaWord >> 16) & 0xffff;
+  } else {
+    return (dmaWord) & 0xffff;
+  }
+  return static_cast<int16_t>(dmaWord);
+}
+
+float DMASample::GetVoltage(AnalogInput *input) const {
+  uint16_t value = GetValue(input);
+  if (value == 0xffff) return 0.0;
+  uint32_t lsb_weight = input->GetLSBWeight();
+  int32_t offset = input->GetOffset();
+  float voltage = lsb_weight * 1.0e-9 * value - offset * 1.0e-9;
+  return voltage;
+}
diff --git a/aos/externals/forwpilib/dma.h b/aos/externals/forwpilib/dma.h
new file mode 100644
index 0000000..754b0a5
--- /dev/null
+++ b/aos/externals/forwpilib/dma.h
@@ -0,0 +1,121 @@
+#ifndef _DMA_H_
+#define _DMA_H_
+
+// Interface to the roboRIO FPGA's DMA features.
+
+#include <stdint.h>
+
+#include <array>
+#include <memory>
+
+#include "ChipObject.h"
+#include "ErrorBase.h"
+
+class DMA;
+class DigitalSource;
+class AnalogInput;
+class Encoder;
+
+// A POD class which stores the data from a DMA sample and provides safe ways to
+// access it.
+class DMASample {
+ public:
+  DMASample() = default;
+
+  // Returns the FPGA timestamp of the sample.
+  double GetTimestamp() const;
+
+  // All Get methods either return the requested value, or set the Error.
+
+  // Returns the value of the digital input in the sample.
+  bool Get(DigitalSource *input) const;
+  // Returns the raw value of the encoder in the sample.
+  int32_t GetRaw(Encoder *input) const;
+  // Returns the {1, 2, or 4} X scaled value of the encoder in the sample.
+  int32_t Get(Encoder *input) const;
+  // Returns the raw 12-bit value from the ADC.
+  uint16_t GetValue(AnalogInput *input) const;
+  // Returns the scaled value of an analog input.
+  float GetVoltage(AnalogInput *input) const;
+
+ private:
+  friend DMA;
+
+  // Returns the offset of the sample type in the buffer, or -1 if it isn't in
+  // the sample.
+  ssize_t offset(int index) const;
+
+  // TODO(austin): This should be re-used from WPILib...  Once I merge this back
+  // into WPILib.
+
+  DMA *dma_;
+  uint32_t read_buffer_[64];
+};
+
+// TODO(austin): ErrorBase...
+class DMA : public ErrorBase {
+ public:
+  DMA();
+  virtual ~DMA();
+
+  // Sets whether or not DMA is paused.
+  void SetPause(bool pause);
+
+  // Sets the number of triggers that need to occur before a sample is saved.
+  void SetRate(uint32_t cycles);
+
+  // Adds the input signal to the state to snapshot on the trigger event.
+  // It is safe to add the same input multiple times, but there is currently
+  // no way to remove one once it has been added.
+  // Call Add() and SetExternalTrigger() before Start().
+  void Add(Encoder *encoder);
+  void Add(DigitalSource *input);
+  void Add(AnalogInput *input);
+
+  // Configures DMA to trigger on an external trigger.  There can only be 4
+  // external triggers.
+  // Call Add() and SetExternalTrigger() before Start().
+  void SetExternalTrigger(DigitalSource *input, bool rising, bool falling);
+
+  // Starts reading samples into the buffer.  Clears all previous samples before
+  // starting.
+  // Call Start() before Read().
+  void Start(size_t queue_depth);
+
+  enum ReadStatus {
+    STATUS_OK = 0,
+    STATUS_TIMEOUT = 1,
+    STATUS_ERROR = 2,
+  };
+
+  // Reads a sample from the DMA buffer, waiting up to timeout_ms for it.
+  // Returns a status code indicating whether the read worked, timed out, or
+  // failed.
+  // Returns in *remaining_out the number of DMA samples still queued after this
+  // Read().
+  // Call Add() and SetExternalTrigger() then Start() before Read().
+  // The sample is only usable while this DMA object is left started.
+  ReadStatus Read(DMASample *sample, uint32_t timeout_ms,
+                  size_t *remaining_out);
+
+  // Translates a ReadStatus code to a string name.
+  static const char *NameOfReadStatus(ReadStatus s);
+
+ private:
+  ::std::unique_ptr<nFPGA::tDMAManager> manager_;  // set by Start()
+  typedef nFPGA::nRoboRIO_FPGANamespace::tDMA tDMA;
+  friend DMASample;
+
+  // The offsets into the sample structure for each DMA type, or -1 if it isn't
+  // in the set of values.
+  ssize_t channel_offsets_[18];
+
+  // The size of the data to read to get a sample.
+  size_t capture_size_ = 0;
+  tDMA::tConfig tconfig_;
+  tDMA *tdma_config_;
+
+  ::std::array<bool, 4> trigger_channels_ = {{false, false, false, false}};
+};
+
+#endif  // _DMA_H_
diff --git a/aos/externals/gtest.patch b/aos/externals/gtest.patch
new file mode 100644
index 0000000..f0ee200
--- /dev/null
+++ b/aos/externals/gtest.patch
@@ -0,0 +1,59 @@
+diff --git src/gtest-port.cc b/src/gtest-port.cc
+index b860d48..acb459b 100644
+--- a/src/gtest-port.cc
++++ b/src/gtest-port.cc
+@@ -35,6 +35,8 @@
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <string.h>
++#include <sys/types.h>
++#include <dirent.h>
+ 
+ #if GTEST_OS_WINDOWS_MOBILE
+ # include <windows.h>  // For TerminateProcess()
+@@ -98,6 +98,21 @@ size_t GetThreadCount() {
+   }
+ }
+ 
++#elif GTEST_OS_LINUX
++
++size_t GetThreadCount() {
++  size_t thread_count = 0;
++  if (DIR *dir = opendir("/proc/self/task")) {
++    while (dirent *entry = readdir(dir)) {
++      if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
++        ++thread_count;
++      }
++    }
++    closedir(dir);
++  }
++  return thread_count;
++}
++
+ #else
+ 
+ size_t GetThreadCount() {
+diff --git a/src/gtest-death-test.cc b/src/gtest-death-test.cc
+index 8b2e413..faad3a4 100644
+--- a/src/gtest-death-test.cc
++++ b/src/gtest-death-test.cc
+@@ -44,6 +44,8 @@
+ # include <fcntl.h>
+ # include <limits.h>
+ # include <stdarg.h>
++# include <sys/time.h>
++# include <sys/resource.h>
+ 
+ # if GTEST_OS_WINDOWS
+ #  include <windows.h>
+@@ -898,6 +900,11 @@ inline char** GetEnviron() { return environ; }
+ // This function is called in a clone()-ed process and thus must avoid
+ // any potentially unsafe operations like malloc or libc functions.
+ static int ExecDeathTestChildMain(void* child_arg) {
++  rlimit core_rlimit;
++  core_rlimit.rlim_cur = 0;
++  core_rlimit.rlim_max = 0;
++  GTEST_DEATH_TEST_CHECK_SYSCALL_(setrlimit(RLIMIT_CORE, &core_rlimit));
++
+   ExecDeathTestArgs* const args = static_cast<ExecDeathTestArgs*>(child_arg);
+   GTEST_DEATH_TEST_CHECK_SYSCALL_(close(args->close_fd));
diff --git a/aos/externals/gtest/gtest_main.cc b/aos/externals/gtest/gtest_main.cc
new file mode 100644
index 0000000..db403bb
--- /dev/null
+++ b/aos/externals/gtest/gtest_main.cc
@@ -0,0 +1,67 @@
+#include <iostream>
+#include <getopt.h>
+
+#include "gtest/gtest.h"
+
+namespace aos {
+namespace common {
+namespace testing {
+
+// Actually declared/defined in aos/common/queue_testutils.
+void SetLogFileName(const char* filename) __attribute__((weak));
+void ForcePrintLogsDuringTests() __attribute__((weak));
+
+}  // namespace testing
+}  // namespace common
+}  // namespace aos
+
+GTEST_API_ int main(int argc, char **argv) {
+  static const struct option long_options[] = {
+      {"help", no_argument, 0, 'h'},
+      {"print-logs", no_argument, 0, 'p'},
+      {"log-file", required_argument, 0, 'o'},
+      {0, 0, 0, 0},
+  };
+
+  testing::InitGoogleTest(&argc, argv);
+
+  // The gtest library modifies argc and argv to remove all of its own command
+  // line switches etc. So after calling InitGoogleTest() we can parse our own
+  // command line options.
+  while (true) {
+    int c = getopt_long(argc, argv, "pho:", long_options, nullptr);
+
+    if (c == -1) {
+      break;
+    }
+
+    switch (c) {
+      case 'h':
+        printf(
+            "\nFRC971 options:\n"
+            "  -p, --print-logs\n"
+            "      Print the log messages as they are being generated.\n"
+            "  -o, --log-file=FILE\n"
+            "      Print all log messages to FILE instead of standard output\n"
+            );
+        break;
+
+      case 'p':
+        if (::aos::common::testing::ForcePrintLogsDuringTests) {
+          ::aos::common::testing::ForcePrintLogsDuringTests();
+        }
+        break;
+
+      case 'o':
+        if (::aos::common::testing::SetLogFileName) {
+          ::aos::common::testing::SetLogFileName(optarg);
+        }
+        break;
+
+      case '?':
+        abort();
+    }
+  }
+
+  return RUN_ALL_TESTS();
+}
diff --git a/aos/externals/gyp.patch b/aos/externals/gyp.patch
new file mode 100644
index 0000000..b09b67d
--- /dev/null
+++ b/aos/externals/gyp.patch
@@ -0,0 +1,21 @@
+diff -rupN before/pylib/gyp/input.py after/pylib/gyp/input.py
+--- before/pylib/gyp/input.py	2012-11-20 16:38:09.394784918 -0800
++++ after/pylib/gyp/input.py	2012-11-20 16:39:10.527105964 -0800
+@@ -2412,17 +2412,6 @@ def ValidateSourcesInTarget(target, targ
+     basename = os.path.basename(name)  # Don't include extension.
+     basenames.setdefault(basename, []).append(source)
+ 
+-  error = ''
+-  for basename, files in basenames.iteritems():
+-    if len(files) > 1:
+-      error += '  %s: %s\n' % (basename, ' '.join(files))
+-
+-  if error:
+-    print('static library %s has several files with the same basename:\n' %
+-          target + error + 'Some build systems, e.g. MSVC08, '
+-          'cannot handle that.')
+-    raise GypError('Duplicate basenames in sources section, see list above')
+-
+ 
+ def ValidateRulesInTarget(target, target_dict, extra_sources_for_rules):
+   """Ensures that the rules sections in target_dict are valid and consistent,
diff --git a/aos/externals/seasocks.patch b/aos/externals/seasocks.patch
new file mode 100644
index 0000000..e98c65d
--- /dev/null
+++ b/aos/externals/seasocks.patch
@@ -0,0 +1,40 @@
+diff --git a/src/main/c/HybiPacketDecoder.cpp b/src/main/c/HybiPacketDecoder.cpp
+index f0fdefe..c2971b2 100644
+--- a/src/main/c/HybiPacketDecoder.cpp
++++ b/src/main/c/HybiPacketDecoder.cpp
+@@ -27,6 +27,7 @@
+ #include "internal/LogStream.h"
+ 
+ #include <arpa/inet.h>
++#include <string.h>
+ 
+ namespace seasocks {
+ 
+@@ -56,18 +57,24 @@ HybiPacketDecoder::MessageState HybiPacketDecoder::decodeNextMessage(std::vector
+     auto ptr = _messageStart + 2;
+     if (payloadLength == 126) {
+         if (_buffer.size() < 4) { return NoMessage; }
+-        payloadLength = htons(*reinterpret_cast<const uint16_t*>(&_buffer[ptr]));
++        uint16_t raw_length;
++        memcpy(&raw_length, &_buffer[ptr], sizeof(raw_length));
++        payloadLength = htons(raw_length);
+         ptr += 2;
+     } else if (payloadLength == 127) {
+         if (_buffer.size() < 10) { return NoMessage; }
+-        payloadLength = __bswap_64(*reinterpret_cast<const uint64_t*>(&_buffer[ptr]));
++        uint64_t raw_length;
++        memcpy(&raw_length, &_buffer[ptr], sizeof(raw_length));
++        payloadLength = __bswap_64(raw_length);
+         ptr += 8;
+     }
+     uint32_t mask = 0;
+     if (maskBit) {
+         // MASK is set.
+         if (_buffer.size() < ptr + 4) { return NoMessage; }
+-        mask = htonl(*reinterpret_cast<const uint32_t*>(&_buffer[ptr]));
++        uint32_t raw_length;
++        memcpy(&raw_length, &_buffer[ptr], sizeof(raw_length));
++        mask = htonl(raw_length);
+         ptr += 4;
+     }
+     auto bytesLeftInBuffer = _buffer.size() - ptr;
diff --git a/aos/externals/seasocks/gen_embedded.py b/aos/externals/seasocks/gen_embedded.py
new file mode 100755
index 0000000..d0fd603
--- /dev/null
+++ b/aos/externals/seasocks/gen_embedded.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python3
+
+# This file is a modified version of the gen_embedded script included in the
+# scripts directory of seasocks (version 1.1.2). It has been modified to
+# recursively find the web files itself, which was originally done by piping
+# in the results from a "find" shell command.
+
+# The embedded files includes only those that are required for the server to run
+# (including 404 files, a default index page, favicon, etc.)
+
+import os, os.path, sys
+
+output = sys.argv[1]
+assert output[0] == '"'
+assert output[-1] == '"'
+output = output[1:-1]
+
+if not os.path.exists(os.path.dirname(output)):
+  os.makedirs(os.path.dirname(output))
+o = open(output, 'w')
+
+web = []
+for root, dirs, files in os.walk("./www_defaults", topdown=False):
+  for name in files:
+    web.append(os.path.join(root, name))
+  for name in dirs:
+    web.append(os.path.join(root, name))
+
+o.write("""
+#include "internal/Embedded.h"
+
+#include <string>
+#include <unordered_map>
+
+namespace {
+
+std::unordered_map<std::string, EmbeddedContent> embedded = {
+""")
+
+for f in web:
+  bytes = open(f, 'rb').read()
+  o.write('{"/%s", {' % os.path.basename(f))
+  o.write('"' + "".join(['\\x%02x' % ord(x) for x in bytes]) + '"')
+  o.write(',%d }},' % len(bytes))
+
+o.write("""
+};
+
+} // namespace
+
+const EmbeddedContent* findEmbeddedContent(const std::string& name) {
+  auto found = embedded.find(name);
+  if (found == embedded.end()) {
+    return NULL;
+  }
+  return &found->second;
+}
+""")
+
+o.close()
diff --git a/aos/externals/seasocks/internal/Config.h b/aos/externals/seasocks/internal/Config.h
new file mode 100644
index 0000000..e99d356
--- /dev/null
+++ b/aos/externals/seasocks/internal/Config.h
@@ -0,0 +1,221 @@
+// Generated by Comran from version 1.1.2 with the autoconf scripts from upstream
+/* src/main/c/internal/Config.h.  Generated from Config.h.in by configure.  */
+/* src/main/c/internal/Config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* define if the compiler supports basic C++11 syntax */
+/* #undef HAVE_CXX11 */
+
+/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you
+   don't. */
+#define HAVE_DECL_STRERROR_R 1
+
+/* Define to 1 if you have the `dup2' function. */
+#define HAVE_DUP2 1
+
+/* Define to 1 if you have the `eventfd' function. */
+#define HAVE_EVENTFD 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the `fork' function. */
+#define HAVE_FORK 1
+
+/* Define to 1 if you have the `gethostname' function. */
+#define HAVE_GETHOSTNAME 1
+
+/* Define to 1 if you have the `getopt' function. */
+#define HAVE_GETOPT 1
+
+/* Define to 1 if you have the <getopt.h> header file. */
+#define HAVE_GETOPT_H 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+   to 0 otherwise. */
+/* #undef HAVE_MALLOC */
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if the system has the type `ptrdiff_t'. */
+#define HAVE_PTRDIFF_T 1
+
+/* Define to 1 if you have the `rmdir' function. */
+#define HAVE_RMDIR 1
+
+/* Define to 1 if you have the `socket' function. */
+#define HAVE_SOCKET 1
+
+/* Define to 1 if you have the `sqrt' function. */
+#define HAVE_SQRT 1
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#define HAVE_STDDEF_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strchr' function. */
+#define HAVE_STRCHR 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the `strerror_r' function. */
+#define HAVE_STRERROR_R 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `syscall' function. */
+#define HAVE_SYSCALL 1
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* define if unordered_map supports emplace */
+#define HAVE_UNORDERED_MAP_EMPLACE 1
+
+/* Define to 1 if you have the `vfork' function. */
+#define HAVE_VFORK 1
+
+/* Define to 1 if you have the <vfork.h> header file. */
+/* #undef HAVE_VFORK_H */
+
+/* Define to 1 if `fork' works. */
+#define HAVE_WORKING_FORK 1
+
+/* Define to 1 if `vfork' works. */
+#define HAVE_WORKING_VFORK 1
+
+/* Define to 1 if the system has the type `_Bool'. */
+/* #undef HAVE__BOOL */
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "matt@godbolt.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "SeaSocks"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "SeaSocks 0.1"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "seasocks"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL "https://github.com/mattgodbolt/seasocks"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "0.1"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if strerror_r returns char *. */
+#define STRERROR_R_CHAR_P 1
+
+/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
+   <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
+   #define below would cause a syntax error. */
+/* #undef _UINT32_T */
+
+/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
+   <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
+   #define below would cause a syntax error. */
+/* #undef _UINT64_T */
+
+/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
+   <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
+   #define below would cause a syntax error. */
+/* #undef _UINT8_T */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to rpl_malloc if the replacement function should be used. */
+/* #undef malloc */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef pid_t */
+
+/* Define to the equivalent of the C99 'restrict' keyword, or to
+   nothing if this is not supported.  Do not define if restrict is
+   supported directly.  */
+#define restrict __restrict
+/* Work around a bug in Sun C++: it does not support _Restrict or
+   __restrict__, even though the corresponding Sun C compiler ends up with
+   "#define restrict _Restrict" or "#define restrict __restrict__" in the
+   previous line.  Perhaps some future version of Sun C++ will work with
+   restrict; if so, hopefully it defines __RESTRICT like Sun C does.  */
+#if defined __SUNPRO_CC && !defined __RESTRICT
+# define _Restrict
+# define __restrict__
+#endif
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define to the type of an unsigned integer type of width exactly 16 bits if
+   such a type exists and the standard includes do not define it. */
+/* #undef uint16_t */
+
+/* Define to the type of an unsigned integer type of width exactly 32 bits if
+   such a type exists and the standard includes do not define it. */
+/* #undef uint32_t */
+
+/* Define to the type of an unsigned integer type of width exactly 64 bits if
+   such a type exists and the standard includes do not define it. */
+/* #undef uint64_t */
+
+/* Define to the type of an unsigned integer type of width exactly 8 bits if
+   such a type exists and the standard includes do not define it. */
+/* #undef uint8_t */
+
+/* Define as `fork' if `vfork' does not work. */
+/* #undef vfork */
diff --git a/aos/linux_code/README.txt b/aos/linux_code/README.txt
new file mode 100644
index 0000000..65feb21
--- /dev/null
+++ b/aos/linux_code/README.txt
@@ -0,0 +1,10 @@
+see ../README.txt for stuff affecting all code
+
+The folder is called linux_code because it mainly deals with code that uses the queue system, which only works under GNU/Linux for a variety of reasons, some fundamental (futexes) and some because nobody bothers to fix them.
+The layout is designed with multiple linux boxes in mind.
+
+The code for the linux box that sends motor outputs etc is in ../prime/.
+
+[NOTES]
+Any code should call aos::Init() (or aos::InitNRT() for processes that don't need to be realtime) before making any calls to any of the aos functions.
+Making calls to any of the aos functions (including aos::Init()) from more than 1 thread per process is not supported, but using fork(2) after some aos functions have been called and then continuing to make aos function calls (without calling one of the exec(3) functions) in both processes is supported.
diff --git a/aos/linux_code/complex_thread_local.cc b/aos/linux_code/complex_thread_local.cc
new file mode 100644
index 0000000..d57323e
--- /dev/null
+++ b/aos/linux_code/complex_thread_local.cc
@@ -0,0 +1,69 @@
+#include "aos/linux_code/complex_thread_local.h"
+
+#include <pthread.h>
+
+#include "aos/common/once.h"
+#include "aos/common/die.h"
+
+#define SIMPLE_CHECK(call)              \
+  do {                                  \
+    const int value = call;             \
+    if (value != 0) {                   \
+      PRDie(value, "%s failed", #call); \
+    }                                   \
+  } while (false)
+
+namespace aos {
+namespace {
+
+void ExecuteDestructorList(void *v) {
+  for (const ComplexThreadLocalDestructor *c =
+           static_cast<ComplexThreadLocalDestructor *>(v);
+       c != nullptr; c = c->next) {
+    c->function(c->param);
+  }
+}
+
+pthread_key_t *CreateKey() {
+  static pthread_key_t r;
+  SIMPLE_CHECK(pthread_key_create(&r, ExecuteDestructorList));
+  return &r;
+}
+
+::aos::Once<pthread_key_t> key_once(CreateKey);
+
+} // namespace
+
+void ComplexThreadLocalDestructor::Add() {
+  static_assert(
+      ::std::is_pod<ComplexThreadLocalDestructor>::value,
+      "ComplexThreadLocalDestructor might not be safe to pass through void*");
+  pthread_key_t *const key = key_once.Get();
+
+  next = static_cast<ComplexThreadLocalDestructor *>(pthread_getspecific(*key));
+  SIMPLE_CHECK(pthread_setspecific(*key, this));
+}
+
+void ComplexThreadLocalDestructor::Remove() {
+  pthread_key_t *const key = key_once.Get();
+
+  ComplexThreadLocalDestructor *previous = nullptr;
+  for (ComplexThreadLocalDestructor *c =
+           static_cast<ComplexThreadLocalDestructor *>(
+               pthread_getspecific(*key));
+       c != nullptr; c = c->next) {
+    if (c == this) {
+      // If it's the first one.
+      if (previous == nullptr) {
+        SIMPLE_CHECK(pthread_setspecific(*key, next));
+      } else {
+        previous->next = next;
+      }
+      return;
+    }
+    previous = c;
+  }
+  ::aos::Die("%p is not in the destructor list\n", this);
+}
+
+}  // namespace aos
diff --git a/aos/linux_code/complex_thread_local.h b/aos/linux_code/complex_thread_local.h
new file mode 100644
index 0000000..7ada875
--- /dev/null
+++ b/aos/linux_code/complex_thread_local.h
@@ -0,0 +1,131 @@
+#ifndef AOS_LINUX_CODE_COMPLEX_THREAD_LOCAL_H_
+#define AOS_LINUX_CODE_COMPLEX_THREAD_LOCAL_H_
+
+#include <assert.h>
+
+#include <type_traits>
+#include <utility>
+
+namespace aos {
+
+// Instances form a (per-thread) list of destructor functions to call when the
+// thread exits.
+// Only ComplexThreadLocal should use this.
+struct ComplexThreadLocalDestructor {
+  // Adds this to the list of destructors in this thread.
+  void Add();
+  // Removes this from the list of destructors in this thread. ::aos::Dies if it
+  // is not there.
+  void Remove();
+
+  void (*function)(void *);
+  void *param;
+
+  ComplexThreadLocalDestructor *next;
+};
+
+// Handles creating a thread-local (per type) object with non-trivial
+// constructor and/or destructor. It will be correctly destroyed on thread exit.
+//
+// Each thread using an instantiation of this class has its own independent slot
+// for storing a T. An instance of T is not actually constructed until a thread
+// calls Create, after which a pointer to it will be returned from get() etc
+// until after Clear is called.
+//
+// Example usage:
+// class Something {
+//  private:
+//   class Data {
+//    public:
+//     Data(const ::std::string &value) : value_(value) {}
+//
+//     int DoSomething() {
+//       if (cached_result_ == 0) {
+//         // Do something expensive with value_ and store it in
+//         // cached_result_.
+//       }
+//       return cached_result_;
+//     }
+//
+//    private:
+//     const ::std::string value_;
+//     int cached_result_ = 0;
+//   };
+//   ComplexThreadLocal<Data> thread_local_;
+//   ::std::string a_string_;
+//
+//   int DoSomething() {
+//     thread_local_.Create(a_string_);
+//     return thread_local_->DoSomething();
+//   }
+// };
+//
+// The current implementation is based on
+// <http://stackoverflow.com/questions/12049684/gcc-4-7-on-linux-pthreads-nontrivial-thread-local-workaround-using-thread-n>.
+// TODO(brians): Change this to just simple standard C++ thread_local once all
+// of our compilers have support.
+template <typename T>
+class ComplexThreadLocal {
+ public:
+  // Actually creates the object in this thread if there is not one there
+  // already.
+  // args are all perfectly forwarded to the constructor.
+  template <typename... Args>
+  void Create(Args &&... args) {
+    if (initialized) return;
+    new (&storage) T(::std::forward<Args>(args)...);
+    destructor.function = PlacementDelete;
+    destructor.param = &storage;
+    destructor.Add();
+    initialized = true;
+  }
+
+  // Removes the object in this thread (if any), including calling its
+  // destructor.
+  void Clear() {
+    if (!initialized) return;
+    destructor.Remove();
+    PlacementDelete(&storage);
+    initialized = false;
+  }
+
+  // Returns true if there is already an object in this thread.
+  bool created() const { return initialized; }
+
+  // Returns the object currently created in this thread or nullptr.
+  T *operator->() const {
+    return get();
+  }
+  T *get() const {
+    if (initialized) {
+      return static_cast<T *>(static_cast<void *>(&storage));
+    } else {
+      return nullptr;
+    }
+  }
+
+ private:
+  typedef typename ::std::aligned_storage<
+      sizeof(T), ::std::alignment_of<T>::value>::type Storage;
+
+  // Convenient helper for calling a destructor.
+  static void PlacementDelete(void *t) { static_cast<T *>(t)->~T(); }
+
+  // True iff this storage has been initialized.
+  static __thread bool initialized;
+  // Where we actually store the object for this thread (if any).
+  static __thread Storage storage;
+  // The linked list element representing this storage.
+  static __thread ComplexThreadLocalDestructor destructor;
+};
+
+template <typename T>
+__thread bool ComplexThreadLocal<T>::initialized;
+template <typename T>
+__thread typename ComplexThreadLocal<T>::Storage ComplexThreadLocal<T>::storage;
+template <typename T>
+__thread ComplexThreadLocalDestructor ComplexThreadLocal<T>::destructor;
+
+}  // namespace aos
+
+#endif  // AOS_LINUX_CODE_COMPLEX_THREAD_LOCAL_H_
diff --git a/aos/linux_code/complex_thread_local_test.cc b/aos/linux_code/complex_thread_local_test.cc
new file mode 100644
index 0000000..97f0568
--- /dev/null
+++ b/aos/linux_code/complex_thread_local_test.cc
@@ -0,0 +1,101 @@
+#include "aos/linux_code/complex_thread_local.h"
+
+#include <atomic>
+
+#include "gtest/gtest.h"
+
+#include "aos/common/util/thread.h"
+
+namespace aos {
+namespace testing {
+
+class ComplexThreadLocalTest : public ::testing::Test {
+ protected:
+  struct TraceableObject {
+    TraceableObject(int data = 0) : data(data) { ++constructions; }
+    ~TraceableObject() { ++destructions; }
+
+    static ::std::atomic<int> constructions, destructions;
+
+    int data;
+  };
+  ComplexThreadLocal<TraceableObject> local;
+
+ private:
+  void SetUp() override {
+    local.Clear();
+    EXPECT_EQ(TraceableObject::constructions, TraceableObject::destructions)
+        << "There should be no way to create and destroy different numbers.";
+    TraceableObject::constructions = TraceableObject::destructions = 0;
+  }
+};
+::std::atomic<int> ComplexThreadLocalTest::TraceableObject::constructions;
+::std::atomic<int> ComplexThreadLocalTest::TraceableObject::destructions;
+
+TEST_F(ComplexThreadLocalTest, Basic) {
+  EXPECT_EQ(0, TraceableObject::constructions);
+  EXPECT_EQ(0, TraceableObject::destructions);
+  EXPECT_FALSE(local.created());
+  EXPECT_EQ(nullptr, local.get());
+
+  local.Create(971);
+  EXPECT_EQ(1, TraceableObject::constructions);
+  EXPECT_EQ(0, TraceableObject::destructions);
+  EXPECT_TRUE(local.created());
+  EXPECT_EQ(971, local->data);
+
+  local.Create(254);
+  EXPECT_EQ(1, TraceableObject::constructions);
+  EXPECT_EQ(0, TraceableObject::destructions);
+  EXPECT_TRUE(local.created());
+  EXPECT_EQ(971, local->data);
+
+  local.Clear();
+  EXPECT_EQ(1, TraceableObject::constructions);
+  EXPECT_EQ(1, TraceableObject::destructions);
+  EXPECT_FALSE(local.created());
+  EXPECT_EQ(nullptr, local.get());
+
+  local.Create(973);
+  EXPECT_EQ(2, TraceableObject::constructions);
+  EXPECT_EQ(1, TraceableObject::destructions);
+  EXPECT_TRUE(local.created());
+  EXPECT_EQ(973, local->data);
+}
+
+TEST_F(ComplexThreadLocalTest, AnotherThread) {
+  EXPECT_FALSE(local.created());
+  util::FunctionThread::RunInOtherThread([this]() {
+    EXPECT_FALSE(local.created());
+    local.Create(971);
+    EXPECT_TRUE(local.created());
+    EXPECT_EQ(971, local->data);
+    EXPECT_EQ(1, TraceableObject::constructions);
+    EXPECT_EQ(0, TraceableObject::destructions);
+  });
+  EXPECT_EQ(1, TraceableObject::constructions);
+  EXPECT_EQ(1, TraceableObject::destructions);
+  EXPECT_FALSE(local.created());
+}
+
+TEST_F(ComplexThreadLocalTest, TwoThreads) {
+  util::FunctionThread thread([this](util::FunctionThread *) {
+    local.Create(971);
+    EXPECT_EQ(971, local->data);
+    EXPECT_EQ(0, TraceableObject::destructions);
+  });
+  thread.Start();
+  local.Create(973);
+  EXPECT_EQ(973, local->data);
+  thread.Join();
+  EXPECT_TRUE(local.created());
+  EXPECT_EQ(2, TraceableObject::constructions);
+  EXPECT_EQ(1, TraceableObject::destructions);
+  local.Clear();
+  EXPECT_EQ(2, TraceableObject::constructions);
+  EXPECT_EQ(2, TraceableObject::destructions);
+  EXPECT_FALSE(local.created());
+}
+
+}  // namespace testing
+}  // namespace aos
diff --git a/aos/linux_code/configuration.cc b/aos/linux_code/configuration.cc
new file mode 100644
index 0000000..e4d5d80
--- /dev/null
+++ b/aos/linux_code/configuration.cc
@@ -0,0 +1,116 @@
+#include "aos/linux_code/configuration.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ifaddrs.h>
+#include <unistd.h>
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/unique_malloc_ptr.h"
+#include "aos/common/once.h"
+
+namespace aos {
+namespace configuration {
+namespace {
+
+// TODO(brians): This shouldn't be necesary for running tests.  Provide a way to
+// set the IP address when running tests from the test.
+const char *const kLinuxNetInterface = "eth0";
+const in_addr *DoGetOwnIPAddress() {
+  static const char *kOverrideVariable = "FRC971_IP_OVERRIDE";
+  const char *override_ip = getenv(kOverrideVariable);
+  if (override_ip != NULL) {
+    LOG(INFO, "Override IP is %s\n", override_ip);
+    static in_addr r;
+    if (inet_aton(override_ip, &r) != 0) {
+      return &r;
+    } else {
+      LOG(WARNING, "error parsing %s value '%s'\n",
+          kOverrideVariable, override_ip);
+    }
+  } else {
+    LOG(INFO, "Couldn't get environmental variable.\n");
+  }
+
+  ifaddrs *addrs;
+  if (getifaddrs(&addrs) != 0) {
+    PLOG(FATAL, "getifaddrs(%p) failed", &addrs);
+  }
+  // Smart pointers don't work very well for iterating through a linked list,
+  // but it does do a very nice job of making sure that addrs gets freed.
+  unique_c_ptr<ifaddrs, freeifaddrs> addrs_deleter(addrs);
+
+  for (; addrs != nullptr; addrs = addrs->ifa_next) {
+    // ifa_addr tends to be nullptr on CAN interfaces.
+    if (addrs->ifa_addr != nullptr && addrs->ifa_addr->sa_family == AF_INET) {
+      if (strcmp(kLinuxNetInterface, addrs->ifa_name) == 0) {
+        static const in_addr r =
+            reinterpret_cast<sockaddr_in *>(__builtin_assume_aligned(
+                addrs->ifa_addr, alignof(sockaddr_in)))->sin_addr;
+        return &r;
+      }
+    }
+  }
+  LOG(FATAL, "couldn't find an AF_INET interface named \"%s\"\n",
+      kLinuxNetInterface);
+}
+
+const char *DoGetRootDirectory() {
+  ssize_t size = 0;
+  char *r = NULL;
+  while (true) {
+    if (r != NULL) delete r;
+    size += 256;
+    r = new char[size];
+
+    ssize_t ret = readlink("/proc/self/exe", r, size);
+    if (ret < 0) {
+      if (ret != -1) {
+        LOG(WARNING, "it returned %zd, not -1\n", ret);
+      }
+      PLOG(FATAL, "readlink(\"/proc/self/exe\", %p, %zu) failed", r, size);
+    }
+    if (ret < size) {
+      void *last_slash = memrchr(r, '/', ret);
+      if (last_slash == NULL) {
+        r[ret] = '\0';
+        LOG(FATAL, "couldn't find a '/' in \"%s\"\n", r);
+      }
+      *static_cast<char *>(last_slash) = '\0';
+      LOG(INFO, "got a root dir of \"%s\"\n", r);
+      return r;
+    }
+  }
+}
+
+const char *DoGetLoggingDirectory() {
+  static const char kSuffix[] = "/../../tmp/robot_logs";
+  const char *root = GetRootDirectory();
+  char *r = new char[strlen(root) + sizeof(kSuffix)];
+  strcpy(r, root);
+  strcat(r, kSuffix);
+  return r;
+}
+
+}  // namespace
+
+const char *GetRootDirectory() {
+  static aos::Once<const char> once(DoGetRootDirectory);
+  return once.Get();
+}
+
+const char *GetLoggingDirectory() {
+  static aos::Once<const char> once(DoGetLoggingDirectory);
+  return once.Get();
+}
+
+const in_addr &GetOwnIPAddress() {
+  static aos::Once<const in_addr> once(DoGetOwnIPAddress);
+  return *once.Get();
+}
+
+}  // namespace configuration
+}  // namespace aos
diff --git a/aos/linux_code/configuration.h b/aos/linux_code/configuration.h
new file mode 100644
index 0000000..3568f28
--- /dev/null
+++ b/aos/linux_code/configuration.h
@@ -0,0 +1,31 @@
+#ifndef AOS_LINUX_CODE_CONFIGURATION_H_
+#define AOS_LINUX_CODE_CONFIGURATION_H_
+
+#include <stdint.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+namespace aos {
+
+// Holds global configuration data. All of the functions are safe to call
+// from wherever.
+namespace configuration {
+
+// Returns "our" IP address.
+const in_addr &GetOwnIPAddress();
+
+// Returns the "root directory" for this run. Under linux, this is the
+// directory where the executable is located (from /proc/self/exe)
+// The return value will always be to a static string, so no freeing is
+// necessary.
+const char *GetRootDirectory();
+// Returns the directory where logs get written. Relative to GetRootDirectory().
+// The return value will always be to a static string, so no freeing is
+// necessary.
+const char *GetLoggingDirectory();
+
+}  // namespace configuration
+}  // namespace aos
+
+#endif  // AOS_LINUX_CODE_CONFIGURATION_H_
diff --git a/aos/linux_code/core.cc b/aos/linux_code/core.cc
new file mode 100644
index 0000000..189df1d
--- /dev/null
+++ b/aos/linux_code/core.cc
@@ -0,0 +1,32 @@
+#include <sys/wait.h>
+#include <sys/select.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <string>
+
+#include "aos/linux_code/init.h"
+#include "aos/common/util/run_command.h"
+
+// Initializes shared memory. This is the only file that will create the shared
+// memory file if it doesn't already exist (and set everything up).
+//
+// Will also touch the file given as a first argument.
+
+int main(int argc, char **argv) {
+  aos::InitCreate();
+
+  if (argc > 1) {
+    const int result = ::aos::util::RunCommand(
+        (std::string("touch '") + argv[1] + "'").c_str());
+    if (result == -1 || !WIFEXITED(result) || WEXITSTATUS(result) != 0) {
+      fprintf(stderr, "`touch '%s'` failed; result = %x\n", argv[1], result);
+      exit(EXIT_FAILURE);
+    }
+  }
+
+  select(0, NULL, NULL, NULL, NULL);  // wait forever
+  aos::Cleanup();
+}
diff --git a/aos/linux_code/dump_rtprio.cc b/aos/linux_code/dump_rtprio.cc
new file mode 100644
index 0000000..cae69f1
--- /dev/null
+++ b/aos/linux_code/dump_rtprio.cc
@@ -0,0 +1,282 @@
+// This is a utility program that prints out realtime priorities for processes
+// on a system. It is useful both because the standard tools don't format that
+// information very well and the roboRIO's busybox ones don't seem to do it at
+// all.
+//
+// The output format is the following comma-separated columns:
+// exe,name,cpumask,policy,nice,priority,tid,pid,ppid,sid,cpu
+
+#include <sched.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <unistd.h>
+
+#include <string>
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/logging/logging_impl.h"
+#include "aos/common/time.h"
+
+namespace {
+
+const char *policy_string(uint32_t policy) {
+  switch (policy) {
+    case SCHED_OTHER:
+      return "OTHER";
+    case SCHED_BATCH:
+      return "BATCH";
+    case SCHED_IDLE:
+      return "IDLE";
+    case SCHED_FIFO:
+      return "FIFO";
+    case SCHED_RR:
+      return "RR";
+#ifdef SCHED_DEADLINE
+    case SCHED_DEADLINE:
+      return "DEADLINE";
+#endif
+    default:
+      return "???";
+  }
+}
+
+::std::string strip_string_prefix(size_t length, ::std::string str) {
+  str = str.substr(length);
+  while (str[0] == ' ' || str[0] == '\t') {
+    str = str.substr(1);
+  }
+  return str.substr(0, str.size() - 1);
+}
+
+int find_pid_max() {
+  int r;
+  FILE *pid_max_file = fopen("/proc/sys/kernel/pid_max", "r");
+  if (pid_max_file == nullptr) {
+    PLOG(FATAL, "fopen(\"/proc/sys/kernel/pid_max\")");
+  }
+  CHECK_EQ(1, fscanf(pid_max_file, "%d", &r));
+  PCHECK(fclose(pid_max_file));
+  return r;
+}
+
+cpu_set_t find_all_cpus() {
+  long nproc = sysconf(_SC_NPROCESSORS_CONF);
+  if (nproc == -1) {
+    PLOG(FATAL, "sysconf(_SC_NPROCESSORS_CONF)");
+  }
+  cpu_set_t r;
+  CPU_ZERO(&r);
+  for (long i = 0; i < nproc; ++i) {
+    CPU_SET(i, &r);
+  }
+  return r;
+}
+
+cpu_set_t find_cpu_mask(int process, bool *not_there) {
+  cpu_set_t r;
+  const int result = sched_getaffinity(process, sizeof(r), &r);
+  if (result == -1 && errno == ESRCH) {
+    *not_there = true;
+    return cpu_set_t();
+  }
+  if (result != 0) {
+    PLOG(FATAL, "sched_getaffinity(%d, %zu, %p)", process, sizeof(r), &r);
+  }
+  return r;
+}
+
+sched_param find_sched_param(int process, bool *not_there) {
+  sched_param r;
+  const int result = sched_getparam(process, &r);
+  if (result == -1 && errno == ESRCH) {
+    *not_there = true;
+    return sched_param();
+  }
+  if (result != 0) {
+    PLOG(FATAL, "sched_getparam(%d)", process);
+  }
+  return r;
+}
+
+int find_scheduler(int process, bool *not_there) {
+  int scheduler = sched_getscheduler(process);
+  if (scheduler == -1 && errno == ESRCH) {
+    *not_there = true;
+    return 0;
+  }
+  if (scheduler == -1) {
+    PLOG(FATAL, "sched_getscheduler(%d)", process);
+  }
+  return scheduler;
+}
+
+::std::string find_exe(int process, bool *not_there) {
+  ::std::string exe_filename = "/proc/" + ::std::to_string(process) + "/exe";
+  char exe_buffer[1024];
+  ssize_t exe_size =
+      readlink(exe_filename.c_str(), exe_buffer, sizeof(exe_buffer));
+  if (exe_size == -1 && errno == ENOENT) {
+    return "ENOENT";
+  } else {
+    if (exe_size == -1 && errno == ESRCH) {
+      *not_there = true;
+      return "";
+    }
+    if (exe_size == -1) {
+      PLOG(FATAL, "readlink(%s, %p, %zu)", exe_filename.c_str(), exe_buffer,
+           sizeof(exe_buffer));
+    }
+    return ::std::string(exe_buffer, exe_size);
+  }
+}
+
+int find_nice_value(int process, bool *not_there) {
+  errno = 0;
+  int nice_value = getpriority(PRIO_PROCESS, process);
+  if (errno == ESRCH) {
+    *not_there = true;
+    return 0;
+  }
+  if (errno != 0) {
+    PLOG(FATAL, "getpriority(PRIO_PROCESS, %d)", process);
+  }
+  return nice_value;
+}
+
+void read_stat(int process, int *ppid, int *sid, bool *not_there) {
+  ::std::string stat_filename = "/proc/" + ::std::to_string(process) + "/stat";
+  FILE *stat = fopen(stat_filename.c_str(), "r");
+  if (stat == nullptr && errno == ENOENT) {
+    *not_there = true;
+    return;
+  }
+  if (stat == nullptr) {
+    PLOG(FATAL, "fopen(%s, \"r\")", stat_filename.c_str());
+  }
+
+  char buffer[2048];
+  if (fgets(buffer, sizeof(buffer), stat) == nullptr) {
+    if (ferror(stat)) {
+      if (errno == ESRCH) {
+        *not_there = true;
+        return;
+      }
+      PLOG(FATAL, "fgets(%p, %zu, %p)", buffer, sizeof(buffer), stat);
+    }
+  }
+
+  int pid = 0;
+
+  int field = 0;
+  size_t field_start = 0;
+  int parens = 0;
+  for (size_t i = 0; i < sizeof(buffer); ++i) {
+    if (buffer[i] == '\0') break;
+    if (buffer[i] == '(') ++parens;
+    if (parens > 0) {
+      if (buffer[i] == ')') --parens;
+    } else if (buffer[i] == ' ') {
+      ::std::string field_string(buffer, field_start, i - field_start);
+      switch (field) {
+        case 0:
+          pid = ::std::stoi(field_string);
+          break;
+        case 3:
+          *ppid = ::std::stoi(field_string);
+          break;
+        case 4:
+          *sid = ::std::stoi(field_string);
+          break;
+        default:
+          break;
+      }
+      ++field;
+      field_start = i + 1;
+    }
+  }
+  PCHECK(fclose(stat));
+
+  if (field < 4) {
+    LOG(FATAL, "couldn't get fields from /proc/%d/stat\n", process);
+  }
+  CHECK_EQ(pid, process);
+}
+
+void read_status(int process, int ppid, int *pgrp, ::std::string *name,
+                 bool *not_there) {
+  ::std::string status_filename =
+      "/proc/" + ::std::to_string(process) + "/status";
+  FILE *status = fopen(status_filename.c_str(), "r");
+  if (status == nullptr && errno == ENOENT) {
+    *not_there = true;
+    return;
+  }
+  if (status == nullptr) {
+    PLOG(FATAL, "fopen(%s, \"r\")", status_filename.c_str());
+  }
+
+  int pid = 0, status_ppid = 0;
+  while (true) {
+    char buffer[1024];
+    if (fgets(buffer, sizeof(buffer), status) == nullptr) {
+      if (ferror(status)) {
+        PLOG(FATAL, "fgets(%p, %zu, %p)", buffer, sizeof(buffer), status);
+      } else {
+        break;
+      }
+    }
+    ::std::string line(buffer);
+    if (line.substr(0, 5) == "Name:") {
+      *name = strip_string_prefix(5, line);
+    } else if (line.substr(0, 4) == "Pid:") {
+      pid = ::std::stoi(strip_string_prefix(4, line));
+    } else if (line.substr(0, 5) == "PPid:") {
+      status_ppid = ::std::stoi(strip_string_prefix(5, line));
+    } else if (line.substr(0, 5) == "Tgid:") {
+      *pgrp = ::std::stoi(strip_string_prefix(5, line));
+    }
+  }
+  PCHECK(fclose(status));
+  CHECK_EQ(pid, process);
+  CHECK_EQ(status_ppid, ppid);
+}
+
+}  // namespace
+
+int main() {
+  ::aos::logging::Init();
+  ::aos::logging::AddImplementation(
+      new ::aos::logging::StreamLogImplementation(stdout));
+
+  const int pid_max = find_pid_max();
+  const cpu_set_t all_cpus = find_all_cpus();
+
+  for (int i = 0; i < pid_max; ++i) {
+    bool not_there = false;
+
+    const cpu_set_t cpu_mask = find_cpu_mask(i, &not_there);
+    const sched_param param = find_sched_param(i, &not_there);
+    const int scheduler = find_scheduler(i, &not_there);
+    const ::std::string exe = find_exe(i, &not_there);
+    const int nice_value = find_nice_value(i, &not_there);
+
+    int ppid = 0, sid = 0;
+    read_stat(i, &ppid, &sid, &not_there);
+
+    int pgrp = 0;
+    ::std::string name;
+    read_status(i, ppid, &pgrp, &name, &not_there);
+
+    if (not_there) continue;
+
+    const char *cpu_mask_string =
+        CPU_EQUAL(&cpu_mask, &all_cpus) ? "all" : "???";
+
+    printf("%s,%s,%s,%s,%d,%d,%d,%d,%d,%d\n", exe.c_str(), name.c_str(),
+           cpu_mask_string, policy_string(scheduler), nice_value,
+           param.sched_priority, i, pgrp, ppid, sid);
+  }
+}
diff --git a/aos/linux_code/init.cc b/aos/linux_code/init.cc
new file mode 100644
index 0000000..bf0b92d
--- /dev/null
+++ b/aos/linux_code/init.cc
@@ -0,0 +1,167 @@
+#include "aos/linux_code/init.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <sched.h>
+#include <sys/resource.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/prctl.h>
+#include <malloc.h>
+
+#include "aos/common/die.h"
+#include "aos/linux_code/logging/linux_logging.h"
+#include "aos/linux_code/ipc_lib/shared_mem.h"
+
+#ifdef TCMALLOC
+namespace FLAG__namespace_do_not_use_directly_use_DECLARE_double_instead {
+extern double FLAGS_tcmalloc_release_rate;
+}
+using FLAG__namespace_do_not_use_directly_use_DECLARE_double_instead::
+    FLAGS_tcmalloc_release_rate;
+#endif
+
+namespace aos {
+namespace logging {
+namespace internal {
+
+// Implemented in aos/linux_code/logging/linux_interface.cc.
+void ReloadThreadName();
+
+}  // namespace internal
+}  // namespace logging
+namespace {
+
+void SetSoftRLimit(int resource, rlim64_t soft, bool set_for_root) {
+  bool am_root = getuid() == 0;
+  if (set_for_root || !am_root) {
+    struct rlimit64 rlim;
+    if (getrlimit64(resource, &rlim) == -1) {
+      PDie("%s-init: getrlimit64(%d) failed",
+           program_invocation_short_name, resource);
+    }
+    rlim.rlim_cur = soft;
+    rlim.rlim_max = ::std::max(rlim.rlim_max, soft);
+
+    if (setrlimit64(resource, &rlim) == -1) {
+      PDie("%s-init: setrlimit64(%d, {cur=%ju,max=%ju}) failed",
+           program_invocation_short_name, resource, (uintmax_t)rlim.rlim_cur,
+           (uintmax_t)rlim.rlim_max);
+    }
+  }
+}
+
+// Common stuff that needs to happen at the beginning of both the realtime and
+// non-realtime initialization sequences. May be called twice.
+void InitStart() {
+  ::aos::logging::Init();
+  WriteCoreDumps();
+}
+
+void LockAllMemory() {
+  // Allow locking as much as we want into RAM.
+  SetSoftRLimit(RLIMIT_MEMLOCK, RLIM_INFINITY, false);
+
+  InitStart();
+  if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
+    PDie("%s-init: mlockall failed", program_invocation_short_name);
+  }
+
+  // Don't give freed memory back to the OS.
+  CHECK_EQ(1, mallopt(M_TRIM_THRESHOLD, -1));
+  // Don't use mmap for large malloc chunks.
+  CHECK_EQ(1, mallopt(M_MMAP_MAX, 0));
+
+#ifdef TCMALLOC
+  // Tell tcmalloc not to return memory.
+  FLAGS_tcmalloc_release_rate = 0.0;
+#endif
+
+  // Forces the memory pages for all the stack space that we're ever going to
+  // use to be loaded into memory (so it can be locked there).
+  uint8_t data[4096 * 8];
+  // Not 0 because linux might optimize that to a 0-filled page.
+  memset(data, 1, sizeof(data));
+
+  static const size_t kHeapPreallocSize = 512 * 1024;
+  char *const heap_data = static_cast<char *>(malloc(kHeapPreallocSize));
+  memset(heap_data, 1, kHeapPreallocSize);
+  free(heap_data);
+}
+
+const char *const kNoRealtimeEnvironmentVariable = "AOS_NO_REALTIME";
+
+}  // namespace
+
+void InitNRT() {
+  InitStart();
+  aos_core_create_shared_mem(false, false);
+  logging::linux_code::Register();
+}
+
+void InitCreate() {
+  InitStart();
+  aos_core_create_shared_mem(true, false);
+  logging::linux_code::Register();
+}
+
+void Init(int relative_priority) {
+  bool realtime = getenv(kNoRealtimeEnvironmentVariable) == nullptr;
+  if (realtime) {
+    LockAllMemory();
+
+    // Only let rt processes run for 3 seconds straight.
+    SetSoftRLimit(RLIMIT_RTTIME, 3000000, true);
+
+    // Allow rt processes up to priority 40.
+    SetSoftRLimit(RLIMIT_RTPRIO, 40, false);
+
+    // Set our process to the appropriate priority.
+    struct sched_param param;
+    param.sched_priority = 30 + relative_priority;
+    if (sched_setscheduler(0, SCHED_FIFO, &param) != 0) {
+      PDie("%s-init: setting SCHED_FIFO failed", program_invocation_short_name);
+    }
+  } else {
+    fprintf(stderr, "%s not doing realtime initialization because environment"
+            " variable %s is set\n", program_invocation_short_name,
+            kNoRealtimeEnvironmentVariable);
+    printf("no realtime for %s. see stderr\n", program_invocation_short_name);
+  }
+
+  InitStart();
+  aos_core_create_shared_mem(false, realtime);
+  logging::linux_code::Register();
+}
+
+void Cleanup() {
+  aos_core_free_shared_mem();
+}
+
+void WriteCoreDumps() {
+  // Do create core files of unlimited size.
+  SetSoftRLimit(RLIMIT_CORE, RLIM_INFINITY, true);
+}
+
+void SetCurrentThreadRealtimePriority(int priority) {
+  struct sched_param param;
+  param.sched_priority = priority;
+  if (sched_setscheduler(0, SCHED_FIFO, &param) == -1) {
+    PLOG(FATAL, "sched_setscheduler(0, SCHED_FIFO, %d) failed", priority);
+  }
+}
+
+void SetCurrentThreadName(const ::std::string &name) {
+  if (name.size() > 16) {
+    LOG(FATAL, "thread name '%s' too long\n", name.c_str());
+  }
+  LOG(INFO, "this thread is changing to '%s'\n", name.c_str());
+  PCHECK(prctl(PR_SET_NAME, name.c_str()));
+  logging::internal::ReloadThreadName();
+}
+
+}  // namespace aos
diff --git a/aos/linux_code/init.h b/aos/linux_code/init.h
new file mode 100644
index 0000000..2e57166
--- /dev/null
+++ b/aos/linux_code/init.h
@@ -0,0 +1,40 @@
+#ifndef AOS_LINUX_CODE_INIT_H_
+#define AOS_LINUX_CODE_INIT_H_
+
+#include <string>
+
+namespace aos {
+
+// In order to use shared memory, one of the Init* functions must be called in
+// exactly 1 thread per process. It is OK to keep going without calling one of
+// them again after fork(2)ing.
+
+// Does the non-realtime parts of the initialization process.
+void InitNRT();
+// Initializes everything, including the realtime stuff.
+// relative_priority adjusts the priority of this process relative to all of the
+// other ones (positive for higher priority).
+void Init(int relative_priority = 0);
+// Same as InitNRT, except will remove an existing shared memory file and create
+// a new one.
+void InitCreate();
+// Cleans up (probably not going to get called very often because few things can
+// exit gracefully).
+void Cleanup();
+
+// Sets up this process to write core dump files.
+// This is called by Init*, but it's here for other files that want this
+// behavior without calling Init*.
+void WriteCoreDumps();
+
+// Sets the current thread's realtime priority.
+void SetCurrentThreadRealtimePriority(int priority);
+
+// Sets the name of the current thread.
+// This will displayed by `top -H`, dump_rtprio, and show up in logs.
+// name can have a maximum of 16 characters.
+void SetCurrentThreadName(const ::std::string &name);
+
+}  // namespace aos
+
+#endif  // AOS_LINUX_CODE_INIT_H_
diff --git a/aos/linux_code/ipc_lib/aos_sync.cc b/aos/linux_code/ipc_lib/aos_sync.cc
new file mode 100644
index 0000000..1275bbf
--- /dev/null
+++ b/aos/linux_code/ipc_lib/aos_sync.cc
@@ -0,0 +1,440 @@
+#if !AOS_DEBUG
+#define NDEBUG
+#endif
+
+#include "aos/linux_code/ipc_lib/aos_sync.h"
+
+#include <linux/futex.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <errno.h>
+#include <stdint.h>
+#include <limits.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <stddef.h>
+#include <assert.h>
+#include <pthread.h>
+#include <sched.h>
+
+#include <algorithm>
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/once.h"
+#include "aos/common/macros.h"
+
+// This code was originally based on <http://www.akkadia.org/drepper/futex.pdf>,
+// but is has since evolved a lot. However, that still has useful information.
+//
+// Finding information about actually using futexes is really REALLY hard, so
+//   here's a list of the stuff that I've used:
+// futex(7) has a really high-level overview.
+// <http://locklessinc.com/articles/futex_cheat_sheet/> describes some of the
+//   operations in a bit more detail than most places.
+// <http://locklessinc.com/articles/mutex_cv_futex/> is the basis of our
+//   implementations (before PI).
+// <http://lwn.net/Articles/360699/> has a nice overview of futexes in late 2009
+//   (fairly recent compared to everything else...).
+// <https://www.kernel.org/doc/Documentation/pi-futex.txt>,
+//   <https://www.kernel.org/doc/Documentation/futex-requeue-pi.txt>,
+//   <https://www.kernel.org/doc/Documentation/robust-futexes.txt>,
+//   and <https://www.kernel.org/doc/Documentation/robust-futex-ABI.txt> are all
+//   useful references.
+// The kernel source (kernel/futex.c) has some useful comments about what the
+//   various operations do (except figuring out which argument goes where in the
+//   syscall is still confusing).
+// futex(2) is basically useless except for describing the order of the
+//   arguments (it only has high-level descriptions of what some of the
+//   operations do, and some of them are wrong in Wheezy).
+// glibc's nptl pthreads implementation is the intended user of most of these
+//   things, so it is also a good place to look for examples. However, it is all
+//   very hard to read because it supports ~20 different kinds of mutexes and
+//   several variations of condition variables, and some of the pieces of code
+//   are only written in assembly.
+// set_robust_list(2) is wrong in Wheezy (it doesn't actually take a TID
+//   argument).
+//
+// Can't use PRIVATE futex operations because they use the pid (or something) as
+//   part of the hash.
+//
+// ThreadSanitizer understands how these mutexes etc work. It appears to be able
+// to figure out the happens-before relationship from the __ATOMIC_SEQ_CST
+// atomic primitives.
+//
+// Remember that EAGAIN and EWOUDBLOCK are the same! (ie if you get EAGAIN from
+// FUTEX_WAIT, the docs call it EWOULDBLOCK...)
+
+// Values for an aos_mutex.futex (kernel-mandated):
+// 0 = unlocked
+// TID = locked, not contended
+// |FUTEX_WAITERS = there are waiters (aka contended)
+//
+// Values for an aos_futex being used directly:
+// 0 = unset
+// 1 = set
+//
+// The value of an aos_condition is just a generation counter.
+
+namespace {
+
+// These sys_futex_* functions are wrappers around syscall(SYS_futex). They each
+// take a specific set of arguments for a given futex operation. They return the
+// result or a negated errno value. -1..-4095 mean errors and not successful
+// results, which is guaranteed by the kernel.
+//
+// They each have optimized versions for ARM EABI (the syscall interface is
+// different for non-EABI ARM, so that is the right thing to test for) that
+// don't go through syscall(2) or errno.
+// These use register variables to get the values in the right registers to
+// actually make the syscall.
+
+// The actual macro that we key off of to use the inline versions or not.
+#define ARM_EABI_INLINE_SYSCALL defined(__ARM_EABI__)
+
+// Used for FUTEX_WAIT, FUTEX_LOCK_PI, and FUTEX_TRYLOCK_PI.
+inline int sys_futex_wait(int op, aos_futex *addr1, int val1,
+                          const struct timespec *timeout) {
+#if ARM_EABI_INLINE_SYSCALL
+  register aos_futex *addr1_reg __asm__("r0") = addr1;
+  register int op_reg __asm__("r1") = op;
+  register int val1_reg __asm__("r2") = val1;
+  register const struct timespec *timeout_reg __asm__("r3") = timeout;
+  register int syscall_number __asm__("r7") = SYS_futex;
+  register int result __asm__("r0");
+  __asm__ volatile("swi #0"
+                   : "=r"(result)
+                   : "r"(addr1_reg), "r"(op_reg), "r"(val1_reg),
+                     "r"(timeout_reg), "r"(syscall_number)
+                   : "memory");
+  return result;
+#else
+  const int r = syscall(SYS_futex, addr1, op, val1, timeout);
+  if (r == -1) return -errno;
+  return r;
+#endif
+}
+
+inline int sys_futex_wake(aos_futex *addr1, int val1) {
+#if ARM_EABI_INLINE_SYSCALL
+  register aos_futex *addr1_reg __asm__("r0") = addr1;
+  register int op_reg __asm__("r1") = FUTEX_WAKE;
+  register int val1_reg __asm__("r2") = val1;
+  register int syscall_number __asm__("r7") = SYS_futex;
+  register int result __asm__("r0");
+  __asm__ volatile("swi #0"
+                   : "=r"(result)
+                   : "r"(addr1_reg), "r"(op_reg), "r"(val1_reg),
+                     "r"(syscall_number)
+                   : "memory");
+  return result;
+#else
+  const int r = syscall(SYS_futex, addr1, FUTEX_WAKE, val1);
+  if (r == -1) return -errno;
+  return r;
+#endif
+}
+
+inline int sys_futex_unlock_pi(aos_futex *addr1) {
+#if ARM_EABI_INLINE_SYSCALL
+  register aos_futex *addr1_reg __asm__("r0") = addr1;
+  register int op_reg __asm__("r1") = FUTEX_UNLOCK_PI;
+  register int syscall_number __asm__("r7") = SYS_futex;
+  register int result __asm__("r0");
+  __asm__ volatile("swi #0"
+                   : "=r"(result)
+                   : "r"(addr1_reg), "r"(op_reg), "r"(syscall_number)
+                   : "memory");
+  return result;
+#else
+  const int r = syscall(SYS_futex, addr1, FUTEX_UNLOCK_PI);
+  if (r == -1) return -errno;
+  return r;
+#endif
+}
+
+// Returns true if it succeeds and false if it fails.
+// This is the same as __sync_bool_compare_and_swap, except it provides an easy
+// place to switch implementations and/or work around bugs.
+inline bool compare_and_swap(aos_futex *f, uint32_t before, uint32_t after) {
+  return __sync_bool_compare_and_swap(f, before, after);
+}
+
+pid_t do_get_tid() {
+  pid_t r = syscall(SYS_gettid);
+  assert(r > 0);
+  return r;
+}
+
+// This gets called by functions before LOG(FATAL)ing with error messages that
+// would be incorrect if the error was caused by a process forking without
+// initialize_in_new_thread getting called in the fork.
+void check_cached_tid(pid_t tid) {
+  pid_t actual = do_get_tid();
+  if (tid != actual) {
+    LOG(FATAL,
+        "task %jd forked into %jd without letting aos_sync know"
+        " so we're not really sure what's going on\n",
+        static_cast<intmax_t>(tid), static_cast<intmax_t>(actual));
+  }
+}
+
+// Starts off at 0 in each new thread (because that's what it gets initialized
+// to in most of them or it gets to reset to 0 after a fork by atfork_child()).
+thread_local pid_t my_tid = 0;
+
+// Gets called before the fork(2) wrapper function returns in the child.
+void atfork_child() {
+  // The next time get_tid() is called, it will set everything up again.
+  my_tid = 0;
+}
+
+void *InstallAtforkHook() {
+  if (pthread_atfork(NULL, NULL, atfork_child) != 0) {
+    PLOG(FATAL, "pthread_atfork(NULL, NULL, %p) failed", atfork_child);
+  }
+  return nullptr;
+}
+
+// This gets called to set everything up in a new thread by get_tid().
+void initialize_in_new_thread();
+
+// Gets the current thread's TID and does all of the 1-time initialization the
+// first time it's called in a given thread.
+inline uint32_t get_tid() {
+  if (__builtin_expect(my_tid == 0, 0)) {
+    initialize_in_new_thread();
+  }
+  static_assert(sizeof(my_tid) <= sizeof(uint32_t), "pid_t is too big");
+  return static_cast<uint32_t>(my_tid);
+}
+
+void initialize_in_new_thread() {
+  // No synchronization necessary in most of this because it's all thread-local!
+
+  my_tid = do_get_tid();
+
+  static ::aos::Once<void> atfork_hook_installed(InstallAtforkHook);
+  atfork_hook_installed.Get();
+}
+
+// Split out separately from mutex_get so condition_wait can call it too.
+inline int mutex_do_get(aos_mutex *m, bool signals_fail,
+                        const struct timespec *timeout) {
+  const uint32_t tid = get_tid();
+
+  while (true) {
+    // If the atomic 0->TID transition fails.
+    if (!compare_and_swap(&m->futex, 0, tid)) {
+      // Wait in the kernel, which handles atomically ORing in FUTEX_WAITERS
+      // before actually sleeping.
+      const int ret = sys_futex_wait(FUTEX_LOCK_PI, &m->futex, 1, timeout);
+      if (ret != 0) {
+        if (timeout != NULL && ret == -ETIMEDOUT) {
+          return 3;
+        }
+        if (__builtin_expect(ret == -EINTR, 1)) {
+          if (signals_fail) {
+            return 2;
+          } else {
+            continue;
+          }
+        }
+        if (ret == -EDEADLK) {
+          LOG(FATAL, "multiple lock of %p by %" PRId32 "\n", m, tid);
+        }
+        PELOG(FATAL, -ret, "FUTEX_LOCK_PI(%p(=%" PRIu32 "), 1, %p) failed",
+              &m->futex, __atomic_load_n(&m->futex, __ATOMIC_SEQ_CST), timeout);
+      } else {
+        // The kernel already handled setting the value to our TID (ish).
+        break;
+      }
+    } else {
+      // Fastpath succeeded, so no need to call into the kernel.
+      break;
+    }
+  }
+
+#ifdef AOS_SANITIZER_thread
+  // Help tsan figure out that we're synchronizing on this.
+  __sync_fetch_and_add(&m->futex, 0);
+#endif
+
+  return 0;
+}
+
+// The common implementation for everything that wants to lock a mutex.
+// If signals_fail is false, the function will try again if the wait syscall is
+// interrupted by a signal.
+// timeout can be NULL for no timeout.
+inline int mutex_get(aos_mutex *m, bool signals_fail,
+                     const struct timespec *timeout) {
+  get_tid();
+  const int r = mutex_do_get(m, signals_fail, timeout);
+  return r;
+}
+
+// The common implementation for broadcast and signal.
+// number_requeue is the number of waiters to requeue (probably INT_MAX or 0). 1
+// will always be woken.
+void condition_wake(aos_condition *c, aos_mutex * /*m*/, int number_requeue) {
+  // Make it so that anybody just going to sleep won't.
+  // This is where we might accidentally wake more than just 1 waiter with 1
+  // signal():
+  //   1 already sleeping will be woken but n might never actually make it to
+  //     sleep in the kernel because of this.
+  __atomic_add_fetch(c, 1, __ATOMIC_SEQ_CST);
+
+  const int ret = sys_futex_wake(
+      c, ::std::min(::std::max(number_requeue, 1), INT_MAX - 4096));
+  if (__builtin_expect(
+          static_cast<unsigned int>(ret) > static_cast<unsigned int>(-4096),
+          0)) {
+    PELOG(FATAL, -ret, "FUTEX_WAKE(%p, %d) failed", c, INT_MAX - 4096);
+  }
+}
+
+}  // namespace
+
+int mutex_lock(aos_mutex *m) {
+  return mutex_get(m, true, NULL);
+}
+int mutex_lock_timeout(aos_mutex *m, const struct timespec *timeout) {
+  return mutex_get(m, true, timeout);
+}
+int mutex_grab(aos_mutex *m) {
+  return mutex_get(m, false, NULL);
+}
+
+void mutex_unlock(aos_mutex *m) {
+  const uint32_t tid = get_tid();
+
+  const uint32_t value = __atomic_load_n(&m->futex, __ATOMIC_SEQ_CST);
+  if (__builtin_expect((value & FUTEX_TID_MASK) != tid, 0)) {
+    check_cached_tid(tid);
+    if ((value & FUTEX_TID_MASK) == 0) {
+      LOG(FATAL, "multiple unlock of aos_mutex %p by %" PRId32 "\n", m, tid);
+    } else {
+      LOG(FATAL, "aos_mutex %p is locked by %" PRId32 ", not %" PRId32 "\n",
+          m, value & FUTEX_TID_MASK, tid);
+    }
+  }
+
+  // If the atomic TID->0 transition fails (ie FUTEX_WAITERS is set),
+  if (!compare_and_swap(&m->futex, tid, 0)) {
+    // The kernel handles everything else.
+    const int ret = sys_futex_unlock_pi(&m->futex);
+    if (ret != 0) {
+      PELOG(FATAL, -ret, "FUTEX_UNLOCK_PI(%p) failed", &m->futex);
+    }
+  } else {
+    // There aren't any waiters, so no need to call into the kernel.
+  }
+}
+
+int mutex_trylock(aos_mutex *m) {
+  // Try an atomic 0->TID transition.
+  uint32_t c = __sync_val_compare_and_swap(&m->futex, 0, get_tid());
+
+  if (c != 0) {
+    // Somebody else had it locked; we failed.
+    return 4;
+  }
+  return 0;
+}
+
+bool mutex_islocked(const aos_mutex *m) {
+  const uint32_t tid = get_tid();
+
+  const uint32_t value = __atomic_load_n(&m->futex, __ATOMIC_RELAXED);
+  return (value & FUTEX_TID_MASK) == tid;
+}
+
+int condition_wait(aos_condition *c, aos_mutex *m) {
+  const uint32_t wait_start = __atomic_load_n(c, __ATOMIC_SEQ_CST);
+
+  mutex_unlock(m);
+
+  while (true) {
+    // Wait in the kernel iff the value of it doesn't change (ie somebody else
+    // does a wake) from before we unlocked the mutex.
+    int ret;
+    ret = sys_futex_wait(FUTEX_WAIT, c, wait_start, nullptr);
+    if (ret != 0) {
+      // If it failed because somebody else did a wake and changed the value
+      // before we actually made it to sleep.
+      if (__builtin_expect(ret == -EAGAIN, 1)) {
+        // Everything is just normal locks
+        // etc, so there's no need to do anything special here.
+
+        // We have to relock it ourself because the kernel didn't do it.
+        const int r = mutex_do_get(m, false, nullptr);
+        assert(__builtin_expect(r == 0 || r == 1, 1));
+        return r;
+      }
+      // Try again if it was because of a signal.
+      if (__builtin_expect(ret == -EINTR, 1)) continue;
+      PELOG(FATAL, -ret, "FUTEX_WAIT(%p, %" PRIu32 ", nullptr) failed",
+            c, wait_start);
+    } else {
+      // We have to take the lock ourself because the kernel won't, but
+      // there's no need for it to be anything special because all waiters
+      // just relock it like usual.
+      const int r = mutex_do_get(m, false, nullptr);
+      assert(__builtin_expect(r == 0 || r == 1, 1));
+      return r;
+    }
+  }
+}
+
+void condition_signal(aos_condition *c, aos_mutex *m) {
+  condition_wake(c, m, 0);
+}
+
+void condition_broadcast(aos_condition *c, aos_mutex *m) {
+  condition_wake(c, m, INT_MAX);
+}
+
+int futex_wait_timeout(aos_futex *m, const struct timespec *timeout) {
+  if (__atomic_load_n(m, __ATOMIC_SEQ_CST) != 0) {
+    return 0;
+  }
+  const int ret = sys_futex_wait(FUTEX_WAIT, m, 0, timeout);
+  if (ret != 0) {
+    if (ret == -EINTR) {
+      return 1;
+    } else if (ret == -ETIMEDOUT) {
+      return 2;
+    } else if (ret != -EWOULDBLOCK) {
+      errno = -ret;
+      return -1;
+    }
+  }
+#ifdef AOS_SANITIZER_thread
+  // Help tsan figure out that we're synchronizing on this.
+  __sync_add_and_fetch(m, 0);
+#endif
+  return 0;
+}
+
+int futex_wait(aos_futex *m) { return futex_wait_timeout(m, NULL); }
+
+int futex_set_value(aos_futex *m, uint32_t value) {
+  __atomic_store_n(m, value, __ATOMIC_SEQ_CST);
+  const int r = sys_futex_wake(m, INT_MAX - 4096);
+  if (__builtin_expect(
+          static_cast<unsigned int>(r) > static_cast<unsigned int>(-4096), 0)) {
+    errno = -r;
+    return -1;
+  } else {
+    return r;
+  }
+}
+
+int futex_set(aos_futex *m) {
+  return futex_set_value(m, 1);
+}
+
+int futex_unset(aos_futex *m) {
+  return !__atomic_exchange_n(m, 0, __ATOMIC_SEQ_CST);
+}
diff --git a/aos/linux_code/ipc_lib/aos_sync.h b/aos/linux_code/ipc_lib/aos_sync.h
new file mode 100644
index 0000000..2628558
--- /dev/null
+++ b/aos/linux_code/ipc_lib/aos_sync.h
@@ -0,0 +1,131 @@
+#ifndef AOS_LINUX_CODE_IPC_LIB_SYNC_H_
+#define AOS_LINUX_CODE_IPC_LIB_SYNC_H_
+
+#include <stdlib.h>
+#include <signal.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif  // __cplusplus
+
+// TODO(brians) add client requests to make helgrind useful with this code
+// <http://www.valgrind.org/docs/manual/hg-manual.html#hg-manual.client-requests>
+// and <http://www.valgrind.org/docs/manual/drd-manual.html#drd-manual.clientreqs>
+// list the interesting ones
+
+// Have to remember to align structs containing it (recursively) to sizeof(int).
+// Valid initial values for use with futex_ functions are 0 (unset) and 1 (set).
+// The value should not be changed after multiple processes have started
+// accessing an instance except through the functions declared in this file.
+typedef uint32_t aos_futex __attribute__((aligned(sizeof(int))));
+
+// For use with the condition_ functions.
+// No initialization is necessary.
+typedef aos_futex aos_condition;
+
+// For use with the mutex_ functions.
+// futex must be initialized to 0.
+// The recommended way to initialize one of these is by memset(3)ing the whole
+// thing to 0 or using C++ () initialization to avoid depending on the
+// implementation.
+struct aos_mutex {
+  aos_futex futex;
+};
+
+// The mutex_ functions are designed to be used as mutexes. A mutex can only be
+// unlocked from the same task which originally locked it.
+
+// All of these return 2 if
+// interrupted by a signal, 3 if timed out, or 4 if an optional lock fails. Some
+// of them (obviously) can never return some of those values.
+//
+// One of the highest priority processes blocked on a given mutex will be the
+// one to lock it when it is unlocked.
+int mutex_lock(struct aos_mutex *m) __attribute__((warn_unused_result));
+// Returns 2 if it timed out or 1 if interrupted by a signal.
+int mutex_lock_timeout(struct aos_mutex *m, const struct timespec *timeout)
+    __attribute__((warn_unused_result));
+// Ignores signals (retries until something other than getting a signal
+// happens).
+int mutex_grab(struct aos_mutex *m) __attribute__((warn_unused_result));
+// LOG(FATAL)s for multiple unlocking.
+void mutex_unlock(struct aos_mutex *m);
+// Does not block waiting for the mutex.
+int mutex_trylock(struct aos_mutex *m) __attribute__((warn_unused_result));
+#ifdef __cplusplus
+// Returns whether or not the mutex is locked by this thread.
+// There aren't very many valid uses for this function; the main ones are
+// checking mutexes as they are destroyed to catch problems with that early and
+// stack-based recursive mutex locking.
+bool mutex_islocked(const aos_mutex *m);
+#endif
+
+// The futex_ functions are similar to the mutex_ ones but different.
+// They are designed for signalling when something happens (possibly to
+// multiple listeners). A aos_futex manipulated with them can only be set or
+// unset. Also, they can be set/unset/waited on from any task independently of
+// who did something first and have no priority inversion protection.
+// They return -1 for other error (which will be in errno from futex(2)).
+// They have no spurious wakeups (because everybody always gets woken up).
+//
+// Another name for this kind of synchronization mechanism is a "notification".
+// Python calls it an "event".
+//
+// They are different from the condition_ functions in that they do NOT work
+// correctly as standard condition variables. While it is possible to keep
+// track of the "condition" using the value part of the futex_* functions, the
+// obvious implementation has basically the same race condition that condition
+// variables are designed to prevent between somebody else grabbing the mutex
+// and changing whether it's set or not and the futex_ function changing the
+// futex's value. A futex is effectively a resettable condition variable with
+// the condition being "has it been set"; if you have some other condition (for
+// example messages are available to read on a queue), use the condition_
+// functions or there will be race conditions.
+
+// Wait for the futex to be set. Will return immediately if it's already set.
+// Returns 0 if successful or it was already set, 1 if interrupted by a signal,
+// or -1 with an error in errno.
+int futex_wait(aos_futex *m) __attribute__((warn_unused_result));
+// The same as futex_wait except returns 2 if it times out.
+int futex_wait_timeout(aos_futex *m, const struct timespec *timeout)
+  __attribute__((warn_unused_result));
+
+// Set the futex and wake up anybody waiting on it.
+// Returns the number that were woken or -1 with an error in errno.
+//
+// This will always wake up all waiters at the same time and set the value to 1.
+int futex_set(aos_futex *m);
+// Same as above except lets something other than 1 be used as the final value.
+int futex_set_value(aos_futex *m, aos_futex value);
+// Unsets the futex (sets the value to 0).
+// Returns 0 if it was set before and 1 if it wasn't.
+// Can not fail.
+int futex_unset(aos_futex *m);
+
+// The condition_ functions implement condition variable support. The API is
+// similar to the pthreads api and works the same way. The same m argument must
+// be passed in for all calls to all of the condition_ functions with a given c.
+// They do have the potential for spurious wakeups.
+
+// Wait for the condition variable to be signalled. m will be unlocked
+// atomically with actually starting to wait. m is guaranteed to be locked when
+// this function returns.
+// NOTE: The relocking of m is not atomic with stopping the actual wait and
+// other process(es) may lock (+unlock) the mutex first.
+// Returns 0.
+int condition_wait(aos_condition *c, struct aos_mutex *m)
+    __attribute__((warn_unused_result));
+// If any other processes are condition_waiting on c, wake 1 of them. Does not
+// require m to be locked.
+// NOTE: There is a small chance that this will wake more than just 1 waiter.
+void condition_signal(aos_condition *c, struct aos_mutex *m);
+// Wakes all processes that are condition_waiting on c. Does not require m to be
+// locked.
+void condition_broadcast(aos_condition *c, struct aos_mutex *m);
+
+#ifdef __cplusplus
+}
+#endif  // __cplusplus
+
+#endif  // AOS_LINUX_CODE_IPC_LIB_SYNC_H_
diff --git a/aos/linux_code/ipc_lib/condition.cc b/aos/linux_code/ipc_lib/condition.cc
new file mode 100644
index 0000000..62ede1c
--- /dev/null
+++ b/aos/linux_code/ipc_lib/condition.cc
@@ -0,0 +1,30 @@
+#include "aos/common/condition.h"
+
+#include <inttypes.h>
+#include <assert.h>
+
+#include "aos/common/type_traits.h"
+#include "aos/common/mutex.h"
+
+namespace aos {
+
+static_assert(shm_ok<Condition>::value,
+              "Condition should work in shared memory");
+
+Condition::Condition(Mutex *m) : impl_(), m_(m) {}
+
+bool Condition::Wait() {
+  const int ret = condition_wait(&impl_, &m_->impl_);
+  assert(__builtin_expect(ret == 0 || ret == 1, 1));
+  return ret == 1;
+}
+
+void Condition::Signal() {
+  condition_signal(&impl_, &m_->impl_);
+}
+
+void Condition::Broadcast() {
+  condition_broadcast(&impl_, &m_->impl_);
+}
+
+}  // namespace aos
diff --git a/aos/linux_code/ipc_lib/core_lib.c b/aos/linux_code/ipc_lib/core_lib.c
new file mode 100644
index 0000000..de418a4
--- /dev/null
+++ b/aos/linux_code/ipc_lib/core_lib.c
@@ -0,0 +1,46 @@
+#include "aos/linux_code/ipc_lib/core_lib.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "aos/linux_code/ipc_lib/shared_mem.h"
+
+static uint8_t aos_8max(uint8_t l, uint8_t r) {
+  return (l > r) ? l : r;
+}
+void *shm_malloc_aligned(size_t length, uint8_t alignment) {
+  // minimum alignments from
+  // <http://software.intel.com/en-us/articles/data-alignment-when-migrating-to-64-bit-intel-architecture/>
+  if (length <= 1) {
+    alignment = aos_8max(alignment, 1);
+  } else if (length <= 2) {
+    alignment = aos_8max(alignment, 2);
+  } else if (length <= 4) {
+    alignment = aos_8max(alignment, 4);
+  } else if (length <= 8) {
+    alignment = aos_8max(alignment, 8);
+  } else if (length <= 16) {
+    alignment = aos_8max(alignment, 16);
+  } else {
+    alignment = aos_8max(alignment, (length >= 64) ? 64 : 16);
+  }
+
+  void *msg = NULL;
+  aos_shm_core *shm_core = global_core->mem_struct;
+  int result = mutex_grab(&shm_core->msg_alloc_lock);
+  assert(result == 0);
+  shm_core->msg_alloc = (uint8_t *)shm_core->msg_alloc - length;
+  const uint8_t align_extra = (uintptr_t)shm_core->msg_alloc % alignment;
+  shm_core->msg_alloc = (uint8_t *)shm_core->msg_alloc - align_extra;
+  msg = shm_core->msg_alloc;
+  if (msg <= global_core->shared_mem) {
+    fprintf(stderr, "core_lib: RAN OUT OF SHARED MEMORY!!!----------------------------------------------------------\n");
+    printf("if you didn't see the stderr output just then, you should have\n");
+    abort();
+  }
+  //printf("alloc %p\n", msg);
+  mutex_unlock(&shm_core->msg_alloc_lock);
+  return msg;
+}
+
diff --git a/aos/linux_code/ipc_lib/core_lib.h b/aos/linux_code/ipc_lib/core_lib.h
new file mode 100644
index 0000000..ef81c3c
--- /dev/null
+++ b/aos/linux_code/ipc_lib/core_lib.h
@@ -0,0 +1,33 @@
+#ifndef _AOS_CORE_LIB_H_
+#define _AOS_CORE_LIB_H_
+
+#include <stdint.h>
+
+#include "aos/linux_code/ipc_lib/aos_sync.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif  // __cplusplus
+
+// alloc_size was taken out of clang in r197866. It appears that it never
+// actually did anything.
+#if defined(__clang__)
+#define attribute_alloc_size(n)
+#else
+#define attribute_alloc_size(n) __attribute__((alloc_size(n)))
+#endif
+
+void *shm_malloc_aligned(size_t length, uint8_t alignment)
+    attribute_alloc_size(1);
+static void *shm_malloc(size_t length) attribute_alloc_size(1);
+static inline void *shm_malloc(size_t length) {
+  return shm_malloc_aligned(length, 0);
+}
+
+#undef attribute_alloc_size
+
+#ifdef __cplusplus
+}
+#endif  // __cplusplus
+
+#endif
diff --git a/aos/linux_code/ipc_lib/event.cc b/aos/linux_code/ipc_lib/event.cc
new file mode 100644
index 0000000..e95b45e
--- /dev/null
+++ b/aos/linux_code/ipc_lib/event.cc
@@ -0,0 +1,35 @@
+#include "aos/common/event.h"
+
+#include "aos/common/type_traits.h"
+#include "aos/common/logging/logging.h"
+
+namespace aos {
+
+Event::Event() : impl_(0) {
+  static_assert(shm_ok<Event>::value,
+                "Event is not safe for use in shared memory.");
+}
+
+void Event::Wait() {
+  int ret;
+  do {
+    ret = futex_wait(&impl_);
+  } while (ret == 1);
+  if (ret == 0) return;
+  CHECK_EQ(-1, ret);
+  PLOG(FATAL, "futex_wait(%p) failed", &impl_);
+}
+
+// We're not going to expose the number woken because that's not easily portable
+// to condition variable-based implementations.
+void Event::Set() {
+  if (futex_set(&impl_) == -1) {
+    PLOG(FATAL, "futex_set(%p) failed", &impl_);
+  }
+}
+
+bool Event::Clear() {
+  return !futex_unset(&impl_);
+}
+
+}  // namespace aos
diff --git a/aos/linux_code/ipc_lib/ipc_lib.gyp b/aos/linux_code/ipc_lib/ipc_lib.gyp
new file mode 100644
index 0000000..974a9f6
--- /dev/null
+++ b/aos/linux_code/ipc_lib/ipc_lib.gyp
@@ -0,0 +1,111 @@
+{
+  'targets': [
+    {
+      'target_name': 'aos_sync',
+      'type': 'static_library',
+      'sources': [
+        'aos_sync.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/build/aos.gyp:logging_interface',
+        '<(AOS)/common/common.gyp:once',
+      ],
+    },
+    {
+      'target_name': 'core_lib',
+      'type': 'static_library',
+      'sources': [
+        'core_lib.c',
+      ],
+      'dependencies': [
+        'aos_sync',
+        'shared_mem',
+      ],
+      'export_dependent_settings': [
+        'aos_sync',
+      ],
+    },
+    {
+      'target_name': 'shared_mem',
+      'type': 'static_library',
+      'sources': [
+        'shared_mem.c',
+      ],
+      'dependencies': [
+        'aos_sync',
+        '<(AOS)/build/aos.gyp:logging_interface',
+      ],
+      'export_dependent_settings': [
+        'aos_sync',
+      ],
+    },
+    {
+      'target_name': 'queue',
+      'type': 'static_library',
+      'sources': [
+        'queue.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/common/common.gyp:condition',
+        '<(AOS)/common/common.gyp:mutex',
+        'core_lib',
+        '<(AOS)/build/aos.gyp:logging_interface',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/build/aos.gyp:logging_interface',
+      ],
+    },
+    {
+      'target_name': 'raw_queue_test',
+      'type': 'executable',
+      'sources': [
+        'raw_queue_test.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+        'queue',
+        '<(AOS)/build/aos.gyp:logging',
+        'core_lib',
+        '<(AOS)/common/common.gyp:queue_testutils',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/common/common.gyp:die',
+        '<(AOS)/common/util/util.gyp:thread',
+        '<(AOS)/common/util/util.gyp:death_test_log_implementation',
+      ],
+    },
+    {
+      'target_name': 'ipc_stress_test',
+      'type': 'executable',
+      'sources': [
+        'ipc_stress_test.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/common/common.gyp:queue_testutils',
+        '<(AOS)/common/common.gyp:mutex',
+        'core_lib',
+        '<(AOS)/common/common.gyp:die',
+        '<(AOS)/common/libc/libc.gyp:dirname',
+        '<(AOS)/common/libc/libc.gyp:aos_strsignal',
+        '<(AOS)/build/aos.gyp:logging',
+      ],
+      'variables': {
+        'is_special_test': 1,
+      },
+    },
+    {
+      'target_name': 'scoped_message_ptr',
+      'type': 'static_library',
+      'sources': [
+        #'scoped_message_ptr.h',
+      ],
+      'dependencies': [
+        'queue',
+      ],
+      'export_dependent_settings': [
+        'queue',
+      ],
+    },
+  ],
+}
diff --git a/aos/linux_code/ipc_lib/ipc_stress_test.cc b/aos/linux_code/ipc_lib/ipc_stress_test.cc
new file mode 100644
index 0000000..880d226
--- /dev/null
+++ b/aos/linux_code/ipc_lib/ipc_stress_test.cc
@@ -0,0 +1,253 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <libgen.h>
+
+#include <string>
+
+#include "aos/common/time.h"
+#include "aos/common/queue_testutils.h"
+#include "aos/common/type_traits.h"
+#include "aos/common/mutex.h"
+#include "aos/linux_code/ipc_lib/core_lib.h"
+#include "aos/common/die.h"
+#include "aos/common/libc/dirname.h"
+#include "aos/common/libc/aos_strsignal.h"
+#include "aos/common/logging/logging.h"
+
+// This runs all of the IPC-related tests in a bunch of parallel processes for a
+// while and makes sure that they don't fail. It also captures the stdout and
+// stderr output from each test run and only prints it out (not interleaved with
+// the output from any other run) if the test fails.
+//
+// They have to be run in separate processes because (in addition to various
+// parts of our code not being thread-safe...) gtest does not like multiple
+// threads.
+//
+// It's written in C++ for performance. We need actual OS-level parallelism for
+// this to work, which means that Ruby's out because it doesn't have good
+// support for doing that. My Python implementation ended up pretty heavily disk
+// IO-bound, which is a bad way to test CPU contention.
+
+namespace aos {
+
+// Each test is represented by the name of the test binary and then any
+// arguments to pass to it.
+// Using --gtest_filter is a bad idea because it seems to result in a lot of
+// swapping which causes everything to be disk-bound (at least for me).
+static const size_t kTestMaxArgs = 10;
+static const char * kTests[][kTestMaxArgs] = {
+  {"queue_test"},
+  {"condition_test"},
+  {"mutex_test"},
+  {"raw_queue_test"},
+};
+static const size_t kTestsLength = sizeof(kTests) / sizeof(kTests[0]);
+// These arguments get inserted before any per-test arguments.
+static const char *kDefaultArgs[] = {
+  "--gtest_repeat=30",
+  "--gtest_shuffle",
+};
+
+// How many test processes to run at a time.
+static const int kTesters = 100;
+// How long to test for.
+static constexpr time::Time kTestTime = time::Time::InSeconds(30);
+
+// The structure that gets put into shared memory and then referenced by all of
+// the child processes.
+struct Shared {
+  Shared(const time::Time &stop_time)
+    : stop_time(stop_time), total_iterations(0) {}
+
+  // Synchronizes access to stdout/stderr to avoid interleaving failure
+  // messages.
+  Mutex output_mutex;
+
+  // When to stop.
+  time::Time stop_time;
+
+  // The total number of iterations. Updated by each child as it finishes.
+  int total_iterations;
+  // Sychronizes writes to total_iterations
+  Mutex total_iterations_mutex;
+
+  const char *path;
+};
+static_assert(shm_ok<Shared>::value,
+              "it's going to get shared between forked processes");
+
+// Gets called after each child forks to run a test.
+void __attribute__((noreturn)) DoRunTest(
+    Shared *shared, const char *(*test)[kTestMaxArgs], int pipes[2]) {
+  if (close(pipes[0]) == -1) {
+    PDie("close(%d) of read end of pipe failed", pipes[0]);
+  }
+  if (close(STDIN_FILENO) == -1) {
+    PDie("close(STDIN_FILENO(=%d)) failed", STDIN_FILENO);
+  }
+  if (dup2(pipes[1], STDOUT_FILENO) == -1) {
+    PDie("dup2(%d, STDOUT_FILENO(=%d)) failed", pipes[1], STDOUT_FILENO);
+  }
+  if (dup2(pipes[1], STDERR_FILENO) == -1) {
+    PDie("dup2(%d, STDERR_FILENO(=%d)) failed", pipes[1], STDERR_FILENO);
+  }
+
+  size_t size = kTestMaxArgs;
+  size_t default_size = sizeof(kDefaultArgs) / sizeof(kDefaultArgs[0]);
+  // There's no chance to free this because we either exec or Die.
+  const char **args = new const char *[size + default_size + 1];
+  // The actual executable to run.
+  ::std::string executable;
+  int i = 0;
+  for (size_t test_i = 0; test_i < size; ++test_i) {
+    const char *c = (*test)[test_i];
+    if (i == 0) {
+      executable = ::std::string(shared->path) + "/" + c;
+      args[0] = executable.c_str();
+      for (const ::std::string &ci : kDefaultArgs) {
+        args[++i] = ci.c_str();
+      }
+    } else {
+      args[i] = c;
+    }
+    ++i;
+  }
+  args[size] = NULL;
+  execv(executable.c_str(), const_cast<char *const *>(args));
+  PDie("execv(%s, %p) failed", executable.c_str(), args);
+}
+
+void DoRun(Shared *shared) {
+  int iterations = 0;
+  // An iterator pointing to a random one of the tests.
+  // We randomize based on PID because otherwise they all end up running the
+  // same test at the same time for the whole test.
+  const char *(*test)[kTestMaxArgs] = &kTests[getpid() % kTestsLength];
+  int pipes[2];
+  while (time::Time::Now() < shared->stop_time) {
+    if (pipe(pipes) == -1) {
+      PDie("pipe(%p) failed", &pipes);
+    }
+    switch (fork()) {
+      case 0:  // in runner
+        DoRunTest(shared, test, pipes);
+      case -1:
+        PDie("fork() failed");
+    }
+
+    if (close(pipes[1]) == -1) {
+      PDie("close(%d) of write end of pipe failed", pipes[1]);
+    }
+
+    ::std::string output;
+    char buffer[2048];
+    while (true) {
+      ssize_t ret = read(pipes[0], &buffer, sizeof(buffer));
+      if (ret == 0) {  // EOF
+        if (close(pipes[0]) == -1) {
+          PDie("close(%d) of pipe at EOF failed", pipes[0]);
+        }
+        break;
+      } else if (ret == -1) {
+        PDie("read(%d, %p, %zd) failed", pipes[0], &buffer, sizeof(buffer));
+      }
+      output += ::std::string(buffer, ret);
+    }
+
+    int status;
+    while (true) {
+      if (wait(&status) == -1) {
+        if (errno == EINTR) continue;
+        PDie("wait(%p) in child failed", &status);
+      } else {
+        break;
+      }
+    }
+    if (WIFEXITED(status)) {
+      if (WEXITSTATUS(status) != 0) {
+        MutexLocker sync(&shared->output_mutex);
+        fprintf(stderr, "Test %s exited with status %d. output:\n",
+                (*test)[0], WEXITSTATUS(status));
+        fputs(output.c_str(), stderr);
+      }
+    } else if (WIFSIGNALED(status)) {
+      MutexLocker sync(&shared->output_mutex);
+      fprintf(stderr, "Test %s terminated by signal %d: %s.\n", (*test)[0],
+              WTERMSIG(status), aos_strsignal(WTERMSIG(status)));
+        fputs(output.c_str(), stderr);
+    } else {
+      CHECK(WIFSTOPPED(status));
+      Die("Test %s was stopped.\n", (*test)[0]);
+    }
+
+    ++test;
+    if (test == kTests + 1) test = kTests;
+    ++iterations;
+  }
+  {
+    MutexLocker sync(&shared->total_iterations_mutex);
+    shared->total_iterations += iterations;
+  }
+}
+
+void Run(Shared *shared) {
+  switch (fork()) {
+    case 0:  // in child
+      DoRun(shared);
+      _exit(EXIT_SUCCESS);
+    case -1:
+      PDie("fork() of child failed");
+  }
+}
+
+int Main(int argc, char **argv) {
+  if (argc < 1) {
+    fputs("need an argument\n", stderr);
+    return EXIT_FAILURE;
+  }
+
+  ::aos::common::testing::GlobalCoreInstance global_core;
+
+  Shared *shared = static_cast<Shared *>(shm_malloc(sizeof(Shared)));
+  new (shared) Shared(time::Time::Now() + kTestTime);
+
+  if (asprintf(const_cast<char **>(&shared->path),
+               "%s/../tests", ::aos::libc::Dirname(argv[0]).c_str()) == -1) {
+    PDie("asprintf failed");
+  }
+
+  for (int i = 0; i < kTesters; ++i) {
+    Run(shared);
+  }
+
+  bool error = false;
+  for (int i = 0; i < kTesters; ++i) {
+    int status;
+    if (wait(&status) == -1) {
+      if (errno == EINTR) {
+        --i;
+      } else {
+        PDie("wait(%p) failed", &status);
+      }
+    }
+    if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+      error = true;
+    }
+  }
+
+  printf("Ran a total of %d tests.\n", shared->total_iterations);
+  if (error) {
+    printf("A child had a problem during the test.\n");
+  }
+  return error ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
+}  // namespace aos
+
+int main(int argc, char **argv) {
+  return ::aos::Main(argc, argv);
+}
diff --git a/aos/linux_code/ipc_lib/mutex.cc b/aos/linux_code/ipc_lib/mutex.cc
new file mode 100644
index 0000000..c5b8652
--- /dev/null
+++ b/aos/linux_code/ipc_lib/mutex.cc
@@ -0,0 +1,58 @@
+#include "aos/common/mutex.h"
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "aos/common/type_traits.h"
+#include "aos/common/logging/logging.h"
+
+namespace aos {
+
+Mutex::Mutex() : impl_() {
+  static_assert(shm_ok<Mutex>::value,
+                "Mutex is not safe for use in shared memory.");
+}
+
+Mutex::~Mutex() {
+  if (__builtin_expect(mutex_islocked(&impl_), false)) {
+    LOG(FATAL, "destroying locked mutex %p (aka %p)\n",
+        this, &impl_);
+  }
+}
+
+// Lock and Unlock use the return values of mutex_lock/mutex_unlock
+// to determine whether the lock/unlock succeeded.
+
+bool Mutex::Lock() {
+  const int ret = mutex_grab(&impl_);
+  if (ret == 0) {
+    return false;
+  } else {
+    LOG(FATAL, "mutex_grab(%p(=%" PRIu32 ")) failed with %d\n",
+        &impl_, impl_.futex, ret);
+  }
+}
+
+void Mutex::Unlock() {
+  mutex_unlock(&impl_);
+}
+
+Mutex::State Mutex::TryLock() {
+  const int ret = mutex_trylock(&impl_);
+  switch (ret) {
+    case 0:
+      return State::kLocked;
+    case 4:
+      return State::kLockFailed;
+    default:
+      LOG(FATAL, "mutex_trylock(%p(=%" PRIu32 ")) failed with %d\n",
+          &impl_, impl_.futex, ret);
+  }
+}
+
+bool Mutex::OwnedBySelf() const {
+  return mutex_islocked(&impl_);
+}
+
+}  // namespace aos
diff --git a/aos/linux_code/ipc_lib/queue.cc b/aos/linux_code/ipc_lib/queue.cc
new file mode 100644
index 0000000..81ad51b
--- /dev/null
+++ b/aos/linux_code/ipc_lib/queue.cc
@@ -0,0 +1,567 @@
+#if !AOS_DEBUG
+#define NDEBUG
+#endif
+
+#include "aos/linux_code/ipc_lib/queue.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#include <memory>
+#include <algorithm>
+
+#include "aos/common/type_traits.h"
+#include "aos/linux_code/ipc_lib/core_lib.h"
+
+namespace aos {
+namespace {
+
+static_assert(shm_ok<RawQueue>::value,
+              "RawQueue instances go into shared memory");
+
+const bool kReadDebug = false;
+const bool kWriteDebug = false;
+const bool kRefDebug = false;
+const bool kFetchDebug = false;
+const bool kReadIndexDebug = false;
+
+// The number of extra messages the pool associated with each queue will be able
+// to hold (for readers who are slow about freeing them or who leak one when
+// they get killed).
+const int kExtraMessages = 20;
+
+}  // namespace
+
+constexpr Options<RawQueue>::Option RawQueue::kPeek;
+constexpr Options<RawQueue>::Option RawQueue::kFromEnd;
+constexpr Options<RawQueue>::Option RawQueue::kNonBlock;
+constexpr Options<RawQueue>::Option RawQueue::kBlock;
+constexpr Options<RawQueue>::Option RawQueue::kOverride;
+
+// This is what gets stuck in before each queue message in memory. It is always
+// allocated aligned to 8 bytes and its size has to maintain that alignment for
+// the message that follows immediately.
+struct RawQueue::MessageHeader {
+  MessageHeader *next;
+
+  // Gets the message header immediately preceding msg.
+  static MessageHeader *Get(const void *msg) {
+    return reinterpret_cast<MessageHeader *>(__builtin_assume_aligned(
+        static_cast<uint8_t *>(const_cast<void *>(msg)) - sizeof(MessageHeader),
+        alignof(MessageHeader)));
+  }
+
+  int32_t ref_count() const {
+    return __atomic_load_n(&ref_count_, __ATOMIC_RELAXED);
+  }
+  void set_ref_count(int32_t val) {
+    __atomic_store_n(&ref_count_, val, __ATOMIC_RELAXED);
+  }
+
+  void ref_count_sub() {
+    __atomic_sub_fetch(&ref_count_, 1, __ATOMIC_RELAXED);
+  }
+  void ref_count_add() {
+    __atomic_add_fetch(&ref_count_, 1, __ATOMIC_RELAXED);
+  }
+
+ private:
+  // This gets accessed with atomic instructions without any
+  // locks held by various member functions.
+  int32_t ref_count_;
+
+  // Padding to make the total size 8 bytes if we have 4-byte pointers or bump
+  // it to 16 if a pointer is 8 bytes by itself.
+#if __SIZEOF_POINTER__ == 8
+#ifdef __clang__
+  // Clang is smart enough to realize this is unused, but GCC doesn't like the
+  // attribute here...
+  __attribute__((unused))
+#endif
+  char padding[4];
+#elif __SIZEOF_POINTER__ == 4
+  // No padding needed to get 8 byte total size.
+#else
+#error Unknown pointer size.
+#endif
+};
+
+inline int RawQueue::index_add1(int index) {
+  // Doing it this way instead of with % is more efficient on ARM.
+  int r = index + 1;
+  assert(index <= data_length_);
+  if (r == data_length_) {
+    return 0;
+  } else {
+    return r;
+  }
+}
+
+void RawQueue::DecrementMessageReferenceCount(const void *msg) {
+  MessageHeader *header = MessageHeader::Get(msg);
+  header->ref_count_sub();
+  if (kRefDebug) {
+    printf("%p ref dec count: %p count=%d\n", this, msg, header->ref_count());
+  }
+
+  // The only way it should ever be 0 is if we were the last one to decrement,
+  // in which case nobody else should have it around to re-increment it or
+  // anything in the middle, so this is safe to do not atomically with the
+  // decrement.
+  if (header->ref_count() == 0) {
+    DoFreeMessage(msg);
+  } else {
+    assert(header->ref_count() > 0);
+  }
+}
+
+inline void RawQueue::IncrementMessageReferenceCount(const void *msg) const {
+  MessageHeader *const header = MessageHeader::Get(msg);
+  header->ref_count_add();
+  if (kRefDebug) {
+    printf("%p ref inc count: %p\n", this, msg);
+  }
+}
+
+inline void RawQueue::DoFreeMessage(const void *msg) {
+  MessageHeader *header = MessageHeader::Get(msg);
+  if (kRefDebug) {
+    printf("%p ref free to %p: %p\n", this, recycle_, msg);
+  }
+
+  if (__builtin_expect(recycle_ != nullptr, 0)) {
+    void *const new_msg = recycle_->GetMessage();
+    if (new_msg == nullptr) {
+      fprintf(stderr, "queue: couldn't get a message"
+              " for recycle queue %p\n", recycle_);
+    } else {
+      header->ref_count_add();
+      if (!recycle_->WriteMessage(const_cast<void *>(msg), kOverride)) {
+        fprintf(stderr, "queue: %p->WriteMessage(%p, kOverride) failed."
+                " aborting\n", recycle_, msg);
+        printf("see stderr\n");
+        abort();
+      }
+      msg = new_msg;
+      header = MessageHeader::Get(new_msg);
+    }
+  }
+
+  // This works around GCC bug 60272 (fixed in 4.8.3).
+  // new_next should just get replaced with header->next (and the body of the
+  // loop should become empty).
+  // The bug is that the store to new_next after the compare/exchange is
+  // unconditional but it should only be if it fails, which could mean
+  // overwriting what somebody else who preempted us right then changed it to.
+  // TODO(brians): Get rid of this workaround once we get a new enough GCC.
+  MessageHeader *new_next = __atomic_load_n(&free_messages_, __ATOMIC_RELAXED);
+  do {
+    header->next = new_next;
+  } while (__builtin_expect(
+      !__atomic_compare_exchange_n(&free_messages_, &new_next, header, true,
+                                   __ATOMIC_RELEASE, __ATOMIC_RELAXED),
+      0));
+}
+
+void *RawQueue::GetMessage() {
+  MessageHeader *header = __atomic_load_n(&free_messages_, __ATOMIC_RELAXED);
+  do {
+    if (__builtin_expect(header == nullptr, 0)) {
+      LOG(FATAL, "overused pool of queue %p (%s)\n", this, name_);
+    }
+  } while (__builtin_expect(
+      !__atomic_compare_exchange_n(&free_messages_, &header, header->next, true,
+                                   __ATOMIC_ACQ_REL, __ATOMIC_RELAXED),
+      0));
+  void *msg = reinterpret_cast<uint8_t *>(header + 1);
+  // It might be uninitialized, 0 from a previous use, or 1 from previously
+  // being recycled.
+  header->set_ref_count(1);
+  if (kRefDebug) {
+    printf("%p ref alloc: %p\n", this, msg);
+  }
+  return msg;
+}
+
+RawQueue::RawQueue(const char *name, size_t length, int hash, int queue_length)
+    : readable_(&data_lock_), writable_(&data_lock_) {
+  static_assert(shm_ok<RawQueue::MessageHeader>::value,
+                "the whole point is to stick it in shared memory");
+  static_assert((sizeof(RawQueue::MessageHeader) % 8) == 0,
+                "need to revalidate size/alignent assumptions");
+
+  if (queue_length < 1) {
+    LOG(FATAL, "queue length %d of %s needs to be at least 1\n", queue_length,
+        name_);
+  }
+
+  const size_t name_size = strlen(name) + 1;
+  char *temp = static_cast<char *>(shm_malloc(name_size));
+  memcpy(temp, name, name_size);
+  name_ = temp;
+  length_ = length;
+  hash_ = hash;
+  queue_length_ = queue_length;
+
+  next_ = NULL;
+  recycle_ = NULL;
+
+  if (kFetchDebug) {
+    printf("initializing name=%s, length=%zd, hash=%d, queue_length=%d\n",
+           name, length, hash, queue_length);
+  }
+
+  data_length_ = queue_length + 1;
+  data_ = static_cast<void **>(shm_malloc(sizeof(void *) * data_length_));
+  data_start_ = 0;
+  data_end_ = 0;
+  messages_ = 0;
+
+  msg_length_ = length + sizeof(MessageHeader);
+
+  // Create all of the messages for the free list and stick them on.
+  {
+    MessageHeader *previous = nullptr;
+    for (int i = 0; i < queue_length + kExtraMessages; ++i) {
+      MessageHeader *const message =
+          static_cast<MessageHeader *>(shm_malloc(msg_length_));
+      free_messages_ = message;
+      message->next = previous;
+      previous = message;
+    }
+  }
+
+  readable_waiting_ = false;
+
+  if (kFetchDebug) {
+    printf("made queue %s\n", name);
+  }
+}
+
+RawQueue *RawQueue::Fetch(const char *name, size_t length, int hash,
+                    int queue_length) {
+  if (kFetchDebug) {
+    printf("fetching queue %s\n", name);
+  }
+  if (mutex_lock(&global_core->mem_struct->queues.lock) != 0) {
+    LOG(FATAL, "mutex_lock(%p) failed\n",
+        &global_core->mem_struct->queues.lock);
+  }
+  RawQueue *current = static_cast<RawQueue *>(
+      global_core->mem_struct->queues.pointer);
+  if (current != NULL) {
+    while (true) {
+      // If we found a matching queue.
+      if (strcmp(current->name_, name) == 0 && current->length_ == length &&
+          current->hash_ == hash && current->queue_length_ == queue_length) {
+        mutex_unlock(&global_core->mem_struct->queues.lock);
+        return current;
+      } else {
+        if (kFetchDebug) {
+          printf("rejected queue %s strcmp=%d target=%s\n", current->name_,
+                 strcmp(current->name_, name), name);
+        }
+      }
+      // If this is the last one.
+      if (current->next_ == NULL) break;
+      current = current->next_;
+    }
+  }
+
+  RawQueue *r = new (shm_malloc(sizeof(RawQueue)))
+      RawQueue(name, length, hash, queue_length);
+  if (current == NULL) {  // if we don't already have one
+    global_core->mem_struct->queues.pointer = r;
+  } else {
+    current->next_ = r;
+  }
+
+  mutex_unlock(&global_core->mem_struct->queues.lock);
+  return r;
+}
+
+RawQueue *RawQueue::Fetch(const char *name, size_t length, int hash,
+                    int queue_length,
+                    int recycle_hash, int recycle_length, RawQueue **recycle) {
+  RawQueue *r = Fetch(name, length, hash, queue_length);
+  r->recycle_ = Fetch(name, length, recycle_hash, recycle_length);
+  if (r == r->recycle_) {
+    fprintf(stderr, "queue: r->recycle_(=%p) == r(=%p)\n", r->recycle_, r);
+    printf("see stderr\n");
+    r->recycle_ = NULL;
+    abort();
+  }
+  *recycle = r->recycle_;
+  return r;
+}
+
+bool RawQueue::DoWriteMessage(void *msg, Options<RawQueue> options) {
+  if (kWriteDebug) {
+    printf("queue: %p->WriteMessage(%p, %x)\n", this, msg, options.printable());
+  }
+  {
+    IPCMutexLocker locker(&data_lock_);
+    CHECK(!locker.owner_died());
+    bool writable_waited = false;
+
+    int new_end;
+    while (true) {
+      new_end = index_add1(data_end_);
+      // If there is room in the queue right now.
+      if (new_end != data_start_) break;
+      if (options & kNonBlock) {
+        if (kWriteDebug) {
+          printf("queue: not blocking on %p. returning false\n", this);
+        }
+        DecrementMessageReferenceCount(msg);
+        return false;
+      } else if (options & kOverride) {
+        if (kWriteDebug) {
+          printf("queue: overriding on %p\n", this);
+        }
+        // Avoid leaking the message that we're going to overwrite.
+        DecrementMessageReferenceCount(data_[data_start_]);
+        data_start_ = index_add1(data_start_);
+      } else {  // kBlock
+        assert(options & kBlock);
+        if (kWriteDebug) {
+          printf("queue: going to wait for writable_ of %p\n", this);
+        }
+        CHECK(!writable_.Wait());
+        writable_waited = true;
+      }
+    }
+    data_[data_end_] = msg;
+    ++messages_;
+    data_end_ = new_end;
+
+    if (readable_waiting_) {
+      if (kWriteDebug) {
+        printf("queue: broadcasting to readable_ of %p\n", this);
+      }
+      readable_waiting_ = false;
+      readable_.Broadcast();
+    } else if (kWriteDebug) {
+      printf("queue: skipping broadcast to readable_ of %p\n", this);
+    }
+
+    // If we got a signal on writable_ here and it's still writable, then we
+    // need to signal the next person in line (if any).
+    if (writable_waited && is_writable()) {
+      if (kWriteDebug) {
+        printf("queue: resignalling writable_ of %p\n", this);
+      }
+      writable_.Signal();
+    }
+  }
+  if (kWriteDebug) {
+    printf("queue: write returning true on queue %p\n", this);
+  }
+  return true;
+}
+
+inline void RawQueue::ReadCommonEnd() {
+  if (is_writable()) {
+    if (kReadDebug) {
+      printf("queue: %ssignalling writable_ of %p\n",
+             writable_start_ ? "not " : "", this);
+    }
+    if (!writable_start_) writable_.Signal();
+  }
+}
+
+bool RawQueue::ReadCommonStart(Options<RawQueue> options, int *index) {
+  while (data_start_ == data_end_ || ((index != NULL) && messages_ <= *index)) {
+    if (options & kNonBlock) {
+      if (kReadDebug) {
+        printf("queue: not going to block waiting on %p\n", this);
+      }
+      return false;
+    } else {  // kBlock
+      assert(options & kBlock);
+      if (kReadDebug) {
+        printf("queue: going to wait for readable_ of %p\n", this);
+      }
+      readable_waiting_ = true;
+      // Wait for a message to become readable.
+      CHECK(!readable_.Wait());
+      if (kReadDebug) {
+        printf("queue: done waiting for readable_ of %p\n", this);
+      }
+    }
+  }
+  // We have to check down here because we might have unlocked the mutex while
+  // Wait()ing above so this value might have changed.
+  writable_start_ = is_writable();
+  if (kReadDebug) {
+    printf("queue: %p->read(%p) start=%d end=%d writable_start=%d\n",
+           this, index, data_start_, data_end_, writable_start_);
+  }
+  return true;
+}
+
+inline int RawQueue::LastMessageIndex() const {
+  int pos = data_end_ - 1;
+  if (pos < 0) {  // If it wrapped around.
+    pos = data_length_ - 1;
+  }
+  return pos;
+}
+
+const void *RawQueue::DoReadMessage(Options<RawQueue> options) {
+  // TODO(brians): Test this function.
+  if (kReadDebug) {
+    printf("queue: %p->ReadMessage(%x)\n", this, options.printable());
+  }
+  void *msg = NULL;
+
+  IPCMutexLocker locker(&data_lock_);
+  CHECK(!locker.owner_died());
+
+  if (!ReadCommonStart(options, nullptr)) {
+    if (kReadDebug) {
+      printf("queue: %p common returned false\n", this);
+    }
+    return NULL;
+  }
+
+  if (options & kFromEnd) {
+    if (options & kPeek) {
+      if (kReadDebug) {
+        printf("queue: %p shortcutting c2: %d\n", this, LastMessageIndex());
+      }
+      msg = data_[LastMessageIndex()];
+      IncrementMessageReferenceCount(msg);
+    } else {
+      while (true) {
+        if (kReadDebug) {
+          printf("queue: %p start of c2\n", this);
+        }
+        // This loop pulls each message out of the buffer.
+        const int pos = data_start_;
+        data_start_ = index_add1(data_start_);
+        // If this is the last one.
+        if (data_start_ == data_end_) {
+          if (kReadDebug) {
+            printf("queue: %p reading from c2: %d\n", this, pos);
+          }
+          msg = data_[pos];
+          break;
+        }
+        // This message is not going to be in the queue any more.
+        DecrementMessageReferenceCount(data_[pos]);
+      }
+    }
+  } else {
+    if (kReadDebug) {
+      printf("queue: %p reading from d2: %d\n", this, data_start_);
+    }
+    msg = data_[data_start_];
+    if (options & kPeek) {
+      IncrementMessageReferenceCount(msg);
+    } else {
+      data_start_ = index_add1(data_start_);
+    }
+  }
+  ReadCommonEnd();
+  if (kReadDebug) {
+    printf("queue: %p read returning %p\n", this, msg);
+  }
+  return msg;
+}
+
+const void *RawQueue::DoReadMessageIndex(Options<RawQueue> options,
+                                         int *index) {
+  if (kReadDebug) {
+    printf("queue: %p->ReadMessageIndex(%x, %p(*=%d))\n",
+           this, options.printable(), index, *index);
+  }
+  void *msg = NULL;
+
+  IPCMutexLocker locker(&data_lock_);
+  CHECK(!locker.owner_died());
+
+  if (!ReadCommonStart(options, index)) {
+    if (kReadDebug) {
+      printf("queue: %p common returned false\n", this);
+    }
+    return NULL;
+  }
+
+  // TODO(parker): Handle integer wrap on the index.
+
+  if (options & kFromEnd) {
+    if (kReadDebug) {
+      printf("queue: %p reading from c1: %d\n", this, LastMessageIndex());
+    }
+    msg = data_[LastMessageIndex()];
+
+    // We'd skip this if we had kPeek, but kPeek | kFromEnd isn't valid for
+    // reading with an index.
+    *index = messages_;
+  } else {
+    // Where we're going to start reading.
+    int my_start;
+
+    const int unread_messages = messages_ - *index;
+    assert(unread_messages > 0);
+    int current_messages = data_end_ - data_start_;
+    if (current_messages < 0) current_messages += data_length_;
+    if (kReadIndexDebug) {
+      printf("queue: %p start=%d end=%d current=%d\n",
+             this, data_start_, data_end_, current_messages);
+    }
+    assert(current_messages > 0);
+    // If we're behind the available messages.
+    if (unread_messages > current_messages) {
+      // Catch index up to the last available message.
+      *index = messages_ - current_messages;
+      // And that's the one we're going to read.
+      my_start = data_start_;
+      if (kReadIndexDebug) {
+        printf("queue: %p jumping ahead to message %d (have %d) (at %d)\n",
+               this, *index, messages_, data_start_);
+      }
+    } else {
+      // Just start reading at the first available message that we haven't yet
+      // read.
+      my_start = data_end_ - unread_messages;
+      if (kReadIndexDebug) {
+        printf("queue: %p original read from %d\n", this, my_start);
+      }
+      if (data_start_ < data_end_) {
+        assert(my_start >= 0);
+      }
+      if (my_start < 0) my_start += data_length_;
+    }
+
+    if (kReadDebug) {
+      printf("queue: %p reading from d1: %d\n", this, my_start);
+    }
+    // We have to be either after the start or before the end, even if the queue
+    // is wrapped around (should be both if it's not).
+    assert((my_start >= data_start_) || (my_start < data_end_));
+    // More sanity checking.
+    assert((my_start >= 0) && (my_start < data_length_));
+    msg = data_[my_start];
+    if (!(options & kPeek)) ++(*index);
+  }
+  IncrementMessageReferenceCount(msg);
+
+  ReadCommonEnd();
+  return msg;
+}
+
+int RawQueue::FreeMessages() const {
+  int r = 0;
+  MessageHeader *header = free_messages_;
+  while (header != nullptr) {
+    ++r;
+    header = header->next;
+  }
+  return r;
+}
+
+}  // namespace aos
diff --git a/aos/linux_code/ipc_lib/queue.h b/aos/linux_code/ipc_lib/queue.h
new file mode 100644
index 0000000..828e8f4
--- /dev/null
+++ b/aos/linux_code/ipc_lib/queue.h
@@ -0,0 +1,228 @@
+#ifndef AOS_LINUX_CODE_IPC_LIB_QUEUE_H_
+#define AOS_LINUX_CODE_IPC_LIB_QUEUE_H_
+
+#include "aos/linux_code/ipc_lib/shared_mem.h"
+#include "aos/common/mutex.h"
+#include "aos/common/condition.h"
+#include "aos/common/util/options.h"
+#include "aos/common/logging/logging.h"
+
+// TODO(brians) add valgrind client requests to the queue and shared_mem_malloc
+// code to make checking for leaks work better
+// <http://www.valgrind.org/docs/manual/mc-manual.html#mc-manual.mempools>
+// describes how
+
+// Any pointers returned from these functions can be safely passed to other
+// processes because they are all shared memory pointers.
+// IMPORTANT: Any message pointer must be passed back in some way
+// (FreeMessage and WriteMessage are common ones) or the
+// application will leak shared memory.
+// NOTE: Taking a message from ReadMessage and then passing it to WriteMessage
+// might work, but it is not guaranteed to.
+
+namespace aos {
+
+// Queues are the primary way to use shared memory. Basic use consists of
+// calling Queue::Fetch and then reading and/or writing messages.
+// Queues (as the name suggests) are a FIFO stack of messages. Each combination
+// of name and type signature will result in a different queue, which means
+// that if you only recompile some code that uses differently sized messages,
+// it will simply use a different queue than the old code.
+class RawQueue {
+ public:
+  // Retrieves (and creates if necessary) a queue. Each combination of name and
+  // signature refers to a completely independent queue.
+  // length is how large each message will be
+  // hash can differentiate multiple otherwise identical queues
+  // queue_length is how many messages the queue will be able to hold
+  // Will never return NULL.
+  static RawQueue *Fetch(const char *name, size_t length, int hash,
+                         int queue_length);
+  // Same as above, except sets up the returned queue so that it will put
+  // messages on *recycle when they are freed (after they have been released by
+  // all other readers/writers and are not in the queue).
+  // recycle_queue_length determines how many freed messages will be kept.
+  // Other code can retrieve the 2 queues separately (the recycle queue will
+  // have the same length and hash as the main one). However, any frees made
+  // using a queue with only (name,length,hash,queue_length) before the
+  // recycle queue has been associated with it will not go on to the recycle
+  // queue.
+  // NOTE: calling this function with the same (name,length,hash,queue_length)
+  // but multiple recycle_queue_lengths will result in each freed message being
+  // put onto an undefined one of the recycle queues.
+  // Will never return NULL.
+  static RawQueue *Fetch(const char *name, size_t length, int hash,
+                         int queue_length, int recycle_hash,
+                         int recycle_queue_length, RawQueue **recycle);
+
+  // Doesn't update the currently read index (the read messages in the queue or
+  // the index). This means the returned message (and any others skipped with
+  // kFromEnd) will be left in the queue.
+  // For reading only.
+  // Not valid for ReadMessageIndex combined with kFromEnd.
+  static constexpr Options<RawQueue>::Option kPeek{0x0001};
+  // Reads the last message in the queue instead of just the next one.
+  // NOTE: This removes all of the messages until the last one from the queue
+  // (which means that nobody else will read them).
+  // For reading only.
+  // Not valid for ReadMessageIndex combined with kPeek.
+  static constexpr Options<RawQueue>::Option kFromEnd{0x0002};
+  // Causes reads to return NULL and writes to fail instead of waiting.
+  // For reading and writing.
+  static constexpr Options<RawQueue>::Option kNonBlock{0x0004};
+  // Causes things to block.
+  // For reading and writing.
+  static constexpr Options<RawQueue>::Option kBlock{0x0008};
+  // Causes writes to overwrite the oldest message in the queue instead of
+  // blocking.
+  // For writing only.
+  static constexpr Options<RawQueue>::Option kOverride{0x0010};
+
+  // Writes a message into the queue.
+  // This function takes ownership of msg.
+  // NOTE: msg must point to a valid message from this queue
+  // Returns true on success. A return value of false means msg has already been
+  // freed.
+  bool WriteMessage(void *msg, Options<RawQueue> options) {
+    static constexpr Options<RawQueue> kWriteFailureOptions =
+        kNonBlock | kBlock | kOverride;
+    if (!options.NoOthersSet(kWriteFailureOptions)) {
+      LOG(FATAL, "illegal write options in %x\n", options.printable());
+    }
+    if (!options.ExactlyOneSet(kWriteFailureOptions)) {
+      LOG(FATAL, "invalid write options %x\n", options.printable());
+    }
+    return DoWriteMessage(msg, options);
+  }
+
+  // Reads a message out of the queue.
+  // The return value will have at least the length of this queue's worth of
+  // valid data where it's pointing to.
+  // The return value is const because other people might be viewing the same
+  // messsage. Do not cast the const away!
+  // IMPORTANT: The return value (if not NULL) must eventually be passed to
+  // FreeMessage.
+  const void *ReadMessage(Options<RawQueue> options) {
+    CheckReadOptions(options);
+    return DoReadMessage(options);
+  }
+  // The same as ReadMessage, except it will never return the
+  // same message twice (when used with the same index argument). However,
+  // may not return some messages that pass through the queue.
+  // *index should start as 0. index does not have to be in shared memory, but
+  // it can be.
+  // Calling with both kPeek and kFromEnd in options isn't valid because that
+  // would mean ignoring index, which would make this function the same as
+  // ReadMessage (which should be used instead).
+  const void *ReadMessageIndex(Options<RawQueue> options, int *index) {
+    CheckReadOptions(options);
+    static constexpr Options<RawQueue> kFromEndAndPeek = kFromEnd | kPeek;
+    if (options.AllSet(kFromEndAndPeek)) {
+      LOG(FATAL, "ReadMessageIndex(kFromEnd | kPeek) is not allowed\n");
+    }
+    return DoReadMessageIndex(options, index);
+  }
+
+  // Retrieves ("allocates") a message that can then be written to the queue.
+  // NOTE: the return value will be completely uninitialized
+  // The return value will have at least the length of this queue's worth of
+  // valid memory where it's pointing to.
+  // Returns NULL for error.
+  // IMPORTANT: The return value (if not NULL) must eventually be passed to
+  // FreeMessage or WriteMessage.
+  void *GetMessage();
+
+  // It is ok to call this method with a NULL msg.
+  void FreeMessage(const void *msg) {
+    if (msg != NULL) DecrementMessageReferenceCount(msg);
+  }
+
+  // UNSAFE! Returns the number of free messages we have. Only safe to use when
+  // only 1 task is using this object (ie in tests).
+  int FreeMessages() const;
+
+ private:
+  struct MessageHeader;
+
+  // The public wrappers around these are inlined and do argument checking.
+  bool DoWriteMessage(void *msg, Options<RawQueue> options);
+  const void *DoReadMessage(Options<RawQueue> options);
+  const void *DoReadMessageIndex(Options<RawQueue> options, int *index);
+  void CheckReadOptions(Options<RawQueue> options) {
+    static constexpr Options<RawQueue> kValidOptions =
+        kPeek | kFromEnd | kNonBlock | kBlock;
+    if (!options.NoOthersSet(kValidOptions)) {
+      LOG(FATAL, "illegal read options in %x\n", options.printable());
+    }
+    static constexpr Options<RawQueue> kBlockChoices = kNonBlock | kBlock;
+    if (!options.ExactlyOneSet(kBlockChoices)) {
+      LOG(FATAL, "invalid read options %x\n", options.printable());
+    }
+  }
+
+  // Adds 1 to the given index and handles wrapping correctly.
+  int index_add1(int index);
+
+  bool is_readable() { return data_end_ != data_start_; }
+  bool is_writable() { return index_add1(data_end_) != data_start_; }
+
+  // These next 4 allow finding the right one.
+  const char *name_;
+  size_t length_;
+  int hash_;
+  int queue_length_;
+  // The next one in the linked list of queues.
+  RawQueue *next_;
+
+  RawQueue *recycle_;
+
+  Mutex data_lock_;  // protects operations on data_ etc
+  // Always gets broadcasted to because different readers might have different
+  // ideas of what "readable" means (ie ones using separated indices).
+  Condition readable_;
+  Condition writable_;
+  int data_length_;  // max length into data + 1
+  int data_start_;  // is an index into data
+  int data_end_;  // is an index into data
+  int messages_;  // that have passed through
+  void **data_;  // array of messages (with headers)
+
+  size_t msg_length_;  // sizeof(each message) including the header
+  // A pointer to the first in the linked list of free messages.
+  MessageHeader *free_messages_;
+
+  // Keeps track of if the queue was writable before a read so we can Signal() a
+  // reader if we transition it.
+  bool writable_start_;
+
+  // True iff somebody is currently Wait()ing on readable_.
+  // Set to true by each reader before calling Wait() and set back to false
+  // before the Broadcast().
+  bool readable_waiting_;
+
+  // Actually frees the given message.
+  void DoFreeMessage(const void *msg);
+  // Calls DoFreeMessage if appropriate.
+  void DecrementMessageReferenceCount(const void *msg);
+  // Only does the actual incrementing of the reference count.
+  void IncrementMessageReferenceCount(const void *msg) const;
+
+  // Must be called with data_lock_ locked.
+  // *read_data will be initialized.
+  // Returns with a readable message in data_ or false.
+  bool ReadCommonStart(Options<RawQueue> options, int *index);
+  // Deals with setting/unsetting readable_ and writable_.
+  // Must be called after data_lock_ has been unlocked.
+  // read_data should be the same thing that was passed in to ReadCommonStart.
+  void ReadCommonEnd();
+  // Returns the index of the last message.
+  // Useful for reading with kPeek.
+  int LastMessageIndex() const;
+
+  // Gets called by Fetch when necessary (with placement new).
+  RawQueue(const char *name, size_t length, int hash, int queue_length);
+};
+
+}  // namespace aos
+
+#endif  // AOS_LINUX_CODE_IPC_LIB_QUEUE_H_
diff --git a/aos/linux_code/ipc_lib/raw_queue_test.cc b/aos/linux_code/ipc_lib/raw_queue_test.cc
new file mode 100644
index 0000000..adb84b9
--- /dev/null
+++ b/aos/linux_code/ipc_lib/raw_queue_test.cc
@@ -0,0 +1,1032 @@
+#include "aos/linux_code/ipc_lib/queue.h"
+
+#include <unistd.h>
+#include <sys/mman.h>
+#include <inttypes.h>
+
+#include <ostream>
+#include <memory>
+#include <map>
+
+#include "gtest/gtest.h"
+
+#include "aos/linux_code/ipc_lib/core_lib.h"
+#include "aos/common/type_traits.h"
+#include "aos/common/queue_testutils.h"
+#include "aos/common/time.h"
+#include "aos/common/logging/logging.h"
+#include "aos/common/die.h"
+#include "aos/common/util/thread.h"
+#include "aos/common/util/options.h"
+#include "aos/common/util/death_test_log_implementation.h"
+
+using ::testing::AssertionResult;
+using ::testing::AssertionSuccess;
+using ::testing::AssertionFailure;
+using ::aos::common::testing::GlobalCoreInstance;
+
+namespace aos {
+namespace testing {
+
+// The same constant from queue.cc. This will have to be updated if that one is.
+const int kExtraMessages = 20;
+
+class RawQueueTest : public ::testing::Test {
+ protected:
+  static const size_t kFailureSize = 400;
+  static char *fatal_failure;
+ private:
+  enum class ResultType : uint8_t {
+    NotCalled,
+    Called,
+    Returned,
+  };
+  const std::string ResultTypeString(volatile const ResultType &result) {
+    switch (result) {
+      case ResultType::Returned:
+        return "Returned";
+      case ResultType::Called:
+        return "Called";
+      case ResultType::NotCalled:
+        return "NotCalled";
+      default:
+        return std::string("unknown(") +
+               ::std::to_string(static_cast<uint8_t>(result)) + ")";
+    }
+  }
+  static_assert(aos::shm_ok<ResultType>::value,
+                "this will get put in shared memory");
+  template<typename T>
+  struct FunctionToCall {
+    FunctionToCall() : result(ResultType::NotCalled), started() {
+    }
+
+    volatile ResultType result;
+    bool expected;
+    void (*function)(T*, char*);
+    T *arg;
+    volatile char failure[kFailureSize];
+    aos_futex started;
+  };
+  template<typename T>
+  static void Hangs_(FunctionToCall<T> *const to_call) {
+    time::SleepFor(time::Time::InSeconds(0.01));
+    ASSERT_EQ(1, futex_set(&to_call->started));
+    to_call->result = ResultType::Called;
+    to_call->function(to_call->arg, const_cast<char *>(to_call->failure));
+    to_call->result = ResultType::Returned;
+  }
+
+  // How long until a function is considered to have hung.
+  static constexpr time::Time kHangTime = time::Time::InSeconds(0.09);
+  // How long to sleep after forking (for debugging).
+  static constexpr time::Time kForkSleep = time::Time::InSeconds(0);
+
+  // Represents a process that has been forked off. The destructor kills the
+  // process and wait(2)s for it.
+  class ForkedProcess {
+   public:
+    ForkedProcess(pid_t pid, aos_futex *done)
+        : pid_(pid), done_(done), exiting_(false) {};
+    ~ForkedProcess() {
+      if (!exiting_) {
+        if (kill(pid_, SIGTERM) == -1) {
+          if (errno == ESRCH) {
+            printf("process %jd was already dead\n",
+                   static_cast<intmax_t>(pid_));
+          } else {
+            PLOG(FATAL, "kill(SIGKILL, %jd) failed",
+                 static_cast<intmax_t>(pid_));
+          }
+        }
+      }
+      const pid_t ret = wait(NULL);
+      if (ret == -1) {
+        LOG(WARNING, "wait(NULL) failed."
+            " child %jd might still be alive\n",
+            static_cast<intmax_t>(pid_));
+      } else if (ret == 0) {
+        LOG(WARNING, "child %jd wasn't waitable. it might still be alive\n",
+            static_cast<intmax_t>(pid_));
+      } else if (ret != pid_) {
+        LOG(WARNING, "child %d is now confirmed dead"
+            ", but child %jd might still be alive\n",
+            ret, static_cast<intmax_t>(pid_));
+      }
+    }
+
+    enum class JoinResult {
+      Finished, Hung, Error
+    };
+    JoinResult Join(time::Time timeout = kHangTime) {
+      timespec done_timeout = (kForkSleep + timeout).ToTimespec();
+      switch (futex_wait_timeout(done_, &done_timeout)) {
+        case 2:
+          return JoinResult::Hung;
+        case 0:
+          exiting_ = true;
+          return JoinResult::Finished;
+        default:
+          return JoinResult::Error;
+      }
+    }
+
+   private:
+    const pid_t pid_;
+    aos_futex *const done_;
+    // True iff we know that the process is already exiting.
+    bool exiting_;
+  } __attribute__((unused));
+
+  // State for HangsFork and HangsCheck.
+  typedef uint8_t ChildID;
+  static void ReapExitHandler() {
+    for (auto it = children_.begin(); it != children_.end(); ++it) {
+      delete it->second;
+    }
+  }
+  static std::map<ChildID, ForkedProcess *> children_;
+  std::map<ChildID, FunctionToCall<void> *> to_calls_;
+
+  void SetUp() override {
+    ::testing::Test::SetUp();
+
+    SetDieTestMode(true);
+
+    fatal_failure = static_cast<char *>(shm_malloc(sizeof(fatal_failure)));
+    static bool registered = false;
+    if (!registered) {
+      atexit(ReapExitHandler);
+      registered = true;
+    }
+  }
+
+ protected:
+  // function gets called with arg in a forked process.
+  // Leaks shared memory.
+  template<typename T> __attribute__((warn_unused_result))
+  std::unique_ptr<ForkedProcess> ForkExecute(void (*function)(T*), T *arg) {
+    aos_futex *done = static_cast<aos_futex *>(shm_malloc_aligned(
+            sizeof(*done), alignof(aos_futex)));
+    *done = 0;
+    const pid_t pid = fork();
+    switch (pid) {
+      case 0:  // child
+        if (kForkSleep != time::Time(0, 0)) {
+          LOG(INFO, "pid %jd sleeping for %ds%dns\n",
+              static_cast<intmax_t>(getpid()),
+              kForkSleep.sec(), kForkSleep.nsec());
+          time::SleepFor(kForkSleep);
+        }
+        ::aos::common::testing::PreventExit();
+        function(arg);
+        CHECK_NE(-1, futex_set(done));
+        exit(EXIT_SUCCESS);
+      case -1:  // parent failure
+        PLOG(ERROR, "fork() failed");
+        return std::unique_ptr<ForkedProcess>();
+      default:  // parent
+        return std::unique_ptr<ForkedProcess>(new ForkedProcess(pid, done));
+    }
+  }
+
+  // Checks whether or not the given function hangs.
+  // expected is whether to return success or failure if the function hangs
+  // NOTE: There are other reasons for it to return a failure than the function
+  // doing the wrong thing.
+  // Leaks shared memory.
+  template<typename T>
+  AssertionResult Hangs(void (*function)(T*, char*), T *arg, bool expected) {
+    AssertionResult fork_result(HangsFork<T>(function, arg, expected, 0));
+    if (!fork_result) {
+      return fork_result;
+    }
+    return HangsCheck(0);
+  }
+  // Starts the first part of Hangs.
+  // Use HangsCheck to get the result.
+  // Returns whether the fork succeeded or not, NOT whether or not the hang
+  // check succeeded.
+  template<typename T>
+  AssertionResult HangsFork(void (*function)(T*, char *), T *arg,
+                            bool expected, ChildID id) {
+    static_assert(aos::shm_ok<FunctionToCall<T>>::value,
+                  "this is going into shared memory");
+    FunctionToCall<T> *const to_call =
+        static_cast<FunctionToCall<T> *>(
+            shm_malloc_aligned(sizeof(*to_call), alignof(FunctionToCall<T>)));
+    new (to_call) FunctionToCall<T>();
+    to_call->function = function;
+    to_call->arg = arg;
+    to_call->expected = expected;
+    to_call->failure[0] = '\0';
+    static_cast<char *>(fatal_failure)[0] = '\0';
+    children_[id] = ForkExecute(Hangs_, to_call).release();
+    if (!children_[id]) return AssertionFailure() << "ForkExecute failed";
+    CHECK_EQ(0, futex_wait(&to_call->started));
+    to_calls_[id] = reinterpret_cast<FunctionToCall<void> *>(to_call);
+    return AssertionSuccess();
+  }
+  // Checks whether or not a function hung like it was supposed to.
+  // Use HangsFork first.
+  // NOTE: calls to HangsFork and HangsCheck with the same id argument will
+  // correspond, but they do not nest. Also, id 0 is used by Hangs.
+  // Return value is the same as Hangs.
+  AssertionResult HangsCheck(ChildID id) {
+    std::unique_ptr<ForkedProcess> child(children_[id]);
+    children_.erase(id);
+    const ForkedProcess::JoinResult result = child->Join();
+    if (to_calls_[id]->failure[0] != '\0') {
+      return AssertionFailure() << "function says: "
+          << const_cast<char *>(to_calls_[id]->failure);
+    }
+    if (result == ForkedProcess::JoinResult::Finished) {
+      return !to_calls_[id]->expected ? AssertionSuccess() : (AssertionFailure()
+          << "something happened and the the test only got to "
+          << ResultTypeString(to_calls_[id]->result));
+    } else {
+      if (to_calls_[id]->result == ResultType::Called) {
+        return to_calls_[id]->expected ? AssertionSuccess() :
+            AssertionFailure();
+      } else if (result == ForkedProcess::JoinResult::Error) {
+        return AssertionFailure() << "error joining child";
+      } else {
+        if (to_calls_[id]->result == ResultType::NotCalled) {
+          return AssertionFailure() << "stuff took too long getting started";
+        }
+        return AssertionFailure() << "something weird happened";
+      }
+    }
+  }
+#define EXPECT_HANGS(function, arg) \
+  EXPECT_HANGS_COND(function, arg, true, EXPECT_TRUE)
+#define EXPECT_RETURNS(function, arg) \
+  EXPECT_HANGS_COND(function, arg, false, EXPECT_TRUE)
+#define EXPECT_RETURNS_FAILS(function, arg) \
+  EXPECT_HANGS_COND(function, arg, false, EXPECT_FALSE)
+#define EXPECT_HANGS_COND(function, arg, hangs, cond) do { \
+  cond(Hangs(function, arg, hangs)); \
+  if (fatal_failure[0] != '\0') { \
+    FAIL() << fatal_failure; \
+  } \
+} while (false)
+
+  struct TestMessage {
+    // Some contents because we don't really want to test empty messages.
+    int16_t data;
+  };
+  struct MessageArgs {
+    RawQueue *const queue;
+    Options<RawQueue> flags;
+    int16_t data;  // -1 means NULL expected
+  };
+  static void WriteTestMessage(MessageArgs *args, char *failure) {
+    TestMessage *msg = static_cast<TestMessage *>(args->queue->GetMessage());
+    if (msg == NULL) {
+      snprintf(fatal_failure, kFailureSize,
+               "couldn't get_msg from %p", args->queue);
+      return;
+    }
+    msg->data = args->data;
+    if (!args->queue->WriteMessage(msg, args->flags)) {
+      snprintf(failure, kFailureSize, "%p->WriteMessage(%p, %x) failed",
+               args->queue, msg, args->flags.printable());
+    }
+  }
+  static void ReadTestMessage(MessageArgs *args, char *failure) {
+    const TestMessage *msg = static_cast<const TestMessage *>(
+        args->queue->ReadMessage(args->flags));
+    if (msg == NULL) {
+      if (args->data != -1) {
+        snprintf(failure, kFailureSize,
+                 "expected data of %" PRId16 " but got NULL message",
+                 args->data);
+      }
+    } else {
+      if (args->data != msg->data) {
+        snprintf(failure, kFailureSize,
+                 "expected data of %" PRId16 " but got %" PRId16 " instead",
+                 args->data, msg->data);
+      }
+      args->queue->FreeMessage(msg);
+    }
+  }
+
+  void PushMessage(RawQueue *queue, uint16_t data) {
+    TestMessage *message = static_cast<TestMessage *>(queue->GetMessage());
+    message->data = data;
+    ASSERT_TRUE(queue->WriteMessage(message, RawQueue::kOverride));
+  }
+
+ private:
+  GlobalCoreInstance my_core;
+};
+
+char *RawQueueTest::fatal_failure;
+std::map<RawQueueTest::ChildID, RawQueueTest::ForkedProcess *>
+    RawQueueTest::children_;
+constexpr time::Time RawQueueTest::kHangTime;
+constexpr time::Time RawQueueTest::kForkSleep;
+
+typedef RawQueueTest RawQueueDeathTest;
+
+TEST_F(RawQueueTest, Reading) {
+  RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
+  MessageArgs args{queue, RawQueue::kBlock, -1};
+
+  args.flags = RawQueue::kNonBlock;
+  EXPECT_RETURNS(ReadTestMessage, &args);
+  args.flags = RawQueue::kNonBlock | RawQueue::kPeek;
+  EXPECT_RETURNS(ReadTestMessage, &args);
+  args.flags = RawQueue::kBlock;
+  EXPECT_HANGS(ReadTestMessage, &args);
+  args.flags = RawQueue::kPeek | RawQueue::kBlock;
+  EXPECT_HANGS(ReadTestMessage, &args);
+  args.data = 254;
+  args.flags = RawQueue::kBlock;
+  EXPECT_RETURNS(WriteTestMessage, &args);
+  args.flags = RawQueue::kPeek | RawQueue::kBlock;
+  EXPECT_RETURNS(ReadTestMessage, &args);
+  args.flags = RawQueue::kPeek | RawQueue::kBlock;
+  EXPECT_RETURNS(ReadTestMessage, &args);
+  args.flags = RawQueue::kPeek | RawQueue::kNonBlock;
+  EXPECT_RETURNS(ReadTestMessage, &args);
+  args.flags = RawQueue::kBlock;
+  EXPECT_RETURNS(ReadTestMessage, &args);
+  args.flags = RawQueue::kBlock;
+  args.data = -1;
+  EXPECT_HANGS(ReadTestMessage, &args);
+  args.flags = RawQueue::kNonBlock;
+  EXPECT_RETURNS(ReadTestMessage, &args);
+  args.flags = RawQueue::kBlock;
+  args.data = 971;
+  EXPECT_RETURNS_FAILS(ReadTestMessage, &args);
+}
+TEST_F(RawQueueTest, Writing) {
+  RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
+  MessageArgs args{queue, RawQueue::kBlock, 973};
+
+  args.flags = RawQueue::kBlock;
+  EXPECT_RETURNS(WriteTestMessage, &args);
+  args.flags = RawQueue::kBlock;
+  EXPECT_HANGS(WriteTestMessage, &args);
+  args.flags = RawQueue::kNonBlock;
+  EXPECT_RETURNS_FAILS(WriteTestMessage, &args);
+  args.flags = RawQueue::kNonBlock;
+  EXPECT_RETURNS_FAILS(WriteTestMessage, &args);
+  args.flags = RawQueue::kPeek | RawQueue::kBlock;
+  EXPECT_RETURNS(ReadTestMessage, &args);
+  args.data = 971;
+  args.flags = RawQueue::kOverride;
+  EXPECT_RETURNS(WriteTestMessage, &args);
+  args.flags = RawQueue::kOverride;
+  EXPECT_RETURNS(WriteTestMessage, &args);
+  args.flags = RawQueue::kBlock;
+  EXPECT_RETURNS(ReadTestMessage, &args);
+  args.flags = RawQueue::kNonBlock;
+  EXPECT_RETURNS(WriteTestMessage, &args);
+  args.flags = RawQueue::kBlock;
+  EXPECT_RETURNS(ReadTestMessage, &args);
+  args.flags = RawQueue::kOverride;
+  EXPECT_RETURNS(WriteTestMessage, &args);
+  args.flags = RawQueue::kBlock;
+  EXPECT_RETURNS(ReadTestMessage, &args);
+}
+
+TEST_F(RawQueueTest, MultiRead) {
+  RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
+  MessageArgs args{queue, RawQueue::kBlock, 1323};
+
+  args.flags = RawQueue::kBlock;
+  EXPECT_RETURNS(WriteTestMessage, &args);
+  args.flags = RawQueue::kBlock;
+  ASSERT_TRUE(HangsFork(ReadTestMessage, &args, true, 1));
+  ASSERT_TRUE(HangsFork(ReadTestMessage, &args, true, 2));
+  AssertionResult one = HangsCheck(1);
+  AssertionResult two = HangsCheck(2);
+  EXPECT_TRUE(one != two) << "'" <<
+      one.failure_message() << "' vs '" << two.failure_message() << "'";
+  // TODO(brians) finish this
+}
+
+// There used to be a bug where reading first without an index and then with an
+// index would crash. This test makes sure that's fixed.
+TEST_F(RawQueueTest, ReadIndexAndNot) {
+  RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
+
+  // Write a message, read it (with ReadMessage), and then write another
+  // message (before freeing the read one so the queue allocates a distinct
+  // message to use for it).
+  TestMessage *msg = static_cast<TestMessage *>(queue->GetMessage());
+  ASSERT_NE(nullptr, msg);
+  ASSERT_TRUE(queue->WriteMessage(msg, RawQueue::kBlock));
+  const void *read_msg = queue->ReadMessage(RawQueue::kBlock);
+  EXPECT_NE(nullptr, read_msg);
+  msg = static_cast<TestMessage *>(queue->GetMessage());
+  queue->FreeMessage(read_msg);
+  ASSERT_NE(nullptr, msg);
+  ASSERT_TRUE(queue->WriteMessage(msg, RawQueue::kBlock));
+
+  int index = 0;
+  const void *second_read_msg =
+      queue->ReadMessageIndex(RawQueue::kBlock, &index);
+  EXPECT_NE(nullptr, second_read_msg);
+  EXPECT_NE(read_msg, second_read_msg)
+      << "We already took that message out of the queue.";
+}
+
+TEST_F(RawQueueTest, Recycle) {
+  // TODO(brians) basic test of recycle queue
+  // include all of the ways a message can get into the recycle queue
+  RawQueue *recycle_queue = reinterpret_cast<RawQueue *>(23);
+  RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage),
+                                          1, 2, 2, 2, &recycle_queue);
+  ASSERT_NE(reinterpret_cast<RawQueue *>(23), recycle_queue);
+  MessageArgs args{queue, RawQueue::kBlock, 973},
+      recycle{recycle_queue, RawQueue::kBlock, 973};
+
+  args.flags = RawQueue::kBlock;
+  EXPECT_RETURNS(WriteTestMessage, &args);
+  EXPECT_HANGS(ReadTestMessage, &recycle);
+  args.data = 254;
+  EXPECT_RETURNS(WriteTestMessage, &args);
+  EXPECT_HANGS(ReadTestMessage, &recycle);
+  args.data = 971;
+  args.flags = RawQueue::kOverride;
+  EXPECT_RETURNS(WriteTestMessage, &args);
+  recycle.flags = RawQueue::kBlock;
+  EXPECT_RETURNS(ReadTestMessage, &recycle);
+
+  EXPECT_HANGS(ReadTestMessage, &recycle);
+
+  TestMessage *msg = static_cast<TestMessage *>(queue->GetMessage());
+  ASSERT_TRUE(msg != NULL);
+  msg->data = 341;
+  queue->FreeMessage(msg);
+  recycle.data = 341;
+  EXPECT_RETURNS(ReadTestMessage, &recycle);
+
+  EXPECT_HANGS(ReadTestMessage, &recycle);
+
+  args.data = 254;
+  args.flags = RawQueue::kPeek | RawQueue::kBlock;
+  EXPECT_RETURNS(ReadTestMessage, &args);
+  recycle.flags = RawQueue::kBlock;
+  EXPECT_HANGS(ReadTestMessage, &recycle);
+  args.flags = RawQueue::kBlock;
+  EXPECT_RETURNS(ReadTestMessage, &args);
+  recycle.data = 254;
+  EXPECT_RETURNS(ReadTestMessage, &recycle);
+}
+
+// Makes sure that when a message doesn't get written with kNonBlock it does get
+// freed.
+TEST_F(RawQueueTest, NonBlockFailFree) {
+  RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
+
+  void *message1 = queue->GetMessage();
+  void *message2 = queue->GetMessage();
+  ASSERT_TRUE(queue->WriteMessage(message1, RawQueue::kNonBlock));
+  ASSERT_FALSE(queue->WriteMessage(message2, RawQueue::kNonBlock));
+  EXPECT_EQ(message2, queue->GetMessage());
+}
+
+// All of the tests from here down are designed to test every branch to
+// make sure it does what it's supposed to. They are generally pretty repetitive
+// and boring, and some of them may duplicate other tests above, but these ones
+// make it a lot easier to figure out what's wrong with bugs not related to race
+// conditions.
+
+TEST_F(RawQueueTest, ReadIndexNotFull) {
+  RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
+  const TestMessage *message, *peek_message;
+
+  EXPECT_EQ(0, kExtraMessages + 2 - queue->FreeMessages());
+  PushMessage(queue, 971);
+  EXPECT_EQ(1, kExtraMessages + 2 - queue->FreeMessages());
+
+  int index = 0;
+  peek_message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
+  message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(message, peek_message);
+  EXPECT_EQ(971, message->data);
+  EXPECT_EQ(1, index);
+  queue->FreeMessage(message);
+  queue->FreeMessage(peek_message);
+
+  PushMessage(queue, 1768);
+  EXPECT_EQ(2, kExtraMessages + 2 - queue->FreeMessages());
+  peek_message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
+  message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(message, peek_message);
+  EXPECT_EQ(1768, message->data);
+  EXPECT_EQ(2, index);
+  queue->FreeMessage(message);
+  queue->FreeMessage(peek_message);
+
+  PushMessage(queue, 254);
+  peek_message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
+  message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(message, peek_message);
+  EXPECT_EQ(254, message->data);
+  EXPECT_EQ(3, index);
+  queue->FreeMessage(message);
+  queue->FreeMessage(peek_message);
+
+  index = 0;
+  peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
+      RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
+  message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
+      RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(message, peek_message);
+  EXPECT_EQ(254, message->data);
+  EXPECT_EQ(3, index);
+  queue->FreeMessage(message);
+  queue->FreeMessage(peek_message);
+
+  EXPECT_EQ(2, kExtraMessages + 2 - queue->FreeMessages());
+}
+
+TEST_F(RawQueueTest, ReadIndexNotBehind) {
+  RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
+  const TestMessage *message, *peek_message;
+
+  EXPECT_EQ(0, kExtraMessages + 2 - queue->FreeMessages());
+  PushMessage(queue, 971);
+  EXPECT_EQ(1, kExtraMessages + 2 - queue->FreeMessages());
+  PushMessage(queue, 1768);
+  EXPECT_EQ(2, kExtraMessages + 2 - queue->FreeMessages());
+
+  int index = 0;
+  peek_message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
+  message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(message, peek_message);
+  EXPECT_EQ(971, message->data);
+  EXPECT_EQ(1, index);
+  queue->FreeMessage(message);
+  queue->FreeMessage(peek_message);
+
+  index = 0;
+  peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
+      RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
+  message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
+      RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(message, peek_message);
+  EXPECT_EQ(1768, message->data);
+  EXPECT_EQ(2, index);
+  queue->FreeMessage(message);
+}
+
+TEST_F(RawQueueTest, ReadIndexLittleBehindNotFull) {
+  RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
+  const TestMessage *message, *peek_message;
+
+  PushMessage(queue, 971);
+  PushMessage(queue, 1768);
+  ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
+
+  int index = 0;
+
+  peek_message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
+  message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(message, peek_message);
+  EXPECT_EQ(1768, message->data);
+  EXPECT_EQ(2, index);
+  queue->FreeMessage(message);
+  queue->FreeMessage(peek_message);
+
+  index = 0;
+  peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
+      RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
+  message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
+      RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(message, peek_message);
+  EXPECT_EQ(1768, message->data);
+  EXPECT_EQ(2, index);
+  queue->FreeMessage(message);
+}
+
+TEST_F(RawQueueTest, ReadIndexMoreBehind) {
+  RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
+  const TestMessage *message, *peek_message;
+
+  PushMessage(queue, 971);
+  PushMessage(queue, 1768);
+  ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
+  PushMessage(queue, 254);
+
+  int index = 0;
+
+  peek_message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
+  message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(message, peek_message);
+  EXPECT_EQ(1768, message->data);
+  EXPECT_EQ(2, index);
+  queue->FreeMessage(message);
+  queue->FreeMessage(peek_message);
+
+  peek_message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
+  message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(message, peek_message);
+  EXPECT_EQ(254, message->data);
+  EXPECT_EQ(3, index);
+  queue->FreeMessage(message);
+  queue->FreeMessage(peek_message);
+
+  index = 0;
+  peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
+      RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
+  message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
+      RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(message, peek_message);
+  EXPECT_EQ(254, message->data);
+  EXPECT_EQ(3, index);
+  queue->FreeMessage(message);
+}
+
+TEST_F(RawQueueTest, ReadIndexMoreBehindNotFull) {
+  RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
+  const TestMessage *message, *peek_message;
+
+  PushMessage(queue, 971);
+  PushMessage(queue, 1768);
+  ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
+  PushMessage(queue, 254);
+  ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
+
+  int index = 0;
+
+  peek_message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
+  message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(message, peek_message);
+  EXPECT_EQ(254, message->data);
+  EXPECT_EQ(3, index);
+  queue->FreeMessage(message);
+  queue->FreeMessage(peek_message);
+
+  index = 0;
+  peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
+      RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
+  message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
+      RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(message, peek_message);
+  EXPECT_EQ(254, message->data);
+  EXPECT_EQ(3, index);
+  queue->FreeMessage(message);
+}
+
+TEST_F(RawQueueTest, ReadIndexLotBehind) {
+  RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
+  const TestMessage *message, *peek_message;
+
+  PushMessage(queue, 971);
+  PushMessage(queue, 1768);
+  {
+    const void *message1, *message2;
+    message1 = queue->ReadMessage(RawQueue::kNonBlock);
+    ASSERT_NE(nullptr, message1);
+    PushMessage(queue, 254);
+    message2 = queue->ReadMessage(RawQueue::kNonBlock);
+    ASSERT_NE(nullptr, message2);
+    PushMessage(queue, 973);
+    EXPECT_EQ(4, kExtraMessages + 2 - queue->FreeMessages());
+    queue->FreeMessage(message1);
+    EXPECT_EQ(3, kExtraMessages + 2 - queue->FreeMessages());
+    queue->FreeMessage(message2);
+    EXPECT_EQ(2, kExtraMessages + 2 - queue->FreeMessages());
+  }
+
+  int index = 0;
+
+  peek_message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
+  message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(message, peek_message);
+  EXPECT_EQ(254, message->data);
+  EXPECT_EQ(3, index);
+  queue->FreeMessage(message);
+  queue->FreeMessage(peek_message);
+
+  peek_message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
+  message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(message, peek_message);
+  EXPECT_EQ(973, message->data);
+  EXPECT_EQ(4, index);
+  queue->FreeMessage(message);
+  queue->FreeMessage(peek_message);
+
+  index = 0;
+  peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
+      RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
+  message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
+      RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(message, peek_message);
+  EXPECT_EQ(973, message->data);
+  EXPECT_EQ(4, index);
+  queue->FreeMessage(message);
+}
+
+TEST_F(RawQueueTest, ReadIndexLotBehindNotFull) {
+  RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
+  const TestMessage *message, *peek_message;
+
+  PushMessage(queue, 971);
+  PushMessage(queue, 1768);
+  ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
+  PushMessage(queue, 254);
+  ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
+  PushMessage(queue, 973);
+  ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
+
+  int index = 0;
+
+  peek_message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
+  message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(message, peek_message);
+  EXPECT_EQ(973, message->data);
+  EXPECT_EQ(4, index);
+  queue->FreeMessage(message);
+  queue->FreeMessage(peek_message);
+
+  index = 0;
+  peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
+      RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
+  message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
+      RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(message, peek_message);
+  EXPECT_EQ(973, message->data);
+  EXPECT_EQ(4, index);
+  queue->FreeMessage(message);
+}
+
+TEST_F(RawQueueTest, ReadIndexEvenMoreBehind) {
+  RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
+  const TestMessage *message, *peek_message;
+
+  PushMessage(queue, 971);
+  PushMessage(queue, 1768);
+  ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
+  PushMessage(queue, 254);
+  ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
+  PushMessage(queue, 973);
+  ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
+  PushMessage(queue, 1114);
+
+  int index = 0;
+
+  peek_message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
+  message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(message, peek_message);
+  EXPECT_EQ(973, message->data);
+  EXPECT_EQ(4, index);
+  queue->FreeMessage(message);
+  queue->FreeMessage(peek_message);
+
+  peek_message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
+  message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(message, peek_message);
+  EXPECT_EQ(1114, message->data);
+  EXPECT_EQ(5, index);
+  queue->FreeMessage(message);
+  queue->FreeMessage(peek_message);
+
+  index = 0;
+  peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
+      RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
+  message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
+      RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(message, peek_message);
+  EXPECT_EQ(1114, message->data);
+  EXPECT_EQ(5, index);
+  queue->FreeMessage(message);
+}
+
+TEST_F(RawQueueTest, ReadIndexEvenMoreBehindNotFull) {
+  RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
+  const TestMessage *message, *peek_message;
+
+  PushMessage(queue, 971);
+  PushMessage(queue, 1768);
+  ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
+  PushMessage(queue, 254);
+  ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
+  PushMessage(queue, 973);
+  ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
+  PushMessage(queue, 1114);
+  ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
+
+  int index = 0;
+
+  peek_message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
+  message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(message, peek_message);
+  EXPECT_EQ(1114, message->data);
+  EXPECT_EQ(5, index);
+  queue->FreeMessage(message);
+  queue->FreeMessage(peek_message);
+
+  index = 0;
+  peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
+      RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
+  message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
+      RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(message, peek_message);
+  EXPECT_EQ(1114, message->data);
+  EXPECT_EQ(5, index);
+  queue->FreeMessage(message);
+}
+
+TEST_F(RawQueueTest, MessageReferenceCounts) {
+  RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
+  const void *message1, *message2;
+
+  EXPECT_EQ(0, kExtraMessages + 2 - queue->FreeMessages());
+  message1 = queue->GetMessage();
+  EXPECT_NE(nullptr, message1);
+  EXPECT_EQ(1, kExtraMessages + 2 - queue->FreeMessages());
+  message2 = queue->GetMessage();
+  EXPECT_NE(nullptr, message2);
+  EXPECT_EQ(2, kExtraMessages + 2 - queue->FreeMessages());
+  queue->FreeMessage(message1);
+  EXPECT_EQ(1, kExtraMessages + 2 - queue->FreeMessages());
+  queue->FreeMessage(message2);
+  EXPECT_EQ(0, kExtraMessages + 2 - queue->FreeMessages());
+}
+
+// Tests that writing with kNonBlock fails and frees the message.
+TEST_F(RawQueueTest, WriteDontBlock) {
+  RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
+  void *message;
+
+  PushMessage(queue, 971);
+  int free_before = queue->FreeMessages();
+  message = queue->GetMessage();
+  ASSERT_NE(nullptr, message);
+  EXPECT_NE(free_before, queue->FreeMessages());
+  EXPECT_FALSE(queue->WriteMessage(message, RawQueue::kNonBlock));
+  EXPECT_EQ(free_before, queue->FreeMessages());
+}
+
+// Tests that writing with kOverride pushes the last message out of the queue.
+TEST_F(RawQueueTest, WriteOverride) {
+  RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
+  TestMessage *message1;
+
+  PushMessage(queue, 971);
+  PushMessage(queue, 1768);
+  int free_before = queue->FreeMessages();
+  message1 = static_cast<TestMessage *>(queue->GetMessage());
+  ASSERT_NE(nullptr, message1);
+  EXPECT_NE(free_before, queue->FreeMessages());
+  message1->data = 254;
+  EXPECT_TRUE(queue->WriteMessage(message1, RawQueue::kOverride));
+  EXPECT_EQ(free_before, queue->FreeMessages());
+
+  const TestMessage *message2;
+  message2 =
+      static_cast<const TestMessage *>(queue->ReadMessage(RawQueue::kNonBlock));
+  EXPECT_EQ(1768, message2->data);
+  queue->FreeMessage(message2);
+  EXPECT_EQ(free_before + 1, queue->FreeMessages());
+  message2 =
+      static_cast<const TestMessage *>(queue->ReadMessage(RawQueue::kNonBlock));
+  EXPECT_EQ(254, message2->data);
+  queue->FreeMessage(message2);
+  EXPECT_EQ(free_before + 2, queue->FreeMessages());
+}
+
+// Makes sure that ThreadSanitizer doesn't catch any issues freeing from
+// multiple threads at once.
+TEST_F(RawQueueTest, MultiThreadedFree) {
+  RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
+  PushMessage(queue, 971);
+  int free_before = queue->FreeMessages();
+
+  const void *const message1 =
+      queue->ReadMessage(RawQueue::kPeek | RawQueue::kNonBlock);
+  const void *const message2 =
+      queue->ReadMessage(RawQueue::kPeek | RawQueue::kNonBlock);
+  ASSERT_NE(nullptr, message1);
+  ASSERT_NE(nullptr, message2);
+  EXPECT_EQ(free_before, queue->FreeMessages());
+  util::FunctionThread t1([message1, queue](util::Thread *) {
+    queue->FreeMessage(message1);
+  });
+  util::FunctionThread t2([message2, queue](util::Thread *) {
+    queue->FreeMessage(message2);
+  });
+  t1.Start();
+  t2.Start();
+  t1.WaitUntilDone();
+  t2.WaitUntilDone();
+  EXPECT_EQ(free_before, queue->FreeMessages());
+}
+
+TEST_F(RawQueueDeathTest, OptionsValidation) {
+  RawQueue *const queue = RawQueue::Fetch("Queue", 1, 1, 1);
+
+  EXPECT_DEATH(
+      {
+        logging::AddImplementation(new util::DeathTestLogImplementation());
+        queue->WriteMessage(nullptr, RawQueue::kPeek);
+      },
+      ".*illegal write option.*");
+  EXPECT_DEATH(
+      {
+        logging::AddImplementation(new util::DeathTestLogImplementation());
+        queue->WriteMessage(nullptr, RawQueue::kFromEnd);
+      },
+      ".*illegal write option.*");
+  EXPECT_DEATH(
+      {
+        logging::AddImplementation(new util::DeathTestLogImplementation());
+        queue->WriteMessage(nullptr, RawQueue::kPeek | RawQueue::kFromEnd);
+      },
+      ".*illegal write option.*");
+  EXPECT_DEATH(
+      {
+        logging::AddImplementation(new util::DeathTestLogImplementation());
+        queue->WriteMessage(nullptr, RawQueue::kNonBlock | RawQueue::kBlock);
+      },
+      ".*invalid write option.*");
+
+  EXPECT_DEATH(
+      {
+        logging::AddImplementation(new util::DeathTestLogImplementation());
+        queue->ReadMessageIndex(
+            RawQueue::kBlock | RawQueue::kFromEnd | RawQueue::kPeek, nullptr);
+      },
+      ".*ReadMessageIndex.*is not allowed.*");
+  EXPECT_DEATH(
+      {
+        logging::AddImplementation(new util::DeathTestLogImplementation());
+        queue->ReadMessageIndex(RawQueue::kOverride, nullptr);
+      },
+      ".*illegal read option.*");
+  EXPECT_DEATH(
+      {
+        logging::AddImplementation(new util::DeathTestLogImplementation());
+        queue->ReadMessageIndex(RawQueue::kOverride | RawQueue::kBlock,
+                                nullptr);
+      },
+      ".*illegal read option.*");
+  EXPECT_DEATH(
+      {
+        logging::AddImplementation(new util::DeathTestLogImplementation());
+        queue->ReadMessage(RawQueue::kNonBlock | RawQueue::kBlock);
+      },
+      ".*invalid read option.*");
+}
+
+}  // namespace testing
+}  // namespace aos
diff --git a/aos/linux_code/ipc_lib/shared_mem.c b/aos/linux_code/ipc_lib/shared_mem.c
new file mode 100644
index 0000000..c43bfa2
--- /dev/null
+++ b/aos/linux_code/ipc_lib/shared_mem.c
@@ -0,0 +1,140 @@
+#include "aos/linux_code/ipc_lib/shared_mem.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "aos/linux_code/ipc_lib/core_lib.h"
+#include "aos/common/logging/logging.h"
+
+// the path for the shared memory segment. see shm_open(3) for restrictions
+#define AOS_SHM_NAME "/aos_shared_mem"
+// Size of the shared mem segment.
+// This must fit in the tmpfs for /dev/shm/
+#define SIZEOFSHMSEG (4096 * 0x3000)
+
+void init_shared_mem_core(aos_shm_core *shm_core) {
+  memset(&shm_core->time_offset, 0 , sizeof(shm_core->time_offset));
+  memset(&shm_core->msg_alloc_lock, 0, sizeof(shm_core->msg_alloc_lock));
+  shm_core->queues.pointer = NULL;
+  memset(&shm_core->queues.lock, 0, sizeof(shm_core->queues.lock));
+  shm_core->queue_types.pointer = NULL;
+  memset(&shm_core->queue_types.lock, 0, sizeof(shm_core->queue_types.lock));
+}
+
+ptrdiff_t aos_core_get_mem_usage(void) {
+  return global_core->size -
+      ((ptrdiff_t)global_core->mem_struct->msg_alloc -
+       (ptrdiff_t)global_core->mem_struct);
+}
+
+struct aos_core *global_core = NULL;
+
+// TODO(brians): madvise(2) it to put this shm in core dumps.
+void aos_core_create_shared_mem(int create, int lock) {
+  assert(global_core == NULL);
+  static struct aos_core global_core_data;
+  global_core = &global_core_data;
+
+  {
+    char *shm_name = getenv("AOS_SHM_NAME");
+    if (shm_name == NULL) {
+      global_core->shm_name = AOS_SHM_NAME;
+    } else {
+      printf("AOS_SHM_NAME defined, using %s\n", shm_name);
+      global_core->shm_name = shm_name;
+    }
+  }
+
+  int shm;
+  if (create) {
+    while (1) {
+      shm = shm_open(global_core->shm_name, O_RDWR | O_CREAT | O_EXCL, 0666);
+      global_core->owner = 1;
+      if (shm == -1 && errno == EEXIST) {
+        printf("shared_mem: going to shm_unlink(%s)\n", global_core->shm_name);
+        if (shm_unlink(global_core->shm_name) == -1) {
+          PLOG(WARNING, "shm_unlink(%s) failed", global_core->shm_name);
+          break;
+        }
+      } else {
+        break;
+      }
+    }
+  } else {
+    shm = shm_open(global_core->shm_name, O_RDWR, 0);
+    global_core->owner = 0;
+  }
+  if (shm == -1) {
+    PLOG(FATAL, "shm_open(%s, O_RDWR [| O_CREAT | O_EXCL, 0|0666) failed",
+         global_core->shm_name);
+  }
+  if (global_core->owner) {
+    if (ftruncate(shm, SIZEOFSHMSEG) == -1) {
+      PLOG(FATAL, "fruncate(%d, 0x%zx) failed", shm, (size_t)SIZEOFSHMSEG);
+    }
+  }
+  int flags = MAP_SHARED | MAP_FIXED;
+  if (lock) flags |= MAP_LOCKED | MAP_POPULATE;
+  void *shm_address = mmap((void *)SHM_START, SIZEOFSHMSEG,
+                           PROT_READ | PROT_WRITE, flags, shm, 0);
+  if (shm_address == MAP_FAILED) {
+    PLOG(FATAL, "shared_mem: mmap(%p, 0x%zx, stuff, %x, %d, 0) failed",
+         (void *)SHM_START, (size_t)SIZEOFSHMSEG, flags, shm);
+  }
+  if (create) {
+    printf("shared_mem: creating %s, shm at: %p\n", global_core->shm_name,
+           shm_address);
+  } else {
+    printf("shared_mem: not creating, shm at: %p\n", shm_address);
+  }
+  if (close(shm) == -1) {
+    PLOG(WARNING, "close(%d(=shm) failed", shm);
+  }
+  if (shm_address != (void *)SHM_START) {
+    LOG(FATAL, "shm isn't at hard-coded %p. at %p instead\n",
+        (void *)SHM_START, shm_address);
+  }
+  aos_core_use_address_as_shared_mem(shm_address, SIZEOFSHMSEG);
+  LOG(INFO, "shared_mem: end of create_shared_mem owner=%d\n",
+          global_core->owner);
+}
+
+void aos_core_use_address_as_shared_mem(void *address, size_t size) {
+  global_core->mem_struct = address;
+  global_core->size = size;
+  global_core->shared_mem =
+      (uint8_t *)address + sizeof(*global_core->mem_struct);
+  if (global_core->owner) {
+    global_core->mem_struct->msg_alloc = (uint8_t *)address + global_core->size;
+    init_shared_mem_core(global_core->mem_struct);
+    futex_set(&global_core->mem_struct->creation_condition);
+  } else {
+    if (futex_wait(&global_core->mem_struct->creation_condition) != 0) {
+      LOG(FATAL, "waiting on creation_condition failed\n");
+    }
+  }
+}
+
+void aos_core_free_shared_mem() {
+  void *shm_address = global_core->shared_mem;
+  if (munmap((void *)SHM_START, SIZEOFSHMSEG) == -1) {
+    PLOG(FATAL, "munmap(%p, 0x%zx) failed", shm_address,
+         (size_t)SIZEOFSHMSEG);
+  }
+  if (global_core->owner) {
+    if (shm_unlink(global_core->shm_name)) {
+      PLOG(FATAL, "shared_mem: shm_unlink(%s) failed", global_core->shm_name);
+    }
+  }
+}
+
+int aos_core_is_init(void) {
+  return global_core != NULL;
+}
diff --git a/aos/linux_code/ipc_lib/shared_mem.h b/aos/linux_code/ipc_lib/shared_mem.h
new file mode 100644
index 0000000..423fd0c
--- /dev/null
+++ b/aos/linux_code/ipc_lib/shared_mem.h
@@ -0,0 +1,87 @@
+#ifndef _SHARED_MEM_H_
+#define _SHARED_MEM_H_
+
+#include <stddef.h>
+#include <unistd.h>
+#include <time.h>
+
+#include "aos/linux_code/ipc_lib/aos_sync.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct aos_core *global_core __attribute__((weak));
+
+// Where the shared memory segment starts in each process's address space.
+// Has to be the same in all of them so that stuff in shared memory
+// can have regular pointers to other stuff in shared memory.
+#define SHM_START 0x20000000
+
+// A structure that represents some kind of global pointer that everything
+// shares.
+typedef struct aos_global_pointer_t {
+  struct aos_mutex lock;
+  void *pointer;
+} aos_global_pointer;
+
+typedef struct aos_shm_core_t {
+  // Gets 0-initialized at the start (as part of shared memory) and
+  // the owner sets as soon as it finishes setting stuff up.
+  aos_condition creation_condition;
+
+  // An offset from CLOCK_REALTIME to times for all the code.
+  // This is currently only set to non-zero by the log replay code.
+  // There is no synchronization on this to avoid the overhead because it is
+  // only updated with proper memory barriers when only a single task is
+  // running.
+  struct timespec time_offset;
+
+  struct aos_mutex msg_alloc_lock;
+  void *msg_alloc;
+
+  // A pointer to the head of the linked list of queues.
+  // pointer points to a ::aos::Queue.
+  aos_global_pointer queues;
+  // A pointer to the head of the linked list of queue message types.
+  // pointer points to a ::aos::type_cache::ShmType.
+  aos_global_pointer queue_types;
+} aos_shm_core;
+
+struct aos_core {
+  // Non-0 if we "own" shared_mem and should shm_unlink(3) it when we're done.
+  int owner;
+  void *shared_mem;
+  // How large the chunk of shared memory is.
+  ptrdiff_t size;
+  aos_shm_core *mem_struct;
+  // For the owner to store the name of the file to unlink when closing.
+  const char *shm_name;
+};
+
+void init_shared_mem_core(aos_shm_core *shm_core);
+
+ptrdiff_t aos_core_get_mem_usage(void);
+
+// Takes the specified memory address and uses it as the shared memory.
+// address is the memory address, and size is the size of the memory.
+// global_core needs to point to an instance of struct aos_core, and owner
+// should be set correctly there.
+// The owner should verify that the first sizeof(mutex) of data is set to 0
+// before passing the memory to this function.
+void aos_core_use_address_as_shared_mem(void *address, size_t size);
+
+// create is true to remove any existing shm to create a fresh one or false to
+// fail if it does not already exist.
+// lock is true to lock shared memory into RAM or false to not.
+void aos_core_create_shared_mem(int create, int lock);
+void aos_core_free_shared_mem(void);
+
+// Returns whether or not the shared memory system is active.
+int aos_core_is_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/aos/linux_code/ipc_lib/unique_message_ptr.h b/aos/linux_code/ipc_lib/unique_message_ptr.h
new file mode 100644
index 0000000..e30a4c0
--- /dev/null
+++ b/aos/linux_code/ipc_lib/unique_message_ptr.h
@@ -0,0 +1,39 @@
+#include <memory>
+
+#include "aos/atom_code/ipc_lib/queue.h"
+
+namespace aos {
+namespace internal {
+
+template<typename T>
+class queue_free {
+ public:
+  queue_free(RawQueue *queue) : queue_(queue) {}
+
+  void operator()(const T *message) {
+    queue_->FreeMessage(static_cast<const void *>(message));
+  }
+
+ private:
+  RawQueue *const queue_;
+};
+
+}  // namespace internal
+
+template<typename T>
+class unique_message_ptr : public ::std::unique_ptr<T, ::aos::internal::queue_free<T>> {
+ public:
+  unique_message_ptr(RawQueue *queue, T *message = NULL)
+      : ::std::unique_ptr<T, ::aos::internal::queue_free<T>>(message, ::aos::internal::queue_free<T>(queue)) {}
+
+  // Perfectly forward this so that the move functionality of ::std::unique_ptr
+  // works.
+  template <typename... Args>
+  unique_message_ptr<T> &operator=(Args &&... args) {
+        ::std::unique_ptr<T, ::aos::internal::queue_free<T>>::operator=(
+            ::std::forward<Args>(args)...);
+        return *this;
+  }
+};
+
+}  // namespace aos
diff --git a/aos/linux_code/linux_code.gyp b/aos/linux_code/linux_code.gyp
new file mode 100644
index 0000000..59f5d27
--- /dev/null
+++ b/aos/linux_code/linux_code.gyp
@@ -0,0 +1,76 @@
+{
+  'targets': [
+    {
+      'target_name': 'dump_rtprio',
+      'type': 'executable',
+      'variables': {
+        'no_rsync': 1,
+      },
+      'sources': [
+        'dump_rtprio.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/common.gyp:time',
+      ],
+    },
+    {
+      'target_name': 'complex_thread_local',
+      'type': 'static_library',
+      'sources': [
+        'complex_thread_local.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/common/common.gyp:once',
+        '<(AOS)/common/common.gyp:die',
+      ],
+    },
+    {
+      'target_name': 'complex_thread_local_test',
+      'type': 'executable',
+      'sources': [
+        'complex_thread_local_test.cc',
+      ],
+      'dependencies': [
+        'complex_thread_local',
+        '<(EXTERNALS):gtest',
+        '<(AOS)/common/util/util.gyp:thread',
+        '<(AOS)/build/aos.gyp:logging',
+      ],
+    },
+    {
+      'target_name': 'init',
+      'type': 'static_library',
+      'sources': [
+        'init.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:shared_mem',
+        '<(AOS)/common/common.gyp:die',
+        '<(AOS)/build/aos.gyp:logging',
+      ],
+    },
+    {
+      'target_name': 'configuration',
+      'type': 'static_library',
+      'sources': [
+        'configuration.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/common/common.gyp:once',
+        '<(AOS)/build/aos.gyp:logging',
+      ],
+    },
+    {
+      'target_name': 'core',
+      'type': 'executable',
+      'sources': [
+        'core.cc',
+      ],
+      'dependencies': [
+        'init',
+        '<(AOS)/common/util/util.gyp:run_command',
+      ],
+    },
+  ],
+}
diff --git a/aos/linux_code/logging/binary_log_file.cc b/aos/linux_code/logging/binary_log_file.cc
new file mode 100644
index 0000000..b063fae
--- /dev/null
+++ b/aos/linux_code/logging/binary_log_file.cc
@@ -0,0 +1,263 @@
+#include "aos/linux_code/logging/binary_log_file.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <signal.h>
+#include <setjmp.h>
+
+namespace aos {
+namespace logging {
+namespace linux_code {
+namespace {
+
+unsigned long SystemPageSize() {
+  static unsigned long r = sysconf(_SC_PAGESIZE);
+  return r;
+}
+
+}  // namespace
+
+LogFileAccessor::LogFileAccessor(int fd, bool writable)
+    : fd_(fd), writable_(writable), offset_(0), current_(0), position_(0) {
+  // Check to make sure that mmap will allow mmaping in chunks of kPageSize.
+  if (SystemPageSize() > kPageSize || (kPageSize % SystemPageSize()) != 0) {
+    LOG(FATAL, "system page size (%lu) not factor of kPageSize (%zd).\n",
+        SystemPageSize(), kPageSize);
+  }
+
+  MapNextPage();
+}
+
+void LogFileAccessor::Sync() const {
+  msync(current_, kPageSize, MS_ASYNC | MS_INVALIDATE);
+}
+
+void LogFileAccessor::SkipToLastSeekablePage() {
+  CHECK(definitely_use_mmap());
+
+  struct stat info;
+  if (fstat(fd_, &info) == -1) {
+    PLOG(FATAL, "fstat(%d, %p) failed", fd_, &info);
+  }
+
+  CHECK((info.st_size % kPageSize) == 0);
+  const auto last_readable_page_number = (info.st_size / kPageSize) - 1;
+  const auto last_seekable_page_number =
+      last_readable_page_number / kSeekPages * kSeekPages;
+  const off_t new_offset = last_seekable_page_number * kPageSize;
+  // We don't want to go backwards...
+  if (new_offset > offset_) {
+    Unmap(current_);
+    offset_ = new_offset;
+    MapNextPage();
+  }
+}
+
+// The only way to tell is using fstat, but we don't really want to be making a
+// syscall every single time somebody wants to know the answer, so it gets
+// cached in is_last_page_.
+bool LogFileAccessor::IsLastPage() {
+  if (is_last_page_ != Maybe::kUnknown) {
+    return is_last_page_ == Maybe::kYes;
+  }
+
+  struct stat info;
+  if (fstat(fd_, &info) == -1) {
+    PLOG(FATAL, "fstat(%d, %p) failed", fd_, &info);
+  }
+  bool r = offset_ == static_cast<off_t>(info.st_size - kPageSize);
+  is_last_page_ = r ? Maybe::kYes : Maybe::kNo;
+  return r;
+}
+
+void LogFileAccessor::MapNextPage() {
+  if (writable_) {
+    if (ftruncate(fd_, offset_ + kPageSize) == -1) {
+      PLOG(FATAL, "ftruncate(%d, %zd) failed", fd_, kPageSize);
+    }
+  }
+
+  if (use_read_ == Maybe::kYes) {
+    ssize_t todo = kPageSize;
+    while (todo > 0) {
+      ssize_t result = read(fd_, current_ + (kPageSize - todo), todo);
+      if (result == -1) {
+        PLOG(FATAL, "read(%d, %p, %zu) failed", fd_,
+             current_ + (kPageSize - todo), todo);
+      } else if (result == 0) {
+        memset(current_, 0, todo);
+        result = todo;
+      }
+      todo -= result;
+    }
+    CHECK_EQ(0, todo);
+  } else {
+    current_ = static_cast<char *>(
+        mmap(NULL, kPageSize, PROT_READ | (writable_ ? PROT_WRITE : 0),
+             MAP_SHARED, fd_, offset_));
+    if (current_ == MAP_FAILED) {
+      if (!writable_ && use_read_ == Maybe::kUnknown && errno == ENODEV) {
+        LOG(INFO, "Falling back to reading the file using read(2).\n");
+        use_read_ = Maybe::kYes;
+        current_ = new char[kPageSize];
+        MapNextPage();
+        return;
+      } else {
+        PLOG(FATAL,
+             "mmap(NULL, %zd, PROT_READ [ | PROT_WRITE], MAP_SHARED, %d, %jd)"
+             " failed",
+             kPageSize, fd_, static_cast<intmax_t>(offset_));
+      }
+    } else {
+      use_read_ = Maybe::kNo;
+    }
+    if (madvise(current_, kPageSize, MADV_SEQUENTIAL | MADV_WILLNEED) == -1) {
+      PLOG(WARNING, "madvise(%p, %zd, MADV_SEQUENTIAL | MADV_WILLNEED) failed",
+           current_, kPageSize);
+    }
+  }
+  offset_ += kPageSize;
+}
+
+void LogFileAccessor::Unmap(void *location) {
+  CHECK_NE(Maybe::kUnknown, use_read_);
+
+  if (use_read_ == Maybe::kNo) {
+    if (munmap(location, kPageSize) == -1) {
+      PLOG(FATAL, "munmap(%p, %zd) failed", location, kPageSize);
+    }
+  }
+  is_last_page_ = Maybe::kUnknown;
+  position_ = 0;
+}
+
+const LogFileMessageHeader *LogFileReader::ReadNextMessage(bool wait) {
+  LogFileMessageHeader *r;
+  do {
+    r = static_cast<LogFileMessageHeader *>(
+        static_cast<void *>(&current()[position()]));
+    if (wait) {
+      CHECK(definitely_use_mmap());
+      if (futex_wait(&r->marker) != 0) continue;
+    }
+    if (r->marker == 2) {
+      Unmap(current());
+      MapNextPage();
+      CheckCurrentPageReadable();
+      r = static_cast<LogFileMessageHeader *>(static_cast<void *>(current()));
+    }
+  } while (wait && r->marker == 0);
+  if (r->marker == 0) {
+    return NULL;
+  }
+  IncrementPosition(sizeof(LogFileMessageHeader) + r->name_size +
+                    r->message_size);
+  if (position() >= kPageSize) {
+    // It's a lot better to blow up here rather than getting SIGBUS errors the
+    // next time we try to read...
+    LOG(FATAL, "corrupt log file running over page size\n");
+  }
+  return r;
+}
+
+// This mess is because the only not completely hackish way to do this is to set
+// up a handler for SIGBUS/SIGSEGV that siglongjmps out to avoid either the
+// instruction being repeated infinitely (and more signals being delivered) or
+// (with SA_RESETHAND) the signal killing the process.
+namespace {
+
+void *volatile fault_address;
+sigjmp_buf jump_context;
+
+void CheckCurrentPageReadableHandler(int /*signal*/, siginfo_t *info, void *) {
+  fault_address = info->si_addr;
+
+  siglongjmp(jump_context, 1);
+}
+
+}  // namespace
+void LogFileReader::CheckCurrentPageReadable() {
+  if (definitely_use_read()) return;
+
+  if (sigsetjmp(jump_context, 1) == 0) {
+    struct sigaction action;
+    action.sa_sigaction = CheckCurrentPageReadableHandler;
+    sigemptyset(&action.sa_mask);
+    action.sa_flags = SA_RESETHAND | SA_SIGINFO;
+    struct sigaction previous_bus, previous_segv;
+    if (sigaction(SIGBUS, &action, &previous_bus) == -1) {
+      PLOG(FATAL, "sigaction(SIGBUS(=%d), %p, %p) failed",
+           SIGBUS, &action, &previous_bus);
+    }
+    if (sigaction(SIGSEGV, &action, &previous_segv) == -1) {
+      PLOG(FATAL, "sigaction(SIGSEGV(=%d), %p, %p) failed",
+           SIGSEGV, &action, &previous_segv);
+    }
+
+    char __attribute__((unused)) c = current()[0];
+
+    if (sigaction(SIGBUS, &previous_bus, NULL) == -1) {
+      PLOG(FATAL, "sigaction(SIGBUS(=%d), %p, NULL) failed",
+           SIGBUS, &previous_bus);
+    }
+    if (sigaction(SIGSEGV, &previous_segv, NULL) == -1) {
+      PLOG(FATAL, "sigaction(SIGSEGV(=%d), %p, NULL) failed",
+           SIGSEGV, &previous_segv);
+    }
+  } else {
+    if (fault_address == current()) {
+      LOG(FATAL, "could not read 1 byte at offset 0x%jx into log file\n",
+          static_cast<uintmax_t>(offset()));
+    } else {
+      LOG(FATAL, "faulted at %p, not %p like we were (maybe) supposed to\n",
+          fault_address, current());
+    }
+  }
+}
+
+LogFileMessageHeader *LogFileWriter::GetWritePosition(size_t message_size) {
+  if (NeedNewPageFor(message_size)) ForceNewPage();
+  LogFileMessageHeader *const r = static_cast<LogFileMessageHeader *>(
+      static_cast<void *>(&current()[position()]));
+  IncrementPosition(message_size);
+  return r;
+}
+
+// A number of seekable pages, not the actual file offset, is stored in *cookie.
+bool LogFileWriter::ShouldClearSeekableData(off_t *cookie,
+                                            size_t next_message_size) const {
+  off_t next_message_page = (offset() / kPageSize) - 1;
+  if (NeedNewPageFor(next_message_size)) {
+    ++next_message_page;
+  }
+  const off_t current_seekable_page = next_message_page / kSeekPages;
+  CHECK_LE(*cookie, current_seekable_page);
+  const bool r = *cookie != current_seekable_page;
+  *cookie = current_seekable_page;
+  return r;
+}
+
+bool LogFileWriter::NeedNewPageFor(size_t bytes) const {
+  return position() + bytes + (kAlignment - (bytes % kAlignment)) +
+             sizeof(aos_futex) >
+         kPageSize;
+}
+
+void LogFileWriter::ForceNewPage() {
+  char *const temp = current();
+  MapNextPage();
+  if (futex_set_value(
+          static_cast<aos_futex *>(static_cast<void *>(&temp[position()])),
+          2) == -1) {
+    PLOG(WARNING, "readers will hang because futex_set_value(%p, 2) failed",
+         &temp[position()]);
+  }
+  Unmap(temp);
+}
+
+}  // namespace linux_code
+}  // namespace logging
+}  // namespace aos
diff --git a/aos/linux_code/logging/binary_log_file.h b/aos/linux_code/logging/binary_log_file.h
new file mode 100644
index 0000000..bcf9da1
--- /dev/null
+++ b/aos/linux_code/logging/binary_log_file.h
@@ -0,0 +1,207 @@
+#ifndef AOS_LINUX_CODE_LOGGING_BINARY_LOG_FILE_H_
+#define AOS_LINUX_CODE_LOGGING_BINARY_LOG_FILE_H_
+
+#include <sys/types.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <algorithm>
+
+#include "aos/common/logging/logging_impl.h"
+
+namespace aos {
+namespace logging {
+namespace linux_code {
+
+// What to align messages to. A macro because it gets used in attributes.
+// This definition gets #undefed later. Use LogFileAccessor::kAlignment instead.
+#define MESSAGE_ALIGNMENT 8
+
+// File format: {
+//   LogFileMessageHeader header;
+//   char *name;  // of the process that wrote the message
+//   void *message;
+// } not crossing kPageSize boundaries into the file and aligned to
+// MESSAGE_ALIGNMENT.
+//
+// Field sizes designed to fit the various values from LogMessage even on
+// other machines (hopefully) because they're baked into the files. They are
+// layed out so that all of the fields are aligned even though the whole thing
+// is packed.
+//
+// A lot of the fields don't have comments because they're the same as the
+// identically named fields in LogMessage.
+struct __attribute__((aligned(MESSAGE_ALIGNMENT))) __attribute__((packed))
+    LogFileMessageHeader {
+  // Represents the type of an individual message.
+  enum class MessageType : uint16_t {
+    // char[] (no '\0' on the end).
+    kString,
+    kStructType,
+    kStruct,
+    kMatrix,
+  };
+
+  // Gets futex_set once this one has been written
+  // for readers keeping up with a live writer.
+  //
+  // Gets initialized to 0 by ftruncate.
+  //
+  // There will be something here after the last message on a "page" set to 2
+  // (by the futex_set) to indicate that the next message is on the next page.
+  aos_futex marker;
+  static_assert(sizeof(marker) == 4, "mutex changed size!");
+  static_assert(MESSAGE_ALIGNMENT >= alignof(aos_futex),
+                "MESSAGE_ALIGNMENT is too small");
+
+  uint32_t time_sec;
+  static_assert(sizeof(time_sec) >= sizeof(LogMessage::seconds),
+                "tv_sec won't fit");
+  uint32_t time_nsec;
+  static_assert(sizeof(time_nsec) >= sizeof(LogMessage::nseconds),
+                "tv_nsec won't fit");
+
+  int32_t source;
+  static_assert(sizeof(source) >= sizeof(LogMessage::source), "PIDs won't fit");
+
+  // Both including all of the bytes in that part of the message.
+  uint32_t name_size, message_size;
+
+  uint16_t sequence;
+  static_assert(sizeof(sequence) == sizeof(LogMessage::sequence),
+                "something changed");
+
+  MessageType type;
+
+  log_level level;
+  static_assert(sizeof(level) == 1, "log_level changed size!");
+};
+static_assert(std::is_pod<LogFileMessageHeader>::value,
+              "LogFileMessageHeader will to get dumped to a file");
+static_assert(offsetof(LogFileMessageHeader, marker) == 0,
+              "marker has to be at the start so readers can find it");
+
+// Handles the mmapping and munmapping for reading and writing log files.
+class LogFileAccessor {
+ public:
+  LogFileAccessor(int fd, bool writable);
+  ~LogFileAccessor() {
+    if (use_read_ == Maybe::kYes) {
+      delete[] current_;
+    }
+  }
+
+  // Asynchronously syncs all open mappings.
+  void Sync() const;
+
+  // Returns true iff we currently have the last page in the file mapped.
+  // This is fundamentally a racy question, so the return value may not be
+  // accurate by the time this method returns.
+  bool IsLastPage();
+
+  // Skips to the last page which is an even multiple of kSeekPages.
+  // This is fundamentally racy, so it may not actually be on the very last
+  // possible multiple of kSeekPages when it returns, but it should be close.
+  // This will never move backwards.
+  void SkipToLastSeekablePage();
+
+  size_t file_offset(const void *msg) {
+    return offset() + (static_cast<const char *>(msg) - current());
+  }
+
+ protected:
+  // The size of the chunks that get mmaped/munmapped together. Large enough so
+  // that not too much space is wasted and it's hopefully bigger than and a
+  // multiple of the system page size but small enough so that really large
+  // chunks of memory don't have to get mapped at the same time.
+  static const size_t kPageSize = 16384;
+  // What to align messages to, copied into an actual constant.
+  static const size_t kAlignment = MESSAGE_ALIGNMENT;
+#undef MESSAGE_ALIGNMENT
+  // Pages which are multiples of this from the beginning of a file start with
+  // no saved state (ie struct types). This allows seeking immediately to the
+  // largest currently written interval of this number when following.
+  static const size_t kSeekPages = 256;
+
+  char *current() const { return current_; }
+  size_t position() const { return position_; }
+  off_t offset() const { return offset_; }
+
+  void IncrementPosition(size_t size) {
+    position_ += size;
+    AlignPosition();
+  }
+
+  void MapNextPage();
+  void Unmap(void *location);
+
+  // Advances position to the next (aligned) location.
+  void AlignPosition() {
+    position_ += kAlignment - (position_ % kAlignment);
+  }
+
+ protected:
+  bool definitely_use_read() const { return use_read_ == Maybe::kYes; }
+  bool definitely_use_mmap() const { return use_read_ == Maybe::kNo; }
+
+ private:
+  // Used for representing things that we might know to be true/false or we
+  // might not know (yet).
+  enum class Maybe { kUnknown, kYes, kNo };
+
+  const int fd_;
+  const bool writable_;
+
+  // Into the file. Always a multiple of kPageSize.
+  off_t offset_;
+  char *current_;
+  size_t position_;
+
+  Maybe is_last_page_ = Maybe::kUnknown;
+
+  // Use read instead of mmap (necessary for fds that don't support mmap).
+  Maybe use_read_ = Maybe::kUnknown;
+};
+
+class LogFileReader : public LogFileAccessor {
+ public:
+  LogFileReader(int fd) : LogFileAccessor(fd, false) {}
+
+  // May return NULL iff wait is false.
+  const LogFileMessageHeader *ReadNextMessage(bool wait);
+
+ private:
+  // Tries reading from the current page to see if it fails because the file
+  // isn't big enough.
+  void CheckCurrentPageReadable();
+};
+
+class LogFileWriter : public LogFileAccessor {
+ public:
+  LogFileWriter(int fd) : LogFileAccessor(fd, true) {}
+
+  // message_size should be the total number of bytes needed for the message.
+  LogFileMessageHeader *GetWritePosition(size_t message_size);
+
+  // Returns true exactly once for each unique cookie on each page where cached
+  // data should be cleared.
+  // Call with a non-zero next_message_size to determine if cached data should
+  // be forgotten before writing a next_message_size-sized message.
+  // cookie should be initialized to 0.
+  bool ShouldClearSeekableData(off_t *cookie, size_t next_message_size) const;
+
+  // Forces a move to a new page for the next message.
+  // This is important when there is cacheable data that needs to be re-written
+  // before a message which will spill over onto the next page but the cacheable
+  // message being refreshed is smaller and won't get to a new page by itself.
+  void ForceNewPage();
+
+ private:
+  bool NeedNewPageFor(size_t bytes) const;
+};
+
+}  // namespace linux_code
+}  // namespace logging
+}  // namespace aos
+
+#endif  // AOS_LINUX_CODE_LOGGING_BINARY_LOG_FILE_H_
diff --git a/aos/linux_code/logging/binary_log_writer.cc b/aos/linux_code/logging/binary_log_writer.cc
new file mode 100644
index 0000000..dbe61e0
--- /dev/null
+++ b/aos/linux_code/logging/binary_log_writer.cc
@@ -0,0 +1,311 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <time.h>
+#include <string.h>
+#include <string>
+#include <unistd.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <mntent.h>
+
+#include <map>
+#include <unordered_set>
+
+#include "aos/linux_code/logging/linux_logging.h"
+#include "aos/linux_code/logging/binary_log_file.h"
+#include "aos/linux_code/init.h"
+#include "aos/linux_code/configuration.h"
+#include "aos/common/queue_types.h"
+#include "aos/common/die.h"
+
+namespace aos {
+namespace logging {
+namespace linux_code {
+namespace {
+
+void CheckTypeWritten(uint32_t type_id, LogFileWriter *writer,
+                      ::std::unordered_set<uint32_t> *written_type_ids) {
+  if (written_type_ids->count(type_id) > 0) return;
+  if (MessageType::IsPrimitive(type_id)) return;
+
+  const MessageType &type = type_cache::Get(type_id);
+  for (int i = 0; i < type.number_fields; ++i) {
+    CheckTypeWritten(type.fields[i]->type, writer, written_type_ids);
+  }
+
+  char buffer[1024];
+  ssize_t size = type.Serialize(buffer, sizeof(buffer));
+  if (size == -1) {
+    LOG(WARNING, "%zu-byte buffer is too small to serialize type %s\n",
+        sizeof(buffer), type.name.c_str());
+    return;
+  }
+  LogFileMessageHeader *const output =
+      writer->GetWritePosition(sizeof(LogFileMessageHeader) + size);
+
+  output->time_sec = output->time_nsec = 0;
+  output->source = getpid();
+  output->name_size = 0;
+  output->sequence = 0;
+  output->level = FATAL;
+
+  memcpy(output + 1, buffer, size);
+  output->message_size = size;
+
+  output->type = LogFileMessageHeader::MessageType::kStructType;
+  futex_set(&output->marker);
+
+  written_type_ids->insert(type_id);
+}
+
+void AllocateLogName(char **filename, const char *directory) {
+  int fileindex = 0;
+  DIR *const d = opendir(directory);
+  if (d == nullptr) {
+    PDie("could not open directory %s", directory);
+  }
+  int index = 0;
+  while (true) {
+    errno = 0;
+    struct dirent *const dir = readdir(d);
+    if (dir == nullptr) {
+      if (errno == 0) {
+        break;
+      } else {
+        PLOG(FATAL, "readdir(%p) failed", d);
+      }
+    } else {
+      if (sscanf(dir->d_name, "aos_log-%d", &index) == 1) {
+        if (index >= fileindex) {
+          fileindex = index + 1;
+        }
+      }
+    }
+  }
+  closedir(d);
+
+  char previous[512];
+  ::std::string path = ::std::string(directory) + "/aos_log-current";
+  ssize_t len = ::readlink(path.c_str(), previous, sizeof(previous));
+  if (len != -1) {
+    previous[len] = '\0';
+  } else {
+    previous[0] = '\0';
+    LOG(INFO, "Could not find aos_log-current\n");
+    printf("Could not find aos_log-current\n");
+  }
+  if (asprintf(filename, "%s/aos_log-%03d", directory, fileindex) == -1) {
+    PDie("couldn't create final name");
+  }
+  LOG(INFO, "Created log file (aos_log-%d) in directory (%s). Previous file "
+            "was (%s).\n",
+      fileindex, directory, previous);
+  printf("Created log file (aos_log-%d) in directory (%s). Previous file was "
+         "(%s).\n",
+         fileindex, directory, previous);
+}
+
+#ifdef AOS_ARCHITECTURE_arm_frc
+bool FoundThumbDrive(const char *path) {
+  FILE *mnt_fp = setmntent("/etc/mtab", "r");
+  if (mnt_fp == nullptr) {
+    Die("Could not open /etc/mtab");
+  }
+
+  bool found = false;
+  struct mntent mntbuf;
+  char buf[256];
+  while (!found) {
+    struct mntent *mount_list = getmntent_r(mnt_fp, &mntbuf, buf, sizeof(buf));
+    if (mount_list == nullptr) {
+      break;
+    }
+    if (strcmp(mount_list->mnt_dir, path) == 0) {
+      found = true;
+    }
+  }
+  endmntent(mnt_fp);
+  return found;
+}
+
+bool FindDevice(char *device, size_t device_size) {
+  char test_device[10];
+  for (char i = 'a'; i < 'z'; ++i) {
+    snprintf(test_device, sizeof(test_device), "/dev/sd%c", i);
+    LOG(INFO, "Trying to access %s\n", test_device);
+    if (access(test_device, F_OK) != -1) {
+      snprintf(device, device_size, "sd%c", i);
+      return true;
+    }
+  }
+  return false;
+}
+#endif
+
+int BinaryLogReaderMain() {
+  InitNRT();
+
+#ifdef AOS_ARCHITECTURE_arm_frc
+  char folder[128];
+
+  {
+    char dev_name[8];
+    while (!FindDevice(dev_name, sizeof(dev_name))) {
+      LOG(INFO, "Waiting for a device\n");
+      printf("Waiting for a device\n");
+      sleep(5);
+    }
+    snprintf(folder, sizeof(folder), "/media/%s1", dev_name);
+    while (!FoundThumbDrive(folder)) {
+      LOG(INFO, "Waiting for %s\n", folder);
+      printf("Waiting for %s\n", folder);
+      sleep(1);
+    }
+    snprintf(folder, sizeof(folder), "/media/%s1/", dev_name);
+  }
+
+  if (access(folder, F_OK) == -1) {
+#else
+  const char *folder = configuration::GetLoggingDirectory();
+  if (access(folder, R_OK | W_OK) == -1) {
+#endif
+    LOG(FATAL, "folder '%s' does not exist. please create it\n", folder);
+  }
+  LOG(INFO, "logging to folder '%s'\n", folder);
+
+  char *tmp;
+  AllocateLogName(&tmp, folder);
+  char *tmp2;
+  if (asprintf(&tmp2, "%s/aos_log-current", folder) == -1) {
+    PLOG(WARNING, "couldn't create current symlink name");
+  } else {
+    if (unlink(tmp2) == -1 && (errno != EROFS && errno != ENOENT)) {
+      LOG(WARNING, "unlink('%s') failed", tmp2);
+    }
+    if (symlink(tmp, tmp2) == -1) {
+      PLOG(WARNING, "symlink('%s', '%s') failed", tmp, tmp2);
+    }
+    free(tmp2);
+  }
+  int fd = open(tmp, O_SYNC | O_APPEND | O_RDWR | O_CREAT,
+                S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+  free(tmp);
+  if (fd == -1) {
+    PLOG(FATAL, "opening file '%s' failed", tmp);
+  }
+  LogFileWriter writer(fd);
+
+  ::std::unordered_set<uint32_t> written_type_ids;
+  off_t clear_type_ids_cookie = 0;
+
+  while (true) {
+    const LogMessage *const msg = ReadNext();
+    if (msg == NULL) continue;
+
+    const size_t raw_output_length =
+        sizeof(LogFileMessageHeader) + msg->name_length + msg->message_length;
+    size_t output_length = raw_output_length;
+    if (msg->type == LogMessage::Type::kStruct) {
+      output_length += sizeof(msg->structure.type_id) + sizeof(uint32_t) +
+                       msg->structure.string_length;
+      if (writer.ShouldClearSeekableData(&clear_type_ids_cookie,
+                                         output_length)) {
+        writer.ForceNewPage();
+        written_type_ids.clear();
+      }
+      CheckTypeWritten(msg->structure.type_id, &writer, &written_type_ids);
+    } else if (msg->type == LogMessage::Type::kMatrix) {
+      output_length +=
+          sizeof(msg->matrix.type) + sizeof(uint32_t) + sizeof(uint16_t) +
+          sizeof(uint16_t) + msg->matrix.string_length;
+      CHECK(MessageType::IsPrimitive(msg->matrix.type));
+    }
+    LogFileMessageHeader *const output = writer.GetWritePosition(output_length);
+    char *output_strings = reinterpret_cast<char *>(output) + sizeof(*output);
+    output->name_size = msg->name_length;
+    output->message_size = msg->message_length;
+    output->source = msg->source;
+    output->level = msg->level;
+    output->time_sec = msg->seconds;
+    output->time_nsec = msg->nseconds;
+    output->sequence = msg->sequence;
+    memcpy(output_strings, msg->name, msg->name_length);
+
+    switch (msg->type) {
+      case LogMessage::Type::kString:
+        memcpy(output_strings + msg->name_length, msg->message,
+               msg->message_length);
+        output->type = LogFileMessageHeader::MessageType::kString;
+        break;
+      case LogMessage::Type::kStruct: {
+        char *position = output_strings + msg->name_length;
+
+        memcpy(position, &msg->structure.type_id,
+               sizeof(msg->structure.type_id));
+        position += sizeof(msg->structure.type_id);
+        output->message_size += sizeof(msg->structure.type_id);
+
+        const uint32_t length = msg->structure.string_length;
+        memcpy(position, &length, sizeof(length));
+        position += sizeof(length);
+        memcpy(position, msg->structure.serialized,
+               length + msg->message_length);
+        position += length + msg->message_length;
+        output->message_size += sizeof(length) + length;
+
+        output->type = LogFileMessageHeader::MessageType::kStruct;
+      } break;
+      case LogMessage::Type::kMatrix: {
+        char *position = output_strings + msg->name_length;
+
+        memcpy(position, &msg->matrix.type, sizeof(msg->matrix.type));
+        position += sizeof(msg->matrix.type);
+        output->message_size += sizeof(msg->matrix.type);
+
+        uint32_t length = msg->matrix.string_length;
+        memcpy(position, &length, sizeof(length));
+        position += sizeof(length);
+        output->message_size += sizeof(length);
+
+        uint16_t rows = msg->matrix.rows, cols = msg->matrix.cols;
+        memcpy(position, &rows, sizeof(rows));
+        position += sizeof(rows);
+        memcpy(position, &cols, sizeof(cols));
+        position += sizeof(cols);
+        output->message_size += sizeof(rows) + sizeof(cols);
+        CHECK_EQ(msg->message_length,
+                 MessageType::Sizeof(msg->matrix.type) * rows * cols);
+
+        memcpy(position, msg->matrix.data, msg->message_length + length);
+        output->message_size += length;
+
+        output->type = LogFileMessageHeader::MessageType::kMatrix;
+      } break;
+    }
+
+    if (output->message_size - msg->message_length !=
+        output_length - raw_output_length) {
+      LOG(FATAL, "%zu != %zu\n", output->message_size - msg->message_length,
+          output_length - raw_output_length);
+    }
+
+    futex_set(&output->marker);
+
+    logging::linux_code::Free(msg);
+  }
+
+  Cleanup();
+  return 0;
+}
+
+}  // namespace
+}  // namespace linux_code
+}  // namespace logging
+}  // namespace aos
+
+int main() {
+  return ::aos::logging::linux_code::BinaryLogReaderMain();
+}
diff --git a/aos/linux_code/logging/linux_interface.cc b/aos/linux_code/logging/linux_interface.cc
new file mode 100644
index 0000000..b0a5c1b
--- /dev/null
+++ b/aos/linux_code/logging/linux_interface.cc
@@ -0,0 +1,85 @@
+#include "aos/linux_code/logging/linux_logging.h"
+
+#include <sys/prctl.h>
+
+#include "aos/linux_code/complex_thread_local.h"
+#include "aos/common/die.h"
+
+namespace aos {
+namespace logging {
+namespace internal {
+namespace {
+
+// TODO(brians): Differentiate between threads with the same name in the same
+// process.
+
+::std::string GetMyName() {
+  // The maximum number of characters that can make up a thread name.
+  // The docs are unclear if it can be 16 characters with no '\0', so we'll be
+  // safe by adding our own where necessary.
+  static const size_t kThreadNameLength = 16;
+
+  ::std::string process_name(program_invocation_short_name);
+
+  char thread_name_array[kThreadNameLength + 1];
+  if (prctl(PR_GET_NAME, thread_name_array) != 0) {
+    PDie("prctl(PR_GET_NAME, %p) failed", thread_name_array);
+  }
+  thread_name_array[sizeof(thread_name_array) - 1] = '\0';
+  ::std::string thread_name(thread_name_array);
+
+  // If the first bunch of characters are the same.
+  // We cut off comparing at the shorter of the 2 strings because one or the
+  // other often ends up cut off.
+  if (strncmp(thread_name.c_str(), process_name.c_str(),
+              ::std::min(thread_name.length(), process_name.length())) == 0) {
+    // This thread doesn't have an actual name.
+    return process_name;
+  }
+
+  return process_name + '.' + thread_name;
+}
+
+::aos::ComplexThreadLocal<Context> my_context;
+
+// True if we're going to delete the current Context object ASAP. The
+// reason for doing this instead of just deleting them is that tsan (at least)
+// doesn't like it when pthread_atfork handlers do complicated stuff and it's
+// not a great idea anyways.
+thread_local bool delete_current_context(false);
+
+}  // namespace
+
+// Used in aos/linux_code/init.cc when a thread's name is changed.
+void ReloadThreadName() {
+  if (my_context.created()) {
+    ::std::string my_name = GetMyName();
+    if (my_name.size() + 1 > sizeof(Context::name)) {
+      Die("logging: process/thread name '%s' is too long\n",
+          my_name.c_str());
+    }
+    strcpy(my_context->name, my_name.c_str());
+    my_context->name_size = my_name.size();
+  }
+}
+
+Context *Context::Get() {
+  if (__builtin_expect(delete_current_context, false)) {
+    my_context.Clear();
+    delete_current_context = false;
+  }
+  if (__builtin_expect(!my_context.created(), false)) {
+    my_context.Create();
+    ReloadThreadName();
+    my_context->source = getpid();
+  }
+  return my_context.get();
+}
+
+void Context::Delete() {
+  delete_current_context = true;
+}
+
+}  // namespace internal
+}  // namespace logging
+}  // namespace aos
diff --git a/aos/linux_code/logging/linux_logging.cc b/aos/linux_code/logging/linux_logging.cc
new file mode 100644
index 0000000..b13a740
--- /dev/null
+++ b/aos/linux_code/logging/linux_logging.cc
@@ -0,0 +1,145 @@
+#include "aos/linux_code/logging/linux_logging.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <unistd.h>
+#include <limits.h>
+#include <inttypes.h>
+
+#include <algorithm>
+
+#include "aos/common/die.h"
+#include "aos/common/logging/logging_impl.h"
+#include "aos/linux_code/ipc_lib/queue.h"
+#include "aos/common/time.h"
+
+namespace aos {
+namespace logging {
+namespace linux_code {
+namespace {
+
+RawQueue *queue = NULL;
+
+int dropped_messages = 0;
+::aos::time::Time dropped_start, backoff_start;
+// Wait this long after dropping a message before even trying to write any more.
+constexpr ::aos::time::Time kDropBackoff = ::aos::time::Time::InSeconds(0.1);
+
+LogMessage *GetMessageOrDie() {
+  LogMessage *message = static_cast<LogMessage *>(queue->GetMessage());
+  if (message == NULL) {
+    LOG(FATAL, "%p->GetMessage() failed\n", queue);
+  } else {
+    return message;
+  }
+}
+
+class LinuxQueueLogImplementation : public LogImplementation {
+  __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0)))
+  virtual void DoLog(log_level level, const char *format, va_list ap) override {
+    LogMessage *message = GetMessageOrDie();
+    internal::FillInMessage(level, format, ap, message);
+    Write(message);
+  }
+
+  virtual void LogStruct(log_level level, const ::std::string &message_string,
+                         size_t size, const MessageType *type,
+                         const ::std::function<size_t(char *)> &serialize)
+      override {
+    LogMessage *message = GetMessageOrDie();
+    internal::FillInMessageStructure(level, message_string, size, type,
+                                     serialize, message);
+    Write(message);
+  }
+
+  virtual void LogMatrix(log_level level, const ::std::string &message_string,
+                         uint32_t type_id, int rows, int cols, const void *data)
+      override {
+    LogMessage *message = GetMessageOrDie();
+    internal::FillInMessageMatrix(level, message_string, type_id, rows, cols,
+                                  data, message);
+    Write(message);
+  }
+};
+
+}  // namespace
+
+void Register() {
+  Init();
+
+  queue = RawQueue::Fetch("LoggingQueue", sizeof(LogMessage), 1323, 40000);
+  if (queue == NULL) {
+    Die("logging: couldn't fetch queue\n");
+  }
+
+  AddImplementation(new LinuxQueueLogImplementation());
+}
+
+const LogMessage *ReadNext(Options<RawQueue> flags, int *index) {
+  return static_cast<const LogMessage *>(queue->ReadMessageIndex(flags, index));
+}
+
+const LogMessage *ReadNext() {
+  return ReadNext(RawQueue::kBlock);
+}
+
+const LogMessage *ReadNext(Options<RawQueue> flags) {
+  const LogMessage *r = NULL;
+  do {
+    r = static_cast<const LogMessage *>(queue->ReadMessage(flags));
+    // not blocking means return a NULL if that's what it gets
+  } while ((flags & RawQueue::kBlock) && r == NULL);
+  return r;
+}
+
+LogMessage *Get() {
+  return static_cast<LogMessage *>(queue->GetMessage());
+}
+
+void Free(const LogMessage *msg) {
+  queue->FreeMessage(msg);
+}
+
+void Write(LogMessage *msg) {
+  if (__builtin_expect(dropped_messages > 0, false)) {
+    ::aos::time::Time message_time =
+        ::aos::time::Time(msg->seconds, msg->nseconds);
+    if (message_time - backoff_start < kDropBackoff) {
+      ++dropped_messages;
+      queue->FreeMessage(msg);
+      return;
+    }
+
+    LogMessage *dropped_message = GetMessageOrDie();
+    internal::FillInMessageVarargs(
+        ERROR, dropped_message,
+        "%d logs starting at %" PRId32 ".%" PRId32 " dropped\n",
+        dropped_messages, dropped_start.sec(), dropped_start.nsec());
+    if (queue->WriteMessage(dropped_message, RawQueue::kNonBlock)) {
+      dropped_messages = 0;
+    } else {
+      // Don't even bother trying to write this message because it's not likely
+      // to work and it would be confusing to have one log in the middle of a
+      // string of failures get through.
+      ++dropped_messages;
+      backoff_start = message_time;
+      queue->FreeMessage(msg);
+      return;
+    }
+  }
+  if (!queue->WriteMessage(msg, RawQueue::kNonBlock)) {
+    if (dropped_messages == 0) {
+      dropped_start = backoff_start =
+          ::aos::time::Time(msg->seconds, msg->nseconds);
+    }
+    ++dropped_messages;
+  }
+}
+
+}  // namespace linux_code
+}  // namespace logging
+}  // namespace aos
diff --git a/aos/linux_code/logging/linux_logging.h b/aos/linux_code/logging/linux_logging.h
new file mode 100644
index 0000000..63eeaf1
--- /dev/null
+++ b/aos/linux_code/logging/linux_logging.h
@@ -0,0 +1,34 @@
+#ifndef AOS_LINUX_CODE_LOGGING_LOGGING_H_
+#define AOS_LINUX_CODE_LOGGING_LOGGING_H_
+
+#include "aos/common/logging/logging_impl.h"
+#include "aos/common/util/options.h"
+
+namespace aos {
+
+class RawQueue;
+
+namespace logging {
+namespace linux_code {
+
+// Calls AddImplementation to register the usual linux logging implementation
+// which sends the messages through a queue. This implementation relies on
+// another process(es) to read the log messages that it puts into the queue.
+// This function is usually called by aos::Init*.
+void Register();
+
+// Fairly simple wrappers around the raw queue calls.
+
+// This one never returns NULL if flags contains BLOCK.
+const LogMessage *ReadNext(Options<RawQueue> flags);
+const LogMessage *ReadNext(Options<RawQueue> flags, int *index);
+const LogMessage *ReadNext();
+LogMessage *Get();
+void Free(const LogMessage *msg);
+void Write(LogMessage *msg);
+
+}  // namespace linux_code
+}  // namespace logging
+}  // namespace aos
+
+#endif
diff --git a/aos/linux_code/logging/log_displayer.cc b/aos/linux_code/logging/log_displayer.cc
new file mode 100644
index 0000000..4050bd4
--- /dev/null
+++ b/aos/linux_code/logging/log_displayer.cc
@@ -0,0 +1,410 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <inttypes.h>
+
+#include <algorithm>
+#include <memory>
+#include <string>
+
+#include "aos/linux_code/configuration.h"
+#include "aos/linux_code/logging/binary_log_file.h"
+#include "aos/common/queue_types.h"
+#include "aos/common/logging/logging_impl.h"
+#include "aos/common/logging/logging_printf_formats.h"
+#include "aos/common/util/string_to_num.h"
+
+using ::aos::logging::linux_code::LogFileMessageHeader;
+
+namespace {
+
+const char *kArgsHelp = "[OPTION]... [FILE]\n"
+    "Display log file FILE (created by BinaryLogReader) to stdout.\n"
+    "FILE is \"aos_log-current\" by default.\n"
+    "FILE can also be \"-\" to read from standard input.\n"
+    "\n"
+    "  -n, --name-prefix NAME  "
+    "only display entries from processes which share NAME as a prefix\n"
+    "  -N, --name NAME         only display entries from processes named NAME\n"
+    "  -l, --level LEVEL       "
+      "only display log entries at least as important as LEVEL\n"
+    "  -p, --pid PID           only display log entries from process PID\n"
+    "  -f, --follow            "
+      "wait when the end of the file is reached (implies --end)\n"
+    "  -t, --terminate         stop when the end of file is reached (default)\n"
+    "  -b, --beginning         start at the beginning of the file (default)\n"
+    "  -e, --end               start at the end of the file\n"
+    "  -s, --skip NUMBER       skip NUMBER matching logs\n"
+    "  -m, --max NUMBER        only display up to NUMBER logs\n"
+    "  // -o, --format FORMAT  use FORMAT to display log entries\n"
+    "  -h, --help              display this help and exit\n"
+    "\n"
+    "LEVEL must be DEBUG, INFO, WARNING, ERROR, or FATAL.\n"
+    "  It defaults to INFO.\n"
+    "\n"
+    "TODO(brians) implement the commented out ones.\n";
+
+const char *kExampleUsages = "To view logs from the shooter:\n"
+    "\t`log_displayer -n shooter`\n"
+    "To view debug logs from the shooter:\n"
+    "\t`log_displayer -n shooter -l DEBUG`\n"
+    "To view what the shooter is logging in realtime:\n"
+    "\t`log_displayer -f -n shooter`\n"
+    "To view shooter logs from an old log file:\n"
+    "\t`log_displayer aos_log-<number> -n shooter`\n"
+    "To view the statuses of the shooter hall effects in realtime:\n"
+    "\t`log_displayer -f -n shooter -l DEBUG | grep .Position`\n";
+
+void PrintHelpAndExit() {
+  fprintf(stderr, "Usage: %s %s", program_invocation_name, kArgsHelp);
+  fprintf(stderr, "\nExample usages:\n\n%s", kExampleUsages);
+
+  // Get the possible executables from start_list.txt.
+  FILE *start_list = fopen("start_list.txt", "r");
+  if (!start_list) {
+    ::std::string path(::aos::configuration::GetRootDirectory());
+    path += "/start_list.txt";
+    start_list = fopen(path.c_str(), "r");
+    if (!start_list) {
+      printf("\nCannot open start_list.txt. This means that the\n"
+      "possible arguments for the -n option cannot be shown. log_displayer\n"
+      "looks for start_list.txt in the current working directory and in\n"
+      "%s.\n\n", ::aos::configuration::GetRootDirectory());
+      PLOG(FATAL, "Unable to open start_list.txt");
+    }
+  }
+
+  // Get file size.
+  if (fseek(start_list, 0, SEEK_END)) {
+    PLOG(FATAL, "fseek() failed while reading start_list.txt");
+  }
+  int size = ftell(start_list);
+  if (size < 0) {
+    PLOG(FATAL, "ftell() failed while reading start_list.txt");
+  }
+  rewind(start_list);
+
+  ::std::unique_ptr<char[]> contents(new char[size + 1]);
+  if (contents == NULL) {
+    LOG(FATAL, "malloc() failed while reading start_list.txt.\n");
+  }
+  size_t bytes_read = fread(contents.get(), 1, size, start_list);
+  if (bytes_read < static_cast<size_t>(size)) {
+    LOG(FATAL, "Read %zu bytes from start_list.txt, expected %d.\n",
+        bytes_read, size);
+  }
+
+  // printf doesn't like strings without the \0.
+  contents[size] = '\0';
+  fprintf(stderr, "\nPossible arguments for the -n option:\n%s", contents.get());
+
+  if (fclose(start_list)) {
+    LOG(FATAL, "fclose() failed.\n");
+  }
+
+  exit(EXIT_SUCCESS);
+}
+
+}  // namespace
+
+int main(int argc, char **argv) {
+  const char *filter_name = nullptr, *filter_exact_name = nullptr;
+  size_t filter_length = 0;
+  log_level filter_level = INFO;
+  bool follow = false;
+  // Whether we need to skip everything until we get to the end of the file.
+  bool skip_to_end = false;
+  const char *filename = "aos_log-current";
+  int display_max = 0;
+  int32_t source_pid = -1;
+
+  ::aos::logging::Init();
+  ::aos::logging::AddImplementation(
+      new ::aos::logging::StreamLogImplementation(stdout));
+
+  while (true) {
+    static struct option long_options[] = {
+      {"name-prefix", required_argument, NULL, 'n'},
+      {"name", required_argument, NULL, 'N'},
+      {"level", required_argument, NULL, 'l'},
+      {"pid", required_argument, NULL, 'p'},
+
+      {"follow", no_argument, NULL, 'f'},
+      {"terminate", no_argument, NULL, 't'},
+      {"beginning", no_argument, NULL, 'b'},
+      {"end", no_argument, NULL, 'e'},
+      {"skip", required_argument, NULL, 's'},
+      {"max", required_argument, NULL, 'm'},
+
+      {"format", required_argument, NULL, 'o'},
+
+      {"help", no_argument, NULL, 'h'},
+      {0, 0, 0, 0}
+    };
+    int option_index = 0;
+
+    const int c = getopt_long(argc, argv, "N:n:l:p:fts:m:o:h",
+                    long_options, &option_index);
+    if (c == -1) { // if we're at the end
+      break;
+    }
+    switch (c) {
+      case 0:
+        fputs("LogDisplayer: got a 0 option but didn't set up any\n", stderr);
+        abort();
+      case 'n':
+        filter_name = optarg;
+        filter_exact_name = nullptr;
+        filter_length = strlen(filter_name);
+        break;
+      case 'N':
+        filter_exact_name = optarg;
+        filter_name = nullptr;
+        filter_length = strlen(filter_name);
+        break;
+      case 'l':
+        filter_level = ::aos::logging::str_log(optarg);
+        if (filter_level == LOG_UNKNOWN) {
+          fprintf(stderr, "LogDisplayer: unknown log level '%s'\n", optarg);
+          exit(EXIT_FAILURE);
+        }
+        break;
+      case 'p':
+        if (!::aos::util::StringToNumber(::std::string(optarg), &source_pid)) {
+          fprintf(stderr, "ERROR: -p expects a number, not '%s'.\n", optarg);
+          exit(EXIT_FAILURE);
+        }
+        if (source_pid < 0) {
+          fprintf(stderr, "LogDisplayer: invalid pid '%s'\n", optarg);
+          exit(EXIT_FAILURE);
+        }
+        break;
+      case 'f':
+        follow = true;
+        skip_to_end = true;
+        break;
+      case 't':
+        follow = false;
+        break;
+      case 'b':
+        skip_to_end = false;
+        break;
+      case 'e':
+        skip_to_end = true;
+        break;
+      case 'm':
+        if (!::aos::util::StringToNumber(::std::string(optarg), &display_max)) {
+          fprintf(stderr, "ERROR: -m expects a number, not '%s'.\n", optarg);
+          exit(EXIT_FAILURE);
+        }
+        if (display_max <= 0) {
+          fprintf(stderr, "LogDisplayer: invalid max log number '%s'\n",
+              optarg);
+          exit(EXIT_FAILURE);
+        }
+        break;
+      case 'o':
+        abort();
+        break;
+      case 'h':
+        PrintHelpAndExit();
+        break;
+      case '?':
+        break;
+      default:
+        fprintf(stderr, "LogDisplayer: in a bad spot (%s: %d)\n",
+                __FILE__, __LINE__);
+        abort();
+    }
+  }
+
+  if (optind < argc) {
+    // We got a filename.
+    filename = argv[optind++];
+  }
+  if (optind < argc) {
+    fputs("non-option ARGV-elements: ", stderr);
+    while (optind < argc) {
+      fprintf(stderr, "%s\n", argv[optind++]);
+    }
+  }
+
+  int fd;
+  if (strcmp(filename, "-") == 0) {
+    if (skip_to_end) {
+      fputs("Can't skip to end of stdin!\n", stderr);
+      return EXIT_FAILURE;
+    }
+    fd = STDIN_FILENO;
+  } else {
+    fd = open(filename, O_RDONLY);
+  }
+
+  fprintf(stderr, "displaying down to level %s from file '%s'\n",
+      ::aos::logging::log_str(filter_level), filename);
+
+  if (fd == -1) {
+    PLOG(FATAL, "couldn't open file '%s' for reading", filename);
+  }
+  ::aos::logging::linux_code::LogFileReader reader(fd);
+
+  if (skip_to_end) {
+    fputs("skipping old logs...\n", stderr);
+    reader.SkipToLastSeekablePage();
+  }
+
+  const LogFileMessageHeader *msg;
+  int displayed = 0;
+  do {
+    msg = reader.ReadNextMessage(follow);
+    if (msg == NULL) {
+      fputs("reached end of file\n", stderr);
+      return 0;
+    }
+
+    if (msg->type == LogFileMessageHeader::MessageType::kStructType) {
+      size_t bytes = msg->message_size;
+      ::aos::MessageType *type = ::aos::MessageType::Deserialize(
+          reinterpret_cast<const char *>(msg + 1), &bytes);
+      if (type == nullptr) {
+        LOG(INFO, "Trying old version of type decoding.\n");
+        bytes = msg->message_size;
+        type = ::aos::MessageType::Deserialize(
+            reinterpret_cast<const char *>(msg + 1), &bytes, false);
+      }
+
+      if (type == nullptr) {
+        LOG(WARNING, "Error deserializing MessageType of size %" PRIx32
+                     " starting at %zx.\n",
+            msg->message_size, reader.file_offset(msg + 1));
+      } else {
+        ::aos::type_cache::Add(*type);
+      }
+      continue;
+    }
+
+    if (source_pid >= 0 && msg->source != source_pid) {
+      // Message is from the wrong process.
+      continue;
+    }
+
+    if (skip_to_end) {
+      if (reader.IsLastPage()) {
+        fputs("done skipping old logs\n", stderr);
+        skip_to_end = false;
+      } else {
+        continue;
+      }
+    }
+
+    if (::aos::logging::log_gt_important(filter_level, msg->level)) continue;
+
+    const char *position =
+        reinterpret_cast<const char *>(msg + 1);
+
+    if (filter_name != nullptr) {
+      const size_t compare_length =
+          ::std::min<size_t>(filter_length, msg->name_size);
+      if (memcmp(filter_name, position, compare_length) != 0) {
+        continue;
+      }
+      if (compare_length < msg->name_size) {
+        if (position[compare_length] != '.') continue;
+      }
+    }
+
+    if (filter_exact_name != nullptr) {
+      if (filter_length != msg->name_size) continue;
+      if (memcmp(filter_exact_name, position, filter_length) != 0) {
+        continue;
+      }
+    }
+
+    if (display_max && displayed++ >= display_max) {
+      fputs("Not displaying the rest of the messages.\n", stderr);
+      return 0;
+    }
+
+    position += msg->name_size;
+
+#define BASE_ARGS                                                           \
+  AOS_LOGGING_BASE_ARGS(                                                    \
+      msg->name_size, reinterpret_cast<const char *>(msg + 1), msg->source, \
+      msg->sequence, msg->level, msg->time_sec, msg->time_nsec)
+    switch (msg->type) {
+      case LogFileMessageHeader::MessageType::kString:
+        fprintf(stdout, AOS_LOGGING_BASE_FORMAT "%.*s", BASE_ARGS,
+                static_cast<int>(msg->message_size), position);
+        break;
+      case LogFileMessageHeader::MessageType::kStruct: {
+        uint32_t type_id;
+        memcpy(&type_id, position, sizeof(type_id));
+        position += sizeof(type_id);
+
+        uint32_t string_length;
+        memcpy(&string_length, position, sizeof(string_length));
+        position += sizeof(string_length);
+
+        char buffer[2048];
+        size_t output_length = sizeof(buffer);
+        size_t input_length =
+            msg->message_size -
+            (sizeof(type_id) + sizeof(uint32_t) + string_length);
+        if (!PrintMessage(buffer, &output_length, position + string_length,
+                          &input_length, ::aos::type_cache::Get(type_id))) {
+          LOG(FATAL, "printing message (%.*s) of type %s into %zu-byte buffer "
+                     "failed\n",
+              static_cast<int>(string_length), position,
+              ::aos::type_cache::Get(type_id).name.c_str(), sizeof(buffer));
+        }
+        if (input_length > 0) {
+          LOG(WARNING, "%zu extra bytes on message of type %s\n",
+              input_length, ::aos::type_cache::Get(type_id).name.c_str());
+        }
+        fprintf(stdout, AOS_LOGGING_BASE_FORMAT "%.*s: %.*s\n", BASE_ARGS,
+                static_cast<int>(string_length), position,
+                static_cast<int>(sizeof(buffer) - output_length), buffer);
+      } break;
+      case LogFileMessageHeader::MessageType::kMatrix: {
+        uint32_t type;
+        memcpy(&type, position, sizeof(type));
+        position += sizeof(type);
+
+        uint32_t string_length;
+        memcpy(&string_length, position, sizeof(string_length));
+        position += sizeof(string_length);
+
+        uint16_t rows;
+        memcpy(&rows, position, sizeof(rows));
+        position += sizeof(rows);
+        uint16_t cols;
+        memcpy(&cols, position, sizeof(cols));
+        position += sizeof(cols);
+
+        const size_t matrix_bytes =
+            msg->message_size -
+            (sizeof(type) + sizeof(uint32_t) + sizeof(uint16_t) +
+             sizeof(uint16_t) + string_length);
+        CHECK_EQ(matrix_bytes, ::aos::MessageType::Sizeof(type) * rows * cols);
+        char buffer[2048];
+        size_t output_length = sizeof(buffer);
+        if (!::aos::PrintMatrix(buffer, &output_length,
+                                position + string_length, type, rows, cols)) {
+          LOG(FATAL, "printing %dx%d matrix of type %" PRIu32 " failed\n", rows,
+              cols, type);
+        }
+        fprintf(stdout, AOS_LOGGING_BASE_FORMAT "%.*s: %.*s\n", BASE_ARGS,
+                static_cast<int>(string_length), position,
+                static_cast<int>(sizeof(buffer) - output_length), buffer);
+      } break;
+      case LogFileMessageHeader::MessageType::kStructType:
+        LOG(FATAL, "shouldn't get here\n");
+        break;
+    }
+#undef BASE_ARGS
+  } while (msg != NULL);
+}
diff --git a/aos/linux_code/logging/log_replay.cc b/aos/linux_code/logging/log_replay.cc
new file mode 100644
index 0000000..32991de
--- /dev/null
+++ b/aos/linux_code/logging/log_replay.cc
@@ -0,0 +1,44 @@
+#include "aos/linux_code/logging/log_replay.h"
+
+namespace aos {
+namespace logging {
+namespace linux_code {
+
+bool LogReplayer::ProcessMessage() {
+  const LogFileMessageHeader *message = reader_->ReadNextMessage(false);
+  if (message == nullptr) return true;
+  if (message->type != LogFileMessageHeader::MessageType::kStruct) return false;
+
+  const char *position = reinterpret_cast<const char *>(message + 1);
+
+  ::std::string process(position, message->name_size);
+  position += message->name_size;
+
+  uint32_t type_id;
+  memcpy(&type_id, position, sizeof(type_id));
+  position += sizeof(type_id);
+
+  uint32_t message_length;
+  memcpy(&message_length, position, sizeof(message_length));
+  position += sizeof(message_length);
+  ::std::string message_text(position, message_length);
+  position += message_length;
+
+  size_t split_index = message_text.find_first_of(':') + 2;
+  split_index = message_text.find_first_of(':', split_index) + 2;
+  message_text = message_text.substr(split_index);
+
+  auto handler = handlers_.find(Key(process, message_text));
+  if (handler == handlers_.end()) return false;
+
+  handler->second->HandleStruct(
+      ::aos::time::Time(message->time_sec, message->time_nsec), type_id,
+      position,
+      message->message_size -
+          (sizeof(type_id) + sizeof(message_length) + message_length));
+  return false;
+}
+
+}  // namespace linux_code
+}  // namespace logging
+}  // namespace aos
diff --git a/aos/linux_code/logging/log_replay.h b/aos/linux_code/logging/log_replay.h
new file mode 100644
index 0000000..942f26f
--- /dev/null
+++ b/aos/linux_code/logging/log_replay.h
@@ -0,0 +1,164 @@
+#ifndef AOS_LINUX_CODE_LOGGING_LOG_REPLAY_H_
+#define AOS_LINUX_CODE_LOGGING_LOG_REPLAY_H_
+
+#include <unordered_map>
+#include <string>
+#include <functional>
+#include <memory>
+
+#include "aos/linux_code/logging/binary_log_file.h"
+#include "aos/common/queue.h"
+#include "aos/common/logging/logging.h"
+#include "aos/common/macros.h"
+#include "aos/linux_code/ipc_lib/queue.h"
+#include "aos/common/queue_types.h"
+
+namespace aos {
+namespace logging {
+namespace linux_code {
+
+// Manages pulling logged queue messages out of log files.
+//
+// Basic usage:
+//   - Use the Add* methods to register handlers for various message sources.
+//   - Call OpenFile to open a log file.
+//   - Call ProcessMessage repeatedly until it returns true.
+//
+// This code could do something to adapt similar-but-not-identical
+// messages to the current versions, but currently it will LOG(FATAL) if any of
+// the messages don't match up exactly.
+class LogReplayer {
+ public:
+  LogReplayer() {}
+
+  // Gets ready to read messages from fd.
+  // Does not take ownership of fd.
+  void OpenFile(int fd) {
+    reader_.reset(new LogFileReader(fd));
+  }
+  // Closes the currently open file.
+  void CloseCurrentFile() { reader_.reset(); }
+  // Returns true if we have a file which is currently open.
+  bool HasCurrentFile() const { return reader_.get() != nullptr; }
+
+  // Processes a single message from the currently open file.
+  // Returns true if there are no more messages in the file.
+  // This will not call any of the handlers if the next message either has no
+  // registered handlers or is not a queue message.
+  bool ProcessMessage();
+
+  // Adds a handler for messages with a certain string from a certain process.
+  // T must be a Message with the same format as the messages generated by
+  // the .q files.
+  // LOG(FATAL)s for duplicate handlers.
+  template <class T>
+  void AddHandler(const ::std::string &process_name,
+                  const ::std::string &log_message,
+                  ::std::function<void(const T &message)> handler) {
+    CHECK(handlers_.emplace(
+        ::std::piecewise_construct,
+        ::std::forward_as_tuple(process_name, log_message),
+        ::std::forward_as_tuple(::std::unique_ptr<StructHandlerInterface>(
+            new TypedStructHandler<T>(handler)))).second);
+  }
+
+  // Adds a handler which takes messages and places them directly on a queue.
+  // T must be a Message with the same format as the messages generated by
+  // the .q files.
+  template <class T>
+  void AddDirectQueueSender(const ::std::string &process_name,
+                            const ::std::string &log_message,
+                            const ::aos::Queue<T> &queue) {
+    AddHandler(process_name, log_message,
+               ::std::function<void(const T &)>(
+                   QueueDumpStructHandler<T>(queue.name())));
+  }
+
+ private:
+  // A generic handler of struct log messages.
+  class StructHandlerInterface {
+   public:
+    virtual ~StructHandlerInterface() {}
+
+    virtual void HandleStruct(::aos::time::Time log_time, uint32_t type_id,
+                              const void *data, size_t data_size) = 0;
+  };
+
+  // Converts struct log messages to a message type and passes it to an
+  // ::std::function.
+  template <class T>
+  class TypedStructHandler : public StructHandlerInterface {
+   public:
+    TypedStructHandler(::std::function<void(const T &message)> handler)
+        : handler_(handler) {}
+
+    void HandleStruct(::aos::time::Time log_time, uint32_t type_id,
+                      const void *data, size_t data_size) override {
+      CHECK_EQ(type_id, T::GetType()->id);
+      T message;
+      CHECK_EQ(data_size, T::Size());
+      CHECK_EQ(data_size, message.Deserialize(static_cast<const char *>(data)));
+      message.sent_time = log_time;
+      handler_(message);
+    }
+
+   private:
+    const ::std::function<void(T message)> handler_;
+  };
+
+  // A callable class which dumps messages straight to a queue.
+  template <class T>
+  class QueueDumpStructHandler {
+   public:
+    QueueDumpStructHandler(const ::std::string &queue_name)
+        : queue_(RawQueue::Fetch(queue_name.c_str(), sizeof(T), T::kHash,
+                                 T::kQueueLength)) {}
+
+    void operator()(const T &message) {
+      LOG_STRUCT(DEBUG, "re-sending", message);
+      void *raw_message = queue_->GetMessage();
+      CHECK_NOTNULL(raw_message);
+      memcpy(raw_message, &message, sizeof(message));
+      CHECK(queue_->WriteMessage(raw_message, RawQueue::kOverride));
+    }
+
+   private:
+    ::aos::RawQueue *const queue_;
+  };
+
+  // A key for specifying log messages to give to a certain handler.
+  struct Key {
+    Key(const ::std::string &process_name, const ::std::string &log_message)
+        : process_name(process_name), log_message(log_message) {}
+
+    ::std::string process_name;
+    ::std::string log_message;
+  };
+
+  struct KeyHash {
+    size_t operator()(const Key &key) const {
+      return string_hash(key.process_name) ^
+             (string_hash(key.log_message) << 1);
+    }
+
+   private:
+    const ::std::hash<::std::string> string_hash = ::std::hash<::std::string>();
+  };
+  struct KeyEqual {
+    bool operator()(const Key &a, const Key &b) const {
+      return a.process_name == b.process_name && a.log_message == b.log_message;
+    }
+  };
+
+  ::std::unordered_map<const Key, ::std::unique_ptr<StructHandlerInterface>,
+                       KeyHash, KeyEqual> handlers_;
+  ::std::unique_ptr<LogFileReader> reader_;
+
+  DISALLOW_COPY_AND_ASSIGN(LogReplayer);
+};
+
+}  // namespace linux_code
+}  // namespace logging
+}  // namespace aos
+
+#endif  // AOS_LINUX_CODE_LOGGING_LOG_REPLAY_H_
diff --git a/aos/linux_code/logging/log_streamer.cc b/aos/linux_code/logging/log_streamer.cc
new file mode 100644
index 0000000..2fe7c04
--- /dev/null
+++ b/aos/linux_code/logging/log_streamer.cc
@@ -0,0 +1,51 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <time.h>
+#include <string.h>
+#include <string>
+#include <unistd.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <fcntl.h>
+#include <inttypes.h>
+
+#include "aos/linux_code/logging/linux_logging.h"
+#include "aos/linux_code/init.h"
+#include "aos/linux_code/ipc_lib/queue.h"
+#include "aos/common/logging/logging_impl.h"
+#include "aos/common/time.h"
+
+namespace aos {
+namespace logging {
+namespace linux_code {
+namespace {
+
+int LogStreamerMain() {
+  InitNRT();
+
+  const time::Time now = time::Time::Now();
+  printf("starting at %" PRId32 "s%" PRId32 "ns-----------------------------\n",
+         now.sec(), now.nsec());
+
+  while (true) {
+    const LogMessage *const msg = ReadNext();
+    if (msg == NULL) continue;
+
+    internal::PrintMessage(stdout, *msg);
+
+    logging::linux_code::Free(msg);
+  }
+
+  Cleanup();
+  return 0;
+}
+
+}  // namespace
+}  // namespace linux_code
+}  // namespace logging
+}  // namespace aos
+
+int main() {
+  return ::aos::logging::linux_code::LogStreamerMain();
+}
diff --git a/aos/linux_code/logging/logging.gyp b/aos/linux_code/logging/logging.gyp
new file mode 100644
index 0000000..2ae9e0b
--- /dev/null
+++ b/aos/linux_code/logging/logging.gyp
@@ -0,0 +1,73 @@
+{
+  'targets': [
+    # linux_* is dealt with by aos/build/aos.gyp:logging.
+    {
+      'target_name': 'log_replay',
+      'type': 'static_library',
+      'sources': [
+        'log_replay.cc',
+      ],
+      'dependencies': [
+        'binary_log_file',
+        '<(AOS)/common/common.gyp:queues',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:queue',
+      ],
+    },
+    {
+      'target_name': 'binary_log_writer',
+      'type': 'executable',
+      'sources': [
+        'binary_log_writer.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(AOS)/linux_code/linux_code.gyp:configuration',
+        '<(AOS)/common/common.gyp:die',
+        'binary_log_file',
+        '<(AOS)/common/common.gyp:queue_types',
+      ],
+    },
+    {
+      'target_name': 'log_streamer',
+      'type': 'executable',
+      'sources': [
+        'log_streamer.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:queue',
+      ],
+    },
+    {
+      'target_name': 'log_displayer',
+      'type': 'executable',
+      'sources': [
+        'log_displayer.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        'binary_log_file',
+        '<(AOS)/common/common.gyp:queue_types',
+        '<(AOS)/linux_code/linux_code.gyp:configuration',
+      ],
+    },
+    {
+      'target_name': 'binary_log_file',
+      'type': 'static_library',
+      'sources': [
+        'binary_log_file.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/build/aos.gyp:logging',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/build/aos.gyp:logging',
+      ],
+    },
+  ],
+}
diff --git a/aos/linux_code/output/HTTPServer.cpp b/aos/linux_code/output/HTTPServer.cpp
new file mode 100644
index 0000000..d18572b
--- /dev/null
+++ b/aos/linux_code/output/HTTPServer.cpp
@@ -0,0 +1,152 @@
+#include "aos/linux_code/output/HTTPServer.h"
+
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+#include <memory>
+
+#include "event2/event.h"
+
+#include "aos/common/scoped_fd.h"
+#include "aos/common/unique_malloc_ptr.h"
+
+namespace aos {
+namespace http {
+
+HTTPServer::HTTPServer(const char *directory, uint16_t port) :
+    directory_(directory), base_(event_base_new()), http_(evhttp_new(base_)) {
+  if (base_ == NULL) {
+    LOG(FATAL, "couldn't create an event_base\n");
+  }
+  if (http_ == NULL) {
+    LOG(FATAL, "couldn't create an evhttp\n");
+  }
+  if (evhttp_bind_socket(http_, "0.0.0.0", port) != 0) {
+    LOG(FATAL, "evhttp_bind_socket(%p, \"0.0.0.0\", %" PRIu16 ") failed\n",
+        http_, port);
+  }
+  evhttp_set_gencb(http_, StaticServeFile, this);
+}
+
+void HTTPServer::AddPage(const std::string &path,
+                         void (*handler)(evhttp_request *, void *), void *data) {
+  switch (evhttp_set_cb(http_, path.c_str(), handler, data)) {
+    case 0:
+      LOG(DEBUG, "set callback handler for '%s'\n", path.c_str());
+      break;
+    case -1:
+      LOG(INFO, "changed callback handler for '%s'\n", path.c_str());
+      break;
+    default:
+      LOG(WARNING, "evhttp_set_cb(%p, %s, %p, %p) failed\n", http_, path.c_str(),
+          handler, data);
+      break;
+  }
+}
+
+void HTTPServer::AddStandardHeaders(evhttp_request *request) {
+  if (evhttp_add_header(evhttp_request_get_output_headers(request),
+                        "Server", "aos::HTTPServer/0.0") == -1) {
+    LOG(WARNING, "adding Server header failed\n");
+  }
+}
+
+namespace {
+// All of these functions return false, NULL, or -1 if they fail (and send back
+// an error).
+
+// Returns the path of the file that is being requested.
+const char *GetPath(evhttp_request *request) {
+  // Docs are unclear whether this needs freeing, but it looks like it just
+  // returns an internal field of the request.
+  // Running valgrind with no freeing of uri or path doesn't report anything
+  // related to this code.
+  const evhttp_uri *uri = evhttp_request_get_evhttp_uri(request);
+  const char *path = evhttp_uri_get_path(uri);
+  if (path == NULL) {
+    evhttp_send_error(request, HTTP_BADREQUEST, "need a path");
+    return NULL;
+  }
+  if (strstr(path, "..") != NULL) {
+    evhttp_send_error(request, HTTP_NOTFOUND, "no .. allowed!!");
+    return NULL;
+  }
+  return path;
+}
+// Returns an fd open for reading for the file at "directory/path".
+int OpenFile(evhttp_request *request, const char *path,
+                   const char *directory) {
+  char *temp;
+  if (asprintf(&temp, "%s/%s", directory, path) == -1) {
+    PLOG(WARNING, "asprintf(%p, \"%%s/%%s\", %p, %p) failed",
+         &temp, directory, path);
+    evhttp_send_error(request, HTTP_INTERNAL, NULL);
+    return -1;
+  }
+  const unique_c_ptr<char> filename(temp);
+  ScopedFD file(open(filename.get(), O_RDONLY));
+  if (!file) {
+    if (errno == ENOENT) {
+      evhttp_send_error(request, HTTP_NOTFOUND, NULL);
+      return -1;
+    }
+    PLOG(ERROR, "open('%s', 0) failed", filename.get(),
+    evhttp_send_error(request, HTTP_INTERNAL, NULL);
+    return -1;
+  }
+  return file.release();
+}
+// Returns the size of the file specified by the given fd.
+off_t GetSize(int file) {
+  struct stat info;
+  if (fstat(file, &info) == -1) {
+    PLOG(ERROR, "stat(%d, %p) failed", file, &info);
+    return -1;
+  }
+  return info.st_size;
+}
+bool SendFileResponse(evhttp_request *request, int file_num) {
+  ScopedFD file(file_num);
+  const off_t size = GetSize(file.get());
+  if (size == -1) {
+    evhttp_send_error(request, HTTP_INTERNAL, NULL);
+    return false;
+  }
+  evbuffer *const buf = evhttp_request_get_output_buffer(request);
+  if (evbuffer_add_file(buf, file.get(), 0, size) == -1) {
+    LOG(WARNING, "evbuffer_add_file(%p, %d, 0, %jd) failed\n", buf,
+        file.get(), static_cast<intmax_t>(size));
+    evhttp_send_error(request, HTTP_INTERNAL, NULL);
+    return false;
+  } else {
+    // it succeeded, so evhttp takes ownership
+    file.release();
+  }
+  evhttp_send_reply(request, HTTP_OK, NULL, NULL);
+  return true;
+}
+
+}  // namespace
+void HTTPServer::ServeFile(evhttp_request *request) {
+  AddStandardHeaders(request);
+
+  const char *path = GetPath(request);
+  if (path == NULL) return;
+
+  ScopedFD file(OpenFile(request, path, directory_));
+  if (!file) return;
+
+  if (!SendFileResponse(request, file.release())) return;
+}
+
+void HTTPServer::Run() {
+  event_base_dispatch(base_);
+  LOG(FATAL, "event_base_dispatch returned\n");
+}
+
+}  // namespace http
+}  // namespace aos
diff --git a/aos/linux_code/output/HTTPServer.h b/aos/linux_code/output/HTTPServer.h
new file mode 100644
index 0000000..99eb295
--- /dev/null
+++ b/aos/linux_code/output/HTTPServer.h
@@ -0,0 +1,58 @@
+#include "event2/buffer.h"
+#include "event2/http.h"
+
+#include <string>
+
+namespace aos {
+namespace http {
+
+// An HTTP server that serves files from a directory using libevent.
+// Also allows configuring certain URLs to be dynamically generated.
+class HTTPServer {
+ public:
+  HTTPServer(const char *directory, uint16_t port);
+  // Starts serving pages.
+  // Might not clean up everything before returning.
+  void Run();
+ protected:
+  template<class T> class MemberHandler {
+   public:
+    typedef void (T::*Handler)(evhttp_request *);
+    struct Holder {
+      T *self;
+      Handler handler;
+    };
+    static void Call(evhttp_request *request, void *handler_in) {
+      const Holder *const holder = static_cast<Holder *>(handler_in);
+      AddStandardHeaders(request);
+      ((holder->self)->*(holder->handler))(request);
+    }
+  };
+  void AddPage(const std::string &path, void (*handler)(evhttp_request *, void *),
+               void *data);
+  template<class T> void AddPage(const std::string &path,
+                                 typename MemberHandler<T>::Handler handler,
+                                 T *self) {
+    // have to put "typename" in, so the typedef makes it clearer
+    typedef typename MemberHandler<T>::Holder HolderType;
+    AddPage(path, MemberHandler<T>::Call, new HolderType{self, handler});
+  }
+  // This gets set up as the generic handler.
+  // It can also be called separately to serve the file that the request is
+  // requesting from the filesystem.
+  void ServeFile(evhttp_request *request);
+ private:
+  // The directory where files to be served come from.
+  const char *directory_;
+  // The main libevent structure.
+  event_base *const base_;
+  // The libevent HTTP server handle.
+  evhttp *const http_;
+  static void AddStandardHeaders(evhttp_request *request);
+  static void StaticServeFile(evhttp_request *request, void *self) {
+    static_cast<HTTPServer *>(self)->ServeFile(request);
+  }
+};
+
+}  // namespace http
+}  // namespace aos
diff --git a/aos/linux_code/output/ctemplate_cache.cc b/aos/linux_code/output/ctemplate_cache.cc
new file mode 100644
index 0000000..cf961c6
--- /dev/null
+++ b/aos/linux_code/output/ctemplate_cache.cc
@@ -0,0 +1,24 @@
+#include "aos/linux_code/output/ctemplate_cache.h"
+
+#include "aos/linux_code/configuration.h"
+#include "aos/common/once.h"
+
+namespace aos {
+namespace http {
+
+namespace {
+ctemplate::TemplateCache *CreateTemplateCache() {
+  ctemplate::TemplateCache *r = new ctemplate::TemplateCache();
+
+  r->SetTemplateRootDirectory(configuration::GetRootDirectory());
+
+  return r;
+}
+}  // namespace
+ctemplate::TemplateCache *get_template_cache() {
+  static Once<ctemplate::TemplateCache> once(CreateTemplateCache);
+  return once.Get();
+}
+
+}  // namespace http
+}  // namespace aos
diff --git a/aos/linux_code/output/ctemplate_cache.h b/aos/linux_code/output/ctemplate_cache.h
new file mode 100644
index 0000000..7e5dc3d
--- /dev/null
+++ b/aos/linux_code/output/ctemplate_cache.h
@@ -0,0 +1,12 @@
+#include "ctemplate/template_cache.h"
+
+namespace aos {
+namespace http {
+
+// Retrieves the cache used by all of the aos functions etc.
+// This cache will have its root directory set to the directory where the
+// executable is running from.
+ctemplate::TemplateCache *get_template_cache();
+
+}  // namespace http
+}  // namespace aos
diff --git a/aos/linux_code/output/evhttp_ctemplate_emitter.cc b/aos/linux_code/output/evhttp_ctemplate_emitter.cc
new file mode 100644
index 0000000..2301ffb
--- /dev/null
+++ b/aos/linux_code/output/evhttp_ctemplate_emitter.cc
@@ -0,0 +1,18 @@
+#include "aos/linux_code/output/evhttp_ctemplate_emitter.h"
+
+#include "aos/common/logging/logging.h"
+
+namespace aos {
+namespace http {
+
+void EvhttpCtemplateEmitter::Emit(const char *s, size_t slen) {
+  if (error_) return;
+  if (evbuffer_add(buf_, s, slen) != 0) {
+    LOG(ERROR, "evbuffer_add(%p, %p, %zd) failed\n",
+        buf_, s, slen);
+    error_ = true;
+  }
+}
+
+}  // namespace http
+}  // namespace aos
diff --git a/aos/linux_code/output/evhttp_ctemplate_emitter.h b/aos/linux_code/output/evhttp_ctemplate_emitter.h
new file mode 100644
index 0000000..5b8e96a
--- /dev/null
+++ b/aos/linux_code/output/evhttp_ctemplate_emitter.h
@@ -0,0 +1,34 @@
+#ifndef AOS_LINUX_CODE_OUTPUT_EVHTTP_CTEMPLATE_EMITTER_H_
+#define AOS_LINUX_CODE_OUTPUT_EVHTTP_CTEMPLATE_EMITTER_H_
+
+#include <string.h>
+
+#include "event2/buffer.h"
+#include "ctemplate/template_emitter.h"
+
+namespace aos {
+namespace http {
+
+// Writes everything directly into an evbuffer*.
+// Handles errors by refusing to write anything else into the buffer and storing
+// the state (which can be retrieved with error()).
+class EvhttpCtemplateEmitter : public ctemplate::ExpandEmitter {
+ public:
+  EvhttpCtemplateEmitter(evbuffer *buf) : buf_(buf), error_(false) {}
+  virtual void Emit(char c) { Emit(&c, 1); };
+  virtual void Emit(const std::string& s) { Emit(s.data(), s.size()); };
+  virtual void Emit(const char* s) { Emit(s, strlen(s)); }
+  virtual void Emit(const char* s, size_t slen);
+  // Retrieves whether or not there has been an error. If true, the error will
+  // already have been logged.
+  bool error() { return error_; }
+
+ private:
+  evbuffer *const buf_;
+  bool error_;
+};
+
+}  // namespace http
+}  // namespace aos
+
+#endif  // AOS_LINUX_CODE_OUTPUT_EVHTTP_CTEMPLATE_EMITTER_H_
diff --git a/aos/linux_code/output/output.gyp b/aos/linux_code/output/output.gyp
new file mode 100644
index 0000000..f697630
--- /dev/null
+++ b/aos/linux_code/output/output.gyp
@@ -0,0 +1,24 @@
+{
+  'targets': [
+    {
+      'target_name': 'http_server',
+      'type': 'static_library',
+      'sources': [
+        'HTTPServer.cpp',
+        'evhttp_ctemplate_emitter.cc',
+        'ctemplate_cache.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):libevent',
+        '<(EXTERNALS):ctemplate',
+        '<(AOS)/common/common.gyp:once',
+        '<(AOS)/common/common.gyp:scoped_fd',
+        '<(AOS)/build/aos.gyp:logging',
+      ],
+      'export_dependent_settings': [
+        '<(EXTERNALS):libevent',
+        '<(EXTERNALS):ctemplate',
+      ],
+    },
+  ],
+}
diff --git a/aos/linux_code/queue-tmpl.h b/aos/linux_code/queue-tmpl.h
new file mode 100644
index 0000000..25eb8d9
--- /dev/null
+++ b/aos/linux_code/queue-tmpl.h
@@ -0,0 +1,116 @@
+namespace aos {
+
+template <class T>
+bool ScopedMessagePtr<T>::Send() {
+  assert(msg_ != NULL);
+  msg_->SetTimeToNow();
+  assert(queue_ != NULL);
+  bool return_value = queue_->WriteMessage(msg_, RawQueue::kOverride);
+  msg_ = NULL;
+  return return_value;
+}
+
+template <class T>
+bool ScopedMessagePtr<T>::SendBlocking() {
+  assert(msg_ != NULL);
+  msg_->SetTimeToNow();
+  assert(queue_ != NULL);
+  bool return_value = queue_->WriteMessage(msg_, RawQueue::kBlock);
+  msg_ = NULL;
+  return return_value;
+}
+
+template <class T>
+void ScopedMessagePtr<T>::reset(T *msg) {
+  if (queue_ != NULL && msg_ != NULL) {
+    queue_->FreeMessage(msg_);
+  }
+  msg_ = msg;
+}
+
+template <class T>
+void Queue<T>::Init() {
+  if (queue_ == NULL) {
+    queue_ = RawQueue::Fetch(queue_name_, sizeof(T),
+                             static_cast<int>(T::kHash),
+                             T::kQueueLength);
+    queue_msg_.set_queue(queue_);
+  }
+}
+
+template <class T>
+void Queue<T>::Clear() {
+  if (queue_ != NULL) {
+    queue_msg_.reset();
+    queue_ = NULL;
+    queue_msg_.set_queue(NULL);
+  }
+  index_ = 0;
+}
+
+template <class T>
+bool Queue<T>::FetchNext() {
+  Init();
+  const T *msg = static_cast<const T *>(
+      queue_->ReadMessageIndex(RawQueue::kNonBlock, &index_));
+  // Only update the internal pointer if we got a new message.
+  if (msg != NULL) {
+    queue_msg_.reset(msg);
+  }
+  return msg != NULL;
+}
+
+template <class T>
+void Queue<T>::FetchNextBlocking() {
+  Init();
+  const T *msg = static_cast<const T *>(
+      queue_->ReadMessageIndex(RawQueue::kBlock, &index_));
+  queue_msg_.reset(msg);
+  assert (msg != NULL);
+}
+
+template <class T>
+bool Queue<T>::FetchLatest() {
+  Init();
+  static constexpr Options<RawQueue> kOptions =
+      RawQueue::kFromEnd | RawQueue::kNonBlock;
+  const T *msg =
+      static_cast<const T *>(queue_->ReadMessageIndex(kOptions, &index_));
+  // Only update the internal pointer if we got a new message.
+  if (msg != NULL && msg != queue_msg_.get()) {
+    queue_msg_.reset(msg);
+    return true;
+  }
+  // The message has to get freed if we didn't use it (and RawQueue::FreeMessage
+  // is ok to call on NULL).
+  queue_->FreeMessage(msg);
+  return false;
+}
+
+template <class T>
+void Queue<T>::FetchAnother() {
+  if (!FetchLatest()) FetchNextBlocking();
+}
+
+template <class T>
+ScopedMessagePtr<T> Queue<T>::MakeMessage() {
+  Init();
+  return ScopedMessagePtr<T>(queue_, MakeRawMessage());
+}
+
+template <class T>
+T *Queue<T>::MakeRawMessage() {
+  T *ret = static_cast<T *>(queue_->GetMessage());
+  assert(ret != NULL);
+  return ret;
+}
+
+template <class T>
+aos::MessageBuilder<T> Queue<T>::MakeWithBuilder() {
+  Init();
+  T *const ret = MakeRawMessage();
+  ret->Zero();
+  return aos::MessageBuilder<T>(queue_, ret);
+}
+
+}  // namespace aos
diff --git a/aos/linux_code/starter/starter.cc b/aos/linux_code/starter/starter.cc
new file mode 100644
index 0000000..616bbdb
--- /dev/null
+++ b/aos/linux_code/starter/starter.cc
@@ -0,0 +1,819 @@
+// This has to come before anybody drags in <stdlib.h> or else we end up with
+// the wrong version of WIFEXITED etc (for one thing, they don't const-qualify
+// their casts) (sometimes at least).
+#include <sys/wait.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/inotify.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+#include <stdint.h>
+#include <errno.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include <map>
+#include <functional>
+#include <deque>
+#include <fstream>
+#include <queue>
+#include <list>
+#include <string>
+#include <vector>
+#include <memory>
+#include <set>
+
+#include <event2/event.h>
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/logging/logging_impl.h"
+#include "aos/linux_code/init.h"
+#include "aos/common/unique_malloc_ptr.h"
+#include "aos/common/time.h"
+#include "aos/common/once.h"
+#include "aos/common/libc/aos_strsignal.h"
+#include "aos/common/util/run_command.h"
+
+// This is the main piece of code that starts all of the rest of the code and
+// restarts it when the binaries are modified.
+//
+// Throughout, the code is not terribly concerned with thread safety because
+// there is only 1 thread. It does some setup and then lets inotify run things
+// when appropriate.
+//
+// NOTE: This program should never exit nicely. It catches all nice attempts to
+// exit, forwards them to all of the children that it has started, waits for
+// them to exit nicely, and then SIGKILLs anybody left (which will always
+// include itself).
+
+using ::std::unique_ptr;
+
+namespace aos {
+namespace starter {
+
+// TODO(brians): split out the c++ libevent wrapper stuff into its own file(s)
+class EventBaseDeleter {
+ public:
+  void operator()(event_base *base) {
+    if (base == NULL) return;
+    event_base_free(base);
+  }
+};
+typedef unique_ptr<event_base, EventBaseDeleter> EventBaseUniquePtr;
+EventBaseUniquePtr libevent_base;
+
+class EventDeleter {
+ public:
+  void operator()(event *evt) {
+    if (evt == NULL) return;
+    if (event_del(evt) != 0) {
+      LOG(WARNING, "event_del(%p) failed\n", evt);
+    }
+  }
+};
+typedef unique_ptr<event, EventDeleter> EventUniquePtr;
+
+// Watches a file path for modifications. Once created, keeps watching until
+// destroyed or RemoveWatch() is called.
+// TODO(brians): split this out into its own file + tests
+class FileWatch {
+ public:
+  // Will call callback(value) when filename is modified.
+  // If value is NULL, then a pointer to this object will be passed instead.
+  //
+  // Watching for file creations is slightly different. To do that, pass true
+  // as create, the directory where the file will be created for filename, and
+  // the name of the file (without directory name) for check_filename.
+  FileWatch(std::string filename,
+            std::function<void(void *)> callback,
+            void *value,
+            bool create = false,
+            std::string check_filename = "")
+      : filename_(filename),
+        callback_(callback),
+        value_(value),
+        create_(create),
+        check_filename_(check_filename),
+        watch_(-1) {
+    init_once.Get();
+
+    CreateWatch();
+  }
+  // Cleans up everything.
+  ~FileWatch() {
+    if (watch_ != -1) {
+      RemoveWatch();
+    }
+  }
+
+  // After calling this method, this object won't really be doing much of
+  // anything besides possibly running its callback or something.
+  void RemoveWatch() {
+    CHECK_NE(watch_, -1);
+    CHECK_EQ(watch_to_remove_, -1);
+
+    if (inotify_rm_watch(notify_fd, watch_) == -1) {
+      PLOG(WARNING, "inotify_rm_watch(%d, %d) failed", notify_fd, watch_);
+    }
+    watch_to_remove_ = watch_;
+    watch_ = -1;
+  }
+
+ private:
+  // Performs the static initialization. Called by init_once from the
+  // constructor.
+  static void *Init() {
+    notify_fd = inotify_init1(IN_CLOEXEC);
+    EventUniquePtr notify_event(event_new(libevent_base.get(), notify_fd,
+                                          EV_READ | EV_PERSIST,
+                                          FileWatch::INotifyReadable, NULL));
+    event_add(notify_event.release(), NULL);
+    return NULL;
+  }
+
+  void RemoveWatchFromMap() {
+    int watch = watch_to_remove_;
+    if (watch == -1) {
+      CHECK_NE(watch_, -1);
+      watch = watch_;
+    }
+    if (watchers[watch] != this) {
+      LOG(WARNING, "watcher for %s (%p) didn't find itself in the map\n",
+          filename_.c_str(), this);
+    } else {
+      watchers.erase(watch);
+    }
+    LOG(DEBUG, "removed watch ID %d\n", watch);
+    if (watch_to_remove_ == -1) {
+      watch_ = -1;
+    } else {
+      watch_to_remove_ = -1;
+    }
+  }
+
+  void CreateWatch() {
+    CHECK_EQ(watch_, -1);
+    watch_ = inotify_add_watch(notify_fd, filename_.c_str(),
+                               create_ ? IN_CREATE : (IN_ATTRIB |
+                                                     IN_MODIFY |
+                                                     IN_DELETE_SELF |
+                                                     IN_MOVE_SELF));
+    if (watch_ == -1) {
+      PLOG(FATAL, "inotify_add_watch(%d, %s,"
+                  " %s ? IN_CREATE : (IN_ATTRIB | IN_MODIFY)) failed",
+           notify_fd, filename_.c_str(), create_ ? "true" : "false");
+    }
+    watchers[watch_] = this;
+    LOG(DEBUG, "watch for %s is %d\n", filename_.c_str(), watch_);
+  }
+
+  // This gets set up as the callback for EV_READ on the inotify file
+  // descriptor. It calls FileNotified on the appropriate instance.
+  static void INotifyReadable(int /*fd*/, short /*events*/, void *) {
+    unsigned int to_read;
+    // Use FIONREAD to figure out how many bytes there are to read.
+    if (ioctl(notify_fd, FIONREAD, &to_read) < 0) {
+      PLOG(FATAL, "FIONREAD(%d, %p) failed", notify_fd, &to_read);
+    }
+    inotify_event *notifyevt = static_cast<inotify_event *>(malloc(to_read));
+    const char *end = reinterpret_cast<char *>(notifyevt) + to_read;
+    aos::unique_c_ptr<inotify_event> freer(notifyevt);
+
+    ssize_t ret = read(notify_fd, notifyevt, to_read);
+    if (ret < 0) {
+      PLOG(FATAL, "read(%d, %p, %u) failed", notify_fd, notifyevt, to_read);
+    }
+    if (static_cast<size_t>(ret) != to_read) {
+      LOG(ERROR, "read(%d, %p, %u) returned %zd instead of %u\n",
+          notify_fd, notifyevt, to_read, ret, to_read);
+      return;
+    }
+
+    // Keep looping through until we get to the end because inotify does return
+    // multiple events at once.
+    while (reinterpret_cast<char *>(notifyevt) < end) {
+      if (watchers.count(notifyevt->wd) != 1) {
+        LOG(WARNING, "couldn't find whose watch ID %d is\n", notifyevt->wd);
+      } else {
+        LOG(DEBUG, "mask=%" PRIu32 "\n", notifyevt->mask);
+        // If the watch was removed.
+        if (notifyevt->mask & IN_IGNORED) {
+          watchers[notifyevt->wd]->WatchDeleted();
+        } else {
+          watchers[notifyevt->wd]
+              ->FileNotified((notifyevt->len > 0) ? notifyevt->name : NULL);
+        }
+      }
+
+      notifyevt = reinterpret_cast<inotify_event *>(
+          __builtin_assume_aligned(reinterpret_cast<char *>(notifyevt) +
+                                       sizeof(*notifyevt) + notifyevt->len,
+                                   alignof(inotify_event)));
+    }
+  }
+
+  // INotifyReadable calls this method whenever the watch for our file gets
+  // removed somehow.
+  void WatchDeleted() {
+    LOG(DEBUG, "watch for %s deleted\n", filename_.c_str());
+    RemoveWatchFromMap();
+    CreateWatch();
+  }
+
+  // INotifyReadable calls this method whenever the watch for our file triggers.
+  void FileNotified(const char *filename) {
+    CHECK_NE(watch_, -1);
+    LOG(DEBUG, "got a notification for %s\n", filename_.c_str());
+
+    if (!check_filename_.empty()) {
+      if (filename == NULL) {
+        return;
+      }
+      if (std::string(filename) != check_filename_) {
+        return;
+      }
+    }
+
+    callback_((value_ == NULL) ? this : value_);
+  }
+
+  // To make sure that Init gets called exactly once.
+  static ::aos::Once<void> init_once;
+
+  const std::string filename_;
+  const std::function<void(void *)> callback_;
+  void *const value_;
+  const bool create_;
+  std::string check_filename_;
+
+  // The watch descriptor or -1 if we don't have one any more.
+  int watch_;
+  // The watch that we still have to take out of the map once we get the
+  // IN_IGNORED or -1.
+  int watch_to_remove_ = -1;
+
+  // Map from watch IDs to instances of this class.
+  // <https://patchwork.kernel.org/patch/73192/> ("inotify: do not reuse watch
+  // descriptors") says they won't get reused, but that shouldn't be counted on
+  // because we might have a modified/different version/whatever kernel.
+  static std::map<int, FileWatch *> watchers;
+  // The inotify(7) file descriptor.
+  static int notify_fd;
+
+  DISALLOW_COPY_AND_ASSIGN(FileWatch);
+};
+::aos::Once<void> FileWatch::init_once(FileWatch::Init);
+std::map<int, FileWatch *> FileWatch::watchers;
+int FileWatch::notify_fd;
+
+// Runs the given command and returns its first line of output (not including
+// the \n). LOG(FATAL)s if the command has an exit status other than 0 or does
+// not print out an entire line.
+std::string RunCommand(std::string command) {
+  // popen(3) might fail and not set it.
+  errno = 0;
+  FILE *pipe = popen(command.c_str(), "r");
+  if (pipe == NULL) {
+    PLOG(FATAL, "popen(\"%s\", \"r\") failed", command.c_str());
+  }
+
+  // result_size is how many bytes result is currently allocated to.
+  size_t result_size = 128, read = 0;
+  unique_c_ptr<char> result(static_cast<char *>(malloc(result_size)));
+  while (true) {
+    // If we filled up the buffer, then realloc(3) it bigger.
+    if (read == result_size) {
+      result_size *= 2;
+      void *new_result = realloc(result.get(), result_size);
+      if (new_result == NULL) {
+        PLOG(FATAL, "realloc(%p, %zd) failed", result.get(), result_size);
+      } else {
+        result.release();
+        result = unique_c_ptr<char>(static_cast<char *>(new_result));
+      }
+    }
+
+    size_t ret = fread(result.get() + read, 1, result_size - read, pipe);
+    // If the read didn't fill up the whole buffer, check to see if it was
+    // because of an error.
+    if (ret < result_size - read) {
+      if (ferror(pipe)) {
+        PLOG(FATAL, "couldn't finish reading output of \"%s\"\n",
+             command.c_str());
+      }
+    }
+    read += ret;
+    if (read > 0 && result.get()[read - 1] == '\n') {
+      break;
+    }
+
+    if (feof(pipe)) {
+      LOG(FATAL, "`%s` failed. didn't print a whole line\n", command.c_str());
+    }
+  }
+
+  // Get rid of the first \n and anything after it.
+  *strchrnul(result.get(), '\n') = '\0';
+
+  int child_status = pclose(pipe);
+  if (child_status == -1) {
+    PLOG(FATAL, "pclose(%p) failed", pipe);
+  }
+
+  if (child_status != 0) {
+    LOG(FATAL, "`%s` failed. return %d\n", command.c_str(), child_status);
+  }
+
+  return std::string(result.get());
+}
+
+// Will call callback(arg) after time.
+void Timeout(time::Time time, void (*callback)(int, short, void *), void *arg) {
+  EventUniquePtr timeout(evtimer_new(libevent_base.get(), callback, arg));
+  struct timeval time_timeval = time.ToTimeval();
+  if (evtimer_add(timeout.release(), &time_timeval) != 0) {
+    LOG(FATAL, "evtimer_add(%p, %p) failed\n",
+        timeout.release(), &time_timeval);
+  }
+}
+
+class Child;
+// This is where all of the Child instances except core live.
+std::vector<unique_ptr<Child>> children;
+// A global place to hold on to which child is core.
+unique_ptr<Child> core;
+
+// Represents a child process. It will take care of restarting itself etc.
+class Child {
+ public:
+  // command is the (space-separated) command to run and its arguments.
+  Child(const std::string &command) : pid_(-1),
+        stat_at_start_valid_(false) {
+    if (!restart_timeout) {
+      restart_timeout = EventUniquePtr(
+          evtimer_new(libevent_base.get(), StaticDoRestart, nullptr));
+    }
+    const char *start, *end;
+    start = command.c_str();
+    while (true) {
+      end = strchrnul(start, ' ');
+      args_.push_back(std::string(start, end - start));
+      start = end + 1;
+      if (*end == '\0') {
+        break;
+      }
+    }
+
+    original_binary_ = RunCommand("which " + args_[0]);
+    binary_ = original_binary_ + ".stm";
+
+    watcher_ = unique_ptr<FileWatch>(
+        new FileWatch(original_binary_, StaticFileModified, this));
+
+    Start();
+  }
+
+  pid_t pid() { return pid_; }
+
+  // This gets called whenever the actual process dies and should (probably) be
+  // restarted.
+  void ProcessDied() {
+    pid_ = -1;
+    restarts_.push(time::Time::Now());
+    if (restarts_.size() > kMaxRestartsNumber) {
+      time::Time oldest = restarts_.front();
+      restarts_.pop();
+      if ((time::Time::Now() - oldest) <= kMaxRestartsTime) {
+        LOG(WARNING, "process %s getting restarted too often\n", name());
+        Timeout(kResumeWait, StaticStart, this);
+        return;
+      }
+    }
+    Start();
+  }
+
+  // Returns a name for logging purposes.
+  const char *name() {
+    return args_[0].c_str();
+  }
+
+ private:
+  struct CheckDiedStatus {
+    Child *self;
+    pid_t old_pid;
+  };
+
+  // How long to wait for a child to die nicely.
+  static constexpr time::Time kProcessDieTime = time::Time::InSeconds(2);
+
+  // How long to wait after the file is modified to restart it.
+  // This is important because some programs like modifying the binaries by
+  // writing them in little bits, which results in attempting to start partial
+  // binaries without this.
+  static constexpr time::Time kRestartWaitTime = time::Time::InSeconds(1.5);
+
+  // Only kMaxRestartsNumber restarts will be allowed in kMaxRestartsTime.
+  static constexpr time::Time kMaxRestartsTime = time::Time::InSeconds(4);
+  static const size_t kMaxRestartsNumber = 3;
+  // How long to wait if it gets restarted too many times.
+  static constexpr time::Time kResumeWait = time::Time::InSeconds(5);
+
+  static void StaticFileModified(void *self) {
+    static_cast<Child *>(self)->FileModified();
+  }
+
+  void FileModified() {
+    LOG(DEBUG, "file for %s modified\n", name());
+    struct timeval restart_time_timeval = kRestartWaitTime.ToTimeval();
+    // This will reset the timeout again if it hasn't run yet.
+    if (evtimer_add(restart_timeout.get(), &restart_time_timeval) != 0) {
+      LOG(FATAL, "evtimer_add(%p, %p) failed\n",
+          restart_timeout.get(), &restart_time_timeval);
+    }
+    waiting_to_restart.insert(this);
+  }
+
+  static void StaticDoRestart(int, short, void *) {
+    LOG(DEBUG, "restarting everything that needs it\n");
+    if (waiting_to_restart.find(core.get()) != waiting_to_restart.end()) {
+      core->DoRestart();
+      waiting_to_restart.erase(core.get());
+    }
+    for (auto c : waiting_to_restart) {
+      c->DoRestart();
+    }
+    waiting_to_restart.clear();
+  }
+
+  // Called after somebody else has finished modifying the file.
+  void DoRestart() {
+    fprintf(stderr, "DoRestart(%s)\n", binary_.c_str());
+    if (stat_at_start_valid_) {
+      struct stat current_stat;
+      if (stat(original_binary_.c_str(), &current_stat) == -1) {
+        PLOG(FATAL, "stat(%s, %p) failed",
+             original_binary_.c_str(), &current_stat);
+      }
+      if (current_stat.st_mtime == stat_at_start_.st_mtime) {
+        LOG(DEBUG, "ignoring trigger for %s because mtime didn't change\n",
+            name());
+        return;
+      }
+    }
+
+    if (this == core.get()) {
+      fprintf(stderr, "Restarting core -> exiting now.\n");
+      exit(0);
+    }
+    if (pid_ != -1) {
+      LOG(DEBUG, "sending SIGTERM to child %d to restart it\n", pid_);
+      if (kill(pid_, SIGTERM) == -1) {
+        PLOG(WARNING, "kill(%d, SIGTERM) failed", pid_);
+      }
+      CheckDiedStatus *status = new CheckDiedStatus();
+      status->self = this;
+      status->old_pid = pid_;
+      Timeout(kProcessDieTime, StaticCheckDied, status);
+    } else {
+      LOG(WARNING, "%s restart attempted but not running\n", name());
+    }
+  }
+
+  static void StaticCheckDied(int, short, void *status_in) {
+    CheckDiedStatus *status = static_cast<CheckDiedStatus *>(status_in);
+    status->self->CheckDied(status->old_pid);
+    delete status;
+  }
+
+  // Checks to see if the child using the PID old_pid is still running.
+  void CheckDied(pid_t old_pid) {
+    if (pid_ == old_pid) {
+      LOG(WARNING, "child %d refused to die\n", old_pid);
+      if (kill(old_pid, SIGKILL) == -1) {
+        PLOG(WARNING, "kill(%d, SIGKILL) failed", old_pid);
+      }
+    }
+  }
+
+  static void StaticStart(int, short, void *self) {
+    static_cast<Child *>(self)->Start();
+  }
+
+  // Actually starts the child.
+  void Start() {
+    if (pid_ != -1) {
+      LOG(WARNING, "calling Start() but already have child %d running\n",
+          pid_);
+      if (kill(pid_, SIGKILL) == -1) {
+        PLOG(WARNING, "kill(%d, SIGKILL) failed", pid_);
+        return;
+      }
+      pid_ = -1;
+    }
+
+    // Remove the name that we run from (ie from a previous execution) and then
+    // hard link the real filename to it.
+    if (unlink(binary_.c_str()) != 0 && errno != ENOENT) {
+      PLOG(FATAL, "removing %s failed", binary_.c_str());
+    }
+    if (link(original_binary_.c_str(), binary_.c_str()) != 0) {
+      PLOG(FATAL, "link('%s', '%s') failed",
+           original_binary_.c_str(), binary_.c_str());
+    }
+
+    if (stat(original_binary_.c_str(), &stat_at_start_) == -1) {
+      PLOG(FATAL, "stat(%s, %p) failed",
+           original_binary_.c_str(), &stat_at_start_);
+    }
+    stat_at_start_valid_ = true;
+
+    if ((pid_ = fork()) == 0) {
+      ssize_t args_size = args_.size();
+      const char **argv = new const char *[args_size + 1];
+      for (int i = 0; i < args_size; ++i) {
+        argv[i] = args_[i].c_str();
+      }
+      argv[args_size] = NULL;
+      // The const_cast is safe because no code that might care if it gets
+      // modified can run afterwards.
+      execv(binary_.c_str(), const_cast<char **>(argv));
+      PLOG(FATAL, "execv(%s, %p) failed", binary_.c_str(), argv);
+      _exit(EXIT_FAILURE);
+    }
+    if (pid_ == -1) {
+      PLOG(FATAL, "forking to run \"%s\" failed", binary_.c_str());
+    }
+    LOG(DEBUG, "started \"%s\" successfully\n", binary_.c_str());
+  }
+
+  // A history of the times that this process has been restarted.
+  std::queue<time::Time, std::list<time::Time>> restarts_;
+
+  // The currently running child's PID or NULL.
+  pid_t pid_;
+
+  // All of the arguments (including the name of the binary).
+  std::deque<std::string> args_;
+
+  // The name of the real binary that we were told to run.
+  std::string original_binary_;
+  // The name of the file that we're actually running.
+  std::string binary_;
+
+  // Watches original_binary_.
+  unique_ptr<FileWatch> watcher_;
+
+  // Captured from the original file when we most recently started a new child
+  // process. Used to see if it actually changes or not.
+  struct stat stat_at_start_;
+  bool stat_at_start_valid_;
+
+  // An event that restarts after kRestartWaitTime.
+  static EventUniquePtr restart_timeout;
+
+  // The set of children waiting to be restarted once all modifications stop.
+  static ::std::set<Child *> waiting_to_restart;
+
+  DISALLOW_COPY_AND_ASSIGN(Child);
+};
+
+constexpr time::Time Child::kProcessDieTime;
+constexpr time::Time Child::kRestartWaitTime;
+constexpr time::Time Child::kMaxRestartsTime;
+constexpr time::Time Child::kResumeWait;
+
+EventUniquePtr Child::restart_timeout;
+::std::set<Child *> Child::waiting_to_restart;
+
+// Kills off the entire process group (including ourself).
+void KillChildren(bool try_nice) {
+  if (try_nice) {
+    static const int kNiceStopSignal = SIGTERM;
+    static const time::Time kNiceWaitTime = time::Time::InSeconds(1);
+
+    // Make sure that we don't just nicely stop ourself...
+    sigset_t mask;
+    sigemptyset(&mask);
+    sigaddset(&mask, kNiceStopSignal);
+    sigprocmask(SIG_BLOCK, &mask, NULL);
+
+    kill(-getpid(), kNiceStopSignal);
+
+    fflush(NULL);
+    time::SleepFor(kNiceWaitTime);
+  }
+
+  // Send SIGKILL to our whole process group, which will forcibly terminate any
+  // of them that are still running (us for sure, maybe more too).
+  kill(-getpid(), SIGKILL);
+}
+
+void ExitHandler() {
+  KillChildren(true);
+}
+
+void KillChildrenSignalHandler(int signum) {
+  // If we get SIGSEGV or some other random signal who knows what's happening
+  // and we should just kill everybody immediately.
+  // This is a list of all of the signals that mean some form of "nicely stop".
+  KillChildren(signum == SIGHUP || signum == SIGINT || signum == SIGQUIT ||
+               signum == SIGABRT || signum == SIGPIPE || signum == SIGTERM ||
+               signum == SIGXCPU);
+}
+
+// Returns the currently running child with PID pid or an empty unique_ptr.
+const unique_ptr<Child> &FindChild(pid_t pid) {
+  for (auto it = children.begin(); it != children.end(); ++it) {
+    if (pid == (*it)->pid()) {
+      return *it;
+    }
+  }
+
+  if (pid == core->pid()) {
+    return core;
+  }
+
+  static const unique_ptr<Child> kNothing;
+  return kNothing;
+}
+
+// Gets set up as a libevent handler for SIGCHLD.
+// Handles calling Child::ProcessDied() on the appropriate one.
+void SigCHLDReceived(int /*fd*/, short /*events*/, void *) {
+  // In a while loop in case we miss any SIGCHLDs.
+  while (true) {
+    siginfo_t infop;
+    infop.si_pid = 0;
+    if (waitid(P_ALL, 0, &infop, WEXITED | WSTOPPED | WNOHANG) != 0) {
+      PLOG(WARNING, "waitid failed");
+      continue;
+    }
+    // If there are no more child process deaths to process.
+    if (infop.si_pid == 0) {
+      return;
+    }
+
+    pid_t pid = infop.si_pid;
+    int status = infop.si_status;
+    const unique_ptr<Child> &child = FindChild(pid);
+    if (child) {
+      switch (infop.si_code) {
+        case CLD_EXITED:
+          LOG(WARNING, "child %d (%s) exited with status %d\n",
+              pid, child->name(), status);
+          break;
+        case CLD_DUMPED:
+          LOG(INFO, "child %d actually dumped core. "
+              "falling through to killed by signal case\n", pid);
+        case CLD_KILLED:
+          // If somebody (possibly us) sent it SIGTERM that means that they just
+          // want it to stop, so it stopping isn't a WARNING.
+          LOG((status == SIGTERM) ? DEBUG : WARNING,
+              "child %d (%s) was killed by signal %d (%s)\n",
+              pid, child->name(), status, aos_strsignal(status));
+          break;
+        case CLD_STOPPED:
+          LOG(WARNING, "child %d (%s) was stopped by signal %d "
+              "(giving it a SIGCONT(%d))\n",
+              pid, child->name(), status, SIGCONT);
+          kill(pid, SIGCONT);
+          continue;
+        default:
+          LOG(WARNING, "something happened to child %d (%s) (killing it)\n",
+              pid, child->name());
+          kill(pid, SIGKILL);
+          continue;
+      }
+    } else {
+      LOG(WARNING, "couldn't find a Child for pid %d\n", pid);
+      return;
+    }
+
+    if (child == core) {
+      LOG(FATAL, "core died\n");
+    }
+    child->ProcessDied();
+  }
+}
+
+// This is used for communicating the name of the file to read processes to
+// start from main to Run.
+const char *child_list_file;
+
+void Run(void *watch);
+void Main() {
+  logging::Init();
+
+  if (setpgid(0 /*self*/, 0 /*make PGID the same as PID*/) != 0) {
+    PLOG(FATAL, "setpgid(0, 0) failed");
+  }
+
+  // Make sure that we kill all children when we exit.
+  atexit(ExitHandler);
+  // Do it on some signals too (ones that we otherwise tend to receive and then
+  // leave all of our children going).
+  signal(SIGHUP, KillChildrenSignalHandler);
+  signal(SIGINT, KillChildrenSignalHandler);
+  signal(SIGQUIT, KillChildrenSignalHandler);
+  signal(SIGILL, KillChildrenSignalHandler);
+  signal(SIGABRT, KillChildrenSignalHandler);
+  signal(SIGFPE, KillChildrenSignalHandler);
+  signal(SIGSEGV, KillChildrenSignalHandler);
+  signal(SIGPIPE, KillChildrenSignalHandler);
+  signal(SIGTERM, KillChildrenSignalHandler);
+  signal(SIGBUS, KillChildrenSignalHandler);
+  signal(SIGXCPU, KillChildrenSignalHandler);
+  
+  libevent_base = EventBaseUniquePtr(event_base_new());
+
+  std::string core_touch_file = "/tmp/starter.";
+  core_touch_file += std::to_string(static_cast<intmax_t>(getpid()));
+  core_touch_file += ".core_touch_file";
+  const int result =
+      ::aos::util::RunCommand(("touch '" + core_touch_file + "'").c_str());
+  if (result == -1) {
+    PLOG(FATAL, "running `touch '%s'` failed\n", core_touch_file.c_str());
+  } else if (!WIFEXITED(result) || WEXITSTATUS(result) != 0) {
+    LOG(FATAL, "`touch '%s'` gave result %x\n", core_touch_file.c_str(),
+        result);
+  }
+  FileWatch core_touch_file_watch(core_touch_file, Run, NULL);
+  core = unique_ptr<Child>(
+      new Child("core " + core_touch_file));
+
+  FILE *pid_file = fopen("/tmp/starter.pid", "w");
+  if (pid_file == NULL) {
+    PLOG(FATAL, "fopen(\"/tmp/starter.pid\", \"w\") failed");
+  } else {
+    if (fprintf(pid_file, "%d", core->pid()) == -1) {
+      PLOG(WARNING, "fprintf(%p, \"%%d\", %d) failed",
+           pid_file, core->pid());
+    }
+    fclose(pid_file);
+  }
+
+  LOG(INFO, "waiting for %s to appear\n", core_touch_file.c_str());
+
+  event_base_dispatch(libevent_base.get());
+  LOG(FATAL, "event_base_dispatch(%p) returned\n", libevent_base.get());
+}
+
+// This is the callback for when core creates the file indicating that it has
+// started.
+void Run(void *watch) {
+  // Make it so it doesn't keep on seeing random changes in /tmp.
+  static_cast<FileWatch *>(watch)->RemoveWatch();
+
+  // It's safe now because core is up.
+  aos::InitNRT();
+
+  std::ifstream list_file(child_list_file);
+  
+  while (true) {
+    std::string child_name;
+    getline(list_file, child_name);
+    if ((list_file.rdstate() & std::ios_base::eofbit) != 0) {
+      break;
+    }
+    if (list_file.rdstate() != 0) {
+      LOG(FATAL, "reading input file %s failed\n", child_list_file);
+    }
+    children.push_back(unique_ptr<Child>(new Child(child_name)));
+  }
+
+  EventUniquePtr sigchld(event_new(libevent_base.get(), SIGCHLD,
+                                   EV_SIGNAL | EV_PERSIST,
+                                   SigCHLDReceived, NULL));
+  event_add(sigchld.release(), NULL);
+}
+
+const char *kArgsHelp = "[OPTION]... START_LIST\n"
+    "Start all of the robot code binaries in START_LIST.\n"
+    "\n"
+    "START_LIST is the file to read binaries (looked up on PATH) to run.\n"
+    "  --help        display this help and exit\n";
+void PrintHelp() {
+  fprintf(stderr, "Usage: %s %s", program_invocation_name, kArgsHelp);
+}
+
+}  // namespace starter
+}  // namespace aos
+
+int main(int argc, char *argv[]) {
+  if (argc != 2) {
+    aos::starter::PrintHelp();
+    exit(EXIT_FAILURE);
+  }
+  if (strcmp(argv[1], "--help") == 0) {
+    aos::starter::PrintHelp();
+    exit(EXIT_SUCCESS);
+  }
+
+  aos::starter::child_list_file = argv[1];
+
+  aos::starter::Main();
+}
diff --git a/aos/linux_code/starter/starter.gyp b/aos/linux_code/starter/starter.gyp
new file mode 100644
index 0000000..9a16647
--- /dev/null
+++ b/aos/linux_code/starter/starter.gyp
@@ -0,0 +1,28 @@
+{
+  'targets': [
+    {
+      'target_name': 'starter_exe',
+      'type': 'executable',
+      'sources': [
+        'starter.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(EXTERNALS):libevent',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/common.gyp:once',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/common/libc/libc.gyp:aos_strsignal',
+        '<(AOS)/common/util/util.gyp:run_command',
+      ],
+      'copies': [
+        {
+          'destination': '<(rsync_dir)',
+          'files': [
+            'starter.sh',
+          ],
+        },
+      ],
+    },
+  ],
+}
diff --git a/aos/linux_code/starter/starter.sh b/aos/linux_code/starter/starter.sh
new file mode 100755
index 0000000..b81bf62
--- /dev/null
+++ b/aos/linux_code/starter/starter.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+# NI already has a core pattern, so we probably shouldn't change it.
+#echo '/home/driver/tmp/robot_logs/%e-%s-%p-%t.coredump' > /proc/sys/kernel/core_pattern
+
+while true; do
+	export PATH=$PATH:/home/admin/robot_code
+	starter_exe /home/admin/robot_code/start_list.txt
+done
diff --git a/aos/linux_code/starter/testing_list.txt b/aos/linux_code/starter/testing_list.txt
new file mode 100644
index 0000000..96d412d
--- /dev/null
+++ b/aos/linux_code/starter/testing_list.txt
@@ -0,0 +1,3 @@
+../bin/LogReader
+../bin/JoystickCode
+../bin/AutoMode
diff --git a/aos/prime/README.txt b/aos/prime/README.txt
new file mode 100644
index 0000000..07c414b
--- /dev/null
+++ b/aos/prime/README.txt
@@ -0,0 +1,10 @@
+see ../README.txt for stuff affecting crio and linux code
+
+This folder has code for the linux box that talks to the cRIO etc. It is called the prime. We have multiple explanations for that name:
+  It is the primary controller.
+  PRIME/Primary Robot Intelligent Management Entity
+  Represents Optimus Prime, one of the good transformers who battle the bad ones that 254 names robots after.
+  It is easy to type and doesn't conflict with anything else common for tab-completion.
+  It's not hardware-specific.
+
+The code that would be useful on any linux box is in ../linux_code/.
diff --git a/aos/prime/input/input.gyp b/aos/prime/input/input.gyp
new file mode 100644
index 0000000..25ba45d
--- /dev/null
+++ b/aos/prime/input/input.gyp
@@ -0,0 +1,21 @@
+{
+  'targets': [
+    {
+      'target_name': 'joystick_input',
+      'type': 'static_library',
+      'sources': [
+        'joystick_input.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/common/input/input.gyp:driver_station_data',
+        '<(AOS)/common/messages/messages.gyp:robot_state',
+        '<(AOS)/common/network/network.gyp:socket',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/logging/logging.gyp:queue_logging',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/input/input.gyp:driver_station_data',
+      ],
+    },
+  ],
+}
diff --git a/aos/prime/input/joystick_input.cc b/aos/prime/input/joystick_input.cc
new file mode 100644
index 0000000..cf9e7c0
--- /dev/null
+++ b/aos/prime/input/joystick_input.cc
@@ -0,0 +1,66 @@
+#include "aos/prime/input/joystick_input.h"
+
+#include <string.h>
+
+#include "aos/common/messages/robot_state.q.h"
+#include "aos/common/logging/logging.h"
+#include "aos/common/logging/queue_logging.h"
+
+namespace aos {
+namespace input {
+
+void JoystickInput::Run() {
+  driver_station::Data data;
+  while (true) {
+    joystick_state.FetchAnother();
+
+    data.Update(*joystick_state);
+
+    {
+      using driver_station::JoystickFeature;
+      using driver_station::ButtonLocation;
+      for (int joystick = 1; joystick <= JoystickFeature::kJoysticks;
+           ++joystick) {
+        for (int button = 1; button <= ButtonLocation::kButtons; ++button) {
+          ButtonLocation location(joystick, button);
+          if (data.PosEdge(location)) {
+            LOG(INFO, "PosEdge(%d, %d)\n", joystick, button);
+          }
+          if (data.NegEdge(location)) {
+            LOG(INFO, "NegEdge(%d, %d)\n", joystick, button);
+          }
+        }
+        if (data.GetPOV(joystick) != data.GetOldPOV(joystick)) {
+          LOG(INFO, "POV %d %d->%d\n", joystick, data.GetOldPOV(joystick),
+              data.GetPOV(joystick));
+        }
+      }
+    }
+    {
+      using driver_station::ControlBit;
+      if (data.PosEdge(ControlBit::kFmsAttached)) {
+        LOG(INFO, "PosEdge(kFmsAttached)\n");
+      }
+      if (data.NegEdge(ControlBit::kFmsAttached)) {
+        LOG(INFO, "NegEdge(kFmsAttached)\n");
+      }
+      if (data.PosEdge(ControlBit::kAutonomous)) {
+        LOG(INFO, "PosEdge(kAutonomous)\n");
+      }
+      if (data.NegEdge(ControlBit::kAutonomous)) {
+        LOG(INFO, "NegEdge(kAutonomous)\n");
+      }
+      if (data.PosEdge(ControlBit::kEnabled)) {
+        LOG(INFO, "PosEdge(kEnabled)\n");
+      }
+      if (data.NegEdge(ControlBit::kEnabled)) {
+        LOG(INFO, "NegEdge(kEnabled)\n");
+      }
+    }
+
+    RunIteration(data);
+  }
+}
+
+}  // namespace input
+}  // namespace aos
diff --git a/aos/prime/input/joystick_input.h b/aos/prime/input/joystick_input.h
new file mode 100644
index 0000000..ec97580
--- /dev/null
+++ b/aos/prime/input/joystick_input.h
@@ -0,0 +1,32 @@
+#ifndef AOS_LINUX_CODE_INPUT_JOYSTICKS_INPUT_H_
+#define AOS_LINUX_CODE_INPUT_JOYSTICKS_INPUT_H_
+
+#include "aos/common/input/driver_station_data.h"
+
+namespace aos {
+namespace input {
+
+// A class for handling joystick packet values.
+// It will call RunIteration each time a new packet is received.
+//
+// This class automatically handles updating ::aos::joystick_state and logging
+// (at INFO) button edges.
+class JoystickInput {
+ public:
+  void Run();
+
+ private:
+  // Subclasses should do whatever they want with data here.
+  virtual void RunIteration(const driver_station::Data &data) = 0;
+};
+
+// Class which will proxy joystick information from UDP packets to the queues.
+class JoystickProxy {
+ public:
+  void Run();
+};
+
+}  // namespace input
+}  // namespace aos
+
+#endif  // AOS_LINUX_CODE_INPUT_JOYSTICKS_INPUT_H_
diff --git a/bot3/actors/actors.gyp b/bot3/actors/actors.gyp
new file mode 100644
index 0000000..794939a
--- /dev/null
+++ b/bot3/actors/actors.gyp
@@ -0,0 +1,10 @@
+{
+  'targets': [
+    {
+      'target_name': 'binaries',
+      'type': 'none',
+      'dependencies': [
+      ],
+    },
+  ],
+}
diff --git a/bot3/autonomous/auto.cc b/bot3/autonomous/auto.cc
new file mode 100644
index 0000000..0a2f99a
--- /dev/null
+++ b/bot3/autonomous/auto.cc
@@ -0,0 +1,47 @@
+#include <stdio.h>
+
+#include <memory>
+
+#include "aos/common/util/phased_loop.h"
+#include "aos/common/time.h"
+#include "aos/common/util/trapezoid_profile.h"
+#include "aos/common/logging/logging.h"
+#include "aos/common/logging/queue_logging.h"
+
+#include "bot3/autonomous/auto.q.h"
+#include "bot3/control_loops/drivetrain/drivetrain.q.h"
+#include "frc971/actors/drivetrain_actor.h"
+
+using ::aos::time::Time;
+using ::bot3::control_loops::drivetrain_queue;
+
+namespace bot3 {
+namespace autonomous {
+
+struct ProfileParams {
+  double velocity;
+  double acceleration;
+};
+
+namespace time = ::aos::time;
+
+bool ShouldExitAuto() {
+  ::bot3::autonomous::autonomous.FetchLatest();
+  bool ans = !::bot3::autonomous::autonomous->run_auto;
+  if (ans) {
+    LOG(INFO, "Time to exit auto mode\n");
+  }
+  return ans;
+}
+
+void HandleAuto() {
+  ::aos::time::Time start_time = ::aos::time::Time::Now();
+  LOG(INFO, "Starting auto mode at %f\n", start_time.ToSeconds());
+  ::std::unique_ptr<::frc971::actors::DrivetrainAction> drive;
+  LOG(INFO, "Doing nothing in auto.\n");
+
+  if (ShouldExitAuto()) return;
+}
+
+}  // namespace autonomous
+}  // namespace bot3
diff --git a/bot3/autonomous/auto.h b/bot3/autonomous/auto.h
new file mode 100644
index 0000000..896d22c
--- /dev/null
+++ b/bot3/autonomous/auto.h
@@ -0,0 +1,12 @@
+#ifndef BOT3_AUTONOMOUS_AUTO_H_
+#define BOT3_AUTONOMOUS_AUTO_H_
+
+namespace bot3 {
+namespace autonomous {
+
+void HandleAuto();
+
+}  // namespace autonomous
+}  // namespace bot3
+
+#endif  // BOT3_AUTONOMOUS_AUTO_H_
diff --git a/bot3/autonomous/auto.q b/bot3/autonomous/auto.q
new file mode 100644
index 0000000..3636d31
--- /dev/null
+++ b/bot3/autonomous/auto.q
@@ -0,0 +1,8 @@
+package bot3.autonomous;
+
+message AutoControl {
+  // True if auto mode should be running, false otherwise.
+  bool run_auto;
+};
+
+queue AutoControl autonomous;
diff --git a/bot3/autonomous/auto_main.cc b/bot3/autonomous/auto_main.cc
new file mode 100644
index 0000000..f9b978c
--- /dev/null
+++ b/bot3/autonomous/auto_main.cc
@@ -0,0 +1,42 @@
+#include <stdio.h>
+
+#include "aos/common/time.h"
+#include "aos/linux_code/init.h"
+#include "aos/common/logging/logging.h"
+#include "bot3/autonomous/auto.q.h"
+#include "bot3/autonomous/auto.h"
+
+using ::aos::time::Time;
+
+int main(int /*argc*/, char * /*argv*/[]) {
+  ::aos::Init();
+
+  LOG(INFO, "Auto main started\n");
+  ::bot3::autonomous::autonomous.FetchLatest();
+  while (!::bot3::autonomous::autonomous.get()) {
+    ::bot3::autonomous::autonomous.FetchNextBlocking();
+    LOG(INFO, "Got another auto packet\n");
+  }
+
+  while (true) {
+    while (!::bot3::autonomous::autonomous->run_auto) {
+      ::bot3::autonomous::autonomous.FetchNextBlocking();
+      LOG(INFO, "Got another auto packet\n");
+    }
+    LOG(INFO, "Starting auto mode\n");
+    ::aos::time::Time start_time = ::aos::time::Time::Now();
+    ::bot3::autonomous::HandleAuto();
+
+    ::aos::time::Time elapsed_time = ::aos::time::Time::Now() - start_time;
+    LOG(INFO, "Auto mode exited in %f, waiting for it to finish.\n",
+        elapsed_time.ToSeconds());
+    while (::bot3::autonomous::autonomous->run_auto) {
+      ::bot3::autonomous::autonomous.FetchNextBlocking();
+      LOG(INFO, "Got another auto packet\n");
+    }
+    LOG(INFO, "Waiting for auto to start back up.\n");
+  }
+  ::aos::Cleanup();
+  return 0;
+}
+
diff --git a/bot3/autonomous/autonomous.gyp b/bot3/autonomous/autonomous.gyp
new file mode 100644
index 0000000..140fb5b
--- /dev/null
+++ b/bot3/autonomous/autonomous.gyp
@@ -0,0 +1,46 @@
+{
+  'targets': [
+    {
+      'target_name': 'auto_queue',
+      'type': 'static_library',
+      'sources': ['auto.q'],
+      'variables': {
+        'header_path': 'bot3/autonomous',
+      },
+      'includes': ['../../aos/build/queues.gypi'],
+    },
+    {
+      'target_name': 'auto_lib',
+      'type': 'static_library',
+      'sources': [
+        'auto.cc',
+      ],
+      'dependencies': [
+        'auto_queue',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+        '<(DEPTH)/bot3/control_loops/drivetrain/drivetrain.gyp:drivetrain_queue',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/common/util/util.gyp:phased_loop',
+        '<(AOS)/common/util/util.gyp:trapezoid_profile',
+        '<(AOS)/build/aos.gyp:logging',
+        #'<(DEPTH)/frc971/actors/actors.gyp:drivetrain_action_lib',
+        '<(AOS)/common/logging/logging.gyp:queue_logging',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+      ],
+    },
+    {
+      'target_name': 'auto_bot3',
+      'type': 'executable',
+      'sources': [
+        'auto_main.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        'auto_queue',
+        'auto_lib',
+      ],
+    },
+  ],
+}
diff --git a/bot3/bot3.gyp b/bot3/bot3.gyp
new file mode 100644
index 0000000..6e94f53
--- /dev/null
+++ b/bot3/bot3.gyp
@@ -0,0 +1,23 @@
+{
+  'targets': [
+    {
+      'target_name': 'joystick_reader_bot3',
+      'type': 'executable',
+      'sources': [
+        'joystick_reader.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/prime/input/input.gyp:joystick_input',
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/common/util/util.gyp:log_interval',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+
+        '<(DEPTH)/frc971/queues/queues.gyp:gyro',
+        '<(DEPTH)/bot3/control_loops/drivetrain/drivetrain.gyp:drivetrain_queue',
+        '<(DEPTH)/bot3/autonomous/autonomous.gyp:auto_queue',
+      ],
+    },
+  ],
+}
diff --git a/bot3/control_loops/drivetrain/drivetrain.cc b/bot3/control_loops/drivetrain/drivetrain.cc
new file mode 100644
index 0000000..0c191d1
--- /dev/null
+++ b/bot3/control_loops/drivetrain/drivetrain.cc
@@ -0,0 +1,762 @@
+#include "bot3/control_loops/drivetrain/drivetrain.h"
+
+#include <stdio.h>
+#include <sched.h>
+#include <cmath>
+#include <memory>
+#include "Eigen/Dense"
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/controls/polytope.h"
+#include "aos/common/commonmath.h"
+#include "aos/common/logging/queue_logging.h"
+#include "aos/common/logging/matrix_logging.h"
+
+#include "frc971/control_loops/state_feedback_loop.h"
+#include "frc971/control_loops/coerce_goal.h"
+#include "bot3/control_loops/drivetrain/polydrivetrain_cim_plant.h"
+#include "bot3/control_loops/drivetrain/drivetrain.q.h"
+#include "frc971/queues/gyro.q.h"
+#include "frc971/shifter_hall_effect.h"
+#include "bot3/control_loops/drivetrain/drivetrain_dog_motor_plant.h"
+#include "bot3/control_loops/drivetrain/polydrivetrain_dog_motor_plant.h"
+
+// A consistent way to mark code that goes away without shifters.
+#define HAVE_SHIFTERS 0
+
+using ::frc971::sensors::gyro_reading;
+
+namespace bot3 {
+namespace control_loops {
+
+class DrivetrainMotorsSS {
+ public:
+  class LimitedDrivetrainLoop : public StateFeedbackLoop<4, 2, 2> {
+   public:
+    LimitedDrivetrainLoop(StateFeedbackLoop<4, 2, 2> &&loop)
+        : StateFeedbackLoop<4, 2, 2>(::std::move(loop)),
+          U_Poly_((Eigen::Matrix<double, 4, 2>() << 1, 0, -1, 0, 0, 1, 0, -1)
+                      .finished(),
+                  (Eigen::Matrix<double, 4, 1>() << 12.0, 12.0, 12.0, 12.0)
+                      .finished()) {
+      ::aos::controls::HPolytope<0>::Init();
+      T << 1, -1, 1, 1;
+      T_inverse = T.inverse();
+    }
+
+    bool output_was_capped() const { return output_was_capped_; }
+
+   private:
+    virtual void CapU() {
+      const Eigen::Matrix<double, 4, 1> error = R() - X_hat();
+
+      if (::std::abs(U(0, 0)) > 12.0 || ::std::abs(U(1, 0)) > 12.0) {
+        mutable_U() =
+            U() * 12.0 / ::std::max(::std::abs(U(0, 0)), ::std::abs(U(1, 0)));
+        LOG_MATRIX(DEBUG, "U is now", U());
+        // TODO(Austin): Figure out why the polytope stuff wasn't working and
+        // remove this hack.
+        output_was_capped_ = true;
+        return;
+
+        LOG_MATRIX(DEBUG, "U at start", U());
+        LOG_MATRIX(DEBUG, "R at start", R());
+        LOG_MATRIX(DEBUG, "Xhat at start", X_hat());
+
+        Eigen::Matrix<double, 2, 2> position_K;
+        position_K << K(0, 0), K(0, 2), K(1, 0), K(1, 2);
+        Eigen::Matrix<double, 2, 2> velocity_K;
+        velocity_K << K(0, 1), K(0, 3), K(1, 1), K(1, 3);
+
+        Eigen::Matrix<double, 2, 1> position_error;
+        position_error << error(0, 0), error(2, 0);
+        const auto drive_error = T_inverse * position_error;
+        Eigen::Matrix<double, 2, 1> velocity_error;
+        velocity_error << error(1, 0), error(3, 0);
+        LOG_MATRIX(DEBUG, "error", error);
+
+        const auto &poly = U_Poly_;
+        const Eigen::Matrix<double, 4, 2> pos_poly_H =
+            poly.H() * position_K * T;
+        const Eigen::Matrix<double, 4, 1> pos_poly_k =
+            poly.k() - poly.H() * velocity_K * velocity_error;
+        const ::aos::controls::HPolytope<2> pos_poly(pos_poly_H, pos_poly_k);
+
+        Eigen::Matrix<double, 2, 1> adjusted_pos_error;
+        {
+          const auto &P = drive_error;
+
+          Eigen::Matrix<double, 1, 2> L45;
+          L45 << ::aos::sign(P(1, 0)), -::aos::sign(P(0, 0));
+          const double w45 = 0;
+
+          Eigen::Matrix<double, 1, 2> LH;
+          if (::std::abs(P(0, 0)) > ::std::abs(P(1, 0))) {
+            LH << 0, 1;
+          } else {
+            LH << 1, 0;
+          }
+          const double wh = LH.dot(P);
+
+          Eigen::Matrix<double, 2, 2> standard;
+          standard << L45, LH;
+          Eigen::Matrix<double, 2, 1> W;
+          W << w45, wh;
+          const Eigen::Matrix<double, 2, 1> intersection =
+              standard.inverse() * W;
+
+          bool is_inside_h;
+          const auto adjusted_pos_error_h = frc971::control_loops::DoCoerceGoal(
+              pos_poly, LH, wh, drive_error, &is_inside_h);
+          const auto adjusted_pos_error_45 =
+              frc971::control_loops::DoCoerceGoal(pos_poly, L45, w45,
+                                                  intersection, nullptr);
+          if (pos_poly.IsInside(intersection)) {
+            adjusted_pos_error = adjusted_pos_error_h;
+          } else {
+            if (is_inside_h) {
+              if (adjusted_pos_error_h.norm() > adjusted_pos_error_45.norm()) {
+                adjusted_pos_error = adjusted_pos_error_h;
+              } else {
+                adjusted_pos_error = adjusted_pos_error_45;
+              }
+            } else {
+              adjusted_pos_error = adjusted_pos_error_45;
+            }
+          }
+        }
+
+        LOG_MATRIX(DEBUG, "adjusted_pos_error", adjusted_pos_error);
+        mutable_U() =
+            velocity_K * velocity_error + position_K * T * adjusted_pos_error;
+        LOG_MATRIX(DEBUG, "U is now", U());
+      } else {
+        output_was_capped_ = false;
+      }
+    }
+
+    const ::aos::controls::HPolytope<2> U_Poly_;
+    Eigen::Matrix<double, 2, 2> T, T_inverse;
+    bool output_was_capped_ = false;
+    ;
+  };
+
+  DrivetrainMotorsSS()
+      : loop_(new LimitedDrivetrainLoop(
+            ::bot3::control_loops::MakeDrivetrainLoop())),
+        filtered_offset_(0.0),
+        gyro_(0.0),
+        left_goal_(0.0),
+        right_goal_(0.0),
+        raw_left_(0.0),
+        raw_right_(0.0) {
+    // Low gear on both.
+    loop_->set_controller_index(0);
+  }
+
+  void SetGoal(double left, double left_velocity, double right,
+               double right_velocity) {
+    left_goal_ = left;
+    right_goal_ = right;
+    loop_->mutable_R() << left, left_velocity, right, right_velocity;
+  }
+  void SetRawPosition(double left, double right) {
+    raw_right_ = right;
+    raw_left_ = left;
+    Eigen::Matrix<double, 2, 1> Y;
+    Y << left + filtered_offset_, right - filtered_offset_;
+    loop_->Correct(Y);
+  }
+  void SetPosition(double left, double right, double gyro) {
+    // Decay the offset quickly because this gyro is great.
+    const double offset = (right - left - gyro * kDrivetrainTurnWidth) / 2.0;
+    filtered_offset_ = 0.25 * offset + 0.75 * filtered_offset_;
+    gyro_ = gyro;
+    SetRawPosition(left, right);
+  }
+
+  void SetExternalMotors(double left_voltage, double right_voltage) {
+    loop_->mutable_U() << left_voltage, right_voltage;
+  }
+
+  void Update(bool stop_motors, bool enable_control_loop) {
+    if (enable_control_loop) {
+      loop_->Update(stop_motors);
+    } else {
+      if (stop_motors) {
+        loop_->mutable_U().setZero();
+        loop_->mutable_U_uncapped().setZero();
+      }
+      loop_->UpdateObserver();
+    }
+    ::Eigen::Matrix<double, 4, 1> E = loop_->R() - loop_->X_hat();
+    LOG_MATRIX(DEBUG, "E", E);
+  }
+
+  double GetEstimatedRobotSpeed() const {
+    // lets just call the average of left and right velocities close enough
+    return (loop_->X_hat(1, 0) + loop_->X_hat(3, 0)) / 2;
+  }
+
+  double GetEstimatedLeftEncoder() const { return loop_->X_hat(0, 0); }
+
+  double GetEstimatedRightEncoder() const { return loop_->X_hat(2, 0); }
+
+  bool OutputWasCapped() const { return loop_->output_was_capped(); }
+
+  void SendMotors(DrivetrainQueue::Output *output) const {
+    if (output) {
+      output->left_voltage = loop_->U(0, 0);
+      output->right_voltage = loop_->U(1, 0);
+      output->left_high = false;
+      output->right_high = false;
+    }
+  }
+
+  const LimitedDrivetrainLoop &loop() const { return *loop_; }
+
+ private:
+  ::std::unique_ptr<LimitedDrivetrainLoop> loop_;
+
+  double filtered_offset_;
+  double gyro_;
+  double left_goal_;
+  double right_goal_;
+  double raw_left_;
+  double raw_right_;
+};
+
+class PolyDrivetrain {
+ public:
+  enum Gear { HIGH, LOW, SHIFTING_UP, SHIFTING_DOWN };
+  // Stall Torque in N m
+  static constexpr double kStallTorque = 2.42;
+  // Stall Current in Amps
+  static constexpr double kStallCurrent = 133.0;
+  // Free Speed in RPM. Used number from last year.
+  static constexpr double kFreeSpeed = 4650.0;
+  // Free Current in Amps
+  static constexpr double kFreeCurrent = 2.7;
+  // Moment of inertia of the drivetrain in kg m^2
+  // Just borrowed from last year.
+  static constexpr double J = 10;
+  // Mass of the robot, in kg.
+  static constexpr double m = 68;
+  // Radius of the robot, in meters (from last year).
+  static constexpr double rb = 0.9603 / 2.0;
+  static constexpr double kWheelRadius = 0.0515938;
+  // Resistance of the motor, divided by the number of motors.
+  static constexpr double kR =
+      (12.0 / kStallCurrent / 2 + 0.03) / (0.93 * 0.93);
+  // Motor velocity constant
+  static constexpr double Kv =
+      ((kFreeSpeed / 60.0 * 2.0 * M_PI) / (12.0 - kR * kFreeCurrent));
+  // Torque constant
+  static constexpr double Kt = kStallTorque / kStallCurrent;
+
+  PolyDrivetrain()
+      : U_Poly_((Eigen::Matrix<double, 4, 2>() << /*[[*/ 1, 0 /*]*/,
+                 /*[*/ -1, 0 /*]*/,
+                 /*[*/ 0, 1 /*]*/,
+                 /*[*/ 0, -1 /*]]*/).finished(),
+                (Eigen::Matrix<double, 4, 1>() << /*[[*/ 12 /*]*/,
+                 /*[*/ 12 /*]*/,
+                 /*[*/ 12 /*]*/,
+                 /*[*/ 12 /*]]*/).finished()),
+        loop_(new StateFeedbackLoop<2, 2, 2>(
+            ::bot3::control_loops::MakeVelocityDrivetrainLoop())),
+        ttrust_(1.1),
+        wheel_(0.0),
+        throttle_(0.0),
+        quickturn_(false),
+        stale_count_(0),
+        position_time_delta_(0.01),
+        left_gear_(LOW),
+        right_gear_(LOW),
+        counter_(0) {
+    last_position_.Zero();
+    position_.Zero();
+  }
+  static bool IsInGear(Gear gear) { return gear == LOW || gear == HIGH; }
+
+  static double MotorSpeed(
+      const frc971::constants::ShifterHallEffect &hall_effect,
+      double shifter_position, double velocity) {
+    // TODO(austin): G_high, G_low and kWheelRadius
+    const double avg_hall_effect =
+        (hall_effect.clear_high + hall_effect.clear_low) / 2.0;
+
+    if (shifter_position > avg_hall_effect) {
+      return velocity / kDrivetrainHighGearRatio / kWheelRadius;
+    } else {
+      return velocity / kDrivetrainLowGearRatio / kWheelRadius;
+    }
+  }
+
+  Gear ComputeGear(const frc971::constants::ShifterHallEffect &hall_effect,
+                   double velocity, Gear current) {
+    const double low_omega = MotorSpeed(hall_effect, 0.0, ::std::abs(velocity));
+    const double high_omega =
+        MotorSpeed(hall_effect, 1.0, ::std::abs(velocity));
+
+    double high_torque = ((12.0 - high_omega / Kv) * Kt / kR);
+    double low_torque = ((12.0 - low_omega / Kv) * Kt / kR);
+    double high_power = high_torque * high_omega;
+    double low_power = low_torque * low_omega;
+
+    // TODO(aschuh): Do this right!
+    if ((current == HIGH || high_power > low_power + 160) &&
+        ::std::abs(velocity) > 0.14) {
+      return HIGH;
+    } else {
+      return LOW;
+    }
+  }
+
+  void SetGoal(double wheel, double throttle, bool quickturn, bool highgear) {
+    const double kWheelNonLinearity = 0.5;
+    // Apply a sin function that's scaled to make it feel better.
+    const double angular_range = M_PI_2 * kWheelNonLinearity;
+
+    wheel_ = sin(angular_range * wheel) / sin(angular_range);
+    wheel_ = sin(angular_range * wheel_) / sin(angular_range);
+    wheel_ *= 2.3;
+    quickturn_ = quickturn;
+
+    static const double kThrottleDeadband = 0.05;
+    if (::std::abs(throttle) < kThrottleDeadband) {
+      throttle_ = 0;
+    } else {
+      throttle_ = copysign((::std::abs(throttle) - kThrottleDeadband) /
+                               (1.0 - kThrottleDeadband),
+                           throttle);
+    }
+
+    // TODO(austin): Fix the upshift logic to include states.
+    Gear requested_gear;
+    if (false) {
+      const double current_left_velocity =
+          (position_.left_encoder - last_position_.left_encoder) /
+          position_time_delta_;
+      const double current_right_velocity =
+          (position_.right_encoder - last_position_.right_encoder) /
+          position_time_delta_;
+
+      Gear left_requested = ComputeGear(kDrivetrainLeftShifter,
+                                        current_left_velocity, left_gear_);
+      Gear right_requested = ComputeGear(kDrivetrainRightShifter,
+                                         current_right_velocity, right_gear_);
+      requested_gear =
+          (left_requested == HIGH || right_requested == HIGH) ? HIGH : LOW;
+    } else {
+      requested_gear = highgear ? HIGH : LOW;
+    }
+
+    const Gear shift_up = kDrivetrainClutchTransmission ? HIGH : SHIFTING_UP;
+    const Gear shift_down = kDrivetrainClutchTransmission ? LOW : SHIFTING_DOWN;
+
+    if (left_gear_ != requested_gear) {
+      if (IsInGear(left_gear_)) {
+        if (requested_gear == HIGH) {
+          left_gear_ = shift_up;
+        } else {
+          left_gear_ = shift_down;
+        }
+      } else {
+        if (requested_gear == HIGH && left_gear_ == SHIFTING_DOWN) {
+          left_gear_ = SHIFTING_UP;
+        } else if (requested_gear == LOW && left_gear_ == SHIFTING_UP) {
+          left_gear_ = SHIFTING_DOWN;
+        }
+      }
+    }
+    if (right_gear_ != requested_gear) {
+      if (IsInGear(right_gear_)) {
+        if (requested_gear == HIGH) {
+          right_gear_ = shift_up;
+        } else {
+          right_gear_ = shift_down;
+        }
+      } else {
+        if (requested_gear == HIGH && right_gear_ == SHIFTING_DOWN) {
+          right_gear_ = SHIFTING_UP;
+        } else if (requested_gear == LOW && right_gear_ == SHIFTING_UP) {
+          right_gear_ = SHIFTING_DOWN;
+        }
+      }
+    }
+  }
+  void SetPosition(const DrivetrainQueue::Position *position) {
+    if (position == NULL) {
+      ++stale_count_;
+    } else {
+      last_position_ = position_;
+      position_ = *position;
+      position_time_delta_ = (stale_count_ + 1) * 0.01;
+      stale_count_ = 0;
+    }
+
+#if HAVE_SHIFTERS
+    if (position) {
+      GearLogging gear_logging;
+      // Switch to the correct controller.
+      const double left_middle_shifter_position =
+          (kDrivetrainLeftShifter.clear_high +
+           kDrivetrainLeftShifter.clear_low) /
+          2.0;
+      const double right_middle_shifter_position =
+          (kDrivetrainRightShifter.clear_high +
+           kDrivetrainRightShifter.clear_low) /
+          2.0;
+
+      if (position->left_shifter_position < left_middle_shifter_position ||
+          left_gear_ == LOW) {
+        if (position->right_shifter_position < right_middle_shifter_position ||
+            right_gear_ == LOW) {
+          gear_logging.left_loop_high = false;
+          gear_logging.right_loop_high = false;
+          loop_->set_controller_index(gear_logging.controller_index = 0);
+        } else {
+          gear_logging.left_loop_high = false;
+          gear_logging.right_loop_high = true;
+          loop_->set_controller_index(gear_logging.controller_index = 1);
+        }
+      } else {
+        if (position->right_shifter_position < right_middle_shifter_position ||
+            right_gear_ == LOW) {
+          gear_logging.left_loop_high = true;
+          gear_logging.right_loop_high = false;
+          loop_->set_controller_index(gear_logging.controller_index = 2);
+        } else {
+          gear_logging.left_loop_high = true;
+          gear_logging.right_loop_high = true;
+          loop_->set_controller_index(gear_logging.controller_index = 3);
+        }
+      }
+
+      // TODO(austin): Constants.
+      if (position->left_shifter_position > kDrivetrainLeftShifter.clear_high &&
+          left_gear_ == SHIFTING_UP) {
+        left_gear_ = HIGH;
+      }
+      if (position->left_shifter_position < kDrivetrainLeftShifter.clear_low &&
+          left_gear_ == SHIFTING_DOWN) {
+        left_gear_ = LOW;
+      }
+      if (position->right_shifter_position >
+              kDrivetrainRightShifter.clear_high &&
+          right_gear_ == SHIFTING_UP) {
+        right_gear_ = HIGH;
+      }
+      if (position->right_shifter_position <
+              kDrivetrainRightShifter.clear_low &&
+          right_gear_ == SHIFTING_DOWN) {
+        right_gear_ = LOW;
+      }
+
+      gear_logging.left_state = left_gear_;
+      gear_logging.right_state = right_gear_;
+      LOG_STRUCT(DEBUG, "state", gear_logging);
+    }
+#endif
+  }
+
+  double FilterVelocity(double throttle) {
+    const Eigen::Matrix<double, 2, 2> FF =
+        loop_->B().inverse() *
+        (Eigen::Matrix<double, 2, 2>::Identity() - loop_->A());
+
+    constexpr int kHighGearController = 3;
+    const Eigen::Matrix<double, 2, 2> FF_high =
+        loop_->controller(kHighGearController).plant.B().inverse() *
+        (Eigen::Matrix<double, 2, 2>::Identity() -
+         loop_->controller(kHighGearController).plant.A());
+
+    ::Eigen::Matrix<double, 1, 2> FF_sum = FF.colwise().sum();
+    int min_FF_sum_index;
+    const double min_FF_sum = FF_sum.minCoeff(&min_FF_sum_index);
+    const double min_K_sum = loop_->K().col(min_FF_sum_index).sum();
+    const double high_min_FF_sum = FF_high.col(0).sum();
+
+    const double adjusted_ff_voltage = ::aos::Clip(
+        throttle * 12.0 * min_FF_sum / high_min_FF_sum, -12.0, 12.0);
+    return (adjusted_ff_voltage +
+            ttrust_ * min_K_sum * (loop_->X_hat(0, 0) + loop_->X_hat(1, 0)) /
+                2.0) /
+           (ttrust_ * min_K_sum + min_FF_sum);
+  }
+
+  double MaxVelocity() {
+    const Eigen::Matrix<double, 2, 2> FF =
+        loop_->B().inverse() *
+        (Eigen::Matrix<double, 2, 2>::Identity() - loop_->A());
+
+    constexpr int kHighGearController = 3;
+    const Eigen::Matrix<double, 2, 2> FF_high =
+        loop_->controller(kHighGearController).plant.B().inverse() *
+        (Eigen::Matrix<double, 2, 2>::Identity() -
+         loop_->controller(kHighGearController).plant.A());
+
+    ::Eigen::Matrix<double, 1, 2> FF_sum = FF.colwise().sum();
+    int min_FF_sum_index;
+    const double min_FF_sum = FF_sum.minCoeff(&min_FF_sum_index);
+    // const double min_K_sum = loop_->K().col(min_FF_sum_index).sum();
+    const double high_min_FF_sum = FF_high.col(0).sum();
+
+    const double adjusted_ff_voltage =
+        ::aos::Clip(12.0 * min_FF_sum / high_min_FF_sum, -12.0, 12.0);
+    return adjusted_ff_voltage / min_FF_sum;
+  }
+
+  void Update() {
+    // TODO(austin): Observer for the current velocity instead of difference
+    // calculations.
+    ++counter_;
+#if HAVE_SHIFTERS
+    const double current_left_velocity =
+        (position_.left_encoder - last_position_.left_encoder) /
+        position_time_delta_;
+    const double current_right_velocity =
+        (position_.right_encoder - last_position_.right_encoder) /
+        position_time_delta_;
+    const double left_motor_speed =
+        MotorSpeed(kDrivetrainLeftShifter, position_.left_shifter_position,
+                   current_left_velocity);
+    const double right_motor_speed =
+        MotorSpeed(kDrivetrainRightShifter, position_.right_shifter_position,
+                   current_right_velocity);
+
+    {
+      CIMLogging logging;
+
+      // Reset the CIM model to the current conditions to be ready for when we
+      // shift.
+      if (IsInGear(left_gear_)) {
+        logging.left_in_gear = true;
+      } else {
+        logging.left_in_gear = false;
+      }
+      logging.left_motor_speed = left_motor_speed;
+      logging.left_velocity = current_left_velocity;
+      if (IsInGear(right_gear_)) {
+        logging.right_in_gear = true;
+      } else {
+        logging.right_in_gear = false;
+      }
+      logging.right_motor_speed = right_motor_speed;
+      logging.right_velocity = current_right_velocity;
+
+      LOG_STRUCT(DEBUG, "currently", logging);
+    }
+#endif
+
+#if HAVE_SHIFTERS
+    if (IsInGear(left_gear_) && IsInGear(right_gear_)) {
+#else
+    {
+#endif
+      // FF * X = U (steady state)
+      const Eigen::Matrix<double, 2, 2> FF =
+          loop_->B().inverse() *
+          (Eigen::Matrix<double, 2, 2>::Identity() - loop_->A());
+
+      // Invert the plant to figure out how the velocity filter would have to
+      // work
+      // out in order to filter out the forwards negative inertia.
+      // This math assumes that the left and right power and velocity are
+      // equals,
+      // and that the plant is the same on the left and right.
+      const double fvel = FilterVelocity(throttle_);
+
+      const double sign_svel = wheel_ * ((fvel > 0.0) ? 1.0 : -1.0);
+      double steering_velocity;
+      if (quickturn_) {
+        steering_velocity = wheel_ * MaxVelocity();
+      } else {
+        steering_velocity = ::std::abs(fvel) * wheel_;
+      }
+      const double left_velocity = fvel - steering_velocity;
+      const double right_velocity = fvel + steering_velocity;
+      LOG(DEBUG, "l=%f r=%f\n", left_velocity, right_velocity);
+
+      // Integrate velocity to get the position.
+      // This position is used to get integral control.
+      loop_->mutable_R() << left_velocity, right_velocity;
+
+      if (!quickturn_) {
+        // K * R = w
+        Eigen::Matrix<double, 1, 2> equality_k;
+        equality_k << 1 + sign_svel, -(1 - sign_svel);
+        const double equality_w = 0.0;
+
+        // Construct a constraint on R by manipulating the constraint on U
+        ::aos::controls::HPolytope<2> R_poly = ::aos::controls::HPolytope<2>(
+            U_Poly_.H() * (loop_->K() + FF),
+            U_Poly_.k() + U_Poly_.H() * loop_->K() * loop_->X_hat());
+
+        // Limit R back inside the box.
+        loop_->mutable_R() = frc971::control_loops::CoerceGoal(
+            R_poly, equality_k, equality_w, loop_->R());
+      }
+
+      const Eigen::Matrix<double, 2, 1> FF_volts = FF * loop_->R();
+      const Eigen::Matrix<double, 2, 1> U_ideal =
+          loop_->K() * (loop_->R() - loop_->X_hat()) + FF_volts;
+
+      for (int i = 0; i < 2; i++) {
+        loop_->mutable_U()[i] = ::aos::Clip(U_ideal[i], -12, 12);
+      }
+
+      // TODO(austin): Model this better.
+      // TODO(austin): Feed back?
+      loop_->mutable_X_hat() =
+          loop_->A() * loop_->X_hat() + loop_->B() * loop_->U();
+#if HAVE_SHIFTERS
+    } else {
+      // Any motor is not in gear.  Speed match.
+      ::Eigen::Matrix<double, 1, 1> R_left;
+      ::Eigen::Matrix<double, 1, 1> R_right;
+      R_left(0, 0) = left_motor_speed;
+      R_right(0, 0) = right_motor_speed;
+
+      const double wiggle =
+          (static_cast<double>((counter_ % 20) / 10) - 0.5) * 5.0;
+
+      loop_->mutable_U(0, 0) =
+          ::aos::Clip((R_left / Kv)(0, 0) + (IsInGear(left_gear_) ? 0 : wiggle),
+                      -12.0, 12.0);
+      loop_->mutable_U(1, 0) = ::aos::Clip(
+          (R_right / Kv)(0, 0) + (IsInGear(right_gear_) ? 0 : wiggle), -12.0,
+          12.0);
+      loop_->mutable_U() *= 12.0 / ::aos::robot_state->voltage_battery;
+#endif
+    }
+  }
+
+  void SendMotors(DrivetrainQueue::Output *output) {
+    if (output != NULL) {
+      output->left_voltage = loop_->U(0, 0);
+      output->right_voltage = loop_->U(1, 0);
+      output->left_high = left_gear_ == HIGH || left_gear_ == SHIFTING_UP;
+      output->right_high = right_gear_ == HIGH || right_gear_ == SHIFTING_UP;
+    }
+  }
+
+ private:
+  const ::aos::controls::HPolytope<2> U_Poly_;
+
+  ::std::unique_ptr<StateFeedbackLoop<2, 2, 2>> loop_;
+
+  const double ttrust_;
+  double wheel_;
+  double throttle_;
+  bool quickturn_;
+  int stale_count_;
+  double position_time_delta_;
+  Gear left_gear_;
+  Gear right_gear_;
+  DrivetrainQueue::Position last_position_;
+  DrivetrainQueue::Position position_;
+  int counter_;
+};
+constexpr double PolyDrivetrain::kStallTorque;
+constexpr double PolyDrivetrain::kStallCurrent;
+constexpr double PolyDrivetrain::kFreeSpeed;
+constexpr double PolyDrivetrain::kFreeCurrent;
+constexpr double PolyDrivetrain::J;
+constexpr double PolyDrivetrain::m;
+constexpr double PolyDrivetrain::rb;
+constexpr double PolyDrivetrain::kWheelRadius;
+constexpr double PolyDrivetrain::kR;
+constexpr double PolyDrivetrain::Kv;
+constexpr double PolyDrivetrain::Kt;
+
+void DrivetrainLoop::RunIteration(const DrivetrainQueue::Goal *goal,
+                                  const DrivetrainQueue::Position *position,
+                                  DrivetrainQueue::Output *output,
+                                  DrivetrainQueue::Status *status) {
+  // TODO(aschuh): These should be members of the class.
+  static DrivetrainMotorsSS dt_closedloop;
+  static PolyDrivetrain dt_openloop;
+
+  bool bad_pos = false;
+  if (position == nullptr) {
+    LOG_INTERVAL(no_position_);
+    bad_pos = true;
+  }
+  no_position_.Print();
+
+  bool control_loop_driving = false;
+  if (goal) {
+    double wheel = goal->steering;
+    double throttle = goal->throttle;
+    bool quickturn = goal->quickturn;
+#if HAVE_SHIFTERS
+    bool highgear = goal->highgear;
+#endif
+
+    control_loop_driving = goal->control_loop_driving;
+    double left_goal = goal->left_goal;
+    double right_goal = goal->right_goal;
+
+    dt_closedloop.SetGoal(left_goal, goal->left_velocity_goal, right_goal,
+                          goal->right_velocity_goal);
+#if HAVE_SHIFTERS
+    dt_openloop.SetGoal(wheel, throttle, quickturn, highgear);
+#else
+    dt_openloop.SetGoal(wheel, throttle, quickturn, false);
+#endif
+  }
+
+  if (!bad_pos) {
+    const double left_encoder = position->left_encoder;
+    const double right_encoder = position->right_encoder;
+    if (gyro_reading.FetchLatest()) {
+      LOG_STRUCT(DEBUG, "using", *gyro_reading.get());
+      dt_closedloop.SetPosition(left_encoder, right_encoder,
+                                gyro_reading->angle);
+    } else {
+      dt_closedloop.SetRawPosition(left_encoder, right_encoder);
+    }
+  }
+  dt_openloop.SetPosition(position);
+  dt_openloop.Update();
+
+  if (control_loop_driving) {
+    dt_closedloop.Update(output == NULL, true);
+    dt_closedloop.SendMotors(output);
+  } else {
+    dt_openloop.SendMotors(output);
+    if (output) {
+      dt_closedloop.SetExternalMotors(output->left_voltage,
+                                      output->right_voltage);
+    }
+    dt_closedloop.Update(output == NULL, false);
+  }
+
+  // set the output status of the control loop state
+  if (status) {
+    bool done = false;
+    if (goal) {
+      done = ((::std::abs(goal->left_goal -
+                          dt_closedloop.GetEstimatedLeftEncoder()) <
+               kDrivetrainDoneDistance) &&
+              (::std::abs(goal->right_goal -
+                          dt_closedloop.GetEstimatedRightEncoder()) <
+               kDrivetrainDoneDistance));
+    }
+    status->is_done = done;
+    status->robot_speed = dt_closedloop.GetEstimatedRobotSpeed();
+    status->filtered_left_position = dt_closedloop.GetEstimatedLeftEncoder();
+    status->filtered_right_position = dt_closedloop.GetEstimatedRightEncoder();
+
+    status->filtered_left_velocity = dt_closedloop.loop().X_hat(1, 0);
+    status->filtered_right_velocity = dt_closedloop.loop().X_hat(3, 0);
+    status->output_was_capped = dt_closedloop.OutputWasCapped();
+    status->uncapped_left_voltage = dt_closedloop.loop().U_uncapped(0, 0);
+    status->uncapped_right_voltage = dt_closedloop.loop().U_uncapped(1, 0);
+  }
+}
+
+}  // namespace control_loops
+}  // namespace bot3
diff --git a/bot3/control_loops/drivetrain/drivetrain.gyp b/bot3/control_loops/drivetrain/drivetrain.gyp
new file mode 100644
index 0000000..92678d1
--- /dev/null
+++ b/bot3/control_loops/drivetrain/drivetrain.gyp
@@ -0,0 +1,105 @@
+{
+  'targets': [
+    {
+      'target_name': 'replay_drivetrain_bot3',
+      'type': 'executable',
+      'variables': {
+        'no_rsync': 1,
+      },
+      'sources': [
+        'replay_drivetrain.cc',
+      ],
+      'dependencies': [
+        'drivetrain_queue',
+        '<(AOS)/common/controls/controls.gyp:replay_control_loop',
+        '<(AOS)/linux_code/linux_code.gyp:init',
+      ],
+    },
+    {
+      'target_name': 'drivetrain_queue',
+      'type': 'static_library',
+      'sources': ['drivetrain.q'],
+      'variables': {
+        'header_path': 'bot3/control_loops/drivetrain',
+      },
+      'dependencies': [
+        '<(AOS)/common/controls/controls.gyp:control_loop_queues',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/controls/controls.gyp:control_loop_queues',
+      ],
+      'includes': ['../../../aos/build/queues.gypi'],
+    },
+    {
+      'target_name': 'polydrivetrain_plants',
+      'type': 'static_library',
+      'sources': [
+        'polydrivetrain_dog_motor_plant.cc',
+        'drivetrain_dog_motor_plant.cc',
+      ],
+      'dependencies': [
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+      ],
+      'export_dependent_settings': [
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+      ],
+    },
+    {
+      'target_name': 'drivetrain_lib',
+      'type': 'static_library',
+      'sources': [
+        'drivetrain.cc',
+        'polydrivetrain_cim_plant.cc',
+        'drivetrain_dog_motor_plant.cc',
+        'polydrivetrain_dog_motor_plant.cc',
+      ],
+      'dependencies': [
+        'drivetrain_queue',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+        '<(AOS)/common/controls/controls.gyp:polytope',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:coerce_goal',
+        '<(DEPTH)/frc971/queues/queues.gyp:gyro',
+        '<(AOS)/common/util/util.gyp:log_interval',
+        '<(AOS)/common/logging/logging.gyp:queue_logging',
+        '<(AOS)/common/logging/logging.gyp:matrix_logging',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/controls/controls.gyp:polytope',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:coerce_goal',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+        'drivetrain_queue',
+      ],
+    },
+    {
+      'target_name': 'drivetrain_lib_test_bot3',
+      'type': 'executable',
+      'sources': [
+        'drivetrain_lib_test.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+        'drivetrain_queue',
+        'drivetrain_lib',
+        '<(AOS)/common/controls/controls.gyp:control_loop_test',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+        '<(DEPTH)/frc971/queues/queues.gyp:gyro',
+        '<(AOS)/common/common.gyp:queues',
+        '<(AOS)/common/network/network.gyp:team_number',
+      ],
+    },
+    {
+      'target_name': 'drivetrain_bot3',
+      'type': 'executable',
+      'sources': [
+        'drivetrain_main.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        'drivetrain_lib',
+        'drivetrain_queue',
+      ],
+    },
+  ],
+}
diff --git a/bot3/control_loops/drivetrain/drivetrain.h b/bot3/control_loops/drivetrain/drivetrain.h
new file mode 100644
index 0000000..551349d
--- /dev/null
+++ b/bot3/control_loops/drivetrain/drivetrain.h
@@ -0,0 +1,60 @@
+#ifndef BOT3_CONTROL_LOOPS_DRIVETRAIN_H_
+#define BOT3_CONTROL_LOOPS_DRIVETRAIN_H_
+
+#include "Eigen/Dense"
+
+#include "aos/common/controls/polytope.h"
+#include "aos/common/controls/control_loop.h"
+#include "aos/common/controls/polytope.h"
+#include "aos/common/util/log_interval.h"
+
+#include "frc971/shifter_hall_effect.h"
+#include "bot3/control_loops/drivetrain/drivetrain.q.h"
+
+namespace bot3 {
+namespace control_loops {
+
+// Constants
+// TODO(comran): Get actual constants.
+constexpr double kDrivetrainTurnWidth = 0.5;
+constexpr double kDrivetrainDoneDistance = 0.02;
+constexpr double kDrivetrainEncoderRatio = 20.0 / 50.0;
+constexpr double kDrivetrainHighGearRatio =
+    kDrivetrainEncoderRatio * 20.0 / 50.0;
+constexpr double kDrivetrainLowGearRatio = kDrivetrainHighGearRatio;
+const bool kDrivetrainClutchTransmission = false;
+const ::frc971::constants::ShifterHallEffect kDrivetrainRightShifter{
+    555, 657, 660, 560, 0.2, 0.7};
+const ::frc971::constants::ShifterHallEffect kDrivetrainLeftShifter{
+    555, 660, 644, 552, 0.2, 0.7};
+// End constants
+
+class DrivetrainLoop
+    : public aos::controls::ControlLoop<control_loops::DrivetrainQueue> {
+ public:
+  // Constructs a control loop which can take a Drivetrain or defaults to the
+  // drivetrain at bot3::control_loops::drivetrain
+  explicit DrivetrainLoop(control_loops::DrivetrainQueue *my_drivetrain =
+                              &control_loops::drivetrain_queue)
+      : aos::controls::ControlLoop<control_loops::DrivetrainQueue>(
+            my_drivetrain) {
+    ::aos::controls::HPolytope<0>::Init();
+  }
+
+ protected:
+  // Executes one cycle of the control loop.
+  virtual void RunIteration(
+      const control_loops::DrivetrainQueue::Goal *goal,
+      const control_loops::DrivetrainQueue::Position *position,
+      control_loops::DrivetrainQueue::Output *output,
+      control_loops::DrivetrainQueue::Status *status);
+
+  typedef ::aos::util::SimpleLogInterval SimpleLogInterval;
+  SimpleLogInterval no_position_ = SimpleLogInterval(
+      ::aos::time::Time::InSeconds(0.25), WARNING, "no position");
+};
+
+}  // namespace control_loops
+}  // namespace bot3
+
+#endif  // BOT3_CONTROL_LOOPS_DRIVETRAIN_H_
diff --git a/bot3/control_loops/drivetrain/drivetrain.q b/bot3/control_loops/drivetrain/drivetrain.q
new file mode 100644
index 0000000..f6eb030
--- /dev/null
+++ b/bot3/control_loops/drivetrain/drivetrain.q
@@ -0,0 +1,71 @@
+package bot3.control_loops;
+
+import "aos/common/controls/control_loops.q";
+
+struct GearLogging {
+  int8_t controller_index;
+  bool left_loop_high;
+  bool right_loop_high;
+  int8_t left_state;
+  int8_t right_state;
+};
+
+struct CIMLogging {
+  bool left_in_gear;
+  bool right_in_gear;
+  double left_motor_speed;
+  double right_motor_speed;
+  double left_velocity;
+  double right_velocity;
+};
+
+queue_group DrivetrainQueue {
+  implements aos.control_loops.ControlLoop;
+
+  message Goal {
+    double steering;
+    double throttle;
+    //bool highgear;
+    bool quickturn;
+    bool control_loop_driving;
+    double left_goal;
+    double left_velocity_goal;
+    double right_goal;
+    double right_velocity_goal;
+  };
+
+  message Position {
+    double left_encoder;
+    double right_encoder;
+    //double left_shifter_position;
+    //double right_shifter_position;
+  };
+
+  message Output {
+    double left_voltage;
+    double right_voltage;
+    bool left_high;
+    bool right_high;
+  };
+
+  message Status {
+    double robot_speed;
+    double filtered_left_position;
+    double filtered_right_position;
+    double filtered_left_velocity;
+    double filtered_right_velocity;
+
+    double uncapped_left_voltage;
+    double uncapped_right_voltage;
+    bool output_was_capped;
+
+    bool is_done;
+  };
+
+  queue Goal goal;
+  queue Position position;
+  queue Output output;
+  queue Status status;
+};
+
+queue_group DrivetrainQueue drivetrain_queue;
diff --git a/bot3/control_loops/drivetrain/drivetrain_dog_motor_plant.cc b/bot3/control_loops/drivetrain/drivetrain_dog_motor_plant.cc
new file mode 100644
index 0000000..e24fa71
--- /dev/null
+++ b/bot3/control_loops/drivetrain/drivetrain_dog_motor_plant.cc
@@ -0,0 +1,133 @@
+#include "bot3/control_loops/drivetrain/drivetrain_dog_motor_plant.h"
+
+#include <vector>
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace bot3 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeDrivetrainLowLowPlantCoefficients() {
+  Eigen::Matrix<double, 4, 4> A;
+  A << 1.0, 0.00494348612824, 0.0, 1.24048455404e-05, 0.0, 0.977484092703, 0.0, 0.00492433284048, 0.0, 1.24048455404e-05, 1.0, 0.00494348612824, 0.0, 0.00492433284048, 0.0, 0.977484092703;
+  Eigen::Matrix<double, 4, 2> B;
+  B << 2.09180756177e-05, -4.59153636043e-06, 0.00833405032795, -0.00182269526971, -4.59153636043e-06, 2.09180756177e-05, -0.00182269526971, 0.00833405032795;
+  Eigen::Matrix<double, 2, 4> C;
+  C << 1, 0, 0, 0, 0, 0, 1, 0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0, 0, 0, 0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<4, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeDrivetrainLowHighPlantCoefficients() {
+  Eigen::Matrix<double, 4, 4> A;
+  A << 1.0, 0.00494348612824, 0.0, 1.24048455404e-05, 0.0, 0.977484092703, 0.0, 0.00492433284048, 0.0, 1.24048455404e-05, 1.0, 0.00494348612824, 0.0, 0.00492433284048, 0.0, 0.977484092703;
+  Eigen::Matrix<double, 4, 2> B;
+  B << 2.09180756177e-05, -4.59153636043e-06, 0.00833405032795, -0.00182269526971, -4.59153636043e-06, 2.09180756177e-05, -0.00182269526971, 0.00833405032795;
+  Eigen::Matrix<double, 2, 4> C;
+  C << 1, 0, 0, 0, 0, 0, 1, 0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0, 0, 0, 0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<4, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeDrivetrainHighLowPlantCoefficients() {
+  Eigen::Matrix<double, 4, 4> A;
+  A << 1.0, 0.00494348612824, 0.0, 1.24048455404e-05, 0.0, 0.977484092703, 0.0, 0.00492433284048, 0.0, 1.24048455404e-05, 1.0, 0.00494348612824, 0.0, 0.00492433284048, 0.0, 0.977484092703;
+  Eigen::Matrix<double, 4, 2> B;
+  B << 2.09180756177e-05, -4.59153636043e-06, 0.00833405032795, -0.00182269526971, -4.59153636043e-06, 2.09180756177e-05, -0.00182269526971, 0.00833405032795;
+  Eigen::Matrix<double, 2, 4> C;
+  C << 1, 0, 0, 0, 0, 0, 1, 0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0, 0, 0, 0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<4, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeDrivetrainHighHighPlantCoefficients() {
+  Eigen::Matrix<double, 4, 4> A;
+  A << 1.0, 0.00494348612824, 0.0, 1.24048455404e-05, 0.0, 0.977484092703, 0.0, 0.00492433284048, 0.0, 1.24048455404e-05, 1.0, 0.00494348612824, 0.0, 0.00492433284048, 0.0, 0.977484092703;
+  Eigen::Matrix<double, 4, 2> B;
+  B << 2.09180756177e-05, -4.59153636043e-06, 0.00833405032795, -0.00182269526971, -4.59153636043e-06, 2.09180756177e-05, -0.00182269526971, 0.00833405032795;
+  Eigen::Matrix<double, 2, 4> C;
+  C << 1, 0, 0, 0, 0, 0, 1, 0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0, 0, 0, 0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<4, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackController<4, 2, 2> MakeDrivetrainLowLowController() {
+  Eigen::Matrix<double, 4, 2> L;
+  L << 1.2774840927, 0.00492433284048, 79.1440456622, 1.05150722636, 0.00492433284048, 1.2774840927, 1.05150722636, 79.1440456622;
+  Eigen::Matrix<double, 2, 4> K;
+  K << 160.19677247, 15.5358468938, 1.60401194139, 1.33861213093, 1.60401194142, 1.33861213094, 160.19677247, 15.5358468938;
+  Eigen::Matrix<double, 4, 4> A_inv;
+  A_inv << 1.0, -0.00505742153256, 0.0, 1.27875036472e-05, 0.0, 1.02306051542, 0.0, -0.00515393603998, 0.0, 1.27875036472e-05, 1.0, -0.00505742153256, 0.0, -0.00515393603998, 0.0, 1.02306051542;
+  return StateFeedbackController<4, 2, 2>(L, K, A_inv, MakeDrivetrainLowLowPlantCoefficients());
+}
+
+StateFeedbackController<4, 2, 2> MakeDrivetrainLowHighController() {
+  Eigen::Matrix<double, 4, 2> L;
+  L << 1.2774840927, 0.00492433284048, 79.1440456622, 1.05150722636, 0.00492433284048, 1.2774840927, 1.05150722636, 79.1440456622;
+  Eigen::Matrix<double, 2, 4> K;
+  K << 160.19677247, 15.5358468938, 1.60401194139, 1.33861213093, 1.60401194142, 1.33861213094, 160.19677247, 15.5358468938;
+  Eigen::Matrix<double, 4, 4> A_inv;
+  A_inv << 1.0, -0.00505742153256, 0.0, 1.27875036472e-05, 0.0, 1.02306051542, 0.0, -0.00515393603998, 0.0, 1.27875036472e-05, 1.0, -0.00505742153256, 0.0, -0.00515393603998, 0.0, 1.02306051542;
+  return StateFeedbackController<4, 2, 2>(L, K, A_inv, MakeDrivetrainLowHighPlantCoefficients());
+}
+
+StateFeedbackController<4, 2, 2> MakeDrivetrainHighLowController() {
+  Eigen::Matrix<double, 4, 2> L;
+  L << 1.2774840927, 0.00492433284048, 79.1440456622, 1.05150722636, 0.00492433284048, 1.2774840927, 1.05150722636, 79.1440456622;
+  Eigen::Matrix<double, 2, 4> K;
+  K << 160.19677247, 15.5358468938, 1.60401194139, 1.33861213093, 1.60401194142, 1.33861213094, 160.19677247, 15.5358468938;
+  Eigen::Matrix<double, 4, 4> A_inv;
+  A_inv << 1.0, -0.00505742153256, 0.0, 1.27875036472e-05, 0.0, 1.02306051542, 0.0, -0.00515393603998, 0.0, 1.27875036472e-05, 1.0, -0.00505742153256, 0.0, -0.00515393603998, 0.0, 1.02306051542;
+  return StateFeedbackController<4, 2, 2>(L, K, A_inv, MakeDrivetrainHighLowPlantCoefficients());
+}
+
+StateFeedbackController<4, 2, 2> MakeDrivetrainHighHighController() {
+  Eigen::Matrix<double, 4, 2> L;
+  L << 1.2774840927, 0.00492433284048, 79.1440456622, 1.05150722636, 0.00492433284048, 1.2774840927, 1.05150722636, 79.1440456622;
+  Eigen::Matrix<double, 2, 4> K;
+  K << 160.19677247, 15.5358468938, 1.60401194139, 1.33861213093, 1.60401194142, 1.33861213094, 160.19677247, 15.5358468938;
+  Eigen::Matrix<double, 4, 4> A_inv;
+  A_inv << 1.0, -0.00505742153256, 0.0, 1.27875036472e-05, 0.0, 1.02306051542, 0.0, -0.00515393603998, 0.0, 1.27875036472e-05, 1.0, -0.00505742153256, 0.0, -0.00515393603998, 0.0, 1.02306051542;
+  return StateFeedbackController<4, 2, 2>(L, K, A_inv, MakeDrivetrainHighHighPlantCoefficients());
+}
+
+StateFeedbackPlant<4, 2, 2> MakeDrivetrainPlant() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackPlantCoefficients<4, 2, 2>>> plants(4);
+  plants[0] = ::std::unique_ptr<StateFeedbackPlantCoefficients<4, 2, 2>>(new StateFeedbackPlantCoefficients<4, 2, 2>(MakeDrivetrainLowLowPlantCoefficients()));
+  plants[1] = ::std::unique_ptr<StateFeedbackPlantCoefficients<4, 2, 2>>(new StateFeedbackPlantCoefficients<4, 2, 2>(MakeDrivetrainLowHighPlantCoefficients()));
+  plants[2] = ::std::unique_ptr<StateFeedbackPlantCoefficients<4, 2, 2>>(new StateFeedbackPlantCoefficients<4, 2, 2>(MakeDrivetrainHighLowPlantCoefficients()));
+  plants[3] = ::std::unique_ptr<StateFeedbackPlantCoefficients<4, 2, 2>>(new StateFeedbackPlantCoefficients<4, 2, 2>(MakeDrivetrainHighHighPlantCoefficients()));
+  return StateFeedbackPlant<4, 2, 2>(&plants);
+}
+
+StateFeedbackLoop<4, 2, 2> MakeDrivetrainLoop() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackController<4, 2, 2>>> controllers(4);
+  controllers[0] = ::std::unique_ptr<StateFeedbackController<4, 2, 2>>(new StateFeedbackController<4, 2, 2>(MakeDrivetrainLowLowController()));
+  controllers[1] = ::std::unique_ptr<StateFeedbackController<4, 2, 2>>(new StateFeedbackController<4, 2, 2>(MakeDrivetrainLowHighController()));
+  controllers[2] = ::std::unique_ptr<StateFeedbackController<4, 2, 2>>(new StateFeedbackController<4, 2, 2>(MakeDrivetrainHighLowController()));
+  controllers[3] = ::std::unique_ptr<StateFeedbackController<4, 2, 2>>(new StateFeedbackController<4, 2, 2>(MakeDrivetrainHighHighController()));
+  return StateFeedbackLoop<4, 2, 2>(&controllers);
+}
+
+}  // namespace control_loops
+}  // namespace bot3
diff --git a/bot3/control_loops/drivetrain/drivetrain_dog_motor_plant.h b/bot3/control_loops/drivetrain/drivetrain_dog_motor_plant.h
new file mode 100644
index 0000000..f5d5896
--- /dev/null
+++ b/bot3/control_loops/drivetrain/drivetrain_dog_motor_plant.h
@@ -0,0 +1,32 @@
+#ifndef BOT3_CONTROL_LOOPS_DRIVETRAIN_DRIVETRAIN_DOG_MOTOR_PLANT_H_
+#define BOT3_CONTROL_LOOPS_DRIVETRAIN_DRIVETRAIN_DOG_MOTOR_PLANT_H_
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace bot3 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeDrivetrainLowLowPlantCoefficients();
+
+StateFeedbackController<4, 2, 2> MakeDrivetrainLowLowController();
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeDrivetrainLowHighPlantCoefficients();
+
+StateFeedbackController<4, 2, 2> MakeDrivetrainLowHighController();
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeDrivetrainHighLowPlantCoefficients();
+
+StateFeedbackController<4, 2, 2> MakeDrivetrainHighLowController();
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeDrivetrainHighHighPlantCoefficients();
+
+StateFeedbackController<4, 2, 2> MakeDrivetrainHighHighController();
+
+StateFeedbackPlant<4, 2, 2> MakeDrivetrainPlant();
+
+StateFeedbackLoop<4, 2, 2> MakeDrivetrainLoop();
+
+}  // namespace control_loops
+}  // namespace bot3
+
+#endif  // BOT3_CONTROL_LOOPS_DRIVETRAIN_DRIVETRAIN_DOG_MOTOR_PLANT_H_
diff --git a/bot3/control_loops/drivetrain/drivetrain_lib_test.cc b/bot3/control_loops/drivetrain/drivetrain_lib_test.cc
new file mode 100644
index 0000000..b9e828e
--- /dev/null
+++ b/bot3/control_loops/drivetrain/drivetrain_lib_test.cc
@@ -0,0 +1,296 @@
+#include <unistd.h>
+
+#include <memory>
+
+#include "gtest/gtest.h"
+#include "aos/common/network/team_number.h"
+#include "aos/common/queue_testutils.h"
+#include "aos/common/controls/polytope.h"
+#include "aos/common/controls/control_loop_test.h"
+
+#include "bot3/control_loops/drivetrain/drivetrain.q.h"
+#include "bot3/control_loops/drivetrain/drivetrain.h"
+#include "frc971/control_loops/state_feedback_loop.h"
+#include "frc971/control_loops/coerce_goal.h"
+#include "bot3/control_loops/drivetrain/drivetrain_dog_motor_plant.h"
+#include "frc971/queues/gyro.q.h"
+
+namespace bot3 {
+namespace control_loops {
+namespace testing {
+
+class Environment : public ::testing::Environment {
+ public:
+  virtual ~Environment() {}
+  // how to set up the environment.
+  virtual void SetUp() {
+    aos::controls::HPolytope<0>::Init();
+  }
+};
+::testing::Environment* const holder_env =
+  ::testing::AddGlobalTestEnvironment(new Environment);
+
+class TeamNumberEnvironment : public ::testing::Environment {
+ public:
+  // Override this to define how to set up the environment.
+  virtual void SetUp() { aos::network::OverrideTeamNumber(971); }
+};
+
+::testing::Environment* const team_number_env =
+    ::testing::AddGlobalTestEnvironment(new TeamNumberEnvironment);
+
+// Class which simulates the drivetrain and sends out queue messages containing
+// the position.
+class DrivetrainSimulation {
+ public:
+  // Constructs a motor simulation.
+  // TODO(aschuh) Do we want to test the clutch one too?
+  DrivetrainSimulation()
+      : drivetrain_plant_(
+            new StateFeedbackPlant<4, 2, 2>(MakeDrivetrainPlant())),
+        my_drivetrain_queue_(".bot3.control_loops.drivetrain",
+                       0x8a8dde77, ".bot3.control_loops.drivetrain.goal",
+                       ".bot3.control_loops.drivetrain.position",
+                       ".bot3.control_loops.drivetrain.output",
+                       ".bot3.control_loops.drivetrain.status") {
+    Reinitialize();
+  }
+
+  // Resets the plant.
+  void Reinitialize() {
+    drivetrain_plant_->mutable_X(0, 0) = 0.0;
+    drivetrain_plant_->mutable_X(1, 0) = 0.0;
+    drivetrain_plant_->mutable_Y() =
+        drivetrain_plant_->C() * drivetrain_plant_->X();
+    last_left_position_ = drivetrain_plant_->Y(0, 0);
+    last_right_position_ = drivetrain_plant_->Y(1, 0);
+  }
+
+  // Returns the position of the drivetrain.
+  double GetLeftPosition() const { return drivetrain_plant_->Y(0, 0); }
+  double GetRightPosition() const { return drivetrain_plant_->Y(1, 0); }
+
+  // Sends out the position queue messages.
+  void SendPositionMessage() {
+    const double left_encoder = GetLeftPosition();
+    const double right_encoder = GetRightPosition();
+
+    ::aos::ScopedMessagePtr<control_loops::DrivetrainQueue::Position> position =
+        my_drivetrain_queue_.position.MakeMessage();
+    position->left_encoder = left_encoder;
+    position->right_encoder = right_encoder;
+    position.Send();
+  }
+
+  // Simulates the drivetrain moving for one timestep.
+  void Simulate() {
+    last_left_position_ = drivetrain_plant_->Y(0, 0);
+    last_right_position_ = drivetrain_plant_->Y(1, 0);
+    EXPECT_TRUE(my_drivetrain_queue_.output.FetchLatest());
+    drivetrain_plant_->mutable_U() << my_drivetrain_queue_.output->left_voltage,
+        my_drivetrain_queue_.output->right_voltage;
+    drivetrain_plant_->Update();
+  }
+
+  ::std::unique_ptr<StateFeedbackPlant<4, 2, 2>> drivetrain_plant_;
+ private:
+  DrivetrainQueue my_drivetrain_queue_;
+  double last_left_position_;
+  double last_right_position_;
+};
+
+class DrivetrainTest : public ::aos::testing::ControlLoopTest {
+ protected:
+  // Create a new instance of the test queue so that it invalidates the queue
+  // that it points to.  Otherwise, we will have a pointer to shared memory that
+  // is no longer valid.
+  DrivetrainQueue my_drivetrain_queue_;
+
+  // Create a loop and simulation plant.
+  DrivetrainLoop drivetrain_motor_;
+  DrivetrainSimulation drivetrain_motor_plant_;
+
+  DrivetrainTest() : my_drivetrain_queue_(".bot3.control_loops.drivetrain",
+                               0x8a8dde77,
+                               ".bot3.control_loops.drivetrain.goal",
+                               ".bot3.control_loops.drivetrain.position",
+                               ".bot3.control_loops.drivetrain.output",
+                               ".bot3.control_loops.drivetrain.status"),
+                drivetrain_motor_(&my_drivetrain_queue_),
+                drivetrain_motor_plant_() {
+    ::frc971::sensors::gyro_reading.Clear();
+  }
+
+  void VerifyNearGoal() {
+    my_drivetrain_queue_.goal.FetchLatest();
+    my_drivetrain_queue_.position.FetchLatest();
+    EXPECT_NEAR(my_drivetrain_queue_.goal->left_goal,
+                drivetrain_motor_plant_.GetLeftPosition(),
+                1e-2);
+    EXPECT_NEAR(my_drivetrain_queue_.goal->right_goal,
+                drivetrain_motor_plant_.GetRightPosition(),
+                1e-2);
+  }
+
+  virtual ~DrivetrainTest() {
+    ::frc971::sensors::gyro_reading.Clear();
+  }
+};
+
+// Tests that the drivetrain converges on a goal.
+TEST_F(DrivetrainTest, ConvergesCorrectly) {
+  my_drivetrain_queue_.goal.MakeWithBuilder().control_loop_driving(true)
+      .left_goal(-1.0)
+      .right_goal(1.0).Send();
+  for (int i = 0; i < 200; ++i) {
+    drivetrain_motor_plant_.SendPositionMessage();
+    drivetrain_motor_.Iterate();
+    drivetrain_motor_plant_.Simulate();
+    SimulateTimestep(true);
+  }
+  VerifyNearGoal();
+}
+
+// Tests that it survives disabling.
+TEST_F(DrivetrainTest, SurvivesDisabling) {
+  my_drivetrain_queue_.goal.MakeWithBuilder().control_loop_driving(true)
+      .left_goal(-1.0)
+      .right_goal(1.0).Send();
+  for (int i = 0; i < 500; ++i) {
+    drivetrain_motor_plant_.SendPositionMessage();
+    drivetrain_motor_.Iterate();
+    drivetrain_motor_plant_.Simulate();
+    if (i > 20 && i < 200) {
+      SimulateTimestep(false);
+    } else {
+      SimulateTimestep(true);
+    }
+  }
+  VerifyNearGoal();
+}
+
+// Tests that never having a goal doesn't break.
+TEST_F(DrivetrainTest, NoGoalStart) {
+  for (int i = 0; i < 20; ++i) {
+    drivetrain_motor_plant_.SendPositionMessage();
+    drivetrain_motor_.Iterate();
+    drivetrain_motor_plant_.Simulate();
+  }
+}
+
+// Tests that never having a goal, but having driver's station messages, doesn't
+// break.
+TEST_F(DrivetrainTest, NoGoalWithRobotState) {
+  for (int i = 0; i < 20; ++i) {
+    drivetrain_motor_plant_.SendPositionMessage();
+    drivetrain_motor_.Iterate();
+    drivetrain_motor_plant_.Simulate();
+    SimulateTimestep(true);
+  }
+}
+
+::aos::controls::HPolytope<2> MakeBox(double x1_min, double x1_max,
+                                      double x2_min, double x2_max) {
+  Eigen::Matrix<double, 4, 2> box_H;
+  box_H << /*[[*/ 1.0, 0.0 /*]*/,
+            /*[*/-1.0, 0.0 /*]*/,
+            /*[*/ 0.0, 1.0 /*]*/,
+            /*[*/ 0.0,-1.0 /*]]*/;
+  Eigen::Matrix<double, 4, 1> box_k;
+  box_k << /*[[*/ x1_max /*]*/,
+            /*[*/-x1_min /*]*/,
+            /*[*/ x2_max /*]*/,
+            /*[*/-x2_min /*]]*/;
+  ::aos::controls::HPolytope<2> t_poly(box_H, box_k);
+  return t_poly;
+}
+
+class CoerceGoalTest : public ::testing::Test {
+ public:
+  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
+};
+
+// WHOOOHH!
+TEST_F(CoerceGoalTest, Inside) {
+  ::aos::controls::HPolytope<2> box = MakeBox(1, 2, 1, 2);
+
+  Eigen::Matrix<double, 1, 2> K;
+  K << /*[[*/ 1, -1 /*]]*/;
+
+  Eigen::Matrix<double, 2, 1> R;
+  R << /*[[*/ 1.5, 1.5 /*]]*/;
+
+  Eigen::Matrix<double, 2, 1> output =
+      ::frc971::control_loops::CoerceGoal(box, K, 0, R);
+
+  EXPECT_EQ(R(0, 0), output(0, 0));
+  EXPECT_EQ(R(1, 0), output(1, 0));
+}
+
+TEST_F(CoerceGoalTest, Outside_Inside_Intersect) {
+  ::aos::controls::HPolytope<2> box = MakeBox(1, 2, 1, 2);
+
+  Eigen::Matrix<double, 1, 2> K;
+  K << 1, -1;
+
+  Eigen::Matrix<double, 2, 1> R;
+  R << 5, 5;
+
+  Eigen::Matrix<double, 2, 1> output =
+      ::frc971::control_loops::CoerceGoal(box, K, 0, R);
+
+  EXPECT_EQ(2.0, output(0, 0));
+  EXPECT_EQ(2.0, output(1, 0));
+}
+
+TEST_F(CoerceGoalTest, Outside_Inside_no_Intersect) {
+  ::aos::controls::HPolytope<2> box = MakeBox(3, 4, 1, 2);
+
+  Eigen::Matrix<double, 1, 2> K;
+  K << 1, -1;
+
+  Eigen::Matrix<double, 2, 1> R;
+  R << 5, 5;
+
+  Eigen::Matrix<double, 2, 1> output =
+      ::frc971::control_loops::CoerceGoal(box, K, 0, R);
+
+  EXPECT_EQ(3.0, output(0, 0));
+  EXPECT_EQ(2.0, output(1, 0));
+}
+
+TEST_F(CoerceGoalTest, Middle_Of_Edge) {
+  ::aos::controls::HPolytope<2> box = MakeBox(0, 4, 1, 2);
+
+  Eigen::Matrix<double, 1, 2> K;
+  K << -1, 1;
+
+  Eigen::Matrix<double, 2, 1> R;
+  R << 5, 5;
+
+  Eigen::Matrix<double, 2, 1> output =
+      ::frc971::control_loops::CoerceGoal(box, K, 0, R);
+
+  EXPECT_EQ(2.0, output(0, 0));
+  EXPECT_EQ(2.0, output(1, 0));
+}
+
+TEST_F(CoerceGoalTest, PerpendicularLine) {
+  ::aos::controls::HPolytope<2> box = MakeBox(1, 2, 1, 2);
+
+  Eigen::Matrix<double, 1, 2> K;
+  K << 1, 1;
+
+  Eigen::Matrix<double, 2, 1> R;
+  R << 5, 5;
+
+  Eigen::Matrix<double, 2, 1> output =
+      ::frc971::control_loops::CoerceGoal(box, K, 0, R);
+
+  EXPECT_EQ(1.0, output(0, 0));
+  EXPECT_EQ(1.0, output(1, 0));
+}
+
+}  // namespace testing
+}  // namespace control_loops
+}  // namespace bot3
diff --git a/bot3/control_loops/drivetrain/drivetrain_main.cc b/bot3/control_loops/drivetrain/drivetrain_main.cc
new file mode 100644
index 0000000..f06acc0
--- /dev/null
+++ b/bot3/control_loops/drivetrain/drivetrain_main.cc
@@ -0,0 +1,11 @@
+#include "bot3/control_loops/drivetrain/drivetrain.h"
+
+#include "aos/linux_code/init.h"
+
+int main() {
+  ::aos::Init();
+  bot3::control_loops::DrivetrainLoop drivetrain;
+  drivetrain.Run();
+  ::aos::Cleanup();
+  return 0;
+}
diff --git a/bot3/control_loops/drivetrain/polydrivetrain_cim_plant.cc b/bot3/control_loops/drivetrain/polydrivetrain_cim_plant.cc
new file mode 100644
index 0000000..86eb915
--- /dev/null
+++ b/bot3/control_loops/drivetrain/polydrivetrain_cim_plant.cc
@@ -0,0 +1,49 @@
+#include "bot3/control_loops/drivetrain/polydrivetrain_cim_plant.h"
+
+#include <vector>
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace bot3 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<1, 1, 1> MakeCIMPlantCoefficients() {
+  Eigen::Matrix<double, 1, 1> A;
+  A << 0.783924473544;
+  Eigen::Matrix<double, 1, 1> B;
+  B << 8.94979586973;
+  Eigen::Matrix<double, 1, 1> C;
+  C << 1;
+  Eigen::Matrix<double, 1, 1> D;
+  D << 0;
+  Eigen::Matrix<double, 1, 1> U_max;
+  U_max << 12.0;
+  Eigen::Matrix<double, 1, 1> U_min;
+  U_min << -12.0;
+  return StateFeedbackPlantCoefficients<1, 1, 1>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackController<1, 1, 1> MakeCIMController() {
+  Eigen::Matrix<double, 1, 1> L;
+  L << 0.773924473544;
+  Eigen::Matrix<double, 1, 1> K;
+  K << 0.086473980503;
+  Eigen::Matrix<double, 1, 1> A_inv;
+  A_inv << 1.2756330919;
+  return StateFeedbackController<1, 1, 1>(L, K, A_inv, MakeCIMPlantCoefficients());
+}
+
+StateFeedbackPlant<1, 1, 1> MakeCIMPlant() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackPlantCoefficients<1, 1, 1>>> plants(1);
+  plants[0] = ::std::unique_ptr<StateFeedbackPlantCoefficients<1, 1, 1>>(new StateFeedbackPlantCoefficients<1, 1, 1>(MakeCIMPlantCoefficients()));
+  return StateFeedbackPlant<1, 1, 1>(&plants);
+}
+
+StateFeedbackLoop<1, 1, 1> MakeCIMLoop() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackController<1, 1, 1>>> controllers(1);
+  controllers[0] = ::std::unique_ptr<StateFeedbackController<1, 1, 1>>(new StateFeedbackController<1, 1, 1>(MakeCIMController()));
+  return StateFeedbackLoop<1, 1, 1>(&controllers);
+}
+
+}  // namespace control_loops
+}  // namespace bot3
diff --git a/bot3/control_loops/drivetrain/polydrivetrain_cim_plant.h b/bot3/control_loops/drivetrain/polydrivetrain_cim_plant.h
new file mode 100644
index 0000000..dcbd577
--- /dev/null
+++ b/bot3/control_loops/drivetrain/polydrivetrain_cim_plant.h
@@ -0,0 +1,20 @@
+#ifndef BOT3_CONTROL_LOOPS_DRIVETRAIN_POLYDRIVETRAIN_CIM_PLANT_H_
+#define BOT3_CONTROL_LOOPS_DRIVETRAIN_POLYDRIVETRAIN_CIM_PLANT_H_
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace bot3 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<1, 1, 1> MakeCIMPlantCoefficients();
+
+StateFeedbackController<1, 1, 1> MakeCIMController();
+
+StateFeedbackPlant<1, 1, 1> MakeCIMPlant();
+
+StateFeedbackLoop<1, 1, 1> MakeCIMLoop();
+
+}  // namespace control_loops
+}  // namespace bot3
+
+#endif  // BOT3_CONTROL_LOOPS_DRIVETRAIN_POLYDRIVETRAIN_CIM_PLANT_H_
diff --git a/bot3/control_loops/drivetrain/polydrivetrain_dog_motor_plant.cc b/bot3/control_loops/drivetrain/polydrivetrain_dog_motor_plant.cc
new file mode 100644
index 0000000..95913ff
--- /dev/null
+++ b/bot3/control_loops/drivetrain/polydrivetrain_dog_motor_plant.cc
@@ -0,0 +1,133 @@
+#include "bot3/control_loops/drivetrain/polydrivetrain_dog_motor_plant.h"
+
+#include <vector>
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace bot3 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<2, 2, 2> MakeVelocityDrivetrainLowLowPlantCoefficients() {
+  Eigen::Matrix<double, 2, 2> A;
+  A << 0.955499400541, 0.00962691403749, 0.00962691403749, 0.955499400541;
+  Eigen::Matrix<double, 2, 2> B;
+  B << 0.0164714763931, -0.00356331126397, -0.00356331126397, 0.0164714763931;
+  Eigen::Matrix<double, 2, 2> C;
+  C << 1.0, 0.0, 0.0, 1.0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0.0, 0.0, 0.0, 0.0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<2, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackPlantCoefficients<2, 2, 2> MakeVelocityDrivetrainLowHighPlantCoefficients() {
+  Eigen::Matrix<double, 2, 2> A;
+  A << 0.955499400541, 0.00962691403749, 0.00962691403749, 0.955499400541;
+  Eigen::Matrix<double, 2, 2> B;
+  B << 0.0164714763931, -0.00356331126397, -0.00356331126397, 0.0164714763931;
+  Eigen::Matrix<double, 2, 2> C;
+  C << 1.0, 0.0, 0.0, 1.0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0.0, 0.0, 0.0, 0.0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<2, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackPlantCoefficients<2, 2, 2> MakeVelocityDrivetrainHighLowPlantCoefficients() {
+  Eigen::Matrix<double, 2, 2> A;
+  A << 0.955499400541, 0.00962691403749, 0.00962691403749, 0.955499400541;
+  Eigen::Matrix<double, 2, 2> B;
+  B << 0.0164714763931, -0.00356331126397, -0.00356331126397, 0.0164714763931;
+  Eigen::Matrix<double, 2, 2> C;
+  C << 1.0, 0.0, 0.0, 1.0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0.0, 0.0, 0.0, 0.0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<2, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackPlantCoefficients<2, 2, 2> MakeVelocityDrivetrainHighHighPlantCoefficients() {
+  Eigen::Matrix<double, 2, 2> A;
+  A << 0.955499400541, 0.00962691403749, 0.00962691403749, 0.955499400541;
+  Eigen::Matrix<double, 2, 2> B;
+  B << 0.0164714763931, -0.00356331126397, -0.00356331126397, 0.0164714763931;
+  Eigen::Matrix<double, 2, 2> C;
+  C << 1.0, 0.0, 0.0, 1.0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0.0, 0.0, 0.0, 0.0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<2, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackController<2, 2, 2> MakeVelocityDrivetrainLowLowController() {
+  Eigen::Matrix<double, 2, 2> L;
+  L << 0.935499400541, 0.00962691403749, 0.00962691403749, 0.935499400541;
+  Eigen::Matrix<double, 2, 2> K;
+  K << 22.7750288573, 5.51143253556, 5.51143253556, 22.7750288573;
+  Eigen::Matrix<double, 2, 2> A_inv;
+  A_inv << 1.04667938127, -0.010545576923, -0.010545576923, 1.04667938127;
+  return StateFeedbackController<2, 2, 2>(L, K, A_inv, MakeVelocityDrivetrainLowLowPlantCoefficients());
+}
+
+StateFeedbackController<2, 2, 2> MakeVelocityDrivetrainLowHighController() {
+  Eigen::Matrix<double, 2, 2> L;
+  L << 0.935499400541, 0.00962691403749, 0.00962691403749, 0.935499400541;
+  Eigen::Matrix<double, 2, 2> K;
+  K << 22.7750288573, 5.51143253556, 5.51143253556, 22.7750288573;
+  Eigen::Matrix<double, 2, 2> A_inv;
+  A_inv << 1.04667938127, -0.010545576923, -0.010545576923, 1.04667938127;
+  return StateFeedbackController<2, 2, 2>(L, K, A_inv, MakeVelocityDrivetrainLowHighPlantCoefficients());
+}
+
+StateFeedbackController<2, 2, 2> MakeVelocityDrivetrainHighLowController() {
+  Eigen::Matrix<double, 2, 2> L;
+  L << 0.935499400541, 0.00962691403749, 0.00962691403749, 0.935499400541;
+  Eigen::Matrix<double, 2, 2> K;
+  K << 22.7750288573, 5.51143253556, 5.51143253556, 22.7750288573;
+  Eigen::Matrix<double, 2, 2> A_inv;
+  A_inv << 1.04667938127, -0.010545576923, -0.010545576923, 1.04667938127;
+  return StateFeedbackController<2, 2, 2>(L, K, A_inv, MakeVelocityDrivetrainHighLowPlantCoefficients());
+}
+
+StateFeedbackController<2, 2, 2> MakeVelocityDrivetrainHighHighController() {
+  Eigen::Matrix<double, 2, 2> L;
+  L << 0.935499400541, 0.00962691403749, 0.00962691403749, 0.935499400541;
+  Eigen::Matrix<double, 2, 2> K;
+  K << 22.7750288573, 5.51143253556, 5.51143253556, 22.7750288573;
+  Eigen::Matrix<double, 2, 2> A_inv;
+  A_inv << 1.04667938127, -0.010545576923, -0.010545576923, 1.04667938127;
+  return StateFeedbackController<2, 2, 2>(L, K, A_inv, MakeVelocityDrivetrainHighHighPlantCoefficients());
+}
+
+StateFeedbackPlant<2, 2, 2> MakeVelocityDrivetrainPlant() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackPlantCoefficients<2, 2, 2>>> plants(4);
+  plants[0] = ::std::unique_ptr<StateFeedbackPlantCoefficients<2, 2, 2>>(new StateFeedbackPlantCoefficients<2, 2, 2>(MakeVelocityDrivetrainLowLowPlantCoefficients()));
+  plants[1] = ::std::unique_ptr<StateFeedbackPlantCoefficients<2, 2, 2>>(new StateFeedbackPlantCoefficients<2, 2, 2>(MakeVelocityDrivetrainLowHighPlantCoefficients()));
+  plants[2] = ::std::unique_ptr<StateFeedbackPlantCoefficients<2, 2, 2>>(new StateFeedbackPlantCoefficients<2, 2, 2>(MakeVelocityDrivetrainHighLowPlantCoefficients()));
+  plants[3] = ::std::unique_ptr<StateFeedbackPlantCoefficients<2, 2, 2>>(new StateFeedbackPlantCoefficients<2, 2, 2>(MakeVelocityDrivetrainHighHighPlantCoefficients()));
+  return StateFeedbackPlant<2, 2, 2>(&plants);
+}
+
+StateFeedbackLoop<2, 2, 2> MakeVelocityDrivetrainLoop() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackController<2, 2, 2>>> controllers(4);
+  controllers[0] = ::std::unique_ptr<StateFeedbackController<2, 2, 2>>(new StateFeedbackController<2, 2, 2>(MakeVelocityDrivetrainLowLowController()));
+  controllers[1] = ::std::unique_ptr<StateFeedbackController<2, 2, 2>>(new StateFeedbackController<2, 2, 2>(MakeVelocityDrivetrainLowHighController()));
+  controllers[2] = ::std::unique_ptr<StateFeedbackController<2, 2, 2>>(new StateFeedbackController<2, 2, 2>(MakeVelocityDrivetrainHighLowController()));
+  controllers[3] = ::std::unique_ptr<StateFeedbackController<2, 2, 2>>(new StateFeedbackController<2, 2, 2>(MakeVelocityDrivetrainHighHighController()));
+  return StateFeedbackLoop<2, 2, 2>(&controllers);
+}
+
+}  // namespace control_loops
+}  // namespace bot3
diff --git a/bot3/control_loops/drivetrain/polydrivetrain_dog_motor_plant.h b/bot3/control_loops/drivetrain/polydrivetrain_dog_motor_plant.h
new file mode 100644
index 0000000..191d1aa
--- /dev/null
+++ b/bot3/control_loops/drivetrain/polydrivetrain_dog_motor_plant.h
@@ -0,0 +1,32 @@
+#ifndef BOT3_CONTROL_LOOPS_DRIVETRAIN_POLYDRIVETRAIN_DOG_MOTOR_PLANT_H_
+#define BOT3_CONTROL_LOOPS_DRIVETRAIN_POLYDRIVETRAIN_DOG_MOTOR_PLANT_H_
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace bot3 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<2, 2, 2> MakeVelocityDrivetrainLowLowPlantCoefficients();
+
+StateFeedbackController<2, 2, 2> MakeVelocityDrivetrainLowLowController();
+
+StateFeedbackPlantCoefficients<2, 2, 2> MakeVelocityDrivetrainLowHighPlantCoefficients();
+
+StateFeedbackController<2, 2, 2> MakeVelocityDrivetrainLowHighController();
+
+StateFeedbackPlantCoefficients<2, 2, 2> MakeVelocityDrivetrainHighLowPlantCoefficients();
+
+StateFeedbackController<2, 2, 2> MakeVelocityDrivetrainHighLowController();
+
+StateFeedbackPlantCoefficients<2, 2, 2> MakeVelocityDrivetrainHighHighPlantCoefficients();
+
+StateFeedbackController<2, 2, 2> MakeVelocityDrivetrainHighHighController();
+
+StateFeedbackPlant<2, 2, 2> MakeVelocityDrivetrainPlant();
+
+StateFeedbackLoop<2, 2, 2> MakeVelocityDrivetrainLoop();
+
+}  // namespace control_loops
+}  // namespace bot3
+
+#endif  // BOT3_CONTROL_LOOPS_DRIVETRAIN_POLYDRIVETRAIN_DOG_MOTOR_PLANT_H_
diff --git a/bot3/control_loops/drivetrain/replay_drivetrain.cc b/bot3/control_loops/drivetrain/replay_drivetrain.cc
new file mode 100644
index 0000000..f2fb87c
--- /dev/null
+++ b/bot3/control_loops/drivetrain/replay_drivetrain.cc
@@ -0,0 +1,24 @@
+#include "aos/common/controls/replay_control_loop.h"
+#include "aos/linux_code/init.h"
+
+#include "bot3/control_loops/drivetrain/drivetrain.q.h"
+
+// Reads one or more log files and sends out all the queue messages (in the
+// correct order and at the correct time) to feed a "live" drivetrain process.
+
+int main(int argc, char **argv) {
+  if (argc <= 1) {
+    fprintf(stderr, "Need at least one file to replay!\n");
+    return EXIT_FAILURE;
+  }
+
+  ::aos::InitNRT();
+
+  ::aos::controls::ControlLoopReplayer<::bot3::control_loops::DrivetrainQueue>
+      replayer(&::bot3::control_loops::drivetrain_queue, "drivetrain");
+  for (int i = 1; i < argc; ++i) {
+    replayer.ProcessFile(argv[i]);
+  }
+
+  ::aos::Cleanup();
+}
diff --git a/bot3/control_loops/intake/intake.cc b/bot3/control_loops/intake/intake.cc
new file mode 100644
index 0000000..935730b
--- /dev/null
+++ b/bot3/control_loops/intake/intake.cc
@@ -0,0 +1,36 @@
+#include "bot3/control_loops/intake/intake.h"
+
+#include "bot3/control_loops/intake/intake.q.h"
+
+namespace bot3 {
+namespace control_loops {
+
+Intake::Intake(control_loops::IntakeQueue *intake)
+    : aos::controls::ControlLoop<control_loops::IntakeQueue>(intake) {}
+
+void Intake::RunIteration(
+    const control_loops::IntakeQueue::Goal *goal,
+    const control_loops::IntakeQueue::Position * /*position*/,
+    control_loops::IntakeQueue::Output *output,
+    control_loops::IntakeQueue::Status * /*status*/) {
+
+  if (output != nullptr) {
+    output->Zero();
+
+    const int16_t intake_movement = goal->movement;
+
+    if (intake_movement > 0) {
+      // Suck.
+      output->intake = kIntakeVoltageFullPower;
+    } else if (intake_movement < 0) {
+      // Spit.
+      output->intake = -kIntakeVoltageFullPower;
+    } else {
+      // Stationary.
+      output->intake = 0.0;
+    }
+  }
+}
+
+}  // namespace control_loops
+}  // namespace bot3
diff --git a/bot3/control_loops/intake/intake.gyp b/bot3/control_loops/intake/intake.gyp
new file mode 100644
index 0000000..41f1b7f
--- /dev/null
+++ b/bot3/control_loops/intake/intake.gyp
@@ -0,0 +1,60 @@
+{
+  'targets': [
+    {
+      'target_name': 'intake_queue',
+      'type': 'static_library',
+      'sources': ['intake.q'],
+      'variables': {
+        'header_path': 'bot3/control_loops/intake',
+      },
+      'dependencies': [
+        '<(AOS)/common/controls/controls.gyp:control_loop_queues',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/controls/controls.gyp:control_loop_queues',
+      ],
+      'includes': ['../../../aos/build/queues.gypi'],
+    },
+    {
+      'target_name': 'intake_lib',
+      'type': 'static_library',
+      'sources': [
+        'intake.cc',
+      ],
+      'dependencies': [
+        'intake_queue',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+      ],
+      'export_dependent_settings': [
+        'intake_queue',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+      ],
+    },
+    {
+      'target_name': 'intake_lib_test',
+      'type': 'executable',
+      'sources': [
+        'intake_lib_test.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+        'intake_lib',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+        '<(AOS)/common/controls/controls.gyp:control_loop_test',
+        '<(AOS)/common/common.gyp:time',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:team_number_test_environment',
+      ],
+    },
+    {
+      'target_name': 'intake',
+      'type': 'executable',
+      'sources': [
+        'intake_main.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        'intake_lib',
+      ],
+    },
+  ],
+}
diff --git a/bot3/control_loops/intake/intake.h b/bot3/control_loops/intake/intake.h
new file mode 100644
index 0000000..43cd9fc
--- /dev/null
+++ b/bot3/control_loops/intake/intake.h
@@ -0,0 +1,28 @@
+#ifndef BOT3_CONTROL_LOOPS_INTAKE_H_
+#define BOT3_CONTROL_LOOPS_INTAKE_H_
+
+#include "aos/common/controls/control_loop.h"
+
+#include "bot3/control_loops/intake/intake.q.h"
+
+namespace bot3 {
+namespace control_loops {
+
+constexpr double kIntakeVoltageFullPower = 12.0;
+
+class Intake : public aos::controls::ControlLoop<control_loops::IntakeQueue> {
+ public:
+  explicit Intake(
+      control_loops::IntakeQueue *intake_queue = &control_loops::intake_queue);
+
+ protected:
+  void RunIteration(const control_loops::IntakeQueue::Goal *goal,
+                    const control_loops::IntakeQueue::Position *position,
+                    control_loops::IntakeQueue::Output *output,
+                    control_loops::IntakeQueue::Status *status) override;
+};
+
+}  // namespace control_loops
+}  // namespace bot3
+
+#endif  // BOT3_CONTROL_LOOPS_INTAKE_H_
diff --git a/bot3/control_loops/intake/intake.q b/bot3/control_loops/intake/intake.q
new file mode 100644
index 0000000..3047f6b
--- /dev/null
+++ b/bot3/control_loops/intake/intake.q
@@ -0,0 +1,27 @@
+package bot3.control_loops;
+
+import "aos/common/controls/control_loops.q";
+
+queue_group IntakeQueue {
+  implements aos.control_loops.ControlLoop;
+
+  message Goal {
+    // Positive = suck, negative = spit, zero = stationary.
+    int16_t movement;
+  };
+
+  message Position {};
+
+  message Output {
+    double intake;
+  };
+
+  message Status {};
+
+  queue Goal goal;
+  queue Position position;
+  queue Output output;
+  queue Status status;
+};
+
+queue_group IntakeQueue intake_queue;
diff --git a/bot3/control_loops/intake/intake_lib_test.cc b/bot3/control_loops/intake/intake_lib_test.cc
new file mode 100644
index 0000000..6fe6672
--- /dev/null
+++ b/bot3/control_loops/intake/intake_lib_test.cc
@@ -0,0 +1,123 @@
+#include "bot3/control_loops/intake/intake.h"
+
+#include <math.h>
+#include <unistd.h>
+
+#include "gtest/gtest.h"
+#include "aos/common/queue.h"
+#include "aos/common/commonmath.h"
+#include "aos/common/controls/control_loop_test.h"
+#include "bot3/control_loops/intake/intake.q.h"
+
+using ::aos::time::Time;
+
+namespace bot3 {
+namespace control_loops {
+namespace testing {
+
+// Class which simulates the elevator and sends out queue messages with the
+// position.
+class IntakeSimulation {
+ public:
+  // Constructs a simulation.
+  IntakeSimulation()
+      : queue_(".bot3.control_loops.intake_queue", 0x627ceeeb,
+                      ".bot3.control_loops.intake_queue.goal",
+                      ".bot3.control_loops.intake_queue.position",
+                      ".bot3.control_loops.intake_queue.output",
+                      ".bot3.control_loops.intake_queue.status") {
+  }
+
+  // Simulates for a single timestep.
+  void Simulate() {
+    EXPECT_TRUE(queue_.output.FetchLatest());
+  }
+
+ private:
+  IntakeQueue queue_;
+};
+
+class IntakeTest : public ::aos::testing::ControlLoopTest {
+ protected:
+  IntakeTest()
+      : queue_(".bot3.control_loops.intake_queue", 0x627ceeeb,
+                      ".bot3.control_loops.intake_queue.goal",
+                      ".bot3.control_loops.intake_queue.position",
+                      ".bot3.control_loops.intake_queue.output",
+                      ".bot3.control_loops.intake_queue.status"),
+        intake_(&queue_),
+        plant_() {
+    set_team_id(971);
+  }
+
+  // Runs one iteration of the whole simulation.
+  void RunIteration(bool enabled = true) {
+    SendMessages(enabled);
+
+    queue_.position.MakeMessage().Send();
+
+    intake_.Iterate();
+
+    TickTime();
+  }
+
+  // Runs iterations until the specified amount of simulated time has elapsed.
+  void RunForTime(const Time &run_for, bool enabled = true) {
+    const auto start_time = Time::Now();
+    while (Time::Now() < start_time + run_for) {
+      RunIteration(enabled);
+    }
+  }
+
+  // Create a new instance of the test queue so that it invalidates the queue
+  // that it points to. Otherwise, we will have a pointed to shared memory that
+  // is no longer valid.
+  IntakeQueue queue_;
+
+  // Create a control loop.
+  Intake intake_;
+  IntakeSimulation plant_;
+};
+
+// Tests that the loop does nothing when the goal is zero.
+TEST_F(IntakeTest, DoesNothing) {
+  ASSERT_TRUE(queue_.goal.MakeWithBuilder()
+                  .movement(0)
+                  .Send());
+
+  // Run for a bit.
+  RunForTime(1.0);
+
+  ASSERT_TRUE(queue_.output.FetchLatest());
+  EXPECT_EQ(queue_.output->intake, 0.0);
+}
+
+// Tests that the intake sucks with a positive goal.
+TEST_F(IntakeTest, SuckingGoal) {
+  ASSERT_TRUE(queue_.goal.MakeWithBuilder()
+                  .movement(1)
+                  .Send());
+
+  // Run for a bit.
+  RunForTime(1.0);
+
+  ASSERT_TRUE(queue_.output.FetchLatest());
+  EXPECT_GT(queue_.output->intake, 0.0);
+}
+
+// Tests that the intake spits with a negative goal.
+TEST_F(IntakeTest, SpittingGoal) {
+  ASSERT_TRUE(queue_.goal.MakeWithBuilder()
+                  .movement(-1)
+                  .Send());
+
+  // Run for a bit.
+  RunForTime(1.0);
+
+  ASSERT_TRUE(queue_.output.FetchLatest());
+  EXPECT_LT(queue_.output->intake, 0.0);
+}
+
+}  // namespace testing
+}  // namespace control_loops
+}  // namespace bot3
diff --git a/bot3/control_loops/intake/intake_main.cc b/bot3/control_loops/intake/intake_main.cc
new file mode 100644
index 0000000..ccc5fab
--- /dev/null
+++ b/bot3/control_loops/intake/intake_main.cc
@@ -0,0 +1,11 @@
+#include "bot3/control_loops/intake/intake.h"
+
+#include "aos/linux_code/init.h"
+
+int main() {
+  ::aos::Init();
+  ::bot3::control_loops::Intake intake;
+  intake.Run();
+  ::aos::Cleanup();
+  return 0;
+}
diff --git a/bot3/control_loops/python/control_loop.py b/bot3/control_loops/python/control_loop.py
new file mode 100644
index 0000000..881880f
--- /dev/null
+++ b/bot3/control_loops/python/control_loop.py
@@ -0,0 +1,338 @@
+import controls
+import numpy
+
+class Constant(object):
+  def __init__ (self, name, formatt, value):
+    self.name = name
+    self.formatt = formatt
+    self.value = value
+    self.formatToType = {}
+    self.formatToType['%f'] = "double";
+    self.formatToType['%d'] = "int";
+  def __str__ (self):
+    return str("\nstatic constexpr %s %s = "+ self.formatt +";\n") % \
+        (self.formatToType[self.formatt], self.name, self.value)
+
+
+class ControlLoopWriter(object):
+  def __init__(self, gain_schedule_name, loops, namespaces=None, write_constants=False):
+    """Constructs a control loop writer.
+
+    Args:
+      gain_schedule_name: string, Name of the overall controller.
+      loops: array[ControlLoop], a list of control loops to gain schedule
+        in order.
+      namespaces: array[string], a list of names of namespaces to nest in
+        order.  If None, the default will be used.
+    """
+    self._gain_schedule_name = gain_schedule_name
+    self._loops = loops
+    if namespaces:
+      self._namespaces = namespaces
+    else:
+      self._namespaces = ['frc971', 'control_loops']
+
+    self._namespace_start = '\n'.join(
+        ['namespace %s {' % name for name in self._namespaces])
+
+    self._namespace_end = '\n'.join(
+        ['}  // namespace %s' % name for name in reversed(self._namespaces)])
+    
+    self._constant_list = []
+
+  def AddConstant(self, constant):
+    """Adds a constant to write.
+
+    Args:
+      constant: Constant, the constant to add to the header.
+    """
+    self._constant_list.append(constant)
+
+  def _TopDirectory(self):
+    return self._namespaces[0]
+
+  def _HeaderGuard(self, header_file):
+    return (self._TopDirectory().upper() + '_CONTROL_LOOPS_' +
+            header_file.upper().replace('.', '_').replace('/', '_') +
+            '_')
+
+  def Write(self, header_file, cc_file):
+    """Writes the loops to the specified files."""
+    self.WriteHeader(header_file)
+    self.WriteCC(header_file, cc_file)
+
+  def _GenericType(self, typename):
+    """Returns a loop template using typename for the type."""
+    num_states = self._loops[0].A.shape[0]
+    num_inputs = self._loops[0].B.shape[1]
+    num_outputs = self._loops[0].C.shape[0]
+    return '%s<%d, %d, %d>' % (
+        typename, num_states, num_inputs, num_outputs)
+
+  def _ControllerType(self):
+    """Returns a template name for StateFeedbackController."""
+    return self._GenericType('StateFeedbackController')
+
+  def _LoopType(self):
+    """Returns a template name for StateFeedbackLoop."""
+    return self._GenericType('StateFeedbackLoop')
+
+  def _PlantType(self):
+    """Returns a template name for StateFeedbackPlant."""
+    return self._GenericType('StateFeedbackPlant')
+
+  def _CoeffType(self):
+    """Returns a template name for StateFeedbackPlantCoefficients."""
+    return self._GenericType('StateFeedbackPlantCoefficients')
+
+  def WriteHeader(self, header_file, double_appendage=False, MoI_ratio=0.0):
+    """Writes the header file to the file named header_file.
+       Set double_appendage to true in order to include a ratio of
+       moments of inertia constant. Currently, only used for 2014 claw."""
+    with open(header_file, 'w') as fd:
+      header_guard = self._HeaderGuard(header_file)
+      fd.write('#ifndef %s\n'
+               '#define %s\n\n' % (header_guard, header_guard))
+      fd.write('#include \"frc971/control_loops/state_feedback_loop.h\"\n')
+      fd.write('\n')
+
+      fd.write(self._namespace_start)
+
+      for const in self._constant_list:
+          fd.write(str(const))
+
+      fd.write('\n\n')
+      for loop in self._loops:
+        fd.write(loop.DumpPlantHeader())
+        fd.write('\n')
+        fd.write(loop.DumpControllerHeader())
+        fd.write('\n')
+
+      fd.write('%s Make%sPlant();\n\n' %
+               (self._PlantType(), self._gain_schedule_name))
+
+      fd.write('%s Make%sLoop();\n\n' %
+               (self._LoopType(), self._gain_schedule_name))
+
+      fd.write(self._namespace_end)
+      fd.write('\n\n')
+      fd.write("#endif  // %s\n" % header_guard)
+
+  def WriteCC(self, header_file_name, cc_file):
+    """Writes the cc file to the file named cc_file."""
+    with open(cc_file, 'w') as fd:
+      fd.write('#include \"%s/control_loops/%s\"\n' %
+               (self._TopDirectory(), header_file_name))
+      fd.write('\n')
+      fd.write('#include <vector>\n')
+      fd.write('\n')
+      fd.write('#include \"frc971/control_loops/state_feedback_loop.h\"\n')
+      fd.write('\n')
+      fd.write(self._namespace_start)
+      fd.write('\n\n')
+      for loop in self._loops:
+        fd.write(loop.DumpPlant())
+        fd.write('\n')
+
+      for loop in self._loops:
+        fd.write(loop.DumpController())
+        fd.write('\n')
+
+      fd.write('%s Make%sPlant() {\n' %
+               (self._PlantType(), self._gain_schedule_name))
+      fd.write('  ::std::vector< ::std::unique_ptr<%s>> plants(%d);\n' % (
+          self._CoeffType(), len(self._loops)))
+      for index, loop in enumerate(self._loops):
+        fd.write('  plants[%d] = ::std::unique_ptr<%s>(new %s(%s));\n' %
+                 (index, self._CoeffType(), self._CoeffType(),
+                  loop.PlantFunction()))
+      fd.write('  return %s(&plants);\n' % self._PlantType())
+      fd.write('}\n\n')
+
+      fd.write('%s Make%sLoop() {\n' %
+               (self._LoopType(), self._gain_schedule_name))
+      fd.write('  ::std::vector< ::std::unique_ptr<%s>> controllers(%d);\n' % (
+          self._ControllerType(), len(self._loops)))
+      for index, loop in enumerate(self._loops):
+        fd.write('  controllers[%d] = ::std::unique_ptr<%s>(new %s(%s));\n' %
+                 (index, self._ControllerType(), self._ControllerType(),
+                  loop.ControllerFunction()))
+      fd.write('  return %s(&controllers);\n' % self._LoopType())
+      fd.write('}\n\n')
+
+      fd.write(self._namespace_end)
+      fd.write('\n')
+
+
+class ControlLoop(object):
+  def __init__(self, name):
+    """Constructs a control loop object.
+
+    Args:
+      name: string, The name of the loop to use when writing the C++ files.
+    """
+    self._name = name
+
+  def ContinuousToDiscrete(self, A_continuous, B_continuous, dt):
+    """Calculates the discrete time values for A and B.
+
+      Args:
+        A_continuous: numpy.matrix, The continuous time A matrix
+        B_continuous: numpy.matrix, The continuous time B matrix
+        dt: float, The time step of the control loop
+
+      Returns:
+        (A, B), numpy.matrix, the control matricies.
+    """
+    return controls.c2d(A_continuous, B_continuous, dt)
+
+  def InitializeState(self):
+    """Sets X, Y, and X_hat to zero defaults."""
+    self.X = numpy.zeros((self.A.shape[0], 1))
+    self.Y = self.C * self.X
+    self.X_hat = numpy.zeros((self.A.shape[0], 1))
+
+  def PlaceControllerPoles(self, poles):
+    """Places the controller poles.
+
+    Args:
+      poles: array, An array of poles.  Must be complex conjegates if they have
+        any imaginary portions.
+    """
+    self.K = controls.dplace(self.A, self.B, poles)
+
+  def PlaceObserverPoles(self, poles):
+    """Places the observer poles.
+
+    Args:
+      poles: array, An array of poles.  Must be complex conjegates if they have
+        any imaginary portions.
+    """
+    self.L = controls.dplace(self.A.T, self.C.T, poles).T
+
+  def Update(self, U):
+    """Simulates one time step with the provided U."""
+    #U = numpy.clip(U, self.U_min, self.U_max)
+    self.X = self.A * self.X + self.B * U
+    self.Y = self.C * self.X + self.D * U
+
+  def PredictObserver(self, U):
+    """Runs the predict step of the observer update."""
+    self.X_hat = (self.A * self.X_hat + self.B * U)
+
+  def CorrectObserver(self, U):
+    """Runs the correct step of the observer update."""
+    self.X_hat += numpy.linalg.inv(self.A) * self.L * (
+        self.Y - self.C * self.X_hat - self.D * U)
+
+  def UpdateObserver(self, U):
+    """Updates the observer given the provided U."""
+    self.X_hat = (self.A * self.X_hat + self.B * U +
+                  self.L * (self.Y - self.C * self.X_hat - self.D * U))
+
+  def _DumpMatrix(self, matrix_name, matrix):
+    """Dumps the provided matrix into a variable called matrix_name.
+
+    Args:
+      matrix_name: string, The variable name to save the matrix to.
+      matrix: The matrix to dump.
+
+    Returns:
+      string, The C++ commands required to populate a variable named matrix_name
+        with the contents of matrix.
+    """
+    ans = ['  Eigen::Matrix<double, %d, %d> %s;\n' % (
+        matrix.shape[0], matrix.shape[1], matrix_name)]
+    first = True
+    for x in xrange(matrix.shape[0]):
+      for y in xrange(matrix.shape[1]):
+        element = matrix[x, y]
+        if first:
+          ans.append('  %s << ' % matrix_name)
+          first = False
+        else:
+          ans.append(', ')
+        ans.append(str(element))
+
+    ans.append(';\n')
+    return ''.join(ans)
+
+  def DumpPlantHeader(self):
+    """Writes out a c++ header declaration which will create a Plant object.
+
+    Returns:
+      string, The header declaration for the function.
+    """
+    num_states = self.A.shape[0]
+    num_inputs = self.B.shape[1]
+    num_outputs = self.C.shape[0]
+    return 'StateFeedbackPlantCoefficients<%d, %d, %d> Make%sPlantCoefficients();\n' % (
+        num_states, num_inputs, num_outputs, self._name)
+
+  def DumpPlant(self):
+    """Writes out a c++ function which will create a PlantCoefficients object.
+
+    Returns:
+      string, The function which will create the object.
+    """
+    num_states = self.A.shape[0]
+    num_inputs = self.B.shape[1]
+    num_outputs = self.C.shape[0]
+    ans = ['StateFeedbackPlantCoefficients<%d, %d, %d>'
+           ' Make%sPlantCoefficients() {\n' % (
+        num_states, num_inputs, num_outputs, self._name)]
+
+    ans.append(self._DumpMatrix('A', self.A))
+    ans.append(self._DumpMatrix('B', self.B))
+    ans.append(self._DumpMatrix('C', self.C))
+    ans.append(self._DumpMatrix('D', self.D))
+    ans.append(self._DumpMatrix('U_max', self.U_max))
+    ans.append(self._DumpMatrix('U_min', self.U_min))
+
+    ans.append('  return StateFeedbackPlantCoefficients<%d, %d, %d>'
+               '(A, B, C, D, U_max, U_min);\n' % (num_states, num_inputs,
+                                                  num_outputs))
+    ans.append('}\n')
+    return ''.join(ans)
+
+  def PlantFunction(self):
+    """Returns the name of the plant coefficient function."""
+    return 'Make%sPlantCoefficients()' % self._name
+
+  def ControllerFunction(self):
+    """Returns the name of the controller function."""
+    return 'Make%sController()' % self._name
+
+  def DumpControllerHeader(self):
+    """Writes out a c++ header declaration which will create a Controller object.
+
+    Returns:
+      string, The header declaration for the function.
+    """
+    num_states = self.A.shape[0]
+    num_inputs = self.B.shape[1]
+    num_outputs = self.C.shape[0]
+    return 'StateFeedbackController<%d, %d, %d> %s;\n' % (
+        num_states, num_inputs, num_outputs, self.ControllerFunction())
+
+  def DumpController(self):
+    """Returns a c++ function which will create a Controller object.
+
+    Returns:
+      string, The function which will create the object.
+    """
+    num_states = self.A.shape[0]
+    num_inputs = self.B.shape[1]
+    num_outputs = self.C.shape[0]
+    ans = ['StateFeedbackController<%d, %d, %d> %s {\n' % (
+        num_states, num_inputs, num_outputs, self.ControllerFunction())]
+
+    ans.append(self._DumpMatrix('L', self.L))
+    ans.append(self._DumpMatrix('K', self.K))
+    ans.append(self._DumpMatrix('A_inv', numpy.linalg.inv(self.A)))
+
+    ans.append('  return StateFeedbackController<%d, %d, %d>'
+               '(L, K, A_inv, Make%sPlantCoefficients());\n' % (
+                   num_states, num_inputs, num_outputs, self._name))
+    ans.append('}\n')
+    return ''.join(ans)
diff --git a/bot3/control_loops/python/controls.py b/bot3/control_loops/python/controls.py
new file mode 100644
index 0000000..b66bd56
--- /dev/null
+++ b/bot3/control_loops/python/controls.py
@@ -0,0 +1,153 @@
+#!/usr/bin/python
+
+"""
+Control loop pole placement library.
+
+This library will grow to support many different pole placement methods.
+Currently it only supports direct pole placement.
+"""
+
+__author__ = 'Austin Schuh (austin.linux@gmail.com)'
+
+import numpy
+import slycot
+import scipy.signal.cont2discrete
+
+class Error (Exception):
+  """Base class for all control loop exceptions."""
+
+
+class PolePlacementError(Error):
+  """Exception raised when pole placement fails."""
+
+
+# TODO(aschuh): dplace should take a control system object.
+# There should also exist a function to manipulate laplace expressions, and
+# something to plot bode plots and all that.
+def dplace(A, B, poles, alpha=1e-6):
+  """Set the poles of (A - BF) to poles.
+
+  Args:
+    A: numpy.matrix(n x n), The A matrix.
+    B: numpy.matrix(n x m), The B matrix.
+    poles: array(imaginary numbers), The poles to use.  Complex conjugates poles
+      must be in pairs.
+
+  Raises:
+    ValueError: Arguments were the wrong shape or there were too many poles.
+    PolePlacementError: Pole placement failed.
+
+  Returns:
+    numpy.matrix(m x n), K
+  """
+  # See http://www.icm.tu-bs.de/NICONET/doc/SB01BD.html for a description of the
+  # fortran code that this is cleaning up the interface to.
+  n = A.shape[0]
+  if A.shape[1] != n:
+    raise ValueError("A must be square")
+  if B.shape[0] != n:
+    raise ValueError("B must have the same number of states as A.")
+  m = B.shape[1]
+
+  num_poles = len(poles)
+  if num_poles > n:
+    raise ValueError("Trying to place more poles than states.")
+
+  out = slycot.sb01bd(n=n,
+                      m=m,
+                      np=num_poles,
+                      alpha=alpha,
+                      A=A,
+                      B=B,
+                      w=numpy.array(poles),
+                      dico='D')
+
+  A_z = numpy.matrix(out[0])
+  num_too_small_eigenvalues = out[2]
+  num_assigned_eigenvalues = out[3]
+  num_uncontrollable_eigenvalues = out[4]
+  K = numpy.matrix(-out[5])
+  Z = numpy.matrix(out[6])
+
+  if num_too_small_eigenvalues != 0:
+    raise PolePlacementError("Number of eigenvalues that are too small "
+                             "and are therefore unmodified is %d." %
+                             num_too_small_eigenvalues)
+  if num_assigned_eigenvalues != num_poles:
+    raise PolePlacementError("Did not place all the eigenvalues that were "
+                             "requested. Only placed %d eigenvalues." %
+                             num_assigned_eigenvalues)
+  if num_uncontrollable_eigenvalues != 0:
+    raise PolePlacementError("Found %d uncontrollable eigenvlaues." %
+                             num_uncontrollable_eigenvalues)
+
+  return K
+
+
+def c2d(A, B, dt):
+  """Converts from continuous time state space representation to discrete time.
+     Returns (A, B).  C and D are unchanged."""
+
+  ans_a, ans_b, _, _, _ = scipy.signal.cont2discrete((A, B, None, None), dt)
+  return numpy.matrix(ans_a), numpy.matrix(ans_b)
+
+def ctrb(A, B):
+  """Returns the controlability matrix.
+
+    This matrix must have full rank for all the states to be controlable.
+  """
+  n = A.shape[0]
+  output = B
+  intermediate = B
+  for i in xrange(0, n):
+    intermediate = A * intermediate
+    output = numpy.concatenate((output, intermediate), axis=1)
+
+  return output
+
+def dlqr(A, B, Q, R):
+  """Solves for the optimal lqr controller.
+
+    x(n+1) = A * x(n) + B * u(n)
+    J = sum(0, inf, x.T * Q * x + u.T * R * u)
+  """
+
+  # P = (A.T * P * A) - (A.T * P * B * numpy.linalg.inv(R + B.T * P *B) * (A.T * P.T * B).T + Q
+
+  P, rcond, w, S, T = slycot.sb02od(
+      n=A.shape[0], m=B.shape[1], A=A, B=B, Q=Q, R=R, dico='D')
+
+  F = numpy.linalg.inv(R + B.T * P *B) * B.T * P * A
+  return F
+
+def kalman(A, B, C, Q, R):
+  """Solves for the steady state kalman gain and covariance matricies.
+
+    Args:
+      A, B, C: SS matricies.
+      Q: The model uncertantity
+      R: The measurement uncertainty
+
+    Returns:
+      KalmanGain, Covariance.
+  """
+  P = Q
+
+  I = numpy.matrix(numpy.eye(P.shape[0]))
+  At = A.T
+  Ct = C.T
+  i = 0
+
+  while True:
+    last_P = P
+    P_prior = A * P * At + Q
+    S = C * P_prior * Ct + R
+    K = P_prior * Ct * numpy.linalg.inv(S)
+    P = (I - K * C) * P_prior
+
+    diff = P - last_P
+    i += 1
+    if numpy.linalg.norm(diff) / numpy.linalg.norm(P) < 1e-9:
+      break
+
+  return K, P
diff --git a/bot3/control_loops/python/drivetrain.py b/bot3/control_loops/python/drivetrain.py
new file mode 100644
index 0000000..8ed62d6
--- /dev/null
+++ b/bot3/control_loops/python/drivetrain.py
@@ -0,0 +1,242 @@
+#!/usr/bin/python
+
+import control_loop
+import controls
+import numpy
+import sys
+from matplotlib import pylab
+
+
+class CIM(control_loop.ControlLoop):
+  def __init__(self):
+    super(CIM, self).__init__("CIM")
+    # Stall Torque in N m
+    self.stall_torque = 2.42
+    # Stall Current in Amps
+    self.stall_current = 133
+    # Free Speed in RPM
+    self.free_speed = 4650.0
+    # Free Current in Amps
+    self.free_current = 2.7
+    # Moment of inertia of the CIM in kg m^2
+    self.J = 0.0001
+    # Resistance of the motor, divided by 2 to account for the 2 motors
+    self.R = 12.0 / self.stall_current
+    # Motor velocity constant
+    self.Kv = ((self.free_speed / 60.0 * 2.0 * numpy.pi) /
+              (12.0 - self.R * self.free_current))
+    # Torque constant
+    self.Kt = self.stall_torque / self.stall_current
+    # Control loop time step
+    self.dt = 0.005
+
+    # State feedback matrices
+    self.A_continuous = numpy.matrix(
+        [[-self.Kt / self.Kv / (self.J * self.R)]])
+    self.B_continuous = numpy.matrix(
+        [[self.Kt / (self.J * self.R)]])
+    self.C = numpy.matrix([[1]])
+    self.D = numpy.matrix([[0]])
+
+    self.A, self.B = self.ContinuousToDiscrete(self.A_continuous,
+                                               self.B_continuous, self.dt)
+
+    self.PlaceControllerPoles([0.01])
+    self.PlaceObserverPoles([0.01])
+
+    self.U_max = numpy.matrix([[12.0]])
+    self.U_min = numpy.matrix([[-12.0]])
+
+    self.InitializeState()
+
+
+class Drivetrain(control_loop.ControlLoop):
+  def __init__(self, name="Drivetrain", left_low=True, right_low=True):
+    super(Drivetrain, self).__init__(name)
+    # Stall Torque in N m
+    self.stall_torque = 2.42
+    # Stall Current in Amps
+    self.stall_current = 133.0
+    # Free Speed in RPM. Used number from last year.
+    self.free_speed = 4650.0
+    # Free Current in Amps
+    self.free_current = 2.7
+    # Moment of inertia of the drivetrain in kg m^2
+    # Just borrowed from last year.
+    self.J = 10
+    # Mass of the robot, in kg.
+    self.m = 68
+    # Radius of the robot, in meters (from last year).
+    self.rb = 0.9603 / 2.0
+    # Radius of the wheels, in meters.
+    self.r = .0515938
+    # Resistance of the motor, divided by the number of motors.
+    self.R = 12.0 / self.stall_current / 2
+    # Motor velocity constant
+    self.Kv = ((self.free_speed / 60.0 * 2.0 * numpy.pi) /
+               (12.0 - self.R * self.free_current))
+    # Torque constant
+    self.Kt = self.stall_torque / self.stall_current
+    # Gear ratios
+    self.G_const = 28.0 / 50.0 * 20.0 / 64.0
+
+    self.G_low = self.G_const
+    self.G_high = self.G_const
+
+    if left_low:
+      self.Gl = self.G_low
+    else:
+      self.Gl = self.G_high
+    if right_low:
+      self.Gr = self.G_low
+    else:
+      self.Gr = self.G_high
+
+    # Control loop time step
+    self.dt = 0.005
+
+    # These describe the way that a given side of a robot will be influenced
+    # by the other side. Units of 1 / kg.
+    self.msp = 1.0 / self.m + self.rb * self.rb / self.J
+    self.msn = 1.0 / self.m - self.rb * self.rb / self.J
+    # The calculations which we will need for A and B.
+    self.tcl = -self.Kt / self.Kv / (self.Gl * self.Gl * self.R * self.r * self.r)
+    self.tcr = -self.Kt / self.Kv / (self.Gr * self.Gr * self.R * self.r * self.r)
+    self.mpl = self.Kt / (self.Gl * self.R * self.r)
+    self.mpr = self.Kt / (self.Gr * self.R * self.r)
+
+    # State feedback matrices
+    # X will be of the format
+    # [[positionl], [velocityl], [positionr], velocityr]]
+    self.A_continuous = numpy.matrix(
+        [[0, 1, 0, 0],
+         [0, self.msp * self.tcl, 0, self.msn * self.tcr],
+         [0, 0, 0, 1],
+         [0, self.msn * self.tcl, 0, self.msp * self.tcr]])
+    self.B_continuous = numpy.matrix(
+        [[0, 0],
+         [self.msp * self.mpl, self.msn * self.mpr],
+         [0, 0],
+         [self.msn * self.mpl, self.msp * self.mpr]])
+    self.C = numpy.matrix([[1, 0, 0, 0],
+                           [0, 0, 1, 0]])
+    self.D = numpy.matrix([[0, 0],
+                           [0, 0]])
+
+    #print "THE NUMBER I WANT" + str(numpy.linalg.inv(self.A_continuous) * -self.B_continuous * numpy.matrix([[12.0], [12.0]]))
+    self.A, self.B = self.ContinuousToDiscrete(
+        self.A_continuous, self.B_continuous, self.dt)
+
+    # Poles from last year.
+    self.hp = 0.65
+    self.lp = 0.83
+    self.PlaceControllerPoles([self.hp, self.lp, self.hp, self.lp])
+    print self.K
+    q_pos = 0.07
+    q_vel = 1.0
+    self.Q = numpy.matrix([[(1.0 / (q_pos ** 2.0)), 0.0, 0.0, 0.0],
+                           [0.0, (1.0 / (q_vel ** 2.0)), 0.0, 0.0],
+                           [0.0, 0.0, (1.0 / (q_pos ** 2.0)), 0.0],
+                           [0.0, 0.0, 0.0, (1.0 / (q_vel ** 2.0))]])
+
+    self.R = numpy.matrix([[(1.0 / (12.0 ** 2.0)), 0.0],
+                           [0.0, (1.0 / (12.0 ** 2.0))]])
+    self.K = controls.dlqr(self.A, self.B, self.Q, self.R)
+    print self.A
+    print self.B
+    print self.K
+    print numpy.linalg.eig(self.A - self.B * self.K)[0]
+
+    self.hlp = 0.3
+    self.llp = 0.4
+    self.PlaceObserverPoles([self.hlp, self.hlp, self.llp, self.llp])
+
+    self.U_max = numpy.matrix([[12.0], [12.0]])
+    self.U_min = numpy.matrix([[-12.0], [-12.0]])
+    self.InitializeState()
+
+def main(argv):
+  # Simulate the response of the system to a step input.
+  drivetrain = Drivetrain()
+  simulated_left = []
+  simulated_right = []
+  for _ in xrange(100):
+    drivetrain.Update(numpy.matrix([[12.0], [12.0]]))
+    simulated_left.append(drivetrain.X[0, 0])
+    simulated_right.append(drivetrain.X[2, 0])
+
+  #pylab.plot(range(100), simulated_left)
+  #pylab.plot(range(100), simulated_right)
+  #pylab.show()
+
+  # Simulate forwards motion.
+  drivetrain = Drivetrain()
+  close_loop_left = []
+  close_loop_right = []
+  R = numpy.matrix([[1.0], [0.0], [1.0], [0.0]])
+  for _ in xrange(100):
+    U = numpy.clip(drivetrain.K * (R - drivetrain.X_hat),
+                   drivetrain.U_min, drivetrain.U_max)
+    drivetrain.UpdateObserver(U)
+    drivetrain.Update(U)
+    close_loop_left.append(drivetrain.X[0, 0])
+    close_loop_right.append(drivetrain.X[2, 0])
+
+  #pylab.plot(range(100), close_loop_left)
+  #pylab.plot(range(100), close_loop_right)
+  #pylab.show()
+
+  # Try turning in place
+  drivetrain = Drivetrain()
+  close_loop_left = []
+  close_loop_right = []
+  R = numpy.matrix([[-1.0], [0.0], [1.0], [0.0]])
+  for _ in xrange(100):
+    U = numpy.clip(drivetrain.K * (R - drivetrain.X_hat),
+                   drivetrain.U_min, drivetrain.U_max)
+    drivetrain.UpdateObserver(U)
+    drivetrain.Update(U)
+    close_loop_left.append(drivetrain.X[0, 0])
+    close_loop_right.append(drivetrain.X[2, 0])
+
+  #pylab.plot(range(100), close_loop_left)
+  #pylab.plot(range(100), close_loop_right)
+  #pylab.show()
+
+  # Try turning just one side.
+  drivetrain = Drivetrain()
+  close_loop_left = []
+  close_loop_right = []
+  R = numpy.matrix([[0.0], [0.0], [1.0], [0.0]])
+  for _ in xrange(100):
+    U = numpy.clip(drivetrain.K * (R - drivetrain.X_hat),
+                   drivetrain.U_min, drivetrain.U_max)
+    drivetrain.UpdateObserver(U)
+    drivetrain.Update(U)
+    close_loop_left.append(drivetrain.X[0, 0])
+    close_loop_right.append(drivetrain.X[2, 0])
+
+  #pylab.plot(range(100), close_loop_left)
+  #pylab.plot(range(100), close_loop_right)
+  #pylab.show()
+
+  # Write the generated constants out to a file.
+  print "Output one"
+  drivetrain_low_low = Drivetrain(name="DrivetrainLowLow", left_low=True, right_low=True)
+  drivetrain_low_high = Drivetrain(name="DrivetrainLowHigh", left_low=True, right_low=False)
+  drivetrain_high_low = Drivetrain(name="DrivetrainHighLow", left_low=False, right_low=True)
+  drivetrain_high_high = Drivetrain(name="DrivetrainHighHigh", left_low=False, right_low=False)
+
+  if len(argv) != 5:
+    print "Expected .h file name and .cc file name"
+  else:
+    dog_loop_writer = control_loop.ControlLoopWriter(
+        "Drivetrain", [drivetrain_low_low, drivetrain_low_high,
+                       drivetrain_high_low, drivetrain_high_high])
+    if argv[1][-3:] == '.cc':
+      dog_loop_writer.Write(argv[2], argv[1])
+    else:
+      dog_loop_writer.Write(argv[1], argv[2])
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))
diff --git a/bot3/control_loops/python/elevator.py b/bot3/control_loops/python/elevator.py
new file mode 100644
index 0000000..2d72ff2
--- /dev/null
+++ b/bot3/control_loops/python/elevator.py
@@ -0,0 +1,247 @@
+#!/usr/bin/python
+
+import control_loop
+import controls
+import polytope
+import polydrivetrain
+import numpy
+import sys
+import matplotlib
+from matplotlib import pylab
+
+class Elevator(control_loop.ControlLoop):
+  def __init__(self, name="Elevator", mass=None):
+    super(Elevator, self).__init__(name)
+    # Stall Torque in N m
+    self.stall_torque = 2.42
+    # Stall Current in Amps
+    self.stall_current = 133
+    # Free Speed in RPM
+    self.free_speed = 4650.0
+    # Free Current in Amps
+    self.free_current = 2.7
+    # Mass of the elevator
+    # TODO(comran): Get actual value.
+    self.mass = 13.0
+    # Resistance of the motor
+    self.R = 12.0 / self.stall_current
+    # Motor velocity constant
+    self.Kv = ((self.free_speed / 60.0 * 2.0 * numpy.pi) /
+               (12.0 - self.R * self.free_current))
+    # Torque constant
+    self.Kt = self.stall_torque / self.stall_current
+    # Gear ratio
+    # TODO(comran): Get actual value.
+    self.G = (56.0 / 12.0) * (84.0 / 14.0)
+    # Pulley diameter
+    # TODO(comran): Get actual value.
+    self.r = 32 * 0.005 / numpy.pi / 2.0
+    # Control loop time step
+    self.dt = 0.005
+
+    # Elevator spring constant (N/m)
+    # TODO(comran): Get actual value.
+    self.spring = 800.0
+
+    # State is [average position, average velocity]
+    # Input is [V]
+
+    # TODO(comran): Change everything below.
+
+    C1 = self.spring / (self.mass * 0.5)
+    C2 = self.Kt * self.G / (self.mass * 0.5 * self.r * self.R)
+    C3 = self.G * self.G * self.Kt / (
+        self.R  * self.r * self.r * self.mass * 0.5 * self.Kv)
+
+    self.A_continuous = numpy.matrix(
+        [[0, 1, 0, 0],
+         [0, -C3, 0, 0],
+         [0, 0, 0, 1],
+         [0, 0, -C1 * 2.0, -C3]])
+
+    print "Full speed is", C2 / C3 * 12.0
+
+    # Start with the unmodified input
+    self.B_continuous = numpy.matrix(
+        [[0, 0],
+         [C2 / 2.0, C2 / 2.0],
+         [0, 0],
+         [C2 / 2.0, -C2 / 2.0]])
+
+    self.C = numpy.matrix([[1, 0, 1, 0],
+                           [1, 0, -1, 0]])
+    self.D = numpy.matrix([[0, 0],
+                           [0, 0]])
+
+    self.A, self.B = self.ContinuousToDiscrete(
+        self.A_continuous, self.B_continuous, self.dt)
+
+    print self.A
+
+    controlability = controls.ctrb(self.A, self.B);
+    print "Rank of augmented controlability matrix.", numpy.linalg.matrix_rank(
+        controlability)
+
+    q_pos = 0.02
+    q_vel = 0.400
+    q_pos_diff = 0.01
+    q_vel_diff = 0.45
+    self.Q = numpy.matrix([[(1.0 / (q_pos ** 2.0)), 0.0, 0.0, 0.0],
+                           [0.0, (1.0 / (q_vel ** 2.0)), 0.0, 0.0],
+                           [0.0, 0.0, (1.0 / (q_pos_diff ** 2.0)), 0.0],
+                           [0.0, 0.0, 0.0, (1.0 / (q_vel_diff ** 2.0))]])
+
+    self.R = numpy.matrix([[(1.0 / (12.0 ** 2.0)), 0.0],
+                           [0.0, 1.0 / (12.0 ** 2.0)]])
+    self.K = controls.dlqr(self.A, self.B, self.Q, self.R)
+    print self.K
+
+    print numpy.linalg.eig(self.A - self.B * self.K)[0]
+
+    self.rpl = 0.20
+    self.ipl = 0.05
+    self.PlaceObserverPoles([self.rpl + 1j * self.ipl,
+                             self.rpl + 1j * self.ipl,
+                             self.rpl - 1j * self.ipl,
+                             self.rpl - 1j * self.ipl])
+
+    # The box formed by U_min and U_max must encompass all possible values,
+    # or else Austin's code gets angry.
+    self.U_max = numpy.matrix([[12.0], [12.0]])
+    self.U_min = numpy.matrix([[-12.0], [-12.0]])
+
+    self.InitializeState()
+
+
+def CapU(U):
+  if U[0, 0] - U[1, 0] > 24:
+    return numpy.matrix([[12], [-12]])
+  elif U[0, 0] - U[1, 0] < -24:
+    return numpy.matrix([[-12], [12]])
+  else:
+    max_u = max(U[0, 0], U[1, 0])
+    min_u = min(U[0, 0], U[1, 0])
+    if max_u > 12:
+      return U - (max_u - 12)
+    if min_u < -12:
+      return U - (min_u + 12)
+    return U
+
+
+def run_test(elevator, initial_X, goal, max_separation_error=0.01,
+             show_graph=True, iterations=200, controller_elevator=None,
+             observer_elevator=None):
+  """Runs the elevator plant with an initial condition and goal.
+
+    The tests themselves are not terribly sophisticated; I just test for
+    whether the goal has been reached and whether the separation goes
+    outside of the initial and goal values by more than max_separation_error.
+    Prints out something for a failure of either condition and returns
+    False if tests fail.
+    Args:
+      elevator: elevator object to use.
+      initial_X: starting state.
+      goal: goal state.
+      show_graph: Whether or not to display a graph showing the changing
+           states and voltages.
+      iterations: Number of timesteps to run the model for.
+      controller_elevator: elevator object to get K from, or None if we should
+          use elevator.
+      observer_elevator: elevator object to use for the observer, or None if we
+          should use the actual state.
+  """
+
+  elevator.X = initial_X
+
+  if controller_elevator is None:
+    controller_elevator = elevator
+
+  if observer_elevator is not None:
+    observer_elevator.X_hat = initial_X + 0.01
+    observer_elevator.X_hat = initial_X
+
+  # Various lists for graphing things.
+  t = []
+  x_avg = []
+  x_sep = []
+  x_hat_avg = []
+  x_hat_sep = []
+  v_avg = []
+  v_sep = []
+  u_left = []
+  u_right = []
+
+  sep_plot_gain = 100.0
+
+  for i in xrange(iterations):
+    X_hat = elevator.X
+    if observer_elevator is not None:
+      X_hat = observer_elevator.X_hat
+      x_hat_avg.append(observer_elevator.X_hat[0, 0])
+      x_hat_sep.append(observer_elevator.X_hat[2, 0] * sep_plot_gain)
+    U = controller_elevator.K * (goal - X_hat)
+    U = CapU(U)
+    x_avg.append(elevator.X[0, 0])
+    v_avg.append(elevator.X[1, 0])
+    x_sep.append(elevator.X[2, 0] * sep_plot_gain)
+    v_sep.append(elevator.X[3, 0])
+    if observer_elevator is not None:
+      observer_elevator.PredictObserver(U)
+    elevator.Update(U)
+    if observer_elevator is not None:
+      observer_elevator.Y = elevator.Y
+      observer_elevator.CorrectObserver(U)
+
+    t.append(i * elevator.dt)
+    u_left.append(U[0, 0])
+    u_right.append(U[1, 0])
+
+  print numpy.linalg.inv(elevator.A)
+  print "delta time is ", elevator.dt
+  print "Velocity at t=0 is ", x_avg[0], v_avg[0], x_sep[0], v_sep[0]
+  print "Velocity at t=1+dt is ", x_avg[1], v_avg[1], x_sep[1], v_sep[1]
+
+  if show_graph:
+    pylab.subplot(2, 1, 1)
+    pylab.plot(t, x_avg, label='x avg')
+    pylab.plot(t, x_sep, label='x sep')
+    if observer_elevator is not None:
+      pylab.plot(t, x_hat_avg, label='x_hat avg')
+      pylab.plot(t, x_hat_sep, label='x_hat sep')
+    pylab.legend()
+
+    pylab.subplot(2, 1, 2)
+    pylab.plot(t, u_left, label='u left')
+    pylab.plot(t, u_right, label='u right')
+    pylab.legend()
+    pylab.show()
+
+
+def main(argv):
+  loaded_mass = 25
+  #loaded_mass = 0
+  elevator = Elevator(mass=13 + loaded_mass)
+  elevator_controller = Elevator(mass=13 + 15)
+  observer_elevator = Elevator(mass=13 + 15)
+  #observer_elevator = None
+
+  # Test moving the elevator with constant separation.
+  initial_X = numpy.matrix([[0.0], [0.0], [0.01], [0.0]])
+  #initial_X = numpy.matrix([[0.0], [0.0], [0.00], [0.0]])
+  R = numpy.matrix([[1.0], [0.0], [0.0], [0.0]])
+  run_test(elevator, initial_X, R, controller_elevator=elevator_controller,
+           observer_elevator=observer_elevator)
+
+  # Write the generated constants out to a file.
+  if len(argv) != 3:
+    print "Expected .h file name and .cc file name for the elevator."
+  else:
+    elevator = Elevator("Elevator")
+    loop_writer = control_loop.ControlLoopWriter("Elevator", [elevator])
+    if argv[1][-3:] == '.cc':
+      loop_writer.Write(argv[2], argv[1])
+    else:
+      loop_writer.Write(argv[1], argv[2])
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))
diff --git a/bot3/control_loops/python/elevator3.py b/bot3/control_loops/python/elevator3.py
new file mode 100755
index 0000000..120e8cc
--- /dev/null
+++ b/bot3/control_loops/python/elevator3.py
@@ -0,0 +1,273 @@
+#!/usr/bin/python
+
+import control_loop
+import controls
+import numpy
+import sys
+import matplotlib
+from matplotlib import pylab
+
+class Elevator(control_loop.ControlLoop):
+  def __init__(self, name="Elevator", mass=None):
+    super(Elevator, self).__init__(name)
+    # Stall Torque in N m
+    self.stall_torque = 2.402
+    # Stall Current in Amps
+    self.stall_current = 126.145
+    # Free Speed in RPM
+    self.free_speed = 5015.562
+    # Free Current in Amps
+    self.free_current = 1.170
+    # Mass of the Elevator
+    if mass is None:
+      self.mass = 5.0
+    else:
+      self.mass = mass
+
+    # Number of motors
+    self.num_motors = 2.0
+    # Resistance of the motor
+    self.resistance = 12.0 / self.stall_current
+    # Motor velocity constant
+    self.Kv = ((self.free_speed / 60.0 * 2.0 * numpy.pi) /
+               (12.0 - self.resistance * self.free_current))
+    # Torque constant
+    self.Kt = (self.num_motors * self.stall_torque) / self.stall_current
+    # Gear ratio
+    self.G = 8
+    # Radius of pulley
+    self.r = 0.0254
+
+    # Control loop time step
+    self.dt = 0.005
+
+    # State is [position, velocity]
+    # Input is [Voltage]
+
+    C1 = self.Kt * self.G * self.G / (self.Kv * self.resistance * self.r * self.r * self.mass)
+    C2 = self.G * self.Kt / (self.resistance * self.r * self.mass)
+
+    self.A_continuous = numpy.matrix(
+        [[0, 1],
+         [0, -C1]])
+
+    # Start with the unmodified input
+    self.B_continuous = numpy.matrix(
+        [[0],
+         [C2]])
+
+    self.C = numpy.matrix([[1, 0]])
+    self.D = numpy.matrix([[0]])
+    
+    self.A, self.B = self.ContinuousToDiscrete(
+        self.A_continuous, self.B_continuous, self.dt)
+
+    controlability = controls.ctrb(self.A, self.B);
+
+    q_pos = 0.015
+    q_vel = 0.5
+    self.Q = numpy.matrix([[(1.0 / (q_pos ** 2.0)), 0.0],
+                           [0.0, (1.0 / (q_vel ** 2.0))]])
+
+    self.R = numpy.matrix([[(1.0 / (12.0 ** 2.0))]])
+    self.K = controls.dlqr(self.A, self.B, self.Q, self.R)
+
+    print 'K', self.K
+    print 'Poles are', numpy.linalg.eig(self.A - self.B * self.K)[0]
+
+    self.rpl = 0.30
+    self.ipl = 0.10
+    self.PlaceObserverPoles([self.rpl + 1j * self.ipl,
+                             self.rpl - 1j * self.ipl])
+
+    #    print 'L is', self.L
+
+    q_pos = 0.05
+    q_vel = 2.65
+    self.Q = numpy.matrix([[(q_pos ** 2.0), 0.0],
+                           [0.0, (q_vel ** 2.0)]])
+
+    r_volts = 0.025
+    self.R = numpy.matrix([[(r_volts ** 2.0)]])
+
+    self.KalmanGain, self.Q_steady = controls.kalman(
+        A=self.A, B=self.B, C=self.C, Q=self.Q, R=self.R)
+
+    #    print 'Kal', self.KalmanGain
+    self.L = self.A * self.KalmanGain
+    print 'KalL is', self.L
+
+    # The box formed by U_min and U_max must encompass all possible values,
+    # or else Austin's code gets angry.
+    self.U_max = numpy.matrix([[12.0]])
+    self.U_min = numpy.matrix([[-12.0]])
+
+    self.InitializeState()
+
+class IntegralElevator(Elevator):
+  def __init__(self, name="IntegralElevator", mass=None):
+    super(IntegralElevator, self).__init__(name=name, mass=mass)
+
+    self.A_continuous_unaugmented = self.A_continuous
+    self.B_continuous_unaugmented = self.B_continuous
+
+    self.A_continuous = numpy.matrix(numpy.zeros((3, 3)))
+    self.A_continuous[0:2, 0:2] = self.A_continuous_unaugmented
+    self.A_continuous[0:2, 2] = self.B_continuous_unaugmented
+
+    self.B_continuous = numpy.matrix(numpy.zeros((3, 1)))
+    self.B_continuous[0:2, 0] = self.B_continuous_unaugmented
+
+    self.C_unaugmented = self.C
+    self.C = numpy.matrix(numpy.zeros((1, 3)))
+    self.C[0:1, 0:2] = self.C_unaugmented
+
+    self.A, self.B = self.ContinuousToDiscrete(self.A_continuous, self.B_continuous, self.dt)
+
+    q_pos = 0.08
+    q_vel = 0.40
+    q_voltage = 6.0
+    self.Q = numpy.matrix([[(q_pos ** 2.0), 0.0, 0.0],
+                           [0.0, (q_vel ** 2.0), 0.0],
+                           [0.0, 0.0, (q_voltage ** 2.0)]])
+
+    r_pos = 0.05
+    self.R = numpy.matrix([[(r_pos ** 2.0)]])
+
+    self.KalmanGain, self.Q_steady = controls.kalman(
+        A=self.A, B=self.B, C=self.C, Q=self.Q, R=self.R)
+    self.L = self.A * self.KalmanGain
+
+    self.K_unaugmented = self.K
+    self.K = numpy.matrix(numpy.zeros((1, 3)))
+    self.K[0, 0:2] = self.K_unaugmented
+    self.K[0, 2] = 1
+
+    self.InitializeState()
+
+
+class ScenarioPlotter(object):
+  def __init__(self):
+    # Various lists for graphing things.
+    self.t = []
+    self.x = []
+    self.v = []
+    self.a = []
+    self.x_hat = []
+    self.u = []
+
+  def run_test(self, elevator, goal,
+               iterations=200, controller_elevator=None,
+               observer_elevator=None):
+    """Runs the Elevator plant with an initial condition and goal.
+
+      Args:
+        Elevator: elevator object to use.
+        initial_X: starting state.
+        goal: goal state.
+        iterations: Number of timesteps to run the model for.
+        controller_Elevator: elevator object to get K from, or None if we should
+            use Elevator.
+        observer_Elevator: elevator object to use for the observer, or None if we should
+            use the actual state.
+    """
+
+    if controller_elevator is None:
+      controller_elevator = elevator
+
+    vbat = 10.0
+    if self.t:
+      initial_t = self.t[-1] + elevator.dt
+    else:
+      initial_t = 0
+    for i in xrange(iterations):
+      X_hat = elevator.X
+      if observer_elevator is not None:
+        X_hat = observer_elevator.X_hat
+        self.x_hat.append(observer_elevator.X_hat[0, 0])
+      gravity_compensation =  9.8 * elevator.mass * elevator.r / elevator.G / elevator.Kt * elevator.resistance
+
+      U = controller_elevator.K * (goal - X_hat)
+      U[0, 0] = numpy.clip(U[0, 0], -vbat , vbat )
+      self.x.append(elevator.X[0, 0])
+      if self.v:
+        last_v = self.v[-1]
+      else:
+        last_v = 0
+      self.v.append(elevator.X[1, 0])
+      self.a.append((self.v[-1] - last_v) / elevator.dt)
+
+      if observer_elevator is not None:
+        observer_elevator.Y = elevator.Y
+        observer_elevator.CorrectObserver(U)
+
+      elevator.Update(U - gravity_compensation)
+
+      if observer_elevator is not None:
+        observer_elevator.PredictObserver(U)
+
+      self.t.append(initial_t + i * elevator.dt)
+      self.u.append(U[0, 0])
+#      if numpy.abs((goal - X_hat)[0:2, 0]).sum() < .025:
+#        print "Time: ", self.t[-1]
+#        break
+
+    print "Time: ", self.t[-1]
+
+
+  def Plot(self):
+    pylab.subplot(3, 1, 1)
+    pylab.plot(self.t, self.x, label='x')
+    pylab.plot(self.t, self.x_hat, label='x_hat')
+    pylab.legend()
+
+    pylab.subplot(3, 1, 2)
+    pylab.plot(self.t, self.u, label='u')
+
+    pylab.subplot(3, 1, 3)
+    pylab.plot(self.t, self.a, label='a')
+
+    pylab.legend()
+    pylab.show()
+
+
+def main(argv):
+  loaded_mass = 7+4.0
+  #loaded_mass = 0
+  #observer_elevator = None
+
+  # Test moving the Elevator
+  initial_X = numpy.matrix([[0.0], [0.0]])
+  up_R = numpy.matrix([[0.4572], [0.0], [0.0]])
+  down_R = numpy.matrix([[0.0], [0.0], [0.0]])
+  totemass = 3.54
+  scenario_plotter = ScenarioPlotter()
+
+  elevator_controller = IntegralElevator(mass=4*totemass + loaded_mass)
+  observer_elevator = IntegralElevator(mass=4*totemass + loaded_mass)
+
+  for i in xrange(0, 7):
+    elevator = Elevator(mass=i*totemass + loaded_mass)
+    print 'Actual poles are', numpy.linalg.eig(elevator.A - elevator.B * elevator_controller.K[0, 0:2])[0]
+
+    elevator.X = initial_X
+    scenario_plotter.run_test(elevator, goal=up_R, controller_elevator=elevator_controller,
+                              observer_elevator=observer_elevator, iterations=200)
+    scenario_plotter.run_test(elevator, goal=down_R, controller_elevator=elevator_controller,
+                              observer_elevator=observer_elevator, iterations=200)
+
+  scenario_plotter.Plot()
+
+  # Write the generated constants out to a file.
+  if len(argv) != 3:
+    print "Expected .h file name and .cc file name for the Elevator."
+  else:
+    elevator = Elevator("Elevator")
+    loop_writer = control_loop.ControlLoopWriter("Elevator", [elevator])
+    if argv[1][-3:] == '.cc':
+      loop_writer.Write(argv[2], argv[1])
+    else:
+      loop_writer.Write(argv[1], argv[2])
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))
diff --git a/bot3/control_loops/python/polydrivetrain.py b/bot3/control_loops/python/polydrivetrain.py
new file mode 100644
index 0000000..a62c8c8
--- /dev/null
+++ b/bot3/control_loops/python/polydrivetrain.py
@@ -0,0 +1,504 @@
+#!/usr/bin/python
+
+import numpy
+import sys
+import polytope
+import drivetrain
+import control_loop
+import controls
+from matplotlib import pylab
+
+__author__ = 'Austin Schuh (austin.linux@gmail.com)'
+
+
+def CoerceGoal(region, K, w, R):
+  """Intersects a line with a region, and finds the closest point to R.
+
+  Finds a point that is closest to R inside the region, and on the line
+  defined by K X = w.  If it is not possible to find a point on the line,
+  finds a point that is inside the region and closest to the line.  This
+  function assumes that
+
+  Args:
+    region: HPolytope, the valid goal region.
+    K: numpy.matrix (2 x 1), the matrix for the equation [K1, K2] [x1; x2] = w
+    w: float, the offset in the equation above.
+    R: numpy.matrix (2 x 1), the point to be closest to.
+
+  Returns:
+    numpy.matrix (2 x 1), the point.
+  """
+  return DoCoerceGoal(region, K, w, R)[0]
+
+def DoCoerceGoal(region, K, w, R):
+  if region.IsInside(R):
+    return (R, True)
+
+  perpendicular_vector = K.T / numpy.linalg.norm(K)
+  parallel_vector = numpy.matrix([[perpendicular_vector[1, 0]],
+                                  [-perpendicular_vector[0, 0]]])
+  
+  # We want to impose the constraint K * X = w on the polytope H * X <= k.
+  # We do this by breaking X up into parallel and perpendicular components to
+  # the half plane.  This gives us the following equation.
+  #
+  #  parallel * (parallel.T \dot X) + perpendicular * (perpendicular \dot X)) = X
+  #
+  # Then, substitute this into the polytope.
+  #
+  #  H * (parallel * (parallel.T \dot X) + perpendicular * (perpendicular \dot X)) <= k
+  #
+  # Substitute K * X = w
+  #
+  # H * parallel * (parallel.T \dot X) + H * perpendicular * w <= k
+  #
+  # Move all the knowns to the right side.
+  #
+  # H * parallel * ([parallel1 parallel2] * X) <= k - H * perpendicular * w
+  #
+  # Let t = parallel.T \dot X, the component parallel to the surface.
+  #
+  # H * parallel * t <= k - H * perpendicular * w
+  #
+  # This is a polytope which we can solve, and use to figure out the range of X
+  # that we care about!
+
+  t_poly = polytope.HPolytope(
+      region.H * parallel_vector,
+      region.k - region.H * perpendicular_vector * w)
+
+  vertices = t_poly.Vertices()
+
+  if vertices.shape[0]:
+    # The region exists!
+    # Find the closest vertex
+    min_distance = numpy.infty
+    closest_point = None
+    for vertex in vertices:
+      point = parallel_vector * vertex + perpendicular_vector * w
+      length = numpy.linalg.norm(R - point)
+      if length < min_distance:
+        min_distance = length
+        closest_point = point
+
+    return (closest_point, True)
+  else:
+    # Find the vertex of the space that is closest to the line.
+    region_vertices = region.Vertices()
+    min_distance = numpy.infty
+    closest_point = None
+    for vertex in region_vertices:
+      point = vertex.T
+      length = numpy.abs((perpendicular_vector.T * point)[0, 0])
+      if length < min_distance:
+        min_distance = length
+        closest_point = point
+
+    return (closest_point, False)
+
+
+class VelocityDrivetrainModel(control_loop.ControlLoop):
+  def __init__(self, left_low=True, right_low=True, name="VelocityDrivetrainModel"):
+    super(VelocityDrivetrainModel, self).__init__(name)
+    self._drivetrain = drivetrain.Drivetrain(left_low=left_low,
+                                             right_low=right_low)
+    self.dt = 0.01
+    self.A_continuous = numpy.matrix(
+        [[self._drivetrain.A_continuous[1, 1], self._drivetrain.A_continuous[1, 3]],
+         [self._drivetrain.A_continuous[3, 1], self._drivetrain.A_continuous[3, 3]]])
+
+    self.B_continuous = numpy.matrix(
+        [[self._drivetrain.B_continuous[1, 0], self._drivetrain.B_continuous[1, 1]],
+         [self._drivetrain.B_continuous[3, 0], self._drivetrain.B_continuous[3, 1]]])
+    self.C = numpy.matrix(numpy.eye(2));
+    self.D = numpy.matrix(numpy.zeros((2, 2)));
+
+    self.A, self.B = self.ContinuousToDiscrete(self.A_continuous,
+                                               self.B_continuous, self.dt)
+
+    # FF * X = U (steady state)
+    self.FF = self.B.I * (numpy.eye(2) - self.A)
+
+    self.PlaceControllerPoles([0.6, 0.6])
+    self.PlaceObserverPoles([0.02, 0.02])
+
+    self.G_high = self._drivetrain.G_high
+    self.G_low = self._drivetrain.G_low
+    self.R = self._drivetrain.R
+    self.r = self._drivetrain.r
+    self.Kv = self._drivetrain.Kv
+    self.Kt = self._drivetrain.Kt
+
+    self.U_max = self._drivetrain.U_max
+    self.U_min = self._drivetrain.U_min
+
+
+class VelocityDrivetrain(object):
+  HIGH = 'high'
+  LOW = 'low'
+  SHIFTING_UP = 'up'
+  SHIFTING_DOWN = 'down'
+
+  def __init__(self):
+    self.drivetrain_low_low = VelocityDrivetrainModel(
+        left_low=True, right_low=True, name='VelocityDrivetrainLowLow')
+    self.drivetrain_low_high = VelocityDrivetrainModel(left_low=True, right_low=False, name='VelocityDrivetrainLowHigh')
+    self.drivetrain_high_low = VelocityDrivetrainModel(left_low=False, right_low=True, name = 'VelocityDrivetrainHighLow')
+    self.drivetrain_high_high = VelocityDrivetrainModel(left_low=False, right_low=False, name = 'VelocityDrivetrainHighHigh')
+
+    # X is [lvel, rvel]
+    self.X = numpy.matrix(
+        [[0.0],
+         [0.0]])
+
+    self.U_poly = polytope.HPolytope(
+        numpy.matrix([[1, 0],
+                      [-1, 0],
+                      [0, 1],
+                      [0, -1]]),
+        numpy.matrix([[12],
+                      [12],
+                      [12],
+                      [12]]))
+
+    self.U_max = numpy.matrix(
+        [[12.0],
+         [12.0]])
+    self.U_min = numpy.matrix(
+        [[-12.0000000000],
+         [-12.0000000000]])
+
+    self.dt = 0.01
+
+    self.R = numpy.matrix(
+        [[0.0],
+         [0.0]])
+
+    # ttrust is the comprimise between having full throttle negative inertia,
+    # and having no throttle negative inertia.  A value of 0 is full throttle
+    # inertia.  A value of 1 is no throttle negative inertia.
+    self.ttrust = 1.1
+
+    self.left_gear = VelocityDrivetrain.LOW
+    self.right_gear = VelocityDrivetrain.LOW
+    self.left_shifter_position = 0.0
+    self.right_shifter_position = 0.0
+    self.left_cim = drivetrain.CIM()
+    self.right_cim = drivetrain.CIM()
+
+  def IsInGear(self, gear):
+    return gear is VelocityDrivetrain.HIGH or gear is VelocityDrivetrain.LOW
+
+  def MotorRPM(self, shifter_position, velocity):
+    if shifter_position > 0.5:
+      return (velocity / self.CurrentDrivetrain().G_high /
+              self.CurrentDrivetrain().r)
+    else:
+      return (velocity / self.CurrentDrivetrain().G_low /
+              self.CurrentDrivetrain().r)
+
+  def CurrentDrivetrain(self):
+    if self.left_shifter_position > 0.5:
+      if self.right_shifter_position > 0.5:
+        return self.drivetrain_high_high
+      else:
+        return self.drivetrain_high_low
+    else:
+      if self.right_shifter_position > 0.5:
+        return self.drivetrain_low_high
+      else:
+        return self.drivetrain_low_low
+
+  def SimShifter(self, gear, shifter_position):
+    if gear is VelocityDrivetrain.HIGH or gear is VelocityDrivetrain.SHIFTING_UP:
+      shifter_position = min(shifter_position + 0.5, 1.0)
+    else:
+      shifter_position = max(shifter_position - 0.5, 0.0)
+
+    if shifter_position == 1.0:
+      gear = VelocityDrivetrain.HIGH
+    elif shifter_position == 0.0:
+      gear = VelocityDrivetrain.LOW
+
+    return gear, shifter_position
+
+  def ComputeGear(self, wheel_velocity, should_print=False, current_gear=False, gear_name=None):
+    high_omega = (wheel_velocity / self.CurrentDrivetrain().G_high /
+                  self.CurrentDrivetrain().r)
+    low_omega = (wheel_velocity / self.CurrentDrivetrain().G_low /
+                 self.CurrentDrivetrain().r)
+    #print gear_name, "Motor Energy Difference.", 0.5 * 0.000140032647 * (low_omega * low_omega - high_omega * high_omega), "joules"
+    high_torque = ((12.0 - high_omega / self.CurrentDrivetrain().Kv) *
+                   self.CurrentDrivetrain().Kt / self.CurrentDrivetrain().R)
+    low_torque = ((12.0 - low_omega / self.CurrentDrivetrain().Kv) *
+                  self.CurrentDrivetrain().Kt / self.CurrentDrivetrain().R)
+    high_power = high_torque * high_omega
+    low_power = low_torque * low_omega
+    #if should_print:
+    #  print gear_name, "High omega", high_omega, "Low omega", low_omega
+    #  print gear_name, "High torque", high_torque, "Low torque", low_torque
+    #  print gear_name, "High power", high_power, "Low power", low_power
+
+    # Shift algorithm improvements.
+    # TODO(aschuh):
+    # It takes time to shift.  Shifting down for 1 cycle doesn't make sense
+    # because you will end up slower than without shifting.  Figure out how
+    # to include that info.
+    # If the driver is still in high gear, but isn't asking for the extra power
+    # from low gear, don't shift until he asks for it.
+    goal_gear_is_high = high_power > low_power
+    #goal_gear_is_high = True
+
+    if not self.IsInGear(current_gear):
+      print gear_name, 'Not in gear.'
+      return current_gear
+    else:
+      is_high = current_gear is VelocityDrivetrain.HIGH
+      if is_high != goal_gear_is_high:
+        if goal_gear_is_high:
+          print gear_name, 'Shifting up.'
+          return VelocityDrivetrain.SHIFTING_UP
+        else:
+          print gear_name, 'Shifting down.'
+          return VelocityDrivetrain.SHIFTING_DOWN
+      else:
+        return current_gear
+
+  def FilterVelocity(self, throttle):
+    # Invert the plant to figure out how the velocity filter would have to work
+    # out in order to filter out the forwards negative inertia.
+    # This math assumes that the left and right power and velocity are equal.
+
+    # The throttle filter should filter such that the motor in the highest gear
+    # should be controlling the time constant.
+    # Do this by finding the index of FF that has the lowest value, and computing
+    # the sums using that index.
+    FF_sum = self.CurrentDrivetrain().FF.sum(axis=1)
+    min_FF_sum_index = numpy.argmin(FF_sum)
+    min_FF_sum = FF_sum[min_FF_sum_index, 0]
+    min_K_sum = self.CurrentDrivetrain().K[min_FF_sum_index, :].sum()
+    # Compute the FF sum for high gear.
+    high_min_FF_sum = self.drivetrain_high_high.FF[0, :].sum()
+
+    # U = self.K[0, :].sum() * (R - x_avg) + self.FF[0, :].sum() * R
+    # throttle * 12.0 = (self.K[0, :].sum() + self.FF[0, :].sum()) * R
+    #                   - self.K[0, :].sum() * x_avg
+
+    # R = (throttle * 12.0 + self.K[0, :].sum() * x_avg) /
+    #     (self.K[0, :].sum() + self.FF[0, :].sum())
+
+    # U = (K + FF) * R - K * X
+    # (K + FF) ^-1 * (U + K * X) = R
+
+    # Scale throttle by min_FF_sum / high_min_FF_sum.  This will make low gear
+    # have the same velocity goal as high gear, and so that the robot will hold
+    # the same speed for the same throttle for all gears.
+    adjusted_ff_voltage = numpy.clip(throttle * 12.0 * min_FF_sum / high_min_FF_sum, -12.0, 12.0)
+    return ((adjusted_ff_voltage + self.ttrust * min_K_sum * (self.X[0, 0] + self.X[1, 0]) / 2.0)
+            / (self.ttrust * min_K_sum + min_FF_sum))
+
+  def Update(self, throttle, steering):
+    # Shift into the gear which sends the most power to the floor.
+    # This is the same as sending the most torque down to the floor at the
+    # wheel.
+
+    self.left_gear = self.right_gear = True
+    if False:
+      self.left_gear = self.ComputeGear(self.X[0, 0], should_print=True,
+                                        current_gear=self.left_gear,
+                                        gear_name="left")
+      self.right_gear = self.ComputeGear(self.X[1, 0], should_print=True,
+                                         current_gear=self.right_gear,
+                                         gear_name="right")
+      if self.IsInGear(self.left_gear):
+        self.left_cim.X[0, 0] = self.MotorRPM(self.left_shifter_position, self.X[0, 0])
+
+      if self.IsInGear(self.right_gear):
+        self.right_cim.X[0, 0] = self.MotorRPM(self.right_shifter_position, self.X[0, 0])
+
+    steering *= 2.3
+    if True or self.IsInGear(self.left_gear) and self.IsInGear(self.right_gear):
+      # Filter the throttle to provide a nicer response.
+      fvel = self.FilterVelocity(throttle)
+
+      # Constant radius means that angualar_velocity / linear_velocity = constant.
+      # Compute the left and right velocities.
+      steering_velocity = numpy.abs(fvel) * steering
+      left_velocity = fvel - steering_velocity
+      right_velocity = fvel + steering_velocity
+
+      # Write this constraint in the form of K * R = w
+      # angular velocity / linear velocity = constant
+      # (left - right) / (left + right) = constant
+      # left - right = constant * left + constant * right
+
+      # (fvel - steering * numpy.abs(fvel) - fvel - steering * numpy.abs(fvel)) /
+      #  (fvel - steering * numpy.abs(fvel) + fvel + steering * numpy.abs(fvel)) =
+      #       constant
+      # (- 2 * steering * numpy.abs(fvel)) / (2 * fvel) = constant
+      # (-steering * sign(fvel)) = constant
+      # (-steering * sign(fvel)) * (left + right) = left - right
+      # (steering * sign(fvel) + 1) * left + (steering * sign(fvel) - 1) * right = 0
+
+      equality_k = numpy.matrix(
+          [[1 + steering * numpy.sign(fvel), -(1 - steering * numpy.sign(fvel))]])
+      equality_w = 0.0
+
+      self.R[0, 0] = left_velocity
+      self.R[1, 0] = right_velocity
+
+      # Construct a constraint on R by manipulating the constraint on U
+      # Start out with H * U <= k
+      # U = FF * R + K * (R - X)
+      # H * (FF * R + K * R - K * X) <= k
+      # H * (FF + K) * R <= k + H * K * X
+      R_poly = polytope.HPolytope(
+          self.U_poly.H * (self.CurrentDrivetrain().K + self.CurrentDrivetrain().FF),
+          self.U_poly.k + self.U_poly.H * self.CurrentDrivetrain().K * self.X)
+
+      # Limit R back inside the box.
+      self.boxed_R = CoerceGoal(R_poly, equality_k, equality_w, self.R)
+
+      FF_volts = self.CurrentDrivetrain().FF * self.boxed_R
+      self.U_ideal = self.CurrentDrivetrain().K * (self.boxed_R - self.X) + FF_volts
+    else:
+      print 'Not all in gear'
+      if not self.IsInGear(self.left_gear) and not self.IsInGear(self.right_gear):
+        # TODO(austin): Use battery volts here.
+        R_left = self.MotorRPM(self.left_shifter_position, self.X[0, 0])
+        self.U_ideal[0, 0] = numpy.clip(
+            self.left_cim.K * (R_left - self.left_cim.X) + R_left / self.left_cim.Kv,
+            self.left_cim.U_min, self.left_cim.U_max)
+        self.left_cim.Update(self.U_ideal[0, 0])
+
+        R_right = self.MotorRPM(self.right_shifter_position, self.X[1, 0])
+        self.U_ideal[1, 0] = numpy.clip(
+            self.right_cim.K * (R_right - self.right_cim.X) + R_right / self.right_cim.Kv,
+            self.right_cim.U_min, self.right_cim.U_max)
+        self.right_cim.Update(self.U_ideal[1, 0])
+      else:
+        assert False
+
+    self.U = numpy.clip(self.U_ideal, self.U_min, self.U_max)
+
+    # TODO(austin): Model the robot as not accelerating when you shift...
+    # This hack only works when you shift at the same time.
+    if True or self.IsInGear(self.left_gear) and self.IsInGear(self.right_gear):
+      self.X = self.CurrentDrivetrain().A * self.X + self.CurrentDrivetrain().B * self.U
+
+    self.left_gear, self.left_shifter_position = self.SimShifter(
+        self.left_gear, self.left_shifter_position)
+    self.right_gear, self.right_shifter_position = self.SimShifter(
+        self.right_gear, self.right_shifter_position)
+
+    print "U is", self.U[0, 0], self.U[1, 0]
+    print "Left shifter", self.left_gear, self.left_shifter_position, "Right shifter", self.right_gear, self.right_shifter_position
+
+
+def main(argv):
+  vdrivetrain = VelocityDrivetrain()
+
+  if len(argv) != 7:
+    print "Expected .h file name and .cc file name"
+  else:
+    dog_loop_writer = control_loop.ControlLoopWriter(
+        "VelocityDrivetrain", [vdrivetrain.drivetrain_low_low,
+                       vdrivetrain.drivetrain_low_high,
+                       vdrivetrain.drivetrain_high_low,
+                       vdrivetrain.drivetrain_high_high])
+
+    if argv[1][-3:] == '.cc':
+      dog_loop_writer.Write(argv[2], argv[1])
+    else:
+      dog_loop_writer.Write(argv[1], argv[2])
+
+    cim_writer = control_loop.ControlLoopWriter(
+        "CIM", [drivetrain.CIM()])
+
+    if argv[5][-3:] == '.cc':
+      cim_writer.Write(argv[6], argv[5])
+    else:
+      cim_writer.Write(argv[5], argv[6])
+    return
+
+  vl_plot = []
+  vr_plot = []
+  ul_plot = []
+  ur_plot = []
+  radius_plot = []
+  t_plot = []
+  left_gear_plot = []
+  right_gear_plot = []
+  vdrivetrain.left_shifter_position = 0.0
+  vdrivetrain.right_shifter_position = 0.0
+  vdrivetrain.left_gear = VelocityDrivetrain.LOW
+  vdrivetrain.right_gear = VelocityDrivetrain.LOW
+
+  print "K is", vdrivetrain.CurrentDrivetrain().K
+
+  if vdrivetrain.left_gear is VelocityDrivetrain.HIGH:
+    print "Left is high"
+  else:
+    print "Left is low"
+  if vdrivetrain.right_gear is VelocityDrivetrain.HIGH:
+    print "Right is high"
+  else:
+    print "Right is low"
+
+  for t in numpy.arange(0, 1.7, vdrivetrain.dt):
+    if t < 0.5:
+      vdrivetrain.Update(throttle=0.00, steering=1.0)
+    elif t < 1.2:
+      vdrivetrain.Update(throttle=0.5, steering=1.0)
+    else:
+      vdrivetrain.Update(throttle=0.00, steering=1.0)
+    t_plot.append(t)
+    vl_plot.append(vdrivetrain.X[0, 0])
+    vr_plot.append(vdrivetrain.X[1, 0])
+    ul_plot.append(vdrivetrain.U[0, 0])
+    ur_plot.append(vdrivetrain.U[1, 0])
+    left_gear_plot.append((vdrivetrain.left_gear is VelocityDrivetrain.HIGH) * 2.0 - 10.0)
+    right_gear_plot.append((vdrivetrain.right_gear is VelocityDrivetrain.HIGH) * 2.0 - 10.0)
+
+    fwd_velocity = (vdrivetrain.X[1, 0] + vdrivetrain.X[0, 0]) / 2
+    turn_velocity = (vdrivetrain.X[1, 0] - vdrivetrain.X[0, 0])
+    if abs(fwd_velocity) < 0.0000001:
+      radius_plot.append(turn_velocity)
+    else:
+      radius_plot.append(turn_velocity / fwd_velocity)
+
+  cim_velocity_plot = []
+  cim_voltage_plot = []
+  cim_time = []
+  cim = drivetrain.CIM()
+  R = numpy.matrix([[300]])
+  for t in numpy.arange(0, 0.5, cim.dt):
+    U = numpy.clip(cim.K * (R - cim.X) + R / cim.Kv, cim.U_min, cim.U_max)
+    cim.Update(U)
+    cim_velocity_plot.append(cim.X[0, 0])
+    cim_voltage_plot.append(U[0, 0] * 10)
+    cim_time.append(t)
+  pylab.plot(cim_time, cim_velocity_plot, label='cim spinup')
+  pylab.plot(cim_time, cim_voltage_plot, label='cim voltage')
+  pylab.legend()
+  pylab.show()
+
+  # TODO(austin):
+  # Shifting compensation.
+
+  # Tighten the turn.
+  # Closed loop drive.
+
+  pylab.plot(t_plot, vl_plot, label='left velocity')
+  pylab.plot(t_plot, vr_plot, label='right velocity')
+  pylab.plot(t_plot, ul_plot, label='left voltage')
+  pylab.plot(t_plot, ur_plot, label='right voltage')
+  pylab.plot(t_plot, radius_plot, label='radius')
+  pylab.plot(t_plot, left_gear_plot, label='left gear high')
+  pylab.plot(t_plot, right_gear_plot, label='right gear high')
+  pylab.legend()
+  pylab.show()
+  return 0
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))
diff --git a/bot3/control_loops/python/polydrivetrain_test.py b/bot3/control_loops/python/polydrivetrain_test.py
new file mode 100644
index 0000000..434cdca
--- /dev/null
+++ b/bot3/control_loops/python/polydrivetrain_test.py
@@ -0,0 +1,82 @@
+#!/usr/bin/python
+
+import polydrivetrain
+import numpy
+from numpy.testing import *
+import polytope
+import unittest
+
+__author__ = 'Austin Schuh (austin.linux@gmail.com)'
+
+
+class TestVelocityDrivetrain(unittest.TestCase):
+  def MakeBox(self, x1_min, x1_max, x2_min, x2_max):
+    H = numpy.matrix([[1, 0],
+                      [-1, 0],
+                      [0, 1],
+                      [0, -1]])
+    K = numpy.matrix([[x1_max],
+                      [-x1_min],
+                      [x2_max],
+                      [-x2_min]])
+    return polytope.HPolytope(H, K)
+
+  def test_coerce_inside(self):
+    """Tests coercion when the point is inside the box."""
+    box = self.MakeBox(1, 2, 1, 2)
+
+    # x1 = x2
+    K = numpy.matrix([[1, -1]])
+    w = 0
+
+    assert_array_equal(polydrivetrain.CoerceGoal(box, K, w,
+                                                 numpy.matrix([[1.5], [1.5]])),
+                       numpy.matrix([[1.5], [1.5]]))
+
+  def test_coerce_outside_intersect(self):
+    """Tests coercion when the line intersects the box."""
+    box = self.MakeBox(1, 2, 1, 2)
+
+    # x1 = x2
+    K = numpy.matrix([[1, -1]])
+    w = 0
+
+    assert_array_equal(polydrivetrain.CoerceGoal(box, K, w, numpy.matrix([[5], [5]])),
+                       numpy.matrix([[2.0], [2.0]]))
+
+  def test_coerce_outside_no_intersect(self):
+    """Tests coercion when the line does not intersect the box."""
+    box = self.MakeBox(3, 4, 1, 2)
+
+    # x1 = x2
+    K = numpy.matrix([[1, -1]])
+    w = 0
+
+    assert_array_equal(polydrivetrain.CoerceGoal(box, K, w, numpy.matrix([[5], [5]])),
+                       numpy.matrix([[3.0], [2.0]]))
+
+  def test_coerce_middle_of_edge(self):
+    """Tests coercion when the line intersects the middle of an edge."""
+    box = self.MakeBox(0, 4, 1, 2)
+
+    # x1 = x2
+    K = numpy.matrix([[-1, 1]])
+    w = 0
+
+    assert_array_equal(polydrivetrain.CoerceGoal(box, K, w, numpy.matrix([[5], [5]])),
+                       numpy.matrix([[2.0], [2.0]]))
+
+  def test_coerce_perpendicular_line(self):
+    """Tests coercion when the line does not intersect and is in quadrant 2."""
+    box = self.MakeBox(1, 2, 1, 2)
+
+    # x1 = -x2
+    K = numpy.matrix([[1, 1]])
+    w = 0
+
+    assert_array_equal(polydrivetrain.CoerceGoal(box, K, w, numpy.matrix([[5], [5]])),
+                       numpy.matrix([[1.0], [1.0]]))
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/bot3/control_loops/update_drivetrain.sh b/bot3/control_loops/update_drivetrain.sh
new file mode 100644
index 0000000..369cbc5
--- /dev/null
+++ b/bot3/control_loops/update_drivetrain.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+#
+# Updates the drivetrain controllers.
+
+cd $(dirname $0)
+
+./python/drivetrain.py drivetrain/drivetrain_dog_motor_plant.h \
+    drivetrain/drivetrain_dog_motor_plant.cc \
+    drivetrain/drivetrain_clutch_motor_plant.h \
+    drivetrain/drivetrain_clutch_motor_plant.cc
diff --git a/bot3/control_loops/update_polydrivetrain.sh b/bot3/control_loops/update_polydrivetrain.sh
new file mode 100644
index 0000000..37987d5
--- /dev/null
+++ b/bot3/control_loops/update_polydrivetrain.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+#
+# Updates the polydrivetrain controllers and CIM models.
+
+cd $(dirname $0)
+
+./python/polydrivetrain.py drivetrain/polydrivetrain_dog_motor_plant.h \
+    drivetrain/polydrivetrain_dog_motor_plant.cc \
+    drivetrain/polydrivetrain_clutch_motor_plant.h \
+    drivetrain/polydrivetrain_clutch_motor_plant.cc \
+    drivetrain/polydrivetrain_cim_plant.h \
+    drivetrain/polydrivetrain_cim_plant.cc
diff --git a/bot3/joystick_reader.cc b/bot3/joystick_reader.cc
new file mode 100644
index 0000000..fd7f36b
--- /dev/null
+++ b/bot3/joystick_reader.cc
@@ -0,0 +1,148 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <math.h>
+
+#include "aos/linux_code/init.h"
+#include "aos/prime/input/joystick_input.h"
+#include "aos/common/input/driver_station_data.h"
+#include "aos/common/logging/logging.h"
+#include "aos/common/util/log_interval.h"
+#include "aos/common/time.h"
+#include "aos/common/actions/actions.h"
+
+#include "bot3/control_loops/drivetrain/drivetrain.q.h"
+#include "frc971/queues/gyro.q.h"
+#include "bot3/autonomous/auto.q.h"
+
+using ::bot3::control_loops::drivetrain_queue;
+using ::frc971::sensors::gyro_reading;
+
+using ::aos::input::driver_station::ButtonLocation;
+using ::aos::input::driver_station::POVLocation;
+using ::aos::input::driver_station::JoystickAxis;
+using ::aos::input::driver_station::ControlBit;
+
+namespace bot3 {
+namespace input {
+namespace joysticks {
+
+const JoystickAxis kSteeringWheel(1, 1), kDriveThrottle(2, 2);
+const ButtonLocation kShiftHigh(2, 1), kShiftLow(2, 3);
+const ButtonLocation kQuickTurn(1, 5);
+
+// TODO(comran): Figure out the actions we need.
+
+class Reader : public ::aos::input::JoystickInput {
+ public:
+  Reader() : was_running_(false) {}
+
+  virtual void RunIteration(const ::aos::input::driver_station::Data &data) {
+    bool last_auto_running = auto_running_;
+    auto_running_ = data.GetControlBit(ControlBit::kAutonomous) &&
+                    data.GetControlBit(ControlBit::kEnabled);
+    if (auto_running_ != last_auto_running) {
+      if (auto_running_) {
+        StartAuto();
+      } else {
+        StopAuto();
+      }
+    }
+
+    if (!data.GetControlBit(ControlBit::kAutonomous)) {
+      HandleDrivetrain(data);
+      HandleTeleop(data);
+    }
+  }
+
+  void HandleDrivetrain(const ::aos::input::driver_station::Data &data) {
+    const double wheel = -data.GetAxis(kSteeringWheel);
+    const double throttle = -data.GetAxis(kDriveThrottle);
+
+    if (!drivetrain_queue.goal.MakeWithBuilder()
+             .steering(wheel)
+             .throttle(throttle)
+             .quickturn(data.IsPressed(kQuickTurn))
+             .control_loop_driving(false)
+             .Send()) {
+      LOG(WARNING, "sending stick values failed\n");
+    }
+  }
+
+  void HandleTeleop(const ::aos::input::driver_station::Data &data) {
+    if (!data.GetControlBit(ControlBit::kEnabled)) {
+      action_queue_.CancelAllActions();
+      LOG(DEBUG, "Canceling\n");
+    }
+
+    // TODO(comran): Run stuff when buttons are pushed.
+
+    // TODO(comran): If it cannot get a status from the superstructure...
+    /*
+    if (!superstructure_queue.status.get()) {
+      LOG(ERROR, "Got no superstructure status packet.\n");
+    }
+    */
+
+    // TODO(comran): If everything looks good, start teleop.
+    /*if (superstructure_queue.status.get() && superstructure_queue.status->zeroed) {
+      if (waiting_for_zero_) {
+        LOG(INFO, "Zeroed! Starting teleop mode.\n");
+        waiting_for_zero_ = false;
+
+        // Set the initial goals to where we are now.
+        superstructure_goal_ = 0.0;
+      }
+    } else {
+      waiting_for_zero_ = true;
+    }*/
+
+    if (!waiting_for_zero_) {
+      if (!action_queue_.Running()) {
+        // TODO(comran): Send some goals.
+      }
+    }
+
+    if (action_queue_.Running()) {
+      // If we are running an action, update our goals to the current goals.
+      // TODO(comran): Do this for each superstructure queue.
+    }
+    action_queue_.Tick();
+    was_running_ = action_queue_.Running();
+  }
+
+ private:
+  void StartAuto() {
+    LOG(INFO, "Starting auto mode\n");
+    ::bot3::autonomous::autonomous.MakeWithBuilder().run_auto(true).Send();
+  }
+
+  void StopAuto() {
+    LOG(INFO, "Stopping auto mode\n");
+    ::bot3::autonomous::autonomous.MakeWithBuilder().run_auto(false).Send();
+  }
+
+  bool was_running_;
+
+  // If we're waiting for the subsystems to zero.
+  bool waiting_for_zero_ = true;
+
+  bool auto_running_ = false;
+
+  ::aos::common::actions::ActionQueue action_queue_;
+
+  ::aos::util::SimpleLogInterval no_drivetrain_status_ =
+      ::aos::util::SimpleLogInterval(::aos::time::Time::InSeconds(0.2), WARNING,
+                                     "no drivetrain status");
+};
+
+}  // namespace joysticks
+}  // namespace input
+}  // namespace bot3
+
+int main() {
+  ::aos::Init();
+  ::bot3::input::joysticks::Reader reader;
+  reader.Run();
+  ::aos::Cleanup();
+}
diff --git a/bot3/prime/build.sh b/bot3/prime/build.sh
new file mode 100755
index 0000000..9586590
--- /dev/null
+++ b/bot3/prime/build.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+cd $(dirname $0)
+
+exec ../../aos/build/build.py $0 prime bot3 prime.gyp "$@"
diff --git a/bot3/prime/prime.gyp b/bot3/prime/prime.gyp
new file mode 100644
index 0000000..f0a0e27
--- /dev/null
+++ b/bot3/prime/prime.gyp
@@ -0,0 +1,40 @@
+{
+  'targets': [
+    {
+      'target_name': 'All',
+      'type': 'none',
+      'dependencies': [
+        '<(AOS)/build/aos_all.gyp:Prime',
+
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop_test',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:position_sensor_sim_test',
+        '../control_loops/drivetrain/drivetrain.gyp:drivetrain_bot3',
+        '../control_loops/drivetrain/drivetrain.gyp:drivetrain_lib_test_bot3',
+        '../control_loops/drivetrain/drivetrain.gyp:replay_drivetrain_bot3',
+        '../control_loops/intake/intake.gyp:intake',
+        '../control_loops/intake/intake.gyp:intake_lib_test',
+        #'../autonomous/autonomous.gyp:auto_bot3',
+        '../bot3.gyp:joystick_reader_bot3',
+        '<(DEPTH)/frc971/zeroing/zeroing.gyp:zeroing_test',
+        #'../http_status/http_status.gyp:http_status',
+        '<(DEPTH)/frc971/control_loops/voltage_cap/voltage_cap.gyp:voltage_cap_test',
+        '../actors/actors.gyp:binaries',
+      ],
+      'copies': [
+        {
+          'destination': '<(rsync_dir)',
+          'files': [
+            'start_list.txt',
+          ],
+        },
+      ],
+      'conditions': [
+        ['ARCHITECTURE=="arm_frc"', {
+          'dependencies': [
+            '../wpilib/wpilib.gyp:wpilib_interface_bot3',
+          ],
+        }],
+      ],
+    },
+  ],
+}
diff --git a/bot3/prime/start_list.txt b/bot3/prime/start_list.txt
new file mode 100644
index 0000000..390595a
--- /dev/null
+++ b/bot3/prime/start_list.txt
@@ -0,0 +1,7 @@
+joystick_reader_bot3
+wpilib_interface_bot3
+binary_log_writer
+drivetrain_bot3
+auto_bot3
+drivetrain_action_bot3
+http_status_bot3
diff --git a/bot3/wpilib/wpilib.gyp b/bot3/wpilib/wpilib.gyp
new file mode 100644
index 0000000..311f6cd
--- /dev/null
+++ b/bot3/wpilib/wpilib.gyp
@@ -0,0 +1,36 @@
+{
+  'targets': [
+    {
+      'target_name': 'wpilib_interface_bot3',
+      'type': 'executable',
+      'sources': [
+        'wpilib_interface.cc'
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(AOS)/common/common.gyp:stl_mutex',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(EXTERNALS):WPILib',
+        '<(DEPTH)/bot3/control_loops/drivetrain/drivetrain.gyp:drivetrain_queue',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+        '<(AOS)/common/util/util.gyp:log_interval',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/common/logging/logging.gyp:queue_logging',
+        '<(AOS)/common/messages/messages.gyp:robot_state',
+        '<(AOS)/common/util/util.gyp:phased_loop',
+        '<(AOS)/common/messages/messages.gyp:robot_state',
+        '<(DEPTH)/frc971/wpilib/wpilib.gyp:hall_effect',
+        '<(DEPTH)/frc971/wpilib/wpilib.gyp:joystick_sender',
+        '<(DEPTH)/frc971/wpilib/wpilib.gyp:loop_output_handler',
+        '<(DEPTH)/frc971/wpilib/wpilib.gyp:buffered_pcm',
+        '<(DEPTH)/frc971/wpilib/wpilib.gyp:gyro_sender',
+        '<(DEPTH)/frc971/wpilib/wpilib.gyp:dma_edge_counting',
+        '<(DEPTH)/frc971/wpilib/wpilib.gyp:interrupt_edge_counting',
+        '<(DEPTH)/frc971/wpilib/wpilib.gyp:encoder_and_potentiometer',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:queues',
+        '<(DEPTH)/frc971/wpilib/wpilib.gyp:logging_queue',
+        '<(DEPTH)/bot3/control_loops/drivetrain/drivetrain.gyp:drivetrain_lib',
+      ],
+    },
+  ],
+}
diff --git a/bot3/wpilib/wpilib_interface.cc b/bot3/wpilib/wpilib_interface.cc
new file mode 100644
index 0000000..49be884
--- /dev/null
+++ b/bot3/wpilib/wpilib_interface.cc
@@ -0,0 +1,363 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <thread>
+#include <mutex>
+#include <functional>
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/logging/queue_logging.h"
+#include "aos/common/time.h"
+#include "aos/common/util/log_interval.h"
+#include "aos/common/util/phased_loop.h"
+#include "aos/common/util/wrapping_counter.h"
+#include "aos/common/stl_mutex.h"
+#include "aos/linux_code/init.h"
+#include "aos/common/messages/robot_state.q.h"
+
+#include "frc971/control_loops/control_loops.q.h"
+#include "bot3/control_loops/drivetrain/drivetrain.q.h"
+
+#include "frc971/wpilib/hall_effect.h"
+#include "frc971/wpilib/joystick_sender.h"
+#include "frc971/wpilib/loop_output_handler.h"
+#include "frc971/wpilib/buffered_solenoid.h"
+#include "frc971/wpilib/buffered_pcm.h"
+#include "frc971/wpilib/gyro_sender.h"
+#include "frc971/wpilib/dma_edge_counting.h"
+#include "frc971/wpilib/interrupt_edge_counting.h"
+#include "frc971/wpilib/encoder_and_potentiometer.h"
+#include "frc971/wpilib/logging.q.h"
+#include "bot3/control_loops/drivetrain/drivetrain.h"
+
+#include "Encoder.h"
+#include "Talon.h"
+#include "DriverStation.h"
+#include "AnalogInput.h"
+#include "Compressor.h"
+#include "Relay.h"
+#include "RobotBase.h"
+#include "dma.h"
+#include "ControllerPower.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+using ::aos::util::SimpleLogInterval;
+using ::bot3::control_loops::drivetrain_queue;
+using ::frc971::wpilib::DMAEncoderAndPotentiometer;
+using ::frc971::PotAndIndexPosition;
+using ::frc971::wpilib::InterruptEncoderAndPotentiometer;
+using ::frc971::wpilib::DMASynchronizer;
+using ::frc971::wpilib::BufferedPcm;
+using ::frc971::wpilib::LoopOutputHandler;
+using ::frc971::wpilib::JoystickSender;
+using ::frc971::wpilib::GyroSender;
+
+namespace bot3 {
+namespace wpilib {
+
+double drivetrain_translate(int32_t in) {
+  return static_cast<double>(in) /
+         (256.0 /*cpr*/ * 4.0 /*4x*/) *
+         ::bot3::control_loops::kDrivetrainEncoderRatio *
+         (4 /*wheel diameter*/ * 2.54 / 100.0 * M_PI);
+}
+
+// TODO(comran): Check/update the values below for the bot3.
+static const double kMaximumEncoderPulsesPerSecond =
+    19500.0 /* free speed RPM */ * 12.0 / 56.0 /* belt reduction */ /
+    60.0 /* seconds / minute */ * 256.0 /* CPR */ *
+    4.0 /* index pulse = 1/4 cycle */;
+
+class SensorReader {
+ public:
+  SensorReader() {
+    // Set it to filter out anything shorter than 1/4 of the minimum pulse width
+    // we should ever see.
+    filter_.SetPeriodNanoSeconds(
+        static_cast<int>(1 / 4.0 / kMaximumEncoderPulsesPerSecond * 1e9 + 0.5));
+  }
+
+  void set_left_encoder(::std::unique_ptr<Encoder> left_encoder) {
+    left_encoder_ = ::std::move(left_encoder);
+  }
+
+  void set_right_encoder(::std::unique_ptr<Encoder> right_encoder) {
+    right_encoder_ = ::std::move(right_encoder);
+  }
+
+  // All of the DMA-related set_* calls must be made before this, and it doesn't
+  // hurt to do all of them.
+  // TODO(comran): Do we still need dma?
+  void set_dma(::std::unique_ptr<DMA> dma) {
+    dma_synchronizer_.reset(new DMASynchronizer(::std::move(dma)));
+  }
+
+  void operator()() {
+    LOG(INFO, "In sensor reader thread\n");
+    ::aos::SetCurrentThreadName("SensorReader");
+
+    my_pid_ = getpid();
+    ds_ = DriverStation::GetInstance();
+
+    dma_synchronizer_->Start();
+    LOG(INFO, "Things are now started\n");
+
+    ::aos::SetCurrentThreadRealtimePriority(kPriority);
+    while (run_) {
+      ::aos::time::PhasedLoopXMS(5, 4000);
+      RunIteration();
+    }
+  }
+
+  void RunIteration() {
+    {
+      auto new_state = ::aos::robot_state.MakeMessage();
+
+      new_state->reader_pid = my_pid_;
+      new_state->outputs_enabled = ds_->IsSysActive();
+      new_state->browned_out = ds_->IsSysBrownedOut();
+
+      new_state->is_3v3_active = ControllerPower::GetEnabled3V3();
+      new_state->is_5v_active = ControllerPower::GetEnabled5V();
+      new_state->voltage_3v3 = ControllerPower::GetVoltage3V3();
+      new_state->voltage_5v = ControllerPower::GetVoltage5V();
+
+      new_state->voltage_roborio_in = ControllerPower::GetInputVoltage();
+      new_state->voltage_battery = ds_->GetBatteryVoltage();
+
+      LOG_STRUCT(DEBUG, "robot_state", *new_state);
+
+      new_state.Send();
+    }
+
+    {
+      auto drivetrain_message = drivetrain_queue.position.MakeMessage();
+      drivetrain_message->right_encoder =
+          -drivetrain_translate(right_encoder_->GetRaw());
+      drivetrain_message->left_encoder =
+          drivetrain_translate(left_encoder_->GetRaw());
+
+      drivetrain_message.Send();
+    }
+
+    dma_synchronizer_->RunIteration();
+  }
+
+  void Quit() { run_ = false; }
+
+ private:
+  static const int kPriority = 30;
+  static const int kInterruptPriority = 55;
+
+  int32_t my_pid_;
+  DriverStation *ds_;
+
+  void CopyPotAndIndexPosition(
+      const DMAEncoderAndPotentiometer &encoder, PotAndIndexPosition *position,
+      ::std::function<double(int32_t)> encoder_translate,
+      ::std::function<double(double)> potentiometer_translate, bool reverse,
+      double potentiometer_offset) {
+    const double multiplier = reverse ? -1.0 : 1.0;
+    position->encoder =
+        multiplier * encoder_translate(encoder.polled_encoder_value());
+    position->pot = multiplier * potentiometer_translate(
+                                     encoder.polled_potentiometer_voltage()) +
+                    potentiometer_offset;
+    position->latched_encoder =
+        multiplier * encoder_translate(encoder.last_encoder_value());
+    position->latched_pot =
+        multiplier *
+            potentiometer_translate(encoder.last_potentiometer_voltage()) +
+        potentiometer_offset;
+    position->index_pulses = encoder.index_posedge_count();
+  }
+
+  void CopyPotAndIndexPosition(
+      const InterruptEncoderAndPotentiometer &encoder,
+      PotAndIndexPosition *position,
+      ::std::function<double(int32_t)> encoder_translate,
+      ::std::function<double(double)> potentiometer_translate, bool reverse,
+      double potentiometer_offset) {
+    const double multiplier = reverse ? -1.0 : 1.0;
+    position->encoder =
+        multiplier * encoder_translate(encoder.encoder()->GetRaw());
+    position->pot = multiplier * potentiometer_translate(
+                                     encoder.potentiometer()->GetVoltage()) +
+                    potentiometer_offset;
+    position->latched_encoder =
+        multiplier * encoder_translate(encoder.last_encoder_value());
+    position->latched_pot =
+        multiplier *
+            potentiometer_translate(encoder.last_potentiometer_voltage()) +
+        potentiometer_offset;
+    position->index_pulses = encoder.index_posedge_count();
+  }
+
+  ::std::unique_ptr<DMASynchronizer> dma_synchronizer_;
+
+  ::std::unique_ptr<Encoder> left_encoder_;
+  ::std::unique_ptr<Encoder> right_encoder_;
+
+  ::std::atomic<bool> run_{true};
+  DigitalGlitchFilter filter_;
+};
+
+class SolenoidWriter {
+ public:
+  SolenoidWriter(const ::std::unique_ptr<::frc971::wpilib::BufferedPcm> &pcm)
+      : pcm_(pcm) {}
+
+  void set_pressure_switch(::std::unique_ptr<DigitalSource> pressure_switch) {
+    pressure_switch_ = ::std::move(pressure_switch);
+  }
+
+  void set_compressor_relay(::std::unique_ptr<Relay> compressor_relay) {
+    compressor_relay_ = ::std::move(compressor_relay);
+  }
+
+  void operator()() {
+    ::aos::SetCurrentThreadName("Solenoids");
+    ::aos::SetCurrentThreadRealtimePriority(30);
+
+    while (run_) {
+      ::aos::time::PhasedLoopXMS(20, 1000);
+
+      ::aos::joystick_state.FetchLatest();
+
+      {
+        ::frc971::wpilib::PneumaticsToLog to_log;
+        {
+          const bool compressor_on = !pressure_switch_->Get();
+          to_log.compressor_on = compressor_on;
+          if (compressor_on) {
+            compressor_relay_->Set(Relay::kForward);
+          } else {
+            compressor_relay_->Set(Relay::kOff);
+          }
+        }
+
+        pcm_->Flush();
+        to_log.read_solenoids = pcm_->GetAll();
+        LOG_STRUCT(DEBUG, "pneumatics info", to_log);
+      }
+    }
+  }
+
+  void Quit() { run_ = false; }
+
+ private:
+  const ::std::unique_ptr<BufferedPcm> &pcm_;
+  ::std::unique_ptr<DigitalSource> pressure_switch_;
+  ::std::unique_ptr<Relay> compressor_relay_;
+
+  ::std::atomic<bool> run_{true};
+};
+
+class DrivetrainWriter : public LoopOutputHandler {
+ public:
+  void set_left_drivetrain_talon(::std::unique_ptr<Talon> t) {
+    left_drivetrain_talon_ = ::std::move(t);
+  }
+
+  void set_right_drivetrain_talon(::std::unique_ptr<Talon> t) {
+    right_drivetrain_talon_ = ::std::move(t);
+  }
+
+ private:
+  virtual void Read() override {
+    ::bot3::control_loops::drivetrain_queue.output.FetchAnother();
+  }
+
+  virtual void Write() override {
+    auto &queue = ::bot3::control_loops::drivetrain_queue.output;
+    LOG_STRUCT(DEBUG, "will output", *queue);
+    left_drivetrain_talon_->Set(queue->left_voltage / 12.0);
+    right_drivetrain_talon_->Set(-queue->right_voltage / 12.0);
+  }
+
+  virtual void Stop() override {
+    LOG(WARNING, "drivetrain output too old\n");
+    left_drivetrain_talon_->Disable();
+    right_drivetrain_talon_->Disable();
+  }
+
+  ::std::unique_ptr<Talon> left_drivetrain_talon_;
+  ::std::unique_ptr<Talon> right_drivetrain_talon_;
+};
+
+// TODO(brian): Replace this with ::std::make_unique once all our toolchains
+// have support.
+template <class T, class... U>
+std::unique_ptr<T> make_unique(U &&... u) {
+  return std::unique_ptr<T>(new T(std::forward<U>(u)...));
+}
+
+class WPILibRobot : public RobotBase {
+ public:
+  ::std::unique_ptr<Encoder> encoder(int index) {
+    return make_unique<Encoder>(10 + index * 2, 11 + index * 2, false,
+                                Encoder::k4X);
+  }
+  virtual void StartCompetition() {
+    ::aos::InitNRT();
+    ::aos::SetCurrentThreadName("StartCompetition");
+
+    JoystickSender joystick_sender;
+    ::std::thread joystick_thread(::std::ref(joystick_sender));
+
+    SensorReader reader;
+    LOG(INFO, "Creating the reader\n");
+
+    // TODO(comran): Find talon/encoder numbers.
+    reader.set_left_encoder(encoder(2));
+    reader.set_right_encoder(encoder(3));
+    reader.set_dma(make_unique<DMA>());
+    ::std::thread reader_thread(::std::ref(reader));
+    GyroSender gyro_sender;
+    ::std::thread gyro_thread(::std::ref(gyro_sender));
+
+    DrivetrainWriter drivetrain_writer;
+    drivetrain_writer.set_left_drivetrain_talon(
+        ::std::unique_ptr<Talon>(new Talon(8)));
+    drivetrain_writer.set_right_drivetrain_talon(
+        ::std::unique_ptr<Talon>(new Talon(0)));
+    ::std::thread drivetrain_writer_thread(::std::ref(drivetrain_writer));
+
+    ::std::unique_ptr<::frc971::wpilib::BufferedPcm> pcm(
+        new ::frc971::wpilib::BufferedPcm());
+    SolenoidWriter solenoid_writer(pcm);
+    solenoid_writer.set_pressure_switch(make_unique<DigitalInput>(9));
+    solenoid_writer.set_compressor_relay(make_unique<Relay>(0));
+    ::std::thread solenoid_thread(::std::ref(solenoid_writer));
+
+    // Wait forever. Not much else to do...
+    PCHECK(select(0, nullptr, nullptr, nullptr, nullptr));
+
+    LOG(ERROR, "Exiting WPILibRobot\n");
+
+    joystick_sender.Quit();
+    joystick_thread.join();
+    reader.Quit();
+    reader_thread.join();
+    gyro_sender.Quit();
+    gyro_thread.join();
+
+    drivetrain_writer.Quit();
+    drivetrain_writer_thread.join();
+    solenoid_writer.Quit();
+    solenoid_thread.join();
+
+    ::aos::Cleanup();
+  }
+};
+
+}  // namespace wpilib
+}  // namespace bot3
+
+
+START_ROBOT_CLASS(::bot3::wpilib::WPILibRobot);
diff --git a/doc/building-the-code.txt b/doc/building-the-code.txt
new file mode 100644
index 0000000..c2676d1
--- /dev/null
+++ b/doc/building-the-code.txt
@@ -0,0 +1,43 @@
+This file contains instructions on how to set up a computer to build the code.
+
+[OS]
+Most of these instructions assume 64 bit Debian Wheezy.
+
+[Install Packages]
+First, you have to download and follow the directions in
+  <http://robotics.mvla.net/files/frc971/packages/frc971.list>.
+Then, run `apt-get install python3`.
+The build script will tell you what other packages to install when you run it.
+  It's pretty smart about not checking for things it doesn't need, so you might
+  want to build 'deploy all' to see everything it wants.
+  You will have to accept the
+    "WARNING: The following packages cannot be authenticated!" warning for
+    various packages downloaded from our package repository.
+  This works for amd64 Wheezy, no guarantees or support for anything else.
+
+[Running Locally]
+If you want to be able to run the realtime code on your development machine
+  without just disabling the realtime part (set the AOS_NO_REALTIME environment
+  variable), follow the directions in //aos/config/aos.conf.
+If you want to run the clang or gcc_4.8 amd64 code, add /opt/clang-3.5/lib64/ to
+  LD_LIBRARY_PATH. Using the system gcc-compiled versions should just work.
+
+[Compiling and Downloading]
+Run //frc971/*/build.sh.
+  Give it clean, tests, or deploy as a first argument to do something other
+    than just build.
+  Each action (build (the default), clean, tests, or deploy) has a different
+    default set of versions of the code it builds. You can change those by
+    passing another argument. Some popular ones are 'all' (build everything),
+        'clang-amd64-none' (the most basic one for local testing), and
+        'gcc_frc-arm-nodebug' (the one that gets downloaded). See its --help for
+        more details.
+
+[Communicating with the cRIO]
+Use netconsole (in the amd64 outputs directories) to communicate directly with
+  the cRIO.
+Use "reboot" from within netconsole.sh will reboot the cRIO.  ^C will
+  stop the netconsole program.  "version" will tell you the the
+  VxWorks and WIND versions and "help" will give you a list of VxWorks
+  commands that you can use.
+Make sure your computer is on the right subnet first.
diff --git a/doc/clang-3.5.ctl b/doc/clang-3.5.ctl
new file mode 100644
index 0000000..b20c52a
--- /dev/null
+++ b/doc/clang-3.5.ctl
@@ -0,0 +1,13 @@
+Source: llvm-toolchain-snapshot
+Section: misc
+Priority: optional
+Homepage: http://www.llvm.org/
+Standards-Version: 3.9.2
+Package: clang-3.5
+Version: 1:3.5~svn201561
+Maintainer: FRC Team 971 <spartanrobotics.org>
+Depends: libbsd0, libc6, libedit2, libncurses5, libpython2.7, libtinfo5, zlib1g
+Architecture: amd64
+Description: Clang 3.5 with included GCC 4.8 so it actually works.
+ This is just 1 massive package with a newer clang that doesn't conflict with
+ other stuff like the official clang-3.5 package does.
diff --git a/doc/codereview-directions.txt b/doc/codereview-directions.txt
new file mode 100644
index 0000000..4610c95
--- /dev/null
+++ b/doc/codereview-directions.txt
@@ -0,0 +1,56 @@
+This file has some general information about how 971 does code reviews.
+
+We use Rietveld (<https://code.google.com/p/rietveld>) running in an app engine
+  app of ours. It is at <http://971code.appspot.com/>.
+
+[General Procedure]
+We try to code review all code before it gets checked in to svn. Code reviews
+  are also sometimes useful for getting feedback about documentation etc.
+First, somebody starts a code review and sends out emails to people asking them
+  to look. Then, other people look at it and make suggestions (in the form of
+  comments). The person who started the review (the owner of it) looks at the
+  comments and responds to them and/or changes their code and uploads new
+  versions for everybody to look at. Once all of the reviewers approve the code,
+  the owner checks it in and closes the code review (issue).
+
+[Reviewing]
+This is the section for people who have received emails about reviewing code
+  should look.
+The email that you receive will have a link to the issue (like
+  <http://971code.appspot.com/82001/>). Click on it to go to the issue page.
+  The most useful form of diff are the "Side-by-side diffs". Click the "View"
+  link in that column next to each file to look at it. After the first set of
+  comments, the "Delta from patch set" links are also helpful to see what got
+  changed so that you don't have to look at everything again. While looking at
+  a diff, double-click on any line of code to leave a comment there. You can
+  also reply to existing comments. The web interface sometimes hides comments
+  right after you create/edit them. Refresh the page to fix that (don't just do
+  it again, or you'll end up with 2 identical comments). Once you are done
+  looking at all of the files and making comments, click the
+  "Publish+Mail Comments" link (at the top of each diff or on the left of the
+  main issue page) to send out your comments. You can also put general notes in
+  the "Message" box. If you think that it looks good, then put "LGTM" at the top
+  of the message. The owner of the code review will keep looking at your
+  comments, making changes, and sending out more messages until it's finished.
+
+[Starting a Review]
+To begin, log in to <http://971code.appspot.com/> then click the "Create Issue"
+  link. Download the "upload.py" script and use that, not the web form, for
+  uploading a diff. (The web form has too many problems and is unusable with
+  git.) The script will find svn, git, or hg diffs in your current directory. If
+  you want the diff to cover back to an earlier change number, use the --rev
+  arg.
+
+  You don't need to give it a -s (--server) arg since the right default server
+  address is in the script. You can give it a -e (--email) arg with your gmail
+  address or let it ask you. (If you use 2-factor login for gmail, which I
+  recommend, you'll need to create an application-specific password instead of
+  using your regular password + OTP code.)
+
+  After it uploads, you can review the diffs on the web page. You can change
+  code and upload another diff. When ready, use the web UI to send the code
+  review email. Don't delete the old diffs; they are helpful for reviewers to
+  figure out what changed.
+
+For more information about using Rietveld, see
+  <https://code.google.com/p/rietveld/wiki/CodeReviewHelp>.
diff --git a/doc/environment_variables b/doc/environment_variables
new file mode 100644
index 0000000..98d51bc
--- /dev/null
+++ b/doc/environment_variables
@@ -0,0 +1,4 @@
+A list of environment variables useful for running the code on not-robots:
+  AOS_NO_REALTIME
+  AOS_SHM_NAME
+  AOS_TEAM_NUMBER
diff --git a/doc/git-setup.txt b/doc/git-setup.txt
new file mode 100644
index 0000000..6fc52b5
--- /dev/null
+++ b/doc/git-setup.txt
@@ -0,0 +1,58 @@
+Some of us are using git for managing quickly changing code. This file has
+notes for setting that up.
+
+[Cloning]
+`git clone \
+    ssh://USERNAME@robotics.mvla.net/www/https/git/frc971/SOMEBODY/2014.git`
+  where USERNAME is your login on the server and SOMEBODY is whoever's git
+  repo you want to clone
+If you don't have a login on the server, then cloning
+  https://robotics.mvla.net/git/frc971/somebody/2014.git instead should work
+  (with your SVN username and password). However, that form of URL is read-
+  only. In order for this to work, you have to either set the environment
+  variable GIT_SSL_NO_VERIFY to 1 or set the git option http.sslverify to false.
+  If you get an error like the one below, install a newer version of git.
+    Unable to find 8fcd87533b76ca5b4b83fb6031ddf0de5e03eb57 under https://robotics.mvla.net/git/frc971/brian/2013.git
+    Cannot obtain needed object 8fcd87533b76ca5b4b83fb6031ddf0de5e03eb57
+    error: Fetch failed.
+  I get this error sometimes with version 1.7.2.5 but not with version 1.7.10.4.
+
+[Adding Other People's Repositories]
+`git remote add SOMEBODY \
+    ssh://USERNAME@robotics.mvla.net/www/https/git/frc971/SOMEBODY/2014.git`
+  where USERNAME is your login on the server and SOMEBODY is another person's
+  git repository
+The https:// URL discussed above in [Cloning] will work too.
+
+[Working with Other People's Repositories]
+`git fetch SOMEBODY` will pull their changes, and then you can rebase on top of
+  them, merge them in, etc.
+`git push --mirror` will push all of your local branches so that everybody else
+  can see them. (This is the default if the configuration option remote.<remote>.mirror is set.)
+  However, you can not do that with an https:// URL.
+
+[Synchronizing with SVN]
+Somebody should occasionally copy all of the files from git (bbb_cape,
+  frc971, and aos) into svn.
+
+[Server Setup]
+You need a place to store your files. You will need an adminstrator to
+  create a folder for you in /www/https/git/frc971 (on the server) with the
+  correct permissions and group.
+
+[Repository Setup]
+To create a git repository on the server,
+  `git init --bare 2014.git` in your folder (ie
+    "/www/https/git/frc971/USERNAME/"), `cd 2014.git`,
+    `git config --local gc.pruneExpire never`, `rm -r objects/`, and then
+    `ln -s /www/https/git/frc971/objects/2014 objects`. That will set you up
+    with a repository in the standard location and make it so all of the objects
+    in it won't be duplicated with the identical ones in everybody else's
+    repositories.
+In order for https:// access to work, you have to make sure to rename
+  .git/hooks/post-update.sample to .git/hooks/post-update (and then run
+  `git update-server-info` if you're not going to push immediately).
+
+To learn more about git, see git(1) (`man git` or
+  <http://manpages.debian.net/cgi-bin/man.cgi?query=git>) (especially the NOTES
+  section).
diff --git a/frc971/analysis/analysis.py b/frc971/analysis/analysis.py
new file mode 100755
index 0000000..e477bdd
--- /dev/null
+++ b/frc971/analysis/analysis.py
@@ -0,0 +1,377 @@
+#!/usr/bin/python3
+import matplotlib
+from matplotlib import pylab
+from matplotlib.font_manager import FontProperties
+
+class Dataset(object):
+  def __init__(self):
+    self.time = []
+    self.data = []
+
+  def Add(self, time, data):
+    self.time.append(time)
+    self.data.append(data)
+
+
+class Plotter(object):
+  def __init__(self):
+    self.signal = dict()
+
+  def Add(self, binary, struct_instance_name, *data_search_path):
+    """
+    Specifies a specific piece of data to plot
+
+    Args:
+      binary: str, The name of the executable that generated the log.
+      struct_instance_name: str, The name of the struct instance whose data
+                            contents should be plotted.
+      data_search_path: [str], The path into the struct of the exact piece of
+                        data to plot.
+
+    Returns:
+      None
+    """
+    self.signal[(binary, struct_instance_name, data_search_path)] = Dataset()
+
+  def HandleLine(self, line):
+    """
+    Parses a line from a log file and adds the data to the plot data.
+
+    Args:
+      line: str, The line from the log file to parse
+
+    Returns:
+      None
+    """
+    pline = ParseLine(line)
+    for key in self.signal:
+      value = self.signal[key]
+      binary = key[0]
+      struct_instance_name = key[1]
+      data_search_path = key[2]
+      boolean_multiplier = None
+
+      # If the plot definition line ends with a "-b X" where X is a number then
+      # that number gets drawn when the value is True. Zero gets drawn when the
+      # value is False.
+      if len(data_search_path) >= 2 and data_search_path[-2] == '-b':
+        boolean_multiplier = float(data_search_path[-1])
+        data_search_path = data_search_path[:-2]
+
+      # Make sure that we're looking at the right binary structure instance.
+      if binary == pline.name:
+        if pline.msg.startswith(struct_instance_name + ': '):
+          # Parse the structure and traverse it as specified in
+          # `data_search_path`. This lets the user access very deeply nested
+          # structures.
+          _, _, data = pline.ParseStruct()
+          for path in data_search_path:
+            data = data[path]
+
+          if boolean_multiplier is not None:
+            if data == 'T':
+              value.Add(pline.time, boolean_multiplier)
+            else:
+              value.Add(pline.time, 0)
+          else:
+            value.Add(pline.time, data)
+
+  def Plot(self, no_binary_in_legend):
+    """
+    Plots all the data after it's parsed.
+
+    This should only be called after `HandleFile` has been called so that there
+    is actual data to plot.
+    """
+    for key in self.signal:
+      value = self.signal[key]
+
+      # Create a legend label using the binary name (optional), the structure
+      # name and the data search path.
+      label = key[1] + '.' + '.'.join(key[2])
+      if not no_binary_in_legend:
+        label = key[0] + ' ' + label
+
+      pylab.plot(value.time, value.data, label=label)
+
+    # Set legend font size to small and move it to the top center.
+    fontP = FontProperties()
+    fontP.set_size('small')
+    pylab.legend(bbox_to_anchor=(0.5, 1.05), prop=fontP)
+
+    pylab.show()
+
+  def PlotFile(self, f, no_binary_in_legend=False):
+    """
+    Parses and plots all the data.
+
+    Args:
+      f: str, The filename of the log whose data to parse and plot.
+
+    Returns:
+      None
+    """
+    self.HandleFile(f)
+    self.Plot(no_binary_in_legend)
+
+  def HandleFile(self, f):
+    """
+    Parses the specified log file.
+
+    Args:
+      f: str, The filename of the log whose data to parse.
+
+    Returns:
+      None
+    """
+    with open(f, 'r') as fd:
+      for line in fd:
+        self.HandleLine(line)
+
+
+class LogEntry:
+  """This class provides a way to parse log entries."""
+
+  def __init__(self, line):
+    """Creates a LogEntry from a line."""
+    name_index = line.find('(')
+    self.name = line[0:name_index]
+
+    pid_index = line.find(')', name_index + 1)
+    self.pid = int(line[name_index + 1:pid_index])
+
+    msg_index_index = line.find(')', pid_index + 1)
+    self.msg_index = int(line[pid_index + 2:msg_index_index])
+
+    level_index = line.find(' ', msg_index_index + 3)
+    self.level = line[msg_index_index + 3:level_index]
+
+    time_index_start = line.find(' at ', level_index) + 4
+    time_index_end = line.find('s:', level_index)
+    self.time = float(line[time_index_start:time_index_end])
+
+    filename_end = line.find(':', time_index_end + 3)
+    self.filename = line[time_index_end + 3:filename_end]
+
+    linenumber_end = line.find(':', filename_end + 2)
+    self.linenumber = int(line[filename_end + 2:linenumber_end])
+
+    self.msg = line[linenumber_end+2:]
+
+  def __str__(self):
+    """Formats the data cleanly."""
+    return '%s(%d)(%d): %s at %fs: %s: %d: %s' % (self.name, self.pid, self.msg_index, self.level, self.time, self.filename, self.linenumber, self.msg)
+
+  def __JsonizeTokenArray(self, sub_array, tokens, token_index):
+    """Parses an array from the provided tokens.
+
+    Args:
+      sub_array: list, The list to stick the elements in.
+      tokens: list of strings, The list with all the tokens in it.
+      token_index: int, Where to start in the token list.
+
+    Returns:
+      int, The last token used.
+    """
+    # Make sure the data starts with a '['
+    if tokens[token_index] != '[':
+      print(tokens)
+      print('Expected [ at beginning, found', tokens[token_index + 1])
+      return None
+
+    # Eat the '['
+    token_index += 1
+
+    # Loop through the tokens.
+    while token_index < len(tokens):
+      if tokens[token_index + 1] == ',':
+        # Next item is a comma, so we should just add the element.
+        sub_array.append(tokens[token_index])
+        token_index += 2
+      elif tokens[token_index + 1] == ']':
+        # Next item is a ']', so we should just add the element and finish.
+        sub_array.append(tokens[token_index])
+        token_index += 1
+        return token_index
+      else:
+        # Otherwise, it must be a sub-message.
+        sub_json = dict()
+        token_index = self.JsonizeTokens(sub_json, tokens, token_index + 1)
+        sub_array.append(sub_json)
+        if tokens[token_index] == ',':
+          # Handle there either being another data element.
+          token_index += 1
+        elif tokens[token_index] == ']':
+          # Handle the end of the array.
+          return token_index
+        else:
+          print('Unexpected ', tokens[token_index])
+          return None
+
+    print('Unexpected end')
+    return None
+
+  def JsonizeTokens(self, json, tokens, token_index):
+    """Creates a json-like dictionary from the provided tokens.
+
+    Args:
+      json: dict, The dict to stick the elements in.
+      tokens: list of strings, The list with all the tokens in it.
+      token_index: int, Where to start in the token list.
+
+    Returns:
+      int, The last token used.
+    """
+    # Check that the message starts with a {
+    if tokens[token_index] != '{':
+      print(tokens)
+      print('Expected { at beginning, found', tokens[token_index])
+      return None
+
+    # Eat the {
+    token_index += 1
+
+    # States and state variable for parsing elements.
+    STATE_INIT = 'init'
+    STATE_HAS_NAME = 'name'
+    STATE_HAS_COLON = 'colon'
+    STATE_EXPECTING_SUBMSG = 'submsg'
+    STATE_EXPECTING_COMMA = 'comma'
+    parser_state = STATE_INIT
+
+    while token_index < len(tokens):
+      if tokens[token_index] == '}':
+        # Finish if there is a }
+        return token_index + 1
+      elif tokens[token_index] == '{':
+        if parser_state != STATE_EXPECTING_SUBMSG:
+          print(tokens)
+          print(parser_state)
+          print('Bad input, was not expecting {')
+          return None
+        # Found a submessage, parse it.
+        sub_json = dict()
+        token_index = self.JsonizeTokens(sub_json, tokens, token_index)
+        json[token_name] = sub_json
+        parser_state = STATE_EXPECTING_COMMA
+      else:
+        if parser_state == STATE_INIT:
+          # This token is the name.
+          token_name = tokens[token_index]
+          parser_state = STATE_HAS_NAME
+        elif parser_state == STATE_HAS_NAME:
+          if tokens[token_index] != ':':
+            print(tokens)
+            print(parser_state)
+            print('Bad input, found', tokens[token_index], 'expected :')
+            return None
+          # After a name, comes a :
+          parser_state = STATE_HAS_COLON
+        elif parser_state == STATE_HAS_COLON:
+          # After the colon, figure out what is next.
+          if tokens[token_index] == '[':
+            # Found a sub-array!
+            sub_array = []
+            token_index = self.__JsonizeTokenArray(sub_array, tokens, token_index)
+            json[token_name] = sub_array
+            parser_state = STATE_EXPECTING_COMMA
+          elif tokens[token_index + 1] == '{':
+            # Found a sub-message, trigger parsing it.
+            parser_state = STATE_EXPECTING_SUBMSG
+          else:
+            # This is just an element, move on.
+            json[token_name] = tokens[token_index]
+            parser_state = STATE_EXPECTING_COMMA
+        elif parser_state == STATE_EXPECTING_COMMA:
+          # Complain if there isn't a comma here.
+          if tokens[token_index] != ',':
+            print(tokens)
+            print(parser_state)
+            print('Bad input, found', tokens[token_index], 'expected ,')
+            return None
+          parser_state = STATE_INIT
+        else:
+          print('Bad parser state')
+          return None
+        token_index += 1
+
+    print('Unexpected end')
+    return None
+
+  def ParseStruct(self):
+    """Parses the message as a structure.
+
+    Returns:
+      struct_name, struct_type, json dict.
+    """
+    struct_name_index = self.msg.find(':')
+    struct_name = self.msg[0:struct_name_index]
+
+    struct_body = self.msg[struct_name_index+2:]
+    tokens = []
+    this_token = ''
+    # For the various deliminators, append what we have found so far to the
+    # list and the token.
+    for char in struct_body:
+      if char == '{':
+        if this_token:
+          tokens.append(this_token)
+          this_token = ''
+        tokens.append('{')
+      elif char == '}':
+        if this_token:
+          tokens.append(this_token)
+          this_token = ''
+        tokens.append('}')
+      elif char == '[':
+        if this_token:
+          tokens.append(this_token)
+          this_token = ''
+        tokens.append('[')
+      elif char == ']':
+        if this_token:
+          tokens.append(this_token)
+          this_token = ''
+        tokens.append(']')
+      elif char == ':':
+        if this_token:
+          tokens.append(this_token)
+          this_token = ''
+        tokens.append(':')
+      elif char == ',':
+        if this_token:
+          tokens.append(this_token)
+          this_token = ''
+        tokens.append(',')
+      elif char == ' ':
+        if this_token:
+          tokens.append(this_token)
+          this_token = ''
+      else:
+        this_token += char
+    if this_token:
+      tokens.append(this_token)
+
+    struct_type = tokens[0]
+    json = dict()
+    # Now that we have tokens, parse them.
+    self.JsonizeTokens(json, tokens, 1)
+
+    return (struct_name, struct_type, json)
+
+
+def ParseLine(line):
+  return LogEntry(line)
+
+if __name__ == '__main__':
+  print('motor_writer(2240)(07421): DEBUG   at 0000000819.99620s: ../../frc971/output/motor_writer.cc: 105: sending: .aos.controls.OutputCheck{pwm_value:221, pulse_length:2.233333}')
+  line = ParseLine('motor_writer(2240)(07421): DEBUG   at 0000000819.99620s: ../../frc971/output/motor_writer.cc: 105: sending: .aos.controls.OutputCheck{pwm_value:221, pulse_length:2.233333}')
+  if '.aos.controls.OutputCheck' in line.msg:
+    print(line)
+    print(line.ParseStruct())
+
+  line = ParseLine('claw(2263)(19404): DEBUG   at 0000000820.00000s: ../../aos/common/controls/control_loop-tmpl.h: 104: position: .frc971.control_loops.ClawGroup.Position{top:.frc971.control_loops.HalfClawPosition{position:1.672153, front:.frc971.HallEffectStruct{current:f, posedge_count:0, negedge_count:52}, calibration:.frc971.HallEffectStruct{current:f, posedge_count:6, negedge_count:13}, back:.frc971.HallEffectStruct{current:f, posedge_count:0, negedge_count:62}, posedge_value:0.642681, negedge_value:0.922207}, bottom:.frc971.control_loops.HalfClawPosition{position:1.353539, front:.frc971.HallEffectStruct{current:f, posedge_count:2, negedge_count:150}, calibration:.frc971.HallEffectStruct{current:f, posedge_count:8, negedge_count:18}, back:.frc971.HallEffectStruct{current:f, posedge_count:0, negedge_count:6}, posedge_value:0.434514, negedge_value:0.759491}}')
+  print(line.ParseStruct())
+
+  line = ParseLine('joystick_proxy(2255)(39560): DEBUG   at 0000000820.00730s: ../../aos/prime/input/joystick_input.cc: 61: sending: .aos.RobotState{joysticks:[.aos.Joystick{buttons:0, axis:[0.000000, 1.000000, 1.000000, 0.000000]}, .aos.Joystick{buttons:0, axis:[-0.401575, 1.000000, -1.007874, 0.000000]}, .aos.Joystick{buttons:0, axis:[0.007874, 0.000000, 1.000000, -1.007874]}, .aos.Joystick{buttons:0, axis:[0.000000, 0.000000, 0.000000, 0.000000]}], test_mode:f, fms_attached:f, enabled:T, autonomous:f, team_id:971, fake:f}')
+  print(line.ParseStruct())
diff --git a/frc971/analysis/plot_action.py b/frc971/analysis/plot_action.py
new file mode 100755
index 0000000..2f50ffd
--- /dev/null
+++ b/frc971/analysis/plot_action.py
@@ -0,0 +1,88 @@
+#!/usr/bin/python3
+
+import sys
+import numpy
+import analysis
+import argparse
+
+def ReadPlotDefinitions(filename):
+  """
+  Read a file with plotting definitions.
+
+  A plotting definition is a single line that defines what data to search for
+  in order to plot it. The following in a file would duplicate the default
+  behaviour:
+
+    fridge goal height
+    fridge goal angle
+    fridge goal velocity
+    fridge goal angular_velocity
+    fridge output left_arm
+    fridge output right_arm
+    fridge output left_elevator
+    fridge output right_elevator
+
+  Lines are ignored if they start with a hash mark (i.e. '#').
+
+  Lines that end with a "-b X" where X is a number then it designates that line
+  as plotting a boolean value. X is the value plotted when the boolean is true.
+  When the boolean is false then the values is plotted as zero. For example,
+  the following boolean value is drawn to toggle between 2.0 and 0 when the
+  boolean is True and False, respectively:
+
+    fridge status zeroed -b 2.0
+
+  Args:
+    filename: The name of the file to read the definitions from.
+
+  Returns:
+    [[str]]: The definitions in the specified file.
+  """
+  defs = []
+  with open(filename) as fd:
+    for line in fd:
+      raw_defs = line.split()
+
+      # Only add to the list of definitions if the line's not empty and it
+      # doesn't start with a hash.
+      if raw_defs and not raw_defs[0].startswith('#'):
+        defs.append(raw_defs)
+
+  return defs
+
+def main():
+  # Parse all command line arguments.
+  arg_parser = argparse.ArgumentParser(description='Log Plotter')
+  arg_parser.add_argument('log_file', metavar='LOG_FILE', type=str, \
+      help='The file from which to read logs and plot.')
+  arg_parser.add_argument('--plot-defs', '-p', action='store', type=str, \
+      help='Read the items to plot from this file.')
+  arg_parser.add_argument('--no-binary', '-n', action='store_true', \
+      help='Don\'t print the binary name in the legend.')
+
+  args = arg_parser.parse_args(sys.argv[1:])
+
+  p = analysis.Plotter()
+
+  # If the user defines the list of data to plot in a file, read it from there.
+  if args.plot_defs:
+    defs = ReadPlotDefinitions(args.plot_defs)
+    for definition in defs:
+      p.Add(definition[0], definition[1], *definition[2:])
+
+  # Otherwise use a pre-defined set of data to plot.
+  else:
+    p.Add('fridge', 'goal', 'height')
+    p.Add('fridge', 'goal', 'angle')
+    p.Add('fridge', 'goal', 'velocity')
+    p.Add('fridge', 'goal', 'angular_velocity')
+
+    p.Add('fridge', 'output', 'left_arm')
+    p.Add('fridge', 'output', 'right_arm')
+    p.Add('fridge', 'output', 'left_elevator')
+    p.Add('fridge', 'output', 'right_elevator')
+
+  p.PlotFile(args.log_file, args.no_binary)
+
+if __name__ == '__main__':
+  main()
diff --git a/frc971/autonomous/auto.q b/frc971/autonomous/auto.q
new file mode 100644
index 0000000..5791034
--- /dev/null
+++ b/frc971/autonomous/auto.q
@@ -0,0 +1,8 @@
+package frc971.autonomous;
+
+message AutoControl {
+  // True if auto mode should be running, false otherwise.
+  bool run_auto;
+};
+
+queue AutoControl autonomous;
diff --git a/frc971/autonomous/autonomous.gyp b/frc971/autonomous/autonomous.gyp
new file mode 100644
index 0000000..e36a532
--- /dev/null
+++ b/frc971/autonomous/autonomous.gyp
@@ -0,0 +1,13 @@
+{
+  'targets': [
+    {
+      'target_name': 'auto_queue',
+      'type': 'static_library',
+      'sources': ['auto.q'],
+      'variables': {
+        'header_path': 'frc971/autonomous',
+      },
+      'includes': ['../../aos/build/queues.gypi'],
+    },
+  ],
+}
diff --git a/frc971/constants.h b/frc971/constants.h
new file mode 100644
index 0000000..890c63c
--- /dev/null
+++ b/frc971/constants.h
@@ -0,0 +1,22 @@
+#ifndef FRC971_CONSTANTS_H_
+#define FRC971_CONSTANTS_H_
+
+namespace frc971 {
+namespace constants {
+
+struct ZeroingConstants {
+  // The number of samples in the moving average filter.
+  int average_filter_size;
+  // The difference in scaled units between two index pulses.
+  double index_difference;
+  // The absolute position in scaled units of one of the index pulses.
+  double measured_index_position;
+  // Value between 0 and 1 which determines a fraction of the index_diff
+  // you want to use.
+  double allowable_encoder_error;
+};
+
+}  // namespace constants
+}  // namespace frc971
+
+#endif  // FRC971_CONSTANTS_H_
diff --git a/frc971/control_loops/coerce_goal.cc b/frc971/control_loops/coerce_goal.cc
new file mode 100644
index 0000000..6482cc7
--- /dev/null
+++ b/frc971/control_loops/coerce_goal.cc
@@ -0,0 +1,63 @@
+#include "frc971/control_loops/coerce_goal.h"
+
+#include "Eigen/Dense"
+
+#include "aos/common/controls/polytope.h"
+
+namespace frc971 {
+namespace control_loops {
+
+Eigen::Matrix<double, 2, 1> DoCoerceGoal(const aos::controls::HPolytope<2> &region,
+                                         const Eigen::Matrix<double, 1, 2> &K,
+                                         double w,
+                                         const Eigen::Matrix<double, 2, 1> &R,
+                                         bool *is_inside) {
+  if (region.IsInside(R)) {
+    if (is_inside) *is_inside = true;
+    return R;
+  }
+  Eigen::Matrix<double, 2, 1> parallel_vector;
+  Eigen::Matrix<double, 2, 1> perpendicular_vector;
+  perpendicular_vector = K.transpose().normalized();
+  parallel_vector << perpendicular_vector(1, 0), -perpendicular_vector(0, 0);
+
+  aos::controls::HPolytope<1> t_poly(
+      region.H() * parallel_vector,
+      region.k() - region.H() * perpendicular_vector * w);
+
+  Eigen::Matrix<double, 1, Eigen::Dynamic> vertices = t_poly.Vertices();
+  if (vertices.innerSize() > 0) {
+    double min_distance_sqr = 0;
+    Eigen::Matrix<double, 2, 1> closest_point;
+    for (int i = 0; i < vertices.innerSize(); i++) {
+      Eigen::Matrix<double, 2, 1> point;
+      point = parallel_vector * vertices(0, i) + perpendicular_vector * w;
+      const double length = (R - point).squaredNorm();
+      if (i == 0 || length < min_distance_sqr) {
+        closest_point = point;
+        min_distance_sqr = length;
+      }
+    }
+    if (is_inside) *is_inside = true;
+    return closest_point;
+  } else {
+    Eigen::Matrix<double, 2, Eigen::Dynamic> region_vertices =
+        region.Vertices();
+    double min_distance = INFINITY;
+    int closest_i = 0;
+    for (int i = 0; i < region_vertices.outerSize(); i++) {
+      const double length = ::std::abs(
+          (perpendicular_vector.transpose() * (region_vertices.col(i)))(0, 0));
+      if (i == 0 || length < min_distance) {
+        closest_i = i;
+        min_distance = length;
+      }
+    }
+    if (is_inside) *is_inside = false;
+    return (Eigen::Matrix<double, 2, 1>() << region_vertices(0, closest_i),
+            region_vertices(1, closest_i)).finished();
+  }
+}
+
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/frc971/control_loops/coerce_goal.h b/frc971/control_loops/coerce_goal.h
new file mode 100644
index 0000000..3933050
--- /dev/null
+++ b/frc971/control_loops/coerce_goal.h
@@ -0,0 +1,32 @@
+#ifndef FRC971_CONTROL_LOOPS_COERCE_GOAL_H_
+#define FRC971_CONTROL_LOOPS_COERCE_GOAL_H_
+
+#include "Eigen/Dense"
+
+#include "aos/common/controls/polytope.h"
+
+namespace frc971 {
+namespace control_loops {
+
+Eigen::Matrix<double, 2, 1> DoCoerceGoal(const aos::controls::HPolytope<2> &region,
+                                         const Eigen::Matrix<double, 1, 2> &K,
+                                         double w,
+                                         const Eigen::Matrix<double, 2, 1> &R,
+                                         bool *is_inside);
+
+// Intersects a line with a region, and finds the closest point to R.
+// Finds a point that is closest to R inside the region, and on the line
+// defined by K X = w.  If it is not possible to find a point on the line,
+// finds a point that is inside the region and closest to the line.
+static inline Eigen::Matrix<double, 2, 1>
+    CoerceGoal(const aos::controls::HPolytope<2> &region,
+               const Eigen::Matrix<double, 1, 2> &K,
+               double w,
+               const Eigen::Matrix<double, 2, 1> &R) {
+  return DoCoerceGoal(region, K, w, R, nullptr);
+}
+
+}  // namespace control_loops
+}  // namespace frc971
+
+#endif  // FRC971_CONTROL_LOOPS_COERCE_GOAL_H_
diff --git a/frc971/control_loops/control_loops.gyp b/frc971/control_loops/control_loops.gyp
new file mode 100644
index 0000000..ff62bac
--- /dev/null
+++ b/frc971/control_loops/control_loops.gyp
@@ -0,0 +1,112 @@
+{
+  'targets': [
+    {
+      'target_name': 'team_number_test_environment',
+      'type': 'static_library',
+      'sources': [
+        'team_number_test_environment.cc'
+      ],
+      'dependencies': [
+        '<(AOS)/common/network/network.gyp:team_number',
+        '<(EXTERNALS):gtest',
+      ],
+      'export_dependent_settings': [
+        '<(EXTERNALS):gtest',
+      ],
+    },
+    {
+      'target_name': 'state_feedback_loop_test',
+      'type': 'executable',
+      'sources': [
+        'state_feedback_loop_test.cc',
+      ],
+      'dependencies': [
+        'state_feedback_loop',
+        '<(EXTERNALS):gtest',
+      ],
+    },
+    {
+      'target_name': 'hall_effect_tracker',
+      'type': 'static_library',
+      'sources': [
+        #'hall_effect_tracker.h',
+      ],
+      'dependencies': [
+        'queues',
+      ],
+      'export_dependent_settings': [
+        'queues',
+      ],
+    },
+    {
+      'target_name': 'queues',
+      'type': 'static_library',
+      'sources': [
+        'control_loops.q',
+      ],
+      'variables': {
+        'header_path': 'frc971/control_loops',
+      },
+      'includes': ['../../aos/build/queues.gypi'],
+    },
+    {
+      'target_name': 'position_sensor_sim_test',
+      'type': 'executable',
+      'sources': [
+        'position_sensor_sim_test.cc',
+      ],
+      'dependencies': [
+        'queues',
+        'position_sensor_sim',
+        '<(EXTERNALS):gtest',
+        '<(AOS)/build/aos.gyp:logging',
+      ],
+    },
+    {
+      'target_name': 'position_sensor_sim',
+      'type': 'static_library',
+      'sources': [
+        'position_sensor_sim.cc',
+      ],
+      'dependencies': [
+        'queues',
+        'gaussian_noise',
+      ],
+    },
+    {
+      'target_name': 'gaussian_noise',
+      'type': 'static_library',
+      'sources': [
+        'gaussian_noise.cc',
+      ],
+    },
+    {
+      'target_name': 'coerce_goal',
+      'type': 'static_library',
+      'sources': [
+        'coerce_goal.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):eigen',
+        '<(AOS)/common/controls/controls.gyp:polytope',
+      ],
+      'export_dependent_settings': [
+        '<(EXTERNALS):eigen',
+        '<(AOS)/common/controls/controls.gyp:polytope',
+      ],
+    },
+    {
+      'target_name': 'state_feedback_loop',
+      'type': 'static_library',
+      'sources': [
+        #'state_feedback_loop.h'
+      ],
+      'dependencies': [
+        '<(EXTERNALS):eigen',
+      ],
+      'export_dependent_settings': [
+        '<(EXTERNALS):eigen',
+      ],
+    },
+  ],
+}
diff --git a/frc971/control_loops/control_loops.q b/frc971/control_loops/control_loops.q
new file mode 100644
index 0000000..37a6420
--- /dev/null
+++ b/frc971/control_loops/control_loops.q
@@ -0,0 +1,62 @@
+package frc971;
+
+// Represents all of the data for a single potentiometer and indexed encoder
+// pair.
+// The units on all of the positions are the same.
+// All encoder values are relative to where the encoder was at some arbitrary
+// point in time. All potentiometer values are relative to some arbitrary 0
+// position which varies with each robot.
+struct PotAndIndexPosition {
+  // Current position read from the encoder.
+  double encoder;
+  // Current position read from the potentiometer.
+  double pot;
+
+  // Position from the encoder latched at the last index pulse.
+  double latched_encoder;
+  // Position from the potentiometer latched at the last index pulse.
+  double latched_pot;
+
+  // How many index pulses we've seen since startup. Starts at 0.
+  uint32_t index_pulses;
+};
+
+// The internal state of a zeroing estimator.
+struct EstimatorState {
+  // If true, there has been a fatal error for the estimator.
+  bool error;
+  // If the joint has seen an index pulse and is zeroed.
+  bool zeroed;
+  // The estimated position of the joint.
+  double position;
+};
+
+// A left/right pair of PotAndIndexPositions.
+struct PotAndIndexPair {
+  PotAndIndexPosition left;
+  PotAndIndexPosition right;
+};
+
+// Records edges captured on a single hall effect sensor.
+struct HallEffectStruct {
+  bool current;
+  int32_t posedge_count;
+  int32_t negedge_count;
+  double posedge_value;
+  double negedge_value;
+};
+
+// Records the positions for a mechanism with edge-capturing sensors on it.
+struct HallEffectPositions {
+  double current;
+  double posedge;
+  double negedge;
+};
+
+// Records edges captured on a single hall effect sensor.
+struct PosedgeOnlyCountedHallEffectStruct {
+  bool current;
+  int32_t posedge_count;
+  int32_t negedge_count;
+  double posedge_value;
+};
diff --git a/frc971/control_loops/gaussian_noise.cc b/frc971/control_loops/gaussian_noise.cc
new file mode 100644
index 0000000..c1c8701
--- /dev/null
+++ b/frc971/control_loops/gaussian_noise.cc
@@ -0,0 +1,18 @@
+#include "frc971/control_loops/gaussian_noise.h"
+
+namespace frc971 {
+namespace control_loops {
+
+GaussianNoise::GaussianNoise(unsigned int seed, double stddev)
+    : stddev_(stddev),
+      generator_(seed),
+      distribution_(0.0, 1.0) {
+  // Everything is initialized now.
+}
+
+double GaussianNoise::AddNoiseToSample(double sample) {
+  return sample + (distribution_(generator_) * stddev_);
+}
+
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/frc971/control_loops/gaussian_noise.h b/frc971/control_loops/gaussian_noise.h
new file mode 100644
index 0000000..8adf840
--- /dev/null
+++ b/frc971/control_loops/gaussian_noise.h
@@ -0,0 +1,36 @@
+#ifndef FRC971_CONTROL_LOOPS_GAUSSIAN_NOISE_H_
+#define FRC971_CONTROL_LOOPS_GAUSSIAN_NOISE_H_
+
+#include <unistd.h>
+
+#include <memory>
+#include <random>
+
+namespace frc971 {
+namespace control_loops {
+
+class GaussianNoise {
+ public:
+  // seed: The seed for the random number generator.
+  // stddev: The standard deviation of the distribution.
+  GaussianNoise(unsigned int seed, double stddev);
+
+  // Returns a version of the sample with gaussian noise added in.
+  double AddNoiseToSample(double sample);
+
+  // Sets the standard deviation of the gaussian noise.
+  inline void set_standard_deviation(double stddev) {
+    stddev_ = stddev;
+  }
+
+ private:
+  double stddev_;
+
+  std::default_random_engine generator_;
+  std::normal_distribution<double> distribution_;
+};
+
+}  // namespace control_loops
+}  // namespace frc971
+
+#endif  // FRC971_CONTROL_LOOPS_GAUSSIAN_NOISE_H_
diff --git a/frc971/control_loops/hall_effect_tracker.h b/frc971/control_loops/hall_effect_tracker.h
new file mode 100644
index 0000000..d1b6efe
--- /dev/null
+++ b/frc971/control_loops/hall_effect_tracker.h
@@ -0,0 +1,75 @@
+#ifndef FRC971_CONTROL_LOOPS_HALL_EFFECT_H_
+#define FRC971_CONTROL_LOOPS_HALL_EFFECT_H_
+
+#include <stdint.h>
+
+#include "frc971/control_loops/control_loops.q.h"
+
+namespace frc971 {
+
+// TODO(aschuh): Can we filter for 2 cycles instead of just 1?
+class HallEffectTracker {
+ public:
+  int32_t get_posedges() const { return posedges_.count(); }
+  int32_t get_negedges() const { return negedges_.count(); }
+
+  bool either_count_changed() const {
+    return posedges_.count_changed() || negedges_.count_changed();
+  }
+  bool posedge_count_changed() const { return posedges_.count_changed(); }
+  bool negedge_count_changed() const { return negedges_.count_changed(); }
+
+  bool value() const { return value_; }
+  bool last_value() const { return last_value_; }
+  bool is_posedge() const { return value() && !last_value(); }
+  bool is_negedge() const { return !value() && last_value(); }
+
+  double posedge_value() const { return posedge_value_; }
+  double negedge_value() const { return negedge_value_; }
+
+  void Update(const HallEffectStruct &position) {
+    last_value_ = value_;
+    value_ = position.current;
+    posedge_value_ = position.posedge_value;
+    negedge_value_ = position.negedge_value;
+    posedges_.update(position.posedge_count);
+    negedges_.update(position.negedge_count);
+  }
+
+  void Reset(const HallEffectStruct &position) {
+    posedges_.Reset(position.posedge_count);
+    negedges_.Reset(position.negedge_count);
+    value_ = position.current;
+    last_value_ = position.current;
+    posedge_value_ = position.posedge_value;
+    negedge_value_ = position.negedge_value;
+  }
+
+ private:
+  class {
+   public:
+    void update(int32_t count) {
+      previous_count_ = count_;
+      count_ = count;
+    }
+
+    void Reset(int32_t count) { count_ = count; }
+
+    bool count_changed() const { return previous_count_ != count_; }
+
+    int32_t count() const { return count_; }
+
+   private:
+    int32_t count_ = 0;
+    int32_t previous_count_ = 0;
+  } posedges_, negedges_;
+
+  bool value_ = false;
+  bool last_value_ = false;
+
+  double posedge_value_ = 0, negedge_value_ = 0;
+};
+
+}  // namespace frc971
+
+#endif  // FRC971_CONTROL_LOOPS_HALL_EFFECT_H_
diff --git a/frc971/control_loops/position_sensor_sim.cc b/frc971/control_loops/position_sensor_sim.cc
new file mode 100644
index 0000000..caa383e
--- /dev/null
+++ b/frc971/control_loops/position_sensor_sim.cc
@@ -0,0 +1,97 @@
+#include "frc971/control_loops/position_sensor_sim.h"
+
+#include <cmath>
+
+namespace frc971 {
+namespace control_loops {
+
+/* Index pulse/segment Explanation:
+ *
+ * The index segments are labelled starting at zero and go up. Each index
+ * segment is the space between the two bordering index pulses. The length of
+ * each index segment is determined by the `index_diff` variable in the
+ * constructor below.
+ *
+ * The index pulses are encountered when the mechanism moves from one index
+ * segment to another.
+ *
+ *         index segment
+ *               |
+ *               V
+ *
+ * +--- 0---+--- 1---+--- 2---+--- 3---+--- 4---+--- 5---+--- 6---+
+ *
+ * |        |        |        |        |        |        |        |
+ * 0        1        2        3        4        5        6        7
+ *
+ *                   A
+ *                   |
+ *              index pulse
+ */
+
+PositionSensorSimulator::PositionSensorSimulator(double index_diff,
+                                                 unsigned int noise_seed)
+    : index_diff_(index_diff), pot_noise_(noise_seed, 0.0) {
+  Initialize(0.0, 0.0);
+}
+
+void PositionSensorSimulator::Initialize(double start_position,
+                                         double pot_noise_stddev,
+                                         double known_index_pos /* = 0*/) {
+  // We're going to make the index pulse we know "segment zero".
+  cur_index_segment_ = floor((start_position - known_index_pos) / index_diff_);
+  known_index_pos_ = known_index_pos;
+  cur_index_ = 0;
+  index_count_ = 0;
+  cur_pos_ = start_position;
+  start_position_ = start_position;
+  pot_noise_.set_standard_deviation(pot_noise_stddev);
+}
+
+void PositionSensorSimulator::MoveTo(double new_pos) {
+  // Compute which index segment we're in. In other words, compute between
+  // which two index pulses we are.
+  const int new_index_segment =
+      floor((new_pos - known_index_pos_) / index_diff_);
+
+  if (new_index_segment < cur_index_segment_) {
+    // We've crossed an index pulse in the negative direction. That means the
+    // index pulse we just crossed is the higher end of the current index
+    // segment. For example, if the mechanism moved from index segment four to
+    // index segment three, then we just crossed index pulse 4.
+    cur_index_ = new_index_segment + 1;
+    index_count_++;
+  } else if (new_index_segment > cur_index_segment_) {
+    // We've crossed an index pulse in the positive direction. That means the
+    // index pulse we just crossed is the lower end of the index segment. For
+    // example, if the mechanism moved from index segment seven to index
+    // segment eight, then we just crossed index pulse eight.
+    cur_index_ = new_index_segment;
+    index_count_++;
+  }
+
+  cur_index_segment_ = new_index_segment;
+  cur_pos_ = new_pos;
+}
+
+void PositionSensorSimulator::GetSensorValues(PotAndIndexPosition *values) {
+  values->pot = pot_noise_.AddNoiseToSample(cur_pos_);
+  values->encoder = cur_pos_ - start_position_;
+
+  if (index_count_ == 0) {
+    values->latched_pot = 0.0;
+    values->latched_encoder = 0.0;
+  } else {
+    // Determine the position of the index pulse relative to absolute zero.
+    double index_pulse_position = cur_index_ * index_diff_ + known_index_pos_;
+
+    // Populate the latched pot/encoder samples.
+    values->latched_pot = pot_noise_.AddNoiseToSample(index_pulse_position);
+    values->latched_encoder = index_pulse_position - start_position_;
+  }
+
+  values->index_pulses = index_count_;
+}
+
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/frc971/control_loops/position_sensor_sim.h b/frc971/control_loops/position_sensor_sim.h
new file mode 100644
index 0000000..6c1884d
--- /dev/null
+++ b/frc971/control_loops/position_sensor_sim.h
@@ -0,0 +1,76 @@
+#ifndef FRC971_CONTROL_LOOPS_POSITION_SENSOR_SIM_H_
+#define FRC971_CONTROL_LOOPS_POSITION_SENSOR_SIM_H_
+
+#include "frc971/control_loops/control_loops.q.h"
+#include "frc971/control_loops/gaussian_noise.h"
+
+namespace frc971 {
+namespace control_loops {
+
+// NOTE: All potentiometer and encoder values in this class are assumed to be in
+// translated SI units.
+
+class PositionSensorSimulator {
+ public:
+  // index_diff: The interval between index pulses. This is measured in SI
+  //             units. For example, if an index pulse hits every 5cm on the
+  //             elevator, set this to 0.05.
+  // noise_seed: The seed to feed into the random number generator for the
+  //             potentiometer values.
+  // TODO(danielp): Allow for starting with a non-zero encoder value.
+  PositionSensorSimulator(double index_diff, unsigned int noise_seed = 0);
+
+  // Set new parameters for the sensors. This is useful for unit tests to change
+  // the simulated sensors' behavior on the fly.
+  // start_position: The position relative to absolute zero where the simulated
+  //                 structure starts. For example, to simulate the elevator
+  //                 starting at 40cm above absolute zero, set this to 0.4.
+  // pot_noise_stddev: The pot noise is sampled from a gaussian distribution.
+  //                   This specifies the standard deviation of that
+  //                   distribution.
+  // known_index_pos: The absolute position of an index pulse.
+  void Initialize(double start_position,
+                  double pot_noise_stddev,
+                  double known_index_pos = 0.0);
+
+  // Simulate the structure moving to a new position. The new value is measured
+  // relative to absolute zero. This will update the simulated sensors with new
+  // readings.
+  // new_position: The new position relative to absolute zero.
+  void MoveTo(double new_position);
+
+  // Get the current values of the simulated sensors.
+  // values: The target structure will be populated with simulated sensor
+  //         readings. The readings will be in SI units. For example the units
+  //         can be given in radians, meters, etc.
+  void GetSensorValues(PotAndIndexPosition* values);
+
+ private:
+  // The absolute segment between two index pulses the simulation is on. For
+  // example, when the current position is betwen index pulse zero and one,
+  // the current index segment is considered to be zero. Index segment one is
+  // between index pulses 1 and 2, etc.
+  int cur_index_segment_;
+  // Index pulse to use for calculating latched sensor values, relative to
+  // absolute zero. In other words this always holds the index pulse that was
+  // encountered most recently.
+  int cur_index_;
+  // How many index pulses we've seen.
+  int index_count_;
+  // Distance between index pulses on the mechanism.
+  double index_diff_;
+  // Absolute position of a known index pulse.
+  double known_index_pos_;
+  // Current position of the mechanism relative to absolute zero.
+  double cur_pos_;
+  // Starting position of the mechanism relative to absolute zero. See the
+  // `starting_position` parameter in the constructor for more info.
+  double start_position_;
+  // Gaussian noise to add to pot readings.
+  GaussianNoise pot_noise_;
+};
+
+}  // namespace control_loops
+}  // namespace frc971
+
+#endif /* FRC971_CONTROL_LOOPS_POSITION_SENSOR_SIM_H_ */
diff --git a/frc971/control_loops/position_sensor_sim_test.cc b/frc971/control_loops/position_sensor_sim_test.cc
new file mode 100644
index 0000000..0c9d3a9
--- /dev/null
+++ b/frc971/control_loops/position_sensor_sim_test.cc
@@ -0,0 +1,154 @@
+#include <unistd.h>
+
+#include <memory>
+
+#include <random>
+
+#include "gtest/gtest.h"
+#include "frc971/control_loops/control_loops.q.h"
+#include "frc971/control_loops/position_sensor_sim.h"
+#include "aos/common/die.h"
+
+namespace frc971 {
+namespace control_loops {
+
+class PositionSensorSimTest : public ::testing::Test {
+ protected:
+  PositionSensorSimTest() {}
+};
+
+TEST_F(PositionSensorSimTest, NoIndices) {
+  // We'll simulate a potentiometer with no noise so that we can accurately
+  // verify where the mechanism currently is. Overall though, the purpose of
+  // this test is to verify that no false index pulses are generated while the
+  // mechanism stays between two index pulses.
+  const double index_diff = 0.5;
+  PotAndIndexPosition position;
+  PositionSensorSimulator sim(index_diff);
+  sim.Initialize(3.6 * index_diff, 0);
+
+  // Make sure that we don't accidentally hit an index pulse.
+  for (int i = 0; i < 30; i++) {
+    sim.MoveTo(3.6 * index_diff);
+    sim.GetSensorValues(&position);
+    ASSERT_DOUBLE_EQ(3.6 * index_diff, position.pot);
+    ASSERT_EQ(0u, position.index_pulses);
+  }
+
+  for (int i = 0; i < 30; i++) {
+    sim.MoveTo(3.0 * index_diff);
+    sim.GetSensorValues(&position);
+    ASSERT_DOUBLE_EQ(3.0 * index_diff, position.pot);
+    ASSERT_EQ(0u, position.index_pulses);
+  }
+
+  for (int i = 0; i < 30; i++) {
+    sim.MoveTo(3.99 * index_diff);
+    sim.GetSensorValues(&position);
+    ASSERT_DOUBLE_EQ(3.99 * index_diff, position.pot);
+    ASSERT_EQ(0u, position.index_pulses);
+  }
+
+  for (int i = 0; i < 30; i++) {
+    sim.MoveTo(3.0 * index_diff);
+    sim.GetSensorValues(&position);
+    ASSERT_DOUBLE_EQ(3.0 * index_diff, position.pot);
+    ASSERT_EQ(0u, position.index_pulses);
+  }
+}
+
+TEST_F(PositionSensorSimTest, CountIndices) {
+  // The purpose of this test is to verify that the simulator latches the
+  // correct index pulse when transitioning from one segment to another. We
+  // again simulate zero noise on the potentiometer to accurately verify the
+  // mechanism's position during the index pulses.
+  const double index_diff = 0.8;
+  PotAndIndexPosition position;
+  PositionSensorSimulator sim(index_diff);
+  sim.Initialize(4.6 * index_diff, 0);
+
+  // Make sure that we get an index pulse on every transition.
+  sim.GetSensorValues(&position);
+  ASSERT_EQ(0u, position.index_pulses);
+
+  sim.MoveTo(3.6 * index_diff);
+  sim.GetSensorValues(&position);
+  ASSERT_DOUBLE_EQ(4.0 * index_diff, position.latched_pot);
+  ASSERT_EQ(1u, position.index_pulses);
+
+  sim.MoveTo(4.5 * index_diff);
+  sim.GetSensorValues(&position);
+  ASSERT_DOUBLE_EQ(4.0 * index_diff, position.latched_pot);
+  ASSERT_EQ(2u, position.index_pulses);
+
+  sim.MoveTo(5.9 * index_diff);
+  sim.GetSensorValues(&position);
+  ASSERT_DOUBLE_EQ(5.0 * index_diff, position.latched_pot);
+  ASSERT_EQ(3u, position.index_pulses);
+
+  sim.MoveTo(6.1 * index_diff);
+  sim.GetSensorValues(&position);
+  ASSERT_DOUBLE_EQ(6.0 * index_diff, position.latched_pot);
+  ASSERT_EQ(4u, position.index_pulses);
+
+  sim.MoveTo(8.7 * index_diff);
+  sim.GetSensorValues(&position);
+  ASSERT_DOUBLE_EQ(8.0 * index_diff, position.latched_pot);
+  ASSERT_EQ(5u, position.index_pulses);
+
+  sim.MoveTo(7.3 * index_diff);
+  sim.GetSensorValues(&position);
+  ASSERT_DOUBLE_EQ(8.0 * index_diff, position.latched_pot);
+  ASSERT_EQ(6u, position.index_pulses);
+}
+
+// Tests that the simulator handles non-zero specified index pulse locations
+// correctly.
+TEST_F(PositionSensorSimTest, NonZeroIndexLocation) {
+  const double index_diff = 0.5;
+  PositionSensorSimulator sim(index_diff);
+  sim.Initialize(index_diff * 0.25, 0.0, index_diff * 0.5);
+  PotAndIndexPosition position;
+
+  sim.MoveTo(0.75 * index_diff);
+  sim.GetSensorValues(&position);
+  EXPECT_EQ(1u, position.index_pulses);
+  EXPECT_DOUBLE_EQ(index_diff * 0.5, position.latched_pot);
+  EXPECT_DOUBLE_EQ(index_diff * 0.25, position.latched_encoder);
+
+  sim.MoveTo(index_diff);
+  sim.GetSensorValues(&position);
+  EXPECT_EQ(1u, position.index_pulses);
+  EXPECT_DOUBLE_EQ(index_diff * 0.5, position.latched_pot);
+  EXPECT_DOUBLE_EQ(index_diff * 0.25, position.latched_encoder);
+
+  sim.MoveTo(1.75 * index_diff);
+  sim.GetSensorValues(&position);
+  EXPECT_EQ(2u, position.index_pulses);
+  EXPECT_DOUBLE_EQ(index_diff * 1.5, position.latched_pot);
+  EXPECT_DOUBLE_EQ(index_diff * 1.25, position.latched_encoder);
+
+  // Try it with our known index pulse not being our first one.
+  sim.Initialize(index_diff * 0.25, 0.0, index_diff * 1.5);
+
+  sim.MoveTo(0.75 * index_diff);
+  sim.GetSensorValues(&position);
+  EXPECT_EQ(1u, position.index_pulses);
+  EXPECT_DOUBLE_EQ(index_diff * 0.5, position.latched_pot);
+  EXPECT_DOUBLE_EQ(index_diff * 0.25, position.latched_encoder);
+
+  sim.MoveTo(index_diff);
+  sim.GetSensorValues(&position);
+  EXPECT_EQ(1u, position.index_pulses);
+  EXPECT_DOUBLE_EQ(index_diff * 0.5, position.latched_pot);
+  EXPECT_DOUBLE_EQ(index_diff * 0.25, position.latched_encoder);
+
+  sim.MoveTo(1.75 * index_diff);
+  sim.GetSensorValues(&position);
+  EXPECT_EQ(2u, position.index_pulses);
+  EXPECT_DOUBLE_EQ(index_diff * 1.5, position.latched_pot);
+  EXPECT_DOUBLE_EQ(index_diff * 1.25, position.latched_encoder);
+}
+
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/frc971/control_loops/python/control_loop.py b/frc971/control_loops/python/control_loop.py
new file mode 100644
index 0000000..881880f
--- /dev/null
+++ b/frc971/control_loops/python/control_loop.py
@@ -0,0 +1,338 @@
+import controls
+import numpy
+
+class Constant(object):
+  def __init__ (self, name, formatt, value):
+    self.name = name
+    self.formatt = formatt
+    self.value = value
+    self.formatToType = {}
+    self.formatToType['%f'] = "double";
+    self.formatToType['%d'] = "int";
+  def __str__ (self):
+    return str("\nstatic constexpr %s %s = "+ self.formatt +";\n") % \
+        (self.formatToType[self.formatt], self.name, self.value)
+
+
+class ControlLoopWriter(object):
+  def __init__(self, gain_schedule_name, loops, namespaces=None, write_constants=False):
+    """Constructs a control loop writer.
+
+    Args:
+      gain_schedule_name: string, Name of the overall controller.
+      loops: array[ControlLoop], a list of control loops to gain schedule
+        in order.
+      namespaces: array[string], a list of names of namespaces to nest in
+        order.  If None, the default will be used.
+    """
+    self._gain_schedule_name = gain_schedule_name
+    self._loops = loops
+    if namespaces:
+      self._namespaces = namespaces
+    else:
+      self._namespaces = ['frc971', 'control_loops']
+
+    self._namespace_start = '\n'.join(
+        ['namespace %s {' % name for name in self._namespaces])
+
+    self._namespace_end = '\n'.join(
+        ['}  // namespace %s' % name for name in reversed(self._namespaces)])
+    
+    self._constant_list = []
+
+  def AddConstant(self, constant):
+    """Adds a constant to write.
+
+    Args:
+      constant: Constant, the constant to add to the header.
+    """
+    self._constant_list.append(constant)
+
+  def _TopDirectory(self):
+    return self._namespaces[0]
+
+  def _HeaderGuard(self, header_file):
+    return (self._TopDirectory().upper() + '_CONTROL_LOOPS_' +
+            header_file.upper().replace('.', '_').replace('/', '_') +
+            '_')
+
+  def Write(self, header_file, cc_file):
+    """Writes the loops to the specified files."""
+    self.WriteHeader(header_file)
+    self.WriteCC(header_file, cc_file)
+
+  def _GenericType(self, typename):
+    """Returns a loop template using typename for the type."""
+    num_states = self._loops[0].A.shape[0]
+    num_inputs = self._loops[0].B.shape[1]
+    num_outputs = self._loops[0].C.shape[0]
+    return '%s<%d, %d, %d>' % (
+        typename, num_states, num_inputs, num_outputs)
+
+  def _ControllerType(self):
+    """Returns a template name for StateFeedbackController."""
+    return self._GenericType('StateFeedbackController')
+
+  def _LoopType(self):
+    """Returns a template name for StateFeedbackLoop."""
+    return self._GenericType('StateFeedbackLoop')
+
+  def _PlantType(self):
+    """Returns a template name for StateFeedbackPlant."""
+    return self._GenericType('StateFeedbackPlant')
+
+  def _CoeffType(self):
+    """Returns a template name for StateFeedbackPlantCoefficients."""
+    return self._GenericType('StateFeedbackPlantCoefficients')
+
+  def WriteHeader(self, header_file, double_appendage=False, MoI_ratio=0.0):
+    """Writes the header file to the file named header_file.
+       Set double_appendage to true in order to include a ratio of
+       moments of inertia constant. Currently, only used for 2014 claw."""
+    with open(header_file, 'w') as fd:
+      header_guard = self._HeaderGuard(header_file)
+      fd.write('#ifndef %s\n'
+               '#define %s\n\n' % (header_guard, header_guard))
+      fd.write('#include \"frc971/control_loops/state_feedback_loop.h\"\n')
+      fd.write('\n')
+
+      fd.write(self._namespace_start)
+
+      for const in self._constant_list:
+          fd.write(str(const))
+
+      fd.write('\n\n')
+      for loop in self._loops:
+        fd.write(loop.DumpPlantHeader())
+        fd.write('\n')
+        fd.write(loop.DumpControllerHeader())
+        fd.write('\n')
+
+      fd.write('%s Make%sPlant();\n\n' %
+               (self._PlantType(), self._gain_schedule_name))
+
+      fd.write('%s Make%sLoop();\n\n' %
+               (self._LoopType(), self._gain_schedule_name))
+
+      fd.write(self._namespace_end)
+      fd.write('\n\n')
+      fd.write("#endif  // %s\n" % header_guard)
+
+  def WriteCC(self, header_file_name, cc_file):
+    """Writes the cc file to the file named cc_file."""
+    with open(cc_file, 'w') as fd:
+      fd.write('#include \"%s/control_loops/%s\"\n' %
+               (self._TopDirectory(), header_file_name))
+      fd.write('\n')
+      fd.write('#include <vector>\n')
+      fd.write('\n')
+      fd.write('#include \"frc971/control_loops/state_feedback_loop.h\"\n')
+      fd.write('\n')
+      fd.write(self._namespace_start)
+      fd.write('\n\n')
+      for loop in self._loops:
+        fd.write(loop.DumpPlant())
+        fd.write('\n')
+
+      for loop in self._loops:
+        fd.write(loop.DumpController())
+        fd.write('\n')
+
+      fd.write('%s Make%sPlant() {\n' %
+               (self._PlantType(), self._gain_schedule_name))
+      fd.write('  ::std::vector< ::std::unique_ptr<%s>> plants(%d);\n' % (
+          self._CoeffType(), len(self._loops)))
+      for index, loop in enumerate(self._loops):
+        fd.write('  plants[%d] = ::std::unique_ptr<%s>(new %s(%s));\n' %
+                 (index, self._CoeffType(), self._CoeffType(),
+                  loop.PlantFunction()))
+      fd.write('  return %s(&plants);\n' % self._PlantType())
+      fd.write('}\n\n')
+
+      fd.write('%s Make%sLoop() {\n' %
+               (self._LoopType(), self._gain_schedule_name))
+      fd.write('  ::std::vector< ::std::unique_ptr<%s>> controllers(%d);\n' % (
+          self._ControllerType(), len(self._loops)))
+      for index, loop in enumerate(self._loops):
+        fd.write('  controllers[%d] = ::std::unique_ptr<%s>(new %s(%s));\n' %
+                 (index, self._ControllerType(), self._ControllerType(),
+                  loop.ControllerFunction()))
+      fd.write('  return %s(&controllers);\n' % self._LoopType())
+      fd.write('}\n\n')
+
+      fd.write(self._namespace_end)
+      fd.write('\n')
+
+
+class ControlLoop(object):
+  def __init__(self, name):
+    """Constructs a control loop object.
+
+    Args:
+      name: string, The name of the loop to use when writing the C++ files.
+    """
+    self._name = name
+
+  def ContinuousToDiscrete(self, A_continuous, B_continuous, dt):
+    """Calculates the discrete time values for A and B.
+
+      Args:
+        A_continuous: numpy.matrix, The continuous time A matrix
+        B_continuous: numpy.matrix, The continuous time B matrix
+        dt: float, The time step of the control loop
+
+      Returns:
+        (A, B), numpy.matrix, the control matricies.
+    """
+    return controls.c2d(A_continuous, B_continuous, dt)
+
+  def InitializeState(self):
+    """Sets X, Y, and X_hat to zero defaults."""
+    self.X = numpy.zeros((self.A.shape[0], 1))
+    self.Y = self.C * self.X
+    self.X_hat = numpy.zeros((self.A.shape[0], 1))
+
+  def PlaceControllerPoles(self, poles):
+    """Places the controller poles.
+
+    Args:
+      poles: array, An array of poles.  Must be complex conjegates if they have
+        any imaginary portions.
+    """
+    self.K = controls.dplace(self.A, self.B, poles)
+
+  def PlaceObserverPoles(self, poles):
+    """Places the observer poles.
+
+    Args:
+      poles: array, An array of poles.  Must be complex conjegates if they have
+        any imaginary portions.
+    """
+    self.L = controls.dplace(self.A.T, self.C.T, poles).T
+
+  def Update(self, U):
+    """Simulates one time step with the provided U."""
+    #U = numpy.clip(U, self.U_min, self.U_max)
+    self.X = self.A * self.X + self.B * U
+    self.Y = self.C * self.X + self.D * U
+
+  def PredictObserver(self, U):
+    """Runs the predict step of the observer update."""
+    self.X_hat = (self.A * self.X_hat + self.B * U)
+
+  def CorrectObserver(self, U):
+    """Runs the correct step of the observer update."""
+    self.X_hat += numpy.linalg.inv(self.A) * self.L * (
+        self.Y - self.C * self.X_hat - self.D * U)
+
+  def UpdateObserver(self, U):
+    """Updates the observer given the provided U."""
+    self.X_hat = (self.A * self.X_hat + self.B * U +
+                  self.L * (self.Y - self.C * self.X_hat - self.D * U))
+
+  def _DumpMatrix(self, matrix_name, matrix):
+    """Dumps the provided matrix into a variable called matrix_name.
+
+    Args:
+      matrix_name: string, The variable name to save the matrix to.
+      matrix: The matrix to dump.
+
+    Returns:
+      string, The C++ commands required to populate a variable named matrix_name
+        with the contents of matrix.
+    """
+    ans = ['  Eigen::Matrix<double, %d, %d> %s;\n' % (
+        matrix.shape[0], matrix.shape[1], matrix_name)]
+    first = True
+    for x in xrange(matrix.shape[0]):
+      for y in xrange(matrix.shape[1]):
+        element = matrix[x, y]
+        if first:
+          ans.append('  %s << ' % matrix_name)
+          first = False
+        else:
+          ans.append(', ')
+        ans.append(str(element))
+
+    ans.append(';\n')
+    return ''.join(ans)
+
+  def DumpPlantHeader(self):
+    """Writes out a c++ header declaration which will create a Plant object.
+
+    Returns:
+      string, The header declaration for the function.
+    """
+    num_states = self.A.shape[0]
+    num_inputs = self.B.shape[1]
+    num_outputs = self.C.shape[0]
+    return 'StateFeedbackPlantCoefficients<%d, %d, %d> Make%sPlantCoefficients();\n' % (
+        num_states, num_inputs, num_outputs, self._name)
+
+  def DumpPlant(self):
+    """Writes out a c++ function which will create a PlantCoefficients object.
+
+    Returns:
+      string, The function which will create the object.
+    """
+    num_states = self.A.shape[0]
+    num_inputs = self.B.shape[1]
+    num_outputs = self.C.shape[0]
+    ans = ['StateFeedbackPlantCoefficients<%d, %d, %d>'
+           ' Make%sPlantCoefficients() {\n' % (
+        num_states, num_inputs, num_outputs, self._name)]
+
+    ans.append(self._DumpMatrix('A', self.A))
+    ans.append(self._DumpMatrix('B', self.B))
+    ans.append(self._DumpMatrix('C', self.C))
+    ans.append(self._DumpMatrix('D', self.D))
+    ans.append(self._DumpMatrix('U_max', self.U_max))
+    ans.append(self._DumpMatrix('U_min', self.U_min))
+
+    ans.append('  return StateFeedbackPlantCoefficients<%d, %d, %d>'
+               '(A, B, C, D, U_max, U_min);\n' % (num_states, num_inputs,
+                                                  num_outputs))
+    ans.append('}\n')
+    return ''.join(ans)
+
+  def PlantFunction(self):
+    """Returns the name of the plant coefficient function."""
+    return 'Make%sPlantCoefficients()' % self._name
+
+  def ControllerFunction(self):
+    """Returns the name of the controller function."""
+    return 'Make%sController()' % self._name
+
+  def DumpControllerHeader(self):
+    """Writes out a c++ header declaration which will create a Controller object.
+
+    Returns:
+      string, The header declaration for the function.
+    """
+    num_states = self.A.shape[0]
+    num_inputs = self.B.shape[1]
+    num_outputs = self.C.shape[0]
+    return 'StateFeedbackController<%d, %d, %d> %s;\n' % (
+        num_states, num_inputs, num_outputs, self.ControllerFunction())
+
+  def DumpController(self):
+    """Returns a c++ function which will create a Controller object.
+
+    Returns:
+      string, The function which will create the object.
+    """
+    num_states = self.A.shape[0]
+    num_inputs = self.B.shape[1]
+    num_outputs = self.C.shape[0]
+    ans = ['StateFeedbackController<%d, %d, %d> %s {\n' % (
+        num_states, num_inputs, num_outputs, self.ControllerFunction())]
+
+    ans.append(self._DumpMatrix('L', self.L))
+    ans.append(self._DumpMatrix('K', self.K))
+    ans.append(self._DumpMatrix('A_inv', numpy.linalg.inv(self.A)))
+
+    ans.append('  return StateFeedbackController<%d, %d, %d>'
+               '(L, K, A_inv, Make%sPlantCoefficients());\n' % (
+                   num_states, num_inputs, num_outputs, self._name))
+    ans.append('}\n')
+    return ''.join(ans)
diff --git a/frc971/control_loops/python/controls.py b/frc971/control_loops/python/controls.py
new file mode 100644
index 0000000..b66bd56
--- /dev/null
+++ b/frc971/control_loops/python/controls.py
@@ -0,0 +1,153 @@
+#!/usr/bin/python
+
+"""
+Control loop pole placement library.
+
+This library will grow to support many different pole placement methods.
+Currently it only supports direct pole placement.
+"""
+
+__author__ = 'Austin Schuh (austin.linux@gmail.com)'
+
+import numpy
+import slycot
+import scipy.signal.cont2discrete
+
+class Error (Exception):
+  """Base class for all control loop exceptions."""
+
+
+class PolePlacementError(Error):
+  """Exception raised when pole placement fails."""
+
+
+# TODO(aschuh): dplace should take a control system object.
+# There should also exist a function to manipulate laplace expressions, and
+# something to plot bode plots and all that.
+def dplace(A, B, poles, alpha=1e-6):
+  """Set the poles of (A - BF) to poles.
+
+  Args:
+    A: numpy.matrix(n x n), The A matrix.
+    B: numpy.matrix(n x m), The B matrix.
+    poles: array(imaginary numbers), The poles to use.  Complex conjugates poles
+      must be in pairs.
+
+  Raises:
+    ValueError: Arguments were the wrong shape or there were too many poles.
+    PolePlacementError: Pole placement failed.
+
+  Returns:
+    numpy.matrix(m x n), K
+  """
+  # See http://www.icm.tu-bs.de/NICONET/doc/SB01BD.html for a description of the
+  # fortran code that this is cleaning up the interface to.
+  n = A.shape[0]
+  if A.shape[1] != n:
+    raise ValueError("A must be square")
+  if B.shape[0] != n:
+    raise ValueError("B must have the same number of states as A.")
+  m = B.shape[1]
+
+  num_poles = len(poles)
+  if num_poles > n:
+    raise ValueError("Trying to place more poles than states.")
+
+  out = slycot.sb01bd(n=n,
+                      m=m,
+                      np=num_poles,
+                      alpha=alpha,
+                      A=A,
+                      B=B,
+                      w=numpy.array(poles),
+                      dico='D')
+
+  A_z = numpy.matrix(out[0])
+  num_too_small_eigenvalues = out[2]
+  num_assigned_eigenvalues = out[3]
+  num_uncontrollable_eigenvalues = out[4]
+  K = numpy.matrix(-out[5])
+  Z = numpy.matrix(out[6])
+
+  if num_too_small_eigenvalues != 0:
+    raise PolePlacementError("Number of eigenvalues that are too small "
+                             "and are therefore unmodified is %d." %
+                             num_too_small_eigenvalues)
+  if num_assigned_eigenvalues != num_poles:
+    raise PolePlacementError("Did not place all the eigenvalues that were "
+                             "requested. Only placed %d eigenvalues." %
+                             num_assigned_eigenvalues)
+  if num_uncontrollable_eigenvalues != 0:
+    raise PolePlacementError("Found %d uncontrollable eigenvlaues." %
+                             num_uncontrollable_eigenvalues)
+
+  return K
+
+
+def c2d(A, B, dt):
+  """Converts from continuous time state space representation to discrete time.
+     Returns (A, B).  C and D are unchanged."""
+
+  ans_a, ans_b, _, _, _ = scipy.signal.cont2discrete((A, B, None, None), dt)
+  return numpy.matrix(ans_a), numpy.matrix(ans_b)
+
+def ctrb(A, B):
+  """Returns the controlability matrix.
+
+    This matrix must have full rank for all the states to be controlable.
+  """
+  n = A.shape[0]
+  output = B
+  intermediate = B
+  for i in xrange(0, n):
+    intermediate = A * intermediate
+    output = numpy.concatenate((output, intermediate), axis=1)
+
+  return output
+
+def dlqr(A, B, Q, R):
+  """Solves for the optimal lqr controller.
+
+    x(n+1) = A * x(n) + B * u(n)
+    J = sum(0, inf, x.T * Q * x + u.T * R * u)
+  """
+
+  # P = (A.T * P * A) - (A.T * P * B * numpy.linalg.inv(R + B.T * P *B) * (A.T * P.T * B).T + Q
+
+  P, rcond, w, S, T = slycot.sb02od(
+      n=A.shape[0], m=B.shape[1], A=A, B=B, Q=Q, R=R, dico='D')
+
+  F = numpy.linalg.inv(R + B.T * P *B) * B.T * P * A
+  return F
+
+def kalman(A, B, C, Q, R):
+  """Solves for the steady state kalman gain and covariance matricies.
+
+    Args:
+      A, B, C: SS matricies.
+      Q: The model uncertantity
+      R: The measurement uncertainty
+
+    Returns:
+      KalmanGain, Covariance.
+  """
+  P = Q
+
+  I = numpy.matrix(numpy.eye(P.shape[0]))
+  At = A.T
+  Ct = C.T
+  i = 0
+
+  while True:
+    last_P = P
+    P_prior = A * P * At + Q
+    S = C * P_prior * Ct + R
+    K = P_prior * Ct * numpy.linalg.inv(S)
+    P = (I - K * C) * P_prior
+
+    diff = P - last_P
+    i += 1
+    if numpy.linalg.norm(diff) / numpy.linalg.norm(P) < 1e-9:
+      break
+
+  return K, P
diff --git a/frc971/control_loops/python/libcdd.py b/frc971/control_loops/python/libcdd.py
new file mode 100644
index 0000000..6b81a4f
--- /dev/null
+++ b/frc971/control_loops/python/libcdd.py
@@ -0,0 +1,130 @@
+#!/usr/bin/python
+
+"""Wrapper around libcdd, a polytope manipulation library."""
+
+__author__ = 'Austin Schuh (austin.linux@gmail.com)'
+
+import ctypes
+import sys
+
+# Wrapper around PyFile_AsFile so that we can print out the error messages.
+# Set the arg type and return types of the function call.
+class FILE(ctypes.Structure):
+  pass
+
+ctypes.pythonapi.PyFile_AsFile.argtypes = [ctypes.py_object]
+ctypes.pythonapi.PyFile_AsFile.restype = ctypes.POINTER(FILE)
+
+# Load and init libcdd.  libcdd is a C library that implements algorithm to
+# manipulate half space and vertex representations of polytopes.
+# Unfortunately, the library was compiled with C++ even though it has a lot of C
+# code in it, so all the symbol names are mangled.  Ug.
+libcdd = ctypes.cdll.LoadLibrary('libcdd.so')
+libcdd._Z23dd_set_global_constantsv()
+
+# The variable type mytype that libcdd defines (double[1])
+# See http://docs.python.org/2/library/ctypes.html#arrays for the documentation
+# explaining why ctypes.c_double * 1 => double[1]
+# libcdd defines mytype to various things so it can essentially template its
+# functions.  What a weird library.
+mytype = ctypes.c_double * 1
+
+
+# Forward declaration for the polyhedra data structure.
+class dd_polyhedradata(ctypes.Structure):
+  pass
+
+
+# Definition of dd_matrixdata
+class dd_matrixdata(ctypes.Structure):
+  _fields_ = [
+      ("rowsize", ctypes.c_long),
+      ("linset", ctypes.POINTER(ctypes.c_ulong)),
+      ("colsize", ctypes.c_long),
+      ("representation", ctypes.c_int),
+      ("numbtype", ctypes.c_int),
+      ("matrix", ctypes.POINTER(ctypes.POINTER(mytype))),
+      ("objective", ctypes.c_int),
+      ("rowvec", ctypes.POINTER(mytype)),
+  ]
+
+# Define the input and output types for a bunch of libcdd functions.
+libcdd._Z15dd_CreateMatrixll.restype = ctypes.POINTER(dd_matrixdata)
+libcdd._Z9ddd_get_dPd.argtypes = [mytype]
+libcdd._Z9ddd_get_dPd.restype = ctypes.c_double
+
+libcdd._Z17dd_CopyGeneratorsP16dd_polyhedradata.argtypes = [
+    ctypes.POINTER(dd_polyhedradata)
+]
+libcdd._Z17dd_CopyGeneratorsP16dd_polyhedradata.restype = ctypes.POINTER(dd_matrixdata)
+
+libcdd._Z16dd_DDMatrix2PolyP13dd_matrixdataP12dd_ErrorType.argtypes = [
+    ctypes.POINTER(dd_matrixdata),
+    ctypes.POINTER(ctypes.c_int)
+]
+libcdd._Z16dd_DDMatrix2PolyP13dd_matrixdataP12dd_ErrorType.restype = (
+  ctypes.POINTER(dd_polyhedradata))
+
+libcdd._Z13dd_FreeMatrixP13dd_matrixdata.argtypes = [
+    ctypes.POINTER(dd_matrixdata)
+]
+
+libcdd._Z16dd_FreePolyhedraP16dd_polyhedradata.argtypes = [
+  ctypes.POINTER(dd_polyhedradata)
+]
+
+libcdd._Z9ddd_set_dPdd.argtypes = [
+  mytype,
+  ctypes.c_double
+]
+
+
+# Various enums.
+DD_INEQUALITY = 1
+DD_REAL = 1
+DD_NO_ERRORS = 17
+
+
+def dd_CreateMatrix(rows, cols):
+  return libcdd._Z15dd_CreateMatrixll(
+      ctypes.c_long(rows),
+      ctypes.c_long(cols))
+
+
+def dd_set_d(mytype_address, double_value):
+  libcdd._Z9ddd_set_dPdd(mytype_address,
+      ctypes.c_double(double_value))
+
+
+def dd_CopyGenerators(polyhedraptr):
+  return libcdd._Z17dd_CopyGeneratorsP16dd_polyhedradata(polyhedraptr)
+
+
+def dd_get_d(mytype_address):
+  return libcdd._Z9ddd_get_dPd(mytype_address)
+
+
+def dd_FreeMatrix(matrixptr):
+  libcdd._Z13dd_FreeMatrixP13dd_matrixdata(matrixptr)
+
+
+def dd_FreePolyhedra(polyhedraptr):
+  libcdd._Z16dd_FreePolyhedraP16dd_polyhedradata(polyhedraptr)
+
+
+def dd_DDMatrix2Poly(matrixptr):
+  error = ctypes.c_int()
+  polyhedraptr = libcdd._Z16dd_DDMatrix2PolyP13dd_matrixdataP12dd_ErrorType(
+      matrixptr,
+      ctypes.byref(error))
+
+  # Return None on error.
+  # The error values are enums, so they aren't exposed.
+  if error.value != DD_NO_ERRORS:
+    # Dump out the errors to stderr
+    libcdd._Z21dd_WriteErrorMessagesP8_IO_FILE12dd_ErrorType(
+        ctypes.pythonapi.PyFile_AsFile(ctypes.py_object(sys.stdout)),
+        error)
+    dd_FreePolyhedra(polyhedraptr)
+    return None
+  return polyhedraptr
diff --git a/frc971/control_loops/python/polytope.py b/frc971/control_loops/python/polytope.py
new file mode 100644
index 0000000..e08a160
--- /dev/null
+++ b/frc971/control_loops/python/polytope.py
@@ -0,0 +1,224 @@
+#!/usr/bin/python
+
+"""
+Polyhedral set library.
+
+This library implements convex regions of the form H x <= k, where H, x, and k
+are matricies.  It also provides convenient methods to find all the verticies.
+"""
+
+__author__ = 'Austin Schuh (austin.linux@gmail.com)'
+
+
+import libcdd
+import numpy
+import string
+import sys
+
+
+def _PiecewiseConcat(*args):
+  """Concatenates strings inside lists, elementwise.
+
+  Given ['a', 's'] and ['d', 'f'], returns ['ad', 'sf']
+  """
+  return map(''.join, zip(*args))
+
+
+def _SplitAndPad(s):
+  """Splits a string on newlines, and pads the lines to be the same width."""
+  split_string = s.split('\n')
+  width = max(len(stringpiece) for stringpiece in split_string) + 1
+
+  padded_strings = [string.ljust(stringpiece, width, ' ')
+                        for stringpiece in split_string]
+  return padded_strings
+
+
+def _PadHeight(padded_array, min_height):
+  """Adds lines of spaces to the top and bottom of an array symmetrically."""
+  height = len(padded_array)
+  if height < min_height:
+    pad_array = [' ' * len(padded_array[0])]
+    height_error = min_height - height
+    return (pad_array * ((height_error) / 2) +
+            padded_array +
+            pad_array * ((height_error + 1) / 2))
+  return padded_array
+
+
+class HPolytope(object):
+  """This object represents a H-polytope.
+
+  Polytopes are convex regions in n-dimensional space.
+  For H-polytopes, this is represented as the intersection of a set of half
+  planes.  The mathematic equation that represents this is H x <= k.
+  """
+
+  def __init__(self, H, k):
+    """Constructs a H-polytope from the H and k matricies.
+
+    Args:
+      H: numpy.Matrix (n by k), where n is the number of constraints, and k is
+        the number of dimensions in the space.  Does not copy the matrix.
+      k: numpy.Matrix (n by 1).  Does not copy the matrix.
+    """
+    self._H = H
+    self._k = k
+
+  @property
+  def k(self):
+    """Returns the k in H x <= k."""
+    return self._k
+
+  @property
+  def H(self):
+    """Returns the H in H x <= k."""
+    return self._H
+
+  @property
+  def ndim(self):
+    """Returns the dimension of the set."""
+    return self._H.shape[1]
+
+  @property
+  def num_constraints(self):
+    """Returns the number of constraints defining the set."""
+    return self._k.shape[0]
+
+  def IsInside(self, point):
+    """Returns true if the point is inside the polytope, edges included."""
+    return (self._H * point <= self._k).all()
+
+  def Vertices(self):
+    """Returns a matrix with the vertices of the set in its rows."""
+    # TODO(aschuh): It would be better to write some small C/C++ function that
+    # does all of this and takes in a numpy array.
+    # The copy is expensive in Python and cheaper in C.
+
+    # Create an empty matrix with the correct size.
+    matrixptr = libcdd.dd_CreateMatrix(self.num_constraints, self.ndim + 1)
+    matrix = matrixptr.contents
+
+    try:
+      # Copy the data into the matrix.
+      for i in xrange(self.num_constraints):
+        libcdd.dd_set_d(matrix.matrix[i][0], self._k[i, 0])
+        for j in xrange(self.ndim):
+          libcdd.dd_set_d(matrix.matrix[i][j + 1], -self._H[i, j])
+
+      # Set enums to the correct values.
+      matrix.representation = libcdd.DD_INEQUALITY
+      matrix.numbtype = libcdd.DD_REAL
+
+      # TODO(aschuh): Set linearity if it is useful.
+      # This would be useful if we had any constraints saying B - A x = 0
+
+      # Build a Polyhedra
+      polyhedraptr = libcdd.dd_DDMatrix2Poly(matrixptr)
+
+      if not polyhedraptr:
+        return None
+
+      try:
+        # Return None on error.
+        # The error values are enums, so they aren't exposed.
+
+        # Magic happens here.  Computes the vertices
+        vertex_matrixptr = libcdd.dd_CopyGenerators(
+            polyhedraptr)
+        vertex_matrix = vertex_matrixptr.contents
+
+        try:
+          # Count the number of vertices and rays in the result.
+          num_vertices = 0
+          num_rays = 0
+          for i in xrange(vertex_matrix.rowsize):
+            if libcdd.dd_get_d(vertex_matrix.matrix[i][0]) == 0:
+              num_rays += 1
+            else:
+              num_vertices += 1
+
+          # Build zeroed matricies for the new vertices and rays.
+          vertices = numpy.matrix(numpy.zeros((num_vertices,
+                                               vertex_matrix.colsize - 1)))
+          rays = numpy.matrix(numpy.zeros((num_rays,
+                                           vertex_matrix.colsize - 1)))
+
+          ray_index = 0
+          vertex_index = 0
+
+          # Copy the data out of the matrix.
+          for index in xrange(vertex_matrix.rowsize):
+            if libcdd.dd_get_d(vertex_matrix.matrix[index][0]) == 0.0:
+              for j in xrange(vertex_matrix.colsize - 1):
+                rays[ray_index, j] = libcdd.dd_get_d(
+                    vertex_matrix.matrix[index][j + 1])
+              ray_index += 1
+            else:
+              for j in xrange(vertex_matrix.colsize - 1):
+                vertices[vertex_index, j] = libcdd.dd_get_d(
+                    vertex_matrix.matrix[index][j + 1])
+              vertex_index += 1
+        finally:
+          # Free everything.
+          libcdd.dd_FreeMatrix(vertex_matrixptr)
+
+      finally:
+        libcdd.dd_FreePolyhedra(polyhedraptr)
+
+    finally:
+      libcdd.dd_FreeMatrix(matrixptr)
+
+    # Rays are unsupported right now.  This may change in the future.
+    assert(rays.shape[0] == 0)
+
+    return vertices
+
+
+  def __str__(self):
+    """Returns a formatted version of the polytope.
+
+    The dump will look something like the following, which prints out the matrix
+    comparison.
+
+    [[ 1  0]            [[12]
+     [-1  0]  [[x0]  <=  [12]
+     [ 0  1]   [x1]]     [12]
+     [ 0 -1]]            [12]]
+    """
+    height = max(self.ndim, self.num_constraints)
+
+    # Split the print up into 4 parts and concatenate them all.
+    H_strings = _PadHeight(_SplitAndPad(str(self.H)), height)
+    v_strings = _PadHeight(_SplitAndPad(str(self.k)), height)
+    x_strings = _PadHeight(self._MakeXStrings(), height)
+    cmp_strings = self._MakeCmpStrings(height)
+
+    return '\n'.join(_PiecewiseConcat(H_strings, x_strings,
+                                      cmp_strings, v_strings))
+
+  def _MakeXStrings(self):
+    """Builds an array of strings with constraint names in it for printing."""
+    x_strings = []
+    if self.ndim == 1:
+      x_strings = ["[[x0]] "]
+    else:
+      for index in xrange(self.ndim):
+        if index == 0:
+          x = "[[x%d]  " % index
+        elif index == self.ndim - 1:
+          x = " [x%d]] " % index
+        else:
+          x = " [x%d]  " % index
+        x_strings.append(x)
+    return x_strings
+
+  def _MakeCmpStrings(self, height):
+    """Builds an array of strings with the comparison in it for printing."""
+    cmp_strings = []
+    for index in xrange(height):
+      if index == (height - 1) / 2:
+        cmp_strings.append("<= ")
+      else:
+        cmp_strings.append("   ")
+    return cmp_strings
diff --git a/frc971/control_loops/python/polytope_test.py b/frc971/control_loops/python/polytope_test.py
new file mode 100755
index 0000000..9a35ebe
--- /dev/null
+++ b/frc971/control_loops/python/polytope_test.py
@@ -0,0 +1,192 @@
+#!/usr/bin/python
+
+import numpy
+from numpy.testing import *
+import polytope
+import unittest
+
+__author__ = 'Austin Schuh (austin.linux@gmail.com)'
+
+def MakePoint(*args):
+  """Makes a point from a set of arguments."""
+  return numpy.matrix([[arg] for arg in args])
+
+class TestHPolytope(unittest.TestCase):
+  def setUp(self):
+    """Builds a simple box polytope."""
+    self.H = numpy.matrix([[1, 0],
+                           [-1, 0],
+                           [0, 1],
+                           [0, -1]])
+    self.k = numpy.matrix([[12],
+                           [12],
+                           [12],
+                           [12]])
+    self.p = polytope.HPolytope(self.H, self.k)
+
+  def test_Hk(self):
+    """Tests that H and k are saved correctly."""
+    assert_array_equal(self.p.H, self.H)
+    assert_array_equal(self.p.k, self.k)
+
+  def test_IsInside(self):
+    """Tests IsInside for various points."""
+    inside_points = [
+      MakePoint(0, 0),
+      MakePoint(6, 6),
+      MakePoint(12, 6),
+      MakePoint(-6, 10)]
+    outside_points = [
+      MakePoint(14, 0),
+      MakePoint(-14, 0),
+      MakePoint(0, 14),
+      MakePoint(0, -14),
+      MakePoint(14, -14)]
+
+    for inside_point in inside_points:
+      self.assertTrue(self.p.IsInside(inside_point),
+                      msg='Point is' + str(inside_point))
+
+    for outside_point in outside_points:
+      self.assertFalse(self.p.IsInside(outside_point),
+                       msg='Point is' + str(outside_point))
+
+  def AreVertices(self, p, vertices):
+    """Checks that all the vertices are on corners of the set."""
+    for i in xrange(vertices.shape[0]):
+      # Check that all the vertices have the correct number of active
+      # constraints.
+      lmda = p.H * vertices[i,:].T - p.k
+      num_active_constraints = 0
+      for j in xrange(lmda.shape[0]):
+        # Verify that the constraints are either active, or not violated.
+        if numpy.abs(lmda[j, 0]) <= 1e-9:
+          num_active_constraints += 1
+        else:
+          self.assertLessEqual(lmda[j, 0], 0.0)
+
+      self.assertEqual(p.ndim, num_active_constraints)
+
+  def HasSamePoints(self, expected, actual):
+    """Verifies that the points in expected are in actual."""
+    found_points = set()
+    self.assertEqual(expected.shape, actual.shape)
+    for index in xrange(expected.shape[0]):
+      expected_point = expected[index, :]
+      for actual_index in xrange(actual.shape[0]):
+        actual_point = actual[actual_index, :]
+        if numpy.abs(expected_point - actual_point).max() <= 1e-4:
+          found_points.add(actual_index)
+          break
+
+    self.assertEqual(len(found_points), actual.shape[0],
+        msg="Expected:\n" + str(expected) + "\nActual:\n" + str(actual))
+
+  def test_Skewed_Nonsym_Vertices(self):
+    """Tests the vertices of a severely skewed space."""
+    self.H = numpy.matrix([[10, -1],
+                           [-1, -1],
+                           [-1, 10],
+                           [10, 10]])
+    self.k = numpy.matrix([[2],
+                           [2],
+                           [2],
+                           [2]])
+    self.p = polytope.HPolytope(self.H, self.k)
+    vertices = self.p.Vertices()
+    self.AreVertices(self.p, vertices)
+
+    self.HasSamePoints(
+        numpy.matrix([[0., 0.2],
+                      [0.2, 0.],
+                      [-2., 0.],
+                      [0., -2.]]),
+        vertices)
+
+  def test_Vertices_Nonsym(self):
+    """Tests the vertices of a nonsymetric space."""
+    self.k = numpy.matrix([[6],
+                           [12],
+                           [2],
+                           [10]])
+    self.p = polytope.HPolytope(self.H, self.k)
+    vertices = self.p.Vertices()
+    self.AreVertices(self.p, vertices)
+
+    self.HasSamePoints(
+        numpy.matrix([[6., 2.],
+                      [6., -10.],
+                      [-12., -10.],
+                      [-12., 2.]]),
+        vertices)
+
+  def test_Vertices(self):
+    """Tests the vertices of a nonsymetric space."""
+    self.HasSamePoints(self.p.Vertices(),
+                       numpy.matrix([[12., 12.],
+                                     [12., -12.],
+                                     [-12., -12.],
+                                     [-12., 12.]]))
+
+  def test_concat(self):
+    """Tests that the concat function works for simple inputs."""
+    self.assertEqual(["asd", "qwe"],
+                     polytope._PiecewiseConcat(["a", "q"],
+                                               ["s", "w"],
+                                               ["d", "e"]))
+
+  def test_str(self):
+    """Verifies that the str method works for the provided p."""
+    self.assertEqual('[[ 1  0]            [[12]  \n'
+                     ' [-1  0]  [[x0]  <=  [12]  \n'
+                     ' [ 0  1]   [x1]]     [12]  \n'
+                     ' [ 0 -1]]            [12]] ',
+                     str(self.p))
+
+  def MakePWithDims(self, num_constraints, num_dims):
+    """Makes a zeroed out polytope with the correct size."""
+    self.p = polytope.HPolytope(
+        numpy.matrix(numpy.zeros((num_constraints, num_dims))),
+        numpy.matrix(numpy.zeros((num_constraints, 1))))
+
+  def test_few_constraints_odd_constraint_even_dims_str(self):
+    """Tests printing out the set with odd constraints and even dimensions."""
+    self.MakePWithDims(num_constraints=5, num_dims=2)
+    self.assertEqual('[[ 0.  0.]            [[ 0.]  \n'
+                     ' [ 0.  0.]  [[x0]      [ 0.]  \n'
+                     ' [ 0.  0.]   [x1]] <=  [ 0.]  \n'
+                     ' [ 0.  0.]             [ 0.]  \n'
+                     ' [ 0.  0.]]            [ 0.]] ',
+                     str(self.p))
+
+  def test_few_constraints_odd_constraint_small_dims_str(self):
+    """Tests printing out the set with odd constraints and odd dimensions."""
+    self.MakePWithDims(num_constraints=5, num_dims=1)
+    self.assertEqual('[[ 0.]            [[ 0.]  \n'
+                     ' [ 0.]             [ 0.]  \n'
+                     ' [ 0.]  [[x0]] <=  [ 0.]  \n'
+                     ' [ 0.]             [ 0.]  \n'
+                     ' [ 0.]]            [ 0.]] ',
+                     str(self.p))
+
+  def test_few_constraints_odd_constraint_odd_dims_str(self):
+    """Tests printing out the set with odd constraints and odd dimensions."""
+    self.MakePWithDims(num_constraints=5, num_dims=3)
+    self.assertEqual('[[ 0.  0.  0.]            [[ 0.]  \n'
+                     ' [ 0.  0.  0.]  [[x0]      [ 0.]  \n'
+                     ' [ 0.  0.  0.]   [x1]  <=  [ 0.]  \n'
+                     ' [ 0.  0.  0.]   [x2]]     [ 0.]  \n'
+                     ' [ 0.  0.  0.]]            [ 0.]] ',
+                     str(self.p))
+
+  def test_many_constraints_even_constraint_odd_dims_str(self):
+    """Tests printing out the set with even constraints and odd dimensions."""
+    self.MakePWithDims(num_constraints=2, num_dims=3)
+    self.assertEqual('[[ 0.  0.  0.]  [[x0]     [[ 0.]  \n'
+                     ' [ 0.  0.  0.]]  [x1]  <=  [ 0.]] \n'
+                     '                 [x2]]            ',
+                     str(self.p))
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/frc971/control_loops/state_feedback_loop.h b/frc971/control_loops/state_feedback_loop.h
new file mode 100644
index 0000000..6ebd32e
--- /dev/null
+++ b/frc971/control_loops/state_feedback_loop.h
@@ -0,0 +1,428 @@
+#ifndef FRC971_CONTROL_LOOPS_STATE_FEEDBACK_LOOP_H_
+#define FRC971_CONTROL_LOOPS_STATE_FEEDBACK_LOOP_H_
+
+#include <assert.h>
+
+#include <vector>
+#include <memory>
+#include <iostream>
+
+#include "Eigen/Dense"
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/macros.h"
+
+// For everything in this file, "inputs" and "outputs" are defined from the
+// perspective of the plant. This means U is an input and Y is an output
+// (because you give the plant U (powers) and it gives you back a Y (sensor
+// values). This is the opposite of what they mean from the perspective of the
+// controller (U is an output because that's what goes to the motors and Y is an
+// input because that's what comes back from the sensors).
+
+template <int number_of_states, int number_of_inputs, int number_of_outputs>
+class StateFeedbackPlantCoefficients final {
+ public:
+  EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
+
+  StateFeedbackPlantCoefficients(const StateFeedbackPlantCoefficients &other)
+      : A_(other.A()),
+        B_(other.B()),
+        C_(other.C()),
+        D_(other.D()),
+        U_min_(other.U_min()),
+        U_max_(other.U_max()) {
+  }
+
+  StateFeedbackPlantCoefficients(
+      const Eigen::Matrix<double, number_of_states, number_of_states> &A,
+      const Eigen::Matrix<double, number_of_states, number_of_inputs> &B,
+      const Eigen::Matrix<double, number_of_outputs, number_of_states> &C,
+      const Eigen::Matrix<double, number_of_outputs, number_of_inputs> &D,
+      const Eigen::Matrix<double, number_of_inputs, 1> &U_max,
+      const Eigen::Matrix<double, number_of_inputs, 1> &U_min)
+      : A_(A),
+        B_(B),
+        C_(C),
+        D_(D),
+        U_min_(U_min),
+        U_max_(U_max) {
+  }
+
+  const Eigen::Matrix<double, number_of_states, number_of_states> &A() const {
+    return A_;
+  }
+  double A(int i, int j) const { return A()(i, j); }
+  const Eigen::Matrix<double, number_of_states, number_of_inputs> &B() const {
+    return B_;
+  }
+  double B(int i, int j) const { return B()(i, j); }
+  const Eigen::Matrix<double, number_of_outputs, number_of_states> &C() const {
+    return C_;
+  }
+  double C(int i, int j) const { return C()(i, j); }
+  const Eigen::Matrix<double, number_of_outputs, number_of_inputs> &D() const {
+    return D_;
+  }
+  double D(int i, int j) const { return D()(i, j); }
+  const Eigen::Matrix<double, number_of_inputs, 1> &U_min() const {
+    return U_min_;
+  }
+  double U_min(int i, int j) const { return U_min()(i, j); }
+  const Eigen::Matrix<double, number_of_inputs, 1> &U_max() const {
+    return U_max_;
+  }
+  double U_max(int i, int j) const { return U_max()(i, j); }
+
+ private:
+  const Eigen::Matrix<double, number_of_states, number_of_states> A_;
+  const Eigen::Matrix<double, number_of_states, number_of_inputs> B_;
+  const Eigen::Matrix<double, number_of_outputs, number_of_states> C_;
+  const Eigen::Matrix<double, number_of_outputs, number_of_inputs> D_;
+  const Eigen::Matrix<double, number_of_inputs, 1> U_min_;
+  const Eigen::Matrix<double, number_of_inputs, 1> U_max_;
+
+  StateFeedbackPlantCoefficients &operator=(
+      StateFeedbackPlantCoefficients other) = delete;
+};
+
+template <int number_of_states, int number_of_inputs, int number_of_outputs>
+class StateFeedbackPlant {
+ public:
+  EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
+
+  StateFeedbackPlant(
+      ::std::vector< ::std::unique_ptr<StateFeedbackPlantCoefficients<
+          number_of_states, number_of_inputs, number_of_outputs>>> *
+          coefficients)
+      : coefficients_(::std::move(*coefficients)), plant_index_(0) {
+    Reset();
+  }
+
+  StateFeedbackPlant(StateFeedbackPlant &&other)
+      : plant_index_(other.plant_index_) {
+    ::std::swap(coefficients_, other.coefficients_);
+    X_.swap(other.X_);
+    Y_.swap(other.Y_);
+    U_.swap(other.U_);
+  }
+
+  virtual ~StateFeedbackPlant() {}
+
+  const Eigen::Matrix<double, number_of_states, number_of_states> &A() const {
+    return coefficients().A();
+  }
+  double A(int i, int j) const { return A()(i, j); }
+  const Eigen::Matrix<double, number_of_states, number_of_inputs> &B() const {
+    return coefficients().B();
+  }
+  double B(int i, int j) const { return B()(i, j); }
+  const Eigen::Matrix<double, number_of_outputs, number_of_states> &C() const {
+    return coefficients().C();
+  }
+  double C(int i, int j) const { return C()(i, j); }
+  const Eigen::Matrix<double, number_of_outputs, number_of_inputs> &D() const {
+    return coefficients().D();
+  }
+  double D(int i, int j) const { return D()(i, j); }
+  const Eigen::Matrix<double, number_of_inputs, 1> &U_min() const {
+    return coefficients().U_min();
+  }
+  double U_min(int i, int j) const { return U_min()(i, j); }
+  const Eigen::Matrix<double, number_of_inputs, 1> &U_max() const {
+    return coefficients().U_max();
+  }
+  double U_max(int i, int j) const { return U_max()(i, j); }
+
+  const Eigen::Matrix<double, number_of_states, 1> &X() const { return X_; }
+  double X(int i, int j) const { return X()(i, j); }
+  const Eigen::Matrix<double, number_of_outputs, 1> &Y() const { return Y_; }
+  double Y(int i, int j) const { return Y()(i, j); }
+  const Eigen::Matrix<double, number_of_inputs, 1> &U() const { return U_; }
+  double U(int i, int j) const { return U()(i, j); }
+
+  Eigen::Matrix<double, number_of_states, 1> &mutable_X() { return X_; }
+  double &mutable_X(int i, int j) { return mutable_X()(i, j); }
+  Eigen::Matrix<double, number_of_outputs, 1> &mutable_Y() { return Y_; }
+  double &mutable_Y(int i, int j) { return mutable_Y()(i, j); }
+  Eigen::Matrix<double, number_of_inputs, 1> &mutable_U() { return U_; }
+  double &mutable_U(int i, int j) { return mutable_U()(i, j); }
+
+  const StateFeedbackPlantCoefficients<
+      number_of_states, number_of_inputs, number_of_outputs>
+          &coefficients() const {
+    return *coefficients_[plant_index_];
+  }
+
+  int plant_index() const { return plant_index_; }
+  void set_plant_index(int plant_index) {
+    if (plant_index < 0) {
+      plant_index_ = 0;
+    } else if (plant_index >= static_cast<int>(coefficients_.size())) {
+      plant_index_ = static_cast<int>(coefficients_.size()) - 1;
+    } else {
+      plant_index_ = plant_index;
+    }
+  }
+
+  void Reset() {
+    X_.setZero();
+    Y_.setZero();
+    U_.setZero();
+  }
+
+  // Assert that U is within the hardware range.
+  virtual void CheckU() {
+    for (int i = 0; i < kNumInputs; ++i) {
+      assert(U(i, 0) <= U_max(i, 0) + 0.00001);
+      assert(U(i, 0) >= U_min(i, 0) - 0.00001);
+    }
+  }
+
+  // Computes the new X and Y given the control input.
+  void Update() {
+    // Powers outside of the range are more likely controller bugs than things
+    // that the plant should deal with.
+    CheckU();
+    X_ = A() * X() + B() * U();
+    Y_ = C() * X() + D() * U();
+  }
+
+ protected:
+  // these are accessible from non-templated subclasses
+  static const int kNumStates = number_of_states;
+  static const int kNumOutputs = number_of_outputs;
+  static const int kNumInputs = number_of_inputs;
+
+ private:
+  Eigen::Matrix<double, number_of_states, 1> X_;
+  Eigen::Matrix<double, number_of_outputs, 1> Y_;
+  Eigen::Matrix<double, number_of_inputs, 1> U_;
+
+  ::std::vector< ::std::unique_ptr<StateFeedbackPlantCoefficients<
+      number_of_states, number_of_inputs, number_of_outputs>>> coefficients_;
+
+  int plant_index_;
+
+  DISALLOW_COPY_AND_ASSIGN(StateFeedbackPlant);
+};
+
+// A Controller is a structure which holds a plant and the K and L matrices.
+// This is designed such that multiple controllers can share one set of state to
+// support gain scheduling easily.
+template <int number_of_states, int number_of_inputs, int number_of_outputs>
+struct StateFeedbackController final {
+  EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
+
+  const Eigen::Matrix<double, number_of_states, number_of_outputs> L;
+  const Eigen::Matrix<double, number_of_inputs, number_of_states> K;
+  const Eigen::Matrix<double, number_of_states, number_of_states> A_inv;
+  StateFeedbackPlantCoefficients<number_of_states, number_of_inputs,
+                                 number_of_outputs> plant;
+
+  StateFeedbackController(
+      const Eigen::Matrix<double, number_of_states, number_of_outputs> &L,
+      const Eigen::Matrix<double, number_of_inputs, number_of_states> &K,
+      const Eigen::Matrix<double, number_of_states, number_of_states> &A_inv,
+      const StateFeedbackPlantCoefficients<number_of_states, number_of_inputs,
+                                           number_of_outputs> &plant)
+      : L(L),
+        K(K),
+        A_inv(A_inv),
+        plant(plant) {
+  }
+};
+
+template <int number_of_states, int number_of_inputs, int number_of_outputs>
+class StateFeedbackLoop {
+ public:
+  EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
+
+  StateFeedbackLoop(const StateFeedbackController<
+      number_of_states, number_of_inputs, number_of_outputs> &controller)
+      : controller_index_(0) {
+    controllers_.emplace_back(new StateFeedbackController<
+        number_of_states, number_of_inputs, number_of_outputs>(controller));
+    Reset();
+  }
+
+  StateFeedbackLoop(
+      const Eigen::Matrix<double, number_of_states, number_of_outputs> &L,
+      const Eigen::Matrix<double, number_of_inputs, number_of_states> &K,
+      const Eigen::Matrix<double, number_of_states, number_of_states> &A_inv,
+      const StateFeedbackPlantCoefficients<number_of_states, number_of_inputs,
+                               number_of_outputs> &plant)
+      : controller_index_(0) {
+    controllers_.emplace_back(
+        new StateFeedbackController<number_of_states, number_of_inputs,
+                                    number_of_outputs>(L, K, A_inv, plant));
+
+    Reset();
+  }
+
+  StateFeedbackLoop(::std::vector< ::std::unique_ptr<StateFeedbackController<
+      number_of_states, number_of_inputs, number_of_outputs>>> *controllers)
+      : controllers_(::std::move(*controllers)), controller_index_(0) {
+    Reset();
+  }
+
+  StateFeedbackLoop(StateFeedbackLoop &&other) {
+    X_hat_.swap(other.X_hat_);
+    R_.swap(other.R_);
+    U_.swap(other.U_);
+    U_uncapped_.swap(other.U_uncapped_);
+    ::std::swap(controllers_, other.controllers_);
+    controller_index_ = other.controller_index_;
+  }
+
+  virtual ~StateFeedbackLoop() {}
+
+  const Eigen::Matrix<double, number_of_states, number_of_states> &A() const {
+    return controller().plant.A();
+  }
+  double A(int i, int j) const { return A()(i, j); }
+  const Eigen::Matrix<double, number_of_states, number_of_inputs> &B() const {
+    return controller().plant.B();
+  }
+  const Eigen::Matrix<double, number_of_states, number_of_states> &A_inv() const {
+    return controller().A_inv;
+  }
+  double A_inv(int i, int j) const { return A_inv()(i, j); }
+  double B(int i, int j) const { return B()(i, j); }
+  const Eigen::Matrix<double, number_of_outputs, number_of_states> &C() const {
+    return controller().plant.C();
+  }
+  double C(int i, int j) const { return C()(i, j); }
+  const Eigen::Matrix<double, number_of_outputs, number_of_inputs> &D() const {
+    return controller().plant.D();
+  }
+  double D(int i, int j) const { return D()(i, j); }
+  const Eigen::Matrix<double, number_of_inputs, 1> &U_min() const {
+    return controller().plant.U_min();
+  }
+  double U_min(int i, int j) const { return U_min()(i, j); }
+  const Eigen::Matrix<double, number_of_inputs, 1> &U_max() const {
+    return controller().plant.U_max();
+  }
+  double U_max(int i, int j) const { return U_max()(i, j); }
+
+  const Eigen::Matrix<double, number_of_inputs, number_of_states> &K() const {
+    return controller().K;
+  }
+  double K(int i, int j) const { return K()(i, j); }
+  const Eigen::Matrix<double, number_of_states, number_of_outputs> &L() const {
+    return controller().L;
+  }
+  double L(int i, int j) const { return L()(i, j); }
+
+  const Eigen::Matrix<double, number_of_states, 1> &X_hat() const {
+    return X_hat_;
+  }
+  double X_hat(int i, int j) const { return X_hat()(i, j); }
+  const Eigen::Matrix<double, number_of_states, 1> &R() const { return R_; }
+  double R(int i, int j) const { return R()(i, j); }
+  const Eigen::Matrix<double, number_of_inputs, 1> &U() const { return U_; }
+  double U(int i, int j) const { return U()(i, j); }
+  const Eigen::Matrix<double, number_of_inputs, 1> &U_uncapped() const {
+    return U_uncapped_;
+  }
+  double U_uncapped(int i, int j) const { return U_uncapped()(i, j); }
+
+  Eigen::Matrix<double, number_of_states, 1> &mutable_X_hat() { return X_hat_; }
+  double &mutable_X_hat(int i, int j) { return mutable_X_hat()(i, j); }
+  Eigen::Matrix<double, number_of_states, 1> &mutable_R() { return R_; }
+  double &mutable_R(int i, int j) { return mutable_R()(i, j); }
+  Eigen::Matrix<double, number_of_inputs, 1> &mutable_U() { return U_; }
+  double &mutable_U(int i, int j) { return mutable_U()(i, j); }
+  Eigen::Matrix<double, number_of_inputs, 1> &mutable_U_uncapped() {
+    return U_uncapped_;
+  }
+  double &mutable_U_uncapped(int i, int j) {
+    return mutable_U_uncapped()(i, j);
+  }
+
+  const StateFeedbackController<number_of_states, number_of_inputs,
+                                number_of_outputs> &controller() const {
+    return *controllers_[controller_index_];
+  }
+
+  const StateFeedbackController<number_of_states, number_of_inputs,
+                                number_of_outputs> &controller(
+                                    int index) const {
+    return *controllers_[index];
+  }
+
+  void Reset() {
+    X_hat_.setZero();
+    R_.setZero();
+    U_.setZero();
+    U_uncapped_.setZero();
+  }
+
+  // If U is outside the hardware range, limit it before the plant tries to use
+  // it.
+  virtual void CapU() {
+    for (int i = 0; i < kNumInputs; ++i) {
+      if (U(i, 0) > U_max(i, 0)) {
+        U_(i, 0) = U_max(i, 0);
+      } else if (U(i, 0) < U_min(i, 0)) {
+        U_(i, 0) = U_min(i, 0);
+      }
+    }
+  }
+
+  // Corrects X_hat given the observation in Y.
+  void Correct(const Eigen::Matrix<double, number_of_outputs, 1> &Y) {
+    X_hat_ += A_inv() * L() * (Y - C() * X_hat_ - D() * U());
+  }
+
+  // stop_motors is whether or not to output all 0s.
+  void Update(bool stop_motors) {
+    if (stop_motors) {
+      U_.setZero();
+      U_uncapped_.setZero();
+    } else {
+      U_ = U_uncapped_ = K() * (R() - X_hat());
+      CapU();
+    }
+
+    UpdateObserver();
+  }
+
+  void UpdateObserver() {
+    X_hat_ = A() * X_hat() + B() * U();
+  }
+
+  // Sets the current controller to be index, clamped to be within range.
+  void set_controller_index(int index) {
+    if (index < 0) {
+      controller_index_ = 0;
+    } else if (index >= static_cast<int>(controllers_.size())) {
+      controller_index_ = static_cast<int>(controllers_.size()) - 1;
+    } else {
+      controller_index_ = index;
+    }
+  }
+
+  int controller_index() const { return controller_index_; }
+
+ protected:
+  ::std::vector< ::std::unique_ptr<StateFeedbackController<
+      number_of_states, number_of_inputs, number_of_outputs>>> controllers_;
+
+  // These are accessible from non-templated subclasses.
+  static const int kNumStates = number_of_states;
+  static const int kNumOutputs = number_of_outputs;
+  static const int kNumInputs = number_of_inputs;
+
+ private:
+  Eigen::Matrix<double, number_of_states, 1> X_hat_;
+  Eigen::Matrix<double, number_of_states, 1> R_;
+  Eigen::Matrix<double, number_of_inputs, 1> U_;
+  Eigen::Matrix<double, number_of_inputs, 1> U_uncapped_;
+
+  int controller_index_;
+
+  DISALLOW_COPY_AND_ASSIGN(StateFeedbackLoop);
+};
+
+#endif  // FRC971_CONTROL_LOOPS_STATE_FEEDBACK_LOOP_H_
diff --git a/frc971/control_loops/state_feedback_loop_test.cc b/frc971/control_loops/state_feedback_loop_test.cc
new file mode 100644
index 0000000..f355b6d
--- /dev/null
+++ b/frc971/control_loops/state_feedback_loop_test.cc
@@ -0,0 +1,49 @@
+#include "frc971/control_loops/state_feedback_loop.h"
+
+#include "gtest/gtest.h"
+
+namespace testing {
+
+// Tests that everything compiles and nothing crashes even if
+// number_of_inputs!=number_of_outputs.
+// There used to be lots of bugs in this area.
+TEST(StateFeedbackLoopTest, UnequalSizes) {
+  // In general, most (all?) errors will make these statements either not
+  // compile or have assertion failures at runtime.
+  const StateFeedbackPlantCoefficients<2, 4, 7> coefficients(
+      Eigen::Matrix<double, 2, 2>::Identity(),
+      Eigen::Matrix<double, 2, 4>::Identity(),
+      Eigen::Matrix<double, 7, 2>::Identity(),
+      Eigen::Matrix<double, 7, 4>::Identity(),
+      Eigen::Matrix<double, 4, 1>::Constant(1),
+      Eigen::Matrix<double, 4, 1>::Constant(-1));
+
+  {
+    ::std::vector< ::std::unique_ptr<StateFeedbackPlantCoefficients<2, 4, 7>>> v;
+    v.emplace_back(new StateFeedbackPlantCoefficients<2, 4, 7>(coefficients));
+    StateFeedbackPlant<2, 4, 7> plant(&v);
+    plant.Update();
+    plant.Reset();
+    plant.CheckU();
+  }
+  {
+    StateFeedbackLoop<2, 4, 7> test_loop(StateFeedbackController<2, 4, 7>(
+        Eigen::Matrix<double, 2, 7>::Identity(),
+        Eigen::Matrix<double, 4, 2>::Identity(),
+        Eigen::Matrix<double, 2, 2>::Identity(), coefficients));
+    test_loop.Correct(Eigen::Matrix<double, 7, 1>::Identity());
+    test_loop.Update(false);
+    test_loop.CapU();
+  }
+  {
+    StateFeedbackLoop<2, 4, 7> test_loop(
+        Eigen::Matrix<double, 2, 7>::Identity(),
+        Eigen::Matrix<double, 4, 2>::Identity(),
+        Eigen::Matrix<double, 2, 2>::Identity(), coefficients);
+    test_loop.Correct(Eigen::Matrix<double, 7, 1>::Identity());
+    test_loop.Update(false);
+    test_loop.CapU();
+  }
+}
+
+}  // namespace testing
diff --git a/frc971/control_loops/team_number_test_environment.cc b/frc971/control_loops/team_number_test_environment.cc
new file mode 100644
index 0000000..624a119
--- /dev/null
+++ b/frc971/control_loops/team_number_test_environment.cc
@@ -0,0 +1,15 @@
+#include "frc971/control_loops/team_number_test_environment.h"
+
+#include "aos/common/network/team_number.h"
+
+namespace frc971 {
+namespace control_loops {
+namespace testing {
+
+void TeamNumberEnvironment::SetUp() {
+  ::aos::network::OverrideTeamNumber(kTeamNumber);
+}
+
+}  // namespace testing
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/frc971/control_loops/team_number_test_environment.h b/frc971/control_loops/team_number_test_environment.h
new file mode 100644
index 0000000..f0c1a16
--- /dev/null
+++ b/frc971/control_loops/team_number_test_environment.h
@@ -0,0 +1,30 @@
+#ifndef FRC971_CONTROL_LOOPS_TEAM_NUMBER_TEST_ENVIRONMENT_H_
+#define FRC971_CONTROL_LOOPS_TEAM_NUMBER_TEST_ENVIRONMENT_H_
+
+#include "gtest/gtest.h"
+
+namespace frc971 {
+namespace control_loops {
+namespace testing {
+
+// The team number we use for tests.
+static const int kTeamNumber = 1;
+
+// Overrides the team number to kTeamNumber before any test consructors run.
+// This is important for tests which retrieve constants values during
+// construction.
+class TeamNumberEnvironment : public ::testing::Environment {
+ public:
+  void SetUp() override;
+};
+
+// The static variable in a header is intentional. Kind of a hack, undefined
+// order, but that works OK here.
+static ::testing::Environment* const team_number_env =
+    ::testing::AddGlobalTestEnvironment(new TeamNumberEnvironment());
+
+}  // namespace testing
+}  // namespace control_loops
+}  // namespace frc971
+
+#endif  // FRC971_CONTROL_LOOPS_TEAM_NUMBER_TEST_ENVIRONMENT_H_
diff --git a/frc971/control_loops/voltage_cap/voltage_cap.cc b/frc971/control_loops/voltage_cap/voltage_cap.cc
new file mode 100644
index 0000000..3de5828
--- /dev/null
+++ b/frc971/control_loops/voltage_cap/voltage_cap.cc
@@ -0,0 +1,95 @@
+#include "voltage_cap.h"
+
+#include <limits>
+
+namespace frc971 {
+namespace control_loops {
+
+void VoltageCap(double max_voltage, double voltage_one, double voltage_two,
+                double *out_voltage_one, double *out_voltage_two) {
+  *out_voltage_one = *out_voltage_two =
+      ::std::numeric_limits<double>::quiet_NaN();
+  if (voltage_one <= max_voltage && voltage_two <= max_voltage &&
+      voltage_one >= -max_voltage && voltage_two >= -max_voltage) {
+    *out_voltage_one = voltage_one;
+    *out_voltage_two = voltage_two;
+  } else if (voltage_one - voltage_two > 2 * max_voltage) {
+    //(voltage_one is larger)
+    // if the difference between the two voltages is more than 24 we know a
+    // 45degree slope will not intersect the 'box'
+    *out_voltage_one = max_voltage;
+    *out_voltage_two = -max_voltage;
+    // top left corner of 'box'
+  } else if (voltage_one - voltage_two < -2 * max_voltage) {
+    //(voltage_two is larger)
+    // if the difference between the two voltages is less than -24 we know a
+    //  45degree slope will not intersect the 'box'
+    *out_voltage_one = -max_voltage;
+    *out_voltage_two = max_voltage;
+    // bottom right corner of 'box'
+  } else {
+    if (voltage_one >= 0) {
+      if (voltage_two >= 0) {
+        // Quadrant 1
+        if (voltage_one > voltage_two) {
+          // Above box
+          double difference = voltage_one - voltage_two;
+          *out_voltage_one = max_voltage;
+          *out_voltage_two = max_voltage - difference;
+        } else {
+          // Right of box
+          double difference = voltage_two - voltage_one;
+          *out_voltage_one = max_voltage - difference;
+          *out_voltage_two = max_voltage;
+        }
+      } else {  // voltage_two < 0
+        // Quadrant 2
+        double difference = voltage_one - voltage_two;
+        if (-voltage_two > voltage_one) {
+          // Left of box
+          *out_voltage_one = -max_voltage + difference;
+          *out_voltage_two = -max_voltage;
+        } else {
+          // Above box
+          *out_voltage_one = max_voltage;
+          *out_voltage_two = max_voltage - difference;
+        }
+      }
+    } else {  // voltage_one < 0
+      if (voltage_two <= 0) {
+        // Quadrant 3
+        if (voltage_one < voltage_two) {
+          // Left of Box
+          double difference = voltage_two - voltage_one;
+          *out_voltage_one = -max_voltage;
+          *out_voltage_two = -max_voltage + difference;
+        } else {
+          // Under box
+          double difference = voltage_one - voltage_two;
+          *out_voltage_one = -max_voltage + difference;
+          *out_voltage_two = -max_voltage;
+        }
+      } else {  // voltage_two > 0
+        // Quadrant 4
+        double difference = voltage_two - voltage_one;
+        if (-voltage_one > voltage_two) {
+          // Right of box
+          *out_voltage_one = -max_voltage;
+          *out_voltage_two = -max_voltage + difference;
+        } else {
+          // Under box
+          *out_voltage_one = max_voltage - difference;
+          *out_voltage_two = max_voltage;
+        }
+      }
+    }
+  }
+}
+
+void VoltageCap(double voltage_one, double voltage_two, double *out_voltage_one,
+                double *out_voltage_two) {
+  VoltageCap(12.0, voltage_one, voltage_two, out_voltage_one, out_voltage_two);
+}
+
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/frc971/control_loops/voltage_cap/voltage_cap.gyp b/frc971/control_loops/voltage_cap/voltage_cap.gyp
new file mode 100644
index 0000000..08bd27a
--- /dev/null
+++ b/frc971/control_loops/voltage_cap/voltage_cap.gyp
@@ -0,0 +1,23 @@
+{
+  'targets': [
+    {
+      'target_name': 'voltage_cap',
+      'type': 'static_library',
+      'sources': [
+        'voltage_cap.cc',
+      ],
+    },
+    {
+      'target_name': 'voltage_cap_test',
+      'type': 'executable',
+      'sources': [
+        'voltage_cap_test.cc',
+      ],
+      'dependencies': [
+        'voltage_cap',
+        '<(EXTERNALS):gtest',
+        '<(AOS)/common/common.gyp:queue_testutils',
+      ],
+    },
+  ],
+}
diff --git a/frc971/control_loops/voltage_cap/voltage_cap.h b/frc971/control_loops/voltage_cap/voltage_cap.h
new file mode 100644
index 0000000..49aa9e8
--- /dev/null
+++ b/frc971/control_loops/voltage_cap/voltage_cap.h
@@ -0,0 +1,33 @@
+#ifndef FRC971_CONTROL_LOOPS_VOLTAGE_CAP_VOLTAGE_CAP_H_
+#define FRC971_CONTROL_LOOPS_VOLTAGE_CAP_VOLTAGE_CAP_H_
+
+#include <stdio.h>
+
+namespace frc971 {
+namespace control_loops {
+
+// This function maintains the difference of power between two voltages passed in
+//   that are outside of our range of possible voltage output.
+// This is because we figured that maintaining the difference rather than the ratio
+//   between the voltages would get us to our goal as fast as possible.
+//
+//
+// The 'box' is a box formed on a graph by the maximum and minimun voltages of
+//   voltage_one and voltage_two with
+//   voltage_one on the y-axis and voltage_two on the x-axis.
+// If a line with a slope of one(45degrees) is plotted from the point formed
+//   by graphing voltage_one(y) and voltage_two(x), the first intersecting point of
+//   the box is the maximum voltage that we can output to get to the goal as
+//   fast as possible.
+// If the line does not intersect the box, then we use the closest corner of
+//   the box to the line in either quadrant two or quadrant four of the graph.
+void VoltageCap(double max_voltage, double voltage_one, double voltage_two,
+                double *out_voltage_one, double *out_voltage_two);
+  // Defaults to 12v if no voltage is specified.
+void VoltageCap(double voltage_one, double voltage_two, double *out_voltage_one,
+                double *out_voltage_two);
+
+}  // namespace control_loops
+}  // namespace frc971
+
+#endif  // FRC971_CONTROL_LOOPS_VOLTAGE_CAP_VOLTAGE_CAP_H_
diff --git a/frc971/control_loops/voltage_cap/voltage_cap_test.cc b/frc971/control_loops/voltage_cap/voltage_cap_test.cc
new file mode 100644
index 0000000..f508b25
--- /dev/null
+++ b/frc971/control_loops/voltage_cap/voltage_cap_test.cc
@@ -0,0 +1,253 @@
+#include <unistd.h>
+
+#include "frc971/control_loops/voltage_cap/voltage_cap.h"
+
+#include "gtest/gtest.h"
+#include "aos/common/queue.h"
+#include "aos/common/queue_testutils.h"
+
+using ::aos::time::Time;
+
+namespace frc971 {
+namespace control_loops {
+namespace testing {
+
+class VoltageTest : public ::testing::Test {
+ protected:
+  // Bring up and down Core.
+  ::aos::common::testing::GlobalCoreInstance my_core;
+};
+
+// Tests that voltage inputs return the same if inside the box.
+TEST_F(VoltageTest, BasicVoltage12) {
+  double voltage_one, voltage_two;
+  VoltageCap(12.0, 11.3, 2.6, &voltage_one, &voltage_two);
+  EXPECT_EQ(11.3, voltage_one);
+  EXPECT_EQ(2.6, voltage_two);
+}
+// Tests that voltage inputs in the 4th quadrant both get capped to their
+// maximum.
+TEST_F(VoltageTest, QuadrantFourNoIntersect12) {
+  double voltage_one, voltage_two;
+  VoltageCap(12.0, -50.0, 50, &voltage_one, &voltage_two);
+  EXPECT_EQ(-12.0, voltage_one);
+  EXPECT_EQ(12.0, voltage_two);
+}
+
+// Tests if the difference between two voltages is more than 24.0v then default
+// to the most outputable voltage in that direction.
+TEST_F(VoltageTest, LargeDifference12) {
+  double voltage_one, voltage_two;
+  VoltageCap(12.0, -13.0, 13.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(-12.0, voltage_one);  // just off bottom right corner
+  EXPECT_EQ(12.0, voltage_two);
+
+  VoltageCap(12.0, 13.0, -13.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(12.0, voltage_one);  // just off top left corner
+  EXPECT_EQ(-12.0, voltage_two);
+
+  VoltageCap(12.0, 10.0, 36.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(-12.0, voltage_one);  // 1st quadrant line just off bottom right
+  EXPECT_EQ(12.0, voltage_two);
+
+  VoltageCap(12.0, 10.0, -36.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(12.0, voltage_one);  // 3rd quadrant line just off top left
+  EXPECT_EQ(-12.0, voltage_two);
+}
+
+// Tests that the 45degree angle line intersects the box and returns a value
+// within the box.
+TEST_F(VoltageTest, QuadrantOneIntersect12) {
+  double voltage_one, voltage_two;
+  VoltageCap(12.0, 50.0, 50.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(12.0, voltage_one);  // 45degree angle from origin
+  EXPECT_EQ(12.0, voltage_two);
+
+  voltage_one = 0.0;
+
+  VoltageCap(12.0, 13.0, 11.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(12.0, voltage_one);
+  EXPECT_EQ(10.0, voltage_two);
+}
+TEST_F(VoltageTest, QuadrantTwoIntersect12) {
+  double voltage_one, voltage_two;
+  VoltageCap(12.0, 13.0, -2.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(12.0, voltage_one);
+  EXPECT_EQ(-3.0, voltage_two);
+
+  VoltageCap(12.0, 2.0, -13.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(3.0, voltage_one);
+  EXPECT_EQ(-12.0, voltage_two);
+}
+TEST_F(VoltageTest, QuadrantThreeIntersect12) {
+  double voltage_one, voltage_two;
+  VoltageCap(12.0, -50.0, -50.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(-12.0, voltage_one);  // 45degree angle from origin
+  EXPECT_EQ(-12.0, voltage_two);
+
+  voltage_one = 0.0;
+
+  VoltageCap(12.0, -13.0, -11.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(-12.0, voltage_one);
+  EXPECT_EQ(-10.0, voltage_two);
+}
+TEST_F(VoltageTest, QuadrantFourIntersect12) {
+  double voltage_one, voltage_two;
+  VoltageCap(12.0, -13.0, 2.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(-12.0, voltage_one);
+  EXPECT_EQ(3.0, voltage_two);
+
+  VoltageCap(12.0, -2.0, 13.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(-3.0, voltage_one);
+  EXPECT_EQ(12.0, voltage_two);
+}
+
+// Tests whether cross quadrants works (also supplies additional points to
+// test).
+TEST_F(VoltageTest, QuadrantOneToTwo12) {
+  // Point in Quadrant 1 intersects box in Quadrant 2.
+  double voltage_one, voltage_two;
+  VoltageCap(12.0, 33.0, 11.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(12.0, voltage_one);
+  EXPECT_EQ(-10.0, voltage_two);
+}
+TEST_F(VoltageTest, QuadrantOneToFour12){
+  // Point in Quadrant 1 intersects box in Quadrant 4.
+  double voltage_one, voltage_two;
+  VoltageCap(12.0, 11.0, 33.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(-10.0, voltage_one);
+  EXPECT_EQ(12.0, voltage_two);
+}
+TEST_F(VoltageTest, QuadrantThreeToTwo12) {
+  // Point in Quadrant 3 intersects box in Quadrant 2.
+  double voltage_one, voltage_two;
+  VoltageCap(12.0, -11.0, -33.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(10.0, voltage_one);
+  EXPECT_EQ(-12.0, voltage_two);
+}
+TEST_F(VoltageTest, QuadrantThreeToFour12) {
+  // Point in Quadrant 3 intersects box in Quadrant 4.
+  double voltage_one, voltage_two;
+  VoltageCap(12.0, -33.0, -11.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(-12.0, voltage_one);
+  EXPECT_EQ(10.0, voltage_two);
+}
+
+// Tests that voltage inputs return the same if inside the box.
+TEST_F(VoltageTest, BasicVoltage6) {
+  double voltage_one, voltage_two;
+  VoltageCap(6.0, 5.3, 2.6, &voltage_one, &voltage_two);
+  EXPECT_EQ(5.3, voltage_one);
+  EXPECT_EQ(2.6, voltage_two);
+}
+// Tests that voltage inputs in the 4th quadrant both get capped to their
+// maximum.
+TEST_F(VoltageTest, QuadrantFourNoIntersect6) {
+  double voltage_one, voltage_two;
+  VoltageCap(6.0, -50.0, 50, &voltage_one, &voltage_two);
+  EXPECT_EQ(-6.0, voltage_one);
+  EXPECT_EQ(6.0, voltage_two);
+}
+
+// Tests if the difference between two voltages is more than 12.0v then default
+// to the most outputable voltage in that direction.
+TEST_F(VoltageTest, LargeDifference6) {
+  double voltage_one, voltage_two;
+  VoltageCap(6.0, -13.0, 13.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(-6.0, voltage_one);  // just off bottom right corner
+  EXPECT_EQ(6.0, voltage_two);
+
+  VoltageCap(6.0, 13.0, -13.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(6.0, voltage_one);  // just off top left corner
+  EXPECT_EQ(-6.0, voltage_two);
+
+  VoltageCap(6.0, 10.0, 36.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(-6.0, voltage_one);  // 1st quadrant line just off bottom right
+  EXPECT_EQ(6.0, voltage_two);
+
+  VoltageCap(6.0, 10.0, -36.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(6.0, voltage_one);  // 3rd quadrant line just off top left
+  EXPECT_EQ(-6.0, voltage_two);
+}
+
+// Tests that the 45degree angle line intersects the box and returns a value
+// within the box
+TEST_F(VoltageTest, QuadrantOneIntersect6) {
+  double voltage_one, voltage_two;
+  VoltageCap(6.0, 50.0, 50.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(6.0, voltage_one);  // 45degree angle from origin
+  EXPECT_EQ(6.0, voltage_two);
+
+  voltage_one = 0.0;
+
+  VoltageCap(6.0, 13.0, 11.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(6.0, voltage_one);
+  EXPECT_EQ(4.0, voltage_two);
+}
+TEST_F(VoltageTest, QuadrantTwoIntersect6) {
+  double voltage_one, voltage_two;
+  VoltageCap(6.0, 9.0, -2.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(6.0, voltage_one);
+  EXPECT_EQ(-5.0, voltage_two);
+
+  VoltageCap(6.0, 2.0, -9.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(5.0, voltage_one);
+  EXPECT_EQ(-6.0, voltage_two);
+}
+TEST_F(VoltageTest, QuadrantThreeIntersect6) {
+  double voltage_one, voltage_two;
+  VoltageCap(6.0, -50.0, -50.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(-6.0, voltage_one);  // 45degree angle from origin
+  EXPECT_EQ(-6.0, voltage_two);
+
+  voltage_one = 0.0;
+
+  VoltageCap(6.0, -13.0, -11.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(-6.0, voltage_one);
+  EXPECT_EQ(-4.0, voltage_two);
+}
+TEST_F(VoltageTest, QuadrantFourIntersect6) {
+  double voltage_one, voltage_two;
+  VoltageCap(6.0, -9.0, 2.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(-6.0, voltage_one);
+  EXPECT_EQ(5.0, voltage_two);
+
+  VoltageCap(6.0, -2.0, 9.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(-5.0, voltage_one);
+  EXPECT_EQ(6.0, voltage_two);
+}
+
+// Tests whether cross quadrants works (also supplies additional points to
+// test).
+TEST_F(VoltageTest, QuadrantOneToTwo6) {
+  // Point in Quadrant 1 intersects box in Quadrant 2.
+  double voltage_one, voltage_two;
+  VoltageCap(6.0, 33.0, 22.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(6.0, voltage_one);
+  EXPECT_EQ(-5.0, voltage_two);
+}
+TEST_F(VoltageTest, QuadrantOneToFour6){
+  // Point in Quadrant 1 intersects box in Quadrant 4.
+  double voltage_one, voltage_two;
+  VoltageCap(6.0, 22.0, 33.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(-5.0, voltage_one);
+  EXPECT_EQ(6.0, voltage_two);
+}
+TEST_F(VoltageTest, QuadrantThreeToTw6) {
+  // Point in Quadrant 3 intersects box in Quadrant 2.
+  double voltage_one, voltage_two;
+  VoltageCap(6.0, -22.0, -33.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(5.0, voltage_one);
+  EXPECT_EQ(-6.0, voltage_two);
+}
+TEST_F(VoltageTest, QuadrantThreeToFour6) {
+  // Point in Quadrant 3 intersects box in Quadrant 4.
+  double voltage_one, voltage_two;
+  VoltageCap(6.0, -33.0, -22.0, &voltage_one, &voltage_two);
+  EXPECT_EQ(-6.0, voltage_one);
+  EXPECT_EQ(5.0, voltage_two);
+}
+
+}  // namespace testing
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/frc971/control_loops/zeroed_joint.h b/frc971/control_loops/zeroed_joint.h
new file mode 100644
index 0000000..f25434f
--- /dev/null
+++ b/frc971/control_loops/zeroed_joint.h
@@ -0,0 +1,457 @@
+#ifndef FRC971_CONTROL_LOOPS_ZEROED_JOINT_H_
+#define FRC971_CONTROL_LOOPS_ZEROED_JOINT_H_
+
+#include <memory>
+
+#include "aos/common/controls/control_loop.h"
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace frc971 {
+namespace control_loops {
+namespace testing {
+class WristTest_NoWindupPositive_Test;
+class WristTest_NoWindupNegative_Test;
+};
+
+// Note: Everything in this file assumes that there is a 1 cycle delay between
+// power being requested and it showing up at the motor.  It assumes that
+// X_hat(2, 1) is the voltage being applied as well.  It will go unstable if
+// that isn't true.
+
+template<int kNumZeroSensors>
+class ZeroedJoint;
+
+// This class implements the CapU function correctly given all the extra
+// information that we know about from the wrist motor.
+template<int kNumZeroSensors>
+class ZeroedStateFeedbackLoop : public StateFeedbackLoop<3, 1, 1> {
+ public:
+  ZeroedStateFeedbackLoop(StateFeedbackLoop<3, 1, 1> loop,
+                          ZeroedJoint<kNumZeroSensors> *zeroed_joint)
+      : StateFeedbackLoop<3, 1, 1>(loop),
+        zeroed_joint_(zeroed_joint),
+        voltage_(0.0),
+        last_voltage_(0.0) {
+  }
+
+  // Caps U, but this time respects the state of the wrist as well.
+  virtual void CapU();
+
+  // Returns the accumulated voltage.
+  double voltage() const { return voltage_; }
+
+  // Returns the uncapped voltage.
+  double uncapped_voltage() const { return uncapped_voltage_; }
+
+  // Zeros the accumulator.
+  void ZeroPower() { voltage_ = 0.0; }
+ private:
+  ZeroedJoint<kNumZeroSensors> *zeroed_joint_;
+
+  // The accumulated voltage to apply to the motor.
+  double voltage_;
+  double last_voltage_;
+  double uncapped_voltage_;
+};
+
+template<int kNumZeroSensors>
+void ZeroedStateFeedbackLoop<kNumZeroSensors>::CapU() {
+  const double old_voltage = voltage_;
+  voltage_ += U(0, 0);
+
+  uncapped_voltage_ = voltage_;
+
+  // Do all our computations with the voltage, and then compute what the delta
+  // is to make that happen.
+  if (zeroed_joint_->state_ == ZeroedJoint<kNumZeroSensors>::READY) {
+    if (Y(0, 0) >= zeroed_joint_->config_data_.upper_limit) {
+      voltage_ = std::min(0.0, voltage_);
+    }
+    if (Y(0, 0) <= zeroed_joint_->config_data_.lower_limit) {
+      voltage_ = std::max(0.0, voltage_);
+    }
+  }
+
+  const bool is_ready =
+      zeroed_joint_->state_ == ZeroedJoint<kNumZeroSensors>::READY;
+  double limit = is_ready ?
+      12.0 : zeroed_joint_->config_data_.max_zeroing_voltage;
+
+  // Make sure that reality and the observer can't get too far off.  There is a
+  // delay by one cycle between the applied voltage and X_hat(2, 0), so compare
+  // against last cycle's voltage.
+  if (X_hat(2, 0) > last_voltage_ + 2.0) {
+    //X_hat(2, 0) = last_voltage_ + 2.0;
+    voltage_ -= X_hat(2, 0) - (last_voltage_ + 2.0);
+    LOG(DEBUG, "X_hat(2, 0) = %f\n", X_hat(2, 0));
+  } else if (X_hat(2, 0) < last_voltage_ -2.0) {
+    //X_hat(2, 0) = last_voltage_ - 2.0;
+    voltage_ += X_hat(2, 0) - (last_voltage_ - 2.0);
+    LOG(DEBUG, "X_hat(2, 0) = %f\n", X_hat(2, 0));
+  }
+
+  voltage_ = std::min(limit, voltage_);
+  voltage_ = std::max(-limit, voltage_);
+  U(0, 0) = voltage_ - old_voltage;
+  LOG(DEBUG, "abc %f\n", X_hat(2, 0) - voltage_);
+  LOG(DEBUG, "error %f\n", X_hat(0, 0) - R(0, 0));
+
+  last_voltage_ = voltage_;
+}
+
+
+// Class to zero and control a joint with any number of zeroing sensors with a
+// state feedback controller.
+template<int kNumZeroSensors>
+class ZeroedJoint {
+ public:
+  // Sturcture to hold the hardware configuration information.
+  struct ConfigurationData {
+    // Angle at the lower hardware limit.
+    double lower_limit;
+    // Angle at the upper hardware limit.
+    double upper_limit;
+    // Speed (and direction) to move while zeroing.
+    double zeroing_speed;
+    // Speed (and direction) to move while moving off the sensor.
+    double zeroing_off_speed;
+    // Maximum voltage to apply when zeroing.
+    double max_zeroing_voltage;
+    // Deadband voltage.
+    double deadband_voltage;
+    // Angles where we see a positive edge from the hall effect sensors.
+    double hall_effect_start_angle[kNumZeroSensors];
+  };
+
+  // Current position data for the encoder and hall effect information.
+  struct PositionData {
+    // Current encoder position.
+    double position;
+    // Array of hall effect values.
+    bool hall_effects[kNumZeroSensors];
+    // Array of the last positive edge position for the sensors.
+    double hall_effect_positions[kNumZeroSensors];
+  };
+
+  ZeroedJoint(StateFeedbackLoop<3, 1, 1> loop)
+      : loop_(new ZeroedStateFeedbackLoop<kNumZeroSensors>(loop, this)),
+        last_good_time_(0, 0),
+        state_(UNINITIALIZED),
+        error_count_(0),
+        zero_offset_(0.0),
+        capped_goal_(false) {
+  }
+
+  // Copies the provided configuration data locally.
+  void set_config_data(const ConfigurationData &config_data) {
+    config_data_ = config_data;
+  }
+
+  // Clips the goal to be inside the limits and returns the clipped goal.
+  // Requires the constants to have already been fetched.
+  double ClipGoal(double goal) const {
+    return ::std::min(config_data_.upper_limit,
+                      std::max(config_data_.lower_limit, goal));
+  }
+
+  // Updates the loop and state machine.
+  // position is null if the position data is stale, output_enabled is true if
+  // the output will actually go to the motors, and goal_angle and goal_velocity
+  // are the goal position and velocities.
+  double Update(const ZeroedJoint<kNumZeroSensors>::PositionData *position,
+                bool output_enabled,
+                double goal_angle, double goal_velocity);
+
+  // True if the code is zeroing.
+  bool is_zeroing() const { return state_ == ZEROING; }
+
+  // True if the code is moving off the hall effect.
+  bool is_moving_off() const { return state_ == MOVING_OFF; }
+
+  // True if the state machine is uninitialized.
+  bool is_uninitialized() const { return state_ == UNINITIALIZED; }
+
+  // True if the state machine is ready.
+  bool is_ready() const { return state_ == READY; }
+
+  // Returns the uncapped voltage.
+  double U_uncapped() const { return loop_->U_uncapped(0, 0); }
+
+  // True if the goal was moved to avoid goal windup.
+  bool capped_goal() const { return capped_goal_; }
+
+  // Timestamp
+  static const double dt;
+
+  double absolute_position() const { return loop_->X_hat(0, 0); }
+
+ private:
+  friend class ZeroedStateFeedbackLoop<kNumZeroSensors>;
+  // Friend the wrist test cases so that they can simulate windeup.
+  friend class testing::WristTest_NoWindupPositive_Test;
+  friend class testing::WristTest_NoWindupNegative_Test;
+
+  static const ::aos::time::Time kRezeroTime;
+
+  // The state feedback control loop to talk to.
+  ::std::unique_ptr<ZeroedStateFeedbackLoop<kNumZeroSensors>> loop_;
+
+  ConfigurationData config_data_;
+
+  ::aos::time::Time last_good_time_;
+
+  // Returns the index of the first active sensor, or -1 if none are active.
+  int ActiveSensorIndex(
+      const ZeroedJoint<kNumZeroSensors>::PositionData *position) {
+    if (!position) {
+      return -1;
+    }
+    int active_index = -1;
+    for (int i = 0; i < kNumZeroSensors; ++i) {
+      if (position->hall_effects[i]) {
+        if (active_index != -1) {
+          LOG(ERROR, "More than one hall effect sensor is active\n");
+        } else {
+          active_index = i;
+        }
+      }
+    }
+    return active_index;
+  }
+  // Returns true if any of the sensors are active.
+  bool AnySensorsActive(
+      const ZeroedJoint<kNumZeroSensors>::PositionData *position) {
+    return ActiveSensorIndex(position) != -1;
+  }
+
+  // Enum to store the state of the internal zeroing state machine.
+  enum State {
+    UNINITIALIZED,
+    MOVING_OFF,
+    ZEROING,
+    READY,
+    ESTOP
+  };
+
+  // Internal state for zeroing.
+  State state_;
+
+  // Missed position packet count.
+  int error_count_;
+  // Offset from the raw encoder value to the absolute angle.
+  double zero_offset_;
+  // Position that gets incremented when zeroing the wrist to slowly move it to
+  // the hall effect sensor.
+  double zeroing_position_;
+  // Last position at which the hall effect sensor was off.
+  double last_off_position_;
+
+  // True if the zeroing goal was capped during this cycle.
+  bool capped_goal_;
+
+  // Returns true if number is between first and second inclusive.
+  bool is_between(double first, double second, double number) {
+    if ((number >= first || number >= second) &&
+        (number <= first || number <= second)) {
+      return true;
+    }
+    return false;
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(ZeroedJoint);
+};
+
+template <int kNumZeroSensors>
+const ::aos::time::Time ZeroedJoint<kNumZeroSensors>::kRezeroTime =
+    ::aos::time::Time::InSeconds(2);
+
+template <int kNumZeroSensors>
+/*static*/ const double ZeroedJoint<kNumZeroSensors>::dt = 0.01;
+
+// Updates the zeroed joint controller and state machine.
+template <int kNumZeroSensors>
+double ZeroedJoint<kNumZeroSensors>::Update(
+    const ZeroedJoint<kNumZeroSensors>::PositionData *position,
+    bool output_enabled,
+    double goal_angle, double goal_velocity) {
+  // Uninitialize the bot if too many cycles pass without an encoder.
+  if (position == NULL) {
+    LOG(WARNING, "no new pos given\n");
+    error_count_++;
+  }
+  if (error_count_ >= 4) {
+    output_enabled = false;
+    LOG(WARNING, "err_count is %d so disabling\n", error_count_);
+
+    if ((::aos::time::Time::Now() - last_good_time_) > kRezeroTime) {
+      LOG(WARNING, "err_count is %d (or 1st time) so forcing a re-zero\n",
+          error_count_);
+      state_ = UNINITIALIZED;
+      loop_->Reset();
+    }
+  }
+  if (position != NULL) {
+    last_good_time_ = ::aos::time::Time::Now();
+    error_count_ = 0;
+  }
+
+  // Compute the absolute position of the wrist.
+  double absolute_position;
+  if (position) {
+    absolute_position = position->position;
+    if (state_ == READY) {
+      absolute_position -= zero_offset_;
+    }
+    loop_->Y << absolute_position;
+    if (!AnySensorsActive(position)) {
+      last_off_position_ = position->position;
+    }
+  } else {
+    // Dead recon for now.
+    absolute_position = loop_->X_hat(0, 0);
+  }
+
+  switch (state_) {
+    case UNINITIALIZED:
+      LOG(DEBUG, "UNINITIALIZED\n");
+      if (position) {
+        // Reset the zeroing goal.
+        zeroing_position_ = absolute_position;
+        // Clear the observer state.
+        loop_->X_hat << absolute_position, 0.0, 0.0;
+        loop_->ZeroPower();
+        // Set the goal to here to make it so it doesn't move when disabled.
+        loop_->R = loop_->X_hat;
+        // Only progress if we are enabled.
+        if (::aos::joystick_state->enabled) {
+          if (AnySensorsActive(position)) {
+            state_ = MOVING_OFF;
+          } else {
+            state_ = ZEROING;
+          }
+        }
+      }
+      break;
+    case MOVING_OFF:
+      LOG(DEBUG, "MOVING_OFF\n");
+      {
+        // Move off the hall effect sensor.
+        if (!::aos::joystick_state->enabled) {
+          // Start over if disabled.
+          state_ = UNINITIALIZED;
+        } else if (position && !AnySensorsActive(position)) {
+          // We are now off the sensor.  Time to zero now.
+          state_ = ZEROING;
+        } else {
+          // Slowly creep off the sensor.
+          zeroing_position_ -= config_data_.zeroing_off_speed * dt;
+          loop_->R << zeroing_position_, -config_data_.zeroing_off_speed, 0.0;
+          break;
+        }
+      }
+    case ZEROING:
+      LOG(DEBUG, "ZEROING\n");
+      {
+        int active_sensor_index = ActiveSensorIndex(position);
+        if (!::aos::joystick_state->enabled) {
+          // Start over if disabled.
+          state_ = UNINITIALIZED;
+        } else if (position && active_sensor_index != -1) {
+          state_ = READY;
+          // Verify that the calibration number is between the last off position
+          // and the current on position.  If this is not true, move off and try
+          // again.
+          const double calibration =
+              position->hall_effect_positions[active_sensor_index];
+          if (!is_between(last_off_position_, position->position, 
+                          calibration)) {
+            LOG(ERROR, "Got a bogus calibration number.  Trying again.\n");
+            LOG(ERROR,
+                "Last off position was %f, current is %f, calibration is %f\n",
+                last_off_position_, position->position,
+                position->hall_effect_positions[active_sensor_index]);
+            state_ = MOVING_OFF;
+          } else {
+            // Save the zero, and then offset the observer to deal with the
+            // phantom step change.
+            const double old_zero_offset = zero_offset_;
+            zero_offset_ =
+                position->hall_effect_positions[active_sensor_index] -
+                config_data_.hall_effect_start_angle[active_sensor_index];
+            loop_->X_hat(0, 0) += old_zero_offset - zero_offset_;
+            loop_->Y(0, 0) += old_zero_offset - zero_offset_;
+          }
+        } else {
+          // Slowly creep towards the sensor.
+          zeroing_position_ += config_data_.zeroing_speed * dt;
+          loop_->R << zeroing_position_, config_data_.zeroing_speed, 0.0;
+        }
+        break;
+      }
+
+    case READY:
+      LOG(DEBUG, "READY\n");
+      {
+        const double limited_goal = ClipGoal(goal_angle);
+        loop_->R << limited_goal, goal_velocity, 0.0;
+        break;
+      }
+
+    case ESTOP:
+      LOG(DEBUG, "ESTOP\n");
+      LOG(WARNING, "have already given up\n");
+      return 0.0;
+  }
+
+  // Update the observer.
+  loop_->Update(position != NULL, !output_enabled);
+
+  LOG(DEBUG, "X_hat={%f, %f, %f}\n",
+      loop_->X_hat(0, 0), loop_->X_hat(1, 0), loop_->X_hat(2, 0));
+
+  capped_goal_ = false;
+  // Verify that the zeroing goal hasn't run away.
+  switch (state_) {
+    case UNINITIALIZED:
+    case READY:
+    case ESTOP:
+      // Not zeroing.  No worries.
+      break;
+    case MOVING_OFF:
+    case ZEROING:
+      // Check if we have cliped and adjust the goal.
+      if (loop_->uncapped_voltage() > config_data_.max_zeroing_voltage) {
+        double dx = (loop_->uncapped_voltage() -
+                     config_data_.max_zeroing_voltage) / loop_->K(0, 0);
+        zeroing_position_ -= dx;
+        capped_goal_ = true;
+      } else if(loop_->uncapped_voltage() < -config_data_.max_zeroing_voltage) {
+        double dx = (loop_->uncapped_voltage() +
+                     config_data_.max_zeroing_voltage) / loop_->K(0, 0);
+        zeroing_position_ -= dx;
+        capped_goal_ = true;
+      }
+      break;
+  }
+  if (output_enabled) {
+    double voltage = loop_->voltage();
+    if (voltage > 0) {
+      voltage += config_data_.deadband_voltage;
+    } else if (voltage < 0) {
+      voltage -= config_data_.deadband_voltage;
+    }
+    if (voltage > 12.0) {
+      voltage = 12.0;
+    } else if (voltage < -12.0) {
+      voltage = -12.0;
+    }
+    return voltage;
+  } else {
+    return 0.0;
+  }
+}
+
+}  // namespace control_loops
+}  // namespace frc971
+
+#endif  // FRC971_CONTROL_LOOPS_ZEROED_JOINT_H_
diff --git a/frc971/frc971.gyp b/frc971/frc971.gyp
new file mode 100644
index 0000000..0f38180
--- /dev/null
+++ b/frc971/frc971.gyp
@@ -0,0 +1,16 @@
+{
+  'targets': [
+    {
+      'target_name': 'All',
+      'type': 'none',
+      'dependencies': [
+        '<(AOS)/build/aos_all.gyp:Prime',
+
+        'control_loops/control_loops.gyp:state_feedback_loop_test',
+        'control_loops/control_loops.gyp:position_sensor_sim_test',
+        'zeroing/zeroing.gyp:zeroing_test',
+        'control_loops/voltage_cap/voltage_cap.gyp:voltage_cap_test',
+      ],
+    },
+  ],
+}
diff --git a/frc971/queues/gyro.q b/frc971/queues/gyro.q
new file mode 100644
index 0000000..7b234a1
--- /dev/null
+++ b/frc971/queues/gyro.q
@@ -0,0 +1,13 @@
+package frc971.sensors;
+
+message GyroReading {
+	// Positive is counter-clockwise (Austin says "it's Positive").
+	// Right-hand coordinate system around the Z-axis going up.
+	double angle;
+};
+queue GyroReading gyro_reading;
+
+message Uid {
+	uint32_t uid;
+};
+queue Uid gyro_part_id;
diff --git a/frc971/queues/queues.gyp b/frc971/queues/queues.gyp
new file mode 100644
index 0000000..1818f89
--- /dev/null
+++ b/frc971/queues/queues.gyp
@@ -0,0 +1,15 @@
+{
+  'targets': [
+    {
+      'target_name': 'gyro',
+      'type': 'static_library',
+      'sources': [
+        'gyro.q',
+      ],
+      'variables': {
+        'header_path': 'frc971/queues',
+      },
+      'includes': ['../../aos/build/queues.gypi'],
+    },
+  ],
+}
diff --git a/frc971/shifter_hall_effect.h b/frc971/shifter_hall_effect.h
new file mode 100644
index 0000000..aaa5ebd
--- /dev/null
+++ b/frc971/shifter_hall_effect.h
@@ -0,0 +1,21 @@
+#ifndef FRC971_SHIFTER_HALL_EFFECT_H_
+#define FRC971_SHIFTER_HALL_EFFECT_H_
+
+namespace frc971 {
+namespace constants {
+
+// Contains the voltages for an analog hall effect sensor on a shifter.
+struct ShifterHallEffect {
+  // The numbers to use for scaling raw voltages to 0-1.
+  // Low is near 0.0, high is near 1.0
+  double low_gear_middle, low_gear_low;
+  double high_gear_high, high_gear_middle;
+
+  // The numbers for when the dog is clear of each gear.
+  double clear_low, clear_high;
+};
+
+} // constants
+} // frc971
+
+#endif
diff --git a/frc971/wpilib/buffered_pcm.cc b/frc971/wpilib/buffered_pcm.cc
new file mode 100644
index 0000000..084d4b5
--- /dev/null
+++ b/frc971/wpilib/buffered_pcm.cc
@@ -0,0 +1,29 @@
+#include "frc971/wpilib/buffered_pcm.h"
+
+#include <inttypes.h>
+
+#include "aos/common/logging/logging.h"
+
+namespace frc971 {
+namespace wpilib {
+
+::std::unique_ptr<BufferedSolenoid> BufferedPcm::MakeSolenoid(int number) {
+  return ::std::unique_ptr<BufferedSolenoid>(
+      new BufferedSolenoid(number, this));
+}
+
+void BufferedPcm::Set(int number, bool value) {
+  if (value) {
+    values_ |= 1 << number;
+  } else {
+    values_ &= ~(1 << number);
+  }
+}
+
+void BufferedPcm::Flush() {
+  LOG(DEBUG, "sending solenoids 0x%" PRIx8 "\n", values_);
+  SolenoidBase::Set(values_, 0xFF);
+}
+
+}  // namespace wpilib
+}  // namespace frc971
diff --git a/frc971/wpilib/buffered_pcm.h b/frc971/wpilib/buffered_pcm.h
new file mode 100644
index 0000000..50f86fc
--- /dev/null
+++ b/frc971/wpilib/buffered_pcm.h
@@ -0,0 +1,44 @@
+#ifndef FRC971_WPILIB_BUFFERED_PCM_H_
+#define FRC971_WPILIB_BUFFERED_PCM_H_
+
+#include <memory>
+
+#include "SolenoidBase.h"
+
+#include "frc971/wpilib/buffered_solenoid.h"
+
+namespace frc971 {
+namespace wpilib {
+
+// Manages setting values for all solenoids for a single PCM in a single CAN
+// message.
+//
+// The way to use this is to call MakeSolenoid for whichever solenoid numbers
+// you want, call Set on those, and then periodically call Flush on this object
+// to write all of the buffered values out.
+class BufferedPcm : public SolenoidBase {
+ public:
+  explicit BufferedPcm(uint8_t module = GetDefaultSolenoidModule())
+      : SolenoidBase(module) {}
+
+  // Creates a new BufferedSolenoid for a specified port number.
+  ::std::unique_ptr<BufferedSolenoid> MakeSolenoid(int number);
+
+  // Actually sends all of the values out.
+  void Flush();
+
+ private:
+  // WPILib declares this pure virtual and then never calls it...
+  virtual void InitSolenoid() override {}
+
+  void Set(int number, bool value);
+
+  uint8_t values_ = 0;
+
+  friend class BufferedSolenoid;
+};
+
+}  // namespace wpilib
+}  // namespace frc971
+
+#endif  // FRC971_WPILIB_BUFFERED_PCM_H_
diff --git a/frc971/wpilib/buffered_solenoid.cc b/frc971/wpilib/buffered_solenoid.cc
new file mode 100644
index 0000000..cd68da8
--- /dev/null
+++ b/frc971/wpilib/buffered_solenoid.cc
@@ -0,0 +1,13 @@
+#include "frc971/wpilib/buffered_solenoid.h"
+
+#include "frc971/wpilib/buffered_pcm.h"
+
+namespace frc971 {
+namespace wpilib {
+
+void BufferedSolenoid::Set(bool value) {
+  pcm_->Set(number_, value);
+}
+
+}  // namespace wpilib
+}  // namespace frc971
diff --git a/frc971/wpilib/buffered_solenoid.h b/frc971/wpilib/buffered_solenoid.h
new file mode 100644
index 0000000..f0a4c11
--- /dev/null
+++ b/frc971/wpilib/buffered_solenoid.h
@@ -0,0 +1,28 @@
+#ifndef FRC971_WPILIB_BUFFERED_SOLENOID_H_
+#define FRC971_WPILIB_BUFFERED_SOLENOID_H_
+
+namespace frc971 {
+namespace wpilib {
+
+class BufferedPcm;
+
+// Handles sending values for a single solenoid to a BufferedPcm. Instances are
+// created with BufferedPcm::MakeSolenoid.
+class BufferedSolenoid {
+ public:
+  // Sets or unsets the solenoid.
+  void Set(bool value);
+
+ private:
+  BufferedSolenoid(int number, BufferedPcm *pcm) : number_(number), pcm_(pcm) {}
+
+  const int number_;
+  BufferedPcm *const pcm_;
+
+  friend class BufferedPcm;
+};
+
+}  // namespace wpilib
+}  // namespace frc971
+
+#endif  // FRC971_WPILIB_BUFFERED_SOLENOID_H_
diff --git a/frc971/wpilib/dma_edge_counting.cc b/frc971/wpilib/dma_edge_counting.cc
new file mode 100644
index 0000000..77d84b5
--- /dev/null
+++ b/frc971/wpilib/dma_edge_counting.cc
@@ -0,0 +1,65 @@
+#include "frc971/wpilib/dma_edge_counting.h"
+
+#include "aos/common/logging/logging.h"
+
+namespace frc971 {
+namespace wpilib {
+
+bool DMAEdgeCounter::ExtractValue(const DMASample &sample) const {
+  if (inverted_) {
+    return !sample.Get(input_);
+  } else {
+    return sample.Get(input_);
+  }
+}
+
+void DMAEdgeCounter::UpdateFromSample(const DMASample &sample) {
+  if (!have_prev_sample_) {
+    have_prev_sample_ = true;
+  } else {
+    if (!ExtractValue(prev_sample_) && ExtractValue(sample)) {
+      pos_edge_count_++;
+      pos_edge_time_ = sample.GetTimestamp();
+      pos_last_encoder_ = sample.GetRaw(encoder_);
+    } else if (ExtractValue(prev_sample_) && !ExtractValue(sample)) {
+      neg_edge_count_++;
+      neg_edge_time_ = sample.GetTimestamp();
+      neg_last_encoder_ = sample.GetRaw(encoder_);
+    }
+  }
+
+  prev_sample_ = sample;
+}
+
+void DMASynchronizer::CheckDMA() {
+  DMASample current_sample;
+
+  size_t remaining = 0;
+  while (true) {
+    switch (dma_->Read(&current_sample, 0, &remaining)) {
+      case DMA::STATUS_OK:
+        for (auto &c : handlers_) {
+          c->UpdateFromSample(current_sample);
+        }
+
+        if (remaining == 0) {
+          if (sample_time_ < current_sample.GetTimestamp()) {
+            // If the latest DMA sample happened after we started polling, then
+            // just use the values from it because they're more recent.
+            for (auto &c : handlers_) {
+              c->PollFromSample(current_sample);
+            }
+          }
+          return;
+        }
+      case DMA::STATUS_TIMEOUT:
+        return;
+      case DMA::STATUS_ERROR:
+        LOG(WARNING, "DMA read failed\n");
+        break;
+    }
+  }
+}
+
+}  // namespace wpilib
+}  // namespace frc971
diff --git a/frc971/wpilib/dma_edge_counting.h b/frc971/wpilib/dma_edge_counting.h
new file mode 100644
index 0000000..939dc5e
--- /dev/null
+++ b/frc971/wpilib/dma_edge_counting.h
@@ -0,0 +1,185 @@
+#ifndef FRC971_WPILIB_DMA_EDGE_COUNTING_H_
+#define FRC971_WPILIB_DMA_EDGE_COUNTING_H_
+
+#include <memory>
+#include <vector>
+
+#include "aos/common/macros.h"
+
+#include "frc971/wpilib/hall_effect.h"
+
+#include "DigitalSource.h"
+#include "Encoder.h"
+#include "AnalogInput.h"
+#include "Utility.h"
+#include "dma.h"
+
+namespace frc971 {
+namespace wpilib {
+
+// Generic interface for classes that do something with DMA samples and also
+// poll current sensor values.
+class DMASampleHandlerInterface {
+ public:
+  virtual ~DMASampleHandlerInterface() {}
+
+  // Updates values based on a new DMA sample.
+  virtual void UpdateFromSample(const DMASample &sample) = 0;
+
+  // Polls the current values and saves them for later reference.
+  virtual void UpdatePolledValue() = 0;
+
+  // Fills in the "polled" values from sample.
+  // This is only called when a DMA event happens right as we're polling values.
+  virtual void PollFromSample(const DMASample &sample) = 0;
+
+  // Adds readings and triggers appropriate to this object to dma.
+  virtual void AddToDMA(DMA *dma) = 0;
+};
+
+// Counts edges on a sensor using DMA data and latches encoder values
+// corresponding to those edges.
+class DMAEdgeCounter : public DMASampleHandlerInterface {
+ public:
+  DMAEdgeCounter(Encoder *encoder, DigitalSource *input)
+      : encoder_(encoder), input_(input), inverted_(false) {}
+  DMAEdgeCounter(Encoder *encoder, HallEffect *input)
+      : encoder_(encoder), input_(input), inverted_(true) {}
+
+  int positive_count() const { return pos_edge_count_; }
+  int negative_count() const { return neg_edge_count_; }
+  int last_positive_encoder_value() const { return pos_last_encoder_; }
+  int last_negative_encoder_value() const { return neg_last_encoder_; }
+
+  // Returns the value of the sensor in the last-read DMA sample.
+  bool last_value() const { return ExtractValue(prev_sample_); }
+  // Returns the most recent polled value of the sensor.
+  bool polled_value() const { return polled_value_; }
+  // Returns the most recent polled reading from the encoder.
+  int polled_encoder() const { return polled_encoder_; }
+
+ private:
+  void UpdateFromSample(const DMASample &sample) override;
+  void UpdatePolledValue() override {
+    polled_value_ = input_->Get();
+    polled_encoder_ = encoder_->GetRaw();
+  }
+  void PollFromSample(const DMASample &sample) override {
+    polled_value_ = ExtractValue(sample);
+    polled_encoder_ = sample.GetRaw(encoder_);
+  }
+  void AddToDMA(DMA *dma) override {
+    dma->Add(encoder_);
+    dma->Add(input_);
+  }
+
+  bool ExtractValue(const DMASample &sample) const;
+
+  Encoder *const encoder_;
+  DigitalSource *const input_;
+  const bool inverted_;
+
+  // The last DMA reading we got.
+  DMASample prev_sample_;
+  // Whether or not we actually have anything in prev_sample_.
+  bool have_prev_sample_ = false;
+
+  // Values related to the positive edge.
+  int pos_edge_count_ = 0;
+  double pos_edge_time_ = 0.0;
+  int pos_last_encoder_ = 0;
+
+  // Values related to the negative edge.
+  int neg_edge_count_ = 0;
+  double neg_edge_time_ = 0.0;
+  int neg_last_encoder_ = 0;
+
+  bool polled_value_ = false;
+  int polled_encoder_ = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(DMAEdgeCounter);
+};
+
+// Reads a hall effect in sync with DMA samples.
+class DMADigitalReader : public DMASampleHandlerInterface {
+ public:
+  DMADigitalReader(DigitalSource *input) : input_(input), inverted_(false) {}
+  DMADigitalReader(HallEffect *input) : input_(input), inverted_(true) {}
+
+  bool value() const { return value_; }
+
+ private:
+  void UpdateFromSample(const DMASample & /*sample*/) override {}
+  void UpdatePolledValue() override { value_ = input_->Get(); }
+  void PollFromSample(const DMASample &sample) override {
+    if (inverted_) {
+      value_ = !sample.Get(input_);
+    } else {
+      value_ = sample.Get(input_);
+    }
+  }
+  void AddToDMA(DMA *dma) override {
+    dma->Add(input_);
+  }
+
+  DigitalSource *const input_;
+  const bool inverted_;
+
+  bool value_;
+
+  DISALLOW_COPY_AND_ASSIGN(DMADigitalReader);
+};
+
+// This class handles updating the sampled data on multiple
+// DMASampleHandlerInterfaces. The caller should create an instance and then
+// periodically call RunIteration, retrieving whatever data from the
+// DMASampleHandlerInterfaces after each iteration.
+class DMASynchronizer {
+ public:
+  DMASynchronizer(::std::unique_ptr<DMA> dma) : dma_(::std::move(dma)) {}
+
+  // Adds a new handler to this object. This method must not be called after
+  // Start().
+  void Add(DMASampleHandlerInterface *handler) {
+    handler->AddToDMA(dma_.get());
+    handlers_.emplace_back(handler);
+  }
+
+  // Actually starts watching for DMA samples.
+  // Add may not be called any more after this.
+  void Start() {
+    dma_->Start(1024);
+  }
+
+  // Updates all sensor values.
+  void RunIteration() {
+    SampleSensors();
+    CheckDMA();
+  }
+
+ private:
+  // Reads the state of all the sensors and records it as the polled values of
+  // all the inputs.
+  void SampleSensors() {
+    sample_time_ = GetFPGATime();
+    for (auto &c : handlers_) {
+      c->UpdatePolledValue();
+    }
+  }
+
+  // Gets called by the DMA handler to update edge counts.
+  void CheckDMA();
+
+  const ::std::unique_ptr<DMA> dma_;
+  ::std::vector<DMASampleHandlerInterface *> handlers_;
+
+  // The time at which we most recently read the sensor values.
+  double sample_time_ = 0.0;
+
+  DISALLOW_COPY_AND_ASSIGN(DMASynchronizer);
+};
+
+}  // namespace wpilib
+}  // namespace frc971
+
+#endif  // FRC971_WPILIB_DMA_EDGE_COUNTING_H_
diff --git a/frc971/wpilib/encoder_and_potentiometer.cc b/frc971/wpilib/encoder_and_potentiometer.cc
new file mode 100644
index 0000000..800c49b
--- /dev/null
+++ b/frc971/wpilib/encoder_and_potentiometer.cc
@@ -0,0 +1,57 @@
+#include "frc971/wpilib/encoder_and_potentiometer.h"
+
+#include "aos/linux_code/init.h"
+#include "aos/common/logging/logging.h"
+
+namespace frc971 {
+namespace wpilib {
+
+void DMAEncoderAndPotentiometer::UpdateFromSample(const DMASample &sample) {
+  if (index_last_value_) {
+    // It was already true last time, so check if it's reset back to false yet.
+    index_last_value_ = sample.Get(index_.get());
+  } else if (sample.Get(index_.get())) {
+    // This sample is posedge, so record all the values.
+    index_last_value_ = true;
+    ++index_posedge_count_;
+    last_encoder_value_ = sample.GetRaw(encoder_.get());
+    last_potentiometer_voltage_ = sample.GetVoltage(potentiometer_.get());
+  }
+}
+
+void InterruptEncoderAndPotentiometer::Start() {
+  CHECK_NE(nullptr, encoder_);
+  CHECK_NE(nullptr, index_);
+  CHECK_NE(nullptr, potentiometer_);
+  CHECK_NE(0, priority_);
+  thread_ = ::std::thread(::std::ref(*this));
+}
+
+void InterruptEncoderAndPotentiometer::operator()() {
+  ::aos::SetCurrentThreadName("IntEncPot_" +
+                              ::std::to_string(potentiometer_->GetChannel()));
+
+  index_->RequestInterrupts();
+  index_->SetUpSourceEdge(true, false);
+
+  ::aos::SetCurrentThreadRealtimePriority(priority_);
+
+  InterruptableSensorBase::WaitResult result = InterruptableSensorBase::kBoth;
+  while (run_) {
+    result = index_->WaitForInterrupt(
+        0.1, result != InterruptableSensorBase::kTimeout);
+    if (result == InterruptableSensorBase::kTimeout) {
+      continue;
+    }
+
+    {
+      ::aos::MutexLocker locker(&mutex_);
+      last_potentiometer_voltage_ = potentiometer_->GetVoltage();
+      last_encoder_value_ = encoder_->GetRaw();
+      ++index_posedge_count_;
+    }
+  }
+}
+
+}  // namespace wpilib
+}  // namespace frc971
diff --git a/frc971/wpilib/encoder_and_potentiometer.h b/frc971/wpilib/encoder_and_potentiometer.h
new file mode 100644
index 0000000..2450841
--- /dev/null
+++ b/frc971/wpilib/encoder_and_potentiometer.h
@@ -0,0 +1,169 @@
+#ifndef FRC971_ENCODER_AND_POTENTIOMETER_H_
+#define FRC971_ENCODER_AND_POTENTIOMETER_H_
+
+#include <atomic>
+#include <thread>
+
+#include "aos/common/macros.h"
+#include "aos/common/mutex.h"
+
+#include "Encoder.h"
+#include "DigitalSource.h"
+#include "AnalogInput.h"
+#include "dma.h"
+
+#include "frc971/wpilib/dma_edge_counting.h"
+
+namespace frc971 {
+namespace wpilib {
+
+// Latches values from an encoder and potentiometer on positive edges from
+// another input using an interrupt.
+class InterruptEncoderAndPotentiometer {
+ public:
+  // priority is the priority the thread will run at.
+  InterruptEncoderAndPotentiometer(int priority) : priority_(priority) {}
+
+  // Starts the thread running so it can receive interrupts.
+  void Start();
+
+  // Tells the thread to stop running and then waits for it to finish.
+  void Stop() {
+    run_ = false;
+    thread_.join();
+  }
+
+  // Loops until Stop() is called, reading interrupts.
+  // Designed to be called by ::std::thread internally.
+  void operator()();
+
+  // Returns the mutex which must be held while calling index_posedge_count(),
+  // last_encoder_value(), and last_potentiometer_voltage().
+  // Holding this mutex will increase the handling latency.
+  ::aos::Mutex *mutex() { return &mutex_; }
+
+  void set_encoder(::std::unique_ptr<Encoder> encoder) {
+    encoder_ = ::std::move(encoder);
+  }
+  Encoder *encoder() const { return encoder_.get(); }
+
+  void set_index(::std::unique_ptr<DigitalSource> index) {
+    index_ = ::std::move(index);
+  }
+  DigitalSource *index() const { return index_.get(); }
+
+  void set_potentiometer(::std::unique_ptr<AnalogInput> potentiometer) {
+    potentiometer_ = ::std::move(potentiometer);
+  }
+  AnalogInput *potentiometer() const { return potentiometer_.get(); }
+
+  // Returns the number of poseges that have happened on the index input.
+  // mutex() must be held while calling this.
+  uint32_t index_posedge_count() const { return index_posedge_count_; }
+  // Returns the value of the encoder at the last index posedge.
+  // mutex() must be held while calling this.
+  int32_t last_encoder_value() const { return last_encoder_value_; }
+  // Returns the voltage of the potentiometer at the last index posedge.
+  // mutex() must be held while calling this.
+  float last_potentiometer_voltage() const {
+    return last_potentiometer_voltage_;
+  }
+
+ private:
+  ::std::unique_ptr<Encoder> encoder_;
+  ::std::unique_ptr<DigitalSource> index_;
+  ::std::unique_ptr<AnalogInput> potentiometer_;
+
+  int32_t last_encoder_value_{0};
+  float last_potentiometer_voltage_{0.0f};
+  uint32_t index_posedge_count_{0};
+
+  ::aos::Mutex mutex_;
+
+  const int priority_;
+
+  ::std::atomic<bool> run_{true};
+  ::std::thread thread_;
+
+  DISALLOW_COPY_AND_ASSIGN(InterruptEncoderAndPotentiometer);
+};
+
+// Latches values from an encoder and potentiometer on positive edges from
+// another input using DMA.
+class DMAEncoderAndPotentiometer : public DMASampleHandlerInterface {
+ public:
+  DMAEncoderAndPotentiometer() {}
+
+  void set_encoder(::std::unique_ptr<Encoder> encoder) {
+    encoder_ = ::std::move(encoder);
+  }
+  Encoder *encoder() const { return encoder_.get(); }
+
+  void set_index(::std::unique_ptr<DigitalSource> index) {
+    index_ = ::std::move(index);
+  }
+  DigitalSource *index() const { return index_.get(); }
+
+  void set_potentiometer(::std::unique_ptr<AnalogInput> potentiometer) {
+    potentiometer_ = ::std::move(potentiometer);
+  }
+  AnalogInput *potentiometer() const { return potentiometer_.get(); }
+
+  // Returns the most recent polled value of the encoder.
+  uint32_t polled_encoder_value() const { return polled_encoder_value_; }
+  // Returns the most recent polled voltage of the potentiometer.
+  float polled_potentiometer_voltage() const {
+    return polled_potentiometer_voltage_;
+  }
+
+  // Returns the number of poseges that have happened on the index input.
+  uint32_t index_posedge_count() const { return index_posedge_count_; }
+  // Returns the value of the encoder at the last index posedge.
+  int32_t last_encoder_value() const { return last_encoder_value_; }
+  // Returns the voltage of the potentiometer at the last index posedge.
+  float last_potentiometer_voltage() const {
+    return last_potentiometer_voltage_;
+  }
+
+  virtual void UpdateFromSample(const DMASample &sample) override;
+
+  virtual void PollFromSample(const DMASample &sample) override {
+    polled_encoder_value_ = sample.GetRaw(encoder_.get());
+    polled_potentiometer_voltage_ = sample.GetVoltage(potentiometer_.get());
+  }
+
+  virtual void UpdatePolledValue() override {
+    polled_encoder_value_ = encoder_->GetRaw();
+    polled_potentiometer_voltage_ = potentiometer_->GetVoltage();
+  }
+
+  virtual void AddToDMA(DMA *dma) override {
+    dma->Add(encoder_.get());
+    dma->Add(index_.get());
+    dma->Add(potentiometer_.get());
+    dma->SetExternalTrigger(index_.get(), true, true);
+  }
+
+ private:
+  ::std::unique_ptr<Encoder> encoder_;
+  ::std::unique_ptr<DigitalSource> index_;
+  ::std::unique_ptr<AnalogInput> potentiometer_;
+
+  int32_t polled_encoder_value_ = 0;
+  float polled_potentiometer_voltage_ = 0.0f;
+
+  int32_t last_encoder_value_ = 0;
+  float last_potentiometer_voltage_ = 0.0f;
+
+  uint32_t index_posedge_count_ = 0;
+
+  // Whether or not it was triggered in the last sample.
+  bool index_last_value_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(DMAEncoderAndPotentiometer);
+};
+
+}  // namespace wpilib
+}  // namespace frc971
+
+#endif  // FRC971_ENCODER_AND_POTENTIOMETER_H_
diff --git a/frc971/wpilib/gyro_interface.cc b/frc971/wpilib/gyro_interface.cc
new file mode 100644
index 0000000..4b440a9
--- /dev/null
+++ b/frc971/wpilib/gyro_interface.cc
@@ -0,0 +1,144 @@
+#include "frc971/wpilib/gyro_interface.h"
+
+#include <inttypes.h>
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/time.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+namespace frc971 {
+namespace wpilib {
+
+GyroInterface::GyroInterface() : gyro_(new SPI(SPI::kOnboardCS0)) {
+  // The gyro goes up to 8.08MHz.
+  // The myRIO goes up to 4MHz, so the roboRIO probably does too.
+  gyro_->SetClockRate(4e6);
+  gyro_->SetChipSelectActiveLow();
+  gyro_->SetClockActiveHigh();
+  gyro_->SetSampleDataOnRising();
+  gyro_->SetMSBFirst();
+}
+
+bool GyroInterface::InitializeGyro() {
+  uint32_t result;
+  if (!DoTransaction(0x20000003, &result)) {
+    LOG(WARNING, "failed to start a self-check\n");
+    return false;
+  }
+  if (result != 1) {
+    // We might have hit a parity error or something and are now retrying, so
+    // this isn't a very big deal.
+    LOG(INFO, "gyro unexpected initial response 0x%" PRIx32 "\n", result);
+  }
+
+  // Wait for it to assert the fault conditions before reading them.
+  ::aos::time::SleepFor(::aos::time::Time::InMS(50));
+
+  if (!DoTransaction(0x20000000, &result)) {
+    LOG(WARNING, "failed to clear latched non-fault data\n");
+    return false;
+  }
+  LOG(DEBUG, "gyro dummy response is 0x%" PRIx32 "\n", result);
+
+  if (!DoTransaction(0x20000000, &result)) {
+    LOG(WARNING, "failed to read self-test data\n");
+    return false;
+  }
+  if (ExtractStatus(result) != 2) {
+    LOG(WARNING, "gyro first value 0x%" PRIx32 " not self-test data\n", result);
+    return false;
+  }
+  if (ExtractErrors(result) != 0x7F) {
+    LOG(WARNING, "gyro first value 0x%" PRIx32 " does not have all errors\n",
+        result);
+    return false;
+  }
+
+  if (!DoTransaction(0x20000000, &result)) {
+    LOG(WARNING, "failed to clear latched self-test data\n");
+    return false;
+  }
+  if (ExtractStatus(result) != 2) {
+    LOG(WARNING, "gyro second value 0x%" PRIx32 " not self-test data\n",
+        result);
+    return false;
+  }
+
+  return true;
+}
+
+bool GyroInterface::DoTransaction(uint32_t to_write, uint32_t *result) {
+  static const uint8_t kBytes = 4;
+  static_assert(kBytes == sizeof(to_write),
+                "need the same number of bytes as sizeof(the data)");
+
+  if (__builtin_parity(to_write & ~1) == 0) to_write |= 1;
+
+  uint8_t to_send[kBytes], to_receive[kBytes];
+  const uint32_t to_write_flipped = __builtin_bswap32(to_write);
+  memcpy(to_send, &to_write_flipped, kBytes);
+
+  switch (gyro_->Transaction(to_send, to_receive, kBytes)) {
+    case -1:
+      LOG(INFO, "SPI::Transaction failed\n");
+      return false;
+    case kBytes:
+      break;
+    default:
+      LOG(FATAL, "SPI::Transaction returned something weird\n");
+  }
+
+  memcpy(result, to_receive, kBytes);
+  if (__builtin_parity(*result & 0xFFFF) != 1) {
+    LOG(INFO, "high byte parity failure\n");
+    return false;
+  }
+  if (__builtin_parity(*result) != 1) {
+    LOG(INFO, "whole value parity failure\n");
+    return false;
+  }
+
+  *result = __builtin_bswap32(*result);
+  return true;
+}
+
+uint16_t GyroInterface::DoRead(uint8_t address) {
+  const uint32_t command = (0x8 << 28) | (address << 17);
+  uint32_t response;
+  while (true) {
+    if (!DoTransaction(command, &response)) {
+      LOG(WARNING, "reading 0x%" PRIx8 " failed\n", address);
+      continue;
+    }
+    if ((response & 0xEFE00000) != 0x4E000000) {
+      LOG(WARNING, "gyro read from 0x%" PRIx8
+                   " gave unexpected response 0x%" PRIx32 "\n",
+          address, response);
+      continue;
+    }
+    return (response >> 5) & 0xFFFF;
+  }
+}
+
+double GyroInterface::ExtractAngle(uint32_t value) {
+  const int16_t reading = -(int16_t)(value >> 10 & 0xFFFF);
+  return static_cast<double>(reading) * 2.0 * M_PI / 360.0 / 80.0;
+}
+
+uint32_t GyroInterface::ReadPartID() {
+  return (DoRead(0x0E) << 16) | DoRead(0x10);
+}
+
+uint32_t GyroInterface::GetReading() {
+  uint32_t result;
+  if (!DoTransaction(0x20000000, &result)) {
+    return 0;
+  }
+  return result;
+}
+
+}  // namespace wpilib
+}  // namespace frc971
diff --git a/frc971/wpilib/gyro_interface.h b/frc971/wpilib/gyro_interface.h
new file mode 100644
index 0000000..baba248
--- /dev/null
+++ b/frc971/wpilib/gyro_interface.h
@@ -0,0 +1,55 @@
+#ifndef FRC971_WPILIB_GYRO_INTERFACE_H_
+#define FRC971_WPILIB_GYRO_INTERFACE_H_
+
+#include <memory>
+
+#include "SPI.h"
+
+namespace frc971 {
+namespace wpilib {
+
+class GyroInterface {
+ public:
+  GyroInterface();
+
+  // Runs the recommended gyro startup procedure including checking all of the
+  // self-test bits.
+  // Returns true if it succeeds.
+  bool InitializeGyro();
+
+  // Reads one of the gyro's "registers" and returns the value.
+  // Retries until it succeeds.
+  uint16_t DoRead(uint8_t address);
+
+  // Returns all of the non-data bits in the "header" except the parity from
+  // value.
+  uint8_t ExtractStatus(uint32_t value) { return (value >> 26) & ~4; }
+  // Returns all of the error bits in the "footer" from value.
+  uint8_t ExtractErrors(uint32_t value) { return (value >> 1) & 0x7F; }
+
+  // Returns the anglular rate contained in value.
+  double ExtractAngle(uint32_t value);
+
+  // Performs a transaction with the gyro.
+  // to_write is the value to write. This function handles setting the checksum
+  // bit.
+  // result is where to stick the result. This function verifies the parity bit.
+  // Returns true for success.
+  bool DoTransaction(uint32_t to_write, uint32_t *result);
+
+  // Returns the part ID from the gyro.
+  // Retries until it succeeds.
+  uint32_t ReadPartID();
+
+  // Gets a reading from the gyro.
+  // Returns a value to be passed to the Extract* methods or 0 for error.
+  uint32_t GetReading();
+
+ private:
+  ::std::unique_ptr<SPI> gyro_;
+};
+
+}  // namespace wpilib
+}  // namespace frc971
+
+#endif  // FRC971_WPILIB_GYRO_INTERFACE_H_
diff --git a/frc971/wpilib/gyro_sender.cc b/frc971/wpilib/gyro_sender.cc
new file mode 100644
index 0000000..d3b9500
--- /dev/null
+++ b/frc971/wpilib/gyro_sender.cc
@@ -0,0 +1,138 @@
+#include "frc971/wpilib/gyro_sender.h"
+
+#include <inttypes.h>
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/logging/queue_logging.h"
+#include "aos/common/util/phased_loop.h"
+#include "aos/common/messages/robot_state.q.h"
+#include "aos/common/time.h"
+#include "aos/linux_code/init.h"
+
+#include "frc971/queues/gyro.q.h"
+
+namespace frc971 {
+namespace wpilib {
+
+GyroSender::GyroSender() {}
+
+void GyroSender::operator()() {
+  ::aos::SetCurrentThreadName("Gyro");
+
+  // Try to initialize repeatedly as long as we're supposed to be running.
+  while (run_ && !gyro_.InitializeGyro()) {
+    ::aos::time::SleepFor(::aos::time::Time::InMS(50));
+  }
+  LOG(INFO, "gyro initialized successfully\n");
+
+  auto message = ::frc971::sensors::gyro_part_id.MakeMessage();
+  message->uid = gyro_.ReadPartID();
+  LOG_STRUCT(INFO, "gyro ID", *message);
+  message.Send();
+
+  // In radians, ready to send out.
+  double angle = 0;
+
+  int startup_cycles_left = 2 * kReadingRate;
+
+  double zeroing_data[6 * kReadingRate];
+  size_t zeroing_index = 0;
+  bool zeroed = false;
+  bool have_zeroing_data = false;
+  double zero_offset = 0;
+
+  while (run_) {
+    ::aos::time::PhasedLoopXMS(1000 / kReadingRate, 0);
+
+    const uint32_t result = gyro_.GetReading();
+    if (result == 0) {
+      LOG(WARNING, "normal gyro read failed\n");
+      continue;
+    }
+    switch (gyro_.ExtractStatus(result)) {
+      case 0:
+        LOG(WARNING, "gyro says data is bad\n");
+        continue;
+      case 1:
+        break;
+      default:
+        LOG(WARNING, "gyro gave weird status 0x%" PRIx8 "\n",
+            gyro_.ExtractStatus(result));
+        continue;
+    }
+    if (gyro_.ExtractErrors(result) != 0) {
+      const uint8_t errors = gyro_.ExtractErrors(result);
+      if (errors & (1 << 6)) {
+        LOG(WARNING, "gyro gave PLL error\n");
+      }
+      if (errors & (1 << 5)) {
+        LOG(WARNING, "gyro gave quadrature error\n");
+      }
+      if (errors & (1 << 4)) {
+        LOG(WARNING, "gyro gave non-volatile memory error\n");
+      }
+      if (errors & (1 << 3)) {
+        LOG(WARNING, "gyro gave volatile memory error\n");
+      }
+      if (errors & (1 << 2)) {
+        LOG(WARNING, "gyro gave power error\n");
+      }
+      if (errors & (1 << 1)) {
+        LOG(WARNING, "gyro gave continuous self-test error\n");
+      }
+      if (errors & 1) {
+        LOG(WARNING, "gyro gave unexpected self-test mode\n");
+      }
+      continue;
+    }
+
+    if (startup_cycles_left > 0) {
+      --startup_cycles_left;
+      continue;
+    }
+
+    const double new_angle =
+        gyro_.ExtractAngle(result) / static_cast<double>(kReadingRate);
+    auto message = ::frc971::sensors::gyro_reading.MakeMessage();
+    if (zeroed) {
+      angle += new_angle;
+      angle += zero_offset;
+      message->angle = angle;
+      LOG_STRUCT(DEBUG, "sending", *message);
+      message.Send();
+    } else {
+      // TODO(brian): Don't break without 6 seconds of standing still before
+      // enabling. Ideas:
+      //   Don't allow driving until we have at least some data?
+      //   Some kind of indicator light?
+      {
+        message->angle = new_angle;
+        LOG_STRUCT(DEBUG, "collected while zeroing", *message);
+        message->angle = 0.0;
+        message.Send();
+      }
+      zeroing_data[zeroing_index] = new_angle;
+      ++zeroing_index;
+      if (zeroing_index >= sizeof(zeroing_data) / sizeof(zeroing_data[0])) {
+        zeroing_index = 0;
+        have_zeroing_data = true;
+      }
+
+      ::aos::joystick_state.FetchLatest();
+      if (::aos::joystick_state.get() && ::aos::joystick_state->enabled &&
+          have_zeroing_data) {
+        zero_offset = 0;
+        for (size_t i = 0; i < sizeof(zeroing_data) / sizeof(zeroing_data[0]);
+             ++i) {
+          zero_offset -= zeroing_data[i];
+        }
+        zero_offset /= sizeof(zeroing_data) / sizeof(zeroing_data[0]);
+        LOG(INFO, "total zero offset %f\n", zero_offset);
+        zeroed = true;
+      }
+    }
+  }
+}
+
+}  // namespace wpilib
+}  // namespace frc971
diff --git a/frc971/wpilib/gyro_sender.h b/frc971/wpilib/gyro_sender.h
new file mode 100644
index 0000000..029ace9
--- /dev/null
+++ b/frc971/wpilib/gyro_sender.h
@@ -0,0 +1,41 @@
+#ifndef FRC971_WPILIB_GYRO_H_
+#define FRC971_WPILIB_GYRO_H_
+
+#include <stdint.h>
+
+#include <atomic>
+
+#include "frc971/wpilib/gyro_interface.h"
+
+namespace frc971 {
+namespace wpilib {
+
+// Handles reading the gyro over SPI and sending out angles on a queue.
+//
+// This is designed to be passed into ::std::thread's constructor so it will run
+// as a separate thread.
+class GyroSender {
+ public:
+  GyroSender();
+
+  // For ::std::thread to call.
+  //
+  // Initializes the gyro and then loops forever taking readings.
+  void operator()();
+
+  void Quit() { run_ = false; }
+
+ private:
+
+  // Readings per second.
+  static const int kReadingRate = 200;
+
+  GyroInterface gyro_;
+
+  ::std::atomic<bool> run_{true};
+};
+
+}  // namespace wpilib
+}  // namespace frc971
+
+#endif  // FRC971_WPILIB_GYRO_H_
diff --git a/frc971/wpilib/hall_effect.h b/frc971/wpilib/hall_effect.h
new file mode 100644
index 0000000..407f2b9
--- /dev/null
+++ b/frc971/wpilib/hall_effect.h
@@ -0,0 +1,19 @@
+#ifndef FRC971_WPILIB_HALL_EFFECT_H_
+#define FRC971_WPILIB_HALL_EFFECT_H_
+
+#include "DigitalInput.h"
+
+namespace frc971 {
+namespace wpilib {
+
+// Inverts the output from a digital input.
+class HallEffect : public DigitalInput {
+ public:
+  HallEffect(int index) : DigitalInput(index) {}
+  virtual bool Get() override { return !DigitalInput::Get(); }
+};
+
+}  // namespace wpilib
+}  // namespace frc971
+
+#endif  // FRC971_WPILIB_HALL_EFFECT_H_
diff --git a/frc971/wpilib/interrupt_edge_counting.cc b/frc971/wpilib/interrupt_edge_counting.cc
new file mode 100644
index 0000000..4bdb2d2
--- /dev/null
+++ b/frc971/wpilib/interrupt_edge_counting.cc
@@ -0,0 +1,104 @@
+#include "frc971/wpilib/interrupt_edge_counting.h"
+
+#include "aos/common/time.h"
+#include "aos/linux_code/init.h"
+
+namespace frc971 {
+namespace wpilib {
+
+void EdgeCounter::GatherPolledValue() {
+  shadow_values_.polled_value = input_->Get();
+  bool miss_match = (shadow_values_.polled_value != current_value_);
+  if (miss_match && last_miss_match_) {
+    current_value_ = shadow_values_.polled_value;
+    last_miss_match_ = false;
+  } else {
+    last_miss_match_ = miss_match;
+  }
+}
+
+void EdgeCounter::operator()() {
+  ::aos::SetCurrentThreadName("EdgeCounter_" +
+                              ::std::to_string(input_->GetChannelForRouting()));
+
+  input_->RequestInterrupts();
+  input_->SetUpSourceEdge(true, true);
+
+  {
+    ::std::unique_lock<::aos::stl_mutex> mutex_guard(*mutex());
+    current_value_ = input_->Get();
+  }
+
+  ::aos::SetCurrentThreadRealtimePriority(priority());
+  InterruptableSensorBase::WaitResult result = InterruptableSensorBase::kBoth;
+  while (should_run()) {
+    result = input_->WaitForInterrupt(
+        0.1, result != InterruptableSensorBase::kTimeout);
+    if (result == InterruptableSensorBase::kTimeout) {
+      continue;
+    }
+    interrupt_received();
+
+    ::std::unique_lock<::aos::stl_mutex> mutex_guard(*mutex());
+    int32_t encoder_value = encoder_->GetRaw();
+    bool hall_value = input_->Get();
+    if (current_value_ != hall_value) {
+      if (hall_value) {
+        ++shadow_values_.positive_interrupt_count;
+        shadow_values_.last_positive_encoder_value = encoder_value;
+      } else {
+        ++shadow_values_.negative_interrupt_count;
+        shadow_values_.last_negative_encoder_value = encoder_value;
+      }
+      current_value_ = hall_value;
+    } else {
+      LOG(WARNING, "Detected spurious edge on %d.  Dropping it.\n",
+          input_->GetChannelForRouting());
+    }
+  }
+}
+
+void InterruptSynchronizer::RunIteration() {
+  while (true) {
+    if (!TryStartIteration()) continue;
+
+    // Wait more than the amount of time it takes for a digital input change
+    // to go from visible to software to having triggered an interrupt.
+    ::aos::time::SleepFor(::aos::time::Time::InUS(120));
+
+    if (TryFinishingIteration()) return;
+  }
+}
+
+bool InterruptSynchronizer::TryStartIteration() {
+  for (auto &c : handlers_) {
+    c->save_interrupt_count();
+  }
+
+  {
+    ::std::unique_lock<::aos::stl_mutex> mutex_guard(mutex_);
+    for (auto &c : handlers_) {
+      c->GatherPolledValue();
+    }
+  }
+  return true;
+}
+
+bool InterruptSynchronizer::TryFinishingIteration() {
+  // Make sure no interrupts have occurred while we were waiting.  If they
+  // have, we are in an inconsistent state and need to try again.
+  ::std::unique_lock<::aos::stl_mutex> mutex_guard(mutex_);
+  for (auto &c : handlers_) {
+    if (c->interrupt_count_changed()) {
+      LOG(WARNING, "got an interrupt while sampling. retrying\n");
+      return false;
+    }
+  }
+  for (auto &c : handlers_) {
+    c->CommitValue();
+  }
+  return true;
+}
+
+}  // namespace wpilib
+}  // namespace frc971
diff --git a/frc971/wpilib/interrupt_edge_counting.h b/frc971/wpilib/interrupt_edge_counting.h
new file mode 100644
index 0000000..f0b5e32
--- /dev/null
+++ b/frc971/wpilib/interrupt_edge_counting.h
@@ -0,0 +1,234 @@
+#ifndef FRC971_WPILIB_INTERRUPT_EDGE_COUNTING_H_
+#define FRC971_WPILIB_INTERRUPT_EDGE_COUNTING_H_
+
+#include <memory>
+#include <atomic>
+#include <thread>
+#include <vector>
+
+#include "aos/common/stl_mutex.h"
+#include "aos/common/macros.h"
+
+#include "DigitalSource.h"
+#include "Encoder.h"
+#include "AnalogInput.h"
+#include "Utility.h"
+
+namespace frc971 {
+namespace wpilib {
+
+class InterruptSynchronizer;
+
+// Handles interrupts arriving from a single source.
+//
+// Instances of subclasses should be passed to InterruptSynchronizer::Add to use
+// them. All methods which are called with the lock held should avoid taking too
+// long because they directly contribute to interrupt-handling latency for all
+// InterruptHandlers in the same InterruptSynchronizer.
+//
+// Each instance handles any important sensor reading which must happen right
+// after an interrupt triggers from a single source. It is also important that
+// some sensors are sampled after any pending interrupts have been processed.
+// This is handled using a per-InterruptSynchronizer mutex. Each
+// InterruptHandler records that it has received an interrupt, locks the mutex,
+// and then updates a "shadow" state. The InterruptSynchronizer then triggers
+// making this "shadow" state visible after making sure no more interrupts have
+// arrived while holding the mutex.
+class InterruptHandler {
+ public:
+  virtual ~InterruptHandler() {}
+
+  // Stops the thread which actually does the sampling and waits for it to
+  // finish.
+  void Quit() {
+    run_ = false;
+    thread_.join();
+  }
+
+  // Starts the thread running.
+  // set_priority and set_mutex must be called first.
+  void Start() {
+    CHECK_NE(nullptr, mutex_);
+    CHECK_NE(0, priority_);
+    thread_ = ::std::thread(::std::ref(*this));
+  }
+
+  // Polls the current values and saves them to the "shadow" output.
+  // Called while the lock is held.
+  virtual void GatherPolledValue() = 0;
+
+  // Actually outputs the "shadow" state collected during the most recent
+  // GatherPolledValue.
+  // Called while the lock is held.
+  virtual void CommitValue() = 0;
+
+  // Saves the current interrupt count to be compared when
+  // interrupt_count_changed() is called.
+  void save_interrupt_count() { saved_interrupt_count_ = interrupt_count_; }
+  // Returns whether or not the interrupt count has changed since
+  // save_interrupt_count() was last called.
+  bool interrupt_count_changed() const {
+    return saved_interrupt_count_ != interrupt_count_;
+  }
+
+  // Sets the priority the thread will run at.
+  // This must be called before Start.
+  void set_priority(int priority) { priority_ = priority; }
+
+  // Sets the mutex to use for synchronizing readings.
+  // This must be called before Start.
+  void set_mutex(::aos::stl_mutex *mutex) { mutex_ = mutex; }
+
+  // Waits for interrupts, locks the mutex, and updates the internal state.
+  // Should only be called by the (internal) ::std::thread.
+  virtual void operator()() = 0;
+
+ protected:
+  // Indicates that another interrupt has been received (not handled yet).
+  void interrupt_received() { ++interrupt_count_; }
+
+  int priority() const { return priority_; }
+
+  ::aos::stl_mutex *mutex() { return mutex_; }
+
+  // Returns true if the thread should continue running.
+  bool should_run() const { return run_; }
+
+ private:
+  ::std::atomic<int> interrupt_count_{0};
+  int saved_interrupt_count_;
+
+  ::std::atomic<bool> run_{true};
+  ::std::thread thread_;
+
+  int priority_ = 0;
+  ::aos::stl_mutex *mutex_ = nullptr;
+};
+
+// Latches the value of an encoder on rising and falling edges of a digital
+// input.
+class EdgeCounter : public InterruptHandler {
+ public:
+  EdgeCounter(Encoder *encoder, DigitalSource *input)
+      : encoder_(encoder), input_(input) {}
+
+  // Returns the current interrupt edge counts and encoder values.
+  int positive_interrupt_count() const {
+    return output_.positive_interrupt_count;
+  }
+  int negative_interrupt_count() const {
+    return output_.negative_interrupt_count;
+  }
+  int32_t last_positive_encoder_value() const {
+    return output_.last_positive_encoder_value;
+  }
+  int32_t last_negative_encoder_value() const {
+    return output_.last_negative_encoder_value;
+  }
+  // Returns the current polled value.
+  bool polled_value() const { return output_.polled_value; }
+
+ private:
+  struct OutputValues {
+    bool polled_value = false;
+    int positive_interrupt_count = 0, negative_interrupt_count = 0;
+    int32_t last_positive_encoder_value = 0, last_negative_encoder_value = 0;
+  };
+
+  void GatherPolledValue() override;
+  void CommitValue() override { output_ = shadow_values_; }
+  void operator()() override;
+
+  Encoder *encoder_;
+  DigitalSource *input_;
+
+  // The following variables represent the current "shadow" state.
+  bool current_value_ = false;
+  bool last_miss_match_ = true;
+  OutputValues shadow_values_;
+
+  // The actual output values.
+  OutputValues output_;
+
+  DISALLOW_COPY_AND_ASSIGN(EdgeCounter);
+};
+
+// Synchronizes reading an encoder with interrupt handling.
+class InterruptSynchronizedEncoder : public InterruptHandler {
+ public:
+  InterruptSynchronizedEncoder(Encoder *encoder) : encoder_(encoder) {}
+
+  int32_t get() const { return output_; }
+
+ private:
+  void GatherPolledValue() override { shadow_ = encoder_->GetRaw(); }
+  void CommitValue() override { output_ = shadow_; }
+  void operator()() override {}
+
+  Encoder *const encoder_;
+
+  int32_t shadow_, output_;
+};
+
+// Synchronizes interrupts with poll-based sampling on multiple
+// InterruptHandlers.
+//
+// See InterruptHandler for an overview of the logic.
+//
+// Usage is to create an instance, call Add 1 or more times, call Start, and
+// then call RunIteration during normal sensor sampling. After RunIteration
+// returns, the output values from the various InterruptHandlers can be
+// retrieved.
+class InterruptSynchronizer {
+ public:
+  InterruptSynchronizer(int interrupt_priority)
+      : interrupt_priority_(interrupt_priority) {}
+
+  void Add(InterruptHandler *handler) {
+    handler->set_mutex(&mutex_);
+    handler->set_priority(interrupt_priority_);
+    handlers_.emplace_back(handler);
+  }
+
+  void Start() {
+    for (auto &c : handlers_) {
+      c->Start();
+    }
+  }
+
+  // Updates all of the counts and makes sure everything is synchronized.
+  // IMPORTANT: This will usually only take 120uS but WILL occasionally take
+  // longer, so be careful about letting that jitter get into control loops.
+  void RunIteration();
+
+  // Asks all of the InterruptHandlers to stop and waits until they have done
+  // so.
+  void Quit() {
+    for (auto &c : handlers_) {
+      c->Quit();
+    }
+  }
+
+ private:
+  // Starts a sampling iteration.  See RunIteration for usage.
+  // Returns true if we are ready to go or false if we already need to retry.
+  bool TryStartIteration();
+
+  // Attempts to finish a sampling iteration.  See RunIteration for usage.
+  // Returns true if the iteration succeeded, and false otherwise.
+  bool TryFinishingIteration();
+
+  const int interrupt_priority_;
+
+  // The mutex used to synchronize all the sampling.
+  ::aos::stl_mutex mutex_;
+
+  ::std::vector<InterruptHandler *> handlers_;
+
+  DISALLOW_COPY_AND_ASSIGN(InterruptSynchronizer);
+};
+
+}  // namespace wpilib
+}  // namespace frc971
+
+#endif  // FRC971_WPILIB_INTERRUPT_EDGE_COUNTING_H_
diff --git a/frc971/wpilib/joystick_sender.cc b/frc971/wpilib/joystick_sender.cc
new file mode 100644
index 0000000..236cc0f
--- /dev/null
+++ b/frc971/wpilib/joystick_sender.cc
@@ -0,0 +1,50 @@
+#include "frc971/wpilib/joystick_sender.h"
+
+#include "aos/common/messages/robot_state.q.h"
+#include "aos/linux_code/init.h"
+#include "aos/common/network/team_number.h"
+#include "aos/common/logging/queue_logging.h"
+
+#include "DriverStation.h"
+#include "HAL/HAL.hpp"
+
+namespace frc971 {
+namespace wpilib {
+
+void JoystickSender::operator()() {
+  DriverStation *ds = DriverStation::GetInstance();
+  ::aos::SetCurrentThreadName("DSReader");
+  uint16_t team_id = ::aos::network::GetTeamNumber();
+
+  ::aos::SetCurrentThreadRealtimePriority(29);
+
+  while (run_) {
+    ds->WaitForData();
+    auto new_state = ::aos::joystick_state.MakeMessage();
+
+    HALControlWord control_word;
+    HALGetControlWord(&control_word);
+    new_state->test_mode = control_word.test;
+    new_state->fms_attached = control_word.fmsAttached;
+    new_state->enabled = control_word.enabled;
+    new_state->autonomous = control_word.autonomous;
+    new_state->team_id = team_id;
+    new_state->fake = false;
+
+    for (int i = 0; i < 4; ++i) {
+      new_state->joysticks[i].buttons = ds->GetStickButtons(i);
+      for (int j = 0; j < 4; ++j) {
+        new_state->joysticks[i].axis[j] = ds->GetStickAxis(i, j);
+      }
+      new_state->joysticks[i].pov = ds->GetStickPOV(i, 0);
+    }
+    LOG_STRUCT(DEBUG, "joystick_state", *new_state);
+
+    if (!new_state.Send()) {
+      LOG(WARNING, "sending joystick_state failed\n");
+    }
+  }
+}
+
+}  // namespace wpilib
+}  // namespace frc971
diff --git a/frc971/wpilib/joystick_sender.h b/frc971/wpilib/joystick_sender.h
new file mode 100644
index 0000000..205f9c4
--- /dev/null
+++ b/frc971/wpilib/joystick_sender.h
@@ -0,0 +1,22 @@
+#ifndef FRC971_WPILIB_JOYSTICK_SENDER_H_
+#define FRC971_WPILIB_JOYSTICK_SENDER_H_
+
+#include <atomic>
+
+namespace frc971 {
+namespace wpilib {
+
+class JoystickSender {
+ public:
+  void operator()();
+
+  void Quit() { run_ = false; }
+
+ private:
+  ::std::atomic<bool> run_{true};
+};
+
+}  // namespace wpilib
+}  // namespace frc971
+
+#endif  // FRC971_WPILIB_JOYSTICK_SENDER_H_
diff --git a/frc971/wpilib/logging.q b/frc971/wpilib/logging.q
new file mode 100644
index 0000000..a2b3799
--- /dev/null
+++ b/frc971/wpilib/logging.q
@@ -0,0 +1,7 @@
+package frc971.wpilib;
+
+// Information about the current state of the pneumatics system to log.
+struct PneumaticsToLog {
+  bool compressor_on;
+  uint8_t read_solenoids;
+};
diff --git a/frc971/wpilib/loop_output_handler.cc b/frc971/wpilib/loop_output_handler.cc
new file mode 100644
index 0000000..cb5e4ec
--- /dev/null
+++ b/frc971/wpilib/loop_output_handler.cc
@@ -0,0 +1,72 @@
+#include "frc971/wpilib/loop_output_handler.h"
+
+#include <sys/timerfd.h>
+
+#include <thread>
+#include <functional>
+
+#include "aos/linux_code/init.h"
+#include "aos/common/messages/robot_state.q.h"
+
+namespace frc971 {
+namespace wpilib {
+
+constexpr ::aos::time::Time LoopOutputHandler::kStopTimeout;
+
+LoopOutputHandler::LoopOutputHandler() : watchdog_(this) {}
+
+void LoopOutputHandler::operator()() {
+  ::aos::SetCurrentThreadName("OutputHandler");
+  ::std::thread watchdog_thread(::std::ref(watchdog_));
+
+  ::aos::SetCurrentThreadRealtimePriority(30);
+  while (run_) {
+    no_joystick_state_.Print();
+    fake_joystick_state_.Print();
+    Read();
+    ::aos::joystick_state.FetchLatest();
+    if (!::aos::joystick_state.get()) {
+      LOG_INTERVAL(no_joystick_state_);
+      continue;
+    }
+    if (::aos::joystick_state->fake) {
+      LOG_INTERVAL(fake_joystick_state_);
+      continue;
+    }
+
+    watchdog_.Reset();
+    Write();
+  }
+
+  Stop();
+
+  watchdog_.Quit();
+  watchdog_thread.join();
+}
+
+LoopOutputHandler::Watchdog::Watchdog(LoopOutputHandler *handler)
+    : handler_(handler),
+      timerfd_(timerfd_create(::aos::time::Time::kDefaultClock, 0)) {
+  if (timerfd_.get() == -1) {
+    PLOG(FATAL, "timerfd_create(Time::kDefaultClock, 0)");
+  }
+  ::aos::SetCurrentThreadRealtimePriority(35);
+  ::aos::SetCurrentThreadName("OutputWatchdog");
+}
+
+void LoopOutputHandler::Watchdog::operator()() {
+  uint8_t buf[8];
+  while (run_) {
+    PCHECK(read(timerfd_.get(), buf, sizeof(buf)));
+    handler_->Stop();
+  }
+}
+
+void LoopOutputHandler::Watchdog::Reset() {
+  itimerspec value = itimerspec();
+  value.it_value = kStopTimeout.ToTimespec();
+  PCHECK(timerfd_settime(timerfd_.get(), 0, &value, nullptr));
+}
+
+}  // namespace wpilib
+}  // namespace frc971
diff --git a/frc971/wpilib/loop_output_handler.h b/frc971/wpilib/loop_output_handler.h
new file mode 100644
index 0000000..fe32763
--- /dev/null
+++ b/frc971/wpilib/loop_output_handler.h
@@ -0,0 +1,89 @@
+#ifndef FRC971_WPILIB_LOOP_OUTPUT_HANDLER_H_
+#define FRC971_WPILIB_LOOP_OUTPUT_HANDLER_H_
+
+#include "aos/common/scoped_fd.h"
+#include "aos/common/time.h"
+#include "aos/common/util/log_interval.h"
+
+#include <atomic>
+
+namespace frc971 {
+namespace wpilib {
+
+// Handles sending the output from a single control loop to the hardware.
+//
+// This class implements stopping motors when no new values are received for too
+// long efficiently.
+//
+// The intended use is to have a subclass for each loop which implements the
+// pure virtual methods and is then run in a separate thread. The operator()
+// loops writing values until Quit() is called.
+class LoopOutputHandler {
+ public:
+  LoopOutputHandler();
+
+  void Quit() { run_ = false; }
+
+  void operator()();
+
+ protected:
+  // Read a message from the appropriate queue.
+  // This must block.
+  virtual void Read() = 0;
+
+  // Send the output from the appropriate queue to the hardware.
+  // Read() will always be called at least once before per invocation of this.
+  virtual void Write() = 0;
+
+  // Stop all outputs. This will be called in a separate thread (if at all).
+  // The subclass implementation should handle any appropriate logging.
+  // This will be called exactly once if Read() blocks for too long and once
+  // after Quit is called.
+  virtual void Stop() = 0;
+
+ private:
+  // The thread that actually contains a timerfd to implement timeouts. The
+  // idea is to have a timerfd that is repeatedly set to the timeout expiration
+  // in the future so it will never actually expire unless it is not reset for
+  // too long.
+  //
+  // This class nicely encapsulates the raw fd and manipulating it. Its
+  // operator() loops until Quit() is called, calling Stop() on its associated
+  // LoopOutputHandler whenever the timerfd expires.
+  class Watchdog {
+   public:
+    Watchdog(LoopOutputHandler *handler);
+
+    void operator()();
+
+    void Reset();
+
+    void Quit() { run_ = false; }
+
+   private:
+    LoopOutputHandler *const handler_;
+
+    ::aos::ScopedFD timerfd_;
+
+    ::std::atomic<bool> run_{true};
+  };
+
+  static constexpr ::aos::time::Time kStopTimeout =
+      ::aos::time::Time::InSeconds(0.02);
+
+  Watchdog watchdog_;
+
+  ::std::atomic<bool> run_{true};
+
+  ::aos::util::SimpleLogInterval no_joystick_state_ =
+      ::aos::util::SimpleLogInterval(::aos::time::Time::InSeconds(0.5), INFO,
+                                     "no joystick state -> not outputting");
+  ::aos::util::SimpleLogInterval fake_joystick_state_ =
+      ::aos::util::SimpleLogInterval(::aos::time::Time::InSeconds(0.5), DEBUG,
+                                     "fake joystick state -> not outputting");
+};
+
+}  // namespace wpilib
+}  // namespace frc971
+
+#endif  // FRC971_WPILIB_LOOP_OUTPUT_HANDLER_H_
diff --git a/frc971/wpilib/wpilib.gyp b/frc971/wpilib/wpilib.gyp
new file mode 100644
index 0000000..997b810
--- /dev/null
+++ b/frc971/wpilib/wpilib.gyp
@@ -0,0 +1,165 @@
+{
+  'targets': [
+    {
+      'target_name': 'logging_queue',
+      'type': 'static_library',
+      'sources': [
+        'logging.q',
+      ],
+      'variables': {
+        'header_path': 'frc971/wpilib',
+      },
+      'includes': [ '../../aos/build/queues.gypi' ],
+    },
+    {
+      'target_name': 'encoder_and_potentiometer',
+      'type': 'static_library',
+      'sources': [
+        'encoder_and_potentiometer.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):WPILib',
+        'dma_edge_counting',
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/common.gyp:mutex',
+      ],
+      'export_dependent_settings': [
+        '<(EXTERNALS):WPILib',
+        'dma_edge_counting',
+        '<(AOS)/common/common.gyp:mutex',
+      ],
+    },
+    {
+      'target_name': 'dma_edge_counting',
+      'type': 'static_library',
+      'sources': [
+        'dma_edge_counting.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):WPILib',
+        '<(AOS)/build/aos.gyp:logging',
+        'hall_effect',
+      ],
+      'export_dependent_settings': [
+        '<(EXTERNALS):WPILib',
+        'hall_effect',
+      ],
+    },
+    {
+      'target_name': 'interrupt_edge_counting',
+      'type': 'static_library',
+      'sources': [
+        'interrupt_edge_counting.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):WPILib',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/common.gyp:stl_mutex',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/linux_code/linux_code.gyp:init',
+      ],
+      'export_dependent_settings': [
+        '<(EXTERNALS):WPILib',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/common.gyp:stl_mutex',
+      ],
+    },
+    {
+      'target_name': 'buffered_pcm',
+      'type': 'static_library',
+      'sources': [
+        'buffered_solenoid.cc',
+        'buffered_pcm.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):WPILib',
+        '<(AOS)/build/aos.gyp:logging',
+      ],
+      'export_dependent_settings': [
+        '<(EXTERNALS):WPILib',
+      ],
+    },
+    {
+      'target_name': 'gyro_interface',
+      'type': 'static_library',
+      'sources': [
+        'gyro_interface.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):WPILib',
+        '<(AOS)/build/aos.gyp:logging',
+      ],
+      'export_dependent_settings': [
+        '<(EXTERNALS):WPILib',
+      ],
+    },
+    {
+      'target_name': 'gyro_sender',
+      'type': 'static_library',
+      'sources': [
+        'gyro_sender.cc',
+      ],
+      'dependencies': [
+        '<(DEPTH)/frc971/queues/queues.gyp:gyro',
+        'gyro_interface',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/logging/logging.gyp:queue_logging',
+        '<(AOS)/common/util/util.gyp:phased_loop',
+        '<(AOS)/common/messages/messages.gyp:robot_state',
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(AOS)/common/common.gyp:time',
+      ],
+      'export_dependent_settings': [
+        'gyro_interface',
+        '<(AOS)/common/common.gyp:time',
+      ],
+    },
+    {
+      'target_name': 'loop_output_handler',
+      'type': 'static_library',
+      'sources': [
+        'loop_output_handler.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/common/common.gyp:scoped_fd',
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/common/util/util.gyp:log_interval',
+        '<(AOS)/common/messages/messages.gyp:robot_state',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/common.gyp:scoped_fd',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/common/util/util.gyp:log_interval',
+      ],
+    },
+    {
+      'target_name': 'joystick_sender',
+      'type': 'static_library',
+      'sources': [
+        'joystick_sender.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):WPILib',
+        '<(AOS)/common/messages/messages.gyp:robot_state',
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(AOS)/common/network/network.gyp:team_number',
+        '<(AOS)/common/logging/logging.gyp:queue_logging',
+      ],
+    },
+    {
+      'target_name': 'hall_effect',
+      'type': 'static_library',
+      'sources': [
+        #'hall_effect.h',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):WPILib',
+      ],
+      'export_dependent_settings': [
+        '<(EXTERNALS):WPILib',
+      ],
+    },
+  ],
+}
diff --git a/frc971/zeroing/zeroing.cc b/frc971/zeroing/zeroing.cc
new file mode 100644
index 0000000..e54446a
--- /dev/null
+++ b/frc971/zeroing/zeroing.cc
@@ -0,0 +1,124 @@
+#include "frc971/zeroing/zeroing.h"
+
+#include <cmath>
+#include <vector>
+
+namespace frc971 {
+namespace zeroing {
+
+void PopulateEstimatorState(const zeroing::ZeroingEstimator& estimator,
+                            EstimatorState* state) {
+  state->error = estimator.error();
+  state->zeroed = estimator.zeroed();
+  state->position = estimator.position();
+}
+
+ZeroingEstimator::ZeroingEstimator(
+    const constants::ZeroingConstants& constants) {
+  index_diff_ = constants.index_difference;
+  max_sample_count_ = constants.average_filter_size;
+  known_index_pos_ = constants.measured_index_position;
+  allowable_encoder_error_ = constants.allowable_encoder_error;
+  start_pos_samples_.reserve(max_sample_count_);
+  Reset();
+}
+
+void ZeroingEstimator::Reset() {
+  samples_idx_ = 0;
+  start_pos_ = 0;
+  start_pos_samples_.clear();
+  zeroed_ = false;
+  wait_for_index_pulse_ = true;
+  last_used_index_pulse_count_ = 0;
+  first_start_pos_ = 0.0;
+  error_ = false;
+}
+
+void ZeroingEstimator::TriggerError() {
+  if (!error_) {
+    LOG(ERROR, "Manually triggered zeroing error.\n");
+    error_ = true;
+  }
+}
+
+double ZeroingEstimator::CalculateStartPosition(double start_average,
+                                                double latched_encoder) const {
+  // We calculate an aproximation of the value of the last index position.
+  // Also account for index pulses not lining up with integer multiples of the
+  // index_diff.
+  double index_pos = start_average + latched_encoder - known_index_pos_;
+  // We round index_pos to the closest valid value of the index.
+  double accurate_index_pos = (round(index_pos / index_diff_)) * index_diff_;
+  // Now we reverse the first calculation to get the accurate start position.
+  return accurate_index_pos - latched_encoder + known_index_pos_;
+}
+
+void ZeroingEstimator::UpdateEstimate(const PotAndIndexPosition& info) {
+  // We want to make sure that we encounter at least one index pulse while
+  // zeroing. So we take the index pulse count from the first sample after
+  // reset and wait for that count to change before we consider ourselves
+  // zeroed.
+  if (wait_for_index_pulse_) {
+    last_used_index_pulse_count_ = info.index_pulses;
+    wait_for_index_pulse_ = false;
+  }
+
+  if (start_pos_samples_.size() < max_sample_count_) {
+    start_pos_samples_.push_back(info.pot - info.encoder);
+  } else {
+    start_pos_samples_[samples_idx_] = info.pot - info.encoder;
+  }
+
+  // Drop the oldest sample when we run this function the next time around.
+  samples_idx_ = (samples_idx_ + 1) % max_sample_count_;
+
+  double sample_sum = 0.0;
+
+  for (size_t i = 0; i < start_pos_samples_.size(); ++i) {
+    sample_sum += start_pos_samples_[i];
+  }
+
+  // Calculates the average of the starting position.
+  double start_average = sample_sum / start_pos_samples_.size();
+
+  // If there are no index pulses to use or we don't have enough samples yet to
+  // have a well-filtered starting position then we use the filtered value as
+  // our best guess.
+  if (!zeroed_ && (info.index_pulses == last_used_index_pulse_count_ ||
+                   offset_ratio_ready() < 1.0)) {
+    start_pos_ = start_average;
+  } else if (!zeroed_ || last_used_index_pulse_count_ != info.index_pulses) {
+    // Note the accurate start position and the current index pulse count so
+    // that we only run this logic once per index pulse. That should be more
+    // resilient to corrupted intermediate data.
+    start_pos_ = CalculateStartPosition(start_average, info.latched_encoder);
+    last_used_index_pulse_count_ = info.index_pulses;
+    // Save the first starting position.
+    if (!zeroed_) {
+      first_start_pos_ = start_pos_;
+      LOG(INFO, "latching start position %f\n", first_start_pos_);
+    }
+
+    // Now that we have an accurate starting position we can consider ourselves
+    // zeroed.
+    zeroed_ = true;
+    // Throw an error if first_start_pos is bigger/smaller than
+    // allowable_encoder_error_ * index_diff +
+    // start_pos.
+    if (::std::abs(first_start_pos_ - start_pos_) >
+        allowable_encoder_error_ * index_diff_) {
+      if (!error_) {
+        LOG(ERROR,
+            "Encoder ticks out of range since last index pulse. first start "
+            "position: %f recent starting position: %f\n",
+            first_start_pos_, start_pos_);
+        error_ = true;
+      }
+    }
+  }
+
+  pos_ = start_pos_ + info.encoder;
+}
+
+}  // namespace zeroing
+}  // namespace frc971
diff --git a/frc971/zeroing/zeroing.gyp b/frc971/zeroing/zeroing.gyp
new file mode 100644
index 0000000..0a7a2fc
--- /dev/null
+++ b/frc971/zeroing/zeroing.gyp
@@ -0,0 +1,33 @@
+{
+  'targets': [
+    {
+      'target_name': 'zeroing',
+      'type': 'static_library',
+      'sources': [
+        'zeroing.cc',
+      ],
+      'dependencies': [
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:queues',
+      ],
+      'export_dependent_settings': [
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:queues',
+      ],
+    },
+    {
+      'target_name': 'zeroing_test',
+      'type': 'executable',
+      'sources': [
+        'zeroing_test.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+        '<(AOS)/common/common.gyp:queue_testutils',
+        'zeroing',
+        '<(AOS)/common/util/util.gyp:thread',
+        '<(AOS)/common/common.gyp:die',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:position_sensor_sim',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:queues',
+      ],
+    },
+  ],
+}
diff --git a/frc971/zeroing/zeroing.h b/frc971/zeroing/zeroing.h
new file mode 100644
index 0000000..4176f48
--- /dev/null
+++ b/frc971/zeroing/zeroing.h
@@ -0,0 +1,121 @@
+#ifndef FRC971_ZEROING_ZEROING_H_
+#define FRC971_ZEROING_ZEROING_H_
+
+#include <cstdint>
+#include <vector>
+
+#include "frc971/control_loops/control_loops.q.h"
+#include "frc971/constants.h"
+
+// TODO(pschrader): Flag an error if encoder index pulse is not n revolutions
+// away from the last one (i.e. got extra counts from noise, etc..)
+//
+// TODO(pschrader): Flag error if the pot disagrees too much with the encoder
+// after being zeroed.
+//
+// TODO(pschrader): Watch the offset over long periods of time and flag if it
+// gets too far away from the initial value.
+
+namespace frc971 {
+namespace zeroing {
+
+// Estimates the position with encoder,
+// the pot and the indices.
+class ZeroingEstimator {
+ public:
+  ZeroingEstimator(const constants::ZeroingConstants &constants);
+
+  // Update the internal logic with the next sensor values.
+  void UpdateEstimate(const PotAndIndexPosition &info);
+
+  // Reset the internal logic so it needs to be re-zeroed.
+  void Reset();
+
+  // Manually trigger an internal error. This is used for testing the error
+  // logic.
+  void TriggerError();
+
+  // Returns true if an error has occurred, false otherwise. This gets reset to
+  // false when the Reset() function is called.
+  bool error() const { return error_; }
+
+  // Returns true if the logic considers the corresponding mechanism to be
+  // zeroed. It return false otherwise. For example, right after a call to
+  // Reset() this returns false.
+  bool zeroed() const { return zeroed_; }
+
+  // Return the estimated position of the corresponding mechanism. This value
+  // is in SI units. For example, the estimator for the elevator would return a
+  // value in meters for the height relative to absolute zero.
+  double position() const { return pos_; }
+
+  // Return the estimated starting position of the corresponding mechansim. In
+  // some contexts we refer to this as the "offset".
+  double offset() const { return start_pos_; }
+
+  // Returns a number between 0 and 1 that represents the percentage of the
+  // samples being used in the moving average filter. A value of 0.0 means that
+  // no samples are being used. A value of 1.0 means that the filter is using
+  // as many samples as it has room for. For example, after a Reset() this
+  // value returns 0.0. As more samples get added with UpdateEstimate(...) the
+  // return value starts increasing to 1.0.
+  double offset_ratio_ready() const {
+    return start_pos_samples_.size() / static_cast<double>(max_sample_count_);
+  }
+
+ private:
+  // This function calculates the start position given the internal state and
+  // the provided `latched_encoder' value.
+  double CalculateStartPosition(double start_average,
+                                double latched_encoder) const;
+
+  // The estimated position.
+  double pos_;
+  // The distance between two consecutive index positions.
+  double index_diff_;
+  // The next position in 'start_pos_samples_' to be used to store the next
+  // sample.
+  int samples_idx_;
+  // Last 'max_sample_count_' samples for start positions.
+  std::vector<double> start_pos_samples_;
+  // The number of the last samples of start position to consider in the
+  // estimation.
+  size_t max_sample_count_;
+  // The estimated starting position of the mechanism. We also call this the
+  // 'offset' in some contexts.
+  double start_pos_;
+  // The absolute position of any index pulse on the mechanism. This is used to
+  // account for the various ways the encoders get mounted into the robot.
+  double known_index_pos_;
+  // Flag for triggering logic that takes note of the current index pulse count
+  // after a reset. See `last_used_index_pulse_count_'.
+  bool wait_for_index_pulse_;
+  // After a reset we keep track of the index pulse count with this. Only after
+  // the index pulse count changes (i.e. increments at least once or wraps
+  // around) will we consider the mechanism zeroed. We also use this to store
+  // the most recent `PotAndIndexPosition::index_pulses' value when the start
+  // position was calculated. It helps us calculate the start position only on
+  // index pulses to reject corrupted intermediate data.
+  uint32_t last_used_index_pulse_count_;
+  // Marker to track whether we're fully zeroed yet or not.
+  bool zeroed_;
+  // Marker to track whether an error has occurred. This gets reset to false
+  // whenever Reset() is called.
+  bool error_;
+  // Stores the position "start_pos" variable the first time the program
+  // is zeroed.
+  double first_start_pos_;
+  // Value between 0 and 1 which determines a fraction of the index_diff
+  // you want to use.
+  double allowable_encoder_error_;
+};
+
+// Populates an EstimatorState struct with information from the zeroing
+// estimator.
+void PopulateEstimatorState(const ZeroingEstimator &estimator,
+                            EstimatorState *state);
+
+}  // namespace zeroing
+}  // namespace frc971
+
+#endif  // FRC971_ZEROING_ZEROING_H_
diff --git a/frc971/zeroing/zeroing_queue.q b/frc971/zeroing/zeroing_queue.q
new file mode 100644
index 0000000..e218173
--- /dev/null
+++ b/frc971/zeroing/zeroing_queue.q
@@ -0,0 +1,14 @@
+package frc971.zeroing;
+
+struct ZeroingInfo {
+	double pot;
+	double encoder;
+	double index_encoder;
+	int32_t index_count;
+};
+
+message TestMessage {
+	int32_t test_int;
+};
+
+queue TestMessage test_queue;
diff --git a/frc971/zeroing/zeroing_test.cc b/frc971/zeroing/zeroing_test.cc
new file mode 100644
index 0000000..4a82e04
--- /dev/null
+++ b/frc971/zeroing/zeroing_test.cc
@@ -0,0 +1,297 @@
+#include <unistd.h>
+
+#include <memory>
+
+#include <random>
+
+#include "gtest/gtest.h"
+#include "frc971/zeroing/zeroing.h"
+#include "frc971/control_loops/control_loops.q.h"
+#include "aos/common/queue_testutils.h"
+#include "aos/common/util/thread.h"
+#include "aos/common/die.h"
+#include "frc971/control_loops/position_sensor_sim.h"
+
+namespace frc971 {
+namespace zeroing {
+
+using control_loops::PositionSensorSimulator;
+using constants::ZeroingConstants;
+
+static const size_t kSampleSize = 30;
+static const double kAcceptableUnzeroedError = 0.2;
+static const double kIndexErrorFraction = 0.3;
+
+class ZeroingTest : public ::testing::Test {
+ protected:
+  void SetUp() override { aos::SetDieTestMode(true); }
+
+  void MoveTo(PositionSensorSimulator* simulator, ZeroingEstimator* estimator,
+              double new_position) {
+    PotAndIndexPosition sensor_values_;
+    simulator->MoveTo(new_position);
+    simulator->GetSensorValues(&sensor_values_);
+    estimator->UpdateEstimate(sensor_values_);
+  }
+
+  aos::common::testing::GlobalCoreInstance my_core;
+};
+
+TEST_F(ZeroingTest, TestMovingAverageFilter) {
+  const double index_diff = 1.0;
+  PositionSensorSimulator sim(index_diff);
+  sim.Initialize(3.6 * index_diff, index_diff / 3.0);
+  ZeroingEstimator estimator(ZeroingConstants{
+      kSampleSize, index_diff, 0.0, kIndexErrorFraction});
+
+  // The zeroing code is supposed to perform some filtering on the difference
+  // between the potentiometer value and the encoder value. We assume that 300
+  // samples are sufficient to have updated the filter.
+  for (int i = 0; i < 300; i++) {
+    MoveTo(&sim, &estimator, 3.3 * index_diff);
+  }
+  ASSERT_NEAR(3.3 * index_diff, estimator.position(),
+              kAcceptableUnzeroedError * index_diff);
+
+  for (int i = 0; i < 300; i++) {
+    MoveTo(&sim, &estimator, 3.9 * index_diff);
+  }
+  ASSERT_NEAR(3.9 * index_diff, estimator.position(),
+              kAcceptableUnzeroedError * index_diff);
+}
+
+TEST_F(ZeroingTest, NotZeroedBeforeEnoughSamplesCollected) {
+  double index_diff = 0.5;
+  double position = 3.6 * index_diff;
+  PositionSensorSimulator sim(index_diff);
+  sim.Initialize(position, index_diff / 3.0);
+  ZeroingEstimator estimator(ZeroingConstants{
+      kSampleSize, index_diff, 0.0, kIndexErrorFraction});
+
+  // Make sure that the zeroing code does not consider itself zeroed until we
+  // collect a good amount of samples. In this case we're waiting until the
+  // moving average filter is full.
+  for (unsigned int i = 0; i < kSampleSize - 1; i++) {
+    MoveTo(&sim, &estimator, position += index_diff);
+    ASSERT_FALSE(estimator.zeroed());
+  }
+
+  MoveTo(&sim, &estimator, position);
+  ASSERT_TRUE(estimator.zeroed());
+}
+
+TEST_F(ZeroingTest, TestLotsOfMovement) {
+  double index_diff = 1.0;
+  PositionSensorSimulator sim(index_diff);
+  sim.Initialize(3.6, index_diff / 3.0);
+  ZeroingEstimator estimator(ZeroingConstants{
+      kSampleSize, index_diff, 0.0, kIndexErrorFraction});
+
+  // The zeroing code is supposed to perform some filtering on the difference
+  // between the potentiometer value and the encoder value. We assume that 300
+  // samples are sufficient to have updated the filter.
+  for (int i = 0; i < 300; i++) {
+    MoveTo(&sim, &estimator, 3.6);
+  }
+  ASSERT_NEAR(3.6, estimator.position(), kAcceptableUnzeroedError * index_diff);
+
+  // With a single index pulse the zeroing estimator should be able to lock
+  // onto the true value of the position.
+  MoveTo(&sim, &estimator, 4.01);
+  ASSERT_NEAR(4.01, estimator.position(), 0.001);
+
+  MoveTo(&sim, &estimator, 4.99);
+  ASSERT_NEAR(4.99, estimator.position(), 0.001);
+
+  MoveTo(&sim, &estimator, 3.99);
+  ASSERT_NEAR(3.99, estimator.position(), 0.001);
+
+  MoveTo(&sim, &estimator, 3.01);
+  ASSERT_NEAR(3.01, estimator.position(), 0.001);
+
+  MoveTo(&sim, &estimator, 13.55);
+  ASSERT_NEAR(13.55, estimator.position(), 0.001);
+}
+
+TEST_F(ZeroingTest, TestDifferentIndexDiffs) {
+  double index_diff = 0.89;
+  PositionSensorSimulator sim(index_diff);
+  sim.Initialize(3.5 * index_diff, index_diff / 3.0);
+  ZeroingEstimator estimator(ZeroingConstants{
+      kSampleSize, index_diff, 0.0, kIndexErrorFraction});
+
+  // The zeroing code is supposed to perform some filtering on the difference
+  // between the potentiometer value and the encoder value. We assume that 300
+  // samples are sufficient to have updated the filter.
+  for (int i = 0; i < 300; i++) {
+    MoveTo(&sim, &estimator, 3.5 * index_diff);
+  }
+  ASSERT_NEAR(3.5 * index_diff, estimator.position(),
+              kAcceptableUnzeroedError * index_diff);
+
+  // With a single index pulse the zeroing estimator should be able to lock
+  // onto the true value of the position.
+  MoveTo(&sim, &estimator, 4.01);
+  ASSERT_NEAR(4.01, estimator.position(), 0.001);
+
+  MoveTo(&sim, &estimator, 4.99);
+  ASSERT_NEAR(4.99, estimator.position(), 0.001);
+
+  MoveTo(&sim, &estimator, 3.99);
+  ASSERT_NEAR(3.99, estimator.position(), 0.001);
+
+  MoveTo(&sim, &estimator, 3.01);
+  ASSERT_NEAR(3.01, estimator.position(), 0.001);
+
+  MoveTo(&sim, &estimator, 13.55);
+  ASSERT_NEAR(13.55, estimator.position(), 0.001);
+}
+
+TEST_F(ZeroingTest, TestPercentage) {
+  double index_diff = 0.89;
+  PositionSensorSimulator sim(index_diff);
+  sim.Initialize(3.5 * index_diff, index_diff / 3.0);
+  ZeroingEstimator estimator(ZeroingConstants{
+      kSampleSize, index_diff, 0.0, kIndexErrorFraction});
+
+  for (unsigned int i = 0; i < kSampleSize / 2; i++) {
+    MoveTo(&sim, &estimator, 3.5 * index_diff);
+  }
+  ASSERT_NEAR(0.5, estimator.offset_ratio_ready(), 0.001);
+}
+
+TEST_F(ZeroingTest, TestOffset) {
+  double index_diff = 0.89;
+  PositionSensorSimulator sim(index_diff);
+  sim.Initialize(3.1 * index_diff, index_diff / 3.0);
+  ZeroingEstimator estimator(ZeroingConstants{
+      kSampleSize, index_diff, 0.0, kIndexErrorFraction});
+
+  MoveTo(&sim, &estimator, 3.1 * index_diff);
+
+  for (unsigned int i = 0; i < kSampleSize; i++) {
+    MoveTo(&sim, &estimator, 5.0 * index_diff);
+  }
+
+  ASSERT_NEAR(3.1 * index_diff, estimator.offset(), 0.001);
+}
+
+TEST_F(ZeroingTest, WaitForIndexPulseAfterReset) {
+  double index_diff = 0.6;
+  PositionSensorSimulator sim(index_diff);
+  sim.Initialize(3.1 * index_diff, index_diff / 3.0);
+  ZeroingEstimator estimator(ZeroingConstants{
+      kSampleSize, index_diff, 0.0, kIndexErrorFraction});
+
+  // Make sure to fill up the averaging filter with samples.
+  for (unsigned int i = 0; i < kSampleSize; i++) {
+    MoveTo(&sim, &estimator, 3.1 * index_diff);
+  }
+
+  // Make sure we're not zeroed until we hit an index pulse.
+  ASSERT_FALSE(estimator.zeroed());
+
+  // Trigger an index pulse; we should now be zeroed.
+  MoveTo(&sim, &estimator, 4.5 * index_diff);
+  ASSERT_TRUE(estimator.zeroed());
+
+  // Reset the zeroing logic and supply a bunch of samples within the current
+  // index segment.
+  estimator.Reset();
+  for (unsigned int i = 0; i < kSampleSize; i++) {
+    MoveTo(&sim, &estimator, 4.2 * index_diff);
+  }
+
+  // Make sure we're not zeroed until we hit an index pulse.
+  ASSERT_FALSE(estimator.zeroed());
+
+  // Trigger another index pulse; we should be zeroed again.
+  MoveTo(&sim, &estimator, 3.1 * index_diff);
+  ASSERT_TRUE(estimator.zeroed());
+}
+
+TEST_F(ZeroingTest, TestNonZeroIndexPulseOffsets) {
+  const double index_diff = 0.9;
+  const double known_index_pos = 3.5 * index_diff;
+  PositionSensorSimulator sim(index_diff);
+  sim.Initialize(3.3 * index_diff, index_diff / 3.0, known_index_pos);
+  ZeroingEstimator estimator(ZeroingConstants{
+      kSampleSize, index_diff, known_index_pos, kIndexErrorFraction});
+
+  // Make sure to fill up the averaging filter with samples.
+  for (unsigned int i = 0; i < kSampleSize; i++) {
+    MoveTo(&sim, &estimator, 3.3 * index_diff);
+  }
+
+  // Make sure we're not zeroed until we hit an index pulse.
+  ASSERT_FALSE(estimator.zeroed());
+
+  // Trigger an index pulse; we should now be zeroed.
+  MoveTo(&sim, &estimator, 3.7 * index_diff);
+  ASSERT_TRUE(estimator.zeroed());
+  ASSERT_DOUBLE_EQ(3.3 * index_diff, estimator.offset());
+  ASSERT_DOUBLE_EQ(3.7 * index_diff, estimator.position());
+
+  // Trigger one more index pulse and check the offset.
+  MoveTo(&sim, &estimator, 4.7 * index_diff);
+  ASSERT_DOUBLE_EQ(3.3 * index_diff, estimator.offset());
+  ASSERT_DOUBLE_EQ(4.7 * index_diff, estimator.position());
+}
+
+TEST_F(ZeroingTest, BasicErrorAPITest) {
+  const double index_diff = 1.0;
+  ZeroingEstimator estimator(ZeroingConstants{
+      kSampleSize, index_diff, 0.0, kIndexErrorFraction});
+  PositionSensorSimulator sim(index_diff);
+  sim.Initialize(1.5 * index_diff, index_diff / 3.0, 0.0);
+
+  // Perform a simple move and make sure that no error occured.
+  MoveTo(&sim, &estimator, 3.5 * index_diff);
+  ASSERT_FALSE(estimator.error());
+
+  // Trigger an error and make sure it's reported.
+  estimator.TriggerError();
+  ASSERT_TRUE(estimator.error());
+
+  // Make sure that it can recover after a reset.
+  estimator.Reset();
+  ASSERT_FALSE(estimator.error());
+  MoveTo(&sim, &estimator, 4.5 * index_diff);
+  MoveTo(&sim, &estimator, 5.5 * index_diff);
+  ASSERT_FALSE(estimator.error());
+}
+
+// I want to test that the the zeroing class can
+// detect an error when the starting position
+// changes too much. I do so by creating the
+// simulator at an 'X' positon, making sure
+// that the estimator is zeroed, and then
+// initializing the simulator at another
+// position. After making sure it's zeroed,
+// if the error() function returns true,
+// then, it works.
+TEST_F(ZeroingTest, TestOffsetError) {
+  const double index_diff = 0.8;
+  const double known_index_pos = 2 * index_diff;
+  int sample_size = 30;
+  PositionSensorSimulator sim(index_diff);
+  sim.Initialize(10 * index_diff, index_diff / 3.0, known_index_pos);
+  ZeroingEstimator estimator(ZeroingConstants{
+      sample_size, index_diff, known_index_pos, kIndexErrorFraction});
+
+  for (int i = 0; i < sample_size; i++) {
+    MoveTo(&sim, &estimator, 13 * index_diff);
+  }
+  MoveTo(&sim, &estimator, 8 * index_diff);
+
+  ASSERT_TRUE(estimator.zeroed());
+  ASSERT_FALSE(estimator.error());
+  sim.Initialize(9.0 * index_diff + 0.31 * index_diff, index_diff / 3.0,
+                 known_index_pos);
+  MoveTo(&sim, &estimator, 9 * index_diff);
+  ASSERT_TRUE(estimator.zeroed());
+  ASSERT_TRUE(estimator.error());
+}
+
+}  // namespace zeroing
+}  // namespace frc971
diff --git a/output/.gitignore b/output/.gitignore
new file mode 100644
index 0000000..d675b14
--- /dev/null
+++ b/output/.gitignore
@@ -0,0 +1,16 @@
+/prime/
+/crio/
+/flasher/
+/compiled-*/
+/ip_address.txt
+/ccache_dir/
+
+/crio/
+/crio-debug/
+
+/arm_frc-[^-]*-[^-]*/
+/arm_frc-[^-]*-debug-[^-]*/
+/amd64-[^-]*-[^-]*/
+/amd64-[^-]*-debug-[^-]*/
+/bot3-[^-]*-[^-]*-[^-]*/
+/bot3-[^-]*-[^-]*-debug-[^-]*/
diff --git a/output/downloaded/.gitignore b/output/downloaded/.gitignore
new file mode 100644
index 0000000..b59b5d2
--- /dev/null
+++ b/output/downloaded/.gitignore
@@ -0,0 +1,21 @@
+/ctemplate-129.tar.gz
+/ctemplate-129/
+/eigen-3.2.1.tar.bz2
+/eigen-3.2.1/
+/gtest-1.6.0-p2/
+/gtest-1.6.0.zip
+/gyp-1738/
+/jpeg-8d/
+/jpegsrc.v8d.tar.gz
+/libjpeg/
+/ninja-v1.4.0/
+/gflags-2.0.tar.gz
+/gflags-2.0/
+/libevent-2.0.21.tar.gz
+/libevent-2.0.21/
+/libcdd-094g.tar.gz
+/libcdd-094g/
+/gmp-5.1.3.tar.lz
+/gperftools-2.3.tar.gz
+/libunwind-1.1.tar.gz
+/seasocks-1.1.2-p1/
diff --git a/third_party/gflags/.gitattributes b/third_party/gflags/.gitattributes
new file mode 100644
index 0000000..87fe9c0
--- /dev/null
+++ b/third_party/gflags/.gitattributes
@@ -0,0 +1,3 @@
+# treat all files in this repository as text files
+# and normalize them to LF line endings when committed
+* text
diff --git a/third_party/gflags/.gitignore b/third_party/gflags/.gitignore
new file mode 100644
index 0000000..4281522
--- /dev/null
+++ b/third_party/gflags/.gitignore
@@ -0,0 +1,17 @@
+/xcode/
+/build/
+/build-*/
+.DS_Store
+CMakeCache.txt
+DartConfiguration.tcl
+Makefile
+CMakeFiles/
+/Testing/
+/include/gflags/config.h
+/include/gflags/gflags_completions.h
+/include/gflags/gflags_declare.h
+/include/gflags/gflags.h
+/lib/
+/test/gflags_unittest_main.cc
+/test/gflags_unittest-main.cc
+/packages/
diff --git a/third_party/gflags/.gitmodules b/third_party/gflags/.gitmodules
new file mode 100644
index 0000000..aa2072c
--- /dev/null
+++ b/third_party/gflags/.gitmodules
@@ -0,0 +1,4 @@
+[submodule "doc"]
+	path = doc
+	url = https://github.com/gflags/gflags.git
+	branch = gh-pages
diff --git a/third_party/gflags/AUTHORS.txt b/third_party/gflags/AUTHORS.txt
new file mode 100644
index 0000000..887918b
--- /dev/null
+++ b/third_party/gflags/AUTHORS.txt
@@ -0,0 +1,2 @@
+google-gflags@googlegroups.com
+
diff --git a/third_party/gflags/CMakeLists.txt b/third_party/gflags/CMakeLists.txt
new file mode 100644
index 0000000..c32bce3
--- /dev/null
+++ b/third_party/gflags/CMakeLists.txt
@@ -0,0 +1,510 @@
+cmake_minimum_required (VERSION 2.8.12 FATAL_ERROR)
+
+if (POLICY CMP0042)
+  cmake_policy (SET CMP0042 NEW)
+endif ()
+
+# ----------------------------------------------------------------------------
+# includes
+set (CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
+include (utils)
+
+# ----------------------------------------------------------------------------
+# package information
+set (PACKAGE_NAME      "gflags")
+set (PACKAGE_VERSION   "2.2.0")
+set (PACKAGE_STRING    "${PACKAGE_NAME} ${PACKAGE_VERSION}")
+set (PACKAGE_TARNAME   "${PACKAGE_NAME}-${PACKAGE_VERSION}")
+set (PACKAGE_BUGREPORT "https://github.com/schuhschuh/gflags/issues")
+
+project (${PACKAGE_NAME} CXX)
+if (CMAKE_VERSION VERSION_LESS 100)
+  # C language still needed because the following required CMake modules
+  # (or their dependencies, respectively) are not correctly handling
+  # the case where only CXX is enabled.
+  # - CheckTypeSize.cmake (fixed in CMake 3.1, cf. http://www.cmake.org/Bug/view.php?id=14056)
+  # - FindThreads.cmake (--> CheckIncludeFiles.cmake <--)
+  enable_language (C)
+endif ()
+
+version_numbers (
+  ${PACKAGE_VERSION}
+    PACKAGE_VERSION_MAJOR
+    PACKAGE_VERSION_MINOR
+    PACKAGE_VERSION_PATCH
+)
+
+set (PACKAGE_SOVERSION "${PACKAGE_VERSION_MAJOR}")
+
+# ----------------------------------------------------------------------------
+# options
+if (NOT GFLAGS_NAMESPACE)
+  # maintain binary backwards compatibility with gflags library version <= 2.0,
+  # but at the same time enable the use of the preferred new "gflags" namespace
+  set (GFLAGS_NAMESPACE "google;${PACKAGE_NAME}" CACHE STRING "Name(s) of library namespace (separate multiple options by semicolon)")
+  mark_as_advanced (GFLAGS_NAMESPACE)
+endif ()
+set (GFLAGS_NAMESPACE_SECONDARY "${GFLAGS_NAMESPACE}")
+list (REMOVE_DUPLICATES GFLAGS_NAMESPACE_SECONDARY)
+if (NOT GFLAGS_NAMESPACE_SECONDARY)
+  message (FATAL_ERROR "GFLAGS_NAMESPACE must be set to one (or more) valid C++ namespace identifier(s separated by semicolon \";\").")
+endif ()
+foreach (ns IN LISTS GFLAGS_NAMESPACE_SECONDARY)
+  if (NOT ns MATCHES "^[a-zA-Z][a-zA-Z0-9_]*$")
+    message (FATAL_ERROR "GFLAGS_NAMESPACE contains invalid namespace identifier: ${ns}")
+  endif ()
+endforeach ()
+list (GET       GFLAGS_NAMESPACE_SECONDARY 0 GFLAGS_NAMESPACE)
+list (REMOVE_AT GFLAGS_NAMESPACE_SECONDARY 0)
+
+option (BUILD_SHARED_LIBS          "Request build of shared libraries."                                       OFF)
+option (BUILD_STATIC_LIBS          "Request build of static libraries (default if BUILD_SHARED_LIBS is OFF)." OFF)
+option (BUILD_gflags_LIB           "Request build of the multi-threaded gflags library."                      ON)
+option (BUILD_gflags_nothreads_LIB "Request build of the single-threaded gflags library."                     ON)
+option (BUILD_PACKAGING            "Enable build of distribution packages using CPack."                       OFF)
+option (BUILD_TESTING              "Enable build of the unit tests and their execution using CTest."          OFF)
+option (INSTALL_HEADERS            "Request packaging of headers and other development files."                ON)
+
+mark_as_advanced (CLEAR CMAKE_INSTALL_PREFIX)
+mark_as_advanced (CMAKE_CONFIGURATION_TYPES
+                  BUILD_STATIC_LIBS
+                  INSTALL_HEADERS)
+if (APPLE)
+  mark_as_advanced(CMAKE_OSX_ARCHITECTURES
+                   CMAKE_OSX_DEPLOYMENT_TARGET
+                   CMAKE_OSX_SYSROOT)
+endif ()
+
+if (NOT BUILD_SHARED_LIBS AND NOT BUILD_STATIC_LIBS)
+  set (BUILD_STATIC_LIBS ON)
+endif ()
+if (NOT BUILD_gflags_LIB AND NOT BUILD_gflags_nothreads_LIB)
+ message (FATAL_ERROR "At least one of BUILD_gflags_LIB and BUILD_gflags_nothreads_LIB must be ON.")
+endif ()
+
+if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CXX_FLAGS)
+  set_property (CACHE CMAKE_BUILD_TYPE PROPERTY VALUE Release)
+endif ()
+
+if (NOT GFLAGS_INCLUDE_DIR)
+  set (GFLAGS_INCLUDE_DIR "${PACKAGE_NAME}" CACHE STRING "Name of include directory of installed header files")
+  mark_as_advanced (GFLAGS_INCLUDE_DIR)
+else ()
+  if (IS_ABSOLUTE GFLAGS_INCLUDE_DIR)
+    message (FATAL_ERROR "GFLAGS_INCLUDE_DIR must be a path relative to CMAKE_INSTALL_PREFIX/include")
+  endif ()
+  if (GFLAGS_INCLUDE_DIR MATCHES "^\\.\\.[/\\]")
+    message (FATAL_ERROR "GFLAGS_INCLUDE_DIR must not start with parent directory reference (../)")
+  endif ()
+endif ()
+
+# ----------------------------------------------------------------------------
+# system checks
+include (CheckTypeSize)
+include (CheckIncludeFileCXX)
+include (CheckCXXSymbolExists)
+
+if (WIN32 AND NOT CYGWIN)
+  set (OS_WINDOWS 1)
+else ()
+  set (OS_WINDOWS 0)
+endif ()
+
+if (MSVC)
+  set (HAVE_SYS_TYPES_H 1)
+  set (HAVE_STDINT_H    1)
+  set (HAVE_STDDEF_H    1) # used by CheckTypeSize module
+  set (HAVE_INTTYPES_H  0)
+  set (HAVE_UNISTD_H    0)
+  set (HAVE_SYS_STAT_H  1)
+  set (HAVE_SHLWAPI_H   1)
+else ()
+  foreach (fname IN ITEMS unistd stdint inttypes sys/types sys/stat fnmatch)
+    string (TOUPPER "${fname}" FNAME)
+    string (REPLACE "/" "_" FNAME "${FNAME}")
+    if (NOT HAVE_${FNAME}_H)
+      check_include_file_cxx ("${fname}.h" HAVE_${FNAME}_H)
+    endif ()
+  endforeach ()
+  # the following are used in #if directives not #ifdef
+  bool_to_int (HAVE_STDINT_H)
+  bool_to_int (HAVE_SYS_TYPES_H)
+  bool_to_int (HAVE_INTTYPES_H)
+  if (NOT HAVE_FNMATCH_H AND OS_WINDOWS)
+    check_include_file_cxx ("shlwapi.h" HAVE_SHLWAPI_H)
+  endif ()
+endif ()
+
+set (GFLAGS_INTTYPES_FORMAT "" CACHE STRING "Format of integer types: \"C99\" (uint32_t), \"BSD\" (u_int32_t), \"VC7\" (__int32)")
+set_property (CACHE GFLAGS_INTTYPES_FORMAT PROPERTY STRINGS "C99;BSD;VC7")
+mark_as_advanced (GFLAGS_INTTYPES_FORMAT)
+if (NOT GFLAGS_INTTYPES_FORMAT)
+  set (TYPES uint32_t u_int32_t)
+  if (MSVC)
+    list (INSERT TYPES 0 __int32)
+  endif ()
+  foreach (type IN LISTS TYPES)
+    check_type_size (${type} ${type} LANGUAGE CXX)
+    if (HAVE_${type})
+      break ()
+    endif ()
+  endforeach ()
+  if (HAVE_uint32_t)
+    set_property (CACHE GFLAGS_INTTYPES_FORMAT PROPERTY VALUE C99)
+  elseif (HAVE_u_int32_t)
+    set_property (CACHE GFLAGS_INTTYPES_FORMAT PROPERTY VALUE BSD)
+  elseif (HAVE___int32)
+    set_property (CACHE GFLAGS_INTTYPES_FORMAT PROPERTY VALUE VC7)
+  else ()
+    mark_as_advanced (CLEAR GFLAGS_INTTYPES_FORMAT)
+    message (FATAL_ERROR "Do not know how to define a 32-bit integer quantity on your system!"
+                         " Neither uint32_t, u_int32_t, nor __int32 seem to be available."
+                         " Set GFLAGS_INTTYPES_FORMAT to either C99, BSD, or VC7 and try again.")
+  endif ()
+endif ()
+# use of special characters in strings to circumvent bug #0008226
+if ("^${GFLAGS_INTTYPES_FORMAT}$" STREQUAL "^WIN$")
+  set_property (CACHE GFLAGS_INTTYPES_FORMAT PROPERTY VALUE VC7)
+endif ()
+if (NOT GFLAGS_INTTYPES_FORMAT MATCHES "^(C99|BSD|VC7)$")
+  message (FATAL_ERROR "Invalid value for GFLAGS_INTTYPES_FORMAT! Choose one of \"C99\", \"BSD\", or \"VC7\"")
+endif ()
+set (GFLAGS_INTTYPES_FORMAT_C99 0)
+set (GFLAGS_INTTYPES_FORMAT_BSD 0)
+set (GFLAGS_INTTYPES_FORMAT_VC7 0)
+set ("GFLAGS_INTTYPES_FORMAT_${GFLAGS_INTTYPES_FORMAT}" 1)
+
+if (MSVC)
+  set (HAVE_strtoll 0)
+  set (HAVE_strtoq  0)
+else ()
+  check_cxx_symbol_exists (strtoll stdlib.h HAVE_STRTOLL)
+  if (NOT HAVE_STRTOLL)
+    check_cxx_symbol_exists (strtoq stdlib.h HAVE_STRTOQ)
+  endif ()
+endif ()
+
+set (CMAKE_THREAD_PREFER_PTHREAD TRUE)
+find_package (Threads)
+if (Threads_FOUND AND CMAKE_USE_PTHREADS_INIT)
+  set (HAVE_PTHREAD 1)
+  check_type_size (pthread_rwlock_t RWLOCK LANGUAGE CXX)
+else ()
+  set (HAVE_PTHREAD 0)
+endif ()
+
+if (UNIX AND NOT HAVE_PTHREAD AND BUILD_gflags_LIB)
+  if (CMAKE_HAVE_PTHREAD_H)
+    set (what "library")
+  else ()
+    set (what ".h file")
+  endif ()
+  message (FATAL_ERROR "Could not find pthread${what}. Check the log file"
+                       "\n\t${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log"
+                       "\nor disable the build of the multi-threaded gflags library (BUILD_gflags_LIB=OFF).")
+endif ()
+
+# ----------------------------------------------------------------------------
+# source files - excluding root subdirectory and/or .in suffix
+set (PUBLIC_HDRS
+  "gflags.h"
+  "gflags_declare.h"
+  "gflags_completions.h"
+)
+
+if (GFLAGS_NAMESPACE_SECONDARY)
+  set (INCLUDE_GFLAGS_NS_H "// Import gflags library symbols into alternative/deprecated namespace(s)")
+  foreach (ns IN LISTS GFLAGS_NAMESPACE_SECONDARY)
+    string (TOUPPER "${ns}" NS)
+    set (gflags_ns_h "${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}/gflags_${ns}.h")
+    configure_file ("${PROJECT_SOURCE_DIR}/src/gflags_ns.h.in" "${gflags_ns_h}" @ONLY)
+    list (APPEND PUBLIC_HDRS "${gflags_ns_h}")
+    set (INCLUDE_GFLAGS_NS_H "${INCLUDE_GFLAGS_NS_H}\n#include \"gflags_${ns}.h\"")
+  endforeach ()
+else ()
+  set (INCLUDE_GFLAGS_NS_H)
+endif ()
+
+set (PRIVATE_HDRS
+  "config.h"
+  "util.h"
+  "mutex.h"
+)
+
+set (GFLAGS_SRCS
+  "gflags.cc"
+  "gflags_reporting.cc"
+  "gflags_completions.cc"
+)
+
+if (OS_WINDOWS)
+  list (APPEND PRIVATE_HDRS "windows_port.h")
+  list (APPEND GFLAGS_SRCS  "windows_port.cc")
+endif ()
+
+# ----------------------------------------------------------------------------
+# configure source files
+if (CMAKE_COMPILER_IS_GNUCXX)
+  set (GFLAGS_ATTRIBUTE_UNUSED "__attribute((unused))")
+else ()
+  set (GFLAGS_ATTRIBUTE_UNUSED)
+endif ()
+
+# whenever we build a shared library (DLL on Windows), configure the public
+# headers of the API for use of this library rather than the optionally
+# also build statically linked library; users can override GFLAGS_DLL_DECL
+if (BUILD_SHARED_LIBS)
+  set (GFLAGS_IS_A_DLL 1)
+else ()
+  set (GFLAGS_IS_A_DLL 0)
+endif ()
+
+configure_headers (PUBLIC_HDRS  ${PUBLIC_HDRS})
+configure_sources (PRIVATE_HDRS ${PRIVATE_HDRS})
+configure_sources (GFLAGS_SRCS  ${GFLAGS_SRCS})
+
+# ----------------------------------------------------------------------------
+# output directories
+set (CMAKE_RUNTIME_OUTPUT_DIRECTORY "bin")
+set (CMAKE_LIBRARY_OUTPUT_DIRECTORY "lib")
+set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY "lib")
+
+# ----------------------------------------------------------------------------
+# installation directories
+if (OS_WINDOWS)
+  set (RUNTIME_INSTALL_DIR Bin)
+  set (LIBRARY_INSTALL_DIR Lib)
+  set (INCLUDE_INSTALL_DIR Include)
+  set (CONFIG_INSTALL_DIR  CMake)
+else ()
+  set (RUNTIME_INSTALL_DIR bin)
+  # The LIB_INSTALL_DIR and LIB_SUFFIX variables are used by the Fedora
+  # package maintainers. Also package maintainers of other distribution
+  # packages need to be able to specify the name of the library directory.
+  if (NOT LIB_INSTALL_DIR)
+    set (LIB_INSTALL_DIR "lib${LIB_SUFFIX}")
+  endif ()
+  set (LIBRARY_INSTALL_DIR "${LIB_INSTALL_DIR}"
+    CACHE PATH "Directory of installed libraries, e.g., \"lib64\""
+  )
+  mark_as_advanced (LIBRARY_INSTALL_DIR)
+  set (INCLUDE_INSTALL_DIR include)
+  set (CONFIG_INSTALL_DIR  ${LIBRARY_INSTALL_DIR}/cmake/${PACKAGE_NAME})
+endif ()
+
+# ----------------------------------------------------------------------------
+# add library targets
+set (TARGETS)
+# static vs. shared
+foreach (TYPE IN ITEMS STATIC SHARED)
+  if (BUILD_${TYPE}_LIBS)
+    # whether or not targets are a DLL
+    if (OS_WINDOWS AND "^${TYPE}$" STREQUAL "^SHARED$")
+      set (GFLAGS_IS_A_DLL 1)
+    else ()
+      set (GFLAGS_IS_A_DLL 0)
+    endif ()
+    string (TOLOWER "${TYPE}" type)
+    # multi-threaded vs. single-threaded
+    foreach (opts IN ITEMS "" _nothreads)
+      if (BUILD_gflags${opts}_LIB)
+        add_library (gflags${opts}-${type} ${TYPE} ${GFLAGS_SRCS} ${PRIVATE_HDRS} ${PUBLIC_HDRS})
+        set (include_dirs "$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>")
+        if (INSTALL_HEADERS)
+          list (APPEND include_dirs "$<INSTALL_INTERFACE:${INCLUDE_INSTALL_DIR}>")
+        endif ()
+        target_include_directories (gflags${opts}-${type}
+          PUBLIC  "${include_dirs}"
+          PRIVATE "${PROJECT_SOURCE_DIR}/src;${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}"
+        )
+        if (opts MATCHES "nothreads")
+          set (defines "GFLAGS_IS_A_DLL=${GFLAGS_IS_A_DLL};NOTHREADS")
+        else ()
+          set (defines "GFLAGS_IS_A_DLL=${GFLAGS_IS_A_DLL}")
+          if (CMAKE_USE_PTHREADS_INIT)
+            target_link_libraries (gflags${opts}-${type} ${CMAKE_THREAD_LIBS_INIT})
+          endif ()
+        endif ()
+        set_target_properties (
+          gflags${opts}-${type} PROPERTIES COMPILE_DEFINITIONS "${defines}"
+                                           OUTPUT_NAME         "gflags${opts}"
+                                           VERSION             "${PACKAGE_VERSION}"
+                                           SOVERSION           "${PACKAGE_SOVERSION}"
+        )
+        if (HAVE_SHLWAPI_H)
+          target_link_libraries (gflags${opts}-${type} shlwapi.lib)
+        endif ()
+        if (NOT TARGET gflags${opts})
+          add_custom_target (gflags${opts})
+        endif ()
+        add_dependencies (gflags${opts} gflags${opts}-${type})
+        list (APPEND TARGETS gflags${opts}-${type})
+      endif ()
+    endforeach ()
+  endif ()
+endforeach ()
+
+# ----------------------------------------------------------------------------
+# installation rules
+file (RELATIVE_PATH INSTALL_PREFIX_REL2CONFIG_DIR "${CMAKE_INSTALL_PREFIX}/${CONFIG_INSTALL_DIR}" "${CMAKE_INSTALL_PREFIX}")
+configure_file (cmake/config.cmake.in  "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-config-install.cmake" @ONLY)
+configure_file (cmake/version.cmake.in "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-config-version.cmake" @ONLY)
+
+install (TARGETS ${TARGETS} DESTINATION ${LIBRARY_INSTALL_DIR} EXPORT gflags-lib)
+if (INSTALL_HEADERS)
+  install (FILES ${PUBLIC_HDRS} DESTINATION ${INCLUDE_INSTALL_DIR}/${GFLAGS_INCLUDE_DIR})
+  install (
+    FILES "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-config-install.cmake"
+    RENAME ${PACKAGE_NAME}-config.cmake
+    DESTINATION ${CONFIG_INSTALL_DIR}
+  )
+  install (
+    FILES "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-config-version.cmake"
+    DESTINATION ${CONFIG_INSTALL_DIR}
+  )
+  install (EXPORT gflags-lib DESTINATION ${CONFIG_INSTALL_DIR} FILE ${PACKAGE_NAME}-export.cmake)
+  if (UNIX)
+    install (PROGRAMS src/gflags_completions.sh DESTINATION ${RUNTIME_INSTALL_DIR})
+  endif ()
+endif ()
+
+# ----------------------------------------------------------------------------
+# support direct use of build tree
+set (INSTALL_PREFIX_REL2CONFIG_DIR .)
+export (TARGETS ${TARGETS} FILE "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-export.cmake")
+export (PACKAGE gflags)
+configure_file (cmake/config.cmake.in "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-config.cmake" @ONLY)
+
+# ----------------------------------------------------------------------------
+# testing - MUST follow the generation of the build tree config file
+if (BUILD_TESTING)
+  include (CTest)
+  enable_testing ()
+  add_subdirectory (test)
+endif ()
+
+# ----------------------------------------------------------------------------
+# packaging
+if (BUILD_PACKAGING)
+
+  if (NOT BUILD_SHARED_LIBS AND NOT INSTALL_HEADERS)
+    message (WARNING "Package will contain static libraries without headers!"
+                     "\nRecommended options for generation of runtime package:"
+                     "\n  BUILD_SHARED_LIBS=ON"
+                     "\n  BUILD_STATIC_LIBS=OFF"
+                     "\n  INSTALL_HEADERS=OFF"
+                     "\nRecommended options for generation of development package:"
+                     "\n  BUILD_SHARED_LIBS=ON"
+                     "\n  BUILD_STATIC_LIBS=ON"
+                     "\n  INSTALL_HEADERS=ON")
+  endif ()
+
+  # default package generators
+  if (APPLE)
+    set (PACKAGE_GENERATOR        "PackageMaker")
+    set (PACKAGE_SOURCE_GENERATOR "TGZ;ZIP")
+  elseif (UNIX)
+    set (PACKAGE_GENERATOR        "DEB;RPM")
+    set (PACKAGE_SOURCE_GENERATOR "TGZ;ZIP")
+  else ()
+    set (PACKAGE_GENERATOR        "ZIP")
+    set (PACKAGE_SOURCE_GENERATOR "ZIP")
+  endif ()
+
+  # used package generators
+  set (CPACK_GENERATOR        "${PACKAGE_GENERATOR}"        CACHE STRING "List of binary package generators (CPack).")
+  set (CPACK_SOURCE_GENERATOR "${PACKAGE_SOURCE_GENERATOR}" CACHE STRING "List of source package generators (CPack).")
+  mark_as_advanced (CPACK_GENERATOR CPACK_SOURCE_GENERATOR)
+
+  # some package generators (e.g., PackageMaker) do not allow .md extension
+  configure_file ("${CMAKE_CURRENT_LIST_DIR}/README.md" "${CMAKE_CURRENT_BINARY_DIR}/README.txt" COPYONLY)
+
+  # common package information
+  set (CPACK_PACKAGE_VENDOR              "Andreas Schuh")
+  set (CPACK_PACKAGE_CONTACT             "google-gflags@googlegroups.com")
+  set (CPACK_PACKAGE_NAME                "${PACKAGE_NAME}")
+  set (CPACK_PACKAGE_VERSION             "${PACKAGE_VERSION}")
+  set (CPACK_PACKAGE_VERSION_MAJOR       "${PACKAGE_VERSION_MAJOR}")
+  set (CPACK_PACKAGE_VERSION_MINOR       "${PACKAGE_VERSION_MINOR}")
+  set (CPACK_PACKAGE_VERSION_PATCH       "${PACKAGE_VERSION_PATCH}")
+  set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "A commandline flags library that allows for distributed flags.")
+  set (CPACK_RESOURCE_FILE_WELCOME       "${CMAKE_CURRENT_BINARY_DIR}/README.txt")
+  set (CPACK_RESOURCE_FILE_LICENSE       "${CMAKE_CURRENT_LIST_DIR}/COPYING.txt")
+  set (CPACK_PACKAGE_DESCRIPTION_FILE    "${CMAKE_CURRENT_BINARY_DIR}/README.txt")
+  set (CPACK_INSTALL_PREFIX              "${CMAKE_INSTALL_PREFIX}")
+  set (CPACK_OUTPUT_FILE_PREFIX          packages)
+  set (CPACK_PACKAGE_RELOCATABLE         TRUE)
+  set (CPACK_MONOLITHIC_INSTALL          TRUE)
+
+  # RPM package information -- used in cmake/package.cmake.in also for DEB
+  set (CPACK_RPM_PACKAGE_GROUP   "Development/Libraries")
+  set (CPACK_RPM_PACKAGE_LICENSE "BSD")
+  set (CPACK_RPM_PACKAGE_URL     "http://schuhschuh.github.com/gflags")
+  set (CPACK_RPM_CHANGELOG_FILE  "${CMAKE_CURRENT_LIST_DIR}/ChangeLog.txt")
+
+  if (INSTALL_HEADERS)
+    set (CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_LIST_DIR}/doc/index.html")
+  else ()
+    set (CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_LIST_DIR}/cmake/README_runtime.txt")
+  endif ()
+
+  # system/architecture
+  if (WINDOWS)
+    if (CMAKE_CL_64)
+      set (CPACK_SYSTEM_NAME "win64")
+    else ()
+      set (CPACK_SYSTEM_NAME "win32")
+    endif ()
+    set (CPACK_PACKAGE_ARCHITECTURE)
+  elseif (APPLE)
+    set (CPACK_PACKAGE_ARCHITECTURE darwin)
+  else ()
+    string (TOLOWER "${CMAKE_SYSTEM_NAME}" CPACK_SYSTEM_NAME)
+    if (CMAKE_CXX_FLAGS MATCHES "-m32")
+      set (CPACK_PACKAGE_ARCHITECTURE i386)
+    else ()
+      execute_process (
+        COMMAND         dpkg --print-architecture
+        RESULT_VARIABLE RV
+        OUTPUT_VARIABLE CPACK_PACKAGE_ARCHITECTURE
+      )
+      if (RV EQUAL 0)
+	      string (STRIP "${CPACK_PACKAGE_ARCHITECTURE}" CPACK_PACKAGE_ARCHITECTURE)
+      else ()
+        execute_process (COMMAND uname -m OUTPUT_VARIABLE CPACK_PACKAGE_ARCHITECTURE)
+        if (CPACK_PACKAGE_ARCHITECTURE MATCHES "x86_64")
+	        set (CPACK_PACKAGE_ARCHITECTURE amd64)
+        else ()
+          set (CPACK_PACKAGE_ARCHITECTURE i386)
+        endif ()
+      endif ()
+    endif ()
+  endif ()
+
+  # source package settings
+  set (CPACK_SOURCE_TOPLEVEL_TAG      "source")
+  set (CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
+  set (CPACK_SOURCE_IGNORE_FILES      "/\\\\.git/;\\\\.swp$;\\\\.#;/#;\\\\.*~;cscope\\\\.*;/[Bb]uild[.+-_a-zA-Z0-9]*/")
+
+  # default binary package settings
+  set (CPACK_INCLUDE_TOPLEVEL_DIRECTORY TRUE)
+  set (CPACK_PACKAGE_FILE_NAME          "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CPACK_SYSTEM_NAME}")
+  if (CPACK_PACKAGE_ARCHITECTURE)
+    set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-${CPACK_PACKAGE_ARCHITECTURE}")
+  endif ()
+
+  # generator specific configuration file
+  #
+  # allow package maintainers to use their own configuration file
+  # $ cmake -DCPACK_PROJECT_CONFIG_FILE:FILE=/path/to/package/config
+  if (NOT CPACK_PROJECT_CONFIG_FILE)
+    configure_file (
+      "${CMAKE_CURRENT_LIST_DIR}/cmake/package.cmake.in"
+      "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-package.cmake" @ONLY
+    )
+    set (CPACK_PROJECT_CONFIG_FILE "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-package.cmake")
+  endif ()
+
+  include (CPack)
+
+endif () # BUILD_PACKAGING
diff --git a/third_party/gflags/COPYING.txt b/third_party/gflags/COPYING.txt
new file mode 100644
index 0000000..d15b0c2
--- /dev/null
+++ b/third_party/gflags/COPYING.txt
@@ -0,0 +1,28 @@
+Copyright (c) 2006, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+    * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/third_party/gflags/ChangeLog.txt b/third_party/gflags/ChangeLog.txt
new file mode 100644
index 0000000..eea9f83
--- /dev/null
+++ b/third_party/gflags/ChangeLog.txt
@@ -0,0 +1,218 @@
+* Tue Mar 24 2014 - Andreas Schuh <andreas.schuh.84@gmail.com>
+
+- gflags: version 2.1.2
+- Moved project to GitHub
+- Added GFLAGS_NAMESPACE definition to gflags_declare.h
+- Fixed issue 94: Keep "google" as primary namespace and import symbols into "gflags" namespace
+- Fixed issue 96: Fix binary ABI compatibility with gflags 2.0 using "google" as primary namespace
+- Fixed issue 97/101: Removed (patched) CMake modules and enabled C language instead
+- Fixed issue 103: Set CMake policy CMP0042 to silence warning regarding MACOS_RPATH setting
+
+* Sun Mar 20 2014 - Andreas Schuh <google-gflags@googlegroups.com>
+
+- gflags: version 2.1.1
+- Fixed issue 77: GFLAGS_IS_A_DLL expands to empty string in gflags_declare.h
+- Fixed issue 79: GFLAGS_NAMESPACE not expanded to actual namespace in gflags_declare.h
+- Fixed issue 80: Allow include path to differ from GFLAGS_NAMESPACE
+
+* Thu Mar 20 2014 - Andreas Schuh <google-gflags@googlegroups.com>
+
+- gflags: version 2.1.0
+- Build system configuration using CMake instead of autotools
+- CPack packaging support for Debian/Ubuntu, Red Hat, and Mac OS X
+- Fixed issue 54: Fix "invalid suffix on literal" (C++11)
+- Fixed issue 57: Use _strdup instead of strdup on Windows
+- Fixed issue 62: Change all preprocessor include guards to start with GFLAGS_
+- Fixed issue 64: Add DEFINE_validator macro
+- Fixed issue 73: Warnings in Visual Studio 2010 and unable to compile unit test
+
+* Wed Jan 25 2012 - Google Inc. <google-gflags@googlegroups.com>
+
+- gflags: version 2.0
+- Changed the 'official' gflags email in setup.py/etc
+- Renamed google-gflags.sln to gflags.sln
+- Changed copyright text to reflect Google's relinquished ownership
+
+* Tue Dec 20 2011 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.7
+- Add CommandLineFlagInfo::flag_ptr pointing to current storage (musji)
+- PORTING: flush after writing to stderr, needed on cygwin
+- PORTING: Clean up the GFLAGS_DLL_DECL stuff better
+- Fix a bug in StringPrintf() that affected large strings (csilvers)
+- Die at configure-time when g++ isn't installed
+
+* Fri Jul 29 2011 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.6
+- BUGFIX: Fix a bug where we were leaving out a required $(top_srcdir)
+- Fix definition of clstring (jyrki)
+- Split up flag declares into its own file (jyrki)
+- Add --version support (csilvers)
+- Update the README for gflags with static libs
+- Update acx_pthread.m4 for nostdlib
+- Change ReparseCommandLineFlags to return void (csilvers)
+- Some doc typofixes and example augmentation (various)
+
+* Mon Jan 24 2011 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.5
+- Better reporting of current vs default value (handler)
+- Add API for cleaning up of memory at program-exit (jmarantz)
+- Fix macros to work inside namespaces (csilvers)
+- Use our own string typedef in case string is redefined (csilvers)
+- Updated to autoconf 2.65
+
+* Wed Oct 13 2010 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.4
+- Add a check to prevent passing 0 to DEFINE_string (jorg)
+- Reduce compile (.o) size (jyrki)
+- Some small changes to quiet debug compiles (alexk)
+- PORTING: better support static linking on windows (csilvers)
+- DOCUMENTATION: change default values, use validators, etc.
+- Update the NEWS file to be non-empty
+- Add pkg-config (.pc) files for libgflags and libgflags_nothreads
+
+* Mon Jan  4 2010 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.3
+- PORTABILITY: can now build and run tests under MSVC (csilvers)
+- Remove the python gflags code, which is now its own package (tansell)
+- Clarify that "last flag wins" in the docs (csilvers)
+- Comment danger of using GetAllFlags in validators (wojtekm)
+- PORTABILITY: Some fixes necessary for c++0x (mboerger)
+- Makefile fix: $(srcdir) -> $(top_srcdir) in one place (csilvres)
+- INSTALL: autotools to autoconf v2.64 + automake v1.11 (csilvers)
+
+* Thu Sep 10 2009 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.2
+- PORTABILITY: can now build and run tests under mingw (csilvers)
+- Using a string arg for a bool flag is a compile-time error (rbayardo)
+- Add --helpxml to gflags.py (salcianu)
+- Protect against a hypothetical global d'tor mutex problem (csilvers)
+- BUGFIX: can now define a flag after 'using namespace google' (hamaji)
+
+* Tue Apr 14 2009 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.1
+- Add both foo and nofoo for boolean flags, with --undefok (andychu)
+- Better document how validators work (wojtekm)
+- Improve binary-detection for bash-completion (mtamsky)
+- Python: Add a concept of "key flags", used with --help (salcianu)
+- Python: Robustify flag_values (salcianu)
+- Python: Add a new DEFINE_bool alias (keir, andrewliu)
+- Python: Do module introspection based on module name (dsturtevant)
+- Fix autoconf a bit better, especially on windows and solaris (ajenjo)
+- BUG FIX: gflags_nothreads was linking against the wrong lib (ajenjo)
+- BUG FIX: threads-detection failed on FreeBSD; replace it (ajenjo)
+- PORTABILITY: Quiet an internal compiler error with SUSE 10 (csilvers)
+- PORTABILITY: Update deb.sh for more recenty debuilds (csilvers)
+- PORTABILITY: #include more headers to satify new gcc's (csilvers)
+- INSTALL: Updated to autoconf 2.61 and libtool 1.5.26 (csilvers)
+
+* Fri Oct  3 2008 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.0
+- Add a missing newline to an error string (bcmills)
+- (otherwise exactly the same as gflags 1.0rc2)
+
+* Thu Sep 18 2008 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.0rc2
+- Report current flag values in --helpxml (hdn)
+- Fix compilation troubles with gcc 4.3.3 (simonb)
+- BUG FIX: I was missing a std:: in DECLARE_string (csilvers)
+- BUG FIX: Clarify in docs how to specify --bool flags (csilvers)
+- BUG FIX: Fix --helpshort for source files not in a subdir (csilvers)
+- BUG FIX: Fix python unittest for 64-bit builds (bcmills)
+
+* Tue Aug 19 2008 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 1.0rc1
+- Move #include files from google/ to gflags/ (csilvers)
+- Small optimizations to reduce binary (library) size (jyrki)
+- BUGFIX: forgot a std:: in one of the .h files (csilvers)
+- Speed up locking by making sure calls are inlined (ajenjo)
+- 64-BIT COMPATIBILITY: Use %PRId64 instead of %lld (csilvers)
+- PORTABILITY: fix Makefile to work with Cygwin (ajenjo)
+- PORTABILITY: fix code to compile under Visual Studio (ajenjo)
+- PORTABILITY: fix code to compile under Solaris 10 with CC (csilvers)
+
+* Mon Jul 21 2008 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 0.9
+- Add the ability to validate a command-line flag (csilvers)
+- Add completion support for commandline flags in bash (daven)
+- Add -W compile flags to Makefile, when using gcc (csilvers)
+- Allow helpstring to be NULL (cristianoc)
+- Improved documentation of classes in the .cc file (csilvers)
+- Fix python bug with AppendFlagValues + shortnames (jjtswan)
+- Use bool instead of int for boolean flags in gflags.py (bcmills)
+- Simplify the way we declare flags, now more foolproof (csilvers)
+- Better error messages when bool flags collide (colohan)
+- Only evaluate DEFINE_foo macro args once (csilvers)
+
+* Wed Mar 26 2008 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 0.8
+- Export DescribeOneFlag() in the API
+- Add support for automatic line wrapping at 80 cols for gflags.py
+- Bugfix: do not treat an isolated "-" the same as an isolated "--"
+- Update rpm spec to point to Google Code rather than sourceforge (!)
+- Improve documentation (including documenting thread-safety)
+- Improve #include hygiene
+- Improve testing
+
+* Thu Oct 18 2007 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 0.7
+- Deal even more correctly with libpthread not linked in (csilvers)
+- Add STRIP_LOG, an improved DO_NOT_SHOW_COMMANDLINE_HELP (sioffe)
+- Be more accurate printing default flag values in --help (dsturtevant)
+- Reduce .o file size a bit by using shorter namespace names (jeff)
+- Use relative install path, so 'setup.py --home' works (csilvers)
+- Notice when a boolean flag has a non-boolean default (bnmouli)
+- Broaden --helpshort to match foo-main.cc and foo_main.cc (hendrie)
+- Fix "no modules match" message for --helpshort, etc (hendrie)
+
+* Wed Aug 15 2007 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 0.6
+- Deal correctly with case that libpthread is not linked in (csilvers)
+- Update Makefile/tests so we pass "make distcheck" (csilvers)
+- Document and test that last assignment to a flag wins (wan)
+
+* Tue Jun 12 2007 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 0.5
+- Include all m4 macros in the distribution (csilvers)
+- Python: Fix broken data_files field in setup.py (sidlon)
+- Python: better string serliaizing and unparsing (abo, csimmons)
+- Fix checks for NaN and inf to work with Mac OS X (csilvers)
+
+* Thu Apr 19 2007 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 0.4
+- Remove is_default from GetCommandLineFlagInfo (csilvers)
+- Portability fixes: includes, strtoll, gcc4.3 errors (csilvers)
+- A few doc typo cleanups (csilvers)
+
+* Wed Mar 28 2007 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 0.3
+- python portability fix: use popen instead of subprocess (csilvers)
+- Add is_default to CommandLineFlagInfo (pchien)
+- Make docs a bit prettier (csilvers)
+- Actually include the python files in the distribution! :-/ (csilvers)
+
+* Mon Jan 22 2007 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 0.2
+- added support for python commandlineflags, as well as c++
+- gflags2man, a script to turn flags into a man page (dchristian)
+
+* Wed Dec 13 2006 - Google Inc. <opensource@google.com>
+
+- google-gflags: version 0.1
diff --git a/third_party/gflags/INSTALL.md b/third_party/gflags/INSTALL.md
new file mode 100644
index 0000000..b89d86d
--- /dev/null
+++ b/third_party/gflags/INSTALL.md
@@ -0,0 +1,67 @@
+Installing a binary distribution package
+========================================
+
+No official binary distribution packages are provided by the gflags developers.
+There may, however, be binary packages available for your OS. Please consult
+also the package repositories of your Linux distribution.
+
+For example on Debian/Ubuntu Linux, gflags can be installed using the
+following command:
+
+    sudo apt-get install gflags
+
+
+Compiling the source code
+=========================
+
+The build system of gflags is since version 2.1 based on [CMake](http://cmake.org).
+The common steps to build, test, and install software are therefore:
+
+1. Extract source files.
+2. Create build directory and change to it.
+3. Run CMake to configure the build tree.
+4. Build the software using selected build tool.
+5. Test the built software.
+6. Install the built files.
+
+On Unix-like systems with GNU Make as build tool, these build steps can be
+summarized by the following sequence of commands executed in a shell,
+where ```$package``` and ```$version``` are shell variables which represent
+the name of this package and the obtained version of the software.
+
+    $ tar xzf gflags-$version-source.tar.gz
+    $ cd gflags-$version
+    $ mkdir build && cd build
+    $ ccmake ..
+    
+      - Press 'c' to configure the build system and 'e' to ignore warnings.
+      - Set CMAKE_INSTALL_PREFIX and other CMake variables and options.
+      - Continue pressing 'c' until the option 'g' is available.
+      - Then press 'g' to generate the configuration files for GNU Make.
+    
+    $ make
+    $ make test    (optional)
+    $ make install (optional)
+
+In the following, only gflags-specific CMake settings available to
+configure the build and installation are documented. Note that most of these
+variables are for advanced users and binary package maintainers only.
+They usually do not have to be modified.
+
+
+CMake Option                | Description
+--------------------------- | -------------------------------------------------------
+CMAKE_INSTALL_PREFIX        | Installation directory, e.g., "/usr/local" on Unix and "C:\Program Files\gflags" on Windows.
+BUILD_SHARED_LIBS           | Request build of dynamic link libraries.
+BUILD_STATIC_LIBS           | Request build of static link libraries. Implied if BUILD_SHARED_LIBS is OFF.
+BUILD_PACKAGING             | Enable binary package generation using CPack.
+BUILD_TESTING               | Build tests for execution by CTest.
+BUILD_NC_TESTS              | Request inclusion of negative compilation tests (requires Python).
+BUILD_CONFIG_TESTS          | Request inclusion of package configuration tests (requires Python).
+BUILD_gflags_LIBS           | Request build of multi-threaded gflags libraries (if threading library found).
+BUILD_gflags_nothreads_LIBS | Request build of single-threaded gflags libraries.
+GFLAGS_NAMESPACE            | Name of the C++ namespace to be used by the gflags library. Note that the public source header files are installed in a subdirectory named after this namespace. To maintain backwards compatibility with the Google Commandline Flags, set this variable to "google". The default is "gflags".
+GFLAGS_INTTYPES_FORMAT      | String identifying format of built-in integer types.
+GFLAGS_INCLUDE_DIR          | Name of headers installation directory relative to CMAKE_INSTALL_PREFIX.
+LIBRARY_INSTALL_DIR         | Name of library installation directory relative to CMAKE_INSTALL_PREFIX.
+INSTALL_HEADERS             | Request installation of public header files.
diff --git a/third_party/gflags/README.md b/third_party/gflags/README.md
new file mode 100644
index 0000000..79bd202
--- /dev/null
+++ b/third_party/gflags/README.md
@@ -0,0 +1,270 @@
+24 March 2015
+-------------
+
+I've just released gflags 2.1.2.
+
+This release completes the namespace change fixes. In particular,
+it restores binary ABI compatibility with release version 2.0.
+The deprecated "google" namespace is by default still kept as
+primary namespace while symbols are imported into the new "gflags" namespace.
+This can be overridden using the CMake variable GFLAGS_NAMESPACE.
+
+Other fixes of the build configuration are related to the (patched)
+CMake modules FindThreads.cmake and CheckTypeSize.cmake. These have
+been removed and instead the C language is enabled again even though
+gflags is written in C++ only.
+
+This release also marks the complete move of the gflags project
+from Google Code to GitHub. Email addresses of original issue
+reporters got lost in the process. Given the age of most issue reports,
+this should be negligable.
+
+Please report any further issues using the GitHub issue tracker.
+
+
+30 March 2014
+-------------
+
+I've just released gflags 2.1.1.
+
+This release fixes a few bugs in the configuration of gflags\_declare.h
+and adds a separate GFLAGS\_INCLUDE\_DIR CMake variable to the build configuration.
+Setting GFLAGS\_NAMESPACE to "google" no longer changes also the include
+path of the public header files. This allows the use of the library with
+other Google projects such as glog which still use the deprecated "google"
+namespace for the gflags library, but include it as "gflags/gflags.h".
+
+20 March 2014
+-------------
+
+I've just released gflags 2.1.
+
+The major changes are the use of CMake for the build configuration instead
+of the autotools and packaging support through CPack. The default namespace
+of all C++ symbols is now "gflags" instead of "google". This can be
+configured via the GFLAGS\_NAMESPACE variable.
+
+This release compiles with all major compilers without warnings and passed
+the unit tests on  Ubuntu 12.04, Windows 7 (Visual Studio 2008 and 2010,
+Cygwin, MinGW), and Mac OS X (Xcode 5.1).
+
+The SVN repository on Google Code is now frozen and replaced by a Git
+repository such that it can be used as Git submodule by projects. The main
+hosting of this project remains at Google Code. Thanks to the distributed
+character of Git, I can push (and pull) changes from both GitHub and Google Code
+in order to keep the two public repositories in sync.
+When fixing an issue for a pull request through either of these hosting
+platforms, please reference the issue number as
+[described here](https://code.google.com/p/support/wiki/IssueTracker#Integration_with_version_control).
+For the further development, I am following the
+[Git branching model](http://nvie.com/posts/a-successful-git-branching-model/)
+with feature branch names prefixed by "feature/" and bugfix branch names
+prefixed by "bugfix/", respectively.
+
+Binary and source [packages](https://github.com/schuhschuh/gflags/releases) are available on GitHub.
+
+
+14 January 2014
+---------------
+
+The migration of the build system to CMake is almost complete.
+What remains to be done is rewriting the tests in Python such they can be
+executed on non-Unix platforms and splitting them up into separate CTest tests.
+Though merging these changes into the master branch yet remains to be done,
+it is recommended to already start using the
+[cmake-migration](https://github.com/schuhschuh/gflags/tree/cmake-migration) branch.
+
+
+20 April 2013
+-------------
+
+More than a year has past since I (Andreas) took over the maintenance for
+`gflags`. Only few minor changes have been made since then, much to my regret.
+To get more involved and stimulate participation in the further
+development of the library, I moved the project source code today to
+[GitHub](https://github.com/schuhschuh/gflags).
+I believe that the strengths of [Git](http://git-scm.com/) will allow for better community collaboration
+as well as ease the integration of changes made by others. I encourage everyone
+who would like to contribute to send me pull requests.
+Git's lightweight feature branches will also provide the right tool for more
+radical changes which should only be merged back into the master branch
+after these are complete and implement the desired behavior.
+
+The SVN repository remains accessible at Google Code and I will keep the
+master branch of the Git repository hosted at GitHub and the trunk of the
+Subversion repository synchronized. Initially, I was going to simply switch the
+Google Code project to Git, but in this case the SVN repository would be
+frozen and force everyone who would like the latest development changes to
+use Git as well. Therefore I decided to host the public Git repository at GitHub
+instead.
+
+Please continue to report any issues with gflags on Google Code. The GitHub project will
+only be used to host the Git repository.
+
+One major change of the project structure I have in mind for the next weeks
+is the migration from autotools to [CMake](http://www.cmake.org/).
+Check out the (unstable!)
+[cmake-migration](https://github.com/schuhschuh/gflags/tree/cmake-migration)
+branch on GitHub for details.
+
+
+25 January 2012
+---------------
+
+I've just released gflags 2.0.
+
+The `google-gflags` project has been renamed to `gflags`.  I
+(csilvers) am stepping down as maintainer, to be replaced by Andreas
+Schuh.  Welcome to the team, Andreas!  I've seen the energy you have
+around gflags and the ideas you have for the project going forward,
+and look forward to having you on the team.
+
+I bumped the major version number up to 2 to reflect the new community
+ownership of the project.  All the [changes](ChangeLog.txt)
+are related to the renaming.  There are no functional changes from
+gflags 1.7.  In particular, I've kept the code in the namespace
+`google`, though in a future version it should be renamed to `gflags`.
+I've also kept the `/usr/local/include/google/` subdirectory as
+synonym of `/usr/local/include/gflags/`, though the former name has
+been obsolete for some time now.
+
+
+18 January 2011
+---------------
+
+The `google-gflags` Google Code page has been renamed to
+`gflags`, in preparation for the project being renamed to
+`gflags`.  In the coming weeks, I'll be stepping down as
+maintainer for the gflags project, and as part of that Google is
+relinquishing ownership of the project; it will now be entirely
+community run.  The name change reflects that shift.
+
+
+20 December 2011
+----------------
+
+I've just released gflags 1.7.  This is a minor release; the major
+change is that `CommandLineFlagInfo` now exports the address in memory
+where the flag is located.  There has also been a bugfix involving
+very long --help strings, and some other minor [changes](ChangeLog.txt).
+
+29 July 2011
+------------
+
+I've just released gflags 1.6.  The major new feature in this release
+is support for setting version info, so that --version does something
+useful.
+
+One minor change has required bumping the library number:
+`ReparseCommandlineFlags` now returns `void` instead of `int` (the int
+return value was always meaningless).  Though I doubt anyone ever used
+this (meaningless) return value, technically it's a change to the ABI
+that requires a version bump.  A bit sad.
+
+There's also a procedural change with this release: I've changed the
+internal tools used to integrate Google-supplied patches for gflags
+into the opensource release.  These new tools should result in more
+frequent updates with better change descriptions.  They will also
+result in future `ChangeLog` entries being much more verbose (for better
+or for worse).
+
+See the [ChangeLog](ChangeLog.txt) for a full list of changes for this release.
+
+24 January 2011
+---------------
+
+I've just released gflags 1.5.  This release has only minor changes
+from 1.4, including some slightly better reporting in --help, and
+an new memory-cleanup function that can help when running gflags-using
+libraries under valgrind.  The major change is to fix up the macros
+(`DEFINE_bool` and the like) to work more reliably inside namespaces.
+
+If you have not had a problem with these macros, and don't need any of
+the other changes described, there is no need to upgrade.  See the
+[ChangeLog](ChangeLog.txt) for a full list of changes for this release.
+
+11 October 2010
+---------------
+
+I've just released gflags 1.4.  This release has only minor changes
+from 1.3, including some documentation tweaks and some work to make
+the library smaller.  If 1.3 is working well for you, there's no
+particular reason to upgrade.
+
+4 January 2010
+--------------
+
+I've just released gflags 1.3.  gflags now compiles under MSVC, and
+all tests pass.  I **really** never thought non-unix-y Windows folks
+would want gflags, but at least some of them do.
+
+The major news, though, is that I've separated out the python package
+into its own library, [python-gflags](http://code.google.com/p/python-gflags).
+If you're interested in the Python version of gflags, that's the place to
+get it now.
+
+10 September 2009
+-----------------
+
+I've just released gflags 1.2.  The major change from gflags 1.1 is it
+now compiles under MinGW (as well as cygwin), and all tests pass.  I
+never thought Windows folks would want unix-style command-line flags,
+since they're so different from the Windows style, but I guess I was
+wrong!
+
+The other changes are minor, such as support for --htmlxml in the
+python version of gflags.
+
+15 April 2009
+-------------
+
+I've just released gflags 1.1.  It has only minor changes fdrom gflags
+1.0 (see the [ChangeLog](ChangeLog.txt) for details).
+The major change is that I moved to a new system for creating .deb and .rpm files.
+This allows me to create x86\_64 deb and rpm files.
+
+In the process of moving to this new system, I noticed an
+inconsistency: the tar.gz and .rpm files created libraries named
+libgflags.so, but the deb file created libgoogle-gflags.so.  I have
+fixed the deb file to create libraries like the others.  I'm no expert
+in debian packaging, but I believe this has caused the package name to
+change as well.  Please let me know (at
+[[mailto:google-gflags@googlegroups.com](mailto:google-gflags@googlegroups.com)
+google-gflags@googlegroups.com]) if this causes problems for you --
+especially if you know of a fix!  I would be happy to change the deb
+packages to add symlinks from the old library name to the new
+(libgoogle-gflags.so -> libgflags.so), but that is beyond my knowledge
+of how to make .debs.
+
+If you've tried to install a .rpm or .deb and it doesn't work for you,
+let me know.  I'm excited to finally have 64-bit package files, but
+there may still be some wrinkles in the new system to iron out.
+
+1 October 2008
+--------------
+
+gflags 1.0rc2 was out for a few weeks without any issues, so gflags
+1.0 is now released.  This is much like gflags 0.9.  The major change
+is that the .h files have been moved from `/usr/include/google` to
+`/usr/include/gflags`.  While I have backwards-compatibility
+forwarding headeds in place, please rewrite existing code to say
+```
+   #include <gflags/gflags.h>
+```
+instead of
+```
+   #include <google/gflags.h>
+```
+
+I've kept the default namespace to google.  You can still change with
+with the appropriate flag to the configure script (`./configure
+--help` to see the flags).  If you have feedback as to whether the
+default namespace should change to gflags, which would be a
+non-backwards-compatible change, send mail to
+`google-gflags@googlegroups.com`!
+
+Version 1.0 also has some neat new features, like support for bash
+commandline-completion of help flags.  See the [ChangeLog](ChangeLog.txt)
+for more details.
+
+If I don't hear any bad news for a few weeks, I'll release 1.0-final.
diff --git a/third_party/gflags/cmake/README_runtime.txt b/third_party/gflags/cmake/README_runtime.txt
new file mode 100644
index 0000000..d2556b2
--- /dev/null
+++ b/third_party/gflags/cmake/README_runtime.txt
@@ -0,0 +1,4 @@
+This package contains runtime libraries only which are required
+by applications that use these libraries for the commandline flags
+processing. If you want to develop such application, download
+and install the development package instead.
diff --git a/third_party/gflags/cmake/config.cmake.in b/third_party/gflags/cmake/config.cmake.in
new file mode 100644
index 0000000..a7419c2
--- /dev/null
+++ b/third_party/gflags/cmake/config.cmake.in
@@ -0,0 +1,111 @@
+## gflags CMake configuration file
+
+# library version information
+set (@PACKAGE_NAME@_VERSION_STRING "@PACKAGE_VERSION@")
+set (@PACKAGE_NAME@_VERSION_MAJOR  @PACKAGE_VERSION_MAJOR@)
+set (@PACKAGE_NAME@_VERSION_MINOR  @PACKAGE_VERSION_MINOR@)
+set (@PACKAGE_NAME@_VERSION_PATCH  @PACKAGE_VERSION_PATCH@)
+
+# import targets
+include ("${CMAKE_CURRENT_LIST_DIR}/@PACKAGE_NAME@-export.cmake")
+
+# installation prefix
+get_filename_component (CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
+get_filename_component (_INSTALL_PREFIX "${CMAKE_CURRENT_LIST_DIR}/@INSTALL_PREFIX_REL2CONFIG_DIR@" ABSOLUTE)
+
+# include directory
+#
+# Newer versions of CMake set the INTERFACE_INCLUDE_DIRECTORIES property
+# of the imported targets. It is hence not necessary to add this path
+# manually to the include search path for targets which link to gflags.
+set (@PACKAGE_NAME@_INCLUDE_DIR "${_INSTALL_PREFIX}/@INCLUDE_INSTALL_DIR@")
+
+# default settings
+if (NOT DEFINED @PACKAGE_NAME@_SHARED)
+  if (TARGET @PACKAGE_NAME@-static OR TARGET @PACKAGE_NAME@_nothreads-static)
+    set (@PACKAGE_NAME@_SHARED FALSE)
+  else ()
+    set (@PACKAGE_NAME@_SHARED TRUE)
+  endif ()
+endif ()
+if (NOT DEFINED @PACKAGE_NAME@_NOTHREADS)
+  if (TARGET @PACKAGE_NAME@-static OR TARGET @PACKAGE_NAME@-shared)
+    set (@PACKAGE_NAME@_NOTHREADS FALSE)
+  else ()
+    set (@PACKAGE_NAME@_NOTHREADS TRUE)
+  endif ()
+endif ()
+
+# choose imported library target
+if (NOT @PACKAGE_NAME@_TARGET)
+  if (@PACKAGE_NAME@_SHARED)
+    if (@PACKAGE_NAME@_NOTHREADS)
+      set (@PACKAGE_NAME@_TARGET @PACKAGE_NAME@_nothreads-shared)
+    else ()
+      set (@PACKAGE_NAME@_TARGET @PACKAGE_NAME@-shared)
+    endif ()
+  else ()
+    if (@PACKAGE_NAME@_NOTHREADS)
+      set (@PACKAGE_NAME@_TARGET @PACKAGE_NAME@_nothreads-static)
+    else ()
+      set (@PACKAGE_NAME@_TARGET @PACKAGE_NAME@-static)
+    endif ()
+  endif ()
+endif ()
+if (NOT TARGET ${@PACKAGE_NAME@_TARGET})
+  message (FATAL_ERROR "Your @PACKAGE_NAME@ installation does not contain a ${@PACKAGE_NAME@_TARGET} library target!"
+                       " Try a different combination of @PACKAGE_NAME@_SHARED and @PACKAGE_NAME@_NOTHREADS.")
+endif ()
+
+# add more convenient "@PACKAGE_NAME@" import target
+if (NOT TARGET @PACKAGE_NAME@)
+  if (@PACKAGE_NAME@_SHARED)
+    add_library (@PACKAGE_NAME@ SHARED IMPORTED)
+  else ()
+    add_library (@PACKAGE_NAME@ STATIC IMPORTED)
+  endif ()
+  # INTERFACE_INCLUDE_DIRECTORIES
+  get_target_property (_@PACKAGE_NAME@_INCLUDES ${@PACKAGE_NAME@_TARGET} INTERFACE_INCLUDE_DIRECTORIES)
+  if (_@PACKAGE_NAME@_INCLUDES)
+    set_target_properties(@PACKAGE_NAME@ PROPERTIES
+      INTERFACE_INCLUDE_DIRECTORIES "${_@PACKAGE_NAME@_INCLUDES}"
+    )
+  endif ()
+  unset (_@PACKAGE_NAME@_INCLUDES)
+  # set configuration specific properties
+  get_target_property (_@PACKAGE_NAME@_CONFIGURATIONS ${@PACKAGE_NAME@_TARGET} IMPORTED_CONFIGURATIONS)
+  set_target_properties (@PACKAGE_NAME@ PROPERTIES IMPORTED_CONFIGURATIONS "${_@PACKAGE_NAME@_CONFIGURATIONS}")
+  foreach (_@PACKAGE_NAME@_CONFIG IN LISTS _@PACKAGE_NAME@_CONFIGURATIONS)
+    # IMPORTED_LOCATION_<config>
+    get_target_property (_@PACKAGE_NAME@_LOCATION ${@PACKAGE_NAME@_TARGET} IMPORTED_LOCATION_${_@PACKAGE_NAME@_CONFIG})
+    if (_@PACKAGE_NAME@_LOCATION)
+      set_target_properties(@PACKAGE_NAME@ PROPERTIES
+        IMPORTED_LOCATION_${_@PACKAGE_NAME@_CONFIG} "${_@PACKAGE_NAME@_LOCATION}"
+      )
+    endif ()
+    unset (_@PACKAGE_NAME@_LOCATION)
+    # IMPORTED_LINK_INTERFACE_LANGUAGES_<config> (static)
+    get_target_property (_@PACKAGE_NAME@_LANGUAGES ${@PACKAGE_NAME@_TARGET} IMPORTED_LINK_INTERFACE_LANGUAGES_${_@PACKAGE_NAME@_CONFIG})
+    if (_@PACKAGE_NAME@_LANGUAGES)
+      set_target_properties(@PACKAGE_NAME@ PROPERTIES
+        IMPORTED_LINK_INTERFACE_LANGUAGES_${_@PACKAGE_NAME@_CONFIG} "${_@PACKAGE_NAME@_LANGUAGES}"
+      )
+    endif ()
+    unset (_@PACKAGE_NAME@_LANGUAGES)
+    # IMPORTED_SONAME_<config> (shared)
+    get_target_property (_@PACKAGE_NAME@_SONAME ${@PACKAGE_NAME@_TARGET} IMPORTED_SONAME_${_@PACKAGE_NAME@_CONFIG})
+    if (_@PACKAGE_NAME@_SONAME)
+      set_target_properties(@PACKAGE_NAME@ PROPERTIES
+        IMPORTED_SONAME_${_@PACKAGE_NAME@_CONFIG} "${_@PACKAGE_NAME@_SONAME}"
+      )
+    endif ()
+    unset (_@PACKAGE_NAME@_SONAME)
+  endforeach ()
+  unset (_@PACKAGE_NAME@_CONFIGURATIONS)
+endif ()
+
+# alias for default import target to be compatible with older CMake package configurations
+set (@PACKAGE_NAME@_LIBRARIES "${@PACKAGE_NAME@_TARGET}")
+
+# unset private variables
+unset (_INSTALL_PREFIX)
diff --git a/third_party/gflags/cmake/execute_test.cmake b/third_party/gflags/cmake/execute_test.cmake
new file mode 100644
index 0000000..df008cf
--- /dev/null
+++ b/third_party/gflags/cmake/execute_test.cmake
@@ -0,0 +1,53 @@
+# ----------------------------------------------------------------------------
+# sanitize string stored in variable for use in regular expression.
+macro (sanitize_for_regex STRVAR)
+  string (REGEX REPLACE "([.+*?^$()])" "\\\\\\1" ${STRVAR} "${${STRVAR}}")
+endmacro ()
+
+# ----------------------------------------------------------------------------
+# script arguments
+if (NOT COMMAND)
+  message (FATAL_ERROR "Test command not specified!")
+endif ()
+if (NOT DEFINED EXPECTED_RC)
+  set (EXPECTED_RC 0)
+endif ()
+if (EXPECTED_OUTPUT)
+  sanitize_for_regex(EXPECTED_OUTPUT)
+endif ()
+if (UNEXPECTED_OUTPUT)
+  sanitize_for_regex(UNEXPECTED_OUTPUT)
+endif ()
+
+# ----------------------------------------------------------------------------
+# set a few environment variables (useful for --tryfromenv)
+set (ENV{FLAGS_undefok} "foo,bar")
+set (ENV{FLAGS_weirdo}  "")
+set (ENV{FLAGS_version} "true")
+set (ENV{FLAGS_help}    "false")
+
+# ----------------------------------------------------------------------------
+# execute test command
+execute_process(
+  COMMAND ${COMMAND}
+  RESULT_VARIABLE RC
+  OUTPUT_VARIABLE OUTPUT
+  ERROR_VARIABLE  OUTPUT
+)
+
+if (OUTPUT)
+  message ("${OUTPUT}")
+endif ()
+
+# ----------------------------------------------------------------------------
+# check test result
+if (NOT RC EQUAL EXPECTED_RC)
+  string (REPLACE ";" " " COMMAND "${COMMAND}")
+  message (FATAL_ERROR "Command:\n\t${COMMAND}\nExit status is ${RC}, expected ${EXPECTED_RC}")
+endif ()
+if (EXPECTED_OUTPUT AND NOT OUTPUT MATCHES "${EXPECTED_OUTPUT}")
+  message (FATAL_ERROR "Test output does not match expected output: ${EXPECTED_OUTPUT}")
+endif ()
+if (UNEXPECTED_OUTPUT AND OUTPUT MATCHES "${UNEXPECTED_OUTPUT}")
+  message (FATAL_ERROR "Test output matches unexpected output: ${UNEXPECTED_OUTPUT}")
+endif ()
\ No newline at end of file
diff --git a/third_party/gflags/cmake/package.cmake.in b/third_party/gflags/cmake/package.cmake.in
new file mode 100644
index 0000000..aaec792
--- /dev/null
+++ b/third_party/gflags/cmake/package.cmake.in
@@ -0,0 +1,49 @@
+# Per-generator CPack configuration file. See CPACK_PROJECT_CONFIG_FILE documented at
+# http://www.cmake.org/cmake/help/v2.8.12/cpack.html#variable:CPACK_PROJECT_CONFIG_FILE
+#
+# All common CPACK_* variables are set in CMakeLists.txt already. This file only
+# overrides some of these to provide package generator specific settings.
+
+# whether package contains all development files or only runtime files
+set (DEVEL @INSTALL_HEADERS@)
+
+# ------------------------------------------------------------------------------
+# Mac OS X package
+if (CPACK_GENERATOR MATCHES "PackageMaker|DragNDrop")
+
+  set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}")
+  if (DEVEL)
+    set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-devel")
+  endif ()
+  set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-${CPACK_PACKAGE_VERSION}")
+
+# ------------------------------------------------------------------------------
+# Debian package
+elseif (CPACK_GENERATOR MATCHES "DEB")
+
+  set (CPACK_PACKAGE_FILE_NAME   "lib${CPACK_PACKAGE_NAME}")
+  if (DEVEL)
+    set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-dev")
+  else ()
+    set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}0")
+  endif ()
+  set (CPACK_PACKAGE_FILE_NAME   "${CPACK_PACKAGE_FILE_NAME}_${CPACK_PACKAGE_VERSION}-1_${CPACK_PACKAGE_ARCHITECTURE}")
+
+  set (CPACK_DEBIAN_PACKAGE_DEPENDS)
+  set (CPACK_DEBIAN_PACKAGE_SECTION      "devel")
+  set (CPACK_DEBIAN_PACKAGE_PRIORITY     "optional")
+  set (CPACK_DEBIAN_PACKAGE_HOMEPAGE     "${CPACK_RPM_PACKAGE_URL}")
+  set (CPACK_DEBIAN_PACKAGE_MAINTAINER   "${CPACK_PACKAGE_VENDOR}")
+  set (CPACK_DEBIAN_PACKAGE_ARCHITECTURE "${CPACK_PACKAGE_ARCHITECTURE}")
+
+# ------------------------------------------------------------------------------
+# RPM package
+elseif (CPACK_GENERATOR MATCHES "RPM")
+
+  set (CPACK_PACKAGE_FILE_NAME   "${CPACK_PACKAGE_NAME}")
+  if (DEVEL)
+    set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-devel")
+  endif ()
+  set (CPACK_PACKAGE_FILE_NAME   "${CPACK_PACKAGE_FILE_NAME}-${CPACK_PACKAGE_VERSION}-1.${CPACK_PACKAGE_ARCHITECTURE}")
+
+endif ()
diff --git a/third_party/gflags/cmake/utils.cmake b/third_party/gflags/cmake/utils.cmake
new file mode 100644
index 0000000..9cef463
--- /dev/null
+++ b/third_party/gflags/cmake/utils.cmake
@@ -0,0 +1,96 @@
+## Utility CMake functions.
+
+# ----------------------------------------------------------------------------
+## Convert boolean value to 0 or 1
+macro (bool_to_int VAR)
+  if (${VAR})
+    set (${VAR} 1)
+  else ()
+    set (${VAR} 0)
+  endif ()
+endmacro ()
+
+# ----------------------------------------------------------------------------
+## Extract version numbers from version string.
+function (version_numbers version major minor patch)
+  if (version MATCHES "([0-9]+)(\\.[0-9]+)?(\\.[0-9]+)?(rc[1-9][0-9]*|[a-z]+)?")
+    if (CMAKE_MATCH_1)
+      set (_major ${CMAKE_MATCH_1})
+    else ()
+      set (_major 0)
+    endif ()
+    if (CMAKE_MATCH_2)
+      set (_minor ${CMAKE_MATCH_2})
+      string (REGEX REPLACE "^\\." "" _minor "${_minor}")
+    else ()
+      set (_minor 0)
+    endif ()
+    if (CMAKE_MATCH_3)
+      set (_patch ${CMAKE_MATCH_3})
+      string (REGEX REPLACE "^\\." "" _patch "${_patch}")
+    else ()
+      set (_patch 0)
+    endif ()
+  else ()
+    set (_major 0)
+    set (_minor 0)
+    set (_patch 0)
+  endif ()
+  set ("${major}" "${_major}" PARENT_SCOPE)
+  set ("${minor}" "${_minor}" PARENT_SCOPE)
+  set ("${patch}" "${_patch}" PARENT_SCOPE)
+endfunction ()
+
+# ----------------------------------------------------------------------------
+## Configure public header files
+function (configure_headers out)
+  set (tmp)
+  foreach (src IN LISTS ARGN)
+    if (IS_ABSOLUTE "${src}")
+      list (APPEND tmp "${src}")
+    elseif (EXISTS "${PROJECT_SOURCE_DIR}/src/${src}.in")
+      configure_file ("${PROJECT_SOURCE_DIR}/src/${src}.in" "${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}/${src}" @ONLY)
+      list (APPEND tmp "${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}/${src}")
+    else ()
+	    configure_file ("${PROJECT_SOURCE_DIR}/src/${src}" "${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}/${src}" COPYONLY)
+      list (APPEND tmp "${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}/${src}")
+    endif ()
+  endforeach ()
+  set (${out} "${tmp}" PARENT_SCOPE)
+endfunction ()
+
+# ----------------------------------------------------------------------------
+## Configure source files with .in suffix
+function (configure_sources out)
+  set (tmp)
+  foreach (src IN LISTS ARGN)
+    if (src MATCHES ".h$" AND EXISTS "${PROJECT_SOURCE_DIR}/src/${src}.in")
+      configure_file ("${PROJECT_SOURCE_DIR}/src/${src}.in" "${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}/${src}" @ONLY)
+      list (APPEND tmp "${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}/${src}")
+    else ()
+      list (APPEND tmp "${PROJECT_SOURCE_DIR}/src/${src}")
+    endif ()
+  endforeach ()
+  set (${out} "${tmp}" PARENT_SCOPE)
+endfunction ()
+
+# ----------------------------------------------------------------------------
+## Add usage test
+#
+# Using PASS_REGULAR_EXPRESSION and FAIL_REGULAR_EXPRESSION would
+# do as well, but CMake/CTest does not allow us to specify an
+# expected exit status. Moreover, the execute_test.cmake script
+# sets environment variables needed by the --fromenv/--tryfromenv tests.
+macro (add_gflags_test name expected_rc expected_output unexpected_output cmd)
+  set (args "--test_tmpdir=${PROJECT_BINARY_DIR}/Testing/Temporary"
+            "--srcdir=${PROJECT_SOURCE_DIR}/test")
+  add_test (
+    NAME    ${name}
+    COMMAND "${CMAKE_COMMAND}" "-DCOMMAND:STRING=$<TARGET_FILE:${cmd}>;${args};${ARGN}"
+                               "-DEXPECTED_RC:STRING=${expected_rc}"
+                               "-DEXPECTED_OUTPUT:STRING=${expected_output}"
+                               "-DUNEXPECTED_OUTPUT:STRING=${unexpected_output}"
+                               -P "${PROJECT_SOURCE_DIR}/cmake/execute_test.cmake"
+    WORKING_DIRECTORY "${GFLAGS_FLAGFILES_DIR}"
+  )
+endmacro ()
diff --git a/third_party/gflags/cmake/version.cmake.in b/third_party/gflags/cmake/version.cmake.in
new file mode 100644
index 0000000..1e1af05
--- /dev/null
+++ b/third_party/gflags/cmake/version.cmake.in
@@ -0,0 +1,21 @@
+## gflags CMake configuration version file
+
+# -----------------------------------------------------------------------------
+# library version
+set (PACKAGE_VERSION "@PACKAGE_VERSION@")
+
+# -----------------------------------------------------------------------------
+# check compatibility
+
+# Perform compatibility check here using the input CMake variables.
+# See example in http://www.cmake.org/Wiki/CMake_2.6_Notes.
+
+set (PACKAGE_VERSION_COMPATIBLE TRUE)
+set (PACKAGE_VERSION_UNSUITABLE FALSE)
+
+if ("${PACKAGE_FIND_VERSION_MAJOR}" EQUAL "@PACKAGE_VERSION_MAJOR@" AND
+    "${PACKAGE_FIND_VERSION_MINOR}" EQUAL "@PACKAGE_VERSION_MINOR@")
+  set (PACKAGE_VERSION_EXACT TRUE)
+else ()
+  set (PACKAGE_VERSION_EXACT FALSE)
+endif ()
diff --git a/third_party/gflags/doc b/third_party/gflags/doc
new file mode 160000
index 0000000..e1d15b3
--- /dev/null
+++ b/third_party/gflags/doc
@@ -0,0 +1 @@
+Subproject commit e1d15b33406ec571095e7a91dbc4b2ada1ae3bac
diff --git a/third_party/gflags/src/config.h.in b/third_party/gflags/src/config.h.in
new file mode 100644
index 0000000..a8708da
--- /dev/null
+++ b/third_party/gflags/src/config.h.in
@@ -0,0 +1,112 @@
+/* Generated from config.h.in during build configuration using CMake. */
+
+// Note: This header file is only used internally. It is not part of public interface!
+
+// ---------------------------------------------------------------------------
+// System checks
+
+// Define if you build this library for a MS Windows OS.
+#cmakedefine OS_WINDOWS
+
+// Define if you have the <stdint.h> header file.
+#cmakedefine HAVE_STDINT_H
+
+// Define if you have the <sys/types.h> header file.
+#cmakedefine HAVE_SYS_TYPES_H
+
+// Define if you have the <inttypes.h> header file.
+#cmakedefine HAVE_INTTYPES_H
+
+// Define if you have the <sys/stat.h> header file.
+#cmakedefine HAVE_SYS_STAT_H
+
+// Define if you have the <unistd.h> header file.
+#cmakedefine HAVE_UNISTD_H
+
+// Define if you have the <fnmatch.h> header file.
+#cmakedefine HAVE_FNMATCH_H
+
+// Define if you have the <shlwapi.h> header file (Windows 2000/XP).
+#cmakedefine HAVE_SHLWAPI_H
+
+// Define if you have the strtoll function.
+#cmakedefine HAVE_STRTOLL
+
+// Define if you have the strtoq function.
+#cmakedefine HAVE_STRTOQ
+
+// Define if you have the <pthread.h> header file.
+#cmakedefine HAVE_PTHREAD
+
+// Define if your pthread library defines the type pthread_rwlock_t
+#cmakedefine HAVE_RWLOCK
+
+// gcc requires this to get PRId64, etc.
+#if defined(HAVE_INTTYPES_H) && !defined(__STDC_FORMAT_MACROS)
+#  define __STDC_FORMAT_MACROS 1
+#endif
+
+// ---------------------------------------------------------------------------
+// Package information
+
+// Name of package.
+#define PACKAGE @PROJECT_NAME@
+
+// Define to the full name of this package.
+#define PACKAGE_NAME @PACKAGE_NAME@
+
+// Define to the full name and version of this package.
+#define PACKAGE_STRING @PACKAGE_STRING@
+
+// Define to the one symbol short name of this package.
+#define PACKAGE_TARNAME @PACKAGE_TARNAME@
+
+// Define to the version of this package.
+#define PACKAGE_VERSION @PACKAGE_VERSION@
+
+// Version number of package.
+#define VERSION PACKAGE_VERSION
+
+// Define to the address where bug reports for this package should be sent.
+#define PACKAGE_BUGREPORT @PACKAGE_BUGREPORT@
+
+// ---------------------------------------------------------------------------
+// Path separator
+#ifndef PATH_SEPARATOR
+#  ifdef OS_WINDOWS
+#    define PATH_SEPARATOR  '\\'
+#  else
+#    define PATH_SEPARATOR  '/'
+#  endif
+#endif
+
+// ---------------------------------------------------------------------------
+// Windows
+
+// Whether gflags library is a DLL.
+#ifndef GFLAGS_IS_A_DLL
+#  define GFLAGS_IS_A_DLL 0
+#endif
+
+// Always export symbols when compiling a shared library as this file is only
+// included by internal modules when building the gflags library itself.
+// The gflags_declare.h header file will set it to import these symbols otherwise.
+#ifndef GFLAGS_DLL_DECL
+#  if GFLAGS_IS_A_DLL && defined(_MSC_VER)
+#    define GFLAGS_DLL_DECL __declspec(dllexport)
+#  else
+#    define GFLAGS_DLL_DECL
+#  endif
+#endif
+// Flags defined by the gflags library itself must be exported
+#ifndef GFLAGS_DLL_DEFINE_FLAG
+#  define GFLAGS_DLL_DEFINE_FLAG GFLAGS_DLL_DECL
+#endif
+
+#ifdef OS_WINDOWS
+// The unittests import the symbols of the shared gflags library
+#  if GFLAGS_IS_A_DLL && defined(_MSC_VER)
+#    define GFLAGS_DLL_DECL_FOR_UNITTESTS __declspec(dllimport)
+#  endif
+#  include "windows_port.h"
+#endif
diff --git a/third_party/gflags/src/gflags.cc b/third_party/gflags/src/gflags.cc
new file mode 100644
index 0000000..285050f
--- /dev/null
+++ b/third_party/gflags/src/gflags.cc
@@ -0,0 +1,1957 @@
+// Copyright (c) 1999, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ---
+// Revamped and reorganized by Craig Silverstein
+//
+// This file contains the implementation of all our command line flags
+// stuff.  Here's how everything fits together
+//
+// * FlagRegistry owns CommandLineFlags owns FlagValue.
+// * FlagSaver holds a FlagRegistry (saves it at construct time,
+//     restores it at destroy time).
+// * CommandLineFlagParser lives outside that hierarchy, but works on
+//     CommandLineFlags (modifying the FlagValues).
+// * Free functions like SetCommandLineOption() work via one of the
+//     above (such as CommandLineFlagParser).
+//
+// In more detail:
+//
+// -- The main classes that hold flag data:
+//
+// FlagValue holds the current value of a flag.  It's
+// pseudo-templatized: every operation on a FlagValue is typed.  It
+// also deals with storage-lifetime issues (so flag values don't go
+// away in a destructor), which is why we need a whole class to hold a
+// variable's value.
+//
+// CommandLineFlag is all the information about a single command-line
+// flag.  It has a FlagValue for the flag's current value, but also
+// the flag's name, type, etc.
+//
+// FlagRegistry is a collection of CommandLineFlags.  There's the
+// global registry, which is where flags defined via DEFINE_foo()
+// live.  But it's possible to define your own flag, manually, in a
+// different registry you create.  (In practice, multiple registries
+// are used only by FlagSaver).
+//
+// A given FlagValue is owned by exactly one CommandLineFlag.  A given
+// CommandLineFlag is owned by exactly one FlagRegistry.  FlagRegistry
+// has a lock; any operation that writes to a FlagValue or
+// CommandLineFlag owned by that registry must acquire the
+// FlagRegistry lock before doing so.
+//
+// --- Some other classes and free functions:
+//
+// CommandLineFlagInfo is a client-exposed version of CommandLineFlag.
+// Once it's instantiated, it has no dependencies or relationships
+// with any other part of this file.
+//
+// FlagRegisterer is the helper class used by the DEFINE_* macros to
+// allow work to be done at global initialization time.
+//
+// CommandLineFlagParser is the class that reads from the commandline
+// and instantiates flag values based on that.  It needs to poke into
+// the innards of the FlagValue->CommandLineFlag->FlagRegistry class
+// hierarchy to do that.  It's careful to acquire the FlagRegistry
+// lock before doing any writing or other non-const actions.
+//
+// GetCommandLineOption is just a hook into registry routines to
+// retrieve a flag based on its name.  SetCommandLineOption, on the
+// other hand, hooks into CommandLineFlagParser.  Other API functions
+// are, similarly, mostly hooks into the functionality described above.
+
+#include "config.h"
+#include "gflags.h"
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#if defined(HAVE_FNMATCH_H)
+#  include <fnmatch.h>
+#elif defined(HAVE_SHLWAPI_H)
+#  include <shlwapi.h>
+#endif
+#include <stdarg.h> // For va_list and related operations
+#include <stdio.h>
+#include <string.h>
+
+#include <algorithm>
+#include <map>
+#include <string>
+#include <utility>     // for pair<>
+#include <vector>
+
+#include "mutex.h"
+#include "util.h"
+
+// Special flags, type 1: the 'recursive' flags.  They set another flag's val.
+DEFINE_string(flagfile,   "", "load flags from file");
+DEFINE_string(fromenv,    "", "set flags from the environment"
+                              " [use 'export FLAGS_flag1=value']");
+DEFINE_string(tryfromenv, "", "set flags from the environment if present");
+
+// Special flags, type 2: the 'parsing' flags.  They modify how we parse.
+DEFINE_string(undefok, "", "comma-separated list of flag names that it is okay to specify "
+                           "on the command line even if the program does not define a flag "
+                           "with that name.  IMPORTANT: flags in this list that have "
+                           "arguments MUST use the flag=value format");
+
+namespace GFLAGS_NAMESPACE {
+
+using std::map;
+using std::pair;
+using std::sort;
+using std::string;
+using std::vector;
+
+// This is used by the unittest to test error-exit code
+void GFLAGS_DLL_DECL (*gflags_exitfunc)(int) = &exit;  // from stdlib.h
+
+
+// The help message indicating that the commandline flag has been
+// 'stripped'. It will not show up when doing "-help" and its
+// variants. The flag is stripped if STRIP_FLAG_HELP is set to 1
+// before including base/gflags.h
+
+// This is used by this file, and also in gflags_reporting.cc
+const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001";
+
+namespace {
+
+// There are also 'reporting' flags, in gflags_reporting.cc.
+
+static const char kError[] = "ERROR: ";
+
+// Indicates that undefined options are to be ignored.
+// Enables deferred processing of flags in dynamically loaded libraries.
+static bool allow_command_line_reparsing = false;
+
+static bool logging_is_probably_set_up = false;
+
+// This is a 'prototype' validate-function.  'Real' validate
+// functions, take a flag-value as an argument: ValidateFn(bool) or
+// ValidateFn(uint64).  However, for easier storage, we strip off this
+// argument and then restore it when actually calling the function on
+// a flag value.
+typedef bool (*ValidateFnProto)();
+
+// Whether we should die when reporting an error.
+enum DieWhenReporting { DIE, DO_NOT_DIE };
+
+// Report Error and exit if requested.
+static void ReportError(DieWhenReporting should_die, const char* format, ...) {
+  char error_message[255];
+  va_list ap;
+  va_start(ap, format);
+  vsnprintf(error_message, sizeof(error_message), format, ap);
+  va_end(ap);
+  fprintf(stderr, "%s", error_message);
+  fflush(stderr);   // should be unnecessary, but cygwin's rxvt buffers stderr
+  if (should_die == DIE) gflags_exitfunc(1);
+}
+
+
+// --------------------------------------------------------------------
+// FlagValue
+//    This represent the value a single flag might have.  The major
+//    functionality is to convert from a string to an object of a
+//    given type, and back.  Thread-compatible.
+// --------------------------------------------------------------------
+
+class CommandLineFlag;
+class FlagValue {
+ public:
+  FlagValue(void* valbuf, const char* type, bool transfer_ownership_of_value);
+  ~FlagValue();
+
+  bool ParseFrom(const char* spec);
+  string ToString() const;
+
+ private:
+  friend class CommandLineFlag;  // for many things, including Validate()
+  friend class GFLAGS_NAMESPACE::FlagSaverImpl;  // calls New()
+  friend class FlagRegistry;     // checks value_buffer_ for flags_by_ptr_ map
+  template <typename T> friend T GetFromEnv(const char*, const char*, T);
+  friend bool TryParseLocked(const CommandLineFlag*, FlagValue*,
+                             const char*, string*);  // for New(), CopyFrom()
+
+  enum ValueType {
+    FV_BOOL = 0,
+    FV_INT32 = 1,
+    FV_INT64 = 2,
+    FV_UINT64 = 3,
+    FV_DOUBLE = 4,
+    FV_STRING = 5,
+    FV_MAX_INDEX = 5,
+  };
+  const char* TypeName() const;
+  bool Equal(const FlagValue& x) const;
+  FlagValue* New() const;   // creates a new one with default value
+  void CopyFrom(const FlagValue& x);
+  int ValueSize() const;
+
+  // Calls the given validate-fn on value_buffer_, and returns
+  // whatever it returns.  But first casts validate_fn_proto to a
+  // function that takes our value as an argument (eg void
+  // (*validate_fn)(bool) for a bool flag).
+  bool Validate(const char* flagname, ValidateFnProto validate_fn_proto) const;
+
+  void* value_buffer_;          // points to the buffer holding our data
+  int8 type_;                   // how to interpret value_
+  bool owns_value_;         // whether to free value on destruct
+
+  FlagValue(const FlagValue&);   // no copying!
+  void operator=(const FlagValue&);
+};
+
+
+// This could be a templated method of FlagValue, but doing so adds to the
+// size of the .o.  Since there's no type-safety here anyway, macro is ok.
+#define VALUE_AS(type)  *reinterpret_cast<type*>(value_buffer_)
+#define OTHER_VALUE_AS(fv, type)  *reinterpret_cast<type*>(fv.value_buffer_)
+#define SET_VALUE_AS(type, value)  VALUE_AS(type) = (value)
+
+FlagValue::FlagValue(void* valbuf, const char* type,
+                     bool transfer_ownership_of_value)
+    : value_buffer_(valbuf),
+      owns_value_(transfer_ownership_of_value) {
+  for (type_ = 0; type_ <= FV_MAX_INDEX; ++type_) {
+    if (!strcmp(type, TypeName())) {
+      break;
+    }
+  }
+  assert(type_ <= FV_MAX_INDEX);  // Unknown typename
+}
+
+FlagValue::~FlagValue() {
+  if (!owns_value_) {
+    return;
+  }
+  switch (type_) {
+    case FV_BOOL: delete reinterpret_cast<bool*>(value_buffer_); break;
+    case FV_INT32: delete reinterpret_cast<int32*>(value_buffer_); break;
+    case FV_INT64: delete reinterpret_cast<int64*>(value_buffer_); break;
+    case FV_UINT64: delete reinterpret_cast<uint64*>(value_buffer_); break;
+    case FV_DOUBLE: delete reinterpret_cast<double*>(value_buffer_); break;
+    case FV_STRING: delete reinterpret_cast<string*>(value_buffer_); break;
+  }
+}
+
+bool FlagValue::ParseFrom(const char* value) {
+  if (type_ == FV_BOOL) {
+    const char* kTrue[] = { "1", "t", "true", "y", "yes" };
+    const char* kFalse[] = { "0", "f", "false", "n", "no" };
+    COMPILE_ASSERT(sizeof(kTrue) == sizeof(kFalse), true_false_equal);
+    for (size_t i = 0; i < sizeof(kTrue)/sizeof(*kTrue); ++i) {
+      if (strcasecmp(value, kTrue[i]) == 0) {
+        SET_VALUE_AS(bool, true);
+        return true;
+      } else if (strcasecmp(value, kFalse[i]) == 0) {
+        SET_VALUE_AS(bool, false);
+        return true;
+      }
+    }
+    return false;   // didn't match a legal input
+
+  } else if (type_ == FV_STRING) {
+    SET_VALUE_AS(string, value);
+    return true;
+  }
+
+  // OK, it's likely to be numeric, and we'll be using a strtoXXX method.
+  if (value[0] == '\0')   // empty-string is only allowed for string type.
+    return false;
+  char* end;
+  // Leading 0x puts us in base 16.  But leading 0 does not put us in base 8!
+  // It caused too many bugs when we had that behavior.
+  int base = 10;    // by default
+  if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'))
+    base = 16;
+  errno = 0;
+
+  switch (type_) {
+    case FV_INT32: {
+      const int64 r = strto64(value, &end, base);
+      if (errno || end != value + strlen(value))  return false;  // bad parse
+      if (static_cast<int32>(r) != r)  // worked, but number out of range
+        return false;
+      SET_VALUE_AS(int32, static_cast<int32>(r));
+      return true;
+    }
+    case FV_INT64: {
+      const int64 r = strto64(value, &end, base);
+      if (errno || end != value + strlen(value))  return false;  // bad parse
+      SET_VALUE_AS(int64, r);
+      return true;
+    }
+    case FV_UINT64: {
+      while (*value == ' ') value++;
+      if (*value == '-') return false;  // negative number
+      const uint64 r = strtou64(value, &end, base);
+      if (errno || end != value + strlen(value))  return false;  // bad parse
+      SET_VALUE_AS(uint64, r);
+      return true;
+    }
+    case FV_DOUBLE: {
+      const double r = strtod(value, &end);
+      if (errno || end != value + strlen(value))  return false;  // bad parse
+      SET_VALUE_AS(double, r);
+      return true;
+    }
+    default: {
+      assert(false);  // unknown type
+      return false;
+    }
+  }
+}
+
+string FlagValue::ToString() const {
+  char intbuf[64];    // enough to hold even the biggest number
+  switch (type_) {
+    case FV_BOOL:
+      return VALUE_AS(bool) ? "true" : "false";
+    case FV_INT32:
+      snprintf(intbuf, sizeof(intbuf), "%" PRId32, VALUE_AS(int32));
+      return intbuf;
+    case FV_INT64:
+      snprintf(intbuf, sizeof(intbuf), "%" PRId64, VALUE_AS(int64));
+      return intbuf;
+    case FV_UINT64:
+      snprintf(intbuf, sizeof(intbuf), "%" PRIu64, VALUE_AS(uint64));
+      return intbuf;
+    case FV_DOUBLE:
+      snprintf(intbuf, sizeof(intbuf), "%.17g", VALUE_AS(double));
+      return intbuf;
+    case FV_STRING:
+      return VALUE_AS(string);
+    default:
+      assert(false);
+      return "";  // unknown type
+  }
+}
+
+bool FlagValue::Validate(const char* flagname,
+                         ValidateFnProto validate_fn_proto) const {
+  switch (type_) {
+    case FV_BOOL:
+      return reinterpret_cast<bool (*)(const char*, bool)>(
+          validate_fn_proto)(flagname, VALUE_AS(bool));
+    case FV_INT32:
+      return reinterpret_cast<bool (*)(const char*, int32)>(
+          validate_fn_proto)(flagname, VALUE_AS(int32));
+    case FV_INT64:
+      return reinterpret_cast<bool (*)(const char*, int64)>(
+          validate_fn_proto)(flagname, VALUE_AS(int64));
+    case FV_UINT64:
+      return reinterpret_cast<bool (*)(const char*, uint64)>(
+          validate_fn_proto)(flagname, VALUE_AS(uint64));
+    case FV_DOUBLE:
+      return reinterpret_cast<bool (*)(const char*, double)>(
+          validate_fn_proto)(flagname, VALUE_AS(double));
+    case FV_STRING:
+      return reinterpret_cast<bool (*)(const char*, const string&)>(
+          validate_fn_proto)(flagname, VALUE_AS(string));
+    default:
+      assert(false);  // unknown type
+      return false;
+  }
+}
+
+const char* FlagValue::TypeName() const {
+  static const char types[] =
+      "bool\0xx"
+      "int32\0x"
+      "int64\0x"
+      "uint64\0"
+      "double\0"
+      "string";
+  if (type_ > FV_MAX_INDEX) {
+    assert(false);
+    return "";
+  }
+  // Directly indexing the strings in the 'types' string, each of them is 7 bytes long.
+  return &types[type_ * 7];
+}
+
+bool FlagValue::Equal(const FlagValue& x) const {
+  if (type_ != x.type_)
+    return false;
+  switch (type_) {
+    case FV_BOOL:   return VALUE_AS(bool) == OTHER_VALUE_AS(x, bool);
+    case FV_INT32:  return VALUE_AS(int32) == OTHER_VALUE_AS(x, int32);
+    case FV_INT64:  return VALUE_AS(int64) == OTHER_VALUE_AS(x, int64);
+    case FV_UINT64: return VALUE_AS(uint64) == OTHER_VALUE_AS(x, uint64);
+    case FV_DOUBLE: return VALUE_AS(double) == OTHER_VALUE_AS(x, double);
+    case FV_STRING: return VALUE_AS(string) == OTHER_VALUE_AS(x, string);
+    default: assert(false); return false;  // unknown type
+  }
+}
+
+FlagValue* FlagValue::New() const {
+  const char *type = TypeName();
+  switch (type_) {
+    case FV_BOOL:   return new FlagValue(new bool(false), type, true);
+    case FV_INT32:  return new FlagValue(new int32(0), type, true);
+    case FV_INT64:  return new FlagValue(new int64(0), type, true);
+    case FV_UINT64: return new FlagValue(new uint64(0), type, true);
+    case FV_DOUBLE: return new FlagValue(new double(0.0), type, true);
+    case FV_STRING: return new FlagValue(new string, type, true);
+    default: assert(false); return NULL;  // unknown type
+  }
+}
+
+void FlagValue::CopyFrom(const FlagValue& x) {
+  assert(type_ == x.type_);
+  switch (type_) {
+    case FV_BOOL:   SET_VALUE_AS(bool, OTHER_VALUE_AS(x, bool));      break;
+    case FV_INT32:  SET_VALUE_AS(int32, OTHER_VALUE_AS(x, int32));    break;
+    case FV_INT64:  SET_VALUE_AS(int64, OTHER_VALUE_AS(x, int64));    break;
+    case FV_UINT64: SET_VALUE_AS(uint64, OTHER_VALUE_AS(x, uint64));  break;
+    case FV_DOUBLE: SET_VALUE_AS(double, OTHER_VALUE_AS(x, double));  break;
+    case FV_STRING: SET_VALUE_AS(string, OTHER_VALUE_AS(x, string));  break;
+    default: assert(false);  // unknown type
+  }
+}
+
+int FlagValue::ValueSize() const {
+  if (type_ > FV_MAX_INDEX) {
+    assert(false);  // unknown type
+    return 0;
+  }
+  static const uint8 valuesize[] = {
+    sizeof(bool),
+    sizeof(int32),
+    sizeof(int64),
+    sizeof(uint64),
+    sizeof(double),
+    sizeof(string),
+  };
+  return valuesize[type_];
+}
+
+// --------------------------------------------------------------------
+// CommandLineFlag
+//    This represents a single flag, including its name, description,
+//    default value, and current value.  Mostly this serves as a
+//    struct, though it also knows how to register itself.
+//       All CommandLineFlags are owned by a (exactly one)
+//    FlagRegistry.  If you wish to modify fields in this class, you
+//    should acquire the FlagRegistry lock for the registry that owns
+//    this flag.
+// --------------------------------------------------------------------
+
+class CommandLineFlag {
+ public:
+  // Note: we take over memory-ownership of current_val and default_val.
+  CommandLineFlag(const char* name, const char* help, const char* filename,
+                  FlagValue* current_val, FlagValue* default_val);
+  ~CommandLineFlag();
+
+  const char* name() const { return name_; }
+  const char* help() const { return help_; }
+  const char* filename() const { return file_; }
+  const char* CleanFileName() const;  // nixes irrelevant prefix such as homedir
+  string current_value() const { return current_->ToString(); }
+  string default_value() const { return defvalue_->ToString(); }
+  const char* type_name() const { return defvalue_->TypeName(); }
+  ValidateFnProto validate_function() const { return validate_fn_proto_; }
+  const void* flag_ptr() const { return current_->value_buffer_; }
+
+  void FillCommandLineFlagInfo(struct CommandLineFlagInfo* result);
+
+  // If validate_fn_proto_ is non-NULL, calls it on value, returns result.
+  bool Validate(const FlagValue& value) const;
+  bool ValidateCurrent() const { return Validate(*current_); }
+
+ private:
+  // for SetFlagLocked() and setting flags_by_ptr_
+  friend class FlagRegistry;
+  friend class GFLAGS_NAMESPACE::FlagSaverImpl;  // for cloning the values
+  // set validate_fn
+  friend bool AddFlagValidator(const void*, ValidateFnProto);
+
+  // This copies all the non-const members: modified, processed, defvalue, etc.
+  void CopyFrom(const CommandLineFlag& src);
+
+  void UpdateModifiedBit();
+
+  const char* const name_;     // Flag name
+  const char* const help_;     // Help message
+  const char* const file_;     // Which file did this come from?
+  bool modified_;              // Set after default assignment?
+  FlagValue* defvalue_;        // Default value for flag
+  FlagValue* current_;         // Current value for flag
+  // This is a casted, 'generic' version of validate_fn, which actually
+  // takes a flag-value as an arg (void (*validate_fn)(bool), say).
+  // When we pass this to current_->Validate(), it will cast it back to
+  // the proper type.  This may be NULL to mean we have no validate_fn.
+  ValidateFnProto validate_fn_proto_;
+
+  CommandLineFlag(const CommandLineFlag&);   // no copying!
+  void operator=(const CommandLineFlag&);
+};
+
+CommandLineFlag::CommandLineFlag(const char* name, const char* help,
+                                 const char* filename,
+                                 FlagValue* current_val, FlagValue* default_val)
+    : name_(name), help_(help), file_(filename), modified_(false),
+      defvalue_(default_val), current_(current_val), validate_fn_proto_(NULL) {
+}
+
+CommandLineFlag::~CommandLineFlag() {
+  delete current_;
+  delete defvalue_;
+}
+
+const char* CommandLineFlag::CleanFileName() const {
+  // Compute top-level directory & file that this appears in
+  // search full path backwards.
+  // Stop going backwards at kRootDir; and skip by the first slash.
+  static const char kRootDir[] = "";    // can set this to root directory,
+
+  if (sizeof(kRootDir)-1 == 0)          // no prefix to strip
+    return filename();
+
+  const char* clean_name = filename() + strlen(filename()) - 1;
+  while ( clean_name > filename() ) {
+    if (*clean_name == PATH_SEPARATOR) {
+      if (strncmp(clean_name, kRootDir, sizeof(kRootDir)-1) == 0) {
+        clean_name += sizeof(kRootDir)-1;    // past root-dir
+        break;
+      }
+    }
+    --clean_name;
+  }
+  while ( *clean_name == PATH_SEPARATOR ) ++clean_name;  // Skip any slashes
+  return clean_name;
+}
+
+void CommandLineFlag::FillCommandLineFlagInfo(
+    CommandLineFlagInfo* result) {
+  result->name = name();
+  result->type = type_name();
+  result->description = help();
+  result->current_value = current_value();
+  result->default_value = default_value();
+  result->filename = CleanFileName();
+  UpdateModifiedBit();
+  result->is_default = !modified_;
+  result->has_validator_fn = validate_function() != NULL;
+  result->flag_ptr = flag_ptr();
+}
+
+void CommandLineFlag::UpdateModifiedBit() {
+  // Update the "modified" bit in case somebody bypassed the
+  // Flags API and wrote directly through the FLAGS_name variable.
+  if (!modified_ && !current_->Equal(*defvalue_)) {
+    modified_ = true;
+  }
+}
+
+void CommandLineFlag::CopyFrom(const CommandLineFlag& src) {
+  // Note we only copy the non-const members; others are fixed at construct time
+  if (modified_ != src.modified_) modified_ = src.modified_;
+  if (!current_->Equal(*src.current_)) current_->CopyFrom(*src.current_);
+  if (!defvalue_->Equal(*src.defvalue_)) defvalue_->CopyFrom(*src.defvalue_);
+  if (validate_fn_proto_ != src.validate_fn_proto_)
+    validate_fn_proto_ = src.validate_fn_proto_;
+}
+
+bool CommandLineFlag::Validate(const FlagValue& value) const {
+
+  if (validate_function() == NULL)
+    return true;
+  else
+    return value.Validate(name(), validate_function());
+}
+
+
+// --------------------------------------------------------------------
+// FlagRegistry
+//    A FlagRegistry singleton object holds all flag objects indexed
+//    by their names so that if you know a flag's name (as a C
+//    string), you can access or set it.  If the function is named
+//    FooLocked(), you must own the registry lock before calling
+//    the function; otherwise, you should *not* hold the lock, and
+//    the function will acquire it itself if needed.
+// --------------------------------------------------------------------
+
+struct StringCmp {  // Used by the FlagRegistry map class to compare char*'s
+  bool operator() (const char* s1, const char* s2) const {
+    return (strcmp(s1, s2) < 0);
+  }
+};
+
+
+class FlagRegistry {
+ public:
+  FlagRegistry() {
+  }
+  ~FlagRegistry() {
+    // Not using STLDeleteElements as that resides in util and this
+    // class is base.
+    for (FlagMap::iterator p = flags_.begin(), e = flags_.end(); p != e; ++p) {
+      CommandLineFlag* flag = p->second;
+      delete flag;
+    }
+  }
+
+  static void DeleteGlobalRegistry() {
+    delete global_registry_;
+    global_registry_ = NULL;
+  }
+
+  // Store a flag in this registry.  Takes ownership of the given pointer.
+  void RegisterFlag(CommandLineFlag* flag);
+
+  void Lock() { lock_.Lock(); }
+  void Unlock() { lock_.Unlock(); }
+
+  // Returns the flag object for the specified name, or NULL if not found.
+  CommandLineFlag* FindFlagLocked(const char* name);
+
+  // Returns the flag object whose current-value is stored at flag_ptr.
+  // That is, for whom current_->value_buffer_ == flag_ptr
+  CommandLineFlag* FindFlagViaPtrLocked(const void* flag_ptr);
+
+  // A fancier form of FindFlag that works correctly if name is of the
+  // form flag=value.  In that case, we set key to point to flag, and
+  // modify v to point to the value (if present), and return the flag
+  // with the given name.  If the flag does not exist, returns NULL
+  // and sets error_message.
+  CommandLineFlag* SplitArgumentLocked(const char* argument,
+                                       string* key, const char** v,
+                                       string* error_message);
+
+  // Set the value of a flag.  If the flag was successfully set to
+  // value, set msg to indicate the new flag-value, and return true.
+  // Otherwise, set msg to indicate the error, leave flag unchanged,
+  // and return false.  msg can be NULL.
+  bool SetFlagLocked(CommandLineFlag* flag, const char* value,
+                     FlagSettingMode set_mode, string* msg);
+
+  static FlagRegistry* GlobalRegistry();   // returns a singleton registry
+
+ private:
+  friend class GFLAGS_NAMESPACE::FlagSaverImpl;  // reads all the flags in order to copy them
+  friend class CommandLineFlagParser;    // for ValidateAllFlags
+  friend void GFLAGS_NAMESPACE::GetAllFlags(vector<CommandLineFlagInfo>*);
+
+  // The map from name to flag, for FindFlagLocked().
+  typedef map<const char*, CommandLineFlag*, StringCmp> FlagMap;
+  typedef FlagMap::iterator FlagIterator;
+  typedef FlagMap::const_iterator FlagConstIterator;
+  FlagMap flags_;
+
+  // The map from current-value pointer to flag, fo FindFlagViaPtrLocked().
+  typedef map<const void*, CommandLineFlag*> FlagPtrMap;
+  FlagPtrMap flags_by_ptr_;
+
+  static FlagRegistry* global_registry_;   // a singleton registry
+
+  Mutex lock_;
+  static Mutex global_registry_lock_;
+
+  static void InitGlobalRegistry();
+
+  // Disallow
+  FlagRegistry(const FlagRegistry&);
+  FlagRegistry& operator=(const FlagRegistry&);
+};
+
+class FlagRegistryLock {
+ public:
+  explicit FlagRegistryLock(FlagRegistry* fr) : fr_(fr) { fr_->Lock(); }
+  ~FlagRegistryLock() { fr_->Unlock(); }
+ private:
+  FlagRegistry *const fr_;
+};
+
+
+void FlagRegistry::RegisterFlag(CommandLineFlag* flag) {
+  Lock();
+  pair<FlagIterator, bool> ins =
+    flags_.insert(pair<const char*, CommandLineFlag*>(flag->name(), flag));
+  if (ins.second == false) {   // means the name was already in the map
+    if (strcmp(ins.first->second->filename(), flag->filename()) != 0) {
+      ReportError(DIE, "ERROR: flag '%s' was defined more than once "
+                  "(in files '%s' and '%s').\n",
+                  flag->name(),
+                  ins.first->second->filename(),
+                  flag->filename());
+    } else {
+      ReportError(DIE, "ERROR: something wrong with flag '%s' in file '%s'.  "
+                  "One possibility: file '%s' is being linked both statically "
+                  "and dynamically into this executable.\n",
+                  flag->name(),
+                  flag->filename(), flag->filename());
+    }
+  }
+  // Also add to the flags_by_ptr_ map.
+  flags_by_ptr_[flag->current_->value_buffer_] = flag;
+  Unlock();
+}
+
+CommandLineFlag* FlagRegistry::FindFlagLocked(const char* name) {
+  FlagConstIterator i = flags_.find(name);
+  if (i == flags_.end()) {
+    return NULL;
+  } else {
+    return i->second;
+  }
+}
+
+CommandLineFlag* FlagRegistry::FindFlagViaPtrLocked(const void* flag_ptr) {
+  FlagPtrMap::const_iterator i = flags_by_ptr_.find(flag_ptr);
+  if (i == flags_by_ptr_.end()) {
+    return NULL;
+  } else {
+    return i->second;
+  }
+}
+
+CommandLineFlag* FlagRegistry::SplitArgumentLocked(const char* arg,
+                                                   string* key,
+                                                   const char** v,
+                                                   string* error_message) {
+  // Find the flag object for this option
+  const char* flag_name;
+  const char* value = strchr(arg, '=');
+  if (value == NULL) {
+    key->assign(arg);
+    *v = NULL;
+  } else {
+    // Strip out the "=value" portion from arg
+    key->assign(arg, value-arg);
+    *v = ++value;    // advance past the '='
+  }
+  flag_name = key->c_str();
+
+  CommandLineFlag* flag = FindFlagLocked(flag_name);
+
+  if (flag == NULL) {
+    // If we can't find the flag-name, then we should return an error.
+    // The one exception is if 1) the flag-name is 'nox', 2) there
+    // exists a flag named 'x', and 3) 'x' is a boolean flag.
+    // In that case, we want to return flag 'x'.
+    if (!(flag_name[0] == 'n' && flag_name[1] == 'o')) {
+      // flag-name is not 'nox', so we're not in the exception case.
+      *error_message = StringPrintf("%sunknown command line flag '%s'\n",
+                                    kError, key->c_str());
+      return NULL;
+    }
+    flag = FindFlagLocked(flag_name+2);
+    if (flag == NULL) {
+      // No flag named 'x' exists, so we're not in the exception case.
+      *error_message = StringPrintf("%sunknown command line flag '%s'\n",
+                                    kError, key->c_str());
+      return NULL;
+    }
+    if (strcmp(flag->type_name(), "bool") != 0) {
+      // 'x' exists but is not boolean, so we're not in the exception case.
+      *error_message = StringPrintf(
+          "%sboolean value (%s) specified for %s command line flag\n",
+          kError, key->c_str(), flag->type_name());
+      return NULL;
+    }
+    // We're in the exception case!
+    // Make up a fake value to replace the "no" we stripped out
+    key->assign(flag_name+2);   // the name without the "no"
+    *v = "0";
+  }
+
+  // Assign a value if this is a boolean flag
+  if (*v == NULL && strcmp(flag->type_name(), "bool") == 0) {
+    *v = "1";    // the --nox case was already handled, so this is the --x case
+  }
+
+  return flag;
+}
+
+bool TryParseLocked(const CommandLineFlag* flag, FlagValue* flag_value,
+                    const char* value, string* msg) {
+  // Use tenative_value, not flag_value, until we know value is valid.
+  FlagValue* tentative_value = flag_value->New();
+  if (!tentative_value->ParseFrom(value)) {
+    if (msg) {
+      StringAppendF(msg,
+                    "%sillegal value '%s' specified for %s flag '%s'\n",
+                    kError, value,
+                    flag->type_name(), flag->name());
+    }
+    delete tentative_value;
+    return false;
+  } else if (!flag->Validate(*tentative_value)) {
+    if (msg) {
+      StringAppendF(msg,
+          "%sfailed validation of new value '%s' for flag '%s'\n",
+          kError, tentative_value->ToString().c_str(),
+          flag->name());
+    }
+    delete tentative_value;
+    return false;
+  } else {
+    flag_value->CopyFrom(*tentative_value);
+    if (msg) {
+      StringAppendF(msg, "%s set to %s\n",
+                    flag->name(), flag_value->ToString().c_str());
+    }
+    delete tentative_value;
+    return true;
+  }
+}
+
+bool FlagRegistry::SetFlagLocked(CommandLineFlag* flag,
+                                 const char* value,
+                                 FlagSettingMode set_mode,
+                                 string* msg) {
+  flag->UpdateModifiedBit();
+  switch (set_mode) {
+    case SET_FLAGS_VALUE: {
+      // set or modify the flag's value
+      if (!TryParseLocked(flag, flag->current_, value, msg))
+        return false;
+      flag->modified_ = true;
+      break;
+    }
+    case SET_FLAG_IF_DEFAULT: {
+      // set the flag's value, but only if it hasn't been set by someone else
+      if (!flag->modified_) {
+        if (!TryParseLocked(flag, flag->current_, value, msg))
+          return false;
+        flag->modified_ = true;
+      } else {
+        *msg = StringPrintf("%s set to %s",
+                            flag->name(), flag->current_value().c_str());
+      }
+      break;
+    }
+    case SET_FLAGS_DEFAULT: {
+      // modify the flag's default-value
+      if (!TryParseLocked(flag, flag->defvalue_, value, msg))
+        return false;
+      if (!flag->modified_) {
+        // Need to set both defvalue *and* current, in this case
+        TryParseLocked(flag, flag->current_, value, NULL);
+      }
+      break;
+    }
+    default: {
+      // unknown set_mode
+      assert(false);
+      return false;
+    }
+  }
+
+  return true;
+}
+
+// Get the singleton FlagRegistry object
+FlagRegistry* FlagRegistry::global_registry_ = NULL;
+Mutex FlagRegistry::global_registry_lock_(Mutex::LINKER_INITIALIZED);
+
+FlagRegistry* FlagRegistry::GlobalRegistry() {
+  MutexLock acquire_lock(&global_registry_lock_);
+  if (!global_registry_) {
+    global_registry_ = new FlagRegistry;
+  }
+  return global_registry_;
+}
+
+// --------------------------------------------------------------------
+// CommandLineFlagParser
+//    Parsing is done in two stages.  In the first, we go through
+//    argv.  For every flag-like arg we can make sense of, we parse
+//    it and set the appropriate FLAGS_* variable.  For every flag-
+//    like arg we can't make sense of, we store it in a vector,
+//    along with an explanation of the trouble.  In stage 2, we
+//    handle the 'reporting' flags like --help and --mpm_version.
+//    (This is via a call to HandleCommandLineHelpFlags(), in
+//    gflags_reporting.cc.)
+//    An optional stage 3 prints out the error messages.
+//       This is a bit of a simplification.  For instance, --flagfile
+//    is handled as soon as it's seen in stage 1, not in stage 2.
+// --------------------------------------------------------------------
+
+class CommandLineFlagParser {
+ public:
+  // The argument is the flag-registry to register the parsed flags in
+  explicit CommandLineFlagParser(FlagRegistry* reg) : registry_(reg) {}
+  ~CommandLineFlagParser() {}
+
+  // Stage 1: Every time this is called, it reads all flags in argv.
+  // However, it ignores all flags that have been successfully set
+  // before.  Typically this is only called once, so this 'reparsing'
+  // behavior isn't important.  It can be useful when trying to
+  // reparse after loading a dll, though.
+  uint32 ParseNewCommandLineFlags(int* argc, char*** argv, bool remove_flags);
+
+  // Stage 2: print reporting info and exit, if requested.
+  // In gflags_reporting.cc:HandleCommandLineHelpFlags().
+
+  // Stage 3: validate all the commandline flags that have validators
+  // registered.
+  void ValidateAllFlags();
+
+  // Stage 4: report any errors and return true if any were found.
+  bool ReportErrors();
+
+  // Set a particular command line option.  "newval" is a string
+  // describing the new value that the option has been set to.  If
+  // option_name does not specify a valid option name, or value is not
+  // a valid value for option_name, newval is empty.  Does recursive
+  // processing for --flagfile and --fromenv.  Returns the new value
+  // if everything went ok, or empty-string if not.  (Actually, the
+  // return-string could hold many flag/value pairs due to --flagfile.)
+  // NB: Must have called registry_->Lock() before calling this function.
+  string ProcessSingleOptionLocked(CommandLineFlag* flag,
+                                   const char* value,
+                                   FlagSettingMode set_mode);
+
+  // Set a whole batch of command line options as specified by contentdata,
+  // which is in flagfile format (and probably has been read from a flagfile).
+  // Returns the new value if everything went ok, or empty-string if
+  // not.  (Actually, the return-string could hold many flag/value
+  // pairs due to --flagfile.)
+  // NB: Must have called registry_->Lock() before calling this function.
+  string ProcessOptionsFromStringLocked(const string& contentdata,
+                                        FlagSettingMode set_mode);
+
+  // These are the 'recursive' flags, defined at the top of this file.
+  // Whenever we see these flags on the commandline, we must take action.
+  // These are called by ProcessSingleOptionLocked and, similarly, return
+  // new values if everything went ok, or the empty-string if not.
+  string ProcessFlagfileLocked(const string& flagval, FlagSettingMode set_mode);
+  // diff fromenv/tryfromenv
+  string ProcessFromenvLocked(const string& flagval, FlagSettingMode set_mode,
+                              bool errors_are_fatal);
+
+ private:
+  FlagRegistry* const registry_;
+  map<string, string> error_flags_;      // map from name to error message
+  // This could be a set<string>, but we reuse the map to minimize the .o size
+  map<string, string> undefined_names_;  // --[flag] name was not registered
+};
+
+
+// Parse a list of (comma-separated) flags.
+static void ParseFlagList(const char* value, vector<string>* flags) {
+  for (const char *p = value; p && *p; value = p) {
+    p = strchr(value, ',');
+    size_t len;
+    if (p) {
+      len = p - value;
+      p++;
+    } else {
+      len = strlen(value);
+    }
+
+    if (len == 0)
+      ReportError(DIE, "ERROR: empty flaglist entry\n");
+    if (value[0] == '-')
+      ReportError(DIE, "ERROR: flag \"%*s\" begins with '-'\n", len, value);
+
+    flags->push_back(string(value, len));
+  }
+}
+
+// Snarf an entire file into a C++ string.  This is just so that we
+// can do all the I/O in one place and not worry about it everywhere.
+// Plus, it's convenient to have the whole file contents at hand.
+// Adds a newline at the end of the file.
+#define PFATAL(s)  do { perror(s); gflags_exitfunc(1); } while (0)
+
+static string ReadFileIntoString(const char* filename) {
+  const int kBufSize = 8092;
+  char buffer[kBufSize];
+  string s;
+  FILE* fp;
+  if ((errno = SafeFOpen(&fp, filename, "r")) != 0) PFATAL(filename);
+  size_t n;
+  while ( (n=fread(buffer, 1, kBufSize, fp)) > 0 ) {
+    if (ferror(fp))  PFATAL(filename);
+    s.append(buffer, n);
+  }
+  fclose(fp);
+  return s;
+}
+
+uint32 CommandLineFlagParser::ParseNewCommandLineFlags(int* argc, char*** argv,
+                                                       bool remove_flags) {
+  const char *program_name = strrchr((*argv)[0], PATH_SEPARATOR);   // nix path
+  program_name = (program_name == NULL ? (*argv)[0] : program_name+1);
+
+  int first_nonopt = *argc;        // for non-options moved to the end
+
+  registry_->Lock();
+  for (int i = 1; i < first_nonopt; i++) {
+    char* arg = (*argv)[i];
+
+    // Like getopt(), we permute non-option flags to be at the end.
+    if (arg[0] != '-' ||           // must be a program argument
+        (arg[0] == '-' && arg[1] == '\0')) {  // "-" is an argument, not a flag
+      memmove((*argv) + i, (*argv) + i+1, (*argc - (i+1)) * sizeof((*argv)[i]));
+      (*argv)[*argc-1] = arg;      // we go last
+      first_nonopt--;              // we've been pushed onto the stack
+      i--;                         // to undo the i++ in the loop
+      continue;
+    }
+
+    if (arg[0] == '-') arg++;      // allow leading '-'
+    if (arg[0] == '-') arg++;      // or leading '--'
+
+    // -- alone means what it does for GNU: stop options parsing
+    if (*arg == '\0') {
+      first_nonopt = i+1;
+      break;
+    }
+
+    // Find the flag object for this option
+    string key;
+    const char* value;
+    string error_message;
+    CommandLineFlag* flag = registry_->SplitArgumentLocked(arg, &key, &value,
+                                                           &error_message);
+    if (flag == NULL) {
+      undefined_names_[key] = "";    // value isn't actually used
+      error_flags_[key] = error_message;
+      continue;
+    }
+
+    if (value == NULL) {
+      // Boolean options are always assigned a value by SplitArgumentLocked()
+      assert(strcmp(flag->type_name(), "bool") != 0);
+      if (i+1 >= first_nonopt) {
+        // This flag needs a value, but there is nothing available
+        error_flags_[key] = (string(kError) + "flag '" + (*argv)[i] + "'"
+                             + " is missing its argument");
+        if (flag->help() && flag->help()[0] > '\001') {
+          // Be useful in case we have a non-stripped description.
+          error_flags_[key] += string("; flag description: ") + flag->help();
+        }
+        error_flags_[key] += "\n";
+        break;    // we treat this as an unrecoverable error
+      } else {
+        value = (*argv)[++i];                   // read next arg for value
+
+        // Heuristic to detect the case where someone treats a string arg
+        // like a bool:
+        // --my_string_var --foo=bar
+        // We look for a flag of string type, whose value begins with a
+        // dash, and where the flag-name and value are separated by a
+        // space rather than an '='.
+        // To avoid false positives, we also require the word "true"
+        // or "false" in the help string.  Without this, a valid usage
+        // "-lat -30.5" would trigger the warning.  The common cases we
+        // want to solve talk about true and false as values.
+        if (value[0] == '-'
+            && strcmp(flag->type_name(), "string") == 0
+            && (strstr(flag->help(), "true")
+                || strstr(flag->help(), "false"))) {
+          LOG(WARNING) << "Did you really mean to set flag '"
+                       << flag->name() << "' to the value '"
+                       << value << "'?";
+        }
+      }
+    }
+
+    // TODO(csilvers): only set a flag if we hadn't set it before here
+    ProcessSingleOptionLocked(flag, value, SET_FLAGS_VALUE);
+  }
+  registry_->Unlock();
+
+  if (remove_flags) {   // Fix up argc and argv by removing command line flags
+    (*argv)[first_nonopt-1] = (*argv)[0];
+    (*argv) += (first_nonopt-1);
+    (*argc) -= (first_nonopt-1);
+    first_nonopt = 1;   // because we still don't count argv[0]
+  }
+
+  logging_is_probably_set_up = true;   // because we've parsed --logdir, etc.
+
+  return first_nonopt;
+}
+
+string CommandLineFlagParser::ProcessFlagfileLocked(const string& flagval,
+                                                    FlagSettingMode set_mode) {
+  if (flagval.empty())
+    return "";
+
+  string msg;
+  vector<string> filename_list;
+  ParseFlagList(flagval.c_str(), &filename_list);  // take a list of filenames
+  for (size_t i = 0; i < filename_list.size(); ++i) {
+    const char* file = filename_list[i].c_str();
+    msg += ProcessOptionsFromStringLocked(ReadFileIntoString(file), set_mode);
+  }
+  return msg;
+}
+
+string CommandLineFlagParser::ProcessFromenvLocked(const string& flagval,
+                                                   FlagSettingMode set_mode,
+                                                   bool errors_are_fatal) {
+  if (flagval.empty())
+    return "";
+
+  string msg;
+  vector<string> flaglist;
+  ParseFlagList(flagval.c_str(), &flaglist);
+
+  for (size_t i = 0; i < flaglist.size(); ++i) {
+    const char* flagname = flaglist[i].c_str();
+    CommandLineFlag* flag = registry_->FindFlagLocked(flagname);
+    if (flag == NULL) {
+      error_flags_[flagname] =
+          StringPrintf("%sunknown command line flag '%s' "
+                       "(via --fromenv or --tryfromenv)\n",
+                       kError, flagname);
+      undefined_names_[flagname] = "";
+      continue;
+    }
+
+    const string envname = string("FLAGS_") + string(flagname);
+	string envval;
+	if (!SafeGetEnv(envname.c_str(), envval)) {
+      if (errors_are_fatal) {
+        error_flags_[flagname] = (string(kError) + envname +
+                                  " not found in environment\n");
+      }
+      continue;
+    }
+
+    // Avoid infinite recursion.
+    if (envval == "fromenv" || envval == "tryfromenv") {
+      error_flags_[flagname] =
+          StringPrintf("%sinfinite recursion on environment flag '%s'\n",
+                       kError, envval.c_str());
+      continue;
+    }
+
+    msg += ProcessSingleOptionLocked(flag, envval.c_str(), set_mode);
+  }
+  return msg;
+}
+
+string CommandLineFlagParser::ProcessSingleOptionLocked(
+    CommandLineFlag* flag, const char* value, FlagSettingMode set_mode) {
+  string msg;
+  if (value && !registry_->SetFlagLocked(flag, value, set_mode, &msg)) {
+    error_flags_[flag->name()] = msg;
+    return "";
+  }
+
+  // The recursive flags, --flagfile and --fromenv and --tryfromenv,
+  // must be dealt with as soon as they're seen.  They will emit
+  // messages of their own.
+  if (strcmp(flag->name(), "flagfile") == 0) {
+    msg += ProcessFlagfileLocked(FLAGS_flagfile, set_mode);
+
+  } else if (strcmp(flag->name(), "fromenv") == 0) {
+    // last arg indicates envval-not-found is fatal (unlike in --tryfromenv)
+    msg += ProcessFromenvLocked(FLAGS_fromenv, set_mode, true);
+
+  } else if (strcmp(flag->name(), "tryfromenv") == 0) {
+    msg += ProcessFromenvLocked(FLAGS_tryfromenv, set_mode, false);
+  }
+
+  return msg;
+}
+
+void CommandLineFlagParser::ValidateAllFlags() {
+  FlagRegistryLock frl(registry_);
+  for (FlagRegistry::FlagConstIterator i = registry_->flags_.begin();
+       i != registry_->flags_.end(); ++i) {
+    if (!i->second->ValidateCurrent()) {
+      // only set a message if one isn't already there.  (If there's
+      // an error message, our job is done, even if it's not exactly
+      // the same error.)
+      if (error_flags_[i->second->name()].empty())
+        error_flags_[i->second->name()] =
+            string(kError) + "--" + i->second->name() +
+            " must be set on the commandline"
+            " (default value fails validation)\n";
+    }
+  }
+}
+
+bool CommandLineFlagParser::ReportErrors() {
+  // error_flags_ indicates errors we saw while parsing.
+  // But we ignore undefined-names if ok'ed by --undef_ok
+  if (!FLAGS_undefok.empty()) {
+    vector<string> flaglist;
+    ParseFlagList(FLAGS_undefok.c_str(), &flaglist);
+    for (size_t i = 0; i < flaglist.size(); ++i) {
+      // We also deal with --no<flag>, in case the flagname was boolean
+      const string no_version = string("no") + flaglist[i];
+      if (undefined_names_.find(flaglist[i]) != undefined_names_.end()) {
+        error_flags_[flaglist[i]] = "";    // clear the error message
+      } else if (undefined_names_.find(no_version) != undefined_names_.end()) {
+        error_flags_[no_version] = "";
+      }
+    }
+  }
+  // Likewise, if they decided to allow reparsing, all undefined-names
+  // are ok; we just silently ignore them now, and hope that a future
+  // parse will pick them up somehow.
+  if (allow_command_line_reparsing) {
+    for (map<string, string>::const_iterator it = undefined_names_.begin();
+         it != undefined_names_.end();  ++it)
+      error_flags_[it->first] = "";      // clear the error message
+  }
+
+  bool found_error = false;
+  string error_message;
+  for (map<string, string>::const_iterator it = error_flags_.begin();
+       it != error_flags_.end(); ++it) {
+    if (!it->second.empty()) {
+      error_message.append(it->second.data(), it->second.size());
+      found_error = true;
+    }
+  }
+  if (found_error)
+    ReportError(DO_NOT_DIE, "%s", error_message.c_str());
+  return found_error;
+}
+
+string CommandLineFlagParser::ProcessOptionsFromStringLocked(
+    const string& contentdata, FlagSettingMode set_mode) {
+  string retval;
+  const char* flagfile_contents = contentdata.c_str();
+  bool flags_are_relevant = true;   // set to false when filenames don't match
+  bool in_filename_section = false;
+
+  const char* line_end = flagfile_contents;
+  // We read this file a line at a time.
+  for (; line_end; flagfile_contents = line_end + 1) {
+    while (*flagfile_contents && isspace(*flagfile_contents))
+      ++flagfile_contents;
+    line_end = strchr(flagfile_contents, '\n');
+    size_t len = line_end ? line_end - flagfile_contents
+                          : strlen(flagfile_contents);
+    string line(flagfile_contents, len);
+
+    // Each line can be one of four things:
+    // 1) A comment line -- we skip it
+    // 2) An empty line -- we skip it
+    // 3) A list of filenames -- starts a new filenames+flags section
+    // 4) A --flag=value line -- apply if previous filenames match
+    if (line.empty() || line[0] == '#') {
+      // comment or empty line; just ignore
+
+    } else if (line[0] == '-') {    // flag
+      in_filename_section = false;  // instead, it was a flag-line
+      if (!flags_are_relevant)      // skip this flag; applies to someone else
+        continue;
+
+      const char* name_and_val = line.c_str() + 1;    // skip the leading -
+      if (*name_and_val == '-')
+        name_and_val++;                               // skip second - too
+      string key;
+      const char* value;
+      string error_message;
+      CommandLineFlag* flag = registry_->SplitArgumentLocked(name_and_val,
+                                                             &key, &value,
+                                                             &error_message);
+      // By API, errors parsing flagfile lines are silently ignored.
+      if (flag == NULL) {
+        // "WARNING: flagname '" + key + "' not found\n"
+      } else if (value == NULL) {
+        // "WARNING: flagname '" + key + "' missing a value\n"
+      } else {
+        retval += ProcessSingleOptionLocked(flag, value, set_mode);
+      }
+
+    } else {                        // a filename!
+      if (!in_filename_section) {   // start over: assume filenames don't match
+        in_filename_section = true;
+        flags_are_relevant = false;
+      }
+
+      // Split the line up at spaces into glob-patterns
+      const char* space = line.c_str();   // just has to be non-NULL
+      for (const char* word = line.c_str(); *space; word = space+1) {
+        if (flags_are_relevant)     // we can stop as soon as we match
+          break;
+        space = strchr(word, ' ');
+        if (space == NULL)
+          space = word + strlen(word);
+        const string glob(word, space - word);
+        // We try matching both against the full argv0 and basename(argv0)
+        if (glob == ProgramInvocationName()       // small optimization
+            || glob == ProgramInvocationShortName()
+#if defined(HAVE_FNMATCH_H)
+            || fnmatch(glob.c_str(), ProgramInvocationName(),      FNM_PATHNAME) == 0
+            || fnmatch(glob.c_str(), ProgramInvocationShortName(), FNM_PATHNAME) == 0
+#elif defined(HAVE_SHLWAPI_H)
+            || PathMatchSpec(glob.c_str(), ProgramInvocationName())
+            || PathMatchSpec(glob.c_str(), ProgramInvocationShortName())
+#endif
+            ) {
+          flags_are_relevant = true;
+        }
+      }
+    }
+  }
+  return retval;
+}
+
+// --------------------------------------------------------------------
+// GetFromEnv()
+// AddFlagValidator()
+//    These are helper functions for routines like BoolFromEnv() and
+//    RegisterFlagValidator, defined below.  They're defined here so
+//    they can live in the unnamed namespace (which makes friendship
+//    declarations for these classes possible).
+// --------------------------------------------------------------------
+
+template<typename T>
+T GetFromEnv(const char *varname, const char* type, T dflt) {
+  std::string valstr;
+  if (SafeGetEnv(varname, valstr)) {
+    FlagValue ifv(new T, type, true);
+    if (!ifv.ParseFrom(valstr.c_str())) {
+      ReportError(DIE, "ERROR: error parsing env variable '%s' with value '%s'\n",
+                  varname, valstr.c_str());
+	}
+    return OTHER_VALUE_AS(ifv, T);
+  } else return dflt;
+}
+
+bool AddFlagValidator(const void* flag_ptr, ValidateFnProto validate_fn_proto) {
+  // We want a lock around this routine, in case two threads try to
+  // add a validator (hopefully the same one!) at once.  We could use
+  // our own thread, but we need to loook at the registry anyway, so
+  // we just steal that one.
+  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
+  FlagRegistryLock frl(registry);
+  // First, find the flag whose current-flag storage is 'flag'.
+  // This is the CommandLineFlag whose current_->value_buffer_ == flag
+  CommandLineFlag* flag = registry->FindFlagViaPtrLocked(flag_ptr);
+  if (!flag) {
+    LOG(WARNING) << "Ignoring RegisterValidateFunction() for flag pointer "
+                 << flag_ptr << ": no flag found at that address";
+    return false;
+  } else if (validate_fn_proto == flag->validate_function()) {
+    return true;    // ok to register the same function over and over again
+  } else if (validate_fn_proto != NULL && flag->validate_function() != NULL) {
+    LOG(WARNING) << "Ignoring RegisterValidateFunction() for flag '"
+                 << flag->name() << "': validate-fn already registered";
+    return false;
+  } else {
+    flag->validate_fn_proto_ = validate_fn_proto;
+    return true;
+  }
+}
+
+}  // end unnamed namespaces
+
+
+// Now define the functions that are exported via the .h file
+
+// --------------------------------------------------------------------
+// FlagRegisterer
+//    This class exists merely to have a global constructor (the
+//    kind that runs before main(), that goes an initializes each
+//    flag that's been declared.  Note that it's very important we
+//    don't have a destructor that deletes flag_, because that would
+//    cause us to delete current_storage/defvalue_storage as well,
+//    which can cause a crash if anything tries to access the flag
+//    values in a global destructor.
+// --------------------------------------------------------------------
+
+FlagRegisterer::FlagRegisterer(const char* name, const char* type,
+                               const char* help, const char* filename,
+                               void* current_storage, void* defvalue_storage) {
+  if (help == NULL)
+    help = "";
+  // FlagValue expects the type-name to not include any namespace
+  // components, so we get rid of those, if any.
+  if (strchr(type, ':'))
+    type = strrchr(type, ':') + 1;
+  FlagValue* current = new FlagValue(current_storage, type, false);
+  FlagValue* defvalue = new FlagValue(defvalue_storage, type, false);
+  // Importantly, flag_ will never be deleted, so storage is always good.
+  CommandLineFlag* flag = new CommandLineFlag(name, help, filename,
+                                              current, defvalue);
+  FlagRegistry::GlobalRegistry()->RegisterFlag(flag);   // default registry
+}
+
+// --------------------------------------------------------------------
+// GetAllFlags()
+//    The main way the FlagRegistry class exposes its data.  This
+//    returns, as strings, all the info about all the flags in
+//    the main registry, sorted first by filename they are defined
+//    in, and then by flagname.
+// --------------------------------------------------------------------
+
+struct FilenameFlagnameCmp {
+  bool operator()(const CommandLineFlagInfo& a,
+                  const CommandLineFlagInfo& b) const {
+    int cmp = strcmp(a.filename.c_str(), b.filename.c_str());
+    if (cmp == 0)
+      cmp = strcmp(a.name.c_str(), b.name.c_str());  // secondary sort key
+    return cmp < 0;
+  }
+};
+
+void GetAllFlags(vector<CommandLineFlagInfo>* OUTPUT) {
+  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
+  registry->Lock();
+  for (FlagRegistry::FlagConstIterator i = registry->flags_.begin();
+       i != registry->flags_.end(); ++i) {
+    CommandLineFlagInfo fi;
+    i->second->FillCommandLineFlagInfo(&fi);
+    OUTPUT->push_back(fi);
+  }
+  registry->Unlock();
+  // Now sort the flags, first by filename they occur in, then alphabetically
+  sort(OUTPUT->begin(), OUTPUT->end(), FilenameFlagnameCmp());
+}
+
+// --------------------------------------------------------------------
+// SetArgv()
+// GetArgvs()
+// GetArgv()
+// GetArgv0()
+// ProgramInvocationName()
+// ProgramInvocationShortName()
+// SetUsageMessage()
+// ProgramUsage()
+//    Functions to set and get argv.  Typically the setter is called
+//    by ParseCommandLineFlags.  Also can get the ProgramUsage string,
+//    set by SetUsageMessage.
+// --------------------------------------------------------------------
+
+// These values are not protected by a Mutex because they are normally
+// set only once during program startup.
+static const char* argv0 = "UNKNOWN";      // just the program name
+static const char* cmdline = "";           // the entire command-line
+static vector<string> argvs;
+static uint32 argv_sum = 0;
+static const char* program_usage = NULL;
+
+void SetArgv(int argc, const char** argv) {
+  static bool called_set_argv = false;
+  if (called_set_argv)         // we already have an argv for you
+    return;
+
+  called_set_argv = true;
+
+  assert(argc > 0);            // every program has at least a progname
+  argv0 = strdup(argv[0]);     // small memory leak, but fn only called once
+  assert(argv0);
+
+  string cmdline_string;       // easier than doing strcats
+  for (int i = 0; i < argc; i++) {
+    if (i != 0) {
+      cmdline_string += " ";
+    }
+    cmdline_string += argv[i];
+    argvs.push_back(argv[i]);
+  }
+  cmdline = strdup(cmdline_string.c_str());  // another small memory leak
+  assert(cmdline);
+
+  // Compute a simple sum of all the chars in argv
+  for (const char* c = cmdline; *c; c++)
+    argv_sum += *c;
+}
+
+const vector<string>& GetArgvs() { return argvs; }
+const char* GetArgv()            { return cmdline; }
+const char* GetArgv0()           { return argv0; }
+uint32 GetArgvSum()              { return argv_sum; }
+const char* ProgramInvocationName() {             // like the GNU libc fn
+  return GetArgv0();
+}
+const char* ProgramInvocationShortName() {        // like the GNU libc fn
+  const char* slash = strrchr(argv0, '/');
+#ifdef OS_WINDOWS
+  if (!slash)  slash = strrchr(argv0, '\\');
+#endif
+  return slash ? slash + 1 : argv0;
+}
+
+void SetUsageMessage(const string& usage) {
+  if (program_usage != NULL)
+    ReportError(DIE, "ERROR: SetUsageMessage() called twice\n");
+  program_usage = strdup(usage.c_str());      // small memory leak
+}
+
+const char* ProgramUsage() {
+  if (program_usage) {
+    return program_usage;
+  }
+  return "Warning: SetUsageMessage() never called";
+}
+
+// --------------------------------------------------------------------
+// SetVersionString()
+// VersionString()
+// --------------------------------------------------------------------
+
+static const char* version_string = NULL;
+
+void SetVersionString(const string& version) {
+  if (version_string != NULL)
+    ReportError(DIE, "ERROR: SetVersionString() called twice\n");
+  version_string = strdup(version.c_str());   // small memory leak
+}
+
+const char* VersionString() {
+  return version_string ? version_string : "";
+}
+
+
+// --------------------------------------------------------------------
+// GetCommandLineOption()
+// GetCommandLineFlagInfo()
+// GetCommandLineFlagInfoOrDie()
+// SetCommandLineOption()
+// SetCommandLineOptionWithMode()
+//    The programmatic way to set a flag's value, using a string
+//    for its name rather than the variable itself (that is,
+//    SetCommandLineOption("foo", x) rather than FLAGS_foo = x).
+//    There's also a bit more flexibility here due to the various
+//    set-modes, but typically these are used when you only have
+//    that flag's name as a string, perhaps at runtime.
+//    All of these work on the default, global registry.
+//       For GetCommandLineOption, return false if no such flag
+//    is known, true otherwise.  We clear "value" if a suitable
+//    flag is found.
+// --------------------------------------------------------------------
+
+
+bool GetCommandLineOption(const char* name, string* value) {
+  if (NULL == name)
+    return false;
+  assert(value);
+
+  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
+  FlagRegistryLock frl(registry);
+  CommandLineFlag* flag = registry->FindFlagLocked(name);
+  if (flag == NULL) {
+    return false;
+  } else {
+    *value = flag->current_value();
+    return true;
+  }
+}
+
+bool GetCommandLineFlagInfo(const char* name, CommandLineFlagInfo* OUTPUT) {
+  if (NULL == name) return false;
+  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
+  FlagRegistryLock frl(registry);
+  CommandLineFlag* flag = registry->FindFlagLocked(name);
+  if (flag == NULL) {
+    return false;
+  } else {
+    assert(OUTPUT);
+    flag->FillCommandLineFlagInfo(OUTPUT);
+    return true;
+  }
+}
+
+CommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name) {
+  CommandLineFlagInfo info;
+  if (!GetCommandLineFlagInfo(name, &info)) {
+    fprintf(stderr, "FATAL ERROR: flag name '%s' doesn't exist\n", name);
+    gflags_exitfunc(1);    // almost certainly gflags_exitfunc()
+  }
+  return info;
+}
+
+string SetCommandLineOptionWithMode(const char* name, const char* value,
+                                    FlagSettingMode set_mode) {
+  string result;
+  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
+  FlagRegistryLock frl(registry);
+  CommandLineFlag* flag = registry->FindFlagLocked(name);
+  if (flag) {
+    CommandLineFlagParser parser(registry);
+    result = parser.ProcessSingleOptionLocked(flag, value, set_mode);
+    if (!result.empty()) {   // in the error case, we've already logged
+      // Could consider logging this change
+    }
+  }
+  // The API of this function is that we return empty string on error
+  return result;
+}
+
+string SetCommandLineOption(const char* name, const char* value) {
+  return SetCommandLineOptionWithMode(name, value, SET_FLAGS_VALUE);
+}
+
+// --------------------------------------------------------------------
+// FlagSaver
+// FlagSaverImpl
+//    This class stores the states of all flags at construct time,
+//    and restores all flags to that state at destruct time.
+//    Its major implementation challenge is that it never modifies
+//    pointers in the 'main' registry, so global FLAG_* vars always
+//    point to the right place.
+// --------------------------------------------------------------------
+
+class FlagSaverImpl {
+ public:
+  // Constructs an empty FlagSaverImpl object.
+  explicit FlagSaverImpl(FlagRegistry* main_registry)
+      : main_registry_(main_registry) { }
+  ~FlagSaverImpl() {
+    // reclaim memory from each of our CommandLineFlags
+    vector<CommandLineFlag*>::const_iterator it;
+    for (it = backup_registry_.begin(); it != backup_registry_.end(); ++it)
+      delete *it;
+  }
+
+  // Saves the flag states from the flag registry into this object.
+  // It's an error to call this more than once.
+  // Must be called when the registry mutex is not held.
+  void SaveFromRegistry() {
+    FlagRegistryLock frl(main_registry_);
+    assert(backup_registry_.empty());   // call only once!
+    for (FlagRegistry::FlagConstIterator it = main_registry_->flags_.begin();
+         it != main_registry_->flags_.end();
+         ++it) {
+      const CommandLineFlag* main = it->second;
+      // Sets up all the const variables in backup correctly
+      CommandLineFlag* backup = new CommandLineFlag(
+          main->name(), main->help(), main->filename(),
+          main->current_->New(), main->defvalue_->New());
+      // Sets up all the non-const variables in backup correctly
+      backup->CopyFrom(*main);
+      backup_registry_.push_back(backup);   // add it to a convenient list
+    }
+  }
+
+  // Restores the saved flag states into the flag registry.  We
+  // assume no flags were added or deleted from the registry since
+  // the SaveFromRegistry; if they were, that's trouble!  Must be
+  // called when the registry mutex is not held.
+  void RestoreToRegistry() {
+    FlagRegistryLock frl(main_registry_);
+    vector<CommandLineFlag*>::const_iterator it;
+    for (it = backup_registry_.begin(); it != backup_registry_.end(); ++it) {
+      CommandLineFlag* main = main_registry_->FindFlagLocked((*it)->name());
+      if (main != NULL) {       // if NULL, flag got deleted from registry(!)
+        main->CopyFrom(**it);
+      }
+    }
+  }
+
+ private:
+  FlagRegistry* const main_registry_;
+  vector<CommandLineFlag*> backup_registry_;
+
+  FlagSaverImpl(const FlagSaverImpl&);  // no copying!
+  void operator=(const FlagSaverImpl&);
+};
+
+FlagSaver::FlagSaver()
+    : impl_(new FlagSaverImpl(FlagRegistry::GlobalRegistry())) {
+  impl_->SaveFromRegistry();
+}
+
+FlagSaver::~FlagSaver() {
+  impl_->RestoreToRegistry();
+  delete impl_;
+}
+
+
+// --------------------------------------------------------------------
+// CommandlineFlagsIntoString()
+// ReadFlagsFromString()
+// AppendFlagsIntoFile()
+// ReadFromFlagsFile()
+//    These are mostly-deprecated routines that stick the
+//    commandline flags into a file/string and read them back
+//    out again.  I can see a use for CommandlineFlagsIntoString,
+//    for creating a flagfile, but the rest don't seem that useful
+//    -- some, I think, are a poor-man's attempt at FlagSaver --
+//    and are included only until we can delete them from callers.
+//    Note they don't save --flagfile flags (though they do save
+//    the result of having called the flagfile, of course).
+// --------------------------------------------------------------------
+
+static string TheseCommandlineFlagsIntoString(
+    const vector<CommandLineFlagInfo>& flags) {
+  vector<CommandLineFlagInfo>::const_iterator i;
+
+  size_t retval_space = 0;
+  for (i = flags.begin(); i != flags.end(); ++i) {
+    // An (over)estimate of how much space it will take to print this flag
+    retval_space += i->name.length() + i->current_value.length() + 5;
+  }
+
+  string retval;
+  retval.reserve(retval_space);
+  for (i = flags.begin(); i != flags.end(); ++i) {
+    retval += "--";
+    retval += i->name;
+    retval += "=";
+    retval += i->current_value;
+    retval += "\n";
+  }
+  return retval;
+}
+
+string CommandlineFlagsIntoString() {
+  vector<CommandLineFlagInfo> sorted_flags;
+  GetAllFlags(&sorted_flags);
+  return TheseCommandlineFlagsIntoString(sorted_flags);
+}
+
+bool ReadFlagsFromString(const string& flagfilecontents,
+                         const char* /*prog_name*/,  // TODO(csilvers): nix this
+                         bool errors_are_fatal) {
+  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
+  FlagSaverImpl saved_states(registry);
+  saved_states.SaveFromRegistry();
+
+  CommandLineFlagParser parser(registry);
+  registry->Lock();
+  parser.ProcessOptionsFromStringLocked(flagfilecontents, SET_FLAGS_VALUE);
+  registry->Unlock();
+  // Should we handle --help and such when reading flags from a string?  Sure.
+  HandleCommandLineHelpFlags();
+  if (parser.ReportErrors()) {
+    // Error.  Restore all global flags to their previous values.
+    if (errors_are_fatal)
+      gflags_exitfunc(1);
+    saved_states.RestoreToRegistry();
+    return false;
+  }
+  return true;
+}
+
+// TODO(csilvers): nix prog_name in favor of ProgramInvocationShortName()
+bool AppendFlagsIntoFile(const string& filename, const char *prog_name) {
+  FILE *fp;
+  if (SafeFOpen(&fp, filename.c_str(), "a") != 0) {
+    return false;
+  }
+
+  if (prog_name)
+    fprintf(fp, "%s\n", prog_name);
+
+  vector<CommandLineFlagInfo> flags;
+  GetAllFlags(&flags);
+  // But we don't want --flagfile, which leads to weird recursion issues
+  vector<CommandLineFlagInfo>::iterator i;
+  for (i = flags.begin(); i != flags.end(); ++i) {
+    if (strcmp(i->name.c_str(), "flagfile") == 0) {
+      flags.erase(i);
+      break;
+    }
+  }
+  fprintf(fp, "%s", TheseCommandlineFlagsIntoString(flags).c_str());
+
+  fclose(fp);
+  return true;
+}
+
+bool ReadFromFlagsFile(const string& filename, const char* prog_name,
+                       bool errors_are_fatal) {
+  return ReadFlagsFromString(ReadFileIntoString(filename.c_str()),
+                             prog_name, errors_are_fatal);
+}
+
+
+// --------------------------------------------------------------------
+// BoolFromEnv()
+// Int32FromEnv()
+// Int64FromEnv()
+// Uint64FromEnv()
+// DoubleFromEnv()
+// StringFromEnv()
+//    Reads the value from the environment and returns it.
+//    We use an FlagValue to make the parsing easy.
+//    Example usage:
+//       DEFINE_bool(myflag, BoolFromEnv("MYFLAG_DEFAULT", false), "whatever");
+// --------------------------------------------------------------------
+
+bool BoolFromEnv(const char *v, bool dflt) {
+  return GetFromEnv(v, "bool", dflt);
+}
+int32 Int32FromEnv(const char *v, int32 dflt) {
+  return GetFromEnv(v, "int32", dflt);
+}
+int64 Int64FromEnv(const char *v, int64 dflt)    {
+  return GetFromEnv(v, "int64", dflt);
+}
+uint64 Uint64FromEnv(const char *v, uint64 dflt) {
+  return GetFromEnv(v, "uint64", dflt);
+}
+double DoubleFromEnv(const char *v, double dflt) {
+  return GetFromEnv(v, "double", dflt);
+}
+
+#ifdef _MSC_VER
+#  pragma warning(push)
+#  pragma warning(disable: 4996) // ignore getenv security warning
+#endif
+const char *StringFromEnv(const char *varname, const char *dflt) {
+  const char* const val = getenv(varname);
+  return val ? val : dflt;
+}
+#ifdef _MSC_VER
+#  pragma warning(pop)
+#endif
+
+
+// --------------------------------------------------------------------
+// RegisterFlagValidator()
+//    RegisterFlagValidator() is the function that clients use to
+//    'decorate' a flag with a validation function.  Once this is
+//    done, every time the flag is set (including when the flag
+//    is parsed from argv), the validator-function is called.
+//       These functions return true if the validator was added
+//    successfully, or false if not: the flag already has a validator,
+//    (only one allowed per flag), the 1st arg isn't a flag, etc.
+//       This function is not thread-safe.
+// --------------------------------------------------------------------
+
+bool RegisterFlagValidator(const bool* flag,
+                           bool (*validate_fn)(const char*, bool)) {
+  return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn));
+}
+bool RegisterFlagValidator(const int32* flag,
+                           bool (*validate_fn)(const char*, int32)) {
+  return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn));
+}
+bool RegisterFlagValidator(const int64* flag,
+                           bool (*validate_fn)(const char*, int64)) {
+  return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn));
+}
+bool RegisterFlagValidator(const uint64* flag,
+                           bool (*validate_fn)(const char*, uint64)) {
+  return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn));
+}
+bool RegisterFlagValidator(const double* flag,
+                           bool (*validate_fn)(const char*, double)) {
+  return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn));
+}
+bool RegisterFlagValidator(const string* flag,
+                           bool (*validate_fn)(const char*, const string&)) {
+  return AddFlagValidator(flag, reinterpret_cast<ValidateFnProto>(validate_fn));
+}
+
+
+// --------------------------------------------------------------------
+// ParseCommandLineFlags()
+// ParseCommandLineNonHelpFlags()
+// HandleCommandLineHelpFlags()
+//    This is the main function called from main(), to actually
+//    parse the commandline.  It modifies argc and argv as described
+//    at the top of gflags.h.  You can also divide this
+//    function into two parts, if you want to do work between
+//    the parsing of the flags and the printing of any help output.
+// --------------------------------------------------------------------
+
+static uint32 ParseCommandLineFlagsInternal(int* argc, char*** argv,
+                                            bool remove_flags, bool do_report) {
+  SetArgv(*argc, const_cast<const char**>(*argv));    // save it for later
+
+  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
+  CommandLineFlagParser parser(registry);
+
+  // When we parse the commandline flags, we'll handle --flagfile,
+  // --tryfromenv, etc. as we see them (since flag-evaluation order
+  // may be important).  But sometimes apps set FLAGS_tryfromenv/etc.
+  // manually before calling ParseCommandLineFlags.  We want to evaluate
+  // those too, as if they were the first flags on the commandline.
+  registry->Lock();
+  parser.ProcessFlagfileLocked(FLAGS_flagfile, SET_FLAGS_VALUE);
+  // Last arg here indicates whether flag-not-found is a fatal error or not
+  parser.ProcessFromenvLocked(FLAGS_fromenv, SET_FLAGS_VALUE, true);
+  parser.ProcessFromenvLocked(FLAGS_tryfromenv, SET_FLAGS_VALUE, false);
+  registry->Unlock();
+
+  // Now get the flags specified on the commandline
+  const int r = parser.ParseNewCommandLineFlags(argc, argv, remove_flags);
+
+  if (do_report)
+    HandleCommandLineHelpFlags();   // may cause us to exit on --help, etc.
+
+  // See if any of the unset flags fail their validation checks
+  parser.ValidateAllFlags();
+
+  if (parser.ReportErrors())        // may cause us to exit on illegal flags
+    gflags_exitfunc(1);
+  return r;
+}
+
+uint32 ParseCommandLineFlags(int* argc, char*** argv, bool remove_flags) {
+  return ParseCommandLineFlagsInternal(argc, argv, remove_flags, true);
+}
+
+uint32 ParseCommandLineNonHelpFlags(int* argc, char*** argv,
+                                    bool remove_flags) {
+  return ParseCommandLineFlagsInternal(argc, argv, remove_flags, false);
+}
+
+// --------------------------------------------------------------------
+// AllowCommandLineReparsing()
+// ReparseCommandLineNonHelpFlags()
+//    This is most useful for shared libraries.  The idea is if
+//    a flag is defined in a shared library that is dlopen'ed
+//    sometime after main(), you can ParseCommandLineFlags before
+//    the dlopen, then ReparseCommandLineNonHelpFlags() after the
+//    dlopen, to get the new flags.  But you have to explicitly
+//    Allow() it; otherwise, you get the normal default behavior
+//    of unrecognized flags calling a fatal error.
+// TODO(csilvers): this isn't used.  Just delete it?
+// --------------------------------------------------------------------
+
+void AllowCommandLineReparsing() {
+  allow_command_line_reparsing = true;
+}
+
+void ReparseCommandLineNonHelpFlags() {
+  // We make a copy of argc and argv to pass in
+  const vector<string>& argvs = GetArgvs();
+  int tmp_argc = static_cast<int>(argvs.size());
+  char** tmp_argv = new char* [tmp_argc + 1];
+  for (int i = 0; i < tmp_argc; ++i)
+    tmp_argv[i] = strdup(argvs[i].c_str());   // TODO(csilvers): don't dup
+
+  ParseCommandLineNonHelpFlags(&tmp_argc, &tmp_argv, false);
+
+  for (int i = 0; i < tmp_argc; ++i)
+    free(tmp_argv[i]);
+  delete[] tmp_argv;
+}
+
+void ShutDownCommandLineFlags() {
+  FlagRegistry::DeleteGlobalRegistry();
+}
+
+
+} // namespace GFLAGS_NAMESPACE
diff --git a/third_party/gflags/src/gflags.h.in b/third_party/gflags/src/gflags.h.in
new file mode 100644
index 0000000..0324d39
--- /dev/null
+++ b/third_party/gflags/src/gflags.h.in
@@ -0,0 +1,572 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ---
+// Revamped and reorganized by Craig Silverstein
+//
+// This is the file that should be included by any file which declares
+// or defines a command line flag or wants to parse command line flags
+// or print a program usage message (which will include information about
+// flags).  Executive summary, in the form of an example foo.cc file:
+//
+//    #include "foo.h"         // foo.h has a line "DECLARE_int32(start);"
+//    #include "validators.h"  // hypothetical file defining ValidateIsFile()
+//
+//    DEFINE_int32(end, 1000, "The last record to read");
+//
+//    DEFINE_string(filename, "my_file.txt", "The file to read");
+//    // Crash if the specified file does not exist.
+//    static bool dummy = RegisterFlagValidator(&FLAGS_filename,
+//                                              &ValidateIsFile);
+//
+//    DECLARE_bool(verbose); // some other file has a DEFINE_bool(verbose, ...)
+//
+//    void MyFunc() {
+//      if (FLAGS_verbose) printf("Records %d-%d\n", FLAGS_start, FLAGS_end);
+//    }
+//
+//    Then, at the command-line:
+//       ./foo --noverbose --start=5 --end=100
+//
+// For more details, see
+//    doc/gflags.html
+//
+// --- A note about thread-safety:
+//
+// We describe many functions in this routine as being thread-hostile,
+// thread-compatible, or thread-safe.  Here are the meanings we use:
+//
+// thread-safe: it is safe for multiple threads to call this routine
+//   (or, when referring to a class, methods of this class)
+//   concurrently.
+// thread-hostile: it is not safe for multiple threads to call this
+//   routine (or methods of this class) concurrently.  In gflags,
+//   most thread-hostile routines are intended to be called early in,
+//   or even before, main() -- that is, before threads are spawned.
+// thread-compatible: it is safe for multiple threads to read from
+//   this variable (when applied to variables), or to call const
+//   methods of this class (when applied to classes), as long as no
+//   other thread is writing to the variable or calling non-const
+//   methods of this class.
+
+#ifndef GFLAGS_GFLAGS_H_
+#define GFLAGS_GFLAGS_H_
+
+#include <string>
+#include <vector>
+
+#include "gflags_declare.h" // IWYU pragma: export
+
+
+// We always want to export variables defined in user code
+#ifndef GFLAGS_DLL_DEFINE_FLAG
+#  ifdef _MSC_VER
+#    define GFLAGS_DLL_DEFINE_FLAG __declspec(dllexport)
+#  else
+#    define GFLAGS_DLL_DEFINE_FLAG
+#  endif
+#endif
+
+
+namespace GFLAGS_NAMESPACE {
+
+
+// --------------------------------------------------------------------
+// To actually define a flag in a file, use DEFINE_bool,
+// DEFINE_string, etc. at the bottom of this file.  You may also find
+// it useful to register a validator with the flag.  This ensures that
+// when the flag is parsed from the commandline, or is later set via
+// SetCommandLineOption, we call the validation function. It is _not_
+// called when you assign the value to the flag directly using the = operator.
+//
+// The validation function should return true if the flag value is valid, and
+// false otherwise. If the function returns false for the new setting of the
+// flag, the flag will retain its current value. If it returns false for the
+// default value, ParseCommandLineFlags() will die.
+//
+// This function is safe to call at global construct time (as in the
+// example below).
+//
+// Example use:
+//    static bool ValidatePort(const char* flagname, int32 value) {
+//       if (value > 0 && value < 32768)   // value is ok
+//         return true;
+//       printf("Invalid value for --%s: %d\n", flagname, (int)value);
+//       return false;
+//    }
+//    DEFINE_int32(port, 0, "What port to listen on");
+//    static bool dummy = RegisterFlagValidator(&FLAGS_port, &ValidatePort);
+
+// Returns true if successfully registered, false if not (because the
+// first argument doesn't point to a command-line flag, or because a
+// validator is already registered for this flag).
+extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const bool*        flag, bool (*validate_fn)(const char*, bool));
+extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const int32*       flag, bool (*validate_fn)(const char*, int32));
+extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const int64*       flag, bool (*validate_fn)(const char*, int64));
+extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const uint64*      flag, bool (*validate_fn)(const char*, uint64));
+extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const double*      flag, bool (*validate_fn)(const char*, double));
+extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const std::string* flag, bool (*validate_fn)(const char*, const std::string&));
+
+// Convenience macro for the registration of a flag validator
+#define DEFINE_validator(name, validator) \
+    static const bool name##_validator_registered = \
+            GFLAGS_NAMESPACE::RegisterFlagValidator(&FLAGS_##name, validator)
+
+
+// --------------------------------------------------------------------
+// These methods are the best way to get access to info about the
+// list of commandline flags.  Note that these routines are pretty slow.
+//   GetAllFlags: mostly-complete info about the list, sorted by file.
+//   ShowUsageWithFlags: pretty-prints the list to stdout (what --help does)
+//   ShowUsageWithFlagsRestrict: limit to filenames with restrict as a substr
+//
+// In addition to accessing flags, you can also access argv[0] (the program
+// name) and argv (the entire commandline), which we sock away a copy of.
+// These variables are static, so you should only set them once.
+//
+// No need to export this data only structure from DLL, avoiding VS warning 4251.
+struct CommandLineFlagInfo {
+  std::string name;            // the name of the flag
+  std::string type;            // the type of the flag: int32, etc
+  std::string description;     // the "help text" associated with the flag
+  std::string current_value;   // the current value, as a string
+  std::string default_value;   // the default value, as a string
+  std::string filename;        // 'cleaned' version of filename holding the flag
+  bool has_validator_fn;       // true if RegisterFlagValidator called on this flag
+  bool is_default;             // true if the flag has the default value and
+                               // has not been set explicitly from the cmdline
+                               // or via SetCommandLineOption
+  const void* flag_ptr;        // pointer to the flag's current value (i.e. FLAGS_foo)
+};
+
+// Using this inside of a validator is a recipe for a deadlock.
+// TODO(user) Fix locking when validators are running, to make it safe to
+// call validators during ParseAllFlags.
+// Also make sure then to uncomment the corresponding unit test in
+// gflags_unittest.sh
+extern GFLAGS_DLL_DECL void GetAllFlags(std::vector<CommandLineFlagInfo>* OUTPUT);
+// These two are actually defined in gflags_reporting.cc.
+extern GFLAGS_DLL_DECL void ShowUsageWithFlags(const char *argv0);  // what --help does
+extern GFLAGS_DLL_DECL void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict);
+
+// Create a descriptive string for a flag.
+// Goes to some trouble to make pretty line breaks.
+extern GFLAGS_DLL_DECL std::string DescribeOneFlag(const CommandLineFlagInfo& flag);
+
+// Thread-hostile; meant to be called before any threads are spawned.
+extern GFLAGS_DLL_DECL void SetArgv(int argc, const char** argv);
+
+// The following functions are thread-safe as long as SetArgv() is
+// only called before any threads start.
+extern GFLAGS_DLL_DECL const std::vector<std::string>& GetArgvs();
+extern GFLAGS_DLL_DECL const char* GetArgv();                      // all of argv as a string
+extern GFLAGS_DLL_DECL const char* GetArgv0();                     // only argv0
+extern GFLAGS_DLL_DECL uint32 GetArgvSum();                        // simple checksum of argv
+extern GFLAGS_DLL_DECL const char* ProgramInvocationName();        // argv0, or "UNKNOWN" if not set
+extern GFLAGS_DLL_DECL const char* ProgramInvocationShortName();   // basename(argv0)
+
+// ProgramUsage() is thread-safe as long as SetUsageMessage() is only
+// called before any threads start.
+extern GFLAGS_DLL_DECL const char* ProgramUsage();                 // string set by SetUsageMessage()
+
+// VersionString() is thread-safe as long as SetVersionString() is only
+// called before any threads start.
+extern GFLAGS_DLL_DECL const char* VersionString();                // string set by SetVersionString()
+
+
+
+// --------------------------------------------------------------------
+// Normally you access commandline flags by just saying "if (FLAGS_foo)"
+// or whatever, and set them by calling "FLAGS_foo = bar" (or, more
+// commonly, via the DEFINE_foo macro).  But if you need a bit more
+// control, we have programmatic ways to get/set the flags as well.
+// These programmatic ways to access flags are thread-safe, but direct
+// access is only thread-compatible.
+
+// Return true iff the flagname was found.
+// OUTPUT is set to the flag's value, or unchanged if we return false.
+extern GFLAGS_DLL_DECL bool GetCommandLineOption(const char* name, std::string* OUTPUT);
+
+// Return true iff the flagname was found. OUTPUT is set to the flag's
+// CommandLineFlagInfo or unchanged if we return false.
+extern GFLAGS_DLL_DECL bool GetCommandLineFlagInfo(const char* name, CommandLineFlagInfo* OUTPUT);
+
+// Return the CommandLineFlagInfo of the flagname.  exit() if name not found.
+// Example usage, to check if a flag's value is currently the default value:
+//   if (GetCommandLineFlagInfoOrDie("foo").is_default) ...
+extern GFLAGS_DLL_DECL CommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name);
+
+enum GFLAGS_DLL_DECL FlagSettingMode {
+  // update the flag's value (can call this multiple times).
+  SET_FLAGS_VALUE,
+  // update the flag's value, but *only if* it has not yet been updated
+  // with SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef".
+  SET_FLAG_IF_DEFAULT,
+  // set the flag's default value to this.  If the flag has not yet updated
+  // yet (via SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef")
+  // change the flag's current value to the new default value as well.
+  SET_FLAGS_DEFAULT
+};
+
+// Set a particular flag ("command line option").  Returns a string
+// describing the new value that the option has been set to.  The
+// return value API is not well-specified, so basically just depend on
+// it to be empty if the setting failed for some reason -- the name is
+// not a valid flag name, or the value is not a valid value -- and
+// non-empty else.
+
+// SetCommandLineOption uses set_mode == SET_FLAGS_VALUE (the common case)
+extern GFLAGS_DLL_DECL std::string SetCommandLineOption        (const char* name, const char* value);
+extern GFLAGS_DLL_DECL std::string SetCommandLineOptionWithMode(const char* name, const char* value, FlagSettingMode set_mode);
+
+
+// --------------------------------------------------------------------
+// Saves the states (value, default value, whether the user has set
+// the flag, registered validators, etc) of all flags, and restores
+// them when the FlagSaver is destroyed.  This is very useful in
+// tests, say, when you want to let your tests change the flags, but
+// make sure that they get reverted to the original states when your
+// test is complete.
+//
+// Example usage:
+//   void TestFoo() {
+//     FlagSaver s1;
+//     FLAG_foo = false;
+//     FLAG_bar = "some value";
+//
+//     // test happens here.  You can return at any time
+//     // without worrying about restoring the FLAG values.
+//   }
+//
+// Note: This class is marked with GFLAGS_ATTRIBUTE_UNUSED because all
+// the work is done in the constructor and destructor, so in the standard
+// usage example above, the compiler would complain that it's an
+// unused variable.
+//
+// This class is thread-safe.  However, its destructor writes to
+// exactly the set of flags that have changed value during its
+// lifetime, so concurrent _direct_ access to those flags
+// (i.e. FLAGS_foo instead of {Get,Set}CommandLineOption()) is unsafe.
+
+class GFLAGS_DLL_DECL FlagSaver {
+ public:
+  FlagSaver();
+  ~FlagSaver();
+
+ private:
+  class FlagSaverImpl* impl_;   // we use pimpl here to keep API steady
+
+  FlagSaver(const FlagSaver&);  // no copying!
+  void operator=(const FlagSaver&);
+}@GFLAGS_ATTRIBUTE_UNUSED@;
+
+// --------------------------------------------------------------------
+// Some deprecated or hopefully-soon-to-be-deprecated functions.
+
+// This is often used for logging.  TODO(csilvers): figure out a better way
+extern GFLAGS_DLL_DECL std::string CommandlineFlagsIntoString();
+// Usually where this is used, a FlagSaver should be used instead.
+extern GFLAGS_DLL_DECL
+bool ReadFlagsFromString(const std::string& flagfilecontents,
+                         const char* prog_name,
+                         bool errors_are_fatal);  // uses SET_FLAGS_VALUE
+
+// These let you manually implement --flagfile functionality.
+// DEPRECATED.
+extern GFLAGS_DLL_DECL bool AppendFlagsIntoFile(const std::string& filename, const char* prog_name);
+extern GFLAGS_DLL_DECL bool ReadFromFlagsFile(const std::string& filename, const char* prog_name, bool errors_are_fatal);   // uses SET_FLAGS_VALUE
+
+
+// --------------------------------------------------------------------
+// Useful routines for initializing flags from the environment.
+// In each case, if 'varname' does not exist in the environment
+// return defval.  If 'varname' does exist but is not valid
+// (e.g., not a number for an int32 flag), abort with an error.
+// Otherwise, return the value.  NOTE: for booleans, for true use
+// 't' or 'T' or 'true' or '1', for false 'f' or 'F' or 'false' or '0'.
+
+extern GFLAGS_DLL_DECL bool BoolFromEnv(const char *varname, bool defval);
+extern GFLAGS_DLL_DECL int32 Int32FromEnv(const char *varname, int32 defval);
+extern GFLAGS_DLL_DECL int64 Int64FromEnv(const char *varname, int64 defval);
+extern GFLAGS_DLL_DECL uint64 Uint64FromEnv(const char *varname, uint64 defval);
+extern GFLAGS_DLL_DECL double DoubleFromEnv(const char *varname, double defval);
+extern GFLAGS_DLL_DECL const char *StringFromEnv(const char *varname, const char *defval);
+
+
+// --------------------------------------------------------------------
+// The next two functions parse gflags from main():
+
+// Set the "usage" message for this program.  For example:
+//   string usage("This program does nothing.  Sample usage:\n");
+//   usage += argv[0] + " <uselessarg1> <uselessarg2>";
+//   SetUsageMessage(usage);
+// Do not include commandline flags in the usage: we do that for you!
+// Thread-hostile; meant to be called before any threads are spawned.
+extern GFLAGS_DLL_DECL void SetUsageMessage(const std::string& usage);
+
+// Sets the version string, which is emitted with --version.
+// For instance: SetVersionString("1.3");
+// Thread-hostile; meant to be called before any threads are spawned.
+extern GFLAGS_DLL_DECL void SetVersionString(const std::string& version);
+
+
+// Looks for flags in argv and parses them.  Rearranges argv to put
+// flags first, or removes them entirely if remove_flags is true.
+// If a flag is defined more than once in the command line or flag
+// file, the last definition is used.  Returns the index (into argv)
+// of the first non-flag argument.
+// See top-of-file for more details on this function.
+#ifndef SWIG   // In swig, use ParseCommandLineFlagsScript() instead.
+extern GFLAGS_DLL_DECL uint32 ParseCommandLineFlags(int *argc, char*** argv, bool remove_flags);
+#endif
+
+
+// Calls to ParseCommandLineNonHelpFlags and then to
+// HandleCommandLineHelpFlags can be used instead of a call to
+// ParseCommandLineFlags during initialization, in order to allow for
+// changing default values for some FLAGS (via
+// e.g. SetCommandLineOptionWithMode calls) between the time of
+// command line parsing and the time of dumping help information for
+// the flags as a result of command line parsing.  If a flag is
+// defined more than once in the command line or flag file, the last
+// definition is used.  Returns the index (into argv) of the first
+// non-flag argument.  (If remove_flags is true, will always return 1.)
+extern GFLAGS_DLL_DECL uint32 ParseCommandLineNonHelpFlags(int *argc, char*** argv, bool remove_flags);
+
+// This is actually defined in gflags_reporting.cc.
+// This function is misnamed (it also handles --version, etc.), but
+// it's too late to change that now. :-(
+extern GFLAGS_DLL_DECL void HandleCommandLineHelpFlags();   // in gflags_reporting.cc
+
+// Allow command line reparsing.  Disables the error normally
+// generated when an unknown flag is found, since it may be found in a
+// later parse.  Thread-hostile; meant to be called before any threads
+// are spawned.
+extern GFLAGS_DLL_DECL void AllowCommandLineReparsing();
+
+// Reparse the flags that have not yet been recognized.  Only flags
+// registered since the last parse will be recognized.  Any flag value
+// must be provided as part of the argument using "=", not as a
+// separate command line argument that follows the flag argument.
+// Intended for handling flags from dynamically loaded libraries,
+// since their flags are not registered until they are loaded.
+extern GFLAGS_DLL_DECL void ReparseCommandLineNonHelpFlags();
+
+// Clean up memory allocated by flags.  This is only needed to reduce
+// the quantity of "potentially leaked" reports emitted by memory
+// debugging tools such as valgrind.  It is not required for normal
+// operation, or for the google perftools heap-checker.  It must only
+// be called when the process is about to exit, and all threads that
+// might access flags are quiescent.  Referencing flags after this is
+// called will have unexpected consequences.  This is not safe to run
+// when multiple threads might be running: the function is
+// thread-hostile.
+extern GFLAGS_DLL_DECL void ShutDownCommandLineFlags();
+
+
+// --------------------------------------------------------------------
+// Now come the command line flag declaration/definition macros that
+// will actually be used.  They're kind of hairy.  A major reason
+// for this is initialization: we want people to be able to access
+// variables in global constructors and have that not crash, even if
+// their global constructor runs before the global constructor here.
+// (Obviously, we can't guarantee the flags will have the correct
+// default value in that case, but at least accessing them is safe.)
+// The only way to do that is have flags point to a static buffer.
+// So we make one, using a union to ensure proper alignment, and
+// then use placement-new to actually set up the flag with the
+// correct default value.  In the same vein, we have to worry about
+// flag access in global destructors, so FlagRegisterer has to be
+// careful never to destroy the flag-values it constructs.
+//
+// Note that when we define a flag variable FLAGS_<name>, we also
+// preemptively define a junk variable, FLAGS_no<name>.  This is to
+// cause a link-time error if someone tries to define 2 flags with
+// names like "logging" and "nologging".  We do this because a bool
+// flag FLAG can be set from the command line to true with a "-FLAG"
+// argument, and to false with a "-noFLAG" argument, and so this can
+// potentially avert confusion.
+//
+// We also put flags into their own namespace.  It is purposefully
+// named in an opaque way that people should have trouble typing
+// directly.  The idea is that DEFINE puts the flag in the weird
+// namespace, and DECLARE imports the flag from there into the current
+// namespace.  The net result is to force people to use DECLARE to get
+// access to a flag, rather than saying "extern GFLAGS_DLL_DECL bool FLAGS_whatever;"
+// or some such instead.  We want this so we can put extra
+// functionality (like sanity-checking) in DECLARE if we want, and
+// make sure it is picked up everywhere.
+//
+// We also put the type of the variable in the namespace, so that
+// people can't DECLARE_int32 something that they DEFINE_bool'd
+// elsewhere.
+
+class GFLAGS_DLL_DECL FlagRegisterer {
+ public:
+  FlagRegisterer(const char* name, const char* type,
+                 const char* help, const char* filename,
+                 void* current_storage, void* defvalue_storage);
+};
+
+// If your application #defines STRIP_FLAG_HELP to a non-zero value
+// before #including this file, we remove the help message from the
+// binary file. This can reduce the size of the resulting binary
+// somewhat, and may also be useful for security reasons.
+
+extern GFLAGS_DLL_DECL const char kStrippedFlagHelp[];
+
+
+} // namespace GFLAGS_NAMESPACE
+
+
+#ifndef SWIG  // In swig, ignore the main flag declarations
+
+#if defined(STRIP_FLAG_HELP) && STRIP_FLAG_HELP > 0
+// Need this construct to avoid the 'defined but not used' warning.
+#define MAYBE_STRIPPED_HELP(txt) \
+   (false ? (txt) : GFLAGS_NAMESPACE::kStrippedFlagHelp)
+#else
+#define MAYBE_STRIPPED_HELP(txt) txt
+#endif
+
+// Each command-line flag has two variables associated with it: one
+// with the current value, and one with the default value.  However,
+// we have a third variable, which is where value is assigned; it's a
+// constant.  This guarantees that FLAG_##value is initialized at
+// static initialization time (e.g. before program-start) rather than
+// than global construction time (which is after program-start but
+// before main), at least when 'value' is a compile-time constant.  We
+// use a small trick for the "default value" variable, and call it
+// FLAGS_no<name>.  This serves the second purpose of assuring a
+// compile error if someone tries to define a flag named no<name>
+// which is illegal (--foo and --nofoo both affect the "foo" flag).
+#define DEFINE_VARIABLE(type, shorttype, name, value, help)             \
+  namespace fL##shorttype {                                             \
+    static const type FLAGS_nono##name = value;                         \
+    /* We always want to export defined variables, dll or no */         \
+    GFLAGS_DLL_DEFINE_FLAG type FLAGS_##name = FLAGS_nono##name;        \
+    type FLAGS_no##name = FLAGS_nono##name;                             \
+    static GFLAGS_NAMESPACE::FlagRegisterer o_##name(                   \
+      #name, #type, MAYBE_STRIPPED_HELP(help), __FILE__,                \
+      &FLAGS_##name, &FLAGS_no##name);                                  \
+  }                                                                     \
+  using fL##shorttype::FLAGS_##name
+
+// For DEFINE_bool, we want to do the extra check that the passed-in
+// value is actually a bool, and not a string or something that can be
+// coerced to a bool.  These declarations (no definition needed!) will
+// help us do that, and never evaluate From, which is important.
+// We'll use 'sizeof(IsBool(val))' to distinguish. This code requires
+// that the compiler have different sizes for bool & double. Since
+// this is not guaranteed by the standard, we check it with a
+// COMPILE_ASSERT.
+namespace fLB {
+struct CompileAssert {};
+typedef CompileAssert expected_sizeof_double_neq_sizeof_bool[
+                      (sizeof(double) != sizeof(bool)) ? 1 : -1];
+template<typename From> double GFLAGS_DLL_DECL IsBoolFlag(const From& from);
+GFLAGS_DLL_DECL bool IsBoolFlag(bool from);
+}  // namespace fLB
+
+// Here are the actual DEFINE_*-macros. The respective DECLARE_*-macros
+// are in a separate include, gflags_declare.h, for reducing
+// the physical transitive size for DECLARE use.
+#define DEFINE_bool(name, val, txt)                                     \
+  namespace fLB {                                                       \
+    typedef ::fLB::CompileAssert FLAG_##name##_value_is_not_a_bool[     \
+            (sizeof(::fLB::IsBoolFlag(val)) != sizeof(double))? 1: -1]; \
+  }                                                                     \
+  DEFINE_VARIABLE(bool, B, name, val, txt)
+
+#define DEFINE_int32(name, val, txt) \
+   DEFINE_VARIABLE(GFLAGS_NAMESPACE::int32, I, \
+                   name, val, txt)
+
+#define DEFINE_int64(name, val, txt) \
+   DEFINE_VARIABLE(GFLAGS_NAMESPACE::int64, I64, \
+                   name, val, txt)
+
+#define DEFINE_uint64(name,val, txt) \
+   DEFINE_VARIABLE(GFLAGS_NAMESPACE::uint64, U64, \
+                   name, val, txt)
+
+#define DEFINE_double(name, val, txt) \
+   DEFINE_VARIABLE(double, D, name, val, txt)
+
+// Strings are trickier, because they're not a POD, so we can't
+// construct them at static-initialization time (instead they get
+// constructed at global-constructor time, which is much later).  To
+// try to avoid crashes in that case, we use a char buffer to store
+// the string, which we can static-initialize, and then placement-new
+// into it later.  It's not perfect, but the best we can do.
+
+namespace fLS {
+
+inline clstring* dont_pass0toDEFINE_string(char *stringspot,
+                                           const char *value) {
+  return new(stringspot) clstring(value);
+}
+inline clstring* dont_pass0toDEFINE_string(char *stringspot,
+                                           const clstring &value) {
+  return new(stringspot) clstring(value);
+}
+inline clstring* dont_pass0toDEFINE_string(char *stringspot,
+                                           int value);
+}  // namespace fLS
+
+// We need to define a var named FLAGS_no##name so people don't define
+// --string and --nostring.  And we need a temporary place to put val
+// so we don't have to evaluate it twice.  Two great needs that go
+// great together!
+// The weird 'using' + 'extern' inside the fLS namespace is to work around
+// an unknown compiler bug/issue with the gcc 4.2.1 on SUSE 10.  See
+//    http://code.google.com/p/google-gflags/issues/detail?id=20
+#define DEFINE_string(name, val, txt)                                       \
+  namespace fLS {                                                           \
+    using ::fLS::clstring;                                                  \
+    static union { void* align; char s[sizeof(clstring)]; } s_##name[2];    \
+    clstring* const FLAGS_no##name = ::fLS::                                \
+                                   dont_pass0toDEFINE_string(s_##name[0].s, \
+                                                             val);          \
+    static GFLAGS_NAMESPACE::FlagRegisterer o_##name(                       \
+        #name, "string", MAYBE_STRIPPED_HELP(txt), __FILE__,                \
+        s_##name[0].s, new (s_##name[1].s) clstring(*FLAGS_no##name));      \
+    extern GFLAGS_DLL_DEFINE_FLAG clstring& FLAGS_##name;                   \
+    using fLS::FLAGS_##name;                                                \
+    clstring& FLAGS_##name = *FLAGS_no##name;                               \
+  }                                                                         \
+  using fLS::FLAGS_##name
+
+#endif  // SWIG
+
+
+@INCLUDE_GFLAGS_NS_H@
+
+
+#endif  // GFLAGS_GFLAGS_H_
diff --git a/third_party/gflags/src/gflags_completions.cc b/third_party/gflags/src/gflags_completions.cc
new file mode 100644
index 0000000..3a47623
--- /dev/null
+++ b/third_party/gflags/src/gflags_completions.cc
@@ -0,0 +1,769 @@
+// Copyright (c) 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ---
+
+// Bash-style command line flag completion for C++ binaries
+//
+// This module implements bash-style completions.  It achieves this
+// goal in the following broad chunks:
+//
+//  1) Take a to-be-completed word, and examine it for search hints
+//  2) Identify all potentially matching flags
+//     2a) If there are no matching flags, do nothing.
+//     2b) If all matching flags share a common prefix longer than the
+//         completion word, output just that matching prefix
+//  3) Categorize those flags to produce a rough ordering of relevence.
+//  4) Potentially trim the set of flags returned to a smaller number
+//     that bash is happier with
+//  5) Output the matching flags in groups ordered by relevence.
+//     5a) Force bash to place most-relevent groups at the top of the list
+//     5b) Trim most flag's descriptions to fit on a single terminal line
+
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>   // for strlen
+
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "gflags.h"
+#include "util.h"
+
+using std::set;
+using std::string;
+using std::vector;
+
+
+DEFINE_string(tab_completion_word, "",
+              "If non-empty, HandleCommandLineCompletions() will hijack the "
+              "process and attempt to do bash-style command line flag "
+              "completion on this value.");
+DEFINE_int32(tab_completion_columns, 80,
+             "Number of columns to use in output for tab completion");
+
+
+namespace GFLAGS_NAMESPACE {
+
+
+namespace {
+// Function prototypes and Type forward declarations.  Code may be
+// more easily understood if it is roughly ordered according to
+// control flow, rather than by C's "declare before use" ordering
+struct CompletionOptions;
+struct NotableFlags;
+
+// The entry point if flag completion is to be used.
+static void PrintFlagCompletionInfo(void);
+
+
+// 1) Examine search word
+static void CanonicalizeCursorWordAndSearchOptions(
+    const string &cursor_word,
+    string *canonical_search_token,
+    CompletionOptions *options);
+
+static bool RemoveTrailingChar(string *str, char c);
+
+
+// 2) Find all matches
+static void FindMatchingFlags(
+    const vector<CommandLineFlagInfo> &all_flags,
+    const CompletionOptions &options,
+    const string &match_token,
+    set<const CommandLineFlagInfo *> *all_matches,
+    string *longest_common_prefix);
+
+static bool DoesSingleFlagMatch(
+    const CommandLineFlagInfo &flag,
+    const CompletionOptions &options,
+    const string &match_token);
+
+
+// 3) Categorize matches
+static void CategorizeAllMatchingFlags(
+    const set<const CommandLineFlagInfo *> &all_matches,
+    const string &search_token,
+    const string &module,
+    const string &package_dir,
+    NotableFlags *notable_flags);
+
+static void TryFindModuleAndPackageDir(
+    const vector<CommandLineFlagInfo> all_flags,
+    string *module,
+    string *package_dir);
+
+
+// 4) Decide which flags to use
+static void FinalizeCompletionOutput(
+    const set<const CommandLineFlagInfo *> &matching_flags,
+    CompletionOptions *options,
+    NotableFlags *notable_flags,
+    vector<string> *completions);
+
+static void RetrieveUnusedFlags(
+    const set<const CommandLineFlagInfo *> &matching_flags,
+    const NotableFlags &notable_flags,
+    set<const CommandLineFlagInfo *> *unused_flags);
+
+
+// 5) Output matches
+static void OutputSingleGroupWithLimit(
+    const set<const CommandLineFlagInfo *> &group,
+    const string &line_indentation,
+    const string &header,
+    const string &footer,
+    bool long_output_format,
+    int *remaining_line_limit,
+    size_t *completion_elements_added,
+    vector<string> *completions);
+
+// (helpers for #5)
+static string GetShortFlagLine(
+    const string &line_indentation,
+    const CommandLineFlagInfo &info);
+
+static string GetLongFlagLine(
+    const string &line_indentation,
+    const CommandLineFlagInfo &info);
+
+
+//
+// Useful types
+
+// Try to deduce the intentions behind this completion attempt.  Return the
+// canonical search term in 'canonical_search_token'.  Binary search options
+// are returned in the various booleans, which should all have intuitive
+// semantics, possibly except:
+//  - return_all_matching_flags: Generally, we'll trim the number of
+//    returned candidates to some small number, showing those that are
+//    most likely to be useful first.  If this is set, however, the user
+//    really does want us to return every single flag as an option.
+//  - force_no_update: Any time we output lines, all of which share a
+//    common prefix, bash will 'helpfully' not even bother to show the
+//    output, instead changing the current word to be that common prefix.
+//    If it's clear this shouldn't happen, we'll set this boolean
+struct CompletionOptions {
+  bool flag_name_substring_search;
+  bool flag_location_substring_search;
+  bool flag_description_substring_search;
+  bool return_all_matching_flags;
+  bool force_no_update;
+};
+
+// Notable flags are flags that are special or preferred for some
+// reason.  For example, flags that are defined in the binary's module
+// are expected to be much more relevent than flags defined in some
+// other random location.  These sets are specified roughly in precedence
+// order.  Once a flag is placed in one of these 'higher' sets, it won't
+// be placed in any of the 'lower' sets.
+struct NotableFlags {
+  typedef set<const CommandLineFlagInfo *> FlagSet;
+  FlagSet perfect_match_flag;
+  FlagSet module_flags;       // Found in module file
+  FlagSet package_flags;      // Found in same directory as module file
+  FlagSet most_common_flags;  // One of the XXX most commonly supplied flags
+  FlagSet subpackage_flags;   // Found in subdirectories of package
+};
+
+
+//
+// Tab completion implementation - entry point
+static void PrintFlagCompletionInfo(void) {
+  string cursor_word = FLAGS_tab_completion_word;
+  string canonical_token;
+  CompletionOptions options = { };
+  CanonicalizeCursorWordAndSearchOptions(
+      cursor_word,
+      &canonical_token,
+      &options);
+
+  DVLOG(1) << "Identified canonical_token: '" << canonical_token << "'";
+
+  vector<CommandLineFlagInfo> all_flags;
+  set<const CommandLineFlagInfo *> matching_flags;
+  GetAllFlags(&all_flags);
+  DVLOG(2) << "Found " << all_flags.size() << " flags overall";
+
+  string longest_common_prefix;
+  FindMatchingFlags(
+      all_flags,
+      options,
+      canonical_token,
+      &matching_flags,
+      &longest_common_prefix);
+  DVLOG(1) << "Identified " << matching_flags.size() << " matching flags";
+  DVLOG(1) << "Identified " << longest_common_prefix
+          << " as longest common prefix.";
+  if (longest_common_prefix.size() > canonical_token.size()) {
+    // There's actually a shared common prefix to all matching flags,
+    // so may as well output that and quit quickly.
+    DVLOG(1) << "The common prefix '" << longest_common_prefix
+            << "' was longer than the token '" << canonical_token
+            << "'.  Returning just this prefix for completion.";
+    fprintf(stdout, "--%s", longest_common_prefix.c_str());
+    return;
+  }
+  if (matching_flags.empty()) {
+    VLOG(1) << "There were no matching flags, returning nothing.";
+    return;
+  }
+
+  string module;
+  string package_dir;
+  TryFindModuleAndPackageDir(all_flags, &module, &package_dir);
+  DVLOG(1) << "Identified module: '" << module << "'";
+  DVLOG(1) << "Identified package_dir: '" << package_dir << "'";
+
+  NotableFlags notable_flags;
+  CategorizeAllMatchingFlags(
+      matching_flags,
+      canonical_token,
+      module,
+      package_dir,
+      &notable_flags);
+  DVLOG(2) << "Categorized matching flags:";
+  DVLOG(2) << " perfect_match: " << notable_flags.perfect_match_flag.size();
+  DVLOG(2) << " module: " << notable_flags.module_flags.size();
+  DVLOG(2) << " package: " << notable_flags.package_flags.size();
+  DVLOG(2) << " most common: " << notable_flags.most_common_flags.size();
+  DVLOG(2) << " subpackage: " << notable_flags.subpackage_flags.size();
+
+  vector<string> completions;
+  FinalizeCompletionOutput(
+      matching_flags,
+      &options,
+      &notable_flags,
+      &completions);
+
+  if (options.force_no_update)
+    completions.push_back("~");
+
+  DVLOG(1) << "Finalized with " << completions.size()
+          << " chosen completions";
+
+  for (vector<string>::const_iterator it = completions.begin();
+      it != completions.end();
+      ++it) {
+    DVLOG(9) << "  Completion entry: '" << *it << "'";
+    fprintf(stdout, "%s\n", it->c_str());
+  }
+}
+
+
+// 1) Examine search word (and helper method)
+static void CanonicalizeCursorWordAndSearchOptions(
+    const string &cursor_word,
+    string *canonical_search_token,
+    CompletionOptions *options) {
+  *canonical_search_token = cursor_word;
+  if (canonical_search_token->empty()) return;
+
+  // Get rid of leading quotes and dashes in the search term
+  if ((*canonical_search_token)[0] == '"')
+    *canonical_search_token = canonical_search_token->substr(1);
+  while ((*canonical_search_token)[0] == '-')
+    *canonical_search_token = canonical_search_token->substr(1);
+
+  options->flag_name_substring_search = false;
+  options->flag_location_substring_search = false;
+  options->flag_description_substring_search = false;
+  options->return_all_matching_flags = false;
+  options->force_no_update = false;
+
+  // Look for all search options we can deduce now.  Do this by walking
+  // backwards through the term, looking for up to three '?' and up to
+  // one '+' as suffixed characters.  Consume them if found, and remove
+  // them from the canonical search token.
+  int found_question_marks = 0;
+  int found_plusses = 0;
+  while (true) {
+    if (found_question_marks < 3 &&
+        RemoveTrailingChar(canonical_search_token, '?')) {
+      ++found_question_marks;
+      continue;
+    }
+    if (found_plusses < 1 &&
+        RemoveTrailingChar(canonical_search_token, '+')) {
+      ++found_plusses;
+      continue;
+    }
+    break;
+  }
+
+  switch (found_question_marks) {  // all fallthroughs
+    case 3: options->flag_description_substring_search = true;
+    case 2: options->flag_location_substring_search = true;
+    case 1: options->flag_name_substring_search = true;
+  };
+
+  options->return_all_matching_flags = (found_plusses > 0);
+}
+
+// Returns true if a char was removed
+static bool RemoveTrailingChar(string *str, char c) {
+  if (str->empty()) return false;
+  if ((*str)[str->size() - 1] == c) {
+    *str = str->substr(0, str->size() - 1);
+    return true;
+  }
+  return false;
+}
+
+
+// 2) Find all matches (and helper methods)
+static void FindMatchingFlags(
+    const vector<CommandLineFlagInfo> &all_flags,
+    const CompletionOptions &options,
+    const string &match_token,
+    set<const CommandLineFlagInfo *> *all_matches,
+    string *longest_common_prefix) {
+  all_matches->clear();
+  bool first_match = true;
+  for (vector<CommandLineFlagInfo>::const_iterator it = all_flags.begin();
+      it != all_flags.end();
+      ++it) {
+    if (DoesSingleFlagMatch(*it, options, match_token)) {
+      all_matches->insert(&*it);
+      if (first_match) {
+        first_match = false;
+        *longest_common_prefix = it->name;
+      } else {
+        if (longest_common_prefix->empty() || it->name.empty()) {
+          longest_common_prefix->clear();
+          continue;
+        }
+        string::size_type pos = 0;
+        while (pos < longest_common_prefix->size() &&
+            pos < it->name.size() &&
+            (*longest_common_prefix)[pos] == it->name[pos])
+          ++pos;
+        longest_common_prefix->erase(pos);
+      }
+    }
+  }
+}
+
+// Given the set of all flags, the parsed match options, and the
+// canonical search token, produce the set of all candidate matching
+// flags for subsequent analysis or filtering.
+static bool DoesSingleFlagMatch(
+    const CommandLineFlagInfo &flag,
+    const CompletionOptions &options,
+    const string &match_token) {
+  // Is there a prefix match?
+  string::size_type pos = flag.name.find(match_token);
+  if (pos == 0) return true;
+
+  // Is there a substring match if we want it?
+  if (options.flag_name_substring_search &&
+      pos != string::npos)
+    return true;
+
+  // Is there a location match if we want it?
+  if (options.flag_location_substring_search &&
+      flag.filename.find(match_token) != string::npos)
+    return true;
+
+  // TODO(user): All searches should probably be case-insensitive
+  // (especially this one...)
+  if (options.flag_description_substring_search &&
+      flag.description.find(match_token) != string::npos)
+    return true;
+
+  return false;
+}
+
+// 3) Categorize matches (and helper method)
+
+// Given a set of matching flags, categorize them by
+// likely relevence to this specific binary
+static void CategorizeAllMatchingFlags(
+    const set<const CommandLineFlagInfo *> &all_matches,
+    const string &search_token,
+    const string &module,  // empty if we couldn't find any
+    const string &package_dir,  // empty if we couldn't find any
+    NotableFlags *notable_flags) {
+  notable_flags->perfect_match_flag.clear();
+  notable_flags->module_flags.clear();
+  notable_flags->package_flags.clear();
+  notable_flags->most_common_flags.clear();
+  notable_flags->subpackage_flags.clear();
+
+  for (set<const CommandLineFlagInfo *>::const_iterator it =
+        all_matches.begin();
+      it != all_matches.end();
+      ++it) {
+    DVLOG(2) << "Examining match '" << (*it)->name << "'";
+    DVLOG(7) << "  filename: '" << (*it)->filename << "'";
+    string::size_type pos = string::npos;
+    if (!package_dir.empty())
+      pos = (*it)->filename.find(package_dir);
+    string::size_type slash = string::npos;
+    if (pos != string::npos)  // candidate for package or subpackage match
+      slash = (*it)->filename.find(
+          PATH_SEPARATOR,
+          pos + package_dir.size() + 1);
+
+    if ((*it)->name == search_token) {
+      // Exact match on some flag's name
+      notable_flags->perfect_match_flag.insert(*it);
+      DVLOG(3) << "Result: perfect match";
+    } else if (!module.empty() && (*it)->filename == module) {
+      // Exact match on module filename
+      notable_flags->module_flags.insert(*it);
+      DVLOG(3) << "Result: module match";
+    } else if (!package_dir.empty() &&
+        pos != string::npos && slash == string::npos) {
+      // In the package, since there was no slash after the package portion
+      notable_flags->package_flags.insert(*it);
+      DVLOG(3) << "Result: package match";
+    } else if (false) {
+      // In the list of the XXX most commonly supplied flags overall
+      // TODO(user): Compile this list.
+      DVLOG(3) << "Result: most-common match";
+    } else if (!package_dir.empty() &&
+        pos != string::npos && slash != string::npos) {
+      // In a subdirectory of the package
+      notable_flags->subpackage_flags.insert(*it);
+      DVLOG(3) << "Result: subpackage match";
+    }
+
+    DVLOG(3) << "Result: not special match";
+  }
+}
+
+static void PushNameWithSuffix(vector<string>* suffixes, const char* suffix) {
+  suffixes->push_back(
+      StringPrintf("/%s%s", ProgramInvocationShortName(), suffix));
+}
+
+static void TryFindModuleAndPackageDir(
+    const vector<CommandLineFlagInfo> all_flags,
+    string *module,
+    string *package_dir) {
+  module->clear();
+  package_dir->clear();
+
+  vector<string> suffixes;
+  // TODO(user): There's some inherant ambiguity here - multiple directories
+  // could share the same trailing folder and file structure (and even worse,
+  // same file names), causing us to be unsure as to which of the two is the
+  // actual package for this binary.  In this case, we'll arbitrarily choose.
+  PushNameWithSuffix(&suffixes, ".");
+  PushNameWithSuffix(&suffixes, "-main.");
+  PushNameWithSuffix(&suffixes, "_main.");
+  // These four are new but probably merited?
+  PushNameWithSuffix(&suffixes, "-test.");
+  PushNameWithSuffix(&suffixes, "_test.");
+  PushNameWithSuffix(&suffixes, "-unittest.");
+  PushNameWithSuffix(&suffixes, "_unittest.");
+
+  for (vector<CommandLineFlagInfo>::const_iterator it = all_flags.begin();
+      it != all_flags.end();
+      ++it) {
+    for (vector<string>::const_iterator suffix = suffixes.begin();
+        suffix != suffixes.end();
+        ++suffix) {
+      // TODO(user): Make sure the match is near the end of the string
+      if (it->filename.find(*suffix) != string::npos) {
+        *module = it->filename;
+        string::size_type sep = it->filename.rfind(PATH_SEPARATOR);
+        *package_dir = it->filename.substr(0, (sep == string::npos) ? 0 : sep);
+        return;
+      }
+    }
+  }
+}
+
+// Can't specialize template type on a locally defined type.  Silly C++...
+struct DisplayInfoGroup {
+  const char* header;
+  const char* footer;
+  set<const CommandLineFlagInfo *> *group;
+
+  int SizeInLines() const {
+    int size_in_lines = static_cast<int>(group->size()) + 1;
+    if (strlen(header) > 0) {
+      size_in_lines++;
+    }
+    if (strlen(footer) > 0) {
+      size_in_lines++;
+    }
+    return size_in_lines;
+  }
+};
+
+// 4) Finalize and trim output flag set
+static void FinalizeCompletionOutput(
+    const set<const CommandLineFlagInfo *> &matching_flags,
+    CompletionOptions *options,
+    NotableFlags *notable_flags,
+    vector<string> *completions) {
+
+  // We want to output lines in groups.  Each group needs to be indented
+  // the same to keep its lines together.  Unless otherwise required,
+  // only 99 lines should be output to prevent bash from harassing the
+  // user.
+
+  // First, figure out which output groups we'll actually use.  For each
+  // nonempty group, there will be ~3 lines of header & footer, plus all
+  // output lines themselves.
+  int max_desired_lines =  // "999999 flags should be enough for anyone.  -dave"
+    (options->return_all_matching_flags ? 999999 : 98);
+  int lines_so_far = 0;
+
+  vector<DisplayInfoGroup> output_groups;
+  bool perfect_match_found = false;
+  if (lines_so_far < max_desired_lines &&
+      !notable_flags->perfect_match_flag.empty()) {
+    perfect_match_found = true;
+    DisplayInfoGroup group =
+        { "",
+          "==========",
+          &notable_flags->perfect_match_flag };
+    lines_so_far += group.SizeInLines();
+    output_groups.push_back(group);
+  }
+  if (lines_so_far < max_desired_lines &&
+      !notable_flags->module_flags.empty()) {
+    DisplayInfoGroup group = {
+        "-* Matching module flags *-",
+        "===========================",
+        &notable_flags->module_flags };
+    lines_so_far += group.SizeInLines();
+    output_groups.push_back(group);
+  }
+  if (lines_so_far < max_desired_lines &&
+      !notable_flags->package_flags.empty()) {
+    DisplayInfoGroup group = {
+        "-* Matching package flags *-",
+        "============================",
+        &notable_flags->package_flags };
+    lines_so_far += group.SizeInLines();
+    output_groups.push_back(group);
+  }
+  if (lines_so_far < max_desired_lines &&
+      !notable_flags->most_common_flags.empty()) {
+    DisplayInfoGroup group = {
+        "-* Commonly used flags *-",
+        "=========================",
+        &notable_flags->most_common_flags };
+    lines_so_far += group.SizeInLines();
+    output_groups.push_back(group);
+  }
+  if (lines_so_far < max_desired_lines &&
+      !notable_flags->subpackage_flags.empty()) {
+    DisplayInfoGroup group = {
+        "-* Matching sub-package flags *-",
+        "================================",
+        &notable_flags->subpackage_flags };
+    lines_so_far += group.SizeInLines();
+    output_groups.push_back(group);
+  }
+
+  set<const CommandLineFlagInfo *> obscure_flags;  // flags not notable
+  if (lines_so_far < max_desired_lines) {
+    RetrieveUnusedFlags(matching_flags, *notable_flags, &obscure_flags);
+    if (!obscure_flags.empty()) {
+      DisplayInfoGroup group = {
+          "-* Other flags *-",
+          "",
+          &obscure_flags };
+      lines_so_far += group.SizeInLines();
+      output_groups.push_back(group);
+    }
+  }
+
+  // Second, go through each of the chosen output groups and output
+  // as many of those flags as we can, while remaining below our limit
+  int remaining_lines = max_desired_lines;
+  size_t completions_output = 0;
+  int indent = static_cast<int>(output_groups.size()) - 1;
+  for (vector<DisplayInfoGroup>::const_iterator it =
+        output_groups.begin();
+      it != output_groups.end();
+      ++it, --indent) {
+    OutputSingleGroupWithLimit(
+        *it->group,  // group
+        string(indent, ' '),  // line indentation
+        string(it->header),  // header
+        string(it->footer),  // footer
+        perfect_match_found,  // long format
+        &remaining_lines,  // line limit - reduces this by number printed
+        &completions_output,  // completions (not lines) added
+        completions);  // produced completions
+    perfect_match_found = false;
+  }
+
+  if (completions_output != matching_flags.size()) {
+    options->force_no_update = false;
+    completions->push_back("~ (Remaining flags hidden) ~");
+  } else {
+    options->force_no_update = true;
+  }
+}
+
+static void RetrieveUnusedFlags(
+    const set<const CommandLineFlagInfo *> &matching_flags,
+    const NotableFlags &notable_flags,
+    set<const CommandLineFlagInfo *> *unused_flags) {
+  // Remove from 'matching_flags' set all members of the sets of
+  // flags we've already printed (specifically, those in notable_flags)
+  for (set<const CommandLineFlagInfo *>::const_iterator it =
+        matching_flags.begin();
+      it != matching_flags.end();
+      ++it) {
+    if (notable_flags.perfect_match_flag.count(*it) ||
+        notable_flags.module_flags.count(*it) ||
+        notable_flags.package_flags.count(*it) ||
+        notable_flags.most_common_flags.count(*it) ||
+        notable_flags.subpackage_flags.count(*it))
+      continue;
+    unused_flags->insert(*it);
+  }
+}
+
+// 5) Output matches (and helper methods)
+
+static void OutputSingleGroupWithLimit(
+    const set<const CommandLineFlagInfo *> &group,
+    const string &line_indentation,
+    const string &header,
+    const string &footer,
+    bool long_output_format,
+    int *remaining_line_limit,
+    size_t *completion_elements_output,
+    vector<string> *completions) {
+  if (group.empty()) return;
+  if (!header.empty()) {
+    if (*remaining_line_limit < 2) return;
+    *remaining_line_limit -= 2;
+    completions->push_back(line_indentation + header);
+    completions->push_back(line_indentation + string(header.size(), '-'));
+  }
+  for (set<const CommandLineFlagInfo *>::const_iterator it = group.begin();
+      it != group.end() && *remaining_line_limit > 0;
+      ++it) {
+    --*remaining_line_limit;
+    ++*completion_elements_output;
+    completions->push_back(
+        (long_output_format
+          ? GetLongFlagLine(line_indentation, **it)
+          : GetShortFlagLine(line_indentation, **it)));
+  }
+  if (!footer.empty()) {
+    if (*remaining_line_limit < 1) return;
+    --*remaining_line_limit;
+    completions->push_back(line_indentation + footer);
+  }
+}
+
+static string GetShortFlagLine(
+    const string &line_indentation,
+    const CommandLineFlagInfo &info) {
+  string prefix;
+  bool is_string = (info.type == "string");
+  SStringPrintf(&prefix, "%s--%s [%s%s%s] ",
+                line_indentation.c_str(),
+                info.name.c_str(),
+                (is_string ? "'" : ""),
+                info.default_value.c_str(),
+                (is_string ? "'" : ""));
+  int remainder =
+      FLAGS_tab_completion_columns - static_cast<int>(prefix.size());
+  string suffix;
+  if (remainder > 0)
+    suffix =
+        (static_cast<int>(info.description.size()) > remainder ?
+         (info.description.substr(0, remainder - 3) + "...").c_str() :
+         info.description.c_str());
+  return prefix + suffix;
+}
+
+static string GetLongFlagLine(
+    const string &line_indentation,
+    const CommandLineFlagInfo &info) {
+
+  string output = DescribeOneFlag(info);
+
+  // Replace '-' with '--', and remove trailing newline before appending
+  // the module definition location.
+  string old_flagname = "-" + info.name;
+  output.replace(
+      output.find(old_flagname),
+      old_flagname.size(),
+      "-" + old_flagname);
+  // Stick a newline and indentation in front of the type and default
+  // portions of DescribeOneFlag()s description
+  static const char kNewlineWithIndent[] = "\n    ";
+  output.replace(output.find(" type:"), 1, string(kNewlineWithIndent));
+  output.replace(output.find(" default:"), 1, string(kNewlineWithIndent));
+  output = StringPrintf("%s Details for '--%s':\n"
+                        "%s    defined: %s",
+                        line_indentation.c_str(),
+                        info.name.c_str(),
+                        output.c_str(),
+                        info.filename.c_str());
+
+  // Eliminate any doubled newlines that crept in.  Specifically, if
+  // DescribeOneFlag() decided to break the line just before "type"
+  // or "default", we don't want to introduce an extra blank line
+  static const string line_of_spaces(FLAGS_tab_completion_columns, ' ');
+  static const char kDoubledNewlines[] = "\n     \n";
+  for (string::size_type newlines = output.find(kDoubledNewlines);
+      newlines != string::npos;
+      newlines = output.find(kDoubledNewlines))
+    // Replace each 'doubled newline' with a single newline
+    output.replace(newlines, sizeof(kDoubledNewlines) - 1, string("\n"));
+
+  for (string::size_type newline = output.find('\n');
+      newline != string::npos;
+      newline = output.find('\n')) {
+    int newline_pos = static_cast<int>(newline) % FLAGS_tab_completion_columns;
+    int missing_spaces = FLAGS_tab_completion_columns - newline_pos;
+    output.replace(newline, 1, line_of_spaces, 1, missing_spaces);
+  }
+  return output;
+}
+}  // anonymous
+
+void HandleCommandLineCompletions(void) {
+  if (FLAGS_tab_completion_word.empty()) return;
+  PrintFlagCompletionInfo();
+  gflags_exitfunc(0);
+}
+
+
+} // namespace GFLAGS_NAMESPACE
diff --git a/third_party/gflags/src/gflags_completions.h.in b/third_party/gflags/src/gflags_completions.h.in
new file mode 100644
index 0000000..b27e5fd
--- /dev/null
+++ b/third_party/gflags/src/gflags_completions.h.in
@@ -0,0 +1,121 @@
+// Copyright (c) 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ---
+
+//
+// Implement helpful bash-style command line flag completions
+//
+// ** Functional API:
+// HandleCommandLineCompletions() should be called early during
+// program startup, but after command line flag code has been
+// initialized, such as the beginning of HandleCommandLineHelpFlags().
+// It checks the value of the flag --tab_completion_word.  If this
+// flag is empty, nothing happens here.  If it contains a string,
+// however, then HandleCommandLineCompletions() will hijack the
+// process, attempting to identify the intention behind this
+// completion.  Regardless of the outcome of this deduction, the
+// process will be terminated, similar to --helpshort flag
+// handling.
+//
+// ** Overview of Bash completions:
+// Bash can be told to programatically determine completions for the
+// current 'cursor word'.  It does this by (in this case) invoking a
+// command with some additional arguments identifying the command
+// being executed, the word being completed, and the previous word
+// (if any).  Bash then expects a sequence of output lines to be
+// printed to stdout.  If these lines all contain a common prefix
+// longer than the cursor word, bash will replace the cursor word
+// with that common prefix, and display nothing.  If there isn't such
+// a common prefix, bash will display the lines in pages using 'more'.
+//
+// ** Strategy taken for command line completions:
+// If we can deduce either the exact flag intended, or a common flag
+// prefix, we'll output exactly that.  Otherwise, if information
+// must be displayed to the user, we'll take the opportunity to add
+// some helpful information beyond just the flag name (specifically,
+// we'll include the default flag value and as much of the flag's
+// description as can fit on a single terminal line width, as specified
+// by the flag --tab_completion_columns).  Furthermore, we'll try to
+// make bash order the output such that the most useful or relevent
+// flags are the most likely to be shown at the top.
+//
+// ** Additional features:
+// To assist in finding that one really useful flag, substring matching
+// was implemented.  Before pressing a <TAB> to get completion for the
+// current word, you can append one or more '?' to the flag to do
+// substring matching.  Here's the semantics:
+//   --foo<TAB>     Show me all flags with names prefixed by 'foo'
+//   --foo?<TAB>    Show me all flags with 'foo' somewhere in the name
+//   --foo??<TAB>   Same as prior case, but also search in module
+//                  definition path for 'foo'
+//   --foo???<TAB>  Same as prior case, but also search in flag
+//                  descriptions for 'foo'
+// Finally, we'll trim the output to a relatively small number of
+// flags to keep bash quiet about the verbosity of output.  If one
+// really wanted to see all possible matches, appending a '+' to the
+// search word will force the exhaustive list of matches to be printed.
+//
+// ** How to have bash accept completions from a binary:
+// Bash requires that it be informed about each command that programmatic
+// completion should be enabled for.  Example addition to a .bashrc
+// file would be (your path to gflags_completions.sh file may differ):
+
+/*
+$ complete -o bashdefault -o default -o nospace -C                            \
+ '/home/build/eng/bash/bash_completions.sh --tab_completion_columns $COLUMNS' \
+  time  env  binary_name  another_binary  [...]
+*/
+
+// This would allow the following to work:
+//   $ /path/to/binary_name --vmodule<TAB>
+// Or:
+//   $ ./bin/path/another_binary --gfs_u<TAB>
+// (etc)
+//
+// Sadly, it appears that bash gives no easy way to force this behavior for
+// all commands.  That's where the "time" in the above example comes in.
+// If you haven't specifically added a command to the list of completion
+// supported commands, you can still get completions by prefixing the
+// entire command with "env".
+//   $ env /some/brand/new/binary --vmod<TAB>
+// Assuming that "binary" is a newly compiled binary, this should still
+// produce the expected completion output.
+
+
+#ifndef GFLAGS_COMPLETIONS_H_
+#define GFLAGS_COMPLETIONS_H_
+
+namespace @GFLAGS_NAMESPACE@ {
+
+extern void HandleCommandLineCompletions(void);
+
+}
+
+#endif  // GFLAGS_COMPLETIONS_H_
diff --git a/third_party/gflags/src/gflags_completions.sh b/third_party/gflags/src/gflags_completions.sh
new file mode 100755
index 0000000..c5fb7e6
--- /dev/null
+++ b/third_party/gflags/src/gflags_completions.sh
@@ -0,0 +1,117 @@
+#!/bin/bash
+
+# Copyright (c) 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# ---
+# Author: Dave Nicponski
+#
+# This script is invoked by bash in response to a matching compspec.  When
+# this happens, bash calls this script using the command shown in the -C
+# block of the complete entry, but also appends 3 arguments.  They are:
+#   - The command being used for completion
+#   - The word being completed
+#   - The word preceding the completion word.
+#
+# Here's an example of how you might use this script:
+# $ complete -o bashdefault -o default -o nospace -C                         \
+#   '/usr/local/bin/gflags_completions.sh --tab_completion_columns $COLUMNS' \
+#   time  env  binary_name  another_binary  [...]
+
+# completion_word_index gets the index of the (N-1)th argument for
+# this command line.  completion_word gets the actual argument from
+# this command line at the (N-1)th position
+completion_word_index="$(($# - 1))"
+completion_word="${!completion_word_index}"
+
+# TODO(user): Replace this once gflags_completions.cc has
+# a bool parameter indicating unambiguously to hijack the process for
+# completion purposes.
+if [ -z "$completion_word" ]; then
+  # Until an empty value for the completion word stops being misunderstood
+  # by binaries, don't actually execute the binary or the process
+  # won't be hijacked!
+  exit 0
+fi
+
+# binary_index gets the index of the command being completed (which bash
+# places in the (N-2)nd position.  binary gets the actual command from
+# this command line at that (N-2)nd position
+binary_index="$(($# - 2))"
+binary="${!binary_index}"
+
+# For completions to be universal, we may have setup the compspec to
+# trigger on 'harmless pass-through' commands, like 'time' or 'env'.
+# If the command being completed is one of those two, we'll need to
+# identify the actual command being executed.  To do this, we need
+# the actual command line that the <TAB> was pressed on.  Bash helpfully
+# places this in the $COMP_LINE variable.
+if [ "$binary" == "time" ] || [ "$binary" == "env" ]; then
+  # we'll assume that the first 'argument' is actually the
+  # binary
+
+
+  # TODO(user): This is not perfect - the 'env' command, for instance,
+  #   is allowed to have options between the 'env' and 'the command to
+  #   be executed'.  For example, consider:
+  # $ env FOO="bar"  bin/do_something  --help<TAB>
+  # In this case, we'll mistake the FOO="bar" portion as the binary.
+  #   Perhaps we should continuing consuming leading words until we
+  #   either run out of words, or find a word that is a valid file
+  #   marked as executable.  I can't think of any reason this wouldn't
+  #   work.
+
+  # Break up the 'original command line' (not this script's command line,
+  # rather the one the <TAB> was pressed on) and find the second word.
+  parts=( ${COMP_LINE} )
+  binary=${parts[1]}
+fi
+
+# Build the command line to use for completion.  Basically it involves
+# passing through all the arguments given to this script (except the 3
+# that bash added), and appending a '--tab_completion_word "WORD"' to
+# the arguments.
+params=""
+for ((i=1; i<=$(($# - 3)); ++i)); do 
+  params="$params \"${!i}\"";
+done
+params="$params --tab_completion_word \"$completion_word\""
+
+# TODO(user): Perhaps stash the output in a temporary file somewhere
+# in /tmp, and only cat it to stdout if the command returned a success
+# code, to prevent false positives
+
+# If we think we have a reasonable command to execute, then execute it
+# and hope for the best.
+candidate=$(type -p "$binary")
+if [ ! -z "$candidate" ]; then
+  eval "$candidate 2>/dev/null $params"
+elif [ -f "$binary" ] && [ -x "$binary" ]; then
+  eval "$binary 2>/dev/null $params"
+fi
diff --git a/third_party/gflags/src/gflags_declare.h.in b/third_party/gflags/src/gflags_declare.h.in
new file mode 100644
index 0000000..279db24
--- /dev/null
+++ b/third_party/gflags/src/gflags_declare.h.in
@@ -0,0 +1,141 @@
+// Copyright (c) 1999, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ---
+//
+// Revamped and reorganized by Craig Silverstein
+//
+// This is the file that should be included by any file which declares
+// command line flag.
+
+#ifndef GFLAGS_DECLARE_H_
+#define GFLAGS_DECLARE_H_
+
+
+// ---------------------------------------------------------------------------
+// Namespace of gflags library symbols.
+#define GFLAGS_NAMESPACE @GFLAGS_NAMESPACE@
+
+// ---------------------------------------------------------------------------
+// Windows DLL import/export.
+
+// We always want to import the symbols of the gflags library
+#ifndef GFLAGS_DLL_DECL
+#  if @GFLAGS_IS_A_DLL@ && defined(_MSC_VER)
+#    define GFLAGS_DLL_DECL __declspec(dllimport)
+#  else
+#    define GFLAGS_DLL_DECL
+#  endif
+#endif
+
+// We always want to import variables declared in user code
+#ifndef GFLAGS_DLL_DECLARE_FLAG
+#  ifdef _MSC_VER
+#    define GFLAGS_DLL_DECLARE_FLAG __declspec(dllimport)
+#  else
+#    define GFLAGS_DLL_DECLARE_FLAG
+#  endif
+#endif
+
+// ---------------------------------------------------------------------------
+// Flag types
+#include <string>
+#if @HAVE_STDINT_H@
+#  include <stdint.h>                   // the normal place uint32_t is defined
+#elif @HAVE_SYS_TYPES_H@
+#  include <sys/types.h>                // the normal place u_int32_t is defined
+#elif @HAVE_INTTYPES_H@
+#  include <inttypes.h>                 // a third place for uint32_t or u_int32_t
+#endif
+
+namespace GFLAGS_NAMESPACE {
+
+#if @GFLAGS_INTTYPES_FORMAT_C99@ // C99
+typedef int32_t          int32;
+typedef uint32_t         uint32;
+typedef int64_t          int64;
+typedef uint64_t         uint64;
+#elif @GFLAGS_INTTYPES_FORMAT_BSD@ // BSD
+typedef int32_t          int32;
+typedef u_int32_t        uint32;
+typedef int64_t          int64;
+typedef u_int64_t        uint64;
+#elif @GFLAGS_INTTYPES_FORMAT_VC7@ // Windows
+typedef __int32          int32;
+typedef unsigned __int32 uint32;
+typedef __int64          int64;
+typedef unsigned __int64 uint64;
+#else
+#  error Do not know how to define a 32-bit integer quantity on your system
+#endif
+
+} // namespace GFLAGS_NAMESPACE
+
+
+namespace fLS {
+
+// The meaning of "string" might be different between now and when the
+// macros below get invoked (e.g., if someone is experimenting with
+// other string implementations that get defined after this file is
+// included).  Save the current meaning now and use it in the macros.
+typedef std::string clstring;
+
+} // namespace fLS
+
+
+#define DECLARE_VARIABLE(type, shorttype, name) \
+  /* We always want to import declared variables, dll or no */ \
+  namespace fL##shorttype { extern GFLAGS_DLL_DECLARE_FLAG type FLAGS_##name; } \
+  using fL##shorttype::FLAGS_##name
+
+#define DECLARE_bool(name) \
+  DECLARE_VARIABLE(bool, B, name)
+
+#define DECLARE_int32(name) \
+  DECLARE_VARIABLE(::GFLAGS_NAMESPACE::int32, I, name)
+
+#define DECLARE_int64(name) \
+  DECLARE_VARIABLE(::GFLAGS_NAMESPACE::int64, I64, name)
+
+#define DECLARE_uint64(name) \
+  DECLARE_VARIABLE(::GFLAGS_NAMESPACE::uint64, U64, name)
+
+#define DECLARE_double(name) \
+  DECLARE_VARIABLE(double, D, name)
+
+#define DECLARE_string(name) \
+  /* We always want to import declared variables, dll or no */ \
+  namespace fLS { \
+  using ::fLS::clstring; \
+  extern GFLAGS_DLL_DECLARE_FLAG ::fLS::clstring& FLAGS_##name; \
+  } \
+  using fLS::FLAGS_##name
+
+
+#endif  // GFLAGS_DECLARE_H_
diff --git a/third_party/gflags/src/gflags_ns.h.in b/third_party/gflags/src/gflags_ns.h.in
new file mode 100644
index 0000000..f692666
--- /dev/null
+++ b/third_party/gflags/src/gflags_ns.h.in
@@ -0,0 +1,101 @@
+// Copyright (c) 2014, Andreas Schuh
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// -----------------------------------------------------------------------------
+// Imports the gflags library symbols into an alternative/deprecated namespace.
+
+#ifndef GFLAGS_GFLAGS_H_
+#  error The internal header gflags_@ns@.h may only be included by gflags.h
+#endif
+
+#ifndef GFLAGS_NS_@NS@_H_
+#define GFLAGS_NS_@NS@_H_
+
+
+namespace @ns@ {
+
+
+using GFLAGS_NAMESPACE::int32;
+using GFLAGS_NAMESPACE::uint32;
+using GFLAGS_NAMESPACE::int64;
+using GFLAGS_NAMESPACE::uint64;
+
+using GFLAGS_NAMESPACE::RegisterFlagValidator;
+using GFLAGS_NAMESPACE::CommandLineFlagInfo;
+using GFLAGS_NAMESPACE::GetAllFlags;
+using GFLAGS_NAMESPACE::ShowUsageWithFlags;
+using GFLAGS_NAMESPACE::ShowUsageWithFlagsRestrict;
+using GFLAGS_NAMESPACE::DescribeOneFlag;
+using GFLAGS_NAMESPACE::SetArgv;
+using GFLAGS_NAMESPACE::GetArgvs;
+using GFLAGS_NAMESPACE::GetArgv;
+using GFLAGS_NAMESPACE::GetArgv0;
+using GFLAGS_NAMESPACE::GetArgvSum;
+using GFLAGS_NAMESPACE::ProgramInvocationName;
+using GFLAGS_NAMESPACE::ProgramInvocationShortName;
+using GFLAGS_NAMESPACE::ProgramUsage;
+using GFLAGS_NAMESPACE::VersionString;
+using GFLAGS_NAMESPACE::GetCommandLineOption;
+using GFLAGS_NAMESPACE::GetCommandLineFlagInfo;
+using GFLAGS_NAMESPACE::GetCommandLineFlagInfoOrDie;
+using GFLAGS_NAMESPACE::FlagSettingMode;
+using GFLAGS_NAMESPACE::SET_FLAGS_VALUE;
+using GFLAGS_NAMESPACE::SET_FLAG_IF_DEFAULT;
+using GFLAGS_NAMESPACE::SET_FLAGS_DEFAULT;
+using GFLAGS_NAMESPACE::SetCommandLineOption;
+using GFLAGS_NAMESPACE::SetCommandLineOptionWithMode;
+using GFLAGS_NAMESPACE::FlagSaver;
+using GFLAGS_NAMESPACE::CommandlineFlagsIntoString;
+using GFLAGS_NAMESPACE::ReadFlagsFromString;
+using GFLAGS_NAMESPACE::AppendFlagsIntoFile;
+using GFLAGS_NAMESPACE::ReadFromFlagsFile;
+using GFLAGS_NAMESPACE::BoolFromEnv;
+using GFLAGS_NAMESPACE::Int32FromEnv;
+using GFLAGS_NAMESPACE::Int64FromEnv;
+using GFLAGS_NAMESPACE::Uint64FromEnv;
+using GFLAGS_NAMESPACE::DoubleFromEnv;
+using GFLAGS_NAMESPACE::StringFromEnv;
+using GFLAGS_NAMESPACE::SetUsageMessage;
+using GFLAGS_NAMESPACE::SetVersionString;
+using GFLAGS_NAMESPACE::ParseCommandLineNonHelpFlags;
+using GFLAGS_NAMESPACE::HandleCommandLineHelpFlags;
+using GFLAGS_NAMESPACE::AllowCommandLineReparsing;
+using GFLAGS_NAMESPACE::ReparseCommandLineNonHelpFlags;
+using GFLAGS_NAMESPACE::ShutDownCommandLineFlags;
+using GFLAGS_NAMESPACE::FlagRegisterer;
+
+#ifndef SWIG
+using GFLAGS_NAMESPACE::ParseCommandLineFlags;
+#endif
+
+
+} // namespace @ns@
+
+
+#endif  // GFLAGS_NS_@NS@_H_
diff --git a/third_party/gflags/src/gflags_reporting.cc b/third_party/gflags/src/gflags_reporting.cc
new file mode 100644
index 0000000..9cc41a7
--- /dev/null
+++ b/third_party/gflags/src/gflags_reporting.cc
@@ -0,0 +1,441 @@
+// Copyright (c) 1999, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ---
+//
+// Revamped and reorganized by Craig Silverstein
+//
+// This file contains code for handling the 'reporting' flags.  These
+// are flags that, when present, cause the program to report some
+// information and then exit.  --help and --version are the canonical
+// reporting flags, but we also have flags like --helpxml, etc.
+//
+// There's only one function that's meant to be called externally:
+// HandleCommandLineHelpFlags().  (Well, actually, ShowUsageWithFlags(),
+// ShowUsageWithFlagsRestrict(), and DescribeOneFlag() can be called
+// externally too, but there's little need for it.)  These are all
+// declared in the main gflags.h header file.
+//
+// HandleCommandLineHelpFlags() will check what 'reporting' flags have
+// been defined, if any -- the "help" part of the function name is a
+// bit misleading -- and do the relevant reporting.  It should be
+// called after all flag-values have been assigned, that is, after
+// parsing the command-line.
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include <string>
+#include <vector>
+
+#include "config.h"
+#include "gflags.h"
+#include "gflags_completions.h"
+#include "util.h"
+
+
+// The 'reporting' flags.  They all call gflags_exitfunc().
+DEFINE_bool  (help,        false, "show help on all flags [tip: all flags can have two dashes]");
+DEFINE_bool  (helpfull,    false, "show help on all flags -- same as -help");
+DEFINE_bool  (helpshort,   false, "show help on only the main module for this program");
+DEFINE_string(helpon,      "",    "show help on the modules named by this flag value");
+DEFINE_string(helpmatch,   "",    "show help on modules whose name contains the specified substr");
+DEFINE_bool  (helppackage, false, "show help on all modules in the main package");
+DEFINE_bool  (helpxml,     false, "produce an xml version of help");
+DEFINE_bool  (version,     false, "show version and build info and exit");
+
+
+namespace GFLAGS_NAMESPACE {
+
+
+using std::string;
+using std::vector;
+
+
+// --------------------------------------------------------------------
+// DescribeOneFlag()
+// DescribeOneFlagInXML()
+//    Routines that pretty-print info about a flag.  These use
+//    a CommandLineFlagInfo, which is the way the gflags
+//    API exposes static info about a flag.
+// --------------------------------------------------------------------
+
+static const int kLineLength = 80;
+
+static void AddString(const string& s,
+                      string* final_string, int* chars_in_line) {
+  const int slen = static_cast<int>(s.length());
+  if (*chars_in_line + 1 + slen >= kLineLength) {  // < 80 chars/line
+    *final_string += "\n      ";
+    *chars_in_line = 6;
+  } else {
+    *final_string += " ";
+    *chars_in_line += 1;
+  }
+  *final_string += s;
+  *chars_in_line += slen;
+}
+
+static string PrintStringFlagsWithQuotes(const CommandLineFlagInfo& flag,
+                                         const string& text, bool current) {
+  const char* c_string = (current ? flag.current_value.c_str() :
+                          flag.default_value.c_str());
+  if (strcmp(flag.type.c_str(), "string") == 0) {  // add quotes for strings
+    return StringPrintf("%s: \"%s\"", text.c_str(), c_string);
+  } else {
+    return StringPrintf("%s: %s", text.c_str(), c_string);
+  }
+}
+
+// Create a descriptive string for a flag.
+// Goes to some trouble to make pretty line breaks.
+string DescribeOneFlag(const CommandLineFlagInfo& flag) {
+  string main_part;
+  SStringPrintf(&main_part, "    -%s (%s)",
+                flag.name.c_str(),
+                flag.description.c_str());
+  const char* c_string = main_part.c_str();
+  int chars_left = static_cast<int>(main_part.length());
+  string final_string = "";
+  int chars_in_line = 0;  // how many chars in current line so far?
+  while (1) {
+    assert(chars_left == strlen(c_string));  // Unless there's a \0 in there?
+    const char* newline = strchr(c_string, '\n');
+    if (newline == NULL && chars_in_line+chars_left < kLineLength) {
+      // The whole remainder of the string fits on this line
+      final_string += c_string;
+      chars_in_line += chars_left;
+      break;
+    }
+    if (newline != NULL && newline - c_string < kLineLength - chars_in_line) {
+      int n = static_cast<int>(newline - c_string);
+      final_string.append(c_string, n);
+      chars_left -= n + 1;
+      c_string += n + 1;
+    } else {
+      // Find the last whitespace on this 80-char line
+      int whitespace = kLineLength-chars_in_line-1;  // < 80 chars/line
+      while ( whitespace > 0 && !isspace(c_string[whitespace]) ) {
+        --whitespace;
+      }
+      if (whitespace <= 0) {
+        // Couldn't find any whitespace to make a line break.  Just dump the
+        // rest out!
+        final_string += c_string;
+        chars_in_line = kLineLength;  // next part gets its own line for sure!
+        break;
+      }
+      final_string += string(c_string, whitespace);
+      chars_in_line += whitespace;
+      while (isspace(c_string[whitespace]))  ++whitespace;
+      c_string += whitespace;
+      chars_left -= whitespace;
+    }
+    if (*c_string == '\0')
+      break;
+    StringAppendF(&final_string, "\n      ");
+    chars_in_line = 6;
+  }
+
+  // Append data type
+  AddString(string("type: ") + flag.type, &final_string, &chars_in_line);
+  // The listed default value will be the actual default from the flag
+  // definition in the originating source file, unless the value has
+  // subsequently been modified using SetCommandLineOptionWithMode() with mode
+  // SET_FLAGS_DEFAULT, or by setting FLAGS_foo = bar before ParseCommandLineFlags().
+  AddString(PrintStringFlagsWithQuotes(flag, "default", false), &final_string,
+            &chars_in_line);
+  if (!flag.is_default) {
+    AddString(PrintStringFlagsWithQuotes(flag, "currently", true),
+              &final_string, &chars_in_line);
+  }
+
+  StringAppendF(&final_string, "\n");
+  return final_string;
+}
+
+// Simple routine to xml-escape a string: escape & and < only.
+static string XMLText(const string& txt) {
+  string ans = txt;
+  for (string::size_type pos = 0; (pos = ans.find("&", pos)) != string::npos; )
+    ans.replace(pos++, 1, "&amp;");
+  for (string::size_type pos = 0; (pos = ans.find("<", pos)) != string::npos; )
+    ans.replace(pos++, 1, "&lt;");
+  return ans;
+}
+
+static void AddXMLTag(string* r, const char* tag, const string& txt) {
+  StringAppendF(r, "<%s>%s</%s>", tag, XMLText(txt).c_str(), tag);
+}
+
+
+static string DescribeOneFlagInXML(const CommandLineFlagInfo& flag) {
+  // The file and flagname could have been attributes, but default
+  // and meaning need to avoid attribute normalization.  This way it
+  // can be parsed by simple programs, in addition to xml parsers.
+  string r("<flag>");
+  AddXMLTag(&r, "file", flag.filename);
+  AddXMLTag(&r, "name", flag.name);
+  AddXMLTag(&r, "meaning", flag.description);
+  AddXMLTag(&r, "default", flag.default_value);
+  AddXMLTag(&r, "current", flag.current_value);
+  AddXMLTag(&r, "type", flag.type);
+  r += "</flag>";
+  return r;
+}
+
+// --------------------------------------------------------------------
+// ShowUsageWithFlags()
+// ShowUsageWithFlagsRestrict()
+// ShowXMLOfFlags()
+//    These routines variously expose the registry's list of flag
+//    values.  ShowUsage*() prints the flag-value information
+//    to stdout in a user-readable format (that's what --help uses).
+//    The Restrict() version limits what flags are shown.
+//    ShowXMLOfFlags() prints the flag-value information to stdout
+//    in a machine-readable format.  In all cases, the flags are
+//    sorted: first by filename they are defined in, then by flagname.
+// --------------------------------------------------------------------
+
+static const char* Basename(const char* filename) {
+  const char* sep = strrchr(filename, PATH_SEPARATOR);
+  return sep ? sep + 1 : filename;
+}
+
+static string Dirname(const string& filename) {
+  string::size_type sep = filename.rfind(PATH_SEPARATOR);
+  return filename.substr(0, (sep == string::npos) ? 0 : sep);
+}
+
+// Test whether a filename contains at least one of the substrings.
+static bool FileMatchesSubstring(const string& filename,
+                                 const vector<string>& substrings) {
+  for (vector<string>::const_iterator target = substrings.begin();
+       target != substrings.end();
+       ++target) {
+    if (strstr(filename.c_str(), target->c_str()) != NULL)
+      return true;
+    // If the substring starts with a '/', that means that we want
+    // the string to be at the beginning of a directory component.
+    // That should match the first directory component as well, so
+    // we allow '/foo' to match a filename of 'foo'.
+    if (!target->empty() && (*target)[0] == PATH_SEPARATOR &&
+        strncmp(filename.c_str(), target->c_str() + 1,
+                strlen(target->c_str() + 1)) == 0)
+      return true;
+  }
+  return false;
+}
+
+// Show help for every filename which matches any of the target substrings.
+// If substrings is empty, shows help for every file. If a flag's help message
+// has been stripped (e.g. by adding '#define STRIP_FLAG_HELP 1'
+// before including gflags/gflags.h), then this flag will not be displayed
+// by '--help' and its variants.
+static void ShowUsageWithFlagsMatching(const char *argv0,
+                                       const vector<string> &substrings) {
+  fprintf(stdout, "%s: %s\n", Basename(argv0), ProgramUsage());
+
+  vector<CommandLineFlagInfo> flags;
+  GetAllFlags(&flags);           // flags are sorted by filename, then flagname
+
+  string last_filename;          // so we know when we're at a new file
+  bool first_directory = true;   // controls blank lines between dirs
+  bool found_match = false;      // stays false iff no dir matches restrict
+  for (vector<CommandLineFlagInfo>::const_iterator flag = flags.begin();
+       flag != flags.end();
+       ++flag) {
+    if (substrings.empty() ||
+        FileMatchesSubstring(flag->filename, substrings)) {
+      // If the flag has been stripped, pretend that it doesn't exist.
+      if (flag->description == kStrippedFlagHelp) continue;
+      found_match = true;     // this flag passed the match!
+      if (flag->filename != last_filename) {                      // new file
+        if (Dirname(flag->filename) != Dirname(last_filename)) {  // new dir!
+          if (!first_directory)
+            fprintf(stdout, "\n\n");   // put blank lines between directories
+          first_directory = false;
+        }
+        fprintf(stdout, "\n  Flags from %s:\n", flag->filename.c_str());
+        last_filename = flag->filename;
+      }
+      // Now print this flag
+      fprintf(stdout, "%s", DescribeOneFlag(*flag).c_str());
+    }
+  }
+  if (!found_match && !substrings.empty()) {
+    fprintf(stdout, "\n  No modules matched: use -help\n");
+  }
+}
+
+void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict) {
+  vector<string> substrings;
+  if (restrict != NULL && *restrict != '\0') {
+    substrings.push_back(restrict);
+  }
+  ShowUsageWithFlagsMatching(argv0, substrings);
+}
+
+void ShowUsageWithFlags(const char *argv0) {
+  ShowUsageWithFlagsRestrict(argv0, "");
+}
+
+// Convert the help, program, and usage to xml.
+static void ShowXMLOfFlags(const char *prog_name) {
+  vector<CommandLineFlagInfo> flags;
+  GetAllFlags(&flags);   // flags are sorted: by filename, then flagname
+
+  // XML.  There is no corresponding schema yet
+  fprintf(stdout, "<?xml version=\"1.0\"?>\n");
+  // The document
+  fprintf(stdout, "<AllFlags>\n");
+  // the program name and usage
+  fprintf(stdout, "<program>%s</program>\n",
+          XMLText(Basename(prog_name)).c_str());
+  fprintf(stdout, "<usage>%s</usage>\n",
+          XMLText(ProgramUsage()).c_str());
+  // All the flags
+  for (vector<CommandLineFlagInfo>::const_iterator flag = flags.begin();
+       flag != flags.end();
+       ++flag) {
+    if (flag->description != kStrippedFlagHelp)
+      fprintf(stdout, "%s\n", DescribeOneFlagInXML(*flag).c_str());
+  }
+  // The end of the document
+  fprintf(stdout, "</AllFlags>\n");
+}
+
+// --------------------------------------------------------------------
+// ShowVersion()
+//    Called upon --version.  Prints build-related info.
+// --------------------------------------------------------------------
+
+static void ShowVersion() {
+  const char* version_string = VersionString();
+  if (version_string && *version_string) {
+    fprintf(stdout, "%s version %s\n",
+            ProgramInvocationShortName(), version_string);
+  } else {
+    fprintf(stdout, "%s\n", ProgramInvocationShortName());
+  }
+# if !defined(NDEBUG)
+  fprintf(stdout, "Debug build (NDEBUG not #defined)\n");
+# endif
+}
+
+static void AppendPrognameStrings(vector<string>* substrings,
+                                  const char* progname) {
+  string r("");
+  r += PATH_SEPARATOR;
+  r += progname;
+  substrings->push_back(r + ".");
+  substrings->push_back(r + "-main.");
+  substrings->push_back(r + "_main.");
+}
+
+// --------------------------------------------------------------------
+// HandleCommandLineHelpFlags()
+//    Checks all the 'reporting' commandline flags to see if any
+//    have been set.  If so, handles them appropriately.  Note
+//    that all of them, by definition, cause the program to exit
+//    if they trigger.
+// --------------------------------------------------------------------
+
+void HandleCommandLineHelpFlags() {
+  const char* progname = ProgramInvocationShortName();
+
+  HandleCommandLineCompletions();
+
+  vector<string> substrings;
+  AppendPrognameStrings(&substrings, progname);
+
+  if (FLAGS_helpshort) {
+    // show only flags related to this binary:
+    // E.g. for fileutil.cc, want flags containing   ... "/fileutil." cc
+    ShowUsageWithFlagsMatching(progname, substrings);
+    gflags_exitfunc(1);
+
+  } else if (FLAGS_help || FLAGS_helpfull) {
+    // show all options
+    ShowUsageWithFlagsRestrict(progname, "");   // empty restrict
+    gflags_exitfunc(1);
+
+  } else if (!FLAGS_helpon.empty()) {
+    string restrict = PATH_SEPARATOR + FLAGS_helpon + ".";
+    ShowUsageWithFlagsRestrict(progname, restrict.c_str());
+    gflags_exitfunc(1);
+
+  } else if (!FLAGS_helpmatch.empty()) {
+    ShowUsageWithFlagsRestrict(progname, FLAGS_helpmatch.c_str());
+    gflags_exitfunc(1);
+
+  } else if (FLAGS_helppackage) {
+    // Shows help for all files in the same directory as main().  We
+    // don't want to resort to looking at dirname(progname), because
+    // the user can pick progname, and it may not relate to the file
+    // where main() resides.  So instead, we search the flags for a
+    // filename like "/progname.cc", and take the dirname of that.
+    vector<CommandLineFlagInfo> flags;
+    GetAllFlags(&flags);
+    string last_package;
+    for (vector<CommandLineFlagInfo>::const_iterator flag = flags.begin();
+         flag != flags.end();
+         ++flag) {
+      if (!FileMatchesSubstring(flag->filename, substrings))
+        continue;
+      const string package = Dirname(flag->filename) + PATH_SEPARATOR;
+      if (package != last_package) {
+        ShowUsageWithFlagsRestrict(progname, package.c_str());
+        VLOG(7) << "Found package: " << package;
+        if (!last_package.empty()) {      // means this isn't our first pkg
+          LOG(WARNING) << "Multiple packages contain a file=" << progname;
+        }
+        last_package = package;
+      }
+    }
+    if (last_package.empty()) {   // never found a package to print
+      LOG(WARNING) << "Unable to find a package for file=" << progname;
+    }
+    gflags_exitfunc(1);
+
+  } else if (FLAGS_helpxml) {
+    ShowXMLOfFlags(progname);
+    gflags_exitfunc(1);
+
+  } else if (FLAGS_version) {
+    ShowVersion();
+    // Unlike help, we may be asking for version in a script, so return 0
+    gflags_exitfunc(0);
+
+  }
+}
+
+
+} // namespace GFLAGS_NAMESPACE
diff --git a/third_party/gflags/src/mutex.h b/third_party/gflags/src/mutex.h
new file mode 100644
index 0000000..0bdd9d5
--- /dev/null
+++ b/third_party/gflags/src/mutex.h
@@ -0,0 +1,351 @@
+// Copyright (c) 2007, Google Inc.
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// 
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// 
+// ---
+//
+// A simple mutex wrapper, supporting locks and read-write locks.
+// You should assume the locks are *not* re-entrant.
+//
+// This class is meant to be internal-only and should be wrapped by an
+// internal namespace.  Before you use this module, please give the
+// name of your internal namespace for this module.  Or, if you want
+// to expose it, you'll want to move it to the Google namespace.  We
+// cannot put this class in global namespace because there can be some
+// problems when we have multiple versions of Mutex in each shared object.
+//
+// NOTE: by default, we have #ifdef'ed out the TryLock() method.
+//       This is for two reasons:
+// 1) TryLock() under Windows is a bit annoying (it requires a
+//    #define to be defined very early).
+// 2) TryLock() is broken for NO_THREADS mode, at least in NDEBUG
+//    mode.
+// If you need TryLock(), and either these two caveats are not a
+// problem for you, or you're willing to work around them, then
+// feel free to #define GMUTEX_TRYLOCK, or to remove the #ifdefs
+// in the code below.
+//
+// CYGWIN NOTE: Cygwin support for rwlock seems to be buggy:
+//    http://www.cygwin.com/ml/cygwin/2008-12/msg00017.html
+// Because of that, we might as well use windows locks for
+// cygwin.  They seem to be more reliable than the cygwin pthreads layer.
+//
+// TRICKY IMPLEMENTATION NOTE:
+// This class is designed to be safe to use during
+// dynamic-initialization -- that is, by global constructors that are
+// run before main() starts.  The issue in this case is that
+// dynamic-initialization happens in an unpredictable order, and it
+// could be that someone else's dynamic initializer could call a
+// function that tries to acquire this mutex -- but that all happens
+// before this mutex's constructor has run.  (This can happen even if
+// the mutex and the function that uses the mutex are in the same .cc
+// file.)  Basically, because Mutex does non-trivial work in its
+// constructor, it's not, in the naive implementation, safe to use
+// before dynamic initialization has run on it.
+//
+// The solution used here is to pair the actual mutex primitive with a
+// bool that is set to true when the mutex is dynamically initialized.
+// (Before that it's false.)  Then we modify all mutex routines to
+// look at the bool, and not try to lock/unlock until the bool makes
+// it to true (which happens after the Mutex constructor has run.)
+//
+// This works because before main() starts -- particularly, during
+// dynamic initialization -- there are no threads, so a) it's ok that
+// the mutex operations are a no-op, since we don't need locking then
+// anyway; and b) we can be quite confident our bool won't change
+// state between a call to Lock() and a call to Unlock() (that would
+// require a global constructor in one translation unit to call Lock()
+// and another global constructor in another translation unit to call
+// Unlock() later, which is pretty perverse).
+//
+// That said, it's tricky, and can conceivably fail; it's safest to
+// avoid trying to acquire a mutex in a global constructor, if you
+// can.  One way it can fail is that a really smart compiler might
+// initialize the bool to true at static-initialization time (too
+// early) rather than at dynamic-initialization time.  To discourage
+// that, we set is_safe_ to true in code (not the constructor
+// colon-initializer) and set it to true via a function that always
+// evaluates to true, but that the compiler can't know always
+// evaluates to true.  This should be good enough.
+//
+// A related issue is code that could try to access the mutex
+// after it's been destroyed in the global destructors (because
+// the Mutex global destructor runs before some other global
+// destructor, that tries to acquire the mutex).  The way we
+// deal with this is by taking a constructor arg that global
+// mutexes should pass in, that causes the destructor to do no
+// work.  We still depend on the compiler not doing anything
+// weird to a Mutex's memory after it is destroyed, but for a
+// static global variable, that's pretty safe.
+
+#ifndef GFLAGS_MUTEX_H_
+#define GFLAGS_MUTEX_H_
+
+#include "gflags_declare.h"     // to figure out pthreads support
+
+#if defined(NO_THREADS)
+  typedef int MutexType;        // to keep a lock-count
+#elif defined(OS_WINDOWS)
+# ifndef WIN32_LEAN_AND_MEAN
+#   define WIN32_LEAN_AND_MEAN  // We only need minimal includes
+# endif
+# ifndef NOMINMAX
+#   define NOMINMAX             // Don't want windows to override min()/max()
+# endif
+# ifdef GMUTEX_TRYLOCK
+  // We need Windows NT or later for TryEnterCriticalSection().  If you
+  // don't need that functionality, you can remove these _WIN32_WINNT
+  // lines, and change TryLock() to assert(0) or something.
+#   ifndef _WIN32_WINNT
+#     define _WIN32_WINNT 0x0400
+#   endif
+# endif
+# include <windows.h>
+  typedef CRITICAL_SECTION MutexType;
+#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
+  // Needed for pthread_rwlock_*.  If it causes problems, you could take it
+  // out, but then you'd have to unset HAVE_RWLOCK (at least on linux -- it
+  // *does* cause problems for FreeBSD, or MacOSX, but isn't needed
+  // for locking there.)
+# ifdef __linux__
+#   if _XOPEN_SOURCE < 500      // including not being defined at all
+#     undef _XOPEN_SOURCE
+#     define _XOPEN_SOURCE 500  // may be needed to get the rwlock calls
+#   endif
+# endif
+# include <pthread.h>
+  typedef pthread_rwlock_t MutexType;
+#elif defined(HAVE_PTHREAD)
+# include <pthread.h>
+  typedef pthread_mutex_t MutexType;
+#else
+# error Need to implement mutex.h for your architecture, or #define NO_THREADS
+#endif
+
+#include <assert.h>
+#include <stdlib.h>      // for abort()
+
+#define MUTEX_NAMESPACE gflags_mutex_namespace
+
+namespace MUTEX_NAMESPACE {
+
+class Mutex {
+ public:
+  // This is used for the single-arg constructor
+  enum LinkerInitialized { LINKER_INITIALIZED };
+
+  // Create a Mutex that is not held by anybody.  This constructor is
+  // typically used for Mutexes allocated on the heap or the stack.
+  inline Mutex();
+  // This constructor should be used for global, static Mutex objects.
+  // It inhibits work being done by the destructor, which makes it
+  // safer for code that tries to acqiure this mutex in their global
+  // destructor.
+  inline Mutex(LinkerInitialized);
+
+  // Destructor
+  inline ~Mutex();
+
+  inline void Lock();    // Block if needed until free then acquire exclusively
+  inline void Unlock();  // Release a lock acquired via Lock()
+#ifdef GMUTEX_TRYLOCK
+  inline bool TryLock(); // If free, Lock() and return true, else return false
+#endif
+  // Note that on systems that don't support read-write locks, these may
+  // be implemented as synonyms to Lock() and Unlock().  So you can use
+  // these for efficiency, but don't use them anyplace where being able
+  // to do shared reads is necessary to avoid deadlock.
+  inline void ReaderLock();   // Block until free or shared then acquire a share
+  inline void ReaderUnlock(); // Release a read share of this Mutex
+  inline void WriterLock() { Lock(); }     // Acquire an exclusive lock
+  inline void WriterUnlock() { Unlock(); } // Release a lock from WriterLock()
+
+ private:
+  MutexType mutex_;
+  // We want to make sure that the compiler sets is_safe_ to true only
+  // when we tell it to, and never makes assumptions is_safe_ is
+  // always true.  volatile is the most reliable way to do that.
+  volatile bool is_safe_;
+  // This indicates which constructor was called.
+  bool destroy_;
+
+  inline void SetIsSafe() { is_safe_ = true; }
+
+  // Catch the error of writing Mutex when intending MutexLock.
+  Mutex(Mutex* /*ignored*/) {}
+  // Disallow "evil" constructors
+  Mutex(const Mutex&);
+  void operator=(const Mutex&);
+};
+
+// Now the implementation of Mutex for various systems
+#if defined(NO_THREADS)
+
+// When we don't have threads, we can be either reading or writing,
+// but not both.  We can have lots of readers at once (in no-threads
+// mode, that's most likely to happen in recursive function calls),
+// but only one writer.  We represent this by having mutex_ be -1 when
+// writing and a number > 0 when reading (and 0 when no lock is held).
+//
+// In debug mode, we assert these invariants, while in non-debug mode
+// we do nothing, for efficiency.  That's why everything is in an
+// assert.
+
+Mutex::Mutex() : mutex_(0) { }
+Mutex::Mutex(Mutex::LinkerInitialized) : mutex_(0) { }
+Mutex::~Mutex()            { assert(mutex_ == 0); }
+void Mutex::Lock()         { assert(--mutex_ == -1); }
+void Mutex::Unlock()       { assert(mutex_++ == -1); }
+#ifdef GMUTEX_TRYLOCK
+bool Mutex::TryLock()      { if (mutex_) return false; Lock(); return true; }
+#endif
+void Mutex::ReaderLock()   { assert(++mutex_ > 0); }
+void Mutex::ReaderUnlock() { assert(mutex_-- > 0); }
+
+#elif defined(OS_WINDOWS)
+
+Mutex::Mutex() : destroy_(true) {
+  InitializeCriticalSection(&mutex_);
+  SetIsSafe();
+}
+Mutex::Mutex(LinkerInitialized) : destroy_(false) {
+  InitializeCriticalSection(&mutex_);
+  SetIsSafe();
+}
+Mutex::~Mutex()            { if (destroy_) DeleteCriticalSection(&mutex_); }
+void Mutex::Lock()         { if (is_safe_) EnterCriticalSection(&mutex_); }
+void Mutex::Unlock()       { if (is_safe_) LeaveCriticalSection(&mutex_); }
+#ifdef GMUTEX_TRYLOCK
+bool Mutex::TryLock()      { return is_safe_ ?
+                                 TryEnterCriticalSection(&mutex_) != 0 : true; }
+#endif
+void Mutex::ReaderLock()   { Lock(); }      // we don't have read-write locks
+void Mutex::ReaderUnlock() { Unlock(); }
+
+#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
+
+#define SAFE_PTHREAD(fncall)  do {   /* run fncall if is_safe_ is true */  \
+  if (is_safe_ && fncall(&mutex_) != 0) abort();                           \
+} while (0)
+
+Mutex::Mutex() : destroy_(true) {
+  SetIsSafe();
+  if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) abort();
+}
+Mutex::Mutex(Mutex::LinkerInitialized) : destroy_(false) {
+  SetIsSafe();
+  if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) abort();
+}
+Mutex::~Mutex()       { if (destroy_) SAFE_PTHREAD(pthread_rwlock_destroy); }
+void Mutex::Lock()         { SAFE_PTHREAD(pthread_rwlock_wrlock); }
+void Mutex::Unlock()       { SAFE_PTHREAD(pthread_rwlock_unlock); }
+#ifdef GMUTEX_TRYLOCK
+bool Mutex::TryLock()      { return is_safe_ ?
+                               pthread_rwlock_trywrlock(&mutex_) == 0 : true; }
+#endif
+void Mutex::ReaderLock()   { SAFE_PTHREAD(pthread_rwlock_rdlock); }
+void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
+#undef SAFE_PTHREAD
+
+#elif defined(HAVE_PTHREAD)
+
+#define SAFE_PTHREAD(fncall)  do {   /* run fncall if is_safe_ is true */  \
+  if (is_safe_ && fncall(&mutex_) != 0) abort();                           \
+} while (0)
+
+Mutex::Mutex() : destroy_(true) {
+  SetIsSafe();
+  if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort();
+}
+Mutex::Mutex(Mutex::LinkerInitialized) : destroy_(false) {
+  SetIsSafe();
+  if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort();
+}
+Mutex::~Mutex()       { if (destroy_) SAFE_PTHREAD(pthread_mutex_destroy); }
+void Mutex::Lock()         { SAFE_PTHREAD(pthread_mutex_lock); }
+void Mutex::Unlock()       { SAFE_PTHREAD(pthread_mutex_unlock); }
+#ifdef GMUTEX_TRYLOCK
+bool Mutex::TryLock()      { return is_safe_ ?
+                                 pthread_mutex_trylock(&mutex_) == 0 : true; }
+#endif
+void Mutex::ReaderLock()   { Lock(); }
+void Mutex::ReaderUnlock() { Unlock(); }
+#undef SAFE_PTHREAD
+
+#endif
+
+// --------------------------------------------------------------------------
+// Some helper classes
+
+// MutexLock(mu) acquires mu when constructed and releases it when destroyed.
+class MutexLock {
+ public:
+  explicit MutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); }
+  ~MutexLock() { mu_->Unlock(); }
+ private:
+  Mutex * const mu_;
+  // Disallow "evil" constructors
+  MutexLock(const MutexLock&);
+  void operator=(const MutexLock&);
+};
+
+// ReaderMutexLock and WriterMutexLock do the same, for rwlocks
+class ReaderMutexLock {
+ public:
+  explicit ReaderMutexLock(Mutex *mu) : mu_(mu) { mu_->ReaderLock(); }
+  ~ReaderMutexLock() { mu_->ReaderUnlock(); }
+ private:
+  Mutex * const mu_;
+  // Disallow "evil" constructors
+  ReaderMutexLock(const ReaderMutexLock&);
+  void operator=(const ReaderMutexLock&);
+};
+
+class WriterMutexLock {
+ public:
+  explicit WriterMutexLock(Mutex *mu) : mu_(mu) { mu_->WriterLock(); }
+  ~WriterMutexLock() { mu_->WriterUnlock(); }
+ private:
+  Mutex * const mu_;
+  // Disallow "evil" constructors
+  WriterMutexLock(const WriterMutexLock&);
+  void operator=(const WriterMutexLock&);
+};
+
+// Catch bug where variable name is omitted, e.g. MutexLock (&mu);
+#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_decl_missing_var_name)
+#define ReaderMutexLock(x) COMPILE_ASSERT(0, rmutex_lock_decl_missing_var_name)
+#define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name)
+
+}  // namespace MUTEX_NAMESPACE
+
+using namespace MUTEX_NAMESPACE;
+
+#undef MUTEX_NAMESPACE
+
+#endif  /* #define GFLAGS_MUTEX_H__ */
diff --git a/third_party/gflags/src/util.h b/third_party/gflags/src/util.h
new file mode 100644
index 0000000..366e1be
--- /dev/null
+++ b/third_party/gflags/src/util.h
@@ -0,0 +1,373 @@
+// Copyright (c) 2011, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// ---
+//
+// Some generically useful utility routines that in google-land would
+// be their own projects.  We make a shortened version here.
+
+#ifndef GFLAGS_UTIL_H_
+#define GFLAGS_UTIL_H_
+
+#include "config.h"
+
+#include <assert.h>
+#include <config.h>
+#ifdef HAVE_INTTYPES_H
+#  include <inttypes.h>
+#endif
+#include <stdarg.h>     // for va_*
+#include <stdlib.h>
+#include <stdio.h>
+#include <iostream>
+#include <string>
+#include <errno.h>
+#ifdef HAVE_SYS_STAT_H
+#  include <sys/stat.h> // for mkdir
+#endif
+
+
+namespace GFLAGS_NAMESPACE {
+
+
+// This is used for unittests for death-testing.  It is defined in gflags.cc.
+extern GFLAGS_DLL_DECL void (*gflags_exitfunc)(int);
+
+// Work properly if either strtoll or strtoq is on this system.
+#if defined(strtoll) || defined(HAVE_STRTOLL)
+#  define strto64  strtoll
+#  define strtou64 strtoull
+#elif defined(HAVE_STRTOQ)
+#  define strto64  strtoq
+#  define strtou64 strtouq
+// Neither strtoll nor strtoq are defined.  I hope strtol works!
+#else
+#  define strto64  strtol
+#  define strtou64 strtoul
+#endif
+
+// If we have inttypes.h, it will have defined PRId32/etc for us.
+// If not, take our best guess.
+#ifndef PRId32
+#  define PRId32 "d"
+#endif
+#ifndef PRId64
+#  define PRId64 "lld"
+#endif
+#ifndef PRIu64
+#  define PRIu64 "llu"
+#endif
+
+typedef signed char int8;
+typedef unsigned char uint8;
+
+// -- utility macros ---------------------------------------------------------
+
+template <bool> struct CompileAssert {};
+#define COMPILE_ASSERT(expr, msg) \
+  typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
+
+// Returns the number of elements in an array.
+#define arraysize(arr) (sizeof(arr)/sizeof(*(arr)))
+
+
+// -- logging and testing ---------------------------------------------------
+
+// For now, we ignore the level for logging, and don't show *VLOG's at
+// all, except by hand-editing the lines below
+#define LOG(level)    std::cerr
+#define VLOG(level)   if (true) {} else std::cerr
+#define DVLOG(level)  if (true) {} else std::cerr
+
+// CHECK dies with a fatal error if condition is not true.  It is *not*
+// controlled by NDEBUG, so the check will be executed regardless of
+// compilation mode.  Therefore, it is safe to do things like:
+//    CHECK(fp->Write(x) == 4)
+// We allow stream-like objects after this for debugging, but they're ignored.
+#define EXPECT_TRUE(condition)                                  \
+  if (true) {                                                   \
+    if (!(condition)) {                                         \
+      fprintf(stderr, "Check failed: %s\n", #condition);        \
+      exit(1);                                                  \
+    }                                                           \
+  } else std::cerr << ""
+
+#define EXPECT_OP(op, val1, val2)                                       \
+  if (true) {                                                           \
+    if (!((val1) op (val2))) {                                          \
+      fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2);   \
+      exit(1);                                                          \
+    }                                                                   \
+  } else std::cerr << ""
+
+#define EXPECT_EQ(val1, val2) EXPECT_OP(==, val1, val2)
+#define EXPECT_NE(val1, val2) EXPECT_OP(!=, val1, val2)
+#define EXPECT_LE(val1, val2) EXPECT_OP(<=, val1, val2)
+#define EXPECT_LT(val1, val2) EXPECT_OP(< , val1, val2)
+#define EXPECT_GE(val1, val2) EXPECT_OP(>=, val1, val2)
+#define EXPECT_GT(val1, val2) EXPECT_OP(> , val1, val2)
+#define EXPECT_FALSE(cond)    EXPECT_TRUE(!(cond))
+
+// C99 declares isnan and isinf should be macros, so the #ifdef test
+// should be reliable everywhere.  Of course, it's not, but these
+// are testing pertty marginal functionality anyway, so it's ok to
+// not-run them even in situations they might, with effort, be made to work.
+#ifdef isnan  // Some compilers, like sun's for Solaris 10, don't define this
+#define EXPECT_NAN(arg)                                         \
+  do {                                                          \
+    if (!isnan(arg)) {                                          \
+      fprintf(stderr, "Check failed: isnan(%s)\n", #arg);       \
+      exit(1);                                                  \
+    }                                                           \
+  } while (0)
+#else
+#define EXPECT_NAN(arg)
+#endif
+
+#ifdef isinf  // Some compilers, like sun's for Solaris 10, don't define this
+#define EXPECT_INF(arg)                                         \
+  do {                                                          \
+    if (!isinf(arg)) {                                          \
+      fprintf(stderr, "Check failed: isinf(%s)\n", #arg);       \
+      exit(1);                                                  \
+    }                                                           \
+  } while (0)
+#else
+#define EXPECT_INF(arg)
+#endif
+
+#define EXPECT_DOUBLE_EQ(val1, val2)                                    \
+  do {                                                                  \
+    if (((val1) < (val2) - 0.001 || (val1) > (val2) + 0.001)) {         \
+      fprintf(stderr, "Check failed: %s == %s\n", #val1, #val2);        \
+      exit(1);                                                          \
+    }                                                                   \
+  } while (0)
+
+#define EXPECT_STREQ(val1, val2)                                        \
+  do {                                                                  \
+    if (strcmp((val1), (val2)) != 0) {                                  \
+      fprintf(stderr, "Check failed: streq(%s, %s)\n", #val1, #val2);   \
+      exit(1);                                                          \
+    }                                                                   \
+  } while (0)
+
+// Call this in a .cc file where you will later call RUN_ALL_TESTS in main().
+#define TEST_INIT                                                       \
+  static std::vector<void (*)()> g_testlist;  /* the tests to run */    \
+  static int RUN_ALL_TESTS() {                                          \
+    std::vector<void (*)()>::const_iterator it;                         \
+    for (it = g_testlist.begin(); it != g_testlist.end(); ++it) {       \
+      (*it)();   /* The test will error-exit if there's a problem. */   \
+    }                                                                   \
+    fprintf(stderr, "\nPassed %d tests\n\nPASS\n",                      \
+            static_cast<int>(g_testlist.size()));                       \
+    return 0;                                                           \
+  }
+
+// Note that this macro uses a FlagSaver to keep tests isolated.
+#define TEST(a, b)                                      \
+  struct Test_##a##_##b {                               \
+    Test_##a##_##b() { g_testlist.push_back(&Run); }    \
+    static void Run() {                                 \
+      FlagSaver fs;                                     \
+      fprintf(stderr, "Running test %s/%s\n", #a, #b);  \
+      RunTest();                                        \
+    }                                                   \
+    static void RunTest();                              \
+  };                                                    \
+  static Test_##a##_##b g_test_##a##_##b;               \
+  void Test_##a##_##b::RunTest()
+
+// This is a dummy class that eases the google->opensource transition.
+namespace testing {
+class Test {};
+}
+
+// Call this in a .cc file where you will later call EXPECT_DEATH
+#define EXPECT_DEATH_INIT                               \
+  static bool g_called_exit;                            \
+  static void CalledExit(int) { g_called_exit = true; }
+
+#define EXPECT_DEATH(fn, msg)                                           \
+  do {                                                                  \
+    g_called_exit = false;                                              \
+    gflags_exitfunc = &CalledExit;                            \
+    fn;                                                                 \
+    gflags_exitfunc = &exit;    /* set back to its default */ \
+    if (!g_called_exit) {                                               \
+      fprintf(stderr, "Function didn't die (%s): %s\n", msg, #fn);      \
+      exit(1);                                                          \
+    }                                                                   \
+  } while (0)
+
+#define GTEST_HAS_DEATH_TEST 1
+
+// -- path routines ----------------------------------------------------------
+
+// Tries to create the directory path as a temp-dir.  If it fails,
+// changes path to some directory it *can* create.
+#if defined(__MINGW32__)
+#include <io.h>
+inline void MakeTmpdir(std::string* path) {
+  if (!path->empty()) {
+	path->append("/gflags_unittest_testdir");
+	int err = mkdir(path->c_str());
+	if (err == 0 || errno == EEXIST) return;
+  }
+  // I had trouble creating a directory in /tmp from mingw
+  *path = "./gflags_unittest";
+  mkdir(path->c_str());
+}
+#elif defined(_MSC_VER)
+#include <direct.h>
+inline void MakeTmpdir(std::string* path) {
+  if (!path->empty()) {
+	int err = _mkdir(path->c_str());
+	if (err == 0 || errno == EEXIST) return;
+  }
+  char tmppath_buffer[1024];
+  int tmppath_len = GetTempPathA(sizeof(tmppath_buffer), tmppath_buffer);
+  assert(tmppath_len > 0 && tmppath_len < sizeof(tmppath_buffer));
+  assert(tmppath_buffer[tmppath_len - 1] == '\\');   // API guarantees it
+  *path = std::string(tmppath_buffer) + "gflags_unittest";
+  _mkdir(path->c_str());
+}
+#else
+inline void MakeTmpdir(std::string* path) {
+  if (!path->empty()) {
+	int err = mkdir(path->c_str(), 0755);
+	if (err == 0 || errno == EEXIST) return;
+  }
+  mkdir("/tmp/gflags_unittest", 0755);
+}
+#endif
+
+// -- string routines --------------------------------------------------------
+
+inline void InternalStringPrintf(std::string* output, const char* format,
+                                 va_list ap) {
+  char space[128];    // try a small buffer and hope it fits
+
+  // It's possible for methods that use a va_list to invalidate
+  // the data in it upon use.  The fix is to make a copy
+  // of the structure before using it and use that copy instead.
+  va_list backup_ap;
+  va_copy(backup_ap, ap);
+  int bytes_written = vsnprintf(space, sizeof(space), format, backup_ap);
+  va_end(backup_ap);
+
+  if ((bytes_written >= 0) && (static_cast<size_t>(bytes_written) < sizeof(space))) {
+    output->append(space, bytes_written);
+    return;
+  }
+
+  // Repeatedly increase buffer size until it fits.
+  int length = sizeof(space);
+  while (true) {
+    if (bytes_written < 0) {
+      // Older snprintf() behavior. :-(  Just try doubling the buffer size
+      length *= 2;
+    } else {
+      // We need exactly "bytes_written+1" characters
+      length = bytes_written+1;
+    }
+    char* buf = new char[length];
+
+    // Restore the va_list before we use it again
+    va_copy(backup_ap, ap);
+    bytes_written = vsnprintf(buf, length, format, backup_ap);
+    va_end(backup_ap);
+
+    if ((bytes_written >= 0) && (bytes_written < length)) {
+      output->append(buf, bytes_written);
+      delete[] buf;
+      return;
+    }
+    delete[] buf;
+  }
+}
+
+// Clears output before writing to it.
+inline void SStringPrintf(std::string* output, const char* format, ...) {
+  va_list ap;
+  va_start(ap, format);
+  output->clear();
+  InternalStringPrintf(output, format, ap);
+  va_end(ap);
+}
+
+inline void StringAppendF(std::string* output, const char* format, ...) {
+  va_list ap;
+  va_start(ap, format);
+  InternalStringPrintf(output, format, ap);
+  va_end(ap);
+}
+
+inline std::string StringPrintf(const char* format, ...) {
+  va_list ap;
+  va_start(ap, format);
+  std::string output;
+  InternalStringPrintf(&output, format, ap);
+  va_end(ap);
+  return output;
+}
+
+inline bool SafeGetEnv(const char *varname, std::string &valstr)
+{
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+	char  *val;
+	size_t sz;
+	if (_dupenv_s(&val, &sz, varname) != 0 || !val) return false;
+	valstr = val;
+	free(val);
+#else
+	const char * const val = getenv(varname);
+	if (!val) return false;
+	valstr = val;
+#endif
+	return true;
+}
+
+inline int SafeFOpen(FILE **fp, const char* fname, const char *mode)
+{
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+	return fopen_s(fp, fname, mode);
+#else
+	assert(fp != NULL);
+	*fp = fopen(fname, mode);
+    // errno only guaranteed to be set on failure
+	return ((*fp == NULL) ? errno : 0);
+#endif
+}
+
+
+} // namespace GFLAGS_NAMESPACE
+
+
+#endif  // GFLAGS_UTIL_H_
diff --git a/third_party/gflags/src/windows_port.cc b/third_party/gflags/src/windows_port.cc
new file mode 100644
index 0000000..9ccb630
--- /dev/null
+++ b/third_party/gflags/src/windows_port.cc
@@ -0,0 +1,75 @@
+/* Copyright (c) 2009, Google Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ---
+ * Author: Craig Silverstein
+ */
+
+#ifndef _WIN32
+#  error You should only be including windows/port.cc in a windows environment!
+#endif
+
+#include <string.h>    // for strlen(), memset(), memcmp()
+#include <assert.h>
+#include <stdarg.h>    // for va_list, va_start, va_end
+#include <windows.h>
+
+#include "windows_port.h"
+
+// These call the windows _vsnprintf, but always NUL-terminate.
+#if !defined(__MINGW32__) && !defined(__MINGW64__)  /* mingw already defines */
+
+#ifdef _MSC_VER
+#  pragma warning(push)
+#  pragma warning(disable: 4996) // ignore _vsnprintf security warning
+#endif
+int safe_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
+  if (size == 0)        // not even room for a \0?
+    return -1;          // not what C99 says to do, but what windows does
+  str[size-1] = '\0'; 
+  return _vsnprintf(str, size-1, format, ap);
+}
+#ifdef _MSC_VER
+#  pragma warning(pop)
+#endif
+
+#if _MSC_VER < 1900  // msvs 2015 finally includes snprintf
+
+int snprintf(char *str, size_t size, const char *format, ...) {
+  int r;
+  va_list ap;
+  va_start(ap, format);
+  r = vsnprintf(str, size, format, ap);
+  va_end(ap);
+  return r;
+}
+
+#endif
+
+#endif  /* #if !defined(__MINGW32__) && !defined(__MINGW64__) */
diff --git a/third_party/gflags/src/windows_port.h b/third_party/gflags/src/windows_port.h
new file mode 100644
index 0000000..c8ff24f
--- /dev/null
+++ b/third_party/gflags/src/windows_port.h
@@ -0,0 +1,127 @@
+/* Copyright (c) 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ---
+ * Author: Craig Silverstein
+ *
+ * These are some portability typedefs and defines to make it a bit
+ * easier to compile this code under VC++.
+ *
+ * Several of these are taken from glib:
+ *    http://developer.gnome.org/doc/API/glib/glib-windows-compatability-functions.html
+ */
+
+#ifndef GFLAGS_WINDOWS_PORT_H_
+#define GFLAGS_WINDOWS_PORT_H_
+
+#include "config.h"
+
+// This must be defined before the windows.h is included.
+// It's needed for mutex.h, to give access to the TryLock method.
+#  if !defined(_WIN32_WINNT) && !(defined( __MINGW32__) || defined(__MINGW64__))
+#    define _WIN32_WINNT 0x0400
+#  endif
+// We always want minimal includes
+#ifndef WIN32_LEAN_AND_MEAN
+#  define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include <direct.h>          /* for mkdir */
+#include <stdlib.h>          /* for _putenv, getenv */
+#include <stdio.h>           /* need this to override stdio's snprintf, also defines _unlink used by unit tests */
+#include <stdarg.h>          /* util.h uses va_copy */
+#include <string.h>          /* for _stricmp and _strdup */
+
+/* We can't just use _vsnprintf and _snprintf as drop-in-replacements,
+ * because they don't always NUL-terminate. :-(  We also can't use the
+ * name vsnprintf, since windows defines that (but not snprintf (!)).
+ */
+#if !defined(__MINGW32__) && !defined(__MINGW64__)  /* mingw already defines */
+extern GFLAGS_DLL_DECL int snprintf(char *str, size_t size,
+                                       const char *format, ...);
+extern int GFLAGS_DLL_DECL safe_vsnprintf(char *str, size_t size,
+                                             const char *format, va_list ap);
+#define vsnprintf(str, size, format, ap)  safe_vsnprintf(str, size, format, ap)
+#define va_copy(dst, src)  (dst) = (src)
+#endif  /* #if !defined(__MINGW32__) && !defined(__MINGW64__) */
+
+#ifdef _MSC_VER
+#  pragma warning(push)
+#  pragma warning(disable: 4996) // ignore getenv security warning
+#endif
+inline void setenv(const char* name, const char* value, int) {
+  // In windows, it's impossible to set a variable to the empty string.
+  // We handle this by setting it to "0" and the NUL-ing out the \0.
+  // That is, we putenv("FOO=0") and then find out where in memory the
+  // putenv wrote "FOO=0", and change it in-place to "FOO=\0".
+  // c.f. http://svn.apache.org/viewvc/stdcxx/trunk/tests/src/environ.cpp?r1=611451&r2=637508&pathrev=637508
+  static const char* const kFakeZero = "0";
+  if (*value == '\0')
+    value = kFakeZero;
+  // Apparently the semantics of putenv() is that the input
+  // must live forever, so we leak memory here. :-(
+  const size_t nameval_len = strlen(name) + 1 + strlen(value) + 1;
+  char* nameval = reinterpret_cast<char*>(malloc(nameval_len));
+  snprintf(nameval, nameval_len, "%s=%s", name, value);
+  _putenv(nameval);
+  if (value == kFakeZero) {
+    nameval[nameval_len - 2] = '\0';   // works when putenv() makes no copy
+    if (*getenv(name) != '\0')
+      *getenv(name) = '\0';            // works when putenv() copies nameval
+  }
+}
+#ifdef _MSC_VER
+#  pragma warning(pop)
+#endif
+
+#define strcasecmp _stricmp
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+#define strdup   _strdup
+#define unlink   _unlink
+#endif
+
+#define PRId32  "d"
+#define PRIu32  "u"
+#define PRId64  "I64d"
+#define PRIu64  "I64u"
+
+#if !defined(__MINGW32__) && !defined(__MINGW64__)
+#define strtoq   _strtoi64
+#define strtouq  _strtoui64
+#define strtoll  _strtoi64
+#define strtoull _strtoui64
+#define atoll    _atoi64
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+#endif  /* GFLAGS_WINDOWS_PORT_H_ */
diff --git a/third_party/gflags/test/CMakeLists.txt b/third_party/gflags/test/CMakeLists.txt
new file mode 100644
index 0000000..77b582f
--- /dev/null
+++ b/third_party/gflags/test/CMakeLists.txt
@@ -0,0 +1,205 @@
+## gflags tests
+
+# ----------------------------------------------------------------------------
+# output directories
+set (CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin")
+set (CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
+set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
+
+# set working directory of test commands
+set (GFLAGS_FLAGFILES_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
+
+# ----------------------------------------------------------------------------
+# common include directories and link libraries
+include_directories ("${CMAKE_CURRENT_SOURCE_DIR}")
+include_directories ("${gflags_SOURCE_DIR}/src")
+include_directories ("${gflags_BINARY_DIR}/include")
+include_directories ("${gflags_BINARY_DIR}/include/gflags")
+
+if (BUILD_SHARED_LIBS)
+  set (type shared)
+else ()
+  set (type static)
+endif ()
+if (BUILD_gflags_LIB)
+  link_libraries (gflags-${type})
+else ()
+  link_libraries (gflags_nothreads-${type})
+endif ()
+
+# ----------------------------------------------------------------------------
+# STRIP_FLAG_HELP
+add_executable (gflags_strip_flags_test gflags_strip_flags_test.cc)
+# Make sure the --help output doesn't print the stripped text.
+add_gflags_test (strip_flags_help 1 "" "This text should be stripped out" gflags_strip_flags_test --help)
+# Make sure the stripped text isn't in the binary at all.
+add_test (
+  NAME strip_flags_binary
+  COMMAND "${CMAKE_COMMAND}" "-DBINARY=$<TARGET_FILE:gflags_strip_flags_test>"
+          -P "${CMAKE_CURRENT_SOURCE_DIR}/gflags_strip_flags_test.cmake"
+)
+
+# ----------------------------------------------------------------------------
+# unit tests
+configure_file (gflags_unittest.cc gflags_unittest-main.cc COPYONLY)
+configure_file (gflags_unittest.cc gflags_unittest_main.cc COPYONLY)
+
+add_executable (gflags_unittest      gflags_unittest.cc)
+add_executable (gflags_unittest-main gflags_unittest-main.cc)
+add_executable (gflags_unittest_main gflags_unittest_main.cc)
+
+if (OS_WINDOWS)
+  set (SLASH "\\\\")
+else ()
+  set (SLASH "/")
+endif ()
+
+# First, just make sure the  gflags_unittest  works as-is
+add_gflags_test(unittest 0 "" "" gflags_unittest)
+
+# --help should show all flags, including flags from gflags_reporting
+add_gflags_test(help-reporting 1 "${SLASH}gflags_reporting.cc:" ""  gflags_unittest  --help)
+
+# Make sure that --help prints even very long helpstrings.
+add_gflags_test(long-helpstring 1 "end of a long helpstring" ""  gflags_unittest  --help)
+
+# Make sure --help reflects flag changes made before flag-parsing
+add_gflags_test(changed_bool1 1 "-changed_bool1 (changed) type: bool default: true" ""  gflags_unittest  --help)
+add_gflags_test(changed_bool2 1 "-changed_bool2 (changed) type: bool default: false currently: true" ""  gflags_unittest  --help)
+# And on the command-line, too
+add_gflags_test(changeable_string_var 1 "-changeable_string_var () type: string default: \"1\" currently: \"2\"" ""  gflags_unittest  --changeable_string_var 2 --help)
+
+# --nohelp and --help=false should be as if we didn't say anything
+add_gflags_test(nohelp     0 "PASS" ""  gflags_unittest  --nohelp)
+add_gflags_test(help=false 0 "PASS" ""  gflags_unittest  --help=false)
+
+# --helpfull is the same as help
+add_gflags_test(helpfull 1 "${SLASH}gflags_reporting.cc:" ""  gflags_unittest  --helpfull)
+
+# --helpshort should show only flags from the  gflags_unittest  itself
+add_gflags_test(helpshort 1 "${SLASH}gflags_unittest.cc:" "${SLASH}gflags_reporting.cc:"  gflags_unittest  --helpshort)
+
+# --helpshort should show the tldflag we created in the  gflags_unittest  dir
+add_gflags_test(helpshort-tldflag1 1 "tldflag1" "${SLASH}google.cc:"  gflags_unittest  --helpshort)
+add_gflags_test(helpshort-tldflag2 1 "tldflag2" "${SLASH}google.cc:"  gflags_unittest  --helpshort)
+
+# --helpshort should work if the main source file is suffixed with [_-]main
+add_gflags_test(helpshort-main 1 "${SLASH}gflags_unittest-main.cc:" "${SLASH}gflags_reporting.cc:" gflags_unittest-main --helpshort)
+add_gflags_test(helpshort_main 1 "${SLASH}gflags_unittest_main.cc:" "${SLASH}gflags_reporting.cc:" gflags_unittest_main --helpshort)
+
+# --helpon needs an argument
+add_gflags_test(helpon 1 "'--helpon' is missing its argument; flag description: show help on" ""  gflags_unittest  --helpon)
+# --helpon argument indicates what file we'll show args from
+add_gflags_test(helpon=gflags 1 "${SLASH}gflags.cc:" "${SLASH}gflags_unittest.cc:"  gflags_unittest  --helpon=gflags)
+# another way of specifying the argument
+add_gflags_test(helpon_gflags 1 "${SLASH}gflags.cc:" "${SLASH}gflags_unittest.cc:"  gflags_unittest  --helpon gflags)
+# test another argument
+add_gflags_test(helpon=gflags_unittest 1 "${SLASH}gflags_unittest.cc:" "${SLASH}gflags.cc:"  gflags_unittest  --helpon=gflags_unittest)
+
+# helpmatch is like helpon but takes substrings
+add_gflags_test(helpmatch_reporting 1 "${SLASH}gflags_reporting.cc:" "${SLASH}gflags_unittest.cc:"  gflags_unittest  -helpmatch reporting)
+add_gflags_test(helpmatch=unittest  1 "${SLASH}gflags_unittest.cc:" "${SLASH}gflags.cc:"  gflags_unittest  -helpmatch=unittest)
+
+# if no flags are found with helpmatch or helpon, suggest --help
+add_gflags_test(helpmatch=nosuchsubstring 1 "No modules matched" "${SLASH}gflags_unittest.cc:"  gflags_unittest  -helpmatch=nosuchsubstring)
+add_gflags_test(helpon=nosuchmodule       1 "No modules matched" "${SLASH}gflags_unittest.cc:"  gflags_unittest  -helpon=nosuchmodule)
+
+# helppackage shows all the flags in the same dir as this unittest
+# --help should show all flags, including flags from google.cc
+add_gflags_test(helppackage 1 "${SLASH}gflags_reporting.cc:" ""  gflags_unittest  --helppackage)
+
+# xml!
+add_gflags_test(helpxml 1 "${SLASH}gflags_unittest.cc</file>" "${SLASH}gflags_unittest.cc:"  gflags_unittest  --helpxml)
+
+# just print the version info and exit
+add_gflags_test(version-1 0 "gflags_unittest"      "${SLASH}gflags_unittest.cc:"  gflags_unittest  --version)
+add_gflags_test(version-2 0 "version test_version" "${SLASH}gflags_unittest.cc:"  gflags_unittest  --version)
+
+# --undefok is a fun flag...
+add_gflags_test(undefok-1 1 "unknown command line flag 'foo'" ""  gflags_unittest  --undefok= --foo --unused_bool)
+add_gflags_test(undefok-2 0 "PASS" ""  gflags_unittest  --undefok=foo --foo --unused_bool)
+# If you say foo is ok to be undefined, we'll accept --nofoo as well
+add_gflags_test(undefok-3 0 "PASS" ""  gflags_unittest  --undefok=foo --nofoo --unused_bool)
+# It's ok if the foo is in the middle
+add_gflags_test(undefok-4 0 "PASS" ""  gflags_unittest  --undefok=fee,fi,foo,fum --foo --unused_bool)
+# But the spelling has to be just right...
+add_gflags_test(undefok-5 1 "unknown command line flag 'foo'" ""  gflags_unittest  --undefok=fo --foo --unused_bool)
+add_gflags_test(undefok-6 1 "unknown command line flag 'foo'" ""  gflags_unittest  --undefok=foot --foo --unused_bool)
+
+# See if we can successfully load our flags from the flagfile
+add_gflags_test(flagfile.1 0 "gflags_unittest" "${SLASH}gflags_unittest.cc:"  gflags_unittest  "--flagfile=flagfile.1")
+add_gflags_test(flagfile.2 0 "PASS" ""  gflags_unittest  "--flagfile=flagfile.2")
+add_gflags_test(flagfile.3 0 "PASS" ""  gflags_unittest  "--flagfile=flagfile.3")
+
+# Also try to load flags from the environment
+add_gflags_test(fromenv=version      0 "gflags_unittest" "${SLASH}gflags_unittest.cc:"  gflags_unittest  --fromenv=version)
+add_gflags_test(tryfromenv=version   0 "gflags_unittest" "${SLASH}gflags_unittest.cc:"  gflags_unittest  --tryfromenv=version)
+add_gflags_test(fromenv=help         0 "PASS" ""  gflags_unittest  --fromenv=help)
+add_gflags_test(tryfromenv=help      0 "PASS" ""  gflags_unittest  --tryfromenv=help)
+add_gflags_test(fromenv=helpfull     1 "helpfull not found in environment" ""  gflags_unittest  --fromenv=helpfull)
+add_gflags_test(tryfromenv=helpfull  0 "PASS" ""  gflags_unittest  --tryfromenv=helpfull)
+add_gflags_test(tryfromenv=undefok   0 "PASS" ""  gflags_unittest  --tryfromenv=undefok --foo)
+add_gflags_test(tryfromenv=weirdo    1 "unknown command line flag" ""  gflags_unittest  --tryfromenv=weirdo)
+add_gflags_test(tryfromenv-multiple  0 "gflags_unittest" "${SLASH}gflags_unittest.cc:"  gflags_unittest  --tryfromenv=test_bool,version,unused_bool)
+add_gflags_test(fromenv=test_bool    1 "not found in environment" ""  gflags_unittest  --fromenv=test_bool)
+add_gflags_test(fromenv=test_bool-ok 1 "unknown command line flag" ""  gflags_unittest  --fromenv=test_bool,ok)
+# Here, the --version overrides the fromenv
+add_gflags_test(version-overrides-fromenv 0 "gflags_unittest" "${SLASH}gflags_unittest.cc:"  gflags_unittest  --fromenv=test_bool,version,ok)
+
+# Make sure -- by itself stops argv processing
+add_gflags_test(dashdash 0 "PASS" ""  gflags_unittest  -- --help)
+
+# And we should die if the flag value doesn't pass the validator
+add_gflags_test(always_fail 1 "ERROR: failed validation of new value 'true' for flag 'always_fail'" ""  gflags_unittest  --always_fail)
+
+# And if locking in validators fails
+# TODO(andreas): Worked on Windows 7 Release configuration, but causes
+#                debugger abort() intervention in case of Debug configuration.
+#add_gflags_test(deadlock_if_cant_lock 0 "PASS" ""  gflags_unittest  --deadlock_if_cant_lock)
+
+# ----------------------------------------------------------------------------
+# use gflags_declare.h
+add_executable (gflags_declare_test gflags_declare_test.cc gflags_declare_flags.cc)
+
+add_test(NAME gflags_declare COMMAND gflags_declare_test --message "Hello gflags!")
+set_tests_properties(gflags_declare PROPERTIES PASS_REGULAR_EXPRESSION "Hello gflags!")
+
+# ----------------------------------------------------------------------------
+# configure Python script which configures and builds a test project
+if (BUILD_NC_TESTS OR BUILD_CONFIG_TESTS)
+  find_package (PythonInterp)
+  if (NOT PYTHON_EXECUTABLE)
+    message (FATAL_ERROR "No Python installation found! It is required by the (negative) compilation tests."
+                         " Either install Python or set BUILD_NC_TESTS and BUILD_CONFIG_TESTS to FALSE.")
+  endif ()
+  set (TMPDIR "${PROJECT_BINARY_DIR}/Testing/Temporary")
+  configure_file (gflags_build.py.in "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/build.py" @ONLY)
+  function (add_gflags_build_test name srcdir expect_fail)
+    set (srcdir "${CMAKE_CURRENT_SOURCE_DIR}/${srcdir}")
+    add_test (
+      NAME    "${name}"
+      COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/build.py" 
+                    ${name} ${srcdir} ${expect_fail}
+    )
+  endfunction ()
+endif ()
+
+# ----------------------------------------------------------------------------
+# negative compilation tests
+option (BUILD_NC_TESTS "Request addition of negative compilation tests." OFF)
+mark_as_advanced (BUILD_NC_TESTS)
+if (BUILD_NC_TESTS)
+  add_gflags_build_test (nc_sanity               nc 0)
+  add_gflags_build_test (nc_swapped_args         nc 1)
+  add_gflags_build_test (nc_int_instead_of_bool  nc 1)
+  add_gflags_build_test (nc_bool_in_quotes       nc 1)
+  add_gflags_build_test (nc_define_string_with_0 nc 1)
+endif ()
+
+# ----------------------------------------------------------------------------
+# build configuration test
+option (BUILD_CONFIG_TESTS "Request addition of package configuration tests." OFF)
+mark_as_advanced (BUILD_CONFIG_TESTS)
+if (BUILD_CONFIG_TESTS)
+  add_gflags_build_test (cmake_config config 0)
+endif ()
diff --git a/third_party/gflags/test/config/CMakeLists.txt b/third_party/gflags/test/config/CMakeLists.txt
new file mode 100644
index 0000000..b5bc282
--- /dev/null
+++ b/third_party/gflags/test/config/CMakeLists.txt
@@ -0,0 +1,10 @@
+## gflags package configuration tests
+
+cmake_minimum_required (VERSION 2.8)
+
+project (gflags_${TEST_NAME})
+
+find_package (gflags REQUIRED)
+
+add_executable (foo main.cc)
+target_link_libraries (foo gflags)
diff --git a/third_party/gflags/test/config/main.cc b/third_party/gflags/test/config/main.cc
new file mode 100644
index 0000000..9b2b898
--- /dev/null
+++ b/third_party/gflags/test/config/main.cc
@@ -0,0 +1,12 @@
+#include <iostream>
+#include <gflags/gflags.h>
+
+DEFINE_string(message, "Hello World!", "The message to print");
+
+int main(int argc, char **argv)
+{
+  gflags::SetUsageMessage("Test CMake configuration of gflags library (gflags-config.cmake)");
+  gflags::ParseCommandLineFlags(&argc, &argv, true);
+  std::cout << FLAGS_message << std::endl;
+  return 0;
+}
diff --git a/third_party/gflags/test/config_for_unittests.h b/third_party/gflags/test/config_for_unittests.h
new file mode 100644
index 0000000..914571b
--- /dev/null
+++ b/third_party/gflags/test/config_for_unittests.h
@@ -0,0 +1,79 @@
+// Copyright (c) 2007, Google Inc.
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// 
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ---
+// All Rights Reserved.
+//
+//
+// This file is needed for windows -- unittests are not part of the
+// gflags dll, but still want to include config.h just like the
+// dll does, so they can use internal tools and APIs for testing.
+//
+// The problem is that config.h declares GFLAGS_DLL_DECL to be
+// for exporting symbols, but the unittest needs to *import* symbols
+// (since it's not the dll).
+//
+// The solution is to have this file, which is just like config.h but
+// sets GFLAGS_DLL_DECL to do a dllimport instead of a dllexport.
+//
+// The reason we need this extra GFLAGS_DLL_DECL_FOR_UNITTESTS
+// variable is in case people want to set GFLAGS_DLL_DECL explicitly
+// to something other than __declspec(dllexport).  In that case, they
+// may want to use something other than __declspec(dllimport) for the
+// unittest case.  For that, we allow folks to define both
+// GFLAGS_DLL_DECL and GFLAGS_DLL_DECL_FOR_UNITTESTS explicitly.
+//
+// NOTE: This file is equivalent to config.h on non-windows systems,
+// which never defined GFLAGS_DLL_DECL_FOR_UNITTESTS and always
+// define GFLAGS_DLL_DECL to the empty string.
+
+#include "config.h"
+
+#ifdef GFLAGS_DLL_DECL
+#  undef GFLAGS_DLL_DECL
+#endif
+#ifdef GFLAGS_DLL_DEFINE_FLAG
+#  undef GFLAGS_DLL_DEFINE_FLAG
+#endif
+#ifdef GFLAGS_DLL_DECLARE_FLAG
+#  undef GFLAGS_DLL_DECLARE_FLAG
+#endif
+
+#ifdef GFLAGS_DLL_DECL_FOR_UNITTESTS
+#  define GFLAGS_DLL_DECL  GFLAGS_DLL_DECL_FOR_UNITTESTS
+#else
+#  define GFLAGS_DLL_DECL  // if DLL_DECL_FOR_UNITTESTS isn't defined, use ""
+#endif
+
+// Import flags defined by gflags.cc
+#if GFLAGS_IS_A_DLL && defined(_MSC_VER)
+#  define GFLAGS_DLL_DECLARE_FLAG __declspec(dllimport)
+#else
+#  define GFLAGS_DLL_DECLARE_FLAG
+#endif
\ No newline at end of file
diff --git a/third_party/gflags/test/flagfile.1 b/third_party/gflags/test/flagfile.1
new file mode 100644
index 0000000..e0f9217
--- /dev/null
+++ b/third_party/gflags/test/flagfile.1
@@ -0,0 +1 @@
+--version
\ No newline at end of file
diff --git a/third_party/gflags/test/flagfile.2 b/third_party/gflags/test/flagfile.2
new file mode 100644
index 0000000..864f8e8
--- /dev/null
+++ b/third_party/gflags/test/flagfile.2
@@ -0,0 +1,2 @@
+--foo=bar
+--nounused_bool
\ No newline at end of file
diff --git a/third_party/gflags/test/flagfile.3 b/third_party/gflags/test/flagfile.3
new file mode 100644
index 0000000..76d92bb
--- /dev/null
+++ b/third_party/gflags/test/flagfile.3
@@ -0,0 +1 @@
+--flagfile=flagfile.2
\ No newline at end of file
diff --git a/third_party/gflags/test/gflags_build.py.in b/third_party/gflags/test/gflags_build.py.in
new file mode 100644
index 0000000..a8cba2b
--- /dev/null
+++ b/third_party/gflags/test/gflags_build.py.in
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+
+import os
+import sys
+import subprocess
+import shutil
+
+CMAKE            = '@CMAKE_COMMAND@'
+CMAKE_BUILD_TYPE = '@CMAKE_BUILD_TYPE@'
+TMPDIR           = '@TMPDIR@'
+SRCDIR           = '@SRCDIR@'
+GFLAGS_DIR       = '@gflags_BINARY_DIR@'
+
+if __name__ == "__main__":
+  if len(sys.argv) != 4:
+    sys.stderr.write(' '.join(['usage:', sys.argv[0], '<test_name> <srcdir> <expect_fail:0|1>\n']))
+    sys.exit(1)
+  test_name   = sys.argv[1]
+  srcdir      = sys.argv[2]
+  expect_fail = (sys.argv[3].lower() in ['true', 'yes', 'on', '1'])
+  bindir      = os.path.join(TMPDIR, test_name)
+  if TMPDIR == '':
+    sys.stderr.write('Temporary directory not set!\n')
+    sys.exit(1)
+  # create build directory
+  if os.path.isdir(bindir): shutil.rmtree(bindir)
+  os.makedirs(bindir)
+  # configure the build tree
+  if subprocess.call([CMAKE, '-DCMAKE_BUILD_TYPE:STRING='+CMAKE_BUILD_TYPE,
+                             '-Dgflags_DIR:PATH='+GFLAGS_DIR,
+                             '-DTEST_NAME:STRING='+test_name, srcdir], cwd=bindir) != 0:
+    sys.stderr.write('Failed to configure the build tree!\n')
+    sys.exit(1)
+  # build the test project
+  exit_code = subprocess.call([CMAKE, '--build', bindir, '--config', CMAKE_BUILD_TYPE], cwd=bindir)
+  if expect_fail == True:
+    if exit_code == 0:
+      sys.stderr.write('Build expected to fail, but it succeeded!\n')
+      sys.exit(1)
+    else:
+      sys.stderr.write('Build failed as expected\n')
+      exit_code = 0
+  sys.exit(exit_code)
diff --git a/third_party/gflags/test/gflags_declare_flags.cc b/third_party/gflags/test/gflags_declare_flags.cc
new file mode 100644
index 0000000..dc53de5
--- /dev/null
+++ b/third_party/gflags/test/gflags_declare_flags.cc
@@ -0,0 +1,9 @@
+#include <iostream>
+#include <gflags/gflags_declare.h>
+
+DECLARE_string(message); // in gflags_delcare_test.cc
+
+void print_message()
+{
+  std::cout << FLAGS_message << std::endl;
+}
diff --git a/third_party/gflags/test/gflags_declare_test.cc b/third_party/gflags/test/gflags_declare_test.cc
new file mode 100644
index 0000000..707bcc0
--- /dev/null
+++ b/third_party/gflags/test/gflags_declare_test.cc
@@ -0,0 +1,12 @@
+#include <gflags/gflags.h>
+
+DEFINE_string(message, "", "The message to print");
+void print_message(); // in gflags_declare_flags.cc
+
+int main(int argc, char **argv)
+{
+  gflags::SetUsageMessage("Test compilation and use of gflags_declare.h");
+  gflags::ParseCommandLineFlags(&argc, &argv, true);
+  print_message();
+  return 0;
+}
diff --git a/third_party/gflags/test/gflags_strip_flags_test.cc b/third_party/gflags/test/gflags_strip_flags_test.cc
new file mode 100644
index 0000000..25ef53a
--- /dev/null
+++ b/third_party/gflags/test/gflags_strip_flags_test.cc
@@ -0,0 +1,61 @@
+// Copyright (c) 2011, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ---
+// Author: csilvers@google.com (Craig Silverstein)
+//
+// A simple program that uses STRIP_FLAG_HELP.  We'll have a shell
+// script that runs 'strings' over this program and makes sure
+// that the help string is not in there.
+
+#include "config_for_unittests.h"
+#define STRIP_FLAG_HELP 1
+#include <gflags/gflags.h>
+
+#include <stdio.h>
+
+using GFLAGS_NAMESPACE::SetUsageMessage;
+using GFLAGS_NAMESPACE::ParseCommandLineFlags;
+
+
+DEFINE_bool(test, true, "This text should be stripped out");
+
+int main(int argc, char** argv) {
+  SetUsageMessage("Usage message");
+  ParseCommandLineFlags(&argc, &argv, false);
+
+  // Unfortunately, for us, libtool can replace executables with a shell
+  // script that does some work before calling the 'real' executable
+  // under a different name.  We need the 'real' executable name to run
+  // 'strings' on it, so we construct this binary to print the real
+  // name (argv[0]) on stdout when run.
+  puts(argv[0]);
+
+  return 0;
+}
diff --git a/third_party/gflags/test/gflags_strip_flags_test.cmake b/third_party/gflags/test/gflags_strip_flags_test.cmake
new file mode 100644
index 0000000..bd419c4
--- /dev/null
+++ b/third_party/gflags/test/gflags_strip_flags_test.cmake
@@ -0,0 +1,7 @@
+if (NOT BINARY)
+  message (FATAl_ERROR "BINARY file to check not specified!")
+endif ()
+file (STRINGS "${BINARY}" strings REGEX "This text should be stripped out")
+if (strings)
+  message (FATAL_ERROR "Text not stripped from binary like it should be: ${BINARY}")
+endif ()
\ No newline at end of file
diff --git a/third_party/gflags/test/gflags_unittest.cc b/third_party/gflags/test/gflags_unittest.cc
new file mode 100644
index 0000000..80f7398
--- /dev/null
+++ b/third_party/gflags/test/gflags_unittest.cc
@@ -0,0 +1,1536 @@
+// Copyright (c) 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ---
+//
+// For now, this unit test does not cover all features of
+// gflags.cc
+
+#include "config_for_unittests.h"
+#include <gflags/gflags.h>
+
+#include <math.h>       // for isinf() and isnan()
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#  include <unistd.h>   // for unlink()
+#endif
+#include <vector>
+#include <string>
+#include "util.h"
+TEST_INIT
+EXPECT_DEATH_INIT
+
+// I don't actually use this header file, but #include it under the
+// old location to make sure that the include-header-forwarding
+// works.  But don't bother on windows; the windows port is so new
+// it never had the old location-names.
+#ifndef _MSC_VER
+#include <gflags/gflags_completions.h>
+void (*unused_fn)() = &GFLAGS_NAMESPACE::HandleCommandLineCompletions;
+#endif
+
+using std::string;
+using std::vector;
+using GFLAGS_NAMESPACE::int32;
+using GFLAGS_NAMESPACE::FlagRegisterer;
+using GFLAGS_NAMESPACE::StringFromEnv;
+using GFLAGS_NAMESPACE::RegisterFlagValidator;
+using GFLAGS_NAMESPACE::CommandLineFlagInfo;
+using GFLAGS_NAMESPACE::GetAllFlags;
+
+DEFINE_string(test_tmpdir, "", "Dir we use for temp files");
+DEFINE_string(srcdir, StringFromEnv("SRCDIR", "."), "Source-dir root, needed to find gflags_unittest_flagfile");
+
+DECLARE_string(tryfromenv);   // in gflags.cc
+
+DEFINE_bool(test_bool, false, "tests bool-ness");
+DEFINE_int32(test_int32, -1, "");
+DEFINE_int64(test_int64, -2, "");
+DEFINE_uint64(test_uint64, 2, "");
+DEFINE_double(test_double, -1.0, "");
+DEFINE_string(test_string, "initial", "");
+
+//
+// The below ugliness gets some additional code coverage in the -helpxml
+// and -helpmatch test cases having to do with string lengths and formatting
+//
+DEFINE_bool(test_bool_with_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_long_name,
+            false,
+            "extremely_extremely_extremely_extremely_extremely_extremely_extremely_extremely_long_meaning");
+
+DEFINE_string(test_str1, "initial", "");
+DEFINE_string(test_str2, "initial", "");
+DEFINE_string(test_str3, "initial", "");
+
+// This is used to test setting tryfromenv manually
+DEFINE_string(test_tryfromenv, "initial", "");
+
+// Don't try this at home!
+static int changeable_var = 12;
+DEFINE_int32(changeable_var, ++changeable_var, "");
+
+static int changeable_bool_var = 8008;
+DEFINE_bool(changeable_bool_var, ++changeable_bool_var == 8009, "");
+
+static int changeable_string_var = 0;
+static string ChangeableString() {
+  char r[] = {static_cast<char>('0' + ++changeable_string_var), '\0'};
+  return r;
+}
+DEFINE_string(changeable_string_var, ChangeableString(), "");
+
+// These are never used in this unittest, but can be used by
+// gflags_unittest.sh when it needs to specify flags
+// that are legal for gflags_unittest but don't need to
+// be a particular value.
+DEFINE_bool(unused_bool, true, "unused bool-ness");
+DEFINE_int32(unused_int32, -1001, "");
+DEFINE_int64(unused_int64, -2001, "");
+DEFINE_uint64(unused_uint64, 2000, "");
+DEFINE_double(unused_double, -1000.0, "");
+DEFINE_string(unused_string, "unused", "");
+
+// These flags are used by gflags_unittest.sh
+DEFINE_bool(changed_bool1, false, "changed");
+DEFINE_bool(changed_bool2, false, "changed");
+DEFINE_bool(long_helpstring, false,
+            "This helpstring goes on forever and ever and ever and ever and "
+            "ever and ever and ever and ever and ever and ever and ever and "
+            "ever and ever and ever and ever and ever and ever and ever and "
+            "ever and ever and ever and ever and ever and ever and ever and "
+            "ever and ever and ever and ever and ever and ever and ever and "
+            "ever and ever and ever and ever and ever and ever and ever and "
+            "ever and ever and ever and ever and ever and ever and ever and "
+            "ever and ever and ever and ever and ever and ever and ever and "
+            "ever and ever and ever and ever and ever and ever and ever and "
+            "ever and ever and ever and ever and ever and ever and ever and "
+            "ever.  This is the end of a long helpstring");
+
+
+static bool AlwaysFail(const char* flag, bool value) { return value == false; }
+DEFINE_bool(always_fail, false, "will fail to validate when you set it");
+DEFINE_validator(always_fail, AlwaysFail);
+
+// See the comment by GetAllFlags in gflags.h
+static bool DeadlockIfCantLockInValidators(const char* flag, bool value) {
+  if (!value) {
+    return true;
+  }
+  vector<CommandLineFlagInfo> dummy;
+  GetAllFlags(&dummy);
+  return true;
+}
+DEFINE_bool(deadlock_if_cant_lock,
+            false,
+            "will deadlock if set to true and "
+            "if locking of registry in validators fails.");
+DEFINE_validator(deadlock_if_cant_lock, DeadlockIfCantLockInValidators);
+
+#define MAKEFLAG(x) DEFINE_int32(test_flag_num##x, x, "Test flag")
+
+// Define 10 flags
+#define MAKEFLAG10(x)                           \
+  MAKEFLAG(x##0);                               \
+  MAKEFLAG(x##1);                               \
+  MAKEFLAG(x##2);                               \
+  MAKEFLAG(x##3);                               \
+  MAKEFLAG(x##4);                               \
+  MAKEFLAG(x##5);                               \
+  MAKEFLAG(x##6);                               \
+  MAKEFLAG(x##7);                               \
+  MAKEFLAG(x##8);                               \
+  MAKEFLAG(x##9)
+
+// Define 100 flags
+#define MAKEFLAG100(x)                          \
+  MAKEFLAG10(x##0);                             \
+  MAKEFLAG10(x##1);                             \
+  MAKEFLAG10(x##2);                             \
+  MAKEFLAG10(x##3);                             \
+  MAKEFLAG10(x##4);                             \
+  MAKEFLAG10(x##5);                             \
+  MAKEFLAG10(x##6);                             \
+  MAKEFLAG10(x##7);                             \
+  MAKEFLAG10(x##8);                             \
+  MAKEFLAG10(x##9)
+
+// Define a bunch of command-line flags.  Each occurrence of the MAKEFLAG100
+// macro defines 100 integer flags.  This lets us test the effect of having
+// many flags on startup time.
+MAKEFLAG100(1);
+MAKEFLAG100(2);
+MAKEFLAG100(3);
+MAKEFLAG100(4);
+MAKEFLAG100(5);
+MAKEFLAG100(6);
+MAKEFLAG100(7);
+MAKEFLAG100(8);
+MAKEFLAG100(9);
+MAKEFLAG100(10);
+MAKEFLAG100(11);
+MAKEFLAG100(12);
+MAKEFLAG100(13);
+MAKEFLAG100(14);
+MAKEFLAG100(15);
+
+#undef MAKEFLAG100
+#undef MAKEFLAG10
+#undef MAKEFLAG
+
+// This is a pseudo-flag -- we want to register a flag with a filename
+// at the top level, but there is no way to do this except by faking
+// the filename.
+namespace fLI {
+  static const int32 FLAGS_nonotldflag1 = 12;
+  int32 FLAGS_tldflag1 = FLAGS_nonotldflag1;
+  int32 FLAGS_notldflag1 = FLAGS_nonotldflag1;
+  static FlagRegisterer o_tldflag1(
+    "tldflag1", "int32",
+    "should show up in --helpshort", "gflags_unittest.cc",
+    &FLAGS_tldflag1, &FLAGS_notldflag1);
+}
+using fLI::FLAGS_tldflag1;
+
+namespace fLI {
+  static const int32 FLAGS_nonotldflag2 = 23;
+  int32 FLAGS_tldflag2 = FLAGS_nonotldflag2;
+  int32 FLAGS_notldflag2 = FLAGS_nonotldflag2;
+  static FlagRegisterer o_tldflag2(
+    "tldflag2", "int32",
+    "should show up in --helpshort", "gflags_unittest.",
+    &FLAGS_tldflag2, &FLAGS_notldflag2);
+}
+using fLI::FLAGS_tldflag2;
+
+namespace GFLAGS_NAMESPACE {
+
+namespace {
+
+
+static string TmpFile(const string& basename) {
+#ifdef _MSC_VER
+  return FLAGS_test_tmpdir + "\\" + basename;
+#else
+  return FLAGS_test_tmpdir + "/" + basename;
+#endif
+}
+
+// Returns the definition of the --flagfile flag to be used in the tests.
+// Must be called after ParseCommandLineFlags().
+static const char* GetFlagFileFlag() {
+#ifdef _MSC_VER
+  static const string flagfile = FLAGS_srcdir + "\\gflags_unittest_flagfile";
+#else
+  static const string flagfile = FLAGS_srcdir + "/gflags_unittest_flagfile";
+#endif
+  static const string flagfile_flag = string("--flagfile=") + flagfile;
+  return flagfile_flag.c_str();
+}
+
+
+// Defining a variable of type CompileAssertTypesEqual<T1, T2> will cause a
+// compiler error iff T1 and T2 are different types.
+template <typename T1, typename T2>
+struct CompileAssertTypesEqual;
+
+template <typename T>
+struct CompileAssertTypesEqual<T, T> {
+};
+
+
+template <typename Expected, typename Actual>
+void AssertIsType(Actual& x) {
+  CompileAssertTypesEqual<Expected, Actual>();
+}
+
+// Verify all the flags are the right type.
+TEST(FlagTypes, FlagTypes) {
+  AssertIsType<bool>(FLAGS_test_bool);
+  AssertIsType<int32>(FLAGS_test_int32);
+  AssertIsType<int64>(FLAGS_test_int64);
+  AssertIsType<uint64>(FLAGS_test_uint64);
+  AssertIsType<double>(FLAGS_test_double);
+  AssertIsType<string>(FLAGS_test_string);
+}
+
+#ifdef GTEST_HAS_DEATH_TEST
+// Death tests for "help" options.
+//
+// The help system automatically calls gflags_exitfunc(1) when you specify any of
+// the help-related flags ("-helpmatch", "-helpxml") so we can't test
+// those mainline.
+
+// Tests that "-helpmatch" causes the process to die.
+TEST(ReadFlagsFromStringDeathTest, HelpMatch) {
+  EXPECT_DEATH(ReadFlagsFromString("-helpmatch=base", GetArgv0(), true),
+               "");
+}
+
+
+// Tests that "-helpxml" causes the process to die.
+TEST(ReadFlagsFromStringDeathTest, HelpXml) {
+  EXPECT_DEATH(ReadFlagsFromString("-helpxml", GetArgv0(), true),
+               "");
+}
+#endif
+
+
+// A subroutine needed for testing reading flags from a string.
+void TestFlagString(const string& flags,
+                    const string& expected_string,
+                    bool expected_bool,
+                    int32 expected_int32,
+                    double expected_double) {
+  EXPECT_TRUE(ReadFlagsFromString(flags,
+                                  GetArgv0(),
+                                  // errors are fatal
+                                  true));
+
+  EXPECT_EQ(expected_string, FLAGS_test_string);
+  EXPECT_EQ(expected_bool, FLAGS_test_bool);
+  EXPECT_EQ(expected_int32, FLAGS_test_int32);
+  EXPECT_DOUBLE_EQ(expected_double, FLAGS_test_double);
+}
+
+
+// Tests reading flags from a string.
+TEST(FlagFileTest, ReadFlagsFromString) {
+  TestFlagString(
+      // Flag string
+      "-test_string=continued\n"
+      "# some comments are in order\n"
+      "# some\n"
+      "  # comments\n"
+      "#are\n"
+      "                  #trickier\n"
+      "# than others\n"
+      "-test_bool=true\n"
+      "     -test_int32=1\n"
+      "-test_double=0.0\n",
+      // Expected values
+      "continued",
+      true,
+      1,
+      0.0);
+
+  TestFlagString(
+      // Flag string
+      "# let's make sure it can update values\n"
+      "-test_string=initial\n"
+      "-test_bool=false\n"
+      "-test_int32=123\n"
+      "-test_double=123.0\n",
+      // Expected values
+      "initial",
+      false,
+      123,
+      123.0);
+}
+
+// Tests the filename part of the flagfile
+TEST(FlagFileTest, FilenamesOurfileLast) {
+  FLAGS_test_string = "initial";
+  FLAGS_test_bool = false;
+  FLAGS_test_int32 = -1;
+  FLAGS_test_double = -1.0;
+  TestFlagString(
+      // Flag string
+      "-test_string=continued\n"
+      "# some comments are in order\n"
+      "# some\n"
+      "  # comments\n"
+      "#are\n"
+      "                  #trickier\n"
+      "# than others\n"
+      "not_our_filename\n"
+      "-test_bool=true\n"
+      "     -test_int32=1\n"
+      "gflags_unittest\n"
+      "-test_double=1000.0\n",
+      // Expected values
+      "continued",
+      false,
+      -1,
+      1000.0);
+}
+
+TEST(FlagFileTest, FilenamesOurfileFirst) {
+  FLAGS_test_string = "initial";
+  FLAGS_test_bool = false;
+  FLAGS_test_int32 = -1;
+  FLAGS_test_double = -1.0;
+  TestFlagString(
+      // Flag string
+      "-test_string=continued\n"
+      "# some comments are in order\n"
+      "# some\n"
+      "  # comments\n"
+      "#are\n"
+      "                  #trickier\n"
+      "# than others\n"
+      "gflags_unittest\n"
+      "-test_bool=true\n"
+      "     -test_int32=1\n"
+      "not_our_filename\n"
+      "-test_double=1000.0\n",
+      // Expected values
+      "continued",
+      true,
+      1,
+      -1.0);
+}
+
+#if defined(HAVE_FNMATCH_H) || defined(HAVE_SHLWAPI_H)  // otherwise glob isn't supported
+TEST(FlagFileTest, FilenamesOurfileGlob) {
+  FLAGS_test_string = "initial";
+  FLAGS_test_bool = false;
+  FLAGS_test_int32 = -1;
+  FLAGS_test_double = -1.0;
+  TestFlagString(
+      // Flag string
+      "-test_string=continued\n"
+      "# some comments are in order\n"
+      "# some\n"
+      "  # comments\n"
+      "#are\n"
+      "                  #trickier\n"
+      "# than others\n"
+      "*flags*\n"
+      "-test_bool=true\n"
+      "     -test_int32=1\n"
+      "flags\n"
+      "-test_double=1000.0\n",
+      // Expected values
+      "continued",
+      true,
+      1,
+      -1.0);
+}
+
+TEST(FlagFileTest, FilenamesOurfileInBigList) {
+  FLAGS_test_string = "initial";
+  FLAGS_test_bool = false;
+  FLAGS_test_int32 = -1;
+  FLAGS_test_double = -1.0;
+  TestFlagString(
+      // Flag string
+      "-test_string=continued\n"
+      "# some comments are in order\n"
+      "# some\n"
+      "  # comments\n"
+      "#are\n"
+      "                  #trickier\n"
+      "# than others\n"
+      "*first* *flags* *third*\n"
+      "-test_bool=true\n"
+      "     -test_int32=1\n"
+      "flags\n"
+      "-test_double=1000.0\n",
+      // Expected values
+      "continued",
+      true,
+      1,
+      -1.0);
+}
+#endif  // defined(HAVE_FNMATCH_H) || defined(HAVE_SHLWAPI_H)
+
+// Tests that a failed flag-from-string read keeps flags at default values
+TEST(FlagFileTest, FailReadFlagsFromString) {
+  FLAGS_test_int32 = 119;
+  string flags("# let's make sure it can update values\n"
+               "-test_string=non_initial\n"
+               "-test_bool=false\n"
+               "-test_int32=123\n"
+               "-test_double=illegal\n");
+
+  EXPECT_FALSE(ReadFlagsFromString(flags,
+                                   GetArgv0(),
+                                   // errors are fatal
+                                   false));
+
+  EXPECT_EQ(119, FLAGS_test_int32);
+  EXPECT_EQ("initial", FLAGS_test_string);
+}
+
+// Tests that flags can be set to ordinary values.
+TEST(SetFlagValueTest, OrdinaryValues) {
+  EXPECT_EQ("initial", FLAGS_test_str1);
+
+  SetCommandLineOptionWithMode("test_str1", "second", SET_FLAG_IF_DEFAULT);
+  EXPECT_EQ("second", FLAGS_test_str1);  // set; was default
+
+  SetCommandLineOptionWithMode("test_str1", "third", SET_FLAG_IF_DEFAULT);
+  EXPECT_EQ("second", FLAGS_test_str1);  // already set once
+
+  FLAGS_test_str1 = "initial";
+  SetCommandLineOptionWithMode("test_str1", "third", SET_FLAG_IF_DEFAULT);
+  EXPECT_EQ("initial", FLAGS_test_str1);  // still already set before
+
+  SetCommandLineOptionWithMode("test_str1", "third", SET_FLAGS_VALUE);
+  EXPECT_EQ("third", FLAGS_test_str1);  // changed value
+
+  SetCommandLineOptionWithMode("test_str1", "fourth", SET_FLAGS_DEFAULT);
+  EXPECT_EQ("third", FLAGS_test_str1);
+  // value not changed (already set before)
+
+  EXPECT_EQ("initial", FLAGS_test_str2);
+
+  SetCommandLineOptionWithMode("test_str2", "second", SET_FLAGS_DEFAULT);
+  EXPECT_EQ("second", FLAGS_test_str2);  // changed (was default)
+
+  FLAGS_test_str2 = "extra";
+  EXPECT_EQ("extra", FLAGS_test_str2);
+
+  FLAGS_test_str2 = "second";
+  SetCommandLineOptionWithMode("test_str2", "third", SET_FLAGS_DEFAULT);
+  EXPECT_EQ("third", FLAGS_test_str2);  // still changed (was equal to default)
+
+  SetCommandLineOptionWithMode("test_str2", "fourth", SET_FLAG_IF_DEFAULT);
+  EXPECT_EQ("fourth", FLAGS_test_str2);  // changed (was default)
+
+  EXPECT_EQ("initial", FLAGS_test_str3);
+
+  SetCommandLineOptionWithMode("test_str3", "second", SET_FLAGS_DEFAULT);
+  EXPECT_EQ("second", FLAGS_test_str3);  // changed
+
+  FLAGS_test_str3 = "third";
+  SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAGS_DEFAULT);
+  EXPECT_EQ("third", FLAGS_test_str3);  // not changed (was set)
+
+  SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAG_IF_DEFAULT);
+  EXPECT_EQ("third", FLAGS_test_str3);  // not changed (was set)
+
+  SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAGS_VALUE);
+  EXPECT_EQ("fourth", FLAGS_test_str3);  // changed value
+}
+
+
+// Tests that flags can be set to exceptional values.
+// Note: apparently MINGW doesn't parse inf and nan correctly:
+//    http://www.mail-archive.com/bug-gnulib@gnu.org/msg09573.html
+// This url says FreeBSD also has a problem, but I didn't see that.
+TEST(SetFlagValueTest, ExceptionalValues) {
+#if defined(isinf) && !defined(__MINGW32__)
+  EXPECT_EQ("test_double set to inf\n",
+            SetCommandLineOption("test_double", "inf"));
+  EXPECT_INF(FLAGS_test_double);
+
+  EXPECT_EQ("test_double set to inf\n",
+            SetCommandLineOption("test_double", "INF"));
+  EXPECT_INF(FLAGS_test_double);
+#endif
+
+  // set some bad values
+  EXPECT_EQ("",
+            SetCommandLineOption("test_double", "0.1xxx"));
+  EXPECT_EQ("",
+            SetCommandLineOption("test_double", " "));
+  EXPECT_EQ("",
+            SetCommandLineOption("test_double", ""));
+#if defined(isinf) && !defined(__MINGW32__)
+  EXPECT_EQ("test_double set to -inf\n",
+            SetCommandLineOption("test_double", "-inf"));
+  EXPECT_INF(FLAGS_test_double);
+  EXPECT_GT(0, FLAGS_test_double);
+#endif
+
+#if defined(isnan) && !defined(__MINGW32__)
+  EXPECT_EQ("test_double set to nan\n",
+            SetCommandLineOption("test_double", "NaN"));
+  EXPECT_NAN(FLAGS_test_double);
+#endif
+}
+
+// Tests that integer flags can be specified in many ways
+TEST(SetFlagValueTest, DifferentRadices) {
+  EXPECT_EQ("test_int32 set to 12\n",
+            SetCommandLineOption("test_int32", "12"));
+
+  EXPECT_EQ("test_int32 set to 16\n",
+            SetCommandLineOption("test_int32", "0x10"));
+
+  EXPECT_EQ("test_int32 set to 34\n",
+            SetCommandLineOption("test_int32", "0X22"));
+
+  // Leading 0 is *not* octal; it's still decimal
+  EXPECT_EQ("test_int32 set to 10\n",
+            SetCommandLineOption("test_int32", "010"));
+}
+
+// Tests what happens when you try to set a flag to an illegal value
+TEST(SetFlagValueTest, IllegalValues) {
+  FLAGS_test_bool = true;
+  FLAGS_test_int32 = 119;
+  FLAGS_test_int64 = 1191;
+  FLAGS_test_uint64 = 11911;
+
+  EXPECT_EQ("",
+            SetCommandLineOption("test_bool", "12"));
+
+  EXPECT_EQ("",
+            SetCommandLineOption("test_int32", "7000000000000"));
+
+  EXPECT_EQ("",
+            SetCommandLineOption("test_uint64", "-1"));
+
+  EXPECT_EQ("",
+            SetCommandLineOption("test_int64", "not a number!"));
+
+  // Test the empty string with each type of input
+  EXPECT_EQ("", SetCommandLineOption("test_bool", ""));
+  EXPECT_EQ("", SetCommandLineOption("test_int32", ""));
+  EXPECT_EQ("", SetCommandLineOption("test_int64", ""));
+  EXPECT_EQ("", SetCommandLineOption("test_uint64", ""));
+  EXPECT_EQ("", SetCommandLineOption("test_double", ""));
+  EXPECT_EQ("test_string set to \n", SetCommandLineOption("test_string", ""));
+
+  EXPECT_TRUE(FLAGS_test_bool);
+  EXPECT_EQ(119, FLAGS_test_int32);
+  EXPECT_EQ(1191, FLAGS_test_int64);
+  EXPECT_EQ(11911, FLAGS_test_uint64);
+}
+
+
+// Tests that we only evaluate macro args once
+TEST(MacroArgs, EvaluateOnce) {
+  EXPECT_EQ(13, FLAGS_changeable_var);
+  // Make sure we don't ++ the value somehow, when evaluating the flag.
+  EXPECT_EQ(13, FLAGS_changeable_var);
+  // Make sure the macro only evaluated this var once.
+  EXPECT_EQ(13, changeable_var);
+  // Make sure the actual value and default value are the same
+  SetCommandLineOptionWithMode("changeable_var", "21", SET_FLAG_IF_DEFAULT);
+  EXPECT_EQ(21, FLAGS_changeable_var);
+}
+
+TEST(MacroArgs, EvaluateOnceBool) {
+  EXPECT_TRUE(FLAGS_changeable_bool_var);
+  EXPECT_TRUE(FLAGS_changeable_bool_var);
+  EXPECT_EQ(8009, changeable_bool_var);
+  SetCommandLineOptionWithMode("changeable_bool_var", "false",
+                               SET_FLAG_IF_DEFAULT);
+  EXPECT_FALSE(FLAGS_changeable_bool_var);
+}
+
+TEST(MacroArgs, EvaluateOnceStrings) {
+  EXPECT_EQ("1", FLAGS_changeable_string_var);
+  EXPECT_EQ("1", FLAGS_changeable_string_var);
+  EXPECT_EQ(1, changeable_string_var);
+  SetCommandLineOptionWithMode("changeable_string_var", "different",
+                               SET_FLAG_IF_DEFAULT);
+  EXPECT_EQ("different", FLAGS_changeable_string_var);
+}
+
+// Tests that the FooFromEnv does the right thing
+TEST(FromEnvTest, LegalValues) {
+  setenv("BOOL_VAL1", "true", 1);
+  setenv("BOOL_VAL2", "false", 1);
+  setenv("BOOL_VAL3", "1", 1);
+  setenv("BOOL_VAL4", "F", 1);
+  EXPECT_TRUE(BoolFromEnv("BOOL_VAL1", false));
+  EXPECT_FALSE(BoolFromEnv("BOOL_VAL2", true));
+  EXPECT_TRUE(BoolFromEnv("BOOL_VAL3", false));
+  EXPECT_FALSE(BoolFromEnv("BOOL_VAL4", true));
+  EXPECT_TRUE(BoolFromEnv("BOOL_VAL_UNKNOWN", true));
+  EXPECT_FALSE(BoolFromEnv("BOOL_VAL_UNKNOWN", false));
+
+  setenv("INT_VAL1", "1", 1);
+  setenv("INT_VAL2", "-1", 1);
+  EXPECT_EQ(1, Int32FromEnv("INT_VAL1", 10));
+  EXPECT_EQ(-1, Int32FromEnv("INT_VAL2", 10));
+  EXPECT_EQ(10, Int32FromEnv("INT_VAL_UNKNOWN", 10));
+
+  setenv("INT_VAL3", "1099511627776", 1);
+  EXPECT_EQ(1, Int64FromEnv("INT_VAL1", 20));
+  EXPECT_EQ(-1, Int64FromEnv("INT_VAL2", 20));
+  EXPECT_EQ(1099511627776LL, Int64FromEnv("INT_VAL3", 20));
+  EXPECT_EQ(20, Int64FromEnv("INT_VAL_UNKNOWN", 20));
+
+  EXPECT_EQ(1, Uint64FromEnv("INT_VAL1", 30));
+  EXPECT_EQ(1099511627776ULL, Uint64FromEnv("INT_VAL3", 30));
+  EXPECT_EQ(30, Uint64FromEnv("INT_VAL_UNKNOWN", 30));
+
+  // I pick values here that can be easily represented exactly in floating-point
+  setenv("DOUBLE_VAL1", "0.0", 1);
+  setenv("DOUBLE_VAL2", "1.0", 1);
+  setenv("DOUBLE_VAL3", "-1.0", 1);
+  EXPECT_EQ(0.0, DoubleFromEnv("DOUBLE_VAL1", 40.0));
+  EXPECT_EQ(1.0, DoubleFromEnv("DOUBLE_VAL2", 40.0));
+  EXPECT_EQ(-1.0, DoubleFromEnv("DOUBLE_VAL3", 40.0));
+  EXPECT_EQ(40.0, DoubleFromEnv("DOUBLE_VAL_UNKNOWN", 40.0));
+
+  setenv("STRING_VAL1", "", 1);
+  setenv("STRING_VAL2", "my happy string!", 1);
+  EXPECT_STREQ("", StringFromEnv("STRING_VAL1", "unknown"));
+  EXPECT_STREQ("my happy string!", StringFromEnv("STRING_VAL2", "unknown"));
+  EXPECT_STREQ("unknown", StringFromEnv("STRING_VAL_UNKNOWN", "unknown"));
+}
+
+#ifdef GTEST_HAS_DEATH_TEST
+// Tests that the FooFromEnv dies on parse-error
+TEST(FromEnvDeathTest, IllegalValues) {
+  setenv("BOOL_BAD1", "so true!", 1);
+  setenv("BOOL_BAD2", "", 1);
+  EXPECT_DEATH(BoolFromEnv("BOOL_BAD1", false), "error parsing env variable");
+  EXPECT_DEATH(BoolFromEnv("BOOL_BAD2", true), "error parsing env variable");
+
+  setenv("INT_BAD1", "one", 1);
+  setenv("INT_BAD2", "100000000000000000", 1);
+  setenv("INT_BAD3", "0xx10", 1);
+  setenv("INT_BAD4", "", 1);
+  EXPECT_DEATH(Int32FromEnv("INT_BAD1", 10), "error parsing env variable");
+  EXPECT_DEATH(Int32FromEnv("INT_BAD2", 10), "error parsing env variable");
+  EXPECT_DEATH(Int32FromEnv("INT_BAD3", 10), "error parsing env variable");
+  EXPECT_DEATH(Int32FromEnv("INT_BAD4", 10), "error parsing env variable");
+
+  setenv("BIGINT_BAD1", "18446744073709551616000", 1);
+  EXPECT_DEATH(Int64FromEnv("INT_BAD1", 20), "error parsing env variable");
+  EXPECT_DEATH(Int64FromEnv("INT_BAD3", 20), "error parsing env variable");
+  EXPECT_DEATH(Int64FromEnv("INT_BAD4", 20), "error parsing env variable");
+  EXPECT_DEATH(Int64FromEnv("BIGINT_BAD1", 200), "error parsing env variable");
+
+  setenv("BIGINT_BAD2", "-1", 1);
+  EXPECT_DEATH(Uint64FromEnv("INT_BAD1", 30), "error parsing env variable");
+  EXPECT_DEATH(Uint64FromEnv("INT_BAD3", 30), "error parsing env variable");
+  EXPECT_DEATH(Uint64FromEnv("INT_BAD4", 30), "error parsing env variable");
+  EXPECT_DEATH(Uint64FromEnv("BIGINT_BAD1", 30), "error parsing env variable");
+  // TODO(csilvers): uncomment this when we disallow negative numbers for uint64
+#if 0
+  EXPECT_DEATH(Uint64FromEnv("BIGINT_BAD2", 30), "error parsing env variable");
+#endif
+
+  setenv("DOUBLE_BAD1", "0.0.0", 1);
+  setenv("DOUBLE_BAD2", "", 1);
+  EXPECT_DEATH(DoubleFromEnv("DOUBLE_BAD1", 40.0), "error parsing env variable");
+  EXPECT_DEATH(DoubleFromEnv("DOUBLE_BAD2", 40.0), "error parsing env variable");
+}
+#endif
+
+
+// Tests that FlagSaver can save the states of string flags.
+TEST(FlagSaverTest, CanSaveStringFlagStates) {
+  // 1. Initializes the flags.
+
+  // State of flag test_str1:
+  //   default value - "initial"
+  //   current value - "initial"
+  //   not set       - true
+
+  SetCommandLineOptionWithMode("test_str2", "second", SET_FLAGS_VALUE);
+  // State of flag test_str2:
+  //   default value - "initial"
+  //   current value - "second"
+  //   not set       - false
+
+  SetCommandLineOptionWithMode("test_str3", "second", SET_FLAGS_DEFAULT);
+  // State of flag test_str3:
+  //   default value - "second"
+  //   current value - "second"
+  //   not set       - true
+
+  // 2. Saves the flag states.
+
+  {
+    FlagSaver fs;
+
+    // 3. Modifies the flag states.
+
+    SetCommandLineOptionWithMode("test_str1", "second", SET_FLAGS_VALUE);
+    EXPECT_EQ("second", FLAGS_test_str1);
+    // State of flag test_str1:
+    //   default value - "second"
+    //   current value - "second"
+    //   not set       - true
+
+    SetCommandLineOptionWithMode("test_str2", "third", SET_FLAGS_DEFAULT);
+    EXPECT_EQ("second", FLAGS_test_str2);
+    // State of flag test_str2:
+    //   default value - "third"
+    //   current value - "second"
+    //   not set       - false
+
+    SetCommandLineOptionWithMode("test_str3", "third", SET_FLAGS_VALUE);
+    EXPECT_EQ("third", FLAGS_test_str3);
+    // State of flag test_str1:
+    //   default value - "second"
+    //   current value - "third"
+    //   not set       - false
+
+    // 4. Restores the flag states.
+  }
+
+  // 5. Verifies that the states were restored.
+
+  // Verifies that the value of test_str1 was restored.
+  EXPECT_EQ("initial", FLAGS_test_str1);
+  // Verifies that the "not set" attribute of test_str1 was restored to true.
+  SetCommandLineOptionWithMode("test_str1", "second", SET_FLAG_IF_DEFAULT);
+  EXPECT_EQ("second", FLAGS_test_str1);
+
+  // Verifies that the value of test_str2 was restored.
+  EXPECT_EQ("second", FLAGS_test_str2);
+  // Verifies that the "not set" attribute of test_str2 was restored to false.
+  SetCommandLineOptionWithMode("test_str2", "fourth", SET_FLAG_IF_DEFAULT);
+  EXPECT_EQ("second", FLAGS_test_str2);
+
+  // Verifies that the value of test_str3 was restored.
+  EXPECT_EQ("second", FLAGS_test_str3);
+  // Verifies that the "not set" attribute of test_str3 was restored to true.
+  SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAG_IF_DEFAULT);
+  EXPECT_EQ("fourth", FLAGS_test_str3);
+}
+
+
+// Tests that FlagSaver can save the values of various-typed flags.
+TEST(FlagSaverTest, CanSaveVariousTypedFlagValues) {
+  // Initializes the flags.
+  FLAGS_test_bool = false;
+  FLAGS_test_int32 = -1;
+  FLAGS_test_int64 = -2;
+  FLAGS_test_uint64 = 3;
+  FLAGS_test_double = 4.0;
+  FLAGS_test_string = "good";
+
+  // Saves the flag states.
+  {
+    FlagSaver fs;
+
+    // Modifies the flags.
+    FLAGS_test_bool = true;
+    FLAGS_test_int32 = -5;
+    FLAGS_test_int64 = -6;
+    FLAGS_test_uint64 = 7;
+    FLAGS_test_double = 8.0;
+    FLAGS_test_string = "bad";
+
+    // Restores the flag states.
+  }
+
+  // Verifies the flag values were restored.
+  EXPECT_FALSE(FLAGS_test_bool);
+  EXPECT_EQ(-1, FLAGS_test_int32);
+  EXPECT_EQ(-2, FLAGS_test_int64);
+  EXPECT_EQ(3, FLAGS_test_uint64);
+  EXPECT_DOUBLE_EQ(4.0, FLAGS_test_double);
+  EXPECT_EQ("good", FLAGS_test_string);
+}
+
+TEST(GetAllFlagsTest, BaseTest) {
+  vector<CommandLineFlagInfo> flags;
+  GetAllFlags(&flags);
+  bool found_test_bool = false;
+  vector<CommandLineFlagInfo>::const_iterator i;
+  for (i = flags.begin(); i != flags.end(); ++i) {
+    if (i->name == "test_bool") {
+      found_test_bool = true;
+      EXPECT_EQ(i->type, "bool");
+      EXPECT_EQ(i->default_value, "false");
+      EXPECT_EQ(i->flag_ptr, &FLAGS_test_bool);
+      break;
+    }
+  }
+  EXPECT_TRUE(found_test_bool);
+}
+
+TEST(ShowUsageWithFlagsTest, BaseTest) {
+  // TODO(csilvers): test this by allowing output other than to stdout.
+  // Not urgent since this functionality is tested via
+  // gflags_unittest.sh, though only through use of --help.
+}
+
+TEST(ShowUsageWithFlagsRestrictTest, BaseTest) {
+  // TODO(csilvers): test this by allowing output other than to stdout.
+  // Not urgent since this functionality is tested via
+  // gflags_unittest.sh, though only through use of --helpmatch.
+}
+
+// Note: all these argv-based tests depend on SetArgv being called
+// before ParseCommandLineFlags() in main(), below.
+TEST(GetArgvsTest, BaseTest) {
+  vector<string> argvs = GetArgvs();
+  EXPECT_EQ(4, argvs.size());
+  EXPECT_EQ("/test/argv/for/gflags_unittest", argvs[0]);
+  EXPECT_EQ("argv 2", argvs[1]);
+  EXPECT_EQ("3rd argv", argvs[2]);
+  EXPECT_EQ("argv #4", argvs[3]);
+}
+
+TEST(GetArgvTest, BaseTest) {
+  EXPECT_STREQ("/test/argv/for/gflags_unittest "
+               "argv 2 3rd argv argv #4", GetArgv());
+}
+
+TEST(GetArgv0Test, BaseTest) {
+  EXPECT_STREQ("/test/argv/for/gflags_unittest", GetArgv0());
+}
+
+TEST(GetArgvSumTest, BaseTest) {
+  // This number is just the sum of the ASCII values of all the chars
+  // in GetArgv().
+  EXPECT_EQ(4904, GetArgvSum());
+}
+
+TEST(ProgramInvocationNameTest, BaseTest) {
+  EXPECT_STREQ("/test/argv/for/gflags_unittest",
+               ProgramInvocationName());
+}
+
+TEST(ProgramInvocationShortNameTest, BaseTest) {
+  EXPECT_STREQ("gflags_unittest", ProgramInvocationShortName());
+}
+
+TEST(ProgramUsageTest, BaseTest) {  // Depends on 1st arg to ParseCommandLineFlags()
+  EXPECT_STREQ("/test/argv/for/gflags_unittest: "
+               "<useless flag> [...]\nDoes something useless.\n",
+               ProgramUsage());
+}
+
+TEST(GetCommandLineOptionTest, NameExistsAndIsDefault) {
+  string value("will be changed");
+  bool r = GetCommandLineOption("test_bool", &value);
+  EXPECT_TRUE(r);
+  EXPECT_EQ("false", value);
+
+  r = GetCommandLineOption("test_int32", &value);
+  EXPECT_TRUE(r);
+  EXPECT_EQ("-1", value);
+}
+
+TEST(GetCommandLineOptionTest, NameExistsAndWasAssigned) {
+  FLAGS_test_int32 = 400;
+  string value("will be changed");
+  const bool r = GetCommandLineOption("test_int32", &value);
+  EXPECT_TRUE(r);
+  EXPECT_EQ("400", value);
+}
+
+TEST(GetCommandLineOptionTest, NameExistsAndWasSet) {
+  SetCommandLineOption("test_int32", "700");
+  string value("will be changed");
+  const bool r = GetCommandLineOption("test_int32", &value);
+  EXPECT_TRUE(r);
+  EXPECT_EQ("700", value);
+}
+
+TEST(GetCommandLineOptionTest, NameExistsAndWasNotSet) {
+  // This doesn't set the flag's value, but rather its default value.
+  // is_default is still true, but the 'default' value returned has changed!
+  SetCommandLineOptionWithMode("test_int32", "800", SET_FLAGS_DEFAULT);
+  string value("will be changed");
+  const bool r = GetCommandLineOption("test_int32", &value);
+  EXPECT_TRUE(r);
+  EXPECT_EQ("800", value);
+  EXPECT_TRUE(GetCommandLineFlagInfoOrDie("test_int32").is_default);
+}
+
+TEST(GetCommandLineOptionTest, NameExistsAndWasConditionallySet) {
+  SetCommandLineOptionWithMode("test_int32", "900", SET_FLAG_IF_DEFAULT);
+  string value("will be changed");
+  const bool r = GetCommandLineOption("test_int32", &value);
+  EXPECT_TRUE(r);
+  EXPECT_EQ("900", value);
+}
+
+TEST(GetCommandLineOptionTest, NameDoesNotExist) {
+  string value("will not be changed");
+  const bool r = GetCommandLineOption("test_int3210", &value);
+  EXPECT_FALSE(r);
+  EXPECT_EQ("will not be changed", value);
+}
+
+TEST(GetCommandLineFlagInfoTest, FlagExists) {
+  CommandLineFlagInfo info;
+  bool r = GetCommandLineFlagInfo("test_int32", &info);
+  EXPECT_TRUE(r);
+  EXPECT_EQ("test_int32", info.name);
+  EXPECT_EQ("int32", info.type);
+  EXPECT_EQ("", info.description);
+  EXPECT_EQ("-1", info.current_value);
+  EXPECT_EQ("-1", info.default_value);
+  EXPECT_TRUE(info.is_default);
+  EXPECT_FALSE(info.has_validator_fn);
+  EXPECT_EQ(&FLAGS_test_int32, info.flag_ptr);
+
+  FLAGS_test_bool = true;
+  r = GetCommandLineFlagInfo("test_bool", &info);
+  EXPECT_TRUE(r);
+  EXPECT_EQ("test_bool", info.name);
+  EXPECT_EQ("bool", info.type);
+  EXPECT_EQ("tests bool-ness", info.description);
+  EXPECT_EQ("true", info.current_value);
+  EXPECT_EQ("false", info.default_value);
+  EXPECT_FALSE(info.is_default);
+  EXPECT_FALSE(info.has_validator_fn);
+  EXPECT_EQ(&FLAGS_test_bool, info.flag_ptr);
+
+  FLAGS_test_bool = false;
+  r = GetCommandLineFlagInfo("test_bool", &info);
+  EXPECT_TRUE(r);
+  EXPECT_EQ("test_bool", info.name);
+  EXPECT_EQ("bool", info.type);
+  EXPECT_EQ("tests bool-ness", info.description);
+  EXPECT_EQ("false", info.current_value);
+  EXPECT_EQ("false", info.default_value);
+  EXPECT_FALSE(info.is_default);  // value is same, but flag *was* modified
+  EXPECT_FALSE(info.has_validator_fn);
+  EXPECT_EQ(&FLAGS_test_bool, info.flag_ptr);
+}
+
+TEST(GetCommandLineFlagInfoTest, FlagDoesNotExist) {
+  CommandLineFlagInfo info;
+  // Set to some random values that GetCommandLineFlagInfo should not change
+  info.name = "name";
+  info.type = "type";
+  info.current_value = "curr";
+  info.default_value = "def";
+  info.filename = "/";
+  info.is_default = false;
+  info.has_validator_fn = true;
+  info.flag_ptr = NULL;
+  bool r = GetCommandLineFlagInfo("test_int3210", &info);
+  EXPECT_FALSE(r);
+  EXPECT_EQ("name", info.name);
+  EXPECT_EQ("type", info.type);
+  EXPECT_EQ("", info.description);
+  EXPECT_EQ("curr", info.current_value);
+  EXPECT_EQ("def", info.default_value);
+  EXPECT_EQ("/", info.filename);
+  EXPECT_FALSE(info.is_default);
+  EXPECT_TRUE(info.has_validator_fn);
+  EXPECT_EQ(NULL, info.flag_ptr);
+}
+
+TEST(GetCommandLineFlagInfoOrDieTest, FlagExistsAndIsDefault) {
+  CommandLineFlagInfo info;
+  info = GetCommandLineFlagInfoOrDie("test_int32");
+  EXPECT_EQ("test_int32", info.name);
+  EXPECT_EQ("int32", info.type);
+  EXPECT_EQ("", info.description);
+  EXPECT_EQ("-1", info.current_value);
+  EXPECT_EQ("-1", info.default_value);
+  EXPECT_TRUE(info.is_default);
+  EXPECT_EQ(&FLAGS_test_int32, info.flag_ptr);
+  info = GetCommandLineFlagInfoOrDie("test_bool");
+  EXPECT_EQ("test_bool", info.name);
+  EXPECT_EQ("bool", info.type);
+  EXPECT_EQ("tests bool-ness", info.description);
+  EXPECT_EQ("false", info.current_value);
+  EXPECT_EQ("false", info.default_value);
+  EXPECT_TRUE(info.is_default);
+  EXPECT_FALSE(info.has_validator_fn);
+  EXPECT_EQ(&FLAGS_test_bool, info.flag_ptr);
+}
+
+TEST(GetCommandLineFlagInfoOrDieTest, FlagExistsAndWasAssigned) {
+  FLAGS_test_int32 = 400;
+  CommandLineFlagInfo info;
+  info = GetCommandLineFlagInfoOrDie("test_int32");
+  EXPECT_EQ("test_int32", info.name);
+  EXPECT_EQ("int32", info.type);
+  EXPECT_EQ("", info.description);
+  EXPECT_EQ("400", info.current_value);
+  EXPECT_EQ("-1", info.default_value);
+  EXPECT_FALSE(info.is_default);
+  EXPECT_EQ(&FLAGS_test_int32, info.flag_ptr);
+  FLAGS_test_bool = true;
+  info = GetCommandLineFlagInfoOrDie("test_bool");
+  EXPECT_EQ("test_bool", info.name);
+  EXPECT_EQ("bool", info.type);
+  EXPECT_EQ("tests bool-ness", info.description);
+  EXPECT_EQ("true", info.current_value);
+  EXPECT_EQ("false", info.default_value);
+  EXPECT_FALSE(info.is_default);
+  EXPECT_FALSE(info.has_validator_fn);
+  EXPECT_EQ(&FLAGS_test_bool, info.flag_ptr);
+}
+
+#ifdef GTEST_HAS_DEATH_TEST
+TEST(GetCommandLineFlagInfoOrDieDeathTest, FlagDoesNotExist) {
+  EXPECT_DEATH(GetCommandLineFlagInfoOrDie("test_int3210"),
+               ".*: flag test_int3210 does not exist");
+}
+#endif
+
+
+// These are lightly tested because they're deprecated.  Basically,
+// the tests are meant to cover how existing users use these functions,
+// but not necessarily how new users could use them.
+TEST(DeprecatedFunctionsTest, CommandlineFlagsIntoString) {
+  string s = CommandlineFlagsIntoString();
+  EXPECT_NE(string::npos, s.find("--test_bool="));
+}
+
+TEST(DeprecatedFunctionsTest, AppendFlagsIntoFile) {
+  FLAGS_test_int32 = 10;     // just to make the test more interesting
+  string filename(TmpFile("flagfile"));
+  unlink(filename.c_str());  // just to be safe
+  const bool r = AppendFlagsIntoFile(filename, "not the real argv0");
+  EXPECT_TRUE(r);
+
+  FILE* fp;
+  EXPECT_EQ(0, SafeFOpen(&fp, filename.c_str(), "r"));
+  EXPECT_TRUE(fp != NULL);
+  char line[8192];
+  EXPECT_TRUE(fgets(line, sizeof(line)-1, fp) != NULL);  // get the first line
+  // First line should be progname.
+  EXPECT_STREQ("not the real argv0\n", line);
+
+  bool found_bool = false, found_int32 = false;
+  while (fgets(line, sizeof(line)-1, fp)) {
+    line[sizeof(line)-1] = '\0';    // just to be safe
+    if (strcmp(line, "--test_bool=false\n") == 0)
+      found_bool = true;
+    if (strcmp(line, "--test_int32=10\n") == 0)
+      found_int32 = true;
+  }
+  EXPECT_TRUE(found_int32);
+  EXPECT_TRUE(found_bool);
+  fclose(fp);
+}
+
+TEST(DeprecatedFunctionsTest, ReadFromFlagsFile) {
+  FLAGS_test_int32 = -10;    // just to make the test more interesting
+  string filename(TmpFile("flagfile2"));
+  unlink(filename.c_str());  // just to be safe
+  bool r = AppendFlagsIntoFile(filename, GetArgv0());
+  EXPECT_TRUE(r);
+
+  FLAGS_test_int32 = -11;
+  r = ReadFromFlagsFile(filename, GetArgv0(), true);
+  EXPECT_TRUE(r);
+  EXPECT_EQ(-10, FLAGS_test_int32);
+}  // unnamed namespace
+
+TEST(DeprecatedFunctionsTest, ReadFromFlagsFileFailure) {
+  FLAGS_test_int32 = -20;
+  string filename(TmpFile("flagfile3"));
+  FILE* fp;
+  EXPECT_EQ(0, SafeFOpen(&fp, filename.c_str(), "w"));
+  EXPECT_TRUE(fp != NULL);
+  // Note the error in the bool assignment below...
+  fprintf(fp, "%s\n--test_int32=-21\n--test_bool=not_a_bool!\n", GetArgv0());
+  fclose(fp);
+
+  FLAGS_test_int32 = -22;
+  const bool r = ReadFromFlagsFile(filename, GetArgv0(), false);
+  EXPECT_FALSE(r);
+  EXPECT_EQ(-22, FLAGS_test_int32);   // the -21 from the flagsfile didn't take
+}
+
+TEST(FlagsSetBeforeInitTest, TryFromEnv) {
+  EXPECT_EQ("pre-set", FLAGS_test_tryfromenv);
+}
+
+// The following test case verifies that ParseCommandLineFlags() and
+// ParseCommandLineNonHelpFlags() uses the last definition of a flag
+// in case it's defined more than once.
+
+DEFINE_int32(test_flag, -1, "used for testing gflags.cc");
+
+// Parses and returns the --test_flag flag.
+// If with_help is true, calls ParseCommandLineFlags; otherwise calls
+// ParseCommandLineNonHelpFlags.
+int32 ParseTestFlag(bool with_help, int argc, const char** const_argv) {
+  FlagSaver fs;  // Restores the flags before returning.
+
+  // Makes a copy of the input array s.t. it can be reused
+  // (ParseCommandLineFlags() will alter the array).
+  char** const argv_save = new char*[argc + 1];
+  char** argv = argv_save;
+  memcpy(argv, const_argv, sizeof(*argv)*(argc + 1));
+
+  if (with_help) {
+    ParseCommandLineFlags(&argc, &argv, true);
+  } else {
+    ParseCommandLineNonHelpFlags(&argc, &argv, true);
+  }
+
+  delete[] argv_save;
+  return FLAGS_test_flag;
+}
+
+TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
+     WhenFlagIsDefinedTwiceOnCommandLine) {
+  const char* argv[] = {
+    "my_test",
+    "--test_flag=1",
+    "--test_flag=2",
+    NULL,
+  };
+
+  EXPECT_EQ(2, ParseTestFlag(true, arraysize(argv) - 1, argv));
+  EXPECT_EQ(2, ParseTestFlag(false, arraysize(argv) - 1, argv));
+}
+
+TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
+     WhenFlagIsDefinedTwiceInFlagFile) {
+  const char* argv[] = {
+    "my_test",
+    GetFlagFileFlag(),
+    NULL,
+  };
+
+  EXPECT_EQ(2, ParseTestFlag(true, arraysize(argv) - 1, argv));
+  EXPECT_EQ(2, ParseTestFlag(false, arraysize(argv) - 1, argv));
+}
+
+TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
+     WhenFlagIsDefinedInCommandLineAndThenFlagFile) {
+  const char* argv[] = {
+    "my_test",
+    "--test_flag=0",
+    GetFlagFileFlag(),
+    NULL,
+  };
+
+  EXPECT_EQ(2, ParseTestFlag(true, arraysize(argv) - 1, argv));
+  EXPECT_EQ(2, ParseTestFlag(false, arraysize(argv) - 1, argv));
+}
+
+TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
+     WhenFlagIsDefinedInFlagFileAndThenCommandLine) {
+  const char* argv[] = {
+    "my_test",
+    GetFlagFileFlag(),
+    "--test_flag=3",
+    NULL,
+  };
+
+  EXPECT_EQ(3, ParseTestFlag(true, arraysize(argv) - 1, argv));
+  EXPECT_EQ(3, ParseTestFlag(false, arraysize(argv) - 1, argv));
+}
+
+TEST(ParseCommandLineFlagsUsesLastDefinitionTest,
+     WhenFlagIsDefinedInCommandLineAndFlagFileAndThenCommandLine) {
+  const char* argv[] = {
+    "my_test",
+    "--test_flag=0",
+    GetFlagFileFlag(),
+    "--test_flag=3",
+    NULL,
+  };
+
+  EXPECT_EQ(3, ParseTestFlag(true, arraysize(argv) - 1, argv));
+  EXPECT_EQ(3, ParseTestFlag(false, arraysize(argv) - 1, argv));
+}
+
+TEST(ParseCommandLineFlagsAndDashArgs, TwoDashArgFirst) {
+  const char* argv[] = {
+    "my_test",
+    "--",
+    "--test_flag=0",
+    NULL,
+  };
+
+  EXPECT_EQ(-1, ParseTestFlag(true, arraysize(argv) - 1, argv));
+  EXPECT_EQ(-1, ParseTestFlag(false, arraysize(argv) - 1, argv));
+}
+
+TEST(ParseCommandLineFlagsAndDashArgs, TwoDashArgMiddle) {
+  const char* argv[] = {
+    "my_test",
+    "--test_flag=7",
+    "--",
+    "--test_flag=0",
+    NULL,
+  };
+
+  EXPECT_EQ(7, ParseTestFlag(true, arraysize(argv) - 1, argv));
+  EXPECT_EQ(7, ParseTestFlag(false, arraysize(argv) - 1, argv));
+}
+
+TEST(ParseCommandLineFlagsAndDashArgs, OneDashArg) {
+  const char* argv[] = {
+    "my_test",
+    "-",
+    "--test_flag=0",
+    NULL,
+  };
+
+  EXPECT_EQ(0, ParseTestFlag(true, arraysize(argv) - 1, argv));
+  EXPECT_EQ(0, ParseTestFlag(false, arraysize(argv) - 1, argv));
+}
+
+#ifdef GTEST_HAS_DEATH_TEST
+TEST(ParseCommandLineFlagsUnknownFlagDeathTest,
+     FlagIsCompletelyUnknown) {
+  const char* argv[] = {
+    "my_test",
+    "--this_flag_does_not_exist",
+    NULL,
+  };
+
+  EXPECT_DEATH(ParseTestFlag(true, arraysize(argv) - 1, argv),
+               "unknown command line flag.*");
+  EXPECT_DEATH(ParseTestFlag(false, arraysize(argv) - 1, argv),
+               "unknown command line flag.*");
+}
+
+TEST(ParseCommandLineFlagsUnknownFlagDeathTest,
+     BoolFlagIsCompletelyUnknown) {
+  const char* argv[] = {
+    "my_test",
+    "--nothis_flag_does_not_exist",
+    NULL,
+  };
+
+  EXPECT_DEATH(ParseTestFlag(true, arraysize(argv) - 1, argv),
+               "unknown command line flag.*");
+  EXPECT_DEATH(ParseTestFlag(false, arraysize(argv) - 1, argv),
+               "unknown command line flag.*");
+}
+
+TEST(ParseCommandLineFlagsUnknownFlagDeathTest,
+     FlagIsNotABool) {
+  const char* argv[] = {
+    "my_test",
+    "--notest_string",
+    NULL,
+  };
+
+  EXPECT_DEATH(ParseTestFlag(true, arraysize(argv) - 1, argv),
+               "boolean value .* specified for .* command line flag");
+  EXPECT_DEATH(ParseTestFlag(false, arraysize(argv) - 1, argv),
+               "boolean value .* specified for .* command line flag");
+}
+#endif
+
+TEST(ParseCommandLineFlagsWrongFields,
+     DescriptionIsInvalid) {
+  // These must not be automatic variables, since command line flags
+  // aren't unregistered and gUnit uses FlagSaver to save and restore
+  // command line flags' values.  If these are on the stack, then when
+  // later tests attempt to save and restore their values, the stack
+  // addresses of these variables will be overwritten...  Stack smash!
+  static bool current_storage;
+  static bool defvalue_storage;
+  FlagRegisterer fr("flag_name", "bool", 0, "filename",
+                    &current_storage, &defvalue_storage);
+  CommandLineFlagInfo fi;
+  EXPECT_TRUE(GetCommandLineFlagInfo("flag_name", &fi));
+  EXPECT_EQ("", fi.description);
+  EXPECT_EQ(&current_storage, fi.flag_ptr);
+}
+
+static bool ValidateTestFlagIs5(const char* flagname, int32 flagval) {
+  if (flagval == 5)
+    return true;
+  printf("%s isn't 5!\n", flagname);
+  return false;
+}
+
+static bool ValidateTestFlagIs10(const char* flagname, int32 flagval) {
+  return flagval == 10;
+}
+
+
+TEST(FlagsValidator, ValidFlagViaArgv) {
+  const char* argv[] = {
+    "my_test",
+    "--test_flag=5",
+    NULL,
+  };
+  EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
+  EXPECT_EQ(5, ParseTestFlag(true, arraysize(argv) - 1, argv));
+  // Undo the flag validator setting
+  EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL));
+}
+
+TEST(FlagsValidator, ValidFlagViaSetDefault) {
+  EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
+  // SetCommandLineOptionWithMode returns the empty string on error.
+  EXPECT_NE("", SetCommandLineOptionWithMode("test_flag", "5",
+                                             SET_FLAG_IF_DEFAULT));
+  EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL));
+}
+
+TEST(FlagsValidator, ValidFlagViaSetValue) {
+  EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
+  FLAGS_test_flag = 100;   // doesn't trigger the validator
+  // SetCommandLineOptionWithMode returns the empty string on error.
+  EXPECT_NE("", SetCommandLineOptionWithMode("test_flag", "5",
+                                             SET_FLAGS_VALUE));
+  EXPECT_NE("", SetCommandLineOptionWithMode("test_flag", "5",
+                                             SET_FLAGS_DEFAULT));
+  EXPECT_NE("", SetCommandLineOption("test_flag", "5"));
+  EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL));
+}
+
+#ifdef GTEST_HAS_DEATH_TEST
+TEST(FlagsValidatorDeathTest, InvalidFlagViaArgv) {
+  const char* argv[] = {
+    "my_test",
+    "--test_flag=50",
+    NULL,
+  };
+  EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
+  EXPECT_DEATH(ParseTestFlag(true, arraysize(argv) - 1, argv),
+               "ERROR: failed validation of new value '50' for flag 'test_flag'");
+  EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL));
+}
+#endif
+
+TEST(FlagsValidator, InvalidFlagViaSetDefault) {
+  EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
+  // SetCommandLineOptionWithMode returns the empty string on error.
+  EXPECT_EQ("", SetCommandLineOptionWithMode("test_flag", "50",
+                                             SET_FLAG_IF_DEFAULT));
+  EXPECT_EQ(-1, FLAGS_test_flag);   // the setting-to-50 should have failed
+  EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL));
+}
+
+TEST(FlagsValidator, InvalidFlagViaSetValue) {
+  EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
+  FLAGS_test_flag = 100;   // doesn't trigger the validator
+  // SetCommandLineOptionWithMode returns the empty string on error.
+  EXPECT_EQ("", SetCommandLineOptionWithMode("test_flag", "50",
+                                             SET_FLAGS_VALUE));
+  EXPECT_EQ("", SetCommandLineOptionWithMode("test_flag", "50",
+                                             SET_FLAGS_DEFAULT));
+  EXPECT_EQ("", SetCommandLineOption("test_flag", "50"));
+  EXPECT_EQ(100, FLAGS_test_flag);   // the setting-to-50 should have failed
+  EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL));
+}
+
+#ifdef GTEST_HAS_DEATH_TEST
+TEST(FlagsValidatorDeathTest, InvalidFlagNeverSet) {
+  // If a flag keeps its default value, and that default value is
+  // invalid, we should die at argv-parse time.
+  const char* argv[] = {
+    "my_test",
+    NULL,
+  };
+  EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
+  EXPECT_DEATH(ParseTestFlag(true, arraysize(argv) - 1, argv),
+               "ERROR: --test_flag must be set on the commandline");
+}
+#endif
+
+TEST(FlagsValidator, InvalidFlagPtr) {
+  int32 dummy;
+  EXPECT_FALSE(RegisterFlagValidator(NULL, &ValidateTestFlagIs5));
+  EXPECT_FALSE(RegisterFlagValidator(&dummy, &ValidateTestFlagIs5));
+}
+
+TEST(FlagsValidator, RegisterValidatorTwice) {
+  EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
+  EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
+  EXPECT_FALSE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs10));
+  EXPECT_FALSE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs10));
+  EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
+  EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL));
+  EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs10));
+  EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL));
+}
+
+TEST(FlagsValidator, CommandLineFlagInfo) {
+  CommandLineFlagInfo info;
+  info = GetCommandLineFlagInfoOrDie("test_flag");
+  EXPECT_FALSE(info.has_validator_fn);
+
+  EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
+  info = GetCommandLineFlagInfoOrDie("test_flag");
+  EXPECT_TRUE(info.has_validator_fn);
+
+  EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL));
+  info = GetCommandLineFlagInfoOrDie("test_flag");
+  EXPECT_FALSE(info.has_validator_fn);
+}
+
+TEST(FlagsValidator, FlagSaver) {
+  {
+    FlagSaver fs;
+    EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
+    EXPECT_EQ("", SetCommandLineOption("test_flag", "50"));  // fails validation
+  }
+  EXPECT_NE("", SetCommandLineOption("test_flag", "50"));  // validator is gone
+
+  EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, &ValidateTestFlagIs5));
+  {
+    FlagSaver fs;
+    EXPECT_TRUE(RegisterFlagValidator(&FLAGS_test_flag, NULL));
+    EXPECT_NE("", SetCommandLineOption("test_flag", "50"));  // no validator
+  }
+  EXPECT_EQ("", SetCommandLineOption("test_flag", "50"));  // validator is back
+}
+
+
+}  // unnamed namespace
+
+int main(int argc, char **argv) {
+
+  // Run unit tests only if called without arguments, otherwise this program
+  // is used by an "external" usage test
+  const bool run_tests = (argc == 1);
+
+  // We need to call SetArgv before parsing flags, so our "test" argv will
+  // win out over this executable's real argv.  That makes running this
+  // test with a real --help flag kinda annoying, unfortunately.
+  const char* test_argv[] = { "/test/argv/for/gflags_unittest",
+                              "argv 2", "3rd argv", "argv #4" };
+  SetArgv(arraysize(test_argv), test_argv);
+
+  // The first arg is the usage message, also important for testing.
+  string usage_message = (string(GetArgv0()) +
+                          ": <useless flag> [...]\nDoes something useless.\n");
+
+  // We test setting tryfromenv manually, and making sure
+  // ParseCommandLineFlags still evaluates it.
+  FLAGS_tryfromenv = "test_tryfromenv";
+  setenv("FLAGS_test_tryfromenv", "pre-set", 1);
+
+  // Modify flag values from declared default value in two ways.
+  // The recommended way:
+  SetCommandLineOptionWithMode("changed_bool1", "true", SET_FLAGS_DEFAULT);
+
+  // The non-recommended way:
+  FLAGS_changed_bool2 = true;
+
+  SetUsageMessage(usage_message.c_str());
+  SetVersionString("test_version");
+  ParseCommandLineFlags(&argc, &argv, true);
+  MakeTmpdir(&FLAGS_test_tmpdir);
+
+  int exit_status = 0;
+  if (run_tests) {
+	  fprintf(stdout, "Running the unit tests now...\n\n"); fflush(stdout);
+	  exit_status = RUN_ALL_TESTS();
+  } else fprintf(stderr, "\n\nPASS\n");
+  ShutDownCommandLineFlags();
+  return exit_status;
+}
+
+} // GFLAGS_NAMESPACE
+
+int main(int argc, char** argv) {
+  return GFLAGS_NAMESPACE::main(argc, argv);
+}
+
diff --git a/third_party/gflags/test/gflags_unittest_flagfile b/third_party/gflags/test/gflags_unittest_flagfile
new file mode 100644
index 0000000..f4fa0c4
--- /dev/null
+++ b/third_party/gflags/test/gflags_unittest_flagfile
@@ -0,0 +1,2 @@
+--test_flag=1
+--test_flag=2
diff --git a/third_party/gflags/test/nc/CMakeLists.txt b/third_party/gflags/test/nc/CMakeLists.txt
new file mode 100644
index 0000000..e425d91
--- /dev/null
+++ b/third_party/gflags/test/nc/CMakeLists.txt
@@ -0,0 +1,16 @@
+## gflags negative compilation tests
+
+cmake_minimum_required (VERSION 2.8)
+
+if (NOT TEST_NAME)
+  message (FATAL_ERROR "Missing TEST_NAME CMake flag")
+endif ()
+string (TOUPPER ${TEST_NAME} TEST_NAME_UPPER)
+
+project (gflags_${TEST_NAME})
+
+find_package (gflags REQUIRED)
+include_directories ("${CMAKE_CURRENT_SOURCE_DIR}/..")
+add_definitions (-DTEST_${TEST_NAME_UPPER})
+add_executable (gflags_${TEST_NAME} gflags_nc.cc)
+target_link_libraries(gflags_${TEST_NAME} ${gflags_LIBRARIES})
diff --git a/third_party/gflags/test/nc/gflags_nc.cc b/third_party/gflags/test/nc/gflags_nc.cc
new file mode 100644
index 0000000..1990c30
--- /dev/null
+++ b/third_party/gflags/test/nc/gflags_nc.cc
@@ -0,0 +1,73 @@
+// Copyright (c) 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ---
+//
+// A negative comiple test for gflags.
+
+#include <gflags/gflags.h>
+
+#if defined(TEST_NC_SWAPPED_ARGS)
+
+DEFINE_bool(some_bool_flag,
+            "the default value should go here, not the description",
+            false);
+
+
+#elif defined(TEST_NC_INT_INSTEAD_OF_BOOL)
+
+DEFINE_bool(some_bool_flag_2,
+            0,
+            "should have been an int32 flag but mistakenly used bool instead");
+
+#elif defined(TEST_NC_BOOL_IN_QUOTES)
+
+
+DEFINE_bool(some_bool_flag_3,
+            "false",
+            "false in in quotes, which is wrong");
+
+#elif defined(TEST_NC_SANITY)
+
+DEFINE_bool(some_bool_flag_4,
+            true,
+            "this is the correct usage of DEFINE_bool");
+
+#elif defined(TEST_NC_DEFINE_STRING_WITH_0)
+
+DEFINE_string(some_string_flag,
+              0,
+              "Trying to construct a string by passing 0 would cause a crash.");
+
+#endif
+
+int main(int, char **)
+{
+  return 0;
+}
diff --git a/third_party/googletest/.travis.yml b/third_party/googletest/.travis.yml
new file mode 100644
index 0000000..cd3485c
--- /dev/null
+++ b/third_party/googletest/.travis.yml
@@ -0,0 +1,45 @@
+# Build matrix / environment variable are explained on:
+# http://about.travis-ci.org/docs/user/build-configuration/
+# This file can be validated on:
+# http://lint.travis-ci.org/
+# See also
+# http://stackoverflow.com/questions/22111549/travis-ci-with-clang-3-4-and-c11/30925448#30925448
+# to allow C++11, though we are not yet building with -std=c++11
+
+install:
+# /usr/bin/gcc is 4.6 always, but gcc-X.Y is available.
+- if [ "$CXX" = "g++" ]; then export CXX="g++-4.9" CC="gcc-4.9"; fi
+# /usr/bin/clang is our version already, and clang-X.Y does not exist.
+#- if [ "$CXX" = "clang++" ]; then export CXX="clang++-3.7" CC="clang-3.7"; fi
+- echo ${PATH}
+- ls /usr/local
+- ls /usr/local/bin
+- export PATH=/usr/local/bin:/usr/bin:${PATH}
+- echo ${CXX}
+- ${CXX} --version
+addons:
+  apt:
+    sources:
+    - ubuntu-toolchain-r-test
+    packages:
+    - gcc-4.9
+    - g++-4.9
+    - clang
+    - valgrind
+os:
+  - linux
+  - osx
+language: cpp
+compiler:
+  - gcc
+  - clang
+script: ./travis.sh
+env:
+  matrix:
+    - GTEST_TARGET=googletest SHARED_LIB=OFF STATIC_LIB=ON CMAKE_PKG=OFF BUILD_TYPE=debug   VERBOSE_MAKE=true VERBOSE
+    - GTEST_TARGET=googlemock SHARED_LIB=OFF STATIC_LIB=ON CMAKE_PKG=OFF BUILD_TYPE=debug   VERBOSE_MAKE=true VERBOSE
+#    - GTEST_TARGET=googletest SHARED_LIB=ON  STATIC_LIB=ON CMAKE_PKG=ON  BUILD_TYPE=release VERBOSE_MAKE=false
+#    - GTEST_TARGET=googlemock SHARED_LIB=ON  STATIC_LIB=ON CMAKE_PKG=ON  BUILD_TYPE=release VERBOSE_MAKE=false
+notifications:
+  email: false
+sudo: false
diff --git a/third_party/googletest/README.md b/third_party/googletest/README.md
new file mode 100644
index 0000000..675a216
--- /dev/null
+++ b/third_party/googletest/README.md
@@ -0,0 +1,138 @@
+
+# Google Test #
+
+[![Build Status](https://travis-ci.org/google/googletest.svg?branch=master)](https://travis-ci.org/google/googletest)
+
+Welcome to **Google Test**, Google's C++ test framework!
+
+This repository is a merger of the formerly separate GoogleTest and
+GoogleMock projects. These were so closely related that it makes sense to
+maintain and release them together.
+
+Please see the project page above for more information as well as the
+mailing list for questions, discussions, and development.  There is
+also an IRC channel on OFTC (irc.oftc.net) #gtest available.  Please
+join us!
+
+**Google Mock** is an extension to Google Test for writing and using C++ mock
+classes.  See the separate [Google Mock documentation](googlemock/README.md).
+
+More detailed documentation for googletest (including build instructions) are
+in its interior [googletest/README.md](googletest/README.md) file.
+
+## Features ##
+
+  * An [XUnit](https://en.wikipedia.org/wiki/XUnit) test framework.
+  * Test discovery.
+  * A rich set of assertions.
+  * User-defined assertions.
+  * Death tests.
+  * Fatal and non-fatal failures.
+  * Value-parameterized tests.
+  * Type-parameterized tests.
+  * Various options for running the tests.
+  * XML test report generation.
+
+## Platforms ##
+
+Google test has been used on a variety of platforms:
+
+  * Linux
+  * Mac OS X
+  * Windows
+  * Cygwin
+  * MinGW
+  * Windows Mobile
+  * Symbian
+
+## Who Is Using Google Test? ##
+
+In addition to many internal projects at Google, Google Test is also used by
+the following notable projects:
+
+  * The [Chromium projects](http://www.chromium.org/) (behind the Chrome
+    browser and Chrome OS).
+  * The [LLVM](http://llvm.org/) compiler.
+  * [Protocol Buffers](http://code.google.com/p/protobuf/), Google's data
+    interchange format.
+  * The [OpenCV](http://opencv.org/) computer vision library.
+
+## Related Open Source Projects ##
+
+[Google Test UI](https://github.com/ospector/gtest-gbar) is test runner that runs
+your test binary, allows you to track its progress via a progress bar, and
+displays a list of test failures. Clicking on one shows failure text. Google
+Test UI is written in C#.
+
+[GTest TAP Listener](https://github.com/kinow/gtest-tap-listener) is an event
+listener for Google Test that implements the
+[TAP protocol](http://en.wikipedia.org/wiki/Test_Anything_Protocol) for test
+result output. If your test runner understands TAP, you may find it useful.
+
+## Requirements ##
+
+Google Test is designed to have fairly minimal requirements to build
+and use with your projects, but there are some.  Currently, we support
+Linux, Windows, Mac OS X, and Cygwin.  We will also make our best
+effort to support other platforms (e.g. Solaris, AIX, and z/OS).
+However, since core members of the Google Test project have no access
+to these platforms, Google Test may have outstanding issues there.  If
+you notice any problems on your platform, please notify
+<googletestframework@googlegroups.com>. Patches for fixing them are
+even more welcome!
+
+### Linux Requirements ###
+
+These are the base requirements to build and use Google Test from a source
+package (as described below):
+
+  * GNU-compatible Make or gmake
+  * POSIX-standard shell
+  * POSIX(-2) Regular Expressions (regex.h)
+  * A C++98-standard-compliant compiler
+
+### Windows Requirements ###
+
+  * Microsoft Visual C++ v7.1 or newer
+
+### Cygwin Requirements ###
+
+  * Cygwin v1.5.25-14 or newer
+
+### Mac OS X Requirements ###
+
+  * Mac OS X v10.4 Tiger or newer
+  * XCode Developer Tools
+
+### Requirements for Contributors ###
+
+We welcome patches.  If you plan to contribute a patch, you need to
+build Google Test and its own tests from a git checkout (described
+below), which has further requirements:
+
+  * [Python](http://python.org/) v2.3 or newer (for running some of
+    the tests and re-generating certain source files from templates)
+  * [CMake](http://www.cmake.org/) v2.6.4 or newer
+
+## Regenerating Source Files ##
+
+Some of Google Test's source files are generated from templates (not
+in the C++ sense) using a script.
+For example, the
+file include/gtest/internal/gtest-type-util.h.pump is used to generate
+gtest-type-util.h in the same directory.
+
+You don't need to worry about regenerating the source files
+unless you need to modify them.  You would then modify the
+corresponding `.pump` files and run the '[pump.py](googletest/scripts/pump.py)'
+generator script.  See the [Pump Manual](googletest/docs/PumpManual.md).
+
+### Contributing Code ###
+
+We welcome patches.  Please read the
+[Developer's Guide](googletest/docs/DevGuide.md)
+for how you can contribute. In particular, make sure you have signed
+the Contributor License Agreement, or we won't be able to accept the
+patch.
+
+Happy testing!
diff --git a/third_party/googletest/googlemock/CHANGES b/third_party/googletest/googlemock/CHANGES
new file mode 100644
index 0000000..d6f2f76
--- /dev/null
+++ b/third_party/googletest/googlemock/CHANGES
@@ -0,0 +1,126 @@
+Changes for 1.7.0:
+
+* All new improvements in Google Test 1.7.0.
+* New feature: matchers DoubleNear(), FloatNear(),
+  NanSensitiveDoubleNear(), NanSensitiveFloatNear(),
+  UnorderedElementsAre(), UnorderedElementsAreArray(), WhenSorted(),
+  WhenSortedBy(), IsEmpty(), and SizeIs().
+* Improvement: Google Mock can now be built as a DLL.
+* Improvement: when compiled by a C++11 compiler, matchers AllOf()
+  and AnyOf() can accept an arbitrary number of matchers.
+* Improvement: when compiled by a C++11 compiler, matchers
+  ElementsAreArray() can accept an initializer list.
+* Improvement: when exceptions are enabled, a mock method with no
+  default action now throws instead crashing the test.
+* Improvement: added class testing::StringMatchResultListener to aid
+  definition of composite matchers.
+* Improvement: function return types used in MOCK_METHOD*() macros can
+  now contain unprotected commas.
+* Improvement (potentially breaking): EXPECT_THAT() and ASSERT_THAT()
+  are now more strict in ensuring that the value type and the matcher
+  type are compatible, catching potential bugs in tests.
+* Improvement: Pointee() now works on an optional<T>.
+* Improvement: the ElementsAreArray() matcher can now take a vector or
+  iterator range as input, and makes a copy of its input elements
+  before the conversion to a Matcher.
+* Improvement: the Google Mock Generator can now generate mocks for
+  some class templates.
+* Bug fix: mock object destruction triggerred by another mock object's
+  destruction no longer hangs.
+* Improvement: Google Mock Doctor works better with newer Clang and
+  GCC now.
+* Compatibility fixes.
+* Bug/warning fixes.
+
+Changes for 1.6.0:
+
+* Compilation is much faster and uses much less memory, especially
+  when the constructor and destructor of a mock class are moved out of
+  the class body.
+* New matchers: Pointwise(), Each().
+* New actions: ReturnPointee() and ReturnRefOfCopy().
+* CMake support.
+* Project files for Visual Studio 2010.
+* AllOf() and AnyOf() can handle up-to 10 arguments now.
+* Google Mock doctor understands Clang error messages now.
+* SetArgPointee<> now accepts string literals.
+* gmock_gen.py handles storage specifier macros and template return
+  types now.
+* Compatibility fixes.
+* Bug fixes and implementation clean-ups.
+* Potentially incompatible changes: disables the harmful 'make install'
+  command in autotools.
+
+Potentially breaking changes:
+
+* The description string for MATCHER*() changes from Python-style
+  interpolation to an ordinary C++ string expression.
+* SetArgumentPointee is deprecated in favor of SetArgPointee.
+* Some non-essential project files for Visual Studio 2005 are removed.
+
+Changes for 1.5.0:
+
+ * New feature: Google Mock can be safely used in multi-threaded tests
+   on platforms having pthreads.
+ * New feature: function for printing a value of arbitrary type.
+ * New feature: function ExplainMatchResult() for easy definition of
+   composite matchers.
+ * The new matcher API lets user-defined matchers generate custom
+   explanations more directly and efficiently.
+ * Better failure messages all around.
+ * NotNull() and IsNull() now work with smart pointers.
+ * Field() and Property() now work when the matcher argument is a pointer
+   passed by reference.
+ * Regular expression matchers on all platforms.
+ * Added GCC 4.0 support for Google Mock Doctor.
+ * Added gmock_all_test.cc for compiling most Google Mock tests
+   in a single file.
+ * Significantly cleaned up compiler warnings.
+ * Bug fixes, better test coverage, and implementation clean-ups.
+
+ Potentially breaking changes:
+
+ * Custom matchers defined using MatcherInterface or MakePolymorphicMatcher()
+   need to be updated after upgrading to Google Mock 1.5.0; matchers defined
+   using MATCHER or MATCHER_P* aren't affected.
+ * Dropped support for 'make install'.
+
+Changes for 1.4.0 (we skipped 1.2.* and 1.3.* to match the version of
+Google Test):
+
+ * Works in more environments: Symbian and minGW, Visual C++ 7.1.
+ * Lighter weight: comes with our own implementation of TR1 tuple (no
+   more dependency on Boost!).
+ * New feature: --gmock_catch_leaked_mocks for detecting leaked mocks.
+ * New feature: ACTION_TEMPLATE for defining templatized actions.
+ * New feature: the .After() clause for specifying expectation order.
+ * New feature: the .With() clause for for specifying inter-argument
+   constraints.
+ * New feature: actions ReturnArg<k>(), ReturnNew<T>(...), and
+   DeleteArg<k>().
+ * New feature: matchers Key(), Pair(), Args<...>(), AllArgs(), IsNull(),
+   and Contains().
+ * New feature: utility class MockFunction<F>, useful for checkpoints, etc.
+ * New feature: functions Value(x, m) and SafeMatcherCast<T>(m).
+ * New feature: copying a mock object is rejected at compile time.
+ * New feature: a script for fusing all Google Mock and Google Test
+   source files for easy deployment.
+ * Improved the Google Mock doctor to diagnose more diseases.
+ * Improved the Google Mock generator script.
+ * Compatibility fixes for Mac OS X and gcc.
+ * Bug fixes and implementation clean-ups.
+
+Changes for 1.1.0:
+
+ * New feature: ability to use Google Mock with any testing framework.
+ * New feature: macros for easily defining new matchers
+ * New feature: macros for easily defining new actions.
+ * New feature: more container matchers.
+ * New feature: actions for accessing function arguments and throwing
+   exceptions.
+ * Improved the Google Mock doctor script for diagnosing compiler errors.
+ * Bug fixes and implementation clean-ups.
+
+Changes for 1.0.0:
+
+ * Initial Open Source release of Google Mock
diff --git a/third_party/googletest/googlemock/CMakeLists.txt b/third_party/googletest/googlemock/CMakeLists.txt
new file mode 100644
index 0000000..cd52277
--- /dev/null
+++ b/third_party/googletest/googlemock/CMakeLists.txt
@@ -0,0 +1,186 @@
+########################################################################
+# CMake build script for Google Mock.
+#
+# To run the tests for Google Mock itself on Linux, use 'make test' or
+# ctest.  You can select which tests to run using 'ctest -R regex'.
+# For more options, run 'ctest --help'.
+
+# BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to
+# make it prominent in the GUI.
+option(BUILD_SHARED_LIBS "Build shared libraries (DLLs)." OFF)
+
+option(gmock_build_tests "Build all of Google Mock's own tests." OFF)
+
+# A directory to find Google Test sources.
+if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/gtest/CMakeLists.txt")
+  set(gtest_dir gtest)
+else()
+  set(gtest_dir ../googletest)
+endif()
+
+# Defines pre_project_set_up_hermetic_build() and set_up_hermetic_build().
+include("${gtest_dir}/cmake/hermetic_build.cmake" OPTIONAL)
+
+if (COMMAND pre_project_set_up_hermetic_build)
+  # Google Test also calls hermetic setup functions from add_subdirectory,
+  # although its changes will not affect things at the current scope.
+  pre_project_set_up_hermetic_build()
+endif()
+
+########################################################################
+#
+# Project-wide settings
+
+# Name of the project.
+#
+# CMake files in this project can refer to the root source directory
+# as ${gmock_SOURCE_DIR} and to the root binary directory as
+# ${gmock_BINARY_DIR}.
+# Language "C" is required for find_package(Threads).
+project(gmock CXX C)
+cmake_minimum_required(VERSION 2.6.2)
+
+if (COMMAND set_up_hermetic_build)
+  set_up_hermetic_build()
+endif()
+
+# Instructs CMake to process Google Test's CMakeLists.txt and add its
+# targets to the current scope.  We are placing Google Test's binary
+# directory in a subdirectory of our own as VC compilation may break
+# if they are the same (the default).
+add_subdirectory("${gtest_dir}" "${gmock_BINARY_DIR}/gtest")
+
+# Although Google Test's CMakeLists.txt calls this function, the
+# changes there don't affect the current scope.  Therefore we have to
+# call it again here.
+config_compiler_and_linker()  # from ${gtest_dir}/cmake/internal_utils.cmake
+
+# Adds Google Mock's and Google Test's header directories to the search path.
+include_directories("${gmock_SOURCE_DIR}/include"
+                    "${gmock_SOURCE_DIR}"
+                    "${gtest_SOURCE_DIR}/include"
+                    # This directory is needed to build directly from Google
+                    # Test sources.
+                    "${gtest_SOURCE_DIR}")
+
+# Summary of tuple support for Microsoft Visual Studio:
+# Compiler    version(MS)  version(cmake)  Support
+# ----------  -----------  --------------  -----------------------------
+# <= VS 2010  <= 10        <= 1600         Use Google Tests's own tuple.
+# VS 2012     11           1700            std::tr1::tuple + _VARIADIC_MAX=10
+# VS 2013     12           1800            std::tr1::tuple
+if (MSVC AND MSVC_VERSION EQUAL 1700)
+  add_definitions(/D _VARIADIC_MAX=10)
+endif()
+
+########################################################################
+#
+# Defines the gmock & gmock_main libraries.  User tests should link
+# with one of them.
+
+# Google Mock libraries.  We build them using more strict warnings than what
+# are used for other targets, to ensure that Google Mock can be compiled by
+# a user aggressive about warnings.
+cxx_library(gmock
+            "${cxx_strict}"
+            "${gtest_dir}/src/gtest-all.cc"
+            src/gmock-all.cc)
+
+cxx_library(gmock_main
+            "${cxx_strict}"
+            "${gtest_dir}/src/gtest-all.cc"
+            src/gmock-all.cc
+            src/gmock_main.cc)
+
+########################################################################
+#
+# Google Mock's own tests.
+#
+# You can skip this section if you aren't interested in testing
+# Google Mock itself.
+#
+# The tests are not built by default.  To build them, set the
+# gmock_build_tests option to ON.  You can do it by running ccmake
+# or specifying the -Dgmock_build_tests=ON flag when running cmake.
+
+if (gmock_build_tests)
+  # This must be set in the root directory for the tests to be run by
+  # 'make test' or ctest.
+  enable_testing()
+
+  ############################################################
+  # C++ tests built with standard compiler flags.
+
+  cxx_test(gmock-actions_test gmock_main)
+  cxx_test(gmock-cardinalities_test gmock_main)
+  cxx_test(gmock_ex_test gmock_main)
+  cxx_test(gmock-generated-actions_test gmock_main)
+  cxx_test(gmock-generated-function-mockers_test gmock_main)
+  cxx_test(gmock-generated-internal-utils_test gmock_main)
+  cxx_test(gmock-generated-matchers_test gmock_main)
+  cxx_test(gmock-internal-utils_test gmock_main)
+  cxx_test(gmock-matchers_test gmock_main)
+  cxx_test(gmock-more-actions_test gmock_main)
+  cxx_test(gmock-nice-strict_test gmock_main)
+  cxx_test(gmock-port_test gmock_main)
+  cxx_test(gmock-spec-builders_test gmock_main)
+  cxx_test(gmock_link_test gmock_main test/gmock_link2_test.cc)
+  cxx_test(gmock_test gmock_main)
+
+  if (CMAKE_USE_PTHREADS_INIT)
+    cxx_test(gmock_stress_test gmock)
+  endif()
+
+  # gmock_all_test is commented to save time building and running tests.
+  # Uncomment if necessary.
+  # cxx_test(gmock_all_test gmock_main)
+
+  ############################################################
+  # C++ tests built with non-standard compiler flags.
+
+  cxx_library(gmock_main_no_exception "${cxx_no_exception}"
+    "${gtest_dir}/src/gtest-all.cc" src/gmock-all.cc src/gmock_main.cc)
+
+  cxx_library(gmock_main_no_rtti "${cxx_no_rtti}"
+    "${gtest_dir}/src/gtest-all.cc" src/gmock-all.cc src/gmock_main.cc)
+
+  if (NOT MSVC OR MSVC_VERSION LESS 1600)  # 1600 is Visual Studio 2010.
+    # Visual Studio 2010, 2012, and 2013 define symbols in std::tr1 that
+    # conflict with our own definitions. Therefore using our own tuple does not
+    # work on those compilers.
+    cxx_library(gmock_main_use_own_tuple "${cxx_use_own_tuple}"
+      "${gtest_dir}/src/gtest-all.cc" src/gmock-all.cc src/gmock_main.cc)
+
+    cxx_test_with_flags(gmock_use_own_tuple_test "${cxx_use_own_tuple}"
+      gmock_main_use_own_tuple test/gmock-spec-builders_test.cc)
+  endif()
+
+  cxx_test_with_flags(gmock-more-actions_no_exception_test "${cxx_no_exception}"
+    gmock_main_no_exception test/gmock-more-actions_test.cc)
+
+  cxx_test_with_flags(gmock_no_rtti_test "${cxx_no_rtti}"
+    gmock_main_no_rtti test/gmock-spec-builders_test.cc)
+
+  cxx_shared_library(shared_gmock_main "${cxx_default}"
+    "${gtest_dir}/src/gtest-all.cc" src/gmock-all.cc src/gmock_main.cc)
+
+  # Tests that a binary can be built with Google Mock as a shared library.  On
+  # some system configurations, it may not possible to run the binary without
+  # knowing more details about the system configurations. We do not try to run
+  # this binary. To get a more robust shared library coverage, configure with
+  # -DBUILD_SHARED_LIBS=ON.
+  cxx_executable_with_flags(shared_gmock_test_ "${cxx_default}"
+    shared_gmock_main test/gmock-spec-builders_test.cc)
+  set_target_properties(shared_gmock_test_
+    PROPERTIES
+    COMPILE_DEFINITIONS "GTEST_LINKED_AS_SHARED_LIBRARY=1")
+
+  ############################################################
+  # Python tests.
+
+  cxx_executable(gmock_leak_test_ test gmock_main)
+  py_test(gmock_leak_test)
+
+  cxx_executable(gmock_output_test_ test gmock)
+  py_test(gmock_output_test)
+endif()
diff --git a/third_party/googletest/googlemock/CONTRIBUTORS b/third_party/googletest/googlemock/CONTRIBUTORS
new file mode 100644
index 0000000..6e9ae36
--- /dev/null
+++ b/third_party/googletest/googlemock/CONTRIBUTORS
@@ -0,0 +1,40 @@
+# This file contains a list of people who've made non-trivial
+# contribution to the Google C++ Mocking Framework project.  People
+# who commit code to the project are encouraged to add their names
+# here.  Please keep the list sorted by first names.
+
+Benoit Sigoure <tsuna@google.com>
+Bogdan Piloca <boo@google.com>
+Chandler Carruth <chandlerc@google.com>
+Dave MacLachlan <dmaclach@gmail.com>
+David Anderson <danderson@google.com>
+Dean Sturtevant
+Gene Volovich <gv@cite.com>
+Hal Burch <gmock@hburch.com>
+Jeffrey Yasskin <jyasskin@google.com>
+Jim Keller <jimkeller@google.com>
+Joe Walnes <joe@truemesh.com>
+Jon Wray <jwray@google.com>
+Keir Mierle <mierle@gmail.com>
+Keith Ray <keith.ray@gmail.com>
+Kostya Serebryany <kcc@google.com>
+Lev Makhlis
+Manuel Klimek <klimek@google.com>
+Mario Tanev <radix@google.com>
+Mark Paskin
+Markus Heule <markus.heule@gmail.com>
+Matthew Simmons <simmonmt@acm.org>
+Mike Bland <mbland@google.com>
+Neal Norwitz <nnorwitz@gmail.com>
+Nermin Ozkiranartli <nermin@google.com>
+Owen Carlsen <ocarlsen@google.com>
+Paneendra Ba <paneendra@google.com>
+Paul Menage <menage@google.com>
+Piotr Kaminski <piotrk@google.com>
+Russ Rufer <russ@pentad.com>
+Sverre Sundsdal <sundsdal@gmail.com>
+Takeshi Yoshino <tyoshino@google.com>
+Vadim Berman <vadimb@google.com>
+Vlad Losev <vladl@google.com>
+Wolfgang Klier <wklier@google.com>
+Zhanyong Wan <wan@google.com>
diff --git a/third_party/googletest/googlemock/LICENSE b/third_party/googletest/googlemock/LICENSE
new file mode 100644
index 0000000..1941a11
--- /dev/null
+++ b/third_party/googletest/googlemock/LICENSE
@@ -0,0 +1,28 @@
+Copyright 2008, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+    * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/third_party/googletest/googlemock/Makefile.am b/third_party/googletest/googlemock/Makefile.am
new file mode 100644
index 0000000..7ad4588
--- /dev/null
+++ b/third_party/googletest/googlemock/Makefile.am
@@ -0,0 +1,220 @@
+# Automake file
+
+# Nonstandard package files for distribution.
+EXTRA_DIST = LICENSE
+
+# We may need to build our internally packaged gtest. If so, it will be
+# included in the 'subdirs' variable.
+SUBDIRS = $(subdirs)
+
+# This is generated by the configure script, so clean it for distribution.
+DISTCLEANFILES = scripts/gmock-config
+
+# We define the global AM_CPPFLAGS as everything we compile includes from these
+# directories.
+AM_CPPFLAGS = $(GTEST_CPPFLAGS) -I$(srcdir)/include
+
+# Modifies compiler and linker flags for pthreads compatibility.
+if HAVE_PTHREADS
+  AM_CXXFLAGS = @PTHREAD_CFLAGS@ -DGTEST_HAS_PTHREAD=1
+  AM_LIBS = @PTHREAD_LIBS@
+endif
+
+# Build rules for libraries.
+lib_LTLIBRARIES = lib/libgmock.la lib/libgmock_main.la
+
+lib_libgmock_la_SOURCES = src/gmock-all.cc
+
+pkginclude_HEADERS = \
+  include/gmock/gmock-actions.h \
+  include/gmock/gmock-cardinalities.h \
+  include/gmock/gmock-generated-actions.h \
+  include/gmock/gmock-generated-function-mockers.h \
+  include/gmock/gmock-generated-matchers.h \
+  include/gmock/gmock-generated-nice-strict.h \
+  include/gmock/gmock-matchers.h \
+  include/gmock/gmock-more-actions.h \
+  include/gmock/gmock-more-matchers.h \
+  include/gmock/gmock-spec-builders.h \
+  include/gmock/gmock.h
+
+pkginclude_internaldir = $(pkgincludedir)/internal
+pkginclude_internal_HEADERS = \
+  include/gmock/internal/gmock-generated-internal-utils.h \
+  include/gmock/internal/gmock-internal-utils.h \
+  include/gmock/internal/gmock-port.h
+
+lib_libgmock_main_la_SOURCES = src/gmock_main.cc
+lib_libgmock_main_la_LIBADD = lib/libgmock.la
+
+# Build rules for tests. Automake's naming for some of these variables isn't
+# terribly obvious, so this is a brief reference:
+#
+# TESTS -- Programs run automatically by "make check"
+# check_PROGRAMS -- Programs built by "make check" but not necessarily run
+
+TESTS=
+check_PROGRAMS=
+AM_LDFLAGS = $(GTEST_LDFLAGS)
+
+# This exercises all major components of Google Mock.  It also
+# verifies that libgmock works.
+TESTS += test/gmock-spec-builders_test
+check_PROGRAMS += test/gmock-spec-builders_test
+test_gmock_spec_builders_test_SOURCES = test/gmock-spec-builders_test.cc
+test_gmock_spec_builders_test_LDADD = $(GTEST_LIBS) lib/libgmock.la
+
+# This tests using Google Mock in multiple translation units.  It also
+# verifies that libgmock_main and libgmock work.
+TESTS += test/gmock_link_test
+check_PROGRAMS += test/gmock_link_test
+test_gmock_link_test_SOURCES = \
+  test/gmock_link2_test.cc \
+  test/gmock_link_test.cc \
+  test/gmock_link_test.h
+test_gmock_link_test_LDADD = $(GTEST_LIBS) lib/libgmock_main.la  lib/libgmock.la
+
+if HAVE_PYTHON
+  # Tests that fused gmock files compile and work.
+  TESTS += test/gmock_fused_test
+  check_PROGRAMS += test/gmock_fused_test
+  test_gmock_fused_test_SOURCES = \
+    fused-src/gmock-gtest-all.cc \
+    fused-src/gmock/gmock.h \
+    fused-src/gmock_main.cc \
+    fused-src/gtest/gtest.h \
+    test/gmock_test.cc
+  test_gmock_fused_test_CPPFLAGS = -I"$(srcdir)/fused-src"
+endif
+
+# Google Mock source files that we don't compile directly.
+GMOCK_SOURCE_INGLUDES = \
+  src/gmock-cardinalities.cc \
+  src/gmock-internal-utils.cc \
+  src/gmock-matchers.cc \
+  src/gmock-spec-builders.cc \
+  src/gmock.cc
+
+EXTRA_DIST += $(GMOCK_SOURCE_INGLUDES)
+
+# C++ tests that we don't compile using autotools.
+EXTRA_DIST += \
+  test/gmock-actions_test.cc \
+  test/gmock_all_test.cc \
+  test/gmock-cardinalities_test.cc \
+  test/gmock_ex_test.cc \
+  test/gmock-generated-actions_test.cc \
+  test/gmock-generated-function-mockers_test.cc \
+  test/gmock-generated-internal-utils_test.cc \
+  test/gmock-generated-matchers_test.cc \
+  test/gmock-internal-utils_test.cc \
+  test/gmock-matchers_test.cc \
+  test/gmock-more-actions_test.cc \
+  test/gmock-nice-strict_test.cc \
+  test/gmock-port_test.cc \
+  test/gmock_stress_test.cc
+
+# Python tests, which we don't run using autotools.
+EXTRA_DIST += \
+  test/gmock_leak_test.py \
+  test/gmock_leak_test_.cc \
+  test/gmock_output_test.py \
+  test/gmock_output_test_.cc \
+  test/gmock_output_test_golden.txt \
+  test/gmock_test_utils.py
+
+# Nonstandard package files for distribution.
+EXTRA_DIST += \
+  CHANGES \
+  CONTRIBUTORS \
+  make/Makefile
+
+# Pump scripts for generating Google Mock headers.
+# TODO(chandlerc@google.com): automate the generation of *.h from *.h.pump.
+EXTRA_DIST += \
+  include/gmock/gmock-generated-actions.h.pump \
+  include/gmock/gmock-generated-function-mockers.h.pump \
+  include/gmock/gmock-generated-matchers.h.pump \
+  include/gmock/gmock-generated-nice-strict.h.pump \
+  include/gmock/internal/gmock-generated-internal-utils.h.pump
+
+# Script for fusing Google Mock and Google Test source files.
+EXTRA_DIST += scripts/fuse_gmock_files.py
+
+# The Google Mock Generator tool from the cppclean project.
+EXTRA_DIST += \
+  scripts/generator/LICENSE \
+  scripts/generator/README \
+  scripts/generator/README.cppclean \
+  scripts/generator/cpp/__init__.py \
+  scripts/generator/cpp/ast.py \
+  scripts/generator/cpp/gmock_class.py \
+  scripts/generator/cpp/keywords.py \
+  scripts/generator/cpp/tokenize.py \
+  scripts/generator/cpp/utils.py \
+  scripts/generator/gmock_gen.py
+
+# Script for diagnosing compiler errors in programs that use Google
+# Mock.
+EXTRA_DIST += scripts/gmock_doctor.py
+
+# CMake scripts.
+EXTRA_DIST += \
+  CMakeLists.txt
+
+# Microsoft Visual Studio 2005 projects.
+EXTRA_DIST += \
+  msvc/2005/gmock.sln \
+  msvc/2005/gmock.vcproj \
+  msvc/2005/gmock_config.vsprops \
+  msvc/2005/gmock_main.vcproj \
+  msvc/2005/gmock_test.vcproj
+
+# Microsoft Visual Studio 2010 projects.
+EXTRA_DIST += \
+  msvc/2010/gmock.sln \
+  msvc/2010/gmock.vcxproj \
+  msvc/2010/gmock_config.props \
+  msvc/2010/gmock_main.vcxproj \
+  msvc/2010/gmock_test.vcxproj
+
+if HAVE_PYTHON
+# gmock_test.cc does not really depend on files generated by the
+# fused-gmock-internal rule.  However, gmock_test.o does, and it is
+# important to include test/gmock_test.cc as part of this rule in order to
+# prevent compiling gmock_test.o until all dependent files have been
+# generated.
+$(test_gmock_fused_test_SOURCES): fused-gmock-internal
+
+# TODO(vladl@google.com): Find a way to add Google Tests's sources here.
+fused-gmock-internal: $(pkginclude_HEADERS) $(pkginclude_internal_HEADERS) \
+                      $(lib_libgmock_la_SOURCES) $(GMOCK_SOURCE_INGLUDES) \
+                      $(lib_libgmock_main_la_SOURCES) \
+                      scripts/fuse_gmock_files.py
+	mkdir -p "$(srcdir)/fused-src"
+	chmod -R u+w "$(srcdir)/fused-src"
+	rm -f "$(srcdir)/fused-src/gtest/gtest.h"
+	rm -f "$(srcdir)/fused-src/gmock/gmock.h"
+	rm -f "$(srcdir)/fused-src/gmock-gtest-all.cc"
+	"$(srcdir)/scripts/fuse_gmock_files.py" "$(srcdir)/fused-src"
+	cp -f "$(srcdir)/src/gmock_main.cc" "$(srcdir)/fused-src"
+
+maintainer-clean-local:
+	rm -rf "$(srcdir)/fused-src"
+endif
+
+# Death tests may produce core dumps in the build directory. In case
+# this happens, clean them to keep distcleancheck happy.
+CLEANFILES = core
+
+# Disables 'make install' as installing a compiled version of Google
+# Mock can lead to undefined behavior due to violation of the
+# One-Definition Rule.
+
+install-exec-local:
+	echo "'make install' is dangerous and not supported. Instead, see README for how to integrate Google Mock into your build system."
+	false
+
+install-data-local:
+	echo "'make install' is dangerous and not supported. Instead, see README for how to integrate Google Mock into your build system."
+	false
diff --git a/third_party/googletest/googlemock/README.md b/third_party/googletest/googlemock/README.md
new file mode 100644
index 0000000..c455646
--- /dev/null
+++ b/third_party/googletest/googlemock/README.md
@@ -0,0 +1,333 @@
+## Google Mock ##
+
+The Google C++ mocking framework.
+
+### Overview ###
+
+Google's framework for writing and using C++ mock classes.
+It can help you derive better designs of your system and write better tests.
+
+It is inspired by:
+
+  * [jMock](http://www.jmock.org/),
+  * [EasyMock](http://www.easymock.org/), and
+  * [Hamcrest](http://code.google.com/p/hamcrest/),
+
+and designed with C++'s specifics in mind.
+
+Google mock:
+
+  * lets you create mock classes trivially using simple macros.
+  * supports a rich set of matchers and actions.
+  * handles unordered, partially ordered, or completely ordered expectations.
+  * is extensible by users.
+
+We hope you find it useful!
+
+### Features ###
+
+  * Provides a declarative syntax for defining mocks.
+  * Can easily define partial (hybrid) mocks, which are a cross of real
+    and mock objects.
+  * Handles functions of arbitrary types and overloaded functions.
+  * Comes with a rich set of matchers for validating function arguments.
+  * Uses an intuitive syntax for controlling the behavior of a mock.
+  * Does automatic verification of expectations (no record-and-replay needed).
+  * Allows arbitrary (partial) ordering constraints on
+    function calls to be expressed,.
+  * Lets a user extend it by defining new matchers and actions.
+  * Does not use exceptions.
+  * Is easy to learn and use.
+
+Please see the project page above for more information as well as the
+mailing list for questions, discussions, and development.  There is
+also an IRC channel on OFTC (irc.oftc.net) #gtest available.  Please
+join us!
+
+Please note that code under [scripts/generator](scripts/generator/) is
+from [cppclean](http://code.google.com/p/cppclean/) and released under
+the Apache License, which is different from Google Mock's license.
+
+## Getting Started ##
+
+If you are new to the project, we suggest that you read the user
+documentation in the following order:
+
+  * Learn the [basics](../googletest/docs/Primer.md) of
+    Google Test, if you choose to use Google Mock with it (recommended).
+  * Read [Google Mock for Dummies](docs/ForDummies.md).
+  * Read the instructions below on how to build Google Mock.
+
+You can also watch Zhanyong's [talk](http://www.youtube.com/watch?v=sYpCyLI47rM) on Google Mock's usage and implementation.
+
+Once you understand the basics, check out the rest of the docs:
+
+  * [CheatSheet](googlemock/docs/CheatSheet.md) - all the commonly used stuff
+    at a glance.
+  * [CookBook](googlemock/docs/CookBook.md) - recipes for getting things done,
+    including advanced techniques.
+
+If you need help, please check the
+[KnownIssues](googlemock/docs/KnownIssues.md) and
+[FrequentlyAskedQuestions](googlemock/docs/frequentlyaskedquestions.md) before
+posting a question on the
+[discussion group](http://groups.google.com/group/googlemock).
+
+
+### Using Google Mock Without Google Test ###
+
+Google Mock is not a testing framework itself.  Instead, it needs a
+testing framework for writing tests.  Google Mock works seamlessly
+with [Google Test](http://code.google.com/p/googletest/), butj
+you can also use it with [any C++ testing framework](googlemock/ForDummies.md#Using_Google_Mock_with_Any_Testing_Framework).
+
+### Requirements for End Users ###
+
+Google Mock is implemented on top of [Google Test](
+http://github.com/google/googletest/), and depends on it.
+You must use the bundled version of Google Test when using Google Mock.
+
+You can also easily configure Google Mock to work with another testing
+framework, although it will still need Google Test.  Please read
+["Using_Google_Mock_with_Any_Testing_Framework"](
+    docs/ForDummies.md#Using_Google_Mock_with_Any_Testing_Framework)
+for instructions.
+
+Google Mock depends on advanced C++ features and thus requires a more
+modern compiler. The following are needed to use Google Mock:
+
+#### Linux Requirements ####
+
+  * GNU-compatible Make or "gmake"
+  * POSIX-standard shell
+  * POSIX(-2) Regular Expressions (regex.h)
+  * C++98-standard-compliant compiler (e.g. GCC 3.4 or newer)
+
+#### Windows Requirements ####
+
+  * Microsoft Visual C++ 8.0 SP1 or newer
+
+#### Mac OS X Requirements ####
+
+  * Mac OS X 10.4 Tiger or newer
+  * Developer Tools Installed
+
+### Requirements for Contributors ###
+
+We welcome patches. If you plan to contribute a patch, you need to
+build Google Mock and its tests, which has further requirements:
+
+  * Automake version 1.9 or newer
+  * Autoconf version 2.59 or newer
+  * Libtool / Libtoolize
+  * Python version 2.3 or newer (for running some of the tests and
+    re-generating certain source files from templates)
+
+### Building Google Mock ###
+
+#### Preparing to Build (Unix only) ####
+
+If you are using a Unix system and plan to use the GNU Autotools build
+system to build Google Mock (described below), you'll need to
+configure it now.
+
+To prepare the Autotools build system:
+
+    cd googlemock
+    autoreconf -fvi
+
+To build Google Mock and your tests that use it, you need to tell your
+build system where to find its headers and source files.  The exact
+way to do it depends on which build system you use, and is usually
+straightforward.
+
+This section shows how you can integrate Google Mock into your
+existing build system.
+
+Suppose you put Google Mock in directory `${GMOCK_DIR}` and Google Test
+in `${GTEST_DIR}` (the latter is `${GMOCK_DIR}/gtest` by default).  To
+build Google Mock, create a library build target (or a project as
+called by Visual Studio and Xcode) to compile
+
+    ${GTEST_DIR}/src/gtest-all.cc and ${GMOCK_DIR}/src/gmock-all.cc
+
+with
+
+    ${GTEST_DIR}/include and ${GMOCK_DIR}/include
+
+in the system header search path, and
+
+    ${GTEST_DIR} and ${GMOCK_DIR}
+
+in the normal header search path.  Assuming a Linux-like system and gcc,
+something like the following will do:
+
+    g++ -isystem ${GTEST_DIR}/include -I${GTEST_DIR} \
+        -isystem ${GMOCK_DIR}/include -I${GMOCK_DIR} \
+        -pthread -c ${GTEST_DIR}/src/gtest-all.cc
+    g++ -isystem ${GTEST_DIR}/include -I${GTEST_DIR} \
+        -isystem ${GMOCK_DIR}/include -I${GMOCK_DIR} \
+        -pthread -c ${GMOCK_DIR}/src/gmock-all.cc
+    ar -rv libgmock.a gtest-all.o gmock-all.o
+
+(We need -pthread as Google Test and Google Mock use threads.)
+
+Next, you should compile your test source file with
+${GTEST\_DIR}/include and ${GMOCK\_DIR}/include in the header search
+path, and link it with gmock and any other necessary libraries:
+
+    g++ -isystem ${GTEST_DIR}/include -isystem ${GMOCK_DIR}/include \
+        -pthread path/to/your_test.cc libgmock.a -o your_test
+
+As an example, the make/ directory contains a Makefile that you can
+use to build Google Mock on systems where GNU make is available
+(e.g. Linux, Mac OS X, and Cygwin).  It doesn't try to build Google
+Mock's own tests.  Instead, it just builds the Google Mock library and
+a sample test.  You can use it as a starting point for your own build
+script.
+
+If the default settings are correct for your environment, the
+following commands should succeed:
+
+    cd ${GMOCK_DIR}/make
+    make
+    ./gmock_test
+
+If you see errors, try to tweak the contents of
+[make/Makefile](make/Makefile) to make them go away.
+
+### Windows ###
+
+The msvc/2005 directory contains VC++ 2005 projects and the msvc/2010
+directory contains VC++ 2010 projects for building Google Mock and
+selected tests.
+
+Change to the appropriate directory and run "msbuild gmock.sln" to
+build the library and tests (or open the gmock.sln in the MSVC IDE).
+If you want to create your own project to use with Google Mock, you'll
+have to configure it to use the `gmock_config` propety sheet.  For that:
+
+ * Open the Property Manager window (View | Other Windows | Property Manager)
+ * Right-click on your project and select "Add Existing Property Sheet..."
+ * Navigate to `gmock_config.vsprops` or `gmock_config.props` and select it.
+ * In Project Properties | Configuration Properties | General | Additional
+   Include Directories, type <path to Google Mock>/include.
+
+### Tweaking Google Mock ###
+
+Google Mock can be used in diverse environments.  The default
+configuration may not work (or may not work well) out of the box in
+some environments.  However, you can easily tweak Google Mock by
+defining control macros on the compiler command line.  Generally,
+these macros are named like `GTEST_XYZ` and you define them to either 1
+or 0 to enable or disable a certain feature.
+
+We list the most frequently used macros below.  For a complete list,
+see file [${GTEST\_DIR}/include/gtest/internal/gtest-port.h](
+../googletest/include/gtest/internal/gtest-port.h).
+
+### Choosing a TR1 Tuple Library ###
+
+Google Mock uses the C++ Technical Report 1 (TR1) tuple library
+heavily.  Unfortunately TR1 tuple is not yet widely available with all
+compilers.  The good news is that Google Test 1.4.0+ implements a
+subset of TR1 tuple that's enough for Google Mock's need.  Google Mock
+will automatically use that implementation when the compiler doesn't
+provide TR1 tuple.
+
+Usually you don't need to care about which tuple library Google Test
+and Google Mock use.  However, if your project already uses TR1 tuple,
+you need to tell Google Test and Google Mock to use the same TR1 tuple
+library the rest of your project uses, or the two tuple
+implementations will clash.  To do that, add
+
+    -DGTEST_USE_OWN_TR1_TUPLE=0
+
+to the compiler flags while compiling Google Test, Google Mock, and
+your tests.  If you want to force Google Test and Google Mock to use
+their own tuple library, just add
+
+    -DGTEST_USE_OWN_TR1_TUPLE=1
+
+to the compiler flags instead.
+
+If you want to use Boost's TR1 tuple library with Google Mock, please
+refer to the Boost website (http://www.boost.org/) for how to obtain
+it and set it up.
+
+### As a Shared Library (DLL) ###
+
+Google Mock is compact, so most users can build and link it as a static
+library for the simplicity.  Google Mock can be used as a DLL, but the
+same DLL must contain Google Test as well.  See
+[Google Test's README][gtest_readme]
+for instructions on how to set up necessary compiler settings.
+
+### Tweaking Google Mock ###
+
+Most of Google Test's control macros apply to Google Mock as well.
+Please see [Google Test's README][gtest_readme] for how to tweak them.
+
+### Upgrading from an Earlier Version ###
+
+We strive to keep Google Mock releases backward compatible.
+Sometimes, though, we have to make some breaking changes for the
+users' long-term benefits.  This section describes what you'll need to
+do if you are upgrading from an earlier version of Google Mock.
+
+#### Upgrading from 1.1.0 or Earlier ####
+
+You may need to explicitly enable or disable Google Test's own TR1
+tuple library.  See the instructions in section "[Choosing a TR1 Tuple
+Library](../googletest/#choosing-a-tr1-tuple-library)".
+
+#### Upgrading from 1.4.0 or Earlier ####
+
+On platforms where the pthread library is available, Google Test and
+Google Mock use it in order to be thread-safe.  For this to work, you
+may need to tweak your compiler and/or linker flags.  Please see the
+"[Multi-threaded Tests](../googletest#multi-threaded-tests
+)" section in file Google Test's README for what you may need to do.
+
+If you have custom matchers defined using `MatcherInterface` or
+`MakePolymorphicMatcher()`, you'll need to update their definitions to
+use the new matcher API (
+[monomorphic](http://code.google.com/p/googlemock/wiki/CookBook#Writing_New_Monomorphic_Matchers),
+[polymorphic](http://code.google.com/p/googlemock/wiki/CookBook#Writing_New_Polymorphic_Matchers)).
+Matchers defined using `MATCHER()` or `MATCHER_P*()` aren't affected.
+
+### Developing Google Mock ###
+
+This section discusses how to make your own changes to Google Mock.
+
+#### Testing Google Mock Itself ####
+
+To make sure your changes work as intended and don't break existing
+functionality, you'll want to compile and run Google Test's own tests.
+For that you'll need Autotools.  First, make sure you have followed
+the instructions above to configure Google Mock.
+Then, create a build output directory and enter it.  Next,
+
+    ${GMOCK_DIR}/configure  # try --help for more info
+
+Once you have successfully configured Google Mock, the build steps are
+standard for GNU-style OSS packages.
+
+    make        # Standard makefile following GNU conventions
+    make check  # Builds and runs all tests - all should pass.
+
+Note that when building your project against Google Mock, you are building
+against Google Test as well.  There is no need to configure Google Test
+separately.
+
+#### Contributing a Patch ####
+
+We welcome patches.
+Please read the [Developer's Guide](docs/DevGuide.md)
+for how you can contribute. In particular, make sure you have signed
+the Contributor License Agreement, or we won't be able to accept the
+patch.
+
+Happy testing!
+
+[gtest_readme]: ../googletest/README.md "googletest"
diff --git a/third_party/googletest/googlemock/build-aux/.keep b/third_party/googletest/googlemock/build-aux/.keep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/third_party/googletest/googlemock/build-aux/.keep
diff --git a/third_party/googletest/googlemock/configure.ac b/third_party/googletest/googlemock/configure.ac
new file mode 100644
index 0000000..d268d5d
--- /dev/null
+++ b/third_party/googletest/googlemock/configure.ac
@@ -0,0 +1,146 @@
+m4_include(gtest/m4/acx_pthread.m4)
+
+AC_INIT([Google C++ Mocking Framework],
+        [1.7.0],
+        [googlemock@googlegroups.com],
+        [gmock])
+
+# Provide various options to initialize the Autoconf and configure processes.
+AC_PREREQ([2.59])
+AC_CONFIG_SRCDIR([./LICENSE])
+AC_CONFIG_AUX_DIR([build-aux])
+AC_CONFIG_HEADERS([build-aux/config.h])
+AC_CONFIG_FILES([Makefile])
+AC_CONFIG_FILES([scripts/gmock-config], [chmod +x scripts/gmock-config])
+
+# Initialize Automake with various options. We require at least v1.9, prevent
+# pedantic complaints about package files, and enable various distribution
+# targets.
+AM_INIT_AUTOMAKE([1.9 dist-bzip2 dist-zip foreign subdir-objects])
+
+# Check for programs used in building Google Test.
+AC_PROG_CC
+AC_PROG_CXX
+AC_LANG([C++])
+AC_PROG_LIBTOOL
+
+# TODO(chandlerc@google.com): Currently we aren't running the Python tests
+# against the interpreter detected by AM_PATH_PYTHON, and so we condition
+# HAVE_PYTHON by requiring "python" to be in the PATH, and that interpreter's
+# version to be >= 2.3. This will allow the scripts to use a "/usr/bin/env"
+# hashbang.
+PYTHON=  # We *do not* allow the user to specify a python interpreter
+AC_PATH_PROG([PYTHON],[python],[:])
+AS_IF([test "$PYTHON" != ":"],
+      [AM_PYTHON_CHECK_VERSION([$PYTHON],[2.3],[:],[PYTHON=":"])])
+AM_CONDITIONAL([HAVE_PYTHON],[test "$PYTHON" != ":"])
+
+# TODO(chandlerc@google.com) Check for the necessary system headers.
+
+# Configure pthreads.
+AC_ARG_WITH([pthreads],
+            [AS_HELP_STRING([--with-pthreads],
+               [use pthreads (default is yes)])],
+            [with_pthreads=$withval],
+            [with_pthreads=check])
+
+have_pthreads=no
+AS_IF([test "x$with_pthreads" != "xno"],
+      [ACX_PTHREAD(
+        [],
+        [AS_IF([test "x$with_pthreads" != "xcheck"],
+               [AC_MSG_FAILURE(
+                 [--with-pthreads was specified, but unable to be used])])])
+       have_pthreads="$acx_pthread_ok"])
+AM_CONDITIONAL([HAVE_PTHREADS],[test "x$have_pthreads" == "xyes"])
+AC_SUBST(PTHREAD_CFLAGS)
+AC_SUBST(PTHREAD_LIBS)
+
+# GoogleMock currently has hard dependencies upon GoogleTest above and beyond
+# running its own test suite, so we both provide our own version in
+# a subdirectory and provide some logic to use a custom version or a system
+# installed version.
+AC_ARG_WITH([gtest],
+            [AS_HELP_STRING([--with-gtest],
+                            [Specifies how to find the gtest package. If no
+                            arguments are given, the default behavior, a
+                            system installed gtest will be used if present,
+                            and an internal version built otherwise. If a
+                            path is provided, the gtest built or installed at
+                            that prefix will be used.])],
+            [],
+            [with_gtest=yes])
+AC_ARG_ENABLE([external-gtest],
+              [AS_HELP_STRING([--disable-external-gtest],
+                              [Disables any detection or use of a system
+                              installed or user provided gtest. Any option to
+                              '--with-gtest' is ignored. (Default is enabled.)])
+              ], [], [enable_external_gtest=yes])
+AS_IF([test "x$with_gtest" == "xno"],
+      [AC_MSG_ERROR([dnl
+Support for GoogleTest was explicitly disabled. Currently GoogleMock has a hard
+dependency upon GoogleTest to build, please provide a version, or allow
+GoogleMock to use any installed version and fall back upon its internal
+version.])])
+
+# Setup various GTEST variables. TODO(chandlerc@google.com): When these are
+# used below, they should be used such that any pre-existing values always
+# trump values we set them to, so that they can be used to selectively override
+# details of the detection process.
+AC_ARG_VAR([GTEST_CONFIG],
+           [The exact path of Google Test's 'gtest-config' script.])
+AC_ARG_VAR([GTEST_CPPFLAGS],
+           [C-like preprocessor flags for Google Test.])
+AC_ARG_VAR([GTEST_CXXFLAGS],
+           [C++ compile flags for Google Test.])
+AC_ARG_VAR([GTEST_LDFLAGS],
+           [Linker path and option flags for Google Test.])
+AC_ARG_VAR([GTEST_LIBS],
+           [Library linking flags for Google Test.])
+AC_ARG_VAR([GTEST_VERSION],
+           [The version of Google Test available.])
+HAVE_BUILT_GTEST="no"
+
+GTEST_MIN_VERSION="1.7.0"
+
+AS_IF([test "x${enable_external_gtest}" = "xyes"],
+      [# Begin filling in variables as we are able.
+      AS_IF([test "x${with_gtest}" != "xyes"],
+            [AS_IF([test -x "${with_gtest}/scripts/gtest-config"],
+                   [GTEST_CONFIG="${with_gtest}/scripts/gtest-config"],
+                   [GTEST_CONFIG="${with_gtest}/bin/gtest-config"])
+            AS_IF([test -x "${GTEST_CONFIG}"], [],
+                  [AC_MSG_ERROR([dnl
+Unable to locate either a built or installed Google Test at '${with_gtest}'.])
+                  ])])
+
+      AS_IF([test -x "${GTEST_CONFIG}"], [],
+            [AC_PATH_PROG([GTEST_CONFIG], [gtest-config])])
+      AS_IF([test -x "${GTEST_CONFIG}"],
+            [AC_MSG_CHECKING([for Google Test version >= ${GTEST_MIN_VERSION}])
+            AS_IF([${GTEST_CONFIG} --min-version=${GTEST_MIN_VERSION}],
+                  [AC_MSG_RESULT([yes])
+                  HAVE_BUILT_GTEST="yes"],
+                  [AC_MSG_RESULT([no])])])])
+
+AS_IF([test "x${HAVE_BUILT_GTEST}" = "xyes"],
+      [GTEST_CPPFLAGS=`${GTEST_CONFIG} --cppflags`
+      GTEST_CXXFLAGS=`${GTEST_CONFIG} --cxxflags`
+      GTEST_LDFLAGS=`${GTEST_CONFIG} --ldflags`
+      GTEST_LIBS=`${GTEST_CONFIG} --libs`
+      GTEST_VERSION=`${GTEST_CONFIG} --version`],
+      [AC_CONFIG_SUBDIRS([gtest])
+      # GTEST_CONFIG needs to be executable both in a Makefile environmont and
+      # in a shell script environment, so resolve an absolute path for it here.
+      GTEST_CONFIG="`pwd -P`/gtest/scripts/gtest-config"
+      GTEST_CPPFLAGS='-I$(top_srcdir)/gtest/include'
+      GTEST_CXXFLAGS='-g'
+      GTEST_LDFLAGS=''
+      GTEST_LIBS='$(top_builddir)/gtest/lib/libgtest.la'
+      GTEST_VERSION="${GTEST_MIN_VERSION}"])
+
+# TODO(chandlerc@google.com) Check the types, structures, and other compiler
+# and architecture characteristics.
+
+# Output the generated files. No further autoconf macros may be used.
+AC_OUTPUT
diff --git a/third_party/googletest/googlemock/docs/CheatSheet.md b/third_party/googletest/googlemock/docs/CheatSheet.md
new file mode 100644
index 0000000..aef01b1
--- /dev/null
+++ b/third_party/googletest/googlemock/docs/CheatSheet.md
@@ -0,0 +1,562 @@
+
+
+# Defining a Mock Class #
+
+## Mocking a Normal Class ##
+
+Given
+```
+class Foo {
+  ...
+  virtual ~Foo();
+  virtual int GetSize() const = 0;
+  virtual string Describe(const char* name) = 0;
+  virtual string Describe(int type) = 0;
+  virtual bool Process(Bar elem, int count) = 0;
+};
+```
+(note that `~Foo()` **must** be virtual) we can define its mock as
+```
+#include "gmock/gmock.h"
+
+class MockFoo : public Foo {
+  MOCK_CONST_METHOD0(GetSize, int());
+  MOCK_METHOD1(Describe, string(const char* name));
+  MOCK_METHOD1(Describe, string(int type));
+  MOCK_METHOD2(Process, bool(Bar elem, int count));
+};
+```
+
+To create a "nice" mock object which ignores all uninteresting calls,
+or a "strict" mock object, which treats them as failures:
+```
+NiceMock<MockFoo> nice_foo;     // The type is a subclass of MockFoo.
+StrictMock<MockFoo> strict_foo; // The type is a subclass of MockFoo.
+```
+
+## Mocking a Class Template ##
+
+To mock
+```
+template <typename Elem>
+class StackInterface {
+ public:
+  ...
+  virtual ~StackInterface();
+  virtual int GetSize() const = 0;
+  virtual void Push(const Elem& x) = 0;
+};
+```
+(note that `~StackInterface()` **must** be virtual) just append `_T` to the `MOCK_*` macros:
+```
+template <typename Elem>
+class MockStack : public StackInterface<Elem> {
+ public:
+  ...
+  MOCK_CONST_METHOD0_T(GetSize, int());
+  MOCK_METHOD1_T(Push, void(const Elem& x));
+};
+```
+
+## Specifying Calling Conventions for Mock Functions ##
+
+If your mock function doesn't use the default calling convention, you
+can specify it by appending `_WITH_CALLTYPE` to any of the macros
+described in the previous two sections and supplying the calling
+convention as the first argument to the macro. For example,
+```
+  MOCK_METHOD_1_WITH_CALLTYPE(STDMETHODCALLTYPE, Foo, bool(int n));
+  MOCK_CONST_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, Bar, int(double x, double y));
+```
+where `STDMETHODCALLTYPE` is defined by `<objbase.h>` on Windows.
+
+# Using Mocks in Tests #
+
+The typical flow is:
+  1. Import the Google Mock names you need to use. All Google Mock names are in the `testing` namespace unless they are macros or otherwise noted.
+  1. Create the mock objects.
+  1. Optionally, set the default actions of the mock objects.
+  1. Set your expectations on the mock objects (How will they be called? What wil they do?).
+  1. Exercise code that uses the mock objects; if necessary, check the result using [Google Test](http://code.google.com/p/googletest/) assertions.
+  1. When a mock objects is destructed, Google Mock automatically verifies that all expectations on it have been satisfied.
+
+Here is an example:
+```
+using ::testing::Return;                            // #1
+
+TEST(BarTest, DoesThis) {
+  MockFoo foo;                                    // #2
+
+  ON_CALL(foo, GetSize())                         // #3
+      .WillByDefault(Return(1));
+  // ... other default actions ...
+
+  EXPECT_CALL(foo, Describe(5))                   // #4
+      .Times(3)
+      .WillRepeatedly(Return("Category 5"));
+  // ... other expectations ...
+
+  EXPECT_EQ("good", MyProductionFunction(&foo));  // #5
+}                                                 // #6
+```
+
+# Setting Default Actions #
+
+Google Mock has a **built-in default action** for any function that
+returns `void`, `bool`, a numeric value, or a pointer.
+
+To customize the default action for functions with return type `T` globally:
+```
+using ::testing::DefaultValue;
+
+// Sets the default value to be returned. T must be CopyConstructible.
+DefaultValue<T>::Set(value);
+// Sets a factory. Will be invoked on demand. T must be MoveConstructible.
+//   T MakeT();
+DefaultValue<T>::SetFactory(&MakeT);
+// ... use the mocks ...
+// Resets the default value.
+DefaultValue<T>::Clear();
+```
+
+To customize the default action for a particular method, use `ON_CALL()`:
+```
+ON_CALL(mock_object, method(matchers))
+    .With(multi_argument_matcher)  ?
+    .WillByDefault(action);
+```
+
+# Setting Expectations #
+
+`EXPECT_CALL()` sets **expectations** on a mock method (How will it be
+called? What will it do?):
+```
+EXPECT_CALL(mock_object, method(matchers))
+    .With(multi_argument_matcher)  ?
+    .Times(cardinality)            ?
+    .InSequence(sequences)         *
+    .After(expectations)           *
+    .WillOnce(action)              *
+    .WillRepeatedly(action)        ?
+    .RetiresOnSaturation();        ?
+```
+
+If `Times()` is omitted, the cardinality is assumed to be:
+
+  * `Times(1)` when there is neither `WillOnce()` nor `WillRepeatedly()`;
+  * `Times(n)` when there are `n WillOnce()`s but no `WillRepeatedly()`, where `n` >= 1; or
+  * `Times(AtLeast(n))` when there are `n WillOnce()`s and a `WillRepeatedly()`, where `n` >= 0.
+
+A method with no `EXPECT_CALL()` is free to be invoked _any number of times_, and the default action will be taken each time.
+
+# Matchers #
+
+A **matcher** matches a _single_ argument.  You can use it inside
+`ON_CALL()` or `EXPECT_CALL()`, or use it to validate a value
+directly:
+
+| `EXPECT_THAT(value, matcher)` | Asserts that `value` matches `matcher`. |
+|:------------------------------|:----------------------------------------|
+| `ASSERT_THAT(value, matcher)` | The same as `EXPECT_THAT(value, matcher)`, except that it generates a **fatal** failure. |
+
+Built-in matchers (where `argument` is the function argument) are
+divided into several categories:
+
+## Wildcard ##
+|`_`|`argument` can be any value of the correct type.|
+|:--|:-----------------------------------------------|
+|`A<type>()` or `An<type>()`|`argument` can be any value of type `type`.     |
+
+## Generic Comparison ##
+
+|`Eq(value)` or `value`|`argument == value`|
+|:---------------------|:------------------|
+|`Ge(value)`           |`argument >= value`|
+|`Gt(value)`           |`argument > value` |
+|`Le(value)`           |`argument <= value`|
+|`Lt(value)`           |`argument < value` |
+|`Ne(value)`           |`argument != value`|
+|`IsNull()`            |`argument` is a `NULL` pointer (raw or smart).|
+|`NotNull()`           |`argument` is a non-null pointer (raw or smart).|
+|`Ref(variable)`       |`argument` is a reference to `variable`.|
+|`TypedEq<type>(value)`|`argument` has type `type` and is equal to `value`. You may need to use this instead of `Eq(value)` when the mock function is overloaded.|
+
+Except `Ref()`, these matchers make a _copy_ of `value` in case it's
+modified or destructed later. If the compiler complains that `value`
+doesn't have a public copy constructor, try wrap it in `ByRef()`,
+e.g. `Eq(ByRef(non_copyable_value))`. If you do that, make sure
+`non_copyable_value` is not changed afterwards, or the meaning of your
+matcher will be changed.
+
+## Floating-Point Matchers ##
+
+|`DoubleEq(a_double)`|`argument` is a `double` value approximately equal to `a_double`, treating two NaNs as unequal.|
+|:-------------------|:----------------------------------------------------------------------------------------------|
+|`FloatEq(a_float)`  |`argument` is a `float` value approximately equal to `a_float`, treating two NaNs as unequal.  |
+|`NanSensitiveDoubleEq(a_double)`|`argument` is a `double` value approximately equal to `a_double`, treating two NaNs as equal.  |
+|`NanSensitiveFloatEq(a_float)`|`argument` is a `float` value approximately equal to `a_float`, treating two NaNs as equal.    |
+
+The above matchers use ULP-based comparison (the same as used in
+[Google Test](http://code.google.com/p/googletest/)). They
+automatically pick a reasonable error bound based on the absolute
+value of the expected value.  `DoubleEq()` and `FloatEq()` conform to
+the IEEE standard, which requires comparing two NaNs for equality to
+return false. The `NanSensitive*` version instead treats two NaNs as
+equal, which is often what a user wants.
+
+|`DoubleNear(a_double, max_abs_error)`|`argument` is a `double` value close to `a_double` (absolute error <= `max_abs_error`), treating two NaNs as unequal.|
+|:------------------------------------|:--------------------------------------------------------------------------------------------------------------------|
+|`FloatNear(a_float, max_abs_error)`  |`argument` is a `float` value close to `a_float` (absolute error <= `max_abs_error`), treating two NaNs as unequal.  |
+|`NanSensitiveDoubleNear(a_double, max_abs_error)`|`argument` is a `double` value close to `a_double` (absolute error <= `max_abs_error`), treating two NaNs as equal.  |
+|`NanSensitiveFloatNear(a_float, max_abs_error)`|`argument` is a `float` value close to `a_float` (absolute error <= `max_abs_error`), treating two NaNs as equal.    |
+
+## String Matchers ##
+
+The `argument` can be either a C string or a C++ string object:
+
+|`ContainsRegex(string)`|`argument` matches the given regular expression.|
+|:----------------------|:-----------------------------------------------|
+|`EndsWith(suffix)`     |`argument` ends with string `suffix`.           |
+|`HasSubstr(string)`    |`argument` contains `string` as a sub-string.   |
+|`MatchesRegex(string)` |`argument` matches the given regular expression with the match starting at the first character and ending at the last character.|
+|`StartsWith(prefix)`   |`argument` starts with string `prefix`.         |
+|`StrCaseEq(string)`    |`argument` is equal to `string`, ignoring case. |
+|`StrCaseNe(string)`    |`argument` is not equal to `string`, ignoring case.|
+|`StrEq(string)`        |`argument` is equal to `string`.                |
+|`StrNe(string)`        |`argument` is not equal to `string`.            |
+
+`ContainsRegex()` and `MatchesRegex()` use the regular expression
+syntax defined
+[here](http://code.google.com/p/googletest/wiki/AdvancedGuide#Regular_Expression_Syntax).
+`StrCaseEq()`, `StrCaseNe()`, `StrEq()`, and `StrNe()` work for wide
+strings as well.
+
+## Container Matchers ##
+
+Most STL-style containers support `==`, so you can use
+`Eq(expected_container)` or simply `expected_container` to match a
+container exactly.   If you want to write the elements in-line,
+match them more flexibly, or get more informative messages, you can use:
+
+| `ContainerEq(container)` | The same as `Eq(container)` except that the failure message also includes which elements are in one container but not the other. |
+|:-------------------------|:---------------------------------------------------------------------------------------------------------------------------------|
+| `Contains(e)`            | `argument` contains an element that matches `e`, which can be either a value or a matcher.                                       |
+| `Each(e)`                | `argument` is a container where _every_ element matches `e`, which can be either a value or a matcher.                           |
+| `ElementsAre(e0, e1, ..., en)` | `argument` has `n + 1` elements, where the i-th element matches `ei`, which can be a value or a matcher. 0 to 10 arguments are allowed. |
+| `ElementsAreArray({ e0, e1, ..., en })`, `ElementsAreArray(array)`, or `ElementsAreArray(array, count)` | The same as `ElementsAre()` except that the expected element values/matchers come from an initializer list, STL-style container, or C-style array. |
+| `IsEmpty()`              | `argument` is an empty container (`container.empty()`).                                                                          |
+| `Pointwise(m, container)` | `argument` contains the same number of elements as in `container`, and for all i, (the i-th element in `argument`, the i-th element in `container`) match `m`, which is a matcher on 2-tuples. E.g. `Pointwise(Le(), upper_bounds)` verifies that each element in `argument` doesn't exceed the corresponding element in `upper_bounds`. See more detail below. |
+| `SizeIs(m)`              | `argument` is a container whose size matches `m`. E.g. `SizeIs(2)` or `SizeIs(Lt(2))`.                                           |
+| `UnorderedElementsAre(e0, e1, ..., en)` | `argument` has `n + 1` elements, and under some permutation each element matches an `ei` (for a different `i`), which can be a value or a matcher. 0 to 10 arguments are allowed. |
+| `UnorderedElementsAreArray({ e0, e1, ..., en })`, `UnorderedElementsAreArray(array)`, or `UnorderedElementsAreArray(array, count)` | The same as `UnorderedElementsAre()` except that the expected element values/matchers come from an initializer list, STL-style container, or C-style array. |
+| `WhenSorted(m)`          | When `argument` is sorted using the `<` operator, it matches container matcher `m`. E.g. `WhenSorted(UnorderedElementsAre(1, 2, 3))` verifies that `argument` contains elements `1`, `2`, and `3`, ignoring order. |
+| `WhenSortedBy(comparator, m)` | The same as `WhenSorted(m)`, except that the given comparator instead of `<` is used to sort `argument`. E.g. `WhenSortedBy(std::greater<int>(), ElementsAre(3, 2, 1))`. |
+
+Notes:
+
+  * These matchers can also match:
+    1. a native array passed by reference (e.g. in `Foo(const int (&a)[5])`), and
+    1. an array passed as a pointer and a count (e.g. in `Bar(const T* buffer, int len)` -- see [Multi-argument Matchers](#Multiargument_Matchers.md)).
+  * The array being matched may be multi-dimensional (i.e. its elements can be arrays).
+  * `m` in `Pointwise(m, ...)` should be a matcher for `::testing::tuple<T, U>` where `T` and `U` are the element type of the actual container and the expected container, respectively. For example, to compare two `Foo` containers where `Foo` doesn't support `operator==` but has an `Equals()` method, one might write:
+
+```
+using ::testing::get;
+MATCHER(FooEq, "") {
+  return get<0>(arg).Equals(get<1>(arg));
+}
+...
+EXPECT_THAT(actual_foos, Pointwise(FooEq(), expected_foos));
+```
+
+## Member Matchers ##
+
+|`Field(&class::field, m)`|`argument.field` (or `argument->field` when `argument` is a plain pointer) matches matcher `m`, where `argument` is an object of type _class_.|
+|:------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------|
+|`Key(e)`                 |`argument.first` matches `e`, which can be either a value or a matcher. E.g. `Contains(Key(Le(5)))` can verify that a `map` contains a key `<= 5`.|
+|`Pair(m1, m2)`           |`argument` is an `std::pair` whose `first` field matches `m1` and `second` field matches `m2`.                                                |
+|`Property(&class::property, m)`|`argument.property()` (or `argument->property()` when `argument` is a plain pointer) matches matcher `m`, where `argument` is an object of type _class_.|
+
+## Matching the Result of a Function or Functor ##
+
+|`ResultOf(f, m)`|`f(argument)` matches matcher `m`, where `f` is a function or functor.|
+|:---------------|:---------------------------------------------------------------------|
+
+## Pointer Matchers ##
+
+|`Pointee(m)`|`argument` (either a smart pointer or a raw pointer) points to a value that matches matcher `m`.|
+|:-----------|:-----------------------------------------------------------------------------------------------|
+|`WhenDynamicCastTo<T>(m)`| when `argument` is passed through `dynamic_cast<T>()`, it matches matcher `m`.                 |
+
+## Multiargument Matchers ##
+
+Technically, all matchers match a _single_ value. A "multi-argument"
+matcher is just one that matches a _tuple_. The following matchers can
+be used to match a tuple `(x, y)`:
+
+|`Eq()`|`x == y`|
+|:-----|:-------|
+|`Ge()`|`x >= y`|
+|`Gt()`|`x > y` |
+|`Le()`|`x <= y`|
+|`Lt()`|`x < y` |
+|`Ne()`|`x != y`|
+
+You can use the following selectors to pick a subset of the arguments
+(or reorder them) to participate in the matching:
+
+|`AllArgs(m)`|Equivalent to `m`. Useful as syntactic sugar in `.With(AllArgs(m))`.|
+|:-----------|:-------------------------------------------------------------------|
+|`Args<N1, N2, ..., Nk>(m)`|The tuple of the `k` selected (using 0-based indices) arguments matches `m`, e.g. `Args<1, 2>(Eq())`.|
+
+## Composite Matchers ##
+
+You can make a matcher from one or more other matchers:
+
+|`AllOf(m1, m2, ..., mn)`|`argument` matches all of the matchers `m1` to `mn`.|
+|:-----------------------|:---------------------------------------------------|
+|`AnyOf(m1, m2, ..., mn)`|`argument` matches at least one of the matchers `m1` to `mn`.|
+|`Not(m)`                |`argument` doesn't match matcher `m`.               |
+
+## Adapters for Matchers ##
+
+|`MatcherCast<T>(m)`|casts matcher `m` to type `Matcher<T>`.|
+|:------------------|:--------------------------------------|
+|`SafeMatcherCast<T>(m)`| [safely casts](http://code.google.com/p/googlemock/wiki/CookBook#Casting_Matchers) matcher `m` to type `Matcher<T>`. |
+|`Truly(predicate)` |`predicate(argument)` returns something considered by C++ to be true, where `predicate` is a function or functor.|
+
+## Matchers as Predicates ##
+
+|`Matches(m)(value)`|evaluates to `true` if `value` matches `m`. You can use `Matches(m)` alone as a unary functor.|
+|:------------------|:---------------------------------------------------------------------------------------------|
+|`ExplainMatchResult(m, value, result_listener)`|evaluates to `true` if `value` matches `m`, explaining the result to `result_listener`.       |
+|`Value(value, m)`  |evaluates to `true` if `value` matches `m`.                                                   |
+
+## Defining Matchers ##
+
+| `MATCHER(IsEven, "") { return (arg % 2) == 0; }` | Defines a matcher `IsEven()` to match an even number. |
+|:-------------------------------------------------|:------------------------------------------------------|
+| `MATCHER_P(IsDivisibleBy, n, "") { *result_listener << "where the remainder is " << (arg % n); return (arg % n) == 0; }` | Defines a macher `IsDivisibleBy(n)` to match a number divisible by `n`. |
+| `MATCHER_P2(IsBetween, a, b, std::string(negation ? "isn't" : "is") + " between " + PrintToString(a) + " and " + PrintToString(b)) { return a <= arg && arg <= b; }` | Defines a matcher `IsBetween(a, b)` to match a value in the range [`a`, `b`]. |
+
+**Notes:**
+
+  1. The `MATCHER*` macros cannot be used inside a function or class.
+  1. The matcher body must be _purely functional_ (i.e. it cannot have any side effect, and the result must not depend on anything other than the value being matched and the matcher parameters).
+  1. You can use `PrintToString(x)` to convert a value `x` of any type to a string.
+
+## Matchers as Test Assertions ##
+
+|`ASSERT_THAT(expression, m)`|Generates a [fatal failure](http://code.google.com/p/googletest/wiki/Primer#Assertions) if the value of `expression` doesn't match matcher `m`.|
+|:---------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------|
+|`EXPECT_THAT(expression, m)`|Generates a non-fatal failure if the value of `expression` doesn't match matcher `m`.                                                          |
+
+# Actions #
+
+**Actions** specify what a mock function should do when invoked.
+
+## Returning a Value ##
+
+|`Return()`|Return from a `void` mock function.|
+|:---------|:----------------------------------|
+|`Return(value)`|Return `value`. If the type of `value` is different to the mock function's return type, `value` is converted to the latter type <i>at the time the expectation is set</i>, not when the action is executed.|
+|`ReturnArg<N>()`|Return the `N`-th (0-based) argument.|
+|`ReturnNew<T>(a1, ..., ak)`|Return `new T(a1, ..., ak)`; a different object is created each time.|
+|`ReturnNull()`|Return a null pointer.             |
+|`ReturnPointee(ptr)`|Return the value pointed to by `ptr`.|
+|`ReturnRef(variable)`|Return a reference to `variable`.  |
+|`ReturnRefOfCopy(value)`|Return a reference to a copy of `value`; the copy lives as long as the action.|
+
+## Side Effects ##
+
+|`Assign(&variable, value)`|Assign `value` to variable.|
+|:-------------------------|:--------------------------|
+| `DeleteArg<N>()`         | Delete the `N`-th (0-based) argument, which must be a pointer. |
+| `SaveArg<N>(pointer)`    | Save the `N`-th (0-based) argument to `*pointer`. |
+| `SaveArgPointee<N>(pointer)` | Save the value pointed to by the `N`-th (0-based) argument to `*pointer`. |
+| `SetArgReferee<N>(value)` |	Assign value to the variable referenced by the `N`-th (0-based) argument. |
+|`SetArgPointee<N>(value)` |Assign `value` to the variable pointed by the `N`-th (0-based) argument.|
+|`SetArgumentPointee<N>(value)`|Same as `SetArgPointee<N>(value)`. Deprecated. Will be removed in v1.7.0.|
+|`SetArrayArgument<N>(first, last)`|Copies the elements in source range [`first`, `last`) to the array pointed to by the `N`-th (0-based) argument, which can be either a pointer or an iterator. The action does not take ownership of the elements in the source range.|
+|`SetErrnoAndReturn(error, value)`|Set `errno` to `error` and return `value`.|
+|`Throw(exception)`        |Throws the given exception, which can be any copyable value. Available since v1.1.0.|
+
+## Using a Function or a Functor as an Action ##
+
+|`Invoke(f)`|Invoke `f` with the arguments passed to the mock function, where `f` can be a global/static function or a functor.|
+|:----------|:-----------------------------------------------------------------------------------------------------------------|
+|`Invoke(object_pointer, &class::method)`|Invoke the {method on the object with the arguments passed to the mock function.                                  |
+|`InvokeWithoutArgs(f)`|Invoke `f`, which can be a global/static function or a functor. `f` must take no arguments.                       |
+|`InvokeWithoutArgs(object_pointer, &class::method)`|Invoke the method on the object, which takes no arguments.                                                        |
+|`InvokeArgument<N>(arg1, arg2, ..., argk)`|Invoke the mock function's `N`-th (0-based) argument, which must be a function or a functor, with the `k` arguments.|
+
+The return value of the invoked function is used as the return value
+of the action.
+
+When defining a function or functor to be used with `Invoke*()`, you can declare any unused parameters as `Unused`:
+```
+  double Distance(Unused, double x, double y) { return sqrt(x*x + y*y); }
+  ...
+  EXPECT_CALL(mock, Foo("Hi", _, _)).WillOnce(Invoke(Distance));
+```
+
+In `InvokeArgument<N>(...)`, if an argument needs to be passed by reference, wrap it inside `ByRef()`. For example,
+```
+  InvokeArgument<2>(5, string("Hi"), ByRef(foo))
+```
+calls the mock function's #2 argument, passing to it `5` and `string("Hi")` by value, and `foo` by reference.
+
+## Default Action ##
+
+|`DoDefault()`|Do the default action (specified by `ON_CALL()` or the built-in one).|
+|:------------|:--------------------------------------------------------------------|
+
+**Note:** due to technical reasons, `DoDefault()` cannot be used inside  a composite action - trying to do so will result in a run-time error.
+
+## Composite Actions ##
+
+|`DoAll(a1, a2, ..., an)`|Do all actions `a1` to `an` and return the result of `an` in each invocation. The first `n - 1` sub-actions must return void. |
+|:-----------------------|:-----------------------------------------------------------------------------------------------------------------------------|
+|`IgnoreResult(a)`       |Perform action `a` and ignore its result. `a` must not return void.                                                           |
+|`WithArg<N>(a)`         |Pass the `N`-th (0-based) argument of the mock function to action `a` and perform it.                                         |
+|`WithArgs<N1, N2, ..., Nk>(a)`|Pass the selected (0-based) arguments of the mock function to action `a` and perform it.                                      |
+|`WithoutArgs(a)`        |Perform action `a` without any arguments.                                                                                     |
+
+## Defining Actions ##
+
+| `ACTION(Sum) { return arg0 + arg1; }` | Defines an action `Sum()` to return the sum of the mock function's argument #0 and #1. |
+|:--------------------------------------|:---------------------------------------------------------------------------------------|
+| `ACTION_P(Plus, n) { return arg0 + n; }` | Defines an action `Plus(n)` to return the sum of the mock function's argument #0 and `n`. |
+| `ACTION_Pk(Foo, p1, ..., pk) { statements; }` | Defines a parameterized action `Foo(p1, ..., pk)` to execute the given `statements`.   |
+
+The `ACTION*` macros cannot be used inside a function or class.
+
+# Cardinalities #
+
+These are used in `Times()` to specify how many times a mock function will be called:
+
+|`AnyNumber()`|The function can be called any number of times.|
+|:------------|:----------------------------------------------|
+|`AtLeast(n)` |The call is expected at least `n` times.       |
+|`AtMost(n)`  |The call is expected at most `n` times.        |
+|`Between(m, n)`|The call is expected between `m` and `n` (inclusive) times.|
+|`Exactly(n) or n`|The call is expected exactly `n` times. In particular, the call should never happen when `n` is 0.|
+
+# Expectation Order #
+
+By default, the expectations can be matched in _any_ order.  If some
+or all expectations must be matched in a given order, there are two
+ways to specify it.  They can be used either independently or
+together.
+
+## The After Clause ##
+
+```
+using ::testing::Expectation;
+...
+Expectation init_x = EXPECT_CALL(foo, InitX());
+Expectation init_y = EXPECT_CALL(foo, InitY());
+EXPECT_CALL(foo, Bar())
+    .After(init_x, init_y);
+```
+says that `Bar()` can be called only after both `InitX()` and
+`InitY()` have been called.
+
+If you don't know how many pre-requisites an expectation has when you
+write it, you can use an `ExpectationSet` to collect them:
+
+```
+using ::testing::ExpectationSet;
+...
+ExpectationSet all_inits;
+for (int i = 0; i < element_count; i++) {
+  all_inits += EXPECT_CALL(foo, InitElement(i));
+}
+EXPECT_CALL(foo, Bar())
+    .After(all_inits);
+```
+says that `Bar()` can be called only after all elements have been
+initialized (but we don't care about which elements get initialized
+before the others).
+
+Modifying an `ExpectationSet` after using it in an `.After()` doesn't
+affect the meaning of the `.After()`.
+
+## Sequences ##
+
+When you have a long chain of sequential expectations, it's easier to
+specify the order using **sequences**, which don't require you to given
+each expectation in the chain a different name.  <i>All expected<br>
+calls</i> in the same sequence must occur in the order they are
+specified.
+
+```
+using ::testing::Sequence;
+Sequence s1, s2;
+...
+EXPECT_CALL(foo, Reset())
+    .InSequence(s1, s2)
+    .WillOnce(Return(true));
+EXPECT_CALL(foo, GetSize())
+    .InSequence(s1)
+    .WillOnce(Return(1));
+EXPECT_CALL(foo, Describe(A<const char*>()))
+    .InSequence(s2)
+    .WillOnce(Return("dummy"));
+```
+says that `Reset()` must be called before _both_ `GetSize()` _and_
+`Describe()`, and the latter two can occur in any order.
+
+To put many expectations in a sequence conveniently:
+```
+using ::testing::InSequence;
+{
+  InSequence dummy;
+
+  EXPECT_CALL(...)...;
+  EXPECT_CALL(...)...;
+  ...
+  EXPECT_CALL(...)...;
+}
+```
+says that all expected calls in the scope of `dummy` must occur in
+strict order. The name `dummy` is irrelevant.)
+
+# Verifying and Resetting a Mock #
+
+Google Mock will verify the expectations on a mock object when it is destructed, or you can do it earlier:
+```
+using ::testing::Mock;
+...
+// Verifies and removes the expectations on mock_obj;
+// returns true iff successful.
+Mock::VerifyAndClearExpectations(&mock_obj);
+...
+// Verifies and removes the expectations on mock_obj;
+// also removes the default actions set by ON_CALL();
+// returns true iff successful.
+Mock::VerifyAndClear(&mock_obj);
+```
+
+You can also tell Google Mock that a mock object can be leaked and doesn't
+need to be verified:
+```
+Mock::AllowLeak(&mock_obj);
+```
+
+# Mock Classes #
+
+Google Mock defines a convenient mock class template
+```
+class MockFunction<R(A1, ..., An)> {
+ public:
+  MOCK_METHODn(Call, R(A1, ..., An));
+};
+```
+See this [recipe](http://code.google.com/p/googlemock/wiki/CookBook#Using_Check_Points) for one application of it.
+
+# Flags #
+
+| `--gmock_catch_leaked_mocks=0` | Don't report leaked mock objects as failures. |
+|:-------------------------------|:----------------------------------------------|
+| `--gmock_verbose=LEVEL`        | Sets the default verbosity level (`info`, `warning`, or `error`) of Google Mock messages. |
\ No newline at end of file
diff --git a/third_party/googletest/googlemock/docs/CookBook.md b/third_party/googletest/googlemock/docs/CookBook.md
new file mode 100644
index 0000000..8a0d3f7
--- /dev/null
+++ b/third_party/googletest/googlemock/docs/CookBook.md
@@ -0,0 +1,3675 @@
+
+
+You can find recipes for using Google Mock here. If you haven't yet,
+please read the [ForDummies](ForDummies.md) document first to make sure you understand
+the basics.
+
+**Note:** Google Mock lives in the `testing` name space. For
+readability, it is recommended to write `using ::testing::Foo;` once in
+your file before using the name `Foo` defined by Google Mock. We omit
+such `using` statements in this page for brevity, but you should do it
+in your own code.
+
+# Creating Mock Classes #
+
+## Mocking Private or Protected Methods ##
+
+You must always put a mock method definition (`MOCK_METHOD*`) in a
+`public:` section of the mock class, regardless of the method being
+mocked being `public`, `protected`, or `private` in the base class.
+This allows `ON_CALL` and `EXPECT_CALL` to reference the mock function
+from outside of the mock class.  (Yes, C++ allows a subclass to change
+the access level of a virtual function in the base class.)  Example:
+
+```
+class Foo {
+ public:
+  ...
+  virtual bool Transform(Gadget* g) = 0;
+
+ protected:
+  virtual void Resume();
+
+ private:
+  virtual int GetTimeOut();
+};
+
+class MockFoo : public Foo {
+ public:
+  ...
+  MOCK_METHOD1(Transform, bool(Gadget* g));
+
+  // The following must be in the public section, even though the
+  // methods are protected or private in the base class.
+  MOCK_METHOD0(Resume, void());
+  MOCK_METHOD0(GetTimeOut, int());
+};
+```
+
+## Mocking Overloaded Methods ##
+
+You can mock overloaded functions as usual. No special attention is required:
+
+```
+class Foo {
+  ...
+
+  // Must be virtual as we'll inherit from Foo.
+  virtual ~Foo();
+
+  // Overloaded on the types and/or numbers of arguments.
+  virtual int Add(Element x);
+  virtual int Add(int times, Element x);
+
+  // Overloaded on the const-ness of this object.
+  virtual Bar& GetBar();
+  virtual const Bar& GetBar() const;
+};
+
+class MockFoo : public Foo {
+  ...
+  MOCK_METHOD1(Add, int(Element x));
+  MOCK_METHOD2(Add, int(int times, Element x);
+
+  MOCK_METHOD0(GetBar, Bar&());
+  MOCK_CONST_METHOD0(GetBar, const Bar&());
+};
+```
+
+**Note:** if you don't mock all versions of the overloaded method, the
+compiler will give you a warning about some methods in the base class
+being hidden. To fix that, use `using` to bring them in scope:
+
+```
+class MockFoo : public Foo {
+  ...
+  using Foo::Add;
+  MOCK_METHOD1(Add, int(Element x));
+  // We don't want to mock int Add(int times, Element x);
+  ...
+};
+```
+
+## Mocking Class Templates ##
+
+To mock a class template, append `_T` to the `MOCK_*` macros:
+
+```
+template <typename Elem>
+class StackInterface {
+  ...
+  // Must be virtual as we'll inherit from StackInterface.
+  virtual ~StackInterface();
+
+  virtual int GetSize() const = 0;
+  virtual void Push(const Elem& x) = 0;
+};
+
+template <typename Elem>
+class MockStack : public StackInterface<Elem> {
+  ...
+  MOCK_CONST_METHOD0_T(GetSize, int());
+  MOCK_METHOD1_T(Push, void(const Elem& x));
+};
+```
+
+## Mocking Nonvirtual Methods ##
+
+Google Mock can mock non-virtual functions to be used in what we call _hi-perf
+dependency injection_.
+
+In this case, instead of sharing a common base class with the real
+class, your mock class will be _unrelated_ to the real class, but
+contain methods with the same signatures.  The syntax for mocking
+non-virtual methods is the _same_ as mocking virtual methods:
+
+```
+// A simple packet stream class.  None of its members is virtual.
+class ConcretePacketStream {
+ public:
+  void AppendPacket(Packet* new_packet);
+  const Packet* GetPacket(size_t packet_number) const;
+  size_t NumberOfPackets() const;
+  ...
+};
+
+// A mock packet stream class.  It inherits from no other, but defines
+// GetPacket() and NumberOfPackets().
+class MockPacketStream {
+ public:
+  MOCK_CONST_METHOD1(GetPacket, const Packet*(size_t packet_number));
+  MOCK_CONST_METHOD0(NumberOfPackets, size_t());
+  ...
+};
+```
+
+Note that the mock class doesn't define `AppendPacket()`, unlike the
+real class. That's fine as long as the test doesn't need to call it.
+
+Next, you need a way to say that you want to use
+`ConcretePacketStream` in production code, and use `MockPacketStream`
+in tests.  Since the functions are not virtual and the two classes are
+unrelated, you must specify your choice at _compile time_ (as opposed
+to run time).
+
+One way to do it is to templatize your code that needs to use a packet
+stream.  More specifically, you will give your code a template type
+argument for the type of the packet stream.  In production, you will
+instantiate your template with `ConcretePacketStream` as the type
+argument.  In tests, you will instantiate the same template with
+`MockPacketStream`.  For example, you may write:
+
+```
+template <class PacketStream>
+void CreateConnection(PacketStream* stream) { ... }
+
+template <class PacketStream>
+class PacketReader {
+ public:
+  void ReadPackets(PacketStream* stream, size_t packet_num);
+};
+```
+
+Then you can use `CreateConnection<ConcretePacketStream>()` and
+`PacketReader<ConcretePacketStream>` in production code, and use
+`CreateConnection<MockPacketStream>()` and
+`PacketReader<MockPacketStream>` in tests.
+
+```
+  MockPacketStream mock_stream;
+  EXPECT_CALL(mock_stream, ...)...;
+  .. set more expectations on mock_stream ...
+  PacketReader<MockPacketStream> reader(&mock_stream);
+  ... exercise reader ...
+```
+
+## Mocking Free Functions ##
+
+It's possible to use Google Mock to mock a free function (i.e. a
+C-style function or a static method).  You just need to rewrite your
+code to use an interface (abstract class).
+
+Instead of calling a free function (say, `OpenFile`) directly,
+introduce an interface for it and have a concrete subclass that calls
+the free function:
+
+```
+class FileInterface {
+ public:
+  ...
+  virtual bool Open(const char* path, const char* mode) = 0;
+};
+
+class File : public FileInterface {
+ public:
+  ...
+  virtual bool Open(const char* path, const char* mode) {
+    return OpenFile(path, mode);
+  }
+};
+```
+
+Your code should talk to `FileInterface` to open a file.  Now it's
+easy to mock out the function.
+
+This may seem much hassle, but in practice you often have multiple
+related functions that you can put in the same interface, so the
+per-function syntactic overhead will be much lower.
+
+If you are concerned about the performance overhead incurred by
+virtual functions, and profiling confirms your concern, you can
+combine this with the recipe for [mocking non-virtual methods](#Mocking_Nonvirtual_Methods.md).
+
+## The Nice, the Strict, and the Naggy ##
+
+If a mock method has no `EXPECT_CALL` spec but is called, Google Mock
+will print a warning about the "uninteresting call". The rationale is:
+
+  * New methods may be added to an interface after a test is written. We shouldn't fail a test just because a method it doesn't know about is called.
+  * However, this may also mean there's a bug in the test, so Google Mock shouldn't be silent either. If the user believes these calls are harmless, he can add an `EXPECT_CALL()` to suppress the warning.
+
+However, sometimes you may want to suppress all "uninteresting call"
+warnings, while sometimes you may want the opposite, i.e. to treat all
+of them as errors. Google Mock lets you make the decision on a
+per-mock-object basis.
+
+Suppose your test uses a mock class `MockFoo`:
+
+```
+TEST(...) {
+  MockFoo mock_foo;
+  EXPECT_CALL(mock_foo, DoThis());
+  ... code that uses mock_foo ...
+}
+```
+
+If a method of `mock_foo` other than `DoThis()` is called, it will be
+reported by Google Mock as a warning. However, if you rewrite your
+test to use `NiceMock<MockFoo>` instead, the warning will be gone,
+resulting in a cleaner test output:
+
+```
+using ::testing::NiceMock;
+
+TEST(...) {
+  NiceMock<MockFoo> mock_foo;
+  EXPECT_CALL(mock_foo, DoThis());
+  ... code that uses mock_foo ...
+}
+```
+
+`NiceMock<MockFoo>` is a subclass of `MockFoo`, so it can be used
+wherever `MockFoo` is accepted.
+
+It also works if `MockFoo`'s constructor takes some arguments, as
+`NiceMock<MockFoo>` "inherits" `MockFoo`'s constructors:
+
+```
+using ::testing::NiceMock;
+
+TEST(...) {
+  NiceMock<MockFoo> mock_foo(5, "hi");  // Calls MockFoo(5, "hi").
+  EXPECT_CALL(mock_foo, DoThis());
+  ... code that uses mock_foo ...
+}
+```
+
+The usage of `StrictMock` is similar, except that it makes all
+uninteresting calls failures:
+
+```
+using ::testing::StrictMock;
+
+TEST(...) {
+  StrictMock<MockFoo> mock_foo;
+  EXPECT_CALL(mock_foo, DoThis());
+  ... code that uses mock_foo ...
+
+  // The test will fail if a method of mock_foo other than DoThis()
+  // is called.
+}
+```
+
+There are some caveats though (I don't like them just as much as the
+next guy, but sadly they are side effects of C++'s limitations):
+
+  1. `NiceMock<MockFoo>` and `StrictMock<MockFoo>` only work for mock methods defined using the `MOCK_METHOD*` family of macros **directly** in the `MockFoo` class. If a mock method is defined in a **base class** of `MockFoo`, the "nice" or "strict" modifier may not affect it, depending on the compiler. In particular, nesting `NiceMock` and `StrictMock` (e.g. `NiceMock<StrictMock<MockFoo> >`) is **not** supported.
+  1. The constructors of the base mock (`MockFoo`) cannot have arguments passed by non-const reference, which happens to be banned by the [Google C++ style guide](http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml).
+  1. During the constructor or destructor of `MockFoo`, the mock object is _not_ nice or strict.  This may cause surprises if the constructor or destructor calls a mock method on `this` object. (This behavior, however, is consistent with C++'s general rule: if a constructor or destructor calls a virtual method of `this` object, that method is treated as non-virtual.  In other words, to the base class's constructor or destructor, `this` object behaves like an instance of the base class, not the derived class.  This rule is required for safety.  Otherwise a base constructor may use members of a derived class before they are initialized, or a base destructor may use members of a derived class after they have been destroyed.)
+
+Finally, you should be **very cautious** about when to use naggy or strict mocks, as they tend to make tests more brittle and harder to maintain. When you refactor your code without changing its externally visible behavior, ideally you should't need to update any tests. If your code interacts with a naggy mock, however, you may start to get spammed with warnings as the result of your change. Worse, if your code interacts with a strict mock, your tests may start to fail and you'll be forced to fix them. Our general recommendation is to use nice mocks (not yet the default) most of the time, use naggy mocks (the current default) when developing or debugging tests, and use strict mocks only as the last resort.
+
+## Simplifying the Interface without Breaking Existing Code ##
+
+Sometimes a method has a long list of arguments that is mostly
+uninteresting. For example,
+
+```
+class LogSink {
+ public:
+  ...
+  virtual void send(LogSeverity severity, const char* full_filename,
+                    const char* base_filename, int line,
+                    const struct tm* tm_time,
+                    const char* message, size_t message_len) = 0;
+};
+```
+
+This method's argument list is lengthy and hard to work with (let's
+say that the `message` argument is not even 0-terminated). If we mock
+it as is, using the mock will be awkward. If, however, we try to
+simplify this interface, we'll need to fix all clients depending on
+it, which is often infeasible.
+
+The trick is to re-dispatch the method in the mock class:
+
+```
+class ScopedMockLog : public LogSink {
+ public:
+  ...
+  virtual void send(LogSeverity severity, const char* full_filename,
+                    const char* base_filename, int line, const tm* tm_time,
+                    const char* message, size_t message_len) {
+    // We are only interested in the log severity, full file name, and
+    // log message.
+    Log(severity, full_filename, std::string(message, message_len));
+  }
+
+  // Implements the mock method:
+  //
+  //   void Log(LogSeverity severity,
+  //            const string& file_path,
+  //            const string& message);
+  MOCK_METHOD3(Log, void(LogSeverity severity, const string& file_path,
+                         const string& message));
+};
+```
+
+By defining a new mock method with a trimmed argument list, we make
+the mock class much more user-friendly.
+
+## Alternative to Mocking Concrete Classes ##
+
+Often you may find yourself using classes that don't implement
+interfaces. In order to test your code that uses such a class (let's
+call it `Concrete`), you may be tempted to make the methods of
+`Concrete` virtual and then mock it.
+
+Try not to do that.
+
+Making a non-virtual function virtual is a big decision. It creates an
+extension point where subclasses can tweak your class' behavior. This
+weakens your control on the class because now it's harder to maintain
+the class' invariants. You should make a function virtual only when
+there is a valid reason for a subclass to override it.
+
+Mocking concrete classes directly is problematic as it creates a tight
+coupling between the class and the tests - any small change in the
+class may invalidate your tests and make test maintenance a pain.
+
+To avoid such problems, many programmers have been practicing "coding
+to interfaces": instead of talking to the `Concrete` class, your code
+would define an interface and talk to it. Then you implement that
+interface as an adaptor on top of `Concrete`. In tests, you can easily
+mock that interface to observe how your code is doing.
+
+This technique incurs some overhead:
+
+  * You pay the cost of virtual function calls (usually not a problem).
+  * There is more abstraction for the programmers to learn.
+
+However, it can also bring significant benefits in addition to better
+testability:
+
+  * `Concrete`'s API may not fit your problem domain very well, as you may not be the only client it tries to serve. By designing your own interface, you have a chance to tailor it to your need - you may add higher-level functionalities, rename stuff, etc instead of just trimming the class. This allows you to write your code (user of the interface) in a more natural way, which means it will be more readable, more maintainable, and you'll be more productive.
+  * If `Concrete`'s implementation ever has to change, you don't have to rewrite everywhere it is used. Instead, you can absorb the change in your implementation of the interface, and your other code and tests will be insulated from this change.
+
+Some people worry that if everyone is practicing this technique, they
+will end up writing lots of redundant code. This concern is totally
+understandable. However, there are two reasons why it may not be the
+case:
+
+  * Different projects may need to use `Concrete` in different ways, so the best interfaces for them will be different. Therefore, each of them will have its own domain-specific interface on top of `Concrete`, and they will not be the same code.
+  * If enough projects want to use the same interface, they can always share it, just like they have been sharing `Concrete`. You can check in the interface and the adaptor somewhere near `Concrete` (perhaps in a `contrib` sub-directory) and let many projects use it.
+
+You need to weigh the pros and cons carefully for your particular
+problem, but I'd like to assure you that the Java community has been
+practicing this for a long time and it's a proven effective technique
+applicable in a wide variety of situations. :-)
+
+## Delegating Calls to a Fake ##
+
+Some times you have a non-trivial fake implementation of an
+interface. For example:
+
+```
+class Foo {
+ public:
+  virtual ~Foo() {}
+  virtual char DoThis(int n) = 0;
+  virtual void DoThat(const char* s, int* p) = 0;
+};
+
+class FakeFoo : public Foo {
+ public:
+  virtual char DoThis(int n) {
+    return (n > 0) ? '+' :
+        (n < 0) ? '-' : '0';
+  }
+
+  virtual void DoThat(const char* s, int* p) {
+    *p = strlen(s);
+  }
+};
+```
+
+Now you want to mock this interface such that you can set expectations
+on it. However, you also want to use `FakeFoo` for the default
+behavior, as duplicating it in the mock object is, well, a lot of
+work.
+
+When you define the mock class using Google Mock, you can have it
+delegate its default action to a fake class you already have, using
+this pattern:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+
+class MockFoo : public Foo {
+ public:
+  // Normal mock method definitions using Google Mock.
+  MOCK_METHOD1(DoThis, char(int n));
+  MOCK_METHOD2(DoThat, void(const char* s, int* p));
+
+  // Delegates the default actions of the methods to a FakeFoo object.
+  // This must be called *before* the custom ON_CALL() statements.
+  void DelegateToFake() {
+    ON_CALL(*this, DoThis(_))
+        .WillByDefault(Invoke(&fake_, &FakeFoo::DoThis));
+    ON_CALL(*this, DoThat(_, _))
+        .WillByDefault(Invoke(&fake_, &FakeFoo::DoThat));
+  }
+ private:
+  FakeFoo fake_;  // Keeps an instance of the fake in the mock.
+};
+```
+
+With that, you can use `MockFoo` in your tests as usual. Just remember
+that if you don't explicitly set an action in an `ON_CALL()` or
+`EXPECT_CALL()`, the fake will be called upon to do it:
+
+```
+using ::testing::_;
+
+TEST(AbcTest, Xyz) {
+  MockFoo foo;
+  foo.DelegateToFake(); // Enables the fake for delegation.
+
+  // Put your ON_CALL(foo, ...)s here, if any.
+
+  // No action specified, meaning to use the default action.
+  EXPECT_CALL(foo, DoThis(5));
+  EXPECT_CALL(foo, DoThat(_, _));
+
+  int n = 0;
+  EXPECT_EQ('+', foo.DoThis(5));  // FakeFoo::DoThis() is invoked.
+  foo.DoThat("Hi", &n);           // FakeFoo::DoThat() is invoked.
+  EXPECT_EQ(2, n);
+}
+```
+
+**Some tips:**
+
+  * If you want, you can still override the default action by providing your own `ON_CALL()` or using `.WillOnce()` / `.WillRepeatedly()` in `EXPECT_CALL()`.
+  * In `DelegateToFake()`, you only need to delegate the methods whose fake implementation you intend to use.
+  * The general technique discussed here works for overloaded methods, but you'll need to tell the compiler which version you mean. To disambiguate a mock function (the one you specify inside the parentheses of `ON_CALL()`), see the "Selecting Between Overloaded Functions" section on this page; to disambiguate a fake function (the one you place inside `Invoke()`), use a `static_cast` to specify the function's type. For instance, if class `Foo` has methods `char DoThis(int n)` and `bool DoThis(double x) const`, and you want to invoke the latter, you need to write `Invoke(&fake_, static_cast<bool (FakeFoo::*)(double) const>(&FakeFoo::DoThis))` instead of `Invoke(&fake_, &FakeFoo::DoThis)` (The strange-looking thing inside the angled brackets of `static_cast` is the type of a function pointer to the second `DoThis()` method.).
+  * Having to mix a mock and a fake is often a sign of something gone wrong. Perhaps you haven't got used to the interaction-based way of testing yet. Or perhaps your interface is taking on too many roles and should be split up. Therefore, **don't abuse this**. We would only recommend to do it as an intermediate step when you are refactoring your code.
+
+Regarding the tip on mixing a mock and a fake, here's an example on
+why it may be a bad sign: Suppose you have a class `System` for
+low-level system operations. In particular, it does file and I/O
+operations. And suppose you want to test how your code uses `System`
+to do I/O, and you just want the file operations to work normally. If
+you mock out the entire `System` class, you'll have to provide a fake
+implementation for the file operation part, which suggests that
+`System` is taking on too many roles.
+
+Instead, you can define a `FileOps` interface and an `IOOps` interface
+and split `System`'s functionalities into the two. Then you can mock
+`IOOps` without mocking `FileOps`.
+
+## Delegating Calls to a Real Object ##
+
+When using testing doubles (mocks, fakes, stubs, and etc), sometimes
+their behaviors will differ from those of the real objects. This
+difference could be either intentional (as in simulating an error such
+that you can test the error handling code) or unintentional. If your
+mocks have different behaviors than the real objects by mistake, you
+could end up with code that passes the tests but fails in production.
+
+You can use the _delegating-to-real_ technique to ensure that your
+mock has the same behavior as the real object while retaining the
+ability to validate calls. This technique is very similar to the
+delegating-to-fake technique, the difference being that we use a real
+object instead of a fake. Here's an example:
+
+```
+using ::testing::_;
+using ::testing::AtLeast;
+using ::testing::Invoke;
+
+class MockFoo : public Foo {
+ public:
+  MockFoo() {
+    // By default, all calls are delegated to the real object.
+    ON_CALL(*this, DoThis())
+        .WillByDefault(Invoke(&real_, &Foo::DoThis));
+    ON_CALL(*this, DoThat(_))
+        .WillByDefault(Invoke(&real_, &Foo::DoThat));
+    ...
+  }
+  MOCK_METHOD0(DoThis, ...);
+  MOCK_METHOD1(DoThat, ...);
+  ...
+ private:
+  Foo real_;
+};
+...
+
+  MockFoo mock;
+
+  EXPECT_CALL(mock, DoThis())
+      .Times(3);
+  EXPECT_CALL(mock, DoThat("Hi"))
+      .Times(AtLeast(1));
+  ... use mock in test ...
+```
+
+With this, Google Mock will verify that your code made the right calls
+(with the right arguments, in the right order, called the right number
+of times, etc), and a real object will answer the calls (so the
+behavior will be the same as in production). This gives you the best
+of both worlds.
+
+## Delegating Calls to a Parent Class ##
+
+Ideally, you should code to interfaces, whose methods are all pure
+virtual. In reality, sometimes you do need to mock a virtual method
+that is not pure (i.e, it already has an implementation). For example:
+
+```
+class Foo {
+ public:
+  virtual ~Foo();
+
+  virtual void Pure(int n) = 0;
+  virtual int Concrete(const char* str) { ... }
+};
+
+class MockFoo : public Foo {
+ public:
+  // Mocking a pure method.
+  MOCK_METHOD1(Pure, void(int n));
+  // Mocking a concrete method.  Foo::Concrete() is shadowed.
+  MOCK_METHOD1(Concrete, int(const char* str));
+};
+```
+
+Sometimes you may want to call `Foo::Concrete()` instead of
+`MockFoo::Concrete()`. Perhaps you want to do it as part of a stub
+action, or perhaps your test doesn't need to mock `Concrete()` at all
+(but it would be oh-so painful to have to define a new mock class
+whenever you don't need to mock one of its methods).
+
+The trick is to leave a back door in your mock class for accessing the
+real methods in the base class:
+
+```
+class MockFoo : public Foo {
+ public:
+  // Mocking a pure method.
+  MOCK_METHOD1(Pure, void(int n));
+  // Mocking a concrete method.  Foo::Concrete() is shadowed.
+  MOCK_METHOD1(Concrete, int(const char* str));
+
+  // Use this to call Concrete() defined in Foo.
+  int FooConcrete(const char* str) { return Foo::Concrete(str); }
+};
+```
+
+Now, you can call `Foo::Concrete()` inside an action by:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+...
+  EXPECT_CALL(foo, Concrete(_))
+      .WillOnce(Invoke(&foo, &MockFoo::FooConcrete));
+```
+
+or tell the mock object that you don't want to mock `Concrete()`:
+
+```
+using ::testing::Invoke;
+...
+  ON_CALL(foo, Concrete(_))
+      .WillByDefault(Invoke(&foo, &MockFoo::FooConcrete));
+```
+
+(Why don't we just write `Invoke(&foo, &Foo::Concrete)`? If you do
+that, `MockFoo::Concrete()` will be called (and cause an infinite
+recursion) since `Foo::Concrete()` is virtual. That's just how C++
+works.)
+
+# Using Matchers #
+
+## Matching Argument Values Exactly ##
+
+You can specify exactly which arguments a mock method is expecting:
+
+```
+using ::testing::Return;
+...
+  EXPECT_CALL(foo, DoThis(5))
+      .WillOnce(Return('a'));
+  EXPECT_CALL(foo, DoThat("Hello", bar));
+```
+
+## Using Simple Matchers ##
+
+You can use matchers to match arguments that have a certain property:
+
+```
+using ::testing::Ge;
+using ::testing::NotNull;
+using ::testing::Return;
+...
+  EXPECT_CALL(foo, DoThis(Ge(5)))  // The argument must be >= 5.
+      .WillOnce(Return('a'));
+  EXPECT_CALL(foo, DoThat("Hello", NotNull()));
+  // The second argument must not be NULL.
+```
+
+A frequently used matcher is `_`, which matches anything:
+
+```
+using ::testing::_;
+using ::testing::NotNull;
+...
+  EXPECT_CALL(foo, DoThat(_, NotNull()));
+```
+
+## Combining Matchers ##
+
+You can build complex matchers from existing ones using `AllOf()`,
+`AnyOf()`, and `Not()`:
+
+```
+using ::testing::AllOf;
+using ::testing::Gt;
+using ::testing::HasSubstr;
+using ::testing::Ne;
+using ::testing::Not;
+...
+  // The argument must be > 5 and != 10.
+  EXPECT_CALL(foo, DoThis(AllOf(Gt(5),
+                                Ne(10))));
+
+  // The first argument must not contain sub-string "blah".
+  EXPECT_CALL(foo, DoThat(Not(HasSubstr("blah")),
+                          NULL));
+```
+
+## Casting Matchers ##
+
+Google Mock matchers are statically typed, meaning that the compiler
+can catch your mistake if you use a matcher of the wrong type (for
+example, if you use `Eq(5)` to match a `string` argument). Good for
+you!
+
+Sometimes, however, you know what you're doing and want the compiler
+to give you some slack. One example is that you have a matcher for
+`long` and the argument you want to match is `int`. While the two
+types aren't exactly the same, there is nothing really wrong with
+using a `Matcher<long>` to match an `int` - after all, we can first
+convert the `int` argument to a `long` before giving it to the
+matcher.
+
+To support this need, Google Mock gives you the
+`SafeMatcherCast<T>(m)` function. It casts a matcher `m` to type
+`Matcher<T>`. To ensure safety, Google Mock checks that (let `U` be the
+type `m` accepts):
+
+  1. Type `T` can be implicitly cast to type `U`;
+  1. When both `T` and `U` are built-in arithmetic types (`bool`, integers, and floating-point numbers), the conversion from `T` to `U` is not lossy (in other words, any value representable by `T` can also be represented by `U`); and
+  1. When `U` is a reference, `T` must also be a reference (as the underlying matcher may be interested in the address of the `U` value).
+
+The code won't compile if any of these conditions isn't met.
+
+Here's one example:
+
+```
+using ::testing::SafeMatcherCast;
+
+// A base class and a child class.
+class Base { ... };
+class Derived : public Base { ... };
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD1(DoThis, void(Derived* derived));
+};
+...
+
+  MockFoo foo;
+  // m is a Matcher<Base*> we got from somewhere.
+  EXPECT_CALL(foo, DoThis(SafeMatcherCast<Derived*>(m)));
+```
+
+If you find `SafeMatcherCast<T>(m)` too limiting, you can use a similar
+function `MatcherCast<T>(m)`. The difference is that `MatcherCast` works
+as long as you can `static_cast` type `T` to type `U`.
+
+`MatcherCast` essentially lets you bypass C++'s type system
+(`static_cast` isn't always safe as it could throw away information,
+for example), so be careful not to misuse/abuse it.
+
+## Selecting Between Overloaded Functions ##
+
+If you expect an overloaded function to be called, the compiler may
+need some help on which overloaded version it is.
+
+To disambiguate functions overloaded on the const-ness of this object,
+use the `Const()` argument wrapper.
+
+```
+using ::testing::ReturnRef;
+
+class MockFoo : public Foo {
+  ...
+  MOCK_METHOD0(GetBar, Bar&());
+  MOCK_CONST_METHOD0(GetBar, const Bar&());
+};
+...
+
+  MockFoo foo;
+  Bar bar1, bar2;
+  EXPECT_CALL(foo, GetBar())         // The non-const GetBar().
+      .WillOnce(ReturnRef(bar1));
+  EXPECT_CALL(Const(foo), GetBar())  // The const GetBar().
+      .WillOnce(ReturnRef(bar2));
+```
+
+(`Const()` is defined by Google Mock and returns a `const` reference
+to its argument.)
+
+To disambiguate overloaded functions with the same number of arguments
+but different argument types, you may need to specify the exact type
+of a matcher, either by wrapping your matcher in `Matcher<type>()`, or
+using a matcher whose type is fixed (`TypedEq<type>`, `An<type>()`,
+etc):
+
+```
+using ::testing::An;
+using ::testing::Lt;
+using ::testing::Matcher;
+using ::testing::TypedEq;
+
+class MockPrinter : public Printer {
+ public:
+  MOCK_METHOD1(Print, void(int n));
+  MOCK_METHOD1(Print, void(char c));
+};
+
+TEST(PrinterTest, Print) {
+  MockPrinter printer;
+
+  EXPECT_CALL(printer, Print(An<int>()));            // void Print(int);
+  EXPECT_CALL(printer, Print(Matcher<int>(Lt(5))));  // void Print(int);
+  EXPECT_CALL(printer, Print(TypedEq<char>('a')));   // void Print(char);
+
+  printer.Print(3);
+  printer.Print(6);
+  printer.Print('a');
+}
+```
+
+## Performing Different Actions Based on the Arguments ##
+
+When a mock method is called, the _last_ matching expectation that's
+still active will be selected (think "newer overrides older"). So, you
+can make a method do different things depending on its argument values
+like this:
+
+```
+using ::testing::_;
+using ::testing::Lt;
+using ::testing::Return;
+...
+  // The default case.
+  EXPECT_CALL(foo, DoThis(_))
+      .WillRepeatedly(Return('b'));
+
+  // The more specific case.
+  EXPECT_CALL(foo, DoThis(Lt(5)))
+      .WillRepeatedly(Return('a'));
+```
+
+Now, if `foo.DoThis()` is called with a value less than 5, `'a'` will
+be returned; otherwise `'b'` will be returned.
+
+## Matching Multiple Arguments as a Whole ##
+
+Sometimes it's not enough to match the arguments individually. For
+example, we may want to say that the first argument must be less than
+the second argument. The `With()` clause allows us to match
+all arguments of a mock function as a whole. For example,
+
+```
+using ::testing::_;
+using ::testing::Lt;
+using ::testing::Ne;
+...
+  EXPECT_CALL(foo, InRange(Ne(0), _))
+      .With(Lt());
+```
+
+says that the first argument of `InRange()` must not be 0, and must be
+less than the second argument.
+
+The expression inside `With()` must be a matcher of type
+`Matcher< ::testing::tuple<A1, ..., An> >`, where `A1`, ..., `An` are the
+types of the function arguments.
+
+You can also write `AllArgs(m)` instead of `m` inside `.With()`. The
+two forms are equivalent, but `.With(AllArgs(Lt()))` is more readable
+than `.With(Lt())`.
+
+You can use `Args<k1, ..., kn>(m)` to match the `n` selected arguments
+(as a tuple) against `m`. For example,
+
+```
+using ::testing::_;
+using ::testing::AllOf;
+using ::testing::Args;
+using ::testing::Lt;
+...
+  EXPECT_CALL(foo, Blah(_, _, _))
+      .With(AllOf(Args<0, 1>(Lt()), Args<1, 2>(Lt())));
+```
+
+says that `Blah()` will be called with arguments `x`, `y`, and `z` where
+`x < y < z`.
+
+As a convenience and example, Google Mock provides some matchers for
+2-tuples, including the `Lt()` matcher above. See the [CheatSheet](CheatSheet.md) for
+the complete list.
+
+Note that if you want to pass the arguments to a predicate of your own
+(e.g. `.With(Args<0, 1>(Truly(&MyPredicate)))`), that predicate MUST be
+written to take a `::testing::tuple` as its argument; Google Mock will pass the `n` selected arguments as _one_ single tuple to the predicate.
+
+## Using Matchers as Predicates ##
+
+Have you noticed that a matcher is just a fancy predicate that also
+knows how to describe itself? Many existing algorithms take predicates
+as arguments (e.g. those defined in STL's `<algorithm>` header), and
+it would be a shame if Google Mock matchers are not allowed to
+participate.
+
+Luckily, you can use a matcher where a unary predicate functor is
+expected by wrapping it inside the `Matches()` function. For example,
+
+```
+#include <algorithm>
+#include <vector>
+
+std::vector<int> v;
+...
+// How many elements in v are >= 10?
+const int count = count_if(v.begin(), v.end(), Matches(Ge(10)));
+```
+
+Since you can build complex matchers from simpler ones easily using
+Google Mock, this gives you a way to conveniently construct composite
+predicates (doing the same using STL's `<functional>` header is just
+painful). For example, here's a predicate that's satisfied by any
+number that is >= 0, <= 100, and != 50:
+
+```
+Matches(AllOf(Ge(0), Le(100), Ne(50)))
+```
+
+## Using Matchers in Google Test Assertions ##
+
+Since matchers are basically predicates that also know how to describe
+themselves, there is a way to take advantage of them in
+[Google Test](http://code.google.com/p/googletest/) assertions. It's
+called `ASSERT_THAT` and `EXPECT_THAT`:
+
+```
+  ASSERT_THAT(value, matcher);  // Asserts that value matches matcher.
+  EXPECT_THAT(value, matcher);  // The non-fatal version.
+```
+
+For example, in a Google Test test you can write:
+
+```
+#include "gmock/gmock.h"
+
+using ::testing::AllOf;
+using ::testing::Ge;
+using ::testing::Le;
+using ::testing::MatchesRegex;
+using ::testing::StartsWith;
+...
+
+  EXPECT_THAT(Foo(), StartsWith("Hello"));
+  EXPECT_THAT(Bar(), MatchesRegex("Line \\d+"));
+  ASSERT_THAT(Baz(), AllOf(Ge(5), Le(10)));
+```
+
+which (as you can probably guess) executes `Foo()`, `Bar()`, and
+`Baz()`, and verifies that:
+
+  * `Foo()` returns a string that starts with `"Hello"`.
+  * `Bar()` returns a string that matches regular expression `"Line \\d+"`.
+  * `Baz()` returns a number in the range [5, 10].
+
+The nice thing about these macros is that _they read like
+English_. They generate informative messages too. For example, if the
+first `EXPECT_THAT()` above fails, the message will be something like:
+
+```
+Value of: Foo()
+  Actual: "Hi, world!"
+Expected: starts with "Hello"
+```
+
+**Credit:** The idea of `(ASSERT|EXPECT)_THAT` was stolen from the
+[Hamcrest](http://code.google.com/p/hamcrest/) project, which adds
+`assertThat()` to JUnit.
+
+## Using Predicates as Matchers ##
+
+Google Mock provides a built-in set of matchers. In case you find them
+lacking, you can use an arbitray unary predicate function or functor
+as a matcher - as long as the predicate accepts a value of the type
+you want. You do this by wrapping the predicate inside the `Truly()`
+function, for example:
+
+```
+using ::testing::Truly;
+
+int IsEven(int n) { return (n % 2) == 0 ? 1 : 0; }
+...
+
+  // Bar() must be called with an even number.
+  EXPECT_CALL(foo, Bar(Truly(IsEven)));
+```
+
+Note that the predicate function / functor doesn't have to return
+`bool`. It works as long as the return value can be used as the
+condition in statement `if (condition) ...`.
+
+## Matching Arguments that Are Not Copyable ##
+
+When you do an `EXPECT_CALL(mock_obj, Foo(bar))`, Google Mock saves
+away a copy of `bar`. When `Foo()` is called later, Google Mock
+compares the argument to `Foo()` with the saved copy of `bar`. This
+way, you don't need to worry about `bar` being modified or destroyed
+after the `EXPECT_CALL()` is executed. The same is true when you use
+matchers like `Eq(bar)`, `Le(bar)`, and so on.
+
+But what if `bar` cannot be copied (i.e. has no copy constructor)? You
+could define your own matcher function and use it with `Truly()`, as
+the previous couple of recipes have shown. Or, you may be able to get
+away from it if you can guarantee that `bar` won't be changed after
+the `EXPECT_CALL()` is executed. Just tell Google Mock that it should
+save a reference to `bar`, instead of a copy of it. Here's how:
+
+```
+using ::testing::Eq;
+using ::testing::ByRef;
+using ::testing::Lt;
+...
+  // Expects that Foo()'s argument == bar.
+  EXPECT_CALL(mock_obj, Foo(Eq(ByRef(bar))));
+
+  // Expects that Foo()'s argument < bar.
+  EXPECT_CALL(mock_obj, Foo(Lt(ByRef(bar))));
+```
+
+Remember: if you do this, don't change `bar` after the
+`EXPECT_CALL()`, or the result is undefined.
+
+## Validating a Member of an Object ##
+
+Often a mock function takes a reference to object as an argument. When
+matching the argument, you may not want to compare the entire object
+against a fixed object, as that may be over-specification. Instead,
+you may need to validate a certain member variable or the result of a
+certain getter method of the object. You can do this with `Field()`
+and `Property()`. More specifically,
+
+```
+Field(&Foo::bar, m)
+```
+
+is a matcher that matches a `Foo` object whose `bar` member variable
+satisfies matcher `m`.
+
+```
+Property(&Foo::baz, m)
+```
+
+is a matcher that matches a `Foo` object whose `baz()` method returns
+a value that satisfies matcher `m`.
+
+For example:
+
+> | `Field(&Foo::number, Ge(3))` | Matches `x` where `x.number >= 3`. |
+|:-----------------------------|:-----------------------------------|
+> | `Property(&Foo::name, StartsWith("John "))` | Matches `x` where `x.name()` starts with `"John "`. |
+
+Note that in `Property(&Foo::baz, ...)`, method `baz()` must take no
+argument and be declared as `const`.
+
+BTW, `Field()` and `Property()` can also match plain pointers to
+objects. For instance,
+
+```
+Field(&Foo::number, Ge(3))
+```
+
+matches a plain pointer `p` where `p->number >= 3`. If `p` is `NULL`,
+the match will always fail regardless of the inner matcher.
+
+What if you want to validate more than one members at the same time?
+Remember that there is `AllOf()`.
+
+## Validating the Value Pointed to by a Pointer Argument ##
+
+C++ functions often take pointers as arguments. You can use matchers
+like `IsNull()`, `NotNull()`, and other comparison matchers to match a
+pointer, but what if you want to make sure the value _pointed to_ by
+the pointer, instead of the pointer itself, has a certain property?
+Well, you can use the `Pointee(m)` matcher.
+
+`Pointee(m)` matches a pointer iff `m` matches the value the pointer
+points to. For example:
+
+```
+using ::testing::Ge;
+using ::testing::Pointee;
+...
+  EXPECT_CALL(foo, Bar(Pointee(Ge(3))));
+```
+
+expects `foo.Bar()` to be called with a pointer that points to a value
+greater than or equal to 3.
+
+One nice thing about `Pointee()` is that it treats a `NULL` pointer as
+a match failure, so you can write `Pointee(m)` instead of
+
+```
+  AllOf(NotNull(), Pointee(m))
+```
+
+without worrying that a `NULL` pointer will crash your test.
+
+Also, did we tell you that `Pointee()` works with both raw pointers
+**and** smart pointers (`linked_ptr`, `shared_ptr`, `scoped_ptr`, and
+etc)?
+
+What if you have a pointer to pointer? You guessed it - you can use
+nested `Pointee()` to probe deeper inside the value. For example,
+`Pointee(Pointee(Lt(3)))` matches a pointer that points to a pointer
+that points to a number less than 3 (what a mouthful...).
+
+## Testing a Certain Property of an Object ##
+
+Sometimes you want to specify that an object argument has a certain
+property, but there is no existing matcher that does this. If you want
+good error messages, you should define a matcher. If you want to do it
+quick and dirty, you could get away with writing an ordinary function.
+
+Let's say you have a mock function that takes an object of type `Foo`,
+which has an `int bar()` method and an `int baz()` method, and you
+want to constrain that the argument's `bar()` value plus its `baz()`
+value is a given number. Here's how you can define a matcher to do it:
+
+```
+using ::testing::MatcherInterface;
+using ::testing::MatchResultListener;
+
+class BarPlusBazEqMatcher : public MatcherInterface<const Foo&> {
+ public:
+  explicit BarPlusBazEqMatcher(int expected_sum)
+      : expected_sum_(expected_sum) {}
+
+  virtual bool MatchAndExplain(const Foo& foo,
+                               MatchResultListener* listener) const {
+    return (foo.bar() + foo.baz()) == expected_sum_;
+  }
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "bar() + baz() equals " << expected_sum_;
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "bar() + baz() does not equal " << expected_sum_;
+  }
+ private:
+  const int expected_sum_;
+};
+
+inline Matcher<const Foo&> BarPlusBazEq(int expected_sum) {
+  return MakeMatcher(new BarPlusBazEqMatcher(expected_sum));
+}
+
+...
+
+  EXPECT_CALL(..., DoThis(BarPlusBazEq(5)))...;
+```
+
+## Matching Containers ##
+
+Sometimes an STL container (e.g. list, vector, map, ...) is passed to
+a mock function and you may want to validate it. Since most STL
+containers support the `==` operator, you can write
+`Eq(expected_container)` or simply `expected_container` to match a
+container exactly.
+
+Sometimes, though, you may want to be more flexible (for example, the
+first element must be an exact match, but the second element can be
+any positive number, and so on). Also, containers used in tests often
+have a small number of elements, and having to define the expected
+container out-of-line is a bit of a hassle.
+
+You can use the `ElementsAre()` or `UnorderedElementsAre()` matcher in
+such cases:
+
+```
+using ::testing::_;
+using ::testing::ElementsAre;
+using ::testing::Gt;
+...
+
+  MOCK_METHOD1(Foo, void(const vector<int>& numbers));
+...
+
+  EXPECT_CALL(mock, Foo(ElementsAre(1, Gt(0), _, 5)));
+```
+
+The above matcher says that the container must have 4 elements, which
+must be 1, greater than 0, anything, and 5 respectively.
+
+If you instead write:
+
+```
+using ::testing::_;
+using ::testing::Gt;
+using ::testing::UnorderedElementsAre;
+...
+
+  MOCK_METHOD1(Foo, void(const vector<int>& numbers));
+...
+
+  EXPECT_CALL(mock, Foo(UnorderedElementsAre(1, Gt(0), _, 5)));
+```
+
+It means that the container must have 4 elements, which under some
+permutation must be 1, greater than 0, anything, and 5 respectively.
+
+`ElementsAre()` and `UnorderedElementsAre()` are overloaded to take 0
+to 10 arguments. If more are needed, you can place them in a C-style
+array and use `ElementsAreArray()` or `UnorderedElementsAreArray()`
+instead:
+
+```
+using ::testing::ElementsAreArray;
+...
+
+  // ElementsAreArray accepts an array of element values.
+  const int expected_vector1[] = { 1, 5, 2, 4, ... };
+  EXPECT_CALL(mock, Foo(ElementsAreArray(expected_vector1)));
+
+  // Or, an array of element matchers.
+  Matcher<int> expected_vector2 = { 1, Gt(2), _, 3, ... };
+  EXPECT_CALL(mock, Foo(ElementsAreArray(expected_vector2)));
+```
+
+In case the array needs to be dynamically created (and therefore the
+array size cannot be inferred by the compiler), you can give
+`ElementsAreArray()` an additional argument to specify the array size:
+
+```
+using ::testing::ElementsAreArray;
+...
+  int* const expected_vector3 = new int[count];
+  ... fill expected_vector3 with values ...
+  EXPECT_CALL(mock, Foo(ElementsAreArray(expected_vector3, count)));
+```
+
+**Tips:**
+
+  * `ElementsAre*()` can be used to match _any_ container that implements the STL iterator pattern (i.e. it has a `const_iterator` type and supports `begin()/end()`), not just the ones defined in STL. It will even work with container types yet to be written - as long as they follows the above pattern.
+  * You can use nested `ElementsAre*()` to match nested (multi-dimensional) containers.
+  * If the container is passed by pointer instead of by reference, just write `Pointee(ElementsAre*(...))`.
+  * The order of elements _matters_ for `ElementsAre*()`. Therefore don't use it with containers whose element order is undefined (e.g. `hash_map`).
+
+## Sharing Matchers ##
+
+Under the hood, a Google Mock matcher object consists of a pointer to
+a ref-counted implementation object. Copying matchers is allowed and
+very efficient, as only the pointer is copied. When the last matcher
+that references the implementation object dies, the implementation
+object will be deleted.
+
+Therefore, if you have some complex matcher that you want to use again
+and again, there is no need to build it everytime. Just assign it to a
+matcher variable and use that variable repeatedly! For example,
+
+```
+  Matcher<int> in_range = AllOf(Gt(5), Le(10));
+  ... use in_range as a matcher in multiple EXPECT_CALLs ...
+```
+
+# Setting Expectations #
+
+## Knowing When to Expect ##
+
+`ON_CALL` is likely the single most under-utilized construct in Google Mock.
+
+There are basically two constructs for defining the behavior of a mock object: `ON_CALL` and `EXPECT_CALL`. The difference? `ON_CALL` defines what happens when a mock method is called, but _doesn't imply any expectation on the method being called._ `EXPECT_CALL` not only defines the behavior, but also sets an expectation that _the method will be called with the given arguments, for the given number of times_ (and _in the given order_ when you specify the order too).
+
+Since `EXPECT_CALL` does more, isn't it better than `ON_CALL`? Not really. Every `EXPECT_CALL` adds a constraint on the behavior of the code under test. Having more constraints than necessary is _baaad_ - even worse than not having enough constraints.
+
+This may be counter-intuitive. How could tests that verify more be worse than tests that verify less? Isn't verification the whole point of tests?
+
+The answer, lies in _what_ a test should verify. **A good test verifies the contract of the code.** If a test over-specifies, it doesn't leave enough freedom to the implementation. As a result, changing the implementation without breaking the contract (e.g. refactoring and optimization), which should be perfectly fine to do, can break such tests. Then you have to spend time fixing them, only to see them broken again the next time the implementation is changed.
+
+Keep in mind that one doesn't have to verify more than one property in one test. In fact, **it's a good style to verify only one thing in one test.** If you do that, a bug will likely break only one or two tests instead of dozens (which case would you rather debug?). If you are also in the habit of giving tests descriptive names that tell what they verify, you can often easily guess what's wrong just from the test log itself.
+
+So use `ON_CALL` by default, and only use `EXPECT_CALL` when you actually intend to verify that the call is made. For example, you may have a bunch of `ON_CALL`s in your test fixture to set the common mock behavior shared by all tests in the same group, and write (scarcely) different `EXPECT_CALL`s in different `TEST_F`s to verify different aspects of the code's behavior. Compared with the style where each `TEST` has many `EXPECT_CALL`s, this leads to tests that are more resilient to implementational changes (and thus less likely to require maintenance) and makes the intent of the tests more obvious (so they are easier to maintain when you do need to maintain them).
+
+If you are bothered by the "Uninteresting mock function call" message printed when a mock method without an `EXPECT_CALL` is called, you may use a `NiceMock` instead to suppress all such messages for the mock object, or suppress the message for specific methods by adding `EXPECT_CALL(...).Times(AnyNumber())`. DO NOT suppress it by blindly adding an `EXPECT_CALL(...)`, or you'll have a test that's a pain to maintain.
+
+## Ignoring Uninteresting Calls ##
+
+If you are not interested in how a mock method is called, just don't
+say anything about it. In this case, if the method is ever called,
+Google Mock will perform its default action to allow the test program
+to continue. If you are not happy with the default action taken by
+Google Mock, you can override it using `DefaultValue<T>::Set()`
+(described later in this document) or `ON_CALL()`.
+
+Please note that once you expressed interest in a particular mock
+method (via `EXPECT_CALL()`), all invocations to it must match some
+expectation. If this function is called but the arguments don't match
+any `EXPECT_CALL()` statement, it will be an error.
+
+## Disallowing Unexpected Calls ##
+
+If a mock method shouldn't be called at all, explicitly say so:
+
+```
+using ::testing::_;
+...
+  EXPECT_CALL(foo, Bar(_))
+      .Times(0);
+```
+
+If some calls to the method are allowed, but the rest are not, just
+list all the expected calls:
+
+```
+using ::testing::AnyNumber;
+using ::testing::Gt;
+...
+  EXPECT_CALL(foo, Bar(5));
+  EXPECT_CALL(foo, Bar(Gt(10)))
+      .Times(AnyNumber());
+```
+
+A call to `foo.Bar()` that doesn't match any of the `EXPECT_CALL()`
+statements will be an error.
+
+## Understanding Uninteresting vs Unexpected Calls ##
+
+_Uninteresting_ calls and _unexpected_ calls are different concepts in Google Mock. _Very_ different.
+
+A call `x.Y(...)` is **uninteresting** if there's _not even a single_ `EXPECT_CALL(x, Y(...))` set. In other words, the test isn't interested in the `x.Y()` method at all, as evident in that the test doesn't care to say anything about it.
+
+A call `x.Y(...)` is **unexpected** if there are some `EXPECT_CALL(x, Y(...))s` set, but none of them matches the call. Put another way, the test is interested in the `x.Y()` method (therefore it _explicitly_ sets some `EXPECT_CALL` to verify how it's called); however, the verification fails as the test doesn't expect this particular call to happen.
+
+**An unexpected call is always an error,** as the code under test doesn't behave the way the test expects it to behave.
+
+**By default, an uninteresting call is not an error,** as it violates no constraint specified by the test. (Google Mock's philosophy is that saying nothing means there is no constraint.) However, it leads to a warning, as it _might_ indicate a problem (e.g. the test author might have forgotten to specify a constraint).
+
+In Google Mock, `NiceMock` and `StrictMock` can be used to make a mock class "nice" or "strict". How does this affect uninteresting calls and unexpected calls?
+
+A **nice mock** suppresses uninteresting call warnings. It is less chatty than the default mock, but otherwise is the same. If a test fails with a default mock, it will also fail using a nice mock instead. And vice versa. Don't expect making a mock nice to change the test's result.
+
+A **strict mock** turns uninteresting call warnings into errors. So making a mock strict may change the test's result.
+
+Let's look at an example:
+
+```
+TEST(...) {
+  NiceMock<MockDomainRegistry> mock_registry;
+  EXPECT_CALL(mock_registry, GetDomainOwner("google.com"))
+          .WillRepeatedly(Return("Larry Page"));
+
+  // Use mock_registry in code under test.
+  ... &mock_registry ...
+}
+```
+
+The sole `EXPECT_CALL` here says that all calls to `GetDomainOwner()` must have `"google.com"` as the argument. If `GetDomainOwner("yahoo.com")` is called, it will be an unexpected call, and thus an error. Having a nice mock doesn't change the severity of an unexpected call.
+
+So how do we tell Google Mock that `GetDomainOwner()` can be called with some other arguments as well? The standard technique is to add a "catch all" `EXPECT_CALL`:
+
+```
+  EXPECT_CALL(mock_registry, GetDomainOwner(_))
+        .Times(AnyNumber());  // catches all other calls to this method.
+  EXPECT_CALL(mock_registry, GetDomainOwner("google.com"))
+        .WillRepeatedly(Return("Larry Page"));
+```
+
+Remember that `_` is the wildcard matcher that matches anything. With this, if `GetDomainOwner("google.com")` is called, it will do what the second `EXPECT_CALL` says; if it is called with a different argument, it will do what the first `EXPECT_CALL` says.
+
+Note that the order of the two `EXPECT_CALLs` is important, as a newer `EXPECT_CALL` takes precedence over an older one.
+
+For more on uninteresting calls, nice mocks, and strict mocks, read ["The Nice, the Strict, and the Naggy"](https://code.google.com/p/googlemock/wiki/CookBook#The_Nice,_the_Strict,_and_the_Naggy).
+
+## Expecting Ordered Calls ##
+
+Although an `EXPECT_CALL()` statement defined earlier takes precedence
+when Google Mock tries to match a function call with an expectation,
+by default calls don't have to happen in the order `EXPECT_CALL()`
+statements are written. For example, if the arguments match the
+matchers in the third `EXPECT_CALL()`, but not those in the first two,
+then the third expectation will be used.
+
+If you would rather have all calls occur in the order of the
+expectations, put the `EXPECT_CALL()` statements in a block where you
+define a variable of type `InSequence`:
+
+```
+  using ::testing::_;
+  using ::testing::InSequence;
+
+  {
+    InSequence s;
+
+    EXPECT_CALL(foo, DoThis(5));
+    EXPECT_CALL(bar, DoThat(_))
+        .Times(2);
+    EXPECT_CALL(foo, DoThis(6));
+  }
+```
+
+In this example, we expect a call to `foo.DoThis(5)`, followed by two
+calls to `bar.DoThat()` where the argument can be anything, which are
+in turn followed by a call to `foo.DoThis(6)`. If a call occurred
+out-of-order, Google Mock will report an error.
+
+## Expecting Partially Ordered Calls ##
+
+Sometimes requiring everything to occur in a predetermined order can
+lead to brittle tests. For example, we may care about `A` occurring
+before both `B` and `C`, but aren't interested in the relative order
+of `B` and `C`. In this case, the test should reflect our real intent,
+instead of being overly constraining.
+
+Google Mock allows you to impose an arbitrary DAG (directed acyclic
+graph) on the calls. One way to express the DAG is to use the
+[After](http://code.google.com/p/googlemock/wiki/CheatSheet#The_After_Clause) clause of `EXPECT_CALL`.
+
+Another way is via the `InSequence()` clause (not the same as the
+`InSequence` class), which we borrowed from jMock 2. It's less
+flexible than `After()`, but more convenient when you have long chains
+of sequential calls, as it doesn't require you to come up with
+different names for the expectations in the chains.  Here's how it
+works:
+
+If we view `EXPECT_CALL()` statements as nodes in a graph, and add an
+edge from node A to node B wherever A must occur before B, we can get
+a DAG. We use the term "sequence" to mean a directed path in this
+DAG. Now, if we decompose the DAG into sequences, we just need to know
+which sequences each `EXPECT_CALL()` belongs to in order to be able to
+reconstruct the orginal DAG.
+
+So, to specify the partial order on the expectations we need to do two
+things: first to define some `Sequence` objects, and then for each
+`EXPECT_CALL()` say which `Sequence` objects it is part
+of. Expectations in the same sequence must occur in the order they are
+written. For example,
+
+```
+  using ::testing::Sequence;
+
+  Sequence s1, s2;
+
+  EXPECT_CALL(foo, A())
+      .InSequence(s1, s2);
+  EXPECT_CALL(bar, B())
+      .InSequence(s1);
+  EXPECT_CALL(bar, C())
+      .InSequence(s2);
+  EXPECT_CALL(foo, D())
+      .InSequence(s2);
+```
+
+specifies the following DAG (where `s1` is `A -> B`, and `s2` is `A ->
+C -> D`):
+
+```
+       +---> B
+       |
+  A ---|
+       |
+       +---> C ---> D
+```
+
+This means that A must occur before B and C, and C must occur before
+D. There's no restriction about the order other than these.
+
+## Controlling When an Expectation Retires ##
+
+When a mock method is called, Google Mock only consider expectations
+that are still active. An expectation is active when created, and
+becomes inactive (aka _retires_) when a call that has to occur later
+has occurred. For example, in
+
+```
+  using ::testing::_;
+  using ::testing::Sequence;
+
+  Sequence s1, s2;
+
+  EXPECT_CALL(log, Log(WARNING, _, "File too large."))     // #1
+      .Times(AnyNumber())
+      .InSequence(s1, s2);
+  EXPECT_CALL(log, Log(WARNING, _, "Data set is empty."))  // #2
+      .InSequence(s1);
+  EXPECT_CALL(log, Log(WARNING, _, "User not found."))     // #3
+      .InSequence(s2);
+```
+
+as soon as either #2 or #3 is matched, #1 will retire. If a warning
+`"File too large."` is logged after this, it will be an error.
+
+Note that an expectation doesn't retire automatically when it's
+saturated. For example,
+
+```
+using ::testing::_;
+...
+  EXPECT_CALL(log, Log(WARNING, _, _));                  // #1
+  EXPECT_CALL(log, Log(WARNING, _, "File too large."));  // #2
+```
+
+says that there will be exactly one warning with the message `"File
+too large."`. If the second warning contains this message too, #2 will
+match again and result in an upper-bound-violated error.
+
+If this is not what you want, you can ask an expectation to retire as
+soon as it becomes saturated:
+
+```
+using ::testing::_;
+...
+  EXPECT_CALL(log, Log(WARNING, _, _));                 // #1
+  EXPECT_CALL(log, Log(WARNING, _, "File too large."))  // #2
+      .RetiresOnSaturation();
+```
+
+Here #2 can be used only once, so if you have two warnings with the
+message `"File too large."`, the first will match #2 and the second
+will match #1 - there will be no error.
+
+# Using Actions #
+
+## Returning References from Mock Methods ##
+
+If a mock function's return type is a reference, you need to use
+`ReturnRef()` instead of `Return()` to return a result:
+
+```
+using ::testing::ReturnRef;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD0(GetBar, Bar&());
+};
+...
+
+  MockFoo foo;
+  Bar bar;
+  EXPECT_CALL(foo, GetBar())
+      .WillOnce(ReturnRef(bar));
+```
+
+## Returning Live Values from Mock Methods ##
+
+The `Return(x)` action saves a copy of `x` when the action is
+_created_, and always returns the same value whenever it's
+executed. Sometimes you may want to instead return the _live_ value of
+`x` (i.e. its value at the time when the action is _executed_.).
+
+If the mock function's return type is a reference, you can do it using
+`ReturnRef(x)`, as shown in the previous recipe ("Returning References
+from Mock Methods"). However, Google Mock doesn't let you use
+`ReturnRef()` in a mock function whose return type is not a reference,
+as doing that usually indicates a user error. So, what shall you do?
+
+You may be tempted to try `ByRef()`:
+
+```
+using testing::ByRef;
+using testing::Return;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD0(GetValue, int());
+};
+...
+  int x = 0;
+  MockFoo foo;
+  EXPECT_CALL(foo, GetValue())
+      .WillRepeatedly(Return(ByRef(x)));
+  x = 42;
+  EXPECT_EQ(42, foo.GetValue());
+```
+
+Unfortunately, it doesn't work here. The above code will fail with error:
+
+```
+Value of: foo.GetValue()
+  Actual: 0
+Expected: 42
+```
+
+The reason is that `Return(value)` converts `value` to the actual
+return type of the mock function at the time when the action is
+_created_, not when it is _executed_. (This behavior was chosen for
+the action to be safe when `value` is a proxy object that references
+some temporary objects.) As a result, `ByRef(x)` is converted to an
+`int` value (instead of a `const int&`) when the expectation is set,
+and `Return(ByRef(x))` will always return 0.
+
+`ReturnPointee(pointer)` was provided to solve this problem
+specifically. It returns the value pointed to by `pointer` at the time
+the action is _executed_:
+
+```
+using testing::ReturnPointee;
+...
+  int x = 0;
+  MockFoo foo;
+  EXPECT_CALL(foo, GetValue())
+      .WillRepeatedly(ReturnPointee(&x));  // Note the & here.
+  x = 42;
+  EXPECT_EQ(42, foo.GetValue());  // This will succeed now.
+```
+
+## Combining Actions ##
+
+Want to do more than one thing when a function is called? That's
+fine. `DoAll()` allow you to do sequence of actions every time. Only
+the return value of the last action in the sequence will be used.
+
+```
+using ::testing::DoAll;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD1(Bar, bool(int n));
+};
+...
+
+  EXPECT_CALL(foo, Bar(_))
+      .WillOnce(DoAll(action_1,
+                      action_2,
+                      ...
+                      action_n));
+```
+
+## Mocking Side Effects ##
+
+Sometimes a method exhibits its effect not via returning a value but
+via side effects. For example, it may change some global state or
+modify an output argument. To mock side effects, in general you can
+define your own action by implementing `::testing::ActionInterface`.
+
+If all you need to do is to change an output argument, the built-in
+`SetArgPointee()` action is convenient:
+
+```
+using ::testing::SetArgPointee;
+
+class MockMutator : public Mutator {
+ public:
+  MOCK_METHOD2(Mutate, void(bool mutate, int* value));
+  ...
+};
+...
+
+  MockMutator mutator;
+  EXPECT_CALL(mutator, Mutate(true, _))
+      .WillOnce(SetArgPointee<1>(5));
+```
+
+In this example, when `mutator.Mutate()` is called, we will assign 5
+to the `int` variable pointed to by argument #1
+(0-based).
+
+`SetArgPointee()` conveniently makes an internal copy of the
+value you pass to it, removing the need to keep the value in scope and
+alive. The implication however is that the value must have a copy
+constructor and assignment operator.
+
+If the mock method also needs to return a value as well, you can chain
+`SetArgPointee()` with `Return()` using `DoAll()`:
+
+```
+using ::testing::_;
+using ::testing::Return;
+using ::testing::SetArgPointee;
+
+class MockMutator : public Mutator {
+ public:
+  ...
+  MOCK_METHOD1(MutateInt, bool(int* value));
+};
+...
+
+  MockMutator mutator;
+  EXPECT_CALL(mutator, MutateInt(_))
+      .WillOnce(DoAll(SetArgPointee<0>(5),
+                      Return(true)));
+```
+
+If the output argument is an array, use the
+`SetArrayArgument<N>(first, last)` action instead. It copies the
+elements in source range `[first, last)` to the array pointed to by
+the `N`-th (0-based) argument:
+
+```
+using ::testing::NotNull;
+using ::testing::SetArrayArgument;
+
+class MockArrayMutator : public ArrayMutator {
+ public:
+  MOCK_METHOD2(Mutate, void(int* values, int num_values));
+  ...
+};
+...
+
+  MockArrayMutator mutator;
+  int values[5] = { 1, 2, 3, 4, 5 };
+  EXPECT_CALL(mutator, Mutate(NotNull(), 5))
+      .WillOnce(SetArrayArgument<0>(values, values + 5));
+```
+
+This also works when the argument is an output iterator:
+
+```
+using ::testing::_;
+using ::testing::SeArrayArgument;
+
+class MockRolodex : public Rolodex {
+ public:
+  MOCK_METHOD1(GetNames, void(std::back_insert_iterator<vector<string> >));
+  ...
+};
+...
+
+  MockRolodex rolodex;
+  vector<string> names;
+  names.push_back("George");
+  names.push_back("John");
+  names.push_back("Thomas");
+  EXPECT_CALL(rolodex, GetNames(_))
+      .WillOnce(SetArrayArgument<0>(names.begin(), names.end()));
+```
+
+## Changing a Mock Object's Behavior Based on the State ##
+
+If you expect a call to change the behavior of a mock object, you can use `::testing::InSequence` to specify different behaviors before and after the call:
+
+```
+using ::testing::InSequence;
+using ::testing::Return;
+
+...
+  {
+    InSequence seq;
+    EXPECT_CALL(my_mock, IsDirty())
+        .WillRepeatedly(Return(true));
+    EXPECT_CALL(my_mock, Flush());
+    EXPECT_CALL(my_mock, IsDirty())
+        .WillRepeatedly(Return(false));
+  }
+  my_mock.FlushIfDirty();
+```
+
+This makes `my_mock.IsDirty()` return `true` before `my_mock.Flush()` is called and return `false` afterwards.
+
+If the behavior change is more complex, you can store the effects in a variable and make a mock method get its return value from that variable:
+
+```
+using ::testing::_;
+using ::testing::SaveArg;
+using ::testing::Return;
+
+ACTION_P(ReturnPointee, p) { return *p; }
+...
+  int previous_value = 0;
+  EXPECT_CALL(my_mock, GetPrevValue())
+      .WillRepeatedly(ReturnPointee(&previous_value));
+  EXPECT_CALL(my_mock, UpdateValue(_))
+      .WillRepeatedly(SaveArg<0>(&previous_value));
+  my_mock.DoSomethingToUpdateValue();
+```
+
+Here `my_mock.GetPrevValue()` will always return the argument of the last `UpdateValue()` call.
+
+## Setting the Default Value for a Return Type ##
+
+If a mock method's return type is a built-in C++ type or pointer, by
+default it will return 0 when invoked. Also, in C++ 11 and above, a mock
+method whose return type has a default constructor will return a default-constructed
+value by default.  You only need to specify an
+action if this default value doesn't work for you.
+
+Sometimes, you may want to change this default value, or you may want
+to specify a default value for types Google Mock doesn't know
+about. You can do this using the `::testing::DefaultValue` class
+template:
+
+```
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD0(CalculateBar, Bar());
+};
+...
+
+  Bar default_bar;
+  // Sets the default return value for type Bar.
+  DefaultValue<Bar>::Set(default_bar);
+
+  MockFoo foo;
+
+  // We don't need to specify an action here, as the default
+  // return value works for us.
+  EXPECT_CALL(foo, CalculateBar());
+
+  foo.CalculateBar();  // This should return default_bar.
+
+  // Unsets the default return value.
+  DefaultValue<Bar>::Clear();
+```
+
+Please note that changing the default value for a type can make you
+tests hard to understand. We recommend you to use this feature
+judiciously. For example, you may want to make sure the `Set()` and
+`Clear()` calls are right next to the code that uses your mock.
+
+## Setting the Default Actions for a Mock Method ##
+
+You've learned how to change the default value of a given
+type. However, this may be too coarse for your purpose: perhaps you
+have two mock methods with the same return type and you want them to
+have different behaviors. The `ON_CALL()` macro allows you to
+customize your mock's behavior at the method level:
+
+```
+using ::testing::_;
+using ::testing::AnyNumber;
+using ::testing::Gt;
+using ::testing::Return;
+...
+  ON_CALL(foo, Sign(_))
+      .WillByDefault(Return(-1));
+  ON_CALL(foo, Sign(0))
+      .WillByDefault(Return(0));
+  ON_CALL(foo, Sign(Gt(0)))
+      .WillByDefault(Return(1));
+
+  EXPECT_CALL(foo, Sign(_))
+      .Times(AnyNumber());
+
+  foo.Sign(5);   // This should return 1.
+  foo.Sign(-9);  // This should return -1.
+  foo.Sign(0);   // This should return 0.
+```
+
+As you may have guessed, when there are more than one `ON_CALL()`
+statements, the news order take precedence over the older ones. In
+other words, the **last** one that matches the function arguments will
+be used. This matching order allows you to set up the common behavior
+in a mock object's constructor or the test fixture's set-up phase and
+specialize the mock's behavior later.
+
+## Using Functions/Methods/Functors as Actions ##
+
+If the built-in actions don't suit you, you can easily use an existing
+function, method, or functor as an action:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD2(Sum, int(int x, int y));
+  MOCK_METHOD1(ComplexJob, bool(int x));
+};
+
+int CalculateSum(int x, int y) { return x + y; }
+
+class Helper {
+ public:
+  bool ComplexJob(int x);
+};
+...
+
+  MockFoo foo;
+  Helper helper;
+  EXPECT_CALL(foo, Sum(_, _))
+      .WillOnce(Invoke(CalculateSum));
+  EXPECT_CALL(foo, ComplexJob(_))
+      .WillOnce(Invoke(&helper, &Helper::ComplexJob));
+
+  foo.Sum(5, 6);       // Invokes CalculateSum(5, 6).
+  foo.ComplexJob(10);  // Invokes helper.ComplexJob(10);
+```
+
+The only requirement is that the type of the function, etc must be
+_compatible_ with the signature of the mock function, meaning that the
+latter's arguments can be implicitly converted to the corresponding
+arguments of the former, and the former's return type can be
+implicitly converted to that of the latter. So, you can invoke
+something whose type is _not_ exactly the same as the mock function,
+as long as it's safe to do so - nice, huh?
+
+## Invoking a Function/Method/Functor Without Arguments ##
+
+`Invoke()` is very useful for doing actions that are more complex. It
+passes the mock function's arguments to the function or functor being
+invoked such that the callee has the full context of the call to work
+with. If the invoked function is not interested in some or all of the
+arguments, it can simply ignore them.
+
+Yet, a common pattern is that a test author wants to invoke a function
+without the arguments of the mock function. `Invoke()` allows her to
+do that using a wrapper function that throws away the arguments before
+invoking an underlining nullary function. Needless to say, this can be
+tedious and obscures the intent of the test.
+
+`InvokeWithoutArgs()` solves this problem. It's like `Invoke()` except
+that it doesn't pass the mock function's arguments to the
+callee. Here's an example:
+
+```
+using ::testing::_;
+using ::testing::InvokeWithoutArgs;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD1(ComplexJob, bool(int n));
+};
+
+bool Job1() { ... }
+...
+
+  MockFoo foo;
+  EXPECT_CALL(foo, ComplexJob(_))
+      .WillOnce(InvokeWithoutArgs(Job1));
+
+  foo.ComplexJob(10);  // Invokes Job1().
+```
+
+## Invoking an Argument of the Mock Function ##
+
+Sometimes a mock function will receive a function pointer or a functor
+(in other words, a "callable") as an argument, e.g.
+
+```
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD2(DoThis, bool(int n, bool (*fp)(int)));
+};
+```
+
+and you may want to invoke this callable argument:
+
+```
+using ::testing::_;
+...
+  MockFoo foo;
+  EXPECT_CALL(foo, DoThis(_, _))
+      .WillOnce(...);
+  // Will execute (*fp)(5), where fp is the
+  // second argument DoThis() receives.
+```
+
+Arghh, you need to refer to a mock function argument but C++ has no
+lambda (yet), so you have to define your own action. :-( Or do you
+really?
+
+Well, Google Mock has an action to solve _exactly_ this problem:
+
+```
+  InvokeArgument<N>(arg_1, arg_2, ..., arg_m)
+```
+
+will invoke the `N`-th (0-based) argument the mock function receives,
+with `arg_1`, `arg_2`, ..., and `arg_m`. No matter if the argument is
+a function pointer or a functor, Google Mock handles them both.
+
+With that, you could write:
+
+```
+using ::testing::_;
+using ::testing::InvokeArgument;
+...
+  EXPECT_CALL(foo, DoThis(_, _))
+      .WillOnce(InvokeArgument<1>(5));
+  // Will execute (*fp)(5), where fp is the
+  // second argument DoThis() receives.
+```
+
+What if the callable takes an argument by reference? No problem - just
+wrap it inside `ByRef()`:
+
+```
+...
+  MOCK_METHOD1(Bar, bool(bool (*fp)(int, const Helper&)));
+...
+using ::testing::_;
+using ::testing::ByRef;
+using ::testing::InvokeArgument;
+...
+
+  MockFoo foo;
+  Helper helper;
+  ...
+  EXPECT_CALL(foo, Bar(_))
+      .WillOnce(InvokeArgument<0>(5, ByRef(helper)));
+  // ByRef(helper) guarantees that a reference to helper, not a copy of it,
+  // will be passed to the callable.
+```
+
+What if the callable takes an argument by reference and we do **not**
+wrap the argument in `ByRef()`? Then `InvokeArgument()` will _make a
+copy_ of the argument, and pass a _reference to the copy_, instead of
+a reference to the original value, to the callable. This is especially
+handy when the argument is a temporary value:
+
+```
+...
+  MOCK_METHOD1(DoThat, bool(bool (*f)(const double& x, const string& s)));
+...
+using ::testing::_;
+using ::testing::InvokeArgument;
+...
+
+  MockFoo foo;
+  ...
+  EXPECT_CALL(foo, DoThat(_))
+      .WillOnce(InvokeArgument<0>(5.0, string("Hi")));
+  // Will execute (*f)(5.0, string("Hi")), where f is the function pointer
+  // DoThat() receives.  Note that the values 5.0 and string("Hi") are
+  // temporary and dead once the EXPECT_CALL() statement finishes.  Yet
+  // it's fine to perform this action later, since a copy of the values
+  // are kept inside the InvokeArgument action.
+```
+
+## Ignoring an Action's Result ##
+
+Sometimes you have an action that returns _something_, but you need an
+action that returns `void` (perhaps you want to use it in a mock
+function that returns `void`, or perhaps it needs to be used in
+`DoAll()` and it's not the last in the list). `IgnoreResult()` lets
+you do that. For example:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::Return;
+
+int Process(const MyData& data);
+string DoSomething();
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD1(Abc, void(const MyData& data));
+  MOCK_METHOD0(Xyz, bool());
+};
+...
+
+  MockFoo foo;
+  EXPECT_CALL(foo, Abc(_))
+  // .WillOnce(Invoke(Process));
+  // The above line won't compile as Process() returns int but Abc() needs
+  // to return void.
+      .WillOnce(IgnoreResult(Invoke(Process)));
+
+  EXPECT_CALL(foo, Xyz())
+      .WillOnce(DoAll(IgnoreResult(Invoke(DoSomething)),
+      // Ignores the string DoSomething() returns.
+                      Return(true)));
+```
+
+Note that you **cannot** use `IgnoreResult()` on an action that already
+returns `void`. Doing so will lead to ugly compiler errors.
+
+## Selecting an Action's Arguments ##
+
+Say you have a mock function `Foo()` that takes seven arguments, and
+you have a custom action that you want to invoke when `Foo()` is
+called. Trouble is, the custom action only wants three arguments:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+...
+  MOCK_METHOD7(Foo, bool(bool visible, const string& name, int x, int y,
+                         const map<pair<int, int>, double>& weight,
+                         double min_weight, double max_wight));
+...
+
+bool IsVisibleInQuadrant1(bool visible, int x, int y) {
+  return visible && x >= 0 && y >= 0;
+}
+...
+
+  EXPECT_CALL(mock, Foo(_, _, _, _, _, _, _))
+      .WillOnce(Invoke(IsVisibleInQuadrant1));  // Uh, won't compile. :-(
+```
+
+To please the compiler God, you can to define an "adaptor" that has
+the same signature as `Foo()` and calls the custom action with the
+right arguments:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+
+bool MyIsVisibleInQuadrant1(bool visible, const string& name, int x, int y,
+                            const map<pair<int, int>, double>& weight,
+                            double min_weight, double max_wight) {
+  return IsVisibleInQuadrant1(visible, x, y);
+}
+...
+
+  EXPECT_CALL(mock, Foo(_, _, _, _, _, _, _))
+      .WillOnce(Invoke(MyIsVisibleInQuadrant1));  // Now it works.
+```
+
+But isn't this awkward?
+
+Google Mock provides a generic _action adaptor_, so you can spend your
+time minding more important business than writing your own
+adaptors. Here's the syntax:
+
+```
+  WithArgs<N1, N2, ..., Nk>(action)
+```
+
+creates an action that passes the arguments of the mock function at
+the given indices (0-based) to the inner `action` and performs
+it. Using `WithArgs`, our original example can be written as:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::WithArgs;
+...
+  EXPECT_CALL(mock, Foo(_, _, _, _, _, _, _))
+      .WillOnce(WithArgs<0, 2, 3>(Invoke(IsVisibleInQuadrant1)));
+      // No need to define your own adaptor.
+```
+
+For better readability, Google Mock also gives you:
+
+  * `WithoutArgs(action)` when the inner `action` takes _no_ argument, and
+  * `WithArg<N>(action)` (no `s` after `Arg`) when the inner `action` takes _one_ argument.
+
+As you may have realized, `InvokeWithoutArgs(...)` is just syntactic
+sugar for `WithoutArgs(Inovke(...))`.
+
+Here are more tips:
+
+  * The inner action used in `WithArgs` and friends does not have to be `Invoke()` -- it can be anything.
+  * You can repeat an argument in the argument list if necessary, e.g. `WithArgs<2, 3, 3, 5>(...)`.
+  * You can change the order of the arguments, e.g. `WithArgs<3, 2, 1>(...)`.
+  * The types of the selected arguments do _not_ have to match the signature of the inner action exactly. It works as long as they can be implicitly converted to the corresponding arguments of the inner action. For example, if the 4-th argument of the mock function is an `int` and `my_action` takes a `double`, `WithArg<4>(my_action)` will work.
+
+## Ignoring Arguments in Action Functions ##
+
+The selecting-an-action's-arguments recipe showed us one way to make a
+mock function and an action with incompatible argument lists fit
+together. The downside is that wrapping the action in
+`WithArgs<...>()` can get tedious for people writing the tests.
+
+If you are defining a function, method, or functor to be used with
+`Invoke*()`, and you are not interested in some of its arguments, an
+alternative to `WithArgs` is to declare the uninteresting arguments as
+`Unused`. This makes the definition less cluttered and less fragile in
+case the types of the uninteresting arguments change. It could also
+increase the chance the action function can be reused. For example,
+given
+
+```
+  MOCK_METHOD3(Foo, double(const string& label, double x, double y));
+  MOCK_METHOD3(Bar, double(int index, double x, double y));
+```
+
+instead of
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+
+double DistanceToOriginWithLabel(const string& label, double x, double y) {
+  return sqrt(x*x + y*y);
+}
+
+double DistanceToOriginWithIndex(int index, double x, double y) {
+  return sqrt(x*x + y*y);
+}
+...
+
+  EXEPCT_CALL(mock, Foo("abc", _, _))
+      .WillOnce(Invoke(DistanceToOriginWithLabel));
+  EXEPCT_CALL(mock, Bar(5, _, _))
+      .WillOnce(Invoke(DistanceToOriginWithIndex));
+```
+
+you could write
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::Unused;
+
+double DistanceToOrigin(Unused, double x, double y) {
+  return sqrt(x*x + y*y);
+}
+...
+
+  EXEPCT_CALL(mock, Foo("abc", _, _))
+      .WillOnce(Invoke(DistanceToOrigin));
+  EXEPCT_CALL(mock, Bar(5, _, _))
+      .WillOnce(Invoke(DistanceToOrigin));
+```
+
+## Sharing Actions ##
+
+Just like matchers, a Google Mock action object consists of a pointer
+to a ref-counted implementation object. Therefore copying actions is
+also allowed and very efficient. When the last action that references
+the implementation object dies, the implementation object will be
+deleted.
+
+If you have some complex action that you want to use again and again,
+you may not have to build it from scratch everytime. If the action
+doesn't have an internal state (i.e. if it always does the same thing
+no matter how many times it has been called), you can assign it to an
+action variable and use that variable repeatedly. For example:
+
+```
+  Action<bool(int*)> set_flag = DoAll(SetArgPointee<0>(5),
+                                      Return(true));
+  ... use set_flag in .WillOnce() and .WillRepeatedly() ...
+```
+
+However, if the action has its own state, you may be surprised if you
+share the action object. Suppose you have an action factory
+`IncrementCounter(init)` which creates an action that increments and
+returns a counter whose initial value is `init`, using two actions
+created from the same expression and using a shared action will
+exihibit different behaviors. Example:
+
+```
+  EXPECT_CALL(foo, DoThis())
+      .WillRepeatedly(IncrementCounter(0));
+  EXPECT_CALL(foo, DoThat())
+      .WillRepeatedly(IncrementCounter(0));
+  foo.DoThis();  // Returns 1.
+  foo.DoThis();  // Returns 2.
+  foo.DoThat();  // Returns 1 - Blah() uses a different
+                 // counter than Bar()'s.
+```
+
+versus
+
+```
+  Action<int()> increment = IncrementCounter(0);
+
+  EXPECT_CALL(foo, DoThis())
+      .WillRepeatedly(increment);
+  EXPECT_CALL(foo, DoThat())
+      .WillRepeatedly(increment);
+  foo.DoThis();  // Returns 1.
+  foo.DoThis();  // Returns 2.
+  foo.DoThat();  // Returns 3 - the counter is shared.
+```
+
+# Misc Recipes on Using Google Mock #
+
+## Mocking Methods That Use Move-Only Types ##
+
+C++11 introduced <em>move-only types</em>.  A move-only-typed value can be moved from one object to another, but cannot be copied.  `std::unique_ptr<T>` is probably the most commonly used move-only type.
+
+Mocking a method that takes and/or returns move-only types presents some challenges, but nothing insurmountable.  This recipe shows you how you can do it.
+
+Let’s say we are working on a fictional project that lets one post and share snippets called “buzzes”.  Your code uses these types:
+
+```
+enum class AccessLevel { kInternal, kPublic };
+
+class Buzz {
+ public:
+  explicit Buzz(AccessLevel access) { … }
+  ...
+};
+
+class Buzzer {
+ public:
+  virtual ~Buzzer() {}
+  virtual std::unique_ptr<Buzz> MakeBuzz(const std::string& text) = 0;
+  virtual bool ShareBuzz(std::unique_ptr<Buzz> buzz, Time timestamp) = 0;
+  ...
+};
+```
+
+A `Buzz` object represents a snippet being posted.  A class that implements the `Buzzer` interface is capable of creating and sharing `Buzz`.  Methods in `Buzzer` may return a `unique_ptr<Buzz>` or take a `unique_ptr<Buzz>`.  Now we need to mock `Buzzer` in our tests.
+
+To mock a method that returns a move-only type, you just use the familiar `MOCK_METHOD` syntax as usual:
+
+```
+class MockBuzzer : public Buzzer {
+ public:
+  MOCK_METHOD1(MakeBuzz, std::unique_ptr<Buzz>(const std::string& text));
+  …
+};
+```
+
+However, if you attempt to use the same `MOCK_METHOD` pattern to mock a method that takes a move-only parameter, you’ll get a compiler error currently:
+
+```
+  // Does NOT compile!
+  MOCK_METHOD2(ShareBuzz, bool(std::unique_ptr<Buzz> buzz, Time timestamp));
+```
+
+While it’s highly desirable to make this syntax just work, it’s not trivial and the work hasn’t been done yet.  Fortunately, there is a trick you can apply today to get something that works nearly as well as this.
+
+The trick, is to delegate the `ShareBuzz()` method to a mock method (let’s call it `DoShareBuzz()`) that does not take move-only parameters:
+
+```
+class MockBuzzer : public Buzzer {
+ public:
+  MOCK_METHOD1(MakeBuzz, std::unique_ptr<Buzz>(const std::string& text));
+  MOCK_METHOD2(DoShareBuzz, bool(Buzz* buzz, Time timestamp));
+  bool ShareBuzz(std::unique_ptr<Buzz> buzz, Time timestamp) {
+    return DoShareBuzz(buzz.get(), timestamp);
+  }
+};
+```
+
+Note that there's no need to define or declare `DoShareBuzz()` in a base class.  You only need to define it as a `MOCK_METHOD` in the mock class.
+
+Now that we have the mock class defined, we can use it in tests.  In the following code examples, we assume that we have defined a `MockBuzzer` object named `mock_buzzer_`:
+
+```
+  MockBuzzer mock_buzzer_;
+```
+
+First let’s see how we can set expectations on the `MakeBuzz()` method, which returns a `unique_ptr<Buzz>`.
+
+As usual, if you set an expectation without an action (i.e. the `.WillOnce()` or `.WillRepeated()` clause), when that expectation fires, the default action for that method will be taken.  Since `unique_ptr<>` has a default constructor that returns a null `unique_ptr`, that’s what you’ll get if you don’t specify an action:
+
+```
+  // Use the default action.
+  EXPECT_CALL(mock_buzzer_, MakeBuzz("hello"));
+
+  // Triggers the previous EXPECT_CALL.
+  EXPECT_EQ(nullptr, mock_buzzer_.MakeBuzz("hello"));
+```
+
+If you are not happy with the default action, you can tweak it.  Depending on what you need, you may either tweak the default action for a specific (mock object, mock method) combination using `ON_CALL()`, or you may tweak the default action for all mock methods that return a specific type.  The usage of `ON_CALL()` is similar to `EXPECT_CALL()`, so we’ll skip it and just explain how to do the latter (tweaking the default action for a specific return type).  You do this via the `DefaultValue<>::SetFactory()` and `DefaultValue<>::Clear()` API:
+
+```
+  // Sets the default action for return type std::unique_ptr<Buzz> to
+  // creating a new Buzz every time.
+  DefaultValue<std::unique_ptr<Buzz>>::SetFactory(
+      [] { return MakeUnique<Buzz>(AccessLevel::kInternal); });
+
+  // When this fires, the default action of MakeBuzz() will run, which
+  // will return a new Buzz object.
+  EXPECT_CALL(mock_buzzer_, MakeBuzz("hello")).Times(AnyNumber());
+
+  auto buzz1 = mock_buzzer_.MakeBuzz("hello");
+  auto buzz2 = mock_buzzer_.MakeBuzz("hello");
+  EXPECT_NE(nullptr, buzz1);
+  EXPECT_NE(nullptr, buzz2);
+  EXPECT_NE(buzz1, buzz2);
+
+  // Resets the default action for return type std::unique_ptr<Buzz>,
+  // to avoid interfere with other tests.
+  DefaultValue<std::unique_ptr<Buzz>>::Clear();
+```
+
+What if you want the method to do something other than the default action?  If you just need to return a pre-defined move-only value, you can use the `Return(ByMove(...))` action:
+
+```
+  // When this fires, the unique_ptr<> specified by ByMove(...) will
+  // be returned.
+  EXPECT_CALL(mock_buzzer_, MakeBuzz("world"))
+      .WillOnce(Return(ByMove(MakeUnique<Buzz>(AccessLevel::kInternal))));
+
+  EXPECT_NE(nullptr, mock_buzzer_.MakeBuzz("world"));
+```
+
+Note that `ByMove()` is essential here - if you drop it, the code won’t compile.
+
+Quiz time!  What do you think will happen if a `Return(ByMove(...))` action is performed more than once (e.g. you write `….WillRepeatedly(Return(ByMove(...)));`)?  Come think of it, after the first time the action runs, the source value will be consumed (since it’s a move-only value), so the next time around, there’s no value to move from -- you’ll get a run-time error that `Return(ByMove(...))` can only be run once.
+
+If you need your mock method to do more than just moving a pre-defined value, remember that you can always use `Invoke()` to call a lambda or a callable object, which can do pretty much anything you want:
+
+```
+  EXPECT_CALL(mock_buzzer_, MakeBuzz("x"))
+      .WillRepeatedly(Invoke([](const std::string& text) {
+        return std::make_unique<Buzz>(AccessLevel::kInternal);
+      }));
+
+  EXPECT_NE(nullptr, mock_buzzer_.MakeBuzz("x"));
+  EXPECT_NE(nullptr, mock_buzzer_.MakeBuzz("x"));
+```
+
+Every time this `EXPECT_CALL` fires, a new `unique_ptr<Buzz>` will be created and returned.  You cannot do this with `Return(ByMove(...))`.
+
+Now there’s one topic we haven’t covered: how do you set expectations on `ShareBuzz()`, which takes a move-only-typed parameter?  The answer is you don’t.  Instead, you set expectations on the `DoShareBuzz()` mock method (remember that we defined a `MOCK_METHOD` for `DoShareBuzz()`, not `ShareBuzz()`):
+
+```
+  EXPECT_CALL(mock_buzzer_, DoShareBuzz(NotNull(), _));
+
+  // When one calls ShareBuzz() on the MockBuzzer like this, the call is
+  // forwarded to DoShareBuzz(), which is mocked.  Therefore this statement
+  // will trigger the above EXPECT_CALL.
+  mock_buzzer_.ShareBuzz(MakeUnique&lt;Buzz&gt;(AccessLevel::kInternal),
+                         ::base::Now());
+```
+
+Some of you may have spotted one problem with this approach: the `DoShareBuzz()` mock method differs from the real `ShareBuzz()` method in that it cannot take ownership of the buzz parameter - `ShareBuzz()` will always delete buzz after `DoShareBuzz()` returns.  What if you need to save the buzz object somewhere for later use when `ShareBuzz()` is called?  Indeed, you'd be stuck.
+
+Another problem with the `DoShareBuzz()` we had is that it can surprise people reading or maintaining the test, as one would expect that `DoShareBuzz()` has (logically) the same contract as `ShareBuzz()`.
+
+Fortunately, these problems can be fixed with a bit more code.  Let's try to get it right this time:
+
+```
+class MockBuzzer : public Buzzer {
+ public:
+  MockBuzzer() {
+    // Since DoShareBuzz(buzz, time) is supposed to take ownership of
+    // buzz, define a default behavior for DoShareBuzz(buzz, time) to
+    // delete buzz.
+    ON_CALL(*this, DoShareBuzz(_, _))
+        .WillByDefault(Invoke([](Buzz* buzz, Time timestamp) {
+          delete buzz;
+          return true;
+        }));
+  }
+
+  MOCK_METHOD1(MakeBuzz, std::unique_ptr<Buzz>(const std::string& text));
+
+  // Takes ownership of buzz.
+  MOCK_METHOD2(DoShareBuzz, bool(Buzz* buzz, Time timestamp));
+  bool ShareBuzz(std::unique_ptr<Buzz> buzz, Time timestamp) {
+    return DoShareBuzz(buzz.release(), timestamp);
+  }
+};
+```
+
+Now, the mock `DoShareBuzz()` method is free to save the buzz argument for later use if this is what you want:
+
+```
+  std::unique_ptr<Buzz> intercepted_buzz;
+  EXPECT_CALL(mock_buzzer_, DoShareBuzz(NotNull(), _))
+      .WillOnce(Invoke([&amp;intercepted_buzz](Buzz* buzz, Time timestamp) {
+        // Save buzz in intercepted_buzz for analysis later.
+        intercepted_buzz.reset(buzz);
+        return false;
+      }));
+
+  mock_buzzer_.ShareBuzz(std::make_unique<Buzz>(AccessLevel::kInternal),
+                         Now());
+  EXPECT_NE(nullptr, intercepted_buzz);
+```
+
+Using the tricks covered in this recipe, you are now able to mock methods that take and/or return move-only types.  Put your newly-acquired power to good use - when you design a new API, you can now feel comfortable using `unique_ptrs` as appropriate, without fearing that doing so will compromise your tests.
+
+## Making the Compilation Faster ##
+
+Believe it or not, the _vast majority_ of the time spent on compiling
+a mock class is in generating its constructor and destructor, as they
+perform non-trivial tasks (e.g. verification of the
+expectations). What's more, mock methods with different signatures
+have different types and thus their constructors/destructors need to
+be generated by the compiler separately. As a result, if you mock many
+different types of methods, compiling your mock class can get really
+slow.
+
+If you are experiencing slow compilation, you can move the definition
+of your mock class' constructor and destructor out of the class body
+and into a `.cpp` file. This way, even if you `#include` your mock
+class in N files, the compiler only needs to generate its constructor
+and destructor once, resulting in a much faster compilation.
+
+Let's illustrate the idea using an example. Here's the definition of a
+mock class before applying this recipe:
+
+```
+// File mock_foo.h.
+...
+class MockFoo : public Foo {
+ public:
+  // Since we don't declare the constructor or the destructor,
+  // the compiler will generate them in every translation unit
+  // where this mock class is used.
+
+  MOCK_METHOD0(DoThis, int());
+  MOCK_METHOD1(DoThat, bool(const char* str));
+  ... more mock methods ...
+};
+```
+
+After the change, it would look like:
+
+```
+// File mock_foo.h.
+...
+class MockFoo : public Foo {
+ public:
+  // The constructor and destructor are declared, but not defined, here.
+  MockFoo();
+  virtual ~MockFoo();
+
+  MOCK_METHOD0(DoThis, int());
+  MOCK_METHOD1(DoThat, bool(const char* str));
+  ... more mock methods ...
+};
+```
+and
+```
+// File mock_foo.cpp.
+#include "path/to/mock_foo.h"
+
+// The definitions may appear trivial, but the functions actually do a
+// lot of things through the constructors/destructors of the member
+// variables used to implement the mock methods.
+MockFoo::MockFoo() {}
+MockFoo::~MockFoo() {}
+```
+
+## Forcing a Verification ##
+
+When it's being destoyed, your friendly mock object will automatically
+verify that all expectations on it have been satisfied, and will
+generate [Google Test](http://code.google.com/p/googletest/) failures
+if not. This is convenient as it leaves you with one less thing to
+worry about. That is, unless you are not sure if your mock object will
+be destoyed.
+
+How could it be that your mock object won't eventually be destroyed?
+Well, it might be created on the heap and owned by the code you are
+testing. Suppose there's a bug in that code and it doesn't delete the
+mock object properly - you could end up with a passing test when
+there's actually a bug.
+
+Using a heap checker is a good idea and can alleviate the concern, but
+its implementation may not be 100% reliable. So, sometimes you do want
+to _force_ Google Mock to verify a mock object before it is
+(hopefully) destructed. You can do this with
+`Mock::VerifyAndClearExpectations(&mock_object)`:
+
+```
+TEST(MyServerTest, ProcessesRequest) {
+  using ::testing::Mock;
+
+  MockFoo* const foo = new MockFoo;
+  EXPECT_CALL(*foo, ...)...;
+  // ... other expectations ...
+
+  // server now owns foo.
+  MyServer server(foo);
+  server.ProcessRequest(...);
+
+  // In case that server's destructor will forget to delete foo,
+  // this will verify the expectations anyway.
+  Mock::VerifyAndClearExpectations(foo);
+}  // server is destroyed when it goes out of scope here.
+```
+
+**Tip:** The `Mock::VerifyAndClearExpectations()` function returns a
+`bool` to indicate whether the verification was successful (`true` for
+yes), so you can wrap that function call inside a `ASSERT_TRUE()` if
+there is no point going further when the verification has failed.
+
+## Using Check Points ##
+
+Sometimes you may want to "reset" a mock object at various check
+points in your test: at each check point, you verify that all existing
+expectations on the mock object have been satisfied, and then you set
+some new expectations on it as if it's newly created. This allows you
+to work with a mock object in "phases" whose sizes are each
+manageable.
+
+One such scenario is that in your test's `SetUp()` function, you may
+want to put the object you are testing into a certain state, with the
+help from a mock object. Once in the desired state, you want to clear
+all expectations on the mock, such that in the `TEST_F` body you can
+set fresh expectations on it.
+
+As you may have figured out, the `Mock::VerifyAndClearExpectations()`
+function we saw in the previous recipe can help you here. Or, if you
+are using `ON_CALL()` to set default actions on the mock object and
+want to clear the default actions as well, use
+`Mock::VerifyAndClear(&mock_object)` instead. This function does what
+`Mock::VerifyAndClearExpectations(&mock_object)` does and returns the
+same `bool`, **plus** it clears the `ON_CALL()` statements on
+`mock_object` too.
+
+Another trick you can use to achieve the same effect is to put the
+expectations in sequences and insert calls to a dummy "check-point"
+function at specific places. Then you can verify that the mock
+function calls do happen at the right time. For example, if you are
+exercising code:
+
+```
+Foo(1);
+Foo(2);
+Foo(3);
+```
+
+and want to verify that `Foo(1)` and `Foo(3)` both invoke
+`mock.Bar("a")`, but `Foo(2)` doesn't invoke anything. You can write:
+
+```
+using ::testing::MockFunction;
+
+TEST(FooTest, InvokesBarCorrectly) {
+  MyMock mock;
+  // Class MockFunction<F> has exactly one mock method.  It is named
+  // Call() and has type F.
+  MockFunction<void(string check_point_name)> check;
+  {
+    InSequence s;
+
+    EXPECT_CALL(mock, Bar("a"));
+    EXPECT_CALL(check, Call("1"));
+    EXPECT_CALL(check, Call("2"));
+    EXPECT_CALL(mock, Bar("a"));
+  }
+  Foo(1);
+  check.Call("1");
+  Foo(2);
+  check.Call("2");
+  Foo(3);
+}
+```
+
+The expectation spec says that the first `Bar("a")` must happen before
+check point "1", the second `Bar("a")` must happen after check point "2",
+and nothing should happen between the two check points. The explicit
+check points make it easy to tell which `Bar("a")` is called by which
+call to `Foo()`.
+
+## Mocking Destructors ##
+
+Sometimes you want to make sure a mock object is destructed at the
+right time, e.g. after `bar->A()` is called but before `bar->B()` is
+called. We already know that you can specify constraints on the order
+of mock function calls, so all we need to do is to mock the destructor
+of the mock function.
+
+This sounds simple, except for one problem: a destructor is a special
+function with special syntax and special semantics, and the
+`MOCK_METHOD0` macro doesn't work for it:
+
+```
+  MOCK_METHOD0(~MockFoo, void());  // Won't compile!
+```
+
+The good news is that you can use a simple pattern to achieve the same
+effect. First, add a mock function `Die()` to your mock class and call
+it in the destructor, like this:
+
+```
+class MockFoo : public Foo {
+  ...
+  // Add the following two lines to the mock class.
+  MOCK_METHOD0(Die, void());
+  virtual ~MockFoo() { Die(); }
+};
+```
+
+(If the name `Die()` clashes with an existing symbol, choose another
+name.) Now, we have translated the problem of testing when a `MockFoo`
+object dies to testing when its `Die()` method is called:
+
+```
+  MockFoo* foo = new MockFoo;
+  MockBar* bar = new MockBar;
+  ...
+  {
+    InSequence s;
+
+    // Expects *foo to die after bar->A() and before bar->B().
+    EXPECT_CALL(*bar, A());
+    EXPECT_CALL(*foo, Die());
+    EXPECT_CALL(*bar, B());
+  }
+```
+
+And that's that.
+
+## Using Google Mock and Threads ##
+
+**IMPORTANT NOTE:** What we describe in this recipe is **ONLY** true on
+platforms where Google Mock is thread-safe. Currently these are only
+platforms that support the pthreads library (this includes Linux and Mac).
+To make it thread-safe on other platforms we only need to implement
+some synchronization operations in `"gtest/internal/gtest-port.h"`.
+
+In a **unit** test, it's best if you could isolate and test a piece of
+code in a single-threaded context. That avoids race conditions and
+dead locks, and makes debugging your test much easier.
+
+Yet many programs are multi-threaded, and sometimes to test something
+we need to pound on it from more than one thread. Google Mock works
+for this purpose too.
+
+Remember the steps for using a mock:
+
+  1. Create a mock object `foo`.
+  1. Set its default actions and expectations using `ON_CALL()` and `EXPECT_CALL()`.
+  1. The code under test calls methods of `foo`.
+  1. Optionally, verify and reset the mock.
+  1. Destroy the mock yourself, or let the code under test destroy it. The destructor will automatically verify it.
+
+If you follow the following simple rules, your mocks and threads can
+live happily together:
+
+  * Execute your _test code_ (as opposed to the code being tested) in _one_ thread. This makes your test easy to follow.
+  * Obviously, you can do step #1 without locking.
+  * When doing step #2 and #5, make sure no other thread is accessing `foo`. Obvious too, huh?
+  * #3 and #4 can be done either in one thread or in multiple threads - anyway you want. Google Mock takes care of the locking, so you don't have to do any - unless required by your test logic.
+
+If you violate the rules (for example, if you set expectations on a
+mock while another thread is calling its methods), you get undefined
+behavior. That's not fun, so don't do it.
+
+Google Mock guarantees that the action for a mock function is done in
+the same thread that called the mock function. For example, in
+
+```
+  EXPECT_CALL(mock, Foo(1))
+      .WillOnce(action1);
+  EXPECT_CALL(mock, Foo(2))
+      .WillOnce(action2);
+```
+
+if `Foo(1)` is called in thread 1 and `Foo(2)` is called in thread 2,
+Google Mock will execute `action1` in thread 1 and `action2` in thread
+2.
+
+Google Mock does _not_ impose a sequence on actions performed in
+different threads (doing so may create deadlocks as the actions may
+need to cooperate). This means that the execution of `action1` and
+`action2` in the above example _may_ interleave. If this is a problem,
+you should add proper synchronization logic to `action1` and `action2`
+to make the test thread-safe.
+
+
+Also, remember that `DefaultValue<T>` is a global resource that
+potentially affects _all_ living mock objects in your
+program. Naturally, you won't want to mess with it from multiple
+threads or when there still are mocks in action.
+
+## Controlling How Much Information Google Mock Prints ##
+
+When Google Mock sees something that has the potential of being an
+error (e.g. a mock function with no expectation is called, a.k.a. an
+uninteresting call, which is allowed but perhaps you forgot to
+explicitly ban the call), it prints some warning messages, including
+the arguments of the function and the return value. Hopefully this
+will remind you to take a look and see if there is indeed a problem.
+
+Sometimes you are confident that your tests are correct and may not
+appreciate such friendly messages. Some other times, you are debugging
+your tests or learning about the behavior of the code you are testing,
+and wish you could observe every mock call that happens (including
+argument values and the return value). Clearly, one size doesn't fit
+all.
+
+You can control how much Google Mock tells you using the
+`--gmock_verbose=LEVEL` command-line flag, where `LEVEL` is a string
+with three possible values:
+
+  * `info`: Google Mock will print all informational messages, warnings, and errors (most verbose). At this setting, Google Mock will also log any calls to the `ON_CALL/EXPECT_CALL` macros.
+  * `warning`: Google Mock will print both warnings and errors (less verbose). This is the default.
+  * `error`: Google Mock will print errors only (least verbose).
+
+Alternatively, you can adjust the value of that flag from within your
+tests like so:
+
+```
+  ::testing::FLAGS_gmock_verbose = "error";
+```
+
+Now, judiciously use the right flag to enable Google Mock serve you better!
+
+## Gaining Super Vision into Mock Calls ##
+
+You have a test using Google Mock. It fails: Google Mock tells you
+that some expectations aren't satisfied. However, you aren't sure why:
+Is there a typo somewhere in the matchers? Did you mess up the order
+of the `EXPECT_CALL`s? Or is the code under test doing something
+wrong?  How can you find out the cause?
+
+Won't it be nice if you have X-ray vision and can actually see the
+trace of all `EXPECT_CALL`s and mock method calls as they are made?
+For each call, would you like to see its actual argument values and
+which `EXPECT_CALL` Google Mock thinks it matches?
+
+You can unlock this power by running your test with the
+`--gmock_verbose=info` flag. For example, given the test program:
+
+```
+using testing::_;
+using testing::HasSubstr;
+using testing::Return;
+
+class MockFoo {
+ public:
+  MOCK_METHOD2(F, void(const string& x, const string& y));
+};
+
+TEST(Foo, Bar) {
+  MockFoo mock;
+  EXPECT_CALL(mock, F(_, _)).WillRepeatedly(Return());
+  EXPECT_CALL(mock, F("a", "b"));
+  EXPECT_CALL(mock, F("c", HasSubstr("d")));
+
+  mock.F("a", "good");
+  mock.F("a", "b");
+}
+```
+
+if you run it with `--gmock_verbose=info`, you will see this output:
+
+```
+[ RUN      ] Foo.Bar
+
+foo_test.cc:14: EXPECT_CALL(mock, F(_, _)) invoked
+foo_test.cc:15: EXPECT_CALL(mock, F("a", "b")) invoked
+foo_test.cc:16: EXPECT_CALL(mock, F("c", HasSubstr("d"))) invoked
+foo_test.cc:14: Mock function call matches EXPECT_CALL(mock, F(_, _))...
+    Function call: F(@0x7fff7c8dad40"a", @0x7fff7c8dad10"good")
+foo_test.cc:15: Mock function call matches EXPECT_CALL(mock, F("a", "b"))...
+    Function call: F(@0x7fff7c8dada0"a", @0x7fff7c8dad70"b")
+foo_test.cc:16: Failure
+Actual function call count doesn't match EXPECT_CALL(mock, F("c", HasSubstr("d")))...
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+[  FAILED  ] Foo.Bar
+```
+
+Suppose the bug is that the `"c"` in the third `EXPECT_CALL` is a typo
+and should actually be `"a"`. With the above message, you should see
+that the actual `F("a", "good")` call is matched by the first
+`EXPECT_CALL`, not the third as you thought. From that it should be
+obvious that the third `EXPECT_CALL` is written wrong. Case solved.
+
+## Running Tests in Emacs ##
+
+If you build and run your tests in Emacs, the source file locations of
+Google Mock and [Google Test](http://code.google.com/p/googletest/)
+errors will be highlighted. Just press `<Enter>` on one of them and
+you'll be taken to the offending line. Or, you can just type `C-x ``
+to jump to the next error.
+
+To make it even easier, you can add the following lines to your
+`~/.emacs` file:
+
+```
+(global-set-key "\M-m"   'compile)  ; m is for make
+(global-set-key [M-down] 'next-error)
+(global-set-key [M-up]   '(lambda () (interactive) (next-error -1)))
+```
+
+Then you can type `M-m` to start a build, or `M-up`/`M-down` to move
+back and forth between errors.
+
+## Fusing Google Mock Source Files ##
+
+Google Mock's implementation consists of dozens of files (excluding
+its own tests).  Sometimes you may want them to be packaged up in
+fewer files instead, such that you can easily copy them to a new
+machine and start hacking there.  For this we provide an experimental
+Python script `fuse_gmock_files.py` in the `scripts/` directory
+(starting with release 1.2.0).  Assuming you have Python 2.4 or above
+installed on your machine, just go to that directory and run
+```
+python fuse_gmock_files.py OUTPUT_DIR
+```
+
+and you should see an `OUTPUT_DIR` directory being created with files
+`gtest/gtest.h`, `gmock/gmock.h`, and `gmock-gtest-all.cc` in it.
+These three files contain everything you need to use Google Mock (and
+Google Test).  Just copy them to anywhere you want and you are ready
+to write tests and use mocks.  You can use the
+[scrpts/test/Makefile](http://code.google.com/p/googlemock/source/browse/trunk/scripts/test/Makefile) file as an example on how to compile your tests
+against them.
+
+# Extending Google Mock #
+
+## Writing New Matchers Quickly ##
+
+The `MATCHER*` family of macros can be used to define custom matchers
+easily.  The syntax:
+
+```
+MATCHER(name, description_string_expression) { statements; }
+```
+
+will define a matcher with the given name that executes the
+statements, which must return a `bool` to indicate if the match
+succeeds.  Inside the statements, you can refer to the value being
+matched by `arg`, and refer to its type by `arg_type`.
+
+The description string is a `string`-typed expression that documents
+what the matcher does, and is used to generate the failure message
+when the match fails.  It can (and should) reference the special
+`bool` variable `negation`, and should evaluate to the description of
+the matcher when `negation` is `false`, or that of the matcher's
+negation when `negation` is `true`.
+
+For convenience, we allow the description string to be empty (`""`),
+in which case Google Mock will use the sequence of words in the
+matcher name as the description.
+
+For example:
+```
+MATCHER(IsDivisibleBy7, "") { return (arg % 7) == 0; }
+```
+allows you to write
+```
+  // Expects mock_foo.Bar(n) to be called where n is divisible by 7.
+  EXPECT_CALL(mock_foo, Bar(IsDivisibleBy7()));
+```
+or,
+```
+using ::testing::Not;
+...
+  EXPECT_THAT(some_expression, IsDivisibleBy7());
+  EXPECT_THAT(some_other_expression, Not(IsDivisibleBy7()));
+```
+If the above assertions fail, they will print something like:
+```
+  Value of: some_expression
+  Expected: is divisible by 7
+    Actual: 27
+...
+  Value of: some_other_expression
+  Expected: not (is divisible by 7)
+    Actual: 21
+```
+where the descriptions `"is divisible by 7"` and `"not (is divisible
+by 7)"` are automatically calculated from the matcher name
+`IsDivisibleBy7`.
+
+As you may have noticed, the auto-generated descriptions (especially
+those for the negation) may not be so great. You can always override
+them with a string expression of your own:
+```
+MATCHER(IsDivisibleBy7, std::string(negation ? "isn't" : "is") +
+                        " divisible by 7") {
+  return (arg % 7) == 0;
+}
+```
+
+Optionally, you can stream additional information to a hidden argument
+named `result_listener` to explain the match result. For example, a
+better definition of `IsDivisibleBy7` is:
+```
+MATCHER(IsDivisibleBy7, "") {
+  if ((arg % 7) == 0)
+    return true;
+
+  *result_listener << "the remainder is " << (arg % 7);
+  return false;
+}
+```
+
+With this definition, the above assertion will give a better message:
+```
+  Value of: some_expression
+  Expected: is divisible by 7
+    Actual: 27 (the remainder is 6)
+```
+
+You should let `MatchAndExplain()` print _any additional information_
+that can help a user understand the match result. Note that it should
+explain why the match succeeds in case of a success (unless it's
+obvious) - this is useful when the matcher is used inside
+`Not()`. There is no need to print the argument value itself, as
+Google Mock already prints it for you.
+
+**Notes:**
+
+  1. The type of the value being matched (`arg_type`) is determined by the context in which you use the matcher and is supplied to you by the compiler, so you don't need to worry about declaring it (nor can you).  This allows the matcher to be polymorphic.  For example, `IsDivisibleBy7()` can be used to match any type where the value of `(arg % 7) == 0` can be implicitly converted to a `bool`.  In the `Bar(IsDivisibleBy7())` example above, if method `Bar()` takes an `int`, `arg_type` will be `int`; if it takes an `unsigned long`, `arg_type` will be `unsigned long`; and so on.
+  1. Google Mock doesn't guarantee when or how many times a matcher will be invoked. Therefore the matcher logic must be _purely functional_ (i.e. it cannot have any side effect, and the result must not depend on anything other than the value being matched and the matcher parameters). This requirement must be satisfied no matter how you define the matcher (e.g. using one of the methods described in the following recipes). In particular, a matcher can never call a mock function, as that will affect the state of the mock object and Google Mock.
+
+## Writing New Parameterized Matchers Quickly ##
+
+Sometimes you'll want to define a matcher that has parameters.  For that you
+can use the macro:
+```
+MATCHER_P(name, param_name, description_string) { statements; }
+```
+where the description string can be either `""` or a string expression
+that references `negation` and `param_name`.
+
+For example:
+```
+MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; }
+```
+will allow you to write:
+```
+  EXPECT_THAT(Blah("a"), HasAbsoluteValue(n));
+```
+which may lead to this message (assuming `n` is 10):
+```
+  Value of: Blah("a")
+  Expected: has absolute value 10
+    Actual: -9
+```
+
+Note that both the matcher description and its parameter are
+printed, making the message human-friendly.
+
+In the matcher definition body, you can write `foo_type` to
+reference the type of a parameter named `foo`.  For example, in the
+body of `MATCHER_P(HasAbsoluteValue, value)` above, you can write
+`value_type` to refer to the type of `value`.
+
+Google Mock also provides `MATCHER_P2`, `MATCHER_P3`, ..., up to
+`MATCHER_P10` to support multi-parameter matchers:
+```
+MATCHER_Pk(name, param_1, ..., param_k, description_string) { statements; }
+```
+
+Please note that the custom description string is for a particular
+**instance** of the matcher, where the parameters have been bound to
+actual values.  Therefore usually you'll want the parameter values to
+be part of the description.  Google Mock lets you do that by
+referencing the matcher parameters in the description string
+expression.
+
+For example,
+```
+  using ::testing::PrintToString;
+  MATCHER_P2(InClosedRange, low, hi,
+             std::string(negation ? "isn't" : "is") + " in range [" +
+             PrintToString(low) + ", " + PrintToString(hi) + "]") {
+    return low <= arg && arg <= hi;
+  }
+  ...
+  EXPECT_THAT(3, InClosedRange(4, 6));
+```
+would generate a failure that contains the message:
+```
+  Expected: is in range [4, 6]
+```
+
+If you specify `""` as the description, the failure message will
+contain the sequence of words in the matcher name followed by the
+parameter values printed as a tuple.  For example,
+```
+  MATCHER_P2(InClosedRange, low, hi, "") { ... }
+  ...
+  EXPECT_THAT(3, InClosedRange(4, 6));
+```
+would generate a failure that contains the text:
+```
+  Expected: in closed range (4, 6)
+```
+
+For the purpose of typing, you can view
+```
+MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... }
+```
+as shorthand for
+```
+template <typename p1_type, ..., typename pk_type>
+FooMatcherPk<p1_type, ..., pk_type>
+Foo(p1_type p1, ..., pk_type pk) { ... }
+```
+
+When you write `Foo(v1, ..., vk)`, the compiler infers the types of
+the parameters `v1`, ..., and `vk` for you.  If you are not happy with
+the result of the type inference, you can specify the types by
+explicitly instantiating the template, as in `Foo<long, bool>(5, false)`.
+As said earlier, you don't get to (or need to) specify
+`arg_type` as that's determined by the context in which the matcher
+is used.
+
+You can assign the result of expression `Foo(p1, ..., pk)` to a
+variable of type `FooMatcherPk<p1_type, ..., pk_type>`.  This can be
+useful when composing matchers.  Matchers that don't have a parameter
+or have only one parameter have special types: you can assign `Foo()`
+to a `FooMatcher`-typed variable, and assign `Foo(p)` to a
+`FooMatcherP<p_type>`-typed variable.
+
+While you can instantiate a matcher template with reference types,
+passing the parameters by pointer usually makes your code more
+readable.  If, however, you still want to pass a parameter by
+reference, be aware that in the failure message generated by the
+matcher you will see the value of the referenced object but not its
+address.
+
+You can overload matchers with different numbers of parameters:
+```
+MATCHER_P(Blah, a, description_string_1) { ... }
+MATCHER_P2(Blah, a, b, description_string_2) { ... }
+```
+
+While it's tempting to always use the `MATCHER*` macros when defining
+a new matcher, you should also consider implementing
+`MatcherInterface` or using `MakePolymorphicMatcher()` instead (see
+the recipes that follow), especially if you need to use the matcher a
+lot.  While these approaches require more work, they give you more
+control on the types of the value being matched and the matcher
+parameters, which in general leads to better compiler error messages
+that pay off in the long run.  They also allow overloading matchers
+based on parameter types (as opposed to just based on the number of
+parameters).
+
+## Writing New Monomorphic Matchers ##
+
+A matcher of argument type `T` implements
+`::testing::MatcherInterface<T>` and does two things: it tests whether a
+value of type `T` matches the matcher, and can describe what kind of
+values it matches. The latter ability is used for generating readable
+error messages when expectations are violated.
+
+The interface looks like this:
+
+```
+class MatchResultListener {
+ public:
+  ...
+  // Streams x to the underlying ostream; does nothing if the ostream
+  // is NULL.
+  template <typename T>
+  MatchResultListener& operator<<(const T& x);
+
+  // Returns the underlying ostream.
+  ::std::ostream* stream();
+};
+
+template <typename T>
+class MatcherInterface {
+ public:
+  virtual ~MatcherInterface();
+
+  // Returns true iff the matcher matches x; also explains the match
+  // result to 'listener'.
+  virtual bool MatchAndExplain(T x, MatchResultListener* listener) const = 0;
+
+  // Describes this matcher to an ostream.
+  virtual void DescribeTo(::std::ostream* os) const = 0;
+
+  // Describes the negation of this matcher to an ostream.
+  virtual void DescribeNegationTo(::std::ostream* os) const;
+};
+```
+
+If you need a custom matcher but `Truly()` is not a good option (for
+example, you may not be happy with the way `Truly(predicate)`
+describes itself, or you may want your matcher to be polymorphic as
+`Eq(value)` is), you can define a matcher to do whatever you want in
+two steps: first implement the matcher interface, and then define a
+factory function to create a matcher instance. The second step is not
+strictly needed but it makes the syntax of using the matcher nicer.
+
+For example, you can define a matcher to test whether an `int` is
+divisible by 7 and then use it like this:
+```
+using ::testing::MakeMatcher;
+using ::testing::Matcher;
+using ::testing::MatcherInterface;
+using ::testing::MatchResultListener;
+
+class DivisibleBy7Matcher : public MatcherInterface<int> {
+ public:
+  virtual bool MatchAndExplain(int n, MatchResultListener* listener) const {
+    return (n % 7) == 0;
+  }
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "is divisible by 7";
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "is not divisible by 7";
+  }
+};
+
+inline Matcher<int> DivisibleBy7() {
+  return MakeMatcher(new DivisibleBy7Matcher);
+}
+...
+
+  EXPECT_CALL(foo, Bar(DivisibleBy7()));
+```
+
+You may improve the matcher message by streaming additional
+information to the `listener` argument in `MatchAndExplain()`:
+
+```
+class DivisibleBy7Matcher : public MatcherInterface<int> {
+ public:
+  virtual bool MatchAndExplain(int n,
+                               MatchResultListener* listener) const {
+    const int remainder = n % 7;
+    if (remainder != 0) {
+      *listener << "the remainder is " << remainder;
+    }
+    return remainder == 0;
+  }
+  ...
+};
+```
+
+Then, `EXPECT_THAT(x, DivisibleBy7());` may general a message like this:
+```
+Value of: x
+Expected: is divisible by 7
+  Actual: 23 (the remainder is 2)
+```
+
+## Writing New Polymorphic Matchers ##
+
+You've learned how to write your own matchers in the previous
+recipe. Just one problem: a matcher created using `MakeMatcher()` only
+works for one particular type of arguments. If you want a
+_polymorphic_ matcher that works with arguments of several types (for
+instance, `Eq(x)` can be used to match a `value` as long as `value` ==
+`x` compiles -- `value` and `x` don't have to share the same type),
+you can learn the trick from `"gmock/gmock-matchers.h"` but it's a bit
+involved.
+
+Fortunately, most of the time you can define a polymorphic matcher
+easily with the help of `MakePolymorphicMatcher()`. Here's how you can
+define `NotNull()` as an example:
+
+```
+using ::testing::MakePolymorphicMatcher;
+using ::testing::MatchResultListener;
+using ::testing::NotNull;
+using ::testing::PolymorphicMatcher;
+
+class NotNullMatcher {
+ public:
+  // To implement a polymorphic matcher, first define a COPYABLE class
+  // that has three members MatchAndExplain(), DescribeTo(), and
+  // DescribeNegationTo(), like the following.
+
+  // In this example, we want to use NotNull() with any pointer, so
+  // MatchAndExplain() accepts a pointer of any type as its first argument.
+  // In general, you can define MatchAndExplain() as an ordinary method or
+  // a method template, or even overload it.
+  template <typename T>
+  bool MatchAndExplain(T* p,
+                       MatchResultListener* /* listener */) const {
+    return p != NULL;
+  }
+
+  // Describes the property of a value matching this matcher.
+  void DescribeTo(::std::ostream* os) const { *os << "is not NULL"; }
+
+  // Describes the property of a value NOT matching this matcher.
+  void DescribeNegationTo(::std::ostream* os) const { *os << "is NULL"; }
+};
+
+// To construct a polymorphic matcher, pass an instance of the class
+// to MakePolymorphicMatcher().  Note the return type.
+inline PolymorphicMatcher<NotNullMatcher> NotNull() {
+  return MakePolymorphicMatcher(NotNullMatcher());
+}
+...
+
+  EXPECT_CALL(foo, Bar(NotNull()));  // The argument must be a non-NULL pointer.
+```
+
+**Note:** Your polymorphic matcher class does **not** need to inherit from
+`MatcherInterface` or any other class, and its methods do **not** need
+to be virtual.
+
+Like in a monomorphic matcher, you may explain the match result by
+streaming additional information to the `listener` argument in
+`MatchAndExplain()`.
+
+## Writing New Cardinalities ##
+
+A cardinality is used in `Times()` to tell Google Mock how many times
+you expect a call to occur. It doesn't have to be exact. For example,
+you can say `AtLeast(5)` or `Between(2, 4)`.
+
+If the built-in set of cardinalities doesn't suit you, you are free to
+define your own by implementing the following interface (in namespace
+`testing`):
+
+```
+class CardinalityInterface {
+ public:
+  virtual ~CardinalityInterface();
+
+  // Returns true iff call_count calls will satisfy this cardinality.
+  virtual bool IsSatisfiedByCallCount(int call_count) const = 0;
+
+  // Returns true iff call_count calls will saturate this cardinality.
+  virtual bool IsSaturatedByCallCount(int call_count) const = 0;
+
+  // Describes self to an ostream.
+  virtual void DescribeTo(::std::ostream* os) const = 0;
+};
+```
+
+For example, to specify that a call must occur even number of times,
+you can write
+
+```
+using ::testing::Cardinality;
+using ::testing::CardinalityInterface;
+using ::testing::MakeCardinality;
+
+class EvenNumberCardinality : public CardinalityInterface {
+ public:
+  virtual bool IsSatisfiedByCallCount(int call_count) const {
+    return (call_count % 2) == 0;
+  }
+
+  virtual bool IsSaturatedByCallCount(int call_count) const {
+    return false;
+  }
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "called even number of times";
+  }
+};
+
+Cardinality EvenNumber() {
+  return MakeCardinality(new EvenNumberCardinality);
+}
+...
+
+  EXPECT_CALL(foo, Bar(3))
+      .Times(EvenNumber());
+```
+
+## Writing New Actions Quickly ##
+
+If the built-in actions don't work for you, and you find it
+inconvenient to use `Invoke()`, you can use a macro from the `ACTION*`
+family to quickly define a new action that can be used in your code as
+if it's a built-in action.
+
+By writing
+```
+ACTION(name) { statements; }
+```
+in a namespace scope (i.e. not inside a class or function), you will
+define an action with the given name that executes the statements.
+The value returned by `statements` will be used as the return value of
+the action.  Inside the statements, you can refer to the K-th
+(0-based) argument of the mock function as `argK`.  For example:
+```
+ACTION(IncrementArg1) { return ++(*arg1); }
+```
+allows you to write
+```
+... WillOnce(IncrementArg1());
+```
+
+Note that you don't need to specify the types of the mock function
+arguments.  Rest assured that your code is type-safe though:
+you'll get a compiler error if `*arg1` doesn't support the `++`
+operator, or if the type of `++(*arg1)` isn't compatible with the mock
+function's return type.
+
+Another example:
+```
+ACTION(Foo) {
+  (*arg2)(5);
+  Blah();
+  *arg1 = 0;
+  return arg0;
+}
+```
+defines an action `Foo()` that invokes argument #2 (a function pointer)
+with 5, calls function `Blah()`, sets the value pointed to by argument
+#1 to 0, and returns argument #0.
+
+For more convenience and flexibility, you can also use the following
+pre-defined symbols in the body of `ACTION`:
+
+| `argK_type` | The type of the K-th (0-based) argument of the mock function |
+|:------------|:-------------------------------------------------------------|
+| `args`      | All arguments of the mock function as a tuple                |
+| `args_type` | The type of all arguments of the mock function as a tuple    |
+| `return_type` | The return type of the mock function                         |
+| `function_type` | The type of the mock function                                |
+
+For example, when using an `ACTION` as a stub action for mock function:
+```
+int DoSomething(bool flag, int* ptr);
+```
+we have:
+| **Pre-defined Symbol** | **Is Bound To** |
+|:-----------------------|:----------------|
+| `arg0`                 | the value of `flag` |
+| `arg0_type`            | the type `bool` |
+| `arg1`                 | the value of `ptr` |
+| `arg1_type`            | the type `int*` |
+| `args`                 | the tuple `(flag, ptr)` |
+| `args_type`            | the type `::testing::tuple<bool, int*>` |
+| `return_type`          | the type `int`  |
+| `function_type`        | the type `int(bool, int*)` |
+
+## Writing New Parameterized Actions Quickly ##
+
+Sometimes you'll want to parameterize an action you define.  For that
+we have another macro
+```
+ACTION_P(name, param) { statements; }
+```
+
+For example,
+```
+ACTION_P(Add, n) { return arg0 + n; }
+```
+will allow you to write
+```
+// Returns argument #0 + 5.
+... WillOnce(Add(5));
+```
+
+For convenience, we use the term _arguments_ for the values used to
+invoke the mock function, and the term _parameters_ for the values
+used to instantiate an action.
+
+Note that you don't need to provide the type of the parameter either.
+Suppose the parameter is named `param`, you can also use the
+Google-Mock-defined symbol `param_type` to refer to the type of the
+parameter as inferred by the compiler.  For example, in the body of
+`ACTION_P(Add, n)` above, you can write `n_type` for the type of `n`.
+
+Google Mock also provides `ACTION_P2`, `ACTION_P3`, and etc to support
+multi-parameter actions.  For example,
+```
+ACTION_P2(ReturnDistanceTo, x, y) {
+  double dx = arg0 - x;
+  double dy = arg1 - y;
+  return sqrt(dx*dx + dy*dy);
+}
+```
+lets you write
+```
+... WillOnce(ReturnDistanceTo(5.0, 26.5));
+```
+
+You can view `ACTION` as a degenerated parameterized action where the
+number of parameters is 0.
+
+You can also easily define actions overloaded on the number of parameters:
+```
+ACTION_P(Plus, a) { ... }
+ACTION_P2(Plus, a, b) { ... }
+```
+
+## Restricting the Type of an Argument or Parameter in an ACTION ##
+
+For maximum brevity and reusability, the `ACTION*` macros don't ask
+you to provide the types of the mock function arguments and the action
+parameters.  Instead, we let the compiler infer the types for us.
+
+Sometimes, however, we may want to be more explicit about the types.
+There are several tricks to do that.  For example:
+```
+ACTION(Foo) {
+  // Makes sure arg0 can be converted to int.
+  int n = arg0;
+  ... use n instead of arg0 here ...
+}
+
+ACTION_P(Bar, param) {
+  // Makes sure the type of arg1 is const char*.
+  ::testing::StaticAssertTypeEq<const char*, arg1_type>();
+
+  // Makes sure param can be converted to bool.
+  bool flag = param;
+}
+```
+where `StaticAssertTypeEq` is a compile-time assertion in Google Test
+that verifies two types are the same.
+
+## Writing New Action Templates Quickly ##
+
+Sometimes you want to give an action explicit template parameters that
+cannot be inferred from its value parameters.  `ACTION_TEMPLATE()`
+supports that and can be viewed as an extension to `ACTION()` and
+`ACTION_P*()`.
+
+The syntax:
+```
+ACTION_TEMPLATE(ActionName,
+                HAS_m_TEMPLATE_PARAMS(kind1, name1, ..., kind_m, name_m),
+                AND_n_VALUE_PARAMS(p1, ..., p_n)) { statements; }
+```
+
+defines an action template that takes _m_ explicit template parameters
+and _n_ value parameters, where _m_ is between 1 and 10, and _n_ is
+between 0 and 10.  `name_i` is the name of the i-th template
+parameter, and `kind_i` specifies whether it's a `typename`, an
+integral constant, or a template.  `p_i` is the name of the i-th value
+parameter.
+
+Example:
+```
+// DuplicateArg<k, T>(output) converts the k-th argument of the mock
+// function to type T and copies it to *output.
+ACTION_TEMPLATE(DuplicateArg,
+                // Note the comma between int and k:
+                HAS_2_TEMPLATE_PARAMS(int, k, typename, T),
+                AND_1_VALUE_PARAMS(output)) {
+  *output = T(::testing::get<k>(args));
+}
+```
+
+To create an instance of an action template, write:
+```
+  ActionName<t1, ..., t_m>(v1, ..., v_n)
+```
+where the `t`s are the template arguments and the
+`v`s are the value arguments.  The value argument
+types are inferred by the compiler.  For example:
+```
+using ::testing::_;
+...
+  int n;
+  EXPECT_CALL(mock, Foo(_, _))
+      .WillOnce(DuplicateArg<1, unsigned char>(&n));
+```
+
+If you want to explicitly specify the value argument types, you can
+provide additional template arguments:
+```
+  ActionName<t1, ..., t_m, u1, ..., u_k>(v1, ..., v_n)
+```
+where `u_i` is the desired type of `v_i`.
+
+`ACTION_TEMPLATE` and `ACTION`/`ACTION_P*` can be overloaded on the
+number of value parameters, but not on the number of template
+parameters.  Without the restriction, the meaning of the following is
+unclear:
+
+```
+  OverloadedAction<int, bool>(x);
+```
+
+Are we using a single-template-parameter action where `bool` refers to
+the type of `x`, or a two-template-parameter action where the compiler
+is asked to infer the type of `x`?
+
+## Using the ACTION Object's Type ##
+
+If you are writing a function that returns an `ACTION` object, you'll
+need to know its type.  The type depends on the macro used to define
+the action and the parameter types.  The rule is relatively simple:
+| **Given Definition** | **Expression** | **Has Type** |
+|:---------------------|:---------------|:-------------|
+| `ACTION(Foo)`        | `Foo()`        | `FooAction`  |
+| `ACTION_TEMPLATE(Foo, HAS_m_TEMPLATE_PARAMS(...), AND_0_VALUE_PARAMS())` |	`Foo<t1, ..., t_m>()` | `FooAction<t1, ..., t_m>` |
+| `ACTION_P(Bar, param)` | `Bar(int_value)` | `BarActionP<int>` |
+| `ACTION_TEMPLATE(Bar, HAS_m_TEMPLATE_PARAMS(...), AND_1_VALUE_PARAMS(p1))` | `Bar<t1, ..., t_m>(int_value)` | `FooActionP<t1, ..., t_m, int>` |
+| `ACTION_P2(Baz, p1, p2)` | `Baz(bool_value, int_value)` | `BazActionP2<bool, int>` |
+| `ACTION_TEMPLATE(Baz, HAS_m_TEMPLATE_PARAMS(...), AND_2_VALUE_PARAMS(p1, p2))` | `Baz<t1, ..., t_m>(bool_value, int_value)` | `FooActionP2<t1, ..., t_m, bool, int>` |
+| ...                  | ...            | ...          |
+
+Note that we have to pick different suffixes (`Action`, `ActionP`,
+`ActionP2`, and etc) for actions with different numbers of value
+parameters, or the action definitions cannot be overloaded on the
+number of them.
+
+## Writing New Monomorphic Actions ##
+
+While the `ACTION*` macros are very convenient, sometimes they are
+inappropriate.  For example, despite the tricks shown in the previous
+recipes, they don't let you directly specify the types of the mock
+function arguments and the action parameters, which in general leads
+to unoptimized compiler error messages that can baffle unfamiliar
+users.  They also don't allow overloading actions based on parameter
+types without jumping through some hoops.
+
+An alternative to the `ACTION*` macros is to implement
+`::testing::ActionInterface<F>`, where `F` is the type of the mock
+function in which the action will be used. For example:
+
+```
+template <typename F>class ActionInterface {
+ public:
+  virtual ~ActionInterface();
+
+  // Performs the action.  Result is the return type of function type
+  // F, and ArgumentTuple is the tuple of arguments of F.
+  //
+  // For example, if F is int(bool, const string&), then Result would
+  // be int, and ArgumentTuple would be ::testing::tuple<bool, const string&>.
+  virtual Result Perform(const ArgumentTuple& args) = 0;
+};
+
+using ::testing::_;
+using ::testing::Action;
+using ::testing::ActionInterface;
+using ::testing::MakeAction;
+
+typedef int IncrementMethod(int*);
+
+class IncrementArgumentAction : public ActionInterface<IncrementMethod> {
+ public:
+  virtual int Perform(const ::testing::tuple<int*>& args) {
+    int* p = ::testing::get<0>(args);  // Grabs the first argument.
+    return *p++;
+  }
+};
+
+Action<IncrementMethod> IncrementArgument() {
+  return MakeAction(new IncrementArgumentAction);
+}
+...
+
+  EXPECT_CALL(foo, Baz(_))
+      .WillOnce(IncrementArgument());
+
+  int n = 5;
+  foo.Baz(&n);  // Should return 5 and change n to 6.
+```
+
+## Writing New Polymorphic Actions ##
+
+The previous recipe showed you how to define your own action. This is
+all good, except that you need to know the type of the function in
+which the action will be used. Sometimes that can be a problem. For
+example, if you want to use the action in functions with _different_
+types (e.g. like `Return()` and `SetArgPointee()`).
+
+If an action can be used in several types of mock functions, we say
+it's _polymorphic_. The `MakePolymorphicAction()` function template
+makes it easy to define such an action:
+
+```
+namespace testing {
+
+template <typename Impl>
+PolymorphicAction<Impl> MakePolymorphicAction(const Impl& impl);
+
+}  // namespace testing
+```
+
+As an example, let's define an action that returns the second argument
+in the mock function's argument list. The first step is to define an
+implementation class:
+
+```
+class ReturnSecondArgumentAction {
+ public:
+  template <typename Result, typename ArgumentTuple>
+  Result Perform(const ArgumentTuple& args) const {
+    // To get the i-th (0-based) argument, use ::testing::get<i>(args).
+    return ::testing::get<1>(args);
+  }
+};
+```
+
+This implementation class does _not_ need to inherit from any
+particular class. What matters is that it must have a `Perform()`
+method template. This method template takes the mock function's
+arguments as a tuple in a **single** argument, and returns the result of
+the action. It can be either `const` or not, but must be invokable
+with exactly one template argument, which is the result type. In other
+words, you must be able to call `Perform<R>(args)` where `R` is the
+mock function's return type and `args` is its arguments in a tuple.
+
+Next, we use `MakePolymorphicAction()` to turn an instance of the
+implementation class into the polymorphic action we need. It will be
+convenient to have a wrapper for this:
+
+```
+using ::testing::MakePolymorphicAction;
+using ::testing::PolymorphicAction;
+
+PolymorphicAction<ReturnSecondArgumentAction> ReturnSecondArgument() {
+  return MakePolymorphicAction(ReturnSecondArgumentAction());
+}
+```
+
+Now, you can use this polymorphic action the same way you use the
+built-in ones:
+
+```
+using ::testing::_;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD2(DoThis, int(bool flag, int n));
+  MOCK_METHOD3(DoThat, string(int x, const char* str1, const char* str2));
+};
+...
+
+  MockFoo foo;
+  EXPECT_CALL(foo, DoThis(_, _))
+      .WillOnce(ReturnSecondArgument());
+  EXPECT_CALL(foo, DoThat(_, _, _))
+      .WillOnce(ReturnSecondArgument());
+  ...
+  foo.DoThis(true, 5);         // Will return 5.
+  foo.DoThat(1, "Hi", "Bye");  // Will return "Hi".
+```
+
+## Teaching Google Mock How to Print Your Values ##
+
+When an uninteresting or unexpected call occurs, Google Mock prints the
+argument values and the stack trace to help you debug.  Assertion
+macros like `EXPECT_THAT` and `EXPECT_EQ` also print the values in
+question when the assertion fails.  Google Mock and Google Test do this using
+Google Test's user-extensible value printer.
+
+This printer knows how to print built-in C++ types, native arrays, STL
+containers, and any type that supports the `<<` operator.  For other
+types, it prints the raw bytes in the value and hopes that you the
+user can figure it out.
+[Google Test's advanced guide](http://code.google.com/p/googletest/wiki/AdvancedGuide#Teaching_Google_Test_How_to_Print_Your_Values)
+explains how to extend the printer to do a better job at
+printing your particular type than to dump the bytes.
\ No newline at end of file
diff --git a/third_party/googletest/googlemock/docs/DesignDoc.md b/third_party/googletest/googlemock/docs/DesignDoc.md
new file mode 100644
index 0000000..3f515c3
--- /dev/null
+++ b/third_party/googletest/googlemock/docs/DesignDoc.md
@@ -0,0 +1,280 @@
+This page discusses the design of new Google Mock features.
+
+
+
+# Macros for Defining Actions #
+
+## Problem ##
+
+Due to the lack of closures in C++, it currently requires some
+non-trivial effort to define a custom action in Google Mock.  For
+example, suppose you want to "increment the value pointed to by the
+second argument of the mock function and return it", you could write:
+
+```
+int IncrementArg1(Unused, int* p, Unused) {
+  return ++(*p);
+}
+
+... WillOnce(Invoke(IncrementArg1));
+```
+
+There are several things unsatisfactory about this approach:
+
+  * Even though the action only cares about the second argument of the mock function, its definition needs to list other arguments as dummies.  This is tedious.
+  * The defined action is usable only in mock functions that takes exactly 3 arguments - an unnecessary restriction.
+  * To use the action, one has to say `Invoke(IncrementArg1)`, which isn't as nice as `IncrementArg1()`.
+
+The latter two problems can be overcome using `MakePolymorphicAction()`,
+but it requires much more boilerplate code:
+
+```
+class IncrementArg1Action {
+ public:
+  template <typename Result, typename ArgumentTuple>
+  Result Perform(const ArgumentTuple& args) const {
+    return ++(*tr1::get<1>(args));
+  }
+};
+
+PolymorphicAction<IncrementArg1Action> IncrementArg1() {
+  return MakePolymorphicAction(IncrementArg1Action());
+}
+
+... WillOnce(IncrementArg1());
+```
+
+Our goal is to allow defining custom actions with the least amount of
+boiler-plate C++ requires.
+
+## Solution ##
+
+We propose to introduce a new macro:
+```
+ACTION(name) { statements; }
+```
+
+Using this in a namespace scope will define an action with the given
+name that executes the statements.  Inside the statements, you can
+refer to the K-th (0-based) argument of the mock function as `argK`.
+For example:
+```
+ACTION(IncrementArg1) { return ++(*arg1); }
+```
+allows you to write
+```
+... WillOnce(IncrementArg1());
+```
+
+Note that you don't need to specify the types of the mock function
+arguments, as brevity is a top design goal here.  Rest assured that
+your code is still type-safe though: you'll get a compiler error if
+`*arg1` doesn't support the `++` operator, or if the type of
+`++(*arg1)` isn't compatible with the mock function's return type.
+
+Another example:
+```
+ACTION(Foo) {
+  (*arg2)(5);
+  Blah();
+  *arg1 = 0;
+  return arg0;
+}
+```
+defines an action `Foo()` that invokes argument #2 (a function pointer)
+with 5, calls function `Blah()`, sets the value pointed to by argument
+#1 to 0, and returns argument #0.
+
+For more convenience and flexibility, you can also use the following
+pre-defined symbols in the body of `ACTION`:
+
+| `argK_type` | The type of the K-th (0-based) argument of the mock function |
+|:------------|:-------------------------------------------------------------|
+| `args`      | All arguments of the mock function as a tuple                |
+| `args_type` | The type of all arguments of the mock function as a tuple    |
+| `return_type` | The return type of the mock function                         |
+| `function_type` | The type of the mock function                                |
+
+For example, when using an `ACTION` as a stub action for mock function:
+```
+int DoSomething(bool flag, int* ptr);
+```
+we have:
+| **Pre-defined Symbol** | **Is Bound To** |
+|:-----------------------|:----------------|
+| `arg0`                 | the value of `flag` |
+| `arg0_type`            | the type `bool` |
+| `arg1`                 | the value of `ptr` |
+| `arg1_type`            | the type `int*` |
+| `args`                 | the tuple `(flag, ptr)` |
+| `args_type`            | the type `std::tr1::tuple<bool, int*>` |
+| `return_type`          | the type `int`  |
+| `function_type`        | the type `int(bool, int*)` |
+
+## Parameterized actions ##
+
+Sometimes you'll want to parameterize the action.   For that we propose
+another macro
+```
+ACTION_P(name, param) { statements; }
+```
+
+For example,
+```
+ACTION_P(Add, n) { return arg0 + n; }
+```
+will allow you to write
+```
+// Returns argument #0 + 5.
+... WillOnce(Add(5));
+```
+
+For convenience, we use the term _arguments_ for the values used to
+invoke the mock function, and the term _parameters_ for the values
+used to instantiate an action.
+
+Note that you don't need to provide the type of the parameter either.
+Suppose the parameter is named `param`, you can also use the
+Google-Mock-defined symbol `param_type` to refer to the type of the
+parameter as inferred by the compiler.
+
+We will also provide `ACTION_P2`, `ACTION_P3`, and etc to support
+multi-parameter actions.  For example,
+```
+ACTION_P2(ReturnDistanceTo, x, y) {
+  double dx = arg0 - x;
+  double dy = arg1 - y;
+  return sqrt(dx*dx + dy*dy);
+}
+```
+lets you write
+```
+... WillOnce(ReturnDistanceTo(5.0, 26.5));
+```
+
+You can view `ACTION` as a degenerated parameterized action where the
+number of parameters is 0.
+
+## Advanced Usages ##
+
+### Overloading Actions ###
+
+You can easily define actions overloaded on the number of parameters:
+```
+ACTION_P(Plus, a) { ... }
+ACTION_P2(Plus, a, b) { ... }
+```
+
+### Restricting the Type of an Argument or Parameter ###
+
+For maximum brevity and reusability, the `ACTION*` macros don't let
+you specify the types of the mock function arguments and the action
+parameters.  Instead, we let the compiler infer the types for us.
+
+Sometimes, however, we may want to be more explicit about the types.
+There are several tricks to do that.  For example:
+```
+ACTION(Foo) {
+  // Makes sure arg0 can be converted to int.
+  int n = arg0;
+  ... use n instead of arg0 here ...
+}
+
+ACTION_P(Bar, param) {
+  // Makes sure the type of arg1 is const char*.
+  ::testing::StaticAssertTypeEq<const char*, arg1_type>();
+
+  // Makes sure param can be converted to bool.
+  bool flag = param;
+}
+```
+where `StaticAssertTypeEq` is a compile-time assertion we plan to add to
+Google Test (the name is chosen to match `static_assert` in C++0x).
+
+### Using the ACTION Object's Type ###
+
+If you are writing a function that returns an `ACTION` object, you'll
+need to know its type.  The type depends on the macro used to define
+the action and the parameter types.  The rule is relatively simple:
+| **Given Definition** | **Expression** | **Has Type** |
+|:---------------------|:---------------|:-------------|
+| `ACTION(Foo)`        | `Foo()`        | `FooAction`  |
+| `ACTION_P(Bar, param)` | `Bar(int_value)` | `BarActionP<int>` |
+| `ACTION_P2(Baz, p1, p2)` | `Baz(bool_value, int_value)` | `BazActionP2<bool, int>` |
+| ...                  | ...            | ...          |
+
+Note that we have to pick different suffixes (`Action`, `ActionP`,
+`ActionP2`, and etc) for actions with different numbers of parameters,
+or the action definitions cannot be overloaded on the number of
+parameters.
+
+## When to Use ##
+
+While the new macros are very convenient, please also consider other
+means of implementing actions (e.g. via `ActionInterface` or
+`MakePolymorphicAction()`), especially if you need to use the defined
+action a lot.  While the other approaches require more work, they give
+you more control on the types of the mock function arguments and the
+action parameters, which in general leads to better compiler error
+messages that pay off in the long run.  They also allow overloading
+actions based on parameter types, as opposed to just the number of
+parameters.
+
+## Related Work ##
+
+As you may have realized, the `ACTION*` macros resemble closures (also
+known as lambda expressions or anonymous functions).  Indeed, both of
+them seek to lower the syntactic overhead for defining a function.
+
+C++0x will support lambdas, but they are not part of C++ right now.
+Some non-standard libraries (most notably BLL or Boost Lambda Library)
+try to alleviate this problem.  However, they are not a good choice
+for defining actions as:
+
+  * They are non-standard and not widely installed.  Google Mock only depends on standard libraries and `tr1::tuple`, which is part of the new C++ standard and comes with gcc 4+.  We want to keep it that way.
+  * They are not trivial to learn.
+  * They will become obsolete when C++0x's lambda feature is widely supported.  We don't want to make our users use a dying library.
+  * Since they are based on operators, they are rather ad hoc: you cannot use statements, and you cannot pass the lambda arguments to a function, for example.
+  * They have subtle semantics that easily confuses new users.  For example, in expression `_1++ + foo++`, `foo` will be incremented only once where the expression is evaluated, while `_1` will be incremented every time the unnamed function is invoked.  This is far from intuitive.
+
+`ACTION*` avoid all these problems.
+
+## Future Improvements ##
+
+There may be a need for composing `ACTION*` definitions (i.e. invoking
+another `ACTION` inside the definition of one `ACTION*`).  We are not
+sure we want it yet, as one can get a similar effect by putting
+`ACTION` definitions in function templates and composing the function
+templates.  We'll revisit this based on user feedback.
+
+The reason we don't allow `ACTION*()` inside a function body is that
+the current C++ standard doesn't allow function-local types to be used
+to instantiate templates.  The upcoming C++0x standard will lift this
+restriction.  Once this feature is widely supported by compilers, we
+can revisit the implementation and add support for using `ACTION*()`
+inside a function.
+
+C++0x will also support lambda expressions.  When they become
+available, we may want to support using lambdas as actions.
+
+# Macros for Defining Matchers #
+
+Once the macros for defining actions are implemented, we plan to do
+the same for matchers:
+
+```
+MATCHER(name) { statements; }
+```
+
+where you can refer to the value being matched as `arg`.  For example,
+given:
+
+```
+MATCHER(IsPositive) { return arg > 0; }
+```
+
+you can use `IsPositive()` as a matcher that matches a value iff it is
+greater than 0.
+
+We will also add `MATCHER_P`, `MATCHER_P2`, and etc for parameterized
+matchers.
\ No newline at end of file
diff --git a/third_party/googletest/googlemock/docs/DevGuide.md b/third_party/googletest/googlemock/docs/DevGuide.md
new file mode 100644
index 0000000..be9e64d
--- /dev/null
+++ b/third_party/googletest/googlemock/docs/DevGuide.md
@@ -0,0 +1,132 @@
+
+
+If you are interested in understanding the internals of Google Mock,
+building from source, or contributing ideas or modifications to the
+project, then this document is for you.
+
+# Introduction #
+
+First, let's give you some background of the project.
+
+## Licensing ##
+
+All Google Mock source and pre-built packages are provided under the [New BSD License](http://www.opensource.org/licenses/bsd-license.php).
+
+## The Google Mock Community ##
+
+The Google Mock community exists primarily through the [discussion group](http://groups.google.com/group/googlemock), the
+[issue tracker](http://code.google.com/p/googlemock/issues/list) and, to a lesser extent, the [source control repository](http://code.google.com/p/googlemock/source/checkout). You are definitely encouraged to contribute to the
+discussion and you can also help us to keep the effectiveness of the
+group high by following and promoting the guidelines listed here.
+
+### Please Be Friendly ###
+
+Showing courtesy and respect to others is a vital part of the Google
+culture, and we strongly encourage everyone participating in Google
+Mock development to join us in accepting nothing less. Of course,
+being courteous is not the same as failing to constructively disagree
+with each other, but it does mean that we should be respectful of each
+other when enumerating the 42 technical reasons that a particular
+proposal may not be the best choice. There's never a reason to be
+antagonistic or dismissive toward anyone who is sincerely trying to
+contribute to a discussion.
+
+Sure, C++ testing is serious business and all that, but it's also
+a lot of fun. Let's keep it that way. Let's strive to be one of the
+friendliest communities in all of open source.
+
+### Where to Discuss Google Mock ###
+
+As always, discuss Google Mock in the official [Google C++ Mocking Framework discussion group](http://groups.google.com/group/googlemock).  You don't have to actually submit
+code in order to sign up. Your participation itself is a valuable
+contribution.
+
+# Working with the Code #
+
+If you want to get your hands dirty with the code inside Google Mock,
+this is the section for you.
+
+## Checking Out the Source from Subversion ##
+
+Checking out the Google Mock source is most useful if you plan to
+tweak it yourself.  You check out the source for Google Mock using a
+[Subversion](http://subversion.tigris.org/) client as you would for any
+other project hosted on Google Code.  Please see the instruction on
+the [source code access page](http://code.google.com/p/googlemock/source/checkout) for how to do it.
+
+## Compiling from Source ##
+
+Once you check out the code, you can find instructions on how to
+compile it in the [README](http://code.google.com/p/googlemock/source/browse/trunk/README) file.
+
+## Testing ##
+
+A mocking framework is of no good if itself is not thoroughly tested.
+Tests should be written for any new code, and changes should be
+verified to not break existing tests before they are submitted for
+review. To perform the tests, follow the instructions in [README](http://code.google.com/p/googlemock/source/browse/trunk/README) and
+verify that there are no failures.
+
+# Contributing Code #
+
+We are excited that Google Mock is now open source, and hope to get
+great patches from the community. Before you fire up your favorite IDE
+and begin hammering away at that new feature, though, please take the
+time to read this section and understand the process. While it seems
+rigorous, we want to keep a high standard of quality in the code
+base.
+
+## Contributor License Agreements ##
+
+You must sign a Contributor License Agreement (CLA) before we can
+accept any code.  The CLA protects you and us.
+
+  * If you are an individual writing original source code and you're sure you own the intellectual property, then you'll need to sign an [individual CLA](http://code.google.com/legal/individual-cla-v1.0.html).
+  * If you work for a company that wants to allow you to contribute your work to Google Mock, then you'll need to sign a [corporate CLA](http://code.google.com/legal/corporate-cla-v1.0.html).
+
+Follow either of the two links above to access the appropriate CLA and
+instructions for how to sign and return it.
+
+## Coding Style ##
+
+To keep the source consistent, readable, diffable and easy to merge,
+we use a fairly rigid coding style, as defined by the [google-styleguide](http://code.google.com/p/google-styleguide/) project.  All patches will be expected
+to conform to the style outlined [here](http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml).
+
+## Submitting Patches ##
+
+Please do submit code. Here's what you need to do:
+
+  1. Normally you should make your change against the SVN trunk instead of a branch or a tag, as the latter two are for release control and should be treated mostly as read-only.
+  1. Decide which code you want to submit. A submission should be a set of changes that addresses one issue in the [Google Mock issue tracker](http://code.google.com/p/googlemock/issues/list). Please don't mix more than one logical change per submittal, because it makes the history hard to follow. If you want to make a change that doesn't have a corresponding issue in the issue tracker, please create one.
+  1. Also, coordinate with team members that are listed on the issue in question. This ensures that work isn't being duplicated and communicating your plan early also generally leads to better patches.
+  1. Ensure that your code adheres to the [Google Mock source code style](#Coding_Style.md).
+  1. Ensure that there are unit tests for your code.
+  1. Sign a Contributor License Agreement.
+  1. Create a patch file using `svn diff`.
+  1. We use [Rietveld](http://codereview.appspot.com/) to do web-based code reviews.  You can read about the tool [here](http://code.google.com/p/rietveld/wiki/CodeReviewHelp).  When you are ready, upload your patch via Rietveld and notify `googlemock@googlegroups.com` to review it.  There are several ways to upload the patch.  We recommend using the [upload\_gmock.py](http://code.google.com/p/googlemock/source/browse/trunk/scripts/upload_gmock.py) script, which you can find in the `scripts/` folder in the SVN trunk.
+
+## Google Mock Committers ##
+
+The current members of the Google Mock engineering team are the only
+committers at present. In the great tradition of eating one's own
+dogfood, we will be requiring each new Google Mock engineering team
+member to earn the right to become a committer by following the
+procedures in this document, writing consistently great code, and
+demonstrating repeatedly that he or she truly gets the zen of Google
+Mock.
+
+# Release Process #
+
+We follow the typical release process for Subversion-based projects:
+
+  1. A release branch named `release-X.Y` is created.
+  1. Bugs are fixed and features are added in trunk; those individual patches are merged into the release branch until it's stable.
+  1. An individual point release (the `Z` in `X.Y.Z`) is made by creating a tag from the branch.
+  1. Repeat steps 2 and 3 throughout one release cycle (as determined by features or time).
+  1. Go back to step 1 to create another release branch and so on.
+
+
+---
+
+This page is based on the [Making GWT Better](http://code.google.com/webtoolkit/makinggwtbetter.html) guide from the [Google Web Toolkit](http://code.google.com/webtoolkit/) project.  Except as otherwise [noted](http://code.google.com/policies.html#restrictions), the content of this page is licensed under the [Creative Commons Attribution 2.5 License](http://creativecommons.org/licenses/by/2.5/).
\ No newline at end of file
diff --git a/third_party/googletest/googlemock/docs/Documentation.md b/third_party/googletest/googlemock/docs/Documentation.md
new file mode 100644
index 0000000..920ed59
--- /dev/null
+++ b/third_party/googletest/googlemock/docs/Documentation.md
@@ -0,0 +1,12 @@
+This page lists all documentation wiki pages for Google Mock **(the SVN trunk version)**
+- **if you use a released version of Google Mock, please read the documentation for that specific version instead.**
+
+  * [ForDummies](ForDummies.md) -- start here if you are new to Google Mock.
+  * [CheatSheet](CheatSheet.md) -- a quick reference.
+  * [CookBook](CookBook.md) -- recipes for doing various tasks using Google Mock.
+  * [FrequentlyAskedQuestions](FrequentlyAskedQuestions.md) -- check here before asking a question on the mailing list.
+
+To contribute code to Google Mock, read:
+
+  * [DevGuide](DevGuide.md) -- read this _before_ writing your first patch.
+  * [Pump Manual](http://code.google.com/p/googletest/wiki/PumpManual) -- how we generate some of Google Mock's source files.
\ No newline at end of file
diff --git a/third_party/googletest/googlemock/docs/ForDummies.md b/third_party/googletest/googlemock/docs/ForDummies.md
new file mode 100644
index 0000000..f6c1ba7
--- /dev/null
+++ b/third_party/googletest/googlemock/docs/ForDummies.md
@@ -0,0 +1,439 @@
+
+
+(**Note:** If you get compiler errors that you don't understand, be sure to consult [Google Mock Doctor](http://code.google.com/p/googlemock/wiki/FrequentlyAskedQuestions#How_am_I_supposed_to_make_sense_of_these_horrible_template_error).)
+
+# What Is Google C++ Mocking Framework? #
+When you write a prototype or test, often it's not feasible or wise to rely on real objects entirely. A **mock object** implements the same interface as a real object (so it can be used as one), but lets you specify at run time how it will be used and what it should do (which methods will be called? in which order? how many times? with what arguments? what will they return? etc).
+
+**Note:** It is easy to confuse the term _fake objects_ with mock objects. Fakes and mocks actually mean very different things in the Test-Driven Development (TDD) community:
+
+  * **Fake** objects have working implementations, but usually take some shortcut (perhaps to make the operations less expensive), which makes them not suitable for production. An in-memory file system would be an example of a fake.
+  * **Mocks** are objects pre-programmed with _expectations_, which form a specification of the calls they are expected to receive.
+
+If all this seems too abstract for you, don't worry - the most important thing to remember is that a mock allows you to check the _interaction_ between itself and code that uses it. The difference between fakes and mocks will become much clearer once you start to use mocks.
+
+**Google C++ Mocking Framework** (or **Google Mock** for short) is a library (sometimes we also call it a "framework" to make it sound cool) for creating mock classes and using them. It does to C++ what [jMock](http://www.jmock.org/) and [EasyMock](http://www.easymock.org/) do to Java.
+
+Using Google Mock involves three basic steps:
+
+  1. Use some simple macros to describe the interface you want to mock, and they will expand to the implementation of your mock class;
+  1. Create some mock objects and specify its expectations and behavior using an intuitive syntax;
+  1. Exercise code that uses the mock objects. Google Mock will catch any violation of the expectations as soon as it arises.
+
+# Why Google Mock? #
+While mock objects help you remove unnecessary dependencies in tests and make them fast and reliable, using mocks manually in C++ is _hard_:
+
+  * Someone has to implement the mocks. The job is usually tedious and error-prone. No wonder people go great distance to avoid it.
+  * The quality of those manually written mocks is a bit, uh, unpredictable. You may see some really polished ones, but you may also see some that were hacked up in a hurry and have all sorts of ad hoc restrictions.
+  * The knowledge you gained from using one mock doesn't transfer to the next.
+
+In contrast, Java and Python programmers have some fine mock frameworks, which automate the creation of mocks. As a result, mocking is a proven effective technique and widely adopted practice in those communities. Having the right tool absolutely makes the difference.
+
+Google Mock was built to help C++ programmers. It was inspired by [jMock](http://www.jmock.org/) and [EasyMock](http://www.easymock.org/), but designed with C++'s specifics in mind. It is your friend if any of the following problems is bothering you:
+
+  * You are stuck with a sub-optimal design and wish you had done more prototyping before it was too late, but prototyping in C++ is by no means "rapid".
+  * Your tests are slow as they depend on too many libraries or use expensive resources (e.g. a database).
+  * Your tests are brittle as some resources they use are unreliable (e.g. the network).
+  * You want to test how your code handles a failure (e.g. a file checksum error), but it's not easy to cause one.
+  * You need to make sure that your module interacts with other modules in the right way, but it's hard to observe the interaction; therefore you resort to observing the side effects at the end of the action, which is awkward at best.
+  * You want to "mock out" your dependencies, except that they don't have mock implementations yet; and, frankly, you aren't thrilled by some of those hand-written mocks.
+
+We encourage you to use Google Mock as:
+
+  * a _design_ tool, for it lets you experiment with your interface design early and often. More iterations lead to better designs!
+  * a _testing_ tool to cut your tests' outbound dependencies and probe the interaction between your module and its collaborators.
+
+# Getting Started #
+Using Google Mock is easy! Inside your C++ source file, just #include `"gtest/gtest.h"` and `"gmock/gmock.h"`, and you are ready to go.
+
+# A Case for Mock Turtles #
+Let's look at an example. Suppose you are developing a graphics program that relies on a LOGO-like API for drawing. How would you test that it does the right thing? Well, you can run it and compare the screen with a golden screen snapshot, but let's admit it: tests like this are expensive to run and fragile (What if you just upgraded to a shiny new graphics card that has better anti-aliasing? Suddenly you have to update all your golden images.). It would be too painful if all your tests are like this. Fortunately, you learned about Dependency Injection and know the right thing to do: instead of having your application talk to the drawing API directly, wrap the API in an interface (say, `Turtle`) and code to that interface:
+
+```
+class Turtle {
+  ...
+  virtual ~Turtle() {}
+  virtual void PenUp() = 0;
+  virtual void PenDown() = 0;
+  virtual void Forward(int distance) = 0;
+  virtual void Turn(int degrees) = 0;
+  virtual void GoTo(int x, int y) = 0;
+  virtual int GetX() const = 0;
+  virtual int GetY() const = 0;
+};
+```
+
+(Note that the destructor of `Turtle` **must** be virtual, as is the case for **all** classes you intend to inherit from - otherwise the destructor of the derived class will not be called when you delete an object through a base pointer, and you'll get corrupted program states like memory leaks.)
+
+You can control whether the turtle's movement will leave a trace using `PenUp()` and `PenDown()`, and control its movement using `Forward()`, `Turn()`, and `GoTo()`. Finally, `GetX()` and `GetY()` tell you the current position of the turtle.
+
+Your program will normally use a real implementation of this interface. In tests, you can use a mock implementation instead. This allows you to easily check what drawing primitives your program is calling, with what arguments, and in which order. Tests written this way are much more robust (they won't break because your new machine does anti-aliasing differently), easier to read and maintain (the intent of a test is expressed in the code, not in some binary images), and run _much, much faster_.
+
+# Writing the Mock Class #
+If you are lucky, the mocks you need to use have already been implemented by some nice people. If, however, you find yourself in the position to write a mock class, relax - Google Mock turns this task into a fun game! (Well, almost.)
+
+## How to Define It ##
+Using the `Turtle` interface as example, here are the simple steps you need to follow:
+
+  1. Derive a class `MockTurtle` from `Turtle`.
+  1. Take a _virtual_ function of `Turtle` (while it's possible to [mock non-virtual methods using templates](http://code.google.com/p/googlemock/wiki/CookBook#Mocking_Nonvirtual_Methods), it's much more involved). Count how many arguments it has.
+  1. In the `public:` section of the child class, write `MOCK_METHODn();` (or `MOCK_CONST_METHODn();` if you are mocking a `const` method), where `n` is the number of the arguments; if you counted wrong, shame on you, and a compiler error will tell you so.
+  1. Now comes the fun part: you take the function signature, cut-and-paste the _function name_ as the _first_ argument to the macro, and leave what's left as the _second_ argument (in case you're curious, this is the _type of the function_).
+  1. Repeat until all virtual functions you want to mock are done.
+
+After the process, you should have something like:
+
+```
+#include "gmock/gmock.h"  // Brings in Google Mock.
+class MockTurtle : public Turtle {
+ public:
+  ...
+  MOCK_METHOD0(PenUp, void());
+  MOCK_METHOD0(PenDown, void());
+  MOCK_METHOD1(Forward, void(int distance));
+  MOCK_METHOD1(Turn, void(int degrees));
+  MOCK_METHOD2(GoTo, void(int x, int y));
+  MOCK_CONST_METHOD0(GetX, int());
+  MOCK_CONST_METHOD0(GetY, int());
+};
+```
+
+You don't need to define these mock methods somewhere else - the `MOCK_METHOD*` macros will generate the definitions for you. It's that simple! Once you get the hang of it, you can pump out mock classes faster than your source-control system can handle your check-ins.
+
+**Tip:** If even this is too much work for you, you'll find the
+`gmock_gen.py` tool in Google Mock's `scripts/generator/` directory (courtesy of the [cppclean](http://code.google.com/p/cppclean/) project) useful.  This command-line
+tool requires that you have Python 2.4 installed.  You give it a C++ file and the name of an abstract class defined in it,
+and it will print the definition of the mock class for you.  Due to the
+complexity of the C++ language, this script may not always work, but
+it can be quite handy when it does.  For more details, read the [user documentation](http://code.google.com/p/googlemock/source/browse/trunk/scripts/generator/README).
+
+## Where to Put It ##
+When you define a mock class, you need to decide where to put its definition. Some people put it in a `*_test.cc`. This is fine when the interface being mocked (say, `Foo`) is owned by the same person or team. Otherwise, when the owner of `Foo` changes it, your test could break. (You can't really expect `Foo`'s maintainer to fix every test that uses `Foo`, can you?)
+
+So, the rule of thumb is: if you need to mock `Foo` and it's owned by others, define the mock class in `Foo`'s package (better, in a `testing` sub-package such that you can clearly separate production code and testing utilities), and put it in a `mock_foo.h`. Then everyone can reference `mock_foo.h` from their tests. If `Foo` ever changes, there is only one copy of `MockFoo` to change, and only tests that depend on the changed methods need to be fixed.
+
+Another way to do it: you can introduce a thin layer `FooAdaptor` on top of `Foo` and code to this new interface. Since you own `FooAdaptor`, you can absorb changes in `Foo` much more easily. While this is more work initially, carefully choosing the adaptor interface can make your code easier to write and more readable (a net win in the long run), as you can choose `FooAdaptor` to fit your specific domain much better than `Foo` does.
+
+# Using Mocks in Tests #
+Once you have a mock class, using it is easy. The typical work flow is:
+
+  1. Import the Google Mock names from the `testing` namespace such that you can use them unqualified (You only have to do it once per file. Remember that namespaces are a good idea and good for your health.).
+  1. Create some mock objects.
+  1. Specify your expectations on them (How many times will a method be called? With what arguments? What should it do? etc.).
+  1. Exercise some code that uses the mocks; optionally, check the result using Google Test assertions. If a mock method is called more than expected or with wrong arguments, you'll get an error immediately.
+  1. When a mock is destructed, Google Mock will automatically check whether all expectations on it have been satisfied.
+
+Here's an example:
+
+```
+#include "path/to/mock-turtle.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+using ::testing::AtLeast;                     // #1
+
+TEST(PainterTest, CanDrawSomething) {
+  MockTurtle turtle;                          // #2
+  EXPECT_CALL(turtle, PenDown())              // #3
+      .Times(AtLeast(1));
+
+  Painter painter(&turtle);                   // #4
+
+  EXPECT_TRUE(painter.DrawCircle(0, 0, 10));
+}                                             // #5
+
+int main(int argc, char** argv) {
+  // The following line must be executed to initialize Google Mock
+  // (and Google Test) before running the tests.
+  ::testing::InitGoogleMock(&argc, argv);
+  return RUN_ALL_TESTS();
+}
+```
+
+As you might have guessed, this test checks that `PenDown()` is called at least once. If the `painter` object didn't call this method, your test will fail with a message like this:
+
+```
+path/to/my_test.cc:119: Failure
+Actual function call count doesn't match this expectation:
+Actually: never called;
+Expected: called at least once.
+```
+
+**Tip 1:** If you run the test from an Emacs buffer, you can hit `<Enter>` on the line number displayed in the error message to jump right to the failed expectation.
+
+**Tip 2:** If your mock objects are never deleted, the final verification won't happen. Therefore it's a good idea to use a heap leak checker in your tests when you allocate mocks on the heap.
+
+**Important note:** Google Mock requires expectations to be set **before** the mock functions are called, otherwise the behavior is **undefined**. In particular, you mustn't interleave `EXPECT_CALL()`s and calls to the mock functions.
+
+This means `EXPECT_CALL()` should be read as expecting that a call will occur _in the future_, not that a call has occurred. Why does Google Mock work like that? Well, specifying the expectation beforehand allows Google Mock to report a violation as soon as it arises, when the context (stack trace, etc) is still available. This makes debugging much easier.
+
+Admittedly, this test is contrived and doesn't do much. You can easily achieve the same effect without using Google Mock. However, as we shall reveal soon, Google Mock allows you to do _much more_ with the mocks.
+
+## Using Google Mock with Any Testing Framework ##
+If you want to use something other than Google Test (e.g. [CppUnit](http://apps.sourceforge.net/mediawiki/cppunit/index.php?title=Main_Page) or
+[CxxTest](http://cxxtest.tigris.org/)) as your testing framework, just change the `main()` function in the previous section to:
+```
+int main(int argc, char** argv) {
+  // The following line causes Google Mock to throw an exception on failure,
+  // which will be interpreted by your testing framework as a test failure.
+  ::testing::GTEST_FLAG(throw_on_failure) = true;
+  ::testing::InitGoogleMock(&argc, argv);
+  ... whatever your testing framework requires ...
+}
+```
+
+This approach has a catch: it makes Google Mock throw an exception
+from a mock object's destructor sometimes.  With some compilers, this
+sometimes causes the test program to crash.  You'll still be able to
+notice that the test has failed, but it's not a graceful failure.
+
+A better solution is to use Google Test's
+[event listener API](http://code.google.com/p/googletest/wiki/AdvancedGuide#Extending_Google_Test_by_Handling_Test_Events)
+to report a test failure to your testing framework properly.  You'll need to
+implement the `OnTestPartResult()` method of the event listener interface, but it
+should be straightforward.
+
+If this turns out to be too much work, we suggest that you stick with
+Google Test, which works with Google Mock seamlessly (in fact, it is
+technically part of Google Mock.).  If there is a reason that you
+cannot use Google Test, please let us know.
+
+# Setting Expectations #
+The key to using a mock object successfully is to set the _right expectations_ on it. If you set the expectations too strict, your test will fail as the result of unrelated changes. If you set them too loose, bugs can slip through. You want to do it just right such that your test can catch exactly the kind of bugs you intend it to catch. Google Mock provides the necessary means for you to do it "just right."
+
+## General Syntax ##
+In Google Mock we use the `EXPECT_CALL()` macro to set an expectation on a mock method. The general syntax is:
+
+```
+EXPECT_CALL(mock_object, method(matchers))
+    .Times(cardinality)
+    .WillOnce(action)
+    .WillRepeatedly(action);
+```
+
+The macro has two arguments: first the mock object, and then the method and its arguments. Note that the two are separated by a comma (`,`), not a period (`.`). (Why using a comma? The answer is that it was necessary for technical reasons.)
+
+The macro can be followed by some optional _clauses_ that provide more information about the expectation. We'll discuss how each clause works in the coming sections.
+
+This syntax is designed to make an expectation read like English. For example, you can probably guess that
+
+```
+using ::testing::Return;...
+EXPECT_CALL(turtle, GetX())
+    .Times(5)
+    .WillOnce(Return(100))
+    .WillOnce(Return(150))
+    .WillRepeatedly(Return(200));
+```
+
+says that the `turtle` object's `GetX()` method will be called five times, it will return 100 the first time, 150 the second time, and then 200 every time. Some people like to call this style of syntax a Domain-Specific Language (DSL).
+
+**Note:** Why do we use a macro to do this? It serves two purposes: first it makes expectations easily identifiable (either by `grep` or by a human reader), and second it allows Google Mock to include the source file location of a failed expectation in messages, making debugging easier.
+
+## Matchers: What Arguments Do We Expect? ##
+When a mock function takes arguments, we must specify what arguments we are expecting; for example:
+
+```
+// Expects the turtle to move forward by 100 units.
+EXPECT_CALL(turtle, Forward(100));
+```
+
+Sometimes you may not want to be too specific (Remember that talk about tests being too rigid? Over specification leads to brittle tests and obscures the intent of tests. Therefore we encourage you to specify only what's necessary - no more, no less.). If you care to check that `Forward()` will be called but aren't interested in its actual argument, write `_` as the argument, which means "anything goes":
+
+```
+using ::testing::_;
+...
+// Expects the turtle to move forward.
+EXPECT_CALL(turtle, Forward(_));
+```
+
+`_` is an instance of what we call **matchers**. A matcher is like a predicate and can test whether an argument is what we'd expect. You can use a matcher inside `EXPECT_CALL()` wherever a function argument is expected.
+
+A list of built-in matchers can be found in the [CheatSheet](CheatSheet.md). For example, here's the `Ge` (greater than or equal) matcher:
+
+```
+using ::testing::Ge;...
+EXPECT_CALL(turtle, Forward(Ge(100)));
+```
+
+This checks that the turtle will be told to go forward by at least 100 units.
+
+## Cardinalities: How Many Times Will It Be Called? ##
+The first clause we can specify following an `EXPECT_CALL()` is `Times()`. We call its argument a **cardinality** as it tells _how many times_ the call should occur. It allows us to repeat an expectation many times without actually writing it as many times. More importantly, a cardinality can be "fuzzy", just like a matcher can be. This allows a user to express the intent of a test exactly.
+
+An interesting special case is when we say `Times(0)`. You may have guessed - it means that the function shouldn't be called with the given arguments at all, and Google Mock will report a Google Test failure whenever the function is (wrongfully) called.
+
+We've seen `AtLeast(n)` as an example of fuzzy cardinalities earlier. For the list of built-in cardinalities you can use, see the [CheatSheet](CheatSheet.md).
+
+The `Times()` clause can be omitted. **If you omit `Times()`, Google Mock will infer the cardinality for you.** The rules are easy to remember:
+
+  * If **neither** `WillOnce()` **nor** `WillRepeatedly()` is in the `EXPECT_CALL()`, the inferred cardinality is `Times(1)`.
+  * If there are `n WillOnce()`'s but **no** `WillRepeatedly()`, where `n` >= 1, the cardinality is `Times(n)`.
+  * If there are `n WillOnce()`'s and **one** `WillRepeatedly()`, where `n` >= 0, the cardinality is `Times(AtLeast(n))`.
+
+**Quick quiz:** what do you think will happen if a function is expected to be called twice but actually called four times?
+
+## Actions: What Should It Do? ##
+Remember that a mock object doesn't really have a working implementation? We as users have to tell it what to do when a method is invoked. This is easy in Google Mock.
+
+First, if the return type of a mock function is a built-in type or a pointer, the function has a **default action** (a `void` function will just return, a `bool` function will return `false`, and other functions will return 0). In addition, in C++ 11 and above, a mock function whose return type is default-constructible (i.e. has a default constructor) has a default action of returning a default-constructed value.  If you don't say anything, this behavior will be used.
+
+Second, if a mock function doesn't have a default action, or the default action doesn't suit you, you can specify the action to be taken each time the expectation matches using a series of `WillOnce()` clauses followed by an optional `WillRepeatedly()`. For example,
+
+```
+using ::testing::Return;...
+EXPECT_CALL(turtle, GetX())
+    .WillOnce(Return(100))
+    .WillOnce(Return(200))
+    .WillOnce(Return(300));
+```
+
+This says that `turtle.GetX()` will be called _exactly three times_ (Google Mock inferred this from how many `WillOnce()` clauses we've written, since we didn't explicitly write `Times()`), and will return 100, 200, and 300 respectively.
+
+```
+using ::testing::Return;...
+EXPECT_CALL(turtle, GetY())
+    .WillOnce(Return(100))
+    .WillOnce(Return(200))
+    .WillRepeatedly(Return(300));
+```
+
+says that `turtle.GetY()` will be called _at least twice_ (Google Mock knows this as we've written two `WillOnce()` clauses and a `WillRepeatedly()` while having no explicit `Times()`), will return 100 the first time, 200 the second time, and 300 from the third time on.
+
+Of course, if you explicitly write a `Times()`, Google Mock will not try to infer the cardinality itself. What if the number you specified is larger than there are `WillOnce()` clauses? Well, after all `WillOnce()`s are used up, Google Mock will do the _default_ action for the function every time (unless, of course, you have a `WillRepeatedly()`.).
+
+What can we do inside `WillOnce()` besides `Return()`? You can return a reference using `ReturnRef(variable)`, or invoke a pre-defined function, among [others](http://code.google.com/p/googlemock/wiki/CheatSheet#Actions).
+
+**Important note:** The `EXPECT_CALL()` statement evaluates the action clause only once, even though the action may be performed many times. Therefore you must be careful about side effects. The following may not do what you want:
+
+```
+int n = 100;
+EXPECT_CALL(turtle, GetX())
+.Times(4)
+.WillRepeatedly(Return(n++));
+```
+
+Instead of returning 100, 101, 102, ..., consecutively, this mock function will always return 100 as `n++` is only evaluated once. Similarly, `Return(new Foo)` will create a new `Foo` object when the `EXPECT_CALL()` is executed, and will return the same pointer every time. If you want the side effect to happen every time, you need to define a custom action, which we'll teach in the [CookBook](CookBook.md).
+
+Time for another quiz! What do you think the following means?
+
+```
+using ::testing::Return;...
+EXPECT_CALL(turtle, GetY())
+.Times(4)
+.WillOnce(Return(100));
+```
+
+Obviously `turtle.GetY()` is expected to be called four times. But if you think it will return 100 every time, think twice! Remember that one `WillOnce()` clause will be consumed each time the function is invoked and the default action will be taken afterwards. So the right answer is that `turtle.GetY()` will return 100 the first time, but **return 0 from the second time on**, as returning 0 is the default action for `int` functions.
+
+## Using Multiple Expectations ##
+So far we've only shown examples where you have a single expectation. More realistically, you're going to specify expectations on multiple mock methods, which may be from multiple mock objects.
+
+By default, when a mock method is invoked, Google Mock will search the expectations in the **reverse order** they are defined, and stop when an active expectation that matches the arguments is found (you can think of it as "newer rules override older ones."). If the matching expectation cannot take any more calls, you will get an upper-bound-violated failure. Here's an example:
+
+```
+using ::testing::_;...
+EXPECT_CALL(turtle, Forward(_));  // #1
+EXPECT_CALL(turtle, Forward(10))  // #2
+    .Times(2);
+```
+
+If `Forward(10)` is called three times in a row, the third time it will be an error, as the last matching expectation (#2) has been saturated. If, however, the third `Forward(10)` call is replaced by `Forward(20)`, then it would be OK, as now #1 will be the matching expectation.
+
+**Side note:** Why does Google Mock search for a match in the _reverse_ order of the expectations? The reason is that this allows a user to set up the default expectations in a mock object's constructor or the test fixture's set-up phase and then customize the mock by writing more specific expectations in the test body. So, if you have two expectations on the same method, you want to put the one with more specific matchers **after** the other, or the more specific rule would be shadowed by the more general one that comes after it.
+
+## Ordered vs Unordered Calls ##
+By default, an expectation can match a call even though an earlier expectation hasn't been satisfied. In other words, the calls don't have to occur in the order the expectations are specified.
+
+Sometimes, you may want all the expected calls to occur in a strict order. To say this in Google Mock is easy:
+
+```
+using ::testing::InSequence;...
+TEST(FooTest, DrawsLineSegment) {
+  ...
+  {
+    InSequence dummy;
+
+    EXPECT_CALL(turtle, PenDown());
+    EXPECT_CALL(turtle, Forward(100));
+    EXPECT_CALL(turtle, PenUp());
+  }
+  Foo();
+}
+```
+
+By creating an object of type `InSequence`, all expectations in its scope are put into a _sequence_ and have to occur _sequentially_. Since we are just relying on the constructor and destructor of this object to do the actual work, its name is really irrelevant.
+
+In this example, we test that `Foo()` calls the three expected functions in the order as written. If a call is made out-of-order, it will be an error.
+
+(What if you care about the relative order of some of the calls, but not all of them? Can you specify an arbitrary partial order? The answer is ... yes! If you are impatient, the details can be found in the [CookBook](CookBook#Expecting_Partially_Ordered_Calls.md).)
+
+## All Expectations Are Sticky (Unless Said Otherwise) ##
+Now let's do a quick quiz to see how well you can use this mock stuff already. How would you test that the turtle is asked to go to the origin _exactly twice_ (you want to ignore any other instructions it receives)?
+
+After you've come up with your answer, take a look at ours and compare notes (solve it yourself first - don't cheat!):
+
+```
+using ::testing::_;...
+EXPECT_CALL(turtle, GoTo(_, _))  // #1
+    .Times(AnyNumber());
+EXPECT_CALL(turtle, GoTo(0, 0))  // #2
+    .Times(2);
+```
+
+Suppose `turtle.GoTo(0, 0)` is called three times. In the third time, Google Mock will see that the arguments match expectation #2 (remember that we always pick the last matching expectation). Now, since we said that there should be only two such calls, Google Mock will report an error immediately. This is basically what we've told you in the "Using Multiple Expectations" section above.
+
+This example shows that **expectations in Google Mock are "sticky" by default**, in the sense that they remain active even after we have reached their invocation upper bounds. This is an important rule to remember, as it affects the meaning of the spec, and is **different** to how it's done in many other mocking frameworks (Why'd we do that? Because we think our rule makes the common cases easier to express and understand.).
+
+Simple? Let's see if you've really understood it: what does the following code say?
+
+```
+using ::testing::Return;
+...
+for (int i = n; i > 0; i--) {
+  EXPECT_CALL(turtle, GetX())
+      .WillOnce(Return(10*i));
+}
+```
+
+If you think it says that `turtle.GetX()` will be called `n` times and will return 10, 20, 30, ..., consecutively, think twice! The problem is that, as we said, expectations are sticky. So, the second time `turtle.GetX()` is called, the last (latest) `EXPECT_CALL()` statement will match, and will immediately lead to an "upper bound exceeded" error - this piece of code is not very useful!
+
+One correct way of saying that `turtle.GetX()` will return 10, 20, 30, ..., is to explicitly say that the expectations are _not_ sticky. In other words, they should _retire_ as soon as they are saturated:
+
+```
+using ::testing::Return;
+...
+for (int i = n; i > 0; i--) {
+  EXPECT_CALL(turtle, GetX())
+    .WillOnce(Return(10*i))
+    .RetiresOnSaturation();
+}
+```
+
+And, there's a better way to do it: in this case, we expect the calls to occur in a specific order, and we line up the actions to match the order. Since the order is important here, we should make it explicit using a sequence:
+
+```
+using ::testing::InSequence;
+using ::testing::Return;
+...
+{
+  InSequence s;
+
+  for (int i = 1; i <= n; i++) {
+    EXPECT_CALL(turtle, GetX())
+        .WillOnce(Return(10*i))
+        .RetiresOnSaturation();
+  }
+}
+```
+
+By the way, the other situation where an expectation may _not_ be sticky is when it's in a sequence - as soon as another expectation that comes after it in the sequence has been used, it automatically retires (and will never be used to match any call).
+
+## Uninteresting Calls ##
+A mock object may have many methods, and not all of them are that interesting. For example, in some tests we may not care about how many times `GetX()` and `GetY()` get called.
+
+In Google Mock, if you are not interested in a method, just don't say anything about it. If a call to this method occurs, you'll see a warning in the test output, but it won't be a failure.
+
+# What Now? #
+Congratulations! You've learned enough about Google Mock to start using it. Now, you might want to join the [googlemock](http://groups.google.com/group/googlemock) discussion group and actually write some tests using Google Mock - it will be fun. Hey, it may even be addictive - you've been warned.
+
+Then, if you feel like increasing your mock quotient, you should move on to the [CookBook](CookBook.md). You can learn many advanced features of Google Mock there -- and advance your level of enjoyment and testing bliss.
\ No newline at end of file
diff --git a/third_party/googletest/googlemock/docs/FrequentlyAskedQuestions.md b/third_party/googletest/googlemock/docs/FrequentlyAskedQuestions.md
new file mode 100644
index 0000000..859a71e
--- /dev/null
+++ b/third_party/googletest/googlemock/docs/FrequentlyAskedQuestions.md
@@ -0,0 +1,628 @@
+
+
+Please send your questions to the
+[googlemock](http://groups.google.com/group/googlemock) discussion
+group. If you need help with compiler errors, make sure you have
+tried [Google Mock Doctor](#How_am_I_supposed_to_make_sense_of_these_horrible_template_error.md) first.
+
+## When I call a method on my mock object, the method for the real object is invoked instead.  What's the problem? ##
+
+In order for a method to be mocked, it must be _virtual_, unless you use the [high-perf dependency injection technique](http://code.google.com/p/googlemock/wiki/CookBook#Mocking_Nonvirtual_Methods).
+
+## I wrote some matchers.  After I upgraded to a new version of Google Mock, they no longer compile.  What's going on? ##
+
+After version 1.4.0 of Google Mock was released, we had an idea on how
+to make it easier to write matchers that can generate informative
+messages efficiently.  We experimented with this idea and liked what
+we saw.  Therefore we decided to implement it.
+
+Unfortunately, this means that if you have defined your own matchers
+by implementing `MatcherInterface` or using `MakePolymorphicMatcher()`,
+your definitions will no longer compile.  Matchers defined using the
+`MATCHER*` family of macros are not affected.
+
+Sorry for the hassle if your matchers are affected.  We believe it's
+in everyone's long-term interest to make this change sooner than
+later.  Fortunately, it's usually not hard to migrate an existing
+matcher to the new API.  Here's what you need to do:
+
+If you wrote your matcher like this:
+```
+// Old matcher definition that doesn't work with the latest
+// Google Mock.
+using ::testing::MatcherInterface;
+...
+class MyWonderfulMatcher : public MatcherInterface<MyType> {
+ public:
+  ...
+  virtual bool Matches(MyType value) const {
+    // Returns true if value matches.
+    return value.GetFoo() > 5;
+  }
+  ...
+};
+```
+
+you'll need to change it to:
+```
+// New matcher definition that works with the latest Google Mock.
+using ::testing::MatcherInterface;
+using ::testing::MatchResultListener;
+...
+class MyWonderfulMatcher : public MatcherInterface<MyType> {
+ public:
+  ...
+  virtual bool MatchAndExplain(MyType value,
+                               MatchResultListener* listener) const {
+    // Returns true if value matches.
+    return value.GetFoo() > 5;
+  }
+  ...
+};
+```
+(i.e. rename `Matches()` to `MatchAndExplain()` and give it a second
+argument of type `MatchResultListener*`.)
+
+If you were also using `ExplainMatchResultTo()` to improve the matcher
+message:
+```
+// Old matcher definition that doesn't work with the lastest
+// Google Mock.
+using ::testing::MatcherInterface;
+...
+class MyWonderfulMatcher : public MatcherInterface<MyType> {
+ public:
+  ...
+  virtual bool Matches(MyType value) const {
+    // Returns true if value matches.
+    return value.GetFoo() > 5;
+  }
+
+  virtual void ExplainMatchResultTo(MyType value,
+                                    ::std::ostream* os) const {
+    // Prints some helpful information to os to help
+    // a user understand why value matches (or doesn't match).
+    *os << "the Foo property is " << value.GetFoo();
+  }
+  ...
+};
+```
+
+you should move the logic of `ExplainMatchResultTo()` into
+`MatchAndExplain()`, using the `MatchResultListener` argument where
+the `::std::ostream` was used:
+```
+// New matcher definition that works with the latest Google Mock.
+using ::testing::MatcherInterface;
+using ::testing::MatchResultListener;
+...
+class MyWonderfulMatcher : public MatcherInterface<MyType> {
+ public:
+  ...
+  virtual bool MatchAndExplain(MyType value,
+                               MatchResultListener* listener) const {
+    // Returns true if value matches.
+    *listener << "the Foo property is " << value.GetFoo();
+    return value.GetFoo() > 5;
+  }
+  ...
+};
+```
+
+If your matcher is defined using `MakePolymorphicMatcher()`:
+```
+// Old matcher definition that doesn't work with the latest
+// Google Mock.
+using ::testing::MakePolymorphicMatcher;
+...
+class MyGreatMatcher {
+ public:
+  ...
+  bool Matches(MyType value) const {
+    // Returns true if value matches.
+    return value.GetBar() < 42;
+  }
+  ...
+};
+... MakePolymorphicMatcher(MyGreatMatcher()) ...
+```
+
+you should rename the `Matches()` method to `MatchAndExplain()` and
+add a `MatchResultListener*` argument (the same as what you need to do
+for matchers defined by implementing `MatcherInterface`):
+```
+// New matcher definition that works with the latest Google Mock.
+using ::testing::MakePolymorphicMatcher;
+using ::testing::MatchResultListener;
+...
+class MyGreatMatcher {
+ public:
+  ...
+  bool MatchAndExplain(MyType value,
+                       MatchResultListener* listener) const {
+    // Returns true if value matches.
+    return value.GetBar() < 42;
+  }
+  ...
+};
+... MakePolymorphicMatcher(MyGreatMatcher()) ...
+```
+
+If your polymorphic matcher uses `ExplainMatchResultTo()` for better
+failure messages:
+```
+// Old matcher definition that doesn't work with the latest
+// Google Mock.
+using ::testing::MakePolymorphicMatcher;
+...
+class MyGreatMatcher {
+ public:
+  ...
+  bool Matches(MyType value) const {
+    // Returns true if value matches.
+    return value.GetBar() < 42;
+  }
+  ...
+};
+void ExplainMatchResultTo(const MyGreatMatcher& matcher,
+                          MyType value,
+                          ::std::ostream* os) {
+  // Prints some helpful information to os to help
+  // a user understand why value matches (or doesn't match).
+  *os << "the Bar property is " << value.GetBar();
+}
+... MakePolymorphicMatcher(MyGreatMatcher()) ...
+```
+
+you'll need to move the logic inside `ExplainMatchResultTo()` to
+`MatchAndExplain()`:
+```
+// New matcher definition that works with the latest Google Mock.
+using ::testing::MakePolymorphicMatcher;
+using ::testing::MatchResultListener;
+...
+class MyGreatMatcher {
+ public:
+  ...
+  bool MatchAndExplain(MyType value,
+                       MatchResultListener* listener) const {
+    // Returns true if value matches.
+    *listener << "the Bar property is " << value.GetBar();
+    return value.GetBar() < 42;
+  }
+  ...
+};
+... MakePolymorphicMatcher(MyGreatMatcher()) ...
+```
+
+For more information, you can read these
+[two](http://code.google.com/p/googlemock/wiki/CookBook#Writing_New_Monomorphic_Matchers)
+[recipes](http://code.google.com/p/googlemock/wiki/CookBook#Writing_New_Polymorphic_Matchers)
+from the cookbook.  As always, you
+are welcome to post questions on `googlemock@googlegroups.com` if you
+need any help.
+
+## When using Google Mock, do I have to use Google Test as the testing framework?  I have my favorite testing framework and don't want to switch. ##
+
+Google Mock works out of the box with Google Test.  However, it's easy
+to configure it to work with any testing framework of your choice.
+[Here](http://code.google.com/p/googlemock/wiki/ForDummies#Using_Google_Mock_with_Any_Testing_Framework) is how.
+
+## How am I supposed to make sense of these horrible template errors? ##
+
+If you are confused by the compiler errors gcc threw at you,
+try consulting the _Google Mock Doctor_ tool first.  What it does is to
+scan stdin for gcc error messages, and spit out diagnoses on the
+problems (we call them diseases) your code has.
+
+To "install", run command:
+```
+alias gmd='<path to googlemock>/scripts/gmock_doctor.py'
+```
+
+To use it, do:
+```
+<your-favorite-build-command> <your-test> 2>&1 | gmd
+```
+
+For example:
+```
+make my_test 2>&1 | gmd
+```
+
+Or you can run `gmd` and copy-n-paste gcc's error messages to it.
+
+## Can I mock a variadic function? ##
+
+You cannot mock a variadic function (i.e. a function taking ellipsis
+(`...`) arguments) directly in Google Mock.
+
+The problem is that in general, there is _no way_ for a mock object to
+know how many arguments are passed to the variadic method, and what
+the arguments' types are.  Only the _author of the base class_ knows
+the protocol, and we cannot look into his head.
+
+Therefore, to mock such a function, the _user_ must teach the mock
+object how to figure out the number of arguments and their types.  One
+way to do it is to provide overloaded versions of the function.
+
+Ellipsis arguments are inherited from C and not really a C++ feature.
+They are unsafe to use and don't work with arguments that have
+constructors or destructors.  Therefore we recommend to avoid them in
+C++ as much as possible.
+
+## MSVC gives me warning C4301 or C4373 when I define a mock method with a const parameter.  Why? ##
+
+If you compile this using Microsoft Visual C++ 2005 SP1:
+```
+class Foo {
+  ...
+  virtual void Bar(const int i) = 0;
+};
+
+class MockFoo : public Foo {
+  ...
+  MOCK_METHOD1(Bar, void(const int i));
+};
+```
+You may get the following warning:
+```
+warning C4301: 'MockFoo::Bar': overriding virtual function only differs from 'Foo::Bar' by const/volatile qualifier
+```
+
+This is a MSVC bug.  The same code compiles fine with gcc ,for
+example.  If you use Visual C++ 2008 SP1, you would get the warning:
+```
+warning C4373: 'MockFoo::Bar': virtual function overrides 'Foo::Bar', previous versions of the compiler did not override when parameters only differed by const/volatile qualifiers
+```
+
+In C++, if you _declare_ a function with a `const` parameter, the
+`const` modifier is _ignored_.  Therefore, the `Foo` base class above
+is equivalent to:
+```
+class Foo {
+  ...
+  virtual void Bar(int i) = 0;  // int or const int?  Makes no difference.
+};
+```
+
+In fact, you can _declare_ Bar() with an `int` parameter, and _define_
+it with a `const int` parameter.  The compiler will still match them
+up.
+
+Since making a parameter `const` is meaningless in the method
+_declaration_, we recommend to remove it in both `Foo` and `MockFoo`.
+That should workaround the VC bug.
+
+Note that we are talking about the _top-level_ `const` modifier here.
+If the function parameter is passed by pointer or reference, declaring
+the _pointee_ or _referee_ as `const` is still meaningful.  For
+example, the following two declarations are _not_ equivalent:
+```
+void Bar(int* p);        // Neither p nor *p is const.
+void Bar(const int* p);  // p is not const, but *p is.
+```
+
+## I have a huge mock class, and Microsoft Visual C++ runs out of memory when compiling it.  What can I do? ##
+
+We've noticed that when the `/clr` compiler flag is used, Visual C++
+uses 5~6 times as much memory when compiling a mock class.  We suggest
+to avoid `/clr` when compiling native C++ mocks.
+
+## I can't figure out why Google Mock thinks my expectations are not satisfied.  What should I do? ##
+
+You might want to run your test with
+`--gmock_verbose=info`.  This flag lets Google Mock print a trace
+of every mock function call it receives.  By studying the trace,
+you'll gain insights on why the expectations you set are not met.
+
+## How can I assert that a function is NEVER called? ##
+
+```
+EXPECT_CALL(foo, Bar(_))
+    .Times(0);
+```
+
+## I have a failed test where Google Mock tells me TWICE that a particular expectation is not satisfied.  Isn't this redundant? ##
+
+When Google Mock detects a failure, it prints relevant information
+(the mock function arguments, the state of relevant expectations, and
+etc) to help the user debug.  If another failure is detected, Google
+Mock will do the same, including printing the state of relevant
+expectations.
+
+Sometimes an expectation's state didn't change between two failures,
+and you'll see the same description of the state twice.  They are
+however _not_ redundant, as they refer to _different points in time_.
+The fact they are the same _is_ interesting information.
+
+## I get a heap check failure when using a mock object, but using a real object is fine.  What can be wrong? ##
+
+Does the class (hopefully a pure interface) you are mocking have a
+virtual destructor?
+
+Whenever you derive from a base class, make sure its destructor is
+virtual.  Otherwise Bad Things will happen.  Consider the following
+code:
+
+```
+class Base {
+ public:
+  // Not virtual, but should be.
+  ~Base() { ... }
+  ...
+};
+
+class Derived : public Base {
+ public:
+  ...
+ private:
+  std::string value_;
+};
+
+...
+  Base* p = new Derived;
+  ...
+  delete p;  // Surprise! ~Base() will be called, but ~Derived() will not
+             // - value_ is leaked.
+```
+
+By changing `~Base()` to virtual, `~Derived()` will be correctly
+called when `delete p` is executed, and the heap checker
+will be happy.
+
+## The "newer expectations override older ones" rule makes writing expectations awkward.  Why does Google Mock do that? ##
+
+When people complain about this, often they are referring to code like:
+
+```
+// foo.Bar() should be called twice, return 1 the first time, and return
+// 2 the second time.  However, I have to write the expectations in the
+// reverse order.  This sucks big time!!!
+EXPECT_CALL(foo, Bar())
+    .WillOnce(Return(2))
+    .RetiresOnSaturation();
+EXPECT_CALL(foo, Bar())
+    .WillOnce(Return(1))
+    .RetiresOnSaturation();
+```
+
+The problem is that they didn't pick the **best** way to express the test's
+intent.
+
+By default, expectations don't have to be matched in _any_ particular
+order.  If you want them to match in a certain order, you need to be
+explicit.  This is Google Mock's (and jMock's) fundamental philosophy: it's
+easy to accidentally over-specify your tests, and we want to make it
+harder to do so.
+
+There are two better ways to write the test spec.  You could either
+put the expectations in sequence:
+
+```
+// foo.Bar() should be called twice, return 1 the first time, and return
+// 2 the second time.  Using a sequence, we can write the expectations
+// in their natural order.
+{
+  InSequence s;
+  EXPECT_CALL(foo, Bar())
+      .WillOnce(Return(1))
+      .RetiresOnSaturation();
+  EXPECT_CALL(foo, Bar())
+      .WillOnce(Return(2))
+      .RetiresOnSaturation();
+}
+```
+
+or you can put the sequence of actions in the same expectation:
+
+```
+// foo.Bar() should be called twice, return 1 the first time, and return
+// 2 the second time.
+EXPECT_CALL(foo, Bar())
+    .WillOnce(Return(1))
+    .WillOnce(Return(2))
+    .RetiresOnSaturation();
+```
+
+Back to the original questions: why does Google Mock search the
+expectations (and `ON_CALL`s) from back to front?  Because this
+allows a user to set up a mock's behavior for the common case early
+(e.g. in the mock's constructor or the test fixture's set-up phase)
+and customize it with more specific rules later.  If Google Mock
+searches from front to back, this very useful pattern won't be
+possible.
+
+## Google Mock prints a warning when a function without EXPECT\_CALL is called, even if I have set its behavior using ON\_CALL.  Would it be reasonable not to show the warning in this case? ##
+
+When choosing between being neat and being safe, we lean toward the
+latter.  So the answer is that we think it's better to show the
+warning.
+
+Often people write `ON_CALL`s in the mock object's
+constructor or `SetUp()`, as the default behavior rarely changes from
+test to test.  Then in the test body they set the expectations, which
+are often different for each test.  Having an `ON_CALL` in the set-up
+part of a test doesn't mean that the calls are expected.  If there's
+no `EXPECT_CALL` and the method is called, it's possibly an error.  If
+we quietly let the call go through without notifying the user, bugs
+may creep in unnoticed.
+
+If, however, you are sure that the calls are OK, you can write
+
+```
+EXPECT_CALL(foo, Bar(_))
+    .WillRepeatedly(...);
+```
+
+instead of
+
+```
+ON_CALL(foo, Bar(_))
+    .WillByDefault(...);
+```
+
+This tells Google Mock that you do expect the calls and no warning should be
+printed.
+
+Also, you can control the verbosity using the `--gmock_verbose` flag.
+If you find the output too noisy when debugging, just choose a less
+verbose level.
+
+## How can I delete the mock function's argument in an action? ##
+
+If you find yourself needing to perform some action that's not
+supported by Google Mock directly, remember that you can define your own
+actions using
+[MakeAction()](http://code.google.com/p/googlemock/wiki/CookBook#Writing_New_Actions) or
+[MakePolymorphicAction()](http://code.google.com/p/googlemock/wiki/CookBook#Writing_New_Polymorphic_Actions),
+or you can write a stub function and invoke it using
+[Invoke()](http://code.google.com/p/googlemock/wiki/CookBook#Using_Functions_Methods_Functors).
+
+## MOCK\_METHODn()'s second argument looks funny.  Why don't you use the MOCK\_METHODn(Method, return\_type, arg\_1, ..., arg\_n) syntax? ##
+
+What?!  I think it's beautiful. :-)
+
+While which syntax looks more natural is a subjective matter to some
+extent, Google Mock's syntax was chosen for several practical advantages it
+has.
+
+Try to mock a function that takes a map as an argument:
+```
+virtual int GetSize(const map<int, std::string>& m);
+```
+
+Using the proposed syntax, it would be:
+```
+MOCK_METHOD1(GetSize, int, const map<int, std::string>& m);
+```
+
+Guess what?  You'll get a compiler error as the compiler thinks that
+`const map<int, std::string>& m` are **two**, not one, arguments. To work
+around this you can use `typedef` to give the map type a name, but
+that gets in the way of your work.  Google Mock's syntax avoids this
+problem as the function's argument types are protected inside a pair
+of parentheses:
+```
+// This compiles fine.
+MOCK_METHOD1(GetSize, int(const map<int, std::string>& m));
+```
+
+You still need a `typedef` if the return type contains an unprotected
+comma, but that's much rarer.
+
+Other advantages include:
+  1. `MOCK_METHOD1(Foo, int, bool)` can leave a reader wonder whether the method returns `int` or `bool`, while there won't be such confusion using Google Mock's syntax.
+  1. The way Google Mock describes a function type is nothing new, although many people may not be familiar with it.  The same syntax was used in C, and the `function` library in `tr1` uses this syntax extensively.  Since `tr1` will become a part of the new version of STL, we feel very comfortable to be consistent with it.
+  1. The function type syntax is also used in other parts of Google Mock's API (e.g. the action interface) in order to make the implementation tractable. A user needs to learn it anyway in order to utilize Google Mock's more advanced features.  We'd as well stick to the same syntax in `MOCK_METHOD*`!
+
+## My code calls a static/global function.  Can I mock it? ##
+
+You can, but you need to make some changes.
+
+In general, if you find yourself needing to mock a static function,
+it's a sign that your modules are too tightly coupled (and less
+flexible, less reusable, less testable, etc).  You are probably better
+off defining a small interface and call the function through that
+interface, which then can be easily mocked.  It's a bit of work
+initially, but usually pays for itself quickly.
+
+This Google Testing Blog
+[post](http://googletesting.blogspot.com/2008/06/defeat-static-cling.html)
+says it excellently.  Check it out.
+
+## My mock object needs to do complex stuff.  It's a lot of pain to specify the actions.  Google Mock sucks! ##
+
+I know it's not a question, but you get an answer for free any way. :-)
+
+With Google Mock, you can create mocks in C++ easily.  And people might be
+tempted to use them everywhere. Sometimes they work great, and
+sometimes you may find them, well, a pain to use. So, what's wrong in
+the latter case?
+
+When you write a test without using mocks, you exercise the code and
+assert that it returns the correct value or that the system is in an
+expected state.  This is sometimes called "state-based testing".
+
+Mocks are great for what some call "interaction-based" testing:
+instead of checking the system state at the very end, mock objects
+verify that they are invoked the right way and report an error as soon
+as it arises, giving you a handle on the precise context in which the
+error was triggered.  This is often more effective and economical to
+do than state-based testing.
+
+If you are doing state-based testing and using a test double just to
+simulate the real object, you are probably better off using a fake.
+Using a mock in this case causes pain, as it's not a strong point for
+mocks to perform complex actions.  If you experience this and think
+that mocks suck, you are just not using the right tool for your
+problem. Or, you might be trying to solve the wrong problem. :-)
+
+## I got a warning "Uninteresting function call encountered - default action taken.."  Should I panic? ##
+
+By all means, NO!  It's just an FYI.
+
+What it means is that you have a mock function, you haven't set any
+expectations on it (by Google Mock's rule this means that you are not
+interested in calls to this function and therefore it can be called
+any number of times), and it is called.  That's OK - you didn't say
+it's not OK to call the function!
+
+What if you actually meant to disallow this function to be called, but
+forgot to write `EXPECT_CALL(foo, Bar()).Times(0)`?  While
+one can argue that it's the user's fault, Google Mock tries to be nice and
+prints you a note.
+
+So, when you see the message and believe that there shouldn't be any
+uninteresting calls, you should investigate what's going on.  To make
+your life easier, Google Mock prints the function name and arguments
+when an uninteresting call is encountered.
+
+## I want to define a custom action.  Should I use Invoke() or implement the action interface? ##
+
+Either way is fine - you want to choose the one that's more convenient
+for your circumstance.
+
+Usually, if your action is for a particular function type, defining it
+using `Invoke()` should be easier; if your action can be used in
+functions of different types (e.g. if you are defining
+`Return(value)`), `MakePolymorphicAction()` is
+easiest.  Sometimes you want precise control on what types of
+functions the action can be used in, and implementing
+`ActionInterface` is the way to go here. See the implementation of
+`Return()` in `include/gmock/gmock-actions.h` for an example.
+
+## I'm using the set-argument-pointee action, and the compiler complains about "conflicting return type specified".  What does it mean? ##
+
+You got this error as Google Mock has no idea what value it should return
+when the mock method is called.  `SetArgPointee()` says what the
+side effect is, but doesn't say what the return value should be.  You
+need `DoAll()` to chain a `SetArgPointee()` with a `Return()`.
+
+See this [recipe](http://code.google.com/p/googlemock/wiki/CookBook#Mocking_Side_Effects) for more details and an example.
+
+
+## My question is not in your FAQ! ##
+
+If you cannot find the answer to your question in this FAQ, there are
+some other resources you can use:
+
+  1. read other [wiki pages](http://code.google.com/p/googlemock/w/list),
+  1. search the mailing list [archive](http://groups.google.com/group/googlemock/topics),
+  1. ask it on [googlemock@googlegroups.com](mailto:googlemock@googlegroups.com) and someone will answer it (to prevent spam, we require you to join the [discussion group](http://groups.google.com/group/googlemock) before you can post.).
+
+Please note that creating an issue in the
+[issue tracker](http://code.google.com/p/googlemock/issues/list) is _not_
+a good way to get your answer, as it is monitored infrequently by a
+very small number of people.
+
+When asking a question, it's helpful to provide as much of the
+following information as possible (people cannot help you if there's
+not enough information in your question):
+
+  * the version (or the revision number if you check out from SVN directly) of Google Mock you use (Google Mock is under active development, so it's possible that your problem has been solved in a later version),
+  * your operating system,
+  * the name and version of your compiler,
+  * the complete command line flags you give to your compiler,
+  * the complete compiler error messages (if the question is about compilation),
+  * the _actual_ code (ideally, a minimal but complete program) that has the problem you encounter.
\ No newline at end of file
diff --git a/third_party/googletest/googlemock/docs/KnownIssues.md b/third_party/googletest/googlemock/docs/KnownIssues.md
new file mode 100644
index 0000000..adadf51
--- /dev/null
+++ b/third_party/googletest/googlemock/docs/KnownIssues.md
@@ -0,0 +1,19 @@
+As any non-trivial software system, Google Mock has some known limitations and problems.  We are working on improving it, and welcome your help!  The follow is a list of issues we know about.
+
+
+
+## README contains outdated information on Google Mock's compatibility with other testing frameworks ##
+
+The `README` file in release 1.1.0 still says that Google Mock only works with Google Test.  Actually, you can configure Google Mock to work with any testing framework you choose.
+
+## Tests failing on machines using Power PC CPUs (e.g. some Macs) ##
+
+`gmock_output_test` and `gmock-printers_test` are known to fail with Power PC CPUs.  This is due to portability issues with these tests, and is not an indication of problems in Google Mock itself.  You can safely ignore them.
+
+## Failed to resolve libgtest.so.0 in tests when built against installed Google Test ##
+
+This only applies if you manually built and installed Google Test, and then built a Google Mock against it (either explicitly, or because gtest-config was in your path post-install). In this situation, Libtool has a known issue with certain systems' ldconfig setup:
+
+http://article.gmane.org/gmane.comp.sysutils.automake.general/9025
+
+This requires a manual run of "sudo ldconfig" after the "sudo make install" for Google Test before any binaries which link against it can be executed. This isn't a bug in our install, but we should at least have documented it or hacked a work-around into our install. We should have one of these solutions in our next release.
\ No newline at end of file
diff --git a/third_party/googletest/googlemock/docs/v1_5/CheatSheet.md b/third_party/googletest/googlemock/docs/v1_5/CheatSheet.md
new file mode 100644
index 0000000..3c7bed4
--- /dev/null
+++ b/third_party/googletest/googlemock/docs/v1_5/CheatSheet.md
@@ -0,0 +1,525 @@
+
+
+# Defining a Mock Class #
+
+## Mocking a Normal Class ##
+
+Given
+```
+class Foo {
+  ...
+  virtual ~Foo();
+  virtual int GetSize() const = 0;
+  virtual string Describe(const char* name) = 0;
+  virtual string Describe(int type) = 0;
+  virtual bool Process(Bar elem, int count) = 0;
+};
+```
+(note that `~Foo()` **must** be virtual) we can define its mock as
+```
+#include <gmock/gmock.h>
+
+class MockFoo : public Foo {
+  MOCK_CONST_METHOD0(GetSize, int());
+  MOCK_METHOD1(Describe, string(const char* name));
+  MOCK_METHOD1(Describe, string(int type));
+  MOCK_METHOD2(Process, bool(Bar elem, int count));
+};
+```
+
+To create a "nice" mock object which ignores all uninteresting calls,
+or a "strict" mock object, which treats them as failures:
+```
+NiceMock<MockFoo> nice_foo;     // The type is a subclass of MockFoo.
+StrictMock<MockFoo> strict_foo; // The type is a subclass of MockFoo.
+```
+
+## Mocking a Class Template ##
+
+To mock
+```
+template <typename Elem>
+class StackInterface {
+ public:
+  ...
+  virtual ~StackInterface();
+  virtual int GetSize() const = 0;
+  virtual void Push(const Elem& x) = 0;
+};
+```
+(note that `~StackInterface()` **must** be virtual) just append `_T` to the `MOCK_*` macros:
+```
+template <typename Elem>
+class MockStack : public StackInterface<Elem> {
+ public:
+  ...
+  MOCK_CONST_METHOD0_T(GetSize, int());
+  MOCK_METHOD1_T(Push, void(const Elem& x));
+};
+```
+
+## Specifying Calling Conventions for Mock Functions ##
+
+If your mock function doesn't use the default calling convention, you
+can specify it by appending `_WITH_CALLTYPE` to any of the macros
+described in the previous two sections and supplying the calling
+convention as the first argument to the macro. For example,
+```
+  MOCK_METHOD_1_WITH_CALLTYPE(STDMETHODCALLTYPE, Foo, bool(int n));
+  MOCK_CONST_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, Bar, int(double x, double y));
+```
+where `STDMETHODCALLTYPE` is defined by `<objbase.h>` on Windows.
+
+# Using Mocks in Tests #
+
+The typical flow is:
+  1. Import the Google Mock names you need to use. All Google Mock names are in the `testing` namespace unless they are macros or otherwise noted.
+  1. Create the mock objects.
+  1. Optionally, set the default actions of the mock objects.
+  1. Set your expectations on the mock objects (How will they be called? What wil they do?).
+  1. Exercise code that uses the mock objects; if necessary, check the result using [Google Test](http://code.google.com/p/googletest/) assertions.
+  1. When a mock objects is destructed, Google Mock automatically verifies that all expectations on it have been satisfied.
+
+Here is an example:
+```
+using ::testing::Return;                            // #1
+
+TEST(BarTest, DoesThis) {
+  MockFoo foo;                                    // #2
+
+  ON_CALL(foo, GetSize())                         // #3
+      .WillByDefault(Return(1));
+  // ... other default actions ...
+
+  EXPECT_CALL(foo, Describe(5))                   // #4
+      .Times(3)
+      .WillRepeatedly(Return("Category 5"));
+  // ... other expectations ...
+
+  EXPECT_EQ("good", MyProductionFunction(&foo));  // #5
+}                                                 // #6
+```
+
+# Setting Default Actions #
+
+Google Mock has a **built-in default action** for any function that
+returns `void`, `bool`, a numeric value, or a pointer.
+
+To customize the default action for functions with return type `T` globally:
+```
+using ::testing::DefaultValue;
+
+DefaultValue<T>::Set(value);  // Sets the default value to be returned.
+// ... use the mocks ...
+DefaultValue<T>::Clear();     // Resets the default value.
+```
+
+To customize the default action for a particular method, use `ON_CALL()`:
+```
+ON_CALL(mock_object, method(matchers))
+    .With(multi_argument_matcher)  ?
+    .WillByDefault(action);
+```
+
+# Setting Expectations #
+
+`EXPECT_CALL()` sets **expectations** on a mock method (How will it be
+called? What will it do?):
+```
+EXPECT_CALL(mock_object, method(matchers))
+    .With(multi_argument_matcher)  ?
+    .Times(cardinality)            ?
+    .InSequence(sequences)         *
+    .After(expectations)           *
+    .WillOnce(action)              *
+    .WillRepeatedly(action)        ?
+    .RetiresOnSaturation();        ?
+```
+
+If `Times()` is omitted, the cardinality is assumed to be:
+
+  * `Times(1)` when there is neither `WillOnce()` nor `WillRepeatedly()`;
+  * `Times(n)` when there are `n WillOnce()`s but no `WillRepeatedly()`, where `n` >= 1; or
+  * `Times(AtLeast(n))` when there are `n WillOnce()`s and a `WillRepeatedly()`, where `n` >= 0.
+
+A method with no `EXPECT_CALL()` is free to be invoked _any number of times_, and the default action will be taken each time.
+
+# Matchers #
+
+A **matcher** matches a _single_ argument.  You can use it inside
+`ON_CALL()` or `EXPECT_CALL()`, or use it to validate a value
+directly:
+
+| `EXPECT_THAT(value, matcher)` | Asserts that `value` matches `matcher`. |
+|:------------------------------|:----------------------------------------|
+| `ASSERT_THAT(value, matcher)` | The same as `EXPECT_THAT(value, matcher)`, except that it generates a **fatal** failure. |
+
+Built-in matchers (where `argument` is the function argument) are
+divided into several categories:
+
+## Wildcard ##
+|`_`|`argument` can be any value of the correct type.|
+|:--|:-----------------------------------------------|
+|`A<type>()` or `An<type>()`|`argument` can be any value of type `type`.     |
+
+## Generic Comparison ##
+
+|`Eq(value)` or `value`|`argument == value`|
+|:---------------------|:------------------|
+|`Ge(value)`           |`argument >= value`|
+|`Gt(value)`           |`argument > value` |
+|`Le(value)`           |`argument <= value`|
+|`Lt(value)`           |`argument < value` |
+|`Ne(value)`           |`argument != value`|
+|`IsNull()`            |`argument` is a `NULL` pointer (raw or smart).|
+|`NotNull()`           |`argument` is a non-null pointer (raw or smart).|
+|`Ref(variable)`       |`argument` is a reference to `variable`.|
+|`TypedEq<type>(value)`|`argument` has type `type` and is equal to `value`. You may need to use this instead of `Eq(value)` when the mock function is overloaded.|
+
+Except `Ref()`, these matchers make a _copy_ of `value` in case it's
+modified or destructed later. If the compiler complains that `value`
+doesn't have a public copy constructor, try wrap it in `ByRef()`,
+e.g. `Eq(ByRef(non_copyable_value))`. If you do that, make sure
+`non_copyable_value` is not changed afterwards, or the meaning of your
+matcher will be changed.
+
+## Floating-Point Matchers ##
+
+|`DoubleEq(a_double)`|`argument` is a `double` value approximately equal to `a_double`, treating two NaNs as unequal.|
+|:-------------------|:----------------------------------------------------------------------------------------------|
+|`FloatEq(a_float)`  |`argument` is a `float` value approximately equal to `a_float`, treating two NaNs as unequal.  |
+|`NanSensitiveDoubleEq(a_double)`|`argument` is a `double` value approximately equal to `a_double`, treating two NaNs as equal.  |
+|`NanSensitiveFloatEq(a_float)`|`argument` is a `float` value approximately equal to `a_float`, treating two NaNs as equal.    |
+
+The above matchers use ULP-based comparison (the same as used in
+[Google Test](http://code.google.com/p/googletest/)). They
+automatically pick a reasonable error bound based on the absolute
+value of the expected value.  `DoubleEq()` and `FloatEq()` conform to
+the IEEE standard, which requires comparing two NaNs for equality to
+return false. The `NanSensitive*` version instead treats two NaNs as
+equal, which is often what a user wants.
+
+## String Matchers ##
+
+The `argument` can be either a C string or a C++ string object:
+
+|`ContainsRegex(string)`|`argument` matches the given regular expression.|
+|:----------------------|:-----------------------------------------------|
+|`EndsWith(suffix)`     |`argument` ends with string `suffix`.           |
+|`HasSubstr(string)`    |`argument` contains `string` as a sub-string.   |
+|`MatchesRegex(string)` |`argument` matches the given regular expression with the match starting at the first character and ending at the last character.|
+|`StartsWith(prefix)`   |`argument` starts with string `prefix`.         |
+|`StrCaseEq(string)`    |`argument` is equal to `string`, ignoring case. |
+|`StrCaseNe(string)`    |`argument` is not equal to `string`, ignoring case.|
+|`StrEq(string)`        |`argument` is equal to `string`.                |
+|`StrNe(string)`        |`argument` is not equal to `string`.            |
+
+`StrCaseEq()`, `StrCaseNe()`, `StrEq()`, and `StrNe()` work for wide
+strings as well.
+
+## Container Matchers ##
+
+Most STL-style containers support `==`, so you can use
+`Eq(expected_container)` or simply `expected_container` to match a
+container exactly.   If you want to write the elements in-line,
+match them more flexibly, or get more informative messages, you can use:
+
+| `Contains(e)` | `argument` contains an element that matches `e`, which can be either a value or a matcher. |
+|:--------------|:-------------------------------------------------------------------------------------------|
+|`ElementsAre(e0, e1, ..., en)`|`argument` has `n + 1` elements, where the i-th element matches `ei`, which can be a value or a matcher. 0 to 10 arguments are allowed.|
+|`ElementsAreArray(array)` or `ElementsAreArray(array, count)`|The same as `ElementsAre()` except that the expected element values/matchers come from a C-style array.|
+| `ContainerEq(container)` | The same as `Eq(container)` except that the failure message also includes which elements are in one container but not the other. |
+
+These matchers can also match:
+
+  1. a native array passed by reference (e.g. in `Foo(const int (&a)[5])`), and
+  1. an array passed as a pointer and a count (e.g. in `Bar(const T* buffer, int len)` -- see [Multi-argument Matchers](#Multiargument_Matchers.md)).
+
+where the array may be multi-dimensional (i.e. its elements can be arrays).
+
+## Member Matchers ##
+
+|`Field(&class::field, m)`|`argument.field` (or `argument->field` when `argument` is a plain pointer) matches matcher `m`, where `argument` is an object of type _class_.|
+|:------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------|
+|`Key(e)`                 |`argument.first` matches `e`, which can be either a value or a matcher. E.g. `Contains(Key(Le(5)))` can verify that a `map` contains a key `<= 5`.|
+|`Pair(m1, m2)`           |`argument` is an `std::pair` whose `first` field matches `m1` and `second` field matches `m2`.                                                |
+|`Property(&class::property, m)`|`argument.property()` (or `argument->property()` when `argument` is a plain pointer) matches matcher `m`, where `argument` is an object of type _class_.|
+
+## Matching the Result of a Function or Functor ##
+
+|`ResultOf(f, m)`|`f(argument)` matches matcher `m`, where `f` is a function or functor.|
+|:---------------|:---------------------------------------------------------------------|
+
+## Pointer Matchers ##
+
+|`Pointee(m)`|`argument` (either a smart pointer or a raw pointer) points to a value that matches matcher `m`.|
+|:-----------|:-----------------------------------------------------------------------------------------------|
+
+## Multiargument Matchers ##
+
+These are matchers on tuple types. They can be used in
+`.With()`. The following can be used on functions with <i>two<br>
+arguments</i> `x` and `y`:
+
+|`Eq()`|`x == y`|
+|:-----|:-------|
+|`Ge()`|`x >= y`|
+|`Gt()`|`x > y` |
+|`Le()`|`x <= y`|
+|`Lt()`|`x < y` |
+|`Ne()`|`x != y`|
+
+You can use the following selectors to pick a subset of the arguments
+(or reorder them) to participate in the matching:
+
+|`AllArgs(m)`|Equivalent to `m`. Useful as syntactic sugar in `.With(AllArgs(m))`.|
+|:-----------|:-------------------------------------------------------------------|
+|`Args<N1, N2, ..., Nk>(m)`|The `k` selected (using 0-based indices) arguments match `m`, e.g. `Args<1, 2>(Contains(5))`.|
+
+## Composite Matchers ##
+
+You can make a matcher from one or more other matchers:
+
+|`AllOf(m1, m2, ..., mn)`|`argument` matches all of the matchers `m1` to `mn`.|
+|:-----------------------|:---------------------------------------------------|
+|`AnyOf(m1, m2, ..., mn)`|`argument` matches at least one of the matchers `m1` to `mn`.|
+|`Not(m)`                |`argument` doesn't match matcher `m`.               |
+
+## Adapters for Matchers ##
+
+|`MatcherCast<T>(m)`|casts matcher `m` to type `Matcher<T>`.|
+|:------------------|:--------------------------------------|
+|`SafeMatcherCast<T>(m)`| [safely casts](V1_5_CookBook#Casting_Matchers.md) matcher `m` to type `Matcher<T>`. |
+|`Truly(predicate)` |`predicate(argument)` returns something considered by C++ to be true, where `predicate` is a function or functor.|
+
+## Matchers as Predicates ##
+
+|`Matches(m)`|a unary functor that returns `true` if the argument matches `m`.|
+|:-----------|:---------------------------------------------------------------|
+|`ExplainMatchResult(m, value, result_listener)`|returns `true` if `value` matches `m`, explaining the result to `result_listener`.|
+|`Value(x, m)`|returns `true` if the value of `x` matches `m`.                 |
+
+## Defining Matchers ##
+
+| `MATCHER(IsEven, "") { return (arg % 2) == 0; }` | Defines a matcher `IsEven()` to match an even number. |
+|:-------------------------------------------------|:------------------------------------------------------|
+| `MATCHER_P(IsDivisibleBy, n, "") { *result_listener << "where the remainder is " << (arg % n); return (arg % n) == 0; }` | Defines a macher `IsDivisibleBy(n)` to match a number divisible by `n`. |
+| `MATCHER_P2(IsBetween, a, b, "is between %(a)s and %(b)s") { return a <= arg && arg <= b; }` | Defines a matcher `IsBetween(a, b)` to match a value in the range [`a`, `b`]. |
+
+**Notes:**
+
+  1. The `MATCHER*` macros cannot be used inside a function or class.
+  1. The matcher body must be _purely functional_ (i.e. it cannot have any side effect, and the result must not depend on anything other than the value being matched and the matcher parameters).
+  1. You can use `PrintToString(x)` to convert a value `x` of any type to a string.
+
+## Matchers as Test Assertions ##
+
+|`ASSERT_THAT(expression, m)`|Generates a [fatal failure](http://code.google.com/p/googletest/wiki/GoogleTestPrimer#Assertions) if the value of `expression` doesn't match matcher `m`.|
+|:---------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------|
+|`EXPECT_THAT(expression, m)`|Generates a non-fatal failure if the value of `expression` doesn't match matcher `m`.                                                                    |
+
+# Actions #
+
+**Actions** specify what a mock function should do when invoked.
+
+## Returning a Value ##
+
+|`Return()`|Return from a `void` mock function.|
+|:---------|:----------------------------------|
+|`Return(value)`|Return `value`.                    |
+|`ReturnArg<N>()`|Return the `N`-th (0-based) argument.|
+|`ReturnNew<T>(a1, ..., ak)`|Return `new T(a1, ..., ak)`; a different object is created each time.|
+|`ReturnNull()`|Return a null pointer.             |
+|`ReturnRef(variable)`|Return a reference to `variable`.  |
+
+## Side Effects ##
+
+|`Assign(&variable, value)`|Assign `value` to variable.|
+|:-------------------------|:--------------------------|
+| `DeleteArg<N>()`         | Delete the `N`-th (0-based) argument, which must be a pointer. |
+| `SaveArg<N>(pointer)`    | Save the `N`-th (0-based) argument to `*pointer`. |
+| `SetArgReferee<N>(value)` |	Assign value to the variable referenced by the `N`-th (0-based) argument. |
+|`SetArgumentPointee<N>(value)`|Assign `value` to the variable pointed by the `N`-th (0-based) argument.|
+|`SetArrayArgument<N>(first, last)`|Copies the elements in source range [`first`, `last`) to the array pointed to by the `N`-th (0-based) argument, which can be either a pointer or an iterator. The action does not take ownership of the elements in the source range.|
+|`SetErrnoAndReturn(error, value)`|Set `errno` to `error` and return `value`.|
+|`Throw(exception)`        |Throws the given exception, which can be any copyable value. Available since v1.1.0.|
+
+## Using a Function or a Functor as an Action ##
+
+|`Invoke(f)`|Invoke `f` with the arguments passed to the mock function, where `f` can be a global/static function or a functor.|
+|:----------|:-----------------------------------------------------------------------------------------------------------------|
+|`Invoke(object_pointer, &class::method)`|Invoke the {method on the object with the arguments passed to the mock function.                                  |
+|`InvokeWithoutArgs(f)`|Invoke `f`, which can be a global/static function or a functor. `f` must take no arguments.                       |
+|`InvokeWithoutArgs(object_pointer, &class::method)`|Invoke the method on the object, which takes no arguments.                                                        |
+|`InvokeArgument<N>(arg1, arg2, ..., argk)`|Invoke the mock function's `N`-th (0-based) argument, which must be a function or a functor, with the `k` arguments.|
+
+The return value of the invoked function is used as the return value
+of the action.
+
+When defining a function or functor to be used with `Invoke*()`, you can declare any unused parameters as `Unused`:
+```
+  double Distance(Unused, double x, double y) { return sqrt(x*x + y*y); }
+  ...
+  EXPECT_CALL(mock, Foo("Hi", _, _)).WillOnce(Invoke(Distance));
+```
+
+In `InvokeArgument<N>(...)`, if an argument needs to be passed by reference, wrap it inside `ByRef()`. For example,
+```
+  InvokeArgument<2>(5, string("Hi"), ByRef(foo))
+```
+calls the mock function's #2 argument, passing to it `5` and `string("Hi")` by value, and `foo` by reference.
+
+## Default Action ##
+
+|`DoDefault()`|Do the default action (specified by `ON_CALL()` or the built-in one).|
+|:------------|:--------------------------------------------------------------------|
+
+**Note:** due to technical reasons, `DoDefault()` cannot be used inside  a composite action - trying to do so will result in a run-time error.
+
+## Composite Actions ##
+
+|`DoAll(a1, a2, ..., an)`|Do all actions `a1` to `an` and return the result of `an` in each invocation. The first `n - 1` sub-actions must return void. |
+|:-----------------------|:-----------------------------------------------------------------------------------------------------------------------------|
+|`IgnoreResult(a)`       |Perform action `a` and ignore its result. `a` must not return void.                                                           |
+|`WithArg<N>(a)`         |Pass the `N`-th (0-based) argument of the mock function to action `a` and perform it.                                         |
+|`WithArgs<N1, N2, ..., Nk>(a)`|Pass the selected (0-based) arguments of the mock function to action `a` and perform it.                                      |
+|`WithoutArgs(a)`        |Perform action `a` without any arguments.                                                                                     |
+
+## Defining Actions ##
+
+| `ACTION(Sum) { return arg0 + arg1; }` | Defines an action `Sum()` to return the sum of the mock function's argument #0 and #1. |
+|:--------------------------------------|:---------------------------------------------------------------------------------------|
+| `ACTION_P(Plus, n) { return arg0 + n; }` | Defines an action `Plus(n)` to return the sum of the mock function's argument #0 and `n`. |
+| `ACTION_Pk(Foo, p1, ..., pk) { statements; }` | Defines a parameterized action `Foo(p1, ..., pk)` to execute the given `statements`.   |
+
+The `ACTION*` macros cannot be used inside a function or class.
+
+# Cardinalities #
+
+These are used in `Times()` to specify how many times a mock function will be called:
+
+|`AnyNumber()`|The function can be called any number of times.|
+|:------------|:----------------------------------------------|
+|`AtLeast(n)` |The call is expected at least `n` times.       |
+|`AtMost(n)`  |The call is expected at most `n` times.        |
+|`Between(m, n)`|The call is expected between `m` and `n` (inclusive) times.|
+|`Exactly(n) or n`|The call is expected exactly `n` times. In particular, the call should never happen when `n` is 0.|
+
+# Expectation Order #
+
+By default, the expectations can be matched in _any_ order.  If some
+or all expectations must be matched in a given order, there are two
+ways to specify it.  They can be used either independently or
+together.
+
+## The After Clause ##
+
+```
+using ::testing::Expectation;
+...
+Expectation init_x = EXPECT_CALL(foo, InitX());
+Expectation init_y = EXPECT_CALL(foo, InitY());
+EXPECT_CALL(foo, Bar())
+    .After(init_x, init_y);
+```
+says that `Bar()` can be called only after both `InitX()` and
+`InitY()` have been called.
+
+If you don't know how many pre-requisites an expectation has when you
+write it, you can use an `ExpectationSet` to collect them:
+
+```
+using ::testing::ExpectationSet;
+...
+ExpectationSet all_inits;
+for (int i = 0; i < element_count; i++) {
+  all_inits += EXPECT_CALL(foo, InitElement(i));
+}
+EXPECT_CALL(foo, Bar())
+    .After(all_inits);
+```
+says that `Bar()` can be called only after all elements have been
+initialized (but we don't care about which elements get initialized
+before the others).
+
+Modifying an `ExpectationSet` after using it in an `.After()` doesn't
+affect the meaning of the `.After()`.
+
+## Sequences ##
+
+When you have a long chain of sequential expectations, it's easier to
+specify the order using **sequences**, which don't require you to given
+each expectation in the chain a different name.  <i>All expected<br>
+calls</i> in the same sequence must occur in the order they are
+specified.
+
+```
+using ::testing::Sequence;
+Sequence s1, s2;
+...
+EXPECT_CALL(foo, Reset())
+    .InSequence(s1, s2)
+    .WillOnce(Return(true));
+EXPECT_CALL(foo, GetSize())
+    .InSequence(s1)
+    .WillOnce(Return(1));
+EXPECT_CALL(foo, Describe(A<const char*>()))
+    .InSequence(s2)
+    .WillOnce(Return("dummy"));
+```
+says that `Reset()` must be called before _both_ `GetSize()` _and_
+`Describe()`, and the latter two can occur in any order.
+
+To put many expectations in a sequence conveniently:
+```
+using ::testing::InSequence;
+{
+  InSequence dummy;
+
+  EXPECT_CALL(...)...;
+  EXPECT_CALL(...)...;
+  ...
+  EXPECT_CALL(...)...;
+}
+```
+says that all expected calls in the scope of `dummy` must occur in
+strict order. The name `dummy` is irrelevant.)
+
+# Verifying and Resetting a Mock #
+
+Google Mock will verify the expectations on a mock object when it is destructed, or you can do it earlier:
+```
+using ::testing::Mock;
+...
+// Verifies and removes the expectations on mock_obj;
+// returns true iff successful.
+Mock::VerifyAndClearExpectations(&mock_obj);
+...
+// Verifies and removes the expectations on mock_obj;
+// also removes the default actions set by ON_CALL();
+// returns true iff successful.
+Mock::VerifyAndClear(&mock_obj);
+```
+
+You can also tell Google Mock that a mock object can be leaked and doesn't
+need to be verified:
+```
+Mock::AllowLeak(&mock_obj);
+```
+
+# Mock Classes #
+
+Google Mock defines a convenient mock class template
+```
+class MockFunction<R(A1, ..., An)> {
+ public:
+  MOCK_METHODn(Call, R(A1, ..., An));
+};
+```
+See this [recipe](V1_5_CookBook#Using_Check_Points.md) for one application of it.
+
+# Flags #
+
+| `--gmock_catch_leaked_mocks=0` | Don't report leaked mock objects as failures. |
+|:-------------------------------|:----------------------------------------------|
+| `--gmock_verbose=LEVEL`        | Sets the default verbosity level (`info`, `warning`, or `error`) of Google Mock messages. |
\ No newline at end of file
diff --git a/third_party/googletest/googlemock/docs/v1_5/CookBook.md b/third_party/googletest/googlemock/docs/v1_5/CookBook.md
new file mode 100644
index 0000000..26e153c
--- /dev/null
+++ b/third_party/googletest/googlemock/docs/v1_5/CookBook.md
@@ -0,0 +1,3250 @@
+
+
+You can find recipes for using Google Mock here. If you haven't yet,
+please read the [ForDummies](V1_5_ForDummies.md) document first to make sure you understand
+the basics.
+
+**Note:** Google Mock lives in the `testing` name space. For
+readability, it is recommended to write `using ::testing::Foo;` once in
+your file before using the name `Foo` defined by Google Mock. We omit
+such `using` statements in this page for brevity, but you should do it
+in your own code.
+
+# Creating Mock Classes #
+
+## Mocking Private or Protected Methods ##
+
+You must always put a mock method definition (`MOCK_METHOD*`) in a
+`public:` section of the mock class, regardless of the method being
+mocked being `public`, `protected`, or `private` in the base class.
+This allows `ON_CALL` and `EXPECT_CALL` to reference the mock function
+from outside of the mock class.  (Yes, C++ allows a subclass to change
+the access level of a virtual function in the base class.)  Example:
+
+```
+class Foo {
+ public:
+  ...
+  virtual bool Transform(Gadget* g) = 0;
+
+ protected:
+  virtual void Resume();
+
+ private:
+  virtual int GetTimeOut();
+};
+
+class MockFoo : public Foo {
+ public:
+  ...
+  MOCK_METHOD1(Transform, bool(Gadget* g));
+
+  // The following must be in the public section, even though the
+  // methods are protected or private in the base class.
+  MOCK_METHOD0(Resume, void());
+  MOCK_METHOD0(GetTimeOut, int());
+};
+```
+
+## Mocking Overloaded Methods ##
+
+You can mock overloaded functions as usual. No special attention is required:
+
+```
+class Foo {
+  ...
+
+  // Must be virtual as we'll inherit from Foo.
+  virtual ~Foo();
+
+  // Overloaded on the types and/or numbers of arguments.
+  virtual int Add(Element x);
+  virtual int Add(int times, Element x);
+
+  // Overloaded on the const-ness of this object.
+  virtual Bar& GetBar();
+  virtual const Bar& GetBar() const;
+};
+
+class MockFoo : public Foo {
+  ...
+  MOCK_METHOD1(Add, int(Element x));
+  MOCK_METHOD2(Add, int(int times, Element x);
+
+  MOCK_METHOD0(GetBar, Bar&());
+  MOCK_CONST_METHOD0(GetBar, const Bar&());
+};
+```
+
+**Note:** if you don't mock all versions of the overloaded method, the
+compiler will give you a warning about some methods in the base class
+being hidden. To fix that, use `using` to bring them in scope:
+
+```
+class MockFoo : public Foo {
+  ...
+  using Foo::Add;
+  MOCK_METHOD1(Add, int(Element x));
+  // We don't want to mock int Add(int times, Element x);
+  ...
+};
+```
+
+## Mocking Class Templates ##
+
+To mock a class template, append `_T` to the `MOCK_*` macros:
+
+```
+template <typename Elem>
+class StackInterface {
+  ...
+  // Must be virtual as we'll inherit from StackInterface.
+  virtual ~StackInterface();
+
+  virtual int GetSize() const = 0;
+  virtual void Push(const Elem& x) = 0;
+};
+
+template <typename Elem>
+class MockStack : public StackInterface<Elem> {
+  ...
+  MOCK_CONST_METHOD0_T(GetSize, int());
+  MOCK_METHOD1_T(Push, void(const Elem& x));
+};
+```
+
+## Mocking Nonvirtual Methods ##
+
+Google Mock can mock non-virtual functions to be used in what we call _hi-perf
+dependency injection_.
+
+In this case, instead of sharing a common base class with the real
+class, your mock class will be _unrelated_ to the real class, but
+contain methods with the same signatures.  The syntax for mocking
+non-virtual methods is the _same_ as mocking virtual methods:
+
+```
+// A simple packet stream class.  None of its members is virtual.
+class ConcretePacketStream {
+ public:
+  void AppendPacket(Packet* new_packet);
+  const Packet* GetPacket(size_t packet_number) const;
+  size_t NumberOfPackets() const;
+  ...
+};
+
+// A mock packet stream class.  It inherits from no other, but defines
+// GetPacket() and NumberOfPackets().
+class MockPacketStream {
+ public:
+  MOCK_CONST_METHOD1(GetPacket, const Packet*(size_t packet_number));
+  MOCK_CONST_METHOD0(NumberOfPackets, size_t());
+  ...
+};
+```
+
+Note that the mock class doesn't define `AppendPacket()`, unlike the
+real class. That's fine as long as the test doesn't need to call it.
+
+Next, you need a way to say that you want to use
+`ConcretePacketStream` in production code, and use `MockPacketStream`
+in tests.  Since the functions are not virtual and the two classes are
+unrelated, you must specify your choice at _compile time_ (as opposed
+to run time).
+
+One way to do it is to templatize your code that needs to use a packet
+stream.  More specifically, you will give your code a template type
+argument for the type of the packet stream.  In production, you will
+instantiate your template with `ConcretePacketStream` as the type
+argument.  In tests, you will instantiate the same template with
+`MockPacketStream`.  For example, you may write:
+
+```
+template <class PacketStream>
+void CreateConnection(PacketStream* stream) { ... }
+
+template <class PacketStream>
+class PacketReader {
+ public:
+  void ReadPackets(PacketStream* stream, size_t packet_num);
+};
+```
+
+Then you can use `CreateConnection<ConcretePacketStream>()` and
+`PacketReader<ConcretePacketStream>` in production code, and use
+`CreateConnection<MockPacketStream>()` and
+`PacketReader<MockPacketStream>` in tests.
+
+```
+  MockPacketStream mock_stream;
+  EXPECT_CALL(mock_stream, ...)...;
+  .. set more expectations on mock_stream ...
+  PacketReader<MockPacketStream> reader(&mock_stream);
+  ... exercise reader ...
+```
+
+## Mocking Free Functions ##
+
+It's possible to use Google Mock to mock a free function (i.e. a
+C-style function or a static method).  You just need to rewrite your
+code to use an interface (abstract class).
+
+Instead of calling a free function (say, `OpenFile`) directly,
+introduce an interface for it and have a concrete subclass that calls
+the free function:
+
+```
+class FileInterface {
+ public:
+  ...
+  virtual bool Open(const char* path, const char* mode) = 0;
+};
+
+class File : public FileInterface {
+ public:
+  ...
+  virtual bool Open(const char* path, const char* mode) {
+    return OpenFile(path, mode);
+  }
+};
+```
+
+Your code should talk to `FileInterface` to open a file.  Now it's
+easy to mock out the function.
+
+This may seem much hassle, but in practice you often have multiple
+related functions that you can put in the same interface, so the
+per-function syntactic overhead will be much lower.
+
+If you are concerned about the performance overhead incurred by
+virtual functions, and profiling confirms your concern, you can
+combine this with the recipe for [mocking non-virtual methods](#Mocking_Nonvirtual_Methods.md).
+
+## Nice Mocks and Strict Mocks ##
+
+If a mock method has no `EXPECT_CALL` spec but is called, Google Mock
+will print a warning about the "uninteresting call". The rationale is:
+
+  * New methods may be added to an interface after a test is written. We shouldn't fail a test just because a method it doesn't know about is called.
+  * However, this may also mean there's a bug in the test, so Google Mock shouldn't be silent either. If the user believes these calls are harmless, he can add an `EXPECT_CALL()` to suppress the warning.
+
+However, sometimes you may want to suppress all "uninteresting call"
+warnings, while sometimes you may want the opposite, i.e. to treat all
+of them as errors. Google Mock lets you make the decision on a
+per-mock-object basis.
+
+Suppose your test uses a mock class `MockFoo`:
+
+```
+TEST(...) {
+  MockFoo mock_foo;
+  EXPECT_CALL(mock_foo, DoThis());
+  ... code that uses mock_foo ...
+}
+```
+
+If a method of `mock_foo` other than `DoThis()` is called, it will be
+reported by Google Mock as a warning. However, if you rewrite your
+test to use `NiceMock<MockFoo>` instead, the warning will be gone,
+resulting in a cleaner test output:
+
+```
+using ::testing::NiceMock;
+
+TEST(...) {
+  NiceMock<MockFoo> mock_foo;
+  EXPECT_CALL(mock_foo, DoThis());
+  ... code that uses mock_foo ...
+}
+```
+
+`NiceMock<MockFoo>` is a subclass of `MockFoo`, so it can be used
+wherever `MockFoo` is accepted.
+
+It also works if `MockFoo`'s constructor takes some arguments, as
+`NiceMock<MockFoo>` "inherits" `MockFoo`'s constructors:
+
+```
+using ::testing::NiceMock;
+
+TEST(...) {
+  NiceMock<MockFoo> mock_foo(5, "hi");  // Calls MockFoo(5, "hi").
+  EXPECT_CALL(mock_foo, DoThis());
+  ... code that uses mock_foo ...
+}
+```
+
+The usage of `StrictMock` is similar, except that it makes all
+uninteresting calls failures:
+
+```
+using ::testing::StrictMock;
+
+TEST(...) {
+  StrictMock<MockFoo> mock_foo;
+  EXPECT_CALL(mock_foo, DoThis());
+  ... code that uses mock_foo ...
+
+  // The test will fail if a method of mock_foo other than DoThis()
+  // is called.
+}
+```
+
+There are some caveats though (I don't like them just as much as the
+next guy, but sadly they are side effects of C++'s limitations):
+
+  1. `NiceMock<MockFoo>` and `StrictMock<MockFoo>` only work for mock methods defined using the `MOCK_METHOD*` family of macros **directly** in the `MockFoo` class. If a mock method is defined in a **base class** of `MockFoo`, the "nice" or "strict" modifier may not affect it, depending on the compiler. In particular, nesting `NiceMock` and `StrictMock` (e.g. `NiceMock<StrictMock<MockFoo> >`) is **not** supported.
+  1. The constructors of the base mock (`MockFoo`) cannot have arguments passed by non-const reference, which happens to be banned by the [Google C++ style guide](http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml).
+  1. During the constructor or destructor of `MockFoo`, the mock object is _not_ nice or strict.  This may cause surprises if the constructor or destructor calls a mock method on `this` object. (This behavior, however, is consistent with C++'s general rule: if a constructor or destructor calls a virtual method of `this` object, that method is treated as non-virtual.  In other words, to the base class's constructor or destructor, `this` object behaves like an instance of the base class, not the derived class.  This rule is required for safety.  Otherwise a base constructor may use members of a derived class before they are initialized, or a base destructor may use members of a derived class after they have been destroyed.)
+
+Finally, you should be **very cautious** when using this feature, as the
+decision you make applies to **all** future changes to the mock
+class. If an important change is made in the interface you are mocking
+(and thus in the mock class), it could break your tests (if you use
+`StrictMock`) or let bugs pass through without a warning (if you use
+`NiceMock`). Therefore, try to specify the mock's behavior using
+explicit `EXPECT_CALL` first, and only turn to `NiceMock` or
+`StrictMock` as the last resort.
+
+## Simplifying the Interface without Breaking Existing Code ##
+
+Sometimes a method has a long list of arguments that is mostly
+uninteresting. For example,
+
+```
+class LogSink {
+ public:
+  ...
+  virtual void send(LogSeverity severity, const char* full_filename,
+                    const char* base_filename, int line,
+                    const struct tm* tm_time,
+                    const char* message, size_t message_len) = 0;
+};
+```
+
+This method's argument list is lengthy and hard to work with (let's
+say that the `message` argument is not even 0-terminated). If we mock
+it as is, using the mock will be awkward. If, however, we try to
+simplify this interface, we'll need to fix all clients depending on
+it, which is often infeasible.
+
+The trick is to re-dispatch the method in the mock class:
+
+```
+class ScopedMockLog : public LogSink {
+ public:
+  ...
+  virtual void send(LogSeverity severity, const char* full_filename,
+                    const char* base_filename, int line, const tm* tm_time,
+                    const char* message, size_t message_len) {
+    // We are only interested in the log severity, full file name, and
+    // log message.
+    Log(severity, full_filename, std::string(message, message_len));
+  }
+
+  // Implements the mock method:
+  //
+  //   void Log(LogSeverity severity,
+  //            const string& file_path,
+  //            const string& message);
+  MOCK_METHOD3(Log, void(LogSeverity severity, const string& file_path,
+                         const string& message));
+};
+```
+
+By defining a new mock method with a trimmed argument list, we make
+the mock class much more user-friendly.
+
+## Alternative to Mocking Concrete Classes ##
+
+Often you may find yourself using classes that don't implement
+interfaces. In order to test your code that uses such a class (let's
+call it `Concrete`), you may be tempted to make the methods of
+`Concrete` virtual and then mock it.
+
+Try not to do that.
+
+Making a non-virtual function virtual is a big decision. It creates an
+extension point where subclasses can tweak your class' behavior. This
+weakens your control on the class because now it's harder to maintain
+the class' invariants. You should make a function virtual only when
+there is a valid reason for a subclass to override it.
+
+Mocking concrete classes directly is problematic as it creates a tight
+coupling between the class and the tests - any small change in the
+class may invalidate your tests and make test maintenance a pain.
+
+To avoid such problems, many programmers have been practicing "coding
+to interfaces": instead of talking to the `Concrete` class, your code
+would define an interface and talk to it. Then you implement that
+interface as an adaptor on top of `Concrete`. In tests, you can easily
+mock that interface to observe how your code is doing.
+
+This technique incurs some overhead:
+
+  * You pay the cost of virtual function calls (usually not a problem).
+  * There is more abstraction for the programmers to learn.
+
+However, it can also bring significant benefits in addition to better
+testability:
+
+  * `Concrete`'s API may not fit your problem domain very well, as you may not be the only client it tries to serve. By designing your own interface, you have a chance to tailor it to your need - you may add higher-level functionalities, rename stuff, etc instead of just trimming the class. This allows you to write your code (user of the interface) in a more natural way, which means it will be more readable, more maintainable, and you'll be more productive.
+  * If `Concrete`'s implementation ever has to change, you don't have to rewrite everywhere it is used. Instead, you can absorb the change in your implementation of the interface, and your other code and tests will be insulated from this change.
+
+Some people worry that if everyone is practicing this technique, they
+will end up writing lots of redundant code. This concern is totally
+understandable. However, there are two reasons why it may not be the
+case:
+
+  * Different projects may need to use `Concrete` in different ways, so the best interfaces for them will be different. Therefore, each of them will have its own domain-specific interface on top of `Concrete`, and they will not be the same code.
+  * If enough projects want to use the same interface, they can always share it, just like they have been sharing `Concrete`. You can check in the interface and the adaptor somewhere near `Concrete` (perhaps in a `contrib` sub-directory) and let many projects use it.
+
+You need to weigh the pros and cons carefully for your particular
+problem, but I'd like to assure you that the Java community has been
+practicing this for a long time and it's a proven effective technique
+applicable in a wide variety of situations. :-)
+
+## Delegating Calls to a Fake ##
+
+Some times you have a non-trivial fake implementation of an
+interface. For example:
+
+```
+class Foo {
+ public:
+  virtual ~Foo() {}
+  virtual char DoThis(int n) = 0;
+  virtual void DoThat(const char* s, int* p) = 0;
+};
+
+class FakeFoo : public Foo {
+ public:
+  virtual char DoThis(int n) {
+    return (n > 0) ? '+' :
+        (n < 0) ? '-' : '0';
+  }
+
+  virtual void DoThat(const char* s, int* p) {
+    *p = strlen(s);
+  }
+};
+```
+
+Now you want to mock this interface such that you can set expectations
+on it. However, you also want to use `FakeFoo` for the default
+behavior, as duplicating it in the mock object is, well, a lot of
+work.
+
+When you define the mock class using Google Mock, you can have it
+delegate its default action to a fake class you already have, using
+this pattern:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+
+class MockFoo : public Foo {
+ public:
+  // Normal mock method definitions using Google Mock.
+  MOCK_METHOD1(DoThis, char(int n));
+  MOCK_METHOD2(DoThat, void(const char* s, int* p));
+
+  // Delegates the default actions of the methods to a FakeFoo object.
+  // This must be called *before* the custom ON_CALL() statements.
+  void DelegateToFake() {
+    ON_CALL(*this, DoThis(_))
+        .WillByDefault(Invoke(&fake_, &FakeFoo::DoThis));
+    ON_CALL(*this, DoThat(_, _))
+        .WillByDefault(Invoke(&fake_, &FakeFoo::DoThat));
+  }
+ private:
+  FakeFoo fake_;  // Keeps an instance of the fake in the mock.
+};
+```
+
+With that, you can use `MockFoo` in your tests as usual. Just remember
+that if you don't explicitly set an action in an `ON_CALL()` or
+`EXPECT_CALL()`, the fake will be called upon to do it:
+
+```
+using ::testing::_;
+
+TEST(AbcTest, Xyz) {
+  MockFoo foo;
+  foo.DelegateToFake(); // Enables the fake for delegation.
+
+  // Put your ON_CALL(foo, ...)s here, if any.
+
+  // No action specified, meaning to use the default action.
+  EXPECT_CALL(foo, DoThis(5));
+  EXPECT_CALL(foo, DoThat(_, _));
+
+  int n = 0;
+  EXPECT_EQ('+', foo.DoThis(5));  // FakeFoo::DoThis() is invoked.
+  foo.DoThat("Hi", &n);           // FakeFoo::DoThat() is invoked.
+  EXPECT_EQ(2, n);
+}
+```
+
+**Some tips:**
+
+  * If you want, you can still override the default action by providing your own `ON_CALL()` or using `.WillOnce()` / `.WillRepeatedly()` in `EXPECT_CALL()`.
+  * In `DelegateToFake()`, you only need to delegate the methods whose fake implementation you intend to use.
+  * The general technique discussed here works for overloaded methods, but you'll need to tell the compiler which version you mean. To disambiguate a mock function (the one you specify inside the parentheses of `ON_CALL()`), see the "Selecting Between Overloaded Functions" section on this page; to disambiguate a fake function (the one you place inside `Invoke()`), use a `static_cast` to specify the function's type.
+  * Having to mix a mock and a fake is often a sign of something gone wrong. Perhaps you haven't got used to the interaction-based way of testing yet. Or perhaps your interface is taking on too many roles and should be split up. Therefore, **don't abuse this**. We would only recommend to do it as an intermediate step when you are refactoring your code.
+
+Regarding the tip on mixing a mock and a fake, here's an example on
+why it may be a bad sign: Suppose you have a class `System` for
+low-level system operations. In particular, it does file and I/O
+operations. And suppose you want to test how your code uses `System`
+to do I/O, and you just want the file operations to work normally. If
+you mock out the entire `System` class, you'll have to provide a fake
+implementation for the file operation part, which suggests that
+`System` is taking on too many roles.
+
+Instead, you can define a `FileOps` interface and an `IOOps` interface
+and split `System`'s functionalities into the two. Then you can mock
+`IOOps` without mocking `FileOps`.
+
+## Delegating Calls to a Real Object ##
+
+When using testing doubles (mocks, fakes, stubs, and etc), sometimes
+their behaviors will differ from those of the real objects. This
+difference could be either intentional (as in simulating an error such
+that you can test the error handling code) or unintentional. If your
+mocks have different behaviors than the real objects by mistake, you
+could end up with code that passes the tests but fails in production.
+
+You can use the _delegating-to-real_ technique to ensure that your
+mock has the same behavior as the real object while retaining the
+ability to validate calls. This technique is very similar to the
+delegating-to-fake technique, the difference being that we use a real
+object instead of a fake. Here's an example:
+
+```
+using ::testing::_;
+using ::testing::AtLeast;
+using ::testing::Invoke;
+
+class MockFoo : public Foo {
+ public:
+  MockFoo() {
+    // By default, all calls are delegated to the real object.
+    ON_CALL(*this, DoThis())
+        .WillByDefault(Invoke(&real_, &Foo::DoThis));
+    ON_CALL(*this, DoThat(_))
+        .WillByDefault(Invoke(&real_, &Foo::DoThat));
+    ...
+  }
+  MOCK_METHOD0(DoThis, ...);
+  MOCK_METHOD1(DoThat, ...);
+  ...
+ private:
+  Foo real_;
+};
+...
+
+  MockFoo mock;
+
+  EXPECT_CALL(mock, DoThis())
+      .Times(3);
+  EXPECT_CALL(mock, DoThat("Hi"))
+      .Times(AtLeast(1));
+  ... use mock in test ...
+```
+
+With this, Google Mock will verify that your code made the right calls
+(with the right arguments, in the right order, called the right number
+of times, etc), and a real object will answer the calls (so the
+behavior will be the same as in production). This gives you the best
+of both worlds.
+
+## Delegating Calls to a Parent Class ##
+
+Ideally, you should code to interfaces, whose methods are all pure
+virtual. In reality, sometimes you do need to mock a virtual method
+that is not pure (i.e, it already has an implementation). For example:
+
+```
+class Foo {
+ public:
+  virtual ~Foo();
+
+  virtual void Pure(int n) = 0;
+  virtual int Concrete(const char* str) { ... }
+};
+
+class MockFoo : public Foo {
+ public:
+  // Mocking a pure method.
+  MOCK_METHOD1(Pure, void(int n));
+  // Mocking a concrete method.  Foo::Concrete() is shadowed.
+  MOCK_METHOD1(Concrete, int(const char* str));
+};
+```
+
+Sometimes you may want to call `Foo::Concrete()` instead of
+`MockFoo::Concrete()`. Perhaps you want to do it as part of a stub
+action, or perhaps your test doesn't need to mock `Concrete()` at all
+(but it would be oh-so painful to have to define a new mock class
+whenever you don't need to mock one of its methods).
+
+The trick is to leave a back door in your mock class for accessing the
+real methods in the base class:
+
+```
+class MockFoo : public Foo {
+ public:
+  // Mocking a pure method.
+  MOCK_METHOD1(Pure, void(int n));
+  // Mocking a concrete method.  Foo::Concrete() is shadowed.
+  MOCK_METHOD1(Concrete, int(const char* str));
+
+  // Use this to call Concrete() defined in Foo.
+  int FooConcrete(const char* str) { return Foo::Concrete(str); }
+};
+```
+
+Now, you can call `Foo::Concrete()` inside an action by:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+...
+  EXPECT_CALL(foo, Concrete(_))
+      .WillOnce(Invoke(&foo, &MockFoo::FooConcrete));
+```
+
+or tell the mock object that you don't want to mock `Concrete()`:
+
+```
+using ::testing::Invoke;
+...
+  ON_CALL(foo, Concrete(_))
+      .WillByDefault(Invoke(&foo, &MockFoo::FooConcrete));
+```
+
+(Why don't we just write `Invoke(&foo, &Foo::Concrete)`? If you do
+that, `MockFoo::Concrete()` will be called (and cause an infinite
+recursion) since `Foo::Concrete()` is virtual. That's just how C++
+works.)
+
+# Using Matchers #
+
+## Matching Argument Values Exactly ##
+
+You can specify exactly which arguments a mock method is expecting:
+
+```
+using ::testing::Return;
+...
+  EXPECT_CALL(foo, DoThis(5))
+      .WillOnce(Return('a'));
+  EXPECT_CALL(foo, DoThat("Hello", bar));
+```
+
+## Using Simple Matchers ##
+
+You can use matchers to match arguments that have a certain property:
+
+```
+using ::testing::Ge;
+using ::testing::NotNull;
+using ::testing::Return;
+...
+  EXPECT_CALL(foo, DoThis(Ge(5)))  // The argument must be >= 5.
+      .WillOnce(Return('a'));
+  EXPECT_CALL(foo, DoThat("Hello", NotNull()));
+  // The second argument must not be NULL.
+```
+
+A frequently used matcher is `_`, which matches anything:
+
+```
+using ::testing::_;
+using ::testing::NotNull;
+...
+  EXPECT_CALL(foo, DoThat(_, NotNull()));
+```
+
+## Combining Matchers ##
+
+You can build complex matchers from existing ones using `AllOf()`,
+`AnyOf()`, and `Not()`:
+
+```
+using ::testing::AllOf;
+using ::testing::Gt;
+using ::testing::HasSubstr;
+using ::testing::Ne;
+using ::testing::Not;
+...
+  // The argument must be > 5 and != 10.
+  EXPECT_CALL(foo, DoThis(AllOf(Gt(5),
+                                Ne(10))));
+
+  // The first argument must not contain sub-string "blah".
+  EXPECT_CALL(foo, DoThat(Not(HasSubstr("blah")),
+                          NULL));
+```
+
+## Casting Matchers ##
+
+Google Mock matchers are statically typed, meaning that the compiler
+can catch your mistake if you use a matcher of the wrong type (for
+example, if you use `Eq(5)` to match a `string` argument). Good for
+you!
+
+Sometimes, however, you know what you're doing and want the compiler
+to give you some slack. One example is that you have a matcher for
+`long` and the argument you want to match is `int`. While the two
+types aren't exactly the same, there is nothing really wrong with
+using a `Matcher<long>` to match an `int` - after all, we can first
+convert the `int` argument to a `long` before giving it to the
+matcher.
+
+To support this need, Google Mock gives you the
+`SafeMatcherCast<T>(m)` function. It casts a matcher `m` to type
+`Matcher<T>`. To ensure safety, Google Mock checks that (let `U` be the
+type `m` accepts):
+
+  1. Type `T` can be implicitly cast to type `U`;
+  1. When both `T` and `U` are built-in arithmetic types (`bool`, integers, and floating-point numbers), the conversion from `T` to `U` is not lossy (in other words, any value representable by `T` can also be represented by `U`); and
+  1. When `U` is a reference, `T` must also be a reference (as the underlying matcher may be interested in the address of the `U` value).
+
+The code won't compile if any of these conditions isn't met.
+
+Here's one example:
+
+```
+using ::testing::SafeMatcherCast;
+
+// A base class and a child class.
+class Base { ... };
+class Derived : public Base { ... };
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD1(DoThis, void(Derived* derived));
+};
+...
+
+  MockFoo foo;
+  // m is a Matcher<Base*> we got from somewhere.
+  EXPECT_CALL(foo, DoThis(SafeMatcherCast<Derived*>(m)));
+```
+
+If you find `SafeMatcherCast<T>(m)` too limiting, you can use a similar
+function `MatcherCast<T>(m)`. The difference is that `MatcherCast` works
+as long as you can `static_cast` type `T` to type `U`.
+
+`MatcherCast` essentially lets you bypass C++'s type system
+(`static_cast` isn't always safe as it could throw away information,
+for example), so be careful not to misuse/abuse it.
+
+## Selecting Between Overloaded Functions ##
+
+If you expect an overloaded function to be called, the compiler may
+need some help on which overloaded version it is.
+
+To disambiguate functions overloaded on the const-ness of this object,
+use the `Const()` argument wrapper.
+
+```
+using ::testing::ReturnRef;
+
+class MockFoo : public Foo {
+  ...
+  MOCK_METHOD0(GetBar, Bar&());
+  MOCK_CONST_METHOD0(GetBar, const Bar&());
+};
+...
+
+  MockFoo foo;
+  Bar bar1, bar2;
+  EXPECT_CALL(foo, GetBar())         // The non-const GetBar().
+      .WillOnce(ReturnRef(bar1));
+  EXPECT_CALL(Const(foo), GetBar())  // The const GetBar().
+      .WillOnce(ReturnRef(bar2));
+```
+
+(`Const()` is defined by Google Mock and returns a `const` reference
+to its argument.)
+
+To disambiguate overloaded functions with the same number of arguments
+but different argument types, you may need to specify the exact type
+of a matcher, either by wrapping your matcher in `Matcher<type>()`, or
+using a matcher whose type is fixed (`TypedEq<type>`, `An<type>()`,
+etc):
+
+```
+using ::testing::An;
+using ::testing::Lt;
+using ::testing::Matcher;
+using ::testing::TypedEq;
+
+class MockPrinter : public Printer {
+ public:
+  MOCK_METHOD1(Print, void(int n));
+  MOCK_METHOD1(Print, void(char c));
+};
+
+TEST(PrinterTest, Print) {
+  MockPrinter printer;
+
+  EXPECT_CALL(printer, Print(An<int>()));            // void Print(int);
+  EXPECT_CALL(printer, Print(Matcher<int>(Lt(5))));  // void Print(int);
+  EXPECT_CALL(printer, Print(TypedEq<char>('a')));   // void Print(char);
+
+  printer.Print(3);
+  printer.Print(6);
+  printer.Print('a');
+}
+```
+
+## Performing Different Actions Based on the Arguments ##
+
+When a mock method is called, the _last_ matching expectation that's
+still active will be selected (think "newer overrides older"). So, you
+can make a method do different things depending on its argument values
+like this:
+
+```
+using ::testing::_;
+using ::testing::Lt;
+using ::testing::Return;
+...
+  // The default case.
+  EXPECT_CALL(foo, DoThis(_))
+      .WillRepeatedly(Return('b'));
+
+  // The more specific case.
+  EXPECT_CALL(foo, DoThis(Lt(5)))
+      .WillRepeatedly(Return('a'));
+```
+
+Now, if `foo.DoThis()` is called with a value less than 5, `'a'` will
+be returned; otherwise `'b'` will be returned.
+
+## Matching Multiple Arguments as a Whole ##
+
+Sometimes it's not enough to match the arguments individually. For
+example, we may want to say that the first argument must be less than
+the second argument. The `With()` clause allows us to match
+all arguments of a mock function as a whole. For example,
+
+```
+using ::testing::_;
+using ::testing::Lt;
+using ::testing::Ne;
+...
+  EXPECT_CALL(foo, InRange(Ne(0), _))
+      .With(Lt());
+```
+
+says that the first argument of `InRange()` must not be 0, and must be
+less than the second argument.
+
+The expression inside `With()` must be a matcher of type
+`Matcher<tr1::tuple<A1, ..., An> >`, where `A1`, ..., `An` are the
+types of the function arguments.
+
+You can also write `AllArgs(m)` instead of `m` inside `.With()`. The
+two forms are equivalent, but `.With(AllArgs(Lt()))` is more readable
+than `.With(Lt())`.
+
+You can use `Args<k1, ..., kn>(m)` to match the `n` selected arguments
+against `m`. For example,
+
+```
+using ::testing::_;
+using ::testing::AllOf;
+using ::testing::Args;
+using ::testing::Lt;
+...
+  EXPECT_CALL(foo, Blah(_, _, _))
+      .With(AllOf(Args<0, 1>(Lt()), Args<1, 2>(Lt())));
+```
+
+says that `Blah()` will be called with arguments `x`, `y`, and `z` where
+`x < y < z`.
+
+As a convenience and example, Google Mock provides some matchers for
+2-tuples, including the `Lt()` matcher above. See the [CheatSheet](V1_5_CheatSheet.md) for
+the complete list.
+
+## Using Matchers as Predicates ##
+
+Have you noticed that a matcher is just a fancy predicate that also
+knows how to describe itself? Many existing algorithms take predicates
+as arguments (e.g. those defined in STL's `<algorithm>` header), and
+it would be a shame if Google Mock matchers are not allowed to
+participate.
+
+Luckily, you can use a matcher where a unary predicate functor is
+expected by wrapping it inside the `Matches()` function. For example,
+
+```
+#include <algorithm>
+#include <vector>
+
+std::vector<int> v;
+...
+// How many elements in v are >= 10?
+const int count = count_if(v.begin(), v.end(), Matches(Ge(10)));
+```
+
+Since you can build complex matchers from simpler ones easily using
+Google Mock, this gives you a way to conveniently construct composite
+predicates (doing the same using STL's `<functional>` header is just
+painful). For example, here's a predicate that's satisfied by any
+number that is >= 0, <= 100, and != 50:
+
+```
+Matches(AllOf(Ge(0), Le(100), Ne(50)))
+```
+
+## Using Matchers in Google Test Assertions ##
+
+Since matchers are basically predicates that also know how to describe
+themselves, there is a way to take advantage of them in
+[Google Test](http://code.google.com/p/googletest/) assertions. It's
+called `ASSERT_THAT` and `EXPECT_THAT`:
+
+```
+  ASSERT_THAT(value, matcher);  // Asserts that value matches matcher.
+  EXPECT_THAT(value, matcher);  // The non-fatal version.
+```
+
+For example, in a Google Test test you can write:
+
+```
+#include <gmock/gmock.h>
+
+using ::testing::AllOf;
+using ::testing::Ge;
+using ::testing::Le;
+using ::testing::MatchesRegex;
+using ::testing::StartsWith;
+...
+
+  EXPECT_THAT(Foo(), StartsWith("Hello"));
+  EXPECT_THAT(Bar(), MatchesRegex("Line \\d+"));
+  ASSERT_THAT(Baz(), AllOf(Ge(5), Le(10)));
+```
+
+which (as you can probably guess) executes `Foo()`, `Bar()`, and
+`Baz()`, and verifies that:
+
+  * `Foo()` returns a string that starts with `"Hello"`.
+  * `Bar()` returns a string that matches regular expression `"Line \\d+"`.
+  * `Baz()` returns a number in the range [5, 10].
+
+The nice thing about these macros is that _they read like
+English_. They generate informative messages too. For example, if the
+first `EXPECT_THAT()` above fails, the message will be something like:
+
+```
+Value of: Foo()
+  Actual: "Hi, world!"
+Expected: starts with "Hello"
+```
+
+**Credit:** The idea of `(ASSERT|EXPECT)_THAT` was stolen from the
+[Hamcrest](http://code.google.com/p/hamcrest/) project, which adds
+`assertThat()` to JUnit.
+
+## Using Predicates as Matchers ##
+
+Google Mock provides a built-in set of matchers. In case you find them
+lacking, you can use an arbitray unary predicate function or functor
+as a matcher - as long as the predicate accepts a value of the type
+you want. You do this by wrapping the predicate inside the `Truly()`
+function, for example:
+
+```
+using ::testing::Truly;
+
+int IsEven(int n) { return (n % 2) == 0 ? 1 : 0; }
+...
+
+  // Bar() must be called with an even number.
+  EXPECT_CALL(foo, Bar(Truly(IsEven)));
+```
+
+Note that the predicate function / functor doesn't have to return
+`bool`. It works as long as the return value can be used as the
+condition in statement `if (condition) ...`.
+
+## Matching Arguments that Are Not Copyable ##
+
+When you do an `EXPECT_CALL(mock_obj, Foo(bar))`, Google Mock saves
+away a copy of `bar`. When `Foo()` is called later, Google Mock
+compares the argument to `Foo()` with the saved copy of `bar`. This
+way, you don't need to worry about `bar` being modified or destroyed
+after the `EXPECT_CALL()` is executed. The same is true when you use
+matchers like `Eq(bar)`, `Le(bar)`, and so on.
+
+But what if `bar` cannot be copied (i.e. has no copy constructor)? You
+could define your own matcher function and use it with `Truly()`, as
+the previous couple of recipes have shown. Or, you may be able to get
+away from it if you can guarantee that `bar` won't be changed after
+the `EXPECT_CALL()` is executed. Just tell Google Mock that it should
+save a reference to `bar`, instead of a copy of it. Here's how:
+
+```
+using ::testing::Eq;
+using ::testing::ByRef;
+using ::testing::Lt;
+...
+  // Expects that Foo()'s argument == bar.
+  EXPECT_CALL(mock_obj, Foo(Eq(ByRef(bar))));
+
+  // Expects that Foo()'s argument < bar.
+  EXPECT_CALL(mock_obj, Foo(Lt(ByRef(bar))));
+```
+
+Remember: if you do this, don't change `bar` after the
+`EXPECT_CALL()`, or the result is undefined.
+
+## Validating a Member of an Object ##
+
+Often a mock function takes a reference to object as an argument. When
+matching the argument, you may not want to compare the entire object
+against a fixed object, as that may be over-specification. Instead,
+you may need to validate a certain member variable or the result of a
+certain getter method of the object. You can do this with `Field()`
+and `Property()`. More specifically,
+
+```
+Field(&Foo::bar, m)
+```
+
+is a matcher that matches a `Foo` object whose `bar` member variable
+satisfies matcher `m`.
+
+```
+Property(&Foo::baz, m)
+```
+
+is a matcher that matches a `Foo` object whose `baz()` method returns
+a value that satisfies matcher `m`.
+
+For example:
+
+> | `Field(&Foo::number, Ge(3))` | Matches `x` where `x.number >= 3`. |
+|:-----------------------------|:-----------------------------------|
+> | `Property(&Foo::name, StartsWith("John "))` | Matches `x` where `x.name()` starts with `"John "`. |
+
+Note that in `Property(&Foo::baz, ...)`, method `baz()` must take no
+argument and be declared as `const`.
+
+BTW, `Field()` and `Property()` can also match plain pointers to
+objects. For instance,
+
+```
+Field(&Foo::number, Ge(3))
+```
+
+matches a plain pointer `p` where `p->number >= 3`. If `p` is `NULL`,
+the match will always fail regardless of the inner matcher.
+
+What if you want to validate more than one members at the same time?
+Remember that there is `AllOf()`.
+
+## Validating the Value Pointed to by a Pointer Argument ##
+
+C++ functions often take pointers as arguments. You can use matchers
+like `NULL`, `NotNull()`, and other comparison matchers to match a
+pointer, but what if you want to make sure the value _pointed to_ by
+the pointer, instead of the pointer itself, has a certain property?
+Well, you can use the `Pointee(m)` matcher.
+
+`Pointee(m)` matches a pointer iff `m` matches the value the pointer
+points to. For example:
+
+```
+using ::testing::Ge;
+using ::testing::Pointee;
+...
+  EXPECT_CALL(foo, Bar(Pointee(Ge(3))));
+```
+
+expects `foo.Bar()` to be called with a pointer that points to a value
+greater than or equal to 3.
+
+One nice thing about `Pointee()` is that it treats a `NULL` pointer as
+a match failure, so you can write `Pointee(m)` instead of
+
+```
+  AllOf(NotNull(), Pointee(m))
+```
+
+without worrying that a `NULL` pointer will crash your test.
+
+Also, did we tell you that `Pointee()` works with both raw pointers
+**and** smart pointers (`linked_ptr`, `shared_ptr`, `scoped_ptr`, and
+etc)?
+
+What if you have a pointer to pointer? You guessed it - you can use
+nested `Pointee()` to probe deeper inside the value. For example,
+`Pointee(Pointee(Lt(3)))` matches a pointer that points to a pointer
+that points to a number less than 3 (what a mouthful...).
+
+## Testing a Certain Property of an Object ##
+
+Sometimes you want to specify that an object argument has a certain
+property, but there is no existing matcher that does this. If you want
+good error messages, you should define a matcher. If you want to do it
+quick and dirty, you could get away with writing an ordinary function.
+
+Let's say you have a mock function that takes an object of type `Foo`,
+which has an `int bar()` method and an `int baz()` method, and you
+want to constrain that the argument's `bar()` value plus its `baz()`
+value is a given number. Here's how you can define a matcher to do it:
+
+```
+using ::testing::MatcherInterface;
+using ::testing::MatchResultListener;
+
+class BarPlusBazEqMatcher : public MatcherInterface<const Foo&> {
+ public:
+  explicit BarPlusBazEqMatcher(int expected_sum)
+      : expected_sum_(expected_sum) {}
+
+  virtual bool MatchAndExplain(const Foo& foo,
+                               MatchResultListener* listener) const {
+    return (foo.bar() + foo.baz()) == expected_sum_;
+  }
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "bar() + baz() equals " << expected_sum_;
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "bar() + baz() does not equal " << expected_sum_;
+  }
+ private:
+  const int expected_sum_;
+};
+
+inline Matcher<const Foo&> BarPlusBazEq(int expected_sum) {
+  return MakeMatcher(new BarPlusBazEqMatcher(expected_sum));
+}
+
+...
+
+  EXPECT_CALL(..., DoThis(BarPlusBazEq(5)))...;
+```
+
+## Matching Containers ##
+
+Sometimes an STL container (e.g. list, vector, map, ...) is passed to
+a mock function and you may want to validate it. Since most STL
+containers support the `==` operator, you can write
+`Eq(expected_container)` or simply `expected_container` to match a
+container exactly.
+
+Sometimes, though, you may want to be more flexible (for example, the
+first element must be an exact match, but the second element can be
+any positive number, and so on). Also, containers used in tests often
+have a small number of elements, and having to define the expected
+container out-of-line is a bit of a hassle.
+
+You can use the `ElementsAre()` matcher in such cases:
+
+```
+using ::testing::_;
+using ::testing::ElementsAre;
+using ::testing::Gt;
+...
+
+  MOCK_METHOD1(Foo, void(const vector<int>& numbers));
+...
+
+  EXPECT_CALL(mock, Foo(ElementsAre(1, Gt(0), _, 5)));
+```
+
+The above matcher says that the container must have 4 elements, which
+must be 1, greater than 0, anything, and 5 respectively.
+
+`ElementsAre()` is overloaded to take 0 to 10 arguments. If more are
+needed, you can place them in a C-style array and use
+`ElementsAreArray()` instead:
+
+```
+using ::testing::ElementsAreArray;
+...
+
+  // ElementsAreArray accepts an array of element values.
+  const int expected_vector1[] = { 1, 5, 2, 4, ... };
+  EXPECT_CALL(mock, Foo(ElementsAreArray(expected_vector1)));
+
+  // Or, an array of element matchers.
+  Matcher<int> expected_vector2 = { 1, Gt(2), _, 3, ... };
+  EXPECT_CALL(mock, Foo(ElementsAreArray(expected_vector2)));
+```
+
+In case the array needs to be dynamically created (and therefore the
+array size cannot be inferred by the compiler), you can give
+`ElementsAreArray()` an additional argument to specify the array size:
+
+```
+using ::testing::ElementsAreArray;
+...
+  int* const expected_vector3 = new int[count];
+  ... fill expected_vector3 with values ...
+  EXPECT_CALL(mock, Foo(ElementsAreArray(expected_vector3, count)));
+```
+
+**Tips:**
+
+  * `ElementAre*()` works with _any_ container that implements the STL iterator concept (i.e. it has a `const_iterator` type and supports `begin()/end()`) and supports `size()`, not just the ones defined in STL. It will even work with container types yet to be written - as long as they follows the above pattern.
+  * You can use nested `ElementAre*()` to match nested (multi-dimensional) containers.
+  * If the container is passed by pointer instead of by reference, just write `Pointee(ElementsAre*(...))`.
+  * The order of elements _matters_ for `ElementsAre*()`. Therefore don't use it with containers whose element order is undefined (e.g. `hash_map`).
+
+## Sharing Matchers ##
+
+Under the hood, a Google Mock matcher object consists of a pointer to
+a ref-counted implementation object. Copying matchers is allowed and
+very efficient, as only the pointer is copied. When the last matcher
+that references the implementation object dies, the implementation
+object will be deleted.
+
+Therefore, if you have some complex matcher that you want to use again
+and again, there is no need to build it everytime. Just assign it to a
+matcher variable and use that variable repeatedly! For example,
+
+```
+  Matcher<int> in_range = AllOf(Gt(5), Le(10));
+  ... use in_range as a matcher in multiple EXPECT_CALLs ...
+```
+
+# Setting Expectations #
+
+## Ignoring Uninteresting Calls ##
+
+If you are not interested in how a mock method is called, just don't
+say anything about it. In this case, if the method is ever called,
+Google Mock will perform its default action to allow the test program
+to continue. If you are not happy with the default action taken by
+Google Mock, you can override it using `DefaultValue<T>::Set()`
+(described later in this document) or `ON_CALL()`.
+
+Please note that once you expressed interest in a particular mock
+method (via `EXPECT_CALL()`), all invocations to it must match some
+expectation. If this function is called but the arguments don't match
+any `EXPECT_CALL()` statement, it will be an error.
+
+## Disallowing Unexpected Calls ##
+
+If a mock method shouldn't be called at all, explicitly say so:
+
+```
+using ::testing::_;
+...
+  EXPECT_CALL(foo, Bar(_))
+      .Times(0);
+```
+
+If some calls to the method are allowed, but the rest are not, just
+list all the expected calls:
+
+```
+using ::testing::AnyNumber;
+using ::testing::Gt;
+...
+  EXPECT_CALL(foo, Bar(5));
+  EXPECT_CALL(foo, Bar(Gt(10)))
+      .Times(AnyNumber());
+```
+
+A call to `foo.Bar()` that doesn't match any of the `EXPECT_CALL()`
+statements will be an error.
+
+## Expecting Ordered Calls ##
+
+Although an `EXPECT_CALL()` statement defined earlier takes precedence
+when Google Mock tries to match a function call with an expectation,
+by default calls don't have to happen in the order `EXPECT_CALL()`
+statements are written. For example, if the arguments match the
+matchers in the third `EXPECT_CALL()`, but not those in the first two,
+then the third expectation will be used.
+
+If you would rather have all calls occur in the order of the
+expectations, put the `EXPECT_CALL()` statements in a block where you
+define a variable of type `InSequence`:
+
+```
+  using ::testing::_;
+  using ::testing::InSequence;
+
+  {
+    InSequence s;
+
+    EXPECT_CALL(foo, DoThis(5));
+    EXPECT_CALL(bar, DoThat(_))
+        .Times(2);
+    EXPECT_CALL(foo, DoThis(6));
+  }
+```
+
+In this example, we expect a call to `foo.DoThis(5)`, followed by two
+calls to `bar.DoThat()` where the argument can be anything, which are
+in turn followed by a call to `foo.DoThis(6)`. If a call occurred
+out-of-order, Google Mock will report an error.
+
+## Expecting Partially Ordered Calls ##
+
+Sometimes requiring everything to occur in a predetermined order can
+lead to brittle tests. For example, we may care about `A` occurring
+before both `B` and `C`, but aren't interested in the relative order
+of `B` and `C`. In this case, the test should reflect our real intent,
+instead of being overly constraining.
+
+Google Mock allows you to impose an arbitrary DAG (directed acyclic
+graph) on the calls. One way to express the DAG is to use the
+[After](V1_5_CheatSheet#The_After_Clause.md) clause of `EXPECT_CALL`.
+
+Another way is via the `InSequence()` clause (not the same as the
+`InSequence` class), which we borrowed from jMock 2. It's less
+flexible than `After()`, but more convenient when you have long chains
+of sequential calls, as it doesn't require you to come up with
+different names for the expectations in the chains.  Here's how it
+works:
+
+If we view `EXPECT_CALL()` statements as nodes in a graph, and add an
+edge from node A to node B wherever A must occur before B, we can get
+a DAG. We use the term "sequence" to mean a directed path in this
+DAG. Now, if we decompose the DAG into sequences, we just need to know
+which sequences each `EXPECT_CALL()` belongs to in order to be able to
+reconstruct the orginal DAG.
+
+So, to specify the partial order on the expectations we need to do two
+things: first to define some `Sequence` objects, and then for each
+`EXPECT_CALL()` say which `Sequence` objects it is part
+of. Expectations in the same sequence must occur in the order they are
+written. For example,
+
+```
+  using ::testing::Sequence;
+
+  Sequence s1, s2;
+
+  EXPECT_CALL(foo, A())
+      .InSequence(s1, s2);
+  EXPECT_CALL(bar, B())
+      .InSequence(s1);
+  EXPECT_CALL(bar, C())
+      .InSequence(s2);
+  EXPECT_CALL(foo, D())
+      .InSequence(s2);
+```
+
+specifies the following DAG (where `s1` is `A -> B`, and `s2` is `A ->
+C -> D`):
+
+```
+       +---> B
+       |
+  A ---|
+       |
+       +---> C ---> D
+```
+
+This means that A must occur before B and C, and C must occur before
+D. There's no restriction about the order other than these.
+
+## Controlling When an Expectation Retires ##
+
+When a mock method is called, Google Mock only consider expectations
+that are still active. An expectation is active when created, and
+becomes inactive (aka _retires_) when a call that has to occur later
+has occurred. For example, in
+
+```
+  using ::testing::_;
+  using ::testing::Sequence;
+
+  Sequence s1, s2;
+
+  EXPECT_CALL(log, Log(WARNING, _, "File too large."))     // #1
+      .Times(AnyNumber())
+      .InSequence(s1, s2);
+  EXPECT_CALL(log, Log(WARNING, _, "Data set is empty."))  // #2
+      .InSequence(s1);
+  EXPECT_CALL(log, Log(WARNING, _, "User not found."))     // #3
+      .InSequence(s2);
+```
+
+as soon as either #2 or #3 is matched, #1 will retire. If a warning
+`"File too large."` is logged after this, it will be an error.
+
+Note that an expectation doesn't retire automatically when it's
+saturated. For example,
+
+```
+using ::testing::_;
+...
+  EXPECT_CALL(log, Log(WARNING, _, _));                  // #1
+  EXPECT_CALL(log, Log(WARNING, _, "File too large."));  // #2
+```
+
+says that there will be exactly one warning with the message `"File
+too large."`. If the second warning contains this message too, #2 will
+match again and result in an upper-bound-violated error.
+
+If this is not what you want, you can ask an expectation to retire as
+soon as it becomes saturated:
+
+```
+using ::testing::_;
+...
+  EXPECT_CALL(log, Log(WARNING, _, _));                 // #1
+  EXPECT_CALL(log, Log(WARNING, _, "File too large."))  // #2
+      .RetiresOnSaturation();
+```
+
+Here #2 can be used only once, so if you have two warnings with the
+message `"File too large."`, the first will match #2 and the second
+will match #1 - there will be no error.
+
+# Using Actions #
+
+## Returning References from Mock Methods ##
+
+If a mock function's return type is a reference, you need to use
+`ReturnRef()` instead of `Return()` to return a result:
+
+```
+using ::testing::ReturnRef;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD0(GetBar, Bar&());
+};
+...
+
+  MockFoo foo;
+  Bar bar;
+  EXPECT_CALL(foo, GetBar())
+      .WillOnce(ReturnRef(bar));
+```
+
+## Combining Actions ##
+
+Want to do more than one thing when a function is called? That's
+fine. `DoAll()` allow you to do sequence of actions every time. Only
+the return value of the last action in the sequence will be used.
+
+```
+using ::testing::DoAll;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD1(Bar, bool(int n));
+};
+...
+
+  EXPECT_CALL(foo, Bar(_))
+      .WillOnce(DoAll(action_1,
+                      action_2,
+                      ...
+                      action_n));
+```
+
+## Mocking Side Effects ##
+
+Sometimes a method exhibits its effect not via returning a value but
+via side effects. For example, it may change some global state or
+modify an output argument. To mock side effects, in general you can
+define your own action by implementing `::testing::ActionInterface`.
+
+If all you need to do is to change an output argument, the built-in
+`SetArgumentPointee()` action is convenient:
+
+```
+using ::testing::SetArgumentPointee;
+
+class MockMutator : public Mutator {
+ public:
+  MOCK_METHOD2(Mutate, void(bool mutate, int* value));
+  ...
+};
+...
+
+  MockMutator mutator;
+  EXPECT_CALL(mutator, Mutate(true, _))
+      .WillOnce(SetArgumentPointee<1>(5));
+```
+
+In this example, when `mutator.Mutate()` is called, we will assign 5
+to the `int` variable pointed to by argument #1
+(0-based).
+
+`SetArgumentPointee()` conveniently makes an internal copy of the
+value you pass to it, removing the need to keep the value in scope and
+alive. The implication however is that the value must have a copy
+constructor and assignment operator.
+
+If the mock method also needs to return a value as well, you can chain
+`SetArgumentPointee()` with `Return()` using `DoAll()`:
+
+```
+using ::testing::_;
+using ::testing::Return;
+using ::testing::SetArgumentPointee;
+
+class MockMutator : public Mutator {
+ public:
+  ...
+  MOCK_METHOD1(MutateInt, bool(int* value));
+};
+...
+
+  MockMutator mutator;
+  EXPECT_CALL(mutator, MutateInt(_))
+      .WillOnce(DoAll(SetArgumentPointee<0>(5),
+                      Return(true)));
+```
+
+If the output argument is an array, use the
+`SetArrayArgument<N>(first, last)` action instead. It copies the
+elements in source range `[first, last)` to the array pointed to by
+the `N`-th (0-based) argument:
+
+```
+using ::testing::NotNull;
+using ::testing::SetArrayArgument;
+
+class MockArrayMutator : public ArrayMutator {
+ public:
+  MOCK_METHOD2(Mutate, void(int* values, int num_values));
+  ...
+};
+...
+
+  MockArrayMutator mutator;
+  int values[5] = { 1, 2, 3, 4, 5 };
+  EXPECT_CALL(mutator, Mutate(NotNull(), 5))
+      .WillOnce(SetArrayArgument<0>(values, values + 5));
+```
+
+This also works when the argument is an output iterator:
+
+```
+using ::testing::_;
+using ::testing::SeArrayArgument;
+
+class MockRolodex : public Rolodex {
+ public:
+  MOCK_METHOD1(GetNames, void(std::back_insert_iterator<vector<string> >));
+  ...
+};
+...
+
+  MockRolodex rolodex;
+  vector<string> names;
+  names.push_back("George");
+  names.push_back("John");
+  names.push_back("Thomas");
+  EXPECT_CALL(rolodex, GetNames(_))
+      .WillOnce(SetArrayArgument<0>(names.begin(), names.end()));
+```
+
+## Changing a Mock Object's Behavior Based on the State ##
+
+If you expect a call to change the behavior of a mock object, you can use `::testing::InSequence` to specify different behaviors before and after the call:
+
+```
+using ::testing::InSequence;
+using ::testing::Return;
+
+...
+  {
+    InSequence seq;
+    EXPECT_CALL(my_mock, IsDirty())
+        .WillRepeatedly(Return(true));
+    EXPECT_CALL(my_mock, Flush());
+    EXPECT_CALL(my_mock, IsDirty())
+        .WillRepeatedly(Return(false));
+  }
+  my_mock.FlushIfDirty();
+```
+
+This makes `my_mock.IsDirty()` return `true` before `my_mock.Flush()` is called and return `false` afterwards.
+
+If the behavior change is more complex, you can store the effects in a variable and make a mock method get its return value from that variable:
+
+```
+using ::testing::_;
+using ::testing::SaveArg;
+using ::testing::Return;
+
+ACTION_P(ReturnPointee, p) { return *p; }
+...
+  int previous_value = 0;
+  EXPECT_CALL(my_mock, GetPrevValue())
+      .WillRepeatedly(ReturnPointee(&previous_value));
+  EXPECT_CALL(my_mock, UpdateValue(_))
+      .WillRepeatedly(SaveArg<0>(&previous_value));
+  my_mock.DoSomethingToUpdateValue();
+```
+
+Here `my_mock.GetPrevValue()` will always return the argument of the last `UpdateValue()` call.
+
+## Setting the Default Value for a Return Type ##
+
+If a mock method's return type is a built-in C++ type or pointer, by
+default it will return 0 when invoked. You only need to specify an
+action if this default value doesn't work for you.
+
+Sometimes, you may want to change this default value, or you may want
+to specify a default value for types Google Mock doesn't know
+about. You can do this using the `::testing::DefaultValue` class
+template:
+
+```
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD0(CalculateBar, Bar());
+};
+...
+
+  Bar default_bar;
+  // Sets the default return value for type Bar.
+  DefaultValue<Bar>::Set(default_bar);
+
+  MockFoo foo;
+
+  // We don't need to specify an action here, as the default
+  // return value works for us.
+  EXPECT_CALL(foo, CalculateBar());
+
+  foo.CalculateBar();  // This should return default_bar.
+
+  // Unsets the default return value.
+  DefaultValue<Bar>::Clear();
+```
+
+Please note that changing the default value for a type can make you
+tests hard to understand. We recommend you to use this feature
+judiciously. For example, you may want to make sure the `Set()` and
+`Clear()` calls are right next to the code that uses your mock.
+
+## Setting the Default Actions for a Mock Method ##
+
+You've learned how to change the default value of a given
+type. However, this may be too coarse for your purpose: perhaps you
+have two mock methods with the same return type and you want them to
+have different behaviors. The `ON_CALL()` macro allows you to
+customize your mock's behavior at the method level:
+
+```
+using ::testing::_;
+using ::testing::AnyNumber;
+using ::testing::Gt;
+using ::testing::Return;
+...
+  ON_CALL(foo, Sign(_))
+      .WillByDefault(Return(-1));
+  ON_CALL(foo, Sign(0))
+      .WillByDefault(Return(0));
+  ON_CALL(foo, Sign(Gt(0)))
+      .WillByDefault(Return(1));
+
+  EXPECT_CALL(foo, Sign(_))
+      .Times(AnyNumber());
+
+  foo.Sign(5);   // This should return 1.
+  foo.Sign(-9);  // This should return -1.
+  foo.Sign(0);   // This should return 0.
+```
+
+As you may have guessed, when there are more than one `ON_CALL()`
+statements, the news order take precedence over the older ones. In
+other words, the **last** one that matches the function arguments will
+be used. This matching order allows you to set up the common behavior
+in a mock object's constructor or the test fixture's set-up phase and
+specialize the mock's behavior later.
+
+## Using Functions/Methods/Functors as Actions ##
+
+If the built-in actions don't suit you, you can easily use an existing
+function, method, or functor as an action:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD2(Sum, int(int x, int y));
+  MOCK_METHOD1(ComplexJob, bool(int x));
+};
+
+int CalculateSum(int x, int y) { return x + y; }
+
+class Helper {
+ public:
+  bool ComplexJob(int x);
+};
+...
+
+  MockFoo foo;
+  Helper helper;
+  EXPECT_CALL(foo, Sum(_, _))
+      .WillOnce(Invoke(CalculateSum));
+  EXPECT_CALL(foo, ComplexJob(_))
+      .WillOnce(Invoke(&helper, &Helper::ComplexJob));
+
+  foo.Sum(5, 6);       // Invokes CalculateSum(5, 6).
+  foo.ComplexJob(10);  // Invokes helper.ComplexJob(10);
+```
+
+The only requirement is that the type of the function, etc must be
+_compatible_ with the signature of the mock function, meaning that the
+latter's arguments can be implicitly converted to the corresponding
+arguments of the former, and the former's return type can be
+implicitly converted to that of the latter. So, you can invoke
+something whose type is _not_ exactly the same as the mock function,
+as long as it's safe to do so - nice, huh?
+
+## Invoking a Function/Method/Functor Without Arguments ##
+
+`Invoke()` is very useful for doing actions that are more complex. It
+passes the mock function's arguments to the function or functor being
+invoked such that the callee has the full context of the call to work
+with. If the invoked function is not interested in some or all of the
+arguments, it can simply ignore them.
+
+Yet, a common pattern is that a test author wants to invoke a function
+without the arguments of the mock function. `Invoke()` allows her to
+do that using a wrapper function that throws away the arguments before
+invoking an underlining nullary function. Needless to say, this can be
+tedious and obscures the intent of the test.
+
+`InvokeWithoutArgs()` solves this problem. It's like `Invoke()` except
+that it doesn't pass the mock function's arguments to the
+callee. Here's an example:
+
+```
+using ::testing::_;
+using ::testing::InvokeWithoutArgs;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD1(ComplexJob, bool(int n));
+};
+
+bool Job1() { ... }
+...
+
+  MockFoo foo;
+  EXPECT_CALL(foo, ComplexJob(_))
+      .WillOnce(InvokeWithoutArgs(Job1));
+
+  foo.ComplexJob(10);  // Invokes Job1().
+```
+
+## Invoking an Argument of the Mock Function ##
+
+Sometimes a mock function will receive a function pointer or a functor
+(in other words, a "callable") as an argument, e.g.
+
+```
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD2(DoThis, bool(int n, bool (*fp)(int)));
+};
+```
+
+and you may want to invoke this callable argument:
+
+```
+using ::testing::_;
+...
+  MockFoo foo;
+  EXPECT_CALL(foo, DoThis(_, _))
+      .WillOnce(...);
+  // Will execute (*fp)(5), where fp is the
+  // second argument DoThis() receives.
+```
+
+Arghh, you need to refer to a mock function argument but C++ has no
+lambda (yet), so you have to define your own action. :-( Or do you
+really?
+
+Well, Google Mock has an action to solve _exactly_ this problem:
+
+```
+  InvokeArgument<N>(arg_1, arg_2, ..., arg_m)
+```
+
+will invoke the `N`-th (0-based) argument the mock function receives,
+with `arg_1`, `arg_2`, ..., and `arg_m`. No matter if the argument is
+a function pointer or a functor, Google Mock handles them both.
+
+With that, you could write:
+
+```
+using ::testing::_;
+using ::testing::InvokeArgument;
+...
+  EXPECT_CALL(foo, DoThis(_, _))
+      .WillOnce(InvokeArgument<1>(5));
+  // Will execute (*fp)(5), where fp is the
+  // second argument DoThis() receives.
+```
+
+What if the callable takes an argument by reference? No problem - just
+wrap it inside `ByRef()`:
+
+```
+...
+  MOCK_METHOD1(Bar, bool(bool (*fp)(int, const Helper&)));
+...
+using ::testing::_;
+using ::testing::ByRef;
+using ::testing::InvokeArgument;
+...
+
+  MockFoo foo;
+  Helper helper;
+  ...
+  EXPECT_CALL(foo, Bar(_))
+      .WillOnce(InvokeArgument<0>(5, ByRef(helper)));
+  // ByRef(helper) guarantees that a reference to helper, not a copy of it,
+  // will be passed to the callable.
+```
+
+What if the callable takes an argument by reference and we do **not**
+wrap the argument in `ByRef()`? Then `InvokeArgument()` will _make a
+copy_ of the argument, and pass a _reference to the copy_, instead of
+a reference to the original value, to the callable. This is especially
+handy when the argument is a temporary value:
+
+```
+...
+  MOCK_METHOD1(DoThat, bool(bool (*f)(const double& x, const string& s)));
+...
+using ::testing::_;
+using ::testing::InvokeArgument;
+...
+
+  MockFoo foo;
+  ...
+  EXPECT_CALL(foo, DoThat(_))
+      .WillOnce(InvokeArgument<0>(5.0, string("Hi")));
+  // Will execute (*f)(5.0, string("Hi")), where f is the function pointer
+  // DoThat() receives.  Note that the values 5.0 and string("Hi") are
+  // temporary and dead once the EXPECT_CALL() statement finishes.  Yet
+  // it's fine to perform this action later, since a copy of the values
+  // are kept inside the InvokeArgument action.
+```
+
+## Ignoring an Action's Result ##
+
+Sometimes you have an action that returns _something_, but you need an
+action that returns `void` (perhaps you want to use it in a mock
+function that returns `void`, or perhaps it needs to be used in
+`DoAll()` and it's not the last in the list). `IgnoreResult()` lets
+you do that. For example:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::Return;
+
+int Process(const MyData& data);
+string DoSomething();
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD1(Abc, void(const MyData& data));
+  MOCK_METHOD0(Xyz, bool());
+};
+...
+
+  MockFoo foo;
+  EXPECT_CALL(foo, Abc(_))
+  // .WillOnce(Invoke(Process));
+  // The above line won't compile as Process() returns int but Abc() needs
+  // to return void.
+      .WillOnce(IgnoreResult(Invoke(Process)));
+
+  EXPECT_CALL(foo, Xyz())
+      .WillOnce(DoAll(IgnoreResult(Invoke(DoSomething)),
+      // Ignores the string DoSomething() returns.
+                      Return(true)));
+```
+
+Note that you **cannot** use `IgnoreResult()` on an action that already
+returns `void`. Doing so will lead to ugly compiler errors.
+
+## Selecting an Action's Arguments ##
+
+Say you have a mock function `Foo()` that takes seven arguments, and
+you have a custom action that you want to invoke when `Foo()` is
+called. Trouble is, the custom action only wants three arguments:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+...
+  MOCK_METHOD7(Foo, bool(bool visible, const string& name, int x, int y,
+                         const map<pair<int, int>, double>& weight,
+                         double min_weight, double max_wight));
+...
+
+bool IsVisibleInQuadrant1(bool visible, int x, int y) {
+  return visible && x >= 0 && y >= 0;
+}
+...
+
+  EXPECT_CALL(mock, Foo(_, _, _, _, _, _, _))
+      .WillOnce(Invoke(IsVisibleInQuadrant1));  // Uh, won't compile. :-(
+```
+
+To please the compiler God, you can to define an "adaptor" that has
+the same signature as `Foo()` and calls the custom action with the
+right arguments:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+
+bool MyIsVisibleInQuadrant1(bool visible, const string& name, int x, int y,
+                            const map<pair<int, int>, double>& weight,
+                            double min_weight, double max_wight) {
+  return IsVisibleInQuadrant1(visible, x, y);
+}
+...
+
+  EXPECT_CALL(mock, Foo(_, _, _, _, _, _, _))
+      .WillOnce(Invoke(MyIsVisibleInQuadrant1));  // Now it works.
+```
+
+But isn't this awkward?
+
+Google Mock provides a generic _action adaptor_, so you can spend your
+time minding more important business than writing your own
+adaptors. Here's the syntax:
+
+```
+  WithArgs<N1, N2, ..., Nk>(action)
+```
+
+creates an action that passes the arguments of the mock function at
+the given indices (0-based) to the inner `action` and performs
+it. Using `WithArgs`, our original example can be written as:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::WithArgs;
+...
+  EXPECT_CALL(mock, Foo(_, _, _, _, _, _, _))
+      .WillOnce(WithArgs<0, 2, 3>(Invoke(IsVisibleInQuadrant1)));
+      // No need to define your own adaptor.
+```
+
+For better readability, Google Mock also gives you:
+
+  * `WithoutArgs(action)` when the inner `action` takes _no_ argument, and
+  * `WithArg<N>(action)` (no `s` after `Arg`) when the inner `action` takes _one_ argument.
+
+As you may have realized, `InvokeWithoutArgs(...)` is just syntactic
+sugar for `WithoutArgs(Inovke(...))`.
+
+Here are more tips:
+
+  * The inner action used in `WithArgs` and friends does not have to be `Invoke()` -- it can be anything.
+  * You can repeat an argument in the argument list if necessary, e.g. `WithArgs<2, 3, 3, 5>(...)`.
+  * You can change the order of the arguments, e.g. `WithArgs<3, 2, 1>(...)`.
+  * The types of the selected arguments do _not_ have to match the signature of the inner action exactly. It works as long as they can be implicitly converted to the corresponding arguments of the inner action. For example, if the 4-th argument of the mock function is an `int` and `my_action` takes a `double`, `WithArg<4>(my_action)` will work.
+
+## Ignoring Arguments in Action Functions ##
+
+The selecting-an-action's-arguments recipe showed us one way to make a
+mock function and an action with incompatible argument lists fit
+together. The downside is that wrapping the action in
+`WithArgs<...>()` can get tedious for people writing the tests.
+
+If you are defining a function, method, or functor to be used with
+`Invoke*()`, and you are not interested in some of its arguments, an
+alternative to `WithArgs` is to declare the uninteresting arguments as
+`Unused`. This makes the definition less cluttered and less fragile in
+case the types of the uninteresting arguments change. It could also
+increase the chance the action function can be reused. For example,
+given
+
+```
+  MOCK_METHOD3(Foo, double(const string& label, double x, double y));
+  MOCK_METHOD3(Bar, double(int index, double x, double y));
+```
+
+instead of
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+
+double DistanceToOriginWithLabel(const string& label, double x, double y) {
+  return sqrt(x*x + y*y);
+}
+
+double DistanceToOriginWithIndex(int index, double x, double y) {
+  return sqrt(x*x + y*y);
+}
+...
+
+  EXEPCT_CALL(mock, Foo("abc", _, _))
+      .WillOnce(Invoke(DistanceToOriginWithLabel));
+  EXEPCT_CALL(mock, Bar(5, _, _))
+      .WillOnce(Invoke(DistanceToOriginWithIndex));
+```
+
+you could write
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::Unused;
+
+double DistanceToOrigin(Unused, double x, double y) {
+  return sqrt(x*x + y*y);
+}
+...
+
+  EXEPCT_CALL(mock, Foo("abc", _, _))
+      .WillOnce(Invoke(DistanceToOrigin));
+  EXEPCT_CALL(mock, Bar(5, _, _))
+      .WillOnce(Invoke(DistanceToOrigin));
+```
+
+## Sharing Actions ##
+
+Just like matchers, a Google Mock action object consists of a pointer
+to a ref-counted implementation object. Therefore copying actions is
+also allowed and very efficient. When the last action that references
+the implementation object dies, the implementation object will be
+deleted.
+
+If you have some complex action that you want to use again and again,
+you may not have to build it from scratch everytime. If the action
+doesn't have an internal state (i.e. if it always does the same thing
+no matter how many times it has been called), you can assign it to an
+action variable and use that variable repeatedly. For example:
+
+```
+  Action<bool(int*)> set_flag = DoAll(SetArgumentPointee<0>(5),
+                                      Return(true));
+  ... use set_flag in .WillOnce() and .WillRepeatedly() ...
+```
+
+However, if the action has its own state, you may be surprised if you
+share the action object. Suppose you have an action factory
+`IncrementCounter(init)` which creates an action that increments and
+returns a counter whose initial value is `init`, using two actions
+created from the same expression and using a shared action will
+exihibit different behaviors. Example:
+
+```
+  EXPECT_CALL(foo, DoThis())
+      .WillRepeatedly(IncrementCounter(0));
+  EXPECT_CALL(foo, DoThat())
+      .WillRepeatedly(IncrementCounter(0));
+  foo.DoThis();  // Returns 1.
+  foo.DoThis();  // Returns 2.
+  foo.DoThat();  // Returns 1 - Blah() uses a different
+                 // counter than Bar()'s.
+```
+
+versus
+
+```
+  Action<int()> increment = IncrementCounter(0);
+
+  EXPECT_CALL(foo, DoThis())
+      .WillRepeatedly(increment);
+  EXPECT_CALL(foo, DoThat())
+      .WillRepeatedly(increment);
+  foo.DoThis();  // Returns 1.
+  foo.DoThis();  // Returns 2.
+  foo.DoThat();  // Returns 3 - the counter is shared.
+```
+
+# Misc Recipes on Using Google Mock #
+
+## Forcing a Verification ##
+
+When it's being destoyed, your friendly mock object will automatically
+verify that all expectations on it have been satisfied, and will
+generate [Google Test](http://code.google.com/p/googletest/) failures
+if not. This is convenient as it leaves you with one less thing to
+worry about. That is, unless you are not sure if your mock object will
+be destoyed.
+
+How could it be that your mock object won't eventually be destroyed?
+Well, it might be created on the heap and owned by the code you are
+testing. Suppose there's a bug in that code and it doesn't delete the
+mock object properly - you could end up with a passing test when
+there's actually a bug.
+
+Using a heap checker is a good idea and can alleviate the concern, but
+its implementation may not be 100% reliable. So, sometimes you do want
+to _force_ Google Mock to verify a mock object before it is
+(hopefully) destructed. You can do this with
+`Mock::VerifyAndClearExpectations(&mock_object)`:
+
+```
+TEST(MyServerTest, ProcessesRequest) {
+  using ::testing::Mock;
+
+  MockFoo* const foo = new MockFoo;
+  EXPECT_CALL(*foo, ...)...;
+  // ... other expectations ...
+
+  // server now owns foo.
+  MyServer server(foo);
+  server.ProcessRequest(...);
+
+  // In case that server's destructor will forget to delete foo,
+  // this will verify the expectations anyway.
+  Mock::VerifyAndClearExpectations(foo);
+}  // server is destroyed when it goes out of scope here.
+```
+
+**Tip:** The `Mock::VerifyAndClearExpectations()` function returns a
+`bool` to indicate whether the verification was successful (`true` for
+yes), so you can wrap that function call inside a `ASSERT_TRUE()` if
+there is no point going further when the verification has failed.
+
+## Using Check Points ##
+
+Sometimes you may want to "reset" a mock object at various check
+points in your test: at each check point, you verify that all existing
+expectations on the mock object have been satisfied, and then you set
+some new expectations on it as if it's newly created. This allows you
+to work with a mock object in "phases" whose sizes are each
+manageable.
+
+One such scenario is that in your test's `SetUp()` function, you may
+want to put the object you are testing into a certain state, with the
+help from a mock object. Once in the desired state, you want to clear
+all expectations on the mock, such that in the `TEST_F` body you can
+set fresh expectations on it.
+
+As you may have figured out, the `Mock::VerifyAndClearExpectations()`
+function we saw in the previous recipe can help you here. Or, if you
+are using `ON_CALL()` to set default actions on the mock object and
+want to clear the default actions as well, use
+`Mock::VerifyAndClear(&mock_object)` instead. This function does what
+`Mock::VerifyAndClearExpectations(&mock_object)` does and returns the
+same `bool`, **plus** it clears the `ON_CALL()` statements on
+`mock_object` too.
+
+Another trick you can use to achieve the same effect is to put the
+expectations in sequences and insert calls to a dummy "check-point"
+function at specific places. Then you can verify that the mock
+function calls do happen at the right time. For example, if you are
+exercising code:
+
+```
+Foo(1);
+Foo(2);
+Foo(3);
+```
+
+and want to verify that `Foo(1)` and `Foo(3)` both invoke
+`mock.Bar("a")`, but `Foo(2)` doesn't invoke anything. You can write:
+
+```
+using ::testing::MockFunction;
+
+TEST(FooTest, InvokesBarCorrectly) {
+  MyMock mock;
+  // Class MockFunction<F> has exactly one mock method.  It is named
+  // Call() and has type F.
+  MockFunction<void(string check_point_name)> check;
+  {
+    InSequence s;
+
+    EXPECT_CALL(mock, Bar("a"));
+    EXPECT_CALL(check, Call("1"));
+    EXPECT_CALL(check, Call("2"));
+    EXPECT_CALL(mock, Bar("a"));
+  }
+  Foo(1);
+  check.Call("1");
+  Foo(2);
+  check.Call("2");
+  Foo(3);
+}
+```
+
+The expectation spec says that the first `Bar("a")` must happen before
+check point "1", the second `Bar("a")` must happen after check point "2",
+and nothing should happen between the two check points. The explicit
+check points make it easy to tell which `Bar("a")` is called by which
+call to `Foo()`.
+
+## Mocking Destructors ##
+
+Sometimes you want to make sure a mock object is destructed at the
+right time, e.g. after `bar->A()` is called but before `bar->B()` is
+called. We already know that you can specify constraints on the order
+of mock function calls, so all we need to do is to mock the destructor
+of the mock function.
+
+This sounds simple, except for one problem: a destructor is a special
+function with special syntax and special semantics, and the
+`MOCK_METHOD0` macro doesn't work for it:
+
+```
+  MOCK_METHOD0(~MockFoo, void());  // Won't compile!
+```
+
+The good news is that you can use a simple pattern to achieve the same
+effect. First, add a mock function `Die()` to your mock class and call
+it in the destructor, like this:
+
+```
+class MockFoo : public Foo {
+  ...
+  // Add the following two lines to the mock class.
+  MOCK_METHOD0(Die, void());
+  virtual ~MockFoo() { Die(); }
+};
+```
+
+(If the name `Die()` clashes with an existing symbol, choose another
+name.) Now, we have translated the problem of testing when a `MockFoo`
+object dies to testing when its `Die()` method is called:
+
+```
+  MockFoo* foo = new MockFoo;
+  MockBar* bar = new MockBar;
+  ...
+  {
+    InSequence s;
+
+    // Expects *foo to die after bar->A() and before bar->B().
+    EXPECT_CALL(*bar, A());
+    EXPECT_CALL(*foo, Die());
+    EXPECT_CALL(*bar, B());
+  }
+```
+
+And that's that.
+
+## Using Google Mock and Threads ##
+
+**IMPORTANT NOTE:** What we describe in this recipe is **NOT** true yet,
+as Google Mock is not currently thread-safe.  However, all we need to
+make it thread-safe is to implement some synchronization operations in
+`<gtest/internal/gtest-port.h>` - and then the information below will
+become true.
+
+In a **unit** test, it's best if you could isolate and test a piece of
+code in a single-threaded context. That avoids race conditions and
+dead locks, and makes debugging your test much easier.
+
+Yet many programs are multi-threaded, and sometimes to test something
+we need to pound on it from more than one thread. Google Mock works
+for this purpose too.
+
+Remember the steps for using a mock:
+
+  1. Create a mock object `foo`.
+  1. Set its default actions and expectations using `ON_CALL()` and `EXPECT_CALL()`.
+  1. The code under test calls methods of `foo`.
+  1. Optionally, verify and reset the mock.
+  1. Destroy the mock yourself, or let the code under test destroy it. The destructor will automatically verify it.
+
+If you follow the following simple rules, your mocks and threads can
+live happily togeter:
+
+  * Execute your _test code_ (as opposed to the code being tested) in _one_ thread. This makes your test easy to follow.
+  * Obviously, you can do step #1 without locking.
+  * When doing step #2 and #5, make sure no other thread is accessing `foo`. Obvious too, huh?
+  * #3 and #4 can be done either in one thread or in multiple threads - anyway you want. Google Mock takes care of the locking, so you don't have to do any - unless required by your test logic.
+
+If you violate the rules (for example, if you set expectations on a
+mock while another thread is calling its methods), you get undefined
+behavior. That's not fun, so don't do it.
+
+Google Mock guarantees that the action for a mock function is done in
+the same thread that called the mock function. For example, in
+
+```
+  EXPECT_CALL(mock, Foo(1))
+      .WillOnce(action1);
+  EXPECT_CALL(mock, Foo(2))
+      .WillOnce(action2);
+```
+
+if `Foo(1)` is called in thread 1 and `Foo(2)` is called in thread 2,
+Google Mock will execute `action1` in thread 1 and `action2` in thread
+2.
+
+Google Mock does _not_ impose a sequence on actions performed in
+different threads (doing so may create deadlocks as the actions may
+need to cooperate). This means that the execution of `action1` and
+`action2` in the above example _may_ interleave. If this is a problem,
+you should add proper synchronization logic to `action1` and `action2`
+to make the test thread-safe.
+
+
+Also, remember that `DefaultValue<T>` is a global resource that
+potentially affects _all_ living mock objects in your
+program. Naturally, you won't want to mess with it from multiple
+threads or when there still are mocks in action.
+
+## Controlling How Much Information Google Mock Prints ##
+
+When Google Mock sees something that has the potential of being an
+error (e.g. a mock function with no expectation is called, a.k.a. an
+uninteresting call, which is allowed but perhaps you forgot to
+explicitly ban the call), it prints some warning messages, including
+the arguments of the function and the return value. Hopefully this
+will remind you to take a look and see if there is indeed a problem.
+
+Sometimes you are confident that your tests are correct and may not
+appreciate such friendly messages. Some other times, you are debugging
+your tests or learning about the behavior of the code you are testing,
+and wish you could observe every mock call that happens (including
+argument values and the return value). Clearly, one size doesn't fit
+all.
+
+You can control how much Google Mock tells you using the
+`--gmock_verbose=LEVEL` command-line flag, where `LEVEL` is a string
+with three possible values:
+
+  * `info`: Google Mock will print all informational messages, warnings, and errors (most verbose). At this setting, Google Mock will also log any calls to the `ON_CALL/EXPECT_CALL` macros.
+  * `warning`: Google Mock will print both warnings and errors (less verbose). This is the default.
+  * `error`: Google Mock will print errors only (least verbose).
+
+Alternatively, you can adjust the value of that flag from within your
+tests like so:
+
+```
+  ::testing::FLAGS_gmock_verbose = "error";
+```
+
+Now, judiciously use the right flag to enable Google Mock serve you better!
+
+## Running Tests in Emacs ##
+
+If you build and run your tests in Emacs, the source file locations of
+Google Mock and [Google Test](http://code.google.com/p/googletest/)
+errors will be highlighted. Just press `<Enter>` on one of them and
+you'll be taken to the offending line. Or, you can just type `C-x ``
+to jump to the next error.
+
+To make it even easier, you can add the following lines to your
+`~/.emacs` file:
+
+```
+(global-set-key "\M-m"   'compile)  ; m is for make
+(global-set-key [M-down] 'next-error)
+(global-set-key [M-up]   '(lambda () (interactive) (next-error -1)))
+```
+
+Then you can type `M-m` to start a build, or `M-up`/`M-down` to move
+back and forth between errors.
+
+## Fusing Google Mock Source Files ##
+
+Google Mock's implementation consists of dozens of files (excluding
+its own tests).  Sometimes you may want them to be packaged up in
+fewer files instead, such that you can easily copy them to a new
+machine and start hacking there.  For this we provide an experimental
+Python script `fuse_gmock_files.py` in the `scripts/` directory
+(starting with release 1.2.0).  Assuming you have Python 2.4 or above
+installed on your machine, just go to that directory and run
+```
+python fuse_gmock_files.py OUTPUT_DIR
+```
+
+and you should see an `OUTPUT_DIR` directory being created with files
+`gtest/gtest.h`, `gmock/gmock.h`, and `gmock-gtest-all.cc` in it.
+These three files contain everything you need to use Google Mock (and
+Google Test).  Just copy them to anywhere you want and you are ready
+to write tests and use mocks.  You can use the
+[scrpts/test/Makefile](http://code.google.com/p/googlemock/source/browse/trunk/scripts/test/Makefile) file as an example on how to compile your tests
+against them.
+
+# Extending Google Mock #
+
+## Writing New Matchers Quickly ##
+
+The `MATCHER*` family of macros can be used to define custom matchers
+easily.  The syntax:
+
+```
+MATCHER(name, "description string") { statements; }
+```
+
+will define a matcher with the given name that executes the
+statements, which must return a `bool` to indicate if the match
+succeeds.  Inside the statements, you can refer to the value being
+matched by `arg`, and refer to its type by `arg_type`.
+
+The description string documents what the matcher does, and is used to
+generate the failure message when the match fails.  Since a
+`MATCHER()` is usually defined in a header file shared by multiple C++
+source files, we require the description to be a C-string _literal_ to
+avoid possible side effects.  It can be empty (`""`), in which case
+Google Mock will use the sequence of words in the matcher name as the
+description.
+
+For example:
+```
+MATCHER(IsDivisibleBy7, "") { return (arg % 7) == 0; }
+```
+allows you to write
+```
+  // Expects mock_foo.Bar(n) to be called where n is divisible by 7.
+  EXPECT_CALL(mock_foo, Bar(IsDivisibleBy7()));
+```
+or,
+```
+  // Verifies that the value of some_expression is divisible by 7.
+  EXPECT_THAT(some_expression, IsDivisibleBy7());
+```
+If the above assertion fails, it will print something like:
+```
+  Value of: some_expression
+  Expected: is divisible by 7
+    Actual: 27
+```
+where the description `"is divisible by 7"` is automatically calculated from the
+matcher name `IsDivisibleBy7`.
+
+Optionally, you can stream additional information to a hidden argument
+named `result_listener` to explain the match result. For example, a
+better definition of `IsDivisibleBy7` is:
+```
+MATCHER(IsDivisibleBy7, "") {
+  if ((arg % 7) == 0)
+    return true;
+
+  *result_listener << "the remainder is " << (arg % 7);
+  return false;
+}
+```
+
+With this definition, the above assertion will give a better message:
+```
+  Value of: some_expression
+  Expected: is divisible by 7
+    Actual: 27 (the remainder is 6)
+```
+
+You should let `MatchAndExplain()` print _any additional information_
+that can help a user understand the match result. Note that it should
+explain why the match succeeds in case of a success (unless it's
+obvious) - this is useful when the matcher is used inside
+`Not()`. There is no need to print the argument value itself, as
+Google Mock already prints it for you.
+
+**Notes:**
+
+  1. The type of the value being matched (`arg_type`) is determined by the context in which you use the matcher and is supplied to you by the compiler, so you don't need to worry about declaring it (nor can you).  This allows the matcher to be polymorphic.  For example, `IsDivisibleBy7()` can be used to match any type where the value of `(arg % 7) == 0` can be implicitly converted to a `bool`.  In the `Bar(IsDivisibleBy7())` example above, if method `Bar()` takes an `int`, `arg_type` will be `int`; if it takes an `unsigned long`, `arg_type` will be `unsigned long`; and so on.
+  1. Google Mock doesn't guarantee when or how many times a matcher will be invoked. Therefore the matcher logic must be _purely functional_ (i.e. it cannot have any side effect, and the result must not depend on anything other than the value being matched and the matcher parameters). This requirement must be satisfied no matter how you define the matcher (e.g. using one of the methods described in the following recipes). In particular, a matcher can never call a mock function, as that will affect the state of the mock object and Google Mock.
+
+## Writing New Parameterized Matchers Quickly ##
+
+Sometimes you'll want to define a matcher that has parameters.  For that you
+can use the macro:
+```
+MATCHER_P(name, param_name, "description string") { statements; }
+```
+
+For example:
+```
+MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; }
+```
+will allow you to write:
+```
+  EXPECT_THAT(Blah("a"), HasAbsoluteValue(n));
+```
+which may lead to this message (assuming `n` is 10):
+```
+  Value of: Blah("a")
+  Expected: has absolute value 10
+    Actual: -9
+```
+
+Note that both the matcher description and its parameter are
+printed, making the message human-friendly.
+
+In the matcher definition body, you can write `foo_type` to
+reference the type of a parameter named `foo`.  For example, in the
+body of `MATCHER_P(HasAbsoluteValue, value)` above, you can write
+`value_type` to refer to the type of `value`.
+
+Google Mock also provides `MATCHER_P2`, `MATCHER_P3`, ..., up to
+`MATCHER_P10` to support multi-parameter matchers:
+```
+MATCHER_Pk(name, param_1, ..., param_k, "description string") { statements; }
+```
+
+Please note that the custom description string is for a particular
+**instance** of the matcher, where the parameters have been bound to
+actual values.  Therefore usually you'll want the parameter values to
+be part of the description.  Google Mock lets you do that using
+Python-style interpolations.  The following syntaxes are supported
+currently:
+
+| `%%` | a single `%` character |
+|:-----|:-----------------------|
+| `%(*)s` | all parameters of the matcher printed as a tuple |
+| `%(foo)s` | value of the matcher parameter named `foo` |
+
+For example,
+```
+  MATCHER_P2(InClosedRange, low, hi, "is in range [%(low)s, %(hi)s]") {
+    return low <= arg && arg <= hi;
+  }
+  ...
+  EXPECT_THAT(3, InClosedRange(4, 6));
+```
+would generate a failure that contains the message:
+```
+  Expected: is in range [4, 6]
+```
+
+If you specify `""` as the description, the failure message will
+contain the sequence of words in the matcher name followed by the
+parameter values printed as a tuple.  For example,
+```
+  MATCHER_P2(InClosedRange, low, hi, "") { ... }
+  ...
+  EXPECT_THAT(3, InClosedRange(4, 6));
+```
+would generate a failure that contains the text:
+```
+  Expected: in closed range (4, 6)
+```
+
+For the purpose of typing, you can view
+```
+MATCHER_Pk(Foo, p1, ..., pk, "description string") { ... }
+```
+as shorthand for
+```
+template <typename p1_type, ..., typename pk_type>
+FooMatcherPk<p1_type, ..., pk_type>
+Foo(p1_type p1, ..., pk_type pk) { ... }
+```
+
+When you write `Foo(v1, ..., vk)`, the compiler infers the types of
+the parameters `v1`, ..., and `vk` for you.  If you are not happy with
+the result of the type inference, you can specify the types by
+explicitly instantiating the template, as in `Foo<long, bool>(5, false)`.
+As said earlier, you don't get to (or need to) specify
+`arg_type` as that's determined by the context in which the matcher
+is used.
+
+You can assign the result of expression `Foo(p1, ..., pk)` to a
+variable of type `FooMatcherPk<p1_type, ..., pk_type>`.  This can be
+useful when composing matchers.  Matchers that don't have a parameter
+or have only one parameter have special types: you can assign `Foo()`
+to a `FooMatcher`-typed variable, and assign `Foo(p)` to a
+`FooMatcherP<p_type>`-typed variable.
+
+While you can instantiate a matcher template with reference types,
+passing the parameters by pointer usually makes your code more
+readable.  If, however, you still want to pass a parameter by
+reference, be aware that in the failure message generated by the
+matcher you will see the value of the referenced object but not its
+address.
+
+You can overload matchers with different numbers of parameters:
+```
+MATCHER_P(Blah, a, "description string 1") { ... }
+MATCHER_P2(Blah, a, b, "description string 2") { ... }
+```
+
+While it's tempting to always use the `MATCHER*` macros when defining
+a new matcher, you should also consider implementing
+`MatcherInterface` or using `MakePolymorphicMatcher()` instead (see
+the recipes that follow), especially if you need to use the matcher a
+lot.  While these approaches require more work, they give you more
+control on the types of the value being matched and the matcher
+parameters, which in general leads to better compiler error messages
+that pay off in the long run.  They also allow overloading matchers
+based on parameter types (as opposed to just based on the number of
+parameters).
+
+## Writing New Monomorphic Matchers ##
+
+A matcher of argument type `T` implements
+`::testing::MatcherInterface<T>` and does two things: it tests whether a
+value of type `T` matches the matcher, and can describe what kind of
+values it matches. The latter ability is used for generating readable
+error messages when expectations are violated.
+
+The interface looks like this:
+
+```
+class MatchResultListener {
+ public:
+  ...
+  // Streams x to the underlying ostream; does nothing if the ostream
+  // is NULL.
+  template <typename T>
+  MatchResultListener& operator<<(const T& x);
+
+  // Returns the underlying ostream.
+  ::std::ostream* stream();
+};
+
+template <typename T>
+class MatcherInterface {
+ public:
+  virtual ~MatcherInterface();
+
+  // Returns true iff the matcher matches x; also explains the match
+  // result to 'listener'.
+  virtual bool MatchAndExplain(T x, MatchResultListener* listener) const = 0;
+
+  // Describes this matcher to an ostream.
+  virtual void DescribeTo(::std::ostream* os) const = 0;
+
+  // Describes the negation of this matcher to an ostream.
+  virtual void DescribeNegationTo(::std::ostream* os) const;
+};
+```
+
+If you need a custom matcher but `Truly()` is not a good option (for
+example, you may not be happy with the way `Truly(predicate)`
+describes itself, or you may want your matcher to be polymorphic as
+`Eq(value)` is), you can define a matcher to do whatever you want in
+two steps: first implement the matcher interface, and then define a
+factory function to create a matcher instance. The second step is not
+strictly needed but it makes the syntax of using the matcher nicer.
+
+For example, you can define a matcher to test whether an `int` is
+divisible by 7 and then use it like this:
+```
+using ::testing::MakeMatcher;
+using ::testing::Matcher;
+using ::testing::MatcherInterface;
+using ::testing::MatchResultListener;
+
+class DivisibleBy7Matcher : public MatcherInterface<int> {
+ public:
+  virtual bool MatchAndExplain(int n, MatchResultListener* listener) const {
+    return (n % 7) == 0;
+  }
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "is divisible by 7";
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "is not divisible by 7";
+  }
+};
+
+inline Matcher<int> DivisibleBy7() {
+  return MakeMatcher(new DivisibleBy7Matcher);
+}
+...
+
+  EXPECT_CALL(foo, Bar(DivisibleBy7()));
+```
+
+You may improve the matcher message by streaming additional
+information to the `listener` argument in `MatchAndExplain()`:
+
+```
+class DivisibleBy7Matcher : public MatcherInterface<int> {
+ public:
+  virtual bool MatchAndExplain(int n,
+                               MatchResultListener* listener) const {
+    const int remainder = n % 7;
+    if (remainder != 0) {
+      *listener << "the remainder is " << remainder;
+    }
+    return remainder == 0;
+  }
+  ...
+};
+```
+
+Then, `EXPECT_THAT(x, DivisibleBy7());` may general a message like this:
+```
+Value of: x
+Expected: is divisible by 7
+  Actual: 23 (the remainder is 2)
+```
+
+## Writing New Polymorphic Matchers ##
+
+You've learned how to write your own matchers in the previous
+recipe. Just one problem: a matcher created using `MakeMatcher()` only
+works for one particular type of arguments. If you want a
+_polymorphic_ matcher that works with arguments of several types (for
+instance, `Eq(x)` can be used to match a `value` as long as `value` ==
+`x` compiles -- `value` and `x` don't have to share the same type),
+you can learn the trick from `<gmock/gmock-matchers.h>` but it's a bit
+involved.
+
+Fortunately, most of the time you can define a polymorphic matcher
+easily with the help of `MakePolymorphicMatcher()`. Here's how you can
+define `NotNull()` as an example:
+
+```
+using ::testing::MakePolymorphicMatcher;
+using ::testing::MatchResultListener;
+using ::testing::NotNull;
+using ::testing::PolymorphicMatcher;
+
+class NotNullMatcher {
+ public:
+  // To implement a polymorphic matcher, first define a COPYABLE class
+  // that has three members MatchAndExplain(), DescribeTo(), and
+  // DescribeNegationTo(), like the following.
+
+  // In this example, we want to use NotNull() with any pointer, so
+  // MatchAndExplain() accepts a pointer of any type as its first argument.
+  // In general, you can define MatchAndExplain() as an ordinary method or
+  // a method template, or even overload it.
+  template <typename T>
+  bool MatchAndExplain(T* p,
+                       MatchResultListener* /* listener */) const {
+    return p != NULL;
+  }
+
+  // Describes the property of a value matching this matcher.
+  void DescribeTo(::std::ostream* os) const { *os << "is not NULL"; }
+
+  // Describes the property of a value NOT matching this matcher.
+  void DescribeNegationTo(::std::ostream* os) const { *os << "is NULL"; }
+};
+
+// To construct a polymorphic matcher, pass an instance of the class
+// to MakePolymorphicMatcher().  Note the return type.
+inline PolymorphicMatcher<NotNullMatcher> NotNull() {
+  return MakePolymorphicMatcher(NotNullMatcher());
+}
+...
+
+  EXPECT_CALL(foo, Bar(NotNull()));  // The argument must be a non-NULL pointer.
+```
+
+**Note:** Your polymorphic matcher class does **not** need to inherit from
+`MatcherInterface` or any other class, and its methods do **not** need
+to be virtual.
+
+Like in a monomorphic matcher, you may explain the match result by
+streaming additional information to the `listener` argument in
+`MatchAndExplain()`.
+
+## Writing New Cardinalities ##
+
+A cardinality is used in `Times()` to tell Google Mock how many times
+you expect a call to occur. It doesn't have to be exact. For example,
+you can say `AtLeast(5)` or `Between(2, 4)`.
+
+If the built-in set of cardinalities doesn't suit you, you are free to
+define your own by implementing the following interface (in namespace
+`testing`):
+
+```
+class CardinalityInterface {
+ public:
+  virtual ~CardinalityInterface();
+
+  // Returns true iff call_count calls will satisfy this cardinality.
+  virtual bool IsSatisfiedByCallCount(int call_count) const = 0;
+
+  // Returns true iff call_count calls will saturate this cardinality.
+  virtual bool IsSaturatedByCallCount(int call_count) const = 0;
+
+  // Describes self to an ostream.
+  virtual void DescribeTo(::std::ostream* os) const = 0;
+};
+```
+
+For example, to specify that a call must occur even number of times,
+you can write
+
+```
+using ::testing::Cardinality;
+using ::testing::CardinalityInterface;
+using ::testing::MakeCardinality;
+
+class EvenNumberCardinality : public CardinalityInterface {
+ public:
+  virtual bool IsSatisfiedByCallCount(int call_count) const {
+    return (call_count % 2) == 0;
+  }
+
+  virtual bool IsSaturatedByCallCount(int call_count) const {
+    return false;
+  }
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "called even number of times";
+  }
+};
+
+Cardinality EvenNumber() {
+  return MakeCardinality(new EvenNumberCardinality);
+}
+...
+
+  EXPECT_CALL(foo, Bar(3))
+      .Times(EvenNumber());
+```
+
+## Writing New Actions Quickly ##
+
+If the built-in actions don't work for you, and you find it
+inconvenient to use `Invoke()`, you can use a macro from the `ACTION*`
+family to quickly define a new action that can be used in your code as
+if it's a built-in action.
+
+By writing
+```
+ACTION(name) { statements; }
+```
+in a namespace scope (i.e. not inside a class or function), you will
+define an action with the given name that executes the statements.
+The value returned by `statements` will be used as the return value of
+the action.  Inside the statements, you can refer to the K-th
+(0-based) argument of the mock function as `argK`.  For example:
+```
+ACTION(IncrementArg1) { return ++(*arg1); }
+```
+allows you to write
+```
+... WillOnce(IncrementArg1());
+```
+
+Note that you don't need to specify the types of the mock function
+arguments.  Rest assured that your code is type-safe though:
+you'll get a compiler error if `*arg1` doesn't support the `++`
+operator, or if the type of `++(*arg1)` isn't compatible with the mock
+function's return type.
+
+Another example:
+```
+ACTION(Foo) {
+  (*arg2)(5);
+  Blah();
+  *arg1 = 0;
+  return arg0;
+}
+```
+defines an action `Foo()` that invokes argument #2 (a function pointer)
+with 5, calls function `Blah()`, sets the value pointed to by argument
+#1 to 0, and returns argument #0.
+
+For more convenience and flexibility, you can also use the following
+pre-defined symbols in the body of `ACTION`:
+
+| `argK_type` | The type of the K-th (0-based) argument of the mock function |
+|:------------|:-------------------------------------------------------------|
+| `args`      | All arguments of the mock function as a tuple                |
+| `args_type` | The type of all arguments of the mock function as a tuple    |
+| `return_type` | The return type of the mock function                         |
+| `function_type` | The type of the mock function                                |
+
+For example, when using an `ACTION` as a stub action for mock function:
+```
+int DoSomething(bool flag, int* ptr);
+```
+we have:
+| **Pre-defined Symbol** | **Is Bound To** |
+|:-----------------------|:----------------|
+| `arg0`                 | the value of `flag` |
+| `arg0_type`            | the type `bool` |
+| `arg1`                 | the value of `ptr` |
+| `arg1_type`            | the type `int*` |
+| `args`                 | the tuple `(flag, ptr)` |
+| `args_type`            | the type `std::tr1::tuple<bool, int*>` |
+| `return_type`          | the type `int`  |
+| `function_type`        | the type `int(bool, int*)` |
+
+## Writing New Parameterized Actions Quickly ##
+
+Sometimes you'll want to parameterize an action you define.  For that
+we have another macro
+```
+ACTION_P(name, param) { statements; }
+```
+
+For example,
+```
+ACTION_P(Add, n) { return arg0 + n; }
+```
+will allow you to write
+```
+// Returns argument #0 + 5.
+... WillOnce(Add(5));
+```
+
+For convenience, we use the term _arguments_ for the values used to
+invoke the mock function, and the term _parameters_ for the values
+used to instantiate an action.
+
+Note that you don't need to provide the type of the parameter either.
+Suppose the parameter is named `param`, you can also use the
+Google-Mock-defined symbol `param_type` to refer to the type of the
+parameter as inferred by the compiler.  For example, in the body of
+`ACTION_P(Add, n)` above, you can write `n_type` for the type of `n`.
+
+Google Mock also provides `ACTION_P2`, `ACTION_P3`, and etc to support
+multi-parameter actions.  For example,
+```
+ACTION_P2(ReturnDistanceTo, x, y) {
+  double dx = arg0 - x;
+  double dy = arg1 - y;
+  return sqrt(dx*dx + dy*dy);
+}
+```
+lets you write
+```
+... WillOnce(ReturnDistanceTo(5.0, 26.5));
+```
+
+You can view `ACTION` as a degenerated parameterized action where the
+number of parameters is 0.
+
+You can also easily define actions overloaded on the number of parameters:
+```
+ACTION_P(Plus, a) { ... }
+ACTION_P2(Plus, a, b) { ... }
+```
+
+## Restricting the Type of an Argument or Parameter in an ACTION ##
+
+For maximum brevity and reusability, the `ACTION*` macros don't ask
+you to provide the types of the mock function arguments and the action
+parameters.  Instead, we let the compiler infer the types for us.
+
+Sometimes, however, we may want to be more explicit about the types.
+There are several tricks to do that.  For example:
+```
+ACTION(Foo) {
+  // Makes sure arg0 can be converted to int.
+  int n = arg0;
+  ... use n instead of arg0 here ...
+}
+
+ACTION_P(Bar, param) {
+  // Makes sure the type of arg1 is const char*.
+  ::testing::StaticAssertTypeEq<const char*, arg1_type>();
+
+  // Makes sure param can be converted to bool.
+  bool flag = param;
+}
+```
+where `StaticAssertTypeEq` is a compile-time assertion in Google Test
+that verifies two types are the same.
+
+## Writing New Action Templates Quickly ##
+
+Sometimes you want to give an action explicit template parameters that
+cannot be inferred from its value parameters.  `ACTION_TEMPLATE()`
+supports that and can be viewed as an extension to `ACTION()` and
+`ACTION_P*()`.
+
+The syntax:
+```
+ACTION_TEMPLATE(ActionName,
+                HAS_m_TEMPLATE_PARAMS(kind1, name1, ..., kind_m, name_m),
+                AND_n_VALUE_PARAMS(p1, ..., p_n)) { statements; }
+```
+
+defines an action template that takes _m_ explicit template parameters
+and _n_ value parameters, where _m_ is between 1 and 10, and _n_ is
+between 0 and 10.  `name_i` is the name of the i-th template
+parameter, and `kind_i` specifies whether it's a `typename`, an
+integral constant, or a template.  `p_i` is the name of the i-th value
+parameter.
+
+Example:
+```
+// DuplicateArg<k, T>(output) converts the k-th argument of the mock
+// function to type T and copies it to *output.
+ACTION_TEMPLATE(DuplicateArg,
+                // Note the comma between int and k:
+                HAS_2_TEMPLATE_PARAMS(int, k, typename, T),
+                AND_1_VALUE_PARAMS(output)) {
+  *output = T(std::tr1::get<k>(args));
+}
+```
+
+To create an instance of an action template, write:
+```
+  ActionName<t1, ..., t_m>(v1, ..., v_n)
+```
+where the `t`s are the template arguments and the
+`v`s are the value arguments.  The value argument
+types are inferred by the compiler.  For example:
+```
+using ::testing::_;
+...
+  int n;
+  EXPECT_CALL(mock, Foo(_, _))
+      .WillOnce(DuplicateArg<1, unsigned char>(&n));
+```
+
+If you want to explicitly specify the value argument types, you can
+provide additional template arguments:
+```
+  ActionName<t1, ..., t_m, u1, ..., u_k>(v1, ..., v_n)
+```
+where `u_i` is the desired type of `v_i`.
+
+`ACTION_TEMPLATE` and `ACTION`/`ACTION_P*` can be overloaded on the
+number of value parameters, but not on the number of template
+parameters.  Without the restriction, the meaning of the following is
+unclear:
+
+```
+  OverloadedAction<int, bool>(x);
+```
+
+Are we using a single-template-parameter action where `bool` refers to
+the type of `x`, or a two-template-parameter action where the compiler
+is asked to infer the type of `x`?
+
+## Using the ACTION Object's Type ##
+
+If you are writing a function that returns an `ACTION` object, you'll
+need to know its type.  The type depends on the macro used to define
+the action and the parameter types.  The rule is relatively simple:
+| **Given Definition** | **Expression** | **Has Type** |
+|:---------------------|:---------------|:-------------|
+| `ACTION(Foo)`        | `Foo()`        | `FooAction`  |
+| `ACTION_TEMPLATE(Foo, HAS_m_TEMPLATE_PARAMS(...), AND_0_VALUE_PARAMS())` |	`Foo<t1, ..., t_m>()` | `FooAction<t1, ..., t_m>` |
+| `ACTION_P(Bar, param)` | `Bar(int_value)` | `BarActionP<int>` |
+| `ACTION_TEMPLATE(Bar, HAS_m_TEMPLATE_PARAMS(...), AND_1_VALUE_PARAMS(p1))` | `Bar<t1, ..., t_m>(int_value)` | `FooActionP<t1, ..., t_m, int>` |
+| `ACTION_P2(Baz, p1, p2)` | `Baz(bool_value, int_value)` | `BazActionP2<bool, int>` |
+| `ACTION_TEMPLATE(Baz, HAS_m_TEMPLATE_PARAMS(...), AND_2_VALUE_PARAMS(p1, p2))` | `Baz<t1, ..., t_m>(bool_value, int_value)` | `FooActionP2<t1, ..., t_m, bool, int>` |
+| ...                  | ...            | ...          |
+
+Note that we have to pick different suffixes (`Action`, `ActionP`,
+`ActionP2`, and etc) for actions with different numbers of value
+parameters, or the action definitions cannot be overloaded on the
+number of them.
+
+## Writing New Monomorphic Actions ##
+
+While the `ACTION*` macros are very convenient, sometimes they are
+inappropriate.  For example, despite the tricks shown in the previous
+recipes, they don't let you directly specify the types of the mock
+function arguments and the action parameters, which in general leads
+to unoptimized compiler error messages that can baffle unfamiliar
+users.  They also don't allow overloading actions based on parameter
+types without jumping through some hoops.
+
+An alternative to the `ACTION*` macros is to implement
+`::testing::ActionInterface<F>`, where `F` is the type of the mock
+function in which the action will be used. For example:
+
+```
+template <typename F>class ActionInterface {
+ public:
+  virtual ~ActionInterface();
+
+  // Performs the action.  Result is the return type of function type
+  // F, and ArgumentTuple is the tuple of arguments of F.
+  //
+  // For example, if F is int(bool, const string&), then Result would
+  // be int, and ArgumentTuple would be tr1::tuple<bool, const string&>.
+  virtual Result Perform(const ArgumentTuple& args) = 0;
+};
+
+using ::testing::_;
+using ::testing::Action;
+using ::testing::ActionInterface;
+using ::testing::MakeAction;
+
+typedef int IncrementMethod(int*);
+
+class IncrementArgumentAction : public ActionInterface<IncrementMethod> {
+ public:
+  virtual int Perform(const tr1::tuple<int*>& args) {
+    int* p = tr1::get<0>(args);  // Grabs the first argument.
+    return *p++;
+  }
+};
+
+Action<IncrementMethod> IncrementArgument() {
+  return MakeAction(new IncrementArgumentAction);
+}
+...
+
+  EXPECT_CALL(foo, Baz(_))
+      .WillOnce(IncrementArgument());
+
+  int n = 5;
+  foo.Baz(&n);  // Should return 5 and change n to 6.
+```
+
+## Writing New Polymorphic Actions ##
+
+The previous recipe showed you how to define your own action. This is
+all good, except that you need to know the type of the function in
+which the action will be used. Sometimes that can be a problem. For
+example, if you want to use the action in functions with _different_
+types (e.g. like `Return()` and `SetArgumentPointee()`).
+
+If an action can be used in several types of mock functions, we say
+it's _polymorphic_. The `MakePolymorphicAction()` function template
+makes it easy to define such an action:
+
+```
+namespace testing {
+
+template <typename Impl>
+PolymorphicAction<Impl> MakePolymorphicAction(const Impl& impl);
+
+}  // namespace testing
+```
+
+As an example, let's define an action that returns the second argument
+in the mock function's argument list. The first step is to define an
+implementation class:
+
+```
+class ReturnSecondArgumentAction {
+ public:
+  template <typename Result, typename ArgumentTuple>
+  Result Perform(const ArgumentTuple& args) const {
+    // To get the i-th (0-based) argument, use tr1::get<i>(args).
+    return tr1::get<1>(args);
+  }
+};
+```
+
+This implementation class does _not_ need to inherit from any
+particular class. What matters is that it must have a `Perform()`
+method template. This method template takes the mock function's
+arguments as a tuple in a **single** argument, and returns the result of
+the action. It can be either `const` or not, but must be invokable
+with exactly one template argument, which is the result type. In other
+words, you must be able to call `Perform<R>(args)` where `R` is the
+mock function's return type and `args` is its arguments in a tuple.
+
+Next, we use `MakePolymorphicAction()` to turn an instance of the
+implementation class into the polymorphic action we need. It will be
+convenient to have a wrapper for this:
+
+```
+using ::testing::MakePolymorphicAction;
+using ::testing::PolymorphicAction;
+
+PolymorphicAction<ReturnSecondArgumentAction> ReturnSecondArgument() {
+  return MakePolymorphicAction(ReturnSecondArgumentAction());
+}
+```
+
+Now, you can use this polymorphic action the same way you use the
+built-in ones:
+
+```
+using ::testing::_;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD2(DoThis, int(bool flag, int n));
+  MOCK_METHOD3(DoThat, string(int x, const char* str1, const char* str2));
+};
+...
+
+  MockFoo foo;
+  EXPECT_CALL(foo, DoThis(_, _))
+      .WillOnce(ReturnSecondArgument());
+  EXPECT_CALL(foo, DoThat(_, _, _))
+      .WillOnce(ReturnSecondArgument());
+  ...
+  foo.DoThis(true, 5);         // Will return 5.
+  foo.DoThat(1, "Hi", "Bye");  // Will return "Hi".
+```
+
+## Teaching Google Mock How to Print Your Values ##
+
+When an uninteresting or unexpected call occurs, Google Mock prints
+the argument values to help you debug.  The `EXPECT_THAT` and
+`ASSERT_THAT` assertions also print the value being validated when the
+test fails.  Google Mock does this using the user-extensible value
+printer defined in `<gmock/gmock-printers.h>`.
+
+This printer knows how to print the built-in C++ types, native arrays,
+STL containers, and any type that supports the `<<` operator. For
+other types, it prints the raw bytes in the value and hope you the
+user can figure it out.
+
+Did I say that the printer is `extensible`? That means you can teach
+it to do a better job at printing your particular type than to dump
+the bytes. To do that, you just need to define `<<` for your type:
+
+```
+#include <iostream>
+
+namespace foo {
+
+class Foo { ... };
+
+// It's important that the << operator is defined in the SAME
+// namespace that defines Foo.  C++'s look-up rules rely on that.
+::std::ostream& operator<<(::std::ostream& os, const Foo& foo) {
+  return os << foo.DebugString();  // Whatever needed to print foo to os.
+}
+
+}  // namespace foo
+```
+
+Sometimes, this might not be an option. For example, your team may
+consider it dangerous or bad style to have a `<<` operator for `Foo`,
+or `Foo` may already have a `<<` operator that doesn't do what you
+want (and you cannot change it). Don't despair though - Google Mock
+gives you a second chance to get it right. Namely, you can define a
+`PrintTo()` function like this:
+
+```
+#include <iostream>
+
+namespace foo {
+
+class Foo { ... };
+
+// It's important that PrintTo() is defined in the SAME
+// namespace that defines Foo.  C++'s look-up rules rely on that.
+void PrintTo(const Foo& foo, ::std::ostream* os) {
+  *os << foo.DebugString();  // Whatever needed to print foo to os.
+}
+
+}  // namespace foo
+```
+
+What if you have both `<<` and `PrintTo()`? In this case, the latter
+will override the former when Google Mock is concerned. This allows
+you to customize how the value should appear in Google Mock's output
+without affecting code that relies on the behavior of its `<<`
+operator.
+
+**Note:** When printing a pointer of type `T*`, Google Mock calls
+`PrintTo(T*, std::ostream* os)` instead of `operator<<(std::ostream&, T*)`.
+Therefore the only way to affect how a pointer is printed by Google
+Mock is to define `PrintTo()` for it. Also note that `T*` and `const T*`
+are different types, so you may need to define `PrintTo()` for both.
+
+Why does Google Mock treat pointers specially? There are several reasons:
+
+  * We cannot use `operator<<` to print a `signed char*` or `unsigned char*`, since it will print the pointer as a NUL-terminated C string, which likely will cause an access violation.
+  * We want `NULL` pointers to be printed as `"NULL"`, but `operator<<` prints it as `"0"`, `"nullptr"`, or something else, depending on the compiler.
+  * With some compilers, printing a `NULL` `char*` using `operator<<` will segfault.
+  * `operator<<` prints a function pointer as a `bool` (hence it always prints `"1"`), which is not very useful.
\ No newline at end of file
diff --git a/third_party/googletest/googlemock/docs/v1_5/Documentation.md b/third_party/googletest/googlemock/docs/v1_5/Documentation.md
new file mode 100644
index 0000000..315b0a2
--- /dev/null
+++ b/third_party/googletest/googlemock/docs/v1_5/Documentation.md
@@ -0,0 +1,11 @@
+This page lists all documentation wiki pages for Google Mock **version 1.5.0** -- **if you use a different version of Google Mock, please read the documentation for that specific version instead.**
+
+  * [ForDummies](V1_5_ForDummies.md) -- start here if you are new to Google Mock.
+  * [CheatSheet](V1_5_CheatSheet.md) -- a quick reference.
+  * [CookBook](V1_5_CookBook.md) -- recipes for doing various tasks using Google Mock.
+  * [FrequentlyAskedQuestions](V1_5_FrequentlyAskedQuestions.md) -- check here before asking a question on the mailing list.
+
+To contribute code to Google Mock, read:
+
+  * DevGuide -- read this _before_ writing your first patch.
+  * [Pump Manual](http://code.google.com/p/googletest/wiki/PumpManual) -- how we generate some of Google Mock's source files.
\ No newline at end of file
diff --git a/third_party/googletest/googlemock/docs/v1_5/ForDummies.md b/third_party/googletest/googlemock/docs/v1_5/ForDummies.md
new file mode 100644
index 0000000..f389606
--- /dev/null
+++ b/third_party/googletest/googlemock/docs/v1_5/ForDummies.md
@@ -0,0 +1,439 @@
+
+
+(**Note:** If you get compiler errors that you don't understand, be sure to consult [Google Mock Doctor](V1_5_FrequentlyAskedQuestions#How_am_I_supposed_to_make_sense_of_these_horrible_template_error.md).)
+
+# What Is Google C++ Mocking Framework? #
+When you write a prototype or test, often it's not feasible or wise to rely on real objects entirely. A **mock object** implements the same interface as a real object (so it can be used as one), but lets you specify at run time how it will be used and what it should do (which methods will be called? in which order? how many times? with what arguments? what will they return? etc).
+
+**Note:** It is easy to confuse the term _fake objects_ with mock objects. Fakes and mocks actually mean very different things in the Test-Driven Development (TDD) community:
+
+  * **Fake** objects have working implementations, but usually take some shortcut (perhaps to make the operations less expensive), which makes them not suitable for production. An in-memory file system would be an example of a fake.
+  * **Mocks** are objects pre-programmed with _expectations_, which form a specification of the calls they are expected to receive.
+
+If all this seems too abstract for you, don't worry - the most important thing to remember is that a mock allows you to check the _interaction_ between itself and code that uses it. The difference between fakes and mocks will become much clearer once you start to use mocks.
+
+**Google C++ Mocking Framework** (or **Google Mock** for short) is a library (sometimes we also call it a "framework" to make it sound cool) for creating mock classes and using them. It does to C++ what [jMock](http://www.jmock.org/) and [EasyMock](http://www.easymock.org/) do to Java.
+
+Using Google Mock involves three basic steps:
+
+  1. Use some simple macros to describe the interface you want to mock, and they will expand to the implementation of your mock class;
+  1. Create some mock objects and specify its expectations and behavior using an intuitive syntax;
+  1. Exercise code that uses the mock objects. Google Mock will catch any violation of the expectations as soon as it arises.
+
+# Why Google Mock? #
+While mock objects help you remove unnecessary dependencies in tests and make them fast and reliable, using mocks manually in C++ is _hard_:
+
+  * Someone has to implement the mocks. The job is usually tedious and error-prone. No wonder people go great distance to avoid it.
+  * The quality of those manually written mocks is a bit, uh, unpredictable. You may see some really polished ones, but you may also see some that were hacked up in a hurry and have all sorts of ad hoc restrictions.
+  * The knowledge you gained from using one mock doesn't transfer to the next.
+
+In contrast, Java and Python programmers have some fine mock frameworks, which automate the creation of mocks. As a result, mocking is a proven effective technique and widely adopted practice in those communities. Having the right tool absolutely makes the difference.
+
+Google Mock was built to help C++ programmers. It was inspired by [jMock](http://www.jmock.org/) and [EasyMock](http://www.easymock.org/), but designed with C++'s specifics in mind. It is your friend if any of the following problems is bothering you:
+
+  * You are stuck with a sub-optimal design and wish you had done more prototyping before it was too late, but prototyping in C++ is by no means "rapid".
+  * Your tests are slow as they depend on too many libraries or use expensive resources (e.g. a database).
+  * Your tests are brittle as some resources they use are unreliable (e.g. the network).
+  * You want to test how your code handles a failure (e.g. a file checksum error), but it's not easy to cause one.
+  * You need to make sure that your module interacts with other modules in the right way, but it's hard to observe the interaction; therefore you resort to observing the side effects at the end of the action, which is awkward at best.
+  * You want to "mock out" your dependencies, except that they don't have mock implementations yet; and, frankly, you aren't thrilled by some of those hand-written mocks.
+
+We encourage you to use Google Mock as:
+
+  * a _design_ tool, for it lets you experiment with your interface design early and often. More iterations lead to better designs!
+  * a _testing_ tool to cut your tests' outbound dependencies and probe the interaction between your module and its collaborators.
+
+# Getting Started #
+Using Google Mock is easy! Inside your C++ source file, just #include `<gtest/gtest.h>` and `<gmock/gmock.h>`, and you are ready to go.
+
+# A Case for Mock Turtles #
+Let's look at an example. Suppose you are developing a graphics program that relies on a LOGO-like API for drawing. How would you test that it does the right thing? Well, you can run it and compare the screen with a golden screen snapshot, but let's admit it: tests like this are expensive to run and fragile (What if you just upgraded to a shiny new graphics card that has better anti-aliasing? Suddenly you have to update all your golden images.). It would be too painful if all your tests are like this. Fortunately, you learned about Dependency Injection and know the right thing to do: instead of having your application talk to the drawing API directly, wrap the API in an interface (say, `Turtle`) and code to that interface:
+
+```
+class Turtle {
+  ...
+  virtual ~Turtle() {}
+  virtual void PenUp() = 0;
+  virtual void PenDown() = 0;
+  virtual void Forward(int distance) = 0;
+  virtual void Turn(int degrees) = 0;
+  virtual void GoTo(int x, int y) = 0;
+  virtual int GetX() const = 0;
+  virtual int GetY() const = 0;
+};
+```
+
+(Note that the destructor of `Turtle` **must** be virtual, as is the case for **all** classes you intend to inherit from - otherwise the destructor of the derived class will not be called when you delete an object through a base pointer, and you'll get corrupted program states like memory leaks.)
+
+You can control whether the turtle's movement will leave a trace using `PenUp()` and `PenDown()`, and control its movement using `Forward()`, `Turn()`, and `GoTo()`. Finally, `GetX()` and `GetY()` tell you the current position of the turtle.
+
+Your program will normally use a real implementation of this interface. In tests, you can use a mock implementation instead. This allows you to easily check what drawing primitives your program is calling, with what arguments, and in which order. Tests written this way are much more robust (they won't break because your new machine does anti-aliasing differently), easier to read and maintain (the intent of a test is expressed in the code, not in some binary images), and run _much, much faster_.
+
+# Writing the Mock Class #
+If you are lucky, the mocks you need to use have already been implemented by some nice people. If, however, you find yourself in the position to write a mock class, relax - Google Mock turns this task into a fun game! (Well, almost.)
+
+## How to Define It ##
+Using the `Turtle` interface as example, here are the simple steps you need to follow:
+
+  1. Derive a class `MockTurtle` from `Turtle`.
+  1. Take a virtual function of `Turtle`. Count how many arguments it has.
+  1. In the `public:` section of the child class, write `MOCK_METHODn();` (or `MOCK_CONST_METHODn();` if you are mocking a `const` method), where `n` is the number of the arguments; if you counted wrong, shame on you, and a compiler error will tell you so.
+  1. Now comes the fun part: you take the function signature, cut-and-paste the _function name_ as the _first_ argument to the macro, and leave what's left as the _second_ argument (in case you're curious, this is the _type of the function_).
+  1. Repeat until all virtual functions you want to mock are done.
+
+After the process, you should have something like:
+
+```
+#include <gmock/gmock.h>  // Brings in Google Mock.
+class MockTurtle : public Turtle {
+ public:
+  ...
+  MOCK_METHOD0(PenUp, void());
+  MOCK_METHOD0(PenDown, void());
+  MOCK_METHOD1(Forward, void(int distance));
+  MOCK_METHOD1(Turn, void(int degrees));
+  MOCK_METHOD2(GoTo, void(int x, int y));
+  MOCK_CONST_METHOD0(GetX, int());
+  MOCK_CONST_METHOD0(GetY, int());
+};
+```
+
+You don't need to define these mock methods somewhere else - the `MOCK_METHOD*` macros will generate the definitions for you. It's that simple! Once you get the hang of it, you can pump out mock classes faster than your source-control system can handle your check-ins.
+
+**Tip:** If even this is too much work for you, you'll find the
+`gmock_gen.py` tool in Google Mock's `scripts/generator/` directory (courtesy of the [cppclean](http://code.google.com/p/cppclean/) project) useful.  This command-line
+tool requires that you have Python 2.4 installed.  You give it a C++ file and the name of an abstract class defined in it,
+and it will print the definition of the mock class for you.  Due to the
+complexity of the C++ language, this script may not always work, but
+it can be quite handy when it does.  For more details, read the [user documentation](http://code.google.com/p/googlemock/source/browse/trunk/scripts/generator/README).
+
+## Where to Put It ##
+When you define a mock class, you need to decide where to put its definition. Some people put it in a `*_test.cc`. This is fine when the interface being mocked (say, `Foo`) is owned by the same person or team. Otherwise, when the owner of `Foo` changes it, your test could break. (You can't really expect `Foo`'s maintainer to fix every test that uses `Foo`, can you?)
+
+So, the rule of thumb is: if you need to mock `Foo` and it's owned by others, define the mock class in `Foo`'s package (better, in a `testing` sub-package such that you can clearly separate production code and testing utilities), and put it in a `mock_foo.h`. Then everyone can reference `mock_foo.h` from their tests. If `Foo` ever changes, there is only one copy of `MockFoo` to change, and only tests that depend on the changed methods need to be fixed.
+
+Another way to do it: you can introduce a thin layer `FooAdaptor` on top of `Foo` and code to this new interface. Since you own `FooAdaptor`, you can absorb changes in `Foo` much more easily. While this is more work initially, carefully choosing the adaptor interface can make your code easier to write and more readable (a net win in the long run), as you can choose `FooAdaptor` to fit your specific domain much better than `Foo` does.
+
+# Using Mocks in Tests #
+Once you have a mock class, using it is easy. The typical work flow is:
+
+  1. Import the Google Mock names from the `testing` namespace such that you can use them unqualified (You only have to do it once per file. Remember that namespaces are a good idea and good for your health.).
+  1. Create some mock objects.
+  1. Specify your expectations on them (How many times will a method be called? With what arguments? What should it do? etc.).
+  1. Exercise some code that uses the mocks; optionally, check the result using Google Test assertions. If a mock method is called more than expected or with wrong arguments, you'll get an error immediately.
+  1. When a mock is destructed, Google Mock will automatically check whether all expectations on it have been satisfied.
+
+Here's an example:
+
+```
+#include "path/to/mock-turtle.h"
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+using ::testing::AtLeast;                     // #1
+
+TEST(PainterTest, CanDrawSomething) {
+  MockTurtle turtle;                          // #2
+  EXPECT_CALL(turtle, PenDown())              // #3
+      .Times(AtLeast(1));
+
+  Painter painter(&turtle);                   // #4
+
+  EXPECT_TRUE(painter.DrawCircle(0, 0, 10));
+}                                             // #5
+
+int main(int argc, char** argv) {
+  // The following line must be executed to initialize Google Mock
+  // (and Google Test) before running the tests.
+  ::testing::InitGoogleMock(&argc, argv);
+  return RUN_ALL_TESTS();
+}
+```
+
+As you might have guessed, this test checks that `PenDown()` is called at least once. If the `painter` object didn't call this method, your test will fail with a message like this:
+
+```
+path/to/my_test.cc:119: Failure
+Actual function call count doesn't match this expectation:
+Actually: never called;
+Expected: called at least once.
+```
+
+**Tip 1:** If you run the test from an Emacs buffer, you can hit `<Enter>` on the line number displayed in the error message to jump right to the failed expectation.
+
+**Tip 2:** If your mock objects are never deleted, the final verification won't happen. Therefore it's a good idea to use a heap leak checker in your tests when you allocate mocks on the heap.
+
+**Important note:** Google Mock requires expectations to be set **before** the mock functions are called, otherwise the behavior is **undefined**. In particular, you mustn't interleave `EXPECT_CALL()`s and calls to the mock functions.
+
+This means `EXPECT_CALL()` should be read as expecting that a call will occur _in the future_, not that a call has occurred. Why does Google Mock work like that? Well, specifying the expectation beforehand allows Google Mock to report a violation as soon as it arises, when the context (stack trace, etc) is still available. This makes debugging much easier.
+
+Admittedly, this test is contrived and doesn't do much. You can easily achieve the same effect without using Google Mock. However, as we shall reveal soon, Google Mock allows you to do _much more_ with the mocks.
+
+## Using Google Mock with Any Testing Framework ##
+If you want to use something other than Google Test (e.g. [CppUnit](http://apps.sourceforge.net/mediawiki/cppunit/index.php?title=Main_Page) or
+[CxxTest](http://cxxtest.tigris.org/)) as your testing framework, just change the `main()` function in the previous section to:
+```
+int main(int argc, char** argv) {
+  // The following line causes Google Mock to throw an exception on failure,
+  // which will be interpreted by your testing framework as a test failure.
+  ::testing::GTEST_FLAG(throw_on_failure) = true;
+  ::testing::InitGoogleMock(&argc, argv);
+  ... whatever your testing framework requires ...
+}
+```
+
+This approach has a catch: it makes Google Mock throw an exception
+from a mock object's destructor sometimes.  With some compilers, this
+sometimes causes the test program to crash.  You'll still be able to
+notice that the test has failed, but it's not a graceful failure.
+
+A better solution is to use Google Test's
+[event listener API](http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide#Extending_Google_Test_by_Handling_Test_Events)
+to report a test failure to your testing framework properly.  You'll need to
+implement the `OnTestPartResult()` method of the event listener interface, but it
+should be straightforward.
+
+If this turns out to be too much work, we suggest that you stick with
+Google Test, which works with Google Mock seamlessly (in fact, it is
+technically part of Google Mock.).  If there is a reason that you
+cannot use Google Test, please let us know.
+
+# Setting Expectations #
+The key to using a mock object successfully is to set the _right expectations_ on it. If you set the expectations too strict, your test will fail as the result of unrelated changes. If you set them too loose, bugs can slip through. You want to do it just right such that your test can catch exactly the kind of bugs you intend it to catch. Google Mock provides the necessary means for you to do it "just right."
+
+## General Syntax ##
+In Google Mock we use the `EXPECT_CALL()` macro to set an expectation on a mock method. The general syntax is:
+
+```
+EXPECT_CALL(mock_object, method(matchers))
+    .Times(cardinality)
+    .WillOnce(action)
+    .WillRepeatedly(action);
+```
+
+The macro has two arguments: first the mock object, and then the method and its arguments. Note that the two are separated by a comma (`,`), not a period (`.`). (Why using a comma? The answer is that it was necessary for technical reasons.)
+
+The macro can be followed by some optional _clauses_ that provide more information about the expectation. We'll discuss how each clause works in the coming sections.
+
+This syntax is designed to make an expectation read like English. For example, you can probably guess that
+
+```
+using ::testing::Return;...
+EXPECT_CALL(turtle, GetX())
+    .Times(5)
+    .WillOnce(Return(100))
+    .WillOnce(Return(150))
+    .WillRepeatedly(Return(200));
+```
+
+says that the `turtle` object's `GetX()` method will be called five times, it will return 100 the first time, 150 the second time, and then 200 every time. Some people like to call this style of syntax a Domain-Specific Language (DSL).
+
+**Note:** Why do we use a macro to do this? It serves two purposes: first it makes expectations easily identifiable (either by `grep` or by a human reader), and second it allows Google Mock to include the source file location of a failed expectation in messages, making debugging easier.
+
+## Matchers: What Arguments Do We Expect? ##
+When a mock function takes arguments, we must specify what arguments we are expecting; for example:
+
+```
+// Expects the turtle to move forward by 100 units.
+EXPECT_CALL(turtle, Forward(100));
+```
+
+Sometimes you may not want to be too specific (Remember that talk about tests being too rigid? Over specification leads to brittle tests and obscures the intent of tests. Therefore we encourage you to specify only what's necessary - no more, no less.). If you care to check that `Forward()` will be called but aren't interested in its actual argument, write `_` as the argument, which means "anything goes":
+
+```
+using ::testing::_;
+...
+// Expects the turtle to move forward.
+EXPECT_CALL(turtle, Forward(_));
+```
+
+`_` is an instance of what we call **matchers**. A matcher is like a predicate and can test whether an argument is what we'd expect. You can use a matcher inside `EXPECT_CALL()` wherever a function argument is expected.
+
+A list of built-in matchers can be found in the [CheatSheet](V1_5_CheatSheet.md). For example, here's the `Ge` (greater than or equal) matcher:
+
+```
+using ::testing::Ge;...
+EXPECT_CALL(turtle, Forward(Ge(100)));
+```
+
+This checks that the turtle will be told to go forward by at least 100 units.
+
+## Cardinalities: How Many Times Will It Be Called? ##
+The first clause we can specify following an `EXPECT_CALL()` is `Times()`. We call its argument a **cardinality** as it tells _how many times_ the call should occur. It allows us to repeat an expectation many times without actually writing it as many times. More importantly, a cardinality can be "fuzzy", just like a matcher can be. This allows a user to express the intent of a test exactly.
+
+An interesting special case is when we say `Times(0)`. You may have guessed - it means that the function shouldn't be called with the given arguments at all, and Google Mock will report a Google Test failure whenever the function is (wrongfully) called.
+
+We've seen `AtLeast(n)` as an example of fuzzy cardinalities earlier. For the list of built-in cardinalities you can use, see the [CheatSheet](V1_5_CheatSheet.md).
+
+The `Times()` clause can be omitted. **If you omit `Times()`, Google Mock will infer the cardinality for you.** The rules are easy to remember:
+
+  * If **neither** `WillOnce()` **nor** `WillRepeatedly()` is in the `EXPECT_CALL()`, the inferred cardinality is `Times(1)`.
+  * If there are `n WillOnce()`'s but **no** `WillRepeatedly()`, where `n` >= 1, the cardinality is `Times(n)`.
+  * If there are `n WillOnce()`'s and **one** `WillRepeatedly()`, where `n` >= 0, the cardinality is `Times(AtLeast(n))`.
+
+**Quick quiz:** what do you think will happen if a function is expected to be called twice but actually called four times?
+
+## Actions: What Should It Do? ##
+Remember that a mock object doesn't really have a working implementation? We as users have to tell it what to do when a method is invoked. This is easy in Google Mock.
+
+First, if the return type of a mock function is a built-in type or a pointer, the function has a **default action** (a `void` function will just return, a `bool` function will return `false`, and other functions will return 0). If you don't say anything, this behavior will be used.
+
+Second, if a mock function doesn't have a default action, or the default action doesn't suit you, you can specify the action to be taken each time the expectation matches using a series of `WillOnce()` clauses followed by an optional `WillRepeatedly()`. For example,
+
+```
+using ::testing::Return;...
+EXPECT_CALL(turtle, GetX())
+    .WillOnce(Return(100))
+    .WillOnce(Return(200))
+    .WillOnce(Return(300));
+```
+
+This says that `turtle.GetX()` will be called _exactly three times_ (Google Mock inferred this from how many `WillOnce()` clauses we've written, since we didn't explicitly write `Times()`), and will return 100, 200, and 300 respectively.
+
+```
+using ::testing::Return;...
+EXPECT_CALL(turtle, GetY())
+    .WillOnce(Return(100))
+    .WillOnce(Return(200))
+    .WillRepeatedly(Return(300));
+```
+
+says that `turtle.GetY()` will be called _at least twice_ (Google Mock knows this as we've written two `WillOnce()` clauses and a `WillRepeatedly()` while having no explicit `Times()`), will return 100 the first time, 200 the second time, and 300 from the third time on.
+
+Of course, if you explicitly write a `Times()`, Google Mock will not try to infer the cardinality itself. What if the number you specified is larger than there are `WillOnce()` clauses? Well, after all `WillOnce()`s are used up, Google Mock will do the _default_ action for the function every time (unless, of course, you have a `WillRepeatedly()`.).
+
+What can we do inside `WillOnce()` besides `Return()`? You can return a reference using `ReturnRef(variable)`, or invoke a pre-defined function, among [others](V1_5_CheatSheet#Actions.md).
+
+**Important note:** The `EXPECT_CALL()` statement evaluates the action clause only once, even though the action may be performed many times. Therefore you must be careful about side effects. The following may not do what you want:
+
+```
+int n = 100;
+EXPECT_CALL(turtle, GetX())
+.Times(4)
+.WillOnce(Return(n++));
+```
+
+Instead of returning 100, 101, 102, ..., consecutively, this mock function will always return 100 as `n++` is only evaluated once. Similarly, `Return(new Foo)` will create a new `Foo` object when the `EXPECT_CALL()` is executed, and will return the same pointer every time. If you want the side effect to happen every time, you need to define a custom action, which we'll teach in the [CookBook](V1_5_CookBook.md).
+
+Time for another quiz! What do you think the following means?
+
+```
+using ::testing::Return;...
+EXPECT_CALL(turtle, GetY())
+.Times(4)
+.WillOnce(Return(100));
+```
+
+Obviously `turtle.GetY()` is expected to be called four times. But if you think it will return 100 every time, think twice! Remember that one `WillOnce()` clause will be consumed each time the function is invoked and the default action will be taken afterwards. So the right answer is that `turtle.GetY()` will return 100 the first time, but **return 0 from the second time on**, as returning 0 is the default action for `int` functions.
+
+## Using Multiple Expectations ##
+So far we've only shown examples where you have a single expectation. More realistically, you're going to specify expectations on multiple mock methods, which may be from multiple mock objects.
+
+By default, when a mock method is invoked, Google Mock will search the expectations in the **reverse order** they are defined, and stop when an active expectation that matches the arguments is found (you can think of it as "newer rules override older ones."). If the matching expectation cannot take any more calls, you will get an upper-bound-violated failure. Here's an example:
+
+```
+using ::testing::_;...
+EXPECT_CALL(turtle, Forward(_));  // #1
+EXPECT_CALL(turtle, Forward(10))  // #2
+    .Times(2);
+```
+
+If `Forward(10)` is called three times in a row, the third time it will be an error, as the last matching expectation (#2) has been saturated. If, however, the third `Forward(10)` call is replaced by `Forward(20)`, then it would be OK, as now #1 will be the matching expectation.
+
+**Side note:** Why does Google Mock search for a match in the _reverse_ order of the expectations? The reason is that this allows a user to set up the default expectations in a mock object's constructor or the test fixture's set-up phase and then customize the mock by writing more specific expectations in the test body. So, if you have two expectations on the same method, you want to put the one with more specific matchers **after** the other, or the more specific rule would be shadowed by the more general one that comes after it.
+
+## Ordered vs Unordered Calls ##
+By default, an expectation can match a call even though an earlier expectation hasn't been satisfied. In other words, the calls don't have to occur in the order the expectations are specified.
+
+Sometimes, you may want all the expected calls to occur in a strict order. To say this in Google Mock is easy:
+
+```
+using ::testing::InSequence;...
+TEST(FooTest, DrawsLineSegment) {
+  ...
+  {
+    InSequence dummy;
+
+    EXPECT_CALL(turtle, PenDown());
+    EXPECT_CALL(turtle, Forward(100));
+    EXPECT_CALL(turtle, PenUp());
+  }
+  Foo();
+}
+```
+
+By creating an object of type `InSequence`, all expectations in its scope are put into a _sequence_ and have to occur _sequentially_. Since we are just relying on the constructor and destructor of this object to do the actual work, its name is really irrelevant.
+
+In this example, we test that `Foo()` calls the three expected functions in the order as written. If a call is made out-of-order, it will be an error.
+
+(What if you care about the relative order of some of the calls, but not all of them? Can you specify an arbitrary partial order? The answer is ... yes! If you are impatient, the details can be found in the [CookBook](V1_5_CookBook.md).)
+
+## All Expectations Are Sticky (Unless Said Otherwise) ##
+Now let's do a quick quiz to see how well you can use this mock stuff already. How would you test that the turtle is asked to go to the origin _exactly twice_ (you want to ignore any other instructions it receives)?
+
+After you've come up with your answer, take a look at ours and compare notes (solve it yourself first - don't cheat!):
+
+```
+using ::testing::_;...
+EXPECT_CALL(turtle, GoTo(_, _))  // #1
+    .Times(AnyNumber());
+EXPECT_CALL(turtle, GoTo(0, 0))  // #2
+    .Times(2);
+```
+
+Suppose `turtle.GoTo(0, 0)` is called three times. In the third time, Google Mock will see that the arguments match expectation #2 (remember that we always pick the last matching expectation). Now, since we said that there should be only two such calls, Google Mock will report an error immediately. This is basically what we've told you in the "Using Multiple Expectations" section above.
+
+This example shows that **expectations in Google Mock are "sticky" by default**, in the sense that they remain active even after we have reached their invocation upper bounds. This is an important rule to remember, as it affects the meaning of the spec, and is **different** to how it's done in many other mocking frameworks (Why'd we do that? Because we think our rule makes the common cases easier to express and understand.).
+
+Simple? Let's see if you've really understood it: what does the following code say?
+
+```
+using ::testing::Return;
+...
+for (int i = n; i > 0; i--) {
+  EXPECT_CALL(turtle, GetX())
+      .WillOnce(Return(10*i));
+}
+```
+
+If you think it says that `turtle.GetX()` will be called `n` times and will return 10, 20, 30, ..., consecutively, think twice! The problem is that, as we said, expectations are sticky. So, the second time `turtle.GetX()` is called, the last (latest) `EXPECT_CALL()` statement will match, and will immediately lead to an "upper bound exceeded" error - this piece of code is not very useful!
+
+One correct way of saying that `turtle.GetX()` will return 10, 20, 30, ..., is to explicitly say that the expectations are _not_ sticky. In other words, they should _retire_ as soon as they are saturated:
+
+```
+using ::testing::Return;
+...
+for (int i = n; i > 0; i--) {
+  EXPECT_CALL(turtle, GetX())
+    .WillOnce(Return(10*i))
+    .RetiresOnSaturation();
+}
+```
+
+And, there's a better way to do it: in this case, we expect the calls to occur in a specific order, and we line up the actions to match the order. Since the order is important here, we should make it explicit using a sequence:
+
+```
+using ::testing::InSequence;
+using ::testing::Return;
+...
+{
+  InSequence s;
+
+  for (int i = 1; i <= n; i++) {
+    EXPECT_CALL(turtle, GetX())
+        .WillOnce(Return(10*i))
+        .RetiresOnSaturation();
+  }
+}
+```
+
+By the way, the other situation where an expectation may _not_ be sticky is when it's in a sequence - as soon as another expectation that comes after it in the sequence has been used, it automatically retires (and will never be used to match any call).
+
+## Uninteresting Calls ##
+A mock object may have many methods, and not all of them are that interesting. For example, in some tests we may not care about how many times `GetX()` and `GetY()` get called.
+
+In Google Mock, if you are not interested in a method, just don't say anything about it. If a call to this method occurs, you'll see a warning in the test output, but it won't be a failure.
+
+# What Now? #
+Congratulations! You've learned enough about Google Mock to start using it. Now, you might want to join the [googlemock](http://groups.google.com/group/googlemock) discussion group and actually write some tests using Google Mock - it will be fun. Hey, it may even be addictive - you've been warned.
+
+Then, if you feel like increasing your mock quotient, you should move on to the [CookBook](V1_5_CookBook.md). You can learn many advanced features of Google Mock there -- and advance your level of enjoyment and testing bliss.
\ No newline at end of file
diff --git a/third_party/googletest/googlemock/docs/v1_5/FrequentlyAskedQuestions.md b/third_party/googletest/googlemock/docs/v1_5/FrequentlyAskedQuestions.md
new file mode 100644
index 0000000..7593243
--- /dev/null
+++ b/third_party/googletest/googlemock/docs/v1_5/FrequentlyAskedQuestions.md
@@ -0,0 +1,624 @@
+
+
+Please send your questions to the
+[googlemock](http://groups.google.com/group/googlemock) discussion
+group. If you need help with compiler errors, make sure you have
+tried [Google Mock Doctor](#How_am_I_supposed_to_make_sense_of_these_horrible_template_error.md) first.
+
+## I wrote some matchers.  After I upgraded to a new version of Google Mock, they no longer compile.  What's going on? ##
+
+After version 1.4.0 of Google Mock was released, we had an idea on how
+to make it easier to write matchers that can generate informative
+messages efficiently.  We experimented with this idea and liked what
+we saw.  Therefore we decided to implement it.
+
+Unfortunately, this means that if you have defined your own matchers
+by implementing `MatcherInterface` or using `MakePolymorphicMatcher()`,
+your definitions will no longer compile.  Matchers defined using the
+`MATCHER*` family of macros are not affected.
+
+Sorry for the hassle if your matchers are affected.  We believe it's
+in everyone's long-term interest to make this change sooner than
+later.  Fortunately, it's usually not hard to migrate an existing
+matcher to the new API.  Here's what you need to do:
+
+If you wrote your matcher like this:
+```
+// Old matcher definition that doesn't work with the latest
+// Google Mock.
+using ::testing::MatcherInterface;
+...
+class MyWonderfulMatcher : public MatcherInterface<MyType> {
+ public:
+  ...
+  virtual bool Matches(MyType value) const {
+    // Returns true if value matches.
+    return value.GetFoo() > 5;
+  }
+  ...
+};
+```
+
+you'll need to change it to:
+```
+// New matcher definition that works with the latest Google Mock.
+using ::testing::MatcherInterface;
+using ::testing::MatchResultListener;
+...
+class MyWonderfulMatcher : public MatcherInterface<MyType> {
+ public:
+  ...
+  virtual bool MatchAndExplain(MyType value,
+                               MatchResultListener* listener) const {
+    // Returns true if value matches.
+    return value.GetFoo() > 5;
+  }
+  ...
+};
+```
+(i.e. rename `Matches()` to `MatchAndExplain()` and give it a second
+argument of type `MatchResultListener*`.)
+
+If you were also using `ExplainMatchResultTo()` to improve the matcher
+message:
+```
+// Old matcher definition that doesn't work with the lastest
+// Google Mock.
+using ::testing::MatcherInterface;
+...
+class MyWonderfulMatcher : public MatcherInterface<MyType> {
+ public:
+  ...
+  virtual bool Matches(MyType value) const {
+    // Returns true if value matches.
+    return value.GetFoo() > 5;
+  }
+
+  virtual void ExplainMatchResultTo(MyType value,
+                                    ::std::ostream* os) const {
+    // Prints some helpful information to os to help
+    // a user understand why value matches (or doesn't match).
+    *os << "the Foo property is " << value.GetFoo();
+  }
+  ...
+};
+```
+
+you should move the logic of `ExplainMatchResultTo()` into
+`MatchAndExplain()`, using the `MatchResultListener` argument where
+the `::std::ostream` was used:
+```
+// New matcher definition that works with the latest Google Mock.
+using ::testing::MatcherInterface;
+using ::testing::MatchResultListener;
+...
+class MyWonderfulMatcher : public MatcherInterface<MyType> {
+ public:
+  ...
+  virtual bool MatchAndExplain(MyType value,
+                               MatchResultListener* listener) const {
+    // Returns true if value matches.
+    *listener << "the Foo property is " << value.GetFoo();
+    return value.GetFoo() > 5;
+  }
+  ...
+};
+```
+
+If your matcher is defined using `MakePolymorphicMatcher()`:
+```
+// Old matcher definition that doesn't work with the latest
+// Google Mock.
+using ::testing::MakePolymorphicMatcher;
+...
+class MyGreatMatcher {
+ public:
+  ...
+  bool Matches(MyType value) const {
+    // Returns true if value matches.
+    return value.GetBar() < 42;
+  }
+  ...
+};
+... MakePolymorphicMatcher(MyGreatMatcher()) ...
+```
+
+you should rename the `Matches()` method to `MatchAndExplain()` and
+add a `MatchResultListener*` argument (the same as what you need to do
+for matchers defined by implementing `MatcherInterface`):
+```
+// New matcher definition that works with the latest Google Mock.
+using ::testing::MakePolymorphicMatcher;
+using ::testing::MatchResultListener;
+...
+class MyGreatMatcher {
+ public:
+  ...
+  bool MatchAndExplain(MyType value,
+                       MatchResultListener* listener) const {
+    // Returns true if value matches.
+    return value.GetBar() < 42;
+  }
+  ...
+};
+... MakePolymorphicMatcher(MyGreatMatcher()) ...
+```
+
+If your polymorphic matcher uses `ExplainMatchResultTo()` for better
+failure messages:
+```
+// Old matcher definition that doesn't work with the latest
+// Google Mock.
+using ::testing::MakePolymorphicMatcher;
+...
+class MyGreatMatcher {
+ public:
+  ...
+  bool Matches(MyType value) const {
+    // Returns true if value matches.
+    return value.GetBar() < 42;
+  }
+  ...
+};
+void ExplainMatchResultTo(const MyGreatMatcher& matcher,
+                          MyType value,
+                          ::std::ostream* os) {
+  // Prints some helpful information to os to help
+  // a user understand why value matches (or doesn't match).
+  *os << "the Bar property is " << value.GetBar();
+}
+... MakePolymorphicMatcher(MyGreatMatcher()) ...
+```
+
+you'll need to move the logic inside `ExplainMatchResultTo()` to
+`MatchAndExplain()`:
+```
+// New matcher definition that works with the latest Google Mock.
+using ::testing::MakePolymorphicMatcher;
+using ::testing::MatchResultListener;
+...
+class MyGreatMatcher {
+ public:
+  ...
+  bool MatchAndExplain(MyType value,
+                       MatchResultListener* listener) const {
+    // Returns true if value matches.
+    *listener << "the Bar property is " << value.GetBar();
+    return value.GetBar() < 42;
+  }
+  ...
+};
+... MakePolymorphicMatcher(MyGreatMatcher()) ...
+```
+
+For more information, you can read these
+[two](V1_5_CookBook#Writing_New_Monomorphic_Matchers.md)
+[recipes](V1_5_CookBook#Writing_New_Polymorphic_Matchers.md)
+from the cookbook.  As always, you
+are welcome to post questions on `googlemock@googlegroups.com` if you
+need any help.
+
+## When using Google Mock, do I have to use Google Test as the testing framework?  I have my favorite testing framework and don't want to switch. ##
+
+Google Mock works out of the box with Google Test.  However, it's easy
+to configure it to work with any testing framework of your choice.
+[Here](V1_5_ForDummies#Using_Google_Mock_with_Any_Testing_Framework.md) is how.
+
+## How am I supposed to make sense of these horrible template errors? ##
+
+If you are confused by the compiler errors gcc threw at you,
+try consulting the _Google Mock Doctor_ tool first.  What it does is to
+scan stdin for gcc error messages, and spit out diagnoses on the
+problems (we call them diseases) your code has.
+
+To "install", run command:
+```
+alias gmd='<path to googlemock>/scripts/gmock_doctor.py'
+```
+
+To use it, do:
+```
+<your-favorite-build-command> <your-test> 2>&1 | gmd
+```
+
+For example:
+```
+make my_test 2>&1 | gmd
+```
+
+Or you can run `gmd` and copy-n-paste gcc's error messages to it.
+
+## Can I mock a variadic function? ##
+
+You cannot mock a variadic function (i.e. a function taking ellipsis
+(`...`) arguments) directly in Google Mock.
+
+The problem is that in general, there is _no way_ for a mock object to
+know how many arguments are passed to the variadic method, and what
+the arguments' types are.  Only the _author of the base class_ knows
+the protocol, and we cannot look into his head.
+
+Therefore, to mock such a function, the _user_ must teach the mock
+object how to figure out the number of arguments and their types.  One
+way to do it is to provide overloaded versions of the function.
+
+Ellipsis arguments are inherited from C and not really a C++ feature.
+They are unsafe to use and don't work with arguments that have
+constructors or destructors.  Therefore we recommend to avoid them in
+C++ as much as possible.
+
+## MSVC gives me warning C4301 or C4373 when I define a mock method with a const parameter.  Why? ##
+
+If you compile this using Microsoft Visual C++ 2005 SP1:
+```
+class Foo {
+  ...
+  virtual void Bar(const int i) = 0;
+};
+
+class MockFoo : public Foo {
+  ...
+  MOCK_METHOD1(Bar, void(const int i));
+};
+```
+You may get the following warning:
+```
+warning C4301: 'MockFoo::Bar': overriding virtual function only differs from 'Foo::Bar' by const/volatile qualifier
+```
+
+This is a MSVC bug.  The same code compiles fine with gcc ,for
+example.  If you use Visual C++ 2008 SP1, you would get the warning:
+```
+warning C4373: 'MockFoo::Bar': virtual function overrides 'Foo::Bar', previous versions of the compiler did not override when parameters only differed by const/volatile qualifiers
+```
+
+In C++, if you _declare_ a function with a `const` parameter, the
+`const` modifier is _ignored_.  Therefore, the `Foo` base class above
+is equivalent to:
+```
+class Foo {
+  ...
+  virtual void Bar(int i) = 0;  // int or const int?  Makes no difference.
+};
+```
+
+In fact, you can _declare_ Bar() with an `int` parameter, and _define_
+it with a `const int` parameter.  The compiler will still match them
+up.
+
+Since making a parameter `const` is meaningless in the method
+_declaration_, we recommend to remove it in both `Foo` and `MockFoo`.
+That should workaround the VC bug.
+
+Note that we are talking about the _top-level_ `const` modifier here.
+If the function parameter is passed by pointer or reference, declaring
+the _pointee_ or _referee_ as `const` is still meaningful.  For
+example, the following two declarations are _not_ equivalent:
+```
+void Bar(int* p);        // Neither p nor *p is const.
+void Bar(const int* p);  // p is not const, but *p is.
+```
+
+## I have a huge mock class, and Microsoft Visual C++ runs out of memory when compiling it.  What can I do? ##
+
+We've noticed that when the `/clr` compiler flag is used, Visual C++
+uses 5~6 times as much memory when compiling a mock class.  We suggest
+to avoid `/clr` when compiling native C++ mocks.
+
+## I can't figure out why Google Mock thinks my expectations are not satisfied.  What should I do? ##
+
+You might want to run your test with
+`--gmock_verbose=info`.  This flag lets Google Mock print a trace
+of every mock function call it receives.  By studying the trace,
+you'll gain insights on why the expectations you set are not met.
+
+## How can I assert that a function is NEVER called? ##
+
+```
+EXPECT_CALL(foo, Bar(_))
+    .Times(0);
+```
+
+## I have a failed test where Google Mock tells me TWICE that a particular expectation is not satisfied.  Isn't this redundant? ##
+
+When Google Mock detects a failure, it prints relevant information
+(the mock function arguments, the state of relevant expectations, and
+etc) to help the user debug.  If another failure is detected, Google
+Mock will do the same, including printing the state of relevant
+expectations.
+
+Sometimes an expectation's state didn't change between two failures,
+and you'll see the same description of the state twice.  They are
+however _not_ redundant, as they refer to _different points in time_.
+The fact they are the same _is_ interesting information.
+
+## I get a heap check failure when using a mock object, but using a real object is fine.  What can be wrong? ##
+
+Does the class (hopefully a pure interface) you are mocking have a
+virtual destructor?
+
+Whenever you derive from a base class, make sure its destructor is
+virtual.  Otherwise Bad Things will happen.  Consider the following
+code:
+
+```
+class Base {
+ public:
+  // Not virtual, but should be.
+  ~Base() { ... }
+  ...
+};
+
+class Derived : public Base {
+ public:
+  ...
+ private:
+  std::string value_;
+};
+
+...
+  Base* p = new Derived;
+  ...
+  delete p;  // Surprise! ~Base() will be called, but ~Derived() will not
+             // - value_ is leaked.
+```
+
+By changing `~Base()` to virtual, `~Derived()` will be correctly
+called when `delete p` is executed, and the heap checker
+will be happy.
+
+## The "newer expectations override older ones" rule makes writing expectations awkward.  Why does Google Mock do that? ##
+
+When people complain about this, often they are referring to code like:
+
+```
+// foo.Bar() should be called twice, return 1 the first time, and return
+// 2 the second time.  However, I have to write the expectations in the
+// reverse order.  This sucks big time!!!
+EXPECT_CALL(foo, Bar())
+    .WillOnce(Return(2))
+    .RetiresOnSaturation();
+EXPECT_CALL(foo, Bar())
+    .WillOnce(Return(1))
+    .RetiresOnSaturation();
+```
+
+The problem is that they didn't pick the **best** way to express the test's
+intent.
+
+By default, expectations don't have to be matched in _any_ particular
+order.  If you want them to match in a certain order, you need to be
+explicit.  This is Google Mock's (and jMock's) fundamental philosophy: it's
+easy to accidentally over-specify your tests, and we want to make it
+harder to do so.
+
+There are two better ways to write the test spec.  You could either
+put the expectations in sequence:
+
+```
+// foo.Bar() should be called twice, return 1 the first time, and return
+// 2 the second time.  Using a sequence, we can write the expectations
+// in their natural order.
+{
+  InSequence s;
+  EXPECT_CALL(foo, Bar())
+      .WillOnce(Return(1))
+      .RetiresOnSaturation();
+  EXPECT_CALL(foo, Bar())
+      .WillOnce(Return(2))
+      .RetiresOnSaturation();
+}
+```
+
+or you can put the sequence of actions in the same expectation:
+
+```
+// foo.Bar() should be called twice, return 1 the first time, and return
+// 2 the second time.
+EXPECT_CALL(foo, Bar())
+    .WillOnce(Return(1))
+    .WillOnce(Return(2))
+    .RetiresOnSaturation();
+```
+
+Back to the original questions: why does Google Mock search the
+expectations (and `ON_CALL`s) from back to front?  Because this
+allows a user to set up a mock's behavior for the common case early
+(e.g. in the mock's constructor or the test fixture's set-up phase)
+and customize it with more specific rules later.  If Google Mock
+searches from front to back, this very useful pattern won't be
+possible.
+
+## Google Mock prints a warning when a function without EXPECT\_CALL is called, even if I have set its behavior using ON\_CALL.  Would it be reasonable not to show the warning in this case? ##
+
+When choosing between being neat and being safe, we lean toward the
+latter.  So the answer is that we think it's better to show the
+warning.
+
+Often people write `ON_CALL`s in the mock object's
+constructor or `SetUp()`, as the default behavior rarely changes from
+test to test.  Then in the test body they set the expectations, which
+are often different for each test.  Having an `ON_CALL` in the set-up
+part of a test doesn't mean that the calls are expected.  If there's
+no `EXPECT_CALL` and the method is called, it's possibly an error.  If
+we quietly let the call go through without notifying the user, bugs
+may creep in unnoticed.
+
+If, however, you are sure that the calls are OK, you can write
+
+```
+EXPECT_CALL(foo, Bar(_))
+    .WillRepeatedly(...);
+```
+
+instead of
+
+```
+ON_CALL(foo, Bar(_))
+    .WillByDefault(...);
+```
+
+This tells Google Mock that you do expect the calls and no warning should be
+printed.
+
+Also, you can control the verbosity using the `--gmock_verbose` flag.
+If you find the output too noisy when debugging, just choose a less
+verbose level.
+
+## How can I delete the mock function's argument in an action? ##
+
+If you find yourself needing to perform some action that's not
+supported by Google Mock directly, remember that you can define your own
+actions using
+[MakeAction()](V1_5_CookBook#Writing_New_Actions.md) or
+[MakePolymorphicAction()](V1_5_CookBook#Writing_New_Polymorphic_Actions.md),
+or you can write a stub function and invoke it using
+[Invoke()](V1_5_CookBook#Using_Functions_Methods_Functors.md).
+
+## MOCK\_METHODn()'s second argument looks funny.  Why don't you use the MOCK\_METHODn(Method, return\_type, arg\_1, ..., arg\_n) syntax? ##
+
+What?!  I think it's beautiful. :-)
+
+While which syntax looks more natural is a subjective matter to some
+extent, Google Mock's syntax was chosen for several practical advantages it
+has.
+
+Try to mock a function that takes a map as an argument:
+```
+virtual int GetSize(const map<int, std::string>& m);
+```
+
+Using the proposed syntax, it would be:
+```
+MOCK_METHOD1(GetSize, int, const map<int, std::string>& m);
+```
+
+Guess what?  You'll get a compiler error as the compiler thinks that
+`const map<int, std::string>& m` are **two**, not one, arguments. To work
+around this you can use `typedef` to give the map type a name, but
+that gets in the way of your work.  Google Mock's syntax avoids this
+problem as the function's argument types are protected inside a pair
+of parentheses:
+```
+// This compiles fine.
+MOCK_METHOD1(GetSize, int(const map<int, std::string>& m));
+```
+
+You still need a `typedef` if the return type contains an unprotected
+comma, but that's much rarer.
+
+Other advantages include:
+  1. `MOCK_METHOD1(Foo, int, bool)` can leave a reader wonder whether the method returns `int` or `bool`, while there won't be such confusion using Google Mock's syntax.
+  1. The way Google Mock describes a function type is nothing new, although many people may not be familiar with it.  The same syntax was used in C, and the `function` library in `tr1` uses this syntax extensively.  Since `tr1` will become a part of the new version of STL, we feel very comfortable to be consistent with it.
+  1. The function type syntax is also used in other parts of Google Mock's API (e.g. the action interface) in order to make the implementation tractable. A user needs to learn it anyway in order to utilize Google Mock's more advanced features.  We'd as well stick to the same syntax in `MOCK_METHOD*`!
+
+## My code calls a static/global function.  Can I mock it? ##
+
+You can, but you need to make some changes.
+
+In general, if you find yourself needing to mock a static function,
+it's a sign that your modules are too tightly coupled (and less
+flexible, less reusable, less testable, etc).  You are probably better
+off defining a small interface and call the function through that
+interface, which then can be easily mocked.  It's a bit of work
+initially, but usually pays for itself quickly.
+
+This Google Testing Blog
+[post](http://googletesting.blogspot.com/2008/06/defeat-static-cling.html)
+says it excellently.  Check it out.
+
+## My mock object needs to do complex stuff.  It's a lot of pain to specify the actions.  Google Mock sucks! ##
+
+I know it's not a question, but you get an answer for free any way. :-)
+
+With Google Mock, you can create mocks in C++ easily.  And people might be
+tempted to use them everywhere. Sometimes they work great, and
+sometimes you may find them, well, a pain to use. So, what's wrong in
+the latter case?
+
+When you write a test without using mocks, you exercise the code and
+assert that it returns the correct value or that the system is in an
+expected state.  This is sometimes called "state-based testing".
+
+Mocks are great for what some call "interaction-based" testing:
+instead of checking the system state at the very end, mock objects
+verify that they are invoked the right way and report an error as soon
+as it arises, giving you a handle on the precise context in which the
+error was triggered.  This is often more effective and economical to
+do than state-based testing.
+
+If you are doing state-based testing and using a test double just to
+simulate the real object, you are probably better off using a fake.
+Using a mock in this case causes pain, as it's not a strong point for
+mocks to perform complex actions.  If you experience this and think
+that mocks suck, you are just not using the right tool for your
+problem. Or, you might be trying to solve the wrong problem. :-)
+
+## I got a warning "Uninteresting function call encountered - default action taken.."  Should I panic? ##
+
+By all means, NO!  It's just an FYI.
+
+What it means is that you have a mock function, you haven't set any
+expectations on it (by Google Mock's rule this means that you are not
+interested in calls to this function and therefore it can be called
+any number of times), and it is called.  That's OK - you didn't say
+it's not OK to call the function!
+
+What if you actually meant to disallow this function to be called, but
+forgot to write `EXPECT_CALL(foo, Bar()).Times(0)`?  While
+one can argue that it's the user's fault, Google Mock tries to be nice and
+prints you a note.
+
+So, when you see the message and believe that there shouldn't be any
+uninteresting calls, you should investigate what's going on.  To make
+your life easier, Google Mock prints the function name and arguments
+when an uninteresting call is encountered.
+
+## I want to define a custom action.  Should I use Invoke() or implement the action interface? ##
+
+Either way is fine - you want to choose the one that's more convenient
+for your circumstance.
+
+Usually, if your action is for a particular function type, defining it
+using `Invoke()` should be easier; if your action can be used in
+functions of different types (e.g. if you are defining
+`Return(value)`), `MakePolymorphicAction()` is
+easiest.  Sometimes you want precise control on what types of
+functions the action can be used in, and implementing
+`ActionInterface` is the way to go here. See the implementation of
+`Return()` in `include/gmock/gmock-actions.h` for an example.
+
+## I'm using the set-argument-pointee action, and the compiler complains about "conflicting return type specified".  What does it mean? ##
+
+You got this error as Google Mock has no idea what value it should return
+when the mock method is called.  `SetArgumentPointee()` says what the
+side effect is, but doesn't say what the return value should be.  You
+need `DoAll()` to chain a `SetArgumentPointee()` with a `Return()`.
+
+See this [recipe](V1_5_CookBook#Mocking_Side_Effects.md) for more details and an example.
+
+
+## My question is not in your FAQ! ##
+
+If you cannot find the answer to your question in this FAQ, there are
+some other resources you can use:
+
+  1. read other [wiki pages](http://code.google.com/p/googlemock/w/list),
+  1. search the mailing list [archive](http://groups.google.com/group/googlemock/topics),
+  1. ask it on [googlemock@googlegroups.com](mailto:googlemock@googlegroups.com) and someone will answer it (to prevent spam, we require you to join the [discussion group](http://groups.google.com/group/googlemock) before you can post.).
+
+Please note that creating an issue in the
+[issue tracker](http://code.google.com/p/googlemock/issues/list) is _not_
+a good way to get your answer, as it is monitored infrequently by a
+very small number of people.
+
+When asking a question, it's helpful to provide as much of the
+following information as possible (people cannot help you if there's
+not enough information in your question):
+
+  * the version (or the revision number if you check out from SVN directly) of Google Mock you use (Google Mock is under active development, so it's possible that your problem has been solved in a later version),
+  * your operating system,
+  * the name and version of your compiler,
+  * the complete command line flags you give to your compiler,
+  * the complete compiler error messages (if the question is about compilation),
+  * the _actual_ code (ideally, a minimal but complete program) that has the problem you encounter.
\ No newline at end of file
diff --git a/third_party/googletest/googlemock/docs/v1_6/CheatSheet.md b/third_party/googletest/googlemock/docs/v1_6/CheatSheet.md
new file mode 100644
index 0000000..91de1d2
--- /dev/null
+++ b/third_party/googletest/googlemock/docs/v1_6/CheatSheet.md
@@ -0,0 +1,534 @@
+
+
+# Defining a Mock Class #
+
+## Mocking a Normal Class ##
+
+Given
+```
+class Foo {
+  ...
+  virtual ~Foo();
+  virtual int GetSize() const = 0;
+  virtual string Describe(const char* name) = 0;
+  virtual string Describe(int type) = 0;
+  virtual bool Process(Bar elem, int count) = 0;
+};
+```
+(note that `~Foo()` **must** be virtual) we can define its mock as
+```
+#include "gmock/gmock.h"
+
+class MockFoo : public Foo {
+  MOCK_CONST_METHOD0(GetSize, int());
+  MOCK_METHOD1(Describe, string(const char* name));
+  MOCK_METHOD1(Describe, string(int type));
+  MOCK_METHOD2(Process, bool(Bar elem, int count));
+};
+```
+
+To create a "nice" mock object which ignores all uninteresting calls,
+or a "strict" mock object, which treats them as failures:
+```
+NiceMock<MockFoo> nice_foo;     // The type is a subclass of MockFoo.
+StrictMock<MockFoo> strict_foo; // The type is a subclass of MockFoo.
+```
+
+## Mocking a Class Template ##
+
+To mock
+```
+template <typename Elem>
+class StackInterface {
+ public:
+  ...
+  virtual ~StackInterface();
+  virtual int GetSize() const = 0;
+  virtual void Push(const Elem& x) = 0;
+};
+```
+(note that `~StackInterface()` **must** be virtual) just append `_T` to the `MOCK_*` macros:
+```
+template <typename Elem>
+class MockStack : public StackInterface<Elem> {
+ public:
+  ...
+  MOCK_CONST_METHOD0_T(GetSize, int());
+  MOCK_METHOD1_T(Push, void(const Elem& x));
+};
+```
+
+## Specifying Calling Conventions for Mock Functions ##
+
+If your mock function doesn't use the default calling convention, you
+can specify it by appending `_WITH_CALLTYPE` to any of the macros
+described in the previous two sections and supplying the calling
+convention as the first argument to the macro. For example,
+```
+  MOCK_METHOD_1_WITH_CALLTYPE(STDMETHODCALLTYPE, Foo, bool(int n));
+  MOCK_CONST_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, Bar, int(double x, double y));
+```
+where `STDMETHODCALLTYPE` is defined by `<objbase.h>` on Windows.
+
+# Using Mocks in Tests #
+
+The typical flow is:
+  1. Import the Google Mock names you need to use. All Google Mock names are in the `testing` namespace unless they are macros or otherwise noted.
+  1. Create the mock objects.
+  1. Optionally, set the default actions of the mock objects.
+  1. Set your expectations on the mock objects (How will they be called? What wil they do?).
+  1. Exercise code that uses the mock objects; if necessary, check the result using [Google Test](http://code.google.com/p/googletest/) assertions.
+  1. When a mock objects is destructed, Google Mock automatically verifies that all expectations on it have been satisfied.
+
+Here is an example:
+```
+using ::testing::Return;                            // #1
+
+TEST(BarTest, DoesThis) {
+  MockFoo foo;                                    // #2
+
+  ON_CALL(foo, GetSize())                         // #3
+      .WillByDefault(Return(1));
+  // ... other default actions ...
+
+  EXPECT_CALL(foo, Describe(5))                   // #4
+      .Times(3)
+      .WillRepeatedly(Return("Category 5"));
+  // ... other expectations ...
+
+  EXPECT_EQ("good", MyProductionFunction(&foo));  // #5
+}                                                 // #6
+```
+
+# Setting Default Actions #
+
+Google Mock has a **built-in default action** for any function that
+returns `void`, `bool`, a numeric value, or a pointer.
+
+To customize the default action for functions with return type `T` globally:
+```
+using ::testing::DefaultValue;
+
+DefaultValue<T>::Set(value);  // Sets the default value to be returned.
+// ... use the mocks ...
+DefaultValue<T>::Clear();     // Resets the default value.
+```
+
+To customize the default action for a particular method, use `ON_CALL()`:
+```
+ON_CALL(mock_object, method(matchers))
+    .With(multi_argument_matcher)  ?
+    .WillByDefault(action);
+```
+
+# Setting Expectations #
+
+`EXPECT_CALL()` sets **expectations** on a mock method (How will it be
+called? What will it do?):
+```
+EXPECT_CALL(mock_object, method(matchers))
+    .With(multi_argument_matcher)  ?
+    .Times(cardinality)            ?
+    .InSequence(sequences)         *
+    .After(expectations)           *
+    .WillOnce(action)              *
+    .WillRepeatedly(action)        ?
+    .RetiresOnSaturation();        ?
+```
+
+If `Times()` is omitted, the cardinality is assumed to be:
+
+  * `Times(1)` when there is neither `WillOnce()` nor `WillRepeatedly()`;
+  * `Times(n)` when there are `n WillOnce()`s but no `WillRepeatedly()`, where `n` >= 1; or
+  * `Times(AtLeast(n))` when there are `n WillOnce()`s and a `WillRepeatedly()`, where `n` >= 0.
+
+A method with no `EXPECT_CALL()` is free to be invoked _any number of times_, and the default action will be taken each time.
+
+# Matchers #
+
+A **matcher** matches a _single_ argument.  You can use it inside
+`ON_CALL()` or `EXPECT_CALL()`, or use it to validate a value
+directly:
+
+| `EXPECT_THAT(value, matcher)` | Asserts that `value` matches `matcher`. |
+|:------------------------------|:----------------------------------------|
+| `ASSERT_THAT(value, matcher)` | The same as `EXPECT_THAT(value, matcher)`, except that it generates a **fatal** failure. |
+
+Built-in matchers (where `argument` is the function argument) are
+divided into several categories:
+
+## Wildcard ##
+|`_`|`argument` can be any value of the correct type.|
+|:--|:-----------------------------------------------|
+|`A<type>()` or `An<type>()`|`argument` can be any value of type `type`.     |
+
+## Generic Comparison ##
+
+|`Eq(value)` or `value`|`argument == value`|
+|:---------------------|:------------------|
+|`Ge(value)`           |`argument >= value`|
+|`Gt(value)`           |`argument > value` |
+|`Le(value)`           |`argument <= value`|
+|`Lt(value)`           |`argument < value` |
+|`Ne(value)`           |`argument != value`|
+|`IsNull()`            |`argument` is a `NULL` pointer (raw or smart).|
+|`NotNull()`           |`argument` is a non-null pointer (raw or smart).|
+|`Ref(variable)`       |`argument` is a reference to `variable`.|
+|`TypedEq<type>(value)`|`argument` has type `type` and is equal to `value`. You may need to use this instead of `Eq(value)` when the mock function is overloaded.|
+
+Except `Ref()`, these matchers make a _copy_ of `value` in case it's
+modified or destructed later. If the compiler complains that `value`
+doesn't have a public copy constructor, try wrap it in `ByRef()`,
+e.g. `Eq(ByRef(non_copyable_value))`. If you do that, make sure
+`non_copyable_value` is not changed afterwards, or the meaning of your
+matcher will be changed.
+
+## Floating-Point Matchers ##
+
+|`DoubleEq(a_double)`|`argument` is a `double` value approximately equal to `a_double`, treating two NaNs as unequal.|
+|:-------------------|:----------------------------------------------------------------------------------------------|
+|`FloatEq(a_float)`  |`argument` is a `float` value approximately equal to `a_float`, treating two NaNs as unequal.  |
+|`NanSensitiveDoubleEq(a_double)`|`argument` is a `double` value approximately equal to `a_double`, treating two NaNs as equal.  |
+|`NanSensitiveFloatEq(a_float)`|`argument` is a `float` value approximately equal to `a_float`, treating two NaNs as equal.    |
+
+These matchers use ULP-based comparison (the same as used in
+[Google Test](http://code.google.com/p/googletest/)). They
+automatically pick a reasonable error bound based on the absolute
+value of the expected value.  `DoubleEq()` and `FloatEq()` conform to
+the IEEE standard, which requires comparing two NaNs for equality to
+return false. The `NanSensitive*` version instead treats two NaNs as
+equal, which is often what a user wants.
+
+## String Matchers ##
+
+The `argument` can be either a C string or a C++ string object:
+
+|`ContainsRegex(string)`|`argument` matches the given regular expression.|
+|:----------------------|:-----------------------------------------------|
+|`EndsWith(suffix)`     |`argument` ends with string `suffix`.           |
+|`HasSubstr(string)`    |`argument` contains `string` as a sub-string.   |
+|`MatchesRegex(string)` |`argument` matches the given regular expression with the match starting at the first character and ending at the last character.|
+|`StartsWith(prefix)`   |`argument` starts with string `prefix`.         |
+|`StrCaseEq(string)`    |`argument` is equal to `string`, ignoring case. |
+|`StrCaseNe(string)`    |`argument` is not equal to `string`, ignoring case.|
+|`StrEq(string)`        |`argument` is equal to `string`.                |
+|`StrNe(string)`        |`argument` is not equal to `string`.            |
+
+`ContainsRegex()` and `MatchesRegex()` use the regular expression
+syntax defined
+[here](http://code.google.com/p/googletest/wiki/V1_6_AdvancedGuide#Regular_Expression_Syntax).
+`StrCaseEq()`, `StrCaseNe()`, `StrEq()`, and `StrNe()` work for wide
+strings as well.
+
+## Container Matchers ##
+
+Most STL-style containers support `==`, so you can use
+`Eq(expected_container)` or simply `expected_container` to match a
+container exactly.   If you want to write the elements in-line,
+match them more flexibly, or get more informative messages, you can use:
+
+| `Contains(e)` | `argument` contains an element that matches `e`, which can be either a value or a matcher. |
+|:--------------|:-------------------------------------------------------------------------------------------|
+| `Each(e)`     | `argument` is a container where _every_ element matches `e`, which can be either a value or a matcher. |
+| `ElementsAre(e0, e1, ..., en)` | `argument` has `n + 1` elements, where the i-th element matches `ei`, which can be a value or a matcher. 0 to 10 arguments are allowed. |
+| `ElementsAreArray(array)` or `ElementsAreArray(array, count)` | The same as `ElementsAre()` except that the expected element values/matchers come from a C-style array. |
+| `ContainerEq(container)` | The same as `Eq(container)` except that the failure message also includes which elements are in one container but not the other. |
+| `Pointwise(m, container)` | `argument` contains the same number of elements as in `container`, and for all i, (the i-th element in `argument`, the i-th element in `container`) match `m`, which is a matcher on 2-tuples. E.g. `Pointwise(Le(), upper_bounds)` verifies that each element in `argument` doesn't exceed the corresponding element in `upper_bounds`. |
+
+These matchers can also match:
+
+  1. a native array passed by reference (e.g. in `Foo(const int (&a)[5])`), and
+  1. an array passed as a pointer and a count (e.g. in `Bar(const T* buffer, int len)` -- see [Multi-argument Matchers](#Multiargument_Matchers.md)).
+
+where the array may be multi-dimensional (i.e. its elements can be arrays).
+
+## Member Matchers ##
+
+|`Field(&class::field, m)`|`argument.field` (or `argument->field` when `argument` is a plain pointer) matches matcher `m`, where `argument` is an object of type _class_.|
+|:------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------|
+|`Key(e)`                 |`argument.first` matches `e`, which can be either a value or a matcher. E.g. `Contains(Key(Le(5)))` can verify that a `map` contains a key `<= 5`.|
+|`Pair(m1, m2)`           |`argument` is an `std::pair` whose `first` field matches `m1` and `second` field matches `m2`.                                                |
+|`Property(&class::property, m)`|`argument.property()` (or `argument->property()` when `argument` is a plain pointer) matches matcher `m`, where `argument` is an object of type _class_.|
+
+## Matching the Result of a Function or Functor ##
+
+|`ResultOf(f, m)`|`f(argument)` matches matcher `m`, where `f` is a function or functor.|
+|:---------------|:---------------------------------------------------------------------|
+
+## Pointer Matchers ##
+
+|`Pointee(m)`|`argument` (either a smart pointer or a raw pointer) points to a value that matches matcher `m`.|
+|:-----------|:-----------------------------------------------------------------------------------------------|
+
+## Multiargument Matchers ##
+
+Technically, all matchers match a _single_ value. A "multi-argument"
+matcher is just one that matches a _tuple_. The following matchers can
+be used to match a tuple `(x, y)`:
+
+|`Eq()`|`x == y`|
+|:-----|:-------|
+|`Ge()`|`x >= y`|
+|`Gt()`|`x > y` |
+|`Le()`|`x <= y`|
+|`Lt()`|`x < y` |
+|`Ne()`|`x != y`|
+
+You can use the following selectors to pick a subset of the arguments
+(or reorder them) to participate in the matching:
+
+|`AllArgs(m)`|Equivalent to `m`. Useful as syntactic sugar in `.With(AllArgs(m))`.|
+|:-----------|:-------------------------------------------------------------------|
+|`Args<N1, N2, ..., Nk>(m)`|The tuple of the `k` selected (using 0-based indices) arguments matches `m`, e.g. `Args<1, 2>(Eq())`.|
+
+## Composite Matchers ##
+
+You can make a matcher from one or more other matchers:
+
+|`AllOf(m1, m2, ..., mn)`|`argument` matches all of the matchers `m1` to `mn`.|
+|:-----------------------|:---------------------------------------------------|
+|`AnyOf(m1, m2, ..., mn)`|`argument` matches at least one of the matchers `m1` to `mn`.|
+|`Not(m)`                |`argument` doesn't match matcher `m`.               |
+
+## Adapters for Matchers ##
+
+|`MatcherCast<T>(m)`|casts matcher `m` to type `Matcher<T>`.|
+|:------------------|:--------------------------------------|
+|`SafeMatcherCast<T>(m)`| [safely casts](http://code.google.com/p/googlemock/wiki/V1_6_CookBook#Casting_Matchers) matcher `m` to type `Matcher<T>`. |
+|`Truly(predicate)` |`predicate(argument)` returns something considered by C++ to be true, where `predicate` is a function or functor.|
+
+## Matchers as Predicates ##
+
+|`Matches(m)(value)`|evaluates to `true` if `value` matches `m`. You can use `Matches(m)` alone as a unary functor.|
+|:------------------|:---------------------------------------------------------------------------------------------|
+|`ExplainMatchResult(m, value, result_listener)`|evaluates to `true` if `value` matches `m`, explaining the result to `result_listener`.       |
+|`Value(value, m)`  |evaluates to `true` if `value` matches `m`.                                                   |
+
+## Defining Matchers ##
+
+| `MATCHER(IsEven, "") { return (arg % 2) == 0; }` | Defines a matcher `IsEven()` to match an even number. |
+|:-------------------------------------------------|:------------------------------------------------------|
+| `MATCHER_P(IsDivisibleBy, n, "") { *result_listener << "where the remainder is " << (arg % n); return (arg % n) == 0; }` | Defines a macher `IsDivisibleBy(n)` to match a number divisible by `n`. |
+| `MATCHER_P2(IsBetween, a, b, std::string(negation ? "isn't" : "is") + " between " + PrintToString(a) + " and " + PrintToString(b)) { return a <= arg && arg <= b; }` | Defines a matcher `IsBetween(a, b)` to match a value in the range [`a`, `b`]. |
+
+**Notes:**
+
+  1. The `MATCHER*` macros cannot be used inside a function or class.
+  1. The matcher body must be _purely functional_ (i.e. it cannot have any side effect, and the result must not depend on anything other than the value being matched and the matcher parameters).
+  1. You can use `PrintToString(x)` to convert a value `x` of any type to a string.
+
+## Matchers as Test Assertions ##
+
+|`ASSERT_THAT(expression, m)`|Generates a [fatal failure](http://code.google.com/p/googletest/wiki/V1_6_Primer#Assertions) if the value of `expression` doesn't match matcher `m`.|
+|:---------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------|
+|`EXPECT_THAT(expression, m)`|Generates a non-fatal failure if the value of `expression` doesn't match matcher `m`.                                                               |
+
+# Actions #
+
+**Actions** specify what a mock function should do when invoked.
+
+## Returning a Value ##
+
+|`Return()`|Return from a `void` mock function.|
+|:---------|:----------------------------------|
+|`Return(value)`|Return `value`. If the type of `value` is different to the mock function's return type, `value` is converted to the latter type <i>at the time the expectation is set</i>, not when the action is executed.|
+|`ReturnArg<N>()`|Return the `N`-th (0-based) argument.|
+|`ReturnNew<T>(a1, ..., ak)`|Return `new T(a1, ..., ak)`; a different object is created each time.|
+|`ReturnNull()`|Return a null pointer.             |
+|`ReturnPointee(ptr)`|Return the value pointed to by `ptr`.|
+|`ReturnRef(variable)`|Return a reference to `variable`.  |
+|`ReturnRefOfCopy(value)`|Return a reference to a copy of `value`; the copy lives as long as the action.|
+
+## Side Effects ##
+
+|`Assign(&variable, value)`|Assign `value` to variable.|
+|:-------------------------|:--------------------------|
+| `DeleteArg<N>()`         | Delete the `N`-th (0-based) argument, which must be a pointer. |
+| `SaveArg<N>(pointer)`    | Save the `N`-th (0-based) argument to `*pointer`. |
+| `SaveArgPointee<N>(pointer)` | Save the value pointed to by the `N`-th (0-based) argument to `*pointer`. |
+| `SetArgReferee<N>(value)` |	Assign value to the variable referenced by the `N`-th (0-based) argument. |
+|`SetArgPointee<N>(value)` |Assign `value` to the variable pointed by the `N`-th (0-based) argument.|
+|`SetArgumentPointee<N>(value)`|Same as `SetArgPointee<N>(value)`. Deprecated. Will be removed in v1.7.0.|
+|`SetArrayArgument<N>(first, last)`|Copies the elements in source range [`first`, `last`) to the array pointed to by the `N`-th (0-based) argument, which can be either a pointer or an iterator. The action does not take ownership of the elements in the source range.|
+|`SetErrnoAndReturn(error, value)`|Set `errno` to `error` and return `value`.|
+|`Throw(exception)`        |Throws the given exception, which can be any copyable value. Available since v1.1.0.|
+
+## Using a Function or a Functor as an Action ##
+
+|`Invoke(f)`|Invoke `f` with the arguments passed to the mock function, where `f` can be a global/static function or a functor.|
+|:----------|:-----------------------------------------------------------------------------------------------------------------|
+|`Invoke(object_pointer, &class::method)`|Invoke the {method on the object with the arguments passed to the mock function.                                  |
+|`InvokeWithoutArgs(f)`|Invoke `f`, which can be a global/static function or a functor. `f` must take no arguments.                       |
+|`InvokeWithoutArgs(object_pointer, &class::method)`|Invoke the method on the object, which takes no arguments.                                                        |
+|`InvokeArgument<N>(arg1, arg2, ..., argk)`|Invoke the mock function's `N`-th (0-based) argument, which must be a function or a functor, with the `k` arguments.|
+
+The return value of the invoked function is used as the return value
+of the action.
+
+When defining a function or functor to be used with `Invoke*()`, you can declare any unused parameters as `Unused`:
+```
+  double Distance(Unused, double x, double y) { return sqrt(x*x + y*y); }
+  ...
+  EXPECT_CALL(mock, Foo("Hi", _, _)).WillOnce(Invoke(Distance));
+```
+
+In `InvokeArgument<N>(...)`, if an argument needs to be passed by reference, wrap it inside `ByRef()`. For example,
+```
+  InvokeArgument<2>(5, string("Hi"), ByRef(foo))
+```
+calls the mock function's #2 argument, passing to it `5` and `string("Hi")` by value, and `foo` by reference.
+
+## Default Action ##
+
+|`DoDefault()`|Do the default action (specified by `ON_CALL()` or the built-in one).|
+|:------------|:--------------------------------------------------------------------|
+
+**Note:** due to technical reasons, `DoDefault()` cannot be used inside  a composite action - trying to do so will result in a run-time error.
+
+## Composite Actions ##
+
+|`DoAll(a1, a2, ..., an)`|Do all actions `a1` to `an` and return the result of `an` in each invocation. The first `n - 1` sub-actions must return void. |
+|:-----------------------|:-----------------------------------------------------------------------------------------------------------------------------|
+|`IgnoreResult(a)`       |Perform action `a` and ignore its result. `a` must not return void.                                                           |
+|`WithArg<N>(a)`         |Pass the `N`-th (0-based) argument of the mock function to action `a` and perform it.                                         |
+|`WithArgs<N1, N2, ..., Nk>(a)`|Pass the selected (0-based) arguments of the mock function to action `a` and perform it.                                      |
+|`WithoutArgs(a)`        |Perform action `a` without any arguments.                                                                                     |
+
+## Defining Actions ##
+
+| `ACTION(Sum) { return arg0 + arg1; }` | Defines an action `Sum()` to return the sum of the mock function's argument #0 and #1. |
+|:--------------------------------------|:---------------------------------------------------------------------------------------|
+| `ACTION_P(Plus, n) { return arg0 + n; }` | Defines an action `Plus(n)` to return the sum of the mock function's argument #0 and `n`. |
+| `ACTION_Pk(Foo, p1, ..., pk) { statements; }` | Defines a parameterized action `Foo(p1, ..., pk)` to execute the given `statements`.   |
+
+The `ACTION*` macros cannot be used inside a function or class.
+
+# Cardinalities #
+
+These are used in `Times()` to specify how many times a mock function will be called:
+
+|`AnyNumber()`|The function can be called any number of times.|
+|:------------|:----------------------------------------------|
+|`AtLeast(n)` |The call is expected at least `n` times.       |
+|`AtMost(n)`  |The call is expected at most `n` times.        |
+|`Between(m, n)`|The call is expected between `m` and `n` (inclusive) times.|
+|`Exactly(n) or n`|The call is expected exactly `n` times. In particular, the call should never happen when `n` is 0.|
+
+# Expectation Order #
+
+By default, the expectations can be matched in _any_ order.  If some
+or all expectations must be matched in a given order, there are two
+ways to specify it.  They can be used either independently or
+together.
+
+## The After Clause ##
+
+```
+using ::testing::Expectation;
+...
+Expectation init_x = EXPECT_CALL(foo, InitX());
+Expectation init_y = EXPECT_CALL(foo, InitY());
+EXPECT_CALL(foo, Bar())
+    .After(init_x, init_y);
+```
+says that `Bar()` can be called only after both `InitX()` and
+`InitY()` have been called.
+
+If you don't know how many pre-requisites an expectation has when you
+write it, you can use an `ExpectationSet` to collect them:
+
+```
+using ::testing::ExpectationSet;
+...
+ExpectationSet all_inits;
+for (int i = 0; i < element_count; i++) {
+  all_inits += EXPECT_CALL(foo, InitElement(i));
+}
+EXPECT_CALL(foo, Bar())
+    .After(all_inits);
+```
+says that `Bar()` can be called only after all elements have been
+initialized (but we don't care about which elements get initialized
+before the others).
+
+Modifying an `ExpectationSet` after using it in an `.After()` doesn't
+affect the meaning of the `.After()`.
+
+## Sequences ##
+
+When you have a long chain of sequential expectations, it's easier to
+specify the order using **sequences**, which don't require you to given
+each expectation in the chain a different name.  <i>All expected<br>
+calls</i> in the same sequence must occur in the order they are
+specified.
+
+```
+using ::testing::Sequence;
+Sequence s1, s2;
+...
+EXPECT_CALL(foo, Reset())
+    .InSequence(s1, s2)
+    .WillOnce(Return(true));
+EXPECT_CALL(foo, GetSize())
+    .InSequence(s1)
+    .WillOnce(Return(1));
+EXPECT_CALL(foo, Describe(A<const char*>()))
+    .InSequence(s2)
+    .WillOnce(Return("dummy"));
+```
+says that `Reset()` must be called before _both_ `GetSize()` _and_
+`Describe()`, and the latter two can occur in any order.
+
+To put many expectations in a sequence conveniently:
+```
+using ::testing::InSequence;
+{
+  InSequence dummy;
+
+  EXPECT_CALL(...)...;
+  EXPECT_CALL(...)...;
+  ...
+  EXPECT_CALL(...)...;
+}
+```
+says that all expected calls in the scope of `dummy` must occur in
+strict order. The name `dummy` is irrelevant.)
+
+# Verifying and Resetting a Mock #
+
+Google Mock will verify the expectations on a mock object when it is destructed, or you can do it earlier:
+```
+using ::testing::Mock;
+...
+// Verifies and removes the expectations on mock_obj;
+// returns true iff successful.
+Mock::VerifyAndClearExpectations(&mock_obj);
+...
+// Verifies and removes the expectations on mock_obj;
+// also removes the default actions set by ON_CALL();
+// returns true iff successful.
+Mock::VerifyAndClear(&mock_obj);
+```
+
+You can also tell Google Mock that a mock object can be leaked and doesn't
+need to be verified:
+```
+Mock::AllowLeak(&mock_obj);
+```
+
+# Mock Classes #
+
+Google Mock defines a convenient mock class template
+```
+class MockFunction<R(A1, ..., An)> {
+ public:
+  MOCK_METHODn(Call, R(A1, ..., An));
+};
+```
+See this [recipe](http://code.google.com/p/googlemock/wiki/V1_6_CookBook#Using_Check_Points) for one application of it.
+
+# Flags #
+
+| `--gmock_catch_leaked_mocks=0` | Don't report leaked mock objects as failures. |
+|:-------------------------------|:----------------------------------------------|
+| `--gmock_verbose=LEVEL`        | Sets the default verbosity level (`info`, `warning`, or `error`) of Google Mock messages. |
\ No newline at end of file
diff --git a/third_party/googletest/googlemock/docs/v1_6/CookBook.md b/third_party/googletest/googlemock/docs/v1_6/CookBook.md
new file mode 100644
index 0000000..f5975a0
--- /dev/null
+++ b/third_party/googletest/googlemock/docs/v1_6/CookBook.md
@@ -0,0 +1,3342 @@
+
+
+You can find recipes for using Google Mock here. If you haven't yet,
+please read the [ForDummies](V1_6_ForDummies.md) document first to make sure you understand
+the basics.
+
+**Note:** Google Mock lives in the `testing` name space. For
+readability, it is recommended to write `using ::testing::Foo;` once in
+your file before using the name `Foo` defined by Google Mock. We omit
+such `using` statements in this page for brevity, but you should do it
+in your own code.
+
+# Creating Mock Classes #
+
+## Mocking Private or Protected Methods ##
+
+You must always put a mock method definition (`MOCK_METHOD*`) in a
+`public:` section of the mock class, regardless of the method being
+mocked being `public`, `protected`, or `private` in the base class.
+This allows `ON_CALL` and `EXPECT_CALL` to reference the mock function
+from outside of the mock class.  (Yes, C++ allows a subclass to change
+the access level of a virtual function in the base class.)  Example:
+
+```
+class Foo {
+ public:
+  ...
+  virtual bool Transform(Gadget* g) = 0;
+
+ protected:
+  virtual void Resume();
+
+ private:
+  virtual int GetTimeOut();
+};
+
+class MockFoo : public Foo {
+ public:
+  ...
+  MOCK_METHOD1(Transform, bool(Gadget* g));
+
+  // The following must be in the public section, even though the
+  // methods are protected or private in the base class.
+  MOCK_METHOD0(Resume, void());
+  MOCK_METHOD0(GetTimeOut, int());
+};
+```
+
+## Mocking Overloaded Methods ##
+
+You can mock overloaded functions as usual. No special attention is required:
+
+```
+class Foo {
+  ...
+
+  // Must be virtual as we'll inherit from Foo.
+  virtual ~Foo();
+
+  // Overloaded on the types and/or numbers of arguments.
+  virtual int Add(Element x);
+  virtual int Add(int times, Element x);
+
+  // Overloaded on the const-ness of this object.
+  virtual Bar& GetBar();
+  virtual const Bar& GetBar() const;
+};
+
+class MockFoo : public Foo {
+  ...
+  MOCK_METHOD1(Add, int(Element x));
+  MOCK_METHOD2(Add, int(int times, Element x);
+
+  MOCK_METHOD0(GetBar, Bar&());
+  MOCK_CONST_METHOD0(GetBar, const Bar&());
+};
+```
+
+**Note:** if you don't mock all versions of the overloaded method, the
+compiler will give you a warning about some methods in the base class
+being hidden. To fix that, use `using` to bring them in scope:
+
+```
+class MockFoo : public Foo {
+  ...
+  using Foo::Add;
+  MOCK_METHOD1(Add, int(Element x));
+  // We don't want to mock int Add(int times, Element x);
+  ...
+};
+```
+
+## Mocking Class Templates ##
+
+To mock a class template, append `_T` to the `MOCK_*` macros:
+
+```
+template <typename Elem>
+class StackInterface {
+  ...
+  // Must be virtual as we'll inherit from StackInterface.
+  virtual ~StackInterface();
+
+  virtual int GetSize() const = 0;
+  virtual void Push(const Elem& x) = 0;
+};
+
+template <typename Elem>
+class MockStack : public StackInterface<Elem> {
+  ...
+  MOCK_CONST_METHOD0_T(GetSize, int());
+  MOCK_METHOD1_T(Push, void(const Elem& x));
+};
+```
+
+## Mocking Nonvirtual Methods ##
+
+Google Mock can mock non-virtual functions to be used in what we call _hi-perf
+dependency injection_.
+
+In this case, instead of sharing a common base class with the real
+class, your mock class will be _unrelated_ to the real class, but
+contain methods with the same signatures.  The syntax for mocking
+non-virtual methods is the _same_ as mocking virtual methods:
+
+```
+// A simple packet stream class.  None of its members is virtual.
+class ConcretePacketStream {
+ public:
+  void AppendPacket(Packet* new_packet);
+  const Packet* GetPacket(size_t packet_number) const;
+  size_t NumberOfPackets() const;
+  ...
+};
+
+// A mock packet stream class.  It inherits from no other, but defines
+// GetPacket() and NumberOfPackets().
+class MockPacketStream {
+ public:
+  MOCK_CONST_METHOD1(GetPacket, const Packet*(size_t packet_number));
+  MOCK_CONST_METHOD0(NumberOfPackets, size_t());
+  ...
+};
+```
+
+Note that the mock class doesn't define `AppendPacket()`, unlike the
+real class. That's fine as long as the test doesn't need to call it.
+
+Next, you need a way to say that you want to use
+`ConcretePacketStream` in production code, and use `MockPacketStream`
+in tests.  Since the functions are not virtual and the two classes are
+unrelated, you must specify your choice at _compile time_ (as opposed
+to run time).
+
+One way to do it is to templatize your code that needs to use a packet
+stream.  More specifically, you will give your code a template type
+argument for the type of the packet stream.  In production, you will
+instantiate your template with `ConcretePacketStream` as the type
+argument.  In tests, you will instantiate the same template with
+`MockPacketStream`.  For example, you may write:
+
+```
+template <class PacketStream>
+void CreateConnection(PacketStream* stream) { ... }
+
+template <class PacketStream>
+class PacketReader {
+ public:
+  void ReadPackets(PacketStream* stream, size_t packet_num);
+};
+```
+
+Then you can use `CreateConnection<ConcretePacketStream>()` and
+`PacketReader<ConcretePacketStream>` in production code, and use
+`CreateConnection<MockPacketStream>()` and
+`PacketReader<MockPacketStream>` in tests.
+
+```
+  MockPacketStream mock_stream;
+  EXPECT_CALL(mock_stream, ...)...;
+  .. set more expectations on mock_stream ...
+  PacketReader<MockPacketStream> reader(&mock_stream);
+  ... exercise reader ...
+```
+
+## Mocking Free Functions ##
+
+It's possible to use Google Mock to mock a free function (i.e. a
+C-style function or a static method).  You just need to rewrite your
+code to use an interface (abstract class).
+
+Instead of calling a free function (say, `OpenFile`) directly,
+introduce an interface for it and have a concrete subclass that calls
+the free function:
+
+```
+class FileInterface {
+ public:
+  ...
+  virtual bool Open(const char* path, const char* mode) = 0;
+};
+
+class File : public FileInterface {
+ public:
+  ...
+  virtual bool Open(const char* path, const char* mode) {
+    return OpenFile(path, mode);
+  }
+};
+```
+
+Your code should talk to `FileInterface` to open a file.  Now it's
+easy to mock out the function.
+
+This may seem much hassle, but in practice you often have multiple
+related functions that you can put in the same interface, so the
+per-function syntactic overhead will be much lower.
+
+If you are concerned about the performance overhead incurred by
+virtual functions, and profiling confirms your concern, you can
+combine this with the recipe for [mocking non-virtual methods](#Mocking_Nonvirtual_Methods.md).
+
+## Nice Mocks and Strict Mocks ##
+
+If a mock method has no `EXPECT_CALL` spec but is called, Google Mock
+will print a warning about the "uninteresting call". The rationale is:
+
+  * New methods may be added to an interface after a test is written. We shouldn't fail a test just because a method it doesn't know about is called.
+  * However, this may also mean there's a bug in the test, so Google Mock shouldn't be silent either. If the user believes these calls are harmless, he can add an `EXPECT_CALL()` to suppress the warning.
+
+However, sometimes you may want to suppress all "uninteresting call"
+warnings, while sometimes you may want the opposite, i.e. to treat all
+of them as errors. Google Mock lets you make the decision on a
+per-mock-object basis.
+
+Suppose your test uses a mock class `MockFoo`:
+
+```
+TEST(...) {
+  MockFoo mock_foo;
+  EXPECT_CALL(mock_foo, DoThis());
+  ... code that uses mock_foo ...
+}
+```
+
+If a method of `mock_foo` other than `DoThis()` is called, it will be
+reported by Google Mock as a warning. However, if you rewrite your
+test to use `NiceMock<MockFoo>` instead, the warning will be gone,
+resulting in a cleaner test output:
+
+```
+using ::testing::NiceMock;
+
+TEST(...) {
+  NiceMock<MockFoo> mock_foo;
+  EXPECT_CALL(mock_foo, DoThis());
+  ... code that uses mock_foo ...
+}
+```
+
+`NiceMock<MockFoo>` is a subclass of `MockFoo`, so it can be used
+wherever `MockFoo` is accepted.
+
+It also works if `MockFoo`'s constructor takes some arguments, as
+`NiceMock<MockFoo>` "inherits" `MockFoo`'s constructors:
+
+```
+using ::testing::NiceMock;
+
+TEST(...) {
+  NiceMock<MockFoo> mock_foo(5, "hi");  // Calls MockFoo(5, "hi").
+  EXPECT_CALL(mock_foo, DoThis());
+  ... code that uses mock_foo ...
+}
+```
+
+The usage of `StrictMock` is similar, except that it makes all
+uninteresting calls failures:
+
+```
+using ::testing::StrictMock;
+
+TEST(...) {
+  StrictMock<MockFoo> mock_foo;
+  EXPECT_CALL(mock_foo, DoThis());
+  ... code that uses mock_foo ...
+
+  // The test will fail if a method of mock_foo other than DoThis()
+  // is called.
+}
+```
+
+There are some caveats though (I don't like them just as much as the
+next guy, but sadly they are side effects of C++'s limitations):
+
+  1. `NiceMock<MockFoo>` and `StrictMock<MockFoo>` only work for mock methods defined using the `MOCK_METHOD*` family of macros **directly** in the `MockFoo` class. If a mock method is defined in a **base class** of `MockFoo`, the "nice" or "strict" modifier may not affect it, depending on the compiler. In particular, nesting `NiceMock` and `StrictMock` (e.g. `NiceMock<StrictMock<MockFoo> >`) is **not** supported.
+  1. The constructors of the base mock (`MockFoo`) cannot have arguments passed by non-const reference, which happens to be banned by the [Google C++ style guide](http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml).
+  1. During the constructor or destructor of `MockFoo`, the mock object is _not_ nice or strict.  This may cause surprises if the constructor or destructor calls a mock method on `this` object. (This behavior, however, is consistent with C++'s general rule: if a constructor or destructor calls a virtual method of `this` object, that method is treated as non-virtual.  In other words, to the base class's constructor or destructor, `this` object behaves like an instance of the base class, not the derived class.  This rule is required for safety.  Otherwise a base constructor may use members of a derived class before they are initialized, or a base destructor may use members of a derived class after they have been destroyed.)
+
+Finally, you should be **very cautious** when using this feature, as the
+decision you make applies to **all** future changes to the mock
+class. If an important change is made in the interface you are mocking
+(and thus in the mock class), it could break your tests (if you use
+`StrictMock`) or let bugs pass through without a warning (if you use
+`NiceMock`). Therefore, try to specify the mock's behavior using
+explicit `EXPECT_CALL` first, and only turn to `NiceMock` or
+`StrictMock` as the last resort.
+
+## Simplifying the Interface without Breaking Existing Code ##
+
+Sometimes a method has a long list of arguments that is mostly
+uninteresting. For example,
+
+```
+class LogSink {
+ public:
+  ...
+  virtual void send(LogSeverity severity, const char* full_filename,
+                    const char* base_filename, int line,
+                    const struct tm* tm_time,
+                    const char* message, size_t message_len) = 0;
+};
+```
+
+This method's argument list is lengthy and hard to work with (let's
+say that the `message` argument is not even 0-terminated). If we mock
+it as is, using the mock will be awkward. If, however, we try to
+simplify this interface, we'll need to fix all clients depending on
+it, which is often infeasible.
+
+The trick is to re-dispatch the method in the mock class:
+
+```
+class ScopedMockLog : public LogSink {
+ public:
+  ...
+  virtual void send(LogSeverity severity, const char* full_filename,
+                    const char* base_filename, int line, const tm* tm_time,
+                    const char* message, size_t message_len) {
+    // We are only interested in the log severity, full file name, and
+    // log message.
+    Log(severity, full_filename, std::string(message, message_len));
+  }
+
+  // Implements the mock method:
+  //
+  //   void Log(LogSeverity severity,
+  //            const string& file_path,
+  //            const string& message);
+  MOCK_METHOD3(Log, void(LogSeverity severity, const string& file_path,
+                         const string& message));
+};
+```
+
+By defining a new mock method with a trimmed argument list, we make
+the mock class much more user-friendly.
+
+## Alternative to Mocking Concrete Classes ##
+
+Often you may find yourself using classes that don't implement
+interfaces. In order to test your code that uses such a class (let's
+call it `Concrete`), you may be tempted to make the methods of
+`Concrete` virtual and then mock it.
+
+Try not to do that.
+
+Making a non-virtual function virtual is a big decision. It creates an
+extension point where subclasses can tweak your class' behavior. This
+weakens your control on the class because now it's harder to maintain
+the class' invariants. You should make a function virtual only when
+there is a valid reason for a subclass to override it.
+
+Mocking concrete classes directly is problematic as it creates a tight
+coupling between the class and the tests - any small change in the
+class may invalidate your tests and make test maintenance a pain.
+
+To avoid such problems, many programmers have been practicing "coding
+to interfaces": instead of talking to the `Concrete` class, your code
+would define an interface and talk to it. Then you implement that
+interface as an adaptor on top of `Concrete`. In tests, you can easily
+mock that interface to observe how your code is doing.
+
+This technique incurs some overhead:
+
+  * You pay the cost of virtual function calls (usually not a problem).
+  * There is more abstraction for the programmers to learn.
+
+However, it can also bring significant benefits in addition to better
+testability:
+
+  * `Concrete`'s API may not fit your problem domain very well, as you may not be the only client it tries to serve. By designing your own interface, you have a chance to tailor it to your need - you may add higher-level functionalities, rename stuff, etc instead of just trimming the class. This allows you to write your code (user of the interface) in a more natural way, which means it will be more readable, more maintainable, and you'll be more productive.
+  * If `Concrete`'s implementation ever has to change, you don't have to rewrite everywhere it is used. Instead, you can absorb the change in your implementation of the interface, and your other code and tests will be insulated from this change.
+
+Some people worry that if everyone is practicing this technique, they
+will end up writing lots of redundant code. This concern is totally
+understandable. However, there are two reasons why it may not be the
+case:
+
+  * Different projects may need to use `Concrete` in different ways, so the best interfaces for them will be different. Therefore, each of them will have its own domain-specific interface on top of `Concrete`, and they will not be the same code.
+  * If enough projects want to use the same interface, they can always share it, just like they have been sharing `Concrete`. You can check in the interface and the adaptor somewhere near `Concrete` (perhaps in a `contrib` sub-directory) and let many projects use it.
+
+You need to weigh the pros and cons carefully for your particular
+problem, but I'd like to assure you that the Java community has been
+practicing this for a long time and it's a proven effective technique
+applicable in a wide variety of situations. :-)
+
+## Delegating Calls to a Fake ##
+
+Some times you have a non-trivial fake implementation of an
+interface. For example:
+
+```
+class Foo {
+ public:
+  virtual ~Foo() {}
+  virtual char DoThis(int n) = 0;
+  virtual void DoThat(const char* s, int* p) = 0;
+};
+
+class FakeFoo : public Foo {
+ public:
+  virtual char DoThis(int n) {
+    return (n > 0) ? '+' :
+        (n < 0) ? '-' : '0';
+  }
+
+  virtual void DoThat(const char* s, int* p) {
+    *p = strlen(s);
+  }
+};
+```
+
+Now you want to mock this interface such that you can set expectations
+on it. However, you also want to use `FakeFoo` for the default
+behavior, as duplicating it in the mock object is, well, a lot of
+work.
+
+When you define the mock class using Google Mock, you can have it
+delegate its default action to a fake class you already have, using
+this pattern:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+
+class MockFoo : public Foo {
+ public:
+  // Normal mock method definitions using Google Mock.
+  MOCK_METHOD1(DoThis, char(int n));
+  MOCK_METHOD2(DoThat, void(const char* s, int* p));
+
+  // Delegates the default actions of the methods to a FakeFoo object.
+  // This must be called *before* the custom ON_CALL() statements.
+  void DelegateToFake() {
+    ON_CALL(*this, DoThis(_))
+        .WillByDefault(Invoke(&fake_, &FakeFoo::DoThis));
+    ON_CALL(*this, DoThat(_, _))
+        .WillByDefault(Invoke(&fake_, &FakeFoo::DoThat));
+  }
+ private:
+  FakeFoo fake_;  // Keeps an instance of the fake in the mock.
+};
+```
+
+With that, you can use `MockFoo` in your tests as usual. Just remember
+that if you don't explicitly set an action in an `ON_CALL()` or
+`EXPECT_CALL()`, the fake will be called upon to do it:
+
+```
+using ::testing::_;
+
+TEST(AbcTest, Xyz) {
+  MockFoo foo;
+  foo.DelegateToFake(); // Enables the fake for delegation.
+
+  // Put your ON_CALL(foo, ...)s here, if any.
+
+  // No action specified, meaning to use the default action.
+  EXPECT_CALL(foo, DoThis(5));
+  EXPECT_CALL(foo, DoThat(_, _));
+
+  int n = 0;
+  EXPECT_EQ('+', foo.DoThis(5));  // FakeFoo::DoThis() is invoked.
+  foo.DoThat("Hi", &n);           // FakeFoo::DoThat() is invoked.
+  EXPECT_EQ(2, n);
+}
+```
+
+**Some tips:**
+
+  * If you want, you can still override the default action by providing your own `ON_CALL()` or using `.WillOnce()` / `.WillRepeatedly()` in `EXPECT_CALL()`.
+  * In `DelegateToFake()`, you only need to delegate the methods whose fake implementation you intend to use.
+  * The general technique discussed here works for overloaded methods, but you'll need to tell the compiler which version you mean. To disambiguate a mock function (the one you specify inside the parentheses of `ON_CALL()`), see the "Selecting Between Overloaded Functions" section on this page; to disambiguate a fake function (the one you place inside `Invoke()`), use a `static_cast` to specify the function's type.
+  * Having to mix a mock and a fake is often a sign of something gone wrong. Perhaps you haven't got used to the interaction-based way of testing yet. Or perhaps your interface is taking on too many roles and should be split up. Therefore, **don't abuse this**. We would only recommend to do it as an intermediate step when you are refactoring your code.
+
+Regarding the tip on mixing a mock and a fake, here's an example on
+why it may be a bad sign: Suppose you have a class `System` for
+low-level system operations. In particular, it does file and I/O
+operations. And suppose you want to test how your code uses `System`
+to do I/O, and you just want the file operations to work normally. If
+you mock out the entire `System` class, you'll have to provide a fake
+implementation for the file operation part, which suggests that
+`System` is taking on too many roles.
+
+Instead, you can define a `FileOps` interface and an `IOOps` interface
+and split `System`'s functionalities into the two. Then you can mock
+`IOOps` without mocking `FileOps`.
+
+## Delegating Calls to a Real Object ##
+
+When using testing doubles (mocks, fakes, stubs, and etc), sometimes
+their behaviors will differ from those of the real objects. This
+difference could be either intentional (as in simulating an error such
+that you can test the error handling code) or unintentional. If your
+mocks have different behaviors than the real objects by mistake, you
+could end up with code that passes the tests but fails in production.
+
+You can use the _delegating-to-real_ technique to ensure that your
+mock has the same behavior as the real object while retaining the
+ability to validate calls. This technique is very similar to the
+delegating-to-fake technique, the difference being that we use a real
+object instead of a fake. Here's an example:
+
+```
+using ::testing::_;
+using ::testing::AtLeast;
+using ::testing::Invoke;
+
+class MockFoo : public Foo {
+ public:
+  MockFoo() {
+    // By default, all calls are delegated to the real object.
+    ON_CALL(*this, DoThis())
+        .WillByDefault(Invoke(&real_, &Foo::DoThis));
+    ON_CALL(*this, DoThat(_))
+        .WillByDefault(Invoke(&real_, &Foo::DoThat));
+    ...
+  }
+  MOCK_METHOD0(DoThis, ...);
+  MOCK_METHOD1(DoThat, ...);
+  ...
+ private:
+  Foo real_;
+};
+...
+
+  MockFoo mock;
+
+  EXPECT_CALL(mock, DoThis())
+      .Times(3);
+  EXPECT_CALL(mock, DoThat("Hi"))
+      .Times(AtLeast(1));
+  ... use mock in test ...
+```
+
+With this, Google Mock will verify that your code made the right calls
+(with the right arguments, in the right order, called the right number
+of times, etc), and a real object will answer the calls (so the
+behavior will be the same as in production). This gives you the best
+of both worlds.
+
+## Delegating Calls to a Parent Class ##
+
+Ideally, you should code to interfaces, whose methods are all pure
+virtual. In reality, sometimes you do need to mock a virtual method
+that is not pure (i.e, it already has an implementation). For example:
+
+```
+class Foo {
+ public:
+  virtual ~Foo();
+
+  virtual void Pure(int n) = 0;
+  virtual int Concrete(const char* str) { ... }
+};
+
+class MockFoo : public Foo {
+ public:
+  // Mocking a pure method.
+  MOCK_METHOD1(Pure, void(int n));
+  // Mocking a concrete method.  Foo::Concrete() is shadowed.
+  MOCK_METHOD1(Concrete, int(const char* str));
+};
+```
+
+Sometimes you may want to call `Foo::Concrete()` instead of
+`MockFoo::Concrete()`. Perhaps you want to do it as part of a stub
+action, or perhaps your test doesn't need to mock `Concrete()` at all
+(but it would be oh-so painful to have to define a new mock class
+whenever you don't need to mock one of its methods).
+
+The trick is to leave a back door in your mock class for accessing the
+real methods in the base class:
+
+```
+class MockFoo : public Foo {
+ public:
+  // Mocking a pure method.
+  MOCK_METHOD1(Pure, void(int n));
+  // Mocking a concrete method.  Foo::Concrete() is shadowed.
+  MOCK_METHOD1(Concrete, int(const char* str));
+
+  // Use this to call Concrete() defined in Foo.
+  int FooConcrete(const char* str) { return Foo::Concrete(str); }
+};
+```
+
+Now, you can call `Foo::Concrete()` inside an action by:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+...
+  EXPECT_CALL(foo, Concrete(_))
+      .WillOnce(Invoke(&foo, &MockFoo::FooConcrete));
+```
+
+or tell the mock object that you don't want to mock `Concrete()`:
+
+```
+using ::testing::Invoke;
+...
+  ON_CALL(foo, Concrete(_))
+      .WillByDefault(Invoke(&foo, &MockFoo::FooConcrete));
+```
+
+(Why don't we just write `Invoke(&foo, &Foo::Concrete)`? If you do
+that, `MockFoo::Concrete()` will be called (and cause an infinite
+recursion) since `Foo::Concrete()` is virtual. That's just how C++
+works.)
+
+# Using Matchers #
+
+## Matching Argument Values Exactly ##
+
+You can specify exactly which arguments a mock method is expecting:
+
+```
+using ::testing::Return;
+...
+  EXPECT_CALL(foo, DoThis(5))
+      .WillOnce(Return('a'));
+  EXPECT_CALL(foo, DoThat("Hello", bar));
+```
+
+## Using Simple Matchers ##
+
+You can use matchers to match arguments that have a certain property:
+
+```
+using ::testing::Ge;
+using ::testing::NotNull;
+using ::testing::Return;
+...
+  EXPECT_CALL(foo, DoThis(Ge(5)))  // The argument must be >= 5.
+      .WillOnce(Return('a'));
+  EXPECT_CALL(foo, DoThat("Hello", NotNull()));
+  // The second argument must not be NULL.
+```
+
+A frequently used matcher is `_`, which matches anything:
+
+```
+using ::testing::_;
+using ::testing::NotNull;
+...
+  EXPECT_CALL(foo, DoThat(_, NotNull()));
+```
+
+## Combining Matchers ##
+
+You can build complex matchers from existing ones using `AllOf()`,
+`AnyOf()`, and `Not()`:
+
+```
+using ::testing::AllOf;
+using ::testing::Gt;
+using ::testing::HasSubstr;
+using ::testing::Ne;
+using ::testing::Not;
+...
+  // The argument must be > 5 and != 10.
+  EXPECT_CALL(foo, DoThis(AllOf(Gt(5),
+                                Ne(10))));
+
+  // The first argument must not contain sub-string "blah".
+  EXPECT_CALL(foo, DoThat(Not(HasSubstr("blah")),
+                          NULL));
+```
+
+## Casting Matchers ##
+
+Google Mock matchers are statically typed, meaning that the compiler
+can catch your mistake if you use a matcher of the wrong type (for
+example, if you use `Eq(5)` to match a `string` argument). Good for
+you!
+
+Sometimes, however, you know what you're doing and want the compiler
+to give you some slack. One example is that you have a matcher for
+`long` and the argument you want to match is `int`. While the two
+types aren't exactly the same, there is nothing really wrong with
+using a `Matcher<long>` to match an `int` - after all, we can first
+convert the `int` argument to a `long` before giving it to the
+matcher.
+
+To support this need, Google Mock gives you the
+`SafeMatcherCast<T>(m)` function. It casts a matcher `m` to type
+`Matcher<T>`. To ensure safety, Google Mock checks that (let `U` be the
+type `m` accepts):
+
+  1. Type `T` can be implicitly cast to type `U`;
+  1. When both `T` and `U` are built-in arithmetic types (`bool`, integers, and floating-point numbers), the conversion from `T` to `U` is not lossy (in other words, any value representable by `T` can also be represented by `U`); and
+  1. When `U` is a reference, `T` must also be a reference (as the underlying matcher may be interested in the address of the `U` value).
+
+The code won't compile if any of these conditions isn't met.
+
+Here's one example:
+
+```
+using ::testing::SafeMatcherCast;
+
+// A base class and a child class.
+class Base { ... };
+class Derived : public Base { ... };
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD1(DoThis, void(Derived* derived));
+};
+...
+
+  MockFoo foo;
+  // m is a Matcher<Base*> we got from somewhere.
+  EXPECT_CALL(foo, DoThis(SafeMatcherCast<Derived*>(m)));
+```
+
+If you find `SafeMatcherCast<T>(m)` too limiting, you can use a similar
+function `MatcherCast<T>(m)`. The difference is that `MatcherCast` works
+as long as you can `static_cast` type `T` to type `U`.
+
+`MatcherCast` essentially lets you bypass C++'s type system
+(`static_cast` isn't always safe as it could throw away information,
+for example), so be careful not to misuse/abuse it.
+
+## Selecting Between Overloaded Functions ##
+
+If you expect an overloaded function to be called, the compiler may
+need some help on which overloaded version it is.
+
+To disambiguate functions overloaded on the const-ness of this object,
+use the `Const()` argument wrapper.
+
+```
+using ::testing::ReturnRef;
+
+class MockFoo : public Foo {
+  ...
+  MOCK_METHOD0(GetBar, Bar&());
+  MOCK_CONST_METHOD0(GetBar, const Bar&());
+};
+...
+
+  MockFoo foo;
+  Bar bar1, bar2;
+  EXPECT_CALL(foo, GetBar())         // The non-const GetBar().
+      .WillOnce(ReturnRef(bar1));
+  EXPECT_CALL(Const(foo), GetBar())  // The const GetBar().
+      .WillOnce(ReturnRef(bar2));
+```
+
+(`Const()` is defined by Google Mock and returns a `const` reference
+to its argument.)
+
+To disambiguate overloaded functions with the same number of arguments
+but different argument types, you may need to specify the exact type
+of a matcher, either by wrapping your matcher in `Matcher<type>()`, or
+using a matcher whose type is fixed (`TypedEq<type>`, `An<type>()`,
+etc):
+
+```
+using ::testing::An;
+using ::testing::Lt;
+using ::testing::Matcher;
+using ::testing::TypedEq;
+
+class MockPrinter : public Printer {
+ public:
+  MOCK_METHOD1(Print, void(int n));
+  MOCK_METHOD1(Print, void(char c));
+};
+
+TEST(PrinterTest, Print) {
+  MockPrinter printer;
+
+  EXPECT_CALL(printer, Print(An<int>()));            // void Print(int);
+  EXPECT_CALL(printer, Print(Matcher<int>(Lt(5))));  // void Print(int);
+  EXPECT_CALL(printer, Print(TypedEq<char>('a')));   // void Print(char);
+
+  printer.Print(3);
+  printer.Print(6);
+  printer.Print('a');
+}
+```
+
+## Performing Different Actions Based on the Arguments ##
+
+When a mock method is called, the _last_ matching expectation that's
+still active will be selected (think "newer overrides older"). So, you
+can make a method do different things depending on its argument values
+like this:
+
+```
+using ::testing::_;
+using ::testing::Lt;
+using ::testing::Return;
+...
+  // The default case.
+  EXPECT_CALL(foo, DoThis(_))
+      .WillRepeatedly(Return('b'));
+
+  // The more specific case.
+  EXPECT_CALL(foo, DoThis(Lt(5)))
+      .WillRepeatedly(Return('a'));
+```
+
+Now, if `foo.DoThis()` is called with a value less than 5, `'a'` will
+be returned; otherwise `'b'` will be returned.
+
+## Matching Multiple Arguments as a Whole ##
+
+Sometimes it's not enough to match the arguments individually. For
+example, we may want to say that the first argument must be less than
+the second argument. The `With()` clause allows us to match
+all arguments of a mock function as a whole. For example,
+
+```
+using ::testing::_;
+using ::testing::Lt;
+using ::testing::Ne;
+...
+  EXPECT_CALL(foo, InRange(Ne(0), _))
+      .With(Lt());
+```
+
+says that the first argument of `InRange()` must not be 0, and must be
+less than the second argument.
+
+The expression inside `With()` must be a matcher of type
+`Matcher<tr1::tuple<A1, ..., An> >`, where `A1`, ..., `An` are the
+types of the function arguments.
+
+You can also write `AllArgs(m)` instead of `m` inside `.With()`. The
+two forms are equivalent, but `.With(AllArgs(Lt()))` is more readable
+than `.With(Lt())`.
+
+You can use `Args<k1, ..., kn>(m)` to match the `n` selected arguments
+(as a tuple) against `m`. For example,
+
+```
+using ::testing::_;
+using ::testing::AllOf;
+using ::testing::Args;
+using ::testing::Lt;
+...
+  EXPECT_CALL(foo, Blah(_, _, _))
+      .With(AllOf(Args<0, 1>(Lt()), Args<1, 2>(Lt())));
+```
+
+says that `Blah()` will be called with arguments `x`, `y`, and `z` where
+`x < y < z`.
+
+As a convenience and example, Google Mock provides some matchers for
+2-tuples, including the `Lt()` matcher above. See the [CheatSheet](V1_6_CheatSheet.md) for
+the complete list.
+
+Note that if you want to pass the arguments to a predicate of your own
+(e.g. `.With(Args<0, 1>(Truly(&MyPredicate)))`), that predicate MUST be
+written to take a `tr1::tuple` as its argument; Google Mock will pass the `n`
+selected arguments as _one_ single tuple to the predicate.
+
+## Using Matchers as Predicates ##
+
+Have you noticed that a matcher is just a fancy predicate that also
+knows how to describe itself? Many existing algorithms take predicates
+as arguments (e.g. those defined in STL's `<algorithm>` header), and
+it would be a shame if Google Mock matchers are not allowed to
+participate.
+
+Luckily, you can use a matcher where a unary predicate functor is
+expected by wrapping it inside the `Matches()` function. For example,
+
+```
+#include <algorithm>
+#include <vector>
+
+std::vector<int> v;
+...
+// How many elements in v are >= 10?
+const int count = count_if(v.begin(), v.end(), Matches(Ge(10)));
+```
+
+Since you can build complex matchers from simpler ones easily using
+Google Mock, this gives you a way to conveniently construct composite
+predicates (doing the same using STL's `<functional>` header is just
+painful). For example, here's a predicate that's satisfied by any
+number that is >= 0, <= 100, and != 50:
+
+```
+Matches(AllOf(Ge(0), Le(100), Ne(50)))
+```
+
+## Using Matchers in Google Test Assertions ##
+
+Since matchers are basically predicates that also know how to describe
+themselves, there is a way to take advantage of them in
+[Google Test](http://code.google.com/p/googletest/) assertions. It's
+called `ASSERT_THAT` and `EXPECT_THAT`:
+
+```
+  ASSERT_THAT(value, matcher);  // Asserts that value matches matcher.
+  EXPECT_THAT(value, matcher);  // The non-fatal version.
+```
+
+For example, in a Google Test test you can write:
+
+```
+#include "gmock/gmock.h"
+
+using ::testing::AllOf;
+using ::testing::Ge;
+using ::testing::Le;
+using ::testing::MatchesRegex;
+using ::testing::StartsWith;
+...
+
+  EXPECT_THAT(Foo(), StartsWith("Hello"));
+  EXPECT_THAT(Bar(), MatchesRegex("Line \\d+"));
+  ASSERT_THAT(Baz(), AllOf(Ge(5), Le(10)));
+```
+
+which (as you can probably guess) executes `Foo()`, `Bar()`, and
+`Baz()`, and verifies that:
+
+  * `Foo()` returns a string that starts with `"Hello"`.
+  * `Bar()` returns a string that matches regular expression `"Line \\d+"`.
+  * `Baz()` returns a number in the range [5, 10].
+
+The nice thing about these macros is that _they read like
+English_. They generate informative messages too. For example, if the
+first `EXPECT_THAT()` above fails, the message will be something like:
+
+```
+Value of: Foo()
+  Actual: "Hi, world!"
+Expected: starts with "Hello"
+```
+
+**Credit:** The idea of `(ASSERT|EXPECT)_THAT` was stolen from the
+[Hamcrest](http://code.google.com/p/hamcrest/) project, which adds
+`assertThat()` to JUnit.
+
+## Using Predicates as Matchers ##
+
+Google Mock provides a built-in set of matchers. In case you find them
+lacking, you can use an arbitray unary predicate function or functor
+as a matcher - as long as the predicate accepts a value of the type
+you want. You do this by wrapping the predicate inside the `Truly()`
+function, for example:
+
+```
+using ::testing::Truly;
+
+int IsEven(int n) { return (n % 2) == 0 ? 1 : 0; }
+...
+
+  // Bar() must be called with an even number.
+  EXPECT_CALL(foo, Bar(Truly(IsEven)));
+```
+
+Note that the predicate function / functor doesn't have to return
+`bool`. It works as long as the return value can be used as the
+condition in statement `if (condition) ...`.
+
+## Matching Arguments that Are Not Copyable ##
+
+When you do an `EXPECT_CALL(mock_obj, Foo(bar))`, Google Mock saves
+away a copy of `bar`. When `Foo()` is called later, Google Mock
+compares the argument to `Foo()` with the saved copy of `bar`. This
+way, you don't need to worry about `bar` being modified or destroyed
+after the `EXPECT_CALL()` is executed. The same is true when you use
+matchers like `Eq(bar)`, `Le(bar)`, and so on.
+
+But what if `bar` cannot be copied (i.e. has no copy constructor)? You
+could define your own matcher function and use it with `Truly()`, as
+the previous couple of recipes have shown. Or, you may be able to get
+away from it if you can guarantee that `bar` won't be changed after
+the `EXPECT_CALL()` is executed. Just tell Google Mock that it should
+save a reference to `bar`, instead of a copy of it. Here's how:
+
+```
+using ::testing::Eq;
+using ::testing::ByRef;
+using ::testing::Lt;
+...
+  // Expects that Foo()'s argument == bar.
+  EXPECT_CALL(mock_obj, Foo(Eq(ByRef(bar))));
+
+  // Expects that Foo()'s argument < bar.
+  EXPECT_CALL(mock_obj, Foo(Lt(ByRef(bar))));
+```
+
+Remember: if you do this, don't change `bar` after the
+`EXPECT_CALL()`, or the result is undefined.
+
+## Validating a Member of an Object ##
+
+Often a mock function takes a reference to object as an argument. When
+matching the argument, you may not want to compare the entire object
+against a fixed object, as that may be over-specification. Instead,
+you may need to validate a certain member variable or the result of a
+certain getter method of the object. You can do this with `Field()`
+and `Property()`. More specifically,
+
+```
+Field(&Foo::bar, m)
+```
+
+is a matcher that matches a `Foo` object whose `bar` member variable
+satisfies matcher `m`.
+
+```
+Property(&Foo::baz, m)
+```
+
+is a matcher that matches a `Foo` object whose `baz()` method returns
+a value that satisfies matcher `m`.
+
+For example:
+
+> | `Field(&Foo::number, Ge(3))` | Matches `x` where `x.number >= 3`. |
+|:-----------------------------|:-----------------------------------|
+> | `Property(&Foo::name, StartsWith("John "))` | Matches `x` where `x.name()` starts with `"John "`. |
+
+Note that in `Property(&Foo::baz, ...)`, method `baz()` must take no
+argument and be declared as `const`.
+
+BTW, `Field()` and `Property()` can also match plain pointers to
+objects. For instance,
+
+```
+Field(&Foo::number, Ge(3))
+```
+
+matches a plain pointer `p` where `p->number >= 3`. If `p` is `NULL`,
+the match will always fail regardless of the inner matcher.
+
+What if you want to validate more than one members at the same time?
+Remember that there is `AllOf()`.
+
+## Validating the Value Pointed to by a Pointer Argument ##
+
+C++ functions often take pointers as arguments. You can use matchers
+like `NULL`, `NotNull()`, and other comparison matchers to match a
+pointer, but what if you want to make sure the value _pointed to_ by
+the pointer, instead of the pointer itself, has a certain property?
+Well, you can use the `Pointee(m)` matcher.
+
+`Pointee(m)` matches a pointer iff `m` matches the value the pointer
+points to. For example:
+
+```
+using ::testing::Ge;
+using ::testing::Pointee;
+...
+  EXPECT_CALL(foo, Bar(Pointee(Ge(3))));
+```
+
+expects `foo.Bar()` to be called with a pointer that points to a value
+greater than or equal to 3.
+
+One nice thing about `Pointee()` is that it treats a `NULL` pointer as
+a match failure, so you can write `Pointee(m)` instead of
+
+```
+  AllOf(NotNull(), Pointee(m))
+```
+
+without worrying that a `NULL` pointer will crash your test.
+
+Also, did we tell you that `Pointee()` works with both raw pointers
+**and** smart pointers (`linked_ptr`, `shared_ptr`, `scoped_ptr`, and
+etc)?
+
+What if you have a pointer to pointer? You guessed it - you can use
+nested `Pointee()` to probe deeper inside the value. For example,
+`Pointee(Pointee(Lt(3)))` matches a pointer that points to a pointer
+that points to a number less than 3 (what a mouthful...).
+
+## Testing a Certain Property of an Object ##
+
+Sometimes you want to specify that an object argument has a certain
+property, but there is no existing matcher that does this. If you want
+good error messages, you should define a matcher. If you want to do it
+quick and dirty, you could get away with writing an ordinary function.
+
+Let's say you have a mock function that takes an object of type `Foo`,
+which has an `int bar()` method and an `int baz()` method, and you
+want to constrain that the argument's `bar()` value plus its `baz()`
+value is a given number. Here's how you can define a matcher to do it:
+
+```
+using ::testing::MatcherInterface;
+using ::testing::MatchResultListener;
+
+class BarPlusBazEqMatcher : public MatcherInterface<const Foo&> {
+ public:
+  explicit BarPlusBazEqMatcher(int expected_sum)
+      : expected_sum_(expected_sum) {}
+
+  virtual bool MatchAndExplain(const Foo& foo,
+                               MatchResultListener* listener) const {
+    return (foo.bar() + foo.baz()) == expected_sum_;
+  }
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "bar() + baz() equals " << expected_sum_;
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "bar() + baz() does not equal " << expected_sum_;
+  }
+ private:
+  const int expected_sum_;
+};
+
+inline Matcher<const Foo&> BarPlusBazEq(int expected_sum) {
+  return MakeMatcher(new BarPlusBazEqMatcher(expected_sum));
+}
+
+...
+
+  EXPECT_CALL(..., DoThis(BarPlusBazEq(5)))...;
+```
+
+## Matching Containers ##
+
+Sometimes an STL container (e.g. list, vector, map, ...) is passed to
+a mock function and you may want to validate it. Since most STL
+containers support the `==` operator, you can write
+`Eq(expected_container)` or simply `expected_container` to match a
+container exactly.
+
+Sometimes, though, you may want to be more flexible (for example, the
+first element must be an exact match, but the second element can be
+any positive number, and so on). Also, containers used in tests often
+have a small number of elements, and having to define the expected
+container out-of-line is a bit of a hassle.
+
+You can use the `ElementsAre()` matcher in such cases:
+
+```
+using ::testing::_;
+using ::testing::ElementsAre;
+using ::testing::Gt;
+...
+
+  MOCK_METHOD1(Foo, void(const vector<int>& numbers));
+...
+
+  EXPECT_CALL(mock, Foo(ElementsAre(1, Gt(0), _, 5)));
+```
+
+The above matcher says that the container must have 4 elements, which
+must be 1, greater than 0, anything, and 5 respectively.
+
+`ElementsAre()` is overloaded to take 0 to 10 arguments. If more are
+needed, you can place them in a C-style array and use
+`ElementsAreArray()` instead:
+
+```
+using ::testing::ElementsAreArray;
+...
+
+  // ElementsAreArray accepts an array of element values.
+  const int expected_vector1[] = { 1, 5, 2, 4, ... };
+  EXPECT_CALL(mock, Foo(ElementsAreArray(expected_vector1)));
+
+  // Or, an array of element matchers.
+  Matcher<int> expected_vector2 = { 1, Gt(2), _, 3, ... };
+  EXPECT_CALL(mock, Foo(ElementsAreArray(expected_vector2)));
+```
+
+In case the array needs to be dynamically created (and therefore the
+array size cannot be inferred by the compiler), you can give
+`ElementsAreArray()` an additional argument to specify the array size:
+
+```
+using ::testing::ElementsAreArray;
+...
+  int* const expected_vector3 = new int[count];
+  ... fill expected_vector3 with values ...
+  EXPECT_CALL(mock, Foo(ElementsAreArray(expected_vector3, count)));
+```
+
+**Tips:**
+
+  * `ElementAre*()` works with _any_ container that implements the STL iterator concept (i.e. it has a `const_iterator` type and supports `begin()/end()`) and supports `size()`, not just the ones defined in STL. It will even work with container types yet to be written - as long as they follows the above pattern.
+  * You can use nested `ElementAre*()` to match nested (multi-dimensional) containers.
+  * If the container is passed by pointer instead of by reference, just write `Pointee(ElementsAre*(...))`.
+  * The order of elements _matters_ for `ElementsAre*()`. Therefore don't use it with containers whose element order is undefined (e.g. `hash_map`).
+
+## Sharing Matchers ##
+
+Under the hood, a Google Mock matcher object consists of a pointer to
+a ref-counted implementation object. Copying matchers is allowed and
+very efficient, as only the pointer is copied. When the last matcher
+that references the implementation object dies, the implementation
+object will be deleted.
+
+Therefore, if you have some complex matcher that you want to use again
+and again, there is no need to build it everytime. Just assign it to a
+matcher variable and use that variable repeatedly! For example,
+
+```
+  Matcher<int> in_range = AllOf(Gt(5), Le(10));
+  ... use in_range as a matcher in multiple EXPECT_CALLs ...
+```
+
+# Setting Expectations #
+
+## Ignoring Uninteresting Calls ##
+
+If you are not interested in how a mock method is called, just don't
+say anything about it. In this case, if the method is ever called,
+Google Mock will perform its default action to allow the test program
+to continue. If you are not happy with the default action taken by
+Google Mock, you can override it using `DefaultValue<T>::Set()`
+(described later in this document) or `ON_CALL()`.
+
+Please note that once you expressed interest in a particular mock
+method (via `EXPECT_CALL()`), all invocations to it must match some
+expectation. If this function is called but the arguments don't match
+any `EXPECT_CALL()` statement, it will be an error.
+
+## Disallowing Unexpected Calls ##
+
+If a mock method shouldn't be called at all, explicitly say so:
+
+```
+using ::testing::_;
+...
+  EXPECT_CALL(foo, Bar(_))
+      .Times(0);
+```
+
+If some calls to the method are allowed, but the rest are not, just
+list all the expected calls:
+
+```
+using ::testing::AnyNumber;
+using ::testing::Gt;
+...
+  EXPECT_CALL(foo, Bar(5));
+  EXPECT_CALL(foo, Bar(Gt(10)))
+      .Times(AnyNumber());
+```
+
+A call to `foo.Bar()` that doesn't match any of the `EXPECT_CALL()`
+statements will be an error.
+
+## Expecting Ordered Calls ##
+
+Although an `EXPECT_CALL()` statement defined earlier takes precedence
+when Google Mock tries to match a function call with an expectation,
+by default calls don't have to happen in the order `EXPECT_CALL()`
+statements are written. For example, if the arguments match the
+matchers in the third `EXPECT_CALL()`, but not those in the first two,
+then the third expectation will be used.
+
+If you would rather have all calls occur in the order of the
+expectations, put the `EXPECT_CALL()` statements in a block where you
+define a variable of type `InSequence`:
+
+```
+  using ::testing::_;
+  using ::testing::InSequence;
+
+  {
+    InSequence s;
+
+    EXPECT_CALL(foo, DoThis(5));
+    EXPECT_CALL(bar, DoThat(_))
+        .Times(2);
+    EXPECT_CALL(foo, DoThis(6));
+  }
+```
+
+In this example, we expect a call to `foo.DoThis(5)`, followed by two
+calls to `bar.DoThat()` where the argument can be anything, which are
+in turn followed by a call to `foo.DoThis(6)`. If a call occurred
+out-of-order, Google Mock will report an error.
+
+## Expecting Partially Ordered Calls ##
+
+Sometimes requiring everything to occur in a predetermined order can
+lead to brittle tests. For example, we may care about `A` occurring
+before both `B` and `C`, but aren't interested in the relative order
+of `B` and `C`. In this case, the test should reflect our real intent,
+instead of being overly constraining.
+
+Google Mock allows you to impose an arbitrary DAG (directed acyclic
+graph) on the calls. One way to express the DAG is to use the
+[After](http://code.google.com/p/googlemock/wiki/V1_6_CheatSheet#The_After_Clause) clause of `EXPECT_CALL`.
+
+Another way is via the `InSequence()` clause (not the same as the
+`InSequence` class), which we borrowed from jMock 2. It's less
+flexible than `After()`, but more convenient when you have long chains
+of sequential calls, as it doesn't require you to come up with
+different names for the expectations in the chains.  Here's how it
+works:
+
+If we view `EXPECT_CALL()` statements as nodes in a graph, and add an
+edge from node A to node B wherever A must occur before B, we can get
+a DAG. We use the term "sequence" to mean a directed path in this
+DAG. Now, if we decompose the DAG into sequences, we just need to know
+which sequences each `EXPECT_CALL()` belongs to in order to be able to
+reconstruct the orginal DAG.
+
+So, to specify the partial order on the expectations we need to do two
+things: first to define some `Sequence` objects, and then for each
+`EXPECT_CALL()` say which `Sequence` objects it is part
+of. Expectations in the same sequence must occur in the order they are
+written. For example,
+
+```
+  using ::testing::Sequence;
+
+  Sequence s1, s2;
+
+  EXPECT_CALL(foo, A())
+      .InSequence(s1, s2);
+  EXPECT_CALL(bar, B())
+      .InSequence(s1);
+  EXPECT_CALL(bar, C())
+      .InSequence(s2);
+  EXPECT_CALL(foo, D())
+      .InSequence(s2);
+```
+
+specifies the following DAG (where `s1` is `A -> B`, and `s2` is `A ->
+C -> D`):
+
+```
+       +---> B
+       |
+  A ---|
+       |
+       +---> C ---> D
+```
+
+This means that A must occur before B and C, and C must occur before
+D. There's no restriction about the order other than these.
+
+## Controlling When an Expectation Retires ##
+
+When a mock method is called, Google Mock only consider expectations
+that are still active. An expectation is active when created, and
+becomes inactive (aka _retires_) when a call that has to occur later
+has occurred. For example, in
+
+```
+  using ::testing::_;
+  using ::testing::Sequence;
+
+  Sequence s1, s2;
+
+  EXPECT_CALL(log, Log(WARNING, _, "File too large."))     // #1
+      .Times(AnyNumber())
+      .InSequence(s1, s2);
+  EXPECT_CALL(log, Log(WARNING, _, "Data set is empty."))  // #2
+      .InSequence(s1);
+  EXPECT_CALL(log, Log(WARNING, _, "User not found."))     // #3
+      .InSequence(s2);
+```
+
+as soon as either #2 or #3 is matched, #1 will retire. If a warning
+`"File too large."` is logged after this, it will be an error.
+
+Note that an expectation doesn't retire automatically when it's
+saturated. For example,
+
+```
+using ::testing::_;
+...
+  EXPECT_CALL(log, Log(WARNING, _, _));                  // #1
+  EXPECT_CALL(log, Log(WARNING, _, "File too large."));  // #2
+```
+
+says that there will be exactly one warning with the message `"File
+too large."`. If the second warning contains this message too, #2 will
+match again and result in an upper-bound-violated error.
+
+If this is not what you want, you can ask an expectation to retire as
+soon as it becomes saturated:
+
+```
+using ::testing::_;
+...
+  EXPECT_CALL(log, Log(WARNING, _, _));                 // #1
+  EXPECT_CALL(log, Log(WARNING, _, "File too large."))  // #2
+      .RetiresOnSaturation();
+```
+
+Here #2 can be used only once, so if you have two warnings with the
+message `"File too large."`, the first will match #2 and the second
+will match #1 - there will be no error.
+
+# Using Actions #
+
+## Returning References from Mock Methods ##
+
+If a mock function's return type is a reference, you need to use
+`ReturnRef()` instead of `Return()` to return a result:
+
+```
+using ::testing::ReturnRef;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD0(GetBar, Bar&());
+};
+...
+
+  MockFoo foo;
+  Bar bar;
+  EXPECT_CALL(foo, GetBar())
+      .WillOnce(ReturnRef(bar));
+```
+
+## Returning Live Values from Mock Methods ##
+
+The `Return(x)` action saves a copy of `x` when the action is
+_created_, and always returns the same value whenever it's
+executed. Sometimes you may want to instead return the _live_ value of
+`x` (i.e. its value at the time when the action is _executed_.).
+
+If the mock function's return type is a reference, you can do it using
+`ReturnRef(x)`, as shown in the previous recipe ("Returning References
+from Mock Methods"). However, Google Mock doesn't let you use
+`ReturnRef()` in a mock function whose return type is not a reference,
+as doing that usually indicates a user error. So, what shall you do?
+
+You may be tempted to try `ByRef()`:
+
+```
+using testing::ByRef;
+using testing::Return;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD0(GetValue, int());
+};
+...
+  int x = 0;
+  MockFoo foo;
+  EXPECT_CALL(foo, GetValue())
+      .WillRepeatedly(Return(ByRef(x)));
+  x = 42;
+  EXPECT_EQ(42, foo.GetValue());
+```
+
+Unfortunately, it doesn't work here. The above code will fail with error:
+
+```
+Value of: foo.GetValue()
+  Actual: 0
+Expected: 42
+```
+
+The reason is that `Return(value)` converts `value` to the actual
+return type of the mock function at the time when the action is
+_created_, not when it is _executed_. (This behavior was chosen for
+the action to be safe when `value` is a proxy object that references
+some temporary objects.) As a result, `ByRef(x)` is converted to an
+`int` value (instead of a `const int&`) when the expectation is set,
+and `Return(ByRef(x))` will always return 0.
+
+`ReturnPointee(pointer)` was provided to solve this problem
+specifically. It returns the value pointed to by `pointer` at the time
+the action is _executed_:
+
+```
+using testing::ReturnPointee;
+...
+  int x = 0;
+  MockFoo foo;
+  EXPECT_CALL(foo, GetValue())
+      .WillRepeatedly(ReturnPointee(&x));  // Note the & here.
+  x = 42;
+  EXPECT_EQ(42, foo.GetValue());  // This will succeed now.
+```
+
+## Combining Actions ##
+
+Want to do more than one thing when a function is called? That's
+fine. `DoAll()` allow you to do sequence of actions every time. Only
+the return value of the last action in the sequence will be used.
+
+```
+using ::testing::DoAll;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD1(Bar, bool(int n));
+};
+...
+
+  EXPECT_CALL(foo, Bar(_))
+      .WillOnce(DoAll(action_1,
+                      action_2,
+                      ...
+                      action_n));
+```
+
+## Mocking Side Effects ##
+
+Sometimes a method exhibits its effect not via returning a value but
+via side effects. For example, it may change some global state or
+modify an output argument. To mock side effects, in general you can
+define your own action by implementing `::testing::ActionInterface`.
+
+If all you need to do is to change an output argument, the built-in
+`SetArgPointee()` action is convenient:
+
+```
+using ::testing::SetArgPointee;
+
+class MockMutator : public Mutator {
+ public:
+  MOCK_METHOD2(Mutate, void(bool mutate, int* value));
+  ...
+};
+...
+
+  MockMutator mutator;
+  EXPECT_CALL(mutator, Mutate(true, _))
+      .WillOnce(SetArgPointee<1>(5));
+```
+
+In this example, when `mutator.Mutate()` is called, we will assign 5
+to the `int` variable pointed to by argument #1
+(0-based).
+
+`SetArgPointee()` conveniently makes an internal copy of the
+value you pass to it, removing the need to keep the value in scope and
+alive. The implication however is that the value must have a copy
+constructor and assignment operator.
+
+If the mock method also needs to return a value as well, you can chain
+`SetArgPointee()` with `Return()` using `DoAll()`:
+
+```
+using ::testing::_;
+using ::testing::Return;
+using ::testing::SetArgPointee;
+
+class MockMutator : public Mutator {
+ public:
+  ...
+  MOCK_METHOD1(MutateInt, bool(int* value));
+};
+...
+
+  MockMutator mutator;
+  EXPECT_CALL(mutator, MutateInt(_))
+      .WillOnce(DoAll(SetArgPointee<0>(5),
+                      Return(true)));
+```
+
+If the output argument is an array, use the
+`SetArrayArgument<N>(first, last)` action instead. It copies the
+elements in source range `[first, last)` to the array pointed to by
+the `N`-th (0-based) argument:
+
+```
+using ::testing::NotNull;
+using ::testing::SetArrayArgument;
+
+class MockArrayMutator : public ArrayMutator {
+ public:
+  MOCK_METHOD2(Mutate, void(int* values, int num_values));
+  ...
+};
+...
+
+  MockArrayMutator mutator;
+  int values[5] = { 1, 2, 3, 4, 5 };
+  EXPECT_CALL(mutator, Mutate(NotNull(), 5))
+      .WillOnce(SetArrayArgument<0>(values, values + 5));
+```
+
+This also works when the argument is an output iterator:
+
+```
+using ::testing::_;
+using ::testing::SeArrayArgument;
+
+class MockRolodex : public Rolodex {
+ public:
+  MOCK_METHOD1(GetNames, void(std::back_insert_iterator<vector<string> >));
+  ...
+};
+...
+
+  MockRolodex rolodex;
+  vector<string> names;
+  names.push_back("George");
+  names.push_back("John");
+  names.push_back("Thomas");
+  EXPECT_CALL(rolodex, GetNames(_))
+      .WillOnce(SetArrayArgument<0>(names.begin(), names.end()));
+```
+
+## Changing a Mock Object's Behavior Based on the State ##
+
+If you expect a call to change the behavior of a mock object, you can use `::testing::InSequence` to specify different behaviors before and after the call:
+
+```
+using ::testing::InSequence;
+using ::testing::Return;
+
+...
+  {
+    InSequence seq;
+    EXPECT_CALL(my_mock, IsDirty())
+        .WillRepeatedly(Return(true));
+    EXPECT_CALL(my_mock, Flush());
+    EXPECT_CALL(my_mock, IsDirty())
+        .WillRepeatedly(Return(false));
+  }
+  my_mock.FlushIfDirty();
+```
+
+This makes `my_mock.IsDirty()` return `true` before `my_mock.Flush()` is called and return `false` afterwards.
+
+If the behavior change is more complex, you can store the effects in a variable and make a mock method get its return value from that variable:
+
+```
+using ::testing::_;
+using ::testing::SaveArg;
+using ::testing::Return;
+
+ACTION_P(ReturnPointee, p) { return *p; }
+...
+  int previous_value = 0;
+  EXPECT_CALL(my_mock, GetPrevValue())
+      .WillRepeatedly(ReturnPointee(&previous_value));
+  EXPECT_CALL(my_mock, UpdateValue(_))
+      .WillRepeatedly(SaveArg<0>(&previous_value));
+  my_mock.DoSomethingToUpdateValue();
+```
+
+Here `my_mock.GetPrevValue()` will always return the argument of the last `UpdateValue()` call.
+
+## Setting the Default Value for a Return Type ##
+
+If a mock method's return type is a built-in C++ type or pointer, by
+default it will return 0 when invoked. You only need to specify an
+action if this default value doesn't work for you.
+
+Sometimes, you may want to change this default value, or you may want
+to specify a default value for types Google Mock doesn't know
+about. You can do this using the `::testing::DefaultValue` class
+template:
+
+```
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD0(CalculateBar, Bar());
+};
+...
+
+  Bar default_bar;
+  // Sets the default return value for type Bar.
+  DefaultValue<Bar>::Set(default_bar);
+
+  MockFoo foo;
+
+  // We don't need to specify an action here, as the default
+  // return value works for us.
+  EXPECT_CALL(foo, CalculateBar());
+
+  foo.CalculateBar();  // This should return default_bar.
+
+  // Unsets the default return value.
+  DefaultValue<Bar>::Clear();
+```
+
+Please note that changing the default value for a type can make you
+tests hard to understand. We recommend you to use this feature
+judiciously. For example, you may want to make sure the `Set()` and
+`Clear()` calls are right next to the code that uses your mock.
+
+## Setting the Default Actions for a Mock Method ##
+
+You've learned how to change the default value of a given
+type. However, this may be too coarse for your purpose: perhaps you
+have two mock methods with the same return type and you want them to
+have different behaviors. The `ON_CALL()` macro allows you to
+customize your mock's behavior at the method level:
+
+```
+using ::testing::_;
+using ::testing::AnyNumber;
+using ::testing::Gt;
+using ::testing::Return;
+...
+  ON_CALL(foo, Sign(_))
+      .WillByDefault(Return(-1));
+  ON_CALL(foo, Sign(0))
+      .WillByDefault(Return(0));
+  ON_CALL(foo, Sign(Gt(0)))
+      .WillByDefault(Return(1));
+
+  EXPECT_CALL(foo, Sign(_))
+      .Times(AnyNumber());
+
+  foo.Sign(5);   // This should return 1.
+  foo.Sign(-9);  // This should return -1.
+  foo.Sign(0);   // This should return 0.
+```
+
+As you may have guessed, when there are more than one `ON_CALL()`
+statements, the news order take precedence over the older ones. In
+other words, the **last** one that matches the function arguments will
+be used. This matching order allows you to set up the common behavior
+in a mock object's constructor or the test fixture's set-up phase and
+specialize the mock's behavior later.
+
+## Using Functions/Methods/Functors as Actions ##
+
+If the built-in actions don't suit you, you can easily use an existing
+function, method, or functor as an action:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD2(Sum, int(int x, int y));
+  MOCK_METHOD1(ComplexJob, bool(int x));
+};
+
+int CalculateSum(int x, int y) { return x + y; }
+
+class Helper {
+ public:
+  bool ComplexJob(int x);
+};
+...
+
+  MockFoo foo;
+  Helper helper;
+  EXPECT_CALL(foo, Sum(_, _))
+      .WillOnce(Invoke(CalculateSum));
+  EXPECT_CALL(foo, ComplexJob(_))
+      .WillOnce(Invoke(&helper, &Helper::ComplexJob));
+
+  foo.Sum(5, 6);       // Invokes CalculateSum(5, 6).
+  foo.ComplexJob(10);  // Invokes helper.ComplexJob(10);
+```
+
+The only requirement is that the type of the function, etc must be
+_compatible_ with the signature of the mock function, meaning that the
+latter's arguments can be implicitly converted to the corresponding
+arguments of the former, and the former's return type can be
+implicitly converted to that of the latter. So, you can invoke
+something whose type is _not_ exactly the same as the mock function,
+as long as it's safe to do so - nice, huh?
+
+## Invoking a Function/Method/Functor Without Arguments ##
+
+`Invoke()` is very useful for doing actions that are more complex. It
+passes the mock function's arguments to the function or functor being
+invoked such that the callee has the full context of the call to work
+with. If the invoked function is not interested in some or all of the
+arguments, it can simply ignore them.
+
+Yet, a common pattern is that a test author wants to invoke a function
+without the arguments of the mock function. `Invoke()` allows her to
+do that using a wrapper function that throws away the arguments before
+invoking an underlining nullary function. Needless to say, this can be
+tedious and obscures the intent of the test.
+
+`InvokeWithoutArgs()` solves this problem. It's like `Invoke()` except
+that it doesn't pass the mock function's arguments to the
+callee. Here's an example:
+
+```
+using ::testing::_;
+using ::testing::InvokeWithoutArgs;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD1(ComplexJob, bool(int n));
+};
+
+bool Job1() { ... }
+...
+
+  MockFoo foo;
+  EXPECT_CALL(foo, ComplexJob(_))
+      .WillOnce(InvokeWithoutArgs(Job1));
+
+  foo.ComplexJob(10);  // Invokes Job1().
+```
+
+## Invoking an Argument of the Mock Function ##
+
+Sometimes a mock function will receive a function pointer or a functor
+(in other words, a "callable") as an argument, e.g.
+
+```
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD2(DoThis, bool(int n, bool (*fp)(int)));
+};
+```
+
+and you may want to invoke this callable argument:
+
+```
+using ::testing::_;
+...
+  MockFoo foo;
+  EXPECT_CALL(foo, DoThis(_, _))
+      .WillOnce(...);
+  // Will execute (*fp)(5), where fp is the
+  // second argument DoThis() receives.
+```
+
+Arghh, you need to refer to a mock function argument but C++ has no
+lambda (yet), so you have to define your own action. :-( Or do you
+really?
+
+Well, Google Mock has an action to solve _exactly_ this problem:
+
+```
+  InvokeArgument<N>(arg_1, arg_2, ..., arg_m)
+```
+
+will invoke the `N`-th (0-based) argument the mock function receives,
+with `arg_1`, `arg_2`, ..., and `arg_m`. No matter if the argument is
+a function pointer or a functor, Google Mock handles them both.
+
+With that, you could write:
+
+```
+using ::testing::_;
+using ::testing::InvokeArgument;
+...
+  EXPECT_CALL(foo, DoThis(_, _))
+      .WillOnce(InvokeArgument<1>(5));
+  // Will execute (*fp)(5), where fp is the
+  // second argument DoThis() receives.
+```
+
+What if the callable takes an argument by reference? No problem - just
+wrap it inside `ByRef()`:
+
+```
+...
+  MOCK_METHOD1(Bar, bool(bool (*fp)(int, const Helper&)));
+...
+using ::testing::_;
+using ::testing::ByRef;
+using ::testing::InvokeArgument;
+...
+
+  MockFoo foo;
+  Helper helper;
+  ...
+  EXPECT_CALL(foo, Bar(_))
+      .WillOnce(InvokeArgument<0>(5, ByRef(helper)));
+  // ByRef(helper) guarantees that a reference to helper, not a copy of it,
+  // will be passed to the callable.
+```
+
+What if the callable takes an argument by reference and we do **not**
+wrap the argument in `ByRef()`? Then `InvokeArgument()` will _make a
+copy_ of the argument, and pass a _reference to the copy_, instead of
+a reference to the original value, to the callable. This is especially
+handy when the argument is a temporary value:
+
+```
+...
+  MOCK_METHOD1(DoThat, bool(bool (*f)(const double& x, const string& s)));
+...
+using ::testing::_;
+using ::testing::InvokeArgument;
+...
+
+  MockFoo foo;
+  ...
+  EXPECT_CALL(foo, DoThat(_))
+      .WillOnce(InvokeArgument<0>(5.0, string("Hi")));
+  // Will execute (*f)(5.0, string("Hi")), where f is the function pointer
+  // DoThat() receives.  Note that the values 5.0 and string("Hi") are
+  // temporary and dead once the EXPECT_CALL() statement finishes.  Yet
+  // it's fine to perform this action later, since a copy of the values
+  // are kept inside the InvokeArgument action.
+```
+
+## Ignoring an Action's Result ##
+
+Sometimes you have an action that returns _something_, but you need an
+action that returns `void` (perhaps you want to use it in a mock
+function that returns `void`, or perhaps it needs to be used in
+`DoAll()` and it's not the last in the list). `IgnoreResult()` lets
+you do that. For example:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::Return;
+
+int Process(const MyData& data);
+string DoSomething();
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD1(Abc, void(const MyData& data));
+  MOCK_METHOD0(Xyz, bool());
+};
+...
+
+  MockFoo foo;
+  EXPECT_CALL(foo, Abc(_))
+  // .WillOnce(Invoke(Process));
+  // The above line won't compile as Process() returns int but Abc() needs
+  // to return void.
+      .WillOnce(IgnoreResult(Invoke(Process)));
+
+  EXPECT_CALL(foo, Xyz())
+      .WillOnce(DoAll(IgnoreResult(Invoke(DoSomething)),
+      // Ignores the string DoSomething() returns.
+                      Return(true)));
+```
+
+Note that you **cannot** use `IgnoreResult()` on an action that already
+returns `void`. Doing so will lead to ugly compiler errors.
+
+## Selecting an Action's Arguments ##
+
+Say you have a mock function `Foo()` that takes seven arguments, and
+you have a custom action that you want to invoke when `Foo()` is
+called. Trouble is, the custom action only wants three arguments:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+...
+  MOCK_METHOD7(Foo, bool(bool visible, const string& name, int x, int y,
+                         const map<pair<int, int>, double>& weight,
+                         double min_weight, double max_wight));
+...
+
+bool IsVisibleInQuadrant1(bool visible, int x, int y) {
+  return visible && x >= 0 && y >= 0;
+}
+...
+
+  EXPECT_CALL(mock, Foo(_, _, _, _, _, _, _))
+      .WillOnce(Invoke(IsVisibleInQuadrant1));  // Uh, won't compile. :-(
+```
+
+To please the compiler God, you can to define an "adaptor" that has
+the same signature as `Foo()` and calls the custom action with the
+right arguments:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+
+bool MyIsVisibleInQuadrant1(bool visible, const string& name, int x, int y,
+                            const map<pair<int, int>, double>& weight,
+                            double min_weight, double max_wight) {
+  return IsVisibleInQuadrant1(visible, x, y);
+}
+...
+
+  EXPECT_CALL(mock, Foo(_, _, _, _, _, _, _))
+      .WillOnce(Invoke(MyIsVisibleInQuadrant1));  // Now it works.
+```
+
+But isn't this awkward?
+
+Google Mock provides a generic _action adaptor_, so you can spend your
+time minding more important business than writing your own
+adaptors. Here's the syntax:
+
+```
+  WithArgs<N1, N2, ..., Nk>(action)
+```
+
+creates an action that passes the arguments of the mock function at
+the given indices (0-based) to the inner `action` and performs
+it. Using `WithArgs`, our original example can be written as:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::WithArgs;
+...
+  EXPECT_CALL(mock, Foo(_, _, _, _, _, _, _))
+      .WillOnce(WithArgs<0, 2, 3>(Invoke(IsVisibleInQuadrant1)));
+      // No need to define your own adaptor.
+```
+
+For better readability, Google Mock also gives you:
+
+  * `WithoutArgs(action)` when the inner `action` takes _no_ argument, and
+  * `WithArg<N>(action)` (no `s` after `Arg`) when the inner `action` takes _one_ argument.
+
+As you may have realized, `InvokeWithoutArgs(...)` is just syntactic
+sugar for `WithoutArgs(Inovke(...))`.
+
+Here are more tips:
+
+  * The inner action used in `WithArgs` and friends does not have to be `Invoke()` -- it can be anything.
+  * You can repeat an argument in the argument list if necessary, e.g. `WithArgs<2, 3, 3, 5>(...)`.
+  * You can change the order of the arguments, e.g. `WithArgs<3, 2, 1>(...)`.
+  * The types of the selected arguments do _not_ have to match the signature of the inner action exactly. It works as long as they can be implicitly converted to the corresponding arguments of the inner action. For example, if the 4-th argument of the mock function is an `int` and `my_action` takes a `double`, `WithArg<4>(my_action)` will work.
+
+## Ignoring Arguments in Action Functions ##
+
+The selecting-an-action's-arguments recipe showed us one way to make a
+mock function and an action with incompatible argument lists fit
+together. The downside is that wrapping the action in
+`WithArgs<...>()` can get tedious for people writing the tests.
+
+If you are defining a function, method, or functor to be used with
+`Invoke*()`, and you are not interested in some of its arguments, an
+alternative to `WithArgs` is to declare the uninteresting arguments as
+`Unused`. This makes the definition less cluttered and less fragile in
+case the types of the uninteresting arguments change. It could also
+increase the chance the action function can be reused. For example,
+given
+
+```
+  MOCK_METHOD3(Foo, double(const string& label, double x, double y));
+  MOCK_METHOD3(Bar, double(int index, double x, double y));
+```
+
+instead of
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+
+double DistanceToOriginWithLabel(const string& label, double x, double y) {
+  return sqrt(x*x + y*y);
+}
+
+double DistanceToOriginWithIndex(int index, double x, double y) {
+  return sqrt(x*x + y*y);
+}
+...
+
+  EXEPCT_CALL(mock, Foo("abc", _, _))
+      .WillOnce(Invoke(DistanceToOriginWithLabel));
+  EXEPCT_CALL(mock, Bar(5, _, _))
+      .WillOnce(Invoke(DistanceToOriginWithIndex));
+```
+
+you could write
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::Unused;
+
+double DistanceToOrigin(Unused, double x, double y) {
+  return sqrt(x*x + y*y);
+}
+...
+
+  EXEPCT_CALL(mock, Foo("abc", _, _))
+      .WillOnce(Invoke(DistanceToOrigin));
+  EXEPCT_CALL(mock, Bar(5, _, _))
+      .WillOnce(Invoke(DistanceToOrigin));
+```
+
+## Sharing Actions ##
+
+Just like matchers, a Google Mock action object consists of a pointer
+to a ref-counted implementation object. Therefore copying actions is
+also allowed and very efficient. When the last action that references
+the implementation object dies, the implementation object will be
+deleted.
+
+If you have some complex action that you want to use again and again,
+you may not have to build it from scratch everytime. If the action
+doesn't have an internal state (i.e. if it always does the same thing
+no matter how many times it has been called), you can assign it to an
+action variable and use that variable repeatedly. For example:
+
+```
+  Action<bool(int*)> set_flag = DoAll(SetArgPointee<0>(5),
+                                      Return(true));
+  ... use set_flag in .WillOnce() and .WillRepeatedly() ...
+```
+
+However, if the action has its own state, you may be surprised if you
+share the action object. Suppose you have an action factory
+`IncrementCounter(init)` which creates an action that increments and
+returns a counter whose initial value is `init`, using two actions
+created from the same expression and using a shared action will
+exihibit different behaviors. Example:
+
+```
+  EXPECT_CALL(foo, DoThis())
+      .WillRepeatedly(IncrementCounter(0));
+  EXPECT_CALL(foo, DoThat())
+      .WillRepeatedly(IncrementCounter(0));
+  foo.DoThis();  // Returns 1.
+  foo.DoThis();  // Returns 2.
+  foo.DoThat();  // Returns 1 - Blah() uses a different
+                 // counter than Bar()'s.
+```
+
+versus
+
+```
+  Action<int()> increment = IncrementCounter(0);
+
+  EXPECT_CALL(foo, DoThis())
+      .WillRepeatedly(increment);
+  EXPECT_CALL(foo, DoThat())
+      .WillRepeatedly(increment);
+  foo.DoThis();  // Returns 1.
+  foo.DoThis();  // Returns 2.
+  foo.DoThat();  // Returns 3 - the counter is shared.
+```
+
+# Misc Recipes on Using Google Mock #
+
+## Making the Compilation Faster ##
+
+Believe it or not, the _vast majority_ of the time spent on compiling
+a mock class is in generating its constructor and destructor, as they
+perform non-trivial tasks (e.g. verification of the
+expectations). What's more, mock methods with different signatures
+have different types and thus their constructors/destructors need to
+be generated by the compiler separately. As a result, if you mock many
+different types of methods, compiling your mock class can get really
+slow.
+
+If you are experiencing slow compilation, you can move the definition
+of your mock class' constructor and destructor out of the class body
+and into a `.cpp` file. This way, even if you `#include` your mock
+class in N files, the compiler only needs to generate its constructor
+and destructor once, resulting in a much faster compilation.
+
+Let's illustrate the idea using an example. Here's the definition of a
+mock class before applying this recipe:
+
+```
+// File mock_foo.h.
+...
+class MockFoo : public Foo {
+ public:
+  // Since we don't declare the constructor or the destructor,
+  // the compiler will generate them in every translation unit
+  // where this mock class is used.
+
+  MOCK_METHOD0(DoThis, int());
+  MOCK_METHOD1(DoThat, bool(const char* str));
+  ... more mock methods ...
+};
+```
+
+After the change, it would look like:
+
+```
+// File mock_foo.h.
+...
+class MockFoo : public Foo {
+ public:
+  // The constructor and destructor are declared, but not defined, here.
+  MockFoo();
+  virtual ~MockFoo();
+
+  MOCK_METHOD0(DoThis, int());
+  MOCK_METHOD1(DoThat, bool(const char* str));
+  ... more mock methods ...
+};
+```
+and
+```
+// File mock_foo.cpp.
+#include "path/to/mock_foo.h"
+
+// The definitions may appear trivial, but the functions actually do a
+// lot of things through the constructors/destructors of the member
+// variables used to implement the mock methods.
+MockFoo::MockFoo() {}
+MockFoo::~MockFoo() {}
+```
+
+## Forcing a Verification ##
+
+When it's being destoyed, your friendly mock object will automatically
+verify that all expectations on it have been satisfied, and will
+generate [Google Test](http://code.google.com/p/googletest/) failures
+if not. This is convenient as it leaves you with one less thing to
+worry about. That is, unless you are not sure if your mock object will
+be destoyed.
+
+How could it be that your mock object won't eventually be destroyed?
+Well, it might be created on the heap and owned by the code you are
+testing. Suppose there's a bug in that code and it doesn't delete the
+mock object properly - you could end up with a passing test when
+there's actually a bug.
+
+Using a heap checker is a good idea and can alleviate the concern, but
+its implementation may not be 100% reliable. So, sometimes you do want
+to _force_ Google Mock to verify a mock object before it is
+(hopefully) destructed. You can do this with
+`Mock::VerifyAndClearExpectations(&mock_object)`:
+
+```
+TEST(MyServerTest, ProcessesRequest) {
+  using ::testing::Mock;
+
+  MockFoo* const foo = new MockFoo;
+  EXPECT_CALL(*foo, ...)...;
+  // ... other expectations ...
+
+  // server now owns foo.
+  MyServer server(foo);
+  server.ProcessRequest(...);
+
+  // In case that server's destructor will forget to delete foo,
+  // this will verify the expectations anyway.
+  Mock::VerifyAndClearExpectations(foo);
+}  // server is destroyed when it goes out of scope here.
+```
+
+**Tip:** The `Mock::VerifyAndClearExpectations()` function returns a
+`bool` to indicate whether the verification was successful (`true` for
+yes), so you can wrap that function call inside a `ASSERT_TRUE()` if
+there is no point going further when the verification has failed.
+
+## Using Check Points ##
+
+Sometimes you may want to "reset" a mock object at various check
+points in your test: at each check point, you verify that all existing
+expectations on the mock object have been satisfied, and then you set
+some new expectations on it as if it's newly created. This allows you
+to work with a mock object in "phases" whose sizes are each
+manageable.
+
+One such scenario is that in your test's `SetUp()` function, you may
+want to put the object you are testing into a certain state, with the
+help from a mock object. Once in the desired state, you want to clear
+all expectations on the mock, such that in the `TEST_F` body you can
+set fresh expectations on it.
+
+As you may have figured out, the `Mock::VerifyAndClearExpectations()`
+function we saw in the previous recipe can help you here. Or, if you
+are using `ON_CALL()` to set default actions on the mock object and
+want to clear the default actions as well, use
+`Mock::VerifyAndClear(&mock_object)` instead. This function does what
+`Mock::VerifyAndClearExpectations(&mock_object)` does and returns the
+same `bool`, **plus** it clears the `ON_CALL()` statements on
+`mock_object` too.
+
+Another trick you can use to achieve the same effect is to put the
+expectations in sequences and insert calls to a dummy "check-point"
+function at specific places. Then you can verify that the mock
+function calls do happen at the right time. For example, if you are
+exercising code:
+
+```
+Foo(1);
+Foo(2);
+Foo(3);
+```
+
+and want to verify that `Foo(1)` and `Foo(3)` both invoke
+`mock.Bar("a")`, but `Foo(2)` doesn't invoke anything. You can write:
+
+```
+using ::testing::MockFunction;
+
+TEST(FooTest, InvokesBarCorrectly) {
+  MyMock mock;
+  // Class MockFunction<F> has exactly one mock method.  It is named
+  // Call() and has type F.
+  MockFunction<void(string check_point_name)> check;
+  {
+    InSequence s;
+
+    EXPECT_CALL(mock, Bar("a"));
+    EXPECT_CALL(check, Call("1"));
+    EXPECT_CALL(check, Call("2"));
+    EXPECT_CALL(mock, Bar("a"));
+  }
+  Foo(1);
+  check.Call("1");
+  Foo(2);
+  check.Call("2");
+  Foo(3);
+}
+```
+
+The expectation spec says that the first `Bar("a")` must happen before
+check point "1", the second `Bar("a")` must happen after check point "2",
+and nothing should happen between the two check points. The explicit
+check points make it easy to tell which `Bar("a")` is called by which
+call to `Foo()`.
+
+## Mocking Destructors ##
+
+Sometimes you want to make sure a mock object is destructed at the
+right time, e.g. after `bar->A()` is called but before `bar->B()` is
+called. We already know that you can specify constraints on the order
+of mock function calls, so all we need to do is to mock the destructor
+of the mock function.
+
+This sounds simple, except for one problem: a destructor is a special
+function with special syntax and special semantics, and the
+`MOCK_METHOD0` macro doesn't work for it:
+
+```
+  MOCK_METHOD0(~MockFoo, void());  // Won't compile!
+```
+
+The good news is that you can use a simple pattern to achieve the same
+effect. First, add a mock function `Die()` to your mock class and call
+it in the destructor, like this:
+
+```
+class MockFoo : public Foo {
+  ...
+  // Add the following two lines to the mock class.
+  MOCK_METHOD0(Die, void());
+  virtual ~MockFoo() { Die(); }
+};
+```
+
+(If the name `Die()` clashes with an existing symbol, choose another
+name.) Now, we have translated the problem of testing when a `MockFoo`
+object dies to testing when its `Die()` method is called:
+
+```
+  MockFoo* foo = new MockFoo;
+  MockBar* bar = new MockBar;
+  ...
+  {
+    InSequence s;
+
+    // Expects *foo to die after bar->A() and before bar->B().
+    EXPECT_CALL(*bar, A());
+    EXPECT_CALL(*foo, Die());
+    EXPECT_CALL(*bar, B());
+  }
+```
+
+And that's that.
+
+## Using Google Mock and Threads ##
+
+**IMPORTANT NOTE:** What we describe in this recipe is **ONLY** true on
+platforms where Google Mock is thread-safe. Currently these are only
+platforms that support the pthreads library (this includes Linux and Mac).
+To make it thread-safe on other platforms we only need to implement
+some synchronization operations in `"gtest/internal/gtest-port.h"`.
+
+In a **unit** test, it's best if you could isolate and test a piece of
+code in a single-threaded context. That avoids race conditions and
+dead locks, and makes debugging your test much easier.
+
+Yet many programs are multi-threaded, and sometimes to test something
+we need to pound on it from more than one thread. Google Mock works
+for this purpose too.
+
+Remember the steps for using a mock:
+
+  1. Create a mock object `foo`.
+  1. Set its default actions and expectations using `ON_CALL()` and `EXPECT_CALL()`.
+  1. The code under test calls methods of `foo`.
+  1. Optionally, verify and reset the mock.
+  1. Destroy the mock yourself, or let the code under test destroy it. The destructor will automatically verify it.
+
+If you follow the following simple rules, your mocks and threads can
+live happily togeter:
+
+  * Execute your _test code_ (as opposed to the code being tested) in _one_ thread. This makes your test easy to follow.
+  * Obviously, you can do step #1 without locking.
+  * When doing step #2 and #5, make sure no other thread is accessing `foo`. Obvious too, huh?
+  * #3 and #4 can be done either in one thread or in multiple threads - anyway you want. Google Mock takes care of the locking, so you don't have to do any - unless required by your test logic.
+
+If you violate the rules (for example, if you set expectations on a
+mock while another thread is calling its methods), you get undefined
+behavior. That's not fun, so don't do it.
+
+Google Mock guarantees that the action for a mock function is done in
+the same thread that called the mock function. For example, in
+
+```
+  EXPECT_CALL(mock, Foo(1))
+      .WillOnce(action1);
+  EXPECT_CALL(mock, Foo(2))
+      .WillOnce(action2);
+```
+
+if `Foo(1)` is called in thread 1 and `Foo(2)` is called in thread 2,
+Google Mock will execute `action1` in thread 1 and `action2` in thread
+2.
+
+Google Mock does _not_ impose a sequence on actions performed in
+different threads (doing so may create deadlocks as the actions may
+need to cooperate). This means that the execution of `action1` and
+`action2` in the above example _may_ interleave. If this is a problem,
+you should add proper synchronization logic to `action1` and `action2`
+to make the test thread-safe.
+
+
+Also, remember that `DefaultValue<T>` is a global resource that
+potentially affects _all_ living mock objects in your
+program. Naturally, you won't want to mess with it from multiple
+threads or when there still are mocks in action.
+
+## Controlling How Much Information Google Mock Prints ##
+
+When Google Mock sees something that has the potential of being an
+error (e.g. a mock function with no expectation is called, a.k.a. an
+uninteresting call, which is allowed but perhaps you forgot to
+explicitly ban the call), it prints some warning messages, including
+the arguments of the function and the return value. Hopefully this
+will remind you to take a look and see if there is indeed a problem.
+
+Sometimes you are confident that your tests are correct and may not
+appreciate such friendly messages. Some other times, you are debugging
+your tests or learning about the behavior of the code you are testing,
+and wish you could observe every mock call that happens (including
+argument values and the return value). Clearly, one size doesn't fit
+all.
+
+You can control how much Google Mock tells you using the
+`--gmock_verbose=LEVEL` command-line flag, where `LEVEL` is a string
+with three possible values:
+
+  * `info`: Google Mock will print all informational messages, warnings, and errors (most verbose). At this setting, Google Mock will also log any calls to the `ON_CALL/EXPECT_CALL` macros.
+  * `warning`: Google Mock will print both warnings and errors (less verbose). This is the default.
+  * `error`: Google Mock will print errors only (least verbose).
+
+Alternatively, you can adjust the value of that flag from within your
+tests like so:
+
+```
+  ::testing::FLAGS_gmock_verbose = "error";
+```
+
+Now, judiciously use the right flag to enable Google Mock serve you better!
+
+## Running Tests in Emacs ##
+
+If you build and run your tests in Emacs, the source file locations of
+Google Mock and [Google Test](http://code.google.com/p/googletest/)
+errors will be highlighted. Just press `<Enter>` on one of them and
+you'll be taken to the offending line. Or, you can just type `C-x ``
+to jump to the next error.
+
+To make it even easier, you can add the following lines to your
+`~/.emacs` file:
+
+```
+(global-set-key "\M-m"   'compile)  ; m is for make
+(global-set-key [M-down] 'next-error)
+(global-set-key [M-up]   '(lambda () (interactive) (next-error -1)))
+```
+
+Then you can type `M-m` to start a build, or `M-up`/`M-down` to move
+back and forth between errors.
+
+## Fusing Google Mock Source Files ##
+
+Google Mock's implementation consists of dozens of files (excluding
+its own tests).  Sometimes you may want them to be packaged up in
+fewer files instead, such that you can easily copy them to a new
+machine and start hacking there.  For this we provide an experimental
+Python script `fuse_gmock_files.py` in the `scripts/` directory
+(starting with release 1.2.0).  Assuming you have Python 2.4 or above
+installed on your machine, just go to that directory and run
+```
+python fuse_gmock_files.py OUTPUT_DIR
+```
+
+and you should see an `OUTPUT_DIR` directory being created with files
+`gtest/gtest.h`, `gmock/gmock.h`, and `gmock-gtest-all.cc` in it.
+These three files contain everything you need to use Google Mock (and
+Google Test).  Just copy them to anywhere you want and you are ready
+to write tests and use mocks.  You can use the
+[scrpts/test/Makefile](http://code.google.com/p/googlemock/source/browse/trunk/scripts/test/Makefile) file as an example on how to compile your tests
+against them.
+
+# Extending Google Mock #
+
+## Writing New Matchers Quickly ##
+
+The `MATCHER*` family of macros can be used to define custom matchers
+easily.  The syntax:
+
+```
+MATCHER(name, description_string_expression) { statements; }
+```
+
+will define a matcher with the given name that executes the
+statements, which must return a `bool` to indicate if the match
+succeeds.  Inside the statements, you can refer to the value being
+matched by `arg`, and refer to its type by `arg_type`.
+
+The description string is a `string`-typed expression that documents
+what the matcher does, and is used to generate the failure message
+when the match fails.  It can (and should) reference the special
+`bool` variable `negation`, and should evaluate to the description of
+the matcher when `negation` is `false`, or that of the matcher's
+negation when `negation` is `true`.
+
+For convenience, we allow the description string to be empty (`""`),
+in which case Google Mock will use the sequence of words in the
+matcher name as the description.
+
+For example:
+```
+MATCHER(IsDivisibleBy7, "") { return (arg % 7) == 0; }
+```
+allows you to write
+```
+  // Expects mock_foo.Bar(n) to be called where n is divisible by 7.
+  EXPECT_CALL(mock_foo, Bar(IsDivisibleBy7()));
+```
+or,
+```
+using ::testing::Not;
+...
+  EXPECT_THAT(some_expression, IsDivisibleBy7());
+  EXPECT_THAT(some_other_expression, Not(IsDivisibleBy7()));
+```
+If the above assertions fail, they will print something like:
+```
+  Value of: some_expression
+  Expected: is divisible by 7
+    Actual: 27
+...
+  Value of: some_other_expression
+  Expected: not (is divisible by 7)
+    Actual: 21
+```
+where the descriptions `"is divisible by 7"` and `"not (is divisible
+by 7)"` are automatically calculated from the matcher name
+`IsDivisibleBy7`.
+
+As you may have noticed, the auto-generated descriptions (especially
+those for the negation) may not be so great. You can always override
+them with a string expression of your own:
+```
+MATCHER(IsDivisibleBy7, std::string(negation ? "isn't" : "is") +
+                        " divisible by 7") {
+  return (arg % 7) == 0;
+}
+```
+
+Optionally, you can stream additional information to a hidden argument
+named `result_listener` to explain the match result. For example, a
+better definition of `IsDivisibleBy7` is:
+```
+MATCHER(IsDivisibleBy7, "") {
+  if ((arg % 7) == 0)
+    return true;
+
+  *result_listener << "the remainder is " << (arg % 7);
+  return false;
+}
+```
+
+With this definition, the above assertion will give a better message:
+```
+  Value of: some_expression
+  Expected: is divisible by 7
+    Actual: 27 (the remainder is 6)
+```
+
+You should let `MatchAndExplain()` print _any additional information_
+that can help a user understand the match result. Note that it should
+explain why the match succeeds in case of a success (unless it's
+obvious) - this is useful when the matcher is used inside
+`Not()`. There is no need to print the argument value itself, as
+Google Mock already prints it for you.
+
+**Notes:**
+
+  1. The type of the value being matched (`arg_type`) is determined by the context in which you use the matcher and is supplied to you by the compiler, so you don't need to worry about declaring it (nor can you).  This allows the matcher to be polymorphic.  For example, `IsDivisibleBy7()` can be used to match any type where the value of `(arg % 7) == 0` can be implicitly converted to a `bool`.  In the `Bar(IsDivisibleBy7())` example above, if method `Bar()` takes an `int`, `arg_type` will be `int`; if it takes an `unsigned long`, `arg_type` will be `unsigned long`; and so on.
+  1. Google Mock doesn't guarantee when or how many times a matcher will be invoked. Therefore the matcher logic must be _purely functional_ (i.e. it cannot have any side effect, and the result must not depend on anything other than the value being matched and the matcher parameters). This requirement must be satisfied no matter how you define the matcher (e.g. using one of the methods described in the following recipes). In particular, a matcher can never call a mock function, as that will affect the state of the mock object and Google Mock.
+
+## Writing New Parameterized Matchers Quickly ##
+
+Sometimes you'll want to define a matcher that has parameters.  For that you
+can use the macro:
+```
+MATCHER_P(name, param_name, description_string) { statements; }
+```
+where the description string can be either `""` or a string expression
+that references `negation` and `param_name`.
+
+For example:
+```
+MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; }
+```
+will allow you to write:
+```
+  EXPECT_THAT(Blah("a"), HasAbsoluteValue(n));
+```
+which may lead to this message (assuming `n` is 10):
+```
+  Value of: Blah("a")
+  Expected: has absolute value 10
+    Actual: -9
+```
+
+Note that both the matcher description and its parameter are
+printed, making the message human-friendly.
+
+In the matcher definition body, you can write `foo_type` to
+reference the type of a parameter named `foo`.  For example, in the
+body of `MATCHER_P(HasAbsoluteValue, value)` above, you can write
+`value_type` to refer to the type of `value`.
+
+Google Mock also provides `MATCHER_P2`, `MATCHER_P3`, ..., up to
+`MATCHER_P10` to support multi-parameter matchers:
+```
+MATCHER_Pk(name, param_1, ..., param_k, description_string) { statements; }
+```
+
+Please note that the custom description string is for a particular
+**instance** of the matcher, where the parameters have been bound to
+actual values.  Therefore usually you'll want the parameter values to
+be part of the description.  Google Mock lets you do that by
+referencing the matcher parameters in the description string
+expression.
+
+For example,
+```
+  using ::testing::PrintToString;
+  MATCHER_P2(InClosedRange, low, hi,
+             std::string(negation ? "isn't" : "is") + " in range [" +
+             PrintToString(low) + ", " + PrintToString(hi) + "]") {
+    return low <= arg && arg <= hi;
+  }
+  ...
+  EXPECT_THAT(3, InClosedRange(4, 6));
+```
+would generate a failure that contains the message:
+```
+  Expected: is in range [4, 6]
+```
+
+If you specify `""` as the description, the failure message will
+contain the sequence of words in the matcher name followed by the
+parameter values printed as a tuple.  For example,
+```
+  MATCHER_P2(InClosedRange, low, hi, "") { ... }
+  ...
+  EXPECT_THAT(3, InClosedRange(4, 6));
+```
+would generate a failure that contains the text:
+```
+  Expected: in closed range (4, 6)
+```
+
+For the purpose of typing, you can view
+```
+MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... }
+```
+as shorthand for
+```
+template <typename p1_type, ..., typename pk_type>
+FooMatcherPk<p1_type, ..., pk_type>
+Foo(p1_type p1, ..., pk_type pk) { ... }
+```
+
+When you write `Foo(v1, ..., vk)`, the compiler infers the types of
+the parameters `v1`, ..., and `vk` for you.  If you are not happy with
+the result of the type inference, you can specify the types by
+explicitly instantiating the template, as in `Foo<long, bool>(5, false)`.
+As said earlier, you don't get to (or need to) specify
+`arg_type` as that's determined by the context in which the matcher
+is used.
+
+You can assign the result of expression `Foo(p1, ..., pk)` to a
+variable of type `FooMatcherPk<p1_type, ..., pk_type>`.  This can be
+useful when composing matchers.  Matchers that don't have a parameter
+or have only one parameter have special types: you can assign `Foo()`
+to a `FooMatcher`-typed variable, and assign `Foo(p)` to a
+`FooMatcherP<p_type>`-typed variable.
+
+While you can instantiate a matcher template with reference types,
+passing the parameters by pointer usually makes your code more
+readable.  If, however, you still want to pass a parameter by
+reference, be aware that in the failure message generated by the
+matcher you will see the value of the referenced object but not its
+address.
+
+You can overload matchers with different numbers of parameters:
+```
+MATCHER_P(Blah, a, description_string_1) { ... }
+MATCHER_P2(Blah, a, b, description_string_2) { ... }
+```
+
+While it's tempting to always use the `MATCHER*` macros when defining
+a new matcher, you should also consider implementing
+`MatcherInterface` or using `MakePolymorphicMatcher()` instead (see
+the recipes that follow), especially if you need to use the matcher a
+lot.  While these approaches require more work, they give you more
+control on the types of the value being matched and the matcher
+parameters, which in general leads to better compiler error messages
+that pay off in the long run.  They also allow overloading matchers
+based on parameter types (as opposed to just based on the number of
+parameters).
+
+## Writing New Monomorphic Matchers ##
+
+A matcher of argument type `T` implements
+`::testing::MatcherInterface<T>` and does two things: it tests whether a
+value of type `T` matches the matcher, and can describe what kind of
+values it matches. The latter ability is used for generating readable
+error messages when expectations are violated.
+
+The interface looks like this:
+
+```
+class MatchResultListener {
+ public:
+  ...
+  // Streams x to the underlying ostream; does nothing if the ostream
+  // is NULL.
+  template <typename T>
+  MatchResultListener& operator<<(const T& x);
+
+  // Returns the underlying ostream.
+  ::std::ostream* stream();
+};
+
+template <typename T>
+class MatcherInterface {
+ public:
+  virtual ~MatcherInterface();
+
+  // Returns true iff the matcher matches x; also explains the match
+  // result to 'listener'.
+  virtual bool MatchAndExplain(T x, MatchResultListener* listener) const = 0;
+
+  // Describes this matcher to an ostream.
+  virtual void DescribeTo(::std::ostream* os) const = 0;
+
+  // Describes the negation of this matcher to an ostream.
+  virtual void DescribeNegationTo(::std::ostream* os) const;
+};
+```
+
+If you need a custom matcher but `Truly()` is not a good option (for
+example, you may not be happy with the way `Truly(predicate)`
+describes itself, or you may want your matcher to be polymorphic as
+`Eq(value)` is), you can define a matcher to do whatever you want in
+two steps: first implement the matcher interface, and then define a
+factory function to create a matcher instance. The second step is not
+strictly needed but it makes the syntax of using the matcher nicer.
+
+For example, you can define a matcher to test whether an `int` is
+divisible by 7 and then use it like this:
+```
+using ::testing::MakeMatcher;
+using ::testing::Matcher;
+using ::testing::MatcherInterface;
+using ::testing::MatchResultListener;
+
+class DivisibleBy7Matcher : public MatcherInterface<int> {
+ public:
+  virtual bool MatchAndExplain(int n, MatchResultListener* listener) const {
+    return (n % 7) == 0;
+  }
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "is divisible by 7";
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "is not divisible by 7";
+  }
+};
+
+inline Matcher<int> DivisibleBy7() {
+  return MakeMatcher(new DivisibleBy7Matcher);
+}
+...
+
+  EXPECT_CALL(foo, Bar(DivisibleBy7()));
+```
+
+You may improve the matcher message by streaming additional
+information to the `listener` argument in `MatchAndExplain()`:
+
+```
+class DivisibleBy7Matcher : public MatcherInterface<int> {
+ public:
+  virtual bool MatchAndExplain(int n,
+                               MatchResultListener* listener) const {
+    const int remainder = n % 7;
+    if (remainder != 0) {
+      *listener << "the remainder is " << remainder;
+    }
+    return remainder == 0;
+  }
+  ...
+};
+```
+
+Then, `EXPECT_THAT(x, DivisibleBy7());` may general a message like this:
+```
+Value of: x
+Expected: is divisible by 7
+  Actual: 23 (the remainder is 2)
+```
+
+## Writing New Polymorphic Matchers ##
+
+You've learned how to write your own matchers in the previous
+recipe. Just one problem: a matcher created using `MakeMatcher()` only
+works for one particular type of arguments. If you want a
+_polymorphic_ matcher that works with arguments of several types (for
+instance, `Eq(x)` can be used to match a `value` as long as `value` ==
+`x` compiles -- `value` and `x` don't have to share the same type),
+you can learn the trick from `"gmock/gmock-matchers.h"` but it's a bit
+involved.
+
+Fortunately, most of the time you can define a polymorphic matcher
+easily with the help of `MakePolymorphicMatcher()`. Here's how you can
+define `NotNull()` as an example:
+
+```
+using ::testing::MakePolymorphicMatcher;
+using ::testing::MatchResultListener;
+using ::testing::NotNull;
+using ::testing::PolymorphicMatcher;
+
+class NotNullMatcher {
+ public:
+  // To implement a polymorphic matcher, first define a COPYABLE class
+  // that has three members MatchAndExplain(), DescribeTo(), and
+  // DescribeNegationTo(), like the following.
+
+  // In this example, we want to use NotNull() with any pointer, so
+  // MatchAndExplain() accepts a pointer of any type as its first argument.
+  // In general, you can define MatchAndExplain() as an ordinary method or
+  // a method template, or even overload it.
+  template <typename T>
+  bool MatchAndExplain(T* p,
+                       MatchResultListener* /* listener */) const {
+    return p != NULL;
+  }
+
+  // Describes the property of a value matching this matcher.
+  void DescribeTo(::std::ostream* os) const { *os << "is not NULL"; }
+
+  // Describes the property of a value NOT matching this matcher.
+  void DescribeNegationTo(::std::ostream* os) const { *os << "is NULL"; }
+};
+
+// To construct a polymorphic matcher, pass an instance of the class
+// to MakePolymorphicMatcher().  Note the return type.
+inline PolymorphicMatcher<NotNullMatcher> NotNull() {
+  return MakePolymorphicMatcher(NotNullMatcher());
+}
+...
+
+  EXPECT_CALL(foo, Bar(NotNull()));  // The argument must be a non-NULL pointer.
+```
+
+**Note:** Your polymorphic matcher class does **not** need to inherit from
+`MatcherInterface` or any other class, and its methods do **not** need
+to be virtual.
+
+Like in a monomorphic matcher, you may explain the match result by
+streaming additional information to the `listener` argument in
+`MatchAndExplain()`.
+
+## Writing New Cardinalities ##
+
+A cardinality is used in `Times()` to tell Google Mock how many times
+you expect a call to occur. It doesn't have to be exact. For example,
+you can say `AtLeast(5)` or `Between(2, 4)`.
+
+If the built-in set of cardinalities doesn't suit you, you are free to
+define your own by implementing the following interface (in namespace
+`testing`):
+
+```
+class CardinalityInterface {
+ public:
+  virtual ~CardinalityInterface();
+
+  // Returns true iff call_count calls will satisfy this cardinality.
+  virtual bool IsSatisfiedByCallCount(int call_count) const = 0;
+
+  // Returns true iff call_count calls will saturate this cardinality.
+  virtual bool IsSaturatedByCallCount(int call_count) const = 0;
+
+  // Describes self to an ostream.
+  virtual void DescribeTo(::std::ostream* os) const = 0;
+};
+```
+
+For example, to specify that a call must occur even number of times,
+you can write
+
+```
+using ::testing::Cardinality;
+using ::testing::CardinalityInterface;
+using ::testing::MakeCardinality;
+
+class EvenNumberCardinality : public CardinalityInterface {
+ public:
+  virtual bool IsSatisfiedByCallCount(int call_count) const {
+    return (call_count % 2) == 0;
+  }
+
+  virtual bool IsSaturatedByCallCount(int call_count) const {
+    return false;
+  }
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "called even number of times";
+  }
+};
+
+Cardinality EvenNumber() {
+  return MakeCardinality(new EvenNumberCardinality);
+}
+...
+
+  EXPECT_CALL(foo, Bar(3))
+      .Times(EvenNumber());
+```
+
+## Writing New Actions Quickly ##
+
+If the built-in actions don't work for you, and you find it
+inconvenient to use `Invoke()`, you can use a macro from the `ACTION*`
+family to quickly define a new action that can be used in your code as
+if it's a built-in action.
+
+By writing
+```
+ACTION(name) { statements; }
+```
+in a namespace scope (i.e. not inside a class or function), you will
+define an action with the given name that executes the statements.
+The value returned by `statements` will be used as the return value of
+the action.  Inside the statements, you can refer to the K-th
+(0-based) argument of the mock function as `argK`.  For example:
+```
+ACTION(IncrementArg1) { return ++(*arg1); }
+```
+allows you to write
+```
+... WillOnce(IncrementArg1());
+```
+
+Note that you don't need to specify the types of the mock function
+arguments.  Rest assured that your code is type-safe though:
+you'll get a compiler error if `*arg1` doesn't support the `++`
+operator, or if the type of `++(*arg1)` isn't compatible with the mock
+function's return type.
+
+Another example:
+```
+ACTION(Foo) {
+  (*arg2)(5);
+  Blah();
+  *arg1 = 0;
+  return arg0;
+}
+```
+defines an action `Foo()` that invokes argument #2 (a function pointer)
+with 5, calls function `Blah()`, sets the value pointed to by argument
+#1 to 0, and returns argument #0.
+
+For more convenience and flexibility, you can also use the following
+pre-defined symbols in the body of `ACTION`:
+
+| `argK_type` | The type of the K-th (0-based) argument of the mock function |
+|:------------|:-------------------------------------------------------------|
+| `args`      | All arguments of the mock function as a tuple                |
+| `args_type` | The type of all arguments of the mock function as a tuple    |
+| `return_type` | The return type of the mock function                         |
+| `function_type` | The type of the mock function                                |
+
+For example, when using an `ACTION` as a stub action for mock function:
+```
+int DoSomething(bool flag, int* ptr);
+```
+we have:
+| **Pre-defined Symbol** | **Is Bound To** |
+|:-----------------------|:----------------|
+| `arg0`                 | the value of `flag` |
+| `arg0_type`            | the type `bool` |
+| `arg1`                 | the value of `ptr` |
+| `arg1_type`            | the type `int*` |
+| `args`                 | the tuple `(flag, ptr)` |
+| `args_type`            | the type `std::tr1::tuple<bool, int*>` |
+| `return_type`          | the type `int`  |
+| `function_type`        | the type `int(bool, int*)` |
+
+## Writing New Parameterized Actions Quickly ##
+
+Sometimes you'll want to parameterize an action you define.  For that
+we have another macro
+```
+ACTION_P(name, param) { statements; }
+```
+
+For example,
+```
+ACTION_P(Add, n) { return arg0 + n; }
+```
+will allow you to write
+```
+// Returns argument #0 + 5.
+... WillOnce(Add(5));
+```
+
+For convenience, we use the term _arguments_ for the values used to
+invoke the mock function, and the term _parameters_ for the values
+used to instantiate an action.
+
+Note that you don't need to provide the type of the parameter either.
+Suppose the parameter is named `param`, you can also use the
+Google-Mock-defined symbol `param_type` to refer to the type of the
+parameter as inferred by the compiler.  For example, in the body of
+`ACTION_P(Add, n)` above, you can write `n_type` for the type of `n`.
+
+Google Mock also provides `ACTION_P2`, `ACTION_P3`, and etc to support
+multi-parameter actions.  For example,
+```
+ACTION_P2(ReturnDistanceTo, x, y) {
+  double dx = arg0 - x;
+  double dy = arg1 - y;
+  return sqrt(dx*dx + dy*dy);
+}
+```
+lets you write
+```
+... WillOnce(ReturnDistanceTo(5.0, 26.5));
+```
+
+You can view `ACTION` as a degenerated parameterized action where the
+number of parameters is 0.
+
+You can also easily define actions overloaded on the number of parameters:
+```
+ACTION_P(Plus, a) { ... }
+ACTION_P2(Plus, a, b) { ... }
+```
+
+## Restricting the Type of an Argument or Parameter in an ACTION ##
+
+For maximum brevity and reusability, the `ACTION*` macros don't ask
+you to provide the types of the mock function arguments and the action
+parameters.  Instead, we let the compiler infer the types for us.
+
+Sometimes, however, we may want to be more explicit about the types.
+There are several tricks to do that.  For example:
+```
+ACTION(Foo) {
+  // Makes sure arg0 can be converted to int.
+  int n = arg0;
+  ... use n instead of arg0 here ...
+}
+
+ACTION_P(Bar, param) {
+  // Makes sure the type of arg1 is const char*.
+  ::testing::StaticAssertTypeEq<const char*, arg1_type>();
+
+  // Makes sure param can be converted to bool.
+  bool flag = param;
+}
+```
+where `StaticAssertTypeEq` is a compile-time assertion in Google Test
+that verifies two types are the same.
+
+## Writing New Action Templates Quickly ##
+
+Sometimes you want to give an action explicit template parameters that
+cannot be inferred from its value parameters.  `ACTION_TEMPLATE()`
+supports that and can be viewed as an extension to `ACTION()` and
+`ACTION_P*()`.
+
+The syntax:
+```
+ACTION_TEMPLATE(ActionName,
+                HAS_m_TEMPLATE_PARAMS(kind1, name1, ..., kind_m, name_m),
+                AND_n_VALUE_PARAMS(p1, ..., p_n)) { statements; }
+```
+
+defines an action template that takes _m_ explicit template parameters
+and _n_ value parameters, where _m_ is between 1 and 10, and _n_ is
+between 0 and 10.  `name_i` is the name of the i-th template
+parameter, and `kind_i` specifies whether it's a `typename`, an
+integral constant, or a template.  `p_i` is the name of the i-th value
+parameter.
+
+Example:
+```
+// DuplicateArg<k, T>(output) converts the k-th argument of the mock
+// function to type T and copies it to *output.
+ACTION_TEMPLATE(DuplicateArg,
+                // Note the comma between int and k:
+                HAS_2_TEMPLATE_PARAMS(int, k, typename, T),
+                AND_1_VALUE_PARAMS(output)) {
+  *output = T(std::tr1::get<k>(args));
+}
+```
+
+To create an instance of an action template, write:
+```
+  ActionName<t1, ..., t_m>(v1, ..., v_n)
+```
+where the `t`s are the template arguments and the
+`v`s are the value arguments.  The value argument
+types are inferred by the compiler.  For example:
+```
+using ::testing::_;
+...
+  int n;
+  EXPECT_CALL(mock, Foo(_, _))
+      .WillOnce(DuplicateArg<1, unsigned char>(&n));
+```
+
+If you want to explicitly specify the value argument types, you can
+provide additional template arguments:
+```
+  ActionName<t1, ..., t_m, u1, ..., u_k>(v1, ..., v_n)
+```
+where `u_i` is the desired type of `v_i`.
+
+`ACTION_TEMPLATE` and `ACTION`/`ACTION_P*` can be overloaded on the
+number of value parameters, but not on the number of template
+parameters.  Without the restriction, the meaning of the following is
+unclear:
+
+```
+  OverloadedAction<int, bool>(x);
+```
+
+Are we using a single-template-parameter action where `bool` refers to
+the type of `x`, or a two-template-parameter action where the compiler
+is asked to infer the type of `x`?
+
+## Using the ACTION Object's Type ##
+
+If you are writing a function that returns an `ACTION` object, you'll
+need to know its type.  The type depends on the macro used to define
+the action and the parameter types.  The rule is relatively simple:
+| **Given Definition** | **Expression** | **Has Type** |
+|:---------------------|:---------------|:-------------|
+| `ACTION(Foo)`        | `Foo()`        | `FooAction`  |
+| `ACTION_TEMPLATE(Foo, HAS_m_TEMPLATE_PARAMS(...), AND_0_VALUE_PARAMS())` |	`Foo<t1, ..., t_m>()` | `FooAction<t1, ..., t_m>` |
+| `ACTION_P(Bar, param)` | `Bar(int_value)` | `BarActionP<int>` |
+| `ACTION_TEMPLATE(Bar, HAS_m_TEMPLATE_PARAMS(...), AND_1_VALUE_PARAMS(p1))` | `Bar<t1, ..., t_m>(int_value)` | `FooActionP<t1, ..., t_m, int>` |
+| `ACTION_P2(Baz, p1, p2)` | `Baz(bool_value, int_value)` | `BazActionP2<bool, int>` |
+| `ACTION_TEMPLATE(Baz, HAS_m_TEMPLATE_PARAMS(...), AND_2_VALUE_PARAMS(p1, p2))` | `Baz<t1, ..., t_m>(bool_value, int_value)` | `FooActionP2<t1, ..., t_m, bool, int>` |
+| ...                  | ...            | ...          |
+
+Note that we have to pick different suffixes (`Action`, `ActionP`,
+`ActionP2`, and etc) for actions with different numbers of value
+parameters, or the action definitions cannot be overloaded on the
+number of them.
+
+## Writing New Monomorphic Actions ##
+
+While the `ACTION*` macros are very convenient, sometimes they are
+inappropriate.  For example, despite the tricks shown in the previous
+recipes, they don't let you directly specify the types of the mock
+function arguments and the action parameters, which in general leads
+to unoptimized compiler error messages that can baffle unfamiliar
+users.  They also don't allow overloading actions based on parameter
+types without jumping through some hoops.
+
+An alternative to the `ACTION*` macros is to implement
+`::testing::ActionInterface<F>`, where `F` is the type of the mock
+function in which the action will be used. For example:
+
+```
+template <typename F>class ActionInterface {
+ public:
+  virtual ~ActionInterface();
+
+  // Performs the action.  Result is the return type of function type
+  // F, and ArgumentTuple is the tuple of arguments of F.
+  //
+  // For example, if F is int(bool, const string&), then Result would
+  // be int, and ArgumentTuple would be tr1::tuple<bool, const string&>.
+  virtual Result Perform(const ArgumentTuple& args) = 0;
+};
+
+using ::testing::_;
+using ::testing::Action;
+using ::testing::ActionInterface;
+using ::testing::MakeAction;
+
+typedef int IncrementMethod(int*);
+
+class IncrementArgumentAction : public ActionInterface<IncrementMethod> {
+ public:
+  virtual int Perform(const tr1::tuple<int*>& args) {
+    int* p = tr1::get<0>(args);  // Grabs the first argument.
+    return *p++;
+  }
+};
+
+Action<IncrementMethod> IncrementArgument() {
+  return MakeAction(new IncrementArgumentAction);
+}
+...
+
+  EXPECT_CALL(foo, Baz(_))
+      .WillOnce(IncrementArgument());
+
+  int n = 5;
+  foo.Baz(&n);  // Should return 5 and change n to 6.
+```
+
+## Writing New Polymorphic Actions ##
+
+The previous recipe showed you how to define your own action. This is
+all good, except that you need to know the type of the function in
+which the action will be used. Sometimes that can be a problem. For
+example, if you want to use the action in functions with _different_
+types (e.g. like `Return()` and `SetArgPointee()`).
+
+If an action can be used in several types of mock functions, we say
+it's _polymorphic_. The `MakePolymorphicAction()` function template
+makes it easy to define such an action:
+
+```
+namespace testing {
+
+template <typename Impl>
+PolymorphicAction<Impl> MakePolymorphicAction(const Impl& impl);
+
+}  // namespace testing
+```
+
+As an example, let's define an action that returns the second argument
+in the mock function's argument list. The first step is to define an
+implementation class:
+
+```
+class ReturnSecondArgumentAction {
+ public:
+  template <typename Result, typename ArgumentTuple>
+  Result Perform(const ArgumentTuple& args) const {
+    // To get the i-th (0-based) argument, use tr1::get<i>(args).
+    return tr1::get<1>(args);
+  }
+};
+```
+
+This implementation class does _not_ need to inherit from any
+particular class. What matters is that it must have a `Perform()`
+method template. This method template takes the mock function's
+arguments as a tuple in a **single** argument, and returns the result of
+the action. It can be either `const` or not, but must be invokable
+with exactly one template argument, which is the result type. In other
+words, you must be able to call `Perform<R>(args)` where `R` is the
+mock function's return type and `args` is its arguments in a tuple.
+
+Next, we use `MakePolymorphicAction()` to turn an instance of the
+implementation class into the polymorphic action we need. It will be
+convenient to have a wrapper for this:
+
+```
+using ::testing::MakePolymorphicAction;
+using ::testing::PolymorphicAction;
+
+PolymorphicAction<ReturnSecondArgumentAction> ReturnSecondArgument() {
+  return MakePolymorphicAction(ReturnSecondArgumentAction());
+}
+```
+
+Now, you can use this polymorphic action the same way you use the
+built-in ones:
+
+```
+using ::testing::_;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD2(DoThis, int(bool flag, int n));
+  MOCK_METHOD3(DoThat, string(int x, const char* str1, const char* str2));
+};
+...
+
+  MockFoo foo;
+  EXPECT_CALL(foo, DoThis(_, _))
+      .WillOnce(ReturnSecondArgument());
+  EXPECT_CALL(foo, DoThat(_, _, _))
+      .WillOnce(ReturnSecondArgument());
+  ...
+  foo.DoThis(true, 5);         // Will return 5.
+  foo.DoThat(1, "Hi", "Bye");  // Will return "Hi".
+```
+
+## Teaching Google Mock How to Print Your Values ##
+
+When an uninteresting or unexpected call occurs, Google Mock prints the
+argument values and the stack trace to help you debug.  Assertion
+macros like `EXPECT_THAT` and `EXPECT_EQ` also print the values in
+question when the assertion fails.  Google Mock and Google Test do this using
+Google Test's user-extensible value printer.
+
+This printer knows how to print built-in C++ types, native arrays, STL
+containers, and any type that supports the `<<` operator.  For other
+types, it prints the raw bytes in the value and hopes that you the
+user can figure it out.
+[Google Test's advanced guide](http://code.google.com/p/googletest/wiki/V1_6_AdvancedGuide#Teaching_Google_Test_How_to_Print_Your_Values)
+explains how to extend the printer to do a better job at
+printing your particular type than to dump the bytes.
\ No newline at end of file
diff --git a/third_party/googletest/googlemock/docs/v1_6/Documentation.md b/third_party/googletest/googlemock/docs/v1_6/Documentation.md
new file mode 100644
index 0000000..dcc9156
--- /dev/null
+++ b/third_party/googletest/googlemock/docs/v1_6/Documentation.md
@@ -0,0 +1,12 @@
+This page lists all documentation wiki pages for Google Mock **1.6**
+- **if you use a released version of Google Mock, please read the documentation for that specific version instead.**
+
+  * [ForDummies](V1_6_ForDummies.md) -- start here if you are new to Google Mock.
+  * [CheatSheet](V1_6_CheatSheet.md) -- a quick reference.
+  * [CookBook](V1_6_CookBook.md) -- recipes for doing various tasks using Google Mock.
+  * [FrequentlyAskedQuestions](V1_6_FrequentlyAskedQuestions.md) -- check here before asking a question on the mailing list.
+
+To contribute code to Google Mock, read:
+
+  * [DevGuide](DevGuide.md) -- read this _before_ writing your first patch.
+  * [Pump Manual](http://code.google.com/p/googletest/wiki/V1_6_PumpManual) -- how we generate some of Google Mock's source files.
\ No newline at end of file
diff --git a/third_party/googletest/googlemock/docs/v1_6/ForDummies.md b/third_party/googletest/googlemock/docs/v1_6/ForDummies.md
new file mode 100644
index 0000000..0891b8c
--- /dev/null
+++ b/third_party/googletest/googlemock/docs/v1_6/ForDummies.md
@@ -0,0 +1,439 @@
+
+
+(**Note:** If you get compiler errors that you don't understand, be sure to consult [Google Mock Doctor](http://code.google.com/p/googlemock/wiki/V1_6_FrequentlyAskedQuestions#How_am_I_supposed_to_make_sense_of_these_horrible_template_error).)
+
+# What Is Google C++ Mocking Framework? #
+When you write a prototype or test, often it's not feasible or wise to rely on real objects entirely. A **mock object** implements the same interface as a real object (so it can be used as one), but lets you specify at run time how it will be used and what it should do (which methods will be called? in which order? how many times? with what arguments? what will they return? etc).
+
+**Note:** It is easy to confuse the term _fake objects_ with mock objects. Fakes and mocks actually mean very different things in the Test-Driven Development (TDD) community:
+
+  * **Fake** objects have working implementations, but usually take some shortcut (perhaps to make the operations less expensive), which makes them not suitable for production. An in-memory file system would be an example of a fake.
+  * **Mocks** are objects pre-programmed with _expectations_, which form a specification of the calls they are expected to receive.
+
+If all this seems too abstract for you, don't worry - the most important thing to remember is that a mock allows you to check the _interaction_ between itself and code that uses it. The difference between fakes and mocks will become much clearer once you start to use mocks.
+
+**Google C++ Mocking Framework** (or **Google Mock** for short) is a library (sometimes we also call it a "framework" to make it sound cool) for creating mock classes and using them. It does to C++ what [jMock](http://www.jmock.org/) and [EasyMock](http://www.easymock.org/) do to Java.
+
+Using Google Mock involves three basic steps:
+
+  1. Use some simple macros to describe the interface you want to mock, and they will expand to the implementation of your mock class;
+  1. Create some mock objects and specify its expectations and behavior using an intuitive syntax;
+  1. Exercise code that uses the mock objects. Google Mock will catch any violation of the expectations as soon as it arises.
+
+# Why Google Mock? #
+While mock objects help you remove unnecessary dependencies in tests and make them fast and reliable, using mocks manually in C++ is _hard_:
+
+  * Someone has to implement the mocks. The job is usually tedious and error-prone. No wonder people go great distance to avoid it.
+  * The quality of those manually written mocks is a bit, uh, unpredictable. You may see some really polished ones, but you may also see some that were hacked up in a hurry and have all sorts of ad hoc restrictions.
+  * The knowledge you gained from using one mock doesn't transfer to the next.
+
+In contrast, Java and Python programmers have some fine mock frameworks, which automate the creation of mocks. As a result, mocking is a proven effective technique and widely adopted practice in those communities. Having the right tool absolutely makes the difference.
+
+Google Mock was built to help C++ programmers. It was inspired by [jMock](http://www.jmock.org/) and [EasyMock](http://www.easymock.org/), but designed with C++'s specifics in mind. It is your friend if any of the following problems is bothering you:
+
+  * You are stuck with a sub-optimal design and wish you had done more prototyping before it was too late, but prototyping in C++ is by no means "rapid".
+  * Your tests are slow as they depend on too many libraries or use expensive resources (e.g. a database).
+  * Your tests are brittle as some resources they use are unreliable (e.g. the network).
+  * You want to test how your code handles a failure (e.g. a file checksum error), but it's not easy to cause one.
+  * You need to make sure that your module interacts with other modules in the right way, but it's hard to observe the interaction; therefore you resort to observing the side effects at the end of the action, which is awkward at best.
+  * You want to "mock out" your dependencies, except that they don't have mock implementations yet; and, frankly, you aren't thrilled by some of those hand-written mocks.
+
+We encourage you to use Google Mock as:
+
+  * a _design_ tool, for it lets you experiment with your interface design early and often. More iterations lead to better designs!
+  * a _testing_ tool to cut your tests' outbound dependencies and probe the interaction between your module and its collaborators.
+
+# Getting Started #
+Using Google Mock is easy! Inside your C++ source file, just #include `"gtest/gtest.h"` and `"gmock/gmock.h"`, and you are ready to go.
+
+# A Case for Mock Turtles #
+Let's look at an example. Suppose you are developing a graphics program that relies on a LOGO-like API for drawing. How would you test that it does the right thing? Well, you can run it and compare the screen with a golden screen snapshot, but let's admit it: tests like this are expensive to run and fragile (What if you just upgraded to a shiny new graphics card that has better anti-aliasing? Suddenly you have to update all your golden images.). It would be too painful if all your tests are like this. Fortunately, you learned about Dependency Injection and know the right thing to do: instead of having your application talk to the drawing API directly, wrap the API in an interface (say, `Turtle`) and code to that interface:
+
+```
+class Turtle {
+  ...
+  virtual ~Turtle() {}
+  virtual void PenUp() = 0;
+  virtual void PenDown() = 0;
+  virtual void Forward(int distance) = 0;
+  virtual void Turn(int degrees) = 0;
+  virtual void GoTo(int x, int y) = 0;
+  virtual int GetX() const = 0;
+  virtual int GetY() const = 0;
+};
+```
+
+(Note that the destructor of `Turtle` **must** be virtual, as is the case for **all** classes you intend to inherit from - otherwise the destructor of the derived class will not be called when you delete an object through a base pointer, and you'll get corrupted program states like memory leaks.)
+
+You can control whether the turtle's movement will leave a trace using `PenUp()` and `PenDown()`, and control its movement using `Forward()`, `Turn()`, and `GoTo()`. Finally, `GetX()` and `GetY()` tell you the current position of the turtle.
+
+Your program will normally use a real implementation of this interface. In tests, you can use a mock implementation instead. This allows you to easily check what drawing primitives your program is calling, with what arguments, and in which order. Tests written this way are much more robust (they won't break because your new machine does anti-aliasing differently), easier to read and maintain (the intent of a test is expressed in the code, not in some binary images), and run _much, much faster_.
+
+# Writing the Mock Class #
+If you are lucky, the mocks you need to use have already been implemented by some nice people. If, however, you find yourself in the position to write a mock class, relax - Google Mock turns this task into a fun game! (Well, almost.)
+
+## How to Define It ##
+Using the `Turtle` interface as example, here are the simple steps you need to follow:
+
+  1. Derive a class `MockTurtle` from `Turtle`.
+  1. Take a _virtual_ function of `Turtle` (while it's possible to [mock non-virtual methods using templates](http://code.google.com/p/googlemock/wiki/V1_6_CookBook#Mocking_Nonvirtual_Methods), it's much more involved). Count how many arguments it has.
+  1. In the `public:` section of the child class, write `MOCK_METHODn();` (or `MOCK_CONST_METHODn();` if you are mocking a `const` method), where `n` is the number of the arguments; if you counted wrong, shame on you, and a compiler error will tell you so.
+  1. Now comes the fun part: you take the function signature, cut-and-paste the _function name_ as the _first_ argument to the macro, and leave what's left as the _second_ argument (in case you're curious, this is the _type of the function_).
+  1. Repeat until all virtual functions you want to mock are done.
+
+After the process, you should have something like:
+
+```
+#include "gmock/gmock.h"  // Brings in Google Mock.
+class MockTurtle : public Turtle {
+ public:
+  ...
+  MOCK_METHOD0(PenUp, void());
+  MOCK_METHOD0(PenDown, void());
+  MOCK_METHOD1(Forward, void(int distance));
+  MOCK_METHOD1(Turn, void(int degrees));
+  MOCK_METHOD2(GoTo, void(int x, int y));
+  MOCK_CONST_METHOD0(GetX, int());
+  MOCK_CONST_METHOD0(GetY, int());
+};
+```
+
+You don't need to define these mock methods somewhere else - the `MOCK_METHOD*` macros will generate the definitions for you. It's that simple! Once you get the hang of it, you can pump out mock classes faster than your source-control system can handle your check-ins.
+
+**Tip:** If even this is too much work for you, you'll find the
+`gmock_gen.py` tool in Google Mock's `scripts/generator/` directory (courtesy of the [cppclean](http://code.google.com/p/cppclean/) project) useful.  This command-line
+tool requires that you have Python 2.4 installed.  You give it a C++ file and the name of an abstract class defined in it,
+and it will print the definition of the mock class for you.  Due to the
+complexity of the C++ language, this script may not always work, but
+it can be quite handy when it does.  For more details, read the [user documentation](http://code.google.com/p/googlemock/source/browse/trunk/scripts/generator/README).
+
+## Where to Put It ##
+When you define a mock class, you need to decide where to put its definition. Some people put it in a `*_test.cc`. This is fine when the interface being mocked (say, `Foo`) is owned by the same person or team. Otherwise, when the owner of `Foo` changes it, your test could break. (You can't really expect `Foo`'s maintainer to fix every test that uses `Foo`, can you?)
+
+So, the rule of thumb is: if you need to mock `Foo` and it's owned by others, define the mock class in `Foo`'s package (better, in a `testing` sub-package such that you can clearly separate production code and testing utilities), and put it in a `mock_foo.h`. Then everyone can reference `mock_foo.h` from their tests. If `Foo` ever changes, there is only one copy of `MockFoo` to change, and only tests that depend on the changed methods need to be fixed.
+
+Another way to do it: you can introduce a thin layer `FooAdaptor` on top of `Foo` and code to this new interface. Since you own `FooAdaptor`, you can absorb changes in `Foo` much more easily. While this is more work initially, carefully choosing the adaptor interface can make your code easier to write and more readable (a net win in the long run), as you can choose `FooAdaptor` to fit your specific domain much better than `Foo` does.
+
+# Using Mocks in Tests #
+Once you have a mock class, using it is easy. The typical work flow is:
+
+  1. Import the Google Mock names from the `testing` namespace such that you can use them unqualified (You only have to do it once per file. Remember that namespaces are a good idea and good for your health.).
+  1. Create some mock objects.
+  1. Specify your expectations on them (How many times will a method be called? With what arguments? What should it do? etc.).
+  1. Exercise some code that uses the mocks; optionally, check the result using Google Test assertions. If a mock method is called more than expected or with wrong arguments, you'll get an error immediately.
+  1. When a mock is destructed, Google Mock will automatically check whether all expectations on it have been satisfied.
+
+Here's an example:
+
+```
+#include "path/to/mock-turtle.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+using ::testing::AtLeast;                     // #1
+
+TEST(PainterTest, CanDrawSomething) {
+  MockTurtle turtle;                          // #2
+  EXPECT_CALL(turtle, PenDown())              // #3
+      .Times(AtLeast(1));
+
+  Painter painter(&turtle);                   // #4
+
+  EXPECT_TRUE(painter.DrawCircle(0, 0, 10));
+}                                             // #5
+
+int main(int argc, char** argv) {
+  // The following line must be executed to initialize Google Mock
+  // (and Google Test) before running the tests.
+  ::testing::InitGoogleMock(&argc, argv);
+  return RUN_ALL_TESTS();
+}
+```
+
+As you might have guessed, this test checks that `PenDown()` is called at least once. If the `painter` object didn't call this method, your test will fail with a message like this:
+
+```
+path/to/my_test.cc:119: Failure
+Actual function call count doesn't match this expectation:
+Actually: never called;
+Expected: called at least once.
+```
+
+**Tip 1:** If you run the test from an Emacs buffer, you can hit `<Enter>` on the line number displayed in the error message to jump right to the failed expectation.
+
+**Tip 2:** If your mock objects are never deleted, the final verification won't happen. Therefore it's a good idea to use a heap leak checker in your tests when you allocate mocks on the heap.
+
+**Important note:** Google Mock requires expectations to be set **before** the mock functions are called, otherwise the behavior is **undefined**. In particular, you mustn't interleave `EXPECT_CALL()`s and calls to the mock functions.
+
+This means `EXPECT_CALL()` should be read as expecting that a call will occur _in the future_, not that a call has occurred. Why does Google Mock work like that? Well, specifying the expectation beforehand allows Google Mock to report a violation as soon as it arises, when the context (stack trace, etc) is still available. This makes debugging much easier.
+
+Admittedly, this test is contrived and doesn't do much. You can easily achieve the same effect without using Google Mock. However, as we shall reveal soon, Google Mock allows you to do _much more_ with the mocks.
+
+## Using Google Mock with Any Testing Framework ##
+If you want to use something other than Google Test (e.g. [CppUnit](http://apps.sourceforge.net/mediawiki/cppunit/index.php?title=Main_Page) or
+[CxxTest](http://cxxtest.tigris.org/)) as your testing framework, just change the `main()` function in the previous section to:
+```
+int main(int argc, char** argv) {
+  // The following line causes Google Mock to throw an exception on failure,
+  // which will be interpreted by your testing framework as a test failure.
+  ::testing::GTEST_FLAG(throw_on_failure) = true;
+  ::testing::InitGoogleMock(&argc, argv);
+  ... whatever your testing framework requires ...
+}
+```
+
+This approach has a catch: it makes Google Mock throw an exception
+from a mock object's destructor sometimes.  With some compilers, this
+sometimes causes the test program to crash.  You'll still be able to
+notice that the test has failed, but it's not a graceful failure.
+
+A better solution is to use Google Test's
+[event listener API](http://code.google.com/p/googletest/wiki/V1_6_AdvancedGuide#Extending_Google_Test_by_Handling_Test_Events)
+to report a test failure to your testing framework properly.  You'll need to
+implement the `OnTestPartResult()` method of the event listener interface, but it
+should be straightforward.
+
+If this turns out to be too much work, we suggest that you stick with
+Google Test, which works with Google Mock seamlessly (in fact, it is
+technically part of Google Mock.).  If there is a reason that you
+cannot use Google Test, please let us know.
+
+# Setting Expectations #
+The key to using a mock object successfully is to set the _right expectations_ on it. If you set the expectations too strict, your test will fail as the result of unrelated changes. If you set them too loose, bugs can slip through. You want to do it just right such that your test can catch exactly the kind of bugs you intend it to catch. Google Mock provides the necessary means for you to do it "just right."
+
+## General Syntax ##
+In Google Mock we use the `EXPECT_CALL()` macro to set an expectation on a mock method. The general syntax is:
+
+```
+EXPECT_CALL(mock_object, method(matchers))
+    .Times(cardinality)
+    .WillOnce(action)
+    .WillRepeatedly(action);
+```
+
+The macro has two arguments: first the mock object, and then the method and its arguments. Note that the two are separated by a comma (`,`), not a period (`.`). (Why using a comma? The answer is that it was necessary for technical reasons.)
+
+The macro can be followed by some optional _clauses_ that provide more information about the expectation. We'll discuss how each clause works in the coming sections.
+
+This syntax is designed to make an expectation read like English. For example, you can probably guess that
+
+```
+using ::testing::Return;...
+EXPECT_CALL(turtle, GetX())
+    .Times(5)
+    .WillOnce(Return(100))
+    .WillOnce(Return(150))
+    .WillRepeatedly(Return(200));
+```
+
+says that the `turtle` object's `GetX()` method will be called five times, it will return 100 the first time, 150 the second time, and then 200 every time. Some people like to call this style of syntax a Domain-Specific Language (DSL).
+
+**Note:** Why do we use a macro to do this? It serves two purposes: first it makes expectations easily identifiable (either by `grep` or by a human reader), and second it allows Google Mock to include the source file location of a failed expectation in messages, making debugging easier.
+
+## Matchers: What Arguments Do We Expect? ##
+When a mock function takes arguments, we must specify what arguments we are expecting; for example:
+
+```
+// Expects the turtle to move forward by 100 units.
+EXPECT_CALL(turtle, Forward(100));
+```
+
+Sometimes you may not want to be too specific (Remember that talk about tests being too rigid? Over specification leads to brittle tests and obscures the intent of tests. Therefore we encourage you to specify only what's necessary - no more, no less.). If you care to check that `Forward()` will be called but aren't interested in its actual argument, write `_` as the argument, which means "anything goes":
+
+```
+using ::testing::_;
+...
+// Expects the turtle to move forward.
+EXPECT_CALL(turtle, Forward(_));
+```
+
+`_` is an instance of what we call **matchers**. A matcher is like a predicate and can test whether an argument is what we'd expect. You can use a matcher inside `EXPECT_CALL()` wherever a function argument is expected.
+
+A list of built-in matchers can be found in the [CheatSheet](V1_6_CheatSheet.md). For example, here's the `Ge` (greater than or equal) matcher:
+
+```
+using ::testing::Ge;...
+EXPECT_CALL(turtle, Forward(Ge(100)));
+```
+
+This checks that the turtle will be told to go forward by at least 100 units.
+
+## Cardinalities: How Many Times Will It Be Called? ##
+The first clause we can specify following an `EXPECT_CALL()` is `Times()`. We call its argument a **cardinality** as it tells _how many times_ the call should occur. It allows us to repeat an expectation many times without actually writing it as many times. More importantly, a cardinality can be "fuzzy", just like a matcher can be. This allows a user to express the intent of a test exactly.
+
+An interesting special case is when we say `Times(0)`. You may have guessed - it means that the function shouldn't be called with the given arguments at all, and Google Mock will report a Google Test failure whenever the function is (wrongfully) called.
+
+We've seen `AtLeast(n)` as an example of fuzzy cardinalities earlier. For the list of built-in cardinalities you can use, see the [CheatSheet](V1_6_CheatSheet.md).
+
+The `Times()` clause can be omitted. **If you omit `Times()`, Google Mock will infer the cardinality for you.** The rules are easy to remember:
+
+  * If **neither** `WillOnce()` **nor** `WillRepeatedly()` is in the `EXPECT_CALL()`, the inferred cardinality is `Times(1)`.
+  * If there are `n WillOnce()`'s but **no** `WillRepeatedly()`, where `n` >= 1, the cardinality is `Times(n)`.
+  * If there are `n WillOnce()`'s and **one** `WillRepeatedly()`, where `n` >= 0, the cardinality is `Times(AtLeast(n))`.
+
+**Quick quiz:** what do you think will happen if a function is expected to be called twice but actually called four times?
+
+## Actions: What Should It Do? ##
+Remember that a mock object doesn't really have a working implementation? We as users have to tell it what to do when a method is invoked. This is easy in Google Mock.
+
+First, if the return type of a mock function is a built-in type or a pointer, the function has a **default action** (a `void` function will just return, a `bool` function will return `false`, and other functions will return 0). If you don't say anything, this behavior will be used.
+
+Second, if a mock function doesn't have a default action, or the default action doesn't suit you, you can specify the action to be taken each time the expectation matches using a series of `WillOnce()` clauses followed by an optional `WillRepeatedly()`. For example,
+
+```
+using ::testing::Return;...
+EXPECT_CALL(turtle, GetX())
+    .WillOnce(Return(100))
+    .WillOnce(Return(200))
+    .WillOnce(Return(300));
+```
+
+This says that `turtle.GetX()` will be called _exactly three times_ (Google Mock inferred this from how many `WillOnce()` clauses we've written, since we didn't explicitly write `Times()`), and will return 100, 200, and 300 respectively.
+
+```
+using ::testing::Return;...
+EXPECT_CALL(turtle, GetY())
+    .WillOnce(Return(100))
+    .WillOnce(Return(200))
+    .WillRepeatedly(Return(300));
+```
+
+says that `turtle.GetY()` will be called _at least twice_ (Google Mock knows this as we've written two `WillOnce()` clauses and a `WillRepeatedly()` while having no explicit `Times()`), will return 100 the first time, 200 the second time, and 300 from the third time on.
+
+Of course, if you explicitly write a `Times()`, Google Mock will not try to infer the cardinality itself. What if the number you specified is larger than there are `WillOnce()` clauses? Well, after all `WillOnce()`s are used up, Google Mock will do the _default_ action for the function every time (unless, of course, you have a `WillRepeatedly()`.).
+
+What can we do inside `WillOnce()` besides `Return()`? You can return a reference using `ReturnRef(variable)`, or invoke a pre-defined function, among [others](http://code.google.com/p/googlemock/wiki/V1_6_CheatSheet#Actions).
+
+**Important note:** The `EXPECT_CALL()` statement evaluates the action clause only once, even though the action may be performed many times. Therefore you must be careful about side effects. The following may not do what you want:
+
+```
+int n = 100;
+EXPECT_CALL(turtle, GetX())
+.Times(4)
+.WillRepeatedly(Return(n++));
+```
+
+Instead of returning 100, 101, 102, ..., consecutively, this mock function will always return 100 as `n++` is only evaluated once. Similarly, `Return(new Foo)` will create a new `Foo` object when the `EXPECT_CALL()` is executed, and will return the same pointer every time. If you want the side effect to happen every time, you need to define a custom action, which we'll teach in the [CookBook](V1_6_CookBook.md).
+
+Time for another quiz! What do you think the following means?
+
+```
+using ::testing::Return;...
+EXPECT_CALL(turtle, GetY())
+.Times(4)
+.WillOnce(Return(100));
+```
+
+Obviously `turtle.GetY()` is expected to be called four times. But if you think it will return 100 every time, think twice! Remember that one `WillOnce()` clause will be consumed each time the function is invoked and the default action will be taken afterwards. So the right answer is that `turtle.GetY()` will return 100 the first time, but **return 0 from the second time on**, as returning 0 is the default action for `int` functions.
+
+## Using Multiple Expectations ##
+So far we've only shown examples where you have a single expectation. More realistically, you're going to specify expectations on multiple mock methods, which may be from multiple mock objects.
+
+By default, when a mock method is invoked, Google Mock will search the expectations in the **reverse order** they are defined, and stop when an active expectation that matches the arguments is found (you can think of it as "newer rules override older ones."). If the matching expectation cannot take any more calls, you will get an upper-bound-violated failure. Here's an example:
+
+```
+using ::testing::_;...
+EXPECT_CALL(turtle, Forward(_));  // #1
+EXPECT_CALL(turtle, Forward(10))  // #2
+    .Times(2);
+```
+
+If `Forward(10)` is called three times in a row, the third time it will be an error, as the last matching expectation (#2) has been saturated. If, however, the third `Forward(10)` call is replaced by `Forward(20)`, then it would be OK, as now #1 will be the matching expectation.
+
+**Side note:** Why does Google Mock search for a match in the _reverse_ order of the expectations? The reason is that this allows a user to set up the default expectations in a mock object's constructor or the test fixture's set-up phase and then customize the mock by writing more specific expectations in the test body. So, if you have two expectations on the same method, you want to put the one with more specific matchers **after** the other, or the more specific rule would be shadowed by the more general one that comes after it.
+
+## Ordered vs Unordered Calls ##
+By default, an expectation can match a call even though an earlier expectation hasn't been satisfied. In other words, the calls don't have to occur in the order the expectations are specified.
+
+Sometimes, you may want all the expected calls to occur in a strict order. To say this in Google Mock is easy:
+
+```
+using ::testing::InSequence;...
+TEST(FooTest, DrawsLineSegment) {
+  ...
+  {
+    InSequence dummy;
+
+    EXPECT_CALL(turtle, PenDown());
+    EXPECT_CALL(turtle, Forward(100));
+    EXPECT_CALL(turtle, PenUp());
+  }
+  Foo();
+}
+```
+
+By creating an object of type `InSequence`, all expectations in its scope are put into a _sequence_ and have to occur _sequentially_. Since we are just relying on the constructor and destructor of this object to do the actual work, its name is really irrelevant.
+
+In this example, we test that `Foo()` calls the three expected functions in the order as written. If a call is made out-of-order, it will be an error.
+
+(What if you care about the relative order of some of the calls, but not all of them? Can you specify an arbitrary partial order? The answer is ... yes! If you are impatient, the details can be found in the [CookBook](V1_6_CookBook.md).)
+
+## All Expectations Are Sticky (Unless Said Otherwise) ##
+Now let's do a quick quiz to see how well you can use this mock stuff already. How would you test that the turtle is asked to go to the origin _exactly twice_ (you want to ignore any other instructions it receives)?
+
+After you've come up with your answer, take a look at ours and compare notes (solve it yourself first - don't cheat!):
+
+```
+using ::testing::_;...
+EXPECT_CALL(turtle, GoTo(_, _))  // #1
+    .Times(AnyNumber());
+EXPECT_CALL(turtle, GoTo(0, 0))  // #2
+    .Times(2);
+```
+
+Suppose `turtle.GoTo(0, 0)` is called three times. In the third time, Google Mock will see that the arguments match expectation #2 (remember that we always pick the last matching expectation). Now, since we said that there should be only two such calls, Google Mock will report an error immediately. This is basically what we've told you in the "Using Multiple Expectations" section above.
+
+This example shows that **expectations in Google Mock are "sticky" by default**, in the sense that they remain active even after we have reached their invocation upper bounds. This is an important rule to remember, as it affects the meaning of the spec, and is **different** to how it's done in many other mocking frameworks (Why'd we do that? Because we think our rule makes the common cases easier to express and understand.).
+
+Simple? Let's see if you've really understood it: what does the following code say?
+
+```
+using ::testing::Return;
+...
+for (int i = n; i > 0; i--) {
+  EXPECT_CALL(turtle, GetX())
+      .WillOnce(Return(10*i));
+}
+```
+
+If you think it says that `turtle.GetX()` will be called `n` times and will return 10, 20, 30, ..., consecutively, think twice! The problem is that, as we said, expectations are sticky. So, the second time `turtle.GetX()` is called, the last (latest) `EXPECT_CALL()` statement will match, and will immediately lead to an "upper bound exceeded" error - this piece of code is not very useful!
+
+One correct way of saying that `turtle.GetX()` will return 10, 20, 30, ..., is to explicitly say that the expectations are _not_ sticky. In other words, they should _retire_ as soon as they are saturated:
+
+```
+using ::testing::Return;
+...
+for (int i = n; i > 0; i--) {
+  EXPECT_CALL(turtle, GetX())
+    .WillOnce(Return(10*i))
+    .RetiresOnSaturation();
+}
+```
+
+And, there's a better way to do it: in this case, we expect the calls to occur in a specific order, and we line up the actions to match the order. Since the order is important here, we should make it explicit using a sequence:
+
+```
+using ::testing::InSequence;
+using ::testing::Return;
+...
+{
+  InSequence s;
+
+  for (int i = 1; i <= n; i++) {
+    EXPECT_CALL(turtle, GetX())
+        .WillOnce(Return(10*i))
+        .RetiresOnSaturation();
+  }
+}
+```
+
+By the way, the other situation where an expectation may _not_ be sticky is when it's in a sequence - as soon as another expectation that comes after it in the sequence has been used, it automatically retires (and will never be used to match any call).
+
+## Uninteresting Calls ##
+A mock object may have many methods, and not all of them are that interesting. For example, in some tests we may not care about how many times `GetX()` and `GetY()` get called.
+
+In Google Mock, if you are not interested in a method, just don't say anything about it. If a call to this method occurs, you'll see a warning in the test output, but it won't be a failure.
+
+# What Now? #
+Congratulations! You've learned enough about Google Mock to start using it. Now, you might want to join the [googlemock](http://groups.google.com/group/googlemock) discussion group and actually write some tests using Google Mock - it will be fun. Hey, it may even be addictive - you've been warned.
+
+Then, if you feel like increasing your mock quotient, you should move on to the [CookBook](V1_6_CookBook.md). You can learn many advanced features of Google Mock there -- and advance your level of enjoyment and testing bliss.
\ No newline at end of file
diff --git a/third_party/googletest/googlemock/docs/v1_6/FrequentlyAskedQuestions.md b/third_party/googletest/googlemock/docs/v1_6/FrequentlyAskedQuestions.md
new file mode 100644
index 0000000..f74715d
--- /dev/null
+++ b/third_party/googletest/googlemock/docs/v1_6/FrequentlyAskedQuestions.md
@@ -0,0 +1,628 @@
+
+
+Please send your questions to the
+[googlemock](http://groups.google.com/group/googlemock) discussion
+group. If you need help with compiler errors, make sure you have
+tried [Google Mock Doctor](#How_am_I_supposed_to_make_sense_of_these_horrible_template_error.md) first.
+
+## When I call a method on my mock object, the method for the real object is invoked instead.  What's the problem? ##
+
+In order for a method to be mocked, it must be _virtual_, unless you use the [high-perf dependency injection technique](http://code.google.com/p/googlemock/wiki/V1_6_CookBook#Mocking_Nonvirtual_Methods).
+
+## I wrote some matchers.  After I upgraded to a new version of Google Mock, they no longer compile.  What's going on? ##
+
+After version 1.4.0 of Google Mock was released, we had an idea on how
+to make it easier to write matchers that can generate informative
+messages efficiently.  We experimented with this idea and liked what
+we saw.  Therefore we decided to implement it.
+
+Unfortunately, this means that if you have defined your own matchers
+by implementing `MatcherInterface` or using `MakePolymorphicMatcher()`,
+your definitions will no longer compile.  Matchers defined using the
+`MATCHER*` family of macros are not affected.
+
+Sorry for the hassle if your matchers are affected.  We believe it's
+in everyone's long-term interest to make this change sooner than
+later.  Fortunately, it's usually not hard to migrate an existing
+matcher to the new API.  Here's what you need to do:
+
+If you wrote your matcher like this:
+```
+// Old matcher definition that doesn't work with the latest
+// Google Mock.
+using ::testing::MatcherInterface;
+...
+class MyWonderfulMatcher : public MatcherInterface<MyType> {
+ public:
+  ...
+  virtual bool Matches(MyType value) const {
+    // Returns true if value matches.
+    return value.GetFoo() > 5;
+  }
+  ...
+};
+```
+
+you'll need to change it to:
+```
+// New matcher definition that works with the latest Google Mock.
+using ::testing::MatcherInterface;
+using ::testing::MatchResultListener;
+...
+class MyWonderfulMatcher : public MatcherInterface<MyType> {
+ public:
+  ...
+  virtual bool MatchAndExplain(MyType value,
+                               MatchResultListener* listener) const {
+    // Returns true if value matches.
+    return value.GetFoo() > 5;
+  }
+  ...
+};
+```
+(i.e. rename `Matches()` to `MatchAndExplain()` and give it a second
+argument of type `MatchResultListener*`.)
+
+If you were also using `ExplainMatchResultTo()` to improve the matcher
+message:
+```
+// Old matcher definition that doesn't work with the lastest
+// Google Mock.
+using ::testing::MatcherInterface;
+...
+class MyWonderfulMatcher : public MatcherInterface<MyType> {
+ public:
+  ...
+  virtual bool Matches(MyType value) const {
+    // Returns true if value matches.
+    return value.GetFoo() > 5;
+  }
+
+  virtual void ExplainMatchResultTo(MyType value,
+                                    ::std::ostream* os) const {
+    // Prints some helpful information to os to help
+    // a user understand why value matches (or doesn't match).
+    *os << "the Foo property is " << value.GetFoo();
+  }
+  ...
+};
+```
+
+you should move the logic of `ExplainMatchResultTo()` into
+`MatchAndExplain()`, using the `MatchResultListener` argument where
+the `::std::ostream` was used:
+```
+// New matcher definition that works with the latest Google Mock.
+using ::testing::MatcherInterface;
+using ::testing::MatchResultListener;
+...
+class MyWonderfulMatcher : public MatcherInterface<MyType> {
+ public:
+  ...
+  virtual bool MatchAndExplain(MyType value,
+                               MatchResultListener* listener) const {
+    // Returns true if value matches.
+    *listener << "the Foo property is " << value.GetFoo();
+    return value.GetFoo() > 5;
+  }
+  ...
+};
+```
+
+If your matcher is defined using `MakePolymorphicMatcher()`:
+```
+// Old matcher definition that doesn't work with the latest
+// Google Mock.
+using ::testing::MakePolymorphicMatcher;
+...
+class MyGreatMatcher {
+ public:
+  ...
+  bool Matches(MyType value) const {
+    // Returns true if value matches.
+    return value.GetBar() < 42;
+  }
+  ...
+};
+... MakePolymorphicMatcher(MyGreatMatcher()) ...
+```
+
+you should rename the `Matches()` method to `MatchAndExplain()` and
+add a `MatchResultListener*` argument (the same as what you need to do
+for matchers defined by implementing `MatcherInterface`):
+```
+// New matcher definition that works with the latest Google Mock.
+using ::testing::MakePolymorphicMatcher;
+using ::testing::MatchResultListener;
+...
+class MyGreatMatcher {
+ public:
+  ...
+  bool MatchAndExplain(MyType value,
+                       MatchResultListener* listener) const {
+    // Returns true if value matches.
+    return value.GetBar() < 42;
+  }
+  ...
+};
+... MakePolymorphicMatcher(MyGreatMatcher()) ...
+```
+
+If your polymorphic matcher uses `ExplainMatchResultTo()` for better
+failure messages:
+```
+// Old matcher definition that doesn't work with the latest
+// Google Mock.
+using ::testing::MakePolymorphicMatcher;
+...
+class MyGreatMatcher {
+ public:
+  ...
+  bool Matches(MyType value) const {
+    // Returns true if value matches.
+    return value.GetBar() < 42;
+  }
+  ...
+};
+void ExplainMatchResultTo(const MyGreatMatcher& matcher,
+                          MyType value,
+                          ::std::ostream* os) {
+  // Prints some helpful information to os to help
+  // a user understand why value matches (or doesn't match).
+  *os << "the Bar property is " << value.GetBar();
+}
+... MakePolymorphicMatcher(MyGreatMatcher()) ...
+```
+
+you'll need to move the logic inside `ExplainMatchResultTo()` to
+`MatchAndExplain()`:
+```
+// New matcher definition that works with the latest Google Mock.
+using ::testing::MakePolymorphicMatcher;
+using ::testing::MatchResultListener;
+...
+class MyGreatMatcher {
+ public:
+  ...
+  bool MatchAndExplain(MyType value,
+                       MatchResultListener* listener) const {
+    // Returns true if value matches.
+    *listener << "the Bar property is " << value.GetBar();
+    return value.GetBar() < 42;
+  }
+  ...
+};
+... MakePolymorphicMatcher(MyGreatMatcher()) ...
+```
+
+For more information, you can read these
+[two](http://code.google.com/p/googlemock/wiki/V1_6_CookBook#Writing_New_Monomorphic_Matchers)
+[recipes](http://code.google.com/p/googlemock/wiki/V1_6_CookBook#Writing_New_Polymorphic_Matchers)
+from the cookbook.  As always, you
+are welcome to post questions on `googlemock@googlegroups.com` if you
+need any help.
+
+## When using Google Mock, do I have to use Google Test as the testing framework?  I have my favorite testing framework and don't want to switch. ##
+
+Google Mock works out of the box with Google Test.  However, it's easy
+to configure it to work with any testing framework of your choice.
+[Here](http://code.google.com/p/googlemock/wiki/V1_6_ForDummies#Using_Google_Mock_with_Any_Testing_Framework) is how.
+
+## How am I supposed to make sense of these horrible template errors? ##
+
+If you are confused by the compiler errors gcc threw at you,
+try consulting the _Google Mock Doctor_ tool first.  What it does is to
+scan stdin for gcc error messages, and spit out diagnoses on the
+problems (we call them diseases) your code has.
+
+To "install", run command:
+```
+alias gmd='<path to googlemock>/scripts/gmock_doctor.py'
+```
+
+To use it, do:
+```
+<your-favorite-build-command> <your-test> 2>&1 | gmd
+```
+
+For example:
+```
+make my_test 2>&1 | gmd
+```
+
+Or you can run `gmd` and copy-n-paste gcc's error messages to it.
+
+## Can I mock a variadic function? ##
+
+You cannot mock a variadic function (i.e. a function taking ellipsis
+(`...`) arguments) directly in Google Mock.
+
+The problem is that in general, there is _no way_ for a mock object to
+know how many arguments are passed to the variadic method, and what
+the arguments' types are.  Only the _author of the base class_ knows
+the protocol, and we cannot look into his head.
+
+Therefore, to mock such a function, the _user_ must teach the mock
+object how to figure out the number of arguments and their types.  One
+way to do it is to provide overloaded versions of the function.
+
+Ellipsis arguments are inherited from C and not really a C++ feature.
+They are unsafe to use and don't work with arguments that have
+constructors or destructors.  Therefore we recommend to avoid them in
+C++ as much as possible.
+
+## MSVC gives me warning C4301 or C4373 when I define a mock method with a const parameter.  Why? ##
+
+If you compile this using Microsoft Visual C++ 2005 SP1:
+```
+class Foo {
+  ...
+  virtual void Bar(const int i) = 0;
+};
+
+class MockFoo : public Foo {
+  ...
+  MOCK_METHOD1(Bar, void(const int i));
+};
+```
+You may get the following warning:
+```
+warning C4301: 'MockFoo::Bar': overriding virtual function only differs from 'Foo::Bar' by const/volatile qualifier
+```
+
+This is a MSVC bug.  The same code compiles fine with gcc ,for
+example.  If you use Visual C++ 2008 SP1, you would get the warning:
+```
+warning C4373: 'MockFoo::Bar': virtual function overrides 'Foo::Bar', previous versions of the compiler did not override when parameters only differed by const/volatile qualifiers
+```
+
+In C++, if you _declare_ a function with a `const` parameter, the
+`const` modifier is _ignored_.  Therefore, the `Foo` base class above
+is equivalent to:
+```
+class Foo {
+  ...
+  virtual void Bar(int i) = 0;  // int or const int?  Makes no difference.
+};
+```
+
+In fact, you can _declare_ Bar() with an `int` parameter, and _define_
+it with a `const int` parameter.  The compiler will still match them
+up.
+
+Since making a parameter `const` is meaningless in the method
+_declaration_, we recommend to remove it in both `Foo` and `MockFoo`.
+That should workaround the VC bug.
+
+Note that we are talking about the _top-level_ `const` modifier here.
+If the function parameter is passed by pointer or reference, declaring
+the _pointee_ or _referee_ as `const` is still meaningful.  For
+example, the following two declarations are _not_ equivalent:
+```
+void Bar(int* p);        // Neither p nor *p is const.
+void Bar(const int* p);  // p is not const, but *p is.
+```
+
+## I have a huge mock class, and Microsoft Visual C++ runs out of memory when compiling it.  What can I do? ##
+
+We've noticed that when the `/clr` compiler flag is used, Visual C++
+uses 5~6 times as much memory when compiling a mock class.  We suggest
+to avoid `/clr` when compiling native C++ mocks.
+
+## I can't figure out why Google Mock thinks my expectations are not satisfied.  What should I do? ##
+
+You might want to run your test with
+`--gmock_verbose=info`.  This flag lets Google Mock print a trace
+of every mock function call it receives.  By studying the trace,
+you'll gain insights on why the expectations you set are not met.
+
+## How can I assert that a function is NEVER called? ##
+
+```
+EXPECT_CALL(foo, Bar(_))
+    .Times(0);
+```
+
+## I have a failed test where Google Mock tells me TWICE that a particular expectation is not satisfied.  Isn't this redundant? ##
+
+When Google Mock detects a failure, it prints relevant information
+(the mock function arguments, the state of relevant expectations, and
+etc) to help the user debug.  If another failure is detected, Google
+Mock will do the same, including printing the state of relevant
+expectations.
+
+Sometimes an expectation's state didn't change between two failures,
+and you'll see the same description of the state twice.  They are
+however _not_ redundant, as they refer to _different points in time_.
+The fact they are the same _is_ interesting information.
+
+## I get a heap check failure when using a mock object, but using a real object is fine.  What can be wrong? ##
+
+Does the class (hopefully a pure interface) you are mocking have a
+virtual destructor?
+
+Whenever you derive from a base class, make sure its destructor is
+virtual.  Otherwise Bad Things will happen.  Consider the following
+code:
+
+```
+class Base {
+ public:
+  // Not virtual, but should be.
+  ~Base() { ... }
+  ...
+};
+
+class Derived : public Base {
+ public:
+  ...
+ private:
+  std::string value_;
+};
+
+...
+  Base* p = new Derived;
+  ...
+  delete p;  // Surprise! ~Base() will be called, but ~Derived() will not
+             // - value_ is leaked.
+```
+
+By changing `~Base()` to virtual, `~Derived()` will be correctly
+called when `delete p` is executed, and the heap checker
+will be happy.
+
+## The "newer expectations override older ones" rule makes writing expectations awkward.  Why does Google Mock do that? ##
+
+When people complain about this, often they are referring to code like:
+
+```
+// foo.Bar() should be called twice, return 1 the first time, and return
+// 2 the second time.  However, I have to write the expectations in the
+// reverse order.  This sucks big time!!!
+EXPECT_CALL(foo, Bar())
+    .WillOnce(Return(2))
+    .RetiresOnSaturation();
+EXPECT_CALL(foo, Bar())
+    .WillOnce(Return(1))
+    .RetiresOnSaturation();
+```
+
+The problem is that they didn't pick the **best** way to express the test's
+intent.
+
+By default, expectations don't have to be matched in _any_ particular
+order.  If you want them to match in a certain order, you need to be
+explicit.  This is Google Mock's (and jMock's) fundamental philosophy: it's
+easy to accidentally over-specify your tests, and we want to make it
+harder to do so.
+
+There are two better ways to write the test spec.  You could either
+put the expectations in sequence:
+
+```
+// foo.Bar() should be called twice, return 1 the first time, and return
+// 2 the second time.  Using a sequence, we can write the expectations
+// in their natural order.
+{
+  InSequence s;
+  EXPECT_CALL(foo, Bar())
+      .WillOnce(Return(1))
+      .RetiresOnSaturation();
+  EXPECT_CALL(foo, Bar())
+      .WillOnce(Return(2))
+      .RetiresOnSaturation();
+}
+```
+
+or you can put the sequence of actions in the same expectation:
+
+```
+// foo.Bar() should be called twice, return 1 the first time, and return
+// 2 the second time.
+EXPECT_CALL(foo, Bar())
+    .WillOnce(Return(1))
+    .WillOnce(Return(2))
+    .RetiresOnSaturation();
+```
+
+Back to the original questions: why does Google Mock search the
+expectations (and `ON_CALL`s) from back to front?  Because this
+allows a user to set up a mock's behavior for the common case early
+(e.g. in the mock's constructor or the test fixture's set-up phase)
+and customize it with more specific rules later.  If Google Mock
+searches from front to back, this very useful pattern won't be
+possible.
+
+## Google Mock prints a warning when a function without EXPECT\_CALL is called, even if I have set its behavior using ON\_CALL.  Would it be reasonable not to show the warning in this case? ##
+
+When choosing between being neat and being safe, we lean toward the
+latter.  So the answer is that we think it's better to show the
+warning.
+
+Often people write `ON_CALL`s in the mock object's
+constructor or `SetUp()`, as the default behavior rarely changes from
+test to test.  Then in the test body they set the expectations, which
+are often different for each test.  Having an `ON_CALL` in the set-up
+part of a test doesn't mean that the calls are expected.  If there's
+no `EXPECT_CALL` and the method is called, it's possibly an error.  If
+we quietly let the call go through without notifying the user, bugs
+may creep in unnoticed.
+
+If, however, you are sure that the calls are OK, you can write
+
+```
+EXPECT_CALL(foo, Bar(_))
+    .WillRepeatedly(...);
+```
+
+instead of
+
+```
+ON_CALL(foo, Bar(_))
+    .WillByDefault(...);
+```
+
+This tells Google Mock that you do expect the calls and no warning should be
+printed.
+
+Also, you can control the verbosity using the `--gmock_verbose` flag.
+If you find the output too noisy when debugging, just choose a less
+verbose level.
+
+## How can I delete the mock function's argument in an action? ##
+
+If you find yourself needing to perform some action that's not
+supported by Google Mock directly, remember that you can define your own
+actions using
+[MakeAction()](http://code.google.com/p/googlemock/wiki/V1_6_CookBook#Writing_New_Actions) or
+[MakePolymorphicAction()](http://code.google.com/p/googlemock/wiki/V1_6_CookBook#Writing_New_Polymorphic_Actions),
+or you can write a stub function and invoke it using
+[Invoke()](http://code.google.com/p/googlemock/wiki/V1_6_CookBook#Using_Functions_Methods_Functors).
+
+## MOCK\_METHODn()'s second argument looks funny.  Why don't you use the MOCK\_METHODn(Method, return\_type, arg\_1, ..., arg\_n) syntax? ##
+
+What?!  I think it's beautiful. :-)
+
+While which syntax looks more natural is a subjective matter to some
+extent, Google Mock's syntax was chosen for several practical advantages it
+has.
+
+Try to mock a function that takes a map as an argument:
+```
+virtual int GetSize(const map<int, std::string>& m);
+```
+
+Using the proposed syntax, it would be:
+```
+MOCK_METHOD1(GetSize, int, const map<int, std::string>& m);
+```
+
+Guess what?  You'll get a compiler error as the compiler thinks that
+`const map<int, std::string>& m` are **two**, not one, arguments. To work
+around this you can use `typedef` to give the map type a name, but
+that gets in the way of your work.  Google Mock's syntax avoids this
+problem as the function's argument types are protected inside a pair
+of parentheses:
+```
+// This compiles fine.
+MOCK_METHOD1(GetSize, int(const map<int, std::string>& m));
+```
+
+You still need a `typedef` if the return type contains an unprotected
+comma, but that's much rarer.
+
+Other advantages include:
+  1. `MOCK_METHOD1(Foo, int, bool)` can leave a reader wonder whether the method returns `int` or `bool`, while there won't be such confusion using Google Mock's syntax.
+  1. The way Google Mock describes a function type is nothing new, although many people may not be familiar with it.  The same syntax was used in C, and the `function` library in `tr1` uses this syntax extensively.  Since `tr1` will become a part of the new version of STL, we feel very comfortable to be consistent with it.
+  1. The function type syntax is also used in other parts of Google Mock's API (e.g. the action interface) in order to make the implementation tractable. A user needs to learn it anyway in order to utilize Google Mock's more advanced features.  We'd as well stick to the same syntax in `MOCK_METHOD*`!
+
+## My code calls a static/global function.  Can I mock it? ##
+
+You can, but you need to make some changes.
+
+In general, if you find yourself needing to mock a static function,
+it's a sign that your modules are too tightly coupled (and less
+flexible, less reusable, less testable, etc).  You are probably better
+off defining a small interface and call the function through that
+interface, which then can be easily mocked.  It's a bit of work
+initially, but usually pays for itself quickly.
+
+This Google Testing Blog
+[post](http://googletesting.blogspot.com/2008/06/defeat-static-cling.html)
+says it excellently.  Check it out.
+
+## My mock object needs to do complex stuff.  It's a lot of pain to specify the actions.  Google Mock sucks! ##
+
+I know it's not a question, but you get an answer for free any way. :-)
+
+With Google Mock, you can create mocks in C++ easily.  And people might be
+tempted to use them everywhere. Sometimes they work great, and
+sometimes you may find them, well, a pain to use. So, what's wrong in
+the latter case?
+
+When you write a test without using mocks, you exercise the code and
+assert that it returns the correct value or that the system is in an
+expected state.  This is sometimes called "state-based testing".
+
+Mocks are great for what some call "interaction-based" testing:
+instead of checking the system state at the very end, mock objects
+verify that they are invoked the right way and report an error as soon
+as it arises, giving you a handle on the precise context in which the
+error was triggered.  This is often more effective and economical to
+do than state-based testing.
+
+If you are doing state-based testing and using a test double just to
+simulate the real object, you are probably better off using a fake.
+Using a mock in this case causes pain, as it's not a strong point for
+mocks to perform complex actions.  If you experience this and think
+that mocks suck, you are just not using the right tool for your
+problem. Or, you might be trying to solve the wrong problem. :-)
+
+## I got a warning "Uninteresting function call encountered - default action taken.."  Should I panic? ##
+
+By all means, NO!  It's just an FYI.
+
+What it means is that you have a mock function, you haven't set any
+expectations on it (by Google Mock's rule this means that you are not
+interested in calls to this function and therefore it can be called
+any number of times), and it is called.  That's OK - you didn't say
+it's not OK to call the function!
+
+What if you actually meant to disallow this function to be called, but
+forgot to write `EXPECT_CALL(foo, Bar()).Times(0)`?  While
+one can argue that it's the user's fault, Google Mock tries to be nice and
+prints you a note.
+
+So, when you see the message and believe that there shouldn't be any
+uninteresting calls, you should investigate what's going on.  To make
+your life easier, Google Mock prints the function name and arguments
+when an uninteresting call is encountered.
+
+## I want to define a custom action.  Should I use Invoke() or implement the action interface? ##
+
+Either way is fine - you want to choose the one that's more convenient
+for your circumstance.
+
+Usually, if your action is for a particular function type, defining it
+using `Invoke()` should be easier; if your action can be used in
+functions of different types (e.g. if you are defining
+`Return(value)`), `MakePolymorphicAction()` is
+easiest.  Sometimes you want precise control on what types of
+functions the action can be used in, and implementing
+`ActionInterface` is the way to go here. See the implementation of
+`Return()` in `include/gmock/gmock-actions.h` for an example.
+
+## I'm using the set-argument-pointee action, and the compiler complains about "conflicting return type specified".  What does it mean? ##
+
+You got this error as Google Mock has no idea what value it should return
+when the mock method is called.  `SetArgPointee()` says what the
+side effect is, but doesn't say what the return value should be.  You
+need `DoAll()` to chain a `SetArgPointee()` with a `Return()`.
+
+See this [recipe](http://code.google.com/p/googlemock/wiki/V1_6_CookBook#Mocking_Side_Effects) for more details and an example.
+
+
+## My question is not in your FAQ! ##
+
+If you cannot find the answer to your question in this FAQ, there are
+some other resources you can use:
+
+  1. read other [wiki pages](http://code.google.com/p/googlemock/w/list),
+  1. search the mailing list [archive](http://groups.google.com/group/googlemock/topics),
+  1. ask it on [googlemock@googlegroups.com](mailto:googlemock@googlegroups.com) and someone will answer it (to prevent spam, we require you to join the [discussion group](http://groups.google.com/group/googlemock) before you can post.).
+
+Please note that creating an issue in the
+[issue tracker](http://code.google.com/p/googlemock/issues/list) is _not_
+a good way to get your answer, as it is monitored infrequently by a
+very small number of people.
+
+When asking a question, it's helpful to provide as much of the
+following information as possible (people cannot help you if there's
+not enough information in your question):
+
+  * the version (or the revision number if you check out from SVN directly) of Google Mock you use (Google Mock is under active development, so it's possible that your problem has been solved in a later version),
+  * your operating system,
+  * the name and version of your compiler,
+  * the complete command line flags you give to your compiler,
+  * the complete compiler error messages (if the question is about compilation),
+  * the _actual_ code (ideally, a minimal but complete program) that has the problem you encounter.
\ No newline at end of file
diff --git a/third_party/googletest/googlemock/docs/v1_7/CheatSheet.md b/third_party/googletest/googlemock/docs/v1_7/CheatSheet.md
new file mode 100644
index 0000000..db421e5
--- /dev/null
+++ b/third_party/googletest/googlemock/docs/v1_7/CheatSheet.md
@@ -0,0 +1,556 @@
+
+
+# Defining a Mock Class #
+
+## Mocking a Normal Class ##
+
+Given
+```
+class Foo {
+  ...
+  virtual ~Foo();
+  virtual int GetSize() const = 0;
+  virtual string Describe(const char* name) = 0;
+  virtual string Describe(int type) = 0;
+  virtual bool Process(Bar elem, int count) = 0;
+};
+```
+(note that `~Foo()` **must** be virtual) we can define its mock as
+```
+#include "gmock/gmock.h"
+
+class MockFoo : public Foo {
+  MOCK_CONST_METHOD0(GetSize, int());
+  MOCK_METHOD1(Describe, string(const char* name));
+  MOCK_METHOD1(Describe, string(int type));
+  MOCK_METHOD2(Process, bool(Bar elem, int count));
+};
+```
+
+To create a "nice" mock object which ignores all uninteresting calls,
+or a "strict" mock object, which treats them as failures:
+```
+NiceMock<MockFoo> nice_foo;     // The type is a subclass of MockFoo.
+StrictMock<MockFoo> strict_foo; // The type is a subclass of MockFoo.
+```
+
+## Mocking a Class Template ##
+
+To mock
+```
+template <typename Elem>
+class StackInterface {
+ public:
+  ...
+  virtual ~StackInterface();
+  virtual int GetSize() const = 0;
+  virtual void Push(const Elem& x) = 0;
+};
+```
+(note that `~StackInterface()` **must** be virtual) just append `_T` to the `MOCK_*` macros:
+```
+template <typename Elem>
+class MockStack : public StackInterface<Elem> {
+ public:
+  ...
+  MOCK_CONST_METHOD0_T(GetSize, int());
+  MOCK_METHOD1_T(Push, void(const Elem& x));
+};
+```
+
+## Specifying Calling Conventions for Mock Functions ##
+
+If your mock function doesn't use the default calling convention, you
+can specify it by appending `_WITH_CALLTYPE` to any of the macros
+described in the previous two sections and supplying the calling
+convention as the first argument to the macro. For example,
+```
+  MOCK_METHOD_1_WITH_CALLTYPE(STDMETHODCALLTYPE, Foo, bool(int n));
+  MOCK_CONST_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, Bar, int(double x, double y));
+```
+where `STDMETHODCALLTYPE` is defined by `<objbase.h>` on Windows.
+
+# Using Mocks in Tests #
+
+The typical flow is:
+  1. Import the Google Mock names you need to use. All Google Mock names are in the `testing` namespace unless they are macros or otherwise noted.
+  1. Create the mock objects.
+  1. Optionally, set the default actions of the mock objects.
+  1. Set your expectations on the mock objects (How will they be called? What wil they do?).
+  1. Exercise code that uses the mock objects; if necessary, check the result using [Google Test](http://code.google.com/p/googletest/) assertions.
+  1. When a mock objects is destructed, Google Mock automatically verifies that all expectations on it have been satisfied.
+
+Here is an example:
+```
+using ::testing::Return;                            // #1
+
+TEST(BarTest, DoesThis) {
+  MockFoo foo;                                    // #2
+
+  ON_CALL(foo, GetSize())                         // #3
+      .WillByDefault(Return(1));
+  // ... other default actions ...
+
+  EXPECT_CALL(foo, Describe(5))                   // #4
+      .Times(3)
+      .WillRepeatedly(Return("Category 5"));
+  // ... other expectations ...
+
+  EXPECT_EQ("good", MyProductionFunction(&foo));  // #5
+}                                                 // #6
+```
+
+# Setting Default Actions #
+
+Google Mock has a **built-in default action** for any function that
+returns `void`, `bool`, a numeric value, or a pointer.
+
+To customize the default action for functions with return type `T` globally:
+```
+using ::testing::DefaultValue;
+
+DefaultValue<T>::Set(value);  // Sets the default value to be returned.
+// ... use the mocks ...
+DefaultValue<T>::Clear();     // Resets the default value.
+```
+
+To customize the default action for a particular method, use `ON_CALL()`:
+```
+ON_CALL(mock_object, method(matchers))
+    .With(multi_argument_matcher)  ?
+    .WillByDefault(action);
+```
+
+# Setting Expectations #
+
+`EXPECT_CALL()` sets **expectations** on a mock method (How will it be
+called? What will it do?):
+```
+EXPECT_CALL(mock_object, method(matchers))
+    .With(multi_argument_matcher)  ?
+    .Times(cardinality)            ?
+    .InSequence(sequences)         *
+    .After(expectations)           *
+    .WillOnce(action)              *
+    .WillRepeatedly(action)        ?
+    .RetiresOnSaturation();        ?
+```
+
+If `Times()` is omitted, the cardinality is assumed to be:
+
+  * `Times(1)` when there is neither `WillOnce()` nor `WillRepeatedly()`;
+  * `Times(n)` when there are `n WillOnce()`s but no `WillRepeatedly()`, where `n` >= 1; or
+  * `Times(AtLeast(n))` when there are `n WillOnce()`s and a `WillRepeatedly()`, where `n` >= 0.
+
+A method with no `EXPECT_CALL()` is free to be invoked _any number of times_, and the default action will be taken each time.
+
+# Matchers #
+
+A **matcher** matches a _single_ argument.  You can use it inside
+`ON_CALL()` or `EXPECT_CALL()`, or use it to validate a value
+directly:
+
+| `EXPECT_THAT(value, matcher)` | Asserts that `value` matches `matcher`. |
+|:------------------------------|:----------------------------------------|
+| `ASSERT_THAT(value, matcher)` | The same as `EXPECT_THAT(value, matcher)`, except that it generates a **fatal** failure. |
+
+Built-in matchers (where `argument` is the function argument) are
+divided into several categories:
+
+## Wildcard ##
+|`_`|`argument` can be any value of the correct type.|
+|:--|:-----------------------------------------------|
+|`A<type>()` or `An<type>()`|`argument` can be any value of type `type`.     |
+
+## Generic Comparison ##
+
+|`Eq(value)` or `value`|`argument == value`|
+|:---------------------|:------------------|
+|`Ge(value)`           |`argument >= value`|
+|`Gt(value)`           |`argument > value` |
+|`Le(value)`           |`argument <= value`|
+|`Lt(value)`           |`argument < value` |
+|`Ne(value)`           |`argument != value`|
+|`IsNull()`            |`argument` is a `NULL` pointer (raw or smart).|
+|`NotNull()`           |`argument` is a non-null pointer (raw or smart).|
+|`Ref(variable)`       |`argument` is a reference to `variable`.|
+|`TypedEq<type>(value)`|`argument` has type `type` and is equal to `value`. You may need to use this instead of `Eq(value)` when the mock function is overloaded.|
+
+Except `Ref()`, these matchers make a _copy_ of `value` in case it's
+modified or destructed later. If the compiler complains that `value`
+doesn't have a public copy constructor, try wrap it in `ByRef()`,
+e.g. `Eq(ByRef(non_copyable_value))`. If you do that, make sure
+`non_copyable_value` is not changed afterwards, or the meaning of your
+matcher will be changed.
+
+## Floating-Point Matchers ##
+
+|`DoubleEq(a_double)`|`argument` is a `double` value approximately equal to `a_double`, treating two NaNs as unequal.|
+|:-------------------|:----------------------------------------------------------------------------------------------|
+|`FloatEq(a_float)`  |`argument` is a `float` value approximately equal to `a_float`, treating two NaNs as unequal.  |
+|`NanSensitiveDoubleEq(a_double)`|`argument` is a `double` value approximately equal to `a_double`, treating two NaNs as equal.  |
+|`NanSensitiveFloatEq(a_float)`|`argument` is a `float` value approximately equal to `a_float`, treating two NaNs as equal.    |
+
+The above matchers use ULP-based comparison (the same as used in
+[Google Test](http://code.google.com/p/googletest/)). They
+automatically pick a reasonable error bound based on the absolute
+value of the expected value.  `DoubleEq()` and `FloatEq()` conform to
+the IEEE standard, which requires comparing two NaNs for equality to
+return false. The `NanSensitive*` version instead treats two NaNs as
+equal, which is often what a user wants.
+
+|`DoubleNear(a_double, max_abs_error)`|`argument` is a `double` value close to `a_double` (absolute error <= `max_abs_error`), treating two NaNs as unequal.|
+|:------------------------------------|:--------------------------------------------------------------------------------------------------------------------|
+|`FloatNear(a_float, max_abs_error)`  |`argument` is a `float` value close to `a_float` (absolute error <= `max_abs_error`), treating two NaNs as unequal.  |
+|`NanSensitiveDoubleNear(a_double, max_abs_error)`|`argument` is a `double` value close to `a_double` (absolute error <= `max_abs_error`), treating two NaNs as equal.  |
+|`NanSensitiveFloatNear(a_float, max_abs_error)`|`argument` is a `float` value close to `a_float` (absolute error <= `max_abs_error`), treating two NaNs as equal.    |
+
+## String Matchers ##
+
+The `argument` can be either a C string or a C++ string object:
+
+|`ContainsRegex(string)`|`argument` matches the given regular expression.|
+|:----------------------|:-----------------------------------------------|
+|`EndsWith(suffix)`     |`argument` ends with string `suffix`.           |
+|`HasSubstr(string)`    |`argument` contains `string` as a sub-string.   |
+|`MatchesRegex(string)` |`argument` matches the given regular expression with the match starting at the first character and ending at the last character.|
+|`StartsWith(prefix)`   |`argument` starts with string `prefix`.         |
+|`StrCaseEq(string)`    |`argument` is equal to `string`, ignoring case. |
+|`StrCaseNe(string)`    |`argument` is not equal to `string`, ignoring case.|
+|`StrEq(string)`        |`argument` is equal to `string`.                |
+|`StrNe(string)`        |`argument` is not equal to `string`.            |
+
+`ContainsRegex()` and `MatchesRegex()` use the regular expression
+syntax defined
+[here](http://code.google.com/p/googletest/wiki/AdvancedGuide#Regular_Expression_Syntax).
+`StrCaseEq()`, `StrCaseNe()`, `StrEq()`, and `StrNe()` work for wide
+strings as well.
+
+## Container Matchers ##
+
+Most STL-style containers support `==`, so you can use
+`Eq(expected_container)` or simply `expected_container` to match a
+container exactly.   If you want to write the elements in-line,
+match them more flexibly, or get more informative messages, you can use:
+
+| `ContainerEq(container)` | The same as `Eq(container)` except that the failure message also includes which elements are in one container but not the other. |
+|:-------------------------|:---------------------------------------------------------------------------------------------------------------------------------|
+| `Contains(e)`            | `argument` contains an element that matches `e`, which can be either a value or a matcher.                                       |
+| `Each(e)`                | `argument` is a container where _every_ element matches `e`, which can be either a value or a matcher.                           |
+| `ElementsAre(e0, e1, ..., en)` | `argument` has `n + 1` elements, where the i-th element matches `ei`, which can be a value or a matcher. 0 to 10 arguments are allowed. |
+| `ElementsAreArray({ e0, e1, ..., en })`, `ElementsAreArray(array)`, or `ElementsAreArray(array, count)` | The same as `ElementsAre()` except that the expected element values/matchers come from an initializer list, vector, or C-style array. |
+| `IsEmpty()`              | `argument` is an empty container (`container.empty()`).                                                                          |
+| `Pointwise(m, container)` | `argument` contains the same number of elements as in `container`, and for all i, (the i-th element in `argument`, the i-th element in `container`) match `m`, which is a matcher on 2-tuples. E.g. `Pointwise(Le(), upper_bounds)` verifies that each element in `argument` doesn't exceed the corresponding element in `upper_bounds`. See more detail below. |
+| `SizeIs(m)`              | `argument` is a container whose size matches `m`. E.g. `SizeIs(2)` or `SizeIs(Lt(2))`.                                           |
+| `UnorderedElementsAre(e0, e1, ..., en)` | `argument` has `n + 1` elements, and under some permutation each element matches an `ei` (for a different `i`), which can be a value or a matcher. 0 to 10 arguments are allowed. |
+| `UnorderedElementsAreArray({ e0, e1, ..., en })`, `UnorderedElementsAreArray(array)`, or `UnorderedElementsAreArray(array, count)` | The same as `UnorderedElementsAre()` except that the expected element values/matchers come from an initializer list, vector, or C-style array. |
+| `WhenSorted(m)`          | When `argument` is sorted using the `<` operator, it matches container matcher `m`. E.g. `WhenSorted(UnorderedElementsAre(1, 2, 3))` verifies that `argument` contains elements `1`, `2`, and `3`, ignoring order. |
+| `WhenSortedBy(comparator, m)` | The same as `WhenSorted(m)`, except that the given comparator instead of `<` is used to sort `argument`. E.g. `WhenSortedBy(std::greater<int>(), ElementsAre(3, 2, 1))`. |
+
+Notes:
+
+  * These matchers can also match:
+    1. a native array passed by reference (e.g. in `Foo(const int (&a)[5])`), and
+    1. an array passed as a pointer and a count (e.g. in `Bar(const T* buffer, int len)` -- see [Multi-argument Matchers](#Multiargument_Matchers.md)).
+  * The array being matched may be multi-dimensional (i.e. its elements can be arrays).
+  * `m` in `Pointwise(m, ...)` should be a matcher for `std::tr1::tuple<T, U>` where `T` and `U` are the element type of the actual container and the expected container, respectively. For example, to compare two `Foo` containers where `Foo` doesn't support `operator==` but has an `Equals()` method, one might write:
+
+```
+using ::std::tr1::get;
+MATCHER(FooEq, "") {
+  return get<0>(arg).Equals(get<1>(arg));
+}
+...
+EXPECT_THAT(actual_foos, Pointwise(FooEq(), expected_foos));
+```
+
+## Member Matchers ##
+
+|`Field(&class::field, m)`|`argument.field` (or `argument->field` when `argument` is a plain pointer) matches matcher `m`, where `argument` is an object of type _class_.|
+|:------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------|
+|`Key(e)`                 |`argument.first` matches `e`, which can be either a value or a matcher. E.g. `Contains(Key(Le(5)))` can verify that a `map` contains a key `<= 5`.|
+|`Pair(m1, m2)`           |`argument` is an `std::pair` whose `first` field matches `m1` and `second` field matches `m2`.                                                |
+|`Property(&class::property, m)`|`argument.property()` (or `argument->property()` when `argument` is a plain pointer) matches matcher `m`, where `argument` is an object of type _class_.|
+
+## Matching the Result of a Function or Functor ##
+
+|`ResultOf(f, m)`|`f(argument)` matches matcher `m`, where `f` is a function or functor.|
+|:---------------|:---------------------------------------------------------------------|
+
+## Pointer Matchers ##
+
+|`Pointee(m)`|`argument` (either a smart pointer or a raw pointer) points to a value that matches matcher `m`.|
+|:-----------|:-----------------------------------------------------------------------------------------------|
+
+## Multiargument Matchers ##
+
+Technically, all matchers match a _single_ value. A "multi-argument"
+matcher is just one that matches a _tuple_. The following matchers can
+be used to match a tuple `(x, y)`:
+
+|`Eq()`|`x == y`|
+|:-----|:-------|
+|`Ge()`|`x >= y`|
+|`Gt()`|`x > y` |
+|`Le()`|`x <= y`|
+|`Lt()`|`x < y` |
+|`Ne()`|`x != y`|
+
+You can use the following selectors to pick a subset of the arguments
+(or reorder them) to participate in the matching:
+
+|`AllArgs(m)`|Equivalent to `m`. Useful as syntactic sugar in `.With(AllArgs(m))`.|
+|:-----------|:-------------------------------------------------------------------|
+|`Args<N1, N2, ..., Nk>(m)`|The tuple of the `k` selected (using 0-based indices) arguments matches `m`, e.g. `Args<1, 2>(Eq())`.|
+
+## Composite Matchers ##
+
+You can make a matcher from one or more other matchers:
+
+|`AllOf(m1, m2, ..., mn)`|`argument` matches all of the matchers `m1` to `mn`.|
+|:-----------------------|:---------------------------------------------------|
+|`AnyOf(m1, m2, ..., mn)`|`argument` matches at least one of the matchers `m1` to `mn`.|
+|`Not(m)`                |`argument` doesn't match matcher `m`.               |
+
+## Adapters for Matchers ##
+
+|`MatcherCast<T>(m)`|casts matcher `m` to type `Matcher<T>`.|
+|:------------------|:--------------------------------------|
+|`SafeMatcherCast<T>(m)`| [safely casts](http://code.google.com/p/googlemock/wiki/V1_7_CookBook#Casting_Matchers) matcher `m` to type `Matcher<T>`. |
+|`Truly(predicate)` |`predicate(argument)` returns something considered by C++ to be true, where `predicate` is a function or functor.|
+
+## Matchers as Predicates ##
+
+|`Matches(m)(value)`|evaluates to `true` if `value` matches `m`. You can use `Matches(m)` alone as a unary functor.|
+|:------------------|:---------------------------------------------------------------------------------------------|
+|`ExplainMatchResult(m, value, result_listener)`|evaluates to `true` if `value` matches `m`, explaining the result to `result_listener`.       |
+|`Value(value, m)`  |evaluates to `true` if `value` matches `m`.                                                   |
+
+## Defining Matchers ##
+
+| `MATCHER(IsEven, "") { return (arg % 2) == 0; }` | Defines a matcher `IsEven()` to match an even number. |
+|:-------------------------------------------------|:------------------------------------------------------|
+| `MATCHER_P(IsDivisibleBy, n, "") { *result_listener << "where the remainder is " << (arg % n); return (arg % n) == 0; }` | Defines a macher `IsDivisibleBy(n)` to match a number divisible by `n`. |
+| `MATCHER_P2(IsBetween, a, b, std::string(negation ? "isn't" : "is") + " between " + PrintToString(a) + " and " + PrintToString(b)) { return a <= arg && arg <= b; }` | Defines a matcher `IsBetween(a, b)` to match a value in the range [`a`, `b`]. |
+
+**Notes:**
+
+  1. The `MATCHER*` macros cannot be used inside a function or class.
+  1. The matcher body must be _purely functional_ (i.e. it cannot have any side effect, and the result must not depend on anything other than the value being matched and the matcher parameters).
+  1. You can use `PrintToString(x)` to convert a value `x` of any type to a string.
+
+## Matchers as Test Assertions ##
+
+|`ASSERT_THAT(expression, m)`|Generates a [fatal failure](http://code.google.com/p/googletest/wiki/Primer#Assertions) if the value of `expression` doesn't match matcher `m`.|
+|:---------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------|
+|`EXPECT_THAT(expression, m)`|Generates a non-fatal failure if the value of `expression` doesn't match matcher `m`.                                                          |
+
+# Actions #
+
+**Actions** specify what a mock function should do when invoked.
+
+## Returning a Value ##
+
+|`Return()`|Return from a `void` mock function.|
+|:---------|:----------------------------------|
+|`Return(value)`|Return `value`. If the type of `value` is different to the mock function's return type, `value` is converted to the latter type <i>at the time the expectation is set</i>, not when the action is executed.|
+|`ReturnArg<N>()`|Return the `N`-th (0-based) argument.|
+|`ReturnNew<T>(a1, ..., ak)`|Return `new T(a1, ..., ak)`; a different object is created each time.|
+|`ReturnNull()`|Return a null pointer.             |
+|`ReturnPointee(ptr)`|Return the value pointed to by `ptr`.|
+|`ReturnRef(variable)`|Return a reference to `variable`.  |
+|`ReturnRefOfCopy(value)`|Return a reference to a copy of `value`; the copy lives as long as the action.|
+
+## Side Effects ##
+
+|`Assign(&variable, value)`|Assign `value` to variable.|
+|:-------------------------|:--------------------------|
+| `DeleteArg<N>()`         | Delete the `N`-th (0-based) argument, which must be a pointer. |
+| `SaveArg<N>(pointer)`    | Save the `N`-th (0-based) argument to `*pointer`. |
+| `SaveArgPointee<N>(pointer)` | Save the value pointed to by the `N`-th (0-based) argument to `*pointer`. |
+| `SetArgReferee<N>(value)` |	Assign value to the variable referenced by the `N`-th (0-based) argument. |
+|`SetArgPointee<N>(value)` |Assign `value` to the variable pointed by the `N`-th (0-based) argument.|
+|`SetArgumentPointee<N>(value)`|Same as `SetArgPointee<N>(value)`. Deprecated. Will be removed in v1.7.0.|
+|`SetArrayArgument<N>(first, last)`|Copies the elements in source range [`first`, `last`) to the array pointed to by the `N`-th (0-based) argument, which can be either a pointer or an iterator. The action does not take ownership of the elements in the source range.|
+|`SetErrnoAndReturn(error, value)`|Set `errno` to `error` and return `value`.|
+|`Throw(exception)`        |Throws the given exception, which can be any copyable value. Available since v1.1.0.|
+
+## Using a Function or a Functor as an Action ##
+
+|`Invoke(f)`|Invoke `f` with the arguments passed to the mock function, where `f` can be a global/static function or a functor.|
+|:----------|:-----------------------------------------------------------------------------------------------------------------|
+|`Invoke(object_pointer, &class::method)`|Invoke the {method on the object with the arguments passed to the mock function.                                  |
+|`InvokeWithoutArgs(f)`|Invoke `f`, which can be a global/static function or a functor. `f` must take no arguments.                       |
+|`InvokeWithoutArgs(object_pointer, &class::method)`|Invoke the method on the object, which takes no arguments.                                                        |
+|`InvokeArgument<N>(arg1, arg2, ..., argk)`|Invoke the mock function's `N`-th (0-based) argument, which must be a function or a functor, with the `k` arguments.|
+
+The return value of the invoked function is used as the return value
+of the action.
+
+When defining a function or functor to be used with `Invoke*()`, you can declare any unused parameters as `Unused`:
+```
+  double Distance(Unused, double x, double y) { return sqrt(x*x + y*y); }
+  ...
+  EXPECT_CALL(mock, Foo("Hi", _, _)).WillOnce(Invoke(Distance));
+```
+
+In `InvokeArgument<N>(...)`, if an argument needs to be passed by reference, wrap it inside `ByRef()`. For example,
+```
+  InvokeArgument<2>(5, string("Hi"), ByRef(foo))
+```
+calls the mock function's #2 argument, passing to it `5` and `string("Hi")` by value, and `foo` by reference.
+
+## Default Action ##
+
+|`DoDefault()`|Do the default action (specified by `ON_CALL()` or the built-in one).|
+|:------------|:--------------------------------------------------------------------|
+
+**Note:** due to technical reasons, `DoDefault()` cannot be used inside  a composite action - trying to do so will result in a run-time error.
+
+## Composite Actions ##
+
+|`DoAll(a1, a2, ..., an)`|Do all actions `a1` to `an` and return the result of `an` in each invocation. The first `n - 1` sub-actions must return void. |
+|:-----------------------|:-----------------------------------------------------------------------------------------------------------------------------|
+|`IgnoreResult(a)`       |Perform action `a` and ignore its result. `a` must not return void.                                                           |
+|`WithArg<N>(a)`         |Pass the `N`-th (0-based) argument of the mock function to action `a` and perform it.                                         |
+|`WithArgs<N1, N2, ..., Nk>(a)`|Pass the selected (0-based) arguments of the mock function to action `a` and perform it.                                      |
+|`WithoutArgs(a)`        |Perform action `a` without any arguments.                                                                                     |
+
+## Defining Actions ##
+
+| `ACTION(Sum) { return arg0 + arg1; }` | Defines an action `Sum()` to return the sum of the mock function's argument #0 and #1. |
+|:--------------------------------------|:---------------------------------------------------------------------------------------|
+| `ACTION_P(Plus, n) { return arg0 + n; }` | Defines an action `Plus(n)` to return the sum of the mock function's argument #0 and `n`. |
+| `ACTION_Pk(Foo, p1, ..., pk) { statements; }` | Defines a parameterized action `Foo(p1, ..., pk)` to execute the given `statements`.   |
+
+The `ACTION*` macros cannot be used inside a function or class.
+
+# Cardinalities #
+
+These are used in `Times()` to specify how many times a mock function will be called:
+
+|`AnyNumber()`|The function can be called any number of times.|
+|:------------|:----------------------------------------------|
+|`AtLeast(n)` |The call is expected at least `n` times.       |
+|`AtMost(n)`  |The call is expected at most `n` times.        |
+|`Between(m, n)`|The call is expected between `m` and `n` (inclusive) times.|
+|`Exactly(n) or n`|The call is expected exactly `n` times. In particular, the call should never happen when `n` is 0.|
+
+# Expectation Order #
+
+By default, the expectations can be matched in _any_ order.  If some
+or all expectations must be matched in a given order, there are two
+ways to specify it.  They can be used either independently or
+together.
+
+## The After Clause ##
+
+```
+using ::testing::Expectation;
+...
+Expectation init_x = EXPECT_CALL(foo, InitX());
+Expectation init_y = EXPECT_CALL(foo, InitY());
+EXPECT_CALL(foo, Bar())
+    .After(init_x, init_y);
+```
+says that `Bar()` can be called only after both `InitX()` and
+`InitY()` have been called.
+
+If you don't know how many pre-requisites an expectation has when you
+write it, you can use an `ExpectationSet` to collect them:
+
+```
+using ::testing::ExpectationSet;
+...
+ExpectationSet all_inits;
+for (int i = 0; i < element_count; i++) {
+  all_inits += EXPECT_CALL(foo, InitElement(i));
+}
+EXPECT_CALL(foo, Bar())
+    .After(all_inits);
+```
+says that `Bar()` can be called only after all elements have been
+initialized (but we don't care about which elements get initialized
+before the others).
+
+Modifying an `ExpectationSet` after using it in an `.After()` doesn't
+affect the meaning of the `.After()`.
+
+## Sequences ##
+
+When you have a long chain of sequential expectations, it's easier to
+specify the order using **sequences**, which don't require you to given
+each expectation in the chain a different name.  <i>All expected<br>
+calls</i> in the same sequence must occur in the order they are
+specified.
+
+```
+using ::testing::Sequence;
+Sequence s1, s2;
+...
+EXPECT_CALL(foo, Reset())
+    .InSequence(s1, s2)
+    .WillOnce(Return(true));
+EXPECT_CALL(foo, GetSize())
+    .InSequence(s1)
+    .WillOnce(Return(1));
+EXPECT_CALL(foo, Describe(A<const char*>()))
+    .InSequence(s2)
+    .WillOnce(Return("dummy"));
+```
+says that `Reset()` must be called before _both_ `GetSize()` _and_
+`Describe()`, and the latter two can occur in any order.
+
+To put many expectations in a sequence conveniently:
+```
+using ::testing::InSequence;
+{
+  InSequence dummy;
+
+  EXPECT_CALL(...)...;
+  EXPECT_CALL(...)...;
+  ...
+  EXPECT_CALL(...)...;
+}
+```
+says that all expected calls in the scope of `dummy` must occur in
+strict order. The name `dummy` is irrelevant.)
+
+# Verifying and Resetting a Mock #
+
+Google Mock will verify the expectations on a mock object when it is destructed, or you can do it earlier:
+```
+using ::testing::Mock;
+...
+// Verifies and removes the expectations on mock_obj;
+// returns true iff successful.
+Mock::VerifyAndClearExpectations(&mock_obj);
+...
+// Verifies and removes the expectations on mock_obj;
+// also removes the default actions set by ON_CALL();
+// returns true iff successful.
+Mock::VerifyAndClear(&mock_obj);
+```
+
+You can also tell Google Mock that a mock object can be leaked and doesn't
+need to be verified:
+```
+Mock::AllowLeak(&mock_obj);
+```
+
+# Mock Classes #
+
+Google Mock defines a convenient mock class template
+```
+class MockFunction<R(A1, ..., An)> {
+ public:
+  MOCK_METHODn(Call, R(A1, ..., An));
+};
+```
+See this [recipe](http://code.google.com/p/googlemock/wiki/V1_7_CookBook#Using_Check_Points) for one application of it.
+
+# Flags #
+
+| `--gmock_catch_leaked_mocks=0` | Don't report leaked mock objects as failures. |
+|:-------------------------------|:----------------------------------------------|
+| `--gmock_verbose=LEVEL`        | Sets the default verbosity level (`info`, `warning`, or `error`) of Google Mock messages. |
\ No newline at end of file
diff --git a/third_party/googletest/googlemock/docs/v1_7/CookBook.md b/third_party/googletest/googlemock/docs/v1_7/CookBook.md
new file mode 100644
index 0000000..419a001
--- /dev/null
+++ b/third_party/googletest/googlemock/docs/v1_7/CookBook.md
@@ -0,0 +1,3432 @@
+
+
+You can find recipes for using Google Mock here. If you haven't yet,
+please read the [ForDummies](V1_7_ForDummies.md) document first to make sure you understand
+the basics.
+
+**Note:** Google Mock lives in the `testing` name space. For
+readability, it is recommended to write `using ::testing::Foo;` once in
+your file before using the name `Foo` defined by Google Mock. We omit
+such `using` statements in this page for brevity, but you should do it
+in your own code.
+
+# Creating Mock Classes #
+
+## Mocking Private or Protected Methods ##
+
+You must always put a mock method definition (`MOCK_METHOD*`) in a
+`public:` section of the mock class, regardless of the method being
+mocked being `public`, `protected`, or `private` in the base class.
+This allows `ON_CALL` and `EXPECT_CALL` to reference the mock function
+from outside of the mock class.  (Yes, C++ allows a subclass to change
+the access level of a virtual function in the base class.)  Example:
+
+```
+class Foo {
+ public:
+  ...
+  virtual bool Transform(Gadget* g) = 0;
+
+ protected:
+  virtual void Resume();
+
+ private:
+  virtual int GetTimeOut();
+};
+
+class MockFoo : public Foo {
+ public:
+  ...
+  MOCK_METHOD1(Transform, bool(Gadget* g));
+
+  // The following must be in the public section, even though the
+  // methods are protected or private in the base class.
+  MOCK_METHOD0(Resume, void());
+  MOCK_METHOD0(GetTimeOut, int());
+};
+```
+
+## Mocking Overloaded Methods ##
+
+You can mock overloaded functions as usual. No special attention is required:
+
+```
+class Foo {
+  ...
+
+  // Must be virtual as we'll inherit from Foo.
+  virtual ~Foo();
+
+  // Overloaded on the types and/or numbers of arguments.
+  virtual int Add(Element x);
+  virtual int Add(int times, Element x);
+
+  // Overloaded on the const-ness of this object.
+  virtual Bar& GetBar();
+  virtual const Bar& GetBar() const;
+};
+
+class MockFoo : public Foo {
+  ...
+  MOCK_METHOD1(Add, int(Element x));
+  MOCK_METHOD2(Add, int(int times, Element x);
+
+  MOCK_METHOD0(GetBar, Bar&());
+  MOCK_CONST_METHOD0(GetBar, const Bar&());
+};
+```
+
+**Note:** if you don't mock all versions of the overloaded method, the
+compiler will give you a warning about some methods in the base class
+being hidden. To fix that, use `using` to bring them in scope:
+
+```
+class MockFoo : public Foo {
+  ...
+  using Foo::Add;
+  MOCK_METHOD1(Add, int(Element x));
+  // We don't want to mock int Add(int times, Element x);
+  ...
+};
+```
+
+## Mocking Class Templates ##
+
+To mock a class template, append `_T` to the `MOCK_*` macros:
+
+```
+template <typename Elem>
+class StackInterface {
+  ...
+  // Must be virtual as we'll inherit from StackInterface.
+  virtual ~StackInterface();
+
+  virtual int GetSize() const = 0;
+  virtual void Push(const Elem& x) = 0;
+};
+
+template <typename Elem>
+class MockStack : public StackInterface<Elem> {
+  ...
+  MOCK_CONST_METHOD0_T(GetSize, int());
+  MOCK_METHOD1_T(Push, void(const Elem& x));
+};
+```
+
+## Mocking Nonvirtual Methods ##
+
+Google Mock can mock non-virtual functions to be used in what we call _hi-perf
+dependency injection_.
+
+In this case, instead of sharing a common base class with the real
+class, your mock class will be _unrelated_ to the real class, but
+contain methods with the same signatures.  The syntax for mocking
+non-virtual methods is the _same_ as mocking virtual methods:
+
+```
+// A simple packet stream class.  None of its members is virtual.
+class ConcretePacketStream {
+ public:
+  void AppendPacket(Packet* new_packet);
+  const Packet* GetPacket(size_t packet_number) const;
+  size_t NumberOfPackets() const;
+  ...
+};
+
+// A mock packet stream class.  It inherits from no other, but defines
+// GetPacket() and NumberOfPackets().
+class MockPacketStream {
+ public:
+  MOCK_CONST_METHOD1(GetPacket, const Packet*(size_t packet_number));
+  MOCK_CONST_METHOD0(NumberOfPackets, size_t());
+  ...
+};
+```
+
+Note that the mock class doesn't define `AppendPacket()`, unlike the
+real class. That's fine as long as the test doesn't need to call it.
+
+Next, you need a way to say that you want to use
+`ConcretePacketStream` in production code, and use `MockPacketStream`
+in tests.  Since the functions are not virtual and the two classes are
+unrelated, you must specify your choice at _compile time_ (as opposed
+to run time).
+
+One way to do it is to templatize your code that needs to use a packet
+stream.  More specifically, you will give your code a template type
+argument for the type of the packet stream.  In production, you will
+instantiate your template with `ConcretePacketStream` as the type
+argument.  In tests, you will instantiate the same template with
+`MockPacketStream`.  For example, you may write:
+
+```
+template <class PacketStream>
+void CreateConnection(PacketStream* stream) { ... }
+
+template <class PacketStream>
+class PacketReader {
+ public:
+  void ReadPackets(PacketStream* stream, size_t packet_num);
+};
+```
+
+Then you can use `CreateConnection<ConcretePacketStream>()` and
+`PacketReader<ConcretePacketStream>` in production code, and use
+`CreateConnection<MockPacketStream>()` and
+`PacketReader<MockPacketStream>` in tests.
+
+```
+  MockPacketStream mock_stream;
+  EXPECT_CALL(mock_stream, ...)...;
+  .. set more expectations on mock_stream ...
+  PacketReader<MockPacketStream> reader(&mock_stream);
+  ... exercise reader ...
+```
+
+## Mocking Free Functions ##
+
+It's possible to use Google Mock to mock a free function (i.e. a
+C-style function or a static method).  You just need to rewrite your
+code to use an interface (abstract class).
+
+Instead of calling a free function (say, `OpenFile`) directly,
+introduce an interface for it and have a concrete subclass that calls
+the free function:
+
+```
+class FileInterface {
+ public:
+  ...
+  virtual bool Open(const char* path, const char* mode) = 0;
+};
+
+class File : public FileInterface {
+ public:
+  ...
+  virtual bool Open(const char* path, const char* mode) {
+    return OpenFile(path, mode);
+  }
+};
+```
+
+Your code should talk to `FileInterface` to open a file.  Now it's
+easy to mock out the function.
+
+This may seem much hassle, but in practice you often have multiple
+related functions that you can put in the same interface, so the
+per-function syntactic overhead will be much lower.
+
+If you are concerned about the performance overhead incurred by
+virtual functions, and profiling confirms your concern, you can
+combine this with the recipe for [mocking non-virtual methods](#Mocking_Nonvirtual_Methods.md).
+
+## The Nice, the Strict, and the Naggy ##
+
+If a mock method has no `EXPECT_CALL` spec but is called, Google Mock
+will print a warning about the "uninteresting call". The rationale is:
+
+  * New methods may be added to an interface after a test is written. We shouldn't fail a test just because a method it doesn't know about is called.
+  * However, this may also mean there's a bug in the test, so Google Mock shouldn't be silent either. If the user believes these calls are harmless, he can add an `EXPECT_CALL()` to suppress the warning.
+
+However, sometimes you may want to suppress all "uninteresting call"
+warnings, while sometimes you may want the opposite, i.e. to treat all
+of them as errors. Google Mock lets you make the decision on a
+per-mock-object basis.
+
+Suppose your test uses a mock class `MockFoo`:
+
+```
+TEST(...) {
+  MockFoo mock_foo;
+  EXPECT_CALL(mock_foo, DoThis());
+  ... code that uses mock_foo ...
+}
+```
+
+If a method of `mock_foo` other than `DoThis()` is called, it will be
+reported by Google Mock as a warning. However, if you rewrite your
+test to use `NiceMock<MockFoo>` instead, the warning will be gone,
+resulting in a cleaner test output:
+
+```
+using ::testing::NiceMock;
+
+TEST(...) {
+  NiceMock<MockFoo> mock_foo;
+  EXPECT_CALL(mock_foo, DoThis());
+  ... code that uses mock_foo ...
+}
+```
+
+`NiceMock<MockFoo>` is a subclass of `MockFoo`, so it can be used
+wherever `MockFoo` is accepted.
+
+It also works if `MockFoo`'s constructor takes some arguments, as
+`NiceMock<MockFoo>` "inherits" `MockFoo`'s constructors:
+
+```
+using ::testing::NiceMock;
+
+TEST(...) {
+  NiceMock<MockFoo> mock_foo(5, "hi");  // Calls MockFoo(5, "hi").
+  EXPECT_CALL(mock_foo, DoThis());
+  ... code that uses mock_foo ...
+}
+```
+
+The usage of `StrictMock` is similar, except that it makes all
+uninteresting calls failures:
+
+```
+using ::testing::StrictMock;
+
+TEST(...) {
+  StrictMock<MockFoo> mock_foo;
+  EXPECT_CALL(mock_foo, DoThis());
+  ... code that uses mock_foo ...
+
+  // The test will fail if a method of mock_foo other than DoThis()
+  // is called.
+}
+```
+
+There are some caveats though (I don't like them just as much as the
+next guy, but sadly they are side effects of C++'s limitations):
+
+  1. `NiceMock<MockFoo>` and `StrictMock<MockFoo>` only work for mock methods defined using the `MOCK_METHOD*` family of macros **directly** in the `MockFoo` class. If a mock method is defined in a **base class** of `MockFoo`, the "nice" or "strict" modifier may not affect it, depending on the compiler. In particular, nesting `NiceMock` and `StrictMock` (e.g. `NiceMock<StrictMock<MockFoo> >`) is **not** supported.
+  1. The constructors of the base mock (`MockFoo`) cannot have arguments passed by non-const reference, which happens to be banned by the [Google C++ style guide](http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml).
+  1. During the constructor or destructor of `MockFoo`, the mock object is _not_ nice or strict.  This may cause surprises if the constructor or destructor calls a mock method on `this` object. (This behavior, however, is consistent with C++'s general rule: if a constructor or destructor calls a virtual method of `this` object, that method is treated as non-virtual.  In other words, to the base class's constructor or destructor, `this` object behaves like an instance of the base class, not the derived class.  This rule is required for safety.  Otherwise a base constructor may use members of a derived class before they are initialized, or a base destructor may use members of a derived class after they have been destroyed.)
+
+Finally, you should be **very cautious** about when to use naggy or strict mocks, as they tend to make tests more brittle and harder to maintain. When you refactor your code without changing its externally visible behavior, ideally you should't need to update any tests. If your code interacts with a naggy mock, however, you may start to get spammed with warnings as the result of your change. Worse, if your code interacts with a strict mock, your tests may start to fail and you'll be forced to fix them. Our general recommendation is to use nice mocks (not yet the default) most of the time, use naggy mocks (the current default) when developing or debugging tests, and use strict mocks only as the last resort.
+
+## Simplifying the Interface without Breaking Existing Code ##
+
+Sometimes a method has a long list of arguments that is mostly
+uninteresting. For example,
+
+```
+class LogSink {
+ public:
+  ...
+  virtual void send(LogSeverity severity, const char* full_filename,
+                    const char* base_filename, int line,
+                    const struct tm* tm_time,
+                    const char* message, size_t message_len) = 0;
+};
+```
+
+This method's argument list is lengthy and hard to work with (let's
+say that the `message` argument is not even 0-terminated). If we mock
+it as is, using the mock will be awkward. If, however, we try to
+simplify this interface, we'll need to fix all clients depending on
+it, which is often infeasible.
+
+The trick is to re-dispatch the method in the mock class:
+
+```
+class ScopedMockLog : public LogSink {
+ public:
+  ...
+  virtual void send(LogSeverity severity, const char* full_filename,
+                    const char* base_filename, int line, const tm* tm_time,
+                    const char* message, size_t message_len) {
+    // We are only interested in the log severity, full file name, and
+    // log message.
+    Log(severity, full_filename, std::string(message, message_len));
+  }
+
+  // Implements the mock method:
+  //
+  //   void Log(LogSeverity severity,
+  //            const string& file_path,
+  //            const string& message);
+  MOCK_METHOD3(Log, void(LogSeverity severity, const string& file_path,
+                         const string& message));
+};
+```
+
+By defining a new mock method with a trimmed argument list, we make
+the mock class much more user-friendly.
+
+## Alternative to Mocking Concrete Classes ##
+
+Often you may find yourself using classes that don't implement
+interfaces. In order to test your code that uses such a class (let's
+call it `Concrete`), you may be tempted to make the methods of
+`Concrete` virtual and then mock it.
+
+Try not to do that.
+
+Making a non-virtual function virtual is a big decision. It creates an
+extension point where subclasses can tweak your class' behavior. This
+weakens your control on the class because now it's harder to maintain
+the class' invariants. You should make a function virtual only when
+there is a valid reason for a subclass to override it.
+
+Mocking concrete classes directly is problematic as it creates a tight
+coupling between the class and the tests - any small change in the
+class may invalidate your tests and make test maintenance a pain.
+
+To avoid such problems, many programmers have been practicing "coding
+to interfaces": instead of talking to the `Concrete` class, your code
+would define an interface and talk to it. Then you implement that
+interface as an adaptor on top of `Concrete`. In tests, you can easily
+mock that interface to observe how your code is doing.
+
+This technique incurs some overhead:
+
+  * You pay the cost of virtual function calls (usually not a problem).
+  * There is more abstraction for the programmers to learn.
+
+However, it can also bring significant benefits in addition to better
+testability:
+
+  * `Concrete`'s API may not fit your problem domain very well, as you may not be the only client it tries to serve. By designing your own interface, you have a chance to tailor it to your need - you may add higher-level functionalities, rename stuff, etc instead of just trimming the class. This allows you to write your code (user of the interface) in a more natural way, which means it will be more readable, more maintainable, and you'll be more productive.
+  * If `Concrete`'s implementation ever has to change, you don't have to rewrite everywhere it is used. Instead, you can absorb the change in your implementation of the interface, and your other code and tests will be insulated from this change.
+
+Some people worry that if everyone is practicing this technique, they
+will end up writing lots of redundant code. This concern is totally
+understandable. However, there are two reasons why it may not be the
+case:
+
+  * Different projects may need to use `Concrete` in different ways, so the best interfaces for them will be different. Therefore, each of them will have its own domain-specific interface on top of `Concrete`, and they will not be the same code.
+  * If enough projects want to use the same interface, they can always share it, just like they have been sharing `Concrete`. You can check in the interface and the adaptor somewhere near `Concrete` (perhaps in a `contrib` sub-directory) and let many projects use it.
+
+You need to weigh the pros and cons carefully for your particular
+problem, but I'd like to assure you that the Java community has been
+practicing this for a long time and it's a proven effective technique
+applicable in a wide variety of situations. :-)
+
+## Delegating Calls to a Fake ##
+
+Some times you have a non-trivial fake implementation of an
+interface. For example:
+
+```
+class Foo {
+ public:
+  virtual ~Foo() {}
+  virtual char DoThis(int n) = 0;
+  virtual void DoThat(const char* s, int* p) = 0;
+};
+
+class FakeFoo : public Foo {
+ public:
+  virtual char DoThis(int n) {
+    return (n > 0) ? '+' :
+        (n < 0) ? '-' : '0';
+  }
+
+  virtual void DoThat(const char* s, int* p) {
+    *p = strlen(s);
+  }
+};
+```
+
+Now you want to mock this interface such that you can set expectations
+on it. However, you also want to use `FakeFoo` for the default
+behavior, as duplicating it in the mock object is, well, a lot of
+work.
+
+When you define the mock class using Google Mock, you can have it
+delegate its default action to a fake class you already have, using
+this pattern:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+
+class MockFoo : public Foo {
+ public:
+  // Normal mock method definitions using Google Mock.
+  MOCK_METHOD1(DoThis, char(int n));
+  MOCK_METHOD2(DoThat, void(const char* s, int* p));
+
+  // Delegates the default actions of the methods to a FakeFoo object.
+  // This must be called *before* the custom ON_CALL() statements.
+  void DelegateToFake() {
+    ON_CALL(*this, DoThis(_))
+        .WillByDefault(Invoke(&fake_, &FakeFoo::DoThis));
+    ON_CALL(*this, DoThat(_, _))
+        .WillByDefault(Invoke(&fake_, &FakeFoo::DoThat));
+  }
+ private:
+  FakeFoo fake_;  // Keeps an instance of the fake in the mock.
+};
+```
+
+With that, you can use `MockFoo` in your tests as usual. Just remember
+that if you don't explicitly set an action in an `ON_CALL()` or
+`EXPECT_CALL()`, the fake will be called upon to do it:
+
+```
+using ::testing::_;
+
+TEST(AbcTest, Xyz) {
+  MockFoo foo;
+  foo.DelegateToFake(); // Enables the fake for delegation.
+
+  // Put your ON_CALL(foo, ...)s here, if any.
+
+  // No action specified, meaning to use the default action.
+  EXPECT_CALL(foo, DoThis(5));
+  EXPECT_CALL(foo, DoThat(_, _));
+
+  int n = 0;
+  EXPECT_EQ('+', foo.DoThis(5));  // FakeFoo::DoThis() is invoked.
+  foo.DoThat("Hi", &n);           // FakeFoo::DoThat() is invoked.
+  EXPECT_EQ(2, n);
+}
+```
+
+**Some tips:**
+
+  * If you want, you can still override the default action by providing your own `ON_CALL()` or using `.WillOnce()` / `.WillRepeatedly()` in `EXPECT_CALL()`.
+  * In `DelegateToFake()`, you only need to delegate the methods whose fake implementation you intend to use.
+  * The general technique discussed here works for overloaded methods, but you'll need to tell the compiler which version you mean. To disambiguate a mock function (the one you specify inside the parentheses of `ON_CALL()`), see the "Selecting Between Overloaded Functions" section on this page; to disambiguate a fake function (the one you place inside `Invoke()`), use a `static_cast` to specify the function's type. For instance, if class `Foo` has methods `char DoThis(int n)` and `bool DoThis(double x) const`, and you want to invoke the latter, you need to write `Invoke(&fake_, static_cast<bool (FakeFoo::*)(double) const>(&FakeFoo::DoThis))` instead of `Invoke(&fake_, &FakeFoo::DoThis)` (The strange-looking thing inside the angled brackets of `static_cast` is the type of a function pointer to the second `DoThis()` method.).
+  * Having to mix a mock and a fake is often a sign of something gone wrong. Perhaps you haven't got used to the interaction-based way of testing yet. Or perhaps your interface is taking on too many roles and should be split up. Therefore, **don't abuse this**. We would only recommend to do it as an intermediate step when you are refactoring your code.
+
+Regarding the tip on mixing a mock and a fake, here's an example on
+why it may be a bad sign: Suppose you have a class `System` for
+low-level system operations. In particular, it does file and I/O
+operations. And suppose you want to test how your code uses `System`
+to do I/O, and you just want the file operations to work normally. If
+you mock out the entire `System` class, you'll have to provide a fake
+implementation for the file operation part, which suggests that
+`System` is taking on too many roles.
+
+Instead, you can define a `FileOps` interface and an `IOOps` interface
+and split `System`'s functionalities into the two. Then you can mock
+`IOOps` without mocking `FileOps`.
+
+## Delegating Calls to a Real Object ##
+
+When using testing doubles (mocks, fakes, stubs, and etc), sometimes
+their behaviors will differ from those of the real objects. This
+difference could be either intentional (as in simulating an error such
+that you can test the error handling code) or unintentional. If your
+mocks have different behaviors than the real objects by mistake, you
+could end up with code that passes the tests but fails in production.
+
+You can use the _delegating-to-real_ technique to ensure that your
+mock has the same behavior as the real object while retaining the
+ability to validate calls. This technique is very similar to the
+delegating-to-fake technique, the difference being that we use a real
+object instead of a fake. Here's an example:
+
+```
+using ::testing::_;
+using ::testing::AtLeast;
+using ::testing::Invoke;
+
+class MockFoo : public Foo {
+ public:
+  MockFoo() {
+    // By default, all calls are delegated to the real object.
+    ON_CALL(*this, DoThis())
+        .WillByDefault(Invoke(&real_, &Foo::DoThis));
+    ON_CALL(*this, DoThat(_))
+        .WillByDefault(Invoke(&real_, &Foo::DoThat));
+    ...
+  }
+  MOCK_METHOD0(DoThis, ...);
+  MOCK_METHOD1(DoThat, ...);
+  ...
+ private:
+  Foo real_;
+};
+...
+
+  MockFoo mock;
+
+  EXPECT_CALL(mock, DoThis())
+      .Times(3);
+  EXPECT_CALL(mock, DoThat("Hi"))
+      .Times(AtLeast(1));
+  ... use mock in test ...
+```
+
+With this, Google Mock will verify that your code made the right calls
+(with the right arguments, in the right order, called the right number
+of times, etc), and a real object will answer the calls (so the
+behavior will be the same as in production). This gives you the best
+of both worlds.
+
+## Delegating Calls to a Parent Class ##
+
+Ideally, you should code to interfaces, whose methods are all pure
+virtual. In reality, sometimes you do need to mock a virtual method
+that is not pure (i.e, it already has an implementation). For example:
+
+```
+class Foo {
+ public:
+  virtual ~Foo();
+
+  virtual void Pure(int n) = 0;
+  virtual int Concrete(const char* str) { ... }
+};
+
+class MockFoo : public Foo {
+ public:
+  // Mocking a pure method.
+  MOCK_METHOD1(Pure, void(int n));
+  // Mocking a concrete method.  Foo::Concrete() is shadowed.
+  MOCK_METHOD1(Concrete, int(const char* str));
+};
+```
+
+Sometimes you may want to call `Foo::Concrete()` instead of
+`MockFoo::Concrete()`. Perhaps you want to do it as part of a stub
+action, or perhaps your test doesn't need to mock `Concrete()` at all
+(but it would be oh-so painful to have to define a new mock class
+whenever you don't need to mock one of its methods).
+
+The trick is to leave a back door in your mock class for accessing the
+real methods in the base class:
+
+```
+class MockFoo : public Foo {
+ public:
+  // Mocking a pure method.
+  MOCK_METHOD1(Pure, void(int n));
+  // Mocking a concrete method.  Foo::Concrete() is shadowed.
+  MOCK_METHOD1(Concrete, int(const char* str));
+
+  // Use this to call Concrete() defined in Foo.
+  int FooConcrete(const char* str) { return Foo::Concrete(str); }
+};
+```
+
+Now, you can call `Foo::Concrete()` inside an action by:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+...
+  EXPECT_CALL(foo, Concrete(_))
+      .WillOnce(Invoke(&foo, &MockFoo::FooConcrete));
+```
+
+or tell the mock object that you don't want to mock `Concrete()`:
+
+```
+using ::testing::Invoke;
+...
+  ON_CALL(foo, Concrete(_))
+      .WillByDefault(Invoke(&foo, &MockFoo::FooConcrete));
+```
+
+(Why don't we just write `Invoke(&foo, &Foo::Concrete)`? If you do
+that, `MockFoo::Concrete()` will be called (and cause an infinite
+recursion) since `Foo::Concrete()` is virtual. That's just how C++
+works.)
+
+# Using Matchers #
+
+## Matching Argument Values Exactly ##
+
+You can specify exactly which arguments a mock method is expecting:
+
+```
+using ::testing::Return;
+...
+  EXPECT_CALL(foo, DoThis(5))
+      .WillOnce(Return('a'));
+  EXPECT_CALL(foo, DoThat("Hello", bar));
+```
+
+## Using Simple Matchers ##
+
+You can use matchers to match arguments that have a certain property:
+
+```
+using ::testing::Ge;
+using ::testing::NotNull;
+using ::testing::Return;
+...
+  EXPECT_CALL(foo, DoThis(Ge(5)))  // The argument must be >= 5.
+      .WillOnce(Return('a'));
+  EXPECT_CALL(foo, DoThat("Hello", NotNull()));
+  // The second argument must not be NULL.
+```
+
+A frequently used matcher is `_`, which matches anything:
+
+```
+using ::testing::_;
+using ::testing::NotNull;
+...
+  EXPECT_CALL(foo, DoThat(_, NotNull()));
+```
+
+## Combining Matchers ##
+
+You can build complex matchers from existing ones using `AllOf()`,
+`AnyOf()`, and `Not()`:
+
+```
+using ::testing::AllOf;
+using ::testing::Gt;
+using ::testing::HasSubstr;
+using ::testing::Ne;
+using ::testing::Not;
+...
+  // The argument must be > 5 and != 10.
+  EXPECT_CALL(foo, DoThis(AllOf(Gt(5),
+                                Ne(10))));
+
+  // The first argument must not contain sub-string "blah".
+  EXPECT_CALL(foo, DoThat(Not(HasSubstr("blah")),
+                          NULL));
+```
+
+## Casting Matchers ##
+
+Google Mock matchers are statically typed, meaning that the compiler
+can catch your mistake if you use a matcher of the wrong type (for
+example, if you use `Eq(5)` to match a `string` argument). Good for
+you!
+
+Sometimes, however, you know what you're doing and want the compiler
+to give you some slack. One example is that you have a matcher for
+`long` and the argument you want to match is `int`. While the two
+types aren't exactly the same, there is nothing really wrong with
+using a `Matcher<long>` to match an `int` - after all, we can first
+convert the `int` argument to a `long` before giving it to the
+matcher.
+
+To support this need, Google Mock gives you the
+`SafeMatcherCast<T>(m)` function. It casts a matcher `m` to type
+`Matcher<T>`. To ensure safety, Google Mock checks that (let `U` be the
+type `m` accepts):
+
+  1. Type `T` can be implicitly cast to type `U`;
+  1. When both `T` and `U` are built-in arithmetic types (`bool`, integers, and floating-point numbers), the conversion from `T` to `U` is not lossy (in other words, any value representable by `T` can also be represented by `U`); and
+  1. When `U` is a reference, `T` must also be a reference (as the underlying matcher may be interested in the address of the `U` value).
+
+The code won't compile if any of these conditions isn't met.
+
+Here's one example:
+
+```
+using ::testing::SafeMatcherCast;
+
+// A base class and a child class.
+class Base { ... };
+class Derived : public Base { ... };
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD1(DoThis, void(Derived* derived));
+};
+...
+
+  MockFoo foo;
+  // m is a Matcher<Base*> we got from somewhere.
+  EXPECT_CALL(foo, DoThis(SafeMatcherCast<Derived*>(m)));
+```
+
+If you find `SafeMatcherCast<T>(m)` too limiting, you can use a similar
+function `MatcherCast<T>(m)`. The difference is that `MatcherCast` works
+as long as you can `static_cast` type `T` to type `U`.
+
+`MatcherCast` essentially lets you bypass C++'s type system
+(`static_cast` isn't always safe as it could throw away information,
+for example), so be careful not to misuse/abuse it.
+
+## Selecting Between Overloaded Functions ##
+
+If you expect an overloaded function to be called, the compiler may
+need some help on which overloaded version it is.
+
+To disambiguate functions overloaded on the const-ness of this object,
+use the `Const()` argument wrapper.
+
+```
+using ::testing::ReturnRef;
+
+class MockFoo : public Foo {
+  ...
+  MOCK_METHOD0(GetBar, Bar&());
+  MOCK_CONST_METHOD0(GetBar, const Bar&());
+};
+...
+
+  MockFoo foo;
+  Bar bar1, bar2;
+  EXPECT_CALL(foo, GetBar())         // The non-const GetBar().
+      .WillOnce(ReturnRef(bar1));
+  EXPECT_CALL(Const(foo), GetBar())  // The const GetBar().
+      .WillOnce(ReturnRef(bar2));
+```
+
+(`Const()` is defined by Google Mock and returns a `const` reference
+to its argument.)
+
+To disambiguate overloaded functions with the same number of arguments
+but different argument types, you may need to specify the exact type
+of a matcher, either by wrapping your matcher in `Matcher<type>()`, or
+using a matcher whose type is fixed (`TypedEq<type>`, `An<type>()`,
+etc):
+
+```
+using ::testing::An;
+using ::testing::Lt;
+using ::testing::Matcher;
+using ::testing::TypedEq;
+
+class MockPrinter : public Printer {
+ public:
+  MOCK_METHOD1(Print, void(int n));
+  MOCK_METHOD1(Print, void(char c));
+};
+
+TEST(PrinterTest, Print) {
+  MockPrinter printer;
+
+  EXPECT_CALL(printer, Print(An<int>()));            // void Print(int);
+  EXPECT_CALL(printer, Print(Matcher<int>(Lt(5))));  // void Print(int);
+  EXPECT_CALL(printer, Print(TypedEq<char>('a')));   // void Print(char);
+
+  printer.Print(3);
+  printer.Print(6);
+  printer.Print('a');
+}
+```
+
+## Performing Different Actions Based on the Arguments ##
+
+When a mock method is called, the _last_ matching expectation that's
+still active will be selected (think "newer overrides older"). So, you
+can make a method do different things depending on its argument values
+like this:
+
+```
+using ::testing::_;
+using ::testing::Lt;
+using ::testing::Return;
+...
+  // The default case.
+  EXPECT_CALL(foo, DoThis(_))
+      .WillRepeatedly(Return('b'));
+
+  // The more specific case.
+  EXPECT_CALL(foo, DoThis(Lt(5)))
+      .WillRepeatedly(Return('a'));
+```
+
+Now, if `foo.DoThis()` is called with a value less than 5, `'a'` will
+be returned; otherwise `'b'` will be returned.
+
+## Matching Multiple Arguments as a Whole ##
+
+Sometimes it's not enough to match the arguments individually. For
+example, we may want to say that the first argument must be less than
+the second argument. The `With()` clause allows us to match
+all arguments of a mock function as a whole. For example,
+
+```
+using ::testing::_;
+using ::testing::Lt;
+using ::testing::Ne;
+...
+  EXPECT_CALL(foo, InRange(Ne(0), _))
+      .With(Lt());
+```
+
+says that the first argument of `InRange()` must not be 0, and must be
+less than the second argument.
+
+The expression inside `With()` must be a matcher of type
+`Matcher<tr1::tuple<A1, ..., An> >`, where `A1`, ..., `An` are the
+types of the function arguments.
+
+You can also write `AllArgs(m)` instead of `m` inside `.With()`. The
+two forms are equivalent, but `.With(AllArgs(Lt()))` is more readable
+than `.With(Lt())`.
+
+You can use `Args<k1, ..., kn>(m)` to match the `n` selected arguments
+(as a tuple) against `m`. For example,
+
+```
+using ::testing::_;
+using ::testing::AllOf;
+using ::testing::Args;
+using ::testing::Lt;
+...
+  EXPECT_CALL(foo, Blah(_, _, _))
+      .With(AllOf(Args<0, 1>(Lt()), Args<1, 2>(Lt())));
+```
+
+says that `Blah()` will be called with arguments `x`, `y`, and `z` where
+`x < y < z`.
+
+As a convenience and example, Google Mock provides some matchers for
+2-tuples, including the `Lt()` matcher above. See the [CheatSheet](V1_7_CheatSheet.md) for
+the complete list.
+
+Note that if you want to pass the arguments to a predicate of your own
+(e.g. `.With(Args<0, 1>(Truly(&MyPredicate)))`), that predicate MUST be
+written to take a `tr1::tuple` as its argument; Google Mock will pass the `n`
+selected arguments as _one_ single tuple to the predicate.
+
+## Using Matchers as Predicates ##
+
+Have you noticed that a matcher is just a fancy predicate that also
+knows how to describe itself? Many existing algorithms take predicates
+as arguments (e.g. those defined in STL's `<algorithm>` header), and
+it would be a shame if Google Mock matchers are not allowed to
+participate.
+
+Luckily, you can use a matcher where a unary predicate functor is
+expected by wrapping it inside the `Matches()` function. For example,
+
+```
+#include <algorithm>
+#include <vector>
+
+std::vector<int> v;
+...
+// How many elements in v are >= 10?
+const int count = count_if(v.begin(), v.end(), Matches(Ge(10)));
+```
+
+Since you can build complex matchers from simpler ones easily using
+Google Mock, this gives you a way to conveniently construct composite
+predicates (doing the same using STL's `<functional>` header is just
+painful). For example, here's a predicate that's satisfied by any
+number that is >= 0, <= 100, and != 50:
+
+```
+Matches(AllOf(Ge(0), Le(100), Ne(50)))
+```
+
+## Using Matchers in Google Test Assertions ##
+
+Since matchers are basically predicates that also know how to describe
+themselves, there is a way to take advantage of them in
+[Google Test](http://code.google.com/p/googletest/) assertions. It's
+called `ASSERT_THAT` and `EXPECT_THAT`:
+
+```
+  ASSERT_THAT(value, matcher);  // Asserts that value matches matcher.
+  EXPECT_THAT(value, matcher);  // The non-fatal version.
+```
+
+For example, in a Google Test test you can write:
+
+```
+#include "gmock/gmock.h"
+
+using ::testing::AllOf;
+using ::testing::Ge;
+using ::testing::Le;
+using ::testing::MatchesRegex;
+using ::testing::StartsWith;
+...
+
+  EXPECT_THAT(Foo(), StartsWith("Hello"));
+  EXPECT_THAT(Bar(), MatchesRegex("Line \\d+"));
+  ASSERT_THAT(Baz(), AllOf(Ge(5), Le(10)));
+```
+
+which (as you can probably guess) executes `Foo()`, `Bar()`, and
+`Baz()`, and verifies that:
+
+  * `Foo()` returns a string that starts with `"Hello"`.
+  * `Bar()` returns a string that matches regular expression `"Line \\d+"`.
+  * `Baz()` returns a number in the range [5, 10].
+
+The nice thing about these macros is that _they read like
+English_. They generate informative messages too. For example, if the
+first `EXPECT_THAT()` above fails, the message will be something like:
+
+```
+Value of: Foo()
+  Actual: "Hi, world!"
+Expected: starts with "Hello"
+```
+
+**Credit:** The idea of `(ASSERT|EXPECT)_THAT` was stolen from the
+[Hamcrest](http://code.google.com/p/hamcrest/) project, which adds
+`assertThat()` to JUnit.
+
+## Using Predicates as Matchers ##
+
+Google Mock provides a built-in set of matchers. In case you find them
+lacking, you can use an arbitray unary predicate function or functor
+as a matcher - as long as the predicate accepts a value of the type
+you want. You do this by wrapping the predicate inside the `Truly()`
+function, for example:
+
+```
+using ::testing::Truly;
+
+int IsEven(int n) { return (n % 2) == 0 ? 1 : 0; }
+...
+
+  // Bar() must be called with an even number.
+  EXPECT_CALL(foo, Bar(Truly(IsEven)));
+```
+
+Note that the predicate function / functor doesn't have to return
+`bool`. It works as long as the return value can be used as the
+condition in statement `if (condition) ...`.
+
+## Matching Arguments that Are Not Copyable ##
+
+When you do an `EXPECT_CALL(mock_obj, Foo(bar))`, Google Mock saves
+away a copy of `bar`. When `Foo()` is called later, Google Mock
+compares the argument to `Foo()` with the saved copy of `bar`. This
+way, you don't need to worry about `bar` being modified or destroyed
+after the `EXPECT_CALL()` is executed. The same is true when you use
+matchers like `Eq(bar)`, `Le(bar)`, and so on.
+
+But what if `bar` cannot be copied (i.e. has no copy constructor)? You
+could define your own matcher function and use it with `Truly()`, as
+the previous couple of recipes have shown. Or, you may be able to get
+away from it if you can guarantee that `bar` won't be changed after
+the `EXPECT_CALL()` is executed. Just tell Google Mock that it should
+save a reference to `bar`, instead of a copy of it. Here's how:
+
+```
+using ::testing::Eq;
+using ::testing::ByRef;
+using ::testing::Lt;
+...
+  // Expects that Foo()'s argument == bar.
+  EXPECT_CALL(mock_obj, Foo(Eq(ByRef(bar))));
+
+  // Expects that Foo()'s argument < bar.
+  EXPECT_CALL(mock_obj, Foo(Lt(ByRef(bar))));
+```
+
+Remember: if you do this, don't change `bar` after the
+`EXPECT_CALL()`, or the result is undefined.
+
+## Validating a Member of an Object ##
+
+Often a mock function takes a reference to object as an argument. When
+matching the argument, you may not want to compare the entire object
+against a fixed object, as that may be over-specification. Instead,
+you may need to validate a certain member variable or the result of a
+certain getter method of the object. You can do this with `Field()`
+and `Property()`. More specifically,
+
+```
+Field(&Foo::bar, m)
+```
+
+is a matcher that matches a `Foo` object whose `bar` member variable
+satisfies matcher `m`.
+
+```
+Property(&Foo::baz, m)
+```
+
+is a matcher that matches a `Foo` object whose `baz()` method returns
+a value that satisfies matcher `m`.
+
+For example:
+
+> | `Field(&Foo::number, Ge(3))` | Matches `x` where `x.number >= 3`. |
+|:-----------------------------|:-----------------------------------|
+> | `Property(&Foo::name, StartsWith("John "))` | Matches `x` where `x.name()` starts with `"John "`. |
+
+Note that in `Property(&Foo::baz, ...)`, method `baz()` must take no
+argument and be declared as `const`.
+
+BTW, `Field()` and `Property()` can also match plain pointers to
+objects. For instance,
+
+```
+Field(&Foo::number, Ge(3))
+```
+
+matches a plain pointer `p` where `p->number >= 3`. If `p` is `NULL`,
+the match will always fail regardless of the inner matcher.
+
+What if you want to validate more than one members at the same time?
+Remember that there is `AllOf()`.
+
+## Validating the Value Pointed to by a Pointer Argument ##
+
+C++ functions often take pointers as arguments. You can use matchers
+like `IsNull()`, `NotNull()`, and other comparison matchers to match a
+pointer, but what if you want to make sure the value _pointed to_ by
+the pointer, instead of the pointer itself, has a certain property?
+Well, you can use the `Pointee(m)` matcher.
+
+`Pointee(m)` matches a pointer iff `m` matches the value the pointer
+points to. For example:
+
+```
+using ::testing::Ge;
+using ::testing::Pointee;
+...
+  EXPECT_CALL(foo, Bar(Pointee(Ge(3))));
+```
+
+expects `foo.Bar()` to be called with a pointer that points to a value
+greater than or equal to 3.
+
+One nice thing about `Pointee()` is that it treats a `NULL` pointer as
+a match failure, so you can write `Pointee(m)` instead of
+
+```
+  AllOf(NotNull(), Pointee(m))
+```
+
+without worrying that a `NULL` pointer will crash your test.
+
+Also, did we tell you that `Pointee()` works with both raw pointers
+**and** smart pointers (`linked_ptr`, `shared_ptr`, `scoped_ptr`, and
+etc)?
+
+What if you have a pointer to pointer? You guessed it - you can use
+nested `Pointee()` to probe deeper inside the value. For example,
+`Pointee(Pointee(Lt(3)))` matches a pointer that points to a pointer
+that points to a number less than 3 (what a mouthful...).
+
+## Testing a Certain Property of an Object ##
+
+Sometimes you want to specify that an object argument has a certain
+property, but there is no existing matcher that does this. If you want
+good error messages, you should define a matcher. If you want to do it
+quick and dirty, you could get away with writing an ordinary function.
+
+Let's say you have a mock function that takes an object of type `Foo`,
+which has an `int bar()` method and an `int baz()` method, and you
+want to constrain that the argument's `bar()` value plus its `baz()`
+value is a given number. Here's how you can define a matcher to do it:
+
+```
+using ::testing::MatcherInterface;
+using ::testing::MatchResultListener;
+
+class BarPlusBazEqMatcher : public MatcherInterface<const Foo&> {
+ public:
+  explicit BarPlusBazEqMatcher(int expected_sum)
+      : expected_sum_(expected_sum) {}
+
+  virtual bool MatchAndExplain(const Foo& foo,
+                               MatchResultListener* listener) const {
+    return (foo.bar() + foo.baz()) == expected_sum_;
+  }
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "bar() + baz() equals " << expected_sum_;
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "bar() + baz() does not equal " << expected_sum_;
+  }
+ private:
+  const int expected_sum_;
+};
+
+inline Matcher<const Foo&> BarPlusBazEq(int expected_sum) {
+  return MakeMatcher(new BarPlusBazEqMatcher(expected_sum));
+}
+
+...
+
+  EXPECT_CALL(..., DoThis(BarPlusBazEq(5)))...;
+```
+
+## Matching Containers ##
+
+Sometimes an STL container (e.g. list, vector, map, ...) is passed to
+a mock function and you may want to validate it. Since most STL
+containers support the `==` operator, you can write
+`Eq(expected_container)` or simply `expected_container` to match a
+container exactly.
+
+Sometimes, though, you may want to be more flexible (for example, the
+first element must be an exact match, but the second element can be
+any positive number, and so on). Also, containers used in tests often
+have a small number of elements, and having to define the expected
+container out-of-line is a bit of a hassle.
+
+You can use the `ElementsAre()` or `UnorderedElementsAre()` matcher in
+such cases:
+
+```
+using ::testing::_;
+using ::testing::ElementsAre;
+using ::testing::Gt;
+...
+
+  MOCK_METHOD1(Foo, void(const vector<int>& numbers));
+...
+
+  EXPECT_CALL(mock, Foo(ElementsAre(1, Gt(0), _, 5)));
+```
+
+The above matcher says that the container must have 4 elements, which
+must be 1, greater than 0, anything, and 5 respectively.
+
+If you instead write:
+
+```
+using ::testing::_;
+using ::testing::Gt;
+using ::testing::UnorderedElementsAre;
+...
+
+  MOCK_METHOD1(Foo, void(const vector<int>& numbers));
+...
+
+  EXPECT_CALL(mock, Foo(UnorderedElementsAre(1, Gt(0), _, 5)));
+```
+
+It means that the container must have 4 elements, which under some
+permutation must be 1, greater than 0, anything, and 5 respectively.
+
+`ElementsAre()` and `UnorderedElementsAre()` are overloaded to take 0
+to 10 arguments. If more are needed, you can place them in a C-style
+array and use `ElementsAreArray()` or `UnorderedElementsAreArray()`
+instead:
+
+```
+using ::testing::ElementsAreArray;
+...
+
+  // ElementsAreArray accepts an array of element values.
+  const int expected_vector1[] = { 1, 5, 2, 4, ... };
+  EXPECT_CALL(mock, Foo(ElementsAreArray(expected_vector1)));
+
+  // Or, an array of element matchers.
+  Matcher<int> expected_vector2 = { 1, Gt(2), _, 3, ... };
+  EXPECT_CALL(mock, Foo(ElementsAreArray(expected_vector2)));
+```
+
+In case the array needs to be dynamically created (and therefore the
+array size cannot be inferred by the compiler), you can give
+`ElementsAreArray()` an additional argument to specify the array size:
+
+```
+using ::testing::ElementsAreArray;
+...
+  int* const expected_vector3 = new int[count];
+  ... fill expected_vector3 with values ...
+  EXPECT_CALL(mock, Foo(ElementsAreArray(expected_vector3, count)));
+```
+
+**Tips:**
+
+  * `ElementsAre*()` can be used to match _any_ container that implements the STL iterator pattern (i.e. it has a `const_iterator` type and supports `begin()/end()`), not just the ones defined in STL. It will even work with container types yet to be written - as long as they follows the above pattern.
+  * You can use nested `ElementsAre*()` to match nested (multi-dimensional) containers.
+  * If the container is passed by pointer instead of by reference, just write `Pointee(ElementsAre*(...))`.
+  * The order of elements _matters_ for `ElementsAre*()`. Therefore don't use it with containers whose element order is undefined (e.g. `hash_map`).
+
+## Sharing Matchers ##
+
+Under the hood, a Google Mock matcher object consists of a pointer to
+a ref-counted implementation object. Copying matchers is allowed and
+very efficient, as only the pointer is copied. When the last matcher
+that references the implementation object dies, the implementation
+object will be deleted.
+
+Therefore, if you have some complex matcher that you want to use again
+and again, there is no need to build it everytime. Just assign it to a
+matcher variable and use that variable repeatedly! For example,
+
+```
+  Matcher<int> in_range = AllOf(Gt(5), Le(10));
+  ... use in_range as a matcher in multiple EXPECT_CALLs ...
+```
+
+# Setting Expectations #
+
+## Knowing When to Expect ##
+
+`ON_CALL` is likely the single most under-utilized construct in Google Mock.
+
+There are basically two constructs for defining the behavior of a mock object: `ON_CALL` and `EXPECT_CALL`. The difference? `ON_CALL` defines what happens when a mock method is called, but _doesn't imply any expectation on the method being called._ `EXPECT_CALL` not only defines the behavior, but also sets an expectation that _the method will be called with the given arguments, for the given number of times_ (and _in the given order_ when you specify the order too).
+
+Since `EXPECT_CALL` does more, isn't it better than `ON_CALL`? Not really. Every `EXPECT_CALL` adds a constraint on the behavior of the code under test. Having more constraints than necessary is _baaad_ - even worse than not having enough constraints.
+
+This may be counter-intuitive. How could tests that verify more be worse than tests that verify less? Isn't verification the whole point of tests?
+
+The answer, lies in _what_ a test should verify. **A good test verifies the contract of the code.** If a test over-specifies, it doesn't leave enough freedom to the implementation. As a result, changing the implementation without breaking the contract (e.g. refactoring and optimization), which should be perfectly fine to do, can break such tests. Then you have to spend time fixing them, only to see them broken again the next time the implementation is changed.
+
+Keep in mind that one doesn't have to verify more than one property in one test. In fact, **it's a good style to verify only one thing in one test.** If you do that, a bug will likely break only one or two tests instead of dozens (which case would you rather debug?). If you are also in the habit of giving tests descriptive names that tell what they verify, you can often easily guess what's wrong just from the test log itself.
+
+So use `ON_CALL` by default, and only use `EXPECT_CALL` when you actually intend to verify that the call is made. For example, you may have a bunch of `ON_CALL`s in your test fixture to set the common mock behavior shared by all tests in the same group, and write (scarcely) different `EXPECT_CALL`s in different `TEST_F`s to verify different aspects of the code's behavior. Compared with the style where each `TEST` has many `EXPECT_CALL`s, this leads to tests that are more resilient to implementational changes (and thus less likely to require maintenance) and makes the intent of the tests more obvious (so they are easier to maintain when you do need to maintain them).
+
+## Ignoring Uninteresting Calls ##
+
+If you are not interested in how a mock method is called, just don't
+say anything about it. In this case, if the method is ever called,
+Google Mock will perform its default action to allow the test program
+to continue. If you are not happy with the default action taken by
+Google Mock, you can override it using `DefaultValue<T>::Set()`
+(described later in this document) or `ON_CALL()`.
+
+Please note that once you expressed interest in a particular mock
+method (via `EXPECT_CALL()`), all invocations to it must match some
+expectation. If this function is called but the arguments don't match
+any `EXPECT_CALL()` statement, it will be an error.
+
+## Disallowing Unexpected Calls ##
+
+If a mock method shouldn't be called at all, explicitly say so:
+
+```
+using ::testing::_;
+...
+  EXPECT_CALL(foo, Bar(_))
+      .Times(0);
+```
+
+If some calls to the method are allowed, but the rest are not, just
+list all the expected calls:
+
+```
+using ::testing::AnyNumber;
+using ::testing::Gt;
+...
+  EXPECT_CALL(foo, Bar(5));
+  EXPECT_CALL(foo, Bar(Gt(10)))
+      .Times(AnyNumber());
+```
+
+A call to `foo.Bar()` that doesn't match any of the `EXPECT_CALL()`
+statements will be an error.
+
+## Expecting Ordered Calls ##
+
+Although an `EXPECT_CALL()` statement defined earlier takes precedence
+when Google Mock tries to match a function call with an expectation,
+by default calls don't have to happen in the order `EXPECT_CALL()`
+statements are written. For example, if the arguments match the
+matchers in the third `EXPECT_CALL()`, but not those in the first two,
+then the third expectation will be used.
+
+If you would rather have all calls occur in the order of the
+expectations, put the `EXPECT_CALL()` statements in a block where you
+define a variable of type `InSequence`:
+
+```
+  using ::testing::_;
+  using ::testing::InSequence;
+
+  {
+    InSequence s;
+
+    EXPECT_CALL(foo, DoThis(5));
+    EXPECT_CALL(bar, DoThat(_))
+        .Times(2);
+    EXPECT_CALL(foo, DoThis(6));
+  }
+```
+
+In this example, we expect a call to `foo.DoThis(5)`, followed by two
+calls to `bar.DoThat()` where the argument can be anything, which are
+in turn followed by a call to `foo.DoThis(6)`. If a call occurred
+out-of-order, Google Mock will report an error.
+
+## Expecting Partially Ordered Calls ##
+
+Sometimes requiring everything to occur in a predetermined order can
+lead to brittle tests. For example, we may care about `A` occurring
+before both `B` and `C`, but aren't interested in the relative order
+of `B` and `C`. In this case, the test should reflect our real intent,
+instead of being overly constraining.
+
+Google Mock allows you to impose an arbitrary DAG (directed acyclic
+graph) on the calls. One way to express the DAG is to use the
+[After](http://code.google.com/p/googlemock/wiki/V1_7_CheatSheet#The_After_Clause) clause of `EXPECT_CALL`.
+
+Another way is via the `InSequence()` clause (not the same as the
+`InSequence` class), which we borrowed from jMock 2. It's less
+flexible than `After()`, but more convenient when you have long chains
+of sequential calls, as it doesn't require you to come up with
+different names for the expectations in the chains.  Here's how it
+works:
+
+If we view `EXPECT_CALL()` statements as nodes in a graph, and add an
+edge from node A to node B wherever A must occur before B, we can get
+a DAG. We use the term "sequence" to mean a directed path in this
+DAG. Now, if we decompose the DAG into sequences, we just need to know
+which sequences each `EXPECT_CALL()` belongs to in order to be able to
+reconstruct the orginal DAG.
+
+So, to specify the partial order on the expectations we need to do two
+things: first to define some `Sequence` objects, and then for each
+`EXPECT_CALL()` say which `Sequence` objects it is part
+of. Expectations in the same sequence must occur in the order they are
+written. For example,
+
+```
+  using ::testing::Sequence;
+
+  Sequence s1, s2;
+
+  EXPECT_CALL(foo, A())
+      .InSequence(s1, s2);
+  EXPECT_CALL(bar, B())
+      .InSequence(s1);
+  EXPECT_CALL(bar, C())
+      .InSequence(s2);
+  EXPECT_CALL(foo, D())
+      .InSequence(s2);
+```
+
+specifies the following DAG (where `s1` is `A -> B`, and `s2` is `A ->
+C -> D`):
+
+```
+       +---> B
+       |
+  A ---|
+       |
+       +---> C ---> D
+```
+
+This means that A must occur before B and C, and C must occur before
+D. There's no restriction about the order other than these.
+
+## Controlling When an Expectation Retires ##
+
+When a mock method is called, Google Mock only consider expectations
+that are still active. An expectation is active when created, and
+becomes inactive (aka _retires_) when a call that has to occur later
+has occurred. For example, in
+
+```
+  using ::testing::_;
+  using ::testing::Sequence;
+
+  Sequence s1, s2;
+
+  EXPECT_CALL(log, Log(WARNING, _, "File too large."))     // #1
+      .Times(AnyNumber())
+      .InSequence(s1, s2);
+  EXPECT_CALL(log, Log(WARNING, _, "Data set is empty."))  // #2
+      .InSequence(s1);
+  EXPECT_CALL(log, Log(WARNING, _, "User not found."))     // #3
+      .InSequence(s2);
+```
+
+as soon as either #2 or #3 is matched, #1 will retire. If a warning
+`"File too large."` is logged after this, it will be an error.
+
+Note that an expectation doesn't retire automatically when it's
+saturated. For example,
+
+```
+using ::testing::_;
+...
+  EXPECT_CALL(log, Log(WARNING, _, _));                  // #1
+  EXPECT_CALL(log, Log(WARNING, _, "File too large."));  // #2
+```
+
+says that there will be exactly one warning with the message `"File
+too large."`. If the second warning contains this message too, #2 will
+match again and result in an upper-bound-violated error.
+
+If this is not what you want, you can ask an expectation to retire as
+soon as it becomes saturated:
+
+```
+using ::testing::_;
+...
+  EXPECT_CALL(log, Log(WARNING, _, _));                 // #1
+  EXPECT_CALL(log, Log(WARNING, _, "File too large."))  // #2
+      .RetiresOnSaturation();
+```
+
+Here #2 can be used only once, so if you have two warnings with the
+message `"File too large."`, the first will match #2 and the second
+will match #1 - there will be no error.
+
+# Using Actions #
+
+## Returning References from Mock Methods ##
+
+If a mock function's return type is a reference, you need to use
+`ReturnRef()` instead of `Return()` to return a result:
+
+```
+using ::testing::ReturnRef;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD0(GetBar, Bar&());
+};
+...
+
+  MockFoo foo;
+  Bar bar;
+  EXPECT_CALL(foo, GetBar())
+      .WillOnce(ReturnRef(bar));
+```
+
+## Returning Live Values from Mock Methods ##
+
+The `Return(x)` action saves a copy of `x` when the action is
+_created_, and always returns the same value whenever it's
+executed. Sometimes you may want to instead return the _live_ value of
+`x` (i.e. its value at the time when the action is _executed_.).
+
+If the mock function's return type is a reference, you can do it using
+`ReturnRef(x)`, as shown in the previous recipe ("Returning References
+from Mock Methods"). However, Google Mock doesn't let you use
+`ReturnRef()` in a mock function whose return type is not a reference,
+as doing that usually indicates a user error. So, what shall you do?
+
+You may be tempted to try `ByRef()`:
+
+```
+using testing::ByRef;
+using testing::Return;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD0(GetValue, int());
+};
+...
+  int x = 0;
+  MockFoo foo;
+  EXPECT_CALL(foo, GetValue())
+      .WillRepeatedly(Return(ByRef(x)));
+  x = 42;
+  EXPECT_EQ(42, foo.GetValue());
+```
+
+Unfortunately, it doesn't work here. The above code will fail with error:
+
+```
+Value of: foo.GetValue()
+  Actual: 0
+Expected: 42
+```
+
+The reason is that `Return(value)` converts `value` to the actual
+return type of the mock function at the time when the action is
+_created_, not when it is _executed_. (This behavior was chosen for
+the action to be safe when `value` is a proxy object that references
+some temporary objects.) As a result, `ByRef(x)` is converted to an
+`int` value (instead of a `const int&`) when the expectation is set,
+and `Return(ByRef(x))` will always return 0.
+
+`ReturnPointee(pointer)` was provided to solve this problem
+specifically. It returns the value pointed to by `pointer` at the time
+the action is _executed_:
+
+```
+using testing::ReturnPointee;
+...
+  int x = 0;
+  MockFoo foo;
+  EXPECT_CALL(foo, GetValue())
+      .WillRepeatedly(ReturnPointee(&x));  // Note the & here.
+  x = 42;
+  EXPECT_EQ(42, foo.GetValue());  // This will succeed now.
+```
+
+## Combining Actions ##
+
+Want to do more than one thing when a function is called? That's
+fine. `DoAll()` allow you to do sequence of actions every time. Only
+the return value of the last action in the sequence will be used.
+
+```
+using ::testing::DoAll;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD1(Bar, bool(int n));
+};
+...
+
+  EXPECT_CALL(foo, Bar(_))
+      .WillOnce(DoAll(action_1,
+                      action_2,
+                      ...
+                      action_n));
+```
+
+## Mocking Side Effects ##
+
+Sometimes a method exhibits its effect not via returning a value but
+via side effects. For example, it may change some global state or
+modify an output argument. To mock side effects, in general you can
+define your own action by implementing `::testing::ActionInterface`.
+
+If all you need to do is to change an output argument, the built-in
+`SetArgPointee()` action is convenient:
+
+```
+using ::testing::SetArgPointee;
+
+class MockMutator : public Mutator {
+ public:
+  MOCK_METHOD2(Mutate, void(bool mutate, int* value));
+  ...
+};
+...
+
+  MockMutator mutator;
+  EXPECT_CALL(mutator, Mutate(true, _))
+      .WillOnce(SetArgPointee<1>(5));
+```
+
+In this example, when `mutator.Mutate()` is called, we will assign 5
+to the `int` variable pointed to by argument #1
+(0-based).
+
+`SetArgPointee()` conveniently makes an internal copy of the
+value you pass to it, removing the need to keep the value in scope and
+alive. The implication however is that the value must have a copy
+constructor and assignment operator.
+
+If the mock method also needs to return a value as well, you can chain
+`SetArgPointee()` with `Return()` using `DoAll()`:
+
+```
+using ::testing::_;
+using ::testing::Return;
+using ::testing::SetArgPointee;
+
+class MockMutator : public Mutator {
+ public:
+  ...
+  MOCK_METHOD1(MutateInt, bool(int* value));
+};
+...
+
+  MockMutator mutator;
+  EXPECT_CALL(mutator, MutateInt(_))
+      .WillOnce(DoAll(SetArgPointee<0>(5),
+                      Return(true)));
+```
+
+If the output argument is an array, use the
+`SetArrayArgument<N>(first, last)` action instead. It copies the
+elements in source range `[first, last)` to the array pointed to by
+the `N`-th (0-based) argument:
+
+```
+using ::testing::NotNull;
+using ::testing::SetArrayArgument;
+
+class MockArrayMutator : public ArrayMutator {
+ public:
+  MOCK_METHOD2(Mutate, void(int* values, int num_values));
+  ...
+};
+...
+
+  MockArrayMutator mutator;
+  int values[5] = { 1, 2, 3, 4, 5 };
+  EXPECT_CALL(mutator, Mutate(NotNull(), 5))
+      .WillOnce(SetArrayArgument<0>(values, values + 5));
+```
+
+This also works when the argument is an output iterator:
+
+```
+using ::testing::_;
+using ::testing::SeArrayArgument;
+
+class MockRolodex : public Rolodex {
+ public:
+  MOCK_METHOD1(GetNames, void(std::back_insert_iterator<vector<string> >));
+  ...
+};
+...
+
+  MockRolodex rolodex;
+  vector<string> names;
+  names.push_back("George");
+  names.push_back("John");
+  names.push_back("Thomas");
+  EXPECT_CALL(rolodex, GetNames(_))
+      .WillOnce(SetArrayArgument<0>(names.begin(), names.end()));
+```
+
+## Changing a Mock Object's Behavior Based on the State ##
+
+If you expect a call to change the behavior of a mock object, you can use `::testing::InSequence` to specify different behaviors before and after the call:
+
+```
+using ::testing::InSequence;
+using ::testing::Return;
+
+...
+  {
+    InSequence seq;
+    EXPECT_CALL(my_mock, IsDirty())
+        .WillRepeatedly(Return(true));
+    EXPECT_CALL(my_mock, Flush());
+    EXPECT_CALL(my_mock, IsDirty())
+        .WillRepeatedly(Return(false));
+  }
+  my_mock.FlushIfDirty();
+```
+
+This makes `my_mock.IsDirty()` return `true` before `my_mock.Flush()` is called and return `false` afterwards.
+
+If the behavior change is more complex, you can store the effects in a variable and make a mock method get its return value from that variable:
+
+```
+using ::testing::_;
+using ::testing::SaveArg;
+using ::testing::Return;
+
+ACTION_P(ReturnPointee, p) { return *p; }
+...
+  int previous_value = 0;
+  EXPECT_CALL(my_mock, GetPrevValue())
+      .WillRepeatedly(ReturnPointee(&previous_value));
+  EXPECT_CALL(my_mock, UpdateValue(_))
+      .WillRepeatedly(SaveArg<0>(&previous_value));
+  my_mock.DoSomethingToUpdateValue();
+```
+
+Here `my_mock.GetPrevValue()` will always return the argument of the last `UpdateValue()` call.
+
+## Setting the Default Value for a Return Type ##
+
+If a mock method's return type is a built-in C++ type or pointer, by
+default it will return 0 when invoked. You only need to specify an
+action if this default value doesn't work for you.
+
+Sometimes, you may want to change this default value, or you may want
+to specify a default value for types Google Mock doesn't know
+about. You can do this using the `::testing::DefaultValue` class
+template:
+
+```
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD0(CalculateBar, Bar());
+};
+...
+
+  Bar default_bar;
+  // Sets the default return value for type Bar.
+  DefaultValue<Bar>::Set(default_bar);
+
+  MockFoo foo;
+
+  // We don't need to specify an action here, as the default
+  // return value works for us.
+  EXPECT_CALL(foo, CalculateBar());
+
+  foo.CalculateBar();  // This should return default_bar.
+
+  // Unsets the default return value.
+  DefaultValue<Bar>::Clear();
+```
+
+Please note that changing the default value for a type can make you
+tests hard to understand. We recommend you to use this feature
+judiciously. For example, you may want to make sure the `Set()` and
+`Clear()` calls are right next to the code that uses your mock.
+
+## Setting the Default Actions for a Mock Method ##
+
+You've learned how to change the default value of a given
+type. However, this may be too coarse for your purpose: perhaps you
+have two mock methods with the same return type and you want them to
+have different behaviors. The `ON_CALL()` macro allows you to
+customize your mock's behavior at the method level:
+
+```
+using ::testing::_;
+using ::testing::AnyNumber;
+using ::testing::Gt;
+using ::testing::Return;
+...
+  ON_CALL(foo, Sign(_))
+      .WillByDefault(Return(-1));
+  ON_CALL(foo, Sign(0))
+      .WillByDefault(Return(0));
+  ON_CALL(foo, Sign(Gt(0)))
+      .WillByDefault(Return(1));
+
+  EXPECT_CALL(foo, Sign(_))
+      .Times(AnyNumber());
+
+  foo.Sign(5);   // This should return 1.
+  foo.Sign(-9);  // This should return -1.
+  foo.Sign(0);   // This should return 0.
+```
+
+As you may have guessed, when there are more than one `ON_CALL()`
+statements, the news order take precedence over the older ones. In
+other words, the **last** one that matches the function arguments will
+be used. This matching order allows you to set up the common behavior
+in a mock object's constructor or the test fixture's set-up phase and
+specialize the mock's behavior later.
+
+## Using Functions/Methods/Functors as Actions ##
+
+If the built-in actions don't suit you, you can easily use an existing
+function, method, or functor as an action:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD2(Sum, int(int x, int y));
+  MOCK_METHOD1(ComplexJob, bool(int x));
+};
+
+int CalculateSum(int x, int y) { return x + y; }
+
+class Helper {
+ public:
+  bool ComplexJob(int x);
+};
+...
+
+  MockFoo foo;
+  Helper helper;
+  EXPECT_CALL(foo, Sum(_, _))
+      .WillOnce(Invoke(CalculateSum));
+  EXPECT_CALL(foo, ComplexJob(_))
+      .WillOnce(Invoke(&helper, &Helper::ComplexJob));
+
+  foo.Sum(5, 6);       // Invokes CalculateSum(5, 6).
+  foo.ComplexJob(10);  // Invokes helper.ComplexJob(10);
+```
+
+The only requirement is that the type of the function, etc must be
+_compatible_ with the signature of the mock function, meaning that the
+latter's arguments can be implicitly converted to the corresponding
+arguments of the former, and the former's return type can be
+implicitly converted to that of the latter. So, you can invoke
+something whose type is _not_ exactly the same as the mock function,
+as long as it's safe to do so - nice, huh?
+
+## Invoking a Function/Method/Functor Without Arguments ##
+
+`Invoke()` is very useful for doing actions that are more complex. It
+passes the mock function's arguments to the function or functor being
+invoked such that the callee has the full context of the call to work
+with. If the invoked function is not interested in some or all of the
+arguments, it can simply ignore them.
+
+Yet, a common pattern is that a test author wants to invoke a function
+without the arguments of the mock function. `Invoke()` allows her to
+do that using a wrapper function that throws away the arguments before
+invoking an underlining nullary function. Needless to say, this can be
+tedious and obscures the intent of the test.
+
+`InvokeWithoutArgs()` solves this problem. It's like `Invoke()` except
+that it doesn't pass the mock function's arguments to the
+callee. Here's an example:
+
+```
+using ::testing::_;
+using ::testing::InvokeWithoutArgs;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD1(ComplexJob, bool(int n));
+};
+
+bool Job1() { ... }
+...
+
+  MockFoo foo;
+  EXPECT_CALL(foo, ComplexJob(_))
+      .WillOnce(InvokeWithoutArgs(Job1));
+
+  foo.ComplexJob(10);  // Invokes Job1().
+```
+
+## Invoking an Argument of the Mock Function ##
+
+Sometimes a mock function will receive a function pointer or a functor
+(in other words, a "callable") as an argument, e.g.
+
+```
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD2(DoThis, bool(int n, bool (*fp)(int)));
+};
+```
+
+and you may want to invoke this callable argument:
+
+```
+using ::testing::_;
+...
+  MockFoo foo;
+  EXPECT_CALL(foo, DoThis(_, _))
+      .WillOnce(...);
+  // Will execute (*fp)(5), where fp is the
+  // second argument DoThis() receives.
+```
+
+Arghh, you need to refer to a mock function argument but C++ has no
+lambda (yet), so you have to define your own action. :-( Or do you
+really?
+
+Well, Google Mock has an action to solve _exactly_ this problem:
+
+```
+  InvokeArgument<N>(arg_1, arg_2, ..., arg_m)
+```
+
+will invoke the `N`-th (0-based) argument the mock function receives,
+with `arg_1`, `arg_2`, ..., and `arg_m`. No matter if the argument is
+a function pointer or a functor, Google Mock handles them both.
+
+With that, you could write:
+
+```
+using ::testing::_;
+using ::testing::InvokeArgument;
+...
+  EXPECT_CALL(foo, DoThis(_, _))
+      .WillOnce(InvokeArgument<1>(5));
+  // Will execute (*fp)(5), where fp is the
+  // second argument DoThis() receives.
+```
+
+What if the callable takes an argument by reference? No problem - just
+wrap it inside `ByRef()`:
+
+```
+...
+  MOCK_METHOD1(Bar, bool(bool (*fp)(int, const Helper&)));
+...
+using ::testing::_;
+using ::testing::ByRef;
+using ::testing::InvokeArgument;
+...
+
+  MockFoo foo;
+  Helper helper;
+  ...
+  EXPECT_CALL(foo, Bar(_))
+      .WillOnce(InvokeArgument<0>(5, ByRef(helper)));
+  // ByRef(helper) guarantees that a reference to helper, not a copy of it,
+  // will be passed to the callable.
+```
+
+What if the callable takes an argument by reference and we do **not**
+wrap the argument in `ByRef()`? Then `InvokeArgument()` will _make a
+copy_ of the argument, and pass a _reference to the copy_, instead of
+a reference to the original value, to the callable. This is especially
+handy when the argument is a temporary value:
+
+```
+...
+  MOCK_METHOD1(DoThat, bool(bool (*f)(const double& x, const string& s)));
+...
+using ::testing::_;
+using ::testing::InvokeArgument;
+...
+
+  MockFoo foo;
+  ...
+  EXPECT_CALL(foo, DoThat(_))
+      .WillOnce(InvokeArgument<0>(5.0, string("Hi")));
+  // Will execute (*f)(5.0, string("Hi")), where f is the function pointer
+  // DoThat() receives.  Note that the values 5.0 and string("Hi") are
+  // temporary and dead once the EXPECT_CALL() statement finishes.  Yet
+  // it's fine to perform this action later, since a copy of the values
+  // are kept inside the InvokeArgument action.
+```
+
+## Ignoring an Action's Result ##
+
+Sometimes you have an action that returns _something_, but you need an
+action that returns `void` (perhaps you want to use it in a mock
+function that returns `void`, or perhaps it needs to be used in
+`DoAll()` and it's not the last in the list). `IgnoreResult()` lets
+you do that. For example:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::Return;
+
+int Process(const MyData& data);
+string DoSomething();
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD1(Abc, void(const MyData& data));
+  MOCK_METHOD0(Xyz, bool());
+};
+...
+
+  MockFoo foo;
+  EXPECT_CALL(foo, Abc(_))
+  // .WillOnce(Invoke(Process));
+  // The above line won't compile as Process() returns int but Abc() needs
+  // to return void.
+      .WillOnce(IgnoreResult(Invoke(Process)));
+
+  EXPECT_CALL(foo, Xyz())
+      .WillOnce(DoAll(IgnoreResult(Invoke(DoSomething)),
+      // Ignores the string DoSomething() returns.
+                      Return(true)));
+```
+
+Note that you **cannot** use `IgnoreResult()` on an action that already
+returns `void`. Doing so will lead to ugly compiler errors.
+
+## Selecting an Action's Arguments ##
+
+Say you have a mock function `Foo()` that takes seven arguments, and
+you have a custom action that you want to invoke when `Foo()` is
+called. Trouble is, the custom action only wants three arguments:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+...
+  MOCK_METHOD7(Foo, bool(bool visible, const string& name, int x, int y,
+                         const map<pair<int, int>, double>& weight,
+                         double min_weight, double max_wight));
+...
+
+bool IsVisibleInQuadrant1(bool visible, int x, int y) {
+  return visible && x >= 0 && y >= 0;
+}
+...
+
+  EXPECT_CALL(mock, Foo(_, _, _, _, _, _, _))
+      .WillOnce(Invoke(IsVisibleInQuadrant1));  // Uh, won't compile. :-(
+```
+
+To please the compiler God, you can to define an "adaptor" that has
+the same signature as `Foo()` and calls the custom action with the
+right arguments:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+
+bool MyIsVisibleInQuadrant1(bool visible, const string& name, int x, int y,
+                            const map<pair<int, int>, double>& weight,
+                            double min_weight, double max_wight) {
+  return IsVisibleInQuadrant1(visible, x, y);
+}
+...
+
+  EXPECT_CALL(mock, Foo(_, _, _, _, _, _, _))
+      .WillOnce(Invoke(MyIsVisibleInQuadrant1));  // Now it works.
+```
+
+But isn't this awkward?
+
+Google Mock provides a generic _action adaptor_, so you can spend your
+time minding more important business than writing your own
+adaptors. Here's the syntax:
+
+```
+  WithArgs<N1, N2, ..., Nk>(action)
+```
+
+creates an action that passes the arguments of the mock function at
+the given indices (0-based) to the inner `action` and performs
+it. Using `WithArgs`, our original example can be written as:
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::WithArgs;
+...
+  EXPECT_CALL(mock, Foo(_, _, _, _, _, _, _))
+      .WillOnce(WithArgs<0, 2, 3>(Invoke(IsVisibleInQuadrant1)));
+      // No need to define your own adaptor.
+```
+
+For better readability, Google Mock also gives you:
+
+  * `WithoutArgs(action)` when the inner `action` takes _no_ argument, and
+  * `WithArg<N>(action)` (no `s` after `Arg`) when the inner `action` takes _one_ argument.
+
+As you may have realized, `InvokeWithoutArgs(...)` is just syntactic
+sugar for `WithoutArgs(Inovke(...))`.
+
+Here are more tips:
+
+  * The inner action used in `WithArgs` and friends does not have to be `Invoke()` -- it can be anything.
+  * You can repeat an argument in the argument list if necessary, e.g. `WithArgs<2, 3, 3, 5>(...)`.
+  * You can change the order of the arguments, e.g. `WithArgs<3, 2, 1>(...)`.
+  * The types of the selected arguments do _not_ have to match the signature of the inner action exactly. It works as long as they can be implicitly converted to the corresponding arguments of the inner action. For example, if the 4-th argument of the mock function is an `int` and `my_action` takes a `double`, `WithArg<4>(my_action)` will work.
+
+## Ignoring Arguments in Action Functions ##
+
+The selecting-an-action's-arguments recipe showed us one way to make a
+mock function and an action with incompatible argument lists fit
+together. The downside is that wrapping the action in
+`WithArgs<...>()` can get tedious for people writing the tests.
+
+If you are defining a function, method, or functor to be used with
+`Invoke*()`, and you are not interested in some of its arguments, an
+alternative to `WithArgs` is to declare the uninteresting arguments as
+`Unused`. This makes the definition less cluttered and less fragile in
+case the types of the uninteresting arguments change. It could also
+increase the chance the action function can be reused. For example,
+given
+
+```
+  MOCK_METHOD3(Foo, double(const string& label, double x, double y));
+  MOCK_METHOD3(Bar, double(int index, double x, double y));
+```
+
+instead of
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+
+double DistanceToOriginWithLabel(const string& label, double x, double y) {
+  return sqrt(x*x + y*y);
+}
+
+double DistanceToOriginWithIndex(int index, double x, double y) {
+  return sqrt(x*x + y*y);
+}
+...
+
+  EXEPCT_CALL(mock, Foo("abc", _, _))
+      .WillOnce(Invoke(DistanceToOriginWithLabel));
+  EXEPCT_CALL(mock, Bar(5, _, _))
+      .WillOnce(Invoke(DistanceToOriginWithIndex));
+```
+
+you could write
+
+```
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::Unused;
+
+double DistanceToOrigin(Unused, double x, double y) {
+  return sqrt(x*x + y*y);
+}
+...
+
+  EXEPCT_CALL(mock, Foo("abc", _, _))
+      .WillOnce(Invoke(DistanceToOrigin));
+  EXEPCT_CALL(mock, Bar(5, _, _))
+      .WillOnce(Invoke(DistanceToOrigin));
+```
+
+## Sharing Actions ##
+
+Just like matchers, a Google Mock action object consists of a pointer
+to a ref-counted implementation object. Therefore copying actions is
+also allowed and very efficient. When the last action that references
+the implementation object dies, the implementation object will be
+deleted.
+
+If you have some complex action that you want to use again and again,
+you may not have to build it from scratch everytime. If the action
+doesn't have an internal state (i.e. if it always does the same thing
+no matter how many times it has been called), you can assign it to an
+action variable and use that variable repeatedly. For example:
+
+```
+  Action<bool(int*)> set_flag = DoAll(SetArgPointee<0>(5),
+                                      Return(true));
+  ... use set_flag in .WillOnce() and .WillRepeatedly() ...
+```
+
+However, if the action has its own state, you may be surprised if you
+share the action object. Suppose you have an action factory
+`IncrementCounter(init)` which creates an action that increments and
+returns a counter whose initial value is `init`, using two actions
+created from the same expression and using a shared action will
+exihibit different behaviors. Example:
+
+```
+  EXPECT_CALL(foo, DoThis())
+      .WillRepeatedly(IncrementCounter(0));
+  EXPECT_CALL(foo, DoThat())
+      .WillRepeatedly(IncrementCounter(0));
+  foo.DoThis();  // Returns 1.
+  foo.DoThis();  // Returns 2.
+  foo.DoThat();  // Returns 1 - Blah() uses a different
+                 // counter than Bar()'s.
+```
+
+versus
+
+```
+  Action<int()> increment = IncrementCounter(0);
+
+  EXPECT_CALL(foo, DoThis())
+      .WillRepeatedly(increment);
+  EXPECT_CALL(foo, DoThat())
+      .WillRepeatedly(increment);
+  foo.DoThis();  // Returns 1.
+  foo.DoThis();  // Returns 2.
+  foo.DoThat();  // Returns 3 - the counter is shared.
+```
+
+# Misc Recipes on Using Google Mock #
+
+## Making the Compilation Faster ##
+
+Believe it or not, the _vast majority_ of the time spent on compiling
+a mock class is in generating its constructor and destructor, as they
+perform non-trivial tasks (e.g. verification of the
+expectations). What's more, mock methods with different signatures
+have different types and thus their constructors/destructors need to
+be generated by the compiler separately. As a result, if you mock many
+different types of methods, compiling your mock class can get really
+slow.
+
+If you are experiencing slow compilation, you can move the definition
+of your mock class' constructor and destructor out of the class body
+and into a `.cpp` file. This way, even if you `#include` your mock
+class in N files, the compiler only needs to generate its constructor
+and destructor once, resulting in a much faster compilation.
+
+Let's illustrate the idea using an example. Here's the definition of a
+mock class before applying this recipe:
+
+```
+// File mock_foo.h.
+...
+class MockFoo : public Foo {
+ public:
+  // Since we don't declare the constructor or the destructor,
+  // the compiler will generate them in every translation unit
+  // where this mock class is used.
+
+  MOCK_METHOD0(DoThis, int());
+  MOCK_METHOD1(DoThat, bool(const char* str));
+  ... more mock methods ...
+};
+```
+
+After the change, it would look like:
+
+```
+// File mock_foo.h.
+...
+class MockFoo : public Foo {
+ public:
+  // The constructor and destructor are declared, but not defined, here.
+  MockFoo();
+  virtual ~MockFoo();
+
+  MOCK_METHOD0(DoThis, int());
+  MOCK_METHOD1(DoThat, bool(const char* str));
+  ... more mock methods ...
+};
+```
+and
+```
+// File mock_foo.cpp.
+#include "path/to/mock_foo.h"
+
+// The definitions may appear trivial, but the functions actually do a
+// lot of things through the constructors/destructors of the member
+// variables used to implement the mock methods.
+MockFoo::MockFoo() {}
+MockFoo::~MockFoo() {}
+```
+
+## Forcing a Verification ##
+
+When it's being destoyed, your friendly mock object will automatically
+verify that all expectations on it have been satisfied, and will
+generate [Google Test](http://code.google.com/p/googletest/) failures
+if not. This is convenient as it leaves you with one less thing to
+worry about. That is, unless you are not sure if your mock object will
+be destoyed.
+
+How could it be that your mock object won't eventually be destroyed?
+Well, it might be created on the heap and owned by the code you are
+testing. Suppose there's a bug in that code and it doesn't delete the
+mock object properly - you could end up with a passing test when
+there's actually a bug.
+
+Using a heap checker is a good idea and can alleviate the concern, but
+its implementation may not be 100% reliable. So, sometimes you do want
+to _force_ Google Mock to verify a mock object before it is
+(hopefully) destructed. You can do this with
+`Mock::VerifyAndClearExpectations(&mock_object)`:
+
+```
+TEST(MyServerTest, ProcessesRequest) {
+  using ::testing::Mock;
+
+  MockFoo* const foo = new MockFoo;
+  EXPECT_CALL(*foo, ...)...;
+  // ... other expectations ...
+
+  // server now owns foo.
+  MyServer server(foo);
+  server.ProcessRequest(...);
+
+  // In case that server's destructor will forget to delete foo,
+  // this will verify the expectations anyway.
+  Mock::VerifyAndClearExpectations(foo);
+}  // server is destroyed when it goes out of scope here.
+```
+
+**Tip:** The `Mock::VerifyAndClearExpectations()` function returns a
+`bool` to indicate whether the verification was successful (`true` for
+yes), so you can wrap that function call inside a `ASSERT_TRUE()` if
+there is no point going further when the verification has failed.
+
+## Using Check Points ##
+
+Sometimes you may want to "reset" a mock object at various check
+points in your test: at each check point, you verify that all existing
+expectations on the mock object have been satisfied, and then you set
+some new expectations on it as if it's newly created. This allows you
+to work with a mock object in "phases" whose sizes are each
+manageable.
+
+One such scenario is that in your test's `SetUp()` function, you may
+want to put the object you are testing into a certain state, with the
+help from a mock object. Once in the desired state, you want to clear
+all expectations on the mock, such that in the `TEST_F` body you can
+set fresh expectations on it.
+
+As you may have figured out, the `Mock::VerifyAndClearExpectations()`
+function we saw in the previous recipe can help you here. Or, if you
+are using `ON_CALL()` to set default actions on the mock object and
+want to clear the default actions as well, use
+`Mock::VerifyAndClear(&mock_object)` instead. This function does what
+`Mock::VerifyAndClearExpectations(&mock_object)` does and returns the
+same `bool`, **plus** it clears the `ON_CALL()` statements on
+`mock_object` too.
+
+Another trick you can use to achieve the same effect is to put the
+expectations in sequences and insert calls to a dummy "check-point"
+function at specific places. Then you can verify that the mock
+function calls do happen at the right time. For example, if you are
+exercising code:
+
+```
+Foo(1);
+Foo(2);
+Foo(3);
+```
+
+and want to verify that `Foo(1)` and `Foo(3)` both invoke
+`mock.Bar("a")`, but `Foo(2)` doesn't invoke anything. You can write:
+
+```
+using ::testing::MockFunction;
+
+TEST(FooTest, InvokesBarCorrectly) {
+  MyMock mock;
+  // Class MockFunction<F> has exactly one mock method.  It is named
+  // Call() and has type F.
+  MockFunction<void(string check_point_name)> check;
+  {
+    InSequence s;
+
+    EXPECT_CALL(mock, Bar("a"));
+    EXPECT_CALL(check, Call("1"));
+    EXPECT_CALL(check, Call("2"));
+    EXPECT_CALL(mock, Bar("a"));
+  }
+  Foo(1);
+  check.Call("1");
+  Foo(2);
+  check.Call("2");
+  Foo(3);
+}
+```
+
+The expectation spec says that the first `Bar("a")` must happen before
+check point "1", the second `Bar("a")` must happen after check point "2",
+and nothing should happen between the two check points. The explicit
+check points make it easy to tell which `Bar("a")` is called by which
+call to `Foo()`.
+
+## Mocking Destructors ##
+
+Sometimes you want to make sure a mock object is destructed at the
+right time, e.g. after `bar->A()` is called but before `bar->B()` is
+called. We already know that you can specify constraints on the order
+of mock function calls, so all we need to do is to mock the destructor
+of the mock function.
+
+This sounds simple, except for one problem: a destructor is a special
+function with special syntax and special semantics, and the
+`MOCK_METHOD0` macro doesn't work for it:
+
+```
+  MOCK_METHOD0(~MockFoo, void());  // Won't compile!
+```
+
+The good news is that you can use a simple pattern to achieve the same
+effect. First, add a mock function `Die()` to your mock class and call
+it in the destructor, like this:
+
+```
+class MockFoo : public Foo {
+  ...
+  // Add the following two lines to the mock class.
+  MOCK_METHOD0(Die, void());
+  virtual ~MockFoo() { Die(); }
+};
+```
+
+(If the name `Die()` clashes with an existing symbol, choose another
+name.) Now, we have translated the problem of testing when a `MockFoo`
+object dies to testing when its `Die()` method is called:
+
+```
+  MockFoo* foo = new MockFoo;
+  MockBar* bar = new MockBar;
+  ...
+  {
+    InSequence s;
+
+    // Expects *foo to die after bar->A() and before bar->B().
+    EXPECT_CALL(*bar, A());
+    EXPECT_CALL(*foo, Die());
+    EXPECT_CALL(*bar, B());
+  }
+```
+
+And that's that.
+
+## Using Google Mock and Threads ##
+
+**IMPORTANT NOTE:** What we describe in this recipe is **ONLY** true on
+platforms where Google Mock is thread-safe. Currently these are only
+platforms that support the pthreads library (this includes Linux and Mac).
+To make it thread-safe on other platforms we only need to implement
+some synchronization operations in `"gtest/internal/gtest-port.h"`.
+
+In a **unit** test, it's best if you could isolate and test a piece of
+code in a single-threaded context. That avoids race conditions and
+dead locks, and makes debugging your test much easier.
+
+Yet many programs are multi-threaded, and sometimes to test something
+we need to pound on it from more than one thread. Google Mock works
+for this purpose too.
+
+Remember the steps for using a mock:
+
+  1. Create a mock object `foo`.
+  1. Set its default actions and expectations using `ON_CALL()` and `EXPECT_CALL()`.
+  1. The code under test calls methods of `foo`.
+  1. Optionally, verify and reset the mock.
+  1. Destroy the mock yourself, or let the code under test destroy it. The destructor will automatically verify it.
+
+If you follow the following simple rules, your mocks and threads can
+live happily togeter:
+
+  * Execute your _test code_ (as opposed to the code being tested) in _one_ thread. This makes your test easy to follow.
+  * Obviously, you can do step #1 without locking.
+  * When doing step #2 and #5, make sure no other thread is accessing `foo`. Obvious too, huh?
+  * #3 and #4 can be done either in one thread or in multiple threads - anyway you want. Google Mock takes care of the locking, so you don't have to do any - unless required by your test logic.
+
+If you violate the rules (for example, if you set expectations on a
+mock while another thread is calling its methods), you get undefined
+behavior. That's not fun, so don't do it.
+
+Google Mock guarantees that the action for a mock function is done in
+the same thread that called the mock function. For example, in
+
+```
+  EXPECT_CALL(mock, Foo(1))
+      .WillOnce(action1);
+  EXPECT_CALL(mock, Foo(2))
+      .WillOnce(action2);
+```
+
+if `Foo(1)` is called in thread 1 and `Foo(2)` is called in thread 2,
+Google Mock will execute `action1` in thread 1 and `action2` in thread
+2.
+
+Google Mock does _not_ impose a sequence on actions performed in
+different threads (doing so may create deadlocks as the actions may
+need to cooperate). This means that the execution of `action1` and
+`action2` in the above example _may_ interleave. If this is a problem,
+you should add proper synchronization logic to `action1` and `action2`
+to make the test thread-safe.
+
+
+Also, remember that `DefaultValue<T>` is a global resource that
+potentially affects _all_ living mock objects in your
+program. Naturally, you won't want to mess with it from multiple
+threads or when there still are mocks in action.
+
+## Controlling How Much Information Google Mock Prints ##
+
+When Google Mock sees something that has the potential of being an
+error (e.g. a mock function with no expectation is called, a.k.a. an
+uninteresting call, which is allowed but perhaps you forgot to
+explicitly ban the call), it prints some warning messages, including
+the arguments of the function and the return value. Hopefully this
+will remind you to take a look and see if there is indeed a problem.
+
+Sometimes you are confident that your tests are correct and may not
+appreciate such friendly messages. Some other times, you are debugging
+your tests or learning about the behavior of the code you are testing,
+and wish you could observe every mock call that happens (including
+argument values and the return value). Clearly, one size doesn't fit
+all.
+
+You can control how much Google Mock tells you using the
+`--gmock_verbose=LEVEL` command-line flag, where `LEVEL` is a string
+with three possible values:
+
+  * `info`: Google Mock will print all informational messages, warnings, and errors (most verbose). At this setting, Google Mock will also log any calls to the `ON_CALL/EXPECT_CALL` macros.
+  * `warning`: Google Mock will print both warnings and errors (less verbose). This is the default.
+  * `error`: Google Mock will print errors only (least verbose).
+
+Alternatively, you can adjust the value of that flag from within your
+tests like so:
+
+```
+  ::testing::FLAGS_gmock_verbose = "error";
+```
+
+Now, judiciously use the right flag to enable Google Mock serve you better!
+
+## Gaining Super Vision into Mock Calls ##
+
+You have a test using Google Mock. It fails: Google Mock tells you
+that some expectations aren't satisfied. However, you aren't sure why:
+Is there a typo somewhere in the matchers? Did you mess up the order
+of the `EXPECT_CALL`s? Or is the code under test doing something
+wrong?  How can you find out the cause?
+
+Won't it be nice if you have X-ray vision and can actually see the
+trace of all `EXPECT_CALL`s and mock method calls as they are made?
+For each call, would you like to see its actual argument values and
+which `EXPECT_CALL` Google Mock thinks it matches?
+
+You can unlock this power by running your test with the
+`--gmock_verbose=info` flag. For example, given the test program:
+
+```
+using testing::_;
+using testing::HasSubstr;
+using testing::Return;
+
+class MockFoo {
+ public:
+  MOCK_METHOD2(F, void(const string& x, const string& y));
+};
+
+TEST(Foo, Bar) {
+  MockFoo mock;
+  EXPECT_CALL(mock, F(_, _)).WillRepeatedly(Return());
+  EXPECT_CALL(mock, F("a", "b"));
+  EXPECT_CALL(mock, F("c", HasSubstr("d")));
+
+  mock.F("a", "good");
+  mock.F("a", "b");
+}
+```
+
+if you run it with `--gmock_verbose=info`, you will see this output:
+
+```
+[ RUN      ] Foo.Bar
+
+foo_test.cc:14: EXPECT_CALL(mock, F(_, _)) invoked
+foo_test.cc:15: EXPECT_CALL(mock, F("a", "b")) invoked
+foo_test.cc:16: EXPECT_CALL(mock, F("c", HasSubstr("d"))) invoked
+foo_test.cc:14: Mock function call matches EXPECT_CALL(mock, F(_, _))...
+    Function call: F(@0x7fff7c8dad40"a", @0x7fff7c8dad10"good")
+foo_test.cc:15: Mock function call matches EXPECT_CALL(mock, F("a", "b"))...
+    Function call: F(@0x7fff7c8dada0"a", @0x7fff7c8dad70"b")
+foo_test.cc:16: Failure
+Actual function call count doesn't match EXPECT_CALL(mock, F("c", HasSubstr("d")))...
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+[  FAILED  ] Foo.Bar
+```
+
+Suppose the bug is that the `"c"` in the third `EXPECT_CALL` is a typo
+and should actually be `"a"`. With the above message, you should see
+that the actual `F("a", "good")` call is matched by the first
+`EXPECT_CALL`, not the third as you thought. From that it should be
+obvious that the third `EXPECT_CALL` is written wrong. Case solved.
+
+## Running Tests in Emacs ##
+
+If you build and run your tests in Emacs, the source file locations of
+Google Mock and [Google Test](http://code.google.com/p/googletest/)
+errors will be highlighted. Just press `<Enter>` on one of them and
+you'll be taken to the offending line. Or, you can just type `C-x ``
+to jump to the next error.
+
+To make it even easier, you can add the following lines to your
+`~/.emacs` file:
+
+```
+(global-set-key "\M-m"   'compile)  ; m is for make
+(global-set-key [M-down] 'next-error)
+(global-set-key [M-up]   '(lambda () (interactive) (next-error -1)))
+```
+
+Then you can type `M-m` to start a build, or `M-up`/`M-down` to move
+back and forth between errors.
+
+## Fusing Google Mock Source Files ##
+
+Google Mock's implementation consists of dozens of files (excluding
+its own tests).  Sometimes you may want them to be packaged up in
+fewer files instead, such that you can easily copy them to a new
+machine and start hacking there.  For this we provide an experimental
+Python script `fuse_gmock_files.py` in the `scripts/` directory
+(starting with release 1.2.0).  Assuming you have Python 2.4 or above
+installed on your machine, just go to that directory and run
+```
+python fuse_gmock_files.py OUTPUT_DIR
+```
+
+and you should see an `OUTPUT_DIR` directory being created with files
+`gtest/gtest.h`, `gmock/gmock.h`, and `gmock-gtest-all.cc` in it.
+These three files contain everything you need to use Google Mock (and
+Google Test).  Just copy them to anywhere you want and you are ready
+to write tests and use mocks.  You can use the
+[scrpts/test/Makefile](http://code.google.com/p/googlemock/source/browse/trunk/scripts/test/Makefile) file as an example on how to compile your tests
+against them.
+
+# Extending Google Mock #
+
+## Writing New Matchers Quickly ##
+
+The `MATCHER*` family of macros can be used to define custom matchers
+easily.  The syntax:
+
+```
+MATCHER(name, description_string_expression) { statements; }
+```
+
+will define a matcher with the given name that executes the
+statements, which must return a `bool` to indicate if the match
+succeeds.  Inside the statements, you can refer to the value being
+matched by `arg`, and refer to its type by `arg_type`.
+
+The description string is a `string`-typed expression that documents
+what the matcher does, and is used to generate the failure message
+when the match fails.  It can (and should) reference the special
+`bool` variable `negation`, and should evaluate to the description of
+the matcher when `negation` is `false`, or that of the matcher's
+negation when `negation` is `true`.
+
+For convenience, we allow the description string to be empty (`""`),
+in which case Google Mock will use the sequence of words in the
+matcher name as the description.
+
+For example:
+```
+MATCHER(IsDivisibleBy7, "") { return (arg % 7) == 0; }
+```
+allows you to write
+```
+  // Expects mock_foo.Bar(n) to be called where n is divisible by 7.
+  EXPECT_CALL(mock_foo, Bar(IsDivisibleBy7()));
+```
+or,
+```
+using ::testing::Not;
+...
+  EXPECT_THAT(some_expression, IsDivisibleBy7());
+  EXPECT_THAT(some_other_expression, Not(IsDivisibleBy7()));
+```
+If the above assertions fail, they will print something like:
+```
+  Value of: some_expression
+  Expected: is divisible by 7
+    Actual: 27
+...
+  Value of: some_other_expression
+  Expected: not (is divisible by 7)
+    Actual: 21
+```
+where the descriptions `"is divisible by 7"` and `"not (is divisible
+by 7)"` are automatically calculated from the matcher name
+`IsDivisibleBy7`.
+
+As you may have noticed, the auto-generated descriptions (especially
+those for the negation) may not be so great. You can always override
+them with a string expression of your own:
+```
+MATCHER(IsDivisibleBy7, std::string(negation ? "isn't" : "is") +
+                        " divisible by 7") {
+  return (arg % 7) == 0;
+}
+```
+
+Optionally, you can stream additional information to a hidden argument
+named `result_listener` to explain the match result. For example, a
+better definition of `IsDivisibleBy7` is:
+```
+MATCHER(IsDivisibleBy7, "") {
+  if ((arg % 7) == 0)
+    return true;
+
+  *result_listener << "the remainder is " << (arg % 7);
+  return false;
+}
+```
+
+With this definition, the above assertion will give a better message:
+```
+  Value of: some_expression
+  Expected: is divisible by 7
+    Actual: 27 (the remainder is 6)
+```
+
+You should let `MatchAndExplain()` print _any additional information_
+that can help a user understand the match result. Note that it should
+explain why the match succeeds in case of a success (unless it's
+obvious) - this is useful when the matcher is used inside
+`Not()`. There is no need to print the argument value itself, as
+Google Mock already prints it for you.
+
+**Notes:**
+
+  1. The type of the value being matched (`arg_type`) is determined by the context in which you use the matcher and is supplied to you by the compiler, so you don't need to worry about declaring it (nor can you).  This allows the matcher to be polymorphic.  For example, `IsDivisibleBy7()` can be used to match any type where the value of `(arg % 7) == 0` can be implicitly converted to a `bool`.  In the `Bar(IsDivisibleBy7())` example above, if method `Bar()` takes an `int`, `arg_type` will be `int`; if it takes an `unsigned long`, `arg_type` will be `unsigned long`; and so on.
+  1. Google Mock doesn't guarantee when or how many times a matcher will be invoked. Therefore the matcher logic must be _purely functional_ (i.e. it cannot have any side effect, and the result must not depend on anything other than the value being matched and the matcher parameters). This requirement must be satisfied no matter how you define the matcher (e.g. using one of the methods described in the following recipes). In particular, a matcher can never call a mock function, as that will affect the state of the mock object and Google Mock.
+
+## Writing New Parameterized Matchers Quickly ##
+
+Sometimes you'll want to define a matcher that has parameters.  For that you
+can use the macro:
+```
+MATCHER_P(name, param_name, description_string) { statements; }
+```
+where the description string can be either `""` or a string expression
+that references `negation` and `param_name`.
+
+For example:
+```
+MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; }
+```
+will allow you to write:
+```
+  EXPECT_THAT(Blah("a"), HasAbsoluteValue(n));
+```
+which may lead to this message (assuming `n` is 10):
+```
+  Value of: Blah("a")
+  Expected: has absolute value 10
+    Actual: -9
+```
+
+Note that both the matcher description and its parameter are
+printed, making the message human-friendly.
+
+In the matcher definition body, you can write `foo_type` to
+reference the type of a parameter named `foo`.  For example, in the
+body of `MATCHER_P(HasAbsoluteValue, value)` above, you can write
+`value_type` to refer to the type of `value`.
+
+Google Mock also provides `MATCHER_P2`, `MATCHER_P3`, ..., up to
+`MATCHER_P10` to support multi-parameter matchers:
+```
+MATCHER_Pk(name, param_1, ..., param_k, description_string) { statements; }
+```
+
+Please note that the custom description string is for a particular
+**instance** of the matcher, where the parameters have been bound to
+actual values.  Therefore usually you'll want the parameter values to
+be part of the description.  Google Mock lets you do that by
+referencing the matcher parameters in the description string
+expression.
+
+For example,
+```
+  using ::testing::PrintToString;
+  MATCHER_P2(InClosedRange, low, hi,
+             std::string(negation ? "isn't" : "is") + " in range [" +
+             PrintToString(low) + ", " + PrintToString(hi) + "]") {
+    return low <= arg && arg <= hi;
+  }
+  ...
+  EXPECT_THAT(3, InClosedRange(4, 6));
+```
+would generate a failure that contains the message:
+```
+  Expected: is in range [4, 6]
+```
+
+If you specify `""` as the description, the failure message will
+contain the sequence of words in the matcher name followed by the
+parameter values printed as a tuple.  For example,
+```
+  MATCHER_P2(InClosedRange, low, hi, "") { ... }
+  ...
+  EXPECT_THAT(3, InClosedRange(4, 6));
+```
+would generate a failure that contains the text:
+```
+  Expected: in closed range (4, 6)
+```
+
+For the purpose of typing, you can view
+```
+MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... }
+```
+as shorthand for
+```
+template <typename p1_type, ..., typename pk_type>
+FooMatcherPk<p1_type, ..., pk_type>
+Foo(p1_type p1, ..., pk_type pk) { ... }
+```
+
+When you write `Foo(v1, ..., vk)`, the compiler infers the types of
+the parameters `v1`, ..., and `vk` for you.  If you are not happy with
+the result of the type inference, you can specify the types by
+explicitly instantiating the template, as in `Foo<long, bool>(5, false)`.
+As said earlier, you don't get to (or need to) specify
+`arg_type` as that's determined by the context in which the matcher
+is used.
+
+You can assign the result of expression `Foo(p1, ..., pk)` to a
+variable of type `FooMatcherPk<p1_type, ..., pk_type>`.  This can be
+useful when composing matchers.  Matchers that don't have a parameter
+or have only one parameter have special types: you can assign `Foo()`
+to a `FooMatcher`-typed variable, and assign `Foo(p)` to a
+`FooMatcherP<p_type>`-typed variable.
+
+While you can instantiate a matcher template with reference types,
+passing the parameters by pointer usually makes your code more
+readable.  If, however, you still want to pass a parameter by
+reference, be aware that in the failure message generated by the
+matcher you will see the value of the referenced object but not its
+address.
+
+You can overload matchers with different numbers of parameters:
+```
+MATCHER_P(Blah, a, description_string_1) { ... }
+MATCHER_P2(Blah, a, b, description_string_2) { ... }
+```
+
+While it's tempting to always use the `MATCHER*` macros when defining
+a new matcher, you should also consider implementing
+`MatcherInterface` or using `MakePolymorphicMatcher()` instead (see
+the recipes that follow), especially if you need to use the matcher a
+lot.  While these approaches require more work, they give you more
+control on the types of the value being matched and the matcher
+parameters, which in general leads to better compiler error messages
+that pay off in the long run.  They also allow overloading matchers
+based on parameter types (as opposed to just based on the number of
+parameters).
+
+## Writing New Monomorphic Matchers ##
+
+A matcher of argument type `T` implements
+`::testing::MatcherInterface<T>` and does two things: it tests whether a
+value of type `T` matches the matcher, and can describe what kind of
+values it matches. The latter ability is used for generating readable
+error messages when expectations are violated.
+
+The interface looks like this:
+
+```
+class MatchResultListener {
+ public:
+  ...
+  // Streams x to the underlying ostream; does nothing if the ostream
+  // is NULL.
+  template <typename T>
+  MatchResultListener& operator<<(const T& x);
+
+  // Returns the underlying ostream.
+  ::std::ostream* stream();
+};
+
+template <typename T>
+class MatcherInterface {
+ public:
+  virtual ~MatcherInterface();
+
+  // Returns true iff the matcher matches x; also explains the match
+  // result to 'listener'.
+  virtual bool MatchAndExplain(T x, MatchResultListener* listener) const = 0;
+
+  // Describes this matcher to an ostream.
+  virtual void DescribeTo(::std::ostream* os) const = 0;
+
+  // Describes the negation of this matcher to an ostream.
+  virtual void DescribeNegationTo(::std::ostream* os) const;
+};
+```
+
+If you need a custom matcher but `Truly()` is not a good option (for
+example, you may not be happy with the way `Truly(predicate)`
+describes itself, or you may want your matcher to be polymorphic as
+`Eq(value)` is), you can define a matcher to do whatever you want in
+two steps: first implement the matcher interface, and then define a
+factory function to create a matcher instance. The second step is not
+strictly needed but it makes the syntax of using the matcher nicer.
+
+For example, you can define a matcher to test whether an `int` is
+divisible by 7 and then use it like this:
+```
+using ::testing::MakeMatcher;
+using ::testing::Matcher;
+using ::testing::MatcherInterface;
+using ::testing::MatchResultListener;
+
+class DivisibleBy7Matcher : public MatcherInterface<int> {
+ public:
+  virtual bool MatchAndExplain(int n, MatchResultListener* listener) const {
+    return (n % 7) == 0;
+  }
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "is divisible by 7";
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "is not divisible by 7";
+  }
+};
+
+inline Matcher<int> DivisibleBy7() {
+  return MakeMatcher(new DivisibleBy7Matcher);
+}
+...
+
+  EXPECT_CALL(foo, Bar(DivisibleBy7()));
+```
+
+You may improve the matcher message by streaming additional
+information to the `listener` argument in `MatchAndExplain()`:
+
+```
+class DivisibleBy7Matcher : public MatcherInterface<int> {
+ public:
+  virtual bool MatchAndExplain(int n,
+                               MatchResultListener* listener) const {
+    const int remainder = n % 7;
+    if (remainder != 0) {
+      *listener << "the remainder is " << remainder;
+    }
+    return remainder == 0;
+  }
+  ...
+};
+```
+
+Then, `EXPECT_THAT(x, DivisibleBy7());` may general a message like this:
+```
+Value of: x
+Expected: is divisible by 7
+  Actual: 23 (the remainder is 2)
+```
+
+## Writing New Polymorphic Matchers ##
+
+You've learned how to write your own matchers in the previous
+recipe. Just one problem: a matcher created using `MakeMatcher()` only
+works for one particular type of arguments. If you want a
+_polymorphic_ matcher that works with arguments of several types (for
+instance, `Eq(x)` can be used to match a `value` as long as `value` ==
+`x` compiles -- `value` and `x` don't have to share the same type),
+you can learn the trick from `"gmock/gmock-matchers.h"` but it's a bit
+involved.
+
+Fortunately, most of the time you can define a polymorphic matcher
+easily with the help of `MakePolymorphicMatcher()`. Here's how you can
+define `NotNull()` as an example:
+
+```
+using ::testing::MakePolymorphicMatcher;
+using ::testing::MatchResultListener;
+using ::testing::NotNull;
+using ::testing::PolymorphicMatcher;
+
+class NotNullMatcher {
+ public:
+  // To implement a polymorphic matcher, first define a COPYABLE class
+  // that has three members MatchAndExplain(), DescribeTo(), and
+  // DescribeNegationTo(), like the following.
+
+  // In this example, we want to use NotNull() with any pointer, so
+  // MatchAndExplain() accepts a pointer of any type as its first argument.
+  // In general, you can define MatchAndExplain() as an ordinary method or
+  // a method template, or even overload it.
+  template <typename T>
+  bool MatchAndExplain(T* p,
+                       MatchResultListener* /* listener */) const {
+    return p != NULL;
+  }
+
+  // Describes the property of a value matching this matcher.
+  void DescribeTo(::std::ostream* os) const { *os << "is not NULL"; }
+
+  // Describes the property of a value NOT matching this matcher.
+  void DescribeNegationTo(::std::ostream* os) const { *os << "is NULL"; }
+};
+
+// To construct a polymorphic matcher, pass an instance of the class
+// to MakePolymorphicMatcher().  Note the return type.
+inline PolymorphicMatcher<NotNullMatcher> NotNull() {
+  return MakePolymorphicMatcher(NotNullMatcher());
+}
+...
+
+  EXPECT_CALL(foo, Bar(NotNull()));  // The argument must be a non-NULL pointer.
+```
+
+**Note:** Your polymorphic matcher class does **not** need to inherit from
+`MatcherInterface` or any other class, and its methods do **not** need
+to be virtual.
+
+Like in a monomorphic matcher, you may explain the match result by
+streaming additional information to the `listener` argument in
+`MatchAndExplain()`.
+
+## Writing New Cardinalities ##
+
+A cardinality is used in `Times()` to tell Google Mock how many times
+you expect a call to occur. It doesn't have to be exact. For example,
+you can say `AtLeast(5)` or `Between(2, 4)`.
+
+If the built-in set of cardinalities doesn't suit you, you are free to
+define your own by implementing the following interface (in namespace
+`testing`):
+
+```
+class CardinalityInterface {
+ public:
+  virtual ~CardinalityInterface();
+
+  // Returns true iff call_count calls will satisfy this cardinality.
+  virtual bool IsSatisfiedByCallCount(int call_count) const = 0;
+
+  // Returns true iff call_count calls will saturate this cardinality.
+  virtual bool IsSaturatedByCallCount(int call_count) const = 0;
+
+  // Describes self to an ostream.
+  virtual void DescribeTo(::std::ostream* os) const = 0;
+};
+```
+
+For example, to specify that a call must occur even number of times,
+you can write
+
+```
+using ::testing::Cardinality;
+using ::testing::CardinalityInterface;
+using ::testing::MakeCardinality;
+
+class EvenNumberCardinality : public CardinalityInterface {
+ public:
+  virtual bool IsSatisfiedByCallCount(int call_count) const {
+    return (call_count % 2) == 0;
+  }
+
+  virtual bool IsSaturatedByCallCount(int call_count) const {
+    return false;
+  }
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "called even number of times";
+  }
+};
+
+Cardinality EvenNumber() {
+  return MakeCardinality(new EvenNumberCardinality);
+}
+...
+
+  EXPECT_CALL(foo, Bar(3))
+      .Times(EvenNumber());
+```
+
+## Writing New Actions Quickly ##
+
+If the built-in actions don't work for you, and you find it
+inconvenient to use `Invoke()`, you can use a macro from the `ACTION*`
+family to quickly define a new action that can be used in your code as
+if it's a built-in action.
+
+By writing
+```
+ACTION(name) { statements; }
+```
+in a namespace scope (i.e. not inside a class or function), you will
+define an action with the given name that executes the statements.
+The value returned by `statements` will be used as the return value of
+the action.  Inside the statements, you can refer to the K-th
+(0-based) argument of the mock function as `argK`.  For example:
+```
+ACTION(IncrementArg1) { return ++(*arg1); }
+```
+allows you to write
+```
+... WillOnce(IncrementArg1());
+```
+
+Note that you don't need to specify the types of the mock function
+arguments.  Rest assured that your code is type-safe though:
+you'll get a compiler error if `*arg1` doesn't support the `++`
+operator, or if the type of `++(*arg1)` isn't compatible with the mock
+function's return type.
+
+Another example:
+```
+ACTION(Foo) {
+  (*arg2)(5);
+  Blah();
+  *arg1 = 0;
+  return arg0;
+}
+```
+defines an action `Foo()` that invokes argument #2 (a function pointer)
+with 5, calls function `Blah()`, sets the value pointed to by argument
+#1 to 0, and returns argument #0.
+
+For more convenience and flexibility, you can also use the following
+pre-defined symbols in the body of `ACTION`:
+
+| `argK_type` | The type of the K-th (0-based) argument of the mock function |
+|:------------|:-------------------------------------------------------------|
+| `args`      | All arguments of the mock function as a tuple                |
+| `args_type` | The type of all arguments of the mock function as a tuple    |
+| `return_type` | The return type of the mock function                         |
+| `function_type` | The type of the mock function                                |
+
+For example, when using an `ACTION` as a stub action for mock function:
+```
+int DoSomething(bool flag, int* ptr);
+```
+we have:
+| **Pre-defined Symbol** | **Is Bound To** |
+|:-----------------------|:----------------|
+| `arg0`                 | the value of `flag` |
+| `arg0_type`            | the type `bool` |
+| `arg1`                 | the value of `ptr` |
+| `arg1_type`            | the type `int*` |
+| `args`                 | the tuple `(flag, ptr)` |
+| `args_type`            | the type `std::tr1::tuple<bool, int*>` |
+| `return_type`          | the type `int`  |
+| `function_type`        | the type `int(bool, int*)` |
+
+## Writing New Parameterized Actions Quickly ##
+
+Sometimes you'll want to parameterize an action you define.  For that
+we have another macro
+```
+ACTION_P(name, param) { statements; }
+```
+
+For example,
+```
+ACTION_P(Add, n) { return arg0 + n; }
+```
+will allow you to write
+```
+// Returns argument #0 + 5.
+... WillOnce(Add(5));
+```
+
+For convenience, we use the term _arguments_ for the values used to
+invoke the mock function, and the term _parameters_ for the values
+used to instantiate an action.
+
+Note that you don't need to provide the type of the parameter either.
+Suppose the parameter is named `param`, you can also use the
+Google-Mock-defined symbol `param_type` to refer to the type of the
+parameter as inferred by the compiler.  For example, in the body of
+`ACTION_P(Add, n)` above, you can write `n_type` for the type of `n`.
+
+Google Mock also provides `ACTION_P2`, `ACTION_P3`, and etc to support
+multi-parameter actions.  For example,
+```
+ACTION_P2(ReturnDistanceTo, x, y) {
+  double dx = arg0 - x;
+  double dy = arg1 - y;
+  return sqrt(dx*dx + dy*dy);
+}
+```
+lets you write
+```
+... WillOnce(ReturnDistanceTo(5.0, 26.5));
+```
+
+You can view `ACTION` as a degenerated parameterized action where the
+number of parameters is 0.
+
+You can also easily define actions overloaded on the number of parameters:
+```
+ACTION_P(Plus, a) { ... }
+ACTION_P2(Plus, a, b) { ... }
+```
+
+## Restricting the Type of an Argument or Parameter in an ACTION ##
+
+For maximum brevity and reusability, the `ACTION*` macros don't ask
+you to provide the types of the mock function arguments and the action
+parameters.  Instead, we let the compiler infer the types for us.
+
+Sometimes, however, we may want to be more explicit about the types.
+There are several tricks to do that.  For example:
+```
+ACTION(Foo) {
+  // Makes sure arg0 can be converted to int.
+  int n = arg0;
+  ... use n instead of arg0 here ...
+}
+
+ACTION_P(Bar, param) {
+  // Makes sure the type of arg1 is const char*.
+  ::testing::StaticAssertTypeEq<const char*, arg1_type>();
+
+  // Makes sure param can be converted to bool.
+  bool flag = param;
+}
+```
+where `StaticAssertTypeEq` is a compile-time assertion in Google Test
+that verifies two types are the same.
+
+## Writing New Action Templates Quickly ##
+
+Sometimes you want to give an action explicit template parameters that
+cannot be inferred from its value parameters.  `ACTION_TEMPLATE()`
+supports that and can be viewed as an extension to `ACTION()` and
+`ACTION_P*()`.
+
+The syntax:
+```
+ACTION_TEMPLATE(ActionName,
+                HAS_m_TEMPLATE_PARAMS(kind1, name1, ..., kind_m, name_m),
+                AND_n_VALUE_PARAMS(p1, ..., p_n)) { statements; }
+```
+
+defines an action template that takes _m_ explicit template parameters
+and _n_ value parameters, where _m_ is between 1 and 10, and _n_ is
+between 0 and 10.  `name_i` is the name of the i-th template
+parameter, and `kind_i` specifies whether it's a `typename`, an
+integral constant, or a template.  `p_i` is the name of the i-th value
+parameter.
+
+Example:
+```
+// DuplicateArg<k, T>(output) converts the k-th argument of the mock
+// function to type T and copies it to *output.
+ACTION_TEMPLATE(DuplicateArg,
+                // Note the comma between int and k:
+                HAS_2_TEMPLATE_PARAMS(int, k, typename, T),
+                AND_1_VALUE_PARAMS(output)) {
+  *output = T(std::tr1::get<k>(args));
+}
+```
+
+To create an instance of an action template, write:
+```
+  ActionName<t1, ..., t_m>(v1, ..., v_n)
+```
+where the `t`s are the template arguments and the
+`v`s are the value arguments.  The value argument
+types are inferred by the compiler.  For example:
+```
+using ::testing::_;
+...
+  int n;
+  EXPECT_CALL(mock, Foo(_, _))
+      .WillOnce(DuplicateArg<1, unsigned char>(&n));
+```
+
+If you want to explicitly specify the value argument types, you can
+provide additional template arguments:
+```
+  ActionName<t1, ..., t_m, u1, ..., u_k>(v1, ..., v_n)
+```
+where `u_i` is the desired type of `v_i`.
+
+`ACTION_TEMPLATE` and `ACTION`/`ACTION_P*` can be overloaded on the
+number of value parameters, but not on the number of template
+parameters.  Without the restriction, the meaning of the following is
+unclear:
+
+```
+  OverloadedAction<int, bool>(x);
+```
+
+Are we using a single-template-parameter action where `bool` refers to
+the type of `x`, or a two-template-parameter action where the compiler
+is asked to infer the type of `x`?
+
+## Using the ACTION Object's Type ##
+
+If you are writing a function that returns an `ACTION` object, you'll
+need to know its type.  The type depends on the macro used to define
+the action and the parameter types.  The rule is relatively simple:
+| **Given Definition** | **Expression** | **Has Type** |
+|:---------------------|:---------------|:-------------|
+| `ACTION(Foo)`        | `Foo()`        | `FooAction`  |
+| `ACTION_TEMPLATE(Foo, HAS_m_TEMPLATE_PARAMS(...), AND_0_VALUE_PARAMS())` |	`Foo<t1, ..., t_m>()` | `FooAction<t1, ..., t_m>` |
+| `ACTION_P(Bar, param)` | `Bar(int_value)` | `BarActionP<int>` |
+| `ACTION_TEMPLATE(Bar, HAS_m_TEMPLATE_PARAMS(...), AND_1_VALUE_PARAMS(p1))` | `Bar<t1, ..., t_m>(int_value)` | `FooActionP<t1, ..., t_m, int>` |
+| `ACTION_P2(Baz, p1, p2)` | `Baz(bool_value, int_value)` | `BazActionP2<bool, int>` |
+| `ACTION_TEMPLATE(Baz, HAS_m_TEMPLATE_PARAMS(...), AND_2_VALUE_PARAMS(p1, p2))` | `Baz<t1, ..., t_m>(bool_value, int_value)` | `FooActionP2<t1, ..., t_m, bool, int>` |
+| ...                  | ...            | ...          |
+
+Note that we have to pick different suffixes (`Action`, `ActionP`,
+`ActionP2`, and etc) for actions with different numbers of value
+parameters, or the action definitions cannot be overloaded on the
+number of them.
+
+## Writing New Monomorphic Actions ##
+
+While the `ACTION*` macros are very convenient, sometimes they are
+inappropriate.  For example, despite the tricks shown in the previous
+recipes, they don't let you directly specify the types of the mock
+function arguments and the action parameters, which in general leads
+to unoptimized compiler error messages that can baffle unfamiliar
+users.  They also don't allow overloading actions based on parameter
+types without jumping through some hoops.
+
+An alternative to the `ACTION*` macros is to implement
+`::testing::ActionInterface<F>`, where `F` is the type of the mock
+function in which the action will be used. For example:
+
+```
+template <typename F>class ActionInterface {
+ public:
+  virtual ~ActionInterface();
+
+  // Performs the action.  Result is the return type of function type
+  // F, and ArgumentTuple is the tuple of arguments of F.
+  //
+  // For example, if F is int(bool, const string&), then Result would
+  // be int, and ArgumentTuple would be tr1::tuple<bool, const string&>.
+  virtual Result Perform(const ArgumentTuple& args) = 0;
+};
+
+using ::testing::_;
+using ::testing::Action;
+using ::testing::ActionInterface;
+using ::testing::MakeAction;
+
+typedef int IncrementMethod(int*);
+
+class IncrementArgumentAction : public ActionInterface<IncrementMethod> {
+ public:
+  virtual int Perform(const tr1::tuple<int*>& args) {
+    int* p = tr1::get<0>(args);  // Grabs the first argument.
+    return *p++;
+  }
+};
+
+Action<IncrementMethod> IncrementArgument() {
+  return MakeAction(new IncrementArgumentAction);
+}
+...
+
+  EXPECT_CALL(foo, Baz(_))
+      .WillOnce(IncrementArgument());
+
+  int n = 5;
+  foo.Baz(&n);  // Should return 5 and change n to 6.
+```
+
+## Writing New Polymorphic Actions ##
+
+The previous recipe showed you how to define your own action. This is
+all good, except that you need to know the type of the function in
+which the action will be used. Sometimes that can be a problem. For
+example, if you want to use the action in functions with _different_
+types (e.g. like `Return()` and `SetArgPointee()`).
+
+If an action can be used in several types of mock functions, we say
+it's _polymorphic_. The `MakePolymorphicAction()` function template
+makes it easy to define such an action:
+
+```
+namespace testing {
+
+template <typename Impl>
+PolymorphicAction<Impl> MakePolymorphicAction(const Impl& impl);
+
+}  // namespace testing
+```
+
+As an example, let's define an action that returns the second argument
+in the mock function's argument list. The first step is to define an
+implementation class:
+
+```
+class ReturnSecondArgumentAction {
+ public:
+  template <typename Result, typename ArgumentTuple>
+  Result Perform(const ArgumentTuple& args) const {
+    // To get the i-th (0-based) argument, use tr1::get<i>(args).
+    return tr1::get<1>(args);
+  }
+};
+```
+
+This implementation class does _not_ need to inherit from any
+particular class. What matters is that it must have a `Perform()`
+method template. This method template takes the mock function's
+arguments as a tuple in a **single** argument, and returns the result of
+the action. It can be either `const` or not, but must be invokable
+with exactly one template argument, which is the result type. In other
+words, you must be able to call `Perform<R>(args)` where `R` is the
+mock function's return type and `args` is its arguments in a tuple.
+
+Next, we use `MakePolymorphicAction()` to turn an instance of the
+implementation class into the polymorphic action we need. It will be
+convenient to have a wrapper for this:
+
+```
+using ::testing::MakePolymorphicAction;
+using ::testing::PolymorphicAction;
+
+PolymorphicAction<ReturnSecondArgumentAction> ReturnSecondArgument() {
+  return MakePolymorphicAction(ReturnSecondArgumentAction());
+}
+```
+
+Now, you can use this polymorphic action the same way you use the
+built-in ones:
+
+```
+using ::testing::_;
+
+class MockFoo : public Foo {
+ public:
+  MOCK_METHOD2(DoThis, int(bool flag, int n));
+  MOCK_METHOD3(DoThat, string(int x, const char* str1, const char* str2));
+};
+...
+
+  MockFoo foo;
+  EXPECT_CALL(foo, DoThis(_, _))
+      .WillOnce(ReturnSecondArgument());
+  EXPECT_CALL(foo, DoThat(_, _, _))
+      .WillOnce(ReturnSecondArgument());
+  ...
+  foo.DoThis(true, 5);         // Will return 5.
+  foo.DoThat(1, "Hi", "Bye");  // Will return "Hi".
+```
+
+## Teaching Google Mock How to Print Your Values ##
+
+When an uninteresting or unexpected call occurs, Google Mock prints the
+argument values and the stack trace to help you debug.  Assertion
+macros like `EXPECT_THAT` and `EXPECT_EQ` also print the values in
+question when the assertion fails.  Google Mock and Google Test do this using
+Google Test's user-extensible value printer.
+
+This printer knows how to print built-in C++ types, native arrays, STL
+containers, and any type that supports the `<<` operator.  For other
+types, it prints the raw bytes in the value and hopes that you the
+user can figure it out.
+[Google Test's advanced guide](http://code.google.com/p/googletest/wiki/AdvancedGuide#Teaching_Google_Test_How_to_Print_Your_Values)
+explains how to extend the printer to do a better job at
+printing your particular type than to dump the bytes.
\ No newline at end of file
diff --git a/third_party/googletest/googlemock/docs/v1_7/Documentation.md b/third_party/googletest/googlemock/docs/v1_7/Documentation.md
new file mode 100644
index 0000000..d9181f2
--- /dev/null
+++ b/third_party/googletest/googlemock/docs/v1_7/Documentation.md
@@ -0,0 +1,12 @@
+This page lists all documentation wiki pages for Google Mock **(the SVN trunk version)**
+- **if you use a released version of Google Mock, please read the documentation for that specific version instead.**
+
+  * [ForDummies](V1_7_ForDummies.md) -- start here if you are new to Google Mock.
+  * [CheatSheet](V1_7_CheatSheet.md) -- a quick reference.
+  * [CookBook](V1_7_CookBook.md) -- recipes for doing various tasks using Google Mock.
+  * [FrequentlyAskedQuestions](V1_7_FrequentlyAskedQuestions.md) -- check here before asking a question on the mailing list.
+
+To contribute code to Google Mock, read:
+
+  * [DevGuide](DevGuide.md) -- read this _before_ writing your first patch.
+  * [Pump Manual](http://code.google.com/p/googletest/wiki/PumpManual) -- how we generate some of Google Mock's source files.
\ No newline at end of file
diff --git a/third_party/googletest/googlemock/docs/v1_7/ForDummies.md b/third_party/googletest/googlemock/docs/v1_7/ForDummies.md
new file mode 100644
index 0000000..2ed4300
--- /dev/null
+++ b/third_party/googletest/googlemock/docs/v1_7/ForDummies.md
@@ -0,0 +1,439 @@
+
+
+(**Note:** If you get compiler errors that you don't understand, be sure to consult [Google Mock Doctor](http://code.google.com/p/googlemock/wiki/V1_7_FrequentlyAskedQuestions#How_am_I_supposed_to_make_sense_of_these_horrible_template_error).)
+
+# What Is Google C++ Mocking Framework? #
+When you write a prototype or test, often it's not feasible or wise to rely on real objects entirely. A **mock object** implements the same interface as a real object (so it can be used as one), but lets you specify at run time how it will be used and what it should do (which methods will be called? in which order? how many times? with what arguments? what will they return? etc).
+
+**Note:** It is easy to confuse the term _fake objects_ with mock objects. Fakes and mocks actually mean very different things in the Test-Driven Development (TDD) community:
+
+  * **Fake** objects have working implementations, but usually take some shortcut (perhaps to make the operations less expensive), which makes them not suitable for production. An in-memory file system would be an example of a fake.
+  * **Mocks** are objects pre-programmed with _expectations_, which form a specification of the calls they are expected to receive.
+
+If all this seems too abstract for you, don't worry - the most important thing to remember is that a mock allows you to check the _interaction_ between itself and code that uses it. The difference between fakes and mocks will become much clearer once you start to use mocks.
+
+**Google C++ Mocking Framework** (or **Google Mock** for short) is a library (sometimes we also call it a "framework" to make it sound cool) for creating mock classes and using them. It does to C++ what [jMock](http://www.jmock.org/) and [EasyMock](http://www.easymock.org/) do to Java.
+
+Using Google Mock involves three basic steps:
+
+  1. Use some simple macros to describe the interface you want to mock, and they will expand to the implementation of your mock class;
+  1. Create some mock objects and specify its expectations and behavior using an intuitive syntax;
+  1. Exercise code that uses the mock objects. Google Mock will catch any violation of the expectations as soon as it arises.
+
+# Why Google Mock? #
+While mock objects help you remove unnecessary dependencies in tests and make them fast and reliable, using mocks manually in C++ is _hard_:
+
+  * Someone has to implement the mocks. The job is usually tedious and error-prone. No wonder people go great distance to avoid it.
+  * The quality of those manually written mocks is a bit, uh, unpredictable. You may see some really polished ones, but you may also see some that were hacked up in a hurry and have all sorts of ad hoc restrictions.
+  * The knowledge you gained from using one mock doesn't transfer to the next.
+
+In contrast, Java and Python programmers have some fine mock frameworks, which automate the creation of mocks. As a result, mocking is a proven effective technique and widely adopted practice in those communities. Having the right tool absolutely makes the difference.
+
+Google Mock was built to help C++ programmers. It was inspired by [jMock](http://www.jmock.org/) and [EasyMock](http://www.easymock.org/), but designed with C++'s specifics in mind. It is your friend if any of the following problems is bothering you:
+
+  * You are stuck with a sub-optimal design and wish you had done more prototyping before it was too late, but prototyping in C++ is by no means "rapid".
+  * Your tests are slow as they depend on too many libraries or use expensive resources (e.g. a database).
+  * Your tests are brittle as some resources they use are unreliable (e.g. the network).
+  * You want to test how your code handles a failure (e.g. a file checksum error), but it's not easy to cause one.
+  * You need to make sure that your module interacts with other modules in the right way, but it's hard to observe the interaction; therefore you resort to observing the side effects at the end of the action, which is awkward at best.
+  * You want to "mock out" your dependencies, except that they don't have mock implementations yet; and, frankly, you aren't thrilled by some of those hand-written mocks.
+
+We encourage you to use Google Mock as:
+
+  * a _design_ tool, for it lets you experiment with your interface design early and often. More iterations lead to better designs!
+  * a _testing_ tool to cut your tests' outbound dependencies and probe the interaction between your module and its collaborators.
+
+# Getting Started #
+Using Google Mock is easy! Inside your C++ source file, just #include `"gtest/gtest.h"` and `"gmock/gmock.h"`, and you are ready to go.
+
+# A Case for Mock Turtles #
+Let's look at an example. Suppose you are developing a graphics program that relies on a LOGO-like API for drawing. How would you test that it does the right thing? Well, you can run it and compare the screen with a golden screen snapshot, but let's admit it: tests like this are expensive to run and fragile (What if you just upgraded to a shiny new graphics card that has better anti-aliasing? Suddenly you have to update all your golden images.). It would be too painful if all your tests are like this. Fortunately, you learned about Dependency Injection and know the right thing to do: instead of having your application talk to the drawing API directly, wrap the API in an interface (say, `Turtle`) and code to that interface:
+
+```
+class Turtle {
+  ...
+  virtual ~Turtle() {}
+  virtual void PenUp() = 0;
+  virtual void PenDown() = 0;
+  virtual void Forward(int distance) = 0;
+  virtual void Turn(int degrees) = 0;
+  virtual void GoTo(int x, int y) = 0;
+  virtual int GetX() const = 0;
+  virtual int GetY() const = 0;
+};
+```
+
+(Note that the destructor of `Turtle` **must** be virtual, as is the case for **all** classes you intend to inherit from - otherwise the destructor of the derived class will not be called when you delete an object through a base pointer, and you'll get corrupted program states like memory leaks.)
+
+You can control whether the turtle's movement will leave a trace using `PenUp()` and `PenDown()`, and control its movement using `Forward()`, `Turn()`, and `GoTo()`. Finally, `GetX()` and `GetY()` tell you the current position of the turtle.
+
+Your program will normally use a real implementation of this interface. In tests, you can use a mock implementation instead. This allows you to easily check what drawing primitives your program is calling, with what arguments, and in which order. Tests written this way are much more robust (they won't break because your new machine does anti-aliasing differently), easier to read and maintain (the intent of a test is expressed in the code, not in some binary images), and run _much, much faster_.
+
+# Writing the Mock Class #
+If you are lucky, the mocks you need to use have already been implemented by some nice people. If, however, you find yourself in the position to write a mock class, relax - Google Mock turns this task into a fun game! (Well, almost.)
+
+## How to Define It ##
+Using the `Turtle` interface as example, here are the simple steps you need to follow:
+
+  1. Derive a class `MockTurtle` from `Turtle`.
+  1. Take a _virtual_ function of `Turtle` (while it's possible to [mock non-virtual methods using templates](http://code.google.com/p/googlemock/wiki/V1_7_CookBook#Mocking_Nonvirtual_Methods), it's much more involved). Count how many arguments it has.
+  1. In the `public:` section of the child class, write `MOCK_METHODn();` (or `MOCK_CONST_METHODn();` if you are mocking a `const` method), where `n` is the number of the arguments; if you counted wrong, shame on you, and a compiler error will tell you so.
+  1. Now comes the fun part: you take the function signature, cut-and-paste the _function name_ as the _first_ argument to the macro, and leave what's left as the _second_ argument (in case you're curious, this is the _type of the function_).
+  1. Repeat until all virtual functions you want to mock are done.
+
+After the process, you should have something like:
+
+```
+#include "gmock/gmock.h"  // Brings in Google Mock.
+class MockTurtle : public Turtle {
+ public:
+  ...
+  MOCK_METHOD0(PenUp, void());
+  MOCK_METHOD0(PenDown, void());
+  MOCK_METHOD1(Forward, void(int distance));
+  MOCK_METHOD1(Turn, void(int degrees));
+  MOCK_METHOD2(GoTo, void(int x, int y));
+  MOCK_CONST_METHOD0(GetX, int());
+  MOCK_CONST_METHOD0(GetY, int());
+};
+```
+
+You don't need to define these mock methods somewhere else - the `MOCK_METHOD*` macros will generate the definitions for you. It's that simple! Once you get the hang of it, you can pump out mock classes faster than your source-control system can handle your check-ins.
+
+**Tip:** If even this is too much work for you, you'll find the
+`gmock_gen.py` tool in Google Mock's `scripts/generator/` directory (courtesy of the [cppclean](http://code.google.com/p/cppclean/) project) useful.  This command-line
+tool requires that you have Python 2.4 installed.  You give it a C++ file and the name of an abstract class defined in it,
+and it will print the definition of the mock class for you.  Due to the
+complexity of the C++ language, this script may not always work, but
+it can be quite handy when it does.  For more details, read the [user documentation](http://code.google.com/p/googlemock/source/browse/trunk/scripts/generator/README).
+
+## Where to Put It ##
+When you define a mock class, you need to decide where to put its definition. Some people put it in a `*_test.cc`. This is fine when the interface being mocked (say, `Foo`) is owned by the same person or team. Otherwise, when the owner of `Foo` changes it, your test could break. (You can't really expect `Foo`'s maintainer to fix every test that uses `Foo`, can you?)
+
+So, the rule of thumb is: if you need to mock `Foo` and it's owned by others, define the mock class in `Foo`'s package (better, in a `testing` sub-package such that you can clearly separate production code and testing utilities), and put it in a `mock_foo.h`. Then everyone can reference `mock_foo.h` from their tests. If `Foo` ever changes, there is only one copy of `MockFoo` to change, and only tests that depend on the changed methods need to be fixed.
+
+Another way to do it: you can introduce a thin layer `FooAdaptor` on top of `Foo` and code to this new interface. Since you own `FooAdaptor`, you can absorb changes in `Foo` much more easily. While this is more work initially, carefully choosing the adaptor interface can make your code easier to write and more readable (a net win in the long run), as you can choose `FooAdaptor` to fit your specific domain much better than `Foo` does.
+
+# Using Mocks in Tests #
+Once you have a mock class, using it is easy. The typical work flow is:
+
+  1. Import the Google Mock names from the `testing` namespace such that you can use them unqualified (You only have to do it once per file. Remember that namespaces are a good idea and good for your health.).
+  1. Create some mock objects.
+  1. Specify your expectations on them (How many times will a method be called? With what arguments? What should it do? etc.).
+  1. Exercise some code that uses the mocks; optionally, check the result using Google Test assertions. If a mock method is called more than expected or with wrong arguments, you'll get an error immediately.
+  1. When a mock is destructed, Google Mock will automatically check whether all expectations on it have been satisfied.
+
+Here's an example:
+
+```
+#include "path/to/mock-turtle.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+using ::testing::AtLeast;                     // #1
+
+TEST(PainterTest, CanDrawSomething) {
+  MockTurtle turtle;                          // #2
+  EXPECT_CALL(turtle, PenDown())              // #3
+      .Times(AtLeast(1));
+
+  Painter painter(&turtle);                   // #4
+
+  EXPECT_TRUE(painter.DrawCircle(0, 0, 10));
+}                                             // #5
+
+int main(int argc, char** argv) {
+  // The following line must be executed to initialize Google Mock
+  // (and Google Test) before running the tests.
+  ::testing::InitGoogleMock(&argc, argv);
+  return RUN_ALL_TESTS();
+}
+```
+
+As you might have guessed, this test checks that `PenDown()` is called at least once. If the `painter` object didn't call this method, your test will fail with a message like this:
+
+```
+path/to/my_test.cc:119: Failure
+Actual function call count doesn't match this expectation:
+Actually: never called;
+Expected: called at least once.
+```
+
+**Tip 1:** If you run the test from an Emacs buffer, you can hit `<Enter>` on the line number displayed in the error message to jump right to the failed expectation.
+
+**Tip 2:** If your mock objects are never deleted, the final verification won't happen. Therefore it's a good idea to use a heap leak checker in your tests when you allocate mocks on the heap.
+
+**Important note:** Google Mock requires expectations to be set **before** the mock functions are called, otherwise the behavior is **undefined**. In particular, you mustn't interleave `EXPECT_CALL()`s and calls to the mock functions.
+
+This means `EXPECT_CALL()` should be read as expecting that a call will occur _in the future_, not that a call has occurred. Why does Google Mock work like that? Well, specifying the expectation beforehand allows Google Mock to report a violation as soon as it arises, when the context (stack trace, etc) is still available. This makes debugging much easier.
+
+Admittedly, this test is contrived and doesn't do much. You can easily achieve the same effect without using Google Mock. However, as we shall reveal soon, Google Mock allows you to do _much more_ with the mocks.
+
+## Using Google Mock with Any Testing Framework ##
+If you want to use something other than Google Test (e.g. [CppUnit](http://apps.sourceforge.net/mediawiki/cppunit/index.php?title=Main_Page) or
+[CxxTest](http://cxxtest.tigris.org/)) as your testing framework, just change the `main()` function in the previous section to:
+```
+int main(int argc, char** argv) {
+  // The following line causes Google Mock to throw an exception on failure,
+  // which will be interpreted by your testing framework as a test failure.
+  ::testing::GTEST_FLAG(throw_on_failure) = true;
+  ::testing::InitGoogleMock(&argc, argv);
+  ... whatever your testing framework requires ...
+}
+```
+
+This approach has a catch: it makes Google Mock throw an exception
+from a mock object's destructor sometimes.  With some compilers, this
+sometimes causes the test program to crash.  You'll still be able to
+notice that the test has failed, but it's not a graceful failure.
+
+A better solution is to use Google Test's
+[event listener API](http://code.google.com/p/googletest/wiki/AdvancedGuide#Extending_Google_Test_by_Handling_Test_Events)
+to report a test failure to your testing framework properly.  You'll need to
+implement the `OnTestPartResult()` method of the event listener interface, but it
+should be straightforward.
+
+If this turns out to be too much work, we suggest that you stick with
+Google Test, which works with Google Mock seamlessly (in fact, it is
+technically part of Google Mock.).  If there is a reason that you
+cannot use Google Test, please let us know.
+
+# Setting Expectations #
+The key to using a mock object successfully is to set the _right expectations_ on it. If you set the expectations too strict, your test will fail as the result of unrelated changes. If you set them too loose, bugs can slip through. You want to do it just right such that your test can catch exactly the kind of bugs you intend it to catch. Google Mock provides the necessary means for you to do it "just right."
+
+## General Syntax ##
+In Google Mock we use the `EXPECT_CALL()` macro to set an expectation on a mock method. The general syntax is:
+
+```
+EXPECT_CALL(mock_object, method(matchers))
+    .Times(cardinality)
+    .WillOnce(action)
+    .WillRepeatedly(action);
+```
+
+The macro has two arguments: first the mock object, and then the method and its arguments. Note that the two are separated by a comma (`,`), not a period (`.`). (Why using a comma? The answer is that it was necessary for technical reasons.)
+
+The macro can be followed by some optional _clauses_ that provide more information about the expectation. We'll discuss how each clause works in the coming sections.
+
+This syntax is designed to make an expectation read like English. For example, you can probably guess that
+
+```
+using ::testing::Return;...
+EXPECT_CALL(turtle, GetX())
+    .Times(5)
+    .WillOnce(Return(100))
+    .WillOnce(Return(150))
+    .WillRepeatedly(Return(200));
+```
+
+says that the `turtle` object's `GetX()` method will be called five times, it will return 100 the first time, 150 the second time, and then 200 every time. Some people like to call this style of syntax a Domain-Specific Language (DSL).
+
+**Note:** Why do we use a macro to do this? It serves two purposes: first it makes expectations easily identifiable (either by `grep` or by a human reader), and second it allows Google Mock to include the source file location of a failed expectation in messages, making debugging easier.
+
+## Matchers: What Arguments Do We Expect? ##
+When a mock function takes arguments, we must specify what arguments we are expecting; for example:
+
+```
+// Expects the turtle to move forward by 100 units.
+EXPECT_CALL(turtle, Forward(100));
+```
+
+Sometimes you may not want to be too specific (Remember that talk about tests being too rigid? Over specification leads to brittle tests and obscures the intent of tests. Therefore we encourage you to specify only what's necessary - no more, no less.). If you care to check that `Forward()` will be called but aren't interested in its actual argument, write `_` as the argument, which means "anything goes":
+
+```
+using ::testing::_;
+...
+// Expects the turtle to move forward.
+EXPECT_CALL(turtle, Forward(_));
+```
+
+`_` is an instance of what we call **matchers**. A matcher is like a predicate and can test whether an argument is what we'd expect. You can use a matcher inside `EXPECT_CALL()` wherever a function argument is expected.
+
+A list of built-in matchers can be found in the [CheatSheet](V1_7_CheatSheet.md). For example, here's the `Ge` (greater than or equal) matcher:
+
+```
+using ::testing::Ge;...
+EXPECT_CALL(turtle, Forward(Ge(100)));
+```
+
+This checks that the turtle will be told to go forward by at least 100 units.
+
+## Cardinalities: How Many Times Will It Be Called? ##
+The first clause we can specify following an `EXPECT_CALL()` is `Times()`. We call its argument a **cardinality** as it tells _how many times_ the call should occur. It allows us to repeat an expectation many times without actually writing it as many times. More importantly, a cardinality can be "fuzzy", just like a matcher can be. This allows a user to express the intent of a test exactly.
+
+An interesting special case is when we say `Times(0)`. You may have guessed - it means that the function shouldn't be called with the given arguments at all, and Google Mock will report a Google Test failure whenever the function is (wrongfully) called.
+
+We've seen `AtLeast(n)` as an example of fuzzy cardinalities earlier. For the list of built-in cardinalities you can use, see the [CheatSheet](V1_7_CheatSheet.md).
+
+The `Times()` clause can be omitted. **If you omit `Times()`, Google Mock will infer the cardinality for you.** The rules are easy to remember:
+
+  * If **neither** `WillOnce()` **nor** `WillRepeatedly()` is in the `EXPECT_CALL()`, the inferred cardinality is `Times(1)`.
+  * If there are `n WillOnce()`'s but **no** `WillRepeatedly()`, where `n` >= 1, the cardinality is `Times(n)`.
+  * If there are `n WillOnce()`'s and **one** `WillRepeatedly()`, where `n` >= 0, the cardinality is `Times(AtLeast(n))`.
+
+**Quick quiz:** what do you think will happen if a function is expected to be called twice but actually called four times?
+
+## Actions: What Should It Do? ##
+Remember that a mock object doesn't really have a working implementation? We as users have to tell it what to do when a method is invoked. This is easy in Google Mock.
+
+First, if the return type of a mock function is a built-in type or a pointer, the function has a **default action** (a `void` function will just return, a `bool` function will return `false`, and other functions will return 0). If you don't say anything, this behavior will be used.
+
+Second, if a mock function doesn't have a default action, or the default action doesn't suit you, you can specify the action to be taken each time the expectation matches using a series of `WillOnce()` clauses followed by an optional `WillRepeatedly()`. For example,
+
+```
+using ::testing::Return;...
+EXPECT_CALL(turtle, GetX())
+    .WillOnce(Return(100))
+    .WillOnce(Return(200))
+    .WillOnce(Return(300));
+```
+
+This says that `turtle.GetX()` will be called _exactly three times_ (Google Mock inferred this from how many `WillOnce()` clauses we've written, since we didn't explicitly write `Times()`), and will return 100, 200, and 300 respectively.
+
+```
+using ::testing::Return;...
+EXPECT_CALL(turtle, GetY())
+    .WillOnce(Return(100))
+    .WillOnce(Return(200))
+    .WillRepeatedly(Return(300));
+```
+
+says that `turtle.GetY()` will be called _at least twice_ (Google Mock knows this as we've written two `WillOnce()` clauses and a `WillRepeatedly()` while having no explicit `Times()`), will return 100 the first time, 200 the second time, and 300 from the third time on.
+
+Of course, if you explicitly write a `Times()`, Google Mock will not try to infer the cardinality itself. What if the number you specified is larger than there are `WillOnce()` clauses? Well, after all `WillOnce()`s are used up, Google Mock will do the _default_ action for the function every time (unless, of course, you have a `WillRepeatedly()`.).
+
+What can we do inside `WillOnce()` besides `Return()`? You can return a reference using `ReturnRef(variable)`, or invoke a pre-defined function, among [others](http://code.google.com/p/googlemock/wiki/V1_7_CheatSheet#Actions).
+
+**Important note:** The `EXPECT_CALL()` statement evaluates the action clause only once, even though the action may be performed many times. Therefore you must be careful about side effects. The following may not do what you want:
+
+```
+int n = 100;
+EXPECT_CALL(turtle, GetX())
+.Times(4)
+.WillRepeatedly(Return(n++));
+```
+
+Instead of returning 100, 101, 102, ..., consecutively, this mock function will always return 100 as `n++` is only evaluated once. Similarly, `Return(new Foo)` will create a new `Foo` object when the `EXPECT_CALL()` is executed, and will return the same pointer every time. If you want the side effect to happen every time, you need to define a custom action, which we'll teach in the [CookBook](V1_7_CookBook.md).
+
+Time for another quiz! What do you think the following means?
+
+```
+using ::testing::Return;...
+EXPECT_CALL(turtle, GetY())
+.Times(4)
+.WillOnce(Return(100));
+```
+
+Obviously `turtle.GetY()` is expected to be called four times. But if you think it will return 100 every time, think twice! Remember that one `WillOnce()` clause will be consumed each time the function is invoked and the default action will be taken afterwards. So the right answer is that `turtle.GetY()` will return 100 the first time, but **return 0 from the second time on**, as returning 0 is the default action for `int` functions.
+
+## Using Multiple Expectations ##
+So far we've only shown examples where you have a single expectation. More realistically, you're going to specify expectations on multiple mock methods, which may be from multiple mock objects.
+
+By default, when a mock method is invoked, Google Mock will search the expectations in the **reverse order** they are defined, and stop when an active expectation that matches the arguments is found (you can think of it as "newer rules override older ones."). If the matching expectation cannot take any more calls, you will get an upper-bound-violated failure. Here's an example:
+
+```
+using ::testing::_;...
+EXPECT_CALL(turtle, Forward(_));  // #1
+EXPECT_CALL(turtle, Forward(10))  // #2
+    .Times(2);
+```
+
+If `Forward(10)` is called three times in a row, the third time it will be an error, as the last matching expectation (#2) has been saturated. If, however, the third `Forward(10)` call is replaced by `Forward(20)`, then it would be OK, as now #1 will be the matching expectation.
+
+**Side note:** Why does Google Mock search for a match in the _reverse_ order of the expectations? The reason is that this allows a user to set up the default expectations in a mock object's constructor or the test fixture's set-up phase and then customize the mock by writing more specific expectations in the test body. So, if you have two expectations on the same method, you want to put the one with more specific matchers **after** the other, or the more specific rule would be shadowed by the more general one that comes after it.
+
+## Ordered vs Unordered Calls ##
+By default, an expectation can match a call even though an earlier expectation hasn't been satisfied. In other words, the calls don't have to occur in the order the expectations are specified.
+
+Sometimes, you may want all the expected calls to occur in a strict order. To say this in Google Mock is easy:
+
+```
+using ::testing::InSequence;...
+TEST(FooTest, DrawsLineSegment) {
+  ...
+  {
+    InSequence dummy;
+
+    EXPECT_CALL(turtle, PenDown());
+    EXPECT_CALL(turtle, Forward(100));
+    EXPECT_CALL(turtle, PenUp());
+  }
+  Foo();
+}
+```
+
+By creating an object of type `InSequence`, all expectations in its scope are put into a _sequence_ and have to occur _sequentially_. Since we are just relying on the constructor and destructor of this object to do the actual work, its name is really irrelevant.
+
+In this example, we test that `Foo()` calls the three expected functions in the order as written. If a call is made out-of-order, it will be an error.
+
+(What if you care about the relative order of some of the calls, but not all of them? Can you specify an arbitrary partial order? The answer is ... yes! If you are impatient, the details can be found in the [CookBook](V1_7_CookBook#Expecting_Partially_Ordered_Calls.md).)
+
+## All Expectations Are Sticky (Unless Said Otherwise) ##
+Now let's do a quick quiz to see how well you can use this mock stuff already. How would you test that the turtle is asked to go to the origin _exactly twice_ (you want to ignore any other instructions it receives)?
+
+After you've come up with your answer, take a look at ours and compare notes (solve it yourself first - don't cheat!):
+
+```
+using ::testing::_;...
+EXPECT_CALL(turtle, GoTo(_, _))  // #1
+    .Times(AnyNumber());
+EXPECT_CALL(turtle, GoTo(0, 0))  // #2
+    .Times(2);
+```
+
+Suppose `turtle.GoTo(0, 0)` is called three times. In the third time, Google Mock will see that the arguments match expectation #2 (remember that we always pick the last matching expectation). Now, since we said that there should be only two such calls, Google Mock will report an error immediately. This is basically what we've told you in the "Using Multiple Expectations" section above.
+
+This example shows that **expectations in Google Mock are "sticky" by default**, in the sense that they remain active even after we have reached their invocation upper bounds. This is an important rule to remember, as it affects the meaning of the spec, and is **different** to how it's done in many other mocking frameworks (Why'd we do that? Because we think our rule makes the common cases easier to express and understand.).
+
+Simple? Let's see if you've really understood it: what does the following code say?
+
+```
+using ::testing::Return;
+...
+for (int i = n; i > 0; i--) {
+  EXPECT_CALL(turtle, GetX())
+      .WillOnce(Return(10*i));
+}
+```
+
+If you think it says that `turtle.GetX()` will be called `n` times and will return 10, 20, 30, ..., consecutively, think twice! The problem is that, as we said, expectations are sticky. So, the second time `turtle.GetX()` is called, the last (latest) `EXPECT_CALL()` statement will match, and will immediately lead to an "upper bound exceeded" error - this piece of code is not very useful!
+
+One correct way of saying that `turtle.GetX()` will return 10, 20, 30, ..., is to explicitly say that the expectations are _not_ sticky. In other words, they should _retire_ as soon as they are saturated:
+
+```
+using ::testing::Return;
+...
+for (int i = n; i > 0; i--) {
+  EXPECT_CALL(turtle, GetX())
+    .WillOnce(Return(10*i))
+    .RetiresOnSaturation();
+}
+```
+
+And, there's a better way to do it: in this case, we expect the calls to occur in a specific order, and we line up the actions to match the order. Since the order is important here, we should make it explicit using a sequence:
+
+```
+using ::testing::InSequence;
+using ::testing::Return;
+...
+{
+  InSequence s;
+
+  for (int i = 1; i <= n; i++) {
+    EXPECT_CALL(turtle, GetX())
+        .WillOnce(Return(10*i))
+        .RetiresOnSaturation();
+  }
+}
+```
+
+By the way, the other situation where an expectation may _not_ be sticky is when it's in a sequence - as soon as another expectation that comes after it in the sequence has been used, it automatically retires (and will never be used to match any call).
+
+## Uninteresting Calls ##
+A mock object may have many methods, and not all of them are that interesting. For example, in some tests we may not care about how many times `GetX()` and `GetY()` get called.
+
+In Google Mock, if you are not interested in a method, just don't say anything about it. If a call to this method occurs, you'll see a warning in the test output, but it won't be a failure.
+
+# What Now? #
+Congratulations! You've learned enough about Google Mock to start using it. Now, you might want to join the [googlemock](http://groups.google.com/group/googlemock) discussion group and actually write some tests using Google Mock - it will be fun. Hey, it may even be addictive - you've been warned.
+
+Then, if you feel like increasing your mock quotient, you should move on to the [CookBook](V1_7_CookBook.md). You can learn many advanced features of Google Mock there -- and advance your level of enjoyment and testing bliss.
\ No newline at end of file
diff --git a/third_party/googletest/googlemock/docs/v1_7/FrequentlyAskedQuestions.md b/third_party/googletest/googlemock/docs/v1_7/FrequentlyAskedQuestions.md
new file mode 100644
index 0000000..fa21233
--- /dev/null
+++ b/third_party/googletest/googlemock/docs/v1_7/FrequentlyAskedQuestions.md
@@ -0,0 +1,628 @@
+
+
+Please send your questions to the
+[googlemock](http://groups.google.com/group/googlemock) discussion
+group. If you need help with compiler errors, make sure you have
+tried [Google Mock Doctor](#How_am_I_supposed_to_make_sense_of_these_horrible_template_error.md) first.
+
+## When I call a method on my mock object, the method for the real object is invoked instead.  What's the problem? ##
+
+In order for a method to be mocked, it must be _virtual_, unless you use the [high-perf dependency injection technique](http://code.google.com/p/googlemock/wiki/V1_7_CookBook#Mocking_Nonvirtual_Methods).
+
+## I wrote some matchers.  After I upgraded to a new version of Google Mock, they no longer compile.  What's going on? ##
+
+After version 1.4.0 of Google Mock was released, we had an idea on how
+to make it easier to write matchers that can generate informative
+messages efficiently.  We experimented with this idea and liked what
+we saw.  Therefore we decided to implement it.
+
+Unfortunately, this means that if you have defined your own matchers
+by implementing `MatcherInterface` or using `MakePolymorphicMatcher()`,
+your definitions will no longer compile.  Matchers defined using the
+`MATCHER*` family of macros are not affected.
+
+Sorry for the hassle if your matchers are affected.  We believe it's
+in everyone's long-term interest to make this change sooner than
+later.  Fortunately, it's usually not hard to migrate an existing
+matcher to the new API.  Here's what you need to do:
+
+If you wrote your matcher like this:
+```
+// Old matcher definition that doesn't work with the latest
+// Google Mock.
+using ::testing::MatcherInterface;
+...
+class MyWonderfulMatcher : public MatcherInterface<MyType> {
+ public:
+  ...
+  virtual bool Matches(MyType value) const {
+    // Returns true if value matches.
+    return value.GetFoo() > 5;
+  }
+  ...
+};
+```
+
+you'll need to change it to:
+```
+// New matcher definition that works with the latest Google Mock.
+using ::testing::MatcherInterface;
+using ::testing::MatchResultListener;
+...
+class MyWonderfulMatcher : public MatcherInterface<MyType> {
+ public:
+  ...
+  virtual bool MatchAndExplain(MyType value,
+                               MatchResultListener* listener) const {
+    // Returns true if value matches.
+    return value.GetFoo() > 5;
+  }
+  ...
+};
+```
+(i.e. rename `Matches()` to `MatchAndExplain()` and give it a second
+argument of type `MatchResultListener*`.)
+
+If you were also using `ExplainMatchResultTo()` to improve the matcher
+message:
+```
+// Old matcher definition that doesn't work with the lastest
+// Google Mock.
+using ::testing::MatcherInterface;
+...
+class MyWonderfulMatcher : public MatcherInterface<MyType> {
+ public:
+  ...
+  virtual bool Matches(MyType value) const {
+    // Returns true if value matches.
+    return value.GetFoo() > 5;
+  }
+
+  virtual void ExplainMatchResultTo(MyType value,
+                                    ::std::ostream* os) const {
+    // Prints some helpful information to os to help
+    // a user understand why value matches (or doesn't match).
+    *os << "the Foo property is " << value.GetFoo();
+  }
+  ...
+};
+```
+
+you should move the logic of `ExplainMatchResultTo()` into
+`MatchAndExplain()`, using the `MatchResultListener` argument where
+the `::std::ostream` was used:
+```
+// New matcher definition that works with the latest Google Mock.
+using ::testing::MatcherInterface;
+using ::testing::MatchResultListener;
+...
+class MyWonderfulMatcher : public MatcherInterface<MyType> {
+ public:
+  ...
+  virtual bool MatchAndExplain(MyType value,
+                               MatchResultListener* listener) const {
+    // Returns true if value matches.
+    *listener << "the Foo property is " << value.GetFoo();
+    return value.GetFoo() > 5;
+  }
+  ...
+};
+```
+
+If your matcher is defined using `MakePolymorphicMatcher()`:
+```
+// Old matcher definition that doesn't work with the latest
+// Google Mock.
+using ::testing::MakePolymorphicMatcher;
+...
+class MyGreatMatcher {
+ public:
+  ...
+  bool Matches(MyType value) const {
+    // Returns true if value matches.
+    return value.GetBar() < 42;
+  }
+  ...
+};
+... MakePolymorphicMatcher(MyGreatMatcher()) ...
+```
+
+you should rename the `Matches()` method to `MatchAndExplain()` and
+add a `MatchResultListener*` argument (the same as what you need to do
+for matchers defined by implementing `MatcherInterface`):
+```
+// New matcher definition that works with the latest Google Mock.
+using ::testing::MakePolymorphicMatcher;
+using ::testing::MatchResultListener;
+...
+class MyGreatMatcher {
+ public:
+  ...
+  bool MatchAndExplain(MyType value,
+                       MatchResultListener* listener) const {
+    // Returns true if value matches.
+    return value.GetBar() < 42;
+  }
+  ...
+};
+... MakePolymorphicMatcher(MyGreatMatcher()) ...
+```
+
+If your polymorphic matcher uses `ExplainMatchResultTo()` for better
+failure messages:
+```
+// Old matcher definition that doesn't work with the latest
+// Google Mock.
+using ::testing::MakePolymorphicMatcher;
+...
+class MyGreatMatcher {
+ public:
+  ...
+  bool Matches(MyType value) const {
+    // Returns true if value matches.
+    return value.GetBar() < 42;
+  }
+  ...
+};
+void ExplainMatchResultTo(const MyGreatMatcher& matcher,
+                          MyType value,
+                          ::std::ostream* os) {
+  // Prints some helpful information to os to help
+  // a user understand why value matches (or doesn't match).
+  *os << "the Bar property is " << value.GetBar();
+}
+... MakePolymorphicMatcher(MyGreatMatcher()) ...
+```
+
+you'll need to move the logic inside `ExplainMatchResultTo()` to
+`MatchAndExplain()`:
+```
+// New matcher definition that works with the latest Google Mock.
+using ::testing::MakePolymorphicMatcher;
+using ::testing::MatchResultListener;
+...
+class MyGreatMatcher {
+ public:
+  ...
+  bool MatchAndExplain(MyType value,
+                       MatchResultListener* listener) const {
+    // Returns true if value matches.
+    *listener << "the Bar property is " << value.GetBar();
+    return value.GetBar() < 42;
+  }
+  ...
+};
+... MakePolymorphicMatcher(MyGreatMatcher()) ...
+```
+
+For more information, you can read these
+[two](http://code.google.com/p/googlemock/wiki/V1_7_CookBook#Writing_New_Monomorphic_Matchers)
+[recipes](http://code.google.com/p/googlemock/wiki/V1_7_CookBook#Writing_New_Polymorphic_Matchers)
+from the cookbook.  As always, you
+are welcome to post questions on `googlemock@googlegroups.com` if you
+need any help.
+
+## When using Google Mock, do I have to use Google Test as the testing framework?  I have my favorite testing framework and don't want to switch. ##
+
+Google Mock works out of the box with Google Test.  However, it's easy
+to configure it to work with any testing framework of your choice.
+[Here](http://code.google.com/p/googlemock/wiki/V1_7_ForDummies#Using_Google_Mock_with_Any_Testing_Framework) is how.
+
+## How am I supposed to make sense of these horrible template errors? ##
+
+If you are confused by the compiler errors gcc threw at you,
+try consulting the _Google Mock Doctor_ tool first.  What it does is to
+scan stdin for gcc error messages, and spit out diagnoses on the
+problems (we call them diseases) your code has.
+
+To "install", run command:
+```
+alias gmd='<path to googlemock>/scripts/gmock_doctor.py'
+```
+
+To use it, do:
+```
+<your-favorite-build-command> <your-test> 2>&1 | gmd
+```
+
+For example:
+```
+make my_test 2>&1 | gmd
+```
+
+Or you can run `gmd` and copy-n-paste gcc's error messages to it.
+
+## Can I mock a variadic function? ##
+
+You cannot mock a variadic function (i.e. a function taking ellipsis
+(`...`) arguments) directly in Google Mock.
+
+The problem is that in general, there is _no way_ for a mock object to
+know how many arguments are passed to the variadic method, and what
+the arguments' types are.  Only the _author of the base class_ knows
+the protocol, and we cannot look into his head.
+
+Therefore, to mock such a function, the _user_ must teach the mock
+object how to figure out the number of arguments and their types.  One
+way to do it is to provide overloaded versions of the function.
+
+Ellipsis arguments are inherited from C and not really a C++ feature.
+They are unsafe to use and don't work with arguments that have
+constructors or destructors.  Therefore we recommend to avoid them in
+C++ as much as possible.
+
+## MSVC gives me warning C4301 or C4373 when I define a mock method with a const parameter.  Why? ##
+
+If you compile this using Microsoft Visual C++ 2005 SP1:
+```
+class Foo {
+  ...
+  virtual void Bar(const int i) = 0;
+};
+
+class MockFoo : public Foo {
+  ...
+  MOCK_METHOD1(Bar, void(const int i));
+};
+```
+You may get the following warning:
+```
+warning C4301: 'MockFoo::Bar': overriding virtual function only differs from 'Foo::Bar' by const/volatile qualifier
+```
+
+This is a MSVC bug.  The same code compiles fine with gcc ,for
+example.  If you use Visual C++ 2008 SP1, you would get the warning:
+```
+warning C4373: 'MockFoo::Bar': virtual function overrides 'Foo::Bar', previous versions of the compiler did not override when parameters only differed by const/volatile qualifiers
+```
+
+In C++, if you _declare_ a function with a `const` parameter, the
+`const` modifier is _ignored_.  Therefore, the `Foo` base class above
+is equivalent to:
+```
+class Foo {
+  ...
+  virtual void Bar(int i) = 0;  // int or const int?  Makes no difference.
+};
+```
+
+In fact, you can _declare_ Bar() with an `int` parameter, and _define_
+it with a `const int` parameter.  The compiler will still match them
+up.
+
+Since making a parameter `const` is meaningless in the method
+_declaration_, we recommend to remove it in both `Foo` and `MockFoo`.
+That should workaround the VC bug.
+
+Note that we are talking about the _top-level_ `const` modifier here.
+If the function parameter is passed by pointer or reference, declaring
+the _pointee_ or _referee_ as `const` is still meaningful.  For
+example, the following two declarations are _not_ equivalent:
+```
+void Bar(int* p);        // Neither p nor *p is const.
+void Bar(const int* p);  // p is not const, but *p is.
+```
+
+## I have a huge mock class, and Microsoft Visual C++ runs out of memory when compiling it.  What can I do? ##
+
+We've noticed that when the `/clr` compiler flag is used, Visual C++
+uses 5~6 times as much memory when compiling a mock class.  We suggest
+to avoid `/clr` when compiling native C++ mocks.
+
+## I can't figure out why Google Mock thinks my expectations are not satisfied.  What should I do? ##
+
+You might want to run your test with
+`--gmock_verbose=info`.  This flag lets Google Mock print a trace
+of every mock function call it receives.  By studying the trace,
+you'll gain insights on why the expectations you set are not met.
+
+## How can I assert that a function is NEVER called? ##
+
+```
+EXPECT_CALL(foo, Bar(_))
+    .Times(0);
+```
+
+## I have a failed test where Google Mock tells me TWICE that a particular expectation is not satisfied.  Isn't this redundant? ##
+
+When Google Mock detects a failure, it prints relevant information
+(the mock function arguments, the state of relevant expectations, and
+etc) to help the user debug.  If another failure is detected, Google
+Mock will do the same, including printing the state of relevant
+expectations.
+
+Sometimes an expectation's state didn't change between two failures,
+and you'll see the same description of the state twice.  They are
+however _not_ redundant, as they refer to _different points in time_.
+The fact they are the same _is_ interesting information.
+
+## I get a heap check failure when using a mock object, but using a real object is fine.  What can be wrong? ##
+
+Does the class (hopefully a pure interface) you are mocking have a
+virtual destructor?
+
+Whenever you derive from a base class, make sure its destructor is
+virtual.  Otherwise Bad Things will happen.  Consider the following
+code:
+
+```
+class Base {
+ public:
+  // Not virtual, but should be.
+  ~Base() { ... }
+  ...
+};
+
+class Derived : public Base {
+ public:
+  ...
+ private:
+  std::string value_;
+};
+
+...
+  Base* p = new Derived;
+  ...
+  delete p;  // Surprise! ~Base() will be called, but ~Derived() will not
+             // - value_ is leaked.
+```
+
+By changing `~Base()` to virtual, `~Derived()` will be correctly
+called when `delete p` is executed, and the heap checker
+will be happy.
+
+## The "newer expectations override older ones" rule makes writing expectations awkward.  Why does Google Mock do that? ##
+
+When people complain about this, often they are referring to code like:
+
+```
+// foo.Bar() should be called twice, return 1 the first time, and return
+// 2 the second time.  However, I have to write the expectations in the
+// reverse order.  This sucks big time!!!
+EXPECT_CALL(foo, Bar())
+    .WillOnce(Return(2))
+    .RetiresOnSaturation();
+EXPECT_CALL(foo, Bar())
+    .WillOnce(Return(1))
+    .RetiresOnSaturation();
+```
+
+The problem is that they didn't pick the **best** way to express the test's
+intent.
+
+By default, expectations don't have to be matched in _any_ particular
+order.  If you want them to match in a certain order, you need to be
+explicit.  This is Google Mock's (and jMock's) fundamental philosophy: it's
+easy to accidentally over-specify your tests, and we want to make it
+harder to do so.
+
+There are two better ways to write the test spec.  You could either
+put the expectations in sequence:
+
+```
+// foo.Bar() should be called twice, return 1 the first time, and return
+// 2 the second time.  Using a sequence, we can write the expectations
+// in their natural order.
+{
+  InSequence s;
+  EXPECT_CALL(foo, Bar())
+      .WillOnce(Return(1))
+      .RetiresOnSaturation();
+  EXPECT_CALL(foo, Bar())
+      .WillOnce(Return(2))
+      .RetiresOnSaturation();
+}
+```
+
+or you can put the sequence of actions in the same expectation:
+
+```
+// foo.Bar() should be called twice, return 1 the first time, and return
+// 2 the second time.
+EXPECT_CALL(foo, Bar())
+    .WillOnce(Return(1))
+    .WillOnce(Return(2))
+    .RetiresOnSaturation();
+```
+
+Back to the original questions: why does Google Mock search the
+expectations (and `ON_CALL`s) from back to front?  Because this
+allows a user to set up a mock's behavior for the common case early
+(e.g. in the mock's constructor or the test fixture's set-up phase)
+and customize it with more specific rules later.  If Google Mock
+searches from front to back, this very useful pattern won't be
+possible.
+
+## Google Mock prints a warning when a function without EXPECT\_CALL is called, even if I have set its behavior using ON\_CALL.  Would it be reasonable not to show the warning in this case? ##
+
+When choosing between being neat and being safe, we lean toward the
+latter.  So the answer is that we think it's better to show the
+warning.
+
+Often people write `ON_CALL`s in the mock object's
+constructor or `SetUp()`, as the default behavior rarely changes from
+test to test.  Then in the test body they set the expectations, which
+are often different for each test.  Having an `ON_CALL` in the set-up
+part of a test doesn't mean that the calls are expected.  If there's
+no `EXPECT_CALL` and the method is called, it's possibly an error.  If
+we quietly let the call go through without notifying the user, bugs
+may creep in unnoticed.
+
+If, however, you are sure that the calls are OK, you can write
+
+```
+EXPECT_CALL(foo, Bar(_))
+    .WillRepeatedly(...);
+```
+
+instead of
+
+```
+ON_CALL(foo, Bar(_))
+    .WillByDefault(...);
+```
+
+This tells Google Mock that you do expect the calls and no warning should be
+printed.
+
+Also, you can control the verbosity using the `--gmock_verbose` flag.
+If you find the output too noisy when debugging, just choose a less
+verbose level.
+
+## How can I delete the mock function's argument in an action? ##
+
+If you find yourself needing to perform some action that's not
+supported by Google Mock directly, remember that you can define your own
+actions using
+[MakeAction()](http://code.google.com/p/googlemock/wiki/V1_7_CookBook#Writing_New_Actions) or
+[MakePolymorphicAction()](http://code.google.com/p/googlemock/wiki/V1_7_CookBook#Writing_New_Polymorphic_Actions),
+or you can write a stub function and invoke it using
+[Invoke()](http://code.google.com/p/googlemock/wiki/V1_7_CookBook#Using_Functions_Methods_Functors).
+
+## MOCK\_METHODn()'s second argument looks funny.  Why don't you use the MOCK\_METHODn(Method, return\_type, arg\_1, ..., arg\_n) syntax? ##
+
+What?!  I think it's beautiful. :-)
+
+While which syntax looks more natural is a subjective matter to some
+extent, Google Mock's syntax was chosen for several practical advantages it
+has.
+
+Try to mock a function that takes a map as an argument:
+```
+virtual int GetSize(const map<int, std::string>& m);
+```
+
+Using the proposed syntax, it would be:
+```
+MOCK_METHOD1(GetSize, int, const map<int, std::string>& m);
+```
+
+Guess what?  You'll get a compiler error as the compiler thinks that
+`const map<int, std::string>& m` are **two**, not one, arguments. To work
+around this you can use `typedef` to give the map type a name, but
+that gets in the way of your work.  Google Mock's syntax avoids this
+problem as the function's argument types are protected inside a pair
+of parentheses:
+```
+// This compiles fine.
+MOCK_METHOD1(GetSize, int(const map<int, std::string>& m));
+```
+
+You still need a `typedef` if the return type contains an unprotected
+comma, but that's much rarer.
+
+Other advantages include:
+  1. `MOCK_METHOD1(Foo, int, bool)` can leave a reader wonder whether the method returns `int` or `bool`, while there won't be such confusion using Google Mock's syntax.
+  1. The way Google Mock describes a function type is nothing new, although many people may not be familiar with it.  The same syntax was used in C, and the `function` library in `tr1` uses this syntax extensively.  Since `tr1` will become a part of the new version of STL, we feel very comfortable to be consistent with it.
+  1. The function type syntax is also used in other parts of Google Mock's API (e.g. the action interface) in order to make the implementation tractable. A user needs to learn it anyway in order to utilize Google Mock's more advanced features.  We'd as well stick to the same syntax in `MOCK_METHOD*`!
+
+## My code calls a static/global function.  Can I mock it? ##
+
+You can, but you need to make some changes.
+
+In general, if you find yourself needing to mock a static function,
+it's a sign that your modules are too tightly coupled (and less
+flexible, less reusable, less testable, etc).  You are probably better
+off defining a small interface and call the function through that
+interface, which then can be easily mocked.  It's a bit of work
+initially, but usually pays for itself quickly.
+
+This Google Testing Blog
+[post](http://googletesting.blogspot.com/2008/06/defeat-static-cling.html)
+says it excellently.  Check it out.
+
+## My mock object needs to do complex stuff.  It's a lot of pain to specify the actions.  Google Mock sucks! ##
+
+I know it's not a question, but you get an answer for free any way. :-)
+
+With Google Mock, you can create mocks in C++ easily.  And people might be
+tempted to use them everywhere. Sometimes they work great, and
+sometimes you may find them, well, a pain to use. So, what's wrong in
+the latter case?
+
+When you write a test without using mocks, you exercise the code and
+assert that it returns the correct value or that the system is in an
+expected state.  This is sometimes called "state-based testing".
+
+Mocks are great for what some call "interaction-based" testing:
+instead of checking the system state at the very end, mock objects
+verify that they are invoked the right way and report an error as soon
+as it arises, giving you a handle on the precise context in which the
+error was triggered.  This is often more effective and economical to
+do than state-based testing.
+
+If you are doing state-based testing and using a test double just to
+simulate the real object, you are probably better off using a fake.
+Using a mock in this case causes pain, as it's not a strong point for
+mocks to perform complex actions.  If you experience this and think
+that mocks suck, you are just not using the right tool for your
+problem. Or, you might be trying to solve the wrong problem. :-)
+
+## I got a warning "Uninteresting function call encountered - default action taken.."  Should I panic? ##
+
+By all means, NO!  It's just an FYI.
+
+What it means is that you have a mock function, you haven't set any
+expectations on it (by Google Mock's rule this means that you are not
+interested in calls to this function and therefore it can be called
+any number of times), and it is called.  That's OK - you didn't say
+it's not OK to call the function!
+
+What if you actually meant to disallow this function to be called, but
+forgot to write `EXPECT_CALL(foo, Bar()).Times(0)`?  While
+one can argue that it's the user's fault, Google Mock tries to be nice and
+prints you a note.
+
+So, when you see the message and believe that there shouldn't be any
+uninteresting calls, you should investigate what's going on.  To make
+your life easier, Google Mock prints the function name and arguments
+when an uninteresting call is encountered.
+
+## I want to define a custom action.  Should I use Invoke() or implement the action interface? ##
+
+Either way is fine - you want to choose the one that's more convenient
+for your circumstance.
+
+Usually, if your action is for a particular function type, defining it
+using `Invoke()` should be easier; if your action can be used in
+functions of different types (e.g. if you are defining
+`Return(value)`), `MakePolymorphicAction()` is
+easiest.  Sometimes you want precise control on what types of
+functions the action can be used in, and implementing
+`ActionInterface` is the way to go here. See the implementation of
+`Return()` in `include/gmock/gmock-actions.h` for an example.
+
+## I'm using the set-argument-pointee action, and the compiler complains about "conflicting return type specified".  What does it mean? ##
+
+You got this error as Google Mock has no idea what value it should return
+when the mock method is called.  `SetArgPointee()` says what the
+side effect is, but doesn't say what the return value should be.  You
+need `DoAll()` to chain a `SetArgPointee()` with a `Return()`.
+
+See this [recipe](http://code.google.com/p/googlemock/wiki/V1_7_CookBook#Mocking_Side_Effects) for more details and an example.
+
+
+## My question is not in your FAQ! ##
+
+If you cannot find the answer to your question in this FAQ, there are
+some other resources you can use:
+
+  1. read other [wiki pages](http://code.google.com/p/googlemock/w/list),
+  1. search the mailing list [archive](http://groups.google.com/group/googlemock/topics),
+  1. ask it on [googlemock@googlegroups.com](mailto:googlemock@googlegroups.com) and someone will answer it (to prevent spam, we require you to join the [discussion group](http://groups.google.com/group/googlemock) before you can post.).
+
+Please note that creating an issue in the
+[issue tracker](http://code.google.com/p/googlemock/issues/list) is _not_
+a good way to get your answer, as it is monitored infrequently by a
+very small number of people.
+
+When asking a question, it's helpful to provide as much of the
+following information as possible (people cannot help you if there's
+not enough information in your question):
+
+  * the version (or the revision number if you check out from SVN directly) of Google Mock you use (Google Mock is under active development, so it's possible that your problem has been solved in a later version),
+  * your operating system,
+  * the name and version of your compiler,
+  * the complete command line flags you give to your compiler,
+  * the complete compiler error messages (if the question is about compilation),
+  * the _actual_ code (ideally, a minimal but complete program) that has the problem you encounter.
\ No newline at end of file
diff --git a/third_party/googletest/googlemock/include/gmock/gmock-actions.h b/third_party/googletest/googlemock/include/gmock/gmock-actions.h
new file mode 100644
index 0000000..c09c4d6
--- /dev/null
+++ b/third_party/googletest/googlemock/include/gmock/gmock-actions.h
@@ -0,0 +1,1205 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements some commonly used actions.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_
+
+#ifndef _WIN32_WCE
+# include <errno.h>
+#endif
+
+#include <algorithm>
+#include <string>
+
+#include "gmock/internal/gmock-internal-utils.h"
+#include "gmock/internal/gmock-port.h"
+
+#if GTEST_LANG_CXX11  // Defined by gtest-port.h via gmock-port.h.
+#include <type_traits>
+#endif
+
+namespace testing {
+
+// To implement an action Foo, define:
+//   1. a class FooAction that implements the ActionInterface interface, and
+//   2. a factory function that creates an Action object from a
+//      const FooAction*.
+//
+// The two-level delegation design follows that of Matcher, providing
+// consistency for extension developers.  It also eases ownership
+// management as Action objects can now be copied like plain values.
+
+namespace internal {
+
+template <typename F1, typename F2>
+class ActionAdaptor;
+
+// BuiltInDefaultValueGetter<T, true>::Get() returns a
+// default-constructed T value.  BuiltInDefaultValueGetter<T,
+// false>::Get() crashes with an error.
+//
+// This primary template is used when kDefaultConstructible is true.
+template <typename T, bool kDefaultConstructible>
+struct BuiltInDefaultValueGetter {
+  static T Get() { return T(); }
+};
+template <typename T>
+struct BuiltInDefaultValueGetter<T, false> {
+  static T Get() {
+    Assert(false, __FILE__, __LINE__,
+           "Default action undefined for the function return type.");
+    return internal::Invalid<T>();
+    // The above statement will never be reached, but is required in
+    // order for this function to compile.
+  }
+};
+
+// BuiltInDefaultValue<T>::Get() returns the "built-in" default value
+// for type T, which is NULL when T is a raw pointer type, 0 when T is
+// a numeric type, false when T is bool, or "" when T is string or
+// std::string.  In addition, in C++11 and above, it turns a
+// default-constructed T value if T is default constructible.  For any
+// other type T, the built-in default T value is undefined, and the
+// function will abort the process.
+template <typename T>
+class BuiltInDefaultValue {
+ public:
+#if GTEST_LANG_CXX11
+  // This function returns true iff type T has a built-in default value.
+  static bool Exists() {
+    return ::std::is_default_constructible<T>::value;
+  }
+
+  static T Get() {
+    return BuiltInDefaultValueGetter<
+        T, ::std::is_default_constructible<T>::value>::Get();
+  }
+
+#else  // GTEST_LANG_CXX11
+  // This function returns true iff type T has a built-in default value.
+  static bool Exists() {
+    return false;
+  }
+
+  static T Get() {
+    return BuiltInDefaultValueGetter<T, false>::Get();
+  }
+
+#endif  // GTEST_LANG_CXX11
+};
+
+// This partial specialization says that we use the same built-in
+// default value for T and const T.
+template <typename T>
+class BuiltInDefaultValue<const T> {
+ public:
+  static bool Exists() { return BuiltInDefaultValue<T>::Exists(); }
+  static T Get() { return BuiltInDefaultValue<T>::Get(); }
+};
+
+// This partial specialization defines the default values for pointer
+// types.
+template <typename T>
+class BuiltInDefaultValue<T*> {
+ public:
+  static bool Exists() { return true; }
+  static T* Get() { return NULL; }
+};
+
+// The following specializations define the default values for
+// specific types we care about.
+#define GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(type, value) \
+  template <> \
+  class BuiltInDefaultValue<type> { \
+   public: \
+    static bool Exists() { return true; } \
+    static type Get() { return value; } \
+  }
+
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(void, );  // NOLINT
+#if GTEST_HAS_GLOBAL_STRING
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(::string, "");
+#endif  // GTEST_HAS_GLOBAL_STRING
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(::std::string, "");
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(bool, false);
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned char, '\0');
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed char, '\0');
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(char, '\0');
+
+// There's no need for a default action for signed wchar_t, as that
+// type is the same as wchar_t for gcc, and invalid for MSVC.
+//
+// There's also no need for a default action for unsigned wchar_t, as
+// that type is the same as unsigned int for gcc, and invalid for
+// MSVC.
+#if GMOCK_WCHAR_T_IS_NATIVE_
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(wchar_t, 0U);  // NOLINT
+#endif
+
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned short, 0U);  // NOLINT
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed short, 0);     // NOLINT
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned int, 0U);
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed int, 0);
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned long, 0UL);  // NOLINT
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed long, 0L);     // NOLINT
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(UInt64, 0);
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(Int64, 0);
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(float, 0);
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(double, 0);
+
+#undef GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_
+
+}  // namespace internal
+
+// When an unexpected function call is encountered, Google Mock will
+// let it return a default value if the user has specified one for its
+// return type, or if the return type has a built-in default value;
+// otherwise Google Mock won't know what value to return and will have
+// to abort the process.
+//
+// The DefaultValue<T> class allows a user to specify the
+// default value for a type T that is both copyable and publicly
+// destructible (i.e. anything that can be used as a function return
+// type).  The usage is:
+//
+//   // Sets the default value for type T to be foo.
+//   DefaultValue<T>::Set(foo);
+template <typename T>
+class DefaultValue {
+ public:
+  // Sets the default value for type T; requires T to be
+  // copy-constructable and have a public destructor.
+  static void Set(T x) {
+    delete producer_;
+    producer_ = new FixedValueProducer(x);
+  }
+
+  // Provides a factory function to be called to generate the default value.
+  // This method can be used even if T is only move-constructible, but it is not
+  // limited to that case.
+  typedef T (*FactoryFunction)();
+  static void SetFactory(FactoryFunction factory) {
+    delete producer_;
+    producer_ = new FactoryValueProducer(factory);
+  }
+
+  // Unsets the default value for type T.
+  static void Clear() {
+    delete producer_;
+    producer_ = NULL;
+  }
+
+  // Returns true iff the user has set the default value for type T.
+  static bool IsSet() { return producer_ != NULL; }
+
+  // Returns true if T has a default return value set by the user or there
+  // exists a built-in default value.
+  static bool Exists() {
+    return IsSet() || internal::BuiltInDefaultValue<T>::Exists();
+  }
+
+  // Returns the default value for type T if the user has set one;
+  // otherwise returns the built-in default value. Requires that Exists()
+  // is true, which ensures that the return value is well-defined.
+  static T Get() {
+    return producer_ == NULL ?
+        internal::BuiltInDefaultValue<T>::Get() : producer_->Produce();
+  }
+
+ private:
+  class ValueProducer {
+   public:
+    virtual ~ValueProducer() {}
+    virtual T Produce() = 0;
+  };
+
+  class FixedValueProducer : public ValueProducer {
+   public:
+    explicit FixedValueProducer(T value) : value_(value) {}
+    virtual T Produce() { return value_; }
+
+   private:
+    const T value_;
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(FixedValueProducer);
+  };
+
+  class FactoryValueProducer : public ValueProducer {
+   public:
+    explicit FactoryValueProducer(FactoryFunction factory)
+        : factory_(factory) {}
+    virtual T Produce() { return factory_(); }
+
+   private:
+    const FactoryFunction factory_;
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(FactoryValueProducer);
+  };
+
+  static ValueProducer* producer_;
+};
+
+// This partial specialization allows a user to set default values for
+// reference types.
+template <typename T>
+class DefaultValue<T&> {
+ public:
+  // Sets the default value for type T&.
+  static void Set(T& x) {  // NOLINT
+    address_ = &x;
+  }
+
+  // Unsets the default value for type T&.
+  static void Clear() {
+    address_ = NULL;
+  }
+
+  // Returns true iff the user has set the default value for type T&.
+  static bool IsSet() { return address_ != NULL; }
+
+  // Returns true if T has a default return value set by the user or there
+  // exists a built-in default value.
+  static bool Exists() {
+    return IsSet() || internal::BuiltInDefaultValue<T&>::Exists();
+  }
+
+  // Returns the default value for type T& if the user has set one;
+  // otherwise returns the built-in default value if there is one;
+  // otherwise aborts the process.
+  static T& Get() {
+    return address_ == NULL ?
+        internal::BuiltInDefaultValue<T&>::Get() : *address_;
+  }
+
+ private:
+  static T* address_;
+};
+
+// This specialization allows DefaultValue<void>::Get() to
+// compile.
+template <>
+class DefaultValue<void> {
+ public:
+  static bool Exists() { return true; }
+  static void Get() {}
+};
+
+// Points to the user-set default value for type T.
+template <typename T>
+typename DefaultValue<T>::ValueProducer* DefaultValue<T>::producer_ = NULL;
+
+// Points to the user-set default value for type T&.
+template <typename T>
+T* DefaultValue<T&>::address_ = NULL;
+
+// Implement this interface to define an action for function type F.
+template <typename F>
+class ActionInterface {
+ public:
+  typedef typename internal::Function<F>::Result Result;
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  ActionInterface() {}
+  virtual ~ActionInterface() {}
+
+  // Performs the action.  This method is not const, as in general an
+  // action can have side effects and be stateful.  For example, a
+  // get-the-next-element-from-the-collection action will need to
+  // remember the current element.
+  virtual Result Perform(const ArgumentTuple& args) = 0;
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ActionInterface);
+};
+
+// An Action<F> is a copyable and IMMUTABLE (except by assignment)
+// object that represents an action to be taken when a mock function
+// of type F is called.  The implementation of Action<T> is just a
+// linked_ptr to const ActionInterface<T>, so copying is fairly cheap.
+// Don't inherit from Action!
+//
+// You can view an object implementing ActionInterface<F> as a
+// concrete action (including its current state), and an Action<F>
+// object as a handle to it.
+template <typename F>
+class Action {
+ public:
+  typedef typename internal::Function<F>::Result Result;
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  // Constructs a null Action.  Needed for storing Action objects in
+  // STL containers.
+  Action() : impl_(NULL) {}
+
+  // Constructs an Action from its implementation.  A NULL impl is
+  // used to represent the "do-default" action.
+  explicit Action(ActionInterface<F>* impl) : impl_(impl) {}
+
+  // Copy constructor.
+  Action(const Action& action) : impl_(action.impl_) {}
+
+  // This constructor allows us to turn an Action<Func> object into an
+  // Action<F>, as long as F's arguments can be implicitly converted
+  // to Func's and Func's return type can be implicitly converted to
+  // F's.
+  template <typename Func>
+  explicit Action(const Action<Func>& action);
+
+  // Returns true iff this is the DoDefault() action.
+  bool IsDoDefault() const { return impl_.get() == NULL; }
+
+  // Performs the action.  Note that this method is const even though
+  // the corresponding method in ActionInterface is not.  The reason
+  // is that a const Action<F> means that it cannot be re-bound to
+  // another concrete action, not that the concrete action it binds to
+  // cannot change state.  (Think of the difference between a const
+  // pointer and a pointer to const.)
+  Result Perform(const ArgumentTuple& args) const {
+    internal::Assert(
+        !IsDoDefault(), __FILE__, __LINE__,
+        "You are using DoDefault() inside a composite action like "
+        "DoAll() or WithArgs().  This is not supported for technical "
+        "reasons.  Please instead spell out the default action, or "
+        "assign the default action to an Action variable and use "
+        "the variable in various places.");
+    return impl_->Perform(args);
+  }
+
+ private:
+  template <typename F1, typename F2>
+  friend class internal::ActionAdaptor;
+
+  internal::linked_ptr<ActionInterface<F> > impl_;
+};
+
+// The PolymorphicAction class template makes it easy to implement a
+// polymorphic action (i.e. an action that can be used in mock
+// functions of than one type, e.g. Return()).
+//
+// To define a polymorphic action, a user first provides a COPYABLE
+// implementation class that has a Perform() method template:
+//
+//   class FooAction {
+//    public:
+//     template <typename Result, typename ArgumentTuple>
+//     Result Perform(const ArgumentTuple& args) const {
+//       // Processes the arguments and returns a result, using
+//       // tr1::get<N>(args) to get the N-th (0-based) argument in the tuple.
+//     }
+//     ...
+//   };
+//
+// Then the user creates the polymorphic action using
+// MakePolymorphicAction(object) where object has type FooAction.  See
+// the definition of Return(void) and SetArgumentPointee<N>(value) for
+// complete examples.
+template <typename Impl>
+class PolymorphicAction {
+ public:
+  explicit PolymorphicAction(const Impl& impl) : impl_(impl) {}
+
+  template <typename F>
+  operator Action<F>() const {
+    return Action<F>(new MonomorphicImpl<F>(impl_));
+  }
+
+ private:
+  template <typename F>
+  class MonomorphicImpl : public ActionInterface<F> {
+   public:
+    typedef typename internal::Function<F>::Result Result;
+    typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+    explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {}
+
+    virtual Result Perform(const ArgumentTuple& args) {
+      return impl_.template Perform<Result>(args);
+    }
+
+   private:
+    Impl impl_;
+
+    GTEST_DISALLOW_ASSIGN_(MonomorphicImpl);
+  };
+
+  Impl impl_;
+
+  GTEST_DISALLOW_ASSIGN_(PolymorphicAction);
+};
+
+// Creates an Action from its implementation and returns it.  The
+// created Action object owns the implementation.
+template <typename F>
+Action<F> MakeAction(ActionInterface<F>* impl) {
+  return Action<F>(impl);
+}
+
+// Creates a polymorphic action from its implementation.  This is
+// easier to use than the PolymorphicAction<Impl> constructor as it
+// doesn't require you to explicitly write the template argument, e.g.
+//
+//   MakePolymorphicAction(foo);
+// vs
+//   PolymorphicAction<TypeOfFoo>(foo);
+template <typename Impl>
+inline PolymorphicAction<Impl> MakePolymorphicAction(const Impl& impl) {
+  return PolymorphicAction<Impl>(impl);
+}
+
+namespace internal {
+
+// Allows an Action<F2> object to pose as an Action<F1>, as long as F2
+// and F1 are compatible.
+template <typename F1, typename F2>
+class ActionAdaptor : public ActionInterface<F1> {
+ public:
+  typedef typename internal::Function<F1>::Result Result;
+  typedef typename internal::Function<F1>::ArgumentTuple ArgumentTuple;
+
+  explicit ActionAdaptor(const Action<F2>& from) : impl_(from.impl_) {}
+
+  virtual Result Perform(const ArgumentTuple& args) {
+    return impl_->Perform(args);
+  }
+
+ private:
+  const internal::linked_ptr<ActionInterface<F2> > impl_;
+
+  GTEST_DISALLOW_ASSIGN_(ActionAdaptor);
+};
+
+// Helper struct to specialize ReturnAction to execute a move instead of a copy
+// on return. Useful for move-only types, but could be used on any type.
+template <typename T>
+struct ByMoveWrapper {
+  explicit ByMoveWrapper(T value) : payload(internal::move(value)) {}
+  T payload;
+};
+
+// Implements the polymorphic Return(x) action, which can be used in
+// any function that returns the type of x, regardless of the argument
+// types.
+//
+// Note: The value passed into Return must be converted into
+// Function<F>::Result when this action is cast to Action<F> rather than
+// when that action is performed. This is important in scenarios like
+//
+// MOCK_METHOD1(Method, T(U));
+// ...
+// {
+//   Foo foo;
+//   X x(&foo);
+//   EXPECT_CALL(mock, Method(_)).WillOnce(Return(x));
+// }
+//
+// In the example above the variable x holds reference to foo which leaves
+// scope and gets destroyed.  If copying X just copies a reference to foo,
+// that copy will be left with a hanging reference.  If conversion to T
+// makes a copy of foo, the above code is safe. To support that scenario, we
+// need to make sure that the type conversion happens inside the EXPECT_CALL
+// statement, and conversion of the result of Return to Action<T(U)> is a
+// good place for that.
+//
+template <typename R>
+class ReturnAction {
+ public:
+  // Constructs a ReturnAction object from the value to be returned.
+  // 'value' is passed by value instead of by const reference in order
+  // to allow Return("string literal") to compile.
+  explicit ReturnAction(R value) : value_(new R(internal::move(value))) {}
+
+  // This template type conversion operator allows Return(x) to be
+  // used in ANY function that returns x's type.
+  template <typename F>
+  operator Action<F>() const {
+    // Assert statement belongs here because this is the best place to verify
+    // conditions on F. It produces the clearest error messages
+    // in most compilers.
+    // Impl really belongs in this scope as a local class but can't
+    // because MSVC produces duplicate symbols in different translation units
+    // in this case. Until MS fixes that bug we put Impl into the class scope
+    // and put the typedef both here (for use in assert statement) and
+    // in the Impl class. But both definitions must be the same.
+    typedef typename Function<F>::Result Result;
+    GTEST_COMPILE_ASSERT_(
+        !is_reference<Result>::value,
+        use_ReturnRef_instead_of_Return_to_return_a_reference);
+    return Action<F>(new Impl<R, F>(value_));
+  }
+
+ private:
+  // Implements the Return(x) action for a particular function type F.
+  template <typename R_, typename F>
+  class Impl : public ActionInterface<F> {
+   public:
+    typedef typename Function<F>::Result Result;
+    typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+
+    // The implicit cast is necessary when Result has more than one
+    // single-argument constructor (e.g. Result is std::vector<int>) and R
+    // has a type conversion operator template.  In that case, value_(value)
+    // won't compile as the compiler doesn't known which constructor of
+    // Result to call.  ImplicitCast_ forces the compiler to convert R to
+    // Result without considering explicit constructors, thus resolving the
+    // ambiguity. value_ is then initialized using its copy constructor.
+    explicit Impl(const linked_ptr<R>& value)
+        : value_before_cast_(*value),
+          value_(ImplicitCast_<Result>(value_before_cast_)) {}
+
+    virtual Result Perform(const ArgumentTuple&) { return value_; }
+
+   private:
+    GTEST_COMPILE_ASSERT_(!is_reference<Result>::value,
+                          Result_cannot_be_a_reference_type);
+    // We save the value before casting just in case it is being cast to a
+    // wrapper type.
+    R value_before_cast_;
+    Result value_;
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(Impl);
+  };
+
+  // Partially specialize for ByMoveWrapper. This version of ReturnAction will
+  // move its contents instead.
+  template <typename R_, typename F>
+  class Impl<ByMoveWrapper<R_>, F> : public ActionInterface<F> {
+   public:
+    typedef typename Function<F>::Result Result;
+    typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+
+    explicit Impl(const linked_ptr<R>& wrapper)
+        : performed_(false), wrapper_(wrapper) {}
+
+    virtual Result Perform(const ArgumentTuple&) {
+      GTEST_CHECK_(!performed_)
+          << "A ByMove() action should only be performed once.";
+      performed_ = true;
+      return internal::move(wrapper_->payload);
+    }
+
+   private:
+    bool performed_;
+    const linked_ptr<R> wrapper_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+  const linked_ptr<R> value_;
+
+  GTEST_DISALLOW_ASSIGN_(ReturnAction);
+};
+
+// Implements the ReturnNull() action.
+class ReturnNullAction {
+ public:
+  // Allows ReturnNull() to be used in any pointer-returning function. In C++11
+  // this is enforced by returning nullptr, and in non-C++11 by asserting a
+  // pointer type on compile time.
+  template <typename Result, typename ArgumentTuple>
+  static Result Perform(const ArgumentTuple&) {
+#if GTEST_LANG_CXX11
+    return nullptr;
+#else
+    GTEST_COMPILE_ASSERT_(internal::is_pointer<Result>::value,
+                          ReturnNull_can_be_used_to_return_a_pointer_only);
+    return NULL;
+#endif  // GTEST_LANG_CXX11
+  }
+};
+
+// Implements the Return() action.
+class ReturnVoidAction {
+ public:
+  // Allows Return() to be used in any void-returning function.
+  template <typename Result, typename ArgumentTuple>
+  static void Perform(const ArgumentTuple&) {
+    CompileAssertTypesEqual<void, Result>();
+  }
+};
+
+// Implements the polymorphic ReturnRef(x) action, which can be used
+// in any function that returns a reference to the type of x,
+// regardless of the argument types.
+template <typename T>
+class ReturnRefAction {
+ public:
+  // Constructs a ReturnRefAction object from the reference to be returned.
+  explicit ReturnRefAction(T& ref) : ref_(ref) {}  // NOLINT
+
+  // This template type conversion operator allows ReturnRef(x) to be
+  // used in ANY function that returns a reference to x's type.
+  template <typename F>
+  operator Action<F>() const {
+    typedef typename Function<F>::Result Result;
+    // Asserts that the function return type is a reference.  This
+    // catches the user error of using ReturnRef(x) when Return(x)
+    // should be used, and generates some helpful error message.
+    GTEST_COMPILE_ASSERT_(internal::is_reference<Result>::value,
+                          use_Return_instead_of_ReturnRef_to_return_a_value);
+    return Action<F>(new Impl<F>(ref_));
+  }
+
+ private:
+  // Implements the ReturnRef(x) action for a particular function type F.
+  template <typename F>
+  class Impl : public ActionInterface<F> {
+   public:
+    typedef typename Function<F>::Result Result;
+    typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+
+    explicit Impl(T& ref) : ref_(ref) {}  // NOLINT
+
+    virtual Result Perform(const ArgumentTuple&) {
+      return ref_;
+    }
+
+   private:
+    T& ref_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+  T& ref_;
+
+  GTEST_DISALLOW_ASSIGN_(ReturnRefAction);
+};
+
+// Implements the polymorphic ReturnRefOfCopy(x) action, which can be
+// used in any function that returns a reference to the type of x,
+// regardless of the argument types.
+template <typename T>
+class ReturnRefOfCopyAction {
+ public:
+  // Constructs a ReturnRefOfCopyAction object from the reference to
+  // be returned.
+  explicit ReturnRefOfCopyAction(const T& value) : value_(value) {}  // NOLINT
+
+  // This template type conversion operator allows ReturnRefOfCopy(x) to be
+  // used in ANY function that returns a reference to x's type.
+  template <typename F>
+  operator Action<F>() const {
+    typedef typename Function<F>::Result Result;
+    // Asserts that the function return type is a reference.  This
+    // catches the user error of using ReturnRefOfCopy(x) when Return(x)
+    // should be used, and generates some helpful error message.
+    GTEST_COMPILE_ASSERT_(
+        internal::is_reference<Result>::value,
+        use_Return_instead_of_ReturnRefOfCopy_to_return_a_value);
+    return Action<F>(new Impl<F>(value_));
+  }
+
+ private:
+  // Implements the ReturnRefOfCopy(x) action for a particular function type F.
+  template <typename F>
+  class Impl : public ActionInterface<F> {
+   public:
+    typedef typename Function<F>::Result Result;
+    typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+
+    explicit Impl(const T& value) : value_(value) {}  // NOLINT
+
+    virtual Result Perform(const ArgumentTuple&) {
+      return value_;
+    }
+
+   private:
+    T value_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+  const T value_;
+
+  GTEST_DISALLOW_ASSIGN_(ReturnRefOfCopyAction);
+};
+
+// Implements the polymorphic DoDefault() action.
+class DoDefaultAction {
+ public:
+  // This template type conversion operator allows DoDefault() to be
+  // used in any function.
+  template <typename F>
+  operator Action<F>() const { return Action<F>(NULL); }
+};
+
+// Implements the Assign action to set a given pointer referent to a
+// particular value.
+template <typename T1, typename T2>
+class AssignAction {
+ public:
+  AssignAction(T1* ptr, T2 value) : ptr_(ptr), value_(value) {}
+
+  template <typename Result, typename ArgumentTuple>
+  void Perform(const ArgumentTuple& /* args */) const {
+    *ptr_ = value_;
+  }
+
+ private:
+  T1* const ptr_;
+  const T2 value_;
+
+  GTEST_DISALLOW_ASSIGN_(AssignAction);
+};
+
+#if !GTEST_OS_WINDOWS_MOBILE
+
+// Implements the SetErrnoAndReturn action to simulate return from
+// various system calls and libc functions.
+template <typename T>
+class SetErrnoAndReturnAction {
+ public:
+  SetErrnoAndReturnAction(int errno_value, T result)
+      : errno_(errno_value),
+        result_(result) {}
+  template <typename Result, typename ArgumentTuple>
+  Result Perform(const ArgumentTuple& /* args */) const {
+    errno = errno_;
+    return result_;
+  }
+
+ private:
+  const int errno_;
+  const T result_;
+
+  GTEST_DISALLOW_ASSIGN_(SetErrnoAndReturnAction);
+};
+
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+// Implements the SetArgumentPointee<N>(x) action for any function
+// whose N-th argument (0-based) is a pointer to x's type.  The
+// template parameter kIsProto is true iff type A is ProtocolMessage,
+// proto2::Message, or a sub-class of those.
+template <size_t N, typename A, bool kIsProto>
+class SetArgumentPointeeAction {
+ public:
+  // Constructs an action that sets the variable pointed to by the
+  // N-th function argument to 'value'.
+  explicit SetArgumentPointeeAction(const A& value) : value_(value) {}
+
+  template <typename Result, typename ArgumentTuple>
+  void Perform(const ArgumentTuple& args) const {
+    CompileAssertTypesEqual<void, Result>();
+    *::testing::get<N>(args) = value_;
+  }
+
+ private:
+  const A value_;
+
+  GTEST_DISALLOW_ASSIGN_(SetArgumentPointeeAction);
+};
+
+template <size_t N, typename Proto>
+class SetArgumentPointeeAction<N, Proto, true> {
+ public:
+  // Constructs an action that sets the variable pointed to by the
+  // N-th function argument to 'proto'.  Both ProtocolMessage and
+  // proto2::Message have the CopyFrom() method, so the same
+  // implementation works for both.
+  explicit SetArgumentPointeeAction(const Proto& proto) : proto_(new Proto) {
+    proto_->CopyFrom(proto);
+  }
+
+  template <typename Result, typename ArgumentTuple>
+  void Perform(const ArgumentTuple& args) const {
+    CompileAssertTypesEqual<void, Result>();
+    ::testing::get<N>(args)->CopyFrom(*proto_);
+  }
+
+ private:
+  const internal::linked_ptr<Proto> proto_;
+
+  GTEST_DISALLOW_ASSIGN_(SetArgumentPointeeAction);
+};
+
+// Implements the InvokeWithoutArgs(f) action.  The template argument
+// FunctionImpl is the implementation type of f, which can be either a
+// function pointer or a functor.  InvokeWithoutArgs(f) can be used as an
+// Action<F> as long as f's type is compatible with F (i.e. f can be
+// assigned to a tr1::function<F>).
+template <typename FunctionImpl>
+class InvokeWithoutArgsAction {
+ public:
+  // The c'tor makes a copy of function_impl (either a function
+  // pointer or a functor).
+  explicit InvokeWithoutArgsAction(FunctionImpl function_impl)
+      : function_impl_(function_impl) {}
+
+  // Allows InvokeWithoutArgs(f) to be used as any action whose type is
+  // compatible with f.
+  template <typename Result, typename ArgumentTuple>
+  Result Perform(const ArgumentTuple&) { return function_impl_(); }
+
+ private:
+  FunctionImpl function_impl_;
+
+  GTEST_DISALLOW_ASSIGN_(InvokeWithoutArgsAction);
+};
+
+// Implements the InvokeWithoutArgs(object_ptr, &Class::Method) action.
+template <class Class, typename MethodPtr>
+class InvokeMethodWithoutArgsAction {
+ public:
+  InvokeMethodWithoutArgsAction(Class* obj_ptr, MethodPtr method_ptr)
+      : obj_ptr_(obj_ptr), method_ptr_(method_ptr) {}
+
+  template <typename Result, typename ArgumentTuple>
+  Result Perform(const ArgumentTuple&) const {
+    return (obj_ptr_->*method_ptr_)();
+  }
+
+ private:
+  Class* const obj_ptr_;
+  const MethodPtr method_ptr_;
+
+  GTEST_DISALLOW_ASSIGN_(InvokeMethodWithoutArgsAction);
+};
+
+// Implements the IgnoreResult(action) action.
+template <typename A>
+class IgnoreResultAction {
+ public:
+  explicit IgnoreResultAction(const A& action) : action_(action) {}
+
+  template <typename F>
+  operator Action<F>() const {
+    // Assert statement belongs here because this is the best place to verify
+    // conditions on F. It produces the clearest error messages
+    // in most compilers.
+    // Impl really belongs in this scope as a local class but can't
+    // because MSVC produces duplicate symbols in different translation units
+    // in this case. Until MS fixes that bug we put Impl into the class scope
+    // and put the typedef both here (for use in assert statement) and
+    // in the Impl class. But both definitions must be the same.
+    typedef typename internal::Function<F>::Result Result;
+
+    // Asserts at compile time that F returns void.
+    CompileAssertTypesEqual<void, Result>();
+
+    return Action<F>(new Impl<F>(action_));
+  }
+
+ private:
+  template <typename F>
+  class Impl : public ActionInterface<F> {
+   public:
+    typedef typename internal::Function<F>::Result Result;
+    typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+    explicit Impl(const A& action) : action_(action) {}
+
+    virtual void Perform(const ArgumentTuple& args) {
+      // Performs the action and ignores its result.
+      action_.Perform(args);
+    }
+
+   private:
+    // Type OriginalFunction is the same as F except that its return
+    // type is IgnoredValue.
+    typedef typename internal::Function<F>::MakeResultIgnoredValue
+        OriginalFunction;
+
+    const Action<OriginalFunction> action_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+  const A action_;
+
+  GTEST_DISALLOW_ASSIGN_(IgnoreResultAction);
+};
+
+// A ReferenceWrapper<T> object represents a reference to type T,
+// which can be either const or not.  It can be explicitly converted
+// from, and implicitly converted to, a T&.  Unlike a reference,
+// ReferenceWrapper<T> can be copied and can survive template type
+// inference.  This is used to support by-reference arguments in the
+// InvokeArgument<N>(...) action.  The idea was from "reference
+// wrappers" in tr1, which we don't have in our source tree yet.
+template <typename T>
+class ReferenceWrapper {
+ public:
+  // Constructs a ReferenceWrapper<T> object from a T&.
+  explicit ReferenceWrapper(T& l_value) : pointer_(&l_value) {}  // NOLINT
+
+  // Allows a ReferenceWrapper<T> object to be implicitly converted to
+  // a T&.
+  operator T&() const { return *pointer_; }
+ private:
+  T* pointer_;
+};
+
+// Allows the expression ByRef(x) to be printed as a reference to x.
+template <typename T>
+void PrintTo(const ReferenceWrapper<T>& ref, ::std::ostream* os) {
+  T& value = ref;
+  UniversalPrinter<T&>::Print(value, os);
+}
+
+// Does two actions sequentially.  Used for implementing the DoAll(a1,
+// a2, ...) action.
+template <typename Action1, typename Action2>
+class DoBothAction {
+ public:
+  DoBothAction(Action1 action1, Action2 action2)
+      : action1_(action1), action2_(action2) {}
+
+  // This template type conversion operator allows DoAll(a1, ..., a_n)
+  // to be used in ANY function of compatible type.
+  template <typename F>
+  operator Action<F>() const {
+    return Action<F>(new Impl<F>(action1_, action2_));
+  }
+
+ private:
+  // Implements the DoAll(...) action for a particular function type F.
+  template <typename F>
+  class Impl : public ActionInterface<F> {
+   public:
+    typedef typename Function<F>::Result Result;
+    typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+    typedef typename Function<F>::MakeResultVoid VoidResult;
+
+    Impl(const Action<VoidResult>& action1, const Action<F>& action2)
+        : action1_(action1), action2_(action2) {}
+
+    virtual Result Perform(const ArgumentTuple& args) {
+      action1_.Perform(args);
+      return action2_.Perform(args);
+    }
+
+   private:
+    const Action<VoidResult> action1_;
+    const Action<F> action2_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+  Action1 action1_;
+  Action2 action2_;
+
+  GTEST_DISALLOW_ASSIGN_(DoBothAction);
+};
+
+}  // namespace internal
+
+// An Unused object can be implicitly constructed from ANY value.
+// This is handy when defining actions that ignore some or all of the
+// mock function arguments.  For example, given
+//
+//   MOCK_METHOD3(Foo, double(const string& label, double x, double y));
+//   MOCK_METHOD3(Bar, double(int index, double x, double y));
+//
+// instead of
+//
+//   double DistanceToOriginWithLabel(const string& label, double x, double y) {
+//     return sqrt(x*x + y*y);
+//   }
+//   double DistanceToOriginWithIndex(int index, double x, double y) {
+//     return sqrt(x*x + y*y);
+//   }
+//   ...
+//   EXEPCT_CALL(mock, Foo("abc", _, _))
+//       .WillOnce(Invoke(DistanceToOriginWithLabel));
+//   EXEPCT_CALL(mock, Bar(5, _, _))
+//       .WillOnce(Invoke(DistanceToOriginWithIndex));
+//
+// you could write
+//
+//   // We can declare any uninteresting argument as Unused.
+//   double DistanceToOrigin(Unused, double x, double y) {
+//     return sqrt(x*x + y*y);
+//   }
+//   ...
+//   EXEPCT_CALL(mock, Foo("abc", _, _)).WillOnce(Invoke(DistanceToOrigin));
+//   EXEPCT_CALL(mock, Bar(5, _, _)).WillOnce(Invoke(DistanceToOrigin));
+typedef internal::IgnoredValue Unused;
+
+// This constructor allows us to turn an Action<From> object into an
+// Action<To>, as long as To's arguments can be implicitly converted
+// to From's and From's return type cann be implicitly converted to
+// To's.
+template <typename To>
+template <typename From>
+Action<To>::Action(const Action<From>& from)
+    : impl_(new internal::ActionAdaptor<To, From>(from)) {}
+
+// Creates an action that returns 'value'.  'value' is passed by value
+// instead of const reference - otherwise Return("string literal")
+// will trigger a compiler error about using array as initializer.
+template <typename R>
+internal::ReturnAction<R> Return(R value) {
+  return internal::ReturnAction<R>(internal::move(value));
+}
+
+// Creates an action that returns NULL.
+inline PolymorphicAction<internal::ReturnNullAction> ReturnNull() {
+  return MakePolymorphicAction(internal::ReturnNullAction());
+}
+
+// Creates an action that returns from a void function.
+inline PolymorphicAction<internal::ReturnVoidAction> Return() {
+  return MakePolymorphicAction(internal::ReturnVoidAction());
+}
+
+// Creates an action that returns the reference to a variable.
+template <typename R>
+inline internal::ReturnRefAction<R> ReturnRef(R& x) {  // NOLINT
+  return internal::ReturnRefAction<R>(x);
+}
+
+// Creates an action that returns the reference to a copy of the
+// argument.  The copy is created when the action is constructed and
+// lives as long as the action.
+template <typename R>
+inline internal::ReturnRefOfCopyAction<R> ReturnRefOfCopy(const R& x) {
+  return internal::ReturnRefOfCopyAction<R>(x);
+}
+
+// Modifies the parent action (a Return() action) to perform a move of the
+// argument instead of a copy.
+// Return(ByMove()) actions can only be executed once and will assert this
+// invariant.
+template <typename R>
+internal::ByMoveWrapper<R> ByMove(R x) {
+  return internal::ByMoveWrapper<R>(internal::move(x));
+}
+
+// Creates an action that does the default action for the give mock function.
+inline internal::DoDefaultAction DoDefault() {
+  return internal::DoDefaultAction();
+}
+
+// Creates an action that sets the variable pointed by the N-th
+// (0-based) function argument to 'value'.
+template <size_t N, typename T>
+PolymorphicAction<
+  internal::SetArgumentPointeeAction<
+    N, T, internal::IsAProtocolMessage<T>::value> >
+SetArgPointee(const T& x) {
+  return MakePolymorphicAction(internal::SetArgumentPointeeAction<
+      N, T, internal::IsAProtocolMessage<T>::value>(x));
+}
+
+#if !((GTEST_GCC_VER_ && GTEST_GCC_VER_ < 40000) || GTEST_OS_SYMBIAN)
+// This overload allows SetArgPointee() to accept a string literal.
+// GCC prior to the version 4.0 and Symbian C++ compiler cannot distinguish
+// this overload from the templated version and emit a compile error.
+template <size_t N>
+PolymorphicAction<
+  internal::SetArgumentPointeeAction<N, const char*, false> >
+SetArgPointee(const char* p) {
+  return MakePolymorphicAction(internal::SetArgumentPointeeAction<
+      N, const char*, false>(p));
+}
+
+template <size_t N>
+PolymorphicAction<
+  internal::SetArgumentPointeeAction<N, const wchar_t*, false> >
+SetArgPointee(const wchar_t* p) {
+  return MakePolymorphicAction(internal::SetArgumentPointeeAction<
+      N, const wchar_t*, false>(p));
+}
+#endif
+
+// The following version is DEPRECATED.
+template <size_t N, typename T>
+PolymorphicAction<
+  internal::SetArgumentPointeeAction<
+    N, T, internal::IsAProtocolMessage<T>::value> >
+SetArgumentPointee(const T& x) {
+  return MakePolymorphicAction(internal::SetArgumentPointeeAction<
+      N, T, internal::IsAProtocolMessage<T>::value>(x));
+}
+
+// Creates an action that sets a pointer referent to a given value.
+template <typename T1, typename T2>
+PolymorphicAction<internal::AssignAction<T1, T2> > Assign(T1* ptr, T2 val) {
+  return MakePolymorphicAction(internal::AssignAction<T1, T2>(ptr, val));
+}
+
+#if !GTEST_OS_WINDOWS_MOBILE
+
+// Creates an action that sets errno and returns the appropriate error.
+template <typename T>
+PolymorphicAction<internal::SetErrnoAndReturnAction<T> >
+SetErrnoAndReturn(int errval, T result) {
+  return MakePolymorphicAction(
+      internal::SetErrnoAndReturnAction<T>(errval, result));
+}
+
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+// Various overloads for InvokeWithoutArgs().
+
+// Creates an action that invokes 'function_impl' with no argument.
+template <typename FunctionImpl>
+PolymorphicAction<internal::InvokeWithoutArgsAction<FunctionImpl> >
+InvokeWithoutArgs(FunctionImpl function_impl) {
+  return MakePolymorphicAction(
+      internal::InvokeWithoutArgsAction<FunctionImpl>(function_impl));
+}
+
+// Creates an action that invokes the given method on the given object
+// with no argument.
+template <class Class, typename MethodPtr>
+PolymorphicAction<internal::InvokeMethodWithoutArgsAction<Class, MethodPtr> >
+InvokeWithoutArgs(Class* obj_ptr, MethodPtr method_ptr) {
+  return MakePolymorphicAction(
+      internal::InvokeMethodWithoutArgsAction<Class, MethodPtr>(
+          obj_ptr, method_ptr));
+}
+
+// Creates an action that performs an_action and throws away its
+// result.  In other words, it changes the return type of an_action to
+// void.  an_action MUST NOT return void, or the code won't compile.
+template <typename A>
+inline internal::IgnoreResultAction<A> IgnoreResult(const A& an_action) {
+  return internal::IgnoreResultAction<A>(an_action);
+}
+
+// Creates a reference wrapper for the given L-value.  If necessary,
+// you can explicitly specify the type of the reference.  For example,
+// suppose 'derived' is an object of type Derived, ByRef(derived)
+// would wrap a Derived&.  If you want to wrap a const Base& instead,
+// where Base is a base class of Derived, just write:
+//
+//   ByRef<const Base>(derived)
+template <typename T>
+inline internal::ReferenceWrapper<T> ByRef(T& l_value) {  // NOLINT
+  return internal::ReferenceWrapper<T>(l_value);
+}
+
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_
diff --git a/third_party/googletest/googlemock/include/gmock/gmock-cardinalities.h b/third_party/googletest/googlemock/include/gmock/gmock-cardinalities.h
new file mode 100644
index 0000000..fc315f9
--- /dev/null
+++ b/third_party/googletest/googlemock/include/gmock/gmock-cardinalities.h
@@ -0,0 +1,147 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements some commonly used cardinalities.  More
+// cardinalities can be defined by the user implementing the
+// CardinalityInterface interface if necessary.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_
+
+#include <limits.h>
+#include <ostream>  // NOLINT
+#include "gmock/internal/gmock-port.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+
+// To implement a cardinality Foo, define:
+//   1. a class FooCardinality that implements the
+//      CardinalityInterface interface, and
+//   2. a factory function that creates a Cardinality object from a
+//      const FooCardinality*.
+//
+// The two-level delegation design follows that of Matcher, providing
+// consistency for extension developers.  It also eases ownership
+// management as Cardinality objects can now be copied like plain values.
+
+// The implementation of a cardinality.
+class CardinalityInterface {
+ public:
+  virtual ~CardinalityInterface() {}
+
+  // Conservative estimate on the lower/upper bound of the number of
+  // calls allowed.
+  virtual int ConservativeLowerBound() const { return 0; }
+  virtual int ConservativeUpperBound() const { return INT_MAX; }
+
+  // Returns true iff call_count calls will satisfy this cardinality.
+  virtual bool IsSatisfiedByCallCount(int call_count) const = 0;
+
+  // Returns true iff call_count calls will saturate this cardinality.
+  virtual bool IsSaturatedByCallCount(int call_count) const = 0;
+
+  // Describes self to an ostream.
+  virtual void DescribeTo(::std::ostream* os) const = 0;
+};
+
+// A Cardinality is a copyable and IMMUTABLE (except by assignment)
+// object that specifies how many times a mock function is expected to
+// be called.  The implementation of Cardinality is just a linked_ptr
+// to const CardinalityInterface, so copying is fairly cheap.
+// Don't inherit from Cardinality!
+class GTEST_API_ Cardinality {
+ public:
+  // Constructs a null cardinality.  Needed for storing Cardinality
+  // objects in STL containers.
+  Cardinality() {}
+
+  // Constructs a Cardinality from its implementation.
+  explicit Cardinality(const CardinalityInterface* impl) : impl_(impl) {}
+
+  // Conservative estimate on the lower/upper bound of the number of
+  // calls allowed.
+  int ConservativeLowerBound() const { return impl_->ConservativeLowerBound(); }
+  int ConservativeUpperBound() const { return impl_->ConservativeUpperBound(); }
+
+  // Returns true iff call_count calls will satisfy this cardinality.
+  bool IsSatisfiedByCallCount(int call_count) const {
+    return impl_->IsSatisfiedByCallCount(call_count);
+  }
+
+  // Returns true iff call_count calls will saturate this cardinality.
+  bool IsSaturatedByCallCount(int call_count) const {
+    return impl_->IsSaturatedByCallCount(call_count);
+  }
+
+  // Returns true iff call_count calls will over-saturate this
+  // cardinality, i.e. exceed the maximum number of allowed calls.
+  bool IsOverSaturatedByCallCount(int call_count) const {
+    return impl_->IsSaturatedByCallCount(call_count) &&
+        !impl_->IsSatisfiedByCallCount(call_count);
+  }
+
+  // Describes self to an ostream
+  void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); }
+
+  // Describes the given actual call count to an ostream.
+  static void DescribeActualCallCountTo(int actual_call_count,
+                                        ::std::ostream* os);
+
+ private:
+  internal::linked_ptr<const CardinalityInterface> impl_;
+};
+
+// Creates a cardinality that allows at least n calls.
+GTEST_API_ Cardinality AtLeast(int n);
+
+// Creates a cardinality that allows at most n calls.
+GTEST_API_ Cardinality AtMost(int n);
+
+// Creates a cardinality that allows any number of calls.
+GTEST_API_ Cardinality AnyNumber();
+
+// Creates a cardinality that allows between min and max calls.
+GTEST_API_ Cardinality Between(int min, int max);
+
+// Creates a cardinality that allows exactly n calls.
+GTEST_API_ Cardinality Exactly(int n);
+
+// Creates a cardinality from its implementation.
+inline Cardinality MakeCardinality(const CardinalityInterface* c) {
+  return Cardinality(c);
+}
+
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_
diff --git a/third_party/googletest/googlemock/include/gmock/gmock-generated-actions.h b/third_party/googletest/googlemock/include/gmock/gmock-generated-actions.h
new file mode 100644
index 0000000..b5a889c
--- /dev/null
+++ b/third_party/googletest/googlemock/include/gmock/gmock-generated-actions.h
@@ -0,0 +1,2377 @@
+// This file was GENERATED by a script.  DO NOT EDIT BY HAND!!!
+
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements some commonly used variadic actions.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
+
+#include "gmock/gmock-actions.h"
+#include "gmock/internal/gmock-port.h"
+
+namespace testing {
+namespace internal {
+
+// InvokeHelper<F> knows how to unpack an N-tuple and invoke an N-ary
+// function or method with the unpacked values, where F is a function
+// type that takes N arguments.
+template <typename Result, typename ArgumentTuple>
+class InvokeHelper;
+
+template <typename R>
+class InvokeHelper<R, ::testing::tuple<> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::testing::tuple<>&) {
+           return function();
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::testing::tuple<>&) {
+           return (obj_ptr->*method_ptr)();
+  }
+};
+
+template <typename R, typename A1>
+class InvokeHelper<R, ::testing::tuple<A1> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::testing::tuple<A1>& args) {
+           return function(get<0>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::testing::tuple<A1>& args) {
+           return (obj_ptr->*method_ptr)(get<0>(args));
+  }
+};
+
+template <typename R, typename A1, typename A2>
+class InvokeHelper<R, ::testing::tuple<A1, A2> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::testing::tuple<A1, A2>& args) {
+           return function(get<0>(args), get<1>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::testing::tuple<A1, A2>& args) {
+           return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3>
+class InvokeHelper<R, ::testing::tuple<A1, A2, A3> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::testing::tuple<A1, A2, A3>& args) {
+           return function(get<0>(args), get<1>(args), get<2>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::testing::tuple<A1, A2, A3>& args) {
+           return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args),
+               get<2>(args));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4>
+class InvokeHelper<R, ::testing::tuple<A1, A2, A3, A4> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::testing::tuple<A1, A2, A3,
+      A4>& args) {
+           return function(get<0>(args), get<1>(args), get<2>(args),
+               get<3>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::testing::tuple<A1, A2, A3, A4>& args) {
+           return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args),
+               get<2>(args), get<3>(args));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5>
+class InvokeHelper<R, ::testing::tuple<A1, A2, A3, A4, A5> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::testing::tuple<A1, A2, A3, A4,
+      A5>& args) {
+           return function(get<0>(args), get<1>(args), get<2>(args),
+               get<3>(args), get<4>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::testing::tuple<A1, A2, A3, A4, A5>& args) {
+           return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args),
+               get<2>(args), get<3>(args), get<4>(args));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6>
+class InvokeHelper<R, ::testing::tuple<A1, A2, A3, A4, A5, A6> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::testing::tuple<A1, A2, A3, A4, A5,
+      A6>& args) {
+           return function(get<0>(args), get<1>(args), get<2>(args),
+               get<3>(args), get<4>(args), get<5>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::testing::tuple<A1, A2, A3, A4, A5, A6>& args) {
+           return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args),
+               get<2>(args), get<3>(args), get<4>(args), get<5>(args));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7>
+class InvokeHelper<R, ::testing::tuple<A1, A2, A3, A4, A5, A6, A7> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::testing::tuple<A1, A2, A3, A4, A5,
+      A6, A7>& args) {
+           return function(get<0>(args), get<1>(args), get<2>(args),
+               get<3>(args), get<4>(args), get<5>(args), get<6>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::testing::tuple<A1, A2, A3, A4, A5, A6,
+                            A7>& args) {
+           return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args),
+               get<2>(args), get<3>(args), get<4>(args), get<5>(args),
+               get<6>(args));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7, typename A8>
+class InvokeHelper<R, ::testing::tuple<A1, A2, A3, A4, A5, A6, A7, A8> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::testing::tuple<A1, A2, A3, A4, A5,
+      A6, A7, A8>& args) {
+           return function(get<0>(args), get<1>(args), get<2>(args),
+               get<3>(args), get<4>(args), get<5>(args), get<6>(args),
+               get<7>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::testing::tuple<A1, A2, A3, A4, A5, A6, A7,
+                            A8>& args) {
+           return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args),
+               get<2>(args), get<3>(args), get<4>(args), get<5>(args),
+               get<6>(args), get<7>(args));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7, typename A8, typename A9>
+class InvokeHelper<R, ::testing::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::testing::tuple<A1, A2, A3, A4, A5,
+      A6, A7, A8, A9>& args) {
+           return function(get<0>(args), get<1>(args), get<2>(args),
+               get<3>(args), get<4>(args), get<5>(args), get<6>(args),
+               get<7>(args), get<8>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::testing::tuple<A1, A2, A3, A4, A5, A6, A7, A8,
+                            A9>& args) {
+           return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args),
+               get<2>(args), get<3>(args), get<4>(args), get<5>(args),
+               get<6>(args), get<7>(args), get<8>(args));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7, typename A8, typename A9,
+    typename A10>
+class InvokeHelper<R, ::testing::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9,
+    A10> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::testing::tuple<A1, A2, A3, A4, A5,
+      A6, A7, A8, A9, A10>& args) {
+           return function(get<0>(args), get<1>(args), get<2>(args),
+               get<3>(args), get<4>(args), get<5>(args), get<6>(args),
+               get<7>(args), get<8>(args), get<9>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::testing::tuple<A1, A2, A3, A4, A5, A6, A7, A8,
+                            A9, A10>& args) {
+           return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args),
+               get<2>(args), get<3>(args), get<4>(args), get<5>(args),
+               get<6>(args), get<7>(args), get<8>(args), get<9>(args));
+  }
+};
+
+// An INTERNAL macro for extracting the type of a tuple field.  It's
+// subject to change without notice - DO NOT USE IN USER CODE!
+#define GMOCK_FIELD_(Tuple, N) \
+    typename ::testing::tuple_element<N, Tuple>::type
+
+// SelectArgs<Result, ArgumentTuple, k1, k2, ..., k_n>::type is the
+// type of an n-ary function whose i-th (1-based) argument type is the
+// k{i}-th (0-based) field of ArgumentTuple, which must be a tuple
+// type, and whose return type is Result.  For example,
+//   SelectArgs<int, ::testing::tuple<bool, char, double, long>, 0, 3>::type
+// is int(bool, long).
+//
+// SelectArgs<Result, ArgumentTuple, k1, k2, ..., k_n>::Select(args)
+// returns the selected fields (k1, k2, ..., k_n) of args as a tuple.
+// For example,
+//   SelectArgs<int, tuple<bool, char, double>, 2, 0>::Select(
+//       ::testing::make_tuple(true, 'a', 2.5))
+// returns tuple (2.5, true).
+//
+// The numbers in list k1, k2, ..., k_n must be >= 0, where n can be
+// in the range [0, 10].  Duplicates are allowed and they don't have
+// to be in an ascending or descending order.
+
+template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
+    int k4, int k5, int k6, int k7, int k8, int k9, int k10>
+class SelectArgs {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
+      GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
+      GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5),
+      GMOCK_FIELD_(ArgumentTuple, k6), GMOCK_FIELD_(ArgumentTuple, k7),
+      GMOCK_FIELD_(ArgumentTuple, k8), GMOCK_FIELD_(ArgumentTuple, k9),
+      GMOCK_FIELD_(ArgumentTuple, k10));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    return SelectedArgs(get<k1>(args), get<k2>(args), get<k3>(args),
+        get<k4>(args), get<k5>(args), get<k6>(args), get<k7>(args),
+        get<k8>(args), get<k9>(args), get<k10>(args));
+  }
+};
+
+template <typename Result, typename ArgumentTuple>
+class SelectArgs<Result, ArgumentTuple,
+                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef Result type();
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& /* args */) {
+    return SelectedArgs();
+  }
+};
+
+template <typename Result, typename ArgumentTuple, int k1>
+class SelectArgs<Result, ArgumentTuple,
+                 k1, -1, -1, -1, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    return SelectedArgs(get<k1>(args));
+  }
+};
+
+template <typename Result, typename ArgumentTuple, int k1, int k2>
+class SelectArgs<Result, ArgumentTuple,
+                 k1, k2, -1, -1, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
+      GMOCK_FIELD_(ArgumentTuple, k2));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    return SelectedArgs(get<k1>(args), get<k2>(args));
+  }
+};
+
+template <typename Result, typename ArgumentTuple, int k1, int k2, int k3>
+class SelectArgs<Result, ArgumentTuple,
+                 k1, k2, k3, -1, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
+      GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    return SelectedArgs(get<k1>(args), get<k2>(args), get<k3>(args));
+  }
+};
+
+template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
+    int k4>
+class SelectArgs<Result, ArgumentTuple,
+                 k1, k2, k3, k4, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
+      GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
+      GMOCK_FIELD_(ArgumentTuple, k4));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    return SelectedArgs(get<k1>(args), get<k2>(args), get<k3>(args),
+        get<k4>(args));
+  }
+};
+
+template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
+    int k4, int k5>
+class SelectArgs<Result, ArgumentTuple,
+                 k1, k2, k3, k4, k5, -1, -1, -1, -1, -1> {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
+      GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
+      GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    return SelectedArgs(get<k1>(args), get<k2>(args), get<k3>(args),
+        get<k4>(args), get<k5>(args));
+  }
+};
+
+template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
+    int k4, int k5, int k6>
+class SelectArgs<Result, ArgumentTuple,
+                 k1, k2, k3, k4, k5, k6, -1, -1, -1, -1> {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
+      GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
+      GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5),
+      GMOCK_FIELD_(ArgumentTuple, k6));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    return SelectedArgs(get<k1>(args), get<k2>(args), get<k3>(args),
+        get<k4>(args), get<k5>(args), get<k6>(args));
+  }
+};
+
+template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
+    int k4, int k5, int k6, int k7>
+class SelectArgs<Result, ArgumentTuple,
+                 k1, k2, k3, k4, k5, k6, k7, -1, -1, -1> {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
+      GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
+      GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5),
+      GMOCK_FIELD_(ArgumentTuple, k6), GMOCK_FIELD_(ArgumentTuple, k7));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    return SelectedArgs(get<k1>(args), get<k2>(args), get<k3>(args),
+        get<k4>(args), get<k5>(args), get<k6>(args), get<k7>(args));
+  }
+};
+
+template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
+    int k4, int k5, int k6, int k7, int k8>
+class SelectArgs<Result, ArgumentTuple,
+                 k1, k2, k3, k4, k5, k6, k7, k8, -1, -1> {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
+      GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
+      GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5),
+      GMOCK_FIELD_(ArgumentTuple, k6), GMOCK_FIELD_(ArgumentTuple, k7),
+      GMOCK_FIELD_(ArgumentTuple, k8));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    return SelectedArgs(get<k1>(args), get<k2>(args), get<k3>(args),
+        get<k4>(args), get<k5>(args), get<k6>(args), get<k7>(args),
+        get<k8>(args));
+  }
+};
+
+template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
+    int k4, int k5, int k6, int k7, int k8, int k9>
+class SelectArgs<Result, ArgumentTuple,
+                 k1, k2, k3, k4, k5, k6, k7, k8, k9, -1> {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
+      GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
+      GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5),
+      GMOCK_FIELD_(ArgumentTuple, k6), GMOCK_FIELD_(ArgumentTuple, k7),
+      GMOCK_FIELD_(ArgumentTuple, k8), GMOCK_FIELD_(ArgumentTuple, k9));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    return SelectedArgs(get<k1>(args), get<k2>(args), get<k3>(args),
+        get<k4>(args), get<k5>(args), get<k6>(args), get<k7>(args),
+        get<k8>(args), get<k9>(args));
+  }
+};
+
+#undef GMOCK_FIELD_
+
+// Implements the WithArgs action.
+template <typename InnerAction, int k1 = -1, int k2 = -1, int k3 = -1,
+    int k4 = -1, int k5 = -1, int k6 = -1, int k7 = -1, int k8 = -1,
+    int k9 = -1, int k10 = -1>
+class WithArgsAction {
+ public:
+  explicit WithArgsAction(const InnerAction& action) : action_(action) {}
+
+  template <typename F>
+  operator Action<F>() const { return MakeAction(new Impl<F>(action_)); }
+
+ private:
+  template <typename F>
+  class Impl : public ActionInterface<F> {
+   public:
+    typedef typename Function<F>::Result Result;
+    typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+
+    explicit Impl(const InnerAction& action) : action_(action) {}
+
+    virtual Result Perform(const ArgumentTuple& args) {
+      return action_.Perform(SelectArgs<Result, ArgumentTuple, k1, k2, k3, k4,
+          k5, k6, k7, k8, k9, k10>::Select(args));
+    }
+
+   private:
+    typedef typename SelectArgs<Result, ArgumentTuple,
+        k1, k2, k3, k4, k5, k6, k7, k8, k9, k10>::type InnerFunctionType;
+
+    Action<InnerFunctionType> action_;
+  };
+
+  const InnerAction action_;
+
+  GTEST_DISALLOW_ASSIGN_(WithArgsAction);
+};
+
+// A macro from the ACTION* family (defined later in this file)
+// defines an action that can be used in a mock function.  Typically,
+// these actions only care about a subset of the arguments of the mock
+// function.  For example, if such an action only uses the second
+// argument, it can be used in any mock function that takes >= 2
+// arguments where the type of the second argument is compatible.
+//
+// Therefore, the action implementation must be prepared to take more
+// arguments than it needs.  The ExcessiveArg type is used to
+// represent those excessive arguments.  In order to keep the compiler
+// error messages tractable, we define it in the testing namespace
+// instead of testing::internal.  However, this is an INTERNAL TYPE
+// and subject to change without notice, so a user MUST NOT USE THIS
+// TYPE DIRECTLY.
+struct ExcessiveArg {};
+
+// A helper class needed for implementing the ACTION* macros.
+template <typename Result, class Impl>
+class ActionHelper {
+ public:
+  static Result Perform(Impl* impl, const ::testing::tuple<>& args) {
+    return impl->template gmock_PerformImpl<>(args, ExcessiveArg(),
+        ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg());
+  }
+
+  template <typename A0>
+  static Result Perform(Impl* impl, const ::testing::tuple<A0>& args) {
+    return impl->template gmock_PerformImpl<A0>(args, get<0>(args),
+        ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg());
+  }
+
+  template <typename A0, typename A1>
+  static Result Perform(Impl* impl, const ::testing::tuple<A0, A1>& args) {
+    return impl->template gmock_PerformImpl<A0, A1>(args, get<0>(args),
+        get<1>(args), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg());
+  }
+
+  template <typename A0, typename A1, typename A2>
+  static Result Perform(Impl* impl, const ::testing::tuple<A0, A1, A2>& args) {
+    return impl->template gmock_PerformImpl<A0, A1, A2>(args, get<0>(args),
+        get<1>(args), get<2>(args), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg());
+  }
+
+  template <typename A0, typename A1, typename A2, typename A3>
+  static Result Perform(Impl* impl, const ::testing::tuple<A0, A1, A2,
+      A3>& args) {
+    return impl->template gmock_PerformImpl<A0, A1, A2, A3>(args, get<0>(args),
+        get<1>(args), get<2>(args), get<3>(args), ExcessiveArg(),
+        ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg());
+  }
+
+  template <typename A0, typename A1, typename A2, typename A3, typename A4>
+  static Result Perform(Impl* impl, const ::testing::tuple<A0, A1, A2, A3,
+      A4>& args) {
+    return impl->template gmock_PerformImpl<A0, A1, A2, A3, A4>(args,
+        get<0>(args), get<1>(args), get<2>(args), get<3>(args), get<4>(args),
+        ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg());
+  }
+
+  template <typename A0, typename A1, typename A2, typename A3, typename A4,
+      typename A5>
+  static Result Perform(Impl* impl, const ::testing::tuple<A0, A1, A2, A3, A4,
+      A5>& args) {
+    return impl->template gmock_PerformImpl<A0, A1, A2, A3, A4, A5>(args,
+        get<0>(args), get<1>(args), get<2>(args), get<3>(args), get<4>(args),
+        get<5>(args), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg());
+  }
+
+  template <typename A0, typename A1, typename A2, typename A3, typename A4,
+      typename A5, typename A6>
+  static Result Perform(Impl* impl, const ::testing::tuple<A0, A1, A2, A3, A4,
+      A5, A6>& args) {
+    return impl->template gmock_PerformImpl<A0, A1, A2, A3, A4, A5, A6>(args,
+        get<0>(args), get<1>(args), get<2>(args), get<3>(args), get<4>(args),
+        get<5>(args), get<6>(args), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg());
+  }
+
+  template <typename A0, typename A1, typename A2, typename A3, typename A4,
+      typename A5, typename A6, typename A7>
+  static Result Perform(Impl* impl, const ::testing::tuple<A0, A1, A2, A3, A4,
+      A5, A6, A7>& args) {
+    return impl->template gmock_PerformImpl<A0, A1, A2, A3, A4, A5, A6,
+        A7>(args, get<0>(args), get<1>(args), get<2>(args), get<3>(args),
+        get<4>(args), get<5>(args), get<6>(args), get<7>(args), ExcessiveArg(),
+        ExcessiveArg());
+  }
+
+  template <typename A0, typename A1, typename A2, typename A3, typename A4,
+      typename A5, typename A6, typename A7, typename A8>
+  static Result Perform(Impl* impl, const ::testing::tuple<A0, A1, A2, A3, A4,
+      A5, A6, A7, A8>& args) {
+    return impl->template gmock_PerformImpl<A0, A1, A2, A3, A4, A5, A6, A7,
+        A8>(args, get<0>(args), get<1>(args), get<2>(args), get<3>(args),
+        get<4>(args), get<5>(args), get<6>(args), get<7>(args), get<8>(args),
+        ExcessiveArg());
+  }
+
+  template <typename A0, typename A1, typename A2, typename A3, typename A4,
+      typename A5, typename A6, typename A7, typename A8, typename A9>
+  static Result Perform(Impl* impl, const ::testing::tuple<A0, A1, A2, A3, A4,
+      A5, A6, A7, A8, A9>& args) {
+    return impl->template gmock_PerformImpl<A0, A1, A2, A3, A4, A5, A6, A7, A8,
+        A9>(args, get<0>(args), get<1>(args), get<2>(args), get<3>(args),
+        get<4>(args), get<5>(args), get<6>(args), get<7>(args), get<8>(args),
+        get<9>(args));
+  }
+};
+
+}  // namespace internal
+
+// Various overloads for Invoke().
+
+// WithArgs<N1, N2, ..., Nk>(an_action) creates an action that passes
+// the selected arguments of the mock function to an_action and
+// performs it.  It serves as an adaptor between actions with
+// different argument lists.  C++ doesn't support default arguments for
+// function templates, so we have to overload it.
+template <int k1, typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1>(action);
+}
+
+template <int k1, int k2, typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1, k2>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1, k2>(action);
+}
+
+template <int k1, int k2, int k3, typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1, k2, k3>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1, k2, k3>(action);
+}
+
+template <int k1, int k2, int k3, int k4, typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1, k2, k3, k4>(action);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5>(action);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6>(action);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, int k7,
+    typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6,
+      k7>(action);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8,
+    typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7, k8>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7,
+      k8>(action);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8,
+    int k9, typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7, k8, k9>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7, k8,
+      k9>(action);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8,
+    int k9, int k10, typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7, k8,
+    k9, k10>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7, k8,
+      k9, k10>(action);
+}
+
+// Creates an action that does actions a1, a2, ..., sequentially in
+// each invocation.
+template <typename Action1, typename Action2>
+inline internal::DoBothAction<Action1, Action2>
+DoAll(Action1 a1, Action2 a2) {
+  return internal::DoBothAction<Action1, Action2>(a1, a2);
+}
+
+template <typename Action1, typename Action2, typename Action3>
+inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
+    Action3> >
+DoAll(Action1 a1, Action2 a2, Action3 a3) {
+  return DoAll(a1, DoAll(a2, a3));
+}
+
+template <typename Action1, typename Action2, typename Action3,
+    typename Action4>
+inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
+    internal::DoBothAction<Action3, Action4> > >
+DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4) {
+  return DoAll(a1, DoAll(a2, a3, a4));
+}
+
+template <typename Action1, typename Action2, typename Action3,
+    typename Action4, typename Action5>
+inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
+    internal::DoBothAction<Action3, internal::DoBothAction<Action4,
+    Action5> > > >
+DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5) {
+  return DoAll(a1, DoAll(a2, a3, a4, a5));
+}
+
+template <typename Action1, typename Action2, typename Action3,
+    typename Action4, typename Action5, typename Action6>
+inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
+    internal::DoBothAction<Action3, internal::DoBothAction<Action4,
+    internal::DoBothAction<Action5, Action6> > > > >
+DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6) {
+  return DoAll(a1, DoAll(a2, a3, a4, a5, a6));
+}
+
+template <typename Action1, typename Action2, typename Action3,
+    typename Action4, typename Action5, typename Action6, typename Action7>
+inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
+    internal::DoBothAction<Action3, internal::DoBothAction<Action4,
+    internal::DoBothAction<Action5, internal::DoBothAction<Action6,
+    Action7> > > > > >
+DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6,
+    Action7 a7) {
+  return DoAll(a1, DoAll(a2, a3, a4, a5, a6, a7));
+}
+
+template <typename Action1, typename Action2, typename Action3,
+    typename Action4, typename Action5, typename Action6, typename Action7,
+    typename Action8>
+inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
+    internal::DoBothAction<Action3, internal::DoBothAction<Action4,
+    internal::DoBothAction<Action5, internal::DoBothAction<Action6,
+    internal::DoBothAction<Action7, Action8> > > > > > >
+DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6,
+    Action7 a7, Action8 a8) {
+  return DoAll(a1, DoAll(a2, a3, a4, a5, a6, a7, a8));
+}
+
+template <typename Action1, typename Action2, typename Action3,
+    typename Action4, typename Action5, typename Action6, typename Action7,
+    typename Action8, typename Action9>
+inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
+    internal::DoBothAction<Action3, internal::DoBothAction<Action4,
+    internal::DoBothAction<Action5, internal::DoBothAction<Action6,
+    internal::DoBothAction<Action7, internal::DoBothAction<Action8,
+    Action9> > > > > > > >
+DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6,
+    Action7 a7, Action8 a8, Action9 a9) {
+  return DoAll(a1, DoAll(a2, a3, a4, a5, a6, a7, a8, a9));
+}
+
+template <typename Action1, typename Action2, typename Action3,
+    typename Action4, typename Action5, typename Action6, typename Action7,
+    typename Action8, typename Action9, typename Action10>
+inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
+    internal::DoBothAction<Action3, internal::DoBothAction<Action4,
+    internal::DoBothAction<Action5, internal::DoBothAction<Action6,
+    internal::DoBothAction<Action7, internal::DoBothAction<Action8,
+    internal::DoBothAction<Action9, Action10> > > > > > > > >
+DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6,
+    Action7 a7, Action8 a8, Action9 a9, Action10 a10) {
+  return DoAll(a1, DoAll(a2, a3, a4, a5, a6, a7, a8, a9, a10));
+}
+
+}  // namespace testing
+
+// The ACTION* family of macros can be used in a namespace scope to
+// define custom actions easily.  The syntax:
+//
+//   ACTION(name) { statements; }
+//
+// will define an action with the given name that executes the
+// statements.  The value returned by the statements will be used as
+// the return value of the action.  Inside the statements, you can
+// refer to the K-th (0-based) argument of the mock function by
+// 'argK', and refer to its type by 'argK_type'.  For example:
+//
+//   ACTION(IncrementArg1) {
+//     arg1_type temp = arg1;
+//     return ++(*temp);
+//   }
+//
+// allows you to write
+//
+//   ...WillOnce(IncrementArg1());
+//
+// You can also refer to the entire argument tuple and its type by
+// 'args' and 'args_type', and refer to the mock function type and its
+// return type by 'function_type' and 'return_type'.
+//
+// Note that you don't need to specify the types of the mock function
+// arguments.  However rest assured that your code is still type-safe:
+// you'll get a compiler error if *arg1 doesn't support the ++
+// operator, or if the type of ++(*arg1) isn't compatible with the
+// mock function's return type, for example.
+//
+// Sometimes you'll want to parameterize the action.   For that you can use
+// another macro:
+//
+//   ACTION_P(name, param_name) { statements; }
+//
+// For example:
+//
+//   ACTION_P(Add, n) { return arg0 + n; }
+//
+// will allow you to write:
+//
+//   ...WillOnce(Add(5));
+//
+// Note that you don't need to provide the type of the parameter
+// either.  If you need to reference the type of a parameter named
+// 'foo', you can write 'foo_type'.  For example, in the body of
+// ACTION_P(Add, n) above, you can write 'n_type' to refer to the type
+// of 'n'.
+//
+// We also provide ACTION_P2, ACTION_P3, ..., up to ACTION_P10 to support
+// multi-parameter actions.
+//
+// For the purpose of typing, you can view
+//
+//   ACTION_Pk(Foo, p1, ..., pk) { ... }
+//
+// as shorthand for
+//
+//   template <typename p1_type, ..., typename pk_type>
+//   FooActionPk<p1_type, ..., pk_type> Foo(p1_type p1, ..., pk_type pk) { ... }
+//
+// In particular, you can provide the template type arguments
+// explicitly when invoking Foo(), as in Foo<long, bool>(5, false);
+// although usually you can rely on the compiler to infer the types
+// for you automatically.  You can assign the result of expression
+// Foo(p1, ..., pk) to a variable of type FooActionPk<p1_type, ...,
+// pk_type>.  This can be useful when composing actions.
+//
+// You can also overload actions with different numbers of parameters:
+//
+//   ACTION_P(Plus, a) { ... }
+//   ACTION_P2(Plus, a, b) { ... }
+//
+// While it's tempting to always use the ACTION* macros when defining
+// a new action, you should also consider implementing ActionInterface
+// or using MakePolymorphicAction() instead, especially if you need to
+// use the action a lot.  While these approaches require more work,
+// they give you more control on the types of the mock function
+// arguments and the action parameters, which in general leads to
+// better compiler error messages that pay off in the long run.  They
+// also allow overloading actions based on parameter types (as opposed
+// to just based on the number of parameters).
+//
+// CAVEAT:
+//
+// ACTION*() can only be used in a namespace scope.  The reason is
+// that C++ doesn't yet allow function-local types to be used to
+// instantiate templates.  The up-coming C++0x standard will fix this.
+// Once that's done, we'll consider supporting using ACTION*() inside
+// a function.
+//
+// MORE INFORMATION:
+//
+// To learn more about using these macros, please search for 'ACTION'
+// on http://code.google.com/p/googlemock/wiki/CookBook.
+
+// An internal macro needed for implementing ACTION*().
+#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_\
+    const args_type& args GTEST_ATTRIBUTE_UNUSED_, \
+    arg0_type arg0 GTEST_ATTRIBUTE_UNUSED_, \
+    arg1_type arg1 GTEST_ATTRIBUTE_UNUSED_, \
+    arg2_type arg2 GTEST_ATTRIBUTE_UNUSED_, \
+    arg3_type arg3 GTEST_ATTRIBUTE_UNUSED_, \
+    arg4_type arg4 GTEST_ATTRIBUTE_UNUSED_, \
+    arg5_type arg5 GTEST_ATTRIBUTE_UNUSED_, \
+    arg6_type arg6 GTEST_ATTRIBUTE_UNUSED_, \
+    arg7_type arg7 GTEST_ATTRIBUTE_UNUSED_, \
+    arg8_type arg8 GTEST_ATTRIBUTE_UNUSED_, \
+    arg9_type arg9 GTEST_ATTRIBUTE_UNUSED_
+
+// Sometimes you want to give an action explicit template parameters
+// that cannot be inferred from its value parameters.  ACTION() and
+// ACTION_P*() don't support that.  ACTION_TEMPLATE() remedies that
+// and can be viewed as an extension to ACTION() and ACTION_P*().
+//
+// The syntax:
+//
+//   ACTION_TEMPLATE(ActionName,
+//                   HAS_m_TEMPLATE_PARAMS(kind1, name1, ..., kind_m, name_m),
+//                   AND_n_VALUE_PARAMS(p1, ..., p_n)) { statements; }
+//
+// defines an action template that takes m explicit template
+// parameters and n value parameters.  name_i is the name of the i-th
+// template parameter, and kind_i specifies whether it's a typename,
+// an integral constant, or a template.  p_i is the name of the i-th
+// value parameter.
+//
+// Example:
+//
+//   // DuplicateArg<k, T>(output) converts the k-th argument of the mock
+//   // function to type T and copies it to *output.
+//   ACTION_TEMPLATE(DuplicateArg,
+//                   HAS_2_TEMPLATE_PARAMS(int, k, typename, T),
+//                   AND_1_VALUE_PARAMS(output)) {
+//     *output = T(::testing::get<k>(args));
+//   }
+//   ...
+//     int n;
+//     EXPECT_CALL(mock, Foo(_, _))
+//         .WillOnce(DuplicateArg<1, unsigned char>(&n));
+//
+// To create an instance of an action template, write:
+//
+//   ActionName<t1, ..., t_m>(v1, ..., v_n)
+//
+// where the ts are the template arguments and the vs are the value
+// arguments.  The value argument types are inferred by the compiler.
+// If you want to explicitly specify the value argument types, you can
+// provide additional template arguments:
+//
+//   ActionName<t1, ..., t_m, u1, ..., u_k>(v1, ..., v_n)
+//
+// where u_i is the desired type of v_i.
+//
+// ACTION_TEMPLATE and ACTION/ACTION_P* can be overloaded on the
+// number of value parameters, but not on the number of template
+// parameters.  Without the restriction, the meaning of the following
+// is unclear:
+//
+//   OverloadedAction<int, bool>(x);
+//
+// Are we using a single-template-parameter action where 'bool' refers
+// to the type of x, or are we using a two-template-parameter action
+// where the compiler is asked to infer the type of x?
+//
+// Implementation notes:
+//
+// GMOCK_INTERNAL_*_HAS_m_TEMPLATE_PARAMS and
+// GMOCK_INTERNAL_*_AND_n_VALUE_PARAMS are internal macros for
+// implementing ACTION_TEMPLATE.  The main trick we use is to create
+// new macro invocations when expanding a macro.  For example, we have
+//
+//   #define ACTION_TEMPLATE(name, template_params, value_params)
+//       ... GMOCK_INTERNAL_DECL_##template_params ...
+//
+// which causes ACTION_TEMPLATE(..., HAS_1_TEMPLATE_PARAMS(typename, T), ...)
+// to expand to
+//
+//       ... GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS(typename, T) ...
+//
+// Since GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS is a macro, the
+// preprocessor will continue to expand it to
+//
+//       ... typename T ...
+//
+// This technique conforms to the C++ standard and is portable.  It
+// allows us to implement action templates using O(N) code, where N is
+// the maximum number of template/value parameters supported.  Without
+// using it, we'd have to devote O(N^2) amount of code to implement all
+// combinations of m and n.
+
+// Declares the template parameters.
+#define GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS(kind0, name0) kind0 name0
+#define GMOCK_INTERNAL_DECL_HAS_2_TEMPLATE_PARAMS(kind0, name0, kind1, \
+    name1) kind0 name0, kind1 name1
+#define GMOCK_INTERNAL_DECL_HAS_3_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2) kind0 name0, kind1 name1, kind2 name2
+#define GMOCK_INTERNAL_DECL_HAS_4_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3) kind0 name0, kind1 name1, kind2 name2, \
+    kind3 name3
+#define GMOCK_INTERNAL_DECL_HAS_5_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4) kind0 name0, kind1 name1, \
+    kind2 name2, kind3 name3, kind4 name4
+#define GMOCK_INTERNAL_DECL_HAS_6_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4, kind5, name5) kind0 name0, \
+    kind1 name1, kind2 name2, kind3 name3, kind4 name4, kind5 name5
+#define GMOCK_INTERNAL_DECL_HAS_7_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, \
+    name6) kind0 name0, kind1 name1, kind2 name2, kind3 name3, kind4 name4, \
+    kind5 name5, kind6 name6
+#define GMOCK_INTERNAL_DECL_HAS_8_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, name6, \
+    kind7, name7) kind0 name0, kind1 name1, kind2 name2, kind3 name3, \
+    kind4 name4, kind5 name5, kind6 name6, kind7 name7
+#define GMOCK_INTERNAL_DECL_HAS_9_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, name6, \
+    kind7, name7, kind8, name8) kind0 name0, kind1 name1, kind2 name2, \
+    kind3 name3, kind4 name4, kind5 name5, kind6 name6, kind7 name7, \
+    kind8 name8
+#define GMOCK_INTERNAL_DECL_HAS_10_TEMPLATE_PARAMS(kind0, name0, kind1, \
+    name1, kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, \
+    name6, kind7, name7, kind8, name8, kind9, name9) kind0 name0, \
+    kind1 name1, kind2 name2, kind3 name3, kind4 name4, kind5 name5, \
+    kind6 name6, kind7 name7, kind8 name8, kind9 name9
+
+// Lists the template parameters.
+#define GMOCK_INTERNAL_LIST_HAS_1_TEMPLATE_PARAMS(kind0, name0) name0
+#define GMOCK_INTERNAL_LIST_HAS_2_TEMPLATE_PARAMS(kind0, name0, kind1, \
+    name1) name0, name1
+#define GMOCK_INTERNAL_LIST_HAS_3_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2) name0, name1, name2
+#define GMOCK_INTERNAL_LIST_HAS_4_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3) name0, name1, name2, name3
+#define GMOCK_INTERNAL_LIST_HAS_5_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4) name0, name1, name2, name3, \
+    name4
+#define GMOCK_INTERNAL_LIST_HAS_6_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4, kind5, name5) name0, name1, \
+    name2, name3, name4, name5
+#define GMOCK_INTERNAL_LIST_HAS_7_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, \
+    name6) name0, name1, name2, name3, name4, name5, name6
+#define GMOCK_INTERNAL_LIST_HAS_8_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, name6, \
+    kind7, name7) name0, name1, name2, name3, name4, name5, name6, name7
+#define GMOCK_INTERNAL_LIST_HAS_9_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, name6, \
+    kind7, name7, kind8, name8) name0, name1, name2, name3, name4, name5, \
+    name6, name7, name8
+#define GMOCK_INTERNAL_LIST_HAS_10_TEMPLATE_PARAMS(kind0, name0, kind1, \
+    name1, kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, \
+    name6, kind7, name7, kind8, name8, kind9, name9) name0, name1, name2, \
+    name3, name4, name5, name6, name7, name8, name9
+
+// Declares the types of value parameters.
+#define GMOCK_INTERNAL_DECL_TYPE_AND_0_VALUE_PARAMS()
+#define GMOCK_INTERNAL_DECL_TYPE_AND_1_VALUE_PARAMS(p0) , typename p0##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_2_VALUE_PARAMS(p0, p1) , \
+    typename p0##_type, typename p1##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_3_VALUE_PARAMS(p0, p1, p2) , \
+    typename p0##_type, typename p1##_type, typename p2##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_4_VALUE_PARAMS(p0, p1, p2, p3) , \
+    typename p0##_type, typename p1##_type, typename p2##_type, \
+    typename p3##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) , \
+    typename p0##_type, typename p1##_type, typename p2##_type, \
+    typename p3##_type, typename p4##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) , \
+    typename p0##_type, typename p1##_type, typename p2##_type, \
+    typename p3##_type, typename p4##_type, typename p5##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6) , typename p0##_type, typename p1##_type, typename p2##_type, \
+    typename p3##_type, typename p4##_type, typename p5##_type, \
+    typename p6##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6, p7) , typename p0##_type, typename p1##_type, typename p2##_type, \
+    typename p3##_type, typename p4##_type, typename p5##_type, \
+    typename p6##_type, typename p7##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6, p7, p8) , typename p0##_type, typename p1##_type, typename p2##_type, \
+    typename p3##_type, typename p4##_type, typename p5##_type, \
+    typename p6##_type, typename p7##_type, typename p8##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6, p7, p8, p9) , typename p0##_type, typename p1##_type, \
+    typename p2##_type, typename p3##_type, typename p4##_type, \
+    typename p5##_type, typename p6##_type, typename p7##_type, \
+    typename p8##_type, typename p9##_type
+
+// Initializes the value parameters.
+#define GMOCK_INTERNAL_INIT_AND_0_VALUE_PARAMS()\
+    ()
+#define GMOCK_INTERNAL_INIT_AND_1_VALUE_PARAMS(p0)\
+    (p0##_type gmock_p0) : p0(gmock_p0)
+#define GMOCK_INTERNAL_INIT_AND_2_VALUE_PARAMS(p0, p1)\
+    (p0##_type gmock_p0, p1##_type gmock_p1) : p0(gmock_p0), p1(gmock_p1)
+#define GMOCK_INTERNAL_INIT_AND_3_VALUE_PARAMS(p0, p1, p2)\
+    (p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2)
+#define GMOCK_INTERNAL_INIT_AND_4_VALUE_PARAMS(p0, p1, p2, p3)\
+    (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+        p3##_type gmock_p3) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3)
+#define GMOCK_INTERNAL_INIT_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4)\
+    (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+        p3##_type gmock_p3, p4##_type gmock_p4) : p0(gmock_p0), p1(gmock_p1), \
+        p2(gmock_p2), p3(gmock_p3), p4(gmock_p4)
+#define GMOCK_INTERNAL_INIT_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5)\
+    (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+        p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5)
+#define GMOCK_INTERNAL_INIT_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6)\
+    (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+        p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+        p6##_type gmock_p6) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6)
+#define GMOCK_INTERNAL_INIT_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7)\
+    (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+        p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+        p6##_type gmock_p6, p7##_type gmock_p7) : p0(gmock_p0), p1(gmock_p1), \
+        p2(gmock_p2), p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \
+        p7(gmock_p7)
+#define GMOCK_INTERNAL_INIT_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8)\
+    (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+        p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+        p6##_type gmock_p6, p7##_type gmock_p7, \
+        p8##_type gmock_p8) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \
+        p8(gmock_p8)
+#define GMOCK_INTERNAL_INIT_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8, p9)\
+    (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+        p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+        p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8, \
+        p9##_type gmock_p9) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \
+        p8(gmock_p8), p9(gmock_p9)
+
+// Declares the fields for storing the value parameters.
+#define GMOCK_INTERNAL_DEFN_AND_0_VALUE_PARAMS()
+#define GMOCK_INTERNAL_DEFN_AND_1_VALUE_PARAMS(p0) p0##_type p0;
+#define GMOCK_INTERNAL_DEFN_AND_2_VALUE_PARAMS(p0, p1) p0##_type p0; \
+    p1##_type p1;
+#define GMOCK_INTERNAL_DEFN_AND_3_VALUE_PARAMS(p0, p1, p2) p0##_type p0; \
+    p1##_type p1; p2##_type p2;
+#define GMOCK_INTERNAL_DEFN_AND_4_VALUE_PARAMS(p0, p1, p2, p3) p0##_type p0; \
+    p1##_type p1; p2##_type p2; p3##_type p3;
+#define GMOCK_INTERNAL_DEFN_AND_5_VALUE_PARAMS(p0, p1, p2, p3, \
+    p4) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; p4##_type p4;
+#define GMOCK_INTERNAL_DEFN_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, \
+    p5) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; p4##_type p4; \
+    p5##_type p5;
+#define GMOCK_INTERNAL_DEFN_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; p4##_type p4; \
+    p5##_type p5; p6##_type p6;
+#define GMOCK_INTERNAL_DEFN_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; p4##_type p4; \
+    p5##_type p5; p6##_type p6; p7##_type p7;
+#define GMOCK_INTERNAL_DEFN_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; \
+    p4##_type p4; p5##_type p5; p6##_type p6; p7##_type p7; p8##_type p8;
+#define GMOCK_INTERNAL_DEFN_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8, p9) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; \
+    p4##_type p4; p5##_type p5; p6##_type p6; p7##_type p7; p8##_type p8; \
+    p9##_type p9;
+
+// Lists the value parameters.
+#define GMOCK_INTERNAL_LIST_AND_0_VALUE_PARAMS()
+#define GMOCK_INTERNAL_LIST_AND_1_VALUE_PARAMS(p0) p0
+#define GMOCK_INTERNAL_LIST_AND_2_VALUE_PARAMS(p0, p1) p0, p1
+#define GMOCK_INTERNAL_LIST_AND_3_VALUE_PARAMS(p0, p1, p2) p0, p1, p2
+#define GMOCK_INTERNAL_LIST_AND_4_VALUE_PARAMS(p0, p1, p2, p3) p0, p1, p2, p3
+#define GMOCK_INTERNAL_LIST_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) p0, p1, \
+    p2, p3, p4
+#define GMOCK_INTERNAL_LIST_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) p0, \
+    p1, p2, p3, p4, p5
+#define GMOCK_INTERNAL_LIST_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6) p0, p1, p2, p3, p4, p5, p6
+#define GMOCK_INTERNAL_LIST_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7) p0, p1, p2, p3, p4, p5, p6, p7
+#define GMOCK_INTERNAL_LIST_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8) p0, p1, p2, p3, p4, p5, p6, p7, p8
+#define GMOCK_INTERNAL_LIST_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8, p9) p0, p1, p2, p3, p4, p5, p6, p7, p8, p9
+
+// Lists the value parameter types.
+#define GMOCK_INTERNAL_LIST_TYPE_AND_0_VALUE_PARAMS()
+#define GMOCK_INTERNAL_LIST_TYPE_AND_1_VALUE_PARAMS(p0) , p0##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_2_VALUE_PARAMS(p0, p1) , p0##_type, \
+    p1##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_3_VALUE_PARAMS(p0, p1, p2) , p0##_type, \
+    p1##_type, p2##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_4_VALUE_PARAMS(p0, p1, p2, p3) , \
+    p0##_type, p1##_type, p2##_type, p3##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) , \
+    p0##_type, p1##_type, p2##_type, p3##_type, p4##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) , \
+    p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, p5##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6) , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, p5##_type, \
+    p6##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6, p7) , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+    p5##_type, p6##_type, p7##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6, p7, p8) , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+    p5##_type, p6##_type, p7##_type, p8##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6, p7, p8, p9) , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+    p5##_type, p6##_type, p7##_type, p8##_type, p9##_type
+
+// Declares the value parameters.
+#define GMOCK_INTERNAL_DECL_AND_0_VALUE_PARAMS()
+#define GMOCK_INTERNAL_DECL_AND_1_VALUE_PARAMS(p0) p0##_type p0
+#define GMOCK_INTERNAL_DECL_AND_2_VALUE_PARAMS(p0, p1) p0##_type p0, \
+    p1##_type p1
+#define GMOCK_INTERNAL_DECL_AND_3_VALUE_PARAMS(p0, p1, p2) p0##_type p0, \
+    p1##_type p1, p2##_type p2
+#define GMOCK_INTERNAL_DECL_AND_4_VALUE_PARAMS(p0, p1, p2, p3) p0##_type p0, \
+    p1##_type p1, p2##_type p2, p3##_type p3
+#define GMOCK_INTERNAL_DECL_AND_5_VALUE_PARAMS(p0, p1, p2, p3, \
+    p4) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4
+#define GMOCK_INTERNAL_DECL_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, \
+    p5) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, \
+    p5##_type p5
+#define GMOCK_INTERNAL_DECL_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, \
+    p5##_type p5, p6##_type p6
+#define GMOCK_INTERNAL_DECL_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, \
+    p5##_type p5, p6##_type p6, p7##_type p7
+#define GMOCK_INTERNAL_DECL_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \
+    p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8
+#define GMOCK_INTERNAL_DECL_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8, p9) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \
+    p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8, \
+    p9##_type p9
+
+// The suffix of the class template implementing the action template.
+#define GMOCK_INTERNAL_COUNT_AND_0_VALUE_PARAMS()
+#define GMOCK_INTERNAL_COUNT_AND_1_VALUE_PARAMS(p0) P
+#define GMOCK_INTERNAL_COUNT_AND_2_VALUE_PARAMS(p0, p1) P2
+#define GMOCK_INTERNAL_COUNT_AND_3_VALUE_PARAMS(p0, p1, p2) P3
+#define GMOCK_INTERNAL_COUNT_AND_4_VALUE_PARAMS(p0, p1, p2, p3) P4
+#define GMOCK_INTERNAL_COUNT_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) P5
+#define GMOCK_INTERNAL_COUNT_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) P6
+#define GMOCK_INTERNAL_COUNT_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6) P7
+#define GMOCK_INTERNAL_COUNT_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7) P8
+#define GMOCK_INTERNAL_COUNT_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8) P9
+#define GMOCK_INTERNAL_COUNT_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8, p9) P10
+
+// The name of the class template implementing the action template.
+#define GMOCK_ACTION_CLASS_(name, value_params)\
+    GTEST_CONCAT_TOKEN_(name##Action, GMOCK_INTERNAL_COUNT_##value_params)
+
+#define ACTION_TEMPLATE(name, template_params, value_params)\
+  template <GMOCK_INTERNAL_DECL_##template_params\
+            GMOCK_INTERNAL_DECL_TYPE_##value_params>\
+  class GMOCK_ACTION_CLASS_(name, value_params) {\
+   public:\
+    explicit GMOCK_ACTION_CLASS_(name, value_params)\
+        GMOCK_INTERNAL_INIT_##value_params {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      explicit gmock_Impl GMOCK_INTERNAL_INIT_##value_params {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      GMOCK_INTERNAL_DEFN_##value_params\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(\
+          new gmock_Impl<F>(GMOCK_INTERNAL_LIST_##value_params));\
+    }\
+    GMOCK_INTERNAL_DEFN_##value_params\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(GMOCK_ACTION_CLASS_(name, value_params));\
+  };\
+  template <GMOCK_INTERNAL_DECL_##template_params\
+            GMOCK_INTERNAL_DECL_TYPE_##value_params>\
+  inline GMOCK_ACTION_CLASS_(name, value_params)<\
+      GMOCK_INTERNAL_LIST_##template_params\
+      GMOCK_INTERNAL_LIST_TYPE_##value_params> name(\
+          GMOCK_INTERNAL_DECL_##value_params) {\
+    return GMOCK_ACTION_CLASS_(name, value_params)<\
+        GMOCK_INTERNAL_LIST_##template_params\
+        GMOCK_INTERNAL_LIST_TYPE_##value_params>(\
+            GMOCK_INTERNAL_LIST_##value_params);\
+  }\
+  template <GMOCK_INTERNAL_DECL_##template_params\
+            GMOCK_INTERNAL_DECL_TYPE_##value_params>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      GMOCK_ACTION_CLASS_(name, value_params)<\
+          GMOCK_INTERNAL_LIST_##template_params\
+          GMOCK_INTERNAL_LIST_TYPE_##value_params>::gmock_Impl<F>::\
+              gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION(name)\
+  class name##Action {\
+   public:\
+    name##Action() {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl() {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>());\
+    }\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##Action);\
+  };\
+  inline name##Action name() {\
+    return name##Action();\
+  }\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##Action::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P(name, p0)\
+  template <typename p0##_type>\
+  class name##ActionP {\
+   public:\
+    explicit name##ActionP(p0##_type gmock_p0) : p0(gmock_p0) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      explicit gmock_Impl(p0##_type gmock_p0) : p0(gmock_p0) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0));\
+    }\
+    p0##_type p0;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP);\
+  };\
+  template <typename p0##_type>\
+  inline name##ActionP<p0##_type> name(p0##_type p0) {\
+    return name##ActionP<p0##_type>(p0);\
+  }\
+  template <typename p0##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP<p0##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P2(name, p0, p1)\
+  template <typename p0##_type, typename p1##_type>\
+  class name##ActionP2 {\
+   public:\
+    name##ActionP2(p0##_type gmock_p0, p1##_type gmock_p1) : p0(gmock_p0), \
+        p1(gmock_p1) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1) : p0(gmock_p0), \
+          p1(gmock_p1) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+      p1##_type p1;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0, p1));\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP2);\
+  };\
+  template <typename p0##_type, typename p1##_type>\
+  inline name##ActionP2<p0##_type, p1##_type> name(p0##_type p0, \
+      p1##_type p1) {\
+    return name##ActionP2<p0##_type, p1##_type>(p0, p1);\
+  }\
+  template <typename p0##_type, typename p1##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP2<p0##_type, p1##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P3(name, p0, p1, p2)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type>\
+  class name##ActionP3 {\
+   public:\
+    name##ActionP3(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, \
+          p2##_type gmock_p2) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2));\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP3);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type>\
+  inline name##ActionP3<p0##_type, p1##_type, p2##_type> name(p0##_type p0, \
+      p1##_type p1, p2##_type p2) {\
+    return name##ActionP3<p0##_type, p1##_type, p2##_type>(p0, p1, p2);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP3<p0##_type, p1##_type, \
+          p2##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P4(name, p0, p1, p2, p3)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type>\
+  class name##ActionP4 {\
+   public:\
+    name##ActionP4(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3) : p0(gmock_p0), p1(gmock_p1), \
+        p2(gmock_p2), p3(gmock_p3) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+          p3(gmock_p3) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3));\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP4);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type>\
+  inline name##ActionP4<p0##_type, p1##_type, p2##_type, \
+      p3##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, \
+      p3##_type p3) {\
+    return name##ActionP4<p0##_type, p1##_type, p2##_type, p3##_type>(p0, p1, \
+        p2, p3);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP4<p0##_type, p1##_type, p2##_type, \
+          p3##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P5(name, p0, p1, p2, p3, p4)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type>\
+  class name##ActionP5 {\
+   public:\
+    name##ActionP5(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, \
+        p4##_type gmock_p4) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4) : p0(gmock_p0), \
+          p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), p4(gmock_p4) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3, p4));\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP5);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type>\
+  inline name##ActionP5<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \
+      p4##_type p4) {\
+    return name##ActionP5<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type>(p0, p1, p2, p3, p4);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP5<p0##_type, p1##_type, p2##_type, p3##_type, \
+          p4##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P6(name, p0, p1, p2, p3, p4, p5)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type>\
+  class name##ActionP6 {\
+   public:\
+    name##ActionP6(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, \
+          p5##_type gmock_p5) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+          p3(gmock_p3), p4(gmock_p4), p5(gmock_p5) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3, p4, p5));\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP6);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type>\
+  inline name##ActionP6<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, \
+      p3##_type p3, p4##_type p4, p5##_type p5) {\
+    return name##ActionP6<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type>(p0, p1, p2, p3, p4, p5);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP6<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+          p5##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P7(name, p0, p1, p2, p3, p4, p5, p6)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type>\
+  class name##ActionP7 {\
+   public:\
+    name##ActionP7(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5, p6##_type gmock_p6) : p0(gmock_p0), p1(gmock_p1), \
+        p2(gmock_p2), p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), \
+        p6(gmock_p6) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+          p6##_type gmock_p6) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+          p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+      p6##_type p6;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3, p4, p5, \
+          p6));\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+    p6##_type p6;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP7);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type>\
+  inline name##ActionP7<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type, p6##_type> name(p0##_type p0, p1##_type p1, \
+      p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \
+      p6##_type p6) {\
+    return name##ActionP7<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type, p6##_type>(p0, p1, p2, p3, p4, p5, p6);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP7<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+          p5##_type, p6##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P8(name, p0, p1, p2, p3, p4, p5, p6, p7)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type>\
+  class name##ActionP8 {\
+   public:\
+    name##ActionP8(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5, p6##_type gmock_p6, \
+        p7##_type gmock_p7) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \
+        p7(gmock_p7) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+          p6##_type gmock_p6, p7##_type gmock_p7) : p0(gmock_p0), \
+          p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), p4(gmock_p4), \
+          p5(gmock_p5), p6(gmock_p6), p7(gmock_p7) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+      p6##_type p6;\
+      p7##_type p7;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3, p4, p5, \
+          p6, p7));\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+    p6##_type p6;\
+    p7##_type p7;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP8);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type>\
+  inline name##ActionP8<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type, p6##_type, p7##_type> name(p0##_type p0, \
+      p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \
+      p6##_type p6, p7##_type p7) {\
+    return name##ActionP8<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type, p6##_type, p7##_type>(p0, p1, p2, p3, p4, p5, \
+        p6, p7);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP8<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+          p5##_type, p6##_type, \
+          p7##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type>\
+  class name##ActionP9 {\
+   public:\
+    name##ActionP9(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \
+        p8##_type gmock_p8) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \
+        p8(gmock_p8) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+          p6##_type gmock_p6, p7##_type gmock_p7, \
+          p8##_type gmock_p8) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+          p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \
+          p7(gmock_p7), p8(gmock_p8) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+      p6##_type p6;\
+      p7##_type p7;\
+      p8##_type p8;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3, p4, p5, \
+          p6, p7, p8));\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+    p6##_type p6;\
+    p7##_type p7;\
+    p8##_type p8;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP9);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type>\
+  inline name##ActionP9<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type, p6##_type, p7##_type, \
+      p8##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \
+      p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, \
+      p8##_type p8) {\
+    return name##ActionP9<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type, p6##_type, p7##_type, p8##_type>(p0, p1, p2, \
+        p3, p4, p5, p6, p7, p8);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP9<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+          p5##_type, p6##_type, p7##_type, \
+          p8##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type, \
+      typename p9##_type>\
+  class name##ActionP10 {\
+   public:\
+    name##ActionP10(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \
+        p8##_type gmock_p8, p9##_type gmock_p9) : p0(gmock_p0), p1(gmock_p1), \
+        p2(gmock_p2), p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \
+        p7(gmock_p7), p8(gmock_p8), p9(gmock_p9) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+          p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8, \
+          p9##_type gmock_p9) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+          p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \
+          p7(gmock_p7), p8(gmock_p8), p9(gmock_p9) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+      p6##_type p6;\
+      p7##_type p7;\
+      p8##_type p8;\
+      p9##_type p9;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3, p4, p5, \
+          p6, p7, p8, p9));\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+    p6##_type p6;\
+    p7##_type p7;\
+    p8##_type p8;\
+    p9##_type p9;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP10);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type, \
+      typename p9##_type>\
+  inline name##ActionP10<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, \
+      p9##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \
+      p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8, \
+      p9##_type p9) {\
+    return name##ActionP10<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, p9##_type>(p0, \
+        p1, p2, p3, p4, p5, p6, p7, p8, p9);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type, \
+      typename p9##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP10<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+          p5##_type, p6##_type, p7##_type, p8##_type, \
+          p9##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+namespace testing {
+
+
+// The ACTION*() macros trigger warning C4100 (unreferenced formal
+// parameter) in MSVC with -W4.  Unfortunately they cannot be fixed in
+// the macro definition, as the warnings are generated when the macro
+// is expanded and macro expansion cannot contain #pragma.  Therefore
+// we suppress them here.
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4100)
+#endif
+
+// Various overloads for InvokeArgument<N>().
+//
+// The InvokeArgument<N>(a1, a2, ..., a_k) action invokes the N-th
+// (0-based) argument, which must be a k-ary callable, of the mock
+// function, with arguments a1, a2, ..., a_k.
+//
+// Notes:
+//
+//   1. The arguments are passed by value by default.  If you need to
+//   pass an argument by reference, wrap it inside ByRef().  For
+//   example,
+//
+//     InvokeArgument<1>(5, string("Hello"), ByRef(foo))
+//
+//   passes 5 and string("Hello") by value, and passes foo by
+//   reference.
+//
+//   2. If the callable takes an argument by reference but ByRef() is
+//   not used, it will receive the reference to a copy of the value,
+//   instead of the original value.  For example, when the 0-th
+//   argument of the mock function takes a const string&, the action
+//
+//     InvokeArgument<0>(string("Hello"))
+//
+//   makes a copy of the temporary string("Hello") object and passes a
+//   reference of the copy, instead of the original temporary object,
+//   to the callable.  This makes it easy for a user to define an
+//   InvokeArgument action from temporary values and have it performed
+//   later.
+
+namespace internal {
+namespace invoke_argument {
+
+// Appears in InvokeArgumentAdl's argument list to help avoid
+// accidental calls to user functions of the same name.
+struct AdlTag {};
+
+// InvokeArgumentAdl - a helper for InvokeArgument.
+// The basic overloads are provided here for generic functors.
+// Overloads for other custom-callables are provided in the
+// internal/custom/callback-actions.h header.
+
+template <typename R, typename F>
+R InvokeArgumentAdl(AdlTag, F f) {
+  return f();
+}
+template <typename R, typename F, typename A1>
+R InvokeArgumentAdl(AdlTag, F f, A1 a1) {
+  return f(a1);
+}
+template <typename R, typename F, typename A1, typename A2>
+R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2) {
+  return f(a1, a2);
+}
+template <typename R, typename F, typename A1, typename A2, typename A3>
+R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3) {
+  return f(a1, a2, a3);
+}
+template <typename R, typename F, typename A1, typename A2, typename A3,
+    typename A4>
+R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4) {
+  return f(a1, a2, a3, a4);
+}
+template <typename R, typename F, typename A1, typename A2, typename A3,
+    typename A4, typename A5>
+R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) {
+  return f(a1, a2, a3, a4, a5);
+}
+template <typename R, typename F, typename A1, typename A2, typename A3,
+    typename A4, typename A5, typename A6>
+R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) {
+  return f(a1, a2, a3, a4, a5, a6);
+}
+template <typename R, typename F, typename A1, typename A2, typename A3,
+    typename A4, typename A5, typename A6, typename A7>
+R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6,
+    A7 a7) {
+  return f(a1, a2, a3, a4, a5, a6, a7);
+}
+template <typename R, typename F, typename A1, typename A2, typename A3,
+    typename A4, typename A5, typename A6, typename A7, typename A8>
+R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6,
+    A7 a7, A8 a8) {
+  return f(a1, a2, a3, a4, a5, a6, a7, a8);
+}
+template <typename R, typename F, typename A1, typename A2, typename A3,
+    typename A4, typename A5, typename A6, typename A7, typename A8,
+    typename A9>
+R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6,
+    A7 a7, A8 a8, A9 a9) {
+  return f(a1, a2, a3, a4, a5, a6, a7, a8, a9);
+}
+template <typename R, typename F, typename A1, typename A2, typename A3,
+    typename A4, typename A5, typename A6, typename A7, typename A8,
+    typename A9, typename A10>
+R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6,
+    A7 a7, A8 a8, A9 a9, A10 a10) {
+  return f(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
+}
+}  // namespace invoke_argument
+}  // namespace internal
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_0_VALUE_PARAMS()) {
+  using internal::invoke_argument::InvokeArgumentAdl;
+  return InvokeArgumentAdl<return_type>(
+      internal::invoke_argument::AdlTag(),
+      ::testing::get<k>(args));
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_1_VALUE_PARAMS(p0)) {
+  using internal::invoke_argument::InvokeArgumentAdl;
+  return InvokeArgumentAdl<return_type>(
+      internal::invoke_argument::AdlTag(),
+      ::testing::get<k>(args), p0);
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_2_VALUE_PARAMS(p0, p1)) {
+  using internal::invoke_argument::InvokeArgumentAdl;
+  return InvokeArgumentAdl<return_type>(
+      internal::invoke_argument::AdlTag(),
+      ::testing::get<k>(args), p0, p1);
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_3_VALUE_PARAMS(p0, p1, p2)) {
+  using internal::invoke_argument::InvokeArgumentAdl;
+  return InvokeArgumentAdl<return_type>(
+      internal::invoke_argument::AdlTag(),
+      ::testing::get<k>(args), p0, p1, p2);
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_4_VALUE_PARAMS(p0, p1, p2, p3)) {
+  using internal::invoke_argument::InvokeArgumentAdl;
+  return InvokeArgumentAdl<return_type>(
+      internal::invoke_argument::AdlTag(),
+      ::testing::get<k>(args), p0, p1, p2, p3);
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4)) {
+  using internal::invoke_argument::InvokeArgumentAdl;
+  return InvokeArgumentAdl<return_type>(
+      internal::invoke_argument::AdlTag(),
+      ::testing::get<k>(args), p0, p1, p2, p3, p4);
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5)) {
+  using internal::invoke_argument::InvokeArgumentAdl;
+  return InvokeArgumentAdl<return_type>(
+      internal::invoke_argument::AdlTag(),
+      ::testing::get<k>(args), p0, p1, p2, p3, p4, p5);
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6)) {
+  using internal::invoke_argument::InvokeArgumentAdl;
+  return InvokeArgumentAdl<return_type>(
+      internal::invoke_argument::AdlTag(),
+      ::testing::get<k>(args), p0, p1, p2, p3, p4, p5, p6);
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7)) {
+  using internal::invoke_argument::InvokeArgumentAdl;
+  return InvokeArgumentAdl<return_type>(
+      internal::invoke_argument::AdlTag(),
+      ::testing::get<k>(args), p0, p1, p2, p3, p4, p5, p6, p7);
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8)) {
+  using internal::invoke_argument::InvokeArgumentAdl;
+  return InvokeArgumentAdl<return_type>(
+      internal::invoke_argument::AdlTag(),
+      ::testing::get<k>(args), p0, p1, p2, p3, p4, p5, p6, p7, p8);
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)) {
+  using internal::invoke_argument::InvokeArgumentAdl;
+  return InvokeArgumentAdl<return_type>(
+      internal::invoke_argument::AdlTag(),
+      ::testing::get<k>(args), p0, p1, p2, p3, p4, p5, p6, p7, p8, p9);
+}
+
+// Various overloads for ReturnNew<T>().
+//
+// The ReturnNew<T>(a1, a2, ..., a_k) action returns a pointer to a new
+// instance of type T, constructed on the heap with constructor arguments
+// a1, a2, ..., and a_k. The caller assumes ownership of the returned value.
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_0_VALUE_PARAMS()) {
+  return new T();
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_1_VALUE_PARAMS(p0)) {
+  return new T(p0);
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_2_VALUE_PARAMS(p0, p1)) {
+  return new T(p0, p1);
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_3_VALUE_PARAMS(p0, p1, p2)) {
+  return new T(p0, p1, p2);
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_4_VALUE_PARAMS(p0, p1, p2, p3)) {
+  return new T(p0, p1, p2, p3);
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4)) {
+  return new T(p0, p1, p2, p3, p4);
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5)) {
+  return new T(p0, p1, p2, p3, p4, p5);
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6)) {
+  return new T(p0, p1, p2, p3, p4, p5, p6);
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7)) {
+  return new T(p0, p1, p2, p3, p4, p5, p6, p7);
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8)) {
+  return new T(p0, p1, p2, p3, p4, p5, p6, p7, p8);
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)) {
+  return new T(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9);
+}
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+}  // namespace testing
+
+// Include any custom actions added by the local installation.
+// We must include this header at the end to make sure it can use the
+// declarations from this file.
+#include "gmock/internal/custom/gmock-generated-actions.h"
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
diff --git a/third_party/googletest/googlemock/include/gmock/gmock-generated-actions.h.pump b/third_party/googletest/googlemock/include/gmock/gmock-generated-actions.h.pump
new file mode 100644
index 0000000..66d9f9d
--- /dev/null
+++ b/third_party/googletest/googlemock/include/gmock/gmock-generated-actions.h.pump
@@ -0,0 +1,794 @@
+$$ -*- mode: c++; -*-
+$$ This is a Pump source file.  Please use Pump to convert it to
+$$ gmock-generated-actions.h.
+$$
+$var n = 10  $$ The maximum arity we support.
+$$}} This meta comment fixes auto-indentation in editors.
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements some commonly used variadic actions.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
+
+#include "gmock/gmock-actions.h"
+#include "gmock/internal/gmock-port.h"
+
+namespace testing {
+namespace internal {
+
+// InvokeHelper<F> knows how to unpack an N-tuple and invoke an N-ary
+// function or method with the unpacked values, where F is a function
+// type that takes N arguments.
+template <typename Result, typename ArgumentTuple>
+class InvokeHelper;
+
+
+$range i 0..n
+$for i [[
+$range j 1..i
+$var types = [[$for j [[, typename A$j]]]]
+$var as = [[$for j, [[A$j]]]]
+$var args = [[$if i==0 [[]] $else [[ args]]]]
+$var gets = [[$for j, [[get<$(j - 1)>(args)]]]]
+template <typename R$types>
+class InvokeHelper<R, ::testing::tuple<$as> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::testing::tuple<$as>&$args) {
+           return function($gets);
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::testing::tuple<$as>&$args) {
+           return (obj_ptr->*method_ptr)($gets);
+  }
+};
+
+
+]]
+// An INTERNAL macro for extracting the type of a tuple field.  It's
+// subject to change without notice - DO NOT USE IN USER CODE!
+#define GMOCK_FIELD_(Tuple, N) \
+    typename ::testing::tuple_element<N, Tuple>::type
+
+$range i 1..n
+
+// SelectArgs<Result, ArgumentTuple, k1, k2, ..., k_n>::type is the
+// type of an n-ary function whose i-th (1-based) argument type is the
+// k{i}-th (0-based) field of ArgumentTuple, which must be a tuple
+// type, and whose return type is Result.  For example,
+//   SelectArgs<int, ::testing::tuple<bool, char, double, long>, 0, 3>::type
+// is int(bool, long).
+//
+// SelectArgs<Result, ArgumentTuple, k1, k2, ..., k_n>::Select(args)
+// returns the selected fields (k1, k2, ..., k_n) of args as a tuple.
+// For example,
+//   SelectArgs<int, tuple<bool, char, double>, 2, 0>::Select(
+//       ::testing::make_tuple(true, 'a', 2.5))
+// returns tuple (2.5, true).
+//
+// The numbers in list k1, k2, ..., k_n must be >= 0, where n can be
+// in the range [0, $n].  Duplicates are allowed and they don't have
+// to be in an ascending or descending order.
+
+template <typename Result, typename ArgumentTuple, $for i, [[int k$i]]>
+class SelectArgs {
+ public:
+  typedef Result type($for i, [[GMOCK_FIELD_(ArgumentTuple, k$i)]]);
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    return SelectedArgs($for i, [[get<k$i>(args)]]);
+  }
+};
+
+
+$for i [[
+$range j 1..n
+$range j1 1..i-1
+template <typename Result, typename ArgumentTuple$for j1[[, int k$j1]]>
+class SelectArgs<Result, ArgumentTuple,
+                 $for j, [[$if j <= i-1 [[k$j]] $else [[-1]]]]> {
+ public:
+  typedef Result type($for j1, [[GMOCK_FIELD_(ArgumentTuple, k$j1)]]);
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& [[]]
+$if i == 1 [[/* args */]] $else [[args]]) {
+    return SelectedArgs($for j1, [[get<k$j1>(args)]]);
+  }
+};
+
+
+]]
+#undef GMOCK_FIELD_
+
+$var ks = [[$for i, [[k$i]]]]
+
+// Implements the WithArgs action.
+template <typename InnerAction, $for i, [[int k$i = -1]]>
+class WithArgsAction {
+ public:
+  explicit WithArgsAction(const InnerAction& action) : action_(action) {}
+
+  template <typename F>
+  operator Action<F>() const { return MakeAction(new Impl<F>(action_)); }
+
+ private:
+  template <typename F>
+  class Impl : public ActionInterface<F> {
+   public:
+    typedef typename Function<F>::Result Result;
+    typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+
+    explicit Impl(const InnerAction& action) : action_(action) {}
+
+    virtual Result Perform(const ArgumentTuple& args) {
+      return action_.Perform(SelectArgs<Result, ArgumentTuple, $ks>::Select(args));
+    }
+
+   private:
+    typedef typename SelectArgs<Result, ArgumentTuple,
+        $ks>::type InnerFunctionType;
+
+    Action<InnerFunctionType> action_;
+  };
+
+  const InnerAction action_;
+
+  GTEST_DISALLOW_ASSIGN_(WithArgsAction);
+};
+
+// A macro from the ACTION* family (defined later in this file)
+// defines an action that can be used in a mock function.  Typically,
+// these actions only care about a subset of the arguments of the mock
+// function.  For example, if such an action only uses the second
+// argument, it can be used in any mock function that takes >= 2
+// arguments where the type of the second argument is compatible.
+//
+// Therefore, the action implementation must be prepared to take more
+// arguments than it needs.  The ExcessiveArg type is used to
+// represent those excessive arguments.  In order to keep the compiler
+// error messages tractable, we define it in the testing namespace
+// instead of testing::internal.  However, this is an INTERNAL TYPE
+// and subject to change without notice, so a user MUST NOT USE THIS
+// TYPE DIRECTLY.
+struct ExcessiveArg {};
+
+// A helper class needed for implementing the ACTION* macros.
+template <typename Result, class Impl>
+class ActionHelper {
+ public:
+$range i 0..n
+$for i
+
+[[
+$var template = [[$if i==0 [[]] $else [[
+$range j 0..i-1
+  template <$for j, [[typename A$j]]>
+]]]]
+$range j 0..i-1
+$var As = [[$for j, [[A$j]]]]
+$var as = [[$for j, [[get<$j>(args)]]]]
+$range k 1..n-i
+$var eas = [[$for k, [[ExcessiveArg()]]]]
+$var arg_list = [[$if (i==0) | (i==n) [[$as$eas]] $else [[$as, $eas]]]]
+$template
+  static Result Perform(Impl* impl, const ::testing::tuple<$As>& args) {
+    return impl->template gmock_PerformImpl<$As>(args, $arg_list);
+  }
+
+]]
+};
+
+}  // namespace internal
+
+// Various overloads for Invoke().
+
+// WithArgs<N1, N2, ..., Nk>(an_action) creates an action that passes
+// the selected arguments of the mock function to an_action and
+// performs it.  It serves as an adaptor between actions with
+// different argument lists.  C++ doesn't support default arguments for
+// function templates, so we have to overload it.
+
+$range i 1..n
+$for i [[
+$range j 1..i
+template <$for j [[int k$j, ]]typename InnerAction>
+inline internal::WithArgsAction<InnerAction$for j [[, k$j]]>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction$for j [[, k$j]]>(action);
+}
+
+
+]]
+// Creates an action that does actions a1, a2, ..., sequentially in
+// each invocation.
+$range i 2..n
+$for i [[
+$range j 2..i
+$var types = [[$for j, [[typename Action$j]]]]
+$var Aas = [[$for j [[, Action$j a$j]]]]
+
+template <typename Action1, $types>
+$range k 1..i-1
+
+inline $for k [[internal::DoBothAction<Action$k, ]]Action$i$for k  [[>]]
+
+DoAll(Action1 a1$Aas) {
+$if i==2 [[
+
+  return internal::DoBothAction<Action1, Action2>(a1, a2);
+]] $else [[
+$range j2 2..i
+
+  return DoAll(a1, DoAll($for j2, [[a$j2]]));
+]]
+
+}
+
+]]
+
+}  // namespace testing
+
+// The ACTION* family of macros can be used in a namespace scope to
+// define custom actions easily.  The syntax:
+//
+//   ACTION(name) { statements; }
+//
+// will define an action with the given name that executes the
+// statements.  The value returned by the statements will be used as
+// the return value of the action.  Inside the statements, you can
+// refer to the K-th (0-based) argument of the mock function by
+// 'argK', and refer to its type by 'argK_type'.  For example:
+//
+//   ACTION(IncrementArg1) {
+//     arg1_type temp = arg1;
+//     return ++(*temp);
+//   }
+//
+// allows you to write
+//
+//   ...WillOnce(IncrementArg1());
+//
+// You can also refer to the entire argument tuple and its type by
+// 'args' and 'args_type', and refer to the mock function type and its
+// return type by 'function_type' and 'return_type'.
+//
+// Note that you don't need to specify the types of the mock function
+// arguments.  However rest assured that your code is still type-safe:
+// you'll get a compiler error if *arg1 doesn't support the ++
+// operator, or if the type of ++(*arg1) isn't compatible with the
+// mock function's return type, for example.
+//
+// Sometimes you'll want to parameterize the action.   For that you can use
+// another macro:
+//
+//   ACTION_P(name, param_name) { statements; }
+//
+// For example:
+//
+//   ACTION_P(Add, n) { return arg0 + n; }
+//
+// will allow you to write:
+//
+//   ...WillOnce(Add(5));
+//
+// Note that you don't need to provide the type of the parameter
+// either.  If you need to reference the type of a parameter named
+// 'foo', you can write 'foo_type'.  For example, in the body of
+// ACTION_P(Add, n) above, you can write 'n_type' to refer to the type
+// of 'n'.
+//
+// We also provide ACTION_P2, ACTION_P3, ..., up to ACTION_P$n to support
+// multi-parameter actions.
+//
+// For the purpose of typing, you can view
+//
+//   ACTION_Pk(Foo, p1, ..., pk) { ... }
+//
+// as shorthand for
+//
+//   template <typename p1_type, ..., typename pk_type>
+//   FooActionPk<p1_type, ..., pk_type> Foo(p1_type p1, ..., pk_type pk) { ... }
+//
+// In particular, you can provide the template type arguments
+// explicitly when invoking Foo(), as in Foo<long, bool>(5, false);
+// although usually you can rely on the compiler to infer the types
+// for you automatically.  You can assign the result of expression
+// Foo(p1, ..., pk) to a variable of type FooActionPk<p1_type, ...,
+// pk_type>.  This can be useful when composing actions.
+//
+// You can also overload actions with different numbers of parameters:
+//
+//   ACTION_P(Plus, a) { ... }
+//   ACTION_P2(Plus, a, b) { ... }
+//
+// While it's tempting to always use the ACTION* macros when defining
+// a new action, you should also consider implementing ActionInterface
+// or using MakePolymorphicAction() instead, especially if you need to
+// use the action a lot.  While these approaches require more work,
+// they give you more control on the types of the mock function
+// arguments and the action parameters, which in general leads to
+// better compiler error messages that pay off in the long run.  They
+// also allow overloading actions based on parameter types (as opposed
+// to just based on the number of parameters).
+//
+// CAVEAT:
+//
+// ACTION*() can only be used in a namespace scope.  The reason is
+// that C++ doesn't yet allow function-local types to be used to
+// instantiate templates.  The up-coming C++0x standard will fix this.
+// Once that's done, we'll consider supporting using ACTION*() inside
+// a function.
+//
+// MORE INFORMATION:
+//
+// To learn more about using these macros, please search for 'ACTION'
+// on http://code.google.com/p/googlemock/wiki/CookBook.
+
+$range i 0..n
+$range k 0..n-1
+
+// An internal macro needed for implementing ACTION*().
+#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_\
+    const args_type& args GTEST_ATTRIBUTE_UNUSED_
+$for k [[, \
+    arg$k[[]]_type arg$k GTEST_ATTRIBUTE_UNUSED_]]
+
+
+// Sometimes you want to give an action explicit template parameters
+// that cannot be inferred from its value parameters.  ACTION() and
+// ACTION_P*() don't support that.  ACTION_TEMPLATE() remedies that
+// and can be viewed as an extension to ACTION() and ACTION_P*().
+//
+// The syntax:
+//
+//   ACTION_TEMPLATE(ActionName,
+//                   HAS_m_TEMPLATE_PARAMS(kind1, name1, ..., kind_m, name_m),
+//                   AND_n_VALUE_PARAMS(p1, ..., p_n)) { statements; }
+//
+// defines an action template that takes m explicit template
+// parameters and n value parameters.  name_i is the name of the i-th
+// template parameter, and kind_i specifies whether it's a typename,
+// an integral constant, or a template.  p_i is the name of the i-th
+// value parameter.
+//
+// Example:
+//
+//   // DuplicateArg<k, T>(output) converts the k-th argument of the mock
+//   // function to type T and copies it to *output.
+//   ACTION_TEMPLATE(DuplicateArg,
+//                   HAS_2_TEMPLATE_PARAMS(int, k, typename, T),
+//                   AND_1_VALUE_PARAMS(output)) {
+//     *output = T(::testing::get<k>(args));
+//   }
+//   ...
+//     int n;
+//     EXPECT_CALL(mock, Foo(_, _))
+//         .WillOnce(DuplicateArg<1, unsigned char>(&n));
+//
+// To create an instance of an action template, write:
+//
+//   ActionName<t1, ..., t_m>(v1, ..., v_n)
+//
+// where the ts are the template arguments and the vs are the value
+// arguments.  The value argument types are inferred by the compiler.
+// If you want to explicitly specify the value argument types, you can
+// provide additional template arguments:
+//
+//   ActionName<t1, ..., t_m, u1, ..., u_k>(v1, ..., v_n)
+//
+// where u_i is the desired type of v_i.
+//
+// ACTION_TEMPLATE and ACTION/ACTION_P* can be overloaded on the
+// number of value parameters, but not on the number of template
+// parameters.  Without the restriction, the meaning of the following
+// is unclear:
+//
+//   OverloadedAction<int, bool>(x);
+//
+// Are we using a single-template-parameter action where 'bool' refers
+// to the type of x, or are we using a two-template-parameter action
+// where the compiler is asked to infer the type of x?
+//
+// Implementation notes:
+//
+// GMOCK_INTERNAL_*_HAS_m_TEMPLATE_PARAMS and
+// GMOCK_INTERNAL_*_AND_n_VALUE_PARAMS are internal macros for
+// implementing ACTION_TEMPLATE.  The main trick we use is to create
+// new macro invocations when expanding a macro.  For example, we have
+//
+//   #define ACTION_TEMPLATE(name, template_params, value_params)
+//       ... GMOCK_INTERNAL_DECL_##template_params ...
+//
+// which causes ACTION_TEMPLATE(..., HAS_1_TEMPLATE_PARAMS(typename, T), ...)
+// to expand to
+//
+//       ... GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS(typename, T) ...
+//
+// Since GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS is a macro, the
+// preprocessor will continue to expand it to
+//
+//       ... typename T ...
+//
+// This technique conforms to the C++ standard and is portable.  It
+// allows us to implement action templates using O(N) code, where N is
+// the maximum number of template/value parameters supported.  Without
+// using it, we'd have to devote O(N^2) amount of code to implement all
+// combinations of m and n.
+
+// Declares the template parameters.
+
+$range j 1..n
+$for j [[
+$range m 0..j-1
+#define GMOCK_INTERNAL_DECL_HAS_$j[[]]
+_TEMPLATE_PARAMS($for m, [[kind$m, name$m]]) $for m, [[kind$m name$m]]
+
+
+]]
+
+// Lists the template parameters.
+
+$for j [[
+$range m 0..j-1
+#define GMOCK_INTERNAL_LIST_HAS_$j[[]]
+_TEMPLATE_PARAMS($for m, [[kind$m, name$m]]) $for m, [[name$m]]
+
+
+]]
+
+// Declares the types of value parameters.
+
+$for i [[
+$range j 0..i-1
+#define GMOCK_INTERNAL_DECL_TYPE_AND_$i[[]]
+_VALUE_PARAMS($for j, [[p$j]]) $for j [[, typename p$j##_type]]
+
+
+]]
+
+// Initializes the value parameters.
+
+$for i [[
+$range j 0..i-1
+#define GMOCK_INTERNAL_INIT_AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]])\
+    ($for j, [[p$j##_type gmock_p$j]])$if i>0 [[ : ]]$for j, [[p$j(gmock_p$j)]]
+
+
+]]
+
+// Declares the fields for storing the value parameters.
+
+$for i [[
+$range j 0..i-1
+#define GMOCK_INTERNAL_DEFN_AND_$i[[]]
+_VALUE_PARAMS($for j, [[p$j]]) $for j [[p$j##_type p$j; ]]
+
+
+]]
+
+// Lists the value parameters.
+
+$for i [[
+$range j 0..i-1
+#define GMOCK_INTERNAL_LIST_AND_$i[[]]
+_VALUE_PARAMS($for j, [[p$j]]) $for j, [[p$j]]
+
+
+]]
+
+// Lists the value parameter types.
+
+$for i [[
+$range j 0..i-1
+#define GMOCK_INTERNAL_LIST_TYPE_AND_$i[[]]
+_VALUE_PARAMS($for j, [[p$j]]) $for j [[, p$j##_type]]
+
+
+]]
+
+// Declares the value parameters.
+
+$for i [[
+$range j 0..i-1
+#define GMOCK_INTERNAL_DECL_AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]]) [[]]
+$for j, [[p$j##_type p$j]]
+
+
+]]
+
+// The suffix of the class template implementing the action template.
+$for i [[
+
+
+$range j 0..i-1
+#define GMOCK_INTERNAL_COUNT_AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]]) [[]]
+$if i==1 [[P]] $elif i>=2 [[P$i]]
+]]
+
+
+// The name of the class template implementing the action template.
+#define GMOCK_ACTION_CLASS_(name, value_params)\
+    GTEST_CONCAT_TOKEN_(name##Action, GMOCK_INTERNAL_COUNT_##value_params)
+
+$range k 0..n-1
+
+#define ACTION_TEMPLATE(name, template_params, value_params)\
+  template <GMOCK_INTERNAL_DECL_##template_params\
+            GMOCK_INTERNAL_DECL_TYPE_##value_params>\
+  class GMOCK_ACTION_CLASS_(name, value_params) {\
+   public:\
+    explicit GMOCK_ACTION_CLASS_(name, value_params)\
+        GMOCK_INTERNAL_INIT_##value_params {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      explicit gmock_Impl GMOCK_INTERNAL_INIT_##value_params {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <$for k, [[typename arg$k[[]]_type]]>\
+      return_type gmock_PerformImpl(const args_type& args[[]]
+$for k [[, arg$k[[]]_type arg$k]]) const;\
+      GMOCK_INTERNAL_DEFN_##value_params\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(\
+          new gmock_Impl<F>(GMOCK_INTERNAL_LIST_##value_params));\
+    }\
+    GMOCK_INTERNAL_DEFN_##value_params\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(GMOCK_ACTION_CLASS_(name, value_params));\
+  };\
+  template <GMOCK_INTERNAL_DECL_##template_params\
+            GMOCK_INTERNAL_DECL_TYPE_##value_params>\
+  inline GMOCK_ACTION_CLASS_(name, value_params)<\
+      GMOCK_INTERNAL_LIST_##template_params\
+      GMOCK_INTERNAL_LIST_TYPE_##value_params> name(\
+          GMOCK_INTERNAL_DECL_##value_params) {\
+    return GMOCK_ACTION_CLASS_(name, value_params)<\
+        GMOCK_INTERNAL_LIST_##template_params\
+        GMOCK_INTERNAL_LIST_TYPE_##value_params>(\
+            GMOCK_INTERNAL_LIST_##value_params);\
+  }\
+  template <GMOCK_INTERNAL_DECL_##template_params\
+            GMOCK_INTERNAL_DECL_TYPE_##value_params>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      GMOCK_ACTION_CLASS_(name, value_params)<\
+          GMOCK_INTERNAL_LIST_##template_params\
+          GMOCK_INTERNAL_LIST_TYPE_##value_params>::gmock_Impl<F>::\
+              gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+$for i
+
+[[
+$var template = [[$if i==0 [[]] $else [[
+$range j 0..i-1
+
+  template <$for j, [[typename p$j##_type]]>\
+]]]]
+$var class_name = [[name##Action[[$if i==0 [[]] $elif i==1 [[P]]
+                                                $else [[P$i]]]]]]
+$range j 0..i-1
+$var ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]]
+$var param_types_and_names = [[$for j, [[p$j##_type p$j]]]]
+$var inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(gmock_p$j)]]]]]]
+$var param_field_decls = [[$for j
+[[
+
+      p$j##_type p$j;\
+]]]]
+$var param_field_decls2 = [[$for j
+[[
+
+    p$j##_type p$j;\
+]]]]
+$var params = [[$for j, [[p$j]]]]
+$var param_types = [[$if i==0 [[]] $else [[<$for j, [[p$j##_type]]>]]]]
+$var typename_arg_types = [[$for k, [[typename arg$k[[]]_type]]]]
+$var arg_types_and_names = [[$for k, [[arg$k[[]]_type arg$k]]]]
+$var macro_name = [[$if i==0 [[ACTION]] $elif i==1 [[ACTION_P]]
+                                        $else [[ACTION_P$i]]]]
+
+#define $macro_name(name$for j [[, p$j]])\$template
+  class $class_name {\
+   public:\
+    [[$if i==1 [[explicit ]]]]$class_name($ctor_param_list)$inits {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      [[$if i==1 [[explicit ]]]]gmock_Impl($ctor_param_list)$inits {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <$typename_arg_types>\
+      return_type gmock_PerformImpl(const args_type& args, [[]]
+$arg_types_and_names) const;\$param_field_decls
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>($params));\
+    }\$param_field_decls2
+   private:\
+    GTEST_DISALLOW_ASSIGN_($class_name);\
+  };\$template
+  inline $class_name$param_types name($param_types_and_names) {\
+    return $class_name$param_types($params);\
+  }\$template
+  template <typename F>\
+  template <$typename_arg_types>\
+  typename ::testing::internal::Function<F>::Result\
+      $class_name$param_types::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+]]
+$$ }  // This meta comment fixes auto-indentation in Emacs.  It won't
+$$    // show up in the generated code.
+
+
+namespace testing {
+
+
+// The ACTION*() macros trigger warning C4100 (unreferenced formal
+// parameter) in MSVC with -W4.  Unfortunately they cannot be fixed in
+// the macro definition, as the warnings are generated when the macro
+// is expanded and macro expansion cannot contain #pragma.  Therefore
+// we suppress them here.
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4100)
+#endif
+
+// Various overloads for InvokeArgument<N>().
+//
+// The InvokeArgument<N>(a1, a2, ..., a_k) action invokes the N-th
+// (0-based) argument, which must be a k-ary callable, of the mock
+// function, with arguments a1, a2, ..., a_k.
+//
+// Notes:
+//
+//   1. The arguments are passed by value by default.  If you need to
+//   pass an argument by reference, wrap it inside ByRef().  For
+//   example,
+//
+//     InvokeArgument<1>(5, string("Hello"), ByRef(foo))
+//
+//   passes 5 and string("Hello") by value, and passes foo by
+//   reference.
+//
+//   2. If the callable takes an argument by reference but ByRef() is
+//   not used, it will receive the reference to a copy of the value,
+//   instead of the original value.  For example, when the 0-th
+//   argument of the mock function takes a const string&, the action
+//
+//     InvokeArgument<0>(string("Hello"))
+//
+//   makes a copy of the temporary string("Hello") object and passes a
+//   reference of the copy, instead of the original temporary object,
+//   to the callable.  This makes it easy for a user to define an
+//   InvokeArgument action from temporary values and have it performed
+//   later.
+
+namespace internal {
+namespace invoke_argument {
+
+// Appears in InvokeArgumentAdl's argument list to help avoid
+// accidental calls to user functions of the same name.
+struct AdlTag {};
+
+// InvokeArgumentAdl - a helper for InvokeArgument.
+// The basic overloads are provided here for generic functors.
+// Overloads for other custom-callables are provided in the
+// internal/custom/callback-actions.h header.
+
+$range i 0..n
+$for i
+[[
+$range j 1..i
+
+template <typename R, typename F[[$for j [[, typename A$j]]]]>
+R InvokeArgumentAdl(AdlTag, F f[[$for j [[, A$j a$j]]]]) {
+  return f([[$for j, [[a$j]]]]);
+}
+]]
+
+}  // namespace invoke_argument
+}  // namespace internal
+
+$range i 0..n
+$for i [[
+$range j 0..i-1
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]])) {
+  using internal::invoke_argument::InvokeArgumentAdl;
+  return InvokeArgumentAdl<return_type>(
+      internal::invoke_argument::AdlTag(),
+      ::testing::get<k>(args)$for j [[, p$j]]);
+}
+
+]]
+
+// Various overloads for ReturnNew<T>().
+//
+// The ReturnNew<T>(a1, a2, ..., a_k) action returns a pointer to a new
+// instance of type T, constructed on the heap with constructor arguments
+// a1, a2, ..., and a_k. The caller assumes ownership of the returned value.
+$range i 0..n
+$for i [[
+$range j 0..i-1
+$var ps = [[$for j, [[p$j]]]]
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_$i[[]]_VALUE_PARAMS($ps)) {
+  return new T($ps);
+}
+
+]]
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+}  // namespace testing
+
+// Include any custom callback actions added by the local installation.
+// We must include this header at the end to make sure it can use the
+// declarations from this file.
+#include "gmock/internal/custom/gmock-generated-actions.h"
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
diff --git a/third_party/googletest/googlemock/include/gmock/gmock-generated-function-mockers.h b/third_party/googletest/googlemock/include/gmock/gmock-generated-function-mockers.h
new file mode 100644
index 0000000..4fa5ca9
--- /dev/null
+++ b/third_party/googletest/googlemock/include/gmock/gmock-generated-function-mockers.h
@@ -0,0 +1,1095 @@
+// This file was GENERATED by command:
+//     pump.py gmock-generated-function-mockers.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements function mockers of various arities.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
+
+#include "gmock/gmock-spec-builders.h"
+#include "gmock/internal/gmock-internal-utils.h"
+
+#if GTEST_HAS_STD_FUNCTION_
+# include <functional>
+#endif
+
+namespace testing {
+namespace internal {
+
+template <typename F>
+class FunctionMockerBase;
+
+// Note: class FunctionMocker really belongs to the ::testing
+// namespace.  However if we define it in ::testing, MSVC will
+// complain when classes in ::testing::internal declare it as a
+// friend class template.  To workaround this compiler bug, we define
+// FunctionMocker in ::testing::internal and import it into ::testing.
+template <typename F>
+class FunctionMocker;
+
+template <typename R>
+class FunctionMocker<R()> : public
+    internal::FunctionMockerBase<R()> {
+ public:
+  typedef R F();
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With() {
+    return this->current_spec();
+  }
+
+  R Invoke() {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple());
+  }
+};
+
+template <typename R, typename A1>
+class FunctionMocker<R(A1)> : public
+    internal::FunctionMockerBase<R(A1)> {
+ public:
+  typedef R F(A1);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1) {
+    this->current_spec().SetMatchers(::testing::make_tuple(m1));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1));
+  }
+};
+
+template <typename R, typename A1, typename A2>
+class FunctionMocker<R(A1, A2)> : public
+    internal::FunctionMockerBase<R(A1, A2)> {
+ public:
+  typedef R F(A1, A2);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2) {
+    this->current_spec().SetMatchers(::testing::make_tuple(m1, m2));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1, A2 a2) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1, a2));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3>
+class FunctionMocker<R(A1, A2, A3)> : public
+    internal::FunctionMockerBase<R(A1, A2, A3)> {
+ public:
+  typedef R F(A1, A2, A3);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
+      const Matcher<A3>& m3) {
+    this->current_spec().SetMatchers(::testing::make_tuple(m1, m2, m3));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1, A2 a2, A3 a3) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1, a2, a3));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4>
+class FunctionMocker<R(A1, A2, A3, A4)> : public
+    internal::FunctionMockerBase<R(A1, A2, A3, A4)> {
+ public:
+  typedef R F(A1, A2, A3, A4);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
+      const Matcher<A3>& m3, const Matcher<A4>& m4) {
+    this->current_spec().SetMatchers(::testing::make_tuple(m1, m2, m3, m4));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1, A2 a2, A3 a3, A4 a4) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5>
+class FunctionMocker<R(A1, A2, A3, A4, A5)> : public
+    internal::FunctionMockerBase<R(A1, A2, A3, A4, A5)> {
+ public:
+  typedef R F(A1, A2, A3, A4, A5);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
+      const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5) {
+    this->current_spec().SetMatchers(::testing::make_tuple(m1, m2, m3, m4, m5));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6>
+class FunctionMocker<R(A1, A2, A3, A4, A5, A6)> : public
+    internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6)> {
+ public:
+  typedef R F(A1, A2, A3, A4, A5, A6);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
+      const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
+      const Matcher<A6>& m6) {
+    this->current_spec().SetMatchers(::testing::make_tuple(m1, m2, m3, m4, m5,
+        m6));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5, a6));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7>
+class FunctionMocker<R(A1, A2, A3, A4, A5, A6, A7)> : public
+    internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6, A7)> {
+ public:
+  typedef R F(A1, A2, A3, A4, A5, A6, A7);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
+      const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
+      const Matcher<A6>& m6, const Matcher<A7>& m7) {
+    this->current_spec().SetMatchers(::testing::make_tuple(m1, m2, m3, m4, m5,
+        m6, m7));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5, a6, a7));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7, typename A8>
+class FunctionMocker<R(A1, A2, A3, A4, A5, A6, A7, A8)> : public
+    internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6, A7, A8)> {
+ public:
+  typedef R F(A1, A2, A3, A4, A5, A6, A7, A8);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
+      const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
+      const Matcher<A6>& m6, const Matcher<A7>& m7, const Matcher<A8>& m8) {
+    this->current_spec().SetMatchers(::testing::make_tuple(m1, m2, m3, m4, m5,
+        m6, m7, m8));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5, a6, a7, a8));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7, typename A8, typename A9>
+class FunctionMocker<R(A1, A2, A3, A4, A5, A6, A7, A8, A9)> : public
+    internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6, A7, A8, A9)> {
+ public:
+  typedef R F(A1, A2, A3, A4, A5, A6, A7, A8, A9);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
+      const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
+      const Matcher<A6>& m6, const Matcher<A7>& m7, const Matcher<A8>& m8,
+      const Matcher<A9>& m9) {
+    this->current_spec().SetMatchers(::testing::make_tuple(m1, m2, m3, m4, m5,
+        m6, m7, m8, m9));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5, a6, a7, a8, a9));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7, typename A8, typename A9,
+    typename A10>
+class FunctionMocker<R(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)> : public
+    internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)> {
+ public:
+  typedef R F(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
+      const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
+      const Matcher<A6>& m6, const Matcher<A7>& m7, const Matcher<A8>& m8,
+      const Matcher<A9>& m9, const Matcher<A10>& m10) {
+    this->current_spec().SetMatchers(::testing::make_tuple(m1, m2, m3, m4, m5,
+        m6, m7, m8, m9, m10));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9,
+      A10 a10) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5, a6, a7, a8, a9,
+        a10));
+  }
+};
+
+}  // namespace internal
+
+// The style guide prohibits "using" statements in a namespace scope
+// inside a header file.  However, the FunctionMocker class template
+// is meant to be defined in the ::testing namespace.  The following
+// line is just a trick for working around a bug in MSVC 8.0, which
+// cannot handle it if we define FunctionMocker in ::testing.
+using internal::FunctionMocker;
+
+// GMOCK_RESULT_(tn, F) expands to the result type of function type F.
+// We define this as a variadic macro in case F contains unprotected
+// commas (the same reason that we use variadic macros in other places
+// in this file).
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_RESULT_(tn, ...) \
+    tn ::testing::internal::Function<__VA_ARGS__>::Result
+
+// The type of argument N of the given function type.
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_ARG_(tn, N, ...) \
+    tn ::testing::internal::Function<__VA_ARGS__>::Argument##N
+
+// The matcher type for argument N of the given function type.
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_MATCHER_(tn, N, ...) \
+    const ::testing::Matcher<GMOCK_ARG_(tn, N, __VA_ARGS__)>&
+
+// The variable for mocking the given method.
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_MOCKER_(arity, constness, Method) \
+    GTEST_CONCAT_TOKEN_(gmock##constness##arity##_##Method##_, __LINE__)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD0_(tn, constness, ct, Method, ...) \
+  GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
+      ) constness { \
+    GTEST_COMPILE_ASSERT_((::testing::tuple_size<                          \
+        tn ::testing::internal::Function<__VA_ARGS__>::ArgumentTuple>::value \
+            == 0), \
+        this_method_does_not_take_0_arguments); \
+    GMOCK_MOCKER_(0, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(0, constness, Method).Invoke(); \
+  } \
+  ::testing::MockSpec<__VA_ARGS__>& \
+      gmock_##Method() constness { \
+    GMOCK_MOCKER_(0, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(0, constness, Method).With(); \
+  } \
+  mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(0, constness, \
+      Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD1_(tn, constness, ct, Method, ...) \
+  GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
+      GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1) constness { \
+    GTEST_COMPILE_ASSERT_((::testing::tuple_size<                          \
+        tn ::testing::internal::Function<__VA_ARGS__>::ArgumentTuple>::value \
+            == 1), \
+        this_method_does_not_take_1_argument); \
+    GMOCK_MOCKER_(1, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(1, constness, Method).Invoke(gmock_a1); \
+  } \
+  ::testing::MockSpec<__VA_ARGS__>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1) constness { \
+    GMOCK_MOCKER_(1, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(1, constness, Method).With(gmock_a1); \
+  } \
+  mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(1, constness, \
+      Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD2_(tn, constness, ct, Method, ...) \
+  GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
+      GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \
+      GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2) constness { \
+    GTEST_COMPILE_ASSERT_((::testing::tuple_size<                          \
+        tn ::testing::internal::Function<__VA_ARGS__>::ArgumentTuple>::value \
+            == 2), \
+        this_method_does_not_take_2_arguments); \
+    GMOCK_MOCKER_(2, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(2, constness, Method).Invoke(gmock_a1, gmock_a2); \
+  } \
+  ::testing::MockSpec<__VA_ARGS__>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
+                     GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2) constness { \
+    GMOCK_MOCKER_(2, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(2, constness, Method).With(gmock_a1, gmock_a2); \
+  } \
+  mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(2, constness, \
+      Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD3_(tn, constness, ct, Method, ...) \
+  GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
+      GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \
+      GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2, \
+      GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3) constness { \
+    GTEST_COMPILE_ASSERT_((::testing::tuple_size<                          \
+        tn ::testing::internal::Function<__VA_ARGS__>::ArgumentTuple>::value \
+            == 3), \
+        this_method_does_not_take_3_arguments); \
+    GMOCK_MOCKER_(3, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(3, constness, Method).Invoke(gmock_a1, gmock_a2, \
+        gmock_a3); \
+  } \
+  ::testing::MockSpec<__VA_ARGS__>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
+                     GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
+                     GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3) constness { \
+    GMOCK_MOCKER_(3, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(3, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3); \
+  } \
+  mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(3, constness, \
+      Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD4_(tn, constness, ct, Method, ...) \
+  GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
+      GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \
+      GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2, \
+      GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
+      GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4) constness { \
+    GTEST_COMPILE_ASSERT_((::testing::tuple_size<                          \
+        tn ::testing::internal::Function<__VA_ARGS__>::ArgumentTuple>::value \
+            == 4), \
+        this_method_does_not_take_4_arguments); \
+    GMOCK_MOCKER_(4, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(4, constness, Method).Invoke(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4); \
+  } \
+  ::testing::MockSpec<__VA_ARGS__>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
+                     GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
+                     GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
+                     GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4) constness { \
+    GMOCK_MOCKER_(4, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(4, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4); \
+  } \
+  mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(4, constness, \
+      Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD5_(tn, constness, ct, Method, ...) \
+  GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
+      GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \
+      GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2, \
+      GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
+      GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, \
+      GMOCK_ARG_(tn, 5, __VA_ARGS__) gmock_a5) constness { \
+    GTEST_COMPILE_ASSERT_((::testing::tuple_size<                          \
+        tn ::testing::internal::Function<__VA_ARGS__>::ArgumentTuple>::value \
+            == 5), \
+        this_method_does_not_take_5_arguments); \
+    GMOCK_MOCKER_(5, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(5, constness, Method).Invoke(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5); \
+  } \
+  ::testing::MockSpec<__VA_ARGS__>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
+                     GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
+                     GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
+                     GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
+                     GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5) constness { \
+    GMOCK_MOCKER_(5, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(5, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5); \
+  } \
+  mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(5, constness, \
+      Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD6_(tn, constness, ct, Method, ...) \
+  GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
+      GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \
+      GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2, \
+      GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
+      GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, \
+      GMOCK_ARG_(tn, 5, __VA_ARGS__) gmock_a5, \
+      GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6) constness { \
+    GTEST_COMPILE_ASSERT_((::testing::tuple_size<                          \
+        tn ::testing::internal::Function<__VA_ARGS__>::ArgumentTuple>::value \
+            == 6), \
+        this_method_does_not_take_6_arguments); \
+    GMOCK_MOCKER_(6, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(6, constness, Method).Invoke(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6); \
+  } \
+  ::testing::MockSpec<__VA_ARGS__>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
+                     GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
+                     GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
+                     GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
+                     GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \
+                     GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6) constness { \
+    GMOCK_MOCKER_(6, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(6, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6); \
+  } \
+  mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(6, constness, \
+      Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD7_(tn, constness, ct, Method, ...) \
+  GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
+      GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \
+      GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2, \
+      GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
+      GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, \
+      GMOCK_ARG_(tn, 5, __VA_ARGS__) gmock_a5, \
+      GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \
+      GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7) constness { \
+    GTEST_COMPILE_ASSERT_((::testing::tuple_size<                          \
+        tn ::testing::internal::Function<__VA_ARGS__>::ArgumentTuple>::value \
+            == 7), \
+        this_method_does_not_take_7_arguments); \
+    GMOCK_MOCKER_(7, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(7, constness, Method).Invoke(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7); \
+  } \
+  ::testing::MockSpec<__VA_ARGS__>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
+                     GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
+                     GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
+                     GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
+                     GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \
+                     GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \
+                     GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7) constness { \
+    GMOCK_MOCKER_(7, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(7, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7); \
+  } \
+  mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(7, constness, \
+      Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD8_(tn, constness, ct, Method, ...) \
+  GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
+      GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \
+      GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2, \
+      GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
+      GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, \
+      GMOCK_ARG_(tn, 5, __VA_ARGS__) gmock_a5, \
+      GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \
+      GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7, \
+      GMOCK_ARG_(tn, 8, __VA_ARGS__) gmock_a8) constness { \
+    GTEST_COMPILE_ASSERT_((::testing::tuple_size<                          \
+        tn ::testing::internal::Function<__VA_ARGS__>::ArgumentTuple>::value \
+            == 8), \
+        this_method_does_not_take_8_arguments); \
+    GMOCK_MOCKER_(8, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(8, constness, Method).Invoke(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8); \
+  } \
+  ::testing::MockSpec<__VA_ARGS__>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
+                     GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
+                     GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
+                     GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
+                     GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \
+                     GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \
+                     GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7, \
+                     GMOCK_MATCHER_(tn, 8, __VA_ARGS__) gmock_a8) constness { \
+    GMOCK_MOCKER_(8, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(8, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8); \
+  } \
+  mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(8, constness, \
+      Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD9_(tn, constness, ct, Method, ...) \
+  GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
+      GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \
+      GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2, \
+      GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
+      GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, \
+      GMOCK_ARG_(tn, 5, __VA_ARGS__) gmock_a5, \
+      GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \
+      GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7, \
+      GMOCK_ARG_(tn, 8, __VA_ARGS__) gmock_a8, \
+      GMOCK_ARG_(tn, 9, __VA_ARGS__) gmock_a9) constness { \
+    GTEST_COMPILE_ASSERT_((::testing::tuple_size<                          \
+        tn ::testing::internal::Function<__VA_ARGS__>::ArgumentTuple>::value \
+            == 9), \
+        this_method_does_not_take_9_arguments); \
+    GMOCK_MOCKER_(9, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(9, constness, Method).Invoke(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, \
+        gmock_a9); \
+  } \
+  ::testing::MockSpec<__VA_ARGS__>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
+                     GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
+                     GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
+                     GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
+                     GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \
+                     GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \
+                     GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7, \
+                     GMOCK_MATCHER_(tn, 8, __VA_ARGS__) gmock_a8, \
+                     GMOCK_MATCHER_(tn, 9, __VA_ARGS__) gmock_a9) constness { \
+    GMOCK_MOCKER_(9, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(9, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, \
+        gmock_a9); \
+  } \
+  mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(9, constness, \
+      Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD10_(tn, constness, ct, Method, ...) \
+  GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
+      GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \
+      GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2, \
+      GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
+      GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, \
+      GMOCK_ARG_(tn, 5, __VA_ARGS__) gmock_a5, \
+      GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \
+      GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7, \
+      GMOCK_ARG_(tn, 8, __VA_ARGS__) gmock_a8, \
+      GMOCK_ARG_(tn, 9, __VA_ARGS__) gmock_a9, \
+      GMOCK_ARG_(tn, 10, __VA_ARGS__) gmock_a10) constness { \
+    GTEST_COMPILE_ASSERT_((::testing::tuple_size<                          \
+        tn ::testing::internal::Function<__VA_ARGS__>::ArgumentTuple>::value \
+            == 10), \
+        this_method_does_not_take_10_arguments); \
+    GMOCK_MOCKER_(10, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(10, constness, Method).Invoke(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, gmock_a9, \
+        gmock_a10); \
+  } \
+  ::testing::MockSpec<__VA_ARGS__>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
+                     GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
+                     GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
+                     GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
+                     GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \
+                     GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \
+                     GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7, \
+                     GMOCK_MATCHER_(tn, 8, __VA_ARGS__) gmock_a8, \
+                     GMOCK_MATCHER_(tn, 9, __VA_ARGS__) gmock_a9, \
+                     GMOCK_MATCHER_(tn, 10, \
+                         __VA_ARGS__) gmock_a10) constness { \
+    GMOCK_MOCKER_(10, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(10, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, gmock_a9, \
+        gmock_a10); \
+  } \
+  mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(10, constness, \
+      Method)
+
+#define MOCK_METHOD0(m, ...) GMOCK_METHOD0_(, , , m, __VA_ARGS__)
+#define MOCK_METHOD1(m, ...) GMOCK_METHOD1_(, , , m, __VA_ARGS__)
+#define MOCK_METHOD2(m, ...) GMOCK_METHOD2_(, , , m, __VA_ARGS__)
+#define MOCK_METHOD3(m, ...) GMOCK_METHOD3_(, , , m, __VA_ARGS__)
+#define MOCK_METHOD4(m, ...) GMOCK_METHOD4_(, , , m, __VA_ARGS__)
+#define MOCK_METHOD5(m, ...) GMOCK_METHOD5_(, , , m, __VA_ARGS__)
+#define MOCK_METHOD6(m, ...) GMOCK_METHOD6_(, , , m, __VA_ARGS__)
+#define MOCK_METHOD7(m, ...) GMOCK_METHOD7_(, , , m, __VA_ARGS__)
+#define MOCK_METHOD8(m, ...) GMOCK_METHOD8_(, , , m, __VA_ARGS__)
+#define MOCK_METHOD9(m, ...) GMOCK_METHOD9_(, , , m, __VA_ARGS__)
+#define MOCK_METHOD10(m, ...) GMOCK_METHOD10_(, , , m, __VA_ARGS__)
+
+#define MOCK_CONST_METHOD0(m, ...) GMOCK_METHOD0_(, const, , m, __VA_ARGS__)
+#define MOCK_CONST_METHOD1(m, ...) GMOCK_METHOD1_(, const, , m, __VA_ARGS__)
+#define MOCK_CONST_METHOD2(m, ...) GMOCK_METHOD2_(, const, , m, __VA_ARGS__)
+#define MOCK_CONST_METHOD3(m, ...) GMOCK_METHOD3_(, const, , m, __VA_ARGS__)
+#define MOCK_CONST_METHOD4(m, ...) GMOCK_METHOD4_(, const, , m, __VA_ARGS__)
+#define MOCK_CONST_METHOD5(m, ...) GMOCK_METHOD5_(, const, , m, __VA_ARGS__)
+#define MOCK_CONST_METHOD6(m, ...) GMOCK_METHOD6_(, const, , m, __VA_ARGS__)
+#define MOCK_CONST_METHOD7(m, ...) GMOCK_METHOD7_(, const, , m, __VA_ARGS__)
+#define MOCK_CONST_METHOD8(m, ...) GMOCK_METHOD8_(, const, , m, __VA_ARGS__)
+#define MOCK_CONST_METHOD9(m, ...) GMOCK_METHOD9_(, const, , m, __VA_ARGS__)
+#define MOCK_CONST_METHOD10(m, ...) GMOCK_METHOD10_(, const, , m, __VA_ARGS__)
+
+#define MOCK_METHOD0_T(m, ...) GMOCK_METHOD0_(typename, , , m, __VA_ARGS__)
+#define MOCK_METHOD1_T(m, ...) GMOCK_METHOD1_(typename, , , m, __VA_ARGS__)
+#define MOCK_METHOD2_T(m, ...) GMOCK_METHOD2_(typename, , , m, __VA_ARGS__)
+#define MOCK_METHOD3_T(m, ...) GMOCK_METHOD3_(typename, , , m, __VA_ARGS__)
+#define MOCK_METHOD4_T(m, ...) GMOCK_METHOD4_(typename, , , m, __VA_ARGS__)
+#define MOCK_METHOD5_T(m, ...) GMOCK_METHOD5_(typename, , , m, __VA_ARGS__)
+#define MOCK_METHOD6_T(m, ...) GMOCK_METHOD6_(typename, , , m, __VA_ARGS__)
+#define MOCK_METHOD7_T(m, ...) GMOCK_METHOD7_(typename, , , m, __VA_ARGS__)
+#define MOCK_METHOD8_T(m, ...) GMOCK_METHOD8_(typename, , , m, __VA_ARGS__)
+#define MOCK_METHOD9_T(m, ...) GMOCK_METHOD9_(typename, , , m, __VA_ARGS__)
+#define MOCK_METHOD10_T(m, ...) GMOCK_METHOD10_(typename, , , m, __VA_ARGS__)
+
+#define MOCK_CONST_METHOD0_T(m, ...) \
+    GMOCK_METHOD0_(typename, const, , m, __VA_ARGS__)
+#define MOCK_CONST_METHOD1_T(m, ...) \
+    GMOCK_METHOD1_(typename, const, , m, __VA_ARGS__)
+#define MOCK_CONST_METHOD2_T(m, ...) \
+    GMOCK_METHOD2_(typename, const, , m, __VA_ARGS__)
+#define MOCK_CONST_METHOD3_T(m, ...) \
+    GMOCK_METHOD3_(typename, const, , m, __VA_ARGS__)
+#define MOCK_CONST_METHOD4_T(m, ...) \
+    GMOCK_METHOD4_(typename, const, , m, __VA_ARGS__)
+#define MOCK_CONST_METHOD5_T(m, ...) \
+    GMOCK_METHOD5_(typename, const, , m, __VA_ARGS__)
+#define MOCK_CONST_METHOD6_T(m, ...) \
+    GMOCK_METHOD6_(typename, const, , m, __VA_ARGS__)
+#define MOCK_CONST_METHOD7_T(m, ...) \
+    GMOCK_METHOD7_(typename, const, , m, __VA_ARGS__)
+#define MOCK_CONST_METHOD8_T(m, ...) \
+    GMOCK_METHOD8_(typename, const, , m, __VA_ARGS__)
+#define MOCK_CONST_METHOD9_T(m, ...) \
+    GMOCK_METHOD9_(typename, const, , m, __VA_ARGS__)
+#define MOCK_CONST_METHOD10_T(m, ...) \
+    GMOCK_METHOD10_(typename, const, , m, __VA_ARGS__)
+
+#define MOCK_METHOD0_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD0_(, , ct, m, __VA_ARGS__)
+#define MOCK_METHOD1_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD1_(, , ct, m, __VA_ARGS__)
+#define MOCK_METHOD2_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD2_(, , ct, m, __VA_ARGS__)
+#define MOCK_METHOD3_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD3_(, , ct, m, __VA_ARGS__)
+#define MOCK_METHOD4_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD4_(, , ct, m, __VA_ARGS__)
+#define MOCK_METHOD5_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD5_(, , ct, m, __VA_ARGS__)
+#define MOCK_METHOD6_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD6_(, , ct, m, __VA_ARGS__)
+#define MOCK_METHOD7_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD7_(, , ct, m, __VA_ARGS__)
+#define MOCK_METHOD8_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD8_(, , ct, m, __VA_ARGS__)
+#define MOCK_METHOD9_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD9_(, , ct, m, __VA_ARGS__)
+#define MOCK_METHOD10_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD10_(, , ct, m, __VA_ARGS__)
+
+#define MOCK_CONST_METHOD0_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD0_(, const, ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD1_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD1_(, const, ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD2_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD2_(, const, ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD3_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD3_(, const, ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD4_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD4_(, const, ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD5_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD5_(, const, ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD6_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD6_(, const, ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD7_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD7_(, const, ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD8_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD8_(, const, ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD9_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD9_(, const, ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD10_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD10_(, const, ct, m, __VA_ARGS__)
+
+#define MOCK_METHOD0_T_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD0_(typename, , ct, m, __VA_ARGS__)
+#define MOCK_METHOD1_T_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD1_(typename, , ct, m, __VA_ARGS__)
+#define MOCK_METHOD2_T_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD2_(typename, , ct, m, __VA_ARGS__)
+#define MOCK_METHOD3_T_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD3_(typename, , ct, m, __VA_ARGS__)
+#define MOCK_METHOD4_T_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD4_(typename, , ct, m, __VA_ARGS__)
+#define MOCK_METHOD5_T_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD5_(typename, , ct, m, __VA_ARGS__)
+#define MOCK_METHOD6_T_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD6_(typename, , ct, m, __VA_ARGS__)
+#define MOCK_METHOD7_T_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD7_(typename, , ct, m, __VA_ARGS__)
+#define MOCK_METHOD8_T_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD8_(typename, , ct, m, __VA_ARGS__)
+#define MOCK_METHOD9_T_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD9_(typename, , ct, m, __VA_ARGS__)
+#define MOCK_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD10_(typename, , ct, m, __VA_ARGS__)
+
+#define MOCK_CONST_METHOD0_T_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD0_(typename, const, ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD1_T_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD1_(typename, const, ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD2_T_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD2_(typename, const, ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD3_T_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD3_(typename, const, ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD4_T_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD4_(typename, const, ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD5_T_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD5_(typename, const, ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD6_T_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD6_(typename, const, ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD7_T_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD7_(typename, const, ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD8_T_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD8_(typename, const, ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD9_T_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD9_(typename, const, ct, m, __VA_ARGS__)
+#define MOCK_CONST_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD10_(typename, const, ct, m, __VA_ARGS__)
+
+// A MockFunction<F> class has one mock method whose type is F.  It is
+// useful when you just want your test code to emit some messages and
+// have Google Mock verify the right messages are sent (and perhaps at
+// the right times).  For example, if you are exercising code:
+//
+//   Foo(1);
+//   Foo(2);
+//   Foo(3);
+//
+// and want to verify that Foo(1) and Foo(3) both invoke
+// mock.Bar("a"), but Foo(2) doesn't invoke anything, you can write:
+//
+// TEST(FooTest, InvokesBarCorrectly) {
+//   MyMock mock;
+//   MockFunction<void(string check_point_name)> check;
+//   {
+//     InSequence s;
+//
+//     EXPECT_CALL(mock, Bar("a"));
+//     EXPECT_CALL(check, Call("1"));
+//     EXPECT_CALL(check, Call("2"));
+//     EXPECT_CALL(mock, Bar("a"));
+//   }
+//   Foo(1);
+//   check.Call("1");
+//   Foo(2);
+//   check.Call("2");
+//   Foo(3);
+// }
+//
+// The expectation spec says that the first Bar("a") must happen
+// before check point "1", the second Bar("a") must happen after check
+// point "2", and nothing should happen between the two check
+// points. The explicit check points make it easy to tell which
+// Bar("a") is called by which call to Foo().
+//
+// MockFunction<F> can also be used to exercise code that accepts
+// std::function<F> callbacks. To do so, use AsStdFunction() method
+// to create std::function proxy forwarding to original object's Call.
+// Example:
+//
+// TEST(FooTest, RunsCallbackWithBarArgument) {
+//   MockFunction<int(string)> callback;
+//   EXPECT_CALL(callback, Call("bar")).WillOnce(Return(1));
+//   Foo(callback.AsStdFunction());
+// }
+template <typename F>
+class MockFunction;
+
+template <typename R>
+class MockFunction<R()> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD0_T(Call, R());
+
+#if GTEST_HAS_STD_FUNCTION_
+  std::function<R()> AsStdFunction() {
+    return [this]() -> R {
+      return this->Call();
+    };
+  }
+#endif  // GTEST_HAS_STD_FUNCTION_
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0>
+class MockFunction<R(A0)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD1_T(Call, R(A0));
+
+#if GTEST_HAS_STD_FUNCTION_
+  std::function<R(A0)> AsStdFunction() {
+    return [this](A0 a0) -> R {
+      return this->Call(a0);
+    };
+  }
+#endif  // GTEST_HAS_STD_FUNCTION_
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0, typename A1>
+class MockFunction<R(A0, A1)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD2_T(Call, R(A0, A1));
+
+#if GTEST_HAS_STD_FUNCTION_
+  std::function<R(A0, A1)> AsStdFunction() {
+    return [this](A0 a0, A1 a1) -> R {
+      return this->Call(a0, a1);
+    };
+  }
+#endif  // GTEST_HAS_STD_FUNCTION_
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0, typename A1, typename A2>
+class MockFunction<R(A0, A1, A2)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD3_T(Call, R(A0, A1, A2));
+
+#if GTEST_HAS_STD_FUNCTION_
+  std::function<R(A0, A1, A2)> AsStdFunction() {
+    return [this](A0 a0, A1 a1, A2 a2) -> R {
+      return this->Call(a0, a1, a2);
+    };
+  }
+#endif  // GTEST_HAS_STD_FUNCTION_
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0, typename A1, typename A2, typename A3>
+class MockFunction<R(A0, A1, A2, A3)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD4_T(Call, R(A0, A1, A2, A3));
+
+#if GTEST_HAS_STD_FUNCTION_
+  std::function<R(A0, A1, A2, A3)> AsStdFunction() {
+    return [this](A0 a0, A1 a1, A2 a2, A3 a3) -> R {
+      return this->Call(a0, a1, a2, a3);
+    };
+  }
+#endif  // GTEST_HAS_STD_FUNCTION_
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0, typename A1, typename A2, typename A3,
+    typename A4>
+class MockFunction<R(A0, A1, A2, A3, A4)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD5_T(Call, R(A0, A1, A2, A3, A4));
+
+#if GTEST_HAS_STD_FUNCTION_
+  std::function<R(A0, A1, A2, A3, A4)> AsStdFunction() {
+    return [this](A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) -> R {
+      return this->Call(a0, a1, a2, a3, a4);
+    };
+  }
+#endif  // GTEST_HAS_STD_FUNCTION_
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0, typename A1, typename A2, typename A3,
+    typename A4, typename A5>
+class MockFunction<R(A0, A1, A2, A3, A4, A5)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD6_T(Call, R(A0, A1, A2, A3, A4, A5));
+
+#if GTEST_HAS_STD_FUNCTION_
+  std::function<R(A0, A1, A2, A3, A4, A5)> AsStdFunction() {
+    return [this](A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) -> R {
+      return this->Call(a0, a1, a2, a3, a4, a5);
+    };
+  }
+#endif  // GTEST_HAS_STD_FUNCTION_
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0, typename A1, typename A2, typename A3,
+    typename A4, typename A5, typename A6>
+class MockFunction<R(A0, A1, A2, A3, A4, A5, A6)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD7_T(Call, R(A0, A1, A2, A3, A4, A5, A6));
+
+#if GTEST_HAS_STD_FUNCTION_
+  std::function<R(A0, A1, A2, A3, A4, A5, A6)> AsStdFunction() {
+    return [this](A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) -> R {
+      return this->Call(a0, a1, a2, a3, a4, a5, a6);
+    };
+  }
+#endif  // GTEST_HAS_STD_FUNCTION_
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0, typename A1, typename A2, typename A3,
+    typename A4, typename A5, typename A6, typename A7>
+class MockFunction<R(A0, A1, A2, A3, A4, A5, A6, A7)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD8_T(Call, R(A0, A1, A2, A3, A4, A5, A6, A7));
+
+#if GTEST_HAS_STD_FUNCTION_
+  std::function<R(A0, A1, A2, A3, A4, A5, A6, A7)> AsStdFunction() {
+    return [this](A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) -> R {
+      return this->Call(a0, a1, a2, a3, a4, a5, a6, a7);
+    };
+  }
+#endif  // GTEST_HAS_STD_FUNCTION_
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0, typename A1, typename A2, typename A3,
+    typename A4, typename A5, typename A6, typename A7, typename A8>
+class MockFunction<R(A0, A1, A2, A3, A4, A5, A6, A7, A8)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD9_T(Call, R(A0, A1, A2, A3, A4, A5, A6, A7, A8));
+
+#if GTEST_HAS_STD_FUNCTION_
+  std::function<R(A0, A1, A2, A3, A4, A5, A6, A7, A8)> AsStdFunction() {
+    return [this](A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7,
+        A8 a8) -> R {
+      return this->Call(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+    };
+  }
+#endif  // GTEST_HAS_STD_FUNCTION_
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0, typename A1, typename A2, typename A3,
+    typename A4, typename A5, typename A6, typename A7, typename A8,
+    typename A9>
+class MockFunction<R(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD10_T(Call, R(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9));
+
+#if GTEST_HAS_STD_FUNCTION_
+  std::function<R(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)> AsStdFunction() {
+    return [this](A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7,
+        A8 a8, A9 a9) -> R {
+      return this->Call(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+    };
+  }
+#endif  // GTEST_HAS_STD_FUNCTION_
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
diff --git a/third_party/googletest/googlemock/include/gmock/gmock-generated-function-mockers.h.pump b/third_party/googletest/googlemock/include/gmock/gmock-generated-function-mockers.h.pump
new file mode 100644
index 0000000..811502d
--- /dev/null
+++ b/third_party/googletest/googlemock/include/gmock/gmock-generated-function-mockers.h.pump
@@ -0,0 +1,291 @@
+$$ -*- mode: c++; -*-
+$$ This is a Pump source file.  Please use Pump to convert it to
+$$ gmock-generated-function-mockers.h.
+$$
+$var n = 10  $$ The maximum arity we support.
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements function mockers of various arities.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
+
+#include "gmock/gmock-spec-builders.h"
+#include "gmock/internal/gmock-internal-utils.h"
+
+#if GTEST_HAS_STD_FUNCTION_
+# include <functional>
+#endif
+
+namespace testing {
+namespace internal {
+
+template <typename F>
+class FunctionMockerBase;
+
+// Note: class FunctionMocker really belongs to the ::testing
+// namespace.  However if we define it in ::testing, MSVC will
+// complain when classes in ::testing::internal declare it as a
+// friend class template.  To workaround this compiler bug, we define
+// FunctionMocker in ::testing::internal and import it into ::testing.
+template <typename F>
+class FunctionMocker;
+
+
+$range i 0..n
+$for i [[
+$range j 1..i
+$var typename_As = [[$for j [[, typename A$j]]]]
+$var As = [[$for j, [[A$j]]]]
+$var as = [[$for j, [[a$j]]]]
+$var Aas = [[$for j, [[A$j a$j]]]]
+$var ms = [[$for j, [[m$j]]]]
+$var matchers = [[$for j, [[const Matcher<A$j>& m$j]]]]
+template <typename R$typename_As>
+class FunctionMocker<R($As)> : public
+    internal::FunctionMockerBase<R($As)> {
+ public:
+  typedef R F($As);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With($matchers) {
+
+$if i >= 1 [[
+    this->current_spec().SetMatchers(::testing::make_tuple($ms));
+
+]]
+    return this->current_spec();
+  }
+
+  R Invoke($Aas) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple($as));
+  }
+};
+
+
+]]
+}  // namespace internal
+
+// The style guide prohibits "using" statements in a namespace scope
+// inside a header file.  However, the FunctionMocker class template
+// is meant to be defined in the ::testing namespace.  The following
+// line is just a trick for working around a bug in MSVC 8.0, which
+// cannot handle it if we define FunctionMocker in ::testing.
+using internal::FunctionMocker;
+
+// GMOCK_RESULT_(tn, F) expands to the result type of function type F.
+// We define this as a variadic macro in case F contains unprotected
+// commas (the same reason that we use variadic macros in other places
+// in this file).
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_RESULT_(tn, ...) \
+    tn ::testing::internal::Function<__VA_ARGS__>::Result
+
+// The type of argument N of the given function type.
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_ARG_(tn, N, ...) \
+    tn ::testing::internal::Function<__VA_ARGS__>::Argument##N
+
+// The matcher type for argument N of the given function type.
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_MATCHER_(tn, N, ...) \
+    const ::testing::Matcher<GMOCK_ARG_(tn, N, __VA_ARGS__)>&
+
+// The variable for mocking the given method.
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_MOCKER_(arity, constness, Method) \
+    GTEST_CONCAT_TOKEN_(gmock##constness##arity##_##Method##_, __LINE__)
+
+
+$for i [[
+$range j 1..i
+$var arg_as = [[$for j, \
+      [[GMOCK_ARG_(tn, $j, __VA_ARGS__) gmock_a$j]]]]
+$var as = [[$for j, [[gmock_a$j]]]]
+$var matcher_as = [[$for j, \
+                     [[GMOCK_MATCHER_(tn, $j, __VA_ARGS__) gmock_a$j]]]]
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD$i[[]]_(tn, constness, ct, Method, ...) \
+  GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
+      $arg_as) constness { \
+    GTEST_COMPILE_ASSERT_((::testing::tuple_size<                          \
+        tn ::testing::internal::Function<__VA_ARGS__>::ArgumentTuple>::value == $i), \
+        this_method_does_not_take_$i[[]]_argument[[$if i != 1 [[s]]]]); \
+    GMOCK_MOCKER_($i, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_($i, constness, Method).Invoke($as); \
+  } \
+  ::testing::MockSpec<__VA_ARGS__>& \
+      gmock_##Method($matcher_as) constness { \
+    GMOCK_MOCKER_($i, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_($i, constness, Method).With($as); \
+  } \
+  mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_($i, constness, Method)
+
+
+]]
+$for i [[
+#define MOCK_METHOD$i(m, ...) GMOCK_METHOD$i[[]]_(, , , m, __VA_ARGS__)
+
+]]
+
+
+$for i [[
+#define MOCK_CONST_METHOD$i(m, ...) GMOCK_METHOD$i[[]]_(, const, , m, __VA_ARGS__)
+
+]]
+
+
+$for i [[
+#define MOCK_METHOD$i[[]]_T(m, ...) GMOCK_METHOD$i[[]]_(typename, , , m, __VA_ARGS__)
+
+]]
+
+
+$for i [[
+#define MOCK_CONST_METHOD$i[[]]_T(m, ...) \
+    GMOCK_METHOD$i[[]]_(typename, const, , m, __VA_ARGS__)
+
+]]
+
+
+$for i [[
+#define MOCK_METHOD$i[[]]_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD$i[[]]_(, , ct, m, __VA_ARGS__)
+
+]]
+
+
+$for i [[
+#define MOCK_CONST_METHOD$i[[]]_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD$i[[]]_(, const, ct, m, __VA_ARGS__)
+
+]]
+
+
+$for i [[
+#define MOCK_METHOD$i[[]]_T_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD$i[[]]_(typename, , ct, m, __VA_ARGS__)
+
+]]
+
+
+$for i [[
+#define MOCK_CONST_METHOD$i[[]]_T_WITH_CALLTYPE(ct, m, ...) \
+    GMOCK_METHOD$i[[]]_(typename, const, ct, m, __VA_ARGS__)
+
+]]
+
+// A MockFunction<F> class has one mock method whose type is F.  It is
+// useful when you just want your test code to emit some messages and
+// have Google Mock verify the right messages are sent (and perhaps at
+// the right times).  For example, if you are exercising code:
+//
+//   Foo(1);
+//   Foo(2);
+//   Foo(3);
+//
+// and want to verify that Foo(1) and Foo(3) both invoke
+// mock.Bar("a"), but Foo(2) doesn't invoke anything, you can write:
+//
+// TEST(FooTest, InvokesBarCorrectly) {
+//   MyMock mock;
+//   MockFunction<void(string check_point_name)> check;
+//   {
+//     InSequence s;
+//
+//     EXPECT_CALL(mock, Bar("a"));
+//     EXPECT_CALL(check, Call("1"));
+//     EXPECT_CALL(check, Call("2"));
+//     EXPECT_CALL(mock, Bar("a"));
+//   }
+//   Foo(1);
+//   check.Call("1");
+//   Foo(2);
+//   check.Call("2");
+//   Foo(3);
+// }
+//
+// The expectation spec says that the first Bar("a") must happen
+// before check point "1", the second Bar("a") must happen after check
+// point "2", and nothing should happen between the two check
+// points. The explicit check points make it easy to tell which
+// Bar("a") is called by which call to Foo().
+//
+// MockFunction<F> can also be used to exercise code that accepts
+// std::function<F> callbacks. To do so, use AsStdFunction() method
+// to create std::function proxy forwarding to original object's Call.
+// Example:
+//
+// TEST(FooTest, RunsCallbackWithBarArgument) {
+//   MockFunction<int(string)> callback;
+//   EXPECT_CALL(callback, Call("bar")).WillOnce(Return(1));
+//   Foo(callback.AsStdFunction());
+// }
+template <typename F>
+class MockFunction;
+
+
+$for i [[
+$range j 0..i-1
+$var ArgTypes = [[$for j, [[A$j]]]]
+$var ArgNames = [[$for j, [[a$j]]]]
+$var ArgDecls = [[$for j, [[A$j a$j]]]]
+template <typename R$for j [[, typename A$j]]>
+class MockFunction<R($ArgTypes)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD$i[[]]_T(Call, R($ArgTypes));
+
+#if GTEST_HAS_STD_FUNCTION_
+  std::function<R($ArgTypes)> AsStdFunction() {
+    return [this]($ArgDecls) -> R {
+      return this->Call($ArgNames);
+    };
+  }
+#endif  // GTEST_HAS_STD_FUNCTION_
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+
+]]
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
diff --git a/third_party/googletest/googlemock/include/gmock/gmock-generated-matchers.h b/third_party/googletest/googlemock/include/gmock/gmock-generated-matchers.h
new file mode 100644
index 0000000..57056fd
--- /dev/null
+++ b/third_party/googletest/googlemock/include/gmock/gmock-generated-matchers.h
@@ -0,0 +1,2179 @@
+// This file was GENERATED by command:
+//     pump.py gmock-generated-matchers.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements some commonly used variadic matchers.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
+
+#include <iterator>
+#include <sstream>
+#include <string>
+#include <vector>
+#include "gmock/gmock-matchers.h"
+
+namespace testing {
+namespace internal {
+
+// The type of the i-th (0-based) field of Tuple.
+#define GMOCK_FIELD_TYPE_(Tuple, i) \
+    typename ::testing::tuple_element<i, Tuple>::type
+
+// TupleFields<Tuple, k0, ..., kn> is for selecting fields from a
+// tuple of type Tuple.  It has two members:
+//
+//   type: a tuple type whose i-th field is the ki-th field of Tuple.
+//   GetSelectedFields(t): returns fields k0, ..., and kn of t as a tuple.
+//
+// For example, in class TupleFields<tuple<bool, char, int>, 2, 0>, we have:
+//
+//   type is tuple<int, bool>, and
+//   GetSelectedFields(make_tuple(true, 'a', 42)) is (42, true).
+
+template <class Tuple, int k0 = -1, int k1 = -1, int k2 = -1, int k3 = -1,
+    int k4 = -1, int k5 = -1, int k6 = -1, int k7 = -1, int k8 = -1,
+    int k9 = -1>
+class TupleFields;
+
+// This generic version is used when there are 10 selectors.
+template <class Tuple, int k0, int k1, int k2, int k3, int k4, int k5, int k6,
+    int k7, int k8, int k9>
+class TupleFields {
+ public:
+  typedef ::testing::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
+      GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
+      GMOCK_FIELD_TYPE_(Tuple, k3), GMOCK_FIELD_TYPE_(Tuple, k4),
+      GMOCK_FIELD_TYPE_(Tuple, k5), GMOCK_FIELD_TYPE_(Tuple, k6),
+      GMOCK_FIELD_TYPE_(Tuple, k7), GMOCK_FIELD_TYPE_(Tuple, k8),
+      GMOCK_FIELD_TYPE_(Tuple, k9)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t), get<k4>(t),
+        get<k5>(t), get<k6>(t), get<k7>(t), get<k8>(t), get<k9>(t));
+  }
+};
+
+// The following specialization is used for 0 ~ 9 selectors.
+
+template <class Tuple>
+class TupleFields<Tuple, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef ::testing::tuple<> type;
+  static type GetSelectedFields(const Tuple& /* t */) {
+    return type();
+  }
+};
+
+template <class Tuple, int k0>
+class TupleFields<Tuple, k0, -1, -1, -1, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef ::testing::tuple<GMOCK_FIELD_TYPE_(Tuple, k0)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    return type(get<k0>(t));
+  }
+};
+
+template <class Tuple, int k0, int k1>
+class TupleFields<Tuple, k0, k1, -1, -1, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef ::testing::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
+      GMOCK_FIELD_TYPE_(Tuple, k1)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    return type(get<k0>(t), get<k1>(t));
+  }
+};
+
+template <class Tuple, int k0, int k1, int k2>
+class TupleFields<Tuple, k0, k1, k2, -1, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef ::testing::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
+      GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    return type(get<k0>(t), get<k1>(t), get<k2>(t));
+  }
+};
+
+template <class Tuple, int k0, int k1, int k2, int k3>
+class TupleFields<Tuple, k0, k1, k2, k3, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef ::testing::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
+      GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
+      GMOCK_FIELD_TYPE_(Tuple, k3)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t));
+  }
+};
+
+template <class Tuple, int k0, int k1, int k2, int k3, int k4>
+class TupleFields<Tuple, k0, k1, k2, k3, k4, -1, -1, -1, -1, -1> {
+ public:
+  typedef ::testing::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
+      GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
+      GMOCK_FIELD_TYPE_(Tuple, k3), GMOCK_FIELD_TYPE_(Tuple, k4)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t), get<k4>(t));
+  }
+};
+
+template <class Tuple, int k0, int k1, int k2, int k3, int k4, int k5>
+class TupleFields<Tuple, k0, k1, k2, k3, k4, k5, -1, -1, -1, -1> {
+ public:
+  typedef ::testing::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
+      GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
+      GMOCK_FIELD_TYPE_(Tuple, k3), GMOCK_FIELD_TYPE_(Tuple, k4),
+      GMOCK_FIELD_TYPE_(Tuple, k5)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t), get<k4>(t),
+        get<k5>(t));
+  }
+};
+
+template <class Tuple, int k0, int k1, int k2, int k3, int k4, int k5, int k6>
+class TupleFields<Tuple, k0, k1, k2, k3, k4, k5, k6, -1, -1, -1> {
+ public:
+  typedef ::testing::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
+      GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
+      GMOCK_FIELD_TYPE_(Tuple, k3), GMOCK_FIELD_TYPE_(Tuple, k4),
+      GMOCK_FIELD_TYPE_(Tuple, k5), GMOCK_FIELD_TYPE_(Tuple, k6)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t), get<k4>(t),
+        get<k5>(t), get<k6>(t));
+  }
+};
+
+template <class Tuple, int k0, int k1, int k2, int k3, int k4, int k5, int k6,
+    int k7>
+class TupleFields<Tuple, k0, k1, k2, k3, k4, k5, k6, k7, -1, -1> {
+ public:
+  typedef ::testing::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
+      GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
+      GMOCK_FIELD_TYPE_(Tuple, k3), GMOCK_FIELD_TYPE_(Tuple, k4),
+      GMOCK_FIELD_TYPE_(Tuple, k5), GMOCK_FIELD_TYPE_(Tuple, k6),
+      GMOCK_FIELD_TYPE_(Tuple, k7)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t), get<k4>(t),
+        get<k5>(t), get<k6>(t), get<k7>(t));
+  }
+};
+
+template <class Tuple, int k0, int k1, int k2, int k3, int k4, int k5, int k6,
+    int k7, int k8>
+class TupleFields<Tuple, k0, k1, k2, k3, k4, k5, k6, k7, k8, -1> {
+ public:
+  typedef ::testing::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
+      GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
+      GMOCK_FIELD_TYPE_(Tuple, k3), GMOCK_FIELD_TYPE_(Tuple, k4),
+      GMOCK_FIELD_TYPE_(Tuple, k5), GMOCK_FIELD_TYPE_(Tuple, k6),
+      GMOCK_FIELD_TYPE_(Tuple, k7), GMOCK_FIELD_TYPE_(Tuple, k8)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t), get<k4>(t),
+        get<k5>(t), get<k6>(t), get<k7>(t), get<k8>(t));
+  }
+};
+
+#undef GMOCK_FIELD_TYPE_
+
+// Implements the Args() matcher.
+template <class ArgsTuple, int k0 = -1, int k1 = -1, int k2 = -1, int k3 = -1,
+    int k4 = -1, int k5 = -1, int k6 = -1, int k7 = -1, int k8 = -1,
+    int k9 = -1>
+class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> {
+ public:
+  // ArgsTuple may have top-level const or reference modifiers.
+  typedef GTEST_REMOVE_REFERENCE_AND_CONST_(ArgsTuple) RawArgsTuple;
+  typedef typename internal::TupleFields<RawArgsTuple, k0, k1, k2, k3, k4, k5,
+      k6, k7, k8, k9>::type SelectedArgs;
+  typedef Matcher<const SelectedArgs&> MonomorphicInnerMatcher;
+
+  template <typename InnerMatcher>
+  explicit ArgsMatcherImpl(const InnerMatcher& inner_matcher)
+      : inner_matcher_(SafeMatcherCast<const SelectedArgs&>(inner_matcher)) {}
+
+  virtual bool MatchAndExplain(ArgsTuple args,
+                               MatchResultListener* listener) const {
+    const SelectedArgs& selected_args = GetSelectedArgs(args);
+    if (!listener->IsInterested())
+      return inner_matcher_.Matches(selected_args);
+
+    PrintIndices(listener->stream());
+    *listener << "are " << PrintToString(selected_args);
+
+    StringMatchResultListener inner_listener;
+    const bool match = inner_matcher_.MatchAndExplain(selected_args,
+                                                      &inner_listener);
+    PrintIfNotEmpty(inner_listener.str(), listener->stream());
+    return match;
+  }
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "are a tuple ";
+    PrintIndices(os);
+    inner_matcher_.DescribeTo(os);
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "are a tuple ";
+    PrintIndices(os);
+    inner_matcher_.DescribeNegationTo(os);
+  }
+
+ private:
+  static SelectedArgs GetSelectedArgs(ArgsTuple args) {
+    return TupleFields<RawArgsTuple, k0, k1, k2, k3, k4, k5, k6, k7, k8,
+        k9>::GetSelectedFields(args);
+  }
+
+  // Prints the indices of the selected fields.
+  static void PrintIndices(::std::ostream* os) {
+    *os << "whose fields (";
+    const int indices[10] = { k0, k1, k2, k3, k4, k5, k6, k7, k8, k9 };
+    for (int i = 0; i < 10; i++) {
+      if (indices[i] < 0)
+        break;
+
+      if (i >= 1)
+        *os << ", ";
+
+      *os << "#" << indices[i];
+    }
+    *os << ") ";
+  }
+
+  const MonomorphicInnerMatcher inner_matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(ArgsMatcherImpl);
+};
+
+template <class InnerMatcher, int k0 = -1, int k1 = -1, int k2 = -1,
+    int k3 = -1, int k4 = -1, int k5 = -1, int k6 = -1, int k7 = -1,
+    int k8 = -1, int k9 = -1>
+class ArgsMatcher {
+ public:
+  explicit ArgsMatcher(const InnerMatcher& inner_matcher)
+      : inner_matcher_(inner_matcher) {}
+
+  template <typename ArgsTuple>
+  operator Matcher<ArgsTuple>() const {
+    return MakeMatcher(new ArgsMatcherImpl<ArgsTuple, k0, k1, k2, k3, k4, k5,
+        k6, k7, k8, k9>(inner_matcher_));
+  }
+
+ private:
+  const InnerMatcher inner_matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(ArgsMatcher);
+};
+
+// A set of metafunctions for computing the result type of AllOf.
+// AllOf(m1, ..., mN) returns
+// AllOfResultN<decltype(m1), ..., decltype(mN)>::type.
+
+// Although AllOf isn't defined for one argument, AllOfResult1 is defined
+// to simplify the implementation.
+template <typename M1>
+struct AllOfResult1 {
+  typedef M1 type;
+};
+
+template <typename M1, typename M2>
+struct AllOfResult2 {
+  typedef BothOfMatcher<
+      typename AllOfResult1<M1>::type,
+      typename AllOfResult1<M2>::type
+  > type;
+};
+
+template <typename M1, typename M2, typename M3>
+struct AllOfResult3 {
+  typedef BothOfMatcher<
+      typename AllOfResult1<M1>::type,
+      typename AllOfResult2<M2, M3>::type
+  > type;
+};
+
+template <typename M1, typename M2, typename M3, typename M4>
+struct AllOfResult4 {
+  typedef BothOfMatcher<
+      typename AllOfResult2<M1, M2>::type,
+      typename AllOfResult2<M3, M4>::type
+  > type;
+};
+
+template <typename M1, typename M2, typename M3, typename M4, typename M5>
+struct AllOfResult5 {
+  typedef BothOfMatcher<
+      typename AllOfResult2<M1, M2>::type,
+      typename AllOfResult3<M3, M4, M5>::type
+  > type;
+};
+
+template <typename M1, typename M2, typename M3, typename M4, typename M5,
+    typename M6>
+struct AllOfResult6 {
+  typedef BothOfMatcher<
+      typename AllOfResult3<M1, M2, M3>::type,
+      typename AllOfResult3<M4, M5, M6>::type
+  > type;
+};
+
+template <typename M1, typename M2, typename M3, typename M4, typename M5,
+    typename M6, typename M7>
+struct AllOfResult7 {
+  typedef BothOfMatcher<
+      typename AllOfResult3<M1, M2, M3>::type,
+      typename AllOfResult4<M4, M5, M6, M7>::type
+  > type;
+};
+
+template <typename M1, typename M2, typename M3, typename M4, typename M5,
+    typename M6, typename M7, typename M8>
+struct AllOfResult8 {
+  typedef BothOfMatcher<
+      typename AllOfResult4<M1, M2, M3, M4>::type,
+      typename AllOfResult4<M5, M6, M7, M8>::type
+  > type;
+};
+
+template <typename M1, typename M2, typename M3, typename M4, typename M5,
+    typename M6, typename M7, typename M8, typename M9>
+struct AllOfResult9 {
+  typedef BothOfMatcher<
+      typename AllOfResult4<M1, M2, M3, M4>::type,
+      typename AllOfResult5<M5, M6, M7, M8, M9>::type
+  > type;
+};
+
+template <typename M1, typename M2, typename M3, typename M4, typename M5,
+    typename M6, typename M7, typename M8, typename M9, typename M10>
+struct AllOfResult10 {
+  typedef BothOfMatcher<
+      typename AllOfResult5<M1, M2, M3, M4, M5>::type,
+      typename AllOfResult5<M6, M7, M8, M9, M10>::type
+  > type;
+};
+
+// A set of metafunctions for computing the result type of AnyOf.
+// AnyOf(m1, ..., mN) returns
+// AnyOfResultN<decltype(m1), ..., decltype(mN)>::type.
+
+// Although AnyOf isn't defined for one argument, AnyOfResult1 is defined
+// to simplify the implementation.
+template <typename M1>
+struct AnyOfResult1 {
+  typedef M1 type;
+};
+
+template <typename M1, typename M2>
+struct AnyOfResult2 {
+  typedef EitherOfMatcher<
+      typename AnyOfResult1<M1>::type,
+      typename AnyOfResult1<M2>::type
+  > type;
+};
+
+template <typename M1, typename M2, typename M3>
+struct AnyOfResult3 {
+  typedef EitherOfMatcher<
+      typename AnyOfResult1<M1>::type,
+      typename AnyOfResult2<M2, M3>::type
+  > type;
+};
+
+template <typename M1, typename M2, typename M3, typename M4>
+struct AnyOfResult4 {
+  typedef EitherOfMatcher<
+      typename AnyOfResult2<M1, M2>::type,
+      typename AnyOfResult2<M3, M4>::type
+  > type;
+};
+
+template <typename M1, typename M2, typename M3, typename M4, typename M5>
+struct AnyOfResult5 {
+  typedef EitherOfMatcher<
+      typename AnyOfResult2<M1, M2>::type,
+      typename AnyOfResult3<M3, M4, M5>::type
+  > type;
+};
+
+template <typename M1, typename M2, typename M3, typename M4, typename M5,
+    typename M6>
+struct AnyOfResult6 {
+  typedef EitherOfMatcher<
+      typename AnyOfResult3<M1, M2, M3>::type,
+      typename AnyOfResult3<M4, M5, M6>::type
+  > type;
+};
+
+template <typename M1, typename M2, typename M3, typename M4, typename M5,
+    typename M6, typename M7>
+struct AnyOfResult7 {
+  typedef EitherOfMatcher<
+      typename AnyOfResult3<M1, M2, M3>::type,
+      typename AnyOfResult4<M4, M5, M6, M7>::type
+  > type;
+};
+
+template <typename M1, typename M2, typename M3, typename M4, typename M5,
+    typename M6, typename M7, typename M8>
+struct AnyOfResult8 {
+  typedef EitherOfMatcher<
+      typename AnyOfResult4<M1, M2, M3, M4>::type,
+      typename AnyOfResult4<M5, M6, M7, M8>::type
+  > type;
+};
+
+template <typename M1, typename M2, typename M3, typename M4, typename M5,
+    typename M6, typename M7, typename M8, typename M9>
+struct AnyOfResult9 {
+  typedef EitherOfMatcher<
+      typename AnyOfResult4<M1, M2, M3, M4>::type,
+      typename AnyOfResult5<M5, M6, M7, M8, M9>::type
+  > type;
+};
+
+template <typename M1, typename M2, typename M3, typename M4, typename M5,
+    typename M6, typename M7, typename M8, typename M9, typename M10>
+struct AnyOfResult10 {
+  typedef EitherOfMatcher<
+      typename AnyOfResult5<M1, M2, M3, M4, M5>::type,
+      typename AnyOfResult5<M6, M7, M8, M9, M10>::type
+  > type;
+};
+
+}  // namespace internal
+
+// Args<N1, N2, ..., Nk>(a_matcher) matches a tuple if the selected
+// fields of it matches a_matcher.  C++ doesn't support default
+// arguments for function templates, so we have to overload it.
+template <typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher>(matcher);
+}
+
+template <int k1, typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1>(matcher);
+}
+
+template <int k1, int k2, typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1, k2>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1, k2>(matcher);
+}
+
+template <int k1, int k2, int k3, typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1, k2, k3>(matcher);
+}
+
+template <int k1, int k2, int k3, int k4, typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4>(matcher);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5>(matcher);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6>(matcher);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, int k7,
+    typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6,
+      k7>(matcher);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8,
+    typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7, k8>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7,
+      k8>(matcher);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8,
+    int k9, typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7, k8, k9>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7, k8,
+      k9>(matcher);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8,
+    int k9, int k10, typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7, k8, k9,
+    k10>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7, k8,
+      k9, k10>(matcher);
+}
+
+// ElementsAre(e_1, e_2, ... e_n) matches an STL-style container with
+// n elements, where the i-th element in the container must
+// match the i-th argument in the list.  Each argument of
+// ElementsAre() can be either a value or a matcher.  We support up to
+// 10 arguments.
+//
+// The use of DecayArray in the implementation allows ElementsAre()
+// to accept string literals, whose type is const char[N], but we
+// want to treat them as const char*.
+//
+// NOTE: Since ElementsAre() cares about the order of the elements, it
+// must not be used with containers whose elements's order is
+// undefined (e.g. hash_map).
+
+inline internal::ElementsAreMatcher<
+    ::testing::tuple<> >
+ElementsAre() {
+  typedef ::testing::tuple<> Args;
+  return internal::ElementsAreMatcher<Args>(Args());
+}
+
+template <typename T1>
+inline internal::ElementsAreMatcher<
+    ::testing::tuple<
+        typename internal::DecayArray<T1>::type> >
+ElementsAre(const T1& e1) {
+  typedef ::testing::tuple<
+      typename internal::DecayArray<T1>::type> Args;
+  return internal::ElementsAreMatcher<Args>(Args(e1));
+}
+
+template <typename T1, typename T2>
+inline internal::ElementsAreMatcher<
+    ::testing::tuple<
+        typename internal::DecayArray<T1>::type,
+        typename internal::DecayArray<T2>::type> >
+ElementsAre(const T1& e1, const T2& e2) {
+  typedef ::testing::tuple<
+      typename internal::DecayArray<T1>::type,
+      typename internal::DecayArray<T2>::type> Args;
+  return internal::ElementsAreMatcher<Args>(Args(e1, e2));
+}
+
+template <typename T1, typename T2, typename T3>
+inline internal::ElementsAreMatcher<
+    ::testing::tuple<
+        typename internal::DecayArray<T1>::type,
+        typename internal::DecayArray<T2>::type,
+        typename internal::DecayArray<T3>::type> >
+ElementsAre(const T1& e1, const T2& e2, const T3& e3) {
+  typedef ::testing::tuple<
+      typename internal::DecayArray<T1>::type,
+      typename internal::DecayArray<T2>::type,
+      typename internal::DecayArray<T3>::type> Args;
+  return internal::ElementsAreMatcher<Args>(Args(e1, e2, e3));
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+inline internal::ElementsAreMatcher<
+    ::testing::tuple<
+        typename internal::DecayArray<T1>::type,
+        typename internal::DecayArray<T2>::type,
+        typename internal::DecayArray<T3>::type,
+        typename internal::DecayArray<T4>::type> >
+ElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4) {
+  typedef ::testing::tuple<
+      typename internal::DecayArray<T1>::type,
+      typename internal::DecayArray<T2>::type,
+      typename internal::DecayArray<T3>::type,
+      typename internal::DecayArray<T4>::type> Args;
+  return internal::ElementsAreMatcher<Args>(Args(e1, e2, e3, e4));
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+inline internal::ElementsAreMatcher<
+    ::testing::tuple<
+        typename internal::DecayArray<T1>::type,
+        typename internal::DecayArray<T2>::type,
+        typename internal::DecayArray<T3>::type,
+        typename internal::DecayArray<T4>::type,
+        typename internal::DecayArray<T5>::type> >
+ElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+    const T5& e5) {
+  typedef ::testing::tuple<
+      typename internal::DecayArray<T1>::type,
+      typename internal::DecayArray<T2>::type,
+      typename internal::DecayArray<T3>::type,
+      typename internal::DecayArray<T4>::type,
+      typename internal::DecayArray<T5>::type> Args;
+  return internal::ElementsAreMatcher<Args>(Args(e1, e2, e3, e4, e5));
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+inline internal::ElementsAreMatcher<
+    ::testing::tuple<
+        typename internal::DecayArray<T1>::type,
+        typename internal::DecayArray<T2>::type,
+        typename internal::DecayArray<T3>::type,
+        typename internal::DecayArray<T4>::type,
+        typename internal::DecayArray<T5>::type,
+        typename internal::DecayArray<T6>::type> >
+ElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+    const T5& e5, const T6& e6) {
+  typedef ::testing::tuple<
+      typename internal::DecayArray<T1>::type,
+      typename internal::DecayArray<T2>::type,
+      typename internal::DecayArray<T3>::type,
+      typename internal::DecayArray<T4>::type,
+      typename internal::DecayArray<T5>::type,
+      typename internal::DecayArray<T6>::type> Args;
+  return internal::ElementsAreMatcher<Args>(Args(e1, e2, e3, e4, e5, e6));
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+inline internal::ElementsAreMatcher<
+    ::testing::tuple<
+        typename internal::DecayArray<T1>::type,
+        typename internal::DecayArray<T2>::type,
+        typename internal::DecayArray<T3>::type,
+        typename internal::DecayArray<T4>::type,
+        typename internal::DecayArray<T5>::type,
+        typename internal::DecayArray<T6>::type,
+        typename internal::DecayArray<T7>::type> >
+ElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+    const T5& e5, const T6& e6, const T7& e7) {
+  typedef ::testing::tuple<
+      typename internal::DecayArray<T1>::type,
+      typename internal::DecayArray<T2>::type,
+      typename internal::DecayArray<T3>::type,
+      typename internal::DecayArray<T4>::type,
+      typename internal::DecayArray<T5>::type,
+      typename internal::DecayArray<T6>::type,
+      typename internal::DecayArray<T7>::type> Args;
+  return internal::ElementsAreMatcher<Args>(Args(e1, e2, e3, e4, e5, e6, e7));
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+inline internal::ElementsAreMatcher<
+    ::testing::tuple<
+        typename internal::DecayArray<T1>::type,
+        typename internal::DecayArray<T2>::type,
+        typename internal::DecayArray<T3>::type,
+        typename internal::DecayArray<T4>::type,
+        typename internal::DecayArray<T5>::type,
+        typename internal::DecayArray<T6>::type,
+        typename internal::DecayArray<T7>::type,
+        typename internal::DecayArray<T8>::type> >
+ElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+    const T5& e5, const T6& e6, const T7& e7, const T8& e8) {
+  typedef ::testing::tuple<
+      typename internal::DecayArray<T1>::type,
+      typename internal::DecayArray<T2>::type,
+      typename internal::DecayArray<T3>::type,
+      typename internal::DecayArray<T4>::type,
+      typename internal::DecayArray<T5>::type,
+      typename internal::DecayArray<T6>::type,
+      typename internal::DecayArray<T7>::type,
+      typename internal::DecayArray<T8>::type> Args;
+  return internal::ElementsAreMatcher<Args>(Args(e1, e2, e3, e4, e5, e6, e7,
+      e8));
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+inline internal::ElementsAreMatcher<
+    ::testing::tuple<
+        typename internal::DecayArray<T1>::type,
+        typename internal::DecayArray<T2>::type,
+        typename internal::DecayArray<T3>::type,
+        typename internal::DecayArray<T4>::type,
+        typename internal::DecayArray<T5>::type,
+        typename internal::DecayArray<T6>::type,
+        typename internal::DecayArray<T7>::type,
+        typename internal::DecayArray<T8>::type,
+        typename internal::DecayArray<T9>::type> >
+ElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+    const T5& e5, const T6& e6, const T7& e7, const T8& e8, const T9& e9) {
+  typedef ::testing::tuple<
+      typename internal::DecayArray<T1>::type,
+      typename internal::DecayArray<T2>::type,
+      typename internal::DecayArray<T3>::type,
+      typename internal::DecayArray<T4>::type,
+      typename internal::DecayArray<T5>::type,
+      typename internal::DecayArray<T6>::type,
+      typename internal::DecayArray<T7>::type,
+      typename internal::DecayArray<T8>::type,
+      typename internal::DecayArray<T9>::type> Args;
+  return internal::ElementsAreMatcher<Args>(Args(e1, e2, e3, e4, e5, e6, e7,
+      e8, e9));
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+inline internal::ElementsAreMatcher<
+    ::testing::tuple<
+        typename internal::DecayArray<T1>::type,
+        typename internal::DecayArray<T2>::type,
+        typename internal::DecayArray<T3>::type,
+        typename internal::DecayArray<T4>::type,
+        typename internal::DecayArray<T5>::type,
+        typename internal::DecayArray<T6>::type,
+        typename internal::DecayArray<T7>::type,
+        typename internal::DecayArray<T8>::type,
+        typename internal::DecayArray<T9>::type,
+        typename internal::DecayArray<T10>::type> >
+ElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+    const T5& e5, const T6& e6, const T7& e7, const T8& e8, const T9& e9,
+    const T10& e10) {
+  typedef ::testing::tuple<
+      typename internal::DecayArray<T1>::type,
+      typename internal::DecayArray<T2>::type,
+      typename internal::DecayArray<T3>::type,
+      typename internal::DecayArray<T4>::type,
+      typename internal::DecayArray<T5>::type,
+      typename internal::DecayArray<T6>::type,
+      typename internal::DecayArray<T7>::type,
+      typename internal::DecayArray<T8>::type,
+      typename internal::DecayArray<T9>::type,
+      typename internal::DecayArray<T10>::type> Args;
+  return internal::ElementsAreMatcher<Args>(Args(e1, e2, e3, e4, e5, e6, e7,
+      e8, e9, e10));
+}
+
+// UnorderedElementsAre(e_1, e_2, ..., e_n) is an ElementsAre extension
+// that matches n elements in any order.  We support up to n=10 arguments.
+
+inline internal::UnorderedElementsAreMatcher<
+    ::testing::tuple<> >
+UnorderedElementsAre() {
+  typedef ::testing::tuple<> Args;
+  return internal::UnorderedElementsAreMatcher<Args>(Args());
+}
+
+template <typename T1>
+inline internal::UnorderedElementsAreMatcher<
+    ::testing::tuple<
+        typename internal::DecayArray<T1>::type> >
+UnorderedElementsAre(const T1& e1) {
+  typedef ::testing::tuple<
+      typename internal::DecayArray<T1>::type> Args;
+  return internal::UnorderedElementsAreMatcher<Args>(Args(e1));
+}
+
+template <typename T1, typename T2>
+inline internal::UnorderedElementsAreMatcher<
+    ::testing::tuple<
+        typename internal::DecayArray<T1>::type,
+        typename internal::DecayArray<T2>::type> >
+UnorderedElementsAre(const T1& e1, const T2& e2) {
+  typedef ::testing::tuple<
+      typename internal::DecayArray<T1>::type,
+      typename internal::DecayArray<T2>::type> Args;
+  return internal::UnorderedElementsAreMatcher<Args>(Args(e1, e2));
+}
+
+template <typename T1, typename T2, typename T3>
+inline internal::UnorderedElementsAreMatcher<
+    ::testing::tuple<
+        typename internal::DecayArray<T1>::type,
+        typename internal::DecayArray<T2>::type,
+        typename internal::DecayArray<T3>::type> >
+UnorderedElementsAre(const T1& e1, const T2& e2, const T3& e3) {
+  typedef ::testing::tuple<
+      typename internal::DecayArray<T1>::type,
+      typename internal::DecayArray<T2>::type,
+      typename internal::DecayArray<T3>::type> Args;
+  return internal::UnorderedElementsAreMatcher<Args>(Args(e1, e2, e3));
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+inline internal::UnorderedElementsAreMatcher<
+    ::testing::tuple<
+        typename internal::DecayArray<T1>::type,
+        typename internal::DecayArray<T2>::type,
+        typename internal::DecayArray<T3>::type,
+        typename internal::DecayArray<T4>::type> >
+UnorderedElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4) {
+  typedef ::testing::tuple<
+      typename internal::DecayArray<T1>::type,
+      typename internal::DecayArray<T2>::type,
+      typename internal::DecayArray<T3>::type,
+      typename internal::DecayArray<T4>::type> Args;
+  return internal::UnorderedElementsAreMatcher<Args>(Args(e1, e2, e3, e4));
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+inline internal::UnorderedElementsAreMatcher<
+    ::testing::tuple<
+        typename internal::DecayArray<T1>::type,
+        typename internal::DecayArray<T2>::type,
+        typename internal::DecayArray<T3>::type,
+        typename internal::DecayArray<T4>::type,
+        typename internal::DecayArray<T5>::type> >
+UnorderedElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+    const T5& e5) {
+  typedef ::testing::tuple<
+      typename internal::DecayArray<T1>::type,
+      typename internal::DecayArray<T2>::type,
+      typename internal::DecayArray<T3>::type,
+      typename internal::DecayArray<T4>::type,
+      typename internal::DecayArray<T5>::type> Args;
+  return internal::UnorderedElementsAreMatcher<Args>(Args(e1, e2, e3, e4, e5));
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+inline internal::UnorderedElementsAreMatcher<
+    ::testing::tuple<
+        typename internal::DecayArray<T1>::type,
+        typename internal::DecayArray<T2>::type,
+        typename internal::DecayArray<T3>::type,
+        typename internal::DecayArray<T4>::type,
+        typename internal::DecayArray<T5>::type,
+        typename internal::DecayArray<T6>::type> >
+UnorderedElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+    const T5& e5, const T6& e6) {
+  typedef ::testing::tuple<
+      typename internal::DecayArray<T1>::type,
+      typename internal::DecayArray<T2>::type,
+      typename internal::DecayArray<T3>::type,
+      typename internal::DecayArray<T4>::type,
+      typename internal::DecayArray<T5>::type,
+      typename internal::DecayArray<T6>::type> Args;
+  return internal::UnorderedElementsAreMatcher<Args>(Args(e1, e2, e3, e4, e5,
+      e6));
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+inline internal::UnorderedElementsAreMatcher<
+    ::testing::tuple<
+        typename internal::DecayArray<T1>::type,
+        typename internal::DecayArray<T2>::type,
+        typename internal::DecayArray<T3>::type,
+        typename internal::DecayArray<T4>::type,
+        typename internal::DecayArray<T5>::type,
+        typename internal::DecayArray<T6>::type,
+        typename internal::DecayArray<T7>::type> >
+UnorderedElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+    const T5& e5, const T6& e6, const T7& e7) {
+  typedef ::testing::tuple<
+      typename internal::DecayArray<T1>::type,
+      typename internal::DecayArray<T2>::type,
+      typename internal::DecayArray<T3>::type,
+      typename internal::DecayArray<T4>::type,
+      typename internal::DecayArray<T5>::type,
+      typename internal::DecayArray<T6>::type,
+      typename internal::DecayArray<T7>::type> Args;
+  return internal::UnorderedElementsAreMatcher<Args>(Args(e1, e2, e3, e4, e5,
+      e6, e7));
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+inline internal::UnorderedElementsAreMatcher<
+    ::testing::tuple<
+        typename internal::DecayArray<T1>::type,
+        typename internal::DecayArray<T2>::type,
+        typename internal::DecayArray<T3>::type,
+        typename internal::DecayArray<T4>::type,
+        typename internal::DecayArray<T5>::type,
+        typename internal::DecayArray<T6>::type,
+        typename internal::DecayArray<T7>::type,
+        typename internal::DecayArray<T8>::type> >
+UnorderedElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+    const T5& e5, const T6& e6, const T7& e7, const T8& e8) {
+  typedef ::testing::tuple<
+      typename internal::DecayArray<T1>::type,
+      typename internal::DecayArray<T2>::type,
+      typename internal::DecayArray<T3>::type,
+      typename internal::DecayArray<T4>::type,
+      typename internal::DecayArray<T5>::type,
+      typename internal::DecayArray<T6>::type,
+      typename internal::DecayArray<T7>::type,
+      typename internal::DecayArray<T8>::type> Args;
+  return internal::UnorderedElementsAreMatcher<Args>(Args(e1, e2, e3, e4, e5,
+      e6, e7, e8));
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+inline internal::UnorderedElementsAreMatcher<
+    ::testing::tuple<
+        typename internal::DecayArray<T1>::type,
+        typename internal::DecayArray<T2>::type,
+        typename internal::DecayArray<T3>::type,
+        typename internal::DecayArray<T4>::type,
+        typename internal::DecayArray<T5>::type,
+        typename internal::DecayArray<T6>::type,
+        typename internal::DecayArray<T7>::type,
+        typename internal::DecayArray<T8>::type,
+        typename internal::DecayArray<T9>::type> >
+UnorderedElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+    const T5& e5, const T6& e6, const T7& e7, const T8& e8, const T9& e9) {
+  typedef ::testing::tuple<
+      typename internal::DecayArray<T1>::type,
+      typename internal::DecayArray<T2>::type,
+      typename internal::DecayArray<T3>::type,
+      typename internal::DecayArray<T4>::type,
+      typename internal::DecayArray<T5>::type,
+      typename internal::DecayArray<T6>::type,
+      typename internal::DecayArray<T7>::type,
+      typename internal::DecayArray<T8>::type,
+      typename internal::DecayArray<T9>::type> Args;
+  return internal::UnorderedElementsAreMatcher<Args>(Args(e1, e2, e3, e4, e5,
+      e6, e7, e8, e9));
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+inline internal::UnorderedElementsAreMatcher<
+    ::testing::tuple<
+        typename internal::DecayArray<T1>::type,
+        typename internal::DecayArray<T2>::type,
+        typename internal::DecayArray<T3>::type,
+        typename internal::DecayArray<T4>::type,
+        typename internal::DecayArray<T5>::type,
+        typename internal::DecayArray<T6>::type,
+        typename internal::DecayArray<T7>::type,
+        typename internal::DecayArray<T8>::type,
+        typename internal::DecayArray<T9>::type,
+        typename internal::DecayArray<T10>::type> >
+UnorderedElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+    const T5& e5, const T6& e6, const T7& e7, const T8& e8, const T9& e9,
+    const T10& e10) {
+  typedef ::testing::tuple<
+      typename internal::DecayArray<T1>::type,
+      typename internal::DecayArray<T2>::type,
+      typename internal::DecayArray<T3>::type,
+      typename internal::DecayArray<T4>::type,
+      typename internal::DecayArray<T5>::type,
+      typename internal::DecayArray<T6>::type,
+      typename internal::DecayArray<T7>::type,
+      typename internal::DecayArray<T8>::type,
+      typename internal::DecayArray<T9>::type,
+      typename internal::DecayArray<T10>::type> Args;
+  return internal::UnorderedElementsAreMatcher<Args>(Args(e1, e2, e3, e4, e5,
+      e6, e7, e8, e9, e10));
+}
+
+// AllOf(m1, m2, ..., mk) matches any value that matches all of the given
+// sub-matchers.  AllOf is called fully qualified to prevent ADL from firing.
+
+template <typename M1, typename M2>
+inline typename internal::AllOfResult2<M1, M2>::type
+AllOf(M1 m1, M2 m2) {
+  return typename internal::AllOfResult2<M1, M2>::type(
+      m1,
+      m2);
+}
+
+template <typename M1, typename M2, typename M3>
+inline typename internal::AllOfResult3<M1, M2, M3>::type
+AllOf(M1 m1, M2 m2, M3 m3) {
+  return typename internal::AllOfResult3<M1, M2, M3>::type(
+      m1,
+      ::testing::AllOf(m2, m3));
+}
+
+template <typename M1, typename M2, typename M3, typename M4>
+inline typename internal::AllOfResult4<M1, M2, M3, M4>::type
+AllOf(M1 m1, M2 m2, M3 m3, M4 m4) {
+  return typename internal::AllOfResult4<M1, M2, M3, M4>::type(
+      ::testing::AllOf(m1, m2),
+      ::testing::AllOf(m3, m4));
+}
+
+template <typename M1, typename M2, typename M3, typename M4, typename M5>
+inline typename internal::AllOfResult5<M1, M2, M3, M4, M5>::type
+AllOf(M1 m1, M2 m2, M3 m3, M4 m4, M5 m5) {
+  return typename internal::AllOfResult5<M1, M2, M3, M4, M5>::type(
+      ::testing::AllOf(m1, m2),
+      ::testing::AllOf(m3, m4, m5));
+}
+
+template <typename M1, typename M2, typename M3, typename M4, typename M5,
+    typename M6>
+inline typename internal::AllOfResult6<M1, M2, M3, M4, M5, M6>::type
+AllOf(M1 m1, M2 m2, M3 m3, M4 m4, M5 m5, M6 m6) {
+  return typename internal::AllOfResult6<M1, M2, M3, M4, M5, M6>::type(
+      ::testing::AllOf(m1, m2, m3),
+      ::testing::AllOf(m4, m5, m6));
+}
+
+template <typename M1, typename M2, typename M3, typename M4, typename M5,
+    typename M6, typename M7>
+inline typename internal::AllOfResult7<M1, M2, M3, M4, M5, M6, M7>::type
+AllOf(M1 m1, M2 m2, M3 m3, M4 m4, M5 m5, M6 m6, M7 m7) {
+  return typename internal::AllOfResult7<M1, M2, M3, M4, M5, M6, M7>::type(
+      ::testing::AllOf(m1, m2, m3),
+      ::testing::AllOf(m4, m5, m6, m7));
+}
+
+template <typename M1, typename M2, typename M3, typename M4, typename M5,
+    typename M6, typename M7, typename M8>
+inline typename internal::AllOfResult8<M1, M2, M3, M4, M5, M6, M7, M8>::type
+AllOf(M1 m1, M2 m2, M3 m3, M4 m4, M5 m5, M6 m6, M7 m7, M8 m8) {
+  return typename internal::AllOfResult8<M1, M2, M3, M4, M5, M6, M7, M8>::type(
+      ::testing::AllOf(m1, m2, m3, m4),
+      ::testing::AllOf(m5, m6, m7, m8));
+}
+
+template <typename M1, typename M2, typename M3, typename M4, typename M5,
+    typename M6, typename M7, typename M8, typename M9>
+inline typename internal::AllOfResult9<M1, M2, M3, M4, M5, M6, M7, M8, M9>::type
+AllOf(M1 m1, M2 m2, M3 m3, M4 m4, M5 m5, M6 m6, M7 m7, M8 m8, M9 m9) {
+  return typename internal::AllOfResult9<M1, M2, M3, M4, M5, M6, M7, M8,
+      M9>::type(
+      ::testing::AllOf(m1, m2, m3, m4),
+      ::testing::AllOf(m5, m6, m7, m8, m9));
+}
+
+template <typename M1, typename M2, typename M3, typename M4, typename M5,
+    typename M6, typename M7, typename M8, typename M9, typename M10>
+inline typename internal::AllOfResult10<M1, M2, M3, M4, M5, M6, M7, M8, M9,
+    M10>::type
+AllOf(M1 m1, M2 m2, M3 m3, M4 m4, M5 m5, M6 m6, M7 m7, M8 m8, M9 m9, M10 m10) {
+  return typename internal::AllOfResult10<M1, M2, M3, M4, M5, M6, M7, M8, M9,
+      M10>::type(
+      ::testing::AllOf(m1, m2, m3, m4, m5),
+      ::testing::AllOf(m6, m7, m8, m9, m10));
+}
+
+// AnyOf(m1, m2, ..., mk) matches any value that matches any of the given
+// sub-matchers.  AnyOf is called fully qualified to prevent ADL from firing.
+
+template <typename M1, typename M2>
+inline typename internal::AnyOfResult2<M1, M2>::type
+AnyOf(M1 m1, M2 m2) {
+  return typename internal::AnyOfResult2<M1, M2>::type(
+      m1,
+      m2);
+}
+
+template <typename M1, typename M2, typename M3>
+inline typename internal::AnyOfResult3<M1, M2, M3>::type
+AnyOf(M1 m1, M2 m2, M3 m3) {
+  return typename internal::AnyOfResult3<M1, M2, M3>::type(
+      m1,
+      ::testing::AnyOf(m2, m3));
+}
+
+template <typename M1, typename M2, typename M3, typename M4>
+inline typename internal::AnyOfResult4<M1, M2, M3, M4>::type
+AnyOf(M1 m1, M2 m2, M3 m3, M4 m4) {
+  return typename internal::AnyOfResult4<M1, M2, M3, M4>::type(
+      ::testing::AnyOf(m1, m2),
+      ::testing::AnyOf(m3, m4));
+}
+
+template <typename M1, typename M2, typename M3, typename M4, typename M5>
+inline typename internal::AnyOfResult5<M1, M2, M3, M4, M5>::type
+AnyOf(M1 m1, M2 m2, M3 m3, M4 m4, M5 m5) {
+  return typename internal::AnyOfResult5<M1, M2, M3, M4, M5>::type(
+      ::testing::AnyOf(m1, m2),
+      ::testing::AnyOf(m3, m4, m5));
+}
+
+template <typename M1, typename M2, typename M3, typename M4, typename M5,
+    typename M6>
+inline typename internal::AnyOfResult6<M1, M2, M3, M4, M5, M6>::type
+AnyOf(M1 m1, M2 m2, M3 m3, M4 m4, M5 m5, M6 m6) {
+  return typename internal::AnyOfResult6<M1, M2, M3, M4, M5, M6>::type(
+      ::testing::AnyOf(m1, m2, m3),
+      ::testing::AnyOf(m4, m5, m6));
+}
+
+template <typename M1, typename M2, typename M3, typename M4, typename M5,
+    typename M6, typename M7>
+inline typename internal::AnyOfResult7<M1, M2, M3, M4, M5, M6, M7>::type
+AnyOf(M1 m1, M2 m2, M3 m3, M4 m4, M5 m5, M6 m6, M7 m7) {
+  return typename internal::AnyOfResult7<M1, M2, M3, M4, M5, M6, M7>::type(
+      ::testing::AnyOf(m1, m2, m3),
+      ::testing::AnyOf(m4, m5, m6, m7));
+}
+
+template <typename M1, typename M2, typename M3, typename M4, typename M5,
+    typename M6, typename M7, typename M8>
+inline typename internal::AnyOfResult8<M1, M2, M3, M4, M5, M6, M7, M8>::type
+AnyOf(M1 m1, M2 m2, M3 m3, M4 m4, M5 m5, M6 m6, M7 m7, M8 m8) {
+  return typename internal::AnyOfResult8<M1, M2, M3, M4, M5, M6, M7, M8>::type(
+      ::testing::AnyOf(m1, m2, m3, m4),
+      ::testing::AnyOf(m5, m6, m7, m8));
+}
+
+template <typename M1, typename M2, typename M3, typename M4, typename M5,
+    typename M6, typename M7, typename M8, typename M9>
+inline typename internal::AnyOfResult9<M1, M2, M3, M4, M5, M6, M7, M8, M9>::type
+AnyOf(M1 m1, M2 m2, M3 m3, M4 m4, M5 m5, M6 m6, M7 m7, M8 m8, M9 m9) {
+  return typename internal::AnyOfResult9<M1, M2, M3, M4, M5, M6, M7, M8,
+      M9>::type(
+      ::testing::AnyOf(m1, m2, m3, m4),
+      ::testing::AnyOf(m5, m6, m7, m8, m9));
+}
+
+template <typename M1, typename M2, typename M3, typename M4, typename M5,
+    typename M6, typename M7, typename M8, typename M9, typename M10>
+inline typename internal::AnyOfResult10<M1, M2, M3, M4, M5, M6, M7, M8, M9,
+    M10>::type
+AnyOf(M1 m1, M2 m2, M3 m3, M4 m4, M5 m5, M6 m6, M7 m7, M8 m8, M9 m9, M10 m10) {
+  return typename internal::AnyOfResult10<M1, M2, M3, M4, M5, M6, M7, M8, M9,
+      M10>::type(
+      ::testing::AnyOf(m1, m2, m3, m4, m5),
+      ::testing::AnyOf(m6, m7, m8, m9, m10));
+}
+
+}  // namespace testing
+
+
+// The MATCHER* family of macros can be used in a namespace scope to
+// define custom matchers easily.
+//
+// Basic Usage
+// ===========
+//
+// The syntax
+//
+//   MATCHER(name, description_string) { statements; }
+//
+// defines a matcher with the given name that executes the statements,
+// which must return a bool to indicate if the match succeeds.  Inside
+// the statements, you can refer to the value being matched by 'arg',
+// and refer to its type by 'arg_type'.
+//
+// The description string documents what the matcher does, and is used
+// to generate the failure message when the match fails.  Since a
+// MATCHER() is usually defined in a header file shared by multiple
+// C++ source files, we require the description to be a C-string
+// literal to avoid possible side effects.  It can be empty, in which
+// case we'll use the sequence of words in the matcher name as the
+// description.
+//
+// For example:
+//
+//   MATCHER(IsEven, "") { return (arg % 2) == 0; }
+//
+// allows you to write
+//
+//   // Expects mock_foo.Bar(n) to be called where n is even.
+//   EXPECT_CALL(mock_foo, Bar(IsEven()));
+//
+// or,
+//
+//   // Verifies that the value of some_expression is even.
+//   EXPECT_THAT(some_expression, IsEven());
+//
+// If the above assertion fails, it will print something like:
+//
+//   Value of: some_expression
+//   Expected: is even
+//     Actual: 7
+//
+// where the description "is even" is automatically calculated from the
+// matcher name IsEven.
+//
+// Argument Type
+// =============
+//
+// Note that the type of the value being matched (arg_type) is
+// determined by the context in which you use the matcher and is
+// supplied to you by the compiler, so you don't need to worry about
+// declaring it (nor can you).  This allows the matcher to be
+// polymorphic.  For example, IsEven() can be used to match any type
+// where the value of "(arg % 2) == 0" can be implicitly converted to
+// a bool.  In the "Bar(IsEven())" example above, if method Bar()
+// takes an int, 'arg_type' will be int; if it takes an unsigned long,
+// 'arg_type' will be unsigned long; and so on.
+//
+// Parameterizing Matchers
+// =======================
+//
+// Sometimes you'll want to parameterize the matcher.  For that you
+// can use another macro:
+//
+//   MATCHER_P(name, param_name, description_string) { statements; }
+//
+// For example:
+//
+//   MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; }
+//
+// will allow you to write:
+//
+//   EXPECT_THAT(Blah("a"), HasAbsoluteValue(n));
+//
+// which may lead to this message (assuming n is 10):
+//
+//   Value of: Blah("a")
+//   Expected: has absolute value 10
+//     Actual: -9
+//
+// Note that both the matcher description and its parameter are
+// printed, making the message human-friendly.
+//
+// In the matcher definition body, you can write 'foo_type' to
+// reference the type of a parameter named 'foo'.  For example, in the
+// body of MATCHER_P(HasAbsoluteValue, value) above, you can write
+// 'value_type' to refer to the type of 'value'.
+//
+// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P10 to
+// support multi-parameter matchers.
+//
+// Describing Parameterized Matchers
+// =================================
+//
+// The last argument to MATCHER*() is a string-typed expression.  The
+// expression can reference all of the matcher's parameters and a
+// special bool-typed variable named 'negation'.  When 'negation' is
+// false, the expression should evaluate to the matcher's description;
+// otherwise it should evaluate to the description of the negation of
+// the matcher.  For example,
+//
+//   using testing::PrintToString;
+//
+//   MATCHER_P2(InClosedRange, low, hi,
+//       string(negation ? "is not" : "is") + " in range [" +
+//       PrintToString(low) + ", " + PrintToString(hi) + "]") {
+//     return low <= arg && arg <= hi;
+//   }
+//   ...
+//   EXPECT_THAT(3, InClosedRange(4, 6));
+//   EXPECT_THAT(3, Not(InClosedRange(2, 4)));
+//
+// would generate two failures that contain the text:
+//
+//   Expected: is in range [4, 6]
+//   ...
+//   Expected: is not in range [2, 4]
+//
+// If you specify "" as the description, the failure message will
+// contain the sequence of words in the matcher name followed by the
+// parameter values printed as a tuple.  For example,
+//
+//   MATCHER_P2(InClosedRange, low, hi, "") { ... }
+//   ...
+//   EXPECT_THAT(3, InClosedRange(4, 6));
+//   EXPECT_THAT(3, Not(InClosedRange(2, 4)));
+//
+// would generate two failures that contain the text:
+//
+//   Expected: in closed range (4, 6)
+//   ...
+//   Expected: not (in closed range (2, 4))
+//
+// Types of Matcher Parameters
+// ===========================
+//
+// For the purpose of typing, you can view
+//
+//   MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... }
+//
+// as shorthand for
+//
+//   template <typename p1_type, ..., typename pk_type>
+//   FooMatcherPk<p1_type, ..., pk_type>
+//   Foo(p1_type p1, ..., pk_type pk) { ... }
+//
+// When you write Foo(v1, ..., vk), the compiler infers the types of
+// the parameters v1, ..., and vk for you.  If you are not happy with
+// the result of the type inference, you can specify the types by
+// explicitly instantiating the template, as in Foo<long, bool>(5,
+// false).  As said earlier, you don't get to (or need to) specify
+// 'arg_type' as that's determined by the context in which the matcher
+// is used.  You can assign the result of expression Foo(p1, ..., pk)
+// to a variable of type FooMatcherPk<p1_type, ..., pk_type>.  This
+// can be useful when composing matchers.
+//
+// While you can instantiate a matcher template with reference types,
+// passing the parameters by pointer usually makes your code more
+// readable.  If, however, you still want to pass a parameter by
+// reference, be aware that in the failure message generated by the
+// matcher you will see the value of the referenced object but not its
+// address.
+//
+// Explaining Match Results
+// ========================
+//
+// Sometimes the matcher description alone isn't enough to explain why
+// the match has failed or succeeded.  For example, when expecting a
+// long string, it can be very helpful to also print the diff between
+// the expected string and the actual one.  To achieve that, you can
+// optionally stream additional information to a special variable
+// named result_listener, whose type is a pointer to class
+// MatchResultListener:
+//
+//   MATCHER_P(EqualsLongString, str, "") {
+//     if (arg == str) return true;
+//
+//     *result_listener << "the difference: "
+///                     << DiffStrings(str, arg);
+//     return false;
+//   }
+//
+// Overloading Matchers
+// ====================
+//
+// You can overload matchers with different numbers of parameters:
+//
+//   MATCHER_P(Blah, a, description_string1) { ... }
+//   MATCHER_P2(Blah, a, b, description_string2) { ... }
+//
+// Caveats
+// =======
+//
+// When defining a new matcher, you should also consider implementing
+// MatcherInterface or using MakePolymorphicMatcher().  These
+// approaches require more work than the MATCHER* macros, but also
+// give you more control on the types of the value being matched and
+// the matcher parameters, which may leads to better compiler error
+// messages when the matcher is used wrong.  They also allow
+// overloading matchers based on parameter types (as opposed to just
+// based on the number of parameters).
+//
+// MATCHER*() can only be used in a namespace scope.  The reason is
+// that C++ doesn't yet allow function-local types to be used to
+// instantiate templates.  The up-coming C++0x standard will fix this.
+// Once that's done, we'll consider supporting using MATCHER*() inside
+// a function.
+//
+// More Information
+// ================
+//
+// To learn more about using these macros, please search for 'MATCHER'
+// on http://code.google.com/p/googlemock/wiki/CookBook.
+
+#define MATCHER(name, description)\
+  class name##Matcher {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl()\
+           {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name, \
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::testing::tuple<>()));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>());\
+    }\
+    name##Matcher() {\
+    }\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##Matcher);\
+  };\
+  inline name##Matcher name() {\
+    return name##Matcher();\
+  }\
+  template <typename arg_type>\
+  bool name##Matcher::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg, \
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P(name, p0, description)\
+  template <typename p0##_type>\
+  class name##MatcherP {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      explicit gmock_Impl(p0##_type gmock_p0)\
+           : p0(gmock_p0) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name, \
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::testing::tuple<p0##_type>(p0)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0));\
+    }\
+    explicit name##MatcherP(p0##_type gmock_p0) : p0(gmock_p0) {\
+    }\
+    p0##_type p0;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP);\
+  };\
+  template <typename p0##_type>\
+  inline name##MatcherP<p0##_type> name(p0##_type p0) {\
+    return name##MatcherP<p0##_type>(p0);\
+  }\
+  template <typename p0##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP<p0##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg, \
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P2(name, p0, p1, description)\
+  template <typename p0##_type, typename p1##_type>\
+  class name##MatcherP2 {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1)\
+           : p0(gmock_p0), p1(gmock_p1) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+      p1##_type p1;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name, \
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::testing::tuple<p0##_type, p1##_type>(p0, p1)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0, p1));\
+    }\
+    name##MatcherP2(p0##_type gmock_p0, p1##_type gmock_p1) : p0(gmock_p0), \
+        p1(gmock_p1) {\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP2);\
+  };\
+  template <typename p0##_type, typename p1##_type>\
+  inline name##MatcherP2<p0##_type, p1##_type> name(p0##_type p0, \
+      p1##_type p1) {\
+    return name##MatcherP2<p0##_type, p1##_type>(p0, p1);\
+  }\
+  template <typename p0##_type, typename p1##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP2<p0##_type, \
+      p1##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg, \
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P3(name, p0, p1, p2, description)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type>\
+  class name##MatcherP3 {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2)\
+           : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name, \
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::testing::tuple<p0##_type, p1##_type, p2##_type>(p0, p1, \
+                    p2)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0, p1, p2));\
+    }\
+    name##MatcherP3(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2) {\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP3);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type>\
+  inline name##MatcherP3<p0##_type, p1##_type, p2##_type> name(p0##_type p0, \
+      p1##_type p1, p2##_type p2) {\
+    return name##MatcherP3<p0##_type, p1##_type, p2##_type>(p0, p1, p2);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP3<p0##_type, p1##_type, \
+      p2##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg, \
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P4(name, p0, p1, p2, p3, description)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type>\
+  class name##MatcherP4 {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3)\
+           : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name, \
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::testing::tuple<p0##_type, p1##_type, p2##_type, \
+                    p3##_type>(p0, p1, p2, p3)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0, p1, p2, p3));\
+    }\
+    name##MatcherP4(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3) : p0(gmock_p0), p1(gmock_p1), \
+        p2(gmock_p2), p3(gmock_p3) {\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP4);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type>\
+  inline name##MatcherP4<p0##_type, p1##_type, p2##_type, \
+      p3##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, \
+      p3##_type p3) {\
+    return name##MatcherP4<p0##_type, p1##_type, p2##_type, p3##_type>(p0, \
+        p1, p2, p3);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP4<p0##_type, p1##_type, p2##_type, \
+      p3##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg, \
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P5(name, p0, p1, p2, p3, p4, description)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type>\
+  class name##MatcherP5 {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4)\
+           : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
+               p4(gmock_p4) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name, \
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::testing::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \
+                    p4##_type>(p0, p1, p2, p3, p4)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0, p1, p2, p3, p4));\
+    }\
+    name##MatcherP5(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, \
+        p4##_type gmock_p4) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4) {\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP5);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type>\
+  inline name##MatcherP5<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \
+      p4##_type p4) {\
+    return name##MatcherP5<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type>(p0, p1, p2, p3, p4);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP5<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg, \
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P6(name, p0, p1, p2, p3, p4, p5, description)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type>\
+  class name##MatcherP6 {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5)\
+           : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
+               p4(gmock_p4), p5(gmock_p5) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name, \
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::testing::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \
+                    p4##_type, p5##_type>(p0, p1, p2, p3, p4, p5)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0, p1, p2, p3, p4, p5));\
+    }\
+    name##MatcherP6(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5) {\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP6);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type>\
+  inline name##MatcherP6<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, \
+      p3##_type p3, p4##_type p4, p5##_type p5) {\
+    return name##MatcherP6<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type>(p0, p1, p2, p3, p4, p5);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP6<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+      p5##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg, \
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P7(name, p0, p1, p2, p3, p4, p5, p6, description)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type>\
+  class name##MatcherP7 {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+          p6##_type gmock_p6)\
+           : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
+               p4(gmock_p4), p5(gmock_p5), p6(gmock_p6) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+      p6##_type p6;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name, \
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::testing::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \
+                    p4##_type, p5##_type, p6##_type>(p0, p1, p2, p3, p4, p5, \
+                    p6)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0, p1, p2, p3, p4, p5, p6));\
+    }\
+    name##MatcherP7(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5, p6##_type gmock_p6) : p0(gmock_p0), p1(gmock_p1), \
+        p2(gmock_p2), p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), \
+        p6(gmock_p6) {\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+    p6##_type p6;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP7);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type>\
+  inline name##MatcherP7<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type, p6##_type> name(p0##_type p0, p1##_type p1, \
+      p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \
+      p6##_type p6) {\
+    return name##MatcherP7<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type, p6##_type>(p0, p1, p2, p3, p4, p5, p6);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP7<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+      p5##_type, p6##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg, \
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P8(name, p0, p1, p2, p3, p4, p5, p6, p7, description)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type>\
+  class name##MatcherP8 {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+          p6##_type gmock_p6, p7##_type gmock_p7)\
+           : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
+               p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+      p6##_type p6;\
+      p7##_type p7;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name, \
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::testing::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \
+                    p4##_type, p5##_type, p6##_type, p7##_type>(p0, p1, p2, \
+                    p3, p4, p5, p6, p7)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0, p1, p2, p3, p4, p5, p6, p7));\
+    }\
+    name##MatcherP8(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5, p6##_type gmock_p6, \
+        p7##_type gmock_p7) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \
+        p7(gmock_p7) {\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+    p6##_type p6;\
+    p7##_type p7;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP8);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type>\
+  inline name##MatcherP8<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type, p6##_type, p7##_type> name(p0##_type p0, \
+      p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \
+      p6##_type p6, p7##_type p7) {\
+    return name##MatcherP8<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type, p6##_type, p7##_type>(p0, p1, p2, p3, p4, p5, \
+        p6, p7);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP8<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+      p5##_type, p6##_type, \
+      p7##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg, \
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, description)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type>\
+  class name##MatcherP9 {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+          p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8)\
+           : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
+               p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \
+               p8(gmock_p8) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+      p6##_type p6;\
+      p7##_type p7;\
+      p8##_type p8;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name, \
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::testing::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \
+                    p4##_type, p5##_type, p6##_type, p7##_type, \
+                    p8##_type>(p0, p1, p2, p3, p4, p5, p6, p7, p8)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0, p1, p2, p3, p4, p5, p6, p7, p8));\
+    }\
+    name##MatcherP9(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \
+        p8##_type gmock_p8) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \
+        p8(gmock_p8) {\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+    p6##_type p6;\
+    p7##_type p7;\
+    p8##_type p8;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP9);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type>\
+  inline name##MatcherP9<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type, p6##_type, p7##_type, \
+      p8##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \
+      p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, \
+      p8##_type p8) {\
+    return name##MatcherP9<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type, p6##_type, p7##_type, p8##_type>(p0, p1, p2, \
+        p3, p4, p5, p6, p7, p8);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP9<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+      p5##_type, p6##_type, p7##_type, \
+      p8##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg, \
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, description)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type, \
+      typename p9##_type>\
+  class name##MatcherP10 {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+          p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8, \
+          p9##_type gmock_p9)\
+           : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
+               p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \
+               p8(gmock_p8), p9(gmock_p9) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+      p6##_type p6;\
+      p7##_type p7;\
+      p8##_type p8;\
+      p9##_type p9;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name, \
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::testing::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \
+                    p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, \
+                    p9##_type>(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9));\
+    }\
+    name##MatcherP10(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \
+        p8##_type gmock_p8, p9##_type gmock_p9) : p0(gmock_p0), p1(gmock_p1), \
+        p2(gmock_p2), p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \
+        p7(gmock_p7), p8(gmock_p8), p9(gmock_p9) {\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+    p6##_type p6;\
+    p7##_type p7;\
+    p8##_type p8;\
+    p9##_type p9;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP10);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type, \
+      typename p9##_type>\
+  inline name##MatcherP10<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, \
+      p9##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \
+      p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8, \
+      p9##_type p9) {\
+    return name##MatcherP10<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, p9##_type>(p0, \
+        p1, p2, p3, p4, p5, p6, p7, p8, p9);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type, \
+      typename p9##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP10<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, \
+      p9##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg, \
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
diff --git a/third_party/googletest/googlemock/include/gmock/gmock-generated-matchers.h.pump b/third_party/googletest/googlemock/include/gmock/gmock-generated-matchers.h.pump
new file mode 100644
index 0000000..de30c2c
--- /dev/null
+++ b/third_party/googletest/googlemock/include/gmock/gmock-generated-matchers.h.pump
@@ -0,0 +1,672 @@
+$$ -*- mode: c++; -*-
+$$ This is a Pump source file.  Please use Pump to convert it to
+$$ gmock-generated-actions.h.
+$$
+$var n = 10  $$ The maximum arity we support.
+$$ }} This line fixes auto-indentation of the following code in Emacs.
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements some commonly used variadic matchers.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
+
+#include <iterator>
+#include <sstream>
+#include <string>
+#include <vector>
+#include "gmock/gmock-matchers.h"
+
+namespace testing {
+namespace internal {
+
+$range i 0..n-1
+
+// The type of the i-th (0-based) field of Tuple.
+#define GMOCK_FIELD_TYPE_(Tuple, i) \
+    typename ::testing::tuple_element<i, Tuple>::type
+
+// TupleFields<Tuple, k0, ..., kn> is for selecting fields from a
+// tuple of type Tuple.  It has two members:
+//
+//   type: a tuple type whose i-th field is the ki-th field of Tuple.
+//   GetSelectedFields(t): returns fields k0, ..., and kn of t as a tuple.
+//
+// For example, in class TupleFields<tuple<bool, char, int>, 2, 0>, we have:
+//
+//   type is tuple<int, bool>, and
+//   GetSelectedFields(make_tuple(true, 'a', 42)) is (42, true).
+
+template <class Tuple$for i [[, int k$i = -1]]>
+class TupleFields;
+
+// This generic version is used when there are $n selectors.
+template <class Tuple$for i [[, int k$i]]>
+class TupleFields {
+ public:
+  typedef ::testing::tuple<$for i, [[GMOCK_FIELD_TYPE_(Tuple, k$i)]]> type;
+  static type GetSelectedFields(const Tuple& t) {
+    return type($for i, [[get<k$i>(t)]]);
+  }
+};
+
+// The following specialization is used for 0 ~ $(n-1) selectors.
+
+$for i [[
+$$ }}}
+$range j 0..i-1
+$range k 0..n-1
+
+template <class Tuple$for j [[, int k$j]]>
+class TupleFields<Tuple, $for k, [[$if k < i [[k$k]] $else [[-1]]]]> {
+ public:
+  typedef ::testing::tuple<$for j, [[GMOCK_FIELD_TYPE_(Tuple, k$j)]]> type;
+  static type GetSelectedFields(const Tuple& $if i==0 [[/* t */]] $else [[t]]) {
+    return type($for j, [[get<k$j>(t)]]);
+  }
+};
+
+]]
+
+#undef GMOCK_FIELD_TYPE_
+
+// Implements the Args() matcher.
+
+$var ks = [[$for i, [[k$i]]]]
+template <class ArgsTuple$for i [[, int k$i = -1]]>
+class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> {
+ public:
+  // ArgsTuple may have top-level const or reference modifiers.
+  typedef GTEST_REMOVE_REFERENCE_AND_CONST_(ArgsTuple) RawArgsTuple;
+  typedef typename internal::TupleFields<RawArgsTuple, $ks>::type SelectedArgs;
+  typedef Matcher<const SelectedArgs&> MonomorphicInnerMatcher;
+
+  template <typename InnerMatcher>
+  explicit ArgsMatcherImpl(const InnerMatcher& inner_matcher)
+      : inner_matcher_(SafeMatcherCast<const SelectedArgs&>(inner_matcher)) {}
+
+  virtual bool MatchAndExplain(ArgsTuple args,
+                               MatchResultListener* listener) const {
+    const SelectedArgs& selected_args = GetSelectedArgs(args);
+    if (!listener->IsInterested())
+      return inner_matcher_.Matches(selected_args);
+
+    PrintIndices(listener->stream());
+    *listener << "are " << PrintToString(selected_args);
+
+    StringMatchResultListener inner_listener;
+    const bool match = inner_matcher_.MatchAndExplain(selected_args,
+                                                      &inner_listener);
+    PrintIfNotEmpty(inner_listener.str(), listener->stream());
+    return match;
+  }
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "are a tuple ";
+    PrintIndices(os);
+    inner_matcher_.DescribeTo(os);
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "are a tuple ";
+    PrintIndices(os);
+    inner_matcher_.DescribeNegationTo(os);
+  }
+
+ private:
+  static SelectedArgs GetSelectedArgs(ArgsTuple args) {
+    return TupleFields<RawArgsTuple, $ks>::GetSelectedFields(args);
+  }
+
+  // Prints the indices of the selected fields.
+  static void PrintIndices(::std::ostream* os) {
+    *os << "whose fields (";
+    const int indices[$n] = { $ks };
+    for (int i = 0; i < $n; i++) {
+      if (indices[i] < 0)
+        break;
+
+      if (i >= 1)
+        *os << ", ";
+
+      *os << "#" << indices[i];
+    }
+    *os << ") ";
+  }
+
+  const MonomorphicInnerMatcher inner_matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(ArgsMatcherImpl);
+};
+
+template <class InnerMatcher$for i [[, int k$i = -1]]>
+class ArgsMatcher {
+ public:
+  explicit ArgsMatcher(const InnerMatcher& inner_matcher)
+      : inner_matcher_(inner_matcher) {}
+
+  template <typename ArgsTuple>
+  operator Matcher<ArgsTuple>() const {
+    return MakeMatcher(new ArgsMatcherImpl<ArgsTuple, $ks>(inner_matcher_));
+  }
+
+ private:
+  const InnerMatcher inner_matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(ArgsMatcher);
+};
+
+// A set of metafunctions for computing the result type of AllOf.
+// AllOf(m1, ..., mN) returns
+// AllOfResultN<decltype(m1), ..., decltype(mN)>::type.
+
+// Although AllOf isn't defined for one argument, AllOfResult1 is defined
+// to simplify the implementation.
+template <typename M1>
+struct AllOfResult1 {
+  typedef M1 type;
+};
+
+$range i 1..n
+
+$range i 2..n
+$for i [[
+$range j 2..i
+$var m = i/2
+$range k 1..m
+$range t m+1..i
+
+template <typename M1$for j [[, typename M$j]]>
+struct AllOfResult$i {
+  typedef BothOfMatcher<
+      typename AllOfResult$m<$for k, [[M$k]]>::type,
+      typename AllOfResult$(i-m)<$for t, [[M$t]]>::type
+  > type;
+};
+
+]]
+
+// A set of metafunctions for computing the result type of AnyOf.
+// AnyOf(m1, ..., mN) returns
+// AnyOfResultN<decltype(m1), ..., decltype(mN)>::type.
+
+// Although AnyOf isn't defined for one argument, AnyOfResult1 is defined
+// to simplify the implementation.
+template <typename M1>
+struct AnyOfResult1 {
+  typedef M1 type;
+};
+
+$range i 1..n
+
+$range i 2..n
+$for i [[
+$range j 2..i
+$var m = i/2
+$range k 1..m
+$range t m+1..i
+
+template <typename M1$for j [[, typename M$j]]>
+struct AnyOfResult$i {
+  typedef EitherOfMatcher<
+      typename AnyOfResult$m<$for k, [[M$k]]>::type,
+      typename AnyOfResult$(i-m)<$for t, [[M$t]]>::type
+  > type;
+};
+
+]]
+
+}  // namespace internal
+
+// Args<N1, N2, ..., Nk>(a_matcher) matches a tuple if the selected
+// fields of it matches a_matcher.  C++ doesn't support default
+// arguments for function templates, so we have to overload it.
+
+$range i 0..n
+$for i [[
+$range j 1..i
+template <$for j [[int k$j, ]]typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher$for j [[, k$j]]>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher$for j [[, k$j]]>(matcher);
+}
+
+
+]]
+// ElementsAre(e_1, e_2, ... e_n) matches an STL-style container with
+// n elements, where the i-th element in the container must
+// match the i-th argument in the list.  Each argument of
+// ElementsAre() can be either a value or a matcher.  We support up to
+// $n arguments.
+//
+// The use of DecayArray in the implementation allows ElementsAre()
+// to accept string literals, whose type is const char[N], but we
+// want to treat them as const char*.
+//
+// NOTE: Since ElementsAre() cares about the order of the elements, it
+// must not be used with containers whose elements's order is
+// undefined (e.g. hash_map).
+
+$range i 0..n
+$for i [[
+
+$range j 1..i
+
+$if i>0 [[
+
+template <$for j, [[typename T$j]]>
+]]
+
+inline internal::ElementsAreMatcher<
+    ::testing::tuple<
+$for j, [[
+
+        typename internal::DecayArray<T$j[[]]>::type]]> >
+ElementsAre($for j, [[const T$j& e$j]]) {
+  typedef ::testing::tuple<
+$for j, [[
+
+      typename internal::DecayArray<T$j[[]]>::type]]> Args;
+  return internal::ElementsAreMatcher<Args>(Args($for j, [[e$j]]));
+}
+
+]]
+
+// UnorderedElementsAre(e_1, e_2, ..., e_n) is an ElementsAre extension
+// that matches n elements in any order.  We support up to n=$n arguments.
+
+$range i 0..n
+$for i [[
+
+$range j 1..i
+
+$if i>0 [[
+
+template <$for j, [[typename T$j]]>
+]]
+
+inline internal::UnorderedElementsAreMatcher<
+    ::testing::tuple<
+$for j, [[
+
+        typename internal::DecayArray<T$j[[]]>::type]]> >
+UnorderedElementsAre($for j, [[const T$j& e$j]]) {
+  typedef ::testing::tuple<
+$for j, [[
+
+      typename internal::DecayArray<T$j[[]]>::type]]> Args;
+  return internal::UnorderedElementsAreMatcher<Args>(Args($for j, [[e$j]]));
+}
+
+]]
+
+// AllOf(m1, m2, ..., mk) matches any value that matches all of the given
+// sub-matchers.  AllOf is called fully qualified to prevent ADL from firing.
+
+$range i 2..n
+$for i [[
+$range j 1..i
+$var m = i/2
+$range k 1..m
+$range t m+1..i
+
+template <$for j, [[typename M$j]]>
+inline typename internal::AllOfResult$i<$for j, [[M$j]]>::type
+AllOf($for j, [[M$j m$j]]) {
+  return typename internal::AllOfResult$i<$for j, [[M$j]]>::type(
+      $if m == 1 [[m1]] $else [[::testing::AllOf($for k, [[m$k]])]],
+      $if m+1 == i [[m$i]] $else [[::testing::AllOf($for t, [[m$t]])]]);
+}
+
+]]
+
+// AnyOf(m1, m2, ..., mk) matches any value that matches any of the given
+// sub-matchers.  AnyOf is called fully qualified to prevent ADL from firing.
+
+$range i 2..n
+$for i [[
+$range j 1..i
+$var m = i/2
+$range k 1..m
+$range t m+1..i
+
+template <$for j, [[typename M$j]]>
+inline typename internal::AnyOfResult$i<$for j, [[M$j]]>::type
+AnyOf($for j, [[M$j m$j]]) {
+  return typename internal::AnyOfResult$i<$for j, [[M$j]]>::type(
+      $if m == 1 [[m1]] $else [[::testing::AnyOf($for k, [[m$k]])]],
+      $if m+1 == i [[m$i]] $else [[::testing::AnyOf($for t, [[m$t]])]]);
+}
+
+]]
+
+}  // namespace testing
+$$ } // This Pump meta comment fixes auto-indentation in Emacs. It will not
+$$   // show up in the generated code.
+
+
+// The MATCHER* family of macros can be used in a namespace scope to
+// define custom matchers easily.
+//
+// Basic Usage
+// ===========
+//
+// The syntax
+//
+//   MATCHER(name, description_string) { statements; }
+//
+// defines a matcher with the given name that executes the statements,
+// which must return a bool to indicate if the match succeeds.  Inside
+// the statements, you can refer to the value being matched by 'arg',
+// and refer to its type by 'arg_type'.
+//
+// The description string documents what the matcher does, and is used
+// to generate the failure message when the match fails.  Since a
+// MATCHER() is usually defined in a header file shared by multiple
+// C++ source files, we require the description to be a C-string
+// literal to avoid possible side effects.  It can be empty, in which
+// case we'll use the sequence of words in the matcher name as the
+// description.
+//
+// For example:
+//
+//   MATCHER(IsEven, "") { return (arg % 2) == 0; }
+//
+// allows you to write
+//
+//   // Expects mock_foo.Bar(n) to be called where n is even.
+//   EXPECT_CALL(mock_foo, Bar(IsEven()));
+//
+// or,
+//
+//   // Verifies that the value of some_expression is even.
+//   EXPECT_THAT(some_expression, IsEven());
+//
+// If the above assertion fails, it will print something like:
+//
+//   Value of: some_expression
+//   Expected: is even
+//     Actual: 7
+//
+// where the description "is even" is automatically calculated from the
+// matcher name IsEven.
+//
+// Argument Type
+// =============
+//
+// Note that the type of the value being matched (arg_type) is
+// determined by the context in which you use the matcher and is
+// supplied to you by the compiler, so you don't need to worry about
+// declaring it (nor can you).  This allows the matcher to be
+// polymorphic.  For example, IsEven() can be used to match any type
+// where the value of "(arg % 2) == 0" can be implicitly converted to
+// a bool.  In the "Bar(IsEven())" example above, if method Bar()
+// takes an int, 'arg_type' will be int; if it takes an unsigned long,
+// 'arg_type' will be unsigned long; and so on.
+//
+// Parameterizing Matchers
+// =======================
+//
+// Sometimes you'll want to parameterize the matcher.  For that you
+// can use another macro:
+//
+//   MATCHER_P(name, param_name, description_string) { statements; }
+//
+// For example:
+//
+//   MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; }
+//
+// will allow you to write:
+//
+//   EXPECT_THAT(Blah("a"), HasAbsoluteValue(n));
+//
+// which may lead to this message (assuming n is 10):
+//
+//   Value of: Blah("a")
+//   Expected: has absolute value 10
+//     Actual: -9
+//
+// Note that both the matcher description and its parameter are
+// printed, making the message human-friendly.
+//
+// In the matcher definition body, you can write 'foo_type' to
+// reference the type of a parameter named 'foo'.  For example, in the
+// body of MATCHER_P(HasAbsoluteValue, value) above, you can write
+// 'value_type' to refer to the type of 'value'.
+//
+// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P$n to
+// support multi-parameter matchers.
+//
+// Describing Parameterized Matchers
+// =================================
+//
+// The last argument to MATCHER*() is a string-typed expression.  The
+// expression can reference all of the matcher's parameters and a
+// special bool-typed variable named 'negation'.  When 'negation' is
+// false, the expression should evaluate to the matcher's description;
+// otherwise it should evaluate to the description of the negation of
+// the matcher.  For example,
+//
+//   using testing::PrintToString;
+//
+//   MATCHER_P2(InClosedRange, low, hi,
+//       string(negation ? "is not" : "is") + " in range [" +
+//       PrintToString(low) + ", " + PrintToString(hi) + "]") {
+//     return low <= arg && arg <= hi;
+//   }
+//   ...
+//   EXPECT_THAT(3, InClosedRange(4, 6));
+//   EXPECT_THAT(3, Not(InClosedRange(2, 4)));
+//
+// would generate two failures that contain the text:
+//
+//   Expected: is in range [4, 6]
+//   ...
+//   Expected: is not in range [2, 4]
+//
+// If you specify "" as the description, the failure message will
+// contain the sequence of words in the matcher name followed by the
+// parameter values printed as a tuple.  For example,
+//
+//   MATCHER_P2(InClosedRange, low, hi, "") { ... }
+//   ...
+//   EXPECT_THAT(3, InClosedRange(4, 6));
+//   EXPECT_THAT(3, Not(InClosedRange(2, 4)));
+//
+// would generate two failures that contain the text:
+//
+//   Expected: in closed range (4, 6)
+//   ...
+//   Expected: not (in closed range (2, 4))
+//
+// Types of Matcher Parameters
+// ===========================
+//
+// For the purpose of typing, you can view
+//
+//   MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... }
+//
+// as shorthand for
+//
+//   template <typename p1_type, ..., typename pk_type>
+//   FooMatcherPk<p1_type, ..., pk_type>
+//   Foo(p1_type p1, ..., pk_type pk) { ... }
+//
+// When you write Foo(v1, ..., vk), the compiler infers the types of
+// the parameters v1, ..., and vk for you.  If you are not happy with
+// the result of the type inference, you can specify the types by
+// explicitly instantiating the template, as in Foo<long, bool>(5,
+// false).  As said earlier, you don't get to (or need to) specify
+// 'arg_type' as that's determined by the context in which the matcher
+// is used.  You can assign the result of expression Foo(p1, ..., pk)
+// to a variable of type FooMatcherPk<p1_type, ..., pk_type>.  This
+// can be useful when composing matchers.
+//
+// While you can instantiate a matcher template with reference types,
+// passing the parameters by pointer usually makes your code more
+// readable.  If, however, you still want to pass a parameter by
+// reference, be aware that in the failure message generated by the
+// matcher you will see the value of the referenced object but not its
+// address.
+//
+// Explaining Match Results
+// ========================
+//
+// Sometimes the matcher description alone isn't enough to explain why
+// the match has failed or succeeded.  For example, when expecting a
+// long string, it can be very helpful to also print the diff between
+// the expected string and the actual one.  To achieve that, you can
+// optionally stream additional information to a special variable
+// named result_listener, whose type is a pointer to class
+// MatchResultListener:
+//
+//   MATCHER_P(EqualsLongString, str, "") {
+//     if (arg == str) return true;
+//
+//     *result_listener << "the difference: "
+///                     << DiffStrings(str, arg);
+//     return false;
+//   }
+//
+// Overloading Matchers
+// ====================
+//
+// You can overload matchers with different numbers of parameters:
+//
+//   MATCHER_P(Blah, a, description_string1) { ... }
+//   MATCHER_P2(Blah, a, b, description_string2) { ... }
+//
+// Caveats
+// =======
+//
+// When defining a new matcher, you should also consider implementing
+// MatcherInterface or using MakePolymorphicMatcher().  These
+// approaches require more work than the MATCHER* macros, but also
+// give you more control on the types of the value being matched and
+// the matcher parameters, which may leads to better compiler error
+// messages when the matcher is used wrong.  They also allow
+// overloading matchers based on parameter types (as opposed to just
+// based on the number of parameters).
+//
+// MATCHER*() can only be used in a namespace scope.  The reason is
+// that C++ doesn't yet allow function-local types to be used to
+// instantiate templates.  The up-coming C++0x standard will fix this.
+// Once that's done, we'll consider supporting using MATCHER*() inside
+// a function.
+//
+// More Information
+// ================
+//
+// To learn more about using these macros, please search for 'MATCHER'
+// on http://code.google.com/p/googlemock/wiki/CookBook.
+
+$range i 0..n
+$for i
+
+[[
+$var macro_name = [[$if i==0 [[MATCHER]] $elif i==1 [[MATCHER_P]]
+                                         $else [[MATCHER_P$i]]]]
+$var class_name = [[name##Matcher[[$if i==0 [[]] $elif i==1 [[P]]
+                                                 $else [[P$i]]]]]]
+$range j 0..i-1
+$var template = [[$if i==0 [[]] $else [[
+
+  template <$for j, [[typename p$j##_type]]>\
+]]]]
+$var ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]]
+$var impl_ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]]
+$var impl_inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(gmock_p$j)]]]]]]
+$var inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(gmock_p$j)]]]]]]
+$var params = [[$for j, [[p$j]]]]
+$var param_types = [[$if i==0 [[]] $else [[<$for j, [[p$j##_type]]>]]]]
+$var param_types_and_names = [[$for j, [[p$j##_type p$j]]]]
+$var param_field_decls = [[$for j
+[[
+
+      p$j##_type p$j;\
+]]]]
+$var param_field_decls2 = [[$for j
+[[
+
+    p$j##_type p$j;\
+]]]]
+
+#define $macro_name(name$for j [[, p$j]], description)\$template
+  class $class_name {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      [[$if i==1 [[explicit ]]]]gmock_Impl($impl_ctor_param_list)\
+          $impl_inits {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\$param_field_decls
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name, \
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::testing::tuple<$for j, [[p$j##_type]]>($for j, [[p$j]])));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>($params));\
+    }\
+    [[$if i==1 [[explicit ]]]]$class_name($ctor_param_list)$inits {\
+    }\$param_field_decls2
+   private:\
+    GTEST_DISALLOW_ASSIGN_($class_name);\
+  };\$template
+  inline $class_name$param_types name($param_types_and_names) {\
+    return $class_name$param_types($params);\
+  }\$template
+  template <typename arg_type>\
+  bool $class_name$param_types::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg, \
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+]]
+
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
diff --git a/third_party/googletest/googlemock/include/gmock/gmock-generated-nice-strict.h b/third_party/googletest/googlemock/include/gmock/gmock-generated-nice-strict.h
new file mode 100644
index 0000000..4095f4d
--- /dev/null
+++ b/third_party/googletest/googlemock/include/gmock/gmock-generated-nice-strict.h
@@ -0,0 +1,397 @@
+// This file was GENERATED by command:
+//     pump.py gmock-generated-nice-strict.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Implements class templates NiceMock, NaggyMock, and StrictMock.
+//
+// Given a mock class MockFoo that is created using Google Mock,
+// NiceMock<MockFoo> is a subclass of MockFoo that allows
+// uninteresting calls (i.e. calls to mock methods that have no
+// EXPECT_CALL specs), NaggyMock<MockFoo> is a subclass of MockFoo
+// that prints a warning when an uninteresting call occurs, and
+// StrictMock<MockFoo> is a subclass of MockFoo that treats all
+// uninteresting calls as errors.
+//
+// Currently a mock is naggy by default, so MockFoo and
+// NaggyMock<MockFoo> behave like the same.  However, we will soon
+// switch the default behavior of mocks to be nice, as that in general
+// leads to more maintainable tests.  When that happens, MockFoo will
+// stop behaving like NaggyMock<MockFoo> and start behaving like
+// NiceMock<MockFoo>.
+//
+// NiceMock, NaggyMock, and StrictMock "inherit" the constructors of
+// their respective base class, with up-to 10 arguments.  Therefore
+// you can write NiceMock<MockFoo>(5, "a") to construct a nice mock
+// where MockFoo has a constructor that accepts (int, const char*),
+// for example.
+//
+// A known limitation is that NiceMock<MockFoo>, NaggyMock<MockFoo>,
+// and StrictMock<MockFoo> only works for mock methods defined using
+// the MOCK_METHOD* family of macros DIRECTLY in the MockFoo class.
+// If a mock method is defined in a base class of MockFoo, the "nice"
+// or "strict" modifier may not affect it, depending on the compiler.
+// In particular, nesting NiceMock, NaggyMock, and StrictMock is NOT
+// supported.
+//
+// Another known limitation is that the constructors of the base mock
+// cannot have arguments passed by non-const reference, which are
+// banned by the Google C++ style guide anyway.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_
+
+#include "gmock/gmock-spec-builders.h"
+#include "gmock/internal/gmock-port.h"
+
+namespace testing {
+
+template <class MockClass>
+class NiceMock : public MockClass {
+ public:
+  // We don't factor out the constructor body to a common method, as
+  // we have to avoid a possible clash with members of MockClass.
+  NiceMock() {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  // C++ doesn't (yet) allow inheritance of constructors, so we have
+  // to define it for each arity.
+  template <typename A1>
+  explicit NiceMock(const A1& a1) : MockClass(a1) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+  template <typename A1, typename A2>
+  NiceMock(const A1& a1, const A2& a2) : MockClass(a1, a2) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3>
+  NiceMock(const A1& a1, const A2& a2, const A3& a3) : MockClass(a1, a2, a3) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4>
+  NiceMock(const A1& a1, const A2& a2, const A3& a3,
+      const A4& a4) : MockClass(a1, a2, a3, a4) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5>
+  NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5) : MockClass(a1, a2, a3, a4, a5) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6>
+  NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6) : MockClass(a1, a2, a3, a4, a5, a6) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7>
+  NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7) : MockClass(a1, a2, a3, a4, a5,
+      a6, a7) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7, typename A8>
+  NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7, const A8& a8) : MockClass(a1,
+      a2, a3, a4, a5, a6, a7, a8) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7, typename A8, typename A9>
+  NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7, const A8& a8,
+      const A9& a9) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7, typename A8, typename A9, typename A10>
+  NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9,
+      const A10& a10) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  virtual ~NiceMock() {
+    ::testing::Mock::UnregisterCallReaction(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(NiceMock);
+};
+
+template <class MockClass>
+class NaggyMock : public MockClass {
+ public:
+  // We don't factor out the constructor body to a common method, as
+  // we have to avoid a possible clash with members of MockClass.
+  NaggyMock() {
+    ::testing::Mock::WarnUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  // C++ doesn't (yet) allow inheritance of constructors, so we have
+  // to define it for each arity.
+  template <typename A1>
+  explicit NaggyMock(const A1& a1) : MockClass(a1) {
+    ::testing::Mock::WarnUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+  template <typename A1, typename A2>
+  NaggyMock(const A1& a1, const A2& a2) : MockClass(a1, a2) {
+    ::testing::Mock::WarnUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3>
+  NaggyMock(const A1& a1, const A2& a2, const A3& a3) : MockClass(a1, a2, a3) {
+    ::testing::Mock::WarnUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4>
+  NaggyMock(const A1& a1, const A2& a2, const A3& a3,
+      const A4& a4) : MockClass(a1, a2, a3, a4) {
+    ::testing::Mock::WarnUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5>
+  NaggyMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5) : MockClass(a1, a2, a3, a4, a5) {
+    ::testing::Mock::WarnUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6>
+  NaggyMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6) : MockClass(a1, a2, a3, a4, a5, a6) {
+    ::testing::Mock::WarnUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7>
+  NaggyMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7) : MockClass(a1, a2, a3, a4, a5,
+      a6, a7) {
+    ::testing::Mock::WarnUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7, typename A8>
+  NaggyMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7, const A8& a8) : MockClass(a1,
+      a2, a3, a4, a5, a6, a7, a8) {
+    ::testing::Mock::WarnUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7, typename A8, typename A9>
+  NaggyMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7, const A8& a8,
+      const A9& a9) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9) {
+    ::testing::Mock::WarnUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7, typename A8, typename A9, typename A10>
+  NaggyMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9,
+      const A10& a10) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {
+    ::testing::Mock::WarnUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  virtual ~NaggyMock() {
+    ::testing::Mock::UnregisterCallReaction(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(NaggyMock);
+};
+
+template <class MockClass>
+class StrictMock : public MockClass {
+ public:
+  // We don't factor out the constructor body to a common method, as
+  // we have to avoid a possible clash with members of MockClass.
+  StrictMock() {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  // C++ doesn't (yet) allow inheritance of constructors, so we have
+  // to define it for each arity.
+  template <typename A1>
+  explicit StrictMock(const A1& a1) : MockClass(a1) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+  template <typename A1, typename A2>
+  StrictMock(const A1& a1, const A2& a2) : MockClass(a1, a2) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3>
+  StrictMock(const A1& a1, const A2& a2, const A3& a3) : MockClass(a1, a2, a3) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4>
+  StrictMock(const A1& a1, const A2& a2, const A3& a3,
+      const A4& a4) : MockClass(a1, a2, a3, a4) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5>
+  StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5) : MockClass(a1, a2, a3, a4, a5) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6>
+  StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6) : MockClass(a1, a2, a3, a4, a5, a6) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7>
+  StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7) : MockClass(a1, a2, a3, a4, a5,
+      a6, a7) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7, typename A8>
+  StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7, const A8& a8) : MockClass(a1,
+      a2, a3, a4, a5, a6, a7, a8) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7, typename A8, typename A9>
+  StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7, const A8& a8,
+      const A9& a9) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7, typename A8, typename A9, typename A10>
+  StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9,
+      const A10& a10) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  virtual ~StrictMock() {
+    ::testing::Mock::UnregisterCallReaction(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(StrictMock);
+};
+
+// The following specializations catch some (relatively more common)
+// user errors of nesting nice and strict mocks.  They do NOT catch
+// all possible errors.
+
+// These specializations are declared but not defined, as NiceMock,
+// NaggyMock, and StrictMock cannot be nested.
+
+template <typename MockClass>
+class NiceMock<NiceMock<MockClass> >;
+template <typename MockClass>
+class NiceMock<NaggyMock<MockClass> >;
+template <typename MockClass>
+class NiceMock<StrictMock<MockClass> >;
+
+template <typename MockClass>
+class NaggyMock<NiceMock<MockClass> >;
+template <typename MockClass>
+class NaggyMock<NaggyMock<MockClass> >;
+template <typename MockClass>
+class NaggyMock<StrictMock<MockClass> >;
+
+template <typename MockClass>
+class StrictMock<NiceMock<MockClass> >;
+template <typename MockClass>
+class StrictMock<NaggyMock<MockClass> >;
+template <typename MockClass>
+class StrictMock<StrictMock<MockClass> >;
+
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_
diff --git a/third_party/googletest/googlemock/include/gmock/gmock-generated-nice-strict.h.pump b/third_party/googletest/googlemock/include/gmock/gmock-generated-nice-strict.h.pump
new file mode 100644
index 0000000..3ee1ce7
--- /dev/null
+++ b/third_party/googletest/googlemock/include/gmock/gmock-generated-nice-strict.h.pump
@@ -0,0 +1,161 @@
+$$ -*- mode: c++; -*-
+$$ This is a Pump source file.  Please use Pump to convert it to
+$$ gmock-generated-nice-strict.h.
+$$
+$var n = 10  $$ The maximum arity we support.
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Implements class templates NiceMock, NaggyMock, and StrictMock.
+//
+// Given a mock class MockFoo that is created using Google Mock,
+// NiceMock<MockFoo> is a subclass of MockFoo that allows
+// uninteresting calls (i.e. calls to mock methods that have no
+// EXPECT_CALL specs), NaggyMock<MockFoo> is a subclass of MockFoo
+// that prints a warning when an uninteresting call occurs, and
+// StrictMock<MockFoo> is a subclass of MockFoo that treats all
+// uninteresting calls as errors.
+//
+// Currently a mock is naggy by default, so MockFoo and
+// NaggyMock<MockFoo> behave like the same.  However, we will soon
+// switch the default behavior of mocks to be nice, as that in general
+// leads to more maintainable tests.  When that happens, MockFoo will
+// stop behaving like NaggyMock<MockFoo> and start behaving like
+// NiceMock<MockFoo>.
+//
+// NiceMock, NaggyMock, and StrictMock "inherit" the constructors of
+// their respective base class, with up-to $n arguments.  Therefore
+// you can write NiceMock<MockFoo>(5, "a") to construct a nice mock
+// where MockFoo has a constructor that accepts (int, const char*),
+// for example.
+//
+// A known limitation is that NiceMock<MockFoo>, NaggyMock<MockFoo>,
+// and StrictMock<MockFoo> only works for mock methods defined using
+// the MOCK_METHOD* family of macros DIRECTLY in the MockFoo class.
+// If a mock method is defined in a base class of MockFoo, the "nice"
+// or "strict" modifier may not affect it, depending on the compiler.
+// In particular, nesting NiceMock, NaggyMock, and StrictMock is NOT
+// supported.
+//
+// Another known limitation is that the constructors of the base mock
+// cannot have arguments passed by non-const reference, which are
+// banned by the Google C++ style guide anyway.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_
+
+#include "gmock/gmock-spec-builders.h"
+#include "gmock/internal/gmock-port.h"
+
+namespace testing {
+
+$range kind 0..2
+$for kind [[
+
+$var clazz=[[$if kind==0 [[NiceMock]]
+             $elif kind==1 [[NaggyMock]]
+             $else [[StrictMock]]]]
+
+$var method=[[$if kind==0 [[AllowUninterestingCalls]]
+             $elif kind==1 [[WarnUninterestingCalls]]
+             $else [[FailUninterestingCalls]]]]
+
+template <class MockClass>
+class $clazz : public MockClass {
+ public:
+  // We don't factor out the constructor body to a common method, as
+  // we have to avoid a possible clash with members of MockClass.
+  $clazz() {
+    ::testing::Mock::$method(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  // C++ doesn't (yet) allow inheritance of constructors, so we have
+  // to define it for each arity.
+  template <typename A1>
+  explicit $clazz(const A1& a1) : MockClass(a1) {
+    ::testing::Mock::$method(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+$range i 2..n
+$for i [[
+$range j 1..i
+  template <$for j, [[typename A$j]]>
+  $clazz($for j, [[const A$j& a$j]]) : MockClass($for j, [[a$j]]) {
+    ::testing::Mock::$method(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+
+]]
+  virtual ~$clazz() {
+    ::testing::Mock::UnregisterCallReaction(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_($clazz);
+};
+
+]]
+
+// The following specializations catch some (relatively more common)
+// user errors of nesting nice and strict mocks.  They do NOT catch
+// all possible errors.
+
+// These specializations are declared but not defined, as NiceMock,
+// NaggyMock, and StrictMock cannot be nested.
+
+template <typename MockClass>
+class NiceMock<NiceMock<MockClass> >;
+template <typename MockClass>
+class NiceMock<NaggyMock<MockClass> >;
+template <typename MockClass>
+class NiceMock<StrictMock<MockClass> >;
+
+template <typename MockClass>
+class NaggyMock<NiceMock<MockClass> >;
+template <typename MockClass>
+class NaggyMock<NaggyMock<MockClass> >;
+template <typename MockClass>
+class NaggyMock<StrictMock<MockClass> >;
+
+template <typename MockClass>
+class StrictMock<NiceMock<MockClass> >;
+template <typename MockClass>
+class StrictMock<NaggyMock<MockClass> >;
+template <typename MockClass>
+class StrictMock<StrictMock<MockClass> >;
+
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_
diff --git a/third_party/googletest/googlemock/include/gmock/gmock-matchers.h b/third_party/googletest/googlemock/include/gmock/gmock-matchers.h
new file mode 100644
index 0000000..33b37a7
--- /dev/null
+++ b/third_party/googletest/googlemock/include/gmock/gmock-matchers.h
@@ -0,0 +1,4399 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements some commonly used argument matchers.  More
+// matchers can be defined by the user implementing the
+// MatcherInterface<T> interface if necessary.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_
+
+#include <math.h>
+#include <algorithm>
+#include <iterator>
+#include <limits>
+#include <ostream>  // NOLINT
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "gmock/internal/gmock-internal-utils.h"
+#include "gmock/internal/gmock-port.h"
+#include "gtest/gtest.h"
+
+#if GTEST_HAS_STD_INITIALIZER_LIST_
+# include <initializer_list>  // NOLINT -- must be after gtest.h
+#endif
+
+namespace testing {
+
+// To implement a matcher Foo for type T, define:
+//   1. a class FooMatcherImpl that implements the
+//      MatcherInterface<T> interface, and
+//   2. a factory function that creates a Matcher<T> object from a
+//      FooMatcherImpl*.
+//
+// The two-level delegation design makes it possible to allow a user
+// to write "v" instead of "Eq(v)" where a Matcher is expected, which
+// is impossible if we pass matchers by pointers.  It also eases
+// ownership management as Matcher objects can now be copied like
+// plain values.
+
+// MatchResultListener is an abstract class.  Its << operator can be
+// used by a matcher to explain why a value matches or doesn't match.
+//
+// TODO(wan@google.com): add method
+//   bool InterestedInWhy(bool result) const;
+// to indicate whether the listener is interested in why the match
+// result is 'result'.
+class MatchResultListener {
+ public:
+  // Creates a listener object with the given underlying ostream.  The
+  // listener does not own the ostream, and does not dereference it
+  // in the constructor or destructor.
+  explicit MatchResultListener(::std::ostream* os) : stream_(os) {}
+  virtual ~MatchResultListener() = 0;  // Makes this class abstract.
+
+  // Streams x to the underlying ostream; does nothing if the ostream
+  // is NULL.
+  template <typename T>
+  MatchResultListener& operator<<(const T& x) {
+    if (stream_ != NULL)
+      *stream_ << x;
+    return *this;
+  }
+
+  // Returns the underlying ostream.
+  ::std::ostream* stream() { return stream_; }
+
+  // Returns true iff the listener is interested in an explanation of
+  // the match result.  A matcher's MatchAndExplain() method can use
+  // this information to avoid generating the explanation when no one
+  // intends to hear it.
+  bool IsInterested() const { return stream_ != NULL; }
+
+ private:
+  ::std::ostream* const stream_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MatchResultListener);
+};
+
+inline MatchResultListener::~MatchResultListener() {
+}
+
+// An instance of a subclass of this knows how to describe itself as a
+// matcher.
+class MatcherDescriberInterface {
+ public:
+  virtual ~MatcherDescriberInterface() {}
+
+  // Describes this matcher to an ostream.  The function should print
+  // a verb phrase that describes the property a value matching this
+  // matcher should have.  The subject of the verb phrase is the value
+  // being matched.  For example, the DescribeTo() method of the Gt(7)
+  // matcher prints "is greater than 7".
+  virtual void DescribeTo(::std::ostream* os) const = 0;
+
+  // Describes the negation of this matcher to an ostream.  For
+  // example, if the description of this matcher is "is greater than
+  // 7", the negated description could be "is not greater than 7".
+  // You are not required to override this when implementing
+  // MatcherInterface, but it is highly advised so that your matcher
+  // can produce good error messages.
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "not (";
+    DescribeTo(os);
+    *os << ")";
+  }
+};
+
+// The implementation of a matcher.
+template <typename T>
+class MatcherInterface : public MatcherDescriberInterface {
+ public:
+  // Returns true iff the matcher matches x; also explains the match
+  // result to 'listener' if necessary (see the next paragraph), in
+  // the form of a non-restrictive relative clause ("which ...",
+  // "whose ...", etc) that describes x.  For example, the
+  // MatchAndExplain() method of the Pointee(...) matcher should
+  // generate an explanation like "which points to ...".
+  //
+  // Implementations of MatchAndExplain() should add an explanation of
+  // the match result *if and only if* they can provide additional
+  // information that's not already present (or not obvious) in the
+  // print-out of x and the matcher's description.  Whether the match
+  // succeeds is not a factor in deciding whether an explanation is
+  // needed, as sometimes the caller needs to print a failure message
+  // when the match succeeds (e.g. when the matcher is used inside
+  // Not()).
+  //
+  // For example, a "has at least 10 elements" matcher should explain
+  // what the actual element count is, regardless of the match result,
+  // as it is useful information to the reader; on the other hand, an
+  // "is empty" matcher probably only needs to explain what the actual
+  // size is when the match fails, as it's redundant to say that the
+  // size is 0 when the value is already known to be empty.
+  //
+  // You should override this method when defining a new matcher.
+  //
+  // It's the responsibility of the caller (Google Mock) to guarantee
+  // that 'listener' is not NULL.  This helps to simplify a matcher's
+  // implementation when it doesn't care about the performance, as it
+  // can talk to 'listener' without checking its validity first.
+  // However, in order to implement dummy listeners efficiently,
+  // listener->stream() may be NULL.
+  virtual bool MatchAndExplain(T x, MatchResultListener* listener) const = 0;
+
+  // Inherits these methods from MatcherDescriberInterface:
+  //   virtual void DescribeTo(::std::ostream* os) const = 0;
+  //   virtual void DescribeNegationTo(::std::ostream* os) const;
+};
+
+// A match result listener that stores the explanation in a string.
+class StringMatchResultListener : public MatchResultListener {
+ public:
+  StringMatchResultListener() : MatchResultListener(&ss_) {}
+
+  // Returns the explanation accumulated so far.
+  internal::string str() const { return ss_.str(); }
+
+  // Clears the explanation accumulated so far.
+  void Clear() { ss_.str(""); }
+
+ private:
+  ::std::stringstream ss_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(StringMatchResultListener);
+};
+
+namespace internal {
+
+struct AnyEq {
+  template <typename A, typename B>
+  bool operator()(const A& a, const B& b) const { return a == b; }
+};
+struct AnyNe {
+  template <typename A, typename B>
+  bool operator()(const A& a, const B& b) const { return a != b; }
+};
+struct AnyLt {
+  template <typename A, typename B>
+  bool operator()(const A& a, const B& b) const { return a < b; }
+};
+struct AnyGt {
+  template <typename A, typename B>
+  bool operator()(const A& a, const B& b) const { return a > b; }
+};
+struct AnyLe {
+  template <typename A, typename B>
+  bool operator()(const A& a, const B& b) const { return a <= b; }
+};
+struct AnyGe {
+  template <typename A, typename B>
+  bool operator()(const A& a, const B& b) const { return a >= b; }
+};
+
+// A match result listener that ignores the explanation.
+class DummyMatchResultListener : public MatchResultListener {
+ public:
+  DummyMatchResultListener() : MatchResultListener(NULL) {}
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(DummyMatchResultListener);
+};
+
+// A match result listener that forwards the explanation to a given
+// ostream.  The difference between this and MatchResultListener is
+// that the former is concrete.
+class StreamMatchResultListener : public MatchResultListener {
+ public:
+  explicit StreamMatchResultListener(::std::ostream* os)
+      : MatchResultListener(os) {}
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamMatchResultListener);
+};
+
+// An internal class for implementing Matcher<T>, which will derive
+// from it.  We put functionalities common to all Matcher<T>
+// specializations here to avoid code duplication.
+template <typename T>
+class MatcherBase {
+ public:
+  // Returns true iff the matcher matches x; also explains the match
+  // result to 'listener'.
+  bool MatchAndExplain(T x, MatchResultListener* listener) const {
+    return impl_->MatchAndExplain(x, listener);
+  }
+
+  // Returns true iff this matcher matches x.
+  bool Matches(T x) const {
+    DummyMatchResultListener dummy;
+    return MatchAndExplain(x, &dummy);
+  }
+
+  // Describes this matcher to an ostream.
+  void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); }
+
+  // Describes the negation of this matcher to an ostream.
+  void DescribeNegationTo(::std::ostream* os) const {
+    impl_->DescribeNegationTo(os);
+  }
+
+  // Explains why x matches, or doesn't match, the matcher.
+  void ExplainMatchResultTo(T x, ::std::ostream* os) const {
+    StreamMatchResultListener listener(os);
+    MatchAndExplain(x, &listener);
+  }
+
+  // Returns the describer for this matcher object; retains ownership
+  // of the describer, which is only guaranteed to be alive when
+  // this matcher object is alive.
+  const MatcherDescriberInterface* GetDescriber() const {
+    return impl_.get();
+  }
+
+ protected:
+  MatcherBase() {}
+
+  // Constructs a matcher from its implementation.
+  explicit MatcherBase(const MatcherInterface<T>* impl)
+      : impl_(impl) {}
+
+  virtual ~MatcherBase() {}
+
+ private:
+  // shared_ptr (util/gtl/shared_ptr.h) and linked_ptr have similar
+  // interfaces.  The former dynamically allocates a chunk of memory
+  // to hold the reference count, while the latter tracks all
+  // references using a circular linked list without allocating
+  // memory.  It has been observed that linked_ptr performs better in
+  // typical scenarios.  However, shared_ptr can out-perform
+  // linked_ptr when there are many more uses of the copy constructor
+  // than the default constructor.
+  //
+  // If performance becomes a problem, we should see if using
+  // shared_ptr helps.
+  ::testing::internal::linked_ptr<const MatcherInterface<T> > impl_;
+};
+
+}  // namespace internal
+
+// A Matcher<T> is a copyable and IMMUTABLE (except by assignment)
+// object that can check whether a value of type T matches.  The
+// implementation of Matcher<T> is just a linked_ptr to const
+// MatcherInterface<T>, so copying is fairly cheap.  Don't inherit
+// from Matcher!
+template <typename T>
+class Matcher : public internal::MatcherBase<T> {
+ public:
+  // Constructs a null matcher.  Needed for storing Matcher objects in STL
+  // containers.  A default-constructed matcher is not yet initialized.  You
+  // cannot use it until a valid value has been assigned to it.
+  explicit Matcher() {}  // NOLINT
+
+  // Constructs a matcher from its implementation.
+  explicit Matcher(const MatcherInterface<T>* impl)
+      : internal::MatcherBase<T>(impl) {}
+
+  // Implicit constructor here allows people to write
+  // EXPECT_CALL(foo, Bar(5)) instead of EXPECT_CALL(foo, Bar(Eq(5))) sometimes
+  Matcher(T value);  // NOLINT
+};
+
+// The following two specializations allow the user to write str
+// instead of Eq(str) and "foo" instead of Eq("foo") when a string
+// matcher is expected.
+template <>
+class GTEST_API_ Matcher<const internal::string&>
+    : public internal::MatcherBase<const internal::string&> {
+ public:
+  Matcher() {}
+
+  explicit Matcher(const MatcherInterface<const internal::string&>* impl)
+      : internal::MatcherBase<const internal::string&>(impl) {}
+
+  // Allows the user to write str instead of Eq(str) sometimes, where
+  // str is a string object.
+  Matcher(const internal::string& s);  // NOLINT
+
+  // Allows the user to write "foo" instead of Eq("foo") sometimes.
+  Matcher(const char* s);  // NOLINT
+};
+
+template <>
+class GTEST_API_ Matcher<internal::string>
+    : public internal::MatcherBase<internal::string> {
+ public:
+  Matcher() {}
+
+  explicit Matcher(const MatcherInterface<internal::string>* impl)
+      : internal::MatcherBase<internal::string>(impl) {}
+
+  // Allows the user to write str instead of Eq(str) sometimes, where
+  // str is a string object.
+  Matcher(const internal::string& s);  // NOLINT
+
+  // Allows the user to write "foo" instead of Eq("foo") sometimes.
+  Matcher(const char* s);  // NOLINT
+};
+
+#if GTEST_HAS_STRING_PIECE_
+// The following two specializations allow the user to write str
+// instead of Eq(str) and "foo" instead of Eq("foo") when a StringPiece
+// matcher is expected.
+template <>
+class GTEST_API_ Matcher<const StringPiece&>
+    : public internal::MatcherBase<const StringPiece&> {
+ public:
+  Matcher() {}
+
+  explicit Matcher(const MatcherInterface<const StringPiece&>* impl)
+      : internal::MatcherBase<const StringPiece&>(impl) {}
+
+  // Allows the user to write str instead of Eq(str) sometimes, where
+  // str is a string object.
+  Matcher(const internal::string& s);  // NOLINT
+
+  // Allows the user to write "foo" instead of Eq("foo") sometimes.
+  Matcher(const char* s);  // NOLINT
+
+  // Allows the user to pass StringPieces directly.
+  Matcher(StringPiece s);  // NOLINT
+};
+
+template <>
+class GTEST_API_ Matcher<StringPiece>
+    : public internal::MatcherBase<StringPiece> {
+ public:
+  Matcher() {}
+
+  explicit Matcher(const MatcherInterface<StringPiece>* impl)
+      : internal::MatcherBase<StringPiece>(impl) {}
+
+  // Allows the user to write str instead of Eq(str) sometimes, where
+  // str is a string object.
+  Matcher(const internal::string& s);  // NOLINT
+
+  // Allows the user to write "foo" instead of Eq("foo") sometimes.
+  Matcher(const char* s);  // NOLINT
+
+  // Allows the user to pass StringPieces directly.
+  Matcher(StringPiece s);  // NOLINT
+};
+#endif  // GTEST_HAS_STRING_PIECE_
+
+// The PolymorphicMatcher class template makes it easy to implement a
+// polymorphic matcher (i.e. a matcher that can match values of more
+// than one type, e.g. Eq(n) and NotNull()).
+//
+// To define a polymorphic matcher, a user should provide an Impl
+// class that has a DescribeTo() method and a DescribeNegationTo()
+// method, and define a member function (or member function template)
+//
+//   bool MatchAndExplain(const Value& value,
+//                        MatchResultListener* listener) const;
+//
+// See the definition of NotNull() for a complete example.
+template <class Impl>
+class PolymorphicMatcher {
+ public:
+  explicit PolymorphicMatcher(const Impl& an_impl) : impl_(an_impl) {}
+
+  // Returns a mutable reference to the underlying matcher
+  // implementation object.
+  Impl& mutable_impl() { return impl_; }
+
+  // Returns an immutable reference to the underlying matcher
+  // implementation object.
+  const Impl& impl() const { return impl_; }
+
+  template <typename T>
+  operator Matcher<T>() const {
+    return Matcher<T>(new MonomorphicImpl<T>(impl_));
+  }
+
+ private:
+  template <typename T>
+  class MonomorphicImpl : public MatcherInterface<T> {
+   public:
+    explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {}
+
+    virtual void DescribeTo(::std::ostream* os) const {
+      impl_.DescribeTo(os);
+    }
+
+    virtual void DescribeNegationTo(::std::ostream* os) const {
+      impl_.DescribeNegationTo(os);
+    }
+
+    virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
+      return impl_.MatchAndExplain(x, listener);
+    }
+
+   private:
+    const Impl impl_;
+
+    GTEST_DISALLOW_ASSIGN_(MonomorphicImpl);
+  };
+
+  Impl impl_;
+
+  GTEST_DISALLOW_ASSIGN_(PolymorphicMatcher);
+};
+
+// Creates a matcher from its implementation.  This is easier to use
+// than the Matcher<T> constructor as it doesn't require you to
+// explicitly write the template argument, e.g.
+//
+//   MakeMatcher(foo);
+// vs
+//   Matcher<const string&>(foo);
+template <typename T>
+inline Matcher<T> MakeMatcher(const MatcherInterface<T>* impl) {
+  return Matcher<T>(impl);
+}
+
+// Creates a polymorphic matcher from its implementation.  This is
+// easier to use than the PolymorphicMatcher<Impl> constructor as it
+// doesn't require you to explicitly write the template argument, e.g.
+//
+//   MakePolymorphicMatcher(foo);
+// vs
+//   PolymorphicMatcher<TypeOfFoo>(foo);
+template <class Impl>
+inline PolymorphicMatcher<Impl> MakePolymorphicMatcher(const Impl& impl) {
+  return PolymorphicMatcher<Impl>(impl);
+}
+
+// Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION
+// and MUST NOT BE USED IN USER CODE!!!
+namespace internal {
+
+// The MatcherCastImpl class template is a helper for implementing
+// MatcherCast().  We need this helper in order to partially
+// specialize the implementation of MatcherCast() (C++ allows
+// class/struct templates to be partially specialized, but not
+// function templates.).
+
+// This general version is used when MatcherCast()'s argument is a
+// polymorphic matcher (i.e. something that can be converted to a
+// Matcher but is not one yet; for example, Eq(value)) or a value (for
+// example, "hello").
+template <typename T, typename M>
+class MatcherCastImpl {
+ public:
+  static Matcher<T> Cast(const M& polymorphic_matcher_or_value) {
+    // M can be a polymorhic matcher, in which case we want to use
+    // its conversion operator to create Matcher<T>.  Or it can be a value
+    // that should be passed to the Matcher<T>'s constructor.
+    //
+    // We can't call Matcher<T>(polymorphic_matcher_or_value) when M is a
+    // polymorphic matcher because it'll be ambiguous if T has an implicit
+    // constructor from M (this usually happens when T has an implicit
+    // constructor from any type).
+    //
+    // It won't work to unconditionally implict_cast
+    // polymorphic_matcher_or_value to Matcher<T> because it won't trigger
+    // a user-defined conversion from M to T if one exists (assuming M is
+    // a value).
+    return CastImpl(
+        polymorphic_matcher_or_value,
+        BooleanConstant<
+            internal::ImplicitlyConvertible<M, Matcher<T> >::value>());
+  }
+
+ private:
+  static Matcher<T> CastImpl(const M& value, BooleanConstant<false>) {
+    // M can't be implicitly converted to Matcher<T>, so M isn't a polymorphic
+    // matcher.  It must be a value then.  Use direct initialization to create
+    // a matcher.
+    return Matcher<T>(ImplicitCast_<T>(value));
+  }
+
+  static Matcher<T> CastImpl(const M& polymorphic_matcher_or_value,
+                             BooleanConstant<true>) {
+    // M is implicitly convertible to Matcher<T>, which means that either
+    // M is a polymorhpic matcher or Matcher<T> has an implicit constructor
+    // from M.  In both cases using the implicit conversion will produce a
+    // matcher.
+    //
+    // Even if T has an implicit constructor from M, it won't be called because
+    // creating Matcher<T> would require a chain of two user-defined conversions
+    // (first to create T from M and then to create Matcher<T> from T).
+    return polymorphic_matcher_or_value;
+  }
+};
+
+// This more specialized version is used when MatcherCast()'s argument
+// is already a Matcher.  This only compiles when type T can be
+// statically converted to type U.
+template <typename T, typename U>
+class MatcherCastImpl<T, Matcher<U> > {
+ public:
+  static Matcher<T> Cast(const Matcher<U>& source_matcher) {
+    return Matcher<T>(new Impl(source_matcher));
+  }
+
+ private:
+  class Impl : public MatcherInterface<T> {
+   public:
+    explicit Impl(const Matcher<U>& source_matcher)
+        : source_matcher_(source_matcher) {}
+
+    // We delegate the matching logic to the source matcher.
+    virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
+      return source_matcher_.MatchAndExplain(static_cast<U>(x), listener);
+    }
+
+    virtual void DescribeTo(::std::ostream* os) const {
+      source_matcher_.DescribeTo(os);
+    }
+
+    virtual void DescribeNegationTo(::std::ostream* os) const {
+      source_matcher_.DescribeNegationTo(os);
+    }
+
+   private:
+    const Matcher<U> source_matcher_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+};
+
+// This even more specialized version is used for efficiently casting
+// a matcher to its own type.
+template <typename T>
+class MatcherCastImpl<T, Matcher<T> > {
+ public:
+  static Matcher<T> Cast(const Matcher<T>& matcher) { return matcher; }
+};
+
+}  // namespace internal
+
+// In order to be safe and clear, casting between different matcher
+// types is done explicitly via MatcherCast<T>(m), which takes a
+// matcher m and returns a Matcher<T>.  It compiles only when T can be
+// statically converted to the argument type of m.
+template <typename T, typename M>
+inline Matcher<T> MatcherCast(const M& matcher) {
+  return internal::MatcherCastImpl<T, M>::Cast(matcher);
+}
+
+// Implements SafeMatcherCast().
+//
+// We use an intermediate class to do the actual safe casting as Nokia's
+// Symbian compiler cannot decide between
+// template <T, M> ... (M) and
+// template <T, U> ... (const Matcher<U>&)
+// for function templates but can for member function templates.
+template <typename T>
+class SafeMatcherCastImpl {
+ public:
+  // This overload handles polymorphic matchers and values only since
+  // monomorphic matchers are handled by the next one.
+  template <typename M>
+  static inline Matcher<T> Cast(const M& polymorphic_matcher_or_value) {
+    return internal::MatcherCastImpl<T, M>::Cast(polymorphic_matcher_or_value);
+  }
+
+  // This overload handles monomorphic matchers.
+  //
+  // In general, if type T can be implicitly converted to type U, we can
+  // safely convert a Matcher<U> to a Matcher<T> (i.e. Matcher is
+  // contravariant): just keep a copy of the original Matcher<U>, convert the
+  // argument from type T to U, and then pass it to the underlying Matcher<U>.
+  // The only exception is when U is a reference and T is not, as the
+  // underlying Matcher<U> may be interested in the argument's address, which
+  // is not preserved in the conversion from T to U.
+  template <typename U>
+  static inline Matcher<T> Cast(const Matcher<U>& matcher) {
+    // Enforce that T can be implicitly converted to U.
+    GTEST_COMPILE_ASSERT_((internal::ImplicitlyConvertible<T, U>::value),
+                          T_must_be_implicitly_convertible_to_U);
+    // Enforce that we are not converting a non-reference type T to a reference
+    // type U.
+    GTEST_COMPILE_ASSERT_(
+        internal::is_reference<T>::value || !internal::is_reference<U>::value,
+        cannot_convert_non_referentce_arg_to_reference);
+    // In case both T and U are arithmetic types, enforce that the
+    // conversion is not lossy.
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(T) RawT;
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(U) RawU;
+    const bool kTIsOther = GMOCK_KIND_OF_(RawT) == internal::kOther;
+    const bool kUIsOther = GMOCK_KIND_OF_(RawU) == internal::kOther;
+    GTEST_COMPILE_ASSERT_(
+        kTIsOther || kUIsOther ||
+        (internal::LosslessArithmeticConvertible<RawT, RawU>::value),
+        conversion_of_arithmetic_types_must_be_lossless);
+    return MatcherCast<T>(matcher);
+  }
+};
+
+template <typename T, typename M>
+inline Matcher<T> SafeMatcherCast(const M& polymorphic_matcher) {
+  return SafeMatcherCastImpl<T>::Cast(polymorphic_matcher);
+}
+
+// A<T>() returns a matcher that matches any value of type T.
+template <typename T>
+Matcher<T> A();
+
+// Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION
+// and MUST NOT BE USED IN USER CODE!!!
+namespace internal {
+
+// If the explanation is not empty, prints it to the ostream.
+inline void PrintIfNotEmpty(const internal::string& explanation,
+                            ::std::ostream* os) {
+  if (explanation != "" && os != NULL) {
+    *os << ", " << explanation;
+  }
+}
+
+// Returns true if the given type name is easy to read by a human.
+// This is used to decide whether printing the type of a value might
+// be helpful.
+inline bool IsReadableTypeName(const string& type_name) {
+  // We consider a type name readable if it's short or doesn't contain
+  // a template or function type.
+  return (type_name.length() <= 20 ||
+          type_name.find_first_of("<(") == string::npos);
+}
+
+// Matches the value against the given matcher, prints the value and explains
+// the match result to the listener. Returns the match result.
+// 'listener' must not be NULL.
+// Value cannot be passed by const reference, because some matchers take a
+// non-const argument.
+template <typename Value, typename T>
+bool MatchPrintAndExplain(Value& value, const Matcher<T>& matcher,
+                          MatchResultListener* listener) {
+  if (!listener->IsInterested()) {
+    // If the listener is not interested, we do not need to construct the
+    // inner explanation.
+    return matcher.Matches(value);
+  }
+
+  StringMatchResultListener inner_listener;
+  const bool match = matcher.MatchAndExplain(value, &inner_listener);
+
+  UniversalPrint(value, listener->stream());
+#if GTEST_HAS_RTTI
+  const string& type_name = GetTypeName<Value>();
+  if (IsReadableTypeName(type_name))
+    *listener->stream() << " (of type " << type_name << ")";
+#endif
+  PrintIfNotEmpty(inner_listener.str(), listener->stream());
+
+  return match;
+}
+
+// An internal helper class for doing compile-time loop on a tuple's
+// fields.
+template <size_t N>
+class TuplePrefix {
+ public:
+  // TuplePrefix<N>::Matches(matcher_tuple, value_tuple) returns true
+  // iff the first N fields of matcher_tuple matches the first N
+  // fields of value_tuple, respectively.
+  template <typename MatcherTuple, typename ValueTuple>
+  static bool Matches(const MatcherTuple& matcher_tuple,
+                      const ValueTuple& value_tuple) {
+    return TuplePrefix<N - 1>::Matches(matcher_tuple, value_tuple)
+        && get<N - 1>(matcher_tuple).Matches(get<N - 1>(value_tuple));
+  }
+
+  // TuplePrefix<N>::ExplainMatchFailuresTo(matchers, values, os)
+  // describes failures in matching the first N fields of matchers
+  // against the first N fields of values.  If there is no failure,
+  // nothing will be streamed to os.
+  template <typename MatcherTuple, typename ValueTuple>
+  static void ExplainMatchFailuresTo(const MatcherTuple& matchers,
+                                     const ValueTuple& values,
+                                     ::std::ostream* os) {
+    // First, describes failures in the first N - 1 fields.
+    TuplePrefix<N - 1>::ExplainMatchFailuresTo(matchers, values, os);
+
+    // Then describes the failure (if any) in the (N - 1)-th (0-based)
+    // field.
+    typename tuple_element<N - 1, MatcherTuple>::type matcher =
+        get<N - 1>(matchers);
+    typedef typename tuple_element<N - 1, ValueTuple>::type Value;
+    Value value = get<N - 1>(values);
+    StringMatchResultListener listener;
+    if (!matcher.MatchAndExplain(value, &listener)) {
+      // TODO(wan): include in the message the name of the parameter
+      // as used in MOCK_METHOD*() when possible.
+      *os << "  Expected arg #" << N - 1 << ": ";
+      get<N - 1>(matchers).DescribeTo(os);
+      *os << "\n           Actual: ";
+      // We remove the reference in type Value to prevent the
+      // universal printer from printing the address of value, which
+      // isn't interesting to the user most of the time.  The
+      // matcher's MatchAndExplain() method handles the case when
+      // the address is interesting.
+      internal::UniversalPrint(value, os);
+      PrintIfNotEmpty(listener.str(), os);
+      *os << "\n";
+    }
+  }
+};
+
+// The base case.
+template <>
+class TuplePrefix<0> {
+ public:
+  template <typename MatcherTuple, typename ValueTuple>
+  static bool Matches(const MatcherTuple& /* matcher_tuple */,
+                      const ValueTuple& /* value_tuple */) {
+    return true;
+  }
+
+  template <typename MatcherTuple, typename ValueTuple>
+  static void ExplainMatchFailuresTo(const MatcherTuple& /* matchers */,
+                                     const ValueTuple& /* values */,
+                                     ::std::ostream* /* os */) {}
+};
+
+// TupleMatches(matcher_tuple, value_tuple) returns true iff all
+// matchers in matcher_tuple match the corresponding fields in
+// value_tuple.  It is a compiler error if matcher_tuple and
+// value_tuple have different number of fields or incompatible field
+// types.
+template <typename MatcherTuple, typename ValueTuple>
+bool TupleMatches(const MatcherTuple& matcher_tuple,
+                  const ValueTuple& value_tuple) {
+  // Makes sure that matcher_tuple and value_tuple have the same
+  // number of fields.
+  GTEST_COMPILE_ASSERT_(tuple_size<MatcherTuple>::value ==
+                        tuple_size<ValueTuple>::value,
+                        matcher_and_value_have_different_numbers_of_fields);
+  return TuplePrefix<tuple_size<ValueTuple>::value>::
+      Matches(matcher_tuple, value_tuple);
+}
+
+// Describes failures in matching matchers against values.  If there
+// is no failure, nothing will be streamed to os.
+template <typename MatcherTuple, typename ValueTuple>
+void ExplainMatchFailureTupleTo(const MatcherTuple& matchers,
+                                const ValueTuple& values,
+                                ::std::ostream* os) {
+  TuplePrefix<tuple_size<MatcherTuple>::value>::ExplainMatchFailuresTo(
+      matchers, values, os);
+}
+
+// TransformTupleValues and its helper.
+//
+// TransformTupleValuesHelper hides the internal machinery that
+// TransformTupleValues uses to implement a tuple traversal.
+template <typename Tuple, typename Func, typename OutIter>
+class TransformTupleValuesHelper {
+ private:
+  typedef ::testing::tuple_size<Tuple> TupleSize;
+
+ public:
+  // For each member of tuple 't', taken in order, evaluates '*out++ = f(t)'.
+  // Returns the final value of 'out' in case the caller needs it.
+  static OutIter Run(Func f, const Tuple& t, OutIter out) {
+    return IterateOverTuple<Tuple, TupleSize::value>()(f, t, out);
+  }
+
+ private:
+  template <typename Tup, size_t kRemainingSize>
+  struct IterateOverTuple {
+    OutIter operator() (Func f, const Tup& t, OutIter out) const {
+      *out++ = f(::testing::get<TupleSize::value - kRemainingSize>(t));
+      return IterateOverTuple<Tup, kRemainingSize - 1>()(f, t, out);
+    }
+  };
+  template <typename Tup>
+  struct IterateOverTuple<Tup, 0> {
+    OutIter operator() (Func /* f */, const Tup& /* t */, OutIter out) const {
+      return out;
+    }
+  };
+};
+
+// Successively invokes 'f(element)' on each element of the tuple 't',
+// appending each result to the 'out' iterator. Returns the final value
+// of 'out'.
+template <typename Tuple, typename Func, typename OutIter>
+OutIter TransformTupleValues(Func f, const Tuple& t, OutIter out) {
+  return TransformTupleValuesHelper<Tuple, Func, OutIter>::Run(f, t, out);
+}
+
+// Implements A<T>().
+template <typename T>
+class AnyMatcherImpl : public MatcherInterface<T> {
+ public:
+  virtual bool MatchAndExplain(
+      T /* x */, MatchResultListener* /* listener */) const { return true; }
+  virtual void DescribeTo(::std::ostream* os) const { *os << "is anything"; }
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    // This is mostly for completeness' safe, as it's not very useful
+    // to write Not(A<bool>()).  However we cannot completely rule out
+    // such a possibility, and it doesn't hurt to be prepared.
+    *os << "never matches";
+  }
+};
+
+// Implements _, a matcher that matches any value of any
+// type.  This is a polymorphic matcher, so we need a template type
+// conversion operator to make it appearing as a Matcher<T> for any
+// type T.
+class AnythingMatcher {
+ public:
+  template <typename T>
+  operator Matcher<T>() const { return A<T>(); }
+};
+
+// Implements a matcher that compares a given value with a
+// pre-supplied value using one of the ==, <=, <, etc, operators.  The
+// two values being compared don't have to have the same type.
+//
+// The matcher defined here is polymorphic (for example, Eq(5) can be
+// used to match an int, a short, a double, etc).  Therefore we use
+// a template type conversion operator in the implementation.
+//
+// The following template definition assumes that the Rhs parameter is
+// a "bare" type (i.e. neither 'const T' nor 'T&').
+template <typename D, typename Rhs, typename Op>
+class ComparisonBase {
+ public:
+  explicit ComparisonBase(const Rhs& rhs) : rhs_(rhs) {}
+  template <typename Lhs>
+  operator Matcher<Lhs>() const {
+    return MakeMatcher(new Impl<Lhs>(rhs_));
+  }
+
+ private:
+  template <typename Lhs>
+  class Impl : public MatcherInterface<Lhs> {
+   public:
+    explicit Impl(const Rhs& rhs) : rhs_(rhs) {}
+    virtual bool MatchAndExplain(
+        Lhs lhs, MatchResultListener* /* listener */) const {
+      return Op()(lhs, rhs_);
+    }
+    virtual void DescribeTo(::std::ostream* os) const {
+      *os << D::Desc() << " ";
+      UniversalPrint(rhs_, os);
+    }
+    virtual void DescribeNegationTo(::std::ostream* os) const {
+      *os << D::NegatedDesc() <<  " ";
+      UniversalPrint(rhs_, os);
+    }
+   private:
+    Rhs rhs_;
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+  Rhs rhs_;
+  GTEST_DISALLOW_ASSIGN_(ComparisonBase);
+};
+
+template <typename Rhs>
+class EqMatcher : public ComparisonBase<EqMatcher<Rhs>, Rhs, AnyEq> {
+ public:
+  explicit EqMatcher(const Rhs& rhs)
+      : ComparisonBase<EqMatcher<Rhs>, Rhs, AnyEq>(rhs) { }
+  static const char* Desc() { return "is equal to"; }
+  static const char* NegatedDesc() { return "isn't equal to"; }
+};
+template <typename Rhs>
+class NeMatcher : public ComparisonBase<NeMatcher<Rhs>, Rhs, AnyNe> {
+ public:
+  explicit NeMatcher(const Rhs& rhs)
+      : ComparisonBase<NeMatcher<Rhs>, Rhs, AnyNe>(rhs) { }
+  static const char* Desc() { return "isn't equal to"; }
+  static const char* NegatedDesc() { return "is equal to"; }
+};
+template <typename Rhs>
+class LtMatcher : public ComparisonBase<LtMatcher<Rhs>, Rhs, AnyLt> {
+ public:
+  explicit LtMatcher(const Rhs& rhs)
+      : ComparisonBase<LtMatcher<Rhs>, Rhs, AnyLt>(rhs) { }
+  static const char* Desc() { return "is <"; }
+  static const char* NegatedDesc() { return "isn't <"; }
+};
+template <typename Rhs>
+class GtMatcher : public ComparisonBase<GtMatcher<Rhs>, Rhs, AnyGt> {
+ public:
+  explicit GtMatcher(const Rhs& rhs)
+      : ComparisonBase<GtMatcher<Rhs>, Rhs, AnyGt>(rhs) { }
+  static const char* Desc() { return "is >"; }
+  static const char* NegatedDesc() { return "isn't >"; }
+};
+template <typename Rhs>
+class LeMatcher : public ComparisonBase<LeMatcher<Rhs>, Rhs, AnyLe> {
+ public:
+  explicit LeMatcher(const Rhs& rhs)
+      : ComparisonBase<LeMatcher<Rhs>, Rhs, AnyLe>(rhs) { }
+  static const char* Desc() { return "is <="; }
+  static const char* NegatedDesc() { return "isn't <="; }
+};
+template <typename Rhs>
+class GeMatcher : public ComparisonBase<GeMatcher<Rhs>, Rhs, AnyGe> {
+ public:
+  explicit GeMatcher(const Rhs& rhs)
+      : ComparisonBase<GeMatcher<Rhs>, Rhs, AnyGe>(rhs) { }
+  static const char* Desc() { return "is >="; }
+  static const char* NegatedDesc() { return "isn't >="; }
+};
+
+// Implements the polymorphic IsNull() matcher, which matches any raw or smart
+// pointer that is NULL.
+class IsNullMatcher {
+ public:
+  template <typename Pointer>
+  bool MatchAndExplain(const Pointer& p,
+                       MatchResultListener* /* listener */) const {
+#if GTEST_LANG_CXX11
+    return p == nullptr;
+#else  // GTEST_LANG_CXX11
+    return GetRawPointer(p) == NULL;
+#endif  // GTEST_LANG_CXX11
+  }
+
+  void DescribeTo(::std::ostream* os) const { *os << "is NULL"; }
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "isn't NULL";
+  }
+};
+
+// Implements the polymorphic NotNull() matcher, which matches any raw or smart
+// pointer that is not NULL.
+class NotNullMatcher {
+ public:
+  template <typename Pointer>
+  bool MatchAndExplain(const Pointer& p,
+                       MatchResultListener* /* listener */) const {
+#if GTEST_LANG_CXX11
+    return p != nullptr;
+#else  // GTEST_LANG_CXX11
+    return GetRawPointer(p) != NULL;
+#endif  // GTEST_LANG_CXX11
+  }
+
+  void DescribeTo(::std::ostream* os) const { *os << "isn't NULL"; }
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "is NULL";
+  }
+};
+
+// Ref(variable) matches any argument that is a reference to
+// 'variable'.  This matcher is polymorphic as it can match any
+// super type of the type of 'variable'.
+//
+// The RefMatcher template class implements Ref(variable).  It can
+// only be instantiated with a reference type.  This prevents a user
+// from mistakenly using Ref(x) to match a non-reference function
+// argument.  For example, the following will righteously cause a
+// compiler error:
+//
+//   int n;
+//   Matcher<int> m1 = Ref(n);   // This won't compile.
+//   Matcher<int&> m2 = Ref(n);  // This will compile.
+template <typename T>
+class RefMatcher;
+
+template <typename T>
+class RefMatcher<T&> {
+  // Google Mock is a generic framework and thus needs to support
+  // mocking any function types, including those that take non-const
+  // reference arguments.  Therefore the template parameter T (and
+  // Super below) can be instantiated to either a const type or a
+  // non-const type.
+ public:
+  // RefMatcher() takes a T& instead of const T&, as we want the
+  // compiler to catch using Ref(const_value) as a matcher for a
+  // non-const reference.
+  explicit RefMatcher(T& x) : object_(x) {}  // NOLINT
+
+  template <typename Super>
+  operator Matcher<Super&>() const {
+    // By passing object_ (type T&) to Impl(), which expects a Super&,
+    // we make sure that Super is a super type of T.  In particular,
+    // this catches using Ref(const_value) as a matcher for a
+    // non-const reference, as you cannot implicitly convert a const
+    // reference to a non-const reference.
+    return MakeMatcher(new Impl<Super>(object_));
+  }
+
+ private:
+  template <typename Super>
+  class Impl : public MatcherInterface<Super&> {
+   public:
+    explicit Impl(Super& x) : object_(x) {}  // NOLINT
+
+    // MatchAndExplain() takes a Super& (as opposed to const Super&)
+    // in order to match the interface MatcherInterface<Super&>.
+    virtual bool MatchAndExplain(
+        Super& x, MatchResultListener* listener) const {
+      *listener << "which is located @" << static_cast<const void*>(&x);
+      return &x == &object_;
+    }
+
+    virtual void DescribeTo(::std::ostream* os) const {
+      *os << "references the variable ";
+      UniversalPrinter<Super&>::Print(object_, os);
+    }
+
+    virtual void DescribeNegationTo(::std::ostream* os) const {
+      *os << "does not reference the variable ";
+      UniversalPrinter<Super&>::Print(object_, os);
+    }
+
+   private:
+    const Super& object_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+  T& object_;
+
+  GTEST_DISALLOW_ASSIGN_(RefMatcher);
+};
+
+// Polymorphic helper functions for narrow and wide string matchers.
+inline bool CaseInsensitiveCStringEquals(const char* lhs, const char* rhs) {
+  return String::CaseInsensitiveCStringEquals(lhs, rhs);
+}
+
+inline bool CaseInsensitiveCStringEquals(const wchar_t* lhs,
+                                         const wchar_t* rhs) {
+  return String::CaseInsensitiveWideCStringEquals(lhs, rhs);
+}
+
+// String comparison for narrow or wide strings that can have embedded NUL
+// characters.
+template <typename StringType>
+bool CaseInsensitiveStringEquals(const StringType& s1,
+                                 const StringType& s2) {
+  // Are the heads equal?
+  if (!CaseInsensitiveCStringEquals(s1.c_str(), s2.c_str())) {
+    return false;
+  }
+
+  // Skip the equal heads.
+  const typename StringType::value_type nul = 0;
+  const size_t i1 = s1.find(nul), i2 = s2.find(nul);
+
+  // Are we at the end of either s1 or s2?
+  if (i1 == StringType::npos || i2 == StringType::npos) {
+    return i1 == i2;
+  }
+
+  // Are the tails equal?
+  return CaseInsensitiveStringEquals(s1.substr(i1 + 1), s2.substr(i2 + 1));
+}
+
+// String matchers.
+
+// Implements equality-based string matchers like StrEq, StrCaseNe, and etc.
+template <typename StringType>
+class StrEqualityMatcher {
+ public:
+  StrEqualityMatcher(const StringType& str, bool expect_eq,
+                     bool case_sensitive)
+      : string_(str), expect_eq_(expect_eq), case_sensitive_(case_sensitive) {}
+
+  // Accepts pointer types, particularly:
+  //   const char*
+  //   char*
+  //   const wchar_t*
+  //   wchar_t*
+  template <typename CharType>
+  bool MatchAndExplain(CharType* s, MatchResultListener* listener) const {
+    if (s == NULL) {
+      return !expect_eq_;
+    }
+    return MatchAndExplain(StringType(s), listener);
+  }
+
+  // Matches anything that can convert to StringType.
+  //
+  // This is a template, not just a plain function with const StringType&,
+  // because StringPiece has some interfering non-explicit constructors.
+  template <typename MatcheeStringType>
+  bool MatchAndExplain(const MatcheeStringType& s,
+                       MatchResultListener* /* listener */) const {
+    const StringType& s2(s);
+    const bool eq = case_sensitive_ ? s2 == string_ :
+        CaseInsensitiveStringEquals(s2, string_);
+    return expect_eq_ == eq;
+  }
+
+  void DescribeTo(::std::ostream* os) const {
+    DescribeToHelper(expect_eq_, os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    DescribeToHelper(!expect_eq_, os);
+  }
+
+ private:
+  void DescribeToHelper(bool expect_eq, ::std::ostream* os) const {
+    *os << (expect_eq ? "is " : "isn't ");
+    *os << "equal to ";
+    if (!case_sensitive_) {
+      *os << "(ignoring case) ";
+    }
+    UniversalPrint(string_, os);
+  }
+
+  const StringType string_;
+  const bool expect_eq_;
+  const bool case_sensitive_;
+
+  GTEST_DISALLOW_ASSIGN_(StrEqualityMatcher);
+};
+
+// Implements the polymorphic HasSubstr(substring) matcher, which
+// can be used as a Matcher<T> as long as T can be converted to a
+// string.
+template <typename StringType>
+class HasSubstrMatcher {
+ public:
+  explicit HasSubstrMatcher(const StringType& substring)
+      : substring_(substring) {}
+
+  // Accepts pointer types, particularly:
+  //   const char*
+  //   char*
+  //   const wchar_t*
+  //   wchar_t*
+  template <typename CharType>
+  bool MatchAndExplain(CharType* s, MatchResultListener* listener) const {
+    return s != NULL && MatchAndExplain(StringType(s), listener);
+  }
+
+  // Matches anything that can convert to StringType.
+  //
+  // This is a template, not just a plain function with const StringType&,
+  // because StringPiece has some interfering non-explicit constructors.
+  template <typename MatcheeStringType>
+  bool MatchAndExplain(const MatcheeStringType& s,
+                       MatchResultListener* /* listener */) const {
+    const StringType& s2(s);
+    return s2.find(substring_) != StringType::npos;
+  }
+
+  // Describes what this matcher matches.
+  void DescribeTo(::std::ostream* os) const {
+    *os << "has substring ";
+    UniversalPrint(substring_, os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "has no substring ";
+    UniversalPrint(substring_, os);
+  }
+
+ private:
+  const StringType substring_;
+
+  GTEST_DISALLOW_ASSIGN_(HasSubstrMatcher);
+};
+
+// Implements the polymorphic StartsWith(substring) matcher, which
+// can be used as a Matcher<T> as long as T can be converted to a
+// string.
+template <typename StringType>
+class StartsWithMatcher {
+ public:
+  explicit StartsWithMatcher(const StringType& prefix) : prefix_(prefix) {
+  }
+
+  // Accepts pointer types, particularly:
+  //   const char*
+  //   char*
+  //   const wchar_t*
+  //   wchar_t*
+  template <typename CharType>
+  bool MatchAndExplain(CharType* s, MatchResultListener* listener) const {
+    return s != NULL && MatchAndExplain(StringType(s), listener);
+  }
+
+  // Matches anything that can convert to StringType.
+  //
+  // This is a template, not just a plain function with const StringType&,
+  // because StringPiece has some interfering non-explicit constructors.
+  template <typename MatcheeStringType>
+  bool MatchAndExplain(const MatcheeStringType& s,
+                       MatchResultListener* /* listener */) const {
+    const StringType& s2(s);
+    return s2.length() >= prefix_.length() &&
+        s2.substr(0, prefix_.length()) == prefix_;
+  }
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << "starts with ";
+    UniversalPrint(prefix_, os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "doesn't start with ";
+    UniversalPrint(prefix_, os);
+  }
+
+ private:
+  const StringType prefix_;
+
+  GTEST_DISALLOW_ASSIGN_(StartsWithMatcher);
+};
+
+// Implements the polymorphic EndsWith(substring) matcher, which
+// can be used as a Matcher<T> as long as T can be converted to a
+// string.
+template <typename StringType>
+class EndsWithMatcher {
+ public:
+  explicit EndsWithMatcher(const StringType& suffix) : suffix_(suffix) {}
+
+  // Accepts pointer types, particularly:
+  //   const char*
+  //   char*
+  //   const wchar_t*
+  //   wchar_t*
+  template <typename CharType>
+  bool MatchAndExplain(CharType* s, MatchResultListener* listener) const {
+    return s != NULL && MatchAndExplain(StringType(s), listener);
+  }
+
+  // Matches anything that can convert to StringType.
+  //
+  // This is a template, not just a plain function with const StringType&,
+  // because StringPiece has some interfering non-explicit constructors.
+  template <typename MatcheeStringType>
+  bool MatchAndExplain(const MatcheeStringType& s,
+                       MatchResultListener* /* listener */) const {
+    const StringType& s2(s);
+    return s2.length() >= suffix_.length() &&
+        s2.substr(s2.length() - suffix_.length()) == suffix_;
+  }
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << "ends with ";
+    UniversalPrint(suffix_, os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "doesn't end with ";
+    UniversalPrint(suffix_, os);
+  }
+
+ private:
+  const StringType suffix_;
+
+  GTEST_DISALLOW_ASSIGN_(EndsWithMatcher);
+};
+
+// Implements polymorphic matchers MatchesRegex(regex) and
+// ContainsRegex(regex), which can be used as a Matcher<T> as long as
+// T can be converted to a string.
+class MatchesRegexMatcher {
+ public:
+  MatchesRegexMatcher(const RE* regex, bool full_match)
+      : regex_(regex), full_match_(full_match) {}
+
+  // Accepts pointer types, particularly:
+  //   const char*
+  //   char*
+  //   const wchar_t*
+  //   wchar_t*
+  template <typename CharType>
+  bool MatchAndExplain(CharType* s, MatchResultListener* listener) const {
+    return s != NULL && MatchAndExplain(internal::string(s), listener);
+  }
+
+  // Matches anything that can convert to internal::string.
+  //
+  // This is a template, not just a plain function with const internal::string&,
+  // because StringPiece has some interfering non-explicit constructors.
+  template <class MatcheeStringType>
+  bool MatchAndExplain(const MatcheeStringType& s,
+                       MatchResultListener* /* listener */) const {
+    const internal::string& s2(s);
+    return full_match_ ? RE::FullMatch(s2, *regex_) :
+        RE::PartialMatch(s2, *regex_);
+  }
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << (full_match_ ? "matches" : "contains")
+        << " regular expression ";
+    UniversalPrinter<internal::string>::Print(regex_->pattern(), os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "doesn't " << (full_match_ ? "match" : "contain")
+        << " regular expression ";
+    UniversalPrinter<internal::string>::Print(regex_->pattern(), os);
+  }
+
+ private:
+  const internal::linked_ptr<const RE> regex_;
+  const bool full_match_;
+
+  GTEST_DISALLOW_ASSIGN_(MatchesRegexMatcher);
+};
+
+// Implements a matcher that compares the two fields of a 2-tuple
+// using one of the ==, <=, <, etc, operators.  The two fields being
+// compared don't have to have the same type.
+//
+// The matcher defined here is polymorphic (for example, Eq() can be
+// used to match a tuple<int, short>, a tuple<const long&, double>,
+// etc).  Therefore we use a template type conversion operator in the
+// implementation.
+template <typename D, typename Op>
+class PairMatchBase {
+ public:
+  template <typename T1, typename T2>
+  operator Matcher< ::testing::tuple<T1, T2> >() const {
+    return MakeMatcher(new Impl< ::testing::tuple<T1, T2> >);
+  }
+  template <typename T1, typename T2>
+  operator Matcher<const ::testing::tuple<T1, T2>&>() const {
+    return MakeMatcher(new Impl<const ::testing::tuple<T1, T2>&>);
+  }
+
+ private:
+  static ::std::ostream& GetDesc(::std::ostream& os) {  // NOLINT
+    return os << D::Desc();
+  }
+
+  template <typename Tuple>
+  class Impl : public MatcherInterface<Tuple> {
+   public:
+    virtual bool MatchAndExplain(
+        Tuple args,
+        MatchResultListener* /* listener */) const {
+      return Op()(::testing::get<0>(args), ::testing::get<1>(args));
+    }
+    virtual void DescribeTo(::std::ostream* os) const {
+      *os << "are " << GetDesc;
+    }
+    virtual void DescribeNegationTo(::std::ostream* os) const {
+      *os << "aren't " << GetDesc;
+    }
+  };
+};
+
+class Eq2Matcher : public PairMatchBase<Eq2Matcher, AnyEq> {
+ public:
+  static const char* Desc() { return "an equal pair"; }
+};
+class Ne2Matcher : public PairMatchBase<Ne2Matcher, AnyNe> {
+ public:
+  static const char* Desc() { return "an unequal pair"; }
+};
+class Lt2Matcher : public PairMatchBase<Lt2Matcher, AnyLt> {
+ public:
+  static const char* Desc() { return "a pair where the first < the second"; }
+};
+class Gt2Matcher : public PairMatchBase<Gt2Matcher, AnyGt> {
+ public:
+  static const char* Desc() { return "a pair where the first > the second"; }
+};
+class Le2Matcher : public PairMatchBase<Le2Matcher, AnyLe> {
+ public:
+  static const char* Desc() { return "a pair where the first <= the second"; }
+};
+class Ge2Matcher : public PairMatchBase<Ge2Matcher, AnyGe> {
+ public:
+  static const char* Desc() { return "a pair where the first >= the second"; }
+};
+
+// Implements the Not(...) matcher for a particular argument type T.
+// We do not nest it inside the NotMatcher class template, as that
+// will prevent different instantiations of NotMatcher from sharing
+// the same NotMatcherImpl<T> class.
+template <typename T>
+class NotMatcherImpl : public MatcherInterface<T> {
+ public:
+  explicit NotMatcherImpl(const Matcher<T>& matcher)
+      : matcher_(matcher) {}
+
+  virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
+    return !matcher_.MatchAndExplain(x, listener);
+  }
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    matcher_.DescribeNegationTo(os);
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    matcher_.DescribeTo(os);
+  }
+
+ private:
+  const Matcher<T> matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(NotMatcherImpl);
+};
+
+// Implements the Not(m) matcher, which matches a value that doesn't
+// match matcher m.
+template <typename InnerMatcher>
+class NotMatcher {
+ public:
+  explicit NotMatcher(InnerMatcher matcher) : matcher_(matcher) {}
+
+  // This template type conversion operator allows Not(m) to be used
+  // to match any type m can match.
+  template <typename T>
+  operator Matcher<T>() const {
+    return Matcher<T>(new NotMatcherImpl<T>(SafeMatcherCast<T>(matcher_)));
+  }
+
+ private:
+  InnerMatcher matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(NotMatcher);
+};
+
+// Implements the AllOf(m1, m2) matcher for a particular argument type
+// T. We do not nest it inside the BothOfMatcher class template, as
+// that will prevent different instantiations of BothOfMatcher from
+// sharing the same BothOfMatcherImpl<T> class.
+template <typename T>
+class BothOfMatcherImpl : public MatcherInterface<T> {
+ public:
+  BothOfMatcherImpl(const Matcher<T>& matcher1, const Matcher<T>& matcher2)
+      : matcher1_(matcher1), matcher2_(matcher2) {}
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "(";
+    matcher1_.DescribeTo(os);
+    *os << ") and (";
+    matcher2_.DescribeTo(os);
+    *os << ")";
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "(";
+    matcher1_.DescribeNegationTo(os);
+    *os << ") or (";
+    matcher2_.DescribeNegationTo(os);
+    *os << ")";
+  }
+
+  virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
+    // If either matcher1_ or matcher2_ doesn't match x, we only need
+    // to explain why one of them fails.
+    StringMatchResultListener listener1;
+    if (!matcher1_.MatchAndExplain(x, &listener1)) {
+      *listener << listener1.str();
+      return false;
+    }
+
+    StringMatchResultListener listener2;
+    if (!matcher2_.MatchAndExplain(x, &listener2)) {
+      *listener << listener2.str();
+      return false;
+    }
+
+    // Otherwise we need to explain why *both* of them match.
+    const internal::string s1 = listener1.str();
+    const internal::string s2 = listener2.str();
+
+    if (s1 == "") {
+      *listener << s2;
+    } else {
+      *listener << s1;
+      if (s2 != "") {
+        *listener << ", and " << s2;
+      }
+    }
+    return true;
+  }
+
+ private:
+  const Matcher<T> matcher1_;
+  const Matcher<T> matcher2_;
+
+  GTEST_DISALLOW_ASSIGN_(BothOfMatcherImpl);
+};
+
+#if GTEST_LANG_CXX11
+// MatcherList provides mechanisms for storing a variable number of matchers in
+// a list structure (ListType) and creating a combining matcher from such a
+// list.
+// The template is defined recursively using the following template paramters:
+//   * kSize is the length of the MatcherList.
+//   * Head is the type of the first matcher of the list.
+//   * Tail denotes the types of the remaining matchers of the list.
+template <int kSize, typename Head, typename... Tail>
+struct MatcherList {
+  typedef MatcherList<kSize - 1, Tail...> MatcherListTail;
+  typedef ::std::pair<Head, typename MatcherListTail::ListType> ListType;
+
+  // BuildList stores variadic type values in a nested pair structure.
+  // Example:
+  // MatcherList<3, int, string, float>::BuildList(5, "foo", 2.0) will return
+  // the corresponding result of type pair<int, pair<string, float>>.
+  static ListType BuildList(const Head& matcher, const Tail&... tail) {
+    return ListType(matcher, MatcherListTail::BuildList(tail...));
+  }
+
+  // CreateMatcher<T> creates a Matcher<T> from a given list of matchers (built
+  // by BuildList()). CombiningMatcher<T> is used to combine the matchers of the
+  // list. CombiningMatcher<T> must implement MatcherInterface<T> and have a
+  // constructor taking two Matcher<T>s as input.
+  template <typename T, template <typename /* T */> class CombiningMatcher>
+  static Matcher<T> CreateMatcher(const ListType& matchers) {
+    return Matcher<T>(new CombiningMatcher<T>(
+        SafeMatcherCast<T>(matchers.first),
+        MatcherListTail::template CreateMatcher<T, CombiningMatcher>(
+            matchers.second)));
+  }
+};
+
+// The following defines the base case for the recursive definition of
+// MatcherList.
+template <typename Matcher1, typename Matcher2>
+struct MatcherList<2, Matcher1, Matcher2> {
+  typedef ::std::pair<Matcher1, Matcher2> ListType;
+
+  static ListType BuildList(const Matcher1& matcher1,
+                            const Matcher2& matcher2) {
+    return ::std::pair<Matcher1, Matcher2>(matcher1, matcher2);
+  }
+
+  template <typename T, template <typename /* T */> class CombiningMatcher>
+  static Matcher<T> CreateMatcher(const ListType& matchers) {
+    return Matcher<T>(new CombiningMatcher<T>(
+        SafeMatcherCast<T>(matchers.first),
+        SafeMatcherCast<T>(matchers.second)));
+  }
+};
+
+// VariadicMatcher is used for the variadic implementation of
+// AllOf(m_1, m_2, ...) and AnyOf(m_1, m_2, ...).
+// CombiningMatcher<T> is used to recursively combine the provided matchers
+// (of type Args...).
+template <template <typename T> class CombiningMatcher, typename... Args>
+class VariadicMatcher {
+ public:
+  VariadicMatcher(const Args&... matchers)  // NOLINT
+      : matchers_(MatcherListType::BuildList(matchers...)) {}
+
+  // This template type conversion operator allows an
+  // VariadicMatcher<Matcher1, Matcher2...> object to match any type that
+  // all of the provided matchers (Matcher1, Matcher2, ...) can match.
+  template <typename T>
+  operator Matcher<T>() const {
+    return MatcherListType::template CreateMatcher<T, CombiningMatcher>(
+        matchers_);
+  }
+
+ private:
+  typedef MatcherList<sizeof...(Args), Args...> MatcherListType;
+
+  const typename MatcherListType::ListType matchers_;
+
+  GTEST_DISALLOW_ASSIGN_(VariadicMatcher);
+};
+
+template <typename... Args>
+using AllOfMatcher = VariadicMatcher<BothOfMatcherImpl, Args...>;
+
+#endif  // GTEST_LANG_CXX11
+
+// Used for implementing the AllOf(m_1, ..., m_n) matcher, which
+// matches a value that matches all of the matchers m_1, ..., and m_n.
+template <typename Matcher1, typename Matcher2>
+class BothOfMatcher {
+ public:
+  BothOfMatcher(Matcher1 matcher1, Matcher2 matcher2)
+      : matcher1_(matcher1), matcher2_(matcher2) {}
+
+  // This template type conversion operator allows a
+  // BothOfMatcher<Matcher1, Matcher2> object to match any type that
+  // both Matcher1 and Matcher2 can match.
+  template <typename T>
+  operator Matcher<T>() const {
+    return Matcher<T>(new BothOfMatcherImpl<T>(SafeMatcherCast<T>(matcher1_),
+                                               SafeMatcherCast<T>(matcher2_)));
+  }
+
+ private:
+  Matcher1 matcher1_;
+  Matcher2 matcher2_;
+
+  GTEST_DISALLOW_ASSIGN_(BothOfMatcher);
+};
+
+// Implements the AnyOf(m1, m2) matcher for a particular argument type
+// T.  We do not nest it inside the AnyOfMatcher class template, as
+// that will prevent different instantiations of AnyOfMatcher from
+// sharing the same EitherOfMatcherImpl<T> class.
+template <typename T>
+class EitherOfMatcherImpl : public MatcherInterface<T> {
+ public:
+  EitherOfMatcherImpl(const Matcher<T>& matcher1, const Matcher<T>& matcher2)
+      : matcher1_(matcher1), matcher2_(matcher2) {}
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "(";
+    matcher1_.DescribeTo(os);
+    *os << ") or (";
+    matcher2_.DescribeTo(os);
+    *os << ")";
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "(";
+    matcher1_.DescribeNegationTo(os);
+    *os << ") and (";
+    matcher2_.DescribeNegationTo(os);
+    *os << ")";
+  }
+
+  virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
+    // If either matcher1_ or matcher2_ matches x, we just need to
+    // explain why *one* of them matches.
+    StringMatchResultListener listener1;
+    if (matcher1_.MatchAndExplain(x, &listener1)) {
+      *listener << listener1.str();
+      return true;
+    }
+
+    StringMatchResultListener listener2;
+    if (matcher2_.MatchAndExplain(x, &listener2)) {
+      *listener << listener2.str();
+      return true;
+    }
+
+    // Otherwise we need to explain why *both* of them fail.
+    const internal::string s1 = listener1.str();
+    const internal::string s2 = listener2.str();
+
+    if (s1 == "") {
+      *listener << s2;
+    } else {
+      *listener << s1;
+      if (s2 != "") {
+        *listener << ", and " << s2;
+      }
+    }
+    return false;
+  }
+
+ private:
+  const Matcher<T> matcher1_;
+  const Matcher<T> matcher2_;
+
+  GTEST_DISALLOW_ASSIGN_(EitherOfMatcherImpl);
+};
+
+#if GTEST_LANG_CXX11
+// AnyOfMatcher is used for the variadic implementation of AnyOf(m_1, m_2, ...).
+template <typename... Args>
+using AnyOfMatcher = VariadicMatcher<EitherOfMatcherImpl, Args...>;
+
+#endif  // GTEST_LANG_CXX11
+
+// Used for implementing the AnyOf(m_1, ..., m_n) matcher, which
+// matches a value that matches at least one of the matchers m_1, ...,
+// and m_n.
+template <typename Matcher1, typename Matcher2>
+class EitherOfMatcher {
+ public:
+  EitherOfMatcher(Matcher1 matcher1, Matcher2 matcher2)
+      : matcher1_(matcher1), matcher2_(matcher2) {}
+
+  // This template type conversion operator allows a
+  // EitherOfMatcher<Matcher1, Matcher2> object to match any type that
+  // both Matcher1 and Matcher2 can match.
+  template <typename T>
+  operator Matcher<T>() const {
+    return Matcher<T>(new EitherOfMatcherImpl<T>(
+        SafeMatcherCast<T>(matcher1_), SafeMatcherCast<T>(matcher2_)));
+  }
+
+ private:
+  Matcher1 matcher1_;
+  Matcher2 matcher2_;
+
+  GTEST_DISALLOW_ASSIGN_(EitherOfMatcher);
+};
+
+// Used for implementing Truly(pred), which turns a predicate into a
+// matcher.
+template <typename Predicate>
+class TrulyMatcher {
+ public:
+  explicit TrulyMatcher(Predicate pred) : predicate_(pred) {}
+
+  // This method template allows Truly(pred) to be used as a matcher
+  // for type T where T is the argument type of predicate 'pred'.  The
+  // argument is passed by reference as the predicate may be
+  // interested in the address of the argument.
+  template <typename T>
+  bool MatchAndExplain(T& x,  // NOLINT
+                       MatchResultListener* /* listener */) const {
+    // Without the if-statement, MSVC sometimes warns about converting
+    // a value to bool (warning 4800).
+    //
+    // We cannot write 'return !!predicate_(x);' as that doesn't work
+    // when predicate_(x) returns a class convertible to bool but
+    // having no operator!().
+    if (predicate_(x))
+      return true;
+    return false;
+  }
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << "satisfies the given predicate";
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "doesn't satisfy the given predicate";
+  }
+
+ private:
+  Predicate predicate_;
+
+  GTEST_DISALLOW_ASSIGN_(TrulyMatcher);
+};
+
+// Used for implementing Matches(matcher), which turns a matcher into
+// a predicate.
+template <typename M>
+class MatcherAsPredicate {
+ public:
+  explicit MatcherAsPredicate(M matcher) : matcher_(matcher) {}
+
+  // This template operator() allows Matches(m) to be used as a
+  // predicate on type T where m is a matcher on type T.
+  //
+  // The argument x is passed by reference instead of by value, as
+  // some matcher may be interested in its address (e.g. as in
+  // Matches(Ref(n))(x)).
+  template <typename T>
+  bool operator()(const T& x) const {
+    // We let matcher_ commit to a particular type here instead of
+    // when the MatcherAsPredicate object was constructed.  This
+    // allows us to write Matches(m) where m is a polymorphic matcher
+    // (e.g. Eq(5)).
+    //
+    // If we write Matcher<T>(matcher_).Matches(x) here, it won't
+    // compile when matcher_ has type Matcher<const T&>; if we write
+    // Matcher<const T&>(matcher_).Matches(x) here, it won't compile
+    // when matcher_ has type Matcher<T>; if we just write
+    // matcher_.Matches(x), it won't compile when matcher_ is
+    // polymorphic, e.g. Eq(5).
+    //
+    // MatcherCast<const T&>() is necessary for making the code work
+    // in all of the above situations.
+    return MatcherCast<const T&>(matcher_).Matches(x);
+  }
+
+ private:
+  M matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(MatcherAsPredicate);
+};
+
+// For implementing ASSERT_THAT() and EXPECT_THAT().  The template
+// argument M must be a type that can be converted to a matcher.
+template <typename M>
+class PredicateFormatterFromMatcher {
+ public:
+  explicit PredicateFormatterFromMatcher(M m) : matcher_(internal::move(m)) {}
+
+  // This template () operator allows a PredicateFormatterFromMatcher
+  // object to act as a predicate-formatter suitable for using with
+  // Google Test's EXPECT_PRED_FORMAT1() macro.
+  template <typename T>
+  AssertionResult operator()(const char* value_text, const T& x) const {
+    // We convert matcher_ to a Matcher<const T&> *now* instead of
+    // when the PredicateFormatterFromMatcher object was constructed,
+    // as matcher_ may be polymorphic (e.g. NotNull()) and we won't
+    // know which type to instantiate it to until we actually see the
+    // type of x here.
+    //
+    // We write SafeMatcherCast<const T&>(matcher_) instead of
+    // Matcher<const T&>(matcher_), as the latter won't compile when
+    // matcher_ has type Matcher<T> (e.g. An<int>()).
+    // We don't write MatcherCast<const T&> either, as that allows
+    // potentially unsafe downcasting of the matcher argument.
+    const Matcher<const T&> matcher = SafeMatcherCast<const T&>(matcher_);
+    StringMatchResultListener listener;
+    if (MatchPrintAndExplain(x, matcher, &listener))
+      return AssertionSuccess();
+
+    ::std::stringstream ss;
+    ss << "Value of: " << value_text << "\n"
+       << "Expected: ";
+    matcher.DescribeTo(&ss);
+    ss << "\n  Actual: " << listener.str();
+    return AssertionFailure() << ss.str();
+  }
+
+ private:
+  const M matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(PredicateFormatterFromMatcher);
+};
+
+// A helper function for converting a matcher to a predicate-formatter
+// without the user needing to explicitly write the type.  This is
+// used for implementing ASSERT_THAT() and EXPECT_THAT().
+// Implementation detail: 'matcher' is received by-value to force decaying.
+template <typename M>
+inline PredicateFormatterFromMatcher<M>
+MakePredicateFormatterFromMatcher(M matcher) {
+  return PredicateFormatterFromMatcher<M>(internal::move(matcher));
+}
+
+// Implements the polymorphic floating point equality matcher, which matches
+// two float values using ULP-based approximation or, optionally, a
+// user-specified epsilon.  The template is meant to be instantiated with
+// FloatType being either float or double.
+template <typename FloatType>
+class FloatingEqMatcher {
+ public:
+  // Constructor for FloatingEqMatcher.
+  // The matcher's input will be compared with expected.  The matcher treats two
+  // NANs as equal if nan_eq_nan is true.  Otherwise, under IEEE standards,
+  // equality comparisons between NANs will always return false.  We specify a
+  // negative max_abs_error_ term to indicate that ULP-based approximation will
+  // be used for comparison.
+  FloatingEqMatcher(FloatType expected, bool nan_eq_nan) :
+    expected_(expected), nan_eq_nan_(nan_eq_nan), max_abs_error_(-1) {
+  }
+
+  // Constructor that supports a user-specified max_abs_error that will be used
+  // for comparison instead of ULP-based approximation.  The max absolute
+  // should be non-negative.
+  FloatingEqMatcher(FloatType expected, bool nan_eq_nan,
+                    FloatType max_abs_error)
+      : expected_(expected),
+        nan_eq_nan_(nan_eq_nan),
+        max_abs_error_(max_abs_error) {
+    GTEST_CHECK_(max_abs_error >= 0)
+        << ", where max_abs_error is" << max_abs_error;
+  }
+
+  // Implements floating point equality matcher as a Matcher<T>.
+  template <typename T>
+  class Impl : public MatcherInterface<T> {
+   public:
+    Impl(FloatType expected, bool nan_eq_nan, FloatType max_abs_error)
+        : expected_(expected),
+          nan_eq_nan_(nan_eq_nan),
+          max_abs_error_(max_abs_error) {}
+
+    virtual bool MatchAndExplain(T value,
+                                 MatchResultListener* listener) const {
+      const FloatingPoint<FloatType> actual(value), expected(expected_);
+
+      // Compares NaNs first, if nan_eq_nan_ is true.
+      if (actual.is_nan() || expected.is_nan()) {
+        if (actual.is_nan() && expected.is_nan()) {
+          return nan_eq_nan_;
+        }
+        // One is nan; the other is not nan.
+        return false;
+      }
+      if (HasMaxAbsError()) {
+        // We perform an equality check so that inf will match inf, regardless
+        // of error bounds.  If the result of value - expected_ would result in
+        // overflow or if either value is inf, the default result is infinity,
+        // which should only match if max_abs_error_ is also infinity.
+        if (value == expected_) {
+          return true;
+        }
+
+        const FloatType diff = value - expected_;
+        if (fabs(diff) <= max_abs_error_) {
+          return true;
+        }
+
+        if (listener->IsInterested()) {
+          *listener << "which is " << diff << " from " << expected_;
+        }
+        return false;
+      } else {
+        return actual.AlmostEquals(expected);
+      }
+    }
+
+    virtual void DescribeTo(::std::ostream* os) const {
+      // os->precision() returns the previously set precision, which we
+      // store to restore the ostream to its original configuration
+      // after outputting.
+      const ::std::streamsize old_precision = os->precision(
+          ::std::numeric_limits<FloatType>::digits10 + 2);
+      if (FloatingPoint<FloatType>(expected_).is_nan()) {
+        if (nan_eq_nan_) {
+          *os << "is NaN";
+        } else {
+          *os << "never matches";
+        }
+      } else {
+        *os << "is approximately " << expected_;
+        if (HasMaxAbsError()) {
+          *os << " (absolute error <= " << max_abs_error_ << ")";
+        }
+      }
+      os->precision(old_precision);
+    }
+
+    virtual void DescribeNegationTo(::std::ostream* os) const {
+      // As before, get original precision.
+      const ::std::streamsize old_precision = os->precision(
+          ::std::numeric_limits<FloatType>::digits10 + 2);
+      if (FloatingPoint<FloatType>(expected_).is_nan()) {
+        if (nan_eq_nan_) {
+          *os << "isn't NaN";
+        } else {
+          *os << "is anything";
+        }
+      } else {
+        *os << "isn't approximately " << expected_;
+        if (HasMaxAbsError()) {
+          *os << " (absolute error > " << max_abs_error_ << ")";
+        }
+      }
+      // Restore original precision.
+      os->precision(old_precision);
+    }
+
+   private:
+    bool HasMaxAbsError() const {
+      return max_abs_error_ >= 0;
+    }
+
+    const FloatType expected_;
+    const bool nan_eq_nan_;
+    // max_abs_error will be used for value comparison when >= 0.
+    const FloatType max_abs_error_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+  // The following 3 type conversion operators allow FloatEq(expected) and
+  // NanSensitiveFloatEq(expected) to be used as a Matcher<float>, a
+  // Matcher<const float&>, or a Matcher<float&>, but nothing else.
+  // (While Google's C++ coding style doesn't allow arguments passed
+  // by non-const reference, we may see them in code not conforming to
+  // the style.  Therefore Google Mock needs to support them.)
+  operator Matcher<FloatType>() const {
+    return MakeMatcher(
+        new Impl<FloatType>(expected_, nan_eq_nan_, max_abs_error_));
+  }
+
+  operator Matcher<const FloatType&>() const {
+    return MakeMatcher(
+        new Impl<const FloatType&>(expected_, nan_eq_nan_, max_abs_error_));
+  }
+
+  operator Matcher<FloatType&>() const {
+    return MakeMatcher(
+        new Impl<FloatType&>(expected_, nan_eq_nan_, max_abs_error_));
+  }
+
+ private:
+  const FloatType expected_;
+  const bool nan_eq_nan_;
+  // max_abs_error will be used for value comparison when >= 0.
+  const FloatType max_abs_error_;
+
+  GTEST_DISALLOW_ASSIGN_(FloatingEqMatcher);
+};
+
+// Implements the Pointee(m) matcher for matching a pointer whose
+// pointee matches matcher m.  The pointer can be either raw or smart.
+template <typename InnerMatcher>
+class PointeeMatcher {
+ public:
+  explicit PointeeMatcher(const InnerMatcher& matcher) : matcher_(matcher) {}
+
+  // This type conversion operator template allows Pointee(m) to be
+  // used as a matcher for any pointer type whose pointee type is
+  // compatible with the inner matcher, where type Pointer can be
+  // either a raw pointer or a smart pointer.
+  //
+  // The reason we do this instead of relying on
+  // MakePolymorphicMatcher() is that the latter is not flexible
+  // enough for implementing the DescribeTo() method of Pointee().
+  template <typename Pointer>
+  operator Matcher<Pointer>() const {
+    return MakeMatcher(new Impl<Pointer>(matcher_));
+  }
+
+ private:
+  // The monomorphic implementation that works for a particular pointer type.
+  template <typename Pointer>
+  class Impl : public MatcherInterface<Pointer> {
+   public:
+    typedef typename PointeeOf<GTEST_REMOVE_CONST_(  // NOLINT
+        GTEST_REMOVE_REFERENCE_(Pointer))>::type Pointee;
+
+    explicit Impl(const InnerMatcher& matcher)
+        : matcher_(MatcherCast<const Pointee&>(matcher)) {}
+
+    virtual void DescribeTo(::std::ostream* os) const {
+      *os << "points to a value that ";
+      matcher_.DescribeTo(os);
+    }
+
+    virtual void DescribeNegationTo(::std::ostream* os) const {
+      *os << "does not point to a value that ";
+      matcher_.DescribeTo(os);
+    }
+
+    virtual bool MatchAndExplain(Pointer pointer,
+                                 MatchResultListener* listener) const {
+      if (GetRawPointer(pointer) == NULL)
+        return false;
+
+      *listener << "which points to ";
+      return MatchPrintAndExplain(*pointer, matcher_, listener);
+    }
+
+   private:
+    const Matcher<const Pointee&> matcher_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+  const InnerMatcher matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(PointeeMatcher);
+};
+
+// Implements the WhenDynamicCastTo<T>(m) matcher that matches a pointer or
+// reference that matches inner_matcher when dynamic_cast<T> is applied.
+// The result of dynamic_cast<To> is forwarded to the inner matcher.
+// If To is a pointer and the cast fails, the inner matcher will receive NULL.
+// If To is a reference and the cast fails, this matcher returns false
+// immediately.
+template <typename To>
+class WhenDynamicCastToMatcherBase {
+ public:
+  explicit WhenDynamicCastToMatcherBase(const Matcher<To>& matcher)
+      : matcher_(matcher) {}
+
+  void DescribeTo(::std::ostream* os) const {
+    GetCastTypeDescription(os);
+    matcher_.DescribeTo(os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    GetCastTypeDescription(os);
+    matcher_.DescribeNegationTo(os);
+  }
+
+ protected:
+  const Matcher<To> matcher_;
+
+  static string GetToName() {
+#if GTEST_HAS_RTTI
+    return GetTypeName<To>();
+#else  // GTEST_HAS_RTTI
+    return "the target type";
+#endif  // GTEST_HAS_RTTI
+  }
+
+ private:
+  static void GetCastTypeDescription(::std::ostream* os) {
+    *os << "when dynamic_cast to " << GetToName() << ", ";
+  }
+
+  GTEST_DISALLOW_ASSIGN_(WhenDynamicCastToMatcherBase);
+};
+
+// Primary template.
+// To is a pointer. Cast and forward the result.
+template <typename To>
+class WhenDynamicCastToMatcher : public WhenDynamicCastToMatcherBase<To> {
+ public:
+  explicit WhenDynamicCastToMatcher(const Matcher<To>& matcher)
+      : WhenDynamicCastToMatcherBase<To>(matcher) {}
+
+  template <typename From>
+  bool MatchAndExplain(From from, MatchResultListener* listener) const {
+    // TODO(sbenza): Add more detail on failures. ie did the dyn_cast fail?
+    To to = dynamic_cast<To>(from);
+    return MatchPrintAndExplain(to, this->matcher_, listener);
+  }
+};
+
+// Specialize for references.
+// In this case we return false if the dynamic_cast fails.
+template <typename To>
+class WhenDynamicCastToMatcher<To&> : public WhenDynamicCastToMatcherBase<To&> {
+ public:
+  explicit WhenDynamicCastToMatcher(const Matcher<To&>& matcher)
+      : WhenDynamicCastToMatcherBase<To&>(matcher) {}
+
+  template <typename From>
+  bool MatchAndExplain(From& from, MatchResultListener* listener) const {
+    // We don't want an std::bad_cast here, so do the cast with pointers.
+    To* to = dynamic_cast<To*>(&from);
+    if (to == NULL) {
+      *listener << "which cannot be dynamic_cast to " << this->GetToName();
+      return false;
+    }
+    return MatchPrintAndExplain(*to, this->matcher_, listener);
+  }
+};
+
+// Implements the Field() matcher for matching a field (i.e. member
+// variable) of an object.
+template <typename Class, typename FieldType>
+class FieldMatcher {
+ public:
+  FieldMatcher(FieldType Class::*field,
+               const Matcher<const FieldType&>& matcher)
+      : field_(field), matcher_(matcher) {}
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << "is an object whose given field ";
+    matcher_.DescribeTo(os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "is an object whose given field ";
+    matcher_.DescribeNegationTo(os);
+  }
+
+  template <typename T>
+  bool MatchAndExplain(const T& value, MatchResultListener* listener) const {
+    return MatchAndExplainImpl(
+        typename ::testing::internal::
+            is_pointer<GTEST_REMOVE_CONST_(T)>::type(),
+        value, listener);
+  }
+
+ private:
+  // The first argument of MatchAndExplainImpl() is needed to help
+  // Symbian's C++ compiler choose which overload to use.  Its type is
+  // true_type iff the Field() matcher is used to match a pointer.
+  bool MatchAndExplainImpl(false_type /* is_not_pointer */, const Class& obj,
+                           MatchResultListener* listener) const {
+    *listener << "whose given field is ";
+    return MatchPrintAndExplain(obj.*field_, matcher_, listener);
+  }
+
+  bool MatchAndExplainImpl(true_type /* is_pointer */, const Class* p,
+                           MatchResultListener* listener) const {
+    if (p == NULL)
+      return false;
+
+    *listener << "which points to an object ";
+    // Since *p has a field, it must be a class/struct/union type and
+    // thus cannot be a pointer.  Therefore we pass false_type() as
+    // the first argument.
+    return MatchAndExplainImpl(false_type(), *p, listener);
+  }
+
+  const FieldType Class::*field_;
+  const Matcher<const FieldType&> matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(FieldMatcher);
+};
+
+// Implements the Property() matcher for matching a property
+// (i.e. return value of a getter method) of an object.
+template <typename Class, typename PropertyType>
+class PropertyMatcher {
+ public:
+  // The property may have a reference type, so 'const PropertyType&'
+  // may cause double references and fail to compile.  That's why we
+  // need GTEST_REFERENCE_TO_CONST, which works regardless of
+  // PropertyType being a reference or not.
+  typedef GTEST_REFERENCE_TO_CONST_(PropertyType) RefToConstProperty;
+
+  PropertyMatcher(PropertyType (Class::*property)() const,
+                  const Matcher<RefToConstProperty>& matcher)
+      : property_(property), matcher_(matcher) {}
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << "is an object whose given property ";
+    matcher_.DescribeTo(os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "is an object whose given property ";
+    matcher_.DescribeNegationTo(os);
+  }
+
+  template <typename T>
+  bool MatchAndExplain(const T&value, MatchResultListener* listener) const {
+    return MatchAndExplainImpl(
+        typename ::testing::internal::
+            is_pointer<GTEST_REMOVE_CONST_(T)>::type(),
+        value, listener);
+  }
+
+ private:
+  // The first argument of MatchAndExplainImpl() is needed to help
+  // Symbian's C++ compiler choose which overload to use.  Its type is
+  // true_type iff the Property() matcher is used to match a pointer.
+  bool MatchAndExplainImpl(false_type /* is_not_pointer */, const Class& obj,
+                           MatchResultListener* listener) const {
+    *listener << "whose given property is ";
+    // Cannot pass the return value (for example, int) to MatchPrintAndExplain,
+    // which takes a non-const reference as argument.
+#if defined(_PREFAST_ ) && _MSC_VER == 1800
+    // Workaround bug in VC++ 2013's /analyze parser.
+    // https://connect.microsoft.com/VisualStudio/feedback/details/1106363/internal-compiler-error-with-analyze-due-to-failure-to-infer-move
+    posix::Abort();  // To make sure it is never run.
+    return false;
+#else
+    RefToConstProperty result = (obj.*property_)();
+    return MatchPrintAndExplain(result, matcher_, listener);
+#endif
+  }
+
+  bool MatchAndExplainImpl(true_type /* is_pointer */, const Class* p,
+                           MatchResultListener* listener) const {
+    if (p == NULL)
+      return false;
+
+    *listener << "which points to an object ";
+    // Since *p has a property method, it must be a class/struct/union
+    // type and thus cannot be a pointer.  Therefore we pass
+    // false_type() as the first argument.
+    return MatchAndExplainImpl(false_type(), *p, listener);
+  }
+
+  PropertyType (Class::*property_)() const;
+  const Matcher<RefToConstProperty> matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(PropertyMatcher);
+};
+
+// Type traits specifying various features of different functors for ResultOf.
+// The default template specifies features for functor objects.
+// Functor classes have to typedef argument_type and result_type
+// to be compatible with ResultOf.
+template <typename Functor>
+struct CallableTraits {
+  typedef typename Functor::result_type ResultType;
+  typedef Functor StorageType;
+
+  static void CheckIsValid(Functor /* functor */) {}
+  template <typename T>
+  static ResultType Invoke(Functor f, T arg) { return f(arg); }
+};
+
+// Specialization for function pointers.
+template <typename ArgType, typename ResType>
+struct CallableTraits<ResType(*)(ArgType)> {
+  typedef ResType ResultType;
+  typedef ResType(*StorageType)(ArgType);
+
+  static void CheckIsValid(ResType(*f)(ArgType)) {
+    GTEST_CHECK_(f != NULL)
+        << "NULL function pointer is passed into ResultOf().";
+  }
+  template <typename T>
+  static ResType Invoke(ResType(*f)(ArgType), T arg) {
+    return (*f)(arg);
+  }
+};
+
+// Implements the ResultOf() matcher for matching a return value of a
+// unary function of an object.
+template <typename Callable>
+class ResultOfMatcher {
+ public:
+  typedef typename CallableTraits<Callable>::ResultType ResultType;
+
+  ResultOfMatcher(Callable callable, const Matcher<ResultType>& matcher)
+      : callable_(callable), matcher_(matcher) {
+    CallableTraits<Callable>::CheckIsValid(callable_);
+  }
+
+  template <typename T>
+  operator Matcher<T>() const {
+    return Matcher<T>(new Impl<T>(callable_, matcher_));
+  }
+
+ private:
+  typedef typename CallableTraits<Callable>::StorageType CallableStorageType;
+
+  template <typename T>
+  class Impl : public MatcherInterface<T> {
+   public:
+    Impl(CallableStorageType callable, const Matcher<ResultType>& matcher)
+        : callable_(callable), matcher_(matcher) {}
+
+    virtual void DescribeTo(::std::ostream* os) const {
+      *os << "is mapped by the given callable to a value that ";
+      matcher_.DescribeTo(os);
+    }
+
+    virtual void DescribeNegationTo(::std::ostream* os) const {
+      *os << "is mapped by the given callable to a value that ";
+      matcher_.DescribeNegationTo(os);
+    }
+
+    virtual bool MatchAndExplain(T obj, MatchResultListener* listener) const {
+      *listener << "which is mapped by the given callable to ";
+      // Cannot pass the return value (for example, int) to
+      // MatchPrintAndExplain, which takes a non-const reference as argument.
+      ResultType result =
+          CallableTraits<Callable>::template Invoke<T>(callable_, obj);
+      return MatchPrintAndExplain(result, matcher_, listener);
+    }
+
+   private:
+    // Functors often define operator() as non-const method even though
+    // they are actualy stateless. But we need to use them even when
+    // 'this' is a const pointer. It's the user's responsibility not to
+    // use stateful callables with ResultOf(), which does't guarantee
+    // how many times the callable will be invoked.
+    mutable CallableStorageType callable_;
+    const Matcher<ResultType> matcher_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };  // class Impl
+
+  const CallableStorageType callable_;
+  const Matcher<ResultType> matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(ResultOfMatcher);
+};
+
+// Implements a matcher that checks the size of an STL-style container.
+template <typename SizeMatcher>
+class SizeIsMatcher {
+ public:
+  explicit SizeIsMatcher(const SizeMatcher& size_matcher)
+       : size_matcher_(size_matcher) {
+  }
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    return MakeMatcher(new Impl<Container>(size_matcher_));
+  }
+
+  template <typename Container>
+  class Impl : public MatcherInterface<Container> {
+   public:
+    typedef internal::StlContainerView<
+         GTEST_REMOVE_REFERENCE_AND_CONST_(Container)> ContainerView;
+    typedef typename ContainerView::type::size_type SizeType;
+    explicit Impl(const SizeMatcher& size_matcher)
+        : size_matcher_(MatcherCast<SizeType>(size_matcher)) {}
+
+    virtual void DescribeTo(::std::ostream* os) const {
+      *os << "size ";
+      size_matcher_.DescribeTo(os);
+    }
+    virtual void DescribeNegationTo(::std::ostream* os) const {
+      *os << "size ";
+      size_matcher_.DescribeNegationTo(os);
+    }
+
+    virtual bool MatchAndExplain(Container container,
+                                 MatchResultListener* listener) const {
+      SizeType size = container.size();
+      StringMatchResultListener size_listener;
+      const bool result = size_matcher_.MatchAndExplain(size, &size_listener);
+      *listener
+          << "whose size " << size << (result ? " matches" : " doesn't match");
+      PrintIfNotEmpty(size_listener.str(), listener->stream());
+      return result;
+    }
+
+   private:
+    const Matcher<SizeType> size_matcher_;
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+ private:
+  const SizeMatcher size_matcher_;
+  GTEST_DISALLOW_ASSIGN_(SizeIsMatcher);
+};
+
+// Implements a matcher that checks the begin()..end() distance of an STL-style
+// container.
+template <typename DistanceMatcher>
+class BeginEndDistanceIsMatcher {
+ public:
+  explicit BeginEndDistanceIsMatcher(const DistanceMatcher& distance_matcher)
+      : distance_matcher_(distance_matcher) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    return MakeMatcher(new Impl<Container>(distance_matcher_));
+  }
+
+  template <typename Container>
+  class Impl : public MatcherInterface<Container> {
+   public:
+    typedef internal::StlContainerView<
+        GTEST_REMOVE_REFERENCE_AND_CONST_(Container)> ContainerView;
+    typedef typename std::iterator_traits<
+        typename ContainerView::type::const_iterator>::difference_type
+        DistanceType;
+    explicit Impl(const DistanceMatcher& distance_matcher)
+        : distance_matcher_(MatcherCast<DistanceType>(distance_matcher)) {}
+
+    virtual void DescribeTo(::std::ostream* os) const {
+      *os << "distance between begin() and end() ";
+      distance_matcher_.DescribeTo(os);
+    }
+    virtual void DescribeNegationTo(::std::ostream* os) const {
+      *os << "distance between begin() and end() ";
+      distance_matcher_.DescribeNegationTo(os);
+    }
+
+    virtual bool MatchAndExplain(Container container,
+                                 MatchResultListener* listener) const {
+#if GTEST_HAS_STD_BEGIN_AND_END_
+      using std::begin;
+      using std::end;
+      DistanceType distance = std::distance(begin(container), end(container));
+#else
+      DistanceType distance = std::distance(container.begin(), container.end());
+#endif
+      StringMatchResultListener distance_listener;
+      const bool result =
+          distance_matcher_.MatchAndExplain(distance, &distance_listener);
+      *listener << "whose distance between begin() and end() " << distance
+                << (result ? " matches" : " doesn't match");
+      PrintIfNotEmpty(distance_listener.str(), listener->stream());
+      return result;
+    }
+
+   private:
+    const Matcher<DistanceType> distance_matcher_;
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+ private:
+  const DistanceMatcher distance_matcher_;
+  GTEST_DISALLOW_ASSIGN_(BeginEndDistanceIsMatcher);
+};
+
+// Implements an equality matcher for any STL-style container whose elements
+// support ==. This matcher is like Eq(), but its failure explanations provide
+// more detailed information that is useful when the container is used as a set.
+// The failure message reports elements that are in one of the operands but not
+// the other. The failure messages do not report duplicate or out-of-order
+// elements in the containers (which don't properly matter to sets, but can
+// occur if the containers are vectors or lists, for example).
+//
+// Uses the container's const_iterator, value_type, operator ==,
+// begin(), and end().
+template <typename Container>
+class ContainerEqMatcher {
+ public:
+  typedef internal::StlContainerView<Container> View;
+  typedef typename View::type StlContainer;
+  typedef typename View::const_reference StlContainerReference;
+
+  // We make a copy of expected in case the elements in it are modified
+  // after this matcher is created.
+  explicit ContainerEqMatcher(const Container& expected)
+      : expected_(View::Copy(expected)) {
+    // Makes sure the user doesn't instantiate this class template
+    // with a const or reference type.
+    (void)testing::StaticAssertTypeEq<Container,
+        GTEST_REMOVE_REFERENCE_AND_CONST_(Container)>();
+  }
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << "equals ";
+    UniversalPrint(expected_, os);
+  }
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "does not equal ";
+    UniversalPrint(expected_, os);
+  }
+
+  template <typename LhsContainer>
+  bool MatchAndExplain(const LhsContainer& lhs,
+                       MatchResultListener* listener) const {
+    // GTEST_REMOVE_CONST_() is needed to work around an MSVC 8.0 bug
+    // that causes LhsContainer to be a const type sometimes.
+    typedef internal::StlContainerView<GTEST_REMOVE_CONST_(LhsContainer)>
+        LhsView;
+    typedef typename LhsView::type LhsStlContainer;
+    StlContainerReference lhs_stl_container = LhsView::ConstReference(lhs);
+    if (lhs_stl_container == expected_)
+      return true;
+
+    ::std::ostream* const os = listener->stream();
+    if (os != NULL) {
+      // Something is different. Check for extra values first.
+      bool printed_header = false;
+      for (typename LhsStlContainer::const_iterator it =
+               lhs_stl_container.begin();
+           it != lhs_stl_container.end(); ++it) {
+        if (internal::ArrayAwareFind(expected_.begin(), expected_.end(), *it) ==
+            expected_.end()) {
+          if (printed_header) {
+            *os << ", ";
+          } else {
+            *os << "which has these unexpected elements: ";
+            printed_header = true;
+          }
+          UniversalPrint(*it, os);
+        }
+      }
+
+      // Now check for missing values.
+      bool printed_header2 = false;
+      for (typename StlContainer::const_iterator it = expected_.begin();
+           it != expected_.end(); ++it) {
+        if (internal::ArrayAwareFind(
+                lhs_stl_container.begin(), lhs_stl_container.end(), *it) ==
+            lhs_stl_container.end()) {
+          if (printed_header2) {
+            *os << ", ";
+          } else {
+            *os << (printed_header ? ",\nand" : "which")
+                << " doesn't have these expected elements: ";
+            printed_header2 = true;
+          }
+          UniversalPrint(*it, os);
+        }
+      }
+    }
+
+    return false;
+  }
+
+ private:
+  const StlContainer expected_;
+
+  GTEST_DISALLOW_ASSIGN_(ContainerEqMatcher);
+};
+
+// A comparator functor that uses the < operator to compare two values.
+struct LessComparator {
+  template <typename T, typename U>
+  bool operator()(const T& lhs, const U& rhs) const { return lhs < rhs; }
+};
+
+// Implements WhenSortedBy(comparator, container_matcher).
+template <typename Comparator, typename ContainerMatcher>
+class WhenSortedByMatcher {
+ public:
+  WhenSortedByMatcher(const Comparator& comparator,
+                      const ContainerMatcher& matcher)
+      : comparator_(comparator), matcher_(matcher) {}
+
+  template <typename LhsContainer>
+  operator Matcher<LhsContainer>() const {
+    return MakeMatcher(new Impl<LhsContainer>(comparator_, matcher_));
+  }
+
+  template <typename LhsContainer>
+  class Impl : public MatcherInterface<LhsContainer> {
+   public:
+    typedef internal::StlContainerView<
+         GTEST_REMOVE_REFERENCE_AND_CONST_(LhsContainer)> LhsView;
+    typedef typename LhsView::type LhsStlContainer;
+    typedef typename LhsView::const_reference LhsStlContainerReference;
+    // Transforms std::pair<const Key, Value> into std::pair<Key, Value>
+    // so that we can match associative containers.
+    typedef typename RemoveConstFromKey<
+        typename LhsStlContainer::value_type>::type LhsValue;
+
+    Impl(const Comparator& comparator, const ContainerMatcher& matcher)
+        : comparator_(comparator), matcher_(matcher) {}
+
+    virtual void DescribeTo(::std::ostream* os) const {
+      *os << "(when sorted) ";
+      matcher_.DescribeTo(os);
+    }
+
+    virtual void DescribeNegationTo(::std::ostream* os) const {
+      *os << "(when sorted) ";
+      matcher_.DescribeNegationTo(os);
+    }
+
+    virtual bool MatchAndExplain(LhsContainer lhs,
+                                 MatchResultListener* listener) const {
+      LhsStlContainerReference lhs_stl_container = LhsView::ConstReference(lhs);
+      ::std::vector<LhsValue> sorted_container(lhs_stl_container.begin(),
+                                               lhs_stl_container.end());
+      ::std::sort(
+           sorted_container.begin(), sorted_container.end(), comparator_);
+
+      if (!listener->IsInterested()) {
+        // If the listener is not interested, we do not need to
+        // construct the inner explanation.
+        return matcher_.Matches(sorted_container);
+      }
+
+      *listener << "which is ";
+      UniversalPrint(sorted_container, listener->stream());
+      *listener << " when sorted";
+
+      StringMatchResultListener inner_listener;
+      const bool match = matcher_.MatchAndExplain(sorted_container,
+                                                  &inner_listener);
+      PrintIfNotEmpty(inner_listener.str(), listener->stream());
+      return match;
+    }
+
+   private:
+    const Comparator comparator_;
+    const Matcher<const ::std::vector<LhsValue>&> matcher_;
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(Impl);
+  };
+
+ private:
+  const Comparator comparator_;
+  const ContainerMatcher matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(WhenSortedByMatcher);
+};
+
+// Implements Pointwise(tuple_matcher, rhs_container).  tuple_matcher
+// must be able to be safely cast to Matcher<tuple<const T1&, const
+// T2&> >, where T1 and T2 are the types of elements in the LHS
+// container and the RHS container respectively.
+template <typename TupleMatcher, typename RhsContainer>
+class PointwiseMatcher {
+ public:
+  typedef internal::StlContainerView<RhsContainer> RhsView;
+  typedef typename RhsView::type RhsStlContainer;
+  typedef typename RhsStlContainer::value_type RhsValue;
+
+  // Like ContainerEq, we make a copy of rhs in case the elements in
+  // it are modified after this matcher is created.
+  PointwiseMatcher(const TupleMatcher& tuple_matcher, const RhsContainer& rhs)
+      : tuple_matcher_(tuple_matcher), rhs_(RhsView::Copy(rhs)) {
+    // Makes sure the user doesn't instantiate this class template
+    // with a const or reference type.
+    (void)testing::StaticAssertTypeEq<RhsContainer,
+        GTEST_REMOVE_REFERENCE_AND_CONST_(RhsContainer)>();
+  }
+
+  template <typename LhsContainer>
+  operator Matcher<LhsContainer>() const {
+    return MakeMatcher(new Impl<LhsContainer>(tuple_matcher_, rhs_));
+  }
+
+  template <typename LhsContainer>
+  class Impl : public MatcherInterface<LhsContainer> {
+   public:
+    typedef internal::StlContainerView<
+         GTEST_REMOVE_REFERENCE_AND_CONST_(LhsContainer)> LhsView;
+    typedef typename LhsView::type LhsStlContainer;
+    typedef typename LhsView::const_reference LhsStlContainerReference;
+    typedef typename LhsStlContainer::value_type LhsValue;
+    // We pass the LHS value and the RHS value to the inner matcher by
+    // reference, as they may be expensive to copy.  We must use tuple
+    // instead of pair here, as a pair cannot hold references (C++ 98,
+    // 20.2.2 [lib.pairs]).
+    typedef ::testing::tuple<const LhsValue&, const RhsValue&> InnerMatcherArg;
+
+    Impl(const TupleMatcher& tuple_matcher, const RhsStlContainer& rhs)
+        // mono_tuple_matcher_ holds a monomorphic version of the tuple matcher.
+        : mono_tuple_matcher_(SafeMatcherCast<InnerMatcherArg>(tuple_matcher)),
+          rhs_(rhs) {}
+
+    virtual void DescribeTo(::std::ostream* os) const {
+      *os << "contains " << rhs_.size()
+          << " values, where each value and its corresponding value in ";
+      UniversalPrinter<RhsStlContainer>::Print(rhs_, os);
+      *os << " ";
+      mono_tuple_matcher_.DescribeTo(os);
+    }
+    virtual void DescribeNegationTo(::std::ostream* os) const {
+      *os << "doesn't contain exactly " << rhs_.size()
+          << " values, or contains a value x at some index i"
+          << " where x and the i-th value of ";
+      UniversalPrint(rhs_, os);
+      *os << " ";
+      mono_tuple_matcher_.DescribeNegationTo(os);
+    }
+
+    virtual bool MatchAndExplain(LhsContainer lhs,
+                                 MatchResultListener* listener) const {
+      LhsStlContainerReference lhs_stl_container = LhsView::ConstReference(lhs);
+      const size_t actual_size = lhs_stl_container.size();
+      if (actual_size != rhs_.size()) {
+        *listener << "which contains " << actual_size << " values";
+        return false;
+      }
+
+      typename LhsStlContainer::const_iterator left = lhs_stl_container.begin();
+      typename RhsStlContainer::const_iterator right = rhs_.begin();
+      for (size_t i = 0; i != actual_size; ++i, ++left, ++right) {
+        const InnerMatcherArg value_pair(*left, *right);
+
+        if (listener->IsInterested()) {
+          StringMatchResultListener inner_listener;
+          if (!mono_tuple_matcher_.MatchAndExplain(
+                  value_pair, &inner_listener)) {
+            *listener << "where the value pair (";
+            UniversalPrint(*left, listener->stream());
+            *listener << ", ";
+            UniversalPrint(*right, listener->stream());
+            *listener << ") at index #" << i << " don't match";
+            PrintIfNotEmpty(inner_listener.str(), listener->stream());
+            return false;
+          }
+        } else {
+          if (!mono_tuple_matcher_.Matches(value_pair))
+            return false;
+        }
+      }
+
+      return true;
+    }
+
+   private:
+    const Matcher<InnerMatcherArg> mono_tuple_matcher_;
+    const RhsStlContainer rhs_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+ private:
+  const TupleMatcher tuple_matcher_;
+  const RhsStlContainer rhs_;
+
+  GTEST_DISALLOW_ASSIGN_(PointwiseMatcher);
+};
+
+// Holds the logic common to ContainsMatcherImpl and EachMatcherImpl.
+template <typename Container>
+class QuantifierMatcherImpl : public MatcherInterface<Container> {
+ public:
+  typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+  typedef StlContainerView<RawContainer> View;
+  typedef typename View::type StlContainer;
+  typedef typename View::const_reference StlContainerReference;
+  typedef typename StlContainer::value_type Element;
+
+  template <typename InnerMatcher>
+  explicit QuantifierMatcherImpl(InnerMatcher inner_matcher)
+      : inner_matcher_(
+           testing::SafeMatcherCast<const Element&>(inner_matcher)) {}
+
+  // Checks whether:
+  // * All elements in the container match, if all_elements_should_match.
+  // * Any element in the container matches, if !all_elements_should_match.
+  bool MatchAndExplainImpl(bool all_elements_should_match,
+                           Container container,
+                           MatchResultListener* listener) const {
+    StlContainerReference stl_container = View::ConstReference(container);
+    size_t i = 0;
+    for (typename StlContainer::const_iterator it = stl_container.begin();
+         it != stl_container.end(); ++it, ++i) {
+      StringMatchResultListener inner_listener;
+      const bool matches = inner_matcher_.MatchAndExplain(*it, &inner_listener);
+
+      if (matches != all_elements_should_match) {
+        *listener << "whose element #" << i
+                  << (matches ? " matches" : " doesn't match");
+        PrintIfNotEmpty(inner_listener.str(), listener->stream());
+        return !all_elements_should_match;
+      }
+    }
+    return all_elements_should_match;
+  }
+
+ protected:
+  const Matcher<const Element&> inner_matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(QuantifierMatcherImpl);
+};
+
+// Implements Contains(element_matcher) for the given argument type Container.
+// Symmetric to EachMatcherImpl.
+template <typename Container>
+class ContainsMatcherImpl : public QuantifierMatcherImpl<Container> {
+ public:
+  template <typename InnerMatcher>
+  explicit ContainsMatcherImpl(InnerMatcher inner_matcher)
+      : QuantifierMatcherImpl<Container>(inner_matcher) {}
+
+  // Describes what this matcher does.
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "contains at least one element that ";
+    this->inner_matcher_.DescribeTo(os);
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "doesn't contain any element that ";
+    this->inner_matcher_.DescribeTo(os);
+  }
+
+  virtual bool MatchAndExplain(Container container,
+                               MatchResultListener* listener) const {
+    return this->MatchAndExplainImpl(false, container, listener);
+  }
+
+ private:
+  GTEST_DISALLOW_ASSIGN_(ContainsMatcherImpl);
+};
+
+// Implements Each(element_matcher) for the given argument type Container.
+// Symmetric to ContainsMatcherImpl.
+template <typename Container>
+class EachMatcherImpl : public QuantifierMatcherImpl<Container> {
+ public:
+  template <typename InnerMatcher>
+  explicit EachMatcherImpl(InnerMatcher inner_matcher)
+      : QuantifierMatcherImpl<Container>(inner_matcher) {}
+
+  // Describes what this matcher does.
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "only contains elements that ";
+    this->inner_matcher_.DescribeTo(os);
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "contains some element that ";
+    this->inner_matcher_.DescribeNegationTo(os);
+  }
+
+  virtual bool MatchAndExplain(Container container,
+                               MatchResultListener* listener) const {
+    return this->MatchAndExplainImpl(true, container, listener);
+  }
+
+ private:
+  GTEST_DISALLOW_ASSIGN_(EachMatcherImpl);
+};
+
+// Implements polymorphic Contains(element_matcher).
+template <typename M>
+class ContainsMatcher {
+ public:
+  explicit ContainsMatcher(M m) : inner_matcher_(m) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    return MakeMatcher(new ContainsMatcherImpl<Container>(inner_matcher_));
+  }
+
+ private:
+  const M inner_matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(ContainsMatcher);
+};
+
+// Implements polymorphic Each(element_matcher).
+template <typename M>
+class EachMatcher {
+ public:
+  explicit EachMatcher(M m) : inner_matcher_(m) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    return MakeMatcher(new EachMatcherImpl<Container>(inner_matcher_));
+  }
+
+ private:
+  const M inner_matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(EachMatcher);
+};
+
+// Implements Key(inner_matcher) for the given argument pair type.
+// Key(inner_matcher) matches an std::pair whose 'first' field matches
+// inner_matcher.  For example, Contains(Key(Ge(5))) can be used to match an
+// std::map that contains at least one element whose key is >= 5.
+template <typename PairType>
+class KeyMatcherImpl : public MatcherInterface<PairType> {
+ public:
+  typedef GTEST_REMOVE_REFERENCE_AND_CONST_(PairType) RawPairType;
+  typedef typename RawPairType::first_type KeyType;
+
+  template <typename InnerMatcher>
+  explicit KeyMatcherImpl(InnerMatcher inner_matcher)
+      : inner_matcher_(
+          testing::SafeMatcherCast<const KeyType&>(inner_matcher)) {
+  }
+
+  // Returns true iff 'key_value.first' (the key) matches the inner matcher.
+  virtual bool MatchAndExplain(PairType key_value,
+                               MatchResultListener* listener) const {
+    StringMatchResultListener inner_listener;
+    const bool match = inner_matcher_.MatchAndExplain(key_value.first,
+                                                      &inner_listener);
+    const internal::string explanation = inner_listener.str();
+    if (explanation != "") {
+      *listener << "whose first field is a value " << explanation;
+    }
+    return match;
+  }
+
+  // Describes what this matcher does.
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "has a key that ";
+    inner_matcher_.DescribeTo(os);
+  }
+
+  // Describes what the negation of this matcher does.
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "doesn't have a key that ";
+    inner_matcher_.DescribeTo(os);
+  }
+
+ private:
+  const Matcher<const KeyType&> inner_matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(KeyMatcherImpl);
+};
+
+// Implements polymorphic Key(matcher_for_key).
+template <typename M>
+class KeyMatcher {
+ public:
+  explicit KeyMatcher(M m) : matcher_for_key_(m) {}
+
+  template <typename PairType>
+  operator Matcher<PairType>() const {
+    return MakeMatcher(new KeyMatcherImpl<PairType>(matcher_for_key_));
+  }
+
+ private:
+  const M matcher_for_key_;
+
+  GTEST_DISALLOW_ASSIGN_(KeyMatcher);
+};
+
+// Implements Pair(first_matcher, second_matcher) for the given argument pair
+// type with its two matchers. See Pair() function below.
+template <typename PairType>
+class PairMatcherImpl : public MatcherInterface<PairType> {
+ public:
+  typedef GTEST_REMOVE_REFERENCE_AND_CONST_(PairType) RawPairType;
+  typedef typename RawPairType::first_type FirstType;
+  typedef typename RawPairType::second_type SecondType;
+
+  template <typename FirstMatcher, typename SecondMatcher>
+  PairMatcherImpl(FirstMatcher first_matcher, SecondMatcher second_matcher)
+      : first_matcher_(
+            testing::SafeMatcherCast<const FirstType&>(first_matcher)),
+        second_matcher_(
+            testing::SafeMatcherCast<const SecondType&>(second_matcher)) {
+  }
+
+  // Describes what this matcher does.
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "has a first field that ";
+    first_matcher_.DescribeTo(os);
+    *os << ", and has a second field that ";
+    second_matcher_.DescribeTo(os);
+  }
+
+  // Describes what the negation of this matcher does.
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "has a first field that ";
+    first_matcher_.DescribeNegationTo(os);
+    *os << ", or has a second field that ";
+    second_matcher_.DescribeNegationTo(os);
+  }
+
+  // Returns true iff 'a_pair.first' matches first_matcher and 'a_pair.second'
+  // matches second_matcher.
+  virtual bool MatchAndExplain(PairType a_pair,
+                               MatchResultListener* listener) const {
+    if (!listener->IsInterested()) {
+      // If the listener is not interested, we don't need to construct the
+      // explanation.
+      return first_matcher_.Matches(a_pair.first) &&
+             second_matcher_.Matches(a_pair.second);
+    }
+    StringMatchResultListener first_inner_listener;
+    if (!first_matcher_.MatchAndExplain(a_pair.first,
+                                        &first_inner_listener)) {
+      *listener << "whose first field does not match";
+      PrintIfNotEmpty(first_inner_listener.str(), listener->stream());
+      return false;
+    }
+    StringMatchResultListener second_inner_listener;
+    if (!second_matcher_.MatchAndExplain(a_pair.second,
+                                         &second_inner_listener)) {
+      *listener << "whose second field does not match";
+      PrintIfNotEmpty(second_inner_listener.str(), listener->stream());
+      return false;
+    }
+    ExplainSuccess(first_inner_listener.str(), second_inner_listener.str(),
+                   listener);
+    return true;
+  }
+
+ private:
+  void ExplainSuccess(const internal::string& first_explanation,
+                      const internal::string& second_explanation,
+                      MatchResultListener* listener) const {
+    *listener << "whose both fields match";
+    if (first_explanation != "") {
+      *listener << ", where the first field is a value " << first_explanation;
+    }
+    if (second_explanation != "") {
+      *listener << ", ";
+      if (first_explanation != "") {
+        *listener << "and ";
+      } else {
+        *listener << "where ";
+      }
+      *listener << "the second field is a value " << second_explanation;
+    }
+  }
+
+  const Matcher<const FirstType&> first_matcher_;
+  const Matcher<const SecondType&> second_matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(PairMatcherImpl);
+};
+
+// Implements polymorphic Pair(first_matcher, second_matcher).
+template <typename FirstMatcher, typename SecondMatcher>
+class PairMatcher {
+ public:
+  PairMatcher(FirstMatcher first_matcher, SecondMatcher second_matcher)
+      : first_matcher_(first_matcher), second_matcher_(second_matcher) {}
+
+  template <typename PairType>
+  operator Matcher<PairType> () const {
+    return MakeMatcher(
+        new PairMatcherImpl<PairType>(
+            first_matcher_, second_matcher_));
+  }
+
+ private:
+  const FirstMatcher first_matcher_;
+  const SecondMatcher second_matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(PairMatcher);
+};
+
+// Implements ElementsAre() and ElementsAreArray().
+template <typename Container>
+class ElementsAreMatcherImpl : public MatcherInterface<Container> {
+ public:
+  typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+  typedef internal::StlContainerView<RawContainer> View;
+  typedef typename View::type StlContainer;
+  typedef typename View::const_reference StlContainerReference;
+  typedef typename StlContainer::value_type Element;
+
+  // Constructs the matcher from a sequence of element values or
+  // element matchers.
+  template <typename InputIter>
+  ElementsAreMatcherImpl(InputIter first, InputIter last) {
+    while (first != last) {
+      matchers_.push_back(MatcherCast<const Element&>(*first++));
+    }
+  }
+
+  // Describes what this matcher does.
+  virtual void DescribeTo(::std::ostream* os) const {
+    if (count() == 0) {
+      *os << "is empty";
+    } else if (count() == 1) {
+      *os << "has 1 element that ";
+      matchers_[0].DescribeTo(os);
+    } else {
+      *os << "has " << Elements(count()) << " where\n";
+      for (size_t i = 0; i != count(); ++i) {
+        *os << "element #" << i << " ";
+        matchers_[i].DescribeTo(os);
+        if (i + 1 < count()) {
+          *os << ",\n";
+        }
+      }
+    }
+  }
+
+  // Describes what the negation of this matcher does.
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    if (count() == 0) {
+      *os << "isn't empty";
+      return;
+    }
+
+    *os << "doesn't have " << Elements(count()) << ", or\n";
+    for (size_t i = 0; i != count(); ++i) {
+      *os << "element #" << i << " ";
+      matchers_[i].DescribeNegationTo(os);
+      if (i + 1 < count()) {
+        *os << ", or\n";
+      }
+    }
+  }
+
+  virtual bool MatchAndExplain(Container container,
+                               MatchResultListener* listener) const {
+    // To work with stream-like "containers", we must only walk
+    // through the elements in one pass.
+
+    const bool listener_interested = listener->IsInterested();
+
+    // explanations[i] is the explanation of the element at index i.
+    ::std::vector<internal::string> explanations(count());
+    StlContainerReference stl_container = View::ConstReference(container);
+    typename StlContainer::const_iterator it = stl_container.begin();
+    size_t exam_pos = 0;
+    bool mismatch_found = false;  // Have we found a mismatched element yet?
+
+    // Go through the elements and matchers in pairs, until we reach
+    // the end of either the elements or the matchers, or until we find a
+    // mismatch.
+    for (; it != stl_container.end() && exam_pos != count(); ++it, ++exam_pos) {
+      bool match;  // Does the current element match the current matcher?
+      if (listener_interested) {
+        StringMatchResultListener s;
+        match = matchers_[exam_pos].MatchAndExplain(*it, &s);
+        explanations[exam_pos] = s.str();
+      } else {
+        match = matchers_[exam_pos].Matches(*it);
+      }
+
+      if (!match) {
+        mismatch_found = true;
+        break;
+      }
+    }
+    // If mismatch_found is true, 'exam_pos' is the index of the mismatch.
+
+    // Find how many elements the actual container has.  We avoid
+    // calling size() s.t. this code works for stream-like "containers"
+    // that don't define size().
+    size_t actual_count = exam_pos;
+    for (; it != stl_container.end(); ++it) {
+      ++actual_count;
+    }
+
+    if (actual_count != count()) {
+      // The element count doesn't match.  If the container is empty,
+      // there's no need to explain anything as Google Mock already
+      // prints the empty container.  Otherwise we just need to show
+      // how many elements there actually are.
+      if (listener_interested && (actual_count != 0)) {
+        *listener << "which has " << Elements(actual_count);
+      }
+      return false;
+    }
+
+    if (mismatch_found) {
+      // The element count matches, but the exam_pos-th element doesn't match.
+      if (listener_interested) {
+        *listener << "whose element #" << exam_pos << " doesn't match";
+        PrintIfNotEmpty(explanations[exam_pos], listener->stream());
+      }
+      return false;
+    }
+
+    // Every element matches its expectation.  We need to explain why
+    // (the obvious ones can be skipped).
+    if (listener_interested) {
+      bool reason_printed = false;
+      for (size_t i = 0; i != count(); ++i) {
+        const internal::string& s = explanations[i];
+        if (!s.empty()) {
+          if (reason_printed) {
+            *listener << ",\nand ";
+          }
+          *listener << "whose element #" << i << " matches, " << s;
+          reason_printed = true;
+        }
+      }
+    }
+    return true;
+  }
+
+ private:
+  static Message Elements(size_t count) {
+    return Message() << count << (count == 1 ? " element" : " elements");
+  }
+
+  size_t count() const { return matchers_.size(); }
+
+  ::std::vector<Matcher<const Element&> > matchers_;
+
+  GTEST_DISALLOW_ASSIGN_(ElementsAreMatcherImpl);
+};
+
+// Connectivity matrix of (elements X matchers), in element-major order.
+// Initially, there are no edges.
+// Use NextGraph() to iterate over all possible edge configurations.
+// Use Randomize() to generate a random edge configuration.
+class GTEST_API_ MatchMatrix {
+ public:
+  MatchMatrix(size_t num_elements, size_t num_matchers)
+      : num_elements_(num_elements),
+        num_matchers_(num_matchers),
+        matched_(num_elements_* num_matchers_, 0) {
+  }
+
+  size_t LhsSize() const { return num_elements_; }
+  size_t RhsSize() const { return num_matchers_; }
+  bool HasEdge(size_t ilhs, size_t irhs) const {
+    return matched_[SpaceIndex(ilhs, irhs)] == 1;
+  }
+  void SetEdge(size_t ilhs, size_t irhs, bool b) {
+    matched_[SpaceIndex(ilhs, irhs)] = b ? 1 : 0;
+  }
+
+  // Treating the connectivity matrix as a (LhsSize()*RhsSize())-bit number,
+  // adds 1 to that number; returns false if incrementing the graph left it
+  // empty.
+  bool NextGraph();
+
+  void Randomize();
+
+  string DebugString() const;
+
+ private:
+  size_t SpaceIndex(size_t ilhs, size_t irhs) const {
+    return ilhs * num_matchers_ + irhs;
+  }
+
+  size_t num_elements_;
+  size_t num_matchers_;
+
+  // Each element is a char interpreted as bool. They are stored as a
+  // flattened array in lhs-major order, use 'SpaceIndex()' to translate
+  // a (ilhs, irhs) matrix coordinate into an offset.
+  ::std::vector<char> matched_;
+};
+
+typedef ::std::pair<size_t, size_t> ElementMatcherPair;
+typedef ::std::vector<ElementMatcherPair> ElementMatcherPairs;
+
+// Returns a maximum bipartite matching for the specified graph 'g'.
+// The matching is represented as a vector of {element, matcher} pairs.
+GTEST_API_ ElementMatcherPairs
+FindMaxBipartiteMatching(const MatchMatrix& g);
+
+GTEST_API_ bool FindPairing(const MatchMatrix& matrix,
+                            MatchResultListener* listener);
+
+// Untyped base class for implementing UnorderedElementsAre.  By
+// putting logic that's not specific to the element type here, we
+// reduce binary bloat and increase compilation speed.
+class GTEST_API_ UnorderedElementsAreMatcherImplBase {
+ protected:
+  // A vector of matcher describers, one for each element matcher.
+  // Does not own the describers (and thus can be used only when the
+  // element matchers are alive).
+  typedef ::std::vector<const MatcherDescriberInterface*> MatcherDescriberVec;
+
+  // Describes this UnorderedElementsAre matcher.
+  void DescribeToImpl(::std::ostream* os) const;
+
+  // Describes the negation of this UnorderedElementsAre matcher.
+  void DescribeNegationToImpl(::std::ostream* os) const;
+
+  bool VerifyAllElementsAndMatchersAreMatched(
+      const ::std::vector<string>& element_printouts,
+      const MatchMatrix& matrix,
+      MatchResultListener* listener) const;
+
+  MatcherDescriberVec& matcher_describers() {
+    return matcher_describers_;
+  }
+
+  static Message Elements(size_t n) {
+    return Message() << n << " element" << (n == 1 ? "" : "s");
+  }
+
+ private:
+  MatcherDescriberVec matcher_describers_;
+
+  GTEST_DISALLOW_ASSIGN_(UnorderedElementsAreMatcherImplBase);
+};
+
+// Implements unordered ElementsAre and unordered ElementsAreArray.
+template <typename Container>
+class UnorderedElementsAreMatcherImpl
+    : public MatcherInterface<Container>,
+      public UnorderedElementsAreMatcherImplBase {
+ public:
+  typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+  typedef internal::StlContainerView<RawContainer> View;
+  typedef typename View::type StlContainer;
+  typedef typename View::const_reference StlContainerReference;
+  typedef typename StlContainer::const_iterator StlContainerConstIterator;
+  typedef typename StlContainer::value_type Element;
+
+  // Constructs the matcher from a sequence of element values or
+  // element matchers.
+  template <typename InputIter>
+  UnorderedElementsAreMatcherImpl(InputIter first, InputIter last) {
+    for (; first != last; ++first) {
+      matchers_.push_back(MatcherCast<const Element&>(*first));
+      matcher_describers().push_back(matchers_.back().GetDescriber());
+    }
+  }
+
+  // Describes what this matcher does.
+  virtual void DescribeTo(::std::ostream* os) const {
+    return UnorderedElementsAreMatcherImplBase::DescribeToImpl(os);
+  }
+
+  // Describes what the negation of this matcher does.
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    return UnorderedElementsAreMatcherImplBase::DescribeNegationToImpl(os);
+  }
+
+  virtual bool MatchAndExplain(Container container,
+                               MatchResultListener* listener) const {
+    StlContainerReference stl_container = View::ConstReference(container);
+    ::std::vector<string> element_printouts;
+    MatchMatrix matrix = AnalyzeElements(stl_container.begin(),
+                                         stl_container.end(),
+                                         &element_printouts,
+                                         listener);
+
+    const size_t actual_count = matrix.LhsSize();
+    if (actual_count == 0 && matchers_.empty()) {
+      return true;
+    }
+    if (actual_count != matchers_.size()) {
+      // The element count doesn't match.  If the container is empty,
+      // there's no need to explain anything as Google Mock already
+      // prints the empty container. Otherwise we just need to show
+      // how many elements there actually are.
+      if (actual_count != 0 && listener->IsInterested()) {
+        *listener << "which has " << Elements(actual_count);
+      }
+      return false;
+    }
+
+    return VerifyAllElementsAndMatchersAreMatched(element_printouts,
+                                                  matrix, listener) &&
+           FindPairing(matrix, listener);
+  }
+
+ private:
+  typedef ::std::vector<Matcher<const Element&> > MatcherVec;
+
+  template <typename ElementIter>
+  MatchMatrix AnalyzeElements(ElementIter elem_first, ElementIter elem_last,
+                              ::std::vector<string>* element_printouts,
+                              MatchResultListener* listener) const {
+    element_printouts->clear();
+    ::std::vector<char> did_match;
+    size_t num_elements = 0;
+    for (; elem_first != elem_last; ++num_elements, ++elem_first) {
+      if (listener->IsInterested()) {
+        element_printouts->push_back(PrintToString(*elem_first));
+      }
+      for (size_t irhs = 0; irhs != matchers_.size(); ++irhs) {
+        did_match.push_back(Matches(matchers_[irhs])(*elem_first));
+      }
+    }
+
+    MatchMatrix matrix(num_elements, matchers_.size());
+    ::std::vector<char>::const_iterator did_match_iter = did_match.begin();
+    for (size_t ilhs = 0; ilhs != num_elements; ++ilhs) {
+      for (size_t irhs = 0; irhs != matchers_.size(); ++irhs) {
+        matrix.SetEdge(ilhs, irhs, *did_match_iter++ != 0);
+      }
+    }
+    return matrix;
+  }
+
+  MatcherVec matchers_;
+
+  GTEST_DISALLOW_ASSIGN_(UnorderedElementsAreMatcherImpl);
+};
+
+// Functor for use in TransformTuple.
+// Performs MatcherCast<Target> on an input argument of any type.
+template <typename Target>
+struct CastAndAppendTransform {
+  template <typename Arg>
+  Matcher<Target> operator()(const Arg& a) const {
+    return MatcherCast<Target>(a);
+  }
+};
+
+// Implements UnorderedElementsAre.
+template <typename MatcherTuple>
+class UnorderedElementsAreMatcher {
+ public:
+  explicit UnorderedElementsAreMatcher(const MatcherTuple& args)
+      : matchers_(args) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type View;
+    typedef typename View::value_type Element;
+    typedef ::std::vector<Matcher<const Element&> > MatcherVec;
+    MatcherVec matchers;
+    matchers.reserve(::testing::tuple_size<MatcherTuple>::value);
+    TransformTupleValues(CastAndAppendTransform<const Element&>(), matchers_,
+                         ::std::back_inserter(matchers));
+    return MakeMatcher(new UnorderedElementsAreMatcherImpl<Container>(
+                           matchers.begin(), matchers.end()));
+  }
+
+ private:
+  const MatcherTuple matchers_;
+  GTEST_DISALLOW_ASSIGN_(UnorderedElementsAreMatcher);
+};
+
+// Implements ElementsAre.
+template <typename MatcherTuple>
+class ElementsAreMatcher {
+ public:
+  explicit ElementsAreMatcher(const MatcherTuple& args) : matchers_(args) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type View;
+    typedef typename View::value_type Element;
+    typedef ::std::vector<Matcher<const Element&> > MatcherVec;
+    MatcherVec matchers;
+    matchers.reserve(::testing::tuple_size<MatcherTuple>::value);
+    TransformTupleValues(CastAndAppendTransform<const Element&>(), matchers_,
+                         ::std::back_inserter(matchers));
+    return MakeMatcher(new ElementsAreMatcherImpl<Container>(
+                           matchers.begin(), matchers.end()));
+  }
+
+ private:
+  const MatcherTuple matchers_;
+  GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher);
+};
+
+// Implements UnorderedElementsAreArray().
+template <typename T>
+class UnorderedElementsAreArrayMatcher {
+ public:
+  UnorderedElementsAreArrayMatcher() {}
+
+  template <typename Iter>
+  UnorderedElementsAreArrayMatcher(Iter first, Iter last)
+      : matchers_(first, last) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    return MakeMatcher(
+        new UnorderedElementsAreMatcherImpl<Container>(matchers_.begin(),
+                                                       matchers_.end()));
+  }
+
+ private:
+  ::std::vector<T> matchers_;
+
+  GTEST_DISALLOW_ASSIGN_(UnorderedElementsAreArrayMatcher);
+};
+
+// Implements ElementsAreArray().
+template <typename T>
+class ElementsAreArrayMatcher {
+ public:
+  template <typename Iter>
+  ElementsAreArrayMatcher(Iter first, Iter last) : matchers_(first, last) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    return MakeMatcher(new ElementsAreMatcherImpl<Container>(
+        matchers_.begin(), matchers_.end()));
+  }
+
+ private:
+  const ::std::vector<T> matchers_;
+
+  GTEST_DISALLOW_ASSIGN_(ElementsAreArrayMatcher);
+};
+
+// Given a 2-tuple matcher tm of type Tuple2Matcher and a value second
+// of type Second, BoundSecondMatcher<Tuple2Matcher, Second>(tm,
+// second) is a polymorphic matcher that matches a value x iff tm
+// matches tuple (x, second).  Useful for implementing
+// UnorderedPointwise() in terms of UnorderedElementsAreArray().
+//
+// BoundSecondMatcher is copyable and assignable, as we need to put
+// instances of this class in a vector when implementing
+// UnorderedPointwise().
+template <typename Tuple2Matcher, typename Second>
+class BoundSecondMatcher {
+ public:
+  BoundSecondMatcher(const Tuple2Matcher& tm, const Second& second)
+      : tuple2_matcher_(tm), second_value_(second) {}
+
+  template <typename T>
+  operator Matcher<T>() const {
+    return MakeMatcher(new Impl<T>(tuple2_matcher_, second_value_));
+  }
+
+  // We have to define this for UnorderedPointwise() to compile in
+  // C++98 mode, as it puts BoundSecondMatcher instances in a vector,
+  // which requires the elements to be assignable in C++98.  The
+  // compiler cannot generate the operator= for us, as Tuple2Matcher
+  // and Second may not be assignable.
+  //
+  // However, this should never be called, so the implementation just
+  // need to assert.
+  void operator=(const BoundSecondMatcher& /*rhs*/) {
+    GTEST_LOG_(FATAL) << "BoundSecondMatcher should never be assigned.";
+  }
+
+ private:
+  template <typename T>
+  class Impl : public MatcherInterface<T> {
+   public:
+    typedef ::testing::tuple<T, Second> ArgTuple;
+
+    Impl(const Tuple2Matcher& tm, const Second& second)
+        : mono_tuple2_matcher_(SafeMatcherCast<const ArgTuple&>(tm)),
+          second_value_(second) {}
+
+    virtual void DescribeTo(::std::ostream* os) const {
+      *os << "and ";
+      UniversalPrint(second_value_, os);
+      *os << " ";
+      mono_tuple2_matcher_.DescribeTo(os);
+    }
+
+    virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
+      return mono_tuple2_matcher_.MatchAndExplain(ArgTuple(x, second_value_),
+                                                  listener);
+    }
+
+   private:
+    const Matcher<const ArgTuple&> mono_tuple2_matcher_;
+    const Second second_value_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+  const Tuple2Matcher tuple2_matcher_;
+  const Second second_value_;
+};
+
+// Given a 2-tuple matcher tm and a value second,
+// MatcherBindSecond(tm, second) returns a matcher that matches a
+// value x iff tm matches tuple (x, second).  Useful for implementing
+// UnorderedPointwise() in terms of UnorderedElementsAreArray().
+template <typename Tuple2Matcher, typename Second>
+BoundSecondMatcher<Tuple2Matcher, Second> MatcherBindSecond(
+    const Tuple2Matcher& tm, const Second& second) {
+  return BoundSecondMatcher<Tuple2Matcher, Second>(tm, second);
+}
+
+// Returns the description for a matcher defined using the MATCHER*()
+// macro where the user-supplied description string is "", if
+// 'negation' is false; otherwise returns the description of the
+// negation of the matcher.  'param_values' contains a list of strings
+// that are the print-out of the matcher's parameters.
+GTEST_API_ string FormatMatcherDescription(bool negation,
+                                           const char* matcher_name,
+                                           const Strings& param_values);
+
+}  // namespace internal
+
+// ElementsAreArray(first, last)
+// ElementsAreArray(pointer, count)
+// ElementsAreArray(array)
+// ElementsAreArray(container)
+// ElementsAreArray({ e1, e2, ..., en })
+//
+// The ElementsAreArray() functions are like ElementsAre(...), except
+// that they are given a homogeneous sequence rather than taking each
+// element as a function argument. The sequence can be specified as an
+// array, a pointer and count, a vector, an initializer list, or an
+// STL iterator range. In each of these cases, the underlying sequence
+// can be either a sequence of values or a sequence of matchers.
+//
+// All forms of ElementsAreArray() make a copy of the input matcher sequence.
+
+template <typename Iter>
+inline internal::ElementsAreArrayMatcher<
+    typename ::std::iterator_traits<Iter>::value_type>
+ElementsAreArray(Iter first, Iter last) {
+  typedef typename ::std::iterator_traits<Iter>::value_type T;
+  return internal::ElementsAreArrayMatcher<T>(first, last);
+}
+
+template <typename T>
+inline internal::ElementsAreArrayMatcher<T> ElementsAreArray(
+    const T* pointer, size_t count) {
+  return ElementsAreArray(pointer, pointer + count);
+}
+
+template <typename T, size_t N>
+inline internal::ElementsAreArrayMatcher<T> ElementsAreArray(
+    const T (&array)[N]) {
+  return ElementsAreArray(array, N);
+}
+
+template <typename Container>
+inline internal::ElementsAreArrayMatcher<typename Container::value_type>
+ElementsAreArray(const Container& container) {
+  return ElementsAreArray(container.begin(), container.end());
+}
+
+#if GTEST_HAS_STD_INITIALIZER_LIST_
+template <typename T>
+inline internal::ElementsAreArrayMatcher<T>
+ElementsAreArray(::std::initializer_list<T> xs) {
+  return ElementsAreArray(xs.begin(), xs.end());
+}
+#endif
+
+// UnorderedElementsAreArray(first, last)
+// UnorderedElementsAreArray(pointer, count)
+// UnorderedElementsAreArray(array)
+// UnorderedElementsAreArray(container)
+// UnorderedElementsAreArray({ e1, e2, ..., en })
+//
+// The UnorderedElementsAreArray() functions are like
+// ElementsAreArray(...), but allow matching the elements in any order.
+template <typename Iter>
+inline internal::UnorderedElementsAreArrayMatcher<
+    typename ::std::iterator_traits<Iter>::value_type>
+UnorderedElementsAreArray(Iter first, Iter last) {
+  typedef typename ::std::iterator_traits<Iter>::value_type T;
+  return internal::UnorderedElementsAreArrayMatcher<T>(first, last);
+}
+
+template <typename T>
+inline internal::UnorderedElementsAreArrayMatcher<T>
+UnorderedElementsAreArray(const T* pointer, size_t count) {
+  return UnorderedElementsAreArray(pointer, pointer + count);
+}
+
+template <typename T, size_t N>
+inline internal::UnorderedElementsAreArrayMatcher<T>
+UnorderedElementsAreArray(const T (&array)[N]) {
+  return UnorderedElementsAreArray(array, N);
+}
+
+template <typename Container>
+inline internal::UnorderedElementsAreArrayMatcher<
+    typename Container::value_type>
+UnorderedElementsAreArray(const Container& container) {
+  return UnorderedElementsAreArray(container.begin(), container.end());
+}
+
+#if GTEST_HAS_STD_INITIALIZER_LIST_
+template <typename T>
+inline internal::UnorderedElementsAreArrayMatcher<T>
+UnorderedElementsAreArray(::std::initializer_list<T> xs) {
+  return UnorderedElementsAreArray(xs.begin(), xs.end());
+}
+#endif
+
+// _ is a matcher that matches anything of any type.
+//
+// This definition is fine as:
+//
+//   1. The C++ standard permits using the name _ in a namespace that
+//      is not the global namespace or ::std.
+//   2. The AnythingMatcher class has no data member or constructor,
+//      so it's OK to create global variables of this type.
+//   3. c-style has approved of using _ in this case.
+const internal::AnythingMatcher _ = {};
+// Creates a matcher that matches any value of the given type T.
+template <typename T>
+inline Matcher<T> A() { return MakeMatcher(new internal::AnyMatcherImpl<T>()); }
+
+// Creates a matcher that matches any value of the given type T.
+template <typename T>
+inline Matcher<T> An() { return A<T>(); }
+
+// Creates a polymorphic matcher that matches anything equal to x.
+// Note: if the parameter of Eq() were declared as const T&, Eq("foo")
+// wouldn't compile.
+template <typename T>
+inline internal::EqMatcher<T> Eq(T x) { return internal::EqMatcher<T>(x); }
+
+// Constructs a Matcher<T> from a 'value' of type T.  The constructed
+// matcher matches any value that's equal to 'value'.
+template <typename T>
+Matcher<T>::Matcher(T value) { *this = Eq(value); }
+
+// Creates a monomorphic matcher that matches anything with type Lhs
+// and equal to rhs.  A user may need to use this instead of Eq(...)
+// in order to resolve an overloading ambiguity.
+//
+// TypedEq<T>(x) is just a convenient short-hand for Matcher<T>(Eq(x))
+// or Matcher<T>(x), but more readable than the latter.
+//
+// We could define similar monomorphic matchers for other comparison
+// operations (e.g. TypedLt, TypedGe, and etc), but decided not to do
+// it yet as those are used much less than Eq() in practice.  A user
+// can always write Matcher<T>(Lt(5)) to be explicit about the type,
+// for example.
+template <typename Lhs, typename Rhs>
+inline Matcher<Lhs> TypedEq(const Rhs& rhs) { return Eq(rhs); }
+
+// Creates a polymorphic matcher that matches anything >= x.
+template <typename Rhs>
+inline internal::GeMatcher<Rhs> Ge(Rhs x) {
+  return internal::GeMatcher<Rhs>(x);
+}
+
+// Creates a polymorphic matcher that matches anything > x.
+template <typename Rhs>
+inline internal::GtMatcher<Rhs> Gt(Rhs x) {
+  return internal::GtMatcher<Rhs>(x);
+}
+
+// Creates a polymorphic matcher that matches anything <= x.
+template <typename Rhs>
+inline internal::LeMatcher<Rhs> Le(Rhs x) {
+  return internal::LeMatcher<Rhs>(x);
+}
+
+// Creates a polymorphic matcher that matches anything < x.
+template <typename Rhs>
+inline internal::LtMatcher<Rhs> Lt(Rhs x) {
+  return internal::LtMatcher<Rhs>(x);
+}
+
+// Creates a polymorphic matcher that matches anything != x.
+template <typename Rhs>
+inline internal::NeMatcher<Rhs> Ne(Rhs x) {
+  return internal::NeMatcher<Rhs>(x);
+}
+
+// Creates a polymorphic matcher that matches any NULL pointer.
+inline PolymorphicMatcher<internal::IsNullMatcher > IsNull() {
+  return MakePolymorphicMatcher(internal::IsNullMatcher());
+}
+
+// Creates a polymorphic matcher that matches any non-NULL pointer.
+// This is convenient as Not(NULL) doesn't compile (the compiler
+// thinks that that expression is comparing a pointer with an integer).
+inline PolymorphicMatcher<internal::NotNullMatcher > NotNull() {
+  return MakePolymorphicMatcher(internal::NotNullMatcher());
+}
+
+// Creates a polymorphic matcher that matches any argument that
+// references variable x.
+template <typename T>
+inline internal::RefMatcher<T&> Ref(T& x) {  // NOLINT
+  return internal::RefMatcher<T&>(x);
+}
+
+// Creates a matcher that matches any double argument approximately
+// equal to rhs, where two NANs are considered unequal.
+inline internal::FloatingEqMatcher<double> DoubleEq(double rhs) {
+  return internal::FloatingEqMatcher<double>(rhs, false);
+}
+
+// Creates a matcher that matches any double argument approximately
+// equal to rhs, including NaN values when rhs is NaN.
+inline internal::FloatingEqMatcher<double> NanSensitiveDoubleEq(double rhs) {
+  return internal::FloatingEqMatcher<double>(rhs, true);
+}
+
+// Creates a matcher that matches any double argument approximately equal to
+// rhs, up to the specified max absolute error bound, where two NANs are
+// considered unequal.  The max absolute error bound must be non-negative.
+inline internal::FloatingEqMatcher<double> DoubleNear(
+    double rhs, double max_abs_error) {
+  return internal::FloatingEqMatcher<double>(rhs, false, max_abs_error);
+}
+
+// Creates a matcher that matches any double argument approximately equal to
+// rhs, up to the specified max absolute error bound, including NaN values when
+// rhs is NaN.  The max absolute error bound must be non-negative.
+inline internal::FloatingEqMatcher<double> NanSensitiveDoubleNear(
+    double rhs, double max_abs_error) {
+  return internal::FloatingEqMatcher<double>(rhs, true, max_abs_error);
+}
+
+// Creates a matcher that matches any float argument approximately
+// equal to rhs, where two NANs are considered unequal.
+inline internal::FloatingEqMatcher<float> FloatEq(float rhs) {
+  return internal::FloatingEqMatcher<float>(rhs, false);
+}
+
+// Creates a matcher that matches any float argument approximately
+// equal to rhs, including NaN values when rhs is NaN.
+inline internal::FloatingEqMatcher<float> NanSensitiveFloatEq(float rhs) {
+  return internal::FloatingEqMatcher<float>(rhs, true);
+}
+
+// Creates a matcher that matches any float argument approximately equal to
+// rhs, up to the specified max absolute error bound, where two NANs are
+// considered unequal.  The max absolute error bound must be non-negative.
+inline internal::FloatingEqMatcher<float> FloatNear(
+    float rhs, float max_abs_error) {
+  return internal::FloatingEqMatcher<float>(rhs, false, max_abs_error);
+}
+
+// Creates a matcher that matches any float argument approximately equal to
+// rhs, up to the specified max absolute error bound, including NaN values when
+// rhs is NaN.  The max absolute error bound must be non-negative.
+inline internal::FloatingEqMatcher<float> NanSensitiveFloatNear(
+    float rhs, float max_abs_error) {
+  return internal::FloatingEqMatcher<float>(rhs, true, max_abs_error);
+}
+
+// Creates a matcher that matches a pointer (raw or smart) that points
+// to a value that matches inner_matcher.
+template <typename InnerMatcher>
+inline internal::PointeeMatcher<InnerMatcher> Pointee(
+    const InnerMatcher& inner_matcher) {
+  return internal::PointeeMatcher<InnerMatcher>(inner_matcher);
+}
+
+// Creates a matcher that matches a pointer or reference that matches
+// inner_matcher when dynamic_cast<To> is applied.
+// The result of dynamic_cast<To> is forwarded to the inner matcher.
+// If To is a pointer and the cast fails, the inner matcher will receive NULL.
+// If To is a reference and the cast fails, this matcher returns false
+// immediately.
+template <typename To>
+inline PolymorphicMatcher<internal::WhenDynamicCastToMatcher<To> >
+WhenDynamicCastTo(const Matcher<To>& inner_matcher) {
+  return MakePolymorphicMatcher(
+      internal::WhenDynamicCastToMatcher<To>(inner_matcher));
+}
+
+// Creates a matcher that matches an object whose given field matches
+// 'matcher'.  For example,
+//   Field(&Foo::number, Ge(5))
+// matches a Foo object x iff x.number >= 5.
+template <typename Class, typename FieldType, typename FieldMatcher>
+inline PolymorphicMatcher<
+  internal::FieldMatcher<Class, FieldType> > Field(
+    FieldType Class::*field, const FieldMatcher& matcher) {
+  return MakePolymorphicMatcher(
+      internal::FieldMatcher<Class, FieldType>(
+          field, MatcherCast<const FieldType&>(matcher)));
+  // The call to MatcherCast() is required for supporting inner
+  // matchers of compatible types.  For example, it allows
+  //   Field(&Foo::bar, m)
+  // to compile where bar is an int32 and m is a matcher for int64.
+}
+
+// Creates a matcher that matches an object whose given property
+// matches 'matcher'.  For example,
+//   Property(&Foo::str, StartsWith("hi"))
+// matches a Foo object x iff x.str() starts with "hi".
+template <typename Class, typename PropertyType, typename PropertyMatcher>
+inline PolymorphicMatcher<
+  internal::PropertyMatcher<Class, PropertyType> > Property(
+    PropertyType (Class::*property)() const, const PropertyMatcher& matcher) {
+  return MakePolymorphicMatcher(
+      internal::PropertyMatcher<Class, PropertyType>(
+          property,
+          MatcherCast<GTEST_REFERENCE_TO_CONST_(PropertyType)>(matcher)));
+  // The call to MatcherCast() is required for supporting inner
+  // matchers of compatible types.  For example, it allows
+  //   Property(&Foo::bar, m)
+  // to compile where bar() returns an int32 and m is a matcher for int64.
+}
+
+// Creates a matcher that matches an object iff the result of applying
+// a callable to x matches 'matcher'.
+// For example,
+//   ResultOf(f, StartsWith("hi"))
+// matches a Foo object x iff f(x) starts with "hi".
+// callable parameter can be a function, function pointer, or a functor.
+// Callable has to satisfy the following conditions:
+//   * It is required to keep no state affecting the results of
+//     the calls on it and make no assumptions about how many calls
+//     will be made. Any state it keeps must be protected from the
+//     concurrent access.
+//   * If it is a function object, it has to define type result_type.
+//     We recommend deriving your functor classes from std::unary_function.
+template <typename Callable, typename ResultOfMatcher>
+internal::ResultOfMatcher<Callable> ResultOf(
+    Callable callable, const ResultOfMatcher& matcher) {
+  return internal::ResultOfMatcher<Callable>(
+          callable,
+          MatcherCast<typename internal::CallableTraits<Callable>::ResultType>(
+              matcher));
+  // The call to MatcherCast() is required for supporting inner
+  // matchers of compatible types.  For example, it allows
+  //   ResultOf(Function, m)
+  // to compile where Function() returns an int32 and m is a matcher for int64.
+}
+
+// String matchers.
+
+// Matches a string equal to str.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::string> >
+    StrEq(const internal::string& str) {
+  return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::string>(
+      str, true, true));
+}
+
+// Matches a string not equal to str.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::string> >
+    StrNe(const internal::string& str) {
+  return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::string>(
+      str, false, true));
+}
+
+// Matches a string equal to str, ignoring case.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::string> >
+    StrCaseEq(const internal::string& str) {
+  return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::string>(
+      str, true, false));
+}
+
+// Matches a string not equal to str, ignoring case.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::string> >
+    StrCaseNe(const internal::string& str) {
+  return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::string>(
+      str, false, false));
+}
+
+// Creates a matcher that matches any string, std::string, or C string
+// that contains the given substring.
+inline PolymorphicMatcher<internal::HasSubstrMatcher<internal::string> >
+    HasSubstr(const internal::string& substring) {
+  return MakePolymorphicMatcher(internal::HasSubstrMatcher<internal::string>(
+      substring));
+}
+
+// Matches a string that starts with 'prefix' (case-sensitive).
+inline PolymorphicMatcher<internal::StartsWithMatcher<internal::string> >
+    StartsWith(const internal::string& prefix) {
+  return MakePolymorphicMatcher(internal::StartsWithMatcher<internal::string>(
+      prefix));
+}
+
+// Matches a string that ends with 'suffix' (case-sensitive).
+inline PolymorphicMatcher<internal::EndsWithMatcher<internal::string> >
+    EndsWith(const internal::string& suffix) {
+  return MakePolymorphicMatcher(internal::EndsWithMatcher<internal::string>(
+      suffix));
+}
+
+// Matches a string that fully matches regular expression 'regex'.
+// The matcher takes ownership of 'regex'.
+inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
+    const internal::RE* regex) {
+  return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, true));
+}
+inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
+    const internal::string& regex) {
+  return MatchesRegex(new internal::RE(regex));
+}
+
+// Matches a string that contains regular expression 'regex'.
+// The matcher takes ownership of 'regex'.
+inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
+    const internal::RE* regex) {
+  return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, false));
+}
+inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
+    const internal::string& regex) {
+  return ContainsRegex(new internal::RE(regex));
+}
+
+#if GTEST_HAS_GLOBAL_WSTRING || GTEST_HAS_STD_WSTRING
+// Wide string matchers.
+
+// Matches a string equal to str.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::wstring> >
+    StrEq(const internal::wstring& str) {
+  return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::wstring>(
+      str, true, true));
+}
+
+// Matches a string not equal to str.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::wstring> >
+    StrNe(const internal::wstring& str) {
+  return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::wstring>(
+      str, false, true));
+}
+
+// Matches a string equal to str, ignoring case.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::wstring> >
+    StrCaseEq(const internal::wstring& str) {
+  return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::wstring>(
+      str, true, false));
+}
+
+// Matches a string not equal to str, ignoring case.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::wstring> >
+    StrCaseNe(const internal::wstring& str) {
+  return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::wstring>(
+      str, false, false));
+}
+
+// Creates a matcher that matches any wstring, std::wstring, or C wide string
+// that contains the given substring.
+inline PolymorphicMatcher<internal::HasSubstrMatcher<internal::wstring> >
+    HasSubstr(const internal::wstring& substring) {
+  return MakePolymorphicMatcher(internal::HasSubstrMatcher<internal::wstring>(
+      substring));
+}
+
+// Matches a string that starts with 'prefix' (case-sensitive).
+inline PolymorphicMatcher<internal::StartsWithMatcher<internal::wstring> >
+    StartsWith(const internal::wstring& prefix) {
+  return MakePolymorphicMatcher(internal::StartsWithMatcher<internal::wstring>(
+      prefix));
+}
+
+// Matches a string that ends with 'suffix' (case-sensitive).
+inline PolymorphicMatcher<internal::EndsWithMatcher<internal::wstring> >
+    EndsWith(const internal::wstring& suffix) {
+  return MakePolymorphicMatcher(internal::EndsWithMatcher<internal::wstring>(
+      suffix));
+}
+
+#endif  // GTEST_HAS_GLOBAL_WSTRING || GTEST_HAS_STD_WSTRING
+
+// Creates a polymorphic matcher that matches a 2-tuple where the
+// first field == the second field.
+inline internal::Eq2Matcher Eq() { return internal::Eq2Matcher(); }
+
+// Creates a polymorphic matcher that matches a 2-tuple where the
+// first field >= the second field.
+inline internal::Ge2Matcher Ge() { return internal::Ge2Matcher(); }
+
+// Creates a polymorphic matcher that matches a 2-tuple where the
+// first field > the second field.
+inline internal::Gt2Matcher Gt() { return internal::Gt2Matcher(); }
+
+// Creates a polymorphic matcher that matches a 2-tuple where the
+// first field <= the second field.
+inline internal::Le2Matcher Le() { return internal::Le2Matcher(); }
+
+// Creates a polymorphic matcher that matches a 2-tuple where the
+// first field < the second field.
+inline internal::Lt2Matcher Lt() { return internal::Lt2Matcher(); }
+
+// Creates a polymorphic matcher that matches a 2-tuple where the
+// first field != the second field.
+inline internal::Ne2Matcher Ne() { return internal::Ne2Matcher(); }
+
+// Creates a matcher that matches any value of type T that m doesn't
+// match.
+template <typename InnerMatcher>
+inline internal::NotMatcher<InnerMatcher> Not(InnerMatcher m) {
+  return internal::NotMatcher<InnerMatcher>(m);
+}
+
+// Returns a matcher that matches anything that satisfies the given
+// predicate.  The predicate can be any unary function or functor
+// whose return type can be implicitly converted to bool.
+template <typename Predicate>
+inline PolymorphicMatcher<internal::TrulyMatcher<Predicate> >
+Truly(Predicate pred) {
+  return MakePolymorphicMatcher(internal::TrulyMatcher<Predicate>(pred));
+}
+
+// Returns a matcher that matches the container size. The container must
+// support both size() and size_type which all STL-like containers provide.
+// Note that the parameter 'size' can be a value of type size_type as well as
+// matcher. For instance:
+//   EXPECT_THAT(container, SizeIs(2));     // Checks container has 2 elements.
+//   EXPECT_THAT(container, SizeIs(Le(2));  // Checks container has at most 2.
+template <typename SizeMatcher>
+inline internal::SizeIsMatcher<SizeMatcher>
+SizeIs(const SizeMatcher& size_matcher) {
+  return internal::SizeIsMatcher<SizeMatcher>(size_matcher);
+}
+
+// Returns a matcher that matches the distance between the container's begin()
+// iterator and its end() iterator, i.e. the size of the container. This matcher
+// can be used instead of SizeIs with containers such as std::forward_list which
+// do not implement size(). The container must provide const_iterator (with
+// valid iterator_traits), begin() and end().
+template <typename DistanceMatcher>
+inline internal::BeginEndDistanceIsMatcher<DistanceMatcher>
+BeginEndDistanceIs(const DistanceMatcher& distance_matcher) {
+  return internal::BeginEndDistanceIsMatcher<DistanceMatcher>(distance_matcher);
+}
+
+// Returns a matcher that matches an equal container.
+// This matcher behaves like Eq(), but in the event of mismatch lists the
+// values that are included in one container but not the other. (Duplicate
+// values and order differences are not explained.)
+template <typename Container>
+inline PolymorphicMatcher<internal::ContainerEqMatcher<  // NOLINT
+                            GTEST_REMOVE_CONST_(Container)> >
+    ContainerEq(const Container& rhs) {
+  // This following line is for working around a bug in MSVC 8.0,
+  // which causes Container to be a const type sometimes.
+  typedef GTEST_REMOVE_CONST_(Container) RawContainer;
+  return MakePolymorphicMatcher(
+      internal::ContainerEqMatcher<RawContainer>(rhs));
+}
+
+// Returns a matcher that matches a container that, when sorted using
+// the given comparator, matches container_matcher.
+template <typename Comparator, typename ContainerMatcher>
+inline internal::WhenSortedByMatcher<Comparator, ContainerMatcher>
+WhenSortedBy(const Comparator& comparator,
+             const ContainerMatcher& container_matcher) {
+  return internal::WhenSortedByMatcher<Comparator, ContainerMatcher>(
+      comparator, container_matcher);
+}
+
+// Returns a matcher that matches a container that, when sorted using
+// the < operator, matches container_matcher.
+template <typename ContainerMatcher>
+inline internal::WhenSortedByMatcher<internal::LessComparator, ContainerMatcher>
+WhenSorted(const ContainerMatcher& container_matcher) {
+  return
+      internal::WhenSortedByMatcher<internal::LessComparator, ContainerMatcher>(
+          internal::LessComparator(), container_matcher);
+}
+
+// Matches an STL-style container or a native array that contains the
+// same number of elements as in rhs, where its i-th element and rhs's
+// i-th element (as a pair) satisfy the given pair matcher, for all i.
+// TupleMatcher must be able to be safely cast to Matcher<tuple<const
+// T1&, const T2&> >, where T1 and T2 are the types of elements in the
+// LHS container and the RHS container respectively.
+template <typename TupleMatcher, typename Container>
+inline internal::PointwiseMatcher<TupleMatcher,
+                                  GTEST_REMOVE_CONST_(Container)>
+Pointwise(const TupleMatcher& tuple_matcher, const Container& rhs) {
+  // This following line is for working around a bug in MSVC 8.0,
+  // which causes Container to be a const type sometimes (e.g. when
+  // rhs is a const int[])..
+  typedef GTEST_REMOVE_CONST_(Container) RawContainer;
+  return internal::PointwiseMatcher<TupleMatcher, RawContainer>(
+      tuple_matcher, rhs);
+}
+
+#if GTEST_HAS_STD_INITIALIZER_LIST_
+
+// Supports the Pointwise(m, {a, b, c}) syntax.
+template <typename TupleMatcher, typename T>
+inline internal::PointwiseMatcher<TupleMatcher, std::vector<T> > Pointwise(
+    const TupleMatcher& tuple_matcher, std::initializer_list<T> rhs) {
+  return Pointwise(tuple_matcher, std::vector<T>(rhs));
+}
+
+#endif  // GTEST_HAS_STD_INITIALIZER_LIST_
+
+// UnorderedPointwise(pair_matcher, rhs) matches an STL-style
+// container or a native array that contains the same number of
+// elements as in rhs, where in some permutation of the container, its
+// i-th element and rhs's i-th element (as a pair) satisfy the given
+// pair matcher, for all i.  Tuple2Matcher must be able to be safely
+// cast to Matcher<tuple<const T1&, const T2&> >, where T1 and T2 are
+// the types of elements in the LHS container and the RHS container
+// respectively.
+//
+// This is like Pointwise(pair_matcher, rhs), except that the element
+// order doesn't matter.
+template <typename Tuple2Matcher, typename RhsContainer>
+inline internal::UnorderedElementsAreArrayMatcher<
+    typename internal::BoundSecondMatcher<
+        Tuple2Matcher, typename internal::StlContainerView<GTEST_REMOVE_CONST_(
+                           RhsContainer)>::type::value_type> >
+UnorderedPointwise(const Tuple2Matcher& tuple2_matcher,
+                   const RhsContainer& rhs_container) {
+  // This following line is for working around a bug in MSVC 8.0,
+  // which causes RhsContainer to be a const type sometimes (e.g. when
+  // rhs_container is a const int[]).
+  typedef GTEST_REMOVE_CONST_(RhsContainer) RawRhsContainer;
+
+  // RhsView allows the same code to handle RhsContainer being a
+  // STL-style container and it being a native C-style array.
+  typedef typename internal::StlContainerView<RawRhsContainer> RhsView;
+  typedef typename RhsView::type RhsStlContainer;
+  typedef typename RhsStlContainer::value_type Second;
+  const RhsStlContainer& rhs_stl_container =
+      RhsView::ConstReference(rhs_container);
+
+  // Create a matcher for each element in rhs_container.
+  ::std::vector<internal::BoundSecondMatcher<Tuple2Matcher, Second> > matchers;
+  for (typename RhsStlContainer::const_iterator it = rhs_stl_container.begin();
+       it != rhs_stl_container.end(); ++it) {
+    matchers.push_back(
+        internal::MatcherBindSecond(tuple2_matcher, *it));
+  }
+
+  // Delegate the work to UnorderedElementsAreArray().
+  return UnorderedElementsAreArray(matchers);
+}
+
+#if GTEST_HAS_STD_INITIALIZER_LIST_
+
+// Supports the UnorderedPointwise(m, {a, b, c}) syntax.
+template <typename Tuple2Matcher, typename T>
+inline internal::UnorderedElementsAreArrayMatcher<
+    typename internal::BoundSecondMatcher<Tuple2Matcher, T> >
+UnorderedPointwise(const Tuple2Matcher& tuple2_matcher,
+                   std::initializer_list<T> rhs) {
+  return UnorderedPointwise(tuple2_matcher, std::vector<T>(rhs));
+}
+
+#endif  // GTEST_HAS_STD_INITIALIZER_LIST_
+
+// Matches an STL-style container or a native array that contains at
+// least one element matching the given value or matcher.
+//
+// Examples:
+//   ::std::set<int> page_ids;
+//   page_ids.insert(3);
+//   page_ids.insert(1);
+//   EXPECT_THAT(page_ids, Contains(1));
+//   EXPECT_THAT(page_ids, Contains(Gt(2)));
+//   EXPECT_THAT(page_ids, Not(Contains(4)));
+//
+//   ::std::map<int, size_t> page_lengths;
+//   page_lengths[1] = 100;
+//   EXPECT_THAT(page_lengths,
+//               Contains(::std::pair<const int, size_t>(1, 100)));
+//
+//   const char* user_ids[] = { "joe", "mike", "tom" };
+//   EXPECT_THAT(user_ids, Contains(Eq(::std::string("tom"))));
+template <typename M>
+inline internal::ContainsMatcher<M> Contains(M matcher) {
+  return internal::ContainsMatcher<M>(matcher);
+}
+
+// Matches an STL-style container or a native array that contains only
+// elements matching the given value or matcher.
+//
+// Each(m) is semantically equivalent to Not(Contains(Not(m))). Only
+// the messages are different.
+//
+// Examples:
+//   ::std::set<int> page_ids;
+//   // Each(m) matches an empty container, regardless of what m is.
+//   EXPECT_THAT(page_ids, Each(Eq(1)));
+//   EXPECT_THAT(page_ids, Each(Eq(77)));
+//
+//   page_ids.insert(3);
+//   EXPECT_THAT(page_ids, Each(Gt(0)));
+//   EXPECT_THAT(page_ids, Not(Each(Gt(4))));
+//   page_ids.insert(1);
+//   EXPECT_THAT(page_ids, Not(Each(Lt(2))));
+//
+//   ::std::map<int, size_t> page_lengths;
+//   page_lengths[1] = 100;
+//   page_lengths[2] = 200;
+//   page_lengths[3] = 300;
+//   EXPECT_THAT(page_lengths, Not(Each(Pair(1, 100))));
+//   EXPECT_THAT(page_lengths, Each(Key(Le(3))));
+//
+//   const char* user_ids[] = { "joe", "mike", "tom" };
+//   EXPECT_THAT(user_ids, Not(Each(Eq(::std::string("tom")))));
+template <typename M>
+inline internal::EachMatcher<M> Each(M matcher) {
+  return internal::EachMatcher<M>(matcher);
+}
+
+// Key(inner_matcher) matches an std::pair whose 'first' field matches
+// inner_matcher.  For example, Contains(Key(Ge(5))) can be used to match an
+// std::map that contains at least one element whose key is >= 5.
+template <typename M>
+inline internal::KeyMatcher<M> Key(M inner_matcher) {
+  return internal::KeyMatcher<M>(inner_matcher);
+}
+
+// Pair(first_matcher, second_matcher) matches a std::pair whose 'first' field
+// matches first_matcher and whose 'second' field matches second_matcher.  For
+// example, EXPECT_THAT(map_type, ElementsAre(Pair(Ge(5), "foo"))) can be used
+// to match a std::map<int, string> that contains exactly one element whose key
+// is >= 5 and whose value equals "foo".
+template <typename FirstMatcher, typename SecondMatcher>
+inline internal::PairMatcher<FirstMatcher, SecondMatcher>
+Pair(FirstMatcher first_matcher, SecondMatcher second_matcher) {
+  return internal::PairMatcher<FirstMatcher, SecondMatcher>(
+      first_matcher, second_matcher);
+}
+
+// Returns a predicate that is satisfied by anything that matches the
+// given matcher.
+template <typename M>
+inline internal::MatcherAsPredicate<M> Matches(M matcher) {
+  return internal::MatcherAsPredicate<M>(matcher);
+}
+
+// Returns true iff the value matches the matcher.
+template <typename T, typename M>
+inline bool Value(const T& value, M matcher) {
+  return testing::Matches(matcher)(value);
+}
+
+// Matches the value against the given matcher and explains the match
+// result to listener.
+template <typename T, typename M>
+inline bool ExplainMatchResult(
+    M matcher, const T& value, MatchResultListener* listener) {
+  return SafeMatcherCast<const T&>(matcher).MatchAndExplain(value, listener);
+}
+
+#if GTEST_LANG_CXX11
+// Define variadic matcher versions. They are overloaded in
+// gmock-generated-matchers.h for the cases supported by pre C++11 compilers.
+template <typename... Args>
+inline internal::AllOfMatcher<Args...> AllOf(const Args&... matchers) {
+  return internal::AllOfMatcher<Args...>(matchers...);
+}
+
+template <typename... Args>
+inline internal::AnyOfMatcher<Args...> AnyOf(const Args&... matchers) {
+  return internal::AnyOfMatcher<Args...>(matchers...);
+}
+
+#endif  // GTEST_LANG_CXX11
+
+// AllArgs(m) is a synonym of m.  This is useful in
+//
+//   EXPECT_CALL(foo, Bar(_, _)).With(AllArgs(Eq()));
+//
+// which is easier to read than
+//
+//   EXPECT_CALL(foo, Bar(_, _)).With(Eq());
+template <typename InnerMatcher>
+inline InnerMatcher AllArgs(const InnerMatcher& matcher) { return matcher; }
+
+// These macros allow using matchers to check values in Google Test
+// tests.  ASSERT_THAT(value, matcher) and EXPECT_THAT(value, matcher)
+// succeed iff the value matches the matcher.  If the assertion fails,
+// the value and the description of the matcher will be printed.
+#define ASSERT_THAT(value, matcher) ASSERT_PRED_FORMAT1(\
+    ::testing::internal::MakePredicateFormatterFromMatcher(matcher), value)
+#define EXPECT_THAT(value, matcher) EXPECT_PRED_FORMAT1(\
+    ::testing::internal::MakePredicateFormatterFromMatcher(matcher), value)
+
+}  // namespace testing
+
+// Include any custom callback matchers added by the local installation.
+// We must include this header at the end to make sure it can use the
+// declarations from this file.
+#include "gmock/internal/custom/gmock-matchers.h"
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_
diff --git a/third_party/googletest/googlemock/include/gmock/gmock-more-actions.h b/third_party/googletest/googlemock/include/gmock/gmock-more-actions.h
new file mode 100644
index 0000000..3d387b6
--- /dev/null
+++ b/third_party/googletest/googlemock/include/gmock/gmock-more-actions.h
@@ -0,0 +1,246 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements some actions that depend on gmock-generated-actions.h.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
+
+#include <algorithm>
+
+#include "gmock/gmock-generated-actions.h"
+
+namespace testing {
+namespace internal {
+
+// Implements the Invoke(f) action.  The template argument
+// FunctionImpl is the implementation type of f, which can be either a
+// function pointer or a functor.  Invoke(f) can be used as an
+// Action<F> as long as f's type is compatible with F (i.e. f can be
+// assigned to a tr1::function<F>).
+template <typename FunctionImpl>
+class InvokeAction {
+ public:
+  // The c'tor makes a copy of function_impl (either a function
+  // pointer or a functor).
+  explicit InvokeAction(FunctionImpl function_impl)
+      : function_impl_(function_impl) {}
+
+  template <typename Result, typename ArgumentTuple>
+  Result Perform(const ArgumentTuple& args) {
+    return InvokeHelper<Result, ArgumentTuple>::Invoke(function_impl_, args);
+  }
+
+ private:
+  FunctionImpl function_impl_;
+
+  GTEST_DISALLOW_ASSIGN_(InvokeAction);
+};
+
+// Implements the Invoke(object_ptr, &Class::Method) action.
+template <class Class, typename MethodPtr>
+class InvokeMethodAction {
+ public:
+  InvokeMethodAction(Class* obj_ptr, MethodPtr method_ptr)
+      : method_ptr_(method_ptr), obj_ptr_(obj_ptr) {}
+
+  template <typename Result, typename ArgumentTuple>
+  Result Perform(const ArgumentTuple& args) const {
+    return InvokeHelper<Result, ArgumentTuple>::InvokeMethod(
+        obj_ptr_, method_ptr_, args);
+  }
+
+ private:
+  // The order of these members matters.  Reversing the order can trigger
+  // warning C4121 in MSVC (see
+  // http://computer-programming-forum.com/7-vc.net/6fbc30265f860ad1.htm ).
+  const MethodPtr method_ptr_;
+  Class* const obj_ptr_;
+
+  GTEST_DISALLOW_ASSIGN_(InvokeMethodAction);
+};
+
+// An internal replacement for std::copy which mimics its behavior. This is
+// necessary because Visual Studio deprecates ::std::copy, issuing warning 4996.
+// However Visual Studio 2010 and later do not honor #pragmas which disable that
+// warning.
+template<typename InputIterator, typename OutputIterator>
+inline OutputIterator CopyElements(InputIterator first,
+                                   InputIterator last,
+                                   OutputIterator output) {
+  for (; first != last; ++first, ++output) {
+    *output = *first;
+  }
+  return output;
+}
+
+}  // namespace internal
+
+// Various overloads for Invoke().
+
+// Creates an action that invokes 'function_impl' with the mock
+// function's arguments.
+template <typename FunctionImpl>
+PolymorphicAction<internal::InvokeAction<FunctionImpl> > Invoke(
+    FunctionImpl function_impl) {
+  return MakePolymorphicAction(
+      internal::InvokeAction<FunctionImpl>(function_impl));
+}
+
+// Creates an action that invokes the given method on the given object
+// with the mock function's arguments.
+template <class Class, typename MethodPtr>
+PolymorphicAction<internal::InvokeMethodAction<Class, MethodPtr> > Invoke(
+    Class* obj_ptr, MethodPtr method_ptr) {
+  return MakePolymorphicAction(
+      internal::InvokeMethodAction<Class, MethodPtr>(obj_ptr, method_ptr));
+}
+
+// WithoutArgs(inner_action) can be used in a mock function with a
+// non-empty argument list to perform inner_action, which takes no
+// argument.  In other words, it adapts an action accepting no
+// argument to one that accepts (and ignores) arguments.
+template <typename InnerAction>
+inline internal::WithArgsAction<InnerAction>
+WithoutArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction>(action);
+}
+
+// WithArg<k>(an_action) creates an action that passes the k-th
+// (0-based) argument of the mock function to an_action and performs
+// it.  It adapts an action accepting one argument to one that accepts
+// multiple arguments.  For convenience, we also provide
+// WithArgs<k>(an_action) (defined below) as a synonym.
+template <int k, typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k>
+WithArg(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k>(action);
+}
+
+// The ACTION*() macros trigger warning C4100 (unreferenced formal
+// parameter) in MSVC with -W4.  Unfortunately they cannot be fixed in
+// the macro definition, as the warnings are generated when the macro
+// is expanded and macro expansion cannot contain #pragma.  Therefore
+// we suppress them here.
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4100)
+#endif
+
+// Action ReturnArg<k>() returns the k-th argument of the mock function.
+ACTION_TEMPLATE(ReturnArg,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_0_VALUE_PARAMS()) {
+  return ::testing::get<k>(args);
+}
+
+// Action SaveArg<k>(pointer) saves the k-th (0-based) argument of the
+// mock function to *pointer.
+ACTION_TEMPLATE(SaveArg,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_1_VALUE_PARAMS(pointer)) {
+  *pointer = ::testing::get<k>(args);
+}
+
+// Action SaveArgPointee<k>(pointer) saves the value pointed to
+// by the k-th (0-based) argument of the mock function to *pointer.
+ACTION_TEMPLATE(SaveArgPointee,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_1_VALUE_PARAMS(pointer)) {
+  *pointer = *::testing::get<k>(args);
+}
+
+// Action SetArgReferee<k>(value) assigns 'value' to the variable
+// referenced by the k-th (0-based) argument of the mock function.
+ACTION_TEMPLATE(SetArgReferee,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_1_VALUE_PARAMS(value)) {
+  typedef typename ::testing::tuple_element<k, args_type>::type argk_type;
+  // Ensures that argument #k is a reference.  If you get a compiler
+  // error on the next line, you are using SetArgReferee<k>(value) in
+  // a mock function whose k-th (0-based) argument is not a reference.
+  GTEST_COMPILE_ASSERT_(internal::is_reference<argk_type>::value,
+                        SetArgReferee_must_be_used_with_a_reference_argument);
+  ::testing::get<k>(args) = value;
+}
+
+// Action SetArrayArgument<k>(first, last) copies the elements in
+// source range [first, last) to the array pointed to by the k-th
+// (0-based) argument, which can be either a pointer or an
+// iterator. The action does not take ownership of the elements in the
+// source range.
+ACTION_TEMPLATE(SetArrayArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_2_VALUE_PARAMS(first, last)) {
+  // Visual Studio deprecates ::std::copy, so we use our own copy in that case.
+#ifdef _MSC_VER
+  internal::CopyElements(first, last, ::testing::get<k>(args));
+#else
+  ::std::copy(first, last, ::testing::get<k>(args));
+#endif
+}
+
+// Action DeleteArg<k>() deletes the k-th (0-based) argument of the mock
+// function.
+ACTION_TEMPLATE(DeleteArg,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_0_VALUE_PARAMS()) {
+  delete ::testing::get<k>(args);
+}
+
+// This action returns the value pointed to by 'pointer'.
+ACTION_P(ReturnPointee, pointer) { return *pointer; }
+
+// Action Throw(exception) can be used in a mock function of any type
+// to throw the given exception.  Any copyable value can be thrown.
+#if GTEST_HAS_EXCEPTIONS
+
+// Suppresses the 'unreachable code' warning that VC generates in opt modes.
+# ifdef _MSC_VER
+#  pragma warning(push)          // Saves the current warning state.
+#  pragma warning(disable:4702)  // Temporarily disables warning 4702.
+# endif
+ACTION_P(Throw, exception) { throw exception; }
+# ifdef _MSC_VER
+#  pragma warning(pop)           // Restores the warning state.
+# endif
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
diff --git a/third_party/googletest/googlemock/include/gmock/gmock-more-matchers.h b/third_party/googletest/googlemock/include/gmock/gmock-more-matchers.h
new file mode 100644
index 0000000..3db899f
--- /dev/null
+++ b/third_party/googletest/googlemock/include/gmock/gmock-more-matchers.h
@@ -0,0 +1,58 @@
+// Copyright 2013, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: marcus.boerger@google.com (Marcus Boerger)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements some matchers that depend on gmock-generated-matchers.h.
+//
+// Note that tests are implemented in gmock-matchers_test.cc rather than
+// gmock-more-matchers-test.cc.
+
+#ifndef GMOCK_GMOCK_MORE_MATCHERS_H_
+#define GMOCK_GMOCK_MORE_MATCHERS_H_
+
+#include "gmock/gmock-generated-matchers.h"
+
+namespace testing {
+
+// Defines a matcher that matches an empty container. The container must
+// support both size() and empty(), which all STL-like containers provide.
+MATCHER(IsEmpty, negation ? "isn't empty" : "is empty") {
+  if (arg.empty()) {
+    return true;
+  }
+  *result_listener << "whose size is " << arg.size();
+  return false;
+}
+
+}  // namespace testing
+
+#endif  // GMOCK_GMOCK_MORE_MATCHERS_H_
diff --git a/third_party/googletest/googlemock/include/gmock/gmock-spec-builders.h b/third_party/googletest/googlemock/include/gmock/gmock-spec-builders.h
new file mode 100644
index 0000000..fed7de6
--- /dev/null
+++ b/third_party/googletest/googlemock/include/gmock/gmock-spec-builders.h
@@ -0,0 +1,1847 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements the ON_CALL() and EXPECT_CALL() macros.
+//
+// A user can use the ON_CALL() macro to specify the default action of
+// a mock method.  The syntax is:
+//
+//   ON_CALL(mock_object, Method(argument-matchers))
+//       .With(multi-argument-matcher)
+//       .WillByDefault(action);
+//
+//  where the .With() clause is optional.
+//
+// A user can use the EXPECT_CALL() macro to specify an expectation on
+// a mock method.  The syntax is:
+//
+//   EXPECT_CALL(mock_object, Method(argument-matchers))
+//       .With(multi-argument-matchers)
+//       .Times(cardinality)
+//       .InSequence(sequences)
+//       .After(expectations)
+//       .WillOnce(action)
+//       .WillRepeatedly(action)
+//       .RetiresOnSaturation();
+//
+// where all clauses are optional, and .InSequence()/.After()/
+// .WillOnce() can appear any number of times.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_SPEC_BUILDERS_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_SPEC_BUILDERS_H_
+
+#include <map>
+#include <set>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#if GTEST_HAS_EXCEPTIONS
+# include <stdexcept>  // NOLINT
+#endif
+
+#include "gmock/gmock-actions.h"
+#include "gmock/gmock-cardinalities.h"
+#include "gmock/gmock-matchers.h"
+#include "gmock/internal/gmock-internal-utils.h"
+#include "gmock/internal/gmock-port.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+
+// An abstract handle of an expectation.
+class Expectation;
+
+// A set of expectation handles.
+class ExpectationSet;
+
+// Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION
+// and MUST NOT BE USED IN USER CODE!!!
+namespace internal {
+
+// Implements a mock function.
+template <typename F> class FunctionMocker;
+
+// Base class for expectations.
+class ExpectationBase;
+
+// Implements an expectation.
+template <typename F> class TypedExpectation;
+
+// Helper class for testing the Expectation class template.
+class ExpectationTester;
+
+// Base class for function mockers.
+template <typename F> class FunctionMockerBase;
+
+// Protects the mock object registry (in class Mock), all function
+// mockers, and all expectations.
+//
+// The reason we don't use more fine-grained protection is: when a
+// mock function Foo() is called, it needs to consult its expectations
+// to see which one should be picked.  If another thread is allowed to
+// call a mock function (either Foo() or a different one) at the same
+// time, it could affect the "retired" attributes of Foo()'s
+// expectations when InSequence() is used, and thus affect which
+// expectation gets picked.  Therefore, we sequence all mock function
+// calls to ensure the integrity of the mock objects' states.
+GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_gmock_mutex);
+
+// Untyped base class for ActionResultHolder<R>.
+class UntypedActionResultHolderBase;
+
+// Abstract base class of FunctionMockerBase.  This is the
+// type-agnostic part of the function mocker interface.  Its pure
+// virtual methods are implemented by FunctionMockerBase.
+class GTEST_API_ UntypedFunctionMockerBase {
+ public:
+  UntypedFunctionMockerBase();
+  virtual ~UntypedFunctionMockerBase();
+
+  // Verifies that all expectations on this mock function have been
+  // satisfied.  Reports one or more Google Test non-fatal failures
+  // and returns false if not.
+  bool VerifyAndClearExpectationsLocked()
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex);
+
+  // Clears the ON_CALL()s set on this mock function.
+  virtual void ClearDefaultActionsLocked()
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) = 0;
+
+  // In all of the following Untyped* functions, it's the caller's
+  // responsibility to guarantee the correctness of the arguments'
+  // types.
+
+  // Performs the default action with the given arguments and returns
+  // the action's result.  The call description string will be used in
+  // the error message to describe the call in the case the default
+  // action fails.
+  // L = *
+  virtual UntypedActionResultHolderBase* UntypedPerformDefaultAction(
+      const void* untyped_args,
+      const string& call_description) const = 0;
+
+  // Performs the given action with the given arguments and returns
+  // the action's result.
+  // L = *
+  virtual UntypedActionResultHolderBase* UntypedPerformAction(
+      const void* untyped_action,
+      const void* untyped_args) const = 0;
+
+  // Writes a message that the call is uninteresting (i.e. neither
+  // explicitly expected nor explicitly unexpected) to the given
+  // ostream.
+  virtual void UntypedDescribeUninterestingCall(
+      const void* untyped_args,
+      ::std::ostream* os) const
+          GTEST_LOCK_EXCLUDED_(g_gmock_mutex) = 0;
+
+  // Returns the expectation that matches the given function arguments
+  // (or NULL is there's no match); when a match is found,
+  // untyped_action is set to point to the action that should be
+  // performed (or NULL if the action is "do default"), and
+  // is_excessive is modified to indicate whether the call exceeds the
+  // expected number.
+  virtual const ExpectationBase* UntypedFindMatchingExpectation(
+      const void* untyped_args,
+      const void** untyped_action, bool* is_excessive,
+      ::std::ostream* what, ::std::ostream* why)
+          GTEST_LOCK_EXCLUDED_(g_gmock_mutex) = 0;
+
+  // Prints the given function arguments to the ostream.
+  virtual void UntypedPrintArgs(const void* untyped_args,
+                                ::std::ostream* os) const = 0;
+
+  // Sets the mock object this mock method belongs to, and registers
+  // this information in the global mock registry.  Will be called
+  // whenever an EXPECT_CALL() or ON_CALL() is executed on this mock
+  // method.
+  // TODO(wan@google.com): rename to SetAndRegisterOwner().
+  void RegisterOwner(const void* mock_obj)
+      GTEST_LOCK_EXCLUDED_(g_gmock_mutex);
+
+  // Sets the mock object this mock method belongs to, and sets the
+  // name of the mock function.  Will be called upon each invocation
+  // of this mock function.
+  void SetOwnerAndName(const void* mock_obj, const char* name)
+      GTEST_LOCK_EXCLUDED_(g_gmock_mutex);
+
+  // Returns the mock object this mock method belongs to.  Must be
+  // called after RegisterOwner() or SetOwnerAndName() has been
+  // called.
+  const void* MockObject() const
+      GTEST_LOCK_EXCLUDED_(g_gmock_mutex);
+
+  // Returns the name of this mock method.  Must be called after
+  // SetOwnerAndName() has been called.
+  const char* Name() const
+      GTEST_LOCK_EXCLUDED_(g_gmock_mutex);
+
+  // Returns the result of invoking this mock function with the given
+  // arguments.  This function can be safely called from multiple
+  // threads concurrently.  The caller is responsible for deleting the
+  // result.
+  UntypedActionResultHolderBase* UntypedInvokeWith(
+      const void* untyped_args)
+          GTEST_LOCK_EXCLUDED_(g_gmock_mutex);
+
+ protected:
+  typedef std::vector<const void*> UntypedOnCallSpecs;
+
+  typedef std::vector<internal::linked_ptr<ExpectationBase> >
+  UntypedExpectations;
+
+  // Returns an Expectation object that references and co-owns exp,
+  // which must be an expectation on this mock function.
+  Expectation GetHandleOf(ExpectationBase* exp);
+
+  // Address of the mock object this mock method belongs to.  Only
+  // valid after this mock method has been called or
+  // ON_CALL/EXPECT_CALL has been invoked on it.
+  const void* mock_obj_;  // Protected by g_gmock_mutex.
+
+  // Name of the function being mocked.  Only valid after this mock
+  // method has been called.
+  const char* name_;  // Protected by g_gmock_mutex.
+
+  // All default action specs for this function mocker.
+  UntypedOnCallSpecs untyped_on_call_specs_;
+
+  // All expectations for this function mocker.
+  UntypedExpectations untyped_expectations_;
+};  // class UntypedFunctionMockerBase
+
+// Untyped base class for OnCallSpec<F>.
+class UntypedOnCallSpecBase {
+ public:
+  // The arguments are the location of the ON_CALL() statement.
+  UntypedOnCallSpecBase(const char* a_file, int a_line)
+      : file_(a_file), line_(a_line), last_clause_(kNone) {}
+
+  // Where in the source file was the default action spec defined?
+  const char* file() const { return file_; }
+  int line() const { return line_; }
+
+ protected:
+  // Gives each clause in the ON_CALL() statement a name.
+  enum Clause {
+    // Do not change the order of the enum members!  The run-time
+    // syntax checking relies on it.
+    kNone,
+    kWith,
+    kWillByDefault
+  };
+
+  // Asserts that the ON_CALL() statement has a certain property.
+  void AssertSpecProperty(bool property, const string& failure_message) const {
+    Assert(property, file_, line_, failure_message);
+  }
+
+  // Expects that the ON_CALL() statement has a certain property.
+  void ExpectSpecProperty(bool property, const string& failure_message) const {
+    Expect(property, file_, line_, failure_message);
+  }
+
+  const char* file_;
+  int line_;
+
+  // The last clause in the ON_CALL() statement as seen so far.
+  // Initially kNone and changes as the statement is parsed.
+  Clause last_clause_;
+};  // class UntypedOnCallSpecBase
+
+// This template class implements an ON_CALL spec.
+template <typename F>
+class OnCallSpec : public UntypedOnCallSpecBase {
+ public:
+  typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+  typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple;
+
+  // Constructs an OnCallSpec object from the information inside
+  // the parenthesis of an ON_CALL() statement.
+  OnCallSpec(const char* a_file, int a_line,
+             const ArgumentMatcherTuple& matchers)
+      : UntypedOnCallSpecBase(a_file, a_line),
+        matchers_(matchers),
+        // By default, extra_matcher_ should match anything.  However,
+        // we cannot initialize it with _ as that triggers a compiler
+        // bug in Symbian's C++ compiler (cannot decide between two
+        // overloaded constructors of Matcher<const ArgumentTuple&>).
+        extra_matcher_(A<const ArgumentTuple&>()) {
+  }
+
+  // Implements the .With() clause.
+  OnCallSpec& With(const Matcher<const ArgumentTuple&>& m) {
+    // Makes sure this is called at most once.
+    ExpectSpecProperty(last_clause_ < kWith,
+                       ".With() cannot appear "
+                       "more than once in an ON_CALL().");
+    last_clause_ = kWith;
+
+    extra_matcher_ = m;
+    return *this;
+  }
+
+  // Implements the .WillByDefault() clause.
+  OnCallSpec& WillByDefault(const Action<F>& action) {
+    ExpectSpecProperty(last_clause_ < kWillByDefault,
+                       ".WillByDefault() must appear "
+                       "exactly once in an ON_CALL().");
+    last_clause_ = kWillByDefault;
+
+    ExpectSpecProperty(!action.IsDoDefault(),
+                       "DoDefault() cannot be used in ON_CALL().");
+    action_ = action;
+    return *this;
+  }
+
+  // Returns true iff the given arguments match the matchers.
+  bool Matches(const ArgumentTuple& args) const {
+    return TupleMatches(matchers_, args) && extra_matcher_.Matches(args);
+  }
+
+  // Returns the action specified by the user.
+  const Action<F>& GetAction() const {
+    AssertSpecProperty(last_clause_ == kWillByDefault,
+                       ".WillByDefault() must appear exactly "
+                       "once in an ON_CALL().");
+    return action_;
+  }
+
+ private:
+  // The information in statement
+  //
+  //   ON_CALL(mock_object, Method(matchers))
+  //       .With(multi-argument-matcher)
+  //       .WillByDefault(action);
+  //
+  // is recorded in the data members like this:
+  //
+  //   source file that contains the statement => file_
+  //   line number of the statement            => line_
+  //   matchers                                => matchers_
+  //   multi-argument-matcher                  => extra_matcher_
+  //   action                                  => action_
+  ArgumentMatcherTuple matchers_;
+  Matcher<const ArgumentTuple&> extra_matcher_;
+  Action<F> action_;
+};  // class OnCallSpec
+
+// Possible reactions on uninteresting calls.
+enum CallReaction {
+  kAllow,
+  kWarn,
+  kFail,
+  kDefault = kWarn  // By default, warn about uninteresting calls.
+};
+
+}  // namespace internal
+
+// Utilities for manipulating mock objects.
+class GTEST_API_ Mock {
+ public:
+  // The following public methods can be called concurrently.
+
+  // Tells Google Mock to ignore mock_obj when checking for leaked
+  // mock objects.
+  static void AllowLeak(const void* mock_obj)
+      GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex);
+
+  // Verifies and clears all expectations on the given mock object.
+  // If the expectations aren't satisfied, generates one or more
+  // Google Test non-fatal failures and returns false.
+  static bool VerifyAndClearExpectations(void* mock_obj)
+      GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex);
+
+  // Verifies all expectations on the given mock object and clears its
+  // default actions and expectations.  Returns true iff the
+  // verification was successful.
+  static bool VerifyAndClear(void* mock_obj)
+      GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex);
+
+ private:
+  friend class internal::UntypedFunctionMockerBase;
+
+  // Needed for a function mocker to register itself (so that we know
+  // how to clear a mock object).
+  template <typename F>
+  friend class internal::FunctionMockerBase;
+
+  template <typename M>
+  friend class NiceMock;
+
+  template <typename M>
+  friend class NaggyMock;
+
+  template <typename M>
+  friend class StrictMock;
+
+  // Tells Google Mock to allow uninteresting calls on the given mock
+  // object.
+  static void AllowUninterestingCalls(const void* mock_obj)
+      GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex);
+
+  // Tells Google Mock to warn the user about uninteresting calls on
+  // the given mock object.
+  static void WarnUninterestingCalls(const void* mock_obj)
+      GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex);
+
+  // Tells Google Mock to fail uninteresting calls on the given mock
+  // object.
+  static void FailUninterestingCalls(const void* mock_obj)
+      GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex);
+
+  // Tells Google Mock the given mock object is being destroyed and
+  // its entry in the call-reaction table should be removed.
+  static void UnregisterCallReaction(const void* mock_obj)
+      GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex);
+
+  // Returns the reaction Google Mock will have on uninteresting calls
+  // made on the given mock object.
+  static internal::CallReaction GetReactionOnUninterestingCalls(
+      const void* mock_obj)
+          GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex);
+
+  // Verifies that all expectations on the given mock object have been
+  // satisfied.  Reports one or more Google Test non-fatal failures
+  // and returns false if not.
+  static bool VerifyAndClearExpectationsLocked(void* mock_obj)
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(internal::g_gmock_mutex);
+
+  // Clears all ON_CALL()s set on the given mock object.
+  static void ClearDefaultActionsLocked(void* mock_obj)
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(internal::g_gmock_mutex);
+
+  // Registers a mock object and a mock method it owns.
+  static void Register(
+      const void* mock_obj,
+      internal::UntypedFunctionMockerBase* mocker)
+          GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex);
+
+  // Tells Google Mock where in the source code mock_obj is used in an
+  // ON_CALL or EXPECT_CALL.  In case mock_obj is leaked, this
+  // information helps the user identify which object it is.
+  static void RegisterUseByOnCallOrExpectCall(
+      const void* mock_obj, const char* file, int line)
+          GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex);
+
+  // Unregisters a mock method; removes the owning mock object from
+  // the registry when the last mock method associated with it has
+  // been unregistered.  This is called only in the destructor of
+  // FunctionMockerBase.
+  static void UnregisterLocked(internal::UntypedFunctionMockerBase* mocker)
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(internal::g_gmock_mutex);
+};  // class Mock
+
+// An abstract handle of an expectation.  Useful in the .After()
+// clause of EXPECT_CALL() for setting the (partial) order of
+// expectations.  The syntax:
+//
+//   Expectation e1 = EXPECT_CALL(...)...;
+//   EXPECT_CALL(...).After(e1)...;
+//
+// sets two expectations where the latter can only be matched after
+// the former has been satisfied.
+//
+// Notes:
+//   - This class is copyable and has value semantics.
+//   - Constness is shallow: a const Expectation object itself cannot
+//     be modified, but the mutable methods of the ExpectationBase
+//     object it references can be called via expectation_base().
+//   - The constructors and destructor are defined out-of-line because
+//     the Symbian WINSCW compiler wants to otherwise instantiate them
+//     when it sees this class definition, at which point it doesn't have
+//     ExpectationBase available yet, leading to incorrect destruction
+//     in the linked_ptr (or compilation errors if using a checking
+//     linked_ptr).
+class GTEST_API_ Expectation {
+ public:
+  // Constructs a null object that doesn't reference any expectation.
+  Expectation();
+
+  ~Expectation();
+
+  // This single-argument ctor must not be explicit, in order to support the
+  //   Expectation e = EXPECT_CALL(...);
+  // syntax.
+  //
+  // A TypedExpectation object stores its pre-requisites as
+  // Expectation objects, and needs to call the non-const Retire()
+  // method on the ExpectationBase objects they reference.  Therefore
+  // Expectation must receive a *non-const* reference to the
+  // ExpectationBase object.
+  Expectation(internal::ExpectationBase& exp);  // NOLINT
+
+  // The compiler-generated copy ctor and operator= work exactly as
+  // intended, so we don't need to define our own.
+
+  // Returns true iff rhs references the same expectation as this object does.
+  bool operator==(const Expectation& rhs) const {
+    return expectation_base_ == rhs.expectation_base_;
+  }
+
+  bool operator!=(const Expectation& rhs) const { return !(*this == rhs); }
+
+ private:
+  friend class ExpectationSet;
+  friend class Sequence;
+  friend class ::testing::internal::ExpectationBase;
+  friend class ::testing::internal::UntypedFunctionMockerBase;
+
+  template <typename F>
+  friend class ::testing::internal::FunctionMockerBase;
+
+  template <typename F>
+  friend class ::testing::internal::TypedExpectation;
+
+  // This comparator is needed for putting Expectation objects into a set.
+  class Less {
+   public:
+    bool operator()(const Expectation& lhs, const Expectation& rhs) const {
+      return lhs.expectation_base_.get() < rhs.expectation_base_.get();
+    }
+  };
+
+  typedef ::std::set<Expectation, Less> Set;
+
+  Expectation(
+      const internal::linked_ptr<internal::ExpectationBase>& expectation_base);
+
+  // Returns the expectation this object references.
+  const internal::linked_ptr<internal::ExpectationBase>&
+  expectation_base() const {
+    return expectation_base_;
+  }
+
+  // A linked_ptr that co-owns the expectation this handle references.
+  internal::linked_ptr<internal::ExpectationBase> expectation_base_;
+};
+
+// A set of expectation handles.  Useful in the .After() clause of
+// EXPECT_CALL() for setting the (partial) order of expectations.  The
+// syntax:
+//
+//   ExpectationSet es;
+//   es += EXPECT_CALL(...)...;
+//   es += EXPECT_CALL(...)...;
+//   EXPECT_CALL(...).After(es)...;
+//
+// sets three expectations where the last one can only be matched
+// after the first two have both been satisfied.
+//
+// This class is copyable and has value semantics.
+class ExpectationSet {
+ public:
+  // A bidirectional iterator that can read a const element in the set.
+  typedef Expectation::Set::const_iterator const_iterator;
+
+  // An object stored in the set.  This is an alias of Expectation.
+  typedef Expectation::Set::value_type value_type;
+
+  // Constructs an empty set.
+  ExpectationSet() {}
+
+  // This single-argument ctor must not be explicit, in order to support the
+  //   ExpectationSet es = EXPECT_CALL(...);
+  // syntax.
+  ExpectationSet(internal::ExpectationBase& exp) {  // NOLINT
+    *this += Expectation(exp);
+  }
+
+  // This single-argument ctor implements implicit conversion from
+  // Expectation and thus must not be explicit.  This allows either an
+  // Expectation or an ExpectationSet to be used in .After().
+  ExpectationSet(const Expectation& e) {  // NOLINT
+    *this += e;
+  }
+
+  // The compiler-generator ctor and operator= works exactly as
+  // intended, so we don't need to define our own.
+
+  // Returns true iff rhs contains the same set of Expectation objects
+  // as this does.
+  bool operator==(const ExpectationSet& rhs) const {
+    return expectations_ == rhs.expectations_;
+  }
+
+  bool operator!=(const ExpectationSet& rhs) const { return !(*this == rhs); }
+
+  // Implements the syntax
+  //   expectation_set += EXPECT_CALL(...);
+  ExpectationSet& operator+=(const Expectation& e) {
+    expectations_.insert(e);
+    return *this;
+  }
+
+  int size() const { return static_cast<int>(expectations_.size()); }
+
+  const_iterator begin() const { return expectations_.begin(); }
+  const_iterator end() const { return expectations_.end(); }
+
+ private:
+  Expectation::Set expectations_;
+};
+
+
+// Sequence objects are used by a user to specify the relative order
+// in which the expectations should match.  They are copyable (we rely
+// on the compiler-defined copy constructor and assignment operator).
+class GTEST_API_ Sequence {
+ public:
+  // Constructs an empty sequence.
+  Sequence() : last_expectation_(new Expectation) {}
+
+  // Adds an expectation to this sequence.  The caller must ensure
+  // that no other thread is accessing this Sequence object.
+  void AddExpectation(const Expectation& expectation) const;
+
+ private:
+  // The last expectation in this sequence.  We use a linked_ptr here
+  // because Sequence objects are copyable and we want the copies to
+  // be aliases.  The linked_ptr allows the copies to co-own and share
+  // the same Expectation object.
+  internal::linked_ptr<Expectation> last_expectation_;
+};  // class Sequence
+
+// An object of this type causes all EXPECT_CALL() statements
+// encountered in its scope to be put in an anonymous sequence.  The
+// work is done in the constructor and destructor.  You should only
+// create an InSequence object on the stack.
+//
+// The sole purpose for this class is to support easy definition of
+// sequential expectations, e.g.
+//
+//   {
+//     InSequence dummy;  // The name of the object doesn't matter.
+//
+//     // The following expectations must match in the order they appear.
+//     EXPECT_CALL(a, Bar())...;
+//     EXPECT_CALL(a, Baz())...;
+//     ...
+//     EXPECT_CALL(b, Xyz())...;
+//   }
+//
+// You can create InSequence objects in multiple threads, as long as
+// they are used to affect different mock objects.  The idea is that
+// each thread can create and set up its own mocks as if it's the only
+// thread.  However, for clarity of your tests we recommend you to set
+// up mocks in the main thread unless you have a good reason not to do
+// so.
+class GTEST_API_ InSequence {
+ public:
+  InSequence();
+  ~InSequence();
+ private:
+  bool sequence_created_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(InSequence);  // NOLINT
+} GTEST_ATTRIBUTE_UNUSED_;
+
+namespace internal {
+
+// Points to the implicit sequence introduced by a living InSequence
+// object (if any) in the current thread or NULL.
+GTEST_API_ extern ThreadLocal<Sequence*> g_gmock_implicit_sequence;
+
+// Base class for implementing expectations.
+//
+// There are two reasons for having a type-agnostic base class for
+// Expectation:
+//
+//   1. We need to store collections of expectations of different
+//   types (e.g. all pre-requisites of a particular expectation, all
+//   expectations in a sequence).  Therefore these expectation objects
+//   must share a common base class.
+//
+//   2. We can avoid binary code bloat by moving methods not depending
+//   on the template argument of Expectation to the base class.
+//
+// This class is internal and mustn't be used by user code directly.
+class GTEST_API_ ExpectationBase {
+ public:
+  // source_text is the EXPECT_CALL(...) source that created this Expectation.
+  ExpectationBase(const char* file, int line, const string& source_text);
+
+  virtual ~ExpectationBase();
+
+  // Where in the source file was the expectation spec defined?
+  const char* file() const { return file_; }
+  int line() const { return line_; }
+  const char* source_text() const { return source_text_.c_str(); }
+  // Returns the cardinality specified in the expectation spec.
+  const Cardinality& cardinality() const { return cardinality_; }
+
+  // Describes the source file location of this expectation.
+  void DescribeLocationTo(::std::ostream* os) const {
+    *os << FormatFileLocation(file(), line()) << " ";
+  }
+
+  // Describes how many times a function call matching this
+  // expectation has occurred.
+  void DescribeCallCountTo(::std::ostream* os) const
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex);
+
+  // If this mock method has an extra matcher (i.e. .With(matcher)),
+  // describes it to the ostream.
+  virtual void MaybeDescribeExtraMatcherTo(::std::ostream* os) = 0;
+
+ protected:
+  friend class ::testing::Expectation;
+  friend class UntypedFunctionMockerBase;
+
+  enum Clause {
+    // Don't change the order of the enum members!
+    kNone,
+    kWith,
+    kTimes,
+    kInSequence,
+    kAfter,
+    kWillOnce,
+    kWillRepeatedly,
+    kRetiresOnSaturation
+  };
+
+  typedef std::vector<const void*> UntypedActions;
+
+  // Returns an Expectation object that references and co-owns this
+  // expectation.
+  virtual Expectation GetHandle() = 0;
+
+  // Asserts that the EXPECT_CALL() statement has the given property.
+  void AssertSpecProperty(bool property, const string& failure_message) const {
+    Assert(property, file_, line_, failure_message);
+  }
+
+  // Expects that the EXPECT_CALL() statement has the given property.
+  void ExpectSpecProperty(bool property, const string& failure_message) const {
+    Expect(property, file_, line_, failure_message);
+  }
+
+  // Explicitly specifies the cardinality of this expectation.  Used
+  // by the subclasses to implement the .Times() clause.
+  void SpecifyCardinality(const Cardinality& cardinality);
+
+  // Returns true iff the user specified the cardinality explicitly
+  // using a .Times().
+  bool cardinality_specified() const { return cardinality_specified_; }
+
+  // Sets the cardinality of this expectation spec.
+  void set_cardinality(const Cardinality& a_cardinality) {
+    cardinality_ = a_cardinality;
+  }
+
+  // The following group of methods should only be called after the
+  // EXPECT_CALL() statement, and only when g_gmock_mutex is held by
+  // the current thread.
+
+  // Retires all pre-requisites of this expectation.
+  void RetireAllPreRequisites()
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex);
+
+  // Returns true iff this expectation is retired.
+  bool is_retired() const
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+    return retired_;
+  }
+
+  // Retires this expectation.
+  void Retire()
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+    retired_ = true;
+  }
+
+  // Returns true iff this expectation is satisfied.
+  bool IsSatisfied() const
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+    return cardinality().IsSatisfiedByCallCount(call_count_);
+  }
+
+  // Returns true iff this expectation is saturated.
+  bool IsSaturated() const
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+    return cardinality().IsSaturatedByCallCount(call_count_);
+  }
+
+  // Returns true iff this expectation is over-saturated.
+  bool IsOverSaturated() const
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+    return cardinality().IsOverSaturatedByCallCount(call_count_);
+  }
+
+  // Returns true iff all pre-requisites of this expectation are satisfied.
+  bool AllPrerequisitesAreSatisfied() const
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex);
+
+  // Adds unsatisfied pre-requisites of this expectation to 'result'.
+  void FindUnsatisfiedPrerequisites(ExpectationSet* result) const
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex);
+
+  // Returns the number this expectation has been invoked.
+  int call_count() const
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+    return call_count_;
+  }
+
+  // Increments the number this expectation has been invoked.
+  void IncrementCallCount()
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+    call_count_++;
+  }
+
+  // Checks the action count (i.e. the number of WillOnce() and
+  // WillRepeatedly() clauses) against the cardinality if this hasn't
+  // been done before.  Prints a warning if there are too many or too
+  // few actions.
+  void CheckActionCountIfNotDone() const
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  friend class ::testing::Sequence;
+  friend class ::testing::internal::ExpectationTester;
+
+  template <typename Function>
+  friend class TypedExpectation;
+
+  // Implements the .Times() clause.
+  void UntypedTimes(const Cardinality& a_cardinality);
+
+  // This group of fields are part of the spec and won't change after
+  // an EXPECT_CALL() statement finishes.
+  const char* file_;          // The file that contains the expectation.
+  int line_;                  // The line number of the expectation.
+  const string source_text_;  // The EXPECT_CALL(...) source text.
+  // True iff the cardinality is specified explicitly.
+  bool cardinality_specified_;
+  Cardinality cardinality_;            // The cardinality of the expectation.
+  // The immediate pre-requisites (i.e. expectations that must be
+  // satisfied before this expectation can be matched) of this
+  // expectation.  We use linked_ptr in the set because we want an
+  // Expectation object to be co-owned by its FunctionMocker and its
+  // successors.  This allows multiple mock objects to be deleted at
+  // different times.
+  ExpectationSet immediate_prerequisites_;
+
+  // This group of fields are the current state of the expectation,
+  // and can change as the mock function is called.
+  int call_count_;  // How many times this expectation has been invoked.
+  bool retired_;    // True iff this expectation has retired.
+  UntypedActions untyped_actions_;
+  bool extra_matcher_specified_;
+  bool repeated_action_specified_;  // True if a WillRepeatedly() was specified.
+  bool retires_on_saturation_;
+  Clause last_clause_;
+  mutable bool action_count_checked_;  // Under mutex_.
+  mutable Mutex mutex_;  // Protects action_count_checked_.
+
+  GTEST_DISALLOW_ASSIGN_(ExpectationBase);
+};  // class ExpectationBase
+
+// Impements an expectation for the given function type.
+template <typename F>
+class TypedExpectation : public ExpectationBase {
+ public:
+  typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+  typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple;
+  typedef typename Function<F>::Result Result;
+
+  TypedExpectation(FunctionMockerBase<F>* owner,
+                   const char* a_file, int a_line, const string& a_source_text,
+                   const ArgumentMatcherTuple& m)
+      : ExpectationBase(a_file, a_line, a_source_text),
+        owner_(owner),
+        matchers_(m),
+        // By default, extra_matcher_ should match anything.  However,
+        // we cannot initialize it with _ as that triggers a compiler
+        // bug in Symbian's C++ compiler (cannot decide between two
+        // overloaded constructors of Matcher<const ArgumentTuple&>).
+        extra_matcher_(A<const ArgumentTuple&>()),
+        repeated_action_(DoDefault()) {}
+
+  virtual ~TypedExpectation() {
+    // Check the validity of the action count if it hasn't been done
+    // yet (for example, if the expectation was never used).
+    CheckActionCountIfNotDone();
+    for (UntypedActions::const_iterator it = untyped_actions_.begin();
+         it != untyped_actions_.end(); ++it) {
+      delete static_cast<const Action<F>*>(*it);
+    }
+  }
+
+  // Implements the .With() clause.
+  TypedExpectation& With(const Matcher<const ArgumentTuple&>& m) {
+    if (last_clause_ == kWith) {
+      ExpectSpecProperty(false,
+                         ".With() cannot appear "
+                         "more than once in an EXPECT_CALL().");
+    } else {
+      ExpectSpecProperty(last_clause_ < kWith,
+                         ".With() must be the first "
+                         "clause in an EXPECT_CALL().");
+    }
+    last_clause_ = kWith;
+
+    extra_matcher_ = m;
+    extra_matcher_specified_ = true;
+    return *this;
+  }
+
+  // Implements the .Times() clause.
+  TypedExpectation& Times(const Cardinality& a_cardinality) {
+    ExpectationBase::UntypedTimes(a_cardinality);
+    return *this;
+  }
+
+  // Implements the .Times() clause.
+  TypedExpectation& Times(int n) {
+    return Times(Exactly(n));
+  }
+
+  // Implements the .InSequence() clause.
+  TypedExpectation& InSequence(const Sequence& s) {
+    ExpectSpecProperty(last_clause_ <= kInSequence,
+                       ".InSequence() cannot appear after .After(),"
+                       " .WillOnce(), .WillRepeatedly(), or "
+                       ".RetiresOnSaturation().");
+    last_clause_ = kInSequence;
+
+    s.AddExpectation(GetHandle());
+    return *this;
+  }
+  TypedExpectation& InSequence(const Sequence& s1, const Sequence& s2) {
+    return InSequence(s1).InSequence(s2);
+  }
+  TypedExpectation& InSequence(const Sequence& s1, const Sequence& s2,
+                               const Sequence& s3) {
+    return InSequence(s1, s2).InSequence(s3);
+  }
+  TypedExpectation& InSequence(const Sequence& s1, const Sequence& s2,
+                               const Sequence& s3, const Sequence& s4) {
+    return InSequence(s1, s2, s3).InSequence(s4);
+  }
+  TypedExpectation& InSequence(const Sequence& s1, const Sequence& s2,
+                               const Sequence& s3, const Sequence& s4,
+                               const Sequence& s5) {
+    return InSequence(s1, s2, s3, s4).InSequence(s5);
+  }
+
+  // Implements that .After() clause.
+  TypedExpectation& After(const ExpectationSet& s) {
+    ExpectSpecProperty(last_clause_ <= kAfter,
+                       ".After() cannot appear after .WillOnce(),"
+                       " .WillRepeatedly(), or "
+                       ".RetiresOnSaturation().");
+    last_clause_ = kAfter;
+
+    for (ExpectationSet::const_iterator it = s.begin(); it != s.end(); ++it) {
+      immediate_prerequisites_ += *it;
+    }
+    return *this;
+  }
+  TypedExpectation& After(const ExpectationSet& s1, const ExpectationSet& s2) {
+    return After(s1).After(s2);
+  }
+  TypedExpectation& After(const ExpectationSet& s1, const ExpectationSet& s2,
+                          const ExpectationSet& s3) {
+    return After(s1, s2).After(s3);
+  }
+  TypedExpectation& After(const ExpectationSet& s1, const ExpectationSet& s2,
+                          const ExpectationSet& s3, const ExpectationSet& s4) {
+    return After(s1, s2, s3).After(s4);
+  }
+  TypedExpectation& After(const ExpectationSet& s1, const ExpectationSet& s2,
+                          const ExpectationSet& s3, const ExpectationSet& s4,
+                          const ExpectationSet& s5) {
+    return After(s1, s2, s3, s4).After(s5);
+  }
+
+  // Implements the .WillOnce() clause.
+  TypedExpectation& WillOnce(const Action<F>& action) {
+    ExpectSpecProperty(last_clause_ <= kWillOnce,
+                       ".WillOnce() cannot appear after "
+                       ".WillRepeatedly() or .RetiresOnSaturation().");
+    last_clause_ = kWillOnce;
+
+    untyped_actions_.push_back(new Action<F>(action));
+    if (!cardinality_specified()) {
+      set_cardinality(Exactly(static_cast<int>(untyped_actions_.size())));
+    }
+    return *this;
+  }
+
+  // Implements the .WillRepeatedly() clause.
+  TypedExpectation& WillRepeatedly(const Action<F>& action) {
+    if (last_clause_ == kWillRepeatedly) {
+      ExpectSpecProperty(false,
+                         ".WillRepeatedly() cannot appear "
+                         "more than once in an EXPECT_CALL().");
+    } else {
+      ExpectSpecProperty(last_clause_ < kWillRepeatedly,
+                         ".WillRepeatedly() cannot appear "
+                         "after .RetiresOnSaturation().");
+    }
+    last_clause_ = kWillRepeatedly;
+    repeated_action_specified_ = true;
+
+    repeated_action_ = action;
+    if (!cardinality_specified()) {
+      set_cardinality(AtLeast(static_cast<int>(untyped_actions_.size())));
+    }
+
+    // Now that no more action clauses can be specified, we check
+    // whether their count makes sense.
+    CheckActionCountIfNotDone();
+    return *this;
+  }
+
+  // Implements the .RetiresOnSaturation() clause.
+  TypedExpectation& RetiresOnSaturation() {
+    ExpectSpecProperty(last_clause_ < kRetiresOnSaturation,
+                       ".RetiresOnSaturation() cannot appear "
+                       "more than once.");
+    last_clause_ = kRetiresOnSaturation;
+    retires_on_saturation_ = true;
+
+    // Now that no more action clauses can be specified, we check
+    // whether their count makes sense.
+    CheckActionCountIfNotDone();
+    return *this;
+  }
+
+  // Returns the matchers for the arguments as specified inside the
+  // EXPECT_CALL() macro.
+  const ArgumentMatcherTuple& matchers() const {
+    return matchers_;
+  }
+
+  // Returns the matcher specified by the .With() clause.
+  const Matcher<const ArgumentTuple&>& extra_matcher() const {
+    return extra_matcher_;
+  }
+
+  // Returns the action specified by the .WillRepeatedly() clause.
+  const Action<F>& repeated_action() const { return repeated_action_; }
+
+  // If this mock method has an extra matcher (i.e. .With(matcher)),
+  // describes it to the ostream.
+  virtual void MaybeDescribeExtraMatcherTo(::std::ostream* os) {
+    if (extra_matcher_specified_) {
+      *os << "    Expected args: ";
+      extra_matcher_.DescribeTo(os);
+      *os << "\n";
+    }
+  }
+
+ private:
+  template <typename Function>
+  friend class FunctionMockerBase;
+
+  // Returns an Expectation object that references and co-owns this
+  // expectation.
+  virtual Expectation GetHandle() {
+    return owner_->GetHandleOf(this);
+  }
+
+  // The following methods will be called only after the EXPECT_CALL()
+  // statement finishes and when the current thread holds
+  // g_gmock_mutex.
+
+  // Returns true iff this expectation matches the given arguments.
+  bool Matches(const ArgumentTuple& args) const
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+    return TupleMatches(matchers_, args) && extra_matcher_.Matches(args);
+  }
+
+  // Returns true iff this expectation should handle the given arguments.
+  bool ShouldHandleArguments(const ArgumentTuple& args) const
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+
+    // In case the action count wasn't checked when the expectation
+    // was defined (e.g. if this expectation has no WillRepeatedly()
+    // or RetiresOnSaturation() clause), we check it when the
+    // expectation is used for the first time.
+    CheckActionCountIfNotDone();
+    return !is_retired() && AllPrerequisitesAreSatisfied() && Matches(args);
+  }
+
+  // Describes the result of matching the arguments against this
+  // expectation to the given ostream.
+  void ExplainMatchResultTo(
+      const ArgumentTuple& args,
+      ::std::ostream* os) const
+          GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+
+    if (is_retired()) {
+      *os << "         Expected: the expectation is active\n"
+          << "           Actual: it is retired\n";
+    } else if (!Matches(args)) {
+      if (!TupleMatches(matchers_, args)) {
+        ExplainMatchFailureTupleTo(matchers_, args, os);
+      }
+      StringMatchResultListener listener;
+      if (!extra_matcher_.MatchAndExplain(args, &listener)) {
+        *os << "    Expected args: ";
+        extra_matcher_.DescribeTo(os);
+        *os << "\n           Actual: don't match";
+
+        internal::PrintIfNotEmpty(listener.str(), os);
+        *os << "\n";
+      }
+    } else if (!AllPrerequisitesAreSatisfied()) {
+      *os << "         Expected: all pre-requisites are satisfied\n"
+          << "           Actual: the following immediate pre-requisites "
+          << "are not satisfied:\n";
+      ExpectationSet unsatisfied_prereqs;
+      FindUnsatisfiedPrerequisites(&unsatisfied_prereqs);
+      int i = 0;
+      for (ExpectationSet::const_iterator it = unsatisfied_prereqs.begin();
+           it != unsatisfied_prereqs.end(); ++it) {
+        it->expectation_base()->DescribeLocationTo(os);
+        *os << "pre-requisite #" << i++ << "\n";
+      }
+      *os << "                   (end of pre-requisites)\n";
+    } else {
+      // This line is here just for completeness' sake.  It will never
+      // be executed as currently the ExplainMatchResultTo() function
+      // is called only when the mock function call does NOT match the
+      // expectation.
+      *os << "The call matches the expectation.\n";
+    }
+  }
+
+  // Returns the action that should be taken for the current invocation.
+  const Action<F>& GetCurrentAction(
+      const FunctionMockerBase<F>* mocker,
+      const ArgumentTuple& args) const
+          GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+    const int count = call_count();
+    Assert(count >= 1, __FILE__, __LINE__,
+           "call_count() is <= 0 when GetCurrentAction() is "
+           "called - this should never happen.");
+
+    const int action_count = static_cast<int>(untyped_actions_.size());
+    if (action_count > 0 && !repeated_action_specified_ &&
+        count > action_count) {
+      // If there is at least one WillOnce() and no WillRepeatedly(),
+      // we warn the user when the WillOnce() clauses ran out.
+      ::std::stringstream ss;
+      DescribeLocationTo(&ss);
+      ss << "Actions ran out in " << source_text() << "...\n"
+         << "Called " << count << " times, but only "
+         << action_count << " WillOnce()"
+         << (action_count == 1 ? " is" : "s are") << " specified - ";
+      mocker->DescribeDefaultActionTo(args, &ss);
+      Log(kWarning, ss.str(), 1);
+    }
+
+    return count <= action_count ?
+        *static_cast<const Action<F>*>(untyped_actions_[count - 1]) :
+        repeated_action();
+  }
+
+  // Given the arguments of a mock function call, if the call will
+  // over-saturate this expectation, returns the default action;
+  // otherwise, returns the next action in this expectation.  Also
+  // describes *what* happened to 'what', and explains *why* Google
+  // Mock does it to 'why'.  This method is not const as it calls
+  // IncrementCallCount().  A return value of NULL means the default
+  // action.
+  const Action<F>* GetActionForArguments(
+      const FunctionMockerBase<F>* mocker,
+      const ArgumentTuple& args,
+      ::std::ostream* what,
+      ::std::ostream* why)
+          GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+    if (IsSaturated()) {
+      // We have an excessive call.
+      IncrementCallCount();
+      *what << "Mock function called more times than expected - ";
+      mocker->DescribeDefaultActionTo(args, what);
+      DescribeCallCountTo(why);
+
+      // TODO(wan@google.com): allow the user to control whether
+      // unexpected calls should fail immediately or continue using a
+      // flag --gmock_unexpected_calls_are_fatal.
+      return NULL;
+    }
+
+    IncrementCallCount();
+    RetireAllPreRequisites();
+
+    if (retires_on_saturation_ && IsSaturated()) {
+      Retire();
+    }
+
+    // Must be done after IncrementCount()!
+    *what << "Mock function call matches " << source_text() <<"...\n";
+    return &(GetCurrentAction(mocker, args));
+  }
+
+  // All the fields below won't change once the EXPECT_CALL()
+  // statement finishes.
+  FunctionMockerBase<F>* const owner_;
+  ArgumentMatcherTuple matchers_;
+  Matcher<const ArgumentTuple&> extra_matcher_;
+  Action<F> repeated_action_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TypedExpectation);
+};  // class TypedExpectation
+
+// A MockSpec object is used by ON_CALL() or EXPECT_CALL() for
+// specifying the default behavior of, or expectation on, a mock
+// function.
+
+// Note: class MockSpec really belongs to the ::testing namespace.
+// However if we define it in ::testing, MSVC will complain when
+// classes in ::testing::internal declare it as a friend class
+// template.  To workaround this compiler bug, we define MockSpec in
+// ::testing::internal and import it into ::testing.
+
+// Logs a message including file and line number information.
+GTEST_API_ void LogWithLocation(testing::internal::LogSeverity severity,
+                                const char* file, int line,
+                                const string& message);
+
+template <typename F>
+class MockSpec {
+ public:
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+  typedef typename internal::Function<F>::ArgumentMatcherTuple
+      ArgumentMatcherTuple;
+
+  // Constructs a MockSpec object, given the function mocker object
+  // that the spec is associated with.
+  explicit MockSpec(internal::FunctionMockerBase<F>* function_mocker)
+      : function_mocker_(function_mocker) {}
+
+  // Adds a new default action spec to the function mocker and returns
+  // the newly created spec.
+  internal::OnCallSpec<F>& InternalDefaultActionSetAt(
+      const char* file, int line, const char* obj, const char* call) {
+    LogWithLocation(internal::kInfo, file, line,
+        string("ON_CALL(") + obj + ", " + call + ") invoked");
+    return function_mocker_->AddNewOnCallSpec(file, line, matchers_);
+  }
+
+  // Adds a new expectation spec to the function mocker and returns
+  // the newly created spec.
+  internal::TypedExpectation<F>& InternalExpectedAt(
+      const char* file, int line, const char* obj, const char* call) {
+    const string source_text(string("EXPECT_CALL(") + obj + ", " + call + ")");
+    LogWithLocation(internal::kInfo, file, line, source_text + " invoked");
+    return function_mocker_->AddNewExpectation(
+        file, line, source_text, matchers_);
+  }
+
+ private:
+  template <typename Function>
+  friend class internal::FunctionMocker;
+
+  void SetMatchers(const ArgumentMatcherTuple& matchers) {
+    matchers_ = matchers;
+  }
+
+  // The function mocker that owns this spec.
+  internal::FunctionMockerBase<F>* const function_mocker_;
+  // The argument matchers specified in the spec.
+  ArgumentMatcherTuple matchers_;
+
+  GTEST_DISALLOW_ASSIGN_(MockSpec);
+};  // class MockSpec
+
+// Wrapper type for generically holding an ordinary value or lvalue reference.
+// If T is not a reference type, it must be copyable or movable.
+// ReferenceOrValueWrapper<T> is movable, and will also be copyable unless
+// T is a move-only value type (which means that it will always be copyable
+// if the current platform does not support move semantics).
+//
+// The primary template defines handling for values, but function header
+// comments describe the contract for the whole template (including
+// specializations).
+template <typename T>
+class ReferenceOrValueWrapper {
+ public:
+  // Constructs a wrapper from the given value/reference.
+  explicit ReferenceOrValueWrapper(T value)
+      : value_(::testing::internal::move(value)) {
+  }
+
+  // Unwraps and returns the underlying value/reference, exactly as
+  // originally passed. The behavior of calling this more than once on
+  // the same object is unspecified.
+  T Unwrap() { return ::testing::internal::move(value_); }
+
+  // Provides nondestructive access to the underlying value/reference.
+  // Always returns a const reference (more precisely,
+  // const RemoveReference<T>&). The behavior of calling this after
+  // calling Unwrap on the same object is unspecified.
+  const T& Peek() const {
+    return value_;
+  }
+
+ private:
+  T value_;
+};
+
+// Specialization for lvalue reference types. See primary template
+// for documentation.
+template <typename T>
+class ReferenceOrValueWrapper<T&> {
+ public:
+  // Workaround for debatable pass-by-reference lint warning (c-library-team
+  // policy precludes NOLINT in this context)
+  typedef T& reference;
+  explicit ReferenceOrValueWrapper(reference ref)
+      : value_ptr_(&ref) {}
+  T& Unwrap() { return *value_ptr_; }
+  const T& Peek() const { return *value_ptr_; }
+
+ private:
+  T* value_ptr_;
+};
+
+// MSVC warns about using 'this' in base member initializer list, so
+// we need to temporarily disable the warning.  We have to do it for
+// the entire class to suppress the warning, even though it's about
+// the constructor only.
+
+#ifdef _MSC_VER
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4355)  // Temporarily disables warning 4355.
+#endif  // _MSV_VER
+
+// C++ treats the void type specially.  For example, you cannot define
+// a void-typed variable or pass a void value to a function.
+// ActionResultHolder<T> holds a value of type T, where T must be a
+// copyable type or void (T doesn't need to be default-constructable).
+// It hides the syntactic difference between void and other types, and
+// is used to unify the code for invoking both void-returning and
+// non-void-returning mock functions.
+
+// Untyped base class for ActionResultHolder<T>.
+class UntypedActionResultHolderBase {
+ public:
+  virtual ~UntypedActionResultHolderBase() {}
+
+  // Prints the held value as an action's result to os.
+  virtual void PrintAsActionResult(::std::ostream* os) const = 0;
+};
+
+// This generic definition is used when T is not void.
+template <typename T>
+class ActionResultHolder : public UntypedActionResultHolderBase {
+ public:
+  // Returns the held value. Must not be called more than once.
+  T Unwrap() {
+    return result_.Unwrap();
+  }
+
+  // Prints the held value as an action's result to os.
+  virtual void PrintAsActionResult(::std::ostream* os) const {
+    *os << "\n          Returns: ";
+    // T may be a reference type, so we don't use UniversalPrint().
+    UniversalPrinter<T>::Print(result_.Peek(), os);
+  }
+
+  // Performs the given mock function's default action and returns the
+  // result in a new-ed ActionResultHolder.
+  template <typename F>
+  static ActionResultHolder* PerformDefaultAction(
+      const FunctionMockerBase<F>* func_mocker,
+      const typename Function<F>::ArgumentTuple& args,
+      const string& call_description) {
+    return new ActionResultHolder(Wrapper(
+        func_mocker->PerformDefaultAction(args, call_description)));
+  }
+
+  // Performs the given action and returns the result in a new-ed
+  // ActionResultHolder.
+  template <typename F>
+  static ActionResultHolder*
+  PerformAction(const Action<F>& action,
+                const typename Function<F>::ArgumentTuple& args) {
+    return new ActionResultHolder(Wrapper(action.Perform(args)));
+  }
+
+ private:
+  typedef ReferenceOrValueWrapper<T> Wrapper;
+
+  explicit ActionResultHolder(Wrapper result)
+      : result_(::testing::internal::move(result)) {
+  }
+
+  Wrapper result_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ActionResultHolder);
+};
+
+// Specialization for T = void.
+template <>
+class ActionResultHolder<void> : public UntypedActionResultHolderBase {
+ public:
+  void Unwrap() { }
+
+  virtual void PrintAsActionResult(::std::ostream* /* os */) const {}
+
+  // Performs the given mock function's default action and returns ownership
+  // of an empty ActionResultHolder*.
+  template <typename F>
+  static ActionResultHolder* PerformDefaultAction(
+      const FunctionMockerBase<F>* func_mocker,
+      const typename Function<F>::ArgumentTuple& args,
+      const string& call_description) {
+    func_mocker->PerformDefaultAction(args, call_description);
+    return new ActionResultHolder;
+  }
+
+  // Performs the given action and returns ownership of an empty
+  // ActionResultHolder*.
+  template <typename F>
+  static ActionResultHolder* PerformAction(
+      const Action<F>& action,
+      const typename Function<F>::ArgumentTuple& args) {
+    action.Perform(args);
+    return new ActionResultHolder;
+  }
+
+ private:
+  ActionResultHolder() {}
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ActionResultHolder);
+};
+
+// The base of the function mocker class for the given function type.
+// We put the methods in this class instead of its child to avoid code
+// bloat.
+template <typename F>
+class FunctionMockerBase : public UntypedFunctionMockerBase {
+ public:
+  typedef typename Function<F>::Result Result;
+  typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+  typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple;
+
+  FunctionMockerBase() : current_spec_(this) {}
+
+  // The destructor verifies that all expectations on this mock
+  // function have been satisfied.  If not, it will report Google Test
+  // non-fatal failures for the violations.
+  virtual ~FunctionMockerBase()
+        GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
+    MutexLock l(&g_gmock_mutex);
+    VerifyAndClearExpectationsLocked();
+    Mock::UnregisterLocked(this);
+    ClearDefaultActionsLocked();
+  }
+
+  // Returns the ON_CALL spec that matches this mock function with the
+  // given arguments; returns NULL if no matching ON_CALL is found.
+  // L = *
+  const OnCallSpec<F>* FindOnCallSpec(
+      const ArgumentTuple& args) const {
+    for (UntypedOnCallSpecs::const_reverse_iterator it
+             = untyped_on_call_specs_.rbegin();
+         it != untyped_on_call_specs_.rend(); ++it) {
+      const OnCallSpec<F>* spec = static_cast<const OnCallSpec<F>*>(*it);
+      if (spec->Matches(args))
+        return spec;
+    }
+
+    return NULL;
+  }
+
+  // Performs the default action of this mock function on the given
+  // arguments and returns the result. Asserts (or throws if
+  // exceptions are enabled) with a helpful call descrption if there
+  // is no valid return value. This method doesn't depend on the
+  // mutable state of this object, and thus can be called concurrently
+  // without locking.
+  // L = *
+  Result PerformDefaultAction(const ArgumentTuple& args,
+                              const string& call_description) const {
+    const OnCallSpec<F>* const spec =
+        this->FindOnCallSpec(args);
+    if (spec != NULL) {
+      return spec->GetAction().Perform(args);
+    }
+    const string message = call_description +
+        "\n    The mock function has no default action "
+        "set, and its return type has no default value set.";
+#if GTEST_HAS_EXCEPTIONS
+    if (!DefaultValue<Result>::Exists()) {
+      throw std::runtime_error(message);
+    }
+#else
+    Assert(DefaultValue<Result>::Exists(), "", -1, message);
+#endif
+    return DefaultValue<Result>::Get();
+  }
+
+  // Performs the default action with the given arguments and returns
+  // the action's result.  The call description string will be used in
+  // the error message to describe the call in the case the default
+  // action fails.  The caller is responsible for deleting the result.
+  // L = *
+  virtual UntypedActionResultHolderBase* UntypedPerformDefaultAction(
+      const void* untyped_args,  // must point to an ArgumentTuple
+      const string& call_description) const {
+    const ArgumentTuple& args =
+        *static_cast<const ArgumentTuple*>(untyped_args);
+    return ResultHolder::PerformDefaultAction(this, args, call_description);
+  }
+
+  // Performs the given action with the given arguments and returns
+  // the action's result.  The caller is responsible for deleting the
+  // result.
+  // L = *
+  virtual UntypedActionResultHolderBase* UntypedPerformAction(
+      const void* untyped_action, const void* untyped_args) const {
+    // Make a copy of the action before performing it, in case the
+    // action deletes the mock object (and thus deletes itself).
+    const Action<F> action = *static_cast<const Action<F>*>(untyped_action);
+    const ArgumentTuple& args =
+        *static_cast<const ArgumentTuple*>(untyped_args);
+    return ResultHolder::PerformAction(action, args);
+  }
+
+  // Implements UntypedFunctionMockerBase::ClearDefaultActionsLocked():
+  // clears the ON_CALL()s set on this mock function.
+  virtual void ClearDefaultActionsLocked()
+      GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+
+    // Deleting our default actions may trigger other mock objects to be
+    // deleted, for example if an action contains a reference counted smart
+    // pointer to that mock object, and that is the last reference. So if we
+    // delete our actions within the context of the global mutex we may deadlock
+    // when this method is called again. Instead, make a copy of the set of
+    // actions to delete, clear our set within the mutex, and then delete the
+    // actions outside of the mutex.
+    UntypedOnCallSpecs specs_to_delete;
+    untyped_on_call_specs_.swap(specs_to_delete);
+
+    g_gmock_mutex.Unlock();
+    for (UntypedOnCallSpecs::const_iterator it =
+             specs_to_delete.begin();
+         it != specs_to_delete.end(); ++it) {
+      delete static_cast<const OnCallSpec<F>*>(*it);
+    }
+
+    // Lock the mutex again, since the caller expects it to be locked when we
+    // return.
+    g_gmock_mutex.Lock();
+  }
+
+ protected:
+  template <typename Function>
+  friend class MockSpec;
+
+  typedef ActionResultHolder<Result> ResultHolder;
+
+  // Returns the result of invoking this mock function with the given
+  // arguments.  This function can be safely called from multiple
+  // threads concurrently.
+  Result InvokeWith(const ArgumentTuple& args)
+        GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
+    scoped_ptr<ResultHolder> holder(
+        DownCast_<ResultHolder*>(this->UntypedInvokeWith(&args)));
+    return holder->Unwrap();
+  }
+
+  // Adds and returns a default action spec for this mock function.
+  OnCallSpec<F>& AddNewOnCallSpec(
+      const char* file, int line,
+      const ArgumentMatcherTuple& m)
+          GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
+    Mock::RegisterUseByOnCallOrExpectCall(MockObject(), file, line);
+    OnCallSpec<F>* const on_call_spec = new OnCallSpec<F>(file, line, m);
+    untyped_on_call_specs_.push_back(on_call_spec);
+    return *on_call_spec;
+  }
+
+  // Adds and returns an expectation spec for this mock function.
+  TypedExpectation<F>& AddNewExpectation(
+      const char* file,
+      int line,
+      const string& source_text,
+      const ArgumentMatcherTuple& m)
+          GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
+    Mock::RegisterUseByOnCallOrExpectCall(MockObject(), file, line);
+    TypedExpectation<F>* const expectation =
+        new TypedExpectation<F>(this, file, line, source_text, m);
+    const linked_ptr<ExpectationBase> untyped_expectation(expectation);
+    untyped_expectations_.push_back(untyped_expectation);
+
+    // Adds this expectation into the implicit sequence if there is one.
+    Sequence* const implicit_sequence = g_gmock_implicit_sequence.get();
+    if (implicit_sequence != NULL) {
+      implicit_sequence->AddExpectation(Expectation(untyped_expectation));
+    }
+
+    return *expectation;
+  }
+
+  // The current spec (either default action spec or expectation spec)
+  // being described on this function mocker.
+  MockSpec<F>& current_spec() { return current_spec_; }
+
+ private:
+  template <typename Func> friend class TypedExpectation;
+
+  // Some utilities needed for implementing UntypedInvokeWith().
+
+  // Describes what default action will be performed for the given
+  // arguments.
+  // L = *
+  void DescribeDefaultActionTo(const ArgumentTuple& args,
+                               ::std::ostream* os) const {
+    const OnCallSpec<F>* const spec = FindOnCallSpec(args);
+
+    if (spec == NULL) {
+      *os << (internal::type_equals<Result, void>::value ?
+              "returning directly.\n" :
+              "returning default value.\n");
+    } else {
+      *os << "taking default action specified at:\n"
+          << FormatFileLocation(spec->file(), spec->line()) << "\n";
+    }
+  }
+
+  // Writes a message that the call is uninteresting (i.e. neither
+  // explicitly expected nor explicitly unexpected) to the given
+  // ostream.
+  virtual void UntypedDescribeUninterestingCall(
+      const void* untyped_args,
+      ::std::ostream* os) const
+          GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
+    const ArgumentTuple& args =
+        *static_cast<const ArgumentTuple*>(untyped_args);
+    *os << "Uninteresting mock function call - ";
+    DescribeDefaultActionTo(args, os);
+    *os << "    Function call: " << Name();
+    UniversalPrint(args, os);
+  }
+
+  // Returns the expectation that matches the given function arguments
+  // (or NULL is there's no match); when a match is found,
+  // untyped_action is set to point to the action that should be
+  // performed (or NULL if the action is "do default"), and
+  // is_excessive is modified to indicate whether the call exceeds the
+  // expected number.
+  //
+  // Critical section: We must find the matching expectation and the
+  // corresponding action that needs to be taken in an ATOMIC
+  // transaction.  Otherwise another thread may call this mock
+  // method in the middle and mess up the state.
+  //
+  // However, performing the action has to be left out of the critical
+  // section.  The reason is that we have no control on what the
+  // action does (it can invoke an arbitrary user function or even a
+  // mock function) and excessive locking could cause a dead lock.
+  virtual const ExpectationBase* UntypedFindMatchingExpectation(
+      const void* untyped_args,
+      const void** untyped_action, bool* is_excessive,
+      ::std::ostream* what, ::std::ostream* why)
+          GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
+    const ArgumentTuple& args =
+        *static_cast<const ArgumentTuple*>(untyped_args);
+    MutexLock l(&g_gmock_mutex);
+    TypedExpectation<F>* exp = this->FindMatchingExpectationLocked(args);
+    if (exp == NULL) {  // A match wasn't found.
+      this->FormatUnexpectedCallMessageLocked(args, what, why);
+      return NULL;
+    }
+
+    // This line must be done before calling GetActionForArguments(),
+    // which will increment the call count for *exp and thus affect
+    // its saturation status.
+    *is_excessive = exp->IsSaturated();
+    const Action<F>* action = exp->GetActionForArguments(this, args, what, why);
+    if (action != NULL && action->IsDoDefault())
+      action = NULL;  // Normalize "do default" to NULL.
+    *untyped_action = action;
+    return exp;
+  }
+
+  // Prints the given function arguments to the ostream.
+  virtual void UntypedPrintArgs(const void* untyped_args,
+                                ::std::ostream* os) const {
+    const ArgumentTuple& args =
+        *static_cast<const ArgumentTuple*>(untyped_args);
+    UniversalPrint(args, os);
+  }
+
+  // Returns the expectation that matches the arguments, or NULL if no
+  // expectation matches them.
+  TypedExpectation<F>* FindMatchingExpectationLocked(
+      const ArgumentTuple& args) const
+          GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+    for (typename UntypedExpectations::const_reverse_iterator it =
+             untyped_expectations_.rbegin();
+         it != untyped_expectations_.rend(); ++it) {
+      TypedExpectation<F>* const exp =
+          static_cast<TypedExpectation<F>*>(it->get());
+      if (exp->ShouldHandleArguments(args)) {
+        return exp;
+      }
+    }
+    return NULL;
+  }
+
+  // Returns a message that the arguments don't match any expectation.
+  void FormatUnexpectedCallMessageLocked(
+      const ArgumentTuple& args,
+      ::std::ostream* os,
+      ::std::ostream* why) const
+          GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+    *os << "\nUnexpected mock function call - ";
+    DescribeDefaultActionTo(args, os);
+    PrintTriedExpectationsLocked(args, why);
+  }
+
+  // Prints a list of expectations that have been tried against the
+  // current mock function call.
+  void PrintTriedExpectationsLocked(
+      const ArgumentTuple& args,
+      ::std::ostream* why) const
+          GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+    g_gmock_mutex.AssertHeld();
+    const int count = static_cast<int>(untyped_expectations_.size());
+    *why << "Google Mock tried the following " << count << " "
+         << (count == 1 ? "expectation, but it didn't match" :
+             "expectations, but none matched")
+         << ":\n";
+    for (int i = 0; i < count; i++) {
+      TypedExpectation<F>* const expectation =
+          static_cast<TypedExpectation<F>*>(untyped_expectations_[i].get());
+      *why << "\n";
+      expectation->DescribeLocationTo(why);
+      if (count > 1) {
+        *why << "tried expectation #" << i << ": ";
+      }
+      *why << expectation->source_text() << "...\n";
+      expectation->ExplainMatchResultTo(args, why);
+      expectation->DescribeCallCountTo(why);
+    }
+  }
+
+  // The current spec (either default action spec or expectation spec)
+  // being described on this function mocker.
+  MockSpec<F> current_spec_;
+
+  // There is no generally useful and implementable semantics of
+  // copying a mock object, so copying a mock is usually a user error.
+  // Thus we disallow copying function mockers.  If the user really
+  // wants to copy a mock object, he should implement his own copy
+  // operation, for example:
+  //
+  //   class MockFoo : public Foo {
+  //    public:
+  //     // Defines a copy constructor explicitly.
+  //     MockFoo(const MockFoo& src) {}
+  //     ...
+  //   };
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(FunctionMockerBase);
+};  // class FunctionMockerBase
+
+#ifdef _MSC_VER
+# pragma warning(pop)  // Restores the warning state.
+#endif  // _MSV_VER
+
+// Implements methods of FunctionMockerBase.
+
+// Verifies that all expectations on this mock function have been
+// satisfied.  Reports one or more Google Test non-fatal failures and
+// returns false if not.
+
+// Reports an uninteresting call (whose description is in msg) in the
+// manner specified by 'reaction'.
+void ReportUninterestingCall(CallReaction reaction, const string& msg);
+
+}  // namespace internal
+
+// The style guide prohibits "using" statements in a namespace scope
+// inside a header file.  However, the MockSpec class template is
+// meant to be defined in the ::testing namespace.  The following line
+// is just a trick for working around a bug in MSVC 8.0, which cannot
+// handle it if we define MockSpec in ::testing.
+using internal::MockSpec;
+
+// Const(x) is a convenient function for obtaining a const reference
+// to x.  This is useful for setting expectations on an overloaded
+// const mock method, e.g.
+//
+//   class MockFoo : public FooInterface {
+//    public:
+//     MOCK_METHOD0(Bar, int());
+//     MOCK_CONST_METHOD0(Bar, int&());
+//   };
+//
+//   MockFoo foo;
+//   // Expects a call to non-const MockFoo::Bar().
+//   EXPECT_CALL(foo, Bar());
+//   // Expects a call to const MockFoo::Bar().
+//   EXPECT_CALL(Const(foo), Bar());
+template <typename T>
+inline const T& Const(const T& x) { return x; }
+
+// Constructs an Expectation object that references and co-owns exp.
+inline Expectation::Expectation(internal::ExpectationBase& exp)  // NOLINT
+    : expectation_base_(exp.GetHandle().expectation_base()) {}
+
+}  // namespace testing
+
+// A separate macro is required to avoid compile errors when the name
+// of the method used in call is a result of macro expansion.
+// See CompilesWithMethodNameExpandedFromMacro tests in
+// internal/gmock-spec-builders_test.cc for more details.
+#define GMOCK_ON_CALL_IMPL_(obj, call) \
+    ((obj).gmock_##call).InternalDefaultActionSetAt(__FILE__, __LINE__, \
+                                                    #obj, #call)
+#define ON_CALL(obj, call) GMOCK_ON_CALL_IMPL_(obj, call)
+
+#define GMOCK_EXPECT_CALL_IMPL_(obj, call) \
+    ((obj).gmock_##call).InternalExpectedAt(__FILE__, __LINE__, #obj, #call)
+#define EXPECT_CALL(obj, call) GMOCK_EXPECT_CALL_IMPL_(obj, call)
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_SPEC_BUILDERS_H_
diff --git a/third_party/googletest/googlemock/include/gmock/gmock.h b/third_party/googletest/googlemock/include/gmock/gmock.h
new file mode 100644
index 0000000..6735c71
--- /dev/null
+++ b/third_party/googletest/googlemock/include/gmock/gmock.h
@@ -0,0 +1,94 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This is the main header file a user should include.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_H_
+
+// This file implements the following syntax:
+//
+//   ON_CALL(mock_object.Method(...))
+//     .With(...) ?
+//     .WillByDefault(...);
+//
+// where With() is optional and WillByDefault() must appear exactly
+// once.
+//
+//   EXPECT_CALL(mock_object.Method(...))
+//     .With(...) ?
+//     .Times(...) ?
+//     .InSequence(...) *
+//     .WillOnce(...) *
+//     .WillRepeatedly(...) ?
+//     .RetiresOnSaturation() ? ;
+//
+// where all clauses are optional and WillOnce() can be repeated.
+
+#include "gmock/gmock-actions.h"
+#include "gmock/gmock-cardinalities.h"
+#include "gmock/gmock-generated-actions.h"
+#include "gmock/gmock-generated-function-mockers.h"
+#include "gmock/gmock-generated-nice-strict.h"
+#include "gmock/gmock-generated-matchers.h"
+#include "gmock/gmock-matchers.h"
+#include "gmock/gmock-more-actions.h"
+#include "gmock/gmock-more-matchers.h"
+#include "gmock/internal/gmock-internal-utils.h"
+
+namespace testing {
+
+// Declares Google Mock flags that we want a user to use programmatically.
+GMOCK_DECLARE_bool_(catch_leaked_mocks);
+GMOCK_DECLARE_string_(verbose);
+
+// Initializes Google Mock.  This must be called before running the
+// tests.  In particular, it parses the command line for the flags
+// that Google Mock recognizes.  Whenever a Google Mock flag is seen,
+// it is removed from argv, and *argc is decremented.
+//
+// No value is returned.  Instead, the Google Mock flag variables are
+// updated.
+//
+// Since Google Test is needed for Google Mock to work, this function
+// also initializes Google Test and parses its flags, if that hasn't
+// been done.
+GTEST_API_ void InitGoogleMock(int* argc, char** argv);
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+GTEST_API_ void InitGoogleMock(int* argc, wchar_t** argv);
+
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_H_
diff --git a/third_party/googletest/googlemock/include/gmock/internal/custom/gmock-generated-actions.h b/third_party/googletest/googlemock/include/gmock/internal/custom/gmock-generated-actions.h
new file mode 100644
index 0000000..7dc3b1a
--- /dev/null
+++ b/third_party/googletest/googlemock/include/gmock/internal/custom/gmock-generated-actions.h
@@ -0,0 +1,8 @@
+// This file was GENERATED by command:
+//     pump.py gmock-generated-actions.h.pump
+// DO NOT EDIT BY HAND!!!
+
+#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
+#define GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
+
+#endif  // GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
diff --git a/third_party/googletest/googlemock/include/gmock/internal/custom/gmock-generated-actions.h.pump b/third_party/googletest/googlemock/include/gmock/internal/custom/gmock-generated-actions.h.pump
new file mode 100644
index 0000000..d26c8a0
--- /dev/null
+++ b/third_party/googletest/googlemock/include/gmock/internal/custom/gmock-generated-actions.h.pump
@@ -0,0 +1,10 @@
+$$ -*- mode: c++; -*-
+$$ This is a Pump source file (http://go/pump).  Please use Pump to convert
+$$ it to callback-actions.h.
+$$
+$var max_callback_arity = 5
+$$}} This meta comment fixes auto-indentation in editors.
+#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
+#define GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
+
+#endif  // GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
diff --git a/third_party/googletest/googlemock/include/gmock/internal/custom/gmock-matchers.h b/third_party/googletest/googlemock/include/gmock/internal/custom/gmock-matchers.h
new file mode 100644
index 0000000..f2efef9
--- /dev/null
+++ b/third_party/googletest/googlemock/include/gmock/internal/custom/gmock-matchers.h
@@ -0,0 +1,39 @@
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ============================================================
+// An installation-specific extension point for gmock-matchers.h.
+// ============================================================
+//
+// Adds google3 callback support to CallableTraits.
+//
+#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_CALLBACK_MATCHERS_H_
+#define GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_CALLBACK_MATCHERS_H_
+
+#endif  //  GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_CALLBACK_MATCHERS_H_
diff --git a/third_party/googletest/googlemock/include/gmock/internal/custom/gmock-port.h b/third_party/googletest/googlemock/include/gmock/internal/custom/gmock-port.h
new file mode 100644
index 0000000..9ce8bfe
--- /dev/null
+++ b/third_party/googletest/googlemock/include/gmock/internal/custom/gmock-port.h
@@ -0,0 +1,46 @@
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Injection point for custom user configurations.
+// The following macros can be defined:
+//
+//   Flag related macros:
+//     GMOCK_DECLARE_bool_(name)
+//     GMOCK_DECLARE_int32_(name)
+//     GMOCK_DECLARE_string_(name)
+//     GMOCK_DEFINE_bool_(name, default_val, doc)
+//     GMOCK_DEFINE_int32_(name, default_val, doc)
+//     GMOCK_DEFINE_string_(name, default_val, doc)
+//
+// ** Custom implementation starts here **
+
+#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_PORT_H_
+#define GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_PORT_H_
+
+#endif  // GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_PORT_H_
diff --git a/third_party/googletest/googlemock/include/gmock/internal/gmock-generated-internal-utils.h b/third_party/googletest/googlemock/include/gmock/internal/gmock-generated-internal-utils.h
new file mode 100644
index 0000000..7811e43
--- /dev/null
+++ b/third_party/googletest/googlemock/include/gmock/internal/gmock-generated-internal-utils.h
@@ -0,0 +1,279 @@
+// This file was GENERATED by command:
+//     pump.py gmock-generated-internal-utils.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file contains template meta-programming utility classes needed
+// for implementing Google Mock.
+
+#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
+#define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
+
+#include "gmock/internal/gmock-port.h"
+
+namespace testing {
+
+template <typename T>
+class Matcher;
+
+namespace internal {
+
+// An IgnoredValue object can be implicitly constructed from ANY value.
+// This is used in implementing the IgnoreResult(a) action.
+class IgnoredValue {
+ public:
+  // This constructor template allows any value to be implicitly
+  // converted to IgnoredValue.  The object has no data member and
+  // doesn't try to remember anything about the argument.  We
+  // deliberately omit the 'explicit' keyword in order to allow the
+  // conversion to be implicit.
+  template <typename T>
+  IgnoredValue(const T& /* ignored */) {}  // NOLINT(runtime/explicit)
+};
+
+// MatcherTuple<T>::type is a tuple type where each field is a Matcher
+// for the corresponding field in tuple type T.
+template <typename Tuple>
+struct MatcherTuple;
+
+template <>
+struct MatcherTuple< ::testing::tuple<> > {
+  typedef ::testing::tuple< > type;
+};
+
+template <typename A1>
+struct MatcherTuple< ::testing::tuple<A1> > {
+  typedef ::testing::tuple<Matcher<A1> > type;
+};
+
+template <typename A1, typename A2>
+struct MatcherTuple< ::testing::tuple<A1, A2> > {
+  typedef ::testing::tuple<Matcher<A1>, Matcher<A2> > type;
+};
+
+template <typename A1, typename A2, typename A3>
+struct MatcherTuple< ::testing::tuple<A1, A2, A3> > {
+  typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3> > type;
+};
+
+template <typename A1, typename A2, typename A3, typename A4>
+struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4> > {
+  typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>,
+      Matcher<A4> > type;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5>
+struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5> > {
+  typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
+      Matcher<A5> > type;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5,
+    typename A6>
+struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5, A6> > {
+  typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
+      Matcher<A5>, Matcher<A6> > type;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5,
+    typename A6, typename A7>
+struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5, A6, A7> > {
+  typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
+      Matcher<A5>, Matcher<A6>, Matcher<A7> > type;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5,
+    typename A6, typename A7, typename A8>
+struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5, A6, A7, A8> > {
+  typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
+      Matcher<A5>, Matcher<A6>, Matcher<A7>, Matcher<A8> > type;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5,
+    typename A6, typename A7, typename A8, typename A9>
+struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9> > {
+  typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
+      Matcher<A5>, Matcher<A6>, Matcher<A7>, Matcher<A8>, Matcher<A9> > type;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5,
+    typename A6, typename A7, typename A8, typename A9, typename A10>
+struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9,
+    A10> > {
+  typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
+      Matcher<A5>, Matcher<A6>, Matcher<A7>, Matcher<A8>, Matcher<A9>,
+      Matcher<A10> > type;
+};
+
+// Template struct Function<F>, where F must be a function type, contains
+// the following typedefs:
+//
+//   Result:               the function's return type.
+//   ArgumentN:            the type of the N-th argument, where N starts with 1.
+//   ArgumentTuple:        the tuple type consisting of all parameters of F.
+//   ArgumentMatcherTuple: the tuple type consisting of Matchers for all
+//                         parameters of F.
+//   MakeResultVoid:       the function type obtained by substituting void
+//                         for the return type of F.
+//   MakeResultIgnoredValue:
+//                         the function type obtained by substituting Something
+//                         for the return type of F.
+template <typename F>
+struct Function;
+
+template <typename R>
+struct Function<R()> {
+  typedef R Result;
+  typedef ::testing::tuple<> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid();
+  typedef IgnoredValue MakeResultIgnoredValue();
+};
+
+template <typename R, typename A1>
+struct Function<R(A1)>
+    : Function<R()> {
+  typedef A1 Argument1;
+  typedef ::testing::tuple<A1> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1);
+  typedef IgnoredValue MakeResultIgnoredValue(A1);
+};
+
+template <typename R, typename A1, typename A2>
+struct Function<R(A1, A2)>
+    : Function<R(A1)> {
+  typedef A2 Argument2;
+  typedef ::testing::tuple<A1, A2> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1, A2);
+  typedef IgnoredValue MakeResultIgnoredValue(A1, A2);
+};
+
+template <typename R, typename A1, typename A2, typename A3>
+struct Function<R(A1, A2, A3)>
+    : Function<R(A1, A2)> {
+  typedef A3 Argument3;
+  typedef ::testing::tuple<A1, A2, A3> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1, A2, A3);
+  typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3);
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4>
+struct Function<R(A1, A2, A3, A4)>
+    : Function<R(A1, A2, A3)> {
+  typedef A4 Argument4;
+  typedef ::testing::tuple<A1, A2, A3, A4> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1, A2, A3, A4);
+  typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4);
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5>
+struct Function<R(A1, A2, A3, A4, A5)>
+    : Function<R(A1, A2, A3, A4)> {
+  typedef A5 Argument5;
+  typedef ::testing::tuple<A1, A2, A3, A4, A5> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1, A2, A3, A4, A5);
+  typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5);
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6>
+struct Function<R(A1, A2, A3, A4, A5, A6)>
+    : Function<R(A1, A2, A3, A4, A5)> {
+  typedef A6 Argument6;
+  typedef ::testing::tuple<A1, A2, A3, A4, A5, A6> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6);
+  typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6);
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7>
+struct Function<R(A1, A2, A3, A4, A5, A6, A7)>
+    : Function<R(A1, A2, A3, A4, A5, A6)> {
+  typedef A7 Argument7;
+  typedef ::testing::tuple<A1, A2, A3, A4, A5, A6, A7> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6, A7);
+  typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6, A7);
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7, typename A8>
+struct Function<R(A1, A2, A3, A4, A5, A6, A7, A8)>
+    : Function<R(A1, A2, A3, A4, A5, A6, A7)> {
+  typedef A8 Argument8;
+  typedef ::testing::tuple<A1, A2, A3, A4, A5, A6, A7, A8> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6, A7, A8);
+  typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6, A7, A8);
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7, typename A8, typename A9>
+struct Function<R(A1, A2, A3, A4, A5, A6, A7, A8, A9)>
+    : Function<R(A1, A2, A3, A4, A5, A6, A7, A8)> {
+  typedef A9 Argument9;
+  typedef ::testing::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6, A7, A8, A9);
+  typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6, A7, A8,
+      A9);
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7, typename A8, typename A9,
+    typename A10>
+struct Function<R(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)>
+    : Function<R(A1, A2, A3, A4, A5, A6, A7, A8, A9)> {
+  typedef A10 Argument10;
+  typedef ::testing::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9,
+      A10> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
+  typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6, A7, A8,
+      A9, A10);
+};
+
+}  // namespace internal
+
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
diff --git a/third_party/googletest/googlemock/include/gmock/internal/gmock-generated-internal-utils.h.pump b/third_party/googletest/googlemock/include/gmock/internal/gmock-generated-internal-utils.h.pump
new file mode 100644
index 0000000..800af17
--- /dev/null
+++ b/third_party/googletest/googlemock/include/gmock/internal/gmock-generated-internal-utils.h.pump
@@ -0,0 +1,136 @@
+$$ -*- mode: c++; -*-
+$$ This is a Pump source file.  Please use Pump to convert it to
+$$ gmock-generated-function-mockers.h.
+$$
+$var n = 10  $$ The maximum arity we support.
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file contains template meta-programming utility classes needed
+// for implementing Google Mock.
+
+#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
+#define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
+
+#include "gmock/internal/gmock-port.h"
+
+namespace testing {
+
+template <typename T>
+class Matcher;
+
+namespace internal {
+
+// An IgnoredValue object can be implicitly constructed from ANY value.
+// This is used in implementing the IgnoreResult(a) action.
+class IgnoredValue {
+ public:
+  // This constructor template allows any value to be implicitly
+  // converted to IgnoredValue.  The object has no data member and
+  // doesn't try to remember anything about the argument.  We
+  // deliberately omit the 'explicit' keyword in order to allow the
+  // conversion to be implicit.
+  template <typename T>
+  IgnoredValue(const T& /* ignored */) {}  // NOLINT(runtime/explicit)
+};
+
+// MatcherTuple<T>::type is a tuple type where each field is a Matcher
+// for the corresponding field in tuple type T.
+template <typename Tuple>
+struct MatcherTuple;
+
+
+$range i 0..n
+$for i [[
+$range j 1..i
+$var typename_As = [[$for j, [[typename A$j]]]]
+$var As = [[$for j, [[A$j]]]]
+$var matcher_As = [[$for j, [[Matcher<A$j>]]]]
+template <$typename_As>
+struct MatcherTuple< ::testing::tuple<$As> > {
+  typedef ::testing::tuple<$matcher_As > type;
+};
+
+
+]]
+// Template struct Function<F>, where F must be a function type, contains
+// the following typedefs:
+//
+//   Result:               the function's return type.
+//   ArgumentN:            the type of the N-th argument, where N starts with 1.
+//   ArgumentTuple:        the tuple type consisting of all parameters of F.
+//   ArgumentMatcherTuple: the tuple type consisting of Matchers for all
+//                         parameters of F.
+//   MakeResultVoid:       the function type obtained by substituting void
+//                         for the return type of F.
+//   MakeResultIgnoredValue:
+//                         the function type obtained by substituting Something
+//                         for the return type of F.
+template <typename F>
+struct Function;
+
+template <typename R>
+struct Function<R()> {
+  typedef R Result;
+  typedef ::testing::tuple<> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid();
+  typedef IgnoredValue MakeResultIgnoredValue();
+};
+
+
+$range i 1..n
+$for i [[
+$range j 1..i
+$var typename_As = [[$for j [[, typename A$j]]]]
+$var As = [[$for j, [[A$j]]]]
+$var matcher_As = [[$for j, [[Matcher<A$j>]]]]
+$range k 1..i-1
+$var prev_As = [[$for k, [[A$k]]]]
+template <typename R$typename_As>
+struct Function<R($As)>
+    : Function<R($prev_As)> {
+  typedef A$i Argument$i;
+  typedef ::testing::tuple<$As> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid($As);
+  typedef IgnoredValue MakeResultIgnoredValue($As);
+};
+
+
+]]
+}  // namespace internal
+
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
diff --git a/third_party/googletest/googlemock/include/gmock/internal/gmock-internal-utils.h b/third_party/googletest/googlemock/include/gmock/internal/gmock-internal-utils.h
new file mode 100644
index 0000000..e2ddb05
--- /dev/null
+++ b/third_party/googletest/googlemock/include/gmock/internal/gmock-internal-utils.h
@@ -0,0 +1,511 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file defines some utilities useful for implementing Google
+// Mock.  They are subject to change without notice, so please DO NOT
+// USE THEM IN USER CODE.
+
+#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_
+#define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_
+
+#include <stdio.h>
+#include <ostream>  // NOLINT
+#include <string>
+
+#include "gmock/internal/gmock-generated-internal-utils.h"
+#include "gmock/internal/gmock-port.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+namespace internal {
+
+// Converts an identifier name to a space-separated list of lower-case
+// words.  Each maximum substring of the form [A-Za-z][a-z]*|\d+ is
+// treated as one word.  For example, both "FooBar123" and
+// "foo_bar_123" are converted to "foo bar 123".
+GTEST_API_ string ConvertIdentifierNameToWords(const char* id_name);
+
+// PointeeOf<Pointer>::type is the type of a value pointed to by a
+// Pointer, which can be either a smart pointer or a raw pointer.  The
+// following default implementation is for the case where Pointer is a
+// smart pointer.
+template <typename Pointer>
+struct PointeeOf {
+  // Smart pointer classes define type element_type as the type of
+  // their pointees.
+  typedef typename Pointer::element_type type;
+};
+// This specialization is for the raw pointer case.
+template <typename T>
+struct PointeeOf<T*> { typedef T type; };  // NOLINT
+
+// GetRawPointer(p) returns the raw pointer underlying p when p is a
+// smart pointer, or returns p itself when p is already a raw pointer.
+// The following default implementation is for the smart pointer case.
+template <typename Pointer>
+inline const typename Pointer::element_type* GetRawPointer(const Pointer& p) {
+  return p.get();
+}
+// This overloaded version is for the raw pointer case.
+template <typename Element>
+inline Element* GetRawPointer(Element* p) { return p; }
+
+// This comparator allows linked_ptr to be stored in sets.
+template <typename T>
+struct LinkedPtrLessThan {
+  bool operator()(const ::testing::internal::linked_ptr<T>& lhs,
+                  const ::testing::internal::linked_ptr<T>& rhs) const {
+    return lhs.get() < rhs.get();
+  }
+};
+
+// Symbian compilation can be done with wchar_t being either a native
+// type or a typedef.  Using Google Mock with OpenC without wchar_t
+// should require the definition of _STLP_NO_WCHAR_T.
+//
+// MSVC treats wchar_t as a native type usually, but treats it as the
+// same as unsigned short when the compiler option /Zc:wchar_t- is
+// specified.  It defines _NATIVE_WCHAR_T_DEFINED symbol when wchar_t
+// is a native type.
+#if (GTEST_OS_SYMBIAN && defined(_STLP_NO_WCHAR_T)) || \
+    (defined(_MSC_VER) && !defined(_NATIVE_WCHAR_T_DEFINED))
+// wchar_t is a typedef.
+#else
+# define GMOCK_WCHAR_T_IS_NATIVE_ 1
+#endif
+
+// signed wchar_t and unsigned wchar_t are NOT in the C++ standard.
+// Using them is a bad practice and not portable.  So DON'T use them.
+//
+// Still, Google Mock is designed to work even if the user uses signed
+// wchar_t or unsigned wchar_t (obviously, assuming the compiler
+// supports them).
+//
+// To gcc,
+//   wchar_t == signed wchar_t != unsigned wchar_t == unsigned int
+#ifdef __GNUC__
+// signed/unsigned wchar_t are valid types.
+# define GMOCK_HAS_SIGNED_WCHAR_T_ 1
+#endif
+
+// In what follows, we use the term "kind" to indicate whether a type
+// is bool, an integer type (excluding bool), a floating-point type,
+// or none of them.  This categorization is useful for determining
+// when a matcher argument type can be safely converted to another
+// type in the implementation of SafeMatcherCast.
+enum TypeKind {
+  kBool, kInteger, kFloatingPoint, kOther
+};
+
+// KindOf<T>::value is the kind of type T.
+template <typename T> struct KindOf {
+  enum { value = kOther };  // The default kind.
+};
+
+// This macro declares that the kind of 'type' is 'kind'.
+#define GMOCK_DECLARE_KIND_(type, kind) \
+  template <> struct KindOf<type> { enum { value = kind }; }
+
+GMOCK_DECLARE_KIND_(bool, kBool);
+
+// All standard integer types.
+GMOCK_DECLARE_KIND_(char, kInteger);
+GMOCK_DECLARE_KIND_(signed char, kInteger);
+GMOCK_DECLARE_KIND_(unsigned char, kInteger);
+GMOCK_DECLARE_KIND_(short, kInteger);  // NOLINT
+GMOCK_DECLARE_KIND_(unsigned short, kInteger);  // NOLINT
+GMOCK_DECLARE_KIND_(int, kInteger);
+GMOCK_DECLARE_KIND_(unsigned int, kInteger);
+GMOCK_DECLARE_KIND_(long, kInteger);  // NOLINT
+GMOCK_DECLARE_KIND_(unsigned long, kInteger);  // NOLINT
+
+#if GMOCK_WCHAR_T_IS_NATIVE_
+GMOCK_DECLARE_KIND_(wchar_t, kInteger);
+#endif
+
+// Non-standard integer types.
+GMOCK_DECLARE_KIND_(Int64, kInteger);
+GMOCK_DECLARE_KIND_(UInt64, kInteger);
+
+// All standard floating-point types.
+GMOCK_DECLARE_KIND_(float, kFloatingPoint);
+GMOCK_DECLARE_KIND_(double, kFloatingPoint);
+GMOCK_DECLARE_KIND_(long double, kFloatingPoint);
+
+#undef GMOCK_DECLARE_KIND_
+
+// Evaluates to the kind of 'type'.
+#define GMOCK_KIND_OF_(type) \
+  static_cast< ::testing::internal::TypeKind>( \
+      ::testing::internal::KindOf<type>::value)
+
+// Evaluates to true iff integer type T is signed.
+#define GMOCK_IS_SIGNED_(T) (static_cast<T>(-1) < 0)
+
+// LosslessArithmeticConvertibleImpl<kFromKind, From, kToKind, To>::value
+// is true iff arithmetic type From can be losslessly converted to
+// arithmetic type To.
+//
+// It's the user's responsibility to ensure that both From and To are
+// raw (i.e. has no CV modifier, is not a pointer, and is not a
+// reference) built-in arithmetic types, kFromKind is the kind of
+// From, and kToKind is the kind of To; the value is
+// implementation-defined when the above pre-condition is violated.
+template <TypeKind kFromKind, typename From, TypeKind kToKind, typename To>
+struct LosslessArithmeticConvertibleImpl : public false_type {};
+
+// Converting bool to bool is lossless.
+template <>
+struct LosslessArithmeticConvertibleImpl<kBool, bool, kBool, bool>
+    : public true_type {};  // NOLINT
+
+// Converting bool to any integer type is lossless.
+template <typename To>
+struct LosslessArithmeticConvertibleImpl<kBool, bool, kInteger, To>
+    : public true_type {};  // NOLINT
+
+// Converting bool to any floating-point type is lossless.
+template <typename To>
+struct LosslessArithmeticConvertibleImpl<kBool, bool, kFloatingPoint, To>
+    : public true_type {};  // NOLINT
+
+// Converting an integer to bool is lossy.
+template <typename From>
+struct LosslessArithmeticConvertibleImpl<kInteger, From, kBool, bool>
+    : public false_type {};  // NOLINT
+
+// Converting an integer to another non-bool integer is lossless iff
+// the target type's range encloses the source type's range.
+template <typename From, typename To>
+struct LosslessArithmeticConvertibleImpl<kInteger, From, kInteger, To>
+    : public bool_constant<
+      // When converting from a smaller size to a larger size, we are
+      // fine as long as we are not converting from signed to unsigned.
+      ((sizeof(From) < sizeof(To)) &&
+       (!GMOCK_IS_SIGNED_(From) || GMOCK_IS_SIGNED_(To))) ||
+      // When converting between the same size, the signedness must match.
+      ((sizeof(From) == sizeof(To)) &&
+       (GMOCK_IS_SIGNED_(From) == GMOCK_IS_SIGNED_(To)))> {};  // NOLINT
+
+#undef GMOCK_IS_SIGNED_
+
+// Converting an integer to a floating-point type may be lossy, since
+// the format of a floating-point number is implementation-defined.
+template <typename From, typename To>
+struct LosslessArithmeticConvertibleImpl<kInteger, From, kFloatingPoint, To>
+    : public false_type {};  // NOLINT
+
+// Converting a floating-point to bool is lossy.
+template <typename From>
+struct LosslessArithmeticConvertibleImpl<kFloatingPoint, From, kBool, bool>
+    : public false_type {};  // NOLINT
+
+// Converting a floating-point to an integer is lossy.
+template <typename From, typename To>
+struct LosslessArithmeticConvertibleImpl<kFloatingPoint, From, kInteger, To>
+    : public false_type {};  // NOLINT
+
+// Converting a floating-point to another floating-point is lossless
+// iff the target type is at least as big as the source type.
+template <typename From, typename To>
+struct LosslessArithmeticConvertibleImpl<
+  kFloatingPoint, From, kFloatingPoint, To>
+    : public bool_constant<sizeof(From) <= sizeof(To)> {};  // NOLINT
+
+// LosslessArithmeticConvertible<From, To>::value is true iff arithmetic
+// type From can be losslessly converted to arithmetic type To.
+//
+// It's the user's responsibility to ensure that both From and To are
+// raw (i.e. has no CV modifier, is not a pointer, and is not a
+// reference) built-in arithmetic types; the value is
+// implementation-defined when the above pre-condition is violated.
+template <typename From, typename To>
+struct LosslessArithmeticConvertible
+    : public LosslessArithmeticConvertibleImpl<
+  GMOCK_KIND_OF_(From), From, GMOCK_KIND_OF_(To), To> {};  // NOLINT
+
+// This interface knows how to report a Google Mock failure (either
+// non-fatal or fatal).
+class FailureReporterInterface {
+ public:
+  // The type of a failure (either non-fatal or fatal).
+  enum FailureType {
+    kNonfatal, kFatal
+  };
+
+  virtual ~FailureReporterInterface() {}
+
+  // Reports a failure that occurred at the given source file location.
+  virtual void ReportFailure(FailureType type, const char* file, int line,
+                             const string& message) = 0;
+};
+
+// Returns the failure reporter used by Google Mock.
+GTEST_API_ FailureReporterInterface* GetFailureReporter();
+
+// Asserts that condition is true; aborts the process with the given
+// message if condition is false.  We cannot use LOG(FATAL) or CHECK()
+// as Google Mock might be used to mock the log sink itself.  We
+// inline this function to prevent it from showing up in the stack
+// trace.
+inline void Assert(bool condition, const char* file, int line,
+                   const string& msg) {
+  if (!condition) {
+    GetFailureReporter()->ReportFailure(FailureReporterInterface::kFatal,
+                                        file, line, msg);
+  }
+}
+inline void Assert(bool condition, const char* file, int line) {
+  Assert(condition, file, line, "Assertion failed.");
+}
+
+// Verifies that condition is true; generates a non-fatal failure if
+// condition is false.
+inline void Expect(bool condition, const char* file, int line,
+                   const string& msg) {
+  if (!condition) {
+    GetFailureReporter()->ReportFailure(FailureReporterInterface::kNonfatal,
+                                        file, line, msg);
+  }
+}
+inline void Expect(bool condition, const char* file, int line) {
+  Expect(condition, file, line, "Expectation failed.");
+}
+
+// Severity level of a log.
+enum LogSeverity {
+  kInfo = 0,
+  kWarning = 1
+};
+
+// Valid values for the --gmock_verbose flag.
+
+// All logs (informational and warnings) are printed.
+const char kInfoVerbosity[] = "info";
+// Only warnings are printed.
+const char kWarningVerbosity[] = "warning";
+// No logs are printed.
+const char kErrorVerbosity[] = "error";
+
+// Returns true iff a log with the given severity is visible according
+// to the --gmock_verbose flag.
+GTEST_API_ bool LogIsVisible(LogSeverity severity);
+
+// Prints the given message to stdout iff 'severity' >= the level
+// specified by the --gmock_verbose flag.  If stack_frames_to_skip >=
+// 0, also prints the stack trace excluding the top
+// stack_frames_to_skip frames.  In opt mode, any positive
+// stack_frames_to_skip is treated as 0, since we don't know which
+// function calls will be inlined by the compiler and need to be
+// conservative.
+GTEST_API_ void Log(LogSeverity severity,
+                    const string& message,
+                    int stack_frames_to_skip);
+
+// TODO(wan@google.com): group all type utilities together.
+
+// Type traits.
+
+// is_reference<T>::value is non-zero iff T is a reference type.
+template <typename T> struct is_reference : public false_type {};
+template <typename T> struct is_reference<T&> : public true_type {};
+
+// type_equals<T1, T2>::value is non-zero iff T1 and T2 are the same type.
+template <typename T1, typename T2> struct type_equals : public false_type {};
+template <typename T> struct type_equals<T, T> : public true_type {};
+
+// remove_reference<T>::type removes the reference from type T, if any.
+template <typename T> struct remove_reference { typedef T type; };  // NOLINT
+template <typename T> struct remove_reference<T&> { typedef T type; }; // NOLINT
+
+// DecayArray<T>::type turns an array type U[N] to const U* and preserves
+// other types.  Useful for saving a copy of a function argument.
+template <typename T> struct DecayArray { typedef T type; };  // NOLINT
+template <typename T, size_t N> struct DecayArray<T[N]> {
+  typedef const T* type;
+};
+// Sometimes people use arrays whose size is not available at the use site
+// (e.g. extern const char kNamePrefix[]).  This specialization covers that
+// case.
+template <typename T> struct DecayArray<T[]> {
+  typedef const T* type;
+};
+
+// Disable MSVC warnings for infinite recursion, since in this case the
+// the recursion is unreachable.
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4717)
+#endif
+
+// Invalid<T>() is usable as an expression of type T, but will terminate
+// the program with an assertion failure if actually run.  This is useful
+// when a value of type T is needed for compilation, but the statement
+// will not really be executed (or we don't care if the statement
+// crashes).
+template <typename T>
+inline T Invalid() {
+  Assert(false, "", -1, "Internal error: attempt to return invalid value");
+  // This statement is unreachable, and would never terminate even if it
+  // could be reached. It is provided only to placate compiler warnings
+  // about missing return statements.
+  return Invalid<T>();
+}
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+// Given a raw type (i.e. having no top-level reference or const
+// modifier) RawContainer that's either an STL-style container or a
+// native array, class StlContainerView<RawContainer> has the
+// following members:
+//
+//   - type is a type that provides an STL-style container view to
+//     (i.e. implements the STL container concept for) RawContainer;
+//   - const_reference is a type that provides a reference to a const
+//     RawContainer;
+//   - ConstReference(raw_container) returns a const reference to an STL-style
+//     container view to raw_container, which is a RawContainer.
+//   - Copy(raw_container) returns an STL-style container view of a
+//     copy of raw_container, which is a RawContainer.
+//
+// This generic version is used when RawContainer itself is already an
+// STL-style container.
+template <class RawContainer>
+class StlContainerView {
+ public:
+  typedef RawContainer type;
+  typedef const type& const_reference;
+
+  static const_reference ConstReference(const RawContainer& container) {
+    // Ensures that RawContainer is not a const type.
+    testing::StaticAssertTypeEq<RawContainer,
+        GTEST_REMOVE_CONST_(RawContainer)>();
+    return container;
+  }
+  static type Copy(const RawContainer& container) { return container; }
+};
+
+// This specialization is used when RawContainer is a native array type.
+template <typename Element, size_t N>
+class StlContainerView<Element[N]> {
+ public:
+  typedef GTEST_REMOVE_CONST_(Element) RawElement;
+  typedef internal::NativeArray<RawElement> type;
+  // NativeArray<T> can represent a native array either by value or by
+  // reference (selected by a constructor argument), so 'const type'
+  // can be used to reference a const native array.  We cannot
+  // 'typedef const type& const_reference' here, as that would mean
+  // ConstReference() has to return a reference to a local variable.
+  typedef const type const_reference;
+
+  static const_reference ConstReference(const Element (&array)[N]) {
+    // Ensures that Element is not a const type.
+    testing::StaticAssertTypeEq<Element, RawElement>();
+#if GTEST_OS_SYMBIAN
+    // The Nokia Symbian compiler confuses itself in template instantiation
+    // for this call without the cast to Element*:
+    // function call '[testing::internal::NativeArray<char *>].NativeArray(
+    //     {lval} const char *[4], long, testing::internal::RelationToSource)'
+    //     does not match
+    // 'testing::internal::NativeArray<char *>::NativeArray(
+    //     char *const *, unsigned int, testing::internal::RelationToSource)'
+    // (instantiating: 'testing::internal::ContainsMatcherImpl
+    //     <const char * (&)[4]>::Matches(const char * (&)[4]) const')
+    // (instantiating: 'testing::internal::StlContainerView<char *[4]>::
+    //     ConstReference(const char * (&)[4])')
+    // (and though the N parameter type is mismatched in the above explicit
+    // conversion of it doesn't help - only the conversion of the array).
+    return type(const_cast<Element*>(&array[0]), N,
+                RelationToSourceReference());
+#else
+    return type(array, N, RelationToSourceReference());
+#endif  // GTEST_OS_SYMBIAN
+  }
+  static type Copy(const Element (&array)[N]) {
+#if GTEST_OS_SYMBIAN
+    return type(const_cast<Element*>(&array[0]), N, RelationToSourceCopy());
+#else
+    return type(array, N, RelationToSourceCopy());
+#endif  // GTEST_OS_SYMBIAN
+  }
+};
+
+// This specialization is used when RawContainer is a native array
+// represented as a (pointer, size) tuple.
+template <typename ElementPointer, typename Size>
+class StlContainerView< ::testing::tuple<ElementPointer, Size> > {
+ public:
+  typedef GTEST_REMOVE_CONST_(
+      typename internal::PointeeOf<ElementPointer>::type) RawElement;
+  typedef internal::NativeArray<RawElement> type;
+  typedef const type const_reference;
+
+  static const_reference ConstReference(
+      const ::testing::tuple<ElementPointer, Size>& array) {
+    return type(get<0>(array), get<1>(array), RelationToSourceReference());
+  }
+  static type Copy(const ::testing::tuple<ElementPointer, Size>& array) {
+    return type(get<0>(array), get<1>(array), RelationToSourceCopy());
+  }
+};
+
+// The following specialization prevents the user from instantiating
+// StlContainer with a reference type.
+template <typename T> class StlContainerView<T&>;
+
+// A type transform to remove constness from the first part of a pair.
+// Pairs like that are used as the value_type of associative containers,
+// and this transform produces a similar but assignable pair.
+template <typename T>
+struct RemoveConstFromKey {
+  typedef T type;
+};
+
+// Partially specialized to remove constness from std::pair<const K, V>.
+template <typename K, typename V>
+struct RemoveConstFromKey<std::pair<const K, V> > {
+  typedef std::pair<K, V> type;
+};
+
+// Mapping from booleans to types. Similar to boost::bool_<kValue> and
+// std::integral_constant<bool, kValue>.
+template <bool kValue>
+struct BooleanConstant {};
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_
+
diff --git a/third_party/googletest/googlemock/include/gmock/internal/gmock-port.h b/third_party/googletest/googlemock/include/gmock/internal/gmock-port.h
new file mode 100644
index 0000000..63f4a68
--- /dev/null
+++ b/third_party/googletest/googlemock/include/gmock/internal/gmock-port.h
@@ -0,0 +1,91 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vadimb@google.com (Vadim Berman)
+//
+// Low-level types and utilities for porting Google Mock to various
+// platforms.  All macros ending with _ and symbols defined in an
+// internal namespace are subject to change without notice.  Code
+// outside Google Mock MUST NOT USE THEM DIRECTLY.  Macros that don't
+// end with _ are part of Google Mock's public API and can be used by
+// code outside Google Mock.
+
+#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_
+#define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_
+
+#include <assert.h>
+#include <stdlib.h>
+#include <iostream>
+
+// Most of the utilities needed for porting Google Mock are also
+// required for Google Test and are defined in gtest-port.h.
+//
+// Note to maintainers: to reduce code duplication, prefer adding
+// portability utilities to Google Test's gtest-port.h instead of
+// here, as Google Mock depends on Google Test.  Only add a utility
+// here if it's truly specific to Google Mock.
+#include "gtest/internal/gtest-linked_ptr.h"
+#include "gtest/internal/gtest-port.h"
+#include "gmock/internal/custom/gmock-port.h"
+
+// To avoid conditional compilation everywhere, we make it
+// gmock-port.h's responsibility to #include the header implementing
+// tr1/tuple.  gmock-port.h does this via gtest-port.h, which is
+// guaranteed to pull in the tuple header.
+
+// For MS Visual C++, check the compiler version. At least VS 2003 is
+// required to compile Google Mock.
+#if defined(_MSC_VER) && _MSC_VER < 1310
+# error "At least Visual C++ 2003 (7.1) is required to compile Google Mock."
+#endif
+
+// Macro for referencing flags.  This is public as we want the user to
+// use this syntax to reference Google Mock flags.
+#define GMOCK_FLAG(name) FLAGS_gmock_##name
+
+#if !defined(GMOCK_DECLARE_bool_)
+
+// Macros for declaring flags.
+#define GMOCK_DECLARE_bool_(name) extern GTEST_API_ bool GMOCK_FLAG(name)
+#define GMOCK_DECLARE_int32_(name) \
+    extern GTEST_API_ ::testing::internal::Int32 GMOCK_FLAG(name)
+#define GMOCK_DECLARE_string_(name) \
+    extern GTEST_API_ ::std::string GMOCK_FLAG(name)
+
+// Macros for defining flags.
+#define GMOCK_DEFINE_bool_(name, default_val, doc) \
+    GTEST_API_ bool GMOCK_FLAG(name) = (default_val)
+#define GMOCK_DEFINE_int32_(name, default_val, doc) \
+    GTEST_API_ ::testing::internal::Int32 GMOCK_FLAG(name) = (default_val)
+#define GMOCK_DEFINE_string_(name, default_val, doc) \
+    GTEST_API_ ::std::string GMOCK_FLAG(name) = (default_val)
+
+#endif  // !defined(GMOCK_DECLARE_bool_)
+
+#endif  // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_
diff --git a/third_party/googletest/googlemock/make/Makefile b/third_party/googletest/googlemock/make/Makefile
new file mode 100644
index 0000000..c1cc0e9
--- /dev/null
+++ b/third_party/googletest/googlemock/make/Makefile
@@ -0,0 +1,101 @@
+# A sample Makefile for building both Google Mock and Google Test and
+# using them in user tests.  This file is self-contained, so you don't
+# need to use the Makefile in Google Test's source tree.  Please tweak
+# it to suit your environment and project.  You may want to move it to
+# your project's root directory.
+#
+# SYNOPSIS:
+#
+#   make [all]  - makes everything.
+#   make TARGET - makes the given target.
+#   make clean  - removes all files generated by make.
+
+# Please tweak the following variable definitions as needed by your
+# project, except GMOCK_HEADERS and GTEST_HEADERS, which you can use
+# in your own targets but shouldn't modify.
+
+# Points to the root of Google Test, relative to where this file is.
+# Remember to tweak this if you move this file, or if you want to use
+# a copy of Google Test at a different location.
+GTEST_DIR = ../gtest
+
+# Points to the root of Google Mock, relative to where this file is.
+# Remember to tweak this if you move this file.
+GMOCK_DIR = ..
+
+# Where to find user code.
+USER_DIR = ../test
+
+# Flags passed to the preprocessor.
+# Set Google Test and Google Mock's header directories as system
+# directories, such that the compiler doesn't generate warnings in
+# these headers.
+CPPFLAGS += -isystem $(GTEST_DIR)/include -isystem $(GMOCK_DIR)/include
+
+# Flags passed to the C++ compiler.
+CXXFLAGS += -g -Wall -Wextra -pthread
+
+# All tests produced by this Makefile.  Remember to add new tests you
+# created to the list.
+TESTS = gmock_test
+
+# All Google Test headers.  Usually you shouldn't change this
+# definition.
+GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \
+                $(GTEST_DIR)/include/gtest/internal/*.h
+
+# All Google Mock headers. Note that all Google Test headers are
+# included here too, as they are #included by Google Mock headers.
+# Usually you shouldn't change this definition.	
+GMOCK_HEADERS = $(GMOCK_DIR)/include/gmock/*.h \
+                $(GMOCK_DIR)/include/gmock/internal/*.h \
+                $(GTEST_HEADERS)
+
+# House-keeping build targets.
+
+all : $(TESTS)
+
+clean :
+	rm -f $(TESTS) gmock.a gmock_main.a *.o
+
+# Builds gmock.a and gmock_main.a.  These libraries contain both
+# Google Mock and Google Test.  A test should link with either gmock.a
+# or gmock_main.a, depending on whether it defines its own main()
+# function.  It's fine if your test only uses features from Google
+# Test (and not Google Mock).
+
+# Usually you shouldn't tweak such internal variables, indicated by a
+# trailing _.
+GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS)
+GMOCK_SRCS_ = $(GMOCK_DIR)/src/*.cc $(GMOCK_HEADERS)
+
+# For simplicity and to avoid depending on implementation details of
+# Google Mock and Google Test, the dependencies specified below are
+# conservative and not optimized.  This is fine as Google Mock and
+# Google Test compile fast and for ordinary users their source rarely
+# changes.
+gtest-all.o : $(GTEST_SRCS_)
+	$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) -I$(GMOCK_DIR) $(CXXFLAGS) \
+            -c $(GTEST_DIR)/src/gtest-all.cc
+
+gmock-all.o : $(GMOCK_SRCS_)
+	$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) -I$(GMOCK_DIR) $(CXXFLAGS) \
+            -c $(GMOCK_DIR)/src/gmock-all.cc
+
+gmock_main.o : $(GMOCK_SRCS_)
+	$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) -I$(GMOCK_DIR) $(CXXFLAGS) \
+            -c $(GMOCK_DIR)/src/gmock_main.cc
+
+gmock.a : gmock-all.o gtest-all.o
+	$(AR) $(ARFLAGS) $@ $^
+
+gmock_main.a : gmock-all.o gtest-all.o gmock_main.o
+	$(AR) $(ARFLAGS) $@ $^
+
+# Builds a sample test.
+
+gmock_test.o : $(USER_DIR)/gmock_test.cc $(GMOCK_HEADERS)
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/gmock_test.cc
+
+gmock_test : gmock_test.o gmock_main.a
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
diff --git a/third_party/googletest/googlemock/msvc/2005/gmock.sln b/third_party/googletest/googlemock/msvc/2005/gmock.sln
new file mode 100644
index 0000000..b752f87
--- /dev/null
+++ b/third_party/googletest/googlemock/msvc/2005/gmock.sln
@@ -0,0 +1,32 @@
+

+Microsoft Visual Studio Solution File, Format Version 9.00

+# Visual Studio 2005

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gmock", "gmock.vcproj", "{34681F0D-CE45-415D-B5F2-5C662DFE3BD5}"

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gmock_test", "gmock_test.vcproj", "{F10D22F8-AC7B-4213-8720-608E7D878CD2}"

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gmock_main", "gmock_main.vcproj", "{E4EF614B-30DF-4954-8C53-580A0BF6B589}"

+EndProject

+Global

+	GlobalSection(SolutionConfigurationPlatforms) = preSolution

+		Debug|Win32 = Debug|Win32

+		Release|Win32 = Release|Win32

+	EndGlobalSection

+	GlobalSection(ProjectConfigurationPlatforms) = postSolution

+		{34681F0D-CE45-415D-B5F2-5C662DFE3BD5}.Debug|Win32.ActiveCfg = Debug|Win32

+		{34681F0D-CE45-415D-B5F2-5C662DFE3BD5}.Debug|Win32.Build.0 = Debug|Win32

+		{34681F0D-CE45-415D-B5F2-5C662DFE3BD5}.Release|Win32.ActiveCfg = Release|Win32

+		{34681F0D-CE45-415D-B5F2-5C662DFE3BD5}.Release|Win32.Build.0 = Release|Win32

+		{F10D22F8-AC7B-4213-8720-608E7D878CD2}.Debug|Win32.ActiveCfg = Debug|Win32

+		{F10D22F8-AC7B-4213-8720-608E7D878CD2}.Debug|Win32.Build.0 = Debug|Win32

+		{F10D22F8-AC7B-4213-8720-608E7D878CD2}.Release|Win32.ActiveCfg = Release|Win32

+		{F10D22F8-AC7B-4213-8720-608E7D878CD2}.Release|Win32.Build.0 = Release|Win32

+		{E4EF614B-30DF-4954-8C53-580A0BF6B589}.Debug|Win32.ActiveCfg = Debug|Win32

+		{E4EF614B-30DF-4954-8C53-580A0BF6B589}.Debug|Win32.Build.0 = Debug|Win32

+		{E4EF614B-30DF-4954-8C53-580A0BF6B589}.Release|Win32.ActiveCfg = Release|Win32

+		{E4EF614B-30DF-4954-8C53-580A0BF6B589}.Release|Win32.Build.0 = Release|Win32

+	EndGlobalSection

+	GlobalSection(SolutionProperties) = preSolution

+		HideSolutionNode = FALSE

+	EndGlobalSection

+EndGlobal

diff --git a/third_party/googletest/googlemock/msvc/2005/gmock.vcproj b/third_party/googletest/googlemock/msvc/2005/gmock.vcproj
new file mode 100644
index 0000000..4bbfe98
--- /dev/null
+++ b/third_party/googletest/googlemock/msvc/2005/gmock.vcproj
@@ -0,0 +1,191 @@
+<?xml version="1.0" encoding="Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="8.00"

+	Name="gmock"

+	ProjectGUID="{34681F0D-CE45-415D-B5F2-5C662DFE3BD5}"

+	RootNamespace="gmock"

+	Keyword="Win32Proj"

+	>

+	<Platforms>

+		<Platform

+			Name="Win32"

+		/>

+	</Platforms>

+	<ToolFiles>

+	</ToolFiles>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"

+			IntermediateDirectory="$(OutDir)\$(ProjectName)"

+			ConfigurationType="4"

+			InheritedPropertySheets=".\gmock_config.vsprops"

+			CharacterSet="1"

+			>

+			<Tool

+				Name="VCPreBuildEventTool"

+			/>

+			<Tool

+				Name="VCCustomBuildTool"

+			/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"

+			/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"

+			/>

+			<Tool

+				Name="VCMIDLTool"

+			/>

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="0"

+				AdditionalIncludeDirectories="..\..\include;..\.."

+				PreprocessorDefinitions="WIN32;_DEBUG;_LIB"

+				MinimalRebuild="true"

+				BasicRuntimeChecks="3"

+				RuntimeLibrary="1"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="true"

+				DebugInformationFormat="3"

+			/>

+			<Tool

+				Name="VCManagedResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCPreLinkEventTool"

+			/>

+			<Tool

+				Name="VCLibrarianTool"

+			/>

+			<Tool

+				Name="VCALinkTool"

+			/>

+			<Tool

+				Name="VCXDCMakeTool"

+			/>

+			<Tool

+				Name="VCBscMakeTool"

+			/>

+			<Tool

+				Name="VCFxCopTool"

+			/>

+			<Tool

+				Name="VCPostBuildEventTool"

+			/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"

+			IntermediateDirectory="$(OutDir)\$(ProjectName)"

+			ConfigurationType="4"

+			InheritedPropertySheets=".\gmock_config.vsprops"

+			CharacterSet="1"

+			WholeProgramOptimization="1"

+			>

+			<Tool

+				Name="VCPreBuildEventTool"

+			/>

+			<Tool

+				Name="VCCustomBuildTool"

+			/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"

+			/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"

+			/>

+			<Tool

+				Name="VCMIDLTool"

+			/>

+			<Tool

+				Name="VCCLCompilerTool"

+				AdditionalIncludeDirectories="..\..\include;..\.."

+				PreprocessorDefinitions="WIN32;NDEBUG;_LIB"

+				RuntimeLibrary="0"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="true"

+				DebugInformationFormat="3"

+			/>

+			<Tool

+				Name="VCManagedResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCPreLinkEventTool"

+			/>

+			<Tool

+				Name="VCLibrarianTool"

+			/>

+			<Tool

+				Name="VCALinkTool"

+			/>

+			<Tool

+				Name="VCXDCMakeTool"

+			/>

+			<Tool

+				Name="VCBscMakeTool"

+			/>

+			<Tool

+				Name="VCFxCopTool"

+			/>

+			<Tool

+				Name="VCPostBuildEventTool"

+			/>

+		</Configuration>

+	</Configurations>

+	<References>

+	</References>

+	<Files>

+		<Filter

+			Name="Source Files"

+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"

+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"

+			>

+			<File

+				RelativePath="..\..\src\gmock-all.cc"

+				>

+			</File>

+			<File

+				RelativePath="$(GTestDir)\src\gtest-all.cc"

+				>

+				<FileConfiguration

+					Name="Debug|Win32"

+					>

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="$(GTestDir)"

+					/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32"

+					>

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="$(GTestDir)"

+					/>

+				</FileConfiguration>

+			</File>

+		</Filter>

+		<Filter

+			Name="Public Header Files"

+			Filter="h;hpp;hxx;hm;inl;inc;xsd"

+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"

+			>

+		</Filter>

+		<Filter

+			Name="Private Header Files"

+			>

+		</Filter>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/third_party/googletest/googlemock/msvc/2005/gmock_config.vsprops b/third_party/googletest/googlemock/msvc/2005/gmock_config.vsprops
new file mode 100644
index 0000000..8b65cfb
--- /dev/null
+++ b/third_party/googletest/googlemock/msvc/2005/gmock_config.vsprops
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="Windows-1252"?>

+<VisualStudioPropertySheet

+	ProjectType="Visual C++"

+	Version="8.00"

+	Name="gmock_config"

+	>

+	<Tool

+		Name="VCCLCompilerTool"

+		AdditionalIncludeDirectories="&quot;$(GTestDir)/include&quot;"

+	/>

+	<UserMacro

+		Name="GTestDir"

+		Value="../../gtest"

+	/>

+</VisualStudioPropertySheet>

diff --git a/third_party/googletest/googlemock/msvc/2005/gmock_main.vcproj b/third_party/googletest/googlemock/msvc/2005/gmock_main.vcproj
new file mode 100644
index 0000000..01505a9
--- /dev/null
+++ b/third_party/googletest/googlemock/msvc/2005/gmock_main.vcproj
@@ -0,0 +1,187 @@
+<?xml version="1.0" encoding="Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="8.00"

+	Name="gmock_main"

+	ProjectGUID="{E4EF614B-30DF-4954-8C53-580A0BF6B589}"

+	RootNamespace="gmock_main"

+	Keyword="Win32Proj"

+	>

+	<Platforms>

+		<Platform

+			Name="Win32"

+		/>

+	</Platforms>

+	<ToolFiles>

+	</ToolFiles>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"

+			IntermediateDirectory="$(OutDir)\$(ProjectName)"

+			ConfigurationType="4"

+			InheritedPropertySheets=".\gmock_config.vsprops"

+			CharacterSet="1"

+			>

+			<Tool

+				Name="VCPreBuildEventTool"

+			/>

+			<Tool

+				Name="VCCustomBuildTool"

+			/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"

+			/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"

+			/>

+			<Tool

+				Name="VCMIDLTool"

+			/>

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="0"

+				AdditionalIncludeDirectories="../../include"

+				PreprocessorDefinitions="WIN32;_DEBUG;_LIB"

+				MinimalRebuild="true"

+				BasicRuntimeChecks="3"

+				RuntimeLibrary="1"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="true"

+				DebugInformationFormat="3"

+			/>

+			<Tool

+				Name="VCManagedResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCPreLinkEventTool"

+			/>

+			<Tool

+				Name="VCLibrarianTool"

+			/>

+			<Tool

+				Name="VCALinkTool"

+			/>

+			<Tool

+				Name="VCXDCMakeTool"

+			/>

+			<Tool

+				Name="VCBscMakeTool"

+			/>

+			<Tool

+				Name="VCFxCopTool"

+			/>

+			<Tool

+				Name="VCPostBuildEventTool"

+			/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"

+			IntermediateDirectory="$(OutDir)\$(ProjectName)"

+			ConfigurationType="4"

+			InheritedPropertySheets=".\gmock_config.vsprops"

+			CharacterSet="1"

+			WholeProgramOptimization="1"

+			>

+			<Tool

+				Name="VCPreBuildEventTool"

+			/>

+			<Tool

+				Name="VCCustomBuildTool"

+			/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"

+			/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"

+			/>

+			<Tool

+				Name="VCMIDLTool"

+			/>

+			<Tool

+				Name="VCCLCompilerTool"

+				AdditionalIncludeDirectories="../../include"

+				PreprocessorDefinitions="WIN32;NDEBUG;_LIB"

+				RuntimeLibrary="0"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="true"

+				DebugInformationFormat="3"

+			/>

+			<Tool

+				Name="VCManagedResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCPreLinkEventTool"

+			/>

+			<Tool

+				Name="VCLibrarianTool"

+			/>

+			<Tool

+				Name="VCALinkTool"

+			/>

+			<Tool

+				Name="VCXDCMakeTool"

+			/>

+			<Tool

+				Name="VCBscMakeTool"

+			/>

+			<Tool

+				Name="VCFxCopTool"

+			/>

+			<Tool

+				Name="VCPostBuildEventTool"

+			/>

+		</Configuration>

+	</Configurations>

+	<References>

+		<ProjectReference

+			ReferencedProjectIdentifier="{34681F0D-CE45-415D-B5F2-5C662DFE3BD5}"

+			RelativePathToProject=".\gmock.vcproj"

+		/>

+	</References>

+	<Files>

+		<Filter

+			Name="Source Files"

+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"

+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"

+			>

+			<File

+				RelativePath="..\..\src\gmock_main.cc"

+				>

+				<FileConfiguration

+					Name="Debug|Win32"

+					>

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="../../include"

+					/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32"

+					>

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="../../include"

+					/>

+				</FileConfiguration>

+			</File>

+		</Filter>

+		<Filter

+			Name="Header Files"

+			Filter="h;hpp;hxx;hm;inl;inc;xsd"

+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"

+			>

+		</Filter>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/third_party/googletest/googlemock/msvc/2005/gmock_test.vcproj b/third_party/googletest/googlemock/msvc/2005/gmock_test.vcproj
new file mode 100644
index 0000000..d1e01e7
--- /dev/null
+++ b/third_party/googletest/googlemock/msvc/2005/gmock_test.vcproj
@@ -0,0 +1,201 @@
+<?xml version="1.0" encoding="Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="8.00"

+	Name="gmock_test"

+	ProjectGUID="{F10D22F8-AC7B-4213-8720-608E7D878CD2}"

+	RootNamespace="gmock_test"

+	Keyword="Win32Proj"

+	>

+	<Platforms>

+		<Platform

+			Name="Win32"

+		/>

+	</Platforms>

+	<ToolFiles>

+	</ToolFiles>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"

+			IntermediateDirectory="$(OutDir)\$(ProjectName)"

+			ConfigurationType="1"

+			InheritedPropertySheets=".\gmock_config.vsprops"

+			CharacterSet="1"

+			>

+			<Tool

+				Name="VCPreBuildEventTool"

+			/>

+			<Tool

+				Name="VCCustomBuildTool"

+			/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"

+			/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"

+			/>

+			<Tool

+				Name="VCMIDLTool"

+			/>

+			<Tool

+				Name="VCCLCompilerTool"

+				AdditionalOptions="/bigobj"

+				Optimization="0"

+				AdditionalIncludeDirectories="..\..\include;..\.."

+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"

+				MinimalRebuild="true"

+				BasicRuntimeChecks="3"

+				RuntimeLibrary="1"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="true"

+				DebugInformationFormat="3"

+			/>

+			<Tool

+				Name="VCManagedResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCPreLinkEventTool"

+			/>

+			<Tool

+				Name="VCLinkerTool"

+				LinkIncremental="2"

+				GenerateDebugInformation="true"

+				SubSystem="1"

+				TargetMachine="1"

+			/>

+			<Tool

+				Name="VCALinkTool"

+			/>

+			<Tool

+				Name="VCManifestTool"

+			/>

+			<Tool

+				Name="VCXDCMakeTool"

+			/>

+			<Tool

+				Name="VCBscMakeTool"

+			/>

+			<Tool

+				Name="VCFxCopTool"

+			/>

+			<Tool

+				Name="VCAppVerifierTool"

+			/>

+			<Tool

+				Name="VCWebDeploymentTool"

+			/>

+			<Tool

+				Name="VCPostBuildEventTool"

+			/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"

+			IntermediateDirectory="$(OutDir)\$(ProjectName)"

+			ConfigurationType="1"

+			InheritedPropertySheets=".\gmock_config.vsprops"

+			CharacterSet="1"

+			WholeProgramOptimization="1"

+			>

+			<Tool

+				Name="VCPreBuildEventTool"

+			/>

+			<Tool

+				Name="VCCustomBuildTool"

+			/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"

+			/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"

+			/>

+			<Tool

+				Name="VCMIDLTool"

+			/>

+			<Tool

+				Name="VCCLCompilerTool"

+				AdditionalOptions="/bigobj"

+				AdditionalIncludeDirectories="..\..\include;..\.."

+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"

+				RuntimeLibrary="0"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="true"

+				DebugInformationFormat="3"

+			/>

+			<Tool

+				Name="VCManagedResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCPreLinkEventTool"

+			/>

+			<Tool

+				Name="VCLinkerTool"

+				LinkIncremental="1"

+				GenerateDebugInformation="true"

+				SubSystem="1"

+				OptimizeReferences="2"

+				EnableCOMDATFolding="2"

+				TargetMachine="1"

+			/>

+			<Tool

+				Name="VCALinkTool"

+			/>

+			<Tool

+				Name="VCManifestTool"

+			/>

+			<Tool

+				Name="VCXDCMakeTool"

+			/>

+			<Tool

+				Name="VCBscMakeTool"

+			/>

+			<Tool

+				Name="VCFxCopTool"

+			/>

+			<Tool

+				Name="VCAppVerifierTool"

+			/>

+			<Tool

+				Name="VCWebDeploymentTool"

+			/>

+			<Tool

+				Name="VCPostBuildEventTool"

+			/>

+		</Configuration>

+	</Configurations>

+	<References>

+		<ProjectReference

+			ReferencedProjectIdentifier="{E4EF614B-30DF-4954-8C53-580A0BF6B589}"

+			RelativePathToProject=".\gmock_main.vcproj"

+		/>

+	</References>

+	<Files>

+		<Filter

+			Name="Source Files"

+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"

+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"

+			>

+			<File

+				RelativePath="..\..\test\gmock_all_test.cc"

+				>

+			</File>

+		</Filter>

+		<Filter

+			Name="Header Files"

+			Filter="h;hpp;hxx;hm;inl;inc;xsd"

+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"

+			>

+		</Filter>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/third_party/googletest/googlemock/msvc/2010/gmock.sln b/third_party/googletest/googlemock/msvc/2010/gmock.sln
new file mode 100644
index 0000000..d949656
--- /dev/null
+++ b/third_party/googletest/googlemock/msvc/2010/gmock.sln
@@ -0,0 +1,32 @@
+

+Microsoft Visual Studio Solution File, Format Version 11.00

+# Visual C++ Express 2010

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gmock", "gmock.vcxproj", "{34681F0D-CE45-415D-B5F2-5C662DFE3BD5}"

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gmock_test", "gmock_test.vcxproj", "{F10D22F8-AC7B-4213-8720-608E7D878CD2}"

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gmock_main", "gmock_main.vcxproj", "{E4EF614B-30DF-4954-8C53-580A0BF6B589}"

+EndProject

+Global

+	GlobalSection(SolutionConfigurationPlatforms) = preSolution

+		Debug|Win32 = Debug|Win32

+		Release|Win32 = Release|Win32

+	EndGlobalSection

+	GlobalSection(ProjectConfigurationPlatforms) = postSolution

+		{34681F0D-CE45-415D-B5F2-5C662DFE3BD5}.Debug|Win32.ActiveCfg = Debug|Win32

+		{34681F0D-CE45-415D-B5F2-5C662DFE3BD5}.Debug|Win32.Build.0 = Debug|Win32

+		{34681F0D-CE45-415D-B5F2-5C662DFE3BD5}.Release|Win32.ActiveCfg = Release|Win32

+		{34681F0D-CE45-415D-B5F2-5C662DFE3BD5}.Release|Win32.Build.0 = Release|Win32

+		{F10D22F8-AC7B-4213-8720-608E7D878CD2}.Debug|Win32.ActiveCfg = Debug|Win32

+		{F10D22F8-AC7B-4213-8720-608E7D878CD2}.Debug|Win32.Build.0 = Debug|Win32

+		{F10D22F8-AC7B-4213-8720-608E7D878CD2}.Release|Win32.ActiveCfg = Release|Win32

+		{F10D22F8-AC7B-4213-8720-608E7D878CD2}.Release|Win32.Build.0 = Release|Win32

+		{E4EF614B-30DF-4954-8C53-580A0BF6B589}.Debug|Win32.ActiveCfg = Debug|Win32

+		{E4EF614B-30DF-4954-8C53-580A0BF6B589}.Debug|Win32.Build.0 = Debug|Win32

+		{E4EF614B-30DF-4954-8C53-580A0BF6B589}.Release|Win32.ActiveCfg = Release|Win32

+		{E4EF614B-30DF-4954-8C53-580A0BF6B589}.Release|Win32.Build.0 = Release|Win32

+	EndGlobalSection

+	GlobalSection(SolutionProperties) = preSolution

+		HideSolutionNode = FALSE

+	EndGlobalSection

+EndGlobal

diff --git a/third_party/googletest/googlemock/msvc/2010/gmock.vcxproj b/third_party/googletest/googlemock/msvc/2010/gmock.vcxproj
new file mode 100644
index 0000000..21a85ef
--- /dev/null
+++ b/third_party/googletest/googlemock/msvc/2010/gmock.vcxproj
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{34681F0D-CE45-415D-B5F2-5C662DFE3BD5}</ProjectGuid>

+    <RootNamespace>gmock</RootNamespace>

+    <Keyword>Win32Proj</Keyword>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>StaticLibrary</ConfigurationType>

+    <CharacterSet>Unicode</CharacterSet>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>StaticLibrary</ConfigurationType>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+    <Import Project="gmock_config.props" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+    <Import Project="gmock_config.props" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup>

+    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>

+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(OutDir)$(ProjectName)\</IntDir>

+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(OutDir)$(ProjectName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <Optimization>Disabled</Optimization>

+      <AdditionalIncludeDirectories>..\..\include;..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <MinimalRebuild>true</MinimalRebuild>

+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <WarningLevel>Level3</WarningLevel>

+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

+    </ClCompile>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <AdditionalIncludeDirectories>..\..\include;..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <WarningLevel>Level3</WarningLevel>

+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

+    </ClCompile>

+  </ItemDefinitionGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\src\gmock-all.cc" />

+    <ClCompile Include="$(GTestDir)\src\gtest-all.cc">

+      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(GTestDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(GTestDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+    </ClCompile>

+  </ItemGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/googletest/googlemock/msvc/2010/gmock_config.props b/third_party/googletest/googlemock/msvc/2010/gmock_config.props
new file mode 100644
index 0000000..bd497f1
--- /dev/null
+++ b/third_party/googletest/googlemock/msvc/2010/gmock_config.props
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <PropertyGroup Label="UserMacros">

+    <GTestDir>../../gtest</GTestDir>

+  </PropertyGroup>

+  <PropertyGroup>

+    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>

+  </PropertyGroup>

+  <ItemDefinitionGroup>

+    <ClCompile>

+      <AdditionalIncludeDirectories>$(GTestDir)/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+    </ClCompile>

+  </ItemDefinitionGroup>

+  <ItemGroup>

+    <BuildMacro Include="GTestDir">

+      <Value>$(GTestDir)</Value>

+    </BuildMacro>

+  </ItemGroup>

+</Project>

diff --git a/third_party/googletest/googlemock/msvc/2010/gmock_main.vcxproj b/third_party/googletest/googlemock/msvc/2010/gmock_main.vcxproj
new file mode 100644
index 0000000..27fecd5
--- /dev/null
+++ b/third_party/googletest/googlemock/msvc/2010/gmock_main.vcxproj
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{E4EF614B-30DF-4954-8C53-580A0BF6B589}</ProjectGuid>

+    <RootNamespace>gmock_main</RootNamespace>

+    <Keyword>Win32Proj</Keyword>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>StaticLibrary</ConfigurationType>

+    <CharacterSet>Unicode</CharacterSet>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>StaticLibrary</ConfigurationType>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+    <Import Project="gmock_config.props" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+    <Import Project="gmock_config.props" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup>

+    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>

+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(OutDir)$(ProjectName)\</IntDir>

+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(OutDir)$(ProjectName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <Optimization>Disabled</Optimization>

+      <AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <MinimalRebuild>true</MinimalRebuild>

+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <WarningLevel>Level3</WarningLevel>

+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

+    </ClCompile>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <WarningLevel>Level3</WarningLevel>

+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

+    </ClCompile>

+  </ItemDefinitionGroup>

+  <ItemGroup>

+    <ProjectReference Include="gmock.vcxproj">

+      <Project>{34681f0d-ce45-415d-b5f2-5c662dfe3bd5}</Project>

+      <CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>

+      <ReferenceOutputAssembly>true</ReferenceOutputAssembly>

+    </ProjectReference>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\src\gmock_main.cc">

+      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+    </ClCompile>

+  </ItemGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/googletest/googlemock/msvc/2010/gmock_test.vcxproj b/third_party/googletest/googlemock/msvc/2010/gmock_test.vcxproj
new file mode 100644
index 0000000..265439e
--- /dev/null
+++ b/third_party/googletest/googlemock/msvc/2010/gmock_test.vcxproj
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{F10D22F8-AC7B-4213-8720-608E7D878CD2}</ProjectGuid>

+    <RootNamespace>gmock_test</RootNamespace>

+    <Keyword>Win32Proj</Keyword>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <CharacterSet>Unicode</CharacterSet>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+    <Import Project="gmock_config.props" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+    <Import Project="gmock_config.props" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup>

+    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>

+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(OutDir)$(ProjectName)\</IntDir>

+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>

+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>

+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(OutDir)$(ProjectName)\</IntDir>

+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>

+      <Optimization>Disabled</Optimization>

+      <AdditionalIncludeDirectories>..\..\include;..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <MinimalRebuild>true</MinimalRebuild>

+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <WarningLevel>Level3</WarningLevel>

+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

+    </ClCompile>

+    <Link>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <SubSystem>Console</SubSystem>

+      <TargetMachine>MachineX86</TargetMachine>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>

+      <AdditionalIncludeDirectories>..\..\include;..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <WarningLevel>Level3</WarningLevel>

+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

+    </ClCompile>

+    <Link>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <SubSystem>Console</SubSystem>

+      <OptimizeReferences>true</OptimizeReferences>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <TargetMachine>MachineX86</TargetMachine>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemGroup>

+    <ProjectReference Include="gmock_main.vcxproj">

+      <Project>{e4ef614b-30df-4954-8c53-580a0bf6b589}</Project>

+      <CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>

+      <ReferenceOutputAssembly>true</ReferenceOutputAssembly>

+    </ProjectReference>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\test\gmock_all_test.cc" />

+  </ItemGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/googletest/googlemock/scripts/fuse_gmock_files.py b/third_party/googletest/googlemock/scripts/fuse_gmock_files.py
new file mode 100755
index 0000000..fc0baf7
--- /dev/null
+++ b/third_party/googletest/googlemock/scripts/fuse_gmock_files.py
@@ -0,0 +1,240 @@
+#!/usr/bin/env python
+#
+# Copyright 2009, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""fuse_gmock_files.py v0.1.0
+Fuses Google Mock and Google Test source code into two .h files and a .cc file.
+
+SYNOPSIS
+       fuse_gmock_files.py [GMOCK_ROOT_DIR] OUTPUT_DIR
+
+       Scans GMOCK_ROOT_DIR for Google Mock and Google Test source
+       code, assuming Google Test is in the GMOCK_ROOT_DIR/gtest
+       sub-directory, and generates three files:
+       OUTPUT_DIR/gtest/gtest.h, OUTPUT_DIR/gmock/gmock.h, and
+       OUTPUT_DIR/gmock-gtest-all.cc.  Then you can build your tests
+       by adding OUTPUT_DIR to the include search path and linking
+       with OUTPUT_DIR/gmock-gtest-all.cc.  These three files contain
+       everything you need to use Google Mock.  Hence you can
+       "install" Google Mock by copying them to wherever you want.
+
+       GMOCK_ROOT_DIR can be omitted and defaults to the parent
+       directory of the directory holding this script.
+
+EXAMPLES
+       ./fuse_gmock_files.py fused_gmock
+       ./fuse_gmock_files.py path/to/unpacked/gmock fused_gmock
+
+This tool is experimental.  In particular, it assumes that there is no
+conditional inclusion of Google Mock or Google Test headers.  Please
+report any problems to googlemock@googlegroups.com.  You can read
+http://code.google.com/p/googlemock/wiki/CookBook for more
+information.
+"""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import os
+import re
+import sets
+import sys
+
+# We assume that this file is in the scripts/ directory in the Google
+# Mock root directory.
+DEFAULT_GMOCK_ROOT_DIR = os.path.join(os.path.dirname(__file__), '..')
+
+# We need to call into gtest/scripts/fuse_gtest_files.py.
+sys.path.append(os.path.join(DEFAULT_GMOCK_ROOT_DIR, 'gtest/scripts'))
+import fuse_gtest_files
+gtest = fuse_gtest_files
+
+# Regex for matching '#include "gmock/..."'.
+INCLUDE_GMOCK_FILE_REGEX = re.compile(r'^\s*#\s*include\s*"(gmock/.+)"')
+
+# Where to find the source seed files.
+GMOCK_H_SEED = 'include/gmock/gmock.h'
+GMOCK_ALL_CC_SEED = 'src/gmock-all.cc'
+
+# Where to put the generated files.
+GTEST_H_OUTPUT = 'gtest/gtest.h'
+GMOCK_H_OUTPUT = 'gmock/gmock.h'
+GMOCK_GTEST_ALL_CC_OUTPUT = 'gmock-gtest-all.cc'
+
+
+def GetGTestRootDir(gmock_root):
+  """Returns the root directory of Google Test."""
+
+  return os.path.join(gmock_root, 'gtest')
+
+
+def ValidateGMockRootDir(gmock_root):
+  """Makes sure gmock_root points to a valid gmock root directory.
+
+  The function aborts the program on failure.
+  """
+
+  gtest.ValidateGTestRootDir(GetGTestRootDir(gmock_root))
+  gtest.VerifyFileExists(gmock_root, GMOCK_H_SEED)
+  gtest.VerifyFileExists(gmock_root, GMOCK_ALL_CC_SEED)
+
+
+def ValidateOutputDir(output_dir):
+  """Makes sure output_dir points to a valid output directory.
+
+  The function aborts the program on failure.
+  """
+
+  gtest.VerifyOutputFile(output_dir, gtest.GTEST_H_OUTPUT)
+  gtest.VerifyOutputFile(output_dir, GMOCK_H_OUTPUT)
+  gtest.VerifyOutputFile(output_dir, GMOCK_GTEST_ALL_CC_OUTPUT)
+
+
+def FuseGMockH(gmock_root, output_dir):
+  """Scans folder gmock_root to generate gmock/gmock.h in output_dir."""
+
+  output_file = file(os.path.join(output_dir, GMOCK_H_OUTPUT), 'w')
+  processed_files = sets.Set()  # Holds all gmock headers we've processed.
+
+  def ProcessFile(gmock_header_path):
+    """Processes the given gmock header file."""
+
+    # We don't process the same header twice.
+    if gmock_header_path in processed_files:
+      return
+
+    processed_files.add(gmock_header_path)
+
+    # Reads each line in the given gmock header.
+    for line in file(os.path.join(gmock_root, gmock_header_path), 'r'):
+      m = INCLUDE_GMOCK_FILE_REGEX.match(line)
+      if m:
+        # It's '#include "gmock/..."' - let's process it recursively.
+        ProcessFile('include/' + m.group(1))
+      else:
+        m = gtest.INCLUDE_GTEST_FILE_REGEX.match(line)
+        if m:
+          # It's '#include "gtest/foo.h"'.  We translate it to
+          # "gtest/gtest.h", regardless of what foo is, since all
+          # gtest headers are fused into gtest/gtest.h.
+
+          # There is no need to #include gtest.h twice.
+          if not gtest.GTEST_H_SEED in processed_files:
+            processed_files.add(gtest.GTEST_H_SEED)
+            output_file.write('#include "%s"\n' % (gtest.GTEST_H_OUTPUT,))
+        else:
+          # Otherwise we copy the line unchanged to the output file.
+          output_file.write(line)
+
+  ProcessFile(GMOCK_H_SEED)
+  output_file.close()
+
+
+def FuseGMockAllCcToFile(gmock_root, output_file):
+  """Scans folder gmock_root to fuse gmock-all.cc into output_file."""
+
+  processed_files = sets.Set()
+
+  def ProcessFile(gmock_source_file):
+    """Processes the given gmock source file."""
+
+    # We don't process the same #included file twice.
+    if gmock_source_file in processed_files:
+      return
+
+    processed_files.add(gmock_source_file)
+
+    # Reads each line in the given gmock source file.
+    for line in file(os.path.join(gmock_root, gmock_source_file), 'r'):
+      m = INCLUDE_GMOCK_FILE_REGEX.match(line)
+      if m:
+        # It's '#include "gmock/foo.h"'.  We treat it as '#include
+        # "gmock/gmock.h"', as all other gmock headers are being fused
+        # into gmock.h and cannot be #included directly.
+
+        # There is no need to #include "gmock/gmock.h" more than once.
+        if not GMOCK_H_SEED in processed_files:
+          processed_files.add(GMOCK_H_SEED)
+          output_file.write('#include "%s"\n' % (GMOCK_H_OUTPUT,))
+      else:
+        m = gtest.INCLUDE_GTEST_FILE_REGEX.match(line)
+        if m:
+          # It's '#include "gtest/..."'.
+          # There is no need to #include gtest.h as it has been
+          # #included by gtest-all.cc.
+          pass
+        else:
+          m = gtest.INCLUDE_SRC_FILE_REGEX.match(line)
+          if m:
+            # It's '#include "src/foo"' - let's process it recursively.
+            ProcessFile(m.group(1))
+          else:
+            # Otherwise we copy the line unchanged to the output file.
+            output_file.write(line)
+
+  ProcessFile(GMOCK_ALL_CC_SEED)
+
+
+def FuseGMockGTestAllCc(gmock_root, output_dir):
+  """Scans folder gmock_root to generate gmock-gtest-all.cc in output_dir."""
+
+  output_file = file(os.path.join(output_dir, GMOCK_GTEST_ALL_CC_OUTPUT), 'w')
+  # First, fuse gtest-all.cc into gmock-gtest-all.cc.
+  gtest.FuseGTestAllCcToFile(GetGTestRootDir(gmock_root), output_file)
+  # Next, append fused gmock-all.cc to gmock-gtest-all.cc.
+  FuseGMockAllCcToFile(gmock_root, output_file)
+  output_file.close()
+
+
+def FuseGMock(gmock_root, output_dir):
+  """Fuses gtest.h, gmock.h, and gmock-gtest-all.h."""
+
+  ValidateGMockRootDir(gmock_root)
+  ValidateOutputDir(output_dir)
+
+  gtest.FuseGTestH(GetGTestRootDir(gmock_root), output_dir)
+  FuseGMockH(gmock_root, output_dir)
+  FuseGMockGTestAllCc(gmock_root, output_dir)
+
+
+def main():
+  argc = len(sys.argv)
+  if argc == 2:
+    # fuse_gmock_files.py OUTPUT_DIR
+    FuseGMock(DEFAULT_GMOCK_ROOT_DIR, sys.argv[1])
+  elif argc == 3:
+    # fuse_gmock_files.py GMOCK_ROOT_DIR OUTPUT_DIR
+    FuseGMock(sys.argv[1], sys.argv[2])
+  else:
+    print __doc__
+    sys.exit(1)
+
+
+if __name__ == '__main__':
+  main()
diff --git a/third_party/googletest/googlemock/scripts/generator/LICENSE b/third_party/googletest/googlemock/scripts/generator/LICENSE
new file mode 100644
index 0000000..87ea063
--- /dev/null
+++ b/third_party/googletest/googlemock/scripts/generator/LICENSE
@@ -0,0 +1,203 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [2007] Neal Norwitz
+   Portions Copyright [2007] Google Inc.
+
+   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.
diff --git a/third_party/googletest/googlemock/scripts/generator/README b/third_party/googletest/googlemock/scripts/generator/README
new file mode 100644
index 0000000..d6f9597
--- /dev/null
+++ b/third_party/googletest/googlemock/scripts/generator/README
@@ -0,0 +1,35 @@
+
+The Google Mock class generator is an application that is part of cppclean.
+For more information about cppclean, see the README.cppclean file or
+visit http://code.google.com/p/cppclean/
+
+cppclean requires Python 2.3.5 or later.  If you don't have Python installed
+on your system, you will also need to install it.  You can download Python
+from:  http://www.python.org/download/releases/
+
+To use the Google Mock class generator, you need to call it
+on the command line passing the header file and class for which you want
+to generate a Google Mock class.
+
+Make sure to install the scripts somewhere in your path.  Then you can
+run the program.
+
+  gmock_gen.py header-file.h [ClassName]...
+
+If no ClassNames are specified, all classes in the file are emitted.
+
+To change the indentation from the default of 2, set INDENT in
+the environment.  For example to use an indent of 4 spaces:
+
+INDENT=4 gmock_gen.py header-file.h ClassName
+
+This version was made from SVN revision 281 in the cppclean repository.
+
+Known Limitations
+-----------------
+Not all code will be generated properly.  For example, when mocking templated
+classes, the template information is lost.  You will need to add the template
+information manually.
+
+Not all permutations of using multiple pointers/references will be rendered
+properly.  These will also have to be fixed manually.
diff --git a/third_party/googletest/googlemock/scripts/generator/README.cppclean b/third_party/googletest/googlemock/scripts/generator/README.cppclean
new file mode 100644
index 0000000..65431b6
--- /dev/null
+++ b/third_party/googletest/googlemock/scripts/generator/README.cppclean
@@ -0,0 +1,115 @@
+Goal:
+-----
+  CppClean attempts to find problems in C++ source that slow development
+  in large code bases, for example various forms of unused code.
+  Unused code can be unused functions, methods, data members, types, etc
+  to unnecessary #include directives.  Unnecessary #includes can cause
+  considerable extra compiles increasing the edit-compile-run cycle.
+
+  The project home page is:   http://code.google.com/p/cppclean/
+
+
+Features:
+---------
+ * Find and print C++ language constructs: classes, methods, functions, etc.
+ * Find classes with virtual methods, no virtual destructor, and no bases
+ * Find global/static data that are potential problems when using threads
+ * Unnecessary forward class declarations
+ * Unnecessary function declarations
+ * Undeclared function definitions
+ * (planned) Find unnecessary header files #included
+   - No direct reference to anything in the header
+   - Header is unnecessary if classes were forward declared instead
+ * (planned) Source files that reference headers not directly #included,
+   ie, files that rely on a transitive #include from another header
+ * (planned) Unused members (private, protected, & public) methods and data
+ * (planned) Store AST in a SQL database so relationships can be queried
+
+AST is Abstract Syntax Tree, a representation of parsed source code.
+http://en.wikipedia.org/wiki/Abstract_syntax_tree
+
+
+System Requirements:
+--------------------
+ * Python 2.4 or later (2.3 probably works too)
+ * Works on Windows (untested), Mac OS X, and Unix
+
+
+How to Run:
+-----------
+  For all examples, it is assumed that cppclean resides in a directory called
+  /cppclean.
+
+  To print warnings for classes with virtual methods, no virtual destructor and
+  no base classes:
+
+      /cppclean/run.sh nonvirtual_dtors.py file1.h file2.h file3.cc ...
+
+  To print all the functions defined in header file(s):
+
+      /cppclean/run.sh functions.py file1.h file2.h ...
+
+  All the commands take multiple files on the command line.  Other programs
+  include: find_warnings, headers, methods, and types.  Some other programs
+  are available, but used primarily for debugging.
+
+  run.sh is a simple wrapper that sets PYTHONPATH to /cppclean and then
+  runs the program in /cppclean/cpp/PROGRAM.py.  There is currently
+  no equivalent for Windows.  Contributions for a run.bat file
+  would be greatly appreciated.
+
+
+How to Configure:
+-----------------
+  You can add a siteheaders.py file in /cppclean/cpp to configure where
+  to look for other headers (typically -I options passed to a compiler).
+  Currently two values are supported:  _TRANSITIVE and GetIncludeDirs.
+  _TRANSITIVE should be set to a boolean value (True or False) indicating
+  whether to transitively process all header files.  The default is False.
+
+  GetIncludeDirs is a function that takes a single argument and returns
+  a sequence of directories to include.  This can be a generator or
+  return a static list.
+
+      def GetIncludeDirs(filename):
+          return ['/some/path/with/other/headers']
+
+      # Here is a more complicated example.
+      def GetIncludeDirs(filename):
+          yield '/path1'
+          yield os.path.join('/path2', os.path.dirname(filename))
+          yield '/path3'
+
+
+How to Test:
+------------
+  For all examples, it is assumed that cppclean resides in a directory called
+  /cppclean.  The tests require
+
+  cd /cppclean
+  make test
+  # To generate expected results after a change:
+  make expected
+
+
+Current Status:
+---------------
+  The parser works pretty well for header files, parsing about 99% of Google's
+  header files.  Anything which inspects structure of C++ source files should
+  work reasonably well.  Function bodies are not transformed to an AST,
+  but left as tokens.  Much work is still needed on finding unused header files
+  and storing an AST in a database.
+
+
+Non-goals:
+----------
+ * Parsing all valid C++ source
+ * Handling invalid C++ source gracefully
+ * Compiling to machine code (or anything beyond an AST)
+
+
+Contact:
+--------
+  If you used cppclean, I would love to hear about your experiences
+  cppclean@googlegroups.com.  Even if you don't use cppclean, I'd like to
+  hear from you.  :-)  (You can contact me directly at:  nnorwitz@gmail.com)
diff --git a/third_party/googletest/googlemock/scripts/generator/cpp/__init__.py b/third_party/googletest/googlemock/scripts/generator/cpp/__init__.py
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/third_party/googletest/googlemock/scripts/generator/cpp/__init__.py
diff --git a/third_party/googletest/googlemock/scripts/generator/cpp/ast.py b/third_party/googletest/googlemock/scripts/generator/cpp/ast.py
new file mode 100755
index 0000000..11cbe91
--- /dev/null
+++ b/third_party/googletest/googlemock/scripts/generator/cpp/ast.py
@@ -0,0 +1,1733 @@
+#!/usr/bin/env python
+#
+# Copyright 2007 Neal Norwitz
+# Portions Copyright 2007 Google Inc.
+#
+# 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.
+
+"""Generate an Abstract Syntax Tree (AST) for C++."""
+
+__author__ = 'nnorwitz@google.com (Neal Norwitz)'
+
+
+# TODO:
+#  * Tokens should never be exported, need to convert to Nodes
+#    (return types, parameters, etc.)
+#  * Handle static class data for templatized classes
+#  * Handle casts (both C++ and C-style)
+#  * Handle conditions and loops (if/else, switch, for, while/do)
+#
+# TODO much, much later:
+#  * Handle #define
+#  * exceptions
+
+
+try:
+    # Python 3.x
+    import builtins
+except ImportError:
+    # Python 2.x
+    import __builtin__ as builtins
+
+import sys
+import traceback
+
+from cpp import keywords
+from cpp import tokenize
+from cpp import utils
+
+
+if not hasattr(builtins, 'reversed'):
+    # Support Python 2.3 and earlier.
+    def reversed(seq):
+        for i in range(len(seq)-1, -1, -1):
+            yield seq[i]
+
+if not hasattr(builtins, 'next'):
+    # Support Python 2.5 and earlier.
+    def next(obj):
+        return obj.next()
+
+
+VISIBILITY_PUBLIC, VISIBILITY_PROTECTED, VISIBILITY_PRIVATE = range(3)
+
+FUNCTION_NONE = 0x00
+FUNCTION_CONST = 0x01
+FUNCTION_VIRTUAL = 0x02
+FUNCTION_PURE_VIRTUAL = 0x04
+FUNCTION_CTOR = 0x08
+FUNCTION_DTOR = 0x10
+FUNCTION_ATTRIBUTE = 0x20
+FUNCTION_UNKNOWN_ANNOTATION = 0x40
+FUNCTION_THROW = 0x80
+FUNCTION_OVERRIDE = 0x100
+
+"""
+These are currently unused.  Should really handle these properly at some point.
+
+TYPE_MODIFIER_INLINE   = 0x010000
+TYPE_MODIFIER_EXTERN   = 0x020000
+TYPE_MODIFIER_STATIC   = 0x040000
+TYPE_MODIFIER_CONST    = 0x080000
+TYPE_MODIFIER_REGISTER = 0x100000
+TYPE_MODIFIER_VOLATILE = 0x200000
+TYPE_MODIFIER_MUTABLE  = 0x400000
+
+TYPE_MODIFIER_MAP = {
+    'inline': TYPE_MODIFIER_INLINE,
+    'extern': TYPE_MODIFIER_EXTERN,
+    'static': TYPE_MODIFIER_STATIC,
+    'const': TYPE_MODIFIER_CONST,
+    'register': TYPE_MODIFIER_REGISTER,
+    'volatile': TYPE_MODIFIER_VOLATILE,
+    'mutable': TYPE_MODIFIER_MUTABLE,
+    }
+"""
+
+_INTERNAL_TOKEN = 'internal'
+_NAMESPACE_POP = 'ns-pop'
+
+
+# TODO(nnorwitz): use this as a singleton for templated_types, etc
+# where we don't want to create a new empty dict each time.  It is also const.
+class _NullDict(object):
+    __contains__ = lambda self: False
+    keys = values = items = iterkeys = itervalues = iteritems = lambda self: ()
+
+
+# TODO(nnorwitz): move AST nodes into a separate module.
+class Node(object):
+    """Base AST node."""
+
+    def __init__(self, start, end):
+        self.start = start
+        self.end = end
+
+    def IsDeclaration(self):
+        """Returns bool if this node is a declaration."""
+        return False
+
+    def IsDefinition(self):
+        """Returns bool if this node is a definition."""
+        return False
+
+    def IsExportable(self):
+        """Returns bool if this node exportable from a header file."""
+        return False
+
+    def Requires(self, node):
+        """Does this AST node require the definition of the node passed in?"""
+        return False
+
+    def XXX__str__(self):
+        return self._StringHelper(self.__class__.__name__, '')
+
+    def _StringHelper(self, name, suffix):
+        if not utils.DEBUG:
+            return '%s(%s)' % (name, suffix)
+        return '%s(%d, %d, %s)' % (name, self.start, self.end, suffix)
+
+    def __repr__(self):
+        return str(self)
+
+
+class Define(Node):
+    def __init__(self, start, end, name, definition):
+        Node.__init__(self, start, end)
+        self.name = name
+        self.definition = definition
+
+    def __str__(self):
+        value = '%s %s' % (self.name, self.definition)
+        return self._StringHelper(self.__class__.__name__, value)
+
+
+class Include(Node):
+    def __init__(self, start, end, filename, system):
+        Node.__init__(self, start, end)
+        self.filename = filename
+        self.system = system
+
+    def __str__(self):
+        fmt = '"%s"'
+        if self.system:
+            fmt = '<%s>'
+        return self._StringHelper(self.__class__.__name__, fmt % self.filename)
+
+
+class Goto(Node):
+    def __init__(self, start, end, label):
+        Node.__init__(self, start, end)
+        self.label = label
+
+    def __str__(self):
+        return self._StringHelper(self.__class__.__name__, str(self.label))
+
+
+class Expr(Node):
+    def __init__(self, start, end, expr):
+        Node.__init__(self, start, end)
+        self.expr = expr
+
+    def Requires(self, node):
+        # TODO(nnorwitz): impl.
+        return False
+
+    def __str__(self):
+        return self._StringHelper(self.__class__.__name__, str(self.expr))
+
+
+class Return(Expr):
+    pass
+
+
+class Delete(Expr):
+    pass
+
+
+class Friend(Expr):
+    def __init__(self, start, end, expr, namespace):
+        Expr.__init__(self, start, end, expr)
+        self.namespace = namespace[:]
+
+
+class Using(Node):
+    def __init__(self, start, end, names):
+        Node.__init__(self, start, end)
+        self.names = names
+
+    def __str__(self):
+        return self._StringHelper(self.__class__.__name__, str(self.names))
+
+
+class Parameter(Node):
+    def __init__(self, start, end, name, parameter_type, default):
+        Node.__init__(self, start, end)
+        self.name = name
+        self.type = parameter_type
+        self.default = default
+
+    def Requires(self, node):
+        # TODO(nnorwitz): handle namespaces, etc.
+        return self.type.name == node.name
+
+    def __str__(self):
+        name = str(self.type)
+        suffix = '%s %s' % (name, self.name)
+        if self.default:
+            suffix += ' = ' + ''.join([d.name for d in self.default])
+        return self._StringHelper(self.__class__.__name__, suffix)
+
+
+class _GenericDeclaration(Node):
+    def __init__(self, start, end, name, namespace):
+        Node.__init__(self, start, end)
+        self.name = name
+        self.namespace = namespace[:]
+
+    def FullName(self):
+        prefix = ''
+        if self.namespace and self.namespace[-1]:
+            prefix = '::'.join(self.namespace) + '::'
+        return prefix + self.name
+
+    def _TypeStringHelper(self, suffix):
+        if self.namespace:
+            names = [n or '<anonymous>' for n in self.namespace]
+            suffix += ' in ' + '::'.join(names)
+        return self._StringHelper(self.__class__.__name__, suffix)
+
+
+# TODO(nnorwitz): merge with Parameter in some way?
+class VariableDeclaration(_GenericDeclaration):
+    def __init__(self, start, end, name, var_type, initial_value, namespace):
+        _GenericDeclaration.__init__(self, start, end, name, namespace)
+        self.type = var_type
+        self.initial_value = initial_value
+
+    def Requires(self, node):
+        # TODO(nnorwitz): handle namespaces, etc.
+        return self.type.name == node.name
+
+    def ToString(self):
+        """Return a string that tries to reconstitute the variable decl."""
+        suffix = '%s %s' % (self.type, self.name)
+        if self.initial_value:
+            suffix += ' = ' + self.initial_value
+        return suffix
+
+    def __str__(self):
+        return self._StringHelper(self.__class__.__name__, self.ToString())
+
+
+class Typedef(_GenericDeclaration):
+    def __init__(self, start, end, name, alias, namespace):
+        _GenericDeclaration.__init__(self, start, end, name, namespace)
+        self.alias = alias
+
+    def IsDefinition(self):
+        return True
+
+    def IsExportable(self):
+        return True
+
+    def Requires(self, node):
+        # TODO(nnorwitz): handle namespaces, etc.
+        name = node.name
+        for token in self.alias:
+            if token is not None and name == token.name:
+                return True
+        return False
+
+    def __str__(self):
+        suffix = '%s, %s' % (self.name, self.alias)
+        return self._TypeStringHelper(suffix)
+
+
+class _NestedType(_GenericDeclaration):
+    def __init__(self, start, end, name, fields, namespace):
+        _GenericDeclaration.__init__(self, start, end, name, namespace)
+        self.fields = fields
+
+    def IsDefinition(self):
+        return True
+
+    def IsExportable(self):
+        return True
+
+    def __str__(self):
+        suffix = '%s, {%s}' % (self.name, self.fields)
+        return self._TypeStringHelper(suffix)
+
+
+class Union(_NestedType):
+    pass
+
+
+class Enum(_NestedType):
+    pass
+
+
+class Class(_GenericDeclaration):
+    def __init__(self, start, end, name, bases, templated_types, body, namespace):
+        _GenericDeclaration.__init__(self, start, end, name, namespace)
+        self.bases = bases
+        self.body = body
+        self.templated_types = templated_types
+
+    def IsDeclaration(self):
+        return self.bases is None and self.body is None
+
+    def IsDefinition(self):
+        return not self.IsDeclaration()
+
+    def IsExportable(self):
+        return not self.IsDeclaration()
+
+    def Requires(self, node):
+        # TODO(nnorwitz): handle namespaces, etc.
+        if self.bases:
+            for token_list in self.bases:
+                # TODO(nnorwitz): bases are tokens, do name comparision.
+                for token in token_list:
+                    if token.name == node.name:
+                        return True
+        # TODO(nnorwitz): search in body too.
+        return False
+
+    def __str__(self):
+        name = self.name
+        if self.templated_types:
+            name += '<%s>' % self.templated_types
+        suffix = '%s, %s, %s' % (name, self.bases, self.body)
+        return self._TypeStringHelper(suffix)
+
+
+class Struct(Class):
+    pass
+
+
+class Function(_GenericDeclaration):
+    def __init__(self, start, end, name, return_type, parameters,
+                 modifiers, templated_types, body, namespace):
+        _GenericDeclaration.__init__(self, start, end, name, namespace)
+        converter = TypeConverter(namespace)
+        self.return_type = converter.CreateReturnType(return_type)
+        self.parameters = converter.ToParameters(parameters)
+        self.modifiers = modifiers
+        self.body = body
+        self.templated_types = templated_types
+
+    def IsDeclaration(self):
+        return self.body is None
+
+    def IsDefinition(self):
+        return self.body is not None
+
+    def IsExportable(self):
+        if self.return_type and 'static' in self.return_type.modifiers:
+            return False
+        return None not in self.namespace
+
+    def Requires(self, node):
+        if self.parameters:
+            # TODO(nnorwitz): parameters are tokens, do name comparision.
+            for p in self.parameters:
+                if p.name == node.name:
+                    return True
+        # TODO(nnorwitz): search in body too.
+        return False
+
+    def __str__(self):
+        # TODO(nnorwitz): add templated_types.
+        suffix = ('%s %s(%s), 0x%02x, %s' %
+                  (self.return_type, self.name, self.parameters,
+                   self.modifiers, self.body))
+        return self._TypeStringHelper(suffix)
+
+
+class Method(Function):
+    def __init__(self, start, end, name, in_class, return_type, parameters,
+                 modifiers, templated_types, body, namespace):
+        Function.__init__(self, start, end, name, return_type, parameters,
+                          modifiers, templated_types, body, namespace)
+        # TODO(nnorwitz): in_class could also be a namespace which can
+        # mess up finding functions properly.
+        self.in_class = in_class
+
+
+class Type(_GenericDeclaration):
+    """Type used for any variable (eg class, primitive, struct, etc)."""
+
+    def __init__(self, start, end, name, templated_types, modifiers,
+                 reference, pointer, array):
+        """
+        Args:
+          name: str name of main type
+          templated_types: [Class (Type?)] template type info between <>
+          modifiers: [str] type modifiers (keywords) eg, const, mutable, etc.
+          reference, pointer, array: bools
+        """
+        _GenericDeclaration.__init__(self, start, end, name, [])
+        self.templated_types = templated_types
+        if not name and modifiers:
+            self.name = modifiers.pop()
+        self.modifiers = modifiers
+        self.reference = reference
+        self.pointer = pointer
+        self.array = array
+
+    def __str__(self):
+        prefix = ''
+        if self.modifiers:
+            prefix = ' '.join(self.modifiers) + ' '
+        name = str(self.name)
+        if self.templated_types:
+            name += '<%s>' % self.templated_types
+        suffix = prefix + name
+        if self.reference:
+            suffix += '&'
+        if self.pointer:
+            suffix += '*'
+        if self.array:
+            suffix += '[]'
+        return self._TypeStringHelper(suffix)
+
+    # By definition, Is* are always False.  A Type can only exist in
+    # some sort of variable declaration, parameter, or return value.
+    def IsDeclaration(self):
+        return False
+
+    def IsDefinition(self):
+        return False
+
+    def IsExportable(self):
+        return False
+
+
+class TypeConverter(object):
+
+    def __init__(self, namespace_stack):
+        self.namespace_stack = namespace_stack
+
+    def _GetTemplateEnd(self, tokens, start):
+        count = 1
+        end = start
+        while 1:
+            token = tokens[end]
+            end += 1
+            if token.name == '<':
+                count += 1
+            elif token.name == '>':
+                count -= 1
+                if count == 0:
+                    break
+        return tokens[start:end-1], end
+
+    def ToType(self, tokens):
+        """Convert [Token,...] to [Class(...), ] useful for base classes.
+        For example, code like class Foo : public Bar<x, y> { ... };
+        the "Bar<x, y>" portion gets converted to an AST.
+
+        Returns:
+          [Class(...), ...]
+        """
+        result = []
+        name_tokens = []
+        reference = pointer = array = False
+
+        def AddType(templated_types):
+            # Partition tokens into name and modifier tokens.
+            names = []
+            modifiers = []
+            for t in name_tokens:
+                if keywords.IsKeyword(t.name):
+                    modifiers.append(t.name)
+                else:
+                    names.append(t.name)
+            name = ''.join(names)
+            if name_tokens:
+                result.append(Type(name_tokens[0].start, name_tokens[-1].end,
+                                   name, templated_types, modifiers,
+                                   reference, pointer, array))
+            del name_tokens[:]
+
+        i = 0
+        end = len(tokens)
+        while i < end:
+            token = tokens[i]
+            if token.name == '<':
+                new_tokens, new_end = self._GetTemplateEnd(tokens, i+1)
+                AddType(self.ToType(new_tokens))
+                # If there is a comma after the template, we need to consume
+                # that here otherwise it becomes part of the name.
+                i = new_end
+                reference = pointer = array = False
+            elif token.name == ',':
+                AddType([])
+                reference = pointer = array = False
+            elif token.name == '*':
+                pointer = True
+            elif token.name == '&':
+                reference = True
+            elif token.name == '[':
+               pointer = True
+            elif token.name == ']':
+                pass
+            else:
+                name_tokens.append(token)
+            i += 1
+
+        if name_tokens:
+            # No '<' in the tokens, just a simple name and no template.
+            AddType([])
+        return result
+
+    def DeclarationToParts(self, parts, needs_name_removed):
+        name = None
+        default = []
+        if needs_name_removed:
+            # Handle default (initial) values properly.
+            for i, t in enumerate(parts):
+                if t.name == '=':
+                    default = parts[i+1:]
+                    name = parts[i-1].name
+                    if name == ']' and parts[i-2].name == '[':
+                        name = parts[i-3].name
+                        i -= 1
+                    parts = parts[:i-1]
+                    break
+            else:
+                if parts[-1].token_type == tokenize.NAME:
+                    name = parts.pop().name
+                else:
+                    # TODO(nnorwitz): this is a hack that happens for code like
+                    # Register(Foo<T>); where it thinks this is a function call
+                    # but it's actually a declaration.
+                    name = '???'
+        modifiers = []
+        type_name = []
+        other_tokens = []
+        templated_types = []
+        i = 0
+        end = len(parts)
+        while i < end:
+            p = parts[i]
+            if keywords.IsKeyword(p.name):
+                modifiers.append(p.name)
+            elif p.name == '<':
+                templated_tokens, new_end = self._GetTemplateEnd(parts, i+1)
+                templated_types = self.ToType(templated_tokens)
+                i = new_end - 1
+                # Don't add a spurious :: to data members being initialized.
+                next_index = i + 1
+                if next_index < end and parts[next_index].name == '::':
+                    i += 1
+            elif p.name in ('[', ']', '='):
+                # These are handled elsewhere.
+                other_tokens.append(p)
+            elif p.name not in ('*', '&', '>'):
+                # Ensure that names have a space between them.
+                if (type_name and type_name[-1].token_type == tokenize.NAME and
+                    p.token_type == tokenize.NAME):
+                    type_name.append(tokenize.Token(tokenize.SYNTAX, ' ', 0, 0))
+                type_name.append(p)
+            else:
+                other_tokens.append(p)
+            i += 1
+        type_name = ''.join([t.name for t in type_name])
+        return name, type_name, templated_types, modifiers, default, other_tokens
+
+    def ToParameters(self, tokens):
+        if not tokens:
+            return []
+
+        result = []
+        name = type_name = ''
+        type_modifiers = []
+        pointer = reference = array = False
+        first_token = None
+        default = []
+
+        def AddParameter(end):
+            if default:
+                del default[0]  # Remove flag.
+            parts = self.DeclarationToParts(type_modifiers, True)
+            (name, type_name, templated_types, modifiers,
+             unused_default, unused_other_tokens) = parts
+            parameter_type = Type(first_token.start, first_token.end,
+                                  type_name, templated_types, modifiers,
+                                  reference, pointer, array)
+            p = Parameter(first_token.start, end, name,
+                          parameter_type, default)
+            result.append(p)
+
+        template_count = 0
+        for s in tokens:
+            if not first_token:
+                first_token = s
+            if s.name == '<':
+                template_count += 1
+            elif s.name == '>':
+                template_count -= 1
+            if template_count > 0:
+                type_modifiers.append(s)
+                continue
+
+            if s.name == ',':
+                AddParameter(s.start)
+                name = type_name = ''
+                type_modifiers = []
+                pointer = reference = array = False
+                first_token = None
+                default = []
+            elif s.name == '*':
+                pointer = True
+            elif s.name == '&':
+                reference = True
+            elif s.name == '[':
+                array = True
+            elif s.name == ']':
+                pass  # Just don't add to type_modifiers.
+            elif s.name == '=':
+                # Got a default value.  Add any value (None) as a flag.
+                default.append(None)
+            elif default:
+                default.append(s)
+            else:
+                type_modifiers.append(s)
+        AddParameter(tokens[-1].end)
+        return result
+
+    def CreateReturnType(self, return_type_seq):
+        if not return_type_seq:
+            return None
+        start = return_type_seq[0].start
+        end = return_type_seq[-1].end
+        _, name, templated_types, modifiers, default, other_tokens = \
+           self.DeclarationToParts(return_type_seq, False)
+        names = [n.name for n in other_tokens]
+        reference = '&' in names
+        pointer = '*' in names
+        array = '[' in names
+        return Type(start, end, name, templated_types, modifiers,
+                    reference, pointer, array)
+
+    def GetTemplateIndices(self, names):
+        # names is a list of strings.
+        start = names.index('<')
+        end = len(names) - 1
+        while end > 0:
+            if names[end] == '>':
+                break
+            end -= 1
+        return start, end+1
+
+class AstBuilder(object):
+    def __init__(self, token_stream, filename, in_class='', visibility=None,
+                 namespace_stack=[]):
+        self.tokens = token_stream
+        self.filename = filename
+        # TODO(nnorwitz): use a better data structure (deque) for the queue.
+        # Switching directions of the "queue" improved perf by about 25%.
+        # Using a deque should be even better since we access from both sides.
+        self.token_queue = []
+        self.namespace_stack = namespace_stack[:]
+        self.in_class = in_class
+        if in_class is None:
+            self.in_class_name_only = None
+        else:
+            self.in_class_name_only = in_class.split('::')[-1]
+        self.visibility = visibility
+        self.in_function = False
+        self.current_token = None
+        # Keep the state whether we are currently handling a typedef or not.
+        self._handling_typedef = False
+
+        self.converter = TypeConverter(self.namespace_stack)
+
+    def HandleError(self, msg, token):
+        printable_queue = list(reversed(self.token_queue[-20:]))
+        sys.stderr.write('Got %s in %s @ %s %s\n' %
+                         (msg, self.filename, token, printable_queue))
+
+    def Generate(self):
+        while 1:
+            token = self._GetNextToken()
+            if not token:
+                break
+
+            # Get the next token.
+            self.current_token = token
+
+            # Dispatch on the next token type.
+            if token.token_type == _INTERNAL_TOKEN:
+                if token.name == _NAMESPACE_POP:
+                    self.namespace_stack.pop()
+                continue
+
+            try:
+                result = self._GenerateOne(token)
+                if result is not None:
+                    yield result
+            except:
+                self.HandleError('exception', token)
+                raise
+
+    def _CreateVariable(self, pos_token, name, type_name, type_modifiers,
+                        ref_pointer_name_seq, templated_types, value=None):
+        reference = '&' in ref_pointer_name_seq
+        pointer = '*' in ref_pointer_name_seq
+        array = '[' in ref_pointer_name_seq
+        var_type = Type(pos_token.start, pos_token.end, type_name,
+                        templated_types, type_modifiers,
+                        reference, pointer, array)
+        return VariableDeclaration(pos_token.start, pos_token.end,
+                                   name, var_type, value, self.namespace_stack)
+
+    def _GenerateOne(self, token):
+        if token.token_type == tokenize.NAME:
+            if (keywords.IsKeyword(token.name) and
+                not keywords.IsBuiltinType(token.name)):
+                method = getattr(self, 'handle_' + token.name)
+                return method()
+            elif token.name == self.in_class_name_only:
+                # The token name is the same as the class, must be a ctor if
+                # there is a paren.  Otherwise, it's the return type.
+                # Peek ahead to get the next token to figure out which.
+                next = self._GetNextToken()
+                self._AddBackToken(next)
+                if next.token_type == tokenize.SYNTAX and next.name == '(':
+                    return self._GetMethod([token], FUNCTION_CTOR, None, True)
+                # Fall through--handle like any other method.
+
+            # Handle data or function declaration/definition.
+            syntax = tokenize.SYNTAX
+            temp_tokens, last_token = \
+                self._GetVarTokensUpTo(syntax, '(', ';', '{', '[')
+            temp_tokens.insert(0, token)
+            if last_token.name == '(':
+                # If there is an assignment before the paren,
+                # this is an expression, not a method.
+                expr = bool([e for e in temp_tokens if e.name == '='])
+                if expr:
+                    new_temp = self._GetTokensUpTo(tokenize.SYNTAX, ';')
+                    temp_tokens.append(last_token)
+                    temp_tokens.extend(new_temp)
+                    last_token = tokenize.Token(tokenize.SYNTAX, ';', 0, 0)
+
+            if last_token.name == '[':
+                # Handle array, this isn't a method, unless it's an operator.
+                # TODO(nnorwitz): keep the size somewhere.
+                # unused_size = self._GetTokensUpTo(tokenize.SYNTAX, ']')
+                temp_tokens.append(last_token)
+                if temp_tokens[-2].name == 'operator':
+                    temp_tokens.append(self._GetNextToken())
+                else:
+                    temp_tokens2, last_token = \
+                        self._GetVarTokensUpTo(tokenize.SYNTAX, ';')
+                    temp_tokens.extend(temp_tokens2)
+
+            if last_token.name == ';':
+                # Handle data, this isn't a method.
+                parts = self.converter.DeclarationToParts(temp_tokens, True)
+                (name, type_name, templated_types, modifiers, default,
+                 unused_other_tokens) = parts
+
+                t0 = temp_tokens[0]
+                names = [t.name for t in temp_tokens]
+                if templated_types:
+                    start, end = self.converter.GetTemplateIndices(names)
+                    names = names[:start] + names[end:]
+                default = ''.join([t.name for t in default])
+                return self._CreateVariable(t0, name, type_name, modifiers,
+                                            names, templated_types, default)
+            if last_token.name == '{':
+                self._AddBackTokens(temp_tokens[1:])
+                self._AddBackToken(last_token)
+                method_name = temp_tokens[0].name
+                method = getattr(self, 'handle_' + method_name, None)
+                if not method:
+                    # Must be declaring a variable.
+                    # TODO(nnorwitz): handle the declaration.
+                    return None
+                return method()
+            return self._GetMethod(temp_tokens, 0, None, False)
+        elif token.token_type == tokenize.SYNTAX:
+            if token.name == '~' and self.in_class:
+                # Must be a dtor (probably not in method body).
+                token = self._GetNextToken()
+                # self.in_class can contain A::Name, but the dtor will only
+                # be Name.  Make sure to compare against the right value.
+                if (token.token_type == tokenize.NAME and
+                    token.name == self.in_class_name_only):
+                    return self._GetMethod([token], FUNCTION_DTOR, None, True)
+            # TODO(nnorwitz): handle a lot more syntax.
+        elif token.token_type == tokenize.PREPROCESSOR:
+            # TODO(nnorwitz): handle more preprocessor directives.
+            # token starts with a #, so remove it and strip whitespace.
+            name = token.name[1:].lstrip()
+            if name.startswith('include'):
+                # Remove "include".
+                name = name[7:].strip()
+                assert name
+                # Handle #include \<newline> "header-on-second-line.h".
+                if name.startswith('\\'):
+                    name = name[1:].strip()
+                assert name[0] in '<"', token
+                assert name[-1] in '>"', token
+                system = name[0] == '<'
+                filename = name[1:-1]
+                return Include(token.start, token.end, filename, system)
+            if name.startswith('define'):
+                # Remove "define".
+                name = name[6:].strip()
+                assert name
+                value = ''
+                for i, c in enumerate(name):
+                    if c.isspace():
+                        value = name[i:].lstrip()
+                        name = name[:i]
+                        break
+                return Define(token.start, token.end, name, value)
+            if name.startswith('if') and name[2:3].isspace():
+                condition = name[3:].strip()
+                if condition.startswith('0') or condition.startswith('(0)'):
+                    self._SkipIf0Blocks()
+        return None
+
+    def _GetTokensUpTo(self, expected_token_type, expected_token):
+        return self._GetVarTokensUpTo(expected_token_type, expected_token)[0]
+
+    def _GetVarTokensUpTo(self, expected_token_type, *expected_tokens):
+        last_token = self._GetNextToken()
+        tokens = []
+        while (last_token.token_type != expected_token_type or
+               last_token.name not in expected_tokens):
+            tokens.append(last_token)
+            last_token = self._GetNextToken()
+        return tokens, last_token
+
+    # TODO(nnorwitz): remove _IgnoreUpTo() it shouldn't be necesary.
+    def _IgnoreUpTo(self, token_type, token):
+        unused_tokens = self._GetTokensUpTo(token_type, token)
+
+    def _SkipIf0Blocks(self):
+        count = 1
+        while 1:
+            token = self._GetNextToken()
+            if token.token_type != tokenize.PREPROCESSOR:
+                continue
+
+            name = token.name[1:].lstrip()
+            if name.startswith('endif'):
+                count -= 1
+                if count == 0:
+                    break
+            elif name.startswith('if'):
+                count += 1
+
+    def _GetMatchingChar(self, open_paren, close_paren, GetNextToken=None):
+        if GetNextToken is None:
+            GetNextToken = self._GetNextToken
+        # Assumes the current token is open_paren and we will consume
+        # and return up to the close_paren.
+        count = 1
+        token = GetNextToken()
+        while 1:
+            if token.token_type == tokenize.SYNTAX:
+                if token.name == open_paren:
+                    count += 1
+                elif token.name == close_paren:
+                    count -= 1
+                    if count == 0:
+                        break
+            yield token
+            token = GetNextToken()
+        yield token
+
+    def _GetParameters(self):
+        return self._GetMatchingChar('(', ')')
+
+    def GetScope(self):
+        return self._GetMatchingChar('{', '}')
+
+    def _GetNextToken(self):
+        if self.token_queue:
+            return self.token_queue.pop()
+        return next(self.tokens)
+
+    def _AddBackToken(self, token):
+        if token.whence == tokenize.WHENCE_STREAM:
+            token.whence = tokenize.WHENCE_QUEUE
+            self.token_queue.insert(0, token)
+        else:
+            assert token.whence == tokenize.WHENCE_QUEUE, token
+            self.token_queue.append(token)
+
+    def _AddBackTokens(self, tokens):
+        if tokens:
+            if tokens[-1].whence == tokenize.WHENCE_STREAM:
+                for token in tokens:
+                    token.whence = tokenize.WHENCE_QUEUE
+                self.token_queue[:0] = reversed(tokens)
+            else:
+                assert tokens[-1].whence == tokenize.WHENCE_QUEUE, tokens
+                self.token_queue.extend(reversed(tokens))
+
+    def GetName(self, seq=None):
+        """Returns ([tokens], next_token_info)."""
+        GetNextToken = self._GetNextToken
+        if seq is not None:
+            it = iter(seq)
+            GetNextToken = lambda: next(it)
+        next_token = GetNextToken()
+        tokens = []
+        last_token_was_name = False
+        while (next_token.token_type == tokenize.NAME or
+               (next_token.token_type == tokenize.SYNTAX and
+                next_token.name in ('::', '<'))):
+            # Two NAMEs in a row means the identifier should terminate.
+            # It's probably some sort of variable declaration.
+            if last_token_was_name and next_token.token_type == tokenize.NAME:
+                break
+            last_token_was_name = next_token.token_type == tokenize.NAME
+            tokens.append(next_token)
+            # Handle templated names.
+            if next_token.name == '<':
+                tokens.extend(self._GetMatchingChar('<', '>', GetNextToken))
+                last_token_was_name = True
+            next_token = GetNextToken()
+        return tokens, next_token
+
+    def GetMethod(self, modifiers, templated_types):
+        return_type_and_name = self._GetTokensUpTo(tokenize.SYNTAX, '(')
+        assert len(return_type_and_name) >= 1
+        return self._GetMethod(return_type_and_name, modifiers, templated_types,
+                               False)
+
+    def _GetMethod(self, return_type_and_name, modifiers, templated_types,
+                   get_paren):
+        template_portion = None
+        if get_paren:
+            token = self._GetNextToken()
+            assert token.token_type == tokenize.SYNTAX, token
+            if token.name == '<':
+                # Handle templatized dtors.
+                template_portion = [token]
+                template_portion.extend(self._GetMatchingChar('<', '>'))
+                token = self._GetNextToken()
+            assert token.token_type == tokenize.SYNTAX, token
+            assert token.name == '(', token
+
+        name = return_type_and_name.pop()
+        # Handle templatized ctors.
+        if name.name == '>':
+            index = 1
+            while return_type_and_name[index].name != '<':
+                index += 1
+            template_portion = return_type_and_name[index:] + [name]
+            del return_type_and_name[index:]
+            name = return_type_and_name.pop()
+        elif name.name == ']':
+            rt = return_type_and_name
+            assert rt[-1].name == '[', return_type_and_name
+            assert rt[-2].name == 'operator', return_type_and_name
+            name_seq = return_type_and_name[-2:]
+            del return_type_and_name[-2:]
+            name = tokenize.Token(tokenize.NAME, 'operator[]',
+                                  name_seq[0].start, name.end)
+            # Get the open paren so _GetParameters() below works.
+            unused_open_paren = self._GetNextToken()
+
+        # TODO(nnorwitz): store template_portion.
+        return_type = return_type_and_name
+        indices = name
+        if return_type:
+            indices = return_type[0]
+
+        # Force ctor for templatized ctors.
+        if name.name == self.in_class and not modifiers:
+            modifiers |= FUNCTION_CTOR
+        parameters = list(self._GetParameters())
+        del parameters[-1]              # Remove trailing ')'.
+
+        # Handling operator() is especially weird.
+        if name.name == 'operator' and not parameters:
+            token = self._GetNextToken()
+            assert token.name == '(', token
+            parameters = list(self._GetParameters())
+            del parameters[-1]          # Remove trailing ')'.
+
+        token = self._GetNextToken()
+        while token.token_type == tokenize.NAME:
+            modifier_token = token
+            token = self._GetNextToken()
+            if modifier_token.name == 'const':
+                modifiers |= FUNCTION_CONST
+            elif modifier_token.name == '__attribute__':
+                # TODO(nnorwitz): handle more __attribute__ details.
+                modifiers |= FUNCTION_ATTRIBUTE
+                assert token.name == '(', token
+                # Consume everything between the (parens).
+                unused_tokens = list(self._GetMatchingChar('(', ')'))
+                token = self._GetNextToken()
+            elif modifier_token.name == 'throw':
+                modifiers |= FUNCTION_THROW
+                assert token.name == '(', token
+                # Consume everything between the (parens).
+                unused_tokens = list(self._GetMatchingChar('(', ')'))
+                token = self._GetNextToken()
+            elif modifier_token.name == 'override':
+                modifiers |= FUNCTION_OVERRIDE
+            elif modifier_token.name == modifier_token.name.upper():
+                # HACK(nnorwitz):  assume that all upper-case names
+                # are some macro we aren't expanding.
+                modifiers |= FUNCTION_UNKNOWN_ANNOTATION
+            else:
+                self.HandleError('unexpected token', modifier_token)
+
+        assert token.token_type == tokenize.SYNTAX, token
+        # Handle ctor initializers.
+        if token.name == ':':
+            # TODO(nnorwitz): anything else to handle for initializer list?
+            while token.name != ';' and token.name != '{':
+                token = self._GetNextToken()
+
+        # Handle pointer to functions that are really data but look
+        # like method declarations.
+        if token.name == '(':
+            if parameters[0].name == '*':
+                # name contains the return type.
+                name = parameters.pop()
+                # parameters contains the name of the data.
+                modifiers = [p.name for p in parameters]
+                # Already at the ( to open the parameter list.
+                function_parameters = list(self._GetMatchingChar('(', ')'))
+                del function_parameters[-1]  # Remove trailing ')'.
+                # TODO(nnorwitz): store the function_parameters.
+                token = self._GetNextToken()
+                assert token.token_type == tokenize.SYNTAX, token
+                assert token.name == ';', token
+                return self._CreateVariable(indices, name.name, indices.name,
+                                            modifiers, '', None)
+            # At this point, we got something like:
+            #  return_type (type::*name_)(params);
+            # This is a data member called name_ that is a function pointer.
+            # With this code: void (sq_type::*field_)(string&);
+            # We get: name=void return_type=[] parameters=sq_type ... field_
+            # TODO(nnorwitz): is return_type always empty?
+            # TODO(nnorwitz): this isn't even close to being correct.
+            # Just put in something so we don't crash and can move on.
+            real_name = parameters[-1]
+            modifiers = [p.name for p in self._GetParameters()]
+            del modifiers[-1]           # Remove trailing ')'.
+            return self._CreateVariable(indices, real_name.name, indices.name,
+                                        modifiers, '', None)
+
+        if token.name == '{':
+            body = list(self.GetScope())
+            del body[-1]                # Remove trailing '}'.
+        else:
+            body = None
+            if token.name == '=':
+                token = self._GetNextToken()
+
+                if token.name == 'default' or token.name == 'delete':
+                    # Ignore explicitly defaulted and deleted special members
+                    # in C++11.
+                    token = self._GetNextToken()
+                else:
+                    # Handle pure-virtual declarations.
+                    assert token.token_type == tokenize.CONSTANT, token
+                    assert token.name == '0', token
+                    modifiers |= FUNCTION_PURE_VIRTUAL
+                    token = self._GetNextToken()
+
+            if token.name == '[':
+                # TODO(nnorwitz): store tokens and improve parsing.
+                # template <typename T, size_t N> char (&ASH(T (&seq)[N]))[N];
+                tokens = list(self._GetMatchingChar('[', ']'))
+                token = self._GetNextToken()
+
+            assert token.name == ';', (token, return_type_and_name, parameters)
+
+        # Looks like we got a method, not a function.
+        if len(return_type) > 2 and return_type[-1].name == '::':
+            return_type, in_class = \
+                         self._GetReturnTypeAndClassName(return_type)
+            return Method(indices.start, indices.end, name.name, in_class,
+                          return_type, parameters, modifiers, templated_types,
+                          body, self.namespace_stack)
+        return Function(indices.start, indices.end, name.name, return_type,
+                        parameters, modifiers, templated_types, body,
+                        self.namespace_stack)
+
+    def _GetReturnTypeAndClassName(self, token_seq):
+        # Splitting the return type from the class name in a method
+        # can be tricky.  For example, Return::Type::Is::Hard::To::Find().
+        # Where is the return type and where is the class name?
+        # The heuristic used is to pull the last name as the class name.
+        # This includes all the templated type info.
+        # TODO(nnorwitz): if there is only One name like in the
+        # example above, punt and assume the last bit is the class name.
+
+        # Ignore a :: prefix, if exists so we can find the first real name.
+        i = 0
+        if token_seq[0].name == '::':
+            i = 1
+        # Ignore a :: suffix, if exists.
+        end = len(token_seq) - 1
+        if token_seq[end-1].name == '::':
+            end -= 1
+
+        # Make a copy of the sequence so we can append a sentinel
+        # value. This is required for GetName will has to have some
+        # terminating condition beyond the last name.
+        seq_copy = token_seq[i:end]
+        seq_copy.append(tokenize.Token(tokenize.SYNTAX, '', 0, 0))
+        names = []
+        while i < end:
+            # Iterate through the sequence parsing out each name.
+            new_name, next = self.GetName(seq_copy[i:])
+            assert new_name, 'Got empty new_name, next=%s' % next
+            # We got a pointer or ref.  Add it to the name.
+            if next and next.token_type == tokenize.SYNTAX:
+                new_name.append(next)
+            names.append(new_name)
+            i += len(new_name)
+
+        # Now that we have the names, it's time to undo what we did.
+
+        # Remove the sentinel value.
+        names[-1].pop()
+        # Flatten the token sequence for the return type.
+        return_type = [e for seq in names[:-1] for e in seq]
+        # The class name is the last name.
+        class_name = names[-1]
+        return return_type, class_name
+
+    def handle_bool(self):
+        pass
+
+    def handle_char(self):
+        pass
+
+    def handle_int(self):
+        pass
+
+    def handle_long(self):
+        pass
+
+    def handle_short(self):
+        pass
+
+    def handle_double(self):
+        pass
+
+    def handle_float(self):
+        pass
+
+    def handle_void(self):
+        pass
+
+    def handle_wchar_t(self):
+        pass
+
+    def handle_unsigned(self):
+        pass
+
+    def handle_signed(self):
+        pass
+
+    def _GetNestedType(self, ctor):
+        name = None
+        name_tokens, token = self.GetName()
+        if name_tokens:
+            name = ''.join([t.name for t in name_tokens])
+
+        # Handle forward declarations.
+        if token.token_type == tokenize.SYNTAX and token.name == ';':
+            return ctor(token.start, token.end, name, None,
+                        self.namespace_stack)
+
+        if token.token_type == tokenize.NAME and self._handling_typedef:
+            self._AddBackToken(token)
+            return ctor(token.start, token.end, name, None,
+                        self.namespace_stack)
+
+        # Must be the type declaration.
+        fields = list(self._GetMatchingChar('{', '}'))
+        del fields[-1]                  # Remove trailing '}'.
+        if token.token_type == tokenize.SYNTAX and token.name == '{':
+            next = self._GetNextToken()
+            new_type = ctor(token.start, token.end, name, fields,
+                            self.namespace_stack)
+            # A name means this is an anonymous type and the name
+            # is the variable declaration.
+            if next.token_type != tokenize.NAME:
+                return new_type
+            name = new_type
+            token = next
+
+        # Must be variable declaration using the type prefixed with keyword.
+        assert token.token_type == tokenize.NAME, token
+        return self._CreateVariable(token, token.name, name, [], '', None)
+
+    def handle_struct(self):
+        # Special case the handling typedef/aliasing of structs here.
+        # It would be a pain to handle in the class code.
+        name_tokens, var_token = self.GetName()
+        if name_tokens:
+            next_token = self._GetNextToken()
+            is_syntax = (var_token.token_type == tokenize.SYNTAX and
+                         var_token.name[0] in '*&')
+            is_variable = (var_token.token_type == tokenize.NAME and
+                           next_token.name == ';')
+            variable = var_token
+            if is_syntax and not is_variable:
+                variable = next_token
+                temp = self._GetNextToken()
+                if temp.token_type == tokenize.SYNTAX and temp.name == '(':
+                    # Handle methods declared to return a struct.
+                    t0 = name_tokens[0]
+                    struct = tokenize.Token(tokenize.NAME, 'struct',
+                                            t0.start-7, t0.start-2)
+                    type_and_name = [struct]
+                    type_and_name.extend(name_tokens)
+                    type_and_name.extend((var_token, next_token))
+                    return self._GetMethod(type_and_name, 0, None, False)
+                assert temp.name == ';', (temp, name_tokens, var_token)
+            if is_syntax or (is_variable and not self._handling_typedef):
+                modifiers = ['struct']
+                type_name = ''.join([t.name for t in name_tokens])
+                position = name_tokens[0]
+                return self._CreateVariable(position, variable.name, type_name,
+                                            modifiers, var_token.name, None)
+            name_tokens.extend((var_token, next_token))
+            self._AddBackTokens(name_tokens)
+        else:
+            self._AddBackToken(var_token)
+        return self._GetClass(Struct, VISIBILITY_PUBLIC, None)
+
+    def handle_union(self):
+        return self._GetNestedType(Union)
+
+    def handle_enum(self):
+        return self._GetNestedType(Enum)
+
+    def handle_auto(self):
+        # TODO(nnorwitz): warn about using auto?  Probably not since it
+        # will be reclaimed and useful for C++0x.
+        pass
+
+    def handle_register(self):
+        pass
+
+    def handle_const(self):
+        pass
+
+    def handle_inline(self):
+        pass
+
+    def handle_extern(self):
+        pass
+
+    def handle_static(self):
+        pass
+
+    def handle_virtual(self):
+        # What follows must be a method.
+        token = token2 = self._GetNextToken()
+        if token.name == 'inline':
+            # HACK(nnorwitz): handle inline dtors by ignoring 'inline'.
+            token2 = self._GetNextToken()
+        if token2.token_type == tokenize.SYNTAX and token2.name == '~':
+            return self.GetMethod(FUNCTION_VIRTUAL + FUNCTION_DTOR, None)
+        assert token.token_type == tokenize.NAME or token.name == '::', token
+        return_type_and_name = self._GetTokensUpTo(tokenize.SYNTAX, '(')  # )
+        return_type_and_name.insert(0, token)
+        if token2 is not token:
+            return_type_and_name.insert(1, token2)
+        return self._GetMethod(return_type_and_name, FUNCTION_VIRTUAL,
+                               None, False)
+
+    def handle_volatile(self):
+        pass
+
+    def handle_mutable(self):
+        pass
+
+    def handle_public(self):
+        assert self.in_class
+        self.visibility = VISIBILITY_PUBLIC
+
+    def handle_protected(self):
+        assert self.in_class
+        self.visibility = VISIBILITY_PROTECTED
+
+    def handle_private(self):
+        assert self.in_class
+        self.visibility = VISIBILITY_PRIVATE
+
+    def handle_friend(self):
+        tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';')
+        assert tokens
+        t0 = tokens[0]
+        return Friend(t0.start, t0.end, tokens, self.namespace_stack)
+
+    def handle_static_cast(self):
+        pass
+
+    def handle_const_cast(self):
+        pass
+
+    def handle_dynamic_cast(self):
+        pass
+
+    def handle_reinterpret_cast(self):
+        pass
+
+    def handle_new(self):
+        pass
+
+    def handle_delete(self):
+        tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';')
+        assert tokens
+        return Delete(tokens[0].start, tokens[0].end, tokens)
+
+    def handle_typedef(self):
+        token = self._GetNextToken()
+        if (token.token_type == tokenize.NAME and
+            keywords.IsKeyword(token.name)):
+            # Token must be struct/enum/union/class.
+            method = getattr(self, 'handle_' + token.name)
+            self._handling_typedef = True
+            tokens = [method()]
+            self._handling_typedef = False
+        else:
+            tokens = [token]
+
+        # Get the remainder of the typedef up to the semi-colon.
+        tokens.extend(self._GetTokensUpTo(tokenize.SYNTAX, ';'))
+
+        # TODO(nnorwitz): clean all this up.
+        assert tokens
+        name = tokens.pop()
+        indices = name
+        if tokens:
+            indices = tokens[0]
+        if not indices:
+            indices = token
+        if name.name == ')':
+            # HACK(nnorwitz): Handle pointers to functions "properly".
+            if (len(tokens) >= 4 and
+                tokens[1].name == '(' and tokens[2].name == '*'):
+                tokens.append(name)
+                name = tokens[3]
+        elif name.name == ']':
+            # HACK(nnorwitz): Handle arrays properly.
+            if len(tokens) >= 2:
+                tokens.append(name)
+                name = tokens[1]
+        new_type = tokens
+        if tokens and isinstance(tokens[0], tokenize.Token):
+            new_type = self.converter.ToType(tokens)[0]
+        return Typedef(indices.start, indices.end, name.name,
+                       new_type, self.namespace_stack)
+
+    def handle_typeid(self):
+        pass  # Not needed yet.
+
+    def handle_typename(self):
+        pass  # Not needed yet.
+
+    def _GetTemplatedTypes(self):
+        result = {}
+        tokens = list(self._GetMatchingChar('<', '>'))
+        len_tokens = len(tokens) - 1    # Ignore trailing '>'.
+        i = 0
+        while i < len_tokens:
+            key = tokens[i].name
+            i += 1
+            if keywords.IsKeyword(key) or key == ',':
+                continue
+            type_name = default = None
+            if i < len_tokens:
+                i += 1
+                if tokens[i-1].name == '=':
+                    assert i < len_tokens, '%s %s' % (i, tokens)
+                    default, unused_next_token = self.GetName(tokens[i:])
+                    i += len(default)
+                else:
+                    if tokens[i-1].name != ',':
+                        # We got something like: Type variable.
+                        # Re-adjust the key (variable) and type_name (Type).
+                        key = tokens[i-1].name
+                        type_name = tokens[i-2]
+
+            result[key] = (type_name, default)
+        return result
+
+    def handle_template(self):
+        token = self._GetNextToken()
+        assert token.token_type == tokenize.SYNTAX, token
+        assert token.name == '<', token
+        templated_types = self._GetTemplatedTypes()
+        # TODO(nnorwitz): for now, just ignore the template params.
+        token = self._GetNextToken()
+        if token.token_type == tokenize.NAME:
+            if token.name == 'class':
+                return self._GetClass(Class, VISIBILITY_PRIVATE, templated_types)
+            elif token.name == 'struct':
+                return self._GetClass(Struct, VISIBILITY_PUBLIC, templated_types)
+            elif token.name == 'friend':
+                return self.handle_friend()
+        self._AddBackToken(token)
+        tokens, last = self._GetVarTokensUpTo(tokenize.SYNTAX, '(', ';')
+        tokens.append(last)
+        self._AddBackTokens(tokens)
+        if last.name == '(':
+            return self.GetMethod(FUNCTION_NONE, templated_types)
+        # Must be a variable definition.
+        return None
+
+    def handle_true(self):
+        pass  # Nothing to do.
+
+    def handle_false(self):
+        pass  # Nothing to do.
+
+    def handle_asm(self):
+        pass  # Not needed yet.
+
+    def handle_class(self):
+        return self._GetClass(Class, VISIBILITY_PRIVATE, None)
+
+    def _GetBases(self):
+        # Get base classes.
+        bases = []
+        while 1:
+            token = self._GetNextToken()
+            assert token.token_type == tokenize.NAME, token
+            # TODO(nnorwitz): store kind of inheritance...maybe.
+            if token.name not in ('public', 'protected', 'private'):
+                # If inheritance type is not specified, it is private.
+                # Just put the token back so we can form a name.
+                # TODO(nnorwitz): it would be good to warn about this.
+                self._AddBackToken(token)
+            else:
+                # Check for virtual inheritance.
+                token = self._GetNextToken()
+                if token.name != 'virtual':
+                    self._AddBackToken(token)
+                else:
+                    # TODO(nnorwitz): store that we got virtual for this base.
+                    pass
+            base, next_token = self.GetName()
+            bases_ast = self.converter.ToType(base)
+            assert len(bases_ast) == 1, bases_ast
+            bases.append(bases_ast[0])
+            assert next_token.token_type == tokenize.SYNTAX, next_token
+            if next_token.name == '{':
+                token = next_token
+                break
+            # Support multiple inheritance.
+            assert next_token.name == ',', next_token
+        return bases, token
+
+    def _GetClass(self, class_type, visibility, templated_types):
+        class_name = None
+        class_token = self._GetNextToken()
+        if class_token.token_type != tokenize.NAME:
+            assert class_token.token_type == tokenize.SYNTAX, class_token
+            token = class_token
+        else:
+            # Skip any macro (e.g. storage class specifiers) after the
+            # 'class' keyword.
+            next_token = self._GetNextToken()
+            if next_token.token_type == tokenize.NAME:
+                self._AddBackToken(next_token)
+            else:
+                self._AddBackTokens([class_token, next_token])
+            name_tokens, token = self.GetName()
+            class_name = ''.join([t.name for t in name_tokens])
+        bases = None
+        if token.token_type == tokenize.SYNTAX:
+            if token.name == ';':
+                # Forward declaration.
+                return class_type(class_token.start, class_token.end,
+                                  class_name, None, templated_types, None,
+                                  self.namespace_stack)
+            if token.name in '*&':
+                # Inline forward declaration.  Could be method or data.
+                name_token = self._GetNextToken()
+                next_token = self._GetNextToken()
+                if next_token.name == ';':
+                    # Handle data
+                    modifiers = ['class']
+                    return self._CreateVariable(class_token, name_token.name,
+                                                class_name,
+                                                modifiers, token.name, None)
+                else:
+                    # Assume this is a method.
+                    tokens = (class_token, token, name_token, next_token)
+                    self._AddBackTokens(tokens)
+                    return self.GetMethod(FUNCTION_NONE, None)
+            if token.name == ':':
+                bases, token = self._GetBases()
+
+        body = None
+        if token.token_type == tokenize.SYNTAX and token.name == '{':
+            assert token.token_type == tokenize.SYNTAX, token
+            assert token.name == '{', token
+
+            ast = AstBuilder(self.GetScope(), self.filename, class_name,
+                             visibility, self.namespace_stack)
+            body = list(ast.Generate())
+
+            if not self._handling_typedef:
+                token = self._GetNextToken()
+                if token.token_type != tokenize.NAME:
+                    assert token.token_type == tokenize.SYNTAX, token
+                    assert token.name == ';', token
+                else:
+                    new_class = class_type(class_token.start, class_token.end,
+                                           class_name, bases, None,
+                                           body, self.namespace_stack)
+
+                    modifiers = []
+                    return self._CreateVariable(class_token,
+                                                token.name, new_class,
+                                                modifiers, token.name, None)
+        else:
+            if not self._handling_typedef:
+                self.HandleError('non-typedef token', token)
+            self._AddBackToken(token)
+
+        return class_type(class_token.start, class_token.end, class_name,
+                          bases, templated_types, body, self.namespace_stack)
+
+    def handle_namespace(self):
+        token = self._GetNextToken()
+        # Support anonymous namespaces.
+        name = None
+        if token.token_type == tokenize.NAME:
+            name = token.name
+            token = self._GetNextToken()
+        self.namespace_stack.append(name)
+        assert token.token_type == tokenize.SYNTAX, token
+        # Create an internal token that denotes when the namespace is complete.
+        internal_token = tokenize.Token(_INTERNAL_TOKEN, _NAMESPACE_POP,
+                                        None, None)
+        internal_token.whence = token.whence
+        if token.name == '=':
+            # TODO(nnorwitz): handle aliasing namespaces.
+            name, next_token = self.GetName()
+            assert next_token.name == ';', next_token
+            self._AddBackToken(internal_token)
+        else:
+            assert token.name == '{', token
+            tokens = list(self.GetScope())
+            # Replace the trailing } with the internal namespace pop token.
+            tokens[-1] = internal_token
+            # Handle namespace with nothing in it.
+            self._AddBackTokens(tokens)
+        return None
+
+    def handle_using(self):
+        tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';')
+        assert tokens
+        return Using(tokens[0].start, tokens[0].end, tokens)
+
+    def handle_explicit(self):
+        assert self.in_class
+        # Nothing much to do.
+        # TODO(nnorwitz): maybe verify the method name == class name.
+        # This must be a ctor.
+        return self.GetMethod(FUNCTION_CTOR, None)
+
+    def handle_this(self):
+        pass  # Nothing to do.
+
+    def handle_operator(self):
+        # Pull off the next token(s?) and make that part of the method name.
+        pass
+
+    def handle_sizeof(self):
+        pass
+
+    def handle_case(self):
+        pass
+
+    def handle_switch(self):
+        pass
+
+    def handle_default(self):
+        token = self._GetNextToken()
+        assert token.token_type == tokenize.SYNTAX
+        assert token.name == ':'
+
+    def handle_if(self):
+        pass
+
+    def handle_else(self):
+        pass
+
+    def handle_return(self):
+        tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';')
+        if not tokens:
+            return Return(self.current_token.start, self.current_token.end, None)
+        return Return(tokens[0].start, tokens[0].end, tokens)
+
+    def handle_goto(self):
+        tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';')
+        assert len(tokens) == 1, str(tokens)
+        return Goto(tokens[0].start, tokens[0].end, tokens[0].name)
+
+    def handle_try(self):
+        pass  # Not needed yet.
+
+    def handle_catch(self):
+        pass  # Not needed yet.
+
+    def handle_throw(self):
+        pass  # Not needed yet.
+
+    def handle_while(self):
+        pass
+
+    def handle_do(self):
+        pass
+
+    def handle_for(self):
+        pass
+
+    def handle_break(self):
+        self._IgnoreUpTo(tokenize.SYNTAX, ';')
+
+    def handle_continue(self):
+        self._IgnoreUpTo(tokenize.SYNTAX, ';')
+
+
+def BuilderFromSource(source, filename):
+    """Utility method that returns an AstBuilder from source code.
+
+    Args:
+      source: 'C++ source code'
+      filename: 'file1'
+
+    Returns:
+      AstBuilder
+    """
+    return AstBuilder(tokenize.GetTokens(source), filename)
+
+
+def PrintIndentifiers(filename, should_print):
+    """Prints all identifiers for a C++ source file.
+
+    Args:
+      filename: 'file1'
+      should_print: predicate with signature: bool Function(token)
+    """
+    source = utils.ReadFile(filename, False)
+    if source is None:
+        sys.stderr.write('Unable to find: %s\n' % filename)
+        return
+
+    #print('Processing %s' % actual_filename)
+    builder = BuilderFromSource(source, filename)
+    try:
+        for node in builder.Generate():
+            if should_print(node):
+                print(node.name)
+    except KeyboardInterrupt:
+        return
+    except:
+        pass
+
+
+def PrintAllIndentifiers(filenames, should_print):
+    """Prints all identifiers for each C++ source file in filenames.
+
+    Args:
+      filenames: ['file1', 'file2', ...]
+      should_print: predicate with signature: bool Function(token)
+    """
+    for path in filenames:
+        PrintIndentifiers(path, should_print)
+
+
+def main(argv):
+    for filename in argv[1:]:
+        source = utils.ReadFile(filename)
+        if source is None:
+            continue
+
+        print('Processing %s' % filename)
+        builder = BuilderFromSource(source, filename)
+        try:
+            entire_ast = filter(None, builder.Generate())
+        except KeyboardInterrupt:
+            return
+        except:
+            # Already printed a warning, print the traceback and continue.
+            traceback.print_exc()
+        else:
+            if utils.DEBUG:
+                for ast in entire_ast:
+                    print(ast)
+
+
+if __name__ == '__main__':
+    main(sys.argv)
diff --git a/third_party/googletest/googlemock/scripts/generator/cpp/gmock_class.py b/third_party/googletest/googlemock/scripts/generator/cpp/gmock_class.py
new file mode 100755
index 0000000..f9966cb
--- /dev/null
+++ b/third_party/googletest/googlemock/scripts/generator/cpp/gmock_class.py
@@ -0,0 +1,227 @@
+#!/usr/bin/env python
+#
+# Copyright 2008 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.
+
+"""Generate Google Mock classes from base classes.
+
+This program will read in a C++ source file and output the Google Mock
+classes for the specified classes.  If no class is specified, all
+classes in the source file are emitted.
+
+Usage:
+  gmock_class.py header-file.h [ClassName]...
+
+Output is sent to stdout.
+"""
+
+__author__ = 'nnorwitz@google.com (Neal Norwitz)'
+
+
+import os
+import re
+import sys
+
+from cpp import ast
+from cpp import utils
+
+# Preserve compatibility with Python 2.3.
+try:
+  _dummy = set
+except NameError:
+  import sets
+  set = sets.Set
+
+_VERSION = (1, 0, 1)  # The version of this script.
+# How many spaces to indent.  Can set me with the INDENT environment variable.
+_INDENT = 2
+
+
+def _GenerateMethods(output_lines, source, class_node):
+  function_type = (ast.FUNCTION_VIRTUAL | ast.FUNCTION_PURE_VIRTUAL |
+                   ast.FUNCTION_OVERRIDE)
+  ctor_or_dtor = ast.FUNCTION_CTOR | ast.FUNCTION_DTOR
+  indent = ' ' * _INDENT
+
+  for node in class_node.body:
+    # We only care about virtual functions.
+    if (isinstance(node, ast.Function) and
+        node.modifiers & function_type and
+        not node.modifiers & ctor_or_dtor):
+      # Pick out all the elements we need from the original function.
+      const = ''
+      if node.modifiers & ast.FUNCTION_CONST:
+        const = 'CONST_'
+      return_type = 'void'
+      if node.return_type:
+        # Add modifiers like 'const'.
+        modifiers = ''
+        if node.return_type.modifiers:
+          modifiers = ' '.join(node.return_type.modifiers) + ' '
+        return_type = modifiers + node.return_type.name
+        template_args = [arg.name for arg in node.return_type.templated_types]
+        if template_args:
+          return_type += '<' + ', '.join(template_args) + '>'
+          if len(template_args) > 1:
+            for line in [
+                '// The following line won\'t really compile, as the return',
+                '// type has multiple template arguments.  To fix it, use a',
+                '// typedef for the return type.']:
+              output_lines.append(indent + line)
+        if node.return_type.pointer:
+          return_type += '*'
+        if node.return_type.reference:
+          return_type += '&'
+        num_parameters = len(node.parameters)
+        if len(node.parameters) == 1:
+          first_param = node.parameters[0]
+          if source[first_param.start:first_param.end].strip() == 'void':
+            # We must treat T(void) as a function with no parameters.
+            num_parameters = 0
+      tmpl = ''
+      if class_node.templated_types:
+        tmpl = '_T'
+      mock_method_macro = 'MOCK_%sMETHOD%d%s' % (const, num_parameters, tmpl)
+
+      args = ''
+      if node.parameters:
+        # Due to the parser limitations, it is impossible to keep comments
+        # while stripping the default parameters.  When defaults are
+        # present, we choose to strip them and comments (and produce
+        # compilable code).
+        # TODO(nnorwitz@google.com): Investigate whether it is possible to
+        # preserve parameter name when reconstructing parameter text from
+        # the AST.
+        if len([param for param in node.parameters if param.default]) > 0:
+          args = ', '.join(param.type.name for param in node.parameters)
+        else:
+          # Get the full text of the parameters from the start
+          # of the first parameter to the end of the last parameter.
+          start = node.parameters[0].start
+          end = node.parameters[-1].end
+          # Remove // comments.
+          args_strings = re.sub(r'//.*', '', source[start:end])
+          # Condense multiple spaces and eliminate newlines putting the
+          # parameters together on a single line.  Ensure there is a
+          # space in an argument which is split by a newline without
+          # intervening whitespace, e.g.: int\nBar
+          args = re.sub('  +', ' ', args_strings.replace('\n', ' '))
+
+      # Create the mock method definition.
+      output_lines.extend(['%s%s(%s,' % (indent, mock_method_macro, node.name),
+                           '%s%s(%s));' % (indent*3, return_type, args)])
+
+
+def _GenerateMocks(filename, source, ast_list, desired_class_names):
+  processed_class_names = set()
+  lines = []
+  for node in ast_list:
+    if (isinstance(node, ast.Class) and node.body and
+        # desired_class_names being None means that all classes are selected.
+        (not desired_class_names or node.name in desired_class_names)):
+      class_name = node.name
+      parent_name = class_name
+      processed_class_names.add(class_name)
+      class_node = node
+      # Add namespace before the class.
+      if class_node.namespace:
+        lines.extend(['namespace %s {' % n for n in class_node.namespace])  # }
+        lines.append('')
+
+      # Add template args for templated classes.
+      if class_node.templated_types:
+        # TODO(paulchang): The AST doesn't preserve template argument order,
+        # so we have to make up names here.
+        # TODO(paulchang): Handle non-type template arguments (e.g.
+        # template<typename T, int N>).
+        template_arg_count = len(class_node.templated_types.keys())
+        template_args = ['T%d' % n for n in range(template_arg_count)]
+        template_decls = ['typename ' + arg for arg in template_args]
+        lines.append('template <' + ', '.join(template_decls) + '>')
+        parent_name += '<' + ', '.join(template_args) + '>'
+
+      # Add the class prolog.
+      lines.append('class Mock%s : public %s {'  # }
+                   % (class_name, parent_name))
+      lines.append('%spublic:' % (' ' * (_INDENT // 2)))
+
+      # Add all the methods.
+      _GenerateMethods(lines, source, class_node)
+
+      # Close the class.
+      if lines:
+        # If there are no virtual methods, no need for a public label.
+        if len(lines) == 2:
+          del lines[-1]
+
+        # Only close the class if there really is a class.
+        lines.append('};')
+        lines.append('')  # Add an extra newline.
+
+      # Close the namespace.
+      if class_node.namespace:
+        for i in range(len(class_node.namespace)-1, -1, -1):
+          lines.append('}  // namespace %s' % class_node.namespace[i])
+        lines.append('')  # Add an extra newline.
+
+  if desired_class_names:
+    missing_class_name_list = list(desired_class_names - processed_class_names)
+    if missing_class_name_list:
+      missing_class_name_list.sort()
+      sys.stderr.write('Class(es) not found in %s: %s\n' %
+                       (filename, ', '.join(missing_class_name_list)))
+  elif not processed_class_names:
+    sys.stderr.write('No class found in %s\n' % filename)
+
+  return lines
+
+
+def main(argv=sys.argv):
+  if len(argv) < 2:
+    sys.stderr.write('Google Mock Class Generator v%s\n\n' %
+                     '.'.join(map(str, _VERSION)))
+    sys.stderr.write(__doc__)
+    return 1
+
+  global _INDENT
+  try:
+    _INDENT = int(os.environ['INDENT'])
+  except KeyError:
+    pass
+  except:
+    sys.stderr.write('Unable to use indent of %s\n' % os.environ.get('INDENT'))
+
+  filename = argv[1]
+  desired_class_names = None  # None means all classes in the source file.
+  if len(argv) >= 3:
+    desired_class_names = set(argv[2:])
+  source = utils.ReadFile(filename)
+  if source is None:
+    return 1
+
+  builder = ast.BuilderFromSource(source, filename)
+  try:
+    entire_ast = filter(None, builder.Generate())
+  except KeyboardInterrupt:
+    return
+  except:
+    # An error message was already printed since we couldn't parse.
+    sys.exit(1)
+  else:
+    lines = _GenerateMocks(filename, source, entire_ast, desired_class_names)
+    sys.stdout.write('\n'.join(lines))
+
+
+if __name__ == '__main__':
+  main(sys.argv)
diff --git a/third_party/googletest/googlemock/scripts/generator/cpp/gmock_class_test.py b/third_party/googletest/googlemock/scripts/generator/cpp/gmock_class_test.py
new file mode 100755
index 0000000..018f90a
--- /dev/null
+++ b/third_party/googletest/googlemock/scripts/generator/cpp/gmock_class_test.py
@@ -0,0 +1,448 @@
+#!/usr/bin/env python
+#
+# Copyright 2009 Neal Norwitz All Rights Reserved.
+# Portions Copyright 2009 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.
+
+"""Tests for gmock.scripts.generator.cpp.gmock_class."""
+
+__author__ = 'nnorwitz@google.com (Neal Norwitz)'
+
+
+import os
+import sys
+import unittest
+
+# Allow the cpp imports below to work when run as a standalone script.
+sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
+
+from cpp import ast
+from cpp import gmock_class
+
+
+class TestCase(unittest.TestCase):
+  """Helper class that adds assert methods."""
+
+  def StripLeadingWhitespace(self, lines):
+    """Strip leading whitespace in each line in 'lines'."""
+    return '\n'.join([s.lstrip() for s in lines.split('\n')])
+
+  def assertEqualIgnoreLeadingWhitespace(self, expected_lines, lines):
+    """Specialized assert that ignores the indent level."""
+    self.assertEqual(expected_lines, self.StripLeadingWhitespace(lines))
+
+
+class GenerateMethodsTest(TestCase):
+
+  def GenerateMethodSource(self, cpp_source):
+    """Convert C++ source to Google Mock output source lines."""
+    method_source_lines = []
+    # <test> is a pseudo-filename, it is not read or written.
+    builder = ast.BuilderFromSource(cpp_source, '<test>')
+    ast_list = list(builder.Generate())
+    gmock_class._GenerateMethods(method_source_lines, cpp_source, ast_list[0])
+    return '\n'.join(method_source_lines)
+
+  def testSimpleMethod(self):
+    source = """
+class Foo {
+ public:
+  virtual int Bar();
+};
+"""
+    self.assertEqualIgnoreLeadingWhitespace(
+        'MOCK_METHOD0(Bar,\nint());',
+        self.GenerateMethodSource(source))
+
+  def testSimpleConstructorsAndDestructor(self):
+    source = """
+class Foo {
+ public:
+  Foo();
+  Foo(int x);
+  Foo(const Foo& f);
+  Foo(Foo&& f);
+  ~Foo();
+  virtual int Bar() = 0;
+};
+"""
+    # The constructors and destructor should be ignored.
+    self.assertEqualIgnoreLeadingWhitespace(
+        'MOCK_METHOD0(Bar,\nint());',
+        self.GenerateMethodSource(source))
+
+  def testVirtualDestructor(self):
+    source = """
+class Foo {
+ public:
+  virtual ~Foo();
+  virtual int Bar() = 0;
+};
+"""
+    # The destructor should be ignored.
+    self.assertEqualIgnoreLeadingWhitespace(
+        'MOCK_METHOD0(Bar,\nint());',
+        self.GenerateMethodSource(source))
+
+  def testExplicitlyDefaultedConstructorsAndDestructor(self):
+    source = """
+class Foo {
+ public:
+  Foo() = default;
+  Foo(const Foo& f) = default;
+  Foo(Foo&& f) = default;
+  ~Foo() = default;
+  virtual int Bar() = 0;
+};
+"""
+    # The constructors and destructor should be ignored.
+    self.assertEqualIgnoreLeadingWhitespace(
+        'MOCK_METHOD0(Bar,\nint());',
+        self.GenerateMethodSource(source))
+
+  def testExplicitlyDeletedConstructorsAndDestructor(self):
+    source = """
+class Foo {
+ public:
+  Foo() = delete;
+  Foo(const Foo& f) = delete;
+  Foo(Foo&& f) = delete;
+  ~Foo() = delete;
+  virtual int Bar() = 0;
+};
+"""
+    # The constructors and destructor should be ignored.
+    self.assertEqualIgnoreLeadingWhitespace(
+        'MOCK_METHOD0(Bar,\nint());',
+        self.GenerateMethodSource(source))
+
+  def testSimpleOverrideMethod(self):
+    source = """
+class Foo {
+ public:
+  int Bar() override;
+};
+"""
+    self.assertEqualIgnoreLeadingWhitespace(
+        'MOCK_METHOD0(Bar,\nint());',
+        self.GenerateMethodSource(source))
+
+  def testSimpleConstMethod(self):
+    source = """
+class Foo {
+ public:
+  virtual void Bar(bool flag) const;
+};
+"""
+    self.assertEqualIgnoreLeadingWhitespace(
+        'MOCK_CONST_METHOD1(Bar,\nvoid(bool flag));',
+        self.GenerateMethodSource(source))
+
+  def testExplicitVoid(self):
+    source = """
+class Foo {
+ public:
+  virtual int Bar(void);
+};
+"""
+    self.assertEqualIgnoreLeadingWhitespace(
+        'MOCK_METHOD0(Bar,\nint(void));',
+        self.GenerateMethodSource(source))
+
+  def testStrangeNewlineInParameter(self):
+    source = """
+class Foo {
+ public:
+  virtual void Bar(int
+a) = 0;
+};
+"""
+    self.assertEqualIgnoreLeadingWhitespace(
+        'MOCK_METHOD1(Bar,\nvoid(int a));',
+        self.GenerateMethodSource(source))
+
+  def testDefaultParameters(self):
+    source = """
+class Foo {
+ public:
+  virtual void Bar(int a, char c = 'x') = 0;
+};
+"""
+    self.assertEqualIgnoreLeadingWhitespace(
+        'MOCK_METHOD2(Bar,\nvoid(int, char));',
+        self.GenerateMethodSource(source))
+
+  def testMultipleDefaultParameters(self):
+    source = """
+class Foo {
+ public:
+  virtual void Bar(int a = 42, char c = 'x') = 0;
+};
+"""
+    self.assertEqualIgnoreLeadingWhitespace(
+        'MOCK_METHOD2(Bar,\nvoid(int, char));',
+        self.GenerateMethodSource(source))
+
+  def testRemovesCommentsWhenDefaultsArePresent(self):
+    source = """
+class Foo {
+ public:
+  virtual void Bar(int a = 42 /* a comment */,
+                   char /* other comment */ c= 'x') = 0;
+};
+"""
+    self.assertEqualIgnoreLeadingWhitespace(
+        'MOCK_METHOD2(Bar,\nvoid(int, char));',
+        self.GenerateMethodSource(source))
+
+  def testDoubleSlashCommentsInParameterListAreRemoved(self):
+    source = """
+class Foo {
+ public:
+  virtual void Bar(int a,  // inline comments should be elided.
+                   int b   // inline comments should be elided.
+                   ) const = 0;
+};
+"""
+    self.assertEqualIgnoreLeadingWhitespace(
+        'MOCK_CONST_METHOD2(Bar,\nvoid(int a, int b));',
+        self.GenerateMethodSource(source))
+
+  def testCStyleCommentsInParameterListAreNotRemoved(self):
+    # NOTE(nnorwitz): I'm not sure if it's the best behavior to keep these
+    # comments.  Also note that C style comments after the last parameter
+    # are still elided.
+    source = """
+class Foo {
+ public:
+  virtual const string& Bar(int /* keeper */, int b);
+};
+"""
+    self.assertEqualIgnoreLeadingWhitespace(
+        'MOCK_METHOD2(Bar,\nconst string&(int /* keeper */, int b));',
+        self.GenerateMethodSource(source))
+
+  def testArgsOfTemplateTypes(self):
+    source = """
+class Foo {
+ public:
+  virtual int Bar(const vector<int>& v, map<int, string>* output);
+};"""
+    self.assertEqualIgnoreLeadingWhitespace(
+        'MOCK_METHOD2(Bar,\n'
+        'int(const vector<int>& v, map<int, string>* output));',
+        self.GenerateMethodSource(source))
+
+  def testReturnTypeWithOneTemplateArg(self):
+    source = """
+class Foo {
+ public:
+  virtual vector<int>* Bar(int n);
+};"""
+    self.assertEqualIgnoreLeadingWhitespace(
+        'MOCK_METHOD1(Bar,\nvector<int>*(int n));',
+        self.GenerateMethodSource(source))
+
+  def testReturnTypeWithManyTemplateArgs(self):
+    source = """
+class Foo {
+ public:
+  virtual map<int, string> Bar();
+};"""
+    # Comparing the comment text is brittle - we'll think of something
+    # better in case this gets annoying, but for now let's keep it simple.
+    self.assertEqualIgnoreLeadingWhitespace(
+        '// The following line won\'t really compile, as the return\n'
+        '// type has multiple template arguments.  To fix it, use a\n'
+        '// typedef for the return type.\n'
+        'MOCK_METHOD0(Bar,\nmap<int, string>());',
+        self.GenerateMethodSource(source))
+
+  def testSimpleMethodInTemplatedClass(self):
+    source = """
+template<class T>
+class Foo {
+ public:
+  virtual int Bar();
+};
+"""
+    self.assertEqualIgnoreLeadingWhitespace(
+        'MOCK_METHOD0_T(Bar,\nint());',
+        self.GenerateMethodSource(source))
+
+  def testPointerArgWithoutNames(self):
+    source = """
+class Foo {
+  virtual int Bar(C*);
+};
+"""
+    self.assertEqualIgnoreLeadingWhitespace(
+        'MOCK_METHOD1(Bar,\nint(C*));',
+        self.GenerateMethodSource(source))
+
+  def testReferenceArgWithoutNames(self):
+    source = """
+class Foo {
+  virtual int Bar(C&);
+};
+"""
+    self.assertEqualIgnoreLeadingWhitespace(
+        'MOCK_METHOD1(Bar,\nint(C&));',
+        self.GenerateMethodSource(source))
+
+  def testArrayArgWithoutNames(self):
+    source = """
+class Foo {
+  virtual int Bar(C[]);
+};
+"""
+    self.assertEqualIgnoreLeadingWhitespace(
+        'MOCK_METHOD1(Bar,\nint(C[]));',
+        self.GenerateMethodSource(source))
+
+
+class GenerateMocksTest(TestCase):
+
+  def GenerateMocks(self, cpp_source):
+    """Convert C++ source to complete Google Mock output source."""
+    # <test> is a pseudo-filename, it is not read or written.
+    filename = '<test>'
+    builder = ast.BuilderFromSource(cpp_source, filename)
+    ast_list = list(builder.Generate())
+    lines = gmock_class._GenerateMocks(filename, cpp_source, ast_list, None)
+    return '\n'.join(lines)
+
+  def testNamespaces(self):
+    source = """
+namespace Foo {
+namespace Bar { class Forward; }
+namespace Baz {
+
+class Test {
+ public:
+  virtual void Foo();
+};
+
+}  // namespace Baz
+}  // namespace Foo
+"""
+    expected = """\
+namespace Foo {
+namespace Baz {
+
+class MockTest : public Test {
+public:
+MOCK_METHOD0(Foo,
+void());
+};
+
+}  // namespace Baz
+}  // namespace Foo
+"""
+    self.assertEqualIgnoreLeadingWhitespace(
+        expected, self.GenerateMocks(source))
+
+  def testClassWithStorageSpecifierMacro(self):
+    source = """
+class STORAGE_SPECIFIER Test {
+ public:
+  virtual void Foo();
+};
+"""
+    expected = """\
+class MockTest : public Test {
+public:
+MOCK_METHOD0(Foo,
+void());
+};
+"""
+    self.assertEqualIgnoreLeadingWhitespace(
+        expected, self.GenerateMocks(source))
+
+  def testTemplatedForwardDeclaration(self):
+    source = """
+template <class T> class Forward;  // Forward declaration should be ignored.
+class Test {
+ public:
+  virtual void Foo();
+};
+"""
+    expected = """\
+class MockTest : public Test {
+public:
+MOCK_METHOD0(Foo,
+void());
+};
+"""
+    self.assertEqualIgnoreLeadingWhitespace(
+        expected, self.GenerateMocks(source))
+
+  def testTemplatedClass(self):
+    source = """
+template <typename S, typename T>
+class Test {
+ public:
+  virtual void Foo();
+};
+"""
+    expected = """\
+template <typename T0, typename T1>
+class MockTest : public Test<T0, T1> {
+public:
+MOCK_METHOD0_T(Foo,
+void());
+};
+"""
+    self.assertEqualIgnoreLeadingWhitespace(
+        expected, self.GenerateMocks(source))
+
+  def testTemplateInATemplateTypedef(self):
+    source = """
+class Test {
+ public:
+  typedef std::vector<std::list<int>> FooType;
+  virtual void Bar(const FooType& test_arg);
+};
+"""
+    expected = """\
+class MockTest : public Test {
+public:
+MOCK_METHOD1(Bar,
+void(const FooType& test_arg));
+};
+"""
+    self.assertEqualIgnoreLeadingWhitespace(
+        expected, self.GenerateMocks(source))
+
+  def testTemplateInATemplateTypedefWithComma(self):
+    source = """
+class Test {
+ public:
+  typedef std::function<void(
+      const vector<std::list<int>>&, int> FooType;
+  virtual void Bar(const FooType& test_arg);
+};
+"""
+    expected = """\
+class MockTest : public Test {
+public:
+MOCK_METHOD1(Bar,
+void(const FooType& test_arg));
+};
+"""
+    self.assertEqualIgnoreLeadingWhitespace(
+        expected, self.GenerateMocks(source))
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/third_party/googletest/googlemock/scripts/generator/cpp/keywords.py b/third_party/googletest/googlemock/scripts/generator/cpp/keywords.py
new file mode 100755
index 0000000..f694450
--- /dev/null
+++ b/third_party/googletest/googlemock/scripts/generator/cpp/keywords.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python
+#
+# Copyright 2007 Neal Norwitz
+# Portions Copyright 2007 Google Inc.
+#
+# 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.
+
+"""C++ keywords and helper utilities for determining keywords."""
+
+__author__ = 'nnorwitz@google.com (Neal Norwitz)'
+
+
+try:
+    # Python 3.x
+    import builtins
+except ImportError:
+    # Python 2.x
+    import __builtin__ as builtins
+
+
+if not hasattr(builtins, 'set'):
+    # Nominal support for Python 2.3.
+    from sets import Set as set
+
+
+TYPES = set('bool char int long short double float void wchar_t unsigned signed'.split())
+TYPE_MODIFIERS = set('auto register const inline extern static virtual volatile mutable'.split())
+ACCESS = set('public protected private friend'.split())
+
+CASTS = set('static_cast const_cast dynamic_cast reinterpret_cast'.split())
+
+OTHERS = set('true false asm class namespace using explicit this operator sizeof'.split())
+OTHER_TYPES = set('new delete typedef struct union enum typeid typename template'.split())
+
+CONTROL = set('case switch default if else return goto'.split())
+EXCEPTION = set('try catch throw'.split())
+LOOP = set('while do for break continue'.split())
+
+ALL = TYPES | TYPE_MODIFIERS | ACCESS | CASTS | OTHERS | OTHER_TYPES | CONTROL | EXCEPTION | LOOP
+
+
+def IsKeyword(token):
+    return token in ALL
+
+def IsBuiltinType(token):
+    if token in ('virtual', 'inline'):
+        # These only apply to methods, they can't be types by themselves.
+        return False
+    return token in TYPES or token in TYPE_MODIFIERS
diff --git a/third_party/googletest/googlemock/scripts/generator/cpp/tokenize.py b/third_party/googletest/googlemock/scripts/generator/cpp/tokenize.py
new file mode 100755
index 0000000..359d556
--- /dev/null
+++ b/third_party/googletest/googlemock/scripts/generator/cpp/tokenize.py
@@ -0,0 +1,287 @@
+#!/usr/bin/env python
+#
+# Copyright 2007 Neal Norwitz
+# Portions Copyright 2007 Google Inc.
+#
+# 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.
+
+"""Tokenize C++ source code."""
+
+__author__ = 'nnorwitz@google.com (Neal Norwitz)'
+
+
+try:
+    # Python 3.x
+    import builtins
+except ImportError:
+    # Python 2.x
+    import __builtin__ as builtins
+
+
+import sys
+
+from cpp import utils
+
+
+if not hasattr(builtins, 'set'):
+    # Nominal support for Python 2.3.
+    from sets import Set as set
+
+
+# Add $ as a valid identifier char since so much code uses it.
+_letters = 'abcdefghijklmnopqrstuvwxyz'
+VALID_IDENTIFIER_CHARS = set(_letters + _letters.upper() + '_0123456789$')
+HEX_DIGITS = set('0123456789abcdefABCDEF')
+INT_OR_FLOAT_DIGITS = set('01234567890eE-+')
+
+
+# C++0x string preffixes.
+_STR_PREFIXES = set(('R', 'u8', 'u8R', 'u', 'uR', 'U', 'UR', 'L', 'LR'))
+
+
+# Token types.
+UNKNOWN = 'UNKNOWN'
+SYNTAX = 'SYNTAX'
+CONSTANT = 'CONSTANT'
+NAME = 'NAME'
+PREPROCESSOR = 'PREPROCESSOR'
+
+# Where the token originated from.  This can be used for backtracking.
+# It is always set to WHENCE_STREAM in this code.
+WHENCE_STREAM, WHENCE_QUEUE = range(2)
+
+
+class Token(object):
+    """Data container to represent a C++ token.
+
+    Tokens can be identifiers, syntax char(s), constants, or
+    pre-processor directives.
+
+    start contains the index of the first char of the token in the source
+    end contains the index of the last char of the token in the source
+    """
+
+    def __init__(self, token_type, name, start, end):
+        self.token_type = token_type
+        self.name = name
+        self.start = start
+        self.end = end
+        self.whence = WHENCE_STREAM
+
+    def __str__(self):
+        if not utils.DEBUG:
+            return 'Token(%r)' % self.name
+        return 'Token(%r, %s, %s)' % (self.name, self.start, self.end)
+
+    __repr__ = __str__
+
+
+def _GetString(source, start, i):
+    i = source.find('"', i+1)
+    while source[i-1] == '\\':
+        # Count the trailing backslashes.
+        backslash_count = 1
+        j = i - 2
+        while source[j] == '\\':
+            backslash_count += 1
+            j -= 1
+        # When trailing backslashes are even, they escape each other.
+        if (backslash_count % 2) == 0:
+            break
+        i = source.find('"', i+1)
+    return i + 1
+
+
+def _GetChar(source, start, i):
+    # NOTE(nnorwitz): may not be quite correct, should be good enough.
+    i = source.find("'", i+1)
+    while source[i-1] == '\\':
+        # Need to special case '\\'.
+        if (i - 2) > start and source[i-2] == '\\':
+            break
+        i = source.find("'", i+1)
+    # Try to handle unterminated single quotes (in a #if 0 block).
+    if i < 0:
+        i = start
+    return i + 1
+
+
+def GetTokens(source):
+    """Returns a sequence of Tokens.
+
+    Args:
+      source: string of C++ source code.
+
+    Yields:
+      Token that represents the next token in the source.
+    """
+    # Cache various valid character sets for speed.
+    valid_identifier_chars = VALID_IDENTIFIER_CHARS
+    hex_digits = HEX_DIGITS
+    int_or_float_digits = INT_OR_FLOAT_DIGITS
+    int_or_float_digits2 = int_or_float_digits | set('.')
+
+    # Only ignore errors while in a #if 0 block.
+    ignore_errors = False
+    count_ifs = 0
+
+    i = 0
+    end = len(source)
+    while i < end:
+        # Skip whitespace.
+        while i < end and source[i].isspace():
+            i += 1
+        if i >= end:
+            return
+
+        token_type = UNKNOWN
+        start = i
+        c = source[i]
+        if c.isalpha() or c == '_':              # Find a string token.
+            token_type = NAME
+            while source[i] in valid_identifier_chars:
+                i += 1
+            # String and character constants can look like a name if
+            # they are something like L"".
+            if (source[i] == "'" and (i - start) == 1 and
+                source[start:i] in 'uUL'):
+                # u, U, and L are valid C++0x character preffixes.
+                token_type = CONSTANT
+                i = _GetChar(source, start, i)
+            elif source[i] == "'" and source[start:i] in _STR_PREFIXES:
+                token_type = CONSTANT
+                i = _GetString(source, start, i)
+        elif c == '/' and source[i+1] == '/':    # Find // comments.
+            i = source.find('\n', i)
+            if i == -1:  # Handle EOF.
+                i = end
+            continue
+        elif c == '/' and source[i+1] == '*':    # Find /* comments. */
+            i = source.find('*/', i) + 2
+            continue
+        elif c in ':+-<>&|*=':                   # : or :: (plus other chars).
+            token_type = SYNTAX
+            i += 1
+            new_ch = source[i]
+            if new_ch == c and c != '>':         # Treat ">>" as two tokens.
+                i += 1
+            elif c == '-' and new_ch == '>':
+                i += 1
+            elif new_ch == '=':
+                i += 1
+        elif c in '()[]{}~!?^%;/.,':             # Handle single char tokens.
+            token_type = SYNTAX
+            i += 1
+            if c == '.' and source[i].isdigit():
+                token_type = CONSTANT
+                i += 1
+                while source[i] in int_or_float_digits:
+                    i += 1
+                # Handle float suffixes.
+                for suffix in ('l', 'f'):
+                    if suffix == source[i:i+1].lower():
+                        i += 1
+                        break
+        elif c.isdigit():                        # Find integer.
+            token_type = CONSTANT
+            if c == '0' and source[i+1] in 'xX':
+                # Handle hex digits.
+                i += 2
+                while source[i] in hex_digits:
+                    i += 1
+            else:
+                while source[i] in int_or_float_digits2:
+                    i += 1
+            # Handle integer (and float) suffixes.
+            for suffix in ('ull', 'll', 'ul', 'l', 'f', 'u'):
+                size = len(suffix)
+                if suffix == source[i:i+size].lower():
+                    i += size
+                    break
+        elif c == '"':                           # Find string.
+            token_type = CONSTANT
+            i = _GetString(source, start, i)
+        elif c == "'":                           # Find char.
+            token_type = CONSTANT
+            i = _GetChar(source, start, i)
+        elif c == '#':                           # Find pre-processor command.
+            token_type = PREPROCESSOR
+            got_if = source[i:i+3] == '#if' and source[i+3:i+4].isspace()
+            if got_if:
+                count_ifs += 1
+            elif source[i:i+6] == '#endif':
+                count_ifs -= 1
+                if count_ifs == 0:
+                    ignore_errors = False
+
+            # TODO(nnorwitz): handle preprocessor statements (\ continuations).
+            while 1:
+                i1 = source.find('\n', i)
+                i2 = source.find('//', i)
+                i3 = source.find('/*', i)
+                i4 = source.find('"', i)
+                # NOTE(nnorwitz): doesn't handle comments in #define macros.
+                # Get the first important symbol (newline, comment, EOF/end).
+                i = min([x for x in (i1, i2, i3, i4, end) if x != -1])
+
+                # Handle #include "dir//foo.h" properly.
+                if source[i] == '"':
+                    i = source.find('"', i+1) + 1
+                    assert i > 0
+                    continue
+                # Keep going if end of the line and the line ends with \.
+                if not (i == i1 and source[i-1] == '\\'):
+                    if got_if:
+                        condition = source[start+4:i].lstrip()
+                        if (condition.startswith('0') or
+                            condition.startswith('(0)')):
+                            ignore_errors = True
+                    break
+                i += 1
+        elif c == '\\':                          # Handle \ in code.
+            # This is different from the pre-processor \ handling.
+            i += 1
+            continue
+        elif ignore_errors:
+            # The tokenizer seems to be in pretty good shape.  This
+            # raise is conditionally disabled so that bogus code
+            # in an #if 0 block can be handled.  Since we will ignore
+            # it anyways, this is probably fine.  So disable the
+            # exception and  return the bogus char.
+            i += 1
+        else:
+            sys.stderr.write('Got invalid token in %s @ %d token:%s: %r\n' %
+                             ('?', i, c, source[i-10:i+10]))
+            raise RuntimeError('unexpected token')
+
+        if i <= 0:
+            print('Invalid index, exiting now.')
+            return
+        yield Token(token_type, source[start:i], start, i)
+
+
+if __name__ == '__main__':
+    def main(argv):
+        """Driver mostly for testing purposes."""
+        for filename in argv[1:]:
+            source = utils.ReadFile(filename)
+            if source is None:
+                continue
+
+            for token in GetTokens(source):
+                print('%-12s: %s' % (token.token_type, token.name))
+                # print('\r%6.2f%%' % (100.0 * index / token.end),)
+            sys.stdout.write('\n')
+
+
+    main(sys.argv)
diff --git a/third_party/googletest/googlemock/scripts/generator/cpp/utils.py b/third_party/googletest/googlemock/scripts/generator/cpp/utils.py
new file mode 100755
index 0000000..eab36ee
--- /dev/null
+++ b/third_party/googletest/googlemock/scripts/generator/cpp/utils.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+#
+# Copyright 2007 Neal Norwitz
+# Portions Copyright 2007 Google Inc.
+#
+# 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.
+
+"""Generic utilities for C++ parsing."""
+
+__author__ = 'nnorwitz@google.com (Neal Norwitz)'
+
+
+import sys
+
+
+# Set to True to see the start/end token indices.
+DEBUG = True
+
+
+def ReadFile(filename, print_error=True):
+    """Returns the contents of a file."""
+    try:
+        fp = open(filename)
+        try:
+            return fp.read()
+        finally:
+            fp.close()
+    except IOError:
+        if print_error:
+            print('Error reading %s: %s' % (filename, sys.exc_info()[1]))
+        return None
diff --git a/third_party/googletest/googlemock/scripts/generator/gmock_gen.py b/third_party/googletest/googlemock/scripts/generator/gmock_gen.py
new file mode 100755
index 0000000..8cc0d13
--- /dev/null
+++ b/third_party/googletest/googlemock/scripts/generator/gmock_gen.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python
+#
+# Copyright 2008 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.
+
+"""Driver for starting up Google Mock class generator."""
+
+__author__ = 'nnorwitz@google.com (Neal Norwitz)'
+
+import os
+import sys
+
+if __name__ == '__main__':
+  # Add the directory of this script to the path so we can import gmock_class.
+  sys.path.append(os.path.dirname(__file__))
+
+  from cpp import gmock_class
+  # Fix the docstring in case they require the usage.
+  gmock_class.__doc__ = gmock_class.__doc__.replace('gmock_class.py', __file__)
+  gmock_class.main()
diff --git a/third_party/googletest/googlemock/scripts/gmock-config.in b/third_party/googletest/googlemock/scripts/gmock-config.in
new file mode 100755
index 0000000..2baefe9
--- /dev/null
+++ b/third_party/googletest/googlemock/scripts/gmock-config.in
@@ -0,0 +1,303 @@
+#!/bin/sh
+
+# These variables are automatically filled in by the configure script.
+name="@PACKAGE_TARNAME@"
+version="@PACKAGE_VERSION@"
+
+show_usage()
+{
+  echo "Usage: gmock-config [OPTIONS...]"
+}
+
+show_help()
+{
+  show_usage
+  cat <<\EOF
+
+The `gmock-config' script provides access to the necessary compile and linking
+flags to connect with Google C++ Mocking Framework, both in a build prior to
+installation, and on the system proper after installation. The installation
+overrides may be issued in combination with any other queries, but will only
+affect installation queries if called on a built but not installed gmock. The
+installation queries may not be issued with any other types of queries, and
+only one installation query may be made at a time. The version queries and
+compiler flag queries may be combined as desired but not mixed. Different
+version queries are always combined with logical "and" semantics, and only the
+last of any particular query is used while all previous ones ignored. All
+versions must be specified as a sequence of numbers separated by periods.
+Compiler flag queries output the union of the sets of flags when combined.
+
+ Examples:
+  gmock-config --min-version=1.0 || echo "Insufficient Google Mock version."
+
+  g++ $(gmock-config --cppflags --cxxflags) -o foo.o -c foo.cpp
+  g++ $(gmock-config --ldflags --libs) -o foo foo.o
+
+  # When using a built but not installed Google Mock:
+  g++ $(../../my_gmock_build/scripts/gmock-config ...) ...
+
+  # When using an installed Google Mock, but with installation overrides:
+  export GMOCK_PREFIX="/opt"
+  g++ $(gmock-config --libdir="/opt/lib64" ...) ...
+
+ Help:
+  --usage                    brief usage information
+  --help                     display this help message
+
+ Installation Overrides:
+  --prefix=<dir>             overrides the installation prefix
+  --exec-prefix=<dir>        overrides the executable installation prefix
+  --libdir=<dir>             overrides the library installation prefix
+  --includedir=<dir>         overrides the header file installation prefix
+
+ Installation Queries:
+  --prefix                   installation prefix
+  --exec-prefix              executable installation prefix
+  --libdir                   library installation directory
+  --includedir               header file installation directory
+  --version                  the version of the Google Mock installation
+
+ Version Queries:
+  --min-version=VERSION      return 0 if the version is at least VERSION
+  --exact-version=VERSION    return 0 if the version is exactly VERSION
+  --max-version=VERSION      return 0 if the version is at most VERSION
+
+ Compilation Flag Queries:
+  --cppflags                 compile flags specific to the C-like preprocessors
+  --cxxflags                 compile flags appropriate for C++ programs
+  --ldflags                  linker flags
+  --libs                     libraries for linking
+
+EOF
+}
+
+# This function bounds our version with a min and a max. It uses some clever
+# POSIX-compliant variable expansion to portably do all the work in the shell
+# and avoid any dependency on a particular "sed" or "awk" implementation.
+# Notable is that it will only ever compare the first 3 components of versions.
+# Further components will be cleanly stripped off. All versions must be
+# unadorned, so "v1.0" will *not* work. The minimum version must be in $1, and
+# the max in $2. TODO(chandlerc@google.com): If this ever breaks, we should
+# investigate expanding this via autom4te from AS_VERSION_COMPARE rather than
+# continuing to maintain our own shell version.
+check_versions()
+{
+  major_version=${version%%.*}
+  minor_version="0"
+  point_version="0"
+  if test "${version#*.}" != "${version}"; then
+    minor_version=${version#*.}
+    minor_version=${minor_version%%.*}
+  fi
+  if test "${version#*.*.}" != "${version}"; then
+    point_version=${version#*.*.}
+    point_version=${point_version%%.*}
+  fi
+
+  min_version="$1"
+  min_major_version=${min_version%%.*}
+  min_minor_version="0"
+  min_point_version="0"
+  if test "${min_version#*.}" != "${min_version}"; then
+    min_minor_version=${min_version#*.}
+    min_minor_version=${min_minor_version%%.*}
+  fi
+  if test "${min_version#*.*.}" != "${min_version}"; then
+    min_point_version=${min_version#*.*.}
+    min_point_version=${min_point_version%%.*}
+  fi
+
+  max_version="$2"
+  max_major_version=${max_version%%.*}
+  max_minor_version="0"
+  max_point_version="0"
+  if test "${max_version#*.}" != "${max_version}"; then
+    max_minor_version=${max_version#*.}
+    max_minor_version=${max_minor_version%%.*}
+  fi
+  if test "${max_version#*.*.}" != "${max_version}"; then
+    max_point_version=${max_version#*.*.}
+    max_point_version=${max_point_version%%.*}
+  fi
+
+  test $(($major_version)) -lt $(($min_major_version)) && exit 1
+  if test $(($major_version)) -eq $(($min_major_version)); then
+    test $(($minor_version)) -lt $(($min_minor_version)) && exit 1
+    if test $(($minor_version)) -eq $(($min_minor_version)); then
+      test $(($point_version)) -lt $(($min_point_version)) && exit 1
+    fi
+  fi
+
+  test $(($major_version)) -gt $(($max_major_version)) && exit 1
+  if test $(($major_version)) -eq $(($max_major_version)); then
+    test $(($minor_version)) -gt $(($max_minor_version)) && exit 1
+    if test $(($minor_version)) -eq $(($max_minor_version)); then
+      test $(($point_version)) -gt $(($max_point_version)) && exit 1
+    fi
+  fi
+
+  exit 0
+}
+
+# Show the usage line when no arguments are specified.
+if test $# -eq 0; then
+  show_usage
+  exit 1
+fi
+
+while test $# -gt 0; do
+  case $1 in
+    --usage)          show_usage;         exit 0;;
+    --help)           show_help;          exit 0;;
+
+    # Installation overrides
+    --prefix=*)       GMOCK_PREFIX=${1#--prefix=};;
+    --exec-prefix=*)  GMOCK_EXEC_PREFIX=${1#--exec-prefix=};;
+    --libdir=*)       GMOCK_LIBDIR=${1#--libdir=};;
+    --includedir=*)   GMOCK_INCLUDEDIR=${1#--includedir=};;
+
+    # Installation queries
+    --prefix|--exec-prefix|--libdir|--includedir|--version)
+      if test -n "${do_query}"; then
+        show_usage
+        exit 1
+      fi
+      do_query=${1#--}
+      ;;
+
+    # Version checking
+    --min-version=*)
+      do_check_versions=yes
+      min_version=${1#--min-version=}
+      ;;
+    --max-version=*)
+      do_check_versions=yes
+      max_version=${1#--max-version=}
+      ;;
+    --exact-version=*)
+      do_check_versions=yes
+      exact_version=${1#--exact-version=}
+      ;;
+
+    # Compiler flag output
+    --cppflags)       echo_cppflags=yes;;
+    --cxxflags)       echo_cxxflags=yes;;
+    --ldflags)        echo_ldflags=yes;;
+    --libs)           echo_libs=yes;;
+
+    # Everything else is an error
+    *)                show_usage;         exit 1;;
+  esac
+  shift
+done
+
+# These have defaults filled in by the configure script but can also be
+# overridden by environment variables or command line parameters.
+prefix="${GMOCK_PREFIX:-@prefix@}"
+exec_prefix="${GMOCK_EXEC_PREFIX:-@exec_prefix@}"
+libdir="${GMOCK_LIBDIR:-@libdir@}"
+includedir="${GMOCK_INCLUDEDIR:-@includedir@}"
+
+# We try and detect if our binary is not located at its installed location. If
+# it's not, we provide variables pointing to the source and build tree rather
+# than to the install tree. We also locate Google Test using the configured
+# gtest-config script rather than searching the PATH and our bindir for one.
+# This allows building against a just-built gmock rather than an installed
+# gmock.
+bindir="@bindir@"
+this_relative_bindir=`dirname $0`
+this_bindir=`cd ${this_relative_bindir}; pwd -P`
+if test "${this_bindir}" = "${this_bindir%${bindir}}"; then
+  # The path to the script doesn't end in the bindir sequence from Autoconf,
+  # assume that we are in a build tree.
+  build_dir=`dirname ${this_bindir}`
+  src_dir=`cd ${this_bindir}/@top_srcdir@; pwd -P`
+
+  # TODO(chandlerc@google.com): This is a dangerous dependency on libtool, we
+  # should work to remove it, and/or remove libtool altogether, replacing it
+  # with direct references to the library and a link path.
+  gmock_libs="${build_dir}/lib/libgmock.la"
+  gmock_ldflags=""
+
+  # We provide hooks to include from either the source or build dir, where the
+  # build dir is always preferred. This will potentially allow us to write
+  # build rules for generated headers and have them automatically be preferred
+  # over provided versions.
+  gmock_cppflags="-I${build_dir}/include -I${src_dir}/include"
+  gmock_cxxflags=""
+
+  # Directly invoke the gtest-config script used during the build process.
+  gtest_config="@GTEST_CONFIG@"
+else
+  # We're using an installed gmock, although it may be staged under some
+  # prefix. Assume (as our own libraries do) that we can resolve the prefix,
+  # and are present in the dynamic link paths.
+  gmock_ldflags="-L${libdir}"
+  gmock_libs="-l${name}"
+  gmock_cppflags="-I${includedir}"
+  gmock_cxxflags=""
+
+  # We also prefer any gtest-config script installed in our prefix. Lacking
+  # one, we look in the PATH for one.
+  gtest_config="${bindir}/gtest-config"
+  if test ! -x "${gtest_config}"; then
+    gtest_config=`which gtest-config`
+  fi
+fi
+
+# Ensure that we have located a Google Test to link against.
+if ! test -x "${gtest_config}"; then
+  echo "Unable to locate Google Test, check your Google Mock configuration" \
+       "and installation" >&2
+  exit 1
+elif ! "${gtest_config}" "--exact-version=@GTEST_VERSION@"; then
+  echo "The Google Test found is not the same version as Google Mock was " \
+       "built against" >&2
+  exit 1
+fi
+
+# Add the necessary Google Test bits into the various flag variables
+gmock_cppflags="${gmock_cppflags} `${gtest_config} --cppflags`"
+gmock_cxxflags="${gmock_cxxflags} `${gtest_config} --cxxflags`"
+gmock_ldflags="${gmock_ldflags} `${gtest_config} --ldflags`"
+gmock_libs="${gmock_libs} `${gtest_config} --libs`"
+
+# Do an installation query if requested.
+if test -n "$do_query"; then
+  case $do_query in
+    prefix)           echo $prefix;       exit 0;;
+    exec-prefix)      echo $exec_prefix;  exit 0;;
+    libdir)           echo $libdir;       exit 0;;
+    includedir)       echo $includedir;   exit 0;;
+    version)          echo $version;      exit 0;;
+    *)                show_usage;         exit 1;;
+  esac
+fi
+
+# Do a version check if requested.
+if test "$do_check_versions" = "yes"; then
+  # Make sure we didn't receive a bad combination of parameters.
+  test "$echo_cppflags" = "yes" && show_usage && exit 1
+  test "$echo_cxxflags" = "yes" && show_usage && exit 1
+  test "$echo_ldflags" = "yes"  && show_usage && exit 1
+  test "$echo_libs" = "yes"     && show_usage && exit 1
+
+  if test "$exact_version" != ""; then
+    check_versions $exact_version $exact_version
+    # unreachable
+  else
+    check_versions ${min_version:-0.0.0} ${max_version:-9999.9999.9999}
+    # unreachable
+  fi
+fi
+
+# Do the output in the correct order so that these can be used in-line of
+# a compiler invocation.
+output=""
+test "$echo_cppflags" = "yes" && output="$output $gmock_cppflags"
+test "$echo_cxxflags" = "yes" && output="$output $gmock_cxxflags"
+test "$echo_ldflags" = "yes"  && output="$output $gmock_ldflags"
+test "$echo_libs" = "yes"     && output="$output $gmock_libs"
+echo $output
+
+exit 0
diff --git a/third_party/googletest/googlemock/scripts/gmock_doctor.py b/third_party/googletest/googlemock/scripts/gmock_doctor.py
new file mode 100755
index 0000000..74992bc
--- /dev/null
+++ b/third_party/googletest/googlemock/scripts/gmock_doctor.py
@@ -0,0 +1,640 @@
+#!/usr/bin/env python
+#
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Converts compiler's errors in code using Google Mock to plain English."""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import re
+import sys
+
+_VERSION = '1.0.3'
+
+_EMAIL = 'googlemock@googlegroups.com'
+
+_COMMON_GMOCK_SYMBOLS = [
+    # Matchers
+    '_',
+    'A',
+    'AddressSatisfies',
+    'AllOf',
+    'An',
+    'AnyOf',
+    'ContainerEq',
+    'Contains',
+    'ContainsRegex',
+    'DoubleEq',
+    'ElementsAre',
+    'ElementsAreArray',
+    'EndsWith',
+    'Eq',
+    'Field',
+    'FloatEq',
+    'Ge',
+    'Gt',
+    'HasSubstr',
+    'IsInitializedProto',
+    'Le',
+    'Lt',
+    'MatcherCast',
+    'Matches',
+    'MatchesRegex',
+    'NanSensitiveDoubleEq',
+    'NanSensitiveFloatEq',
+    'Ne',
+    'Not',
+    'NotNull',
+    'Pointee',
+    'Property',
+    'Ref',
+    'ResultOf',
+    'SafeMatcherCast',
+    'StartsWith',
+    'StrCaseEq',
+    'StrCaseNe',
+    'StrEq',
+    'StrNe',
+    'Truly',
+    'TypedEq',
+    'Value',
+
+    # Actions
+    'Assign',
+    'ByRef',
+    'DeleteArg',
+    'DoAll',
+    'DoDefault',
+    'IgnoreResult',
+    'Invoke',
+    'InvokeArgument',
+    'InvokeWithoutArgs',
+    'Return',
+    'ReturnNew',
+    'ReturnNull',
+    'ReturnRef',
+    'SaveArg',
+    'SetArgReferee',
+    'SetArgPointee',
+    'SetArgumentPointee',
+    'SetArrayArgument',
+    'SetErrnoAndReturn',
+    'Throw',
+    'WithArg',
+    'WithArgs',
+    'WithoutArgs',
+
+    # Cardinalities
+    'AnyNumber',
+    'AtLeast',
+    'AtMost',
+    'Between',
+    'Exactly',
+
+    # Sequences
+    'InSequence',
+    'Sequence',
+
+    # Misc
+    'DefaultValue',
+    'Mock',
+    ]
+
+# Regex for matching source file path and line number in the compiler's errors.
+_GCC_FILE_LINE_RE = r'(?P<file>.*):(?P<line>\d+):(\d+:)?\s+'
+_CLANG_FILE_LINE_RE = r'(?P<file>.*):(?P<line>\d+):(?P<column>\d+):\s+'
+_CLANG_NON_GMOCK_FILE_LINE_RE = (
+    r'(?P<file>.*[/\\^](?!gmock-)[^/\\]+):(?P<line>\d+):(?P<column>\d+):\s+')
+
+
+def _FindAllMatches(regex, s):
+  """Generates all matches of regex in string s."""
+
+  r = re.compile(regex)
+  return r.finditer(s)
+
+
+def _GenericDiagnoser(short_name, long_name, diagnoses, msg):
+  """Diagnoses the given disease by pattern matching.
+
+  Can provide different diagnoses for different patterns.
+
+  Args:
+    short_name: Short name of the disease.
+    long_name:  Long name of the disease.
+    diagnoses:  A list of pairs (regex, pattern for formatting the diagnosis
+                for matching regex).
+    msg:        Compiler's error messages.
+  Yields:
+    Tuples of the form
+      (short name of disease, long name of disease, diagnosis).
+  """
+  for regex, diagnosis in diagnoses:
+    if re.search(regex, msg):
+      diagnosis = '%(file)s:%(line)s:' + diagnosis
+      for m in _FindAllMatches(regex, msg):
+        yield (short_name, long_name, diagnosis % m.groupdict())
+
+
+def _NeedToReturnReferenceDiagnoser(msg):
+  """Diagnoses the NRR disease, given the error messages by the compiler."""
+
+  gcc_regex = (r'In member function \'testing::internal::ReturnAction<R>.*\n'
+               + _GCC_FILE_LINE_RE + r'instantiated from here\n'
+               r'.*gmock-actions\.h.*error: creating array with negative size')
+  clang_regex = (r'error:.*array.*negative.*\r?\n'
+                 r'(.*\n)*?' +
+                 _CLANG_NON_GMOCK_FILE_LINE_RE +
+                 r'note: in instantiation of function template specialization '
+                 r'\'testing::internal::ReturnAction<(?P<type>.*)>'
+                 r'::operator Action<.*>\' requested here')
+  clang11_re = (r'use_ReturnRef_instead_of_Return_to_return_a_reference.*'
+                r'(.*\n)*?' + _CLANG_NON_GMOCK_FILE_LINE_RE)
+
+  diagnosis = """
+You are using a Return() action in a function that returns a reference to
+%(type)s.  Please use ReturnRef() instead."""
+  return _GenericDiagnoser('NRR', 'Need to Return Reference',
+                           [(clang_regex, diagnosis),
+                            (clang11_re, diagnosis % {'type': 'a type'}),
+                            (gcc_regex, diagnosis % {'type': 'a type'})],
+                           msg)
+
+
+def _NeedToReturnSomethingDiagnoser(msg):
+  """Diagnoses the NRS disease, given the error messages by the compiler."""
+
+  gcc_regex = (_GCC_FILE_LINE_RE + r'(instantiated from here\n.'
+               r'*gmock.*actions\.h.*error: void value not ignored)'
+               r'|(error: control reaches end of non-void function)')
+  clang_regex1 = (_CLANG_FILE_LINE_RE +
+                  r'error: cannot initialize return object '
+                  r'of type \'Result\' \(aka \'(?P<return_type>.*)\'\) '
+                  r'with an rvalue of type \'void\'')
+  clang_regex2 = (_CLANG_FILE_LINE_RE +
+                  r'error: cannot initialize return object '
+                  r'of type \'(?P<return_type>.*)\' '
+                  r'with an rvalue of type \'void\'')
+  diagnosis = """
+You are using an action that returns void, but it needs to return
+%(return_type)s.  Please tell it *what* to return.  Perhaps you can use
+the pattern DoAll(some_action, Return(some_value))?"""
+  return _GenericDiagnoser(
+      'NRS',
+      'Need to Return Something',
+      [(gcc_regex, diagnosis % {'return_type': '*something*'}),
+       (clang_regex1, diagnosis),
+       (clang_regex2, diagnosis)],
+      msg)
+
+
+def _NeedToReturnNothingDiagnoser(msg):
+  """Diagnoses the NRN disease, given the error messages by the compiler."""
+
+  gcc_regex = (_GCC_FILE_LINE_RE + r'instantiated from here\n'
+               r'.*gmock-actions\.h.*error: instantiation of '
+               r'\'testing::internal::ReturnAction<R>::Impl<F>::value_\' '
+               r'as type \'void\'')
+  clang_regex1 = (r'error: field has incomplete type '
+                  r'\'Result\' \(aka \'void\'\)(\r)?\n'
+                  r'(.*\n)*?' +
+                  _CLANG_NON_GMOCK_FILE_LINE_RE + r'note: in instantiation '
+                  r'of function template specialization '
+                  r'\'testing::internal::ReturnAction<(?P<return_type>.*)>'
+                  r'::operator Action<void \(.*\)>\' requested here')
+  clang_regex2 = (r'error: field has incomplete type '
+                  r'\'Result\' \(aka \'void\'\)(\r)?\n'
+                  r'(.*\n)*?' +
+                  _CLANG_NON_GMOCK_FILE_LINE_RE + r'note: in instantiation '
+                  r'of function template specialization '
+                  r'\'testing::internal::DoBothAction<.*>'
+                  r'::operator Action<(?P<return_type>.*) \(.*\)>\' '
+                  r'requested here')
+  diagnosis = """
+You are using an action that returns %(return_type)s, but it needs to return
+void.  Please use a void-returning action instead.
+
+All actions but the last in DoAll(...) must return void.  Perhaps you need
+to re-arrange the order of actions in a DoAll(), if you are using one?"""
+  return _GenericDiagnoser(
+      'NRN',
+      'Need to Return Nothing',
+      [(gcc_regex, diagnosis % {'return_type': '*something*'}),
+       (clang_regex1, diagnosis),
+       (clang_regex2, diagnosis)],
+      msg)
+
+
+def _IncompleteByReferenceArgumentDiagnoser(msg):
+  """Diagnoses the IBRA disease, given the error messages by the compiler."""
+
+  gcc_regex = (_GCC_FILE_LINE_RE + r'instantiated from here\n'
+               r'.*gtest-printers\.h.*error: invalid application of '
+               r'\'sizeof\' to incomplete type \'(?P<type>.*)\'')
+
+  clang_regex = (r'.*gtest-printers\.h.*error: invalid application of '
+                 r'\'sizeof\' to an incomplete type '
+                 r'\'(?P<type>.*)( const)?\'\r?\n'
+                 r'(.*\n)*?' +
+                 _CLANG_NON_GMOCK_FILE_LINE_RE +
+                 r'note: in instantiation of member function '
+                 r'\'testing::internal2::TypeWithoutFormatter<.*>::'
+                 r'PrintValue\' requested here')
+  diagnosis = """
+In order to mock this function, Google Mock needs to see the definition
+of type "%(type)s" - declaration alone is not enough.  Either #include
+the header that defines it, or change the argument to be passed
+by pointer."""
+
+  return _GenericDiagnoser('IBRA', 'Incomplete By-Reference Argument Type',
+                           [(gcc_regex, diagnosis),
+                            (clang_regex, diagnosis)],
+                           msg)
+
+
+def _OverloadedFunctionMatcherDiagnoser(msg):
+  """Diagnoses the OFM disease, given the error messages by the compiler."""
+
+  gcc_regex = (_GCC_FILE_LINE_RE + r'error: no matching function for '
+               r'call to \'Truly\(<unresolved overloaded function type>\)')
+  clang_regex = (_CLANG_FILE_LINE_RE + r'error: no matching function for '
+                 r'call to \'Truly')
+  diagnosis = """
+The argument you gave to Truly() is an overloaded function.  Please tell
+your compiler which overloaded version you want to use.
+
+For example, if you want to use the version whose signature is
+  bool Foo(int n);
+you should write
+  Truly(static_cast<bool (*)(int n)>(Foo))"""
+  return _GenericDiagnoser('OFM', 'Overloaded Function Matcher',
+                           [(gcc_regex, diagnosis),
+                            (clang_regex, diagnosis)],
+                           msg)
+
+
+def _OverloadedFunctionActionDiagnoser(msg):
+  """Diagnoses the OFA disease, given the error messages by the compiler."""
+
+  gcc_regex = (_GCC_FILE_LINE_RE + r'error: no matching function for call to '
+               r'\'Invoke\(<unresolved overloaded function type>')
+  clang_regex = (_CLANG_FILE_LINE_RE + r'error: no matching '
+                 r'function for call to \'Invoke\'\r?\n'
+                 r'(.*\n)*?'
+                 r'.*\bgmock-generated-actions\.h:\d+:\d+:\s+'
+                 r'note: candidate template ignored:\s+'
+                 r'couldn\'t infer template argument \'FunctionImpl\'')
+  diagnosis = """
+Function you are passing to Invoke is overloaded.  Please tell your compiler
+which overloaded version you want to use.
+
+For example, if you want to use the version whose signature is
+  bool MyFunction(int n, double x);
+you should write something like
+  Invoke(static_cast<bool (*)(int n, double x)>(MyFunction))"""
+  return _GenericDiagnoser('OFA', 'Overloaded Function Action',
+                           [(gcc_regex, diagnosis),
+                            (clang_regex, diagnosis)],
+                           msg)
+
+
+def _OverloadedMethodActionDiagnoser(msg):
+  """Diagnoses the OMA disease, given the error messages by the compiler."""
+
+  gcc_regex = (_GCC_FILE_LINE_RE + r'error: no matching function for '
+               r'call to \'Invoke\(.+, <unresolved overloaded function '
+               r'type>\)')
+  clang_regex = (_CLANG_FILE_LINE_RE + r'error: no matching function '
+                 r'for call to \'Invoke\'\r?\n'
+                 r'(.*\n)*?'
+                 r'.*\bgmock-generated-actions\.h:\d+:\d+: '
+                 r'note: candidate function template not viable: '
+                 r'requires .*, but 2 (arguments )?were provided')
+  diagnosis = """
+The second argument you gave to Invoke() is an overloaded method.  Please
+tell your compiler which overloaded version you want to use.
+
+For example, if you want to use the version whose signature is
+  class Foo {
+    ...
+    bool Bar(int n, double x);
+  };
+you should write something like
+  Invoke(foo, static_cast<bool (Foo::*)(int n, double x)>(&Foo::Bar))"""
+  return _GenericDiagnoser('OMA', 'Overloaded Method Action',
+                           [(gcc_regex, diagnosis),
+                            (clang_regex, diagnosis)],
+                           msg)
+
+
+def _MockObjectPointerDiagnoser(msg):
+  """Diagnoses the MOP disease, given the error messages by the compiler."""
+
+  gcc_regex = (_GCC_FILE_LINE_RE + r'error: request for member '
+               r'\'gmock_(?P<method>.+)\' in \'(?P<mock_object>.+)\', '
+               r'which is of non-class type \'(.*::)*(?P<class_name>.+)\*\'')
+  clang_regex = (_CLANG_FILE_LINE_RE + r'error: member reference type '
+                 r'\'(?P<class_name>.*?) *\' is a pointer; '
+                 r'(did you mean|maybe you meant) to use \'->\'\?')
+  diagnosis = """
+The first argument to ON_CALL() and EXPECT_CALL() must be a mock *object*,
+not a *pointer* to it.  Please write '*(%(mock_object)s)' instead of
+'%(mock_object)s' as your first argument.
+
+For example, given the mock class:
+
+  class %(class_name)s : public ... {
+    ...
+    MOCK_METHOD0(%(method)s, ...);
+  };
+
+and the following mock instance:
+
+  %(class_name)s* mock_ptr = ...
+
+you should use the EXPECT_CALL like this:
+
+  EXPECT_CALL(*mock_ptr, %(method)s(...));"""
+
+  return _GenericDiagnoser(
+      'MOP',
+      'Mock Object Pointer',
+      [(gcc_regex, diagnosis),
+       (clang_regex, diagnosis % {'mock_object': 'mock_object',
+                                  'method': 'method',
+                                  'class_name': '%(class_name)s'})],
+       msg)
+
+
+def _NeedToUseSymbolDiagnoser(msg):
+  """Diagnoses the NUS disease, given the error messages by the compiler."""
+
+  gcc_regex = (_GCC_FILE_LINE_RE + r'error: \'(?P<symbol>.+)\' '
+               r'(was not declared in this scope|has not been declared)')
+  clang_regex = (_CLANG_FILE_LINE_RE +
+                 r'error: (use of undeclared identifier|unknown type name|'
+                 r'no template named) \'(?P<symbol>[^\']+)\'')
+  diagnosis = """
+'%(symbol)s' is defined by Google Mock in the testing namespace.
+Did you forget to write
+  using testing::%(symbol)s;
+?"""
+  for m in (list(_FindAllMatches(gcc_regex, msg)) +
+            list(_FindAllMatches(clang_regex, msg))):
+    symbol = m.groupdict()['symbol']
+    if symbol in _COMMON_GMOCK_SYMBOLS:
+      yield ('NUS', 'Need to Use Symbol', diagnosis % m.groupdict())
+
+
+def _NeedToUseReturnNullDiagnoser(msg):
+  """Diagnoses the NRNULL disease, given the error messages by the compiler."""
+
+  gcc_regex = ('instantiated from \'testing::internal::ReturnAction<R>'
+               '::operator testing::Action<Func>\(\) const.*\n' +
+               _GCC_FILE_LINE_RE + r'instantiated from here\n'
+               r'.*error: no matching function for call to \'ImplicitCast_\('
+               r'(:?long )?int&\)')
+  clang_regex = (r'\bgmock-actions.h:.* error: no matching function for '
+                 r'call to \'ImplicitCast_\'\r?\n'
+                 r'(.*\n)*?' +
+                 _CLANG_NON_GMOCK_FILE_LINE_RE + r'note: in instantiation '
+                 r'of function template specialization '
+                 r'\'testing::internal::ReturnAction<(int|long)>::operator '
+                 r'Action<(?P<type>.*)\(\)>\' requested here')
+  diagnosis = """
+You are probably calling Return(NULL) and the compiler isn't sure how to turn
+NULL into %(type)s. Use ReturnNull() instead.
+Note: the line number may be off; please fix all instances of Return(NULL)."""
+  return _GenericDiagnoser(
+      'NRNULL', 'Need to use ReturnNull',
+      [(clang_regex, diagnosis),
+       (gcc_regex, diagnosis % {'type': 'the right type'})],
+      msg)
+
+
+def _TypeInTemplatedBaseDiagnoser(msg):
+  """Diagnoses the TTB disease, given the error messages by the compiler."""
+
+  # This version works when the type is used as the mock function's return
+  # type.
+  gcc_4_3_1_regex_type_in_retval = (
+      r'In member function \'int .*\n' + _GCC_FILE_LINE_RE +
+      r'error: a function call cannot appear in a constant-expression')
+  gcc_4_4_0_regex_type_in_retval = (
+      r'error: a function call cannot appear in a constant-expression'
+      + _GCC_FILE_LINE_RE + r'error: template argument 1 is invalid\n')
+  # This version works when the type is used as the mock function's sole
+  # parameter type.
+  gcc_regex_type_of_sole_param = (
+      _GCC_FILE_LINE_RE +
+      r'error: \'(?P<type>.+)\' was not declared in this scope\n'
+      r'.*error: template argument 1 is invalid\n')
+  # This version works when the type is used as a parameter of a mock
+  # function that has multiple parameters.
+  gcc_regex_type_of_a_param = (
+      r'error: expected `;\' before \'::\' token\n'
+      + _GCC_FILE_LINE_RE +
+      r'error: \'(?P<type>.+)\' was not declared in this scope\n'
+      r'.*error: template argument 1 is invalid\n'
+      r'.*error: \'.+\' was not declared in this scope')
+  clang_regex_type_of_retval_or_sole_param = (
+      _CLANG_FILE_LINE_RE +
+      r'error: use of undeclared identifier \'(?P<type>.*)\'\n'
+      r'(.*\n)*?'
+      r'(?P=file):(?P=line):\d+: error: '
+      r'non-friend class member \'Result\' cannot have a qualified name'
+      )
+  clang_regex_type_of_a_param = (
+      _CLANG_FILE_LINE_RE +
+      r'error: C\+\+ requires a type specifier for all declarations\n'
+      r'(.*\n)*?'
+      r'(?P=file):(?P=line):(?P=column): error: '
+      r'C\+\+ requires a type specifier for all declarations'
+      )
+  clang_regex_unknown_type = (
+      _CLANG_FILE_LINE_RE +
+      r'error: unknown type name \'(?P<type>[^\']+)\''
+      )
+
+  diagnosis = """
+In a mock class template, types or typedefs defined in the base class
+template are *not* automatically visible.  This is how C++ works.  Before
+you can use a type or typedef named %(type)s defined in base class Base<T>, you
+need to make it visible.  One way to do it is:
+
+  typedef typename Base<T>::%(type)s %(type)s;"""
+
+  for diag in _GenericDiagnoser(
+      'TTB', 'Type in Template Base',
+      [(gcc_4_3_1_regex_type_in_retval, diagnosis % {'type': 'Foo'}),
+       (gcc_4_4_0_regex_type_in_retval, diagnosis % {'type': 'Foo'}),
+       (gcc_regex_type_of_sole_param, diagnosis),
+       (gcc_regex_type_of_a_param, diagnosis),
+       (clang_regex_type_of_retval_or_sole_param, diagnosis),
+       (clang_regex_type_of_a_param, diagnosis % {'type': 'Foo'})],
+      msg):
+    yield diag
+  # Avoid overlap with the NUS pattern.
+  for m in _FindAllMatches(clang_regex_unknown_type, msg):
+    type_ = m.groupdict()['type']
+    if type_ not in _COMMON_GMOCK_SYMBOLS:
+      yield ('TTB', 'Type in Template Base', diagnosis % m.groupdict())
+
+
+def _WrongMockMethodMacroDiagnoser(msg):
+  """Diagnoses the WMM disease, given the error messages by the compiler."""
+
+  gcc_regex = (_GCC_FILE_LINE_RE +
+               r'.*this_method_does_not_take_(?P<wrong_args>\d+)_argument.*\n'
+               r'.*\n'
+               r'.*candidates are.*FunctionMocker<[^>]+A(?P<args>\d+)\)>')
+  clang_regex = (_CLANG_NON_GMOCK_FILE_LINE_RE +
+                 r'error:.*array.*negative.*r?\n'
+                 r'(.*\n)*?'
+                 r'(?P=file):(?P=line):(?P=column): error: too few arguments '
+                 r'to function call, expected (?P<args>\d+), '
+                 r'have (?P<wrong_args>\d+)')
+  clang11_re = (_CLANG_NON_GMOCK_FILE_LINE_RE +
+                r'.*this_method_does_not_take_'
+                r'(?P<wrong_args>\d+)_argument.*')
+  diagnosis = """
+You are using MOCK_METHOD%(wrong_args)s to define a mock method that has
+%(args)s arguments. Use MOCK_METHOD%(args)s (or MOCK_CONST_METHOD%(args)s,
+MOCK_METHOD%(args)s_T, MOCK_CONST_METHOD%(args)s_T as appropriate) instead."""
+  return _GenericDiagnoser('WMM', 'Wrong MOCK_METHODn Macro',
+                           [(gcc_regex, diagnosis),
+                            (clang11_re, diagnosis % {'wrong_args': 'm',
+                                                      'args': 'n'}),
+                            (clang_regex, diagnosis)],
+                           msg)
+
+
+def _WrongParenPositionDiagnoser(msg):
+  """Diagnoses the WPP disease, given the error messages by the compiler."""
+
+  gcc_regex = (_GCC_FILE_LINE_RE +
+               r'error:.*testing::internal::MockSpec<.* has no member named \''
+               r'(?P<method>\w+)\'')
+  clang_regex = (_CLANG_NON_GMOCK_FILE_LINE_RE +
+                 r'error: no member named \'(?P<method>\w+)\' in '
+                 r'\'testing::internal::MockSpec<.*>\'')
+  diagnosis = """
+The closing parenthesis of ON_CALL or EXPECT_CALL should be *before*
+".%(method)s".  For example, you should write:
+  EXPECT_CALL(my_mock, Foo(_)).%(method)s(...);
+instead of:
+  EXPECT_CALL(my_mock, Foo(_).%(method)s(...));"""
+  return _GenericDiagnoser('WPP', 'Wrong Parenthesis Position',
+                           [(gcc_regex, diagnosis),
+                            (clang_regex, diagnosis)],
+                           msg)
+
+
+_DIAGNOSERS = [
+    _IncompleteByReferenceArgumentDiagnoser,
+    _MockObjectPointerDiagnoser,
+    _NeedToReturnNothingDiagnoser,
+    _NeedToReturnReferenceDiagnoser,
+    _NeedToReturnSomethingDiagnoser,
+    _NeedToUseReturnNullDiagnoser,
+    _NeedToUseSymbolDiagnoser,
+    _OverloadedFunctionActionDiagnoser,
+    _OverloadedFunctionMatcherDiagnoser,
+    _OverloadedMethodActionDiagnoser,
+    _TypeInTemplatedBaseDiagnoser,
+    _WrongMockMethodMacroDiagnoser,
+    _WrongParenPositionDiagnoser,
+    ]
+
+
+def Diagnose(msg):
+  """Generates all possible diagnoses given the compiler error message."""
+
+  msg = re.sub(r'\x1b\[[^m]*m', '', msg)  # Strips all color formatting.
+  # Assuming the string is using the UTF-8 encoding, replaces the left and
+  # the right single quote characters with apostrophes.
+  msg = re.sub(r'(\xe2\x80\x98|\xe2\x80\x99)', "'", msg)
+
+  diagnoses = []
+  for diagnoser in _DIAGNOSERS:
+    for diag in diagnoser(msg):
+      diagnosis = '[%s - %s]\n%s' % diag
+      if not diagnosis in diagnoses:
+        diagnoses.append(diagnosis)
+  return diagnoses
+
+
+def main():
+  print ('Google Mock Doctor v%s - '
+         'diagnoses problems in code using Google Mock.' % _VERSION)
+
+  if sys.stdin.isatty():
+    print ('Please copy and paste the compiler errors here.  Press c-D when '
+           'you are done:')
+  else:
+    print ('Waiting for compiler errors on stdin . . .')
+
+  msg = sys.stdin.read().strip()
+  diagnoses = Diagnose(msg)
+  count = len(diagnoses)
+  if not count:
+    print ("""
+Your compiler complained:
+8<------------------------------------------------------------
+%s
+------------------------------------------------------------>8
+
+Uh-oh, I'm not smart enough to figure out what the problem is. :-(
+However...
+If you send your source code and the compiler's error messages to
+%s, you can be helped and I can get smarter --
+win-win for us!""" % (msg, _EMAIL))
+  else:
+    print ('------------------------------------------------------------')
+    print ('Your code appears to have the following',)
+    if count > 1:
+      print ('%s diseases:' % (count,))
+    else:
+      print ('disease:')
+    i = 0
+    for d in diagnoses:
+      i += 1
+      if count > 1:
+        print ('\n#%s:' % (i,))
+      print (d)
+    print ("""
+How did I do?  If you think I'm wrong or unhelpful, please send your
+source code and the compiler's error messages to %s.
+Then you can be helped and I can get smarter -- I promise I won't be upset!""" %
+           _EMAIL)
+
+
+if __name__ == '__main__':
+  main()
diff --git a/third_party/googletest/googlemock/scripts/upload.py b/third_party/googletest/googlemock/scripts/upload.py
new file mode 100755
index 0000000..6e6f9a1
--- /dev/null
+++ b/third_party/googletest/googlemock/scripts/upload.py
@@ -0,0 +1,1387 @@
+#!/usr/bin/env python
+#
+# Copyright 2007 Google Inc.
+#
+# 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.
+
+"""Tool for uploading diffs from a version control system to the codereview app.
+
+Usage summary: upload.py [options] [-- diff_options]
+
+Diff options are passed to the diff command of the underlying system.
+
+Supported version control systems:
+  Git
+  Mercurial
+  Subversion
+
+It is important for Git/Mercurial users to specify a tree/node/branch to diff
+against by using the '--rev' option.
+"""
+# This code is derived from appcfg.py in the App Engine SDK (open source),
+# and from ASPN recipe #146306.
+
+import cookielib
+import getpass
+import logging
+import md5
+import mimetypes
+import optparse
+import os
+import re
+import socket
+import subprocess
+import sys
+import urllib
+import urllib2
+import urlparse
+
+try:
+  import readline
+except ImportError:
+  pass
+
+# The logging verbosity:
+#  0: Errors only.
+#  1: Status messages.
+#  2: Info logs.
+#  3: Debug logs.
+verbosity = 1
+
+# Max size of patch or base file.
+MAX_UPLOAD_SIZE = 900 * 1024
+
+
+def GetEmail(prompt):
+  """Prompts the user for their email address and returns it.
+
+  The last used email address is saved to a file and offered up as a suggestion
+  to the user. If the user presses enter without typing in anything the last
+  used email address is used. If the user enters a new address, it is saved
+  for next time we prompt.
+
+  """
+  last_email_file_name = os.path.expanduser("~/.last_codereview_email_address")
+  last_email = ""
+  if os.path.exists(last_email_file_name):
+    try:
+      last_email_file = open(last_email_file_name, "r")
+      last_email = last_email_file.readline().strip("\n")
+      last_email_file.close()
+      prompt += " [%s]" % last_email
+    except IOError, e:
+      pass
+  email = raw_input(prompt + ": ").strip()
+  if email:
+    try:
+      last_email_file = open(last_email_file_name, "w")
+      last_email_file.write(email)
+      last_email_file.close()
+    except IOError, e:
+      pass
+  else:
+    email = last_email
+  return email
+
+
+def StatusUpdate(msg):
+  """Print a status message to stdout.
+
+  If 'verbosity' is greater than 0, print the message.
+
+  Args:
+    msg: The string to print.
+  """
+  if verbosity > 0:
+    print msg
+
+
+def ErrorExit(msg):
+  """Print an error message to stderr and exit."""
+  print >>sys.stderr, msg
+  sys.exit(1)
+
+
+class ClientLoginError(urllib2.HTTPError):
+  """Raised to indicate there was an error authenticating with ClientLogin."""
+
+  def __init__(self, url, code, msg, headers, args):
+    urllib2.HTTPError.__init__(self, url, code, msg, headers, None)
+    self.args = args
+    self.reason = args["Error"]
+
+
+class AbstractRpcServer(object):
+  """Provides a common interface for a simple RPC server."""
+
+  def __init__(self, host, auth_function, host_override=None, extra_headers={},
+               save_cookies=False):
+    """Creates a new HttpRpcServer.
+
+    Args:
+      host: The host to send requests to.
+      auth_function: A function that takes no arguments and returns an
+        (email, password) tuple when called. Will be called if authentication
+        is required.
+      host_override: The host header to send to the server (defaults to host).
+      extra_headers: A dict of extra headers to append to every request.
+      save_cookies: If True, save the authentication cookies to local disk.
+        If False, use an in-memory cookiejar instead.  Subclasses must
+        implement this functionality.  Defaults to False.
+    """
+    self.host = host
+    self.host_override = host_override
+    self.auth_function = auth_function
+    self.authenticated = False
+    self.extra_headers = extra_headers
+    self.save_cookies = save_cookies
+    self.opener = self._GetOpener()
+    if self.host_override:
+      logging.info("Server: %s; Host: %s", self.host, self.host_override)
+    else:
+      logging.info("Server: %s", self.host)
+
+  def _GetOpener(self):
+    """Returns an OpenerDirector for making HTTP requests.
+
+    Returns:
+      A urllib2.OpenerDirector object.
+    """
+    raise NotImplementedError()
+
+  def _CreateRequest(self, url, data=None):
+    """Creates a new urllib request."""
+    logging.debug("Creating request for: '%s' with payload:\n%s", url, data)
+    req = urllib2.Request(url, data=data)
+    if self.host_override:
+      req.add_header("Host", self.host_override)
+    for key, value in self.extra_headers.iteritems():
+      req.add_header(key, value)
+    return req
+
+  def _GetAuthToken(self, email, password):
+    """Uses ClientLogin to authenticate the user, returning an auth token.
+
+    Args:
+      email:    The user's email address
+      password: The user's password
+
+    Raises:
+      ClientLoginError: If there was an error authenticating with ClientLogin.
+      HTTPError: If there was some other form of HTTP error.
+
+    Returns:
+      The authentication token returned by ClientLogin.
+    """
+    account_type = "GOOGLE"
+    if self.host.endswith(".google.com"):
+      # Needed for use inside Google.
+      account_type = "HOSTED"
+    req = self._CreateRequest(
+        url="https://www.google.com/accounts/ClientLogin",
+        data=urllib.urlencode({
+            "Email": email,
+            "Passwd": password,
+            "service": "ah",
+            "source": "rietveld-codereview-upload",
+            "accountType": account_type,
+        }),
+    )
+    try:
+      response = self.opener.open(req)
+      response_body = response.read()
+      response_dict = dict(x.split("=")
+                           for x in response_body.split("\n") if x)
+      return response_dict["Auth"]
+    except urllib2.HTTPError, e:
+      if e.code == 403:
+        body = e.read()
+        response_dict = dict(x.split("=", 1) for x in body.split("\n") if x)
+        raise ClientLoginError(req.get_full_url(), e.code, e.msg,
+                               e.headers, response_dict)
+      else:
+        raise
+
+  def _GetAuthCookie(self, auth_token):
+    """Fetches authentication cookies for an authentication token.
+
+    Args:
+      auth_token: The authentication token returned by ClientLogin.
+
+    Raises:
+      HTTPError: If there was an error fetching the authentication cookies.
+    """
+    # This is a dummy value to allow us to identify when we're successful.
+    continue_location = "http://localhost/"
+    args = {"continue": continue_location, "auth": auth_token}
+    req = self._CreateRequest("http://%s/_ah/login?%s" %
+                              (self.host, urllib.urlencode(args)))
+    try:
+      response = self.opener.open(req)
+    except urllib2.HTTPError, e:
+      response = e
+    if (response.code != 302 or
+        response.info()["location"] != continue_location):
+      raise urllib2.HTTPError(req.get_full_url(), response.code, response.msg,
+                              response.headers, response.fp)
+    self.authenticated = True
+
+  def _Authenticate(self):
+    """Authenticates the user.
+
+    The authentication process works as follows:
+     1) We get a username and password from the user
+     2) We use ClientLogin to obtain an AUTH token for the user
+        (see http://code.google.com/apis/accounts/AuthForInstalledApps.html).
+     3) We pass the auth token to /_ah/login on the server to obtain an
+        authentication cookie. If login was successful, it tries to redirect
+        us to the URL we provided.
+
+    If we attempt to access the upload API without first obtaining an
+    authentication cookie, it returns a 401 response and directs us to
+    authenticate ourselves with ClientLogin.
+    """
+    for i in range(3):
+      credentials = self.auth_function()
+      try:
+        auth_token = self._GetAuthToken(credentials[0], credentials[1])
+      except ClientLoginError, e:
+        if e.reason == "BadAuthentication":
+          print >>sys.stderr, "Invalid username or password."
+          continue
+        if e.reason == "CaptchaRequired":
+          print >>sys.stderr, (
+              "Please go to\n"
+              "https://www.google.com/accounts/DisplayUnlockCaptcha\n"
+              "and verify you are a human.  Then try again.")
+          break
+        if e.reason == "NotVerified":
+          print >>sys.stderr, "Account not verified."
+          break
+        if e.reason == "TermsNotAgreed":
+          print >>sys.stderr, "User has not agreed to TOS."
+          break
+        if e.reason == "AccountDeleted":
+          print >>sys.stderr, "The user account has been deleted."
+          break
+        if e.reason == "AccountDisabled":
+          print >>sys.stderr, "The user account has been disabled."
+          break
+        if e.reason == "ServiceDisabled":
+          print >>sys.stderr, ("The user's access to the service has been "
+                               "disabled.")
+          break
+        if e.reason == "ServiceUnavailable":
+          print >>sys.stderr, "The service is not available; try again later."
+          break
+        raise
+      self._GetAuthCookie(auth_token)
+      return
+
+  def Send(self, request_path, payload=None,
+           content_type="application/octet-stream",
+           timeout=None,
+           **kwargs):
+    """Sends an RPC and returns the response.
+
+    Args:
+      request_path: The path to send the request to, eg /api/appversion/create.
+      payload: The body of the request, or None to send an empty request.
+      content_type: The Content-Type header to use.
+      timeout: timeout in seconds; default None i.e. no timeout.
+        (Note: for large requests on OS X, the timeout doesn't work right.)
+      kwargs: Any keyword arguments are converted into query string parameters.
+
+    Returns:
+      The response body, as a string.
+    """
+    # TODO: Don't require authentication.  Let the server say
+    # whether it is necessary.
+    if not self.authenticated:
+      self._Authenticate()
+
+    old_timeout = socket.getdefaulttimeout()
+    socket.setdefaulttimeout(timeout)
+    try:
+      tries = 0
+      while True:
+        tries += 1
+        args = dict(kwargs)
+        url = "http://%s%s" % (self.host, request_path)
+        if args:
+          url += "?" + urllib.urlencode(args)
+        req = self._CreateRequest(url=url, data=payload)
+        req.add_header("Content-Type", content_type)
+        try:
+          f = self.opener.open(req)
+          response = f.read()
+          f.close()
+          return response
+        except urllib2.HTTPError, e:
+          if tries > 3:
+            raise
+          elif e.code == 401:
+            self._Authenticate()
+##           elif e.code >= 500 and e.code < 600:
+##             # Server Error - try again.
+##             continue
+          else:
+            raise
+    finally:
+      socket.setdefaulttimeout(old_timeout)
+
+
+class HttpRpcServer(AbstractRpcServer):
+  """Provides a simplified RPC-style interface for HTTP requests."""
+
+  def _Authenticate(self):
+    """Save the cookie jar after authentication."""
+    super(HttpRpcServer, self)._Authenticate()
+    if self.save_cookies:
+      StatusUpdate("Saving authentication cookies to %s" % self.cookie_file)
+      self.cookie_jar.save()
+
+  def _GetOpener(self):
+    """Returns an OpenerDirector that supports cookies and ignores redirects.
+
+    Returns:
+      A urllib2.OpenerDirector object.
+    """
+    opener = urllib2.OpenerDirector()
+    opener.add_handler(urllib2.ProxyHandler())
+    opener.add_handler(urllib2.UnknownHandler())
+    opener.add_handler(urllib2.HTTPHandler())
+    opener.add_handler(urllib2.HTTPDefaultErrorHandler())
+    opener.add_handler(urllib2.HTTPSHandler())
+    opener.add_handler(urllib2.HTTPErrorProcessor())
+    if self.save_cookies:
+      self.cookie_file = os.path.expanduser("~/.codereview_upload_cookies")
+      self.cookie_jar = cookielib.MozillaCookieJar(self.cookie_file)
+      if os.path.exists(self.cookie_file):
+        try:
+          self.cookie_jar.load()
+          self.authenticated = True
+          StatusUpdate("Loaded authentication cookies from %s" %
+                       self.cookie_file)
+        except (cookielib.LoadError, IOError):
+          # Failed to load cookies - just ignore them.
+          pass
+      else:
+        # Create an empty cookie file with mode 600
+        fd = os.open(self.cookie_file, os.O_CREAT, 0600)
+        os.close(fd)
+      # Always chmod the cookie file
+      os.chmod(self.cookie_file, 0600)
+    else:
+      # Don't save cookies across runs of update.py.
+      self.cookie_jar = cookielib.CookieJar()
+    opener.add_handler(urllib2.HTTPCookieProcessor(self.cookie_jar))
+    return opener
+
+
+parser = optparse.OptionParser(usage="%prog [options] [-- diff_options]")
+parser.add_option("-y", "--assume_yes", action="store_true",
+                  dest="assume_yes", default=False,
+                  help="Assume that the answer to yes/no questions is 'yes'.")
+# Logging
+group = parser.add_option_group("Logging options")
+group.add_option("-q", "--quiet", action="store_const", const=0,
+                 dest="verbose", help="Print errors only.")
+group.add_option("-v", "--verbose", action="store_const", const=2,
+                 dest="verbose", default=1,
+                 help="Print info level logs (default).")
+group.add_option("--noisy", action="store_const", const=3,
+                 dest="verbose", help="Print all logs.")
+# Review server
+group = parser.add_option_group("Review server options")
+group.add_option("-s", "--server", action="store", dest="server",
+                 default="codereview.appspot.com",
+                 metavar="SERVER",
+                 help=("The server to upload to. The format is host[:port]. "
+                       "Defaults to 'codereview.appspot.com'."))
+group.add_option("-e", "--email", action="store", dest="email",
+                 metavar="EMAIL", default=None,
+                 help="The username to use. Will prompt if omitted.")
+group.add_option("-H", "--host", action="store", dest="host",
+                 metavar="HOST", default=None,
+                 help="Overrides the Host header sent with all RPCs.")
+group.add_option("--no_cookies", action="store_false",
+                 dest="save_cookies", default=True,
+                 help="Do not save authentication cookies to local disk.")
+# Issue
+group = parser.add_option_group("Issue options")
+group.add_option("-d", "--description", action="store", dest="description",
+                 metavar="DESCRIPTION", default=None,
+                 help="Optional description when creating an issue.")
+group.add_option("-f", "--description_file", action="store",
+                 dest="description_file", metavar="DESCRIPTION_FILE",
+                 default=None,
+                 help="Optional path of a file that contains "
+                      "the description when creating an issue.")
+group.add_option("-r", "--reviewers", action="store", dest="reviewers",
+                 metavar="REVIEWERS", default=None,
+                 help="Add reviewers (comma separated email addresses).")
+group.add_option("--cc", action="store", dest="cc",
+                 metavar="CC", default=None,
+                 help="Add CC (comma separated email addresses).")
+# Upload options
+group = parser.add_option_group("Patch options")
+group.add_option("-m", "--message", action="store", dest="message",
+                 metavar="MESSAGE", default=None,
+                 help="A message to identify the patch. "
+                      "Will prompt if omitted.")
+group.add_option("-i", "--issue", type="int", action="store",
+                 metavar="ISSUE", default=None,
+                 help="Issue number to which to add. Defaults to new issue.")
+group.add_option("--download_base", action="store_true",
+                 dest="download_base", default=False,
+                 help="Base files will be downloaded by the server "
+                 "(side-by-side diffs may not work on files with CRs).")
+group.add_option("--rev", action="store", dest="revision",
+                 metavar="REV", default=None,
+                 help="Branch/tree/revision to diff against (used by DVCS).")
+group.add_option("--send_mail", action="store_true",
+                 dest="send_mail", default=False,
+                 help="Send notification email to reviewers.")
+
+
+def GetRpcServer(options):
+  """Returns an instance of an AbstractRpcServer.
+
+  Returns:
+    A new AbstractRpcServer, on which RPC calls can be made.
+  """
+
+  rpc_server_class = HttpRpcServer
+
+  def GetUserCredentials():
+    """Prompts the user for a username and password."""
+    email = options.email
+    if email is None:
+      email = GetEmail("Email (login for uploading to %s)" % options.server)
+    password = getpass.getpass("Password for %s: " % email)
+    return (email, password)
+
+  # If this is the dev_appserver, use fake authentication.
+  host = (options.host or options.server).lower()
+  if host == "localhost" or host.startswith("localhost:"):
+    email = options.email
+    if email is None:
+      email = "test@example.com"
+      logging.info("Using debug user %s.  Override with --email" % email)
+    server = rpc_server_class(
+        options.server,
+        lambda: (email, "password"),
+        host_override=options.host,
+        extra_headers={"Cookie":
+                       'dev_appserver_login="%s:False"' % email},
+        save_cookies=options.save_cookies)
+    # Don't try to talk to ClientLogin.
+    server.authenticated = True
+    return server
+
+  return rpc_server_class(options.server, GetUserCredentials,
+                          host_override=options.host,
+                          save_cookies=options.save_cookies)
+
+
+def EncodeMultipartFormData(fields, files):
+  """Encode form fields for multipart/form-data.
+
+  Args:
+    fields: A sequence of (name, value) elements for regular form fields.
+    files: A sequence of (name, filename, value) elements for data to be
+           uploaded as files.
+  Returns:
+    (content_type, body) ready for httplib.HTTP instance.
+
+  Source:
+    http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/146306
+  """
+  BOUNDARY = '-M-A-G-I-C---B-O-U-N-D-A-R-Y-'
+  CRLF = '\r\n'
+  lines = []
+  for (key, value) in fields:
+    lines.append('--' + BOUNDARY)
+    lines.append('Content-Disposition: form-data; name="%s"' % key)
+    lines.append('')
+    lines.append(value)
+  for (key, filename, value) in files:
+    lines.append('--' + BOUNDARY)
+    lines.append('Content-Disposition: form-data; name="%s"; filename="%s"' %
+             (key, filename))
+    lines.append('Content-Type: %s' % GetContentType(filename))
+    lines.append('')
+    lines.append(value)
+  lines.append('--' + BOUNDARY + '--')
+  lines.append('')
+  body = CRLF.join(lines)
+  content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
+  return content_type, body
+
+
+def GetContentType(filename):
+  """Helper to guess the content-type from the filename."""
+  return mimetypes.guess_type(filename)[0] or 'application/octet-stream'
+
+
+# Use a shell for subcommands on Windows to get a PATH search.
+use_shell = sys.platform.startswith("win")
+
+def RunShellWithReturnCode(command, print_output=False,
+                           universal_newlines=True):
+  """Executes a command and returns the output from stdout and the return code.
+
+  Args:
+    command: Command to execute.
+    print_output: If True, the output is printed to stdout.
+                  If False, both stdout and stderr are ignored.
+    universal_newlines: Use universal_newlines flag (default: True).
+
+  Returns:
+    Tuple (output, return code)
+  """
+  logging.info("Running %s", command)
+  p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+                       shell=use_shell, universal_newlines=universal_newlines)
+  if print_output:
+    output_array = []
+    while True:
+      line = p.stdout.readline()
+      if not line:
+        break
+      print line.strip("\n")
+      output_array.append(line)
+    output = "".join(output_array)
+  else:
+    output = p.stdout.read()
+  p.wait()
+  errout = p.stderr.read()
+  if print_output and errout:
+    print >>sys.stderr, errout
+  p.stdout.close()
+  p.stderr.close()
+  return output, p.returncode
+
+
+def RunShell(command, silent_ok=False, universal_newlines=True,
+             print_output=False):
+  data, retcode = RunShellWithReturnCode(command, print_output,
+                                         universal_newlines)
+  if retcode:
+    ErrorExit("Got error status from %s:\n%s" % (command, data))
+  if not silent_ok and not data:
+    ErrorExit("No output from %s" % command)
+  return data
+
+
+class VersionControlSystem(object):
+  """Abstract base class providing an interface to the VCS."""
+
+  def __init__(self, options):
+    """Constructor.
+
+    Args:
+      options: Command line options.
+    """
+    self.options = options
+
+  def GenerateDiff(self, args):
+    """Return the current diff as a string.
+
+    Args:
+      args: Extra arguments to pass to the diff command.
+    """
+    raise NotImplementedError(
+        "abstract method -- subclass %s must override" % self.__class__)
+
+  def GetUnknownFiles(self):
+    """Return a list of files unknown to the VCS."""
+    raise NotImplementedError(
+        "abstract method -- subclass %s must override" % self.__class__)
+
+  def CheckForUnknownFiles(self):
+    """Show an "are you sure?" prompt if there are unknown files."""
+    unknown_files = self.GetUnknownFiles()
+    if unknown_files:
+      print "The following files are not added to version control:"
+      for line in unknown_files:
+        print line
+      prompt = "Are you sure to continue?(y/N) "
+      answer = raw_input(prompt).strip()
+      if answer != "y":
+        ErrorExit("User aborted")
+
+  def GetBaseFile(self, filename):
+    """Get the content of the upstream version of a file.
+
+    Returns:
+      A tuple (base_content, new_content, is_binary, status)
+        base_content: The contents of the base file.
+        new_content: For text files, this is empty.  For binary files, this is
+          the contents of the new file, since the diff output won't contain
+          information to reconstruct the current file.
+        is_binary: True iff the file is binary.
+        status: The status of the file.
+    """
+
+    raise NotImplementedError(
+        "abstract method -- subclass %s must override" % self.__class__)
+
+
+  def GetBaseFiles(self, diff):
+    """Helper that calls GetBase file for each file in the patch.
+
+    Returns:
+      A dictionary that maps from filename to GetBaseFile's tuple.  Filenames
+      are retrieved based on lines that start with "Index:" or
+      "Property changes on:".
+    """
+    files = {}
+    for line in diff.splitlines(True):
+      if line.startswith('Index:') or line.startswith('Property changes on:'):
+        unused, filename = line.split(':', 1)
+        # On Windows if a file has property changes its filename uses '\'
+        # instead of '/'.
+        filename = filename.strip().replace('\\', '/')
+        files[filename] = self.GetBaseFile(filename)
+    return files
+
+
+  def UploadBaseFiles(self, issue, rpc_server, patch_list, patchset, options,
+                      files):
+    """Uploads the base files (and if necessary, the current ones as well)."""
+
+    def UploadFile(filename, file_id, content, is_binary, status, is_base):
+      """Uploads a file to the server."""
+      file_too_large = False
+      if is_base:
+        type = "base"
+      else:
+        type = "current"
+      if len(content) > MAX_UPLOAD_SIZE:
+        print ("Not uploading the %s file for %s because it's too large." %
+               (type, filename))
+        file_too_large = True
+        content = ""
+      checksum = md5.new(content).hexdigest()
+      if options.verbose > 0 and not file_too_large:
+        print "Uploading %s file for %s" % (type, filename)
+      url = "/%d/upload_content/%d/%d" % (int(issue), int(patchset), file_id)
+      form_fields = [("filename", filename),
+                     ("status", status),
+                     ("checksum", checksum),
+                     ("is_binary", str(is_binary)),
+                     ("is_current", str(not is_base)),
+                    ]
+      if file_too_large:
+        form_fields.append(("file_too_large", "1"))
+      if options.email:
+        form_fields.append(("user", options.email))
+      ctype, body = EncodeMultipartFormData(form_fields,
+                                            [("data", filename, content)])
+      response_body = rpc_server.Send(url, body,
+                                      content_type=ctype)
+      if not response_body.startswith("OK"):
+        StatusUpdate("  --> %s" % response_body)
+        sys.exit(1)
+
+    patches = dict()
+    [patches.setdefault(v, k) for k, v in patch_list]
+    for filename in patches.keys():
+      base_content, new_content, is_binary, status = files[filename]
+      file_id_str = patches.get(filename)
+      if file_id_str.find("nobase") != -1:
+        base_content = None
+        file_id_str = file_id_str[file_id_str.rfind("_") + 1:]
+      file_id = int(file_id_str)
+      if base_content != None:
+        UploadFile(filename, file_id, base_content, is_binary, status, True)
+      if new_content != None:
+        UploadFile(filename, file_id, new_content, is_binary, status, False)
+
+  def IsImage(self, filename):
+    """Returns true if the filename has an image extension."""
+    mimetype =  mimetypes.guess_type(filename)[0]
+    if not mimetype:
+      return False
+    return mimetype.startswith("image/")
+
+
+class SubversionVCS(VersionControlSystem):
+  """Implementation of the VersionControlSystem interface for Subversion."""
+
+  def __init__(self, options):
+    super(SubversionVCS, self).__init__(options)
+    if self.options.revision:
+      match = re.match(r"(\d+)(:(\d+))?", self.options.revision)
+      if not match:
+        ErrorExit("Invalid Subversion revision %s." % self.options.revision)
+      self.rev_start = match.group(1)
+      self.rev_end = match.group(3)
+    else:
+      self.rev_start = self.rev_end = None
+    # Cache output from "svn list -r REVNO dirname".
+    # Keys: dirname, Values: 2-tuple (ouput for start rev and end rev).
+    self.svnls_cache = {}
+    # SVN base URL is required to fetch files deleted in an older revision.
+    # Result is cached to not guess it over and over again in GetBaseFile().
+    required = self.options.download_base or self.options.revision is not None
+    self.svn_base = self._GuessBase(required)
+
+  def GuessBase(self, required):
+    """Wrapper for _GuessBase."""
+    return self.svn_base
+
+  def _GuessBase(self, required):
+    """Returns the SVN base URL.
+
+    Args:
+      required: If true, exits if the url can't be guessed, otherwise None is
+        returned.
+    """
+    info = RunShell(["svn", "info"])
+    for line in info.splitlines():
+      words = line.split()
+      if len(words) == 2 and words[0] == "URL:":
+        url = words[1]
+        scheme, netloc, path, params, query, fragment = urlparse.urlparse(url)
+        username, netloc = urllib.splituser(netloc)
+        if username:
+          logging.info("Removed username from base URL")
+        if netloc.endswith("svn.python.org"):
+          if netloc == "svn.python.org":
+            if path.startswith("/projects/"):
+              path = path[9:]
+          elif netloc != "pythondev@svn.python.org":
+            ErrorExit("Unrecognized Python URL: %s" % url)
+          base = "http://svn.python.org/view/*checkout*%s/" % path
+          logging.info("Guessed Python base = %s", base)
+        elif netloc.endswith("svn.collab.net"):
+          if path.startswith("/repos/"):
+            path = path[6:]
+          base = "http://svn.collab.net/viewvc/*checkout*%s/" % path
+          logging.info("Guessed CollabNet base = %s", base)
+        elif netloc.endswith(".googlecode.com"):
+          path = path + "/"
+          base = urlparse.urlunparse(("http", netloc, path, params,
+                                      query, fragment))
+          logging.info("Guessed Google Code base = %s", base)
+        else:
+          path = path + "/"
+          base = urlparse.urlunparse((scheme, netloc, path, params,
+                                      query, fragment))
+          logging.info("Guessed base = %s", base)
+        return base
+    if required:
+      ErrorExit("Can't find URL in output from svn info")
+    return None
+
+  def GenerateDiff(self, args):
+    cmd = ["svn", "diff"]
+    if self.options.revision:
+      cmd += ["-r", self.options.revision]
+    cmd.extend(args)
+    data = RunShell(cmd)
+    count = 0
+    for line in data.splitlines():
+      if line.startswith("Index:") or line.startswith("Property changes on:"):
+        count += 1
+        logging.info(line)
+    if not count:
+      ErrorExit("No valid patches found in output from svn diff")
+    return data
+
+  def _CollapseKeywords(self, content, keyword_str):
+    """Collapses SVN keywords."""
+    # svn cat translates keywords but svn diff doesn't. As a result of this
+    # behavior patching.PatchChunks() fails with a chunk mismatch error.
+    # This part was originally written by the Review Board development team
+    # who had the same problem (http://reviews.review-board.org/r/276/).
+    # Mapping of keywords to known aliases
+    svn_keywords = {
+      # Standard keywords
+      'Date':                ['Date', 'LastChangedDate'],
+      'Revision':            ['Revision', 'LastChangedRevision', 'Rev'],
+      'Author':              ['Author', 'LastChangedBy'],
+      'HeadURL':             ['HeadURL', 'URL'],
+      'Id':                  ['Id'],
+
+      # Aliases
+      'LastChangedDate':     ['LastChangedDate', 'Date'],
+      'LastChangedRevision': ['LastChangedRevision', 'Rev', 'Revision'],
+      'LastChangedBy':       ['LastChangedBy', 'Author'],
+      'URL':                 ['URL', 'HeadURL'],
+    }
+
+    def repl(m):
+       if m.group(2):
+         return "$%s::%s$" % (m.group(1), " " * len(m.group(3)))
+       return "$%s$" % m.group(1)
+    keywords = [keyword
+                for name in keyword_str.split(" ")
+                for keyword in svn_keywords.get(name, [])]
+    return re.sub(r"\$(%s):(:?)([^\$]+)\$" % '|'.join(keywords), repl, content)
+
+  def GetUnknownFiles(self):
+    status = RunShell(["svn", "status", "--ignore-externals"], silent_ok=True)
+    unknown_files = []
+    for line in status.split("\n"):
+      if line and line[0] == "?":
+        unknown_files.append(line)
+    return unknown_files
+
+  def ReadFile(self, filename):
+    """Returns the contents of a file."""
+    file = open(filename, 'rb')
+    result = ""
+    try:
+      result = file.read()
+    finally:
+      file.close()
+    return result
+
+  def GetStatus(self, filename):
+    """Returns the status of a file."""
+    if not self.options.revision:
+      status = RunShell(["svn", "status", "--ignore-externals", filename])
+      if not status:
+        ErrorExit("svn status returned no output for %s" % filename)
+      status_lines = status.splitlines()
+      # If file is in a cl, the output will begin with
+      # "\n--- Changelist 'cl_name':\n".  See
+      # http://svn.collab.net/repos/svn/trunk/notes/changelist-design.txt
+      if (len(status_lines) == 3 and
+          not status_lines[0] and
+          status_lines[1].startswith("--- Changelist")):
+        status = status_lines[2]
+      else:
+        status = status_lines[0]
+    # If we have a revision to diff against we need to run "svn list"
+    # for the old and the new revision and compare the results to get
+    # the correct status for a file.
+    else:
+      dirname, relfilename = os.path.split(filename)
+      if dirname not in self.svnls_cache:
+        cmd = ["svn", "list", "-r", self.rev_start, dirname or "."]
+        out, returncode = RunShellWithReturnCode(cmd)
+        if returncode:
+          ErrorExit("Failed to get status for %s." % filename)
+        old_files = out.splitlines()
+        args = ["svn", "list"]
+        if self.rev_end:
+          args += ["-r", self.rev_end]
+        cmd = args + [dirname or "."]
+        out, returncode = RunShellWithReturnCode(cmd)
+        if returncode:
+          ErrorExit("Failed to run command %s" % cmd)
+        self.svnls_cache[dirname] = (old_files, out.splitlines())
+      old_files, new_files = self.svnls_cache[dirname]
+      if relfilename in old_files and relfilename not in new_files:
+        status = "D   "
+      elif relfilename in old_files and relfilename in new_files:
+        status = "M   "
+      else:
+        status = "A   "
+    return status
+
+  def GetBaseFile(self, filename):
+    status = self.GetStatus(filename)
+    base_content = None
+    new_content = None
+
+    # If a file is copied its status will be "A  +", which signifies
+    # "addition-with-history".  See "svn st" for more information.  We need to
+    # upload the original file or else diff parsing will fail if the file was
+    # edited.
+    if status[0] == "A" and status[3] != "+":
+      # We'll need to upload the new content if we're adding a binary file
+      # since diff's output won't contain it.
+      mimetype = RunShell(["svn", "propget", "svn:mime-type", filename],
+                          silent_ok=True)
+      base_content = ""
+      is_binary = mimetype and not mimetype.startswith("text/")
+      if is_binary and self.IsImage(filename):
+        new_content = self.ReadFile(filename)
+    elif (status[0] in ("M", "D", "R") or
+          (status[0] == "A" and status[3] == "+") or  # Copied file.
+          (status[0] == " " and status[1] == "M")):  # Property change.
+      args = []
+      if self.options.revision:
+        url = "%s/%s@%s" % (self.svn_base, filename, self.rev_start)
+      else:
+        # Don't change filename, it's needed later.
+        url = filename
+        args += ["-r", "BASE"]
+      cmd = ["svn"] + args + ["propget", "svn:mime-type", url]
+      mimetype, returncode = RunShellWithReturnCode(cmd)
+      if returncode:
+        # File does not exist in the requested revision.
+        # Reset mimetype, it contains an error message.
+        mimetype = ""
+      get_base = False
+      is_binary = mimetype and not mimetype.startswith("text/")
+      if status[0] == " ":
+        # Empty base content just to force an upload.
+        base_content = ""
+      elif is_binary:
+        if self.IsImage(filename):
+          get_base = True
+          if status[0] == "M":
+            if not self.rev_end:
+              new_content = self.ReadFile(filename)
+            else:
+              url = "%s/%s@%s" % (self.svn_base, filename, self.rev_end)
+              new_content = RunShell(["svn", "cat", url],
+                                     universal_newlines=True, silent_ok=True)
+        else:
+          base_content = ""
+      else:
+        get_base = True
+
+      if get_base:
+        if is_binary:
+          universal_newlines = False
+        else:
+          universal_newlines = True
+        if self.rev_start:
+          # "svn cat -r REV delete_file.txt" doesn't work. cat requires
+          # the full URL with "@REV" appended instead of using "-r" option.
+          url = "%s/%s@%s" % (self.svn_base, filename, self.rev_start)
+          base_content = RunShell(["svn", "cat", url],
+                                  universal_newlines=universal_newlines,
+                                  silent_ok=True)
+        else:
+          base_content = RunShell(["svn", "cat", filename],
+                                  universal_newlines=universal_newlines,
+                                  silent_ok=True)
+        if not is_binary:
+          args = []
+          if self.rev_start:
+            url = "%s/%s@%s" % (self.svn_base, filename, self.rev_start)
+          else:
+            url = filename
+            args += ["-r", "BASE"]
+          cmd = ["svn"] + args + ["propget", "svn:keywords", url]
+          keywords, returncode = RunShellWithReturnCode(cmd)
+          if keywords and not returncode:
+            base_content = self._CollapseKeywords(base_content, keywords)
+    else:
+      StatusUpdate("svn status returned unexpected output: %s" % status)
+      sys.exit(1)
+    return base_content, new_content, is_binary, status[0:5]
+
+
+class GitVCS(VersionControlSystem):
+  """Implementation of the VersionControlSystem interface for Git."""
+
+  def __init__(self, options):
+    super(GitVCS, self).__init__(options)
+    # Map of filename -> hash of base file.
+    self.base_hashes = {}
+
+  def GenerateDiff(self, extra_args):
+    # This is more complicated than svn's GenerateDiff because we must convert
+    # the diff output to include an svn-style "Index:" line as well as record
+    # the hashes of the base files, so we can upload them along with our diff.
+    if self.options.revision:
+      extra_args = [self.options.revision] + extra_args
+    gitdiff = RunShell(["git", "diff", "--full-index"] + extra_args)
+    svndiff = []
+    filecount = 0
+    filename = None
+    for line in gitdiff.splitlines():
+      match = re.match(r"diff --git a/(.*) b/.*$", line)
+      if match:
+        filecount += 1
+        filename = match.group(1)
+        svndiff.append("Index: %s\n" % filename)
+      else:
+        # The "index" line in a git diff looks like this (long hashes elided):
+        #   index 82c0d44..b2cee3f 100755
+        # We want to save the left hash, as that identifies the base file.
+        match = re.match(r"index (\w+)\.\.", line)
+        if match:
+          self.base_hashes[filename] = match.group(1)
+      svndiff.append(line + "\n")
+    if not filecount:
+      ErrorExit("No valid patches found in output from git diff")
+    return "".join(svndiff)
+
+  def GetUnknownFiles(self):
+    status = RunShell(["git", "ls-files", "--exclude-standard", "--others"],
+                      silent_ok=True)
+    return status.splitlines()
+
+  def GetBaseFile(self, filename):
+    hash = self.base_hashes[filename]
+    base_content = None
+    new_content = None
+    is_binary = False
+    if hash == "0" * 40:  # All-zero hash indicates no base file.
+      status = "A"
+      base_content = ""
+    else:
+      status = "M"
+      base_content, returncode = RunShellWithReturnCode(["git", "show", hash])
+      if returncode:
+        ErrorExit("Got error status from 'git show %s'" % hash)
+    return (base_content, new_content, is_binary, status)
+
+
+class MercurialVCS(VersionControlSystem):
+  """Implementation of the VersionControlSystem interface for Mercurial."""
+
+  def __init__(self, options, repo_dir):
+    super(MercurialVCS, self).__init__(options)
+    # Absolute path to repository (we can be in a subdir)
+    self.repo_dir = os.path.normpath(repo_dir)
+    # Compute the subdir
+    cwd = os.path.normpath(os.getcwd())
+    assert cwd.startswith(self.repo_dir)
+    self.subdir = cwd[len(self.repo_dir):].lstrip(r"\/")
+    if self.options.revision:
+      self.base_rev = self.options.revision
+    else:
+      self.base_rev = RunShell(["hg", "parent", "-q"]).split(':')[1].strip()
+
+  def _GetRelPath(self, filename):
+    """Get relative path of a file according to the current directory,
+    given its logical path in the repo."""
+    assert filename.startswith(self.subdir), filename
+    return filename[len(self.subdir):].lstrip(r"\/")
+
+  def GenerateDiff(self, extra_args):
+    # If no file specified, restrict to the current subdir
+    extra_args = extra_args or ["."]
+    cmd = ["hg", "diff", "--git", "-r", self.base_rev] + extra_args
+    data = RunShell(cmd, silent_ok=True)
+    svndiff = []
+    filecount = 0
+    for line in data.splitlines():
+      m = re.match("diff --git a/(\S+) b/(\S+)", line)
+      if m:
+        # Modify line to make it look like as it comes from svn diff.
+        # With this modification no changes on the server side are required
+        # to make upload.py work with Mercurial repos.
+        # NOTE: for proper handling of moved/copied files, we have to use
+        # the second filename.
+        filename = m.group(2)
+        svndiff.append("Index: %s" % filename)
+        svndiff.append("=" * 67)
+        filecount += 1
+        logging.info(line)
+      else:
+        svndiff.append(line)
+    if not filecount:
+      ErrorExit("No valid patches found in output from hg diff")
+    return "\n".join(svndiff) + "\n"
+
+  def GetUnknownFiles(self):
+    """Return a list of files unknown to the VCS."""
+    args = []
+    status = RunShell(["hg", "status", "--rev", self.base_rev, "-u", "."],
+        silent_ok=True)
+    unknown_files = []
+    for line in status.splitlines():
+      st, fn = line.split(" ", 1)
+      if st == "?":
+        unknown_files.append(fn)
+    return unknown_files
+
+  def GetBaseFile(self, filename):
+    # "hg status" and "hg cat" both take a path relative to the current subdir
+    # rather than to the repo root, but "hg diff" has given us the full path
+    # to the repo root.
+    base_content = ""
+    new_content = None
+    is_binary = False
+    oldrelpath = relpath = self._GetRelPath(filename)
+    # "hg status -C" returns two lines for moved/copied files, one otherwise
+    out = RunShell(["hg", "status", "-C", "--rev", self.base_rev, relpath])
+    out = out.splitlines()
+    # HACK: strip error message about missing file/directory if it isn't in
+    # the working copy
+    if out[0].startswith('%s: ' % relpath):
+      out = out[1:]
+    if len(out) > 1:
+      # Moved/copied => considered as modified, use old filename to
+      # retrieve base contents
+      oldrelpath = out[1].strip()
+      status = "M"
+    else:
+      status, _ = out[0].split(' ', 1)
+    if status != "A":
+      base_content = RunShell(["hg", "cat", "-r", self.base_rev, oldrelpath],
+        silent_ok=True)
+      is_binary = "\0" in base_content  # Mercurial's heuristic
+    if status != "R":
+      new_content = open(relpath, "rb").read()
+      is_binary = is_binary or "\0" in new_content
+    if is_binary and base_content:
+      # Fetch again without converting newlines
+      base_content = RunShell(["hg", "cat", "-r", self.base_rev, oldrelpath],
+        silent_ok=True, universal_newlines=False)
+    if not is_binary or not self.IsImage(relpath):
+      new_content = None
+    return base_content, new_content, is_binary, status
+
+
+# NOTE: The SplitPatch function is duplicated in engine.py, keep them in sync.
+def SplitPatch(data):
+  """Splits a patch into separate pieces for each file.
+
+  Args:
+    data: A string containing the output of svn diff.
+
+  Returns:
+    A list of 2-tuple (filename, text) where text is the svn diff output
+      pertaining to filename.
+  """
+  patches = []
+  filename = None
+  diff = []
+  for line in data.splitlines(True):
+    new_filename = None
+    if line.startswith('Index:'):
+      unused, new_filename = line.split(':', 1)
+      new_filename = new_filename.strip()
+    elif line.startswith('Property changes on:'):
+      unused, temp_filename = line.split(':', 1)
+      # When a file is modified, paths use '/' between directories, however
+      # when a property is modified '\' is used on Windows.  Make them the same
+      # otherwise the file shows up twice.
+      temp_filename = temp_filename.strip().replace('\\', '/')
+      if temp_filename != filename:
+        # File has property changes but no modifications, create a new diff.
+        new_filename = temp_filename
+    if new_filename:
+      if filename and diff:
+        patches.append((filename, ''.join(diff)))
+      filename = new_filename
+      diff = [line]
+      continue
+    if diff is not None:
+      diff.append(line)
+  if filename and diff:
+    patches.append((filename, ''.join(diff)))
+  return patches
+
+
+def UploadSeparatePatches(issue, rpc_server, patchset, data, options):
+  """Uploads a separate patch for each file in the diff output.
+
+  Returns a list of [patch_key, filename] for each file.
+  """
+  patches = SplitPatch(data)
+  rv = []
+  for patch in patches:
+    if len(patch[1]) > MAX_UPLOAD_SIZE:
+      print ("Not uploading the patch for " + patch[0] +
+             " because the file is too large.")
+      continue
+    form_fields = [("filename", patch[0])]
+    if not options.download_base:
+      form_fields.append(("content_upload", "1"))
+    files = [("data", "data.diff", patch[1])]
+    ctype, body = EncodeMultipartFormData(form_fields, files)
+    url = "/%d/upload_patch/%d" % (int(issue), int(patchset))
+    print "Uploading patch for " + patch[0]
+    response_body = rpc_server.Send(url, body, content_type=ctype)
+    lines = response_body.splitlines()
+    if not lines or lines[0] != "OK":
+      StatusUpdate("  --> %s" % response_body)
+      sys.exit(1)
+    rv.append([lines[1], patch[0]])
+  return rv
+
+
+def GuessVCS(options):
+  """Helper to guess the version control system.
+
+  This examines the current directory, guesses which VersionControlSystem
+  we're using, and returns an instance of the appropriate class.  Exit with an
+  error if we can't figure it out.
+
+  Returns:
+    A VersionControlSystem instance. Exits if the VCS can't be guessed.
+  """
+  # Mercurial has a command to get the base directory of a repository
+  # Try running it, but don't die if we don't have hg installed.
+  # NOTE: we try Mercurial first as it can sit on top of an SVN working copy.
+  try:
+    out, returncode = RunShellWithReturnCode(["hg", "root"])
+    if returncode == 0:
+      return MercurialVCS(options, out.strip())
+  except OSError, (errno, message):
+    if errno != 2:  # ENOENT -- they don't have hg installed.
+      raise
+
+  # Subversion has a .svn in all working directories.
+  if os.path.isdir('.svn'):
+    logging.info("Guessed VCS = Subversion")
+    return SubversionVCS(options)
+
+  # Git has a command to test if you're in a git tree.
+  # Try running it, but don't die if we don't have git installed.
+  try:
+    out, returncode = RunShellWithReturnCode(["git", "rev-parse",
+                                              "--is-inside-work-tree"])
+    if returncode == 0:
+      return GitVCS(options)
+  except OSError, (errno, message):
+    if errno != 2:  # ENOENT -- they don't have git installed.
+      raise
+
+  ErrorExit(("Could not guess version control system. "
+             "Are you in a working copy directory?"))
+
+
+def RealMain(argv, data=None):
+  """The real main function.
+
+  Args:
+    argv: Command line arguments.
+    data: Diff contents. If None (default) the diff is generated by
+      the VersionControlSystem implementation returned by GuessVCS().
+
+  Returns:
+    A 2-tuple (issue id, patchset id).
+    The patchset id is None if the base files are not uploaded by this
+    script (applies only to SVN checkouts).
+  """
+  logging.basicConfig(format=("%(asctime).19s %(levelname)s %(filename)s:"
+                              "%(lineno)s %(message)s "))
+  os.environ['LC_ALL'] = 'C'
+  options, args = parser.parse_args(argv[1:])
+  global verbosity
+  verbosity = options.verbose
+  if verbosity >= 3:
+    logging.getLogger().setLevel(logging.DEBUG)
+  elif verbosity >= 2:
+    logging.getLogger().setLevel(logging.INFO)
+  vcs = GuessVCS(options)
+  if isinstance(vcs, SubversionVCS):
+    # base field is only allowed for Subversion.
+    # Note: Fetching base files may become deprecated in future releases.
+    base = vcs.GuessBase(options.download_base)
+  else:
+    base = None
+  if not base and options.download_base:
+    options.download_base = True
+    logging.info("Enabled upload of base file")
+  if not options.assume_yes:
+    vcs.CheckForUnknownFiles()
+  if data is None:
+    data = vcs.GenerateDiff(args)
+  files = vcs.GetBaseFiles(data)
+  if verbosity >= 1:
+    print "Upload server:", options.server, "(change with -s/--server)"
+  if options.issue:
+    prompt = "Message describing this patch set: "
+  else:
+    prompt = "New issue subject: "
+  message = options.message or raw_input(prompt).strip()
+  if not message:
+    ErrorExit("A non-empty message is required")
+  rpc_server = GetRpcServer(options)
+  form_fields = [("subject", message)]
+  if base:
+    form_fields.append(("base", base))
+  if options.issue:
+    form_fields.append(("issue", str(options.issue)))
+  if options.email:
+    form_fields.append(("user", options.email))
+  if options.reviewers:
+    for reviewer in options.reviewers.split(','):
+      if "@" in reviewer and not reviewer.split("@")[1].count(".") == 1:
+        ErrorExit("Invalid email address: %s" % reviewer)
+    form_fields.append(("reviewers", options.reviewers))
+  if options.cc:
+    for cc in options.cc.split(','):
+      if "@" in cc and not cc.split("@")[1].count(".") == 1:
+        ErrorExit("Invalid email address: %s" % cc)
+    form_fields.append(("cc", options.cc))
+  description = options.description
+  if options.description_file:
+    if options.description:
+      ErrorExit("Can't specify description and description_file")
+    file = open(options.description_file, 'r')
+    description = file.read()
+    file.close()
+  if description:
+    form_fields.append(("description", description))
+  # Send a hash of all the base file so the server can determine if a copy
+  # already exists in an earlier patchset.
+  base_hashes = ""
+  for file, info in files.iteritems():
+    if not info[0] is None:
+      checksum = md5.new(info[0]).hexdigest()
+      if base_hashes:
+        base_hashes += "|"
+      base_hashes += checksum + ":" + file
+  form_fields.append(("base_hashes", base_hashes))
+  # If we're uploading base files, don't send the email before the uploads, so
+  # that it contains the file status.
+  if options.send_mail and options.download_base:
+    form_fields.append(("send_mail", "1"))
+  if not options.download_base:
+    form_fields.append(("content_upload", "1"))
+  if len(data) > MAX_UPLOAD_SIZE:
+    print "Patch is large, so uploading file patches separately."
+    uploaded_diff_file = []
+    form_fields.append(("separate_patches", "1"))
+  else:
+    uploaded_diff_file = [("data", "data.diff", data)]
+  ctype, body = EncodeMultipartFormData(form_fields, uploaded_diff_file)
+  response_body = rpc_server.Send("/upload", body, content_type=ctype)
+  patchset = None
+  if not options.download_base or not uploaded_diff_file:
+    lines = response_body.splitlines()
+    if len(lines) >= 2:
+      msg = lines[0]
+      patchset = lines[1].strip()
+      patches = [x.split(" ", 1) for x in lines[2:]]
+    else:
+      msg = response_body
+  else:
+    msg = response_body
+  StatusUpdate(msg)
+  if not response_body.startswith("Issue created.") and \
+  not response_body.startswith("Issue updated."):
+    sys.exit(0)
+  issue = msg[msg.rfind("/")+1:]
+
+  if not uploaded_diff_file:
+    result = UploadSeparatePatches(issue, rpc_server, patchset, data, options)
+    if not options.download_base:
+      patches = result
+
+  if not options.download_base:
+    vcs.UploadBaseFiles(issue, rpc_server, patches, patchset, options, files)
+    if options.send_mail:
+      rpc_server.Send("/" + issue + "/mail", payload="")
+  return issue, patchset
+
+
+def main():
+  try:
+    RealMain(sys.argv)
+  except KeyboardInterrupt:
+    print
+    StatusUpdate("Interrupted.")
+    sys.exit(1)
+
+
+if __name__ == "__main__":
+  main()
diff --git a/third_party/googletest/googlemock/scripts/upload_gmock.py b/third_party/googletest/googlemock/scripts/upload_gmock.py
new file mode 100755
index 0000000..5dc484b
--- /dev/null
+++ b/third_party/googletest/googlemock/scripts/upload_gmock.py
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+#
+# Copyright 2009, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""upload_gmock.py v0.1.0 -- uploads a Google Mock patch for review.
+
+This simple wrapper passes all command line flags and
+--cc=googlemock@googlegroups.com to upload.py.
+
+USAGE: upload_gmock.py [options for upload.py]
+"""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import os
+import sys
+
+CC_FLAG = '--cc='
+GMOCK_GROUP = 'googlemock@googlegroups.com'
+
+
+def main():
+  # Finds the path to upload.py, assuming it is in the same directory
+  # as this file.
+  my_dir = os.path.dirname(os.path.abspath(__file__))
+  upload_py_path = os.path.join(my_dir, 'upload.py')
+
+  # Adds Google Mock discussion group to the cc line if it's not there
+  # already.
+  upload_py_argv = [upload_py_path]
+  found_cc_flag = False
+  for arg in sys.argv[1:]:
+    if arg.startswith(CC_FLAG):
+      found_cc_flag = True
+      cc_line = arg[len(CC_FLAG):]
+      cc_list = [addr for addr in cc_line.split(',') if addr]
+      if GMOCK_GROUP not in cc_list:
+        cc_list.append(GMOCK_GROUP)
+      upload_py_argv.append(CC_FLAG + ','.join(cc_list))
+    else:
+      upload_py_argv.append(arg)
+
+  if not found_cc_flag:
+    upload_py_argv.append(CC_FLAG + GMOCK_GROUP)
+
+  # Invokes upload.py with the modified command line flags.
+  os.execv(upload_py_path, upload_py_argv)
+
+
+if __name__ == '__main__':
+  main()
diff --git a/third_party/googletest/googlemock/src/gmock-all.cc b/third_party/googletest/googlemock/src/gmock-all.cc
new file mode 100644
index 0000000..7aebce7
--- /dev/null
+++ b/third_party/googletest/googlemock/src/gmock-all.cc
@@ -0,0 +1,47 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// Google C++ Mocking Framework (Google Mock)
+//
+// This file #includes all Google Mock implementation .cc files.  The
+// purpose is to allow a user to build Google Mock by compiling this
+// file alone.
+
+// This line ensures that gmock.h can be compiled on its own, even
+// when it's fused.
+#include "gmock/gmock.h"
+
+// The following lines pull in the real gmock *.cc files.
+#include "src/gmock-cardinalities.cc"
+#include "src/gmock-internal-utils.cc"
+#include "src/gmock-matchers.cc"
+#include "src/gmock-spec-builders.cc"
+#include "src/gmock.cc"
diff --git a/third_party/googletest/googlemock/src/gmock-cardinalities.cc b/third_party/googletest/googlemock/src/gmock-cardinalities.cc
new file mode 100644
index 0000000..50ec728
--- /dev/null
+++ b/third_party/googletest/googlemock/src/gmock-cardinalities.cc
@@ -0,0 +1,156 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements cardinalities.
+
+#include "gmock/gmock-cardinalities.h"
+
+#include <limits.h>
+#include <ostream>  // NOLINT
+#include <sstream>
+#include <string>
+#include "gmock/internal/gmock-internal-utils.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+
+namespace {
+
+// Implements the Between(m, n) cardinality.
+class BetweenCardinalityImpl : public CardinalityInterface {
+ public:
+  BetweenCardinalityImpl(int min, int max)
+      : min_(min >= 0 ? min : 0),
+        max_(max >= min_ ? max : min_) {
+    std::stringstream ss;
+    if (min < 0) {
+      ss << "The invocation lower bound must be >= 0, "
+         << "but is actually " << min << ".";
+      internal::Expect(false, __FILE__, __LINE__, ss.str());
+    } else if (max < 0) {
+      ss << "The invocation upper bound must be >= 0, "
+         << "but is actually " << max << ".";
+      internal::Expect(false, __FILE__, __LINE__, ss.str());
+    } else if (min > max) {
+      ss << "The invocation upper bound (" << max
+         << ") must be >= the invocation lower bound (" << min
+         << ").";
+      internal::Expect(false, __FILE__, __LINE__, ss.str());
+    }
+  }
+
+  // Conservative estimate on the lower/upper bound of the number of
+  // calls allowed.
+  virtual int ConservativeLowerBound() const { return min_; }
+  virtual int ConservativeUpperBound() const { return max_; }
+
+  virtual bool IsSatisfiedByCallCount(int call_count) const {
+    return min_ <= call_count && call_count <= max_;
+  }
+
+  virtual bool IsSaturatedByCallCount(int call_count) const {
+    return call_count >= max_;
+  }
+
+  virtual void DescribeTo(::std::ostream* os) const;
+
+ private:
+  const int min_;
+  const int max_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(BetweenCardinalityImpl);
+};
+
+// Formats "n times" in a human-friendly way.
+inline internal::string FormatTimes(int n) {
+  if (n == 1) {
+    return "once";
+  } else if (n == 2) {
+    return "twice";
+  } else {
+    std::stringstream ss;
+    ss << n << " times";
+    return ss.str();
+  }
+}
+
+// Describes the Between(m, n) cardinality in human-friendly text.
+void BetweenCardinalityImpl::DescribeTo(::std::ostream* os) const {
+  if (min_ == 0) {
+    if (max_ == 0) {
+      *os << "never called";
+    } else if (max_ == INT_MAX) {
+      *os << "called any number of times";
+    } else {
+      *os << "called at most " << FormatTimes(max_);
+    }
+  } else if (min_ == max_) {
+    *os << "called " << FormatTimes(min_);
+  } else if (max_ == INT_MAX) {
+    *os << "called at least " << FormatTimes(min_);
+  } else {
+    // 0 < min_ < max_ < INT_MAX
+    *os << "called between " << min_ << " and " << max_ << " times";
+  }
+}
+
+}  // Unnamed namespace
+
+// Describes the given call count to an ostream.
+void Cardinality::DescribeActualCallCountTo(int actual_call_count,
+                                            ::std::ostream* os) {
+  if (actual_call_count > 0) {
+    *os << "called " << FormatTimes(actual_call_count);
+  } else {
+    *os << "never called";
+  }
+}
+
+// Creates a cardinality that allows at least n calls.
+GTEST_API_ Cardinality AtLeast(int n) { return Between(n, INT_MAX); }
+
+// Creates a cardinality that allows at most n calls.
+GTEST_API_ Cardinality AtMost(int n) { return Between(0, n); }
+
+// Creates a cardinality that allows any number of calls.
+GTEST_API_ Cardinality AnyNumber() { return AtLeast(0); }
+
+// Creates a cardinality that allows between min and max calls.
+GTEST_API_ Cardinality Between(int min, int max) {
+  return Cardinality(new BetweenCardinalityImpl(min, max));
+}
+
+// Creates a cardinality that allows exactly n calls.
+GTEST_API_ Cardinality Exactly(int n) { return Between(n, n); }
+
+}  // namespace testing
diff --git a/third_party/googletest/googlemock/src/gmock-internal-utils.cc b/third_party/googletest/googlemock/src/gmock-internal-utils.cc
new file mode 100644
index 0000000..fb53080
--- /dev/null
+++ b/third_party/googletest/googlemock/src/gmock-internal-utils.cc
@@ -0,0 +1,174 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file defines some utilities useful for implementing Google
+// Mock.  They are subject to change without notice, so please DO NOT
+// USE THEM IN USER CODE.
+
+#include "gmock/internal/gmock-internal-utils.h"
+
+#include <ctype.h>
+#include <ostream>  // NOLINT
+#include <string>
+#include "gmock/gmock.h"
+#include "gmock/internal/gmock-port.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+namespace internal {
+
+// Converts an identifier name to a space-separated list of lower-case
+// words.  Each maximum substring of the form [A-Za-z][a-z]*|\d+ is
+// treated as one word.  For example, both "FooBar123" and
+// "foo_bar_123" are converted to "foo bar 123".
+GTEST_API_ string ConvertIdentifierNameToWords(const char* id_name) {
+  string result;
+  char prev_char = '\0';
+  for (const char* p = id_name; *p != '\0'; prev_char = *(p++)) {
+    // We don't care about the current locale as the input is
+    // guaranteed to be a valid C++ identifier name.
+    const bool starts_new_word = IsUpper(*p) ||
+        (!IsAlpha(prev_char) && IsLower(*p)) ||
+        (!IsDigit(prev_char) && IsDigit(*p));
+
+    if (IsAlNum(*p)) {
+      if (starts_new_word && result != "")
+        result += ' ';
+      result += ToLower(*p);
+    }
+  }
+  return result;
+}
+
+// This class reports Google Mock failures as Google Test failures.  A
+// user can define another class in a similar fashion if he intends to
+// use Google Mock with a testing framework other than Google Test.
+class GoogleTestFailureReporter : public FailureReporterInterface {
+ public:
+  virtual void ReportFailure(FailureType type, const char* file, int line,
+                             const string& message) {
+    AssertHelper(type == kFatal ?
+                 TestPartResult::kFatalFailure :
+                 TestPartResult::kNonFatalFailure,
+                 file,
+                 line,
+                 message.c_str()) = Message();
+    if (type == kFatal) {
+      posix::Abort();
+    }
+  }
+};
+
+// Returns the global failure reporter.  Will create a
+// GoogleTestFailureReporter and return it the first time called.
+GTEST_API_ FailureReporterInterface* GetFailureReporter() {
+  // Points to the global failure reporter used by Google Mock.  gcc
+  // guarantees that the following use of failure_reporter is
+  // thread-safe.  We may need to add additional synchronization to
+  // protect failure_reporter if we port Google Mock to other
+  // compilers.
+  static FailureReporterInterface* const failure_reporter =
+      new GoogleTestFailureReporter();
+  return failure_reporter;
+}
+
+// Protects global resources (stdout in particular) used by Log().
+static GTEST_DEFINE_STATIC_MUTEX_(g_log_mutex);
+
+// Returns true iff a log with the given severity is visible according
+// to the --gmock_verbose flag.
+GTEST_API_ bool LogIsVisible(LogSeverity severity) {
+  if (GMOCK_FLAG(verbose) == kInfoVerbosity) {
+    // Always show the log if --gmock_verbose=info.
+    return true;
+  } else if (GMOCK_FLAG(verbose) == kErrorVerbosity) {
+    // Always hide it if --gmock_verbose=error.
+    return false;
+  } else {
+    // If --gmock_verbose is neither "info" nor "error", we treat it
+    // as "warning" (its default value).
+    return severity == kWarning;
+  }
+}
+
+// Prints the given message to stdout iff 'severity' >= the level
+// specified by the --gmock_verbose flag.  If stack_frames_to_skip >=
+// 0, also prints the stack trace excluding the top
+// stack_frames_to_skip frames.  In opt mode, any positive
+// stack_frames_to_skip is treated as 0, since we don't know which
+// function calls will be inlined by the compiler and need to be
+// conservative.
+GTEST_API_ void Log(LogSeverity severity,
+                    const string& message,
+                    int stack_frames_to_skip) {
+  if (!LogIsVisible(severity))
+    return;
+
+  // Ensures that logs from different threads don't interleave.
+  MutexLock l(&g_log_mutex);
+
+  // "using ::std::cout;" doesn't work with Symbian's STLport, where cout is a
+  // macro.
+
+  if (severity == kWarning) {
+    // Prints a GMOCK WARNING marker to make the warnings easily searchable.
+    std::cout << "\nGMOCK WARNING:";
+  }
+  // Pre-pends a new-line to message if it doesn't start with one.
+  if (message.empty() || message[0] != '\n') {
+    std::cout << "\n";
+  }
+  std::cout << message;
+  if (stack_frames_to_skip >= 0) {
+#ifdef NDEBUG
+    // In opt mode, we have to be conservative and skip no stack frame.
+    const int actual_to_skip = 0;
+#else
+    // In dbg mode, we can do what the caller tell us to do (plus one
+    // for skipping this function's stack frame).
+    const int actual_to_skip = stack_frames_to_skip + 1;
+#endif  // NDEBUG
+
+    // Appends a new-line to message if it doesn't end with one.
+    if (!message.empty() && *message.rbegin() != '\n') {
+      std::cout << "\n";
+    }
+    std::cout << "Stack trace:\n"
+         << ::testing::internal::GetCurrentOsStackTraceExceptTop(
+             ::testing::UnitTest::GetInstance(), actual_to_skip);
+  }
+  std::cout << ::std::flush;
+}
+
+}  // namespace internal
+}  // namespace testing
diff --git a/third_party/googletest/googlemock/src/gmock-matchers.cc b/third_party/googletest/googlemock/src/gmock-matchers.cc
new file mode 100644
index 0000000..e742451
--- /dev/null
+++ b/third_party/googletest/googlemock/src/gmock-matchers.cc
@@ -0,0 +1,498 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements Matcher<const string&>, Matcher<string>, and
+// utilities for defining matchers.
+
+#include "gmock/gmock-matchers.h"
+#include "gmock/gmock-generated-matchers.h"
+
+#include <string.h>
+#include <sstream>
+#include <string>
+
+namespace testing {
+
+// Constructs a matcher that matches a const string& whose value is
+// equal to s.
+Matcher<const internal::string&>::Matcher(const internal::string& s) {
+  *this = Eq(s);
+}
+
+// Constructs a matcher that matches a const string& whose value is
+// equal to s.
+Matcher<const internal::string&>::Matcher(const char* s) {
+  *this = Eq(internal::string(s));
+}
+
+// Constructs a matcher that matches a string whose value is equal to s.
+Matcher<internal::string>::Matcher(const internal::string& s) { *this = Eq(s); }
+
+// Constructs a matcher that matches a string whose value is equal to s.
+Matcher<internal::string>::Matcher(const char* s) {
+  *this = Eq(internal::string(s));
+}
+
+#if GTEST_HAS_STRING_PIECE_
+// Constructs a matcher that matches a const StringPiece& whose value is
+// equal to s.
+Matcher<const StringPiece&>::Matcher(const internal::string& s) {
+  *this = Eq(s);
+}
+
+// Constructs a matcher that matches a const StringPiece& whose value is
+// equal to s.
+Matcher<const StringPiece&>::Matcher(const char* s) {
+  *this = Eq(internal::string(s));
+}
+
+// Constructs a matcher that matches a const StringPiece& whose value is
+// equal to s.
+Matcher<const StringPiece&>::Matcher(StringPiece s) {
+  *this = Eq(s.ToString());
+}
+
+// Constructs a matcher that matches a StringPiece whose value is equal to s.
+Matcher<StringPiece>::Matcher(const internal::string& s) {
+  *this = Eq(s);
+}
+
+// Constructs a matcher that matches a StringPiece whose value is equal to s.
+Matcher<StringPiece>::Matcher(const char* s) {
+  *this = Eq(internal::string(s));
+}
+
+// Constructs a matcher that matches a StringPiece whose value is equal to s.
+Matcher<StringPiece>::Matcher(StringPiece s) {
+  *this = Eq(s.ToString());
+}
+#endif  // GTEST_HAS_STRING_PIECE_
+
+namespace internal {
+
+// Joins a vector of strings as if they are fields of a tuple; returns
+// the joined string.
+GTEST_API_ string JoinAsTuple(const Strings& fields) {
+  switch (fields.size()) {
+    case 0:
+      return "";
+    case 1:
+      return fields[0];
+    default:
+      string result = "(" + fields[0];
+      for (size_t i = 1; i < fields.size(); i++) {
+        result += ", ";
+        result += fields[i];
+      }
+      result += ")";
+      return result;
+  }
+}
+
+// Returns the description for a matcher defined using the MATCHER*()
+// macro where the user-supplied description string is "", if
+// 'negation' is false; otherwise returns the description of the
+// negation of the matcher.  'param_values' contains a list of strings
+// that are the print-out of the matcher's parameters.
+GTEST_API_ string FormatMatcherDescription(bool negation,
+                                           const char* matcher_name,
+                                           const Strings& param_values) {
+  string result = ConvertIdentifierNameToWords(matcher_name);
+  if (param_values.size() >= 1)
+    result += " " + JoinAsTuple(param_values);
+  return negation ? "not (" + result + ")" : result;
+}
+
+// FindMaxBipartiteMatching and its helper class.
+//
+// Uses the well-known Ford-Fulkerson max flow method to find a maximum
+// bipartite matching. Flow is considered to be from left to right.
+// There is an implicit source node that is connected to all of the left
+// nodes, and an implicit sink node that is connected to all of the
+// right nodes. All edges have unit capacity.
+//
+// Neither the flow graph nor the residual flow graph are represented
+// explicitly. Instead, they are implied by the information in 'graph' and
+// a vector<int> called 'left_' whose elements are initialized to the
+// value kUnused. This represents the initial state of the algorithm,
+// where the flow graph is empty, and the residual flow graph has the
+// following edges:
+//   - An edge from source to each left_ node
+//   - An edge from each right_ node to sink
+//   - An edge from each left_ node to each right_ node, if the
+//     corresponding edge exists in 'graph'.
+//
+// When the TryAugment() method adds a flow, it sets left_[l] = r for some
+// nodes l and r. This induces the following changes:
+//   - The edges (source, l), (l, r), and (r, sink) are added to the
+//     flow graph.
+//   - The same three edges are removed from the residual flow graph.
+//   - The reverse edges (l, source), (r, l), and (sink, r) are added
+//     to the residual flow graph, which is a directional graph
+//     representing unused flow capacity.
+//
+// When the method augments a flow (moving left_[l] from some r1 to some
+// other r2), this can be thought of as "undoing" the above steps with
+// respect to r1 and "redoing" them with respect to r2.
+//
+// It bears repeating that the flow graph and residual flow graph are
+// never represented explicitly, but can be derived by looking at the
+// information in 'graph' and in left_.
+//
+// As an optimization, there is a second vector<int> called right_ which
+// does not provide any new information. Instead, it enables more
+// efficient queries about edges entering or leaving the right-side nodes
+// of the flow or residual flow graphs. The following invariants are
+// maintained:
+//
+// left[l] == kUnused or right[left[l]] == l
+// right[r] == kUnused or left[right[r]] == r
+//
+// . [ source ]                                        .
+// .   |||                                             .
+// .   |||                                             .
+// .   ||\--> left[0]=1  ---\    right[0]=-1 ----\     .
+// .   ||                   |                    |     .
+// .   |\---> left[1]=-1    \--> right[1]=0  ---\|     .
+// .   |                                        ||     .
+// .   \----> left[2]=2  ------> right[2]=2  --\||     .
+// .                                           |||     .
+// .         elements           matchers       vvv     .
+// .                                         [ sink ]  .
+//
+// See Also:
+//   [1] Cormen, et al (2001). "Section 26.2: The Ford-Fulkerson method".
+//       "Introduction to Algorithms (Second ed.)", pp. 651-664.
+//   [2] "Ford-Fulkerson algorithm", Wikipedia,
+//       'http://en.wikipedia.org/wiki/Ford%E2%80%93Fulkerson_algorithm'
+class MaxBipartiteMatchState {
+ public:
+  explicit MaxBipartiteMatchState(const MatchMatrix& graph)
+      : graph_(&graph),
+        left_(graph_->LhsSize(), kUnused),
+        right_(graph_->RhsSize(), kUnused) {
+  }
+
+  // Returns the edges of a maximal match, each in the form {left, right}.
+  ElementMatcherPairs Compute() {
+    // 'seen' is used for path finding { 0: unseen, 1: seen }.
+    ::std::vector<char> seen;
+    // Searches the residual flow graph for a path from each left node to
+    // the sink in the residual flow graph, and if one is found, add flow
+    // to the graph. It's okay to search through the left nodes once. The
+    // edge from the implicit source node to each previously-visited left
+    // node will have flow if that left node has any path to the sink
+    // whatsoever. Subsequent augmentations can only add flow to the
+    // network, and cannot take away that previous flow unit from the source.
+    // Since the source-to-left edge can only carry one flow unit (or,
+    // each element can be matched to only one matcher), there is no need
+    // to visit the left nodes more than once looking for augmented paths.
+    // The flow is known to be possible or impossible by looking at the
+    // node once.
+    for (size_t ilhs = 0; ilhs < graph_->LhsSize(); ++ilhs) {
+      // Reset the path-marking vector and try to find a path from
+      // source to sink starting at the left_[ilhs] node.
+      GTEST_CHECK_(left_[ilhs] == kUnused)
+          << "ilhs: " << ilhs << ", left_[ilhs]: " << left_[ilhs];
+      // 'seen' initialized to 'graph_->RhsSize()' copies of 0.
+      seen.assign(graph_->RhsSize(), 0);
+      TryAugment(ilhs, &seen);
+    }
+    ElementMatcherPairs result;
+    for (size_t ilhs = 0; ilhs < left_.size(); ++ilhs) {
+      size_t irhs = left_[ilhs];
+      if (irhs == kUnused) continue;
+      result.push_back(ElementMatcherPair(ilhs, irhs));
+    }
+    return result;
+  }
+
+ private:
+  static const size_t kUnused = static_cast<size_t>(-1);
+
+  // Perform a depth-first search from left node ilhs to the sink.  If a
+  // path is found, flow is added to the network by linking the left and
+  // right vector elements corresponding each segment of the path.
+  // Returns true if a path to sink was found, which means that a unit of
+  // flow was added to the network. The 'seen' vector elements correspond
+  // to right nodes and are marked to eliminate cycles from the search.
+  //
+  // Left nodes will only be explored at most once because they
+  // are accessible from at most one right node in the residual flow
+  // graph.
+  //
+  // Note that left_[ilhs] is the only element of left_ that TryAugment will
+  // potentially transition from kUnused to another value. Any other
+  // left_ element holding kUnused before TryAugment will be holding it
+  // when TryAugment returns.
+  //
+  bool TryAugment(size_t ilhs, ::std::vector<char>* seen) {
+    for (size_t irhs = 0; irhs < graph_->RhsSize(); ++irhs) {
+      if ((*seen)[irhs])
+        continue;
+      if (!graph_->HasEdge(ilhs, irhs))
+        continue;
+      // There's an available edge from ilhs to irhs.
+      (*seen)[irhs] = 1;
+      // Next a search is performed to determine whether
+      // this edge is a dead end or leads to the sink.
+      //
+      // right_[irhs] == kUnused means that there is residual flow from
+      // right node irhs to the sink, so we can use that to finish this
+      // flow path and return success.
+      //
+      // Otherwise there is residual flow to some ilhs. We push flow
+      // along that path and call ourselves recursively to see if this
+      // ultimately leads to sink.
+      if (right_[irhs] == kUnused || TryAugment(right_[irhs], seen)) {
+        // Add flow from left_[ilhs] to right_[irhs].
+        left_[ilhs] = irhs;
+        right_[irhs] = ilhs;
+        return true;
+      }
+    }
+    return false;
+  }
+
+  const MatchMatrix* graph_;  // not owned
+  // Each element of the left_ vector represents a left hand side node
+  // (i.e. an element) and each element of right_ is a right hand side
+  // node (i.e. a matcher). The values in the left_ vector indicate
+  // outflow from that node to a node on the the right_ side. The values
+  // in the right_ indicate inflow, and specify which left_ node is
+  // feeding that right_ node, if any. For example, left_[3] == 1 means
+  // there's a flow from element #3 to matcher #1. Such a flow would also
+  // be redundantly represented in the right_ vector as right_[1] == 3.
+  // Elements of left_ and right_ are either kUnused or mutually
+  // referent. Mutually referent means that left_[right_[i]] = i and
+  // right_[left_[i]] = i.
+  ::std::vector<size_t> left_;
+  ::std::vector<size_t> right_;
+
+  GTEST_DISALLOW_ASSIGN_(MaxBipartiteMatchState);
+};
+
+const size_t MaxBipartiteMatchState::kUnused;
+
+GTEST_API_ ElementMatcherPairs
+FindMaxBipartiteMatching(const MatchMatrix& g) {
+  return MaxBipartiteMatchState(g).Compute();
+}
+
+static void LogElementMatcherPairVec(const ElementMatcherPairs& pairs,
+                                     ::std::ostream* stream) {
+  typedef ElementMatcherPairs::const_iterator Iter;
+  ::std::ostream& os = *stream;
+  os << "{";
+  const char *sep = "";
+  for (Iter it = pairs.begin(); it != pairs.end(); ++it) {
+    os << sep << "\n  ("
+       << "element #" << it->first << ", "
+       << "matcher #" << it->second << ")";
+    sep = ",";
+  }
+  os << "\n}";
+}
+
+// Tries to find a pairing, and explains the result.
+GTEST_API_ bool FindPairing(const MatchMatrix& matrix,
+                            MatchResultListener* listener) {
+  ElementMatcherPairs matches = FindMaxBipartiteMatching(matrix);
+
+  size_t max_flow = matches.size();
+  bool result = (max_flow == matrix.RhsSize());
+
+  if (!result) {
+    if (listener->IsInterested()) {
+      *listener << "where no permutation of the elements can "
+                   "satisfy all matchers, and the closest match is "
+                << max_flow << " of " << matrix.RhsSize()
+                << " matchers with the pairings:\n";
+      LogElementMatcherPairVec(matches, listener->stream());
+    }
+    return false;
+  }
+
+  if (matches.size() > 1) {
+    if (listener->IsInterested()) {
+      const char *sep = "where:\n";
+      for (size_t mi = 0; mi < matches.size(); ++mi) {
+        *listener << sep << " - element #" << matches[mi].first
+                  << " is matched by matcher #" << matches[mi].second;
+        sep = ",\n";
+      }
+    }
+  }
+  return true;
+}
+
+bool MatchMatrix::NextGraph() {
+  for (size_t ilhs = 0; ilhs < LhsSize(); ++ilhs) {
+    for (size_t irhs = 0; irhs < RhsSize(); ++irhs) {
+      char& b = matched_[SpaceIndex(ilhs, irhs)];
+      if (!b) {
+        b = 1;
+        return true;
+      }
+      b = 0;
+    }
+  }
+  return false;
+}
+
+void MatchMatrix::Randomize() {
+  for (size_t ilhs = 0; ilhs < LhsSize(); ++ilhs) {
+    for (size_t irhs = 0; irhs < RhsSize(); ++irhs) {
+      char& b = matched_[SpaceIndex(ilhs, irhs)];
+      b = static_cast<char>(rand() & 1);  // NOLINT
+    }
+  }
+}
+
+string MatchMatrix::DebugString() const {
+  ::std::stringstream ss;
+  const char *sep = "";
+  for (size_t i = 0; i < LhsSize(); ++i) {
+    ss << sep;
+    for (size_t j = 0; j < RhsSize(); ++j) {
+      ss << HasEdge(i, j);
+    }
+    sep = ";";
+  }
+  return ss.str();
+}
+
+void UnorderedElementsAreMatcherImplBase::DescribeToImpl(
+    ::std::ostream* os) const {
+  if (matcher_describers_.empty()) {
+    *os << "is empty";
+    return;
+  }
+  if (matcher_describers_.size() == 1) {
+    *os << "has " << Elements(1) << " and that element ";
+    matcher_describers_[0]->DescribeTo(os);
+    return;
+  }
+  *os << "has " << Elements(matcher_describers_.size())
+      << " and there exists some permutation of elements such that:\n";
+  const char* sep = "";
+  for (size_t i = 0; i != matcher_describers_.size(); ++i) {
+    *os << sep << " - element #" << i << " ";
+    matcher_describers_[i]->DescribeTo(os);
+    sep = ", and\n";
+  }
+}
+
+void UnorderedElementsAreMatcherImplBase::DescribeNegationToImpl(
+    ::std::ostream* os) const {
+  if (matcher_describers_.empty()) {
+    *os << "isn't empty";
+    return;
+  }
+  if (matcher_describers_.size() == 1) {
+    *os << "doesn't have " << Elements(1)
+        << ", or has " << Elements(1) << " that ";
+    matcher_describers_[0]->DescribeNegationTo(os);
+    return;
+  }
+  *os << "doesn't have " << Elements(matcher_describers_.size())
+      << ", or there exists no permutation of elements such that:\n";
+  const char* sep = "";
+  for (size_t i = 0; i != matcher_describers_.size(); ++i) {
+    *os << sep << " - element #" << i << " ";
+    matcher_describers_[i]->DescribeTo(os);
+    sep = ", and\n";
+  }
+}
+
+// Checks that all matchers match at least one element, and that all
+// elements match at least one matcher. This enables faster matching
+// and better error reporting.
+// Returns false, writing an explanation to 'listener', if and only
+// if the success criteria are not met.
+bool UnorderedElementsAreMatcherImplBase::
+VerifyAllElementsAndMatchersAreMatched(
+    const ::std::vector<string>& element_printouts,
+    const MatchMatrix& matrix,
+    MatchResultListener* listener) const {
+  bool result = true;
+  ::std::vector<char> element_matched(matrix.LhsSize(), 0);
+  ::std::vector<char> matcher_matched(matrix.RhsSize(), 0);
+
+  for (size_t ilhs = 0; ilhs < matrix.LhsSize(); ilhs++) {
+    for (size_t irhs = 0; irhs < matrix.RhsSize(); irhs++) {
+      char matched = matrix.HasEdge(ilhs, irhs);
+      element_matched[ilhs] |= matched;
+      matcher_matched[irhs] |= matched;
+    }
+  }
+
+  {
+    const char* sep =
+        "where the following matchers don't match any elements:\n";
+    for (size_t mi = 0; mi < matcher_matched.size(); ++mi) {
+      if (matcher_matched[mi])
+        continue;
+      result = false;
+      if (listener->IsInterested()) {
+        *listener << sep << "matcher #" << mi << ": ";
+        matcher_describers_[mi]->DescribeTo(listener->stream());
+        sep = ",\n";
+      }
+    }
+  }
+
+  {
+    const char* sep =
+        "where the following elements don't match any matchers:\n";
+    const char* outer_sep = "";
+    if (!result) {
+      outer_sep = "\nand ";
+    }
+    for (size_t ei = 0; ei < element_matched.size(); ++ei) {
+      if (element_matched[ei])
+        continue;
+      result = false;
+      if (listener->IsInterested()) {
+        *listener << outer_sep << sep << "element #" << ei << ": "
+                  << element_printouts[ei];
+        sep = ",\n";
+        outer_sep = "";
+      }
+    }
+  }
+  return result;
+}
+
+}  // namespace internal
+}  // namespace testing
diff --git a/third_party/googletest/googlemock/src/gmock-spec-builders.cc b/third_party/googletest/googlemock/src/gmock-spec-builders.cc
new file mode 100644
index 0000000..2b48af1
--- /dev/null
+++ b/third_party/googletest/googlemock/src/gmock-spec-builders.cc
@@ -0,0 +1,823 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements the spec builder syntax (ON_CALL and
+// EXPECT_CALL).
+
+#include "gmock/gmock-spec-builders.h"
+
+#include <stdlib.h>
+#include <iostream>  // NOLINT
+#include <map>
+#include <set>
+#include <string>
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#if GTEST_OS_CYGWIN || GTEST_OS_LINUX || GTEST_OS_MAC
+# include <unistd.h>  // NOLINT
+#endif
+
+namespace testing {
+namespace internal {
+
+// Protects the mock object registry (in class Mock), all function
+// mockers, and all expectations.
+GTEST_API_ GTEST_DEFINE_STATIC_MUTEX_(g_gmock_mutex);
+
+// Logs a message including file and line number information.
+GTEST_API_ void LogWithLocation(testing::internal::LogSeverity severity,
+                                const char* file, int line,
+                                const string& message) {
+  ::std::ostringstream s;
+  s << file << ":" << line << ": " << message << ::std::endl;
+  Log(severity, s.str(), 0);
+}
+
+// Constructs an ExpectationBase object.
+ExpectationBase::ExpectationBase(const char* a_file,
+                                 int a_line,
+                                 const string& a_source_text)
+    : file_(a_file),
+      line_(a_line),
+      source_text_(a_source_text),
+      cardinality_specified_(false),
+      cardinality_(Exactly(1)),
+      call_count_(0),
+      retired_(false),
+      extra_matcher_specified_(false),
+      repeated_action_specified_(false),
+      retires_on_saturation_(false),
+      last_clause_(kNone),
+      action_count_checked_(false) {}
+
+// Destructs an ExpectationBase object.
+ExpectationBase::~ExpectationBase() {}
+
+// Explicitly specifies the cardinality of this expectation.  Used by
+// the subclasses to implement the .Times() clause.
+void ExpectationBase::SpecifyCardinality(const Cardinality& a_cardinality) {
+  cardinality_specified_ = true;
+  cardinality_ = a_cardinality;
+}
+
+// Retires all pre-requisites of this expectation.
+void ExpectationBase::RetireAllPreRequisites()
+    GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+  if (is_retired()) {
+    // We can take this short-cut as we never retire an expectation
+    // until we have retired all its pre-requisites.
+    return;
+  }
+
+  for (ExpectationSet::const_iterator it = immediate_prerequisites_.begin();
+       it != immediate_prerequisites_.end(); ++it) {
+    ExpectationBase* const prerequisite = it->expectation_base().get();
+    if (!prerequisite->is_retired()) {
+      prerequisite->RetireAllPreRequisites();
+      prerequisite->Retire();
+    }
+  }
+}
+
+// Returns true iff all pre-requisites of this expectation have been
+// satisfied.
+bool ExpectationBase::AllPrerequisitesAreSatisfied() const
+    GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+  g_gmock_mutex.AssertHeld();
+  for (ExpectationSet::const_iterator it = immediate_prerequisites_.begin();
+       it != immediate_prerequisites_.end(); ++it) {
+    if (!(it->expectation_base()->IsSatisfied()) ||
+        !(it->expectation_base()->AllPrerequisitesAreSatisfied()))
+      return false;
+  }
+  return true;
+}
+
+// Adds unsatisfied pre-requisites of this expectation to 'result'.
+void ExpectationBase::FindUnsatisfiedPrerequisites(ExpectationSet* result) const
+    GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+  g_gmock_mutex.AssertHeld();
+  for (ExpectationSet::const_iterator it = immediate_prerequisites_.begin();
+       it != immediate_prerequisites_.end(); ++it) {
+    if (it->expectation_base()->IsSatisfied()) {
+      // If *it is satisfied and has a call count of 0, some of its
+      // pre-requisites may not be satisfied yet.
+      if (it->expectation_base()->call_count_ == 0) {
+        it->expectation_base()->FindUnsatisfiedPrerequisites(result);
+      }
+    } else {
+      // Now that we know *it is unsatisfied, we are not so interested
+      // in whether its pre-requisites are satisfied.  Therefore we
+      // don't recursively call FindUnsatisfiedPrerequisites() here.
+      *result += *it;
+    }
+  }
+}
+
+// Describes how many times a function call matching this
+// expectation has occurred.
+void ExpectationBase::DescribeCallCountTo(::std::ostream* os) const
+    GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+  g_gmock_mutex.AssertHeld();
+
+  // Describes how many times the function is expected to be called.
+  *os << "         Expected: to be ";
+  cardinality().DescribeTo(os);
+  *os << "\n           Actual: ";
+  Cardinality::DescribeActualCallCountTo(call_count(), os);
+
+  // Describes the state of the expectation (e.g. is it satisfied?
+  // is it active?).
+  *os << " - " << (IsOverSaturated() ? "over-saturated" :
+                   IsSaturated() ? "saturated" :
+                   IsSatisfied() ? "satisfied" : "unsatisfied")
+      << " and "
+      << (is_retired() ? "retired" : "active");
+}
+
+// Checks the action count (i.e. the number of WillOnce() and
+// WillRepeatedly() clauses) against the cardinality if this hasn't
+// been done before.  Prints a warning if there are too many or too
+// few actions.
+void ExpectationBase::CheckActionCountIfNotDone() const
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+  bool should_check = false;
+  {
+    MutexLock l(&mutex_);
+    if (!action_count_checked_) {
+      action_count_checked_ = true;
+      should_check = true;
+    }
+  }
+
+  if (should_check) {
+    if (!cardinality_specified_) {
+      // The cardinality was inferred - no need to check the action
+      // count against it.
+      return;
+    }
+
+    // The cardinality was explicitly specified.
+    const int action_count = static_cast<int>(untyped_actions_.size());
+    const int upper_bound = cardinality().ConservativeUpperBound();
+    const int lower_bound = cardinality().ConservativeLowerBound();
+    bool too_many;  // True if there are too many actions, or false
+    // if there are too few.
+    if (action_count > upper_bound ||
+        (action_count == upper_bound && repeated_action_specified_)) {
+      too_many = true;
+    } else if (0 < action_count && action_count < lower_bound &&
+               !repeated_action_specified_) {
+      too_many = false;
+    } else {
+      return;
+    }
+
+    ::std::stringstream ss;
+    DescribeLocationTo(&ss);
+    ss << "Too " << (too_many ? "many" : "few")
+       << " actions specified in " << source_text() << "...\n"
+       << "Expected to be ";
+    cardinality().DescribeTo(&ss);
+    ss << ", but has " << (too_many ? "" : "only ")
+       << action_count << " WillOnce()"
+       << (action_count == 1 ? "" : "s");
+    if (repeated_action_specified_) {
+      ss << " and a WillRepeatedly()";
+    }
+    ss << ".";
+    Log(kWarning, ss.str(), -1);  // -1 means "don't print stack trace".
+  }
+}
+
+// Implements the .Times() clause.
+void ExpectationBase::UntypedTimes(const Cardinality& a_cardinality) {
+  if (last_clause_ == kTimes) {
+    ExpectSpecProperty(false,
+                       ".Times() cannot appear "
+                       "more than once in an EXPECT_CALL().");
+  } else {
+    ExpectSpecProperty(last_clause_ < kTimes,
+                       ".Times() cannot appear after "
+                       ".InSequence(), .WillOnce(), .WillRepeatedly(), "
+                       "or .RetiresOnSaturation().");
+  }
+  last_clause_ = kTimes;
+
+  SpecifyCardinality(a_cardinality);
+}
+
+// Points to the implicit sequence introduced by a living InSequence
+// object (if any) in the current thread or NULL.
+GTEST_API_ ThreadLocal<Sequence*> g_gmock_implicit_sequence;
+
+// Reports an uninteresting call (whose description is in msg) in the
+// manner specified by 'reaction'.
+void ReportUninterestingCall(CallReaction reaction, const string& msg) {
+  // Include a stack trace only if --gmock_verbose=info is specified.
+  const int stack_frames_to_skip =
+      GMOCK_FLAG(verbose) == kInfoVerbosity ? 3 : -1;
+  switch (reaction) {
+    case kAllow:
+      Log(kInfo, msg, stack_frames_to_skip);
+      break;
+    case kWarn:
+      Log(kWarning,
+          msg +
+          "\nNOTE: You can safely ignore the above warning unless this "
+          "call should not happen.  Do not suppress it by blindly adding "
+          "an EXPECT_CALL() if you don't mean to enforce the call.  "
+          "See http://code.google.com/p/googlemock/wiki/CookBook#"
+          "Knowing_When_to_Expect for details.\n",
+          stack_frames_to_skip);
+      break;
+    default:  // FAIL
+      Expect(false, NULL, -1, msg);
+  }
+}
+
+UntypedFunctionMockerBase::UntypedFunctionMockerBase()
+    : mock_obj_(NULL), name_("") {}
+
+UntypedFunctionMockerBase::~UntypedFunctionMockerBase() {}
+
+// Sets the mock object this mock method belongs to, and registers
+// this information in the global mock registry.  Will be called
+// whenever an EXPECT_CALL() or ON_CALL() is executed on this mock
+// method.
+void UntypedFunctionMockerBase::RegisterOwner(const void* mock_obj)
+    GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
+  {
+    MutexLock l(&g_gmock_mutex);
+    mock_obj_ = mock_obj;
+  }
+  Mock::Register(mock_obj, this);
+}
+
+// Sets the mock object this mock method belongs to, and sets the name
+// of the mock function.  Will be called upon each invocation of this
+// mock function.
+void UntypedFunctionMockerBase::SetOwnerAndName(const void* mock_obj,
+                                                const char* name)
+    GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
+  // We protect name_ under g_gmock_mutex in case this mock function
+  // is called from two threads concurrently.
+  MutexLock l(&g_gmock_mutex);
+  mock_obj_ = mock_obj;
+  name_ = name;
+}
+
+// Returns the name of the function being mocked.  Must be called
+// after RegisterOwner() or SetOwnerAndName() has been called.
+const void* UntypedFunctionMockerBase::MockObject() const
+    GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
+  const void* mock_obj;
+  {
+    // We protect mock_obj_ under g_gmock_mutex in case this mock
+    // function is called from two threads concurrently.
+    MutexLock l(&g_gmock_mutex);
+    Assert(mock_obj_ != NULL, __FILE__, __LINE__,
+           "MockObject() must not be called before RegisterOwner() or "
+           "SetOwnerAndName() has been called.");
+    mock_obj = mock_obj_;
+  }
+  return mock_obj;
+}
+
+// Returns the name of this mock method.  Must be called after
+// SetOwnerAndName() has been called.
+const char* UntypedFunctionMockerBase::Name() const
+    GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
+  const char* name;
+  {
+    // We protect name_ under g_gmock_mutex in case this mock
+    // function is called from two threads concurrently.
+    MutexLock l(&g_gmock_mutex);
+    Assert(name_ != NULL, __FILE__, __LINE__,
+           "Name() must not be called before SetOwnerAndName() has "
+           "been called.");
+    name = name_;
+  }
+  return name;
+}
+
+// Calculates the result of invoking this mock function with the given
+// arguments, prints it, and returns it.  The caller is responsible
+// for deleting the result.
+UntypedActionResultHolderBase*
+UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args)
+    GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
+  if (untyped_expectations_.size() == 0) {
+    // No expectation is set on this mock method - we have an
+    // uninteresting call.
+
+    // We must get Google Mock's reaction on uninteresting calls
+    // made on this mock object BEFORE performing the action,
+    // because the action may DELETE the mock object and make the
+    // following expression meaningless.
+    const CallReaction reaction =
+        Mock::GetReactionOnUninterestingCalls(MockObject());
+
+    // True iff we need to print this call's arguments and return
+    // value.  This definition must be kept in sync with
+    // the behavior of ReportUninterestingCall().
+    const bool need_to_report_uninteresting_call =
+        // If the user allows this uninteresting call, we print it
+        // only when he wants informational messages.
+        reaction == kAllow ? LogIsVisible(kInfo) :
+        // If the user wants this to be a warning, we print it only
+        // when he wants to see warnings.
+        reaction == kWarn ? LogIsVisible(kWarning) :
+        // Otherwise, the user wants this to be an error, and we
+        // should always print detailed information in the error.
+        true;
+
+    if (!need_to_report_uninteresting_call) {
+      // Perform the action without printing the call information.
+      return this->UntypedPerformDefaultAction(untyped_args, "");
+    }
+
+    // Warns about the uninteresting call.
+    ::std::stringstream ss;
+    this->UntypedDescribeUninterestingCall(untyped_args, &ss);
+
+    // Calculates the function result.
+    UntypedActionResultHolderBase* const result =
+        this->UntypedPerformDefaultAction(untyped_args, ss.str());
+
+    // Prints the function result.
+    if (result != NULL)
+      result->PrintAsActionResult(&ss);
+
+    ReportUninterestingCall(reaction, ss.str());
+    return result;
+  }
+
+  bool is_excessive = false;
+  ::std::stringstream ss;
+  ::std::stringstream why;
+  ::std::stringstream loc;
+  const void* untyped_action = NULL;
+
+  // The UntypedFindMatchingExpectation() function acquires and
+  // releases g_gmock_mutex.
+  const ExpectationBase* const untyped_expectation =
+      this->UntypedFindMatchingExpectation(
+          untyped_args, &untyped_action, &is_excessive,
+          &ss, &why);
+  const bool found = untyped_expectation != NULL;
+
+  // True iff we need to print the call's arguments and return value.
+  // This definition must be kept in sync with the uses of Expect()
+  // and Log() in this function.
+  const bool need_to_report_call =
+      !found || is_excessive || LogIsVisible(kInfo);
+  if (!need_to_report_call) {
+    // Perform the action without printing the call information.
+    return
+        untyped_action == NULL ?
+        this->UntypedPerformDefaultAction(untyped_args, "") :
+        this->UntypedPerformAction(untyped_action, untyped_args);
+  }
+
+  ss << "    Function call: " << Name();
+  this->UntypedPrintArgs(untyped_args, &ss);
+
+  // In case the action deletes a piece of the expectation, we
+  // generate the message beforehand.
+  if (found && !is_excessive) {
+    untyped_expectation->DescribeLocationTo(&loc);
+  }
+
+  UntypedActionResultHolderBase* const result =
+      untyped_action == NULL ?
+      this->UntypedPerformDefaultAction(untyped_args, ss.str()) :
+      this->UntypedPerformAction(untyped_action, untyped_args);
+  if (result != NULL)
+    result->PrintAsActionResult(&ss);
+  ss << "\n" << why.str();
+
+  if (!found) {
+    // No expectation matches this call - reports a failure.
+    Expect(false, NULL, -1, ss.str());
+  } else if (is_excessive) {
+    // We had an upper-bound violation and the failure message is in ss.
+    Expect(false, untyped_expectation->file(),
+           untyped_expectation->line(), ss.str());
+  } else {
+    // We had an expected call and the matching expectation is
+    // described in ss.
+    Log(kInfo, loc.str() + ss.str(), 2);
+  }
+
+  return result;
+}
+
+// Returns an Expectation object that references and co-owns exp,
+// which must be an expectation on this mock function.
+Expectation UntypedFunctionMockerBase::GetHandleOf(ExpectationBase* exp) {
+  for (UntypedExpectations::const_iterator it =
+           untyped_expectations_.begin();
+       it != untyped_expectations_.end(); ++it) {
+    if (it->get() == exp) {
+      return Expectation(*it);
+    }
+  }
+
+  Assert(false, __FILE__, __LINE__, "Cannot find expectation.");
+  return Expectation();
+  // The above statement is just to make the code compile, and will
+  // never be executed.
+}
+
+// Verifies that all expectations on this mock function have been
+// satisfied.  Reports one or more Google Test non-fatal failures
+// and returns false if not.
+bool UntypedFunctionMockerBase::VerifyAndClearExpectationsLocked()
+    GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
+  g_gmock_mutex.AssertHeld();
+  bool expectations_met = true;
+  for (UntypedExpectations::const_iterator it =
+           untyped_expectations_.begin();
+       it != untyped_expectations_.end(); ++it) {
+    ExpectationBase* const untyped_expectation = it->get();
+    if (untyped_expectation->IsOverSaturated()) {
+      // There was an upper-bound violation.  Since the error was
+      // already reported when it occurred, there is no need to do
+      // anything here.
+      expectations_met = false;
+    } else if (!untyped_expectation->IsSatisfied()) {
+      expectations_met = false;
+      ::std::stringstream ss;
+      ss  << "Actual function call count doesn't match "
+          << untyped_expectation->source_text() << "...\n";
+      // No need to show the source file location of the expectation
+      // in the description, as the Expect() call that follows already
+      // takes care of it.
+      untyped_expectation->MaybeDescribeExtraMatcherTo(&ss);
+      untyped_expectation->DescribeCallCountTo(&ss);
+      Expect(false, untyped_expectation->file(),
+             untyped_expectation->line(), ss.str());
+    }
+  }
+
+  // Deleting our expectations may trigger other mock objects to be deleted, for
+  // example if an action contains a reference counted smart pointer to that
+  // mock object, and that is the last reference. So if we delete our
+  // expectations within the context of the global mutex we may deadlock when
+  // this method is called again. Instead, make a copy of the set of
+  // expectations to delete, clear our set within the mutex, and then clear the
+  // copied set outside of it.
+  UntypedExpectations expectations_to_delete;
+  untyped_expectations_.swap(expectations_to_delete);
+
+  g_gmock_mutex.Unlock();
+  expectations_to_delete.clear();
+  g_gmock_mutex.Lock();
+
+  return expectations_met;
+}
+
+}  // namespace internal
+
+// Class Mock.
+
+namespace {
+
+typedef std::set<internal::UntypedFunctionMockerBase*> FunctionMockers;
+
+// The current state of a mock object.  Such information is needed for
+// detecting leaked mock objects and explicitly verifying a mock's
+// expectations.
+struct MockObjectState {
+  MockObjectState()
+      : first_used_file(NULL), first_used_line(-1), leakable(false) {}
+
+  // Where in the source file an ON_CALL or EXPECT_CALL is first
+  // invoked on this mock object.
+  const char* first_used_file;
+  int first_used_line;
+  ::std::string first_used_test_case;
+  ::std::string first_used_test;
+  bool leakable;  // true iff it's OK to leak the object.
+  FunctionMockers function_mockers;  // All registered methods of the object.
+};
+
+// A global registry holding the state of all mock objects that are
+// alive.  A mock object is added to this registry the first time
+// Mock::AllowLeak(), ON_CALL(), or EXPECT_CALL() is called on it.  It
+// is removed from the registry in the mock object's destructor.
+class MockObjectRegistry {
+ public:
+  // Maps a mock object (identified by its address) to its state.
+  typedef std::map<const void*, MockObjectState> StateMap;
+
+  // This destructor will be called when a program exits, after all
+  // tests in it have been run.  By then, there should be no mock
+  // object alive.  Therefore we report any living object as test
+  // failure, unless the user explicitly asked us to ignore it.
+  ~MockObjectRegistry() {
+    // "using ::std::cout;" doesn't work with Symbian's STLport, where cout is
+    // a macro.
+
+    if (!GMOCK_FLAG(catch_leaked_mocks))
+      return;
+
+    int leaked_count = 0;
+    for (StateMap::const_iterator it = states_.begin(); it != states_.end();
+         ++it) {
+      if (it->second.leakable)  // The user said it's fine to leak this object.
+        continue;
+
+      // TODO(wan@google.com): Print the type of the leaked object.
+      // This can help the user identify the leaked object.
+      std::cout << "\n";
+      const MockObjectState& state = it->second;
+      std::cout << internal::FormatFileLocation(state.first_used_file,
+                                                state.first_used_line);
+      std::cout << " ERROR: this mock object";
+      if (state.first_used_test != "") {
+        std::cout << " (used in test " << state.first_used_test_case << "."
+             << state.first_used_test << ")";
+      }
+      std::cout << " should be deleted but never is. Its address is @"
+           << it->first << ".";
+      leaked_count++;
+    }
+    if (leaked_count > 0) {
+      std::cout << "\nERROR: " << leaked_count
+           << " leaked mock " << (leaked_count == 1 ? "object" : "objects")
+           << " found at program exit.\n";
+      std::cout.flush();
+      ::std::cerr.flush();
+      // RUN_ALL_TESTS() has already returned when this destructor is
+      // called.  Therefore we cannot use the normal Google Test
+      // failure reporting mechanism.
+      _exit(1);  // We cannot call exit() as it is not reentrant and
+                 // may already have been called.
+    }
+  }
+
+  StateMap& states() { return states_; }
+
+ private:
+  StateMap states_;
+};
+
+// Protected by g_gmock_mutex.
+MockObjectRegistry g_mock_object_registry;
+
+// Maps a mock object to the reaction Google Mock should have when an
+// uninteresting method is called.  Protected by g_gmock_mutex.
+std::map<const void*, internal::CallReaction> g_uninteresting_call_reaction;
+
+// Sets the reaction Google Mock should have when an uninteresting
+// method of the given mock object is called.
+void SetReactionOnUninterestingCalls(const void* mock_obj,
+                                     internal::CallReaction reaction)
+    GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  g_uninteresting_call_reaction[mock_obj] = reaction;
+}
+
+}  // namespace
+
+// Tells Google Mock to allow uninteresting calls on the given mock
+// object.
+void Mock::AllowUninterestingCalls(const void* mock_obj)
+    GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
+  SetReactionOnUninterestingCalls(mock_obj, internal::kAllow);
+}
+
+// Tells Google Mock to warn the user about uninteresting calls on the
+// given mock object.
+void Mock::WarnUninterestingCalls(const void* mock_obj)
+    GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
+  SetReactionOnUninterestingCalls(mock_obj, internal::kWarn);
+}
+
+// Tells Google Mock to fail uninteresting calls on the given mock
+// object.
+void Mock::FailUninterestingCalls(const void* mock_obj)
+    GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
+  SetReactionOnUninterestingCalls(mock_obj, internal::kFail);
+}
+
+// Tells Google Mock the given mock object is being destroyed and its
+// entry in the call-reaction table should be removed.
+void Mock::UnregisterCallReaction(const void* mock_obj)
+    GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  g_uninteresting_call_reaction.erase(mock_obj);
+}
+
+// Returns the reaction Google Mock will have on uninteresting calls
+// made on the given mock object.
+internal::CallReaction Mock::GetReactionOnUninterestingCalls(
+    const void* mock_obj)
+        GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  return (g_uninteresting_call_reaction.count(mock_obj) == 0) ?
+      internal::kDefault : g_uninteresting_call_reaction[mock_obj];
+}
+
+// Tells Google Mock to ignore mock_obj when checking for leaked mock
+// objects.
+void Mock::AllowLeak(const void* mock_obj)
+    GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  g_mock_object_registry.states()[mock_obj].leakable = true;
+}
+
+// Verifies and clears all expectations on the given mock object.  If
+// the expectations aren't satisfied, generates one or more Google
+// Test non-fatal failures and returns false.
+bool Mock::VerifyAndClearExpectations(void* mock_obj)
+    GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  return VerifyAndClearExpectationsLocked(mock_obj);
+}
+
+// Verifies all expectations on the given mock object and clears its
+// default actions and expectations.  Returns true iff the
+// verification was successful.
+bool Mock::VerifyAndClear(void* mock_obj)
+    GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  ClearDefaultActionsLocked(mock_obj);
+  return VerifyAndClearExpectationsLocked(mock_obj);
+}
+
+// Verifies and clears all expectations on the given mock object.  If
+// the expectations aren't satisfied, generates one or more Google
+// Test non-fatal failures and returns false.
+bool Mock::VerifyAndClearExpectationsLocked(void* mock_obj)
+    GTEST_EXCLUSIVE_LOCK_REQUIRED_(internal::g_gmock_mutex) {
+  internal::g_gmock_mutex.AssertHeld();
+  if (g_mock_object_registry.states().count(mock_obj) == 0) {
+    // No EXPECT_CALL() was set on the given mock object.
+    return true;
+  }
+
+  // Verifies and clears the expectations on each mock method in the
+  // given mock object.
+  bool expectations_met = true;
+  FunctionMockers& mockers =
+      g_mock_object_registry.states()[mock_obj].function_mockers;
+  for (FunctionMockers::const_iterator it = mockers.begin();
+       it != mockers.end(); ++it) {
+    if (!(*it)->VerifyAndClearExpectationsLocked()) {
+      expectations_met = false;
+    }
+  }
+
+  // We don't clear the content of mockers, as they may still be
+  // needed by ClearDefaultActionsLocked().
+  return expectations_met;
+}
+
+// Registers a mock object and a mock method it owns.
+void Mock::Register(const void* mock_obj,
+                    internal::UntypedFunctionMockerBase* mocker)
+    GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  g_mock_object_registry.states()[mock_obj].function_mockers.insert(mocker);
+}
+
+// Tells Google Mock where in the source code mock_obj is used in an
+// ON_CALL or EXPECT_CALL.  In case mock_obj is leaked, this
+// information helps the user identify which object it is.
+void Mock::RegisterUseByOnCallOrExpectCall(const void* mock_obj,
+                                           const char* file, int line)
+    GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  MockObjectState& state = g_mock_object_registry.states()[mock_obj];
+  if (state.first_used_file == NULL) {
+    state.first_used_file = file;
+    state.first_used_line = line;
+    const TestInfo* const test_info =
+        UnitTest::GetInstance()->current_test_info();
+    if (test_info != NULL) {
+      // TODO(wan@google.com): record the test case name when the
+      // ON_CALL or EXPECT_CALL is invoked from SetUpTestCase() or
+      // TearDownTestCase().
+      state.first_used_test_case = test_info->test_case_name();
+      state.first_used_test = test_info->name();
+    }
+  }
+}
+
+// Unregisters a mock method; removes the owning mock object from the
+// registry when the last mock method associated with it has been
+// unregistered.  This is called only in the destructor of
+// FunctionMockerBase.
+void Mock::UnregisterLocked(internal::UntypedFunctionMockerBase* mocker)
+    GTEST_EXCLUSIVE_LOCK_REQUIRED_(internal::g_gmock_mutex) {
+  internal::g_gmock_mutex.AssertHeld();
+  for (MockObjectRegistry::StateMap::iterator it =
+           g_mock_object_registry.states().begin();
+       it != g_mock_object_registry.states().end(); ++it) {
+    FunctionMockers& mockers = it->second.function_mockers;
+    if (mockers.erase(mocker) > 0) {
+      // mocker was in mockers and has been just removed.
+      if (mockers.empty()) {
+        g_mock_object_registry.states().erase(it);
+      }
+      return;
+    }
+  }
+}
+
+// Clears all ON_CALL()s set on the given mock object.
+void Mock::ClearDefaultActionsLocked(void* mock_obj)
+    GTEST_EXCLUSIVE_LOCK_REQUIRED_(internal::g_gmock_mutex) {
+  internal::g_gmock_mutex.AssertHeld();
+
+  if (g_mock_object_registry.states().count(mock_obj) == 0) {
+    // No ON_CALL() was set on the given mock object.
+    return;
+  }
+
+  // Clears the default actions for each mock method in the given mock
+  // object.
+  FunctionMockers& mockers =
+      g_mock_object_registry.states()[mock_obj].function_mockers;
+  for (FunctionMockers::const_iterator it = mockers.begin();
+       it != mockers.end(); ++it) {
+    (*it)->ClearDefaultActionsLocked();
+  }
+
+  // We don't clear the content of mockers, as they may still be
+  // needed by VerifyAndClearExpectationsLocked().
+}
+
+Expectation::Expectation() {}
+
+Expectation::Expectation(
+    const internal::linked_ptr<internal::ExpectationBase>& an_expectation_base)
+    : expectation_base_(an_expectation_base) {}
+
+Expectation::~Expectation() {}
+
+// Adds an expectation to a sequence.
+void Sequence::AddExpectation(const Expectation& expectation) const {
+  if (*last_expectation_ != expectation) {
+    if (last_expectation_->expectation_base() != NULL) {
+      expectation.expectation_base()->immediate_prerequisites_
+          += *last_expectation_;
+    }
+    *last_expectation_ = expectation;
+  }
+}
+
+// Creates the implicit sequence if there isn't one.
+InSequence::InSequence() {
+  if (internal::g_gmock_implicit_sequence.get() == NULL) {
+    internal::g_gmock_implicit_sequence.set(new Sequence);
+    sequence_created_ = true;
+  } else {
+    sequence_created_ = false;
+  }
+}
+
+// Deletes the implicit sequence if it was created by the constructor
+// of this object.
+InSequence::~InSequence() {
+  if (sequence_created_) {
+    delete internal::g_gmock_implicit_sequence.get();
+    internal::g_gmock_implicit_sequence.set(NULL);
+  }
+}
+
+}  // namespace testing
diff --git a/third_party/googletest/googlemock/src/gmock.cc b/third_party/googletest/googlemock/src/gmock.cc
new file mode 100644
index 0000000..eac3d84
--- /dev/null
+++ b/third_party/googletest/googlemock/src/gmock.cc
@@ -0,0 +1,183 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include "gmock/gmock.h"
+#include "gmock/internal/gmock-port.h"
+
+namespace testing {
+
+// TODO(wan@google.com): support using environment variables to
+// control the flag values, like what Google Test does.
+
+GMOCK_DEFINE_bool_(catch_leaked_mocks, true,
+                   "true iff Google Mock should report leaked mock objects "
+                   "as failures.");
+
+GMOCK_DEFINE_string_(verbose, internal::kWarningVerbosity,
+                     "Controls how verbose Google Mock's output is."
+                     "  Valid values:\n"
+                     "  info    - prints all messages.\n"
+                     "  warning - prints warnings and errors.\n"
+                     "  error   - prints errors only.");
+
+namespace internal {
+
+// Parses a string as a command line flag.  The string should have the
+// format "--gmock_flag=value".  When def_optional is true, the
+// "=value" part can be omitted.
+//
+// Returns the value of the flag, or NULL if the parsing failed.
+static const char* ParseGoogleMockFlagValue(const char* str,
+                                            const char* flag,
+                                            bool def_optional) {
+  // str and flag must not be NULL.
+  if (str == NULL || flag == NULL) return NULL;
+
+  // The flag must start with "--gmock_".
+  const std::string flag_str = std::string("--gmock_") + flag;
+  const size_t flag_len = flag_str.length();
+  if (strncmp(str, flag_str.c_str(), flag_len) != 0) return NULL;
+
+  // Skips the flag name.
+  const char* flag_end = str + flag_len;
+
+  // When def_optional is true, it's OK to not have a "=value" part.
+  if (def_optional && (flag_end[0] == '\0')) {
+    return flag_end;
+  }
+
+  // If def_optional is true and there are more characters after the
+  // flag name, or if def_optional is false, there must be a '=' after
+  // the flag name.
+  if (flag_end[0] != '=') return NULL;
+
+  // Returns the string after "=".
+  return flag_end + 1;
+}
+
+// Parses a string for a Google Mock bool flag, in the form of
+// "--gmock_flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+static bool ParseGoogleMockBoolFlag(const char* str, const char* flag,
+                                    bool* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseGoogleMockFlagValue(str, flag, true);
+
+  // Aborts if the parsing failed.
+  if (value_str == NULL) return false;
+
+  // Converts the string value to a bool.
+  *value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F');
+  return true;
+}
+
+// Parses a string for a Google Mock string flag, in the form of
+// "--gmock_flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+template <typename String>
+static bool ParseGoogleMockStringFlag(const char* str, const char* flag,
+                                      String* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseGoogleMockFlagValue(str, flag, false);
+
+  // Aborts if the parsing failed.
+  if (value_str == NULL) return false;
+
+  // Sets *value to the value of the flag.
+  *value = value_str;
+  return true;
+}
+
+// The internal implementation of InitGoogleMock().
+//
+// The type parameter CharType can be instantiated to either char or
+// wchar_t.
+template <typename CharType>
+void InitGoogleMockImpl(int* argc, CharType** argv) {
+  // Makes sure Google Test is initialized.  InitGoogleTest() is
+  // idempotent, so it's fine if the user has already called it.
+  InitGoogleTest(argc, argv);
+  if (*argc <= 0) return;
+
+  for (int i = 1; i != *argc; i++) {
+    const std::string arg_string = StreamableToString(argv[i]);
+    const char* const arg = arg_string.c_str();
+
+    // Do we see a Google Mock flag?
+    if (ParseGoogleMockBoolFlag(arg, "catch_leaked_mocks",
+                                &GMOCK_FLAG(catch_leaked_mocks)) ||
+        ParseGoogleMockStringFlag(arg, "verbose", &GMOCK_FLAG(verbose))) {
+      // Yes.  Shift the remainder of the argv list left by one.  Note
+      // that argv has (*argc + 1) elements, the last one always being
+      // NULL.  The following loop moves the trailing NULL element as
+      // well.
+      for (int j = i; j != *argc; j++) {
+        argv[j] = argv[j + 1];
+      }
+
+      // Decrements the argument count.
+      (*argc)--;
+
+      // We also need to decrement the iterator as we just removed
+      // an element.
+      i--;
+    }
+  }
+}
+
+}  // namespace internal
+
+// Initializes Google Mock.  This must be called before running the
+// tests.  In particular, it parses a command line for the flags that
+// Google Mock recognizes.  Whenever a Google Mock flag is seen, it is
+// removed from argv, and *argc is decremented.
+//
+// No value is returned.  Instead, the Google Mock flag variables are
+// updated.
+//
+// Since Google Test is needed for Google Mock to work, this function
+// also initializes Google Test and parses its flags, if that hasn't
+// been done.
+GTEST_API_ void InitGoogleMock(int* argc, char** argv) {
+  internal::InitGoogleMockImpl(argc, argv);
+}
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+GTEST_API_ void InitGoogleMock(int* argc, wchar_t** argv) {
+  internal::InitGoogleMockImpl(argc, argv);
+}
+
+}  // namespace testing
diff --git a/third_party/googletest/googlemock/src/gmock_main.cc b/third_party/googletest/googlemock/src/gmock_main.cc
new file mode 100644
index 0000000..bd5be03
--- /dev/null
+++ b/third_party/googletest/googlemock/src/gmock_main.cc
@@ -0,0 +1,54 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include <iostream>
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+// MS C++ compiler/linker has a bug on Windows (not on Windows CE), which
+// causes a link error when _tmain is defined in a static library and UNICODE
+// is enabled. For this reason instead of _tmain, main function is used on
+// Windows. See the following link to track the current status of this bug:
+// http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=394464  // NOLINT
+#if GTEST_OS_WINDOWS_MOBILE
+# include <tchar.h>  // NOLINT
+
+GTEST_API_ int _tmain(int argc, TCHAR** argv) {
+#else
+GTEST_API_ int main(int argc, char** argv) {
+#endif  // GTEST_OS_WINDOWS_MOBILE
+  std::cout << "Running main() from gmock_main.cc\n";
+  // Since Google Mock depends on Google Test, InitGoogleMock() is
+  // also responsible for initializing Google Test.  Therefore there's
+  // no need for calling testing::InitGoogleTest() separately.
+  testing::InitGoogleMock(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/googletest/googlemock/test/gmock-actions_test.cc b/third_party/googletest/googlemock/test/gmock-actions_test.cc
new file mode 100644
index 0000000..a665fc5
--- /dev/null
+++ b/third_party/googletest/googlemock/test/gmock-actions_test.cc
@@ -0,0 +1,1411 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests the built-in actions.
+
+#include "gmock/gmock-actions.h"
+#include <algorithm>
+#include <iterator>
+#include <memory>
+#include <string>
+#include "gmock/gmock.h"
+#include "gmock/internal/gmock-port.h"
+#include "gtest/gtest.h"
+#include "gtest/gtest-spi.h"
+
+namespace {
+
+// This list should be kept sorted.
+using testing::Action;
+using testing::ActionInterface;
+using testing::Assign;
+using testing::ByMove;
+using testing::ByRef;
+using testing::DefaultValue;
+using testing::DoDefault;
+using testing::IgnoreResult;
+using testing::Invoke;
+using testing::InvokeWithoutArgs;
+using testing::MakePolymorphicAction;
+using testing::Ne;
+using testing::PolymorphicAction;
+using testing::Return;
+using testing::ReturnNull;
+using testing::ReturnRef;
+using testing::ReturnRefOfCopy;
+using testing::SetArgPointee;
+using testing::SetArgumentPointee;
+using testing::_;
+using testing::get;
+using testing::internal::BuiltInDefaultValue;
+using testing::internal::Int64;
+using testing::internal::UInt64;
+using testing::make_tuple;
+using testing::tuple;
+using testing::tuple_element;
+
+#if !GTEST_OS_WINDOWS_MOBILE
+using testing::SetErrnoAndReturn;
+#endif
+
+#if GTEST_HAS_PROTOBUF_
+using testing::internal::TestMessage;
+#endif  // GTEST_HAS_PROTOBUF_
+
+// Tests that BuiltInDefaultValue<T*>::Get() returns NULL.
+TEST(BuiltInDefaultValueTest, IsNullForPointerTypes) {
+  EXPECT_TRUE(BuiltInDefaultValue<int*>::Get() == NULL);
+  EXPECT_TRUE(BuiltInDefaultValue<const char*>::Get() == NULL);
+  EXPECT_TRUE(BuiltInDefaultValue<void*>::Get() == NULL);
+}
+
+// Tests that BuiltInDefaultValue<T*>::Exists() return true.
+TEST(BuiltInDefaultValueTest, ExistsForPointerTypes) {
+  EXPECT_TRUE(BuiltInDefaultValue<int*>::Exists());
+  EXPECT_TRUE(BuiltInDefaultValue<const char*>::Exists());
+  EXPECT_TRUE(BuiltInDefaultValue<void*>::Exists());
+}
+
+// Tests that BuiltInDefaultValue<T>::Get() returns 0 when T is a
+// built-in numeric type.
+TEST(BuiltInDefaultValueTest, IsZeroForNumericTypes) {
+  EXPECT_EQ(0U, BuiltInDefaultValue<unsigned char>::Get());
+  EXPECT_EQ(0, BuiltInDefaultValue<signed char>::Get());
+  EXPECT_EQ(0, BuiltInDefaultValue<char>::Get());
+#if GMOCK_HAS_SIGNED_WCHAR_T_
+  EXPECT_EQ(0U, BuiltInDefaultValue<unsigned wchar_t>::Get());
+  EXPECT_EQ(0, BuiltInDefaultValue<signed wchar_t>::Get());
+#endif
+#if GMOCK_WCHAR_T_IS_NATIVE_
+  EXPECT_EQ(0, BuiltInDefaultValue<wchar_t>::Get());
+#endif
+  EXPECT_EQ(0U, BuiltInDefaultValue<unsigned short>::Get());  // NOLINT
+  EXPECT_EQ(0, BuiltInDefaultValue<signed short>::Get());  // NOLINT
+  EXPECT_EQ(0, BuiltInDefaultValue<short>::Get());  // NOLINT
+  EXPECT_EQ(0U, BuiltInDefaultValue<unsigned int>::Get());
+  EXPECT_EQ(0, BuiltInDefaultValue<signed int>::Get());
+  EXPECT_EQ(0, BuiltInDefaultValue<int>::Get());
+  EXPECT_EQ(0U, BuiltInDefaultValue<unsigned long>::Get());  // NOLINT
+  EXPECT_EQ(0, BuiltInDefaultValue<signed long>::Get());  // NOLINT
+  EXPECT_EQ(0, BuiltInDefaultValue<long>::Get());  // NOLINT
+  EXPECT_EQ(0U, BuiltInDefaultValue<UInt64>::Get());
+  EXPECT_EQ(0, BuiltInDefaultValue<Int64>::Get());
+  EXPECT_EQ(0, BuiltInDefaultValue<float>::Get());
+  EXPECT_EQ(0, BuiltInDefaultValue<double>::Get());
+}
+
+// Tests that BuiltInDefaultValue<T>::Exists() returns true when T is a
+// built-in numeric type.
+TEST(BuiltInDefaultValueTest, ExistsForNumericTypes) {
+  EXPECT_TRUE(BuiltInDefaultValue<unsigned char>::Exists());
+  EXPECT_TRUE(BuiltInDefaultValue<signed char>::Exists());
+  EXPECT_TRUE(BuiltInDefaultValue<char>::Exists());
+#if GMOCK_HAS_SIGNED_WCHAR_T_
+  EXPECT_TRUE(BuiltInDefaultValue<unsigned wchar_t>::Exists());
+  EXPECT_TRUE(BuiltInDefaultValue<signed wchar_t>::Exists());
+#endif
+#if GMOCK_WCHAR_T_IS_NATIVE_
+  EXPECT_TRUE(BuiltInDefaultValue<wchar_t>::Exists());
+#endif
+  EXPECT_TRUE(BuiltInDefaultValue<unsigned short>::Exists());  // NOLINT
+  EXPECT_TRUE(BuiltInDefaultValue<signed short>::Exists());  // NOLINT
+  EXPECT_TRUE(BuiltInDefaultValue<short>::Exists());  // NOLINT
+  EXPECT_TRUE(BuiltInDefaultValue<unsigned int>::Exists());
+  EXPECT_TRUE(BuiltInDefaultValue<signed int>::Exists());
+  EXPECT_TRUE(BuiltInDefaultValue<int>::Exists());
+  EXPECT_TRUE(BuiltInDefaultValue<unsigned long>::Exists());  // NOLINT
+  EXPECT_TRUE(BuiltInDefaultValue<signed long>::Exists());  // NOLINT
+  EXPECT_TRUE(BuiltInDefaultValue<long>::Exists());  // NOLINT
+  EXPECT_TRUE(BuiltInDefaultValue<UInt64>::Exists());
+  EXPECT_TRUE(BuiltInDefaultValue<Int64>::Exists());
+  EXPECT_TRUE(BuiltInDefaultValue<float>::Exists());
+  EXPECT_TRUE(BuiltInDefaultValue<double>::Exists());
+}
+
+// Tests that BuiltInDefaultValue<bool>::Get() returns false.
+TEST(BuiltInDefaultValueTest, IsFalseForBool) {
+  EXPECT_FALSE(BuiltInDefaultValue<bool>::Get());
+}
+
+// Tests that BuiltInDefaultValue<bool>::Exists() returns true.
+TEST(BuiltInDefaultValueTest, BoolExists) {
+  EXPECT_TRUE(BuiltInDefaultValue<bool>::Exists());
+}
+
+// Tests that BuiltInDefaultValue<T>::Get() returns "" when T is a
+// string type.
+TEST(BuiltInDefaultValueTest, IsEmptyStringForString) {
+#if GTEST_HAS_GLOBAL_STRING
+  EXPECT_EQ("", BuiltInDefaultValue< ::string>::Get());
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+  EXPECT_EQ("", BuiltInDefaultValue< ::std::string>::Get());
+}
+
+// Tests that BuiltInDefaultValue<T>::Exists() returns true when T is a
+// string type.
+TEST(BuiltInDefaultValueTest, ExistsForString) {
+#if GTEST_HAS_GLOBAL_STRING
+  EXPECT_TRUE(BuiltInDefaultValue< ::string>::Exists());
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+  EXPECT_TRUE(BuiltInDefaultValue< ::std::string>::Exists());
+}
+
+// Tests that BuiltInDefaultValue<const T>::Get() returns the same
+// value as BuiltInDefaultValue<T>::Get() does.
+TEST(BuiltInDefaultValueTest, WorksForConstTypes) {
+  EXPECT_EQ("", BuiltInDefaultValue<const std::string>::Get());
+  EXPECT_EQ(0, BuiltInDefaultValue<const int>::Get());
+  EXPECT_TRUE(BuiltInDefaultValue<char* const>::Get() == NULL);
+  EXPECT_FALSE(BuiltInDefaultValue<const bool>::Get());
+}
+
+// A type that's default constructible.
+class MyDefaultConstructible {
+ public:
+  MyDefaultConstructible() : value_(42) {}
+
+  int value() const { return value_; }
+
+ private:
+  int value_;
+};
+
+// A type that's not default constructible.
+class MyNonDefaultConstructible {
+ public:
+  // Does not have a default ctor.
+  explicit MyNonDefaultConstructible(int a_value) : value_(a_value) {}
+
+  int value() const { return value_; }
+
+ private:
+  int value_;
+};
+
+#if GTEST_LANG_CXX11
+
+TEST(BuiltInDefaultValueTest, ExistsForDefaultConstructibleType) {
+  EXPECT_TRUE(BuiltInDefaultValue<MyDefaultConstructible>::Exists());
+}
+
+TEST(BuiltInDefaultValueTest, IsDefaultConstructedForDefaultConstructibleType) {
+  EXPECT_EQ(42, BuiltInDefaultValue<MyDefaultConstructible>::Get().value());
+}
+
+#endif  // GTEST_LANG_CXX11
+
+TEST(BuiltInDefaultValueTest, DoesNotExistForNonDefaultConstructibleType) {
+  EXPECT_FALSE(BuiltInDefaultValue<MyNonDefaultConstructible>::Exists());
+}
+
+// Tests that BuiltInDefaultValue<T&>::Get() aborts the program.
+TEST(BuiltInDefaultValueDeathTest, IsUndefinedForReferences) {
+  EXPECT_DEATH_IF_SUPPORTED({
+    BuiltInDefaultValue<int&>::Get();
+  }, "");
+  EXPECT_DEATH_IF_SUPPORTED({
+    BuiltInDefaultValue<const char&>::Get();
+  }, "");
+}
+
+TEST(BuiltInDefaultValueDeathTest, IsUndefinedForNonDefaultConstructibleType) {
+  EXPECT_DEATH_IF_SUPPORTED({
+    BuiltInDefaultValue<MyNonDefaultConstructible>::Get();
+  }, "");
+}
+
+// Tests that DefaultValue<T>::IsSet() is false initially.
+TEST(DefaultValueTest, IsInitiallyUnset) {
+  EXPECT_FALSE(DefaultValue<int>::IsSet());
+  EXPECT_FALSE(DefaultValue<MyDefaultConstructible>::IsSet());
+  EXPECT_FALSE(DefaultValue<const MyNonDefaultConstructible>::IsSet());
+}
+
+// Tests that DefaultValue<T> can be set and then unset.
+TEST(DefaultValueTest, CanBeSetAndUnset) {
+  EXPECT_TRUE(DefaultValue<int>::Exists());
+  EXPECT_FALSE(DefaultValue<const MyNonDefaultConstructible>::Exists());
+
+  DefaultValue<int>::Set(1);
+  DefaultValue<const MyNonDefaultConstructible>::Set(
+      MyNonDefaultConstructible(42));
+
+  EXPECT_EQ(1, DefaultValue<int>::Get());
+  EXPECT_EQ(42, DefaultValue<const MyNonDefaultConstructible>::Get().value());
+
+  EXPECT_TRUE(DefaultValue<int>::Exists());
+  EXPECT_TRUE(DefaultValue<const MyNonDefaultConstructible>::Exists());
+
+  DefaultValue<int>::Clear();
+  DefaultValue<const MyNonDefaultConstructible>::Clear();
+
+  EXPECT_FALSE(DefaultValue<int>::IsSet());
+  EXPECT_FALSE(DefaultValue<const MyNonDefaultConstructible>::IsSet());
+
+  EXPECT_TRUE(DefaultValue<int>::Exists());
+  EXPECT_FALSE(DefaultValue<const MyNonDefaultConstructible>::Exists());
+}
+
+// Tests that DefaultValue<T>::Get() returns the
+// BuiltInDefaultValue<T>::Get() when DefaultValue<T>::IsSet() is
+// false.
+TEST(DefaultValueDeathTest, GetReturnsBuiltInDefaultValueWhenUnset) {
+  EXPECT_FALSE(DefaultValue<int>::IsSet());
+  EXPECT_TRUE(DefaultValue<int>::Exists());
+  EXPECT_FALSE(DefaultValue<MyNonDefaultConstructible>::IsSet());
+  EXPECT_FALSE(DefaultValue<MyNonDefaultConstructible>::Exists());
+
+  EXPECT_EQ(0, DefaultValue<int>::Get());
+
+  EXPECT_DEATH_IF_SUPPORTED({
+    DefaultValue<MyNonDefaultConstructible>::Get();
+  }, "");
+}
+
+#if GTEST_HAS_STD_UNIQUE_PTR_
+TEST(DefaultValueTest, GetWorksForMoveOnlyIfSet) {
+  EXPECT_TRUE(DefaultValue<std::unique_ptr<int>>::Exists());
+  EXPECT_TRUE(DefaultValue<std::unique_ptr<int>>::Get() == NULL);
+  DefaultValue<std::unique_ptr<int>>::SetFactory([] {
+    return std::unique_ptr<int>(new int(42));
+  });
+  EXPECT_TRUE(DefaultValue<std::unique_ptr<int>>::Exists());
+  std::unique_ptr<int> i = DefaultValue<std::unique_ptr<int>>::Get();
+  EXPECT_EQ(42, *i);
+}
+#endif  // GTEST_HAS_STD_UNIQUE_PTR_
+
+// Tests that DefaultValue<void>::Get() returns void.
+TEST(DefaultValueTest, GetWorksForVoid) {
+  return DefaultValue<void>::Get();
+}
+
+// Tests using DefaultValue with a reference type.
+
+// Tests that DefaultValue<T&>::IsSet() is false initially.
+TEST(DefaultValueOfReferenceTest, IsInitiallyUnset) {
+  EXPECT_FALSE(DefaultValue<int&>::IsSet());
+  EXPECT_FALSE(DefaultValue<MyDefaultConstructible&>::IsSet());
+  EXPECT_FALSE(DefaultValue<MyNonDefaultConstructible&>::IsSet());
+}
+
+// Tests that DefaultValue<T&>::Exists is false initiallly.
+TEST(DefaultValueOfReferenceTest, IsInitiallyNotExisting) {
+  EXPECT_FALSE(DefaultValue<int&>::Exists());
+  EXPECT_FALSE(DefaultValue<MyDefaultConstructible&>::Exists());
+  EXPECT_FALSE(DefaultValue<MyNonDefaultConstructible&>::Exists());
+}
+
+// Tests that DefaultValue<T&> can be set and then unset.
+TEST(DefaultValueOfReferenceTest, CanBeSetAndUnset) {
+  int n = 1;
+  DefaultValue<const int&>::Set(n);
+  MyNonDefaultConstructible x(42);
+  DefaultValue<MyNonDefaultConstructible&>::Set(x);
+
+  EXPECT_TRUE(DefaultValue<const int&>::Exists());
+  EXPECT_TRUE(DefaultValue<MyNonDefaultConstructible&>::Exists());
+
+  EXPECT_EQ(&n, &(DefaultValue<const int&>::Get()));
+  EXPECT_EQ(&x, &(DefaultValue<MyNonDefaultConstructible&>::Get()));
+
+  DefaultValue<const int&>::Clear();
+  DefaultValue<MyNonDefaultConstructible&>::Clear();
+
+  EXPECT_FALSE(DefaultValue<const int&>::Exists());
+  EXPECT_FALSE(DefaultValue<MyNonDefaultConstructible&>::Exists());
+
+  EXPECT_FALSE(DefaultValue<const int&>::IsSet());
+  EXPECT_FALSE(DefaultValue<MyNonDefaultConstructible&>::IsSet());
+}
+
+// Tests that DefaultValue<T&>::Get() returns the
+// BuiltInDefaultValue<T&>::Get() when DefaultValue<T&>::IsSet() is
+// false.
+TEST(DefaultValueOfReferenceDeathTest, GetReturnsBuiltInDefaultValueWhenUnset) {
+  EXPECT_FALSE(DefaultValue<int&>::IsSet());
+  EXPECT_FALSE(DefaultValue<MyNonDefaultConstructible&>::IsSet());
+
+  EXPECT_DEATH_IF_SUPPORTED({
+    DefaultValue<int&>::Get();
+  }, "");
+  EXPECT_DEATH_IF_SUPPORTED({
+    DefaultValue<MyNonDefaultConstructible>::Get();
+  }, "");
+}
+
+// Tests that ActionInterface can be implemented by defining the
+// Perform method.
+
+typedef int MyGlobalFunction(bool, int);
+
+class MyActionImpl : public ActionInterface<MyGlobalFunction> {
+ public:
+  virtual int Perform(const tuple<bool, int>& args) {
+    return get<0>(args) ? get<1>(args) : 0;
+  }
+};
+
+TEST(ActionInterfaceTest, CanBeImplementedByDefiningPerform) {
+  MyActionImpl my_action_impl;
+  (void)my_action_impl;
+}
+
+TEST(ActionInterfaceTest, MakeAction) {
+  Action<MyGlobalFunction> action = MakeAction(new MyActionImpl);
+
+  // When exercising the Perform() method of Action<F>, we must pass
+  // it a tuple whose size and type are compatible with F's argument
+  // types.  For example, if F is int(), then Perform() takes a
+  // 0-tuple; if F is void(bool, int), then Perform() takes a
+  // tuple<bool, int>, and so on.
+  EXPECT_EQ(5, action.Perform(make_tuple(true, 5)));
+}
+
+// Tests that Action<F> can be contructed from a pointer to
+// ActionInterface<F>.
+TEST(ActionTest, CanBeConstructedFromActionInterface) {
+  Action<MyGlobalFunction> action(new MyActionImpl);
+}
+
+// Tests that Action<F> delegates actual work to ActionInterface<F>.
+TEST(ActionTest, DelegatesWorkToActionInterface) {
+  const Action<MyGlobalFunction> action(new MyActionImpl);
+
+  EXPECT_EQ(5, action.Perform(make_tuple(true, 5)));
+  EXPECT_EQ(0, action.Perform(make_tuple(false, 1)));
+}
+
+// Tests that Action<F> can be copied.
+TEST(ActionTest, IsCopyable) {
+  Action<MyGlobalFunction> a1(new MyActionImpl);
+  Action<MyGlobalFunction> a2(a1);  // Tests the copy constructor.
+
+  // a1 should continue to work after being copied from.
+  EXPECT_EQ(5, a1.Perform(make_tuple(true, 5)));
+  EXPECT_EQ(0, a1.Perform(make_tuple(false, 1)));
+
+  // a2 should work like the action it was copied from.
+  EXPECT_EQ(5, a2.Perform(make_tuple(true, 5)));
+  EXPECT_EQ(0, a2.Perform(make_tuple(false, 1)));
+
+  a2 = a1;  // Tests the assignment operator.
+
+  // a1 should continue to work after being copied from.
+  EXPECT_EQ(5, a1.Perform(make_tuple(true, 5)));
+  EXPECT_EQ(0, a1.Perform(make_tuple(false, 1)));
+
+  // a2 should work like the action it was copied from.
+  EXPECT_EQ(5, a2.Perform(make_tuple(true, 5)));
+  EXPECT_EQ(0, a2.Perform(make_tuple(false, 1)));
+}
+
+// Tests that an Action<From> object can be converted to a
+// compatible Action<To> object.
+
+class IsNotZero : public ActionInterface<bool(int)> {  // NOLINT
+ public:
+  virtual bool Perform(const tuple<int>& arg) {
+    return get<0>(arg) != 0;
+  }
+};
+
+#if !GTEST_OS_SYMBIAN
+// Compiling this test on Nokia's Symbian compiler fails with:
+//  'Result' is not a member of class 'testing::internal::Function<int>'
+//  (point of instantiation: '@unnamed@gmock_actions_test_cc@::
+//      ActionTest_CanBeConvertedToOtherActionType_Test::TestBody()')
+// with no obvious fix.
+TEST(ActionTest, CanBeConvertedToOtherActionType) {
+  const Action<bool(int)> a1(new IsNotZero);  // NOLINT
+  const Action<int(char)> a2 = Action<int(char)>(a1);  // NOLINT
+  EXPECT_EQ(1, a2.Perform(make_tuple('a')));
+  EXPECT_EQ(0, a2.Perform(make_tuple('\0')));
+}
+#endif  // !GTEST_OS_SYMBIAN
+
+// The following two classes are for testing MakePolymorphicAction().
+
+// Implements a polymorphic action that returns the second of the
+// arguments it receives.
+class ReturnSecondArgumentAction {
+ public:
+  // We want to verify that MakePolymorphicAction() can work with a
+  // polymorphic action whose Perform() method template is either
+  // const or not.  This lets us verify the non-const case.
+  template <typename Result, typename ArgumentTuple>
+  Result Perform(const ArgumentTuple& args) { return get<1>(args); }
+};
+
+// Implements a polymorphic action that can be used in a nullary
+// function to return 0.
+class ReturnZeroFromNullaryFunctionAction {
+ public:
+  // For testing that MakePolymorphicAction() works when the
+  // implementation class' Perform() method template takes only one
+  // template parameter.
+  //
+  // We want to verify that MakePolymorphicAction() can work with a
+  // polymorphic action whose Perform() method template is either
+  // const or not.  This lets us verify the const case.
+  template <typename Result>
+  Result Perform(const tuple<>&) const { return 0; }
+};
+
+// These functions verify that MakePolymorphicAction() returns a
+// PolymorphicAction<T> where T is the argument's type.
+
+PolymorphicAction<ReturnSecondArgumentAction> ReturnSecondArgument() {
+  return MakePolymorphicAction(ReturnSecondArgumentAction());
+}
+
+PolymorphicAction<ReturnZeroFromNullaryFunctionAction>
+ReturnZeroFromNullaryFunction() {
+  return MakePolymorphicAction(ReturnZeroFromNullaryFunctionAction());
+}
+
+// Tests that MakePolymorphicAction() turns a polymorphic action
+// implementation class into a polymorphic action.
+TEST(MakePolymorphicActionTest, ConstructsActionFromImpl) {
+  Action<int(bool, int, double)> a1 = ReturnSecondArgument();  // NOLINT
+  EXPECT_EQ(5, a1.Perform(make_tuple(false, 5, 2.0)));
+}
+
+// Tests that MakePolymorphicAction() works when the implementation
+// class' Perform() method template has only one template parameter.
+TEST(MakePolymorphicActionTest, WorksWhenPerformHasOneTemplateParameter) {
+  Action<int()> a1 = ReturnZeroFromNullaryFunction();
+  EXPECT_EQ(0, a1.Perform(make_tuple()));
+
+  Action<void*()> a2 = ReturnZeroFromNullaryFunction();
+  EXPECT_TRUE(a2.Perform(make_tuple()) == NULL);
+}
+
+// Tests that Return() works as an action for void-returning
+// functions.
+TEST(ReturnTest, WorksForVoid) {
+  const Action<void(int)> ret = Return();  // NOLINT
+  return ret.Perform(make_tuple(1));
+}
+
+// Tests that Return(v) returns v.
+TEST(ReturnTest, ReturnsGivenValue) {
+  Action<int()> ret = Return(1);  // NOLINT
+  EXPECT_EQ(1, ret.Perform(make_tuple()));
+
+  ret = Return(-5);
+  EXPECT_EQ(-5, ret.Perform(make_tuple()));
+}
+
+// Tests that Return("string literal") works.
+TEST(ReturnTest, AcceptsStringLiteral) {
+  Action<const char*()> a1 = Return("Hello");
+  EXPECT_STREQ("Hello", a1.Perform(make_tuple()));
+
+  Action<std::string()> a2 = Return("world");
+  EXPECT_EQ("world", a2.Perform(make_tuple()));
+}
+
+// Test struct which wraps a vector of integers. Used in
+// 'SupportsWrapperReturnType' test.
+struct IntegerVectorWrapper {
+  std::vector<int> * v;
+  IntegerVectorWrapper(std::vector<int>& _v) : v(&_v) {}  // NOLINT
+};
+
+// Tests that Return() works when return type is a wrapper type.
+TEST(ReturnTest, SupportsWrapperReturnType) {
+  // Initialize vector of integers.
+  std::vector<int> v;
+  for (int i = 0; i < 5; ++i) v.push_back(i);
+
+  // Return() called with 'v' as argument. The Action will return the same data
+  // as 'v' (copy) but it will be wrapped in an IntegerVectorWrapper.
+  Action<IntegerVectorWrapper()> a = Return(v);
+  const std::vector<int>& result = *(a.Perform(make_tuple()).v);
+  EXPECT_THAT(result, ::testing::ElementsAre(0, 1, 2, 3, 4));
+}
+
+// Tests that Return(v) is covaraint.
+
+struct Base {
+  bool operator==(const Base&) { return true; }
+};
+
+struct Derived : public Base {
+  bool operator==(const Derived&) { return true; }
+};
+
+TEST(ReturnTest, IsCovariant) {
+  Base base;
+  Derived derived;
+  Action<Base*()> ret = Return(&base);
+  EXPECT_EQ(&base, ret.Perform(make_tuple()));
+
+  ret = Return(&derived);
+  EXPECT_EQ(&derived, ret.Perform(make_tuple()));
+}
+
+// Tests that the type of the value passed into Return is converted into T
+// when the action is cast to Action<T(...)> rather than when the action is
+// performed. See comments on testing::internal::ReturnAction in
+// gmock-actions.h for more information.
+class FromType {
+ public:
+  explicit FromType(bool* is_converted) : converted_(is_converted) {}
+  bool* converted() const { return converted_; }
+
+ private:
+  bool* const converted_;
+
+  GTEST_DISALLOW_ASSIGN_(FromType);
+};
+
+class ToType {
+ public:
+  // Must allow implicit conversion due to use in ImplicitCast_<T>.
+  ToType(const FromType& x) { *x.converted() = true; }  // NOLINT
+};
+
+TEST(ReturnTest, ConvertsArgumentWhenConverted) {
+  bool converted = false;
+  FromType x(&converted);
+  Action<ToType()> action(Return(x));
+  EXPECT_TRUE(converted) << "Return must convert its argument in its own "
+                         << "conversion operator.";
+  converted = false;
+  action.Perform(tuple<>());
+  EXPECT_FALSE(converted) << "Action must NOT convert its argument "
+                          << "when performed.";
+}
+
+class DestinationType {};
+
+class SourceType {
+ public:
+  // Note: a non-const typecast operator.
+  operator DestinationType() { return DestinationType(); }
+};
+
+TEST(ReturnTest, CanConvertArgumentUsingNonConstTypeCastOperator) {
+  SourceType s;
+  Action<DestinationType()> action(Return(s));
+}
+
+// Tests that ReturnNull() returns NULL in a pointer-returning function.
+TEST(ReturnNullTest, WorksInPointerReturningFunction) {
+  const Action<int*()> a1 = ReturnNull();
+  EXPECT_TRUE(a1.Perform(make_tuple()) == NULL);
+
+  const Action<const char*(bool)> a2 = ReturnNull();  // NOLINT
+  EXPECT_TRUE(a2.Perform(make_tuple(true)) == NULL);
+}
+
+#if GTEST_HAS_STD_UNIQUE_PTR_
+// Tests that ReturnNull() returns NULL for shared_ptr and unique_ptr returning
+// functions.
+TEST(ReturnNullTest, WorksInSmartPointerReturningFunction) {
+  const Action<std::unique_ptr<const int>()> a1 = ReturnNull();
+  EXPECT_TRUE(a1.Perform(make_tuple()) == nullptr);
+
+  const Action<std::shared_ptr<int>(std::string)> a2 = ReturnNull();
+  EXPECT_TRUE(a2.Perform(make_tuple("foo")) == nullptr);
+}
+#endif  // GTEST_HAS_STD_UNIQUE_PTR_
+
+// Tests that ReturnRef(v) works for reference types.
+TEST(ReturnRefTest, WorksForReference) {
+  const int n = 0;
+  const Action<const int&(bool)> ret = ReturnRef(n);  // NOLINT
+
+  EXPECT_EQ(&n, &ret.Perform(make_tuple(true)));
+}
+
+// Tests that ReturnRef(v) is covariant.
+TEST(ReturnRefTest, IsCovariant) {
+  Base base;
+  Derived derived;
+  Action<Base&()> a = ReturnRef(base);
+  EXPECT_EQ(&base, &a.Perform(make_tuple()));
+
+  a = ReturnRef(derived);
+  EXPECT_EQ(&derived, &a.Perform(make_tuple()));
+}
+
+// Tests that ReturnRefOfCopy(v) works for reference types.
+TEST(ReturnRefOfCopyTest, WorksForReference) {
+  int n = 42;
+  const Action<const int&()> ret = ReturnRefOfCopy(n);
+
+  EXPECT_NE(&n, &ret.Perform(make_tuple()));
+  EXPECT_EQ(42, ret.Perform(make_tuple()));
+
+  n = 43;
+  EXPECT_NE(&n, &ret.Perform(make_tuple()));
+  EXPECT_EQ(42, ret.Perform(make_tuple()));
+}
+
+// Tests that ReturnRefOfCopy(v) is covariant.
+TEST(ReturnRefOfCopyTest, IsCovariant) {
+  Base base;
+  Derived derived;
+  Action<Base&()> a = ReturnRefOfCopy(base);
+  EXPECT_NE(&base, &a.Perform(make_tuple()));
+
+  a = ReturnRefOfCopy(derived);
+  EXPECT_NE(&derived, &a.Perform(make_tuple()));
+}
+
+// Tests that DoDefault() does the default action for the mock method.
+
+class MockClass {
+ public:
+  MockClass() {}
+
+  MOCK_METHOD1(IntFunc, int(bool flag));  // NOLINT
+  MOCK_METHOD0(Foo, MyNonDefaultConstructible());
+#if GTEST_HAS_STD_UNIQUE_PTR_
+  MOCK_METHOD0(MakeUnique, std::unique_ptr<int>());
+  MOCK_METHOD0(MakeUniqueBase, std::unique_ptr<Base>());
+  MOCK_METHOD0(MakeVectorUnique, std::vector<std::unique_ptr<int>>());
+#endif
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockClass);
+};
+
+// Tests that DoDefault() returns the built-in default value for the
+// return type by default.
+TEST(DoDefaultTest, ReturnsBuiltInDefaultValueByDefault) {
+  MockClass mock;
+  EXPECT_CALL(mock, IntFunc(_))
+      .WillOnce(DoDefault());
+  EXPECT_EQ(0, mock.IntFunc(true));
+}
+
+// Tests that DoDefault() throws (when exceptions are enabled) or aborts
+// the process when there is no built-in default value for the return type.
+TEST(DoDefaultDeathTest, DiesForUnknowType) {
+  MockClass mock;
+  EXPECT_CALL(mock, Foo())
+      .WillRepeatedly(DoDefault());
+#if GTEST_HAS_EXCEPTIONS
+  EXPECT_ANY_THROW(mock.Foo());
+#else
+  EXPECT_DEATH_IF_SUPPORTED({
+    mock.Foo();
+  }, "");
+#endif
+}
+
+// Tests that using DoDefault() inside a composite action leads to a
+// run-time error.
+
+void VoidFunc(bool /* flag */) {}
+
+TEST(DoDefaultDeathTest, DiesIfUsedInCompositeAction) {
+  MockClass mock;
+  EXPECT_CALL(mock, IntFunc(_))
+      .WillRepeatedly(DoAll(Invoke(VoidFunc),
+                            DoDefault()));
+
+  // Ideally we should verify the error message as well.  Sadly,
+  // EXPECT_DEATH() can only capture stderr, while Google Mock's
+  // errors are printed on stdout.  Therefore we have to settle for
+  // not verifying the message.
+  EXPECT_DEATH_IF_SUPPORTED({
+    mock.IntFunc(true);
+  }, "");
+}
+
+// Tests that DoDefault() returns the default value set by
+// DefaultValue<T>::Set() when it's not overriden by an ON_CALL().
+TEST(DoDefaultTest, ReturnsUserSpecifiedPerTypeDefaultValueWhenThereIsOne) {
+  DefaultValue<int>::Set(1);
+  MockClass mock;
+  EXPECT_CALL(mock, IntFunc(_))
+      .WillOnce(DoDefault());
+  EXPECT_EQ(1, mock.IntFunc(false));
+  DefaultValue<int>::Clear();
+}
+
+// Tests that DoDefault() does the action specified by ON_CALL().
+TEST(DoDefaultTest, DoesWhatOnCallSpecifies) {
+  MockClass mock;
+  ON_CALL(mock, IntFunc(_))
+      .WillByDefault(Return(2));
+  EXPECT_CALL(mock, IntFunc(_))
+      .WillOnce(DoDefault());
+  EXPECT_EQ(2, mock.IntFunc(false));
+}
+
+// Tests that using DoDefault() in ON_CALL() leads to a run-time failure.
+TEST(DoDefaultTest, CannotBeUsedInOnCall) {
+  MockClass mock;
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    ON_CALL(mock, IntFunc(_))
+      .WillByDefault(DoDefault());
+  }, "DoDefault() cannot be used in ON_CALL()");
+}
+
+// Tests that SetArgPointee<N>(v) sets the variable pointed to by
+// the N-th (0-based) argument to v.
+TEST(SetArgPointeeTest, SetsTheNthPointee) {
+  typedef void MyFunction(bool, int*, char*);
+  Action<MyFunction> a = SetArgPointee<1>(2);
+
+  int n = 0;
+  char ch = '\0';
+  a.Perform(make_tuple(true, &n, &ch));
+  EXPECT_EQ(2, n);
+  EXPECT_EQ('\0', ch);
+
+  a = SetArgPointee<2>('a');
+  n = 0;
+  ch = '\0';
+  a.Perform(make_tuple(true, &n, &ch));
+  EXPECT_EQ(0, n);
+  EXPECT_EQ('a', ch);
+}
+
+#if !((GTEST_GCC_VER_ && GTEST_GCC_VER_ < 40000) || GTEST_OS_SYMBIAN)
+// Tests that SetArgPointee<N>() accepts a string literal.
+// GCC prior to v4.0 and the Symbian compiler do not support this.
+TEST(SetArgPointeeTest, AcceptsStringLiteral) {
+  typedef void MyFunction(std::string*, const char**);
+  Action<MyFunction> a = SetArgPointee<0>("hi");
+  std::string str;
+  const char* ptr = NULL;
+  a.Perform(make_tuple(&str, &ptr));
+  EXPECT_EQ("hi", str);
+  EXPECT_TRUE(ptr == NULL);
+
+  a = SetArgPointee<1>("world");
+  str = "";
+  a.Perform(make_tuple(&str, &ptr));
+  EXPECT_EQ("", str);
+  EXPECT_STREQ("world", ptr);
+}
+
+TEST(SetArgPointeeTest, AcceptsWideStringLiteral) {
+  typedef void MyFunction(const wchar_t**);
+  Action<MyFunction> a = SetArgPointee<0>(L"world");
+  const wchar_t* ptr = NULL;
+  a.Perform(make_tuple(&ptr));
+  EXPECT_STREQ(L"world", ptr);
+
+# if GTEST_HAS_STD_WSTRING
+
+  typedef void MyStringFunction(std::wstring*);
+  Action<MyStringFunction> a2 = SetArgPointee<0>(L"world");
+  std::wstring str = L"";
+  a2.Perform(make_tuple(&str));
+  EXPECT_EQ(L"world", str);
+
+# endif
+}
+#endif
+
+// Tests that SetArgPointee<N>() accepts a char pointer.
+TEST(SetArgPointeeTest, AcceptsCharPointer) {
+  typedef void MyFunction(bool, std::string*, const char**);
+  const char* const hi = "hi";
+  Action<MyFunction> a = SetArgPointee<1>(hi);
+  std::string str;
+  const char* ptr = NULL;
+  a.Perform(make_tuple(true, &str, &ptr));
+  EXPECT_EQ("hi", str);
+  EXPECT_TRUE(ptr == NULL);
+
+  char world_array[] = "world";
+  char* const world = world_array;
+  a = SetArgPointee<2>(world);
+  str = "";
+  a.Perform(make_tuple(true, &str, &ptr));
+  EXPECT_EQ("", str);
+  EXPECT_EQ(world, ptr);
+}
+
+TEST(SetArgPointeeTest, AcceptsWideCharPointer) {
+  typedef void MyFunction(bool, const wchar_t**);
+  const wchar_t* const hi = L"hi";
+  Action<MyFunction> a = SetArgPointee<1>(hi);
+  const wchar_t* ptr = NULL;
+  a.Perform(make_tuple(true, &ptr));
+  EXPECT_EQ(hi, ptr);
+
+# if GTEST_HAS_STD_WSTRING
+
+  typedef void MyStringFunction(bool, std::wstring*);
+  wchar_t world_array[] = L"world";
+  wchar_t* const world = world_array;
+  Action<MyStringFunction> a2 = SetArgPointee<1>(world);
+  std::wstring str;
+  a2.Perform(make_tuple(true, &str));
+  EXPECT_EQ(world_array, str);
+# endif
+}
+
+#if GTEST_HAS_PROTOBUF_
+
+// Tests that SetArgPointee<N>(proto_buffer) sets the v1 protobuf
+// variable pointed to by the N-th (0-based) argument to proto_buffer.
+TEST(SetArgPointeeTest, SetsTheNthPointeeOfProtoBufferType) {
+  TestMessage* const msg = new TestMessage;
+  msg->set_member("yes");
+  TestMessage orig_msg;
+  orig_msg.CopyFrom(*msg);
+
+  Action<void(bool, TestMessage*)> a = SetArgPointee<1>(*msg);
+  // SetArgPointee<N>(proto_buffer) makes a copy of proto_buffer
+  // s.t. the action works even when the original proto_buffer has
+  // died.  We ensure this behavior by deleting msg before using the
+  // action.
+  delete msg;
+
+  TestMessage dest;
+  EXPECT_FALSE(orig_msg.Equals(dest));
+  a.Perform(make_tuple(true, &dest));
+  EXPECT_TRUE(orig_msg.Equals(dest));
+}
+
+// Tests that SetArgPointee<N>(proto_buffer) sets the
+// ::ProtocolMessage variable pointed to by the N-th (0-based)
+// argument to proto_buffer.
+TEST(SetArgPointeeTest, SetsTheNthPointeeOfProtoBufferBaseType) {
+  TestMessage* const msg = new TestMessage;
+  msg->set_member("yes");
+  TestMessage orig_msg;
+  orig_msg.CopyFrom(*msg);
+
+  Action<void(bool, ::ProtocolMessage*)> a = SetArgPointee<1>(*msg);
+  // SetArgPointee<N>(proto_buffer) makes a copy of proto_buffer
+  // s.t. the action works even when the original proto_buffer has
+  // died.  We ensure this behavior by deleting msg before using the
+  // action.
+  delete msg;
+
+  TestMessage dest;
+  ::ProtocolMessage* const dest_base = &dest;
+  EXPECT_FALSE(orig_msg.Equals(dest));
+  a.Perform(make_tuple(true, dest_base));
+  EXPECT_TRUE(orig_msg.Equals(dest));
+}
+
+// Tests that SetArgPointee<N>(proto2_buffer) sets the v2
+// protobuf variable pointed to by the N-th (0-based) argument to
+// proto2_buffer.
+TEST(SetArgPointeeTest, SetsTheNthPointeeOfProto2BufferType) {
+  using testing::internal::FooMessage;
+  FooMessage* const msg = new FooMessage;
+  msg->set_int_field(2);
+  msg->set_string_field("hi");
+  FooMessage orig_msg;
+  orig_msg.CopyFrom(*msg);
+
+  Action<void(bool, FooMessage*)> a = SetArgPointee<1>(*msg);
+  // SetArgPointee<N>(proto2_buffer) makes a copy of
+  // proto2_buffer s.t. the action works even when the original
+  // proto2_buffer has died.  We ensure this behavior by deleting msg
+  // before using the action.
+  delete msg;
+
+  FooMessage dest;
+  dest.set_int_field(0);
+  a.Perform(make_tuple(true, &dest));
+  EXPECT_EQ(2, dest.int_field());
+  EXPECT_EQ("hi", dest.string_field());
+}
+
+// Tests that SetArgPointee<N>(proto2_buffer) sets the
+// proto2::Message variable pointed to by the N-th (0-based) argument
+// to proto2_buffer.
+TEST(SetArgPointeeTest, SetsTheNthPointeeOfProto2BufferBaseType) {
+  using testing::internal::FooMessage;
+  FooMessage* const msg = new FooMessage;
+  msg->set_int_field(2);
+  msg->set_string_field("hi");
+  FooMessage orig_msg;
+  orig_msg.CopyFrom(*msg);
+
+  Action<void(bool, ::proto2::Message*)> a = SetArgPointee<1>(*msg);
+  // SetArgPointee<N>(proto2_buffer) makes a copy of
+  // proto2_buffer s.t. the action works even when the original
+  // proto2_buffer has died.  We ensure this behavior by deleting msg
+  // before using the action.
+  delete msg;
+
+  FooMessage dest;
+  dest.set_int_field(0);
+  ::proto2::Message* const dest_base = &dest;
+  a.Perform(make_tuple(true, dest_base));
+  EXPECT_EQ(2, dest.int_field());
+  EXPECT_EQ("hi", dest.string_field());
+}
+
+#endif  // GTEST_HAS_PROTOBUF_
+
+// Tests that SetArgumentPointee<N>(v) sets the variable pointed to by
+// the N-th (0-based) argument to v.
+TEST(SetArgumentPointeeTest, SetsTheNthPointee) {
+  typedef void MyFunction(bool, int*, char*);
+  Action<MyFunction> a = SetArgumentPointee<1>(2);
+
+  int n = 0;
+  char ch = '\0';
+  a.Perform(make_tuple(true, &n, &ch));
+  EXPECT_EQ(2, n);
+  EXPECT_EQ('\0', ch);
+
+  a = SetArgumentPointee<2>('a');
+  n = 0;
+  ch = '\0';
+  a.Perform(make_tuple(true, &n, &ch));
+  EXPECT_EQ(0, n);
+  EXPECT_EQ('a', ch);
+}
+
+#if GTEST_HAS_PROTOBUF_
+
+// Tests that SetArgumentPointee<N>(proto_buffer) sets the v1 protobuf
+// variable pointed to by the N-th (0-based) argument to proto_buffer.
+TEST(SetArgumentPointeeTest, SetsTheNthPointeeOfProtoBufferType) {
+  TestMessage* const msg = new TestMessage;
+  msg->set_member("yes");
+  TestMessage orig_msg;
+  orig_msg.CopyFrom(*msg);
+
+  Action<void(bool, TestMessage*)> a = SetArgumentPointee<1>(*msg);
+  // SetArgumentPointee<N>(proto_buffer) makes a copy of proto_buffer
+  // s.t. the action works even when the original proto_buffer has
+  // died.  We ensure this behavior by deleting msg before using the
+  // action.
+  delete msg;
+
+  TestMessage dest;
+  EXPECT_FALSE(orig_msg.Equals(dest));
+  a.Perform(make_tuple(true, &dest));
+  EXPECT_TRUE(orig_msg.Equals(dest));
+}
+
+// Tests that SetArgumentPointee<N>(proto_buffer) sets the
+// ::ProtocolMessage variable pointed to by the N-th (0-based)
+// argument to proto_buffer.
+TEST(SetArgumentPointeeTest, SetsTheNthPointeeOfProtoBufferBaseType) {
+  TestMessage* const msg = new TestMessage;
+  msg->set_member("yes");
+  TestMessage orig_msg;
+  orig_msg.CopyFrom(*msg);
+
+  Action<void(bool, ::ProtocolMessage*)> a = SetArgumentPointee<1>(*msg);
+  // SetArgumentPointee<N>(proto_buffer) makes a copy of proto_buffer
+  // s.t. the action works even when the original proto_buffer has
+  // died.  We ensure this behavior by deleting msg before using the
+  // action.
+  delete msg;
+
+  TestMessage dest;
+  ::ProtocolMessage* const dest_base = &dest;
+  EXPECT_FALSE(orig_msg.Equals(dest));
+  a.Perform(make_tuple(true, dest_base));
+  EXPECT_TRUE(orig_msg.Equals(dest));
+}
+
+// Tests that SetArgumentPointee<N>(proto2_buffer) sets the v2
+// protobuf variable pointed to by the N-th (0-based) argument to
+// proto2_buffer.
+TEST(SetArgumentPointeeTest, SetsTheNthPointeeOfProto2BufferType) {
+  using testing::internal::FooMessage;
+  FooMessage* const msg = new FooMessage;
+  msg->set_int_field(2);
+  msg->set_string_field("hi");
+  FooMessage orig_msg;
+  orig_msg.CopyFrom(*msg);
+
+  Action<void(bool, FooMessage*)> a = SetArgumentPointee<1>(*msg);
+  // SetArgumentPointee<N>(proto2_buffer) makes a copy of
+  // proto2_buffer s.t. the action works even when the original
+  // proto2_buffer has died.  We ensure this behavior by deleting msg
+  // before using the action.
+  delete msg;
+
+  FooMessage dest;
+  dest.set_int_field(0);
+  a.Perform(make_tuple(true, &dest));
+  EXPECT_EQ(2, dest.int_field());
+  EXPECT_EQ("hi", dest.string_field());
+}
+
+// Tests that SetArgumentPointee<N>(proto2_buffer) sets the
+// proto2::Message variable pointed to by the N-th (0-based) argument
+// to proto2_buffer.
+TEST(SetArgumentPointeeTest, SetsTheNthPointeeOfProto2BufferBaseType) {
+  using testing::internal::FooMessage;
+  FooMessage* const msg = new FooMessage;
+  msg->set_int_field(2);
+  msg->set_string_field("hi");
+  FooMessage orig_msg;
+  orig_msg.CopyFrom(*msg);
+
+  Action<void(bool, ::proto2::Message*)> a = SetArgumentPointee<1>(*msg);
+  // SetArgumentPointee<N>(proto2_buffer) makes a copy of
+  // proto2_buffer s.t. the action works even when the original
+  // proto2_buffer has died.  We ensure this behavior by deleting msg
+  // before using the action.
+  delete msg;
+
+  FooMessage dest;
+  dest.set_int_field(0);
+  ::proto2::Message* const dest_base = &dest;
+  a.Perform(make_tuple(true, dest_base));
+  EXPECT_EQ(2, dest.int_field());
+  EXPECT_EQ("hi", dest.string_field());
+}
+
+#endif  // GTEST_HAS_PROTOBUF_
+
+// Sample functions and functors for testing Invoke() and etc.
+int Nullary() { return 1; }
+
+class NullaryFunctor {
+ public:
+  int operator()() { return 2; }
+};
+
+bool g_done = false;
+void VoidNullary() { g_done = true; }
+
+class VoidNullaryFunctor {
+ public:
+  void operator()() { g_done = true; }
+};
+
+class Foo {
+ public:
+  Foo() : value_(123) {}
+
+  int Nullary() const { return value_; }
+
+ private:
+  int value_;
+};
+
+// Tests InvokeWithoutArgs(function).
+TEST(InvokeWithoutArgsTest, Function) {
+  // As an action that takes one argument.
+  Action<int(int)> a = InvokeWithoutArgs(Nullary);  // NOLINT
+  EXPECT_EQ(1, a.Perform(make_tuple(2)));
+
+  // As an action that takes two arguments.
+  Action<int(int, double)> a2 = InvokeWithoutArgs(Nullary);  // NOLINT
+  EXPECT_EQ(1, a2.Perform(make_tuple(2, 3.5)));
+
+  // As an action that returns void.
+  Action<void(int)> a3 = InvokeWithoutArgs(VoidNullary);  // NOLINT
+  g_done = false;
+  a3.Perform(make_tuple(1));
+  EXPECT_TRUE(g_done);
+}
+
+// Tests InvokeWithoutArgs(functor).
+TEST(InvokeWithoutArgsTest, Functor) {
+  // As an action that takes no argument.
+  Action<int()> a = InvokeWithoutArgs(NullaryFunctor());  // NOLINT
+  EXPECT_EQ(2, a.Perform(make_tuple()));
+
+  // As an action that takes three arguments.
+  Action<int(int, double, char)> a2 =  // NOLINT
+      InvokeWithoutArgs(NullaryFunctor());
+  EXPECT_EQ(2, a2.Perform(make_tuple(3, 3.5, 'a')));
+
+  // As an action that returns void.
+  Action<void()> a3 = InvokeWithoutArgs(VoidNullaryFunctor());
+  g_done = false;
+  a3.Perform(make_tuple());
+  EXPECT_TRUE(g_done);
+}
+
+// Tests InvokeWithoutArgs(obj_ptr, method).
+TEST(InvokeWithoutArgsTest, Method) {
+  Foo foo;
+  Action<int(bool, char)> a =  // NOLINT
+      InvokeWithoutArgs(&foo, &Foo::Nullary);
+  EXPECT_EQ(123, a.Perform(make_tuple(true, 'a')));
+}
+
+// Tests using IgnoreResult() on a polymorphic action.
+TEST(IgnoreResultTest, PolymorphicAction) {
+  Action<void(int)> a = IgnoreResult(Return(5));  // NOLINT
+  a.Perform(make_tuple(1));
+}
+
+// Tests using IgnoreResult() on a monomorphic action.
+
+int ReturnOne() {
+  g_done = true;
+  return 1;
+}
+
+TEST(IgnoreResultTest, MonomorphicAction) {
+  g_done = false;
+  Action<void()> a = IgnoreResult(Invoke(ReturnOne));
+  a.Perform(make_tuple());
+  EXPECT_TRUE(g_done);
+}
+
+// Tests using IgnoreResult() on an action that returns a class type.
+
+MyNonDefaultConstructible ReturnMyNonDefaultConstructible(double /* x */) {
+  g_done = true;
+  return MyNonDefaultConstructible(42);
+}
+
+TEST(IgnoreResultTest, ActionReturningClass) {
+  g_done = false;
+  Action<void(int)> a =
+      IgnoreResult(Invoke(ReturnMyNonDefaultConstructible));  // NOLINT
+  a.Perform(make_tuple(2));
+  EXPECT_TRUE(g_done);
+}
+
+TEST(AssignTest, Int) {
+  int x = 0;
+  Action<void(int)> a = Assign(&x, 5);
+  a.Perform(make_tuple(0));
+  EXPECT_EQ(5, x);
+}
+
+TEST(AssignTest, String) {
+  ::std::string x;
+  Action<void(void)> a = Assign(&x, "Hello, world");
+  a.Perform(make_tuple());
+  EXPECT_EQ("Hello, world", x);
+}
+
+TEST(AssignTest, CompatibleTypes) {
+  double x = 0;
+  Action<void(int)> a = Assign(&x, 5);
+  a.Perform(make_tuple(0));
+  EXPECT_DOUBLE_EQ(5, x);
+}
+
+#if !GTEST_OS_WINDOWS_MOBILE
+
+class SetErrnoAndReturnTest : public testing::Test {
+ protected:
+  virtual void SetUp() { errno = 0; }
+  virtual void TearDown() { errno = 0; }
+};
+
+TEST_F(SetErrnoAndReturnTest, Int) {
+  Action<int(void)> a = SetErrnoAndReturn(ENOTTY, -5);
+  EXPECT_EQ(-5, a.Perform(make_tuple()));
+  EXPECT_EQ(ENOTTY, errno);
+}
+
+TEST_F(SetErrnoAndReturnTest, Ptr) {
+  int x;
+  Action<int*(void)> a = SetErrnoAndReturn(ENOTTY, &x);
+  EXPECT_EQ(&x, a.Perform(make_tuple()));
+  EXPECT_EQ(ENOTTY, errno);
+}
+
+TEST_F(SetErrnoAndReturnTest, CompatibleTypes) {
+  Action<double()> a = SetErrnoAndReturn(EINVAL, 5);
+  EXPECT_DOUBLE_EQ(5.0, a.Perform(make_tuple()));
+  EXPECT_EQ(EINVAL, errno);
+}
+
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+// Tests ByRef().
+
+// Tests that ReferenceWrapper<T> is copyable.
+TEST(ByRefTest, IsCopyable) {
+  const std::string s1 = "Hi";
+  const std::string s2 = "Hello";
+
+  ::testing::internal::ReferenceWrapper<const std::string> ref_wrapper =
+      ByRef(s1);
+  const std::string& r1 = ref_wrapper;
+  EXPECT_EQ(&s1, &r1);
+
+  // Assigns a new value to ref_wrapper.
+  ref_wrapper = ByRef(s2);
+  const std::string& r2 = ref_wrapper;
+  EXPECT_EQ(&s2, &r2);
+
+  ::testing::internal::ReferenceWrapper<const std::string> ref_wrapper1 =
+      ByRef(s1);
+  // Copies ref_wrapper1 to ref_wrapper.
+  ref_wrapper = ref_wrapper1;
+  const std::string& r3 = ref_wrapper;
+  EXPECT_EQ(&s1, &r3);
+}
+
+// Tests using ByRef() on a const value.
+TEST(ByRefTest, ConstValue) {
+  const int n = 0;
+  // int& ref = ByRef(n);  // This shouldn't compile - we have a
+                           // negative compilation test to catch it.
+  const int& const_ref = ByRef(n);
+  EXPECT_EQ(&n, &const_ref);
+}
+
+// Tests using ByRef() on a non-const value.
+TEST(ByRefTest, NonConstValue) {
+  int n = 0;
+
+  // ByRef(n) can be used as either an int&,
+  int& ref = ByRef(n);
+  EXPECT_EQ(&n, &ref);
+
+  // or a const int&.
+  const int& const_ref = ByRef(n);
+  EXPECT_EQ(&n, &const_ref);
+}
+
+// Tests explicitly specifying the type when using ByRef().
+TEST(ByRefTest, ExplicitType) {
+  int n = 0;
+  const int& r1 = ByRef<const int>(n);
+  EXPECT_EQ(&n, &r1);
+
+  // ByRef<char>(n);  // This shouldn't compile - we have a negative
+                      // compilation test to catch it.
+
+  Derived d;
+  Derived& r2 = ByRef<Derived>(d);
+  EXPECT_EQ(&d, &r2);
+
+  const Derived& r3 = ByRef<const Derived>(d);
+  EXPECT_EQ(&d, &r3);
+
+  Base& r4 = ByRef<Base>(d);
+  EXPECT_EQ(&d, &r4);
+
+  const Base& r5 = ByRef<const Base>(d);
+  EXPECT_EQ(&d, &r5);
+
+  // The following shouldn't compile - we have a negative compilation
+  // test for it.
+  //
+  // Base b;
+  // ByRef<Derived>(b);
+}
+
+// Tests that Google Mock prints expression ByRef(x) as a reference to x.
+TEST(ByRefTest, PrintsCorrectly) {
+  int n = 42;
+  ::std::stringstream expected, actual;
+  testing::internal::UniversalPrinter<const int&>::Print(n, &expected);
+  testing::internal::UniversalPrint(ByRef(n), &actual);
+  EXPECT_EQ(expected.str(), actual.str());
+}
+
+#if GTEST_HAS_STD_UNIQUE_PTR_
+
+std::unique_ptr<int> UniquePtrSource() {
+  return std::unique_ptr<int>(new int(19));
+}
+
+std::vector<std::unique_ptr<int>> VectorUniquePtrSource() {
+  std::vector<std::unique_ptr<int>> out;
+  out.emplace_back(new int(7));
+  return out;
+}
+
+TEST(MockMethodTest, CanReturnMoveOnlyValue_Return) {
+  MockClass mock;
+  std::unique_ptr<int> i(new int(19));
+  EXPECT_CALL(mock, MakeUnique()).WillOnce(Return(ByMove(std::move(i))));
+  EXPECT_CALL(mock, MakeVectorUnique())
+      .WillOnce(Return(ByMove(VectorUniquePtrSource())));
+  Derived* d = new Derived;
+  EXPECT_CALL(mock, MakeUniqueBase())
+      .WillOnce(Return(ByMove(std::unique_ptr<Derived>(d))));
+
+  std::unique_ptr<int> result1 = mock.MakeUnique();
+  EXPECT_EQ(19, *result1);
+
+  std::vector<std::unique_ptr<int>> vresult = mock.MakeVectorUnique();
+  EXPECT_EQ(1u, vresult.size());
+  EXPECT_NE(nullptr, vresult[0]);
+  EXPECT_EQ(7, *vresult[0]);
+
+  std::unique_ptr<Base> result2 = mock.MakeUniqueBase();
+  EXPECT_EQ(d, result2.get());
+}
+
+TEST(MockMethodTest, CanReturnMoveOnlyValue_DoAllReturn) {
+  testing::MockFunction<void()> mock_function;
+  MockClass mock;
+  std::unique_ptr<int> i(new int(19));
+  EXPECT_CALL(mock_function, Call());
+  EXPECT_CALL(mock, MakeUnique()).WillOnce(DoAll(
+      InvokeWithoutArgs(&mock_function, &testing::MockFunction<void()>::Call),
+      Return(ByMove(std::move(i)))));
+
+  std::unique_ptr<int> result1 = mock.MakeUnique();
+  EXPECT_EQ(19, *result1);
+}
+
+TEST(MockMethodTest, CanReturnMoveOnlyValue_Invoke) {
+  MockClass mock;
+
+  // Check default value
+  DefaultValue<std::unique_ptr<int>>::SetFactory([] {
+    return std::unique_ptr<int>(new int(42));
+  });
+  EXPECT_EQ(42, *mock.MakeUnique());
+
+  EXPECT_CALL(mock, MakeUnique()).WillRepeatedly(Invoke(UniquePtrSource));
+  EXPECT_CALL(mock, MakeVectorUnique())
+      .WillRepeatedly(Invoke(VectorUniquePtrSource));
+  std::unique_ptr<int> result1 = mock.MakeUnique();
+  EXPECT_EQ(19, *result1);
+  std::unique_ptr<int> result2 = mock.MakeUnique();
+  EXPECT_EQ(19, *result2);
+  EXPECT_NE(result1, result2);
+
+  std::vector<std::unique_ptr<int>> vresult = mock.MakeVectorUnique();
+  EXPECT_EQ(1u, vresult.size());
+  EXPECT_NE(nullptr, vresult[0]);
+  EXPECT_EQ(7, *vresult[0]);
+}
+
+#endif  // GTEST_HAS_STD_UNIQUE_PTR_
+
+}  // Unnamed namespace
diff --git a/third_party/googletest/googlemock/test/gmock-cardinalities_test.cc b/third_party/googletest/googlemock/test/gmock-cardinalities_test.cc
new file mode 100644
index 0000000..64815e5
--- /dev/null
+++ b/third_party/googletest/googlemock/test/gmock-cardinalities_test.cc
@@ -0,0 +1,428 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests the built-in cardinalities.
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "gtest/gtest-spi.h"
+
+namespace {
+
+using std::stringstream;
+using testing::AnyNumber;
+using testing::AtLeast;
+using testing::AtMost;
+using testing::Between;
+using testing::Cardinality;
+using testing::CardinalityInterface;
+using testing::Exactly;
+using testing::IsSubstring;
+using testing::MakeCardinality;
+
+class MockFoo {
+ public:
+  MockFoo() {}
+  MOCK_METHOD0(Bar, int());  // NOLINT
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFoo);
+};
+
+// Tests that Cardinality objects can be default constructed.
+TEST(CardinalityTest, IsDefaultConstructable) {
+  Cardinality c;
+}
+
+// Tests that Cardinality objects are copyable.
+TEST(CardinalityTest, IsCopyable) {
+  // Tests the copy constructor.
+  Cardinality c = Exactly(1);
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(0));
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(1));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(1));
+
+  // Tests the assignment operator.
+  c = Exactly(2);
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(1));
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(2));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(2));
+}
+
+TEST(CardinalityTest, IsOverSaturatedByCallCountWorks) {
+  const Cardinality c = AtMost(5);
+  EXPECT_FALSE(c.IsOverSaturatedByCallCount(4));
+  EXPECT_FALSE(c.IsOverSaturatedByCallCount(5));
+  EXPECT_TRUE(c.IsOverSaturatedByCallCount(6));
+}
+
+// Tests that Cardinality::DescribeActualCallCountTo() creates the
+// correct description.
+TEST(CardinalityTest, CanDescribeActualCallCount) {
+  stringstream ss0;
+  Cardinality::DescribeActualCallCountTo(0, &ss0);
+  EXPECT_EQ("never called", ss0.str());
+
+  stringstream ss1;
+  Cardinality::DescribeActualCallCountTo(1, &ss1);
+  EXPECT_EQ("called once", ss1.str());
+
+  stringstream ss2;
+  Cardinality::DescribeActualCallCountTo(2, &ss2);
+  EXPECT_EQ("called twice", ss2.str());
+
+  stringstream ss3;
+  Cardinality::DescribeActualCallCountTo(3, &ss3);
+  EXPECT_EQ("called 3 times", ss3.str());
+}
+
+// Tests AnyNumber()
+TEST(AnyNumber, Works) {
+  const Cardinality c = AnyNumber();
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(0));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(0));
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(1));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(1));
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(9));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(9));
+
+  stringstream ss;
+  c.DescribeTo(&ss);
+  EXPECT_PRED_FORMAT2(IsSubstring, "called any number of times",
+                      ss.str());
+}
+
+TEST(AnyNumberTest, HasCorrectBounds) {
+  const Cardinality c = AnyNumber();
+  EXPECT_EQ(0, c.ConservativeLowerBound());
+  EXPECT_EQ(INT_MAX, c.ConservativeUpperBound());
+}
+
+// Tests AtLeast(n).
+
+TEST(AtLeastTest, OnNegativeNumber) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    AtLeast(-1);
+  }, "The invocation lower bound must be >= 0");
+}
+
+TEST(AtLeastTest, OnZero) {
+  const Cardinality c = AtLeast(0);
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(0));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(0));
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(1));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(1));
+
+  stringstream ss;
+  c.DescribeTo(&ss);
+  EXPECT_PRED_FORMAT2(IsSubstring, "any number of times",
+                      ss.str());
+}
+
+TEST(AtLeastTest, OnPositiveNumber) {
+  const Cardinality c = AtLeast(2);
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(0));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(0));
+
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(1));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(1));
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(2));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(2));
+
+  stringstream ss1;
+  AtLeast(1).DescribeTo(&ss1);
+  EXPECT_PRED_FORMAT2(IsSubstring, "at least once",
+                      ss1.str());
+
+  stringstream ss2;
+  c.DescribeTo(&ss2);
+  EXPECT_PRED_FORMAT2(IsSubstring, "at least twice",
+                      ss2.str());
+
+  stringstream ss3;
+  AtLeast(3).DescribeTo(&ss3);
+  EXPECT_PRED_FORMAT2(IsSubstring, "at least 3 times",
+                      ss3.str());
+}
+
+TEST(AtLeastTest, HasCorrectBounds) {
+  const Cardinality c = AtLeast(2);
+  EXPECT_EQ(2, c.ConservativeLowerBound());
+  EXPECT_EQ(INT_MAX, c.ConservativeUpperBound());
+}
+
+// Tests AtMost(n).
+
+TEST(AtMostTest, OnNegativeNumber) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    AtMost(-1);
+  }, "The invocation upper bound must be >= 0");
+}
+
+TEST(AtMostTest, OnZero) {
+  const Cardinality c = AtMost(0);
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(0));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(0));
+
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(1));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(1));
+
+  stringstream ss;
+  c.DescribeTo(&ss);
+  EXPECT_PRED_FORMAT2(IsSubstring, "never called",
+                      ss.str());
+}
+
+TEST(AtMostTest, OnPositiveNumber) {
+  const Cardinality c = AtMost(2);
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(0));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(0));
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(1));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(1));
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(2));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(2));
+
+  stringstream ss1;
+  AtMost(1).DescribeTo(&ss1);
+  EXPECT_PRED_FORMAT2(IsSubstring, "called at most once",
+                      ss1.str());
+
+  stringstream ss2;
+  c.DescribeTo(&ss2);
+  EXPECT_PRED_FORMAT2(IsSubstring, "called at most twice",
+                      ss2.str());
+
+  stringstream ss3;
+  AtMost(3).DescribeTo(&ss3);
+  EXPECT_PRED_FORMAT2(IsSubstring, "called at most 3 times",
+                      ss3.str());
+}
+
+TEST(AtMostTest, HasCorrectBounds) {
+  const Cardinality c = AtMost(2);
+  EXPECT_EQ(0, c.ConservativeLowerBound());
+  EXPECT_EQ(2, c.ConservativeUpperBound());
+}
+
+// Tests Between(m, n).
+
+TEST(BetweenTest, OnNegativeStart) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    Between(-1, 2);
+  }, "The invocation lower bound must be >= 0, but is actually -1");
+}
+
+TEST(BetweenTest, OnNegativeEnd) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    Between(1, -2);
+  }, "The invocation upper bound must be >= 0, but is actually -2");
+}
+
+TEST(BetweenTest, OnStartBiggerThanEnd) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    Between(2, 1);
+  }, "The invocation upper bound (1) must be >= "
+     "the invocation lower bound (2)");
+}
+
+TEST(BetweenTest, OnZeroStartAndZeroEnd) {
+  const Cardinality c = Between(0, 0);
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(0));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(0));
+
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(1));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(1));
+
+  stringstream ss;
+  c.DescribeTo(&ss);
+  EXPECT_PRED_FORMAT2(IsSubstring, "never called",
+                      ss.str());
+}
+
+TEST(BetweenTest, OnZeroStartAndNonZeroEnd) {
+  const Cardinality c = Between(0, 2);
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(0));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(0));
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(2));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(2));
+
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(4));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(4));
+
+  stringstream ss;
+  c.DescribeTo(&ss);
+  EXPECT_PRED_FORMAT2(IsSubstring, "called at most twice",
+                      ss.str());
+}
+
+TEST(BetweenTest, OnSameStartAndEnd) {
+  const Cardinality c = Between(3, 3);
+
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(2));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(2));
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(3));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(3));
+
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(4));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(4));
+
+  stringstream ss;
+  c.DescribeTo(&ss);
+  EXPECT_PRED_FORMAT2(IsSubstring, "called 3 times",
+                      ss.str());
+}
+
+TEST(BetweenTest, OnDifferentStartAndEnd) {
+  const Cardinality c = Between(3, 5);
+
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(2));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(2));
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(3));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(3));
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(5));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(5));
+
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(6));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(6));
+
+  stringstream ss;
+  c.DescribeTo(&ss);
+  EXPECT_PRED_FORMAT2(IsSubstring, "called between 3 and 5 times",
+                      ss.str());
+}
+
+TEST(BetweenTest, HasCorrectBounds) {
+  const Cardinality c = Between(3, 5);
+  EXPECT_EQ(3, c.ConservativeLowerBound());
+  EXPECT_EQ(5, c.ConservativeUpperBound());
+}
+
+// Tests Exactly(n).
+
+TEST(ExactlyTest, OnNegativeNumber) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    Exactly(-1);
+  }, "The invocation lower bound must be >= 0");
+}
+
+TEST(ExactlyTest, OnZero) {
+  const Cardinality c = Exactly(0);
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(0));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(0));
+
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(1));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(1));
+
+  stringstream ss;
+  c.DescribeTo(&ss);
+  EXPECT_PRED_FORMAT2(IsSubstring, "never called",
+                      ss.str());
+}
+
+TEST(ExactlyTest, OnPositiveNumber) {
+  const Cardinality c = Exactly(2);
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(0));
+  EXPECT_FALSE(c.IsSaturatedByCallCount(0));
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(2));
+  EXPECT_TRUE(c.IsSaturatedByCallCount(2));
+
+  stringstream ss1;
+  Exactly(1).DescribeTo(&ss1);
+  EXPECT_PRED_FORMAT2(IsSubstring, "called once",
+                      ss1.str());
+
+  stringstream ss2;
+  c.DescribeTo(&ss2);
+  EXPECT_PRED_FORMAT2(IsSubstring, "called twice",
+                      ss2.str());
+
+  stringstream ss3;
+  Exactly(3).DescribeTo(&ss3);
+  EXPECT_PRED_FORMAT2(IsSubstring, "called 3 times",
+                      ss3.str());
+}
+
+TEST(ExactlyTest, HasCorrectBounds) {
+  const Cardinality c = Exactly(3);
+  EXPECT_EQ(3, c.ConservativeLowerBound());
+  EXPECT_EQ(3, c.ConservativeUpperBound());
+}
+
+// Tests that a user can make his own cardinality by implementing
+// CardinalityInterface and calling MakeCardinality().
+
+class EvenCardinality : public CardinalityInterface {
+ public:
+  // Returns true iff call_count calls will satisfy this cardinality.
+  virtual bool IsSatisfiedByCallCount(int call_count) const {
+    return (call_count % 2 == 0);
+  }
+
+  // Returns true iff call_count calls will saturate this cardinality.
+  virtual bool IsSaturatedByCallCount(int /* call_count */) const {
+    return false;
+  }
+
+  // Describes self to an ostream.
+  virtual void DescribeTo(::std::ostream* ss) const {
+    *ss << "called even number of times";
+  }
+};
+
+TEST(MakeCardinalityTest, ConstructsCardinalityFromInterface) {
+  const Cardinality c = MakeCardinality(new EvenCardinality);
+
+  EXPECT_TRUE(c.IsSatisfiedByCallCount(2));
+  EXPECT_FALSE(c.IsSatisfiedByCallCount(3));
+
+  EXPECT_FALSE(c.IsSaturatedByCallCount(10000));
+
+  stringstream ss;
+  c.DescribeTo(&ss);
+  EXPECT_EQ("called even number of times", ss.str());
+}
+
+}  // Unnamed namespace
diff --git a/third_party/googletest/googlemock/test/gmock-generated-actions_test.cc b/third_party/googletest/googlemock/test/gmock-generated-actions_test.cc
new file mode 100644
index 0000000..c2d2a0a
--- /dev/null
+++ b/third_party/googletest/googlemock/test/gmock-generated-actions_test.cc
@@ -0,0 +1,1227 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests the built-in actions generated by a script.
+
+#include "gmock/gmock-generated-actions.h"
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+namespace gmock_generated_actions_test {
+
+using ::std::plus;
+using ::std::string;
+using testing::get;
+using testing::make_tuple;
+using testing::tuple;
+using testing::tuple_element;
+using testing::_;
+using testing::Action;
+using testing::ActionInterface;
+using testing::ByRef;
+using testing::DoAll;
+using testing::Invoke;
+using testing::Return;
+using testing::ReturnNew;
+using testing::SetArgPointee;
+using testing::StaticAssertTypeEq;
+using testing::Unused;
+using testing::WithArgs;
+
+// For suppressing compiler warnings on conversion possibly losing precision.
+inline short Short(short n) { return n; }  // NOLINT
+inline char Char(char ch) { return ch; }
+
+// Sample functions and functors for testing various actions.
+int Nullary() { return 1; }
+
+class NullaryFunctor {
+ public:
+  int operator()() { return 2; }
+};
+
+bool g_done = false;
+
+bool Unary(int x) { return x < 0; }
+
+const char* Plus1(const char* s) { return s + 1; }
+
+bool ByConstRef(const string& s) { return s == "Hi"; }
+
+const double g_double = 0;
+bool ReferencesGlobalDouble(const double& x) { return &x == &g_double; }
+
+string ByNonConstRef(string& s) { return s += "+"; }  // NOLINT
+
+struct UnaryFunctor {
+  int operator()(bool x) { return x ? 1 : -1; }
+};
+
+const char* Binary(const char* input, short n) { return input + n; }  // NOLINT
+
+void VoidBinary(int, char) { g_done = true; }
+
+int Ternary(int x, char y, short z) { return x + y + z; }  // NOLINT
+
+void VoidTernary(int, char, bool) { g_done = true; }
+
+int SumOf4(int a, int b, int c, int d) { return a + b + c + d; }
+
+string Concat4(const char* s1, const char* s2, const char* s3,
+               const char* s4) {
+  return string(s1) + s2 + s3 + s4;
+}
+
+int SumOf5(int a, int b, int c, int d, int e) { return a + b + c + d + e; }
+
+struct SumOf5Functor {
+  int operator()(int a, int b, int c, int d, int e) {
+    return a + b + c + d + e;
+  }
+};
+
+string Concat5(const char* s1, const char* s2, const char* s3,
+               const char* s4, const char* s5) {
+  return string(s1) + s2 + s3 + s4 + s5;
+}
+
+int SumOf6(int a, int b, int c, int d, int e, int f) {
+  return a + b + c + d + e + f;
+}
+
+struct SumOf6Functor {
+  int operator()(int a, int b, int c, int d, int e, int f) {
+    return a + b + c + d + e + f;
+  }
+};
+
+string Concat6(const char* s1, const char* s2, const char* s3,
+               const char* s4, const char* s5, const char* s6) {
+  return string(s1) + s2 + s3 + s4 + s5 + s6;
+}
+
+string Concat7(const char* s1, const char* s2, const char* s3,
+               const char* s4, const char* s5, const char* s6,
+               const char* s7) {
+  return string(s1) + s2 + s3 + s4 + s5 + s6 + s7;
+}
+
+string Concat8(const char* s1, const char* s2, const char* s3,
+               const char* s4, const char* s5, const char* s6,
+               const char* s7, const char* s8) {
+  return string(s1) + s2 + s3 + s4 + s5 + s6 + s7 + s8;
+}
+
+string Concat9(const char* s1, const char* s2, const char* s3,
+               const char* s4, const char* s5, const char* s6,
+               const char* s7, const char* s8, const char* s9) {
+  return string(s1) + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9;
+}
+
+string Concat10(const char* s1, const char* s2, const char* s3,
+                const char* s4, const char* s5, const char* s6,
+                const char* s7, const char* s8, const char* s9,
+                const char* s10) {
+  return string(s1) + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10;
+}
+
+// A helper that turns the type of a C-string literal from const
+// char[N] to const char*.
+inline const char* CharPtr(const char* s) { return s; }
+
+// Tests InvokeArgument<N>(...).
+
+// Tests using InvokeArgument with a nullary function.
+TEST(InvokeArgumentTest, Function0) {
+  Action<int(int, int(*)())> a = InvokeArgument<1>();  // NOLINT
+  EXPECT_EQ(1, a.Perform(make_tuple(2, &Nullary)));
+}
+
+// Tests using InvokeArgument with a unary function.
+TEST(InvokeArgumentTest, Functor1) {
+  Action<int(UnaryFunctor)> a = InvokeArgument<0>(true);  // NOLINT
+  EXPECT_EQ(1, a.Perform(make_tuple(UnaryFunctor())));
+}
+
+// Tests using InvokeArgument with a 5-ary function.
+TEST(InvokeArgumentTest, Function5) {
+  Action<int(int(*)(int, int, int, int, int))> a =  // NOLINT
+      InvokeArgument<0>(10000, 2000, 300, 40, 5);
+  EXPECT_EQ(12345, a.Perform(make_tuple(&SumOf5)));
+}
+
+// Tests using InvokeArgument with a 5-ary functor.
+TEST(InvokeArgumentTest, Functor5) {
+  Action<int(SumOf5Functor)> a =  // NOLINT
+      InvokeArgument<0>(10000, 2000, 300, 40, 5);
+  EXPECT_EQ(12345, a.Perform(make_tuple(SumOf5Functor())));
+}
+
+// Tests using InvokeArgument with a 6-ary function.
+TEST(InvokeArgumentTest, Function6) {
+  Action<int(int(*)(int, int, int, int, int, int))> a =  // NOLINT
+      InvokeArgument<0>(100000, 20000, 3000, 400, 50, 6);
+  EXPECT_EQ(123456, a.Perform(make_tuple(&SumOf6)));
+}
+
+// Tests using InvokeArgument with a 6-ary functor.
+TEST(InvokeArgumentTest, Functor6) {
+  Action<int(SumOf6Functor)> a =  // NOLINT
+      InvokeArgument<0>(100000, 20000, 3000, 400, 50, 6);
+  EXPECT_EQ(123456, a.Perform(make_tuple(SumOf6Functor())));
+}
+
+// Tests using InvokeArgument with a 7-ary function.
+TEST(InvokeArgumentTest, Function7) {
+  Action<string(string(*)(const char*, const char*, const char*,
+                          const char*, const char*, const char*,
+                          const char*))> a =
+      InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7");
+  EXPECT_EQ("1234567", a.Perform(make_tuple(&Concat7)));
+}
+
+// Tests using InvokeArgument with a 8-ary function.
+TEST(InvokeArgumentTest, Function8) {
+  Action<string(string(*)(const char*, const char*, const char*,
+                          const char*, const char*, const char*,
+                          const char*, const char*))> a =
+      InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7", "8");
+  EXPECT_EQ("12345678", a.Perform(make_tuple(&Concat8)));
+}
+
+// Tests using InvokeArgument with a 9-ary function.
+TEST(InvokeArgumentTest, Function9) {
+  Action<string(string(*)(const char*, const char*, const char*,
+                          const char*, const char*, const char*,
+                          const char*, const char*, const char*))> a =
+      InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7", "8", "9");
+  EXPECT_EQ("123456789", a.Perform(make_tuple(&Concat9)));
+}
+
+// Tests using InvokeArgument with a 10-ary function.
+TEST(InvokeArgumentTest, Function10) {
+  Action<string(string(*)(const char*, const char*, const char*,
+                          const char*, const char*, const char*,
+                          const char*, const char*, const char*,
+                          const char*))> a =
+      InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7", "8", "9", "0");
+  EXPECT_EQ("1234567890", a.Perform(make_tuple(&Concat10)));
+}
+
+// Tests using InvokeArgument with a function that takes a pointer argument.
+TEST(InvokeArgumentTest, ByPointerFunction) {
+  Action<const char*(const char*(*)(const char* input, short n))> a =  // NOLINT
+      InvokeArgument<0>(static_cast<const char*>("Hi"), Short(1));
+  EXPECT_STREQ("i", a.Perform(make_tuple(&Binary)));
+}
+
+// Tests using InvokeArgument with a function that takes a const char*
+// by passing it a C-string literal.
+TEST(InvokeArgumentTest, FunctionWithCStringLiteral) {
+  Action<const char*(const char*(*)(const char* input, short n))> a =  // NOLINT
+      InvokeArgument<0>("Hi", Short(1));
+  EXPECT_STREQ("i", a.Perform(make_tuple(&Binary)));
+}
+
+// Tests using InvokeArgument with a function that takes a const reference.
+TEST(InvokeArgumentTest, ByConstReferenceFunction) {
+  Action<bool(bool(*function)(const string& s))> a =  // NOLINT
+      InvokeArgument<0>(string("Hi"));
+  // When action 'a' is constructed, it makes a copy of the temporary
+  // string object passed to it, so it's OK to use 'a' later, when the
+  // temporary object has already died.
+  EXPECT_TRUE(a.Perform(make_tuple(&ByConstRef)));
+}
+
+// Tests using InvokeArgument with ByRef() and a function that takes a
+// const reference.
+TEST(InvokeArgumentTest, ByExplicitConstReferenceFunction) {
+  Action<bool(bool(*)(const double& x))> a =  // NOLINT
+      InvokeArgument<0>(ByRef(g_double));
+  // The above line calls ByRef() on a const value.
+  EXPECT_TRUE(a.Perform(make_tuple(&ReferencesGlobalDouble)));
+
+  double x = 0;
+  a = InvokeArgument<0>(ByRef(x));  // This calls ByRef() on a non-const.
+  EXPECT_FALSE(a.Perform(make_tuple(&ReferencesGlobalDouble)));
+}
+
+// Tests using WithArgs and with an action that takes 1 argument.
+TEST(WithArgsTest, OneArg) {
+  Action<bool(double x, int n)> a = WithArgs<1>(Invoke(Unary));  // NOLINT
+  EXPECT_TRUE(a.Perform(make_tuple(1.5, -1)));
+  EXPECT_FALSE(a.Perform(make_tuple(1.5, 1)));
+}
+
+// Tests using WithArgs with an action that takes 2 arguments.
+TEST(WithArgsTest, TwoArgs) {
+  Action<const char*(const char* s, double x, short n)> a =
+      WithArgs<0, 2>(Invoke(Binary));
+  const char s[] = "Hello";
+  EXPECT_EQ(s + 2, a.Perform(make_tuple(CharPtr(s), 0.5, Short(2))));
+}
+
+// Tests using WithArgs with an action that takes 3 arguments.
+TEST(WithArgsTest, ThreeArgs) {
+  Action<int(int, double, char, short)> a =  // NOLINT
+      WithArgs<0, 2, 3>(Invoke(Ternary));
+  EXPECT_EQ(123, a.Perform(make_tuple(100, 6.5, Char(20), Short(3))));
+}
+
+// Tests using WithArgs with an action that takes 4 arguments.
+TEST(WithArgsTest, FourArgs) {
+  Action<string(const char*, const char*, double, const char*, const char*)> a =
+      WithArgs<4, 3, 1, 0>(Invoke(Concat4));
+  EXPECT_EQ("4310", a.Perform(make_tuple(CharPtr("0"), CharPtr("1"), 2.5,
+                                         CharPtr("3"), CharPtr("4"))));
+}
+
+// Tests using WithArgs with an action that takes 5 arguments.
+TEST(WithArgsTest, FiveArgs) {
+  Action<string(const char*, const char*, const char*,
+                const char*, const char*)> a =
+      WithArgs<4, 3, 2, 1, 0>(Invoke(Concat5));
+  EXPECT_EQ("43210",
+            a.Perform(make_tuple(CharPtr("0"), CharPtr("1"), CharPtr("2"),
+                                 CharPtr("3"), CharPtr("4"))));
+}
+
+// Tests using WithArgs with an action that takes 6 arguments.
+TEST(WithArgsTest, SixArgs) {
+  Action<string(const char*, const char*, const char*)> a =
+      WithArgs<0, 1, 2, 2, 1, 0>(Invoke(Concat6));
+  EXPECT_EQ("012210",
+            a.Perform(make_tuple(CharPtr("0"), CharPtr("1"), CharPtr("2"))));
+}
+
+// Tests using WithArgs with an action that takes 7 arguments.
+TEST(WithArgsTest, SevenArgs) {
+  Action<string(const char*, const char*, const char*, const char*)> a =
+      WithArgs<0, 1, 2, 3, 2, 1, 0>(Invoke(Concat7));
+  EXPECT_EQ("0123210",
+            a.Perform(make_tuple(CharPtr("0"), CharPtr("1"), CharPtr("2"),
+                                 CharPtr("3"))));
+}
+
+// Tests using WithArgs with an action that takes 8 arguments.
+TEST(WithArgsTest, EightArgs) {
+  Action<string(const char*, const char*, const char*, const char*)> a =
+      WithArgs<0, 1, 2, 3, 0, 1, 2, 3>(Invoke(Concat8));
+  EXPECT_EQ("01230123",
+            a.Perform(make_tuple(CharPtr("0"), CharPtr("1"), CharPtr("2"),
+                                 CharPtr("3"))));
+}
+
+// Tests using WithArgs with an action that takes 9 arguments.
+TEST(WithArgsTest, NineArgs) {
+  Action<string(const char*, const char*, const char*, const char*)> a =
+      WithArgs<0, 1, 2, 3, 1, 2, 3, 2, 3>(Invoke(Concat9));
+  EXPECT_EQ("012312323",
+            a.Perform(make_tuple(CharPtr("0"), CharPtr("1"), CharPtr("2"),
+                                 CharPtr("3"))));
+}
+
+// Tests using WithArgs with an action that takes 10 arguments.
+TEST(WithArgsTest, TenArgs) {
+  Action<string(const char*, const char*, const char*, const char*)> a =
+      WithArgs<0, 1, 2, 3, 2, 1, 0, 1, 2, 3>(Invoke(Concat10));
+  EXPECT_EQ("0123210123",
+            a.Perform(make_tuple(CharPtr("0"), CharPtr("1"), CharPtr("2"),
+                                 CharPtr("3"))));
+}
+
+// Tests using WithArgs with an action that is not Invoke().
+class SubstractAction : public ActionInterface<int(int, int)> {  // NOLINT
+ public:
+  virtual int Perform(const tuple<int, int>& args) {
+    return get<0>(args) - get<1>(args);
+  }
+};
+
+TEST(WithArgsTest, NonInvokeAction) {
+  Action<int(const string&, int, int)> a =  // NOLINT
+      WithArgs<2, 1>(MakeAction(new SubstractAction));
+  EXPECT_EQ(8, a.Perform(make_tuple(string("hi"), 2, 10)));
+}
+
+// Tests using WithArgs to pass all original arguments in the original order.
+TEST(WithArgsTest, Identity) {
+  Action<int(int x, char y, short z)> a =  // NOLINT
+      WithArgs<0, 1, 2>(Invoke(Ternary));
+  EXPECT_EQ(123, a.Perform(make_tuple(100, Char(20), Short(3))));
+}
+
+// Tests using WithArgs with repeated arguments.
+TEST(WithArgsTest, RepeatedArguments) {
+  Action<int(bool, int m, int n)> a =  // NOLINT
+      WithArgs<1, 1, 1, 1>(Invoke(SumOf4));
+  EXPECT_EQ(4, a.Perform(make_tuple(false, 1, 10)));
+}
+
+// Tests using WithArgs with reversed argument order.
+TEST(WithArgsTest, ReversedArgumentOrder) {
+  Action<const char*(short n, const char* input)> a =  // NOLINT
+      WithArgs<1, 0>(Invoke(Binary));
+  const char s[] = "Hello";
+  EXPECT_EQ(s + 2, a.Perform(make_tuple(Short(2), CharPtr(s))));
+}
+
+// Tests using WithArgs with compatible, but not identical, argument types.
+TEST(WithArgsTest, ArgsOfCompatibleTypes) {
+  Action<long(short x, char y, double z, char c)> a =  // NOLINT
+      WithArgs<0, 1, 3>(Invoke(Ternary));
+  EXPECT_EQ(123, a.Perform(make_tuple(Short(100), Char(20), 5.6, Char(3))));
+}
+
+// Tests using WithArgs with an action that returns void.
+TEST(WithArgsTest, VoidAction) {
+  Action<void(double x, char c, int n)> a = WithArgs<2, 1>(Invoke(VoidBinary));
+  g_done = false;
+  a.Perform(make_tuple(1.5, 'a', 3));
+  EXPECT_TRUE(g_done);
+}
+
+// Tests DoAll(a1, a2).
+TEST(DoAllTest, TwoActions) {
+  int n = 0;
+  Action<int(int*)> a = DoAll(SetArgPointee<0>(1),  // NOLINT
+                              Return(2));
+  EXPECT_EQ(2, a.Perform(make_tuple(&n)));
+  EXPECT_EQ(1, n);
+}
+
+// Tests DoAll(a1, a2, a3).
+TEST(DoAllTest, ThreeActions) {
+  int m = 0, n = 0;
+  Action<int(int*, int*)> a = DoAll(SetArgPointee<0>(1),  // NOLINT
+                                    SetArgPointee<1>(2),
+                                    Return(3));
+  EXPECT_EQ(3, a.Perform(make_tuple(&m, &n)));
+  EXPECT_EQ(1, m);
+  EXPECT_EQ(2, n);
+}
+
+// Tests DoAll(a1, a2, a3, a4).
+TEST(DoAllTest, FourActions) {
+  int m = 0, n = 0;
+  char ch = '\0';
+  Action<int(int*, int*, char*)> a =  // NOLINT
+      DoAll(SetArgPointee<0>(1),
+            SetArgPointee<1>(2),
+            SetArgPointee<2>('a'),
+            Return(3));
+  EXPECT_EQ(3, a.Perform(make_tuple(&m, &n, &ch)));
+  EXPECT_EQ(1, m);
+  EXPECT_EQ(2, n);
+  EXPECT_EQ('a', ch);
+}
+
+// Tests DoAll(a1, a2, a3, a4, a5).
+TEST(DoAllTest, FiveActions) {
+  int m = 0, n = 0;
+  char a = '\0', b = '\0';
+  Action<int(int*, int*, char*, char*)> action =  // NOLINT
+      DoAll(SetArgPointee<0>(1),
+            SetArgPointee<1>(2),
+            SetArgPointee<2>('a'),
+            SetArgPointee<3>('b'),
+            Return(3));
+  EXPECT_EQ(3, action.Perform(make_tuple(&m, &n, &a, &b)));
+  EXPECT_EQ(1, m);
+  EXPECT_EQ(2, n);
+  EXPECT_EQ('a', a);
+  EXPECT_EQ('b', b);
+}
+
+// Tests DoAll(a1, a2, ..., a6).
+TEST(DoAllTest, SixActions) {
+  int m = 0, n = 0;
+  char a = '\0', b = '\0', c = '\0';
+  Action<int(int*, int*, char*, char*, char*)> action =  // NOLINT
+      DoAll(SetArgPointee<0>(1),
+            SetArgPointee<1>(2),
+            SetArgPointee<2>('a'),
+            SetArgPointee<3>('b'),
+            SetArgPointee<4>('c'),
+            Return(3));
+  EXPECT_EQ(3, action.Perform(make_tuple(&m, &n, &a, &b, &c)));
+  EXPECT_EQ(1, m);
+  EXPECT_EQ(2, n);
+  EXPECT_EQ('a', a);
+  EXPECT_EQ('b', b);
+  EXPECT_EQ('c', c);
+}
+
+// Tests DoAll(a1, a2, ..., a7).
+TEST(DoAllTest, SevenActions) {
+  int m = 0, n = 0;
+  char a = '\0', b = '\0', c = '\0', d = '\0';
+  Action<int(int*, int*, char*, char*, char*, char*)> action =  // NOLINT
+      DoAll(SetArgPointee<0>(1),
+            SetArgPointee<1>(2),
+            SetArgPointee<2>('a'),
+            SetArgPointee<3>('b'),
+            SetArgPointee<4>('c'),
+            SetArgPointee<5>('d'),
+            Return(3));
+  EXPECT_EQ(3, action.Perform(make_tuple(&m, &n, &a, &b, &c, &d)));
+  EXPECT_EQ(1, m);
+  EXPECT_EQ(2, n);
+  EXPECT_EQ('a', a);
+  EXPECT_EQ('b', b);
+  EXPECT_EQ('c', c);
+  EXPECT_EQ('d', d);
+}
+
+// Tests DoAll(a1, a2, ..., a8).
+TEST(DoAllTest, EightActions) {
+  int m = 0, n = 0;
+  char a = '\0', b = '\0', c = '\0', d = '\0', e = '\0';
+  Action<int(int*, int*, char*, char*, char*, char*,  // NOLINT
+             char*)> action =
+      DoAll(SetArgPointee<0>(1),
+            SetArgPointee<1>(2),
+            SetArgPointee<2>('a'),
+            SetArgPointee<3>('b'),
+            SetArgPointee<4>('c'),
+            SetArgPointee<5>('d'),
+            SetArgPointee<6>('e'),
+            Return(3));
+  EXPECT_EQ(3, action.Perform(make_tuple(&m, &n, &a, &b, &c, &d, &e)));
+  EXPECT_EQ(1, m);
+  EXPECT_EQ(2, n);
+  EXPECT_EQ('a', a);
+  EXPECT_EQ('b', b);
+  EXPECT_EQ('c', c);
+  EXPECT_EQ('d', d);
+  EXPECT_EQ('e', e);
+}
+
+// Tests DoAll(a1, a2, ..., a9).
+TEST(DoAllTest, NineActions) {
+  int m = 0, n = 0;
+  char a = '\0', b = '\0', c = '\0', d = '\0', e = '\0', f = '\0';
+  Action<int(int*, int*, char*, char*, char*, char*,  // NOLINT
+             char*, char*)> action =
+      DoAll(SetArgPointee<0>(1),
+            SetArgPointee<1>(2),
+            SetArgPointee<2>('a'),
+            SetArgPointee<3>('b'),
+            SetArgPointee<4>('c'),
+            SetArgPointee<5>('d'),
+            SetArgPointee<6>('e'),
+            SetArgPointee<7>('f'),
+            Return(3));
+  EXPECT_EQ(3, action.Perform(make_tuple(&m, &n, &a, &b, &c, &d, &e, &f)));
+  EXPECT_EQ(1, m);
+  EXPECT_EQ(2, n);
+  EXPECT_EQ('a', a);
+  EXPECT_EQ('b', b);
+  EXPECT_EQ('c', c);
+  EXPECT_EQ('d', d);
+  EXPECT_EQ('e', e);
+  EXPECT_EQ('f', f);
+}
+
+// Tests DoAll(a1, a2, ..., a10).
+TEST(DoAllTest, TenActions) {
+  int m = 0, n = 0;
+  char a = '\0', b = '\0', c = '\0', d = '\0';
+  char e = '\0', f = '\0', g = '\0';
+  Action<int(int*, int*, char*, char*, char*, char*,  // NOLINT
+             char*, char*, char*)> action =
+      DoAll(SetArgPointee<0>(1),
+            SetArgPointee<1>(2),
+            SetArgPointee<2>('a'),
+            SetArgPointee<3>('b'),
+            SetArgPointee<4>('c'),
+            SetArgPointee<5>('d'),
+            SetArgPointee<6>('e'),
+            SetArgPointee<7>('f'),
+            SetArgPointee<8>('g'),
+            Return(3));
+  EXPECT_EQ(3, action.Perform(make_tuple(&m, &n, &a, &b, &c, &d, &e, &f, &g)));
+  EXPECT_EQ(1, m);
+  EXPECT_EQ(2, n);
+  EXPECT_EQ('a', a);
+  EXPECT_EQ('b', b);
+  EXPECT_EQ('c', c);
+  EXPECT_EQ('d', d);
+  EXPECT_EQ('e', e);
+  EXPECT_EQ('f', f);
+  EXPECT_EQ('g', g);
+}
+
+// The ACTION*() macros trigger warning C4100 (unreferenced formal
+// parameter) in MSVC with -W4.  Unfortunately they cannot be fixed in
+// the macro definition, as the warnings are generated when the macro
+// is expanded and macro expansion cannot contain #pragma.  Therefore
+// we suppress them here.
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4100)
+#endif
+
+// Tests the ACTION*() macro family.
+
+// Tests that ACTION() can define an action that doesn't reference the
+// mock function arguments.
+ACTION(Return5) { return 5; }
+
+TEST(ActionMacroTest, WorksWhenNotReferencingArguments) {
+  Action<double()> a1 = Return5();
+  EXPECT_DOUBLE_EQ(5, a1.Perform(make_tuple()));
+
+  Action<int(double, bool)> a2 = Return5();
+  EXPECT_EQ(5, a2.Perform(make_tuple(1, true)));
+}
+
+// Tests that ACTION() can define an action that returns void.
+ACTION(IncrementArg1) { (*arg1)++; }
+
+TEST(ActionMacroTest, WorksWhenReturningVoid) {
+  Action<void(int, int*)> a1 = IncrementArg1();
+  int n = 0;
+  a1.Perform(make_tuple(5, &n));
+  EXPECT_EQ(1, n);
+}
+
+// Tests that the body of ACTION() can reference the type of the
+// argument.
+ACTION(IncrementArg2) {
+  StaticAssertTypeEq<int*, arg2_type>();
+  arg2_type temp = arg2;
+  (*temp)++;
+}
+
+TEST(ActionMacroTest, CanReferenceArgumentType) {
+  Action<void(int, bool, int*)> a1 = IncrementArg2();
+  int n = 0;
+  a1.Perform(make_tuple(5, false, &n));
+  EXPECT_EQ(1, n);
+}
+
+// Tests that the body of ACTION() can reference the argument tuple
+// via args_type and args.
+ACTION(Sum2) {
+  StaticAssertTypeEq<tuple<int, char, int*>, args_type>();
+  args_type args_copy = args;
+  return get<0>(args_copy) + get<1>(args_copy);
+}
+
+TEST(ActionMacroTest, CanReferenceArgumentTuple) {
+  Action<int(int, char, int*)> a1 = Sum2();
+  int dummy = 0;
+  EXPECT_EQ(11, a1.Perform(make_tuple(5, Char(6), &dummy)));
+}
+
+// Tests that the body of ACTION() can reference the mock function
+// type.
+int Dummy(bool flag) { return flag? 1 : 0; }
+
+ACTION(InvokeDummy) {
+  StaticAssertTypeEq<int(bool), function_type>();
+  function_type* fp = &Dummy;
+  return (*fp)(true);
+}
+
+TEST(ActionMacroTest, CanReferenceMockFunctionType) {
+  Action<int(bool)> a1 = InvokeDummy();
+  EXPECT_EQ(1, a1.Perform(make_tuple(true)));
+  EXPECT_EQ(1, a1.Perform(make_tuple(false)));
+}
+
+// Tests that the body of ACTION() can reference the mock function's
+// return type.
+ACTION(InvokeDummy2) {
+  StaticAssertTypeEq<int, return_type>();
+  return_type result = Dummy(true);
+  return result;
+}
+
+TEST(ActionMacroTest, CanReferenceMockFunctionReturnType) {
+  Action<int(bool)> a1 = InvokeDummy2();
+  EXPECT_EQ(1, a1.Perform(make_tuple(true)));
+  EXPECT_EQ(1, a1.Perform(make_tuple(false)));
+}
+
+// Tests that ACTION() works for arguments passed by const reference.
+ACTION(ReturnAddrOfConstBoolReferenceArg) {
+  StaticAssertTypeEq<const bool&, arg1_type>();
+  return &arg1;
+}
+
+TEST(ActionMacroTest, WorksForConstReferenceArg) {
+  Action<const bool*(int, const bool&)> a = ReturnAddrOfConstBoolReferenceArg();
+  const bool b = false;
+  EXPECT_EQ(&b, a.Perform(tuple<int, const bool&>(0, b)));
+}
+
+// Tests that ACTION() works for arguments passed by non-const reference.
+ACTION(ReturnAddrOfIntReferenceArg) {
+  StaticAssertTypeEq<int&, arg0_type>();
+  return &arg0;
+}
+
+TEST(ActionMacroTest, WorksForNonConstReferenceArg) {
+  Action<int*(int&, bool, int)> a = ReturnAddrOfIntReferenceArg();
+  int n = 0;
+  EXPECT_EQ(&n, a.Perform(tuple<int&, bool, int>(n, true, 1)));
+}
+
+// Tests that ACTION() can be used in a namespace.
+namespace action_test {
+ACTION(Sum) { return arg0 + arg1; }
+}  // namespace action_test
+
+TEST(ActionMacroTest, WorksInNamespace) {
+  Action<int(int, int)> a1 = action_test::Sum();
+  EXPECT_EQ(3, a1.Perform(make_tuple(1, 2)));
+}
+
+// Tests that the same ACTION definition works for mock functions with
+// different argument numbers.
+ACTION(PlusTwo) { return arg0 + 2; }
+
+TEST(ActionMacroTest, WorksForDifferentArgumentNumbers) {
+  Action<int(int)> a1 = PlusTwo();
+  EXPECT_EQ(4, a1.Perform(make_tuple(2)));
+
+  Action<double(float, void*)> a2 = PlusTwo();
+  int dummy;
+  EXPECT_DOUBLE_EQ(6, a2.Perform(make_tuple(4.0f, &dummy)));
+}
+
+// Tests that ACTION_P can define a parameterized action.
+ACTION_P(Plus, n) { return arg0 + n; }
+
+TEST(ActionPMacroTest, DefinesParameterizedAction) {
+  Action<int(int m, bool t)> a1 = Plus(9);
+  EXPECT_EQ(10, a1.Perform(make_tuple(1, true)));
+}
+
+// Tests that the body of ACTION_P can reference the argument types
+// and the parameter type.
+ACTION_P(TypedPlus, n) {
+  arg0_type t1 = arg0;
+  n_type t2 = n;
+  return t1 + t2;
+}
+
+TEST(ActionPMacroTest, CanReferenceArgumentAndParameterTypes) {
+  Action<int(char m, bool t)> a1 = TypedPlus(9);
+  EXPECT_EQ(10, a1.Perform(make_tuple(Char(1), true)));
+}
+
+// Tests that a parameterized action can be used in any mock function
+// whose type is compatible.
+TEST(ActionPMacroTest, WorksInCompatibleMockFunction) {
+  Action<std::string(const std::string& s)> a1 = Plus("tail");
+  const std::string re = "re";
+  EXPECT_EQ("retail", a1.Perform(make_tuple(re)));
+}
+
+// Tests that we can use ACTION*() to define actions overloaded on the
+// number of parameters.
+
+ACTION(OverloadedAction) { return arg0 ? arg1 : "hello"; }
+
+ACTION_P(OverloadedAction, default_value) {
+  return arg0 ? arg1 : default_value;
+}
+
+ACTION_P2(OverloadedAction, true_value, false_value) {
+  return arg0 ? true_value : false_value;
+}
+
+TEST(ActionMacroTest, CanDefineOverloadedActions) {
+  typedef Action<const char*(bool, const char*)> MyAction;
+
+  const MyAction a1 = OverloadedAction();
+  EXPECT_STREQ("hello", a1.Perform(make_tuple(false, CharPtr("world"))));
+  EXPECT_STREQ("world", a1.Perform(make_tuple(true, CharPtr("world"))));
+
+  const MyAction a2 = OverloadedAction("hi");
+  EXPECT_STREQ("hi", a2.Perform(make_tuple(false, CharPtr("world"))));
+  EXPECT_STREQ("world", a2.Perform(make_tuple(true, CharPtr("world"))));
+
+  const MyAction a3 = OverloadedAction("hi", "you");
+  EXPECT_STREQ("hi", a3.Perform(make_tuple(true, CharPtr("world"))));
+  EXPECT_STREQ("you", a3.Perform(make_tuple(false, CharPtr("world"))));
+}
+
+// Tests ACTION_Pn where n >= 3.
+
+ACTION_P3(Plus, m, n, k) { return arg0 + m + n + k; }
+
+TEST(ActionPnMacroTest, WorksFor3Parameters) {
+  Action<double(int m, bool t)> a1 = Plus(100, 20, 3.4);
+  EXPECT_DOUBLE_EQ(3123.4, a1.Perform(make_tuple(3000, true)));
+
+  Action<std::string(const std::string& s)> a2 = Plus("tail", "-", ">");
+  const std::string re = "re";
+  EXPECT_EQ("retail->", a2.Perform(make_tuple(re)));
+}
+
+ACTION_P4(Plus, p0, p1, p2, p3) { return arg0 + p0 + p1 + p2 + p3; }
+
+TEST(ActionPnMacroTest, WorksFor4Parameters) {
+  Action<int(int)> a1 = Plus(1, 2, 3, 4);
+  EXPECT_EQ(10 + 1 + 2 + 3 + 4, a1.Perform(make_tuple(10)));
+}
+
+ACTION_P5(Plus, p0, p1, p2, p3, p4) { return arg0 + p0 + p1 + p2 + p3 + p4; }
+
+TEST(ActionPnMacroTest, WorksFor5Parameters) {
+  Action<int(int)> a1 = Plus(1, 2, 3, 4, 5);
+  EXPECT_EQ(10 + 1 + 2 + 3 + 4 + 5, a1.Perform(make_tuple(10)));
+}
+
+ACTION_P6(Plus, p0, p1, p2, p3, p4, p5) {
+  return arg0 + p0 + p1 + p2 + p3 + p4 + p5;
+}
+
+TEST(ActionPnMacroTest, WorksFor6Parameters) {
+  Action<int(int)> a1 = Plus(1, 2, 3, 4, 5, 6);
+  EXPECT_EQ(10 + 1 + 2 + 3 + 4 + 5 + 6, a1.Perform(make_tuple(10)));
+}
+
+ACTION_P7(Plus, p0, p1, p2, p3, p4, p5, p6) {
+  return arg0 + p0 + p1 + p2 + p3 + p4 + p5 + p6;
+}
+
+TEST(ActionPnMacroTest, WorksFor7Parameters) {
+  Action<int(int)> a1 = Plus(1, 2, 3, 4, 5, 6, 7);
+  EXPECT_EQ(10 + 1 + 2 + 3 + 4 + 5 + 6 + 7, a1.Perform(make_tuple(10)));
+}
+
+ACTION_P8(Plus, p0, p1, p2, p3, p4, p5, p6, p7) {
+  return arg0 + p0 + p1 + p2 + p3 + p4 + p5 + p6 + p7;
+}
+
+TEST(ActionPnMacroTest, WorksFor8Parameters) {
+  Action<int(int)> a1 = Plus(1, 2, 3, 4, 5, 6, 7, 8);
+  EXPECT_EQ(10 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8, a1.Perform(make_tuple(10)));
+}
+
+ACTION_P9(Plus, p0, p1, p2, p3, p4, p5, p6, p7, p8) {
+  return arg0 + p0 + p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8;
+}
+
+TEST(ActionPnMacroTest, WorksFor9Parameters) {
+  Action<int(int)> a1 = Plus(1, 2, 3, 4, 5, 6, 7, 8, 9);
+  EXPECT_EQ(10 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9, a1.Perform(make_tuple(10)));
+}
+
+ACTION_P10(Plus, p0, p1, p2, p3, p4, p5, p6, p7, p8, last_param) {
+  arg0_type t0 = arg0;
+  last_param_type t9 = last_param;
+  return t0 + p0 + p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + t9;
+}
+
+TEST(ActionPnMacroTest, WorksFor10Parameters) {
+  Action<int(int)> a1 = Plus(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+  EXPECT_EQ(10 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10,
+            a1.Perform(make_tuple(10)));
+}
+
+// Tests that the action body can promote the parameter types.
+
+ACTION_P2(PadArgument, prefix, suffix) {
+  // The following lines promote the two parameters to desired types.
+  std::string prefix_str(prefix);
+  char suffix_char = static_cast<char>(suffix);
+  return prefix_str + arg0 + suffix_char;
+}
+
+TEST(ActionPnMacroTest, SimpleTypePromotion) {
+  Action<std::string(const char*)> no_promo =
+      PadArgument(std::string("foo"), 'r');
+  Action<std::string(const char*)> promo =
+      PadArgument("foo", static_cast<int>('r'));
+  EXPECT_EQ("foobar", no_promo.Perform(make_tuple(CharPtr("ba"))));
+  EXPECT_EQ("foobar", promo.Perform(make_tuple(CharPtr("ba"))));
+}
+
+// Tests that we can partially restrict parameter types using a
+// straight-forward pattern.
+
+// Defines a generic action that doesn't restrict the types of its
+// parameters.
+ACTION_P3(ConcatImpl, a, b, c) {
+  std::stringstream ss;
+  ss << a << b << c;
+  return ss.str();
+}
+
+// Next, we try to restrict that either the first parameter is a
+// string, or the second parameter is an int.
+
+// Defines a partially specialized wrapper that restricts the first
+// parameter to std::string.
+template <typename T1, typename T2>
+// ConcatImplActionP3 is the class template ACTION_P3 uses to
+// implement ConcatImpl.  We shouldn't change the name as this
+// pattern requires the user to use it directly.
+ConcatImplActionP3<std::string, T1, T2>
+Concat(const std::string& a, T1 b, T2 c) {
+  GTEST_INTENTIONAL_CONST_COND_PUSH_()
+  if (true) {
+  GTEST_INTENTIONAL_CONST_COND_POP_()
+    // This branch verifies that ConcatImpl() can be invoked without
+    // explicit template arguments.
+    return ConcatImpl(a, b, c);
+  } else {
+    // This branch verifies that ConcatImpl() can also be invoked with
+    // explicit template arguments.  It doesn't really need to be
+    // executed as this is a compile-time verification.
+    return ConcatImpl<std::string, T1, T2>(a, b, c);
+  }
+}
+
+// Defines another partially specialized wrapper that restricts the
+// second parameter to int.
+template <typename T1, typename T2>
+ConcatImplActionP3<T1, int, T2>
+Concat(T1 a, int b, T2 c) {
+  return ConcatImpl(a, b, c);
+}
+
+TEST(ActionPnMacroTest, CanPartiallyRestrictParameterTypes) {
+  Action<const std::string()> a1 = Concat("Hello", "1", 2);
+  EXPECT_EQ("Hello12", a1.Perform(make_tuple()));
+
+  a1 = Concat(1, 2, 3);
+  EXPECT_EQ("123", a1.Perform(make_tuple()));
+}
+
+// Verifies the type of an ACTION*.
+
+ACTION(DoFoo) {}
+ACTION_P(DoFoo, p) {}
+ACTION_P2(DoFoo, p0, p1) {}
+
+TEST(ActionPnMacroTest, TypesAreCorrect) {
+  // DoFoo() must be assignable to a DoFooAction variable.
+  DoFooAction a0 = DoFoo();
+
+  // DoFoo(1) must be assignable to a DoFooActionP variable.
+  DoFooActionP<int> a1 = DoFoo(1);
+
+  // DoFoo(p1, ..., pk) must be assignable to a DoFooActionPk
+  // variable, and so on.
+  DoFooActionP2<int, char> a2 = DoFoo(1, '2');
+  PlusActionP3<int, int, char> a3 = Plus(1, 2, '3');
+  PlusActionP4<int, int, int, char> a4 = Plus(1, 2, 3, '4');
+  PlusActionP5<int, int, int, int, char> a5 = Plus(1, 2, 3, 4, '5');
+  PlusActionP6<int, int, int, int, int, char> a6 = Plus(1, 2, 3, 4, 5, '6');
+  PlusActionP7<int, int, int, int, int, int, char> a7 =
+      Plus(1, 2, 3, 4, 5, 6, '7');
+  PlusActionP8<int, int, int, int, int, int, int, char> a8 =
+      Plus(1, 2, 3, 4, 5, 6, 7, '8');
+  PlusActionP9<int, int, int, int, int, int, int, int, char> a9 =
+      Plus(1, 2, 3, 4, 5, 6, 7, 8, '9');
+  PlusActionP10<int, int, int, int, int, int, int, int, int, char> a10 =
+      Plus(1, 2, 3, 4, 5, 6, 7, 8, 9, '0');
+
+  // Avoid "unused variable" warnings.
+  (void)a0;
+  (void)a1;
+  (void)a2;
+  (void)a3;
+  (void)a4;
+  (void)a5;
+  (void)a6;
+  (void)a7;
+  (void)a8;
+  (void)a9;
+  (void)a10;
+}
+
+// Tests that an ACTION_P*() action can be explicitly instantiated
+// with reference-typed parameters.
+
+ACTION_P(Plus1, x) { return x; }
+ACTION_P2(Plus2, x, y) { return x + y; }
+ACTION_P3(Plus3, x, y, z) { return x + y + z; }
+ACTION_P10(Plus10, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) {
+  return a0 + a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+TEST(ActionPnMacroTest, CanExplicitlyInstantiateWithReferenceTypes) {
+  int x = 1, y = 2, z = 3;
+  const tuple<> empty = make_tuple();
+
+  Action<int()> a = Plus1<int&>(x);
+  EXPECT_EQ(1, a.Perform(empty));
+
+  a = Plus2<const int&, int&>(x, y);
+  EXPECT_EQ(3, a.Perform(empty));
+
+  a = Plus3<int&, const int&, int&>(x, y, z);
+  EXPECT_EQ(6, a.Perform(empty));
+
+  int n[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+  a = Plus10<const int&, int&, const int&, int&, const int&, int&, const int&,
+      int&, const int&, int&>(n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7],
+                              n[8], n[9]);
+  EXPECT_EQ(55, a.Perform(empty));
+}
+
+class NullaryConstructorClass {
+ public:
+  NullaryConstructorClass() : value_(123) {}
+  int value_;
+};
+
+// Tests using ReturnNew() with a nullary constructor.
+TEST(ReturnNewTest, NoArgs) {
+  Action<NullaryConstructorClass*()> a = ReturnNew<NullaryConstructorClass>();
+  NullaryConstructorClass* c = a.Perform(make_tuple());
+  EXPECT_EQ(123, c->value_);
+  delete c;
+}
+
+class UnaryConstructorClass {
+ public:
+  explicit UnaryConstructorClass(int value) : value_(value) {}
+  int value_;
+};
+
+// Tests using ReturnNew() with a unary constructor.
+TEST(ReturnNewTest, Unary) {
+  Action<UnaryConstructorClass*()> a = ReturnNew<UnaryConstructorClass>(4000);
+  UnaryConstructorClass* c = a.Perform(make_tuple());
+  EXPECT_EQ(4000, c->value_);
+  delete c;
+}
+
+TEST(ReturnNewTest, UnaryWorksWhenMockMethodHasArgs) {
+  Action<UnaryConstructorClass*(bool, int)> a =
+      ReturnNew<UnaryConstructorClass>(4000);
+  UnaryConstructorClass* c = a.Perform(make_tuple(false, 5));
+  EXPECT_EQ(4000, c->value_);
+  delete c;
+}
+
+TEST(ReturnNewTest, UnaryWorksWhenMockMethodReturnsPointerToConst) {
+  Action<const UnaryConstructorClass*()> a =
+      ReturnNew<UnaryConstructorClass>(4000);
+  const UnaryConstructorClass* c = a.Perform(make_tuple());
+  EXPECT_EQ(4000, c->value_);
+  delete c;
+}
+
+class TenArgConstructorClass {
+ public:
+  TenArgConstructorClass(int a1, int a2, int a3, int a4, int a5,
+                         int a6, int a7, int a8, int a9, int a10)
+    : value_(a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10) {
+  }
+  int value_;
+};
+
+// Tests using ReturnNew() with a 10-argument constructor.
+TEST(ReturnNewTest, ConstructorThatTakes10Arguments) {
+  Action<TenArgConstructorClass*()> a =
+      ReturnNew<TenArgConstructorClass>(1000000000, 200000000, 30000000,
+                                        4000000, 500000, 60000,
+                                        7000, 800, 90, 0);
+  TenArgConstructorClass* c = a.Perform(make_tuple());
+  EXPECT_EQ(1234567890, c->value_);
+  delete c;
+}
+
+// Tests that ACTION_TEMPLATE works when there is no value parameter.
+ACTION_TEMPLATE(CreateNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_0_VALUE_PARAMS()) {
+  return new T;
+}
+
+TEST(ActionTemplateTest, WorksWithoutValueParam) {
+  const Action<int*()> a = CreateNew<int>();
+  int* p = a.Perform(make_tuple());
+  delete p;
+}
+
+// Tests that ACTION_TEMPLATE works when there are value parameters.
+ACTION_TEMPLATE(CreateNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_1_VALUE_PARAMS(a0)) {
+  return new T(a0);
+}
+
+TEST(ActionTemplateTest, WorksWithValueParams) {
+  const Action<int*()> a = CreateNew<int>(42);
+  int* p = a.Perform(make_tuple());
+  EXPECT_EQ(42, *p);
+  delete p;
+}
+
+// Tests that ACTION_TEMPLATE works for integral template parameters.
+ACTION_TEMPLATE(MyDeleteArg,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_0_VALUE_PARAMS()) {
+  delete get<k>(args);
+}
+
+// Resets a bool variable in the destructor.
+class BoolResetter {
+ public:
+  explicit BoolResetter(bool* value) : value_(value) {}
+  ~BoolResetter() { *value_ = false; }
+ private:
+  bool* value_;
+};
+
+TEST(ActionTemplateTest, WorksForIntegralTemplateParams) {
+  const Action<void(int*, BoolResetter*)> a = MyDeleteArg<1>();
+  int n = 0;
+  bool b = true;
+  BoolResetter* resetter = new BoolResetter(&b);
+  a.Perform(make_tuple(&n, resetter));
+  EXPECT_FALSE(b);  // Verifies that resetter is deleted.
+}
+
+// Tests that ACTION_TEMPLATES works for template template parameters.
+ACTION_TEMPLATE(ReturnSmartPointer,
+                HAS_1_TEMPLATE_PARAMS(template <typename Pointee> class,
+                                      Pointer),
+                AND_1_VALUE_PARAMS(pointee)) {
+  return Pointer<pointee_type>(new pointee_type(pointee));
+}
+
+TEST(ActionTemplateTest, WorksForTemplateTemplateParameters) {
+  using ::testing::internal::linked_ptr;
+  const Action<linked_ptr<int>()> a = ReturnSmartPointer<linked_ptr>(42);
+  linked_ptr<int> p = a.Perform(make_tuple());
+  EXPECT_EQ(42, *p);
+}
+
+// Tests that ACTION_TEMPLATE works for 10 template parameters.
+template <typename T1, typename T2, typename T3, int k4, bool k5,
+          unsigned int k6, typename T7, typename T8, typename T9>
+struct GiantTemplate {
+ public:
+  explicit GiantTemplate(int a_value) : value(a_value) {}
+  int value;
+};
+
+ACTION_TEMPLATE(ReturnGiant,
+                HAS_10_TEMPLATE_PARAMS(
+                    typename, T1,
+                    typename, T2,
+                    typename, T3,
+                    int, k4,
+                    bool, k5,
+                    unsigned int, k6,
+                    class, T7,
+                    class, T8,
+                    class, T9,
+                    template <typename T> class, T10),
+                AND_1_VALUE_PARAMS(value)) {
+  return GiantTemplate<T10<T1>, T2, T3, k4, k5, k6, T7, T8, T9>(value);
+}
+
+TEST(ActionTemplateTest, WorksFor10TemplateParameters) {
+  using ::testing::internal::linked_ptr;
+  typedef GiantTemplate<linked_ptr<int>, bool, double, 5,
+      true, 6, char, unsigned, int> Giant;
+  const Action<Giant()> a = ReturnGiant<
+      int, bool, double, 5, true, 6, char, unsigned, int, linked_ptr>(42);
+  Giant giant = a.Perform(make_tuple());
+  EXPECT_EQ(42, giant.value);
+}
+
+// Tests that ACTION_TEMPLATE works for 10 value parameters.
+ACTION_TEMPLATE(ReturnSum,
+                HAS_1_TEMPLATE_PARAMS(typename, Number),
+                AND_10_VALUE_PARAMS(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10)) {
+  return static_cast<Number>(v1) + v2 + v3 + v4 + v5 + v6 + v7 + v8 + v9 + v10;
+}
+
+TEST(ActionTemplateTest, WorksFor10ValueParameters) {
+  const Action<int()> a = ReturnSum<int>(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+  EXPECT_EQ(55, a.Perform(make_tuple()));
+}
+
+// Tests that ACTION_TEMPLATE and ACTION/ACTION_P* can be overloaded
+// on the number of value parameters.
+
+ACTION(ReturnSum) { return 0; }
+
+ACTION_P(ReturnSum, x) { return x; }
+
+ACTION_TEMPLATE(ReturnSum,
+                HAS_1_TEMPLATE_PARAMS(typename, Number),
+                AND_2_VALUE_PARAMS(v1, v2)) {
+  return static_cast<Number>(v1) + v2;
+}
+
+ACTION_TEMPLATE(ReturnSum,
+                HAS_1_TEMPLATE_PARAMS(typename, Number),
+                AND_3_VALUE_PARAMS(v1, v2, v3)) {
+  return static_cast<Number>(v1) + v2 + v3;
+}
+
+ACTION_TEMPLATE(ReturnSum,
+                HAS_2_TEMPLATE_PARAMS(typename, Number, int, k),
+                AND_4_VALUE_PARAMS(v1, v2, v3, v4)) {
+  return static_cast<Number>(v1) + v2 + v3 + v4 + k;
+}
+
+TEST(ActionTemplateTest, CanBeOverloadedOnNumberOfValueParameters) {
+  const Action<int()> a0 = ReturnSum();
+  const Action<int()> a1 = ReturnSum(1);
+  const Action<int()> a2 = ReturnSum<int>(1, 2);
+  const Action<int()> a3 = ReturnSum<int>(1, 2, 3);
+  const Action<int()> a4 = ReturnSum<int, 10000>(2000, 300, 40, 5);
+  EXPECT_EQ(0, a0.Perform(make_tuple()));
+  EXPECT_EQ(1, a1.Perform(make_tuple()));
+  EXPECT_EQ(3, a2.Perform(make_tuple()));
+  EXPECT_EQ(6, a3.Perform(make_tuple()));
+  EXPECT_EQ(12345, a4.Perform(make_tuple()));
+}
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+}  // namespace gmock_generated_actions_test
+}  // namespace testing
diff --git a/third_party/googletest/googlemock/test/gmock-generated-function-mockers_test.cc b/third_party/googletest/googlemock/test/gmock-generated-function-mockers_test.cc
new file mode 100644
index 0000000..a86a613
--- /dev/null
+++ b/third_party/googletest/googlemock/test/gmock-generated-function-mockers_test.cc
@@ -0,0 +1,622 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests the function mocker classes.
+
+#include "gmock/gmock-generated-function-mockers.h"
+
+#if GTEST_OS_WINDOWS
+// MSDN says the header file to be included for STDMETHOD is BaseTyps.h but
+// we are getting compiler errors if we use basetyps.h, hence including
+// objbase.h for definition of STDMETHOD.
+# include <objbase.h>
+#endif  // GTEST_OS_WINDOWS
+
+#include <map>
+#include <string>
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+// There is a bug in MSVC (fixed in VS 2008) that prevents creating a
+// mock for a function with const arguments, so we don't test such
+// cases for MSVC versions older than 2008.
+#if !GTEST_OS_WINDOWS || (_MSC_VER >= 1500)
+# define GMOCK_ALLOWS_CONST_PARAM_FUNCTIONS
+#endif  // !GTEST_OS_WINDOWS || (_MSC_VER >= 1500)
+
+namespace testing {
+namespace gmock_generated_function_mockers_test {
+
+using testing::internal::string;
+using testing::_;
+using testing::A;
+using testing::An;
+using testing::AnyNumber;
+using testing::Const;
+using testing::DoDefault;
+using testing::Eq;
+using testing::Lt;
+using testing::MockFunction;
+using testing::Ref;
+using testing::Return;
+using testing::ReturnRef;
+using testing::TypedEq;
+
+class FooInterface {
+ public:
+  virtual ~FooInterface() {}
+
+  virtual void VoidReturning(int x) = 0;
+
+  virtual int Nullary() = 0;
+  virtual bool Unary(int x) = 0;
+  virtual long Binary(short x, int y) = 0;  // NOLINT
+  virtual int Decimal(bool b, char c, short d, int e, long f,  // NOLINT
+                      float g, double h, unsigned i, char* j, const string& k)
+      = 0;
+
+  virtual bool TakesNonConstReference(int& n) = 0;  // NOLINT
+  virtual string TakesConstReference(const int& n) = 0;
+#ifdef GMOCK_ALLOWS_CONST_PARAM_FUNCTIONS
+  virtual bool TakesConst(const int x) = 0;
+#endif  // GMOCK_ALLOWS_CONST_PARAM_FUNCTIONS
+
+  virtual int OverloadedOnArgumentNumber() = 0;
+  virtual int OverloadedOnArgumentNumber(int n) = 0;
+
+  virtual int OverloadedOnArgumentType(int n) = 0;
+  virtual char OverloadedOnArgumentType(char c) = 0;
+
+  virtual int OverloadedOnConstness() = 0;
+  virtual char OverloadedOnConstness() const = 0;
+
+  virtual int TypeWithHole(int (*func)()) = 0;
+  virtual int TypeWithComma(const std::map<int, string>& a_map) = 0;
+
+#if GTEST_OS_WINDOWS
+  STDMETHOD_(int, CTNullary)() = 0;
+  STDMETHOD_(bool, CTUnary)(int x) = 0;
+  STDMETHOD_(int, CTDecimal)(bool b, char c, short d, int e, long f,  // NOLINT
+      float g, double h, unsigned i, char* j, const string& k) = 0;
+  STDMETHOD_(char, CTConst)(int x) const = 0;
+#endif  // GTEST_OS_WINDOWS
+};
+
+// Const qualifiers on arguments were once (incorrectly) considered
+// significant in determining whether two virtual functions had the same
+// signature. This was fixed in Visual Studio 2008. However, the compiler
+// still emits a warning that alerts about this change in behavior.
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable : 4373)
+#endif
+class MockFoo : public FooInterface {
+ public:
+  MockFoo() {}
+
+  // Makes sure that a mock function parameter can be named.
+  MOCK_METHOD1(VoidReturning, void(int n));  // NOLINT
+
+  MOCK_METHOD0(Nullary, int());  // NOLINT
+
+  // Makes sure that a mock function parameter can be unnamed.
+  MOCK_METHOD1(Unary, bool(int));  // NOLINT
+  MOCK_METHOD2(Binary, long(short, int));  // NOLINT
+  MOCK_METHOD10(Decimal, int(bool, char, short, int, long, float,  // NOLINT
+                             double, unsigned, char*, const string& str));
+
+  MOCK_METHOD1(TakesNonConstReference, bool(int&));  // NOLINT
+  MOCK_METHOD1(TakesConstReference, string(const int&));
+
+#ifdef GMOCK_ALLOWS_CONST_PARAM_FUNCTIONS
+  MOCK_METHOD1(TakesConst, bool(const int));  // NOLINT
+#endif
+
+  // Tests that the function return type can contain unprotected comma.
+  MOCK_METHOD0(ReturnTypeWithComma, std::map<int, string>());
+  MOCK_CONST_METHOD1(ReturnTypeWithComma,
+                     std::map<int, string>(int));  // NOLINT
+
+  MOCK_METHOD0(OverloadedOnArgumentNumber, int());  // NOLINT
+  MOCK_METHOD1(OverloadedOnArgumentNumber, int(int));  // NOLINT
+
+  MOCK_METHOD1(OverloadedOnArgumentType, int(int));  // NOLINT
+  MOCK_METHOD1(OverloadedOnArgumentType, char(char));  // NOLINT
+
+  MOCK_METHOD0(OverloadedOnConstness, int());  // NOLINT
+  MOCK_CONST_METHOD0(OverloadedOnConstness, char());  // NOLINT
+
+  MOCK_METHOD1(TypeWithHole, int(int (*)()));  // NOLINT
+  MOCK_METHOD1(TypeWithComma, int(const std::map<int, string>&));  // NOLINT
+
+#if GTEST_OS_WINDOWS
+  MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, CTNullary, int());
+  MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, CTUnary, bool(int));
+  MOCK_METHOD10_WITH_CALLTYPE(STDMETHODCALLTYPE, CTDecimal, int(bool b, char c,
+      short d, int e, long f, float g, double h, unsigned i, char* j,
+      const string& k));
+  MOCK_CONST_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, CTConst, char(int));
+
+  // Tests that the function return type can contain unprotected comma.
+  MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, CTReturnTypeWithComma,
+                             std::map<int, string>());
+#endif  // GTEST_OS_WINDOWS
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFoo);
+};
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+class FunctionMockerTest : public testing::Test {
+ protected:
+  FunctionMockerTest() : foo_(&mock_foo_) {}
+
+  FooInterface* const foo_;
+  MockFoo mock_foo_;
+};
+
+// Tests mocking a void-returning function.
+TEST_F(FunctionMockerTest, MocksVoidFunction) {
+  EXPECT_CALL(mock_foo_, VoidReturning(Lt(100)));
+  foo_->VoidReturning(0);
+}
+
+// Tests mocking a nullary function.
+TEST_F(FunctionMockerTest, MocksNullaryFunction) {
+  EXPECT_CALL(mock_foo_, Nullary())
+      .WillOnce(DoDefault())
+      .WillOnce(Return(1));
+
+  EXPECT_EQ(0, foo_->Nullary());
+  EXPECT_EQ(1, foo_->Nullary());
+}
+
+// Tests mocking a unary function.
+TEST_F(FunctionMockerTest, MocksUnaryFunction) {
+  EXPECT_CALL(mock_foo_, Unary(Eq(2)))
+      .Times(2)
+      .WillOnce(Return(true));
+
+  EXPECT_TRUE(foo_->Unary(2));
+  EXPECT_FALSE(foo_->Unary(2));
+}
+
+// Tests mocking a binary function.
+TEST_F(FunctionMockerTest, MocksBinaryFunction) {
+  EXPECT_CALL(mock_foo_, Binary(2, _))
+      .WillOnce(Return(3));
+
+  EXPECT_EQ(3, foo_->Binary(2, 1));
+}
+
+// Tests mocking a decimal function.
+TEST_F(FunctionMockerTest, MocksDecimalFunction) {
+  EXPECT_CALL(mock_foo_, Decimal(true, 'a', 0, 0, 1L, A<float>(),
+                                 Lt(100), 5U, NULL, "hi"))
+      .WillOnce(Return(5));
+
+  EXPECT_EQ(5, foo_->Decimal(true, 'a', 0, 0, 1, 0, 0, 5, NULL, "hi"));
+}
+
+// Tests mocking a function that takes a non-const reference.
+TEST_F(FunctionMockerTest, MocksFunctionWithNonConstReferenceArgument) {
+  int a = 0;
+  EXPECT_CALL(mock_foo_, TakesNonConstReference(Ref(a)))
+      .WillOnce(Return(true));
+
+  EXPECT_TRUE(foo_->TakesNonConstReference(a));
+}
+
+// Tests mocking a function that takes a const reference.
+TEST_F(FunctionMockerTest, MocksFunctionWithConstReferenceArgument) {
+  int a = 0;
+  EXPECT_CALL(mock_foo_, TakesConstReference(Ref(a)))
+      .WillOnce(Return("Hello"));
+
+  EXPECT_EQ("Hello", foo_->TakesConstReference(a));
+}
+
+#ifdef GMOCK_ALLOWS_CONST_PARAM_FUNCTIONS
+// Tests mocking a function that takes a const variable.
+TEST_F(FunctionMockerTest, MocksFunctionWithConstArgument) {
+  EXPECT_CALL(mock_foo_, TakesConst(Lt(10)))
+      .WillOnce(DoDefault());
+
+  EXPECT_FALSE(foo_->TakesConst(5));
+}
+#endif  // GMOCK_ALLOWS_CONST_PARAM_FUNCTIONS
+
+// Tests mocking functions overloaded on the number of arguments.
+TEST_F(FunctionMockerTest, MocksFunctionsOverloadedOnArgumentNumber) {
+  EXPECT_CALL(mock_foo_, OverloadedOnArgumentNumber())
+      .WillOnce(Return(1));
+  EXPECT_CALL(mock_foo_, OverloadedOnArgumentNumber(_))
+      .WillOnce(Return(2));
+
+  EXPECT_EQ(2, foo_->OverloadedOnArgumentNumber(1));
+  EXPECT_EQ(1, foo_->OverloadedOnArgumentNumber());
+}
+
+// Tests mocking functions overloaded on the types of argument.
+TEST_F(FunctionMockerTest, MocksFunctionsOverloadedOnArgumentType) {
+  EXPECT_CALL(mock_foo_, OverloadedOnArgumentType(An<int>()))
+      .WillOnce(Return(1));
+  EXPECT_CALL(mock_foo_, OverloadedOnArgumentType(TypedEq<char>('a')))
+      .WillOnce(Return('b'));
+
+  EXPECT_EQ(1, foo_->OverloadedOnArgumentType(0));
+  EXPECT_EQ('b', foo_->OverloadedOnArgumentType('a'));
+}
+
+// Tests mocking functions overloaded on the const-ness of this object.
+TEST_F(FunctionMockerTest, MocksFunctionsOverloadedOnConstnessOfThis) {
+  EXPECT_CALL(mock_foo_, OverloadedOnConstness());
+  EXPECT_CALL(Const(mock_foo_), OverloadedOnConstness())
+      .WillOnce(Return('a'));
+
+  EXPECT_EQ(0, foo_->OverloadedOnConstness());
+  EXPECT_EQ('a', Const(*foo_).OverloadedOnConstness());
+}
+
+TEST_F(FunctionMockerTest, MocksReturnTypeWithComma) {
+  const std::map<int, string> a_map;
+  EXPECT_CALL(mock_foo_, ReturnTypeWithComma())
+      .WillOnce(Return(a_map));
+  EXPECT_CALL(mock_foo_, ReturnTypeWithComma(42))
+      .WillOnce(Return(a_map));
+
+  EXPECT_EQ(a_map, mock_foo_.ReturnTypeWithComma());
+  EXPECT_EQ(a_map, mock_foo_.ReturnTypeWithComma(42));
+}
+
+#if GTEST_OS_WINDOWS
+// Tests mocking a nullary function with calltype.
+TEST_F(FunctionMockerTest, MocksNullaryFunctionWithCallType) {
+  EXPECT_CALL(mock_foo_, CTNullary())
+      .WillOnce(Return(-1))
+      .WillOnce(Return(0));
+
+  EXPECT_EQ(-1, foo_->CTNullary());
+  EXPECT_EQ(0, foo_->CTNullary());
+}
+
+// Tests mocking a unary function with calltype.
+TEST_F(FunctionMockerTest, MocksUnaryFunctionWithCallType) {
+  EXPECT_CALL(mock_foo_, CTUnary(Eq(2)))
+      .Times(2)
+      .WillOnce(Return(true))
+      .WillOnce(Return(false));
+
+  EXPECT_TRUE(foo_->CTUnary(2));
+  EXPECT_FALSE(foo_->CTUnary(2));
+}
+
+// Tests mocking a decimal function with calltype.
+TEST_F(FunctionMockerTest, MocksDecimalFunctionWithCallType) {
+  EXPECT_CALL(mock_foo_, CTDecimal(true, 'a', 0, 0, 1L, A<float>(),
+                                   Lt(100), 5U, NULL, "hi"))
+      .WillOnce(Return(10));
+
+  EXPECT_EQ(10, foo_->CTDecimal(true, 'a', 0, 0, 1, 0, 0, 5, NULL, "hi"));
+}
+
+// Tests mocking functions overloaded on the const-ness of this object.
+TEST_F(FunctionMockerTest, MocksFunctionsConstFunctionWithCallType) {
+  EXPECT_CALL(Const(mock_foo_), CTConst(_))
+      .WillOnce(Return('a'));
+
+  EXPECT_EQ('a', Const(*foo_).CTConst(0));
+}
+
+TEST_F(FunctionMockerTest, MocksReturnTypeWithCommaAndCallType) {
+  const std::map<int, string> a_map;
+  EXPECT_CALL(mock_foo_, CTReturnTypeWithComma())
+      .WillOnce(Return(a_map));
+
+  EXPECT_EQ(a_map, mock_foo_.CTReturnTypeWithComma());
+}
+
+#endif  // GTEST_OS_WINDOWS
+
+class MockB {
+ public:
+  MockB() {}
+
+  MOCK_METHOD0(DoB, void());
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockB);
+};
+
+// Tests that functions with no EXPECT_CALL() ruls can be called any
+// number of times.
+TEST(ExpectCallTest, UnmentionedFunctionCanBeCalledAnyNumberOfTimes) {
+  {
+    MockB b;
+  }
+
+  {
+    MockB b;
+    b.DoB();
+  }
+
+  {
+    MockB b;
+    b.DoB();
+    b.DoB();
+  }
+}
+
+// Tests mocking template interfaces.
+
+template <typename T>
+class StackInterface {
+ public:
+  virtual ~StackInterface() {}
+
+  // Template parameter appears in function parameter.
+  virtual void Push(const T& value) = 0;
+  virtual void Pop() = 0;
+  virtual int GetSize() const = 0;
+  // Template parameter appears in function return type.
+  virtual const T& GetTop() const = 0;
+};
+
+template <typename T>
+class MockStack : public StackInterface<T> {
+ public:
+  MockStack() {}
+
+  MOCK_METHOD1_T(Push, void(const T& elem));
+  MOCK_METHOD0_T(Pop, void());
+  MOCK_CONST_METHOD0_T(GetSize, int());  // NOLINT
+  MOCK_CONST_METHOD0_T(GetTop, const T&());
+
+  // Tests that the function return type can contain unprotected comma.
+  MOCK_METHOD0_T(ReturnTypeWithComma, std::map<int, int>());
+  MOCK_CONST_METHOD1_T(ReturnTypeWithComma, std::map<int, int>(int));  // NOLINT
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockStack);
+};
+
+// Tests that template mock works.
+TEST(TemplateMockTest, Works) {
+  MockStack<int> mock;
+
+  EXPECT_CALL(mock, GetSize())
+      .WillOnce(Return(0))
+      .WillOnce(Return(1))
+      .WillOnce(Return(0));
+  EXPECT_CALL(mock, Push(_));
+  int n = 5;
+  EXPECT_CALL(mock, GetTop())
+      .WillOnce(ReturnRef(n));
+  EXPECT_CALL(mock, Pop())
+      .Times(AnyNumber());
+
+  EXPECT_EQ(0, mock.GetSize());
+  mock.Push(5);
+  EXPECT_EQ(1, mock.GetSize());
+  EXPECT_EQ(5, mock.GetTop());
+  mock.Pop();
+  EXPECT_EQ(0, mock.GetSize());
+}
+
+TEST(TemplateMockTest, MethodWithCommaInReturnTypeWorks) {
+  MockStack<int> mock;
+
+  const std::map<int, int> a_map;
+  EXPECT_CALL(mock, ReturnTypeWithComma())
+      .WillOnce(Return(a_map));
+  EXPECT_CALL(mock, ReturnTypeWithComma(1))
+      .WillOnce(Return(a_map));
+
+  EXPECT_EQ(a_map, mock.ReturnTypeWithComma());
+  EXPECT_EQ(a_map, mock.ReturnTypeWithComma(1));
+}
+
+#if GTEST_OS_WINDOWS
+// Tests mocking template interfaces with calltype.
+
+template <typename T>
+class StackInterfaceWithCallType {
+ public:
+  virtual ~StackInterfaceWithCallType() {}
+
+  // Template parameter appears in function parameter.
+  STDMETHOD_(void, Push)(const T& value) = 0;
+  STDMETHOD_(void, Pop)() = 0;
+  STDMETHOD_(int, GetSize)() const = 0;
+  // Template parameter appears in function return type.
+  STDMETHOD_(const T&, GetTop)() const = 0;
+};
+
+template <typename T>
+class MockStackWithCallType : public StackInterfaceWithCallType<T> {
+ public:
+  MockStackWithCallType() {}
+
+  MOCK_METHOD1_T_WITH_CALLTYPE(STDMETHODCALLTYPE, Push, void(const T& elem));
+  MOCK_METHOD0_T_WITH_CALLTYPE(STDMETHODCALLTYPE, Pop, void());
+  MOCK_CONST_METHOD0_T_WITH_CALLTYPE(STDMETHODCALLTYPE, GetSize, int());
+  MOCK_CONST_METHOD0_T_WITH_CALLTYPE(STDMETHODCALLTYPE, GetTop, const T&());
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockStackWithCallType);
+};
+
+// Tests that template mock with calltype works.
+TEST(TemplateMockTestWithCallType, Works) {
+  MockStackWithCallType<int> mock;
+
+  EXPECT_CALL(mock, GetSize())
+      .WillOnce(Return(0))
+      .WillOnce(Return(1))
+      .WillOnce(Return(0));
+  EXPECT_CALL(mock, Push(_));
+  int n = 5;
+  EXPECT_CALL(mock, GetTop())
+      .WillOnce(ReturnRef(n));
+  EXPECT_CALL(mock, Pop())
+      .Times(AnyNumber());
+
+  EXPECT_EQ(0, mock.GetSize());
+  mock.Push(5);
+  EXPECT_EQ(1, mock.GetSize());
+  EXPECT_EQ(5, mock.GetTop());
+  mock.Pop();
+  EXPECT_EQ(0, mock.GetSize());
+}
+#endif  // GTEST_OS_WINDOWS
+
+#define MY_MOCK_METHODS1_ \
+    MOCK_METHOD0(Overloaded, void()); \
+    MOCK_CONST_METHOD1(Overloaded, int(int n)); \
+    MOCK_METHOD2(Overloaded, bool(bool f, int n))
+
+class MockOverloadedOnArgNumber {
+ public:
+  MockOverloadedOnArgNumber() {}
+
+  MY_MOCK_METHODS1_;
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockOverloadedOnArgNumber);
+};
+
+TEST(OverloadedMockMethodTest, CanOverloadOnArgNumberInMacroBody) {
+  MockOverloadedOnArgNumber mock;
+  EXPECT_CALL(mock, Overloaded());
+  EXPECT_CALL(mock, Overloaded(1)).WillOnce(Return(2));
+  EXPECT_CALL(mock, Overloaded(true, 1)).WillOnce(Return(true));
+
+  mock.Overloaded();
+  EXPECT_EQ(2, mock.Overloaded(1));
+  EXPECT_TRUE(mock.Overloaded(true, 1));
+}
+
+#define MY_MOCK_METHODS2_ \
+    MOCK_CONST_METHOD1(Overloaded, int(int n)); \
+    MOCK_METHOD1(Overloaded, int(int n));
+
+class MockOverloadedOnConstness {
+ public:
+  MockOverloadedOnConstness() {}
+
+  MY_MOCK_METHODS2_;
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockOverloadedOnConstness);
+};
+
+TEST(OverloadedMockMethodTest, CanOverloadOnConstnessInMacroBody) {
+  MockOverloadedOnConstness mock;
+  const MockOverloadedOnConstness* const_mock = &mock;
+  EXPECT_CALL(mock, Overloaded(1)).WillOnce(Return(2));
+  EXPECT_CALL(*const_mock, Overloaded(1)).WillOnce(Return(3));
+
+  EXPECT_EQ(2, mock.Overloaded(1));
+  EXPECT_EQ(3, const_mock->Overloaded(1));
+}
+
+TEST(MockFunctionTest, WorksForVoidNullary) {
+  MockFunction<void()> foo;
+  EXPECT_CALL(foo, Call());
+  foo.Call();
+}
+
+TEST(MockFunctionTest, WorksForNonVoidNullary) {
+  MockFunction<int()> foo;
+  EXPECT_CALL(foo, Call())
+      .WillOnce(Return(1))
+      .WillOnce(Return(2));
+  EXPECT_EQ(1, foo.Call());
+  EXPECT_EQ(2, foo.Call());
+}
+
+TEST(MockFunctionTest, WorksForVoidUnary) {
+  MockFunction<void(int)> foo;
+  EXPECT_CALL(foo, Call(1));
+  foo.Call(1);
+}
+
+TEST(MockFunctionTest, WorksForNonVoidBinary) {
+  MockFunction<int(bool, int)> foo;
+  EXPECT_CALL(foo, Call(false, 42))
+      .WillOnce(Return(1))
+      .WillOnce(Return(2));
+  EXPECT_CALL(foo, Call(true, Ge(100)))
+      .WillOnce(Return(3));
+  EXPECT_EQ(1, foo.Call(false, 42));
+  EXPECT_EQ(2, foo.Call(false, 42));
+  EXPECT_EQ(3, foo.Call(true, 120));
+}
+
+TEST(MockFunctionTest, WorksFor10Arguments) {
+  MockFunction<int(bool a0, char a1, int a2, int a3, int a4,
+                   int a5, int a6, char a7, int a8, bool a9)> foo;
+  EXPECT_CALL(foo, Call(_, 'a', _, _, _, _, _, _, _, _))
+      .WillOnce(Return(1))
+      .WillOnce(Return(2));
+  EXPECT_EQ(1, foo.Call(false, 'a', 0, 0, 0, 0, 0, 'b', 0, true));
+  EXPECT_EQ(2, foo.Call(true, 'a', 0, 0, 0, 0, 0, 'b', 1, false));
+}
+
+#if GTEST_HAS_STD_FUNCTION_
+TEST(MockFunctionTest, AsStdFunction) {
+  MockFunction<int(int)> foo;
+  auto call = [](const std::function<int(int)> &f, int i) {
+    return f(i);
+  };
+  EXPECT_CALL(foo, Call(1)).WillOnce(Return(-1));
+  EXPECT_CALL(foo, Call(2)).WillOnce(Return(-2));
+  EXPECT_EQ(-1, call(foo.AsStdFunction(), 1));
+  EXPECT_EQ(-2, call(foo.AsStdFunction(), 2));
+}
+
+TEST(MockFunctionTest, AsStdFunctionReturnsReference) {
+  MockFunction<int&()> foo;
+  int value = 1;
+  EXPECT_CALL(foo, Call()).WillOnce(ReturnRef(value));
+  int& ref = foo.AsStdFunction()();
+  EXPECT_EQ(1, ref);
+  value = 2;
+  EXPECT_EQ(2, ref);
+}
+#endif  // GTEST_HAS_STD_FUNCTION_
+
+}  // namespace gmock_generated_function_mockers_test
+}  // namespace testing
diff --git a/third_party/googletest/googlemock/test/gmock-generated-internal-utils_test.cc b/third_party/googletest/googlemock/test/gmock-generated-internal-utils_test.cc
new file mode 100644
index 0000000..e0a535a
--- /dev/null
+++ b/third_party/googletest/googlemock/test/gmock-generated-internal-utils_test.cc
@@ -0,0 +1,127 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests the internal utilities.
+
+#include "gmock/internal/gmock-generated-internal-utils.h"
+#include "gmock/internal/gmock-internal-utils.h"
+#include "gtest/gtest.h"
+
+namespace {
+
+using ::testing::tuple;
+using ::testing::Matcher;
+using ::testing::internal::CompileAssertTypesEqual;
+using ::testing::internal::MatcherTuple;
+using ::testing::internal::Function;
+using ::testing::internal::IgnoredValue;
+
+// Tests the MatcherTuple template struct.
+
+TEST(MatcherTupleTest, ForSize0) {
+  CompileAssertTypesEqual<tuple<>, MatcherTuple<tuple<> >::type>();
+}
+
+TEST(MatcherTupleTest, ForSize1) {
+  CompileAssertTypesEqual<tuple<Matcher<int> >,
+                          MatcherTuple<tuple<int> >::type>();
+}
+
+TEST(MatcherTupleTest, ForSize2) {
+  CompileAssertTypesEqual<tuple<Matcher<int>, Matcher<char> >,
+                          MatcherTuple<tuple<int, char> >::type>();
+}
+
+TEST(MatcherTupleTest, ForSize5) {
+  CompileAssertTypesEqual<tuple<Matcher<int>, Matcher<char>, Matcher<bool>,
+                                Matcher<double>, Matcher<char*> >,
+                          MatcherTuple<tuple<int, char, bool, double, char*>
+                                      >::type>();
+}
+
+// Tests the Function template struct.
+
+TEST(FunctionTest, Nullary) {
+  typedef Function<int()> F;  // NOLINT
+  CompileAssertTypesEqual<int, F::Result>();
+  CompileAssertTypesEqual<tuple<>, F::ArgumentTuple>();
+  CompileAssertTypesEqual<tuple<>, F::ArgumentMatcherTuple>();
+  CompileAssertTypesEqual<void(), F::MakeResultVoid>();
+  CompileAssertTypesEqual<IgnoredValue(), F::MakeResultIgnoredValue>();
+}
+
+TEST(FunctionTest, Unary) {
+  typedef Function<int(bool)> F;  // NOLINT
+  CompileAssertTypesEqual<int, F::Result>();
+  CompileAssertTypesEqual<bool, F::Argument1>();
+  CompileAssertTypesEqual<tuple<bool>, F::ArgumentTuple>();
+  CompileAssertTypesEqual<tuple<Matcher<bool> >, F::ArgumentMatcherTuple>();
+  CompileAssertTypesEqual<void(bool), F::MakeResultVoid>();  // NOLINT
+  CompileAssertTypesEqual<IgnoredValue(bool),  // NOLINT
+      F::MakeResultIgnoredValue>();
+}
+
+TEST(FunctionTest, Binary) {
+  typedef Function<int(bool, const long&)> F;  // NOLINT
+  CompileAssertTypesEqual<int, F::Result>();
+  CompileAssertTypesEqual<bool, F::Argument1>();
+  CompileAssertTypesEqual<const long&, F::Argument2>();  // NOLINT
+  CompileAssertTypesEqual<tuple<bool, const long&>, F::ArgumentTuple>();  // NOLINT
+  CompileAssertTypesEqual<tuple<Matcher<bool>, Matcher<const long&> >,  // NOLINT
+                          F::ArgumentMatcherTuple>();
+  CompileAssertTypesEqual<void(bool, const long&), F::MakeResultVoid>();  // NOLINT
+  CompileAssertTypesEqual<IgnoredValue(bool, const long&),  // NOLINT
+      F::MakeResultIgnoredValue>();
+}
+
+TEST(FunctionTest, LongArgumentList) {
+  typedef Function<char(bool, int, char*, int&, const long&)> F;  // NOLINT
+  CompileAssertTypesEqual<char, F::Result>();
+  CompileAssertTypesEqual<bool, F::Argument1>();
+  CompileAssertTypesEqual<int, F::Argument2>();
+  CompileAssertTypesEqual<char*, F::Argument3>();
+  CompileAssertTypesEqual<int&, F::Argument4>();
+  CompileAssertTypesEqual<const long&, F::Argument5>();  // NOLINT
+  CompileAssertTypesEqual<tuple<bool, int, char*, int&, const long&>,  // NOLINT
+                          F::ArgumentTuple>();
+  CompileAssertTypesEqual<tuple<Matcher<bool>, Matcher<int>, Matcher<char*>,
+                                Matcher<int&>, Matcher<const long&> >,  // NOLINT
+                          F::ArgumentMatcherTuple>();
+  CompileAssertTypesEqual<void(bool, int, char*, int&, const long&),  // NOLINT
+                          F::MakeResultVoid>();
+  CompileAssertTypesEqual<
+      IgnoredValue(bool, int, char*, int&, const long&),  // NOLINT
+      F::MakeResultIgnoredValue>();
+}
+
+}  // Unnamed namespace
diff --git a/third_party/googletest/googlemock/test/gmock-generated-matchers_test.cc b/third_party/googletest/googlemock/test/gmock-generated-matchers_test.cc
new file mode 100644
index 0000000..0e9f77f
--- /dev/null
+++ b/third_party/googletest/googlemock/test/gmock-generated-matchers_test.cc
@@ -0,0 +1,1286 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests the built-in matchers generated by a script.
+
+#include "gmock/gmock-generated-matchers.h"
+
+#include <list>
+#include <map>
+#include <set>
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "gtest/gtest-spi.h"
+
+namespace {
+
+using std::list;
+using std::map;
+using std::pair;
+using std::set;
+using std::stringstream;
+using std::vector;
+using testing::get;
+using testing::make_tuple;
+using testing::tuple;
+using testing::_;
+using testing::Args;
+using testing::Contains;
+using testing::ElementsAre;
+using testing::ElementsAreArray;
+using testing::Eq;
+using testing::Ge;
+using testing::Gt;
+using testing::Le;
+using testing::Lt;
+using testing::MakeMatcher;
+using testing::Matcher;
+using testing::MatcherInterface;
+using testing::MatchResultListener;
+using testing::Ne;
+using testing::Not;
+using testing::Pointee;
+using testing::PrintToString;
+using testing::Ref;
+using testing::StaticAssertTypeEq;
+using testing::StrEq;
+using testing::Value;
+using testing::internal::ElementsAreArrayMatcher;
+using testing::internal::string;
+
+// Returns the description of the given matcher.
+template <typename T>
+string Describe(const Matcher<T>& m) {
+  stringstream ss;
+  m.DescribeTo(&ss);
+  return ss.str();
+}
+
+// Returns the description of the negation of the given matcher.
+template <typename T>
+string DescribeNegation(const Matcher<T>& m) {
+  stringstream ss;
+  m.DescribeNegationTo(&ss);
+  return ss.str();
+}
+
+// Returns the reason why x matches, or doesn't match, m.
+template <typename MatcherType, typename Value>
+string Explain(const MatcherType& m, const Value& x) {
+  stringstream ss;
+  m.ExplainMatchResultTo(x, &ss);
+  return ss.str();
+}
+
+// Tests Args<k0, ..., kn>(m).
+
+TEST(ArgsTest, AcceptsZeroTemplateArg) {
+  const tuple<int, bool> t(5, true);
+  EXPECT_THAT(t, Args<>(Eq(tuple<>())));
+  EXPECT_THAT(t, Not(Args<>(Ne(tuple<>()))));
+}
+
+TEST(ArgsTest, AcceptsOneTemplateArg) {
+  const tuple<int, bool> t(5, true);
+  EXPECT_THAT(t, Args<0>(Eq(make_tuple(5))));
+  EXPECT_THAT(t, Args<1>(Eq(make_tuple(true))));
+  EXPECT_THAT(t, Not(Args<1>(Eq(make_tuple(false)))));
+}
+
+TEST(ArgsTest, AcceptsTwoTemplateArgs) {
+  const tuple<short, int, long> t(4, 5, 6L);  // NOLINT
+
+  EXPECT_THAT(t, (Args<0, 1>(Lt())));
+  EXPECT_THAT(t, (Args<1, 2>(Lt())));
+  EXPECT_THAT(t, Not(Args<0, 2>(Gt())));
+}
+
+TEST(ArgsTest, AcceptsRepeatedTemplateArgs) {
+  const tuple<short, int, long> t(4, 5, 6L);  // NOLINT
+  EXPECT_THAT(t, (Args<0, 0>(Eq())));
+  EXPECT_THAT(t, Not(Args<1, 1>(Ne())));
+}
+
+TEST(ArgsTest, AcceptsDecreasingTemplateArgs) {
+  const tuple<short, int, long> t(4, 5, 6L);  // NOLINT
+  EXPECT_THAT(t, (Args<2, 0>(Gt())));
+  EXPECT_THAT(t, Not(Args<2, 1>(Lt())));
+}
+
+// The MATCHER*() macros trigger warning C4100 (unreferenced formal
+// parameter) in MSVC with -W4.  Unfortunately they cannot be fixed in
+// the macro definition, as the warnings are generated when the macro
+// is expanded and macro expansion cannot contain #pragma.  Therefore
+// we suppress them here.
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4100)
+#endif
+
+MATCHER(SumIsZero, "") {
+  return get<0>(arg) + get<1>(arg) + get<2>(arg) == 0;
+}
+
+TEST(ArgsTest, AcceptsMoreTemplateArgsThanArityOfOriginalTuple) {
+  EXPECT_THAT(make_tuple(-1, 2), (Args<0, 0, 1>(SumIsZero())));
+  EXPECT_THAT(make_tuple(1, 2), Not(Args<0, 0, 1>(SumIsZero())));
+}
+
+TEST(ArgsTest, CanBeNested) {
+  const tuple<short, int, long, int> t(4, 5, 6L, 6);  // NOLINT
+  EXPECT_THAT(t, (Args<1, 2, 3>(Args<1, 2>(Eq()))));
+  EXPECT_THAT(t, (Args<0, 1, 3>(Args<0, 2>(Lt()))));
+}
+
+TEST(ArgsTest, CanMatchTupleByValue) {
+  typedef tuple<char, int, int> Tuple3;
+  const Matcher<Tuple3> m = Args<1, 2>(Lt());
+  EXPECT_TRUE(m.Matches(Tuple3('a', 1, 2)));
+  EXPECT_FALSE(m.Matches(Tuple3('b', 2, 2)));
+}
+
+TEST(ArgsTest, CanMatchTupleByReference) {
+  typedef tuple<char, char, int> Tuple3;
+  const Matcher<const Tuple3&> m = Args<0, 1>(Lt());
+  EXPECT_TRUE(m.Matches(Tuple3('a', 'b', 2)));
+  EXPECT_FALSE(m.Matches(Tuple3('b', 'b', 2)));
+}
+
+// Validates that arg is printed as str.
+MATCHER_P(PrintsAs, str, "") {
+  return testing::PrintToString(arg) == str;
+}
+
+TEST(ArgsTest, AcceptsTenTemplateArgs) {
+  EXPECT_THAT(make_tuple(0, 1L, 2, 3L, 4, 5, 6, 7, 8, 9),
+              (Args<9, 8, 7, 6, 5, 4, 3, 2, 1, 0>(
+                  PrintsAs("(9, 8, 7, 6, 5, 4, 3, 2, 1, 0)"))));
+  EXPECT_THAT(make_tuple(0, 1L, 2, 3L, 4, 5, 6, 7, 8, 9),
+              Not(Args<9, 8, 7, 6, 5, 4, 3, 2, 1, 0>(
+                      PrintsAs("(0, 8, 7, 6, 5, 4, 3, 2, 1, 0)"))));
+}
+
+TEST(ArgsTest, DescirbesSelfCorrectly) {
+  const Matcher<tuple<int, bool, char> > m = Args<2, 0>(Lt());
+  EXPECT_EQ("are a tuple whose fields (#2, #0) are a pair where "
+            "the first < the second",
+            Describe(m));
+}
+
+TEST(ArgsTest, DescirbesNestedArgsCorrectly) {
+  const Matcher<const tuple<int, bool, char, int>&> m =
+      Args<0, 2, 3>(Args<2, 0>(Lt()));
+  EXPECT_EQ("are a tuple whose fields (#0, #2, #3) are a tuple "
+            "whose fields (#2, #0) are a pair where the first < the second",
+            Describe(m));
+}
+
+TEST(ArgsTest, DescribesNegationCorrectly) {
+  const Matcher<tuple<int, char> > m = Args<1, 0>(Gt());
+  EXPECT_EQ("are a tuple whose fields (#1, #0) aren't a pair "
+            "where the first > the second",
+            DescribeNegation(m));
+}
+
+TEST(ArgsTest, ExplainsMatchResultWithoutInnerExplanation) {
+  const Matcher<tuple<bool, int, int> > m = Args<1, 2>(Eq());
+  EXPECT_EQ("whose fields (#1, #2) are (42, 42)",
+            Explain(m, make_tuple(false, 42, 42)));
+  EXPECT_EQ("whose fields (#1, #2) are (42, 43)",
+            Explain(m, make_tuple(false, 42, 43)));
+}
+
+// For testing Args<>'s explanation.
+class LessThanMatcher : public MatcherInterface<tuple<char, int> > {
+ public:
+  virtual void DescribeTo(::std::ostream* os) const {}
+
+  virtual bool MatchAndExplain(tuple<char, int> value,
+                               MatchResultListener* listener) const {
+    const int diff = get<0>(value) - get<1>(value);
+    if (diff > 0) {
+      *listener << "where the first value is " << diff
+                << " more than the second";
+    }
+    return diff < 0;
+  }
+};
+
+Matcher<tuple<char, int> > LessThan() {
+  return MakeMatcher(new LessThanMatcher);
+}
+
+TEST(ArgsTest, ExplainsMatchResultWithInnerExplanation) {
+  const Matcher<tuple<char, int, int> > m = Args<0, 2>(LessThan());
+  EXPECT_EQ("whose fields (#0, #2) are ('a' (97, 0x61), 42), "
+            "where the first value is 55 more than the second",
+            Explain(m, make_tuple('a', 42, 42)));
+  EXPECT_EQ("whose fields (#0, #2) are ('\\0', 43)",
+            Explain(m, make_tuple('\0', 42, 43)));
+}
+
+// For testing ExplainMatchResultTo().
+class GreaterThanMatcher : public MatcherInterface<int> {
+ public:
+  explicit GreaterThanMatcher(int rhs) : rhs_(rhs) {}
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "is greater than " << rhs_;
+  }
+
+  virtual bool MatchAndExplain(int lhs,
+                               MatchResultListener* listener) const {
+    const int diff = lhs - rhs_;
+    if (diff > 0) {
+      *listener << "which is " << diff << " more than " << rhs_;
+    } else if (diff == 0) {
+      *listener << "which is the same as " << rhs_;
+    } else {
+      *listener << "which is " << -diff << " less than " << rhs_;
+    }
+
+    return lhs > rhs_;
+  }
+
+ private:
+  int rhs_;
+};
+
+Matcher<int> GreaterThan(int n) {
+  return MakeMatcher(new GreaterThanMatcher(n));
+}
+
+// Tests for ElementsAre().
+
+TEST(ElementsAreTest, CanDescribeExpectingNoElement) {
+  Matcher<const vector<int>&> m = ElementsAre();
+  EXPECT_EQ("is empty", Describe(m));
+}
+
+TEST(ElementsAreTest, CanDescribeExpectingOneElement) {
+  Matcher<vector<int> > m = ElementsAre(Gt(5));
+  EXPECT_EQ("has 1 element that is > 5", Describe(m));
+}
+
+TEST(ElementsAreTest, CanDescribeExpectingManyElements) {
+  Matcher<list<string> > m = ElementsAre(StrEq("one"), "two");
+  EXPECT_EQ("has 2 elements where\n"
+            "element #0 is equal to \"one\",\n"
+            "element #1 is equal to \"two\"", Describe(m));
+}
+
+TEST(ElementsAreTest, CanDescribeNegationOfExpectingNoElement) {
+  Matcher<vector<int> > m = ElementsAre();
+  EXPECT_EQ("isn't empty", DescribeNegation(m));
+}
+
+TEST(ElementsAreTest, CanDescribeNegationOfExpectingOneElment) {
+  Matcher<const list<int>& > m = ElementsAre(Gt(5));
+  EXPECT_EQ("doesn't have 1 element, or\n"
+            "element #0 isn't > 5", DescribeNegation(m));
+}
+
+TEST(ElementsAreTest, CanDescribeNegationOfExpectingManyElements) {
+  Matcher<const list<string>& > m = ElementsAre("one", "two");
+  EXPECT_EQ("doesn't have 2 elements, or\n"
+            "element #0 isn't equal to \"one\", or\n"
+            "element #1 isn't equal to \"two\"", DescribeNegation(m));
+}
+
+TEST(ElementsAreTest, DoesNotExplainTrivialMatch) {
+  Matcher<const list<int>& > m = ElementsAre(1, Ne(2));
+
+  list<int> test_list;
+  test_list.push_back(1);
+  test_list.push_back(3);
+  EXPECT_EQ("", Explain(m, test_list));  // No need to explain anything.
+}
+
+TEST(ElementsAreTest, ExplainsNonTrivialMatch) {
+  Matcher<const vector<int>& > m =
+      ElementsAre(GreaterThan(1), 0, GreaterThan(2));
+
+  const int a[] = { 10, 0, 100 };
+  vector<int> test_vector(a, a + GTEST_ARRAY_SIZE_(a));
+  EXPECT_EQ("whose element #0 matches, which is 9 more than 1,\n"
+            "and whose element #2 matches, which is 98 more than 2",
+            Explain(m, test_vector));
+}
+
+TEST(ElementsAreTest, CanExplainMismatchWrongSize) {
+  Matcher<const list<int>& > m = ElementsAre(1, 3);
+
+  list<int> test_list;
+  // No need to explain when the container is empty.
+  EXPECT_EQ("", Explain(m, test_list));
+
+  test_list.push_back(1);
+  EXPECT_EQ("which has 1 element", Explain(m, test_list));
+}
+
+TEST(ElementsAreTest, CanExplainMismatchRightSize) {
+  Matcher<const vector<int>& > m = ElementsAre(1, GreaterThan(5));
+
+  vector<int> v;
+  v.push_back(2);
+  v.push_back(1);
+  EXPECT_EQ("whose element #0 doesn't match", Explain(m, v));
+
+  v[0] = 1;
+  EXPECT_EQ("whose element #1 doesn't match, which is 4 less than 5",
+            Explain(m, v));
+}
+
+TEST(ElementsAreTest, MatchesOneElementVector) {
+  vector<string> test_vector;
+  test_vector.push_back("test string");
+
+  EXPECT_THAT(test_vector, ElementsAre(StrEq("test string")));
+}
+
+TEST(ElementsAreTest, MatchesOneElementList) {
+  list<string> test_list;
+  test_list.push_back("test string");
+
+  EXPECT_THAT(test_list, ElementsAre("test string"));
+}
+
+TEST(ElementsAreTest, MatchesThreeElementVector) {
+  vector<string> test_vector;
+  test_vector.push_back("one");
+  test_vector.push_back("two");
+  test_vector.push_back("three");
+
+  EXPECT_THAT(test_vector, ElementsAre("one", StrEq("two"), _));
+}
+
+TEST(ElementsAreTest, MatchesOneElementEqMatcher) {
+  vector<int> test_vector;
+  test_vector.push_back(4);
+
+  EXPECT_THAT(test_vector, ElementsAre(Eq(4)));
+}
+
+TEST(ElementsAreTest, MatchesOneElementAnyMatcher) {
+  vector<int> test_vector;
+  test_vector.push_back(4);
+
+  EXPECT_THAT(test_vector, ElementsAre(_));
+}
+
+TEST(ElementsAreTest, MatchesOneElementValue) {
+  vector<int> test_vector;
+  test_vector.push_back(4);
+
+  EXPECT_THAT(test_vector, ElementsAre(4));
+}
+
+TEST(ElementsAreTest, MatchesThreeElementsMixedMatchers) {
+  vector<int> test_vector;
+  test_vector.push_back(1);
+  test_vector.push_back(2);
+  test_vector.push_back(3);
+
+  EXPECT_THAT(test_vector, ElementsAre(1, Eq(2), _));
+}
+
+TEST(ElementsAreTest, MatchesTenElementVector) {
+  const int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+  vector<int> test_vector(a, a + GTEST_ARRAY_SIZE_(a));
+
+  EXPECT_THAT(test_vector,
+              // The element list can contain values and/or matchers
+              // of different types.
+              ElementsAre(0, Ge(0), _, 3, 4, Ne(2), Eq(6), 7, 8, _));
+}
+
+TEST(ElementsAreTest, DoesNotMatchWrongSize) {
+  vector<string> test_vector;
+  test_vector.push_back("test string");
+  test_vector.push_back("test string");
+
+  Matcher<vector<string> > m = ElementsAre(StrEq("test string"));
+  EXPECT_FALSE(m.Matches(test_vector));
+}
+
+TEST(ElementsAreTest, DoesNotMatchWrongValue) {
+  vector<string> test_vector;
+  test_vector.push_back("other string");
+
+  Matcher<vector<string> > m = ElementsAre(StrEq("test string"));
+  EXPECT_FALSE(m.Matches(test_vector));
+}
+
+TEST(ElementsAreTest, DoesNotMatchWrongOrder) {
+  vector<string> test_vector;
+  test_vector.push_back("one");
+  test_vector.push_back("three");
+  test_vector.push_back("two");
+
+  Matcher<vector<string> > m = ElementsAre(
+    StrEq("one"), StrEq("two"), StrEq("three"));
+  EXPECT_FALSE(m.Matches(test_vector));
+}
+
+TEST(ElementsAreTest, WorksForNestedContainer) {
+  const char* strings[] = {
+    "Hi",
+    "world"
+  };
+
+  vector<list<char> > nested;
+  for (size_t i = 0; i < GTEST_ARRAY_SIZE_(strings); i++) {
+    nested.push_back(list<char>(strings[i], strings[i] + strlen(strings[i])));
+  }
+
+  EXPECT_THAT(nested, ElementsAre(ElementsAre('H', Ne('e')),
+                                  ElementsAre('w', 'o', _, _, 'd')));
+  EXPECT_THAT(nested, Not(ElementsAre(ElementsAre('H', 'e'),
+                                      ElementsAre('w', 'o', _, _, 'd'))));
+}
+
+TEST(ElementsAreTest, WorksWithByRefElementMatchers) {
+  int a[] = { 0, 1, 2 };
+  vector<int> v(a, a + GTEST_ARRAY_SIZE_(a));
+
+  EXPECT_THAT(v, ElementsAre(Ref(v[0]), Ref(v[1]), Ref(v[2])));
+  EXPECT_THAT(v, Not(ElementsAre(Ref(v[0]), Ref(v[1]), Ref(a[2]))));
+}
+
+TEST(ElementsAreTest, WorksWithContainerPointerUsingPointee) {
+  int a[] = { 0, 1, 2 };
+  vector<int> v(a, a + GTEST_ARRAY_SIZE_(a));
+
+  EXPECT_THAT(&v, Pointee(ElementsAre(0, 1, _)));
+  EXPECT_THAT(&v, Not(Pointee(ElementsAre(0, _, 3))));
+}
+
+TEST(ElementsAreTest, WorksWithNativeArrayPassedByReference) {
+  int array[] = { 0, 1, 2 };
+  EXPECT_THAT(array, ElementsAre(0, 1, _));
+  EXPECT_THAT(array, Not(ElementsAre(1, _, _)));
+  EXPECT_THAT(array, Not(ElementsAre(0, _)));
+}
+
+class NativeArrayPassedAsPointerAndSize {
+ public:
+  NativeArrayPassedAsPointerAndSize() {}
+
+  MOCK_METHOD2(Helper, void(int* array, int size));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(NativeArrayPassedAsPointerAndSize);
+};
+
+TEST(ElementsAreTest, WorksWithNativeArrayPassedAsPointerAndSize) {
+  int array[] = { 0, 1 };
+  ::testing::tuple<int*, size_t> array_as_tuple(array, 2);
+  EXPECT_THAT(array_as_tuple, ElementsAre(0, 1));
+  EXPECT_THAT(array_as_tuple, Not(ElementsAre(0)));
+
+  NativeArrayPassedAsPointerAndSize helper;
+  EXPECT_CALL(helper, Helper(_, _))
+      .With(ElementsAre(0, 1));
+  helper.Helper(array, 2);
+}
+
+TEST(ElementsAreTest, WorksWithTwoDimensionalNativeArray) {
+  const char a2[][3] = { "hi", "lo" };
+  EXPECT_THAT(a2, ElementsAre(ElementsAre('h', 'i', '\0'),
+                              ElementsAre('l', 'o', '\0')));
+  EXPECT_THAT(a2, ElementsAre(StrEq("hi"), StrEq("lo")));
+  EXPECT_THAT(a2, ElementsAre(Not(ElementsAre('h', 'o', '\0')),
+                              ElementsAre('l', 'o', '\0')));
+}
+
+TEST(ElementsAreTest, AcceptsStringLiteral) {
+  string array[] = { "hi", "one", "two" };
+  EXPECT_THAT(array, ElementsAre("hi", "one", "two"));
+  EXPECT_THAT(array, Not(ElementsAre("hi", "one", "too")));
+}
+
+#ifndef _MSC_VER
+
+// The following test passes a value of type const char[] to a
+// function template that expects const T&.  Some versions of MSVC
+// generates a compiler error C2665 for that.  We believe it's a bug
+// in MSVC.  Therefore this test is #if-ed out for MSVC.
+
+// Declared here with the size unknown.  Defined AFTER the following test.
+extern const char kHi[];
+
+TEST(ElementsAreTest, AcceptsArrayWithUnknownSize) {
+  // The size of kHi is not known in this test, but ElementsAre() should
+  // still accept it.
+
+  string array1[] = { "hi" };
+  EXPECT_THAT(array1, ElementsAre(kHi));
+
+  string array2[] = { "ho" };
+  EXPECT_THAT(array2, Not(ElementsAre(kHi)));
+}
+
+const char kHi[] = "hi";
+
+#endif  // _MSC_VER
+
+TEST(ElementsAreTest, MakesCopyOfArguments) {
+  int x = 1;
+  int y = 2;
+  // This should make a copy of x and y.
+  ::testing::internal::ElementsAreMatcher<testing::tuple<int, int> >
+          polymorphic_matcher = ElementsAre(x, y);
+  // Changing x and y now shouldn't affect the meaning of the above matcher.
+  x = y = 0;
+  const int array1[] = { 1, 2 };
+  EXPECT_THAT(array1, polymorphic_matcher);
+  const int array2[] = { 0, 0 };
+  EXPECT_THAT(array2, Not(polymorphic_matcher));
+}
+
+
+// Tests for ElementsAreArray().  Since ElementsAreArray() shares most
+// of the implementation with ElementsAre(), we don't test it as
+// thoroughly here.
+
+TEST(ElementsAreArrayTest, CanBeCreatedWithValueArray) {
+  const int a[] = { 1, 2, 3 };
+
+  vector<int> test_vector(a, a + GTEST_ARRAY_SIZE_(a));
+  EXPECT_THAT(test_vector, ElementsAreArray(a));
+
+  test_vector[2] = 0;
+  EXPECT_THAT(test_vector, Not(ElementsAreArray(a)));
+}
+
+TEST(ElementsAreArrayTest, CanBeCreatedWithArraySize) {
+  const char* a[] = { "one", "two", "three" };
+
+  vector<string> test_vector(a, a + GTEST_ARRAY_SIZE_(a));
+  EXPECT_THAT(test_vector, ElementsAreArray(a, GTEST_ARRAY_SIZE_(a)));
+
+  const char** p = a;
+  test_vector[0] = "1";
+  EXPECT_THAT(test_vector, Not(ElementsAreArray(p, GTEST_ARRAY_SIZE_(a))));
+}
+
+TEST(ElementsAreArrayTest, CanBeCreatedWithoutArraySize) {
+  const char* a[] = { "one", "two", "three" };
+
+  vector<string> test_vector(a, a + GTEST_ARRAY_SIZE_(a));
+  EXPECT_THAT(test_vector, ElementsAreArray(a));
+
+  test_vector[0] = "1";
+  EXPECT_THAT(test_vector, Not(ElementsAreArray(a)));
+}
+
+TEST(ElementsAreArrayTest, CanBeCreatedWithMatcherArray) {
+  const Matcher<string> kMatcherArray[] =
+    { StrEq("one"), StrEq("two"), StrEq("three") };
+
+  vector<string> test_vector;
+  test_vector.push_back("one");
+  test_vector.push_back("two");
+  test_vector.push_back("three");
+  EXPECT_THAT(test_vector, ElementsAreArray(kMatcherArray));
+
+  test_vector.push_back("three");
+  EXPECT_THAT(test_vector, Not(ElementsAreArray(kMatcherArray)));
+}
+
+TEST(ElementsAreArrayTest, CanBeCreatedWithVector) {
+  const int a[] = { 1, 2, 3 };
+  vector<int> test_vector(a, a + GTEST_ARRAY_SIZE_(a));
+  const vector<int> expected(a, a + GTEST_ARRAY_SIZE_(a));
+  EXPECT_THAT(test_vector, ElementsAreArray(expected));
+  test_vector.push_back(4);
+  EXPECT_THAT(test_vector, Not(ElementsAreArray(expected)));
+}
+
+#if GTEST_HAS_STD_INITIALIZER_LIST_
+
+TEST(ElementsAreArrayTest, TakesInitializerList) {
+  const int a[5] = { 1, 2, 3, 4, 5 };
+  EXPECT_THAT(a, ElementsAreArray({ 1, 2, 3, 4, 5 }));
+  EXPECT_THAT(a, Not(ElementsAreArray({ 1, 2, 3, 5, 4 })));
+  EXPECT_THAT(a, Not(ElementsAreArray({ 1, 2, 3, 4, 6 })));
+}
+
+TEST(ElementsAreArrayTest, TakesInitializerListOfCStrings) {
+  const string a[5] = { "a", "b", "c", "d", "e" };
+  EXPECT_THAT(a, ElementsAreArray({ "a", "b", "c", "d", "e" }));
+  EXPECT_THAT(a, Not(ElementsAreArray({ "a", "b", "c", "e", "d" })));
+  EXPECT_THAT(a, Not(ElementsAreArray({ "a", "b", "c", "d", "ef" })));
+}
+
+TEST(ElementsAreArrayTest, TakesInitializerListOfSameTypedMatchers) {
+  const int a[5] = { 1, 2, 3, 4, 5 };
+  EXPECT_THAT(a, ElementsAreArray(
+      { Eq(1), Eq(2), Eq(3), Eq(4), Eq(5) }));
+  EXPECT_THAT(a, Not(ElementsAreArray(
+      { Eq(1), Eq(2), Eq(3), Eq(4), Eq(6) })));
+}
+
+TEST(ElementsAreArrayTest,
+     TakesInitializerListOfDifferentTypedMatchers) {
+  const int a[5] = { 1, 2, 3, 4, 5 };
+  // The compiler cannot infer the type of the initializer list if its
+  // elements have different types.  We must explicitly specify the
+  // unified element type in this case.
+  EXPECT_THAT(a, ElementsAreArray<Matcher<int> >(
+      { Eq(1), Ne(-2), Ge(3), Le(4), Eq(5) }));
+  EXPECT_THAT(a, Not(ElementsAreArray<Matcher<int> >(
+      { Eq(1), Ne(-2), Ge(3), Le(4), Eq(6) })));
+}
+
+#endif  // GTEST_HAS_STD_INITIALIZER_LIST_
+
+TEST(ElementsAreArrayTest, CanBeCreatedWithMatcherVector) {
+  const int a[] = { 1, 2, 3 };
+  const Matcher<int> kMatchers[] = { Eq(1), Eq(2), Eq(3) };
+  vector<int> test_vector(a, a + GTEST_ARRAY_SIZE_(a));
+  const vector<Matcher<int> > expected(
+      kMatchers, kMatchers + GTEST_ARRAY_SIZE_(kMatchers));
+  EXPECT_THAT(test_vector, ElementsAreArray(expected));
+  test_vector.push_back(4);
+  EXPECT_THAT(test_vector, Not(ElementsAreArray(expected)));
+}
+
+TEST(ElementsAreArrayTest, CanBeCreatedWithIteratorRange) {
+  const int a[] = { 1, 2, 3 };
+  const vector<int> test_vector(a, a + GTEST_ARRAY_SIZE_(a));
+  const vector<int> expected(a, a + GTEST_ARRAY_SIZE_(a));
+  EXPECT_THAT(test_vector, ElementsAreArray(expected.begin(), expected.end()));
+  // Pointers are iterators, too.
+  EXPECT_THAT(test_vector, ElementsAreArray(a, a + GTEST_ARRAY_SIZE_(a)));
+  // The empty range of NULL pointers should also be okay.
+  int* const null_int = NULL;
+  EXPECT_THAT(test_vector, Not(ElementsAreArray(null_int, null_int)));
+  EXPECT_THAT((vector<int>()), ElementsAreArray(null_int, null_int));
+}
+
+// Since ElementsAre() and ElementsAreArray() share much of the
+// implementation, we only do a sanity test for native arrays here.
+TEST(ElementsAreArrayTest, WorksWithNativeArray) {
+  ::std::string a[] = { "hi", "ho" };
+  ::std::string b[] = { "hi", "ho" };
+
+  EXPECT_THAT(a, ElementsAreArray(b));
+  EXPECT_THAT(a, ElementsAreArray(b, 2));
+  EXPECT_THAT(a, Not(ElementsAreArray(b, 1)));
+}
+
+TEST(ElementsAreArrayTest, SourceLifeSpan) {
+  const int a[] = { 1, 2, 3 };
+  vector<int> test_vector(a, a + GTEST_ARRAY_SIZE_(a));
+  vector<int> expect(a, a + GTEST_ARRAY_SIZE_(a));
+  ElementsAreArrayMatcher<int> matcher_maker =
+      ElementsAreArray(expect.begin(), expect.end());
+  EXPECT_THAT(test_vector, matcher_maker);
+  // Changing in place the values that initialized matcher_maker should not
+  // affect matcher_maker anymore. It should have made its own copy of them.
+  typedef vector<int>::iterator Iter;
+  for (Iter it = expect.begin(); it != expect.end(); ++it) { *it += 10; }
+  EXPECT_THAT(test_vector, matcher_maker);
+  test_vector.push_back(3);
+  EXPECT_THAT(test_vector, Not(matcher_maker));
+}
+
+// Tests for the MATCHER*() macro family.
+
+// Tests that a simple MATCHER() definition works.
+
+MATCHER(IsEven, "") { return (arg % 2) == 0; }
+
+TEST(MatcherMacroTest, Works) {
+  const Matcher<int> m = IsEven();
+  EXPECT_TRUE(m.Matches(6));
+  EXPECT_FALSE(m.Matches(7));
+
+  EXPECT_EQ("is even", Describe(m));
+  EXPECT_EQ("not (is even)", DescribeNegation(m));
+  EXPECT_EQ("", Explain(m, 6));
+  EXPECT_EQ("", Explain(m, 7));
+}
+
+// This also tests that the description string can reference 'negation'.
+MATCHER(IsEven2, negation ? "is odd" : "is even") {
+  if ((arg % 2) == 0) {
+    // Verifies that we can stream to result_listener, a listener
+    // supplied by the MATCHER macro implicitly.
+    *result_listener << "OK";
+    return true;
+  } else {
+    *result_listener << "% 2 == " << (arg % 2);
+    return false;
+  }
+}
+
+// This also tests that the description string can reference matcher
+// parameters.
+MATCHER_P2(EqSumOf, x, y,
+           string(negation ? "doesn't equal" : "equals") + " the sum of " +
+           PrintToString(x) + " and " + PrintToString(y)) {
+  if (arg == (x + y)) {
+    *result_listener << "OK";
+    return true;
+  } else {
+    // Verifies that we can stream to the underlying stream of
+    // result_listener.
+    if (result_listener->stream() != NULL) {
+      *result_listener->stream() << "diff == " << (x + y - arg);
+    }
+    return false;
+  }
+}
+
+// Tests that the matcher description can reference 'negation' and the
+// matcher parameters.
+TEST(MatcherMacroTest, DescriptionCanReferenceNegationAndParameters) {
+  const Matcher<int> m1 = IsEven2();
+  EXPECT_EQ("is even", Describe(m1));
+  EXPECT_EQ("is odd", DescribeNegation(m1));
+
+  const Matcher<int> m2 = EqSumOf(5, 9);
+  EXPECT_EQ("equals the sum of 5 and 9", Describe(m2));
+  EXPECT_EQ("doesn't equal the sum of 5 and 9", DescribeNegation(m2));
+}
+
+// Tests explaining match result in a MATCHER* macro.
+TEST(MatcherMacroTest, CanExplainMatchResult) {
+  const Matcher<int> m1 = IsEven2();
+  EXPECT_EQ("OK", Explain(m1, 4));
+  EXPECT_EQ("% 2 == 1", Explain(m1, 5));
+
+  const Matcher<int> m2 = EqSumOf(1, 2);
+  EXPECT_EQ("OK", Explain(m2, 3));
+  EXPECT_EQ("diff == -1", Explain(m2, 4));
+}
+
+// Tests that the body of MATCHER() can reference the type of the
+// value being matched.
+
+MATCHER(IsEmptyString, "") {
+  StaticAssertTypeEq< ::std::string, arg_type>();
+  return arg == "";
+}
+
+MATCHER(IsEmptyStringByRef, "") {
+  StaticAssertTypeEq<const ::std::string&, arg_type>();
+  return arg == "";
+}
+
+TEST(MatcherMacroTest, CanReferenceArgType) {
+  const Matcher< ::std::string> m1 = IsEmptyString();
+  EXPECT_TRUE(m1.Matches(""));
+
+  const Matcher<const ::std::string&> m2 = IsEmptyStringByRef();
+  EXPECT_TRUE(m2.Matches(""));
+}
+
+// Tests that MATCHER() can be used in a namespace.
+
+namespace matcher_test {
+MATCHER(IsOdd, "") { return (arg % 2) != 0; }
+}  // namespace matcher_test
+
+TEST(MatcherMacroTest, WorksInNamespace) {
+  Matcher<int> m = matcher_test::IsOdd();
+  EXPECT_FALSE(m.Matches(4));
+  EXPECT_TRUE(m.Matches(5));
+}
+
+// Tests that Value() can be used to compose matchers.
+MATCHER(IsPositiveOdd, "") {
+  return Value(arg, matcher_test::IsOdd()) && arg > 0;
+}
+
+TEST(MatcherMacroTest, CanBeComposedUsingValue) {
+  EXPECT_THAT(3, IsPositiveOdd());
+  EXPECT_THAT(4, Not(IsPositiveOdd()));
+  EXPECT_THAT(-1, Not(IsPositiveOdd()));
+}
+
+// Tests that a simple MATCHER_P() definition works.
+
+MATCHER_P(IsGreaterThan32And, n, "") { return arg > 32 && arg > n; }
+
+TEST(MatcherPMacroTest, Works) {
+  const Matcher<int> m = IsGreaterThan32And(5);
+  EXPECT_TRUE(m.Matches(36));
+  EXPECT_FALSE(m.Matches(5));
+
+  EXPECT_EQ("is greater than 32 and 5", Describe(m));
+  EXPECT_EQ("not (is greater than 32 and 5)", DescribeNegation(m));
+  EXPECT_EQ("", Explain(m, 36));
+  EXPECT_EQ("", Explain(m, 5));
+}
+
+// Tests that the description is calculated correctly from the matcher name.
+MATCHER_P(_is_Greater_Than32and_, n, "") { return arg > 32 && arg > n; }
+
+TEST(MatcherPMacroTest, GeneratesCorrectDescription) {
+  const Matcher<int> m = _is_Greater_Than32and_(5);
+
+  EXPECT_EQ("is greater than 32 and 5", Describe(m));
+  EXPECT_EQ("not (is greater than 32 and 5)", DescribeNegation(m));
+  EXPECT_EQ("", Explain(m, 36));
+  EXPECT_EQ("", Explain(m, 5));
+}
+
+// Tests that a MATCHER_P matcher can be explicitly instantiated with
+// a reference parameter type.
+
+class UncopyableFoo {
+ public:
+  explicit UncopyableFoo(char value) : value_(value) {}
+ private:
+  UncopyableFoo(const UncopyableFoo&);
+  void operator=(const UncopyableFoo&);
+
+  char value_;
+};
+
+MATCHER_P(ReferencesUncopyable, variable, "") { return &arg == &variable; }
+
+TEST(MatcherPMacroTest, WorksWhenExplicitlyInstantiatedWithReference) {
+  UncopyableFoo foo1('1'), foo2('2');
+  const Matcher<const UncopyableFoo&> m =
+      ReferencesUncopyable<const UncopyableFoo&>(foo1);
+
+  EXPECT_TRUE(m.Matches(foo1));
+  EXPECT_FALSE(m.Matches(foo2));
+
+  // We don't want the address of the parameter printed, as most
+  // likely it will just annoy the user.  If the address is
+  // interesting, the user should consider passing the parameter by
+  // pointer instead.
+  EXPECT_EQ("references uncopyable 1-byte object <31>", Describe(m));
+}
+
+
+// Tests that the body of MATCHER_Pn() can reference the parameter
+// types.
+
+MATCHER_P3(ParamTypesAreIntLongAndChar, foo, bar, baz, "") {
+  StaticAssertTypeEq<int, foo_type>();
+  StaticAssertTypeEq<long, bar_type>();  // NOLINT
+  StaticAssertTypeEq<char, baz_type>();
+  return arg == 0;
+}
+
+TEST(MatcherPnMacroTest, CanReferenceParamTypes) {
+  EXPECT_THAT(0, ParamTypesAreIntLongAndChar(10, 20L, 'a'));
+}
+
+// Tests that a MATCHER_Pn matcher can be explicitly instantiated with
+// reference parameter types.
+
+MATCHER_P2(ReferencesAnyOf, variable1, variable2, "") {
+  return &arg == &variable1 || &arg == &variable2;
+}
+
+TEST(MatcherPnMacroTest, WorksWhenExplicitlyInstantiatedWithReferences) {
+  UncopyableFoo foo1('1'), foo2('2'), foo3('3');
+  const Matcher<const UncopyableFoo&> m =
+      ReferencesAnyOf<const UncopyableFoo&, const UncopyableFoo&>(foo1, foo2);
+
+  EXPECT_TRUE(m.Matches(foo1));
+  EXPECT_TRUE(m.Matches(foo2));
+  EXPECT_FALSE(m.Matches(foo3));
+}
+
+TEST(MatcherPnMacroTest,
+     GeneratesCorretDescriptionWhenExplicitlyInstantiatedWithReferences) {
+  UncopyableFoo foo1('1'), foo2('2');
+  const Matcher<const UncopyableFoo&> m =
+      ReferencesAnyOf<const UncopyableFoo&, const UncopyableFoo&>(foo1, foo2);
+
+  // We don't want the addresses of the parameters printed, as most
+  // likely they will just annoy the user.  If the addresses are
+  // interesting, the user should consider passing the parameters by
+  // pointers instead.
+  EXPECT_EQ("references any of (1-byte object <31>, 1-byte object <32>)",
+            Describe(m));
+}
+
+// Tests that a simple MATCHER_P2() definition works.
+
+MATCHER_P2(IsNotInClosedRange, low, hi, "") { return arg < low || arg > hi; }
+
+TEST(MatcherPnMacroTest, Works) {
+  const Matcher<const long&> m = IsNotInClosedRange(10, 20);  // NOLINT
+  EXPECT_TRUE(m.Matches(36L));
+  EXPECT_FALSE(m.Matches(15L));
+
+  EXPECT_EQ("is not in closed range (10, 20)", Describe(m));
+  EXPECT_EQ("not (is not in closed range (10, 20))", DescribeNegation(m));
+  EXPECT_EQ("", Explain(m, 36L));
+  EXPECT_EQ("", Explain(m, 15L));
+}
+
+// Tests that MATCHER*() definitions can be overloaded on the number
+// of parameters; also tests MATCHER_Pn() where n >= 3.
+
+MATCHER(EqualsSumOf, "") { return arg == 0; }
+MATCHER_P(EqualsSumOf, a, "") { return arg == a; }
+MATCHER_P2(EqualsSumOf, a, b, "") { return arg == a + b; }
+MATCHER_P3(EqualsSumOf, a, b, c, "") { return arg == a + b + c; }
+MATCHER_P4(EqualsSumOf, a, b, c, d, "") { return arg == a + b + c + d; }
+MATCHER_P5(EqualsSumOf, a, b, c, d, e, "") { return arg == a + b + c + d + e; }
+MATCHER_P6(EqualsSumOf, a, b, c, d, e, f, "") {
+  return arg == a + b + c + d + e + f;
+}
+MATCHER_P7(EqualsSumOf, a, b, c, d, e, f, g, "") {
+  return arg == a + b + c + d + e + f + g;
+}
+MATCHER_P8(EqualsSumOf, a, b, c, d, e, f, g, h, "") {
+  return arg == a + b + c + d + e + f + g + h;
+}
+MATCHER_P9(EqualsSumOf, a, b, c, d, e, f, g, h, i, "") {
+  return arg == a + b + c + d + e + f + g + h + i;
+}
+MATCHER_P10(EqualsSumOf, a, b, c, d, e, f, g, h, i, j, "") {
+  return arg == a + b + c + d + e + f + g + h + i + j;
+}
+
+TEST(MatcherPnMacroTest, CanBeOverloadedOnNumberOfParameters) {
+  EXPECT_THAT(0, EqualsSumOf());
+  EXPECT_THAT(1, EqualsSumOf(1));
+  EXPECT_THAT(12, EqualsSumOf(10, 2));
+  EXPECT_THAT(123, EqualsSumOf(100, 20, 3));
+  EXPECT_THAT(1234, EqualsSumOf(1000, 200, 30, 4));
+  EXPECT_THAT(12345, EqualsSumOf(10000, 2000, 300, 40, 5));
+  EXPECT_THAT("abcdef",
+              EqualsSumOf(::std::string("a"), 'b', 'c', "d", "e", 'f'));
+  EXPECT_THAT("abcdefg",
+              EqualsSumOf(::std::string("a"), 'b', 'c', "d", "e", 'f', 'g'));
+  EXPECT_THAT("abcdefgh",
+              EqualsSumOf(::std::string("a"), 'b', 'c', "d", "e", 'f', 'g',
+                          "h"));
+  EXPECT_THAT("abcdefghi",
+              EqualsSumOf(::std::string("a"), 'b', 'c', "d", "e", 'f', 'g',
+                          "h", 'i'));
+  EXPECT_THAT("abcdefghij",
+              EqualsSumOf(::std::string("a"), 'b', 'c', "d", "e", 'f', 'g',
+                          "h", 'i', ::std::string("j")));
+
+  EXPECT_THAT(1, Not(EqualsSumOf()));
+  EXPECT_THAT(-1, Not(EqualsSumOf(1)));
+  EXPECT_THAT(-12, Not(EqualsSumOf(10, 2)));
+  EXPECT_THAT(-123, Not(EqualsSumOf(100, 20, 3)));
+  EXPECT_THAT(-1234, Not(EqualsSumOf(1000, 200, 30, 4)));
+  EXPECT_THAT(-12345, Not(EqualsSumOf(10000, 2000, 300, 40, 5)));
+  EXPECT_THAT("abcdef ",
+              Not(EqualsSumOf(::std::string("a"), 'b', 'c', "d", "e", 'f')));
+  EXPECT_THAT("abcdefg ",
+              Not(EqualsSumOf(::std::string("a"), 'b', 'c', "d", "e", 'f',
+                              'g')));
+  EXPECT_THAT("abcdefgh ",
+              Not(EqualsSumOf(::std::string("a"), 'b', 'c', "d", "e", 'f', 'g',
+                              "h")));
+  EXPECT_THAT("abcdefghi ",
+              Not(EqualsSumOf(::std::string("a"), 'b', 'c', "d", "e", 'f', 'g',
+                              "h", 'i')));
+  EXPECT_THAT("abcdefghij ",
+              Not(EqualsSumOf(::std::string("a"), 'b', 'c', "d", "e", 'f', 'g',
+                              "h", 'i', ::std::string("j"))));
+}
+
+// Tests that a MATCHER_Pn() definition can be instantiated with any
+// compatible parameter types.
+TEST(MatcherPnMacroTest, WorksForDifferentParameterTypes) {
+  EXPECT_THAT(123, EqualsSumOf(100L, 20, static_cast<char>(3)));
+  EXPECT_THAT("abcd", EqualsSumOf(::std::string("a"), "b", 'c', "d"));
+
+  EXPECT_THAT(124, Not(EqualsSumOf(100L, 20, static_cast<char>(3))));
+  EXPECT_THAT("abcde", Not(EqualsSumOf(::std::string("a"), "b", 'c', "d")));
+}
+
+// Tests that the matcher body can promote the parameter types.
+
+MATCHER_P2(EqConcat, prefix, suffix, "") {
+  // The following lines promote the two parameters to desired types.
+  std::string prefix_str(prefix);
+  char suffix_char = static_cast<char>(suffix);
+  return arg == prefix_str + suffix_char;
+}
+
+TEST(MatcherPnMacroTest, SimpleTypePromotion) {
+  Matcher<std::string> no_promo =
+      EqConcat(std::string("foo"), 't');
+  Matcher<const std::string&> promo =
+      EqConcat("foo", static_cast<int>('t'));
+  EXPECT_FALSE(no_promo.Matches("fool"));
+  EXPECT_FALSE(promo.Matches("fool"));
+  EXPECT_TRUE(no_promo.Matches("foot"));
+  EXPECT_TRUE(promo.Matches("foot"));
+}
+
+// Verifies the type of a MATCHER*.
+
+TEST(MatcherPnMacroTest, TypesAreCorrect) {
+  // EqualsSumOf() must be assignable to a EqualsSumOfMatcher variable.
+  EqualsSumOfMatcher a0 = EqualsSumOf();
+
+  // EqualsSumOf(1) must be assignable to a EqualsSumOfMatcherP variable.
+  EqualsSumOfMatcherP<int> a1 = EqualsSumOf(1);
+
+  // EqualsSumOf(p1, ..., pk) must be assignable to a EqualsSumOfMatcherPk
+  // variable, and so on.
+  EqualsSumOfMatcherP2<int, char> a2 = EqualsSumOf(1, '2');
+  EqualsSumOfMatcherP3<int, int, char> a3 = EqualsSumOf(1, 2, '3');
+  EqualsSumOfMatcherP4<int, int, int, char> a4 = EqualsSumOf(1, 2, 3, '4');
+  EqualsSumOfMatcherP5<int, int, int, int, char> a5 =
+      EqualsSumOf(1, 2, 3, 4, '5');
+  EqualsSumOfMatcherP6<int, int, int, int, int, char> a6 =
+      EqualsSumOf(1, 2, 3, 4, 5, '6');
+  EqualsSumOfMatcherP7<int, int, int, int, int, int, char> a7 =
+      EqualsSumOf(1, 2, 3, 4, 5, 6, '7');
+  EqualsSumOfMatcherP8<int, int, int, int, int, int, int, char> a8 =
+      EqualsSumOf(1, 2, 3, 4, 5, 6, 7, '8');
+  EqualsSumOfMatcherP9<int, int, int, int, int, int, int, int, char> a9 =
+      EqualsSumOf(1, 2, 3, 4, 5, 6, 7, 8, '9');
+  EqualsSumOfMatcherP10<int, int, int, int, int, int, int, int, int, char> a10 =
+      EqualsSumOf(1, 2, 3, 4, 5, 6, 7, 8, 9, '0');
+
+  // Avoid "unused variable" warnings.
+  (void)a0;
+  (void)a1;
+  (void)a2;
+  (void)a3;
+  (void)a4;
+  (void)a5;
+  (void)a6;
+  (void)a7;
+  (void)a8;
+  (void)a9;
+  (void)a10;
+}
+
+// Tests that matcher-typed parameters can be used in Value() inside a
+// MATCHER_Pn definition.
+
+// Succeeds if arg matches exactly 2 of the 3 matchers.
+MATCHER_P3(TwoOf, m1, m2, m3, "") {
+  const int count = static_cast<int>(Value(arg, m1))
+      + static_cast<int>(Value(arg, m2)) + static_cast<int>(Value(arg, m3));
+  return count == 2;
+}
+
+TEST(MatcherPnMacroTest, CanUseMatcherTypedParameterInValue) {
+  EXPECT_THAT(42, TwoOf(Gt(0), Lt(50), Eq(10)));
+  EXPECT_THAT(0, Not(TwoOf(Gt(-1), Lt(1), Eq(0))));
+}
+
+// Tests Contains().
+
+TEST(ContainsTest, ListMatchesWhenElementIsInContainer) {
+  list<int> some_list;
+  some_list.push_back(3);
+  some_list.push_back(1);
+  some_list.push_back(2);
+  EXPECT_THAT(some_list, Contains(1));
+  EXPECT_THAT(some_list, Contains(Gt(2.5)));
+  EXPECT_THAT(some_list, Contains(Eq(2.0f)));
+
+  list<string> another_list;
+  another_list.push_back("fee");
+  another_list.push_back("fie");
+  another_list.push_back("foe");
+  another_list.push_back("fum");
+  EXPECT_THAT(another_list, Contains(string("fee")));
+}
+
+TEST(ContainsTest, ListDoesNotMatchWhenElementIsNotInContainer) {
+  list<int> some_list;
+  some_list.push_back(3);
+  some_list.push_back(1);
+  EXPECT_THAT(some_list, Not(Contains(4)));
+}
+
+TEST(ContainsTest, SetMatchesWhenElementIsInContainer) {
+  set<int> some_set;
+  some_set.insert(3);
+  some_set.insert(1);
+  some_set.insert(2);
+  EXPECT_THAT(some_set, Contains(Eq(1.0)));
+  EXPECT_THAT(some_set, Contains(Eq(3.0f)));
+  EXPECT_THAT(some_set, Contains(2));
+
+  set<const char*> another_set;
+  another_set.insert("fee");
+  another_set.insert("fie");
+  another_set.insert("foe");
+  another_set.insert("fum");
+  EXPECT_THAT(another_set, Contains(Eq(string("fum"))));
+}
+
+TEST(ContainsTest, SetDoesNotMatchWhenElementIsNotInContainer) {
+  set<int> some_set;
+  some_set.insert(3);
+  some_set.insert(1);
+  EXPECT_THAT(some_set, Not(Contains(4)));
+
+  set<const char*> c_string_set;
+  c_string_set.insert("hello");
+  EXPECT_THAT(c_string_set, Not(Contains(string("hello").c_str())));
+}
+
+TEST(ContainsTest, ExplainsMatchResultCorrectly) {
+  const int a[2] = { 1, 2 };
+  Matcher<const int (&)[2]> m = Contains(2);
+  EXPECT_EQ("whose element #1 matches", Explain(m, a));
+
+  m = Contains(3);
+  EXPECT_EQ("", Explain(m, a));
+
+  m = Contains(GreaterThan(0));
+  EXPECT_EQ("whose element #0 matches, which is 1 more than 0", Explain(m, a));
+
+  m = Contains(GreaterThan(10));
+  EXPECT_EQ("", Explain(m, a));
+}
+
+TEST(ContainsTest, DescribesItselfCorrectly) {
+  Matcher<vector<int> > m = Contains(1);
+  EXPECT_EQ("contains at least one element that is equal to 1", Describe(m));
+
+  Matcher<vector<int> > m2 = Not(m);
+  EXPECT_EQ("doesn't contain any element that is equal to 1", Describe(m2));
+}
+
+TEST(ContainsTest, MapMatchesWhenElementIsInContainer) {
+  map<const char*, int> my_map;
+  const char* bar = "a string";
+  my_map[bar] = 2;
+  EXPECT_THAT(my_map, Contains(pair<const char* const, int>(bar, 2)));
+
+  map<string, int> another_map;
+  another_map["fee"] = 1;
+  another_map["fie"] = 2;
+  another_map["foe"] = 3;
+  another_map["fum"] = 4;
+  EXPECT_THAT(another_map, Contains(pair<const string, int>(string("fee"), 1)));
+  EXPECT_THAT(another_map, Contains(pair<const string, int>("fie", 2)));
+}
+
+TEST(ContainsTest, MapDoesNotMatchWhenElementIsNotInContainer) {
+  map<int, int> some_map;
+  some_map[1] = 11;
+  some_map[2] = 22;
+  EXPECT_THAT(some_map, Not(Contains(pair<const int, int>(2, 23))));
+}
+
+TEST(ContainsTest, ArrayMatchesWhenElementIsInContainer) {
+  const char* string_array[] = { "fee", "fie", "foe", "fum" };
+  EXPECT_THAT(string_array, Contains(Eq(string("fum"))));
+}
+
+TEST(ContainsTest, ArrayDoesNotMatchWhenElementIsNotInContainer) {
+  int int_array[] = { 1, 2, 3, 4 };
+  EXPECT_THAT(int_array, Not(Contains(5)));
+}
+
+TEST(ContainsTest, AcceptsMatcher) {
+  const int a[] = { 1, 2, 3 };
+  EXPECT_THAT(a, Contains(Gt(2)));
+  EXPECT_THAT(a, Not(Contains(Gt(4))));
+}
+
+TEST(ContainsTest, WorksForNativeArrayAsTuple) {
+  const int a[] = { 1, 2 };
+  const int* const pointer = a;
+  EXPECT_THAT(make_tuple(pointer, 2), Contains(1));
+  EXPECT_THAT(make_tuple(pointer, 2), Not(Contains(Gt(3))));
+}
+
+TEST(ContainsTest, WorksForTwoDimensionalNativeArray) {
+  int a[][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
+  EXPECT_THAT(a, Contains(ElementsAre(4, 5, 6)));
+  EXPECT_THAT(a, Contains(Contains(5)));
+  EXPECT_THAT(a, Not(Contains(ElementsAre(3, 4, 5))));
+  EXPECT_THAT(a, Contains(Not(Contains(5))));
+}
+
+TEST(AllOfTest, HugeMatcher) {
+  // Verify that using AllOf with many arguments doesn't cause
+  // the compiler to exceed template instantiation depth limit.
+  EXPECT_THAT(0, testing::AllOf(_, _, _, _, _, _, _, _, _,
+                                testing::AllOf(_, _, _, _, _, _, _, _, _, _)));
+}
+
+TEST(AnyOfTest, HugeMatcher) {
+  // Verify that using AnyOf with many arguments doesn't cause
+  // the compiler to exceed template instantiation depth limit.
+  EXPECT_THAT(0, testing::AnyOf(_, _, _, _, _, _, _, _, _,
+                                testing::AnyOf(_, _, _, _, _, _, _, _, _, _)));
+}
+
+namespace adl_test {
+
+// Verifies that the implementation of ::testing::AllOf and ::testing::AnyOf
+// don't issue unqualified recursive calls.  If they do, the argument dependent
+// name lookup will cause AllOf/AnyOf in the 'adl_test' namespace to be found
+// as a candidate and the compilation will break due to an ambiguous overload.
+
+// The matcher must be in the same namespace as AllOf/AnyOf to make argument
+// dependent lookup find those.
+MATCHER(M, "") { return true; }
+
+template <typename T1, typename T2>
+bool AllOf(const T1& t1, const T2& t2) { return true; }
+
+TEST(AllOfTest, DoesNotCallAllOfUnqualified) {
+  EXPECT_THAT(42, testing::AllOf(
+      M(), M(), M(), M(), M(), M(), M(), M(), M(), M()));
+}
+
+template <typename T1, typename T2> bool
+AnyOf(const T1& t1, const T2& t2) { return true; }
+
+TEST(AnyOfTest, DoesNotCallAnyOfUnqualified) {
+  EXPECT_THAT(42, testing::AnyOf(
+      M(), M(), M(), M(), M(), M(), M(), M(), M(), M()));
+}
+
+}  // namespace adl_test
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+}  // namespace
diff --git a/third_party/googletest/googlemock/test/gmock-internal-utils_test.cc b/third_party/googletest/googlemock/test/gmock-internal-utils_test.cc
new file mode 100644
index 0000000..4f00f0d
--- /dev/null
+++ b/third_party/googletest/googlemock/test/gmock-internal-utils_test.cc
@@ -0,0 +1,698 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests the internal utilities.
+
+#include "gmock/internal/gmock-internal-utils.h"
+#include <stdlib.h>
+#include <map>
+#include <string>
+#include <sstream>
+#include <vector>
+#include "gmock/gmock.h"
+#include "gmock/internal/gmock-port.h"
+#include "gtest/gtest.h"
+#include "gtest/gtest-spi.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+#if GTEST_OS_CYGWIN
+# include <sys/types.h>  // For ssize_t. NOLINT
+#endif
+
+class ProtocolMessage;
+
+namespace proto2 {
+class Message;
+}  // namespace proto2
+
+namespace testing {
+namespace internal {
+
+namespace {
+
+TEST(ConvertIdentifierNameToWordsTest, WorksWhenNameContainsNoWord) {
+  EXPECT_EQ("", ConvertIdentifierNameToWords(""));
+  EXPECT_EQ("", ConvertIdentifierNameToWords("_"));
+  EXPECT_EQ("", ConvertIdentifierNameToWords("__"));
+}
+
+TEST(ConvertIdentifierNameToWordsTest, WorksWhenNameContainsDigits) {
+  EXPECT_EQ("1", ConvertIdentifierNameToWords("_1"));
+  EXPECT_EQ("2", ConvertIdentifierNameToWords("2_"));
+  EXPECT_EQ("34", ConvertIdentifierNameToWords("_34_"));
+  EXPECT_EQ("34 56", ConvertIdentifierNameToWords("_34_56"));
+}
+
+TEST(ConvertIdentifierNameToWordsTest, WorksWhenNameContainsCamelCaseWords) {
+  EXPECT_EQ("a big word", ConvertIdentifierNameToWords("ABigWord"));
+  EXPECT_EQ("foo bar", ConvertIdentifierNameToWords("FooBar"));
+  EXPECT_EQ("foo", ConvertIdentifierNameToWords("Foo_"));
+  EXPECT_EQ("foo bar", ConvertIdentifierNameToWords("_Foo_Bar_"));
+  EXPECT_EQ("foo and bar", ConvertIdentifierNameToWords("_Foo__And_Bar"));
+}
+
+TEST(ConvertIdentifierNameToWordsTest, WorksWhenNameContains_SeparatedWords) {
+  EXPECT_EQ("foo bar", ConvertIdentifierNameToWords("foo_bar"));
+  EXPECT_EQ("foo", ConvertIdentifierNameToWords("_foo_"));
+  EXPECT_EQ("foo bar", ConvertIdentifierNameToWords("_foo_bar_"));
+  EXPECT_EQ("foo and bar", ConvertIdentifierNameToWords("_foo__and_bar"));
+}
+
+TEST(ConvertIdentifierNameToWordsTest, WorksWhenNameIsMixture) {
+  EXPECT_EQ("foo bar 123", ConvertIdentifierNameToWords("Foo_bar123"));
+  EXPECT_EQ("chapter 11 section 1",
+            ConvertIdentifierNameToWords("_Chapter11Section_1_"));
+}
+
+TEST(PointeeOfTest, WorksForSmartPointers) {
+  CompileAssertTypesEqual<const char,
+      PointeeOf<internal::linked_ptr<const char> >::type>();
+#if GTEST_HAS_STD_UNIQUE_PTR_
+  CompileAssertTypesEqual<int, PointeeOf<std::unique_ptr<int> >::type>();
+#endif  // GTEST_HAS_STD_UNIQUE_PTR_
+#if GTEST_HAS_STD_SHARED_PTR_
+  CompileAssertTypesEqual<std::string,
+                          PointeeOf<std::shared_ptr<std::string> >::type>();
+#endif  // GTEST_HAS_STD_SHARED_PTR_
+}
+
+TEST(PointeeOfTest, WorksForRawPointers) {
+  CompileAssertTypesEqual<int, PointeeOf<int*>::type>();
+  CompileAssertTypesEqual<const char, PointeeOf<const char*>::type>();
+  CompileAssertTypesEqual<void, PointeeOf<void*>::type>();
+}
+
+TEST(GetRawPointerTest, WorksForSmartPointers) {
+#if GTEST_HAS_STD_UNIQUE_PTR_
+  const char* const raw_p1 = new const char('a');  // NOLINT
+  const std::unique_ptr<const char> p1(raw_p1);
+  EXPECT_EQ(raw_p1, GetRawPointer(p1));
+#endif  // GTEST_HAS_STD_UNIQUE_PTR_
+#if GTEST_HAS_STD_SHARED_PTR_
+  double* const raw_p2 = new double(2.5);  // NOLINT
+  const std::shared_ptr<double> p2(raw_p2);
+  EXPECT_EQ(raw_p2, GetRawPointer(p2));
+#endif  // GTEST_HAS_STD_SHARED_PTR_
+
+  const char* const raw_p4 = new const char('a');  // NOLINT
+  const internal::linked_ptr<const char> p4(raw_p4);
+  EXPECT_EQ(raw_p4, GetRawPointer(p4));
+}
+
+TEST(GetRawPointerTest, WorksForRawPointers) {
+  int* p = NULL;
+  // Don't use EXPECT_EQ as no NULL-testing magic on Symbian.
+  EXPECT_TRUE(NULL == GetRawPointer(p));
+  int n = 1;
+  EXPECT_EQ(&n, GetRawPointer(&n));
+}
+
+// Tests KindOf<T>.
+
+class Base {};
+class Derived : public Base {};
+
+TEST(KindOfTest, Bool) {
+  EXPECT_EQ(kBool, GMOCK_KIND_OF_(bool));  // NOLINT
+}
+
+TEST(KindOfTest, Integer) {
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(char));  // NOLINT
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(signed char));  // NOLINT
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(unsigned char));  // NOLINT
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(short));  // NOLINT
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(unsigned short));  // NOLINT
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(int));  // NOLINT
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(unsigned int));  // NOLINT
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(long));  // NOLINT
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(unsigned long));  // NOLINT
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(wchar_t));  // NOLINT
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(Int64));  // NOLINT
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(UInt64));  // NOLINT
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(size_t));  // NOLINT
+#if GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_CYGWIN
+  // ssize_t is not defined on Windows and possibly some other OSes.
+  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(ssize_t));  // NOLINT
+#endif
+}
+
+TEST(KindOfTest, FloatingPoint) {
+  EXPECT_EQ(kFloatingPoint, GMOCK_KIND_OF_(float));  // NOLINT
+  EXPECT_EQ(kFloatingPoint, GMOCK_KIND_OF_(double));  // NOLINT
+  EXPECT_EQ(kFloatingPoint, GMOCK_KIND_OF_(long double));  // NOLINT
+}
+
+TEST(KindOfTest, Other) {
+  EXPECT_EQ(kOther, GMOCK_KIND_OF_(void*));  // NOLINT
+  EXPECT_EQ(kOther, GMOCK_KIND_OF_(char**));  // NOLINT
+  EXPECT_EQ(kOther, GMOCK_KIND_OF_(Base));  // NOLINT
+}
+
+// Tests LosslessArithmeticConvertible<T, U>.
+
+TEST(LosslessArithmeticConvertibleTest, BoolToBool) {
+  EXPECT_TRUE((LosslessArithmeticConvertible<bool, bool>::value));
+}
+
+TEST(LosslessArithmeticConvertibleTest, BoolToInteger) {
+  EXPECT_TRUE((LosslessArithmeticConvertible<bool, char>::value));
+  EXPECT_TRUE((LosslessArithmeticConvertible<bool, int>::value));
+  EXPECT_TRUE(
+      (LosslessArithmeticConvertible<bool, unsigned long>::value));  // NOLINT
+}
+
+TEST(LosslessArithmeticConvertibleTest, BoolToFloatingPoint) {
+  EXPECT_TRUE((LosslessArithmeticConvertible<bool, float>::value));
+  EXPECT_TRUE((LosslessArithmeticConvertible<bool, double>::value));
+}
+
+TEST(LosslessArithmeticConvertibleTest, IntegerToBool) {
+  EXPECT_FALSE((LosslessArithmeticConvertible<unsigned char, bool>::value));
+  EXPECT_FALSE((LosslessArithmeticConvertible<int, bool>::value));
+}
+
+TEST(LosslessArithmeticConvertibleTest, IntegerToInteger) {
+  // Unsigned => larger signed is fine.
+  EXPECT_TRUE((LosslessArithmeticConvertible<unsigned char, int>::value));
+
+  // Unsigned => larger unsigned is fine.
+  EXPECT_TRUE(
+      (LosslessArithmeticConvertible<unsigned short, UInt64>::value)); // NOLINT
+
+  // Signed => unsigned is not fine.
+  EXPECT_FALSE((LosslessArithmeticConvertible<short, UInt64>::value)); // NOLINT
+  EXPECT_FALSE((LosslessArithmeticConvertible<
+      signed char, unsigned int>::value));  // NOLINT
+
+  // Same size and same signedness: fine too.
+  EXPECT_TRUE((LosslessArithmeticConvertible<
+               unsigned char, unsigned char>::value));
+  EXPECT_TRUE((LosslessArithmeticConvertible<int, int>::value));
+  EXPECT_TRUE((LosslessArithmeticConvertible<wchar_t, wchar_t>::value));
+  EXPECT_TRUE((LosslessArithmeticConvertible<
+               unsigned long, unsigned long>::value));  // NOLINT
+
+  // Same size, different signedness: not fine.
+  EXPECT_FALSE((LosslessArithmeticConvertible<
+                unsigned char, signed char>::value));
+  EXPECT_FALSE((LosslessArithmeticConvertible<int, unsigned int>::value));
+  EXPECT_FALSE((LosslessArithmeticConvertible<UInt64, Int64>::value));
+
+  // Larger size => smaller size is not fine.
+  EXPECT_FALSE((LosslessArithmeticConvertible<long, char>::value));  // NOLINT
+  EXPECT_FALSE((LosslessArithmeticConvertible<int, signed char>::value));
+  EXPECT_FALSE((LosslessArithmeticConvertible<Int64, unsigned int>::value));
+}
+
+TEST(LosslessArithmeticConvertibleTest, IntegerToFloatingPoint) {
+  // Integers cannot be losslessly converted to floating-points, as
+  // the format of the latter is implementation-defined.
+  EXPECT_FALSE((LosslessArithmeticConvertible<char, float>::value));
+  EXPECT_FALSE((LosslessArithmeticConvertible<int, double>::value));
+  EXPECT_FALSE((LosslessArithmeticConvertible<
+                short, long double>::value));  // NOLINT
+}
+
+TEST(LosslessArithmeticConvertibleTest, FloatingPointToBool) {
+  EXPECT_FALSE((LosslessArithmeticConvertible<float, bool>::value));
+  EXPECT_FALSE((LosslessArithmeticConvertible<double, bool>::value));
+}
+
+TEST(LosslessArithmeticConvertibleTest, FloatingPointToInteger) {
+  EXPECT_FALSE((LosslessArithmeticConvertible<float, long>::value));  // NOLINT
+  EXPECT_FALSE((LosslessArithmeticConvertible<double, Int64>::value));
+  EXPECT_FALSE((LosslessArithmeticConvertible<long double, int>::value));
+}
+
+TEST(LosslessArithmeticConvertibleTest, FloatingPointToFloatingPoint) {
+  // Smaller size => larger size is fine.
+  EXPECT_TRUE((LosslessArithmeticConvertible<float, double>::value));
+  EXPECT_TRUE((LosslessArithmeticConvertible<float, long double>::value));
+  EXPECT_TRUE((LosslessArithmeticConvertible<double, long double>::value));
+
+  // Same size: fine.
+  EXPECT_TRUE((LosslessArithmeticConvertible<float, float>::value));
+  EXPECT_TRUE((LosslessArithmeticConvertible<double, double>::value));
+
+  // Larger size => smaller size is not fine.
+  EXPECT_FALSE((LosslessArithmeticConvertible<double, float>::value));
+  GTEST_INTENTIONAL_CONST_COND_PUSH_()
+  if (sizeof(double) == sizeof(long double)) {  // NOLINT
+  GTEST_INTENTIONAL_CONST_COND_POP_()
+    // In some implementations (e.g. MSVC), double and long double
+    // have the same size.
+    EXPECT_TRUE((LosslessArithmeticConvertible<long double, double>::value));
+  } else {
+    EXPECT_FALSE((LosslessArithmeticConvertible<long double, double>::value));
+  }
+}
+
+// Tests the TupleMatches() template function.
+
+TEST(TupleMatchesTest, WorksForSize0) {
+  tuple<> matchers;
+  tuple<> values;
+
+  EXPECT_TRUE(TupleMatches(matchers, values));
+}
+
+TEST(TupleMatchesTest, WorksForSize1) {
+  tuple<Matcher<int> > matchers(Eq(1));
+  tuple<int> values1(1),
+      values2(2);
+
+  EXPECT_TRUE(TupleMatches(matchers, values1));
+  EXPECT_FALSE(TupleMatches(matchers, values2));
+}
+
+TEST(TupleMatchesTest, WorksForSize2) {
+  tuple<Matcher<int>, Matcher<char> > matchers(Eq(1), Eq('a'));
+  tuple<int, char> values1(1, 'a'),
+      values2(1, 'b'),
+      values3(2, 'a'),
+      values4(2, 'b');
+
+  EXPECT_TRUE(TupleMatches(matchers, values1));
+  EXPECT_FALSE(TupleMatches(matchers, values2));
+  EXPECT_FALSE(TupleMatches(matchers, values3));
+  EXPECT_FALSE(TupleMatches(matchers, values4));
+}
+
+TEST(TupleMatchesTest, WorksForSize5) {
+  tuple<Matcher<int>, Matcher<char>, Matcher<bool>, Matcher<long>,  // NOLINT
+      Matcher<string> >
+      matchers(Eq(1), Eq('a'), Eq(true), Eq(2L), Eq("hi"));
+  tuple<int, char, bool, long, string>  // NOLINT
+      values1(1, 'a', true, 2L, "hi"),
+      values2(1, 'a', true, 2L, "hello"),
+      values3(2, 'a', true, 2L, "hi");
+
+  EXPECT_TRUE(TupleMatches(matchers, values1));
+  EXPECT_FALSE(TupleMatches(matchers, values2));
+  EXPECT_FALSE(TupleMatches(matchers, values3));
+}
+
+// Tests that Assert(true, ...) succeeds.
+TEST(AssertTest, SucceedsOnTrue) {
+  Assert(true, __FILE__, __LINE__, "This should succeed.");
+  Assert(true, __FILE__, __LINE__);  // This should succeed too.
+}
+
+// Tests that Assert(false, ...) generates a fatal failure.
+TEST(AssertTest, FailsFatallyOnFalse) {
+  EXPECT_DEATH_IF_SUPPORTED({
+    Assert(false, __FILE__, __LINE__, "This should fail.");
+  }, "");
+
+  EXPECT_DEATH_IF_SUPPORTED({
+    Assert(false, __FILE__, __LINE__);
+  }, "");
+}
+
+// Tests that Expect(true, ...) succeeds.
+TEST(ExpectTest, SucceedsOnTrue) {
+  Expect(true, __FILE__, __LINE__, "This should succeed.");
+  Expect(true, __FILE__, __LINE__);  // This should succeed too.
+}
+
+// Tests that Expect(false, ...) generates a non-fatal failure.
+TEST(ExpectTest, FailsNonfatallyOnFalse) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    Expect(false, __FILE__, __LINE__, "This should fail.");
+  }, "This should fail");
+
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    Expect(false, __FILE__, __LINE__);
+  }, "Expectation failed");
+}
+
+// Tests LogIsVisible().
+
+class LogIsVisibleTest : public ::testing::Test {
+ protected:
+  virtual void SetUp() {
+    original_verbose_ = GMOCK_FLAG(verbose);
+  }
+
+  virtual void TearDown() { GMOCK_FLAG(verbose) = original_verbose_; }
+
+  string original_verbose_;
+};
+
+TEST_F(LogIsVisibleTest, AlwaysReturnsTrueIfVerbosityIsInfo) {
+  GMOCK_FLAG(verbose) = kInfoVerbosity;
+  EXPECT_TRUE(LogIsVisible(kInfo));
+  EXPECT_TRUE(LogIsVisible(kWarning));
+}
+
+TEST_F(LogIsVisibleTest, AlwaysReturnsFalseIfVerbosityIsError) {
+  GMOCK_FLAG(verbose) = kErrorVerbosity;
+  EXPECT_FALSE(LogIsVisible(kInfo));
+  EXPECT_FALSE(LogIsVisible(kWarning));
+}
+
+TEST_F(LogIsVisibleTest, WorksWhenVerbosityIsWarning) {
+  GMOCK_FLAG(verbose) = kWarningVerbosity;
+  EXPECT_FALSE(LogIsVisible(kInfo));
+  EXPECT_TRUE(LogIsVisible(kWarning));
+}
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Tests the Log() function.
+
+// Verifies that Log() behaves correctly for the given verbosity level
+// and log severity.
+void TestLogWithSeverity(const string& verbosity, LogSeverity severity,
+                         bool should_print) {
+  const string old_flag = GMOCK_FLAG(verbose);
+  GMOCK_FLAG(verbose) = verbosity;
+  CaptureStdout();
+  Log(severity, "Test log.\n", 0);
+  if (should_print) {
+    EXPECT_THAT(GetCapturedStdout().c_str(),
+                ContainsRegex(
+                    severity == kWarning ?
+                    "^\nGMOCK WARNING:\nTest log\\.\nStack trace:\n" :
+                    "^\nTest log\\.\nStack trace:\n"));
+  } else {
+    EXPECT_STREQ("", GetCapturedStdout().c_str());
+  }
+  GMOCK_FLAG(verbose) = old_flag;
+}
+
+// Tests that when the stack_frames_to_skip parameter is negative,
+// Log() doesn't include the stack trace in the output.
+TEST(LogTest, NoStackTraceWhenStackFramesToSkipIsNegative) {
+  const string saved_flag = GMOCK_FLAG(verbose);
+  GMOCK_FLAG(verbose) = kInfoVerbosity;
+  CaptureStdout();
+  Log(kInfo, "Test log.\n", -1);
+  EXPECT_STREQ("\nTest log.\n", GetCapturedStdout().c_str());
+  GMOCK_FLAG(verbose) = saved_flag;
+}
+
+struct MockStackTraceGetter : testing::internal::OsStackTraceGetterInterface {
+  virtual string CurrentStackTrace(int max_depth, int skip_count) {
+    return (testing::Message() << max_depth << "::" << skip_count << "\n")
+        .GetString();
+  }
+  virtual void UponLeavingGTest() {}
+};
+
+// Tests that in opt mode, a positive stack_frames_to_skip argument is
+// treated as 0.
+TEST(LogTest, NoSkippingStackFrameInOptMode) {
+  MockStackTraceGetter* mock_os_stack_trace_getter = new MockStackTraceGetter;
+  GetUnitTestImpl()->set_os_stack_trace_getter(mock_os_stack_trace_getter);
+
+  CaptureStdout();
+  Log(kWarning, "Test log.\n", 100);
+  const string log = GetCapturedStdout();
+
+  string expected_trace =
+      (testing::Message() << GTEST_FLAG(stack_trace_depth) << "::").GetString();
+  string expected_message =
+      "\nGMOCK WARNING:\n"
+      "Test log.\n"
+      "Stack trace:\n" +
+      expected_trace;
+  EXPECT_THAT(log, HasSubstr(expected_message));
+  int skip_count = atoi(log.substr(expected_message.size()).c_str());
+
+# if defined(NDEBUG)
+  // In opt mode, no stack frame should be skipped.
+  const int expected_skip_count = 0;
+# else
+  // In dbg mode, the stack frames should be skipped.
+  const int expected_skip_count = 100;
+# endif
+
+  // Note that each inner implementation layer will +1 the number to remove
+  // itself from the trace. This means that the value is a little higher than
+  // expected, but close enough.
+  EXPECT_THAT(skip_count,
+              AllOf(Ge(expected_skip_count), Le(expected_skip_count + 10)));
+
+  // Restores the default OS stack trace getter.
+  GetUnitTestImpl()->set_os_stack_trace_getter(NULL);
+}
+
+// Tests that all logs are printed when the value of the
+// --gmock_verbose flag is "info".
+TEST(LogTest, AllLogsArePrintedWhenVerbosityIsInfo) {
+  TestLogWithSeverity(kInfoVerbosity, kInfo, true);
+  TestLogWithSeverity(kInfoVerbosity, kWarning, true);
+}
+
+// Tests that only warnings are printed when the value of the
+// --gmock_verbose flag is "warning".
+TEST(LogTest, OnlyWarningsArePrintedWhenVerbosityIsWarning) {
+  TestLogWithSeverity(kWarningVerbosity, kInfo, false);
+  TestLogWithSeverity(kWarningVerbosity, kWarning, true);
+}
+
+// Tests that no logs are printed when the value of the
+// --gmock_verbose flag is "error".
+TEST(LogTest, NoLogsArePrintedWhenVerbosityIsError) {
+  TestLogWithSeverity(kErrorVerbosity, kInfo, false);
+  TestLogWithSeverity(kErrorVerbosity, kWarning, false);
+}
+
+// Tests that only warnings are printed when the value of the
+// --gmock_verbose flag is invalid.
+TEST(LogTest, OnlyWarningsArePrintedWhenVerbosityIsInvalid) {
+  TestLogWithSeverity("invalid", kInfo, false);
+  TestLogWithSeverity("invalid", kWarning, true);
+}
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+TEST(TypeTraitsTest, true_type) {
+  EXPECT_TRUE(true_type::value);
+}
+
+TEST(TypeTraitsTest, false_type) {
+  EXPECT_FALSE(false_type::value);
+}
+
+TEST(TypeTraitsTest, is_reference) {
+  EXPECT_FALSE(is_reference<int>::value);
+  EXPECT_FALSE(is_reference<char*>::value);
+  EXPECT_TRUE(is_reference<const int&>::value);
+}
+
+TEST(TypeTraitsTest, is_pointer) {
+  EXPECT_FALSE(is_pointer<int>::value);
+  EXPECT_FALSE(is_pointer<char&>::value);
+  EXPECT_TRUE(is_pointer<const int*>::value);
+}
+
+TEST(TypeTraitsTest, type_equals) {
+  EXPECT_FALSE((type_equals<int, const int>::value));
+  EXPECT_FALSE((type_equals<int, int&>::value));
+  EXPECT_FALSE((type_equals<int, double>::value));
+  EXPECT_TRUE((type_equals<char, char>::value));
+}
+
+TEST(TypeTraitsTest, remove_reference) {
+  EXPECT_TRUE((type_equals<char, remove_reference<char&>::type>::value));
+  EXPECT_TRUE((type_equals<const int,
+               remove_reference<const int&>::type>::value));
+  EXPECT_TRUE((type_equals<int, remove_reference<int>::type>::value));
+  EXPECT_TRUE((type_equals<double*, remove_reference<double*>::type>::value));
+}
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Verifies that Log() behaves correctly for the given verbosity level
+// and log severity.
+std::string GrabOutput(void(*logger)(), const char* verbosity) {
+  const string saved_flag = GMOCK_FLAG(verbose);
+  GMOCK_FLAG(verbose) = verbosity;
+  CaptureStdout();
+  logger();
+  GMOCK_FLAG(verbose) = saved_flag;
+  return GetCapturedStdout();
+}
+
+class DummyMock {
+ public:
+  MOCK_METHOD0(TestMethod, void());
+  MOCK_METHOD1(TestMethodArg, void(int dummy));
+};
+
+void ExpectCallLogger() {
+  DummyMock mock;
+  EXPECT_CALL(mock, TestMethod());
+  mock.TestMethod();
+};
+
+// Verifies that EXPECT_CALL logs if the --gmock_verbose flag is set to "info".
+TEST(ExpectCallTest, LogsWhenVerbosityIsInfo) {
+  EXPECT_THAT(std::string(GrabOutput(ExpectCallLogger, kInfoVerbosity)),
+              HasSubstr("EXPECT_CALL(mock, TestMethod())"));
+}
+
+// Verifies that EXPECT_CALL doesn't log
+// if the --gmock_verbose flag is set to "warning".
+TEST(ExpectCallTest, DoesNotLogWhenVerbosityIsWarning) {
+  EXPECT_STREQ("", GrabOutput(ExpectCallLogger, kWarningVerbosity).c_str());
+}
+
+// Verifies that EXPECT_CALL doesn't log
+// if the --gmock_verbose flag is set to "error".
+TEST(ExpectCallTest,  DoesNotLogWhenVerbosityIsError) {
+  EXPECT_STREQ("", GrabOutput(ExpectCallLogger, kErrorVerbosity).c_str());
+}
+
+void OnCallLogger() {
+  DummyMock mock;
+  ON_CALL(mock, TestMethod());
+};
+
+// Verifies that ON_CALL logs if the --gmock_verbose flag is set to "info".
+TEST(OnCallTest, LogsWhenVerbosityIsInfo) {
+  EXPECT_THAT(std::string(GrabOutput(OnCallLogger, kInfoVerbosity)),
+              HasSubstr("ON_CALL(mock, TestMethod())"));
+}
+
+// Verifies that ON_CALL doesn't log
+// if the --gmock_verbose flag is set to "warning".
+TEST(OnCallTest, DoesNotLogWhenVerbosityIsWarning) {
+  EXPECT_STREQ("", GrabOutput(OnCallLogger, kWarningVerbosity).c_str());
+}
+
+// Verifies that ON_CALL doesn't log if
+// the --gmock_verbose flag is set to "error".
+TEST(OnCallTest, DoesNotLogWhenVerbosityIsError) {
+  EXPECT_STREQ("", GrabOutput(OnCallLogger, kErrorVerbosity).c_str());
+}
+
+void OnCallAnyArgumentLogger() {
+  DummyMock mock;
+  ON_CALL(mock, TestMethodArg(_));
+}
+
+// Verifies that ON_CALL prints provided _ argument.
+TEST(OnCallTest, LogsAnythingArgument) {
+  EXPECT_THAT(std::string(GrabOutput(OnCallAnyArgumentLogger, kInfoVerbosity)),
+              HasSubstr("ON_CALL(mock, TestMethodArg(_)"));
+}
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+// Tests StlContainerView.
+
+TEST(StlContainerViewTest, WorksForStlContainer) {
+  StaticAssertTypeEq<std::vector<int>,
+      StlContainerView<std::vector<int> >::type>();
+  StaticAssertTypeEq<const std::vector<double>&,
+      StlContainerView<std::vector<double> >::const_reference>();
+
+  typedef std::vector<char> Chars;
+  Chars v1;
+  const Chars& v2(StlContainerView<Chars>::ConstReference(v1));
+  EXPECT_EQ(&v1, &v2);
+
+  v1.push_back('a');
+  Chars v3 = StlContainerView<Chars>::Copy(v1);
+  EXPECT_THAT(v3, Eq(v3));
+}
+
+TEST(StlContainerViewTest, WorksForStaticNativeArray) {
+  StaticAssertTypeEq<NativeArray<int>,
+      StlContainerView<int[3]>::type>();
+  StaticAssertTypeEq<NativeArray<double>,
+      StlContainerView<const double[4]>::type>();
+  StaticAssertTypeEq<NativeArray<char[3]>,
+      StlContainerView<const char[2][3]>::type>();
+
+  StaticAssertTypeEq<const NativeArray<int>,
+      StlContainerView<int[2]>::const_reference>();
+
+  int a1[3] = { 0, 1, 2 };
+  NativeArray<int> a2 = StlContainerView<int[3]>::ConstReference(a1);
+  EXPECT_EQ(3U, a2.size());
+  EXPECT_EQ(a1, a2.begin());
+
+  const NativeArray<int> a3 = StlContainerView<int[3]>::Copy(a1);
+  ASSERT_EQ(3U, a3.size());
+  EXPECT_EQ(0, a3.begin()[0]);
+  EXPECT_EQ(1, a3.begin()[1]);
+  EXPECT_EQ(2, a3.begin()[2]);
+
+  // Makes sure a1 and a3 aren't aliases.
+  a1[0] = 3;
+  EXPECT_EQ(0, a3.begin()[0]);
+}
+
+TEST(StlContainerViewTest, WorksForDynamicNativeArray) {
+  StaticAssertTypeEq<NativeArray<int>,
+      StlContainerView<tuple<const int*, size_t> >::type>();
+  StaticAssertTypeEq<NativeArray<double>,
+      StlContainerView<tuple<linked_ptr<double>, int> >::type>();
+
+  StaticAssertTypeEq<const NativeArray<int>,
+      StlContainerView<tuple<const int*, int> >::const_reference>();
+
+  int a1[3] = { 0, 1, 2 };
+  const int* const p1 = a1;
+  NativeArray<int> a2 = StlContainerView<tuple<const int*, int> >::
+      ConstReference(make_tuple(p1, 3));
+  EXPECT_EQ(3U, a2.size());
+  EXPECT_EQ(a1, a2.begin());
+
+  const NativeArray<int> a3 = StlContainerView<tuple<int*, size_t> >::
+      Copy(make_tuple(static_cast<int*>(a1), 3));
+  ASSERT_EQ(3U, a3.size());
+  EXPECT_EQ(0, a3.begin()[0]);
+  EXPECT_EQ(1, a3.begin()[1]);
+  EXPECT_EQ(2, a3.begin()[2]);
+
+  // Makes sure a1 and a3 aren't aliases.
+  a1[0] = 3;
+  EXPECT_EQ(0, a3.begin()[0]);
+}
+
+}  // namespace
+}  // namespace internal
+}  // namespace testing
diff --git a/third_party/googletest/googlemock/test/gmock-matchers_test.cc b/third_party/googletest/googlemock/test/gmock-matchers_test.cc
new file mode 100644
index 0000000..b09acba
--- /dev/null
+++ b/third_party/googletest/googlemock/test/gmock-matchers_test.cc
@@ -0,0 +1,5646 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests some commonly used argument matchers.
+
+#include "gmock/gmock-matchers.h"
+#include "gmock/gmock-more-matchers.h"
+
+#include <string.h>
+#include <time.h>
+#include <deque>
+#include <functional>
+#include <iostream>
+#include <iterator>
+#include <limits>
+#include <list>
+#include <map>
+#include <set>
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "gtest/gtest-spi.h"
+
+#if GTEST_HAS_STD_FORWARD_LIST_
+# include <forward_list>  // NOLINT
+#endif
+
+namespace testing {
+
+namespace internal {
+GTEST_API_ string JoinAsTuple(const Strings& fields);
+}  // namespace internal
+
+namespace gmock_matchers_test {
+
+using std::greater;
+using std::less;
+using std::list;
+using std::make_pair;
+using std::map;
+using std::multimap;
+using std::multiset;
+using std::ostream;
+using std::pair;
+using std::set;
+using std::stringstream;
+using std::vector;
+using testing::A;
+using testing::AllArgs;
+using testing::AllOf;
+using testing::An;
+using testing::AnyOf;
+using testing::ByRef;
+using testing::ContainsRegex;
+using testing::DoubleEq;
+using testing::DoubleNear;
+using testing::EndsWith;
+using testing::Eq;
+using testing::ExplainMatchResult;
+using testing::Field;
+using testing::FloatEq;
+using testing::FloatNear;
+using testing::Ge;
+using testing::Gt;
+using testing::HasSubstr;
+using testing::IsEmpty;
+using testing::IsNull;
+using testing::Key;
+using testing::Le;
+using testing::Lt;
+using testing::MakeMatcher;
+using testing::MakePolymorphicMatcher;
+using testing::MatchResultListener;
+using testing::Matcher;
+using testing::MatcherCast;
+using testing::MatcherInterface;
+using testing::Matches;
+using testing::MatchesRegex;
+using testing::NanSensitiveDoubleEq;
+using testing::NanSensitiveDoubleNear;
+using testing::NanSensitiveFloatEq;
+using testing::NanSensitiveFloatNear;
+using testing::Ne;
+using testing::Not;
+using testing::NotNull;
+using testing::Pair;
+using testing::Pointee;
+using testing::Pointwise;
+using testing::PolymorphicMatcher;
+using testing::Property;
+using testing::Ref;
+using testing::ResultOf;
+using testing::SizeIs;
+using testing::StartsWith;
+using testing::StrCaseEq;
+using testing::StrCaseNe;
+using testing::StrEq;
+using testing::StrNe;
+using testing::StringMatchResultListener;
+using testing::Truly;
+using testing::TypedEq;
+using testing::UnorderedPointwise;
+using testing::Value;
+using testing::WhenSorted;
+using testing::WhenSortedBy;
+using testing::_;
+using testing::get;
+using testing::internal::DummyMatchResultListener;
+using testing::internal::ElementMatcherPair;
+using testing::internal::ElementMatcherPairs;
+using testing::internal::ExplainMatchFailureTupleTo;
+using testing::internal::FloatingEqMatcher;
+using testing::internal::FormatMatcherDescription;
+using testing::internal::IsReadableTypeName;
+using testing::internal::JoinAsTuple;
+using testing::internal::linked_ptr;
+using testing::internal::MatchMatrix;
+using testing::internal::RE;
+using testing::internal::scoped_ptr;
+using testing::internal::StreamMatchResultListener;
+using testing::internal::Strings;
+using testing::internal::linked_ptr;
+using testing::internal::scoped_ptr;
+using testing::internal::string;
+using testing::make_tuple;
+using testing::tuple;
+
+// For testing ExplainMatchResultTo().
+class GreaterThanMatcher : public MatcherInterface<int> {
+ public:
+  explicit GreaterThanMatcher(int rhs) : rhs_(rhs) {}
+
+  virtual void DescribeTo(ostream* os) const {
+    *os << "is > " << rhs_;
+  }
+
+  virtual bool MatchAndExplain(int lhs,
+                               MatchResultListener* listener) const {
+    const int diff = lhs - rhs_;
+    if (diff > 0) {
+      *listener << "which is " << diff << " more than " << rhs_;
+    } else if (diff == 0) {
+      *listener << "which is the same as " << rhs_;
+    } else {
+      *listener << "which is " << -diff << " less than " << rhs_;
+    }
+
+    return lhs > rhs_;
+  }
+
+ private:
+  int rhs_;
+};
+
+Matcher<int> GreaterThan(int n) {
+  return MakeMatcher(new GreaterThanMatcher(n));
+}
+
+string OfType(const string& type_name) {
+#if GTEST_HAS_RTTI
+  return " (of type " + type_name + ")";
+#else
+  return "";
+#endif
+}
+
+// Returns the description of the given matcher.
+template <typename T>
+string Describe(const Matcher<T>& m) {
+  stringstream ss;
+  m.DescribeTo(&ss);
+  return ss.str();
+}
+
+// Returns the description of the negation of the given matcher.
+template <typename T>
+string DescribeNegation(const Matcher<T>& m) {
+  stringstream ss;
+  m.DescribeNegationTo(&ss);
+  return ss.str();
+}
+
+// Returns the reason why x matches, or doesn't match, m.
+template <typename MatcherType, typename Value>
+string Explain(const MatcherType& m, const Value& x) {
+  StringMatchResultListener listener;
+  ExplainMatchResult(m, x, &listener);
+  return listener.str();
+}
+
+TEST(MatchResultListenerTest, StreamingWorks) {
+  StringMatchResultListener listener;
+  listener << "hi" << 5;
+  EXPECT_EQ("hi5", listener.str());
+
+  listener.Clear();
+  EXPECT_EQ("", listener.str());
+
+  listener << 42;
+  EXPECT_EQ("42", listener.str());
+
+  // Streaming shouldn't crash when the underlying ostream is NULL.
+  DummyMatchResultListener dummy;
+  dummy << "hi" << 5;
+}
+
+TEST(MatchResultListenerTest, CanAccessUnderlyingStream) {
+  EXPECT_TRUE(DummyMatchResultListener().stream() == NULL);
+  EXPECT_TRUE(StreamMatchResultListener(NULL).stream() == NULL);
+
+  EXPECT_EQ(&std::cout, StreamMatchResultListener(&std::cout).stream());
+}
+
+TEST(MatchResultListenerTest, IsInterestedWorks) {
+  EXPECT_TRUE(StringMatchResultListener().IsInterested());
+  EXPECT_TRUE(StreamMatchResultListener(&std::cout).IsInterested());
+
+  EXPECT_FALSE(DummyMatchResultListener().IsInterested());
+  EXPECT_FALSE(StreamMatchResultListener(NULL).IsInterested());
+}
+
+// Makes sure that the MatcherInterface<T> interface doesn't
+// change.
+class EvenMatcherImpl : public MatcherInterface<int> {
+ public:
+  virtual bool MatchAndExplain(int x,
+                               MatchResultListener* /* listener */) const {
+    return x % 2 == 0;
+  }
+
+  virtual void DescribeTo(ostream* os) const {
+    *os << "is an even number";
+  }
+
+  // We deliberately don't define DescribeNegationTo() and
+  // ExplainMatchResultTo() here, to make sure the definition of these
+  // two methods is optional.
+};
+
+// Makes sure that the MatcherInterface API doesn't change.
+TEST(MatcherInterfaceTest, CanBeImplementedUsingPublishedAPI) {
+  EvenMatcherImpl m;
+}
+
+// Tests implementing a monomorphic matcher using MatchAndExplain().
+
+class NewEvenMatcherImpl : public MatcherInterface<int> {
+ public:
+  virtual bool MatchAndExplain(int x, MatchResultListener* listener) const {
+    const bool match = x % 2 == 0;
+    // Verifies that we can stream to a listener directly.
+    *listener << "value % " << 2;
+    if (listener->stream() != NULL) {
+      // Verifies that we can stream to a listener's underlying stream
+      // too.
+      *listener->stream() << " == " << (x % 2);
+    }
+    return match;
+  }
+
+  virtual void DescribeTo(ostream* os) const {
+    *os << "is an even number";
+  }
+};
+
+TEST(MatcherInterfaceTest, CanBeImplementedUsingNewAPI) {
+  Matcher<int> m = MakeMatcher(new NewEvenMatcherImpl);
+  EXPECT_TRUE(m.Matches(2));
+  EXPECT_FALSE(m.Matches(3));
+  EXPECT_EQ("value % 2 == 0", Explain(m, 2));
+  EXPECT_EQ("value % 2 == 1", Explain(m, 3));
+}
+
+// Tests default-constructing a matcher.
+TEST(MatcherTest, CanBeDefaultConstructed) {
+  Matcher<double> m;
+}
+
+// Tests that Matcher<T> can be constructed from a MatcherInterface<T>*.
+TEST(MatcherTest, CanBeConstructedFromMatcherInterface) {
+  const MatcherInterface<int>* impl = new EvenMatcherImpl;
+  Matcher<int> m(impl);
+  EXPECT_TRUE(m.Matches(4));
+  EXPECT_FALSE(m.Matches(5));
+}
+
+// Tests that value can be used in place of Eq(value).
+TEST(MatcherTest, CanBeImplicitlyConstructedFromValue) {
+  Matcher<int> m1 = 5;
+  EXPECT_TRUE(m1.Matches(5));
+  EXPECT_FALSE(m1.Matches(6));
+}
+
+// Tests that NULL can be used in place of Eq(NULL).
+TEST(MatcherTest, CanBeImplicitlyConstructedFromNULL) {
+  Matcher<int*> m1 = NULL;
+  EXPECT_TRUE(m1.Matches(NULL));
+  int n = 0;
+  EXPECT_FALSE(m1.Matches(&n));
+}
+
+// Tests that matchers are copyable.
+TEST(MatcherTest, IsCopyable) {
+  // Tests the copy constructor.
+  Matcher<bool> m1 = Eq(false);
+  EXPECT_TRUE(m1.Matches(false));
+  EXPECT_FALSE(m1.Matches(true));
+
+  // Tests the assignment operator.
+  m1 = Eq(true);
+  EXPECT_TRUE(m1.Matches(true));
+  EXPECT_FALSE(m1.Matches(false));
+}
+
+// Tests that Matcher<T>::DescribeTo() calls
+// MatcherInterface<T>::DescribeTo().
+TEST(MatcherTest, CanDescribeItself) {
+  EXPECT_EQ("is an even number",
+            Describe(Matcher<int>(new EvenMatcherImpl)));
+}
+
+// Tests Matcher<T>::MatchAndExplain().
+TEST(MatcherTest, MatchAndExplain) {
+  Matcher<int> m = GreaterThan(0);
+  StringMatchResultListener listener1;
+  EXPECT_TRUE(m.MatchAndExplain(42, &listener1));
+  EXPECT_EQ("which is 42 more than 0", listener1.str());
+
+  StringMatchResultListener listener2;
+  EXPECT_FALSE(m.MatchAndExplain(-9, &listener2));
+  EXPECT_EQ("which is 9 less than 0", listener2.str());
+}
+
+// Tests that a C-string literal can be implicitly converted to a
+// Matcher<string> or Matcher<const string&>.
+TEST(StringMatcherTest, CanBeImplicitlyConstructedFromCStringLiteral) {
+  Matcher<string> m1 = "hi";
+  EXPECT_TRUE(m1.Matches("hi"));
+  EXPECT_FALSE(m1.Matches("hello"));
+
+  Matcher<const string&> m2 = "hi";
+  EXPECT_TRUE(m2.Matches("hi"));
+  EXPECT_FALSE(m2.Matches("hello"));
+}
+
+// Tests that a string object can be implicitly converted to a
+// Matcher<string> or Matcher<const string&>.
+TEST(StringMatcherTest, CanBeImplicitlyConstructedFromString) {
+  Matcher<string> m1 = string("hi");
+  EXPECT_TRUE(m1.Matches("hi"));
+  EXPECT_FALSE(m1.Matches("hello"));
+
+  Matcher<const string&> m2 = string("hi");
+  EXPECT_TRUE(m2.Matches("hi"));
+  EXPECT_FALSE(m2.Matches("hello"));
+}
+
+#if GTEST_HAS_STRING_PIECE_
+// Tests that a C-string literal can be implicitly converted to a
+// Matcher<StringPiece> or Matcher<const StringPiece&>.
+TEST(StringPieceMatcherTest, CanBeImplicitlyConstructedFromCStringLiteral) {
+  Matcher<StringPiece> m1 = "cats";
+  EXPECT_TRUE(m1.Matches("cats"));
+  EXPECT_FALSE(m1.Matches("dogs"));
+
+  Matcher<const StringPiece&> m2 = "cats";
+  EXPECT_TRUE(m2.Matches("cats"));
+  EXPECT_FALSE(m2.Matches("dogs"));
+}
+
+// Tests that a string object can be implicitly converted to a
+// Matcher<StringPiece> or Matcher<const StringPiece&>.
+TEST(StringPieceMatcherTest, CanBeImplicitlyConstructedFromString) {
+  Matcher<StringPiece> m1 = string("cats");
+  EXPECT_TRUE(m1.Matches("cats"));
+  EXPECT_FALSE(m1.Matches("dogs"));
+
+  Matcher<const StringPiece&> m2 = string("cats");
+  EXPECT_TRUE(m2.Matches("cats"));
+  EXPECT_FALSE(m2.Matches("dogs"));
+}
+
+// Tests that a StringPiece object can be implicitly converted to a
+// Matcher<StringPiece> or Matcher<const StringPiece&>.
+TEST(StringPieceMatcherTest, CanBeImplicitlyConstructedFromStringPiece) {
+  Matcher<StringPiece> m1 = StringPiece("cats");
+  EXPECT_TRUE(m1.Matches("cats"));
+  EXPECT_FALSE(m1.Matches("dogs"));
+
+  Matcher<const StringPiece&> m2 = StringPiece("cats");
+  EXPECT_TRUE(m2.Matches("cats"));
+  EXPECT_FALSE(m2.Matches("dogs"));
+}
+#endif  // GTEST_HAS_STRING_PIECE_
+
+// Tests that MakeMatcher() constructs a Matcher<T> from a
+// MatcherInterface* without requiring the user to explicitly
+// write the type.
+TEST(MakeMatcherTest, ConstructsMatcherFromMatcherInterface) {
+  const MatcherInterface<int>* dummy_impl = NULL;
+  Matcher<int> m = MakeMatcher(dummy_impl);
+}
+
+// Tests that MakePolymorphicMatcher() can construct a polymorphic
+// matcher from its implementation using the old API.
+const int g_bar = 1;
+class ReferencesBarOrIsZeroImpl {
+ public:
+  template <typename T>
+  bool MatchAndExplain(const T& x,
+                       MatchResultListener* /* listener */) const {
+    const void* p = &x;
+    return p == &g_bar || x == 0;
+  }
+
+  void DescribeTo(ostream* os) const { *os << "g_bar or zero"; }
+
+  void DescribeNegationTo(ostream* os) const {
+    *os << "doesn't reference g_bar and is not zero";
+  }
+};
+
+// This function verifies that MakePolymorphicMatcher() returns a
+// PolymorphicMatcher<T> where T is the argument's type.
+PolymorphicMatcher<ReferencesBarOrIsZeroImpl> ReferencesBarOrIsZero() {
+  return MakePolymorphicMatcher(ReferencesBarOrIsZeroImpl());
+}
+
+TEST(MakePolymorphicMatcherTest, ConstructsMatcherUsingOldAPI) {
+  // Using a polymorphic matcher to match a reference type.
+  Matcher<const int&> m1 = ReferencesBarOrIsZero();
+  EXPECT_TRUE(m1.Matches(0));
+  // Verifies that the identity of a by-reference argument is preserved.
+  EXPECT_TRUE(m1.Matches(g_bar));
+  EXPECT_FALSE(m1.Matches(1));
+  EXPECT_EQ("g_bar or zero", Describe(m1));
+
+  // Using a polymorphic matcher to match a value type.
+  Matcher<double> m2 = ReferencesBarOrIsZero();
+  EXPECT_TRUE(m2.Matches(0.0));
+  EXPECT_FALSE(m2.Matches(0.1));
+  EXPECT_EQ("g_bar or zero", Describe(m2));
+}
+
+// Tests implementing a polymorphic matcher using MatchAndExplain().
+
+class PolymorphicIsEvenImpl {
+ public:
+  void DescribeTo(ostream* os) const { *os << "is even"; }
+
+  void DescribeNegationTo(ostream* os) const {
+    *os << "is odd";
+  }
+
+  template <typename T>
+  bool MatchAndExplain(const T& x, MatchResultListener* listener) const {
+    // Verifies that we can stream to the listener directly.
+    *listener << "% " << 2;
+    if (listener->stream() != NULL) {
+      // Verifies that we can stream to the listener's underlying stream
+      // too.
+      *listener->stream() << " == " << (x % 2);
+    }
+    return (x % 2) == 0;
+  }
+};
+
+PolymorphicMatcher<PolymorphicIsEvenImpl> PolymorphicIsEven() {
+  return MakePolymorphicMatcher(PolymorphicIsEvenImpl());
+}
+
+TEST(MakePolymorphicMatcherTest, ConstructsMatcherUsingNewAPI) {
+  // Using PolymorphicIsEven() as a Matcher<int>.
+  const Matcher<int> m1 = PolymorphicIsEven();
+  EXPECT_TRUE(m1.Matches(42));
+  EXPECT_FALSE(m1.Matches(43));
+  EXPECT_EQ("is even", Describe(m1));
+
+  const Matcher<int> not_m1 = Not(m1);
+  EXPECT_EQ("is odd", Describe(not_m1));
+
+  EXPECT_EQ("% 2 == 0", Explain(m1, 42));
+
+  // Using PolymorphicIsEven() as a Matcher<char>.
+  const Matcher<char> m2 = PolymorphicIsEven();
+  EXPECT_TRUE(m2.Matches('\x42'));
+  EXPECT_FALSE(m2.Matches('\x43'));
+  EXPECT_EQ("is even", Describe(m2));
+
+  const Matcher<char> not_m2 = Not(m2);
+  EXPECT_EQ("is odd", Describe(not_m2));
+
+  EXPECT_EQ("% 2 == 0", Explain(m2, '\x42'));
+}
+
+// Tests that MatcherCast<T>(m) works when m is a polymorphic matcher.
+TEST(MatcherCastTest, FromPolymorphicMatcher) {
+  Matcher<int> m = MatcherCast<int>(Eq(5));
+  EXPECT_TRUE(m.Matches(5));
+  EXPECT_FALSE(m.Matches(6));
+}
+
+// For testing casting matchers between compatible types.
+class IntValue {
+ public:
+  // An int can be statically (although not implicitly) cast to a
+  // IntValue.
+  explicit IntValue(int a_value) : value_(a_value) {}
+
+  int value() const { return value_; }
+ private:
+  int value_;
+};
+
+// For testing casting matchers between compatible types.
+bool IsPositiveIntValue(const IntValue& foo) {
+  return foo.value() > 0;
+}
+
+// Tests that MatcherCast<T>(m) works when m is a Matcher<U> where T
+// can be statically converted to U.
+TEST(MatcherCastTest, FromCompatibleType) {
+  Matcher<double> m1 = Eq(2.0);
+  Matcher<int> m2 = MatcherCast<int>(m1);
+  EXPECT_TRUE(m2.Matches(2));
+  EXPECT_FALSE(m2.Matches(3));
+
+  Matcher<IntValue> m3 = Truly(IsPositiveIntValue);
+  Matcher<int> m4 = MatcherCast<int>(m3);
+  // In the following, the arguments 1 and 0 are statically converted
+  // to IntValue objects, and then tested by the IsPositiveIntValue()
+  // predicate.
+  EXPECT_TRUE(m4.Matches(1));
+  EXPECT_FALSE(m4.Matches(0));
+}
+
+// Tests that MatcherCast<T>(m) works when m is a Matcher<const T&>.
+TEST(MatcherCastTest, FromConstReferenceToNonReference) {
+  Matcher<const int&> m1 = Eq(0);
+  Matcher<int> m2 = MatcherCast<int>(m1);
+  EXPECT_TRUE(m2.Matches(0));
+  EXPECT_FALSE(m2.Matches(1));
+}
+
+// Tests that MatcherCast<T>(m) works when m is a Matcher<T&>.
+TEST(MatcherCastTest, FromReferenceToNonReference) {
+  Matcher<int&> m1 = Eq(0);
+  Matcher<int> m2 = MatcherCast<int>(m1);
+  EXPECT_TRUE(m2.Matches(0));
+  EXPECT_FALSE(m2.Matches(1));
+}
+
+// Tests that MatcherCast<const T&>(m) works when m is a Matcher<T>.
+TEST(MatcherCastTest, FromNonReferenceToConstReference) {
+  Matcher<int> m1 = Eq(0);
+  Matcher<const int&> m2 = MatcherCast<const int&>(m1);
+  EXPECT_TRUE(m2.Matches(0));
+  EXPECT_FALSE(m2.Matches(1));
+}
+
+// Tests that MatcherCast<T&>(m) works when m is a Matcher<T>.
+TEST(MatcherCastTest, FromNonReferenceToReference) {
+  Matcher<int> m1 = Eq(0);
+  Matcher<int&> m2 = MatcherCast<int&>(m1);
+  int n = 0;
+  EXPECT_TRUE(m2.Matches(n));
+  n = 1;
+  EXPECT_FALSE(m2.Matches(n));
+}
+
+// Tests that MatcherCast<T>(m) works when m is a Matcher<T>.
+TEST(MatcherCastTest, FromSameType) {
+  Matcher<int> m1 = Eq(0);
+  Matcher<int> m2 = MatcherCast<int>(m1);
+  EXPECT_TRUE(m2.Matches(0));
+  EXPECT_FALSE(m2.Matches(1));
+}
+
+// Implicitly convertible from any type.
+struct ConvertibleFromAny {
+  ConvertibleFromAny(int a_value) : value(a_value) {}
+  template <typename T>
+  ConvertibleFromAny(const T& /*a_value*/) : value(-1) {
+    ADD_FAILURE() << "Conversion constructor called";
+  }
+  int value;
+};
+
+bool operator==(const ConvertibleFromAny& a, const ConvertibleFromAny& b) {
+  return a.value == b.value;
+}
+
+ostream& operator<<(ostream& os, const ConvertibleFromAny& a) {
+  return os << a.value;
+}
+
+TEST(MatcherCastTest, ConversionConstructorIsUsed) {
+  Matcher<ConvertibleFromAny> m = MatcherCast<ConvertibleFromAny>(1);
+  EXPECT_TRUE(m.Matches(ConvertibleFromAny(1)));
+  EXPECT_FALSE(m.Matches(ConvertibleFromAny(2)));
+}
+
+TEST(MatcherCastTest, FromConvertibleFromAny) {
+  Matcher<ConvertibleFromAny> m =
+      MatcherCast<ConvertibleFromAny>(Eq(ConvertibleFromAny(1)));
+  EXPECT_TRUE(m.Matches(ConvertibleFromAny(1)));
+  EXPECT_FALSE(m.Matches(ConvertibleFromAny(2)));
+}
+
+struct IntReferenceWrapper {
+  IntReferenceWrapper(const int& a_value) : value(&a_value) {}
+  const int* value;
+};
+
+bool operator==(const IntReferenceWrapper& a, const IntReferenceWrapper& b) {
+  return a.value == b.value;
+}
+
+TEST(MatcherCastTest, ValueIsNotCopied) {
+  int n = 42;
+  Matcher<IntReferenceWrapper> m = MatcherCast<IntReferenceWrapper>(n);
+  // Verify that the matcher holds a reference to n, not to its temporary copy.
+  EXPECT_TRUE(m.Matches(n));
+}
+
+class Base {
+ public:
+  virtual ~Base() {}
+  Base() {}
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Base);
+};
+
+class Derived : public Base {
+ public:
+  Derived() : Base() {}
+  int i;
+};
+
+class OtherDerived : public Base {};
+
+// Tests that SafeMatcherCast<T>(m) works when m is a polymorphic matcher.
+TEST(SafeMatcherCastTest, FromPolymorphicMatcher) {
+  Matcher<char> m2 = SafeMatcherCast<char>(Eq(32));
+  EXPECT_TRUE(m2.Matches(' '));
+  EXPECT_FALSE(m2.Matches('\n'));
+}
+
+// Tests that SafeMatcherCast<T>(m) works when m is a Matcher<U> where
+// T and U are arithmetic types and T can be losslessly converted to
+// U.
+TEST(SafeMatcherCastTest, FromLosslesslyConvertibleArithmeticType) {
+  Matcher<double> m1 = DoubleEq(1.0);
+  Matcher<float> m2 = SafeMatcherCast<float>(m1);
+  EXPECT_TRUE(m2.Matches(1.0f));
+  EXPECT_FALSE(m2.Matches(2.0f));
+
+  Matcher<char> m3 = SafeMatcherCast<char>(TypedEq<int>('a'));
+  EXPECT_TRUE(m3.Matches('a'));
+  EXPECT_FALSE(m3.Matches('b'));
+}
+
+// Tests that SafeMatcherCast<T>(m) works when m is a Matcher<U> where T and U
+// are pointers or references to a derived and a base class, correspondingly.
+TEST(SafeMatcherCastTest, FromBaseClass) {
+  Derived d, d2;
+  Matcher<Base*> m1 = Eq(&d);
+  Matcher<Derived*> m2 = SafeMatcherCast<Derived*>(m1);
+  EXPECT_TRUE(m2.Matches(&d));
+  EXPECT_FALSE(m2.Matches(&d2));
+
+  Matcher<Base&> m3 = Ref(d);
+  Matcher<Derived&> m4 = SafeMatcherCast<Derived&>(m3);
+  EXPECT_TRUE(m4.Matches(d));
+  EXPECT_FALSE(m4.Matches(d2));
+}
+
+// Tests that SafeMatcherCast<T&>(m) works when m is a Matcher<const T&>.
+TEST(SafeMatcherCastTest, FromConstReferenceToReference) {
+  int n = 0;
+  Matcher<const int&> m1 = Ref(n);
+  Matcher<int&> m2 = SafeMatcherCast<int&>(m1);
+  int n1 = 0;
+  EXPECT_TRUE(m2.Matches(n));
+  EXPECT_FALSE(m2.Matches(n1));
+}
+
+// Tests that MatcherCast<const T&>(m) works when m is a Matcher<T>.
+TEST(SafeMatcherCastTest, FromNonReferenceToConstReference) {
+  Matcher<int> m1 = Eq(0);
+  Matcher<const int&> m2 = SafeMatcherCast<const int&>(m1);
+  EXPECT_TRUE(m2.Matches(0));
+  EXPECT_FALSE(m2.Matches(1));
+}
+
+// Tests that SafeMatcherCast<T&>(m) works when m is a Matcher<T>.
+TEST(SafeMatcherCastTest, FromNonReferenceToReference) {
+  Matcher<int> m1 = Eq(0);
+  Matcher<int&> m2 = SafeMatcherCast<int&>(m1);
+  int n = 0;
+  EXPECT_TRUE(m2.Matches(n));
+  n = 1;
+  EXPECT_FALSE(m2.Matches(n));
+}
+
+// Tests that SafeMatcherCast<T>(m) works when m is a Matcher<T>.
+TEST(SafeMatcherCastTest, FromSameType) {
+  Matcher<int> m1 = Eq(0);
+  Matcher<int> m2 = SafeMatcherCast<int>(m1);
+  EXPECT_TRUE(m2.Matches(0));
+  EXPECT_FALSE(m2.Matches(1));
+}
+
+TEST(SafeMatcherCastTest, ConversionConstructorIsUsed) {
+  Matcher<ConvertibleFromAny> m = SafeMatcherCast<ConvertibleFromAny>(1);
+  EXPECT_TRUE(m.Matches(ConvertibleFromAny(1)));
+  EXPECT_FALSE(m.Matches(ConvertibleFromAny(2)));
+}
+
+TEST(SafeMatcherCastTest, FromConvertibleFromAny) {
+  Matcher<ConvertibleFromAny> m =
+      SafeMatcherCast<ConvertibleFromAny>(Eq(ConvertibleFromAny(1)));
+  EXPECT_TRUE(m.Matches(ConvertibleFromAny(1)));
+  EXPECT_FALSE(m.Matches(ConvertibleFromAny(2)));
+}
+
+TEST(SafeMatcherCastTest, ValueIsNotCopied) {
+  int n = 42;
+  Matcher<IntReferenceWrapper> m = SafeMatcherCast<IntReferenceWrapper>(n);
+  // Verify that the matcher holds a reference to n, not to its temporary copy.
+  EXPECT_TRUE(m.Matches(n));
+}
+
+TEST(ExpectThat, TakesLiterals) {
+  EXPECT_THAT(1, 1);
+  EXPECT_THAT(1.0, 1.0);
+  EXPECT_THAT(string(), "");
+}
+
+TEST(ExpectThat, TakesFunctions) {
+  struct Helper {
+    static void Func() {}
+  };
+  void (*func)() = Helper::Func;
+  EXPECT_THAT(func, Helper::Func);
+  EXPECT_THAT(func, &Helper::Func);
+}
+
+// Tests that A<T>() matches any value of type T.
+TEST(ATest, MatchesAnyValue) {
+  // Tests a matcher for a value type.
+  Matcher<double> m1 = A<double>();
+  EXPECT_TRUE(m1.Matches(91.43));
+  EXPECT_TRUE(m1.Matches(-15.32));
+
+  // Tests a matcher for a reference type.
+  int a = 2;
+  int b = -6;
+  Matcher<int&> m2 = A<int&>();
+  EXPECT_TRUE(m2.Matches(a));
+  EXPECT_TRUE(m2.Matches(b));
+}
+
+TEST(ATest, WorksForDerivedClass) {
+  Base base;
+  Derived derived;
+  EXPECT_THAT(&base, A<Base*>());
+  // This shouldn't compile: EXPECT_THAT(&base, A<Derived*>());
+  EXPECT_THAT(&derived, A<Base*>());
+  EXPECT_THAT(&derived, A<Derived*>());
+}
+
+// Tests that A<T>() describes itself properly.
+TEST(ATest, CanDescribeSelf) {
+  EXPECT_EQ("is anything", Describe(A<bool>()));
+}
+
+// Tests that An<T>() matches any value of type T.
+TEST(AnTest, MatchesAnyValue) {
+  // Tests a matcher for a value type.
+  Matcher<int> m1 = An<int>();
+  EXPECT_TRUE(m1.Matches(9143));
+  EXPECT_TRUE(m1.Matches(-1532));
+
+  // Tests a matcher for a reference type.
+  int a = 2;
+  int b = -6;
+  Matcher<int&> m2 = An<int&>();
+  EXPECT_TRUE(m2.Matches(a));
+  EXPECT_TRUE(m2.Matches(b));
+}
+
+// Tests that An<T>() describes itself properly.
+TEST(AnTest, CanDescribeSelf) {
+  EXPECT_EQ("is anything", Describe(An<int>()));
+}
+
+// Tests that _ can be used as a matcher for any type and matches any
+// value of that type.
+TEST(UnderscoreTest, MatchesAnyValue) {
+  // Uses _ as a matcher for a value type.
+  Matcher<int> m1 = _;
+  EXPECT_TRUE(m1.Matches(123));
+  EXPECT_TRUE(m1.Matches(-242));
+
+  // Uses _ as a matcher for a reference type.
+  bool a = false;
+  const bool b = true;
+  Matcher<const bool&> m2 = _;
+  EXPECT_TRUE(m2.Matches(a));
+  EXPECT_TRUE(m2.Matches(b));
+}
+
+// Tests that _ describes itself properly.
+TEST(UnderscoreTest, CanDescribeSelf) {
+  Matcher<int> m = _;
+  EXPECT_EQ("is anything", Describe(m));
+}
+
+// Tests that Eq(x) matches any value equal to x.
+TEST(EqTest, MatchesEqualValue) {
+  // 2 C-strings with same content but different addresses.
+  const char a1[] = "hi";
+  const char a2[] = "hi";
+
+  Matcher<const char*> m1 = Eq(a1);
+  EXPECT_TRUE(m1.Matches(a1));
+  EXPECT_FALSE(m1.Matches(a2));
+}
+
+// Tests that Eq(v) describes itself properly.
+
+class Unprintable {
+ public:
+  Unprintable() : c_('a') {}
+
+  bool operator==(const Unprintable& /* rhs */) { return true; }
+ private:
+  char c_;
+};
+
+TEST(EqTest, CanDescribeSelf) {
+  Matcher<Unprintable> m = Eq(Unprintable());
+  EXPECT_EQ("is equal to 1-byte object <61>", Describe(m));
+}
+
+// Tests that Eq(v) can be used to match any type that supports
+// comparing with type T, where T is v's type.
+TEST(EqTest, IsPolymorphic) {
+  Matcher<int> m1 = Eq(1);
+  EXPECT_TRUE(m1.Matches(1));
+  EXPECT_FALSE(m1.Matches(2));
+
+  Matcher<char> m2 = Eq(1);
+  EXPECT_TRUE(m2.Matches('\1'));
+  EXPECT_FALSE(m2.Matches('a'));
+}
+
+// Tests that TypedEq<T>(v) matches values of type T that's equal to v.
+TEST(TypedEqTest, ChecksEqualityForGivenType) {
+  Matcher<char> m1 = TypedEq<char>('a');
+  EXPECT_TRUE(m1.Matches('a'));
+  EXPECT_FALSE(m1.Matches('b'));
+
+  Matcher<int> m2 = TypedEq<int>(6);
+  EXPECT_TRUE(m2.Matches(6));
+  EXPECT_FALSE(m2.Matches(7));
+}
+
+// Tests that TypedEq(v) describes itself properly.
+TEST(TypedEqTest, CanDescribeSelf) {
+  EXPECT_EQ("is equal to 2", Describe(TypedEq<int>(2)));
+}
+
+// Tests that TypedEq<T>(v) has type Matcher<T>.
+
+// Type<T>::IsTypeOf(v) compiles iff the type of value v is T, where T
+// is a "bare" type (i.e. not in the form of const U or U&).  If v's
+// type is not T, the compiler will generate a message about
+// "undefined referece".
+template <typename T>
+struct Type {
+  static bool IsTypeOf(const T& /* v */) { return true; }
+
+  template <typename T2>
+  static void IsTypeOf(T2 v);
+};
+
+TEST(TypedEqTest, HasSpecifiedType) {
+  // Verfies that the type of TypedEq<T>(v) is Matcher<T>.
+  Type<Matcher<int> >::IsTypeOf(TypedEq<int>(5));
+  Type<Matcher<double> >::IsTypeOf(TypedEq<double>(5));
+}
+
+// Tests that Ge(v) matches anything >= v.
+TEST(GeTest, ImplementsGreaterThanOrEqual) {
+  Matcher<int> m1 = Ge(0);
+  EXPECT_TRUE(m1.Matches(1));
+  EXPECT_TRUE(m1.Matches(0));
+  EXPECT_FALSE(m1.Matches(-1));
+}
+
+// Tests that Ge(v) describes itself properly.
+TEST(GeTest, CanDescribeSelf) {
+  Matcher<int> m = Ge(5);
+  EXPECT_EQ("is >= 5", Describe(m));
+}
+
+// Tests that Gt(v) matches anything > v.
+TEST(GtTest, ImplementsGreaterThan) {
+  Matcher<double> m1 = Gt(0);
+  EXPECT_TRUE(m1.Matches(1.0));
+  EXPECT_FALSE(m1.Matches(0.0));
+  EXPECT_FALSE(m1.Matches(-1.0));
+}
+
+// Tests that Gt(v) describes itself properly.
+TEST(GtTest, CanDescribeSelf) {
+  Matcher<int> m = Gt(5);
+  EXPECT_EQ("is > 5", Describe(m));
+}
+
+// Tests that Le(v) matches anything <= v.
+TEST(LeTest, ImplementsLessThanOrEqual) {
+  Matcher<char> m1 = Le('b');
+  EXPECT_TRUE(m1.Matches('a'));
+  EXPECT_TRUE(m1.Matches('b'));
+  EXPECT_FALSE(m1.Matches('c'));
+}
+
+// Tests that Le(v) describes itself properly.
+TEST(LeTest, CanDescribeSelf) {
+  Matcher<int> m = Le(5);
+  EXPECT_EQ("is <= 5", Describe(m));
+}
+
+// Tests that Lt(v) matches anything < v.
+TEST(LtTest, ImplementsLessThan) {
+  Matcher<const string&> m1 = Lt("Hello");
+  EXPECT_TRUE(m1.Matches("Abc"));
+  EXPECT_FALSE(m1.Matches("Hello"));
+  EXPECT_FALSE(m1.Matches("Hello, world!"));
+}
+
+// Tests that Lt(v) describes itself properly.
+TEST(LtTest, CanDescribeSelf) {
+  Matcher<int> m = Lt(5);
+  EXPECT_EQ("is < 5", Describe(m));
+}
+
+// Tests that Ne(v) matches anything != v.
+TEST(NeTest, ImplementsNotEqual) {
+  Matcher<int> m1 = Ne(0);
+  EXPECT_TRUE(m1.Matches(1));
+  EXPECT_TRUE(m1.Matches(-1));
+  EXPECT_FALSE(m1.Matches(0));
+}
+
+// Tests that Ne(v) describes itself properly.
+TEST(NeTest, CanDescribeSelf) {
+  Matcher<int> m = Ne(5);
+  EXPECT_EQ("isn't equal to 5", Describe(m));
+}
+
+// Tests that IsNull() matches any NULL pointer of any type.
+TEST(IsNullTest, MatchesNullPointer) {
+  Matcher<int*> m1 = IsNull();
+  int* p1 = NULL;
+  int n = 0;
+  EXPECT_TRUE(m1.Matches(p1));
+  EXPECT_FALSE(m1.Matches(&n));
+
+  Matcher<const char*> m2 = IsNull();
+  const char* p2 = NULL;
+  EXPECT_TRUE(m2.Matches(p2));
+  EXPECT_FALSE(m2.Matches("hi"));
+
+#if !GTEST_OS_SYMBIAN
+  // Nokia's Symbian compiler generates:
+  // gmock-matchers.h: ambiguous access to overloaded function
+  // gmock-matchers.h: 'testing::Matcher<void *>::Matcher(void *)'
+  // gmock-matchers.h: 'testing::Matcher<void *>::Matcher(const testing::
+  //     MatcherInterface<void *> *)'
+  // gmock-matchers.h:  (point of instantiation: 'testing::
+  //     gmock_matchers_test::IsNullTest_MatchesNullPointer_Test::TestBody()')
+  // gmock-matchers.h:   (instantiating: 'testing::PolymorphicMatc
+  Matcher<void*> m3 = IsNull();
+  void* p3 = NULL;
+  EXPECT_TRUE(m3.Matches(p3));
+  EXPECT_FALSE(m3.Matches(reinterpret_cast<void*>(0xbeef)));
+#endif
+}
+
+TEST(IsNullTest, LinkedPtr) {
+  const Matcher<linked_ptr<int> > m = IsNull();
+  const linked_ptr<int> null_p;
+  const linked_ptr<int> non_null_p(new int);
+
+  EXPECT_TRUE(m.Matches(null_p));
+  EXPECT_FALSE(m.Matches(non_null_p));
+}
+
+TEST(IsNullTest, ReferenceToConstLinkedPtr) {
+  const Matcher<const linked_ptr<double>&> m = IsNull();
+  const linked_ptr<double> null_p;
+  const linked_ptr<double> non_null_p(new double);
+
+  EXPECT_TRUE(m.Matches(null_p));
+  EXPECT_FALSE(m.Matches(non_null_p));
+}
+
+#if GTEST_LANG_CXX11
+TEST(IsNullTest, StdFunction) {
+  const Matcher<std::function<void()>> m = IsNull();
+
+  EXPECT_TRUE(m.Matches(std::function<void()>()));
+  EXPECT_FALSE(m.Matches([]{}));
+}
+#endif  // GTEST_LANG_CXX11
+
+// Tests that IsNull() describes itself properly.
+TEST(IsNullTest, CanDescribeSelf) {
+  Matcher<int*> m = IsNull();
+  EXPECT_EQ("is NULL", Describe(m));
+  EXPECT_EQ("isn't NULL", DescribeNegation(m));
+}
+
+// Tests that NotNull() matches any non-NULL pointer of any type.
+TEST(NotNullTest, MatchesNonNullPointer) {
+  Matcher<int*> m1 = NotNull();
+  int* p1 = NULL;
+  int n = 0;
+  EXPECT_FALSE(m1.Matches(p1));
+  EXPECT_TRUE(m1.Matches(&n));
+
+  Matcher<const char*> m2 = NotNull();
+  const char* p2 = NULL;
+  EXPECT_FALSE(m2.Matches(p2));
+  EXPECT_TRUE(m2.Matches("hi"));
+}
+
+TEST(NotNullTest, LinkedPtr) {
+  const Matcher<linked_ptr<int> > m = NotNull();
+  const linked_ptr<int> null_p;
+  const linked_ptr<int> non_null_p(new int);
+
+  EXPECT_FALSE(m.Matches(null_p));
+  EXPECT_TRUE(m.Matches(non_null_p));
+}
+
+TEST(NotNullTest, ReferenceToConstLinkedPtr) {
+  const Matcher<const linked_ptr<double>&> m = NotNull();
+  const linked_ptr<double> null_p;
+  const linked_ptr<double> non_null_p(new double);
+
+  EXPECT_FALSE(m.Matches(null_p));
+  EXPECT_TRUE(m.Matches(non_null_p));
+}
+
+#if GTEST_LANG_CXX11
+TEST(NotNullTest, StdFunction) {
+  const Matcher<std::function<void()>> m = NotNull();
+
+  EXPECT_TRUE(m.Matches([]{}));
+  EXPECT_FALSE(m.Matches(std::function<void()>()));
+}
+#endif  // GTEST_LANG_CXX11
+
+// Tests that NotNull() describes itself properly.
+TEST(NotNullTest, CanDescribeSelf) {
+  Matcher<int*> m = NotNull();
+  EXPECT_EQ("isn't NULL", Describe(m));
+}
+
+// Tests that Ref(variable) matches an argument that references
+// 'variable'.
+TEST(RefTest, MatchesSameVariable) {
+  int a = 0;
+  int b = 0;
+  Matcher<int&> m = Ref(a);
+  EXPECT_TRUE(m.Matches(a));
+  EXPECT_FALSE(m.Matches(b));
+}
+
+// Tests that Ref(variable) describes itself properly.
+TEST(RefTest, CanDescribeSelf) {
+  int n = 5;
+  Matcher<int&> m = Ref(n);
+  stringstream ss;
+  ss << "references the variable @" << &n << " 5";
+  EXPECT_EQ(string(ss.str()), Describe(m));
+}
+
+// Test that Ref(non_const_varialbe) can be used as a matcher for a
+// const reference.
+TEST(RefTest, CanBeUsedAsMatcherForConstReference) {
+  int a = 0;
+  int b = 0;
+  Matcher<const int&> m = Ref(a);
+  EXPECT_TRUE(m.Matches(a));
+  EXPECT_FALSE(m.Matches(b));
+}
+
+// Tests that Ref(variable) is covariant, i.e. Ref(derived) can be
+// used wherever Ref(base) can be used (Ref(derived) is a sub-type
+// of Ref(base), but not vice versa.
+
+TEST(RefTest, IsCovariant) {
+  Base base, base2;
+  Derived derived;
+  Matcher<const Base&> m1 = Ref(base);
+  EXPECT_TRUE(m1.Matches(base));
+  EXPECT_FALSE(m1.Matches(base2));
+  EXPECT_FALSE(m1.Matches(derived));
+
+  m1 = Ref(derived);
+  EXPECT_TRUE(m1.Matches(derived));
+  EXPECT_FALSE(m1.Matches(base));
+  EXPECT_FALSE(m1.Matches(base2));
+}
+
+TEST(RefTest, ExplainsResult) {
+  int n = 0;
+  EXPECT_THAT(Explain(Matcher<const int&>(Ref(n)), n),
+              StartsWith("which is located @"));
+
+  int m = 0;
+  EXPECT_THAT(Explain(Matcher<const int&>(Ref(n)), m),
+              StartsWith("which is located @"));
+}
+
+// Tests string comparison matchers.
+
+TEST(StrEqTest, MatchesEqualString) {
+  Matcher<const char*> m = StrEq(string("Hello"));
+  EXPECT_TRUE(m.Matches("Hello"));
+  EXPECT_FALSE(m.Matches("hello"));
+  EXPECT_FALSE(m.Matches(NULL));
+
+  Matcher<const string&> m2 = StrEq("Hello");
+  EXPECT_TRUE(m2.Matches("Hello"));
+  EXPECT_FALSE(m2.Matches("Hi"));
+}
+
+TEST(StrEqTest, CanDescribeSelf) {
+  Matcher<string> m = StrEq("Hi-\'\"?\\\a\b\f\n\r\t\v\xD3");
+  EXPECT_EQ("is equal to \"Hi-\'\\\"?\\\\\\a\\b\\f\\n\\r\\t\\v\\xD3\"",
+      Describe(m));
+
+  string str("01204500800");
+  str[3] = '\0';
+  Matcher<string> m2 = StrEq(str);
+  EXPECT_EQ("is equal to \"012\\04500800\"", Describe(m2));
+  str[0] = str[6] = str[7] = str[9] = str[10] = '\0';
+  Matcher<string> m3 = StrEq(str);
+  EXPECT_EQ("is equal to \"\\012\\045\\0\\08\\0\\0\"", Describe(m3));
+}
+
+TEST(StrNeTest, MatchesUnequalString) {
+  Matcher<const char*> m = StrNe("Hello");
+  EXPECT_TRUE(m.Matches(""));
+  EXPECT_TRUE(m.Matches(NULL));
+  EXPECT_FALSE(m.Matches("Hello"));
+
+  Matcher<string> m2 = StrNe(string("Hello"));
+  EXPECT_TRUE(m2.Matches("hello"));
+  EXPECT_FALSE(m2.Matches("Hello"));
+}
+
+TEST(StrNeTest, CanDescribeSelf) {
+  Matcher<const char*> m = StrNe("Hi");
+  EXPECT_EQ("isn't equal to \"Hi\"", Describe(m));
+}
+
+TEST(StrCaseEqTest, MatchesEqualStringIgnoringCase) {
+  Matcher<const char*> m = StrCaseEq(string("Hello"));
+  EXPECT_TRUE(m.Matches("Hello"));
+  EXPECT_TRUE(m.Matches("hello"));
+  EXPECT_FALSE(m.Matches("Hi"));
+  EXPECT_FALSE(m.Matches(NULL));
+
+  Matcher<const string&> m2 = StrCaseEq("Hello");
+  EXPECT_TRUE(m2.Matches("hello"));
+  EXPECT_FALSE(m2.Matches("Hi"));
+}
+
+TEST(StrCaseEqTest, MatchesEqualStringWith0IgnoringCase) {
+  string str1("oabocdooeoo");
+  string str2("OABOCDOOEOO");
+  Matcher<const string&> m0 = StrCaseEq(str1);
+  EXPECT_FALSE(m0.Matches(str2 + string(1, '\0')));
+
+  str1[3] = str2[3] = '\0';
+  Matcher<const string&> m1 = StrCaseEq(str1);
+  EXPECT_TRUE(m1.Matches(str2));
+
+  str1[0] = str1[6] = str1[7] = str1[10] = '\0';
+  str2[0] = str2[6] = str2[7] = str2[10] = '\0';
+  Matcher<const string&> m2 = StrCaseEq(str1);
+  str1[9] = str2[9] = '\0';
+  EXPECT_FALSE(m2.Matches(str2));
+
+  Matcher<const string&> m3 = StrCaseEq(str1);
+  EXPECT_TRUE(m3.Matches(str2));
+
+  EXPECT_FALSE(m3.Matches(str2 + "x"));
+  str2.append(1, '\0');
+  EXPECT_FALSE(m3.Matches(str2));
+  EXPECT_FALSE(m3.Matches(string(str2, 0, 9)));
+}
+
+TEST(StrCaseEqTest, CanDescribeSelf) {
+  Matcher<string> m = StrCaseEq("Hi");
+  EXPECT_EQ("is equal to (ignoring case) \"Hi\"", Describe(m));
+}
+
+TEST(StrCaseNeTest, MatchesUnequalStringIgnoringCase) {
+  Matcher<const char*> m = StrCaseNe("Hello");
+  EXPECT_TRUE(m.Matches("Hi"));
+  EXPECT_TRUE(m.Matches(NULL));
+  EXPECT_FALSE(m.Matches("Hello"));
+  EXPECT_FALSE(m.Matches("hello"));
+
+  Matcher<string> m2 = StrCaseNe(string("Hello"));
+  EXPECT_TRUE(m2.Matches(""));
+  EXPECT_FALSE(m2.Matches("Hello"));
+}
+
+TEST(StrCaseNeTest, CanDescribeSelf) {
+  Matcher<const char*> m = StrCaseNe("Hi");
+  EXPECT_EQ("isn't equal to (ignoring case) \"Hi\"", Describe(m));
+}
+
+// Tests that HasSubstr() works for matching string-typed values.
+TEST(HasSubstrTest, WorksForStringClasses) {
+  const Matcher<string> m1 = HasSubstr("foo");
+  EXPECT_TRUE(m1.Matches(string("I love food.")));
+  EXPECT_FALSE(m1.Matches(string("tofo")));
+
+  const Matcher<const std::string&> m2 = HasSubstr("foo");
+  EXPECT_TRUE(m2.Matches(std::string("I love food.")));
+  EXPECT_FALSE(m2.Matches(std::string("tofo")));
+}
+
+// Tests that HasSubstr() works for matching C-string-typed values.
+TEST(HasSubstrTest, WorksForCStrings) {
+  const Matcher<char*> m1 = HasSubstr("foo");
+  EXPECT_TRUE(m1.Matches(const_cast<char*>("I love food.")));
+  EXPECT_FALSE(m1.Matches(const_cast<char*>("tofo")));
+  EXPECT_FALSE(m1.Matches(NULL));
+
+  const Matcher<const char*> m2 = HasSubstr("foo");
+  EXPECT_TRUE(m2.Matches("I love food."));
+  EXPECT_FALSE(m2.Matches("tofo"));
+  EXPECT_FALSE(m2.Matches(NULL));
+}
+
+// Tests that HasSubstr(s) describes itself properly.
+TEST(HasSubstrTest, CanDescribeSelf) {
+  Matcher<string> m = HasSubstr("foo\n\"");
+  EXPECT_EQ("has substring \"foo\\n\\\"\"", Describe(m));
+}
+
+TEST(KeyTest, CanDescribeSelf) {
+  Matcher<const pair<std::string, int>&> m = Key("foo");
+  EXPECT_EQ("has a key that is equal to \"foo\"", Describe(m));
+  EXPECT_EQ("doesn't have a key that is equal to \"foo\"", DescribeNegation(m));
+}
+
+TEST(KeyTest, ExplainsResult) {
+  Matcher<pair<int, bool> > m = Key(GreaterThan(10));
+  EXPECT_EQ("whose first field is a value which is 5 less than 10",
+            Explain(m, make_pair(5, true)));
+  EXPECT_EQ("whose first field is a value which is 5 more than 10",
+            Explain(m, make_pair(15, true)));
+}
+
+TEST(KeyTest, MatchesCorrectly) {
+  pair<int, std::string> p(25, "foo");
+  EXPECT_THAT(p, Key(25));
+  EXPECT_THAT(p, Not(Key(42)));
+  EXPECT_THAT(p, Key(Ge(20)));
+  EXPECT_THAT(p, Not(Key(Lt(25))));
+}
+
+TEST(KeyTest, SafelyCastsInnerMatcher) {
+  Matcher<int> is_positive = Gt(0);
+  Matcher<int> is_negative = Lt(0);
+  pair<char, bool> p('a', true);
+  EXPECT_THAT(p, Key(is_positive));
+  EXPECT_THAT(p, Not(Key(is_negative)));
+}
+
+TEST(KeyTest, InsideContainsUsingMap) {
+  map<int, char> container;
+  container.insert(make_pair(1, 'a'));
+  container.insert(make_pair(2, 'b'));
+  container.insert(make_pair(4, 'c'));
+  EXPECT_THAT(container, Contains(Key(1)));
+  EXPECT_THAT(container, Not(Contains(Key(3))));
+}
+
+TEST(KeyTest, InsideContainsUsingMultimap) {
+  multimap<int, char> container;
+  container.insert(make_pair(1, 'a'));
+  container.insert(make_pair(2, 'b'));
+  container.insert(make_pair(4, 'c'));
+
+  EXPECT_THAT(container, Not(Contains(Key(25))));
+  container.insert(make_pair(25, 'd'));
+  EXPECT_THAT(container, Contains(Key(25)));
+  container.insert(make_pair(25, 'e'));
+  EXPECT_THAT(container, Contains(Key(25)));
+
+  EXPECT_THAT(container, Contains(Key(1)));
+  EXPECT_THAT(container, Not(Contains(Key(3))));
+}
+
+TEST(PairTest, Typing) {
+  // Test verifies the following type conversions can be compiled.
+  Matcher<const pair<const char*, int>&> m1 = Pair("foo", 42);
+  Matcher<const pair<const char*, int> > m2 = Pair("foo", 42);
+  Matcher<pair<const char*, int> > m3 = Pair("foo", 42);
+
+  Matcher<pair<int, const std::string> > m4 = Pair(25, "42");
+  Matcher<pair<const std::string, int> > m5 = Pair("25", 42);
+}
+
+TEST(PairTest, CanDescribeSelf) {
+  Matcher<const pair<std::string, int>&> m1 = Pair("foo", 42);
+  EXPECT_EQ("has a first field that is equal to \"foo\""
+            ", and has a second field that is equal to 42",
+            Describe(m1));
+  EXPECT_EQ("has a first field that isn't equal to \"foo\""
+            ", or has a second field that isn't equal to 42",
+            DescribeNegation(m1));
+  // Double and triple negation (1 or 2 times not and description of negation).
+  Matcher<const pair<int, int>&> m2 = Not(Pair(Not(13), 42));
+  EXPECT_EQ("has a first field that isn't equal to 13"
+            ", and has a second field that is equal to 42",
+            DescribeNegation(m2));
+}
+
+TEST(PairTest, CanExplainMatchResultTo) {
+  // If neither field matches, Pair() should explain about the first
+  // field.
+  const Matcher<pair<int, int> > m = Pair(GreaterThan(0), GreaterThan(0));
+  EXPECT_EQ("whose first field does not match, which is 1 less than 0",
+            Explain(m, make_pair(-1, -2)));
+
+  // If the first field matches but the second doesn't, Pair() should
+  // explain about the second field.
+  EXPECT_EQ("whose second field does not match, which is 2 less than 0",
+            Explain(m, make_pair(1, -2)));
+
+  // If the first field doesn't match but the second does, Pair()
+  // should explain about the first field.
+  EXPECT_EQ("whose first field does not match, which is 1 less than 0",
+            Explain(m, make_pair(-1, 2)));
+
+  // If both fields match, Pair() should explain about them both.
+  EXPECT_EQ("whose both fields match, where the first field is a value "
+            "which is 1 more than 0, and the second field is a value "
+            "which is 2 more than 0",
+            Explain(m, make_pair(1, 2)));
+
+  // If only the first match has an explanation, only this explanation should
+  // be printed.
+  const Matcher<pair<int, int> > explain_first = Pair(GreaterThan(0), 0);
+  EXPECT_EQ("whose both fields match, where the first field is a value "
+            "which is 1 more than 0",
+            Explain(explain_first, make_pair(1, 0)));
+
+  // If only the second match has an explanation, only this explanation should
+  // be printed.
+  const Matcher<pair<int, int> > explain_second = Pair(0, GreaterThan(0));
+  EXPECT_EQ("whose both fields match, where the second field is a value "
+            "which is 1 more than 0",
+            Explain(explain_second, make_pair(0, 1)));
+}
+
+TEST(PairTest, MatchesCorrectly) {
+  pair<int, std::string> p(25, "foo");
+
+  // Both fields match.
+  EXPECT_THAT(p, Pair(25, "foo"));
+  EXPECT_THAT(p, Pair(Ge(20), HasSubstr("o")));
+
+  // 'first' doesnt' match, but 'second' matches.
+  EXPECT_THAT(p, Not(Pair(42, "foo")));
+  EXPECT_THAT(p, Not(Pair(Lt(25), "foo")));
+
+  // 'first' matches, but 'second' doesn't match.
+  EXPECT_THAT(p, Not(Pair(25, "bar")));
+  EXPECT_THAT(p, Not(Pair(25, Not("foo"))));
+
+  // Neither field matches.
+  EXPECT_THAT(p, Not(Pair(13, "bar")));
+  EXPECT_THAT(p, Not(Pair(Lt(13), HasSubstr("a"))));
+}
+
+TEST(PairTest, SafelyCastsInnerMatchers) {
+  Matcher<int> is_positive = Gt(0);
+  Matcher<int> is_negative = Lt(0);
+  pair<char, bool> p('a', true);
+  EXPECT_THAT(p, Pair(is_positive, _));
+  EXPECT_THAT(p, Not(Pair(is_negative, _)));
+  EXPECT_THAT(p, Pair(_, is_positive));
+  EXPECT_THAT(p, Not(Pair(_, is_negative)));
+}
+
+TEST(PairTest, InsideContainsUsingMap) {
+  map<int, char> container;
+  container.insert(make_pair(1, 'a'));
+  container.insert(make_pair(2, 'b'));
+  container.insert(make_pair(4, 'c'));
+  EXPECT_THAT(container, Contains(Pair(1, 'a')));
+  EXPECT_THAT(container, Contains(Pair(1, _)));
+  EXPECT_THAT(container, Contains(Pair(_, 'a')));
+  EXPECT_THAT(container, Not(Contains(Pair(3, _))));
+}
+
+// Tests StartsWith(s).
+
+TEST(StartsWithTest, MatchesStringWithGivenPrefix) {
+  const Matcher<const char*> m1 = StartsWith(string(""));
+  EXPECT_TRUE(m1.Matches("Hi"));
+  EXPECT_TRUE(m1.Matches(""));
+  EXPECT_FALSE(m1.Matches(NULL));
+
+  const Matcher<const string&> m2 = StartsWith("Hi");
+  EXPECT_TRUE(m2.Matches("Hi"));
+  EXPECT_TRUE(m2.Matches("Hi Hi!"));
+  EXPECT_TRUE(m2.Matches("High"));
+  EXPECT_FALSE(m2.Matches("H"));
+  EXPECT_FALSE(m2.Matches(" Hi"));
+}
+
+TEST(StartsWithTest, CanDescribeSelf) {
+  Matcher<const std::string> m = StartsWith("Hi");
+  EXPECT_EQ("starts with \"Hi\"", Describe(m));
+}
+
+// Tests EndsWith(s).
+
+TEST(EndsWithTest, MatchesStringWithGivenSuffix) {
+  const Matcher<const char*> m1 = EndsWith("");
+  EXPECT_TRUE(m1.Matches("Hi"));
+  EXPECT_TRUE(m1.Matches(""));
+  EXPECT_FALSE(m1.Matches(NULL));
+
+  const Matcher<const string&> m2 = EndsWith(string("Hi"));
+  EXPECT_TRUE(m2.Matches("Hi"));
+  EXPECT_TRUE(m2.Matches("Wow Hi Hi"));
+  EXPECT_TRUE(m2.Matches("Super Hi"));
+  EXPECT_FALSE(m2.Matches("i"));
+  EXPECT_FALSE(m2.Matches("Hi "));
+}
+
+TEST(EndsWithTest, CanDescribeSelf) {
+  Matcher<const std::string> m = EndsWith("Hi");
+  EXPECT_EQ("ends with \"Hi\"", Describe(m));
+}
+
+// Tests MatchesRegex().
+
+TEST(MatchesRegexTest, MatchesStringMatchingGivenRegex) {
+  const Matcher<const char*> m1 = MatchesRegex("a.*z");
+  EXPECT_TRUE(m1.Matches("az"));
+  EXPECT_TRUE(m1.Matches("abcz"));
+  EXPECT_FALSE(m1.Matches(NULL));
+
+  const Matcher<const string&> m2 = MatchesRegex(new RE("a.*z"));
+  EXPECT_TRUE(m2.Matches("azbz"));
+  EXPECT_FALSE(m2.Matches("az1"));
+  EXPECT_FALSE(m2.Matches("1az"));
+}
+
+TEST(MatchesRegexTest, CanDescribeSelf) {
+  Matcher<const std::string> m1 = MatchesRegex(string("Hi.*"));
+  EXPECT_EQ("matches regular expression \"Hi.*\"", Describe(m1));
+
+  Matcher<const char*> m2 = MatchesRegex(new RE("a.*"));
+  EXPECT_EQ("matches regular expression \"a.*\"", Describe(m2));
+}
+
+// Tests ContainsRegex().
+
+TEST(ContainsRegexTest, MatchesStringContainingGivenRegex) {
+  const Matcher<const char*> m1 = ContainsRegex(string("a.*z"));
+  EXPECT_TRUE(m1.Matches("az"));
+  EXPECT_TRUE(m1.Matches("0abcz1"));
+  EXPECT_FALSE(m1.Matches(NULL));
+
+  const Matcher<const string&> m2 = ContainsRegex(new RE("a.*z"));
+  EXPECT_TRUE(m2.Matches("azbz"));
+  EXPECT_TRUE(m2.Matches("az1"));
+  EXPECT_FALSE(m2.Matches("1a"));
+}
+
+TEST(ContainsRegexTest, CanDescribeSelf) {
+  Matcher<const std::string> m1 = ContainsRegex("Hi.*");
+  EXPECT_EQ("contains regular expression \"Hi.*\"", Describe(m1));
+
+  Matcher<const char*> m2 = ContainsRegex(new RE("a.*"));
+  EXPECT_EQ("contains regular expression \"a.*\"", Describe(m2));
+}
+
+// Tests for wide strings.
+#if GTEST_HAS_STD_WSTRING
+TEST(StdWideStrEqTest, MatchesEqual) {
+  Matcher<const wchar_t*> m = StrEq(::std::wstring(L"Hello"));
+  EXPECT_TRUE(m.Matches(L"Hello"));
+  EXPECT_FALSE(m.Matches(L"hello"));
+  EXPECT_FALSE(m.Matches(NULL));
+
+  Matcher<const ::std::wstring&> m2 = StrEq(L"Hello");
+  EXPECT_TRUE(m2.Matches(L"Hello"));
+  EXPECT_FALSE(m2.Matches(L"Hi"));
+
+  Matcher<const ::std::wstring&> m3 = StrEq(L"\xD3\x576\x8D3\xC74D");
+  EXPECT_TRUE(m3.Matches(L"\xD3\x576\x8D3\xC74D"));
+  EXPECT_FALSE(m3.Matches(L"\xD3\x576\x8D3\xC74E"));
+
+  ::std::wstring str(L"01204500800");
+  str[3] = L'\0';
+  Matcher<const ::std::wstring&> m4 = StrEq(str);
+  EXPECT_TRUE(m4.Matches(str));
+  str[0] = str[6] = str[7] = str[9] = str[10] = L'\0';
+  Matcher<const ::std::wstring&> m5 = StrEq(str);
+  EXPECT_TRUE(m5.Matches(str));
+}
+
+TEST(StdWideStrEqTest, CanDescribeSelf) {
+  Matcher< ::std::wstring> m = StrEq(L"Hi-\'\"?\\\a\b\f\n\r\t\v");
+  EXPECT_EQ("is equal to L\"Hi-\'\\\"?\\\\\\a\\b\\f\\n\\r\\t\\v\"",
+    Describe(m));
+
+  Matcher< ::std::wstring> m2 = StrEq(L"\xD3\x576\x8D3\xC74D");
+  EXPECT_EQ("is equal to L\"\\xD3\\x576\\x8D3\\xC74D\"",
+    Describe(m2));
+
+  ::std::wstring str(L"01204500800");
+  str[3] = L'\0';
+  Matcher<const ::std::wstring&> m4 = StrEq(str);
+  EXPECT_EQ("is equal to L\"012\\04500800\"", Describe(m4));
+  str[0] = str[6] = str[7] = str[9] = str[10] = L'\0';
+  Matcher<const ::std::wstring&> m5 = StrEq(str);
+  EXPECT_EQ("is equal to L\"\\012\\045\\0\\08\\0\\0\"", Describe(m5));
+}
+
+TEST(StdWideStrNeTest, MatchesUnequalString) {
+  Matcher<const wchar_t*> m = StrNe(L"Hello");
+  EXPECT_TRUE(m.Matches(L""));
+  EXPECT_TRUE(m.Matches(NULL));
+  EXPECT_FALSE(m.Matches(L"Hello"));
+
+  Matcher< ::std::wstring> m2 = StrNe(::std::wstring(L"Hello"));
+  EXPECT_TRUE(m2.Matches(L"hello"));
+  EXPECT_FALSE(m2.Matches(L"Hello"));
+}
+
+TEST(StdWideStrNeTest, CanDescribeSelf) {
+  Matcher<const wchar_t*> m = StrNe(L"Hi");
+  EXPECT_EQ("isn't equal to L\"Hi\"", Describe(m));
+}
+
+TEST(StdWideStrCaseEqTest, MatchesEqualStringIgnoringCase) {
+  Matcher<const wchar_t*> m = StrCaseEq(::std::wstring(L"Hello"));
+  EXPECT_TRUE(m.Matches(L"Hello"));
+  EXPECT_TRUE(m.Matches(L"hello"));
+  EXPECT_FALSE(m.Matches(L"Hi"));
+  EXPECT_FALSE(m.Matches(NULL));
+
+  Matcher<const ::std::wstring&> m2 = StrCaseEq(L"Hello");
+  EXPECT_TRUE(m2.Matches(L"hello"));
+  EXPECT_FALSE(m2.Matches(L"Hi"));
+}
+
+TEST(StdWideStrCaseEqTest, MatchesEqualStringWith0IgnoringCase) {
+  ::std::wstring str1(L"oabocdooeoo");
+  ::std::wstring str2(L"OABOCDOOEOO");
+  Matcher<const ::std::wstring&> m0 = StrCaseEq(str1);
+  EXPECT_FALSE(m0.Matches(str2 + ::std::wstring(1, L'\0')));
+
+  str1[3] = str2[3] = L'\0';
+  Matcher<const ::std::wstring&> m1 = StrCaseEq(str1);
+  EXPECT_TRUE(m1.Matches(str2));
+
+  str1[0] = str1[6] = str1[7] = str1[10] = L'\0';
+  str2[0] = str2[6] = str2[7] = str2[10] = L'\0';
+  Matcher<const ::std::wstring&> m2 = StrCaseEq(str1);
+  str1[9] = str2[9] = L'\0';
+  EXPECT_FALSE(m2.Matches(str2));
+
+  Matcher<const ::std::wstring&> m3 = StrCaseEq(str1);
+  EXPECT_TRUE(m3.Matches(str2));
+
+  EXPECT_FALSE(m3.Matches(str2 + L"x"));
+  str2.append(1, L'\0');
+  EXPECT_FALSE(m3.Matches(str2));
+  EXPECT_FALSE(m3.Matches(::std::wstring(str2, 0, 9)));
+}
+
+TEST(StdWideStrCaseEqTest, CanDescribeSelf) {
+  Matcher< ::std::wstring> m = StrCaseEq(L"Hi");
+  EXPECT_EQ("is equal to (ignoring case) L\"Hi\"", Describe(m));
+}
+
+TEST(StdWideStrCaseNeTest, MatchesUnequalStringIgnoringCase) {
+  Matcher<const wchar_t*> m = StrCaseNe(L"Hello");
+  EXPECT_TRUE(m.Matches(L"Hi"));
+  EXPECT_TRUE(m.Matches(NULL));
+  EXPECT_FALSE(m.Matches(L"Hello"));
+  EXPECT_FALSE(m.Matches(L"hello"));
+
+  Matcher< ::std::wstring> m2 = StrCaseNe(::std::wstring(L"Hello"));
+  EXPECT_TRUE(m2.Matches(L""));
+  EXPECT_FALSE(m2.Matches(L"Hello"));
+}
+
+TEST(StdWideStrCaseNeTest, CanDescribeSelf) {
+  Matcher<const wchar_t*> m = StrCaseNe(L"Hi");
+  EXPECT_EQ("isn't equal to (ignoring case) L\"Hi\"", Describe(m));
+}
+
+// Tests that HasSubstr() works for matching wstring-typed values.
+TEST(StdWideHasSubstrTest, WorksForStringClasses) {
+  const Matcher< ::std::wstring> m1 = HasSubstr(L"foo");
+  EXPECT_TRUE(m1.Matches(::std::wstring(L"I love food.")));
+  EXPECT_FALSE(m1.Matches(::std::wstring(L"tofo")));
+
+  const Matcher<const ::std::wstring&> m2 = HasSubstr(L"foo");
+  EXPECT_TRUE(m2.Matches(::std::wstring(L"I love food.")));
+  EXPECT_FALSE(m2.Matches(::std::wstring(L"tofo")));
+}
+
+// Tests that HasSubstr() works for matching C-wide-string-typed values.
+TEST(StdWideHasSubstrTest, WorksForCStrings) {
+  const Matcher<wchar_t*> m1 = HasSubstr(L"foo");
+  EXPECT_TRUE(m1.Matches(const_cast<wchar_t*>(L"I love food.")));
+  EXPECT_FALSE(m1.Matches(const_cast<wchar_t*>(L"tofo")));
+  EXPECT_FALSE(m1.Matches(NULL));
+
+  const Matcher<const wchar_t*> m2 = HasSubstr(L"foo");
+  EXPECT_TRUE(m2.Matches(L"I love food."));
+  EXPECT_FALSE(m2.Matches(L"tofo"));
+  EXPECT_FALSE(m2.Matches(NULL));
+}
+
+// Tests that HasSubstr(s) describes itself properly.
+TEST(StdWideHasSubstrTest, CanDescribeSelf) {
+  Matcher< ::std::wstring> m = HasSubstr(L"foo\n\"");
+  EXPECT_EQ("has substring L\"foo\\n\\\"\"", Describe(m));
+}
+
+// Tests StartsWith(s).
+
+TEST(StdWideStartsWithTest, MatchesStringWithGivenPrefix) {
+  const Matcher<const wchar_t*> m1 = StartsWith(::std::wstring(L""));
+  EXPECT_TRUE(m1.Matches(L"Hi"));
+  EXPECT_TRUE(m1.Matches(L""));
+  EXPECT_FALSE(m1.Matches(NULL));
+
+  const Matcher<const ::std::wstring&> m2 = StartsWith(L"Hi");
+  EXPECT_TRUE(m2.Matches(L"Hi"));
+  EXPECT_TRUE(m2.Matches(L"Hi Hi!"));
+  EXPECT_TRUE(m2.Matches(L"High"));
+  EXPECT_FALSE(m2.Matches(L"H"));
+  EXPECT_FALSE(m2.Matches(L" Hi"));
+}
+
+TEST(StdWideStartsWithTest, CanDescribeSelf) {
+  Matcher<const ::std::wstring> m = StartsWith(L"Hi");
+  EXPECT_EQ("starts with L\"Hi\"", Describe(m));
+}
+
+// Tests EndsWith(s).
+
+TEST(StdWideEndsWithTest, MatchesStringWithGivenSuffix) {
+  const Matcher<const wchar_t*> m1 = EndsWith(L"");
+  EXPECT_TRUE(m1.Matches(L"Hi"));
+  EXPECT_TRUE(m1.Matches(L""));
+  EXPECT_FALSE(m1.Matches(NULL));
+
+  const Matcher<const ::std::wstring&> m2 = EndsWith(::std::wstring(L"Hi"));
+  EXPECT_TRUE(m2.Matches(L"Hi"));
+  EXPECT_TRUE(m2.Matches(L"Wow Hi Hi"));
+  EXPECT_TRUE(m2.Matches(L"Super Hi"));
+  EXPECT_FALSE(m2.Matches(L"i"));
+  EXPECT_FALSE(m2.Matches(L"Hi "));
+}
+
+TEST(StdWideEndsWithTest, CanDescribeSelf) {
+  Matcher<const ::std::wstring> m = EndsWith(L"Hi");
+  EXPECT_EQ("ends with L\"Hi\"", Describe(m));
+}
+
+#endif  // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+TEST(GlobalWideStrEqTest, MatchesEqual) {
+  Matcher<const wchar_t*> m = StrEq(::wstring(L"Hello"));
+  EXPECT_TRUE(m.Matches(L"Hello"));
+  EXPECT_FALSE(m.Matches(L"hello"));
+  EXPECT_FALSE(m.Matches(NULL));
+
+  Matcher<const ::wstring&> m2 = StrEq(L"Hello");
+  EXPECT_TRUE(m2.Matches(L"Hello"));
+  EXPECT_FALSE(m2.Matches(L"Hi"));
+
+  Matcher<const ::wstring&> m3 = StrEq(L"\xD3\x576\x8D3\xC74D");
+  EXPECT_TRUE(m3.Matches(L"\xD3\x576\x8D3\xC74D"));
+  EXPECT_FALSE(m3.Matches(L"\xD3\x576\x8D3\xC74E"));
+
+  ::wstring str(L"01204500800");
+  str[3] = L'\0';
+  Matcher<const ::wstring&> m4 = StrEq(str);
+  EXPECT_TRUE(m4.Matches(str));
+  str[0] = str[6] = str[7] = str[9] = str[10] = L'\0';
+  Matcher<const ::wstring&> m5 = StrEq(str);
+  EXPECT_TRUE(m5.Matches(str));
+}
+
+TEST(GlobalWideStrEqTest, CanDescribeSelf) {
+  Matcher< ::wstring> m = StrEq(L"Hi-\'\"?\\\a\b\f\n\r\t\v");
+  EXPECT_EQ("is equal to L\"Hi-\'\\\"?\\\\\\a\\b\\f\\n\\r\\t\\v\"",
+    Describe(m));
+
+  Matcher< ::wstring> m2 = StrEq(L"\xD3\x576\x8D3\xC74D");
+  EXPECT_EQ("is equal to L\"\\xD3\\x576\\x8D3\\xC74D\"",
+    Describe(m2));
+
+  ::wstring str(L"01204500800");
+  str[3] = L'\0';
+  Matcher<const ::wstring&> m4 = StrEq(str);
+  EXPECT_EQ("is equal to L\"012\\04500800\"", Describe(m4));
+  str[0] = str[6] = str[7] = str[9] = str[10] = L'\0';
+  Matcher<const ::wstring&> m5 = StrEq(str);
+  EXPECT_EQ("is equal to L\"\\012\\045\\0\\08\\0\\0\"", Describe(m5));
+}
+
+TEST(GlobalWideStrNeTest, MatchesUnequalString) {
+  Matcher<const wchar_t*> m = StrNe(L"Hello");
+  EXPECT_TRUE(m.Matches(L""));
+  EXPECT_TRUE(m.Matches(NULL));
+  EXPECT_FALSE(m.Matches(L"Hello"));
+
+  Matcher< ::wstring> m2 = StrNe(::wstring(L"Hello"));
+  EXPECT_TRUE(m2.Matches(L"hello"));
+  EXPECT_FALSE(m2.Matches(L"Hello"));
+}
+
+TEST(GlobalWideStrNeTest, CanDescribeSelf) {
+  Matcher<const wchar_t*> m = StrNe(L"Hi");
+  EXPECT_EQ("isn't equal to L\"Hi\"", Describe(m));
+}
+
+TEST(GlobalWideStrCaseEqTest, MatchesEqualStringIgnoringCase) {
+  Matcher<const wchar_t*> m = StrCaseEq(::wstring(L"Hello"));
+  EXPECT_TRUE(m.Matches(L"Hello"));
+  EXPECT_TRUE(m.Matches(L"hello"));
+  EXPECT_FALSE(m.Matches(L"Hi"));
+  EXPECT_FALSE(m.Matches(NULL));
+
+  Matcher<const ::wstring&> m2 = StrCaseEq(L"Hello");
+  EXPECT_TRUE(m2.Matches(L"hello"));
+  EXPECT_FALSE(m2.Matches(L"Hi"));
+}
+
+TEST(GlobalWideStrCaseEqTest, MatchesEqualStringWith0IgnoringCase) {
+  ::wstring str1(L"oabocdooeoo");
+  ::wstring str2(L"OABOCDOOEOO");
+  Matcher<const ::wstring&> m0 = StrCaseEq(str1);
+  EXPECT_FALSE(m0.Matches(str2 + ::wstring(1, L'\0')));
+
+  str1[3] = str2[3] = L'\0';
+  Matcher<const ::wstring&> m1 = StrCaseEq(str1);
+  EXPECT_TRUE(m1.Matches(str2));
+
+  str1[0] = str1[6] = str1[7] = str1[10] = L'\0';
+  str2[0] = str2[6] = str2[7] = str2[10] = L'\0';
+  Matcher<const ::wstring&> m2 = StrCaseEq(str1);
+  str1[9] = str2[9] = L'\0';
+  EXPECT_FALSE(m2.Matches(str2));
+
+  Matcher<const ::wstring&> m3 = StrCaseEq(str1);
+  EXPECT_TRUE(m3.Matches(str2));
+
+  EXPECT_FALSE(m3.Matches(str2 + L"x"));
+  str2.append(1, L'\0');
+  EXPECT_FALSE(m3.Matches(str2));
+  EXPECT_FALSE(m3.Matches(::wstring(str2, 0, 9)));
+}
+
+TEST(GlobalWideStrCaseEqTest, CanDescribeSelf) {
+  Matcher< ::wstring> m = StrCaseEq(L"Hi");
+  EXPECT_EQ("is equal to (ignoring case) L\"Hi\"", Describe(m));
+}
+
+TEST(GlobalWideStrCaseNeTest, MatchesUnequalStringIgnoringCase) {
+  Matcher<const wchar_t*> m = StrCaseNe(L"Hello");
+  EXPECT_TRUE(m.Matches(L"Hi"));
+  EXPECT_TRUE(m.Matches(NULL));
+  EXPECT_FALSE(m.Matches(L"Hello"));
+  EXPECT_FALSE(m.Matches(L"hello"));
+
+  Matcher< ::wstring> m2 = StrCaseNe(::wstring(L"Hello"));
+  EXPECT_TRUE(m2.Matches(L""));
+  EXPECT_FALSE(m2.Matches(L"Hello"));
+}
+
+TEST(GlobalWideStrCaseNeTest, CanDescribeSelf) {
+  Matcher<const wchar_t*> m = StrCaseNe(L"Hi");
+  EXPECT_EQ("isn't equal to (ignoring case) L\"Hi\"", Describe(m));
+}
+
+// Tests that HasSubstr() works for matching wstring-typed values.
+TEST(GlobalWideHasSubstrTest, WorksForStringClasses) {
+  const Matcher< ::wstring> m1 = HasSubstr(L"foo");
+  EXPECT_TRUE(m1.Matches(::wstring(L"I love food.")));
+  EXPECT_FALSE(m1.Matches(::wstring(L"tofo")));
+
+  const Matcher<const ::wstring&> m2 = HasSubstr(L"foo");
+  EXPECT_TRUE(m2.Matches(::wstring(L"I love food.")));
+  EXPECT_FALSE(m2.Matches(::wstring(L"tofo")));
+}
+
+// Tests that HasSubstr() works for matching C-wide-string-typed values.
+TEST(GlobalWideHasSubstrTest, WorksForCStrings) {
+  const Matcher<wchar_t*> m1 = HasSubstr(L"foo");
+  EXPECT_TRUE(m1.Matches(const_cast<wchar_t*>(L"I love food.")));
+  EXPECT_FALSE(m1.Matches(const_cast<wchar_t*>(L"tofo")));
+  EXPECT_FALSE(m1.Matches(NULL));
+
+  const Matcher<const wchar_t*> m2 = HasSubstr(L"foo");
+  EXPECT_TRUE(m2.Matches(L"I love food."));
+  EXPECT_FALSE(m2.Matches(L"tofo"));
+  EXPECT_FALSE(m2.Matches(NULL));
+}
+
+// Tests that HasSubstr(s) describes itself properly.
+TEST(GlobalWideHasSubstrTest, CanDescribeSelf) {
+  Matcher< ::wstring> m = HasSubstr(L"foo\n\"");
+  EXPECT_EQ("has substring L\"foo\\n\\\"\"", Describe(m));
+}
+
+// Tests StartsWith(s).
+
+TEST(GlobalWideStartsWithTest, MatchesStringWithGivenPrefix) {
+  const Matcher<const wchar_t*> m1 = StartsWith(::wstring(L""));
+  EXPECT_TRUE(m1.Matches(L"Hi"));
+  EXPECT_TRUE(m1.Matches(L""));
+  EXPECT_FALSE(m1.Matches(NULL));
+
+  const Matcher<const ::wstring&> m2 = StartsWith(L"Hi");
+  EXPECT_TRUE(m2.Matches(L"Hi"));
+  EXPECT_TRUE(m2.Matches(L"Hi Hi!"));
+  EXPECT_TRUE(m2.Matches(L"High"));
+  EXPECT_FALSE(m2.Matches(L"H"));
+  EXPECT_FALSE(m2.Matches(L" Hi"));
+}
+
+TEST(GlobalWideStartsWithTest, CanDescribeSelf) {
+  Matcher<const ::wstring> m = StartsWith(L"Hi");
+  EXPECT_EQ("starts with L\"Hi\"", Describe(m));
+}
+
+// Tests EndsWith(s).
+
+TEST(GlobalWideEndsWithTest, MatchesStringWithGivenSuffix) {
+  const Matcher<const wchar_t*> m1 = EndsWith(L"");
+  EXPECT_TRUE(m1.Matches(L"Hi"));
+  EXPECT_TRUE(m1.Matches(L""));
+  EXPECT_FALSE(m1.Matches(NULL));
+
+  const Matcher<const ::wstring&> m2 = EndsWith(::wstring(L"Hi"));
+  EXPECT_TRUE(m2.Matches(L"Hi"));
+  EXPECT_TRUE(m2.Matches(L"Wow Hi Hi"));
+  EXPECT_TRUE(m2.Matches(L"Super Hi"));
+  EXPECT_FALSE(m2.Matches(L"i"));
+  EXPECT_FALSE(m2.Matches(L"Hi "));
+}
+
+TEST(GlobalWideEndsWithTest, CanDescribeSelf) {
+  Matcher<const ::wstring> m = EndsWith(L"Hi");
+  EXPECT_EQ("ends with L\"Hi\"", Describe(m));
+}
+
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+
+typedef ::testing::tuple<long, int> Tuple2;  // NOLINT
+
+// Tests that Eq() matches a 2-tuple where the first field == the
+// second field.
+TEST(Eq2Test, MatchesEqualArguments) {
+  Matcher<const Tuple2&> m = Eq();
+  EXPECT_TRUE(m.Matches(Tuple2(5L, 5)));
+  EXPECT_FALSE(m.Matches(Tuple2(5L, 6)));
+}
+
+// Tests that Eq() describes itself properly.
+TEST(Eq2Test, CanDescribeSelf) {
+  Matcher<const Tuple2&> m = Eq();
+  EXPECT_EQ("are an equal pair", Describe(m));
+}
+
+// Tests that Ge() matches a 2-tuple where the first field >= the
+// second field.
+TEST(Ge2Test, MatchesGreaterThanOrEqualArguments) {
+  Matcher<const Tuple2&> m = Ge();
+  EXPECT_TRUE(m.Matches(Tuple2(5L, 4)));
+  EXPECT_TRUE(m.Matches(Tuple2(5L, 5)));
+  EXPECT_FALSE(m.Matches(Tuple2(5L, 6)));
+}
+
+// Tests that Ge() describes itself properly.
+TEST(Ge2Test, CanDescribeSelf) {
+  Matcher<const Tuple2&> m = Ge();
+  EXPECT_EQ("are a pair where the first >= the second", Describe(m));
+}
+
+// Tests that Gt() matches a 2-tuple where the first field > the
+// second field.
+TEST(Gt2Test, MatchesGreaterThanArguments) {
+  Matcher<const Tuple2&> m = Gt();
+  EXPECT_TRUE(m.Matches(Tuple2(5L, 4)));
+  EXPECT_FALSE(m.Matches(Tuple2(5L, 5)));
+  EXPECT_FALSE(m.Matches(Tuple2(5L, 6)));
+}
+
+// Tests that Gt() describes itself properly.
+TEST(Gt2Test, CanDescribeSelf) {
+  Matcher<const Tuple2&> m = Gt();
+  EXPECT_EQ("are a pair where the first > the second", Describe(m));
+}
+
+// Tests that Le() matches a 2-tuple where the first field <= the
+// second field.
+TEST(Le2Test, MatchesLessThanOrEqualArguments) {
+  Matcher<const Tuple2&> m = Le();
+  EXPECT_TRUE(m.Matches(Tuple2(5L, 6)));
+  EXPECT_TRUE(m.Matches(Tuple2(5L, 5)));
+  EXPECT_FALSE(m.Matches(Tuple2(5L, 4)));
+}
+
+// Tests that Le() describes itself properly.
+TEST(Le2Test, CanDescribeSelf) {
+  Matcher<const Tuple2&> m = Le();
+  EXPECT_EQ("are a pair where the first <= the second", Describe(m));
+}
+
+// Tests that Lt() matches a 2-tuple where the first field < the
+// second field.
+TEST(Lt2Test, MatchesLessThanArguments) {
+  Matcher<const Tuple2&> m = Lt();
+  EXPECT_TRUE(m.Matches(Tuple2(5L, 6)));
+  EXPECT_FALSE(m.Matches(Tuple2(5L, 5)));
+  EXPECT_FALSE(m.Matches(Tuple2(5L, 4)));
+}
+
+// Tests that Lt() describes itself properly.
+TEST(Lt2Test, CanDescribeSelf) {
+  Matcher<const Tuple2&> m = Lt();
+  EXPECT_EQ("are a pair where the first < the second", Describe(m));
+}
+
+// Tests that Ne() matches a 2-tuple where the first field != the
+// second field.
+TEST(Ne2Test, MatchesUnequalArguments) {
+  Matcher<const Tuple2&> m = Ne();
+  EXPECT_TRUE(m.Matches(Tuple2(5L, 6)));
+  EXPECT_TRUE(m.Matches(Tuple2(5L, 4)));
+  EXPECT_FALSE(m.Matches(Tuple2(5L, 5)));
+}
+
+// Tests that Ne() describes itself properly.
+TEST(Ne2Test, CanDescribeSelf) {
+  Matcher<const Tuple2&> m = Ne();
+  EXPECT_EQ("are an unequal pair", Describe(m));
+}
+
+// Tests that Not(m) matches any value that doesn't match m.
+TEST(NotTest, NegatesMatcher) {
+  Matcher<int> m;
+  m = Not(Eq(2));
+  EXPECT_TRUE(m.Matches(3));
+  EXPECT_FALSE(m.Matches(2));
+}
+
+// Tests that Not(m) describes itself properly.
+TEST(NotTest, CanDescribeSelf) {
+  Matcher<int> m = Not(Eq(5));
+  EXPECT_EQ("isn't equal to 5", Describe(m));
+}
+
+// Tests that monomorphic matchers are safely cast by the Not matcher.
+TEST(NotTest, NotMatcherSafelyCastsMonomorphicMatchers) {
+  // greater_than_5 is a monomorphic matcher.
+  Matcher<int> greater_than_5 = Gt(5);
+
+  Matcher<const int&> m = Not(greater_than_5);
+  Matcher<int&> m2 = Not(greater_than_5);
+  Matcher<int&> m3 = Not(m);
+}
+
+// Helper to allow easy testing of AllOf matchers with num parameters.
+void AllOfMatches(int num, const Matcher<int>& m) {
+  SCOPED_TRACE(Describe(m));
+  EXPECT_TRUE(m.Matches(0));
+  for (int i = 1; i <= num; ++i) {
+    EXPECT_FALSE(m.Matches(i));
+  }
+  EXPECT_TRUE(m.Matches(num + 1));
+}
+
+// Tests that AllOf(m1, ..., mn) matches any value that matches all of
+// the given matchers.
+TEST(AllOfTest, MatchesWhenAllMatch) {
+  Matcher<int> m;
+  m = AllOf(Le(2), Ge(1));
+  EXPECT_TRUE(m.Matches(1));
+  EXPECT_TRUE(m.Matches(2));
+  EXPECT_FALSE(m.Matches(0));
+  EXPECT_FALSE(m.Matches(3));
+
+  m = AllOf(Gt(0), Ne(1), Ne(2));
+  EXPECT_TRUE(m.Matches(3));
+  EXPECT_FALSE(m.Matches(2));
+  EXPECT_FALSE(m.Matches(1));
+  EXPECT_FALSE(m.Matches(0));
+
+  m = AllOf(Gt(0), Ne(1), Ne(2), Ne(3));
+  EXPECT_TRUE(m.Matches(4));
+  EXPECT_FALSE(m.Matches(3));
+  EXPECT_FALSE(m.Matches(2));
+  EXPECT_FALSE(m.Matches(1));
+  EXPECT_FALSE(m.Matches(0));
+
+  m = AllOf(Ge(0), Lt(10), Ne(3), Ne(5), Ne(7));
+  EXPECT_TRUE(m.Matches(0));
+  EXPECT_TRUE(m.Matches(1));
+  EXPECT_FALSE(m.Matches(3));
+
+  // The following tests for varying number of sub-matchers. Due to the way
+  // the sub-matchers are handled it is enough to test every sub-matcher once
+  // with sub-matchers using the same matcher type. Varying matcher types are
+  // checked for above.
+  AllOfMatches(2, AllOf(Ne(1), Ne(2)));
+  AllOfMatches(3, AllOf(Ne(1), Ne(2), Ne(3)));
+  AllOfMatches(4, AllOf(Ne(1), Ne(2), Ne(3), Ne(4)));
+  AllOfMatches(5, AllOf(Ne(1), Ne(2), Ne(3), Ne(4), Ne(5)));
+  AllOfMatches(6, AllOf(Ne(1), Ne(2), Ne(3), Ne(4), Ne(5), Ne(6)));
+  AllOfMatches(7, AllOf(Ne(1), Ne(2), Ne(3), Ne(4), Ne(5), Ne(6), Ne(7)));
+  AllOfMatches(8, AllOf(Ne(1), Ne(2), Ne(3), Ne(4), Ne(5), Ne(6), Ne(7),
+                        Ne(8)));
+  AllOfMatches(9, AllOf(Ne(1), Ne(2), Ne(3), Ne(4), Ne(5), Ne(6), Ne(7),
+                        Ne(8), Ne(9)));
+  AllOfMatches(10, AllOf(Ne(1), Ne(2), Ne(3), Ne(4), Ne(5), Ne(6), Ne(7), Ne(8),
+                         Ne(9), Ne(10)));
+}
+
+#if GTEST_LANG_CXX11
+// Tests the variadic version of the AllOfMatcher.
+TEST(AllOfTest, VariadicMatchesWhenAllMatch) {
+  // Make sure AllOf is defined in the right namespace and does not depend on
+  // ADL.
+  ::testing::AllOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
+  Matcher<int> m = AllOf(Ne(1), Ne(2), Ne(3), Ne(4), Ne(5), Ne(6), Ne(7), Ne(8),
+                         Ne(9), Ne(10), Ne(11));
+  EXPECT_THAT(Describe(m), EndsWith("and (isn't equal to 11))))))))))"));
+  AllOfMatches(11, m);
+  AllOfMatches(50, AllOf(Ne(1), Ne(2), Ne(3), Ne(4), Ne(5), Ne(6), Ne(7), Ne(8),
+                         Ne(9), Ne(10), Ne(11), Ne(12), Ne(13), Ne(14), Ne(15),
+                         Ne(16), Ne(17), Ne(18), Ne(19), Ne(20), Ne(21), Ne(22),
+                         Ne(23), Ne(24), Ne(25), Ne(26), Ne(27), Ne(28), Ne(29),
+                         Ne(30), Ne(31), Ne(32), Ne(33), Ne(34), Ne(35), Ne(36),
+                         Ne(37), Ne(38), Ne(39), Ne(40), Ne(41), Ne(42), Ne(43),
+                         Ne(44), Ne(45), Ne(46), Ne(47), Ne(48), Ne(49),
+                         Ne(50)));
+}
+
+#endif  // GTEST_LANG_CXX11
+
+// Tests that AllOf(m1, ..., mn) describes itself properly.
+TEST(AllOfTest, CanDescribeSelf) {
+  Matcher<int> m;
+  m = AllOf(Le(2), Ge(1));
+  EXPECT_EQ("(is <= 2) and (is >= 1)", Describe(m));
+
+  m = AllOf(Gt(0), Ne(1), Ne(2));
+  EXPECT_EQ("(is > 0) and "
+            "((isn't equal to 1) and "
+            "(isn't equal to 2))",
+            Describe(m));
+
+
+  m = AllOf(Gt(0), Ne(1), Ne(2), Ne(3));
+  EXPECT_EQ("((is > 0) and "
+            "(isn't equal to 1)) and "
+            "((isn't equal to 2) and "
+            "(isn't equal to 3))",
+            Describe(m));
+
+
+  m = AllOf(Ge(0), Lt(10), Ne(3), Ne(5), Ne(7));
+  EXPECT_EQ("((is >= 0) and "
+            "(is < 10)) and "
+            "((isn't equal to 3) and "
+            "((isn't equal to 5) and "
+            "(isn't equal to 7)))",
+            Describe(m));
+}
+
+// Tests that AllOf(m1, ..., mn) describes its negation properly.
+TEST(AllOfTest, CanDescribeNegation) {
+  Matcher<int> m;
+  m = AllOf(Le(2), Ge(1));
+  EXPECT_EQ("(isn't <= 2) or "
+            "(isn't >= 1)",
+            DescribeNegation(m));
+
+  m = AllOf(Gt(0), Ne(1), Ne(2));
+  EXPECT_EQ("(isn't > 0) or "
+            "((is equal to 1) or "
+            "(is equal to 2))",
+            DescribeNegation(m));
+
+
+  m = AllOf(Gt(0), Ne(1), Ne(2), Ne(3));
+  EXPECT_EQ("((isn't > 0) or "
+            "(is equal to 1)) or "
+            "((is equal to 2) or "
+            "(is equal to 3))",
+            DescribeNegation(m));
+
+
+  m = AllOf(Ge(0), Lt(10), Ne(3), Ne(5), Ne(7));
+  EXPECT_EQ("((isn't >= 0) or "
+            "(isn't < 10)) or "
+            "((is equal to 3) or "
+            "((is equal to 5) or "
+            "(is equal to 7)))",
+            DescribeNegation(m));
+}
+
+// Tests that monomorphic matchers are safely cast by the AllOf matcher.
+TEST(AllOfTest, AllOfMatcherSafelyCastsMonomorphicMatchers) {
+  // greater_than_5 and less_than_10 are monomorphic matchers.
+  Matcher<int> greater_than_5 = Gt(5);
+  Matcher<int> less_than_10 = Lt(10);
+
+  Matcher<const int&> m = AllOf(greater_than_5, less_than_10);
+  Matcher<int&> m2 = AllOf(greater_than_5, less_than_10);
+  Matcher<int&> m3 = AllOf(greater_than_5, m2);
+
+  // Tests that BothOf works when composing itself.
+  Matcher<const int&> m4 = AllOf(greater_than_5, less_than_10, less_than_10);
+  Matcher<int&> m5 = AllOf(greater_than_5, less_than_10, less_than_10);
+}
+
+TEST(AllOfTest, ExplainsResult) {
+  Matcher<int> m;
+
+  // Successful match.  Both matchers need to explain.  The second
+  // matcher doesn't give an explanation, so only the first matcher's
+  // explanation is printed.
+  m = AllOf(GreaterThan(10), Lt(30));
+  EXPECT_EQ("which is 15 more than 10", Explain(m, 25));
+
+  // Successful match.  Both matchers need to explain.
+  m = AllOf(GreaterThan(10), GreaterThan(20));
+  EXPECT_EQ("which is 20 more than 10, and which is 10 more than 20",
+            Explain(m, 30));
+
+  // Successful match.  All matchers need to explain.  The second
+  // matcher doesn't given an explanation.
+  m = AllOf(GreaterThan(10), Lt(30), GreaterThan(20));
+  EXPECT_EQ("which is 15 more than 10, and which is 5 more than 20",
+            Explain(m, 25));
+
+  // Successful match.  All matchers need to explain.
+  m = AllOf(GreaterThan(10), GreaterThan(20), GreaterThan(30));
+  EXPECT_EQ("which is 30 more than 10, and which is 20 more than 20, "
+            "and which is 10 more than 30",
+            Explain(m, 40));
+
+  // Failed match.  The first matcher, which failed, needs to
+  // explain.
+  m = AllOf(GreaterThan(10), GreaterThan(20));
+  EXPECT_EQ("which is 5 less than 10", Explain(m, 5));
+
+  // Failed match.  The second matcher, which failed, needs to
+  // explain.  Since it doesn't given an explanation, nothing is
+  // printed.
+  m = AllOf(GreaterThan(10), Lt(30));
+  EXPECT_EQ("", Explain(m, 40));
+
+  // Failed match.  The second matcher, which failed, needs to
+  // explain.
+  m = AllOf(GreaterThan(10), GreaterThan(20));
+  EXPECT_EQ("which is 5 less than 20", Explain(m, 15));
+}
+
+// Helper to allow easy testing of AnyOf matchers with num parameters.
+void AnyOfMatches(int num, const Matcher<int>& m) {
+  SCOPED_TRACE(Describe(m));
+  EXPECT_FALSE(m.Matches(0));
+  for (int i = 1; i <= num; ++i) {
+    EXPECT_TRUE(m.Matches(i));
+  }
+  EXPECT_FALSE(m.Matches(num + 1));
+}
+
+// Tests that AnyOf(m1, ..., mn) matches any value that matches at
+// least one of the given matchers.
+TEST(AnyOfTest, MatchesWhenAnyMatches) {
+  Matcher<int> m;
+  m = AnyOf(Le(1), Ge(3));
+  EXPECT_TRUE(m.Matches(1));
+  EXPECT_TRUE(m.Matches(4));
+  EXPECT_FALSE(m.Matches(2));
+
+  m = AnyOf(Lt(0), Eq(1), Eq(2));
+  EXPECT_TRUE(m.Matches(-1));
+  EXPECT_TRUE(m.Matches(1));
+  EXPECT_TRUE(m.Matches(2));
+  EXPECT_FALSE(m.Matches(0));
+
+  m = AnyOf(Lt(0), Eq(1), Eq(2), Eq(3));
+  EXPECT_TRUE(m.Matches(-1));
+  EXPECT_TRUE(m.Matches(1));
+  EXPECT_TRUE(m.Matches(2));
+  EXPECT_TRUE(m.Matches(3));
+  EXPECT_FALSE(m.Matches(0));
+
+  m = AnyOf(Le(0), Gt(10), 3, 5, 7);
+  EXPECT_TRUE(m.Matches(0));
+  EXPECT_TRUE(m.Matches(11));
+  EXPECT_TRUE(m.Matches(3));
+  EXPECT_FALSE(m.Matches(2));
+
+  // The following tests for varying number of sub-matchers. Due to the way
+  // the sub-matchers are handled it is enough to test every sub-matcher once
+  // with sub-matchers using the same matcher type. Varying matcher types are
+  // checked for above.
+  AnyOfMatches(2, AnyOf(1, 2));
+  AnyOfMatches(3, AnyOf(1, 2, 3));
+  AnyOfMatches(4, AnyOf(1, 2, 3, 4));
+  AnyOfMatches(5, AnyOf(1, 2, 3, 4, 5));
+  AnyOfMatches(6, AnyOf(1, 2, 3, 4, 5, 6));
+  AnyOfMatches(7, AnyOf(1, 2, 3, 4, 5, 6, 7));
+  AnyOfMatches(8, AnyOf(1, 2, 3, 4, 5, 6, 7, 8));
+  AnyOfMatches(9, AnyOf(1, 2, 3, 4, 5, 6, 7, 8, 9));
+  AnyOfMatches(10, AnyOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
+}
+
+#if GTEST_LANG_CXX11
+// Tests the variadic version of the AnyOfMatcher.
+TEST(AnyOfTest, VariadicMatchesWhenAnyMatches) {
+  // Also make sure AnyOf is defined in the right namespace and does not depend
+  // on ADL.
+  Matcher<int> m = ::testing::AnyOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
+
+  EXPECT_THAT(Describe(m), EndsWith("or (is equal to 11))))))))))"));
+  AnyOfMatches(11, m);
+  AnyOfMatches(50, AnyOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+                         11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+                         21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+                         31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+                         41, 42, 43, 44, 45, 46, 47, 48, 49, 50));
+}
+
+#endif  // GTEST_LANG_CXX11
+
+// Tests that AnyOf(m1, ..., mn) describes itself properly.
+TEST(AnyOfTest, CanDescribeSelf) {
+  Matcher<int> m;
+  m = AnyOf(Le(1), Ge(3));
+  EXPECT_EQ("(is <= 1) or (is >= 3)",
+            Describe(m));
+
+  m = AnyOf(Lt(0), Eq(1), Eq(2));
+  EXPECT_EQ("(is < 0) or "
+            "((is equal to 1) or (is equal to 2))",
+            Describe(m));
+
+  m = AnyOf(Lt(0), Eq(1), Eq(2), Eq(3));
+  EXPECT_EQ("((is < 0) or "
+            "(is equal to 1)) or "
+            "((is equal to 2) or "
+            "(is equal to 3))",
+            Describe(m));
+
+  m = AnyOf(Le(0), Gt(10), 3, 5, 7);
+  EXPECT_EQ("((is <= 0) or "
+            "(is > 10)) or "
+            "((is equal to 3) or "
+            "((is equal to 5) or "
+            "(is equal to 7)))",
+            Describe(m));
+}
+
+// Tests that AnyOf(m1, ..., mn) describes its negation properly.
+TEST(AnyOfTest, CanDescribeNegation) {
+  Matcher<int> m;
+  m = AnyOf(Le(1), Ge(3));
+  EXPECT_EQ("(isn't <= 1) and (isn't >= 3)",
+            DescribeNegation(m));
+
+  m = AnyOf(Lt(0), Eq(1), Eq(2));
+  EXPECT_EQ("(isn't < 0) and "
+            "((isn't equal to 1) and (isn't equal to 2))",
+            DescribeNegation(m));
+
+  m = AnyOf(Lt(0), Eq(1), Eq(2), Eq(3));
+  EXPECT_EQ("((isn't < 0) and "
+            "(isn't equal to 1)) and "
+            "((isn't equal to 2) and "
+            "(isn't equal to 3))",
+            DescribeNegation(m));
+
+  m = AnyOf(Le(0), Gt(10), 3, 5, 7);
+  EXPECT_EQ("((isn't <= 0) and "
+            "(isn't > 10)) and "
+            "((isn't equal to 3) and "
+            "((isn't equal to 5) and "
+            "(isn't equal to 7)))",
+            DescribeNegation(m));
+}
+
+// Tests that monomorphic matchers are safely cast by the AnyOf matcher.
+TEST(AnyOfTest, AnyOfMatcherSafelyCastsMonomorphicMatchers) {
+  // greater_than_5 and less_than_10 are monomorphic matchers.
+  Matcher<int> greater_than_5 = Gt(5);
+  Matcher<int> less_than_10 = Lt(10);
+
+  Matcher<const int&> m = AnyOf(greater_than_5, less_than_10);
+  Matcher<int&> m2 = AnyOf(greater_than_5, less_than_10);
+  Matcher<int&> m3 = AnyOf(greater_than_5, m2);
+
+  // Tests that EitherOf works when composing itself.
+  Matcher<const int&> m4 = AnyOf(greater_than_5, less_than_10, less_than_10);
+  Matcher<int&> m5 = AnyOf(greater_than_5, less_than_10, less_than_10);
+}
+
+TEST(AnyOfTest, ExplainsResult) {
+  Matcher<int> m;
+
+  // Failed match.  Both matchers need to explain.  The second
+  // matcher doesn't give an explanation, so only the first matcher's
+  // explanation is printed.
+  m = AnyOf(GreaterThan(10), Lt(0));
+  EXPECT_EQ("which is 5 less than 10", Explain(m, 5));
+
+  // Failed match.  Both matchers need to explain.
+  m = AnyOf(GreaterThan(10), GreaterThan(20));
+  EXPECT_EQ("which is 5 less than 10, and which is 15 less than 20",
+            Explain(m, 5));
+
+  // Failed match.  All matchers need to explain.  The second
+  // matcher doesn't given an explanation.
+  m = AnyOf(GreaterThan(10), Gt(20), GreaterThan(30));
+  EXPECT_EQ("which is 5 less than 10, and which is 25 less than 30",
+            Explain(m, 5));
+
+  // Failed match.  All matchers need to explain.
+  m = AnyOf(GreaterThan(10), GreaterThan(20), GreaterThan(30));
+  EXPECT_EQ("which is 5 less than 10, and which is 15 less than 20, "
+            "and which is 25 less than 30",
+            Explain(m, 5));
+
+  // Successful match.  The first matcher, which succeeded, needs to
+  // explain.
+  m = AnyOf(GreaterThan(10), GreaterThan(20));
+  EXPECT_EQ("which is 5 more than 10", Explain(m, 15));
+
+  // Successful match.  The second matcher, which succeeded, needs to
+  // explain.  Since it doesn't given an explanation, nothing is
+  // printed.
+  m = AnyOf(GreaterThan(10), Lt(30));
+  EXPECT_EQ("", Explain(m, 0));
+
+  // Successful match.  The second matcher, which succeeded, needs to
+  // explain.
+  m = AnyOf(GreaterThan(30), GreaterThan(20));
+  EXPECT_EQ("which is 5 more than 20", Explain(m, 25));
+}
+
+// The following predicate function and predicate functor are for
+// testing the Truly(predicate) matcher.
+
+// Returns non-zero if the input is positive.  Note that the return
+// type of this function is not bool.  It's OK as Truly() accepts any
+// unary function or functor whose return type can be implicitly
+// converted to bool.
+int IsPositive(double x) {
+  return x > 0 ? 1 : 0;
+}
+
+// This functor returns true if the input is greater than the given
+// number.
+class IsGreaterThan {
+ public:
+  explicit IsGreaterThan(int threshold) : threshold_(threshold) {}
+
+  bool operator()(int n) const { return n > threshold_; }
+
+ private:
+  int threshold_;
+};
+
+// For testing Truly().
+const int foo = 0;
+
+// This predicate returns true iff the argument references foo and has
+// a zero value.
+bool ReferencesFooAndIsZero(const int& n) {
+  return (&n == &foo) && (n == 0);
+}
+
+// Tests that Truly(predicate) matches what satisfies the given
+// predicate.
+TEST(TrulyTest, MatchesWhatSatisfiesThePredicate) {
+  Matcher<double> m = Truly(IsPositive);
+  EXPECT_TRUE(m.Matches(2.0));
+  EXPECT_FALSE(m.Matches(-1.5));
+}
+
+// Tests that Truly(predicate_functor) works too.
+TEST(TrulyTest, CanBeUsedWithFunctor) {
+  Matcher<int> m = Truly(IsGreaterThan(5));
+  EXPECT_TRUE(m.Matches(6));
+  EXPECT_FALSE(m.Matches(4));
+}
+
+// A class that can be implicitly converted to bool.
+class ConvertibleToBool {
+ public:
+  explicit ConvertibleToBool(int number) : number_(number) {}
+  operator bool() const { return number_ != 0; }
+
+ private:
+  int number_;
+};
+
+ConvertibleToBool IsNotZero(int number) {
+  return ConvertibleToBool(number);
+}
+
+// Tests that the predicate used in Truly() may return a class that's
+// implicitly convertible to bool, even when the class has no
+// operator!().
+TEST(TrulyTest, PredicateCanReturnAClassConvertibleToBool) {
+  Matcher<int> m = Truly(IsNotZero);
+  EXPECT_TRUE(m.Matches(1));
+  EXPECT_FALSE(m.Matches(0));
+}
+
+// Tests that Truly(predicate) can describe itself properly.
+TEST(TrulyTest, CanDescribeSelf) {
+  Matcher<double> m = Truly(IsPositive);
+  EXPECT_EQ("satisfies the given predicate",
+            Describe(m));
+}
+
+// Tests that Truly(predicate) works when the matcher takes its
+// argument by reference.
+TEST(TrulyTest, WorksForByRefArguments) {
+  Matcher<const int&> m = Truly(ReferencesFooAndIsZero);
+  EXPECT_TRUE(m.Matches(foo));
+  int n = 0;
+  EXPECT_FALSE(m.Matches(n));
+}
+
+// Tests that Matches(m) is a predicate satisfied by whatever that
+// matches matcher m.
+TEST(MatchesTest, IsSatisfiedByWhatMatchesTheMatcher) {
+  EXPECT_TRUE(Matches(Ge(0))(1));
+  EXPECT_FALSE(Matches(Eq('a'))('b'));
+}
+
+// Tests that Matches(m) works when the matcher takes its argument by
+// reference.
+TEST(MatchesTest, WorksOnByRefArguments) {
+  int m = 0, n = 0;
+  EXPECT_TRUE(Matches(AllOf(Ref(n), Eq(0)))(n));
+  EXPECT_FALSE(Matches(Ref(m))(n));
+}
+
+// Tests that a Matcher on non-reference type can be used in
+// Matches().
+TEST(MatchesTest, WorksWithMatcherOnNonRefType) {
+  Matcher<int> eq5 = Eq(5);
+  EXPECT_TRUE(Matches(eq5)(5));
+  EXPECT_FALSE(Matches(eq5)(2));
+}
+
+// Tests Value(value, matcher).  Since Value() is a simple wrapper for
+// Matches(), which has been tested already, we don't spend a lot of
+// effort on testing Value().
+TEST(ValueTest, WorksWithPolymorphicMatcher) {
+  EXPECT_TRUE(Value("hi", StartsWith("h")));
+  EXPECT_FALSE(Value(5, Gt(10)));
+}
+
+TEST(ValueTest, WorksWithMonomorphicMatcher) {
+  const Matcher<int> is_zero = Eq(0);
+  EXPECT_TRUE(Value(0, is_zero));
+  EXPECT_FALSE(Value('a', is_zero));
+
+  int n = 0;
+  const Matcher<const int&> ref_n = Ref(n);
+  EXPECT_TRUE(Value(n, ref_n));
+  EXPECT_FALSE(Value(1, ref_n));
+}
+
+TEST(ExplainMatchResultTest, WorksWithPolymorphicMatcher) {
+  StringMatchResultListener listener1;
+  EXPECT_TRUE(ExplainMatchResult(PolymorphicIsEven(), 42, &listener1));
+  EXPECT_EQ("% 2 == 0", listener1.str());
+
+  StringMatchResultListener listener2;
+  EXPECT_FALSE(ExplainMatchResult(Ge(42), 1.5, &listener2));
+  EXPECT_EQ("", listener2.str());
+}
+
+TEST(ExplainMatchResultTest, WorksWithMonomorphicMatcher) {
+  const Matcher<int> is_even = PolymorphicIsEven();
+  StringMatchResultListener listener1;
+  EXPECT_TRUE(ExplainMatchResult(is_even, 42, &listener1));
+  EXPECT_EQ("% 2 == 0", listener1.str());
+
+  const Matcher<const double&> is_zero = Eq(0);
+  StringMatchResultListener listener2;
+  EXPECT_FALSE(ExplainMatchResult(is_zero, 1.5, &listener2));
+  EXPECT_EQ("", listener2.str());
+}
+
+MATCHER_P(Really, inner_matcher, "") {
+  return ExplainMatchResult(inner_matcher, arg, result_listener);
+}
+
+TEST(ExplainMatchResultTest, WorksInsideMATCHER) {
+  EXPECT_THAT(0, Really(Eq(0)));
+}
+
+TEST(AllArgsTest, WorksForTuple) {
+  EXPECT_THAT(make_tuple(1, 2L), AllArgs(Lt()));
+  EXPECT_THAT(make_tuple(2L, 1), Not(AllArgs(Lt())));
+}
+
+TEST(AllArgsTest, WorksForNonTuple) {
+  EXPECT_THAT(42, AllArgs(Gt(0)));
+  EXPECT_THAT('a', Not(AllArgs(Eq('b'))));
+}
+
+class AllArgsHelper {
+ public:
+  AllArgsHelper() {}
+
+  MOCK_METHOD2(Helper, int(char x, int y));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(AllArgsHelper);
+};
+
+TEST(AllArgsTest, WorksInWithClause) {
+  AllArgsHelper helper;
+  ON_CALL(helper, Helper(_, _))
+      .With(AllArgs(Lt()))
+      .WillByDefault(Return(1));
+  EXPECT_CALL(helper, Helper(_, _));
+  EXPECT_CALL(helper, Helper(_, _))
+      .With(AllArgs(Gt()))
+      .WillOnce(Return(2));
+
+  EXPECT_EQ(1, helper.Helper('\1', 2));
+  EXPECT_EQ(2, helper.Helper('a', 1));
+}
+
+// Tests that ASSERT_THAT() and EXPECT_THAT() work when the value
+// matches the matcher.
+TEST(MatcherAssertionTest, WorksWhenMatcherIsSatisfied) {
+  ASSERT_THAT(5, Ge(2)) << "This should succeed.";
+  ASSERT_THAT("Foo", EndsWith("oo"));
+  EXPECT_THAT(2, AllOf(Le(7), Ge(0))) << "This should succeed too.";
+  EXPECT_THAT("Hello", StartsWith("Hell"));
+}
+
+// Tests that ASSERT_THAT() and EXPECT_THAT() work when the value
+// doesn't match the matcher.
+TEST(MatcherAssertionTest, WorksWhenMatcherIsNotSatisfied) {
+  // 'n' must be static as it is used in an EXPECT_FATAL_FAILURE(),
+  // which cannot reference auto variables.
+  static unsigned short n;  // NOLINT
+  n = 5;
+
+  // VC++ prior to version 8.0 SP1 has a bug where it will not see any
+  // functions declared in the namespace scope from within nested classes.
+  // EXPECT/ASSERT_(NON)FATAL_FAILURE macros use nested classes so that all
+  // namespace-level functions invoked inside them need to be explicitly
+  // resolved.
+  EXPECT_FATAL_FAILURE(ASSERT_THAT(n, ::testing::Gt(10)),
+                       "Value of: n\n"
+                       "Expected: is > 10\n"
+                       "  Actual: 5" + OfType("unsigned short"));
+  n = 0;
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_THAT(n, ::testing::AllOf(::testing::Le(7), ::testing::Ge(5))),
+      "Value of: n\n"
+      "Expected: (is <= 7) and (is >= 5)\n"
+      "  Actual: 0" + OfType("unsigned short"));
+}
+
+// Tests that ASSERT_THAT() and EXPECT_THAT() work when the argument
+// has a reference type.
+TEST(MatcherAssertionTest, WorksForByRefArguments) {
+  // We use a static variable here as EXPECT_FATAL_FAILURE() cannot
+  // reference auto variables.
+  static int n;
+  n = 0;
+  EXPECT_THAT(n, AllOf(Le(7), Ref(n)));
+  EXPECT_FATAL_FAILURE(ASSERT_THAT(n, ::testing::Not(::testing::Ref(n))),
+                       "Value of: n\n"
+                       "Expected: does not reference the variable @");
+  // Tests the "Actual" part.
+  EXPECT_FATAL_FAILURE(ASSERT_THAT(n, ::testing::Not(::testing::Ref(n))),
+                       "Actual: 0" + OfType("int") + ", which is located @");
+}
+
+#if !GTEST_OS_SYMBIAN
+// Tests that ASSERT_THAT() and EXPECT_THAT() work when the matcher is
+// monomorphic.
+
+// ASSERT_THAT("hello", starts_with_he) fails to compile with Nokia's
+// Symbian compiler: it tries to compile
+// template<T, U> class MatcherCastImpl { ...
+//   virtual bool MatchAndExplain(T x, ...) const {
+//     return source_matcher_.MatchAndExplain(static_cast<U>(x), ...);
+// with U == string and T == const char*
+// With ASSERT_THAT("hello"...) changed to ASSERT_THAT(string("hello") ... )
+// the compiler silently crashes with no output.
+// If MatcherCastImpl is changed to use U(x) instead of static_cast<U>(x)
+// the code compiles but the converted string is bogus.
+TEST(MatcherAssertionTest, WorksForMonomorphicMatcher) {
+  Matcher<const char*> starts_with_he = StartsWith("he");
+  ASSERT_THAT("hello", starts_with_he);
+
+  Matcher<const string&> ends_with_ok = EndsWith("ok");
+  ASSERT_THAT("book", ends_with_ok);
+  const string bad = "bad";
+  EXPECT_NONFATAL_FAILURE(EXPECT_THAT(bad, ends_with_ok),
+                          "Value of: bad\n"
+                          "Expected: ends with \"ok\"\n"
+                          "  Actual: \"bad\"");
+  Matcher<int> is_greater_than_5 = Gt(5);
+  EXPECT_NONFATAL_FAILURE(EXPECT_THAT(5, is_greater_than_5),
+                          "Value of: 5\n"
+                          "Expected: is > 5\n"
+                          "  Actual: 5" + OfType("int"));
+}
+#endif  // !GTEST_OS_SYMBIAN
+
+// Tests floating-point matchers.
+template <typename RawType>
+class FloatingPointTest : public testing::Test {
+ protected:
+  typedef testing::internal::FloatingPoint<RawType> Floating;
+  typedef typename Floating::Bits Bits;
+
+  FloatingPointTest()
+      : max_ulps_(Floating::kMaxUlps),
+        zero_bits_(Floating(0).bits()),
+        one_bits_(Floating(1).bits()),
+        infinity_bits_(Floating(Floating::Infinity()).bits()),
+        close_to_positive_zero_(
+            Floating::ReinterpretBits(zero_bits_ + max_ulps_/2)),
+        close_to_negative_zero_(
+            -Floating::ReinterpretBits(zero_bits_ + max_ulps_ - max_ulps_/2)),
+        further_from_negative_zero_(-Floating::ReinterpretBits(
+            zero_bits_ + max_ulps_ + 1 - max_ulps_/2)),
+        close_to_one_(Floating::ReinterpretBits(one_bits_ + max_ulps_)),
+        further_from_one_(Floating::ReinterpretBits(one_bits_ + max_ulps_ + 1)),
+        infinity_(Floating::Infinity()),
+        close_to_infinity_(
+            Floating::ReinterpretBits(infinity_bits_ - max_ulps_)),
+        further_from_infinity_(
+            Floating::ReinterpretBits(infinity_bits_ - max_ulps_ - 1)),
+        max_(Floating::Max()),
+        nan1_(Floating::ReinterpretBits(Floating::kExponentBitMask | 1)),
+        nan2_(Floating::ReinterpretBits(Floating::kExponentBitMask | 200)) {
+  }
+
+  void TestSize() {
+    EXPECT_EQ(sizeof(RawType), sizeof(Bits));
+  }
+
+  // A battery of tests for FloatingEqMatcher::Matches.
+  // matcher_maker is a pointer to a function which creates a FloatingEqMatcher.
+  void TestMatches(
+      testing::internal::FloatingEqMatcher<RawType> (*matcher_maker)(RawType)) {
+    Matcher<RawType> m1 = matcher_maker(0.0);
+    EXPECT_TRUE(m1.Matches(-0.0));
+    EXPECT_TRUE(m1.Matches(close_to_positive_zero_));
+    EXPECT_TRUE(m1.Matches(close_to_negative_zero_));
+    EXPECT_FALSE(m1.Matches(1.0));
+
+    Matcher<RawType> m2 = matcher_maker(close_to_positive_zero_);
+    EXPECT_FALSE(m2.Matches(further_from_negative_zero_));
+
+    Matcher<RawType> m3 = matcher_maker(1.0);
+    EXPECT_TRUE(m3.Matches(close_to_one_));
+    EXPECT_FALSE(m3.Matches(further_from_one_));
+
+    // Test commutativity: matcher_maker(0.0).Matches(1.0) was tested above.
+    EXPECT_FALSE(m3.Matches(0.0));
+
+    Matcher<RawType> m4 = matcher_maker(-infinity_);
+    EXPECT_TRUE(m4.Matches(-close_to_infinity_));
+
+    Matcher<RawType> m5 = matcher_maker(infinity_);
+    EXPECT_TRUE(m5.Matches(close_to_infinity_));
+
+    // This is interesting as the representations of infinity_ and nan1_
+    // are only 1 DLP apart.
+    EXPECT_FALSE(m5.Matches(nan1_));
+
+    // matcher_maker can produce a Matcher<const RawType&>, which is needed in
+    // some cases.
+    Matcher<const RawType&> m6 = matcher_maker(0.0);
+    EXPECT_TRUE(m6.Matches(-0.0));
+    EXPECT_TRUE(m6.Matches(close_to_positive_zero_));
+    EXPECT_FALSE(m6.Matches(1.0));
+
+    // matcher_maker can produce a Matcher<RawType&>, which is needed in some
+    // cases.
+    Matcher<RawType&> m7 = matcher_maker(0.0);
+    RawType x = 0.0;
+    EXPECT_TRUE(m7.Matches(x));
+    x = 0.01f;
+    EXPECT_FALSE(m7.Matches(x));
+  }
+
+  // Pre-calculated numbers to be used by the tests.
+
+  const size_t max_ulps_;
+
+  const Bits zero_bits_;  // The bits that represent 0.0.
+  const Bits one_bits_;  // The bits that represent 1.0.
+  const Bits infinity_bits_;  // The bits that represent +infinity.
+
+  // Some numbers close to 0.0.
+  const RawType close_to_positive_zero_;
+  const RawType close_to_negative_zero_;
+  const RawType further_from_negative_zero_;
+
+  // Some numbers close to 1.0.
+  const RawType close_to_one_;
+  const RawType further_from_one_;
+
+  // Some numbers close to +infinity.
+  const RawType infinity_;
+  const RawType close_to_infinity_;
+  const RawType further_from_infinity_;
+
+  // Maximum representable value that's not infinity.
+  const RawType max_;
+
+  // Some NaNs.
+  const RawType nan1_;
+  const RawType nan2_;
+};
+
+// Tests floating-point matchers with fixed epsilons.
+template <typename RawType>
+class FloatingPointNearTest : public FloatingPointTest<RawType> {
+ protected:
+  typedef FloatingPointTest<RawType> ParentType;
+
+  // A battery of tests for FloatingEqMatcher::Matches with a fixed epsilon.
+  // matcher_maker is a pointer to a function which creates a FloatingEqMatcher.
+  void TestNearMatches(
+      testing::internal::FloatingEqMatcher<RawType>
+          (*matcher_maker)(RawType, RawType)) {
+    Matcher<RawType> m1 = matcher_maker(0.0, 0.0);
+    EXPECT_TRUE(m1.Matches(0.0));
+    EXPECT_TRUE(m1.Matches(-0.0));
+    EXPECT_FALSE(m1.Matches(ParentType::close_to_positive_zero_));
+    EXPECT_FALSE(m1.Matches(ParentType::close_to_negative_zero_));
+    EXPECT_FALSE(m1.Matches(1.0));
+
+    Matcher<RawType> m2 = matcher_maker(0.0, 1.0);
+    EXPECT_TRUE(m2.Matches(0.0));
+    EXPECT_TRUE(m2.Matches(-0.0));
+    EXPECT_TRUE(m2.Matches(1.0));
+    EXPECT_TRUE(m2.Matches(-1.0));
+    EXPECT_FALSE(m2.Matches(ParentType::close_to_one_));
+    EXPECT_FALSE(m2.Matches(-ParentType::close_to_one_));
+
+    // Check that inf matches inf, regardless of the of the specified max
+    // absolute error.
+    Matcher<RawType> m3 = matcher_maker(ParentType::infinity_, 0.0);
+    EXPECT_TRUE(m3.Matches(ParentType::infinity_));
+    EXPECT_FALSE(m3.Matches(ParentType::close_to_infinity_));
+    EXPECT_FALSE(m3.Matches(-ParentType::infinity_));
+
+    Matcher<RawType> m4 = matcher_maker(-ParentType::infinity_, 0.0);
+    EXPECT_TRUE(m4.Matches(-ParentType::infinity_));
+    EXPECT_FALSE(m4.Matches(-ParentType::close_to_infinity_));
+    EXPECT_FALSE(m4.Matches(ParentType::infinity_));
+
+    // Test various overflow scenarios.
+    Matcher<RawType> m5 = matcher_maker(ParentType::max_, ParentType::max_);
+    EXPECT_TRUE(m5.Matches(ParentType::max_));
+    EXPECT_FALSE(m5.Matches(-ParentType::max_));
+
+    Matcher<RawType> m6 = matcher_maker(-ParentType::max_, ParentType::max_);
+    EXPECT_FALSE(m6.Matches(ParentType::max_));
+    EXPECT_TRUE(m6.Matches(-ParentType::max_));
+
+    Matcher<RawType> m7 = matcher_maker(ParentType::max_, 0);
+    EXPECT_TRUE(m7.Matches(ParentType::max_));
+    EXPECT_FALSE(m7.Matches(-ParentType::max_));
+
+    Matcher<RawType> m8 = matcher_maker(-ParentType::max_, 0);
+    EXPECT_FALSE(m8.Matches(ParentType::max_));
+    EXPECT_TRUE(m8.Matches(-ParentType::max_));
+
+    // The difference between max() and -max() normally overflows to infinity,
+    // but it should still match if the max_abs_error is also infinity.
+    Matcher<RawType> m9 = matcher_maker(
+        ParentType::max_, ParentType::infinity_);
+    EXPECT_TRUE(m8.Matches(-ParentType::max_));
+
+    // matcher_maker can produce a Matcher<const RawType&>, which is needed in
+    // some cases.
+    Matcher<const RawType&> m10 = matcher_maker(0.0, 1.0);
+    EXPECT_TRUE(m10.Matches(-0.0));
+    EXPECT_TRUE(m10.Matches(ParentType::close_to_positive_zero_));
+    EXPECT_FALSE(m10.Matches(ParentType::close_to_one_));
+
+    // matcher_maker can produce a Matcher<RawType&>, which is needed in some
+    // cases.
+    Matcher<RawType&> m11 = matcher_maker(0.0, 1.0);
+    RawType x = 0.0;
+    EXPECT_TRUE(m11.Matches(x));
+    x = 1.0f;
+    EXPECT_TRUE(m11.Matches(x));
+    x = -1.0f;
+    EXPECT_TRUE(m11.Matches(x));
+    x = 1.1f;
+    EXPECT_FALSE(m11.Matches(x));
+    x = -1.1f;
+    EXPECT_FALSE(m11.Matches(x));
+  }
+};
+
+// Instantiate FloatingPointTest for testing floats.
+typedef FloatingPointTest<float> FloatTest;
+
+TEST_F(FloatTest, FloatEqApproximatelyMatchesFloats) {
+  TestMatches(&FloatEq);
+}
+
+TEST_F(FloatTest, NanSensitiveFloatEqApproximatelyMatchesFloats) {
+  TestMatches(&NanSensitiveFloatEq);
+}
+
+TEST_F(FloatTest, FloatEqCannotMatchNaN) {
+  // FloatEq never matches NaN.
+  Matcher<float> m = FloatEq(nan1_);
+  EXPECT_FALSE(m.Matches(nan1_));
+  EXPECT_FALSE(m.Matches(nan2_));
+  EXPECT_FALSE(m.Matches(1.0));
+}
+
+TEST_F(FloatTest, NanSensitiveFloatEqCanMatchNaN) {
+  // NanSensitiveFloatEq will match NaN.
+  Matcher<float> m = NanSensitiveFloatEq(nan1_);
+  EXPECT_TRUE(m.Matches(nan1_));
+  EXPECT_TRUE(m.Matches(nan2_));
+  EXPECT_FALSE(m.Matches(1.0));
+}
+
+TEST_F(FloatTest, FloatEqCanDescribeSelf) {
+  Matcher<float> m1 = FloatEq(2.0f);
+  EXPECT_EQ("is approximately 2", Describe(m1));
+  EXPECT_EQ("isn't approximately 2", DescribeNegation(m1));
+
+  Matcher<float> m2 = FloatEq(0.5f);
+  EXPECT_EQ("is approximately 0.5", Describe(m2));
+  EXPECT_EQ("isn't approximately 0.5", DescribeNegation(m2));
+
+  Matcher<float> m3 = FloatEq(nan1_);
+  EXPECT_EQ("never matches", Describe(m3));
+  EXPECT_EQ("is anything", DescribeNegation(m3));
+}
+
+TEST_F(FloatTest, NanSensitiveFloatEqCanDescribeSelf) {
+  Matcher<float> m1 = NanSensitiveFloatEq(2.0f);
+  EXPECT_EQ("is approximately 2", Describe(m1));
+  EXPECT_EQ("isn't approximately 2", DescribeNegation(m1));
+
+  Matcher<float> m2 = NanSensitiveFloatEq(0.5f);
+  EXPECT_EQ("is approximately 0.5", Describe(m2));
+  EXPECT_EQ("isn't approximately 0.5", DescribeNegation(m2));
+
+  Matcher<float> m3 = NanSensitiveFloatEq(nan1_);
+  EXPECT_EQ("is NaN", Describe(m3));
+  EXPECT_EQ("isn't NaN", DescribeNegation(m3));
+}
+
+// Instantiate FloatingPointTest for testing floats with a user-specified
+// max absolute error.
+typedef FloatingPointNearTest<float> FloatNearTest;
+
+TEST_F(FloatNearTest, FloatNearMatches) {
+  TestNearMatches(&FloatNear);
+}
+
+TEST_F(FloatNearTest, NanSensitiveFloatNearApproximatelyMatchesFloats) {
+  TestNearMatches(&NanSensitiveFloatNear);
+}
+
+TEST_F(FloatNearTest, FloatNearCanDescribeSelf) {
+  Matcher<float> m1 = FloatNear(2.0f, 0.5f);
+  EXPECT_EQ("is approximately 2 (absolute error <= 0.5)", Describe(m1));
+  EXPECT_EQ(
+      "isn't approximately 2 (absolute error > 0.5)", DescribeNegation(m1));
+
+  Matcher<float> m2 = FloatNear(0.5f, 0.5f);
+  EXPECT_EQ("is approximately 0.5 (absolute error <= 0.5)", Describe(m2));
+  EXPECT_EQ(
+      "isn't approximately 0.5 (absolute error > 0.5)", DescribeNegation(m2));
+
+  Matcher<float> m3 = FloatNear(nan1_, 0.0);
+  EXPECT_EQ("never matches", Describe(m3));
+  EXPECT_EQ("is anything", DescribeNegation(m3));
+}
+
+TEST_F(FloatNearTest, NanSensitiveFloatNearCanDescribeSelf) {
+  Matcher<float> m1 = NanSensitiveFloatNear(2.0f, 0.5f);
+  EXPECT_EQ("is approximately 2 (absolute error <= 0.5)", Describe(m1));
+  EXPECT_EQ(
+      "isn't approximately 2 (absolute error > 0.5)", DescribeNegation(m1));
+
+  Matcher<float> m2 = NanSensitiveFloatNear(0.5f, 0.5f);
+  EXPECT_EQ("is approximately 0.5 (absolute error <= 0.5)", Describe(m2));
+  EXPECT_EQ(
+      "isn't approximately 0.5 (absolute error > 0.5)", DescribeNegation(m2));
+
+  Matcher<float> m3 = NanSensitiveFloatNear(nan1_, 0.1f);
+  EXPECT_EQ("is NaN", Describe(m3));
+  EXPECT_EQ("isn't NaN", DescribeNegation(m3));
+}
+
+TEST_F(FloatNearTest, FloatNearCannotMatchNaN) {
+  // FloatNear never matches NaN.
+  Matcher<float> m = FloatNear(ParentType::nan1_, 0.1f);
+  EXPECT_FALSE(m.Matches(nan1_));
+  EXPECT_FALSE(m.Matches(nan2_));
+  EXPECT_FALSE(m.Matches(1.0));
+}
+
+TEST_F(FloatNearTest, NanSensitiveFloatNearCanMatchNaN) {
+  // NanSensitiveFloatNear will match NaN.
+  Matcher<float> m = NanSensitiveFloatNear(nan1_, 0.1f);
+  EXPECT_TRUE(m.Matches(nan1_));
+  EXPECT_TRUE(m.Matches(nan2_));
+  EXPECT_FALSE(m.Matches(1.0));
+}
+
+// Instantiate FloatingPointTest for testing doubles.
+typedef FloatingPointTest<double> DoubleTest;
+
+TEST_F(DoubleTest, DoubleEqApproximatelyMatchesDoubles) {
+  TestMatches(&DoubleEq);
+}
+
+TEST_F(DoubleTest, NanSensitiveDoubleEqApproximatelyMatchesDoubles) {
+  TestMatches(&NanSensitiveDoubleEq);
+}
+
+TEST_F(DoubleTest, DoubleEqCannotMatchNaN) {
+  // DoubleEq never matches NaN.
+  Matcher<double> m = DoubleEq(nan1_);
+  EXPECT_FALSE(m.Matches(nan1_));
+  EXPECT_FALSE(m.Matches(nan2_));
+  EXPECT_FALSE(m.Matches(1.0));
+}
+
+TEST_F(DoubleTest, NanSensitiveDoubleEqCanMatchNaN) {
+  // NanSensitiveDoubleEq will match NaN.
+  Matcher<double> m = NanSensitiveDoubleEq(nan1_);
+  EXPECT_TRUE(m.Matches(nan1_));
+  EXPECT_TRUE(m.Matches(nan2_));
+  EXPECT_FALSE(m.Matches(1.0));
+}
+
+TEST_F(DoubleTest, DoubleEqCanDescribeSelf) {
+  Matcher<double> m1 = DoubleEq(2.0);
+  EXPECT_EQ("is approximately 2", Describe(m1));
+  EXPECT_EQ("isn't approximately 2", DescribeNegation(m1));
+
+  Matcher<double> m2 = DoubleEq(0.5);
+  EXPECT_EQ("is approximately 0.5", Describe(m2));
+  EXPECT_EQ("isn't approximately 0.5", DescribeNegation(m2));
+
+  Matcher<double> m3 = DoubleEq(nan1_);
+  EXPECT_EQ("never matches", Describe(m3));
+  EXPECT_EQ("is anything", DescribeNegation(m3));
+}
+
+TEST_F(DoubleTest, NanSensitiveDoubleEqCanDescribeSelf) {
+  Matcher<double> m1 = NanSensitiveDoubleEq(2.0);
+  EXPECT_EQ("is approximately 2", Describe(m1));
+  EXPECT_EQ("isn't approximately 2", DescribeNegation(m1));
+
+  Matcher<double> m2 = NanSensitiveDoubleEq(0.5);
+  EXPECT_EQ("is approximately 0.5", Describe(m2));
+  EXPECT_EQ("isn't approximately 0.5", DescribeNegation(m2));
+
+  Matcher<double> m3 = NanSensitiveDoubleEq(nan1_);
+  EXPECT_EQ("is NaN", Describe(m3));
+  EXPECT_EQ("isn't NaN", DescribeNegation(m3));
+}
+
+// Instantiate FloatingPointTest for testing floats with a user-specified
+// max absolute error.
+typedef FloatingPointNearTest<double> DoubleNearTest;
+
+TEST_F(DoubleNearTest, DoubleNearMatches) {
+  TestNearMatches(&DoubleNear);
+}
+
+TEST_F(DoubleNearTest, NanSensitiveDoubleNearApproximatelyMatchesDoubles) {
+  TestNearMatches(&NanSensitiveDoubleNear);
+}
+
+TEST_F(DoubleNearTest, DoubleNearCanDescribeSelf) {
+  Matcher<double> m1 = DoubleNear(2.0, 0.5);
+  EXPECT_EQ("is approximately 2 (absolute error <= 0.5)", Describe(m1));
+  EXPECT_EQ(
+      "isn't approximately 2 (absolute error > 0.5)", DescribeNegation(m1));
+
+  Matcher<double> m2 = DoubleNear(0.5, 0.5);
+  EXPECT_EQ("is approximately 0.5 (absolute error <= 0.5)", Describe(m2));
+  EXPECT_EQ(
+      "isn't approximately 0.5 (absolute error > 0.5)", DescribeNegation(m2));
+
+  Matcher<double> m3 = DoubleNear(nan1_, 0.0);
+  EXPECT_EQ("never matches", Describe(m3));
+  EXPECT_EQ("is anything", DescribeNegation(m3));
+}
+
+TEST_F(DoubleNearTest, ExplainsResultWhenMatchFails) {
+  EXPECT_EQ("", Explain(DoubleNear(2.0, 0.1), 2.05));
+  EXPECT_EQ("which is 0.2 from 2", Explain(DoubleNear(2.0, 0.1), 2.2));
+  EXPECT_EQ("which is -0.3 from 2", Explain(DoubleNear(2.0, 0.1), 1.7));
+
+  const string explanation = Explain(DoubleNear(2.1, 1e-10), 2.1 + 1.2e-10);
+  // Different C++ implementations may print floating-point numbers
+  // slightly differently.
+  EXPECT_TRUE(explanation == "which is 1.2e-10 from 2.1" ||  // GCC
+              explanation == "which is 1.2e-010 from 2.1")   // MSVC
+      << " where explanation is \"" << explanation << "\".";
+}
+
+TEST_F(DoubleNearTest, NanSensitiveDoubleNearCanDescribeSelf) {
+  Matcher<double> m1 = NanSensitiveDoubleNear(2.0, 0.5);
+  EXPECT_EQ("is approximately 2 (absolute error <= 0.5)", Describe(m1));
+  EXPECT_EQ(
+      "isn't approximately 2 (absolute error > 0.5)", DescribeNegation(m1));
+
+  Matcher<double> m2 = NanSensitiveDoubleNear(0.5, 0.5);
+  EXPECT_EQ("is approximately 0.5 (absolute error <= 0.5)", Describe(m2));
+  EXPECT_EQ(
+      "isn't approximately 0.5 (absolute error > 0.5)", DescribeNegation(m2));
+
+  Matcher<double> m3 = NanSensitiveDoubleNear(nan1_, 0.1);
+  EXPECT_EQ("is NaN", Describe(m3));
+  EXPECT_EQ("isn't NaN", DescribeNegation(m3));
+}
+
+TEST_F(DoubleNearTest, DoubleNearCannotMatchNaN) {
+  // DoubleNear never matches NaN.
+  Matcher<double> m = DoubleNear(ParentType::nan1_, 0.1);
+  EXPECT_FALSE(m.Matches(nan1_));
+  EXPECT_FALSE(m.Matches(nan2_));
+  EXPECT_FALSE(m.Matches(1.0));
+}
+
+TEST_F(DoubleNearTest, NanSensitiveDoubleNearCanMatchNaN) {
+  // NanSensitiveDoubleNear will match NaN.
+  Matcher<double> m = NanSensitiveDoubleNear(nan1_, 0.1);
+  EXPECT_TRUE(m.Matches(nan1_));
+  EXPECT_TRUE(m.Matches(nan2_));
+  EXPECT_FALSE(m.Matches(1.0));
+}
+
+TEST(PointeeTest, RawPointer) {
+  const Matcher<int*> m = Pointee(Ge(0));
+
+  int n = 1;
+  EXPECT_TRUE(m.Matches(&n));
+  n = -1;
+  EXPECT_FALSE(m.Matches(&n));
+  EXPECT_FALSE(m.Matches(NULL));
+}
+
+TEST(PointeeTest, RawPointerToConst) {
+  const Matcher<const double*> m = Pointee(Ge(0));
+
+  double x = 1;
+  EXPECT_TRUE(m.Matches(&x));
+  x = -1;
+  EXPECT_FALSE(m.Matches(&x));
+  EXPECT_FALSE(m.Matches(NULL));
+}
+
+TEST(PointeeTest, ReferenceToConstRawPointer) {
+  const Matcher<int* const &> m = Pointee(Ge(0));
+
+  int n = 1;
+  EXPECT_TRUE(m.Matches(&n));
+  n = -1;
+  EXPECT_FALSE(m.Matches(&n));
+  EXPECT_FALSE(m.Matches(NULL));
+}
+
+TEST(PointeeTest, ReferenceToNonConstRawPointer) {
+  const Matcher<double* &> m = Pointee(Ge(0));
+
+  double x = 1.0;
+  double* p = &x;
+  EXPECT_TRUE(m.Matches(p));
+  x = -1;
+  EXPECT_FALSE(m.Matches(p));
+  p = NULL;
+  EXPECT_FALSE(m.Matches(p));
+}
+
+MATCHER_P(FieldIIs, inner_matcher, "") {
+  return ExplainMatchResult(inner_matcher, arg.i, result_listener);
+}
+
+TEST(WhenDynamicCastToTest, SameType) {
+  Derived derived;
+  derived.i = 4;
+
+  // Right type. A pointer is passed down.
+  Base* as_base_ptr = &derived;
+  EXPECT_THAT(as_base_ptr, WhenDynamicCastTo<Derived*>(Not(IsNull())));
+  EXPECT_THAT(as_base_ptr, WhenDynamicCastTo<Derived*>(Pointee(FieldIIs(4))));
+  EXPECT_THAT(as_base_ptr,
+              Not(WhenDynamicCastTo<Derived*>(Pointee(FieldIIs(5)))));
+}
+
+TEST(WhenDynamicCastToTest, WrongTypes) {
+  Base base;
+  Derived derived;
+  OtherDerived other_derived;
+
+  // Wrong types. NULL is passed.
+  EXPECT_THAT(&base, Not(WhenDynamicCastTo<Derived*>(Pointee(_))));
+  EXPECT_THAT(&base, WhenDynamicCastTo<Derived*>(IsNull()));
+  Base* as_base_ptr = &derived;
+  EXPECT_THAT(as_base_ptr, Not(WhenDynamicCastTo<OtherDerived*>(Pointee(_))));
+  EXPECT_THAT(as_base_ptr, WhenDynamicCastTo<OtherDerived*>(IsNull()));
+  as_base_ptr = &other_derived;
+  EXPECT_THAT(as_base_ptr, Not(WhenDynamicCastTo<Derived*>(Pointee(_))));
+  EXPECT_THAT(as_base_ptr, WhenDynamicCastTo<Derived*>(IsNull()));
+}
+
+TEST(WhenDynamicCastToTest, AlreadyNull) {
+  // Already NULL.
+  Base* as_base_ptr = NULL;
+  EXPECT_THAT(as_base_ptr, WhenDynamicCastTo<Derived*>(IsNull()));
+}
+
+struct AmbiguousCastTypes {
+  class VirtualDerived : public virtual Base {};
+  class DerivedSub1 : public VirtualDerived {};
+  class DerivedSub2 : public VirtualDerived {};
+  class ManyDerivedInHierarchy : public DerivedSub1, public DerivedSub2 {};
+};
+
+TEST(WhenDynamicCastToTest, AmbiguousCast) {
+  AmbiguousCastTypes::DerivedSub1 sub1;
+  AmbiguousCastTypes::ManyDerivedInHierarchy many_derived;
+  // Multiply derived from Base. dynamic_cast<> returns NULL.
+  Base* as_base_ptr =
+      static_cast<AmbiguousCastTypes::DerivedSub1*>(&many_derived);
+  EXPECT_THAT(as_base_ptr,
+              WhenDynamicCastTo<AmbiguousCastTypes::VirtualDerived*>(IsNull()));
+  as_base_ptr = &sub1;
+  EXPECT_THAT(
+      as_base_ptr,
+      WhenDynamicCastTo<AmbiguousCastTypes::VirtualDerived*>(Not(IsNull())));
+}
+
+TEST(WhenDynamicCastToTest, Describe) {
+  Matcher<Base*> matcher = WhenDynamicCastTo<Derived*>(Pointee(_));
+#if GTEST_HAS_RTTI
+  const string prefix =
+      "when dynamic_cast to " + internal::GetTypeName<Derived*>() + ", ";
+#else  // GTEST_HAS_RTTI
+  const string prefix = "when dynamic_cast, ";
+#endif  // GTEST_HAS_RTTI
+  EXPECT_EQ(prefix + "points to a value that is anything", Describe(matcher));
+  EXPECT_EQ(prefix + "does not point to a value that is anything",
+            DescribeNegation(matcher));
+}
+
+TEST(WhenDynamicCastToTest, Explain) {
+  Matcher<Base*> matcher = WhenDynamicCastTo<Derived*>(Pointee(_));
+  Base* null = NULL;
+  EXPECT_THAT(Explain(matcher, null), HasSubstr("NULL"));
+  Derived derived;
+  EXPECT_TRUE(matcher.Matches(&derived));
+  EXPECT_THAT(Explain(matcher, &derived), HasSubstr("which points to "));
+
+  // With references, the matcher itself can fail. Test for that one.
+  Matcher<const Base&> ref_matcher = WhenDynamicCastTo<const OtherDerived&>(_);
+  EXPECT_THAT(Explain(ref_matcher, derived),
+              HasSubstr("which cannot be dynamic_cast"));
+}
+
+TEST(WhenDynamicCastToTest, GoodReference) {
+  Derived derived;
+  derived.i = 4;
+  Base& as_base_ref = derived;
+  EXPECT_THAT(as_base_ref, WhenDynamicCastTo<const Derived&>(FieldIIs(4)));
+  EXPECT_THAT(as_base_ref, WhenDynamicCastTo<const Derived&>(Not(FieldIIs(5))));
+}
+
+TEST(WhenDynamicCastToTest, BadReference) {
+  Derived derived;
+  Base& as_base_ref = derived;
+  EXPECT_THAT(as_base_ref, Not(WhenDynamicCastTo<const OtherDerived&>(_)));
+}
+
+// Minimal const-propagating pointer.
+template <typename T>
+class ConstPropagatingPtr {
+ public:
+  typedef T element_type;
+
+  ConstPropagatingPtr() : val_() {}
+  explicit ConstPropagatingPtr(T* t) : val_(t) {}
+  ConstPropagatingPtr(const ConstPropagatingPtr& other) : val_(other.val_) {}
+
+  T* get() { return val_; }
+  T& operator*() { return *val_; }
+  // Most smart pointers return non-const T* and T& from the next methods.
+  const T* get() const { return val_; }
+  const T& operator*() const { return *val_; }
+
+ private:
+  T* val_;
+};
+
+TEST(PointeeTest, WorksWithConstPropagatingPointers) {
+  const Matcher< ConstPropagatingPtr<int> > m = Pointee(Lt(5));
+  int three = 3;
+  const ConstPropagatingPtr<int> co(&three);
+  ConstPropagatingPtr<int> o(&three);
+  EXPECT_TRUE(m.Matches(o));
+  EXPECT_TRUE(m.Matches(co));
+  *o = 6;
+  EXPECT_FALSE(m.Matches(o));
+  EXPECT_FALSE(m.Matches(ConstPropagatingPtr<int>()));
+}
+
+TEST(PointeeTest, NeverMatchesNull) {
+  const Matcher<const char*> m = Pointee(_);
+  EXPECT_FALSE(m.Matches(NULL));
+}
+
+// Tests that we can write Pointee(value) instead of Pointee(Eq(value)).
+TEST(PointeeTest, MatchesAgainstAValue) {
+  const Matcher<int*> m = Pointee(5);
+
+  int n = 5;
+  EXPECT_TRUE(m.Matches(&n));
+  n = -1;
+  EXPECT_FALSE(m.Matches(&n));
+  EXPECT_FALSE(m.Matches(NULL));
+}
+
+TEST(PointeeTest, CanDescribeSelf) {
+  const Matcher<int*> m = Pointee(Gt(3));
+  EXPECT_EQ("points to a value that is > 3", Describe(m));
+  EXPECT_EQ("does not point to a value that is > 3",
+            DescribeNegation(m));
+}
+
+TEST(PointeeTest, CanExplainMatchResult) {
+  const Matcher<const string*> m = Pointee(StartsWith("Hi"));
+
+  EXPECT_EQ("", Explain(m, static_cast<const string*>(NULL)));
+
+  const Matcher<long*> m2 = Pointee(GreaterThan(1));  // NOLINT
+  long n = 3;  // NOLINT
+  EXPECT_EQ("which points to 3" + OfType("long") + ", which is 2 more than 1",
+            Explain(m2, &n));
+}
+
+TEST(PointeeTest, AlwaysExplainsPointee) {
+  const Matcher<int*> m = Pointee(0);
+  int n = 42;
+  EXPECT_EQ("which points to 42" + OfType("int"), Explain(m, &n));
+}
+
+// An uncopyable class.
+class Uncopyable {
+ public:
+  Uncopyable() : value_(-1) {}
+  explicit Uncopyable(int a_value) : value_(a_value) {}
+
+  int value() const { return value_; }
+  void set_value(int i) { value_ = i; }
+
+ private:
+  int value_;
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Uncopyable);
+};
+
+// Returns true iff x.value() is positive.
+bool ValueIsPositive(const Uncopyable& x) { return x.value() > 0; }
+
+MATCHER_P(UncopyableIs, inner_matcher, "") {
+  return ExplainMatchResult(inner_matcher, arg.value(), result_listener);
+}
+
+// A user-defined struct for testing Field().
+struct AStruct {
+  AStruct() : x(0), y(1.0), z(5), p(NULL) {}
+  AStruct(const AStruct& rhs)
+      : x(rhs.x), y(rhs.y), z(rhs.z.value()), p(rhs.p) {}
+
+  int x;           // A non-const field.
+  const double y;  // A const field.
+  Uncopyable z;    // An uncopyable field.
+  const char* p;   // A pointer field.
+
+ private:
+  GTEST_DISALLOW_ASSIGN_(AStruct);
+};
+
+// A derived struct for testing Field().
+struct DerivedStruct : public AStruct {
+  char ch;
+
+ private:
+  GTEST_DISALLOW_ASSIGN_(DerivedStruct);
+};
+
+// Tests that Field(&Foo::field, ...) works when field is non-const.
+TEST(FieldTest, WorksForNonConstField) {
+  Matcher<AStruct> m = Field(&AStruct::x, Ge(0));
+
+  AStruct a;
+  EXPECT_TRUE(m.Matches(a));
+  a.x = -1;
+  EXPECT_FALSE(m.Matches(a));
+}
+
+// Tests that Field(&Foo::field, ...) works when field is const.
+TEST(FieldTest, WorksForConstField) {
+  AStruct a;
+
+  Matcher<AStruct> m = Field(&AStruct::y, Ge(0.0));
+  EXPECT_TRUE(m.Matches(a));
+  m = Field(&AStruct::y, Le(0.0));
+  EXPECT_FALSE(m.Matches(a));
+}
+
+// Tests that Field(&Foo::field, ...) works when field is not copyable.
+TEST(FieldTest, WorksForUncopyableField) {
+  AStruct a;
+
+  Matcher<AStruct> m = Field(&AStruct::z, Truly(ValueIsPositive));
+  EXPECT_TRUE(m.Matches(a));
+  m = Field(&AStruct::z, Not(Truly(ValueIsPositive)));
+  EXPECT_FALSE(m.Matches(a));
+}
+
+// Tests that Field(&Foo::field, ...) works when field is a pointer.
+TEST(FieldTest, WorksForPointerField) {
+  // Matching against NULL.
+  Matcher<AStruct> m = Field(&AStruct::p, static_cast<const char*>(NULL));
+  AStruct a;
+  EXPECT_TRUE(m.Matches(a));
+  a.p = "hi";
+  EXPECT_FALSE(m.Matches(a));
+
+  // Matching a pointer that is not NULL.
+  m = Field(&AStruct::p, StartsWith("hi"));
+  a.p = "hill";
+  EXPECT_TRUE(m.Matches(a));
+  a.p = "hole";
+  EXPECT_FALSE(m.Matches(a));
+}
+
+// Tests that Field() works when the object is passed by reference.
+TEST(FieldTest, WorksForByRefArgument) {
+  Matcher<const AStruct&> m = Field(&AStruct::x, Ge(0));
+
+  AStruct a;
+  EXPECT_TRUE(m.Matches(a));
+  a.x = -1;
+  EXPECT_FALSE(m.Matches(a));
+}
+
+// Tests that Field(&Foo::field, ...) works when the argument's type
+// is a sub-type of Foo.
+TEST(FieldTest, WorksForArgumentOfSubType) {
+  // Note that the matcher expects DerivedStruct but we say AStruct
+  // inside Field().
+  Matcher<const DerivedStruct&> m = Field(&AStruct::x, Ge(0));
+
+  DerivedStruct d;
+  EXPECT_TRUE(m.Matches(d));
+  d.x = -1;
+  EXPECT_FALSE(m.Matches(d));
+}
+
+// Tests that Field(&Foo::field, m) works when field's type and m's
+// argument type are compatible but not the same.
+TEST(FieldTest, WorksForCompatibleMatcherType) {
+  // The field is an int, but the inner matcher expects a signed char.
+  Matcher<const AStruct&> m = Field(&AStruct::x,
+                                    Matcher<signed char>(Ge(0)));
+
+  AStruct a;
+  EXPECT_TRUE(m.Matches(a));
+  a.x = -1;
+  EXPECT_FALSE(m.Matches(a));
+}
+
+// Tests that Field() can describe itself.
+TEST(FieldTest, CanDescribeSelf) {
+  Matcher<const AStruct&> m = Field(&AStruct::x, Ge(0));
+
+  EXPECT_EQ("is an object whose given field is >= 0", Describe(m));
+  EXPECT_EQ("is an object whose given field isn't >= 0", DescribeNegation(m));
+}
+
+// Tests that Field() can explain the match result.
+TEST(FieldTest, CanExplainMatchResult) {
+  Matcher<const AStruct&> m = Field(&AStruct::x, Ge(0));
+
+  AStruct a;
+  a.x = 1;
+  EXPECT_EQ("whose given field is 1" + OfType("int"), Explain(m, a));
+
+  m = Field(&AStruct::x, GreaterThan(0));
+  EXPECT_EQ(
+      "whose given field is 1" + OfType("int") + ", which is 1 more than 0",
+      Explain(m, a));
+}
+
+// Tests that Field() works when the argument is a pointer to const.
+TEST(FieldForPointerTest, WorksForPointerToConst) {
+  Matcher<const AStruct*> m = Field(&AStruct::x, Ge(0));
+
+  AStruct a;
+  EXPECT_TRUE(m.Matches(&a));
+  a.x = -1;
+  EXPECT_FALSE(m.Matches(&a));
+}
+
+// Tests that Field() works when the argument is a pointer to non-const.
+TEST(FieldForPointerTest, WorksForPointerToNonConst) {
+  Matcher<AStruct*> m = Field(&AStruct::x, Ge(0));
+
+  AStruct a;
+  EXPECT_TRUE(m.Matches(&a));
+  a.x = -1;
+  EXPECT_FALSE(m.Matches(&a));
+}
+
+// Tests that Field() works when the argument is a reference to a const pointer.
+TEST(FieldForPointerTest, WorksForReferenceToConstPointer) {
+  Matcher<AStruct* const&> m = Field(&AStruct::x, Ge(0));
+
+  AStruct a;
+  EXPECT_TRUE(m.Matches(&a));
+  a.x = -1;
+  EXPECT_FALSE(m.Matches(&a));
+}
+
+// Tests that Field() does not match the NULL pointer.
+TEST(FieldForPointerTest, DoesNotMatchNull) {
+  Matcher<const AStruct*> m = Field(&AStruct::x, _);
+  EXPECT_FALSE(m.Matches(NULL));
+}
+
+// Tests that Field(&Foo::field, ...) works when the argument's type
+// is a sub-type of const Foo*.
+TEST(FieldForPointerTest, WorksForArgumentOfSubType) {
+  // Note that the matcher expects DerivedStruct but we say AStruct
+  // inside Field().
+  Matcher<DerivedStruct*> m = Field(&AStruct::x, Ge(0));
+
+  DerivedStruct d;
+  EXPECT_TRUE(m.Matches(&d));
+  d.x = -1;
+  EXPECT_FALSE(m.Matches(&d));
+}
+
+// Tests that Field() can describe itself when used to match a pointer.
+TEST(FieldForPointerTest, CanDescribeSelf) {
+  Matcher<const AStruct*> m = Field(&AStruct::x, Ge(0));
+
+  EXPECT_EQ("is an object whose given field is >= 0", Describe(m));
+  EXPECT_EQ("is an object whose given field isn't >= 0", DescribeNegation(m));
+}
+
+// Tests that Field() can explain the result of matching a pointer.
+TEST(FieldForPointerTest, CanExplainMatchResult) {
+  Matcher<const AStruct*> m = Field(&AStruct::x, Ge(0));
+
+  AStruct a;
+  a.x = 1;
+  EXPECT_EQ("", Explain(m, static_cast<const AStruct*>(NULL)));
+  EXPECT_EQ("which points to an object whose given field is 1" + OfType("int"),
+            Explain(m, &a));
+
+  m = Field(&AStruct::x, GreaterThan(0));
+  EXPECT_EQ("which points to an object whose given field is 1" + OfType("int") +
+            ", which is 1 more than 0", Explain(m, &a));
+}
+
+// A user-defined class for testing Property().
+class AClass {
+ public:
+  AClass() : n_(0) {}
+
+  // A getter that returns a non-reference.
+  int n() const { return n_; }
+
+  void set_n(int new_n) { n_ = new_n; }
+
+  // A getter that returns a reference to const.
+  const string& s() const { return s_; }
+
+  void set_s(const string& new_s) { s_ = new_s; }
+
+  // A getter that returns a reference to non-const.
+  double& x() const { return x_; }
+ private:
+  int n_;
+  string s_;
+
+  static double x_;
+};
+
+double AClass::x_ = 0.0;
+
+// A derived class for testing Property().
+class DerivedClass : public AClass {
+ public:
+  int k() const { return k_; }
+ private:
+  int k_;
+};
+
+// Tests that Property(&Foo::property, ...) works when property()
+// returns a non-reference.
+TEST(PropertyTest, WorksForNonReferenceProperty) {
+  Matcher<const AClass&> m = Property(&AClass::n, Ge(0));
+
+  AClass a;
+  a.set_n(1);
+  EXPECT_TRUE(m.Matches(a));
+
+  a.set_n(-1);
+  EXPECT_FALSE(m.Matches(a));
+}
+
+// Tests that Property(&Foo::property, ...) works when property()
+// returns a reference to const.
+TEST(PropertyTest, WorksForReferenceToConstProperty) {
+  Matcher<const AClass&> m = Property(&AClass::s, StartsWith("hi"));
+
+  AClass a;
+  a.set_s("hill");
+  EXPECT_TRUE(m.Matches(a));
+
+  a.set_s("hole");
+  EXPECT_FALSE(m.Matches(a));
+}
+
+// Tests that Property(&Foo::property, ...) works when property()
+// returns a reference to non-const.
+TEST(PropertyTest, WorksForReferenceToNonConstProperty) {
+  double x = 0.0;
+  AClass a;
+
+  Matcher<const AClass&> m = Property(&AClass::x, Ref(x));
+  EXPECT_FALSE(m.Matches(a));
+
+  m = Property(&AClass::x, Not(Ref(x)));
+  EXPECT_TRUE(m.Matches(a));
+}
+
+// Tests that Property(&Foo::property, ...) works when the argument is
+// passed by value.
+TEST(PropertyTest, WorksForByValueArgument) {
+  Matcher<AClass> m = Property(&AClass::s, StartsWith("hi"));
+
+  AClass a;
+  a.set_s("hill");
+  EXPECT_TRUE(m.Matches(a));
+
+  a.set_s("hole");
+  EXPECT_FALSE(m.Matches(a));
+}
+
+// Tests that Property(&Foo::property, ...) works when the argument's
+// type is a sub-type of Foo.
+TEST(PropertyTest, WorksForArgumentOfSubType) {
+  // The matcher expects a DerivedClass, but inside the Property() we
+  // say AClass.
+  Matcher<const DerivedClass&> m = Property(&AClass::n, Ge(0));
+
+  DerivedClass d;
+  d.set_n(1);
+  EXPECT_TRUE(m.Matches(d));
+
+  d.set_n(-1);
+  EXPECT_FALSE(m.Matches(d));
+}
+
+// Tests that Property(&Foo::property, m) works when property()'s type
+// and m's argument type are compatible but different.
+TEST(PropertyTest, WorksForCompatibleMatcherType) {
+  // n() returns an int but the inner matcher expects a signed char.
+  Matcher<const AClass&> m = Property(&AClass::n,
+                                      Matcher<signed char>(Ge(0)));
+
+  AClass a;
+  EXPECT_TRUE(m.Matches(a));
+  a.set_n(-1);
+  EXPECT_FALSE(m.Matches(a));
+}
+
+// Tests that Property() can describe itself.
+TEST(PropertyTest, CanDescribeSelf) {
+  Matcher<const AClass&> m = Property(&AClass::n, Ge(0));
+
+  EXPECT_EQ("is an object whose given property is >= 0", Describe(m));
+  EXPECT_EQ("is an object whose given property isn't >= 0",
+            DescribeNegation(m));
+}
+
+// Tests that Property() can explain the match result.
+TEST(PropertyTest, CanExplainMatchResult) {
+  Matcher<const AClass&> m = Property(&AClass::n, Ge(0));
+
+  AClass a;
+  a.set_n(1);
+  EXPECT_EQ("whose given property is 1" + OfType("int"), Explain(m, a));
+
+  m = Property(&AClass::n, GreaterThan(0));
+  EXPECT_EQ(
+      "whose given property is 1" + OfType("int") + ", which is 1 more than 0",
+      Explain(m, a));
+}
+
+// Tests that Property() works when the argument is a pointer to const.
+TEST(PropertyForPointerTest, WorksForPointerToConst) {
+  Matcher<const AClass*> m = Property(&AClass::n, Ge(0));
+
+  AClass a;
+  a.set_n(1);
+  EXPECT_TRUE(m.Matches(&a));
+
+  a.set_n(-1);
+  EXPECT_FALSE(m.Matches(&a));
+}
+
+// Tests that Property() works when the argument is a pointer to non-const.
+TEST(PropertyForPointerTest, WorksForPointerToNonConst) {
+  Matcher<AClass*> m = Property(&AClass::s, StartsWith("hi"));
+
+  AClass a;
+  a.set_s("hill");
+  EXPECT_TRUE(m.Matches(&a));
+
+  a.set_s("hole");
+  EXPECT_FALSE(m.Matches(&a));
+}
+
+// Tests that Property() works when the argument is a reference to a
+// const pointer.
+TEST(PropertyForPointerTest, WorksForReferenceToConstPointer) {
+  Matcher<AClass* const&> m = Property(&AClass::s, StartsWith("hi"));
+
+  AClass a;
+  a.set_s("hill");
+  EXPECT_TRUE(m.Matches(&a));
+
+  a.set_s("hole");
+  EXPECT_FALSE(m.Matches(&a));
+}
+
+// Tests that Property() does not match the NULL pointer.
+TEST(PropertyForPointerTest, WorksForReferenceToNonConstProperty) {
+  Matcher<const AClass*> m = Property(&AClass::x, _);
+  EXPECT_FALSE(m.Matches(NULL));
+}
+
+// Tests that Property(&Foo::property, ...) works when the argument's
+// type is a sub-type of const Foo*.
+TEST(PropertyForPointerTest, WorksForArgumentOfSubType) {
+  // The matcher expects a DerivedClass, but inside the Property() we
+  // say AClass.
+  Matcher<const DerivedClass*> m = Property(&AClass::n, Ge(0));
+
+  DerivedClass d;
+  d.set_n(1);
+  EXPECT_TRUE(m.Matches(&d));
+
+  d.set_n(-1);
+  EXPECT_FALSE(m.Matches(&d));
+}
+
+// Tests that Property() can describe itself when used to match a pointer.
+TEST(PropertyForPointerTest, CanDescribeSelf) {
+  Matcher<const AClass*> m = Property(&AClass::n, Ge(0));
+
+  EXPECT_EQ("is an object whose given property is >= 0", Describe(m));
+  EXPECT_EQ("is an object whose given property isn't >= 0",
+            DescribeNegation(m));
+}
+
+// Tests that Property() can explain the result of matching a pointer.
+TEST(PropertyForPointerTest, CanExplainMatchResult) {
+  Matcher<const AClass*> m = Property(&AClass::n, Ge(0));
+
+  AClass a;
+  a.set_n(1);
+  EXPECT_EQ("", Explain(m, static_cast<const AClass*>(NULL)));
+  EXPECT_EQ(
+      "which points to an object whose given property is 1" + OfType("int"),
+      Explain(m, &a));
+
+  m = Property(&AClass::n, GreaterThan(0));
+  EXPECT_EQ("which points to an object whose given property is 1" +
+            OfType("int") + ", which is 1 more than 0",
+            Explain(m, &a));
+}
+
+// Tests ResultOf.
+
+// Tests that ResultOf(f, ...) compiles and works as expected when f is a
+// function pointer.
+string IntToStringFunction(int input) { return input == 1 ? "foo" : "bar"; }
+
+TEST(ResultOfTest, WorksForFunctionPointers) {
+  Matcher<int> matcher = ResultOf(&IntToStringFunction, Eq(string("foo")));
+
+  EXPECT_TRUE(matcher.Matches(1));
+  EXPECT_FALSE(matcher.Matches(2));
+}
+
+// Tests that ResultOf() can describe itself.
+TEST(ResultOfTest, CanDescribeItself) {
+  Matcher<int> matcher = ResultOf(&IntToStringFunction, StrEq("foo"));
+
+  EXPECT_EQ("is mapped by the given callable to a value that "
+            "is equal to \"foo\"", Describe(matcher));
+  EXPECT_EQ("is mapped by the given callable to a value that "
+            "isn't equal to \"foo\"", DescribeNegation(matcher));
+}
+
+// Tests that ResultOf() can explain the match result.
+int IntFunction(int input) { return input == 42 ? 80 : 90; }
+
+TEST(ResultOfTest, CanExplainMatchResult) {
+  Matcher<int> matcher = ResultOf(&IntFunction, Ge(85));
+  EXPECT_EQ("which is mapped by the given callable to 90" + OfType("int"),
+            Explain(matcher, 36));
+
+  matcher = ResultOf(&IntFunction, GreaterThan(85));
+  EXPECT_EQ("which is mapped by the given callable to 90" + OfType("int") +
+            ", which is 5 more than 85", Explain(matcher, 36));
+}
+
+// Tests that ResultOf(f, ...) compiles and works as expected when f(x)
+// returns a non-reference.
+TEST(ResultOfTest, WorksForNonReferenceResults) {
+  Matcher<int> matcher = ResultOf(&IntFunction, Eq(80));
+
+  EXPECT_TRUE(matcher.Matches(42));
+  EXPECT_FALSE(matcher.Matches(36));
+}
+
+// Tests that ResultOf(f, ...) compiles and works as expected when f(x)
+// returns a reference to non-const.
+double& DoubleFunction(double& input) { return input; }  // NOLINT
+
+Uncopyable& RefUncopyableFunction(Uncopyable& obj) {  // NOLINT
+  return obj;
+}
+
+TEST(ResultOfTest, WorksForReferenceToNonConstResults) {
+  double x = 3.14;
+  double x2 = x;
+  Matcher<double&> matcher = ResultOf(&DoubleFunction, Ref(x));
+
+  EXPECT_TRUE(matcher.Matches(x));
+  EXPECT_FALSE(matcher.Matches(x2));
+
+  // Test that ResultOf works with uncopyable objects
+  Uncopyable obj(0);
+  Uncopyable obj2(0);
+  Matcher<Uncopyable&> matcher2 =
+      ResultOf(&RefUncopyableFunction, Ref(obj));
+
+  EXPECT_TRUE(matcher2.Matches(obj));
+  EXPECT_FALSE(matcher2.Matches(obj2));
+}
+
+// Tests that ResultOf(f, ...) compiles and works as expected when f(x)
+// returns a reference to const.
+const string& StringFunction(const string& input) { return input; }
+
+TEST(ResultOfTest, WorksForReferenceToConstResults) {
+  string s = "foo";
+  string s2 = s;
+  Matcher<const string&> matcher = ResultOf(&StringFunction, Ref(s));
+
+  EXPECT_TRUE(matcher.Matches(s));
+  EXPECT_FALSE(matcher.Matches(s2));
+}
+
+// Tests that ResultOf(f, m) works when f(x) and m's
+// argument types are compatible but different.
+TEST(ResultOfTest, WorksForCompatibleMatcherTypes) {
+  // IntFunction() returns int but the inner matcher expects a signed char.
+  Matcher<int> matcher = ResultOf(IntFunction, Matcher<signed char>(Ge(85)));
+
+  EXPECT_TRUE(matcher.Matches(36));
+  EXPECT_FALSE(matcher.Matches(42));
+}
+
+// Tests that the program aborts when ResultOf is passed
+// a NULL function pointer.
+TEST(ResultOfDeathTest, DiesOnNullFunctionPointers) {
+  EXPECT_DEATH_IF_SUPPORTED(
+      ResultOf(static_cast<string(*)(int dummy)>(NULL), Eq(string("foo"))),
+               "NULL function pointer is passed into ResultOf\\(\\)\\.");
+}
+
+// Tests that ResultOf(f, ...) compiles and works as expected when f is a
+// function reference.
+TEST(ResultOfTest, WorksForFunctionReferences) {
+  Matcher<int> matcher = ResultOf(IntToStringFunction, StrEq("foo"));
+  EXPECT_TRUE(matcher.Matches(1));
+  EXPECT_FALSE(matcher.Matches(2));
+}
+
+// Tests that ResultOf(f, ...) compiles and works as expected when f is a
+// function object.
+struct Functor : public ::std::unary_function<int, string> {
+  result_type operator()(argument_type input) const {
+    return IntToStringFunction(input);
+  }
+};
+
+TEST(ResultOfTest, WorksForFunctors) {
+  Matcher<int> matcher = ResultOf(Functor(), Eq(string("foo")));
+
+  EXPECT_TRUE(matcher.Matches(1));
+  EXPECT_FALSE(matcher.Matches(2));
+}
+
+// Tests that ResultOf(f, ...) compiles and works as expected when f is a
+// functor with more then one operator() defined. ResultOf() must work
+// for each defined operator().
+struct PolymorphicFunctor {
+  typedef int result_type;
+  int operator()(int n) { return n; }
+  int operator()(const char* s) { return static_cast<int>(strlen(s)); }
+};
+
+TEST(ResultOfTest, WorksForPolymorphicFunctors) {
+  Matcher<int> matcher_int = ResultOf(PolymorphicFunctor(), Ge(5));
+
+  EXPECT_TRUE(matcher_int.Matches(10));
+  EXPECT_FALSE(matcher_int.Matches(2));
+
+  Matcher<const char*> matcher_string = ResultOf(PolymorphicFunctor(), Ge(5));
+
+  EXPECT_TRUE(matcher_string.Matches("long string"));
+  EXPECT_FALSE(matcher_string.Matches("shrt"));
+}
+
+const int* ReferencingFunction(const int& n) { return &n; }
+
+struct ReferencingFunctor {
+  typedef const int* result_type;
+  result_type operator()(const int& n) { return &n; }
+};
+
+TEST(ResultOfTest, WorksForReferencingCallables) {
+  const int n = 1;
+  const int n2 = 1;
+  Matcher<const int&> matcher2 = ResultOf(ReferencingFunction, Eq(&n));
+  EXPECT_TRUE(matcher2.Matches(n));
+  EXPECT_FALSE(matcher2.Matches(n2));
+
+  Matcher<const int&> matcher3 = ResultOf(ReferencingFunctor(), Eq(&n));
+  EXPECT_TRUE(matcher3.Matches(n));
+  EXPECT_FALSE(matcher3.Matches(n2));
+}
+
+class DivisibleByImpl {
+ public:
+  explicit DivisibleByImpl(int a_divider) : divider_(a_divider) {}
+
+  // For testing using ExplainMatchResultTo() with polymorphic matchers.
+  template <typename T>
+  bool MatchAndExplain(const T& n, MatchResultListener* listener) const {
+    *listener << "which is " << (n % divider_) << " modulo "
+              << divider_;
+    return (n % divider_) == 0;
+  }
+
+  void DescribeTo(ostream* os) const {
+    *os << "is divisible by " << divider_;
+  }
+
+  void DescribeNegationTo(ostream* os) const {
+    *os << "is not divisible by " << divider_;
+  }
+
+  void set_divider(int a_divider) { divider_ = a_divider; }
+  int divider() const { return divider_; }
+
+ private:
+  int divider_;
+};
+
+PolymorphicMatcher<DivisibleByImpl> DivisibleBy(int n) {
+  return MakePolymorphicMatcher(DivisibleByImpl(n));
+}
+
+// Tests that when AllOf() fails, only the first failing matcher is
+// asked to explain why.
+TEST(ExplainMatchResultTest, AllOf_False_False) {
+  const Matcher<int> m = AllOf(DivisibleBy(4), DivisibleBy(3));
+  EXPECT_EQ("which is 1 modulo 4", Explain(m, 5));
+}
+
+// Tests that when AllOf() fails, only the first failing matcher is
+// asked to explain why.
+TEST(ExplainMatchResultTest, AllOf_False_True) {
+  const Matcher<int> m = AllOf(DivisibleBy(4), DivisibleBy(3));
+  EXPECT_EQ("which is 2 modulo 4", Explain(m, 6));
+}
+
+// Tests that when AllOf() fails, only the first failing matcher is
+// asked to explain why.
+TEST(ExplainMatchResultTest, AllOf_True_False) {
+  const Matcher<int> m = AllOf(Ge(1), DivisibleBy(3));
+  EXPECT_EQ("which is 2 modulo 3", Explain(m, 5));
+}
+
+// Tests that when AllOf() succeeds, all matchers are asked to explain
+// why.
+TEST(ExplainMatchResultTest, AllOf_True_True) {
+  const Matcher<int> m = AllOf(DivisibleBy(2), DivisibleBy(3));
+  EXPECT_EQ("which is 0 modulo 2, and which is 0 modulo 3", Explain(m, 6));
+}
+
+TEST(ExplainMatchResultTest, AllOf_True_True_2) {
+  const Matcher<int> m = AllOf(Ge(2), Le(3));
+  EXPECT_EQ("", Explain(m, 2));
+}
+
+TEST(ExplainmatcherResultTest, MonomorphicMatcher) {
+  const Matcher<int> m = GreaterThan(5);
+  EXPECT_EQ("which is 1 more than 5", Explain(m, 6));
+}
+
+// The following two tests verify that values without a public copy
+// ctor can be used as arguments to matchers like Eq(), Ge(), and etc
+// with the help of ByRef().
+
+class NotCopyable {
+ public:
+  explicit NotCopyable(int a_value) : value_(a_value) {}
+
+  int value() const { return value_; }
+
+  bool operator==(const NotCopyable& rhs) const {
+    return value() == rhs.value();
+  }
+
+  bool operator>=(const NotCopyable& rhs) const {
+    return value() >= rhs.value();
+  }
+ private:
+  int value_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(NotCopyable);
+};
+
+TEST(ByRefTest, AllowsNotCopyableConstValueInMatchers) {
+  const NotCopyable const_value1(1);
+  const Matcher<const NotCopyable&> m = Eq(ByRef(const_value1));
+
+  const NotCopyable n1(1), n2(2);
+  EXPECT_TRUE(m.Matches(n1));
+  EXPECT_FALSE(m.Matches(n2));
+}
+
+TEST(ByRefTest, AllowsNotCopyableValueInMatchers) {
+  NotCopyable value2(2);
+  const Matcher<NotCopyable&> m = Ge(ByRef(value2));
+
+  NotCopyable n1(1), n2(2);
+  EXPECT_FALSE(m.Matches(n1));
+  EXPECT_TRUE(m.Matches(n2));
+}
+
+TEST(IsEmptyTest, ImplementsIsEmpty) {
+  vector<int> container;
+  EXPECT_THAT(container, IsEmpty());
+  container.push_back(0);
+  EXPECT_THAT(container, Not(IsEmpty()));
+  container.push_back(1);
+  EXPECT_THAT(container, Not(IsEmpty()));
+}
+
+TEST(IsEmptyTest, WorksWithString) {
+  string text;
+  EXPECT_THAT(text, IsEmpty());
+  text = "foo";
+  EXPECT_THAT(text, Not(IsEmpty()));
+  text = string("\0", 1);
+  EXPECT_THAT(text, Not(IsEmpty()));
+}
+
+TEST(IsEmptyTest, CanDescribeSelf) {
+  Matcher<vector<int> > m = IsEmpty();
+  EXPECT_EQ("is empty", Describe(m));
+  EXPECT_EQ("isn't empty", DescribeNegation(m));
+}
+
+TEST(IsEmptyTest, ExplainsResult) {
+  Matcher<vector<int> > m = IsEmpty();
+  vector<int> container;
+  EXPECT_EQ("", Explain(m, container));
+  container.push_back(0);
+  EXPECT_EQ("whose size is 1", Explain(m, container));
+}
+
+TEST(SizeIsTest, ImplementsSizeIs) {
+  vector<int> container;
+  EXPECT_THAT(container, SizeIs(0));
+  EXPECT_THAT(container, Not(SizeIs(1)));
+  container.push_back(0);
+  EXPECT_THAT(container, Not(SizeIs(0)));
+  EXPECT_THAT(container, SizeIs(1));
+  container.push_back(0);
+  EXPECT_THAT(container, Not(SizeIs(0)));
+  EXPECT_THAT(container, SizeIs(2));
+}
+
+TEST(SizeIsTest, WorksWithMap) {
+  map<string, int> container;
+  EXPECT_THAT(container, SizeIs(0));
+  EXPECT_THAT(container, Not(SizeIs(1)));
+  container.insert(make_pair("foo", 1));
+  EXPECT_THAT(container, Not(SizeIs(0)));
+  EXPECT_THAT(container, SizeIs(1));
+  container.insert(make_pair("bar", 2));
+  EXPECT_THAT(container, Not(SizeIs(0)));
+  EXPECT_THAT(container, SizeIs(2));
+}
+
+TEST(SizeIsTest, WorksWithReferences) {
+  vector<int> container;
+  Matcher<const vector<int>&> m = SizeIs(1);
+  EXPECT_THAT(container, Not(m));
+  container.push_back(0);
+  EXPECT_THAT(container, m);
+}
+
+TEST(SizeIsTest, CanDescribeSelf) {
+  Matcher<vector<int> > m = SizeIs(2);
+  EXPECT_EQ("size is equal to 2", Describe(m));
+  EXPECT_EQ("size isn't equal to 2", DescribeNegation(m));
+}
+
+TEST(SizeIsTest, ExplainsResult) {
+  Matcher<vector<int> > m1 = SizeIs(2);
+  Matcher<vector<int> > m2 = SizeIs(Lt(2u));
+  Matcher<vector<int> > m3 = SizeIs(AnyOf(0, 3));
+  Matcher<vector<int> > m4 = SizeIs(GreaterThan(1));
+  vector<int> container;
+  EXPECT_EQ("whose size 0 doesn't match", Explain(m1, container));
+  EXPECT_EQ("whose size 0 matches", Explain(m2, container));
+  EXPECT_EQ("whose size 0 matches", Explain(m3, container));
+  EXPECT_EQ("whose size 0 doesn't match, which is 1 less than 1",
+            Explain(m4, container));
+  container.push_back(0);
+  container.push_back(0);
+  EXPECT_EQ("whose size 2 matches", Explain(m1, container));
+  EXPECT_EQ("whose size 2 doesn't match", Explain(m2, container));
+  EXPECT_EQ("whose size 2 doesn't match", Explain(m3, container));
+  EXPECT_EQ("whose size 2 matches, which is 1 more than 1",
+            Explain(m4, container));
+}
+
+#if GTEST_HAS_TYPED_TEST
+// Tests ContainerEq with different container types, and
+// different element types.
+
+template <typename T>
+class ContainerEqTest : public testing::Test {};
+
+typedef testing::Types<
+    set<int>,
+    vector<size_t>,
+    multiset<size_t>,
+    list<int> >
+    ContainerEqTestTypes;
+
+TYPED_TEST_CASE(ContainerEqTest, ContainerEqTestTypes);
+
+// Tests that the filled container is equal to itself.
+TYPED_TEST(ContainerEqTest, EqualsSelf) {
+  static const int vals[] = {1, 1, 2, 3, 5, 8};
+  TypeParam my_set(vals, vals + 6);
+  const Matcher<TypeParam> m = ContainerEq(my_set);
+  EXPECT_TRUE(m.Matches(my_set));
+  EXPECT_EQ("", Explain(m, my_set));
+}
+
+// Tests that missing values are reported.
+TYPED_TEST(ContainerEqTest, ValueMissing) {
+  static const int vals[] = {1, 1, 2, 3, 5, 8};
+  static const int test_vals[] = {2, 1, 8, 5};
+  TypeParam my_set(vals, vals + 6);
+  TypeParam test_set(test_vals, test_vals + 4);
+  const Matcher<TypeParam> m = ContainerEq(my_set);
+  EXPECT_FALSE(m.Matches(test_set));
+  EXPECT_EQ("which doesn't have these expected elements: 3",
+            Explain(m, test_set));
+}
+
+// Tests that added values are reported.
+TYPED_TEST(ContainerEqTest, ValueAdded) {
+  static const int vals[] = {1, 1, 2, 3, 5, 8};
+  static const int test_vals[] = {1, 2, 3, 5, 8, 46};
+  TypeParam my_set(vals, vals + 6);
+  TypeParam test_set(test_vals, test_vals + 6);
+  const Matcher<const TypeParam&> m = ContainerEq(my_set);
+  EXPECT_FALSE(m.Matches(test_set));
+  EXPECT_EQ("which has these unexpected elements: 46", Explain(m, test_set));
+}
+
+// Tests that added and missing values are reported together.
+TYPED_TEST(ContainerEqTest, ValueAddedAndRemoved) {
+  static const int vals[] = {1, 1, 2, 3, 5, 8};
+  static const int test_vals[] = {1, 2, 3, 8, 46};
+  TypeParam my_set(vals, vals + 6);
+  TypeParam test_set(test_vals, test_vals + 5);
+  const Matcher<TypeParam> m = ContainerEq(my_set);
+  EXPECT_FALSE(m.Matches(test_set));
+  EXPECT_EQ("which has these unexpected elements: 46,\n"
+            "and doesn't have these expected elements: 5",
+            Explain(m, test_set));
+}
+
+// Tests duplicated value -- expect no explanation.
+TYPED_TEST(ContainerEqTest, DuplicateDifference) {
+  static const int vals[] = {1, 1, 2, 3, 5, 8};
+  static const int test_vals[] = {1, 2, 3, 5, 8};
+  TypeParam my_set(vals, vals + 6);
+  TypeParam test_set(test_vals, test_vals + 5);
+  const Matcher<const TypeParam&> m = ContainerEq(my_set);
+  // Depending on the container, match may be true or false
+  // But in any case there should be no explanation.
+  EXPECT_EQ("", Explain(m, test_set));
+}
+#endif  // GTEST_HAS_TYPED_TEST
+
+// Tests that mutliple missing values are reported.
+// Using just vector here, so order is predicatble.
+TEST(ContainerEqExtraTest, MultipleValuesMissing) {
+  static const int vals[] = {1, 1, 2, 3, 5, 8};
+  static const int test_vals[] = {2, 1, 5};
+  vector<int> my_set(vals, vals + 6);
+  vector<int> test_set(test_vals, test_vals + 3);
+  const Matcher<vector<int> > m = ContainerEq(my_set);
+  EXPECT_FALSE(m.Matches(test_set));
+  EXPECT_EQ("which doesn't have these expected elements: 3, 8",
+            Explain(m, test_set));
+}
+
+// Tests that added values are reported.
+// Using just vector here, so order is predicatble.
+TEST(ContainerEqExtraTest, MultipleValuesAdded) {
+  static const int vals[] = {1, 1, 2, 3, 5, 8};
+  static const int test_vals[] = {1, 2, 92, 3, 5, 8, 46};
+  list<size_t> my_set(vals, vals + 6);
+  list<size_t> test_set(test_vals, test_vals + 7);
+  const Matcher<const list<size_t>&> m = ContainerEq(my_set);
+  EXPECT_FALSE(m.Matches(test_set));
+  EXPECT_EQ("which has these unexpected elements: 92, 46",
+            Explain(m, test_set));
+}
+
+// Tests that added and missing values are reported together.
+TEST(ContainerEqExtraTest, MultipleValuesAddedAndRemoved) {
+  static const int vals[] = {1, 1, 2, 3, 5, 8};
+  static const int test_vals[] = {1, 2, 3, 92, 46};
+  list<size_t> my_set(vals, vals + 6);
+  list<size_t> test_set(test_vals, test_vals + 5);
+  const Matcher<const list<size_t> > m = ContainerEq(my_set);
+  EXPECT_FALSE(m.Matches(test_set));
+  EXPECT_EQ("which has these unexpected elements: 92, 46,\n"
+            "and doesn't have these expected elements: 5, 8",
+            Explain(m, test_set));
+}
+
+// Tests to see that duplicate elements are detected,
+// but (as above) not reported in the explanation.
+TEST(ContainerEqExtraTest, MultiSetOfIntDuplicateDifference) {
+  static const int vals[] = {1, 1, 2, 3, 5, 8};
+  static const int test_vals[] = {1, 2, 3, 5, 8};
+  vector<int> my_set(vals, vals + 6);
+  vector<int> test_set(test_vals, test_vals + 5);
+  const Matcher<vector<int> > m = ContainerEq(my_set);
+  EXPECT_TRUE(m.Matches(my_set));
+  EXPECT_FALSE(m.Matches(test_set));
+  // There is nothing to report when both sets contain all the same values.
+  EXPECT_EQ("", Explain(m, test_set));
+}
+
+// Tests that ContainerEq works for non-trivial associative containers,
+// like maps.
+TEST(ContainerEqExtraTest, WorksForMaps) {
+  map<int, std::string> my_map;
+  my_map[0] = "a";
+  my_map[1] = "b";
+
+  map<int, std::string> test_map;
+  test_map[0] = "aa";
+  test_map[1] = "b";
+
+  const Matcher<const map<int, std::string>&> m = ContainerEq(my_map);
+  EXPECT_TRUE(m.Matches(my_map));
+  EXPECT_FALSE(m.Matches(test_map));
+
+  EXPECT_EQ("which has these unexpected elements: (0, \"aa\"),\n"
+            "and doesn't have these expected elements: (0, \"a\")",
+            Explain(m, test_map));
+}
+
+TEST(ContainerEqExtraTest, WorksForNativeArray) {
+  int a1[] = {1, 2, 3};
+  int a2[] = {1, 2, 3};
+  int b[] = {1, 2, 4};
+
+  EXPECT_THAT(a1, ContainerEq(a2));
+  EXPECT_THAT(a1, Not(ContainerEq(b)));
+}
+
+TEST(ContainerEqExtraTest, WorksForTwoDimensionalNativeArray) {
+  const char a1[][3] = {"hi", "lo"};
+  const char a2[][3] = {"hi", "lo"};
+  const char b[][3] = {"lo", "hi"};
+
+  // Tests using ContainerEq() in the first dimension.
+  EXPECT_THAT(a1, ContainerEq(a2));
+  EXPECT_THAT(a1, Not(ContainerEq(b)));
+
+  // Tests using ContainerEq() in the second dimension.
+  EXPECT_THAT(a1, ElementsAre(ContainerEq(a2[0]), ContainerEq(a2[1])));
+  EXPECT_THAT(a1, ElementsAre(Not(ContainerEq(b[0])), ContainerEq(a2[1])));
+}
+
+TEST(ContainerEqExtraTest, WorksForNativeArrayAsTuple) {
+  const int a1[] = {1, 2, 3};
+  const int a2[] = {1, 2, 3};
+  const int b[] = {1, 2, 3, 4};
+
+  const int* const p1 = a1;
+  EXPECT_THAT(make_tuple(p1, 3), ContainerEq(a2));
+  EXPECT_THAT(make_tuple(p1, 3), Not(ContainerEq(b)));
+
+  const int c[] = {1, 3, 2};
+  EXPECT_THAT(make_tuple(p1, 3), Not(ContainerEq(c)));
+}
+
+TEST(ContainerEqExtraTest, CopiesNativeArrayParameter) {
+  std::string a1[][3] = {
+    {"hi", "hello", "ciao"},
+    {"bye", "see you", "ciao"}
+  };
+
+  std::string a2[][3] = {
+    {"hi", "hello", "ciao"},
+    {"bye", "see you", "ciao"}
+  };
+
+  const Matcher<const std::string(&)[2][3]> m = ContainerEq(a2);
+  EXPECT_THAT(a1, m);
+
+  a2[0][0] = "ha";
+  EXPECT_THAT(a1, m);
+}
+
+TEST(WhenSortedByTest, WorksForEmptyContainer) {
+  const vector<int> numbers;
+  EXPECT_THAT(numbers, WhenSortedBy(less<int>(), ElementsAre()));
+  EXPECT_THAT(numbers, Not(WhenSortedBy(less<int>(), ElementsAre(1))));
+}
+
+TEST(WhenSortedByTest, WorksForNonEmptyContainer) {
+  vector<unsigned> numbers;
+  numbers.push_back(3);
+  numbers.push_back(1);
+  numbers.push_back(2);
+  numbers.push_back(2);
+  EXPECT_THAT(numbers, WhenSortedBy(greater<unsigned>(),
+                                    ElementsAre(3, 2, 2, 1)));
+  EXPECT_THAT(numbers, Not(WhenSortedBy(greater<unsigned>(),
+                                        ElementsAre(1, 2, 2, 3))));
+}
+
+TEST(WhenSortedByTest, WorksForNonVectorContainer) {
+  list<string> words;
+  words.push_back("say");
+  words.push_back("hello");
+  words.push_back("world");
+  EXPECT_THAT(words, WhenSortedBy(less<string>(),
+                                  ElementsAre("hello", "say", "world")));
+  EXPECT_THAT(words, Not(WhenSortedBy(less<string>(),
+                                      ElementsAre("say", "hello", "world"))));
+}
+
+TEST(WhenSortedByTest, WorksForNativeArray) {
+  const int numbers[] = {1, 3, 2, 4};
+  const int sorted_numbers[] = {1, 2, 3, 4};
+  EXPECT_THAT(numbers, WhenSortedBy(less<int>(), ElementsAre(1, 2, 3, 4)));
+  EXPECT_THAT(numbers, WhenSortedBy(less<int>(),
+                                    ElementsAreArray(sorted_numbers)));
+  EXPECT_THAT(numbers, Not(WhenSortedBy(less<int>(), ElementsAre(1, 3, 2, 4))));
+}
+
+TEST(WhenSortedByTest, CanDescribeSelf) {
+  const Matcher<vector<int> > m = WhenSortedBy(less<int>(), ElementsAre(1, 2));
+  EXPECT_EQ("(when sorted) has 2 elements where\n"
+            "element #0 is equal to 1,\n"
+            "element #1 is equal to 2",
+            Describe(m));
+  EXPECT_EQ("(when sorted) doesn't have 2 elements, or\n"
+            "element #0 isn't equal to 1, or\n"
+            "element #1 isn't equal to 2",
+            DescribeNegation(m));
+}
+
+TEST(WhenSortedByTest, ExplainsMatchResult) {
+  const int a[] = {2, 1};
+  EXPECT_EQ("which is { 1, 2 } when sorted, whose element #0 doesn't match",
+            Explain(WhenSortedBy(less<int>(), ElementsAre(2, 3)), a));
+  EXPECT_EQ("which is { 1, 2 } when sorted",
+            Explain(WhenSortedBy(less<int>(), ElementsAre(1, 2)), a));
+}
+
+// WhenSorted() is a simple wrapper on WhenSortedBy().  Hence we don't
+// need to test it as exhaustively as we test the latter.
+
+TEST(WhenSortedTest, WorksForEmptyContainer) {
+  const vector<int> numbers;
+  EXPECT_THAT(numbers, WhenSorted(ElementsAre()));
+  EXPECT_THAT(numbers, Not(WhenSorted(ElementsAre(1))));
+}
+
+TEST(WhenSortedTest, WorksForNonEmptyContainer) {
+  list<string> words;
+  words.push_back("3");
+  words.push_back("1");
+  words.push_back("2");
+  words.push_back("2");
+  EXPECT_THAT(words, WhenSorted(ElementsAre("1", "2", "2", "3")));
+  EXPECT_THAT(words, Not(WhenSorted(ElementsAre("3", "1", "2", "2"))));
+}
+
+TEST(WhenSortedTest, WorksForMapTypes) {
+    map<string, int> word_counts;
+    word_counts["and"] = 1;
+    word_counts["the"] = 1;
+    word_counts["buffalo"] = 2;
+    EXPECT_THAT(word_counts, WhenSorted(ElementsAre(
+            Pair("and", 1), Pair("buffalo", 2), Pair("the", 1))));
+    EXPECT_THAT(word_counts, Not(WhenSorted(ElementsAre(
+            Pair("and", 1), Pair("the", 1), Pair("buffalo", 2)))));
+}
+
+TEST(WhenSortedTest, WorksForMultiMapTypes) {
+    multimap<int, int> ifib;
+    ifib.insert(make_pair(8, 6));
+    ifib.insert(make_pair(2, 3));
+    ifib.insert(make_pair(1, 1));
+    ifib.insert(make_pair(3, 4));
+    ifib.insert(make_pair(1, 2));
+    ifib.insert(make_pair(5, 5));
+    EXPECT_THAT(ifib, WhenSorted(ElementsAre(Pair(1, 1),
+                                             Pair(1, 2),
+                                             Pair(2, 3),
+                                             Pair(3, 4),
+                                             Pair(5, 5),
+                                             Pair(8, 6))));
+    EXPECT_THAT(ifib, Not(WhenSorted(ElementsAre(Pair(8, 6),
+                                                 Pair(2, 3),
+                                                 Pair(1, 1),
+                                                 Pair(3, 4),
+                                                 Pair(1, 2),
+                                                 Pair(5, 5)))));
+}
+
+TEST(WhenSortedTest, WorksForPolymorphicMatcher) {
+    std::deque<int> d;
+    d.push_back(2);
+    d.push_back(1);
+    EXPECT_THAT(d, WhenSorted(ElementsAre(1, 2)));
+    EXPECT_THAT(d, Not(WhenSorted(ElementsAre(2, 1))));
+}
+
+TEST(WhenSortedTest, WorksForVectorConstRefMatcher) {
+    std::deque<int> d;
+    d.push_back(2);
+    d.push_back(1);
+    Matcher<const std::vector<int>&> vector_match = ElementsAre(1, 2);
+    EXPECT_THAT(d, WhenSorted(vector_match));
+    Matcher<const std::vector<int>&> not_vector_match = ElementsAre(2, 1);
+    EXPECT_THAT(d, Not(WhenSorted(not_vector_match)));
+}
+
+// Deliberately bare pseudo-container.
+// Offers only begin() and end() accessors, yielding InputIterator.
+template <typename T>
+class Streamlike {
+ private:
+  class ConstIter;
+ public:
+  typedef ConstIter const_iterator;
+  typedef T value_type;
+
+  template <typename InIter>
+  Streamlike(InIter first, InIter last) : remainder_(first, last) {}
+
+  const_iterator begin() const {
+    return const_iterator(this, remainder_.begin());
+  }
+  const_iterator end() const {
+    return const_iterator(this, remainder_.end());
+  }
+
+ private:
+  class ConstIter : public std::iterator<std::input_iterator_tag,
+                                         value_type,
+                                         ptrdiff_t,
+                                         const value_type*,
+                                         const value_type&> {
+   public:
+    ConstIter(const Streamlike* s,
+              typename std::list<value_type>::iterator pos)
+        : s_(s), pos_(pos) {}
+
+    const value_type& operator*() const { return *pos_; }
+    const value_type* operator->() const { return &*pos_; }
+    ConstIter& operator++() {
+      s_->remainder_.erase(pos_++);
+      return *this;
+    }
+
+    // *iter++ is required to work (see std::istreambuf_iterator).
+    // (void)iter++ is also required to work.
+    class PostIncrProxy {
+     public:
+      explicit PostIncrProxy(const value_type& value) : value_(value) {}
+      value_type operator*() const { return value_; }
+     private:
+      value_type value_;
+    };
+    PostIncrProxy operator++(int) {
+      PostIncrProxy proxy(**this);
+      ++(*this);
+      return proxy;
+    }
+
+    friend bool operator==(const ConstIter& a, const ConstIter& b) {
+      return a.s_ == b.s_ && a.pos_ == b.pos_;
+    }
+    friend bool operator!=(const ConstIter& a, const ConstIter& b) {
+      return !(a == b);
+    }
+
+   private:
+    const Streamlike* s_;
+    typename std::list<value_type>::iterator pos_;
+  };
+
+  friend std::ostream& operator<<(std::ostream& os, const Streamlike& s) {
+    os << "[";
+    typedef typename std::list<value_type>::const_iterator Iter;
+    const char* sep = "";
+    for (Iter it = s.remainder_.begin(); it != s.remainder_.end(); ++it) {
+      os << sep << *it;
+      sep = ",";
+    }
+    os << "]";
+    return os;
+  }
+
+  mutable std::list<value_type> remainder_;  // modified by iteration
+};
+
+TEST(StreamlikeTest, Iteration) {
+  const int a[5] = {2, 1, 4, 5, 3};
+  Streamlike<int> s(a, a + 5);
+  Streamlike<int>::const_iterator it = s.begin();
+  const int* ip = a;
+  while (it != s.end()) {
+    SCOPED_TRACE(ip - a);
+    EXPECT_EQ(*ip++, *it++);
+  }
+}
+
+#if GTEST_HAS_STD_FORWARD_LIST_
+TEST(BeginEndDistanceIsTest, WorksWithForwardList) {
+  std::forward_list<int> container;
+  EXPECT_THAT(container, BeginEndDistanceIs(0));
+  EXPECT_THAT(container, Not(BeginEndDistanceIs(1)));
+  container.push_front(0);
+  EXPECT_THAT(container, Not(BeginEndDistanceIs(0)));
+  EXPECT_THAT(container, BeginEndDistanceIs(1));
+  container.push_front(0);
+  EXPECT_THAT(container, Not(BeginEndDistanceIs(0)));
+  EXPECT_THAT(container, BeginEndDistanceIs(2));
+}
+#endif  // GTEST_HAS_STD_FORWARD_LIST_
+
+TEST(BeginEndDistanceIsTest, WorksWithNonStdList) {
+  const int a[5] = {1, 2, 3, 4, 5};
+  Streamlike<int> s(a, a + 5);
+  EXPECT_THAT(s, BeginEndDistanceIs(5));
+}
+
+TEST(BeginEndDistanceIsTest, CanDescribeSelf) {
+  Matcher<vector<int> > m = BeginEndDistanceIs(2);
+  EXPECT_EQ("distance between begin() and end() is equal to 2", Describe(m));
+  EXPECT_EQ("distance between begin() and end() isn't equal to 2",
+            DescribeNegation(m));
+}
+
+TEST(BeginEndDistanceIsTest, ExplainsResult) {
+  Matcher<vector<int> > m1 = BeginEndDistanceIs(2);
+  Matcher<vector<int> > m2 = BeginEndDistanceIs(Lt(2));
+  Matcher<vector<int> > m3 = BeginEndDistanceIs(AnyOf(0, 3));
+  Matcher<vector<int> > m4 = BeginEndDistanceIs(GreaterThan(1));
+  vector<int> container;
+  EXPECT_EQ("whose distance between begin() and end() 0 doesn't match",
+            Explain(m1, container));
+  EXPECT_EQ("whose distance between begin() and end() 0 matches",
+            Explain(m2, container));
+  EXPECT_EQ("whose distance between begin() and end() 0 matches",
+            Explain(m3, container));
+  EXPECT_EQ(
+      "whose distance between begin() and end() 0 doesn't match, which is 1 "
+      "less than 1",
+      Explain(m4, container));
+  container.push_back(0);
+  container.push_back(0);
+  EXPECT_EQ("whose distance between begin() and end() 2 matches",
+            Explain(m1, container));
+  EXPECT_EQ("whose distance between begin() and end() 2 doesn't match",
+            Explain(m2, container));
+  EXPECT_EQ("whose distance between begin() and end() 2 doesn't match",
+            Explain(m3, container));
+  EXPECT_EQ(
+      "whose distance between begin() and end() 2 matches, which is 1 more "
+      "than 1",
+      Explain(m4, container));
+}
+
+TEST(WhenSortedTest, WorksForStreamlike) {
+  // Streamlike 'container' provides only minimal iterator support.
+  // Its iterators are tagged with input_iterator_tag.
+  const int a[5] = {2, 1, 4, 5, 3};
+  Streamlike<int> s(a, a + GTEST_ARRAY_SIZE_(a));
+  EXPECT_THAT(s, WhenSorted(ElementsAre(1, 2, 3, 4, 5)));
+  EXPECT_THAT(s, Not(WhenSorted(ElementsAre(2, 1, 4, 5, 3))));
+}
+
+TEST(WhenSortedTest, WorksForVectorConstRefMatcherOnStreamlike) {
+  const int a[] = {2, 1, 4, 5, 3};
+  Streamlike<int> s(a, a + GTEST_ARRAY_SIZE_(a));
+  Matcher<const std::vector<int>&> vector_match = ElementsAre(1, 2, 3, 4, 5);
+  EXPECT_THAT(s, WhenSorted(vector_match));
+  EXPECT_THAT(s, Not(WhenSorted(ElementsAre(2, 1, 4, 5, 3))));
+}
+
+// Tests using ElementsAre() and ElementsAreArray() with stream-like
+// "containers".
+
+TEST(ElemensAreStreamTest, WorksForStreamlike) {
+  const int a[5] = {1, 2, 3, 4, 5};
+  Streamlike<int> s(a, a + GTEST_ARRAY_SIZE_(a));
+  EXPECT_THAT(s, ElementsAre(1, 2, 3, 4, 5));
+  EXPECT_THAT(s, Not(ElementsAre(2, 1, 4, 5, 3)));
+}
+
+TEST(ElemensAreArrayStreamTest, WorksForStreamlike) {
+  const int a[5] = {1, 2, 3, 4, 5};
+  Streamlike<int> s(a, a + GTEST_ARRAY_SIZE_(a));
+
+  vector<int> expected;
+  expected.push_back(1);
+  expected.push_back(2);
+  expected.push_back(3);
+  expected.push_back(4);
+  expected.push_back(5);
+  EXPECT_THAT(s, ElementsAreArray(expected));
+
+  expected[3] = 0;
+  EXPECT_THAT(s, Not(ElementsAreArray(expected)));
+}
+
+TEST(ElementsAreTest, WorksWithUncopyable) {
+  Uncopyable objs[2];
+  objs[0].set_value(-3);
+  objs[1].set_value(1);
+  EXPECT_THAT(objs, ElementsAre(UncopyableIs(-3), Truly(ValueIsPositive)));
+}
+
+TEST(ElementsAreTest, TakesStlContainer) {
+  const int actual[] = {3, 1, 2};
+
+  ::std::list<int> expected;
+  expected.push_back(3);
+  expected.push_back(1);
+  expected.push_back(2);
+  EXPECT_THAT(actual, ElementsAreArray(expected));
+
+  expected.push_back(4);
+  EXPECT_THAT(actual, Not(ElementsAreArray(expected)));
+}
+
+// Tests for UnorderedElementsAreArray()
+
+TEST(UnorderedElementsAreArrayTest, SucceedsWhenExpected) {
+  const int a[] = {0, 1, 2, 3, 4};
+  std::vector<int> s(a, a + GTEST_ARRAY_SIZE_(a));
+  do {
+    StringMatchResultListener listener;
+    EXPECT_TRUE(ExplainMatchResult(UnorderedElementsAreArray(a),
+                                   s, &listener)) << listener.str();
+  } while (std::next_permutation(s.begin(), s.end()));
+}
+
+TEST(UnorderedElementsAreArrayTest, VectorBool) {
+  const bool a[] = {0, 1, 0, 1, 1};
+  const bool b[] = {1, 0, 1, 1, 0};
+  std::vector<bool> expected(a, a + GTEST_ARRAY_SIZE_(a));
+  std::vector<bool> actual(b, b + GTEST_ARRAY_SIZE_(b));
+  StringMatchResultListener listener;
+  EXPECT_TRUE(ExplainMatchResult(UnorderedElementsAreArray(expected),
+                                 actual, &listener)) << listener.str();
+}
+
+TEST(UnorderedElementsAreArrayTest, WorksForStreamlike) {
+  // Streamlike 'container' provides only minimal iterator support.
+  // Its iterators are tagged with input_iterator_tag, and it has no
+  // size() or empty() methods.
+  const int a[5] = {2, 1, 4, 5, 3};
+  Streamlike<int> s(a, a + GTEST_ARRAY_SIZE_(a));
+
+  ::std::vector<int> expected;
+  expected.push_back(1);
+  expected.push_back(2);
+  expected.push_back(3);
+  expected.push_back(4);
+  expected.push_back(5);
+  EXPECT_THAT(s, UnorderedElementsAreArray(expected));
+
+  expected.push_back(6);
+  EXPECT_THAT(s, Not(UnorderedElementsAreArray(expected)));
+}
+
+TEST(UnorderedElementsAreArrayTest, TakesStlContainer) {
+  const int actual[] = {3, 1, 2};
+
+  ::std::list<int> expected;
+  expected.push_back(1);
+  expected.push_back(2);
+  expected.push_back(3);
+  EXPECT_THAT(actual, UnorderedElementsAreArray(expected));
+
+  expected.push_back(4);
+  EXPECT_THAT(actual, Not(UnorderedElementsAreArray(expected)));
+}
+
+#if GTEST_HAS_STD_INITIALIZER_LIST_
+
+TEST(UnorderedElementsAreArrayTest, TakesInitializerList) {
+  const int a[5] = {2, 1, 4, 5, 3};
+  EXPECT_THAT(a, UnorderedElementsAreArray({1, 2, 3, 4, 5}));
+  EXPECT_THAT(a, Not(UnorderedElementsAreArray({1, 2, 3, 4, 6})));
+}
+
+TEST(UnorderedElementsAreArrayTest, TakesInitializerListOfCStrings) {
+  const string a[5] = {"a", "b", "c", "d", "e"};
+  EXPECT_THAT(a, UnorderedElementsAreArray({"a", "b", "c", "d", "e"}));
+  EXPECT_THAT(a, Not(UnorderedElementsAreArray({"a", "b", "c", "d", "ef"})));
+}
+
+TEST(UnorderedElementsAreArrayTest, TakesInitializerListOfSameTypedMatchers) {
+  const int a[5] = {2, 1, 4, 5, 3};
+  EXPECT_THAT(a, UnorderedElementsAreArray(
+      {Eq(1), Eq(2), Eq(3), Eq(4), Eq(5)}));
+  EXPECT_THAT(a, Not(UnorderedElementsAreArray(
+      {Eq(1), Eq(2), Eq(3), Eq(4), Eq(6)})));
+}
+
+TEST(UnorderedElementsAreArrayTest,
+     TakesInitializerListOfDifferentTypedMatchers) {
+  const int a[5] = {2, 1, 4, 5, 3};
+  // The compiler cannot infer the type of the initializer list if its
+  // elements have different types.  We must explicitly specify the
+  // unified element type in this case.
+  EXPECT_THAT(a, UnorderedElementsAreArray<Matcher<int> >(
+      {Eq(1), Ne(-2), Ge(3), Le(4), Eq(5)}));
+  EXPECT_THAT(a, Not(UnorderedElementsAreArray<Matcher<int> >(
+      {Eq(1), Ne(-2), Ge(3), Le(4), Eq(6)})));
+}
+
+#endif  // GTEST_HAS_STD_INITIALIZER_LIST_
+
+class UnorderedElementsAreTest : public testing::Test {
+ protected:
+  typedef std::vector<int> IntVec;
+};
+
+TEST_F(UnorderedElementsAreTest, WorksWithUncopyable) {
+  Uncopyable objs[2];
+  objs[0].set_value(-3);
+  objs[1].set_value(1);
+  EXPECT_THAT(objs,
+              UnorderedElementsAre(Truly(ValueIsPositive), UncopyableIs(-3)));
+}
+
+TEST_F(UnorderedElementsAreTest, SucceedsWhenExpected) {
+  const int a[] = {1, 2, 3};
+  std::vector<int> s(a, a + GTEST_ARRAY_SIZE_(a));
+  do {
+    StringMatchResultListener listener;
+    EXPECT_TRUE(ExplainMatchResult(UnorderedElementsAre(1, 2, 3),
+                                   s, &listener)) << listener.str();
+  } while (std::next_permutation(s.begin(), s.end()));
+}
+
+TEST_F(UnorderedElementsAreTest, FailsWhenAnElementMatchesNoMatcher) {
+  const int a[] = {1, 2, 3};
+  std::vector<int> s(a, a + GTEST_ARRAY_SIZE_(a));
+  std::vector<Matcher<int> > mv;
+  mv.push_back(1);
+  mv.push_back(2);
+  mv.push_back(2);
+  // The element with value '3' matches nothing: fail fast.
+  StringMatchResultListener listener;
+  EXPECT_FALSE(ExplainMatchResult(UnorderedElementsAreArray(mv),
+                                  s, &listener)) << listener.str();
+}
+
+TEST_F(UnorderedElementsAreTest, WorksForStreamlike) {
+  // Streamlike 'container' provides only minimal iterator support.
+  // Its iterators are tagged with input_iterator_tag, and it has no
+  // size() or empty() methods.
+  const int a[5] = {2, 1, 4, 5, 3};
+  Streamlike<int> s(a, a + GTEST_ARRAY_SIZE_(a));
+
+  EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5));
+  EXPECT_THAT(s, Not(UnorderedElementsAre(2, 2, 3, 4, 5)));
+}
+
+// One naive implementation of the matcher runs in O(N!) time, which is too
+// slow for many real-world inputs. This test shows that our matcher can match
+// 100 inputs very quickly (a few milliseconds).  An O(100!) is 10^158
+// iterations and obviously effectively incomputable.
+// [ RUN      ] UnorderedElementsAreTest.Performance
+// [       OK ] UnorderedElementsAreTest.Performance (4 ms)
+TEST_F(UnorderedElementsAreTest, Performance) {
+  std::vector<int> s;
+  std::vector<Matcher<int> > mv;
+  for (int i = 0; i < 100; ++i) {
+    s.push_back(i);
+    mv.push_back(_);
+  }
+  mv[50] = Eq(0);
+  StringMatchResultListener listener;
+  EXPECT_TRUE(ExplainMatchResult(UnorderedElementsAreArray(mv),
+                                 s, &listener)) << listener.str();
+}
+
+// Another variant of 'Performance' with similar expectations.
+// [ RUN      ] UnorderedElementsAreTest.PerformanceHalfStrict
+// [       OK ] UnorderedElementsAreTest.PerformanceHalfStrict (4 ms)
+TEST_F(UnorderedElementsAreTest, PerformanceHalfStrict) {
+  std::vector<int> s;
+  std::vector<Matcher<int> > mv;
+  for (int i = 0; i < 100; ++i) {
+    s.push_back(i);
+    if (i & 1) {
+      mv.push_back(_);
+    } else {
+      mv.push_back(i);
+    }
+  }
+  StringMatchResultListener listener;
+  EXPECT_TRUE(ExplainMatchResult(UnorderedElementsAreArray(mv),
+                                 s, &listener)) << listener.str();
+}
+
+TEST_F(UnorderedElementsAreTest, FailMessageCountWrong) {
+  std::vector<int> v;
+  v.push_back(4);
+  StringMatchResultListener listener;
+  EXPECT_FALSE(ExplainMatchResult(UnorderedElementsAre(1, 2, 3),
+                                  v, &listener)) << listener.str();
+  EXPECT_THAT(listener.str(), Eq("which has 1 element"));
+}
+
+TEST_F(UnorderedElementsAreTest, FailMessageCountWrongZero) {
+  std::vector<int> v;
+  StringMatchResultListener listener;
+  EXPECT_FALSE(ExplainMatchResult(UnorderedElementsAre(1, 2, 3),
+                                  v, &listener)) << listener.str();
+  EXPECT_THAT(listener.str(), Eq(""));
+}
+
+TEST_F(UnorderedElementsAreTest, FailMessageUnmatchedMatchers) {
+  std::vector<int> v;
+  v.push_back(1);
+  v.push_back(1);
+  StringMatchResultListener listener;
+  EXPECT_FALSE(ExplainMatchResult(UnorderedElementsAre(1, 2),
+                                  v, &listener)) << listener.str();
+  EXPECT_THAT(
+      listener.str(),
+      Eq("where the following matchers don't match any elements:\n"
+         "matcher #1: is equal to 2"));
+}
+
+TEST_F(UnorderedElementsAreTest, FailMessageUnmatchedElements) {
+  std::vector<int> v;
+  v.push_back(1);
+  v.push_back(2);
+  StringMatchResultListener listener;
+  EXPECT_FALSE(ExplainMatchResult(UnorderedElementsAre(1, 1),
+                                  v, &listener)) << listener.str();
+  EXPECT_THAT(
+      listener.str(),
+      Eq("where the following elements don't match any matchers:\n"
+         "element #1: 2"));
+}
+
+TEST_F(UnorderedElementsAreTest, FailMessageUnmatchedMatcherAndElement) {
+  std::vector<int> v;
+  v.push_back(2);
+  v.push_back(3);
+  StringMatchResultListener listener;
+  EXPECT_FALSE(ExplainMatchResult(UnorderedElementsAre(1, 2),
+                                  v, &listener)) << listener.str();
+  EXPECT_THAT(
+      listener.str(),
+      Eq("where"
+         " the following matchers don't match any elements:\n"
+         "matcher #0: is equal to 1\n"
+         "and"
+         " where"
+         " the following elements don't match any matchers:\n"
+         "element #1: 3"));
+}
+
+// Test helper for formatting element, matcher index pairs in expectations.
+static string EMString(int element, int matcher) {
+  stringstream ss;
+  ss << "(element #" << element << ", matcher #" << matcher << ")";
+  return ss.str();
+}
+
+TEST_F(UnorderedElementsAreTest, FailMessageImperfectMatchOnly) {
+  // A situation where all elements and matchers have a match
+  // associated with them, but the max matching is not perfect.
+  std::vector<string> v;
+  v.push_back("a");
+  v.push_back("b");
+  v.push_back("c");
+  StringMatchResultListener listener;
+  EXPECT_FALSE(ExplainMatchResult(
+      UnorderedElementsAre("a", "a", AnyOf("b", "c")), v, &listener))
+      << listener.str();
+
+  string prefix =
+      "where no permutation of the elements can satisfy all matchers, "
+      "and the closest match is 2 of 3 matchers with the "
+      "pairings:\n";
+
+  // We have to be a bit loose here, because there are 4 valid max matches.
+  EXPECT_THAT(
+      listener.str(),
+      AnyOf(prefix + "{\n  " + EMString(0, 0) +
+                     ",\n  " + EMString(1, 2) + "\n}",
+            prefix + "{\n  " + EMString(0, 1) +
+                     ",\n  " + EMString(1, 2) + "\n}",
+            prefix + "{\n  " + EMString(0, 0) +
+                     ",\n  " + EMString(2, 2) + "\n}",
+            prefix + "{\n  " + EMString(0, 1) +
+                     ",\n  " + EMString(2, 2) + "\n}"));
+}
+
+TEST_F(UnorderedElementsAreTest, Describe) {
+  EXPECT_THAT(Describe<IntVec>(UnorderedElementsAre()),
+              Eq("is empty"));
+  EXPECT_THAT(
+      Describe<IntVec>(UnorderedElementsAre(345)),
+      Eq("has 1 element and that element is equal to 345"));
+  EXPECT_THAT(
+      Describe<IntVec>(UnorderedElementsAre(111, 222, 333)),
+      Eq("has 3 elements and there exists some permutation "
+         "of elements such that:\n"
+         " - element #0 is equal to 111, and\n"
+         " - element #1 is equal to 222, and\n"
+         " - element #2 is equal to 333"));
+}
+
+TEST_F(UnorderedElementsAreTest, DescribeNegation) {
+  EXPECT_THAT(DescribeNegation<IntVec>(UnorderedElementsAre()),
+              Eq("isn't empty"));
+  EXPECT_THAT(
+      DescribeNegation<IntVec>(UnorderedElementsAre(345)),
+      Eq("doesn't have 1 element, or has 1 element that isn't equal to 345"));
+  EXPECT_THAT(
+      DescribeNegation<IntVec>(UnorderedElementsAre(123, 234, 345)),
+      Eq("doesn't have 3 elements, or there exists no permutation "
+         "of elements such that:\n"
+         " - element #0 is equal to 123, and\n"
+         " - element #1 is equal to 234, and\n"
+         " - element #2 is equal to 345"));
+}
+
+namespace {
+
+// Used as a check on the more complex max flow method used in the
+// real testing::internal::FindMaxBipartiteMatching. This method is
+// compatible but runs in worst-case factorial time, so we only
+// use it in testing for small problem sizes.
+template <typename Graph>
+class BacktrackingMaxBPMState {
+ public:
+  // Does not take ownership of 'g'.
+  explicit BacktrackingMaxBPMState(const Graph* g) : graph_(g) { }
+
+  ElementMatcherPairs Compute() {
+    if (graph_->LhsSize() == 0 || graph_->RhsSize() == 0) {
+      return best_so_far_;
+    }
+    lhs_used_.assign(graph_->LhsSize(), kUnused);
+    rhs_used_.assign(graph_->RhsSize(), kUnused);
+    for (size_t irhs = 0; irhs < graph_->RhsSize(); ++irhs) {
+      matches_.clear();
+      RecurseInto(irhs);
+      if (best_so_far_.size() == graph_->RhsSize())
+        break;
+    }
+    return best_so_far_;
+  }
+
+ private:
+  static const size_t kUnused = static_cast<size_t>(-1);
+
+  void PushMatch(size_t lhs, size_t rhs) {
+    matches_.push_back(ElementMatcherPair(lhs, rhs));
+    lhs_used_[lhs] = rhs;
+    rhs_used_[rhs] = lhs;
+    if (matches_.size() > best_so_far_.size()) {
+      best_so_far_ = matches_;
+    }
+  }
+
+  void PopMatch() {
+    const ElementMatcherPair& back = matches_.back();
+    lhs_used_[back.first] = kUnused;
+    rhs_used_[back.second] = kUnused;
+    matches_.pop_back();
+  }
+
+  bool RecurseInto(size_t irhs) {
+    if (rhs_used_[irhs] != kUnused) {
+      return true;
+    }
+    for (size_t ilhs = 0; ilhs < graph_->LhsSize(); ++ilhs) {
+      if (lhs_used_[ilhs] != kUnused) {
+        continue;
+      }
+      if (!graph_->HasEdge(ilhs, irhs)) {
+        continue;
+      }
+      PushMatch(ilhs, irhs);
+      if (best_so_far_.size() == graph_->RhsSize()) {
+        return false;
+      }
+      for (size_t mi = irhs + 1; mi < graph_->RhsSize(); ++mi) {
+        if (!RecurseInto(mi)) return false;
+      }
+      PopMatch();
+    }
+    return true;
+  }
+
+  const Graph* graph_;  // not owned
+  std::vector<size_t> lhs_used_;
+  std::vector<size_t> rhs_used_;
+  ElementMatcherPairs matches_;
+  ElementMatcherPairs best_so_far_;
+};
+
+template <typename Graph>
+const size_t BacktrackingMaxBPMState<Graph>::kUnused;
+
+}  // namespace
+
+// Implement a simple backtracking algorithm to determine if it is possible
+// to find one element per matcher, without reusing elements.
+template <typename Graph>
+ElementMatcherPairs
+FindBacktrackingMaxBPM(const Graph& g) {
+  return BacktrackingMaxBPMState<Graph>(&g).Compute();
+}
+
+class BacktrackingBPMTest : public ::testing::Test { };
+
+// Tests the MaxBipartiteMatching algorithm with square matrices.
+// The single int param is the # of nodes on each of the left and right sides.
+class BipartiteTest : public ::testing::TestWithParam<int> { };
+
+// Verify all match graphs up to some moderate number of edges.
+TEST_P(BipartiteTest, Exhaustive) {
+  int nodes = GetParam();
+  MatchMatrix graph(nodes, nodes);
+  do {
+    ElementMatcherPairs matches =
+        internal::FindMaxBipartiteMatching(graph);
+    EXPECT_EQ(FindBacktrackingMaxBPM(graph).size(), matches.size())
+        << "graph: " << graph.DebugString();
+    // Check that all elements of matches are in the graph.
+    // Check that elements of first and second are unique.
+    std::vector<bool> seen_element(graph.LhsSize());
+    std::vector<bool> seen_matcher(graph.RhsSize());
+    SCOPED_TRACE(PrintToString(matches));
+    for (size_t i = 0; i < matches.size(); ++i) {
+      size_t ilhs = matches[i].first;
+      size_t irhs = matches[i].second;
+      EXPECT_TRUE(graph.HasEdge(ilhs, irhs));
+      EXPECT_FALSE(seen_element[ilhs]);
+      EXPECT_FALSE(seen_matcher[irhs]);
+      seen_element[ilhs] = true;
+      seen_matcher[irhs] = true;
+    }
+  } while (graph.NextGraph());
+}
+
+INSTANTIATE_TEST_CASE_P(AllGraphs, BipartiteTest,
+                        ::testing::Range(0, 5));
+
+// Parameterized by a pair interpreted as (LhsSize, RhsSize).
+class BipartiteNonSquareTest
+    : public ::testing::TestWithParam<std::pair<size_t, size_t> > {
+};
+
+TEST_F(BipartiteNonSquareTest, SimpleBacktracking) {
+  //   .......
+  // 0:-----\ :
+  // 1:---\ | :
+  // 2:---\ | :
+  // 3:-\ | | :
+  //  :.......:
+  //    0 1 2
+  MatchMatrix g(4, 3);
+  static const int kEdges[][2] = {{0, 2}, {1, 1}, {2, 1}, {3, 0}};
+  for (size_t i = 0; i < GTEST_ARRAY_SIZE_(kEdges); ++i) {
+    g.SetEdge(kEdges[i][0], kEdges[i][1], true);
+  }
+  EXPECT_THAT(FindBacktrackingMaxBPM(g),
+              ElementsAre(Pair(3, 0),
+                          Pair(AnyOf(1, 2), 1),
+                          Pair(0, 2))) << g.DebugString();
+}
+
+// Verify a few nonsquare matrices.
+TEST_P(BipartiteNonSquareTest, Exhaustive) {
+  size_t nlhs = GetParam().first;
+  size_t nrhs = GetParam().second;
+  MatchMatrix graph(nlhs, nrhs);
+  do {
+    EXPECT_EQ(FindBacktrackingMaxBPM(graph).size(),
+              internal::FindMaxBipartiteMatching(graph).size())
+        << "graph: " << graph.DebugString()
+        << "\nbacktracking: "
+        << PrintToString(FindBacktrackingMaxBPM(graph))
+        << "\nmax flow: "
+        << PrintToString(internal::FindMaxBipartiteMatching(graph));
+  } while (graph.NextGraph());
+}
+
+INSTANTIATE_TEST_CASE_P(AllGraphs, BipartiteNonSquareTest,
+    testing::Values(
+        std::make_pair(1, 2),
+        std::make_pair(2, 1),
+        std::make_pair(3, 2),
+        std::make_pair(2, 3),
+        std::make_pair(4, 1),
+        std::make_pair(1, 4),
+        std::make_pair(4, 3),
+        std::make_pair(3, 4)));
+
+class BipartiteRandomTest
+    : public ::testing::TestWithParam<std::pair<int, int> > {
+};
+
+// Verifies a large sample of larger graphs.
+TEST_P(BipartiteRandomTest, LargerNets) {
+  int nodes = GetParam().first;
+  int iters = GetParam().second;
+  MatchMatrix graph(nodes, nodes);
+
+  testing::internal::Int32 seed = GTEST_FLAG(random_seed);
+  if (seed == 0) {
+    seed = static_cast<testing::internal::Int32>(time(NULL));
+  }
+
+  for (; iters > 0; --iters, ++seed) {
+    srand(static_cast<int>(seed));
+    graph.Randomize();
+    EXPECT_EQ(FindBacktrackingMaxBPM(graph).size(),
+              internal::FindMaxBipartiteMatching(graph).size())
+        << " graph: " << graph.DebugString()
+        << "\nTo reproduce the failure, rerun the test with the flag"
+           " --" << GTEST_FLAG_PREFIX_ << "random_seed=" << seed;
+  }
+}
+
+// Test argument is a std::pair<int, int> representing (nodes, iters).
+INSTANTIATE_TEST_CASE_P(Samples, BipartiteRandomTest,
+    testing::Values(
+        std::make_pair(5, 10000),
+        std::make_pair(6, 5000),
+        std::make_pair(7, 2000),
+        std::make_pair(8, 500),
+        std::make_pair(9, 100)));
+
+// Tests IsReadableTypeName().
+
+TEST(IsReadableTypeNameTest, ReturnsTrueForShortNames) {
+  EXPECT_TRUE(IsReadableTypeName("int"));
+  EXPECT_TRUE(IsReadableTypeName("const unsigned char*"));
+  EXPECT_TRUE(IsReadableTypeName("MyMap<int, void*>"));
+  EXPECT_TRUE(IsReadableTypeName("void (*)(int, bool)"));
+}
+
+TEST(IsReadableTypeNameTest, ReturnsTrueForLongNonTemplateNonFunctionNames) {
+  EXPECT_TRUE(IsReadableTypeName("my_long_namespace::MyClassName"));
+  EXPECT_TRUE(IsReadableTypeName("int [5][6][7][8][9][10][11]"));
+  EXPECT_TRUE(IsReadableTypeName("my_namespace::MyOuterClass::MyInnerClass"));
+}
+
+TEST(IsReadableTypeNameTest, ReturnsFalseForLongTemplateNames) {
+  EXPECT_FALSE(
+      IsReadableTypeName("basic_string<char, std::char_traits<char> >"));
+  EXPECT_FALSE(IsReadableTypeName("std::vector<int, std::alloc_traits<int> >"));
+}
+
+TEST(IsReadableTypeNameTest, ReturnsFalseForLongFunctionTypeNames) {
+  EXPECT_FALSE(IsReadableTypeName("void (&)(int, bool, char, float)"));
+}
+
+// Tests JoinAsTuple().
+
+TEST(JoinAsTupleTest, JoinsEmptyTuple) {
+  EXPECT_EQ("", JoinAsTuple(Strings()));
+}
+
+TEST(JoinAsTupleTest, JoinsOneTuple) {
+  const char* fields[] = {"1"};
+  EXPECT_EQ("1", JoinAsTuple(Strings(fields, fields + 1)));
+}
+
+TEST(JoinAsTupleTest, JoinsTwoTuple) {
+  const char* fields[] = {"1", "a"};
+  EXPECT_EQ("(1, a)", JoinAsTuple(Strings(fields, fields + 2)));
+}
+
+TEST(JoinAsTupleTest, JoinsTenTuple) {
+  const char* fields[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
+  EXPECT_EQ("(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)",
+            JoinAsTuple(Strings(fields, fields + 10)));
+}
+
+// Tests FormatMatcherDescription().
+
+TEST(FormatMatcherDescriptionTest, WorksForEmptyDescription) {
+  EXPECT_EQ("is even",
+            FormatMatcherDescription(false, "IsEven", Strings()));
+  EXPECT_EQ("not (is even)",
+            FormatMatcherDescription(true, "IsEven", Strings()));
+
+  const char* params[] = {"5"};
+  EXPECT_EQ("equals 5",
+            FormatMatcherDescription(false, "Equals",
+                                     Strings(params, params + 1)));
+
+  const char* params2[] = {"5", "8"};
+  EXPECT_EQ("is in range (5, 8)",
+            FormatMatcherDescription(false, "IsInRange",
+                                     Strings(params2, params2 + 2)));
+}
+
+// Tests PolymorphicMatcher::mutable_impl().
+TEST(PolymorphicMatcherTest, CanAccessMutableImpl) {
+  PolymorphicMatcher<DivisibleByImpl> m(DivisibleByImpl(42));
+  DivisibleByImpl& impl = m.mutable_impl();
+  EXPECT_EQ(42, impl.divider());
+
+  impl.set_divider(0);
+  EXPECT_EQ(0, m.mutable_impl().divider());
+}
+
+// Tests PolymorphicMatcher::impl().
+TEST(PolymorphicMatcherTest, CanAccessImpl) {
+  const PolymorphicMatcher<DivisibleByImpl> m(DivisibleByImpl(42));
+  const DivisibleByImpl& impl = m.impl();
+  EXPECT_EQ(42, impl.divider());
+}
+
+TEST(MatcherTupleTest, ExplainsMatchFailure) {
+  stringstream ss1;
+  ExplainMatchFailureTupleTo(make_tuple(Matcher<char>(Eq('a')), GreaterThan(5)),
+                             make_tuple('a', 10), &ss1);
+  EXPECT_EQ("", ss1.str());  // Successful match.
+
+  stringstream ss2;
+  ExplainMatchFailureTupleTo(make_tuple(GreaterThan(5), Matcher<char>(Eq('a'))),
+                             make_tuple(2, 'b'), &ss2);
+  EXPECT_EQ("  Expected arg #0: is > 5\n"
+            "           Actual: 2, which is 3 less than 5\n"
+            "  Expected arg #1: is equal to 'a' (97, 0x61)\n"
+            "           Actual: 'b' (98, 0x62)\n",
+            ss2.str());  // Failed match where both arguments need explanation.
+
+  stringstream ss3;
+  ExplainMatchFailureTupleTo(make_tuple(GreaterThan(5), Matcher<char>(Eq('a'))),
+                             make_tuple(2, 'a'), &ss3);
+  EXPECT_EQ("  Expected arg #0: is > 5\n"
+            "           Actual: 2, which is 3 less than 5\n",
+            ss3.str());  // Failed match where only one argument needs
+                         // explanation.
+}
+
+// Tests Each().
+
+TEST(EachTest, ExplainsMatchResultCorrectly) {
+  set<int> a;  // empty
+
+  Matcher<set<int> > m = Each(2);
+  EXPECT_EQ("", Explain(m, a));
+
+  Matcher<const int(&)[1]> n = Each(1);  // NOLINT
+
+  const int b[1] = {1};
+  EXPECT_EQ("", Explain(n, b));
+
+  n = Each(3);
+  EXPECT_EQ("whose element #0 doesn't match", Explain(n, b));
+
+  a.insert(1);
+  a.insert(2);
+  a.insert(3);
+  m = Each(GreaterThan(0));
+  EXPECT_EQ("", Explain(m, a));
+
+  m = Each(GreaterThan(10));
+  EXPECT_EQ("whose element #0 doesn't match, which is 9 less than 10",
+            Explain(m, a));
+}
+
+TEST(EachTest, DescribesItselfCorrectly) {
+  Matcher<vector<int> > m = Each(1);
+  EXPECT_EQ("only contains elements that is equal to 1", Describe(m));
+
+  Matcher<vector<int> > m2 = Not(m);
+  EXPECT_EQ("contains some element that isn't equal to 1", Describe(m2));
+}
+
+TEST(EachTest, MatchesVectorWhenAllElementsMatch) {
+  vector<int> some_vector;
+  EXPECT_THAT(some_vector, Each(1));
+  some_vector.push_back(3);
+  EXPECT_THAT(some_vector, Not(Each(1)));
+  EXPECT_THAT(some_vector, Each(3));
+  some_vector.push_back(1);
+  some_vector.push_back(2);
+  EXPECT_THAT(some_vector, Not(Each(3)));
+  EXPECT_THAT(some_vector, Each(Lt(3.5)));
+
+  vector<string> another_vector;
+  another_vector.push_back("fee");
+  EXPECT_THAT(another_vector, Each(string("fee")));
+  another_vector.push_back("fie");
+  another_vector.push_back("foe");
+  another_vector.push_back("fum");
+  EXPECT_THAT(another_vector, Not(Each(string("fee"))));
+}
+
+TEST(EachTest, MatchesMapWhenAllElementsMatch) {
+  map<const char*, int> my_map;
+  const char* bar = "a string";
+  my_map[bar] = 2;
+  EXPECT_THAT(my_map, Each(make_pair(bar, 2)));
+
+  map<string, int> another_map;
+  EXPECT_THAT(another_map, Each(make_pair(string("fee"), 1)));
+  another_map["fee"] = 1;
+  EXPECT_THAT(another_map, Each(make_pair(string("fee"), 1)));
+  another_map["fie"] = 2;
+  another_map["foe"] = 3;
+  another_map["fum"] = 4;
+  EXPECT_THAT(another_map, Not(Each(make_pair(string("fee"), 1))));
+  EXPECT_THAT(another_map, Not(Each(make_pair(string("fum"), 1))));
+  EXPECT_THAT(another_map, Each(Pair(_, Gt(0))));
+}
+
+TEST(EachTest, AcceptsMatcher) {
+  const int a[] = {1, 2, 3};
+  EXPECT_THAT(a, Each(Gt(0)));
+  EXPECT_THAT(a, Not(Each(Gt(1))));
+}
+
+TEST(EachTest, WorksForNativeArrayAsTuple) {
+  const int a[] = {1, 2};
+  const int* const pointer = a;
+  EXPECT_THAT(make_tuple(pointer, 2), Each(Gt(0)));
+  EXPECT_THAT(make_tuple(pointer, 2), Not(Each(Gt(1))));
+}
+
+// For testing Pointwise().
+class IsHalfOfMatcher {
+ public:
+  template <typename T1, typename T2>
+  bool MatchAndExplain(const tuple<T1, T2>& a_pair,
+                       MatchResultListener* listener) const {
+    if (get<0>(a_pair) == get<1>(a_pair)/2) {
+      *listener << "where the second is " << get<1>(a_pair);
+      return true;
+    } else {
+      *listener << "where the second/2 is " << get<1>(a_pair)/2;
+      return false;
+    }
+  }
+
+  void DescribeTo(ostream* os) const {
+    *os << "are a pair where the first is half of the second";
+  }
+
+  void DescribeNegationTo(ostream* os) const {
+    *os << "are a pair where the first isn't half of the second";
+  }
+};
+
+PolymorphicMatcher<IsHalfOfMatcher> IsHalfOf() {
+  return MakePolymorphicMatcher(IsHalfOfMatcher());
+}
+
+TEST(PointwiseTest, DescribesSelf) {
+  vector<int> rhs;
+  rhs.push_back(1);
+  rhs.push_back(2);
+  rhs.push_back(3);
+  const Matcher<const vector<int>&> m = Pointwise(IsHalfOf(), rhs);
+  EXPECT_EQ("contains 3 values, where each value and its corresponding value "
+            "in { 1, 2, 3 } are a pair where the first is half of the second",
+            Describe(m));
+  EXPECT_EQ("doesn't contain exactly 3 values, or contains a value x at some "
+            "index i where x and the i-th value of { 1, 2, 3 } are a pair "
+            "where the first isn't half of the second",
+            DescribeNegation(m));
+}
+
+TEST(PointwiseTest, MakesCopyOfRhs) {
+  list<signed char> rhs;
+  rhs.push_back(2);
+  rhs.push_back(4);
+
+  int lhs[] = {1, 2};
+  const Matcher<const int (&)[2]> m = Pointwise(IsHalfOf(), rhs);
+  EXPECT_THAT(lhs, m);
+
+  // Changing rhs now shouldn't affect m, which made a copy of rhs.
+  rhs.push_back(6);
+  EXPECT_THAT(lhs, m);
+}
+
+TEST(PointwiseTest, WorksForLhsNativeArray) {
+  const int lhs[] = {1, 2, 3};
+  vector<int> rhs;
+  rhs.push_back(2);
+  rhs.push_back(4);
+  rhs.push_back(6);
+  EXPECT_THAT(lhs, Pointwise(Lt(), rhs));
+  EXPECT_THAT(lhs, Not(Pointwise(Gt(), rhs)));
+}
+
+TEST(PointwiseTest, WorksForRhsNativeArray) {
+  const int rhs[] = {1, 2, 3};
+  vector<int> lhs;
+  lhs.push_back(2);
+  lhs.push_back(4);
+  lhs.push_back(6);
+  EXPECT_THAT(lhs, Pointwise(Gt(), rhs));
+  EXPECT_THAT(lhs, Not(Pointwise(Lt(), rhs)));
+}
+
+#if GTEST_HAS_STD_INITIALIZER_LIST_
+
+TEST(PointwiseTest, WorksForRhsInitializerList) {
+  const vector<int> lhs{2, 4, 6};
+  EXPECT_THAT(lhs, Pointwise(Gt(), {1, 2, 3}));
+  EXPECT_THAT(lhs, Not(Pointwise(Lt(), {3, 3, 7})));
+}
+
+#endif  // GTEST_HAS_STD_INITIALIZER_LIST_
+
+TEST(PointwiseTest, RejectsWrongSize) {
+  const double lhs[2] = {1, 2};
+  const int rhs[1] = {0};
+  EXPECT_THAT(lhs, Not(Pointwise(Gt(), rhs)));
+  EXPECT_EQ("which contains 2 values",
+            Explain(Pointwise(Gt(), rhs), lhs));
+
+  const int rhs2[3] = {0, 1, 2};
+  EXPECT_THAT(lhs, Not(Pointwise(Gt(), rhs2)));
+}
+
+TEST(PointwiseTest, RejectsWrongContent) {
+  const double lhs[3] = {1, 2, 3};
+  const int rhs[3] = {2, 6, 4};
+  EXPECT_THAT(lhs, Not(Pointwise(IsHalfOf(), rhs)));
+  EXPECT_EQ("where the value pair (2, 6) at index #1 don't match, "
+            "where the second/2 is 3",
+            Explain(Pointwise(IsHalfOf(), rhs), lhs));
+}
+
+TEST(PointwiseTest, AcceptsCorrectContent) {
+  const double lhs[3] = {1, 2, 3};
+  const int rhs[3] = {2, 4, 6};
+  EXPECT_THAT(lhs, Pointwise(IsHalfOf(), rhs));
+  EXPECT_EQ("", Explain(Pointwise(IsHalfOf(), rhs), lhs));
+}
+
+TEST(PointwiseTest, AllowsMonomorphicInnerMatcher) {
+  const double lhs[3] = {1, 2, 3};
+  const int rhs[3] = {2, 4, 6};
+  const Matcher<tuple<const double&, const int&> > m1 = IsHalfOf();
+  EXPECT_THAT(lhs, Pointwise(m1, rhs));
+  EXPECT_EQ("", Explain(Pointwise(m1, rhs), lhs));
+
+  // This type works as a tuple<const double&, const int&> can be
+  // implicitly cast to tuple<double, int>.
+  const Matcher<tuple<double, int> > m2 = IsHalfOf();
+  EXPECT_THAT(lhs, Pointwise(m2, rhs));
+  EXPECT_EQ("", Explain(Pointwise(m2, rhs), lhs));
+}
+
+TEST(UnorderedPointwiseTest, DescribesSelf) {
+  vector<int> rhs;
+  rhs.push_back(1);
+  rhs.push_back(2);
+  rhs.push_back(3);
+  const Matcher<const vector<int>&> m = UnorderedPointwise(IsHalfOf(), rhs);
+  EXPECT_EQ(
+      "has 3 elements and there exists some permutation of elements such "
+      "that:\n"
+      " - element #0 and 1 are a pair where the first is half of the second, "
+      "and\n"
+      " - element #1 and 2 are a pair where the first is half of the second, "
+      "and\n"
+      " - element #2 and 3 are a pair where the first is half of the second",
+      Describe(m));
+  EXPECT_EQ(
+      "doesn't have 3 elements, or there exists no permutation of elements "
+      "such that:\n"
+      " - element #0 and 1 are a pair where the first is half of the second, "
+      "and\n"
+      " - element #1 and 2 are a pair where the first is half of the second, "
+      "and\n"
+      " - element #2 and 3 are a pair where the first is half of the second",
+      DescribeNegation(m));
+}
+
+TEST(UnorderedPointwiseTest, MakesCopyOfRhs) {
+  list<signed char> rhs;
+  rhs.push_back(2);
+  rhs.push_back(4);
+
+  int lhs[] = {2, 1};
+  const Matcher<const int (&)[2]> m = UnorderedPointwise(IsHalfOf(), rhs);
+  EXPECT_THAT(lhs, m);
+
+  // Changing rhs now shouldn't affect m, which made a copy of rhs.
+  rhs.push_back(6);
+  EXPECT_THAT(lhs, m);
+}
+
+TEST(UnorderedPointwiseTest, WorksForLhsNativeArray) {
+  const int lhs[] = {1, 2, 3};
+  vector<int> rhs;
+  rhs.push_back(4);
+  rhs.push_back(6);
+  rhs.push_back(2);
+  EXPECT_THAT(lhs, UnorderedPointwise(Lt(), rhs));
+  EXPECT_THAT(lhs, Not(UnorderedPointwise(Gt(), rhs)));
+}
+
+TEST(UnorderedPointwiseTest, WorksForRhsNativeArray) {
+  const int rhs[] = {1, 2, 3};
+  vector<int> lhs;
+  lhs.push_back(4);
+  lhs.push_back(2);
+  lhs.push_back(6);
+  EXPECT_THAT(lhs, UnorderedPointwise(Gt(), rhs));
+  EXPECT_THAT(lhs, Not(UnorderedPointwise(Lt(), rhs)));
+}
+
+#if GTEST_HAS_STD_INITIALIZER_LIST_
+
+TEST(UnorderedPointwiseTest, WorksForRhsInitializerList) {
+  const vector<int> lhs{2, 4, 6};
+  EXPECT_THAT(lhs, UnorderedPointwise(Gt(), {5, 1, 3}));
+  EXPECT_THAT(lhs, Not(UnorderedPointwise(Lt(), {1, 1, 7})));
+}
+
+#endif  // GTEST_HAS_STD_INITIALIZER_LIST_
+
+TEST(UnorderedPointwiseTest, RejectsWrongSize) {
+  const double lhs[2] = {1, 2};
+  const int rhs[1] = {0};
+  EXPECT_THAT(lhs, Not(UnorderedPointwise(Gt(), rhs)));
+  EXPECT_EQ("which has 2 elements",
+            Explain(UnorderedPointwise(Gt(), rhs), lhs));
+
+  const int rhs2[3] = {0, 1, 2};
+  EXPECT_THAT(lhs, Not(UnorderedPointwise(Gt(), rhs2)));
+}
+
+TEST(UnorderedPointwiseTest, RejectsWrongContent) {
+  const double lhs[3] = {1, 2, 3};
+  const int rhs[3] = {2, 6, 6};
+  EXPECT_THAT(lhs, Not(UnorderedPointwise(IsHalfOf(), rhs)));
+  EXPECT_EQ("where the following elements don't match any matchers:\n"
+            "element #1: 2",
+            Explain(UnorderedPointwise(IsHalfOf(), rhs), lhs));
+}
+
+TEST(UnorderedPointwiseTest, AcceptsCorrectContentInSameOrder) {
+  const double lhs[3] = {1, 2, 3};
+  const int rhs[3] = {2, 4, 6};
+  EXPECT_THAT(lhs, UnorderedPointwise(IsHalfOf(), rhs));
+}
+
+TEST(UnorderedPointwiseTest, AcceptsCorrectContentInDifferentOrder) {
+  const double lhs[3] = {1, 2, 3};
+  const int rhs[3] = {6, 4, 2};
+  EXPECT_THAT(lhs, UnorderedPointwise(IsHalfOf(), rhs));
+}
+
+TEST(UnorderedPointwiseTest, AllowsMonomorphicInnerMatcher) {
+  const double lhs[3] = {1, 2, 3};
+  const int rhs[3] = {4, 6, 2};
+  const Matcher<tuple<const double&, const int&> > m1 = IsHalfOf();
+  EXPECT_THAT(lhs, UnorderedPointwise(m1, rhs));
+
+  // This type works as a tuple<const double&, const int&> can be
+  // implicitly cast to tuple<double, int>.
+  const Matcher<tuple<double, int> > m2 = IsHalfOf();
+  EXPECT_THAT(lhs, UnorderedPointwise(m2, rhs));
+}
+
+}  // namespace gmock_matchers_test
+}  // namespace testing
diff --git a/third_party/googletest/googlemock/test/gmock-more-actions_test.cc b/third_party/googletest/googlemock/test/gmock-more-actions_test.cc
new file mode 100644
index 0000000..9477fe9
--- /dev/null
+++ b/third_party/googletest/googlemock/test/gmock-more-actions_test.cc
@@ -0,0 +1,705 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests the built-in actions in gmock-more-actions.h.
+
+#include "gmock/gmock-more-actions.h"
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "gtest/internal/gtest-linked_ptr.h"
+
+namespace testing {
+namespace gmock_more_actions_test {
+
+using ::std::plus;
+using ::std::string;
+using testing::get;
+using testing::make_tuple;
+using testing::tuple;
+using testing::tuple_element;
+using testing::_;
+using testing::Action;
+using testing::ActionInterface;
+using testing::DeleteArg;
+using testing::Invoke;
+using testing::Return;
+using testing::ReturnArg;
+using testing::ReturnPointee;
+using testing::SaveArg;
+using testing::SaveArgPointee;
+using testing::SetArgReferee;
+using testing::StaticAssertTypeEq;
+using testing::Unused;
+using testing::WithArg;
+using testing::WithoutArgs;
+using testing::internal::linked_ptr;
+
+// For suppressing compiler warnings on conversion possibly losing precision.
+inline short Short(short n) { return n; }  // NOLINT
+inline char Char(char ch) { return ch; }
+
+// Sample functions and functors for testing Invoke() and etc.
+int Nullary() { return 1; }
+
+class NullaryFunctor {
+ public:
+  int operator()() { return 2; }
+};
+
+bool g_done = false;
+void VoidNullary() { g_done = true; }
+
+class VoidNullaryFunctor {
+ public:
+  void operator()() { g_done = true; }
+};
+
+bool Unary(int x) { return x < 0; }
+
+const char* Plus1(const char* s) { return s + 1; }
+
+void VoidUnary(int /* n */) { g_done = true; }
+
+bool ByConstRef(const string& s) { return s == "Hi"; }
+
+const double g_double = 0;
+bool ReferencesGlobalDouble(const double& x) { return &x == &g_double; }
+
+string ByNonConstRef(string& s) { return s += "+"; }  // NOLINT
+
+struct UnaryFunctor {
+  int operator()(bool x) { return x ? 1 : -1; }
+};
+
+const char* Binary(const char* input, short n) { return input + n; }  // NOLINT
+
+void VoidBinary(int, char) { g_done = true; }
+
+int Ternary(int x, char y, short z) { return x + y + z; }  // NOLINT
+
+void VoidTernary(int, char, bool) { g_done = true; }
+
+int SumOf4(int a, int b, int c, int d) { return a + b + c + d; }
+
+int SumOfFirst2(int a, int b, Unused, Unused) { return a + b; }
+
+void VoidFunctionWithFourArguments(char, int, float, double) { g_done = true; }
+
+string Concat4(const char* s1, const char* s2, const char* s3,
+               const char* s4) {
+  return string(s1) + s2 + s3 + s4;
+}
+
+int SumOf5(int a, int b, int c, int d, int e) { return a + b + c + d + e; }
+
+struct SumOf5Functor {
+  int operator()(int a, int b, int c, int d, int e) {
+    return a + b + c + d + e;
+  }
+};
+
+string Concat5(const char* s1, const char* s2, const char* s3,
+               const char* s4, const char* s5) {
+  return string(s1) + s2 + s3 + s4 + s5;
+}
+
+int SumOf6(int a, int b, int c, int d, int e, int f) {
+  return a + b + c + d + e + f;
+}
+
+struct SumOf6Functor {
+  int operator()(int a, int b, int c, int d, int e, int f) {
+    return a + b + c + d + e + f;
+  }
+};
+
+string Concat6(const char* s1, const char* s2, const char* s3,
+               const char* s4, const char* s5, const char* s6) {
+  return string(s1) + s2 + s3 + s4 + s5 + s6;
+}
+
+string Concat7(const char* s1, const char* s2, const char* s3,
+               const char* s4, const char* s5, const char* s6,
+               const char* s7) {
+  return string(s1) + s2 + s3 + s4 + s5 + s6 + s7;
+}
+
+string Concat8(const char* s1, const char* s2, const char* s3,
+               const char* s4, const char* s5, const char* s6,
+               const char* s7, const char* s8) {
+  return string(s1) + s2 + s3 + s4 + s5 + s6 + s7 + s8;
+}
+
+string Concat9(const char* s1, const char* s2, const char* s3,
+               const char* s4, const char* s5, const char* s6,
+               const char* s7, const char* s8, const char* s9) {
+  return string(s1) + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9;
+}
+
+string Concat10(const char* s1, const char* s2, const char* s3,
+                const char* s4, const char* s5, const char* s6,
+                const char* s7, const char* s8, const char* s9,
+                const char* s10) {
+  return string(s1) + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10;
+}
+
+class Foo {
+ public:
+  Foo() : value_(123) {}
+
+  int Nullary() const { return value_; }
+
+  short Unary(long x) { return static_cast<short>(value_ + x); }  // NOLINT
+
+  string Binary(const string& str, char c) const { return str + c; }
+
+  int Ternary(int x, bool y, char z) { return value_ + x + y*z; }
+
+  int SumOf4(int a, int b, int c, int d) const {
+    return a + b + c + d + value_;
+  }
+
+  int SumOfLast2(Unused, Unused, int a, int b) const { return a + b; }
+
+  int SumOf5(int a, int b, int c, int d, int e) { return a + b + c + d + e; }
+
+  int SumOf6(int a, int b, int c, int d, int e, int f) {
+    return a + b + c + d + e + f;
+  }
+
+  string Concat7(const char* s1, const char* s2, const char* s3,
+                 const char* s4, const char* s5, const char* s6,
+                 const char* s7) {
+    return string(s1) + s2 + s3 + s4 + s5 + s6 + s7;
+  }
+
+  string Concat8(const char* s1, const char* s2, const char* s3,
+                 const char* s4, const char* s5, const char* s6,
+                 const char* s7, const char* s8) {
+    return string(s1) + s2 + s3 + s4 + s5 + s6 + s7 + s8;
+  }
+
+  string Concat9(const char* s1, const char* s2, const char* s3,
+                 const char* s4, const char* s5, const char* s6,
+                 const char* s7, const char* s8, const char* s9) {
+    return string(s1) + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9;
+  }
+
+  string Concat10(const char* s1, const char* s2, const char* s3,
+                  const char* s4, const char* s5, const char* s6,
+                  const char* s7, const char* s8, const char* s9,
+                  const char* s10) {
+    return string(s1) + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10;
+  }
+
+ private:
+  int value_;
+};
+
+// Tests using Invoke() with a nullary function.
+TEST(InvokeTest, Nullary) {
+  Action<int()> a = Invoke(Nullary);  // NOLINT
+  EXPECT_EQ(1, a.Perform(make_tuple()));
+}
+
+// Tests using Invoke() with a unary function.
+TEST(InvokeTest, Unary) {
+  Action<bool(int)> a = Invoke(Unary);  // NOLINT
+  EXPECT_FALSE(a.Perform(make_tuple(1)));
+  EXPECT_TRUE(a.Perform(make_tuple(-1)));
+}
+
+// Tests using Invoke() with a binary function.
+TEST(InvokeTest, Binary) {
+  Action<const char*(const char*, short)> a = Invoke(Binary);  // NOLINT
+  const char* p = "Hello";
+  EXPECT_EQ(p + 2, a.Perform(make_tuple(p, Short(2))));
+}
+
+// Tests using Invoke() with a ternary function.
+TEST(InvokeTest, Ternary) {
+  Action<int(int, char, short)> a = Invoke(Ternary);  // NOLINT
+  EXPECT_EQ(6, a.Perform(make_tuple(1, '\2', Short(3))));
+}
+
+// Tests using Invoke() with a 4-argument function.
+TEST(InvokeTest, FunctionThatTakes4Arguments) {
+  Action<int(int, int, int, int)> a = Invoke(SumOf4);  // NOLINT
+  EXPECT_EQ(1234, a.Perform(make_tuple(1000, 200, 30, 4)));
+}
+
+// Tests using Invoke() with a 5-argument function.
+TEST(InvokeTest, FunctionThatTakes5Arguments) {
+  Action<int(int, int, int, int, int)> a = Invoke(SumOf5);  // NOLINT
+  EXPECT_EQ(12345, a.Perform(make_tuple(10000, 2000, 300, 40, 5)));
+}
+
+// Tests using Invoke() with a 6-argument function.
+TEST(InvokeTest, FunctionThatTakes6Arguments) {
+  Action<int(int, int, int, int, int, int)> a = Invoke(SumOf6);  // NOLINT
+  EXPECT_EQ(123456, a.Perform(make_tuple(100000, 20000, 3000, 400, 50, 6)));
+}
+
+// A helper that turns the type of a C-string literal from const
+// char[N] to const char*.
+inline const char* CharPtr(const char* s) { return s; }
+
+// Tests using Invoke() with a 7-argument function.
+TEST(InvokeTest, FunctionThatTakes7Arguments) {
+  Action<string(const char*, const char*, const char*, const char*,
+                const char*, const char*, const char*)> a =
+      Invoke(Concat7);
+  EXPECT_EQ("1234567",
+            a.Perform(make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
+                                 CharPtr("4"), CharPtr("5"), CharPtr("6"),
+                                 CharPtr("7"))));
+}
+
+// Tests using Invoke() with a 8-argument function.
+TEST(InvokeTest, FunctionThatTakes8Arguments) {
+  Action<string(const char*, const char*, const char*, const char*,
+                const char*, const char*, const char*, const char*)> a =
+      Invoke(Concat8);
+  EXPECT_EQ("12345678",
+            a.Perform(make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
+                                 CharPtr("4"), CharPtr("5"), CharPtr("6"),
+                                 CharPtr("7"), CharPtr("8"))));
+}
+
+// Tests using Invoke() with a 9-argument function.
+TEST(InvokeTest, FunctionThatTakes9Arguments) {
+  Action<string(const char*, const char*, const char*, const char*,
+                const char*, const char*, const char*, const char*,
+                const char*)> a = Invoke(Concat9);
+  EXPECT_EQ("123456789",
+            a.Perform(make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
+                                 CharPtr("4"), CharPtr("5"), CharPtr("6"),
+                                 CharPtr("7"), CharPtr("8"), CharPtr("9"))));
+}
+
+// Tests using Invoke() with a 10-argument function.
+TEST(InvokeTest, FunctionThatTakes10Arguments) {
+  Action<string(const char*, const char*, const char*, const char*,
+                const char*, const char*, const char*, const char*,
+                const char*, const char*)> a = Invoke(Concat10);
+  EXPECT_EQ("1234567890",
+            a.Perform(make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
+                                 CharPtr("4"), CharPtr("5"), CharPtr("6"),
+                                 CharPtr("7"), CharPtr("8"), CharPtr("9"),
+                                 CharPtr("0"))));
+}
+
+// Tests using Invoke() with functions with parameters declared as Unused.
+TEST(InvokeTest, FunctionWithUnusedParameters) {
+  Action<int(int, int, double, const string&)> a1 =
+      Invoke(SumOfFirst2);
+  EXPECT_EQ(12, a1.Perform(make_tuple(10, 2, 5.6, string("hi"))));
+
+  Action<int(int, int, bool, int*)> a2 =
+      Invoke(SumOfFirst2);
+  EXPECT_EQ(23, a2.Perform(make_tuple(20, 3, true, static_cast<int*>(NULL))));
+}
+
+// Tests using Invoke() with methods with parameters declared as Unused.
+TEST(InvokeTest, MethodWithUnusedParameters) {
+  Foo foo;
+  Action<int(string, bool, int, int)> a1 =
+      Invoke(&foo, &Foo::SumOfLast2);
+  EXPECT_EQ(12, a1.Perform(make_tuple(CharPtr("hi"), true, 10, 2)));
+
+  Action<int(char, double, int, int)> a2 =
+      Invoke(&foo, &Foo::SumOfLast2);
+  EXPECT_EQ(23, a2.Perform(make_tuple('a', 2.5, 20, 3)));
+}
+
+// Tests using Invoke() with a functor.
+TEST(InvokeTest, Functor) {
+  Action<long(long, int)> a = Invoke(plus<long>());  // NOLINT
+  EXPECT_EQ(3L, a.Perform(make_tuple(1, 2)));
+}
+
+// Tests using Invoke(f) as an action of a compatible type.
+TEST(InvokeTest, FunctionWithCompatibleType) {
+  Action<long(int, short, char, bool)> a = Invoke(SumOf4);  // NOLINT
+  EXPECT_EQ(4321, a.Perform(make_tuple(4000, Short(300), Char(20), true)));
+}
+
+// Tests using Invoke() with an object pointer and a method pointer.
+
+// Tests using Invoke() with a nullary method.
+TEST(InvokeMethodTest, Nullary) {
+  Foo foo;
+  Action<int()> a = Invoke(&foo, &Foo::Nullary);  // NOLINT
+  EXPECT_EQ(123, a.Perform(make_tuple()));
+}
+
+// Tests using Invoke() with a unary method.
+TEST(InvokeMethodTest, Unary) {
+  Foo foo;
+  Action<short(long)> a = Invoke(&foo, &Foo::Unary);  // NOLINT
+  EXPECT_EQ(4123, a.Perform(make_tuple(4000)));
+}
+
+// Tests using Invoke() with a binary method.
+TEST(InvokeMethodTest, Binary) {
+  Foo foo;
+  Action<string(const string&, char)> a = Invoke(&foo, &Foo::Binary);
+  string s("Hell");
+  EXPECT_EQ("Hello", a.Perform(make_tuple(s, 'o')));
+}
+
+// Tests using Invoke() with a ternary method.
+TEST(InvokeMethodTest, Ternary) {
+  Foo foo;
+  Action<int(int, bool, char)> a = Invoke(&foo, &Foo::Ternary);  // NOLINT
+  EXPECT_EQ(1124, a.Perform(make_tuple(1000, true, Char(1))));
+}
+
+// Tests using Invoke() with a 4-argument method.
+TEST(InvokeMethodTest, MethodThatTakes4Arguments) {
+  Foo foo;
+  Action<int(int, int, int, int)> a = Invoke(&foo, &Foo::SumOf4);  // NOLINT
+  EXPECT_EQ(1357, a.Perform(make_tuple(1000, 200, 30, 4)));
+}
+
+// Tests using Invoke() with a 5-argument method.
+TEST(InvokeMethodTest, MethodThatTakes5Arguments) {
+  Foo foo;
+  Action<int(int, int, int, int, int)> a = Invoke(&foo, &Foo::SumOf5);  // NOLINT
+  EXPECT_EQ(12345, a.Perform(make_tuple(10000, 2000, 300, 40, 5)));
+}
+
+// Tests using Invoke() with a 6-argument method.
+TEST(InvokeMethodTest, MethodThatTakes6Arguments) {
+  Foo foo;
+  Action<int(int, int, int, int, int, int)> a =  // NOLINT
+      Invoke(&foo, &Foo::SumOf6);
+  EXPECT_EQ(123456, a.Perform(make_tuple(100000, 20000, 3000, 400, 50, 6)));
+}
+
+// Tests using Invoke() with a 7-argument method.
+TEST(InvokeMethodTest, MethodThatTakes7Arguments) {
+  Foo foo;
+  Action<string(const char*, const char*, const char*, const char*,
+                const char*, const char*, const char*)> a =
+      Invoke(&foo, &Foo::Concat7);
+  EXPECT_EQ("1234567",
+            a.Perform(make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
+                                 CharPtr("4"), CharPtr("5"), CharPtr("6"),
+                                 CharPtr("7"))));
+}
+
+// Tests using Invoke() with a 8-argument method.
+TEST(InvokeMethodTest, MethodThatTakes8Arguments) {
+  Foo foo;
+  Action<string(const char*, const char*, const char*, const char*,
+                const char*, const char*, const char*, const char*)> a =
+      Invoke(&foo, &Foo::Concat8);
+  EXPECT_EQ("12345678",
+            a.Perform(make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
+                                 CharPtr("4"), CharPtr("5"), CharPtr("6"),
+                                 CharPtr("7"), CharPtr("8"))));
+}
+
+// Tests using Invoke() with a 9-argument method.
+TEST(InvokeMethodTest, MethodThatTakes9Arguments) {
+  Foo foo;
+  Action<string(const char*, const char*, const char*, const char*,
+                const char*, const char*, const char*, const char*,
+                const char*)> a = Invoke(&foo, &Foo::Concat9);
+  EXPECT_EQ("123456789",
+            a.Perform(make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
+                                 CharPtr("4"), CharPtr("5"), CharPtr("6"),
+                                 CharPtr("7"), CharPtr("8"), CharPtr("9"))));
+}
+
+// Tests using Invoke() with a 10-argument method.
+TEST(InvokeMethodTest, MethodThatTakes10Arguments) {
+  Foo foo;
+  Action<string(const char*, const char*, const char*, const char*,
+                const char*, const char*, const char*, const char*,
+                const char*, const char*)> a = Invoke(&foo, &Foo::Concat10);
+  EXPECT_EQ("1234567890",
+            a.Perform(make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
+                                 CharPtr("4"), CharPtr("5"), CharPtr("6"),
+                                 CharPtr("7"), CharPtr("8"), CharPtr("9"),
+                                 CharPtr("0"))));
+}
+
+// Tests using Invoke(f) as an action of a compatible type.
+TEST(InvokeMethodTest, MethodWithCompatibleType) {
+  Foo foo;
+  Action<long(int, short, char, bool)> a =  // NOLINT
+      Invoke(&foo, &Foo::SumOf4);
+  EXPECT_EQ(4444, a.Perform(make_tuple(4000, Short(300), Char(20), true)));
+}
+
+// Tests using WithoutArgs with an action that takes no argument.
+TEST(WithoutArgsTest, NoArg) {
+  Action<int(int n)> a = WithoutArgs(Invoke(Nullary));  // NOLINT
+  EXPECT_EQ(1, a.Perform(make_tuple(2)));
+}
+
+// Tests using WithArg with an action that takes 1 argument.
+TEST(WithArgTest, OneArg) {
+  Action<bool(double x, int n)> b = WithArg<1>(Invoke(Unary));  // NOLINT
+  EXPECT_TRUE(b.Perform(make_tuple(1.5, -1)));
+  EXPECT_FALSE(b.Perform(make_tuple(1.5, 1)));
+}
+
+TEST(ReturnArgActionTest, WorksForOneArgIntArg0) {
+  const Action<int(int)> a = ReturnArg<0>();
+  EXPECT_EQ(5, a.Perform(make_tuple(5)));
+}
+
+TEST(ReturnArgActionTest, WorksForMultiArgBoolArg0) {
+  const Action<bool(bool, bool, bool)> a = ReturnArg<0>();
+  EXPECT_TRUE(a.Perform(make_tuple(true, false, false)));
+}
+
+TEST(ReturnArgActionTest, WorksForMultiArgStringArg2) {
+  const Action<string(int, int, string, int)> a = ReturnArg<2>();
+  EXPECT_EQ("seven", a.Perform(make_tuple(5, 6, string("seven"), 8)));
+}
+
+TEST(SaveArgActionTest, WorksForSameType) {
+  int result = 0;
+  const Action<void(int n)> a1 = SaveArg<0>(&result);
+  a1.Perform(make_tuple(5));
+  EXPECT_EQ(5, result);
+}
+
+TEST(SaveArgActionTest, WorksForCompatibleType) {
+  int result = 0;
+  const Action<void(bool, char)> a1 = SaveArg<1>(&result);
+  a1.Perform(make_tuple(true, 'a'));
+  EXPECT_EQ('a', result);
+}
+
+TEST(SaveArgPointeeActionTest, WorksForSameType) {
+  int result = 0;
+  const int value = 5;
+  const Action<void(const int*)> a1 = SaveArgPointee<0>(&result);
+  a1.Perform(make_tuple(&value));
+  EXPECT_EQ(5, result);
+}
+
+TEST(SaveArgPointeeActionTest, WorksForCompatibleType) {
+  int result = 0;
+  char value = 'a';
+  const Action<void(bool, char*)> a1 = SaveArgPointee<1>(&result);
+  a1.Perform(make_tuple(true, &value));
+  EXPECT_EQ('a', result);
+}
+
+TEST(SaveArgPointeeActionTest, WorksForLinkedPtr) {
+  int result = 0;
+  linked_ptr<int> value(new int(5));
+  const Action<void(linked_ptr<int>)> a1 = SaveArgPointee<0>(&result);
+  a1.Perform(make_tuple(value));
+  EXPECT_EQ(5, result);
+}
+
+TEST(SetArgRefereeActionTest, WorksForSameType) {
+  int value = 0;
+  const Action<void(int&)> a1 = SetArgReferee<0>(1);
+  a1.Perform(tuple<int&>(value));
+  EXPECT_EQ(1, value);
+}
+
+TEST(SetArgRefereeActionTest, WorksForCompatibleType) {
+  int value = 0;
+  const Action<void(int, int&)> a1 = SetArgReferee<1>('a');
+  a1.Perform(tuple<int, int&>(0, value));
+  EXPECT_EQ('a', value);
+}
+
+TEST(SetArgRefereeActionTest, WorksWithExtraArguments) {
+  int value = 0;
+  const Action<void(bool, int, int&, const char*)> a1 = SetArgReferee<2>('a');
+  a1.Perform(tuple<bool, int, int&, const char*>(true, 0, value, "hi"));
+  EXPECT_EQ('a', value);
+}
+
+// A class that can be used to verify that its destructor is called: it will set
+// the bool provided to the constructor to true when destroyed.
+class DeletionTester {
+ public:
+  explicit DeletionTester(bool* is_deleted)
+    : is_deleted_(is_deleted) {
+    // Make sure the bit is set to false.
+    *is_deleted_ = false;
+  }
+
+  ~DeletionTester() {
+    *is_deleted_ = true;
+  }
+
+ private:
+  bool* is_deleted_;
+};
+
+TEST(DeleteArgActionTest, OneArg) {
+  bool is_deleted = false;
+  DeletionTester* t = new DeletionTester(&is_deleted);
+  const Action<void(DeletionTester*)> a1 = DeleteArg<0>();      // NOLINT
+  EXPECT_FALSE(is_deleted);
+  a1.Perform(make_tuple(t));
+  EXPECT_TRUE(is_deleted);
+}
+
+TEST(DeleteArgActionTest, TenArgs) {
+  bool is_deleted = false;
+  DeletionTester* t = new DeletionTester(&is_deleted);
+  const Action<void(bool, int, int, const char*, bool,
+                    int, int, int, int, DeletionTester*)> a1 = DeleteArg<9>();
+  EXPECT_FALSE(is_deleted);
+  a1.Perform(make_tuple(true, 5, 6, CharPtr("hi"), false, 7, 8, 9, 10, t));
+  EXPECT_TRUE(is_deleted);
+}
+
+#if GTEST_HAS_EXCEPTIONS
+
+TEST(ThrowActionTest, ThrowsGivenExceptionInVoidFunction) {
+  const Action<void(int n)> a = Throw('a');
+  EXPECT_THROW(a.Perform(make_tuple(0)), char);
+}
+
+class MyException {};
+
+TEST(ThrowActionTest, ThrowsGivenExceptionInNonVoidFunction) {
+  const Action<double(char ch)> a = Throw(MyException());
+  EXPECT_THROW(a.Perform(make_tuple('0')), MyException);
+}
+
+TEST(ThrowActionTest, ThrowsGivenExceptionInNullaryFunction) {
+  const Action<double()> a = Throw(MyException());
+  EXPECT_THROW(a.Perform(make_tuple()), MyException);
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// Tests that SetArrayArgument<N>(first, last) sets the elements of the array
+// pointed to by the N-th (0-based) argument to values in range [first, last).
+TEST(SetArrayArgumentTest, SetsTheNthArray) {
+  typedef void MyFunction(bool, int*, char*);
+  int numbers[] = { 1, 2, 3 };
+  Action<MyFunction> a = SetArrayArgument<1>(numbers, numbers + 3);
+
+  int n[4] = {};
+  int* pn = n;
+  char ch[4] = {};
+  char* pch = ch;
+  a.Perform(make_tuple(true, pn, pch));
+  EXPECT_EQ(1, n[0]);
+  EXPECT_EQ(2, n[1]);
+  EXPECT_EQ(3, n[2]);
+  EXPECT_EQ(0, n[3]);
+  EXPECT_EQ('\0', ch[0]);
+  EXPECT_EQ('\0', ch[1]);
+  EXPECT_EQ('\0', ch[2]);
+  EXPECT_EQ('\0', ch[3]);
+
+  // Tests first and last are iterators.
+  std::string letters = "abc";
+  a = SetArrayArgument<2>(letters.begin(), letters.end());
+  std::fill_n(n, 4, 0);
+  std::fill_n(ch, 4, '\0');
+  a.Perform(make_tuple(true, pn, pch));
+  EXPECT_EQ(0, n[0]);
+  EXPECT_EQ(0, n[1]);
+  EXPECT_EQ(0, n[2]);
+  EXPECT_EQ(0, n[3]);
+  EXPECT_EQ('a', ch[0]);
+  EXPECT_EQ('b', ch[1]);
+  EXPECT_EQ('c', ch[2]);
+  EXPECT_EQ('\0', ch[3]);
+}
+
+// Tests SetArrayArgument<N>(first, last) where first == last.
+TEST(SetArrayArgumentTest, SetsTheNthArrayWithEmptyRange) {
+  typedef void MyFunction(bool, int*);
+  int numbers[] = { 1, 2, 3 };
+  Action<MyFunction> a = SetArrayArgument<1>(numbers, numbers);
+
+  int n[4] = {};
+  int* pn = n;
+  a.Perform(make_tuple(true, pn));
+  EXPECT_EQ(0, n[0]);
+  EXPECT_EQ(0, n[1]);
+  EXPECT_EQ(0, n[2]);
+  EXPECT_EQ(0, n[3]);
+}
+
+// Tests SetArrayArgument<N>(first, last) where *first is convertible
+// (but not equal) to the argument type.
+TEST(SetArrayArgumentTest, SetsTheNthArrayWithConvertibleType) {
+  typedef void MyFunction(bool, int*);
+  char chars[] = { 97, 98, 99 };
+  Action<MyFunction> a = SetArrayArgument<1>(chars, chars + 3);
+
+  int codes[4] = { 111, 222, 333, 444 };
+  int* pcodes = codes;
+  a.Perform(make_tuple(true, pcodes));
+  EXPECT_EQ(97, codes[0]);
+  EXPECT_EQ(98, codes[1]);
+  EXPECT_EQ(99, codes[2]);
+  EXPECT_EQ(444, codes[3]);
+}
+
+// Test SetArrayArgument<N>(first, last) with iterator as argument.
+TEST(SetArrayArgumentTest, SetsTheNthArrayWithIteratorArgument) {
+  typedef void MyFunction(bool, std::back_insert_iterator<std::string>);
+  std::string letters = "abc";
+  Action<MyFunction> a = SetArrayArgument<1>(letters.begin(), letters.end());
+
+  std::string s;
+  a.Perform(make_tuple(true, back_inserter(s)));
+  EXPECT_EQ(letters, s);
+}
+
+TEST(ReturnPointeeTest, Works) {
+  int n = 42;
+  const Action<int()> a = ReturnPointee(&n);
+  EXPECT_EQ(42, a.Perform(make_tuple()));
+
+  n = 43;
+  EXPECT_EQ(43, a.Perform(make_tuple()));
+}
+
+}  // namespace gmock_generated_actions_test
+}  // namespace testing
diff --git a/third_party/googletest/googlemock/test/gmock-nice-strict_test.cc b/third_party/googletest/googlemock/test/gmock-nice-strict_test.cc
new file mode 100644
index 0000000..d0adcbb
--- /dev/null
+++ b/third_party/googletest/googlemock/test/gmock-nice-strict_test.cc
@@ -0,0 +1,424 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include "gmock/gmock-generated-nice-strict.h"
+
+#include <string>
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "gtest/gtest-spi.h"
+
+// This must not be defined inside the ::testing namespace, or it will
+// clash with ::testing::Mock.
+class Mock {
+ public:
+  Mock() {}
+
+  MOCK_METHOD0(DoThis, void());
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Mock);
+};
+
+namespace testing {
+namespace gmock_nice_strict_test {
+
+using testing::internal::string;
+using testing::GMOCK_FLAG(verbose);
+using testing::HasSubstr;
+using testing::NaggyMock;
+using testing::NiceMock;
+using testing::StrictMock;
+
+#if GTEST_HAS_STREAM_REDIRECTION
+using testing::internal::CaptureStdout;
+using testing::internal::GetCapturedStdout;
+#endif
+
+// Defines some mock classes needed by the tests.
+
+class Foo {
+ public:
+  virtual ~Foo() {}
+
+  virtual void DoThis() = 0;
+  virtual int DoThat(bool flag) = 0;
+};
+
+class MockFoo : public Foo {
+ public:
+  MockFoo() {}
+  void Delete() { delete this; }
+
+  MOCK_METHOD0(DoThis, void());
+  MOCK_METHOD1(DoThat, int(bool flag));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFoo);
+};
+
+class MockBar {
+ public:
+  explicit MockBar(const string& s) : str_(s) {}
+
+  MockBar(char a1, char a2, string a3, string a4, int a5, int a6,
+          const string& a7, const string& a8, bool a9, bool a10) {
+    str_ = string() + a1 + a2 + a3 + a4 + static_cast<char>(a5) +
+        static_cast<char>(a6) + a7 + a8 + (a9 ? 'T' : 'F') + (a10 ? 'T' : 'F');
+  }
+
+  virtual ~MockBar() {}
+
+  const string& str() const { return str_; }
+
+  MOCK_METHOD0(This, int());
+  MOCK_METHOD2(That, string(int, bool));
+
+ private:
+  string str_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockBar);
+};
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Tests that a raw mock generates warnings for uninteresting calls.
+TEST(RawMockTest, WarningForUninterestingCall) {
+  const string saved_flag = GMOCK_FLAG(verbose);
+  GMOCK_FLAG(verbose) = "warning";
+
+  MockFoo raw_foo;
+
+  CaptureStdout();
+  raw_foo.DoThis();
+  raw_foo.DoThat(true);
+  EXPECT_THAT(GetCapturedStdout(),
+              HasSubstr("Uninteresting mock function call"));
+
+  GMOCK_FLAG(verbose) = saved_flag;
+}
+
+// Tests that a raw mock generates warnings for uninteresting calls
+// that delete the mock object.
+TEST(RawMockTest, WarningForUninterestingCallAfterDeath) {
+  const string saved_flag = GMOCK_FLAG(verbose);
+  GMOCK_FLAG(verbose) = "warning";
+
+  MockFoo* const raw_foo = new MockFoo;
+
+  ON_CALL(*raw_foo, DoThis())
+      .WillByDefault(Invoke(raw_foo, &MockFoo::Delete));
+
+  CaptureStdout();
+  raw_foo->DoThis();
+  EXPECT_THAT(GetCapturedStdout(),
+              HasSubstr("Uninteresting mock function call"));
+
+  GMOCK_FLAG(verbose) = saved_flag;
+}
+
+// Tests that a raw mock generates informational logs for
+// uninteresting calls.
+TEST(RawMockTest, InfoForUninterestingCall) {
+  MockFoo raw_foo;
+
+  const string saved_flag = GMOCK_FLAG(verbose);
+  GMOCK_FLAG(verbose) = "info";
+  CaptureStdout();
+  raw_foo.DoThis();
+  EXPECT_THAT(GetCapturedStdout(),
+              HasSubstr("Uninteresting mock function call"));
+
+  GMOCK_FLAG(verbose) = saved_flag;
+}
+
+// Tests that a nice mock generates no warning for uninteresting calls.
+TEST(NiceMockTest, NoWarningForUninterestingCall) {
+  NiceMock<MockFoo> nice_foo;
+
+  CaptureStdout();
+  nice_foo.DoThis();
+  nice_foo.DoThat(true);
+  EXPECT_EQ("", GetCapturedStdout());
+}
+
+// Tests that a nice mock generates no warning for uninteresting calls
+// that delete the mock object.
+TEST(NiceMockTest, NoWarningForUninterestingCallAfterDeath) {
+  NiceMock<MockFoo>* const nice_foo = new NiceMock<MockFoo>;
+
+  ON_CALL(*nice_foo, DoThis())
+      .WillByDefault(Invoke(nice_foo, &MockFoo::Delete));
+
+  CaptureStdout();
+  nice_foo->DoThis();
+  EXPECT_EQ("", GetCapturedStdout());
+}
+
+// Tests that a nice mock generates informational logs for
+// uninteresting calls.
+TEST(NiceMockTest, InfoForUninterestingCall) {
+  NiceMock<MockFoo> nice_foo;
+
+  const string saved_flag = GMOCK_FLAG(verbose);
+  GMOCK_FLAG(verbose) = "info";
+  CaptureStdout();
+  nice_foo.DoThis();
+  EXPECT_THAT(GetCapturedStdout(),
+              HasSubstr("Uninteresting mock function call"));
+
+  GMOCK_FLAG(verbose) = saved_flag;
+}
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+// Tests that a nice mock allows expected calls.
+TEST(NiceMockTest, AllowsExpectedCall) {
+  NiceMock<MockFoo> nice_foo;
+
+  EXPECT_CALL(nice_foo, DoThis());
+  nice_foo.DoThis();
+}
+
+// Tests that an unexpected call on a nice mock fails.
+TEST(NiceMockTest, UnexpectedCallFails) {
+  NiceMock<MockFoo> nice_foo;
+
+  EXPECT_CALL(nice_foo, DoThis()).Times(0);
+  EXPECT_NONFATAL_FAILURE(nice_foo.DoThis(), "called more times than expected");
+}
+
+// Tests that NiceMock works with a mock class that has a non-default
+// constructor.
+TEST(NiceMockTest, NonDefaultConstructor) {
+  NiceMock<MockBar> nice_bar("hi");
+  EXPECT_EQ("hi", nice_bar.str());
+
+  nice_bar.This();
+  nice_bar.That(5, true);
+}
+
+// Tests that NiceMock works with a mock class that has a 10-ary
+// non-default constructor.
+TEST(NiceMockTest, NonDefaultConstructor10) {
+  NiceMock<MockBar> nice_bar('a', 'b', "c", "d", 'e', 'f',
+                             "g", "h", true, false);
+  EXPECT_EQ("abcdefghTF", nice_bar.str());
+
+  nice_bar.This();
+  nice_bar.That(5, true);
+}
+
+#if !GTEST_OS_SYMBIAN && !GTEST_OS_WINDOWS_MOBILE
+// Tests that NiceMock<Mock> compiles where Mock is a user-defined
+// class (as opposed to ::testing::Mock).  We had to work around an
+// MSVC 8.0 bug that caused the symbol Mock used in the definition of
+// NiceMock to be looked up in the wrong context, and this test
+// ensures that our fix works.
+//
+// We have to skip this test on Symbian and Windows Mobile, as it
+// causes the program to crash there, for reasons unclear to us yet.
+TEST(NiceMockTest, AcceptsClassNamedMock) {
+  NiceMock< ::Mock> nice;
+  EXPECT_CALL(nice, DoThis());
+  nice.DoThis();
+}
+#endif  // !GTEST_OS_SYMBIAN && !GTEST_OS_WINDOWS_MOBILE
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Tests that a naggy mock generates warnings for uninteresting calls.
+TEST(NaggyMockTest, WarningForUninterestingCall) {
+  const string saved_flag = GMOCK_FLAG(verbose);
+  GMOCK_FLAG(verbose) = "warning";
+
+  NaggyMock<MockFoo> naggy_foo;
+
+  CaptureStdout();
+  naggy_foo.DoThis();
+  naggy_foo.DoThat(true);
+  EXPECT_THAT(GetCapturedStdout(),
+              HasSubstr("Uninteresting mock function call"));
+
+  GMOCK_FLAG(verbose) = saved_flag;
+}
+
+// Tests that a naggy mock generates a warning for an uninteresting call
+// that deletes the mock object.
+TEST(NaggyMockTest, WarningForUninterestingCallAfterDeath) {
+  const string saved_flag = GMOCK_FLAG(verbose);
+  GMOCK_FLAG(verbose) = "warning";
+
+  NaggyMock<MockFoo>* const naggy_foo = new NaggyMock<MockFoo>;
+
+  ON_CALL(*naggy_foo, DoThis())
+      .WillByDefault(Invoke(naggy_foo, &MockFoo::Delete));
+
+  CaptureStdout();
+  naggy_foo->DoThis();
+  EXPECT_THAT(GetCapturedStdout(),
+              HasSubstr("Uninteresting mock function call"));
+
+  GMOCK_FLAG(verbose) = saved_flag;
+}
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+// Tests that a naggy mock allows expected calls.
+TEST(NaggyMockTest, AllowsExpectedCall) {
+  NaggyMock<MockFoo> naggy_foo;
+
+  EXPECT_CALL(naggy_foo, DoThis());
+  naggy_foo.DoThis();
+}
+
+// Tests that an unexpected call on a naggy mock fails.
+TEST(NaggyMockTest, UnexpectedCallFails) {
+  NaggyMock<MockFoo> naggy_foo;
+
+  EXPECT_CALL(naggy_foo, DoThis()).Times(0);
+  EXPECT_NONFATAL_FAILURE(naggy_foo.DoThis(),
+                          "called more times than expected");
+}
+
+// Tests that NaggyMock works with a mock class that has a non-default
+// constructor.
+TEST(NaggyMockTest, NonDefaultConstructor) {
+  NaggyMock<MockBar> naggy_bar("hi");
+  EXPECT_EQ("hi", naggy_bar.str());
+
+  naggy_bar.This();
+  naggy_bar.That(5, true);
+}
+
+// Tests that NaggyMock works with a mock class that has a 10-ary
+// non-default constructor.
+TEST(NaggyMockTest, NonDefaultConstructor10) {
+  NaggyMock<MockBar> naggy_bar('0', '1', "2", "3", '4', '5',
+                               "6", "7", true, false);
+  EXPECT_EQ("01234567TF", naggy_bar.str());
+
+  naggy_bar.This();
+  naggy_bar.That(5, true);
+}
+
+#if !GTEST_OS_SYMBIAN && !GTEST_OS_WINDOWS_MOBILE
+// Tests that NaggyMock<Mock> compiles where Mock is a user-defined
+// class (as opposed to ::testing::Mock).  We had to work around an
+// MSVC 8.0 bug that caused the symbol Mock used in the definition of
+// NaggyMock to be looked up in the wrong context, and this test
+// ensures that our fix works.
+//
+// We have to skip this test on Symbian and Windows Mobile, as it
+// causes the program to crash there, for reasons unclear to us yet.
+TEST(NaggyMockTest, AcceptsClassNamedMock) {
+  NaggyMock< ::Mock> naggy;
+  EXPECT_CALL(naggy, DoThis());
+  naggy.DoThis();
+}
+#endif  // !GTEST_OS_SYMBIAN && !GTEST_OS_WINDOWS_MOBILE
+
+// Tests that a strict mock allows expected calls.
+TEST(StrictMockTest, AllowsExpectedCall) {
+  StrictMock<MockFoo> strict_foo;
+
+  EXPECT_CALL(strict_foo, DoThis());
+  strict_foo.DoThis();
+}
+
+// Tests that an unexpected call on a strict mock fails.
+TEST(StrictMockTest, UnexpectedCallFails) {
+  StrictMock<MockFoo> strict_foo;
+
+  EXPECT_CALL(strict_foo, DoThis()).Times(0);
+  EXPECT_NONFATAL_FAILURE(strict_foo.DoThis(),
+                          "called more times than expected");
+}
+
+// Tests that an uninteresting call on a strict mock fails.
+TEST(StrictMockTest, UninterestingCallFails) {
+  StrictMock<MockFoo> strict_foo;
+
+  EXPECT_NONFATAL_FAILURE(strict_foo.DoThis(),
+                          "Uninteresting mock function call");
+}
+
+// Tests that an uninteresting call on a strict mock fails, even if
+// the call deletes the mock object.
+TEST(StrictMockTest, UninterestingCallFailsAfterDeath) {
+  StrictMock<MockFoo>* const strict_foo = new StrictMock<MockFoo>;
+
+  ON_CALL(*strict_foo, DoThis())
+      .WillByDefault(Invoke(strict_foo, &MockFoo::Delete));
+
+  EXPECT_NONFATAL_FAILURE(strict_foo->DoThis(),
+                          "Uninteresting mock function call");
+}
+
+// Tests that StrictMock works with a mock class that has a
+// non-default constructor.
+TEST(StrictMockTest, NonDefaultConstructor) {
+  StrictMock<MockBar> strict_bar("hi");
+  EXPECT_EQ("hi", strict_bar.str());
+
+  EXPECT_NONFATAL_FAILURE(strict_bar.That(5, true),
+                          "Uninteresting mock function call");
+}
+
+// Tests that StrictMock works with a mock class that has a 10-ary
+// non-default constructor.
+TEST(StrictMockTest, NonDefaultConstructor10) {
+  StrictMock<MockBar> strict_bar('a', 'b', "c", "d", 'e', 'f',
+                                 "g", "h", true, false);
+  EXPECT_EQ("abcdefghTF", strict_bar.str());
+
+  EXPECT_NONFATAL_FAILURE(strict_bar.That(5, true),
+                          "Uninteresting mock function call");
+}
+
+#if !GTEST_OS_SYMBIAN && !GTEST_OS_WINDOWS_MOBILE
+// Tests that StrictMock<Mock> compiles where Mock is a user-defined
+// class (as opposed to ::testing::Mock).  We had to work around an
+// MSVC 8.0 bug that caused the symbol Mock used in the definition of
+// StrictMock to be looked up in the wrong context, and this test
+// ensures that our fix works.
+//
+// We have to skip this test on Symbian and Windows Mobile, as it
+// causes the program to crash there, for reasons unclear to us yet.
+TEST(StrictMockTest, AcceptsClassNamedMock) {
+  StrictMock< ::Mock> strict;
+  EXPECT_CALL(strict, DoThis());
+  strict.DoThis();
+}
+#endif  // !GTEST_OS_SYMBIAN && !GTEST_OS_WINDOWS_MOBILE
+
+}  // namespace gmock_nice_strict_test
+}  // namespace testing
diff --git a/third_party/googletest/googlemock/test/gmock-port_test.cc b/third_party/googletest/googlemock/test/gmock-port_test.cc
new file mode 100644
index 0000000..d6a8d44
--- /dev/null
+++ b/third_party/googletest/googlemock/test/gmock-port_test.cc
@@ -0,0 +1,43 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vladl@google.com (Vlad Losev)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests the internal cross-platform support utilities.
+
+#include "gmock/internal/gmock-port.h"
+#include "gtest/gtest.h"
+
+// NOTE: if this file is left without tests for some reason, put a dummy
+// test here to make references to symbols in the gtest library and avoid
+// 'undefined symbol' linker errors in gmock_main:
+
+TEST(DummyTest, Dummy) {}
diff --git a/third_party/googletest/googlemock/test/gmock-spec-builders_test.cc b/third_party/googletest/googlemock/test/gmock-spec-builders_test.cc
new file mode 100644
index 0000000..342c22f
--- /dev/null
+++ b/third_party/googletest/googlemock/test/gmock-spec-builders_test.cc
@@ -0,0 +1,2644 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests the spec builder syntax.
+
+#include "gmock/gmock-spec-builders.h"
+
+#include <ostream>  // NOLINT
+#include <sstream>
+#include <string>
+
+#include "gmock/gmock.h"
+#include "gmock/internal/gmock-port.h"
+#include "gtest/gtest.h"
+#include "gtest/gtest-spi.h"
+#include "gtest/internal/gtest-port.h"
+
+namespace testing {
+namespace internal {
+
+// Helper class for testing the Expectation class template.
+class ExpectationTester {
+ public:
+  // Sets the call count of the given expectation to the given number.
+  void SetCallCount(int n, ExpectationBase* exp) {
+    exp->call_count_ = n;
+  }
+};
+
+}  // namespace internal
+}  // namespace testing
+
+namespace {
+
+using testing::_;
+using testing::AnyNumber;
+using testing::AtLeast;
+using testing::AtMost;
+using testing::Between;
+using testing::Cardinality;
+using testing::CardinalityInterface;
+using testing::ContainsRegex;
+using testing::Const;
+using testing::DoAll;
+using testing::DoDefault;
+using testing::Eq;
+using testing::Expectation;
+using testing::ExpectationSet;
+using testing::GMOCK_FLAG(verbose);
+using testing::Gt;
+using testing::InSequence;
+using testing::Invoke;
+using testing::InvokeWithoutArgs;
+using testing::IsNotSubstring;
+using testing::IsSubstring;
+using testing::Lt;
+using testing::Message;
+using testing::Mock;
+using testing::NaggyMock;
+using testing::Ne;
+using testing::Return;
+using testing::Sequence;
+using testing::SetArgPointee;
+using testing::internal::ExpectationTester;
+using testing::internal::FormatFileLocation;
+using testing::internal::kErrorVerbosity;
+using testing::internal::kInfoVerbosity;
+using testing::internal::kWarningVerbosity;
+using testing::internal::linked_ptr;
+using testing::internal::string;
+
+#if GTEST_HAS_STREAM_REDIRECTION
+using testing::HasSubstr;
+using testing::internal::CaptureStdout;
+using testing::internal::GetCapturedStdout;
+#endif
+
+class Incomplete;
+
+class MockIncomplete {
+ public:
+  // This line verifies that a mock method can take a by-reference
+  // argument of an incomplete type.
+  MOCK_METHOD1(ByRefFunc, void(const Incomplete& x));
+};
+
+// Tells Google Mock how to print a value of type Incomplete.
+void PrintTo(const Incomplete& x, ::std::ostream* os);
+
+TEST(MockMethodTest, CanInstantiateWithIncompleteArgType) {
+  // Even though this mock class contains a mock method that takes
+  // by-reference an argument whose type is incomplete, we can still
+  // use the mock, as long as Google Mock knows how to print the
+  // argument.
+  MockIncomplete incomplete;
+  EXPECT_CALL(incomplete, ByRefFunc(_))
+      .Times(AnyNumber());
+}
+
+// The definition of the printer for the argument type doesn't have to
+// be visible where the mock is used.
+void PrintTo(const Incomplete& /* x */, ::std::ostream* os) {
+  *os << "incomplete";
+}
+
+class Result {};
+
+// A type that's not default constructible.
+class NonDefaultConstructible {
+ public:
+  explicit NonDefaultConstructible(int /* dummy */) {}
+};
+
+class MockA {
+ public:
+  MockA() {}
+
+  MOCK_METHOD1(DoA, void(int n));
+  MOCK_METHOD1(ReturnResult, Result(int n));
+  MOCK_METHOD0(ReturnNonDefaultConstructible, NonDefaultConstructible());
+  MOCK_METHOD2(Binary, bool(int x, int y));
+  MOCK_METHOD2(ReturnInt, int(int x, int y));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockA);
+};
+
+class MockB {
+ public:
+  MockB() {}
+
+  MOCK_CONST_METHOD0(DoB, int());  // NOLINT
+  MOCK_METHOD1(DoB, int(int n));  // NOLINT
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockB);
+};
+
+class ReferenceHoldingMock {
+ public:
+  ReferenceHoldingMock() {}
+
+  MOCK_METHOD1(AcceptReference, void(linked_ptr<MockA>*));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ReferenceHoldingMock);
+};
+
+// Tests that EXPECT_CALL and ON_CALL compile in a presence of macro
+// redefining a mock method name. This could happen, for example, when
+// the tested code #includes Win32 API headers which define many APIs
+// as macros, e.g. #define TextOut TextOutW.
+
+#define Method MethodW
+
+class CC {
+ public:
+  virtual ~CC() {}
+  virtual int Method() = 0;
+};
+class MockCC : public CC {
+ public:
+  MockCC() {}
+
+  MOCK_METHOD0(Method, int());
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockCC);
+};
+
+// Tests that a method with expanded name compiles.
+TEST(OnCallSyntaxTest, CompilesWithMethodNameExpandedFromMacro) {
+  MockCC cc;
+  ON_CALL(cc, Method());
+}
+
+// Tests that the method with expanded name not only compiles but runs
+// and returns a correct value, too.
+TEST(OnCallSyntaxTest, WorksWithMethodNameExpandedFromMacro) {
+  MockCC cc;
+  ON_CALL(cc, Method()).WillByDefault(Return(42));
+  EXPECT_EQ(42, cc.Method());
+}
+
+// Tests that a method with expanded name compiles.
+TEST(ExpectCallSyntaxTest, CompilesWithMethodNameExpandedFromMacro) {
+  MockCC cc;
+  EXPECT_CALL(cc, Method());
+  cc.Method();
+}
+
+// Tests that it works, too.
+TEST(ExpectCallSyntaxTest, WorksWithMethodNameExpandedFromMacro) {
+  MockCC cc;
+  EXPECT_CALL(cc, Method()).WillOnce(Return(42));
+  EXPECT_EQ(42, cc.Method());
+}
+
+#undef Method  // Done with macro redefinition tests.
+
+// Tests that ON_CALL evaluates its arguments exactly once as promised
+// by Google Mock.
+TEST(OnCallSyntaxTest, EvaluatesFirstArgumentOnce) {
+  MockA a;
+  MockA* pa = &a;
+
+  ON_CALL(*pa++, DoA(_));
+  EXPECT_EQ(&a + 1, pa);
+}
+
+TEST(OnCallSyntaxTest, EvaluatesSecondArgumentOnce) {
+  MockA a;
+  int n = 0;
+
+  ON_CALL(a, DoA(n++));
+  EXPECT_EQ(1, n);
+}
+
+// Tests that the syntax of ON_CALL() is enforced at run time.
+
+TEST(OnCallSyntaxTest, WithIsOptional) {
+  MockA a;
+
+  ON_CALL(a, DoA(5))
+      .WillByDefault(Return());
+  ON_CALL(a, DoA(_))
+      .With(_)
+      .WillByDefault(Return());
+}
+
+TEST(OnCallSyntaxTest, WithCanAppearAtMostOnce) {
+  MockA a;
+
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    ON_CALL(a, ReturnResult(_))
+        .With(_)
+        .With(_)
+        .WillByDefault(Return(Result()));
+  }, ".With() cannot appear more than once in an ON_CALL()");
+}
+
+TEST(OnCallSyntaxTest, WillByDefaultIsMandatory) {
+  MockA a;
+
+  EXPECT_DEATH_IF_SUPPORTED({
+    ON_CALL(a, DoA(5));
+    a.DoA(5);
+  }, "");
+}
+
+TEST(OnCallSyntaxTest, WillByDefaultCanAppearAtMostOnce) {
+  MockA a;
+
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    ON_CALL(a, DoA(5))
+        .WillByDefault(Return())
+        .WillByDefault(Return());
+  }, ".WillByDefault() must appear exactly once in an ON_CALL()");
+}
+
+// Tests that EXPECT_CALL evaluates its arguments exactly once as
+// promised by Google Mock.
+TEST(ExpectCallSyntaxTest, EvaluatesFirstArgumentOnce) {
+  MockA a;
+  MockA* pa = &a;
+
+  EXPECT_CALL(*pa++, DoA(_));
+  a.DoA(0);
+  EXPECT_EQ(&a + 1, pa);
+}
+
+TEST(ExpectCallSyntaxTest, EvaluatesSecondArgumentOnce) {
+  MockA a;
+  int n = 0;
+
+  EXPECT_CALL(a, DoA(n++));
+  a.DoA(0);
+  EXPECT_EQ(1, n);
+}
+
+// Tests that the syntax of EXPECT_CALL() is enforced at run time.
+
+TEST(ExpectCallSyntaxTest, WithIsOptional) {
+  MockA a;
+
+  EXPECT_CALL(a, DoA(5))
+      .Times(0);
+  EXPECT_CALL(a, DoA(6))
+      .With(_)
+      .Times(0);
+}
+
+TEST(ExpectCallSyntaxTest, WithCanAppearAtMostOnce) {
+  MockA a;
+
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_CALL(a, DoA(6))
+        .With(_)
+        .With(_);
+  }, ".With() cannot appear more than once in an EXPECT_CALL()");
+
+  a.DoA(6);
+}
+
+TEST(ExpectCallSyntaxTest, WithMustBeFirstClause) {
+  MockA a;
+
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_CALL(a, DoA(1))
+        .Times(1)
+        .With(_);
+  }, ".With() must be the first clause in an EXPECT_CALL()");
+
+  a.DoA(1);
+
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_CALL(a, DoA(2))
+        .WillOnce(Return())
+        .With(_);
+  }, ".With() must be the first clause in an EXPECT_CALL()");
+
+  a.DoA(2);
+}
+
+TEST(ExpectCallSyntaxTest, TimesCanBeInferred) {
+  MockA a;
+
+  EXPECT_CALL(a, DoA(1))
+      .WillOnce(Return());
+
+  EXPECT_CALL(a, DoA(2))
+      .WillOnce(Return())
+      .WillRepeatedly(Return());
+
+  a.DoA(1);
+  a.DoA(2);
+  a.DoA(2);
+}
+
+TEST(ExpectCallSyntaxTest, TimesCanAppearAtMostOnce) {
+  MockA a;
+
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_CALL(a, DoA(1))
+        .Times(1)
+        .Times(2);
+  }, ".Times() cannot appear more than once in an EXPECT_CALL()");
+
+  a.DoA(1);
+  a.DoA(1);
+}
+
+TEST(ExpectCallSyntaxTest, TimesMustBeBeforeInSequence) {
+  MockA a;
+  Sequence s;
+
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_CALL(a, DoA(1))
+        .InSequence(s)
+        .Times(1);
+  }, ".Times() cannot appear after ");
+
+  a.DoA(1);
+}
+
+TEST(ExpectCallSyntaxTest, InSequenceIsOptional) {
+  MockA a;
+  Sequence s;
+
+  EXPECT_CALL(a, DoA(1));
+  EXPECT_CALL(a, DoA(2))
+      .InSequence(s);
+
+  a.DoA(1);
+  a.DoA(2);
+}
+
+TEST(ExpectCallSyntaxTest, InSequenceCanAppearMultipleTimes) {
+  MockA a;
+  Sequence s1, s2;
+
+  EXPECT_CALL(a, DoA(1))
+      .InSequence(s1, s2)
+      .InSequence(s1);
+
+  a.DoA(1);
+}
+
+TEST(ExpectCallSyntaxTest, InSequenceMustBeBeforeAfter) {
+  MockA a;
+  Sequence s;
+
+  Expectation e = EXPECT_CALL(a, DoA(1))
+      .Times(AnyNumber());
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_CALL(a, DoA(2))
+        .After(e)
+        .InSequence(s);
+  }, ".InSequence() cannot appear after ");
+
+  a.DoA(2);
+}
+
+TEST(ExpectCallSyntaxTest, InSequenceMustBeBeforeWillOnce) {
+  MockA a;
+  Sequence s;
+
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_CALL(a, DoA(1))
+        .WillOnce(Return())
+        .InSequence(s);
+  }, ".InSequence() cannot appear after ");
+
+  a.DoA(1);
+}
+
+TEST(ExpectCallSyntaxTest, AfterMustBeBeforeWillOnce) {
+  MockA a;
+
+  Expectation e = EXPECT_CALL(a, DoA(1));
+  EXPECT_NONFATAL_FAILURE({
+    EXPECT_CALL(a, DoA(2))
+        .WillOnce(Return())
+        .After(e);
+  }, ".After() cannot appear after ");
+
+  a.DoA(1);
+  a.DoA(2);
+}
+
+TEST(ExpectCallSyntaxTest, WillIsOptional) {
+  MockA a;
+
+  EXPECT_CALL(a, DoA(1));
+  EXPECT_CALL(a, DoA(2))
+      .WillOnce(Return());
+
+  a.DoA(1);
+  a.DoA(2);
+}
+
+TEST(ExpectCallSyntaxTest, WillCanAppearMultipleTimes) {
+  MockA a;
+
+  EXPECT_CALL(a, DoA(1))
+      .Times(AnyNumber())
+      .WillOnce(Return())
+      .WillOnce(Return())
+      .WillOnce(Return());
+}
+
+TEST(ExpectCallSyntaxTest, WillMustBeBeforeWillRepeatedly) {
+  MockA a;
+
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_CALL(a, DoA(1))
+        .WillRepeatedly(Return())
+        .WillOnce(Return());
+  }, ".WillOnce() cannot appear after ");
+
+  a.DoA(1);
+}
+
+TEST(ExpectCallSyntaxTest, WillRepeatedlyIsOptional) {
+  MockA a;
+
+  EXPECT_CALL(a, DoA(1))
+      .WillOnce(Return());
+  EXPECT_CALL(a, DoA(2))
+      .WillOnce(Return())
+      .WillRepeatedly(Return());
+
+  a.DoA(1);
+  a.DoA(2);
+  a.DoA(2);
+}
+
+TEST(ExpectCallSyntaxTest, WillRepeatedlyCannotAppearMultipleTimes) {
+  MockA a;
+
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_CALL(a, DoA(1))
+        .WillRepeatedly(Return())
+        .WillRepeatedly(Return());
+  }, ".WillRepeatedly() cannot appear more than once in an "
+     "EXPECT_CALL()");
+}
+
+TEST(ExpectCallSyntaxTest, WillRepeatedlyMustBeBeforeRetiresOnSaturation) {
+  MockA a;
+
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_CALL(a, DoA(1))
+        .RetiresOnSaturation()
+        .WillRepeatedly(Return());
+  }, ".WillRepeatedly() cannot appear after ");
+}
+
+TEST(ExpectCallSyntaxTest, RetiresOnSaturationIsOptional) {
+  MockA a;
+
+  EXPECT_CALL(a, DoA(1));
+  EXPECT_CALL(a, DoA(1))
+      .RetiresOnSaturation();
+
+  a.DoA(1);
+  a.DoA(1);
+}
+
+TEST(ExpectCallSyntaxTest, RetiresOnSaturationCannotAppearMultipleTimes) {
+  MockA a;
+
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_CALL(a, DoA(1))
+        .RetiresOnSaturation()
+        .RetiresOnSaturation();
+  }, ".RetiresOnSaturation() cannot appear more than once");
+
+  a.DoA(1);
+}
+
+TEST(ExpectCallSyntaxTest, DefaultCardinalityIsOnce) {
+  {
+    MockA a;
+    EXPECT_CALL(a, DoA(1));
+    a.DoA(1);
+  }
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    MockA a;
+    EXPECT_CALL(a, DoA(1));
+  }, "to be called once");
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    MockA a;
+    EXPECT_CALL(a, DoA(1));
+    a.DoA(1);
+    a.DoA(1);
+  }, "to be called once");
+}
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Tests that Google Mock doesn't print a warning when the number of
+// WillOnce() is adequate.
+TEST(ExpectCallSyntaxTest, DoesNotWarnOnAdequateActionCount) {
+  CaptureStdout();
+  {
+    MockB b;
+
+    // It's always fine to omit WillOnce() entirely.
+    EXPECT_CALL(b, DoB())
+        .Times(0);
+    EXPECT_CALL(b, DoB(1))
+        .Times(AtMost(1));
+    EXPECT_CALL(b, DoB(2))
+        .Times(1)
+        .WillRepeatedly(Return(1));
+
+    // It's fine for the number of WillOnce()s to equal the upper bound.
+    EXPECT_CALL(b, DoB(3))
+        .Times(Between(1, 2))
+        .WillOnce(Return(1))
+        .WillOnce(Return(2));
+
+    // It's fine for the number of WillOnce()s to be smaller than the
+    // upper bound when there is a WillRepeatedly().
+    EXPECT_CALL(b, DoB(4))
+        .Times(AtMost(3))
+        .WillOnce(Return(1))
+        .WillRepeatedly(Return(2));
+
+    // Satisfies the above expectations.
+    b.DoB(2);
+    b.DoB(3);
+  }
+  EXPECT_STREQ("", GetCapturedStdout().c_str());
+}
+
+// Tests that Google Mock warns on having too many actions in an
+// expectation compared to its cardinality.
+TEST(ExpectCallSyntaxTest, WarnsOnTooManyActions) {
+  CaptureStdout();
+  {
+    MockB b;
+
+    // Warns when the number of WillOnce()s is larger than the upper bound.
+    EXPECT_CALL(b, DoB())
+        .Times(0)
+        .WillOnce(Return(1));  // #1
+    EXPECT_CALL(b, DoB())
+        .Times(AtMost(1))
+        .WillOnce(Return(1))
+        .WillOnce(Return(2));  // #2
+    EXPECT_CALL(b, DoB(1))
+        .Times(1)
+        .WillOnce(Return(1))
+        .WillOnce(Return(2))
+        .RetiresOnSaturation();  // #3
+
+    // Warns when the number of WillOnce()s equals the upper bound and
+    // there is a WillRepeatedly().
+    EXPECT_CALL(b, DoB())
+        .Times(0)
+        .WillRepeatedly(Return(1));  // #4
+    EXPECT_CALL(b, DoB(2))
+        .Times(1)
+        .WillOnce(Return(1))
+        .WillRepeatedly(Return(2));  // #5
+
+    // Satisfies the above expectations.
+    b.DoB(1);
+    b.DoB(2);
+  }
+  const std::string output = GetCapturedStdout();
+  EXPECT_PRED_FORMAT2(
+      IsSubstring,
+      "Too many actions specified in EXPECT_CALL(b, DoB())...\n"
+      "Expected to be never called, but has 1 WillOnce().",
+      output);  // #1
+  EXPECT_PRED_FORMAT2(
+      IsSubstring,
+      "Too many actions specified in EXPECT_CALL(b, DoB())...\n"
+      "Expected to be called at most once, "
+      "but has 2 WillOnce()s.",
+      output);  // #2
+  EXPECT_PRED_FORMAT2(
+      IsSubstring,
+      "Too many actions specified in EXPECT_CALL(b, DoB(1))...\n"
+      "Expected to be called once, but has 2 WillOnce()s.",
+      output);  // #3
+  EXPECT_PRED_FORMAT2(
+      IsSubstring,
+      "Too many actions specified in EXPECT_CALL(b, DoB())...\n"
+      "Expected to be never called, but has 0 WillOnce()s "
+      "and a WillRepeatedly().",
+      output);  // #4
+  EXPECT_PRED_FORMAT2(
+      IsSubstring,
+      "Too many actions specified in EXPECT_CALL(b, DoB(2))...\n"
+      "Expected to be called once, but has 1 WillOnce() "
+      "and a WillRepeatedly().",
+      output);  // #5
+}
+
+// Tests that Google Mock warns on having too few actions in an
+// expectation compared to its cardinality.
+TEST(ExpectCallSyntaxTest, WarnsOnTooFewActions) {
+  MockB b;
+
+  EXPECT_CALL(b, DoB())
+      .Times(Between(2, 3))
+      .WillOnce(Return(1));
+
+  CaptureStdout();
+  b.DoB();
+  const std::string output = GetCapturedStdout();
+  EXPECT_PRED_FORMAT2(
+      IsSubstring,
+      "Too few actions specified in EXPECT_CALL(b, DoB())...\n"
+      "Expected to be called between 2 and 3 times, "
+      "but has only 1 WillOnce().",
+      output);
+  b.DoB();
+}
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+// Tests the semantics of ON_CALL().
+
+// Tests that the built-in default action is taken when no ON_CALL()
+// is specified.
+TEST(OnCallTest, TakesBuiltInDefaultActionWhenNoOnCall) {
+  MockB b;
+  EXPECT_CALL(b, DoB());
+
+  EXPECT_EQ(0, b.DoB());
+}
+
+// Tests that the built-in default action is taken when no ON_CALL()
+// matches the invocation.
+TEST(OnCallTest, TakesBuiltInDefaultActionWhenNoOnCallMatches) {
+  MockB b;
+  ON_CALL(b, DoB(1))
+      .WillByDefault(Return(1));
+  EXPECT_CALL(b, DoB(_));
+
+  EXPECT_EQ(0, b.DoB(2));
+}
+
+// Tests that the last matching ON_CALL() action is taken.
+TEST(OnCallTest, PicksLastMatchingOnCall) {
+  MockB b;
+  ON_CALL(b, DoB(_))
+      .WillByDefault(Return(3));
+  ON_CALL(b, DoB(2))
+      .WillByDefault(Return(2));
+  ON_CALL(b, DoB(1))
+      .WillByDefault(Return(1));
+  EXPECT_CALL(b, DoB(_));
+
+  EXPECT_EQ(2, b.DoB(2));
+}
+
+// Tests the semantics of EXPECT_CALL().
+
+// Tests that any call is allowed when no EXPECT_CALL() is specified.
+TEST(ExpectCallTest, AllowsAnyCallWhenNoSpec) {
+  MockB b;
+  EXPECT_CALL(b, DoB());
+  // There is no expectation on DoB(int).
+
+  b.DoB();
+
+  // DoB(int) can be called any number of times.
+  b.DoB(1);
+  b.DoB(2);
+}
+
+// Tests that the last matching EXPECT_CALL() fires.
+TEST(ExpectCallTest, PicksLastMatchingExpectCall) {
+  MockB b;
+  EXPECT_CALL(b, DoB(_))
+      .WillRepeatedly(Return(2));
+  EXPECT_CALL(b, DoB(1))
+      .WillRepeatedly(Return(1));
+
+  EXPECT_EQ(1, b.DoB(1));
+}
+
+// Tests lower-bound violation.
+TEST(ExpectCallTest, CatchesTooFewCalls) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    MockB b;
+    EXPECT_CALL(b, DoB(5))
+        .Times(AtLeast(2));
+
+    b.DoB(5);
+  }, "Actual function call count doesn't match EXPECT_CALL(b, DoB(5))...\n"
+     "         Expected: to be called at least twice\n"
+     "           Actual: called once - unsatisfied and active");
+}
+
+// Tests that the cardinality can be inferred when no Times(...) is
+// specified.
+TEST(ExpectCallTest, InfersCardinalityWhenThereIsNoWillRepeatedly) {
+  {
+    MockB b;
+    EXPECT_CALL(b, DoB())
+        .WillOnce(Return(1))
+        .WillOnce(Return(2));
+
+    EXPECT_EQ(1, b.DoB());
+    EXPECT_EQ(2, b.DoB());
+  }
+
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    MockB b;
+    EXPECT_CALL(b, DoB())
+        .WillOnce(Return(1))
+        .WillOnce(Return(2));
+
+    EXPECT_EQ(1, b.DoB());
+  }, "to be called twice");
+
+  {  // NOLINT
+    MockB b;
+    EXPECT_CALL(b, DoB())
+        .WillOnce(Return(1))
+        .WillOnce(Return(2));
+
+    EXPECT_EQ(1, b.DoB());
+    EXPECT_EQ(2, b.DoB());
+    EXPECT_NONFATAL_FAILURE(b.DoB(), "to be called twice");
+  }
+}
+
+TEST(ExpectCallTest, InfersCardinality1WhenThereIsWillRepeatedly) {
+  {
+    MockB b;
+    EXPECT_CALL(b, DoB())
+        .WillOnce(Return(1))
+        .WillRepeatedly(Return(2));
+
+    EXPECT_EQ(1, b.DoB());
+  }
+
+  {  // NOLINT
+    MockB b;
+    EXPECT_CALL(b, DoB())
+        .WillOnce(Return(1))
+        .WillRepeatedly(Return(2));
+
+    EXPECT_EQ(1, b.DoB());
+    EXPECT_EQ(2, b.DoB());
+    EXPECT_EQ(2, b.DoB());
+  }
+
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    MockB b;
+    EXPECT_CALL(b, DoB())
+        .WillOnce(Return(1))
+        .WillRepeatedly(Return(2));
+  }, "to be called at least once");
+}
+
+// Tests that the n-th action is taken for the n-th matching
+// invocation.
+TEST(ExpectCallTest, NthMatchTakesNthAction) {
+  MockB b;
+  EXPECT_CALL(b, DoB())
+      .WillOnce(Return(1))
+      .WillOnce(Return(2))
+      .WillOnce(Return(3));
+
+  EXPECT_EQ(1, b.DoB());
+  EXPECT_EQ(2, b.DoB());
+  EXPECT_EQ(3, b.DoB());
+}
+
+// Tests that the WillRepeatedly() action is taken when the WillOnce(...)
+// list is exhausted.
+TEST(ExpectCallTest, TakesRepeatedActionWhenWillListIsExhausted) {
+  MockB b;
+  EXPECT_CALL(b, DoB())
+      .WillOnce(Return(1))
+      .WillRepeatedly(Return(2));
+
+  EXPECT_EQ(1, b.DoB());
+  EXPECT_EQ(2, b.DoB());
+  EXPECT_EQ(2, b.DoB());
+}
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Tests that the default action is taken when the WillOnce(...) list is
+// exhausted and there is no WillRepeatedly().
+TEST(ExpectCallTest, TakesDefaultActionWhenWillListIsExhausted) {
+  MockB b;
+  EXPECT_CALL(b, DoB(_))
+      .Times(1);
+  EXPECT_CALL(b, DoB())
+      .Times(AnyNumber())
+      .WillOnce(Return(1))
+      .WillOnce(Return(2));
+
+  CaptureStdout();
+  EXPECT_EQ(0, b.DoB(1));  // Shouldn't generate a warning as the
+                           // expectation has no action clause at all.
+  EXPECT_EQ(1, b.DoB());
+  EXPECT_EQ(2, b.DoB());
+  const std::string output1 = GetCapturedStdout();
+  EXPECT_STREQ("", output1.c_str());
+
+  CaptureStdout();
+  EXPECT_EQ(0, b.DoB());
+  EXPECT_EQ(0, b.DoB());
+  const std::string output2 = GetCapturedStdout();
+  EXPECT_THAT(output2.c_str(),
+              HasSubstr("Actions ran out in EXPECT_CALL(b, DoB())...\n"
+                        "Called 3 times, but only 2 WillOnce()s are specified"
+                        " - returning default value."));
+  EXPECT_THAT(output2.c_str(),
+              HasSubstr("Actions ran out in EXPECT_CALL(b, DoB())...\n"
+                        "Called 4 times, but only 2 WillOnce()s are specified"
+                        " - returning default value."));
+}
+
+TEST(FunctionMockerMessageTest, ReportsExpectCallLocationForExhausedActions) {
+  MockB b;
+  std::string expect_call_location = FormatFileLocation(__FILE__, __LINE__ + 1);
+  EXPECT_CALL(b, DoB()).Times(AnyNumber()).WillOnce(Return(1));
+
+  EXPECT_EQ(1, b.DoB());
+
+  CaptureStdout();
+  EXPECT_EQ(0, b.DoB());
+  const std::string output = GetCapturedStdout();
+  // The warning message should contain the call location.
+  EXPECT_PRED_FORMAT2(IsSubstring, expect_call_location, output);
+}
+
+TEST(FunctionMockerMessageTest,
+     ReportsDefaultActionLocationOfUninterestingCallsForNaggyMock) {
+  std::string on_call_location;
+  CaptureStdout();
+  {
+    NaggyMock<MockB> b;
+    on_call_location = FormatFileLocation(__FILE__, __LINE__ + 1);
+    ON_CALL(b, DoB(_)).WillByDefault(Return(0));
+    b.DoB(0);
+  }
+  EXPECT_PRED_FORMAT2(IsSubstring, on_call_location, GetCapturedStdout());
+}
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+// Tests that an uninteresting call performs the default action.
+TEST(UninterestingCallTest, DoesDefaultAction) {
+  // When there is an ON_CALL() statement, the action specified by it
+  // should be taken.
+  MockA a;
+  ON_CALL(a, Binary(_, _))
+      .WillByDefault(Return(true));
+  EXPECT_TRUE(a.Binary(1, 2));
+
+  // When there is no ON_CALL(), the default value for the return type
+  // should be returned.
+  MockB b;
+  EXPECT_EQ(0, b.DoB());
+}
+
+// Tests that an unexpected call performs the default action.
+TEST(UnexpectedCallTest, DoesDefaultAction) {
+  // When there is an ON_CALL() statement, the action specified by it
+  // should be taken.
+  MockA a;
+  ON_CALL(a, Binary(_, _))
+      .WillByDefault(Return(true));
+  EXPECT_CALL(a, Binary(0, 0));
+  a.Binary(0, 0);
+  bool result = false;
+  EXPECT_NONFATAL_FAILURE(result = a.Binary(1, 2),
+                          "Unexpected mock function call");
+  EXPECT_TRUE(result);
+
+  // When there is no ON_CALL(), the default value for the return type
+  // should be returned.
+  MockB b;
+  EXPECT_CALL(b, DoB(0))
+      .Times(0);
+  int n = -1;
+  EXPECT_NONFATAL_FAILURE(n = b.DoB(1),
+                          "Unexpected mock function call");
+  EXPECT_EQ(0, n);
+}
+
+// Tests that when an unexpected void function generates the right
+// failure message.
+TEST(UnexpectedCallTest, GeneratesFailureForVoidFunction) {
+  // First, tests the message when there is only one EXPECT_CALL().
+  MockA a1;
+  EXPECT_CALL(a1, DoA(1));
+  a1.DoA(1);
+  // Ideally we should match the failure message against a regex, but
+  // EXPECT_NONFATAL_FAILURE doesn't support that, so we test for
+  // multiple sub-strings instead.
+  EXPECT_NONFATAL_FAILURE(
+      a1.DoA(9),
+      "Unexpected mock function call - returning directly.\n"
+      "    Function call: DoA(9)\n"
+      "Google Mock tried the following 1 expectation, but it didn't match:");
+  EXPECT_NONFATAL_FAILURE(
+      a1.DoA(9),
+      "  Expected arg #0: is equal to 1\n"
+      "           Actual: 9\n"
+      "         Expected: to be called once\n"
+      "           Actual: called once - saturated and active");
+
+  // Next, tests the message when there are more than one EXPECT_CALL().
+  MockA a2;
+  EXPECT_CALL(a2, DoA(1));
+  EXPECT_CALL(a2, DoA(3));
+  a2.DoA(1);
+  EXPECT_NONFATAL_FAILURE(
+      a2.DoA(2),
+      "Unexpected mock function call - returning directly.\n"
+      "    Function call: DoA(2)\n"
+      "Google Mock tried the following 2 expectations, but none matched:");
+  EXPECT_NONFATAL_FAILURE(
+      a2.DoA(2),
+      "tried expectation #0: EXPECT_CALL(a2, DoA(1))...\n"
+      "  Expected arg #0: is equal to 1\n"
+      "           Actual: 2\n"
+      "         Expected: to be called once\n"
+      "           Actual: called once - saturated and active");
+  EXPECT_NONFATAL_FAILURE(
+      a2.DoA(2),
+      "tried expectation #1: EXPECT_CALL(a2, DoA(3))...\n"
+      "  Expected arg #0: is equal to 3\n"
+      "           Actual: 2\n"
+      "         Expected: to be called once\n"
+      "           Actual: never called - unsatisfied and active");
+  a2.DoA(3);
+}
+
+// Tests that an unexpected non-void function generates the right
+// failure message.
+TEST(UnexpectedCallTest, GeneartesFailureForNonVoidFunction) {
+  MockB b1;
+  EXPECT_CALL(b1, DoB(1));
+  b1.DoB(1);
+  EXPECT_NONFATAL_FAILURE(
+      b1.DoB(2),
+      "Unexpected mock function call - returning default value.\n"
+      "    Function call: DoB(2)\n"
+      "          Returns: 0\n"
+      "Google Mock tried the following 1 expectation, but it didn't match:");
+  EXPECT_NONFATAL_FAILURE(
+      b1.DoB(2),
+      "  Expected arg #0: is equal to 1\n"
+      "           Actual: 2\n"
+      "         Expected: to be called once\n"
+      "           Actual: called once - saturated and active");
+}
+
+// Tests that Google Mock explains that an retired expectation doesn't
+// match the call.
+TEST(UnexpectedCallTest, RetiredExpectation) {
+  MockB b;
+  EXPECT_CALL(b, DoB(1))
+      .RetiresOnSaturation();
+
+  b.DoB(1);
+  EXPECT_NONFATAL_FAILURE(
+      b.DoB(1),
+      "         Expected: the expectation is active\n"
+      "           Actual: it is retired");
+}
+
+// Tests that Google Mock explains that an expectation that doesn't
+// match the arguments doesn't match the call.
+TEST(UnexpectedCallTest, UnmatchedArguments) {
+  MockB b;
+  EXPECT_CALL(b, DoB(1));
+
+  EXPECT_NONFATAL_FAILURE(
+      b.DoB(2),
+      "  Expected arg #0: is equal to 1\n"
+      "           Actual: 2\n");
+  b.DoB(1);
+}
+
+// Tests that Google Mock explains that an expectation with
+// unsatisfied pre-requisites doesn't match the call.
+TEST(UnexpectedCallTest, UnsatisifiedPrerequisites) {
+  Sequence s1, s2;
+  MockB b;
+  EXPECT_CALL(b, DoB(1))
+      .InSequence(s1);
+  EXPECT_CALL(b, DoB(2))
+      .Times(AnyNumber())
+      .InSequence(s1);
+  EXPECT_CALL(b, DoB(3))
+      .InSequence(s2);
+  EXPECT_CALL(b, DoB(4))
+      .InSequence(s1, s2);
+
+  ::testing::TestPartResultArray failures;
+  {
+    ::testing::ScopedFakeTestPartResultReporter reporter(&failures);
+    b.DoB(4);
+    // Now 'failures' contains the Google Test failures generated by
+    // the above statement.
+  }
+
+  // There should be one non-fatal failure.
+  ASSERT_EQ(1, failures.size());
+  const ::testing::TestPartResult& r = failures.GetTestPartResult(0);
+  EXPECT_EQ(::testing::TestPartResult::kNonFatalFailure, r.type());
+
+  // Verifies that the failure message contains the two unsatisfied
+  // pre-requisites but not the satisfied one.
+#if GTEST_USES_PCRE
+  EXPECT_THAT(r.message(), ContainsRegex(
+      // PCRE has trouble using (.|\n) to match any character, but
+      // supports the (?s) prefix for using . to match any character.
+      "(?s)the following immediate pre-requisites are not satisfied:\n"
+      ".*: pre-requisite #0\n"
+      ".*: pre-requisite #1"));
+#elif GTEST_USES_POSIX_RE
+  EXPECT_THAT(r.message(), ContainsRegex(
+      // POSIX RE doesn't understand the (?s) prefix, but has no trouble
+      // with (.|\n).
+      "the following immediate pre-requisites are not satisfied:\n"
+      "(.|\n)*: pre-requisite #0\n"
+      "(.|\n)*: pre-requisite #1"));
+#else
+  // We can only use Google Test's own simple regex.
+  EXPECT_THAT(r.message(), ContainsRegex(
+      "the following immediate pre-requisites are not satisfied:"));
+  EXPECT_THAT(r.message(), ContainsRegex(": pre-requisite #0"));
+  EXPECT_THAT(r.message(), ContainsRegex(": pre-requisite #1"));
+#endif  // GTEST_USES_PCRE
+
+  b.DoB(1);
+  b.DoB(3);
+  b.DoB(4);
+}
+
+TEST(UndefinedReturnValueTest,
+     ReturnValueIsMandatoryWhenNotDefaultConstructible) {
+  MockA a;
+  // TODO(wan@google.com): We should really verify the output message,
+  // but we cannot yet due to that EXPECT_DEATH only captures stderr
+  // while Google Mock logs to stdout.
+#if GTEST_HAS_EXCEPTIONS
+  EXPECT_ANY_THROW(a.ReturnNonDefaultConstructible());
+#else
+  EXPECT_DEATH_IF_SUPPORTED(a.ReturnNonDefaultConstructible(), "");
+#endif
+}
+
+// Tests that an excessive call (one whose arguments match the
+// matchers but is called too many times) performs the default action.
+TEST(ExcessiveCallTest, DoesDefaultAction) {
+  // When there is an ON_CALL() statement, the action specified by it
+  // should be taken.
+  MockA a;
+  ON_CALL(a, Binary(_, _))
+      .WillByDefault(Return(true));
+  EXPECT_CALL(a, Binary(0, 0));
+  a.Binary(0, 0);
+  bool result = false;
+  EXPECT_NONFATAL_FAILURE(result = a.Binary(0, 0),
+                          "Mock function called more times than expected");
+  EXPECT_TRUE(result);
+
+  // When there is no ON_CALL(), the default value for the return type
+  // should be returned.
+  MockB b;
+  EXPECT_CALL(b, DoB(0))
+      .Times(0);
+  int n = -1;
+  EXPECT_NONFATAL_FAILURE(n = b.DoB(0),
+                          "Mock function called more times than expected");
+  EXPECT_EQ(0, n);
+}
+
+// Tests that when a void function is called too many times,
+// the failure message contains the argument values.
+TEST(ExcessiveCallTest, GeneratesFailureForVoidFunction) {
+  MockA a;
+  EXPECT_CALL(a, DoA(_))
+      .Times(0);
+  EXPECT_NONFATAL_FAILURE(
+      a.DoA(9),
+      "Mock function called more times than expected - returning directly.\n"
+      "    Function call: DoA(9)\n"
+      "         Expected: to be never called\n"
+      "           Actual: called once - over-saturated and active");
+}
+
+// Tests that when a non-void function is called too many times, the
+// failure message contains the argument values and the return value.
+TEST(ExcessiveCallTest, GeneratesFailureForNonVoidFunction) {
+  MockB b;
+  EXPECT_CALL(b, DoB(_));
+  b.DoB(1);
+  EXPECT_NONFATAL_FAILURE(
+      b.DoB(2),
+      "Mock function called more times than expected - "
+      "returning default value.\n"
+      "    Function call: DoB(2)\n"
+      "          Returns: 0\n"
+      "         Expected: to be called once\n"
+      "           Actual: called twice - over-saturated and active");
+}
+
+// Tests using sequences.
+
+TEST(InSequenceTest, AllExpectationInScopeAreInSequence) {
+  MockA a;
+  {
+    InSequence dummy;
+
+    EXPECT_CALL(a, DoA(1));
+    EXPECT_CALL(a, DoA(2));
+  }
+
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    a.DoA(2);
+  }, "Unexpected mock function call");
+
+  a.DoA(1);
+  a.DoA(2);
+}
+
+TEST(InSequenceTest, NestedInSequence) {
+  MockA a;
+  {
+    InSequence dummy;
+
+    EXPECT_CALL(a, DoA(1));
+    {
+      InSequence dummy2;
+
+      EXPECT_CALL(a, DoA(2));
+      EXPECT_CALL(a, DoA(3));
+    }
+  }
+
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    a.DoA(1);
+    a.DoA(3);
+  }, "Unexpected mock function call");
+
+  a.DoA(2);
+  a.DoA(3);
+}
+
+TEST(InSequenceTest, ExpectationsOutOfScopeAreNotAffected) {
+  MockA a;
+  {
+    InSequence dummy;
+
+    EXPECT_CALL(a, DoA(1));
+    EXPECT_CALL(a, DoA(2));
+  }
+  EXPECT_CALL(a, DoA(3));
+
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    a.DoA(2);
+  }, "Unexpected mock function call");
+
+  a.DoA(3);
+  a.DoA(1);
+  a.DoA(2);
+}
+
+// Tests that any order is allowed when no sequence is used.
+TEST(SequenceTest, AnyOrderIsOkByDefault) {
+  {
+    MockA a;
+    MockB b;
+
+    EXPECT_CALL(a, DoA(1));
+    EXPECT_CALL(b, DoB())
+        .Times(AnyNumber());
+
+    a.DoA(1);
+    b.DoB();
+  }
+
+  {  // NOLINT
+    MockA a;
+    MockB b;
+
+    EXPECT_CALL(a, DoA(1));
+    EXPECT_CALL(b, DoB())
+        .Times(AnyNumber());
+
+    b.DoB();
+    a.DoA(1);
+  }
+}
+
+// Tests that the calls must be in strict order when a complete order
+// is specified.
+TEST(SequenceTest, CallsMustBeInStrictOrderWhenSaidSo1) {
+  MockA a;
+  ON_CALL(a, ReturnResult(_))
+      .WillByDefault(Return(Result()));
+
+  Sequence s;
+  EXPECT_CALL(a, ReturnResult(1))
+      .InSequence(s);
+  EXPECT_CALL(a, ReturnResult(2))
+      .InSequence(s);
+  EXPECT_CALL(a, ReturnResult(3))
+      .InSequence(s);
+
+  a.ReturnResult(1);
+
+  // May only be called after a.ReturnResult(2).
+  EXPECT_NONFATAL_FAILURE(a.ReturnResult(3), "Unexpected mock function call");
+
+  a.ReturnResult(2);
+  a.ReturnResult(3);
+}
+
+// Tests that the calls must be in strict order when a complete order
+// is specified.
+TEST(SequenceTest, CallsMustBeInStrictOrderWhenSaidSo2) {
+  MockA a;
+  ON_CALL(a, ReturnResult(_))
+      .WillByDefault(Return(Result()));
+
+  Sequence s;
+  EXPECT_CALL(a, ReturnResult(1))
+      .InSequence(s);
+  EXPECT_CALL(a, ReturnResult(2))
+      .InSequence(s);
+
+  // May only be called after a.ReturnResult(1).
+  EXPECT_NONFATAL_FAILURE(a.ReturnResult(2), "Unexpected mock function call");
+
+  a.ReturnResult(1);
+  a.ReturnResult(2);
+}
+
+// Tests specifying a DAG using multiple sequences.
+class PartialOrderTest : public testing::Test {
+ protected:
+  PartialOrderTest() {
+    ON_CALL(a_, ReturnResult(_))
+        .WillByDefault(Return(Result()));
+
+    // Specifies this partial ordering:
+    //
+    // a.ReturnResult(1) ==>
+    //                       a.ReturnResult(2) * n  ==>  a.ReturnResult(3)
+    // b.DoB() * 2       ==>
+    Sequence x, y;
+    EXPECT_CALL(a_, ReturnResult(1))
+        .InSequence(x);
+    EXPECT_CALL(b_, DoB())
+        .Times(2)
+        .InSequence(y);
+    EXPECT_CALL(a_, ReturnResult(2))
+        .Times(AnyNumber())
+        .InSequence(x, y);
+    EXPECT_CALL(a_, ReturnResult(3))
+        .InSequence(x);
+  }
+
+  MockA a_;
+  MockB b_;
+};
+
+TEST_F(PartialOrderTest, CallsMustConformToSpecifiedDag1) {
+  a_.ReturnResult(1);
+  b_.DoB();
+
+  // May only be called after the second DoB().
+  EXPECT_NONFATAL_FAILURE(a_.ReturnResult(2), "Unexpected mock function call");
+
+  b_.DoB();
+  a_.ReturnResult(3);
+}
+
+TEST_F(PartialOrderTest, CallsMustConformToSpecifiedDag2) {
+  // May only be called after ReturnResult(1).
+  EXPECT_NONFATAL_FAILURE(a_.ReturnResult(2), "Unexpected mock function call");
+
+  a_.ReturnResult(1);
+  b_.DoB();
+  b_.DoB();
+  a_.ReturnResult(3);
+}
+
+TEST_F(PartialOrderTest, CallsMustConformToSpecifiedDag3) {
+  // May only be called last.
+  EXPECT_NONFATAL_FAILURE(a_.ReturnResult(3), "Unexpected mock function call");
+
+  a_.ReturnResult(1);
+  b_.DoB();
+  b_.DoB();
+  a_.ReturnResult(3);
+}
+
+TEST_F(PartialOrderTest, CallsMustConformToSpecifiedDag4) {
+  a_.ReturnResult(1);
+  b_.DoB();
+  b_.DoB();
+  a_.ReturnResult(3);
+
+  // May only be called before ReturnResult(3).
+  EXPECT_NONFATAL_FAILURE(a_.ReturnResult(2), "Unexpected mock function call");
+}
+
+TEST(SequenceTest, Retirement) {
+  MockA a;
+  Sequence s;
+
+  EXPECT_CALL(a, DoA(1))
+      .InSequence(s);
+  EXPECT_CALL(a, DoA(_))
+      .InSequence(s)
+      .RetiresOnSaturation();
+  EXPECT_CALL(a, DoA(1))
+      .InSequence(s);
+
+  a.DoA(1);
+  a.DoA(2);
+  a.DoA(1);
+}
+
+// Tests Expectation.
+
+TEST(ExpectationTest, ConstrutorsWork) {
+  MockA a;
+  Expectation e1;  // Default ctor.
+
+  // Ctor from various forms of EXPECT_CALL.
+  Expectation e2 = EXPECT_CALL(a, DoA(2));
+  Expectation e3 = EXPECT_CALL(a, DoA(3)).With(_);
+  {
+    Sequence s;
+    Expectation e4 = EXPECT_CALL(a, DoA(4)).Times(1);
+    Expectation e5 = EXPECT_CALL(a, DoA(5)).InSequence(s);
+  }
+  Expectation e6 = EXPECT_CALL(a, DoA(6)).After(e2);
+  Expectation e7 = EXPECT_CALL(a, DoA(7)).WillOnce(Return());
+  Expectation e8 = EXPECT_CALL(a, DoA(8)).WillRepeatedly(Return());
+  Expectation e9 = EXPECT_CALL(a, DoA(9)).RetiresOnSaturation();
+
+  Expectation e10 = e2;  // Copy ctor.
+
+  EXPECT_THAT(e1, Ne(e2));
+  EXPECT_THAT(e2, Eq(e10));
+
+  a.DoA(2);
+  a.DoA(3);
+  a.DoA(4);
+  a.DoA(5);
+  a.DoA(6);
+  a.DoA(7);
+  a.DoA(8);
+  a.DoA(9);
+}
+
+TEST(ExpectationTest, AssignmentWorks) {
+  MockA a;
+  Expectation e1;
+  Expectation e2 = EXPECT_CALL(a, DoA(1));
+
+  EXPECT_THAT(e1, Ne(e2));
+
+  e1 = e2;
+  EXPECT_THAT(e1, Eq(e2));
+
+  a.DoA(1);
+}
+
+// Tests ExpectationSet.
+
+TEST(ExpectationSetTest, MemberTypesAreCorrect) {
+  ::testing::StaticAssertTypeEq<Expectation, ExpectationSet::value_type>();
+}
+
+TEST(ExpectationSetTest, ConstructorsWork) {
+  MockA a;
+
+  Expectation e1;
+  const Expectation e2;
+  ExpectationSet es1;  // Default ctor.
+  ExpectationSet es2 = EXPECT_CALL(a, DoA(1));  // Ctor from EXPECT_CALL.
+  ExpectationSet es3 = e1;  // Ctor from Expectation.
+  ExpectationSet es4(e1);   // Ctor from Expectation; alternative syntax.
+  ExpectationSet es5 = e2;  // Ctor from const Expectation.
+  ExpectationSet es6(e2);   // Ctor from const Expectation; alternative syntax.
+  ExpectationSet es7 = es2;  // Copy ctor.
+
+  EXPECT_EQ(0, es1.size());
+  EXPECT_EQ(1, es2.size());
+  EXPECT_EQ(1, es3.size());
+  EXPECT_EQ(1, es4.size());
+  EXPECT_EQ(1, es5.size());
+  EXPECT_EQ(1, es6.size());
+  EXPECT_EQ(1, es7.size());
+
+  EXPECT_THAT(es3, Ne(es2));
+  EXPECT_THAT(es4, Eq(es3));
+  EXPECT_THAT(es5, Eq(es4));
+  EXPECT_THAT(es6, Eq(es5));
+  EXPECT_THAT(es7, Eq(es2));
+  a.DoA(1);
+}
+
+TEST(ExpectationSetTest, AssignmentWorks) {
+  ExpectationSet es1;
+  ExpectationSet es2 = Expectation();
+
+  es1 = es2;
+  EXPECT_EQ(1, es1.size());
+  EXPECT_THAT(*(es1.begin()), Eq(Expectation()));
+  EXPECT_THAT(es1, Eq(es2));
+}
+
+TEST(ExpectationSetTest, InsertionWorks) {
+  ExpectationSet es1;
+  Expectation e1;
+  es1 += e1;
+  EXPECT_EQ(1, es1.size());
+  EXPECT_THAT(*(es1.begin()), Eq(e1));
+
+  MockA a;
+  Expectation e2 = EXPECT_CALL(a, DoA(1));
+  es1 += e2;
+  EXPECT_EQ(2, es1.size());
+
+  ExpectationSet::const_iterator it1 = es1.begin();
+  ExpectationSet::const_iterator it2 = it1;
+  ++it2;
+  EXPECT_TRUE(*it1 == e1 || *it2 == e1);  // e1 must be in the set.
+  EXPECT_TRUE(*it1 == e2 || *it2 == e2);  // e2 must be in the set too.
+  a.DoA(1);
+}
+
+TEST(ExpectationSetTest, SizeWorks) {
+  ExpectationSet es;
+  EXPECT_EQ(0, es.size());
+
+  es += Expectation();
+  EXPECT_EQ(1, es.size());
+
+  MockA a;
+  es += EXPECT_CALL(a, DoA(1));
+  EXPECT_EQ(2, es.size());
+
+  a.DoA(1);
+}
+
+TEST(ExpectationSetTest, IsEnumerable) {
+  ExpectationSet es;
+  EXPECT_TRUE(es.begin() == es.end());
+
+  es += Expectation();
+  ExpectationSet::const_iterator it = es.begin();
+  EXPECT_TRUE(it != es.end());
+  EXPECT_THAT(*it, Eq(Expectation()));
+  ++it;
+  EXPECT_TRUE(it== es.end());
+}
+
+// Tests the .After() clause.
+
+TEST(AfterTest, SucceedsWhenPartialOrderIsSatisfied) {
+  MockA a;
+  ExpectationSet es;
+  es += EXPECT_CALL(a, DoA(1));
+  es += EXPECT_CALL(a, DoA(2));
+  EXPECT_CALL(a, DoA(3))
+      .After(es);
+
+  a.DoA(1);
+  a.DoA(2);
+  a.DoA(3);
+}
+
+TEST(AfterTest, SucceedsWhenTotalOrderIsSatisfied) {
+  MockA a;
+  MockB b;
+  // The following also verifies that const Expectation objects work
+  // too.  Do not remove the const modifiers.
+  const Expectation e1 = EXPECT_CALL(a, DoA(1));
+  const Expectation e2 = EXPECT_CALL(b, DoB())
+      .Times(2)
+      .After(e1);
+  EXPECT_CALL(a, DoA(2)).After(e2);
+
+  a.DoA(1);
+  b.DoB();
+  b.DoB();
+  a.DoA(2);
+}
+
+// Calls must be in strict order when specified so using .After().
+TEST(AfterTest, CallsMustBeInStrictOrderWhenSpecifiedSo1) {
+  MockA a;
+  MockB b;
+
+  // Define ordering:
+  //   a.DoA(1) ==> b.DoB() ==> a.DoA(2)
+  Expectation e1 = EXPECT_CALL(a, DoA(1));
+  Expectation e2 = EXPECT_CALL(b, DoB())
+      .After(e1);
+  EXPECT_CALL(a, DoA(2))
+      .After(e2);
+
+  a.DoA(1);
+
+  // May only be called after DoB().
+  EXPECT_NONFATAL_FAILURE(a.DoA(2), "Unexpected mock function call");
+
+  b.DoB();
+  a.DoA(2);
+}
+
+// Calls must be in strict order when specified so using .After().
+TEST(AfterTest, CallsMustBeInStrictOrderWhenSpecifiedSo2) {
+  MockA a;
+  MockB b;
+
+  // Define ordering:
+  //   a.DoA(1) ==> b.DoB() * 2 ==> a.DoA(2)
+  Expectation e1 = EXPECT_CALL(a, DoA(1));
+  Expectation e2 = EXPECT_CALL(b, DoB())
+      .Times(2)
+      .After(e1);
+  EXPECT_CALL(a, DoA(2))
+      .After(e2);
+
+  a.DoA(1);
+  b.DoB();
+
+  // May only be called after the second DoB().
+  EXPECT_NONFATAL_FAILURE(a.DoA(2), "Unexpected mock function call");
+
+  b.DoB();
+  a.DoA(2);
+}
+
+// Calls must satisfy the partial order when specified so.
+TEST(AfterTest, CallsMustSatisfyPartialOrderWhenSpecifiedSo) {
+  MockA a;
+  ON_CALL(a, ReturnResult(_))
+      .WillByDefault(Return(Result()));
+
+  // Define ordering:
+  //   a.DoA(1) ==>
+  //   a.DoA(2) ==> a.ReturnResult(3)
+  Expectation e = EXPECT_CALL(a, DoA(1));
+  const ExpectationSet es = EXPECT_CALL(a, DoA(2));
+  EXPECT_CALL(a, ReturnResult(3))
+      .After(e, es);
+
+  // May only be called last.
+  EXPECT_NONFATAL_FAILURE(a.ReturnResult(3), "Unexpected mock function call");
+
+  a.DoA(2);
+  a.DoA(1);
+  a.ReturnResult(3);
+}
+
+// Calls must satisfy the partial order when specified so.
+TEST(AfterTest, CallsMustSatisfyPartialOrderWhenSpecifiedSo2) {
+  MockA a;
+
+  // Define ordering:
+  //   a.DoA(1) ==>
+  //   a.DoA(2) ==> a.DoA(3)
+  Expectation e = EXPECT_CALL(a, DoA(1));
+  const ExpectationSet es = EXPECT_CALL(a, DoA(2));
+  EXPECT_CALL(a, DoA(3))
+      .After(e, es);
+
+  a.DoA(2);
+
+  // May only be called last.
+  EXPECT_NONFATAL_FAILURE(a.DoA(3), "Unexpected mock function call");
+
+  a.DoA(1);
+  a.DoA(3);
+}
+
+// .After() can be combined with .InSequence().
+TEST(AfterTest, CanBeUsedWithInSequence) {
+  MockA a;
+  Sequence s;
+  Expectation e = EXPECT_CALL(a, DoA(1));
+  EXPECT_CALL(a, DoA(2)).InSequence(s);
+  EXPECT_CALL(a, DoA(3))
+      .InSequence(s)
+      .After(e);
+
+  a.DoA(1);
+
+  // May only be after DoA(2).
+  EXPECT_NONFATAL_FAILURE(a.DoA(3), "Unexpected mock function call");
+
+  a.DoA(2);
+  a.DoA(3);
+}
+
+// .After() can be called multiple times.
+TEST(AfterTest, CanBeCalledManyTimes) {
+  MockA a;
+  Expectation e1 = EXPECT_CALL(a, DoA(1));
+  Expectation e2 = EXPECT_CALL(a, DoA(2));
+  Expectation e3 = EXPECT_CALL(a, DoA(3));
+  EXPECT_CALL(a, DoA(4))
+      .After(e1)
+      .After(e2)
+      .After(e3);
+
+  a.DoA(3);
+  a.DoA(1);
+  a.DoA(2);
+  a.DoA(4);
+}
+
+// .After() accepts up to 5 arguments.
+TEST(AfterTest, AcceptsUpToFiveArguments) {
+  MockA a;
+  Expectation e1 = EXPECT_CALL(a, DoA(1));
+  Expectation e2 = EXPECT_CALL(a, DoA(2));
+  Expectation e3 = EXPECT_CALL(a, DoA(3));
+  ExpectationSet es1 = EXPECT_CALL(a, DoA(4));
+  ExpectationSet es2 = EXPECT_CALL(a, DoA(5));
+  EXPECT_CALL(a, DoA(6))
+      .After(e1, e2, e3, es1, es2);
+
+  a.DoA(5);
+  a.DoA(2);
+  a.DoA(4);
+  a.DoA(1);
+  a.DoA(3);
+  a.DoA(6);
+}
+
+// .After() allows input to contain duplicated Expectations.
+TEST(AfterTest, AcceptsDuplicatedInput) {
+  MockA a;
+  ON_CALL(a, ReturnResult(_))
+      .WillByDefault(Return(Result()));
+
+  // Define ordering:
+  //   DoA(1) ==>
+  //   DoA(2) ==> ReturnResult(3)
+  Expectation e1 = EXPECT_CALL(a, DoA(1));
+  Expectation e2 = EXPECT_CALL(a, DoA(2));
+  ExpectationSet es;
+  es += e1;
+  es += e2;
+  EXPECT_CALL(a, ReturnResult(3))
+      .After(e1, e2, es, e1);
+
+  a.DoA(1);
+
+  // May only be after DoA(2).
+  EXPECT_NONFATAL_FAILURE(a.ReturnResult(3), "Unexpected mock function call");
+
+  a.DoA(2);
+  a.ReturnResult(3);
+}
+
+// An Expectation added to an ExpectationSet after it has been used in
+// an .After() has no effect.
+TEST(AfterTest, ChangesToExpectationSetHaveNoEffectAfterwards) {
+  MockA a;
+  ExpectationSet es1 = EXPECT_CALL(a, DoA(1));
+  Expectation e2 = EXPECT_CALL(a, DoA(2));
+  EXPECT_CALL(a, DoA(3))
+      .After(es1);
+  es1 += e2;
+
+  a.DoA(1);
+  a.DoA(3);
+  a.DoA(2);
+}
+
+// Tests that Google Mock correctly handles calls to mock functions
+// after a mock object owning one of their pre-requisites has died.
+
+// Tests that calls that satisfy the original spec are successful.
+TEST(DeletingMockEarlyTest, Success1) {
+  MockB* const b1 = new MockB;
+  MockA* const a = new MockA;
+  MockB* const b2 = new MockB;
+
+  {
+    InSequence dummy;
+    EXPECT_CALL(*b1, DoB(_))
+        .WillOnce(Return(1));
+    EXPECT_CALL(*a, Binary(_, _))
+        .Times(AnyNumber())
+        .WillRepeatedly(Return(true));
+    EXPECT_CALL(*b2, DoB(_))
+        .Times(AnyNumber())
+        .WillRepeatedly(Return(2));
+  }
+
+  EXPECT_EQ(1, b1->DoB(1));
+  delete b1;
+  // a's pre-requisite has died.
+  EXPECT_TRUE(a->Binary(0, 1));
+  delete b2;
+  // a's successor has died.
+  EXPECT_TRUE(a->Binary(1, 2));
+  delete a;
+}
+
+// Tests that calls that satisfy the original spec are successful.
+TEST(DeletingMockEarlyTest, Success2) {
+  MockB* const b1 = new MockB;
+  MockA* const a = new MockA;
+  MockB* const b2 = new MockB;
+
+  {
+    InSequence dummy;
+    EXPECT_CALL(*b1, DoB(_))
+        .WillOnce(Return(1));
+    EXPECT_CALL(*a, Binary(_, _))
+        .Times(AnyNumber());
+    EXPECT_CALL(*b2, DoB(_))
+        .Times(AnyNumber())
+        .WillRepeatedly(Return(2));
+  }
+
+  delete a;  // a is trivially satisfied.
+  EXPECT_EQ(1, b1->DoB(1));
+  EXPECT_EQ(2, b2->DoB(2));
+  delete b1;
+  delete b2;
+}
+
+// Tests that it's OK to delete a mock object itself in its action.
+
+// Suppresses warning on unreferenced formal parameter in MSVC with
+// -W4.
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4100)
+#endif
+
+ACTION_P(Delete, ptr) { delete ptr; }
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+TEST(DeletingMockEarlyTest, CanDeleteSelfInActionReturningVoid) {
+  MockA* const a = new MockA;
+  EXPECT_CALL(*a, DoA(_)).WillOnce(Delete(a));
+  a->DoA(42);  // This will cause a to be deleted.
+}
+
+TEST(DeletingMockEarlyTest, CanDeleteSelfInActionReturningValue) {
+  MockA* const a = new MockA;
+  EXPECT_CALL(*a, ReturnResult(_))
+      .WillOnce(DoAll(Delete(a), Return(Result())));
+  a->ReturnResult(42);  // This will cause a to be deleted.
+}
+
+// Tests that calls that violate the original spec yield failures.
+TEST(DeletingMockEarlyTest, Failure1) {
+  MockB* const b1 = new MockB;
+  MockA* const a = new MockA;
+  MockB* const b2 = new MockB;
+
+  {
+    InSequence dummy;
+    EXPECT_CALL(*b1, DoB(_))
+        .WillOnce(Return(1));
+    EXPECT_CALL(*a, Binary(_, _))
+        .Times(AnyNumber());
+    EXPECT_CALL(*b2, DoB(_))
+        .Times(AnyNumber())
+        .WillRepeatedly(Return(2));
+  }
+
+  delete a;  // a is trivially satisfied.
+  EXPECT_NONFATAL_FAILURE({
+    b2->DoB(2);
+  }, "Unexpected mock function call");
+  EXPECT_EQ(1, b1->DoB(1));
+  delete b1;
+  delete b2;
+}
+
+// Tests that calls that violate the original spec yield failures.
+TEST(DeletingMockEarlyTest, Failure2) {
+  MockB* const b1 = new MockB;
+  MockA* const a = new MockA;
+  MockB* const b2 = new MockB;
+
+  {
+    InSequence dummy;
+    EXPECT_CALL(*b1, DoB(_));
+    EXPECT_CALL(*a, Binary(_, _))
+        .Times(AnyNumber());
+    EXPECT_CALL(*b2, DoB(_))
+        .Times(AnyNumber());
+  }
+
+  EXPECT_NONFATAL_FAILURE(delete b1,
+                          "Actual: never called");
+  EXPECT_NONFATAL_FAILURE(a->Binary(0, 1),
+                          "Unexpected mock function call");
+  EXPECT_NONFATAL_FAILURE(b2->DoB(1),
+                          "Unexpected mock function call");
+  delete a;
+  delete b2;
+}
+
+class EvenNumberCardinality : public CardinalityInterface {
+ public:
+  // Returns true iff call_count calls will satisfy this cardinality.
+  virtual bool IsSatisfiedByCallCount(int call_count) const {
+    return call_count % 2 == 0;
+  }
+
+  // Returns true iff call_count calls will saturate this cardinality.
+  virtual bool IsSaturatedByCallCount(int /* call_count */) const {
+    return false;
+  }
+
+  // Describes self to an ostream.
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "called even number of times";
+  }
+};
+
+Cardinality EvenNumber() {
+  return Cardinality(new EvenNumberCardinality);
+}
+
+TEST(ExpectationBaseTest,
+     AllPrerequisitesAreSatisfiedWorksForNonMonotonicCardinality) {
+  MockA* a = new MockA;
+  Sequence s;
+
+  EXPECT_CALL(*a, DoA(1))
+      .Times(EvenNumber())
+      .InSequence(s);
+  EXPECT_CALL(*a, DoA(2))
+      .Times(AnyNumber())
+      .InSequence(s);
+  EXPECT_CALL(*a, DoA(3))
+      .Times(AnyNumber());
+
+  a->DoA(3);
+  a->DoA(1);
+  EXPECT_NONFATAL_FAILURE(a->DoA(2), "Unexpected mock function call");
+  EXPECT_NONFATAL_FAILURE(delete a, "to be called even number of times");
+}
+
+// The following tests verify the message generated when a mock
+// function is called.
+
+struct Printable {
+};
+
+inline void operator<<(::std::ostream& os, const Printable&) {
+  os << "Printable";
+}
+
+struct Unprintable {
+  Unprintable() : value(0) {}
+  int value;
+};
+
+class MockC {
+ public:
+  MockC() {}
+
+  MOCK_METHOD6(VoidMethod, void(bool cond, int n, string s, void* p,
+                                const Printable& x, Unprintable y));
+  MOCK_METHOD0(NonVoidMethod, int());  // NOLINT
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockC);
+};
+
+class VerboseFlagPreservingFixture : public testing::Test {
+ protected:
+  VerboseFlagPreservingFixture()
+      : saved_verbose_flag_(GMOCK_FLAG(verbose)) {}
+
+  ~VerboseFlagPreservingFixture() { GMOCK_FLAG(verbose) = saved_verbose_flag_; }
+
+ private:
+  const string saved_verbose_flag_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(VerboseFlagPreservingFixture);
+};
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Tests that an uninteresting mock function call on a naggy mock
+// generates a warning without the stack trace when
+// --gmock_verbose=warning is specified.
+TEST(FunctionCallMessageTest,
+     UninterestingCallOnNaggyMockGeneratesNoStackTraceWhenVerboseWarning) {
+  GMOCK_FLAG(verbose) = kWarningVerbosity;
+  NaggyMock<MockC> c;
+  CaptureStdout();
+  c.VoidMethod(false, 5, "Hi", NULL, Printable(), Unprintable());
+  const std::string output = GetCapturedStdout();
+  EXPECT_PRED_FORMAT2(IsSubstring, "GMOCK WARNING", output);
+  EXPECT_PRED_FORMAT2(IsNotSubstring, "Stack trace:", output);
+}
+
+// Tests that an uninteresting mock function call on a naggy mock
+// generates a warning containing the stack trace when
+// --gmock_verbose=info is specified.
+TEST(FunctionCallMessageTest,
+     UninterestingCallOnNaggyMockGeneratesFyiWithStackTraceWhenVerboseInfo) {
+  GMOCK_FLAG(verbose) = kInfoVerbosity;
+  NaggyMock<MockC> c;
+  CaptureStdout();
+  c.VoidMethod(false, 5, "Hi", NULL, Printable(), Unprintable());
+  const std::string output = GetCapturedStdout();
+  EXPECT_PRED_FORMAT2(IsSubstring, "GMOCK WARNING", output);
+  EXPECT_PRED_FORMAT2(IsSubstring, "Stack trace:", output);
+
+# ifndef NDEBUG
+
+  // We check the stack trace content in dbg-mode only, as opt-mode
+  // may inline the call we are interested in seeing.
+
+  // Verifies that a void mock function's name appears in the stack
+  // trace.
+  EXPECT_PRED_FORMAT2(IsSubstring, "VoidMethod(", output);
+
+  // Verifies that a non-void mock function's name appears in the
+  // stack trace.
+  CaptureStdout();
+  c.NonVoidMethod();
+  const std::string output2 = GetCapturedStdout();
+  EXPECT_PRED_FORMAT2(IsSubstring, "NonVoidMethod(", output2);
+
+# endif  // NDEBUG
+}
+
+// Tests that an uninteresting mock function call on a naggy mock
+// causes the function arguments and return value to be printed.
+TEST(FunctionCallMessageTest,
+     UninterestingCallOnNaggyMockPrintsArgumentsAndReturnValue) {
+  // A non-void mock function.
+  NaggyMock<MockB> b;
+  CaptureStdout();
+  b.DoB();
+  const std::string output1 = GetCapturedStdout();
+  EXPECT_PRED_FORMAT2(
+      IsSubstring,
+      "Uninteresting mock function call - returning default value.\n"
+      "    Function call: DoB()\n"
+      "          Returns: 0\n", output1.c_str());
+  // Makes sure the return value is printed.
+
+  // A void mock function.
+  NaggyMock<MockC> c;
+  CaptureStdout();
+  c.VoidMethod(false, 5, "Hi", NULL, Printable(), Unprintable());
+  const std::string output2 = GetCapturedStdout();
+  EXPECT_THAT(output2.c_str(),
+              ContainsRegex(
+                  "Uninteresting mock function call - returning directly\\.\n"
+                  "    Function call: VoidMethod"
+                  "\\(false, 5, \"Hi\", NULL, @.+ "
+                  "Printable, 4-byte object <00-00 00-00>\\)"));
+  // A void function has no return value to print.
+}
+
+// Tests how the --gmock_verbose flag affects Google Mock's output.
+
+class GMockVerboseFlagTest : public VerboseFlagPreservingFixture {
+ public:
+  // Verifies that the given Google Mock output is correct.  (When
+  // should_print is true, the output should match the given regex and
+  // contain the given function name in the stack trace.  When it's
+  // false, the output should be empty.)
+  void VerifyOutput(const std::string& output, bool should_print,
+                    const string& expected_substring,
+                    const string& function_name) {
+    if (should_print) {
+      EXPECT_THAT(output.c_str(), HasSubstr(expected_substring));
+# ifndef NDEBUG
+      // We check the stack trace content in dbg-mode only, as opt-mode
+      // may inline the call we are interested in seeing.
+      EXPECT_THAT(output.c_str(), HasSubstr(function_name));
+# else
+      // Suppresses 'unused function parameter' warnings.
+      static_cast<void>(function_name);
+# endif  // NDEBUG
+    } else {
+      EXPECT_STREQ("", output.c_str());
+    }
+  }
+
+  // Tests how the flag affects expected calls.
+  void TestExpectedCall(bool should_print) {
+    MockA a;
+    EXPECT_CALL(a, DoA(5));
+    EXPECT_CALL(a, Binary(_, 1))
+        .WillOnce(Return(true));
+
+    // A void-returning function.
+    CaptureStdout();
+    a.DoA(5);
+    VerifyOutput(
+        GetCapturedStdout(),
+        should_print,
+        "Mock function call matches EXPECT_CALL(a, DoA(5))...\n"
+        "    Function call: DoA(5)\n"
+        "Stack trace:\n",
+        "DoA");
+
+    // A non-void-returning function.
+    CaptureStdout();
+    a.Binary(2, 1);
+    VerifyOutput(
+        GetCapturedStdout(),
+        should_print,
+        "Mock function call matches EXPECT_CALL(a, Binary(_, 1))...\n"
+        "    Function call: Binary(2, 1)\n"
+        "          Returns: true\n"
+        "Stack trace:\n",
+        "Binary");
+  }
+
+  // Tests how the flag affects uninteresting calls on a naggy mock.
+  void TestUninterestingCallOnNaggyMock(bool should_print) {
+    NaggyMock<MockA> a;
+    const string note =
+        "NOTE: You can safely ignore the above warning unless this "
+        "call should not happen.  Do not suppress it by blindly adding "
+        "an EXPECT_CALL() if you don't mean to enforce the call.  "
+        "See http://code.google.com/p/googlemock/wiki/CookBook#"
+        "Knowing_When_to_Expect for details.";
+
+    // A void-returning function.
+    CaptureStdout();
+    a.DoA(5);
+    VerifyOutput(
+        GetCapturedStdout(),
+        should_print,
+        "\nGMOCK WARNING:\n"
+        "Uninteresting mock function call - returning directly.\n"
+        "    Function call: DoA(5)\n" +
+        note,
+        "DoA");
+
+    // A non-void-returning function.
+    CaptureStdout();
+    a.Binary(2, 1);
+    VerifyOutput(
+        GetCapturedStdout(),
+        should_print,
+        "\nGMOCK WARNING:\n"
+        "Uninteresting mock function call - returning default value.\n"
+        "    Function call: Binary(2, 1)\n"
+        "          Returns: false\n" +
+        note,
+        "Binary");
+  }
+};
+
+// Tests that --gmock_verbose=info causes both expected and
+// uninteresting calls to be reported.
+TEST_F(GMockVerboseFlagTest, Info) {
+  GMOCK_FLAG(verbose) = kInfoVerbosity;
+  TestExpectedCall(true);
+  TestUninterestingCallOnNaggyMock(true);
+}
+
+// Tests that --gmock_verbose=warning causes uninteresting calls to be
+// reported.
+TEST_F(GMockVerboseFlagTest, Warning) {
+  GMOCK_FLAG(verbose) = kWarningVerbosity;
+  TestExpectedCall(false);
+  TestUninterestingCallOnNaggyMock(true);
+}
+
+// Tests that --gmock_verbose=warning causes neither expected nor
+// uninteresting calls to be reported.
+TEST_F(GMockVerboseFlagTest, Error) {
+  GMOCK_FLAG(verbose) = kErrorVerbosity;
+  TestExpectedCall(false);
+  TestUninterestingCallOnNaggyMock(false);
+}
+
+// Tests that --gmock_verbose=SOME_INVALID_VALUE has the same effect
+// as --gmock_verbose=warning.
+TEST_F(GMockVerboseFlagTest, InvalidFlagIsTreatedAsWarning) {
+  GMOCK_FLAG(verbose) = "invalid";  // Treated as "warning".
+  TestExpectedCall(false);
+  TestUninterestingCallOnNaggyMock(true);
+}
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+// A helper class that generates a failure when printed.  We use it to
+// ensure that Google Mock doesn't print a value (even to an internal
+// buffer) when it is not supposed to do so.
+class PrintMeNot {};
+
+void PrintTo(PrintMeNot /* dummy */, ::std::ostream* /* os */) {
+  ADD_FAILURE() << "Google Mock is printing a value that shouldn't be "
+                << "printed even to an internal buffer.";
+}
+
+class LogTestHelper {
+ public:
+  LogTestHelper() {}
+
+  MOCK_METHOD1(Foo, PrintMeNot(PrintMeNot));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(LogTestHelper);
+};
+
+class GMockLogTest : public VerboseFlagPreservingFixture {
+ protected:
+  LogTestHelper helper_;
+};
+
+TEST_F(GMockLogTest, DoesNotPrintGoodCallInternallyIfVerbosityIsWarning) {
+  GMOCK_FLAG(verbose) = kWarningVerbosity;
+  EXPECT_CALL(helper_, Foo(_))
+      .WillOnce(Return(PrintMeNot()));
+  helper_.Foo(PrintMeNot());  // This is an expected call.
+}
+
+TEST_F(GMockLogTest, DoesNotPrintGoodCallInternallyIfVerbosityIsError) {
+  GMOCK_FLAG(verbose) = kErrorVerbosity;
+  EXPECT_CALL(helper_, Foo(_))
+      .WillOnce(Return(PrintMeNot()));
+  helper_.Foo(PrintMeNot());  // This is an expected call.
+}
+
+TEST_F(GMockLogTest, DoesNotPrintWarningInternallyIfVerbosityIsError) {
+  GMOCK_FLAG(verbose) = kErrorVerbosity;
+  ON_CALL(helper_, Foo(_))
+      .WillByDefault(Return(PrintMeNot()));
+  helper_.Foo(PrintMeNot());  // This should generate a warning.
+}
+
+// Tests Mock::AllowLeak().
+
+TEST(AllowLeakTest, AllowsLeakingUnusedMockObject) {
+  MockA* a = new MockA;
+  Mock::AllowLeak(a);
+}
+
+TEST(AllowLeakTest, CanBeCalledBeforeOnCall) {
+  MockA* a = new MockA;
+  Mock::AllowLeak(a);
+  ON_CALL(*a, DoA(_)).WillByDefault(Return());
+  a->DoA(0);
+}
+
+TEST(AllowLeakTest, CanBeCalledAfterOnCall) {
+  MockA* a = new MockA;
+  ON_CALL(*a, DoA(_)).WillByDefault(Return());
+  Mock::AllowLeak(a);
+}
+
+TEST(AllowLeakTest, CanBeCalledBeforeExpectCall) {
+  MockA* a = new MockA;
+  Mock::AllowLeak(a);
+  EXPECT_CALL(*a, DoA(_));
+  a->DoA(0);
+}
+
+TEST(AllowLeakTest, CanBeCalledAfterExpectCall) {
+  MockA* a = new MockA;
+  EXPECT_CALL(*a, DoA(_)).Times(AnyNumber());
+  Mock::AllowLeak(a);
+}
+
+TEST(AllowLeakTest, WorksWhenBothOnCallAndExpectCallArePresent) {
+  MockA* a = new MockA;
+  ON_CALL(*a, DoA(_)).WillByDefault(Return());
+  EXPECT_CALL(*a, DoA(_)).Times(AnyNumber());
+  Mock::AllowLeak(a);
+}
+
+// Tests that we can verify and clear a mock object's expectations
+// when none of its methods has expectations.
+TEST(VerifyAndClearExpectationsTest, NoMethodHasExpectations) {
+  MockB b;
+  ASSERT_TRUE(Mock::VerifyAndClearExpectations(&b));
+
+  // There should be no expectations on the methods now, so we can
+  // freely call them.
+  EXPECT_EQ(0, b.DoB());
+  EXPECT_EQ(0, b.DoB(1));
+}
+
+// Tests that we can verify and clear a mock object's expectations
+// when some, but not all, of its methods have expectations *and* the
+// verification succeeds.
+TEST(VerifyAndClearExpectationsTest, SomeMethodsHaveExpectationsAndSucceed) {
+  MockB b;
+  EXPECT_CALL(b, DoB())
+      .WillOnce(Return(1));
+  b.DoB();
+  ASSERT_TRUE(Mock::VerifyAndClearExpectations(&b));
+
+  // There should be no expectations on the methods now, so we can
+  // freely call them.
+  EXPECT_EQ(0, b.DoB());
+  EXPECT_EQ(0, b.DoB(1));
+}
+
+// Tests that we can verify and clear a mock object's expectations
+// when some, but not all, of its methods have expectations *and* the
+// verification fails.
+TEST(VerifyAndClearExpectationsTest, SomeMethodsHaveExpectationsAndFail) {
+  MockB b;
+  EXPECT_CALL(b, DoB())
+      .WillOnce(Return(1));
+  bool result = true;
+  EXPECT_NONFATAL_FAILURE(result = Mock::VerifyAndClearExpectations(&b),
+                          "Actual: never called");
+  ASSERT_FALSE(result);
+
+  // There should be no expectations on the methods now, so we can
+  // freely call them.
+  EXPECT_EQ(0, b.DoB());
+  EXPECT_EQ(0, b.DoB(1));
+}
+
+// Tests that we can verify and clear a mock object's expectations
+// when all of its methods have expectations.
+TEST(VerifyAndClearExpectationsTest, AllMethodsHaveExpectations) {
+  MockB b;
+  EXPECT_CALL(b, DoB())
+      .WillOnce(Return(1));
+  EXPECT_CALL(b, DoB(_))
+      .WillOnce(Return(2));
+  b.DoB();
+  b.DoB(1);
+  ASSERT_TRUE(Mock::VerifyAndClearExpectations(&b));
+
+  // There should be no expectations on the methods now, so we can
+  // freely call them.
+  EXPECT_EQ(0, b.DoB());
+  EXPECT_EQ(0, b.DoB(1));
+}
+
+// Tests that we can verify and clear a mock object's expectations
+// when a method has more than one expectation.
+TEST(VerifyAndClearExpectationsTest, AMethodHasManyExpectations) {
+  MockB b;
+  EXPECT_CALL(b, DoB(0))
+      .WillOnce(Return(1));
+  EXPECT_CALL(b, DoB(_))
+      .WillOnce(Return(2));
+  b.DoB(1);
+  bool result = true;
+  EXPECT_NONFATAL_FAILURE(result = Mock::VerifyAndClearExpectations(&b),
+                          "Actual: never called");
+  ASSERT_FALSE(result);
+
+  // There should be no expectations on the methods now, so we can
+  // freely call them.
+  EXPECT_EQ(0, b.DoB());
+  EXPECT_EQ(0, b.DoB(1));
+}
+
+// Tests that we can call VerifyAndClearExpectations() on the same
+// mock object multiple times.
+TEST(VerifyAndClearExpectationsTest, CanCallManyTimes) {
+  MockB b;
+  EXPECT_CALL(b, DoB());
+  b.DoB();
+  Mock::VerifyAndClearExpectations(&b);
+
+  EXPECT_CALL(b, DoB(_))
+      .WillOnce(Return(1));
+  b.DoB(1);
+  Mock::VerifyAndClearExpectations(&b);
+  Mock::VerifyAndClearExpectations(&b);
+
+  // There should be no expectations on the methods now, so we can
+  // freely call them.
+  EXPECT_EQ(0, b.DoB());
+  EXPECT_EQ(0, b.DoB(1));
+}
+
+// Tests that we can clear a mock object's default actions when none
+// of its methods has default actions.
+TEST(VerifyAndClearTest, NoMethodHasDefaultActions) {
+  MockB b;
+  // If this crashes or generates a failure, the test will catch it.
+  Mock::VerifyAndClear(&b);
+  EXPECT_EQ(0, b.DoB());
+}
+
+// Tests that we can clear a mock object's default actions when some,
+// but not all of its methods have default actions.
+TEST(VerifyAndClearTest, SomeMethodsHaveDefaultActions) {
+  MockB b;
+  ON_CALL(b, DoB())
+      .WillByDefault(Return(1));
+
+  Mock::VerifyAndClear(&b);
+
+  // Verifies that the default action of int DoB() was removed.
+  EXPECT_EQ(0, b.DoB());
+}
+
+// Tests that we can clear a mock object's default actions when all of
+// its methods have default actions.
+TEST(VerifyAndClearTest, AllMethodsHaveDefaultActions) {
+  MockB b;
+  ON_CALL(b, DoB())
+      .WillByDefault(Return(1));
+  ON_CALL(b, DoB(_))
+      .WillByDefault(Return(2));
+
+  Mock::VerifyAndClear(&b);
+
+  // Verifies that the default action of int DoB() was removed.
+  EXPECT_EQ(0, b.DoB());
+
+  // Verifies that the default action of int DoB(int) was removed.
+  EXPECT_EQ(0, b.DoB(0));
+}
+
+// Tests that we can clear a mock object's default actions when a
+// method has more than one ON_CALL() set on it.
+TEST(VerifyAndClearTest, AMethodHasManyDefaultActions) {
+  MockB b;
+  ON_CALL(b, DoB(0))
+      .WillByDefault(Return(1));
+  ON_CALL(b, DoB(_))
+      .WillByDefault(Return(2));
+
+  Mock::VerifyAndClear(&b);
+
+  // Verifies that the default actions (there are two) of int DoB(int)
+  // were removed.
+  EXPECT_EQ(0, b.DoB(0));
+  EXPECT_EQ(0, b.DoB(1));
+}
+
+// Tests that we can call VerifyAndClear() on a mock object multiple
+// times.
+TEST(VerifyAndClearTest, CanCallManyTimes) {
+  MockB b;
+  ON_CALL(b, DoB())
+      .WillByDefault(Return(1));
+  Mock::VerifyAndClear(&b);
+  Mock::VerifyAndClear(&b);
+
+  ON_CALL(b, DoB(_))
+      .WillByDefault(Return(1));
+  Mock::VerifyAndClear(&b);
+
+  EXPECT_EQ(0, b.DoB());
+  EXPECT_EQ(0, b.DoB(1));
+}
+
+// Tests that VerifyAndClear() works when the verification succeeds.
+TEST(VerifyAndClearTest, Success) {
+  MockB b;
+  ON_CALL(b, DoB())
+      .WillByDefault(Return(1));
+  EXPECT_CALL(b, DoB(1))
+      .WillOnce(Return(2));
+
+  b.DoB();
+  b.DoB(1);
+  ASSERT_TRUE(Mock::VerifyAndClear(&b));
+
+  // There should be no expectations on the methods now, so we can
+  // freely call them.
+  EXPECT_EQ(0, b.DoB());
+  EXPECT_EQ(0, b.DoB(1));
+}
+
+// Tests that VerifyAndClear() works when the verification fails.
+TEST(VerifyAndClearTest, Failure) {
+  MockB b;
+  ON_CALL(b, DoB(_))
+      .WillByDefault(Return(1));
+  EXPECT_CALL(b, DoB())
+      .WillOnce(Return(2));
+
+  b.DoB(1);
+  bool result = true;
+  EXPECT_NONFATAL_FAILURE(result = Mock::VerifyAndClear(&b),
+                          "Actual: never called");
+  ASSERT_FALSE(result);
+
+  // There should be no expectations on the methods now, so we can
+  // freely call them.
+  EXPECT_EQ(0, b.DoB());
+  EXPECT_EQ(0, b.DoB(1));
+}
+
+// Tests that VerifyAndClear() works when the default actions and
+// expectations are set on a const mock object.
+TEST(VerifyAndClearTest, Const) {
+  MockB b;
+  ON_CALL(Const(b), DoB())
+      .WillByDefault(Return(1));
+
+  EXPECT_CALL(Const(b), DoB())
+      .WillOnce(DoDefault())
+      .WillOnce(Return(2));
+
+  b.DoB();
+  b.DoB();
+  ASSERT_TRUE(Mock::VerifyAndClear(&b));
+
+  // There should be no expectations on the methods now, so we can
+  // freely call them.
+  EXPECT_EQ(0, b.DoB());
+  EXPECT_EQ(0, b.DoB(1));
+}
+
+// Tests that we can set default actions and expectations on a mock
+// object after VerifyAndClear() has been called on it.
+TEST(VerifyAndClearTest, CanSetDefaultActionsAndExpectationsAfterwards) {
+  MockB b;
+  ON_CALL(b, DoB())
+      .WillByDefault(Return(1));
+  EXPECT_CALL(b, DoB(_))
+      .WillOnce(Return(2));
+  b.DoB(1);
+
+  Mock::VerifyAndClear(&b);
+
+  EXPECT_CALL(b, DoB())
+      .WillOnce(Return(3));
+  ON_CALL(b, DoB(_))
+      .WillByDefault(Return(4));
+
+  EXPECT_EQ(3, b.DoB());
+  EXPECT_EQ(4, b.DoB(1));
+}
+
+// Tests that calling VerifyAndClear() on one mock object does not
+// affect other mock objects (either of the same type or not).
+TEST(VerifyAndClearTest, DoesNotAffectOtherMockObjects) {
+  MockA a;
+  MockB b1;
+  MockB b2;
+
+  ON_CALL(a, Binary(_, _))
+      .WillByDefault(Return(true));
+  EXPECT_CALL(a, Binary(_, _))
+      .WillOnce(DoDefault())
+      .WillOnce(Return(false));
+
+  ON_CALL(b1, DoB())
+      .WillByDefault(Return(1));
+  EXPECT_CALL(b1, DoB(_))
+      .WillOnce(Return(2));
+
+  ON_CALL(b2, DoB())
+      .WillByDefault(Return(3));
+  EXPECT_CALL(b2, DoB(_));
+
+  b2.DoB(0);
+  Mock::VerifyAndClear(&b2);
+
+  // Verifies that the default actions and expectations of a and b1
+  // are still in effect.
+  EXPECT_TRUE(a.Binary(0, 0));
+  EXPECT_FALSE(a.Binary(0, 0));
+
+  EXPECT_EQ(1, b1.DoB());
+  EXPECT_EQ(2, b1.DoB(0));
+}
+
+TEST(VerifyAndClearTest,
+     DestroyingChainedMocksDoesNotDeadlockThroughExpectations) {
+  linked_ptr<MockA> a(new MockA);
+  ReferenceHoldingMock test_mock;
+
+  // EXPECT_CALL stores a reference to a inside test_mock.
+  EXPECT_CALL(test_mock, AcceptReference(_))
+      .WillRepeatedly(SetArgPointee<0>(a));
+
+  // Throw away the reference to the mock that we have in a. After this, the
+  // only reference to it is stored by test_mock.
+  a.reset();
+
+  // When test_mock goes out of scope, it destroys the last remaining reference
+  // to the mock object originally pointed to by a. This will cause the MockA
+  // destructor to be called from inside the ReferenceHoldingMock destructor.
+  // The state of all mocks is protected by a single global lock, but there
+  // should be no deadlock.
+}
+
+TEST(VerifyAndClearTest,
+     DestroyingChainedMocksDoesNotDeadlockThroughDefaultAction) {
+  linked_ptr<MockA> a(new MockA);
+  ReferenceHoldingMock test_mock;
+
+  // ON_CALL stores a reference to a inside test_mock.
+  ON_CALL(test_mock, AcceptReference(_))
+      .WillByDefault(SetArgPointee<0>(a));
+
+  // Throw away the reference to the mock that we have in a. After this, the
+  // only reference to it is stored by test_mock.
+  a.reset();
+
+  // When test_mock goes out of scope, it destroys the last remaining reference
+  // to the mock object originally pointed to by a. This will cause the MockA
+  // destructor to be called from inside the ReferenceHoldingMock destructor.
+  // The state of all mocks is protected by a single global lock, but there
+  // should be no deadlock.
+}
+
+// Tests that a mock function's action can call a mock function
+// (either the same function or a different one) either as an explicit
+// action or as a default action without causing a dead lock.  It
+// verifies that the action is not performed inside the critical
+// section.
+TEST(SynchronizationTest, CanCallMockMethodInAction) {
+  MockA a;
+  MockC c;
+  ON_CALL(a, DoA(_))
+      .WillByDefault(IgnoreResult(InvokeWithoutArgs(&c,
+                                                    &MockC::NonVoidMethod)));
+  EXPECT_CALL(a, DoA(1));
+  EXPECT_CALL(a, DoA(1))
+      .WillOnce(Invoke(&a, &MockA::DoA))
+      .RetiresOnSaturation();
+  EXPECT_CALL(c, NonVoidMethod());
+
+  a.DoA(1);
+  // This will match the second EXPECT_CALL() and trigger another a.DoA(1),
+  // which will in turn match the first EXPECT_CALL() and trigger a call to
+  // c.NonVoidMethod() that was specified by the ON_CALL() since the first
+  // EXPECT_CALL() did not specify an action.
+}
+
+}  // namespace
+
+// Allows the user to define his own main and then invoke gmock_main
+// from it. This might be necessary on some platforms which require
+// specific setup and teardown.
+#if GMOCK_RENAME_MAIN
+int gmock_main(int argc, char **argv) {
+#else
+int main(int argc, char **argv) {
+#endif  // GMOCK_RENAME_MAIN
+  testing::InitGoogleMock(&argc, argv);
+
+  // Ensures that the tests pass no matter what value of
+  // --gmock_catch_leaked_mocks and --gmock_verbose the user specifies.
+  testing::GMOCK_FLAG(catch_leaked_mocks) = true;
+  testing::GMOCK_FLAG(verbose) = testing::internal::kWarningVerbosity;
+
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/googletest/googlemock/test/gmock_all_test.cc b/third_party/googletest/googlemock/test/gmock_all_test.cc
new file mode 100644
index 0000000..56d6c49
--- /dev/null
+++ b/third_party/googletest/googlemock/test/gmock_all_test.cc
@@ -0,0 +1,51 @@
+// Copyright 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// Tests for Google C++ Mocking Framework (Google Mock)
+//
+// Some users use a build system that Google Mock doesn't support directly,
+// yet they still want to build and run Google Mock's own tests.  This file
+// includes most such tests, making it easier for these users to maintain
+// their build scripts (they just need to build this file, even though the
+// below list of actual *_test.cc files might change).
+#include "test/gmock-actions_test.cc"
+#include "test/gmock-cardinalities_test.cc"
+#include "test/gmock-generated-actions_test.cc"
+#include "test/gmock-generated-function-mockers_test.cc"
+#include "test/gmock-generated-internal-utils_test.cc"
+#include "test/gmock-generated-matchers_test.cc"
+#include "test/gmock-internal-utils_test.cc"
+#include "test/gmock-matchers_test.cc"
+#include "test/gmock-more-actions_test.cc"
+#include "test/gmock-nice-strict_test.cc"
+#include "test/gmock-port_test.cc"
+#include "test/gmock-spec-builders_test.cc"
+#include "test/gmock_test.cc"
diff --git a/third_party/googletest/googlemock/test/gmock_ex_test.cc b/third_party/googletest/googlemock/test/gmock_ex_test.cc
new file mode 100644
index 0000000..3afed86
--- /dev/null
+++ b/third_party/googletest/googlemock/test/gmock_ex_test.cc
@@ -0,0 +1,81 @@
+// Copyright 2013, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Tests Google Mock's functionality that depends on exceptions.
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace {
+
+using testing::HasSubstr;
+using testing::internal::GoogleTestFailureException;
+
+// A type that cannot be default constructed.
+class NonDefaultConstructible {
+ public:
+  explicit NonDefaultConstructible(int /* dummy */) {}
+};
+
+class MockFoo {
+ public:
+  // A mock method that returns a user-defined type.  Google Mock
+  // doesn't know what the default value for this type is.
+  MOCK_METHOD0(GetNonDefaultConstructible, NonDefaultConstructible());
+};
+
+#if GTEST_HAS_EXCEPTIONS
+
+TEST(DefaultValueTest, ThrowsRuntimeErrorWhenNoDefaultValue) {
+  MockFoo mock;
+  try {
+    // No expectation is set on this method, so Google Mock must
+    // return the default value.  However, since Google Mock knows
+    // nothing about the return type, it doesn't know what to return,
+    // and has to throw (when exceptions are enabled) or abort
+    // (otherwise).
+    mock.GetNonDefaultConstructible();
+    FAIL() << "GetNonDefaultConstructible()'s return type has no default "
+           << "value, so Google Mock should have thrown.";
+  } catch (const GoogleTestFailureException& /* unused */) {
+    FAIL() << "Google Test does not try to catch an exception of type "
+           << "GoogleTestFailureException, which is used for reporting "
+           << "a failure to other testing frameworks.  Google Mock should "
+           << "not throw a GoogleTestFailureException as it will kill the "
+           << "entire test program instead of just the current TEST.";
+  } catch (const std::exception& ex) {
+    EXPECT_THAT(ex.what(), HasSubstr("has no default value"));
+  }
+}
+
+#endif
+
+}  // unnamed namespace
diff --git a/third_party/googletest/googlemock/test/gmock_leak_test.py b/third_party/googletest/googlemock/test/gmock_leak_test.py
new file mode 100755
index 0000000..997680c
--- /dev/null
+++ b/third_party/googletest/googlemock/test/gmock_leak_test.py
@@ -0,0 +1,108 @@
+#!/usr/bin/env python
+#
+# Copyright 2009, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Tests that leaked mock objects can be caught be Google Mock."""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+
+import gmock_test_utils
+
+
+PROGRAM_PATH = gmock_test_utils.GetTestExecutablePath('gmock_leak_test_')
+TEST_WITH_EXPECT_CALL = [PROGRAM_PATH, '--gtest_filter=*ExpectCall*']
+TEST_WITH_ON_CALL = [PROGRAM_PATH, '--gtest_filter=*OnCall*']
+TEST_MULTIPLE_LEAKS = [PROGRAM_PATH, '--gtest_filter=*MultipleLeaked*']
+
+environ = gmock_test_utils.environ
+SetEnvVar = gmock_test_utils.SetEnvVar
+
+# Tests in this file run a Google-Test-based test program and expect it
+# to terminate prematurely.  Therefore they are incompatible with
+# the premature-exit-file protocol by design.  Unset the
+# premature-exit filepath to prevent Google Test from creating
+# the file.
+SetEnvVar(gmock_test_utils.PREMATURE_EXIT_FILE_ENV_VAR, None)
+
+
+class GMockLeakTest(gmock_test_utils.TestCase):
+
+  def testCatchesLeakedMockByDefault(self):
+    self.assertNotEqual(
+        0,
+        gmock_test_utils.Subprocess(TEST_WITH_EXPECT_CALL,
+                                    env=environ).exit_code)
+    self.assertNotEqual(
+        0,
+        gmock_test_utils.Subprocess(TEST_WITH_ON_CALL,
+                                    env=environ).exit_code)
+
+  def testDoesNotCatchLeakedMockWhenDisabled(self):
+    self.assertEquals(
+        0,
+        gmock_test_utils.Subprocess(TEST_WITH_EXPECT_CALL +
+                                    ['--gmock_catch_leaked_mocks=0'],
+                                    env=environ).exit_code)
+    self.assertEquals(
+        0,
+        gmock_test_utils.Subprocess(TEST_WITH_ON_CALL +
+                                    ['--gmock_catch_leaked_mocks=0'],
+                                    env=environ).exit_code)
+
+  def testCatchesLeakedMockWhenEnabled(self):
+    self.assertNotEqual(
+        0,
+        gmock_test_utils.Subprocess(TEST_WITH_EXPECT_CALL +
+                                    ['--gmock_catch_leaked_mocks'],
+                                    env=environ).exit_code)
+    self.assertNotEqual(
+        0,
+        gmock_test_utils.Subprocess(TEST_WITH_ON_CALL +
+                                    ['--gmock_catch_leaked_mocks'],
+                                    env=environ).exit_code)
+
+  def testCatchesLeakedMockWhenEnabledWithExplictFlagValue(self):
+    self.assertNotEqual(
+        0,
+        gmock_test_utils.Subprocess(TEST_WITH_EXPECT_CALL +
+                                    ['--gmock_catch_leaked_mocks=1'],
+                                    env=environ).exit_code)
+
+  def testCatchesMultipleLeakedMocks(self):
+    self.assertNotEqual(
+        0,
+        gmock_test_utils.Subprocess(TEST_MULTIPLE_LEAKS +
+                                    ['--gmock_catch_leaked_mocks'],
+                                    env=environ).exit_code)
+
+
+if __name__ == '__main__':
+  gmock_test_utils.Main()
diff --git a/third_party/googletest/googlemock/test/gmock_leak_test_.cc b/third_party/googletest/googlemock/test/gmock_leak_test_.cc
new file mode 100644
index 0000000..1d27d22
--- /dev/null
+++ b/third_party/googletest/googlemock/test/gmock_leak_test_.cc
@@ -0,0 +1,100 @@
+// Copyright 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This program is for verifying that a leaked mock object can be
+// caught by Google Mock's leak detector.
+
+#include "gmock/gmock.h"
+
+namespace {
+
+using ::testing::Return;
+
+class FooInterface {
+ public:
+  virtual ~FooInterface() {}
+  virtual void DoThis() = 0;
+};
+
+class MockFoo : public FooInterface {
+ public:
+  MockFoo() {}
+
+  MOCK_METHOD0(DoThis, void());
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFoo);
+};
+
+TEST(LeakTest, LeakedMockWithExpectCallCausesFailureWhenLeakCheckingIsEnabled) {
+  MockFoo* foo = new MockFoo;
+
+  EXPECT_CALL(*foo, DoThis());
+  foo->DoThis();
+
+  // In order to test the leak detector, we deliberately leak foo.
+
+  // Makes sure Google Mock's leak detector can change the exit code
+  // to 1 even when the code is already exiting with 0.
+  exit(0);
+}
+
+TEST(LeakTest, LeakedMockWithOnCallCausesFailureWhenLeakCheckingIsEnabled) {
+  MockFoo* foo = new MockFoo;
+
+  ON_CALL(*foo, DoThis()).WillByDefault(Return());
+
+  // In order to test the leak detector, we deliberately leak foo.
+
+  // Makes sure Google Mock's leak detector can change the exit code
+  // to 1 even when the code is already exiting with 0.
+  exit(0);
+}
+
+TEST(LeakTest, CatchesMultipleLeakedMockObjects) {
+  MockFoo* foo1 = new MockFoo;
+  MockFoo* foo2 = new MockFoo;
+
+  ON_CALL(*foo1, DoThis()).WillByDefault(Return());
+  EXPECT_CALL(*foo2, DoThis());
+  foo2->DoThis();
+
+  // In order to test the leak detector, we deliberately leak foo1 and
+  // foo2.
+
+  // Makes sure Google Mock's leak detector can change the exit code
+  // to 1 even when the code is already exiting with 0.
+  exit(0);
+}
+
+}  // namespace
diff --git a/third_party/googletest/googlemock/test/gmock_link2_test.cc b/third_party/googletest/googlemock/test/gmock_link2_test.cc
new file mode 100644
index 0000000..4c310c3
--- /dev/null
+++ b/third_party/googletest/googlemock/test/gmock_link2_test.cc
@@ -0,0 +1,40 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan), vladl@google.com (Vlad Losev)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file is for verifying that various Google Mock constructs do not
+// produce linker errors when instantiated in different translation units.
+// Please see gmock_link_test.h for details.
+
+#define LinkTest LinkTest2
+
+#include  "test/gmock_link_test.h"
diff --git a/third_party/googletest/googlemock/test/gmock_link_test.cc b/third_party/googletest/googlemock/test/gmock_link_test.cc
new file mode 100644
index 0000000..61e97d1
--- /dev/null
+++ b/third_party/googletest/googlemock/test/gmock_link_test.cc
@@ -0,0 +1,40 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan), vladl@google.com (Vlad Losev)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file is for verifying that various Google Mock constructs do not
+// produce linker errors when instantiated in different translation units.
+// Please see gmock_link_test.h for details.
+
+#define LinkTest LinkTest1
+
+#include  "test/gmock_link_test.h"
diff --git a/third_party/googletest/googlemock/test/gmock_link_test.h b/third_party/googletest/googlemock/test/gmock_link_test.h
new file mode 100644
index 0000000..1f55f5b
--- /dev/null
+++ b/third_party/googletest/googlemock/test/gmock_link_test.h
@@ -0,0 +1,669 @@
+// Copyright 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vladl@google.com (Vlad Losev)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests that:
+// a. A header file defining a mock class can be included in multiple
+//    translation units without causing a link error.
+// b. Actions and matchers can be instantiated with identical template
+//    arguments in different translation units without causing link
+//    errors.
+//    The following constructs are currently tested:
+//    Actions:
+//      Return()
+//      Return(value)
+//      ReturnNull
+//      ReturnRef
+//      Assign
+//      SetArgPointee
+//      SetArrayArgument
+//      SetErrnoAndReturn
+//      Invoke(function)
+//      Invoke(object, method)
+//      InvokeWithoutArgs(function)
+//      InvokeWithoutArgs(object, method)
+//      InvokeArgument
+//      WithArg
+//      WithArgs
+//      WithoutArgs
+//      DoAll
+//      DoDefault
+//      IgnoreResult
+//      Throw
+//      ACTION()-generated
+//      ACTION_P()-generated
+//      ACTION_P2()-generated
+//    Matchers:
+//      _
+//      A
+//      An
+//      Eq
+//      Gt, Lt, Ge, Le, Ne
+//      NotNull
+//      Ref
+//      TypedEq
+//      DoubleEq
+//      FloatEq
+//      NanSensitiveDoubleEq
+//      NanSensitiveFloatEq
+//      ContainsRegex
+//      MatchesRegex
+//      EndsWith
+//      HasSubstr
+//      StartsWith
+//      StrCaseEq
+//      StrCaseNe
+//      StrEq
+//      StrNe
+//      ElementsAre
+//      ElementsAreArray
+//      ContainerEq
+//      Field
+//      Property
+//      ResultOf(function)
+//      Pointee
+//      Truly(predicate)
+//      AllOf
+//      AnyOf
+//      Not
+//      MatcherCast<T>
+//
+//  Please note: this test does not verify the functioning of these
+//  constructs, only that the programs using them will link successfully.
+//
+// Implementation note:
+// This test requires identical definitions of Interface and Mock to be
+// included in different translation units.  We achieve this by writing
+// them in this header and #including it in gmock_link_test.cc and
+// gmock_link2_test.cc.  Because the symbols generated by the compiler for
+// those constructs must be identical in both translation units,
+// definitions of Interface and Mock tests MUST be kept in the SAME
+// NON-ANONYMOUS namespace in this file.  The test fixture class LinkTest
+// is defined as LinkTest1 in gmock_link_test.cc and as LinkTest2 in
+// gmock_link2_test.cc to avoid producing linker errors.
+
+#ifndef GMOCK_TEST_GMOCK_LINK_TEST_H_
+#define GMOCK_TEST_GMOCK_LINK_TEST_H_
+
+#include "gmock/gmock.h"
+
+#if !GTEST_OS_WINDOWS_MOBILE
+# include <errno.h>
+#endif
+
+#include "gmock/internal/gmock-port.h"
+#include "gtest/gtest.h"
+#include <iostream>
+#include <vector>
+
+using testing::_;
+using testing::A;
+using testing::AllOf;
+using testing::AnyOf;
+using testing::Assign;
+using testing::ContainerEq;
+using testing::DoAll;
+using testing::DoDefault;
+using testing::DoubleEq;
+using testing::ElementsAre;
+using testing::ElementsAreArray;
+using testing::EndsWith;
+using testing::Eq;
+using testing::Field;
+using testing::FloatEq;
+using testing::Ge;
+using testing::Gt;
+using testing::HasSubstr;
+using testing::IgnoreResult;
+using testing::Invoke;
+using testing::InvokeArgument;
+using testing::InvokeWithoutArgs;
+using testing::IsNull;
+using testing::Le;
+using testing::Lt;
+using testing::Matcher;
+using testing::MatcherCast;
+using testing::NanSensitiveDoubleEq;
+using testing::NanSensitiveFloatEq;
+using testing::Ne;
+using testing::Not;
+using testing::NotNull;
+using testing::Pointee;
+using testing::Property;
+using testing::Ref;
+using testing::ResultOf;
+using testing::Return;
+using testing::ReturnNull;
+using testing::ReturnRef;
+using testing::SetArgPointee;
+using testing::SetArrayArgument;
+using testing::StartsWith;
+using testing::StrCaseEq;
+using testing::StrCaseNe;
+using testing::StrEq;
+using testing::StrNe;
+using testing::Truly;
+using testing::TypedEq;
+using testing::WithArg;
+using testing::WithArgs;
+using testing::WithoutArgs;
+
+#if !GTEST_OS_WINDOWS_MOBILE
+using testing::SetErrnoAndReturn;
+#endif
+
+#if GTEST_HAS_EXCEPTIONS
+using testing::Throw;
+#endif
+
+using testing::ContainsRegex;
+using testing::MatchesRegex;
+
+class Interface {
+ public:
+  virtual ~Interface() {}
+  virtual void VoidFromString(char* str) = 0;
+  virtual char* StringFromString(char* str) = 0;
+  virtual int IntFromString(char* str) = 0;
+  virtual int& IntRefFromString(char* str) = 0;
+  virtual void VoidFromFunc(void(*func)(char* str)) = 0;
+  virtual void VoidFromIntRef(int& n) = 0;  // NOLINT
+  virtual void VoidFromFloat(float n) = 0;
+  virtual void VoidFromDouble(double n) = 0;
+  virtual void VoidFromVector(const std::vector<int>& v) = 0;
+};
+
+class Mock: public Interface {
+ public:
+  Mock() {}
+
+  MOCK_METHOD1(VoidFromString, void(char* str));
+  MOCK_METHOD1(StringFromString, char*(char* str));
+  MOCK_METHOD1(IntFromString, int(char* str));
+  MOCK_METHOD1(IntRefFromString, int&(char* str));
+  MOCK_METHOD1(VoidFromFunc, void(void(*func)(char* str)));
+  MOCK_METHOD1(VoidFromIntRef, void(int& n));  // NOLINT
+  MOCK_METHOD1(VoidFromFloat, void(float n));
+  MOCK_METHOD1(VoidFromDouble, void(double n));
+  MOCK_METHOD1(VoidFromVector, void(const std::vector<int>& v));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Mock);
+};
+
+class InvokeHelper {
+ public:
+  static void StaticVoidFromVoid() {}
+  void VoidFromVoid() {}
+  static void StaticVoidFromString(char* /* str */) {}
+  void VoidFromString(char* /* str */) {}
+  static int StaticIntFromString(char* /* str */) { return 1; }
+  static bool StaticBoolFromString(const char* /* str */) { return true; }
+};
+
+class FieldHelper {
+ public:
+  explicit FieldHelper(int a_field) : field_(a_field) {}
+  int field() const { return field_; }
+  int field_;  // NOLINT -- need external access to field_ to test
+               //           the Field matcher.
+};
+
+// Tests the linkage of the ReturnVoid action.
+TEST(LinkTest, TestReturnVoid) {
+  Mock mock;
+
+  EXPECT_CALL(mock, VoidFromString(_)).WillOnce(Return());
+  mock.VoidFromString(NULL);
+}
+
+// Tests the linkage of the Return action.
+TEST(LinkTest, TestReturn) {
+  Mock mock;
+  char ch = 'x';
+
+  EXPECT_CALL(mock, StringFromString(_)).WillOnce(Return(&ch));
+  mock.StringFromString(NULL);
+}
+
+// Tests the linkage of the ReturnNull action.
+TEST(LinkTest, TestReturnNull) {
+  Mock mock;
+
+  EXPECT_CALL(mock, VoidFromString(_)).WillOnce(Return());
+  mock.VoidFromString(NULL);
+}
+
+// Tests the linkage of the ReturnRef action.
+TEST(LinkTest, TestReturnRef) {
+  Mock mock;
+  int n = 42;
+
+  EXPECT_CALL(mock, IntRefFromString(_)).WillOnce(ReturnRef(n));
+  mock.IntRefFromString(NULL);
+}
+
+// Tests the linkage of the Assign action.
+TEST(LinkTest, TestAssign) {
+  Mock mock;
+  char ch = 'x';
+
+  EXPECT_CALL(mock, VoidFromString(_)).WillOnce(Assign(&ch, 'y'));
+  mock.VoidFromString(NULL);
+}
+
+// Tests the linkage of the SetArgPointee action.
+TEST(LinkTest, TestSetArgPointee) {
+  Mock mock;
+  char ch = 'x';
+
+  EXPECT_CALL(mock, VoidFromString(_)).WillOnce(SetArgPointee<0>('y'));
+  mock.VoidFromString(&ch);
+}
+
+// Tests the linkage of the SetArrayArgument action.
+TEST(LinkTest, TestSetArrayArgument) {
+  Mock mock;
+  char ch = 'x';
+  char ch2 = 'y';
+
+  EXPECT_CALL(mock, VoidFromString(_)).WillOnce(SetArrayArgument<0>(&ch2,
+                                                                    &ch2 + 1));
+  mock.VoidFromString(&ch);
+}
+
+#if !GTEST_OS_WINDOWS_MOBILE
+
+// Tests the linkage of the SetErrnoAndReturn action.
+TEST(LinkTest, TestSetErrnoAndReturn) {
+  Mock mock;
+
+  int saved_errno = errno;
+  EXPECT_CALL(mock, IntFromString(_)).WillOnce(SetErrnoAndReturn(1, -1));
+  mock.IntFromString(NULL);
+  errno = saved_errno;
+}
+
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+// Tests the linkage of the Invoke(function) and Invoke(object, method) actions.
+TEST(LinkTest, TestInvoke) {
+  Mock mock;
+  InvokeHelper test_invoke_helper;
+
+  EXPECT_CALL(mock, VoidFromString(_))
+      .WillOnce(Invoke(&InvokeHelper::StaticVoidFromString))
+      .WillOnce(Invoke(&test_invoke_helper, &InvokeHelper::VoidFromString));
+  mock.VoidFromString(NULL);
+  mock.VoidFromString(NULL);
+}
+
+// Tests the linkage of the InvokeWithoutArgs action.
+TEST(LinkTest, TestInvokeWithoutArgs) {
+  Mock mock;
+  InvokeHelper test_invoke_helper;
+
+  EXPECT_CALL(mock, VoidFromString(_))
+      .WillOnce(InvokeWithoutArgs(&InvokeHelper::StaticVoidFromVoid))
+      .WillOnce(InvokeWithoutArgs(&test_invoke_helper,
+                                  &InvokeHelper::VoidFromVoid));
+  mock.VoidFromString(NULL);
+  mock.VoidFromString(NULL);
+}
+
+// Tests the linkage of the InvokeArgument action.
+TEST(LinkTest, TestInvokeArgument) {
+  Mock mock;
+  char ch = 'x';
+
+  EXPECT_CALL(mock, VoidFromFunc(_)).WillOnce(InvokeArgument<0>(&ch));
+  mock.VoidFromFunc(InvokeHelper::StaticVoidFromString);
+}
+
+// Tests the linkage of the WithArg action.
+TEST(LinkTest, TestWithArg) {
+  Mock mock;
+
+  EXPECT_CALL(mock, VoidFromString(_))
+      .WillOnce(WithArg<0>(Invoke(&InvokeHelper::StaticVoidFromString)));
+  mock.VoidFromString(NULL);
+}
+
+// Tests the linkage of the WithArgs action.
+TEST(LinkTest, TestWithArgs) {
+  Mock mock;
+
+  EXPECT_CALL(mock, VoidFromString(_))
+      .WillOnce(WithArgs<0>(Invoke(&InvokeHelper::StaticVoidFromString)));
+  mock.VoidFromString(NULL);
+}
+
+// Tests the linkage of the WithoutArgs action.
+TEST(LinkTest, TestWithoutArgs) {
+  Mock mock;
+
+  EXPECT_CALL(mock, VoidFromString(_)).WillOnce(WithoutArgs(Return()));
+  mock.VoidFromString(NULL);
+}
+
+// Tests the linkage of the DoAll action.
+TEST(LinkTest, TestDoAll) {
+  Mock mock;
+  char ch = 'x';
+
+  EXPECT_CALL(mock, VoidFromString(_))
+      .WillOnce(DoAll(SetArgPointee<0>('y'), Return()));
+  mock.VoidFromString(&ch);
+}
+
+// Tests the linkage of the DoDefault action.
+TEST(LinkTest, TestDoDefault) {
+  Mock mock;
+  char ch = 'x';
+
+  ON_CALL(mock, VoidFromString(_)).WillByDefault(Return());
+  EXPECT_CALL(mock, VoidFromString(_)).WillOnce(DoDefault());
+  mock.VoidFromString(&ch);
+}
+
+// Tests the linkage of the IgnoreResult action.
+TEST(LinkTest, TestIgnoreResult) {
+  Mock mock;
+
+  EXPECT_CALL(mock, VoidFromString(_)).WillOnce(IgnoreResult(Return(42)));
+  mock.VoidFromString(NULL);
+}
+
+#if GTEST_HAS_EXCEPTIONS
+// Tests the linkage of the Throw action.
+TEST(LinkTest, TestThrow) {
+  Mock mock;
+
+  EXPECT_CALL(mock, VoidFromString(_)).WillOnce(Throw(42));
+  EXPECT_THROW(mock.VoidFromString(NULL), int);
+}
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// The ACTION*() macros trigger warning C4100 (unreferenced formal
+// parameter) in MSVC with -W4.  Unfortunately they cannot be fixed in
+// the macro definition, as the warnings are generated when the macro
+// is expanded and macro expansion cannot contain #pragma.  Therefore
+// we suppress them here.
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4100)
+#endif
+
+// Tests the linkage of actions created using ACTION macro.
+namespace {
+ACTION(Return1) { return 1; }
+}
+
+TEST(LinkTest, TestActionMacro) {
+  Mock mock;
+
+  EXPECT_CALL(mock, IntFromString(_)).WillOnce(Return1());
+  mock.IntFromString(NULL);
+}
+
+// Tests the linkage of actions created using ACTION_P macro.
+namespace {
+ACTION_P(ReturnArgument, ret_value) { return ret_value; }
+}
+
+TEST(LinkTest, TestActionPMacro) {
+  Mock mock;
+
+  EXPECT_CALL(mock, IntFromString(_)).WillOnce(ReturnArgument(42));
+  mock.IntFromString(NULL);
+}
+
+// Tests the linkage of actions created using ACTION_P2 macro.
+namespace {
+ACTION_P2(ReturnEqualsEitherOf, first, second) {
+  return arg0 == first || arg0 == second;
+}
+}
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+TEST(LinkTest, TestActionP2Macro) {
+  Mock mock;
+  char ch = 'x';
+
+  EXPECT_CALL(mock, IntFromString(_))
+      .WillOnce(ReturnEqualsEitherOf("one", "two"));
+  mock.IntFromString(&ch);
+}
+
+// Tests the linkage of the "_" matcher.
+TEST(LinkTest, TestMatcherAnything) {
+  Mock mock;
+
+  ON_CALL(mock, VoidFromString(_)).WillByDefault(Return());
+}
+
+// Tests the linkage of the A matcher.
+TEST(LinkTest, TestMatcherA) {
+  Mock mock;
+
+  ON_CALL(mock, VoidFromString(A<char*>())).WillByDefault(Return());
+}
+
+// Tests the linkage of the Eq and the "bare value" matcher.
+TEST(LinkTest, TestMatchersEq) {
+  Mock mock;
+  const char* p = "x";
+
+  ON_CALL(mock, VoidFromString(Eq(p))).WillByDefault(Return());
+  ON_CALL(mock, VoidFromString(const_cast<char*>("y")))
+      .WillByDefault(Return());
+}
+
+// Tests the linkage of the Lt, Gt, Le, Ge, and Ne matchers.
+TEST(LinkTest, TestMatchersRelations) {
+  Mock mock;
+
+  ON_CALL(mock, VoidFromFloat(Lt(1.0f))).WillByDefault(Return());
+  ON_CALL(mock, VoidFromFloat(Gt(1.0f))).WillByDefault(Return());
+  ON_CALL(mock, VoidFromFloat(Le(1.0f))).WillByDefault(Return());
+  ON_CALL(mock, VoidFromFloat(Ge(1.0f))).WillByDefault(Return());
+  ON_CALL(mock, VoidFromFloat(Ne(1.0f))).WillByDefault(Return());
+}
+
+// Tests the linkage of the NotNull matcher.
+TEST(LinkTest, TestMatcherNotNull) {
+  Mock mock;
+
+  ON_CALL(mock, VoidFromString(NotNull())).WillByDefault(Return());
+}
+
+// Tests the linkage of the IsNull matcher.
+TEST(LinkTest, TestMatcherIsNull) {
+  Mock mock;
+
+  ON_CALL(mock, VoidFromString(IsNull())).WillByDefault(Return());
+}
+
+// Tests the linkage of the Ref matcher.
+TEST(LinkTest, TestMatcherRef) {
+  Mock mock;
+  int a = 0;
+
+  ON_CALL(mock, VoidFromIntRef(Ref(a))).WillByDefault(Return());
+}
+
+// Tests the linkage of the TypedEq matcher.
+TEST(LinkTest, TestMatcherTypedEq) {
+  Mock mock;
+  long a = 0;
+
+  ON_CALL(mock, VoidFromIntRef(TypedEq<int&>(a))).WillByDefault(Return());
+}
+
+// Tests the linkage of the FloatEq, DoubleEq, NanSensitiveFloatEq and
+// NanSensitiveDoubleEq matchers.
+TEST(LinkTest, TestMatchersFloatingPoint) {
+  Mock mock;
+  float a = 0;
+
+  ON_CALL(mock, VoidFromFloat(FloatEq(a))).WillByDefault(Return());
+  ON_CALL(mock, VoidFromDouble(DoubleEq(a))).WillByDefault(Return());
+  ON_CALL(mock, VoidFromFloat(NanSensitiveFloatEq(a))).WillByDefault(Return());
+  ON_CALL(mock, VoidFromDouble(NanSensitiveDoubleEq(a)))
+      .WillByDefault(Return());
+}
+
+// Tests the linkage of the ContainsRegex matcher.
+TEST(LinkTest, TestMatcherContainsRegex) {
+  Mock mock;
+
+  ON_CALL(mock, VoidFromString(ContainsRegex(".*"))).WillByDefault(Return());
+}
+
+// Tests the linkage of the MatchesRegex matcher.
+TEST(LinkTest, TestMatcherMatchesRegex) {
+  Mock mock;
+
+  ON_CALL(mock, VoidFromString(MatchesRegex(".*"))).WillByDefault(Return());
+}
+
+// Tests the linkage of the StartsWith, EndsWith, and HasSubstr matchers.
+TEST(LinkTest, TestMatchersSubstrings) {
+  Mock mock;
+
+  ON_CALL(mock, VoidFromString(StartsWith("a"))).WillByDefault(Return());
+  ON_CALL(mock, VoidFromString(EndsWith("c"))).WillByDefault(Return());
+  ON_CALL(mock, VoidFromString(HasSubstr("b"))).WillByDefault(Return());
+}
+
+// Tests the linkage of the StrEq, StrNe, StrCaseEq, and StrCaseNe matchers.
+TEST(LinkTest, TestMatchersStringEquality) {
+  Mock mock;
+  ON_CALL(mock, VoidFromString(StrEq("a"))).WillByDefault(Return());
+  ON_CALL(mock, VoidFromString(StrNe("a"))).WillByDefault(Return());
+  ON_CALL(mock, VoidFromString(StrCaseEq("a"))).WillByDefault(Return());
+  ON_CALL(mock, VoidFromString(StrCaseNe("a"))).WillByDefault(Return());
+}
+
+// Tests the linkage of the ElementsAre matcher.
+TEST(LinkTest, TestMatcherElementsAre) {
+  Mock mock;
+
+  ON_CALL(mock, VoidFromVector(ElementsAre('a', _))).WillByDefault(Return());
+}
+
+// Tests the linkage of the ElementsAreArray matcher.
+TEST(LinkTest, TestMatcherElementsAreArray) {
+  Mock mock;
+  char arr[] = { 'a', 'b' };
+
+  ON_CALL(mock, VoidFromVector(ElementsAreArray(arr))).WillByDefault(Return());
+}
+
+// Tests the linkage of the ContainerEq matcher.
+TEST(LinkTest, TestMatcherContainerEq) {
+  Mock mock;
+  std::vector<int> v;
+
+  ON_CALL(mock, VoidFromVector(ContainerEq(v))).WillByDefault(Return());
+}
+
+// Tests the linkage of the Field matcher.
+TEST(LinkTest, TestMatcherField) {
+  FieldHelper helper(0);
+
+  Matcher<const FieldHelper&> m = Field(&FieldHelper::field_, Eq(0));
+  EXPECT_TRUE(m.Matches(helper));
+
+  Matcher<const FieldHelper*> m2 = Field(&FieldHelper::field_, Eq(0));
+  EXPECT_TRUE(m2.Matches(&helper));
+}
+
+// Tests the linkage of the Property matcher.
+TEST(LinkTest, TestMatcherProperty) {
+  FieldHelper helper(0);
+
+  Matcher<const FieldHelper&> m = Property(&FieldHelper::field, Eq(0));
+  EXPECT_TRUE(m.Matches(helper));
+
+  Matcher<const FieldHelper*> m2 = Property(&FieldHelper::field, Eq(0));
+  EXPECT_TRUE(m2.Matches(&helper));
+}
+
+// Tests the linkage of the ResultOf matcher.
+TEST(LinkTest, TestMatcherResultOf) {
+  Matcher<char*> m = ResultOf(&InvokeHelper::StaticIntFromString, Eq(1));
+  EXPECT_TRUE(m.Matches(NULL));
+}
+
+// Tests the linkage of the ResultOf matcher.
+TEST(LinkTest, TestMatcherPointee) {
+  int n = 1;
+
+  Matcher<int*> m = Pointee(Eq(1));
+  EXPECT_TRUE(m.Matches(&n));
+}
+
+// Tests the linkage of the Truly matcher.
+TEST(LinkTest, TestMatcherTruly) {
+  Matcher<const char*> m = Truly(&InvokeHelper::StaticBoolFromString);
+  EXPECT_TRUE(m.Matches(NULL));
+}
+
+// Tests the linkage of the AllOf matcher.
+TEST(LinkTest, TestMatcherAllOf) {
+  Matcher<int> m = AllOf(_, Eq(1));
+  EXPECT_TRUE(m.Matches(1));
+}
+
+// Tests the linkage of the AnyOf matcher.
+TEST(LinkTest, TestMatcherAnyOf) {
+  Matcher<int> m = AnyOf(_, Eq(1));
+  EXPECT_TRUE(m.Matches(1));
+}
+
+// Tests the linkage of the Not matcher.
+TEST(LinkTest, TestMatcherNot) {
+  Matcher<int> m = Not(_);
+  EXPECT_FALSE(m.Matches(1));
+}
+
+// Tests the linkage of the MatcherCast<T>() function.
+TEST(LinkTest, TestMatcherCast) {
+  Matcher<const char*> m = MatcherCast<const char*>(_);
+  EXPECT_TRUE(m.Matches(NULL));
+}
+
+#endif  // GMOCK_TEST_GMOCK_LINK_TEST_H_
diff --git a/third_party/googletest/googlemock/test/gmock_output_test.py b/third_party/googletest/googlemock/test/gmock_output_test.py
new file mode 100755
index 0000000..eced8a8
--- /dev/null
+++ b/third_party/googletest/googlemock/test/gmock_output_test.py
@@ -0,0 +1,180 @@
+#!/usr/bin/env python
+#
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Tests the text output of Google C++ Mocking Framework.
+
+SYNOPSIS
+       gmock_output_test.py --build_dir=BUILD/DIR --gengolden
+         # where BUILD/DIR contains the built gmock_output_test_ file.
+       gmock_output_test.py --gengolden
+       gmock_output_test.py
+"""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import os
+import re
+import sys
+
+import gmock_test_utils
+
+
+# The flag for generating the golden file
+GENGOLDEN_FLAG = '--gengolden'
+
+PROGRAM_PATH = gmock_test_utils.GetTestExecutablePath('gmock_output_test_')
+COMMAND = [PROGRAM_PATH, '--gtest_stack_trace_depth=0', '--gtest_print_time=0']
+GOLDEN_NAME = 'gmock_output_test_golden.txt'
+GOLDEN_PATH = os.path.join(gmock_test_utils.GetSourceDir(), GOLDEN_NAME)
+
+
+def ToUnixLineEnding(s):
+  """Changes all Windows/Mac line endings in s to UNIX line endings."""
+
+  return s.replace('\r\n', '\n').replace('\r', '\n')
+
+
+def RemoveReportHeaderAndFooter(output):
+  """Removes Google Test result report's header and footer from the output."""
+
+  output = re.sub(r'.*gtest_main.*\n', '', output)
+  output = re.sub(r'\[.*\d+ tests.*\n', '', output)
+  output = re.sub(r'\[.* test environment .*\n', '', output)
+  output = re.sub(r'\[=+\] \d+ tests .* ran.*', '', output)
+  output = re.sub(r'.* FAILED TESTS\n', '', output)
+  return output
+
+
+def RemoveLocations(output):
+  """Removes all file location info from a Google Test program's output.
+
+  Args:
+       output:  the output of a Google Test program.
+
+  Returns:
+       output with all file location info (in the form of
+       'DIRECTORY/FILE_NAME:LINE_NUMBER: 'or
+       'DIRECTORY\\FILE_NAME(LINE_NUMBER): ') replaced by
+       'FILE:#: '.
+  """
+
+  return re.sub(r'.*[/\\](.+)(\:\d+|\(\d+\))\:', 'FILE:#:', output)
+
+
+def NormalizeErrorMarker(output):
+  """Normalizes the error marker, which is different on Windows vs on Linux."""
+
+  return re.sub(r' error: ', ' Failure\n', output)
+
+
+def RemoveMemoryAddresses(output):
+  """Removes memory addresses from the test output."""
+
+  return re.sub(r'@\w+', '@0x#', output)
+
+
+def RemoveTestNamesOfLeakedMocks(output):
+  """Removes the test names of leaked mock objects from the test output."""
+
+  return re.sub(r'\(used in test .+\) ', '', output)
+
+
+def GetLeakyTests(output):
+  """Returns a list of test names that leak mock objects."""
+
+  # findall() returns a list of all matches of the regex in output.
+  # For example, if '(used in test FooTest.Bar)' is in output, the
+  # list will contain 'FooTest.Bar'.
+  return re.findall(r'\(used in test (.+)\)', output)
+
+
+def GetNormalizedOutputAndLeakyTests(output):
+  """Normalizes the output of gmock_output_test_.
+
+  Args:
+    output: The test output.
+
+  Returns:
+    A tuple (the normalized test output, the list of test names that have
+    leaked mocks).
+  """
+
+  output = ToUnixLineEnding(output)
+  output = RemoveReportHeaderAndFooter(output)
+  output = NormalizeErrorMarker(output)
+  output = RemoveLocations(output)
+  output = RemoveMemoryAddresses(output)
+  return (RemoveTestNamesOfLeakedMocks(output), GetLeakyTests(output))
+
+
+def GetShellCommandOutput(cmd):
+  """Runs a command in a sub-process, and returns its STDOUT in a string."""
+
+  return gmock_test_utils.Subprocess(cmd, capture_stderr=False).output
+
+
+def GetNormalizedCommandOutputAndLeakyTests(cmd):
+  """Runs a command and returns its normalized output and a list of leaky tests.
+
+  Args:
+    cmd:  the shell command.
+  """
+
+  # Disables exception pop-ups on Windows.
+  os.environ['GTEST_CATCH_EXCEPTIONS'] = '1'
+  return GetNormalizedOutputAndLeakyTests(GetShellCommandOutput(cmd))
+
+
+class GMockOutputTest(gmock_test_utils.TestCase):
+  def testOutput(self):
+    (output, leaky_tests) = GetNormalizedCommandOutputAndLeakyTests(COMMAND)
+    golden_file = open(GOLDEN_PATH, 'rb')
+    golden = golden_file.read()
+    golden_file.close()
+
+    # The normalized output should match the golden file.
+    self.assertEquals(golden, output)
+
+    # The raw output should contain 2 leaked mock object errors for
+    # test GMockOutputTest.CatchesLeakedMocks.
+    self.assertEquals(['GMockOutputTest.CatchesLeakedMocks',
+                       'GMockOutputTest.CatchesLeakedMocks'],
+                      leaky_tests)
+
+
+if __name__ == '__main__':
+  if sys.argv[1:] == [GENGOLDEN_FLAG]:
+    (output, _) = GetNormalizedCommandOutputAndLeakyTests(COMMAND)
+    golden_file = open(GOLDEN_PATH, 'wb')
+    golden_file.write(output)
+    golden_file.close()
+  else:
+    gmock_test_utils.Main()
diff --git a/third_party/googletest/googlemock/test/gmock_output_test_.cc b/third_party/googletest/googlemock/test/gmock_output_test_.cc
new file mode 100644
index 0000000..44cba34
--- /dev/null
+++ b/third_party/googletest/googlemock/test/gmock_output_test_.cc
@@ -0,0 +1,291 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Tests Google Mock's output in various scenarios.  This ensures that
+// Google Mock's messages are readable and useful.
+
+#include "gmock/gmock.h"
+
+#include <stdio.h>
+#include <string>
+
+#include "gtest/gtest.h"
+
+using testing::_;
+using testing::AnyNumber;
+using testing::Ge;
+using testing::InSequence;
+using testing::NaggyMock;
+using testing::Ref;
+using testing::Return;
+using testing::Sequence;
+
+class MockFoo {
+ public:
+  MockFoo() {}
+
+  MOCK_METHOD3(Bar, char(const std::string& s, int i, double x));
+  MOCK_METHOD2(Bar2, bool(int x, int y));
+  MOCK_METHOD2(Bar3, void(int x, int y));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFoo);
+};
+
+class GMockOutputTest : public testing::Test {
+ protected:
+  NaggyMock<MockFoo> foo_;
+};
+
+TEST_F(GMockOutputTest, ExpectedCall) {
+  testing::GMOCK_FLAG(verbose) = "info";
+
+  EXPECT_CALL(foo_, Bar2(0, _));
+  foo_.Bar2(0, 0);  // Expected call
+
+  testing::GMOCK_FLAG(verbose) = "warning";
+}
+
+TEST_F(GMockOutputTest, ExpectedCallToVoidFunction) {
+  testing::GMOCK_FLAG(verbose) = "info";
+
+  EXPECT_CALL(foo_, Bar3(0, _));
+  foo_.Bar3(0, 0);  // Expected call
+
+  testing::GMOCK_FLAG(verbose) = "warning";
+}
+
+TEST_F(GMockOutputTest, ExplicitActionsRunOut) {
+  EXPECT_CALL(foo_, Bar2(_, _))
+      .Times(2)
+      .WillOnce(Return(false));
+  foo_.Bar2(2, 2);
+  foo_.Bar2(1, 1);  // Explicit actions in EXPECT_CALL run out.
+}
+
+TEST_F(GMockOutputTest, UnexpectedCall) {
+  EXPECT_CALL(foo_, Bar2(0, _));
+
+  foo_.Bar2(1, 0);  // Unexpected call
+  foo_.Bar2(0, 0);  // Expected call
+}
+
+TEST_F(GMockOutputTest, UnexpectedCallToVoidFunction) {
+  EXPECT_CALL(foo_, Bar3(0, _));
+
+  foo_.Bar3(1, 0);  // Unexpected call
+  foo_.Bar3(0, 0);  // Expected call
+}
+
+TEST_F(GMockOutputTest, ExcessiveCall) {
+  EXPECT_CALL(foo_, Bar2(0, _));
+
+  foo_.Bar2(0, 0);  // Expected call
+  foo_.Bar2(0, 1);  // Excessive call
+}
+
+TEST_F(GMockOutputTest, ExcessiveCallToVoidFunction) {
+  EXPECT_CALL(foo_, Bar3(0, _));
+
+  foo_.Bar3(0, 0);  // Expected call
+  foo_.Bar3(0, 1);  // Excessive call
+}
+
+TEST_F(GMockOutputTest, UninterestingCall) {
+  foo_.Bar2(0, 1);  // Uninteresting call
+}
+
+TEST_F(GMockOutputTest, UninterestingCallToVoidFunction) {
+  foo_.Bar3(0, 1);  // Uninteresting call
+}
+
+TEST_F(GMockOutputTest, RetiredExpectation) {
+  EXPECT_CALL(foo_, Bar2(_, _))
+      .RetiresOnSaturation();
+  EXPECT_CALL(foo_, Bar2(0, 0));
+
+  foo_.Bar2(1, 1);
+  foo_.Bar2(1, 1);  // Matches a retired expectation
+  foo_.Bar2(0, 0);
+}
+
+TEST_F(GMockOutputTest, UnsatisfiedPrerequisite) {
+  {
+    InSequence s;
+    EXPECT_CALL(foo_, Bar(_, 0, _));
+    EXPECT_CALL(foo_, Bar2(0, 0));
+    EXPECT_CALL(foo_, Bar2(1, _));
+  }
+
+  foo_.Bar2(1, 0);  // Has one immediate unsatisfied pre-requisite
+  foo_.Bar("Hi", 0, 0);
+  foo_.Bar2(0, 0);
+  foo_.Bar2(1, 0);
+}
+
+TEST_F(GMockOutputTest, UnsatisfiedPrerequisites) {
+  Sequence s1, s2;
+
+  EXPECT_CALL(foo_, Bar(_, 0, _))
+      .InSequence(s1);
+  EXPECT_CALL(foo_, Bar2(0, 0))
+      .InSequence(s2);
+  EXPECT_CALL(foo_, Bar2(1, _))
+      .InSequence(s1, s2);
+
+  foo_.Bar2(1, 0);  // Has two immediate unsatisfied pre-requisites
+  foo_.Bar("Hi", 0, 0);
+  foo_.Bar2(0, 0);
+  foo_.Bar2(1, 0);
+}
+
+TEST_F(GMockOutputTest, UnsatisfiedWith) {
+  EXPECT_CALL(foo_, Bar2(_, _)).With(Ge());
+}
+
+TEST_F(GMockOutputTest, UnsatisfiedExpectation) {
+  EXPECT_CALL(foo_, Bar(_, _, _));
+  EXPECT_CALL(foo_, Bar2(0, _))
+      .Times(2);
+
+  foo_.Bar2(0, 1);
+}
+
+TEST_F(GMockOutputTest, MismatchArguments) {
+  const std::string s = "Hi";
+  EXPECT_CALL(foo_, Bar(Ref(s), _, Ge(0)));
+
+  foo_.Bar("Ho", 0, -0.1);  // Mismatch arguments
+  foo_.Bar(s, 0, 0);
+}
+
+TEST_F(GMockOutputTest, MismatchWith) {
+  EXPECT_CALL(foo_, Bar2(Ge(2), Ge(1)))
+      .With(Ge());
+
+  foo_.Bar2(2, 3);  // Mismatch With()
+  foo_.Bar2(2, 1);
+}
+
+TEST_F(GMockOutputTest, MismatchArgumentsAndWith) {
+  EXPECT_CALL(foo_, Bar2(Ge(2), Ge(1)))
+      .With(Ge());
+
+  foo_.Bar2(1, 3);  // Mismatch arguments and mismatch With()
+  foo_.Bar2(2, 1);
+}
+
+TEST_F(GMockOutputTest, UnexpectedCallWithDefaultAction) {
+  ON_CALL(foo_, Bar2(_, _))
+      .WillByDefault(Return(true));   // Default action #1
+  ON_CALL(foo_, Bar2(1, _))
+      .WillByDefault(Return(false));  // Default action #2
+
+  EXPECT_CALL(foo_, Bar2(2, 2));
+  foo_.Bar2(1, 0);  // Unexpected call, takes default action #2.
+  foo_.Bar2(0, 0);  // Unexpected call, takes default action #1.
+  foo_.Bar2(2, 2);  // Expected call.
+}
+
+TEST_F(GMockOutputTest, ExcessiveCallWithDefaultAction) {
+  ON_CALL(foo_, Bar2(_, _))
+      .WillByDefault(Return(true));   // Default action #1
+  ON_CALL(foo_, Bar2(1, _))
+      .WillByDefault(Return(false));  // Default action #2
+
+  EXPECT_CALL(foo_, Bar2(2, 2));
+  EXPECT_CALL(foo_, Bar2(1, 1));
+
+  foo_.Bar2(2, 2);  // Expected call.
+  foo_.Bar2(2, 2);  // Excessive call, takes default action #1.
+  foo_.Bar2(1, 1);  // Expected call.
+  foo_.Bar2(1, 1);  // Excessive call, takes default action #2.
+}
+
+TEST_F(GMockOutputTest, UninterestingCallWithDefaultAction) {
+  ON_CALL(foo_, Bar2(_, _))
+      .WillByDefault(Return(true));   // Default action #1
+  ON_CALL(foo_, Bar2(1, _))
+      .WillByDefault(Return(false));  // Default action #2
+
+  foo_.Bar2(2, 2);  // Uninteresting call, takes default action #1.
+  foo_.Bar2(1, 1);  // Uninteresting call, takes default action #2.
+}
+
+TEST_F(GMockOutputTest, ExplicitActionsRunOutWithDefaultAction) {
+  ON_CALL(foo_, Bar2(_, _))
+      .WillByDefault(Return(true));   // Default action #1
+
+  EXPECT_CALL(foo_, Bar2(_, _))
+      .Times(2)
+      .WillOnce(Return(false));
+  foo_.Bar2(2, 2);
+  foo_.Bar2(1, 1);  // Explicit actions in EXPECT_CALL run out.
+}
+
+TEST_F(GMockOutputTest, CatchesLeakedMocks) {
+  MockFoo* foo1 = new MockFoo;
+  MockFoo* foo2 = new MockFoo;
+
+  // Invokes ON_CALL on foo1.
+  ON_CALL(*foo1, Bar(_, _, _)).WillByDefault(Return('a'));
+
+  // Invokes EXPECT_CALL on foo2.
+  EXPECT_CALL(*foo2, Bar2(_, _));
+  EXPECT_CALL(*foo2, Bar2(1, _));
+  EXPECT_CALL(*foo2, Bar3(_, _)).Times(AnyNumber());
+  foo2->Bar2(2, 1);
+  foo2->Bar2(1, 1);
+
+  // Both foo1 and foo2 are deliberately leaked.
+}
+
+void TestCatchesLeakedMocksInAdHocTests() {
+  MockFoo* foo = new MockFoo;
+
+  // Invokes EXPECT_CALL on foo.
+  EXPECT_CALL(*foo, Bar2(_, _));
+  foo->Bar2(2, 1);
+
+  // foo is deliberately leaked.
+}
+
+int main(int argc, char **argv) {
+  testing::InitGoogleMock(&argc, argv);
+
+  // Ensures that the tests pass no matter what value of
+  // --gmock_catch_leaked_mocks and --gmock_verbose the user specifies.
+  testing::GMOCK_FLAG(catch_leaked_mocks) = true;
+  testing::GMOCK_FLAG(verbose) = "warning";
+
+  TestCatchesLeakedMocksInAdHocTests();
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/googletest/googlemock/test/gmock_output_test_golden.txt b/third_party/googletest/googlemock/test/gmock_output_test_golden.txt
new file mode 100644
index 0000000..650a8f0
--- /dev/null
+++ b/third_party/googletest/googlemock/test/gmock_output_test_golden.txt
@@ -0,0 +1,310 @@
+[ RUN      ] GMockOutputTest.ExpectedCall
+
+FILE:#: EXPECT_CALL(foo_, Bar2(0, _)) invoked
+Stack trace:
+
+FILE:#: Mock function call matches EXPECT_CALL(foo_, Bar2(0, _))...
+    Function call: Bar2(0, 0)
+          Returns: false
+Stack trace:
+[       OK ] GMockOutputTest.ExpectedCall
+[ RUN      ] GMockOutputTest.ExpectedCallToVoidFunction
+
+FILE:#: EXPECT_CALL(foo_, Bar3(0, _)) invoked
+Stack trace:
+
+FILE:#: Mock function call matches EXPECT_CALL(foo_, Bar3(0, _))...
+    Function call: Bar3(0, 0)
+Stack trace:
+[       OK ] GMockOutputTest.ExpectedCallToVoidFunction
+[ RUN      ] GMockOutputTest.ExplicitActionsRunOut
+
+GMOCK WARNING:
+FILE:#: Too few actions specified in EXPECT_CALL(foo_, Bar2(_, _))...
+Expected to be called twice, but has only 1 WillOnce().
+GMOCK WARNING:
+FILE:#: Actions ran out in EXPECT_CALL(foo_, Bar2(_, _))...
+Called 2 times, but only 1 WillOnce() is specified - returning default value.
+Stack trace:
+[       OK ] GMockOutputTest.ExplicitActionsRunOut
+[ RUN      ] GMockOutputTest.UnexpectedCall
+unknown file: Failure
+
+Unexpected mock function call - returning default value.
+    Function call: Bar2(1, 0)
+          Returns: false
+Google Mock tried the following 1 expectation, but it didn't match:
+
+FILE:#: EXPECT_CALL(foo_, Bar2(0, _))...
+  Expected arg #0: is equal to 0
+           Actual: 1
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+[  FAILED  ] GMockOutputTest.UnexpectedCall
+[ RUN      ] GMockOutputTest.UnexpectedCallToVoidFunction
+unknown file: Failure
+
+Unexpected mock function call - returning directly.
+    Function call: Bar3(1, 0)
+Google Mock tried the following 1 expectation, but it didn't match:
+
+FILE:#: EXPECT_CALL(foo_, Bar3(0, _))...
+  Expected arg #0: is equal to 0
+           Actual: 1
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+[  FAILED  ] GMockOutputTest.UnexpectedCallToVoidFunction
+[ RUN      ] GMockOutputTest.ExcessiveCall
+FILE:#: Failure
+Mock function called more times than expected - returning default value.
+    Function call: Bar2(0, 1)
+          Returns: false
+         Expected: to be called once
+           Actual: called twice - over-saturated and active
+[  FAILED  ] GMockOutputTest.ExcessiveCall
+[ RUN      ] GMockOutputTest.ExcessiveCallToVoidFunction
+FILE:#: Failure
+Mock function called more times than expected - returning directly.
+    Function call: Bar3(0, 1)
+         Expected: to be called once
+           Actual: called twice - over-saturated and active
+[  FAILED  ] GMockOutputTest.ExcessiveCallToVoidFunction
+[ RUN      ] GMockOutputTest.UninterestingCall
+
+GMOCK WARNING:
+Uninteresting mock function call - returning default value.
+    Function call: Bar2(0, 1)
+          Returns: false
+NOTE: You can safely ignore the above warning unless this call should not happen.  Do not suppress it by blindly adding an EXPECT_CALL() if you don't mean to enforce the call.  See http://code.google.com/p/googlemock/wiki/CookBook#Knowing_When_to_Expect for details.
+[       OK ] GMockOutputTest.UninterestingCall
+[ RUN      ] GMockOutputTest.UninterestingCallToVoidFunction
+
+GMOCK WARNING:
+Uninteresting mock function call - returning directly.
+    Function call: Bar3(0, 1)
+NOTE: You can safely ignore the above warning unless this call should not happen.  Do not suppress it by blindly adding an EXPECT_CALL() if you don't mean to enforce the call.  See http://code.google.com/p/googlemock/wiki/CookBook#Knowing_When_to_Expect for details.
+[       OK ] GMockOutputTest.UninterestingCallToVoidFunction
+[ RUN      ] GMockOutputTest.RetiredExpectation
+unknown file: Failure
+
+Unexpected mock function call - returning default value.
+    Function call: Bar2(1, 1)
+          Returns: false
+Google Mock tried the following 2 expectations, but none matched:
+
+FILE:#: tried expectation #0: EXPECT_CALL(foo_, Bar2(_, _))...
+         Expected: the expectation is active
+           Actual: it is retired
+         Expected: to be called once
+           Actual: called once - saturated and retired
+FILE:#: tried expectation #1: EXPECT_CALL(foo_, Bar2(0, 0))...
+  Expected arg #0: is equal to 0
+           Actual: 1
+  Expected arg #1: is equal to 0
+           Actual: 1
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+[  FAILED  ] GMockOutputTest.RetiredExpectation
+[ RUN      ] GMockOutputTest.UnsatisfiedPrerequisite
+unknown file: Failure
+
+Unexpected mock function call - returning default value.
+    Function call: Bar2(1, 0)
+          Returns: false
+Google Mock tried the following 2 expectations, but none matched:
+
+FILE:#: tried expectation #0: EXPECT_CALL(foo_, Bar2(0, 0))...
+  Expected arg #0: is equal to 0
+           Actual: 1
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+FILE:#: tried expectation #1: EXPECT_CALL(foo_, Bar2(1, _))...
+         Expected: all pre-requisites are satisfied
+           Actual: the following immediate pre-requisites are not satisfied:
+FILE:#: pre-requisite #0
+                   (end of pre-requisites)
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+[  FAILED  ] GMockOutputTest.UnsatisfiedPrerequisite
+[ RUN      ] GMockOutputTest.UnsatisfiedPrerequisites
+unknown file: Failure
+
+Unexpected mock function call - returning default value.
+    Function call: Bar2(1, 0)
+          Returns: false
+Google Mock tried the following 2 expectations, but none matched:
+
+FILE:#: tried expectation #0: EXPECT_CALL(foo_, Bar2(0, 0))...
+  Expected arg #0: is equal to 0
+           Actual: 1
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+FILE:#: tried expectation #1: EXPECT_CALL(foo_, Bar2(1, _))...
+         Expected: all pre-requisites are satisfied
+           Actual: the following immediate pre-requisites are not satisfied:
+FILE:#: pre-requisite #0
+FILE:#: pre-requisite #1
+                   (end of pre-requisites)
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+[  FAILED  ] GMockOutputTest.UnsatisfiedPrerequisites
+[ RUN      ] GMockOutputTest.UnsatisfiedWith
+FILE:#: Failure
+Actual function call count doesn't match EXPECT_CALL(foo_, Bar2(_, _))...
+    Expected args: are a pair where the first >= the second
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+[  FAILED  ] GMockOutputTest.UnsatisfiedWith
+[ RUN      ] GMockOutputTest.UnsatisfiedExpectation
+FILE:#: Failure
+Actual function call count doesn't match EXPECT_CALL(foo_, Bar2(0, _))...
+         Expected: to be called twice
+           Actual: called once - unsatisfied and active
+FILE:#: Failure
+Actual function call count doesn't match EXPECT_CALL(foo_, Bar(_, _, _))...
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+[  FAILED  ] GMockOutputTest.UnsatisfiedExpectation
+[ RUN      ] GMockOutputTest.MismatchArguments
+unknown file: Failure
+
+Unexpected mock function call - returning default value.
+    Function call: Bar(@0x# "Ho", 0, -0.1)
+          Returns: '\0'
+Google Mock tried the following 1 expectation, but it didn't match:
+
+FILE:#: EXPECT_CALL(foo_, Bar(Ref(s), _, Ge(0)))...
+  Expected arg #0: references the variable @0x# "Hi"
+           Actual: "Ho", which is located @0x#
+  Expected arg #2: is >= 0
+           Actual: -0.1
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+[  FAILED  ] GMockOutputTest.MismatchArguments
+[ RUN      ] GMockOutputTest.MismatchWith
+unknown file: Failure
+
+Unexpected mock function call - returning default value.
+    Function call: Bar2(2, 3)
+          Returns: false
+Google Mock tried the following 1 expectation, but it didn't match:
+
+FILE:#: EXPECT_CALL(foo_, Bar2(Ge(2), Ge(1)))...
+    Expected args: are a pair where the first >= the second
+           Actual: don't match
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+[  FAILED  ] GMockOutputTest.MismatchWith
+[ RUN      ] GMockOutputTest.MismatchArgumentsAndWith
+unknown file: Failure
+
+Unexpected mock function call - returning default value.
+    Function call: Bar2(1, 3)
+          Returns: false
+Google Mock tried the following 1 expectation, but it didn't match:
+
+FILE:#: EXPECT_CALL(foo_, Bar2(Ge(2), Ge(1)))...
+  Expected arg #0: is >= 2
+           Actual: 1
+    Expected args: are a pair where the first >= the second
+           Actual: don't match
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+[  FAILED  ] GMockOutputTest.MismatchArgumentsAndWith
+[ RUN      ] GMockOutputTest.UnexpectedCallWithDefaultAction
+unknown file: Failure
+
+Unexpected mock function call - taking default action specified at:
+FILE:#:
+    Function call: Bar2(1, 0)
+          Returns: false
+Google Mock tried the following 1 expectation, but it didn't match:
+
+FILE:#: EXPECT_CALL(foo_, Bar2(2, 2))...
+  Expected arg #0: is equal to 2
+           Actual: 1
+  Expected arg #1: is equal to 2
+           Actual: 0
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+unknown file: Failure
+
+Unexpected mock function call - taking default action specified at:
+FILE:#:
+    Function call: Bar2(0, 0)
+          Returns: true
+Google Mock tried the following 1 expectation, but it didn't match:
+
+FILE:#: EXPECT_CALL(foo_, Bar2(2, 2))...
+  Expected arg #0: is equal to 2
+           Actual: 0
+  Expected arg #1: is equal to 2
+           Actual: 0
+         Expected: to be called once
+           Actual: never called - unsatisfied and active
+[  FAILED  ] GMockOutputTest.UnexpectedCallWithDefaultAction
+[ RUN      ] GMockOutputTest.ExcessiveCallWithDefaultAction
+FILE:#: Failure
+Mock function called more times than expected - taking default action specified at:
+FILE:#:
+    Function call: Bar2(2, 2)
+          Returns: true
+         Expected: to be called once
+           Actual: called twice - over-saturated and active
+FILE:#: Failure
+Mock function called more times than expected - taking default action specified at:
+FILE:#:
+    Function call: Bar2(1, 1)
+          Returns: false
+         Expected: to be called once
+           Actual: called twice - over-saturated and active
+[  FAILED  ] GMockOutputTest.ExcessiveCallWithDefaultAction
+[ RUN      ] GMockOutputTest.UninterestingCallWithDefaultAction
+
+GMOCK WARNING:
+Uninteresting mock function call - taking default action specified at:
+FILE:#:
+    Function call: Bar2(2, 2)
+          Returns: true
+NOTE: You can safely ignore the above warning unless this call should not happen.  Do not suppress it by blindly adding an EXPECT_CALL() if you don't mean to enforce the call.  See http://code.google.com/p/googlemock/wiki/CookBook#Knowing_When_to_Expect for details.
+
+GMOCK WARNING:
+Uninteresting mock function call - taking default action specified at:
+FILE:#:
+    Function call: Bar2(1, 1)
+          Returns: false
+NOTE: You can safely ignore the above warning unless this call should not happen.  Do not suppress it by blindly adding an EXPECT_CALL() if you don't mean to enforce the call.  See http://code.google.com/p/googlemock/wiki/CookBook#Knowing_When_to_Expect for details.
+[       OK ] GMockOutputTest.UninterestingCallWithDefaultAction
+[ RUN      ] GMockOutputTest.ExplicitActionsRunOutWithDefaultAction
+
+GMOCK WARNING:
+FILE:#: Too few actions specified in EXPECT_CALL(foo_, Bar2(_, _))...
+Expected to be called twice, but has only 1 WillOnce().
+GMOCK WARNING:
+FILE:#: Actions ran out in EXPECT_CALL(foo_, Bar2(_, _))...
+Called 2 times, but only 1 WillOnce() is specified - taking default action specified at:
+FILE:#:
+Stack trace:
+[       OK ] GMockOutputTest.ExplicitActionsRunOutWithDefaultAction
+[ RUN      ] GMockOutputTest.CatchesLeakedMocks
+[       OK ] GMockOutputTest.CatchesLeakedMocks
+[  FAILED  ] GMockOutputTest.UnexpectedCall
+[  FAILED  ] GMockOutputTest.UnexpectedCallToVoidFunction
+[  FAILED  ] GMockOutputTest.ExcessiveCall
+[  FAILED  ] GMockOutputTest.ExcessiveCallToVoidFunction
+[  FAILED  ] GMockOutputTest.RetiredExpectation
+[  FAILED  ] GMockOutputTest.UnsatisfiedPrerequisite
+[  FAILED  ] GMockOutputTest.UnsatisfiedPrerequisites
+[  FAILED  ] GMockOutputTest.UnsatisfiedWith
+[  FAILED  ] GMockOutputTest.UnsatisfiedExpectation
+[  FAILED  ] GMockOutputTest.MismatchArguments
+[  FAILED  ] GMockOutputTest.MismatchWith
+[  FAILED  ] GMockOutputTest.MismatchArgumentsAndWith
+[  FAILED  ] GMockOutputTest.UnexpectedCallWithDefaultAction
+[  FAILED  ] GMockOutputTest.ExcessiveCallWithDefaultAction
+
+
+FILE:#: ERROR: this mock object should be deleted but never is. Its address is @0x#.
+FILE:#: ERROR: this mock object should be deleted but never is. Its address is @0x#.
+FILE:#: ERROR: this mock object should be deleted but never is. Its address is @0x#.
+ERROR: 3 leaked mock objects found at program exit.
diff --git a/third_party/googletest/googlemock/test/gmock_stress_test.cc b/third_party/googletest/googlemock/test/gmock_stress_test.cc
new file mode 100644
index 0000000..0e97aee
--- /dev/null
+++ b/third_party/googletest/googlemock/test/gmock_stress_test.cc
@@ -0,0 +1,322 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Tests that Google Mock constructs can be used in a large number of
+// threads concurrently.
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+namespace {
+
+// From <gtest/internal/gtest-port.h>.
+using ::testing::internal::ThreadWithParam;
+
+// The maximum number of test threads (not including helper threads)
+// to create.
+const int kMaxTestThreads = 50;
+
+// How many times to repeat a task in a test thread.
+const int kRepeat = 50;
+
+class MockFoo {
+ public:
+  MOCK_METHOD1(Bar, int(int n));  // NOLINT
+  MOCK_METHOD2(Baz, char(const char* s1, const internal::string& s2));  // NOLINT
+};
+
+// Helper for waiting for the given thread to finish and then deleting it.
+template <typename T>
+void JoinAndDelete(ThreadWithParam<T>* t) {
+  t->Join();
+  delete t;
+}
+
+using internal::linked_ptr;
+
+// Helper classes for testing using linked_ptr concurrently.
+
+class Base {
+ public:
+  explicit Base(int a_x) : x_(a_x) {}
+  virtual ~Base() {}
+  int x() const { return x_; }
+ private:
+  int x_;
+};
+
+class Derived1 : public Base {
+ public:
+  Derived1(int a_x, int a_y) : Base(a_x), y_(a_y) {}
+  int y() const { return y_; }
+ private:
+  int y_;
+};
+
+class Derived2 : public Base {
+ public:
+  Derived2(int a_x, int a_z) : Base(a_x), z_(a_z) {}
+  int z() const { return z_; }
+ private:
+  int z_;
+};
+
+linked_ptr<Derived1> pointer1(new Derived1(1, 2));
+linked_ptr<Derived2> pointer2(new Derived2(3, 4));
+
+struct Dummy {};
+
+// Tests that we can copy from a linked_ptr and read it concurrently.
+void TestConcurrentCopyAndReadLinkedPtr(Dummy /* dummy */) {
+  // Reads pointer1 and pointer2 while they are being copied from in
+  // another thread.
+  EXPECT_EQ(1, pointer1->x());
+  EXPECT_EQ(2, pointer1->y());
+  EXPECT_EQ(3, pointer2->x());
+  EXPECT_EQ(4, pointer2->z());
+
+  // Copies from pointer1.
+  linked_ptr<Derived1> p1(pointer1);
+  EXPECT_EQ(1, p1->x());
+  EXPECT_EQ(2, p1->y());
+
+  // Assigns from pointer2 where the LHS was empty.
+  linked_ptr<Base> p2;
+  p2 = pointer1;
+  EXPECT_EQ(1, p2->x());
+
+  // Assigns from pointer2 where the LHS was not empty.
+  p2 = pointer2;
+  EXPECT_EQ(3, p2->x());
+}
+
+const linked_ptr<Derived1> p0(new Derived1(1, 2));
+
+// Tests that we can concurrently modify two linked_ptrs that point to
+// the same object.
+void TestConcurrentWriteToEqualLinkedPtr(Dummy /* dummy */) {
+  // p1 and p2 point to the same, shared thing.  One thread resets p1.
+  // Another thread assigns to p2.  This will cause the same
+  // underlying "ring" to be updated concurrently.
+  linked_ptr<Derived1> p1(p0);
+  linked_ptr<Derived1> p2(p0);
+
+  EXPECT_EQ(1, p1->x());
+  EXPECT_EQ(2, p1->y());
+
+  EXPECT_EQ(1, p2->x());
+  EXPECT_EQ(2, p2->y());
+
+  p1.reset();
+  p2 = p0;
+
+  EXPECT_EQ(1, p2->x());
+  EXPECT_EQ(2, p2->y());
+}
+
+// Tests that different mock objects can be used in their respective
+// threads.  This should generate no Google Test failure.
+void TestConcurrentMockObjects(Dummy /* dummy */) {
+  // Creates a mock and does some typical operations on it.
+  MockFoo foo;
+  ON_CALL(foo, Bar(_))
+      .WillByDefault(Return(1));
+  ON_CALL(foo, Baz(_, _))
+      .WillByDefault(Return('b'));
+  ON_CALL(foo, Baz(_, "you"))
+      .WillByDefault(Return('a'));
+
+  EXPECT_CALL(foo, Bar(0))
+      .Times(AtMost(3));
+  EXPECT_CALL(foo, Baz(_, _));
+  EXPECT_CALL(foo, Baz("hi", "you"))
+      .WillOnce(Return('z'))
+      .WillRepeatedly(DoDefault());
+
+  EXPECT_EQ(1, foo.Bar(0));
+  EXPECT_EQ(1, foo.Bar(0));
+  EXPECT_EQ('z', foo.Baz("hi", "you"));
+  EXPECT_EQ('a', foo.Baz("hi", "you"));
+  EXPECT_EQ('b', foo.Baz("hi", "me"));
+}
+
+// Tests invoking methods of the same mock object in multiple threads.
+
+struct Helper1Param {
+  MockFoo* mock_foo;
+  int* count;
+};
+
+void Helper1(Helper1Param param) {
+  for (int i = 0; i < kRepeat; i++) {
+    const char ch = param.mock_foo->Baz("a", "b");
+    if (ch == 'a') {
+      // It was an expected call.
+      (*param.count)++;
+    } else {
+      // It was an excessive call.
+      EXPECT_EQ('\0', ch);
+    }
+
+    // An unexpected call.
+    EXPECT_EQ('\0', param.mock_foo->Baz("x", "y")) << "Expected failure.";
+
+    // An uninteresting call.
+    EXPECT_EQ(1, param.mock_foo->Bar(5));
+  }
+}
+
+// This should generate 3*kRepeat + 1 failures in total.
+void TestConcurrentCallsOnSameObject(Dummy /* dummy */) {
+  MockFoo foo;
+
+  ON_CALL(foo, Bar(_))
+      .WillByDefault(Return(1));
+  EXPECT_CALL(foo, Baz(_, "b"))
+      .Times(kRepeat)
+      .WillRepeatedly(Return('a'));
+  EXPECT_CALL(foo, Baz(_, "c"));  // Expected to be unsatisfied.
+
+  // This chunk of code should generate kRepeat failures about
+  // excessive calls, and 2*kRepeat failures about unexpected calls.
+  int count1 = 0;
+  const Helper1Param param = { &foo, &count1 };
+  ThreadWithParam<Helper1Param>* const t =
+      new ThreadWithParam<Helper1Param>(Helper1, param, NULL);
+
+  int count2 = 0;
+  const Helper1Param param2 = { &foo, &count2 };
+  Helper1(param2);
+  JoinAndDelete(t);
+
+  EXPECT_EQ(kRepeat, count1 + count2);
+
+  // foo's destructor should generate one failure about unsatisfied
+  // expectation.
+}
+
+// Tests using the same mock object in multiple threads when the
+// expectations are partially ordered.
+
+void Helper2(MockFoo* foo) {
+  for (int i = 0; i < kRepeat; i++) {
+    foo->Bar(2);
+    foo->Bar(3);
+  }
+}
+
+// This should generate no Google Test failures.
+void TestPartiallyOrderedExpectationsWithThreads(Dummy /* dummy */) {
+  MockFoo foo;
+  Sequence s1, s2;
+
+  {
+    InSequence dummy;
+    EXPECT_CALL(foo, Bar(0));
+    EXPECT_CALL(foo, Bar(1))
+        .InSequence(s1, s2);
+  }
+
+  EXPECT_CALL(foo, Bar(2))
+      .Times(2*kRepeat)
+      .InSequence(s1)
+      .RetiresOnSaturation();
+  EXPECT_CALL(foo, Bar(3))
+      .Times(2*kRepeat)
+      .InSequence(s2);
+
+  {
+    InSequence dummy;
+    EXPECT_CALL(foo, Bar(2))
+        .InSequence(s1, s2);
+    EXPECT_CALL(foo, Bar(4));
+  }
+
+  foo.Bar(0);
+  foo.Bar(1);
+
+  ThreadWithParam<MockFoo*>* const t =
+      new ThreadWithParam<MockFoo*>(Helper2, &foo, NULL);
+  Helper2(&foo);
+  JoinAndDelete(t);
+
+  foo.Bar(2);
+  foo.Bar(4);
+}
+
+// Tests using Google Mock constructs in many threads concurrently.
+TEST(StressTest, CanUseGMockWithThreads) {
+  void (*test_routines[])(Dummy dummy) = {
+    &TestConcurrentCopyAndReadLinkedPtr,
+    &TestConcurrentWriteToEqualLinkedPtr,
+    &TestConcurrentMockObjects,
+    &TestConcurrentCallsOnSameObject,
+    &TestPartiallyOrderedExpectationsWithThreads,
+  };
+
+  const int kRoutines = sizeof(test_routines)/sizeof(test_routines[0]);
+  const int kCopiesOfEachRoutine = kMaxTestThreads / kRoutines;
+  const int kTestThreads = kCopiesOfEachRoutine * kRoutines;
+  ThreadWithParam<Dummy>* threads[kTestThreads] = {};
+  for (int i = 0; i < kTestThreads; i++) {
+    // Creates a thread to run the test function.
+    threads[i] =
+        new ThreadWithParam<Dummy>(test_routines[i % kRoutines], Dummy(), NULL);
+    GTEST_LOG_(INFO) << "Thread #" << i << " running . . .";
+  }
+
+  // At this point, we have many threads running.
+  for (int i = 0; i < kTestThreads; i++) {
+    JoinAndDelete(threads[i]);
+  }
+
+  // Ensures that the correct number of failures have been reported.
+  const TestInfo* const info = UnitTest::GetInstance()->current_test_info();
+  const TestResult& result = *info->result();
+  const int kExpectedFailures = (3*kRepeat + 1)*kCopiesOfEachRoutine;
+  GTEST_CHECK_(kExpectedFailures == result.total_part_count())
+      << "Expected " << kExpectedFailures << " failures, but got "
+      << result.total_part_count();
+}
+
+}  // namespace
+}  // namespace testing
+
+int main(int argc, char **argv) {
+  testing::InitGoogleMock(&argc, argv);
+
+  const int exit_code = RUN_ALL_TESTS();  // Expected to fail.
+  GTEST_CHECK_(exit_code != 0) << "RUN_ALL_TESTS() did not fail as expected";
+
+  printf("\nPASS\n");
+  return 0;
+}
diff --git a/third_party/googletest/googlemock/test/gmock_test.cc b/third_party/googletest/googlemock/test/gmock_test.cc
new file mode 100644
index 0000000..ae5e22c
--- /dev/null
+++ b/third_party/googletest/googlemock/test/gmock_test.cc
@@ -0,0 +1,221 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file tests code in gmock.cc.
+
+#include "gmock/gmock.h"
+
+#include <string>
+#include "gtest/gtest.h"
+#include "gtest/internal/custom/gtest.h"
+
+#if !defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+
+using testing::GMOCK_FLAG(verbose);
+using testing::InitGoogleMock;
+
+// Verifies that calling InitGoogleMock() on argv results in new_argv,
+// and the gmock_verbose flag's value is set to expected_gmock_verbose.
+template <typename Char, int M, int N>
+void TestInitGoogleMock(const Char* (&argv)[M], const Char* (&new_argv)[N],
+                        const ::std::string& expected_gmock_verbose) {
+  const ::std::string old_verbose = GMOCK_FLAG(verbose);
+
+  int argc = M;
+  InitGoogleMock(&argc, const_cast<Char**>(argv));
+  ASSERT_EQ(N, argc) << "The new argv has wrong number of elements.";
+
+  for (int i = 0; i < N; i++) {
+    EXPECT_STREQ(new_argv[i], argv[i]);
+  }
+
+  EXPECT_EQ(expected_gmock_verbose, GMOCK_FLAG(verbose).c_str());
+  GMOCK_FLAG(verbose) = old_verbose;  // Restores the gmock_verbose flag.
+}
+
+TEST(InitGoogleMockTest, ParsesInvalidCommandLine) {
+  const char* argv[] = {
+    NULL
+  };
+
+  const char* new_argv[] = {
+    NULL
+  };
+
+  TestInitGoogleMock(argv, new_argv, GMOCK_FLAG(verbose));
+}
+
+TEST(InitGoogleMockTest, ParsesEmptyCommandLine) {
+  const char* argv[] = {
+    "foo.exe",
+    NULL
+  };
+
+  const char* new_argv[] = {
+    "foo.exe",
+    NULL
+  };
+
+  TestInitGoogleMock(argv, new_argv, GMOCK_FLAG(verbose));
+}
+
+TEST(InitGoogleMockTest, ParsesSingleFlag) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gmock_verbose=info",
+    NULL
+  };
+
+  const char* new_argv[] = {
+    "foo.exe",
+    NULL
+  };
+
+  TestInitGoogleMock(argv, new_argv, "info");
+}
+
+TEST(InitGoogleMockTest, ParsesUnrecognizedFlag) {
+  const char* argv[] = {
+    "foo.exe",
+    "--non_gmock_flag=blah",
+    NULL
+  };
+
+  const char* new_argv[] = {
+    "foo.exe",
+    "--non_gmock_flag=blah",
+    NULL
+  };
+
+  TestInitGoogleMock(argv, new_argv, GMOCK_FLAG(verbose));
+}
+
+TEST(InitGoogleMockTest, ParsesGoogleMockFlagAndUnrecognizedFlag) {
+  const char* argv[] = {
+    "foo.exe",
+    "--non_gmock_flag=blah",
+    "--gmock_verbose=error",
+    NULL
+  };
+
+  const char* new_argv[] = {
+    "foo.exe",
+    "--non_gmock_flag=blah",
+    NULL
+  };
+
+  TestInitGoogleMock(argv, new_argv, "error");
+}
+
+TEST(WideInitGoogleMockTest, ParsesInvalidCommandLine) {
+  const wchar_t* argv[] = {
+    NULL
+  };
+
+  const wchar_t* new_argv[] = {
+    NULL
+  };
+
+  TestInitGoogleMock(argv, new_argv, GMOCK_FLAG(verbose));
+}
+
+TEST(WideInitGoogleMockTest, ParsesEmptyCommandLine) {
+  const wchar_t* argv[] = {
+    L"foo.exe",
+    NULL
+  };
+
+  const wchar_t* new_argv[] = {
+    L"foo.exe",
+    NULL
+  };
+
+  TestInitGoogleMock(argv, new_argv, GMOCK_FLAG(verbose));
+}
+
+TEST(WideInitGoogleMockTest, ParsesSingleFlag) {
+  const wchar_t* argv[] = {
+    L"foo.exe",
+    L"--gmock_verbose=info",
+    NULL
+  };
+
+  const wchar_t* new_argv[] = {
+    L"foo.exe",
+    NULL
+  };
+
+  TestInitGoogleMock(argv, new_argv, "info");
+}
+
+TEST(WideInitGoogleMockTest, ParsesUnrecognizedFlag) {
+  const wchar_t* argv[] = {
+    L"foo.exe",
+    L"--non_gmock_flag=blah",
+    NULL
+  };
+
+  const wchar_t* new_argv[] = {
+    L"foo.exe",
+    L"--non_gmock_flag=blah",
+    NULL
+  };
+
+  TestInitGoogleMock(argv, new_argv, GMOCK_FLAG(verbose));
+}
+
+TEST(WideInitGoogleMockTest, ParsesGoogleMockFlagAndUnrecognizedFlag) {
+  const wchar_t* argv[] = {
+    L"foo.exe",
+    L"--non_gmock_flag=blah",
+    L"--gmock_verbose=error",
+    NULL
+  };
+
+  const wchar_t* new_argv[] = {
+    L"foo.exe",
+    L"--non_gmock_flag=blah",
+    NULL
+  };
+
+  TestInitGoogleMock(argv, new_argv, "error");
+}
+
+#endif  // !defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+
+// Makes sure Google Mock flags can be accessed in code.
+TEST(FlagTest, IsAccessibleInCode) {
+  bool dummy = testing::GMOCK_FLAG(catch_leaked_mocks) &&
+      testing::GMOCK_FLAG(verbose) == "";
+  (void)dummy;  // Avoids the "unused local variable" warning.
+}
diff --git a/third_party/googletest/googlemock/test/gmock_test_utils.py b/third_party/googletest/googlemock/test/gmock_test_utils.py
new file mode 100755
index 0000000..20e3d3d
--- /dev/null
+++ b/third_party/googletest/googlemock/test/gmock_test_utils.py
@@ -0,0 +1,112 @@
+#!/usr/bin/env python
+#
+# Copyright 2006, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Unit test utilities for Google C++ Mocking Framework."""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import os
+import sys
+
+
+# Determines path to gtest_test_utils and imports it.
+SCRIPT_DIR = os.path.dirname(__file__) or '.'
+
+# isdir resolves symbolic links.
+gtest_tests_util_dir = os.path.join(SCRIPT_DIR, '../gtest/test')
+if os.path.isdir(gtest_tests_util_dir):
+  GTEST_TESTS_UTIL_DIR = gtest_tests_util_dir
+else:
+  GTEST_TESTS_UTIL_DIR = os.path.join(SCRIPT_DIR, '../../gtest/test')
+
+sys.path.append(GTEST_TESTS_UTIL_DIR)
+import gtest_test_utils  # pylint: disable-msg=C6204
+
+
+def GetSourceDir():
+  """Returns the absolute path of the directory where the .py files are."""
+
+  return gtest_test_utils.GetSourceDir()
+
+
+def GetTestExecutablePath(executable_name):
+  """Returns the absolute path of the test binary given its name.
+
+  The function will print a message and abort the program if the resulting file
+  doesn't exist.
+
+  Args:
+    executable_name: name of the test binary that the test script runs.
+
+  Returns:
+    The absolute path of the test binary.
+  """
+
+  return gtest_test_utils.GetTestExecutablePath(executable_name)
+
+
+def GetExitStatus(exit_code):
+  """Returns the argument to exit(), or -1 if exit() wasn't called.
+
+  Args:
+    exit_code: the result value of os.system(command).
+  """
+
+  if os.name == 'nt':
+    # On Windows, os.WEXITSTATUS() doesn't work and os.system() returns
+    # the argument to exit() directly.
+    return exit_code
+  else:
+    # On Unix, os.WEXITSTATUS() must be used to extract the exit status
+    # from the result of os.system().
+    if os.WIFEXITED(exit_code):
+      return os.WEXITSTATUS(exit_code)
+    else:
+      return -1
+
+
+# Suppresses the "Invalid const name" lint complaint
+# pylint: disable-msg=C6409
+
+# Exposes utilities from gtest_test_utils.
+Subprocess = gtest_test_utils.Subprocess
+TestCase = gtest_test_utils.TestCase
+environ = gtest_test_utils.environ
+SetEnvVar = gtest_test_utils.SetEnvVar
+PREMATURE_EXIT_FILE_ENV_VAR = gtest_test_utils.PREMATURE_EXIT_FILE_ENV_VAR
+
+# pylint: enable-msg=C6409
+
+
+def Main():
+  """Runs the unit test."""
+
+  gtest_test_utils.Main()
diff --git a/third_party/googletest/googletest/CHANGES b/third_party/googletest/googletest/CHANGES
new file mode 100644
index 0000000..0552132
--- /dev/null
+++ b/third_party/googletest/googletest/CHANGES
@@ -0,0 +1,157 @@
+Changes for 1.7.0:
+
+* New feature: death tests are supported on OpenBSD and in iOS
+  simulator now.
+* New feature: Google Test now implements a protocol to allow
+  a test runner to detect that a test program has exited
+  prematurely and report it as a failure (before it would be
+  falsely reported as a success if the exit code is 0).
+* New feature: Test::RecordProperty() can now be used outside of the
+  lifespan of a test method, in which case it will be attributed to
+  the current test case or the test program in the XML report.
+* New feature (potentially breaking): --gtest_list_tests now prints
+  the type parameters and value parameters for each test.
+* Improvement: char pointers and char arrays are now escaped properly
+  in failure messages.
+* Improvement: failure summary in XML reports now includes file and
+  line information.
+* Improvement: the <testsuites> XML element now has a timestamp attribute.
+* Improvement: When --gtest_filter is specified, XML report now doesn't
+  contain information about tests that are filtered out.
+* Fixed the bug where long --gtest_filter flag values are truncated in
+  death tests.
+* Potentially breaking change: RUN_ALL_TESTS() is now implemented as a
+  function instead of a macro in order to work better with Clang.
+* Compatibility fixes with C++ 11 and various platforms.
+* Bug/warning fixes.
+
+Changes for 1.6.0:
+
+* New feature: ADD_FAILURE_AT() for reporting a test failure at the
+  given source location -- useful for writing testing utilities.
+* New feature: the universal value printer is moved from Google Mock
+  to Google Test.
+* New feature: type parameters and value parameters are reported in
+  the XML report now.
+* A gtest_disable_pthreads CMake option.
+* Colored output works in GNU Screen sessions now.
+* Parameters of value-parameterized tests are now printed in the
+  textual output.
+* Failures from ad hoc test assertions run before RUN_ALL_TESTS() are
+  now correctly reported.
+* Arguments of ASSERT_XY and EXPECT_XY no longer need to support << to
+  ostream.
+* More complete handling of exceptions.
+* GTEST_ASSERT_XY can be used instead of ASSERT_XY in case the latter
+  name is already used by another library.
+* --gtest_catch_exceptions is now true by default, allowing a test
+  program to continue after an exception is thrown.
+* Value-parameterized test fixtures can now derive from Test and
+  WithParamInterface<T> separately, easing conversion of legacy tests.
+* Death test messages are clearly marked to make them more
+  distinguishable from other messages.
+* Compatibility fixes for Android, Google Native Client, MinGW, HP UX,
+  PowerPC, Lucid autotools, libCStd, Sun C++, Borland C++ Builder (Code Gear),
+  IBM XL C++ (Visual Age C++), and C++0x.
+* Bug fixes and implementation clean-ups.
+* Potentially incompatible changes: disables the harmful 'make install'
+  command in autotools.
+
+Changes for 1.5.0:
+
+ * New feature: assertions can be safely called in multiple threads
+   where the pthreads library is available.
+ * New feature: predicates used inside EXPECT_TRUE() and friends
+   can now generate custom failure messages.
+ * New feature: Google Test can now be compiled as a DLL.
+ * New feature: fused source files are included.
+ * New feature: prints help when encountering unrecognized Google Test flags.
+ * Experimental feature: CMake build script (requires CMake 2.6.4+).
+ * Experimental feature: the Pump script for meta programming.
+ * double values streamed to an assertion are printed with enough precision
+   to differentiate any two different values.
+ * Google Test now works on Solaris and AIX.
+ * Build and test script improvements.
+ * Bug fixes and implementation clean-ups.
+
+ Potentially breaking changes:
+
+ * Stopped supporting VC++ 7.1 with exceptions disabled.
+ * Dropped support for 'make install'.
+
+Changes for 1.4.0:
+
+ * New feature: the event listener API
+ * New feature: test shuffling
+ * New feature: the XML report format is closer to junitreport and can
+   be parsed by Hudson now.
+ * New feature: when a test runs under Visual Studio, its failures are
+   integrated in the IDE.
+ * New feature: /MD(d) versions of VC++ projects.
+ * New feature: elapsed time for the tests is printed by default.
+ * New feature: comes with a TR1 tuple implementation such that Boost
+   is no longer needed for Combine().
+ * New feature: EXPECT_DEATH_IF_SUPPORTED macro and friends.
+ * New feature: the Xcode project can now produce static gtest
+   libraries in addition to a framework.
+ * Compatibility fixes for Solaris, Cygwin, minGW, Windows Mobile,
+   Symbian, gcc, and C++Builder.
+ * Bug fixes and implementation clean-ups.
+
+Changes for 1.3.0:
+
+ * New feature: death tests on Windows, Cygwin, and Mac.
+ * New feature: ability to use Google Test assertions in other testing
+   frameworks.
+ * New feature: ability to run disabled test via
+   --gtest_also_run_disabled_tests.
+ * New feature: the --help flag for printing the usage.
+ * New feature: access to Google Test flag values in user code.
+ * New feature: a script that packs Google Test into one .h and one
+   .cc file for easy deployment.
+ * New feature: support for distributing test functions to multiple
+   machines (requires support from the test runner).
+ * Bug fixes and implementation clean-ups.
+
+Changes for 1.2.1:
+
+ * Compatibility fixes for Linux IA-64 and IBM z/OS.
+ * Added support for using Boost and other TR1 implementations.
+ * Changes to the build scripts to support upcoming release of Google C++
+   Mocking Framework.
+ * Added Makefile to the distribution package.
+ * Improved build instructions in README.
+
+Changes for 1.2.0:
+
+ * New feature: value-parameterized tests.
+ * New feature: the ASSERT/EXPECT_(NON)FATAL_FAILURE(_ON_ALL_THREADS)
+   macros.
+ * Changed the XML report format to match JUnit/Ant's.
+ * Added tests to the Xcode project.
+ * Added scons/SConscript for building with SCons.
+ * Added src/gtest-all.cc for building Google Test from a single file.
+ * Fixed compatibility with Solaris and z/OS.
+ * Enabled running Python tests on systems with python 2.3 installed,
+   e.g. Mac OS X 10.4.
+ * Bug fixes.
+
+Changes for 1.1.0:
+
+ * New feature: type-parameterized tests.
+ * New feature: exception assertions.
+ * New feature: printing elapsed time of tests.
+ * Improved the robustness of death tests.
+ * Added an Xcode project and samples.
+ * Adjusted the output format on Windows to be understandable by Visual Studio.
+ * Minor bug fixes.
+
+Changes for 1.0.1:
+
+ * Added project files for Visual Studio 7.1.
+ * Fixed issues with compiling on Mac OS X.
+ * Fixed issues with compiling on Cygwin.
+
+Changes for 1.0.0:
+
+ * Initial Open Source release of Google Test
diff --git a/third_party/googletest/googletest/CMakeLists.txt b/third_party/googletest/googletest/CMakeLists.txt
new file mode 100644
index 0000000..bd78cfe
--- /dev/null
+++ b/third_party/googletest/googletest/CMakeLists.txt
@@ -0,0 +1,260 @@
+########################################################################
+# CMake build script for Google Test.
+#
+# To run the tests for Google Test itself on Linux, use 'make test' or
+# ctest.  You can select which tests to run using 'ctest -R regex'.
+# For more options, run 'ctest --help'.
+
+# BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to
+# make it prominent in the GUI.
+option(BUILD_SHARED_LIBS "Build shared libraries (DLLs)." OFF)
+
+# When other libraries are using a shared version of runtime libraries,
+# Google Test also has to use one.
+option(
+  gtest_force_shared_crt
+  "Use shared (DLL) run-time lib even when Google Test is built as static lib."
+  OFF)
+
+option(gtest_build_tests "Build all of gtest's own tests." OFF)
+
+option(gtest_build_samples "Build gtest's sample programs." OFF)
+
+option(gtest_disable_pthreads "Disable uses of pthreads in gtest." OFF)
+
+# Defines pre_project_set_up_hermetic_build() and set_up_hermetic_build().
+include(cmake/hermetic_build.cmake OPTIONAL)
+
+if (COMMAND pre_project_set_up_hermetic_build)
+  pre_project_set_up_hermetic_build()
+endif()
+
+########################################################################
+#
+# Project-wide settings
+
+# Name of the project.
+#
+# CMake files in this project can refer to the root source directory
+# as ${gtest_SOURCE_DIR} and to the root binary directory as
+# ${gtest_BINARY_DIR}.
+# Language "C" is required for find_package(Threads).
+project(gtest CXX C)
+cmake_minimum_required(VERSION 2.6.2)
+
+if (COMMAND set_up_hermetic_build)
+  set_up_hermetic_build()
+endif()
+
+# Define helper functions and macros used by Google Test.
+include(cmake/internal_utils.cmake)
+
+config_compiler_and_linker()  # Defined in internal_utils.cmake.
+
+# Where Google Test's .h files can be found.
+include_directories(
+  ${gtest_SOURCE_DIR}/include
+  ${gtest_SOURCE_DIR})
+
+# Where Google Test's libraries can be found.
+link_directories(${gtest_BINARY_DIR}/src)
+
+# Summary of tuple support for Microsoft Visual Studio:
+# Compiler    version(MS)  version(cmake)  Support
+# ----------  -----------  --------------  -----------------------------
+# <= VS 2010  <= 10        <= 1600         Use Google Tests's own tuple.
+# VS 2012     11           1700            std::tr1::tuple + _VARIADIC_MAX=10
+# VS 2013     12           1800            std::tr1::tuple
+if (MSVC AND MSVC_VERSION EQUAL 1700)
+  add_definitions(/D _VARIADIC_MAX=10)
+endif()
+
+########################################################################
+#
+# Defines the gtest & gtest_main libraries.  User tests should link
+# with one of them.
+
+# Google Test libraries.  We build them using more strict warnings than what
+# are used for other targets, to ensure that gtest can be compiled by a user
+# aggressive about warnings.
+cxx_library(gtest "${cxx_strict}" src/gtest-all.cc)
+cxx_library(gtest_main "${cxx_strict}" src/gtest_main.cc)
+target_link_libraries(gtest_main gtest)
+
+########################################################################
+#
+# Samples on how to link user tests with gtest or gtest_main.
+#
+# They are not built by default.  To build them, set the
+# gtest_build_samples option to ON.  You can do it by running ccmake
+# or specifying the -Dgtest_build_samples=ON flag when running cmake.
+
+if (gtest_build_samples)
+  cxx_executable(sample1_unittest samples gtest_main samples/sample1.cc)
+  cxx_executable(sample2_unittest samples gtest_main samples/sample2.cc)
+  cxx_executable(sample3_unittest samples gtest_main)
+  cxx_executable(sample4_unittest samples gtest_main samples/sample4.cc)
+  cxx_executable(sample5_unittest samples gtest_main samples/sample1.cc)
+  cxx_executable(sample6_unittest samples gtest_main)
+  cxx_executable(sample7_unittest samples gtest_main)
+  cxx_executable(sample8_unittest samples gtest_main)
+  cxx_executable(sample9_unittest samples gtest)
+  cxx_executable(sample10_unittest samples gtest)
+endif()
+
+########################################################################
+#
+# Google Test's own tests.
+#
+# You can skip this section if you aren't interested in testing
+# Google Test itself.
+#
+# The tests are not built by default.  To build them, set the
+# gtest_build_tests option to ON.  You can do it by running ccmake
+# or specifying the -Dgtest_build_tests=ON flag when running cmake.
+
+if (gtest_build_tests)
+  # This must be set in the root directory for the tests to be run by
+  # 'make test' or ctest.
+  enable_testing()
+
+  ############################################################
+  # C++ tests built with standard compiler flags.
+
+  cxx_test(gtest-death-test_test gtest_main)
+  cxx_test(gtest_environment_test gtest)
+  cxx_test(gtest-filepath_test gtest_main)
+  cxx_test(gtest-linked_ptr_test gtest_main)
+  cxx_test(gtest-listener_test gtest_main)
+  cxx_test(gtest_main_unittest gtest_main)
+  cxx_test(gtest-message_test gtest_main)
+  cxx_test(gtest_no_test_unittest gtest)
+  cxx_test(gtest-options_test gtest_main)
+  cxx_test(gtest-param-test_test gtest
+    test/gtest-param-test2_test.cc)
+  cxx_test(gtest-port_test gtest_main)
+  cxx_test(gtest_pred_impl_unittest gtest_main)
+  cxx_test(gtest_premature_exit_test gtest
+    test/gtest_premature_exit_test.cc)
+  cxx_test(gtest-printers_test gtest_main)
+  cxx_test(gtest_prod_test gtest_main
+    test/production.cc)
+  cxx_test(gtest_repeat_test gtest)
+  cxx_test(gtest_sole_header_test gtest_main)
+  cxx_test(gtest_stress_test gtest)
+  cxx_test(gtest-test-part_test gtest_main)
+  cxx_test(gtest_throw_on_failure_ex_test gtest)
+  cxx_test(gtest-typed-test_test gtest_main
+    test/gtest-typed-test2_test.cc)
+  cxx_test(gtest_unittest gtest_main)
+  cxx_test(gtest-unittest-api_test gtest)
+
+  ############################################################
+  # C++ tests built with non-standard compiler flags.
+
+  # MSVC 7.1 does not support STL with exceptions disabled.
+  if (NOT MSVC OR MSVC_VERSION GREATER 1310)
+    cxx_library(gtest_no_exception "${cxx_no_exception}"
+      src/gtest-all.cc)
+    cxx_library(gtest_main_no_exception "${cxx_no_exception}"
+      src/gtest-all.cc src/gtest_main.cc)
+  endif()
+  cxx_library(gtest_main_no_rtti "${cxx_no_rtti}"
+    src/gtest-all.cc src/gtest_main.cc)
+
+  cxx_test_with_flags(gtest-death-test_ex_nocatch_test
+    "${cxx_exception} -DGTEST_ENABLE_CATCH_EXCEPTIONS_=0"
+    gtest test/gtest-death-test_ex_test.cc)
+  cxx_test_with_flags(gtest-death-test_ex_catch_test
+    "${cxx_exception} -DGTEST_ENABLE_CATCH_EXCEPTIONS_=1"
+    gtest test/gtest-death-test_ex_test.cc)
+
+  cxx_test_with_flags(gtest_no_rtti_unittest "${cxx_no_rtti}"
+    gtest_main_no_rtti test/gtest_unittest.cc)
+
+  cxx_shared_library(gtest_dll "${cxx_default}"
+    src/gtest-all.cc src/gtest_main.cc)
+
+  cxx_executable_with_flags(gtest_dll_test_ "${cxx_default}"
+    gtest_dll test/gtest_all_test.cc)
+  set_target_properties(gtest_dll_test_
+                        PROPERTIES
+                        COMPILE_DEFINITIONS "GTEST_LINKED_AS_SHARED_LIBRARY=1")
+
+  if (NOT MSVC OR MSVC_VERSION LESS 1600)  # 1600 is Visual Studio 2010.
+    # Visual Studio 2010, 2012, and 2013 define symbols in std::tr1 that
+    # conflict with our own definitions. Therefore using our own tuple does not
+    # work on those compilers.
+    cxx_library(gtest_main_use_own_tuple "${cxx_use_own_tuple}"
+      src/gtest-all.cc src/gtest_main.cc)
+
+    cxx_test_with_flags(gtest-tuple_test "${cxx_use_own_tuple}"
+      gtest_main_use_own_tuple test/gtest-tuple_test.cc)
+
+    cxx_test_with_flags(gtest_use_own_tuple_test "${cxx_use_own_tuple}"
+      gtest_main_use_own_tuple
+      test/gtest-param-test_test.cc test/gtest-param-test2_test.cc)
+  endif()
+
+  ############################################################
+  # Python tests.
+
+  cxx_executable(gtest_break_on_failure_unittest_ test gtest)
+  py_test(gtest_break_on_failure_unittest)
+
+  # Visual Studio .NET 2003 does not support STL with exceptions disabled.
+  if (NOT MSVC OR MSVC_VERSION GREATER 1310)  # 1310 is Visual Studio .NET 2003
+    cxx_executable_with_flags(
+      gtest_catch_exceptions_no_ex_test_
+      "${cxx_no_exception}"
+      gtest_main_no_exception
+      test/gtest_catch_exceptions_test_.cc)
+  endif()
+
+  cxx_executable_with_flags(
+    gtest_catch_exceptions_ex_test_
+    "${cxx_exception}"
+    gtest_main
+    test/gtest_catch_exceptions_test_.cc)
+  py_test(gtest_catch_exceptions_test)
+
+  cxx_executable(gtest_color_test_ test gtest)
+  py_test(gtest_color_test)
+
+  cxx_executable(gtest_env_var_test_ test gtest)
+  py_test(gtest_env_var_test)
+
+  cxx_executable(gtest_filter_unittest_ test gtest)
+  py_test(gtest_filter_unittest)
+
+  cxx_executable(gtest_help_test_ test gtest_main)
+  py_test(gtest_help_test)
+
+  cxx_executable(gtest_list_tests_unittest_ test gtest)
+  py_test(gtest_list_tests_unittest)
+
+  cxx_executable(gtest_output_test_ test gtest)
+  py_test(gtest_output_test)
+
+  cxx_executable(gtest_shuffle_test_ test gtest)
+  py_test(gtest_shuffle_test)
+
+  # MSVC 7.1 does not support STL with exceptions disabled.
+  if (NOT MSVC OR MSVC_VERSION GREATER 1310)
+    cxx_executable(gtest_throw_on_failure_test_ test gtest_no_exception)
+    set_target_properties(gtest_throw_on_failure_test_
+      PROPERTIES
+      COMPILE_FLAGS "${cxx_no_exception}")
+    py_test(gtest_throw_on_failure_test)
+  endif()
+
+  cxx_executable(gtest_uninitialized_test_ test gtest)
+  py_test(gtest_uninitialized_test)
+
+  cxx_executable(gtest_xml_outfile1_test_ test gtest_main)
+  cxx_executable(gtest_xml_outfile2_test_ test gtest_main)
+  py_test(gtest_xml_outfiles_test)
+
+  cxx_executable(gtest_xml_output_unittest_ test gtest)
+  py_test(gtest_xml_output_unittest)
+endif()
diff --git a/third_party/googletest/googletest/CONTRIBUTORS b/third_party/googletest/googletest/CONTRIBUTORS
new file mode 100644
index 0000000..feae2fc
--- /dev/null
+++ b/third_party/googletest/googletest/CONTRIBUTORS
@@ -0,0 +1,37 @@
+# This file contains a list of people who've made non-trivial
+# contribution to the Google C++ Testing Framework project.  People
+# who commit code to the project are encouraged to add their names
+# here.  Please keep the list sorted by first names.
+
+Ajay Joshi <jaj@google.com>
+Balázs Dán <balazs.dan@gmail.com>
+Bharat Mediratta <bharat@menalto.com>
+Chandler Carruth <chandlerc@google.com>
+Chris Prince <cprince@google.com>
+Chris Taylor <taylorc@google.com>
+Dan Egnor <egnor@google.com>
+Eric Roman <eroman@chromium.org>
+Hady Zalek <hady.zalek@gmail.com>
+Jeffrey Yasskin <jyasskin@google.com>
+Jói Sigurðsson <joi@google.com>
+Keir Mierle <mierle@gmail.com>
+Keith Ray <keith.ray@gmail.com>
+Kenton Varda <kenton@google.com>
+Manuel Klimek <klimek@google.com>
+Markus Heule <markus.heule@gmail.com>
+Mika Raento <mikie@iki.fi>
+Miklós Fazekas <mfazekas@szemafor.com>
+Pasi Valminen <pasi.valminen@gmail.com>
+Patrick Hanna <phanna@google.com>
+Patrick Riley <pfr@google.com>
+Peter Kaminski <piotrk@google.com>
+Preston Jackson <preston.a.jackson@gmail.com>
+Rainer Klaffenboeck <rainer.klaffenboeck@dynatrace.com>
+Russ Cox <rsc@google.com>
+Russ Rufer <russ@pentad.com>
+Sean Mcafee <eefacm@gmail.com>
+Sigurður Ásgeirsson <siggi@google.com>
+Tracy Bialik <tracy@pentad.com>
+Vadim Berman <vadimb@google.com>
+Vlad Losev <vladl@google.com>
+Zhanyong Wan <wan@google.com>
diff --git a/third_party/googletest/googletest/LICENSE b/third_party/googletest/googletest/LICENSE
new file mode 100644
index 0000000..1941a11
--- /dev/null
+++ b/third_party/googletest/googletest/LICENSE
@@ -0,0 +1,28 @@
+Copyright 2008, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+    * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/third_party/googletest/googletest/Makefile.am b/third_party/googletest/googletest/Makefile.am
new file mode 100644
index 0000000..9c96b42
--- /dev/null
+++ b/third_party/googletest/googletest/Makefile.am
@@ -0,0 +1,306 @@
+# Automake file
+
+ACLOCAL_AMFLAGS = -I m4
+
+# Nonstandard package files for distribution
+EXTRA_DIST = \
+  CHANGES \
+  CONTRIBUTORS \
+  LICENSE \
+  include/gtest/gtest-param-test.h.pump \
+  include/gtest/internal/gtest-param-util-generated.h.pump \
+  include/gtest/internal/gtest-tuple.h.pump \
+  include/gtest/internal/gtest-type-util.h.pump \
+  make/Makefile \
+  scripts/fuse_gtest_files.py \
+  scripts/gen_gtest_pred_impl.py \
+  scripts/pump.py \
+  scripts/test/Makefile
+
+# gtest source files that we don't compile directly.  They are
+# #included by gtest-all.cc.
+GTEST_SRC = \
+  src/gtest-death-test.cc \
+  src/gtest-filepath.cc \
+  src/gtest-internal-inl.h \
+  src/gtest-port.cc \
+  src/gtest-printers.cc \
+  src/gtest-test-part.cc \
+  src/gtest-typed-test.cc \
+  src/gtest.cc
+
+EXTRA_DIST += $(GTEST_SRC)
+
+# Sample files that we don't compile.
+EXTRA_DIST += \
+  samples/prime_tables.h \
+  samples/sample2_unittest.cc \
+  samples/sample3_unittest.cc \
+  samples/sample4_unittest.cc \
+  samples/sample5_unittest.cc \
+  samples/sample6_unittest.cc \
+  samples/sample7_unittest.cc \
+  samples/sample8_unittest.cc \
+  samples/sample9_unittest.cc
+
+# C++ test files that we don't compile directly.
+EXTRA_DIST += \
+  test/gtest-death-test_ex_test.cc \
+  test/gtest-death-test_test.cc \
+  test/gtest-filepath_test.cc \
+  test/gtest-linked_ptr_test.cc \
+  test/gtest-listener_test.cc \
+  test/gtest-message_test.cc \
+  test/gtest-options_test.cc \
+  test/gtest-param-test2_test.cc \
+  test/gtest-param-test2_test.cc \
+  test/gtest-param-test_test.cc \
+  test/gtest-param-test_test.cc \
+  test/gtest-param-test_test.h \
+  test/gtest-port_test.cc \
+  test/gtest_premature_exit_test.cc \
+  test/gtest-printers_test.cc \
+  test/gtest-test-part_test.cc \
+  test/gtest-tuple_test.cc \
+  test/gtest-typed-test2_test.cc \
+  test/gtest-typed-test_test.cc \
+  test/gtest-typed-test_test.h \
+  test/gtest-unittest-api_test.cc \
+  test/gtest_break_on_failure_unittest_.cc \
+  test/gtest_catch_exceptions_test_.cc \
+  test/gtest_color_test_.cc \
+  test/gtest_env_var_test_.cc \
+  test/gtest_environment_test.cc \
+  test/gtest_filter_unittest_.cc \
+  test/gtest_help_test_.cc \
+  test/gtest_list_tests_unittest_.cc \
+  test/gtest_main_unittest.cc \
+  test/gtest_no_test_unittest.cc \
+  test/gtest_output_test_.cc \
+  test/gtest_pred_impl_unittest.cc \
+  test/gtest_prod_test.cc \
+  test/gtest_repeat_test.cc \
+  test/gtest_shuffle_test_.cc \
+  test/gtest_sole_header_test.cc \
+  test/gtest_stress_test.cc \
+  test/gtest_throw_on_failure_ex_test.cc \
+  test/gtest_throw_on_failure_test_.cc \
+  test/gtest_uninitialized_test_.cc \
+  test/gtest_unittest.cc \
+  test/gtest_unittest.cc \
+  test/gtest_xml_outfile1_test_.cc \
+  test/gtest_xml_outfile2_test_.cc \
+  test/gtest_xml_output_unittest_.cc \
+  test/production.cc \
+  test/production.h
+
+# Python tests that we don't run.
+EXTRA_DIST += \
+  test/gtest_break_on_failure_unittest.py \
+  test/gtest_catch_exceptions_test.py \
+  test/gtest_color_test.py \
+  test/gtest_env_var_test.py \
+  test/gtest_filter_unittest.py \
+  test/gtest_help_test.py \
+  test/gtest_list_tests_unittest.py \
+  test/gtest_output_test.py \
+  test/gtest_output_test_golden_lin.txt \
+  test/gtest_shuffle_test.py \
+  test/gtest_test_utils.py \
+  test/gtest_throw_on_failure_test.py \
+  test/gtest_uninitialized_test.py \
+  test/gtest_xml_outfiles_test.py \
+  test/gtest_xml_output_unittest.py \
+  test/gtest_xml_test_utils.py
+
+# CMake script
+EXTRA_DIST += \
+  CMakeLists.txt \
+  cmake/internal_utils.cmake
+
+# MSVC project files
+EXTRA_DIST += \
+  msvc/gtest-md.sln \
+  msvc/gtest-md.vcproj \
+  msvc/gtest.sln \
+  msvc/gtest.vcproj \
+  msvc/gtest_main-md.vcproj \
+  msvc/gtest_main.vcproj \
+  msvc/gtest_prod_test-md.vcproj \
+  msvc/gtest_prod_test.vcproj \
+  msvc/gtest_unittest-md.vcproj \
+  msvc/gtest_unittest.vcproj
+
+# xcode project files
+EXTRA_DIST += \
+  xcode/Config/DebugProject.xcconfig \
+  xcode/Config/FrameworkTarget.xcconfig \
+  xcode/Config/General.xcconfig \
+  xcode/Config/ReleaseProject.xcconfig \
+  xcode/Config/StaticLibraryTarget.xcconfig \
+  xcode/Config/TestTarget.xcconfig \
+  xcode/Resources/Info.plist \
+  xcode/Scripts/runtests.sh \
+  xcode/Scripts/versiongenerate.py \
+  xcode/gtest.xcodeproj/project.pbxproj
+
+# xcode sample files
+EXTRA_DIST += \
+  xcode/Samples/FrameworkSample/Info.plist \
+  xcode/Samples/FrameworkSample/WidgetFramework.xcodeproj/project.pbxproj \
+  xcode/Samples/FrameworkSample/runtests.sh \
+  xcode/Samples/FrameworkSample/widget.cc \
+  xcode/Samples/FrameworkSample/widget.h \
+  xcode/Samples/FrameworkSample/widget_test.cc
+
+# C++Builder project files
+EXTRA_DIST += \
+  codegear/gtest.cbproj \
+  codegear/gtest.groupproj \
+  codegear/gtest_all.cc \
+  codegear/gtest_link.cc \
+  codegear/gtest_main.cbproj \
+  codegear/gtest_unittest.cbproj
+
+# Distribute and install M4 macro
+m4datadir = $(datadir)/aclocal
+m4data_DATA = m4/gtest.m4
+EXTRA_DIST += $(m4data_DATA)
+
+# We define the global AM_CPPFLAGS as everything we compile includes from these
+# directories.
+AM_CPPFLAGS = -I$(srcdir) -I$(srcdir)/include
+
+# Modifies compiler and linker flags for pthreads compatibility.
+if HAVE_PTHREADS
+  AM_CXXFLAGS = @PTHREAD_CFLAGS@ -DGTEST_HAS_PTHREAD=1
+  AM_LIBS = @PTHREAD_LIBS@
+else
+  AM_CXXFLAGS = -DGTEST_HAS_PTHREAD=0
+endif
+
+# Build rules for libraries.
+lib_LTLIBRARIES = lib/libgtest.la lib/libgtest_main.la
+
+lib_libgtest_la_SOURCES = src/gtest-all.cc
+
+pkginclude_HEADERS = \
+  include/gtest/gtest-death-test.h \
+  include/gtest/gtest-message.h \
+  include/gtest/gtest-param-test.h \
+  include/gtest/gtest-printers.h \
+  include/gtest/gtest-spi.h \
+  include/gtest/gtest-test-part.h \
+  include/gtest/gtest-typed-test.h \
+  include/gtest/gtest.h \
+  include/gtest/gtest_pred_impl.h \
+  include/gtest/gtest_prod.h
+
+pkginclude_internaldir = $(pkgincludedir)/internal
+pkginclude_internal_HEADERS = \
+  include/gtest/internal/gtest-death-test-internal.h \
+  include/gtest/internal/gtest-filepath.h \
+  include/gtest/internal/gtest-internal.h \
+  include/gtest/internal/gtest-linked_ptr.h \
+  include/gtest/internal/gtest-param-util-generated.h \
+  include/gtest/internal/gtest-param-util.h \
+  include/gtest/internal/gtest-port.h \
+  include/gtest/internal/gtest-string.h \
+  include/gtest/internal/gtest-tuple.h \
+  include/gtest/internal/gtest-type-util.h
+
+lib_libgtest_main_la_SOURCES = src/gtest_main.cc
+lib_libgtest_main_la_LIBADD = lib/libgtest.la
+
+# Bulid rules for samples and tests. Automake's naming for some of
+# these variables isn't terribly obvious, so this is a brief
+# reference:
+#
+# TESTS -- Programs run automatically by "make check"
+# check_PROGRAMS -- Programs built by "make check" but not necessarily run
+
+noinst_LTLIBRARIES = samples/libsamples.la
+
+samples_libsamples_la_SOURCES = \
+  samples/sample1.cc \
+  samples/sample1.h \
+  samples/sample2.cc \
+  samples/sample2.h \
+  samples/sample3-inl.h \
+  samples/sample4.cc \
+  samples/sample4.h
+
+TESTS=
+TESTS_ENVIRONMENT = GTEST_SOURCE_DIR="$(srcdir)/test" \
+                    GTEST_BUILD_DIR="$(top_builddir)/test"
+check_PROGRAMS=
+
+# A simple sample on using gtest.
+TESTS += samples/sample1_unittest
+check_PROGRAMS += samples/sample1_unittest
+samples_sample1_unittest_SOURCES = samples/sample1_unittest.cc
+samples_sample1_unittest_LDADD = lib/libgtest_main.la \
+                                 lib/libgtest.la \
+                                 samples/libsamples.la
+
+# Another sample.  It also verifies that libgtest works.
+TESTS += samples/sample10_unittest
+check_PROGRAMS += samples/sample10_unittest
+samples_sample10_unittest_SOURCES = samples/sample10_unittest.cc
+samples_sample10_unittest_LDADD = lib/libgtest.la
+
+# This tests most constructs of gtest and verifies that libgtest_main
+# and libgtest work.
+TESTS += test/gtest_all_test
+check_PROGRAMS += test/gtest_all_test
+test_gtest_all_test_SOURCES = test/gtest_all_test.cc
+test_gtest_all_test_LDADD = lib/libgtest_main.la \
+                            lib/libgtest.la
+
+# Tests that fused gtest files compile and work.
+FUSED_GTEST_SRC = \
+  fused-src/gtest/gtest-all.cc \
+  fused-src/gtest/gtest.h \
+  fused-src/gtest/gtest_main.cc
+
+if HAVE_PYTHON
+TESTS += test/fused_gtest_test
+check_PROGRAMS += test/fused_gtest_test
+test_fused_gtest_test_SOURCES = $(FUSED_GTEST_SRC) \
+                                samples/sample1.cc samples/sample1_unittest.cc
+test_fused_gtest_test_CPPFLAGS = -I"$(srcdir)/fused-src"
+
+# Build rules for putting fused Google Test files into the distribution
+# package. The user can also create those files by manually running
+# scripts/fuse_gtest_files.py.
+$(test_fused_gtest_test_SOURCES): fused-gtest
+
+fused-gtest: $(pkginclude_HEADERS) $(pkginclude_internal_HEADERS) \
+             $(GTEST_SRC) src/gtest-all.cc src/gtest_main.cc \
+             scripts/fuse_gtest_files.py
+	mkdir -p "$(srcdir)/fused-src"
+	chmod -R u+w "$(srcdir)/fused-src"
+	rm -f "$(srcdir)/fused-src/gtest/gtest-all.cc"
+	rm -f "$(srcdir)/fused-src/gtest/gtest.h"
+	"$(srcdir)/scripts/fuse_gtest_files.py" "$(srcdir)/fused-src"
+	cp -f "$(srcdir)/src/gtest_main.cc" "$(srcdir)/fused-src/gtest/"
+
+maintainer-clean-local:
+	rm -rf "$(srcdir)/fused-src"
+endif
+
+# Death tests may produce core dumps in the build directory. In case
+# this happens, clean them to keep distcleancheck happy.
+CLEANFILES = core
+
+# Disables 'make install' as installing a compiled version of Google
+# Test can lead to undefined behavior due to violation of the
+# One-Definition Rule.
+
+install-exec-local:
+	echo "'make install' is dangerous and not supported. Instead, see README for how to integrate Google Test into your build system."
+	false
+
+install-data-local:
+	echo "'make install' is dangerous and not supported. Instead, see README for how to integrate Google Test into your build system."
+	false
diff --git a/third_party/googletest/googletest/README.md b/third_party/googletest/googletest/README.md
new file mode 100644
index 0000000..9bd59c8
--- /dev/null
+++ b/third_party/googletest/googletest/README.md
@@ -0,0 +1,280 @@
+
+### Generic Build Instructions ###
+
+#### Setup ####
+
+To build Google Test and your tests that use it, you need to tell your
+build system where to find its headers and source files.  The exact
+way to do it depends on which build system you use, and is usually
+straightforward.
+
+#### Build ####
+
+Suppose you put Google Test in directory `${GTEST_DIR}`.  To build it,
+create a library build target (or a project as called by Visual Studio
+and Xcode) to compile
+
+    ${GTEST_DIR}/src/gtest-all.cc
+
+with `${GTEST_DIR}/include` in the system header search path and `${GTEST_DIR}`
+in the normal header search path.  Assuming a Linux-like system and gcc,
+something like the following will do:
+
+    g++ -isystem ${GTEST_DIR}/include -I${GTEST_DIR} \
+        -pthread -c ${GTEST_DIR}/src/gtest-all.cc
+    ar -rv libgtest.a gtest-all.o
+
+(We need `-pthread` as Google Test uses threads.)
+
+Next, you should compile your test source file with
+`${GTEST_DIR}/include` in the system header search path, and link it
+with gtest and any other necessary libraries:
+
+    g++ -isystem ${GTEST_DIR}/include -pthread path/to/your_test.cc libgtest.a \
+        -o your_test
+
+As an example, the make/ directory contains a Makefile that you can
+use to build Google Test on systems where GNU make is available
+(e.g. Linux, Mac OS X, and Cygwin).  It doesn't try to build Google
+Test's own tests.  Instead, it just builds the Google Test library and
+a sample test.  You can use it as a starting point for your own build
+script.
+
+If the default settings are correct for your environment, the
+following commands should succeed:
+
+    cd ${GTEST_DIR}/make
+    make
+    ./sample1_unittest
+
+If you see errors, try to tweak the contents of `make/Makefile` to make
+them go away.  There are instructions in `make/Makefile` on how to do
+it.
+
+### Using CMake ###
+
+Google Test comes with a CMake build script (
+[CMakeLists.txt](master/CMakeLists.txt)) that can be used on a wide range of platforms ("C" stands for
+cross-platform.). If you don't have CMake installed already, you can
+download it for free from <http://www.cmake.org/>.
+
+CMake works by generating native makefiles or build projects that can
+be used in the compiler environment of your choice.  The typical
+workflow starts with:
+
+    mkdir mybuild       # Create a directory to hold the build output.
+    cd mybuild
+    cmake ${GTEST_DIR}  # Generate native build scripts.
+
+If you want to build Google Test's samples, you should replace the
+last command with
+
+    cmake -Dgtest_build_samples=ON ${GTEST_DIR}
+
+If you are on a \*nix system, you should now see a Makefile in the
+current directory.  Just type 'make' to build gtest.
+
+If you use Windows and have Visual Studio installed, a `gtest.sln` file
+and several `.vcproj` files will be created.  You can then build them
+using Visual Studio.
+
+On Mac OS X with Xcode installed, a `.xcodeproj` file will be generated.
+
+### Legacy Build Scripts ###
+
+Before settling on CMake, we have been providing hand-maintained build
+projects/scripts for Visual Studio, Xcode, and Autotools.  While we
+continue to provide them for convenience, they are not actively
+maintained any more.  We highly recommend that you follow the
+instructions in the previous two sections to integrate Google Test
+with your existing build system.
+
+If you still need to use the legacy build scripts, here's how:
+
+The msvc\ folder contains two solutions with Visual C++ projects.
+Open the `gtest.sln` or `gtest-md.sln` file using Visual Studio, and you
+are ready to build Google Test the same way you build any Visual
+Studio project.  Files that have names ending with -md use DLL
+versions of Microsoft runtime libraries (the /MD or the /MDd compiler
+option).  Files without that suffix use static versions of the runtime
+libraries (the /MT or the /MTd option).  Please note that one must use
+the same option to compile both gtest and the test code.  If you use
+Visual Studio 2005 or above, we recommend the -md version as /MD is
+the default for new projects in these versions of Visual Studio.
+
+On Mac OS X, open the `gtest.xcodeproj` in the `xcode/` folder using
+Xcode.  Build the "gtest" target.  The universal binary framework will
+end up in your selected build directory (selected in the Xcode
+"Preferences..." -> "Building" pane and defaults to xcode/build).
+Alternatively, at the command line, enter:
+
+    xcodebuild
+
+This will build the "Release" configuration of gtest.framework in your
+default build location.  See the "xcodebuild" man page for more
+information about building different configurations and building in
+different locations.
+
+If you wish to use the Google Test Xcode project with Xcode 4.x and
+above, you need to either:
+
+ * update the SDK configuration options in xcode/Config/General.xconfig.
+   Comment options `SDKROOT`, `MACOS_DEPLOYMENT_TARGET`, and `GCC_VERSION`. If
+   you choose this route you lose the ability to target earlier versions
+   of MacOS X.
+ * Install an SDK for an earlier version. This doesn't appear to be
+   supported by Apple, but has been reported to work
+   (http://stackoverflow.com/questions/5378518).
+
+### Tweaking Google Test ###
+
+Google Test can be used in diverse environments.  The default
+configuration may not work (or may not work well) out of the box in
+some environments.  However, you can easily tweak Google Test by
+defining control macros on the compiler command line.  Generally,
+these macros are named like `GTEST_XYZ` and you define them to either 1
+or 0 to enable or disable a certain feature.
+
+We list the most frequently used macros below.  For a complete list,
+see file [include/gtest/internal/gtest-port.h](https://github.com/google/googletest/blob/master/include/gtest/internal/gtest-port.h).
+
+### Choosing a TR1 Tuple Library ###
+
+Some Google Test features require the C++ Technical Report 1 (TR1)
+tuple library, which is not yet available with all compilers.  The
+good news is that Google Test implements a subset of TR1 tuple that's
+enough for its own need, and will automatically use this when the
+compiler doesn't provide TR1 tuple.
+
+Usually you don't need to care about which tuple library Google Test
+uses.  However, if your project already uses TR1 tuple, you need to
+tell Google Test to use the same TR1 tuple library the rest of your
+project uses, or the two tuple implementations will clash.  To do
+that, add
+
+    -DGTEST_USE_OWN_TR1_TUPLE=0
+
+to the compiler flags while compiling Google Test and your tests.  If
+you want to force Google Test to use its own tuple library, just add
+
+    -DGTEST_USE_OWN_TR1_TUPLE=1
+
+to the compiler flags instead.
+
+If you don't want Google Test to use tuple at all, add
+
+    -DGTEST_HAS_TR1_TUPLE=0
+
+and all features using tuple will be disabled.
+
+### Multi-threaded Tests ###
+
+Google Test is thread-safe where the pthread library is available.
+After `#include "gtest/gtest.h"`, you can check the `GTEST_IS_THREADSAFE`
+macro to see whether this is the case (yes if the macro is `#defined` to
+1, no if it's undefined.).
+
+If Google Test doesn't correctly detect whether pthread is available
+in your environment, you can force it with
+
+    -DGTEST_HAS_PTHREAD=1
+
+or
+
+    -DGTEST_HAS_PTHREAD=0
+
+When Google Test uses pthread, you may need to add flags to your
+compiler and/or linker to select the pthread library, or you'll get
+link errors.  If you use the CMake script or the deprecated Autotools
+script, this is taken care of for you.  If you use your own build
+script, you'll need to read your compiler and linker's manual to
+figure out what flags to add.
+
+### As a Shared Library (DLL) ###
+
+Google Test is compact, so most users can build and link it as a
+static library for the simplicity.  You can choose to use Google Test
+as a shared library (known as a DLL on Windows) if you prefer.
+
+To compile *gtest* as a shared library, add
+
+    -DGTEST_CREATE_SHARED_LIBRARY=1
+
+to the compiler flags.  You'll also need to tell the linker to produce
+a shared library instead - consult your linker's manual for how to do
+it.
+
+To compile your *tests* that use the gtest shared library, add
+
+    -DGTEST_LINKED_AS_SHARED_LIBRARY=1
+
+to the compiler flags.
+
+Note: while the above steps aren't technically necessary today when
+using some compilers (e.g. GCC), they may become necessary in the
+future, if we decide to improve the speed of loading the library (see
+<http://gcc.gnu.org/wiki/Visibility> for details).  Therefore you are
+recommended to always add the above flags when using Google Test as a
+shared library.  Otherwise a future release of Google Test may break
+your build script.
+
+### Avoiding Macro Name Clashes ###
+
+In C++, macros don't obey namespaces.  Therefore two libraries that
+both define a macro of the same name will clash if you #include both
+definitions.  In case a Google Test macro clashes with another
+library, you can force Google Test to rename its macro to avoid the
+conflict.
+
+Specifically, if both Google Test and some other code define macro
+FOO, you can add
+
+    -DGTEST_DONT_DEFINE_FOO=1
+
+to the compiler flags to tell Google Test to change the macro's name
+from `FOO` to `GTEST_FOO`.  Currently `FOO` can be `FAIL`, `SUCCEED`,
+or `TEST`.  For example, with `-DGTEST_DONT_DEFINE_TEST=1`, you'll
+need to write
+
+    GTEST_TEST(SomeTest, DoesThis) { ... }
+
+instead of
+
+    TEST(SomeTest, DoesThis) { ... }
+
+in order to define a test.
+
+## Developing Google Test ##
+
+This section discusses how to make your own changes to Google Test.
+
+### Testing Google Test Itself ###
+
+To make sure your changes work as intended and don't break existing
+functionality, you'll want to compile and run Google Test's own tests.
+For that you can use CMake:
+
+    mkdir mybuild
+    cd mybuild
+    cmake -Dgtest_build_tests=ON ${GTEST_DIR}
+
+Make sure you have Python installed, as some of Google Test's tests
+are written in Python.  If the cmake command complains about not being
+able to find Python (`Could NOT find PythonInterp (missing:
+PYTHON_EXECUTABLE)`), try telling it explicitly where your Python
+executable can be found:
+
+    cmake -DPYTHON_EXECUTABLE=path/to/python -Dgtest_build_tests=ON ${GTEST_DIR}
+
+Next, you can build Google Test and all of its own tests.  On \*nix,
+this is usually done by 'make'.  To run the tests, do
+
+    make test
+
+All tests should pass.
+
+Normally you don't need to worry about regenerating the source files,
+unless you need to modify them.  In that case, you should modify the
+corresponding .pump files instead and run the pump.py Python script to
+regenerate them.  You can find pump.py in the [scripts/](scripts/) directory.
+Read the [Pump manual](docs/PumpManual.md) for how to use it.
diff --git a/third_party/googletest/googletest/build-aux/.keep b/third_party/googletest/googletest/build-aux/.keep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/third_party/googletest/googletest/build-aux/.keep
diff --git a/third_party/googletest/googletest/cmake/internal_utils.cmake b/third_party/googletest/googletest/cmake/internal_utils.cmake
new file mode 100644
index 0000000..93e6dbb
--- /dev/null
+++ b/third_party/googletest/googletest/cmake/internal_utils.cmake
@@ -0,0 +1,242 @@
+# Defines functions and macros useful for building Google Test and
+# Google Mock.
+#
+# Note:
+#
+# - This file will be run twice when building Google Mock (once via
+#   Google Test's CMakeLists.txt, and once via Google Mock's).
+#   Therefore it shouldn't have any side effects other than defining
+#   the functions and macros.
+#
+# - The functions/macros defined in this file may depend on Google
+#   Test and Google Mock's option() definitions, and thus must be
+#   called *after* the options have been defined.
+
+# Tweaks CMake's default compiler/linker settings to suit Google Test's needs.
+#
+# This must be a macro(), as inside a function string() can only
+# update variables in the function scope.
+macro(fix_default_compiler_settings_)
+  if (MSVC)
+    # For MSVC, CMake sets certain flags to defaults we want to override.
+    # This replacement code is taken from sample in the CMake Wiki at
+    # http://www.cmake.org/Wiki/CMake_FAQ#Dynamic_Replace.
+    foreach (flag_var
+             CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
+             CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+      if (NOT BUILD_SHARED_LIBS AND NOT gtest_force_shared_crt)
+        # When Google Test is built as a shared library, it should also use
+        # shared runtime libraries.  Otherwise, it may end up with multiple
+        # copies of runtime library data in different modules, resulting in
+        # hard-to-find crashes. When it is built as a static library, it is
+        # preferable to use CRT as static libraries, as we don't have to rely
+        # on CRT DLLs being available. CMake always defaults to using shared
+        # CRT libraries, so we override that default here.
+        string(REPLACE "/MD" "-MT" ${flag_var} "${${flag_var}}")
+      endif()
+
+      # We prefer more strict warning checking for building Google Test.
+      # Replaces /W3 with /W4 in defaults.
+      string(REPLACE "/W3" "/W4" ${flag_var} "${${flag_var}}")
+    endforeach()
+  endif()
+endmacro()
+
+# Defines the compiler/linker flags used to build Google Test and
+# Google Mock.  You can tweak these definitions to suit your need.  A
+# variable's value is empty before it's explicitly assigned to.
+macro(config_compiler_and_linker)
+  if (NOT gtest_disable_pthreads)
+    # Defines CMAKE_USE_PTHREADS_INIT and CMAKE_THREAD_LIBS_INIT.
+    find_package(Threads)
+  endif()
+
+  fix_default_compiler_settings_()
+  if (MSVC)
+    # Newlines inside flags variables break CMake's NMake generator.
+    # TODO(vladl@google.com): Add -RTCs and -RTCu to debug builds.
+    set(cxx_base_flags "-GS -W4 -WX -wd4251 -wd4275 -nologo -J -Zi")
+    if (MSVC_VERSION LESS 1400)  # 1400 is Visual Studio 2005
+      # Suppress spurious warnings MSVC 7.1 sometimes issues.
+      # Forcing value to bool.
+      set(cxx_base_flags "${cxx_base_flags} -wd4800")
+      # Copy constructor and assignment operator could not be generated.
+      set(cxx_base_flags "${cxx_base_flags} -wd4511 -wd4512")
+      # Compatibility warnings not applicable to Google Test.
+      # Resolved overload was found by argument-dependent lookup.
+      set(cxx_base_flags "${cxx_base_flags} -wd4675")
+    endif()
+    if (MSVC_VERSION LESS 1500)  # 1500 is Visual Studio 2008
+      # Conditional expression is constant.
+      # When compiling with /W4, we get several instances of C4127
+      # (Conditional expression is constant). In our code, we disable that
+      # warning on a case-by-case basis. However, on Visual Studio 2005,
+      # the warning fires on std::list. Therefore on that compiler and earlier,
+      # we disable the warning project-wide.
+      set(cxx_base_flags "${cxx_base_flags} -wd4127")
+    endif()
+    if (NOT (MSVC_VERSION LESS 1700))  # 1700 is Visual Studio 2012.
+      # Suppress "unreachable code" warning on VS 2012 and later.
+      # http://stackoverflow.com/questions/3232669 explains the issue.
+      set(cxx_base_flags "${cxx_base_flags} -wd4702")
+    endif()
+
+    set(cxx_base_flags "${cxx_base_flags} -D_UNICODE -DUNICODE -DWIN32 -D_WIN32")
+    set(cxx_base_flags "${cxx_base_flags} -DSTRICT -DWIN32_LEAN_AND_MEAN")
+    set(cxx_exception_flags "-EHsc -D_HAS_EXCEPTIONS=1")
+    set(cxx_no_exception_flags "-D_HAS_EXCEPTIONS=0")
+    set(cxx_no_rtti_flags "-GR-")
+  elseif (CMAKE_COMPILER_IS_GNUCXX)
+    set(cxx_base_flags "-Wall -Wshadow")
+    set(cxx_exception_flags "-fexceptions")
+    set(cxx_no_exception_flags "-fno-exceptions")
+    # Until version 4.3.2, GCC doesn't define a macro to indicate
+    # whether RTTI is enabled.  Therefore we define GTEST_HAS_RTTI
+    # explicitly.
+    set(cxx_no_rtti_flags "-fno-rtti -DGTEST_HAS_RTTI=0")
+    set(cxx_strict_flags
+      "-Wextra -Wno-unused-parameter -Wno-missing-field-initializers")
+  elseif (CMAKE_CXX_COMPILER_ID STREQUAL "SunPro")
+    set(cxx_exception_flags "-features=except")
+    # Sun Pro doesn't provide macros to indicate whether exceptions and
+    # RTTI are enabled, so we define GTEST_HAS_* explicitly.
+    set(cxx_no_exception_flags "-features=no%except -DGTEST_HAS_EXCEPTIONS=0")
+    set(cxx_no_rtti_flags "-features=no%rtti -DGTEST_HAS_RTTI=0")
+  elseif (CMAKE_CXX_COMPILER_ID STREQUAL "VisualAge" OR
+      CMAKE_CXX_COMPILER_ID STREQUAL "XL")
+    # CMake 2.8 changes Visual Age's compiler ID to "XL".
+    set(cxx_exception_flags "-qeh")
+    set(cxx_no_exception_flags "-qnoeh")
+    # Until version 9.0, Visual Age doesn't define a macro to indicate
+    # whether RTTI is enabled.  Therefore we define GTEST_HAS_RTTI
+    # explicitly.
+    set(cxx_no_rtti_flags "-qnortti -DGTEST_HAS_RTTI=0")
+  elseif (CMAKE_CXX_COMPILER_ID STREQUAL "HP")
+    set(cxx_base_flags "-AA -mt")
+    set(cxx_exception_flags "-DGTEST_HAS_EXCEPTIONS=1")
+    set(cxx_no_exception_flags "+noeh -DGTEST_HAS_EXCEPTIONS=0")
+    # RTTI can not be disabled in HP aCC compiler.
+    set(cxx_no_rtti_flags "")
+  endif()
+
+  if (CMAKE_USE_PTHREADS_INIT)  # The pthreads library is available and allowed.
+    set(cxx_base_flags "${cxx_base_flags} -DGTEST_HAS_PTHREAD=1")
+  else()
+    set(cxx_base_flags "${cxx_base_flags} -DGTEST_HAS_PTHREAD=0")
+  endif()
+
+  # For building gtest's own tests and samples.
+  set(cxx_exception "${CMAKE_CXX_FLAGS} ${cxx_base_flags} ${cxx_exception_flags}")
+  set(cxx_no_exception
+    "${CMAKE_CXX_FLAGS} ${cxx_base_flags} ${cxx_no_exception_flags}")
+  set(cxx_default "${cxx_exception}")
+  set(cxx_no_rtti "${cxx_default} ${cxx_no_rtti_flags}")
+  set(cxx_use_own_tuple "${cxx_default} -DGTEST_USE_OWN_TR1_TUPLE=1")
+
+  # For building the gtest libraries.
+  set(cxx_strict "${cxx_default} ${cxx_strict_flags}")
+endmacro()
+
+# Defines the gtest & gtest_main libraries.  User tests should link
+# with one of them.
+function(cxx_library_with_type name type cxx_flags)
+  # type can be either STATIC or SHARED to denote a static or shared library.
+  # ARGN refers to additional arguments after 'cxx_flags'.
+  add_library(${name} ${type} ${ARGN})
+  set_target_properties(${name}
+    PROPERTIES
+    COMPILE_FLAGS "${cxx_flags}")
+  if (BUILD_SHARED_LIBS OR type STREQUAL "SHARED")
+    set_target_properties(${name}
+      PROPERTIES
+      COMPILE_DEFINITIONS "GTEST_CREATE_SHARED_LIBRARY=1")
+  endif()
+  if (CMAKE_USE_PTHREADS_INIT)
+    target_link_libraries(${name} ${CMAKE_THREAD_LIBS_INIT})
+  endif()
+endfunction()
+
+########################################################################
+#
+# Helper functions for creating build targets.
+
+function(cxx_shared_library name cxx_flags)
+  cxx_library_with_type(${name} SHARED "${cxx_flags}" ${ARGN})
+endfunction()
+
+function(cxx_library name cxx_flags)
+  cxx_library_with_type(${name} "" "${cxx_flags}" ${ARGN})
+endfunction()
+
+# cxx_executable_with_flags(name cxx_flags libs srcs...)
+#
+# creates a named C++ executable that depends on the given libraries and
+# is built from the given source files with the given compiler flags.
+function(cxx_executable_with_flags name cxx_flags libs)
+  add_executable(${name} ${ARGN})
+  if (cxx_flags)
+    set_target_properties(${name}
+      PROPERTIES
+      COMPILE_FLAGS "${cxx_flags}")
+  endif()
+  if (BUILD_SHARED_LIBS)
+    set_target_properties(${name}
+      PROPERTIES
+      COMPILE_DEFINITIONS "GTEST_LINKED_AS_SHARED_LIBRARY=1")
+  endif()
+  # To support mixing linking in static and dynamic libraries, link each
+  # library in with an extra call to target_link_libraries.
+  foreach (lib "${libs}")
+    target_link_libraries(${name} ${lib})
+  endforeach()
+endfunction()
+
+# cxx_executable(name dir lib srcs...)
+#
+# creates a named target that depends on the given libs and is built
+# from the given source files.  dir/name.cc is implicitly included in
+# the source file list.
+function(cxx_executable name dir libs)
+  cxx_executable_with_flags(
+    ${name} "${cxx_default}" "${libs}" "${dir}/${name}.cc" ${ARGN})
+endfunction()
+
+# Sets PYTHONINTERP_FOUND and PYTHON_EXECUTABLE.
+find_package(PythonInterp)
+
+# cxx_test_with_flags(name cxx_flags libs srcs...)
+#
+# creates a named C++ test that depends on the given libs and is built
+# from the given source files with the given compiler flags.
+function(cxx_test_with_flags name cxx_flags libs)
+  cxx_executable_with_flags(${name} "${cxx_flags}" "${libs}" ${ARGN})
+  add_test(${name} ${name})
+endfunction()
+
+# cxx_test(name libs srcs...)
+#
+# creates a named test target that depends on the given libs and is
+# built from the given source files.  Unlike cxx_test_with_flags,
+# test/name.cc is already implicitly included in the source file list.
+function(cxx_test name libs)
+  cxx_test_with_flags("${name}" "${cxx_default}" "${libs}"
+    "test/${name}.cc" ${ARGN})
+endfunction()
+
+# py_test(name)
+#
+# creates a Python test with the given name whose main module is in
+# test/name.py.  It does nothing if Python is not installed.
+function(py_test name)
+  # We are not supporting Python tests on Linux yet as they consider
+  # all Linux environments to be google3 and try to use google3 features.
+  if (PYTHONINTERP_FOUND)
+    # ${CMAKE_BINARY_DIR} is known at configuration time, so we can
+    # directly bind it from cmake. ${CTEST_CONFIGURATION_TYPE} is known
+    # only at ctest runtime (by calling ctest -c <Configuration>), so
+    # we have to escape $ to delay variable substitution here.
+    add_test(${name}
+      ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/${name}.py
+          --build_dir=${CMAKE_CURRENT_BINARY_DIR}/\${CTEST_CONFIGURATION_TYPE})
+  endif()
+endfunction()
diff --git a/third_party/googletest/googletest/codegear/gtest.cbproj b/third_party/googletest/googletest/codegear/gtest.cbproj
new file mode 100644
index 0000000..95c3054
--- /dev/null
+++ b/third_party/googletest/googletest/codegear/gtest.cbproj
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <PropertyGroup>

+    <ProjectGuid>{bca37a72-5b07-46cf-b44e-89f8e06451a2}</ProjectGuid>

+    <Config Condition="'$(Config)'==''">Release</Config>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">

+    <Base>true</Base>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">

+    <Base>true</Base>

+    <Cfg_1>true</Cfg_1>

+    <CfgParent>Base</CfgParent>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">

+    <Base>true</Base>

+    <Cfg_2>true</Cfg_2>

+    <CfgParent>Base</CfgParent>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Base)'!=''">

+    <BCC_OptimizeForSpeed>true</BCC_OptimizeForSpeed>

+    <OutputExt>lib</OutputExt>

+    <DCC_CBuilderOutput>JPHNE</DCC_CBuilderOutput>

+    <Defines>NO_STRICT</Defines>

+    <DynamicRTL>true</DynamicRTL>

+    <UsePackages>true</UsePackages>

+    <ProjectType>CppStaticLibrary</ProjectType>

+    <BCC_CPPCompileAlways>true</BCC_CPPCompileAlways>

+    <PackageImports>rtl.bpi;vcl.bpi;bcbie.bpi;vclx.bpi;vclactnband.bpi;xmlrtl.bpi;bcbsmp.bpi;dbrtl.bpi;vcldb.bpi;bdertl.bpi;vcldbx.bpi;dsnap.bpi;dsnapcon.bpi;vclib.bpi;ibxpress.bpi;adortl.bpi;dbxcds.bpi;dbexpress.bpi;DbxCommonDriver.bpi;websnap.bpi;vclie.bpi;webdsnap.bpi;inet.bpi;inetdbbde.bpi;inetdbxpress.bpi;soaprtl.bpi;Rave75VCL.bpi;teeUI.bpi;tee.bpi;teedb.bpi;IndyCore.bpi;IndySystem.bpi;IndyProtocols.bpi;IntrawebDB_90_100.bpi;Intraweb_90_100.bpi;dclZipForged11.bpi;vclZipForged11.bpi;GR32_BDS2006.bpi;GR32_DSGN_BDS2006.bpi;Jcl.bpi;JclVcl.bpi;JvCoreD11R.bpi;JvSystemD11R.bpi;JvStdCtrlsD11R.bpi;JvAppFrmD11R.bpi;JvBandsD11R.bpi;JvDBD11R.bpi;JvDlgsD11R.bpi;JvBDED11R.bpi;JvCmpD11R.bpi;JvCryptD11R.bpi;JvCtrlsD11R.bpi;JvCustomD11R.bpi;JvDockingD11R.bpi;JvDotNetCtrlsD11R.bpi;JvEDID11R.bpi;JvGlobusD11R.bpi;JvHMID11R.bpi;JvInterpreterD11R.bpi;JvJansD11R.bpi;JvManagedThreadsD11R.bpi;JvMMD11R.bpi;JvNetD11R.bpi;JvPageCompsD11R.bpi;JvPluginD11R.bpi;JvPrintPreviewD11R.bpi;JvRuntimeDesignD11R.bpi;JvTimeFrameworkD11R.bpi;JvValidatorsD11R.bpi;JvWizardD11R.bpi;JvXPCtrlsD11R.bpi;VclSmp.bpi;CExceptionExpert11.bpi</PackageImports>

+    <BCC_wpar>false</BCC_wpar>

+    <IncludePath>$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\include;..</IncludePath>

+    <AllPackageLibs>rtl.lib;vcl.lib</AllPackageLibs>

+    <TLIB_PageSize>32</TLIB_PageSize>

+    <ILINK_LibraryPath>$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk</ILINK_LibraryPath>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Cfg_1)'!=''">

+    <BCC_OptimizeForSpeed>false</BCC_OptimizeForSpeed>

+    <DCC_Optimize>false</DCC_Optimize>

+    <DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>

+    <Defines>_DEBUG;$(Defines)</Defines>

+    <ILINK_FullDebugInfo>true</ILINK_FullDebugInfo>

+    <BCC_InlineFunctionExpansion>false</BCC_InlineFunctionExpansion>

+    <ILINK_DisableIncrementalLinking>true</ILINK_DisableIncrementalLinking>

+    <BCC_UseRegisterVariables>None</BCC_UseRegisterVariables>

+    <DCC_Define>DEBUG</DCC_Define>

+    <BCC_DebugLineNumbers>true</BCC_DebugLineNumbers>

+    <IntermediateOutputDir>Debug</IntermediateOutputDir>

+    <TASM_DisplaySourceLines>true</TASM_DisplaySourceLines>

+    <BCC_StackFrames>true</BCC_StackFrames>

+    <BCC_DisableOptimizations>true</BCC_DisableOptimizations>

+    <ILINK_LibraryPath>$(BDS)\lib\debug;$(ILINK_LibraryPath)</ILINK_LibraryPath>

+    <TASM_Debugging>Full</TASM_Debugging>

+    <BCC_SourceDebuggingOn>true</BCC_SourceDebuggingOn>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Cfg_2)'!=''">

+    <Defines>NDEBUG;$(Defines)</Defines>

+    <IntermediateOutputDir>Release</IntermediateOutputDir>

+    <ILINK_LibraryPath>$(BDS)\lib\release;$(ILINK_LibraryPath)</ILINK_LibraryPath>

+    <TASM_Debugging>None</TASM_Debugging>

+  </PropertyGroup>

+  <ProjectExtensions>

+    <Borland.Personality>CPlusPlusBuilder.Personality</Borland.Personality>

+    <Borland.ProjectType>CppStaticLibrary</Borland.ProjectType>

+    <BorlandProject>

+<BorlandProject><CPlusPlusBuilder.Personality><VersionInfo><VersionInfo Name="IncludeVerInfo">False</VersionInfo><VersionInfo Name="AutoIncBuild">False</VersionInfo><VersionInfo Name="MajorVer">1</VersionInfo><VersionInfo Name="MinorVer">0</VersionInfo><VersionInfo Name="Release">0</VersionInfo><VersionInfo Name="Build">0</VersionInfo><VersionInfo Name="Debug">False</VersionInfo><VersionInfo Name="PreRelease">False</VersionInfo><VersionInfo Name="Special">False</VersionInfo><VersionInfo Name="Private">False</VersionInfo><VersionInfo Name="DLL">False</VersionInfo><VersionInfo Name="Locale">1033</VersionInfo><VersionInfo Name="CodePage">1252</VersionInfo></VersionInfo><VersionInfoKeys><VersionInfoKeys Name="CompanyName"></VersionInfoKeys><VersionInfoKeys Name="FileDescription"></VersionInfoKeys><VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="InternalName"></VersionInfoKeys><VersionInfoKeys Name="LegalCopyright"></VersionInfoKeys><VersionInfoKeys Name="LegalTrademarks"></VersionInfoKeys><VersionInfoKeys Name="OriginalFilename"></VersionInfoKeys><VersionInfoKeys Name="ProductName"></VersionInfoKeys><VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="Comments"></VersionInfoKeys></VersionInfoKeys><Debugging><Debugging Name="DebugSourceDirs"></Debugging></Debugging><Parameters><Parameters Name="RunParams"></Parameters><Parameters Name="Launcher"></Parameters><Parameters Name="UseLauncher">False</Parameters><Parameters Name="DebugCWD"></Parameters><Parameters Name="HostApplication"></Parameters><Parameters Name="RemoteHost"></Parameters><Parameters Name="RemotePath"></Parameters><Parameters Name="RemoteParams"></Parameters><Parameters Name="RemoteLauncher"></Parameters><Parameters Name="UseRemoteLauncher">False</Parameters><Parameters Name="RemoteCWD"></Parameters><Parameters Name="RemoteDebug">False</Parameters><Parameters Name="Debug Symbols Search Path"></Parameters><Parameters Name="LoadAllSymbols">True</Parameters><Parameters Name="LoadUnspecifiedSymbols">False</Parameters></Parameters><Excluded_Packages>

+      

+      

+      <Excluded_Packages Name="$(BDS)\bin\bcboffice2k100.bpl">CodeGear C++Builder Office 2000 Servers Package</Excluded_Packages>

+      <Excluded_Packages Name="$(BDS)\bin\bcbofficexp100.bpl">CodeGear C++Builder Office XP Servers Package</Excluded_Packages>

+    </Excluded_Packages><Linker><Linker Name="LibPrefix"></Linker><Linker Name="LibSuffix"></Linker><Linker Name="LibVersion"></Linker></Linker><ProjectProperties><ProjectProperties Name="AutoShowDeps">False</ProjectProperties><ProjectProperties Name="ManagePaths">True</ProjectProperties><ProjectProperties Name="VerifyPackages">True</ProjectProperties></ProjectProperties><HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Count">3</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item0">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\include;..</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item1">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\include;..</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item2">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\src;..\include</HistoryLists_hlIncludePath></HistoryLists_hlIncludePath><HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Count">1</HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Item0">$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk</HistoryLists_hlILINK_LibraryPath></HistoryLists_hlILINK_LibraryPath><HistoryLists_hlDefines><HistoryLists_hlDefines Name="Count">1</HistoryLists_hlDefines><HistoryLists_hlDefines Name="Item0">NO_STRICT</HistoryLists_hlDefines></HistoryLists_hlDefines><HistoryLists_hlTLIB_PageSize><HistoryLists_hlTLIB_PageSize Name="Count">1</HistoryLists_hlTLIB_PageSize><HistoryLists_hlTLIB_PageSize Name="Item0">32</HistoryLists_hlTLIB_PageSize><HistoryLists_hlTLIB_PageSize Name="Item1">16</HistoryLists_hlTLIB_PageSize></HistoryLists_hlTLIB_PageSize></CPlusPlusBuilder.Personality></BorlandProject></BorlandProject>

+  </ProjectExtensions>

+  <Import Project="$(MSBuildBinPath)\Borland.Cpp.Targets" />

+  <ItemGroup>

+    <None Include="..\include\gtest\gtest-death-test.h">

+      <BuildOrder>3</BuildOrder>

+    </None>

+    <None Include="..\include\gtest\gtest-message.h">

+      <BuildOrder>4</BuildOrder>

+    </None>

+    <None Include="..\include\gtest\gtest-param-test.h">

+      <BuildOrder>5</BuildOrder>

+    </None>

+    <None Include="..\include\gtest\gtest-spi.h">

+      <BuildOrder>6</BuildOrder>

+    </None>

+    <None Include="..\include\gtest\gtest-test-part.h">

+      <BuildOrder>7</BuildOrder>

+    </None>

+    <None Include="..\include\gtest\gtest-typed-test.h">

+      <BuildOrder>8</BuildOrder>

+    </None>

+    <None Include="..\include\gtest\gtest.h">

+      <BuildOrder>0</BuildOrder>

+    </None>

+    <None Include="..\include\gtest\gtest_pred_impl.h">

+      <BuildOrder>1</BuildOrder>

+    </None>

+    <None Include="..\include\gtest\gtest_prod.h">

+      <BuildOrder>2</BuildOrder>

+    </None>

+    <None Include="..\include\gtest\internal\gtest-death-test-internal.h">

+      <BuildOrder>9</BuildOrder>

+    </None>

+    <None Include="..\include\gtest\internal\gtest-filepath.h">

+      <BuildOrder>10</BuildOrder>

+    </None>

+    <None Include="..\include\gtest\internal\gtest-internal.h">

+      <BuildOrder>11</BuildOrder>

+    </None>

+    <None Include="..\include\gtest\internal\gtest-linked_ptr.h">

+      <BuildOrder>12</BuildOrder>

+    </None>

+    <None Include="..\include\gtest\internal\gtest-param-util-generated.h">

+      <BuildOrder>14</BuildOrder>

+    </None>

+    <None Include="..\include\gtest\internal\gtest-param-util.h">

+      <BuildOrder>13</BuildOrder>

+    </None>

+    <None Include="..\include\gtest\internal\gtest-port.h">

+      <BuildOrder>15</BuildOrder>

+    </None>

+    <None Include="..\include\gtest\internal\gtest-string.h">

+      <BuildOrder>16</BuildOrder>

+    </None>

+    <None Include="..\include\gtest\internal\gtest-type-util.h">

+      <BuildOrder>17</BuildOrder>

+    </None>

+    <CppCompile Include="gtest_all.cc">

+      <BuildOrder>18</BuildOrder>

+    </CppCompile>

+    <BuildConfiguration Include="Debug">

+      <Key>Cfg_1</Key>

+    </BuildConfiguration>

+    <BuildConfiguration Include="Release">

+      <Key>Cfg_2</Key>

+    </BuildConfiguration>

+  </ItemGroup>

+</Project>
\ No newline at end of file
diff --git a/third_party/googletest/googletest/codegear/gtest.groupproj b/third_party/googletest/googletest/codegear/gtest.groupproj
new file mode 100644
index 0000000..faf31ca
--- /dev/null
+++ b/third_party/googletest/googletest/codegear/gtest.groupproj
@@ -0,0 +1,54 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <PropertyGroup>

+    <ProjectGuid>{c1d923e0-6cba-4332-9b6f-3420acbf5091}</ProjectGuid>

+  </PropertyGroup>

+  <ItemGroup />

+  <ItemGroup>

+    <Projects Include="gtest.cbproj" />

+    <Projects Include="gtest_main.cbproj" />

+    <Projects Include="gtest_unittest.cbproj" />

+  </ItemGroup>

+  <ProjectExtensions>

+    <Borland.Personality>Default.Personality</Borland.Personality>

+    <Borland.ProjectType />

+    <BorlandProject>

+<BorlandProject xmlns=""><Default.Personality></Default.Personality></BorlandProject></BorlandProject>

+  </ProjectExtensions>

+  <Target Name="gtest">

+    <MSBuild Projects="gtest.cbproj" Targets="" />

+  </Target>

+  <Target Name="gtest:Clean">

+    <MSBuild Projects="gtest.cbproj" Targets="Clean" />

+  </Target>

+  <Target Name="gtest:Make">

+    <MSBuild Projects="gtest.cbproj" Targets="Make" />

+  </Target>

+  <Target Name="gtest_main">

+    <MSBuild Projects="gtest_main.cbproj" Targets="" />

+  </Target>

+  <Target Name="gtest_main:Clean">

+    <MSBuild Projects="gtest_main.cbproj" Targets="Clean" />

+  </Target>

+  <Target Name="gtest_main:Make">

+    <MSBuild Projects="gtest_main.cbproj" Targets="Make" />

+  </Target>

+  <Target Name="gtest_unittest">

+    <MSBuild Projects="gtest_unittest.cbproj" Targets="" />

+  </Target>

+  <Target Name="gtest_unittest:Clean">

+    <MSBuild Projects="gtest_unittest.cbproj" Targets="Clean" />

+  </Target>

+  <Target Name="gtest_unittest:Make">

+    <MSBuild Projects="gtest_unittest.cbproj" Targets="Make" />

+  </Target>

+  <Target Name="Build">

+    <CallTarget Targets="gtest;gtest_main;gtest_unittest" />

+  </Target>

+  <Target Name="Clean">

+    <CallTarget Targets="gtest:Clean;gtest_main:Clean;gtest_unittest:Clean" />

+  </Target>

+  <Target Name="Make">

+    <CallTarget Targets="gtest:Make;gtest_main:Make;gtest_unittest:Make" />

+  </Target>

+  <Import Condition="Exists('$(MSBuildBinPath)\Borland.Group.Targets')" Project="$(MSBuildBinPath)\Borland.Group.Targets" />

+</Project>
\ No newline at end of file
diff --git a/third_party/googletest/googletest/codegear/gtest_all.cc b/third_party/googletest/googletest/codegear/gtest_all.cc
new file mode 100644
index 0000000..121b2d8
--- /dev/null
+++ b/third_party/googletest/googletest/codegear/gtest_all.cc
@@ -0,0 +1,38 @@
+// Copyright 2009, Google Inc.

+// All rights reserved.

+//

+// Redistribution and use in source and binary forms, with or without

+// modification, are permitted provided that the following conditions are

+// met:

+//

+//     * Redistributions of source code must retain the above copyright

+// notice, this list of conditions and the following disclaimer.

+//     * Redistributions in binary form must reproduce the above

+// copyright notice, this list of conditions and the following disclaimer

+// in the documentation and/or other materials provided with the

+// distribution.

+//     * Neither the name of Google Inc. nor the names of its

+// contributors may be used to endorse or promote products derived from

+// this software without specific prior written permission.

+//

+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+//

+// Author: Josh Kelley (joshkel@gmail.com)

+//

+// Google C++ Testing Framework (Google Test)

+//

+// C++Builder's IDE cannot build a static library from files with hyphens

+// in their name.  See http://qc.codegear.com/wc/qcmain.aspx?d=70977 .

+// This file serves as a workaround.

+

+#include "src/gtest-all.cc"

diff --git a/third_party/googletest/googletest/codegear/gtest_link.cc b/third_party/googletest/googletest/codegear/gtest_link.cc
new file mode 100644
index 0000000..918eccd
--- /dev/null
+++ b/third_party/googletest/googletest/codegear/gtest_link.cc
@@ -0,0 +1,40 @@
+// Copyright 2009, Google Inc.

+// All rights reserved.

+//

+// Redistribution and use in source and binary forms, with or without

+// modification, are permitted provided that the following conditions are

+// met:

+//

+//     * Redistributions of source code must retain the above copyright

+// notice, this list of conditions and the following disclaimer.

+//     * Redistributions in binary form must reproduce the above

+// copyright notice, this list of conditions and the following disclaimer

+// in the documentation and/or other materials provided with the

+// distribution.

+//     * Neither the name of Google Inc. nor the names of its

+// contributors may be used to endorse or promote products derived from

+// this software without specific prior written permission.

+//

+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+//

+// Author: Josh Kelley (joshkel@gmail.com)

+//

+// Google C++ Testing Framework (Google Test)

+//

+// Links gtest.lib and gtest_main.lib into the current project in C++Builder.

+// This means that these libraries can't be renamed, but it's the only way to

+// ensure that Debug versus Release test builds are linked against the

+// appropriate Debug or Release build of the libraries.

+

+#pragma link "gtest.lib"

+#pragma link "gtest_main.lib"

diff --git a/third_party/googletest/googletest/codegear/gtest_main.cbproj b/third_party/googletest/googletest/codegear/gtest_main.cbproj
new file mode 100644
index 0000000..d76ce13
--- /dev/null
+++ b/third_party/googletest/googletest/codegear/gtest_main.cbproj
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <PropertyGroup>

+    <ProjectGuid>{bca37a72-5b07-46cf-b44e-89f8e06451a2}</ProjectGuid>

+    <Config Condition="'$(Config)'==''">Release</Config>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">

+    <Base>true</Base>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">

+    <Base>true</Base>

+    <Cfg_1>true</Cfg_1>

+    <CfgParent>Base</CfgParent>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">

+    <Base>true</Base>

+    <Cfg_2>true</Cfg_2>

+    <CfgParent>Base</CfgParent>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Base)'!=''">

+    <BCC_OptimizeForSpeed>true</BCC_OptimizeForSpeed>

+    <OutputExt>lib</OutputExt>

+    <DCC_CBuilderOutput>JPHNE</DCC_CBuilderOutput>

+    <Defines>NO_STRICT</Defines>

+    <DynamicRTL>true</DynamicRTL>

+    <UsePackages>true</UsePackages>

+    <ProjectType>CppStaticLibrary</ProjectType>

+    <BCC_CPPCompileAlways>true</BCC_CPPCompileAlways>

+    <PackageImports>rtl.bpi;vcl.bpi;bcbie.bpi;vclx.bpi;vclactnband.bpi;xmlrtl.bpi;bcbsmp.bpi;dbrtl.bpi;vcldb.bpi;bdertl.bpi;vcldbx.bpi;dsnap.bpi;dsnapcon.bpi;vclib.bpi;ibxpress.bpi;adortl.bpi;dbxcds.bpi;dbexpress.bpi;DbxCommonDriver.bpi;websnap.bpi;vclie.bpi;webdsnap.bpi;inet.bpi;inetdbbde.bpi;inetdbxpress.bpi;soaprtl.bpi;Rave75VCL.bpi;teeUI.bpi;tee.bpi;teedb.bpi;IndyCore.bpi;IndySystem.bpi;IndyProtocols.bpi;IntrawebDB_90_100.bpi;Intraweb_90_100.bpi;dclZipForged11.bpi;vclZipForged11.bpi;GR32_BDS2006.bpi;GR32_DSGN_BDS2006.bpi;Jcl.bpi;JclVcl.bpi;JvCoreD11R.bpi;JvSystemD11R.bpi;JvStdCtrlsD11R.bpi;JvAppFrmD11R.bpi;JvBandsD11R.bpi;JvDBD11R.bpi;JvDlgsD11R.bpi;JvBDED11R.bpi;JvCmpD11R.bpi;JvCryptD11R.bpi;JvCtrlsD11R.bpi;JvCustomD11R.bpi;JvDockingD11R.bpi;JvDotNetCtrlsD11R.bpi;JvEDID11R.bpi;JvGlobusD11R.bpi;JvHMID11R.bpi;JvInterpreterD11R.bpi;JvJansD11R.bpi;JvManagedThreadsD11R.bpi;JvMMD11R.bpi;JvNetD11R.bpi;JvPageCompsD11R.bpi;JvPluginD11R.bpi;JvPrintPreviewD11R.bpi;JvRuntimeDesignD11R.bpi;JvTimeFrameworkD11R.bpi;JvValidatorsD11R.bpi;JvWizardD11R.bpi;JvXPCtrlsD11R.bpi;VclSmp.bpi;CExceptionExpert11.bpi</PackageImports>

+    <BCC_wpar>false</BCC_wpar>

+    <IncludePath>$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\include;..</IncludePath>

+    <AllPackageLibs>rtl.lib;vcl.lib</AllPackageLibs>

+    <TLIB_PageSize>32</TLIB_PageSize>

+    <ILINK_LibraryPath>$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk</ILINK_LibraryPath>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Cfg_1)'!=''">

+    <BCC_OptimizeForSpeed>false</BCC_OptimizeForSpeed>

+    <DCC_Optimize>false</DCC_Optimize>

+    <DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>

+    <Defines>_DEBUG;$(Defines)</Defines>

+    <ILINK_FullDebugInfo>true</ILINK_FullDebugInfo>

+    <BCC_InlineFunctionExpansion>false</BCC_InlineFunctionExpansion>

+    <ILINK_DisableIncrementalLinking>true</ILINK_DisableIncrementalLinking>

+    <BCC_UseRegisterVariables>None</BCC_UseRegisterVariables>

+    <DCC_Define>DEBUG</DCC_Define>

+    <BCC_DebugLineNumbers>true</BCC_DebugLineNumbers>

+    <IntermediateOutputDir>Debug</IntermediateOutputDir>

+    <TASM_DisplaySourceLines>true</TASM_DisplaySourceLines>

+    <BCC_StackFrames>true</BCC_StackFrames>

+    <BCC_DisableOptimizations>true</BCC_DisableOptimizations>

+    <ILINK_LibraryPath>$(BDS)\lib\debug;$(ILINK_LibraryPath)</ILINK_LibraryPath>

+    <TASM_Debugging>Full</TASM_Debugging>

+    <BCC_SourceDebuggingOn>true</BCC_SourceDebuggingOn>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Cfg_2)'!=''">

+    <Defines>NDEBUG;$(Defines)</Defines>

+    <IntermediateOutputDir>Release</IntermediateOutputDir>

+    <ILINK_LibraryPath>$(BDS)\lib\release;$(ILINK_LibraryPath)</ILINK_LibraryPath>

+    <TASM_Debugging>None</TASM_Debugging>

+  </PropertyGroup>

+  <ProjectExtensions>

+    <Borland.Personality>CPlusPlusBuilder.Personality</Borland.Personality>

+    <Borland.ProjectType>CppStaticLibrary</Borland.ProjectType>

+    <BorlandProject>

+<BorlandProject><CPlusPlusBuilder.Personality><VersionInfo><VersionInfo Name="IncludeVerInfo">False</VersionInfo><VersionInfo Name="AutoIncBuild">False</VersionInfo><VersionInfo Name="MajorVer">1</VersionInfo><VersionInfo Name="MinorVer">0</VersionInfo><VersionInfo Name="Release">0</VersionInfo><VersionInfo Name="Build">0</VersionInfo><VersionInfo Name="Debug">False</VersionInfo><VersionInfo Name="PreRelease">False</VersionInfo><VersionInfo Name="Special">False</VersionInfo><VersionInfo Name="Private">False</VersionInfo><VersionInfo Name="DLL">False</VersionInfo><VersionInfo Name="Locale">1033</VersionInfo><VersionInfo Name="CodePage">1252</VersionInfo></VersionInfo><VersionInfoKeys><VersionInfoKeys Name="CompanyName"></VersionInfoKeys><VersionInfoKeys Name="FileDescription"></VersionInfoKeys><VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="InternalName"></VersionInfoKeys><VersionInfoKeys Name="LegalCopyright"></VersionInfoKeys><VersionInfoKeys Name="LegalTrademarks"></VersionInfoKeys><VersionInfoKeys Name="OriginalFilename"></VersionInfoKeys><VersionInfoKeys Name="ProductName"></VersionInfoKeys><VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="Comments"></VersionInfoKeys></VersionInfoKeys><Debugging><Debugging Name="DebugSourceDirs"></Debugging></Debugging><Parameters><Parameters Name="RunParams"></Parameters><Parameters Name="Launcher"></Parameters><Parameters Name="UseLauncher">False</Parameters><Parameters Name="DebugCWD"></Parameters><Parameters Name="HostApplication"></Parameters><Parameters Name="RemoteHost"></Parameters><Parameters Name="RemotePath"></Parameters><Parameters Name="RemoteParams"></Parameters><Parameters Name="RemoteLauncher"></Parameters><Parameters Name="UseRemoteLauncher">False</Parameters><Parameters Name="RemoteCWD"></Parameters><Parameters Name="RemoteDebug">False</Parameters><Parameters Name="Debug Symbols Search Path"></Parameters><Parameters Name="LoadAllSymbols">True</Parameters><Parameters Name="LoadUnspecifiedSymbols">False</Parameters></Parameters><Excluded_Packages>

+      <Excluded_Packages Name="$(BDS)\bin\bcboffice2k100.bpl">CodeGear C++Builder Office 2000 Servers Package</Excluded_Packages>

+      <Excluded_Packages Name="$(BDS)\bin\bcbofficexp100.bpl">CodeGear C++Builder Office XP Servers Package</Excluded_Packages>

+    </Excluded_Packages><Linker><Linker Name="LibPrefix"></Linker><Linker Name="LibSuffix"></Linker><Linker Name="LibVersion"></Linker></Linker><ProjectProperties><ProjectProperties Name="AutoShowDeps">False</ProjectProperties><ProjectProperties Name="ManagePaths">True</ProjectProperties><ProjectProperties Name="VerifyPackages">True</ProjectProperties></ProjectProperties><HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Count">3</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item0">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\include;..</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item1">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\include;..</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item2">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\src;..\include</HistoryLists_hlIncludePath></HistoryLists_hlIncludePath><HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Count">1</HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Item0">$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk</HistoryLists_hlILINK_LibraryPath></HistoryLists_hlILINK_LibraryPath><HistoryLists_hlDefines><HistoryLists_hlDefines Name="Count">1</HistoryLists_hlDefines><HistoryLists_hlDefines Name="Item0">NO_STRICT</HistoryLists_hlDefines></HistoryLists_hlDefines><HistoryLists_hlTLIB_PageSize><HistoryLists_hlTLIB_PageSize Name="Count">1</HistoryLists_hlTLIB_PageSize><HistoryLists_hlTLIB_PageSize Name="Item0">32</HistoryLists_hlTLIB_PageSize><HistoryLists_hlTLIB_PageSize Name="Item1">16</HistoryLists_hlTLIB_PageSize></HistoryLists_hlTLIB_PageSize></CPlusPlusBuilder.Personality></BorlandProject></BorlandProject>

+  </ProjectExtensions>

+  <Import Project="$(MSBuildBinPath)\Borland.Cpp.Targets" />

+  <ItemGroup>

+    <CppCompile Include="..\src\gtest_main.cc">

+      <BuildOrder>0</BuildOrder>

+    </CppCompile>

+    <BuildConfiguration Include="Debug">

+      <Key>Cfg_1</Key>

+    </BuildConfiguration>

+    <BuildConfiguration Include="Release">

+      <Key>Cfg_2</Key>

+    </BuildConfiguration>

+  </ItemGroup>

+</Project>

diff --git a/third_party/googletest/googletest/codegear/gtest_unittest.cbproj b/third_party/googletest/googletest/codegear/gtest_unittest.cbproj
new file mode 100644
index 0000000..dc5db8e
--- /dev/null
+++ b/third_party/googletest/googletest/codegear/gtest_unittest.cbproj
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <PropertyGroup>

+    <ProjectGuid>{eea63393-5ac5-4b9c-8909-d75fef2daa41}</ProjectGuid>

+    <Config Condition="'$(Config)'==''">Release</Config>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">

+    <Base>true</Base>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">

+    <Base>true</Base>

+    <Cfg_1>true</Cfg_1>

+    <CfgParent>Base</CfgParent>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">

+    <Base>true</Base>

+    <Cfg_2>true</Cfg_2>

+    <CfgParent>Base</CfgParent>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Base)'!=''">

+    <OutputExt>exe</OutputExt>

+    <BCC_OptimizeForSpeed>true</BCC_OptimizeForSpeed>

+    <Defines>NO_STRICT</Defines>

+    <DCC_CBuilderOutput>JPHNE</DCC_CBuilderOutput>

+    <DynamicRTL>true</DynamicRTL>

+    <ILINK_ObjectSearchPath>..\test</ILINK_ObjectSearchPath>

+    <UsePackages>true</UsePackages>

+    <ProjectType>CppConsoleApplication</ProjectType>

+    <NoVCL>true</NoVCL>

+    <BCC_CPPCompileAlways>true</BCC_CPPCompileAlways>

+    <PackageImports>rtl.bpi;vcl.bpi;bcbie.bpi;vclx.bpi;vclactnband.bpi;xmlrtl.bpi;bcbsmp.bpi;dbrtl.bpi;vcldb.bpi;bdertl.bpi;vcldbx.bpi;dsnap.bpi;dsnapcon.bpi;vclib.bpi;ibxpress.bpi;adortl.bpi;dbxcds.bpi;dbexpress.bpi;DbxCommonDriver.bpi;websnap.bpi;vclie.bpi;webdsnap.bpi;inet.bpi;inetdbbde.bpi;inetdbxpress.bpi;soaprtl.bpi;Rave75VCL.bpi;teeUI.bpi;tee.bpi;teedb.bpi;IndyCore.bpi;IndySystem.bpi;IndyProtocols.bpi;IntrawebDB_90_100.bpi;Intraweb_90_100.bpi;Jcl.bpi;JclVcl.bpi;JvCoreD11R.bpi;JvSystemD11R.bpi;JvStdCtrlsD11R.bpi;JvAppFrmD11R.bpi;JvBandsD11R.bpi;JvDBD11R.bpi;JvDlgsD11R.bpi;JvBDED11R.bpi;JvCmpD11R.bpi;JvCryptD11R.bpi;JvCtrlsD11R.bpi;JvCustomD11R.bpi;JvDockingD11R.bpi;JvDotNetCtrlsD11R.bpi;JvEDID11R.bpi;JvGlobusD11R.bpi;JvHMID11R.bpi;JvInterpreterD11R.bpi;JvJansD11R.bpi;JvManagedThreadsD11R.bpi;JvMMD11R.bpi;JvNetD11R.bpi;JvPageCompsD11R.bpi;JvPluginD11R.bpi;JvPrintPreviewD11R.bpi;JvRuntimeDesignD11R.bpi;JvTimeFrameworkD11R.bpi;JvValidatorsD11R.bpi;JvWizardD11R.bpi;JvXPCtrlsD11R.bpi;VclSmp.bpi</PackageImports>

+    <BCC_wpar>false</BCC_wpar>

+    <IncludePath>$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\include;..\test;..</IncludePath>

+    <ILINK_LibraryPath>$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk;..\test</ILINK_LibraryPath>

+    <Multithreaded>true</Multithreaded>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Cfg_1)'!=''">

+    <BCC_OptimizeForSpeed>false</BCC_OptimizeForSpeed>

+    <DCC_Optimize>false</DCC_Optimize>

+    <DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>

+    <Defines>_DEBUG;$(Defines)</Defines>

+    <ILINK_FullDebugInfo>true</ILINK_FullDebugInfo>

+    <BCC_InlineFunctionExpansion>false</BCC_InlineFunctionExpansion>

+    <ILINK_DisableIncrementalLinking>true</ILINK_DisableIncrementalLinking>

+    <BCC_UseRegisterVariables>None</BCC_UseRegisterVariables>

+    <DCC_Define>DEBUG</DCC_Define>

+    <BCC_DebugLineNumbers>true</BCC_DebugLineNumbers>

+    <IntermediateOutputDir>Debug</IntermediateOutputDir>

+    <TASM_DisplaySourceLines>true</TASM_DisplaySourceLines>

+    <BCC_StackFrames>true</BCC_StackFrames>

+    <BCC_DisableOptimizations>true</BCC_DisableOptimizations>

+    <ILINK_LibraryPath>$(BDS)\lib\debug;$(ILINK_LibraryPath)</ILINK_LibraryPath>

+    <TASM_Debugging>Full</TASM_Debugging>

+    <BCC_SourceDebuggingOn>true</BCC_SourceDebuggingOn>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Cfg_2)'!=''">

+    <Defines>NDEBUG;$(Defines)</Defines>

+    <IntermediateOutputDir>Release</IntermediateOutputDir>

+    <ILINK_LibraryPath>$(BDS)\lib\release;$(ILINK_LibraryPath)</ILINK_LibraryPath>

+    <TASM_Debugging>None</TASM_Debugging>

+  </PropertyGroup>

+  <ProjectExtensions>

+    <Borland.Personality>CPlusPlusBuilder.Personality</Borland.Personality>

+    <Borland.ProjectType>CppConsoleApplication</Borland.ProjectType>

+    <BorlandProject>

+<BorlandProject><CPlusPlusBuilder.Personality><VersionInfo><VersionInfo Name="IncludeVerInfo">False</VersionInfo><VersionInfo Name="AutoIncBuild">False</VersionInfo><VersionInfo Name="MajorVer">1</VersionInfo><VersionInfo Name="MinorVer">0</VersionInfo><VersionInfo Name="Release">0</VersionInfo><VersionInfo Name="Build">0</VersionInfo><VersionInfo Name="Debug">False</VersionInfo><VersionInfo Name="PreRelease">False</VersionInfo><VersionInfo Name="Special">False</VersionInfo><VersionInfo Name="Private">False</VersionInfo><VersionInfo Name="DLL">False</VersionInfo><VersionInfo Name="Locale">1033</VersionInfo><VersionInfo Name="CodePage">1252</VersionInfo></VersionInfo><VersionInfoKeys><VersionInfoKeys Name="CompanyName"></VersionInfoKeys><VersionInfoKeys Name="FileDescription"></VersionInfoKeys><VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="InternalName"></VersionInfoKeys><VersionInfoKeys Name="LegalCopyright"></VersionInfoKeys><VersionInfoKeys Name="LegalTrademarks"></VersionInfoKeys><VersionInfoKeys Name="OriginalFilename"></VersionInfoKeys><VersionInfoKeys Name="ProductName"></VersionInfoKeys><VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="Comments"></VersionInfoKeys></VersionInfoKeys><Debugging><Debugging Name="DebugSourceDirs"></Debugging></Debugging><Parameters><Parameters Name="RunParams"></Parameters><Parameters Name="Launcher"></Parameters><Parameters Name="UseLauncher">False</Parameters><Parameters Name="DebugCWD"></Parameters><Parameters Name="HostApplication"></Parameters><Parameters Name="RemoteHost"></Parameters><Parameters Name="RemotePath"></Parameters><Parameters Name="RemoteParams"></Parameters><Parameters Name="RemoteLauncher"></Parameters><Parameters Name="UseRemoteLauncher">False</Parameters><Parameters Name="RemoteCWD"></Parameters><Parameters Name="RemoteDebug">False</Parameters><Parameters Name="Debug Symbols Search Path"></Parameters><Parameters Name="LoadAllSymbols">True</Parameters><Parameters Name="LoadUnspecifiedSymbols">False</Parameters></Parameters><Excluded_Packages>

+      

+      

+      <Excluded_Packages Name="$(BDS)\bin\bcboffice2k100.bpl">CodeGear C++Builder Office 2000 Servers Package</Excluded_Packages>

+      <Excluded_Packages Name="$(BDS)\bin\bcbofficexp100.bpl">CodeGear C++Builder Office XP Servers Package</Excluded_Packages>

+    </Excluded_Packages><Linker><Linker Name="LibPrefix"></Linker><Linker Name="LibSuffix"></Linker><Linker Name="LibVersion"></Linker></Linker><ProjectProperties><ProjectProperties Name="AutoShowDeps">False</ProjectProperties><ProjectProperties Name="ManagePaths">True</ProjectProperties><ProjectProperties Name="VerifyPackages">True</ProjectProperties></ProjectProperties><HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Count">3</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item0">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\include;..\test;..</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item1">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\include;..\test</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item2">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\include</HistoryLists_hlIncludePath></HistoryLists_hlIncludePath><HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Count">1</HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Item0">$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk;..\test</HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Item1">$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk;..\test</HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Item2">$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk;$(OUTPUTDIR);..\test</HistoryLists_hlILINK_LibraryPath></HistoryLists_hlILINK_LibraryPath><HistoryLists_hlDefines><HistoryLists_hlDefines Name="Count">2</HistoryLists_hlDefines><HistoryLists_hlDefines Name="Item0">NO_STRICT</HistoryLists_hlDefines><HistoryLists_hlDefines Name="Item1">STRICT</HistoryLists_hlDefines></HistoryLists_hlDefines></CPlusPlusBuilder.Personality></BorlandProject></BorlandProject>

+  </ProjectExtensions>

+  <Import Project="$(MSBuildBinPath)\Borland.Cpp.Targets" />

+  <ItemGroup>

+    <CppCompile Include="..\test\gtest_unittest.cc">

+      <BuildOrder>0</BuildOrder>

+    </CppCompile>

+    <CppCompile Include="gtest_link.cc">

+      <BuildOrder>1</BuildOrder>

+    </CppCompile>

+    <BuildConfiguration Include="Debug">

+      <Key>Cfg_1</Key>

+    </BuildConfiguration>

+    <BuildConfiguration Include="Release">

+      <Key>Cfg_2</Key>

+    </BuildConfiguration>

+  </ItemGroup>

+</Project>
\ No newline at end of file
diff --git a/third_party/googletest/googletest/configure.ac b/third_party/googletest/googletest/configure.ac
new file mode 100644
index 0000000..cc592e1
--- /dev/null
+++ b/third_party/googletest/googletest/configure.ac
@@ -0,0 +1,68 @@
+m4_include(m4/acx_pthread.m4)
+
+# At this point, the Xcode project assumes the version string will be three
+# integers separated by periods and surrounded by square brackets (e.g.
+# "[1.0.1]"). It also asumes that there won't be any closing parenthesis
+# between "AC_INIT(" and the closing ")" including comments and strings.
+AC_INIT([Google C++ Testing Framework],
+        [1.7.0],
+        [googletestframework@googlegroups.com],
+        [gtest])
+
+# Provide various options to initialize the Autoconf and configure processes.
+AC_PREREQ([2.59])
+AC_CONFIG_SRCDIR([./LICENSE])
+AC_CONFIG_MACRO_DIR([m4])
+AC_CONFIG_AUX_DIR([build-aux])
+AC_CONFIG_HEADERS([build-aux/config.h])
+AC_CONFIG_FILES([Makefile])
+AC_CONFIG_FILES([scripts/gtest-config], [chmod +x scripts/gtest-config])
+
+# Initialize Automake with various options. We require at least v1.9, prevent
+# pedantic complaints about package files, and enable various distribution
+# targets.
+AM_INIT_AUTOMAKE([1.9 dist-bzip2 dist-zip foreign subdir-objects])
+
+# Check for programs used in building Google Test.
+AC_PROG_CC
+AC_PROG_CXX
+AC_LANG([C++])
+AC_PROG_LIBTOOL
+
+# TODO(chandlerc@google.com): Currently we aren't running the Python tests
+# against the interpreter detected by AM_PATH_PYTHON, and so we condition
+# HAVE_PYTHON by requiring "python" to be in the PATH, and that interpreter's
+# version to be >= 2.3. This will allow the scripts to use a "/usr/bin/env"
+# hashbang.
+PYTHON=  # We *do not* allow the user to specify a python interpreter
+AC_PATH_PROG([PYTHON],[python],[:])
+AS_IF([test "$PYTHON" != ":"],
+      [AM_PYTHON_CHECK_VERSION([$PYTHON],[2.3],[:],[PYTHON=":"])])
+AM_CONDITIONAL([HAVE_PYTHON],[test "$PYTHON" != ":"])
+
+# Configure pthreads.
+AC_ARG_WITH([pthreads],
+            [AS_HELP_STRING([--with-pthreads],
+               [use pthreads (default is yes)])],
+            [with_pthreads=$withval],
+            [with_pthreads=check])
+
+have_pthreads=no
+AS_IF([test "x$with_pthreads" != "xno"],
+      [ACX_PTHREAD(
+        [],
+        [AS_IF([test "x$with_pthreads" != "xcheck"],
+               [AC_MSG_FAILURE(
+                 [--with-pthreads was specified, but unable to be used])])])
+       have_pthreads="$acx_pthread_ok"])
+AM_CONDITIONAL([HAVE_PTHREADS],[test "x$have_pthreads" = "xyes"])
+AC_SUBST(PTHREAD_CFLAGS)
+AC_SUBST(PTHREAD_LIBS)
+
+# TODO(chandlerc@google.com) Check for the necessary system headers.
+
+# TODO(chandlerc@google.com) Check the types, structures, and other compiler
+# and architecture characteristics.
+
+# Output the generated files. No further autoconf macros may be used.
+AC_OUTPUT
diff --git a/third_party/googletest/googletest/docs/AdvancedGuide.md b/third_party/googletest/googletest/docs/AdvancedGuide.md
new file mode 100644
index 0000000..576efc3
--- /dev/null
+++ b/third_party/googletest/googletest/docs/AdvancedGuide.md
@@ -0,0 +1,2183 @@
+
+
+Now that you have read [Primer](Primer.md) and learned how to write tests
+using Google Test, it's time to learn some new tricks. This document
+will show you more assertions as well as how to construct complex
+failure messages, propagate fatal failures, reuse and speed up your
+test fixtures, and use various flags with your tests.
+
+# More Assertions #
+
+This section covers some less frequently used, but still significant,
+assertions.
+
+## Explicit Success and Failure ##
+
+These three assertions do not actually test a value or expression. Instead,
+they generate a success or failure directly. Like the macros that actually
+perform a test, you may stream a custom failure message into the them.
+
+| `SUCCEED();` |
+|:-------------|
+
+Generates a success. This does NOT make the overall test succeed. A test is
+considered successful only if none of its assertions fail during its execution.
+
+Note: `SUCCEED()` is purely documentary and currently doesn't generate any
+user-visible output. However, we may add `SUCCEED()` messages to Google Test's
+output in the future.
+
+| `FAIL();`  | `ADD_FAILURE();` | `ADD_FAILURE_AT("`_file\_path_`", `_line\_number_`);` |
+|:-----------|:-----------------|:------------------------------------------------------|
+
+`FAIL()` generates a fatal failure, while `ADD_FAILURE()` and `ADD_FAILURE_AT()` generate a nonfatal
+failure. These are useful when control flow, rather than a Boolean expression,
+deteremines the test's success or failure. For example, you might want to write
+something like:
+
+```
+switch(expression) {
+  case 1: ... some checks ...
+  case 2: ... some other checks
+  ...
+  default: FAIL() << "We shouldn't get here.";
+}
+```
+
+Note: you can only use `FAIL()` in functions that return `void`. See the [Assertion Placement section](#Assertion_Placement.md) for more information.
+
+_Availability_: Linux, Windows, Mac.
+
+## Exception Assertions ##
+
+These are for verifying that a piece of code throws (or does not
+throw) an exception of the given type:
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_THROW(`_statement_, _exception\_type_`);`  | `EXPECT_THROW(`_statement_, _exception\_type_`);`  | _statement_ throws an exception of the given type  |
+| `ASSERT_ANY_THROW(`_statement_`);`                | `EXPECT_ANY_THROW(`_statement_`);`                | _statement_ throws an exception of any type        |
+| `ASSERT_NO_THROW(`_statement_`);`                 | `EXPECT_NO_THROW(`_statement_`);`                 | _statement_ doesn't throw any exception            |
+
+Examples:
+
+```
+ASSERT_THROW(Foo(5), bar_exception);
+
+EXPECT_NO_THROW({
+  int n = 5;
+  Bar(&n);
+});
+```
+
+_Availability_: Linux, Windows, Mac; since version 1.1.0.
+
+## Predicate Assertions for Better Error Messages ##
+
+Even though Google Test has a rich set of assertions, they can never be
+complete, as it's impossible (nor a good idea) to anticipate all the scenarios
+a user might run into. Therefore, sometimes a user has to use `EXPECT_TRUE()`
+to check a complex expression, for lack of a better macro. This has the problem
+of not showing you the values of the parts of the expression, making it hard to
+understand what went wrong. As a workaround, some users choose to construct the
+failure message by themselves, streaming it into `EXPECT_TRUE()`. However, this
+is awkward especially when the expression has side-effects or is expensive to
+evaluate.
+
+Google Test gives you three different options to solve this problem:
+
+### Using an Existing Boolean Function ###
+
+If you already have a function or a functor that returns `bool` (or a type
+that can be implicitly converted to `bool`), you can use it in a _predicate
+assertion_ to get the function arguments printed for free:
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_PRED1(`_pred1, val1_`);`       | `EXPECT_PRED1(`_pred1, val1_`);` | _pred1(val1)_ returns true |
+| `ASSERT_PRED2(`_pred2, val1, val2_`);` | `EXPECT_PRED2(`_pred2, val1, val2_`);` |  _pred2(val1, val2)_ returns true |
+|  ...                | ...                    | ...          |
+
+In the above, _predn_ is an _n_-ary predicate function or functor, where
+_val1_, _val2_, ..., and _valn_ are its arguments. The assertion succeeds
+if the predicate returns `true` when applied to the given arguments, and fails
+otherwise. When the assertion fails, it prints the value of each argument. In
+either case, the arguments are evaluated exactly once.
+
+Here's an example. Given
+
+```
+// Returns true iff m and n have no common divisors except 1.
+bool MutuallyPrime(int m, int n) { ... }
+const int a = 3;
+const int b = 4;
+const int c = 10;
+```
+
+the assertion `EXPECT_PRED2(MutuallyPrime, a, b);` will succeed, while the
+assertion `EXPECT_PRED2(MutuallyPrime, b, c);` will fail with the message
+
+<pre>
+!MutuallyPrime(b, c) is false, where<br>
+b is 4<br>
+c is 10<br>
+</pre>
+
+**Notes:**
+
+  1. If you see a compiler error "no matching function to call" when using `ASSERT_PRED*` or `EXPECT_PRED*`, please see [this](http://code.google.com/p/googletest/wiki/FAQ#The_compiler_complains_%22no_matching_function_to_call%22) for how to resolve it.
+  1. Currently we only provide predicate assertions of arity <= 5. If you need a higher-arity assertion, let us know.
+
+_Availability_: Linux, Windows, Mac
+
+### Using a Function That Returns an AssertionResult ###
+
+While `EXPECT_PRED*()` and friends are handy for a quick job, the
+syntax is not satisfactory: you have to use different macros for
+different arities, and it feels more like Lisp than C++.  The
+`::testing::AssertionResult` class solves this problem.
+
+An `AssertionResult` object represents the result of an assertion
+(whether it's a success or a failure, and an associated message).  You
+can create an `AssertionResult` using one of these factory
+functions:
+
+```
+namespace testing {
+
+// Returns an AssertionResult object to indicate that an assertion has
+// succeeded.
+AssertionResult AssertionSuccess();
+
+// Returns an AssertionResult object to indicate that an assertion has
+// failed.
+AssertionResult AssertionFailure();
+
+}
+```
+
+You can then use the `<<` operator to stream messages to the
+`AssertionResult` object.
+
+To provide more readable messages in Boolean assertions
+(e.g. `EXPECT_TRUE()`), write a predicate function that returns
+`AssertionResult` instead of `bool`. For example, if you define
+`IsEven()` as:
+
+```
+::testing::AssertionResult IsEven(int n) {
+  if ((n % 2) == 0)
+    return ::testing::AssertionSuccess();
+  else
+    return ::testing::AssertionFailure() << n << " is odd";
+}
+```
+
+instead of:
+
+```
+bool IsEven(int n) {
+  return (n % 2) == 0;
+}
+```
+
+the failed assertion `EXPECT_TRUE(IsEven(Fib(4)))` will print:
+
+<pre>
+Value of: IsEven(Fib(4))<br>
+Actual: false (*3 is odd*)<br>
+Expected: true<br>
+</pre>
+
+instead of a more opaque
+
+<pre>
+Value of: IsEven(Fib(4))<br>
+Actual: false<br>
+Expected: true<br>
+</pre>
+
+If you want informative messages in `EXPECT_FALSE` and `ASSERT_FALSE`
+as well, and are fine with making the predicate slower in the success
+case, you can supply a success message:
+
+```
+::testing::AssertionResult IsEven(int n) {
+  if ((n % 2) == 0)
+    return ::testing::AssertionSuccess() << n << " is even";
+  else
+    return ::testing::AssertionFailure() << n << " is odd";
+}
+```
+
+Then the statement `EXPECT_FALSE(IsEven(Fib(6)))` will print
+
+<pre>
+Value of: IsEven(Fib(6))<br>
+Actual: true (8 is even)<br>
+Expected: false<br>
+</pre>
+
+_Availability_: Linux, Windows, Mac; since version 1.4.1.
+
+### Using a Predicate-Formatter ###
+
+If you find the default message generated by `(ASSERT|EXPECT)_PRED*` and
+`(ASSERT|EXPECT)_(TRUE|FALSE)` unsatisfactory, or some arguments to your
+predicate do not support streaming to `ostream`, you can instead use the
+following _predicate-formatter assertions_ to _fully_ customize how the
+message is formatted:
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_PRED_FORMAT1(`_pred\_format1, val1_`);`        | `EXPECT_PRED_FORMAT1(`_pred\_format1, val1_`); | _pred\_format1(val1)_ is successful |
+| `ASSERT_PRED_FORMAT2(`_pred\_format2, val1, val2_`);` | `EXPECT_PRED_FORMAT2(`_pred\_format2, val1, val2_`);` | _pred\_format2(val1, val2)_ is successful |
+| `...`               | `...`                  | `...`        |
+
+The difference between this and the previous two groups of macros is that instead of
+a predicate, `(ASSERT|EXPECT)_PRED_FORMAT*` take a _predicate-formatter_
+(_pred\_formatn_), which is a function or functor with the signature:
+
+`::testing::AssertionResult PredicateFormattern(const char* `_expr1_`, const char* `_expr2_`, ... const char* `_exprn_`, T1 `_val1_`, T2 `_val2_`, ... Tn `_valn_`);`
+
+where _val1_, _val2_, ..., and _valn_ are the values of the predicate
+arguments, and _expr1_, _expr2_, ..., and _exprn_ are the corresponding
+expressions as they appear in the source code. The types `T1`, `T2`, ..., and
+`Tn` can be either value types or reference types. For example, if an
+argument has type `Foo`, you can declare it as either `Foo` or `const Foo&`,
+whichever is appropriate.
+
+A predicate-formatter returns a `::testing::AssertionResult` object to indicate
+whether the assertion has succeeded or not. The only way to create such an
+object is to call one of these factory functions:
+
+As an example, let's improve the failure message in the previous example, which uses `EXPECT_PRED2()`:
+
+```
+// Returns the smallest prime common divisor of m and n,
+// or 1 when m and n are mutually prime.
+int SmallestPrimeCommonDivisor(int m, int n) { ... }
+
+// A predicate-formatter for asserting that two integers are mutually prime.
+::testing::AssertionResult AssertMutuallyPrime(const char* m_expr,
+                                               const char* n_expr,
+                                               int m,
+                                               int n) {
+  if (MutuallyPrime(m, n))
+    return ::testing::AssertionSuccess();
+ 
+  return ::testing::AssertionFailure()
+      << m_expr << " and " << n_expr << " (" << m << " and " << n
+      << ") are not mutually prime, " << "as they have a common divisor "
+      << SmallestPrimeCommonDivisor(m, n);
+}
+```
+
+With this predicate-formatter, we can use
+
+```
+EXPECT_PRED_FORMAT2(AssertMutuallyPrime, b, c);
+```
+
+to generate the message
+
+<pre>
+b and c (4 and 10) are not mutually prime, as they have a common divisor 2.<br>
+</pre>
+
+As you may have realized, many of the assertions we introduced earlier are
+special cases of `(EXPECT|ASSERT)_PRED_FORMAT*`. In fact, most of them are
+indeed defined using `(EXPECT|ASSERT)_PRED_FORMAT*`.
+
+_Availability_: Linux, Windows, Mac.
+
+
+## Floating-Point Comparison ##
+
+Comparing floating-point numbers is tricky. Due to round-off errors, it is
+very unlikely that two floating-points will match exactly. Therefore,
+`ASSERT_EQ` 's naive comparison usually doesn't work. And since floating-points
+can have a wide value range, no single fixed error bound works. It's better to
+compare by a fixed relative error bound, except for values close to 0 due to
+the loss of precision there.
+
+In general, for floating-point comparison to make sense, the user needs to
+carefully choose the error bound. If they don't want or care to, comparing in
+terms of Units in the Last Place (ULPs) is a good default, and Google Test
+provides assertions to do this. Full details about ULPs are quite long; if you
+want to learn more, see
+[this article on float comparison](http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm).
+
+### Floating-Point Macros ###
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_FLOAT_EQ(`_expected, actual_`);`  | `EXPECT_FLOAT_EQ(`_expected, actual_`);` | the two `float` values are almost equal |
+| `ASSERT_DOUBLE_EQ(`_expected, actual_`);` | `EXPECT_DOUBLE_EQ(`_expected, actual_`);` | the two `double` values are almost equal |
+
+By "almost equal", we mean the two values are within 4 ULP's from each
+other.
+
+The following assertions allow you to choose the acceptable error bound:
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_NEAR(`_val1, val2, abs\_error_`);` | `EXPECT_NEAR`_(val1, val2, abs\_error_`);` | the difference between _val1_ and _val2_ doesn't exceed the given absolute error |
+
+_Availability_: Linux, Windows, Mac.
+
+### Floating-Point Predicate-Format Functions ###
+
+Some floating-point operations are useful, but not that often used. In order
+to avoid an explosion of new macros, we provide them as predicate-format
+functions that can be used in predicate assertion macros (e.g.
+`EXPECT_PRED_FORMAT2`, etc).
+
+```
+EXPECT_PRED_FORMAT2(::testing::FloatLE, val1, val2);
+EXPECT_PRED_FORMAT2(::testing::DoubleLE, val1, val2);
+```
+
+Verifies that _val1_ is less than, or almost equal to, _val2_. You can
+replace `EXPECT_PRED_FORMAT2` in the above table with `ASSERT_PRED_FORMAT2`.
+
+_Availability_: Linux, Windows, Mac.
+
+## Windows HRESULT assertions ##
+
+These assertions test for `HRESULT` success or failure.
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_HRESULT_SUCCEEDED(`_expression_`);` | `EXPECT_HRESULT_SUCCEEDED(`_expression_`);` | _expression_ is a success `HRESULT` |
+| `ASSERT_HRESULT_FAILED(`_expression_`);`    | `EXPECT_HRESULT_FAILED(`_expression_`);`    | _expression_ is a failure `HRESULT` |
+
+The generated output contains the human-readable error message
+associated with the `HRESULT` code returned by _expression_.
+
+You might use them like this:
+
+```
+CComPtr shell;
+ASSERT_HRESULT_SUCCEEDED(shell.CoCreateInstance(L"Shell.Application"));
+CComVariant empty;
+ASSERT_HRESULT_SUCCEEDED(shell->ShellExecute(CComBSTR(url), empty, empty, empty, empty));
+```
+
+_Availability_: Windows.
+
+## Type Assertions ##
+
+You can call the function
+```
+::testing::StaticAssertTypeEq<T1, T2>();
+```
+to assert that types `T1` and `T2` are the same.  The function does
+nothing if the assertion is satisfied.  If the types are different,
+the function call will fail to compile, and the compiler error message
+will likely (depending on the compiler) show you the actual values of
+`T1` and `T2`.  This is mainly useful inside template code.
+
+_Caveat:_ When used inside a member function of a class template or a
+function template, `StaticAssertTypeEq<T1, T2>()` is effective _only if_
+the function is instantiated.  For example, given:
+```
+template <typename T> class Foo {
+ public:
+  void Bar() { ::testing::StaticAssertTypeEq<int, T>(); }
+};
+```
+the code:
+```
+void Test1() { Foo<bool> foo; }
+```
+will _not_ generate a compiler error, as `Foo<bool>::Bar()` is never
+actually instantiated.  Instead, you need:
+```
+void Test2() { Foo<bool> foo; foo.Bar(); }
+```
+to cause a compiler error.
+
+_Availability:_ Linux, Windows, Mac; since version 1.3.0.
+
+## Assertion Placement ##
+
+You can use assertions in any C++ function. In particular, it doesn't
+have to be a method of the test fixture class. The one constraint is
+that assertions that generate a fatal failure (`FAIL*` and `ASSERT_*`)
+can only be used in void-returning functions. This is a consequence of
+Google Test not using exceptions. By placing it in a non-void function
+you'll get a confusing compile error like
+`"error: void value not ignored as it ought to be"`.
+
+If you need to use assertions in a function that returns non-void, one option
+is to make the function return the value in an out parameter instead. For
+example, you can rewrite `T2 Foo(T1 x)` to `void Foo(T1 x, T2* result)`. You
+need to make sure that `*result` contains some sensible value even when the
+function returns prematurely. As the function now returns `void`, you can use
+any assertion inside of it.
+
+If changing the function's type is not an option, you should just use
+assertions that generate non-fatal failures, such as `ADD_FAILURE*` and
+`EXPECT_*`.
+
+_Note_: Constructors and destructors are not considered void-returning
+functions, according to the C++ language specification, and so you may not use
+fatal assertions in them. You'll get a compilation error if you try. A simple
+workaround is to transfer the entire body of the constructor or destructor to a
+private void-returning method. However, you should be aware that a fatal
+assertion failure in a constructor does not terminate the current test, as your
+intuition might suggest; it merely returns from the constructor early, possibly
+leaving your object in a partially-constructed state. Likewise, a fatal
+assertion failure in a destructor may leave your object in a
+partially-destructed state. Use assertions carefully in these situations!
+
+# Teaching Google Test How to Print Your Values #
+
+When a test assertion such as `EXPECT_EQ` fails, Google Test prints the
+argument values to help you debug.  It does this using a
+user-extensible value printer.
+
+This printer knows how to print built-in C++ types, native arrays, STL
+containers, and any type that supports the `<<` operator.  For other
+types, it prints the raw bytes in the value and hopes that you the
+user can figure it out.
+
+As mentioned earlier, the printer is _extensible_.  That means
+you can teach it to do a better job at printing your particular type
+than to dump the bytes.  To do that, define `<<` for your type:
+
+```
+#include <iostream>
+
+namespace foo {
+
+class Bar { ... };  // We want Google Test to be able to print instances of this.
+
+// It's important that the << operator is defined in the SAME
+// namespace that defines Bar.  C++'s look-up rules rely on that.
+::std::ostream& operator<<(::std::ostream& os, const Bar& bar) {
+  return os << bar.DebugString();  // whatever needed to print bar to os
+}
+
+}  // namespace foo
+```
+
+Sometimes, this might not be an option: your team may consider it bad
+style to have a `<<` operator for `Bar`, or `Bar` may already have a
+`<<` operator that doesn't do what you want (and you cannot change
+it).  If so, you can instead define a `PrintTo()` function like this:
+
+```
+#include <iostream>
+
+namespace foo {
+
+class Bar { ... };
+
+// It's important that PrintTo() is defined in the SAME
+// namespace that defines Bar.  C++'s look-up rules rely on that.
+void PrintTo(const Bar& bar, ::std::ostream* os) {
+  *os << bar.DebugString();  // whatever needed to print bar to os
+}
+
+}  // namespace foo
+```
+
+If you have defined both `<<` and `PrintTo()`, the latter will be used
+when Google Test is concerned.  This allows you to customize how the value
+appears in Google Test's output without affecting code that relies on the
+behavior of its `<<` operator.
+
+If you want to print a value `x` using Google Test's value printer
+yourself, just call `::testing::PrintToString(`_x_`)`, which
+returns an `std::string`:
+
+```
+vector<pair<Bar, int> > bar_ints = GetBarIntVector();
+
+EXPECT_TRUE(IsCorrectBarIntVector(bar_ints))
+    << "bar_ints = " << ::testing::PrintToString(bar_ints);
+```
+
+# Death Tests #
+
+In many applications, there are assertions that can cause application failure
+if a condition is not met. These sanity checks, which ensure that the program
+is in a known good state, are there to fail at the earliest possible time after
+some program state is corrupted. If the assertion checks the wrong condition,
+then the program may proceed in an erroneous state, which could lead to memory
+corruption, security holes, or worse. Hence it is vitally important to test
+that such assertion statements work as expected.
+
+Since these precondition checks cause the processes to die, we call such tests
+_death tests_. More generally, any test that checks that a program terminates
+(except by throwing an exception) in an expected fashion is also a death test.
+
+Note that if a piece of code throws an exception, we don't consider it "death"
+for the purpose of death tests, as the caller of the code could catch the exception
+and avoid the crash. If you want to verify exceptions thrown by your code,
+see [Exception Assertions](#Exception_Assertions.md).
+
+If you want to test `EXPECT_*()/ASSERT_*()` failures in your test code, see [Catching Failures](#Catching_Failures.md).
+
+## How to Write a Death Test ##
+
+Google Test has the following macros to support death tests:
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_DEATH(`_statement, regex_`); | `EXPECT_DEATH(`_statement, regex_`); | _statement_ crashes with the given error |
+| `ASSERT_DEATH_IF_SUPPORTED(`_statement, regex_`); | `EXPECT_DEATH_IF_SUPPORTED(`_statement, regex_`); | if death tests are supported, verifies that _statement_ crashes with the given error; otherwise verifies nothing |
+| `ASSERT_EXIT(`_statement, predicate, regex_`); | `EXPECT_EXIT(`_statement, predicate, regex_`); |_statement_ exits with the given error and its exit code matches _predicate_ |
+
+where _statement_ is a statement that is expected to cause the process to
+die, _predicate_ is a function or function object that evaluates an integer
+exit status, and _regex_ is a regular expression that the stderr output of
+_statement_ is expected to match. Note that _statement_ can be _any valid
+statement_ (including _compound statement_) and doesn't have to be an
+expression.
+
+As usual, the `ASSERT` variants abort the current test function, while the
+`EXPECT` variants do not.
+
+**Note:** We use the word "crash" here to mean that the process
+terminates with a _non-zero_ exit status code.  There are two
+possibilities: either the process has called `exit()` or `_exit()`
+with a non-zero value, or it may be killed by a signal.
+
+This means that if _statement_ terminates the process with a 0 exit
+code, it is _not_ considered a crash by `EXPECT_DEATH`.  Use
+`EXPECT_EXIT` instead if this is the case, or if you want to restrict
+the exit code more precisely.
+
+A predicate here must accept an `int` and return a `bool`. The death test
+succeeds only if the predicate returns `true`. Google Test defines a few
+predicates that handle the most common cases:
+
+```
+::testing::ExitedWithCode(exit_code)
+```
+
+This expression is `true` if the program exited normally with the given exit
+code.
+
+```
+::testing::KilledBySignal(signal_number)  // Not available on Windows.
+```
+
+This expression is `true` if the program was killed by the given signal.
+
+The `*_DEATH` macros are convenient wrappers for `*_EXIT` that use a predicate
+that verifies the process' exit code is non-zero.
+
+Note that a death test only cares about three things:
+
+  1. does _statement_ abort or exit the process?
+  1. (in the case of `ASSERT_EXIT` and `EXPECT_EXIT`) does the exit status satisfy _predicate_?  Or (in the case of `ASSERT_DEATH` and `EXPECT_DEATH`) is the exit status non-zero?  And
+  1. does the stderr output match _regex_?
+
+In particular, if _statement_ generates an `ASSERT_*` or `EXPECT_*` failure, it will **not** cause the death test to fail, as Google Test assertions don't abort the process.
+
+To write a death test, simply use one of the above macros inside your test
+function. For example,
+
+```
+TEST(MyDeathTest, Foo) {
+  // This death test uses a compound statement.
+  ASSERT_DEATH({ int n = 5; Foo(&n); }, "Error on line .* of Foo()");
+}
+TEST(MyDeathTest, NormalExit) {
+  EXPECT_EXIT(NormalExit(), ::testing::ExitedWithCode(0), "Success");
+}
+TEST(MyDeathTest, KillMyself) {
+  EXPECT_EXIT(KillMyself(), ::testing::KilledBySignal(SIGKILL), "Sending myself unblockable signal");
+}
+```
+
+verifies that:
+
+  * calling `Foo(5)` causes the process to die with the given error message,
+  * calling `NormalExit()` causes the process to print `"Success"` to stderr and exit with exit code 0, and
+  * calling `KillMyself()` kills the process with signal `SIGKILL`.
+
+The test function body may contain other assertions and statements as well, if
+necessary.
+
+_Important:_ We strongly recommend you to follow the convention of naming your
+test case (not test) `*DeathTest` when it contains a death test, as
+demonstrated in the above example. The `Death Tests And Threads` section below
+explains why.
+
+If a test fixture class is shared by normal tests and death tests, you
+can use typedef to introduce an alias for the fixture class and avoid
+duplicating its code:
+```
+class FooTest : public ::testing::Test { ... };
+
+typedef FooTest FooDeathTest;
+
+TEST_F(FooTest, DoesThis) {
+  // normal test
+}
+
+TEST_F(FooDeathTest, DoesThat) {
+  // death test
+}
+```
+
+_Availability:_ Linux, Windows (requires MSVC 8.0 or above), Cygwin, and Mac (the latter three are supported since v1.3.0).  `(ASSERT|EXPECT)_DEATH_IF_SUPPORTED` are new in v1.4.0.
+
+## Regular Expression Syntax ##
+
+On POSIX systems (e.g. Linux, Cygwin, and Mac), Google Test uses the
+[POSIX extended regular expression](http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap09.html#tag_09_04)
+syntax in death tests. To learn about this syntax, you may want to read this [Wikipedia entry](http://en.wikipedia.org/wiki/Regular_expression#POSIX_Extended_Regular_Expressions).
+
+On Windows, Google Test uses its own simple regular expression
+implementation. It lacks many features you can find in POSIX extended
+regular expressions.  For example, we don't support union (`"x|y"`),
+grouping (`"(xy)"`), brackets (`"[xy]"`), and repetition count
+(`"x{5,7}"`), among others. Below is what we do support (Letter `A` denotes a
+literal character, period (`.`), or a single `\\` escape sequence; `x`
+and `y` denote regular expressions.):
+
+| `c` | matches any literal character `c` |
+|:----|:----------------------------------|
+| `\\d` | matches any decimal digit         |
+| `\\D` | matches any character that's not a decimal digit |
+| `\\f` | matches `\f`                      |
+| `\\n` | matches `\n`                      |
+| `\\r` | matches `\r`                      |
+| `\\s` | matches any ASCII whitespace, including `\n` |
+| `\\S` | matches any character that's not a whitespace |
+| `\\t` | matches `\t`                      |
+| `\\v` | matches `\v`                      |
+| `\\w` | matches any letter, `_`, or decimal digit |
+| `\\W` | matches any character that `\\w` doesn't match |
+| `\\c` | matches any literal character `c`, which must be a punctuation |
+| `\\.` | matches the `.` character         |
+| `.` | matches any single character except `\n` |
+| `A?` | matches 0 or 1 occurrences of `A` |
+| `A*` | matches 0 or many occurrences of `A` |
+| `A+` | matches 1 or many occurrences of `A` |
+| `^` | matches the beginning of a string (not that of each line) |
+| `$` | matches the end of a string (not that of each line) |
+| `xy` | matches `x` followed by `y`       |
+
+To help you determine which capability is available on your system,
+Google Test defines macro `GTEST_USES_POSIX_RE=1` when it uses POSIX
+extended regular expressions, or `GTEST_USES_SIMPLE_RE=1` when it uses
+the simple version.  If you want your death tests to work in both
+cases, you can either `#if` on these macros or use the more limited
+syntax only.
+
+## How It Works ##
+
+Under the hood, `ASSERT_EXIT()` spawns a new process and executes the
+death test statement in that process. The details of of how precisely
+that happens depend on the platform and the variable
+`::testing::GTEST_FLAG(death_test_style)` (which is initialized from the
+command-line flag `--gtest_death_test_style`).
+
+  * On POSIX systems, `fork()` (or `clone()` on Linux) is used to spawn the child, after which:
+    * If the variable's value is `"fast"`, the death test statement is immediately executed.
+    * If the variable's value is `"threadsafe"`, the child process re-executes the unit test binary just as it was originally invoked, but with some extra flags to cause just the single death test under consideration to be run.
+  * On Windows, the child is spawned using the `CreateProcess()` API, and re-executes the binary to cause just the single death test under consideration to be run - much like the `threadsafe` mode on POSIX.
+
+Other values for the variable are illegal and will cause the death test to
+fail. Currently, the flag's default value is `"fast"`. However, we reserve the
+right to change it in the future. Therefore, your tests should not depend on
+this.
+
+In either case, the parent process waits for the child process to complete, and checks that
+
+  1. the child's exit status satisfies the predicate, and
+  1. the child's stderr matches the regular expression.
+
+If the death test statement runs to completion without dying, the child
+process will nonetheless terminate, and the assertion fails.
+
+## Death Tests And Threads ##
+
+The reason for the two death test styles has to do with thread safety. Due to
+well-known problems with forking in the presence of threads, death tests should
+be run in a single-threaded context. Sometimes, however, it isn't feasible to
+arrange that kind of environment. For example, statically-initialized modules
+may start threads before main is ever reached. Once threads have been created,
+it may be difficult or impossible to clean them up.
+
+Google Test has three features intended to raise awareness of threading issues.
+
+  1. A warning is emitted if multiple threads are running when a death test is encountered.
+  1. Test cases with a name ending in "DeathTest" are run before all other tests.
+  1. It uses `clone()` instead of `fork()` to spawn the child process on Linux (`clone()` is not available on Cygwin and Mac), as `fork()` is more likely to cause the child to hang when the parent process has multiple threads.
+
+It's perfectly fine to create threads inside a death test statement; they are
+executed in a separate process and cannot affect the parent.
+
+## Death Test Styles ##
+
+The "threadsafe" death test style was introduced in order to help mitigate the
+risks of testing in a possibly multithreaded environment. It trades increased
+test execution time (potentially dramatically so) for improved thread safety.
+We suggest using the faster, default "fast" style unless your test has specific
+problems with it.
+
+You can choose a particular style of death tests by setting the flag
+programmatically:
+
+```
+::testing::FLAGS_gtest_death_test_style = "threadsafe";
+```
+
+You can do this in `main()` to set the style for all death tests in the
+binary, or in individual tests. Recall that flags are saved before running each
+test and restored afterwards, so you need not do that yourself. For example:
+
+```
+TEST(MyDeathTest, TestOne) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  // This test is run in the "threadsafe" style:
+  ASSERT_DEATH(ThisShouldDie(), "");
+}
+
+TEST(MyDeathTest, TestTwo) {
+  // This test is run in the "fast" style:
+  ASSERT_DEATH(ThisShouldDie(), "");
+}
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  ::testing::FLAGS_gtest_death_test_style = "fast";
+  return RUN_ALL_TESTS();
+}
+```
+
+## Caveats ##
+
+The _statement_ argument of `ASSERT_EXIT()` can be any valid C++ statement.
+If it leaves the current function via a `return` statement or by throwing an exception,
+the death test is considered to have failed.  Some Google Test macros may return
+from the current function (e.g. `ASSERT_TRUE()`), so be sure to avoid them in _statement_.
+
+Since _statement_ runs in the child process, any in-memory side effect (e.g.
+modifying a variable, releasing memory, etc) it causes will _not_ be observable
+in the parent process. In particular, if you release memory in a death test,
+your program will fail the heap check as the parent process will never see the
+memory reclaimed. To solve this problem, you can
+
+  1. try not to free memory in a death test;
+  1. free the memory again in the parent process; or
+  1. do not use the heap checker in your program.
+
+Due to an implementation detail, you cannot place multiple death test
+assertions on the same line; otherwise, compilation will fail with an unobvious
+error message.
+
+Despite the improved thread safety afforded by the "threadsafe" style of death
+test, thread problems such as deadlock are still possible in the presence of
+handlers registered with `pthread_atfork(3)`.
+
+# Using Assertions in Sub-routines #
+
+## Adding Traces to Assertions ##
+
+If a test sub-routine is called from several places, when an assertion
+inside it fails, it can be hard to tell which invocation of the
+sub-routine the failure is from.  You can alleviate this problem using
+extra logging or custom failure messages, but that usually clutters up
+your tests. A better solution is to use the `SCOPED_TRACE` macro:
+
+| `SCOPED_TRACE(`_message_`);` |
+|:-----------------------------|
+
+where _message_ can be anything streamable to `std::ostream`. This
+macro will cause the current file name, line number, and the given
+message to be added in every failure message. The effect will be
+undone when the control leaves the current lexical scope.
+
+For example,
+
+```
+10: void Sub1(int n) {
+11:   EXPECT_EQ(1, Bar(n));
+12:   EXPECT_EQ(2, Bar(n + 1));
+13: }
+14: 
+15: TEST(FooTest, Bar) {
+16:   {
+17:     SCOPED_TRACE("A");  // This trace point will be included in
+18:                         // every failure in this scope.
+19:     Sub1(1);
+20:   }
+21:   // Now it won't.
+22:   Sub1(9);
+23: }
+```
+
+could result in messages like these:
+
+```
+path/to/foo_test.cc:11: Failure
+Value of: Bar(n)
+Expected: 1
+  Actual: 2
+   Trace:
+path/to/foo_test.cc:17: A
+
+path/to/foo_test.cc:12: Failure
+Value of: Bar(n + 1)
+Expected: 2
+  Actual: 3
+```
+
+Without the trace, it would've been difficult to know which invocation
+of `Sub1()` the two failures come from respectively. (You could add an
+extra message to each assertion in `Sub1()` to indicate the value of
+`n`, but that's tedious.)
+
+Some tips on using `SCOPED_TRACE`:
+
+  1. With a suitable message, it's often enough to use `SCOPED_TRACE` at the beginning of a sub-routine, instead of at each call site.
+  1. When calling sub-routines inside a loop, make the loop iterator part of the message in `SCOPED_TRACE` such that you can know which iteration the failure is from.
+  1. Sometimes the line number of the trace point is enough for identifying the particular invocation of a sub-routine. In this case, you don't have to choose a unique message for `SCOPED_TRACE`. You can simply use `""`.
+  1. You can use `SCOPED_TRACE` in an inner scope when there is one in the outer scope. In this case, all active trace points will be included in the failure messages, in reverse order they are encountered.
+  1. The trace dump is clickable in Emacs' compilation buffer - hit return on a line number and you'll be taken to that line in the source file!
+
+_Availability:_ Linux, Windows, Mac.
+
+## Propagating Fatal Failures ##
+
+A common pitfall when using `ASSERT_*` and `FAIL*` is not understanding that
+when they fail they only abort the _current function_, not the entire test. For
+example, the following test will segfault:
+```
+void Subroutine() {
+  // Generates a fatal failure and aborts the current function.
+  ASSERT_EQ(1, 2);
+  // The following won't be executed.
+  ...
+}
+
+TEST(FooTest, Bar) {
+  Subroutine();
+  // The intended behavior is for the fatal failure
+  // in Subroutine() to abort the entire test.
+  // The actual behavior: the function goes on after Subroutine() returns.
+  int* p = NULL;
+  *p = 3; // Segfault!
+}
+```
+
+Since we don't use exceptions, it is technically impossible to
+implement the intended behavior here.  To alleviate this, Google Test
+provides two solutions.  You could use either the
+`(ASSERT|EXPECT)_NO_FATAL_FAILURE` assertions or the
+`HasFatalFailure()` function.  They are described in the following two
+subsections.
+
+### Asserting on Subroutines ###
+
+As shown above, if your test calls a subroutine that has an `ASSERT_*`
+failure in it, the test will continue after the subroutine
+returns. This may not be what you want.
+
+Often people want fatal failures to propagate like exceptions.  For
+that Google Test offers the following macros:
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_NO_FATAL_FAILURE(`_statement_`);` | `EXPECT_NO_FATAL_FAILURE(`_statement_`);` | _statement_ doesn't generate any new fatal failures in the current thread. |
+
+Only failures in the thread that executes the assertion are checked to
+determine the result of this type of assertions.  If _statement_
+creates new threads, failures in these threads are ignored.
+
+Examples:
+
+```
+ASSERT_NO_FATAL_FAILURE(Foo());
+
+int i;
+EXPECT_NO_FATAL_FAILURE({
+  i = Bar();
+});
+```
+
+_Availability:_ Linux, Windows, Mac. Assertions from multiple threads
+are currently not supported.
+
+### Checking for Failures in the Current Test ###
+
+`HasFatalFailure()` in the `::testing::Test` class returns `true` if an
+assertion in the current test has suffered a fatal failure. This
+allows functions to catch fatal failures in a sub-routine and return
+early.
+
+```
+class Test {
+ public:
+  ...
+  static bool HasFatalFailure();
+};
+```
+
+The typical usage, which basically simulates the behavior of a thrown
+exception, is:
+
+```
+TEST(FooTest, Bar) {
+  Subroutine();
+  // Aborts if Subroutine() had a fatal failure.
+  if (HasFatalFailure())
+    return;
+  // The following won't be executed.
+  ...
+}
+```
+
+If `HasFatalFailure()` is used outside of `TEST()` , `TEST_F()` , or a test
+fixture, you must add the `::testing::Test::` prefix, as in:
+
+```
+if (::testing::Test::HasFatalFailure())
+  return;
+```
+
+Similarly, `HasNonfatalFailure()` returns `true` if the current test
+has at least one non-fatal failure, and `HasFailure()` returns `true`
+if the current test has at least one failure of either kind.
+
+_Availability:_ Linux, Windows, Mac.  `HasNonfatalFailure()` and
+`HasFailure()` are available since version 1.4.0.
+
+# Logging Additional Information #
+
+In your test code, you can call `RecordProperty("key", value)` to log
+additional information, where `value` can be either a string or an `int`. The _last_ value recorded for a key will be emitted to the XML output
+if you specify one. For example, the test
+
+```
+TEST_F(WidgetUsageTest, MinAndMaxWidgets) {
+  RecordProperty("MaximumWidgets", ComputeMaxUsage());
+  RecordProperty("MinimumWidgets", ComputeMinUsage());
+}
+```
+
+will output XML like this:
+
+```
+...
+  <testcase name="MinAndMaxWidgets" status="run" time="6" classname="WidgetUsageTest"
+            MaximumWidgets="12"
+            MinimumWidgets="9" />
+...
+```
+
+_Note_:
+  * `RecordProperty()` is a static member of the `Test` class. Therefore it needs to be prefixed with `::testing::Test::` if used outside of the `TEST` body and the test fixture class.
+  * `key` must be a valid XML attribute name, and cannot conflict with the ones already used by Google Test (`name`, `status`, `time`, `classname`, `type_param`, and `value_param`).
+  * Calling `RecordProperty()` outside of the lifespan of a test is allowed. If it's called outside of a test but between a test case's `SetUpTestCase()` and `TearDownTestCase()` methods, it will be attributed to the XML element for the test case. If it's called outside of all test cases (e.g. in a test environment), it will be attributed to the top-level XML element.
+
+_Availability_: Linux, Windows, Mac.
+
+# Sharing Resources Between Tests in the Same Test Case #
+
+
+
+Google Test creates a new test fixture object for each test in order to make
+tests independent and easier to debug. However, sometimes tests use resources
+that are expensive to set up, making the one-copy-per-test model prohibitively
+expensive.
+
+If the tests don't change the resource, there's no harm in them sharing a
+single resource copy. So, in addition to per-test set-up/tear-down, Google Test
+also supports per-test-case set-up/tear-down. To use it:
+
+  1. In your test fixture class (say `FooTest` ), define as `static` some member variables to hold the shared resources.
+  1. In the same test fixture class, define a `static void SetUpTestCase()` function (remember not to spell it as **`SetupTestCase`** with a small `u`!) to set up the shared resources and a `static void TearDownTestCase()` function to tear them down.
+
+That's it! Google Test automatically calls `SetUpTestCase()` before running the
+_first test_ in the `FooTest` test case (i.e. before creating the first
+`FooTest` object), and calls `TearDownTestCase()` after running the _last test_
+in it (i.e. after deleting the last `FooTest` object). In between, the tests
+can use the shared resources.
+
+Remember that the test order is undefined, so your code can't depend on a test
+preceding or following another. Also, the tests must either not modify the
+state of any shared resource, or, if they do modify the state, they must
+restore the state to its original value before passing control to the next
+test.
+
+Here's an example of per-test-case set-up and tear-down:
+```
+class FooTest : public ::testing::Test {
+ protected:
+  // Per-test-case set-up.
+  // Called before the first test in this test case.
+  // Can be omitted if not needed.
+  static void SetUpTestCase() {
+    shared_resource_ = new ...;
+  }
+
+  // Per-test-case tear-down.
+  // Called after the last test in this test case.
+  // Can be omitted if not needed.
+  static void TearDownTestCase() {
+    delete shared_resource_;
+    shared_resource_ = NULL;
+  }
+
+  // You can define per-test set-up and tear-down logic as usual.
+  virtual void SetUp() { ... }
+  virtual void TearDown() { ... }
+
+  // Some expensive resource shared by all tests.
+  static T* shared_resource_;
+};
+
+T* FooTest::shared_resource_ = NULL;
+
+TEST_F(FooTest, Test1) {
+  ... you can refer to shared_resource here ...
+}
+TEST_F(FooTest, Test2) {
+  ... you can refer to shared_resource here ...
+}
+```
+
+_Availability:_ Linux, Windows, Mac.
+
+# Global Set-Up and Tear-Down #
+
+Just as you can do set-up and tear-down at the test level and the test case
+level, you can also do it at the test program level. Here's how.
+
+First, you subclass the `::testing::Environment` class to define a test
+environment, which knows how to set-up and tear-down:
+
+```
+class Environment {
+ public:
+  virtual ~Environment() {}
+  // Override this to define how to set up the environment.
+  virtual void SetUp() {}
+  // Override this to define how to tear down the environment.
+  virtual void TearDown() {}
+};
+```
+
+Then, you register an instance of your environment class with Google Test by
+calling the `::testing::AddGlobalTestEnvironment()` function:
+
+```
+Environment* AddGlobalTestEnvironment(Environment* env);
+```
+
+Now, when `RUN_ALL_TESTS()` is called, it first calls the `SetUp()` method of
+the environment object, then runs the tests if there was no fatal failures, and
+finally calls `TearDown()` of the environment object.
+
+It's OK to register multiple environment objects. In this case, their `SetUp()`
+will be called in the order they are registered, and their `TearDown()` will be
+called in the reverse order.
+
+Note that Google Test takes ownership of the registered environment objects.
+Therefore **do not delete them** by yourself.
+
+You should call `AddGlobalTestEnvironment()` before `RUN_ALL_TESTS()` is
+called, probably in `main()`. If you use `gtest_main`, you need to      call
+this before `main()` starts for it to take effect. One way to do this is to
+define a global variable like this:
+
+```
+::testing::Environment* const foo_env = ::testing::AddGlobalTestEnvironment(new FooEnvironment);
+```
+
+However, we strongly recommend you to write your own `main()` and call
+`AddGlobalTestEnvironment()` there, as relying on initialization of global
+variables makes the code harder to read and may cause problems when you
+register multiple environments from different translation units and the
+environments have dependencies among them (remember that the compiler doesn't
+guarantee the order in which global variables from different translation units
+are initialized).
+
+_Availability:_ Linux, Windows, Mac.
+
+
+# Value Parameterized Tests #
+
+_Value-parameterized tests_ allow you to test your code with different
+parameters without writing multiple copies of the same test.
+
+Suppose you write a test for your code and then realize that your code is affected by a presence of a Boolean command line flag.
+
+```
+TEST(MyCodeTest, TestFoo) {
+  // A code to test foo().
+}
+```
+
+Usually people factor their test code into a function with a Boolean parameter in such situations. The function sets the flag, then executes the testing code.
+
+```
+void TestFooHelper(bool flag_value) {
+  flag = flag_value;
+  // A code to test foo().
+}
+
+TEST(MyCodeTest, TestFoo) {
+  TestFooHelper(false);
+  TestFooHelper(true);
+}
+```
+
+But this setup has serious drawbacks. First, when a test assertion fails in your tests, it becomes unclear what value of the parameter caused it to fail. You can stream a clarifying message into your `EXPECT`/`ASSERT` statements, but it you'll have to do it with all of them. Second, you have to add one such helper function per test. What if you have ten tests? Twenty? A hundred?
+
+Value-parameterized tests will let you write your test only once and then easily instantiate and run it with an arbitrary number of parameter values.
+
+Here are some other situations when value-parameterized tests come handy:
+
+  * You want to test different implementations of an OO interface.
+  * You want to test your code over various inputs (a.k.a. data-driven testing). This feature is easy to abuse, so please exercise your good sense when doing it!
+
+## How to Write Value-Parameterized Tests ##
+
+To write value-parameterized tests, first you should define a fixture
+class.  It must be derived from both `::testing::Test` and
+`::testing::WithParamInterface<T>` (the latter is a pure interface),
+where `T` is the type of your parameter values.  For convenience, you
+can just derive the fixture class from `::testing::TestWithParam<T>`,
+which itself is derived from both `::testing::Test` and
+`::testing::WithParamInterface<T>`. `T` can be any copyable type. If
+it's a raw pointer, you are responsible for managing the lifespan of
+the pointed values.
+
+```
+class FooTest : public ::testing::TestWithParam<const char*> {
+  // You can implement all the usual fixture class members here.
+  // To access the test parameter, call GetParam() from class
+  // TestWithParam<T>.
+};
+
+// Or, when you want to add parameters to a pre-existing fixture class:
+class BaseTest : public ::testing::Test {
+  ...
+};
+class BarTest : public BaseTest,
+                public ::testing::WithParamInterface<const char*> {
+  ...
+};
+```
+
+Then, use the `TEST_P` macro to define as many test patterns using
+this fixture as you want.  The `_P` suffix is for "parameterized" or
+"pattern", whichever you prefer to think.
+
+```
+TEST_P(FooTest, DoesBlah) {
+  // Inside a test, access the test parameter with the GetParam() method
+  // of the TestWithParam<T> class:
+  EXPECT_TRUE(foo.Blah(GetParam()));
+  ...
+}
+
+TEST_P(FooTest, HasBlahBlah) {
+  ...
+}
+```
+
+Finally, you can use `INSTANTIATE_TEST_CASE_P` to instantiate the test
+case with any set of parameters you want. Google Test defines a number of
+functions for generating test parameters. They return what we call
+(surprise!) _parameter generators_. Here is a summary of them,
+which are all in the `testing` namespace:
+
+| `Range(begin, end[, step])` | Yields values `{begin, begin+step, begin+step+step, ...}`. The values do not include `end`. `step` defaults to 1. |
+|:----------------------------|:------------------------------------------------------------------------------------------------------------------|
+| `Values(v1, v2, ..., vN)`   | Yields values `{v1, v2, ..., vN}`.                                                                                |
+| `ValuesIn(container)` and `ValuesIn(begin, end)` | Yields values from a C-style array, an STL-style container, or an iterator range `[begin, end)`. `container`, `begin`, and `end` can be expressions whose values are determined at run time.  |
+| `Bool()`                    | Yields sequence `{false, true}`.                                                                                  |
+| `Combine(g1, g2, ..., gN)`  | Yields all combinations (the Cartesian product for the math savvy) of the values generated by the `N` generators. This is only available if your system provides the `<tr1/tuple>` header. If you are sure your system does, and Google Test disagrees, you can override it by defining `GTEST_HAS_TR1_TUPLE=1`. See comments in [include/gtest/internal/gtest-port.h](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/internal/gtest-port.h) for more information. |
+
+For more details, see the comments at the definitions of these functions in the [source code](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest-param-test.h).
+
+The following statement will instantiate tests from the `FooTest` test case
+each with parameter values `"meeny"`, `"miny"`, and `"moe"`.
+
+```
+INSTANTIATE_TEST_CASE_P(InstantiationName,
+                        FooTest,
+                        ::testing::Values("meeny", "miny", "moe"));
+```
+
+To distinguish different instances of the pattern (yes, you can
+instantiate it more than once), the first argument to
+`INSTANTIATE_TEST_CASE_P` is a prefix that will be added to the actual
+test case name. Remember to pick unique prefixes for different
+instantiations. The tests from the instantiation above will have these
+names:
+
+  * `InstantiationName/FooTest.DoesBlah/0` for `"meeny"`
+  * `InstantiationName/FooTest.DoesBlah/1` for `"miny"`
+  * `InstantiationName/FooTest.DoesBlah/2` for `"moe"`
+  * `InstantiationName/FooTest.HasBlahBlah/0` for `"meeny"`
+  * `InstantiationName/FooTest.HasBlahBlah/1` for `"miny"`
+  * `InstantiationName/FooTest.HasBlahBlah/2` for `"moe"`
+
+You can use these names in [--gtest\_filter](#Running_a_Subset_of_the_Tests.md).
+
+This statement will instantiate all tests from `FooTest` again, each
+with parameter values `"cat"` and `"dog"`:
+
+```
+const char* pets[] = {"cat", "dog"};
+INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest,
+                        ::testing::ValuesIn(pets));
+```
+
+The tests from the instantiation above will have these names:
+
+  * `AnotherInstantiationName/FooTest.DoesBlah/0` for `"cat"`
+  * `AnotherInstantiationName/FooTest.DoesBlah/1` for `"dog"`
+  * `AnotherInstantiationName/FooTest.HasBlahBlah/0` for `"cat"`
+  * `AnotherInstantiationName/FooTest.HasBlahBlah/1` for `"dog"`
+
+Please note that `INSTANTIATE_TEST_CASE_P` will instantiate _all_
+tests in the given test case, whether their definitions come before or
+_after_ the `INSTANTIATE_TEST_CASE_P` statement.
+
+You can see
+[these](http://code.google.com/p/googletest/source/browse/trunk/samples/sample7_unittest.cc)
+[files](http://code.google.com/p/googletest/source/browse/trunk/samples/sample8_unittest.cc) for more examples.
+
+_Availability_: Linux, Windows (requires MSVC 8.0 or above), Mac; since version 1.2.0.
+
+## Creating Value-Parameterized Abstract Tests ##
+
+In the above, we define and instantiate `FooTest` in the same source
+file. Sometimes you may want to define value-parameterized tests in a
+library and let other people instantiate them later. This pattern is
+known as <i>abstract tests</i>. As an example of its application, when you
+are designing an interface you can write a standard suite of abstract
+tests (perhaps using a factory function as the test parameter) that
+all implementations of the interface are expected to pass. When
+someone implements the interface, he can instantiate your suite to get
+all the interface-conformance tests for free.
+
+To define abstract tests, you should organize your code like this:
+
+  1. Put the definition of the parameterized test fixture class (e.g. `FooTest`) in a header file, say `foo_param_test.h`. Think of this as _declaring_ your abstract tests.
+  1. Put the `TEST_P` definitions in `foo_param_test.cc`, which includes `foo_param_test.h`. Think of this as _implementing_ your abstract tests.
+
+Once they are defined, you can instantiate them by including
+`foo_param_test.h`, invoking `INSTANTIATE_TEST_CASE_P()`, and linking
+with `foo_param_test.cc`. You can instantiate the same abstract test
+case multiple times, possibly in different source files.
+
+# Typed Tests #
+
+Suppose you have multiple implementations of the same interface and
+want to make sure that all of them satisfy some common requirements.
+Or, you may have defined several types that are supposed to conform to
+the same "concept" and you want to verify it.  In both cases, you want
+the same test logic repeated for different types.
+
+While you can write one `TEST` or `TEST_F` for each type you want to
+test (and you may even factor the test logic into a function template
+that you invoke from the `TEST`), it's tedious and doesn't scale:
+if you want _m_ tests over _n_ types, you'll end up writing _m\*n_
+`TEST`s.
+
+_Typed tests_ allow you to repeat the same test logic over a list of
+types.  You only need to write the test logic once, although you must
+know the type list when writing typed tests.  Here's how you do it:
+
+First, define a fixture class template.  It should be parameterized
+by a type.  Remember to derive it from `::testing::Test`:
+
+```
+template <typename T>
+class FooTest : public ::testing::Test {
+ public:
+  ...
+  typedef std::list<T> List;
+  static T shared_;
+  T value_;
+};
+```
+
+Next, associate a list of types with the test case, which will be
+repeated for each type in the list:
+
+```
+typedef ::testing::Types<char, int, unsigned int> MyTypes;
+TYPED_TEST_CASE(FooTest, MyTypes);
+```
+
+The `typedef` is necessary for the `TYPED_TEST_CASE` macro to parse
+correctly.  Otherwise the compiler will think that each comma in the
+type list introduces a new macro argument.
+
+Then, use `TYPED_TEST()` instead of `TEST_F()` to define a typed test
+for this test case.  You can repeat this as many times as you want:
+
+```
+TYPED_TEST(FooTest, DoesBlah) {
+  // Inside a test, refer to the special name TypeParam to get the type
+  // parameter.  Since we are inside a derived class template, C++ requires
+  // us to visit the members of FooTest via 'this'.
+  TypeParam n = this->value_;
+
+  // To visit static members of the fixture, add the 'TestFixture::'
+  // prefix.
+  n += TestFixture::shared_;
+
+  // To refer to typedefs in the fixture, add the 'typename TestFixture::'
+  // prefix.  The 'typename' is required to satisfy the compiler.
+  typename TestFixture::List values;
+  values.push_back(n);
+  ...
+}
+
+TYPED_TEST(FooTest, HasPropertyA) { ... }
+```
+
+You can see `samples/sample6_unittest.cc` for a complete example.
+
+_Availability:_ Linux, Windows (requires MSVC 8.0 or above), Mac;
+since version 1.1.0.
+
+# Type-Parameterized Tests #
+
+_Type-parameterized tests_ are like typed tests, except that they
+don't require you to know the list of types ahead of time.  Instead,
+you can define the test logic first and instantiate it with different
+type lists later.  You can even instantiate it more than once in the
+same program.
+
+If you are designing an interface or concept, you can define a suite
+of type-parameterized tests to verify properties that any valid
+implementation of the interface/concept should have.  Then, the author
+of each implementation can just instantiate the test suite with his
+type to verify that it conforms to the requirements, without having to
+write similar tests repeatedly.  Here's an example:
+
+First, define a fixture class template, as we did with typed tests:
+
+```
+template <typename T>
+class FooTest : public ::testing::Test {
+  ...
+};
+```
+
+Next, declare that you will define a type-parameterized test case:
+
+```
+TYPED_TEST_CASE_P(FooTest);
+```
+
+The `_P` suffix is for "parameterized" or "pattern", whichever you
+prefer to think.
+
+Then, use `TYPED_TEST_P()` to define a type-parameterized test.  You
+can repeat this as many times as you want:
+
+```
+TYPED_TEST_P(FooTest, DoesBlah) {
+  // Inside a test, refer to TypeParam to get the type parameter.
+  TypeParam n = 0;
+  ...
+}
+
+TYPED_TEST_P(FooTest, HasPropertyA) { ... }
+```
+
+Now the tricky part: you need to register all test patterns using the
+`REGISTER_TYPED_TEST_CASE_P` macro before you can instantiate them.
+The first argument of the macro is the test case name; the rest are
+the names of the tests in this test case:
+
+```
+REGISTER_TYPED_TEST_CASE_P(FooTest,
+                           DoesBlah, HasPropertyA);
+```
+
+Finally, you are free to instantiate the pattern with the types you
+want.  If you put the above code in a header file, you can `#include`
+it in multiple C++ source files and instantiate it multiple times.
+
+```
+typedef ::testing::Types<char, int, unsigned int> MyTypes;
+INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
+```
+
+To distinguish different instances of the pattern, the first argument
+to the `INSTANTIATE_TYPED_TEST_CASE_P` macro is a prefix that will be
+added to the actual test case name.  Remember to pick unique prefixes
+for different instances.
+
+In the special case where the type list contains only one type, you
+can write that type directly without `::testing::Types<...>`, like this:
+
+```
+INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int);
+```
+
+You can see `samples/sample6_unittest.cc` for a complete example.
+
+_Availability:_ Linux, Windows (requires MSVC 8.0 or above), Mac;
+since version 1.1.0.
+
+# Testing Private Code #
+
+If you change your software's internal implementation, your tests should not
+break as long as the change is not observable by users. Therefore, per the
+_black-box testing principle_, most of the time you should test your code
+through its public interfaces.
+
+If you still find yourself needing to test internal implementation code,
+consider if there's a better design that wouldn't require you to do so. If you
+absolutely have to test non-public interface code though, you can. There are
+two cases to consider:
+
+  * Static functions (_not_ the same as static member functions!) or unnamed namespaces, and
+  * Private or protected class members
+
+## Static Functions ##
+
+Both static functions and definitions/declarations in an unnamed namespace are
+only visible within the same translation unit. To test them, you can `#include`
+the entire `.cc` file being tested in your `*_test.cc` file. (#including `.cc`
+files is not a good way to reuse code - you should not do this in production
+code!)
+
+However, a better approach is to move the private code into the
+`foo::internal` namespace, where `foo` is the namespace your project normally
+uses, and put the private declarations in a `*-internal.h` file. Your
+production `.cc` files and your tests are allowed to include this internal
+header, but your clients are not. This way, you can fully test your internal
+implementation without leaking it to your clients.
+
+## Private Class Members ##
+
+Private class members are only accessible from within the class or by friends.
+To access a class' private members, you can declare your test fixture as a
+friend to the class and define accessors in your fixture. Tests using the
+fixture can then access the private members of your production class via the
+accessors in the fixture. Note that even though your fixture is a friend to
+your production class, your tests are not automatically friends to it, as they
+are technically defined in sub-classes of the fixture.
+
+Another way to test private members is to refactor them into an implementation
+class, which is then declared in a `*-internal.h` file. Your clients aren't
+allowed to include this header but your tests can. Such is called the Pimpl
+(Private Implementation) idiom.
+
+Or, you can declare an individual test as a friend of your class by adding this
+line in the class body:
+
+```
+FRIEND_TEST(TestCaseName, TestName);
+```
+
+For example,
+```
+// foo.h
+#include "gtest/gtest_prod.h"
+
+// Defines FRIEND_TEST.
+class Foo {
+  ...
+ private:
+  FRIEND_TEST(FooTest, BarReturnsZeroOnNull);
+  int Bar(void* x);
+};
+
+// foo_test.cc
+...
+TEST(FooTest, BarReturnsZeroOnNull) {
+  Foo foo;
+  EXPECT_EQ(0, foo.Bar(NULL));
+  // Uses Foo's private member Bar().
+}
+```
+
+Pay special attention when your class is defined in a namespace, as you should
+define your test fixtures and tests in the same namespace if you want them to
+be friends of your class. For example, if the code to be tested looks like:
+
+```
+namespace my_namespace {
+
+class Foo {
+  friend class FooTest;
+  FRIEND_TEST(FooTest, Bar);
+  FRIEND_TEST(FooTest, Baz);
+  ...
+  definition of the class Foo
+  ...
+};
+
+}  // namespace my_namespace
+```
+
+Your test code should be something like:
+
+```
+namespace my_namespace {
+class FooTest : public ::testing::Test {
+ protected:
+  ...
+};
+
+TEST_F(FooTest, Bar) { ... }
+TEST_F(FooTest, Baz) { ... }
+
+}  // namespace my_namespace
+```
+
+# Catching Failures #
+
+If you are building a testing utility on top of Google Test, you'll
+want to test your utility.  What framework would you use to test it?
+Google Test, of course.
+
+The challenge is to verify that your testing utility reports failures
+correctly.  In frameworks that report a failure by throwing an
+exception, you could catch the exception and assert on it.  But Google
+Test doesn't use exceptions, so how do we test that a piece of code
+generates an expected failure?
+
+`"gtest/gtest-spi.h"` contains some constructs to do this.  After
+#including this header, you can use
+
+| `EXPECT_FATAL_FAILURE(`_statement, substring_`);` |
+|:--------------------------------------------------|
+
+to assert that _statement_ generates a fatal (e.g. `ASSERT_*`) failure
+whose message contains the given _substring_, or use
+
+| `EXPECT_NONFATAL_FAILURE(`_statement, substring_`);` |
+|:-----------------------------------------------------|
+
+if you are expecting a non-fatal (e.g. `EXPECT_*`) failure.
+
+For technical reasons, there are some caveats:
+
+  1. You cannot stream a failure message to either macro.
+  1. _statement_ in `EXPECT_FATAL_FAILURE()` cannot reference local non-static variables or non-static members of `this` object.
+  1. _statement_ in `EXPECT_FATAL_FAILURE()` cannot return a value.
+
+_Note:_ Google Test is designed with threads in mind.  Once the
+synchronization primitives in `"gtest/internal/gtest-port.h"` have
+been implemented, Google Test will become thread-safe, meaning that
+you can then use assertions in multiple threads concurrently.  Before
+
+that, however, Google Test only supports single-threaded usage.  Once
+thread-safe, `EXPECT_FATAL_FAILURE()` and `EXPECT_NONFATAL_FAILURE()`
+will capture failures in the current thread only. If _statement_
+creates new threads, failures in these threads will be ignored.  If
+you want to capture failures from all threads instead, you should use
+the following macros:
+
+| `EXPECT_FATAL_FAILURE_ON_ALL_THREADS(`_statement, substring_`);` |
+|:-----------------------------------------------------------------|
+| `EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(`_statement, substring_`);` |
+
+# Getting the Current Test's Name #
+
+Sometimes a function may need to know the name of the currently running test.
+For example, you may be using the `SetUp()` method of your test fixture to set
+the golden file name based on which test is running. The `::testing::TestInfo`
+class has this information:
+
+```
+namespace testing {
+
+class TestInfo {
+ public:
+  // Returns the test case name and the test name, respectively.
+  //
+  // Do NOT delete or free the return value - it's managed by the
+  // TestInfo class.
+  const char* test_case_name() const;
+  const char* name() const;
+};
+
+}  // namespace testing
+```
+
+
+> To obtain a `TestInfo` object for the currently running test, call
+`current_test_info()` on the `UnitTest` singleton object:
+
+```
+// Gets information about the currently running test.
+// Do NOT delete the returned object - it's managed by the UnitTest class.
+const ::testing::TestInfo* const test_info =
+  ::testing::UnitTest::GetInstance()->current_test_info();
+printf("We are in test %s of test case %s.\n",
+       test_info->name(), test_info->test_case_name());
+```
+
+`current_test_info()` returns a null pointer if no test is running. In
+particular, you cannot find the test case name in `TestCaseSetUp()`,
+`TestCaseTearDown()` (where you know the test case name implicitly), or
+functions called from them.
+
+_Availability:_ Linux, Windows, Mac.
+
+# Extending Google Test by Handling Test Events #
+
+Google Test provides an <b>event listener API</b> to let you receive
+notifications about the progress of a test program and test
+failures. The events you can listen to include the start and end of
+the test program, a test case, or a test method, among others. You may
+use this API to augment or replace the standard console output,
+replace the XML output, or provide a completely different form of
+output, such as a GUI or a database. You can also use test events as
+checkpoints to implement a resource leak checker, for example.
+
+_Availability:_ Linux, Windows, Mac; since v1.4.0.
+
+## Defining Event Listeners ##
+
+To define a event listener, you subclass either
+[testing::TestEventListener](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest.h#855)
+or [testing::EmptyTestEventListener](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest.h#905).
+The former is an (abstract) interface, where <i>each pure virtual method<br>
+can be overridden to handle a test event</i> (For example, when a test
+starts, the `OnTestStart()` method will be called.). The latter provides
+an empty implementation of all methods in the interface, such that a
+subclass only needs to override the methods it cares about.
+
+When an event is fired, its context is passed to the handler function
+as an argument. The following argument types are used:
+  * [UnitTest](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest.h#1007) reflects the state of the entire test program,
+  * [TestCase](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest.h#689) has information about a test case, which can contain one or more tests,
+  * [TestInfo](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest.h#599) contains the state of a test, and
+  * [TestPartResult](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest-test-part.h#42) represents the result of a test assertion.
+
+An event handler function can examine the argument it receives to find
+out interesting information about the event and the test program's
+state.  Here's an example:
+
+```
+  class MinimalistPrinter : public ::testing::EmptyTestEventListener {
+    // Called before a test starts.
+    virtual void OnTestStart(const ::testing::TestInfo& test_info) {
+      printf("*** Test %s.%s starting.\n",
+             test_info.test_case_name(), test_info.name());
+    }
+
+    // Called after a failed assertion or a SUCCEED() invocation.
+    virtual void OnTestPartResult(
+        const ::testing::TestPartResult& test_part_result) {
+      printf("%s in %s:%d\n%s\n",
+             test_part_result.failed() ? "*** Failure" : "Success",
+             test_part_result.file_name(),
+             test_part_result.line_number(),
+             test_part_result.summary());
+    }
+
+    // Called after a test ends.
+    virtual void OnTestEnd(const ::testing::TestInfo& test_info) {
+      printf("*** Test %s.%s ending.\n",
+             test_info.test_case_name(), test_info.name());
+    }
+  };
+```
+
+## Using Event Listeners ##
+
+To use the event listener you have defined, add an instance of it to
+the Google Test event listener list (represented by class
+[TestEventListeners](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest.h#929)
+- note the "s" at the end of the name) in your
+`main()` function, before calling `RUN_ALL_TESTS()`:
+```
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  // Gets hold of the event listener list.
+  ::testing::TestEventListeners& listeners =
+      ::testing::UnitTest::GetInstance()->listeners();
+  // Adds a listener to the end.  Google Test takes the ownership.
+  listeners.Append(new MinimalistPrinter);
+  return RUN_ALL_TESTS();
+}
+```
+
+There's only one problem: the default test result printer is still in
+effect, so its output will mingle with the output from your minimalist
+printer. To suppress the default printer, just release it from the
+event listener list and delete it. You can do so by adding one line:
+```
+  ...
+  delete listeners.Release(listeners.default_result_printer());
+  listeners.Append(new MinimalistPrinter);
+  return RUN_ALL_TESTS();
+```
+
+Now, sit back and enjoy a completely different output from your
+tests. For more details, you can read this
+[sample](http://code.google.com/p/googletest/source/browse/trunk/samples/sample9_unittest.cc).
+
+You may append more than one listener to the list. When an `On*Start()`
+or `OnTestPartResult()` event is fired, the listeners will receive it in
+the order they appear in the list (since new listeners are added to
+the end of the list, the default text printer and the default XML
+generator will receive the event first). An `On*End()` event will be
+received by the listeners in the _reverse_ order. This allows output by
+listeners added later to be framed by output from listeners added
+earlier.
+
+## Generating Failures in Listeners ##
+
+You may use failure-raising macros (`EXPECT_*()`, `ASSERT_*()`,
+`FAIL()`, etc) when processing an event. There are some restrictions:
+
+  1. You cannot generate any failure in `OnTestPartResult()` (otherwise it will cause `OnTestPartResult()` to be called recursively).
+  1. A listener that handles `OnTestPartResult()` is not allowed to generate any failure.
+
+When you add listeners to the listener list, you should put listeners
+that handle `OnTestPartResult()` _before_ listeners that can generate
+failures. This ensures that failures generated by the latter are
+attributed to the right test by the former.
+
+We have a sample of failure-raising listener
+[here](http://code.google.com/p/googletest/source/browse/trunk/samples/sample10_unittest.cc).
+
+# Running Test Programs: Advanced Options #
+
+Google Test test programs are ordinary executables. Once built, you can run
+them directly and affect their behavior via the following environment variables
+and/or command line flags. For the flags to work, your programs must call
+`::testing::InitGoogleTest()` before calling `RUN_ALL_TESTS()`.
+
+To see a list of supported flags and their usage, please run your test
+program with the `--help` flag.  You can also use `-h`, `-?`, or `/?`
+for short.  This feature is added in version 1.3.0.
+
+If an option is specified both by an environment variable and by a
+flag, the latter takes precedence.  Most of the options can also be
+set/read in code: to access the value of command line flag
+`--gtest_foo`, write `::testing::GTEST_FLAG(foo)`.  A common pattern is
+to set the value of a flag before calling `::testing::InitGoogleTest()`
+to change the default value of the flag:
+```
+int main(int argc, char** argv) {
+  // Disables elapsed time by default.
+  ::testing::GTEST_FLAG(print_time) = false;
+
+  // This allows the user to override the flag on the command line.
+  ::testing::InitGoogleTest(&argc, argv);
+
+  return RUN_ALL_TESTS();
+}
+```
+
+## Selecting Tests ##
+
+This section shows various options for choosing which tests to run.
+
+### Listing Test Names ###
+
+Sometimes it is necessary to list the available tests in a program before
+running them so that a filter may be applied if needed. Including the flag
+`--gtest_list_tests` overrides all other flags and lists tests in the following
+format:
+```
+TestCase1.
+  TestName1
+  TestName2
+TestCase2.
+  TestName
+```
+
+None of the tests listed are actually run if the flag is provided. There is no
+corresponding environment variable for this flag.
+
+_Availability:_ Linux, Windows, Mac.
+
+### Running a Subset of the Tests ###
+
+By default, a Google Test program runs all tests the user has defined.
+Sometimes, you want to run only a subset of the tests (e.g. for debugging or
+quickly verifying a change). If you set the `GTEST_FILTER` environment variable
+or the `--gtest_filter` flag to a filter string, Google Test will only run the
+tests whose full names (in the form of `TestCaseName.TestName`) match the
+filter.
+
+The format of a filter is a '`:`'-separated list of wildcard patterns (called
+the positive patterns) optionally followed by a '`-`' and another
+'`:`'-separated pattern list (called the negative patterns). A test matches the
+filter if and only if it matches any of the positive patterns but does not
+match any of the negative patterns.
+
+A pattern may contain `'*'` (matches any string) or `'?'` (matches any single
+character). For convenience, the filter `'*-NegativePatterns'` can be also
+written as `'-NegativePatterns'`.
+
+For example:
+
+  * `./foo_test` Has no flag, and thus runs all its tests.
+  * `./foo_test --gtest_filter=*` Also runs everything, due to the single match-everything `*` value.
+  * `./foo_test --gtest_filter=FooTest.*` Runs everything in test case `FooTest`.
+  * `./foo_test --gtest_filter=*Null*:*Constructor*` Runs any test whose full name contains either `"Null"` or `"Constructor"`.
+  * `./foo_test --gtest_filter=-*DeathTest.*` Runs all non-death tests.
+  * `./foo_test --gtest_filter=FooTest.*-FooTest.Bar` Runs everything in test case `FooTest` except `FooTest.Bar`.
+
+_Availability:_ Linux, Windows, Mac.
+
+### Temporarily Disabling Tests ###
+
+If you have a broken test that you cannot fix right away, you can add the
+`DISABLED_` prefix to its name. This will exclude it from execution. This is
+better than commenting out the code or using `#if 0`, as disabled tests are
+still compiled (and thus won't rot).
+
+If you need to disable all tests in a test case, you can either add `DISABLED_`
+to the front of the name of each test, or alternatively add it to the front of
+the test case name.
+
+For example, the following tests won't be run by Google Test, even though they
+will still be compiled:
+
+```
+// Tests that Foo does Abc.
+TEST(FooTest, DISABLED_DoesAbc) { ... }
+
+class DISABLED_BarTest : public ::testing::Test { ... };
+
+// Tests that Bar does Xyz.
+TEST_F(DISABLED_BarTest, DoesXyz) { ... }
+```
+
+_Note:_ This feature should only be used for temporary pain-relief. You still
+have to fix the disabled tests at a later date. As a reminder, Google Test will
+print a banner warning you if a test program contains any disabled tests.
+
+_Tip:_ You can easily count the number of disabled tests you have
+using `grep`. This number can be used as a metric for improving your
+test quality.
+
+_Availability:_ Linux, Windows, Mac.
+
+### Temporarily Enabling Disabled Tests ###
+
+To include [disabled tests](#Temporarily_Disabling_Tests.md) in test
+execution, just invoke the test program with the
+`--gtest_also_run_disabled_tests` flag or set the
+`GTEST_ALSO_RUN_DISABLED_TESTS` environment variable to a value other
+than `0`.  You can combine this with the
+[--gtest\_filter](#Running_a_Subset_of_the_Tests.md) flag to further select
+which disabled tests to run.
+
+_Availability:_ Linux, Windows, Mac; since version 1.3.0.
+
+## Repeating the Tests ##
+
+Once in a while you'll run into a test whose result is hit-or-miss. Perhaps it
+will fail only 1% of the time, making it rather hard to reproduce the bug under
+a debugger. This can be a major source of frustration.
+
+The `--gtest_repeat` flag allows you to repeat all (or selected) test methods
+in a program many times. Hopefully, a flaky test will eventually fail and give
+you a chance to debug. Here's how to use it:
+
+| `$ foo_test --gtest_repeat=1000` | Repeat foo\_test 1000 times and don't stop at failures. |
+|:---------------------------------|:--------------------------------------------------------|
+| `$ foo_test --gtest_repeat=-1`   | A negative count means repeating forever.               |
+| `$ foo_test --gtest_repeat=1000 --gtest_break_on_failure` | Repeat foo\_test 1000 times, stopping at the first failure. This is especially useful when running under a debugger: when the testfails, it will drop into the debugger and you can then inspect variables and stacks. |
+| `$ foo_test --gtest_repeat=1000 --gtest_filter=FooBar` | Repeat the tests whose name matches the filter 1000 times. |
+
+If your test program contains global set-up/tear-down code registered
+using `AddGlobalTestEnvironment()`, it will be repeated in each
+iteration as well, as the flakiness may be in it. You can also specify
+the repeat count by setting the `GTEST_REPEAT` environment variable.
+
+_Availability:_ Linux, Windows, Mac.
+
+## Shuffling the Tests ##
+
+You can specify the `--gtest_shuffle` flag (or set the `GTEST_SHUFFLE`
+environment variable to `1`) to run the tests in a program in a random
+order. This helps to reveal bad dependencies between tests.
+
+By default, Google Test uses a random seed calculated from the current
+time. Therefore you'll get a different order every time. The console
+output includes the random seed value, such that you can reproduce an
+order-related test failure later. To specify the random seed
+explicitly, use the `--gtest_random_seed=SEED` flag (or set the
+`GTEST_RANDOM_SEED` environment variable), where `SEED` is an integer
+between 0 and 99999. The seed value 0 is special: it tells Google Test
+to do the default behavior of calculating the seed from the current
+time.
+
+If you combine this with `--gtest_repeat=N`, Google Test will pick a
+different random seed and re-shuffle the tests in each iteration.
+
+_Availability:_ Linux, Windows, Mac; since v1.4.0.
+
+## Controlling Test Output ##
+
+This section teaches how to tweak the way test results are reported.
+
+### Colored Terminal Output ###
+
+Google Test can use colors in its terminal output to make it easier to spot
+the separation between tests, and whether tests passed.
+
+You can set the GTEST\_COLOR environment variable or set the `--gtest_color`
+command line flag to `yes`, `no`, or `auto` (the default) to enable colors,
+disable colors, or let Google Test decide. When the value is `auto`, Google
+Test will use colors if and only if the output goes to a terminal and (on
+non-Windows platforms) the `TERM` environment variable is set to `xterm` or
+`xterm-color`.
+
+_Availability:_ Linux, Windows, Mac.
+
+### Suppressing the Elapsed Time ###
+
+By default, Google Test prints the time it takes to run each test.  To
+suppress that, run the test program with the `--gtest_print_time=0`
+command line flag.  Setting the `GTEST_PRINT_TIME` environment
+variable to `0` has the same effect.
+
+_Availability:_ Linux, Windows, Mac.  (In Google Test 1.3.0 and lower,
+the default behavior is that the elapsed time is **not** printed.)
+
+### Generating an XML Report ###
+
+Google Test can emit a detailed XML report to a file in addition to its normal
+textual output. The report contains the duration of each test, and thus can
+help you identify slow tests.
+
+To generate the XML report, set the `GTEST_OUTPUT` environment variable or the
+`--gtest_output` flag to the string `"xml:_path_to_output_file_"`, which will
+create the file at the given location. You can also just use the string
+`"xml"`, in which case the output can be found in the `test_detail.xml` file in
+the current directory.
+
+If you specify a directory (for example, `"xml:output/directory/"` on Linux or
+`"xml:output\directory\"` on Windows), Google Test will create the XML file in
+that directory, named after the test executable (e.g. `foo_test.xml` for test
+program `foo_test` or `foo_test.exe`). If the file already exists (perhaps left
+over from a previous run), Google Test will pick a different name (e.g.
+`foo_test_1.xml`) to avoid overwriting it.
+
+The report uses the format described here.  It is based on the
+`junitreport` Ant task and can be parsed by popular continuous build
+systems like [Hudson](https://hudson.dev.java.net/). Since that format
+was originally intended for Java, a little interpretation is required
+to make it apply to Google Test tests, as shown here:
+
+```
+<testsuites name="AllTests" ...>
+  <testsuite name="test_case_name" ...>
+    <testcase name="test_name" ...>
+      <failure message="..."/>
+      <failure message="..."/>
+      <failure message="..."/>
+    </testcase>
+  </testsuite>
+</testsuites>
+```
+
+  * The root `<testsuites>` element corresponds to the entire test program.
+  * `<testsuite>` elements correspond to Google Test test cases.
+  * `<testcase>` elements correspond to Google Test test functions.
+
+For instance, the following program
+
+```
+TEST(MathTest, Addition) { ... }
+TEST(MathTest, Subtraction) { ... }
+TEST(LogicTest, NonContradiction) { ... }
+```
+
+could generate this report:
+
+```
+<?xml version="1.0" encoding="UTF-8"?>
+<testsuites tests="3" failures="1" errors="0" time="35" name="AllTests">
+  <testsuite name="MathTest" tests="2" failures="1" errors="0" time="15">
+    <testcase name="Addition" status="run" time="7" classname="">
+      <failure message="Value of: add(1, 1)&#x0A; Actual: 3&#x0A;Expected: 2" type=""/>
+      <failure message="Value of: add(1, -1)&#x0A; Actual: 1&#x0A;Expected: 0" type=""/>
+    </testcase>
+    <testcase name="Subtraction" status="run" time="5" classname="">
+    </testcase>
+  </testsuite>
+  <testsuite name="LogicTest" tests="1" failures="0" errors="0" time="5">
+    <testcase name="NonContradiction" status="run" time="5" classname="">
+    </testcase>
+  </testsuite>
+</testsuites>
+```
+
+Things to note:
+
+  * The `tests` attribute of a `<testsuites>` or `<testsuite>` element tells how many test functions the Google Test program or test case contains, while the `failures` attribute tells how many of them failed.
+  * The `time` attribute expresses the duration of the test, test case, or entire test program in milliseconds.
+  * Each `<failure>` element corresponds to a single failed Google Test assertion.
+  * Some JUnit concepts don't apply to Google Test, yet we have to conform to the DTD. Therefore you'll see some dummy elements and attributes in the report. You can safely ignore these parts.
+
+_Availability:_ Linux, Windows, Mac.
+
+## Controlling How Failures Are Reported ##
+
+### Turning Assertion Failures into Break-Points ###
+
+When running test programs under a debugger, it's very convenient if the
+debugger can catch an assertion failure and automatically drop into interactive
+mode. Google Test's _break-on-failure_ mode supports this behavior.
+
+To enable it, set the `GTEST_BREAK_ON_FAILURE` environment variable to a value
+other than `0` . Alternatively, you can use the `--gtest_break_on_failure`
+command line flag.
+
+_Availability:_ Linux, Windows, Mac.
+
+### Disabling Catching Test-Thrown Exceptions ###
+
+Google Test can be used either with or without exceptions enabled.  If
+a test throws a C++ exception or (on Windows) a structured exception
+(SEH), by default Google Test catches it, reports it as a test
+failure, and continues with the next test method.  This maximizes the
+coverage of a test run.  Also, on Windows an uncaught exception will
+cause a pop-up window, so catching the exceptions allows you to run
+the tests automatically.
+
+When debugging the test failures, however, you may instead want the
+exceptions to be handled by the debugger, such that you can examine
+the call stack when an exception is thrown.  To achieve that, set the
+`GTEST_CATCH_EXCEPTIONS` environment variable to `0`, or use the
+`--gtest_catch_exceptions=0` flag when running the tests.
+
+**Availability**: Linux, Windows, Mac.
+
+### Letting Another Testing Framework Drive ###
+
+If you work on a project that has already been using another testing
+framework and is not ready to completely switch to Google Test yet,
+you can get much of Google Test's benefit by using its assertions in
+your existing tests.  Just change your `main()` function to look
+like:
+
+```
+#include "gtest/gtest.h"
+
+int main(int argc, char** argv) {
+  ::testing::GTEST_FLAG(throw_on_failure) = true;
+  // Important: Google Test must be initialized.
+  ::testing::InitGoogleTest(&argc, argv);
+
+  ... whatever your existing testing framework requires ...
+}
+```
+
+With that, you can use Google Test assertions in addition to the
+native assertions your testing framework provides, for example:
+
+```
+void TestFooDoesBar() {
+  Foo foo;
+  EXPECT_LE(foo.Bar(1), 100);     // A Google Test assertion.
+  CPPUNIT_ASSERT(foo.IsEmpty());  // A native assertion.
+}
+```
+
+If a Google Test assertion fails, it will print an error message and
+throw an exception, which will be treated as a failure by your host
+testing framework.  If you compile your code with exceptions disabled,
+a failed Google Test assertion will instead exit your program with a
+non-zero code, which will also signal a test failure to your test
+runner.
+
+If you don't write `::testing::GTEST_FLAG(throw_on_failure) = true;` in
+your `main()`, you can alternatively enable this feature by specifying
+the `--gtest_throw_on_failure` flag on the command-line or setting the
+`GTEST_THROW_ON_FAILURE` environment variable to a non-zero value.
+
+Death tests are _not_ supported when other test framework is used to organize tests.
+
+_Availability:_ Linux, Windows, Mac; since v1.3.0.
+
+## Distributing Test Functions to Multiple Machines ##
+
+If you have more than one machine you can use to run a test program,
+you might want to run the test functions in parallel and get the
+result faster.  We call this technique _sharding_, where each machine
+is called a _shard_.
+
+Google Test is compatible with test sharding.  To take advantage of
+this feature, your test runner (not part of Google Test) needs to do
+the following:
+
+  1. Allocate a number of machines (shards) to run the tests.
+  1. On each shard, set the `GTEST_TOTAL_SHARDS` environment variable to the total number of shards.  It must be the same for all shards.
+  1. On each shard, set the `GTEST_SHARD_INDEX` environment variable to the index of the shard.  Different shards must be assigned different indices, which must be in the range `[0, GTEST_TOTAL_SHARDS - 1]`.
+  1. Run the same test program on all shards.  When Google Test sees the above two environment variables, it will select a subset of the test functions to run.  Across all shards, each test function in the program will be run exactly once.
+  1. Wait for all shards to finish, then collect and report the results.
+
+Your project may have tests that were written without Google Test and
+thus don't understand this protocol.  In order for your test runner to
+figure out which test supports sharding, it can set the environment
+variable `GTEST_SHARD_STATUS_FILE` to a non-existent file path.  If a
+test program supports sharding, it will create this file to
+acknowledge the fact (the actual contents of the file are not
+important at this time; although we may stick some useful information
+in it in the future.); otherwise it will not create it.
+
+Here's an example to make it clear.  Suppose you have a test program
+`foo_test` that contains the following 5 test functions:
+```
+TEST(A, V)
+TEST(A, W)
+TEST(B, X)
+TEST(B, Y)
+TEST(B, Z)
+```
+and you have 3 machines at your disposal.  To run the test functions in
+parallel, you would set `GTEST_TOTAL_SHARDS` to 3 on all machines, and
+set `GTEST_SHARD_INDEX` to 0, 1, and 2 on the machines respectively.
+Then you would run the same `foo_test` on each machine.
+
+Google Test reserves the right to change how the work is distributed
+across the shards, but here's one possible scenario:
+
+  * Machine #0 runs `A.V` and `B.X`.
+  * Machine #1 runs `A.W` and `B.Y`.
+  * Machine #2 runs `B.Z`.
+
+_Availability:_ Linux, Windows, Mac; since version 1.3.0.
+
+# Fusing Google Test Source Files #
+
+Google Test's implementation consists of ~30 files (excluding its own
+tests).  Sometimes you may want them to be packaged up in two files (a
+`.h` and a `.cc`) instead, such that you can easily copy them to a new
+machine and start hacking there.  For this we provide an experimental
+Python script `fuse_gtest_files.py` in the `scripts/` directory (since release 1.3.0).
+Assuming you have Python 2.4 or above installed on your machine, just
+go to that directory and run
+```
+python fuse_gtest_files.py OUTPUT_DIR
+```
+
+and you should see an `OUTPUT_DIR` directory being created with files
+`gtest/gtest.h` and `gtest/gtest-all.cc` in it.  These files contain
+everything you need to use Google Test.  Just copy them to anywhere
+you want and you are ready to write tests.  You can use the
+[scripts/test/Makefile](http://code.google.com/p/googletest/source/browse/trunk/scripts/test/Makefile)
+file as an example on how to compile your tests against them.
+
+# Where to Go from Here #
+
+Congratulations! You've now learned more advanced Google Test tools and are
+ready to tackle more complex testing tasks. If you want to dive even deeper, you
+can read the [Frequently-Asked Questions](FAQ.md).
\ No newline at end of file
diff --git a/third_party/googletest/googletest/docs/DevGuide.md b/third_party/googletest/googletest/docs/DevGuide.md
new file mode 100644
index 0000000..867770a
--- /dev/null
+++ b/third_party/googletest/googletest/docs/DevGuide.md
@@ -0,0 +1,139 @@
+
+
+If you are interested in understanding the internals of Google Test,
+building from source, or contributing ideas or modifications to the
+project, then this document is for you.
+
+# Introduction #
+
+First, let's give you some background of the project.
+
+## Licensing ##
+
+All Google Test source and pre-built packages are provided under the [New BSD License](http://www.opensource.org/licenses/bsd-license.php).
+
+## The Google Test Community ##
+
+The Google Test community exists primarily through the [discussion group](http://groups.google.com/group/googletestframework), the
+[issue tracker](http://code.google.com/p/googletest/issues/list) and, to a lesser extent, the [source control repository](http://code.google.com/p/googletest/source/checkout). You are definitely encouraged to contribute to the
+discussion and you can also help us to keep the effectiveness of the
+group high by following and promoting the guidelines listed here.
+
+### Please Be Friendly ###
+
+Showing courtesy and respect to others is a vital part of the Google
+culture, and we strongly encourage everyone participating in Google
+Test development to join us in accepting nothing less. Of course,
+being courteous is not the same as failing to constructively disagree
+with each other, but it does mean that we should be respectful of each
+other when enumerating the 42 technical reasons that a particular
+proposal may not be the best choice. There's never a reason to be
+antagonistic or dismissive toward anyone who is sincerely trying to
+contribute to a discussion.
+
+Sure, C++ testing is serious business and all that, but it's also
+a lot of fun. Let's keep it that way. Let's strive to be one of the
+friendliest communities in all of open source.
+
+### Where to Discuss Google Test ###
+
+As always, discuss Google Test in the official [Google C++ Testing Framework discussion group](http://groups.google.com/group/googletestframework).  You don't have to actually submit
+code in order to sign up. Your participation itself is a valuable
+contribution.
+
+# Working with the Code #
+
+If you want to get your hands dirty with the code inside Google Test,
+this is the section for you.
+
+## Checking Out the Source from Subversion ##
+
+Checking out the Google Test source is most useful if you plan to
+tweak it yourself.  You check out the source for Google Test using a
+[Subversion](http://subversion.tigris.org/) client as you would for any
+other project hosted on Google Code.  Please see the instruction on
+the [source code access page](http://code.google.com/p/googletest/source/checkout) for how to do it.
+
+## Compiling from Source ##
+
+Once you check out the code, you can find instructions on how to
+compile it in the [README](http://code.google.com/p/googletest/source/browse/trunk/README) file.
+
+## Testing ##
+
+A testing framework is of no good if itself is not thoroughly tested.
+Tests should be written for any new code, and changes should be
+verified to not break existing tests before they are submitted for
+review. To perform the tests, follow the instructions in [README](http://code.google.com/p/googletest/source/browse/trunk/README) and
+verify that there are no failures.
+
+# Contributing Code #
+
+We are excited that Google Test is now open source, and hope to get
+great patches from the community. Before you fire up your favorite IDE
+and begin hammering away at that new feature, though, please take the
+time to read this section and understand the process. While it seems
+rigorous, we want to keep a high standard of quality in the code
+base.
+
+## Contributor License Agreements ##
+
+You must sign a Contributor License Agreement (CLA) before we can
+accept any code.  The CLA protects you and us.
+
+  * If you are an individual writing original source code and you're sure you own the intellectual property, then you'll need to sign an [individual CLA](http://code.google.com/legal/individual-cla-v1.0.html).
+  * If you work for a company that wants to allow you to contribute your work to Google Test, then you'll need to sign a [corporate CLA](http://code.google.com/legal/corporate-cla-v1.0.html).
+
+Follow either of the two links above to access the appropriate CLA and
+instructions for how to sign and return it.
+
+## Coding Style ##
+
+To keep the source consistent, readable, diffable and easy to merge,
+we use a fairly rigid coding style, as defined by the [google-styleguide](http://code.google.com/p/google-styleguide/) project.  All patches will be expected
+to conform to the style outlined [here](http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml).
+
+## Updating Generated Code ##
+
+Some of Google Test's source files are generated by the Pump tool (a
+Python script).  If you need to update such files, please modify the
+source (`foo.h.pump`) and re-generate the C++ file using Pump.  You
+can read the PumpManual for details.
+
+## Submitting Patches ##
+
+Please do submit code. Here's what you need to do:
+
+  1. Normally you should make your change against the SVN trunk instead of a branch or a tag, as the latter two are for release control and should be treated mostly as read-only.
+  1. Decide which code you want to submit. A submission should be a set of changes that addresses one issue in the [Google Test issue tracker](http://code.google.com/p/googletest/issues/list). Please don't mix more than one logical change per submittal, because it makes the history hard to follow. If you want to make a change that doesn't have a corresponding issue in the issue tracker, please create one.
+  1. Also, coordinate with team members that are listed on the issue in question. This ensures that work isn't being duplicated and communicating your plan early also generally leads to better patches.
+  1. Ensure that your code adheres to the [Google Test source code style](#Coding_Style.md).
+  1. Ensure that there are unit tests for your code.
+  1. Sign a Contributor License Agreement.
+  1. Create a patch file using `svn diff`.
+  1. We use [Rietveld](http://codereview.appspot.com/) to do web-based code reviews.  You can read about the tool [here](http://code.google.com/p/rietveld/wiki/CodeReviewHelp).  When you are ready, upload your patch via Rietveld and notify `googletestframework@googlegroups.com` to review it.  There are several ways to upload the patch.  We recommend using the [upload\_gtest.py](http://code.google.com/p/googletest/source/browse/trunk/scripts/upload_gtest.py) script, which you can find in the `scripts/` folder in the SVN trunk.
+
+## Google Test Committers ##
+
+The current members of the Google Test engineering team are the only
+committers at present. In the great tradition of eating one's own
+dogfood, we will be requiring each new Google Test engineering team
+member to earn the right to become a committer by following the
+procedures in this document, writing consistently great code, and
+demonstrating repeatedly that he or she truly gets the zen of Google
+Test.
+
+# Release Process #
+
+We follow the typical release process for Subversion-based projects:
+
+  1. A release branch named `release-X.Y` is created.
+  1. Bugs are fixed and features are added in trunk; those individual patches are merged into the release branch until it's stable.
+  1. An individual point release (the `Z` in `X.Y.Z`) is made by creating a tag from the branch.
+  1. Repeat steps 2 and 3 throughout one release cycle (as determined by features or time).
+  1. Go back to step 1 to create another release branch and so on.
+
+
+---
+
+This page is based on the [Making GWT Better](http://code.google.com/webtoolkit/makinggwtbetter.html) guide from the [Google Web Toolkit](http://code.google.com/webtoolkit/) project.  Except as otherwise [noted](http://code.google.com/policies.html#restrictions), the content of this page is licensed under the [Creative Commons Attribution 2.5 License](http://creativecommons.org/licenses/by/2.5/).
\ No newline at end of file
diff --git a/third_party/googletest/googletest/docs/Documentation.md b/third_party/googletest/googletest/docs/Documentation.md
new file mode 100644
index 0000000..8ca1aac
--- /dev/null
+++ b/third_party/googletest/googletest/docs/Documentation.md
@@ -0,0 +1,14 @@
+This page lists all documentation wiki pages for Google Test **(the SVN trunk version)**
+-- **if you use a released version of Google Test, please read the
+documentation for that specific version instead.**
+
+  * [Primer](Primer.md) -- start here if you are new to Google Test.
+  * [Samples](Samples.md) -- learn from examples.
+  * [AdvancedGuide](AdvancedGuide.md) -- learn more about Google Test.
+  * [XcodeGuide](XcodeGuide.md) -- how to use Google Test in Xcode on Mac.
+  * [Frequently-Asked Questions](FAQ.md) -- check here before asking a question on the mailing list.
+
+To contribute code to Google Test, read:
+
+  * [DevGuide](DevGuide.md) -- read this _before_ writing your first patch.
+  * [PumpManual](PumpManual.md) -- how we generate some of Google Test's source files.
\ No newline at end of file
diff --git a/third_party/googletest/googletest/docs/FAQ.md b/third_party/googletest/googletest/docs/FAQ.md
new file mode 100644
index 0000000..ccbd97b
--- /dev/null
+++ b/third_party/googletest/googletest/docs/FAQ.md
@@ -0,0 +1,1087 @@
+
+
+If you cannot find the answer to your question here, and you have read
+[Primer](Primer.md) and [AdvancedGuide](AdvancedGuide.md), send it to
+googletestframework@googlegroups.com.
+
+## Why should I use Google Test instead of my favorite C++ testing framework? ##
+
+First, let us say clearly that we don't want to get into the debate of
+which C++ testing framework is **the best**.  There exist many fine
+frameworks for writing C++ tests, and we have tremendous respect for
+the developers and users of them.  We don't think there is (or will
+be) a single best framework - you have to pick the right tool for the
+particular task you are tackling.
+
+We created Google Test because we couldn't find the right combination
+of features and conveniences in an existing framework to satisfy _our_
+needs.  The following is a list of things that _we_ like about Google
+Test.  We don't claim them to be unique to Google Test - rather, the
+combination of them makes Google Test the choice for us.  We hope this
+list can help you decide whether it is for you too.
+
+  * Google Test is designed to be portable: it doesn't require exceptions or RTTI; it works around various bugs in various compilers and environments; etc.  As a result, it works on Linux, Mac OS X, Windows and several embedded operating systems.
+  * Nonfatal assertions (`EXPECT_*`) have proven to be great time savers, as they allow a test to report multiple failures in a single edit-compile-test cycle.
+  * It's easy to write assertions that generate informative messages: you just use the stream syntax to append any additional information, e.g. `ASSERT_EQ(5, Foo(i)) << " where i = " << i;`.  It doesn't require a new set of macros or special functions.
+  * Google Test automatically detects your tests and doesn't require you to enumerate them in order to run them.
+  * Death tests are pretty handy for ensuring that your asserts in production code are triggered by the right conditions.
+  * `SCOPED_TRACE` helps you understand the context of an assertion failure when it comes from inside a sub-routine or loop.
+  * You can decide which tests to run using name patterns.  This saves time when you want to quickly reproduce a test failure.
+  * Google Test can generate XML test result reports that can be parsed by popular continuous build system like Hudson.
+  * Simple things are easy in Google Test, while hard things are possible: in addition to advanced features like [global test environments](http://code.google.com/p/googletest/wiki/AdvancedGuide#Global_Set-Up_and_Tear-Down) and tests parameterized by [values](http://code.google.com/p/googletest/wiki/AdvancedGuide#Value_Parameterized_Tests) or [types](http://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests), Google Test supports various ways for the user to extend the framework -- if Google Test doesn't do something out of the box, chances are that a user can implement the feature using Google Test's public API, without changing Google Test itself.  In particular, you can:
+    * expand your testing vocabulary by defining [custom predicates](http://code.google.com/p/googletest/wiki/AdvancedGuide#Predicate_Assertions_for_Better_Error_Messages),
+    * teach Google Test how to [print your types](http://code.google.com/p/googletest/wiki/AdvancedGuide#Teaching_Google_Test_How_to_Print_Your_Values),
+    * define your own testing macros or utilities and verify them using Google Test's [Service Provider Interface](http://code.google.com/p/googletest/wiki/AdvancedGuide#Catching_Failures), and
+    * reflect on the test cases or change the test output format by intercepting the [test events](http://code.google.com/p/googletest/wiki/AdvancedGuide#Extending_Google_Test_by_Handling_Test_Events).
+
+## I'm getting warnings when compiling Google Test.  Would you fix them? ##
+
+We strive to minimize compiler warnings Google Test generates.  Before releasing a new version, we test to make sure that it doesn't generate warnings when compiled using its CMake script on Windows, Linux, and Mac OS.
+
+Unfortunately, this doesn't mean you are guaranteed to see no warnings when compiling Google Test in your environment:
+
+  * You may be using a different compiler as we use, or a different version of the same compiler.  We cannot possibly test for all compilers.
+  * You may be compiling on a different platform as we do.
+  * Your project may be using different compiler flags as we do.
+
+It is not always possible to make Google Test warning-free for everyone.  Or, it may not be desirable if the warning is rarely enabled and fixing the violations makes the code more complex.
+
+If you see warnings when compiling Google Test, we suggest that you use the `-isystem` flag (assuming your are using GCC) to mark Google Test headers as system headers.  That'll suppress warnings from Google Test headers.
+
+## Why should not test case names and test names contain underscore? ##
+
+Underscore (`_`) is special, as C++ reserves the following to be used by
+the compiler and the standard library:
+
+  1. any identifier that starts with an `_` followed by an upper-case letter, and
+  1. any identifier that containers two consecutive underscores (i.e. `__`) _anywhere_ in its name.
+
+User code is _prohibited_ from using such identifiers.
+
+Now let's look at what this means for `TEST` and `TEST_F`.
+
+Currently `TEST(TestCaseName, TestName)` generates a class named
+`TestCaseName_TestName_Test`.  What happens if `TestCaseName` or `TestName`
+contains `_`?
+
+  1. If `TestCaseName` starts with an `_` followed by an upper-case letter (say, `_Foo`), we end up with `_Foo_TestName_Test`, which is reserved and thus invalid.
+  1. If `TestCaseName` ends with an `_` (say, `Foo_`), we get `Foo__TestName_Test`, which is invalid.
+  1. If `TestName` starts with an `_` (say, `_Bar`), we get `TestCaseName__Bar_Test`, which is invalid.
+  1. If `TestName` ends with an `_` (say, `Bar_`), we get `TestCaseName_Bar__Test`, which is invalid.
+
+So clearly `TestCaseName` and `TestName` cannot start or end with `_`
+(Actually, `TestCaseName` can start with `_` -- as long as the `_` isn't
+followed by an upper-case letter.  But that's getting complicated.  So
+for simplicity we just say that it cannot start with `_`.).
+
+It may seem fine for `TestCaseName` and `TestName` to contain `_` in the
+middle.  However, consider this:
+```
+TEST(Time, Flies_Like_An_Arrow) { ... }
+TEST(Time_Flies, Like_An_Arrow) { ... }
+```
+
+Now, the two `TEST`s will both generate the same class
+(`Time_Files_Like_An_Arrow_Test`).  That's not good.
+
+So for simplicity, we just ask the users to avoid `_` in `TestCaseName`
+and `TestName`.  The rule is more constraining than necessary, but it's
+simple and easy to remember.  It also gives Google Test some wiggle
+room in case its implementation needs to change in the future.
+
+If you violate the rule, there may not be immediately consequences,
+but your test may (just may) break with a new compiler (or a new
+version of the compiler you are using) or with a new version of Google
+Test.  Therefore it's best to follow the rule.
+
+## Why is it not recommended to install a pre-compiled copy of Google Test (for example, into /usr/local)? ##
+
+In the early days, we said that you could install
+compiled Google Test libraries on `*`nix systems using `make install`.
+Then every user of your machine can write tests without
+recompiling Google Test.
+
+This seemed like a good idea, but it has a
+got-cha: every user needs to compile his tests using the _same_ compiler
+flags used to compile the installed Google Test libraries; otherwise
+he may run into undefined behaviors (i.e. the tests can behave
+strangely and may even crash for no obvious reasons).
+
+Why?  Because C++ has this thing called the One-Definition Rule: if
+two C++ source files contain different definitions of the same
+class/function/variable, and you link them together, you violate the
+rule.  The linker may or may not catch the error (in many cases it's
+not required by the C++ standard to catch the violation).  If it
+doesn't, you get strange run-time behaviors that are unexpected and
+hard to debug.
+
+If you compile Google Test and your test code using different compiler
+flags, they may see different definitions of the same
+class/function/variable (e.g. due to the use of `#if` in Google Test).
+Therefore, for your sanity, we recommend to avoid installing pre-compiled
+Google Test libraries.  Instead, each project should compile
+Google Test itself such that it can be sure that the same flags are
+used for both Google Test and the tests.
+
+## How do I generate 64-bit binaries on Windows (using Visual Studio 2008)? ##
+
+(Answered by Trevor Robinson)
+
+Load the supplied Visual Studio solution file, either `msvc\gtest-md.sln` or
+`msvc\gtest.sln`. Go through the migration wizard to migrate the
+solution and project files to Visual Studio 2008. Select
+`Configuration Manager...` from the `Build` menu. Select `<New...>` from
+the `Active solution platform` dropdown.  Select `x64` from the new
+platform dropdown, leave `Copy settings from` set to `Win32` and
+`Create new project platforms` checked, then click `OK`. You now have
+`Win32` and `x64` platform configurations, selectable from the
+`Standard` toolbar, which allow you to toggle between building 32-bit or
+64-bit binaries (or both at once using Batch Build).
+
+In order to prevent build output files from overwriting one another,
+you'll need to change the `Intermediate Directory` settings for the
+newly created platform configuration across all the projects. To do
+this, multi-select (e.g. using shift-click) all projects (but not the
+solution) in the `Solution Explorer`. Right-click one of them and
+select `Properties`. In the left pane, select `Configuration Properties`,
+and from the `Configuration` dropdown, select `All Configurations`.
+Make sure the selected platform is `x64`. For the
+`Intermediate Directory` setting, change the value from
+`$(PlatformName)\$(ConfigurationName)` to
+`$(OutDir)\$(ProjectName)`. Click `OK` and then build the
+solution. When the build is complete, the 64-bit binaries will be in
+the `msvc\x64\Debug` directory.
+
+## Can I use Google Test on MinGW? ##
+
+We haven't tested this ourselves, but Per Abrahamsen reported that he
+was able to compile and install Google Test successfully when using
+MinGW from Cygwin.  You'll need to configure it with:
+
+`PATH/TO/configure CC="gcc -mno-cygwin" CXX="g++ -mno-cygwin"`
+
+You should be able to replace the `-mno-cygwin` option with direct links
+to the real MinGW binaries, but we haven't tried that.
+
+Caveats:
+
+  * There are many warnings when compiling.
+  * `make check` will produce some errors as not all tests for Google Test itself are compatible with MinGW.
+
+We also have reports on successful cross compilation of Google Test
+MinGW binaries on Linux using
+[these instructions](http://wiki.wxwidgets.org/Cross-Compiling_Under_Linux#Cross-compiling_under_Linux_for_MS_Windows)
+on the WxWidgets site.
+
+Please contact `googletestframework@googlegroups.com` if you are
+interested in improving the support for MinGW.
+
+## Why does Google Test support EXPECT\_EQ(NULL, ptr) and ASSERT\_EQ(NULL, ptr) but not EXPECT\_NE(NULL, ptr) and ASSERT\_NE(NULL, ptr)? ##
+
+Due to some peculiarity of C++, it requires some non-trivial template
+meta programming tricks to support using `NULL` as an argument of the
+`EXPECT_XX()` and `ASSERT_XX()` macros. Therefore we only do it where
+it's most needed (otherwise we make the implementation of Google Test
+harder to maintain and more error-prone than necessary).
+
+The `EXPECT_EQ()` macro takes the _expected_ value as its first
+argument and the _actual_ value as the second. It's reasonable that
+someone wants to write `EXPECT_EQ(NULL, some_expression)`, and this
+indeed was requested several times. Therefore we implemented it.
+
+The need for `EXPECT_NE(NULL, ptr)` isn't nearly as strong. When the
+assertion fails, you already know that `ptr` must be `NULL`, so it
+doesn't add any information to print ptr in this case. That means
+`EXPECT_TRUE(ptr != NULL)` works just as well.
+
+If we were to support `EXPECT_NE(NULL, ptr)`, for consistency we'll
+have to support `EXPECT_NE(ptr, NULL)` as well, as unlike `EXPECT_EQ`,
+we don't have a convention on the order of the two arguments for
+`EXPECT_NE`. This means using the template meta programming tricks
+twice in the implementation, making it even harder to understand and
+maintain. We believe the benefit doesn't justify the cost.
+
+Finally, with the growth of Google Mock's [matcher](http://code.google.com/p/googlemock/wiki/CookBook#Using_Matchers_in_Google_Test_Assertions) library, we are
+encouraging people to use the unified `EXPECT_THAT(value, matcher)`
+syntax more often in tests. One significant advantage of the matcher
+approach is that matchers can be easily combined to form new matchers,
+while the `EXPECT_NE`, etc, macros cannot be easily
+combined. Therefore we want to invest more in the matchers than in the
+`EXPECT_XX()` macros.
+
+## Does Google Test support running tests in parallel? ##
+
+Test runners tend to be tightly coupled with the build/test
+environment, and Google Test doesn't try to solve the problem of
+running tests in parallel.  Instead, we tried to make Google Test work
+nicely with test runners.  For example, Google Test's XML report
+contains the time spent on each test, and its `gtest_list_tests` and
+`gtest_filter` flags can be used for splitting the execution of test
+methods into multiple processes.  These functionalities can help the
+test runner run the tests in parallel.
+
+## Why don't Google Test run the tests in different threads to speed things up? ##
+
+It's difficult to write thread-safe code.  Most tests are not written
+with thread-safety in mind, and thus may not work correctly in a
+multi-threaded setting.
+
+If you think about it, it's already hard to make your code work when
+you know what other threads are doing.  It's much harder, and
+sometimes even impossible, to make your code work when you don't know
+what other threads are doing (remember that test methods can be added,
+deleted, or modified after your test was written).  If you want to run
+the tests in parallel, you'd better run them in different processes.
+
+## Why aren't Google Test assertions implemented using exceptions? ##
+
+Our original motivation was to be able to use Google Test in projects
+that disable exceptions.  Later we realized some additional benefits
+of this approach:
+
+  1. Throwing in a destructor is undefined behavior in C++.  Not using exceptions means Google Test's assertions are safe to use in destructors.
+  1. The `EXPECT_*` family of macros will continue even after a failure, allowing multiple failures in a `TEST` to be reported in a single run. This is a popular feature, as in C++ the edit-compile-test cycle is usually quite long and being able to fixing more than one thing at a time is a blessing.
+  1. If assertions are implemented using exceptions, a test may falsely ignore a failure if it's caught by user code:
+```
+try { ... ASSERT_TRUE(...) ... }
+catch (...) { ... }
+```
+The above code will pass even if the `ASSERT_TRUE` throws.  While it's unlikely for someone to write this in a test, it's possible to run into this pattern when you write assertions in callbacks that are called by the code under test.
+
+The downside of not using exceptions is that `ASSERT_*` (implemented
+using `return`) will only abort the current function, not the current
+`TEST`.
+
+## Why do we use two different macros for tests with and without fixtures? ##
+
+Unfortunately, C++'s macro system doesn't allow us to use the same
+macro for both cases.  One possibility is to provide only one macro
+for tests with fixtures, and require the user to define an empty
+fixture sometimes:
+
+```
+class FooTest : public ::testing::Test {};
+
+TEST_F(FooTest, DoesThis) { ... }
+```
+or
+```
+typedef ::testing::Test FooTest;
+
+TEST_F(FooTest, DoesThat) { ... }
+```
+
+Yet, many people think this is one line too many. :-) Our goal was to
+make it really easy to write tests, so we tried to make simple tests
+trivial to create.  That means using a separate macro for such tests.
+
+We think neither approach is ideal, yet either of them is reasonable.
+In the end, it probably doesn't matter much either way.
+
+## Why don't we use structs as test fixtures? ##
+
+We like to use structs only when representing passive data.  This
+distinction between structs and classes is good for documenting the
+intent of the code's author.  Since test fixtures have logic like
+`SetUp()` and `TearDown()`, they are better defined as classes.
+
+## Why are death tests implemented as assertions instead of using a test runner? ##
+
+Our goal was to make death tests as convenient for a user as C++
+possibly allows.  In particular:
+
+  * The runner-style requires to split the information into two pieces: the definition of the death test itself, and the specification for the runner on how to run the death test and what to expect.  The death test would be written in C++, while the runner spec may or may not be.  A user needs to carefully keep the two in sync. `ASSERT_DEATH(statement, expected_message)` specifies all necessary information in one place, in one language, without boilerplate code. It is very declarative.
+  * `ASSERT_DEATH` has a similar syntax and error-reporting semantics as other Google Test assertions, and thus is easy to learn.
+  * `ASSERT_DEATH` can be mixed with other assertions and other logic at your will.  You are not limited to one death test per test method. For example, you can write something like:
+```
+    if (FooCondition()) {
+      ASSERT_DEATH(Bar(), "blah");
+    } else {
+      ASSERT_EQ(5, Bar());
+    }
+```
+If you prefer one death test per test method, you can write your tests in that style too, but we don't want to impose that on the users.  The fewer artificial limitations the better.
+  * `ASSERT_DEATH` can reference local variables in the current function, and you can decide how many death tests you want based on run-time information.  For example,
+```
+    const int count = GetCount();  // Only known at run time.
+    for (int i = 1; i <= count; i++) {
+      ASSERT_DEATH({
+        double* buffer = new double[i];
+        ... initializes buffer ...
+        Foo(buffer, i)
+      }, "blah blah");
+    }
+```
+The runner-based approach tends to be more static and less flexible, or requires more user effort to get this kind of flexibility.
+
+Another interesting thing about `ASSERT_DEATH` is that it calls `fork()`
+to create a child process to run the death test.  This is lightening
+fast, as `fork()` uses copy-on-write pages and incurs almost zero
+overhead, and the child process starts from the user-supplied
+statement directly, skipping all global and local initialization and
+any code leading to the given statement.  If you launch the child
+process from scratch, it can take seconds just to load everything and
+start running if the test links to many libraries dynamically.
+
+## My death test modifies some state, but the change seems lost after the death test finishes. Why? ##
+
+Death tests (`EXPECT_DEATH`, etc) are executed in a sub-process s.t. the
+expected crash won't kill the test program (i.e. the parent process). As a
+result, any in-memory side effects they incur are observable in their
+respective sub-processes, but not in the parent process. You can think of them
+as running in a parallel universe, more or less.
+
+## The compiler complains about "undefined references" to some static const member variables, but I did define them in the class body. What's wrong? ##
+
+If your class has a static data member:
+
+```
+// foo.h
+class Foo {
+  ...
+  static const int kBar = 100;
+};
+```
+
+You also need to define it _outside_ of the class body in `foo.cc`:
+
+```
+const int Foo::kBar;  // No initializer here.
+```
+
+Otherwise your code is **invalid C++**, and may break in unexpected ways. In
+particular, using it in Google Test comparison assertions (`EXPECT_EQ`, etc)
+will generate an "undefined reference" linker error.
+
+## I have an interface that has several implementations. Can I write a set of tests once and repeat them over all the implementations? ##
+
+Google Test doesn't yet have good support for this kind of tests, or
+data-driven tests in general. We hope to be able to make improvements in this
+area soon.
+
+## Can I derive a test fixture from another? ##
+
+Yes.
+
+Each test fixture has a corresponding and same named test case. This means only
+one test case can use a particular fixture. Sometimes, however, multiple test
+cases may want to use the same or slightly different fixtures. For example, you
+may want to make sure that all of a GUI library's test cases don't leak
+important system resources like fonts and brushes.
+
+In Google Test, you share a fixture among test cases by putting the shared
+logic in a base test fixture, then deriving from that base a separate fixture
+for each test case that wants to use this common logic. You then use `TEST_F()`
+to write tests using each derived fixture.
+
+Typically, your code looks like this:
+
+```
+// Defines a base test fixture.
+class BaseTest : public ::testing::Test {
+  protected:
+   ...
+};
+
+// Derives a fixture FooTest from BaseTest.
+class FooTest : public BaseTest {
+  protected:
+    virtual void SetUp() {
+      BaseTest::SetUp();  // Sets up the base fixture first.
+      ... additional set-up work ...
+    }
+    virtual void TearDown() {
+      ... clean-up work for FooTest ...
+      BaseTest::TearDown();  // Remember to tear down the base fixture
+                             // after cleaning up FooTest!
+    }
+    ... functions and variables for FooTest ...
+};
+
+// Tests that use the fixture FooTest.
+TEST_F(FooTest, Bar) { ... }
+TEST_F(FooTest, Baz) { ... }
+
+... additional fixtures derived from BaseTest ...
+```
+
+If necessary, you can continue to derive test fixtures from a derived fixture.
+Google Test has no limit on how deep the hierarchy can be.
+
+For a complete example using derived test fixtures, see
+[sample5](http://code.google.com/p/googletest/source/browse/trunk/samples/sample5_unittest.cc).
+
+## My compiler complains "void value not ignored as it ought to be." What does this mean? ##
+
+You're probably using an `ASSERT_*()` in a function that doesn't return `void`.
+`ASSERT_*()` can only be used in `void` functions.
+
+## My death test hangs (or seg-faults). How do I fix it? ##
+
+In Google Test, death tests are run in a child process and the way they work is
+delicate. To write death tests you really need to understand how they work.
+Please make sure you have read this.
+
+In particular, death tests don't like having multiple threads in the parent
+process. So the first thing you can try is to eliminate creating threads
+outside of `EXPECT_DEATH()`.
+
+Sometimes this is impossible as some library you must use may be creating
+threads before `main()` is even reached. In this case, you can try to minimize
+the chance of conflicts by either moving as many activities as possible inside
+`EXPECT_DEATH()` (in the extreme case, you want to move everything inside), or
+leaving as few things as possible in it. Also, you can try to set the death
+test style to `"threadsafe"`, which is safer but slower, and see if it helps.
+
+If you go with thread-safe death tests, remember that they rerun the test
+program from the beginning in the child process. Therefore make sure your
+program can run side-by-side with itself and is deterministic.
+
+In the end, this boils down to good concurrent programming. You have to make
+sure that there is no race conditions or dead locks in your program. No silver
+bullet - sorry!
+
+## Should I use the constructor/destructor of the test fixture or the set-up/tear-down function? ##
+
+The first thing to remember is that Google Test does not reuse the
+same test fixture object across multiple tests. For each `TEST_F`,
+Google Test will create a fresh test fixture object, _immediately_
+call `SetUp()`, run the test body, call `TearDown()`, and then
+_immediately_ delete the test fixture object.
+
+When you need to write per-test set-up and tear-down logic, you have
+the choice between using the test fixture constructor/destructor or
+`SetUp()/TearDown()`. The former is usually preferred, as it has the
+following benefits:
+
+  * By initializing a member variable in the constructor, we have the option to make it `const`, which helps prevent accidental changes to its value and makes the tests more obviously correct.
+  * In case we need to subclass the test fixture class, the subclass' constructor is guaranteed to call the base class' constructor first, and the subclass' destructor is guaranteed to call the base class' destructor afterward. With `SetUp()/TearDown()`, a subclass may make the mistake of forgetting to call the base class' `SetUp()/TearDown()` or call them at the wrong moment.
+
+You may still want to use `SetUp()/TearDown()` in the following rare cases:
+  * If the tear-down operation could throw an exception, you must use `TearDown()` as opposed to the destructor, as throwing in a destructor leads to undefined behavior and usually will kill your program right away. Note that many standard libraries (like STL) may throw when exceptions are enabled in the compiler. Therefore you should prefer `TearDown()` if you want to write portable tests that work with or without exceptions.
+  * The assertion macros throw an exception when flag `--gtest_throw_on_failure` is specified. Therefore, you shouldn't use Google Test assertions in a destructor if you plan to run your tests with this flag.
+  * In a constructor or destructor, you cannot make a virtual function call on this object. (You can call a method declared as virtual, but it will be statically bound.) Therefore, if you need to call a method that will be overriden in a derived class, you have to use `SetUp()/TearDown()`.
+
+## The compiler complains "no matching function to call" when I use ASSERT\_PREDn. How do I fix it? ##
+
+If the predicate function you use in `ASSERT_PRED*` or `EXPECT_PRED*` is
+overloaded or a template, the compiler will have trouble figuring out which
+overloaded version it should use. `ASSERT_PRED_FORMAT*` and
+`EXPECT_PRED_FORMAT*` don't have this problem.
+
+If you see this error, you might want to switch to
+`(ASSERT|EXPECT)_PRED_FORMAT*`, which will also give you a better failure
+message. If, however, that is not an option, you can resolve the problem by
+explicitly telling the compiler which version to pick.
+
+For example, suppose you have
+
+```
+bool IsPositive(int n) {
+  return n > 0;
+}
+bool IsPositive(double x) {
+  return x > 0;
+}
+```
+
+you will get a compiler error if you write
+
+```
+EXPECT_PRED1(IsPositive, 5);
+```
+
+However, this will work:
+
+```
+EXPECT_PRED1(*static_cast<bool (*)(int)>*(IsPositive), 5);
+```
+
+(The stuff inside the angled brackets for the `static_cast` operator is the
+type of the function pointer for the `int`-version of `IsPositive()`.)
+
+As another example, when you have a template function
+
+```
+template <typename T>
+bool IsNegative(T x) {
+  return x < 0;
+}
+```
+
+you can use it in a predicate assertion like this:
+
+```
+ASSERT_PRED1(IsNegative*<int>*, -5);
+```
+
+Things are more interesting if your template has more than one parameters. The
+following won't compile:
+
+```
+ASSERT_PRED2(*GreaterThan<int, int>*, 5, 0);
+```
+
+
+as the C++ pre-processor thinks you are giving `ASSERT_PRED2` 4 arguments,
+which is one more than expected. The workaround is to wrap the predicate
+function in parentheses:
+
+```
+ASSERT_PRED2(*(GreaterThan<int, int>)*, 5, 0);
+```
+
+
+## My compiler complains about "ignoring return value" when I call RUN\_ALL\_TESTS(). Why? ##
+
+Some people had been ignoring the return value of `RUN_ALL_TESTS()`. That is,
+instead of
+
+```
+return RUN_ALL_TESTS();
+```
+
+they write
+
+```
+RUN_ALL_TESTS();
+```
+
+This is wrong and dangerous. A test runner needs to see the return value of
+`RUN_ALL_TESTS()` in order to determine if a test has passed. If your `main()`
+function ignores it, your test will be considered successful even if it has a
+Google Test assertion failure. Very bad.
+
+To help the users avoid this dangerous bug, the implementation of
+`RUN_ALL_TESTS()` causes gcc to raise this warning, when the return value is
+ignored. If you see this warning, the fix is simple: just make sure its value
+is used as the return value of `main()`.
+
+## My compiler complains that a constructor (or destructor) cannot return a value. What's going on? ##
+
+Due to a peculiarity of C++, in order to support the syntax for streaming
+messages to an `ASSERT_*`, e.g.
+
+```
+ASSERT_EQ(1, Foo()) << "blah blah" << foo;
+```
+
+we had to give up using `ASSERT*` and `FAIL*` (but not `EXPECT*` and
+`ADD_FAILURE*`) in constructors and destructors. The workaround is to move the
+content of your constructor/destructor to a private void member function, or
+switch to `EXPECT_*()` if that works. This section in the user's guide explains
+it.
+
+## My set-up function is not called. Why? ##
+
+C++ is case-sensitive. It should be spelled as `SetUp()`.  Did you
+spell it as `Setup()`?
+
+Similarly, sometimes people spell `SetUpTestCase()` as `SetupTestCase()` and
+wonder why it's never called.
+
+## How do I jump to the line of a failure in Emacs directly? ##
+
+Google Test's failure message format is understood by Emacs and many other
+IDEs, like acme and XCode. If a Google Test message is in a compilation buffer
+in Emacs, then it's clickable. You can now hit `enter` on a message to jump to
+the corresponding source code, or use `C-x `` to jump to the next failure.
+
+## I have several test cases which share the same test fixture logic, do I have to define a new test fixture class for each of them? This seems pretty tedious. ##
+
+You don't have to. Instead of
+
+```
+class FooTest : public BaseTest {};
+
+TEST_F(FooTest, Abc) { ... }
+TEST_F(FooTest, Def) { ... }
+
+class BarTest : public BaseTest {};
+
+TEST_F(BarTest, Abc) { ... }
+TEST_F(BarTest, Def) { ... }
+```
+
+you can simply `typedef` the test fixtures:
+```
+typedef BaseTest FooTest;
+
+TEST_F(FooTest, Abc) { ... }
+TEST_F(FooTest, Def) { ... }
+
+typedef BaseTest BarTest;
+
+TEST_F(BarTest, Abc) { ... }
+TEST_F(BarTest, Def) { ... }
+```
+
+## The Google Test output is buried in a whole bunch of log messages. What do I do? ##
+
+The Google Test output is meant to be a concise and human-friendly report. If
+your test generates textual output itself, it will mix with the Google Test
+output, making it hard to read. However, there is an easy solution to this
+problem.
+
+Since most log messages go to stderr, we decided to let Google Test output go
+to stdout. This way, you can easily separate the two using redirection. For
+example:
+```
+./my_test > googletest_output.txt
+```
+
+## Why should I prefer test fixtures over global variables? ##
+
+There are several good reasons:
+  1. It's likely your test needs to change the states of its global variables. This makes it difficult to keep side effects from escaping one test and contaminating others, making debugging difficult. By using fixtures, each test has a fresh set of variables that's different (but with the same names). Thus, tests are kept independent of each other.
+  1. Global variables pollute the global namespace.
+  1. Test fixtures can be reused via subclassing, which cannot be done easily with global variables. This is useful if many test cases have something in common.
+
+## How do I test private class members without writing FRIEND\_TEST()s? ##
+
+You should try to write testable code, which means classes should be easily
+tested from their public interface. One way to achieve this is the Pimpl idiom:
+you move all private members of a class into a helper class, and make all
+members of the helper class public.
+
+You have several other options that don't require using `FRIEND_TEST`:
+  * Write the tests as members of the fixture class:
+```
+class Foo {
+  friend class FooTest;
+  ...
+};
+
+class FooTest : public ::testing::Test {
+ protected:
+  ...
+  void Test1() {...} // This accesses private members of class Foo.
+  void Test2() {...} // So does this one.
+};
+
+TEST_F(FooTest, Test1) {
+  Test1();
+}
+
+TEST_F(FooTest, Test2) {
+  Test2();
+}
+```
+  * In the fixture class, write accessors for the tested class' private members, then use the accessors in your tests:
+```
+class Foo {
+  friend class FooTest;
+  ...
+};
+
+class FooTest : public ::testing::Test {
+ protected:
+  ...
+  T1 get_private_member1(Foo* obj) {
+    return obj->private_member1_;
+  }
+};
+
+TEST_F(FooTest, Test1) {
+  ...
+  get_private_member1(x)
+  ...
+}
+```
+  * If the methods are declared **protected**, you can change their access level in a test-only subclass:
+```
+class YourClass {
+  ...
+ protected: // protected access for testability.
+  int DoSomethingReturningInt();
+  ...
+};
+
+// in the your_class_test.cc file:
+class TestableYourClass : public YourClass {
+  ...
+ public: using YourClass::DoSomethingReturningInt; // changes access rights
+  ...
+};
+
+TEST_F(YourClassTest, DoSomethingTest) {
+  TestableYourClass obj;
+  assertEquals(expected_value, obj.DoSomethingReturningInt());
+}
+```
+
+## How do I test private class static members without writing FRIEND\_TEST()s? ##
+
+We find private static methods clutter the header file.  They are
+implementation details and ideally should be kept out of a .h. So often I make
+them free functions instead.
+
+Instead of:
+```
+// foo.h
+class Foo {
+  ...
+ private:
+  static bool Func(int n);
+};
+
+// foo.cc
+bool Foo::Func(int n) { ... }
+
+// foo_test.cc
+EXPECT_TRUE(Foo::Func(12345));
+```
+
+You probably should better write:
+```
+// foo.h
+class Foo {
+  ...
+};
+
+// foo.cc
+namespace internal {
+  bool Func(int n) { ... }
+}
+
+// foo_test.cc
+namespace internal {
+  bool Func(int n);
+}
+
+EXPECT_TRUE(internal::Func(12345));
+```
+
+## I would like to run a test several times with different parameters. Do I need to write several similar copies of it? ##
+
+No. You can use a feature called [value-parameterized tests](AdvancedGuide#Value_Parameterized_Tests.md) which
+lets you repeat your tests with different parameters, without defining it more than once.
+
+## How do I test a file that defines main()? ##
+
+To test a `foo.cc` file, you need to compile and link it into your unit test
+program. However, when the file contains a definition for the `main()`
+function, it will clash with the `main()` of your unit test, and will result in
+a build error.
+
+The right solution is to split it into three files:
+  1. `foo.h` which contains the declarations,
+  1. `foo.cc` which contains the definitions except `main()`, and
+  1. `foo_main.cc` which contains nothing but the definition of `main()`.
+
+Then `foo.cc` can be easily tested.
+
+If you are adding tests to an existing file and don't want an intrusive change
+like this, there is a hack: just include the entire `foo.cc` file in your unit
+test. For example:
+```
+// File foo_unittest.cc
+
+// The headers section
+...
+
+// Renames main() in foo.cc to make room for the unit test main()
+#define main FooMain
+
+#include "a/b/foo.cc"
+
+// The tests start here.
+...
+```
+
+
+However, please remember this is a hack and should only be used as the last
+resort.
+
+## What can the statement argument in ASSERT\_DEATH() be? ##
+
+`ASSERT_DEATH(_statement_, _regex_)` (or any death assertion macro) can be used
+wherever `_statement_` is valid. So basically `_statement_` can be any C++
+statement that makes sense in the current context. In particular, it can
+reference global and/or local variables, and can be:
+  * a simple function call (often the case),
+  * a complex expression, or
+  * a compound statement.
+
+> Some examples are shown here:
+```
+// A death test can be a simple function call.
+TEST(MyDeathTest, FunctionCall) {
+  ASSERT_DEATH(Xyz(5), "Xyz failed");
+}
+
+// Or a complex expression that references variables and functions.
+TEST(MyDeathTest, ComplexExpression) {
+  const bool c = Condition();
+  ASSERT_DEATH((c ? Func1(0) : object2.Method("test")),
+               "(Func1|Method) failed");
+}
+
+// Death assertions can be used any where in a function. In
+// particular, they can be inside a loop.
+TEST(MyDeathTest, InsideLoop) {
+  // Verifies that Foo(0), Foo(1), ..., and Foo(4) all die.
+  for (int i = 0; i < 5; i++) {
+    EXPECT_DEATH_M(Foo(i), "Foo has \\d+ errors",
+                   ::testing::Message() << "where i is " << i);
+  }
+}
+
+// A death assertion can contain a compound statement.
+TEST(MyDeathTest, CompoundStatement) {
+  // Verifies that at lease one of Bar(0), Bar(1), ..., and
+  // Bar(4) dies.
+  ASSERT_DEATH({
+    for (int i = 0; i < 5; i++) {
+      Bar(i);
+    }
+  },
+  "Bar has \\d+ errors");}
+```
+
+`googletest_unittest.cc` contains more examples if you are interested.
+
+## What syntax does the regular expression in ASSERT\_DEATH use? ##
+
+On POSIX systems, Google Test uses the POSIX Extended regular
+expression syntax
+(http://en.wikipedia.org/wiki/Regular_expression#POSIX_Extended_Regular_Expressions).
+On Windows, it uses a limited variant of regular expression
+syntax. For more details, see the
+[regular expression syntax](AdvancedGuide#Regular_Expression_Syntax.md).
+
+## I have a fixture class Foo, but TEST\_F(Foo, Bar) gives me error "no matching function for call to Foo::Foo()". Why? ##
+
+Google Test needs to be able to create objects of your test fixture class, so
+it must have a default constructor. Normally the compiler will define one for
+you. However, there are cases where you have to define your own:
+  * If you explicitly declare a non-default constructor for class `Foo`, then you need to define a default constructor, even if it would be empty.
+  * If `Foo` has a const non-static data member, then you have to define the default constructor _and_ initialize the const member in the initializer list of the constructor. (Early versions of `gcc` doesn't force you to initialize the const member. It's a bug that has been fixed in `gcc 4`.)
+
+## Why does ASSERT\_DEATH complain about previous threads that were already joined? ##
+
+With the Linux pthread library, there is no turning back once you cross the
+line from single thread to multiple threads. The first time you create a
+thread, a manager thread is created in addition, so you get 3, not 2, threads.
+Later when the thread you create joins the main thread, the thread count
+decrements by 1, but the manager thread will never be killed, so you still have
+2 threads, which means you cannot safely run a death test.
+
+The new NPTL thread library doesn't suffer from this problem, as it doesn't
+create a manager thread. However, if you don't control which machine your test
+runs on, you shouldn't depend on this.
+
+## Why does Google Test require the entire test case, instead of individual tests, to be named FOODeathTest when it uses ASSERT\_DEATH? ##
+
+Google Test does not interleave tests from different test cases. That is, it
+runs all tests in one test case first, and then runs all tests in the next test
+case, and so on. Google Test does this because it needs to set up a test case
+before the first test in it is run, and tear it down afterwords. Splitting up
+the test case would require multiple set-up and tear-down processes, which is
+inefficient and makes the semantics unclean.
+
+If we were to determine the order of tests based on test name instead of test
+case name, then we would have a problem with the following situation:
+
+```
+TEST_F(FooTest, AbcDeathTest) { ... }
+TEST_F(FooTest, Uvw) { ... }
+
+TEST_F(BarTest, DefDeathTest) { ... }
+TEST_F(BarTest, Xyz) { ... }
+```
+
+Since `FooTest.AbcDeathTest` needs to run before `BarTest.Xyz`, and we don't
+interleave tests from different test cases, we need to run all tests in the
+`FooTest` case before running any test in the `BarTest` case. This contradicts
+with the requirement to run `BarTest.DefDeathTest` before `FooTest.Uvw`.
+
+## But I don't like calling my entire test case FOODeathTest when it contains both death tests and non-death tests. What do I do? ##
+
+You don't have to, but if you like, you may split up the test case into
+`FooTest` and `FooDeathTest`, where the names make it clear that they are
+related:
+
+```
+class FooTest : public ::testing::Test { ... };
+
+TEST_F(FooTest, Abc) { ... }
+TEST_F(FooTest, Def) { ... }
+
+typedef FooTest FooDeathTest;
+
+TEST_F(FooDeathTest, Uvw) { ... EXPECT_DEATH(...) ... }
+TEST_F(FooDeathTest, Xyz) { ... ASSERT_DEATH(...) ... }
+```
+
+## The compiler complains about "no match for 'operator<<'" when I use an assertion. What gives? ##
+
+If you use a user-defined type `FooType` in an assertion, you must make sure
+there is an `std::ostream& operator<<(std::ostream&, const FooType&)` function
+defined such that we can print a value of `FooType`.
+
+In addition, if `FooType` is declared in a name space, the `<<` operator also
+needs to be defined in the _same_ name space.
+
+## How do I suppress the memory leak messages on Windows? ##
+
+Since the statically initialized Google Test singleton requires allocations on
+the heap, the Visual C++ memory leak detector will report memory leaks at the
+end of the program run. The easiest way to avoid this is to use the
+`_CrtMemCheckpoint` and `_CrtMemDumpAllObjectsSince` calls to not report any
+statically initialized heap objects. See MSDN for more details and additional
+heap check/debug routines.
+
+## I am building my project with Google Test in Visual Studio and all I'm getting is a bunch of linker errors (or warnings). Help! ##
+
+You may get a number of the following linker error or warnings if you
+attempt to link your test project with the Google Test library when
+your project and the are not built using the same compiler settings.
+
+  * LNK2005: symbol already defined in object
+  * LNK4217: locally defined symbol 'symbol' imported in function 'function'
+  * LNK4049: locally defined symbol 'symbol' imported
+
+The Google Test project (gtest.vcproj) has the Runtime Library option
+set to /MT (use multi-threaded static libraries, /MTd for debug). If
+your project uses something else, for example /MD (use multi-threaded
+DLLs, /MDd for debug), you need to change the setting in the Google
+Test project to match your project's.
+
+To update this setting open the project properties in the Visual
+Studio IDE then select the branch Configuration Properties | C/C++ |
+Code Generation and change the option "Runtime Library".  You may also try
+using gtest-md.vcproj instead of gtest.vcproj.
+
+## I put my tests in a library and Google Test doesn't run them. What's happening? ##
+Have you read a
+[warning](http://code.google.com/p/googletest/wiki/Primer#Important_note_for_Visual_C++_users) on
+the Google Test Primer page?
+
+## I want to use Google Test with Visual Studio but don't know where to start. ##
+Many people are in your position and one of the posted his solution to
+our mailing list. Here is his link:
+http://hassanjamilahmad.blogspot.com/2009/07/gtest-starters-help.html.
+
+## I am seeing compile errors mentioning std::type\_traits when I try to use Google Test on Solaris. ##
+Google Test uses parts of the standard C++ library that SunStudio does not support.
+Our users reported success using alternative implementations. Try running the build after runing this commad:
+
+`export CC=cc CXX=CC CXXFLAGS='-library=stlport4'`
+
+## How can my code detect if it is running in a test? ##
+
+If you write code that sniffs whether it's running in a test and does
+different things accordingly, you are leaking test-only logic into
+production code and there is no easy way to ensure that the test-only
+code paths aren't run by mistake in production.  Such cleverness also
+leads to
+[Heisenbugs](http://en.wikipedia.org/wiki/Unusual_software_bug#Heisenbug).
+Therefore we strongly advise against the practice, and Google Test doesn't
+provide a way to do it.
+
+In general, the recommended way to cause the code to behave
+differently under test is [dependency injection](http://jamesshore.com/Blog/Dependency-Injection-Demystified.html).
+You can inject different functionality from the test and from the
+production code.  Since your production code doesn't link in the
+for-test logic at all, there is no danger in accidentally running it.
+
+However, if you _really_, _really_, _really_ have no choice, and if
+you follow the rule of ending your test program names with `_test`,
+you can use the _horrible_ hack of sniffing your executable name
+(`argv[0]` in `main()`) to know whether the code is under test.
+
+## Google Test defines a macro that clashes with one defined by another library. How do I deal with that? ##
+
+In C++, macros don't obey namespaces.  Therefore two libraries that
+both define a macro of the same name will clash if you #include both
+definitions.  In case a Google Test macro clashes with another
+library, you can force Google Test to rename its macro to avoid the
+conflict.
+
+Specifically, if both Google Test and some other code define macro
+`FOO`, you can add
+```
+  -DGTEST_DONT_DEFINE_FOO=1
+```
+to the compiler flags to tell Google Test to change the macro's name
+from `FOO` to `GTEST_FOO`. For example, with `-DGTEST_DONT_DEFINE_TEST=1`, you'll need to write
+```
+  GTEST_TEST(SomeTest, DoesThis) { ... }
+```
+instead of
+```
+  TEST(SomeTest, DoesThis) { ... }
+```
+in order to define a test.
+
+Currently, the following `TEST`, `FAIL`, `SUCCEED`, and the basic comparison assertion macros can have alternative names. You can see the full list of covered macros [here](http://www.google.com/codesearch?q=if+!GTEST_DONT_DEFINE_\w%2B+package:http://googletest\.googlecode\.com+file:/include/gtest/gtest.h). More information can be found in the "Avoiding Macro Name Clashes" section of the README file.
+
+
+## Is it OK if I have two separate `TEST(Foo, Bar)` test methods defined in different namespaces? ##
+
+Yes.
+
+The rule is **all test methods in the same test case must use the same fixture class**. This means that the following is **allowed** because both tests use the same fixture class (`::testing::Test`).
+
+```
+namespace foo {
+TEST(CoolTest, DoSomething) {
+  SUCCEED();
+}
+}  // namespace foo
+
+namespace bar {
+TEST(CoolTest, DoSomething) {
+  SUCCEED();
+}
+}  // namespace foo
+```
+
+However, the following code is **not allowed** and will produce a runtime error from Google Test because the test methods are using different test fixture classes with the same test case name.
+
+```
+namespace foo {
+class CoolTest : public ::testing::Test {};  // Fixture foo::CoolTest
+TEST_F(CoolTest, DoSomething) {
+  SUCCEED();
+}
+}  // namespace foo
+
+namespace bar {
+class CoolTest : public ::testing::Test {};  // Fixture: bar::CoolTest
+TEST_F(CoolTest, DoSomething) {
+  SUCCEED();
+}
+}  // namespace foo
+```
+
+## How do I build Google Testing Framework with Xcode 4? ##
+
+If you try to build Google Test's Xcode project with Xcode 4.0 or later, you may encounter an error message that looks like
+"Missing SDK in target gtest\_framework: /Developer/SDKs/MacOSX10.4u.sdk". That means that Xcode does not support the SDK the project is targeting. See the Xcode section in the [README](http://code.google.com/p/googletest/source/browse/trunk/README) file on how to resolve this.
+
+## My question is not covered in your FAQ! ##
+
+If you cannot find the answer to your question in this FAQ, there are
+some other resources you can use:
+
+  1. read other [wiki pages](http://code.google.com/p/googletest/w/list),
+  1. search the mailing list [archive](http://groups.google.com/group/googletestframework/topics),
+  1. ask it on [googletestframework@googlegroups.com](mailto:googletestframework@googlegroups.com) and someone will answer it (to prevent spam, we require you to join the [discussion group](http://groups.google.com/group/googletestframework) before you can post.).
+
+Please note that creating an issue in the
+[issue tracker](http://code.google.com/p/googletest/issues/list) is _not_
+a good way to get your answer, as it is monitored infrequently by a
+very small number of people.
+
+When asking a question, it's helpful to provide as much of the
+following information as possible (people cannot help you if there's
+not enough information in your question):
+
+  * the version (or the revision number if you check out from SVN directly) of Google Test you use (Google Test is under active development, so it's possible that your problem has been solved in a later version),
+  * your operating system,
+  * the name and version of your compiler,
+  * the complete command line flags you give to your compiler,
+  * the complete compiler error messages (if the question is about compilation),
+  * the _actual_ code (ideally, a minimal but complete program) that has the problem you encounter.
\ No newline at end of file
diff --git a/third_party/googletest/googletest/docs/Primer.md b/third_party/googletest/googletest/docs/Primer.md
new file mode 100644
index 0000000..dbe6c77
--- /dev/null
+++ b/third_party/googletest/googletest/docs/Primer.md
@@ -0,0 +1,501 @@
+
+
+# Introduction: Why Google C++ Testing Framework? #
+
+_Google C++ Testing Framework_ helps you write better C++ tests.
+
+No matter whether you work on Linux, Windows, or a Mac, if you write C++ code,
+Google Test can help you.
+
+So what makes a good test, and how does Google C++ Testing Framework fit in? We believe:
+  1. Tests should be _independent_ and _repeatable_. It's a pain to debug a test that succeeds or fails as a result of other tests.  Google C++ Testing Framework isolates the tests by running each of them on a different object. When a test fails, Google C++ Testing Framework allows you to run it in isolation for quick debugging.
+  1. Tests should be well _organized_ and reflect the structure of the tested code.  Google C++ Testing Framework groups related tests into test cases that can share data and subroutines. This common pattern is easy to recognize and makes tests easy to maintain. Such consistency is especially helpful when people switch projects and start to work on a new code base.
+  1. Tests should be _portable_ and _reusable_. The open-source community has a lot of code that is platform-neutral, its tests should also be platform-neutral.  Google C++ Testing Framework works on different OSes, with different compilers (gcc, MSVC, and others), with or without exceptions, so Google C++ Testing Framework tests can easily work with a variety of configurations.  (Note that the current release only contains build scripts for Linux - we are actively working on scripts for other platforms.)
+  1. When tests fail, they should provide as much _information_ about the problem as possible. Google C++ Testing Framework doesn't stop at the first test failure. Instead, it only stops the current test and continues with the next. You can also set up tests that report non-fatal failures after which the current test continues. Thus, you can detect and fix multiple bugs in a single run-edit-compile cycle.
+  1. The testing framework should liberate test writers from housekeeping chores and let them focus on the test _content_.  Google C++ Testing Framework automatically keeps track of all tests defined, and doesn't require the user to enumerate them in order to run them.
+  1. Tests should be _fast_. With Google C++ Testing Framework, you can reuse shared resources across tests and pay for the set-up/tear-down only once, without making tests depend on each other.
+
+Since Google C++ Testing Framework is based on the popular xUnit
+architecture, you'll feel right at home if you've used JUnit or PyUnit before.
+If not, it will take you about 10 minutes to learn the basics and get started.
+So let's go!
+
+_Note:_ We sometimes refer to Google C++ Testing Framework informally
+as _Google Test_.
+
+# Setting up a New Test Project #
+
+To write a test program using Google Test, you need to compile Google
+Test into a library and link your test with it.  We provide build
+files for some popular build systems: `msvc/` for Visual Studio,
+`xcode/` for Mac Xcode, `make/` for GNU make, `codegear/` for Borland
+C++ Builder, and the autotools script (deprecated) and
+`CMakeLists.txt` for CMake (recommended) in the Google Test root
+directory.  If your build system is not on this list, you can take a
+look at `make/Makefile` to learn how Google Test should be compiled
+(basically you want to compile `src/gtest-all.cc` with `GTEST_ROOT`
+and `GTEST_ROOT/include` in the header search path, where `GTEST_ROOT`
+is the Google Test root directory).
+
+Once you are able to compile the Google Test library, you should
+create a project or build target for your test program.  Make sure you
+have `GTEST_ROOT/include` in the header search path so that the
+compiler can find `"gtest/gtest.h"` when compiling your test.  Set up
+your test project to link with the Google Test library (for example,
+in Visual Studio, this is done by adding a dependency on
+`gtest.vcproj`).
+
+If you still have questions, take a look at how Google Test's own
+tests are built and use them as examples.
+
+# Basic Concepts #
+
+When using Google Test, you start by writing _assertions_, which are statements
+that check whether a condition is true. An assertion's result can be _success_,
+_nonfatal failure_, or _fatal failure_. If a fatal failure occurs, it aborts
+the current function; otherwise the program continues normally.
+
+_Tests_ use assertions to verify the tested code's behavior. If a test crashes
+or has a failed assertion, then it _fails_; otherwise it _succeeds_.
+
+A _test case_ contains one or many tests. You should group your tests into test
+cases that reflect the structure of the tested code. When multiple tests in a
+test case need to share common objects and subroutines, you can put them into a
+_test fixture_ class.
+
+A _test program_ can contain multiple test cases.
+
+We'll now explain how to write a test program, starting at the individual
+assertion level and building up to tests and test cases.
+
+# Assertions #
+
+Google Test assertions are macros that resemble function calls. You test a
+class or function by making assertions about its behavior. When an assertion
+fails, Google Test prints the assertion's source file and line number location,
+along with a failure message. You may also supply a custom failure message
+which will be appended to Google Test's message.
+
+The assertions come in pairs that test the same thing but have different
+effects on the current function. `ASSERT_*` versions generate fatal failures
+when they fail, and **abort the current function**. `EXPECT_*` versions generate
+nonfatal failures, which don't abort the current function. Usually `EXPECT_*`
+are preferred, as they allow more than one failures to be reported in a test.
+However, you should use `ASSERT_*` if it doesn't make sense to continue when
+the assertion in question fails.
+
+Since a failed `ASSERT_*` returns from the current function immediately,
+possibly skipping clean-up code that comes after it, it may cause a space leak.
+Depending on the nature of the leak, it may or may not be worth fixing - so
+keep this in mind if you get a heap checker error in addition to assertion
+errors.
+
+To provide a custom failure message, simply stream it into the macro using the
+`<<` operator, or a sequence of such operators. An example:
+```
+ASSERT_EQ(x.size(), y.size()) << "Vectors x and y are of unequal length";
+
+for (int i = 0; i < x.size(); ++i) {
+  EXPECT_EQ(x[i], y[i]) << "Vectors x and y differ at index " << i;
+}
+```
+
+Anything that can be streamed to an `ostream` can be streamed to an assertion
+macro--in particular, C strings and `string` objects. If a wide string
+(`wchar_t*`, `TCHAR*` in `UNICODE` mode on Windows, or `std::wstring`) is
+streamed to an assertion, it will be translated to UTF-8 when printed.
+
+## Basic Assertions ##
+
+These assertions do basic true/false condition testing.
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_TRUE(`_condition_`)`;  | `EXPECT_TRUE(`_condition_`)`;   | _condition_ is true |
+| `ASSERT_FALSE(`_condition_`)`; | `EXPECT_FALSE(`_condition_`)`;  | _condition_ is false |
+
+Remember, when they fail, `ASSERT_*` yields a fatal failure and
+returns from the current function, while `EXPECT_*` yields a nonfatal
+failure, allowing the function to continue running. In either case, an
+assertion failure means its containing test fails.
+
+_Availability_: Linux, Windows, Mac.
+
+## Binary Comparison ##
+
+This section describes assertions that compare two values.
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+|`ASSERT_EQ(`_expected_`, `_actual_`);`|`EXPECT_EQ(`_expected_`, `_actual_`);`| _expected_ `==` _actual_ |
+|`ASSERT_NE(`_val1_`, `_val2_`);`      |`EXPECT_NE(`_val1_`, `_val2_`);`      | _val1_ `!=` _val2_ |
+|`ASSERT_LT(`_val1_`, `_val2_`);`      |`EXPECT_LT(`_val1_`, `_val2_`);`      | _val1_ `<` _val2_ |
+|`ASSERT_LE(`_val1_`, `_val2_`);`      |`EXPECT_LE(`_val1_`, `_val2_`);`      | _val1_ `<=` _val2_ |
+|`ASSERT_GT(`_val1_`, `_val2_`);`      |`EXPECT_GT(`_val1_`, `_val2_`);`      | _val1_ `>` _val2_ |
+|`ASSERT_GE(`_val1_`, `_val2_`);`      |`EXPECT_GE(`_val1_`, `_val2_`);`      | _val1_ `>=` _val2_ |
+
+In the event of a failure, Google Test prints both _val1_ and _val2_
+. In `ASSERT_EQ*` and `EXPECT_EQ*` (and all other equality assertions
+we'll introduce later), you should put the expression you want to test
+in the position of _actual_, and put its expected value in _expected_,
+as Google Test's failure messages are optimized for this convention.
+
+Value arguments must be comparable by the assertion's comparison
+operator or you'll get a compiler error.  We used to require the
+arguments to support the `<<` operator for streaming to an `ostream`,
+but it's no longer necessary since v1.6.0 (if `<<` is supported, it
+will be called to print the arguments when the assertion fails;
+otherwise Google Test will attempt to print them in the best way it
+can. For more details and how to customize the printing of the
+arguments, see this Google Mock [recipe](http://code.google.com/p/googlemock/wiki/CookBook#Teaching_Google_Mock_How_to_Print_Your_Values).).
+
+These assertions can work with a user-defined type, but only if you define the
+corresponding comparison operator (e.g. `==`, `<`, etc).  If the corresponding
+operator is defined, prefer using the `ASSERT_*()` macros because they will
+print out not only the result of the comparison, but the two operands as well.
+
+Arguments are always evaluated exactly once. Therefore, it's OK for the
+arguments to have side effects. However, as with any ordinary C/C++ function,
+the arguments' evaluation order is undefined (i.e. the compiler is free to
+choose any order) and your code should not depend on any particular argument
+evaluation order.
+
+`ASSERT_EQ()` does pointer equality on pointers. If used on two C strings, it
+tests if they are in the same memory location, not if they have the same value.
+Therefore, if you want to compare C strings (e.g. `const char*`) by value, use
+`ASSERT_STREQ()` , which will be described later on. In particular, to assert
+that a C string is `NULL`, use `ASSERT_STREQ(NULL, c_string)` . However, to
+compare two `string` objects, you should use `ASSERT_EQ`.
+
+Macros in this section work with both narrow and wide string objects (`string`
+and `wstring`).
+
+_Availability_: Linux, Windows, Mac.
+
+## String Comparison ##
+
+The assertions in this group compare two **C strings**. If you want to compare
+two `string` objects, use `EXPECT_EQ`, `EXPECT_NE`, and etc instead.
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_STREQ(`_expected\_str_`, `_actual\_str_`);`    | `EXPECT_STREQ(`_expected\_str_`, `_actual\_str_`);`     | the two C strings have the same content |
+| `ASSERT_STRNE(`_str1_`, `_str2_`);`    | `EXPECT_STRNE(`_str1_`, `_str2_`);`     | the two C strings have different content |
+| `ASSERT_STRCASEEQ(`_expected\_str_`, `_actual\_str_`);`| `EXPECT_STRCASEEQ(`_expected\_str_`, `_actual\_str_`);` | the two C strings have the same content, ignoring case |
+| `ASSERT_STRCASENE(`_str1_`, `_str2_`);`| `EXPECT_STRCASENE(`_str1_`, `_str2_`);` | the two C strings have different content, ignoring case |
+
+Note that "CASE" in an assertion name means that case is ignored.
+
+`*STREQ*` and `*STRNE*` also accept wide C strings (`wchar_t*`). If a
+comparison of two wide strings fails, their values will be printed as UTF-8
+narrow strings.
+
+A `NULL` pointer and an empty string are considered _different_.
+
+_Availability_: Linux, Windows, Mac.
+
+See also: For more string comparison tricks (substring, prefix, suffix, and
+regular expression matching, for example), see the [Advanced Google Test Guide](AdvancedGuide.md).
+
+# Simple Tests #
+
+To create a test:
+  1. Use the `TEST()` macro to define and name a test function, These are ordinary C++ functions that don't return a value.
+  1. In this function, along with any valid C++ statements you want to include, use the various Google Test assertions to check values.
+  1. The test's result is determined by the assertions; if any assertion in the test fails (either fatally or non-fatally), or if the test crashes, the entire test fails. Otherwise, it succeeds.
+
+```
+TEST(test_case_name, test_name) {
+ ... test body ...
+}
+```
+
+
+`TEST()` arguments go from general to specific. The _first_ argument is the
+name of the test case, and the _second_ argument is the test's name within the
+test case. Both names must be valid C++ identifiers, and they should not contain underscore (`_`). A test's _full name_ consists of its containing test case and its
+individual name. Tests from different test cases can have the same individual
+name.
+
+For example, let's take a simple integer function:
+```
+int Factorial(int n); // Returns the factorial of n
+```
+
+A test case for this function might look like:
+```
+// Tests factorial of 0.
+TEST(FactorialTest, HandlesZeroInput) {
+  EXPECT_EQ(1, Factorial(0));
+}
+
+// Tests factorial of positive numbers.
+TEST(FactorialTest, HandlesPositiveInput) {
+  EXPECT_EQ(1, Factorial(1));
+  EXPECT_EQ(2, Factorial(2));
+  EXPECT_EQ(6, Factorial(3));
+  EXPECT_EQ(40320, Factorial(8));
+}
+```
+
+Google Test groups the test results by test cases, so logically-related tests
+should be in the same test case; in other words, the first argument to their
+`TEST()` should be the same. In the above example, we have two tests,
+`HandlesZeroInput` and `HandlesPositiveInput`, that belong to the same test
+case `FactorialTest`.
+
+_Availability_: Linux, Windows, Mac.
+
+# Test Fixtures: Using the Same Data Configuration for Multiple Tests #
+
+If you find yourself writing two or more tests that operate on similar data,
+you can use a _test fixture_. It allows you to reuse the same configuration of
+objects for several different tests.
+
+To create a fixture, just:
+  1. Derive a class from `::testing::Test` . Start its body with `protected:` or `public:` as we'll want to access fixture members from sub-classes.
+  1. Inside the class, declare any objects you plan to use.
+  1. If necessary, write a default constructor or `SetUp()` function to prepare the objects for each test. A common mistake is to spell `SetUp()` as `Setup()` with a small `u` - don't let that happen to you.
+  1. If necessary, write a destructor or `TearDown()` function to release any resources you allocated in `SetUp()` . To learn when you should use the constructor/destructor and when you should use `SetUp()/TearDown()`, read this [FAQ entry](http://code.google.com/p/googletest/wiki/FAQ#Should_I_use_the_constructor/destructor_of_the_test_fixture_or_t).
+  1. If needed, define subroutines for your tests to share.
+
+When using a fixture, use `TEST_F()` instead of `TEST()` as it allows you to
+access objects and subroutines in the test fixture:
+```
+TEST_F(test_case_name, test_name) {
+ ... test body ...
+}
+```
+
+Like `TEST()`, the first argument is the test case name, but for `TEST_F()`
+this must be the name of the test fixture class. You've probably guessed: `_F`
+is for fixture.
+
+Unfortunately, the C++ macro system does not allow us to create a single macro
+that can handle both types of tests. Using the wrong macro causes a compiler
+error.
+
+Also, you must first define a test fixture class before using it in a
+`TEST_F()`, or you'll get the compiler error "`virtual outside class
+declaration`".
+
+For each test defined with `TEST_F()`, Google Test will:
+  1. Create a _fresh_ test fixture at runtime
+  1. Immediately initialize it via `SetUp()` ,
+  1. Run the test
+  1. Clean up by calling `TearDown()`
+  1. Delete the test fixture.  Note that different tests in the same test case have different test fixture objects, and Google Test always deletes a test fixture before it creates the next one. Google Test does not reuse the same test fixture for multiple tests. Any changes one test makes to the fixture do not affect other tests.
+
+As an example, let's write tests for a FIFO queue class named `Queue`, which
+has the following interface:
+```
+template <typename E> // E is the element type.
+class Queue {
+ public:
+  Queue();
+  void Enqueue(const E& element);
+  E* Dequeue(); // Returns NULL if the queue is empty.
+  size_t size() const;
+  ...
+};
+```
+
+First, define a fixture class. By convention, you should give it the name
+`FooTest` where `Foo` is the class being tested.
+```
+class QueueTest : public ::testing::Test {
+ protected:
+  virtual void SetUp() {
+    q1_.Enqueue(1);
+    q2_.Enqueue(2);
+    q2_.Enqueue(3);
+  }
+
+  // virtual void TearDown() {}
+
+  Queue<int> q0_;
+  Queue<int> q1_;
+  Queue<int> q2_;
+};
+```
+
+In this case, `TearDown()` is not needed since we don't have to clean up after
+each test, other than what's already done by the destructor.
+
+Now we'll write tests using `TEST_F()` and this fixture.
+```
+TEST_F(QueueTest, IsEmptyInitially) {
+  EXPECT_EQ(0, q0_.size());
+}
+
+TEST_F(QueueTest, DequeueWorks) {
+  int* n = q0_.Dequeue();
+  EXPECT_EQ(NULL, n);
+
+  n = q1_.Dequeue();
+  ASSERT_TRUE(n != NULL);
+  EXPECT_EQ(1, *n);
+  EXPECT_EQ(0, q1_.size());
+  delete n;
+
+  n = q2_.Dequeue();
+  ASSERT_TRUE(n != NULL);
+  EXPECT_EQ(2, *n);
+  EXPECT_EQ(1, q2_.size());
+  delete n;
+}
+```
+
+The above uses both `ASSERT_*` and `EXPECT_*` assertions. The rule of thumb is
+to use `EXPECT_*` when you want the test to continue to reveal more errors
+after the assertion failure, and use `ASSERT_*` when continuing after failure
+doesn't make sense. For example, the second assertion in the `Dequeue` test is
+`ASSERT_TRUE(n != NULL)`, as we need to dereference the pointer `n` later,
+which would lead to a segfault when `n` is `NULL`.
+
+When these tests run, the following happens:
+  1. Google Test constructs a `QueueTest` object (let's call it `t1` ).
+  1. `t1.SetUp()` initializes `t1` .
+  1. The first test ( `IsEmptyInitially` ) runs on `t1` .
+  1. `t1.TearDown()` cleans up after the test finishes.
+  1. `t1` is destructed.
+  1. The above steps are repeated on another `QueueTest` object, this time running the `DequeueWorks` test.
+
+_Availability_: Linux, Windows, Mac.
+
+_Note_: Google Test automatically saves all _Google Test_ flags when a test
+object is constructed, and restores them when it is destructed.
+
+# Invoking the Tests #
+
+`TEST()` and `TEST_F()` implicitly register their tests with Google Test. So, unlike with many other C++ testing frameworks, you don't have to re-list all your defined tests in order to run them.
+
+After defining your tests, you can run them with `RUN_ALL_TESTS()` , which returns `0` if all the tests are successful, or `1` otherwise. Note that `RUN_ALL_TESTS()` runs _all tests_ in your link unit -- they can be from different test cases, or even different source files.
+
+When invoked, the `RUN_ALL_TESTS()` macro:
+  1. Saves the state of all  Google Test flags.
+  1. Creates a test fixture object for the first test.
+  1. Initializes it via `SetUp()`.
+  1. Runs the test on the fixture object.
+  1. Cleans up the fixture via `TearDown()`.
+  1. Deletes the fixture.
+  1. Restores the state of all Google Test flags.
+  1. Repeats the above steps for the next test, until all tests have run.
+
+In addition, if the text fixture's constructor generates a fatal failure in
+step 2, there is no point for step 3 - 5 and they are thus skipped. Similarly,
+if step 3 generates a fatal failure, step 4 will be skipped.
+
+_Important_: You must not ignore the return value of `RUN_ALL_TESTS()`, or `gcc`
+will give you a compiler error. The rationale for this design is that the
+automated testing service determines whether a test has passed based on its
+exit code, not on its stdout/stderr output; thus your `main()` function must
+return the value of `RUN_ALL_TESTS()`.
+
+Also, you should call `RUN_ALL_TESTS()` only **once**. Calling it more than once
+conflicts with some advanced Google Test features (e.g. thread-safe death
+tests) and thus is not supported.
+
+_Availability_: Linux, Windows, Mac.
+
+# Writing the main() Function #
+
+You can start from this boilerplate:
+```
+#include "this/package/foo.h"
+#include "gtest/gtest.h"
+
+namespace {
+
+// The fixture for testing class Foo.
+class FooTest : public ::testing::Test {
+ protected:
+  // You can remove any or all of the following functions if its body
+  // is empty.
+
+  FooTest() {
+    // You can do set-up work for each test here.
+  }
+
+  virtual ~FooTest() {
+    // You can do clean-up work that doesn't throw exceptions here.
+  }
+
+  // If the constructor and destructor are not enough for setting up
+  // and cleaning up each test, you can define the following methods:
+
+  virtual void SetUp() {
+    // Code here will be called immediately after the constructor (right
+    // before each test).
+  }
+
+  virtual void TearDown() {
+    // Code here will be called immediately after each test (right
+    // before the destructor).
+  }
+
+  // Objects declared here can be used by all tests in the test case for Foo.
+};
+
+// Tests that the Foo::Bar() method does Abc.
+TEST_F(FooTest, MethodBarDoesAbc) {
+  const string input_filepath = "this/package/testdata/myinputfile.dat";
+  const string output_filepath = "this/package/testdata/myoutputfile.dat";
+  Foo f;
+  EXPECT_EQ(0, f.Bar(input_filepath, output_filepath));
+}
+
+// Tests that Foo does Xyz.
+TEST_F(FooTest, DoesXyz) {
+  // Exercises the Xyz feature of Foo.
+}
+
+}  // namespace
+
+int main(int argc, char **argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
+```
+
+The `::testing::InitGoogleTest()` function parses the command line for Google
+Test flags, and removes all recognized flags. This allows the user to control a
+test program's behavior via various flags, which we'll cover in [AdvancedGuide](AdvancedGuide.md).
+You must call this function before calling `RUN_ALL_TESTS()`, or the flags
+won't be properly initialized.
+
+On Windows, `InitGoogleTest()` also works with wide strings, so it can be used
+in programs compiled in `UNICODE` mode as well.
+
+But maybe you think that writing all those main() functions is too much work? We agree with you completely and that's why Google Test provides a basic implementation of main(). If it fits your needs, then just link your test with gtest\_main library and you are good to go.
+
+## Important note for Visual C++ users ##
+If you put your tests into a library and your `main()` function is in a different library or in your .exe file, those tests will not run. The reason is a [bug](https://connect.microsoft.com/feedback/viewfeedback.aspx?FeedbackID=244410&siteid=210) in Visual C++. When you define your tests, Google Test creates certain static objects to register them. These objects are not referenced from elsewhere but their constructors are still supposed to run. When Visual C++ linker sees that nothing in the library is referenced from other places it throws the library out. You have to reference your library with tests from your main program to keep the linker from discarding it. Here is how to do it. Somewhere in your library code declare a function:
+```
+__declspec(dllexport) int PullInMyLibrary() { return 0; }
+```
+If you put your tests in a static library (not DLL) then `__declspec(dllexport)` is not required. Now, in your main program, write a code that invokes that function:
+```
+int PullInMyLibrary();
+static int dummy = PullInMyLibrary();
+```
+This will keep your tests referenced and will make them register themselves at startup.
+
+In addition, if you define your tests in a static library, add `/OPT:NOREF` to your main program linker options. If you use MSVC++ IDE, go to your .exe project properties/Configuration Properties/Linker/Optimization and set References setting to `Keep Unreferenced Data (/OPT:NOREF)`. This will keep Visual C++ linker from discarding individual symbols generated by your tests from the final executable.
+
+There is one more pitfall, though. If you use Google Test as a static library (that's how it is defined in gtest.vcproj) your tests must also reside in a static library. If you have to have them in a DLL, you _must_ change Google Test to build into a DLL as well. Otherwise your tests will not run correctly or will not run at all. The general conclusion here is: make your life easier - do not write your tests in libraries!
+
+# Where to Go from Here #
+
+Congratulations! You've learned the Google Test basics. You can start writing
+and running Google Test tests, read some [samples](Samples.md), or continue with
+[AdvancedGuide](AdvancedGuide.md), which describes many more useful Google Test features.
+
+# Known Limitations #
+
+Google Test is designed to be thread-safe.  The implementation is
+thread-safe on systems where the `pthreads` library is available.  It
+is currently _unsafe_ to use Google Test assertions from two threads
+concurrently on other systems (e.g. Windows).  In most tests this is
+not an issue as usually the assertions are done in the main thread. If
+you want to help, you can volunteer to implement the necessary
+synchronization primitives in `gtest-port.h` for your platform.
\ No newline at end of file
diff --git a/third_party/googletest/googletest/docs/PumpManual.md b/third_party/googletest/googletest/docs/PumpManual.md
new file mode 100644
index 0000000..8184f15
--- /dev/null
+++ b/third_party/googletest/googletest/docs/PumpManual.md
@@ -0,0 +1,177 @@
+
+
+<b>P</b>ump is <b>U</b>seful for <b>M</b>eta <b>P</b>rogramming.
+
+# The Problem #
+
+Template and macro libraries often need to define many classes,
+functions, or macros that vary only (or almost only) in the number of
+arguments they take. It's a lot of repetitive, mechanical, and
+error-prone work.
+
+Variadic templates and variadic macros can alleviate the problem.
+However, while both are being considered by the C++ committee, neither
+is in the standard yet or widely supported by compilers.  Thus they
+are often not a good choice, especially when your code needs to be
+portable. And their capabilities are still limited.
+
+As a result, authors of such libraries often have to write scripts to
+generate their implementation. However, our experience is that it's
+tedious to write such scripts, which tend to reflect the structure of
+the generated code poorly and are often hard to read and edit. For
+example, a small change needed in the generated code may require some
+non-intuitive, non-trivial changes in the script. This is especially
+painful when experimenting with the code.
+
+# Our Solution #
+
+Pump (for Pump is Useful for Meta Programming, Pretty Useful for Meta
+Programming, or Practical Utility for Meta Programming, whichever you
+prefer) is a simple meta-programming tool for C++. The idea is that a
+programmer writes a `foo.pump` file which contains C++ code plus meta
+code that manipulates the C++ code. The meta code can handle
+iterations over a range, nested iterations, local meta variable
+definitions, simple arithmetic, and conditional expressions. You can
+view it as a small Domain-Specific Language. The meta language is
+designed to be non-intrusive (s.t. it won't confuse Emacs' C++ mode,
+for example) and concise, making Pump code intuitive and easy to
+maintain.
+
+## Highlights ##
+
+  * The implementation is in a single Python script and thus ultra portable: no build or installation is needed and it works cross platforms.
+  * Pump tries to be smart with respect to [Google's style guide](http://code.google.com/p/google-styleguide/): it breaks long lines (easy to have when they are generated) at acceptable places to fit within 80 columns and indent the continuation lines correctly.
+  * The format is human-readable and more concise than XML.
+  * The format works relatively well with Emacs' C++ mode.
+
+## Examples ##
+
+The following Pump code (where meta keywords start with `$`, `[[` and `]]` are meta brackets, and `$$` starts a meta comment that ends with the line):
+
+```
+$var n = 3     $$ Defines a meta variable n.
+$range i 0..n  $$ Declares the range of meta iterator i (inclusive).
+$for i [[
+               $$ Meta loop.
+// Foo$i does blah for $i-ary predicates.
+$range j 1..i
+template <size_t N $for j [[, typename A$j]]>
+class Foo$i {
+$if i == 0 [[
+  blah a;
+]] $elif i <= 2 [[
+  blah b;
+]] $else [[
+  blah c;
+]]
+};
+
+]]
+```
+
+will be translated by the Pump compiler to:
+
+```
+// Foo0 does blah for 0-ary predicates.
+template <size_t N>
+class Foo0 {
+  blah a;
+};
+
+// Foo1 does blah for 1-ary predicates.
+template <size_t N, typename A1>
+class Foo1 {
+  blah b;
+};
+
+// Foo2 does blah for 2-ary predicates.
+template <size_t N, typename A1, typename A2>
+class Foo2 {
+  blah b;
+};
+
+// Foo3 does blah for 3-ary predicates.
+template <size_t N, typename A1, typename A2, typename A3>
+class Foo3 {
+  blah c;
+};
+```
+
+In another example,
+
+```
+$range i 1..n
+Func($for i + [[a$i]]);
+$$ The text between i and [[ is the separator between iterations.
+```
+
+will generate one of the following lines (without the comments), depending on the value of `n`:
+
+```
+Func();              // If n is 0.
+Func(a1);            // If n is 1.
+Func(a1 + a2);       // If n is 2.
+Func(a1 + a2 + a3);  // If n is 3.
+// And so on...
+```
+
+## Constructs ##
+
+We support the following meta programming constructs:
+
+| `$var id = exp` | Defines a named constant value. `$id` is valid util the end of the current meta lexical block. |
+|:----------------|:-----------------------------------------------------------------------------------------------|
+| `$range id exp..exp` | Sets the range of an iteration variable, which can be reused in multiple loops later.          |
+| `$for id sep [[ code ]]` | Iteration. The range of `id` must have been defined earlier. `$id` is valid in `code`.         |
+| `$($)`          | Generates a single `$` character.                                                              |
+| `$id`           | Value of the named constant or iteration variable.                                             |
+| `$(exp)`        | Value of the expression.                                                                       |
+| `$if exp [[ code ]] else_branch` | Conditional.                                                                                   |
+| `[[ code ]]`    | Meta lexical block.                                                                            |
+| `cpp_code`      | Raw C++ code.                                                                                  |
+| `$$ comment`    | Meta comment.                                                                                  |
+
+**Note:** To give the user some freedom in formatting the Pump source
+code, Pump ignores a new-line character if it's right after `$for foo`
+or next to `[[` or `]]`. Without this rule you'll often be forced to write
+very long lines to get the desired output. Therefore sometimes you may
+need to insert an extra new-line in such places for a new-line to show
+up in your output.
+
+## Grammar ##
+
+```
+code ::= atomic_code*
+atomic_code ::= $var id = exp
+    | $var id = [[ code ]]
+    | $range id exp..exp
+    | $for id sep [[ code ]]
+    | $($)
+    | $id
+    | $(exp)
+    | $if exp [[ code ]] else_branch
+    | [[ code ]]
+    | cpp_code
+sep ::= cpp_code | empty_string
+else_branch ::= $else [[ code ]]
+    | $elif exp [[ code ]] else_branch
+    | empty_string
+exp ::= simple_expression_in_Python_syntax
+```
+
+## Code ##
+
+You can find the source code of Pump in [scripts/pump.py](../scripts/pump.py). It is still
+very unpolished and lacks automated tests, although it has been
+successfully used many times. If you find a chance to use it in your
+project, please let us know what you think!  We also welcome help on
+improving Pump.
+
+## Real Examples ##
+
+You can find real-world applications of Pump in [Google Test](http://www.google.com/codesearch?q=file%3A\.pump%24+package%3Ahttp%3A%2F%2Fgoogletest\.googlecode\.com) and [Google Mock](http://www.google.com/codesearch?q=file%3A\.pump%24+package%3Ahttp%3A%2F%2Fgooglemock\.googlecode\.com).  The source file `foo.h.pump` generates `foo.h`.
+
+## Tips ##
+
+  * If a meta variable is followed by a letter or digit, you can separate them using `[[]]`, which inserts an empty string. For example `Foo$j[[]]Helper` generate `Foo1Helper` when `j` is 1.
+  * To avoid extra-long Pump source lines, you can break a line anywhere you want by inserting `[[]]` followed by a new line. Since any new-line character next to `[[` or `]]` is ignored, the generated code won't contain this new line.
diff --git a/third_party/googletest/googletest/docs/Samples.md b/third_party/googletest/googletest/docs/Samples.md
new file mode 100644
index 0000000..f21d200
--- /dev/null
+++ b/third_party/googletest/googletest/docs/Samples.md
@@ -0,0 +1,14 @@
+If you're like us, you'd like to look at some Google Test sample code.  The
+[samples folder](../samples) has a number of well-commented samples showing how to use a
+variety of Google Test features.
+
+  * [Sample #1](../samples/sample1_unittest.cc) shows the basic steps of using Google Test to test C++ functions.
+  * [Sample #2](../samples/sample2_unittest.cc) shows a more complex unit test for a class with multiple member functions.
+  * [Sample #3](../samples/sample3_unittest.cc) uses a test fixture.
+  * [Sample #4](../samples/sample4_unittest.cc) is another basic example of using Google Test.
+  * [Sample #5](../samples/sample5_unittest.cc) teaches how to reuse a test fixture in multiple test cases by deriving sub-fixtures from it.
+  * [Sample #6](../samples/sample6_unittest.cc) demonstrates type-parameterized tests.
+  * [Sample #7](../samples/sample7_unittest.cc) teaches the basics of value-parameterized tests.
+  * [Sample #8](../samples/sample8_unittest.cc) shows using `Combine()` in value-parameterized tests.
+  * [Sample #9](../samples/sample9_unittest.cc) shows use of the listener API to modify Google Test's console output and the use of its reflection API to inspect test results.
+  * [Sample #10](../samples/sample10_unittest.cc) shows use of the listener API to implement a primitive memory leak checker.
diff --git a/third_party/googletest/googletest/docs/V1_5_AdvancedGuide.md b/third_party/googletest/googletest/docs/V1_5_AdvancedGuide.md
new file mode 100644
index 0000000..2c3fc1a
--- /dev/null
+++ b/third_party/googletest/googletest/docs/V1_5_AdvancedGuide.md
@@ -0,0 +1,2096 @@
+
+
+Now that you have read [Primer](V1_5_Primer.md) and learned how to write tests
+using Google Test, it's time to learn some new tricks. This document
+will show you more assertions as well as how to construct complex
+failure messages, propagate fatal failures, reuse and speed up your
+test fixtures, and use various flags with your tests.
+
+# More Assertions #
+
+This section covers some less frequently used, but still significant,
+assertions.
+
+## Explicit Success and Failure ##
+
+These three assertions do not actually test a value or expression. Instead,
+they generate a success or failure directly. Like the macros that actually
+perform a test, you may stream a custom failure message into the them.
+
+| `SUCCEED();` |
+|:-------------|
+
+Generates a success. This does NOT make the overall test succeed. A test is
+considered successful only if none of its assertions fail during its execution.
+
+Note: `SUCCEED()` is purely documentary and currently doesn't generate any
+user-visible output. However, we may add `SUCCEED()` messages to Google Test's
+output in the future.
+
+| `FAIL();`  | `ADD_FAILURE();` |
+|:-----------|:-----------------|
+
+`FAIL*` generates a fatal failure while `ADD_FAILURE*` generates a nonfatal
+failure. These are useful when control flow, rather than a Boolean expression,
+deteremines the test's success or failure. For example, you might want to write
+something like:
+
+```
+switch(expression) {
+  case 1: ... some checks ...
+  case 2: ... some other checks
+  ...
+  default: FAIL() << "We shouldn't get here.";
+}
+```
+
+_Availability_: Linux, Windows, Mac.
+
+## Exception Assertions ##
+
+These are for verifying that a piece of code throws (or does not
+throw) an exception of the given type:
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_THROW(`_statement_, _exception\_type_`);`  | `EXPECT_THROW(`_statement_, _exception\_type_`);`  | _statement_ throws an exception of the given type  |
+| `ASSERT_ANY_THROW(`_statement_`);`                | `EXPECT_ANY_THROW(`_statement_`);`                | _statement_ throws an exception of any type        |
+| `ASSERT_NO_THROW(`_statement_`);`                 | `EXPECT_NO_THROW(`_statement_`);`                 | _statement_ doesn't throw any exception            |
+
+Examples:
+
+```
+ASSERT_THROW(Foo(5), bar_exception);
+
+EXPECT_NO_THROW({
+  int n = 5;
+  Bar(&n);
+});
+```
+
+_Availability_: Linux, Windows, Mac; since version 1.1.0.
+
+## Predicate Assertions for Better Error Messages ##
+
+Even though Google Test has a rich set of assertions, they can never be
+complete, as it's impossible (nor a good idea) to anticipate all the scenarios
+a user might run into. Therefore, sometimes a user has to use `EXPECT_TRUE()`
+to check a complex expression, for lack of a better macro. This has the problem
+of not showing you the values of the parts of the expression, making it hard to
+understand what went wrong. As a workaround, some users choose to construct the
+failure message by themselves, streaming it into `EXPECT_TRUE()`. However, this
+is awkward especially when the expression has side-effects or is expensive to
+evaluate.
+
+Google Test gives you three different options to solve this problem:
+
+### Using an Existing Boolean Function ###
+
+If you already have a function or a functor that returns `bool` (or a type
+that can be implicitly converted to `bool`), you can use it in a _predicate
+assertion_ to get the function arguments printed for free:
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_PRED1(`_pred1, val1_`);`       | `EXPECT_PRED1(`_pred1, val1_`);` | _pred1(val1)_ returns true |
+| `ASSERT_PRED2(`_pred2, val1, val2_`);` | `EXPECT_PRED2(`_pred2, val1, val2_`);` |  _pred2(val1, val2)_ returns true |
+|  ...                | ...                    | ...          |
+
+In the above, _predn_ is an _n_-ary predicate function or functor, where
+_val1_, _val2_, ..., and _valn_ are its arguments. The assertion succeeds
+if the predicate returns `true` when applied to the given arguments, and fails
+otherwise. When the assertion fails, it prints the value of each argument. In
+either case, the arguments are evaluated exactly once.
+
+Here's an example. Given
+
+```
+// Returns true iff m and n have no common divisors except 1.
+bool MutuallyPrime(int m, int n) { ... }
+const int a = 3;
+const int b = 4;
+const int c = 10;
+```
+
+the assertion `EXPECT_PRED2(MutuallyPrime, a, b);` will succeed, while the
+assertion `EXPECT_PRED2(MutuallyPrime, b, c);` will fail with the message
+
+<pre>
+!MutuallyPrime(b, c) is false, where<br>
+b is 4<br>
+c is 10<br>
+</pre>
+
+**Notes:**
+
+  1. If you see a compiler error "no matching function to call" when using `ASSERT_PRED*` or `EXPECT_PRED*`, please see [this](http://code.google.com/p/googletest/wiki/V1_5_FAQ#The_compiler_complains_%22no_matching_function_to_call%22) for how to resolve it.
+  1. Currently we only provide predicate assertions of arity <= 5. If you need a higher-arity assertion, let us know.
+
+_Availability_: Linux, Windows, Mac
+
+### Using a Function That Returns an AssertionResult ###
+
+While `EXPECT_PRED*()` and friends are handy for a quick job, the
+syntax is not satisfactory: you have to use different macros for
+different arities, and it feels more like Lisp than C++.  The
+`::testing::AssertionResult` class solves this problem.
+
+An `AssertionResult` object represents the result of an assertion
+(whether it's a success or a failure, and an associated message).  You
+can create an `AssertionResult` using one of these factory
+functions:
+
+```
+namespace testing {
+
+// Returns an AssertionResult object to indicate that an assertion has
+// succeeded.
+AssertionResult AssertionSuccess();
+
+// Returns an AssertionResult object to indicate that an assertion has
+// failed.
+AssertionResult AssertionFailure();
+
+}
+```
+
+You can then use the `<<` operator to stream messages to the
+`AssertionResult` object.
+
+To provide more readable messages in Boolean assertions
+(e.g. `EXPECT_TRUE()`), write a predicate function that returns
+`AssertionResult` instead of `bool`. For example, if you define
+`IsEven()` as:
+
+```
+::testing::AssertionResult IsEven(int n) {
+  if ((n % 2) == 0)
+    return ::testing::AssertionSuccess();
+  else
+    return ::testing::AssertionFailure() << n << " is odd";
+}
+```
+
+instead of:
+
+```
+bool IsEven(int n) {
+  return (n % 2) == 0;
+}
+```
+
+the failed assertion `EXPECT_TRUE(IsEven(Fib(4)))` will print:
+
+<pre>
+Value of: !IsEven(Fib(4))<br>
+Actual: false (*3 is odd*)<br>
+Expected: true<br>
+</pre>
+
+instead of a more opaque
+
+<pre>
+Value of: !IsEven(Fib(4))<br>
+Actual: false<br>
+Expected: true<br>
+</pre>
+
+If you want informative messages in `EXPECT_FALSE` and `ASSERT_FALSE`
+as well, and are fine with making the predicate slower in the success
+case, you can supply a success message:
+
+```
+::testing::AssertionResult IsEven(int n) {
+  if ((n % 2) == 0)
+    return ::testing::AssertionSuccess() << n << " is even";
+  else
+    return ::testing::AssertionFailure() << n << " is odd";
+}
+```
+
+Then the statement `EXPECT_FALSE(IsEven(Fib(6)))` will print
+
+<pre>
+Value of: !IsEven(Fib(6))<br>
+Actual: true (8 is even)<br>
+Expected: false<br>
+</pre>
+
+_Availability_: Linux, Windows, Mac; since version 1.4.1.
+
+### Using a Predicate-Formatter ###
+
+If you find the default message generated by `(ASSERT|EXPECT)_PRED*` and
+`(ASSERT|EXPECT)_(TRUE|FALSE)` unsatisfactory, or some arguments to your
+predicate do not support streaming to `ostream`, you can instead use the
+following _predicate-formatter assertions_ to _fully_ customize how the
+message is formatted:
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_PRED_FORMAT1(`_pred\_format1, val1_`);`        | `EXPECT_PRED_FORMAT1(`_pred\_format1, val1_`); | _pred\_format1(val1)_ is successful |
+| `ASSERT_PRED_FORMAT2(`_pred\_format2, val1, val2_`);` | `EXPECT_PRED_FORMAT2(`_pred\_format2, val1, val2_`);` | _pred\_format2(val1, val2)_ is successful |
+| `...`               | `...`                  | `...`        |
+
+The difference between this and the previous two groups of macros is that instead of
+a predicate, `(ASSERT|EXPECT)_PRED_FORMAT*` take a _predicate-formatter_
+(_pred\_formatn_), which is a function or functor with the signature:
+
+`::testing::AssertionResult PredicateFormattern(const char* `_expr1_`, const char* `_expr2_`, ... const char* `_exprn_`, T1 `_val1_`, T2 `_val2_`, ... Tn `_valn_`);`
+
+where _val1_, _val2_, ..., and _valn_ are the values of the predicate
+arguments, and _expr1_, _expr2_, ..., and _exprn_ are the corresponding
+expressions as they appear in the source code. The types `T1`, `T2`, ..., and
+`Tn` can be either value types or reference types. For example, if an
+argument has type `Foo`, you can declare it as either `Foo` or `const Foo&`,
+whichever is appropriate.
+
+A predicate-formatter returns a `::testing::AssertionResult` object to indicate
+whether the assertion has succeeded or not. The only way to create such an
+object is to call one of these factory functions:
+
+As an example, let's improve the failure message in the previous example, which uses `EXPECT_PRED2()`:
+
+```
+// Returns the smallest prime common divisor of m and n,
+// or 1 when m and n are mutually prime.
+int SmallestPrimeCommonDivisor(int m, int n) { ... }
+
+// A predicate-formatter for asserting that two integers are mutually prime.
+::testing::AssertionResult AssertMutuallyPrime(const char* m_expr,
+                                               const char* n_expr,
+                                               int m,
+                                               int n) {
+  if (MutuallyPrime(m, n))
+    return ::testing::AssertionSuccess();
+ 
+  return ::testing::AssertionFailure()
+      << m_expr << " and " << n_expr << " (" << m << " and " << n
+      << ") are not mutually prime, " << "as they have a common divisor "
+      << SmallestPrimeCommonDivisor(m, n);
+}
+```
+
+With this predicate-formatter, we can use
+
+```
+EXPECT_PRED_FORMAT2(AssertMutuallyPrime, b, c);
+```
+
+to generate the message
+
+<pre>
+b and c (4 and 10) are not mutually prime, as they have a common divisor 2.<br>
+</pre>
+
+As you may have realized, many of the assertions we introduced earlier are
+special cases of `(EXPECT|ASSERT)_PRED_FORMAT*`. In fact, most of them are
+indeed defined using `(EXPECT|ASSERT)_PRED_FORMAT*`.
+
+_Availability_: Linux, Windows, Mac.
+
+
+## Floating-Point Comparison ##
+
+Comparing floating-point numbers is tricky. Due to round-off errors, it is
+very unlikely that two floating-points will match exactly. Therefore,
+`ASSERT_EQ` 's naive comparison usually doesn't work. And since floating-points
+can have a wide value range, no single fixed error bound works. It's better to
+compare by a fixed relative error bound, except for values close to 0 due to
+the loss of precision there.
+
+In general, for floating-point comparison to make sense, the user needs to
+carefully choose the error bound. If they don't want or care to, comparing in
+terms of Units in the Last Place (ULPs) is a good default, and Google Test
+provides assertions to do this. Full details about ULPs are quite long; if you
+want to learn more, see
+[this article on float comparison](http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm).
+
+### Floating-Point Macros ###
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_FLOAT_EQ(`_expected, actual_`);`  | `EXPECT_FLOAT_EQ(`_expected, actual_`);` | the two `float` values are almost equal |
+| `ASSERT_DOUBLE_EQ(`_expected, actual_`);` | `EXPECT_DOUBLE_EQ(`_expected, actual_`);` | the two `double` values are almost equal |
+
+By "almost equal", we mean the two values are within 4 ULP's from each
+other.
+
+The following assertions allow you to choose the acceptable error bound:
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_NEAR(`_val1, val2, abs\_error_`);` | `EXPECT_NEAR`_(val1, val2, abs\_error_`);` | the difference between _val1_ and _val2_ doesn't exceed the given absolute error |
+
+_Availability_: Linux, Windows, Mac.
+
+### Floating-Point Predicate-Format Functions ###
+
+Some floating-point operations are useful, but not that often used. In order
+to avoid an explosion of new macros, we provide them as predicate-format
+functions that can be used in predicate assertion macros (e.g.
+`EXPECT_PRED_FORMAT2`, etc).
+
+```
+EXPECT_PRED_FORMAT2(::testing::FloatLE, val1, val2);
+EXPECT_PRED_FORMAT2(::testing::DoubleLE, val1, val2);
+```
+
+Verifies that _val1_ is less than, or almost equal to, _val2_. You can
+replace `EXPECT_PRED_FORMAT2` in the above table with `ASSERT_PRED_FORMAT2`.
+
+_Availability_: Linux, Windows, Mac.
+
+## Windows HRESULT assertions ##
+
+These assertions test for `HRESULT` success or failure.
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_HRESULT_SUCCEEDED(`_expression_`);` | `EXPECT_HRESULT_SUCCEEDED(`_expression_`);` | _expression_ is a success `HRESULT` |
+| `ASSERT_HRESULT_FAILED(`_expression_`);`    | `EXPECT_HRESULT_FAILED(`_expression_`);`    | _expression_ is a failure `HRESULT` |
+
+The generated output contains the human-readable error message
+associated with the `HRESULT` code returned by _expression_.
+
+You might use them like this:
+
+```
+CComPtr shell;
+ASSERT_HRESULT_SUCCEEDED(shell.CoCreateInstance(L"Shell.Application"));
+CComVariant empty;
+ASSERT_HRESULT_SUCCEEDED(shell->ShellExecute(CComBSTR(url), empty, empty, empty, empty));
+```
+
+_Availability_: Windows.
+
+## Type Assertions ##
+
+You can call the function
+```
+::testing::StaticAssertTypeEq<T1, T2>();
+```
+to assert that types `T1` and `T2` are the same.  The function does
+nothing if the assertion is satisfied.  If the types are different,
+the function call will fail to compile, and the compiler error message
+will likely (depending on the compiler) show you the actual values of
+`T1` and `T2`.  This is mainly useful inside template code.
+
+_Caveat:_ When used inside a member function of a class template or a
+function template, `StaticAssertTypeEq<T1, T2>()` is effective _only if_
+the function is instantiated.  For example, given:
+```
+template <typename T> class Foo {
+ public:
+  void Bar() { ::testing::StaticAssertTypeEq<int, T>(); }
+};
+```
+the code:
+```
+void Test1() { Foo<bool> foo; }
+```
+will _not_ generate a compiler error, as `Foo<bool>::Bar()` is never
+actually instantiated.  Instead, you need:
+```
+void Test2() { Foo<bool> foo; foo.Bar(); }
+```
+to cause a compiler error.
+
+_Availability:_ Linux, Windows, Mac; since version 1.3.0.
+
+## Assertion Placement ##
+
+You can use assertions in any C++ function. In particular, it doesn't
+have to be a method of the test fixture class. The one constraint is
+that assertions that generate a fatal failure (`FAIL*` and `ASSERT_*`)
+can only be used in void-returning functions. This is a consequence of
+Google Test not using exceptions. By placing it in a non-void function
+you'll get a confusing compile error like
+`"error: void value not ignored as it ought to be"`.
+
+If you need to use assertions in a function that returns non-void, one option
+is to make the function return the value in an out parameter instead. For
+example, you can rewrite `T2 Foo(T1 x)` to `void Foo(T1 x, T2* result)`. You
+need to make sure that `*result` contains some sensible value even when the
+function returns prematurely. As the function now returns `void`, you can use
+any assertion inside of it.
+
+If changing the function's type is not an option, you should just use
+assertions that generate non-fatal failures, such as `ADD_FAILURE*` and
+`EXPECT_*`.
+
+_Note_: Constructors and destructors are not considered void-returning
+functions, according to the C++ language specification, and so you may not use
+fatal assertions in them. You'll get a compilation error if you try. A simple
+workaround is to transfer the entire body of the constructor or destructor to a
+private void-returning method. However, you should be aware that a fatal
+assertion failure in a constructor does not terminate the current test, as your
+intuition might suggest; it merely returns from the constructor early, possibly
+leaving your object in a partially-constructed state. Likewise, a fatal
+assertion failure in a destructor may leave your object in a
+partially-destructed state. Use assertions carefully in these situations!
+
+# Death Tests #
+
+In many applications, there are assertions that can cause application failure
+if a condition is not met. These sanity checks, which ensure that the program
+is in a known good state, are there to fail at the earliest possible time after
+some program state is corrupted. If the assertion checks the wrong condition,
+then the program may proceed in an erroneous state, which could lead to memory
+corruption, security holes, or worse. Hence it is vitally important to test
+that such assertion statements work as expected.
+
+Since these precondition checks cause the processes to die, we call such tests
+_death tests_. More generally, any test that checks that a program terminates
+in an expected fashion is also a death test.
+
+If you want to test `EXPECT_*()/ASSERT_*()` failures in your test code, see [Catching Failures](#Catching_Failures.md).
+
+## How to Write a Death Test ##
+
+Google Test has the following macros to support death tests:
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_DEATH(`_statement, regex_`); | `EXPECT_DEATH(`_statement, regex_`); | _statement_ crashes with the given error |
+| `ASSERT_DEATH_IF_SUPPORTED(`_statement, regex_`); | `EXPECT_DEATH_IF_SUPPORTED(`_statement, regex_`); | if death tests are supported, verifies that _statement_ crashes with the given error; otherwise verifies nothing |
+| `ASSERT_EXIT(`_statement, predicate, regex_`); | `EXPECT_EXIT(`_statement, predicate, regex_`); |_statement_ exits with the given error and its exit code matches _predicate_ |
+
+where _statement_ is a statement that is expected to cause the process to
+die, _predicate_ is a function or function object that evaluates an integer
+exit status, and _regex_ is a regular expression that the stderr output of
+_statement_ is expected to match. Note that _statement_ can be _any valid
+statement_ (including _compound statement_) and doesn't have to be an
+expression.
+
+As usual, the `ASSERT` variants abort the current test function, while the
+`EXPECT` variants do not.
+
+**Note:** We use the word "crash" here to mean that the process
+terminates with a _non-zero_ exit status code.  There are two
+possibilities: either the process has called `exit()` or `_exit()`
+with a non-zero value, or it may be killed by a signal.
+
+This means that if _statement_ terminates the process with a 0 exit
+code, it is _not_ considered a crash by `EXPECT_DEATH`.  Use
+`EXPECT_EXIT` instead if this is the case, or if you want to restrict
+the exit code more precisely.
+
+A predicate here must accept an `int` and return a `bool`. The death test
+succeeds only if the predicate returns `true`. Google Test defines a few
+predicates that handle the most common cases:
+
+```
+::testing::ExitedWithCode(exit_code)
+```
+
+This expression is `true` if the program exited normally with the given exit
+code.
+
+```
+::testing::KilledBySignal(signal_number)  // Not available on Windows.
+```
+
+This expression is `true` if the program was killed by the given signal.
+
+The `*_DEATH` macros are convenient wrappers for `*_EXIT` that use a predicate
+that verifies the process' exit code is non-zero.
+
+Note that a death test only cares about three things:
+
+  1. does _statement_ abort or exit the process?
+  1. (in the case of `ASSERT_EXIT` and `EXPECT_EXIT`) does the exit status satisfy _predicate_?  Or (in the case of `ASSERT_DEATH` and `EXPECT_DEATH`) is the exit status non-zero?  And
+  1. does the stderr output match _regex_?
+
+In particular, if _statement_ generates an `ASSERT_*` or `EXPECT_*` failure, it will **not** cause the death test to fail, as Google Test assertions don't abort the process.
+
+To write a death test, simply use one of the above macros inside your test
+function. For example,
+
+```
+TEST(My*DeathTest*, Foo) {
+  // This death test uses a compound statement.
+  ASSERT_DEATH({ int n = 5; Foo(&n); }, "Error on line .* of Foo()");
+}
+TEST(MyDeathTest, NormalExit) {
+  EXPECT_EXIT(NormalExit(), ::testing::ExitedWithCode(0), "Success");
+}
+TEST(MyDeathTest, KillMyself) {
+  EXPECT_EXIT(KillMyself(), ::testing::KilledBySignal(SIGKILL), "Sending myself unblockable signal");
+}
+```
+
+verifies that:
+
+  * calling `Foo(5)` causes the process to die with the given error message,
+  * calling `NormalExit()` causes the process to print `"Success"` to stderr and exit with exit code 0, and
+  * calling `KillMyself()` kills the process with signal `SIGKILL`.
+
+The test function body may contain other assertions and statements as well, if
+necessary.
+
+_Important:_ We strongly recommend you to follow the convention of naming your
+test case (not test) `*DeathTest` when it contains a death test, as
+demonstrated in the above example. The `Death Tests And Threads` section below
+explains why.
+
+If a test fixture class is shared by normal tests and death tests, you
+can use typedef to introduce an alias for the fixture class and avoid
+duplicating its code:
+```
+class FooTest : public ::testing::Test { ... };
+
+typedef FooTest FooDeathTest;
+
+TEST_F(FooTest, DoesThis) {
+  // normal test
+}
+
+TEST_F(FooDeathTest, DoesThat) {
+  // death test
+}
+```
+
+_Availability:_ Linux, Windows (requires MSVC 8.0 or above), Cygwin, and Mac (the latter three are supported since v1.3.0).  `(ASSERT|EXPECT)_DEATH_IF_SUPPORTED` are new in v1.4.0.
+
+## Regular Expression Syntax ##
+
+On POSIX systems (e.g. Linux, Cygwin, and Mac), Google Test uses the
+[POSIX extended regular expression](http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap09.html#tag_09_04)
+syntax in death tests. To learn about this syntax, you may want to read this [Wikipedia entry](http://en.wikipedia.org/wiki/Regular_expression#POSIX_Extended_Regular_Expressions).
+
+On Windows, Google Test uses its own simple regular expression
+implementation. It lacks many features you can find in POSIX extended
+regular expressions.  For example, we don't support union (`"x|y"`),
+grouping (`"(xy)"`), brackets (`"[xy]"`), and repetition count
+(`"x{5,7}"`), among others. Below is what we do support (`A` denotes a
+literal character, period (`.`), or a single `\\` escape sequence; `x`
+and `y` denote regular expressions.):
+
+| `c` | matches any literal character `c` |
+|:----|:----------------------------------|
+| `\\d` | matches any decimal digit         |
+| `\\D` | matches any character that's not a decimal digit |
+| `\\f` | matches `\f`                      |
+| `\\n` | matches `\n`                      |
+| `\\r` | matches `\r`                      |
+| `\\s` | matches any ASCII whitespace, including `\n` |
+| `\\S` | matches any character that's not a whitespace |
+| `\\t` | matches `\t`                      |
+| `\\v` | matches `\v`                      |
+| `\\w` | matches any letter, `_`, or decimal digit |
+| `\\W` | matches any character that `\\w` doesn't match |
+| `\\c` | matches any literal character `c`, which must be a punctuation |
+| `.` | matches any single character except `\n` |
+| `A?` | matches 0 or 1 occurrences of `A` |
+| `A*` | matches 0 or many occurrences of `A` |
+| `A+` | matches 1 or many occurrences of `A` |
+| `^` | matches the beginning of a string (not that of each line) |
+| `$` | matches the end of a string (not that of each line) |
+| `xy` | matches `x` followed by `y`       |
+
+To help you determine which capability is available on your system,
+Google Test defines macro `GTEST_USES_POSIX_RE=1` when it uses POSIX
+extended regular expressions, or `GTEST_USES_SIMPLE_RE=1` when it uses
+the simple version.  If you want your death tests to work in both
+cases, you can either `#if` on these macros or use the more limited
+syntax only.
+
+## How It Works ##
+
+Under the hood, `ASSERT_EXIT()` spawns a new process and executes the
+death test statement in that process. The details of of how precisely
+that happens depend on the platform and the variable
+`::testing::GTEST_FLAG(death_test_style)` (which is initialized from the
+command-line flag `--gtest_death_test_style`).
+
+  * On POSIX systems, `fork()` (or `clone()` on Linux) is used to spawn the child, after which:
+    * If the variable's value is `"fast"`, the death test statement is immediately executed.
+    * If the variable's value is `"threadsafe"`, the child process re-executes the unit test binary just as it was originally invoked, but with some extra flags to cause just the single death test under consideration to be run.
+  * On Windows, the child is spawned using the `CreateProcess()` API, and re-executes the binary to cause just the single death test under consideration to be run - much like the `threadsafe` mode on POSIX.
+
+Other values for the variable are illegal and will cause the death test to
+fail. Currently, the flag's default value is `"fast"`. However, we reserve the
+right to change it in the future. Therefore, your tests should not depend on
+this.
+
+In either case, the parent process waits for the child process to complete, and checks that
+
+  1. the child's exit status satisfies the predicate, and
+  1. the child's stderr matches the regular expression.
+
+If the death test statement runs to completion without dying, the child
+process will nonetheless terminate, and the assertion fails.
+
+## Death Tests And Threads ##
+
+The reason for the two death test styles has to do with thread safety. Due to
+well-known problems with forking in the presence of threads, death tests should
+be run in a single-threaded context. Sometimes, however, it isn't feasible to
+arrange that kind of environment. For example, statically-initialized modules
+may start threads before main is ever reached. Once threads have been created,
+it may be difficult or impossible to clean them up.
+
+Google Test has three features intended to raise awareness of threading issues.
+
+  1. A warning is emitted if multiple threads are running when a death test is encountered.
+  1. Test cases with a name ending in "DeathTest" are run before all other tests.
+  1. It uses `clone()` instead of `fork()` to spawn the child process on Linux (`clone()` is not available on Cygwin and Mac), as `fork()` is more likely to cause the child to hang when the parent process has multiple threads.
+
+It's perfectly fine to create threads inside a death test statement; they are
+executed in a separate process and cannot affect the parent.
+
+## Death Test Styles ##
+
+The "threadsafe" death test style was introduced in order to help mitigate the
+risks of testing in a possibly multithreaded environment. It trades increased
+test execution time (potentially dramatically so) for improved thread safety.
+We suggest using the faster, default "fast" style unless your test has specific
+problems with it.
+
+You can choose a particular style of death tests by setting the flag
+programmatically:
+
+```
+::testing::FLAGS_gtest_death_test_style = "threadsafe";
+```
+
+You can do this in `main()` to set the style for all death tests in the
+binary, or in individual tests. Recall that flags are saved before running each
+test and restored afterwards, so you need not do that yourself. For example:
+
+```
+TEST(MyDeathTest, TestOne) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  // This test is run in the "threadsafe" style:
+  ASSERT_DEATH(ThisShouldDie(), "");
+}
+
+TEST(MyDeathTest, TestTwo) {
+  // This test is run in the "fast" style:
+  ASSERT_DEATH(ThisShouldDie(), "");
+}
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  ::testing::FLAGS_gtest_death_test_style = "fast";
+  return RUN_ALL_TESTS();
+}
+```
+
+## Caveats ##
+
+The _statement_ argument of `ASSERT_EXIT()` can be any valid C++ statement
+except that it can not return from the current function. This means
+_statement_ should not contain `return` or a macro that might return (e.g.
+`ASSERT_TRUE()` ). If _statement_ returns before it crashes, Google Test will
+print an error message, and the test will fail.
+
+Since _statement_ runs in the child process, any in-memory side effect (e.g.
+modifying a variable, releasing memory, etc) it causes will _not_ be observable
+in the parent process. In particular, if you release memory in a death test,
+your program will fail the heap check as the parent process will never see the
+memory reclaimed. To solve this problem, you can
+
+  1. try not to free memory in a death test;
+  1. free the memory again in the parent process; or
+  1. do not use the heap checker in your program.
+
+Due to an implementation detail, you cannot place multiple death test
+assertions on the same line; otherwise, compilation will fail with an unobvious
+error message.
+
+Despite the improved thread safety afforded by the "threadsafe" style of death
+test, thread problems such as deadlock are still possible in the presence of
+handlers registered with `pthread_atfork(3)`.
+
+# Using Assertions in Sub-routines #
+
+## Adding Traces to Assertions ##
+
+If a test sub-routine is called from several places, when an assertion
+inside it fails, it can be hard to tell which invocation of the
+sub-routine the failure is from.  You can alleviate this problem using
+extra logging or custom failure messages, but that usually clutters up
+your tests. A better solution is to use the `SCOPED_TRACE` macro:
+
+| `SCOPED_TRACE(`_message_`);` |
+|:-----------------------------|
+
+where _message_ can be anything streamable to `std::ostream`. This
+macro will cause the current file name, line number, and the given
+message to be added in every failure message. The effect will be
+undone when the control leaves the current lexical scope.
+
+For example,
+
+```
+10: void Sub1(int n) {
+11:   EXPECT_EQ(1, Bar(n));
+12:   EXPECT_EQ(2, Bar(n + 1));
+13: }
+14: 
+15: TEST(FooTest, Bar) {
+16:   {
+17:     SCOPED_TRACE("A");  // This trace point will be included in
+18:                         // every failure in this scope.
+19:     Sub1(1);
+20:   }
+21:   // Now it won't.
+22:   Sub1(9);
+23: }
+```
+
+could result in messages like these:
+
+```
+path/to/foo_test.cc:11: Failure
+Value of: Bar(n)
+Expected: 1
+  Actual: 2
+   Trace:
+path/to/foo_test.cc:17: A
+
+path/to/foo_test.cc:12: Failure
+Value of: Bar(n + 1)
+Expected: 2
+  Actual: 3
+```
+
+Without the trace, it would've been difficult to know which invocation
+of `Sub1()` the two failures come from respectively. (You could add an
+extra message to each assertion in `Sub1()` to indicate the value of
+`n`, but that's tedious.)
+
+Some tips on using `SCOPED_TRACE`:
+
+  1. With a suitable message, it's often enough to use `SCOPED_TRACE` at the beginning of a sub-routine, instead of at each call site.
+  1. When calling sub-routines inside a loop, make the loop iterator part of the message in `SCOPED_TRACE` such that you can know which iteration the failure is from.
+  1. Sometimes the line number of the trace point is enough for identifying the particular invocation of a sub-routine. In this case, you don't have to choose a unique message for `SCOPED_TRACE`. You can simply use `""`.
+  1. You can use `SCOPED_TRACE` in an inner scope when there is one in the outer scope. In this case, all active trace points will be included in the failure messages, in reverse order they are encountered.
+  1. The trace dump is clickable in Emacs' compilation buffer - hit return on a line number and you'll be taken to that line in the source file!
+
+_Availability:_ Linux, Windows, Mac.
+
+## Propagating Fatal Failures ##
+
+A common pitfall when using `ASSERT_*` and `FAIL*` is not understanding that
+when they fail they only abort the _current function_, not the entire test. For
+example, the following test will segfault:
+```
+void Subroutine() {
+  // Generates a fatal failure and aborts the current function.
+  ASSERT_EQ(1, 2);
+  // The following won't be executed.
+  ...
+}
+
+TEST(FooTest, Bar) {
+  Subroutine();
+  // The intended behavior is for the fatal failure
+  // in Subroutine() to abort the entire test.
+  // The actual behavior: the function goes on after Subroutine() returns.
+  int* p = NULL;
+  *p = 3; // Segfault!
+}
+```
+
+Since we don't use exceptions, it is technically impossible to
+implement the intended behavior here.  To alleviate this, Google Test
+provides two solutions.  You could use either the
+`(ASSERT|EXPECT)_NO_FATAL_FAILURE` assertions or the
+`HasFatalFailure()` function.  They are described in the following two
+subsections.
+
+
+
+### Asserting on Subroutines ###
+
+As shown above, if your test calls a subroutine that has an `ASSERT_*`
+failure in it, the test will continue after the subroutine
+returns. This may not be what you want.
+
+Often people want fatal failures to propagate like exceptions.  For
+that Google Test offers the following macros:
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_NO_FATAL_FAILURE(`_statement_`);` | `EXPECT_NO_FATAL_FAILURE(`_statement_`);` | _statement_ doesn't generate any new fatal failures in the current thread. |
+
+Only failures in the thread that executes the assertion are checked to
+determine the result of this type of assertions.  If _statement_
+creates new threads, failures in these threads are ignored.
+
+Examples:
+
+```
+ASSERT_NO_FATAL_FAILURE(Foo());
+
+int i;
+EXPECT_NO_FATAL_FAILURE({
+  i = Bar();
+});
+```
+
+_Availability:_ Linux, Windows, Mac. Assertions from multiple threads
+are currently not supported.
+
+### Checking for Failures in the Current Test ###
+
+`HasFatalFailure()` in the `::testing::Test` class returns `true` if an
+assertion in the current test has suffered a fatal failure. This
+allows functions to catch fatal failures in a sub-routine and return
+early.
+
+```
+class Test {
+ public:
+  ...
+  static bool HasFatalFailure();
+};
+```
+
+The typical usage, which basically simulates the behavior of a thrown
+exception, is:
+
+```
+TEST(FooTest, Bar) {
+  Subroutine();
+  // Aborts if Subroutine() had a fatal failure.
+  if (HasFatalFailure())
+    return;
+  // The following won't be executed.
+  ...
+}
+```
+
+If `HasFatalFailure()` is used outside of `TEST()` , `TEST_F()` , or a test
+fixture, you must add the `::testing::Test::` prefix, as in:
+
+```
+if (::testing::Test::HasFatalFailure())
+  return;
+```
+
+Similarly, `HasNonfatalFailure()` returns `true` if the current test
+has at least one non-fatal failure, and `HasFailure()` returns `true`
+if the current test has at least one failure of either kind.
+
+_Availability:_ Linux, Windows, Mac.  `HasNonfatalFailure()` and
+`HasFailure()` are available since version 1.4.0.
+
+# Logging Additional Information #
+
+In your test code, you can call `RecordProperty("key", value)` to log
+additional information, where `value` can be either a C string or a 32-bit
+integer. The _last_ value recorded for a key will be emitted to the XML output
+if you specify one. For example, the test
+
+```
+TEST_F(WidgetUsageTest, MinAndMaxWidgets) {
+  RecordProperty("MaximumWidgets", ComputeMaxUsage());
+  RecordProperty("MinimumWidgets", ComputeMinUsage());
+}
+```
+
+will output XML like this:
+
+```
+...
+  <testcase name="MinAndMaxWidgets" status="run" time="6" classname="WidgetUsageTest"
+            MaximumWidgets="12"
+            MinimumWidgets="9" />
+...
+```
+
+_Note_:
+  * `RecordProperty()` is a static member of the `Test` class. Therefore it needs to be prefixed with `::testing::Test::` if used outside of the `TEST` body and the test fixture class.
+  * `key` must be a valid XML attribute name, and cannot conflict with the ones already used by Google Test (`name`, `status`,     `time`, and `classname`).
+
+_Availability_: Linux, Windows, Mac.
+
+# Sharing Resources Between Tests in the Same Test Case #
+
+
+
+Google Test creates a new test fixture object for each test in order to make
+tests independent and easier to debug. However, sometimes tests use resources
+that are expensive to set up, making the one-copy-per-test model prohibitively
+expensive.
+
+If the tests don't change the resource, there's no harm in them sharing a
+single resource copy. So, in addition to per-test set-up/tear-down, Google Test
+also supports per-test-case set-up/tear-down. To use it:
+
+  1. In your test fixture class (say `FooTest` ), define as `static` some member variables to hold the shared resources.
+  1. In the same test fixture class, define a `static void SetUpTestCase()` function (remember not to spell it as **`SetupTestCase`** with a small `u`!) to set up the shared resources and a `static void TearDownTestCase()` function to tear them down.
+
+That's it! Google Test automatically calls `SetUpTestCase()` before running the
+_first test_ in the `FooTest` test case (i.e. before creating the first
+`FooTest` object), and calls `TearDownTestCase()` after running the _last test_
+in it (i.e. after deleting the last `FooTest` object). In between, the tests
+can use the shared resources.
+
+Remember that the test order is undefined, so your code can't depend on a test
+preceding or following another. Also, the tests must either not modify the
+state of any shared resource, or, if they do modify the state, they must
+restore the state to its original value before passing control to the next
+test.
+
+Here's an example of per-test-case set-up and tear-down:
+```
+class FooTest : public ::testing::Test {
+ protected:
+  // Per-test-case set-up.
+  // Called before the first test in this test case.
+  // Can be omitted if not needed.
+  static void SetUpTestCase() {
+    shared_resource_ = new ...;
+  }
+
+  // Per-test-case tear-down.
+  // Called after the last test in this test case.
+  // Can be omitted if not needed.
+  static void TearDownTestCase() {
+    delete shared_resource_;
+    shared_resource_ = NULL;
+  }
+
+  // You can define per-test set-up and tear-down logic as usual.
+  virtual void SetUp() { ... }
+  virtual void TearDown() { ... }
+
+  // Some expensive resource shared by all tests.
+  static T* shared_resource_;
+};
+
+T* FooTest::shared_resource_ = NULL;
+
+TEST_F(FooTest, Test1) {
+  ... you can refer to shared_resource here ...
+}
+TEST_F(FooTest, Test2) {
+  ... you can refer to shared_resource here ...
+}
+```
+
+_Availability:_ Linux, Windows, Mac.
+
+# Global Set-Up and Tear-Down #
+
+Just as you can do set-up and tear-down at the test level and the test case
+level, you can also do it at the test program level. Here's how.
+
+First, you subclass the `::testing::Environment` class to define a test
+environment, which knows how to set-up and tear-down:
+
+```
+class Environment {
+ public:
+  virtual ~Environment() {}
+  // Override this to define how to set up the environment.
+  virtual void SetUp() {}
+  // Override this to define how to tear down the environment.
+  virtual void TearDown() {}
+};
+```
+
+Then, you register an instance of your environment class with Google Test by
+calling the `::testing::AddGlobalTestEnvironment()` function:
+
+```
+Environment* AddGlobalTestEnvironment(Environment* env);
+```
+
+Now, when `RUN_ALL_TESTS()` is called, it first calls the `SetUp()` method of
+the environment object, then runs the tests if there was no fatal failures, and
+finally calls `TearDown()` of the environment object.
+
+It's OK to register multiple environment objects. In this case, their `SetUp()`
+will be called in the order they are registered, and their `TearDown()` will be
+called in the reverse order.
+
+Note that Google Test takes ownership of the registered environment objects.
+Therefore **do not delete them** by yourself.
+
+You should call `AddGlobalTestEnvironment()` before `RUN_ALL_TESTS()` is
+called, probably in `main()`. If you use `gtest_main`, you need to      call
+this before `main()` starts for it to take effect. One way to do this is to
+define a global variable like this:
+
+```
+::testing::Environment* const foo_env = ::testing::AddGlobalTestEnvironment(new FooEnvironment);
+```
+
+However, we strongly recommend you to write your own `main()` and call
+`AddGlobalTestEnvironment()` there, as relying on initialization of global
+variables makes the code harder to read and may cause problems when you
+register multiple environments from different translation units and the
+environments have dependencies among them (remember that the compiler doesn't
+guarantee the order in which global variables from different translation units
+are initialized).
+
+_Availability:_ Linux, Windows, Mac.
+
+
+# Value Parameterized Tests #
+
+_Value-parameterized tests_ allow you to test your code with different
+parameters without writing multiple copies of the same test.
+
+Suppose you write a test for your code and then realize that your code is affected by a presence of a Boolean command line flag.
+
+```
+TEST(MyCodeTest, TestFoo) {
+  // A code to test foo().
+}
+```
+
+Usually people factor their test code into a function with a Boolean parameter in such situations. The function sets the flag, then executes the testing code.
+
+```
+void TestFooHelper(bool flag_value) {
+  flag = flag_value;
+  // A code to test foo().
+}
+
+TEST(MyCodeTest, TestFooo) {
+  TestFooHelper(false);
+  TestFooHelper(true);
+}
+```
+
+But this setup has serious drawbacks. First, when a test assertion fails in your tests, it becomes unclear what value of the parameter caused it to fail. You can stream a clarifying message into your `EXPECT`/`ASSERT` statements, but it you'll have to do it with all of them. Second, you have to add one such helper function per test. What if you have ten tests? Twenty? A hundred?
+
+Value-parameterized tests will let you write your test only once and then easily instantiate and run it with an arbitrary number of parameter values.
+
+Here are some other situations when value-parameterized tests come handy:
+
+  * You wan to test different implementations of an OO interface.
+  * You want to test your code over various inputs (a.k.a. data-driven testing). This feature is easy to abuse, so please exercise your good sense when doing it!
+
+## How to Write Value-Parameterized Tests ##
+
+To write value-parameterized tests, first you should define a fixture
+class. It must be derived from `::testing::TestWithParam<T>`, where `T`
+is the type of your parameter values. `TestWithParam<T>` is itself
+derived from `::testing::Test`. `T` can be any copyable type. If it's
+a raw pointer, you are responsible for managing the lifespan of the
+pointed values.
+
+```
+class FooTest : public ::testing::TestWithParam<const char*> {
+  // You can implement all the usual fixture class members here.
+  // To access the test parameter, call GetParam() from class
+  // TestWithParam<T>.
+};
+```
+
+Then, use the `TEST_P` macro to define as many test patterns using
+this fixture as you want.  The `_P` suffix is for "parameterized" or
+"pattern", whichever you prefer to think.
+
+```
+TEST_P(FooTest, DoesBlah) {
+  // Inside a test, access the test parameter with the GetParam() method
+  // of the TestWithParam<T> class:
+  EXPECT_TRUE(foo.Blah(GetParam()));
+  ...
+}
+
+TEST_P(FooTest, HasBlahBlah) {
+  ...
+}
+```
+
+Finally, you can use `INSTANTIATE_TEST_CASE_P` to instantiate the test
+case with any set of parameters you want. Google Test defines a number of
+functions for generating test parameters. They return what we call
+(surprise!) _parameter generators_. Here is a summary of them,
+which are all in the `testing` namespace:
+
+| `Range(begin, end[, step])` | Yields values `{begin, begin+step, begin+step+step, ...}`. The values do not include `end`. `step` defaults to 1. |
+|:----------------------------|:------------------------------------------------------------------------------------------------------------------|
+| `Values(v1, v2, ..., vN)`   | Yields values `{v1, v2, ..., vN}`.                                                                                |
+| `ValuesIn(container)` and `ValuesIn(begin, end)` | Yields values from a C-style array, an STL-style container, or an iterator range `[begin, end)`.                  |
+| `Bool()`                    | Yields sequence `{false, true}`.                                                                                  |
+| `Combine(g1, g2, ..., gN)`  | Yields all combinations (the Cartesian product for the math savvy) of the values generated by the `N` generators. This is only available if your system provides the `<tr1/tuple>` header. If you are sure your system does, and Google Test disagrees, you can override it by defining `GTEST_HAS_TR1_TUPLE=1`. See comments in [include/gtest/internal/gtest-port.h](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/internal/gtest-port.h) for more information. |
+
+For more details, see the comments at the definitions of these functions in the [source code](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest-param-test.h).
+
+The following statement will instantiate tests from the `FooTest` test case
+each with parameter values `"meeny"`, `"miny"`, and `"moe"`.
+
+```
+INSTANTIATE_TEST_CASE_P(InstantiationName,
+                        FooTest,
+                        ::testing::Values("meeny", "miny", "moe"));
+```
+
+To distinguish different instances of the pattern (yes, you can
+instantiate it more than once), the first argument to
+`INSTANTIATE_TEST_CASE_P` is a prefix that will be added to the actual
+test case name. Remember to pick unique prefixes for different
+instantiations. The tests from the instantiation above will have these
+names:
+
+  * `InstantiationName/FooTest.DoesBlah/0` for `"meeny"`
+  * `InstantiationName/FooTest.DoesBlah/1` for `"miny"`
+  * `InstantiationName/FooTest.DoesBlah/2` for `"moe"`
+  * `InstantiationName/FooTest.HasBlahBlah/0` for `"meeny"`
+  * `InstantiationName/FooTest.HasBlahBlah/1` for `"miny"`
+  * `InstantiationName/FooTest.HasBlahBlah/2` for `"moe"`
+
+You can use these names in [--gtest\_filter](#Running_a_Subset_of_the_Tests.md).
+
+This statement will instantiate all tests from `FooTest` again, each
+with parameter values `"cat"` and `"dog"`:
+
+```
+const char* pets[] = {"cat", "dog"};
+INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest,
+                        ::testing::ValuesIn(pets));
+```
+
+The tests from the instantiation above will have these names:
+
+  * `AnotherInstantiationName/FooTest.DoesBlah/0` for `"cat"`
+  * `AnotherInstantiationName/FooTest.DoesBlah/1` for `"dog"`
+  * `AnotherInstantiationName/FooTest.HasBlahBlah/0` for `"cat"`
+  * `AnotherInstantiationName/FooTest.HasBlahBlah/1` for `"dog"`
+
+Please note that `INSTANTIATE_TEST_CASE_P` will instantiate _all_
+tests in the given test case, whether their definitions come before or
+_after_ the `INSTANTIATE_TEST_CASE_P` statement.
+
+You can see
+[these](http://code.google.com/p/googletest/source/browse/trunk/samples/sample7_unittest.cc)
+[files](http://code.google.com/p/googletest/source/browse/trunk/samples/sample8_unittest.cc) for more examples.
+
+_Availability_: Linux, Windows (requires MSVC 8.0 or above), Mac; since version 1.2.0.
+
+## Creating Value-Parameterized Abstract Tests ##
+
+In the above, we define and instantiate `FooTest` in the same source
+file. Sometimes you may want to define value-parameterized tests in a
+library and let other people instantiate them later. This pattern is
+known as <i>abstract tests</i>. As an example of its application, when you
+are designing an interface you can write a standard suite of abstract
+tests (perhaps using a factory function as the test parameter) that
+all implementations of the interface are expected to pass. When
+someone implements the interface, he can instantiate your suite to get
+all the interface-conformance tests for free.
+
+To define abstract tests, you should organize your code like this:
+
+  1. Put the definition of the parameterized test fixture class (e.g. `FooTest`) in a header file, say `foo_param_test.h`. Think of this as _declaring_ your abstract tests.
+  1. Put the `TEST_P` definitions in `foo_param_test.cc`, which includes `foo_param_test.h`. Think of this as _implementing_ your abstract tests.
+
+Once they are defined, you can instantiate them by including
+`foo_param_test.h`, invoking `INSTANTIATE_TEST_CASE_P()`, and linking
+with `foo_param_test.cc`. You can instantiate the same abstract test
+case multiple times, possibly in different source files.
+
+# Typed Tests #
+
+Suppose you have multiple implementations of the same interface and
+want to make sure that all of them satisfy some common requirements.
+Or, you may have defined several types that are supposed to conform to
+the same "concept" and you want to verify it.  In both cases, you want
+the same test logic repeated for different types.
+
+While you can write one `TEST` or `TEST_F` for each type you want to
+test (and you may even factor the test logic into a function template
+that you invoke from the `TEST`), it's tedious and doesn't scale:
+if you want _m_ tests over _n_ types, you'll end up writing _m\*n_
+`TEST`s.
+
+_Typed tests_ allow you to repeat the same test logic over a list of
+types.  You only need to write the test logic once, although you must
+know the type list when writing typed tests.  Here's how you do it:
+
+First, define a fixture class template.  It should be parameterized
+by a type.  Remember to derive it from `::testing::Test`:
+
+```
+template <typename T>
+class FooTest : public ::testing::Test {
+ public:
+  ...
+  typedef std::list<T> List;
+  static T shared_;
+  T value_;
+};
+```
+
+Next, associate a list of types with the test case, which will be
+repeated for each type in the list:
+
+```
+typedef ::testing::Types<char, int, unsigned int> MyTypes;
+TYPED_TEST_CASE(FooTest, MyTypes);
+```
+
+The `typedef` is necessary for the `TYPED_TEST_CASE` macro to parse
+correctly.  Otherwise the compiler will think that each comma in the
+type list introduces a new macro argument.
+
+Then, use `TYPED_TEST()` instead of `TEST_F()` to define a typed test
+for this test case.  You can repeat this as many times as you want:
+
+```
+TYPED_TEST(FooTest, DoesBlah) {
+  // Inside a test, refer to the special name TypeParam to get the type
+  // parameter.  Since we are inside a derived class template, C++ requires
+  // us to visit the members of FooTest via 'this'.
+  TypeParam n = this->value_;
+
+  // To visit static members of the fixture, add the 'TestFixture::'
+  // prefix.
+  n += TestFixture::shared_;
+
+  // To refer to typedefs in the fixture, add the 'typename TestFixture::'
+  // prefix.  The 'typename' is required to satisfy the compiler.
+  typename TestFixture::List values;
+  values.push_back(n);
+  ...
+}
+
+TYPED_TEST(FooTest, HasPropertyA) { ... }
+```
+
+You can see `samples/sample6_unittest.cc` for a complete example.
+
+_Availability:_ Linux, Windows (requires MSVC 8.0 or above), Mac;
+since version 1.1.0.
+
+# Type-Parameterized Tests #
+
+_Type-parameterized tests_ are like typed tests, except that they
+don't require you to know the list of types ahead of time.  Instead,
+you can define the test logic first and instantiate it with different
+type lists later.  You can even instantiate it more than once in the
+same program.
+
+If you are designing an interface or concept, you can define a suite
+of type-parameterized tests to verify properties that any valid
+implementation of the interface/concept should have.  Then, the author
+of each implementation can just instantiate the test suite with his
+type to verify that it conforms to the requirements, without having to
+write similar tests repeatedly.  Here's an example:
+
+First, define a fixture class template, as we did with typed tests:
+
+```
+template <typename T>
+class FooTest : public ::testing::Test {
+  ...
+};
+```
+
+Next, declare that you will define a type-parameterized test case:
+
+```
+TYPED_TEST_CASE_P(FooTest);
+```
+
+The `_P` suffix is for "parameterized" or "pattern", whichever you
+prefer to think.
+
+Then, use `TYPED_TEST_P()` to define a type-parameterized test.  You
+can repeat this as many times as you want:
+
+```
+TYPED_TEST_P(FooTest, DoesBlah) {
+  // Inside a test, refer to TypeParam to get the type parameter.
+  TypeParam n = 0;
+  ...
+}
+
+TYPED_TEST_P(FooTest, HasPropertyA) { ... }
+```
+
+Now the tricky part: you need to register all test patterns using the
+`REGISTER_TYPED_TEST_CASE_P` macro before you can instantiate them.
+The first argument of the macro is the test case name; the rest are
+the names of the tests in this test case:
+
+```
+REGISTER_TYPED_TEST_CASE_P(FooTest,
+                           DoesBlah, HasPropertyA);
+```
+
+Finally, you are free to instantiate the pattern with the types you
+want.  If you put the above code in a header file, you can `#include`
+it in multiple C++ source files and instantiate it multiple times.
+
+```
+typedef ::testing::Types<char, int, unsigned int> MyTypes;
+INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
+```
+
+To distinguish different instances of the pattern, the first argument
+to the `INSTANTIATE_TYPED_TEST_CASE_P` macro is a prefix that will be
+added to the actual test case name.  Remember to pick unique prefixes
+for different instances.
+
+In the special case where the type list contains only one type, you
+can write that type directly without `::testing::Types<...>`, like this:
+
+```
+INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int);
+```
+
+You can see `samples/sample6_unittest.cc` for a complete example.
+
+_Availability:_ Linux, Windows (requires MSVC 8.0 or above), Mac;
+since version 1.1.0.
+
+# Testing Private Code #
+
+If you change your software's internal implementation, your tests should not
+break as long as the change is not observable by users. Therefore, per the
+_black-box testing principle_, most of the time you should test your code
+through its public interfaces.
+
+If you still find yourself needing to test internal implementation code,
+consider if there's a better design that wouldn't require you to do so. If you
+absolutely have to test non-public interface code though, you can. There are
+two cases to consider:
+
+  * Static functions (_not_ the same as static member functions!) or unnamed namespaces, and
+  * Private or protected class members
+
+## Static Functions ##
+
+Both static functions and definitions/declarations in an unnamed namespace are
+only visible within the same translation unit. To test them, you can `#include`
+the entire `.cc` file being tested in your `*_test.cc` file. (#including `.cc`
+files is not a good way to reuse code - you should not do this in production
+code!)
+
+However, a better approach is to move the private code into the
+`foo::internal` namespace, where `foo` is the namespace your project normally
+uses, and put the private declarations in a `*-internal.h` file. Your
+production `.cc` files and your tests are allowed to include this internal
+header, but your clients are not. This way, you can fully test your internal
+implementation without leaking it to your clients.
+
+## Private Class Members ##
+
+Private class members are only accessible from within the class or by friends.
+To access a class' private members, you can declare your test fixture as a
+friend to the class and define accessors in your fixture. Tests using the
+fixture can then access the private members of your production class via the
+accessors in the fixture. Note that even though your fixture is a friend to
+your production class, your tests are not automatically friends to it, as they
+are technically defined in sub-classes of the fixture.
+
+Another way to test private members is to refactor them into an implementation
+class, which is then declared in a `*-internal.h` file. Your clients aren't
+allowed to include this header but your tests can. Such is called the Pimpl
+(Private Implementation) idiom.
+
+Or, you can declare an individual test as a friend of your class by adding this
+line in the class body:
+
+```
+FRIEND_TEST(TestCaseName, TestName);
+```
+
+For example,
+```
+// foo.h
+#include <gtest/gtest_prod.h>
+
+// Defines FRIEND_TEST.
+class Foo {
+  ...
+ private:
+  FRIEND_TEST(FooTest, BarReturnsZeroOnNull);
+  int Bar(void* x);
+};
+
+// foo_test.cc
+...
+TEST(FooTest, BarReturnsZeroOnNull) {
+  Foo foo;
+  EXPECT_EQ(0, foo.Bar(NULL));
+  // Uses Foo's private member Bar().
+}
+```
+
+Pay special attention when your class is defined in a namespace, as you should
+define your test fixtures and tests in the same namespace if you want them to
+be friends of your class. For example, if the code to be tested looks like:
+
+```
+namespace my_namespace {
+
+class Foo {
+  friend class FooTest;
+  FRIEND_TEST(FooTest, Bar);
+  FRIEND_TEST(FooTest, Baz);
+  ...
+  definition of the class Foo
+  ...
+};
+
+}  // namespace my_namespace
+```
+
+Your test code should be something like:
+
+```
+namespace my_namespace {
+class FooTest : public ::testing::Test {
+ protected:
+  ...
+};
+
+TEST_F(FooTest, Bar) { ... }
+TEST_F(FooTest, Baz) { ... }
+
+}  // namespace my_namespace
+```
+
+# Catching Failures #
+
+If you are building a testing utility on top of Google Test, you'll
+want to test your utility.  What framework would you use to test it?
+Google Test, of course.
+
+The challenge is to verify that your testing utility reports failures
+correctly.  In frameworks that report a failure by throwing an
+exception, you could catch the exception and assert on it.  But Google
+Test doesn't use exceptions, so how do we test that a piece of code
+generates an expected failure?
+
+`<gtest/gtest-spi.h>` contains some constructs to do this.  After
+#including this header, you can use
+
+| `EXPECT_FATAL_FAILURE(`_statement, substring_`);` |
+|:--------------------------------------------------|
+
+to assert that _statement_ generates a fatal (e.g. `ASSERT_*`) failure
+whose message contains the given _substring_, or use
+
+| `EXPECT_NONFATAL_FAILURE(`_statement, substring_`);` |
+|:-----------------------------------------------------|
+
+if you are expecting a non-fatal (e.g. `EXPECT_*`) failure.
+
+For technical reasons, there are some caveats:
+
+  1. You cannot stream a failure message to either macro.
+  1. _statement_ in `EXPECT_FATAL_FAILURE()` cannot reference local non-static variables or non-static members of `this` object.
+  1. _statement_ in `EXPECT_FATAL_FAILURE()` cannot return a value.
+
+_Note:_ Google Test is designed with threads in mind.  Once the
+synchronization primitives in `<gtest/internal/gtest-port.h>` have
+been implemented, Google Test will become thread-safe, meaning that
+you can then use assertions in multiple threads concurrently.  Before
+
+that, however, Google Test only supports single-threaded usage.  Once
+thread-safe, `EXPECT_FATAL_FAILURE()` and `EXPECT_NONFATAL_FAILURE()`
+will capture failures in the current thread only. If _statement_
+creates new threads, failures in these threads will be ignored.  If
+you want to capture failures from all threads instead, you should use
+the following macros:
+
+| `EXPECT_FATAL_FAILURE_ON_ALL_THREADS(`_statement, substring_`);` |
+|:-----------------------------------------------------------------|
+| `EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(`_statement, substring_`);` |
+
+# Getting the Current Test's Name #
+
+Sometimes a function may need to know the name of the currently running test.
+For example, you may be using the `SetUp()` method of your test fixture to set
+the golden file name based on which test is running. The `::testing::TestInfo`
+class has this information:
+
+```
+namespace testing {
+
+class TestInfo {
+ public:
+  // Returns the test case name and the test name, respectively.
+  //
+  // Do NOT delete or free the return value - it's managed by the
+  // TestInfo class.
+  const char* test_case_name() const;
+  const char* name() const;
+};
+
+}  // namespace testing
+```
+
+
+> To obtain a `TestInfo` object for the currently running test, call
+`current_test_info()` on the `UnitTest` singleton object:
+
+```
+// Gets information about the currently running test.
+// Do NOT delete the returned object - it's managed by the UnitTest class.
+const ::testing::TestInfo* const test_info =
+  ::testing::UnitTest::GetInstance()->current_test_info();
+printf("We are in test %s of test case %s.\n",
+       test_info->name(), test_info->test_case_name());
+```
+
+`current_test_info()` returns a null pointer if no test is running. In
+particular, you cannot find the test case name in `TestCaseSetUp()`,
+`TestCaseTearDown()` (where you know the test case name implicitly), or
+functions called from them.
+
+_Availability:_ Linux, Windows, Mac.
+
+# Extending Google Test by Handling Test Events #
+
+Google Test provides an <b>event listener API</b> to let you receive
+notifications about the progress of a test program and test
+failures. The events you can listen to include the start and end of
+the test program, a test case, or a test method, among others. You may
+use this API to augment or replace the standard console output,
+replace the XML output, or provide a completely different form of
+output, such as a GUI or a database. You can also use test events as
+checkpoints to implement a resource leak checker, for example.
+
+_Availability:_ Linux, Windows, Mac; since v1.4.0.
+
+## Defining Event Listeners ##
+
+To define a event listener, you subclass either
+[testing::TestEventListener](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest.h#855)
+or [testing::EmptyTestEventListener](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest.h#905).
+The former is an (abstract) interface, where <i>each pure virtual method<br>
+can be overridden to handle a test event</i> (For example, when a test
+starts, the `OnTestStart()` method will be called.). The latter provides
+an empty implementation of all methods in the interface, such that a
+subclass only needs to override the methods it cares about.
+
+When an event is fired, its context is passed to the handler function
+as an argument. The following argument types are used:
+  * [UnitTest](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest.h#1007) reflects the state of the entire test program,
+  * [TestCase](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest.h#689) has information about a test case, which can contain one or more tests,
+  * [TestInfo](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest.h#599) contains the state of a test, and
+  * [TestPartResult](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest-test-part.h#42) represents the result of a test assertion.
+
+An event handler function can examine the argument it receives to find
+out interesting information about the event and the test program's
+state.  Here's an example:
+
+```
+  class MinimalistPrinter : public ::testing::EmptyTestEventListener {
+    // Called before a test starts.
+    virtual void OnTestStart(const ::testing::TestInfo& test_info) {
+      printf("*** Test %s.%s starting.\n",
+             test_info.test_case_name(), test_info.name());
+    }
+
+    // Called after a failed assertion or a SUCCESS().
+    virtual void OnTestPartResult(
+        const ::testing::TestPartResult& test_part_result) {
+      printf("%s in %s:%d\n%s\n",
+             test_part_result.failed() ? "*** Failure" : "Success",
+             test_part_result.file_name(),
+             test_part_result.line_number(),
+             test_part_result.summary());
+    }
+
+    // Called after a test ends.
+    virtual void OnTestEnd(const ::testing::TestInfo& test_info) {
+      printf("*** Test %s.%s ending.\n",
+             test_info.test_case_name(), test_info.name());
+    }
+  };
+```
+
+## Using Event Listeners ##
+
+To use the event listener you have defined, add an instance of it to
+the Google Test event listener list (represented by class
+[TestEventListeners](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest.h#929)
+- note the "s" at the end of the name) in your
+`main()` function, before calling `RUN_ALL_TESTS()`:
+```
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  // Gets hold of the event listener list.
+  ::testing::TestEventListeners& listeners =
+      ::testing::UnitTest::GetInstance()->listeners();
+  // Adds a listener to the end.  Google Test takes the ownership.
+  listeners.Append(new MinimalistPrinter);
+  return RUN_ALL_TESTS();
+}
+```
+
+There's only one problem: the default test result printer is still in
+effect, so its output will mingle with the output from your minimalist
+printer. To suppress the default printer, just release it from the
+event listener list and delete it. You can do so by adding one line:
+```
+  ...
+  delete listeners.Release(listeners.default_result_printer());
+  listeners.Append(new MinimalistPrinter);
+  return RUN_ALL_TESTS();
+```
+
+Now, sit back and enjoy a completely different output from your
+tests. For more details, you can read this
+[sample](http://code.google.com/p/googletest/source/browse/trunk/samples/sample9_unittest.cc).
+
+You may append more than one listener to the list. When an `On*Start()`
+or `OnTestPartResult()` event is fired, the listeners will receive it in
+the order they appear in the list (since new listeners are added to
+the end of the list, the default text printer and the default XML
+generator will receive the event first). An `On*End()` event will be
+received by the listeners in the _reverse_ order. This allows output by
+listeners added later to be framed by output from listeners added
+earlier.
+
+## Generating Failures in Listeners ##
+
+You may use failure-raising macros (`EXPECT_*()`, `ASSERT_*()`,
+`FAIL()`, etc) when processing an event. There are some restrictions:
+
+  1. You cannot generate any failure in `OnTestPartResult()` (otherwise it will cause `OnTestPartResult()` to be called recursively).
+  1. A listener that handles `OnTestPartResult()` is not allowed to generate any failure.
+
+When you add listeners to the listener list, you should put listeners
+that handle `OnTestPartResult()` _before_ listeners that can generate
+failures. This ensures that failures generated by the latter are
+attributed to the right test by the former.
+
+We have a sample of failure-raising listener
+[here](http://code.google.com/p/googletest/source/browse/trunk/samples/sample10_unittest.cc).
+
+# Running Test Programs: Advanced Options #
+
+Google Test test programs are ordinary executables. Once built, you can run
+them directly and affect their behavior via the following environment variables
+and/or command line flags. For the flags to work, your programs must call
+`::testing::InitGoogleTest()` before calling `RUN_ALL_TESTS()`.
+
+To see a list of supported flags and their usage, please run your test
+program with the `--help` flag.  You can also use `-h`, `-?`, or `/?`
+for short.  This feature is added in version 1.3.0.
+
+If an option is specified both by an environment variable and by a
+flag, the latter takes precedence.  Most of the options can also be
+set/read in code: to access the value of command line flag
+`--gtest_foo`, write `::testing::GTEST_FLAG(foo)`.  A common pattern is
+to set the value of a flag before calling `::testing::InitGoogleTest()`
+to change the default value of the flag:
+```
+int main(int argc, char** argv) {
+  // Disables elapsed time by default.
+  ::testing::GTEST_FLAG(print_time) = false;
+
+  // This allows the user to override the flag on the command line.
+  ::testing::InitGoogleTest(&argc, argv);
+
+  return RUN_ALL_TESTS();
+}
+```
+
+## Selecting Tests ##
+
+This section shows various options for choosing which tests to run.
+
+### Listing Test Names ###
+
+Sometimes it is necessary to list the available tests in a program before
+running them so that a filter may be applied if needed. Including the flag
+`--gtest_list_tests` overrides all other flags and lists tests in the following
+format:
+```
+TestCase1.
+  TestName1
+  TestName2
+TestCase2.
+  TestName
+```
+
+None of the tests listed are actually run if the flag is provided. There is no
+corresponding environment variable for this flag.
+
+_Availability:_ Linux, Windows, Mac.
+
+### Running a Subset of the Tests ###
+
+By default, a Google Test program runs all tests the user has defined.
+Sometimes, you want to run only a subset of the tests (e.g. for debugging or
+quickly verifying a change). If you set the `GTEST_FILTER` environment variable
+or the `--gtest_filter` flag to a filter string, Google Test will only run the
+tests whose full names (in the form of `TestCaseName.TestName`) match the
+filter.
+
+The format of a filter is a '`:`'-separated list of wildcard patterns (called
+the positive patterns) optionally followed by a '`-`' and another
+'`:`'-separated pattern list (called the negative patterns). A test matches the
+filter if and only if it matches any of the positive patterns but does not
+match any of the negative patterns.
+
+A pattern may contain `'*'` (matches any string) or `'?'` (matches any single
+character). For convenience, the filter `'*-NegativePatterns'` can be also
+written as `'-NegativePatterns'`.
+
+For example:
+
+  * `./foo_test` Has no flag, and thus runs all its tests.
+  * `./foo_test --gtest_filter=*` Also runs everything, due to the single match-everything `*` value.
+  * `./foo_test --gtest_filter=FooTest.*` Runs everything in test case `FooTest`.
+  * `./foo_test --gtest_filter=*Null*:*Constructor*` Runs any test whose full name contains either `"Null"` or `"Constructor"`.
+  * `./foo_test --gtest_filter=-*DeathTest.*` Runs all non-death tests.
+  * `./foo_test --gtest_filter=FooTest.*-FooTest.Bar` Runs everything in test case `FooTest` except `FooTest.Bar`.
+
+_Availability:_ Linux, Windows, Mac.
+
+### Temporarily Disabling Tests ###
+
+If you have a broken test that you cannot fix right away, you can add the
+`DISABLED_` prefix to its name. This will exclude it from execution. This is
+better than commenting out the code or using `#if 0`, as disabled tests are
+still compiled (and thus won't rot).
+
+If you need to disable all tests in a test case, you can either add `DISABLED_`
+to the front of the name of each test, or alternatively add it to the front of
+the test case name.
+
+For example, the following tests won't be run by Google Test, even though they
+will still be compiled:
+
+```
+// Tests that Foo does Abc.
+TEST(FooTest, DISABLED_DoesAbc) { ... }
+
+class DISABLED_BarTest : public ::testing::Test { ... };
+
+// Tests that Bar does Xyz.
+TEST_F(DISABLED_BarTest, DoesXyz) { ... }
+```
+
+_Note:_ This feature should only be used for temporary pain-relief. You still
+have to fix the disabled tests at a later date. As a reminder, Google Test will
+print a banner warning you if a test program contains any disabled tests.
+
+_Tip:_ You can easily count the number of disabled tests you have
+using `grep`. This number can be used as a metric for improving your
+test quality.
+
+_Availability:_ Linux, Windows, Mac.
+
+### Temporarily Enabling Disabled Tests ###
+
+To include [disabled tests](#Temporarily_Disabling_Tests.md) in test
+execution, just invoke the test program with the
+`--gtest_also_run_disabled_tests` flag or set the
+`GTEST_ALSO_RUN_DISABLED_TESTS` environment variable to a value other
+than `0`.  You can combine this with the
+[--gtest\_filter](#Running_a_Subset_of_the_Tests.md) flag to further select
+which disabled tests to run.
+
+_Availability:_ Linux, Windows, Mac; since version 1.3.0.
+
+## Repeating the Tests ##
+
+Once in a while you'll run into a test whose result is hit-or-miss. Perhaps it
+will fail only 1% of the time, making it rather hard to reproduce the bug under
+a debugger. This can be a major source of frustration.
+
+The `--gtest_repeat` flag allows you to repeat all (or selected) test methods
+in a program many times. Hopefully, a flaky test will eventually fail and give
+you a chance to debug. Here's how to use it:
+
+| `$ foo_test --gtest_repeat=1000` | Repeat foo\_test 1000 times and don't stop at failures. |
+|:---------------------------------|:--------------------------------------------------------|
+| `$ foo_test --gtest_repeat=-1`   | A negative count means repeating forever.               |
+| `$ foo_test --gtest_repeat=1000 --gtest_break_on_failure` | Repeat foo\_test 1000 times, stopping at the first failure. This is especially useful when running under a debugger: when the testfails, it will drop into the debugger and you can then inspect variables and stacks. |
+| `$ foo_test --gtest_repeat=1000 --gtest_filter=FooBar` | Repeat the tests whose name matches the filter 1000 times. |
+
+If your test program contains global set-up/tear-down code registered
+using `AddGlobalTestEnvironment()`, it will be repeated in each
+iteration as well, as the flakiness may be in it. You can also specify
+the repeat count by setting the `GTEST_REPEAT` environment variable.
+
+_Availability:_ Linux, Windows, Mac.
+
+## Shuffling the Tests ##
+
+You can specify the `--gtest_shuffle` flag (or set the `GTEST_SHUFFLE`
+environment variable to `1`) to run the tests in a program in a random
+order. This helps to reveal bad dependencies between tests.
+
+By default, Google Test uses a random seed calculated from the current
+time. Therefore you'll get a different order every time. The console
+output includes the random seed value, such that you can reproduce an
+order-related test failure later. To specify the random seed
+explicitly, use the `--gtest_random_seed=SEED` flag (or set the
+`GTEST_RANDOM_SEED` environment variable), where `SEED` is an integer
+between 0 and 99999. The seed value 0 is special: it tells Google Test
+to do the default behavior of calculating the seed from the current
+time.
+
+If you combine this with `--gtest_repeat=N`, Google Test will pick a
+different random seed and re-shuffle the tests in each iteration.
+
+_Availability:_ Linux, Windows, Mac; since v1.4.0.
+
+## Controlling Test Output ##
+
+This section teaches how to tweak the way test results are reported.
+
+### Colored Terminal Output ###
+
+Google Test can use colors in its terminal output to make it easier to spot
+the separation between tests, and whether tests passed.
+
+You can set the GTEST\_COLOR environment variable or set the `--gtest_color`
+command line flag to `yes`, `no`, or `auto` (the default) to enable colors,
+disable colors, or let Google Test decide. When the value is `auto`, Google
+Test will use colors if and only if the output goes to a terminal and (on
+non-Windows platforms) the `TERM` environment variable is set to `xterm` or
+`xterm-color`.
+
+_Availability:_ Linux, Windows, Mac.
+
+### Suppressing the Elapsed Time ###
+
+By default, Google Test prints the time it takes to run each test.  To
+suppress that, run the test program with the `--gtest_print_time=0`
+command line flag.  Setting the `GTEST_PRINT_TIME` environment
+variable to `0` has the same effect.
+
+_Availability:_ Linux, Windows, Mac.  (In Google Test 1.3.0 and lower,
+the default behavior is that the elapsed time is **not** printed.)
+
+### Generating an XML Report ###
+
+Google Test can emit a detailed XML report to a file in addition to its normal
+textual output. The report contains the duration of each test, and thus can
+help you identify slow tests.
+
+To generate the XML report, set the `GTEST_OUTPUT` environment variable or the
+`--gtest_output` flag to the string `"xml:_path_to_output_file_"`, which will
+create the file at the given location. You can also just use the string
+`"xml"`, in which case the output can be found in the `test_detail.xml` file in
+the current directory.
+
+If you specify a directory (for example, `"xml:output/directory/"` on Linux or
+`"xml:output\directory\"` on Windows), Google Test will create the XML file in
+that directory, named after the test executable (e.g. `foo_test.xml` for test
+program `foo_test` or `foo_test.exe`). If the file already exists (perhaps left
+over from a previous run), Google Test will pick a different name (e.g.
+`foo_test_1.xml`) to avoid overwriting it.
+
+The report uses the format described here.  It is based on the
+`junitreport` Ant task and can be parsed by popular continuous build
+systems like [Hudson](https://hudson.dev.java.net/). Since that format
+was originally intended for Java, a little interpretation is required
+to make it apply to Google Test tests, as shown here:
+
+```
+<testsuites name="AllTests" ...>
+  <testsuite name="test_case_name" ...>
+    <testcase name="test_name" ...>
+      <failure message="..."/>
+      <failure message="..."/>
+      <failure message="..."/>
+    </testcase>
+  </testsuite>
+</testsuites>
+```
+
+  * The root `<testsuites>` element corresponds to the entire test program.
+  * `<testsuite>` elements correspond to Google Test test cases.
+  * `<testcase>` elements correspond to Google Test test functions.
+
+For instance, the following program
+
+```
+TEST(MathTest, Addition) { ... }
+TEST(MathTest, Subtraction) { ... }
+TEST(LogicTest, NonContradiction) { ... }
+```
+
+could generate this report:
+
+```
+<?xml version="1.0" encoding="UTF-8"?>
+<testsuites tests="3" failures="1" errors="0" time="35" name="AllTests">
+  <testsuite name="MathTest" tests="2" failures="1"* errors="0" time="15">
+    <testcase name="Addition" status="run" time="7" classname="">
+      <failure message="Value of: add(1, 1)&#x0A; Actual: 3&#x0A;Expected: 2" type=""/>
+      <failure message="Value of: add(1, -1)&#x0A; Actual: 1&#x0A;Expected: 0" type=""/>
+    </testcase>
+    <testcase name="Subtraction" status="run" time="5" classname="">
+    </testcase>
+  </testsuite>
+  <testsuite name="LogicTest" tests="1" failures="0" errors="0" time="5">
+    <testcase name="NonContradiction" status="run" time="5" classname="">
+    </testcase>
+  </testsuite>
+</testsuites>
+```
+
+Things to note:
+
+  * The `tests` attribute of a `<testsuites>` or `<testsuite>` element tells how many test functions the Google Test program or test case contains, while the `failures` attribute tells how many of them failed.
+  * The `time` attribute expresses the duration of the test, test case, or entire test program in milliseconds.
+  * Each `<failure>` element corresponds to a single failed Google Test assertion.
+  * Some JUnit concepts don't apply to Google Test, yet we have to conform to the DTD. Therefore you'll see some dummy elements and attributes in the report. You can safely ignore these parts.
+
+_Availability:_ Linux, Windows, Mac.
+
+## Controlling How Failures Are Reported ##
+
+### Turning Assertion Failures into Break-Points ###
+
+When running test programs under a debugger, it's very convenient if the
+debugger can catch an assertion failure and automatically drop into interactive
+mode. Google Test's _break-on-failure_ mode supports this behavior.
+
+To enable it, set the `GTEST_BREAK_ON_FAILURE` environment variable to a value
+other than `0` . Alternatively, you can use the `--gtest_break_on_failure`
+command line flag.
+
+_Availability:_ Linux, Windows, Mac.
+
+### Suppressing Pop-ups Caused by Exceptions ###
+
+On Windows, Google Test may be used with exceptions enabled. Even when
+exceptions are disabled, an application can still throw structured exceptions
+(SEH's). If a test throws an exception, by default Google Test doesn't try to
+catch it. Instead, you'll see a pop-up dialog, at which point you can attach
+the process to a debugger and easily find out what went wrong.
+
+However, if you don't want to see the pop-ups (for example, if you run the
+tests in a batch job), set the `GTEST_CATCH_EXCEPTIONS` environment variable to
+a non- `0` value, or use the `--gtest_catch_exceptions` flag. Google Test now
+catches all test-thrown exceptions and logs them as failures.
+
+_Availability:_ Windows. `GTEST_CATCH_EXCEPTIONS` and
+`--gtest_catch_exceptions` have no effect on Google Test's behavior on Linux or
+Mac, even if exceptions are enabled. It is possible to add support for catching
+exceptions on these platforms, but it is not implemented yet.
+
+### Letting Another Testing Framework Drive ###
+
+If you work on a project that has already been using another testing
+framework and is not ready to completely switch to Google Test yet,
+you can get much of Google Test's benefit by using its assertions in
+your existing tests.  Just change your `main()` function to look
+like:
+
+```
+#include <gtest/gtest.h>
+
+int main(int argc, char** argv) {
+  ::testing::GTEST_FLAG(throw_on_failure) = true;
+  // Important: Google Test must be initialized.
+  ::testing::InitGoogleTest(&argc, argv);
+
+  ... whatever your existing testing framework requires ...
+}
+```
+
+With that, you can use Google Test assertions in addition to the
+native assertions your testing framework provides, for example:
+
+```
+void TestFooDoesBar() {
+  Foo foo;
+  EXPECT_LE(foo.Bar(1), 100);     // A Google Test assertion.
+  CPPUNIT_ASSERT(foo.IsEmpty());  // A native assertion.
+}
+```
+
+If a Google Test assertion fails, it will print an error message and
+throw an exception, which will be treated as a failure by your host
+testing framework.  If you compile your code with exceptions disabled,
+a failed Google Test assertion will instead exit your program with a
+non-zero code, which will also signal a test failure to your test
+runner.
+
+If you don't write `::testing::GTEST_FLAG(throw_on_failure) = true;` in
+your `main()`, you can alternatively enable this feature by specifying
+the `--gtest_throw_on_failure` flag on the command-line or setting the
+`GTEST_THROW_ON_FAILURE` environment variable to a non-zero value.
+
+_Availability:_ Linux, Windows, Mac; since v1.3.0.
+
+## Distributing Test Functions to Multiple Machines ##
+
+If you have more than one machine you can use to run a test program,
+you might want to run the test functions in parallel and get the
+result faster.  We call this technique _sharding_, where each machine
+is called a _shard_.
+
+Google Test is compatible with test sharding.  To take advantage of
+this feature, your test runner (not part of Google Test) needs to do
+the following:
+
+  1. Allocate a number of machines (shards) to run the tests.
+  1. On each shard, set the `GTEST_TOTAL_SHARDS` environment variable to the total number of shards.  It must be the same for all shards.
+  1. On each shard, set the `GTEST_SHARD_INDEX` environment variable to the index of the shard.  Different shards must be assigned different indices, which must be in the range `[0, GTEST_TOTAL_SHARDS - 1]`.
+  1. Run the same test program on all shards.  When Google Test sees the above two environment variables, it will select a subset of the test functions to run.  Across all shards, each test function in the program will be run exactly once.
+  1. Wait for all shards to finish, then collect and report the results.
+
+Your project may have tests that were written without Google Test and
+thus don't understand this protocol.  In order for your test runner to
+figure out which test supports sharding, it can set the environment
+variable `GTEST_SHARD_STATUS_FILE` to a non-existent file path.  If a
+test program supports sharding, it will create this file to
+acknowledge the fact (the actual contents of the file are not
+important at this time; although we may stick some useful information
+in it in the future.); otherwise it will not create it.
+
+Here's an example to make it clear.  Suppose you have a test program
+`foo_test` that contains the following 5 test functions:
+```
+TEST(A, V)
+TEST(A, W)
+TEST(B, X)
+TEST(B, Y)
+TEST(B, Z)
+```
+and you have 3 machines at your disposal.  To run the test functions in
+parallel, you would set `GTEST_TOTAL_SHARDS` to 3 on all machines, and
+set `GTEST_SHARD_INDEX` to 0, 1, and 2 on the machines respectively.
+Then you would run the same `foo_test` on each machine.
+
+Google Test reserves the right to change how the work is distributed
+across the shards, but here's one possible scenario:
+
+  * Machine #0 runs `A.V` and `B.X`.
+  * Machine #1 runs `A.W` and `B.Y`.
+  * Machine #2 runs `B.Z`.
+
+_Availability:_ Linux, Windows, Mac; since version 1.3.0.
+
+# Fusing Google Test Source Files #
+
+Google Test's implementation consists of ~30 files (excluding its own
+tests).  Sometimes you may want them to be packaged up in two files (a
+`.h` and a `.cc`) instead, such that you can easily copy them to a new
+machine and start hacking there.  For this we provide an experimental
+Python script `fuse_gtest_files.py` in the `scripts/` directory (since release 1.3.0).
+Assuming you have Python 2.4 or above installed on your machine, just
+go to that directory and run
+```
+python fuse_gtest_files.py OUTPUT_DIR
+```
+
+and you should see an `OUTPUT_DIR` directory being created with files
+`gtest/gtest.h` and `gtest/gtest-all.cc` in it.  These files contain
+everything you need to use Google Test.  Just copy them to anywhere
+you want and you are ready to write tests.  You can use the
+[scrpts/test/Makefile](http://code.google.com/p/googletest/source/browse/trunk/scripts/test/Makefile)
+file as an example on how to compile your tests against them.
+
+# Where to Go from Here #
+
+Congratulations! You've now learned more advanced Google Test tools and are
+ready to tackle more complex testing tasks. If you want to dive even deeper, you
+can read the [FAQ](V1_5_FAQ.md).
\ No newline at end of file
diff --git a/third_party/googletest/googletest/docs/V1_5_Documentation.md b/third_party/googletest/googletest/docs/V1_5_Documentation.md
new file mode 100644
index 0000000..46bba2e
--- /dev/null
+++ b/third_party/googletest/googletest/docs/V1_5_Documentation.md
@@ -0,0 +1,12 @@
+This page lists all official documentation wiki pages for Google Test **1.5.0** -- **if you use a different version of Google Test, make sure to read the documentation for that version instead.**
+
+  * [Primer](V1_5_Primer.md) -- start here if you are new to Google Test.
+  * [Samples](Samples.md) -- learn from examples.
+  * [AdvancedGuide](V1_5_AdvancedGuide.md) -- learn more about Google Test.
+  * [XcodeGuide](V1_5_XcodeGuide.md) -- how to use Google Test in Xcode on Mac.
+  * [Frequently-Asked Questions](V1_5_FAQ.md) -- check here before asking a question on the mailing list.
+
+To contribute code to Google Test, read:
+
+  * DevGuide -- read this _before_ writing your first patch.
+  * [PumpManual](V1_5_PumpManual.md) -- how we generate some of Google Test's source files.
\ No newline at end of file
diff --git a/third_party/googletest/googletest/docs/V1_5_FAQ.md b/third_party/googletest/googletest/docs/V1_5_FAQ.md
new file mode 100644
index 0000000..014dba2
--- /dev/null
+++ b/third_party/googletest/googletest/docs/V1_5_FAQ.md
@@ -0,0 +1,885 @@
+
+
+If you cannot find the answer to your question here, and you have read
+[Primer](V1_5_Primer.md) and [AdvancedGuide](V1_5_AdvancedGuide.md), send it to
+googletestframework@googlegroups.com.
+
+## Why should I use Google Test instead of my favorite C++ testing framework? ##
+
+First, let's say clearly that we don't want to get into the debate of
+which C++ testing framework is **the best**.  There exist many fine
+frameworks for writing C++ tests, and we have tremendous respect for
+the developers and users of them.  We don't think there is (or will
+be) a single best framework - you have to pick the right tool for the
+particular task you are tackling.
+
+We created Google Test because we couldn't find the right combination
+of features and conveniences in an existing framework to satisfy _our_
+needs.  The following is a list of things that _we_ like about Google
+Test.  We don't claim them to be unique to Google Test - rather, the
+combination of them makes Google Test the choice for us.  We hope this
+list can help you decide whether it is for you too.
+
+  * Google Test is designed to be portable.  It works where many STL types (e.g. `std::string` and `std::vector`) don't compile.  It doesn't require exceptions or RTTI.  As a result, it runs on Linux, Mac OS X, Windows and several embedded operating systems.
+  * Nonfatal assertions (`EXPECT_*`) have proven to be great time savers, as they allow a test to report multiple failures in a single edit-compile-test cycle.
+  * It's easy to write assertions that generate informative messages: you just use the stream syntax to append any additional information, e.g. `ASSERT_EQ(5, Foo(i)) << " where i = " << i;`.  It doesn't require a new set of macros or special functions.
+  * Google Test automatically detects your tests and doesn't require you to enumerate them in order to run them.
+  * No framework can anticipate all your needs, so Google Test provides `EXPECT_PRED*` to make it easy to extend your assertion vocabulary.  For a nicer syntax, you can define your own assertion macros trivially in terms of `EXPECT_PRED*`.
+  * Death tests are pretty handy for ensuring that your asserts in production code are triggered by the right conditions.
+  * `SCOPED_TRACE` helps you understand the context of an assertion failure when it comes from inside a sub-routine or loop.
+  * You can decide which tests to run using name patterns.  This saves time when you want to quickly reproduce a test failure.
+
+## How do I generate 64-bit binaries on Windows (using Visual Studio 2008)? ##
+
+(Answered by Trevor Robinson)
+
+Load the supplied Visual Studio solution file, either `msvc\gtest-md.sln` or
+`msvc\gtest.sln`. Go through the migration wizard to migrate the
+solution and project files to Visual Studio 2008. Select
+`Configuration Manager...` from the `Build` menu. Select `<New...>` from
+the `Active solution platform` dropdown.  Select `x64` from the new
+platform dropdown, leave `Copy settings from` set to `Win32` and
+`Create new project platforms` checked, then click `OK`. You now have
+`Win32` and `x64` platform configurations, selectable from the
+`Standard` toolbar, which allow you to toggle between building 32-bit or
+64-bit binaries (or both at once using Batch Build).
+
+In order to prevent build output files from overwriting one another,
+you'll need to change the `Intermediate Directory` settings for the
+newly created platform configuration across all the projects. To do
+this, multi-select (e.g. using shift-click) all projects (but not the
+solution) in the `Solution Explorer`. Right-click one of them and
+select `Properties`. In the left pane, select `Configuration Properties`,
+and from the `Configuration` dropdown, select `All Configurations`.
+Make sure the selected platform is `x64`. For the
+`Intermediate Directory` setting, change the value from
+`$(PlatformName)\$(ConfigurationName)` to
+`$(OutDir)\$(ProjectName)`. Click `OK` and then build the
+solution. When the build is complete, the 64-bit binaries will be in
+the `msvc\x64\Debug` directory.
+
+## Can I use Google Test on MinGW? ##
+
+We haven't tested this ourselves, but Per Abrahamsen reported that he
+was able to compile and install Google Test successfully when using
+MinGW from Cygwin.  You'll need to configure it with:
+
+`PATH/TO/configure CC="gcc -mno-cygwin" CXX="g++ -mno-cygwin"`
+
+You should be able to replace the `-mno-cygwin` option with direct links
+to the real MinGW binaries, but we haven't tried that.
+
+Caveats:
+
+  * There are many warnings when compiling.
+  * `make check` will produce some errors as not all tests for Google Test itself are compatible with MinGW.
+
+We also have reports on successful cross compilation of Google Test MinGW binaries on Linux using [these instructions](http://wiki.wxwidgets.org/Cross-Compiling_Under_Linux#Cross-compiling_under_Linux_for_MS_Windows) on the WxWidgets site.
+
+Please contact `googletestframework@googlegroups.com` if you are
+interested in improving the support for MinGW.
+
+## Why does Google Test support EXPECT\_EQ(NULL, ptr) and ASSERT\_EQ(NULL, ptr) but not EXPECT\_NE(NULL, ptr) and ASSERT\_NE(NULL, ptr)? ##
+
+Due to some peculiarity of C++, it requires some non-trivial template
+meta programming tricks to support using `NULL` as an argument of the
+`EXPECT_XX()` and `ASSERT_XX()` macros. Therefore we only do it where
+it's most needed (otherwise we make the implementation of Google Test
+harder to maintain and more error-prone than necessary).
+
+The `EXPECT_EQ()` macro takes the _expected_ value as its first
+argument and the _actual_ value as the second. It's reasonable that
+someone wants to write `EXPECT_EQ(NULL, some_expression)`, and this
+indeed was requested several times. Therefore we implemented it.
+
+The need for `EXPECT_NE(NULL, ptr)` isn't nearly as strong. When the
+assertion fails, you already know that `ptr` must be `NULL`, so it
+doesn't add any information to print ptr in this case. That means
+`EXPECT_TRUE(ptr ! NULL)` works just as well.
+
+If we were to support `EXPECT_NE(NULL, ptr)`, for consistency we'll
+have to support `EXPECT_NE(ptr, NULL)` as well, as unlike `EXPECT_EQ`,
+we don't have a convention on the order of the two arguments for
+`EXPECT_NE`. This means using the template meta programming tricks
+twice in the implementation, making it even harder to understand and
+maintain. We believe the benefit doesn't justify the cost.
+
+Finally, with the growth of Google Mock's [matcher](http://code.google.com/p/googlemock/wiki/CookBook#Using_Matchers_in_Google_Test_Assertions) library, we are
+encouraging people to use the unified `EXPECT_THAT(value, matcher)`
+syntax more often in tests. One significant advantage of the matcher
+approach is that matchers can be easily combined to form new matchers,
+while the `EXPECT_NE`, etc, macros cannot be easily
+combined. Therefore we want to invest more in the matchers than in the
+`EXPECT_XX()` macros.
+
+## Does Google Test support running tests in parallel? ##
+
+Test runners tend to be tightly coupled with the build/test
+environment, and Google Test doesn't try to solve the problem of
+running tests in parallel.  Instead, we tried to make Google Test work
+nicely with test runners.  For example, Google Test's XML report
+contains the time spent on each test, and its `gtest_list_tests` and
+`gtest_filter` flags can be used for splitting the execution of test
+methods into multiple processes.  These functionalities can help the
+test runner run the tests in parallel.
+
+## Why don't Google Test run the tests in different threads to speed things up? ##
+
+It's difficult to write thread-safe code.  Most tests are not written
+with thread-safety in mind, and thus may not work correctly in a
+multi-threaded setting.
+
+If you think about it, it's already hard to make your code work when
+you know what other threads are doing.  It's much harder, and
+sometimes even impossible, to make your code work when you don't know
+what other threads are doing (remember that test methods can be added,
+deleted, or modified after your test was written).  If you want to run
+the tests in parallel, you'd better run them in different processes.
+
+## Why aren't Google Test assertions implemented using exceptions? ##
+
+Our original motivation was to be able to use Google Test in projects
+that disable exceptions.  Later we realized some additional benefits
+of this approach:
+
+  1. Throwing in a destructor is undefined behavior in C++.  Not using exceptions means Google Test's assertions are safe to use in destructors.
+  1. The `EXPECT_*` family of macros will continue even after a failure, allowing multiple failures in a `TEST` to be reported in a single run. This is a popular feature, as in C++ the edit-compile-test cycle is usually quite long and being able to fixing more than one thing at a time is a blessing.
+  1. If assertions are implemented using exceptions, a test may falsely ignore a failure if it's caught by user code:
+```
+try { ... ASSERT_TRUE(...) ... }
+catch (...) { ... }
+```
+The above code will pass even if the `ASSERT_TRUE` throws.  While it's unlikely for someone to write this in a test, it's possible to run into this pattern when you write assertions in callbacks that are called by the code under test.
+
+The downside of not using exceptions is that `ASSERT_*` (implemented
+using `return`) will only abort the current function, not the current
+`TEST`.
+
+## Why do we use two different macros for tests with and without fixtures? ##
+
+Unfortunately, C++'s macro system doesn't allow us to use the same
+macro for both cases.  One possibility is to provide only one macro
+for tests with fixtures, and require the user to define an empty
+fixture sometimes:
+
+```
+class FooTest : public ::testing::Test {};
+
+TEST_F(FooTest, DoesThis) { ... }
+```
+or
+```
+typedef ::testing::Test FooTest;
+
+TEST_F(FooTest, DoesThat) { ... }
+```
+
+Yet, many people think this is one line too many. :-) Our goal was to
+make it really easy to write tests, so we tried to make simple tests
+trivial to create.  That means using a separate macro for such tests.
+
+We think neither approach is ideal, yet either of them is reasonable.
+In the end, it probably doesn't matter much either way.
+
+## Why don't we use structs as test fixtures? ##
+
+We like to use structs only when representing passive data.  This
+distinction between structs and classes is good for documenting the
+intent of the code's author.  Since test fixtures have logic like
+`SetUp()` and `TearDown()`, they are better defined as classes.
+
+## Why are death tests implemented as assertions instead of using a test runner? ##
+
+Our goal was to make death tests as convenient for a user as C++
+possibly allows.  In particular:
+
+  * The runner-style requires to split the information into two pieces: the definition of the death test itself, and the specification for the runner on how to run the death test and what to expect.  The death test would be written in C++, while the runner spec may or may not be.  A user needs to carefully keep the two in sync. `ASSERT_DEATH(statement, expected_message)` specifies all necessary information in one place, in one language, without boilerplate code. It is very declarative.
+  * `ASSERT_DEATH` has a similar syntax and error-reporting semantics as other Google Test assertions, and thus is easy to learn.
+  * `ASSERT_DEATH` can be mixed with other assertions and other logic at your will.  You are not limited to one death test per test method. For example, you can write something like:
+```
+    if (FooCondition()) {
+      ASSERT_DEATH(Bar(), "blah");
+    } else {
+      ASSERT_EQ(5, Bar());
+    }
+```
+If you prefer one death test per test method, you can write your tests in that style too, but we don't want to impose that on the users.  The fewer artificial limitations the better.
+  * `ASSERT_DEATH` can reference local variables in the current function, and you can decide how many death tests you want based on run-time information.  For example,
+```
+    const int count = GetCount();  // Only known at run time.
+    for (int i = 1; i <= count; i++) {
+      ASSERT_DEATH({
+        double* buffer = new double[i];
+        ... initializes buffer ...
+        Foo(buffer, i)
+      }, "blah blah");
+    }
+```
+The runner-based approach tends to be more static and less flexible, or requires more user effort to get this kind of flexibility.
+
+Another interesting thing about `ASSERT_DEATH` is that it calls `fork()`
+to create a child process to run the death test.  This is lightening
+fast, as `fork()` uses copy-on-write pages and incurs almost zero
+overhead, and the child process starts from the user-supplied
+statement directly, skipping all global and local initialization and
+any code leading to the given statement.  If you launch the child
+process from scratch, it can take seconds just to load everything and
+start running if the test links to many libraries dynamically.
+
+## My death test modifies some state, but the change seems lost after the death test finishes. Why? ##
+
+Death tests (`EXPECT_DEATH`, etc) are executed in a sub-process s.t. the
+expected crash won't kill the test program (i.e. the parent process). As a
+result, any in-memory side effects they incur are observable in their
+respective sub-processes, but not in the parent process. You can think of them
+as running in a parallel universe, more or less.
+
+## The compiler complains about "undefined references" to some static const member variables, but I did define them in the class body. What's wrong? ##
+
+If your class has a static data member:
+
+```
+// foo.h
+class Foo {
+  ...
+  static const int kBar = 100;
+};
+```
+
+You also need to define it _outside_ of the class body in `foo.cc`:
+
+```
+const int Foo::kBar;  // No initializer here.
+```
+
+Otherwise your code is **invalid C++**, and may break in unexpected ways. In
+particular, using it in Google Test comparison assertions (`EXPECT_EQ`, etc)
+will generate an "undefined reference" linker error.
+
+## I have an interface that has several implementations. Can I write a set of tests once and repeat them over all the implementations? ##
+
+Google Test doesn't yet have good support for this kind of tests, or
+data-driven tests in general. We hope to be able to make improvements in this
+area soon.
+
+## Can I derive a test fixture from another? ##
+
+Yes.
+
+Each test fixture has a corresponding and same named test case. This means only
+one test case can use a particular fixture. Sometimes, however, multiple test
+cases may want to use the same or slightly different fixtures. For example, you
+may want to make sure that all of a GUI library's test cases don't leak
+important system resources like fonts and brushes.
+
+In Google Test, you share a fixture among test cases by putting the shared
+logic in a base test fixture, then deriving from that base a separate fixture
+for each test case that wants to use this common logic. You then use `TEST_F()`
+to write tests using each derived fixture.
+
+Typically, your code looks like this:
+
+```
+// Defines a base test fixture.
+class BaseTest : public ::testing::Test {
+  protected:
+   ...
+};
+
+// Derives a fixture FooTest from BaseTest.
+class FooTest : public BaseTest {
+  protected:
+    virtual void SetUp() {
+      BaseTest::SetUp();  // Sets up the base fixture first.
+      ... additional set-up work ...
+    }
+    virtual void TearDown() {
+      ... clean-up work for FooTest ...
+      BaseTest::TearDown();  // Remember to tear down the base fixture
+                             // after cleaning up FooTest!
+    }
+    ... functions and variables for FooTest ...
+};
+
+// Tests that use the fixture FooTest.
+TEST_F(FooTest, Bar) { ... }
+TEST_F(FooTest, Baz) { ... }
+
+... additional fixtures derived from BaseTest ...
+```
+
+If necessary, you can continue to derive test fixtures from a derived fixture.
+Google Test has no limit on how deep the hierarchy can be.
+
+For a complete example using derived test fixtures, see
+`samples/sample5_unittest.cc`.
+
+## My compiler complains "void value not ignored as it ought to be." What does this mean? ##
+
+You're probably using an `ASSERT_*()` in a function that doesn't return `void`.
+`ASSERT_*()` can only be used in `void` functions.
+
+## My death test hangs (or seg-faults). How do I fix it? ##
+
+In Google Test, death tests are run in a child process and the way they work is
+delicate. To write death tests you really need to understand how they work.
+Please make sure you have read this.
+
+In particular, death tests don't like having multiple threads in the parent
+process. So the first thing you can try is to eliminate creating threads
+outside of `EXPECT_DEATH()`.
+
+Sometimes this is impossible as some library you must use may be creating
+threads before `main()` is even reached. In this case, you can try to minimize
+the chance of conflicts by either moving as many activities as possible inside
+`EXPECT_DEATH()` (in the extreme case, you want to move everything inside), or
+leaving as few things as possible in it. Also, you can try to set the death
+test style to `"threadsafe"`, which is safer but slower, and see if it helps.
+
+If you go with thread-safe death tests, remember that they rerun the test
+program from the beginning in the child process. Therefore make sure your
+program can run side-by-side with itself and is deterministic.
+
+In the end, this boils down to good concurrent programming. You have to make
+sure that there is no race conditions or dead locks in your program. No silver
+bullet - sorry!
+
+## Should I use the constructor/destructor of the test fixture or the set-up/tear-down function? ##
+
+The first thing to remember is that Google Test does not reuse the
+same test fixture object across multiple tests. For each `TEST_F`,
+Google Test will create a fresh test fixture object, _immediately_
+call `SetUp()`, run the test, call `TearDown()`, and then
+_immediately_ delete the test fixture object. Therefore, there is no
+need to write a `SetUp()` or `TearDown()` function if the constructor
+or destructor already does the job.
+
+You may still want to use `SetUp()/TearDown()` in the following cases:
+  * If the tear-down operation could throw an exception, you must use `TearDown()` as opposed to the destructor, as throwing in a destructor leads to undefined behavior and usually will kill your program right away. Note that many standard libraries (like STL) may throw when exceptions are enabled in the compiler. Therefore you should prefer `TearDown()` if you want to write portable tests that work with or without exceptions.
+  * The Google Test team is considering making the assertion macros throw on platforms where exceptions are enabled (e.g. Windows, Mac OS, and Linux client-side), which will eliminate the need for the user to propagate failures from a subroutine to its caller. Therefore, you shouldn't use Google Test assertions in a destructor if your code could run on such a platform.
+  * In a constructor or destructor, you cannot make a virtual function call on this object. (You can call a method declared as virtual, but it will be statically bound.) Therefore, if you need to call a method that will be overriden in a derived class, you have to use `SetUp()/TearDown()`.
+
+## The compiler complains "no matching function to call" when I use ASSERT\_PREDn. How do I fix it? ##
+
+If the predicate function you use in `ASSERT_PRED*` or `EXPECT_PRED*` is
+overloaded or a template, the compiler will have trouble figuring out which
+overloaded version it should use. `ASSERT_PRED_FORMAT*` and
+`EXPECT_PRED_FORMAT*` don't have this problem.
+
+If you see this error, you might want to switch to
+`(ASSERT|EXPECT)_PRED_FORMAT*`, which will also give you a better failure
+message. If, however, that is not an option, you can resolve the problem by
+explicitly telling the compiler which version to pick.
+
+For example, suppose you have
+
+```
+bool IsPositive(int n) {
+  return n > 0;
+}
+bool IsPositive(double x) {
+  return x > 0;
+}
+```
+
+you will get a compiler error if you write
+
+```
+EXPECT_PRED1(IsPositive, 5);
+```
+
+However, this will work:
+
+```
+EXPECT_PRED1(*static_cast<bool (*)(int)>*(IsPositive), 5);
+```
+
+(The stuff inside the angled brackets for the `static_cast` operator is the
+type of the function pointer for the `int`-version of `IsPositive()`.)
+
+As another example, when you have a template function
+
+```
+template <typename T>
+bool IsNegative(T x) {
+  return x < 0;
+}
+```
+
+you can use it in a predicate assertion like this:
+
+```
+ASSERT_PRED1(IsNegative*<int>*, -5);
+```
+
+Things are more interesting if your template has more than one parameters. The
+following won't compile:
+
+```
+ASSERT_PRED2(*GreaterThan<int, int>*, 5, 0);
+```
+
+
+as the C++ pre-processor thinks you are giving `ASSERT_PRED2` 4 arguments,
+which is one more than expected. The workaround is to wrap the predicate
+function in parentheses:
+
+```
+ASSERT_PRED2(*(GreaterThan<int, int>)*, 5, 0);
+```
+
+
+## My compiler complains about "ignoring return value" when I call RUN\_ALL\_TESTS(). Why? ##
+
+Some people had been ignoring the return value of `RUN_ALL_TESTS()`. That is,
+instead of
+
+```
+return RUN_ALL_TESTS();
+```
+
+they write
+
+```
+RUN_ALL_TESTS();
+```
+
+This is wrong and dangerous. A test runner needs to see the return value of
+`RUN_ALL_TESTS()` in order to determine if a test has passed. If your `main()`
+function ignores it, your test will be considered successful even if it has a
+Google Test assertion failure. Very bad.
+
+To help the users avoid this dangerous bug, the implementation of
+`RUN_ALL_TESTS()` causes gcc to raise this warning, when the return value is
+ignored. If you see this warning, the fix is simple: just make sure its value
+is used as the return value of `main()`.
+
+## My compiler complains that a constructor (or destructor) cannot return a value. What's going on? ##
+
+Due to a peculiarity of C++, in order to support the syntax for streaming
+messages to an `ASSERT_*`, e.g.
+
+```
+ASSERT_EQ(1, Foo()) << "blah blah" << foo;
+```
+
+we had to give up using `ASSERT*` and `FAIL*` (but not `EXPECT*` and
+`ADD_FAILURE*`) in constructors and destructors. The workaround is to move the
+content of your constructor/destructor to a private void member function, or
+switch to `EXPECT_*()` if that works. This section in the user's guide explains
+it.
+
+## My set-up function is not called. Why? ##
+
+C++ is case-sensitive. It should be spelled as `SetUp()`.  Did you
+spell it as `Setup()`?
+
+Similarly, sometimes people spell `SetUpTestCase()` as `SetupTestCase()` and
+wonder why it's never called.
+
+## How do I jump to the line of a failure in Emacs directly? ##
+
+Google Test's failure message format is understood by Emacs and many other
+IDEs, like acme and XCode. If a Google Test message is in a compilation buffer
+in Emacs, then it's clickable. You can now hit `enter` on a message to jump to
+the corresponding source code, or use `C-x `` to jump to the next failure.
+
+## I have several test cases which share the same test fixture logic, do I have to define a new test fixture class for each of them? This seems pretty tedious. ##
+
+You don't have to. Instead of
+
+```
+class FooTest : public BaseTest {};
+
+TEST_F(FooTest, Abc) { ... }
+TEST_F(FooTest, Def) { ... }
+
+class BarTest : public BaseTest {};
+
+TEST_F(BarTest, Abc) { ... }
+TEST_F(BarTest, Def) { ... }
+```
+
+you can simply `typedef` the test fixtures:
+```
+typedef BaseTest FooTest;
+
+TEST_F(FooTest, Abc) { ... }
+TEST_F(FooTest, Def) { ... }
+
+typedef BaseTest BarTest;
+
+TEST_F(BarTest, Abc) { ... }
+TEST_F(BarTest, Def) { ... }
+```
+
+## The Google Test output is buried in a whole bunch of log messages. What do I do? ##
+
+The Google Test output is meant to be a concise and human-friendly report. If
+your test generates textual output itself, it will mix with the Google Test
+output, making it hard to read. However, there is an easy solution to this
+problem.
+
+Since most log messages go to stderr, we decided to let Google Test output go
+to stdout. This way, you can easily separate the two using redirection. For
+example:
+```
+./my_test > googletest_output.txt
+```
+
+## Why should I prefer test fixtures over global variables? ##
+
+There are several good reasons:
+  1. It's likely your test needs to change the states of its global variables. This makes it difficult to keep side effects from escaping one test and contaminating others, making debugging difficult. By using fixtures, each test has a fresh set of variables that's different (but with the same names). Thus, tests are kept independent of each other.
+  1. Global variables pollute the global namespace.
+  1. Test fixtures can be reused via subclassing, which cannot be done easily with global variables. This is useful if many test cases have something in common.
+
+## How do I test private class members without writing FRIEND\_TEST()s? ##
+
+You should try to write testable code, which means classes should be easily
+tested from their public interface. One way to achieve this is the Pimpl idiom:
+you move all private members of a class into a helper class, and make all
+members of the helper class public.
+
+You have several other options that don't require using `FRIEND_TEST`:
+  * Write the tests as members of the fixture class:
+```
+class Foo {
+  friend class FooTest;
+  ...
+};
+
+class FooTest : public ::testing::Test {
+ protected:
+  ...
+  void Test1() {...} // This accesses private members of class Foo.
+  void Test2() {...} // So does this one.
+};
+
+TEST_F(FooTest, Test1) {
+  Test1();
+}
+
+TEST_F(FooTest, Test2) {
+  Test2();
+}
+```
+  * In the fixture class, write accessors for the tested class' private members, then use the accessors in your tests:
+```
+class Foo {
+  friend class FooTest;
+  ...
+};
+
+class FooTest : public ::testing::Test {
+ protected:
+  ...
+  T1 get_private_member1(Foo* obj) {
+    return obj->private_member1_;
+  }
+};
+
+TEST_F(FooTest, Test1) {
+  ...
+  get_private_member1(x)
+  ...
+}
+```
+  * If the methods are declared **protected**, you can change their access level in a test-only subclass:
+```
+class YourClass {
+  ...
+ protected: // protected access for testability.
+  int DoSomethingReturningInt();
+  ...
+};
+
+// in the your_class_test.cc file:
+class TestableYourClass : public YourClass {
+  ...
+ public: using YourClass::DoSomethingReturningInt; // changes access rights
+  ...
+};
+
+TEST_F(YourClassTest, DoSomethingTest) {
+  TestableYourClass obj;
+  assertEquals(expected_value, obj.DoSomethingReturningInt());
+}
+```
+
+## How do I test private class static members without writing FRIEND\_TEST()s? ##
+
+We find private static methods clutter the header file.  They are
+implementation details and ideally should be kept out of a .h. So often I make
+them free functions instead.
+
+Instead of:
+```
+// foo.h
+class Foo {
+  ...
+ private:
+  static bool Func(int n);
+};
+
+// foo.cc
+bool Foo::Func(int n) { ... }
+
+// foo_test.cc
+EXPECT_TRUE(Foo::Func(12345));
+```
+
+You probably should better write:
+```
+// foo.h
+class Foo {
+  ...
+};
+
+// foo.cc
+namespace internal {
+  bool Func(int n) { ... }
+}
+
+// foo_test.cc
+namespace internal {
+  bool Func(int n);
+}
+
+EXPECT_TRUE(internal::Func(12345));
+```
+
+## I would like to run a test several times with different parameters. Do I need to write several similar copies of it? ##
+
+No. You can use a feature called [value-parameterized tests](V1_5_AdvancedGuide#Value_Parameterized_Tests.md) which
+lets you repeat your tests with different parameters, without defining it more than once.
+
+## How do I test a file that defines main()? ##
+
+To test a `foo.cc` file, you need to compile and link it into your unit test
+program. However, when the file contains a definition for the `main()`
+function, it will clash with the `main()` of your unit test, and will result in
+a build error.
+
+The right solution is to split it into three files:
+  1. `foo.h` which contains the declarations,
+  1. `foo.cc` which contains the definitions except `main()`, and
+  1. `foo_main.cc` which contains nothing but the definition of `main()`.
+
+Then `foo.cc` can be easily tested.
+
+If you are adding tests to an existing file and don't want an intrusive change
+like this, there is a hack: just include the entire `foo.cc` file in your unit
+test. For example:
+```
+// File foo_unittest.cc
+
+// The headers section
+...
+
+// Renames main() in foo.cc to make room for the unit test main()
+#define main FooMain
+
+#include "a/b/foo.cc"
+
+// The tests start here.
+...
+```
+
+
+However, please remember this is a hack and should only be used as the last
+resort.
+
+## What can the statement argument in ASSERT\_DEATH() be? ##
+
+`ASSERT_DEATH(_statement_, _regex_)` (or any death assertion macro) can be used
+wherever `_statement_` is valid. So basically `_statement_` can be any C++
+statement that makes sense in the current context. In particular, it can
+reference global and/or local variables, and can be:
+  * a simple function call (often the case),
+  * a complex expression, or
+  * a compound statement.
+
+> Some examples are shown here:
+```
+// A death test can be a simple function call.
+TEST(MyDeathTest, FunctionCall) {
+  ASSERT_DEATH(Xyz(5), "Xyz failed");
+}
+
+// Or a complex expression that references variables and functions.
+TEST(MyDeathTest, ComplexExpression) {
+  const bool c = Condition();
+  ASSERT_DEATH((c ? Func1(0) : object2.Method("test")),
+               "(Func1|Method) failed");
+}
+
+// Death assertions can be used any where in a function. In
+// particular, they can be inside a loop.
+TEST(MyDeathTest, InsideLoop) {
+  // Verifies that Foo(0), Foo(1), ..., and Foo(4) all die.
+  for (int i = 0; i < 5; i++) {
+    EXPECT_DEATH_M(Foo(i), "Foo has \\d+ errors",
+                   ::testing::Message() << "where i is " << i);
+  }
+}
+
+// A death assertion can contain a compound statement.
+TEST(MyDeathTest, CompoundStatement) {
+  // Verifies that at lease one of Bar(0), Bar(1), ..., and
+  // Bar(4) dies.
+  ASSERT_DEATH({
+    for (int i = 0; i < 5; i++) {
+      Bar(i);
+    }
+  },
+  "Bar has \\d+ errors");}
+```
+
+`googletest_unittest.cc` contains more examples if you are interested.
+
+## What syntax does the regular expression in ASSERT\_DEATH use? ##
+
+On POSIX systems, Google Test uses the POSIX Extended regular
+expression syntax
+(http://en.wikipedia.org/wiki/Regular_expression#POSIX_Extended_Regular_Expressions). On
+Windows, it uses a limited variant of regular expression syntax. For
+more details, see the [regular expression syntax](V1_5_AdvancedGuide#Regular_Expression_Syntax.md).
+
+## I have a fixture class Foo, but TEST\_F(Foo, Bar) gives me error "no matching function for call to Foo::Foo()". Why? ##
+
+Google Test needs to be able to create objects of your test fixture class, so
+it must have a default constructor. Normally the compiler will define one for
+you. However, there are cases where you have to define your own:
+  * If you explicitly declare a non-default constructor for class `Foo`, then you need to define a default constructor, even if it would be empty.
+  * If `Foo` has a const non-static data member, then you have to define the default constructor _and_ initialize the const member in the initializer list of the constructor. (Early versions of `gcc` doesn't force you to initialize the const member. It's a bug that has been fixed in `gcc 4`.)
+
+## Why does ASSERT\_DEATH complain about previous threads that were already joined? ##
+
+With the Linux pthread library, there is no turning back once you cross the
+line from single thread to multiple threads. The first time you create a
+thread, a manager thread is created in addition, so you get 3, not 2, threads.
+Later when the thread you create joins the main thread, the thread count
+decrements by 1, but the manager thread will never be killed, so you still have
+2 threads, which means you cannot safely run a death test.
+
+The new NPTL thread library doesn't suffer from this problem, as it doesn't
+create a manager thread. However, if you don't control which machine your test
+runs on, you shouldn't depend on this.
+
+## Why does Google Test require the entire test case, instead of individual tests, to be named FOODeathTest when it uses ASSERT\_DEATH? ##
+
+Google Test does not interleave tests from different test cases. That is, it
+runs all tests in one test case first, and then runs all tests in the next test
+case, and so on. Google Test does this because it needs to set up a test case
+before the first test in it is run, and tear it down afterwords. Splitting up
+the test case would require multiple set-up and tear-down processes, which is
+inefficient and makes the semantics unclean.
+
+If we were to determine the order of tests based on test name instead of test
+case name, then we would have a problem with the following situation:
+
+```
+TEST_F(FooTest, AbcDeathTest) { ... }
+TEST_F(FooTest, Uvw) { ... }
+
+TEST_F(BarTest, DefDeathTest) { ... }
+TEST_F(BarTest, Xyz) { ... }
+```
+
+Since `FooTest.AbcDeathTest` needs to run before `BarTest.Xyz`, and we don't
+interleave tests from different test cases, we need to run all tests in the
+`FooTest` case before running any test in the `BarTest` case. This contradicts
+with the requirement to run `BarTest.DefDeathTest` before `FooTest.Uvw`.
+
+## But I don't like calling my entire test case FOODeathTest when it contains both death tests and non-death tests. What do I do? ##
+
+You don't have to, but if you like, you may split up the test case into
+`FooTest` and `FooDeathTest`, where the names make it clear that they are
+related:
+
+```
+class FooTest : public ::testing::Test { ... };
+
+TEST_F(FooTest, Abc) { ... }
+TEST_F(FooTest, Def) { ... }
+
+typedef FooTest FooDeathTest;
+
+TEST_F(FooDeathTest, Uvw) { ... EXPECT_DEATH(...) ... }
+TEST_F(FooDeathTest, Xyz) { ... ASSERT_DEATH(...) ... }
+```
+
+## The compiler complains about "no match for 'operator<<'" when I use an assertion. What gives? ##
+
+If you use a user-defined type `FooType` in an assertion, you must make sure
+there is an `std::ostream& operator<<(std::ostream&, const FooType&)` function
+defined such that we can print a value of `FooType`.
+
+In addition, if `FooType` is declared in a name space, the `<<` operator also
+needs to be defined in the _same_ name space.
+
+## How do I suppress the memory leak messages on Windows? ##
+
+Since the statically initialized Google Test singleton requires allocations on
+the heap, the Visual C++ memory leak detector will report memory leaks at the
+end of the program run. The easiest way to avoid this is to use the
+`_CrtMemCheckpoint` and `_CrtMemDumpAllObjectsSince` calls to not report any
+statically initialized heap objects. See MSDN for more details and additional
+heap check/debug routines.
+
+## I am building my project with Google Test in Visual Studio and all I'm getting is a bunch of linker errors (or warnings). Help! ##
+
+You may get a number of the following linker error or warnings if you
+attempt to link your test project with the Google Test library when
+your project and the are not built using the same compiler settings.
+
+  * LNK2005: symbol already defined in object
+  * LNK4217: locally defined symbol 'symbol' imported in function 'function'
+  * LNK4049: locally defined symbol 'symbol' imported
+
+The Google Test project (gtest.vcproj) has the Runtime Library option
+set to /MT (use multi-threaded static libraries, /MTd for debug). If
+your project uses something else, for example /MD (use multi-threaded
+DLLs, /MDd for debug), you need to change the setting in the Google
+Test project to match your project's.
+
+To update this setting open the project properties in the Visual
+Studio IDE then select the branch Configuration Properties | C/C++ |
+Code Generation and change the option "Runtime Library".  You may also try
+using gtest-md.vcproj instead of gtest.vcproj.
+
+## I put my tests in a library and Google Test doesn't run them. What's happening? ##
+Have you read a
+[warning](V1_5_Primer#Important_note_for_Visual_C++_users.md) on
+the Google Test Primer page?
+
+## I want to use Google Test with Visual Studio but don't know where to start. ##
+Many people are in your position and one of the posted his solution to
+our mailing list. Here is his link:
+http://hassanjamilahmad.blogspot.com/2009/07/gtest-starters-help.html.
+
+## My question is not covered in your FAQ! ##
+
+If you cannot find the answer to your question in this FAQ, there are
+some other resources you can use:
+
+  1. read other [wiki pages](http://code.google.com/p/googletest/w/list),
+  1. search the mailing list [archive](http://groups.google.com/group/googletestframework/topics),
+  1. ask it on [googletestframework@googlegroups.com](mailto:googletestframework@googlegroups.com) and someone will answer it (to prevent spam, we require you to join the [discussion group](http://groups.google.com/group/googletestframework) before you can post.).
+
+Please note that creating an issue in the
+[issue tracker](http://code.google.com/p/googletest/issues/list) is _not_
+a good way to get your answer, as it is monitored infrequently by a
+very small number of people.
+
+When asking a question, it's helpful to provide as much of the
+following information as possible (people cannot help you if there's
+not enough information in your question):
+
+  * the version (or the revision number if you check out from SVN directly) of Google Test you use (Google Test is under active development, so it's possible that your problem has been solved in a later version),
+  * your operating system,
+  * the name and version of your compiler,
+  * the complete command line flags you give to your compiler,
+  * the complete compiler error messages (if the question is about compilation),
+  * the _actual_ code (ideally, a minimal but complete program) that has the problem you encounter.
\ No newline at end of file
diff --git a/third_party/googletest/googletest/docs/V1_5_Primer.md b/third_party/googletest/googletest/docs/V1_5_Primer.md
new file mode 100644
index 0000000..5c42e0b
--- /dev/null
+++ b/third_party/googletest/googletest/docs/V1_5_Primer.md
@@ -0,0 +1,497 @@
+
+
+# Introduction: Why Google C++ Testing Framework? #
+
+_Google C++ Testing Framework_ helps you write better C++ tests.
+
+No matter whether you work on Linux, Windows, or a Mac, if you write C++ code,
+Google Test can help you.
+
+So what makes a good test, and how does Google C++ Testing Framework fit in? We believe:
+  1. Tests should be _independent_ and _repeatable_. It's a pain to debug a test that succeeds or fails as a result of other tests.  Google C++ Testing Framework isolates the tests by running each of them on a different object. When a test fails, Google C++ Testing Framework allows you to run it in isolation for quick debugging.
+  1. Tests should be well _organized_ and reflect the structure of the tested code.  Google C++ Testing Framework groups related tests into test cases that can share data and subroutines. This common pattern is easy to recognize and makes tests easy to maintain. Such consistency is especially helpful when people switch projects and start to work on a new code base.
+  1. Tests should be _portable_ and _reusable_. The open-source community has a lot of code that is platform-neutral, its tests should also be platform-neutral.  Google C++ Testing Framework works on different OSes, with different compilers (gcc, MSVC, and others), with or without exceptions, so Google C++ Testing Framework tests can easily work with a variety of configurations.  (Note that the current release only contains build scripts for Linux - we are actively working on scripts for other platforms.)
+  1. When tests fail, they should provide as much _information_ about the problem as possible. Google C++ Testing Framework doesn't stop at the first test failure. Instead, it only stops the current test and continues with the next. You can also set up tests that report non-fatal failures after which the current test continues. Thus, you can detect and fix multiple bugs in a single run-edit-compile cycle.
+  1. The testing framework should liberate test writers from housekeeping chores and let them focus on the test _content_.  Google C++ Testing Framework automatically keeps track of all tests defined, and doesn't require the user to enumerate them in order to run them.
+  1. Tests should be _fast_. With Google C++ Testing Framework, you can reuse shared resources across tests and pay for the set-up/tear-down only once, without making tests depend on each other.
+
+Since Google C++ Testing Framework is based on the popular xUnit
+architecture, you'll feel right at home if you've used JUnit or PyUnit before.
+If not, it will take you about 10 minutes to learn the basics and get started.
+So let's go!
+
+_Note:_ We sometimes refer to Google C++ Testing Framework informally
+as _Google Test_.
+
+# Setting up a New Test Project #
+
+To write a test program using Google Test, you need to compile Google
+Test into a library and link your test with it.  We provide build
+files for some popular build systems (`msvc/` for Visual Studio,
+`xcode/` for Mac Xcode, `make/` for GNU make, `codegear/` for Borland
+C++ Builder, and the autotools script in the
+Google Test root directory).  If your build system is not on this
+list, you can take a look at `make/Makefile` to learn how Google Test
+should be compiled (basically you want to compile `src/gtest-all.cc`
+with `GTEST_ROOT` and `GTEST_ROOT/include` in the header search path,
+where `GTEST_ROOT` is the Google Test root directory).
+
+Once you are able to compile the Google Test library, you should
+create a project or build target for your test program.  Make sure you
+have `GTEST_ROOT/include` in the header search path so that the
+compiler can find `<gtest/gtest.h>` when compiling your test.  Set up
+your test project to link with the Google Test library (for example,
+in Visual Studio, this is done by adding a dependency on
+`gtest.vcproj`).
+
+If you still have questions, take a look at how Google Test's own
+tests are built and use them as examples.
+
+# Basic Concepts #
+
+When using Google Test, you start by writing _assertions_, which are statements
+that check whether a condition is true. An assertion's result can be _success_,
+_nonfatal failure_, or _fatal failure_. If a fatal failure occurs, it aborts
+the current function; otherwise the program continues normally.
+
+_Tests_ use assertions to verify the tested code's behavior. If a test crashes
+or has a failed assertion, then it _fails_; otherwise it _succeeds_.
+
+A _test case_ contains one or many tests. You should group your tests into test
+cases that reflect the structure of the tested code. When multiple tests in a
+test case need to share common objects and subroutines, you can put them into a
+_test fixture_ class.
+
+A _test program_ can contain multiple test cases.
+
+We'll now explain how to write a test program, starting at the individual
+assertion level and building up to tests and test cases.
+
+# Assertions #
+
+Google Test assertions are macros that resemble function calls. You test a
+class or function by making assertions about its behavior. When an assertion
+fails, Google Test prints the assertion's source file and line number location,
+along with a failure message. You may also supply a custom failure message
+which will be appended to Google Test's message.
+
+The assertions come in pairs that test the same thing but have different
+effects on the current function. `ASSERT_*` versions generate fatal failures
+when they fail, and **abort the current function**. `EXPECT_*` versions generate
+nonfatal failures, which don't abort the current function. Usually `EXPECT_*`
+are preferred, as they allow more than one failures to be reported in a test.
+However, you should use `ASSERT_*` if it doesn't make sense to continue when
+the assertion in question fails.
+
+Since a failed `ASSERT_*` returns from the current function immediately,
+possibly skipping clean-up code that comes after it, it may cause a space leak.
+Depending on the nature of the leak, it may or may not be worth fixing - so
+keep this in mind if you get a heap checker error in addition to assertion
+errors.
+
+To provide a custom failure message, simply stream it into the macro using the
+`<<` operator, or a sequence of such operators. An example:
+```
+ASSERT_EQ(x.size(), y.size()) << "Vectors x and y are of unequal length";
+
+for (int i = 0; i < x.size(); ++i) {
+  EXPECT_EQ(x[i], y[i]) << "Vectors x and y differ at index " << i;
+}
+```
+
+Anything that can be streamed to an `ostream` can be streamed to an assertion
+macro--in particular, C strings and `string` objects. If a wide string
+(`wchar_t*`, `TCHAR*` in `UNICODE` mode on Windows, or `std::wstring`) is
+streamed to an assertion, it will be translated to UTF-8 when printed.
+
+## Basic Assertions ##
+
+These assertions do basic true/false condition testing.
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_TRUE(`_condition_`)`;  | `EXPECT_TRUE(`_condition_`)`;   | _condition_ is true |
+| `ASSERT_FALSE(`_condition_`)`; | `EXPECT_FALSE(`_condition_`)`;  | _condition_ is false |
+
+Remember, when they fail, `ASSERT_*` yields a fatal failure and
+returns from the current function, while `EXPECT_*` yields a nonfatal
+failure, allowing the function to continue running. In either case, an
+assertion failure means its containing test fails.
+
+_Availability_: Linux, Windows, Mac.
+
+## Binary Comparison ##
+
+This section describes assertions that compare two values.
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+|`ASSERT_EQ(`_expected_`, `_actual_`);`|`EXPECT_EQ(`_expected_`, `_actual_`);`| _expected_ `==` _actual_ |
+|`ASSERT_NE(`_val1_`, `_val2_`);`      |`EXPECT_NE(`_val1_`, `_val2_`);`      | _val1_ `!=` _val2_ |
+|`ASSERT_LT(`_val1_`, `_val2_`);`      |`EXPECT_LT(`_val1_`, `_val2_`);`      | _val1_ `<` _val2_ |
+|`ASSERT_LE(`_val1_`, `_val2_`);`      |`EXPECT_LE(`_val1_`, `_val2_`);`      | _val1_ `<=` _val2_ |
+|`ASSERT_GT(`_val1_`, `_val2_`);`      |`EXPECT_GT(`_val1_`, `_val2_`);`      | _val1_ `>` _val2_ |
+|`ASSERT_GE(`_val1_`, `_val2_`);`      |`EXPECT_GE(`_val1_`, `_val2_`);`      | _val1_ `>=` _val2_ |
+
+In the event of a failure, Google Test prints both _val1_ and _val2_
+. In `ASSERT_EQ*` and `EXPECT_EQ*` (and all other equality assertions
+we'll introduce later), you should put the expression you want to test
+in the position of _actual_, and put its expected value in _expected_,
+as Google Test's failure messages are optimized for this convention.
+
+Value arguments must be comparable by the assertion's comparison operator or
+you'll get a compiler error. Values must also support the `<<` operator for
+streaming to an `ostream`. All built-in types support this.
+
+These assertions can work with a user-defined type, but only if you define the
+corresponding comparison operator (e.g. `==`, `<`, etc).  If the corresponding
+operator is defined, prefer using the `ASSERT_*()` macros because they will
+print out not only the result of the comparison, but the two operands as well.
+
+Arguments are always evaluated exactly once. Therefore, it's OK for the
+arguments to have side effects. However, as with any ordinary C/C++ function,
+the arguments' evaluation order is undefined (i.e. the compiler is free to
+choose any order) and your code should not depend on any particular argument
+evaluation order.
+
+`ASSERT_EQ()` does pointer equality on pointers. If used on two C strings, it
+tests if they are in the same memory location, not if they have the same value.
+Therefore, if you want to compare C strings (e.g. `const char*`) by value, use
+`ASSERT_STREQ()` , which will be described later on. In particular, to assert
+that a C string is `NULL`, use `ASSERT_STREQ(NULL, c_string)` . However, to
+compare two `string` objects, you should use `ASSERT_EQ`.
+
+Macros in this section work with both narrow and wide string objects (`string`
+and `wstring`).
+
+_Availability_: Linux, Windows, Mac.
+
+## String Comparison ##
+
+The assertions in this group compare two **C strings**. If you want to compare
+two `string` objects, use `EXPECT_EQ`, `EXPECT_NE`, and etc instead.
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_STREQ(`_expected\_str_`, `_actual\_str_`);`    | `EXPECT_STREQ(`_expected\_str_`, `_actual\_str_`);`     | the two C strings have the same content |
+| `ASSERT_STRNE(`_str1_`, `_str2_`);`    | `EXPECT_STRNE(`_str1_`, `_str2_`);`     | the two C strings have different content |
+| `ASSERT_STRCASEEQ(`_expected\_str_`, `_actual\_str_`);`| `EXPECT_STRCASEEQ(`_expected\_str_`, `_actual\_str_`);` | the two C strings have the same content, ignoring case |
+| `ASSERT_STRCASENE(`_str1_`, `_str2_`);`| `EXPECT_STRCASENE(`_str1_`, `_str2_`);` | the two C strings have different content, ignoring case |
+
+Note that "CASE" in an assertion name means that case is ignored.
+
+`*STREQ*` and `*STRNE*` also accept wide C strings (`wchar_t*`). If a
+comparison of two wide strings fails, their values will be printed as UTF-8
+narrow strings.
+
+A `NULL` pointer and an empty string are considered _different_.
+
+_Availability_: Linux, Windows, Mac.
+
+See also: For more string comparison tricks (substring, prefix, suffix, and
+regular expression matching, for example), see the [AdvancedGuide Advanced
+Google Test Guide].
+
+# Simple Tests #
+
+To create a test:
+  1. Use the `TEST()` macro to define and name a test function, These are ordinary C++ functions that don't return a value.
+  1. In this function, along with any valid C++ statements you want to include, use the various Google Test assertions to check values.
+  1. The test's result is determined by the assertions; if any assertion in the test fails (either fatally or non-fatally), or if the test crashes, the entire test fails. Otherwise, it succeeds.
+
+```
+TEST(test_case_name, test_name) {
+ ... test body ...
+}
+```
+
+
+`TEST()` arguments go from general to specific. The _first_ argument is the
+name of the test case, and the _second_ argument is the test's name within the
+test case. Remember that a test case can contain any number of individual
+tests. A test's _full name_ consists of its containing test case and its
+individual name. Tests from different test cases can have the same individual
+name.
+
+For example, let's take a simple integer function:
+```
+int Factorial(int n); // Returns the factorial of n
+```
+
+A test case for this function might look like:
+```
+// Tests factorial of 0.
+TEST(FactorialTest, HandlesZeroInput) {
+  EXPECT_EQ(1, Factorial(0));
+}
+
+// Tests factorial of positive numbers.
+TEST(FactorialTest, HandlesPositiveInput) {
+  EXPECT_EQ(1, Factorial(1));
+  EXPECT_EQ(2, Factorial(2));
+  EXPECT_EQ(6, Factorial(3));
+  EXPECT_EQ(40320, Factorial(8));
+}
+```
+
+Google Test groups the test results by test cases, so logically-related tests
+should be in the same test case; in other words, the first argument to their
+`TEST()` should be the same. In the above example, we have two tests,
+`HandlesZeroInput` and `HandlesPositiveInput`, that belong to the same test
+case `FactorialTest`.
+
+_Availability_: Linux, Windows, Mac.
+
+# Test Fixtures: Using the Same Data Configuration for Multiple Tests #
+
+If you find yourself writing two or more tests that operate on similar data,
+you can use a _test fixture_. It allows you to reuse the same configuration of
+objects for several different tests.
+
+To create a fixture, just:
+  1. Derive a class from `::testing::Test` . Start its body with `protected:` or `public:` as we'll want to access fixture members from sub-classes.
+  1. Inside the class, declare any objects you plan to use.
+  1. If necessary, write a default constructor or `SetUp()` function to prepare the objects for each test. A common mistake is to spell `SetUp()` as `Setup()` with a small `u` - don't let that happen to you.
+  1. If necessary, write a destructor or `TearDown()` function to release any resources you allocated in `SetUp()` . To learn when you should use the constructor/destructor and when you should use `SetUp()/TearDown()`, read this [FAQ entry](http://code.google.com/p/googletest/wiki/V1_5_FAQ#Should_I_use_the_constructor/destructor_of_the_test_fixture_or_t).
+  1. If needed, define subroutines for your tests to share.
+
+When using a fixture, use `TEST_F()` instead of `TEST()` as it allows you to
+access objects and subroutines in the test fixture:
+```
+TEST_F(test_case_name, test_name) {
+ ... test body ...
+}
+```
+
+Like `TEST()`, the first argument is the test case name, but for `TEST_F()`
+this must be the name of the test fixture class. You've probably guessed: `_F`
+is for fixture.
+
+Unfortunately, the C++ macro system does not allow us to create a single macro
+that can handle both types of tests. Using the wrong macro causes a compiler
+error.
+
+Also, you must first define a test fixture class before using it in a
+`TEST_F()`, or you'll get the compiler error "`virtual outside class
+declaration`".
+
+For each test defined with `TEST_F()`, Google Test will:
+  1. Create a _fresh_ test fixture at runtime
+  1. Immediately initialize it via `SetUp()` ,
+  1. Run the test
+  1. Clean up by calling `TearDown()`
+  1. Delete the test fixture.  Note that different tests in the same test case have different test fixture objects, and Google Test always deletes a test fixture before it creates the next one. Google Test does not reuse the same test fixture for multiple tests. Any changes one test makes to the fixture do not affect other tests.
+
+As an example, let's write tests for a FIFO queue class named `Queue`, which
+has the following interface:
+```
+template <typename E> // E is the element type.
+class Queue {
+ public:
+  Queue();
+  void Enqueue(const E& element);
+  E* Dequeue(); // Returns NULL if the queue is empty.
+  size_t size() const;
+  ...
+};
+```
+
+First, define a fixture class. By convention, you should give it the name
+`FooTest` where `Foo` is the class being tested.
+```
+class QueueTest : public ::testing::Test {
+ protected:
+  virtual void SetUp() {
+    q1_.Enqueue(1);
+    q2_.Enqueue(2);
+    q2_.Enqueue(3);
+  }
+
+  // virtual void TearDown() {}
+
+  Queue<int> q0_;
+  Queue<int> q1_;
+  Queue<int> q2_;
+};
+```
+
+In this case, `TearDown()` is not needed since we don't have to clean up after
+each test, other than what's already done by the destructor.
+
+Now we'll write tests using `TEST_F()` and this fixture.
+```
+TEST_F(QueueTest, IsEmptyInitially) {
+  EXPECT_EQ(0, q0_.size());
+}
+
+TEST_F(QueueTest, DequeueWorks) {
+  int* n = q0_.Dequeue();
+  EXPECT_EQ(NULL, n);
+
+  n = q1_.Dequeue();
+  ASSERT_TRUE(n != NULL);
+  EXPECT_EQ(1, *n);
+  EXPECT_EQ(0, q1_.size());
+  delete n;
+
+  n = q2_.Dequeue();
+  ASSERT_TRUE(n != NULL);
+  EXPECT_EQ(2, *n);
+  EXPECT_EQ(1, q2_.size());
+  delete n;
+}
+```
+
+The above uses both `ASSERT_*` and `EXPECT_*` assertions. The rule of thumb is
+to use `EXPECT_*` when you want the test to continue to reveal more errors
+after the assertion failure, and use `ASSERT_*` when continuing after failure
+doesn't make sense. For example, the second assertion in the `Dequeue` test is
+`ASSERT_TRUE(n != NULL)`, as we need to dereference the pointer `n` later,
+which would lead to a segfault when `n` is `NULL`.
+
+When these tests run, the following happens:
+  1. Google Test constructs a `QueueTest` object (let's call it `t1` ).
+  1. `t1.SetUp()` initializes `t1` .
+  1. The first test ( `IsEmptyInitially` ) runs on `t1` .
+  1. `t1.TearDown()` cleans up after the test finishes.
+  1. `t1` is destructed.
+  1. The above steps are repeated on another `QueueTest` object, this time running the `DequeueWorks` test.
+
+_Availability_: Linux, Windows, Mac.
+
+_Note_: Google Test automatically saves all _Google Test_ flags when a test
+object is constructed, and restores them when it is destructed.
+
+# Invoking the Tests #
+
+`TEST()` and `TEST_F()` implicitly register their tests with Google Test. So, unlike with many other C++ testing frameworks, you don't have to re-list all your defined tests in order to run them.
+
+After defining your tests, you can run them with `RUN_ALL_TESTS()` , which returns `0` if all the tests are successful, or `1` otherwise. Note that `RUN_ALL_TESTS()` runs _all tests_ in your link unit -- they can be from different test cases, or even different source files.
+
+When invoked, the `RUN_ALL_TESTS()` macro:
+  1. Saves the state of all  Google Test flags.
+  1. Creates a test fixture object for the first test.
+  1. Initializes it via `SetUp()`.
+  1. Runs the test on the fixture object.
+  1. Cleans up the fixture via `TearDown()`.
+  1. Deletes the fixture.
+  1. Restores the state of all Google Test flags.
+  1. Repeats the above steps for the next test, until all tests have run.
+
+In addition, if the text fixture's constructor generates a fatal failure in
+step 2, there is no point for step 3 - 5 and they are thus skipped. Similarly,
+if step 3 generates a fatal failure, step 4 will be skipped.
+
+_Important_: You must not ignore the return value of `RUN_ALL_TESTS()`, or `gcc`
+will give you a compiler error. The rationale for this design is that the
+automated testing service determines whether a test has passed based on its
+exit code, not on its stdout/stderr output; thus your `main()` function must
+return the value of `RUN_ALL_TESTS()`.
+
+Also, you should call `RUN_ALL_TESTS()` only **once**. Calling it more than once
+conflicts with some advanced Google Test features (e.g. thread-safe death
+tests) and thus is not supported.
+
+_Availability_: Linux, Windows, Mac.
+
+# Writing the main() Function #
+
+You can start from this boilerplate:
+```
+#include "this/package/foo.h"
+#include <gtest/gtest.h>
+
+namespace {
+
+// The fixture for testing class Foo.
+class FooTest : public ::testing::Test {
+ protected:
+  // You can remove any or all of the following functions if its body
+  // is empty.
+
+  FooTest() {
+    // You can do set-up work for each test here.
+  }
+
+  virtual ~FooTest() {
+    // You can do clean-up work that doesn't throw exceptions here.
+  }
+
+  // If the constructor and destructor are not enough for setting up
+  // and cleaning up each test, you can define the following methods:
+
+  virtual void SetUp() {
+    // Code here will be called immediately after the constructor (right
+    // before each test).
+  }
+
+  virtual void TearDown() {
+    // Code here will be called immediately after each test (right
+    // before the destructor).
+  }
+
+  // Objects declared here can be used by all tests in the test case for Foo.
+};
+
+// Tests that the Foo::Bar() method does Abc.
+TEST_F(FooTest, MethodBarDoesAbc) {
+  const string input_filepath = "this/package/testdata/myinputfile.dat";
+  const string output_filepath = "this/package/testdata/myoutputfile.dat";
+  Foo f;
+  EXPECT_EQ(0, f.Bar(input_filepath, output_filepath));
+}
+
+// Tests that Foo does Xyz.
+TEST_F(FooTest, DoesXyz) {
+  // Exercises the Xyz feature of Foo.
+}
+
+}  // namespace
+
+int main(int argc, char **argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
+```
+
+The `::testing::InitGoogleTest()` function parses the command line for Google
+Test flags, and removes all recognized flags. This allows the user to control a
+test program's behavior via various flags, which we'll cover in [AdvancedGuide](V1_5_AdvancedGuide.md).
+You must call this function before calling `RUN_ALL_TESTS()`, or the flags
+won't be properly initialized.
+
+On Windows, `InitGoogleTest()` also works with wide strings, so it can be used
+in programs compiled in `UNICODE` mode as well.
+
+But maybe you think that writing all those main() functions is too much work? We agree with you completely and that's why Google Test provides a basic implementation of main(). If it fits your needs, then just link your test with gtest\_main library and you are good to go.
+
+## Important note for Visual C++ users ##
+If you put your tests into a library and your `main()` function is in a different library or in your .exe file, those tests will not run. The reason is a [bug](https://connect.microsoft.com/feedback/viewfeedback.aspx?FeedbackID=244410&siteid=210) in Visual C++. When you define your tests, Google Test creates certain static objects to register them. These objects are not referenced from elsewhere but their constructors are still supposed to run. When Visual C++ linker sees that nothing in the library is referenced from other places it throws the library out. You have to reference your library with tests from your main program to keep the linker from discarding it. Here is how to do it. Somewhere in your library code declare a function:
+```
+__declspec(dllexport) int PullInMyLibrary() { return 0; }
+```
+If you put your tests in a static library (not DLL) then `__declspec(dllexport)` is not required. Now, in your main program, write a code that invokes that function:
+```
+int PullInMyLibrary();
+static int dummy = PullInMyLibrary();
+```
+This will keep your tests referenced and will make them register themselves at startup.
+
+In addition, if you define your tests in a static library, add `/OPT:NOREF` to your main program linker options. If you use MSVC++ IDE, go to your .exe project properties/Configuration Properties/Linker/Optimization and set References setting to `Keep Unreferenced Data (/OPT:NOREF)`. This will keep Visual C++ linker from discarding individual symbols generated by your tests from the final executable.
+
+There is one more pitfall, though. If you use Google Test as a static library (that's how it is defined in gtest.vcproj) your tests must also reside in a static library. If you have to have them in a DLL, you _must_ change Google Test to build into a DLL as well. Otherwise your tests will not run correctly or will not run at all. The general conclusion here is: make your life easier - do not write your tests in libraries!
+
+# Where to Go from Here #
+
+Congratulations! You've learned the Google Test basics. You can start writing
+and running Google Test tests, read some [samples](Samples.md), or continue with
+[AdvancedGuide](V1_5_AdvancedGuide.md), which describes many more useful Google Test features.
+
+# Known Limitations #
+
+Google Test is designed to be thread-safe.  The implementation is
+thread-safe on systems where the `pthreads` library is available.  It
+is currently _unsafe_ to use Google Test assertions from two threads
+concurrently on other systems (e.g. Windows).  In most tests this is
+not an issue as usually the assertions are done in the main thread. If
+you want to help, you can volunteer to implement the necessary
+synchronization primitives in `gtest-port.h` for your platform.
\ No newline at end of file
diff --git a/third_party/googletest/googletest/docs/V1_5_PumpManual.md b/third_party/googletest/googletest/docs/V1_5_PumpManual.md
new file mode 100644
index 0000000..1571078
--- /dev/null
+++ b/third_party/googletest/googletest/docs/V1_5_PumpManual.md
@@ -0,0 +1,177 @@
+
+
+<b>P</b>ump is <b>U</b>seful for <b>M</b>eta <b>P</b>rogramming.
+
+# The Problem #
+
+Template and macro libraries often need to define many classes,
+functions, or macros that vary only (or almost only) in the number of
+arguments they take. It's a lot of repetitive, mechanical, and
+error-prone work.
+
+Variadic templates and variadic macros can alleviate the problem.
+However, while both are being considered by the C++ committee, neither
+is in the standard yet or widely supported by compilers.  Thus they
+are often not a good choice, especially when your code needs to be
+portable. And their capabilities are still limited.
+
+As a result, authors of such libraries often have to write scripts to
+generate their implementation. However, our experience is that it's
+tedious to write such scripts, which tend to reflect the structure of
+the generated code poorly and are often hard to read and edit. For
+example, a small change needed in the generated code may require some
+non-intuitive, non-trivial changes in the script. This is especially
+painful when experimenting with the code.
+
+# Our Solution #
+
+Pump (for Pump is Useful for Meta Programming, Pretty Useful for Meta
+Programming, or Practical Utility for Meta Programming, whichever you
+prefer) is a simple meta-programming tool for C++. The idea is that a
+programmer writes a `foo.pump` file which contains C++ code plus meta
+code that manipulates the C++ code. The meta code can handle
+iterations over a range, nested iterations, local meta variable
+definitions, simple arithmetic, and conditional expressions. You can
+view it as a small Domain-Specific Language. The meta language is
+designed to be non-intrusive (s.t. it won't confuse Emacs' C++ mode,
+for example) and concise, making Pump code intuitive and easy to
+maintain.
+
+## Highlights ##
+
+  * The implementation is in a single Python script and thus ultra portable: no build or installation is needed and it works cross platforms.
+  * Pump tries to be smart with respect to [Google's style guide](http://code.google.com/p/google-styleguide/): it breaks long lines (easy to have when they are generated) at acceptable places to fit within 80 columns and indent the continuation lines correctly.
+  * The format is human-readable and more concise than XML.
+  * The format works relatively well with Emacs' C++ mode.
+
+## Examples ##
+
+The following Pump code (where meta keywords start with `$`, `[[` and `]]` are meta brackets, and `$$` starts a meta comment that ends with the line):
+
+```
+$var n = 3     $$ Defines a meta variable n.
+$range i 0..n  $$ Declares the range of meta iterator i (inclusive).
+$for i [[
+               $$ Meta loop.
+// Foo$i does blah for $i-ary predicates.
+$range j 1..i
+template <size_t N $for j [[, typename A$j]]>
+class Foo$i {
+$if i == 0 [[
+  blah a;
+]] $elif i <= 2 [[
+  blah b;
+]] $else [[
+  blah c;
+]]
+};
+
+]]
+```
+
+will be translated by the Pump compiler to:
+
+```
+// Foo0 does blah for 0-ary predicates.
+template <size_t N>
+class Foo0 {
+  blah a;
+};
+
+// Foo1 does blah for 1-ary predicates.
+template <size_t N, typename A1>
+class Foo1 {
+  blah b;
+};
+
+// Foo2 does blah for 2-ary predicates.
+template <size_t N, typename A1, typename A2>
+class Foo2 {
+  blah b;
+};
+
+// Foo3 does blah for 3-ary predicates.
+template <size_t N, typename A1, typename A2, typename A3>
+class Foo3 {
+  blah c;
+};
+```
+
+In another example,
+
+```
+$range i 1..n
+Func($for i + [[a$i]]);
+$$ The text between i and [[ is the separator between iterations.
+```
+
+will generate one of the following lines (without the comments), depending on the value of `n`:
+
+```
+Func();              // If n is 0.
+Func(a1);            // If n is 1.
+Func(a1 + a2);       // If n is 2.
+Func(a1 + a2 + a3);  // If n is 3.
+// And so on...
+```
+
+## Constructs ##
+
+We support the following meta programming constructs:
+
+| `$var id = exp` | Defines a named constant value. `$id` is valid util the end of the current meta lexical block. |
+|:----------------|:-----------------------------------------------------------------------------------------------|
+| $range id exp..exp | Sets the range of an iteration variable, which can be reused in multiple loops later.          |
+| $for id sep [[code ](.md)] | Iteration. The range of `id` must have been defined earlier. `$id` is valid in `code`.         |
+| `$($)`          | Generates a single `$` character.                                                              |
+| `$id`           | Value of the named constant or iteration variable.                                             |
+| `$(exp)`        | Value of the expression.                                                                       |
+| `$if exp [[ code ]] else_branch` | Conditional.                                                                                   |
+| `[[ code ]]`    | Meta lexical block.                                                                            |
+| `cpp_code`      | Raw C++ code.                                                                                  |
+| `$$ comment`    | Meta comment.                                                                                  |
+
+**Note:** To give the user some freedom in formatting the Pump source
+code, Pump ignores a new-line character if it's right after `$for foo`
+or next to `[[` or `]]`. Without this rule you'll often be forced to write
+very long lines to get the desired output. Therefore sometimes you may
+need to insert an extra new-line in such places for a new-line to show
+up in your output.
+
+## Grammar ##
+
+```
+code ::= atomic_code*
+atomic_code ::= $var id = exp
+    | $var id = [[ code ]]
+    | $range id exp..exp
+    | $for id sep [[ code ]]
+    | $($)
+    | $id
+    | $(exp)
+    | $if exp [[ code ]] else_branch
+    | [[ code ]]
+    | cpp_code
+sep ::= cpp_code | empty_string
+else_branch ::= $else [[ code ]]
+    | $elif exp [[ code ]] else_branch
+    | empty_string
+exp ::= simple_expression_in_Python_syntax
+```
+
+## Code ##
+
+You can find the source code of Pump in [scripts/pump.py](http://code.google.com/p/googletest/source/browse/trunk/scripts/pump.py). It is still
+very unpolished and lacks automated tests, although it has been
+successfully used many times. If you find a chance to use it in your
+project, please let us know what you think!  We also welcome help on
+improving Pump.
+
+## Real Examples ##
+
+You can find real-world applications of Pump in [Google Test](http://www.google.com/codesearch?q=file%3A\.pump%24+package%3Ahttp%3A%2F%2Fgoogletest\.googlecode\.com) and [Google Mock](http://www.google.com/codesearch?q=file%3A\.pump%24+package%3Ahttp%3A%2F%2Fgooglemock\.googlecode\.com).  The source file `foo.h.pump` generates `foo.h`.
+
+## Tips ##
+
+  * If a meta variable is followed by a letter or digit, you can separate them using `[[]]`, which inserts an empty string. For example `Foo$j[[]]Helper` generate `Foo1Helper` when `j` is 1.
+  * To avoid extra-long Pump source lines, you can break a line anywhere you want by inserting `[[]]` followed by a new line. Since any new-line character next to `[[` or `]]` is ignored, the generated code won't contain this new line.
\ No newline at end of file
diff --git a/third_party/googletest/googletest/docs/V1_5_XcodeGuide.md b/third_party/googletest/googletest/docs/V1_5_XcodeGuide.md
new file mode 100644
index 0000000..bf24bf5
--- /dev/null
+++ b/third_party/googletest/googletest/docs/V1_5_XcodeGuide.md
@@ -0,0 +1,93 @@
+
+
+This guide will explain how to use the Google Testing Framework in your Xcode projects on Mac OS X. This tutorial begins by quickly explaining what to do for experienced users. After the quick start, the guide goes provides additional explanation about each step.
+
+# Quick Start #
+
+Here is the quick guide for using Google Test in your Xcode project.
+
+  1. Download the source from the [website](http://code.google.com/p/googletest) using this command: `svn checkout http://googletest.googlecode.com/svn/trunk/ googletest-read-only`
+  1. Open up the `gtest.xcodeproj` in the `googletest-read-only/xcode/` directory and build the gtest.framework.
+  1. Create a new "Shell Tool" target in your Xcode project called something like "UnitTests"
+  1. Add the gtest.framework to your project and add it to the "Link Binary with Libraries" build phase of "UnitTests"
+  1. Add your unit test source code to the "Compile Sources" build phase of "UnitTests"
+  1. Edit the "UnitTests" executable and add an environment variable named "DYLD\_FRAMEWORK\_PATH" with a value equal to the path to the framework containing the gtest.framework relative to the compiled executable.
+  1. Build and Go
+
+The following sections further explain each of the steps listed above in depth, describing in more detail how to complete it including some variations.
+
+# Get the Source #
+
+Currently, the gtest.framework discussed here isn't available in a tagged release of Google Test, it is only available in the trunk. As explained at the Google Test [site](http://code.google.com/p/googletest/source/checkout">svn), you can get the code from anonymous SVN with this command:
+
+```
+svn checkout http://googletest.googlecode.com/svn/trunk/ googletest-read-only
+```
+
+Alternatively, if you are working with Subversion in your own code base, you can add Google Test as an external dependency to your own Subversion repository. By following this approach, everyone that checks out your svn repository will also receive a copy of Google Test (a specific version, if you wish) without having to check it out explicitly. This makes the set up of your project simpler and reduces the copied code in the repository.
+
+To use `svn:externals`, decide where you would like to have the external source reside. You might choose to put the external source inside the trunk, because you want it to be part of the branch when you make a release. However, keeping it outside the trunk in a version-tagged directory called something like `third-party/googletest/1.0.1`, is another option. Once the location is established, use `svn propedit svn:externals _directory_` to set the svn:externals property on a directory in your repository. This directory won't contain the code, but be its versioned parent directory.
+
+The command `svn propedit` will bring up your Subversion editor, making editing the long, (potentially multi-line) property simpler. This same method can be used to check out a tagged branch, by using the appropriate URL (e.g. `http://googletest.googlecode.com/svn/tags/release-1.0.1`). Additionally, the svn:externals property allows the specification of a particular revision of the trunk with the `-r_##_` option (e.g. `externals/src/googletest -r60 http://googletest.googlecode.com/svn/trunk`).
+
+Here is an example of using the svn:externals properties on a trunk (read via `svn propget`) of a project. This value checks out a copy of Google Test into the `trunk/externals/src/googletest/` directory.
+
+```
+[Computer:svn] user$ svn propget svn:externals trunk
+externals/src/googletest http://googletest.googlecode.com/svn/trunk
+```
+
+# Add the Framework to Your Project #
+
+The next step is to build and add the gtest.framework to your own project. This guide describes two common ways below.
+
+  * **Option 1** --- The simplest way to add Google Test to your own project, is to open gtest.xcodeproj (found in the xcode/ directory of the Google Test trunk) and build the framework manually. Then, add the built framework into your project using the "Add->Existing Framework..." from the context menu or "Project->Add..." from the main menu. The gtest.framework is relocatable and contains the headers and object code that you'll need to make tests. This method requires rebuilding every time you upgrade Google Test in your project.
+  * **Option 2** --- If you are going to be living off the trunk of Google Test, incorporating its latest features into your unit tests (or are a Google Test developer yourself). You'll want to rebuild the framework every time the source updates. to do this, you'll need to add the gtest.xcodeproj file, not the framework itself, to your own Xcode project. Then, from the build products that are revealed by the project's disclosure triangle, you can find the gtest.framework, which can be added to your targets (discussed below).
+
+# Make a Test Target #
+
+To start writing tests, make a new "Shell Tool" target. This target template is available under BSD, Cocoa, or Carbon. Add your unit test source code to the "Compile Sources" build phase of the target.
+
+Next, you'll want to add gtest.framework in two different ways, depending upon which option you chose above.
+
+  * **Option 1** --- During compilation, Xcode will need to know that you are linking against the gtest.framework. Add the gtest.framework to the "Link Binary with Libraries" build phase of your test target. This will include the Google Test headers in your header search path, and will tell the linker where to find the library.
+  * **Option 2** --- If your working out of the trunk, you'll also want to add gtest.framework to your "Link Binary with Libraries" build phase of your test target. In addition, you'll  want to add the gtest.framework as a dependency to your unit test target. This way, Xcode will make sure that gtest.framework is up to date, every time your build your target. Finally, if you don't share build directories with Google Test, you'll have to copy the gtest.framework into your own build products directory using a "Run Script" build phase.
+
+# Set Up the Executable Run Environment #
+
+Since the unit test executable is a shell tool, it doesn't have a bundle with a `Contents/Frameworks` directory, in which to place gtest.framework. Instead, the dynamic linker must be told at runtime to search for the framework in another location. This can be accomplished by setting the "DYLD\_FRAMEWORK\_PATH" environment variable in the "Edit Active Executable ..." Arguments tab, under "Variables to be set in the environment:". The path for this value is the path (relative or absolute) of the directory containing the gtest.framework.
+
+If you haven't set up the DYLD\_FRAMEWORK\_PATH, correctly, you might get a message like this:
+
+```
+[Session started at 2008-08-15 06:23:57 -0600.]
+  dyld: Library not loaded: @loader_path/../Frameworks/gtest.framework/Versions/A/gtest
+    Referenced from: /Users/username/Documents/Sandbox/gtestSample/build/Debug/WidgetFrameworkTest
+    Reason: image not found
+```
+
+To correct this problem, got to the directory containing the executable named in "Referenced from:" value in the error message above. Then, with the terminal in this location, find the relative path to the directory containing the gtest.framework. That is the value you'll need to set as the DYLD\_FRAMEWORK\_PATH.
+
+# Build and Go #
+
+Now, when you click "Build and Go", the test will be executed. Dumping out something like this:
+
+```
+[Session started at 2008-08-06 06:36:13 -0600.]
+[==========] Running 2 tests from 1 test case.
+[----------] Global test environment set-up.
+[----------] 2 tests from WidgetInitializerTest
+[ RUN      ] WidgetInitializerTest.TestConstructor
+[       OK ] WidgetInitializerTest.TestConstructor
+[ RUN      ] WidgetInitializerTest.TestConversion
+[       OK ] WidgetInitializerTest.TestConversion
+[----------] Global test environment tear-down
+[==========] 2 tests from 1 test case ran.
+[  PASSED  ] 2 tests.
+
+The Debugger has exited with status 0.  
+```
+
+# Summary #
+
+Unit testing is a valuable way to ensure your data model stays valid even during rapid development or refactoring. The Google Testing Framework is a great unit testing framework for C and C++ which integrates well with an Xcode development environment.
\ No newline at end of file
diff --git a/third_party/googletest/googletest/docs/V1_6_AdvancedGuide.md b/third_party/googletest/googletest/docs/V1_6_AdvancedGuide.md
new file mode 100644
index 0000000..44e0d6f
--- /dev/null
+++ b/third_party/googletest/googletest/docs/V1_6_AdvancedGuide.md
@@ -0,0 +1,2178 @@
+
+
+Now that you have read [Primer](V1_6_Primer.md) and learned how to write tests
+using Google Test, it's time to learn some new tricks. This document
+will show you more assertions as well as how to construct complex
+failure messages, propagate fatal failures, reuse and speed up your
+test fixtures, and use various flags with your tests.
+
+# More Assertions #
+
+This section covers some less frequently used, but still significant,
+assertions.
+
+## Explicit Success and Failure ##
+
+These three assertions do not actually test a value or expression. Instead,
+they generate a success or failure directly. Like the macros that actually
+perform a test, you may stream a custom failure message into the them.
+
+| `SUCCEED();` |
+|:-------------|
+
+Generates a success. This does NOT make the overall test succeed. A test is
+considered successful only if none of its assertions fail during its execution.
+
+Note: `SUCCEED()` is purely documentary and currently doesn't generate any
+user-visible output. However, we may add `SUCCEED()` messages to Google Test's
+output in the future.
+
+| `FAIL();`  | `ADD_FAILURE();` | `ADD_FAILURE_AT("`_file\_path_`", `_line\_number_`);` |
+|:-----------|:-----------------|:------------------------------------------------------|
+
+`FAIL()` generates a fatal failure, while `ADD_FAILURE()` and `ADD_FAILURE_AT()` generate a nonfatal
+failure. These are useful when control flow, rather than a Boolean expression,
+deteremines the test's success or failure. For example, you might want to write
+something like:
+
+```
+switch(expression) {
+  case 1: ... some checks ...
+  case 2: ... some other checks
+  ...
+  default: FAIL() << "We shouldn't get here.";
+}
+```
+
+_Availability_: Linux, Windows, Mac.
+
+## Exception Assertions ##
+
+These are for verifying that a piece of code throws (or does not
+throw) an exception of the given type:
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_THROW(`_statement_, _exception\_type_`);`  | `EXPECT_THROW(`_statement_, _exception\_type_`);`  | _statement_ throws an exception of the given type  |
+| `ASSERT_ANY_THROW(`_statement_`);`                | `EXPECT_ANY_THROW(`_statement_`);`                | _statement_ throws an exception of any type        |
+| `ASSERT_NO_THROW(`_statement_`);`                 | `EXPECT_NO_THROW(`_statement_`);`                 | _statement_ doesn't throw any exception            |
+
+Examples:
+
+```
+ASSERT_THROW(Foo(5), bar_exception);
+
+EXPECT_NO_THROW({
+  int n = 5;
+  Bar(&n);
+});
+```
+
+_Availability_: Linux, Windows, Mac; since version 1.1.0.
+
+## Predicate Assertions for Better Error Messages ##
+
+Even though Google Test has a rich set of assertions, they can never be
+complete, as it's impossible (nor a good idea) to anticipate all the scenarios
+a user might run into. Therefore, sometimes a user has to use `EXPECT_TRUE()`
+to check a complex expression, for lack of a better macro. This has the problem
+of not showing you the values of the parts of the expression, making it hard to
+understand what went wrong. As a workaround, some users choose to construct the
+failure message by themselves, streaming it into `EXPECT_TRUE()`. However, this
+is awkward especially when the expression has side-effects or is expensive to
+evaluate.
+
+Google Test gives you three different options to solve this problem:
+
+### Using an Existing Boolean Function ###
+
+If you already have a function or a functor that returns `bool` (or a type
+that can be implicitly converted to `bool`), you can use it in a _predicate
+assertion_ to get the function arguments printed for free:
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_PRED1(`_pred1, val1_`);`       | `EXPECT_PRED1(`_pred1, val1_`);` | _pred1(val1)_ returns true |
+| `ASSERT_PRED2(`_pred2, val1, val2_`);` | `EXPECT_PRED2(`_pred2, val1, val2_`);` |  _pred2(val1, val2)_ returns true |
+|  ...                | ...                    | ...          |
+
+In the above, _predn_ is an _n_-ary predicate function or functor, where
+_val1_, _val2_, ..., and _valn_ are its arguments. The assertion succeeds
+if the predicate returns `true` when applied to the given arguments, and fails
+otherwise. When the assertion fails, it prints the value of each argument. In
+either case, the arguments are evaluated exactly once.
+
+Here's an example. Given
+
+```
+// Returns true iff m and n have no common divisors except 1.
+bool MutuallyPrime(int m, int n) { ... }
+const int a = 3;
+const int b = 4;
+const int c = 10;
+```
+
+the assertion `EXPECT_PRED2(MutuallyPrime, a, b);` will succeed, while the
+assertion `EXPECT_PRED2(MutuallyPrime, b, c);` will fail with the message
+
+<pre>
+!MutuallyPrime(b, c) is false, where<br>
+b is 4<br>
+c is 10<br>
+</pre>
+
+**Notes:**
+
+  1. If you see a compiler error "no matching function to call" when using `ASSERT_PRED*` or `EXPECT_PRED*`, please see [this](http://code.google.com/p/googletest/wiki/V1_6_FAQ#The_compiler_complains_%22no_matching_function_to_call%22) for how to resolve it.
+  1. Currently we only provide predicate assertions of arity <= 5. If you need a higher-arity assertion, let us know.
+
+_Availability_: Linux, Windows, Mac
+
+### Using a Function That Returns an AssertionResult ###
+
+While `EXPECT_PRED*()` and friends are handy for a quick job, the
+syntax is not satisfactory: you have to use different macros for
+different arities, and it feels more like Lisp than C++.  The
+`::testing::AssertionResult` class solves this problem.
+
+An `AssertionResult` object represents the result of an assertion
+(whether it's a success or a failure, and an associated message).  You
+can create an `AssertionResult` using one of these factory
+functions:
+
+```
+namespace testing {
+
+// Returns an AssertionResult object to indicate that an assertion has
+// succeeded.
+AssertionResult AssertionSuccess();
+
+// Returns an AssertionResult object to indicate that an assertion has
+// failed.
+AssertionResult AssertionFailure();
+
+}
+```
+
+You can then use the `<<` operator to stream messages to the
+`AssertionResult` object.
+
+To provide more readable messages in Boolean assertions
+(e.g. `EXPECT_TRUE()`), write a predicate function that returns
+`AssertionResult` instead of `bool`. For example, if you define
+`IsEven()` as:
+
+```
+::testing::AssertionResult IsEven(int n) {
+  if ((n % 2) == 0)
+    return ::testing::AssertionSuccess();
+  else
+    return ::testing::AssertionFailure() << n << " is odd";
+}
+```
+
+instead of:
+
+```
+bool IsEven(int n) {
+  return (n % 2) == 0;
+}
+```
+
+the failed assertion `EXPECT_TRUE(IsEven(Fib(4)))` will print:
+
+<pre>
+Value of: !IsEven(Fib(4))<br>
+Actual: false (*3 is odd*)<br>
+Expected: true<br>
+</pre>
+
+instead of a more opaque
+
+<pre>
+Value of: !IsEven(Fib(4))<br>
+Actual: false<br>
+Expected: true<br>
+</pre>
+
+If you want informative messages in `EXPECT_FALSE` and `ASSERT_FALSE`
+as well, and are fine with making the predicate slower in the success
+case, you can supply a success message:
+
+```
+::testing::AssertionResult IsEven(int n) {
+  if ((n % 2) == 0)
+    return ::testing::AssertionSuccess() << n << " is even";
+  else
+    return ::testing::AssertionFailure() << n << " is odd";
+}
+```
+
+Then the statement `EXPECT_FALSE(IsEven(Fib(6)))` will print
+
+<pre>
+Value of: !IsEven(Fib(6))<br>
+Actual: true (8 is even)<br>
+Expected: false<br>
+</pre>
+
+_Availability_: Linux, Windows, Mac; since version 1.4.1.
+
+### Using a Predicate-Formatter ###
+
+If you find the default message generated by `(ASSERT|EXPECT)_PRED*` and
+`(ASSERT|EXPECT)_(TRUE|FALSE)` unsatisfactory, or some arguments to your
+predicate do not support streaming to `ostream`, you can instead use the
+following _predicate-formatter assertions_ to _fully_ customize how the
+message is formatted:
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_PRED_FORMAT1(`_pred\_format1, val1_`);`        | `EXPECT_PRED_FORMAT1(`_pred\_format1, val1_`); | _pred\_format1(val1)_ is successful |
+| `ASSERT_PRED_FORMAT2(`_pred\_format2, val1, val2_`);` | `EXPECT_PRED_FORMAT2(`_pred\_format2, val1, val2_`);` | _pred\_format2(val1, val2)_ is successful |
+| `...`               | `...`                  | `...`        |
+
+The difference between this and the previous two groups of macros is that instead of
+a predicate, `(ASSERT|EXPECT)_PRED_FORMAT*` take a _predicate-formatter_
+(_pred\_formatn_), which is a function or functor with the signature:
+
+`::testing::AssertionResult PredicateFormattern(const char* `_expr1_`, const char* `_expr2_`, ... const char* `_exprn_`, T1 `_val1_`, T2 `_val2_`, ... Tn `_valn_`);`
+
+where _val1_, _val2_, ..., and _valn_ are the values of the predicate
+arguments, and _expr1_, _expr2_, ..., and _exprn_ are the corresponding
+expressions as they appear in the source code. The types `T1`, `T2`, ..., and
+`Tn` can be either value types or reference types. For example, if an
+argument has type `Foo`, you can declare it as either `Foo` or `const Foo&`,
+whichever is appropriate.
+
+A predicate-formatter returns a `::testing::AssertionResult` object to indicate
+whether the assertion has succeeded or not. The only way to create such an
+object is to call one of these factory functions:
+
+As an example, let's improve the failure message in the previous example, which uses `EXPECT_PRED2()`:
+
+```
+// Returns the smallest prime common divisor of m and n,
+// or 1 when m and n are mutually prime.
+int SmallestPrimeCommonDivisor(int m, int n) { ... }
+
+// A predicate-formatter for asserting that two integers are mutually prime.
+::testing::AssertionResult AssertMutuallyPrime(const char* m_expr,
+                                               const char* n_expr,
+                                               int m,
+                                               int n) {
+  if (MutuallyPrime(m, n))
+    return ::testing::AssertionSuccess();
+ 
+  return ::testing::AssertionFailure()
+      << m_expr << " and " << n_expr << " (" << m << " and " << n
+      << ") are not mutually prime, " << "as they have a common divisor "
+      << SmallestPrimeCommonDivisor(m, n);
+}
+```
+
+With this predicate-formatter, we can use
+
+```
+EXPECT_PRED_FORMAT2(AssertMutuallyPrime, b, c);
+```
+
+to generate the message
+
+<pre>
+b and c (4 and 10) are not mutually prime, as they have a common divisor 2.<br>
+</pre>
+
+As you may have realized, many of the assertions we introduced earlier are
+special cases of `(EXPECT|ASSERT)_PRED_FORMAT*`. In fact, most of them are
+indeed defined using `(EXPECT|ASSERT)_PRED_FORMAT*`.
+
+_Availability_: Linux, Windows, Mac.
+
+
+## Floating-Point Comparison ##
+
+Comparing floating-point numbers is tricky. Due to round-off errors, it is
+very unlikely that two floating-points will match exactly. Therefore,
+`ASSERT_EQ` 's naive comparison usually doesn't work. And since floating-points
+can have a wide value range, no single fixed error bound works. It's better to
+compare by a fixed relative error bound, except for values close to 0 due to
+the loss of precision there.
+
+In general, for floating-point comparison to make sense, the user needs to
+carefully choose the error bound. If they don't want or care to, comparing in
+terms of Units in the Last Place (ULPs) is a good default, and Google Test
+provides assertions to do this. Full details about ULPs are quite long; if you
+want to learn more, see
+[this article on float comparison](http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm).
+
+### Floating-Point Macros ###
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_FLOAT_EQ(`_expected, actual_`);`  | `EXPECT_FLOAT_EQ(`_expected, actual_`);` | the two `float` values are almost equal |
+| `ASSERT_DOUBLE_EQ(`_expected, actual_`);` | `EXPECT_DOUBLE_EQ(`_expected, actual_`);` | the two `double` values are almost equal |
+
+By "almost equal", we mean the two values are within 4 ULP's from each
+other.
+
+The following assertions allow you to choose the acceptable error bound:
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_NEAR(`_val1, val2, abs\_error_`);` | `EXPECT_NEAR`_(val1, val2, abs\_error_`);` | the difference between _val1_ and _val2_ doesn't exceed the given absolute error |
+
+_Availability_: Linux, Windows, Mac.
+
+### Floating-Point Predicate-Format Functions ###
+
+Some floating-point operations are useful, but not that often used. In order
+to avoid an explosion of new macros, we provide them as predicate-format
+functions that can be used in predicate assertion macros (e.g.
+`EXPECT_PRED_FORMAT2`, etc).
+
+```
+EXPECT_PRED_FORMAT2(::testing::FloatLE, val1, val2);
+EXPECT_PRED_FORMAT2(::testing::DoubleLE, val1, val2);
+```
+
+Verifies that _val1_ is less than, or almost equal to, _val2_. You can
+replace `EXPECT_PRED_FORMAT2` in the above table with `ASSERT_PRED_FORMAT2`.
+
+_Availability_: Linux, Windows, Mac.
+
+## Windows HRESULT assertions ##
+
+These assertions test for `HRESULT` success or failure.
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_HRESULT_SUCCEEDED(`_expression_`);` | `EXPECT_HRESULT_SUCCEEDED(`_expression_`);` | _expression_ is a success `HRESULT` |
+| `ASSERT_HRESULT_FAILED(`_expression_`);`    | `EXPECT_HRESULT_FAILED(`_expression_`);`    | _expression_ is a failure `HRESULT` |
+
+The generated output contains the human-readable error message
+associated with the `HRESULT` code returned by _expression_.
+
+You might use them like this:
+
+```
+CComPtr shell;
+ASSERT_HRESULT_SUCCEEDED(shell.CoCreateInstance(L"Shell.Application"));
+CComVariant empty;
+ASSERT_HRESULT_SUCCEEDED(shell->ShellExecute(CComBSTR(url), empty, empty, empty, empty));
+```
+
+_Availability_: Windows.
+
+## Type Assertions ##
+
+You can call the function
+```
+::testing::StaticAssertTypeEq<T1, T2>();
+```
+to assert that types `T1` and `T2` are the same.  The function does
+nothing if the assertion is satisfied.  If the types are different,
+the function call will fail to compile, and the compiler error message
+will likely (depending on the compiler) show you the actual values of
+`T1` and `T2`.  This is mainly useful inside template code.
+
+_Caveat:_ When used inside a member function of a class template or a
+function template, `StaticAssertTypeEq<T1, T2>()` is effective _only if_
+the function is instantiated.  For example, given:
+```
+template <typename T> class Foo {
+ public:
+  void Bar() { ::testing::StaticAssertTypeEq<int, T>(); }
+};
+```
+the code:
+```
+void Test1() { Foo<bool> foo; }
+```
+will _not_ generate a compiler error, as `Foo<bool>::Bar()` is never
+actually instantiated.  Instead, you need:
+```
+void Test2() { Foo<bool> foo; foo.Bar(); }
+```
+to cause a compiler error.
+
+_Availability:_ Linux, Windows, Mac; since version 1.3.0.
+
+## Assertion Placement ##
+
+You can use assertions in any C++ function. In particular, it doesn't
+have to be a method of the test fixture class. The one constraint is
+that assertions that generate a fatal failure (`FAIL*` and `ASSERT_*`)
+can only be used in void-returning functions. This is a consequence of
+Google Test not using exceptions. By placing it in a non-void function
+you'll get a confusing compile error like
+`"error: void value not ignored as it ought to be"`.
+
+If you need to use assertions in a function that returns non-void, one option
+is to make the function return the value in an out parameter instead. For
+example, you can rewrite `T2 Foo(T1 x)` to `void Foo(T1 x, T2* result)`. You
+need to make sure that `*result` contains some sensible value even when the
+function returns prematurely. As the function now returns `void`, you can use
+any assertion inside of it.
+
+If changing the function's type is not an option, you should just use
+assertions that generate non-fatal failures, such as `ADD_FAILURE*` and
+`EXPECT_*`.
+
+_Note_: Constructors and destructors are not considered void-returning
+functions, according to the C++ language specification, and so you may not use
+fatal assertions in them. You'll get a compilation error if you try. A simple
+workaround is to transfer the entire body of the constructor or destructor to a
+private void-returning method. However, you should be aware that a fatal
+assertion failure in a constructor does not terminate the current test, as your
+intuition might suggest; it merely returns from the constructor early, possibly
+leaving your object in a partially-constructed state. Likewise, a fatal
+assertion failure in a destructor may leave your object in a
+partially-destructed state. Use assertions carefully in these situations!
+
+# Teaching Google Test How to Print Your Values #
+
+When a test assertion such as `EXPECT_EQ` fails, Google Test prints the
+argument values to help you debug.  It does this using a
+user-extensible value printer.
+
+This printer knows how to print built-in C++ types, native arrays, STL
+containers, and any type that supports the `<<` operator.  For other
+types, it prints the raw bytes in the value and hopes that you the
+user can figure it out.
+
+As mentioned earlier, the printer is _extensible_.  That means
+you can teach it to do a better job at printing your particular type
+than to dump the bytes.  To do that, define `<<` for your type:
+
+```
+#include <iostream>
+
+namespace foo {
+
+class Bar { ... };  // We want Google Test to be able to print instances of this.
+
+// It's important that the << operator is defined in the SAME
+// namespace that defines Bar.  C++'s look-up rules rely on that.
+::std::ostream& operator<<(::std::ostream& os, const Bar& bar) {
+  return os << bar.DebugString();  // whatever needed to print bar to os
+}
+
+}  // namespace foo
+```
+
+Sometimes, this might not be an option: your team may consider it bad
+style to have a `<<` operator for `Bar`, or `Bar` may already have a
+`<<` operator that doesn't do what you want (and you cannot change
+it).  If so, you can instead define a `PrintTo()` function like this:
+
+```
+#include <iostream>
+
+namespace foo {
+
+class Bar { ... };
+
+// It's important that PrintTo() is defined in the SAME
+// namespace that defines Bar.  C++'s look-up rules rely on that.
+void PrintTo(const Bar& bar, ::std::ostream* os) {
+  *os << bar.DebugString();  // whatever needed to print bar to os
+}
+
+}  // namespace foo
+```
+
+If you have defined both `<<` and `PrintTo()`, the latter will be used
+when Google Test is concerned.  This allows you to customize how the value
+appears in Google Test's output without affecting code that relies on the
+behavior of its `<<` operator.
+
+If you want to print a value `x` using Google Test's value printer
+yourself, just call `::testing::PrintToString(`_x_`)`, which
+returns an `std::string`:
+
+```
+vector<pair<Bar, int> > bar_ints = GetBarIntVector();
+
+EXPECT_TRUE(IsCorrectBarIntVector(bar_ints))
+    << "bar_ints = " << ::testing::PrintToString(bar_ints);
+```
+
+# Death Tests #
+
+In many applications, there are assertions that can cause application failure
+if a condition is not met. These sanity checks, which ensure that the program
+is in a known good state, are there to fail at the earliest possible time after
+some program state is corrupted. If the assertion checks the wrong condition,
+then the program may proceed in an erroneous state, which could lead to memory
+corruption, security holes, or worse. Hence it is vitally important to test
+that such assertion statements work as expected.
+
+Since these precondition checks cause the processes to die, we call such tests
+_death tests_. More generally, any test that checks that a program terminates
+(except by throwing an exception) in an expected fashion is also a death test.
+
+Note that if a piece of code throws an exception, we don't consider it "death"
+for the purpose of death tests, as the caller of the code could catch the exception
+and avoid the crash. If you want to verify exceptions thrown by your code,
+see [Exception Assertions](#Exception_Assertions.md).
+
+If you want to test `EXPECT_*()/ASSERT_*()` failures in your test code, see [Catching Failures](#Catching_Failures.md).
+
+## How to Write a Death Test ##
+
+Google Test has the following macros to support death tests:
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_DEATH(`_statement, regex_`); | `EXPECT_DEATH(`_statement, regex_`); | _statement_ crashes with the given error |
+| `ASSERT_DEATH_IF_SUPPORTED(`_statement, regex_`); | `EXPECT_DEATH_IF_SUPPORTED(`_statement, regex_`); | if death tests are supported, verifies that _statement_ crashes with the given error; otherwise verifies nothing |
+| `ASSERT_EXIT(`_statement, predicate, regex_`); | `EXPECT_EXIT(`_statement, predicate, regex_`); |_statement_ exits with the given error and its exit code matches _predicate_ |
+
+where _statement_ is a statement that is expected to cause the process to
+die, _predicate_ is a function or function object that evaluates an integer
+exit status, and _regex_ is a regular expression that the stderr output of
+_statement_ is expected to match. Note that _statement_ can be _any valid
+statement_ (including _compound statement_) and doesn't have to be an
+expression.
+
+As usual, the `ASSERT` variants abort the current test function, while the
+`EXPECT` variants do not.
+
+**Note:** We use the word "crash" here to mean that the process
+terminates with a _non-zero_ exit status code.  There are two
+possibilities: either the process has called `exit()` or `_exit()`
+with a non-zero value, or it may be killed by a signal.
+
+This means that if _statement_ terminates the process with a 0 exit
+code, it is _not_ considered a crash by `EXPECT_DEATH`.  Use
+`EXPECT_EXIT` instead if this is the case, or if you want to restrict
+the exit code more precisely.
+
+A predicate here must accept an `int` and return a `bool`. The death test
+succeeds only if the predicate returns `true`. Google Test defines a few
+predicates that handle the most common cases:
+
+```
+::testing::ExitedWithCode(exit_code)
+```
+
+This expression is `true` if the program exited normally with the given exit
+code.
+
+```
+::testing::KilledBySignal(signal_number)  // Not available on Windows.
+```
+
+This expression is `true` if the program was killed by the given signal.
+
+The `*_DEATH` macros are convenient wrappers for `*_EXIT` that use a predicate
+that verifies the process' exit code is non-zero.
+
+Note that a death test only cares about three things:
+
+  1. does _statement_ abort or exit the process?
+  1. (in the case of `ASSERT_EXIT` and `EXPECT_EXIT`) does the exit status satisfy _predicate_?  Or (in the case of `ASSERT_DEATH` and `EXPECT_DEATH`) is the exit status non-zero?  And
+  1. does the stderr output match _regex_?
+
+In particular, if _statement_ generates an `ASSERT_*` or `EXPECT_*` failure, it will **not** cause the death test to fail, as Google Test assertions don't abort the process.
+
+To write a death test, simply use one of the above macros inside your test
+function. For example,
+
+```
+TEST(My*DeathTest*, Foo) {
+  // This death test uses a compound statement.
+  ASSERT_DEATH({ int n = 5; Foo(&n); }, "Error on line .* of Foo()");
+}
+TEST(MyDeathTest, NormalExit) {
+  EXPECT_EXIT(NormalExit(), ::testing::ExitedWithCode(0), "Success");
+}
+TEST(MyDeathTest, KillMyself) {
+  EXPECT_EXIT(KillMyself(), ::testing::KilledBySignal(SIGKILL), "Sending myself unblockable signal");
+}
+```
+
+verifies that:
+
+  * calling `Foo(5)` causes the process to die with the given error message,
+  * calling `NormalExit()` causes the process to print `"Success"` to stderr and exit with exit code 0, and
+  * calling `KillMyself()` kills the process with signal `SIGKILL`.
+
+The test function body may contain other assertions and statements as well, if
+necessary.
+
+_Important:_ We strongly recommend you to follow the convention of naming your
+test case (not test) `*DeathTest` when it contains a death test, as
+demonstrated in the above example. The `Death Tests And Threads` section below
+explains why.
+
+If a test fixture class is shared by normal tests and death tests, you
+can use typedef to introduce an alias for the fixture class and avoid
+duplicating its code:
+```
+class FooTest : public ::testing::Test { ... };
+
+typedef FooTest FooDeathTest;
+
+TEST_F(FooTest, DoesThis) {
+  // normal test
+}
+
+TEST_F(FooDeathTest, DoesThat) {
+  // death test
+}
+```
+
+_Availability:_ Linux, Windows (requires MSVC 8.0 or above), Cygwin, and Mac (the latter three are supported since v1.3.0).  `(ASSERT|EXPECT)_DEATH_IF_SUPPORTED` are new in v1.4.0.
+
+## Regular Expression Syntax ##
+
+On POSIX systems (e.g. Linux, Cygwin, and Mac), Google Test uses the
+[POSIX extended regular expression](http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap09.html#tag_09_04)
+syntax in death tests. To learn about this syntax, you may want to read this [Wikipedia entry](http://en.wikipedia.org/wiki/Regular_expression#POSIX_Extended_Regular_Expressions).
+
+On Windows, Google Test uses its own simple regular expression
+implementation. It lacks many features you can find in POSIX extended
+regular expressions.  For example, we don't support union (`"x|y"`),
+grouping (`"(xy)"`), brackets (`"[xy]"`), and repetition count
+(`"x{5,7}"`), among others. Below is what we do support (`A` denotes a
+literal character, period (`.`), or a single `\\` escape sequence; `x`
+and `y` denote regular expressions.):
+
+| `c` | matches any literal character `c` |
+|:----|:----------------------------------|
+| `\\d` | matches any decimal digit         |
+| `\\D` | matches any character that's not a decimal digit |
+| `\\f` | matches `\f`                      |
+| `\\n` | matches `\n`                      |
+| `\\r` | matches `\r`                      |
+| `\\s` | matches any ASCII whitespace, including `\n` |
+| `\\S` | matches any character that's not a whitespace |
+| `\\t` | matches `\t`                      |
+| `\\v` | matches `\v`                      |
+| `\\w` | matches any letter, `_`, or decimal digit |
+| `\\W` | matches any character that `\\w` doesn't match |
+| `\\c` | matches any literal character `c`, which must be a punctuation |
+| `.` | matches any single character except `\n` |
+| `A?` | matches 0 or 1 occurrences of `A` |
+| `A*` | matches 0 or many occurrences of `A` |
+| `A+` | matches 1 or many occurrences of `A` |
+| `^` | matches the beginning of a string (not that of each line) |
+| `$` | matches the end of a string (not that of each line) |
+| `xy` | matches `x` followed by `y`       |
+
+To help you determine which capability is available on your system,
+Google Test defines macro `GTEST_USES_POSIX_RE=1` when it uses POSIX
+extended regular expressions, or `GTEST_USES_SIMPLE_RE=1` when it uses
+the simple version.  If you want your death tests to work in both
+cases, you can either `#if` on these macros or use the more limited
+syntax only.
+
+## How It Works ##
+
+Under the hood, `ASSERT_EXIT()` spawns a new process and executes the
+death test statement in that process. The details of of how precisely
+that happens depend on the platform and the variable
+`::testing::GTEST_FLAG(death_test_style)` (which is initialized from the
+command-line flag `--gtest_death_test_style`).
+
+  * On POSIX systems, `fork()` (or `clone()` on Linux) is used to spawn the child, after which:
+    * If the variable's value is `"fast"`, the death test statement is immediately executed.
+    * If the variable's value is `"threadsafe"`, the child process re-executes the unit test binary just as it was originally invoked, but with some extra flags to cause just the single death test under consideration to be run.
+  * On Windows, the child is spawned using the `CreateProcess()` API, and re-executes the binary to cause just the single death test under consideration to be run - much like the `threadsafe` mode on POSIX.
+
+Other values for the variable are illegal and will cause the death test to
+fail. Currently, the flag's default value is `"fast"`. However, we reserve the
+right to change it in the future. Therefore, your tests should not depend on
+this.
+
+In either case, the parent process waits for the child process to complete, and checks that
+
+  1. the child's exit status satisfies the predicate, and
+  1. the child's stderr matches the regular expression.
+
+If the death test statement runs to completion without dying, the child
+process will nonetheless terminate, and the assertion fails.
+
+## Death Tests And Threads ##
+
+The reason for the two death test styles has to do with thread safety. Due to
+well-known problems with forking in the presence of threads, death tests should
+be run in a single-threaded context. Sometimes, however, it isn't feasible to
+arrange that kind of environment. For example, statically-initialized modules
+may start threads before main is ever reached. Once threads have been created,
+it may be difficult or impossible to clean them up.
+
+Google Test has three features intended to raise awareness of threading issues.
+
+  1. A warning is emitted if multiple threads are running when a death test is encountered.
+  1. Test cases with a name ending in "DeathTest" are run before all other tests.
+  1. It uses `clone()` instead of `fork()` to spawn the child process on Linux (`clone()` is not available on Cygwin and Mac), as `fork()` is more likely to cause the child to hang when the parent process has multiple threads.
+
+It's perfectly fine to create threads inside a death test statement; they are
+executed in a separate process and cannot affect the parent.
+
+## Death Test Styles ##
+
+The "threadsafe" death test style was introduced in order to help mitigate the
+risks of testing in a possibly multithreaded environment. It trades increased
+test execution time (potentially dramatically so) for improved thread safety.
+We suggest using the faster, default "fast" style unless your test has specific
+problems with it.
+
+You can choose a particular style of death tests by setting the flag
+programmatically:
+
+```
+::testing::FLAGS_gtest_death_test_style = "threadsafe";
+```
+
+You can do this in `main()` to set the style for all death tests in the
+binary, or in individual tests. Recall that flags are saved before running each
+test and restored afterwards, so you need not do that yourself. For example:
+
+```
+TEST(MyDeathTest, TestOne) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  // This test is run in the "threadsafe" style:
+  ASSERT_DEATH(ThisShouldDie(), "");
+}
+
+TEST(MyDeathTest, TestTwo) {
+  // This test is run in the "fast" style:
+  ASSERT_DEATH(ThisShouldDie(), "");
+}
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  ::testing::FLAGS_gtest_death_test_style = "fast";
+  return RUN_ALL_TESTS();
+}
+```
+
+## Caveats ##
+
+The _statement_ argument of `ASSERT_EXIT()` can be any valid C++ statement.
+If it leaves the current function via a `return` statement or by throwing an exception,
+the death test is considered to have failed.  Some Google Test macros may return
+from the current function (e.g. `ASSERT_TRUE()`), so be sure to avoid them in _statement_.
+
+Since _statement_ runs in the child process, any in-memory side effect (e.g.
+modifying a variable, releasing memory, etc) it causes will _not_ be observable
+in the parent process. In particular, if you release memory in a death test,
+your program will fail the heap check as the parent process will never see the
+memory reclaimed. To solve this problem, you can
+
+  1. try not to free memory in a death test;
+  1. free the memory again in the parent process; or
+  1. do not use the heap checker in your program.
+
+Due to an implementation detail, you cannot place multiple death test
+assertions on the same line; otherwise, compilation will fail with an unobvious
+error message.
+
+Despite the improved thread safety afforded by the "threadsafe" style of death
+test, thread problems such as deadlock are still possible in the presence of
+handlers registered with `pthread_atfork(3)`.
+
+# Using Assertions in Sub-routines #
+
+## Adding Traces to Assertions ##
+
+If a test sub-routine is called from several places, when an assertion
+inside it fails, it can be hard to tell which invocation of the
+sub-routine the failure is from.  You can alleviate this problem using
+extra logging or custom failure messages, but that usually clutters up
+your tests. A better solution is to use the `SCOPED_TRACE` macro:
+
+| `SCOPED_TRACE(`_message_`);` |
+|:-----------------------------|
+
+where _message_ can be anything streamable to `std::ostream`. This
+macro will cause the current file name, line number, and the given
+message to be added in every failure message. The effect will be
+undone when the control leaves the current lexical scope.
+
+For example,
+
+```
+10: void Sub1(int n) {
+11:   EXPECT_EQ(1, Bar(n));
+12:   EXPECT_EQ(2, Bar(n + 1));
+13: }
+14: 
+15: TEST(FooTest, Bar) {
+16:   {
+17:     SCOPED_TRACE("A");  // This trace point will be included in
+18:                         // every failure in this scope.
+19:     Sub1(1);
+20:   }
+21:   // Now it won't.
+22:   Sub1(9);
+23: }
+```
+
+could result in messages like these:
+
+```
+path/to/foo_test.cc:11: Failure
+Value of: Bar(n)
+Expected: 1
+  Actual: 2
+   Trace:
+path/to/foo_test.cc:17: A
+
+path/to/foo_test.cc:12: Failure
+Value of: Bar(n + 1)
+Expected: 2
+  Actual: 3
+```
+
+Without the trace, it would've been difficult to know which invocation
+of `Sub1()` the two failures come from respectively. (You could add an
+extra message to each assertion in `Sub1()` to indicate the value of
+`n`, but that's tedious.)
+
+Some tips on using `SCOPED_TRACE`:
+
+  1. With a suitable message, it's often enough to use `SCOPED_TRACE` at the beginning of a sub-routine, instead of at each call site.
+  1. When calling sub-routines inside a loop, make the loop iterator part of the message in `SCOPED_TRACE` such that you can know which iteration the failure is from.
+  1. Sometimes the line number of the trace point is enough for identifying the particular invocation of a sub-routine. In this case, you don't have to choose a unique message for `SCOPED_TRACE`. You can simply use `""`.
+  1. You can use `SCOPED_TRACE` in an inner scope when there is one in the outer scope. In this case, all active trace points will be included in the failure messages, in reverse order they are encountered.
+  1. The trace dump is clickable in Emacs' compilation buffer - hit return on a line number and you'll be taken to that line in the source file!
+
+_Availability:_ Linux, Windows, Mac.
+
+## Propagating Fatal Failures ##
+
+A common pitfall when using `ASSERT_*` and `FAIL*` is not understanding that
+when they fail they only abort the _current function_, not the entire test. For
+example, the following test will segfault:
+```
+void Subroutine() {
+  // Generates a fatal failure and aborts the current function.
+  ASSERT_EQ(1, 2);
+  // The following won't be executed.
+  ...
+}
+
+TEST(FooTest, Bar) {
+  Subroutine();
+  // The intended behavior is for the fatal failure
+  // in Subroutine() to abort the entire test.
+  // The actual behavior: the function goes on after Subroutine() returns.
+  int* p = NULL;
+  *p = 3; // Segfault!
+}
+```
+
+Since we don't use exceptions, it is technically impossible to
+implement the intended behavior here.  To alleviate this, Google Test
+provides two solutions.  You could use either the
+`(ASSERT|EXPECT)_NO_FATAL_FAILURE` assertions or the
+`HasFatalFailure()` function.  They are described in the following two
+subsections.
+
+### Asserting on Subroutines ###
+
+As shown above, if your test calls a subroutine that has an `ASSERT_*`
+failure in it, the test will continue after the subroutine
+returns. This may not be what you want.
+
+Often people want fatal failures to propagate like exceptions.  For
+that Google Test offers the following macros:
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_NO_FATAL_FAILURE(`_statement_`);` | `EXPECT_NO_FATAL_FAILURE(`_statement_`);` | _statement_ doesn't generate any new fatal failures in the current thread. |
+
+Only failures in the thread that executes the assertion are checked to
+determine the result of this type of assertions.  If _statement_
+creates new threads, failures in these threads are ignored.
+
+Examples:
+
+```
+ASSERT_NO_FATAL_FAILURE(Foo());
+
+int i;
+EXPECT_NO_FATAL_FAILURE({
+  i = Bar();
+});
+```
+
+_Availability:_ Linux, Windows, Mac. Assertions from multiple threads
+are currently not supported.
+
+### Checking for Failures in the Current Test ###
+
+`HasFatalFailure()` in the `::testing::Test` class returns `true` if an
+assertion in the current test has suffered a fatal failure. This
+allows functions to catch fatal failures in a sub-routine and return
+early.
+
+```
+class Test {
+ public:
+  ...
+  static bool HasFatalFailure();
+};
+```
+
+The typical usage, which basically simulates the behavior of a thrown
+exception, is:
+
+```
+TEST(FooTest, Bar) {
+  Subroutine();
+  // Aborts if Subroutine() had a fatal failure.
+  if (HasFatalFailure())
+    return;
+  // The following won't be executed.
+  ...
+}
+```
+
+If `HasFatalFailure()` is used outside of `TEST()` , `TEST_F()` , or a test
+fixture, you must add the `::testing::Test::` prefix, as in:
+
+```
+if (::testing::Test::HasFatalFailure())
+  return;
+```
+
+Similarly, `HasNonfatalFailure()` returns `true` if the current test
+has at least one non-fatal failure, and `HasFailure()` returns `true`
+if the current test has at least one failure of either kind.
+
+_Availability:_ Linux, Windows, Mac.  `HasNonfatalFailure()` and
+`HasFailure()` are available since version 1.4.0.
+
+# Logging Additional Information #
+
+In your test code, you can call `RecordProperty("key", value)` to log
+additional information, where `value` can be either a C string or a 32-bit
+integer. The _last_ value recorded for a key will be emitted to the XML output
+if you specify one. For example, the test
+
+```
+TEST_F(WidgetUsageTest, MinAndMaxWidgets) {
+  RecordProperty("MaximumWidgets", ComputeMaxUsage());
+  RecordProperty("MinimumWidgets", ComputeMinUsage());
+}
+```
+
+will output XML like this:
+
+```
+...
+  <testcase name="MinAndMaxWidgets" status="run" time="6" classname="WidgetUsageTest"
+            MaximumWidgets="12"
+            MinimumWidgets="9" />
+...
+```
+
+_Note_:
+  * `RecordProperty()` is a static member of the `Test` class. Therefore it needs to be prefixed with `::testing::Test::` if used outside of the `TEST` body and the test fixture class.
+  * `key` must be a valid XML attribute name, and cannot conflict with the ones already used by Google Test (`name`, `status`,     `time`, and `classname`).
+
+_Availability_: Linux, Windows, Mac.
+
+# Sharing Resources Between Tests in the Same Test Case #
+
+
+
+Google Test creates a new test fixture object for each test in order to make
+tests independent and easier to debug. However, sometimes tests use resources
+that are expensive to set up, making the one-copy-per-test model prohibitively
+expensive.
+
+If the tests don't change the resource, there's no harm in them sharing a
+single resource copy. So, in addition to per-test set-up/tear-down, Google Test
+also supports per-test-case set-up/tear-down. To use it:
+
+  1. In your test fixture class (say `FooTest` ), define as `static` some member variables to hold the shared resources.
+  1. In the same test fixture class, define a `static void SetUpTestCase()` function (remember not to spell it as **`SetupTestCase`** with a small `u`!) to set up the shared resources and a `static void TearDownTestCase()` function to tear them down.
+
+That's it! Google Test automatically calls `SetUpTestCase()` before running the
+_first test_ in the `FooTest` test case (i.e. before creating the first
+`FooTest` object), and calls `TearDownTestCase()` after running the _last test_
+in it (i.e. after deleting the last `FooTest` object). In between, the tests
+can use the shared resources.
+
+Remember that the test order is undefined, so your code can't depend on a test
+preceding or following another. Also, the tests must either not modify the
+state of any shared resource, or, if they do modify the state, they must
+restore the state to its original value before passing control to the next
+test.
+
+Here's an example of per-test-case set-up and tear-down:
+```
+class FooTest : public ::testing::Test {
+ protected:
+  // Per-test-case set-up.
+  // Called before the first test in this test case.
+  // Can be omitted if not needed.
+  static void SetUpTestCase() {
+    shared_resource_ = new ...;
+  }
+
+  // Per-test-case tear-down.
+  // Called after the last test in this test case.
+  // Can be omitted if not needed.
+  static void TearDownTestCase() {
+    delete shared_resource_;
+    shared_resource_ = NULL;
+  }
+
+  // You can define per-test set-up and tear-down logic as usual.
+  virtual void SetUp() { ... }
+  virtual void TearDown() { ... }
+
+  // Some expensive resource shared by all tests.
+  static T* shared_resource_;
+};
+
+T* FooTest::shared_resource_ = NULL;
+
+TEST_F(FooTest, Test1) {
+  ... you can refer to shared_resource here ...
+}
+TEST_F(FooTest, Test2) {
+  ... you can refer to shared_resource here ...
+}
+```
+
+_Availability:_ Linux, Windows, Mac.
+
+# Global Set-Up and Tear-Down #
+
+Just as you can do set-up and tear-down at the test level and the test case
+level, you can also do it at the test program level. Here's how.
+
+First, you subclass the `::testing::Environment` class to define a test
+environment, which knows how to set-up and tear-down:
+
+```
+class Environment {
+ public:
+  virtual ~Environment() {}
+  // Override this to define how to set up the environment.
+  virtual void SetUp() {}
+  // Override this to define how to tear down the environment.
+  virtual void TearDown() {}
+};
+```
+
+Then, you register an instance of your environment class with Google Test by
+calling the `::testing::AddGlobalTestEnvironment()` function:
+
+```
+Environment* AddGlobalTestEnvironment(Environment* env);
+```
+
+Now, when `RUN_ALL_TESTS()` is called, it first calls the `SetUp()` method of
+the environment object, then runs the tests if there was no fatal failures, and
+finally calls `TearDown()` of the environment object.
+
+It's OK to register multiple environment objects. In this case, their `SetUp()`
+will be called in the order they are registered, and their `TearDown()` will be
+called in the reverse order.
+
+Note that Google Test takes ownership of the registered environment objects.
+Therefore **do not delete them** by yourself.
+
+You should call `AddGlobalTestEnvironment()` before `RUN_ALL_TESTS()` is
+called, probably in `main()`. If you use `gtest_main`, you need to      call
+this before `main()` starts for it to take effect. One way to do this is to
+define a global variable like this:
+
+```
+::testing::Environment* const foo_env = ::testing::AddGlobalTestEnvironment(new FooEnvironment);
+```
+
+However, we strongly recommend you to write your own `main()` and call
+`AddGlobalTestEnvironment()` there, as relying on initialization of global
+variables makes the code harder to read and may cause problems when you
+register multiple environments from different translation units and the
+environments have dependencies among them (remember that the compiler doesn't
+guarantee the order in which global variables from different translation units
+are initialized).
+
+_Availability:_ Linux, Windows, Mac.
+
+
+# Value Parameterized Tests #
+
+_Value-parameterized tests_ allow you to test your code with different
+parameters without writing multiple copies of the same test.
+
+Suppose you write a test for your code and then realize that your code is affected by a presence of a Boolean command line flag.
+
+```
+TEST(MyCodeTest, TestFoo) {
+  // A code to test foo().
+}
+```
+
+Usually people factor their test code into a function with a Boolean parameter in such situations. The function sets the flag, then executes the testing code.
+
+```
+void TestFooHelper(bool flag_value) {
+  flag = flag_value;
+  // A code to test foo().
+}
+
+TEST(MyCodeTest, TestFooo) {
+  TestFooHelper(false);
+  TestFooHelper(true);
+}
+```
+
+But this setup has serious drawbacks. First, when a test assertion fails in your tests, it becomes unclear what value of the parameter caused it to fail. You can stream a clarifying message into your `EXPECT`/`ASSERT` statements, but it you'll have to do it with all of them. Second, you have to add one such helper function per test. What if you have ten tests? Twenty? A hundred?
+
+Value-parameterized tests will let you write your test only once and then easily instantiate and run it with an arbitrary number of parameter values.
+
+Here are some other situations when value-parameterized tests come handy:
+
+  * You want to test different implementations of an OO interface.
+  * You want to test your code over various inputs (a.k.a. data-driven testing). This feature is easy to abuse, so please exercise your good sense when doing it!
+
+## How to Write Value-Parameterized Tests ##
+
+To write value-parameterized tests, first you should define a fixture
+class.  It must be derived from both `::testing::Test` and
+`::testing::WithParamInterface<T>` (the latter is a pure interface),
+where `T` is the type of your parameter values.  For convenience, you
+can just derive the fixture class from `::testing::TestWithParam<T>`,
+which itself is derived from both `::testing::Test` and
+`::testing::WithParamInterface<T>`. `T` can be any copyable type. If
+it's a raw pointer, you are responsible for managing the lifespan of
+the pointed values.
+
+```
+class FooTest : public ::testing::TestWithParam<const char*> {
+  // You can implement all the usual fixture class members here.
+  // To access the test parameter, call GetParam() from class
+  // TestWithParam<T>.
+};
+
+// Or, when you want to add parameters to a pre-existing fixture class:
+class BaseTest : public ::testing::Test {
+  ...
+};
+class BarTest : public BaseTest,
+                public ::testing::WithParamInterface<const char*> {
+  ...
+};
+```
+
+Then, use the `TEST_P` macro to define as many test patterns using
+this fixture as you want.  The `_P` suffix is for "parameterized" or
+"pattern", whichever you prefer to think.
+
+```
+TEST_P(FooTest, DoesBlah) {
+  // Inside a test, access the test parameter with the GetParam() method
+  // of the TestWithParam<T> class:
+  EXPECT_TRUE(foo.Blah(GetParam()));
+  ...
+}
+
+TEST_P(FooTest, HasBlahBlah) {
+  ...
+}
+```
+
+Finally, you can use `INSTANTIATE_TEST_CASE_P` to instantiate the test
+case with any set of parameters you want. Google Test defines a number of
+functions for generating test parameters. They return what we call
+(surprise!) _parameter generators_. Here is a summary of them,
+which are all in the `testing` namespace:
+
+| `Range(begin, end[, step])` | Yields values `{begin, begin+step, begin+step+step, ...}`. The values do not include `end`. `step` defaults to 1. |
+|:----------------------------|:------------------------------------------------------------------------------------------------------------------|
+| `Values(v1, v2, ..., vN)`   | Yields values `{v1, v2, ..., vN}`.                                                                                |
+| `ValuesIn(container)` and `ValuesIn(begin, end)` | Yields values from a C-style array, an STL-style container, or an iterator range `[begin, end)`. `container`, `begin`, and `end` can be expressions whose values are determined at run time.  |
+| `Bool()`                    | Yields sequence `{false, true}`.                                                                                  |
+| `Combine(g1, g2, ..., gN)`  | Yields all combinations (the Cartesian product for the math savvy) of the values generated by the `N` generators. This is only available if your system provides the `<tr1/tuple>` header. If you are sure your system does, and Google Test disagrees, you can override it by defining `GTEST_HAS_TR1_TUPLE=1`. See comments in [include/gtest/internal/gtest-port.h](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/internal/gtest-port.h) for more information. |
+
+For more details, see the comments at the definitions of these functions in the [source code](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest-param-test.h).
+
+The following statement will instantiate tests from the `FooTest` test case
+each with parameter values `"meeny"`, `"miny"`, and `"moe"`.
+
+```
+INSTANTIATE_TEST_CASE_P(InstantiationName,
+                        FooTest,
+                        ::testing::Values("meeny", "miny", "moe"));
+```
+
+To distinguish different instances of the pattern (yes, you can
+instantiate it more than once), the first argument to
+`INSTANTIATE_TEST_CASE_P` is a prefix that will be added to the actual
+test case name. Remember to pick unique prefixes for different
+instantiations. The tests from the instantiation above will have these
+names:
+
+  * `InstantiationName/FooTest.DoesBlah/0` for `"meeny"`
+  * `InstantiationName/FooTest.DoesBlah/1` for `"miny"`
+  * `InstantiationName/FooTest.DoesBlah/2` for `"moe"`
+  * `InstantiationName/FooTest.HasBlahBlah/0` for `"meeny"`
+  * `InstantiationName/FooTest.HasBlahBlah/1` for `"miny"`
+  * `InstantiationName/FooTest.HasBlahBlah/2` for `"moe"`
+
+You can use these names in [--gtest\_filter](#Running_a_Subset_of_the_Tests.md).
+
+This statement will instantiate all tests from `FooTest` again, each
+with parameter values `"cat"` and `"dog"`:
+
+```
+const char* pets[] = {"cat", "dog"};
+INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest,
+                        ::testing::ValuesIn(pets));
+```
+
+The tests from the instantiation above will have these names:
+
+  * `AnotherInstantiationName/FooTest.DoesBlah/0` for `"cat"`
+  * `AnotherInstantiationName/FooTest.DoesBlah/1` for `"dog"`
+  * `AnotherInstantiationName/FooTest.HasBlahBlah/0` for `"cat"`
+  * `AnotherInstantiationName/FooTest.HasBlahBlah/1` for `"dog"`
+
+Please note that `INSTANTIATE_TEST_CASE_P` will instantiate _all_
+tests in the given test case, whether their definitions come before or
+_after_ the `INSTANTIATE_TEST_CASE_P` statement.
+
+You can see
+[these](http://code.google.com/p/googletest/source/browse/trunk/samples/sample7_unittest.cc)
+[files](http://code.google.com/p/googletest/source/browse/trunk/samples/sample8_unittest.cc) for more examples.
+
+_Availability_: Linux, Windows (requires MSVC 8.0 or above), Mac; since version 1.2.0.
+
+## Creating Value-Parameterized Abstract Tests ##
+
+In the above, we define and instantiate `FooTest` in the same source
+file. Sometimes you may want to define value-parameterized tests in a
+library and let other people instantiate them later. This pattern is
+known as <i>abstract tests</i>. As an example of its application, when you
+are designing an interface you can write a standard suite of abstract
+tests (perhaps using a factory function as the test parameter) that
+all implementations of the interface are expected to pass. When
+someone implements the interface, he can instantiate your suite to get
+all the interface-conformance tests for free.
+
+To define abstract tests, you should organize your code like this:
+
+  1. Put the definition of the parameterized test fixture class (e.g. `FooTest`) in a header file, say `foo_param_test.h`. Think of this as _declaring_ your abstract tests.
+  1. Put the `TEST_P` definitions in `foo_param_test.cc`, which includes `foo_param_test.h`. Think of this as _implementing_ your abstract tests.
+
+Once they are defined, you can instantiate them by including
+`foo_param_test.h`, invoking `INSTANTIATE_TEST_CASE_P()`, and linking
+with `foo_param_test.cc`. You can instantiate the same abstract test
+case multiple times, possibly in different source files.
+
+# Typed Tests #
+
+Suppose you have multiple implementations of the same interface and
+want to make sure that all of them satisfy some common requirements.
+Or, you may have defined several types that are supposed to conform to
+the same "concept" and you want to verify it.  In both cases, you want
+the same test logic repeated for different types.
+
+While you can write one `TEST` or `TEST_F` for each type you want to
+test (and you may even factor the test logic into a function template
+that you invoke from the `TEST`), it's tedious and doesn't scale:
+if you want _m_ tests over _n_ types, you'll end up writing _m\*n_
+`TEST`s.
+
+_Typed tests_ allow you to repeat the same test logic over a list of
+types.  You only need to write the test logic once, although you must
+know the type list when writing typed tests.  Here's how you do it:
+
+First, define a fixture class template.  It should be parameterized
+by a type.  Remember to derive it from `::testing::Test`:
+
+```
+template <typename T>
+class FooTest : public ::testing::Test {
+ public:
+  ...
+  typedef std::list<T> List;
+  static T shared_;
+  T value_;
+};
+```
+
+Next, associate a list of types with the test case, which will be
+repeated for each type in the list:
+
+```
+typedef ::testing::Types<char, int, unsigned int> MyTypes;
+TYPED_TEST_CASE(FooTest, MyTypes);
+```
+
+The `typedef` is necessary for the `TYPED_TEST_CASE` macro to parse
+correctly.  Otherwise the compiler will think that each comma in the
+type list introduces a new macro argument.
+
+Then, use `TYPED_TEST()` instead of `TEST_F()` to define a typed test
+for this test case.  You can repeat this as many times as you want:
+
+```
+TYPED_TEST(FooTest, DoesBlah) {
+  // Inside a test, refer to the special name TypeParam to get the type
+  // parameter.  Since we are inside a derived class template, C++ requires
+  // us to visit the members of FooTest via 'this'.
+  TypeParam n = this->value_;
+
+  // To visit static members of the fixture, add the 'TestFixture::'
+  // prefix.
+  n += TestFixture::shared_;
+
+  // To refer to typedefs in the fixture, add the 'typename TestFixture::'
+  // prefix.  The 'typename' is required to satisfy the compiler.
+  typename TestFixture::List values;
+  values.push_back(n);
+  ...
+}
+
+TYPED_TEST(FooTest, HasPropertyA) { ... }
+```
+
+You can see `samples/sample6_unittest.cc` for a complete example.
+
+_Availability:_ Linux, Windows (requires MSVC 8.0 or above), Mac;
+since version 1.1.0.
+
+# Type-Parameterized Tests #
+
+_Type-parameterized tests_ are like typed tests, except that they
+don't require you to know the list of types ahead of time.  Instead,
+you can define the test logic first and instantiate it with different
+type lists later.  You can even instantiate it more than once in the
+same program.
+
+If you are designing an interface or concept, you can define a suite
+of type-parameterized tests to verify properties that any valid
+implementation of the interface/concept should have.  Then, the author
+of each implementation can just instantiate the test suite with his
+type to verify that it conforms to the requirements, without having to
+write similar tests repeatedly.  Here's an example:
+
+First, define a fixture class template, as we did with typed tests:
+
+```
+template <typename T>
+class FooTest : public ::testing::Test {
+  ...
+};
+```
+
+Next, declare that you will define a type-parameterized test case:
+
+```
+TYPED_TEST_CASE_P(FooTest);
+```
+
+The `_P` suffix is for "parameterized" or "pattern", whichever you
+prefer to think.
+
+Then, use `TYPED_TEST_P()` to define a type-parameterized test.  You
+can repeat this as many times as you want:
+
+```
+TYPED_TEST_P(FooTest, DoesBlah) {
+  // Inside a test, refer to TypeParam to get the type parameter.
+  TypeParam n = 0;
+  ...
+}
+
+TYPED_TEST_P(FooTest, HasPropertyA) { ... }
+```
+
+Now the tricky part: you need to register all test patterns using the
+`REGISTER_TYPED_TEST_CASE_P` macro before you can instantiate them.
+The first argument of the macro is the test case name; the rest are
+the names of the tests in this test case:
+
+```
+REGISTER_TYPED_TEST_CASE_P(FooTest,
+                           DoesBlah, HasPropertyA);
+```
+
+Finally, you are free to instantiate the pattern with the types you
+want.  If you put the above code in a header file, you can `#include`
+it in multiple C++ source files and instantiate it multiple times.
+
+```
+typedef ::testing::Types<char, int, unsigned int> MyTypes;
+INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
+```
+
+To distinguish different instances of the pattern, the first argument
+to the `INSTANTIATE_TYPED_TEST_CASE_P` macro is a prefix that will be
+added to the actual test case name.  Remember to pick unique prefixes
+for different instances.
+
+In the special case where the type list contains only one type, you
+can write that type directly without `::testing::Types<...>`, like this:
+
+```
+INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int);
+```
+
+You can see `samples/sample6_unittest.cc` for a complete example.
+
+_Availability:_ Linux, Windows (requires MSVC 8.0 or above), Mac;
+since version 1.1.0.
+
+# Testing Private Code #
+
+If you change your software's internal implementation, your tests should not
+break as long as the change is not observable by users. Therefore, per the
+_black-box testing principle_, most of the time you should test your code
+through its public interfaces.
+
+If you still find yourself needing to test internal implementation code,
+consider if there's a better design that wouldn't require you to do so. If you
+absolutely have to test non-public interface code though, you can. There are
+two cases to consider:
+
+  * Static functions (_not_ the same as static member functions!) or unnamed namespaces, and
+  * Private or protected class members
+
+## Static Functions ##
+
+Both static functions and definitions/declarations in an unnamed namespace are
+only visible within the same translation unit. To test them, you can `#include`
+the entire `.cc` file being tested in your `*_test.cc` file. (#including `.cc`
+files is not a good way to reuse code - you should not do this in production
+code!)
+
+However, a better approach is to move the private code into the
+`foo::internal` namespace, where `foo` is the namespace your project normally
+uses, and put the private declarations in a `*-internal.h` file. Your
+production `.cc` files and your tests are allowed to include this internal
+header, but your clients are not. This way, you can fully test your internal
+implementation without leaking it to your clients.
+
+## Private Class Members ##
+
+Private class members are only accessible from within the class or by friends.
+To access a class' private members, you can declare your test fixture as a
+friend to the class and define accessors in your fixture. Tests using the
+fixture can then access the private members of your production class via the
+accessors in the fixture. Note that even though your fixture is a friend to
+your production class, your tests are not automatically friends to it, as they
+are technically defined in sub-classes of the fixture.
+
+Another way to test private members is to refactor them into an implementation
+class, which is then declared in a `*-internal.h` file. Your clients aren't
+allowed to include this header but your tests can. Such is called the Pimpl
+(Private Implementation) idiom.
+
+Or, you can declare an individual test as a friend of your class by adding this
+line in the class body:
+
+```
+FRIEND_TEST(TestCaseName, TestName);
+```
+
+For example,
+```
+// foo.h
+#include "gtest/gtest_prod.h"
+
+// Defines FRIEND_TEST.
+class Foo {
+  ...
+ private:
+  FRIEND_TEST(FooTest, BarReturnsZeroOnNull);
+  int Bar(void* x);
+};
+
+// foo_test.cc
+...
+TEST(FooTest, BarReturnsZeroOnNull) {
+  Foo foo;
+  EXPECT_EQ(0, foo.Bar(NULL));
+  // Uses Foo's private member Bar().
+}
+```
+
+Pay special attention when your class is defined in a namespace, as you should
+define your test fixtures and tests in the same namespace if you want them to
+be friends of your class. For example, if the code to be tested looks like:
+
+```
+namespace my_namespace {
+
+class Foo {
+  friend class FooTest;
+  FRIEND_TEST(FooTest, Bar);
+  FRIEND_TEST(FooTest, Baz);
+  ...
+  definition of the class Foo
+  ...
+};
+
+}  // namespace my_namespace
+```
+
+Your test code should be something like:
+
+```
+namespace my_namespace {
+class FooTest : public ::testing::Test {
+ protected:
+  ...
+};
+
+TEST_F(FooTest, Bar) { ... }
+TEST_F(FooTest, Baz) { ... }
+
+}  // namespace my_namespace
+```
+
+# Catching Failures #
+
+If you are building a testing utility on top of Google Test, you'll
+want to test your utility.  What framework would you use to test it?
+Google Test, of course.
+
+The challenge is to verify that your testing utility reports failures
+correctly.  In frameworks that report a failure by throwing an
+exception, you could catch the exception and assert on it.  But Google
+Test doesn't use exceptions, so how do we test that a piece of code
+generates an expected failure?
+
+`"gtest/gtest-spi.h"` contains some constructs to do this.  After
+#including this header, you can use
+
+| `EXPECT_FATAL_FAILURE(`_statement, substring_`);` |
+|:--------------------------------------------------|
+
+to assert that _statement_ generates a fatal (e.g. `ASSERT_*`) failure
+whose message contains the given _substring_, or use
+
+| `EXPECT_NONFATAL_FAILURE(`_statement, substring_`);` |
+|:-----------------------------------------------------|
+
+if you are expecting a non-fatal (e.g. `EXPECT_*`) failure.
+
+For technical reasons, there are some caveats:
+
+  1. You cannot stream a failure message to either macro.
+  1. _statement_ in `EXPECT_FATAL_FAILURE()` cannot reference local non-static variables or non-static members of `this` object.
+  1. _statement_ in `EXPECT_FATAL_FAILURE()` cannot return a value.
+
+_Note:_ Google Test is designed with threads in mind.  Once the
+synchronization primitives in `"gtest/internal/gtest-port.h"` have
+been implemented, Google Test will become thread-safe, meaning that
+you can then use assertions in multiple threads concurrently.  Before
+
+that, however, Google Test only supports single-threaded usage.  Once
+thread-safe, `EXPECT_FATAL_FAILURE()` and `EXPECT_NONFATAL_FAILURE()`
+will capture failures in the current thread only. If _statement_
+creates new threads, failures in these threads will be ignored.  If
+you want to capture failures from all threads instead, you should use
+the following macros:
+
+| `EXPECT_FATAL_FAILURE_ON_ALL_THREADS(`_statement, substring_`);` |
+|:-----------------------------------------------------------------|
+| `EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(`_statement, substring_`);` |
+
+# Getting the Current Test's Name #
+
+Sometimes a function may need to know the name of the currently running test.
+For example, you may be using the `SetUp()` method of your test fixture to set
+the golden file name based on which test is running. The `::testing::TestInfo`
+class has this information:
+
+```
+namespace testing {
+
+class TestInfo {
+ public:
+  // Returns the test case name and the test name, respectively.
+  //
+  // Do NOT delete or free the return value - it's managed by the
+  // TestInfo class.
+  const char* test_case_name() const;
+  const char* name() const;
+};
+
+}  // namespace testing
+```
+
+
+> To obtain a `TestInfo` object for the currently running test, call
+`current_test_info()` on the `UnitTest` singleton object:
+
+```
+// Gets information about the currently running test.
+// Do NOT delete the returned object - it's managed by the UnitTest class.
+const ::testing::TestInfo* const test_info =
+  ::testing::UnitTest::GetInstance()->current_test_info();
+printf("We are in test %s of test case %s.\n",
+       test_info->name(), test_info->test_case_name());
+```
+
+`current_test_info()` returns a null pointer if no test is running. In
+particular, you cannot find the test case name in `TestCaseSetUp()`,
+`TestCaseTearDown()` (where you know the test case name implicitly), or
+functions called from them.
+
+_Availability:_ Linux, Windows, Mac.
+
+# Extending Google Test by Handling Test Events #
+
+Google Test provides an <b>event listener API</b> to let you receive
+notifications about the progress of a test program and test
+failures. The events you can listen to include the start and end of
+the test program, a test case, or a test method, among others. You may
+use this API to augment or replace the standard console output,
+replace the XML output, or provide a completely different form of
+output, such as a GUI or a database. You can also use test events as
+checkpoints to implement a resource leak checker, for example.
+
+_Availability:_ Linux, Windows, Mac; since v1.4.0.
+
+## Defining Event Listeners ##
+
+To define a event listener, you subclass either
+[testing::TestEventListener](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest.h#855)
+or [testing::EmptyTestEventListener](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest.h#905).
+The former is an (abstract) interface, where <i>each pure virtual method<br>
+can be overridden to handle a test event</i> (For example, when a test
+starts, the `OnTestStart()` method will be called.). The latter provides
+an empty implementation of all methods in the interface, such that a
+subclass only needs to override the methods it cares about.
+
+When an event is fired, its context is passed to the handler function
+as an argument. The following argument types are used:
+  * [UnitTest](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest.h#1007) reflects the state of the entire test program,
+  * [TestCase](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest.h#689) has information about a test case, which can contain one or more tests,
+  * [TestInfo](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest.h#599) contains the state of a test, and
+  * [TestPartResult](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest-test-part.h#42) represents the result of a test assertion.
+
+An event handler function can examine the argument it receives to find
+out interesting information about the event and the test program's
+state.  Here's an example:
+
+```
+  class MinimalistPrinter : public ::testing::EmptyTestEventListener {
+    // Called before a test starts.
+    virtual void OnTestStart(const ::testing::TestInfo& test_info) {
+      printf("*** Test %s.%s starting.\n",
+             test_info.test_case_name(), test_info.name());
+    }
+
+    // Called after a failed assertion or a SUCCEED() invocation.
+    virtual void OnTestPartResult(
+        const ::testing::TestPartResult& test_part_result) {
+      printf("%s in %s:%d\n%s\n",
+             test_part_result.failed() ? "*** Failure" : "Success",
+             test_part_result.file_name(),
+             test_part_result.line_number(),
+             test_part_result.summary());
+    }
+
+    // Called after a test ends.
+    virtual void OnTestEnd(const ::testing::TestInfo& test_info) {
+      printf("*** Test %s.%s ending.\n",
+             test_info.test_case_name(), test_info.name());
+    }
+  };
+```
+
+## Using Event Listeners ##
+
+To use the event listener you have defined, add an instance of it to
+the Google Test event listener list (represented by class
+[TestEventListeners](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest.h#929)
+- note the "s" at the end of the name) in your
+`main()` function, before calling `RUN_ALL_TESTS()`:
+```
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  // Gets hold of the event listener list.
+  ::testing::TestEventListeners& listeners =
+      ::testing::UnitTest::GetInstance()->listeners();
+  // Adds a listener to the end.  Google Test takes the ownership.
+  listeners.Append(new MinimalistPrinter);
+  return RUN_ALL_TESTS();
+}
+```
+
+There's only one problem: the default test result printer is still in
+effect, so its output will mingle with the output from your minimalist
+printer. To suppress the default printer, just release it from the
+event listener list and delete it. You can do so by adding one line:
+```
+  ...
+  delete listeners.Release(listeners.default_result_printer());
+  listeners.Append(new MinimalistPrinter);
+  return RUN_ALL_TESTS();
+```
+
+Now, sit back and enjoy a completely different output from your
+tests. For more details, you can read this
+[sample](http://code.google.com/p/googletest/source/browse/trunk/samples/sample9_unittest.cc).
+
+You may append more than one listener to the list. When an `On*Start()`
+or `OnTestPartResult()` event is fired, the listeners will receive it in
+the order they appear in the list (since new listeners are added to
+the end of the list, the default text printer and the default XML
+generator will receive the event first). An `On*End()` event will be
+received by the listeners in the _reverse_ order. This allows output by
+listeners added later to be framed by output from listeners added
+earlier.
+
+## Generating Failures in Listeners ##
+
+You may use failure-raising macros (`EXPECT_*()`, `ASSERT_*()`,
+`FAIL()`, etc) when processing an event. There are some restrictions:
+
+  1. You cannot generate any failure in `OnTestPartResult()` (otherwise it will cause `OnTestPartResult()` to be called recursively).
+  1. A listener that handles `OnTestPartResult()` is not allowed to generate any failure.
+
+When you add listeners to the listener list, you should put listeners
+that handle `OnTestPartResult()` _before_ listeners that can generate
+failures. This ensures that failures generated by the latter are
+attributed to the right test by the former.
+
+We have a sample of failure-raising listener
+[here](http://code.google.com/p/googletest/source/browse/trunk/samples/sample10_unittest.cc).
+
+# Running Test Programs: Advanced Options #
+
+Google Test test programs are ordinary executables. Once built, you can run
+them directly and affect their behavior via the following environment variables
+and/or command line flags. For the flags to work, your programs must call
+`::testing::InitGoogleTest()` before calling `RUN_ALL_TESTS()`.
+
+To see a list of supported flags and their usage, please run your test
+program with the `--help` flag.  You can also use `-h`, `-?`, or `/?`
+for short.  This feature is added in version 1.3.0.
+
+If an option is specified both by an environment variable and by a
+flag, the latter takes precedence.  Most of the options can also be
+set/read in code: to access the value of command line flag
+`--gtest_foo`, write `::testing::GTEST_FLAG(foo)`.  A common pattern is
+to set the value of a flag before calling `::testing::InitGoogleTest()`
+to change the default value of the flag:
+```
+int main(int argc, char** argv) {
+  // Disables elapsed time by default.
+  ::testing::GTEST_FLAG(print_time) = false;
+
+  // This allows the user to override the flag on the command line.
+  ::testing::InitGoogleTest(&argc, argv);
+
+  return RUN_ALL_TESTS();
+}
+```
+
+## Selecting Tests ##
+
+This section shows various options for choosing which tests to run.
+
+### Listing Test Names ###
+
+Sometimes it is necessary to list the available tests in a program before
+running them so that a filter may be applied if needed. Including the flag
+`--gtest_list_tests` overrides all other flags and lists tests in the following
+format:
+```
+TestCase1.
+  TestName1
+  TestName2
+TestCase2.
+  TestName
+```
+
+None of the tests listed are actually run if the flag is provided. There is no
+corresponding environment variable for this flag.
+
+_Availability:_ Linux, Windows, Mac.
+
+### Running a Subset of the Tests ###
+
+By default, a Google Test program runs all tests the user has defined.
+Sometimes, you want to run only a subset of the tests (e.g. for debugging or
+quickly verifying a change). If you set the `GTEST_FILTER` environment variable
+or the `--gtest_filter` flag to a filter string, Google Test will only run the
+tests whose full names (in the form of `TestCaseName.TestName`) match the
+filter.
+
+The format of a filter is a '`:`'-separated list of wildcard patterns (called
+the positive patterns) optionally followed by a '`-`' and another
+'`:`'-separated pattern list (called the negative patterns). A test matches the
+filter if and only if it matches any of the positive patterns but does not
+match any of the negative patterns.
+
+A pattern may contain `'*'` (matches any string) or `'?'` (matches any single
+character). For convenience, the filter `'*-NegativePatterns'` can be also
+written as `'-NegativePatterns'`.
+
+For example:
+
+  * `./foo_test` Has no flag, and thus runs all its tests.
+  * `./foo_test --gtest_filter=*` Also runs everything, due to the single match-everything `*` value.
+  * `./foo_test --gtest_filter=FooTest.*` Runs everything in test case `FooTest`.
+  * `./foo_test --gtest_filter=*Null*:*Constructor*` Runs any test whose full name contains either `"Null"` or `"Constructor"`.
+  * `./foo_test --gtest_filter=-*DeathTest.*` Runs all non-death tests.
+  * `./foo_test --gtest_filter=FooTest.*-FooTest.Bar` Runs everything in test case `FooTest` except `FooTest.Bar`.
+
+_Availability:_ Linux, Windows, Mac.
+
+### Temporarily Disabling Tests ###
+
+If you have a broken test that you cannot fix right away, you can add the
+`DISABLED_` prefix to its name. This will exclude it from execution. This is
+better than commenting out the code or using `#if 0`, as disabled tests are
+still compiled (and thus won't rot).
+
+If you need to disable all tests in a test case, you can either add `DISABLED_`
+to the front of the name of each test, or alternatively add it to the front of
+the test case name.
+
+For example, the following tests won't be run by Google Test, even though they
+will still be compiled:
+
+```
+// Tests that Foo does Abc.
+TEST(FooTest, DISABLED_DoesAbc) { ... }
+
+class DISABLED_BarTest : public ::testing::Test { ... };
+
+// Tests that Bar does Xyz.
+TEST_F(DISABLED_BarTest, DoesXyz) { ... }
+```
+
+_Note:_ This feature should only be used for temporary pain-relief. You still
+have to fix the disabled tests at a later date. As a reminder, Google Test will
+print a banner warning you if a test program contains any disabled tests.
+
+_Tip:_ You can easily count the number of disabled tests you have
+using `grep`. This number can be used as a metric for improving your
+test quality.
+
+_Availability:_ Linux, Windows, Mac.
+
+### Temporarily Enabling Disabled Tests ###
+
+To include [disabled tests](#Temporarily_Disabling_Tests.md) in test
+execution, just invoke the test program with the
+`--gtest_also_run_disabled_tests` flag or set the
+`GTEST_ALSO_RUN_DISABLED_TESTS` environment variable to a value other
+than `0`.  You can combine this with the
+[--gtest\_filter](#Running_a_Subset_of_the_Tests.md) flag to further select
+which disabled tests to run.
+
+_Availability:_ Linux, Windows, Mac; since version 1.3.0.
+
+## Repeating the Tests ##
+
+Once in a while you'll run into a test whose result is hit-or-miss. Perhaps it
+will fail only 1% of the time, making it rather hard to reproduce the bug under
+a debugger. This can be a major source of frustration.
+
+The `--gtest_repeat` flag allows you to repeat all (or selected) test methods
+in a program many times. Hopefully, a flaky test will eventually fail and give
+you a chance to debug. Here's how to use it:
+
+| `$ foo_test --gtest_repeat=1000` | Repeat foo\_test 1000 times and don't stop at failures. |
+|:---------------------------------|:--------------------------------------------------------|
+| `$ foo_test --gtest_repeat=-1`   | A negative count means repeating forever.               |
+| `$ foo_test --gtest_repeat=1000 --gtest_break_on_failure` | Repeat foo\_test 1000 times, stopping at the first failure. This is especially useful when running under a debugger: when the testfails, it will drop into the debugger and you can then inspect variables and stacks. |
+| `$ foo_test --gtest_repeat=1000 --gtest_filter=FooBar` | Repeat the tests whose name matches the filter 1000 times. |
+
+If your test program contains global set-up/tear-down code registered
+using `AddGlobalTestEnvironment()`, it will be repeated in each
+iteration as well, as the flakiness may be in it. You can also specify
+the repeat count by setting the `GTEST_REPEAT` environment variable.
+
+_Availability:_ Linux, Windows, Mac.
+
+## Shuffling the Tests ##
+
+You can specify the `--gtest_shuffle` flag (or set the `GTEST_SHUFFLE`
+environment variable to `1`) to run the tests in a program in a random
+order. This helps to reveal bad dependencies between tests.
+
+By default, Google Test uses a random seed calculated from the current
+time. Therefore you'll get a different order every time. The console
+output includes the random seed value, such that you can reproduce an
+order-related test failure later. To specify the random seed
+explicitly, use the `--gtest_random_seed=SEED` flag (or set the
+`GTEST_RANDOM_SEED` environment variable), where `SEED` is an integer
+between 0 and 99999. The seed value 0 is special: it tells Google Test
+to do the default behavior of calculating the seed from the current
+time.
+
+If you combine this with `--gtest_repeat=N`, Google Test will pick a
+different random seed and re-shuffle the tests in each iteration.
+
+_Availability:_ Linux, Windows, Mac; since v1.4.0.
+
+## Controlling Test Output ##
+
+This section teaches how to tweak the way test results are reported.
+
+### Colored Terminal Output ###
+
+Google Test can use colors in its terminal output to make it easier to spot
+the separation between tests, and whether tests passed.
+
+You can set the GTEST\_COLOR environment variable or set the `--gtest_color`
+command line flag to `yes`, `no`, or `auto` (the default) to enable colors,
+disable colors, or let Google Test decide. When the value is `auto`, Google
+Test will use colors if and only if the output goes to a terminal and (on
+non-Windows platforms) the `TERM` environment variable is set to `xterm` or
+`xterm-color`.
+
+_Availability:_ Linux, Windows, Mac.
+
+### Suppressing the Elapsed Time ###
+
+By default, Google Test prints the time it takes to run each test.  To
+suppress that, run the test program with the `--gtest_print_time=0`
+command line flag.  Setting the `GTEST_PRINT_TIME` environment
+variable to `0` has the same effect.
+
+_Availability:_ Linux, Windows, Mac.  (In Google Test 1.3.0 and lower,
+the default behavior is that the elapsed time is **not** printed.)
+
+### Generating an XML Report ###
+
+Google Test can emit a detailed XML report to a file in addition to its normal
+textual output. The report contains the duration of each test, and thus can
+help you identify slow tests.
+
+To generate the XML report, set the `GTEST_OUTPUT` environment variable or the
+`--gtest_output` flag to the string `"xml:_path_to_output_file_"`, which will
+create the file at the given location. You can also just use the string
+`"xml"`, in which case the output can be found in the `test_detail.xml` file in
+the current directory.
+
+If you specify a directory (for example, `"xml:output/directory/"` on Linux or
+`"xml:output\directory\"` on Windows), Google Test will create the XML file in
+that directory, named after the test executable (e.g. `foo_test.xml` for test
+program `foo_test` or `foo_test.exe`). If the file already exists (perhaps left
+over from a previous run), Google Test will pick a different name (e.g.
+`foo_test_1.xml`) to avoid overwriting it.
+
+The report uses the format described here.  It is based on the
+`junitreport` Ant task and can be parsed by popular continuous build
+systems like [Hudson](https://hudson.dev.java.net/). Since that format
+was originally intended for Java, a little interpretation is required
+to make it apply to Google Test tests, as shown here:
+
+```
+<testsuites name="AllTests" ...>
+  <testsuite name="test_case_name" ...>
+    <testcase name="test_name" ...>
+      <failure message="..."/>
+      <failure message="..."/>
+      <failure message="..."/>
+    </testcase>
+  </testsuite>
+</testsuites>
+```
+
+  * The root `<testsuites>` element corresponds to the entire test program.
+  * `<testsuite>` elements correspond to Google Test test cases.
+  * `<testcase>` elements correspond to Google Test test functions.
+
+For instance, the following program
+
+```
+TEST(MathTest, Addition) { ... }
+TEST(MathTest, Subtraction) { ... }
+TEST(LogicTest, NonContradiction) { ... }
+```
+
+could generate this report:
+
+```
+<?xml version="1.0" encoding="UTF-8"?>
+<testsuites tests="3" failures="1" errors="0" time="35" name="AllTests">
+  <testsuite name="MathTest" tests="2" failures="1" errors="0" time="15">
+    <testcase name="Addition" status="run" time="7" classname="">
+      <failure message="Value of: add(1, 1)&#x0A; Actual: 3&#x0A;Expected: 2" type=""/>
+      <failure message="Value of: add(1, -1)&#x0A; Actual: 1&#x0A;Expected: 0" type=""/>
+    </testcase>
+    <testcase name="Subtraction" status="run" time="5" classname="">
+    </testcase>
+  </testsuite>
+  <testsuite name="LogicTest" tests="1" failures="0" errors="0" time="5">
+    <testcase name="NonContradiction" status="run" time="5" classname="">
+    </testcase>
+  </testsuite>
+</testsuites>
+```
+
+Things to note:
+
+  * The `tests` attribute of a `<testsuites>` or `<testsuite>` element tells how many test functions the Google Test program or test case contains, while the `failures` attribute tells how many of them failed.
+  * The `time` attribute expresses the duration of the test, test case, or entire test program in milliseconds.
+  * Each `<failure>` element corresponds to a single failed Google Test assertion.
+  * Some JUnit concepts don't apply to Google Test, yet we have to conform to the DTD. Therefore you'll see some dummy elements and attributes in the report. You can safely ignore these parts.
+
+_Availability:_ Linux, Windows, Mac.
+
+## Controlling How Failures Are Reported ##
+
+### Turning Assertion Failures into Break-Points ###
+
+When running test programs under a debugger, it's very convenient if the
+debugger can catch an assertion failure and automatically drop into interactive
+mode. Google Test's _break-on-failure_ mode supports this behavior.
+
+To enable it, set the `GTEST_BREAK_ON_FAILURE` environment variable to a value
+other than `0` . Alternatively, you can use the `--gtest_break_on_failure`
+command line flag.
+
+_Availability:_ Linux, Windows, Mac.
+
+### Disabling Catching Test-Thrown Exceptions ###
+
+Google Test can be used either with or without exceptions enabled.  If
+a test throws a C++ exception or (on Windows) a structured exception
+(SEH), by default Google Test catches it, reports it as a test
+failure, and continues with the next test method.  This maximizes the
+coverage of a test run.  Also, on Windows an uncaught exception will
+cause a pop-up window, so catching the exceptions allows you to run
+the tests automatically.
+
+When debugging the test failures, however, you may instead want the
+exceptions to be handled by the debugger, such that you can examine
+the call stack when an exception is thrown.  To achieve that, set the
+`GTEST_CATCH_EXCEPTIONS` environment variable to `0`, or use the
+`--gtest_catch_exceptions=0` flag when running the tests.
+
+**Availability**: Linux, Windows, Mac.
+
+### Letting Another Testing Framework Drive ###
+
+If you work on a project that has already been using another testing
+framework and is not ready to completely switch to Google Test yet,
+you can get much of Google Test's benefit by using its assertions in
+your existing tests.  Just change your `main()` function to look
+like:
+
+```
+#include "gtest/gtest.h"
+
+int main(int argc, char** argv) {
+  ::testing::GTEST_FLAG(throw_on_failure) = true;
+  // Important: Google Test must be initialized.
+  ::testing::InitGoogleTest(&argc, argv);
+
+  ... whatever your existing testing framework requires ...
+}
+```
+
+With that, you can use Google Test assertions in addition to the
+native assertions your testing framework provides, for example:
+
+```
+void TestFooDoesBar() {
+  Foo foo;
+  EXPECT_LE(foo.Bar(1), 100);     // A Google Test assertion.
+  CPPUNIT_ASSERT(foo.IsEmpty());  // A native assertion.
+}
+```
+
+If a Google Test assertion fails, it will print an error message and
+throw an exception, which will be treated as a failure by your host
+testing framework.  If you compile your code with exceptions disabled,
+a failed Google Test assertion will instead exit your program with a
+non-zero code, which will also signal a test failure to your test
+runner.
+
+If you don't write `::testing::GTEST_FLAG(throw_on_failure) = true;` in
+your `main()`, you can alternatively enable this feature by specifying
+the `--gtest_throw_on_failure` flag on the command-line or setting the
+`GTEST_THROW_ON_FAILURE` environment variable to a non-zero value.
+
+_Availability:_ Linux, Windows, Mac; since v1.3.0.
+
+## Distributing Test Functions to Multiple Machines ##
+
+If you have more than one machine you can use to run a test program,
+you might want to run the test functions in parallel and get the
+result faster.  We call this technique _sharding_, where each machine
+is called a _shard_.
+
+Google Test is compatible with test sharding.  To take advantage of
+this feature, your test runner (not part of Google Test) needs to do
+the following:
+
+  1. Allocate a number of machines (shards) to run the tests.
+  1. On each shard, set the `GTEST_TOTAL_SHARDS` environment variable to the total number of shards.  It must be the same for all shards.
+  1. On each shard, set the `GTEST_SHARD_INDEX` environment variable to the index of the shard.  Different shards must be assigned different indices, which must be in the range `[0, GTEST_TOTAL_SHARDS - 1]`.
+  1. Run the same test program on all shards.  When Google Test sees the above two environment variables, it will select a subset of the test functions to run.  Across all shards, each test function in the program will be run exactly once.
+  1. Wait for all shards to finish, then collect and report the results.
+
+Your project may have tests that were written without Google Test and
+thus don't understand this protocol.  In order for your test runner to
+figure out which test supports sharding, it can set the environment
+variable `GTEST_SHARD_STATUS_FILE` to a non-existent file path.  If a
+test program supports sharding, it will create this file to
+acknowledge the fact (the actual contents of the file are not
+important at this time; although we may stick some useful information
+in it in the future.); otherwise it will not create it.
+
+Here's an example to make it clear.  Suppose you have a test program
+`foo_test` that contains the following 5 test functions:
+```
+TEST(A, V)
+TEST(A, W)
+TEST(B, X)
+TEST(B, Y)
+TEST(B, Z)
+```
+and you have 3 machines at your disposal.  To run the test functions in
+parallel, you would set `GTEST_TOTAL_SHARDS` to 3 on all machines, and
+set `GTEST_SHARD_INDEX` to 0, 1, and 2 on the machines respectively.
+Then you would run the same `foo_test` on each machine.
+
+Google Test reserves the right to change how the work is distributed
+across the shards, but here's one possible scenario:
+
+  * Machine #0 runs `A.V` and `B.X`.
+  * Machine #1 runs `A.W` and `B.Y`.
+  * Machine #2 runs `B.Z`.
+
+_Availability:_ Linux, Windows, Mac; since version 1.3.0.
+
+# Fusing Google Test Source Files #
+
+Google Test's implementation consists of ~30 files (excluding its own
+tests).  Sometimes you may want them to be packaged up in two files (a
+`.h` and a `.cc`) instead, such that you can easily copy them to a new
+machine and start hacking there.  For this we provide an experimental
+Python script `fuse_gtest_files.py` in the `scripts/` directory (since release 1.3.0).
+Assuming you have Python 2.4 or above installed on your machine, just
+go to that directory and run
+```
+python fuse_gtest_files.py OUTPUT_DIR
+```
+
+and you should see an `OUTPUT_DIR` directory being created with files
+`gtest/gtest.h` and `gtest/gtest-all.cc` in it.  These files contain
+everything you need to use Google Test.  Just copy them to anywhere
+you want and you are ready to write tests.  You can use the
+[scripts/test/Makefile](http://code.google.com/p/googletest/source/browse/trunk/scripts/test/Makefile)
+file as an example on how to compile your tests against them.
+
+# Where to Go from Here #
+
+Congratulations! You've now learned more advanced Google Test tools and are
+ready to tackle more complex testing tasks. If you want to dive even deeper, you
+can read the [Frequently-Asked Questions](V1_6_FAQ.md).
\ No newline at end of file
diff --git a/third_party/googletest/googletest/docs/V1_6_Documentation.md b/third_party/googletest/googletest/docs/V1_6_Documentation.md
new file mode 100644
index 0000000..ca92466
--- /dev/null
+++ b/third_party/googletest/googletest/docs/V1_6_Documentation.md
@@ -0,0 +1,14 @@
+This page lists all documentation wiki pages for Google Test **1.6**
+-- **if you use a released version of Google Test, please read the
+documentation for that specific version instead.**
+
+  * [Primer](V1_6_Primer.md) -- start here if you are new to Google Test.
+  * [Samples](V1_6_Samples.md) -- learn from examples.
+  * [AdvancedGuide](V1_6_AdvancedGuide.md) -- learn more about Google Test.
+  * [XcodeGuide](V1_6_XcodeGuide.md) -- how to use Google Test in Xcode on Mac.
+  * [Frequently-Asked Questions](V1_6_FAQ.md) -- check here before asking a question on the mailing list.
+
+To contribute code to Google Test, read:
+
+  * [DevGuide](DevGuide.md) -- read this _before_ writing your first patch.
+  * [PumpManual](V1_6_PumpManual.md) -- how we generate some of Google Test's source files.
\ No newline at end of file
diff --git a/third_party/googletest/googletest/docs/V1_6_FAQ.md b/third_party/googletest/googletest/docs/V1_6_FAQ.md
new file mode 100644
index 0000000..61677a6
--- /dev/null
+++ b/third_party/googletest/googletest/docs/V1_6_FAQ.md
@@ -0,0 +1,1037 @@
+
+
+If you cannot find the answer to your question here, and you have read
+[Primer](V1_6_Primer.md) and [AdvancedGuide](V1_6_AdvancedGuide.md), send it to
+googletestframework@googlegroups.com.
+
+## Why should I use Google Test instead of my favorite C++ testing framework? ##
+
+First, let us say clearly that we don't want to get into the debate of
+which C++ testing framework is **the best**.  There exist many fine
+frameworks for writing C++ tests, and we have tremendous respect for
+the developers and users of them.  We don't think there is (or will
+be) a single best framework - you have to pick the right tool for the
+particular task you are tackling.
+
+We created Google Test because we couldn't find the right combination
+of features and conveniences in an existing framework to satisfy _our_
+needs.  The following is a list of things that _we_ like about Google
+Test.  We don't claim them to be unique to Google Test - rather, the
+combination of them makes Google Test the choice for us.  We hope this
+list can help you decide whether it is for you too.
+
+  * Google Test is designed to be portable: it doesn't require exceptions or RTTI; it works around various bugs in various compilers and environments; etc.  As a result, it works on Linux, Mac OS X, Windows and several embedded operating systems.
+  * Nonfatal assertions (`EXPECT_*`) have proven to be great time savers, as they allow a test to report multiple failures in a single edit-compile-test cycle.
+  * It's easy to write assertions that generate informative messages: you just use the stream syntax to append any additional information, e.g. `ASSERT_EQ(5, Foo(i)) << " where i = " << i;`.  It doesn't require a new set of macros or special functions.
+  * Google Test automatically detects your tests and doesn't require you to enumerate them in order to run them.
+  * Death tests are pretty handy for ensuring that your asserts in production code are triggered by the right conditions.
+  * `SCOPED_TRACE` helps you understand the context of an assertion failure when it comes from inside a sub-routine or loop.
+  * You can decide which tests to run using name patterns.  This saves time when you want to quickly reproduce a test failure.
+  * Google Test can generate XML test result reports that can be parsed by popular continuous build system like Hudson.
+  * Simple things are easy in Google Test, while hard things are possible: in addition to advanced features like [global test environments](http://code.google.com/p/googletest/wiki/V1_6_AdvancedGuide#Global_Set-Up_and_Tear-Down) and tests parameterized by [values](http://code.google.com/p/googletest/wiki/V1_6_AdvancedGuide#Value_Parameterized_Tests) or [types](http://code.google.com/p/googletest/wiki/V1_6_AdvancedGuide#Typed_Tests), Google Test supports various ways for the user to extend the framework -- if Google Test doesn't do something out of the box, chances are that a user can implement the feature using Google Test's public API, without changing Google Test itself.  In particular, you can:
+    * expand your testing vocabulary by defining [custom predicates](http://code.google.com/p/googletest/wiki/V1_6_AdvancedGuide#Predicate_Assertions_for_Better_Error_Messages),
+    * teach Google Test how to [print your types](http://code.google.com/p/googletest/wiki/V1_6_AdvancedGuide#Teaching_Google_Test_How_to_Print_Your_Values),
+    * define your own testing macros or utilities and verify them using Google Test's [Service Provider Interface](http://code.google.com/p/googletest/wiki/V1_6_AdvancedGuide#Catching_Failures), and
+    * reflect on the test cases or change the test output format by intercepting the [test events](http://code.google.com/p/googletest/wiki/V1_6_AdvancedGuide#Extending_Google_Test_by_Handling_Test_Events).
+
+## I'm getting warnings when compiling Google Test.  Would you fix them? ##
+
+We strive to minimize compiler warnings Google Test generates.  Before releasing a new version, we test to make sure that it doesn't generate warnings when compiled using its CMake script on Windows, Linux, and Mac OS.
+
+Unfortunately, this doesn't mean you are guaranteed to see no warnings when compiling Google Test in your environment:
+
+  * You may be using a different compiler as we use, or a different version of the same compiler.  We cannot possibly test for all compilers.
+  * You may be compiling on a different platform as we do.
+  * Your project may be using different compiler flags as we do.
+
+It is not always possible to make Google Test warning-free for everyone.  Or, it may not be desirable if the warning is rarely enabled and fixing the violations makes the code more complex.
+
+If you see warnings when compiling Google Test, we suggest that you use the `-isystem` flag (assuming your are using GCC) to mark Google Test headers as system headers.  That'll suppress warnings from Google Test headers.
+
+## Why should not test case names and test names contain underscore? ##
+
+Underscore (`_`) is special, as C++ reserves the following to be used by
+the compiler and the standard library:
+
+  1. any identifier that starts with an `_` followed by an upper-case letter, and
+  1. any identifier that containers two consecutive underscores (i.e. `__`) _anywhere_ in its name.
+
+User code is _prohibited_ from using such identifiers.
+
+Now let's look at what this means for `TEST` and `TEST_F`.
+
+Currently `TEST(TestCaseName, TestName)` generates a class named
+`TestCaseName_TestName_Test`.  What happens if `TestCaseName` or `TestName`
+contains `_`?
+
+  1. If `TestCaseName` starts with an `_` followed by an upper-case letter (say, `_Foo`), we end up with `_Foo_TestName_Test`, which is reserved and thus invalid.
+  1. If `TestCaseName` ends with an `_` (say, `Foo_`), we get `Foo__TestName_Test`, which is invalid.
+  1. If `TestName` starts with an `_` (say, `_Bar`), we get `TestCaseName__Bar_Test`, which is invalid.
+  1. If `TestName` ends with an `_` (say, `Bar_`), we get `TestCaseName_Bar__Test`, which is invalid.
+
+So clearly `TestCaseName` and `TestName` cannot start or end with `_`
+(Actually, `TestCaseName` can start with `_` -- as long as the `_` isn't
+followed by an upper-case letter.  But that's getting complicated.  So
+for simplicity we just say that it cannot start with `_`.).
+
+It may seem fine for `TestCaseName` and `TestName` to contain `_` in the
+middle.  However, consider this:
+```
+TEST(Time, Flies_Like_An_Arrow) { ... }
+TEST(Time_Flies, Like_An_Arrow) { ... }
+```
+
+Now, the two `TEST`s will both generate the same class
+(`Time_Files_Like_An_Arrow_Test`).  That's not good.
+
+So for simplicity, we just ask the users to avoid `_` in `TestCaseName`
+and `TestName`.  The rule is more constraining than necessary, but it's
+simple and easy to remember.  It also gives Google Test some wiggle
+room in case its implementation needs to change in the future.
+
+If you violate the rule, there may not be immediately consequences,
+but your test may (just may) break with a new compiler (or a new
+version of the compiler you are using) or with a new version of Google
+Test.  Therefore it's best to follow the rule.
+
+## Why is it not recommended to install a pre-compiled copy of Google Test (for example, into /usr/local)? ##
+
+In the early days, we said that you could install
+compiled Google Test libraries on `*`nix systems using `make install`.
+Then every user of your machine can write tests without
+recompiling Google Test.
+
+This seemed like a good idea, but it has a
+got-cha: every user needs to compile his tests using the _same_ compiler
+flags used to compile the installed Google Test libraries; otherwise
+he may run into undefined behaviors (i.e. the tests can behave
+strangely and may even crash for no obvious reasons).
+
+Why?  Because C++ has this thing called the One-Definition Rule: if
+two C++ source files contain different definitions of the same
+class/function/variable, and you link them together, you violate the
+rule.  The linker may or may not catch the error (in many cases it's
+not required by the C++ standard to catch the violation).  If it
+doesn't, you get strange run-time behaviors that are unexpected and
+hard to debug.
+
+If you compile Google Test and your test code using different compiler
+flags, they may see different definitions of the same
+class/function/variable (e.g. due to the use of `#if` in Google Test).
+Therefore, for your sanity, we recommend to avoid installing pre-compiled
+Google Test libraries.  Instead, each project should compile
+Google Test itself such that it can be sure that the same flags are
+used for both Google Test and the tests.
+
+## How do I generate 64-bit binaries on Windows (using Visual Studio 2008)? ##
+
+(Answered by Trevor Robinson)
+
+Load the supplied Visual Studio solution file, either `msvc\gtest-md.sln` or
+`msvc\gtest.sln`. Go through the migration wizard to migrate the
+solution and project files to Visual Studio 2008. Select
+`Configuration Manager...` from the `Build` menu. Select `<New...>` from
+the `Active solution platform` dropdown.  Select `x64` from the new
+platform dropdown, leave `Copy settings from` set to `Win32` and
+`Create new project platforms` checked, then click `OK`. You now have
+`Win32` and `x64` platform configurations, selectable from the
+`Standard` toolbar, which allow you to toggle between building 32-bit or
+64-bit binaries (or both at once using Batch Build).
+
+In order to prevent build output files from overwriting one another,
+you'll need to change the `Intermediate Directory` settings for the
+newly created platform configuration across all the projects. To do
+this, multi-select (e.g. using shift-click) all projects (but not the
+solution) in the `Solution Explorer`. Right-click one of them and
+select `Properties`. In the left pane, select `Configuration Properties`,
+and from the `Configuration` dropdown, select `All Configurations`.
+Make sure the selected platform is `x64`. For the
+`Intermediate Directory` setting, change the value from
+`$(PlatformName)\$(ConfigurationName)` to
+`$(OutDir)\$(ProjectName)`. Click `OK` and then build the
+solution. When the build is complete, the 64-bit binaries will be in
+the `msvc\x64\Debug` directory.
+
+## Can I use Google Test on MinGW? ##
+
+We haven't tested this ourselves, but Per Abrahamsen reported that he
+was able to compile and install Google Test successfully when using
+MinGW from Cygwin.  You'll need to configure it with:
+
+`PATH/TO/configure CC="gcc -mno-cygwin" CXX="g++ -mno-cygwin"`
+
+You should be able to replace the `-mno-cygwin` option with direct links
+to the real MinGW binaries, but we haven't tried that.
+
+Caveats:
+
+  * There are many warnings when compiling.
+  * `make check` will produce some errors as not all tests for Google Test itself are compatible with MinGW.
+
+We also have reports on successful cross compilation of Google Test
+MinGW binaries on Linux using
+[these instructions](http://wiki.wxwidgets.org/Cross-Compiling_Under_Linux#Cross-compiling_under_Linux_for_MS_Windows)
+on the WxWidgets site.
+
+Please contact `googletestframework@googlegroups.com` if you are
+interested in improving the support for MinGW.
+
+## Why does Google Test support EXPECT\_EQ(NULL, ptr) and ASSERT\_EQ(NULL, ptr) but not EXPECT\_NE(NULL, ptr) and ASSERT\_NE(NULL, ptr)? ##
+
+Due to some peculiarity of C++, it requires some non-trivial template
+meta programming tricks to support using `NULL` as an argument of the
+`EXPECT_XX()` and `ASSERT_XX()` macros. Therefore we only do it where
+it's most needed (otherwise we make the implementation of Google Test
+harder to maintain and more error-prone than necessary).
+
+The `EXPECT_EQ()` macro takes the _expected_ value as its first
+argument and the _actual_ value as the second. It's reasonable that
+someone wants to write `EXPECT_EQ(NULL, some_expression)`, and this
+indeed was requested several times. Therefore we implemented it.
+
+The need for `EXPECT_NE(NULL, ptr)` isn't nearly as strong. When the
+assertion fails, you already know that `ptr` must be `NULL`, so it
+doesn't add any information to print ptr in this case. That means
+`EXPECT_TRUE(ptr ! NULL)` works just as well.
+
+If we were to support `EXPECT_NE(NULL, ptr)`, for consistency we'll
+have to support `EXPECT_NE(ptr, NULL)` as well, as unlike `EXPECT_EQ`,
+we don't have a convention on the order of the two arguments for
+`EXPECT_NE`. This means using the template meta programming tricks
+twice in the implementation, making it even harder to understand and
+maintain. We believe the benefit doesn't justify the cost.
+
+Finally, with the growth of Google Mock's [matcher](http://code.google.com/p/googlemock/wiki/CookBook#Using_Matchers_in_Google_Test_Assertions) library, we are
+encouraging people to use the unified `EXPECT_THAT(value, matcher)`
+syntax more often in tests. One significant advantage of the matcher
+approach is that matchers can be easily combined to form new matchers,
+while the `EXPECT_NE`, etc, macros cannot be easily
+combined. Therefore we want to invest more in the matchers than in the
+`EXPECT_XX()` macros.
+
+## Does Google Test support running tests in parallel? ##
+
+Test runners tend to be tightly coupled with the build/test
+environment, and Google Test doesn't try to solve the problem of
+running tests in parallel.  Instead, we tried to make Google Test work
+nicely with test runners.  For example, Google Test's XML report
+contains the time spent on each test, and its `gtest_list_tests` and
+`gtest_filter` flags can be used for splitting the execution of test
+methods into multiple processes.  These functionalities can help the
+test runner run the tests in parallel.
+
+## Why don't Google Test run the tests in different threads to speed things up? ##
+
+It's difficult to write thread-safe code.  Most tests are not written
+with thread-safety in mind, and thus may not work correctly in a
+multi-threaded setting.
+
+If you think about it, it's already hard to make your code work when
+you know what other threads are doing.  It's much harder, and
+sometimes even impossible, to make your code work when you don't know
+what other threads are doing (remember that test methods can be added,
+deleted, or modified after your test was written).  If you want to run
+the tests in parallel, you'd better run them in different processes.
+
+## Why aren't Google Test assertions implemented using exceptions? ##
+
+Our original motivation was to be able to use Google Test in projects
+that disable exceptions.  Later we realized some additional benefits
+of this approach:
+
+  1. Throwing in a destructor is undefined behavior in C++.  Not using exceptions means Google Test's assertions are safe to use in destructors.
+  1. The `EXPECT_*` family of macros will continue even after a failure, allowing multiple failures in a `TEST` to be reported in a single run. This is a popular feature, as in C++ the edit-compile-test cycle is usually quite long and being able to fixing more than one thing at a time is a blessing.
+  1. If assertions are implemented using exceptions, a test may falsely ignore a failure if it's caught by user code:
+```
+try { ... ASSERT_TRUE(...) ... }
+catch (...) { ... }
+```
+The above code will pass even if the `ASSERT_TRUE` throws.  While it's unlikely for someone to write this in a test, it's possible to run into this pattern when you write assertions in callbacks that are called by the code under test.
+
+The downside of not using exceptions is that `ASSERT_*` (implemented
+using `return`) will only abort the current function, not the current
+`TEST`.
+
+## Why do we use two different macros for tests with and without fixtures? ##
+
+Unfortunately, C++'s macro system doesn't allow us to use the same
+macro for both cases.  One possibility is to provide only one macro
+for tests with fixtures, and require the user to define an empty
+fixture sometimes:
+
+```
+class FooTest : public ::testing::Test {};
+
+TEST_F(FooTest, DoesThis) { ... }
+```
+or
+```
+typedef ::testing::Test FooTest;
+
+TEST_F(FooTest, DoesThat) { ... }
+```
+
+Yet, many people think this is one line too many. :-) Our goal was to
+make it really easy to write tests, so we tried to make simple tests
+trivial to create.  That means using a separate macro for such tests.
+
+We think neither approach is ideal, yet either of them is reasonable.
+In the end, it probably doesn't matter much either way.
+
+## Why don't we use structs as test fixtures? ##
+
+We like to use structs only when representing passive data.  This
+distinction between structs and classes is good for documenting the
+intent of the code's author.  Since test fixtures have logic like
+`SetUp()` and `TearDown()`, they are better defined as classes.
+
+## Why are death tests implemented as assertions instead of using a test runner? ##
+
+Our goal was to make death tests as convenient for a user as C++
+possibly allows.  In particular:
+
+  * The runner-style requires to split the information into two pieces: the definition of the death test itself, and the specification for the runner on how to run the death test and what to expect.  The death test would be written in C++, while the runner spec may or may not be.  A user needs to carefully keep the two in sync. `ASSERT_DEATH(statement, expected_message)` specifies all necessary information in one place, in one language, without boilerplate code. It is very declarative.
+  * `ASSERT_DEATH` has a similar syntax and error-reporting semantics as other Google Test assertions, and thus is easy to learn.
+  * `ASSERT_DEATH` can be mixed with other assertions and other logic at your will.  You are not limited to one death test per test method. For example, you can write something like:
+```
+    if (FooCondition()) {
+      ASSERT_DEATH(Bar(), "blah");
+    } else {
+      ASSERT_EQ(5, Bar());
+    }
+```
+If you prefer one death test per test method, you can write your tests in that style too, but we don't want to impose that on the users.  The fewer artificial limitations the better.
+  * `ASSERT_DEATH` can reference local variables in the current function, and you can decide how many death tests you want based on run-time information.  For example,
+```
+    const int count = GetCount();  // Only known at run time.
+    for (int i = 1; i <= count; i++) {
+      ASSERT_DEATH({
+        double* buffer = new double[i];
+        ... initializes buffer ...
+        Foo(buffer, i)
+      }, "blah blah");
+    }
+```
+The runner-based approach tends to be more static and less flexible, or requires more user effort to get this kind of flexibility.
+
+Another interesting thing about `ASSERT_DEATH` is that it calls `fork()`
+to create a child process to run the death test.  This is lightening
+fast, as `fork()` uses copy-on-write pages and incurs almost zero
+overhead, and the child process starts from the user-supplied
+statement directly, skipping all global and local initialization and
+any code leading to the given statement.  If you launch the child
+process from scratch, it can take seconds just to load everything and
+start running if the test links to many libraries dynamically.
+
+## My death test modifies some state, but the change seems lost after the death test finishes. Why? ##
+
+Death tests (`EXPECT_DEATH`, etc) are executed in a sub-process s.t. the
+expected crash won't kill the test program (i.e. the parent process). As a
+result, any in-memory side effects they incur are observable in their
+respective sub-processes, but not in the parent process. You can think of them
+as running in a parallel universe, more or less.
+
+## The compiler complains about "undefined references" to some static const member variables, but I did define them in the class body. What's wrong? ##
+
+If your class has a static data member:
+
+```
+// foo.h
+class Foo {
+  ...
+  static const int kBar = 100;
+};
+```
+
+You also need to define it _outside_ of the class body in `foo.cc`:
+
+```
+const int Foo::kBar;  // No initializer here.
+```
+
+Otherwise your code is **invalid C++**, and may break in unexpected ways. In
+particular, using it in Google Test comparison assertions (`EXPECT_EQ`, etc)
+will generate an "undefined reference" linker error.
+
+## I have an interface that has several implementations. Can I write a set of tests once and repeat them over all the implementations? ##
+
+Google Test doesn't yet have good support for this kind of tests, or
+data-driven tests in general. We hope to be able to make improvements in this
+area soon.
+
+## Can I derive a test fixture from another? ##
+
+Yes.
+
+Each test fixture has a corresponding and same named test case. This means only
+one test case can use a particular fixture. Sometimes, however, multiple test
+cases may want to use the same or slightly different fixtures. For example, you
+may want to make sure that all of a GUI library's test cases don't leak
+important system resources like fonts and brushes.
+
+In Google Test, you share a fixture among test cases by putting the shared
+logic in a base test fixture, then deriving from that base a separate fixture
+for each test case that wants to use this common logic. You then use `TEST_F()`
+to write tests using each derived fixture.
+
+Typically, your code looks like this:
+
+```
+// Defines a base test fixture.
+class BaseTest : public ::testing::Test {
+  protected:
+   ...
+};
+
+// Derives a fixture FooTest from BaseTest.
+class FooTest : public BaseTest {
+  protected:
+    virtual void SetUp() {
+      BaseTest::SetUp();  // Sets up the base fixture first.
+      ... additional set-up work ...
+    }
+    virtual void TearDown() {
+      ... clean-up work for FooTest ...
+      BaseTest::TearDown();  // Remember to tear down the base fixture
+                             // after cleaning up FooTest!
+    }
+    ... functions and variables for FooTest ...
+};
+
+// Tests that use the fixture FooTest.
+TEST_F(FooTest, Bar) { ... }
+TEST_F(FooTest, Baz) { ... }
+
+... additional fixtures derived from BaseTest ...
+```
+
+If necessary, you can continue to derive test fixtures from a derived fixture.
+Google Test has no limit on how deep the hierarchy can be.
+
+For a complete example using derived test fixtures, see
+[sample5](http://code.google.com/p/googletest/source/browse/trunk/samples/sample5_unittest.cc).
+
+## My compiler complains "void value not ignored as it ought to be." What does this mean? ##
+
+You're probably using an `ASSERT_*()` in a function that doesn't return `void`.
+`ASSERT_*()` can only be used in `void` functions.
+
+## My death test hangs (or seg-faults). How do I fix it? ##
+
+In Google Test, death tests are run in a child process and the way they work is
+delicate. To write death tests you really need to understand how they work.
+Please make sure you have read this.
+
+In particular, death tests don't like having multiple threads in the parent
+process. So the first thing you can try is to eliminate creating threads
+outside of `EXPECT_DEATH()`.
+
+Sometimes this is impossible as some library you must use may be creating
+threads before `main()` is even reached. In this case, you can try to minimize
+the chance of conflicts by either moving as many activities as possible inside
+`EXPECT_DEATH()` (in the extreme case, you want to move everything inside), or
+leaving as few things as possible in it. Also, you can try to set the death
+test style to `"threadsafe"`, which is safer but slower, and see if it helps.
+
+If you go with thread-safe death tests, remember that they rerun the test
+program from the beginning in the child process. Therefore make sure your
+program can run side-by-side with itself and is deterministic.
+
+In the end, this boils down to good concurrent programming. You have to make
+sure that there is no race conditions or dead locks in your program. No silver
+bullet - sorry!
+
+## Should I use the constructor/destructor of the test fixture or the set-up/tear-down function? ##
+
+The first thing to remember is that Google Test does not reuse the
+same test fixture object across multiple tests. For each `TEST_F`,
+Google Test will create a fresh test fixture object, _immediately_
+call `SetUp()`, run the test, call `TearDown()`, and then
+_immediately_ delete the test fixture object. Therefore, there is no
+need to write a `SetUp()` or `TearDown()` function if the constructor
+or destructor already does the job.
+
+You may still want to use `SetUp()/TearDown()` in the following cases:
+  * If the tear-down operation could throw an exception, you must use `TearDown()` as opposed to the destructor, as throwing in a destructor leads to undefined behavior and usually will kill your program right away. Note that many standard libraries (like STL) may throw when exceptions are enabled in the compiler. Therefore you should prefer `TearDown()` if you want to write portable tests that work with or without exceptions.
+  * The Google Test team is considering making the assertion macros throw on platforms where exceptions are enabled (e.g. Windows, Mac OS, and Linux client-side), which will eliminate the need for the user to propagate failures from a subroutine to its caller. Therefore, you shouldn't use Google Test assertions in a destructor if your code could run on such a platform.
+  * In a constructor or destructor, you cannot make a virtual function call on this object. (You can call a method declared as virtual, but it will be statically bound.) Therefore, if you need to call a method that will be overriden in a derived class, you have to use `SetUp()/TearDown()`.
+
+## The compiler complains "no matching function to call" when I use ASSERT\_PREDn. How do I fix it? ##
+
+If the predicate function you use in `ASSERT_PRED*` or `EXPECT_PRED*` is
+overloaded or a template, the compiler will have trouble figuring out which
+overloaded version it should use. `ASSERT_PRED_FORMAT*` and
+`EXPECT_PRED_FORMAT*` don't have this problem.
+
+If you see this error, you might want to switch to
+`(ASSERT|EXPECT)_PRED_FORMAT*`, which will also give you a better failure
+message. If, however, that is not an option, you can resolve the problem by
+explicitly telling the compiler which version to pick.
+
+For example, suppose you have
+
+```
+bool IsPositive(int n) {
+  return n > 0;
+}
+bool IsPositive(double x) {
+  return x > 0;
+}
+```
+
+you will get a compiler error if you write
+
+```
+EXPECT_PRED1(IsPositive, 5);
+```
+
+However, this will work:
+
+```
+EXPECT_PRED1(*static_cast<bool (*)(int)>*(IsPositive), 5);
+```
+
+(The stuff inside the angled brackets for the `static_cast` operator is the
+type of the function pointer for the `int`-version of `IsPositive()`.)
+
+As another example, when you have a template function
+
+```
+template <typename T>
+bool IsNegative(T x) {
+  return x < 0;
+}
+```
+
+you can use it in a predicate assertion like this:
+
+```
+ASSERT_PRED1(IsNegative*<int>*, -5);
+```
+
+Things are more interesting if your template has more than one parameters. The
+following won't compile:
+
+```
+ASSERT_PRED2(*GreaterThan<int, int>*, 5, 0);
+```
+
+
+as the C++ pre-processor thinks you are giving `ASSERT_PRED2` 4 arguments,
+which is one more than expected. The workaround is to wrap the predicate
+function in parentheses:
+
+```
+ASSERT_PRED2(*(GreaterThan<int, int>)*, 5, 0);
+```
+
+
+## My compiler complains about "ignoring return value" when I call RUN\_ALL\_TESTS(). Why? ##
+
+Some people had been ignoring the return value of `RUN_ALL_TESTS()`. That is,
+instead of
+
+```
+return RUN_ALL_TESTS();
+```
+
+they write
+
+```
+RUN_ALL_TESTS();
+```
+
+This is wrong and dangerous. A test runner needs to see the return value of
+`RUN_ALL_TESTS()` in order to determine if a test has passed. If your `main()`
+function ignores it, your test will be considered successful even if it has a
+Google Test assertion failure. Very bad.
+
+To help the users avoid this dangerous bug, the implementation of
+`RUN_ALL_TESTS()` causes gcc to raise this warning, when the return value is
+ignored. If you see this warning, the fix is simple: just make sure its value
+is used as the return value of `main()`.
+
+## My compiler complains that a constructor (or destructor) cannot return a value. What's going on? ##
+
+Due to a peculiarity of C++, in order to support the syntax for streaming
+messages to an `ASSERT_*`, e.g.
+
+```
+ASSERT_EQ(1, Foo()) << "blah blah" << foo;
+```
+
+we had to give up using `ASSERT*` and `FAIL*` (but not `EXPECT*` and
+`ADD_FAILURE*`) in constructors and destructors. The workaround is to move the
+content of your constructor/destructor to a private void member function, or
+switch to `EXPECT_*()` if that works. This section in the user's guide explains
+it.
+
+## My set-up function is not called. Why? ##
+
+C++ is case-sensitive. It should be spelled as `SetUp()`.  Did you
+spell it as `Setup()`?
+
+Similarly, sometimes people spell `SetUpTestCase()` as `SetupTestCase()` and
+wonder why it's never called.
+
+## How do I jump to the line of a failure in Emacs directly? ##
+
+Google Test's failure message format is understood by Emacs and many other
+IDEs, like acme and XCode. If a Google Test message is in a compilation buffer
+in Emacs, then it's clickable. You can now hit `enter` on a message to jump to
+the corresponding source code, or use `C-x `` to jump to the next failure.
+
+## I have several test cases which share the same test fixture logic, do I have to define a new test fixture class for each of them? This seems pretty tedious. ##
+
+You don't have to. Instead of
+
+```
+class FooTest : public BaseTest {};
+
+TEST_F(FooTest, Abc) { ... }
+TEST_F(FooTest, Def) { ... }
+
+class BarTest : public BaseTest {};
+
+TEST_F(BarTest, Abc) { ... }
+TEST_F(BarTest, Def) { ... }
+```
+
+you can simply `typedef` the test fixtures:
+```
+typedef BaseTest FooTest;
+
+TEST_F(FooTest, Abc) { ... }
+TEST_F(FooTest, Def) { ... }
+
+typedef BaseTest BarTest;
+
+TEST_F(BarTest, Abc) { ... }
+TEST_F(BarTest, Def) { ... }
+```
+
+## The Google Test output is buried in a whole bunch of log messages. What do I do? ##
+
+The Google Test output is meant to be a concise and human-friendly report. If
+your test generates textual output itself, it will mix with the Google Test
+output, making it hard to read. However, there is an easy solution to this
+problem.
+
+Since most log messages go to stderr, we decided to let Google Test output go
+to stdout. This way, you can easily separate the two using redirection. For
+example:
+```
+./my_test > googletest_output.txt
+```
+
+## Why should I prefer test fixtures over global variables? ##
+
+There are several good reasons:
+  1. It's likely your test needs to change the states of its global variables. This makes it difficult to keep side effects from escaping one test and contaminating others, making debugging difficult. By using fixtures, each test has a fresh set of variables that's different (but with the same names). Thus, tests are kept independent of each other.
+  1. Global variables pollute the global namespace.
+  1. Test fixtures can be reused via subclassing, which cannot be done easily with global variables. This is useful if many test cases have something in common.
+
+## How do I test private class members without writing FRIEND\_TEST()s? ##
+
+You should try to write testable code, which means classes should be easily
+tested from their public interface. One way to achieve this is the Pimpl idiom:
+you move all private members of a class into a helper class, and make all
+members of the helper class public.
+
+You have several other options that don't require using `FRIEND_TEST`:
+  * Write the tests as members of the fixture class:
+```
+class Foo {
+  friend class FooTest;
+  ...
+};
+
+class FooTest : public ::testing::Test {
+ protected:
+  ...
+  void Test1() {...} // This accesses private members of class Foo.
+  void Test2() {...} // So does this one.
+};
+
+TEST_F(FooTest, Test1) {
+  Test1();
+}
+
+TEST_F(FooTest, Test2) {
+  Test2();
+}
+```
+  * In the fixture class, write accessors for the tested class' private members, then use the accessors in your tests:
+```
+class Foo {
+  friend class FooTest;
+  ...
+};
+
+class FooTest : public ::testing::Test {
+ protected:
+  ...
+  T1 get_private_member1(Foo* obj) {
+    return obj->private_member1_;
+  }
+};
+
+TEST_F(FooTest, Test1) {
+  ...
+  get_private_member1(x)
+  ...
+}
+```
+  * If the methods are declared **protected**, you can change their access level in a test-only subclass:
+```
+class YourClass {
+  ...
+ protected: // protected access for testability.
+  int DoSomethingReturningInt();
+  ...
+};
+
+// in the your_class_test.cc file:
+class TestableYourClass : public YourClass {
+  ...
+ public: using YourClass::DoSomethingReturningInt; // changes access rights
+  ...
+};
+
+TEST_F(YourClassTest, DoSomethingTest) {
+  TestableYourClass obj;
+  assertEquals(expected_value, obj.DoSomethingReturningInt());
+}
+```
+
+## How do I test private class static members without writing FRIEND\_TEST()s? ##
+
+We find private static methods clutter the header file.  They are
+implementation details and ideally should be kept out of a .h. So often I make
+them free functions instead.
+
+Instead of:
+```
+// foo.h
+class Foo {
+  ...
+ private:
+  static bool Func(int n);
+};
+
+// foo.cc
+bool Foo::Func(int n) { ... }
+
+// foo_test.cc
+EXPECT_TRUE(Foo::Func(12345));
+```
+
+You probably should better write:
+```
+// foo.h
+class Foo {
+  ...
+};
+
+// foo.cc
+namespace internal {
+  bool Func(int n) { ... }
+}
+
+// foo_test.cc
+namespace internal {
+  bool Func(int n);
+}
+
+EXPECT_TRUE(internal::Func(12345));
+```
+
+## I would like to run a test several times with different parameters. Do I need to write several similar copies of it? ##
+
+No. You can use a feature called [value-parameterized tests](V1_6_AdvancedGuide#Value_Parameterized_Tests.md) which
+lets you repeat your tests with different parameters, without defining it more than once.
+
+## How do I test a file that defines main()? ##
+
+To test a `foo.cc` file, you need to compile and link it into your unit test
+program. However, when the file contains a definition for the `main()`
+function, it will clash with the `main()` of your unit test, and will result in
+a build error.
+
+The right solution is to split it into three files:
+  1. `foo.h` which contains the declarations,
+  1. `foo.cc` which contains the definitions except `main()`, and
+  1. `foo_main.cc` which contains nothing but the definition of `main()`.
+
+Then `foo.cc` can be easily tested.
+
+If you are adding tests to an existing file and don't want an intrusive change
+like this, there is a hack: just include the entire `foo.cc` file in your unit
+test. For example:
+```
+// File foo_unittest.cc
+
+// The headers section
+...
+
+// Renames main() in foo.cc to make room for the unit test main()
+#define main FooMain
+
+#include "a/b/foo.cc"
+
+// The tests start here.
+...
+```
+
+
+However, please remember this is a hack and should only be used as the last
+resort.
+
+## What can the statement argument in ASSERT\_DEATH() be? ##
+
+`ASSERT_DEATH(_statement_, _regex_)` (or any death assertion macro) can be used
+wherever `_statement_` is valid. So basically `_statement_` can be any C++
+statement that makes sense in the current context. In particular, it can
+reference global and/or local variables, and can be:
+  * a simple function call (often the case),
+  * a complex expression, or
+  * a compound statement.
+
+> Some examples are shown here:
+```
+// A death test can be a simple function call.
+TEST(MyDeathTest, FunctionCall) {
+  ASSERT_DEATH(Xyz(5), "Xyz failed");
+}
+
+// Or a complex expression that references variables and functions.
+TEST(MyDeathTest, ComplexExpression) {
+  const bool c = Condition();
+  ASSERT_DEATH((c ? Func1(0) : object2.Method("test")),
+               "(Func1|Method) failed");
+}
+
+// Death assertions can be used any where in a function. In
+// particular, they can be inside a loop.
+TEST(MyDeathTest, InsideLoop) {
+  // Verifies that Foo(0), Foo(1), ..., and Foo(4) all die.
+  for (int i = 0; i < 5; i++) {
+    EXPECT_DEATH_M(Foo(i), "Foo has \\d+ errors",
+                   ::testing::Message() << "where i is " << i);
+  }
+}
+
+// A death assertion can contain a compound statement.
+TEST(MyDeathTest, CompoundStatement) {
+  // Verifies that at lease one of Bar(0), Bar(1), ..., and
+  // Bar(4) dies.
+  ASSERT_DEATH({
+    for (int i = 0; i < 5; i++) {
+      Bar(i);
+    }
+  },
+  "Bar has \\d+ errors");}
+```
+
+`googletest_unittest.cc` contains more examples if you are interested.
+
+## What syntax does the regular expression in ASSERT\_DEATH use? ##
+
+On POSIX systems, Google Test uses the POSIX Extended regular
+expression syntax
+(http://en.wikipedia.org/wiki/Regular_expression#POSIX_Extended_Regular_Expressions).
+On Windows, it uses a limited variant of regular expression
+syntax. For more details, see the
+[regular expression syntax](V1_6_AdvancedGuide#Regular_Expression_Syntax.md).
+
+## I have a fixture class Foo, but TEST\_F(Foo, Bar) gives me error "no matching function for call to Foo::Foo()". Why? ##
+
+Google Test needs to be able to create objects of your test fixture class, so
+it must have a default constructor. Normally the compiler will define one for
+you. However, there are cases where you have to define your own:
+  * If you explicitly declare a non-default constructor for class `Foo`, then you need to define a default constructor, even if it would be empty.
+  * If `Foo` has a const non-static data member, then you have to define the default constructor _and_ initialize the const member in the initializer list of the constructor. (Early versions of `gcc` doesn't force you to initialize the const member. It's a bug that has been fixed in `gcc 4`.)
+
+## Why does ASSERT\_DEATH complain about previous threads that were already joined? ##
+
+With the Linux pthread library, there is no turning back once you cross the
+line from single thread to multiple threads. The first time you create a
+thread, a manager thread is created in addition, so you get 3, not 2, threads.
+Later when the thread you create joins the main thread, the thread count
+decrements by 1, but the manager thread will never be killed, so you still have
+2 threads, which means you cannot safely run a death test.
+
+The new NPTL thread library doesn't suffer from this problem, as it doesn't
+create a manager thread. However, if you don't control which machine your test
+runs on, you shouldn't depend on this.
+
+## Why does Google Test require the entire test case, instead of individual tests, to be named FOODeathTest when it uses ASSERT\_DEATH? ##
+
+Google Test does not interleave tests from different test cases. That is, it
+runs all tests in one test case first, and then runs all tests in the next test
+case, and so on. Google Test does this because it needs to set up a test case
+before the first test in it is run, and tear it down afterwords. Splitting up
+the test case would require multiple set-up and tear-down processes, which is
+inefficient and makes the semantics unclean.
+
+If we were to determine the order of tests based on test name instead of test
+case name, then we would have a problem with the following situation:
+
+```
+TEST_F(FooTest, AbcDeathTest) { ... }
+TEST_F(FooTest, Uvw) { ... }
+
+TEST_F(BarTest, DefDeathTest) { ... }
+TEST_F(BarTest, Xyz) { ... }
+```
+
+Since `FooTest.AbcDeathTest` needs to run before `BarTest.Xyz`, and we don't
+interleave tests from different test cases, we need to run all tests in the
+`FooTest` case before running any test in the `BarTest` case. This contradicts
+with the requirement to run `BarTest.DefDeathTest` before `FooTest.Uvw`.
+
+## But I don't like calling my entire test case FOODeathTest when it contains both death tests and non-death tests. What do I do? ##
+
+You don't have to, but if you like, you may split up the test case into
+`FooTest` and `FooDeathTest`, where the names make it clear that they are
+related:
+
+```
+class FooTest : public ::testing::Test { ... };
+
+TEST_F(FooTest, Abc) { ... }
+TEST_F(FooTest, Def) { ... }
+
+typedef FooTest FooDeathTest;
+
+TEST_F(FooDeathTest, Uvw) { ... EXPECT_DEATH(...) ... }
+TEST_F(FooDeathTest, Xyz) { ... ASSERT_DEATH(...) ... }
+```
+
+## The compiler complains about "no match for 'operator<<'" when I use an assertion. What gives? ##
+
+If you use a user-defined type `FooType` in an assertion, you must make sure
+there is an `std::ostream& operator<<(std::ostream&, const FooType&)` function
+defined such that we can print a value of `FooType`.
+
+In addition, if `FooType` is declared in a name space, the `<<` operator also
+needs to be defined in the _same_ name space.
+
+## How do I suppress the memory leak messages on Windows? ##
+
+Since the statically initialized Google Test singleton requires allocations on
+the heap, the Visual C++ memory leak detector will report memory leaks at the
+end of the program run. The easiest way to avoid this is to use the
+`_CrtMemCheckpoint` and `_CrtMemDumpAllObjectsSince` calls to not report any
+statically initialized heap objects. See MSDN for more details and additional
+heap check/debug routines.
+
+## I am building my project with Google Test in Visual Studio and all I'm getting is a bunch of linker errors (or warnings). Help! ##
+
+You may get a number of the following linker error or warnings if you
+attempt to link your test project with the Google Test library when
+your project and the are not built using the same compiler settings.
+
+  * LNK2005: symbol already defined in object
+  * LNK4217: locally defined symbol 'symbol' imported in function 'function'
+  * LNK4049: locally defined symbol 'symbol' imported
+
+The Google Test project (gtest.vcproj) has the Runtime Library option
+set to /MT (use multi-threaded static libraries, /MTd for debug). If
+your project uses something else, for example /MD (use multi-threaded
+DLLs, /MDd for debug), you need to change the setting in the Google
+Test project to match your project's.
+
+To update this setting open the project properties in the Visual
+Studio IDE then select the branch Configuration Properties | C/C++ |
+Code Generation and change the option "Runtime Library".  You may also try
+using gtest-md.vcproj instead of gtest.vcproj.
+
+## I put my tests in a library and Google Test doesn't run them. What's happening? ##
+Have you read a
+[warning](http://code.google.com/p/googletest/wiki/V1_6_Primer#Important_note_for_Visual_C++_users) on
+the Google Test Primer page?
+
+## I want to use Google Test with Visual Studio but don't know where to start. ##
+Many people are in your position and one of the posted his solution to
+our mailing list. Here is his link:
+http://hassanjamilahmad.blogspot.com/2009/07/gtest-starters-help.html.
+
+## I am seeing compile errors mentioning std::type\_traits when I try to use Google Test on Solaris. ##
+Google Test uses parts of the standard C++ library that SunStudio does not support.
+Our users reported success using alternative implementations. Try running the build after runing this commad:
+
+`export CC=cc CXX=CC CXXFLAGS='-library=stlport4'`
+
+## How can my code detect if it is running in a test? ##
+
+If you write code that sniffs whether it's running in a test and does
+different things accordingly, you are leaking test-only logic into
+production code and there is no easy way to ensure that the test-only
+code paths aren't run by mistake in production.  Such cleverness also
+leads to
+[Heisenbugs](http://en.wikipedia.org/wiki/Unusual_software_bug#Heisenbug).
+Therefore we strongly advise against the practice, and Google Test doesn't
+provide a way to do it.
+
+In general, the recommended way to cause the code to behave
+differently under test is [dependency injection](http://jamesshore.com/Blog/Dependency-Injection-Demystified.html).
+You can inject different functionality from the test and from the
+production code.  Since your production code doesn't link in the
+for-test logic at all, there is no danger in accidentally running it.
+
+However, if you _really_, _really_, _really_ have no choice, and if
+you follow the rule of ending your test program names with `_test`,
+you can use the _horrible_ hack of sniffing your executable name
+(`argv[0]` in `main()`) to know whether the code is under test.
+
+## Google Test defines a macro that clashes with one defined by another library. How do I deal with that? ##
+
+In C++, macros don't obey namespaces.  Therefore two libraries that
+both define a macro of the same name will clash if you #include both
+definitions.  In case a Google Test macro clashes with another
+library, you can force Google Test to rename its macro to avoid the
+conflict.
+
+Specifically, if both Google Test and some other code define macro
+`FOO`, you can add
+```
+  -DGTEST_DONT_DEFINE_FOO=1
+```
+to the compiler flags to tell Google Test to change the macro's name
+from `FOO` to `GTEST_FOO`. For example, with `-DGTEST_DONT_DEFINE_TEST=1`, you'll need to write
+```
+  GTEST_TEST(SomeTest, DoesThis) { ... }
+```
+instead of
+```
+  TEST(SomeTest, DoesThis) { ... }
+```
+in order to define a test.
+
+Currently, the following `TEST`, `FAIL`, `SUCCEED`, and the basic comparison assertion macros can have alternative names. You can see the full list of covered macros [here](http://www.google.com/codesearch?q=if+!GTEST_DONT_DEFINE_\w%2B+package:http://googletest\.googlecode\.com+file:/include/gtest/gtest.h). More information can be found in the "Avoiding Macro Name Clashes" section of the README file.
+
+## My question is not covered in your FAQ! ##
+
+If you cannot find the answer to your question in this FAQ, there are
+some other resources you can use:
+
+  1. read other [wiki pages](http://code.google.com/p/googletest/w/list),
+  1. search the mailing list [archive](http://groups.google.com/group/googletestframework/topics),
+  1. ask it on [googletestframework@googlegroups.com](mailto:googletestframework@googlegroups.com) and someone will answer it (to prevent spam, we require you to join the [discussion group](http://groups.google.com/group/googletestframework) before you can post.).
+
+Please note that creating an issue in the
+[issue tracker](http://code.google.com/p/googletest/issues/list) is _not_
+a good way to get your answer, as it is monitored infrequently by a
+very small number of people.
+
+When asking a question, it's helpful to provide as much of the
+following information as possible (people cannot help you if there's
+not enough information in your question):
+
+  * the version (or the revision number if you check out from SVN directly) of Google Test you use (Google Test is under active development, so it's possible that your problem has been solved in a later version),
+  * your operating system,
+  * the name and version of your compiler,
+  * the complete command line flags you give to your compiler,
+  * the complete compiler error messages (if the question is about compilation),
+  * the _actual_ code (ideally, a minimal but complete program) that has the problem you encounter.
\ No newline at end of file
diff --git a/third_party/googletest/googletest/docs/V1_6_Primer.md b/third_party/googletest/googletest/docs/V1_6_Primer.md
new file mode 100644
index 0000000..2c51a21
--- /dev/null
+++ b/third_party/googletest/googletest/docs/V1_6_Primer.md
@@ -0,0 +1,501 @@
+
+
+# Introduction: Why Google C++ Testing Framework? #
+
+_Google C++ Testing Framework_ helps you write better C++ tests.
+
+No matter whether you work on Linux, Windows, or a Mac, if you write C++ code,
+Google Test can help you.
+
+So what makes a good test, and how does Google C++ Testing Framework fit in? We believe:
+  1. Tests should be _independent_ and _repeatable_. It's a pain to debug a test that succeeds or fails as a result of other tests.  Google C++ Testing Framework isolates the tests by running each of them on a different object. When a test fails, Google C++ Testing Framework allows you to run it in isolation for quick debugging.
+  1. Tests should be well _organized_ and reflect the structure of the tested code.  Google C++ Testing Framework groups related tests into test cases that can share data and subroutines. This common pattern is easy to recognize and makes tests easy to maintain. Such consistency is especially helpful when people switch projects and start to work on a new code base.
+  1. Tests should be _portable_ and _reusable_. The open-source community has a lot of code that is platform-neutral, its tests should also be platform-neutral.  Google C++ Testing Framework works on different OSes, with different compilers (gcc, MSVC, and others), with or without exceptions, so Google C++ Testing Framework tests can easily work with a variety of configurations.  (Note that the current release only contains build scripts for Linux - we are actively working on scripts for other platforms.)
+  1. When tests fail, they should provide as much _information_ about the problem as possible. Google C++ Testing Framework doesn't stop at the first test failure. Instead, it only stops the current test and continues with the next. You can also set up tests that report non-fatal failures after which the current test continues. Thus, you can detect and fix multiple bugs in a single run-edit-compile cycle.
+  1. The testing framework should liberate test writers from housekeeping chores and let them focus on the test _content_.  Google C++ Testing Framework automatically keeps track of all tests defined, and doesn't require the user to enumerate them in order to run them.
+  1. Tests should be _fast_. With Google C++ Testing Framework, you can reuse shared resources across tests and pay for the set-up/tear-down only once, without making tests depend on each other.
+
+Since Google C++ Testing Framework is based on the popular xUnit
+architecture, you'll feel right at home if you've used JUnit or PyUnit before.
+If not, it will take you about 10 minutes to learn the basics and get started.
+So let's go!
+
+_Note:_ We sometimes refer to Google C++ Testing Framework informally
+as _Google Test_.
+
+# Setting up a New Test Project #
+
+To write a test program using Google Test, you need to compile Google
+Test into a library and link your test with it.  We provide build
+files for some popular build systems: `msvc/` for Visual Studio,
+`xcode/` for Mac Xcode, `make/` for GNU make, `codegear/` for Borland
+C++ Builder, and the autotools script (deprecated) and
+`CMakeLists.txt` for CMake (recommended) in the Google Test root
+directory.  If your build system is not on this list, you can take a
+look at `make/Makefile` to learn how Google Test should be compiled
+(basically you want to compile `src/gtest-all.cc` with `GTEST_ROOT`
+and `GTEST_ROOT/include` in the header search path, where `GTEST_ROOT`
+is the Google Test root directory).
+
+Once you are able to compile the Google Test library, you should
+create a project or build target for your test program.  Make sure you
+have `GTEST_ROOT/include` in the header search path so that the
+compiler can find `"gtest/gtest.h"` when compiling your test.  Set up
+your test project to link with the Google Test library (for example,
+in Visual Studio, this is done by adding a dependency on
+`gtest.vcproj`).
+
+If you still have questions, take a look at how Google Test's own
+tests are built and use them as examples.
+
+# Basic Concepts #
+
+When using Google Test, you start by writing _assertions_, which are statements
+that check whether a condition is true. An assertion's result can be _success_,
+_nonfatal failure_, or _fatal failure_. If a fatal failure occurs, it aborts
+the current function; otherwise the program continues normally.
+
+_Tests_ use assertions to verify the tested code's behavior. If a test crashes
+or has a failed assertion, then it _fails_; otherwise it _succeeds_.
+
+A _test case_ contains one or many tests. You should group your tests into test
+cases that reflect the structure of the tested code. When multiple tests in a
+test case need to share common objects and subroutines, you can put them into a
+_test fixture_ class.
+
+A _test program_ can contain multiple test cases.
+
+We'll now explain how to write a test program, starting at the individual
+assertion level and building up to tests and test cases.
+
+# Assertions #
+
+Google Test assertions are macros that resemble function calls. You test a
+class or function by making assertions about its behavior. When an assertion
+fails, Google Test prints the assertion's source file and line number location,
+along with a failure message. You may also supply a custom failure message
+which will be appended to Google Test's message.
+
+The assertions come in pairs that test the same thing but have different
+effects on the current function. `ASSERT_*` versions generate fatal failures
+when they fail, and **abort the current function**. `EXPECT_*` versions generate
+nonfatal failures, which don't abort the current function. Usually `EXPECT_*`
+are preferred, as they allow more than one failures to be reported in a test.
+However, you should use `ASSERT_*` if it doesn't make sense to continue when
+the assertion in question fails.
+
+Since a failed `ASSERT_*` returns from the current function immediately,
+possibly skipping clean-up code that comes after it, it may cause a space leak.
+Depending on the nature of the leak, it may or may not be worth fixing - so
+keep this in mind if you get a heap checker error in addition to assertion
+errors.
+
+To provide a custom failure message, simply stream it into the macro using the
+`<<` operator, or a sequence of such operators. An example:
+```
+ASSERT_EQ(x.size(), y.size()) << "Vectors x and y are of unequal length";
+
+for (int i = 0; i < x.size(); ++i) {
+  EXPECT_EQ(x[i], y[i]) << "Vectors x and y differ at index " << i;
+}
+```
+
+Anything that can be streamed to an `ostream` can be streamed to an assertion
+macro--in particular, C strings and `string` objects. If a wide string
+(`wchar_t*`, `TCHAR*` in `UNICODE` mode on Windows, or `std::wstring`) is
+streamed to an assertion, it will be translated to UTF-8 when printed.
+
+## Basic Assertions ##
+
+These assertions do basic true/false condition testing.
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_TRUE(`_condition_`)`;  | `EXPECT_TRUE(`_condition_`)`;   | _condition_ is true |
+| `ASSERT_FALSE(`_condition_`)`; | `EXPECT_FALSE(`_condition_`)`;  | _condition_ is false |
+
+Remember, when they fail, `ASSERT_*` yields a fatal failure and
+returns from the current function, while `EXPECT_*` yields a nonfatal
+failure, allowing the function to continue running. In either case, an
+assertion failure means its containing test fails.
+
+_Availability_: Linux, Windows, Mac.
+
+## Binary Comparison ##
+
+This section describes assertions that compare two values.
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+|`ASSERT_EQ(`_expected_`, `_actual_`);`|`EXPECT_EQ(`_expected_`, `_actual_`);`| _expected_ `==` _actual_ |
+|`ASSERT_NE(`_val1_`, `_val2_`);`      |`EXPECT_NE(`_val1_`, `_val2_`);`      | _val1_ `!=` _val2_ |
+|`ASSERT_LT(`_val1_`, `_val2_`);`      |`EXPECT_LT(`_val1_`, `_val2_`);`      | _val1_ `<` _val2_ |
+|`ASSERT_LE(`_val1_`, `_val2_`);`      |`EXPECT_LE(`_val1_`, `_val2_`);`      | _val1_ `<=` _val2_ |
+|`ASSERT_GT(`_val1_`, `_val2_`);`      |`EXPECT_GT(`_val1_`, `_val2_`);`      | _val1_ `>` _val2_ |
+|`ASSERT_GE(`_val1_`, `_val2_`);`      |`EXPECT_GE(`_val1_`, `_val2_`);`      | _val1_ `>=` _val2_ |
+
+In the event of a failure, Google Test prints both _val1_ and _val2_
+. In `ASSERT_EQ*` and `EXPECT_EQ*` (and all other equality assertions
+we'll introduce later), you should put the expression you want to test
+in the position of _actual_, and put its expected value in _expected_,
+as Google Test's failure messages are optimized for this convention.
+
+Value arguments must be comparable by the assertion's comparison
+operator or you'll get a compiler error.  We used to require the
+arguments to support the `<<` operator for streaming to an `ostream`,
+but it's no longer necessary since v1.6.0 (if `<<` is supported, it
+will be called to print the arguments when the assertion fails;
+otherwise Google Test will attempt to print them in the best way it
+can. For more details and how to customize the printing of the
+arguments, see this Google Mock [recipe](http://code.google.com/p/googlemock/wiki/CookBook#Teaching_Google_Mock_How_to_Print_Your_Values).).
+
+These assertions can work with a user-defined type, but only if you define the
+corresponding comparison operator (e.g. `==`, `<`, etc).  If the corresponding
+operator is defined, prefer using the `ASSERT_*()` macros because they will
+print out not only the result of the comparison, but the two operands as well.
+
+Arguments are always evaluated exactly once. Therefore, it's OK for the
+arguments to have side effects. However, as with any ordinary C/C++ function,
+the arguments' evaluation order is undefined (i.e. the compiler is free to
+choose any order) and your code should not depend on any particular argument
+evaluation order.
+
+`ASSERT_EQ()` does pointer equality on pointers. If used on two C strings, it
+tests if they are in the same memory location, not if they have the same value.
+Therefore, if you want to compare C strings (e.g. `const char*`) by value, use
+`ASSERT_STREQ()` , which will be described later on. In particular, to assert
+that a C string is `NULL`, use `ASSERT_STREQ(NULL, c_string)` . However, to
+compare two `string` objects, you should use `ASSERT_EQ`.
+
+Macros in this section work with both narrow and wide string objects (`string`
+and `wstring`).
+
+_Availability_: Linux, Windows, Mac.
+
+## String Comparison ##
+
+The assertions in this group compare two **C strings**. If you want to compare
+two `string` objects, use `EXPECT_EQ`, `EXPECT_NE`, and etc instead.
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_STREQ(`_expected\_str_`, `_actual\_str_`);`    | `EXPECT_STREQ(`_expected\_str_`, `_actual\_str_`);`     | the two C strings have the same content |
+| `ASSERT_STRNE(`_str1_`, `_str2_`);`    | `EXPECT_STRNE(`_str1_`, `_str2_`);`     | the two C strings have different content |
+| `ASSERT_STRCASEEQ(`_expected\_str_`, `_actual\_str_`);`| `EXPECT_STRCASEEQ(`_expected\_str_`, `_actual\_str_`);` | the two C strings have the same content, ignoring case |
+| `ASSERT_STRCASENE(`_str1_`, `_str2_`);`| `EXPECT_STRCASENE(`_str1_`, `_str2_`);` | the two C strings have different content, ignoring case |
+
+Note that "CASE" in an assertion name means that case is ignored.
+
+`*STREQ*` and `*STRNE*` also accept wide C strings (`wchar_t*`). If a
+comparison of two wide strings fails, their values will be printed as UTF-8
+narrow strings.
+
+A `NULL` pointer and an empty string are considered _different_.
+
+_Availability_: Linux, Windows, Mac.
+
+See also: For more string comparison tricks (substring, prefix, suffix, and
+regular expression matching, for example), see the [Advanced Google Test Guide](V1_6_AdvancedGuide.md).
+
+# Simple Tests #
+
+To create a test:
+  1. Use the `TEST()` macro to define and name a test function, These are ordinary C++ functions that don't return a value.
+  1. In this function, along with any valid C++ statements you want to include, use the various Google Test assertions to check values.
+  1. The test's result is determined by the assertions; if any assertion in the test fails (either fatally or non-fatally), or if the test crashes, the entire test fails. Otherwise, it succeeds.
+
+```
+TEST(test_case_name, test_name) {
+ ... test body ...
+}
+```
+
+
+`TEST()` arguments go from general to specific. The _first_ argument is the
+name of the test case, and the _second_ argument is the test's name within the
+test case. Both names must be valid C++ identifiers, and they should not contain underscore (`_`). A test's _full name_ consists of its containing test case and its
+individual name. Tests from different test cases can have the same individual
+name.
+
+For example, let's take a simple integer function:
+```
+int Factorial(int n); // Returns the factorial of n
+```
+
+A test case for this function might look like:
+```
+// Tests factorial of 0.
+TEST(FactorialTest, HandlesZeroInput) {
+  EXPECT_EQ(1, Factorial(0));
+}
+
+// Tests factorial of positive numbers.
+TEST(FactorialTest, HandlesPositiveInput) {
+  EXPECT_EQ(1, Factorial(1));
+  EXPECT_EQ(2, Factorial(2));
+  EXPECT_EQ(6, Factorial(3));
+  EXPECT_EQ(40320, Factorial(8));
+}
+```
+
+Google Test groups the test results by test cases, so logically-related tests
+should be in the same test case; in other words, the first argument to their
+`TEST()` should be the same. In the above example, we have two tests,
+`HandlesZeroInput` and `HandlesPositiveInput`, that belong to the same test
+case `FactorialTest`.
+
+_Availability_: Linux, Windows, Mac.
+
+# Test Fixtures: Using the Same Data Configuration for Multiple Tests #
+
+If you find yourself writing two or more tests that operate on similar data,
+you can use a _test fixture_. It allows you to reuse the same configuration of
+objects for several different tests.
+
+To create a fixture, just:
+  1. Derive a class from `::testing::Test` . Start its body with `protected:` or `public:` as we'll want to access fixture members from sub-classes.
+  1. Inside the class, declare any objects you plan to use.
+  1. If necessary, write a default constructor or `SetUp()` function to prepare the objects for each test. A common mistake is to spell `SetUp()` as `Setup()` with a small `u` - don't let that happen to you.
+  1. If necessary, write a destructor or `TearDown()` function to release any resources you allocated in `SetUp()` . To learn when you should use the constructor/destructor and when you should use `SetUp()/TearDown()`, read this [FAQ entry](http://code.google.com/p/googletest/wiki/V1_6_FAQ#Should_I_use_the_constructor/destructor_of_the_test_fixture_or_t).
+  1. If needed, define subroutines for your tests to share.
+
+When using a fixture, use `TEST_F()` instead of `TEST()` as it allows you to
+access objects and subroutines in the test fixture:
+```
+TEST_F(test_case_name, test_name) {
+ ... test body ...
+}
+```
+
+Like `TEST()`, the first argument is the test case name, but for `TEST_F()`
+this must be the name of the test fixture class. You've probably guessed: `_F`
+is for fixture.
+
+Unfortunately, the C++ macro system does not allow us to create a single macro
+that can handle both types of tests. Using the wrong macro causes a compiler
+error.
+
+Also, you must first define a test fixture class before using it in a
+`TEST_F()`, or you'll get the compiler error "`virtual outside class
+declaration`".
+
+For each test defined with `TEST_F()`, Google Test will:
+  1. Create a _fresh_ test fixture at runtime
+  1. Immediately initialize it via `SetUp()` ,
+  1. Run the test
+  1. Clean up by calling `TearDown()`
+  1. Delete the test fixture.  Note that different tests in the same test case have different test fixture objects, and Google Test always deletes a test fixture before it creates the next one. Google Test does not reuse the same test fixture for multiple tests. Any changes one test makes to the fixture do not affect other tests.
+
+As an example, let's write tests for a FIFO queue class named `Queue`, which
+has the following interface:
+```
+template <typename E> // E is the element type.
+class Queue {
+ public:
+  Queue();
+  void Enqueue(const E& element);
+  E* Dequeue(); // Returns NULL if the queue is empty.
+  size_t size() const;
+  ...
+};
+```
+
+First, define a fixture class. By convention, you should give it the name
+`FooTest` where `Foo` is the class being tested.
+```
+class QueueTest : public ::testing::Test {
+ protected:
+  virtual void SetUp() {
+    q1_.Enqueue(1);
+    q2_.Enqueue(2);
+    q2_.Enqueue(3);
+  }
+
+  // virtual void TearDown() {}
+
+  Queue<int> q0_;
+  Queue<int> q1_;
+  Queue<int> q2_;
+};
+```
+
+In this case, `TearDown()` is not needed since we don't have to clean up after
+each test, other than what's already done by the destructor.
+
+Now we'll write tests using `TEST_F()` and this fixture.
+```
+TEST_F(QueueTest, IsEmptyInitially) {
+  EXPECT_EQ(0, q0_.size());
+}
+
+TEST_F(QueueTest, DequeueWorks) {
+  int* n = q0_.Dequeue();
+  EXPECT_EQ(NULL, n);
+
+  n = q1_.Dequeue();
+  ASSERT_TRUE(n != NULL);
+  EXPECT_EQ(1, *n);
+  EXPECT_EQ(0, q1_.size());
+  delete n;
+
+  n = q2_.Dequeue();
+  ASSERT_TRUE(n != NULL);
+  EXPECT_EQ(2, *n);
+  EXPECT_EQ(1, q2_.size());
+  delete n;
+}
+```
+
+The above uses both `ASSERT_*` and `EXPECT_*` assertions. The rule of thumb is
+to use `EXPECT_*` when you want the test to continue to reveal more errors
+after the assertion failure, and use `ASSERT_*` when continuing after failure
+doesn't make sense. For example, the second assertion in the `Dequeue` test is
+`ASSERT_TRUE(n != NULL)`, as we need to dereference the pointer `n` later,
+which would lead to a segfault when `n` is `NULL`.
+
+When these tests run, the following happens:
+  1. Google Test constructs a `QueueTest` object (let's call it `t1` ).
+  1. `t1.SetUp()` initializes `t1` .
+  1. The first test ( `IsEmptyInitially` ) runs on `t1` .
+  1. `t1.TearDown()` cleans up after the test finishes.
+  1. `t1` is destructed.
+  1. The above steps are repeated on another `QueueTest` object, this time running the `DequeueWorks` test.
+
+_Availability_: Linux, Windows, Mac.
+
+_Note_: Google Test automatically saves all _Google Test_ flags when a test
+object is constructed, and restores them when it is destructed.
+
+# Invoking the Tests #
+
+`TEST()` and `TEST_F()` implicitly register their tests with Google Test. So, unlike with many other C++ testing frameworks, you don't have to re-list all your defined tests in order to run them.
+
+After defining your tests, you can run them with `RUN_ALL_TESTS()` , which returns `0` if all the tests are successful, or `1` otherwise. Note that `RUN_ALL_TESTS()` runs _all tests_ in your link unit -- they can be from different test cases, or even different source files.
+
+When invoked, the `RUN_ALL_TESTS()` macro:
+  1. Saves the state of all  Google Test flags.
+  1. Creates a test fixture object for the first test.
+  1. Initializes it via `SetUp()`.
+  1. Runs the test on the fixture object.
+  1. Cleans up the fixture via `TearDown()`.
+  1. Deletes the fixture.
+  1. Restores the state of all Google Test flags.
+  1. Repeats the above steps for the next test, until all tests have run.
+
+In addition, if the text fixture's constructor generates a fatal failure in
+step 2, there is no point for step 3 - 5 and they are thus skipped. Similarly,
+if step 3 generates a fatal failure, step 4 will be skipped.
+
+_Important_: You must not ignore the return value of `RUN_ALL_TESTS()`, or `gcc`
+will give you a compiler error. The rationale for this design is that the
+automated testing service determines whether a test has passed based on its
+exit code, not on its stdout/stderr output; thus your `main()` function must
+return the value of `RUN_ALL_TESTS()`.
+
+Also, you should call `RUN_ALL_TESTS()` only **once**. Calling it more than once
+conflicts with some advanced Google Test features (e.g. thread-safe death
+tests) and thus is not supported.
+
+_Availability_: Linux, Windows, Mac.
+
+# Writing the main() Function #
+
+You can start from this boilerplate:
+```
+#include "this/package/foo.h"
+#include "gtest/gtest.h"
+
+namespace {
+
+// The fixture for testing class Foo.
+class FooTest : public ::testing::Test {
+ protected:
+  // You can remove any or all of the following functions if its body
+  // is empty.
+
+  FooTest() {
+    // You can do set-up work for each test here.
+  }
+
+  virtual ~FooTest() {
+    // You can do clean-up work that doesn't throw exceptions here.
+  }
+
+  // If the constructor and destructor are not enough for setting up
+  // and cleaning up each test, you can define the following methods:
+
+  virtual void SetUp() {
+    // Code here will be called immediately after the constructor (right
+    // before each test).
+  }
+
+  virtual void TearDown() {
+    // Code here will be called immediately after each test (right
+    // before the destructor).
+  }
+
+  // Objects declared here can be used by all tests in the test case for Foo.
+};
+
+// Tests that the Foo::Bar() method does Abc.
+TEST_F(FooTest, MethodBarDoesAbc) {
+  const string input_filepath = "this/package/testdata/myinputfile.dat";
+  const string output_filepath = "this/package/testdata/myoutputfile.dat";
+  Foo f;
+  EXPECT_EQ(0, f.Bar(input_filepath, output_filepath));
+}
+
+// Tests that Foo does Xyz.
+TEST_F(FooTest, DoesXyz) {
+  // Exercises the Xyz feature of Foo.
+}
+
+}  // namespace
+
+int main(int argc, char **argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
+```
+
+The `::testing::InitGoogleTest()` function parses the command line for Google
+Test flags, and removes all recognized flags. This allows the user to control a
+test program's behavior via various flags, which we'll cover in [AdvancedGuide](V1_6_AdvancedGuide.md).
+You must call this function before calling `RUN_ALL_TESTS()`, or the flags
+won't be properly initialized.
+
+On Windows, `InitGoogleTest()` also works with wide strings, so it can be used
+in programs compiled in `UNICODE` mode as well.
+
+But maybe you think that writing all those main() functions is too much work? We agree with you completely and that's why Google Test provides a basic implementation of main(). If it fits your needs, then just link your test with gtest\_main library and you are good to go.
+
+## Important note for Visual C++ users ##
+If you put your tests into a library and your `main()` function is in a different library or in your .exe file, those tests will not run. The reason is a [bug](https://connect.microsoft.com/feedback/viewfeedback.aspx?FeedbackID=244410&siteid=210) in Visual C++. When you define your tests, Google Test creates certain static objects to register them. These objects are not referenced from elsewhere but their constructors are still supposed to run. When Visual C++ linker sees that nothing in the library is referenced from other places it throws the library out. You have to reference your library with tests from your main program to keep the linker from discarding it. Here is how to do it. Somewhere in your library code declare a function:
+```
+__declspec(dllexport) int PullInMyLibrary() { return 0; }
+```
+If you put your tests in a static library (not DLL) then `__declspec(dllexport)` is not required. Now, in your main program, write a code that invokes that function:
+```
+int PullInMyLibrary();
+static int dummy = PullInMyLibrary();
+```
+This will keep your tests referenced and will make them register themselves at startup.
+
+In addition, if you define your tests in a static library, add `/OPT:NOREF` to your main program linker options. If you use MSVC++ IDE, go to your .exe project properties/Configuration Properties/Linker/Optimization and set References setting to `Keep Unreferenced Data (/OPT:NOREF)`. This will keep Visual C++ linker from discarding individual symbols generated by your tests from the final executable.
+
+There is one more pitfall, though. If you use Google Test as a static library (that's how it is defined in gtest.vcproj) your tests must also reside in a static library. If you have to have them in a DLL, you _must_ change Google Test to build into a DLL as well. Otherwise your tests will not run correctly or will not run at all. The general conclusion here is: make your life easier - do not write your tests in libraries!
+
+# Where to Go from Here #
+
+Congratulations! You've learned the Google Test basics. You can start writing
+and running Google Test tests, read some [samples](V1_6_Samples.md), or continue with
+[AdvancedGuide](V1_6_AdvancedGuide.md), which describes many more useful Google Test features.
+
+# Known Limitations #
+
+Google Test is designed to be thread-safe.  The implementation is
+thread-safe on systems where the `pthreads` library is available.  It
+is currently _unsafe_ to use Google Test assertions from two threads
+concurrently on other systems (e.g. Windows).  In most tests this is
+not an issue as usually the assertions are done in the main thread. If
+you want to help, you can volunteer to implement the necessary
+synchronization primitives in `gtest-port.h` for your platform.
\ No newline at end of file
diff --git a/third_party/googletest/googletest/docs/V1_6_PumpManual.md b/third_party/googletest/googletest/docs/V1_6_PumpManual.md
new file mode 100644
index 0000000..cf6cf56
--- /dev/null
+++ b/third_party/googletest/googletest/docs/V1_6_PumpManual.md
@@ -0,0 +1,177 @@
+
+
+<b>P</b>ump is <b>U</b>seful for <b>M</b>eta <b>P</b>rogramming.
+
+# The Problem #
+
+Template and macro libraries often need to define many classes,
+functions, or macros that vary only (or almost only) in the number of
+arguments they take. It's a lot of repetitive, mechanical, and
+error-prone work.
+
+Variadic templates and variadic macros can alleviate the problem.
+However, while both are being considered by the C++ committee, neither
+is in the standard yet or widely supported by compilers.  Thus they
+are often not a good choice, especially when your code needs to be
+portable. And their capabilities are still limited.
+
+As a result, authors of such libraries often have to write scripts to
+generate their implementation. However, our experience is that it's
+tedious to write such scripts, which tend to reflect the structure of
+the generated code poorly and are often hard to read and edit. For
+example, a small change needed in the generated code may require some
+non-intuitive, non-trivial changes in the script. This is especially
+painful when experimenting with the code.
+
+# Our Solution #
+
+Pump (for Pump is Useful for Meta Programming, Pretty Useful for Meta
+Programming, or Practical Utility for Meta Programming, whichever you
+prefer) is a simple meta-programming tool for C++. The idea is that a
+programmer writes a `foo.pump` file which contains C++ code plus meta
+code that manipulates the C++ code. The meta code can handle
+iterations over a range, nested iterations, local meta variable
+definitions, simple arithmetic, and conditional expressions. You can
+view it as a small Domain-Specific Language. The meta language is
+designed to be non-intrusive (s.t. it won't confuse Emacs' C++ mode,
+for example) and concise, making Pump code intuitive and easy to
+maintain.
+
+## Highlights ##
+
+  * The implementation is in a single Python script and thus ultra portable: no build or installation is needed and it works cross platforms.
+  * Pump tries to be smart with respect to [Google's style guide](http://code.google.com/p/google-styleguide/): it breaks long lines (easy to have when they are generated) at acceptable places to fit within 80 columns and indent the continuation lines correctly.
+  * The format is human-readable and more concise than XML.
+  * The format works relatively well with Emacs' C++ mode.
+
+## Examples ##
+
+The following Pump code (where meta keywords start with `$`, `[[` and `]]` are meta brackets, and `$$` starts a meta comment that ends with the line):
+
+```
+$var n = 3     $$ Defines a meta variable n.
+$range i 0..n  $$ Declares the range of meta iterator i (inclusive).
+$for i [[
+               $$ Meta loop.
+// Foo$i does blah for $i-ary predicates.
+$range j 1..i
+template <size_t N $for j [[, typename A$j]]>
+class Foo$i {
+$if i == 0 [[
+  blah a;
+]] $elif i <= 2 [[
+  blah b;
+]] $else [[
+  blah c;
+]]
+};
+
+]]
+```
+
+will be translated by the Pump compiler to:
+
+```
+// Foo0 does blah for 0-ary predicates.
+template <size_t N>
+class Foo0 {
+  blah a;
+};
+
+// Foo1 does blah for 1-ary predicates.
+template <size_t N, typename A1>
+class Foo1 {
+  blah b;
+};
+
+// Foo2 does blah for 2-ary predicates.
+template <size_t N, typename A1, typename A2>
+class Foo2 {
+  blah b;
+};
+
+// Foo3 does blah for 3-ary predicates.
+template <size_t N, typename A1, typename A2, typename A3>
+class Foo3 {
+  blah c;
+};
+```
+
+In another example,
+
+```
+$range i 1..n
+Func($for i + [[a$i]]);
+$$ The text between i and [[ is the separator between iterations.
+```
+
+will generate one of the following lines (without the comments), depending on the value of `n`:
+
+```
+Func();              // If n is 0.
+Func(a1);            // If n is 1.
+Func(a1 + a2);       // If n is 2.
+Func(a1 + a2 + a3);  // If n is 3.
+// And so on...
+```
+
+## Constructs ##
+
+We support the following meta programming constructs:
+
+| `$var id = exp` | Defines a named constant value. `$id` is valid util the end of the current meta lexical block. |
+|:----------------|:-----------------------------------------------------------------------------------------------|
+| `$range id exp..exp` | Sets the range of an iteration variable, which can be reused in multiple loops later.          |
+| `$for id sep [[ code ]]` | Iteration. The range of `id` must have been defined earlier. `$id` is valid in `code`.         |
+| `$($)`          | Generates a single `$` character.                                                              |
+| `$id`           | Value of the named constant or iteration variable.                                             |
+| `$(exp)`        | Value of the expression.                                                                       |
+| `$if exp [[ code ]] else_branch` | Conditional.                                                                                   |
+| `[[ code ]]`    | Meta lexical block.                                                                            |
+| `cpp_code`      | Raw C++ code.                                                                                  |
+| `$$ comment`    | Meta comment.                                                                                  |
+
+**Note:** To give the user some freedom in formatting the Pump source
+code, Pump ignores a new-line character if it's right after `$for foo`
+or next to `[[` or `]]`. Without this rule you'll often be forced to write
+very long lines to get the desired output. Therefore sometimes you may
+need to insert an extra new-line in such places for a new-line to show
+up in your output.
+
+## Grammar ##
+
+```
+code ::= atomic_code*
+atomic_code ::= $var id = exp
+    | $var id = [[ code ]]
+    | $range id exp..exp
+    | $for id sep [[ code ]]
+    | $($)
+    | $id
+    | $(exp)
+    | $if exp [[ code ]] else_branch
+    | [[ code ]]
+    | cpp_code
+sep ::= cpp_code | empty_string
+else_branch ::= $else [[ code ]]
+    | $elif exp [[ code ]] else_branch
+    | empty_string
+exp ::= simple_expression_in_Python_syntax
+```
+
+## Code ##
+
+You can find the source code of Pump in [scripts/pump.py](http://code.google.com/p/googletest/source/browse/trunk/scripts/pump.py). It is still
+very unpolished and lacks automated tests, although it has been
+successfully used many times. If you find a chance to use it in your
+project, please let us know what you think!  We also welcome help on
+improving Pump.
+
+## Real Examples ##
+
+You can find real-world applications of Pump in [Google Test](http://www.google.com/codesearch?q=file%3A\.pump%24+package%3Ahttp%3A%2F%2Fgoogletest\.googlecode\.com) and [Google Mock](http://www.google.com/codesearch?q=file%3A\.pump%24+package%3Ahttp%3A%2F%2Fgooglemock\.googlecode\.com).  The source file `foo.h.pump` generates `foo.h`.
+
+## Tips ##
+
+  * If a meta variable is followed by a letter or digit, you can separate them using `[[]]`, which inserts an empty string. For example `Foo$j[[]]Helper` generate `Foo1Helper` when `j` is 1.
+  * To avoid extra-long Pump source lines, you can break a line anywhere you want by inserting `[[]]` followed by a new line. Since any new-line character next to `[[` or `]]` is ignored, the generated code won't contain this new line.
\ No newline at end of file
diff --git a/third_party/googletest/googletest/docs/V1_6_Samples.md b/third_party/googletest/googletest/docs/V1_6_Samples.md
new file mode 100644
index 0000000..8122569
--- /dev/null
+++ b/third_party/googletest/googletest/docs/V1_6_Samples.md
@@ -0,0 +1,14 @@
+If you're like us, you'd like to look at some Google Test sample code.  The
+[samples folder](http://code.google.com/p/googletest/source/browse/#svn/trunk/samples) has a number of well-commented samples showing how to use a
+variety of Google Test features.
+
+  * [Sample #1](http://code.google.com/p/googletest/source/browse/trunk/samples/sample1_unittest.cc) shows the basic steps of using Google Test to test C++ functions.
+  * [Sample #2](http://code.google.com/p/googletest/source/browse/trunk/samples/sample2_unittest.cc) shows a more complex unit test for a class with multiple member functions.
+  * [Sample #3](http://code.google.com/p/googletest/source/browse/trunk/samples/sample3_unittest.cc) uses a test fixture.
+  * [Sample #4](http://code.google.com/p/googletest/source/browse/trunk/samples/sample4_unittest.cc) is another basic example of using Google Test.
+  * [Sample #5](http://code.google.com/p/googletest/source/browse/trunk/samples/sample5_unittest.cc) teaches how to reuse a test fixture in multiple test cases by deriving sub-fixtures from it.
+  * [Sample #6](http://code.google.com/p/googletest/source/browse/trunk/samples/sample6_unittest.cc) demonstrates type-parameterized tests.
+  * [Sample #7](http://code.google.com/p/googletest/source/browse/trunk/samples/sample7_unittest.cc) teaches the basics of value-parameterized tests.
+  * [Sample #8](http://code.google.com/p/googletest/source/browse/trunk/samples/sample8_unittest.cc) shows using `Combine()` in value-parameterized tests.
+  * [Sample #9](http://code.google.com/p/googletest/source/browse/trunk/samples/sample9_unittest.cc) shows use of the listener API to modify Google Test's console output and the use of its reflection API to inspect test results.
+  * [Sample #10](http://code.google.com/p/googletest/source/browse/trunk/samples/sample10_unittest.cc) shows use of the listener API to implement a primitive memory leak checker.
\ No newline at end of file
diff --git a/third_party/googletest/googletest/docs/V1_6_XcodeGuide.md b/third_party/googletest/googletest/docs/V1_6_XcodeGuide.md
new file mode 100644
index 0000000..bf24bf5
--- /dev/null
+++ b/third_party/googletest/googletest/docs/V1_6_XcodeGuide.md
@@ -0,0 +1,93 @@
+
+
+This guide will explain how to use the Google Testing Framework in your Xcode projects on Mac OS X. This tutorial begins by quickly explaining what to do for experienced users. After the quick start, the guide goes provides additional explanation about each step.
+
+# Quick Start #
+
+Here is the quick guide for using Google Test in your Xcode project.
+
+  1. Download the source from the [website](http://code.google.com/p/googletest) using this command: `svn checkout http://googletest.googlecode.com/svn/trunk/ googletest-read-only`
+  1. Open up the `gtest.xcodeproj` in the `googletest-read-only/xcode/` directory and build the gtest.framework.
+  1. Create a new "Shell Tool" target in your Xcode project called something like "UnitTests"
+  1. Add the gtest.framework to your project and add it to the "Link Binary with Libraries" build phase of "UnitTests"
+  1. Add your unit test source code to the "Compile Sources" build phase of "UnitTests"
+  1. Edit the "UnitTests" executable and add an environment variable named "DYLD\_FRAMEWORK\_PATH" with a value equal to the path to the framework containing the gtest.framework relative to the compiled executable.
+  1. Build and Go
+
+The following sections further explain each of the steps listed above in depth, describing in more detail how to complete it including some variations.
+
+# Get the Source #
+
+Currently, the gtest.framework discussed here isn't available in a tagged release of Google Test, it is only available in the trunk. As explained at the Google Test [site](http://code.google.com/p/googletest/source/checkout">svn), you can get the code from anonymous SVN with this command:
+
+```
+svn checkout http://googletest.googlecode.com/svn/trunk/ googletest-read-only
+```
+
+Alternatively, if you are working with Subversion in your own code base, you can add Google Test as an external dependency to your own Subversion repository. By following this approach, everyone that checks out your svn repository will also receive a copy of Google Test (a specific version, if you wish) without having to check it out explicitly. This makes the set up of your project simpler and reduces the copied code in the repository.
+
+To use `svn:externals`, decide where you would like to have the external source reside. You might choose to put the external source inside the trunk, because you want it to be part of the branch when you make a release. However, keeping it outside the trunk in a version-tagged directory called something like `third-party/googletest/1.0.1`, is another option. Once the location is established, use `svn propedit svn:externals _directory_` to set the svn:externals property on a directory in your repository. This directory won't contain the code, but be its versioned parent directory.
+
+The command `svn propedit` will bring up your Subversion editor, making editing the long, (potentially multi-line) property simpler. This same method can be used to check out a tagged branch, by using the appropriate URL (e.g. `http://googletest.googlecode.com/svn/tags/release-1.0.1`). Additionally, the svn:externals property allows the specification of a particular revision of the trunk with the `-r_##_` option (e.g. `externals/src/googletest -r60 http://googletest.googlecode.com/svn/trunk`).
+
+Here is an example of using the svn:externals properties on a trunk (read via `svn propget`) of a project. This value checks out a copy of Google Test into the `trunk/externals/src/googletest/` directory.
+
+```
+[Computer:svn] user$ svn propget svn:externals trunk
+externals/src/googletest http://googletest.googlecode.com/svn/trunk
+```
+
+# Add the Framework to Your Project #
+
+The next step is to build and add the gtest.framework to your own project. This guide describes two common ways below.
+
+  * **Option 1** --- The simplest way to add Google Test to your own project, is to open gtest.xcodeproj (found in the xcode/ directory of the Google Test trunk) and build the framework manually. Then, add the built framework into your project using the "Add->Existing Framework..." from the context menu or "Project->Add..." from the main menu. The gtest.framework is relocatable and contains the headers and object code that you'll need to make tests. This method requires rebuilding every time you upgrade Google Test in your project.
+  * **Option 2** --- If you are going to be living off the trunk of Google Test, incorporating its latest features into your unit tests (or are a Google Test developer yourself). You'll want to rebuild the framework every time the source updates. to do this, you'll need to add the gtest.xcodeproj file, not the framework itself, to your own Xcode project. Then, from the build products that are revealed by the project's disclosure triangle, you can find the gtest.framework, which can be added to your targets (discussed below).
+
+# Make a Test Target #
+
+To start writing tests, make a new "Shell Tool" target. This target template is available under BSD, Cocoa, or Carbon. Add your unit test source code to the "Compile Sources" build phase of the target.
+
+Next, you'll want to add gtest.framework in two different ways, depending upon which option you chose above.
+
+  * **Option 1** --- During compilation, Xcode will need to know that you are linking against the gtest.framework. Add the gtest.framework to the "Link Binary with Libraries" build phase of your test target. This will include the Google Test headers in your header search path, and will tell the linker where to find the library.
+  * **Option 2** --- If your working out of the trunk, you'll also want to add gtest.framework to your "Link Binary with Libraries" build phase of your test target. In addition, you'll  want to add the gtest.framework as a dependency to your unit test target. This way, Xcode will make sure that gtest.framework is up to date, every time your build your target. Finally, if you don't share build directories with Google Test, you'll have to copy the gtest.framework into your own build products directory using a "Run Script" build phase.
+
+# Set Up the Executable Run Environment #
+
+Since the unit test executable is a shell tool, it doesn't have a bundle with a `Contents/Frameworks` directory, in which to place gtest.framework. Instead, the dynamic linker must be told at runtime to search for the framework in another location. This can be accomplished by setting the "DYLD\_FRAMEWORK\_PATH" environment variable in the "Edit Active Executable ..." Arguments tab, under "Variables to be set in the environment:". The path for this value is the path (relative or absolute) of the directory containing the gtest.framework.
+
+If you haven't set up the DYLD\_FRAMEWORK\_PATH, correctly, you might get a message like this:
+
+```
+[Session started at 2008-08-15 06:23:57 -0600.]
+  dyld: Library not loaded: @loader_path/../Frameworks/gtest.framework/Versions/A/gtest
+    Referenced from: /Users/username/Documents/Sandbox/gtestSample/build/Debug/WidgetFrameworkTest
+    Reason: image not found
+```
+
+To correct this problem, got to the directory containing the executable named in "Referenced from:" value in the error message above. Then, with the terminal in this location, find the relative path to the directory containing the gtest.framework. That is the value you'll need to set as the DYLD\_FRAMEWORK\_PATH.
+
+# Build and Go #
+
+Now, when you click "Build and Go", the test will be executed. Dumping out something like this:
+
+```
+[Session started at 2008-08-06 06:36:13 -0600.]
+[==========] Running 2 tests from 1 test case.
+[----------] Global test environment set-up.
+[----------] 2 tests from WidgetInitializerTest
+[ RUN      ] WidgetInitializerTest.TestConstructor
+[       OK ] WidgetInitializerTest.TestConstructor
+[ RUN      ] WidgetInitializerTest.TestConversion
+[       OK ] WidgetInitializerTest.TestConversion
+[----------] Global test environment tear-down
+[==========] 2 tests from 1 test case ran.
+[  PASSED  ] 2 tests.
+
+The Debugger has exited with status 0.  
+```
+
+# Summary #
+
+Unit testing is a valuable way to ensure your data model stays valid even during rapid development or refactoring. The Google Testing Framework is a great unit testing framework for C and C++ which integrates well with an Xcode development environment.
\ No newline at end of file
diff --git a/third_party/googletest/googletest/docs/V1_7_AdvancedGuide.md b/third_party/googletest/googletest/docs/V1_7_AdvancedGuide.md
new file mode 100644
index 0000000..a3d6462
--- /dev/null
+++ b/third_party/googletest/googletest/docs/V1_7_AdvancedGuide.md
@@ -0,0 +1,2181 @@
+
+
+Now that you have read [Primer](V1_7_Primer.md) and learned how to write tests
+using Google Test, it's time to learn some new tricks. This document
+will show you more assertions as well as how to construct complex
+failure messages, propagate fatal failures, reuse and speed up your
+test fixtures, and use various flags with your tests.
+
+# More Assertions #
+
+This section covers some less frequently used, but still significant,
+assertions.
+
+## Explicit Success and Failure ##
+
+These three assertions do not actually test a value or expression. Instead,
+they generate a success or failure directly. Like the macros that actually
+perform a test, you may stream a custom failure message into the them.
+
+| `SUCCEED();` |
+|:-------------|
+
+Generates a success. This does NOT make the overall test succeed. A test is
+considered successful only if none of its assertions fail during its execution.
+
+Note: `SUCCEED()` is purely documentary and currently doesn't generate any
+user-visible output. However, we may add `SUCCEED()` messages to Google Test's
+output in the future.
+
+| `FAIL();`  | `ADD_FAILURE();` | `ADD_FAILURE_AT("`_file\_path_`", `_line\_number_`);` |
+|:-----------|:-----------------|:------------------------------------------------------|
+
+`FAIL()` generates a fatal failure, while `ADD_FAILURE()` and `ADD_FAILURE_AT()` generate a nonfatal
+failure. These are useful when control flow, rather than a Boolean expression,
+deteremines the test's success or failure. For example, you might want to write
+something like:
+
+```
+switch(expression) {
+  case 1: ... some checks ...
+  case 2: ... some other checks
+  ...
+  default: FAIL() << "We shouldn't get here.";
+}
+```
+
+_Availability_: Linux, Windows, Mac.
+
+## Exception Assertions ##
+
+These are for verifying that a piece of code throws (or does not
+throw) an exception of the given type:
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_THROW(`_statement_, _exception\_type_`);`  | `EXPECT_THROW(`_statement_, _exception\_type_`);`  | _statement_ throws an exception of the given type  |
+| `ASSERT_ANY_THROW(`_statement_`);`                | `EXPECT_ANY_THROW(`_statement_`);`                | _statement_ throws an exception of any type        |
+| `ASSERT_NO_THROW(`_statement_`);`                 | `EXPECT_NO_THROW(`_statement_`);`                 | _statement_ doesn't throw any exception            |
+
+Examples:
+
+```
+ASSERT_THROW(Foo(5), bar_exception);
+
+EXPECT_NO_THROW({
+  int n = 5;
+  Bar(&n);
+});
+```
+
+_Availability_: Linux, Windows, Mac; since version 1.1.0.
+
+## Predicate Assertions for Better Error Messages ##
+
+Even though Google Test has a rich set of assertions, they can never be
+complete, as it's impossible (nor a good idea) to anticipate all the scenarios
+a user might run into. Therefore, sometimes a user has to use `EXPECT_TRUE()`
+to check a complex expression, for lack of a better macro. This has the problem
+of not showing you the values of the parts of the expression, making it hard to
+understand what went wrong. As a workaround, some users choose to construct the
+failure message by themselves, streaming it into `EXPECT_TRUE()`. However, this
+is awkward especially when the expression has side-effects or is expensive to
+evaluate.
+
+Google Test gives you three different options to solve this problem:
+
+### Using an Existing Boolean Function ###
+
+If you already have a function or a functor that returns `bool` (or a type
+that can be implicitly converted to `bool`), you can use it in a _predicate
+assertion_ to get the function arguments printed for free:
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_PRED1(`_pred1, val1_`);`       | `EXPECT_PRED1(`_pred1, val1_`);` | _pred1(val1)_ returns true |
+| `ASSERT_PRED2(`_pred2, val1, val2_`);` | `EXPECT_PRED2(`_pred2, val1, val2_`);` |  _pred2(val1, val2)_ returns true |
+|  ...                | ...                    | ...          |
+
+In the above, _predn_ is an _n_-ary predicate function or functor, where
+_val1_, _val2_, ..., and _valn_ are its arguments. The assertion succeeds
+if the predicate returns `true` when applied to the given arguments, and fails
+otherwise. When the assertion fails, it prints the value of each argument. In
+either case, the arguments are evaluated exactly once.
+
+Here's an example. Given
+
+```
+// Returns true iff m and n have no common divisors except 1.
+bool MutuallyPrime(int m, int n) { ... }
+const int a = 3;
+const int b = 4;
+const int c = 10;
+```
+
+the assertion `EXPECT_PRED2(MutuallyPrime, a, b);` will succeed, while the
+assertion `EXPECT_PRED2(MutuallyPrime, b, c);` will fail with the message
+
+<pre>
+!MutuallyPrime(b, c) is false, where<br>
+b is 4<br>
+c is 10<br>
+</pre>
+
+**Notes:**
+
+  1. If you see a compiler error "no matching function to call" when using `ASSERT_PRED*` or `EXPECT_PRED*`, please see [this](http://code.google.com/p/googletest/wiki/V1_7_FAQ#The_compiler_complains_%22no_matching_function_to_call%22) for how to resolve it.
+  1. Currently we only provide predicate assertions of arity <= 5. If you need a higher-arity assertion, let us know.
+
+_Availability_: Linux, Windows, Mac
+
+### Using a Function That Returns an AssertionResult ###
+
+While `EXPECT_PRED*()` and friends are handy for a quick job, the
+syntax is not satisfactory: you have to use different macros for
+different arities, and it feels more like Lisp than C++.  The
+`::testing::AssertionResult` class solves this problem.
+
+An `AssertionResult` object represents the result of an assertion
+(whether it's a success or a failure, and an associated message).  You
+can create an `AssertionResult` using one of these factory
+functions:
+
+```
+namespace testing {
+
+// Returns an AssertionResult object to indicate that an assertion has
+// succeeded.
+AssertionResult AssertionSuccess();
+
+// Returns an AssertionResult object to indicate that an assertion has
+// failed.
+AssertionResult AssertionFailure();
+
+}
+```
+
+You can then use the `<<` operator to stream messages to the
+`AssertionResult` object.
+
+To provide more readable messages in Boolean assertions
+(e.g. `EXPECT_TRUE()`), write a predicate function that returns
+`AssertionResult` instead of `bool`. For example, if you define
+`IsEven()` as:
+
+```
+::testing::AssertionResult IsEven(int n) {
+  if ((n % 2) == 0)
+    return ::testing::AssertionSuccess();
+  else
+    return ::testing::AssertionFailure() << n << " is odd";
+}
+```
+
+instead of:
+
+```
+bool IsEven(int n) {
+  return (n % 2) == 0;
+}
+```
+
+the failed assertion `EXPECT_TRUE(IsEven(Fib(4)))` will print:
+
+<pre>
+Value of: IsEven(Fib(4))<br>
+Actual: false (*3 is odd*)<br>
+Expected: true<br>
+</pre>
+
+instead of a more opaque
+
+<pre>
+Value of: IsEven(Fib(4))<br>
+Actual: false<br>
+Expected: true<br>
+</pre>
+
+If you want informative messages in `EXPECT_FALSE` and `ASSERT_FALSE`
+as well, and are fine with making the predicate slower in the success
+case, you can supply a success message:
+
+```
+::testing::AssertionResult IsEven(int n) {
+  if ((n % 2) == 0)
+    return ::testing::AssertionSuccess() << n << " is even";
+  else
+    return ::testing::AssertionFailure() << n << " is odd";
+}
+```
+
+Then the statement `EXPECT_FALSE(IsEven(Fib(6)))` will print
+
+<pre>
+Value of: IsEven(Fib(6))<br>
+Actual: true (8 is even)<br>
+Expected: false<br>
+</pre>
+
+_Availability_: Linux, Windows, Mac; since version 1.4.1.
+
+### Using a Predicate-Formatter ###
+
+If you find the default message generated by `(ASSERT|EXPECT)_PRED*` and
+`(ASSERT|EXPECT)_(TRUE|FALSE)` unsatisfactory, or some arguments to your
+predicate do not support streaming to `ostream`, you can instead use the
+following _predicate-formatter assertions_ to _fully_ customize how the
+message is formatted:
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_PRED_FORMAT1(`_pred\_format1, val1_`);`        | `EXPECT_PRED_FORMAT1(`_pred\_format1, val1_`); | _pred\_format1(val1)_ is successful |
+| `ASSERT_PRED_FORMAT2(`_pred\_format2, val1, val2_`);` | `EXPECT_PRED_FORMAT2(`_pred\_format2, val1, val2_`);` | _pred\_format2(val1, val2)_ is successful |
+| `...`               | `...`                  | `...`        |
+
+The difference between this and the previous two groups of macros is that instead of
+a predicate, `(ASSERT|EXPECT)_PRED_FORMAT*` take a _predicate-formatter_
+(_pred\_formatn_), which is a function or functor with the signature:
+
+`::testing::AssertionResult PredicateFormattern(const char* `_expr1_`, const char* `_expr2_`, ... const char* `_exprn_`, T1 `_val1_`, T2 `_val2_`, ... Tn `_valn_`);`
+
+where _val1_, _val2_, ..., and _valn_ are the values of the predicate
+arguments, and _expr1_, _expr2_, ..., and _exprn_ are the corresponding
+expressions as they appear in the source code. The types `T1`, `T2`, ..., and
+`Tn` can be either value types or reference types. For example, if an
+argument has type `Foo`, you can declare it as either `Foo` or `const Foo&`,
+whichever is appropriate.
+
+A predicate-formatter returns a `::testing::AssertionResult` object to indicate
+whether the assertion has succeeded or not. The only way to create such an
+object is to call one of these factory functions:
+
+As an example, let's improve the failure message in the previous example, which uses `EXPECT_PRED2()`:
+
+```
+// Returns the smallest prime common divisor of m and n,
+// or 1 when m and n are mutually prime.
+int SmallestPrimeCommonDivisor(int m, int n) { ... }
+
+// A predicate-formatter for asserting that two integers are mutually prime.
+::testing::AssertionResult AssertMutuallyPrime(const char* m_expr,
+                                               const char* n_expr,
+                                               int m,
+                                               int n) {
+  if (MutuallyPrime(m, n))
+    return ::testing::AssertionSuccess();
+ 
+  return ::testing::AssertionFailure()
+      << m_expr << " and " << n_expr << " (" << m << " and " << n
+      << ") are not mutually prime, " << "as they have a common divisor "
+      << SmallestPrimeCommonDivisor(m, n);
+}
+```
+
+With this predicate-formatter, we can use
+
+```
+EXPECT_PRED_FORMAT2(AssertMutuallyPrime, b, c);
+```
+
+to generate the message
+
+<pre>
+b and c (4 and 10) are not mutually prime, as they have a common divisor 2.<br>
+</pre>
+
+As you may have realized, many of the assertions we introduced earlier are
+special cases of `(EXPECT|ASSERT)_PRED_FORMAT*`. In fact, most of them are
+indeed defined using `(EXPECT|ASSERT)_PRED_FORMAT*`.
+
+_Availability_: Linux, Windows, Mac.
+
+
+## Floating-Point Comparison ##
+
+Comparing floating-point numbers is tricky. Due to round-off errors, it is
+very unlikely that two floating-points will match exactly. Therefore,
+`ASSERT_EQ` 's naive comparison usually doesn't work. And since floating-points
+can have a wide value range, no single fixed error bound works. It's better to
+compare by a fixed relative error bound, except for values close to 0 due to
+the loss of precision there.
+
+In general, for floating-point comparison to make sense, the user needs to
+carefully choose the error bound. If they don't want or care to, comparing in
+terms of Units in the Last Place (ULPs) is a good default, and Google Test
+provides assertions to do this. Full details about ULPs are quite long; if you
+want to learn more, see
+[this article on float comparison](http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm).
+
+### Floating-Point Macros ###
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_FLOAT_EQ(`_expected, actual_`);`  | `EXPECT_FLOAT_EQ(`_expected, actual_`);` | the two `float` values are almost equal |
+| `ASSERT_DOUBLE_EQ(`_expected, actual_`);` | `EXPECT_DOUBLE_EQ(`_expected, actual_`);` | the two `double` values are almost equal |
+
+By "almost equal", we mean the two values are within 4 ULP's from each
+other.
+
+The following assertions allow you to choose the acceptable error bound:
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_NEAR(`_val1, val2, abs\_error_`);` | `EXPECT_NEAR`_(val1, val2, abs\_error_`);` | the difference between _val1_ and _val2_ doesn't exceed the given absolute error |
+
+_Availability_: Linux, Windows, Mac.
+
+### Floating-Point Predicate-Format Functions ###
+
+Some floating-point operations are useful, but not that often used. In order
+to avoid an explosion of new macros, we provide them as predicate-format
+functions that can be used in predicate assertion macros (e.g.
+`EXPECT_PRED_FORMAT2`, etc).
+
+```
+EXPECT_PRED_FORMAT2(::testing::FloatLE, val1, val2);
+EXPECT_PRED_FORMAT2(::testing::DoubleLE, val1, val2);
+```
+
+Verifies that _val1_ is less than, or almost equal to, _val2_. You can
+replace `EXPECT_PRED_FORMAT2` in the above table with `ASSERT_PRED_FORMAT2`.
+
+_Availability_: Linux, Windows, Mac.
+
+## Windows HRESULT assertions ##
+
+These assertions test for `HRESULT` success or failure.
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_HRESULT_SUCCEEDED(`_expression_`);` | `EXPECT_HRESULT_SUCCEEDED(`_expression_`);` | _expression_ is a success `HRESULT` |
+| `ASSERT_HRESULT_FAILED(`_expression_`);`    | `EXPECT_HRESULT_FAILED(`_expression_`);`    | _expression_ is a failure `HRESULT` |
+
+The generated output contains the human-readable error message
+associated with the `HRESULT` code returned by _expression_.
+
+You might use them like this:
+
+```
+CComPtr shell;
+ASSERT_HRESULT_SUCCEEDED(shell.CoCreateInstance(L"Shell.Application"));
+CComVariant empty;
+ASSERT_HRESULT_SUCCEEDED(shell->ShellExecute(CComBSTR(url), empty, empty, empty, empty));
+```
+
+_Availability_: Windows.
+
+## Type Assertions ##
+
+You can call the function
+```
+::testing::StaticAssertTypeEq<T1, T2>();
+```
+to assert that types `T1` and `T2` are the same.  The function does
+nothing if the assertion is satisfied.  If the types are different,
+the function call will fail to compile, and the compiler error message
+will likely (depending on the compiler) show you the actual values of
+`T1` and `T2`.  This is mainly useful inside template code.
+
+_Caveat:_ When used inside a member function of a class template or a
+function template, `StaticAssertTypeEq<T1, T2>()` is effective _only if_
+the function is instantiated.  For example, given:
+```
+template <typename T> class Foo {
+ public:
+  void Bar() { ::testing::StaticAssertTypeEq<int, T>(); }
+};
+```
+the code:
+```
+void Test1() { Foo<bool> foo; }
+```
+will _not_ generate a compiler error, as `Foo<bool>::Bar()` is never
+actually instantiated.  Instead, you need:
+```
+void Test2() { Foo<bool> foo; foo.Bar(); }
+```
+to cause a compiler error.
+
+_Availability:_ Linux, Windows, Mac; since version 1.3.0.
+
+## Assertion Placement ##
+
+You can use assertions in any C++ function. In particular, it doesn't
+have to be a method of the test fixture class. The one constraint is
+that assertions that generate a fatal failure (`FAIL*` and `ASSERT_*`)
+can only be used in void-returning functions. This is a consequence of
+Google Test not using exceptions. By placing it in a non-void function
+you'll get a confusing compile error like
+`"error: void value not ignored as it ought to be"`.
+
+If you need to use assertions in a function that returns non-void, one option
+is to make the function return the value in an out parameter instead. For
+example, you can rewrite `T2 Foo(T1 x)` to `void Foo(T1 x, T2* result)`. You
+need to make sure that `*result` contains some sensible value even when the
+function returns prematurely. As the function now returns `void`, you can use
+any assertion inside of it.
+
+If changing the function's type is not an option, you should just use
+assertions that generate non-fatal failures, such as `ADD_FAILURE*` and
+`EXPECT_*`.
+
+_Note_: Constructors and destructors are not considered void-returning
+functions, according to the C++ language specification, and so you may not use
+fatal assertions in them. You'll get a compilation error if you try. A simple
+workaround is to transfer the entire body of the constructor or destructor to a
+private void-returning method. However, you should be aware that a fatal
+assertion failure in a constructor does not terminate the current test, as your
+intuition might suggest; it merely returns from the constructor early, possibly
+leaving your object in a partially-constructed state. Likewise, a fatal
+assertion failure in a destructor may leave your object in a
+partially-destructed state. Use assertions carefully in these situations!
+
+# Teaching Google Test How to Print Your Values #
+
+When a test assertion such as `EXPECT_EQ` fails, Google Test prints the
+argument values to help you debug.  It does this using a
+user-extensible value printer.
+
+This printer knows how to print built-in C++ types, native arrays, STL
+containers, and any type that supports the `<<` operator.  For other
+types, it prints the raw bytes in the value and hopes that you the
+user can figure it out.
+
+As mentioned earlier, the printer is _extensible_.  That means
+you can teach it to do a better job at printing your particular type
+than to dump the bytes.  To do that, define `<<` for your type:
+
+```
+#include <iostream>
+
+namespace foo {
+
+class Bar { ... };  // We want Google Test to be able to print instances of this.
+
+// It's important that the << operator is defined in the SAME
+// namespace that defines Bar.  C++'s look-up rules rely on that.
+::std::ostream& operator<<(::std::ostream& os, const Bar& bar) {
+  return os << bar.DebugString();  // whatever needed to print bar to os
+}
+
+}  // namespace foo
+```
+
+Sometimes, this might not be an option: your team may consider it bad
+style to have a `<<` operator for `Bar`, or `Bar` may already have a
+`<<` operator that doesn't do what you want (and you cannot change
+it).  If so, you can instead define a `PrintTo()` function like this:
+
+```
+#include <iostream>
+
+namespace foo {
+
+class Bar { ... };
+
+// It's important that PrintTo() is defined in the SAME
+// namespace that defines Bar.  C++'s look-up rules rely on that.
+void PrintTo(const Bar& bar, ::std::ostream* os) {
+  *os << bar.DebugString();  // whatever needed to print bar to os
+}
+
+}  // namespace foo
+```
+
+If you have defined both `<<` and `PrintTo()`, the latter will be used
+when Google Test is concerned.  This allows you to customize how the value
+appears in Google Test's output without affecting code that relies on the
+behavior of its `<<` operator.
+
+If you want to print a value `x` using Google Test's value printer
+yourself, just call `::testing::PrintToString(`_x_`)`, which
+returns an `std::string`:
+
+```
+vector<pair<Bar, int> > bar_ints = GetBarIntVector();
+
+EXPECT_TRUE(IsCorrectBarIntVector(bar_ints))
+    << "bar_ints = " << ::testing::PrintToString(bar_ints);
+```
+
+# Death Tests #
+
+In many applications, there are assertions that can cause application failure
+if a condition is not met. These sanity checks, which ensure that the program
+is in a known good state, are there to fail at the earliest possible time after
+some program state is corrupted. If the assertion checks the wrong condition,
+then the program may proceed in an erroneous state, which could lead to memory
+corruption, security holes, or worse. Hence it is vitally important to test
+that such assertion statements work as expected.
+
+Since these precondition checks cause the processes to die, we call such tests
+_death tests_. More generally, any test that checks that a program terminates
+(except by throwing an exception) in an expected fashion is also a death test.
+
+Note that if a piece of code throws an exception, we don't consider it "death"
+for the purpose of death tests, as the caller of the code could catch the exception
+and avoid the crash. If you want to verify exceptions thrown by your code,
+see [Exception Assertions](#Exception_Assertions.md).
+
+If you want to test `EXPECT_*()/ASSERT_*()` failures in your test code, see [Catching Failures](#Catching_Failures.md).
+
+## How to Write a Death Test ##
+
+Google Test has the following macros to support death tests:
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_DEATH(`_statement, regex_`); | `EXPECT_DEATH(`_statement, regex_`); | _statement_ crashes with the given error |
+| `ASSERT_DEATH_IF_SUPPORTED(`_statement, regex_`); | `EXPECT_DEATH_IF_SUPPORTED(`_statement, regex_`); | if death tests are supported, verifies that _statement_ crashes with the given error; otherwise verifies nothing |
+| `ASSERT_EXIT(`_statement, predicate, regex_`); | `EXPECT_EXIT(`_statement, predicate, regex_`); |_statement_ exits with the given error and its exit code matches _predicate_ |
+
+where _statement_ is a statement that is expected to cause the process to
+die, _predicate_ is a function or function object that evaluates an integer
+exit status, and _regex_ is a regular expression that the stderr output of
+_statement_ is expected to match. Note that _statement_ can be _any valid
+statement_ (including _compound statement_) and doesn't have to be an
+expression.
+
+As usual, the `ASSERT` variants abort the current test function, while the
+`EXPECT` variants do not.
+
+**Note:** We use the word "crash" here to mean that the process
+terminates with a _non-zero_ exit status code.  There are two
+possibilities: either the process has called `exit()` or `_exit()`
+with a non-zero value, or it may be killed by a signal.
+
+This means that if _statement_ terminates the process with a 0 exit
+code, it is _not_ considered a crash by `EXPECT_DEATH`.  Use
+`EXPECT_EXIT` instead if this is the case, or if you want to restrict
+the exit code more precisely.
+
+A predicate here must accept an `int` and return a `bool`. The death test
+succeeds only if the predicate returns `true`. Google Test defines a few
+predicates that handle the most common cases:
+
+```
+::testing::ExitedWithCode(exit_code)
+```
+
+This expression is `true` if the program exited normally with the given exit
+code.
+
+```
+::testing::KilledBySignal(signal_number)  // Not available on Windows.
+```
+
+This expression is `true` if the program was killed by the given signal.
+
+The `*_DEATH` macros are convenient wrappers for `*_EXIT` that use a predicate
+that verifies the process' exit code is non-zero.
+
+Note that a death test only cares about three things:
+
+  1. does _statement_ abort or exit the process?
+  1. (in the case of `ASSERT_EXIT` and `EXPECT_EXIT`) does the exit status satisfy _predicate_?  Or (in the case of `ASSERT_DEATH` and `EXPECT_DEATH`) is the exit status non-zero?  And
+  1. does the stderr output match _regex_?
+
+In particular, if _statement_ generates an `ASSERT_*` or `EXPECT_*` failure, it will **not** cause the death test to fail, as Google Test assertions don't abort the process.
+
+To write a death test, simply use one of the above macros inside your test
+function. For example,
+
+```
+TEST(MyDeathTest, Foo) {
+  // This death test uses a compound statement.
+  ASSERT_DEATH({ int n = 5; Foo(&n); }, "Error on line .* of Foo()");
+}
+TEST(MyDeathTest, NormalExit) {
+  EXPECT_EXIT(NormalExit(), ::testing::ExitedWithCode(0), "Success");
+}
+TEST(MyDeathTest, KillMyself) {
+  EXPECT_EXIT(KillMyself(), ::testing::KilledBySignal(SIGKILL), "Sending myself unblockable signal");
+}
+```
+
+verifies that:
+
+  * calling `Foo(5)` causes the process to die with the given error message,
+  * calling `NormalExit()` causes the process to print `"Success"` to stderr and exit with exit code 0, and
+  * calling `KillMyself()` kills the process with signal `SIGKILL`.
+
+The test function body may contain other assertions and statements as well, if
+necessary.
+
+_Important:_ We strongly recommend you to follow the convention of naming your
+test case (not test) `*DeathTest` when it contains a death test, as
+demonstrated in the above example. The `Death Tests And Threads` section below
+explains why.
+
+If a test fixture class is shared by normal tests and death tests, you
+can use typedef to introduce an alias for the fixture class and avoid
+duplicating its code:
+```
+class FooTest : public ::testing::Test { ... };
+
+typedef FooTest FooDeathTest;
+
+TEST_F(FooTest, DoesThis) {
+  // normal test
+}
+
+TEST_F(FooDeathTest, DoesThat) {
+  // death test
+}
+```
+
+_Availability:_ Linux, Windows (requires MSVC 8.0 or above), Cygwin, and Mac (the latter three are supported since v1.3.0).  `(ASSERT|EXPECT)_DEATH_IF_SUPPORTED` are new in v1.4.0.
+
+## Regular Expression Syntax ##
+
+On POSIX systems (e.g. Linux, Cygwin, and Mac), Google Test uses the
+[POSIX extended regular expression](http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap09.html#tag_09_04)
+syntax in death tests. To learn about this syntax, you may want to read this [Wikipedia entry](http://en.wikipedia.org/wiki/Regular_expression#POSIX_Extended_Regular_Expressions).
+
+On Windows, Google Test uses its own simple regular expression
+implementation. It lacks many features you can find in POSIX extended
+regular expressions.  For example, we don't support union (`"x|y"`),
+grouping (`"(xy)"`), brackets (`"[xy]"`), and repetition count
+(`"x{5,7}"`), among others. Below is what we do support (Letter `A` denotes a
+literal character, period (`.`), or a single `\\` escape sequence; `x`
+and `y` denote regular expressions.):
+
+| `c` | matches any literal character `c` |
+|:----|:----------------------------------|
+| `\\d` | matches any decimal digit         |
+| `\\D` | matches any character that's not a decimal digit |
+| `\\f` | matches `\f`                      |
+| `\\n` | matches `\n`                      |
+| `\\r` | matches `\r`                      |
+| `\\s` | matches any ASCII whitespace, including `\n` |
+| `\\S` | matches any character that's not a whitespace |
+| `\\t` | matches `\t`                      |
+| `\\v` | matches `\v`                      |
+| `\\w` | matches any letter, `_`, or decimal digit |
+| `\\W` | matches any character that `\\w` doesn't match |
+| `\\c` | matches any literal character `c`, which must be a punctuation |
+| `\\.` | matches the `.` character         |
+| `.` | matches any single character except `\n` |
+| `A?` | matches 0 or 1 occurrences of `A` |
+| `A*` | matches 0 or many occurrences of `A` |
+| `A+` | matches 1 or many occurrences of `A` |
+| `^` | matches the beginning of a string (not that of each line) |
+| `$` | matches the end of a string (not that of each line) |
+| `xy` | matches `x` followed by `y`       |
+
+To help you determine which capability is available on your system,
+Google Test defines macro `GTEST_USES_POSIX_RE=1` when it uses POSIX
+extended regular expressions, or `GTEST_USES_SIMPLE_RE=1` when it uses
+the simple version.  If you want your death tests to work in both
+cases, you can either `#if` on these macros or use the more limited
+syntax only.
+
+## How It Works ##
+
+Under the hood, `ASSERT_EXIT()` spawns a new process and executes the
+death test statement in that process. The details of of how precisely
+that happens depend on the platform and the variable
+`::testing::GTEST_FLAG(death_test_style)` (which is initialized from the
+command-line flag `--gtest_death_test_style`).
+
+  * On POSIX systems, `fork()` (or `clone()` on Linux) is used to spawn the child, after which:
+    * If the variable's value is `"fast"`, the death test statement is immediately executed.
+    * If the variable's value is `"threadsafe"`, the child process re-executes the unit test binary just as it was originally invoked, but with some extra flags to cause just the single death test under consideration to be run.
+  * On Windows, the child is spawned using the `CreateProcess()` API, and re-executes the binary to cause just the single death test under consideration to be run - much like the `threadsafe` mode on POSIX.
+
+Other values for the variable are illegal and will cause the death test to
+fail. Currently, the flag's default value is `"fast"`. However, we reserve the
+right to change it in the future. Therefore, your tests should not depend on
+this.
+
+In either case, the parent process waits for the child process to complete, and checks that
+
+  1. the child's exit status satisfies the predicate, and
+  1. the child's stderr matches the regular expression.
+
+If the death test statement runs to completion without dying, the child
+process will nonetheless terminate, and the assertion fails.
+
+## Death Tests And Threads ##
+
+The reason for the two death test styles has to do with thread safety. Due to
+well-known problems with forking in the presence of threads, death tests should
+be run in a single-threaded context. Sometimes, however, it isn't feasible to
+arrange that kind of environment. For example, statically-initialized modules
+may start threads before main is ever reached. Once threads have been created,
+it may be difficult or impossible to clean them up.
+
+Google Test has three features intended to raise awareness of threading issues.
+
+  1. A warning is emitted if multiple threads are running when a death test is encountered.
+  1. Test cases with a name ending in "DeathTest" are run before all other tests.
+  1. It uses `clone()` instead of `fork()` to spawn the child process on Linux (`clone()` is not available on Cygwin and Mac), as `fork()` is more likely to cause the child to hang when the parent process has multiple threads.
+
+It's perfectly fine to create threads inside a death test statement; they are
+executed in a separate process and cannot affect the parent.
+
+## Death Test Styles ##
+
+The "threadsafe" death test style was introduced in order to help mitigate the
+risks of testing in a possibly multithreaded environment. It trades increased
+test execution time (potentially dramatically so) for improved thread safety.
+We suggest using the faster, default "fast" style unless your test has specific
+problems with it.
+
+You can choose a particular style of death tests by setting the flag
+programmatically:
+
+```
+::testing::FLAGS_gtest_death_test_style = "threadsafe";
+```
+
+You can do this in `main()` to set the style for all death tests in the
+binary, or in individual tests. Recall that flags are saved before running each
+test and restored afterwards, so you need not do that yourself. For example:
+
+```
+TEST(MyDeathTest, TestOne) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  // This test is run in the "threadsafe" style:
+  ASSERT_DEATH(ThisShouldDie(), "");
+}
+
+TEST(MyDeathTest, TestTwo) {
+  // This test is run in the "fast" style:
+  ASSERT_DEATH(ThisShouldDie(), "");
+}
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  ::testing::FLAGS_gtest_death_test_style = "fast";
+  return RUN_ALL_TESTS();
+}
+```
+
+## Caveats ##
+
+The _statement_ argument of `ASSERT_EXIT()` can be any valid C++ statement.
+If it leaves the current function via a `return` statement or by throwing an exception,
+the death test is considered to have failed.  Some Google Test macros may return
+from the current function (e.g. `ASSERT_TRUE()`), so be sure to avoid them in _statement_.
+
+Since _statement_ runs in the child process, any in-memory side effect (e.g.
+modifying a variable, releasing memory, etc) it causes will _not_ be observable
+in the parent process. In particular, if you release memory in a death test,
+your program will fail the heap check as the parent process will never see the
+memory reclaimed. To solve this problem, you can
+
+  1. try not to free memory in a death test;
+  1. free the memory again in the parent process; or
+  1. do not use the heap checker in your program.
+
+Due to an implementation detail, you cannot place multiple death test
+assertions on the same line; otherwise, compilation will fail with an unobvious
+error message.
+
+Despite the improved thread safety afforded by the "threadsafe" style of death
+test, thread problems such as deadlock are still possible in the presence of
+handlers registered with `pthread_atfork(3)`.
+
+# Using Assertions in Sub-routines #
+
+## Adding Traces to Assertions ##
+
+If a test sub-routine is called from several places, when an assertion
+inside it fails, it can be hard to tell which invocation of the
+sub-routine the failure is from.  You can alleviate this problem using
+extra logging or custom failure messages, but that usually clutters up
+your tests. A better solution is to use the `SCOPED_TRACE` macro:
+
+| `SCOPED_TRACE(`_message_`);` |
+|:-----------------------------|
+
+where _message_ can be anything streamable to `std::ostream`. This
+macro will cause the current file name, line number, and the given
+message to be added in every failure message. The effect will be
+undone when the control leaves the current lexical scope.
+
+For example,
+
+```
+10: void Sub1(int n) {
+11:   EXPECT_EQ(1, Bar(n));
+12:   EXPECT_EQ(2, Bar(n + 1));
+13: }
+14: 
+15: TEST(FooTest, Bar) {
+16:   {
+17:     SCOPED_TRACE("A");  // This trace point will be included in
+18:                         // every failure in this scope.
+19:     Sub1(1);
+20:   }
+21:   // Now it won't.
+22:   Sub1(9);
+23: }
+```
+
+could result in messages like these:
+
+```
+path/to/foo_test.cc:11: Failure
+Value of: Bar(n)
+Expected: 1
+  Actual: 2
+   Trace:
+path/to/foo_test.cc:17: A
+
+path/to/foo_test.cc:12: Failure
+Value of: Bar(n + 1)
+Expected: 2
+  Actual: 3
+```
+
+Without the trace, it would've been difficult to know which invocation
+of `Sub1()` the two failures come from respectively. (You could add an
+extra message to each assertion in `Sub1()` to indicate the value of
+`n`, but that's tedious.)
+
+Some tips on using `SCOPED_TRACE`:
+
+  1. With a suitable message, it's often enough to use `SCOPED_TRACE` at the beginning of a sub-routine, instead of at each call site.
+  1. When calling sub-routines inside a loop, make the loop iterator part of the message in `SCOPED_TRACE` such that you can know which iteration the failure is from.
+  1. Sometimes the line number of the trace point is enough for identifying the particular invocation of a sub-routine. In this case, you don't have to choose a unique message for `SCOPED_TRACE`. You can simply use `""`.
+  1. You can use `SCOPED_TRACE` in an inner scope when there is one in the outer scope. In this case, all active trace points will be included in the failure messages, in reverse order they are encountered.
+  1. The trace dump is clickable in Emacs' compilation buffer - hit return on a line number and you'll be taken to that line in the source file!
+
+_Availability:_ Linux, Windows, Mac.
+
+## Propagating Fatal Failures ##
+
+A common pitfall when using `ASSERT_*` and `FAIL*` is not understanding that
+when they fail they only abort the _current function_, not the entire test. For
+example, the following test will segfault:
+```
+void Subroutine() {
+  // Generates a fatal failure and aborts the current function.
+  ASSERT_EQ(1, 2);
+  // The following won't be executed.
+  ...
+}
+
+TEST(FooTest, Bar) {
+  Subroutine();
+  // The intended behavior is for the fatal failure
+  // in Subroutine() to abort the entire test.
+  // The actual behavior: the function goes on after Subroutine() returns.
+  int* p = NULL;
+  *p = 3; // Segfault!
+}
+```
+
+Since we don't use exceptions, it is technically impossible to
+implement the intended behavior here.  To alleviate this, Google Test
+provides two solutions.  You could use either the
+`(ASSERT|EXPECT)_NO_FATAL_FAILURE` assertions or the
+`HasFatalFailure()` function.  They are described in the following two
+subsections.
+
+### Asserting on Subroutines ###
+
+As shown above, if your test calls a subroutine that has an `ASSERT_*`
+failure in it, the test will continue after the subroutine
+returns. This may not be what you want.
+
+Often people want fatal failures to propagate like exceptions.  For
+that Google Test offers the following macros:
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_NO_FATAL_FAILURE(`_statement_`);` | `EXPECT_NO_FATAL_FAILURE(`_statement_`);` | _statement_ doesn't generate any new fatal failures in the current thread. |
+
+Only failures in the thread that executes the assertion are checked to
+determine the result of this type of assertions.  If _statement_
+creates new threads, failures in these threads are ignored.
+
+Examples:
+
+```
+ASSERT_NO_FATAL_FAILURE(Foo());
+
+int i;
+EXPECT_NO_FATAL_FAILURE({
+  i = Bar();
+});
+```
+
+_Availability:_ Linux, Windows, Mac. Assertions from multiple threads
+are currently not supported.
+
+### Checking for Failures in the Current Test ###
+
+`HasFatalFailure()` in the `::testing::Test` class returns `true` if an
+assertion in the current test has suffered a fatal failure. This
+allows functions to catch fatal failures in a sub-routine and return
+early.
+
+```
+class Test {
+ public:
+  ...
+  static bool HasFatalFailure();
+};
+```
+
+The typical usage, which basically simulates the behavior of a thrown
+exception, is:
+
+```
+TEST(FooTest, Bar) {
+  Subroutine();
+  // Aborts if Subroutine() had a fatal failure.
+  if (HasFatalFailure())
+    return;
+  // The following won't be executed.
+  ...
+}
+```
+
+If `HasFatalFailure()` is used outside of `TEST()` , `TEST_F()` , or a test
+fixture, you must add the `::testing::Test::` prefix, as in:
+
+```
+if (::testing::Test::HasFatalFailure())
+  return;
+```
+
+Similarly, `HasNonfatalFailure()` returns `true` if the current test
+has at least one non-fatal failure, and `HasFailure()` returns `true`
+if the current test has at least one failure of either kind.
+
+_Availability:_ Linux, Windows, Mac.  `HasNonfatalFailure()` and
+`HasFailure()` are available since version 1.4.0.
+
+# Logging Additional Information #
+
+In your test code, you can call `RecordProperty("key", value)` to log
+additional information, where `value` can be either a string or an `int`. The _last_ value recorded for a key will be emitted to the XML output
+if you specify one. For example, the test
+
+```
+TEST_F(WidgetUsageTest, MinAndMaxWidgets) {
+  RecordProperty("MaximumWidgets", ComputeMaxUsage());
+  RecordProperty("MinimumWidgets", ComputeMinUsage());
+}
+```
+
+will output XML like this:
+
+```
+...
+  <testcase name="MinAndMaxWidgets" status="run" time="6" classname="WidgetUsageTest"
+            MaximumWidgets="12"
+            MinimumWidgets="9" />
+...
+```
+
+_Note_:
+  * `RecordProperty()` is a static member of the `Test` class. Therefore it needs to be prefixed with `::testing::Test::` if used outside of the `TEST` body and the test fixture class.
+  * `key` must be a valid XML attribute name, and cannot conflict with the ones already used by Google Test (`name`, `status`, `time`, `classname`, `type_param`, and `value_param`).
+  * Calling `RecordProperty()` outside of the lifespan of a test is allowed. If it's called outside of a test but between a test case's `SetUpTestCase()` and `TearDownTestCase()` methods, it will be attributed to the XML element for the test case. If it's called outside of all test cases (e.g. in a test environment), it will be attributed to the top-level XML element.
+
+_Availability_: Linux, Windows, Mac.
+
+# Sharing Resources Between Tests in the Same Test Case #
+
+
+
+Google Test creates a new test fixture object for each test in order to make
+tests independent and easier to debug. However, sometimes tests use resources
+that are expensive to set up, making the one-copy-per-test model prohibitively
+expensive.
+
+If the tests don't change the resource, there's no harm in them sharing a
+single resource copy. So, in addition to per-test set-up/tear-down, Google Test
+also supports per-test-case set-up/tear-down. To use it:
+
+  1. In your test fixture class (say `FooTest` ), define as `static` some member variables to hold the shared resources.
+  1. In the same test fixture class, define a `static void SetUpTestCase()` function (remember not to spell it as **`SetupTestCase`** with a small `u`!) to set up the shared resources and a `static void TearDownTestCase()` function to tear them down.
+
+That's it! Google Test automatically calls `SetUpTestCase()` before running the
+_first test_ in the `FooTest` test case (i.e. before creating the first
+`FooTest` object), and calls `TearDownTestCase()` after running the _last test_
+in it (i.e. after deleting the last `FooTest` object). In between, the tests
+can use the shared resources.
+
+Remember that the test order is undefined, so your code can't depend on a test
+preceding or following another. Also, the tests must either not modify the
+state of any shared resource, or, if they do modify the state, they must
+restore the state to its original value before passing control to the next
+test.
+
+Here's an example of per-test-case set-up and tear-down:
+```
+class FooTest : public ::testing::Test {
+ protected:
+  // Per-test-case set-up.
+  // Called before the first test in this test case.
+  // Can be omitted if not needed.
+  static void SetUpTestCase() {
+    shared_resource_ = new ...;
+  }
+
+  // Per-test-case tear-down.
+  // Called after the last test in this test case.
+  // Can be omitted if not needed.
+  static void TearDownTestCase() {
+    delete shared_resource_;
+    shared_resource_ = NULL;
+  }
+
+  // You can define per-test set-up and tear-down logic as usual.
+  virtual void SetUp() { ... }
+  virtual void TearDown() { ... }
+
+  // Some expensive resource shared by all tests.
+  static T* shared_resource_;
+};
+
+T* FooTest::shared_resource_ = NULL;
+
+TEST_F(FooTest, Test1) {
+  ... you can refer to shared_resource here ...
+}
+TEST_F(FooTest, Test2) {
+  ... you can refer to shared_resource here ...
+}
+```
+
+_Availability:_ Linux, Windows, Mac.
+
+# Global Set-Up and Tear-Down #
+
+Just as you can do set-up and tear-down at the test level and the test case
+level, you can also do it at the test program level. Here's how.
+
+First, you subclass the `::testing::Environment` class to define a test
+environment, which knows how to set-up and tear-down:
+
+```
+class Environment {
+ public:
+  virtual ~Environment() {}
+  // Override this to define how to set up the environment.
+  virtual void SetUp() {}
+  // Override this to define how to tear down the environment.
+  virtual void TearDown() {}
+};
+```
+
+Then, you register an instance of your environment class with Google Test by
+calling the `::testing::AddGlobalTestEnvironment()` function:
+
+```
+Environment* AddGlobalTestEnvironment(Environment* env);
+```
+
+Now, when `RUN_ALL_TESTS()` is called, it first calls the `SetUp()` method of
+the environment object, then runs the tests if there was no fatal failures, and
+finally calls `TearDown()` of the environment object.
+
+It's OK to register multiple environment objects. In this case, their `SetUp()`
+will be called in the order they are registered, and their `TearDown()` will be
+called in the reverse order.
+
+Note that Google Test takes ownership of the registered environment objects.
+Therefore **do not delete them** by yourself.
+
+You should call `AddGlobalTestEnvironment()` before `RUN_ALL_TESTS()` is
+called, probably in `main()`. If you use `gtest_main`, you need to      call
+this before `main()` starts for it to take effect. One way to do this is to
+define a global variable like this:
+
+```
+::testing::Environment* const foo_env = ::testing::AddGlobalTestEnvironment(new FooEnvironment);
+```
+
+However, we strongly recommend you to write your own `main()` and call
+`AddGlobalTestEnvironment()` there, as relying on initialization of global
+variables makes the code harder to read and may cause problems when you
+register multiple environments from different translation units and the
+environments have dependencies among them (remember that the compiler doesn't
+guarantee the order in which global variables from different translation units
+are initialized).
+
+_Availability:_ Linux, Windows, Mac.
+
+
+# Value Parameterized Tests #
+
+_Value-parameterized tests_ allow you to test your code with different
+parameters without writing multiple copies of the same test.
+
+Suppose you write a test for your code and then realize that your code is affected by a presence of a Boolean command line flag.
+
+```
+TEST(MyCodeTest, TestFoo) {
+  // A code to test foo().
+}
+```
+
+Usually people factor their test code into a function with a Boolean parameter in such situations. The function sets the flag, then executes the testing code.
+
+```
+void TestFooHelper(bool flag_value) {
+  flag = flag_value;
+  // A code to test foo().
+}
+
+TEST(MyCodeTest, TestFoo) {
+  TestFooHelper(false);
+  TestFooHelper(true);
+}
+```
+
+But this setup has serious drawbacks. First, when a test assertion fails in your tests, it becomes unclear what value of the parameter caused it to fail. You can stream a clarifying message into your `EXPECT`/`ASSERT` statements, but it you'll have to do it with all of them. Second, you have to add one such helper function per test. What if you have ten tests? Twenty? A hundred?
+
+Value-parameterized tests will let you write your test only once and then easily instantiate and run it with an arbitrary number of parameter values.
+
+Here are some other situations when value-parameterized tests come handy:
+
+  * You want to test different implementations of an OO interface.
+  * You want to test your code over various inputs (a.k.a. data-driven testing). This feature is easy to abuse, so please exercise your good sense when doing it!
+
+## How to Write Value-Parameterized Tests ##
+
+To write value-parameterized tests, first you should define a fixture
+class.  It must be derived from both `::testing::Test` and
+`::testing::WithParamInterface<T>` (the latter is a pure interface),
+where `T` is the type of your parameter values.  For convenience, you
+can just derive the fixture class from `::testing::TestWithParam<T>`,
+which itself is derived from both `::testing::Test` and
+`::testing::WithParamInterface<T>`. `T` can be any copyable type. If
+it's a raw pointer, you are responsible for managing the lifespan of
+the pointed values.
+
+```
+class FooTest : public ::testing::TestWithParam<const char*> {
+  // You can implement all the usual fixture class members here.
+  // To access the test parameter, call GetParam() from class
+  // TestWithParam<T>.
+};
+
+// Or, when you want to add parameters to a pre-existing fixture class:
+class BaseTest : public ::testing::Test {
+  ...
+};
+class BarTest : public BaseTest,
+                public ::testing::WithParamInterface<const char*> {
+  ...
+};
+```
+
+Then, use the `TEST_P` macro to define as many test patterns using
+this fixture as you want.  The `_P` suffix is for "parameterized" or
+"pattern", whichever you prefer to think.
+
+```
+TEST_P(FooTest, DoesBlah) {
+  // Inside a test, access the test parameter with the GetParam() method
+  // of the TestWithParam<T> class:
+  EXPECT_TRUE(foo.Blah(GetParam()));
+  ...
+}
+
+TEST_P(FooTest, HasBlahBlah) {
+  ...
+}
+```
+
+Finally, you can use `INSTANTIATE_TEST_CASE_P` to instantiate the test
+case with any set of parameters you want. Google Test defines a number of
+functions for generating test parameters. They return what we call
+(surprise!) _parameter generators_. Here is a summary of them,
+which are all in the `testing` namespace:
+
+| `Range(begin, end[, step])` | Yields values `{begin, begin+step, begin+step+step, ...}`. The values do not include `end`. `step` defaults to 1. |
+|:----------------------------|:------------------------------------------------------------------------------------------------------------------|
+| `Values(v1, v2, ..., vN)`   | Yields values `{v1, v2, ..., vN}`.                                                                                |
+| `ValuesIn(container)` and `ValuesIn(begin, end)` | Yields values from a C-style array, an STL-style container, or an iterator range `[begin, end)`. `container`, `begin`, and `end` can be expressions whose values are determined at run time.  |
+| `Bool()`                    | Yields sequence `{false, true}`.                                                                                  |
+| `Combine(g1, g2, ..., gN)`  | Yields all combinations (the Cartesian product for the math savvy) of the values generated by the `N` generators. This is only available if your system provides the `<tr1/tuple>` header. If you are sure your system does, and Google Test disagrees, you can override it by defining `GTEST_HAS_TR1_TUPLE=1`. See comments in [include/gtest/internal/gtest-port.h](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/internal/gtest-port.h) for more information. |
+
+For more details, see the comments at the definitions of these functions in the [source code](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest-param-test.h).
+
+The following statement will instantiate tests from the `FooTest` test case
+each with parameter values `"meeny"`, `"miny"`, and `"moe"`.
+
+```
+INSTANTIATE_TEST_CASE_P(InstantiationName,
+                        FooTest,
+                        ::testing::Values("meeny", "miny", "moe"));
+```
+
+To distinguish different instances of the pattern (yes, you can
+instantiate it more than once), the first argument to
+`INSTANTIATE_TEST_CASE_P` is a prefix that will be added to the actual
+test case name. Remember to pick unique prefixes for different
+instantiations. The tests from the instantiation above will have these
+names:
+
+  * `InstantiationName/FooTest.DoesBlah/0` for `"meeny"`
+  * `InstantiationName/FooTest.DoesBlah/1` for `"miny"`
+  * `InstantiationName/FooTest.DoesBlah/2` for `"moe"`
+  * `InstantiationName/FooTest.HasBlahBlah/0` for `"meeny"`
+  * `InstantiationName/FooTest.HasBlahBlah/1` for `"miny"`
+  * `InstantiationName/FooTest.HasBlahBlah/2` for `"moe"`
+
+You can use these names in [--gtest\_filter](#Running_a_Subset_of_the_Tests.md).
+
+This statement will instantiate all tests from `FooTest` again, each
+with parameter values `"cat"` and `"dog"`:
+
+```
+const char* pets[] = {"cat", "dog"};
+INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest,
+                        ::testing::ValuesIn(pets));
+```
+
+The tests from the instantiation above will have these names:
+
+  * `AnotherInstantiationName/FooTest.DoesBlah/0` for `"cat"`
+  * `AnotherInstantiationName/FooTest.DoesBlah/1` for `"dog"`
+  * `AnotherInstantiationName/FooTest.HasBlahBlah/0` for `"cat"`
+  * `AnotherInstantiationName/FooTest.HasBlahBlah/1` for `"dog"`
+
+Please note that `INSTANTIATE_TEST_CASE_P` will instantiate _all_
+tests in the given test case, whether their definitions come before or
+_after_ the `INSTANTIATE_TEST_CASE_P` statement.
+
+You can see
+[these](http://code.google.com/p/googletest/source/browse/trunk/samples/sample7_unittest.cc)
+[files](http://code.google.com/p/googletest/source/browse/trunk/samples/sample8_unittest.cc) for more examples.
+
+_Availability_: Linux, Windows (requires MSVC 8.0 or above), Mac; since version 1.2.0.
+
+## Creating Value-Parameterized Abstract Tests ##
+
+In the above, we define and instantiate `FooTest` in the same source
+file. Sometimes you may want to define value-parameterized tests in a
+library and let other people instantiate them later. This pattern is
+known as <i>abstract tests</i>. As an example of its application, when you
+are designing an interface you can write a standard suite of abstract
+tests (perhaps using a factory function as the test parameter) that
+all implementations of the interface are expected to pass. When
+someone implements the interface, he can instantiate your suite to get
+all the interface-conformance tests for free.
+
+To define abstract tests, you should organize your code like this:
+
+  1. Put the definition of the parameterized test fixture class (e.g. `FooTest`) in a header file, say `foo_param_test.h`. Think of this as _declaring_ your abstract tests.
+  1. Put the `TEST_P` definitions in `foo_param_test.cc`, which includes `foo_param_test.h`. Think of this as _implementing_ your abstract tests.
+
+Once they are defined, you can instantiate them by including
+`foo_param_test.h`, invoking `INSTANTIATE_TEST_CASE_P()`, and linking
+with `foo_param_test.cc`. You can instantiate the same abstract test
+case multiple times, possibly in different source files.
+
+# Typed Tests #
+
+Suppose you have multiple implementations of the same interface and
+want to make sure that all of them satisfy some common requirements.
+Or, you may have defined several types that are supposed to conform to
+the same "concept" and you want to verify it.  In both cases, you want
+the same test logic repeated for different types.
+
+While you can write one `TEST` or `TEST_F` for each type you want to
+test (and you may even factor the test logic into a function template
+that you invoke from the `TEST`), it's tedious and doesn't scale:
+if you want _m_ tests over _n_ types, you'll end up writing _m\*n_
+`TEST`s.
+
+_Typed tests_ allow you to repeat the same test logic over a list of
+types.  You only need to write the test logic once, although you must
+know the type list when writing typed tests.  Here's how you do it:
+
+First, define a fixture class template.  It should be parameterized
+by a type.  Remember to derive it from `::testing::Test`:
+
+```
+template <typename T>
+class FooTest : public ::testing::Test {
+ public:
+  ...
+  typedef std::list<T> List;
+  static T shared_;
+  T value_;
+};
+```
+
+Next, associate a list of types with the test case, which will be
+repeated for each type in the list:
+
+```
+typedef ::testing::Types<char, int, unsigned int> MyTypes;
+TYPED_TEST_CASE(FooTest, MyTypes);
+```
+
+The `typedef` is necessary for the `TYPED_TEST_CASE` macro to parse
+correctly.  Otherwise the compiler will think that each comma in the
+type list introduces a new macro argument.
+
+Then, use `TYPED_TEST()` instead of `TEST_F()` to define a typed test
+for this test case.  You can repeat this as many times as you want:
+
+```
+TYPED_TEST(FooTest, DoesBlah) {
+  // Inside a test, refer to the special name TypeParam to get the type
+  // parameter.  Since we are inside a derived class template, C++ requires
+  // us to visit the members of FooTest via 'this'.
+  TypeParam n = this->value_;
+
+  // To visit static members of the fixture, add the 'TestFixture::'
+  // prefix.
+  n += TestFixture::shared_;
+
+  // To refer to typedefs in the fixture, add the 'typename TestFixture::'
+  // prefix.  The 'typename' is required to satisfy the compiler.
+  typename TestFixture::List values;
+  values.push_back(n);
+  ...
+}
+
+TYPED_TEST(FooTest, HasPropertyA) { ... }
+```
+
+You can see `samples/sample6_unittest.cc` for a complete example.
+
+_Availability:_ Linux, Windows (requires MSVC 8.0 or above), Mac;
+since version 1.1.0.
+
+# Type-Parameterized Tests #
+
+_Type-parameterized tests_ are like typed tests, except that they
+don't require you to know the list of types ahead of time.  Instead,
+you can define the test logic first and instantiate it with different
+type lists later.  You can even instantiate it more than once in the
+same program.
+
+If you are designing an interface or concept, you can define a suite
+of type-parameterized tests to verify properties that any valid
+implementation of the interface/concept should have.  Then, the author
+of each implementation can just instantiate the test suite with his
+type to verify that it conforms to the requirements, without having to
+write similar tests repeatedly.  Here's an example:
+
+First, define a fixture class template, as we did with typed tests:
+
+```
+template <typename T>
+class FooTest : public ::testing::Test {
+  ...
+};
+```
+
+Next, declare that you will define a type-parameterized test case:
+
+```
+TYPED_TEST_CASE_P(FooTest);
+```
+
+The `_P` suffix is for "parameterized" or "pattern", whichever you
+prefer to think.
+
+Then, use `TYPED_TEST_P()` to define a type-parameterized test.  You
+can repeat this as many times as you want:
+
+```
+TYPED_TEST_P(FooTest, DoesBlah) {
+  // Inside a test, refer to TypeParam to get the type parameter.
+  TypeParam n = 0;
+  ...
+}
+
+TYPED_TEST_P(FooTest, HasPropertyA) { ... }
+```
+
+Now the tricky part: you need to register all test patterns using the
+`REGISTER_TYPED_TEST_CASE_P` macro before you can instantiate them.
+The first argument of the macro is the test case name; the rest are
+the names of the tests in this test case:
+
+```
+REGISTER_TYPED_TEST_CASE_P(FooTest,
+                           DoesBlah, HasPropertyA);
+```
+
+Finally, you are free to instantiate the pattern with the types you
+want.  If you put the above code in a header file, you can `#include`
+it in multiple C++ source files and instantiate it multiple times.
+
+```
+typedef ::testing::Types<char, int, unsigned int> MyTypes;
+INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
+```
+
+To distinguish different instances of the pattern, the first argument
+to the `INSTANTIATE_TYPED_TEST_CASE_P` macro is a prefix that will be
+added to the actual test case name.  Remember to pick unique prefixes
+for different instances.
+
+In the special case where the type list contains only one type, you
+can write that type directly without `::testing::Types<...>`, like this:
+
+```
+INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int);
+```
+
+You can see `samples/sample6_unittest.cc` for a complete example.
+
+_Availability:_ Linux, Windows (requires MSVC 8.0 or above), Mac;
+since version 1.1.0.
+
+# Testing Private Code #
+
+If you change your software's internal implementation, your tests should not
+break as long as the change is not observable by users. Therefore, per the
+_black-box testing principle_, most of the time you should test your code
+through its public interfaces.
+
+If you still find yourself needing to test internal implementation code,
+consider if there's a better design that wouldn't require you to do so. If you
+absolutely have to test non-public interface code though, you can. There are
+two cases to consider:
+
+  * Static functions (_not_ the same as static member functions!) or unnamed namespaces, and
+  * Private or protected class members
+
+## Static Functions ##
+
+Both static functions and definitions/declarations in an unnamed namespace are
+only visible within the same translation unit. To test them, you can `#include`
+the entire `.cc` file being tested in your `*_test.cc` file. (#including `.cc`
+files is not a good way to reuse code - you should not do this in production
+code!)
+
+However, a better approach is to move the private code into the
+`foo::internal` namespace, where `foo` is the namespace your project normally
+uses, and put the private declarations in a `*-internal.h` file. Your
+production `.cc` files and your tests are allowed to include this internal
+header, but your clients are not. This way, you can fully test your internal
+implementation without leaking it to your clients.
+
+## Private Class Members ##
+
+Private class members are only accessible from within the class or by friends.
+To access a class' private members, you can declare your test fixture as a
+friend to the class and define accessors in your fixture. Tests using the
+fixture can then access the private members of your production class via the
+accessors in the fixture. Note that even though your fixture is a friend to
+your production class, your tests are not automatically friends to it, as they
+are technically defined in sub-classes of the fixture.
+
+Another way to test private members is to refactor them into an implementation
+class, which is then declared in a `*-internal.h` file. Your clients aren't
+allowed to include this header but your tests can. Such is called the Pimpl
+(Private Implementation) idiom.
+
+Or, you can declare an individual test as a friend of your class by adding this
+line in the class body:
+
+```
+FRIEND_TEST(TestCaseName, TestName);
+```
+
+For example,
+```
+// foo.h
+#include "gtest/gtest_prod.h"
+
+// Defines FRIEND_TEST.
+class Foo {
+  ...
+ private:
+  FRIEND_TEST(FooTest, BarReturnsZeroOnNull);
+  int Bar(void* x);
+};
+
+// foo_test.cc
+...
+TEST(FooTest, BarReturnsZeroOnNull) {
+  Foo foo;
+  EXPECT_EQ(0, foo.Bar(NULL));
+  // Uses Foo's private member Bar().
+}
+```
+
+Pay special attention when your class is defined in a namespace, as you should
+define your test fixtures and tests in the same namespace if you want them to
+be friends of your class. For example, if the code to be tested looks like:
+
+```
+namespace my_namespace {
+
+class Foo {
+  friend class FooTest;
+  FRIEND_TEST(FooTest, Bar);
+  FRIEND_TEST(FooTest, Baz);
+  ...
+  definition of the class Foo
+  ...
+};
+
+}  // namespace my_namespace
+```
+
+Your test code should be something like:
+
+```
+namespace my_namespace {
+class FooTest : public ::testing::Test {
+ protected:
+  ...
+};
+
+TEST_F(FooTest, Bar) { ... }
+TEST_F(FooTest, Baz) { ... }
+
+}  // namespace my_namespace
+```
+
+# Catching Failures #
+
+If you are building a testing utility on top of Google Test, you'll
+want to test your utility.  What framework would you use to test it?
+Google Test, of course.
+
+The challenge is to verify that your testing utility reports failures
+correctly.  In frameworks that report a failure by throwing an
+exception, you could catch the exception and assert on it.  But Google
+Test doesn't use exceptions, so how do we test that a piece of code
+generates an expected failure?
+
+`"gtest/gtest-spi.h"` contains some constructs to do this.  After
+#including this header, you can use
+
+| `EXPECT_FATAL_FAILURE(`_statement, substring_`);` |
+|:--------------------------------------------------|
+
+to assert that _statement_ generates a fatal (e.g. `ASSERT_*`) failure
+whose message contains the given _substring_, or use
+
+| `EXPECT_NONFATAL_FAILURE(`_statement, substring_`);` |
+|:-----------------------------------------------------|
+
+if you are expecting a non-fatal (e.g. `EXPECT_*`) failure.
+
+For technical reasons, there are some caveats:
+
+  1. You cannot stream a failure message to either macro.
+  1. _statement_ in `EXPECT_FATAL_FAILURE()` cannot reference local non-static variables or non-static members of `this` object.
+  1. _statement_ in `EXPECT_FATAL_FAILURE()` cannot return a value.
+
+_Note:_ Google Test is designed with threads in mind.  Once the
+synchronization primitives in `"gtest/internal/gtest-port.h"` have
+been implemented, Google Test will become thread-safe, meaning that
+you can then use assertions in multiple threads concurrently.  Before
+
+that, however, Google Test only supports single-threaded usage.  Once
+thread-safe, `EXPECT_FATAL_FAILURE()` and `EXPECT_NONFATAL_FAILURE()`
+will capture failures in the current thread only. If _statement_
+creates new threads, failures in these threads will be ignored.  If
+you want to capture failures from all threads instead, you should use
+the following macros:
+
+| `EXPECT_FATAL_FAILURE_ON_ALL_THREADS(`_statement, substring_`);` |
+|:-----------------------------------------------------------------|
+| `EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(`_statement, substring_`);` |
+
+# Getting the Current Test's Name #
+
+Sometimes a function may need to know the name of the currently running test.
+For example, you may be using the `SetUp()` method of your test fixture to set
+the golden file name based on which test is running. The `::testing::TestInfo`
+class has this information:
+
+```
+namespace testing {
+
+class TestInfo {
+ public:
+  // Returns the test case name and the test name, respectively.
+  //
+  // Do NOT delete or free the return value - it's managed by the
+  // TestInfo class.
+  const char* test_case_name() const;
+  const char* name() const;
+};
+
+}  // namespace testing
+```
+
+
+> To obtain a `TestInfo` object for the currently running test, call
+`current_test_info()` on the `UnitTest` singleton object:
+
+```
+// Gets information about the currently running test.
+// Do NOT delete the returned object - it's managed by the UnitTest class.
+const ::testing::TestInfo* const test_info =
+  ::testing::UnitTest::GetInstance()->current_test_info();
+printf("We are in test %s of test case %s.\n",
+       test_info->name(), test_info->test_case_name());
+```
+
+`current_test_info()` returns a null pointer if no test is running. In
+particular, you cannot find the test case name in `TestCaseSetUp()`,
+`TestCaseTearDown()` (where you know the test case name implicitly), or
+functions called from them.
+
+_Availability:_ Linux, Windows, Mac.
+
+# Extending Google Test by Handling Test Events #
+
+Google Test provides an <b>event listener API</b> to let you receive
+notifications about the progress of a test program and test
+failures. The events you can listen to include the start and end of
+the test program, a test case, or a test method, among others. You may
+use this API to augment or replace the standard console output,
+replace the XML output, or provide a completely different form of
+output, such as a GUI or a database. You can also use test events as
+checkpoints to implement a resource leak checker, for example.
+
+_Availability:_ Linux, Windows, Mac; since v1.4.0.
+
+## Defining Event Listeners ##
+
+To define a event listener, you subclass either
+[testing::TestEventListener](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest.h#855)
+or [testing::EmptyTestEventListener](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest.h#905).
+The former is an (abstract) interface, where <i>each pure virtual method<br>
+can be overridden to handle a test event</i> (For example, when a test
+starts, the `OnTestStart()` method will be called.). The latter provides
+an empty implementation of all methods in the interface, such that a
+subclass only needs to override the methods it cares about.
+
+When an event is fired, its context is passed to the handler function
+as an argument. The following argument types are used:
+  * [UnitTest](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest.h#1007) reflects the state of the entire test program,
+  * [TestCase](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest.h#689) has information about a test case, which can contain one or more tests,
+  * [TestInfo](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest.h#599) contains the state of a test, and
+  * [TestPartResult](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest-test-part.h#42) represents the result of a test assertion.
+
+An event handler function can examine the argument it receives to find
+out interesting information about the event and the test program's
+state.  Here's an example:
+
+```
+  class MinimalistPrinter : public ::testing::EmptyTestEventListener {
+    // Called before a test starts.
+    virtual void OnTestStart(const ::testing::TestInfo& test_info) {
+      printf("*** Test %s.%s starting.\n",
+             test_info.test_case_name(), test_info.name());
+    }
+
+    // Called after a failed assertion or a SUCCEED() invocation.
+    virtual void OnTestPartResult(
+        const ::testing::TestPartResult& test_part_result) {
+      printf("%s in %s:%d\n%s\n",
+             test_part_result.failed() ? "*** Failure" : "Success",
+             test_part_result.file_name(),
+             test_part_result.line_number(),
+             test_part_result.summary());
+    }
+
+    // Called after a test ends.
+    virtual void OnTestEnd(const ::testing::TestInfo& test_info) {
+      printf("*** Test %s.%s ending.\n",
+             test_info.test_case_name(), test_info.name());
+    }
+  };
+```
+
+## Using Event Listeners ##
+
+To use the event listener you have defined, add an instance of it to
+the Google Test event listener list (represented by class
+[TestEventListeners](http://code.google.com/p/googletest/source/browse/trunk/include/gtest/gtest.h#929)
+- note the "s" at the end of the name) in your
+`main()` function, before calling `RUN_ALL_TESTS()`:
+```
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  // Gets hold of the event listener list.
+  ::testing::TestEventListeners& listeners =
+      ::testing::UnitTest::GetInstance()->listeners();
+  // Adds a listener to the end.  Google Test takes the ownership.
+  listeners.Append(new MinimalistPrinter);
+  return RUN_ALL_TESTS();
+}
+```
+
+There's only one problem: the default test result printer is still in
+effect, so its output will mingle with the output from your minimalist
+printer. To suppress the default printer, just release it from the
+event listener list and delete it. You can do so by adding one line:
+```
+  ...
+  delete listeners.Release(listeners.default_result_printer());
+  listeners.Append(new MinimalistPrinter);
+  return RUN_ALL_TESTS();
+```
+
+Now, sit back and enjoy a completely different output from your
+tests. For more details, you can read this
+[sample](http://code.google.com/p/googletest/source/browse/trunk/samples/sample9_unittest.cc).
+
+You may append more than one listener to the list. When an `On*Start()`
+or `OnTestPartResult()` event is fired, the listeners will receive it in
+the order they appear in the list (since new listeners are added to
+the end of the list, the default text printer and the default XML
+generator will receive the event first). An `On*End()` event will be
+received by the listeners in the _reverse_ order. This allows output by
+listeners added later to be framed by output from listeners added
+earlier.
+
+## Generating Failures in Listeners ##
+
+You may use failure-raising macros (`EXPECT_*()`, `ASSERT_*()`,
+`FAIL()`, etc) when processing an event. There are some restrictions:
+
+  1. You cannot generate any failure in `OnTestPartResult()` (otherwise it will cause `OnTestPartResult()` to be called recursively).
+  1. A listener that handles `OnTestPartResult()` is not allowed to generate any failure.
+
+When you add listeners to the listener list, you should put listeners
+that handle `OnTestPartResult()` _before_ listeners that can generate
+failures. This ensures that failures generated by the latter are
+attributed to the right test by the former.
+
+We have a sample of failure-raising listener
+[here](http://code.google.com/p/googletest/source/browse/trunk/samples/sample10_unittest.cc).
+
+# Running Test Programs: Advanced Options #
+
+Google Test test programs are ordinary executables. Once built, you can run
+them directly and affect their behavior via the following environment variables
+and/or command line flags. For the flags to work, your programs must call
+`::testing::InitGoogleTest()` before calling `RUN_ALL_TESTS()`.
+
+To see a list of supported flags and their usage, please run your test
+program with the `--help` flag.  You can also use `-h`, `-?`, or `/?`
+for short.  This feature is added in version 1.3.0.
+
+If an option is specified both by an environment variable and by a
+flag, the latter takes precedence.  Most of the options can also be
+set/read in code: to access the value of command line flag
+`--gtest_foo`, write `::testing::GTEST_FLAG(foo)`.  A common pattern is
+to set the value of a flag before calling `::testing::InitGoogleTest()`
+to change the default value of the flag:
+```
+int main(int argc, char** argv) {
+  // Disables elapsed time by default.
+  ::testing::GTEST_FLAG(print_time) = false;
+
+  // This allows the user to override the flag on the command line.
+  ::testing::InitGoogleTest(&argc, argv);
+
+  return RUN_ALL_TESTS();
+}
+```
+
+## Selecting Tests ##
+
+This section shows various options for choosing which tests to run.
+
+### Listing Test Names ###
+
+Sometimes it is necessary to list the available tests in a program before
+running them so that a filter may be applied if needed. Including the flag
+`--gtest_list_tests` overrides all other flags and lists tests in the following
+format:
+```
+TestCase1.
+  TestName1
+  TestName2
+TestCase2.
+  TestName
+```
+
+None of the tests listed are actually run if the flag is provided. There is no
+corresponding environment variable for this flag.
+
+_Availability:_ Linux, Windows, Mac.
+
+### Running a Subset of the Tests ###
+
+By default, a Google Test program runs all tests the user has defined.
+Sometimes, you want to run only a subset of the tests (e.g. for debugging or
+quickly verifying a change). If you set the `GTEST_FILTER` environment variable
+or the `--gtest_filter` flag to a filter string, Google Test will only run the
+tests whose full names (in the form of `TestCaseName.TestName`) match the
+filter.
+
+The format of a filter is a '`:`'-separated list of wildcard patterns (called
+the positive patterns) optionally followed by a '`-`' and another
+'`:`'-separated pattern list (called the negative patterns). A test matches the
+filter if and only if it matches any of the positive patterns but does not
+match any of the negative patterns.
+
+A pattern may contain `'*'` (matches any string) or `'?'` (matches any single
+character). For convenience, the filter `'*-NegativePatterns'` can be also
+written as `'-NegativePatterns'`.
+
+For example:
+
+  * `./foo_test` Has no flag, and thus runs all its tests.
+  * `./foo_test --gtest_filter=*` Also runs everything, due to the single match-everything `*` value.
+  * `./foo_test --gtest_filter=FooTest.*` Runs everything in test case `FooTest`.
+  * `./foo_test --gtest_filter=*Null*:*Constructor*` Runs any test whose full name contains either `"Null"` or `"Constructor"`.
+  * `./foo_test --gtest_filter=-*DeathTest.*` Runs all non-death tests.
+  * `./foo_test --gtest_filter=FooTest.*-FooTest.Bar` Runs everything in test case `FooTest` except `FooTest.Bar`.
+
+_Availability:_ Linux, Windows, Mac.
+
+### Temporarily Disabling Tests ###
+
+If you have a broken test that you cannot fix right away, you can add the
+`DISABLED_` prefix to its name. This will exclude it from execution. This is
+better than commenting out the code or using `#if 0`, as disabled tests are
+still compiled (and thus won't rot).
+
+If you need to disable all tests in a test case, you can either add `DISABLED_`
+to the front of the name of each test, or alternatively add it to the front of
+the test case name.
+
+For example, the following tests won't be run by Google Test, even though they
+will still be compiled:
+
+```
+// Tests that Foo does Abc.
+TEST(FooTest, DISABLED_DoesAbc) { ... }
+
+class DISABLED_BarTest : public ::testing::Test { ... };
+
+// Tests that Bar does Xyz.
+TEST_F(DISABLED_BarTest, DoesXyz) { ... }
+```
+
+_Note:_ This feature should only be used for temporary pain-relief. You still
+have to fix the disabled tests at a later date. As a reminder, Google Test will
+print a banner warning you if a test program contains any disabled tests.
+
+_Tip:_ You can easily count the number of disabled tests you have
+using `grep`. This number can be used as a metric for improving your
+test quality.
+
+_Availability:_ Linux, Windows, Mac.
+
+### Temporarily Enabling Disabled Tests ###
+
+To include [disabled tests](#Temporarily_Disabling_Tests.md) in test
+execution, just invoke the test program with the
+`--gtest_also_run_disabled_tests` flag or set the
+`GTEST_ALSO_RUN_DISABLED_TESTS` environment variable to a value other
+than `0`.  You can combine this with the
+[--gtest\_filter](#Running_a_Subset_of_the_Tests.md) flag to further select
+which disabled tests to run.
+
+_Availability:_ Linux, Windows, Mac; since version 1.3.0.
+
+## Repeating the Tests ##
+
+Once in a while you'll run into a test whose result is hit-or-miss. Perhaps it
+will fail only 1% of the time, making it rather hard to reproduce the bug under
+a debugger. This can be a major source of frustration.
+
+The `--gtest_repeat` flag allows you to repeat all (or selected) test methods
+in a program many times. Hopefully, a flaky test will eventually fail and give
+you a chance to debug. Here's how to use it:
+
+| `$ foo_test --gtest_repeat=1000` | Repeat foo\_test 1000 times and don't stop at failures. |
+|:---------------------------------|:--------------------------------------------------------|
+| `$ foo_test --gtest_repeat=-1`   | A negative count means repeating forever.               |
+| `$ foo_test --gtest_repeat=1000 --gtest_break_on_failure` | Repeat foo\_test 1000 times, stopping at the first failure. This is especially useful when running under a debugger: when the testfails, it will drop into the debugger and you can then inspect variables and stacks. |
+| `$ foo_test --gtest_repeat=1000 --gtest_filter=FooBar` | Repeat the tests whose name matches the filter 1000 times. |
+
+If your test program contains global set-up/tear-down code registered
+using `AddGlobalTestEnvironment()`, it will be repeated in each
+iteration as well, as the flakiness may be in it. You can also specify
+the repeat count by setting the `GTEST_REPEAT` environment variable.
+
+_Availability:_ Linux, Windows, Mac.
+
+## Shuffling the Tests ##
+
+You can specify the `--gtest_shuffle` flag (or set the `GTEST_SHUFFLE`
+environment variable to `1`) to run the tests in a program in a random
+order. This helps to reveal bad dependencies between tests.
+
+By default, Google Test uses a random seed calculated from the current
+time. Therefore you'll get a different order every time. The console
+output includes the random seed value, such that you can reproduce an
+order-related test failure later. To specify the random seed
+explicitly, use the `--gtest_random_seed=SEED` flag (or set the
+`GTEST_RANDOM_SEED` environment variable), where `SEED` is an integer
+between 0 and 99999. The seed value 0 is special: it tells Google Test
+to do the default behavior of calculating the seed from the current
+time.
+
+If you combine this with `--gtest_repeat=N`, Google Test will pick a
+different random seed and re-shuffle the tests in each iteration.
+
+_Availability:_ Linux, Windows, Mac; since v1.4.0.
+
+## Controlling Test Output ##
+
+This section teaches how to tweak the way test results are reported.
+
+### Colored Terminal Output ###
+
+Google Test can use colors in its terminal output to make it easier to spot
+the separation between tests, and whether tests passed.
+
+You can set the GTEST\_COLOR environment variable or set the `--gtest_color`
+command line flag to `yes`, `no`, or `auto` (the default) to enable colors,
+disable colors, or let Google Test decide. When the value is `auto`, Google
+Test will use colors if and only if the output goes to a terminal and (on
+non-Windows platforms) the `TERM` environment variable is set to `xterm` or
+`xterm-color`.
+
+_Availability:_ Linux, Windows, Mac.
+
+### Suppressing the Elapsed Time ###
+
+By default, Google Test prints the time it takes to run each test.  To
+suppress that, run the test program with the `--gtest_print_time=0`
+command line flag.  Setting the `GTEST_PRINT_TIME` environment
+variable to `0` has the same effect.
+
+_Availability:_ Linux, Windows, Mac.  (In Google Test 1.3.0 and lower,
+the default behavior is that the elapsed time is **not** printed.)
+
+### Generating an XML Report ###
+
+Google Test can emit a detailed XML report to a file in addition to its normal
+textual output. The report contains the duration of each test, and thus can
+help you identify slow tests.
+
+To generate the XML report, set the `GTEST_OUTPUT` environment variable or the
+`--gtest_output` flag to the string `"xml:_path_to_output_file_"`, which will
+create the file at the given location. You can also just use the string
+`"xml"`, in which case the output can be found in the `test_detail.xml` file in
+the current directory.
+
+If you specify a directory (for example, `"xml:output/directory/"` on Linux or
+`"xml:output\directory\"` on Windows), Google Test will create the XML file in
+that directory, named after the test executable (e.g. `foo_test.xml` for test
+program `foo_test` or `foo_test.exe`). If the file already exists (perhaps left
+over from a previous run), Google Test will pick a different name (e.g.
+`foo_test_1.xml`) to avoid overwriting it.
+
+The report uses the format described here.  It is based on the
+`junitreport` Ant task and can be parsed by popular continuous build
+systems like [Jenkins](http://jenkins-ci.org/). Since that format
+was originally intended for Java, a little interpretation is required
+to make it apply to Google Test tests, as shown here:
+
+```
+<testsuites name="AllTests" ...>
+  <testsuite name="test_case_name" ...>
+    <testcase name="test_name" ...>
+      <failure message="..."/>
+      <failure message="..."/>
+      <failure message="..."/>
+    </testcase>
+  </testsuite>
+</testsuites>
+```
+
+  * The root `<testsuites>` element corresponds to the entire test program.
+  * `<testsuite>` elements correspond to Google Test test cases.
+  * `<testcase>` elements correspond to Google Test test functions.
+
+For instance, the following program
+
+```
+TEST(MathTest, Addition) { ... }
+TEST(MathTest, Subtraction) { ... }
+TEST(LogicTest, NonContradiction) { ... }
+```
+
+could generate this report:
+
+```
+<?xml version="1.0" encoding="UTF-8"?>
+<testsuites tests="3" failures="1" errors="0" time="35" name="AllTests">
+  <testsuite name="MathTest" tests="2" failures="1" errors="0" time="15">
+    <testcase name="Addition" status="run" time="7" classname="">
+      <failure message="Value of: add(1, 1)&#x0A; Actual: 3&#x0A;Expected: 2" type=""/>
+      <failure message="Value of: add(1, -1)&#x0A; Actual: 1&#x0A;Expected: 0" type=""/>
+    </testcase>
+    <testcase name="Subtraction" status="run" time="5" classname="">
+    </testcase>
+  </testsuite>
+  <testsuite name="LogicTest" tests="1" failures="0" errors="0" time="5">
+    <testcase name="NonContradiction" status="run" time="5" classname="">
+    </testcase>
+  </testsuite>
+</testsuites>
+```
+
+Things to note:
+
+  * The `tests` attribute of a `<testsuites>` or `<testsuite>` element tells how many test functions the Google Test program or test case contains, while the `failures` attribute tells how many of them failed.
+  * The `time` attribute expresses the duration of the test, test case, or entire test program in milliseconds.
+  * Each `<failure>` element corresponds to a single failed Google Test assertion.
+  * Some JUnit concepts don't apply to Google Test, yet we have to conform to the DTD. Therefore you'll see some dummy elements and attributes in the report. You can safely ignore these parts.
+
+_Availability:_ Linux, Windows, Mac.
+
+## Controlling How Failures Are Reported ##
+
+### Turning Assertion Failures into Break-Points ###
+
+When running test programs under a debugger, it's very convenient if the
+debugger can catch an assertion failure and automatically drop into interactive
+mode. Google Test's _break-on-failure_ mode supports this behavior.
+
+To enable it, set the `GTEST_BREAK_ON_FAILURE` environment variable to a value
+other than `0` . Alternatively, you can use the `--gtest_break_on_failure`
+command line flag.
+
+_Availability:_ Linux, Windows, Mac.
+
+### Disabling Catching Test-Thrown Exceptions ###
+
+Google Test can be used either with or without exceptions enabled.  If
+a test throws a C++ exception or (on Windows) a structured exception
+(SEH), by default Google Test catches it, reports it as a test
+failure, and continues with the next test method.  This maximizes the
+coverage of a test run.  Also, on Windows an uncaught exception will
+cause a pop-up window, so catching the exceptions allows you to run
+the tests automatically.
+
+When debugging the test failures, however, you may instead want the
+exceptions to be handled by the debugger, such that you can examine
+the call stack when an exception is thrown.  To achieve that, set the
+`GTEST_CATCH_EXCEPTIONS` environment variable to `0`, or use the
+`--gtest_catch_exceptions=0` flag when running the tests.
+
+**Availability**: Linux, Windows, Mac.
+
+### Letting Another Testing Framework Drive ###
+
+If you work on a project that has already been using another testing
+framework and is not ready to completely switch to Google Test yet,
+you can get much of Google Test's benefit by using its assertions in
+your existing tests.  Just change your `main()` function to look
+like:
+
+```
+#include "gtest/gtest.h"
+
+int main(int argc, char** argv) {
+  ::testing::GTEST_FLAG(throw_on_failure) = true;
+  // Important: Google Test must be initialized.
+  ::testing::InitGoogleTest(&argc, argv);
+
+  ... whatever your existing testing framework requires ...
+}
+```
+
+With that, you can use Google Test assertions in addition to the
+native assertions your testing framework provides, for example:
+
+```
+void TestFooDoesBar() {
+  Foo foo;
+  EXPECT_LE(foo.Bar(1), 100);     // A Google Test assertion.
+  CPPUNIT_ASSERT(foo.IsEmpty());  // A native assertion.
+}
+```
+
+If a Google Test assertion fails, it will print an error message and
+throw an exception, which will be treated as a failure by your host
+testing framework.  If you compile your code with exceptions disabled,
+a failed Google Test assertion will instead exit your program with a
+non-zero code, which will also signal a test failure to your test
+runner.
+
+If you don't write `::testing::GTEST_FLAG(throw_on_failure) = true;` in
+your `main()`, you can alternatively enable this feature by specifying
+the `--gtest_throw_on_failure` flag on the command-line or setting the
+`GTEST_THROW_ON_FAILURE` environment variable to a non-zero value.
+
+Death tests are _not_ supported when other test framework is used to organize tests.
+
+_Availability:_ Linux, Windows, Mac; since v1.3.0.
+
+## Distributing Test Functions to Multiple Machines ##
+
+If you have more than one machine you can use to run a test program,
+you might want to run the test functions in parallel and get the
+result faster.  We call this technique _sharding_, where each machine
+is called a _shard_.
+
+Google Test is compatible with test sharding.  To take advantage of
+this feature, your test runner (not part of Google Test) needs to do
+the following:
+
+  1. Allocate a number of machines (shards) to run the tests.
+  1. On each shard, set the `GTEST_TOTAL_SHARDS` environment variable to the total number of shards.  It must be the same for all shards.
+  1. On each shard, set the `GTEST_SHARD_INDEX` environment variable to the index of the shard.  Different shards must be assigned different indices, which must be in the range `[0, GTEST_TOTAL_SHARDS - 1]`.
+  1. Run the same test program on all shards.  When Google Test sees the above two environment variables, it will select a subset of the test functions to run.  Across all shards, each test function in the program will be run exactly once.
+  1. Wait for all shards to finish, then collect and report the results.
+
+Your project may have tests that were written without Google Test and
+thus don't understand this protocol.  In order for your test runner to
+figure out which test supports sharding, it can set the environment
+variable `GTEST_SHARD_STATUS_FILE` to a non-existent file path.  If a
+test program supports sharding, it will create this file to
+acknowledge the fact (the actual contents of the file are not
+important at this time; although we may stick some useful information
+in it in the future.); otherwise it will not create it.
+
+Here's an example to make it clear.  Suppose you have a test program
+`foo_test` that contains the following 5 test functions:
+```
+TEST(A, V)
+TEST(A, W)
+TEST(B, X)
+TEST(B, Y)
+TEST(B, Z)
+```
+and you have 3 machines at your disposal.  To run the test functions in
+parallel, you would set `GTEST_TOTAL_SHARDS` to 3 on all machines, and
+set `GTEST_SHARD_INDEX` to 0, 1, and 2 on the machines respectively.
+Then you would run the same `foo_test` on each machine.
+
+Google Test reserves the right to change how the work is distributed
+across the shards, but here's one possible scenario:
+
+  * Machine #0 runs `A.V` and `B.X`.
+  * Machine #1 runs `A.W` and `B.Y`.
+  * Machine #2 runs `B.Z`.
+
+_Availability:_ Linux, Windows, Mac; since version 1.3.0.
+
+# Fusing Google Test Source Files #
+
+Google Test's implementation consists of ~30 files (excluding its own
+tests).  Sometimes you may want them to be packaged up in two files (a
+`.h` and a `.cc`) instead, such that you can easily copy them to a new
+machine and start hacking there.  For this we provide an experimental
+Python script `fuse_gtest_files.py` in the `scripts/` directory (since release 1.3.0).
+Assuming you have Python 2.4 or above installed on your machine, just
+go to that directory and run
+```
+python fuse_gtest_files.py OUTPUT_DIR
+```
+
+and you should see an `OUTPUT_DIR` directory being created with files
+`gtest/gtest.h` and `gtest/gtest-all.cc` in it.  These files contain
+everything you need to use Google Test.  Just copy them to anywhere
+you want and you are ready to write tests.  You can use the
+[scripts/test/Makefile](http://code.google.com/p/googletest/source/browse/trunk/scripts/test/Makefile)
+file as an example on how to compile your tests against them.
+
+# Where to Go from Here #
+
+Congratulations! You've now learned more advanced Google Test tools and are
+ready to tackle more complex testing tasks. If you want to dive even deeper, you
+can read the [Frequently-Asked Questions](V1_7_FAQ.md).
\ No newline at end of file
diff --git a/third_party/googletest/googletest/docs/V1_7_Documentation.md b/third_party/googletest/googletest/docs/V1_7_Documentation.md
new file mode 100644
index 0000000..282697a
--- /dev/null
+++ b/third_party/googletest/googletest/docs/V1_7_Documentation.md
@@ -0,0 +1,14 @@
+This page lists all documentation wiki pages for Google Test **(the SVN trunk version)**
+-- **if you use a released version of Google Test, please read the
+documentation for that specific version instead.**
+
+  * [Primer](V1_7_Primer.md) -- start here if you are new to Google Test.
+  * [Samples](V1_7_Samples.md) -- learn from examples.
+  * [AdvancedGuide](V1_7_AdvancedGuide.md) -- learn more about Google Test.
+  * [XcodeGuide](V1_7_XcodeGuide.md) -- how to use Google Test in Xcode on Mac.
+  * [Frequently-Asked Questions](V1_7_FAQ.md) -- check here before asking a question on the mailing list.
+
+To contribute code to Google Test, read:
+
+  * [DevGuide](DevGuide.md) -- read this _before_ writing your first patch.
+  * [PumpManual](V1_7_PumpManual.md) -- how we generate some of Google Test's source files.
\ No newline at end of file
diff --git a/third_party/googletest/googletest/docs/V1_7_FAQ.md b/third_party/googletest/googletest/docs/V1_7_FAQ.md
new file mode 100644
index 0000000..b5d547c
--- /dev/null
+++ b/third_party/googletest/googletest/docs/V1_7_FAQ.md
@@ -0,0 +1,1081 @@
+
+
+If you cannot find the answer to your question here, and you have read
+[Primer](V1_7_Primer.md) and [AdvancedGuide](V1_7_AdvancedGuide.md), send it to
+googletestframework@googlegroups.com.
+
+## Why should I use Google Test instead of my favorite C++ testing framework? ##
+
+First, let us say clearly that we don't want to get into the debate of
+which C++ testing framework is **the best**.  There exist many fine
+frameworks for writing C++ tests, and we have tremendous respect for
+the developers and users of them.  We don't think there is (or will
+be) a single best framework - you have to pick the right tool for the
+particular task you are tackling.
+
+We created Google Test because we couldn't find the right combination
+of features and conveniences in an existing framework to satisfy _our_
+needs.  The following is a list of things that _we_ like about Google
+Test.  We don't claim them to be unique to Google Test - rather, the
+combination of them makes Google Test the choice for us.  We hope this
+list can help you decide whether it is for you too.
+
+  * Google Test is designed to be portable: it doesn't require exceptions or RTTI; it works around various bugs in various compilers and environments; etc.  As a result, it works on Linux, Mac OS X, Windows and several embedded operating systems.
+  * Nonfatal assertions (`EXPECT_*`) have proven to be great time savers, as they allow a test to report multiple failures in a single edit-compile-test cycle.
+  * It's easy to write assertions that generate informative messages: you just use the stream syntax to append any additional information, e.g. `ASSERT_EQ(5, Foo(i)) << " where i = " << i;`.  It doesn't require a new set of macros or special functions.
+  * Google Test automatically detects your tests and doesn't require you to enumerate them in order to run them.
+  * Death tests are pretty handy for ensuring that your asserts in production code are triggered by the right conditions.
+  * `SCOPED_TRACE` helps you understand the context of an assertion failure when it comes from inside a sub-routine or loop.
+  * You can decide which tests to run using name patterns.  This saves time when you want to quickly reproduce a test failure.
+  * Google Test can generate XML test result reports that can be parsed by popular continuous build system like Hudson.
+  * Simple things are easy in Google Test, while hard things are possible: in addition to advanced features like [global test environments](http://code.google.com/p/googletest/wiki/V1_7_AdvancedGuide#Global_Set-Up_and_Tear-Down) and tests parameterized by [values](http://code.google.com/p/googletest/wiki/V1_7_AdvancedGuide#Value_Parameterized_Tests) or [types](http://code.google.com/p/googletest/wiki/V1_7_AdvancedGuide#Typed_Tests), Google Test supports various ways for the user to extend the framework -- if Google Test doesn't do something out of the box, chances are that a user can implement the feature using Google Test's public API, without changing Google Test itself.  In particular, you can:
+    * expand your testing vocabulary by defining [custom predicates](http://code.google.com/p/googletest/wiki/V1_7_AdvancedGuide#Predicate_Assertions_for_Better_Error_Messages),
+    * teach Google Test how to [print your types](http://code.google.com/p/googletest/wiki/V1_7_AdvancedGuide#Teaching_Google_Test_How_to_Print_Your_Values),
+    * define your own testing macros or utilities and verify them using Google Test's [Service Provider Interface](http://code.google.com/p/googletest/wiki/V1_7_AdvancedGuide#Catching_Failures), and
+    * reflect on the test cases or change the test output format by intercepting the [test events](http://code.google.com/p/googletest/wiki/V1_7_AdvancedGuide#Extending_Google_Test_by_Handling_Test_Events).
+
+## I'm getting warnings when compiling Google Test.  Would you fix them? ##
+
+We strive to minimize compiler warnings Google Test generates.  Before releasing a new version, we test to make sure that it doesn't generate warnings when compiled using its CMake script on Windows, Linux, and Mac OS.
+
+Unfortunately, this doesn't mean you are guaranteed to see no warnings when compiling Google Test in your environment:
+
+  * You may be using a different compiler as we use, or a different version of the same compiler.  We cannot possibly test for all compilers.
+  * You may be compiling on a different platform as we do.
+  * Your project may be using different compiler flags as we do.
+
+It is not always possible to make Google Test warning-free for everyone.  Or, it may not be desirable if the warning is rarely enabled and fixing the violations makes the code more complex.
+
+If you see warnings when compiling Google Test, we suggest that you use the `-isystem` flag (assuming your are using GCC) to mark Google Test headers as system headers.  That'll suppress warnings from Google Test headers.
+
+## Why should not test case names and test names contain underscore? ##
+
+Underscore (`_`) is special, as C++ reserves the following to be used by
+the compiler and the standard library:
+
+  1. any identifier that starts with an `_` followed by an upper-case letter, and
+  1. any identifier that containers two consecutive underscores (i.e. `__`) _anywhere_ in its name.
+
+User code is _prohibited_ from using such identifiers.
+
+Now let's look at what this means for `TEST` and `TEST_F`.
+
+Currently `TEST(TestCaseName, TestName)` generates a class named
+`TestCaseName_TestName_Test`.  What happens if `TestCaseName` or `TestName`
+contains `_`?
+
+  1. If `TestCaseName` starts with an `_` followed by an upper-case letter (say, `_Foo`), we end up with `_Foo_TestName_Test`, which is reserved and thus invalid.
+  1. If `TestCaseName` ends with an `_` (say, `Foo_`), we get `Foo__TestName_Test`, which is invalid.
+  1. If `TestName` starts with an `_` (say, `_Bar`), we get `TestCaseName__Bar_Test`, which is invalid.
+  1. If `TestName` ends with an `_` (say, `Bar_`), we get `TestCaseName_Bar__Test`, which is invalid.
+
+So clearly `TestCaseName` and `TestName` cannot start or end with `_`
+(Actually, `TestCaseName` can start with `_` -- as long as the `_` isn't
+followed by an upper-case letter.  But that's getting complicated.  So
+for simplicity we just say that it cannot start with `_`.).
+
+It may seem fine for `TestCaseName` and `TestName` to contain `_` in the
+middle.  However, consider this:
+```
+TEST(Time, Flies_Like_An_Arrow) { ... }
+TEST(Time_Flies, Like_An_Arrow) { ... }
+```
+
+Now, the two `TEST`s will both generate the same class
+(`Time_Files_Like_An_Arrow_Test`).  That's not good.
+
+So for simplicity, we just ask the users to avoid `_` in `TestCaseName`
+and `TestName`.  The rule is more constraining than necessary, but it's
+simple and easy to remember.  It also gives Google Test some wiggle
+room in case its implementation needs to change in the future.
+
+If you violate the rule, there may not be immediately consequences,
+but your test may (just may) break with a new compiler (or a new
+version of the compiler you are using) or with a new version of Google
+Test.  Therefore it's best to follow the rule.
+
+## Why is it not recommended to install a pre-compiled copy of Google Test (for example, into /usr/local)? ##
+
+In the early days, we said that you could install
+compiled Google Test libraries on `*`nix systems using `make install`.
+Then every user of your machine can write tests without
+recompiling Google Test.
+
+This seemed like a good idea, but it has a
+got-cha: every user needs to compile his tests using the _same_ compiler
+flags used to compile the installed Google Test libraries; otherwise
+he may run into undefined behaviors (i.e. the tests can behave
+strangely and may even crash for no obvious reasons).
+
+Why?  Because C++ has this thing called the One-Definition Rule: if
+two C++ source files contain different definitions of the same
+class/function/variable, and you link them together, you violate the
+rule.  The linker may or may not catch the error (in many cases it's
+not required by the C++ standard to catch the violation).  If it
+doesn't, you get strange run-time behaviors that are unexpected and
+hard to debug.
+
+If you compile Google Test and your test code using different compiler
+flags, they may see different definitions of the same
+class/function/variable (e.g. due to the use of `#if` in Google Test).
+Therefore, for your sanity, we recommend to avoid installing pre-compiled
+Google Test libraries.  Instead, each project should compile
+Google Test itself such that it can be sure that the same flags are
+used for both Google Test and the tests.
+
+## How do I generate 64-bit binaries on Windows (using Visual Studio 2008)? ##
+
+(Answered by Trevor Robinson)
+
+Load the supplied Visual Studio solution file, either `msvc\gtest-md.sln` or
+`msvc\gtest.sln`. Go through the migration wizard to migrate the
+solution and project files to Visual Studio 2008. Select
+`Configuration Manager...` from the `Build` menu. Select `<New...>` from
+the `Active solution platform` dropdown.  Select `x64` from the new
+platform dropdown, leave `Copy settings from` set to `Win32` and
+`Create new project platforms` checked, then click `OK`. You now have
+`Win32` and `x64` platform configurations, selectable from the
+`Standard` toolbar, which allow you to toggle between building 32-bit or
+64-bit binaries (or both at once using Batch Build).
+
+In order to prevent build output files from overwriting one another,
+you'll need to change the `Intermediate Directory` settings for the
+newly created platform configuration across all the projects. To do
+this, multi-select (e.g. using shift-click) all projects (but not the
+solution) in the `Solution Explorer`. Right-click one of them and
+select `Properties`. In the left pane, select `Configuration Properties`,
+and from the `Configuration` dropdown, select `All Configurations`.
+Make sure the selected platform is `x64`. For the
+`Intermediate Directory` setting, change the value from
+`$(PlatformName)\$(ConfigurationName)` to
+`$(OutDir)\$(ProjectName)`. Click `OK` and then build the
+solution. When the build is complete, the 64-bit binaries will be in
+the `msvc\x64\Debug` directory.
+
+## Can I use Google Test on MinGW? ##
+
+We haven't tested this ourselves, but Per Abrahamsen reported that he
+was able to compile and install Google Test successfully when using
+MinGW from Cygwin.  You'll need to configure it with:
+
+`PATH/TO/configure CC="gcc -mno-cygwin" CXX="g++ -mno-cygwin"`
+
+You should be able to replace the `-mno-cygwin` option with direct links
+to the real MinGW binaries, but we haven't tried that.
+
+Caveats:
+
+  * There are many warnings when compiling.
+  * `make check` will produce some errors as not all tests for Google Test itself are compatible with MinGW.
+
+We also have reports on successful cross compilation of Google Test
+MinGW binaries on Linux using
+[these instructions](http://wiki.wxwidgets.org/Cross-Compiling_Under_Linux#Cross-compiling_under_Linux_for_MS_Windows)
+on the WxWidgets site.
+
+Please contact `googletestframework@googlegroups.com` if you are
+interested in improving the support for MinGW.
+
+## Why does Google Test support EXPECT\_EQ(NULL, ptr) and ASSERT\_EQ(NULL, ptr) but not EXPECT\_NE(NULL, ptr) and ASSERT\_NE(NULL, ptr)? ##
+
+Due to some peculiarity of C++, it requires some non-trivial template
+meta programming tricks to support using `NULL` as an argument of the
+`EXPECT_XX()` and `ASSERT_XX()` macros. Therefore we only do it where
+it's most needed (otherwise we make the implementation of Google Test
+harder to maintain and more error-prone than necessary).
+
+The `EXPECT_EQ()` macro takes the _expected_ value as its first
+argument and the _actual_ value as the second. It's reasonable that
+someone wants to write `EXPECT_EQ(NULL, some_expression)`, and this
+indeed was requested several times. Therefore we implemented it.
+
+The need for `EXPECT_NE(NULL, ptr)` isn't nearly as strong. When the
+assertion fails, you already know that `ptr` must be `NULL`, so it
+doesn't add any information to print ptr in this case. That means
+`EXPECT_TRUE(ptr != NULL)` works just as well.
+
+If we were to support `EXPECT_NE(NULL, ptr)`, for consistency we'll
+have to support `EXPECT_NE(ptr, NULL)` as well, as unlike `EXPECT_EQ`,
+we don't have a convention on the order of the two arguments for
+`EXPECT_NE`. This means using the template meta programming tricks
+twice in the implementation, making it even harder to understand and
+maintain. We believe the benefit doesn't justify the cost.
+
+Finally, with the growth of Google Mock's [matcher](http://code.google.com/p/googlemock/wiki/CookBook#Using_Matchers_in_Google_Test_Assertions) library, we are
+encouraging people to use the unified `EXPECT_THAT(value, matcher)`
+syntax more often in tests. One significant advantage of the matcher
+approach is that matchers can be easily combined to form new matchers,
+while the `EXPECT_NE`, etc, macros cannot be easily
+combined. Therefore we want to invest more in the matchers than in the
+`EXPECT_XX()` macros.
+
+## Does Google Test support running tests in parallel? ##
+
+Test runners tend to be tightly coupled with the build/test
+environment, and Google Test doesn't try to solve the problem of
+running tests in parallel.  Instead, we tried to make Google Test work
+nicely with test runners.  For example, Google Test's XML report
+contains the time spent on each test, and its `gtest_list_tests` and
+`gtest_filter` flags can be used for splitting the execution of test
+methods into multiple processes.  These functionalities can help the
+test runner run the tests in parallel.
+
+## Why don't Google Test run the tests in different threads to speed things up? ##
+
+It's difficult to write thread-safe code.  Most tests are not written
+with thread-safety in mind, and thus may not work correctly in a
+multi-threaded setting.
+
+If you think about it, it's already hard to make your code work when
+you know what other threads are doing.  It's much harder, and
+sometimes even impossible, to make your code work when you don't know
+what other threads are doing (remember that test methods can be added,
+deleted, or modified after your test was written).  If you want to run
+the tests in parallel, you'd better run them in different processes.
+
+## Why aren't Google Test assertions implemented using exceptions? ##
+
+Our original motivation was to be able to use Google Test in projects
+that disable exceptions.  Later we realized some additional benefits
+of this approach:
+
+  1. Throwing in a destructor is undefined behavior in C++.  Not using exceptions means Google Test's assertions are safe to use in destructors.
+  1. The `EXPECT_*` family of macros will continue even after a failure, allowing multiple failures in a `TEST` to be reported in a single run. This is a popular feature, as in C++ the edit-compile-test cycle is usually quite long and being able to fixing more than one thing at a time is a blessing.
+  1. If assertions are implemented using exceptions, a test may falsely ignore a failure if it's caught by user code:
+```
+try { ... ASSERT_TRUE(...) ... }
+catch (...) { ... }
+```
+The above code will pass even if the `ASSERT_TRUE` throws.  While it's unlikely for someone to write this in a test, it's possible to run into this pattern when you write assertions in callbacks that are called by the code under test.
+
+The downside of not using exceptions is that `ASSERT_*` (implemented
+using `return`) will only abort the current function, not the current
+`TEST`.
+
+## Why do we use two different macros for tests with and without fixtures? ##
+
+Unfortunately, C++'s macro system doesn't allow us to use the same
+macro for both cases.  One possibility is to provide only one macro
+for tests with fixtures, and require the user to define an empty
+fixture sometimes:
+
+```
+class FooTest : public ::testing::Test {};
+
+TEST_F(FooTest, DoesThis) { ... }
+```
+or
+```
+typedef ::testing::Test FooTest;
+
+TEST_F(FooTest, DoesThat) { ... }
+```
+
+Yet, many people think this is one line too many. :-) Our goal was to
+make it really easy to write tests, so we tried to make simple tests
+trivial to create.  That means using a separate macro for such tests.
+
+We think neither approach is ideal, yet either of them is reasonable.
+In the end, it probably doesn't matter much either way.
+
+## Why don't we use structs as test fixtures? ##
+
+We like to use structs only when representing passive data.  This
+distinction between structs and classes is good for documenting the
+intent of the code's author.  Since test fixtures have logic like
+`SetUp()` and `TearDown()`, they are better defined as classes.
+
+## Why are death tests implemented as assertions instead of using a test runner? ##
+
+Our goal was to make death tests as convenient for a user as C++
+possibly allows.  In particular:
+
+  * The runner-style requires to split the information into two pieces: the definition of the death test itself, and the specification for the runner on how to run the death test and what to expect.  The death test would be written in C++, while the runner spec may or may not be.  A user needs to carefully keep the two in sync. `ASSERT_DEATH(statement, expected_message)` specifies all necessary information in one place, in one language, without boilerplate code. It is very declarative.
+  * `ASSERT_DEATH` has a similar syntax and error-reporting semantics as other Google Test assertions, and thus is easy to learn.
+  * `ASSERT_DEATH` can be mixed with other assertions and other logic at your will.  You are not limited to one death test per test method. For example, you can write something like:
+```
+    if (FooCondition()) {
+      ASSERT_DEATH(Bar(), "blah");
+    } else {
+      ASSERT_EQ(5, Bar());
+    }
+```
+If you prefer one death test per test method, you can write your tests in that style too, but we don't want to impose that on the users.  The fewer artificial limitations the better.
+  * `ASSERT_DEATH` can reference local variables in the current function, and you can decide how many death tests you want based on run-time information.  For example,
+```
+    const int count = GetCount();  // Only known at run time.
+    for (int i = 1; i <= count; i++) {
+      ASSERT_DEATH({
+        double* buffer = new double[i];
+        ... initializes buffer ...
+        Foo(buffer, i)
+      }, "blah blah");
+    }
+```
+The runner-based approach tends to be more static and less flexible, or requires more user effort to get this kind of flexibility.
+
+Another interesting thing about `ASSERT_DEATH` is that it calls `fork()`
+to create a child process to run the death test.  This is lightening
+fast, as `fork()` uses copy-on-write pages and incurs almost zero
+overhead, and the child process starts from the user-supplied
+statement directly, skipping all global and local initialization and
+any code leading to the given statement.  If you launch the child
+process from scratch, it can take seconds just to load everything and
+start running if the test links to many libraries dynamically.
+
+## My death test modifies some state, but the change seems lost after the death test finishes. Why? ##
+
+Death tests (`EXPECT_DEATH`, etc) are executed in a sub-process s.t. the
+expected crash won't kill the test program (i.e. the parent process). As a
+result, any in-memory side effects they incur are observable in their
+respective sub-processes, but not in the parent process. You can think of them
+as running in a parallel universe, more or less.
+
+## The compiler complains about "undefined references" to some static const member variables, but I did define them in the class body. What's wrong? ##
+
+If your class has a static data member:
+
+```
+// foo.h
+class Foo {
+  ...
+  static const int kBar = 100;
+};
+```
+
+You also need to define it _outside_ of the class body in `foo.cc`:
+
+```
+const int Foo::kBar;  // No initializer here.
+```
+
+Otherwise your code is **invalid C++**, and may break in unexpected ways. In
+particular, using it in Google Test comparison assertions (`EXPECT_EQ`, etc)
+will generate an "undefined reference" linker error.
+
+## I have an interface that has several implementations. Can I write a set of tests once and repeat them over all the implementations? ##
+
+Google Test doesn't yet have good support for this kind of tests, or
+data-driven tests in general. We hope to be able to make improvements in this
+area soon.
+
+## Can I derive a test fixture from another? ##
+
+Yes.
+
+Each test fixture has a corresponding and same named test case. This means only
+one test case can use a particular fixture. Sometimes, however, multiple test
+cases may want to use the same or slightly different fixtures. For example, you
+may want to make sure that all of a GUI library's test cases don't leak
+important system resources like fonts and brushes.
+
+In Google Test, you share a fixture among test cases by putting the shared
+logic in a base test fixture, then deriving from that base a separate fixture
+for each test case that wants to use this common logic. You then use `TEST_F()`
+to write tests using each derived fixture.
+
+Typically, your code looks like this:
+
+```
+// Defines a base test fixture.
+class BaseTest : public ::testing::Test {
+  protected:
+   ...
+};
+
+// Derives a fixture FooTest from BaseTest.
+class FooTest : public BaseTest {
+  protected:
+    virtual void SetUp() {
+      BaseTest::SetUp();  // Sets up the base fixture first.
+      ... additional set-up work ...
+    }
+    virtual void TearDown() {
+      ... clean-up work for FooTest ...
+      BaseTest::TearDown();  // Remember to tear down the base fixture
+                             // after cleaning up FooTest!
+    }
+    ... functions and variables for FooTest ...
+};
+
+// Tests that use the fixture FooTest.
+TEST_F(FooTest, Bar) { ... }
+TEST_F(FooTest, Baz) { ... }
+
+... additional fixtures derived from BaseTest ...
+```
+
+If necessary, you can continue to derive test fixtures from a derived fixture.
+Google Test has no limit on how deep the hierarchy can be.
+
+For a complete example using derived test fixtures, see
+[sample5](http://code.google.com/p/googletest/source/browse/trunk/samples/sample5_unittest.cc).
+
+## My compiler complains "void value not ignored as it ought to be." What does this mean? ##
+
+You're probably using an `ASSERT_*()` in a function that doesn't return `void`.
+`ASSERT_*()` can only be used in `void` functions.
+
+## My death test hangs (or seg-faults). How do I fix it? ##
+
+In Google Test, death tests are run in a child process and the way they work is
+delicate. To write death tests you really need to understand how they work.
+Please make sure you have read this.
+
+In particular, death tests don't like having multiple threads in the parent
+process. So the first thing you can try is to eliminate creating threads
+outside of `EXPECT_DEATH()`.
+
+Sometimes this is impossible as some library you must use may be creating
+threads before `main()` is even reached. In this case, you can try to minimize
+the chance of conflicts by either moving as many activities as possible inside
+`EXPECT_DEATH()` (in the extreme case, you want to move everything inside), or
+leaving as few things as possible in it. Also, you can try to set the death
+test style to `"threadsafe"`, which is safer but slower, and see if it helps.
+
+If you go with thread-safe death tests, remember that they rerun the test
+program from the beginning in the child process. Therefore make sure your
+program can run side-by-side with itself and is deterministic.
+
+In the end, this boils down to good concurrent programming. You have to make
+sure that there is no race conditions or dead locks in your program. No silver
+bullet - sorry!
+
+## Should I use the constructor/destructor of the test fixture or the set-up/tear-down function? ##
+
+The first thing to remember is that Google Test does not reuse the
+same test fixture object across multiple tests. For each `TEST_F`,
+Google Test will create a fresh test fixture object, _immediately_
+call `SetUp()`, run the test, call `TearDown()`, and then
+_immediately_ delete the test fixture object. Therefore, there is no
+need to write a `SetUp()` or `TearDown()` function if the constructor
+or destructor already does the job.
+
+You may still want to use `SetUp()/TearDown()` in the following cases:
+  * If the tear-down operation could throw an exception, you must use `TearDown()` as opposed to the destructor, as throwing in a destructor leads to undefined behavior and usually will kill your program right away. Note that many standard libraries (like STL) may throw when exceptions are enabled in the compiler. Therefore you should prefer `TearDown()` if you want to write portable tests that work with or without exceptions.
+  * The assertion macros throw an exception when flag `--gtest_throw_on_failure` is specified. Therefore, you shouldn't use Google Test assertions in a destructor if you plan to run your tests with this flag.
+  * In a constructor or destructor, you cannot make a virtual function call on this object. (You can call a method declared as virtual, but it will be statically bound.) Therefore, if you need to call a method that will be overriden in a derived class, you have to use `SetUp()/TearDown()`.
+
+## The compiler complains "no matching function to call" when I use ASSERT\_PREDn. How do I fix it? ##
+
+If the predicate function you use in `ASSERT_PRED*` or `EXPECT_PRED*` is
+overloaded or a template, the compiler will have trouble figuring out which
+overloaded version it should use. `ASSERT_PRED_FORMAT*` and
+`EXPECT_PRED_FORMAT*` don't have this problem.
+
+If you see this error, you might want to switch to
+`(ASSERT|EXPECT)_PRED_FORMAT*`, which will also give you a better failure
+message. If, however, that is not an option, you can resolve the problem by
+explicitly telling the compiler which version to pick.
+
+For example, suppose you have
+
+```
+bool IsPositive(int n) {
+  return n > 0;
+}
+bool IsPositive(double x) {
+  return x > 0;
+}
+```
+
+you will get a compiler error if you write
+
+```
+EXPECT_PRED1(IsPositive, 5);
+```
+
+However, this will work:
+
+```
+EXPECT_PRED1(*static_cast<bool (*)(int)>*(IsPositive), 5);
+```
+
+(The stuff inside the angled brackets for the `static_cast` operator is the
+type of the function pointer for the `int`-version of `IsPositive()`.)
+
+As another example, when you have a template function
+
+```
+template <typename T>
+bool IsNegative(T x) {
+  return x < 0;
+}
+```
+
+you can use it in a predicate assertion like this:
+
+```
+ASSERT_PRED1(IsNegative*<int>*, -5);
+```
+
+Things are more interesting if your template has more than one parameters. The
+following won't compile:
+
+```
+ASSERT_PRED2(*GreaterThan<int, int>*, 5, 0);
+```
+
+
+as the C++ pre-processor thinks you are giving `ASSERT_PRED2` 4 arguments,
+which is one more than expected. The workaround is to wrap the predicate
+function in parentheses:
+
+```
+ASSERT_PRED2(*(GreaterThan<int, int>)*, 5, 0);
+```
+
+
+## My compiler complains about "ignoring return value" when I call RUN\_ALL\_TESTS(). Why? ##
+
+Some people had been ignoring the return value of `RUN_ALL_TESTS()`. That is,
+instead of
+
+```
+return RUN_ALL_TESTS();
+```
+
+they write
+
+```
+RUN_ALL_TESTS();
+```
+
+This is wrong and dangerous. A test runner needs to see the return value of
+`RUN_ALL_TESTS()` in order to determine if a test has passed. If your `main()`
+function ignores it, your test will be considered successful even if it has a
+Google Test assertion failure. Very bad.
+
+To help the users avoid this dangerous bug, the implementation of
+`RUN_ALL_TESTS()` causes gcc to raise this warning, when the return value is
+ignored. If you see this warning, the fix is simple: just make sure its value
+is used as the return value of `main()`.
+
+## My compiler complains that a constructor (or destructor) cannot return a value. What's going on? ##
+
+Due to a peculiarity of C++, in order to support the syntax for streaming
+messages to an `ASSERT_*`, e.g.
+
+```
+ASSERT_EQ(1, Foo()) << "blah blah" << foo;
+```
+
+we had to give up using `ASSERT*` and `FAIL*` (but not `EXPECT*` and
+`ADD_FAILURE*`) in constructors and destructors. The workaround is to move the
+content of your constructor/destructor to a private void member function, or
+switch to `EXPECT_*()` if that works. This section in the user's guide explains
+it.
+
+## My set-up function is not called. Why? ##
+
+C++ is case-sensitive. It should be spelled as `SetUp()`.  Did you
+spell it as `Setup()`?
+
+Similarly, sometimes people spell `SetUpTestCase()` as `SetupTestCase()` and
+wonder why it's never called.
+
+## How do I jump to the line of a failure in Emacs directly? ##
+
+Google Test's failure message format is understood by Emacs and many other
+IDEs, like acme and XCode. If a Google Test message is in a compilation buffer
+in Emacs, then it's clickable. You can now hit `enter` on a message to jump to
+the corresponding source code, or use `C-x `` to jump to the next failure.
+
+## I have several test cases which share the same test fixture logic, do I have to define a new test fixture class for each of them? This seems pretty tedious. ##
+
+You don't have to. Instead of
+
+```
+class FooTest : public BaseTest {};
+
+TEST_F(FooTest, Abc) { ... }
+TEST_F(FooTest, Def) { ... }
+
+class BarTest : public BaseTest {};
+
+TEST_F(BarTest, Abc) { ... }
+TEST_F(BarTest, Def) { ... }
+```
+
+you can simply `typedef` the test fixtures:
+```
+typedef BaseTest FooTest;
+
+TEST_F(FooTest, Abc) { ... }
+TEST_F(FooTest, Def) { ... }
+
+typedef BaseTest BarTest;
+
+TEST_F(BarTest, Abc) { ... }
+TEST_F(BarTest, Def) { ... }
+```
+
+## The Google Test output is buried in a whole bunch of log messages. What do I do? ##
+
+The Google Test output is meant to be a concise and human-friendly report. If
+your test generates textual output itself, it will mix with the Google Test
+output, making it hard to read. However, there is an easy solution to this
+problem.
+
+Since most log messages go to stderr, we decided to let Google Test output go
+to stdout. This way, you can easily separate the two using redirection. For
+example:
+```
+./my_test > googletest_output.txt
+```
+
+## Why should I prefer test fixtures over global variables? ##
+
+There are several good reasons:
+  1. It's likely your test needs to change the states of its global variables. This makes it difficult to keep side effects from escaping one test and contaminating others, making debugging difficult. By using fixtures, each test has a fresh set of variables that's different (but with the same names). Thus, tests are kept independent of each other.
+  1. Global variables pollute the global namespace.
+  1. Test fixtures can be reused via subclassing, which cannot be done easily with global variables. This is useful if many test cases have something in common.
+
+## How do I test private class members without writing FRIEND\_TEST()s? ##
+
+You should try to write testable code, which means classes should be easily
+tested from their public interface. One way to achieve this is the Pimpl idiom:
+you move all private members of a class into a helper class, and make all
+members of the helper class public.
+
+You have several other options that don't require using `FRIEND_TEST`:
+  * Write the tests as members of the fixture class:
+```
+class Foo {
+  friend class FooTest;
+  ...
+};
+
+class FooTest : public ::testing::Test {
+ protected:
+  ...
+  void Test1() {...} // This accesses private members of class Foo.
+  void Test2() {...} // So does this one.
+};
+
+TEST_F(FooTest, Test1) {
+  Test1();
+}
+
+TEST_F(FooTest, Test2) {
+  Test2();
+}
+```
+  * In the fixture class, write accessors for the tested class' private members, then use the accessors in your tests:
+```
+class Foo {
+  friend class FooTest;
+  ...
+};
+
+class FooTest : public ::testing::Test {
+ protected:
+  ...
+  T1 get_private_member1(Foo* obj) {
+    return obj->private_member1_;
+  }
+};
+
+TEST_F(FooTest, Test1) {
+  ...
+  get_private_member1(x)
+  ...
+}
+```
+  * If the methods are declared **protected**, you can change their access level in a test-only subclass:
+```
+class YourClass {
+  ...
+ protected: // protected access for testability.
+  int DoSomethingReturningInt();
+  ...
+};
+
+// in the your_class_test.cc file:
+class TestableYourClass : public YourClass {
+  ...
+ public: using YourClass::DoSomethingReturningInt; // changes access rights
+  ...
+};
+
+TEST_F(YourClassTest, DoSomethingTest) {
+  TestableYourClass obj;
+  assertEquals(expected_value, obj.DoSomethingReturningInt());
+}
+```
+
+## How do I test private class static members without writing FRIEND\_TEST()s? ##
+
+We find private static methods clutter the header file.  They are
+implementation details and ideally should be kept out of a .h. So often I make
+them free functions instead.
+
+Instead of:
+```
+// foo.h
+class Foo {
+  ...
+ private:
+  static bool Func(int n);
+};
+
+// foo.cc
+bool Foo::Func(int n) { ... }
+
+// foo_test.cc
+EXPECT_TRUE(Foo::Func(12345));
+```
+
+You probably should better write:
+```
+// foo.h
+class Foo {
+  ...
+};
+
+// foo.cc
+namespace internal {
+  bool Func(int n) { ... }
+}
+
+// foo_test.cc
+namespace internal {
+  bool Func(int n);
+}
+
+EXPECT_TRUE(internal::Func(12345));
+```
+
+## I would like to run a test several times with different parameters. Do I need to write several similar copies of it? ##
+
+No. You can use a feature called [value-parameterized tests](V1_7_AdvancedGuide#Value_Parameterized_Tests.md) which
+lets you repeat your tests with different parameters, without defining it more than once.
+
+## How do I test a file that defines main()? ##
+
+To test a `foo.cc` file, you need to compile and link it into your unit test
+program. However, when the file contains a definition for the `main()`
+function, it will clash with the `main()` of your unit test, and will result in
+a build error.
+
+The right solution is to split it into three files:
+  1. `foo.h` which contains the declarations,
+  1. `foo.cc` which contains the definitions except `main()`, and
+  1. `foo_main.cc` which contains nothing but the definition of `main()`.
+
+Then `foo.cc` can be easily tested.
+
+If you are adding tests to an existing file and don't want an intrusive change
+like this, there is a hack: just include the entire `foo.cc` file in your unit
+test. For example:
+```
+// File foo_unittest.cc
+
+// The headers section
+...
+
+// Renames main() in foo.cc to make room for the unit test main()
+#define main FooMain
+
+#include "a/b/foo.cc"
+
+// The tests start here.
+...
+```
+
+
+However, please remember this is a hack and should only be used as the last
+resort.
+
+## What can the statement argument in ASSERT\_DEATH() be? ##
+
+`ASSERT_DEATH(_statement_, _regex_)` (or any death assertion macro) can be used
+wherever `_statement_` is valid. So basically `_statement_` can be any C++
+statement that makes sense in the current context. In particular, it can
+reference global and/or local variables, and can be:
+  * a simple function call (often the case),
+  * a complex expression, or
+  * a compound statement.
+
+> Some examples are shown here:
+```
+// A death test can be a simple function call.
+TEST(MyDeathTest, FunctionCall) {
+  ASSERT_DEATH(Xyz(5), "Xyz failed");
+}
+
+// Or a complex expression that references variables and functions.
+TEST(MyDeathTest, ComplexExpression) {
+  const bool c = Condition();
+  ASSERT_DEATH((c ? Func1(0) : object2.Method("test")),
+               "(Func1|Method) failed");
+}
+
+// Death assertions can be used any where in a function. In
+// particular, they can be inside a loop.
+TEST(MyDeathTest, InsideLoop) {
+  // Verifies that Foo(0), Foo(1), ..., and Foo(4) all die.
+  for (int i = 0; i < 5; i++) {
+    EXPECT_DEATH_M(Foo(i), "Foo has \\d+ errors",
+                   ::testing::Message() << "where i is " << i);
+  }
+}
+
+// A death assertion can contain a compound statement.
+TEST(MyDeathTest, CompoundStatement) {
+  // Verifies that at lease one of Bar(0), Bar(1), ..., and
+  // Bar(4) dies.
+  ASSERT_DEATH({
+    for (int i = 0; i < 5; i++) {
+      Bar(i);
+    }
+  },
+  "Bar has \\d+ errors");}
+```
+
+`googletest_unittest.cc` contains more examples if you are interested.
+
+## What syntax does the regular expression in ASSERT\_DEATH use? ##
+
+On POSIX systems, Google Test uses the POSIX Extended regular
+expression syntax
+(http://en.wikipedia.org/wiki/Regular_expression#POSIX_Extended_Regular_Expressions).
+On Windows, it uses a limited variant of regular expression
+syntax. For more details, see the
+[regular expression syntax](V1_7_AdvancedGuide#Regular_Expression_Syntax.md).
+
+## I have a fixture class Foo, but TEST\_F(Foo, Bar) gives me error "no matching function for call to Foo::Foo()". Why? ##
+
+Google Test needs to be able to create objects of your test fixture class, so
+it must have a default constructor. Normally the compiler will define one for
+you. However, there are cases where you have to define your own:
+  * If you explicitly declare a non-default constructor for class `Foo`, then you need to define a default constructor, even if it would be empty.
+  * If `Foo` has a const non-static data member, then you have to define the default constructor _and_ initialize the const member in the initializer list of the constructor. (Early versions of `gcc` doesn't force you to initialize the const member. It's a bug that has been fixed in `gcc 4`.)
+
+## Why does ASSERT\_DEATH complain about previous threads that were already joined? ##
+
+With the Linux pthread library, there is no turning back once you cross the
+line from single thread to multiple threads. The first time you create a
+thread, a manager thread is created in addition, so you get 3, not 2, threads.
+Later when the thread you create joins the main thread, the thread count
+decrements by 1, but the manager thread will never be killed, so you still have
+2 threads, which means you cannot safely run a death test.
+
+The new NPTL thread library doesn't suffer from this problem, as it doesn't
+create a manager thread. However, if you don't control which machine your test
+runs on, you shouldn't depend on this.
+
+## Why does Google Test require the entire test case, instead of individual tests, to be named FOODeathTest when it uses ASSERT\_DEATH? ##
+
+Google Test does not interleave tests from different test cases. That is, it
+runs all tests in one test case first, and then runs all tests in the next test
+case, and so on. Google Test does this because it needs to set up a test case
+before the first test in it is run, and tear it down afterwords. Splitting up
+the test case would require multiple set-up and tear-down processes, which is
+inefficient and makes the semantics unclean.
+
+If we were to determine the order of tests based on test name instead of test
+case name, then we would have a problem with the following situation:
+
+```
+TEST_F(FooTest, AbcDeathTest) { ... }
+TEST_F(FooTest, Uvw) { ... }
+
+TEST_F(BarTest, DefDeathTest) { ... }
+TEST_F(BarTest, Xyz) { ... }
+```
+
+Since `FooTest.AbcDeathTest` needs to run before `BarTest.Xyz`, and we don't
+interleave tests from different test cases, we need to run all tests in the
+`FooTest` case before running any test in the `BarTest` case. This contradicts
+with the requirement to run `BarTest.DefDeathTest` before `FooTest.Uvw`.
+
+## But I don't like calling my entire test case FOODeathTest when it contains both death tests and non-death tests. What do I do? ##
+
+You don't have to, but if you like, you may split up the test case into
+`FooTest` and `FooDeathTest`, where the names make it clear that they are
+related:
+
+```
+class FooTest : public ::testing::Test { ... };
+
+TEST_F(FooTest, Abc) { ... }
+TEST_F(FooTest, Def) { ... }
+
+typedef FooTest FooDeathTest;
+
+TEST_F(FooDeathTest, Uvw) { ... EXPECT_DEATH(...) ... }
+TEST_F(FooDeathTest, Xyz) { ... ASSERT_DEATH(...) ... }
+```
+
+## The compiler complains about "no match for 'operator<<'" when I use an assertion. What gives? ##
+
+If you use a user-defined type `FooType` in an assertion, you must make sure
+there is an `std::ostream& operator<<(std::ostream&, const FooType&)` function
+defined such that we can print a value of `FooType`.
+
+In addition, if `FooType` is declared in a name space, the `<<` operator also
+needs to be defined in the _same_ name space.
+
+## How do I suppress the memory leak messages on Windows? ##
+
+Since the statically initialized Google Test singleton requires allocations on
+the heap, the Visual C++ memory leak detector will report memory leaks at the
+end of the program run. The easiest way to avoid this is to use the
+`_CrtMemCheckpoint` and `_CrtMemDumpAllObjectsSince` calls to not report any
+statically initialized heap objects. See MSDN for more details and additional
+heap check/debug routines.
+
+## I am building my project with Google Test in Visual Studio and all I'm getting is a bunch of linker errors (or warnings). Help! ##
+
+You may get a number of the following linker error or warnings if you
+attempt to link your test project with the Google Test library when
+your project and the are not built using the same compiler settings.
+
+  * LNK2005: symbol already defined in object
+  * LNK4217: locally defined symbol 'symbol' imported in function 'function'
+  * LNK4049: locally defined symbol 'symbol' imported
+
+The Google Test project (gtest.vcproj) has the Runtime Library option
+set to /MT (use multi-threaded static libraries, /MTd for debug). If
+your project uses something else, for example /MD (use multi-threaded
+DLLs, /MDd for debug), you need to change the setting in the Google
+Test project to match your project's.
+
+To update this setting open the project properties in the Visual
+Studio IDE then select the branch Configuration Properties | C/C++ |
+Code Generation and change the option "Runtime Library".  You may also try
+using gtest-md.vcproj instead of gtest.vcproj.
+
+## I put my tests in a library and Google Test doesn't run them. What's happening? ##
+Have you read a
+[warning](http://code.google.com/p/googletest/wiki/V1_7_Primer#Important_note_for_Visual_C++_users) on
+the Google Test Primer page?
+
+## I want to use Google Test with Visual Studio but don't know where to start. ##
+Many people are in your position and one of the posted his solution to
+our mailing list. Here is his link:
+http://hassanjamilahmad.blogspot.com/2009/07/gtest-starters-help.html.
+
+## I am seeing compile errors mentioning std::type\_traits when I try to use Google Test on Solaris. ##
+Google Test uses parts of the standard C++ library that SunStudio does not support.
+Our users reported success using alternative implementations. Try running the build after runing this commad:
+
+`export CC=cc CXX=CC CXXFLAGS='-library=stlport4'`
+
+## How can my code detect if it is running in a test? ##
+
+If you write code that sniffs whether it's running in a test and does
+different things accordingly, you are leaking test-only logic into
+production code and there is no easy way to ensure that the test-only
+code paths aren't run by mistake in production.  Such cleverness also
+leads to
+[Heisenbugs](http://en.wikipedia.org/wiki/Unusual_software_bug#Heisenbug).
+Therefore we strongly advise against the practice, and Google Test doesn't
+provide a way to do it.
+
+In general, the recommended way to cause the code to behave
+differently under test is [dependency injection](http://jamesshore.com/Blog/Dependency-Injection-Demystified.html).
+You can inject different functionality from the test and from the
+production code.  Since your production code doesn't link in the
+for-test logic at all, there is no danger in accidentally running it.
+
+However, if you _really_, _really_, _really_ have no choice, and if
+you follow the rule of ending your test program names with `_test`,
+you can use the _horrible_ hack of sniffing your executable name
+(`argv[0]` in `main()`) to know whether the code is under test.
+
+## Google Test defines a macro that clashes with one defined by another library. How do I deal with that? ##
+
+In C++, macros don't obey namespaces.  Therefore two libraries that
+both define a macro of the same name will clash if you #include both
+definitions.  In case a Google Test macro clashes with another
+library, you can force Google Test to rename its macro to avoid the
+conflict.
+
+Specifically, if both Google Test and some other code define macro
+`FOO`, you can add
+```
+  -DGTEST_DONT_DEFINE_FOO=1
+```
+to the compiler flags to tell Google Test to change the macro's name
+from `FOO` to `GTEST_FOO`. For example, with `-DGTEST_DONT_DEFINE_TEST=1`, you'll need to write
+```
+  GTEST_TEST(SomeTest, DoesThis) { ... }
+```
+instead of
+```
+  TEST(SomeTest, DoesThis) { ... }
+```
+in order to define a test.
+
+Currently, the following `TEST`, `FAIL`, `SUCCEED`, and the basic comparison assertion macros can have alternative names. You can see the full list of covered macros [here](http://www.google.com/codesearch?q=if+!GTEST_DONT_DEFINE_\w%2B+package:http://googletest\.googlecode\.com+file:/include/gtest/gtest.h). More information can be found in the "Avoiding Macro Name Clashes" section of the README file.
+
+
+## Is it OK if I have two separate `TEST(Foo, Bar)` test methods defined in different namespaces? ##
+
+Yes.
+
+The rule is **all test methods in the same test case must use the same fixture class**. This means that the following is **allowed** because both tests use the same fixture class (`::testing::Test`).
+
+```
+namespace foo {
+TEST(CoolTest, DoSomething) {
+  SUCCEED();
+}
+}  // namespace foo
+
+namespace bar {
+TEST(CoolTest, DoSomething) {
+  SUCCEED();
+}
+}  // namespace foo
+```
+
+However, the following code is **not allowed** and will produce a runtime error from Google Test because the test methods are using different test fixture classes with the same test case name.
+
+```
+namespace foo {
+class CoolTest : public ::testing::Test {};  // Fixture foo::CoolTest
+TEST_F(CoolTest, DoSomething) {
+  SUCCEED();
+}
+}  // namespace foo
+
+namespace bar {
+class CoolTest : public ::testing::Test {};  // Fixture: bar::CoolTest
+TEST_F(CoolTest, DoSomething) {
+  SUCCEED();
+}
+}  // namespace foo
+```
+
+## How do I build Google Testing Framework with Xcode 4? ##
+
+If you try to build Google Test's Xcode project with Xcode 4.0 or later, you may encounter an error message that looks like
+"Missing SDK in target gtest\_framework: /Developer/SDKs/MacOSX10.4u.sdk". That means that Xcode does not support the SDK the project is targeting. See the Xcode section in the [README](http://code.google.com/p/googletest/source/browse/trunk/README) file on how to resolve this.
+
+## My question is not covered in your FAQ! ##
+
+If you cannot find the answer to your question in this FAQ, there are
+some other resources you can use:
+
+  1. read other [wiki pages](http://code.google.com/p/googletest/w/list),
+  1. search the mailing list [archive](http://groups.google.com/group/googletestframework/topics),
+  1. ask it on [googletestframework@googlegroups.com](mailto:googletestframework@googlegroups.com) and someone will answer it (to prevent spam, we require you to join the [discussion group](http://groups.google.com/group/googletestframework) before you can post.).
+
+Please note that creating an issue in the
+[issue tracker](http://code.google.com/p/googletest/issues/list) is _not_
+a good way to get your answer, as it is monitored infrequently by a
+very small number of people.
+
+When asking a question, it's helpful to provide as much of the
+following information as possible (people cannot help you if there's
+not enough information in your question):
+
+  * the version (or the revision number if you check out from SVN directly) of Google Test you use (Google Test is under active development, so it's possible that your problem has been solved in a later version),
+  * your operating system,
+  * the name and version of your compiler,
+  * the complete command line flags you give to your compiler,
+  * the complete compiler error messages (if the question is about compilation),
+  * the _actual_ code (ideally, a minimal but complete program) that has the problem you encounter.
\ No newline at end of file
diff --git a/third_party/googletest/googletest/docs/V1_7_Primer.md b/third_party/googletest/googletest/docs/V1_7_Primer.md
new file mode 100644
index 0000000..1de5080
--- /dev/null
+++ b/third_party/googletest/googletest/docs/V1_7_Primer.md
@@ -0,0 +1,501 @@
+
+
+# Introduction: Why Google C++ Testing Framework? #
+
+_Google C++ Testing Framework_ helps you write better C++ tests.
+
+No matter whether you work on Linux, Windows, or a Mac, if you write C++ code,
+Google Test can help you.
+
+So what makes a good test, and how does Google C++ Testing Framework fit in? We believe:
+  1. Tests should be _independent_ and _repeatable_. It's a pain to debug a test that succeeds or fails as a result of other tests.  Google C++ Testing Framework isolates the tests by running each of them on a different object. When a test fails, Google C++ Testing Framework allows you to run it in isolation for quick debugging.
+  1. Tests should be well _organized_ and reflect the structure of the tested code.  Google C++ Testing Framework groups related tests into test cases that can share data and subroutines. This common pattern is easy to recognize and makes tests easy to maintain. Such consistency is especially helpful when people switch projects and start to work on a new code base.
+  1. Tests should be _portable_ and _reusable_. The open-source community has a lot of code that is platform-neutral, its tests should also be platform-neutral.  Google C++ Testing Framework works on different OSes, with different compilers (gcc, MSVC, and others), with or without exceptions, so Google C++ Testing Framework tests can easily work with a variety of configurations.  (Note that the current release only contains build scripts for Linux - we are actively working on scripts for other platforms.)
+  1. When tests fail, they should provide as much _information_ about the problem as possible. Google C++ Testing Framework doesn't stop at the first test failure. Instead, it only stops the current test and continues with the next. You can also set up tests that report non-fatal failures after which the current test continues. Thus, you can detect and fix multiple bugs in a single run-edit-compile cycle.
+  1. The testing framework should liberate test writers from housekeeping chores and let them focus on the test _content_.  Google C++ Testing Framework automatically keeps track of all tests defined, and doesn't require the user to enumerate them in order to run them.
+  1. Tests should be _fast_. With Google C++ Testing Framework, you can reuse shared resources across tests and pay for the set-up/tear-down only once, without making tests depend on each other.
+
+Since Google C++ Testing Framework is based on the popular xUnit
+architecture, you'll feel right at home if you've used JUnit or PyUnit before.
+If not, it will take you about 10 minutes to learn the basics and get started.
+So let's go!
+
+_Note:_ We sometimes refer to Google C++ Testing Framework informally
+as _Google Test_.
+
+# Setting up a New Test Project #
+
+To write a test program using Google Test, you need to compile Google
+Test into a library and link your test with it.  We provide build
+files for some popular build systems: `msvc/` for Visual Studio,
+`xcode/` for Mac Xcode, `make/` for GNU make, `codegear/` for Borland
+C++ Builder, and the autotools script (deprecated) and
+`CMakeLists.txt` for CMake (recommended) in the Google Test root
+directory.  If your build system is not on this list, you can take a
+look at `make/Makefile` to learn how Google Test should be compiled
+(basically you want to compile `src/gtest-all.cc` with `GTEST_ROOT`
+and `GTEST_ROOT/include` in the header search path, where `GTEST_ROOT`
+is the Google Test root directory).
+
+Once you are able to compile the Google Test library, you should
+create a project or build target for your test program.  Make sure you
+have `GTEST_ROOT/include` in the header search path so that the
+compiler can find `"gtest/gtest.h"` when compiling your test.  Set up
+your test project to link with the Google Test library (for example,
+in Visual Studio, this is done by adding a dependency on
+`gtest.vcproj`).
+
+If you still have questions, take a look at how Google Test's own
+tests are built and use them as examples.
+
+# Basic Concepts #
+
+When using Google Test, you start by writing _assertions_, which are statements
+that check whether a condition is true. An assertion's result can be _success_,
+_nonfatal failure_, or _fatal failure_. If a fatal failure occurs, it aborts
+the current function; otherwise the program continues normally.
+
+_Tests_ use assertions to verify the tested code's behavior. If a test crashes
+or has a failed assertion, then it _fails_; otherwise it _succeeds_.
+
+A _test case_ contains one or many tests. You should group your tests into test
+cases that reflect the structure of the tested code. When multiple tests in a
+test case need to share common objects and subroutines, you can put them into a
+_test fixture_ class.
+
+A _test program_ can contain multiple test cases.
+
+We'll now explain how to write a test program, starting at the individual
+assertion level and building up to tests and test cases.
+
+# Assertions #
+
+Google Test assertions are macros that resemble function calls. You test a
+class or function by making assertions about its behavior. When an assertion
+fails, Google Test prints the assertion's source file and line number location,
+along with a failure message. You may also supply a custom failure message
+which will be appended to Google Test's message.
+
+The assertions come in pairs that test the same thing but have different
+effects on the current function. `ASSERT_*` versions generate fatal failures
+when they fail, and **abort the current function**. `EXPECT_*` versions generate
+nonfatal failures, which don't abort the current function. Usually `EXPECT_*`
+are preferred, as they allow more than one failures to be reported in a test.
+However, you should use `ASSERT_*` if it doesn't make sense to continue when
+the assertion in question fails.
+
+Since a failed `ASSERT_*` returns from the current function immediately,
+possibly skipping clean-up code that comes after it, it may cause a space leak.
+Depending on the nature of the leak, it may or may not be worth fixing - so
+keep this in mind if you get a heap checker error in addition to assertion
+errors.
+
+To provide a custom failure message, simply stream it into the macro using the
+`<<` operator, or a sequence of such operators. An example:
+```
+ASSERT_EQ(x.size(), y.size()) << "Vectors x and y are of unequal length";
+
+for (int i = 0; i < x.size(); ++i) {
+  EXPECT_EQ(x[i], y[i]) << "Vectors x and y differ at index " << i;
+}
+```
+
+Anything that can be streamed to an `ostream` can be streamed to an assertion
+macro--in particular, C strings and `string` objects. If a wide string
+(`wchar_t*`, `TCHAR*` in `UNICODE` mode on Windows, or `std::wstring`) is
+streamed to an assertion, it will be translated to UTF-8 when printed.
+
+## Basic Assertions ##
+
+These assertions do basic true/false condition testing.
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_TRUE(`_condition_`)`;  | `EXPECT_TRUE(`_condition_`)`;   | _condition_ is true |
+| `ASSERT_FALSE(`_condition_`)`; | `EXPECT_FALSE(`_condition_`)`;  | _condition_ is false |
+
+Remember, when they fail, `ASSERT_*` yields a fatal failure and
+returns from the current function, while `EXPECT_*` yields a nonfatal
+failure, allowing the function to continue running. In either case, an
+assertion failure means its containing test fails.
+
+_Availability_: Linux, Windows, Mac.
+
+## Binary Comparison ##
+
+This section describes assertions that compare two values.
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+|`ASSERT_EQ(`_expected_`, `_actual_`);`|`EXPECT_EQ(`_expected_`, `_actual_`);`| _expected_ `==` _actual_ |
+|`ASSERT_NE(`_val1_`, `_val2_`);`      |`EXPECT_NE(`_val1_`, `_val2_`);`      | _val1_ `!=` _val2_ |
+|`ASSERT_LT(`_val1_`, `_val2_`);`      |`EXPECT_LT(`_val1_`, `_val2_`);`      | _val1_ `<` _val2_ |
+|`ASSERT_LE(`_val1_`, `_val2_`);`      |`EXPECT_LE(`_val1_`, `_val2_`);`      | _val1_ `<=` _val2_ |
+|`ASSERT_GT(`_val1_`, `_val2_`);`      |`EXPECT_GT(`_val1_`, `_val2_`);`      | _val1_ `>` _val2_ |
+|`ASSERT_GE(`_val1_`, `_val2_`);`      |`EXPECT_GE(`_val1_`, `_val2_`);`      | _val1_ `>=` _val2_ |
+
+In the event of a failure, Google Test prints both _val1_ and _val2_
+. In `ASSERT_EQ*` and `EXPECT_EQ*` (and all other equality assertions
+we'll introduce later), you should put the expression you want to test
+in the position of _actual_, and put its expected value in _expected_,
+as Google Test's failure messages are optimized for this convention.
+
+Value arguments must be comparable by the assertion's comparison
+operator or you'll get a compiler error.  We used to require the
+arguments to support the `<<` operator for streaming to an `ostream`,
+but it's no longer necessary since v1.6.0 (if `<<` is supported, it
+will be called to print the arguments when the assertion fails;
+otherwise Google Test will attempt to print them in the best way it
+can. For more details and how to customize the printing of the
+arguments, see this Google Mock [recipe](http://code.google.com/p/googlemock/wiki/CookBook#Teaching_Google_Mock_How_to_Print_Your_Values).).
+
+These assertions can work with a user-defined type, but only if you define the
+corresponding comparison operator (e.g. `==`, `<`, etc).  If the corresponding
+operator is defined, prefer using the `ASSERT_*()` macros because they will
+print out not only the result of the comparison, but the two operands as well.
+
+Arguments are always evaluated exactly once. Therefore, it's OK for the
+arguments to have side effects. However, as with any ordinary C/C++ function,
+the arguments' evaluation order is undefined (i.e. the compiler is free to
+choose any order) and your code should not depend on any particular argument
+evaluation order.
+
+`ASSERT_EQ()` does pointer equality on pointers. If used on two C strings, it
+tests if they are in the same memory location, not if they have the same value.
+Therefore, if you want to compare C strings (e.g. `const char*`) by value, use
+`ASSERT_STREQ()` , which will be described later on. In particular, to assert
+that a C string is `NULL`, use `ASSERT_STREQ(NULL, c_string)` . However, to
+compare two `string` objects, you should use `ASSERT_EQ`.
+
+Macros in this section work with both narrow and wide string objects (`string`
+and `wstring`).
+
+_Availability_: Linux, Windows, Mac.
+
+## String Comparison ##
+
+The assertions in this group compare two **C strings**. If you want to compare
+two `string` objects, use `EXPECT_EQ`, `EXPECT_NE`, and etc instead.
+
+| **Fatal assertion** | **Nonfatal assertion** | **Verifies** |
+|:--------------------|:-----------------------|:-------------|
+| `ASSERT_STREQ(`_expected\_str_`, `_actual\_str_`);`    | `EXPECT_STREQ(`_expected\_str_`, `_actual\_str_`);`     | the two C strings have the same content |
+| `ASSERT_STRNE(`_str1_`, `_str2_`);`    | `EXPECT_STRNE(`_str1_`, `_str2_`);`     | the two C strings have different content |
+| `ASSERT_STRCASEEQ(`_expected\_str_`, `_actual\_str_`);`| `EXPECT_STRCASEEQ(`_expected\_str_`, `_actual\_str_`);` | the two C strings have the same content, ignoring case |
+| `ASSERT_STRCASENE(`_str1_`, `_str2_`);`| `EXPECT_STRCASENE(`_str1_`, `_str2_`);` | the two C strings have different content, ignoring case |
+
+Note that "CASE" in an assertion name means that case is ignored.
+
+`*STREQ*` and `*STRNE*` also accept wide C strings (`wchar_t*`). If a
+comparison of two wide strings fails, their values will be printed as UTF-8
+narrow strings.
+
+A `NULL` pointer and an empty string are considered _different_.
+
+_Availability_: Linux, Windows, Mac.
+
+See also: For more string comparison tricks (substring, prefix, suffix, and
+regular expression matching, for example), see the [Advanced Google Test Guide](V1_7_AdvancedGuide.md).
+
+# Simple Tests #
+
+To create a test:
+  1. Use the `TEST()` macro to define and name a test function, These are ordinary C++ functions that don't return a value.
+  1. In this function, along with any valid C++ statements you want to include, use the various Google Test assertions to check values.
+  1. The test's result is determined by the assertions; if any assertion in the test fails (either fatally or non-fatally), or if the test crashes, the entire test fails. Otherwise, it succeeds.
+
+```
+TEST(test_case_name, test_name) {
+ ... test body ...
+}
+```
+
+
+`TEST()` arguments go from general to specific. The _first_ argument is the
+name of the test case, and the _second_ argument is the test's name within the
+test case. Both names must be valid C++ identifiers, and they should not contain underscore (`_`). A test's _full name_ consists of its containing test case and its
+individual name. Tests from different test cases can have the same individual
+name.
+
+For example, let's take a simple integer function:
+```
+int Factorial(int n); // Returns the factorial of n
+```
+
+A test case for this function might look like:
+```
+// Tests factorial of 0.
+TEST(FactorialTest, HandlesZeroInput) {
+  EXPECT_EQ(1, Factorial(0));
+}
+
+// Tests factorial of positive numbers.
+TEST(FactorialTest, HandlesPositiveInput) {
+  EXPECT_EQ(1, Factorial(1));
+  EXPECT_EQ(2, Factorial(2));
+  EXPECT_EQ(6, Factorial(3));
+  EXPECT_EQ(40320, Factorial(8));
+}
+```
+
+Google Test groups the test results by test cases, so logically-related tests
+should be in the same test case; in other words, the first argument to their
+`TEST()` should be the same. In the above example, we have two tests,
+`HandlesZeroInput` and `HandlesPositiveInput`, that belong to the same test
+case `FactorialTest`.
+
+_Availability_: Linux, Windows, Mac.
+
+# Test Fixtures: Using the Same Data Configuration for Multiple Tests #
+
+If you find yourself writing two or more tests that operate on similar data,
+you can use a _test fixture_. It allows you to reuse the same configuration of
+objects for several different tests.
+
+To create a fixture, just:
+  1. Derive a class from `::testing::Test` . Start its body with `protected:` or `public:` as we'll want to access fixture members from sub-classes.
+  1. Inside the class, declare any objects you plan to use.
+  1. If necessary, write a default constructor or `SetUp()` function to prepare the objects for each test. A common mistake is to spell `SetUp()` as `Setup()` with a small `u` - don't let that happen to you.
+  1. If necessary, write a destructor or `TearDown()` function to release any resources you allocated in `SetUp()` . To learn when you should use the constructor/destructor and when you should use `SetUp()/TearDown()`, read this [FAQ entry](http://code.google.com/p/googletest/wiki/V1_7_FAQ#Should_I_use_the_constructor/destructor_of_the_test_fixture_or_t).
+  1. If needed, define subroutines for your tests to share.
+
+When using a fixture, use `TEST_F()` instead of `TEST()` as it allows you to
+access objects and subroutines in the test fixture:
+```
+TEST_F(test_case_name, test_name) {
+ ... test body ...
+}
+```
+
+Like `TEST()`, the first argument is the test case name, but for `TEST_F()`
+this must be the name of the test fixture class. You've probably guessed: `_F`
+is for fixture.
+
+Unfortunately, the C++ macro system does not allow us to create a single macro
+that can handle both types of tests. Using the wrong macro causes a compiler
+error.
+
+Also, you must first define a test fixture class before using it in a
+`TEST_F()`, or you'll get the compiler error "`virtual outside class
+declaration`".
+
+For each test defined with `TEST_F()`, Google Test will:
+  1. Create a _fresh_ test fixture at runtime
+  1. Immediately initialize it via `SetUp()` ,
+  1. Run the test
+  1. Clean up by calling `TearDown()`
+  1. Delete the test fixture.  Note that different tests in the same test case have different test fixture objects, and Google Test always deletes a test fixture before it creates the next one. Google Test does not reuse the same test fixture for multiple tests. Any changes one test makes to the fixture do not affect other tests.
+
+As an example, let's write tests for a FIFO queue class named `Queue`, which
+has the following interface:
+```
+template <typename E> // E is the element type.
+class Queue {
+ public:
+  Queue();
+  void Enqueue(const E& element);
+  E* Dequeue(); // Returns NULL if the queue is empty.
+  size_t size() const;
+  ...
+};
+```
+
+First, define a fixture class. By convention, you should give it the name
+`FooTest` where `Foo` is the class being tested.
+```
+class QueueTest : public ::testing::Test {
+ protected:
+  virtual void SetUp() {
+    q1_.Enqueue(1);
+    q2_.Enqueue(2);
+    q2_.Enqueue(3);
+  }
+
+  // virtual void TearDown() {}
+
+  Queue<int> q0_;
+  Queue<int> q1_;
+  Queue<int> q2_;
+};
+```
+
+In this case, `TearDown()` is not needed since we don't have to clean up after
+each test, other than what's already done by the destructor.
+
+Now we'll write tests using `TEST_F()` and this fixture.
+```
+TEST_F(QueueTest, IsEmptyInitially) {
+  EXPECT_EQ(0, q0_.size());
+}
+
+TEST_F(QueueTest, DequeueWorks) {
+  int* n = q0_.Dequeue();
+  EXPECT_EQ(NULL, n);
+
+  n = q1_.Dequeue();
+  ASSERT_TRUE(n != NULL);
+  EXPECT_EQ(1, *n);
+  EXPECT_EQ(0, q1_.size());
+  delete n;
+
+  n = q2_.Dequeue();
+  ASSERT_TRUE(n != NULL);
+  EXPECT_EQ(2, *n);
+  EXPECT_EQ(1, q2_.size());
+  delete n;
+}
+```
+
+The above uses both `ASSERT_*` and `EXPECT_*` assertions. The rule of thumb is
+to use `EXPECT_*` when you want the test to continue to reveal more errors
+after the assertion failure, and use `ASSERT_*` when continuing after failure
+doesn't make sense. For example, the second assertion in the `Dequeue` test is
+`ASSERT_TRUE(n != NULL)`, as we need to dereference the pointer `n` later,
+which would lead to a segfault when `n` is `NULL`.
+
+When these tests run, the following happens:
+  1. Google Test constructs a `QueueTest` object (let's call it `t1` ).
+  1. `t1.SetUp()` initializes `t1` .
+  1. The first test ( `IsEmptyInitially` ) runs on `t1` .
+  1. `t1.TearDown()` cleans up after the test finishes.
+  1. `t1` is destructed.
+  1. The above steps are repeated on another `QueueTest` object, this time running the `DequeueWorks` test.
+
+_Availability_: Linux, Windows, Mac.
+
+_Note_: Google Test automatically saves all _Google Test_ flags when a test
+object is constructed, and restores them when it is destructed.
+
+# Invoking the Tests #
+
+`TEST()` and `TEST_F()` implicitly register their tests with Google Test. So, unlike with many other C++ testing frameworks, you don't have to re-list all your defined tests in order to run them.
+
+After defining your tests, you can run them with `RUN_ALL_TESTS()` , which returns `0` if all the tests are successful, or `1` otherwise. Note that `RUN_ALL_TESTS()` runs _all tests_ in your link unit -- they can be from different test cases, or even different source files.
+
+When invoked, the `RUN_ALL_TESTS()` macro:
+  1. Saves the state of all  Google Test flags.
+  1. Creates a test fixture object for the first test.
+  1. Initializes it via `SetUp()`.
+  1. Runs the test on the fixture object.
+  1. Cleans up the fixture via `TearDown()`.
+  1. Deletes the fixture.
+  1. Restores the state of all Google Test flags.
+  1. Repeats the above steps for the next test, until all tests have run.
+
+In addition, if the text fixture's constructor generates a fatal failure in
+step 2, there is no point for step 3 - 5 and they are thus skipped. Similarly,
+if step 3 generates a fatal failure, step 4 will be skipped.
+
+_Important_: You must not ignore the return value of `RUN_ALL_TESTS()`, or `gcc`
+will give you a compiler error. The rationale for this design is that the
+automated testing service determines whether a test has passed based on its
+exit code, not on its stdout/stderr output; thus your `main()` function must
+return the value of `RUN_ALL_TESTS()`.
+
+Also, you should call `RUN_ALL_TESTS()` only **once**. Calling it more than once
+conflicts with some advanced Google Test features (e.g. thread-safe death
+tests) and thus is not supported.
+
+_Availability_: Linux, Windows, Mac.
+
+# Writing the main() Function #
+
+You can start from this boilerplate:
+```
+#include "this/package/foo.h"
+#include "gtest/gtest.h"
+
+namespace {
+
+// The fixture for testing class Foo.
+class FooTest : public ::testing::Test {
+ protected:
+  // You can remove any or all of the following functions if its body
+  // is empty.
+
+  FooTest() {
+    // You can do set-up work for each test here.
+  }
+
+  virtual ~FooTest() {
+    // You can do clean-up work that doesn't throw exceptions here.
+  }
+
+  // If the constructor and destructor are not enough for setting up
+  // and cleaning up each test, you can define the following methods:
+
+  virtual void SetUp() {
+    // Code here will be called immediately after the constructor (right
+    // before each test).
+  }
+
+  virtual void TearDown() {
+    // Code here will be called immediately after each test (right
+    // before the destructor).
+  }
+
+  // Objects declared here can be used by all tests in the test case for Foo.
+};
+
+// Tests that the Foo::Bar() method does Abc.
+TEST_F(FooTest, MethodBarDoesAbc) {
+  const string input_filepath = "this/package/testdata/myinputfile.dat";
+  const string output_filepath = "this/package/testdata/myoutputfile.dat";
+  Foo f;
+  EXPECT_EQ(0, f.Bar(input_filepath, output_filepath));
+}
+
+// Tests that Foo does Xyz.
+TEST_F(FooTest, DoesXyz) {
+  // Exercises the Xyz feature of Foo.
+}
+
+}  // namespace
+
+int main(int argc, char **argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
+```
+
+The `::testing::InitGoogleTest()` function parses the command line for Google
+Test flags, and removes all recognized flags. This allows the user to control a
+test program's behavior via various flags, which we'll cover in [AdvancedGuide](V1_7_AdvancedGuide.md).
+You must call this function before calling `RUN_ALL_TESTS()`, or the flags
+won't be properly initialized.
+
+On Windows, `InitGoogleTest()` also works with wide strings, so it can be used
+in programs compiled in `UNICODE` mode as well.
+
+But maybe you think that writing all those main() functions is too much work? We agree with you completely and that's why Google Test provides a basic implementation of main(). If it fits your needs, then just link your test with gtest\_main library and you are good to go.
+
+## Important note for Visual C++ users ##
+If you put your tests into a library and your `main()` function is in a different library or in your .exe file, those tests will not run. The reason is a [bug](https://connect.microsoft.com/feedback/viewfeedback.aspx?FeedbackID=244410&siteid=210) in Visual C++. When you define your tests, Google Test creates certain static objects to register them. These objects are not referenced from elsewhere but their constructors are still supposed to run. When Visual C++ linker sees that nothing in the library is referenced from other places it throws the library out. You have to reference your library with tests from your main program to keep the linker from discarding it. Here is how to do it. Somewhere in your library code declare a function:
+```
+__declspec(dllexport) int PullInMyLibrary() { return 0; }
+```
+If you put your tests in a static library (not DLL) then `__declspec(dllexport)` is not required. Now, in your main program, write a code that invokes that function:
+```
+int PullInMyLibrary();
+static int dummy = PullInMyLibrary();
+```
+This will keep your tests referenced and will make them register themselves at startup.
+
+In addition, if you define your tests in a static library, add `/OPT:NOREF` to your main program linker options. If you use MSVC++ IDE, go to your .exe project properties/Configuration Properties/Linker/Optimization and set References setting to `Keep Unreferenced Data (/OPT:NOREF)`. This will keep Visual C++ linker from discarding individual symbols generated by your tests from the final executable.
+
+There is one more pitfall, though. If you use Google Test as a static library (that's how it is defined in gtest.vcproj) your tests must also reside in a static library. If you have to have them in a DLL, you _must_ change Google Test to build into a DLL as well. Otherwise your tests will not run correctly or will not run at all. The general conclusion here is: make your life easier - do not write your tests in libraries!
+
+# Where to Go from Here #
+
+Congratulations! You've learned the Google Test basics. You can start writing
+and running Google Test tests, read some [samples](V1_7_Samples.md), or continue with
+[AdvancedGuide](V1_7_AdvancedGuide.md), which describes many more useful Google Test features.
+
+# Known Limitations #
+
+Google Test is designed to be thread-safe.  The implementation is
+thread-safe on systems where the `pthreads` library is available.  It
+is currently _unsafe_ to use Google Test assertions from two threads
+concurrently on other systems (e.g. Windows).  In most tests this is
+not an issue as usually the assertions are done in the main thread. If
+you want to help, you can volunteer to implement the necessary
+synchronization primitives in `gtest-port.h` for your platform.
\ No newline at end of file
diff --git a/third_party/googletest/googletest/docs/V1_7_PumpManual.md b/third_party/googletest/googletest/docs/V1_7_PumpManual.md
new file mode 100644
index 0000000..cf6cf56
--- /dev/null
+++ b/third_party/googletest/googletest/docs/V1_7_PumpManual.md
@@ -0,0 +1,177 @@
+
+
+<b>P</b>ump is <b>U</b>seful for <b>M</b>eta <b>P</b>rogramming.
+
+# The Problem #
+
+Template and macro libraries often need to define many classes,
+functions, or macros that vary only (or almost only) in the number of
+arguments they take. It's a lot of repetitive, mechanical, and
+error-prone work.
+
+Variadic templates and variadic macros can alleviate the problem.
+However, while both are being considered by the C++ committee, neither
+is in the standard yet or widely supported by compilers.  Thus they
+are often not a good choice, especially when your code needs to be
+portable. And their capabilities are still limited.
+
+As a result, authors of such libraries often have to write scripts to
+generate their implementation. However, our experience is that it's
+tedious to write such scripts, which tend to reflect the structure of
+the generated code poorly and are often hard to read and edit. For
+example, a small change needed in the generated code may require some
+non-intuitive, non-trivial changes in the script. This is especially
+painful when experimenting with the code.
+
+# Our Solution #
+
+Pump (for Pump is Useful for Meta Programming, Pretty Useful for Meta
+Programming, or Practical Utility for Meta Programming, whichever you
+prefer) is a simple meta-programming tool for C++. The idea is that a
+programmer writes a `foo.pump` file which contains C++ code plus meta
+code that manipulates the C++ code. The meta code can handle
+iterations over a range, nested iterations, local meta variable
+definitions, simple arithmetic, and conditional expressions. You can
+view it as a small Domain-Specific Language. The meta language is
+designed to be non-intrusive (s.t. it won't confuse Emacs' C++ mode,
+for example) and concise, making Pump code intuitive and easy to
+maintain.
+
+## Highlights ##
+
+  * The implementation is in a single Python script and thus ultra portable: no build or installation is needed and it works cross platforms.
+  * Pump tries to be smart with respect to [Google's style guide](http://code.google.com/p/google-styleguide/): it breaks long lines (easy to have when they are generated) at acceptable places to fit within 80 columns and indent the continuation lines correctly.
+  * The format is human-readable and more concise than XML.
+  * The format works relatively well with Emacs' C++ mode.
+
+## Examples ##
+
+The following Pump code (where meta keywords start with `$`, `[[` and `]]` are meta brackets, and `$$` starts a meta comment that ends with the line):
+
+```
+$var n = 3     $$ Defines a meta variable n.
+$range i 0..n  $$ Declares the range of meta iterator i (inclusive).
+$for i [[
+               $$ Meta loop.
+// Foo$i does blah for $i-ary predicates.
+$range j 1..i
+template <size_t N $for j [[, typename A$j]]>
+class Foo$i {
+$if i == 0 [[
+  blah a;
+]] $elif i <= 2 [[
+  blah b;
+]] $else [[
+  blah c;
+]]
+};
+
+]]
+```
+
+will be translated by the Pump compiler to:
+
+```
+// Foo0 does blah for 0-ary predicates.
+template <size_t N>
+class Foo0 {
+  blah a;
+};
+
+// Foo1 does blah for 1-ary predicates.
+template <size_t N, typename A1>
+class Foo1 {
+  blah b;
+};
+
+// Foo2 does blah for 2-ary predicates.
+template <size_t N, typename A1, typename A2>
+class Foo2 {
+  blah b;
+};
+
+// Foo3 does blah for 3-ary predicates.
+template <size_t N, typename A1, typename A2, typename A3>
+class Foo3 {
+  blah c;
+};
+```
+
+In another example,
+
+```
+$range i 1..n
+Func($for i + [[a$i]]);
+$$ The text between i and [[ is the separator between iterations.
+```
+
+will generate one of the following lines (without the comments), depending on the value of `n`:
+
+```
+Func();              // If n is 0.
+Func(a1);            // If n is 1.
+Func(a1 + a2);       // If n is 2.
+Func(a1 + a2 + a3);  // If n is 3.
+// And so on...
+```
+
+## Constructs ##
+
+We support the following meta programming constructs:
+
+| `$var id = exp` | Defines a named constant value. `$id` is valid util the end of the current meta lexical block. |
+|:----------------|:-----------------------------------------------------------------------------------------------|
+| `$range id exp..exp` | Sets the range of an iteration variable, which can be reused in multiple loops later.          |
+| `$for id sep [[ code ]]` | Iteration. The range of `id` must have been defined earlier. `$id` is valid in `code`.         |
+| `$($)`          | Generates a single `$` character.                                                              |
+| `$id`           | Value of the named constant or iteration variable.                                             |
+| `$(exp)`        | Value of the expression.                                                                       |
+| `$if exp [[ code ]] else_branch` | Conditional.                                                                                   |
+| `[[ code ]]`    | Meta lexical block.                                                                            |
+| `cpp_code`      | Raw C++ code.                                                                                  |
+| `$$ comment`    | Meta comment.                                                                                  |
+
+**Note:** To give the user some freedom in formatting the Pump source
+code, Pump ignores a new-line character if it's right after `$for foo`
+or next to `[[` or `]]`. Without this rule you'll often be forced to write
+very long lines to get the desired output. Therefore sometimes you may
+need to insert an extra new-line in such places for a new-line to show
+up in your output.
+
+## Grammar ##
+
+```
+code ::= atomic_code*
+atomic_code ::= $var id = exp
+    | $var id = [[ code ]]
+    | $range id exp..exp
+    | $for id sep [[ code ]]
+    | $($)
+    | $id
+    | $(exp)
+    | $if exp [[ code ]] else_branch
+    | [[ code ]]
+    | cpp_code
+sep ::= cpp_code | empty_string
+else_branch ::= $else [[ code ]]
+    | $elif exp [[ code ]] else_branch
+    | empty_string
+exp ::= simple_expression_in_Python_syntax
+```
+
+## Code ##
+
+You can find the source code of Pump in [scripts/pump.py](http://code.google.com/p/googletest/source/browse/trunk/scripts/pump.py). It is still
+very unpolished and lacks automated tests, although it has been
+successfully used many times. If you find a chance to use it in your
+project, please let us know what you think!  We also welcome help on
+improving Pump.
+
+## Real Examples ##
+
+You can find real-world applications of Pump in [Google Test](http://www.google.com/codesearch?q=file%3A\.pump%24+package%3Ahttp%3A%2F%2Fgoogletest\.googlecode\.com) and [Google Mock](http://www.google.com/codesearch?q=file%3A\.pump%24+package%3Ahttp%3A%2F%2Fgooglemock\.googlecode\.com).  The source file `foo.h.pump` generates `foo.h`.
+
+## Tips ##
+
+  * If a meta variable is followed by a letter or digit, you can separate them using `[[]]`, which inserts an empty string. For example `Foo$j[[]]Helper` generate `Foo1Helper` when `j` is 1.
+  * To avoid extra-long Pump source lines, you can break a line anywhere you want by inserting `[[]]` followed by a new line. Since any new-line character next to `[[` or `]]` is ignored, the generated code won't contain this new line.
\ No newline at end of file
diff --git a/third_party/googletest/googletest/docs/V1_7_Samples.md b/third_party/googletest/googletest/docs/V1_7_Samples.md
new file mode 100644
index 0000000..8122569
--- /dev/null
+++ b/third_party/googletest/googletest/docs/V1_7_Samples.md
@@ -0,0 +1,14 @@
+If you're like us, you'd like to look at some Google Test sample code.  The
+[samples folder](http://code.google.com/p/googletest/source/browse/#svn/trunk/samples) has a number of well-commented samples showing how to use a
+variety of Google Test features.
+
+  * [Sample #1](http://code.google.com/p/googletest/source/browse/trunk/samples/sample1_unittest.cc) shows the basic steps of using Google Test to test C++ functions.
+  * [Sample #2](http://code.google.com/p/googletest/source/browse/trunk/samples/sample2_unittest.cc) shows a more complex unit test for a class with multiple member functions.
+  * [Sample #3](http://code.google.com/p/googletest/source/browse/trunk/samples/sample3_unittest.cc) uses a test fixture.
+  * [Sample #4](http://code.google.com/p/googletest/source/browse/trunk/samples/sample4_unittest.cc) is another basic example of using Google Test.
+  * [Sample #5](http://code.google.com/p/googletest/source/browse/trunk/samples/sample5_unittest.cc) teaches how to reuse a test fixture in multiple test cases by deriving sub-fixtures from it.
+  * [Sample #6](http://code.google.com/p/googletest/source/browse/trunk/samples/sample6_unittest.cc) demonstrates type-parameterized tests.
+  * [Sample #7](http://code.google.com/p/googletest/source/browse/trunk/samples/sample7_unittest.cc) teaches the basics of value-parameterized tests.
+  * [Sample #8](http://code.google.com/p/googletest/source/browse/trunk/samples/sample8_unittest.cc) shows using `Combine()` in value-parameterized tests.
+  * [Sample #9](http://code.google.com/p/googletest/source/browse/trunk/samples/sample9_unittest.cc) shows use of the listener API to modify Google Test's console output and the use of its reflection API to inspect test results.
+  * [Sample #10](http://code.google.com/p/googletest/source/browse/trunk/samples/sample10_unittest.cc) shows use of the listener API to implement a primitive memory leak checker.
\ No newline at end of file
diff --git a/third_party/googletest/googletest/docs/V1_7_XcodeGuide.md b/third_party/googletest/googletest/docs/V1_7_XcodeGuide.md
new file mode 100644
index 0000000..bf24bf5
--- /dev/null
+++ b/third_party/googletest/googletest/docs/V1_7_XcodeGuide.md
@@ -0,0 +1,93 @@
+
+
+This guide will explain how to use the Google Testing Framework in your Xcode projects on Mac OS X. This tutorial begins by quickly explaining what to do for experienced users. After the quick start, the guide goes provides additional explanation about each step.
+
+# Quick Start #
+
+Here is the quick guide for using Google Test in your Xcode project.
+
+  1. Download the source from the [website](http://code.google.com/p/googletest) using this command: `svn checkout http://googletest.googlecode.com/svn/trunk/ googletest-read-only`
+  1. Open up the `gtest.xcodeproj` in the `googletest-read-only/xcode/` directory and build the gtest.framework.
+  1. Create a new "Shell Tool" target in your Xcode project called something like "UnitTests"
+  1. Add the gtest.framework to your project and add it to the "Link Binary with Libraries" build phase of "UnitTests"
+  1. Add your unit test source code to the "Compile Sources" build phase of "UnitTests"
+  1. Edit the "UnitTests" executable and add an environment variable named "DYLD\_FRAMEWORK\_PATH" with a value equal to the path to the framework containing the gtest.framework relative to the compiled executable.
+  1. Build and Go
+
+The following sections further explain each of the steps listed above in depth, describing in more detail how to complete it including some variations.
+
+# Get the Source #
+
+Currently, the gtest.framework discussed here isn't available in a tagged release of Google Test, it is only available in the trunk. As explained at the Google Test [site](http://code.google.com/p/googletest/source/checkout">svn), you can get the code from anonymous SVN with this command:
+
+```
+svn checkout http://googletest.googlecode.com/svn/trunk/ googletest-read-only
+```
+
+Alternatively, if you are working with Subversion in your own code base, you can add Google Test as an external dependency to your own Subversion repository. By following this approach, everyone that checks out your svn repository will also receive a copy of Google Test (a specific version, if you wish) without having to check it out explicitly. This makes the set up of your project simpler and reduces the copied code in the repository.
+
+To use `svn:externals`, decide where you would like to have the external source reside. You might choose to put the external source inside the trunk, because you want it to be part of the branch when you make a release. However, keeping it outside the trunk in a version-tagged directory called something like `third-party/googletest/1.0.1`, is another option. Once the location is established, use `svn propedit svn:externals _directory_` to set the svn:externals property on a directory in your repository. This directory won't contain the code, but be its versioned parent directory.
+
+The command `svn propedit` will bring up your Subversion editor, making editing the long, (potentially multi-line) property simpler. This same method can be used to check out a tagged branch, by using the appropriate URL (e.g. `http://googletest.googlecode.com/svn/tags/release-1.0.1`). Additionally, the svn:externals property allows the specification of a particular revision of the trunk with the `-r_##_` option (e.g. `externals/src/googletest -r60 http://googletest.googlecode.com/svn/trunk`).
+
+Here is an example of using the svn:externals properties on a trunk (read via `svn propget`) of a project. This value checks out a copy of Google Test into the `trunk/externals/src/googletest/` directory.
+
+```
+[Computer:svn] user$ svn propget svn:externals trunk
+externals/src/googletest http://googletest.googlecode.com/svn/trunk
+```
+
+# Add the Framework to Your Project #
+
+The next step is to build and add the gtest.framework to your own project. This guide describes two common ways below.
+
+  * **Option 1** --- The simplest way to add Google Test to your own project, is to open gtest.xcodeproj (found in the xcode/ directory of the Google Test trunk) and build the framework manually. Then, add the built framework into your project using the "Add->Existing Framework..." from the context menu or "Project->Add..." from the main menu. The gtest.framework is relocatable and contains the headers and object code that you'll need to make tests. This method requires rebuilding every time you upgrade Google Test in your project.
+  * **Option 2** --- If you are going to be living off the trunk of Google Test, incorporating its latest features into your unit tests (or are a Google Test developer yourself). You'll want to rebuild the framework every time the source updates. to do this, you'll need to add the gtest.xcodeproj file, not the framework itself, to your own Xcode project. Then, from the build products that are revealed by the project's disclosure triangle, you can find the gtest.framework, which can be added to your targets (discussed below).
+
+# Make a Test Target #
+
+To start writing tests, make a new "Shell Tool" target. This target template is available under BSD, Cocoa, or Carbon. Add your unit test source code to the "Compile Sources" build phase of the target.
+
+Next, you'll want to add gtest.framework in two different ways, depending upon which option you chose above.
+
+  * **Option 1** --- During compilation, Xcode will need to know that you are linking against the gtest.framework. Add the gtest.framework to the "Link Binary with Libraries" build phase of your test target. This will include the Google Test headers in your header search path, and will tell the linker where to find the library.
+  * **Option 2** --- If your working out of the trunk, you'll also want to add gtest.framework to your "Link Binary with Libraries" build phase of your test target. In addition, you'll  want to add the gtest.framework as a dependency to your unit test target. This way, Xcode will make sure that gtest.framework is up to date, every time your build your target. Finally, if you don't share build directories with Google Test, you'll have to copy the gtest.framework into your own build products directory using a "Run Script" build phase.
+
+# Set Up the Executable Run Environment #
+
+Since the unit test executable is a shell tool, it doesn't have a bundle with a `Contents/Frameworks` directory, in which to place gtest.framework. Instead, the dynamic linker must be told at runtime to search for the framework in another location. This can be accomplished by setting the "DYLD\_FRAMEWORK\_PATH" environment variable in the "Edit Active Executable ..." Arguments tab, under "Variables to be set in the environment:". The path for this value is the path (relative or absolute) of the directory containing the gtest.framework.
+
+If you haven't set up the DYLD\_FRAMEWORK\_PATH, correctly, you might get a message like this:
+
+```
+[Session started at 2008-08-15 06:23:57 -0600.]
+  dyld: Library not loaded: @loader_path/../Frameworks/gtest.framework/Versions/A/gtest
+    Referenced from: /Users/username/Documents/Sandbox/gtestSample/build/Debug/WidgetFrameworkTest
+    Reason: image not found
+```
+
+To correct this problem, got to the directory containing the executable named in "Referenced from:" value in the error message above. Then, with the terminal in this location, find the relative path to the directory containing the gtest.framework. That is the value you'll need to set as the DYLD\_FRAMEWORK\_PATH.
+
+# Build and Go #
+
+Now, when you click "Build and Go", the test will be executed. Dumping out something like this:
+
+```
+[Session started at 2008-08-06 06:36:13 -0600.]
+[==========] Running 2 tests from 1 test case.
+[----------] Global test environment set-up.
+[----------] 2 tests from WidgetInitializerTest
+[ RUN      ] WidgetInitializerTest.TestConstructor
+[       OK ] WidgetInitializerTest.TestConstructor
+[ RUN      ] WidgetInitializerTest.TestConversion
+[       OK ] WidgetInitializerTest.TestConversion
+[----------] Global test environment tear-down
+[==========] 2 tests from 1 test case ran.
+[  PASSED  ] 2 tests.
+
+The Debugger has exited with status 0.  
+```
+
+# Summary #
+
+Unit testing is a valuable way to ensure your data model stays valid even during rapid development or refactoring. The Google Testing Framework is a great unit testing framework for C and C++ which integrates well with an Xcode development environment.
\ No newline at end of file
diff --git a/third_party/googletest/googletest/docs/XcodeGuide.md b/third_party/googletest/googletest/docs/XcodeGuide.md
new file mode 100644
index 0000000..bf24bf5
--- /dev/null
+++ b/third_party/googletest/googletest/docs/XcodeGuide.md
@@ -0,0 +1,93 @@
+
+
+This guide will explain how to use the Google Testing Framework in your Xcode projects on Mac OS X. This tutorial begins by quickly explaining what to do for experienced users. After the quick start, the guide goes provides additional explanation about each step.
+
+# Quick Start #
+
+Here is the quick guide for using Google Test in your Xcode project.
+
+  1. Download the source from the [website](http://code.google.com/p/googletest) using this command: `svn checkout http://googletest.googlecode.com/svn/trunk/ googletest-read-only`
+  1. Open up the `gtest.xcodeproj` in the `googletest-read-only/xcode/` directory and build the gtest.framework.
+  1. Create a new "Shell Tool" target in your Xcode project called something like "UnitTests"
+  1. Add the gtest.framework to your project and add it to the "Link Binary with Libraries" build phase of "UnitTests"
+  1. Add your unit test source code to the "Compile Sources" build phase of "UnitTests"
+  1. Edit the "UnitTests" executable and add an environment variable named "DYLD\_FRAMEWORK\_PATH" with a value equal to the path to the framework containing the gtest.framework relative to the compiled executable.
+  1. Build and Go
+
+The following sections further explain each of the steps listed above in depth, describing in more detail how to complete it including some variations.
+
+# Get the Source #
+
+Currently, the gtest.framework discussed here isn't available in a tagged release of Google Test, it is only available in the trunk. As explained at the Google Test [site](http://code.google.com/p/googletest/source/checkout">svn), you can get the code from anonymous SVN with this command:
+
+```
+svn checkout http://googletest.googlecode.com/svn/trunk/ googletest-read-only
+```
+
+Alternatively, if you are working with Subversion in your own code base, you can add Google Test as an external dependency to your own Subversion repository. By following this approach, everyone that checks out your svn repository will also receive a copy of Google Test (a specific version, if you wish) without having to check it out explicitly. This makes the set up of your project simpler and reduces the copied code in the repository.
+
+To use `svn:externals`, decide where you would like to have the external source reside. You might choose to put the external source inside the trunk, because you want it to be part of the branch when you make a release. However, keeping it outside the trunk in a version-tagged directory called something like `third-party/googletest/1.0.1`, is another option. Once the location is established, use `svn propedit svn:externals _directory_` to set the svn:externals property on a directory in your repository. This directory won't contain the code, but be its versioned parent directory.
+
+The command `svn propedit` will bring up your Subversion editor, making editing the long, (potentially multi-line) property simpler. This same method can be used to check out a tagged branch, by using the appropriate URL (e.g. `http://googletest.googlecode.com/svn/tags/release-1.0.1`). Additionally, the svn:externals property allows the specification of a particular revision of the trunk with the `-r_##_` option (e.g. `externals/src/googletest -r60 http://googletest.googlecode.com/svn/trunk`).
+
+Here is an example of using the svn:externals properties on a trunk (read via `svn propget`) of a project. This value checks out a copy of Google Test into the `trunk/externals/src/googletest/` directory.
+
+```
+[Computer:svn] user$ svn propget svn:externals trunk
+externals/src/googletest http://googletest.googlecode.com/svn/trunk
+```
+
+# Add the Framework to Your Project #
+
+The next step is to build and add the gtest.framework to your own project. This guide describes two common ways below.
+
+  * **Option 1** --- The simplest way to add Google Test to your own project, is to open gtest.xcodeproj (found in the xcode/ directory of the Google Test trunk) and build the framework manually. Then, add the built framework into your project using the "Add->Existing Framework..." from the context menu or "Project->Add..." from the main menu. The gtest.framework is relocatable and contains the headers and object code that you'll need to make tests. This method requires rebuilding every time you upgrade Google Test in your project.
+  * **Option 2** --- If you are going to be living off the trunk of Google Test, incorporating its latest features into your unit tests (or are a Google Test developer yourself). You'll want to rebuild the framework every time the source updates. to do this, you'll need to add the gtest.xcodeproj file, not the framework itself, to your own Xcode project. Then, from the build products that are revealed by the project's disclosure triangle, you can find the gtest.framework, which can be added to your targets (discussed below).
+
+# Make a Test Target #
+
+To start writing tests, make a new "Shell Tool" target. This target template is available under BSD, Cocoa, or Carbon. Add your unit test source code to the "Compile Sources" build phase of the target.
+
+Next, you'll want to add gtest.framework in two different ways, depending upon which option you chose above.
+
+  * **Option 1** --- During compilation, Xcode will need to know that you are linking against the gtest.framework. Add the gtest.framework to the "Link Binary with Libraries" build phase of your test target. This will include the Google Test headers in your header search path, and will tell the linker where to find the library.
+  * **Option 2** --- If your working out of the trunk, you'll also want to add gtest.framework to your "Link Binary with Libraries" build phase of your test target. In addition, you'll  want to add the gtest.framework as a dependency to your unit test target. This way, Xcode will make sure that gtest.framework is up to date, every time your build your target. Finally, if you don't share build directories with Google Test, you'll have to copy the gtest.framework into your own build products directory using a "Run Script" build phase.
+
+# Set Up the Executable Run Environment #
+
+Since the unit test executable is a shell tool, it doesn't have a bundle with a `Contents/Frameworks` directory, in which to place gtest.framework. Instead, the dynamic linker must be told at runtime to search for the framework in another location. This can be accomplished by setting the "DYLD\_FRAMEWORK\_PATH" environment variable in the "Edit Active Executable ..." Arguments tab, under "Variables to be set in the environment:". The path for this value is the path (relative or absolute) of the directory containing the gtest.framework.
+
+If you haven't set up the DYLD\_FRAMEWORK\_PATH, correctly, you might get a message like this:
+
+```
+[Session started at 2008-08-15 06:23:57 -0600.]
+  dyld: Library not loaded: @loader_path/../Frameworks/gtest.framework/Versions/A/gtest
+    Referenced from: /Users/username/Documents/Sandbox/gtestSample/build/Debug/WidgetFrameworkTest
+    Reason: image not found
+```
+
+To correct this problem, got to the directory containing the executable named in "Referenced from:" value in the error message above. Then, with the terminal in this location, find the relative path to the directory containing the gtest.framework. That is the value you'll need to set as the DYLD\_FRAMEWORK\_PATH.
+
+# Build and Go #
+
+Now, when you click "Build and Go", the test will be executed. Dumping out something like this:
+
+```
+[Session started at 2008-08-06 06:36:13 -0600.]
+[==========] Running 2 tests from 1 test case.
+[----------] Global test environment set-up.
+[----------] 2 tests from WidgetInitializerTest
+[ RUN      ] WidgetInitializerTest.TestConstructor
+[       OK ] WidgetInitializerTest.TestConstructor
+[ RUN      ] WidgetInitializerTest.TestConversion
+[       OK ] WidgetInitializerTest.TestConversion
+[----------] Global test environment tear-down
+[==========] 2 tests from 1 test case ran.
+[  PASSED  ] 2 tests.
+
+The Debugger has exited with status 0.  
+```
+
+# Summary #
+
+Unit testing is a valuable way to ensure your data model stays valid even during rapid development or refactoring. The Google Testing Framework is a great unit testing framework for C and C++ which integrates well with an Xcode development environment.
\ No newline at end of file
diff --git a/third_party/googletest/googletest/include/gtest/gtest-death-test.h b/third_party/googletest/googletest/include/gtest/gtest-death-test.h
new file mode 100644
index 0000000..957a69c
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/gtest-death-test.h
@@ -0,0 +1,294 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines the public API for death tests.  It is
+// #included by gtest.h so a user doesn't need to include this
+// directly.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
+
+#include "gtest/internal/gtest-death-test-internal.h"
+
+namespace testing {
+
+// This flag controls the style of death tests.  Valid values are "threadsafe",
+// meaning that the death test child process will re-execute the test binary
+// from the start, running only a single death test, or "fast",
+// meaning that the child process will execute the test logic immediately
+// after forking.
+GTEST_DECLARE_string_(death_test_style);
+
+#if GTEST_HAS_DEATH_TEST
+
+namespace internal {
+
+// Returns a Boolean value indicating whether the caller is currently
+// executing in the context of the death test child process.  Tools such as
+// Valgrind heap checkers may need this to modify their behavior in death
+// tests.  IMPORTANT: This is an internal utility.  Using it may break the
+// implementation of death tests.  User code MUST NOT use it.
+GTEST_API_ bool InDeathTestChild();
+
+}  // namespace internal
+
+// The following macros are useful for writing death tests.
+
+// Here's what happens when an ASSERT_DEATH* or EXPECT_DEATH* is
+// executed:
+//
+//   1. It generates a warning if there is more than one active
+//   thread.  This is because it's safe to fork() or clone() only
+//   when there is a single thread.
+//
+//   2. The parent process clone()s a sub-process and runs the death
+//   test in it; the sub-process exits with code 0 at the end of the
+//   death test, if it hasn't exited already.
+//
+//   3. The parent process waits for the sub-process to terminate.
+//
+//   4. The parent process checks the exit code and error message of
+//   the sub-process.
+//
+// Examples:
+//
+//   ASSERT_DEATH(server.SendMessage(56, "Hello"), "Invalid port number");
+//   for (int i = 0; i < 5; i++) {
+//     EXPECT_DEATH(server.ProcessRequest(i),
+//                  "Invalid request .* in ProcessRequest()")
+//                  << "Failed to die on request " << i;
+//   }
+//
+//   ASSERT_EXIT(server.ExitNow(), ::testing::ExitedWithCode(0), "Exiting");
+//
+//   bool KilledBySIGHUP(int exit_code) {
+//     return WIFSIGNALED(exit_code) && WTERMSIG(exit_code) == SIGHUP;
+//   }
+//
+//   ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!");
+//
+// On the regular expressions used in death tests:
+//
+//   On POSIX-compliant systems (*nix), we use the <regex.h> library,
+//   which uses the POSIX extended regex syntax.
+//
+//   On other platforms (e.g. Windows), we only support a simple regex
+//   syntax implemented as part of Google Test.  This limited
+//   implementation should be enough most of the time when writing
+//   death tests; though it lacks many features you can find in PCRE
+//   or POSIX extended regex syntax.  For example, we don't support
+//   union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and
+//   repetition count ("x{5,7}"), among others.
+//
+//   Below is the syntax that we do support.  We chose it to be a
+//   subset of both PCRE and POSIX extended regex, so it's easy to
+//   learn wherever you come from.  In the following: 'A' denotes a
+//   literal character, period (.), or a single \\ escape sequence;
+//   'x' and 'y' denote regular expressions; 'm' and 'n' are for
+//   natural numbers.
+//
+//     c     matches any literal character c
+//     \\d   matches any decimal digit
+//     \\D   matches any character that's not a decimal digit
+//     \\f   matches \f
+//     \\n   matches \n
+//     \\r   matches \r
+//     \\s   matches any ASCII whitespace, including \n
+//     \\S   matches any character that's not a whitespace
+//     \\t   matches \t
+//     \\v   matches \v
+//     \\w   matches any letter, _, or decimal digit
+//     \\W   matches any character that \\w doesn't match
+//     \\c   matches any literal character c, which must be a punctuation
+//     .     matches any single character except \n
+//     A?    matches 0 or 1 occurrences of A
+//     A*    matches 0 or many occurrences of A
+//     A+    matches 1 or many occurrences of A
+//     ^     matches the beginning of a string (not that of each line)
+//     $     matches the end of a string (not that of each line)
+//     xy    matches x followed by y
+//
+//   If you accidentally use PCRE or POSIX extended regex features
+//   not implemented by us, you will get a run-time failure.  In that
+//   case, please try to rewrite your regular expression within the
+//   above syntax.
+//
+//   This implementation is *not* meant to be as highly tuned or robust
+//   as a compiled regex library, but should perform well enough for a
+//   death test, which already incurs significant overhead by launching
+//   a child process.
+//
+// Known caveats:
+//
+//   A "threadsafe" style death test obtains the path to the test
+//   program from argv[0] and re-executes it in the sub-process.  For
+//   simplicity, the current implementation doesn't search the PATH
+//   when launching the sub-process.  This means that the user must
+//   invoke the test program via a path that contains at least one
+//   path separator (e.g. path/to/foo_test and
+//   /absolute/path/to/bar_test are fine, but foo_test is not).  This
+//   is rarely a problem as people usually don't put the test binary
+//   directory in PATH.
+//
+// TODO(wan@google.com): make thread-safe death tests search the PATH.
+
+// Asserts that a given statement causes the program to exit, with an
+// integer exit status that satisfies predicate, and emitting error output
+// that matches regex.
+# define ASSERT_EXIT(statement, predicate, regex) \
+    GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_)
+
+// Like ASSERT_EXIT, but continues on to successive tests in the
+// test case, if any:
+# define EXPECT_EXIT(statement, predicate, regex) \
+    GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_)
+
+// Asserts that a given statement causes the program to exit, either by
+// explicitly exiting with a nonzero exit code or being killed by a
+// signal, and emitting error output that matches regex.
+# define ASSERT_DEATH(statement, regex) \
+    ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
+
+// Like ASSERT_DEATH, but continues on to successive tests in the
+// test case, if any:
+# define EXPECT_DEATH(statement, regex) \
+    EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
+
+// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*:
+
+// Tests that an exit code describes a normal exit with a given exit code.
+class GTEST_API_ ExitedWithCode {
+ public:
+  explicit ExitedWithCode(int exit_code);
+  bool operator()(int exit_status) const;
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ExitedWithCode& other);
+
+  const int exit_code_;
+};
+
+# if !GTEST_OS_WINDOWS
+// Tests that an exit code describes an exit due to termination by a
+// given signal.
+class GTEST_API_ KilledBySignal {
+ public:
+  explicit KilledBySignal(int signum);
+  bool operator()(int exit_status) const;
+ private:
+  const int signum_;
+};
+# endif  // !GTEST_OS_WINDOWS
+
+// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode.
+// The death testing framework causes this to have interesting semantics,
+// since the sideeffects of the call are only visible in opt mode, and not
+// in debug mode.
+//
+// In practice, this can be used to test functions that utilize the
+// LOG(DFATAL) macro using the following style:
+//
+// int DieInDebugOr12(int* sideeffect) {
+//   if (sideeffect) {
+//     *sideeffect = 12;
+//   }
+//   LOG(DFATAL) << "death";
+//   return 12;
+// }
+//
+// TEST(TestCase, TestDieOr12WorksInDgbAndOpt) {
+//   int sideeffect = 0;
+//   // Only asserts in dbg.
+//   EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death");
+//
+// #ifdef NDEBUG
+//   // opt-mode has sideeffect visible.
+//   EXPECT_EQ(12, sideeffect);
+// #else
+//   // dbg-mode no visible sideeffect.
+//   EXPECT_EQ(0, sideeffect);
+// #endif
+// }
+//
+// This will assert that DieInDebugReturn12InOpt() crashes in debug
+// mode, usually due to a DCHECK or LOG(DFATAL), but returns the
+// appropriate fallback value (12 in this case) in opt mode. If you
+// need to test that a function has appropriate side-effects in opt
+// mode, include assertions against the side-effects.  A general
+// pattern for this is:
+//
+// EXPECT_DEBUG_DEATH({
+//   // Side-effects here will have an effect after this statement in
+//   // opt mode, but none in debug mode.
+//   EXPECT_EQ(12, DieInDebugOr12(&sideeffect));
+// }, "death");
+//
+# ifdef NDEBUG
+
+#  define EXPECT_DEBUG_DEATH(statement, regex) \
+  GTEST_EXECUTE_STATEMENT_(statement, regex)
+
+#  define ASSERT_DEBUG_DEATH(statement, regex) \
+  GTEST_EXECUTE_STATEMENT_(statement, regex)
+
+# else
+
+#  define EXPECT_DEBUG_DEATH(statement, regex) \
+  EXPECT_DEATH(statement, regex)
+
+#  define ASSERT_DEBUG_DEATH(statement, regex) \
+  ASSERT_DEATH(statement, regex)
+
+# endif  // NDEBUG for EXPECT_DEBUG_DEATH
+#endif  // GTEST_HAS_DEATH_TEST
+
+// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and
+// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if
+// death tests are supported; otherwise they just issue a warning.  This is
+// useful when you are combining death test assertions with normal test
+// assertions in one test.
+#if GTEST_HAS_DEATH_TEST
+# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
+    EXPECT_DEATH(statement, regex)
+# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
+    ASSERT_DEATH(statement, regex)
+#else
+# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
+    GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, )
+# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
+    GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, return)
+#endif
+
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
diff --git a/third_party/googletest/googletest/include/gtest/gtest-message.h b/third_party/googletest/googletest/include/gtest/gtest-message.h
new file mode 100644
index 0000000..fe879bc
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/gtest-message.h
@@ -0,0 +1,250 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines the Message class.
+//
+// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
+// leave some internal implementation details in this header file.
+// They are clearly marked by comments like this:
+//
+//   // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+//
+// Such code is NOT meant to be used by a user directly, and is subject
+// to CHANGE WITHOUT NOTICE.  Therefore DO NOT DEPEND ON IT in a user
+// program!
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
+#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
+
+#include <limits>
+
+#include "gtest/internal/gtest-port.h"
+
+// Ensures that there is at least one operator<< in the global namespace.
+// See Message& operator<<(...) below for why.
+void operator<<(const testing::internal::Secret&, int);
+
+namespace testing {
+
+// The Message class works like an ostream repeater.
+//
+// Typical usage:
+//
+//   1. You stream a bunch of values to a Message object.
+//      It will remember the text in a stringstream.
+//   2. Then you stream the Message object to an ostream.
+//      This causes the text in the Message to be streamed
+//      to the ostream.
+//
+// For example;
+//
+//   testing::Message foo;
+//   foo << 1 << " != " << 2;
+//   std::cout << foo;
+//
+// will print "1 != 2".
+//
+// Message is not intended to be inherited from.  In particular, its
+// destructor is not virtual.
+//
+// Note that stringstream behaves differently in gcc and in MSVC.  You
+// can stream a NULL char pointer to it in the former, but not in the
+// latter (it causes an access violation if you do).  The Message
+// class hides this difference by treating a NULL char pointer as
+// "(null)".
+class GTEST_API_ Message {
+ private:
+  // The type of basic IO manipulators (endl, ends, and flush) for
+  // narrow streams.
+  typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&);
+
+ public:
+  // Constructs an empty Message.
+  Message();
+
+  // Copy constructor.
+  Message(const Message& msg) : ss_(new ::std::stringstream) {  // NOLINT
+    *ss_ << msg.GetString();
+  }
+
+  // Constructs a Message from a C-string.
+  explicit Message(const char* str) : ss_(new ::std::stringstream) {
+    *ss_ << str;
+  }
+
+#if GTEST_OS_SYMBIAN
+  // Streams a value (either a pointer or not) to this object.
+  template <typename T>
+  inline Message& operator <<(const T& value) {
+    StreamHelper(typename internal::is_pointer<T>::type(), value);
+    return *this;
+  }
+#else
+  // Streams a non-pointer value to this object.
+  template <typename T>
+  inline Message& operator <<(const T& val) {
+    // Some libraries overload << for STL containers.  These
+    // overloads are defined in the global namespace instead of ::std.
+    //
+    // C++'s symbol lookup rule (i.e. Koenig lookup) says that these
+    // overloads are visible in either the std namespace or the global
+    // namespace, but not other namespaces, including the testing
+    // namespace which Google Test's Message class is in.
+    //
+    // To allow STL containers (and other types that has a << operator
+    // defined in the global namespace) to be used in Google Test
+    // assertions, testing::Message must access the custom << operator
+    // from the global namespace.  With this using declaration,
+    // overloads of << defined in the global namespace and those
+    // visible via Koenig lookup are both exposed in this function.
+    using ::operator <<;
+    *ss_ << val;
+    return *this;
+  }
+
+  // Streams a pointer value to this object.
+  //
+  // This function is an overload of the previous one.  When you
+  // stream a pointer to a Message, this definition will be used as it
+  // is more specialized.  (The C++ Standard, section
+  // [temp.func.order].)  If you stream a non-pointer, then the
+  // previous definition will be used.
+  //
+  // The reason for this overload is that streaming a NULL pointer to
+  // ostream is undefined behavior.  Depending on the compiler, you
+  // may get "0", "(nil)", "(null)", or an access violation.  To
+  // ensure consistent result across compilers, we always treat NULL
+  // as "(null)".
+  template <typename T>
+  inline Message& operator <<(T* const& pointer) {  // NOLINT
+    if (pointer == NULL) {
+      *ss_ << "(null)";
+    } else {
+      *ss_ << pointer;
+    }
+    return *this;
+  }
+#endif  // GTEST_OS_SYMBIAN
+
+  // Since the basic IO manipulators are overloaded for both narrow
+  // and wide streams, we have to provide this specialized definition
+  // of operator <<, even though its body is the same as the
+  // templatized version above.  Without this definition, streaming
+  // endl or other basic IO manipulators to Message will confuse the
+  // compiler.
+  Message& operator <<(BasicNarrowIoManip val) {
+    *ss_ << val;
+    return *this;
+  }
+
+  // Instead of 1/0, we want to see true/false for bool values.
+  Message& operator <<(bool b) {
+    return *this << (b ? "true" : "false");
+  }
+
+  // These two overloads allow streaming a wide C string to a Message
+  // using the UTF-8 encoding.
+  Message& operator <<(const wchar_t* wide_c_str);
+  Message& operator <<(wchar_t* wide_c_str);
+
+#if GTEST_HAS_STD_WSTRING
+  // Converts the given wide string to a narrow string using the UTF-8
+  // encoding, and streams the result to this Message object.
+  Message& operator <<(const ::std::wstring& wstr);
+#endif  // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+  // Converts the given wide string to a narrow string using the UTF-8
+  // encoding, and streams the result to this Message object.
+  Message& operator <<(const ::wstring& wstr);
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+  // Gets the text streamed to this object so far as an std::string.
+  // Each '\0' character in the buffer is replaced with "\\0".
+  //
+  // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+  std::string GetString() const;
+
+ private:
+
+#if GTEST_OS_SYMBIAN
+  // These are needed as the Nokia Symbian Compiler cannot decide between
+  // const T& and const T* in a function template. The Nokia compiler _can_
+  // decide between class template specializations for T and T*, so a
+  // tr1::type_traits-like is_pointer works, and we can overload on that.
+  template <typename T>
+  inline void StreamHelper(internal::true_type /*is_pointer*/, T* pointer) {
+    if (pointer == NULL) {
+      *ss_ << "(null)";
+    } else {
+      *ss_ << pointer;
+    }
+  }
+  template <typename T>
+  inline void StreamHelper(internal::false_type /*is_pointer*/,
+                           const T& value) {
+    // See the comments in Message& operator <<(const T&) above for why
+    // we need this using statement.
+    using ::operator <<;
+    *ss_ << value;
+  }
+#endif  // GTEST_OS_SYMBIAN
+
+  // We'll hold the text streamed to this object here.
+  const internal::scoped_ptr< ::std::stringstream> ss_;
+
+  // We declare (but don't implement) this to prevent the compiler
+  // from implementing the assignment operator.
+  void operator=(const Message&);
+};
+
+// Streams a Message to an ostream.
+inline std::ostream& operator <<(std::ostream& os, const Message& sb) {
+  return os << sb.GetString();
+}
+
+namespace internal {
+
+// Converts a streamable value to an std::string.  A NULL pointer is
+// converted to "(null)".  When the input value is a ::string,
+// ::std::string, ::wstring, or ::std::wstring object, each NUL
+// character in it is replaced with "\\0".
+template <typename T>
+std::string StreamableToString(const T& streamable) {
+  return (Message() << streamable).GetString();
+}
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
diff --git a/third_party/googletest/googletest/include/gtest/gtest-param-test.h b/third_party/googletest/googletest/include/gtest/gtest-param-test.h
new file mode 100644
index 0000000..038f9ba
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/gtest-param-test.h
@@ -0,0 +1,1444 @@
+// This file was GENERATED by command:
+//     pump.py gtest-param-test.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: vladl@google.com (Vlad Losev)
+//
+// Macros and functions for implementing parameterized tests
+// in Google C++ Testing Framework (Google Test)
+//
+// This file is generated by a SCRIPT.  DO NOT EDIT BY HAND!
+//
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+
+
+// Value-parameterized tests allow you to test your code with different
+// parameters without writing multiple copies of the same test.
+//
+// Here is how you use value-parameterized tests:
+
+#if 0
+
+// To write value-parameterized tests, first you should define a fixture
+// class. It is usually derived from testing::TestWithParam<T> (see below for
+// another inheritance scheme that's sometimes useful in more complicated
+// class hierarchies), where the type of your parameter values.
+// TestWithParam<T> is itself derived from testing::Test. T can be any
+// copyable type. If it's a raw pointer, you are responsible for managing the
+// lifespan of the pointed values.
+
+class FooTest : public ::testing::TestWithParam<const char*> {
+  // You can implement all the usual class fixture members here.
+};
+
+// Then, use the TEST_P macro to define as many parameterized tests
+// for this fixture as you want. The _P suffix is for "parameterized"
+// or "pattern", whichever you prefer to think.
+
+TEST_P(FooTest, DoesBlah) {
+  // Inside a test, access the test parameter with the GetParam() method
+  // of the TestWithParam<T> class:
+  EXPECT_TRUE(foo.Blah(GetParam()));
+  ...
+}
+
+TEST_P(FooTest, HasBlahBlah) {
+  ...
+}
+
+// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test
+// case with any set of parameters you want. Google Test defines a number
+// of functions for generating test parameters. They return what we call
+// (surprise!) parameter generators. Here is a  summary of them, which
+// are all in the testing namespace:
+//
+//
+//  Range(begin, end [, step]) - Yields values {begin, begin+step,
+//                               begin+step+step, ...}. The values do not
+//                               include end. step defaults to 1.
+//  Values(v1, v2, ..., vN)    - Yields values {v1, v2, ..., vN}.
+//  ValuesIn(container)        - Yields values from a C-style array, an STL
+//  ValuesIn(begin,end)          container, or an iterator range [begin, end).
+//  Bool()                     - Yields sequence {false, true}.
+//  Combine(g1, g2, ..., gN)   - Yields all combinations (the Cartesian product
+//                               for the math savvy) of the values generated
+//                               by the N generators.
+//
+// For more details, see comments at the definitions of these functions below
+// in this file.
+//
+// The following statement will instantiate tests from the FooTest test case
+// each with parameter values "meeny", "miny", and "moe".
+
+INSTANTIATE_TEST_CASE_P(InstantiationName,
+                        FooTest,
+                        Values("meeny", "miny", "moe"));
+
+// To distinguish different instances of the pattern, (yes, you
+// can instantiate it more then once) the first argument to the
+// INSTANTIATE_TEST_CASE_P macro is a prefix that will be added to the
+// actual test case name. Remember to pick unique prefixes for different
+// instantiations. The tests from the instantiation above will have
+// these names:
+//
+//    * InstantiationName/FooTest.DoesBlah/0 for "meeny"
+//    * InstantiationName/FooTest.DoesBlah/1 for "miny"
+//    * InstantiationName/FooTest.DoesBlah/2 for "moe"
+//    * InstantiationName/FooTest.HasBlahBlah/0 for "meeny"
+//    * InstantiationName/FooTest.HasBlahBlah/1 for "miny"
+//    * InstantiationName/FooTest.HasBlahBlah/2 for "moe"
+//
+// You can use these names in --gtest_filter.
+//
+// This statement will instantiate all tests from FooTest again, each
+// with parameter values "cat" and "dog":
+
+const char* pets[] = {"cat", "dog"};
+INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets));
+
+// The tests from the instantiation above will have these names:
+//
+//    * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat"
+//    * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog"
+//    * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat"
+//    * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog"
+//
+// Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests
+// in the given test case, whether their definitions come before or
+// AFTER the INSTANTIATE_TEST_CASE_P statement.
+//
+// Please also note that generator expressions (including parameters to the
+// generators) are evaluated in InitGoogleTest(), after main() has started.
+// This allows the user on one hand, to adjust generator parameters in order
+// to dynamically determine a set of tests to run and on the other hand,
+// give the user a chance to inspect the generated tests with Google Test
+// reflection API before RUN_ALL_TESTS() is executed.
+//
+// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc
+// for more examples.
+//
+// In the future, we plan to publish the API for defining new parameter
+// generators. But for now this interface remains part of the internal
+// implementation and is subject to change.
+//
+//
+// A parameterized test fixture must be derived from testing::Test and from
+// testing::WithParamInterface<T>, where T is the type of the parameter
+// values. Inheriting from TestWithParam<T> satisfies that requirement because
+// TestWithParam<T> inherits from both Test and WithParamInterface. In more
+// complicated hierarchies, however, it is occasionally useful to inherit
+// separately from Test and WithParamInterface. For example:
+
+class BaseTest : public ::testing::Test {
+  // You can inherit all the usual members for a non-parameterized test
+  // fixture here.
+};
+
+class DerivedTest : public BaseTest, public ::testing::WithParamInterface<int> {
+  // The usual test fixture members go here too.
+};
+
+TEST_F(BaseTest, HasFoo) {
+  // This is an ordinary non-parameterized test.
+}
+
+TEST_P(DerivedTest, DoesBlah) {
+  // GetParam works just the same here as if you inherit from TestWithParam.
+  EXPECT_TRUE(foo.Blah(GetParam()));
+}
+
+#endif  // 0
+
+#include "gtest/internal/gtest-port.h"
+
+#if !GTEST_OS_SYMBIAN
+# include <utility>
+#endif
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*.  Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-param-util.h"
+#include "gtest/internal/gtest-param-util-generated.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+
+// Functions producing parameter generators.
+//
+// Google Test uses these generators to produce parameters for value-
+// parameterized tests. When a parameterized test case is instantiated
+// with a particular generator, Google Test creates and runs tests
+// for each element in the sequence produced by the generator.
+//
+// In the following sample, tests from test case FooTest are instantiated
+// each three times with parameter values 3, 5, and 8:
+//
+// class FooTest : public TestWithParam<int> { ... };
+//
+// TEST_P(FooTest, TestThis) {
+// }
+// TEST_P(FooTest, TestThat) {
+// }
+// INSTANTIATE_TEST_CASE_P(TestSequence, FooTest, Values(3, 5, 8));
+//
+
+// Range() returns generators providing sequences of values in a range.
+//
+// Synopsis:
+// Range(start, end)
+//   - returns a generator producing a sequence of values {start, start+1,
+//     start+2, ..., }.
+// Range(start, end, step)
+//   - returns a generator producing a sequence of values {start, start+step,
+//     start+step+step, ..., }.
+// Notes:
+//   * The generated sequences never include end. For example, Range(1, 5)
+//     returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2)
+//     returns a generator producing {1, 3, 5, 7}.
+//   * start and end must have the same type. That type may be any integral or
+//     floating-point type or a user defined type satisfying these conditions:
+//     * It must be assignable (have operator=() defined).
+//     * It must have operator+() (operator+(int-compatible type) for
+//       two-operand version).
+//     * It must have operator<() defined.
+//     Elements in the resulting sequences will also have that type.
+//   * Condition start < end must be satisfied in order for resulting sequences
+//     to contain any elements.
+//
+template <typename T, typename IncrementT>
+internal::ParamGenerator<T> Range(T start, T end, IncrementT step) {
+  return internal::ParamGenerator<T>(
+      new internal::RangeGenerator<T, IncrementT>(start, end, step));
+}
+
+template <typename T>
+internal::ParamGenerator<T> Range(T start, T end) {
+  return Range(start, end, 1);
+}
+
+// ValuesIn() function allows generation of tests with parameters coming from
+// a container.
+//
+// Synopsis:
+// ValuesIn(const T (&array)[N])
+//   - returns a generator producing sequences with elements from
+//     a C-style array.
+// ValuesIn(const Container& container)
+//   - returns a generator producing sequences with elements from
+//     an STL-style container.
+// ValuesIn(Iterator begin, Iterator end)
+//   - returns a generator producing sequences with elements from
+//     a range [begin, end) defined by a pair of STL-style iterators. These
+//     iterators can also be plain C pointers.
+//
+// Please note that ValuesIn copies the values from the containers
+// passed in and keeps them to generate tests in RUN_ALL_TESTS().
+//
+// Examples:
+//
+// This instantiates tests from test case StringTest
+// each with C-string values of "foo", "bar", and "baz":
+//
+// const char* strings[] = {"foo", "bar", "baz"};
+// INSTANTIATE_TEST_CASE_P(StringSequence, SrtingTest, ValuesIn(strings));
+//
+// This instantiates tests from test case StlStringTest
+// each with STL strings with values "a" and "b":
+//
+// ::std::vector< ::std::string> GetParameterStrings() {
+//   ::std::vector< ::std::string> v;
+//   v.push_back("a");
+//   v.push_back("b");
+//   return v;
+// }
+//
+// INSTANTIATE_TEST_CASE_P(CharSequence,
+//                         StlStringTest,
+//                         ValuesIn(GetParameterStrings()));
+//
+//
+// This will also instantiate tests from CharTest
+// each with parameter values 'a' and 'b':
+//
+// ::std::list<char> GetParameterChars() {
+//   ::std::list<char> list;
+//   list.push_back('a');
+//   list.push_back('b');
+//   return list;
+// }
+// ::std::list<char> l = GetParameterChars();
+// INSTANTIATE_TEST_CASE_P(CharSequence2,
+//                         CharTest,
+//                         ValuesIn(l.begin(), l.end()));
+//
+template <typename ForwardIterator>
+internal::ParamGenerator<
+  typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end) {
+  typedef typename ::testing::internal::IteratorTraits<ForwardIterator>
+      ::value_type ParamType;
+  return internal::ParamGenerator<ParamType>(
+      new internal::ValuesInIteratorRangeGenerator<ParamType>(begin, end));
+}
+
+template <typename T, size_t N>
+internal::ParamGenerator<T> ValuesIn(const T (&array)[N]) {
+  return ValuesIn(array, array + N);
+}
+
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+    const Container& container) {
+  return ValuesIn(container.begin(), container.end());
+}
+
+// Values() allows generating tests from explicitly specified list of
+// parameters.
+//
+// Synopsis:
+// Values(T v1, T v2, ..., T vN)
+//   - returns a generator producing sequences with elements v1, v2, ..., vN.
+//
+// For example, this instantiates tests from test case BarTest each
+// with values "one", "two", and "three":
+//
+// INSTANTIATE_TEST_CASE_P(NumSequence, BarTest, Values("one", "two", "three"));
+//
+// This instantiates tests from test case BazTest each with values 1, 2, 3.5.
+// The exact type of values will depend on the type of parameter in BazTest.
+//
+// INSTANTIATE_TEST_CASE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5));
+//
+// Currently, Values() supports from 1 to 50 parameters.
+//
+template <typename T1>
+internal::ValueArray1<T1> Values(T1 v1) {
+  return internal::ValueArray1<T1>(v1);
+}
+
+template <typename T1, typename T2>
+internal::ValueArray2<T1, T2> Values(T1 v1, T2 v2) {
+  return internal::ValueArray2<T1, T2>(v1, v2);
+}
+
+template <typename T1, typename T2, typename T3>
+internal::ValueArray3<T1, T2, T3> Values(T1 v1, T2 v2, T3 v3) {
+  return internal::ValueArray3<T1, T2, T3>(v1, v2, v3);
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+internal::ValueArray4<T1, T2, T3, T4> Values(T1 v1, T2 v2, T3 v3, T4 v4) {
+  return internal::ValueArray4<T1, T2, T3, T4>(v1, v2, v3, v4);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+internal::ValueArray5<T1, T2, T3, T4, T5> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5) {
+  return internal::ValueArray5<T1, T2, T3, T4, T5>(v1, v2, v3, v4, v5);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+internal::ValueArray6<T1, T2, T3, T4, T5, T6> Values(T1 v1, T2 v2, T3 v3,
+    T4 v4, T5 v5, T6 v6) {
+  return internal::ValueArray6<T1, T2, T3, T4, T5, T6>(v1, v2, v3, v4, v5, v6);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+internal::ValueArray7<T1, T2, T3, T4, T5, T6, T7> Values(T1 v1, T2 v2, T3 v3,
+    T4 v4, T5 v5, T6 v6, T7 v7) {
+  return internal::ValueArray7<T1, T2, T3, T4, T5, T6, T7>(v1, v2, v3, v4, v5,
+      v6, v7);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+internal::ValueArray8<T1, T2, T3, T4, T5, T6, T7, T8> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8) {
+  return internal::ValueArray8<T1, T2, T3, T4, T5, T6, T7, T8>(v1, v2, v3, v4,
+      v5, v6, v7, v8);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+internal::ValueArray9<T1, T2, T3, T4, T5, T6, T7, T8, T9> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9) {
+  return internal::ValueArray9<T1, T2, T3, T4, T5, T6, T7, T8, T9>(v1, v2, v3,
+      v4, v5, v6, v7, v8, v9);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+internal::ValueArray10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> Values(T1 v1,
+    T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10) {
+  return internal::ValueArray10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(v1,
+      v2, v3, v4, v5, v6, v7, v8, v9, v10);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11>
+internal::ValueArray11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10,
+    T11> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11) {
+  return internal::ValueArray11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10,
+      T11>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12>
+internal::ValueArray12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+    T12> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12) {
+  return internal::ValueArray12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13>
+internal::ValueArray13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+    T13> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13) {
+  return internal::ValueArray13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14>
+internal::ValueArray14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) {
+  return internal::ValueArray14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13,
+      v14);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15>
+internal::ValueArray15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+    T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) {
+  return internal::ValueArray15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
+      v13, v14, v15);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16>
+internal::ValueArray16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16) {
+  return internal::ValueArray16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11,
+      v12, v13, v14, v15, v16);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17>
+internal::ValueArray17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17) {
+  return internal::ValueArray17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
+      v11, v12, v13, v14, v15, v16, v17);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18>
+internal::ValueArray18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6,
+    T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18) {
+  return internal::ValueArray18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18>(v1, v2, v3, v4, v5, v6, v7, v8, v9,
+      v10, v11, v12, v13, v14, v15, v16, v17, v18);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19>
+internal::ValueArray19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5,
+    T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14,
+    T15 v15, T16 v16, T17 v17, T18 v18, T19 v19) {
+  return internal::ValueArray19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19>(v1, v2, v3, v4, v5, v6, v7, v8,
+      v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20>
+internal::ValueArray20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20) {
+  return internal::ValueArray20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20>(v1, v2, v3, v4, v5, v6, v7,
+      v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21>
+internal::ValueArray21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21) {
+  return internal::ValueArray21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21>(v1, v2, v3, v4, v5, v6,
+      v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22>
+internal::ValueArray22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22> Values(T1 v1, T2 v2, T3 v3,
+    T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22) {
+  return internal::ValueArray22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22>(v1, v2, v3, v4,
+      v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23>
+internal::ValueArray23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23) {
+  return internal::ValueArray23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23>(v1, v2, v3,
+      v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22, v23);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24>
+internal::ValueArray24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23, T24 v24) {
+  return internal::ValueArray24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24>(v1, v2,
+      v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18,
+      v19, v20, v21, v22, v23, v24);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25>
+internal::ValueArray25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> Values(T1 v1,
+    T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11,
+    T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19,
+    T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25) {
+  return internal::ValueArray25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25>(v1,
+      v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17,
+      v18, v19, v20, v21, v22, v23, v24, v25);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26>
+internal::ValueArray26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+    T26> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26) {
+  return internal::ValueArray26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15,
+      v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27>
+internal::ValueArray27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+    T27> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27) {
+  return internal::ValueArray27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14,
+      v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28>
+internal::ValueArray28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+    T28> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28) {
+  return internal::ValueArray28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13,
+      v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27,
+      v28);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29>
+internal::ValueArray29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29) {
+  return internal::ValueArray29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
+      v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26,
+      v27, v28, v29);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30>
+internal::ValueArray30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+    T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16,
+    T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24,
+    T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) {
+  return internal::ValueArray30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11,
+      v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25,
+      v26, v27, v28, v29, v30);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31>
+internal::ValueArray31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) {
+  return internal::ValueArray31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
+      v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24,
+      v25, v26, v27, v28, v29, v30, v31);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32>
+internal::ValueArray32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32) {
+  return internal::ValueArray32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32>(v1, v2, v3, v4, v5, v6, v7, v8, v9,
+      v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+      v24, v25, v26, v27, v28, v29, v30, v31, v32);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33>
+internal::ValueArray33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6,
+    T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32, T33 v33) {
+  return internal::ValueArray33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33>(v1, v2, v3, v4, v5, v6, v7, v8,
+      v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+      v24, v25, v26, v27, v28, v29, v30, v31, v32, v33);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34>
+internal::ValueArray34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5,
+    T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14,
+    T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22,
+    T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30,
+    T31 v31, T32 v32, T33 v33, T34 v34) {
+  return internal::ValueArray34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34>(v1, v2, v3, v4, v5, v6, v7,
+      v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22,
+      v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35>
+internal::ValueArray35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21,
+    T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29,
+    T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35) {
+  return internal::ValueArray35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35>(v1, v2, v3, v4, v5, v6,
+      v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21,
+      v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36>
+internal::ValueArray36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21,
+    T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29,
+    T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36) {
+  return internal::ValueArray36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36>(v1, v2, v3, v4,
+      v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33,
+      v34, v35, v36);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37>
+internal::ValueArray37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37> Values(T1 v1, T2 v2, T3 v3,
+    T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28,
+    T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36,
+    T37 v37) {
+  return internal::ValueArray37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37>(v1, v2, v3,
+      v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33,
+      v34, v35, v36, v37);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38>
+internal::ValueArray38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28,
+    T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36,
+    T37 v37, T38 v38) {
+  return internal::ValueArray38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38>(v1, v2,
+      v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18,
+      v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32,
+      v33, v34, v35, v36, v37, v38);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39>
+internal::ValueArray39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28,
+    T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36,
+    T37 v37, T38 v38, T39 v39) {
+  return internal::ValueArray39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39>(v1,
+      v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17,
+      v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31,
+      v32, v33, v34, v35, v36, v37, v38, v39);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40>
+internal::ValueArray40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> Values(T1 v1,
+    T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11,
+    T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19,
+    T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27,
+    T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35,
+    T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) {
+  return internal::ValueArray40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15,
+      v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29,
+      v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41>
+internal::ValueArray41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+    T41> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+    T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41) {
+  return internal::ValueArray41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14,
+      v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28,
+      v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42>
+internal::ValueArray42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+    T42> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+    T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+    T42 v42) {
+  return internal::ValueArray42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13,
+      v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27,
+      v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41,
+      v42);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43>
+internal::ValueArray43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+    T43> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+    T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+    T42 v42, T43 v43) {
+  return internal::ValueArray43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
+      v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26,
+      v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40,
+      v41, v42, v43);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44>
+internal::ValueArray44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+    T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+    T42 v42, T43 v43, T44 v44) {
+  return internal::ValueArray44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11,
+      v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25,
+      v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39,
+      v40, v41, v42, v43, v44);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45>
+internal::ValueArray45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+    T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16,
+    T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24,
+    T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32,
+    T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40,
+    T41 v41, T42 v42, T43 v43, T44 v44, T45 v45) {
+  return internal::ValueArray45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
+      v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24,
+      v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38,
+      v39, v40, v41, v42, v43, v44, v45);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46>
+internal::ValueArray46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39,
+    T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) {
+  return internal::ValueArray46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46>(v1, v2, v3, v4, v5, v6, v7, v8, v9,
+      v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+      v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37,
+      v38, v39, v40, v41, v42, v43, v44, v45, v46);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47>
+internal::ValueArray47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39,
+    T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) {
+  return internal::ValueArray47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46, T47>(v1, v2, v3, v4, v5, v6, v7, v8,
+      v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+      v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37,
+      v38, v39, v40, v41, v42, v43, v44, v45, v46, v47);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48>
+internal::ValueArray48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47, T48> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6,
+    T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39,
+    T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47,
+    T48 v48) {
+  return internal::ValueArray48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46, T47, T48>(v1, v2, v3, v4, v5, v6, v7,
+      v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22,
+      v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36,
+      v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49>
+internal::ValueArray49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47, T48, T49> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5,
+    T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14,
+    T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22,
+    T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30,
+    T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38,
+    T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46,
+    T47 v47, T48 v48, T49 v49) {
+  return internal::ValueArray49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46, T47, T48, T49>(v1, v2, v3, v4, v5, v6,
+      v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21,
+      v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35,
+      v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49, typename T50>
+internal::ValueArray50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47, T48, T49, T50> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21,
+    T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29,
+    T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37,
+    T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45,
+    T46 v46, T47 v47, T48 v48, T49 v49, T50 v50) {
+  return internal::ValueArray50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46, T47, T48, T49, T50>(v1, v2, v3, v4,
+      v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33,
+      v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47,
+      v48, v49, v50);
+}
+
+// Bool() allows generating tests with parameters in a set of (false, true).
+//
+// Synopsis:
+// Bool()
+//   - returns a generator producing sequences with elements {false, true}.
+//
+// It is useful when testing code that depends on Boolean flags. Combinations
+// of multiple flags can be tested when several Bool()'s are combined using
+// Combine() function.
+//
+// In the following example all tests in the test case FlagDependentTest
+// will be instantiated twice with parameters false and true.
+//
+// class FlagDependentTest : public testing::TestWithParam<bool> {
+//   virtual void SetUp() {
+//     external_flag = GetParam();
+//   }
+// }
+// INSTANTIATE_TEST_CASE_P(BoolSequence, FlagDependentTest, Bool());
+//
+inline internal::ParamGenerator<bool> Bool() {
+  return Values(false, true);
+}
+
+# if GTEST_HAS_COMBINE
+// Combine() allows the user to combine two or more sequences to produce
+// values of a Cartesian product of those sequences' elements.
+//
+// Synopsis:
+// Combine(gen1, gen2, ..., genN)
+//   - returns a generator producing sequences with elements coming from
+//     the Cartesian product of elements from the sequences generated by
+//     gen1, gen2, ..., genN. The sequence elements will have a type of
+//     tuple<T1, T2, ..., TN> where T1, T2, ..., TN are the types
+//     of elements from sequences produces by gen1, gen2, ..., genN.
+//
+// Combine can have up to 10 arguments. This number is currently limited
+// by the maximum number of elements in the tuple implementation used by Google
+// Test.
+//
+// Example:
+//
+// This will instantiate tests in test case AnimalTest each one with
+// the parameter values tuple("cat", BLACK), tuple("cat", WHITE),
+// tuple("dog", BLACK), and tuple("dog", WHITE):
+//
+// enum Color { BLACK, GRAY, WHITE };
+// class AnimalTest
+//     : public testing::TestWithParam<tuple<const char*, Color> > {...};
+//
+// TEST_P(AnimalTest, AnimalLooksNice) {...}
+//
+// INSTANTIATE_TEST_CASE_P(AnimalVariations, AnimalTest,
+//                         Combine(Values("cat", "dog"),
+//                                 Values(BLACK, WHITE)));
+//
+// This will instantiate tests in FlagDependentTest with all variations of two
+// Boolean flags:
+//
+// class FlagDependentTest
+//     : public testing::TestWithParam<tuple<bool, bool> > {
+//   virtual void SetUp() {
+//     // Assigns external_flag_1 and external_flag_2 values from the tuple.
+//     tie(external_flag_1, external_flag_2) = GetParam();
+//   }
+// };
+//
+// TEST_P(FlagDependentTest, TestFeature1) {
+//   // Test your code using external_flag_1 and external_flag_2 here.
+// }
+// INSTANTIATE_TEST_CASE_P(TwoBoolSequence, FlagDependentTest,
+//                         Combine(Bool(), Bool()));
+//
+template <typename Generator1, typename Generator2>
+internal::CartesianProductHolder2<Generator1, Generator2> Combine(
+    const Generator1& g1, const Generator2& g2) {
+  return internal::CartesianProductHolder2<Generator1, Generator2>(
+      g1, g2);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3>
+internal::CartesianProductHolder3<Generator1, Generator2, Generator3> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3) {
+  return internal::CartesianProductHolder3<Generator1, Generator2, Generator3>(
+      g1, g2, g3);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4>
+internal::CartesianProductHolder4<Generator1, Generator2, Generator3,
+    Generator4> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4) {
+  return internal::CartesianProductHolder4<Generator1, Generator2, Generator3,
+      Generator4>(
+      g1, g2, g3, g4);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5>
+internal::CartesianProductHolder5<Generator1, Generator2, Generator3,
+    Generator4, Generator5> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5) {
+  return internal::CartesianProductHolder5<Generator1, Generator2, Generator3,
+      Generator4, Generator5>(
+      g1, g2, g3, g4, g5);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6>
+internal::CartesianProductHolder6<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6) {
+  return internal::CartesianProductHolder6<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6>(
+      g1, g2, g3, g4, g5, g6);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6,
+    typename Generator7>
+internal::CartesianProductHolder7<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6, Generator7> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6,
+        const Generator7& g7) {
+  return internal::CartesianProductHolder7<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6, Generator7>(
+      g1, g2, g3, g4, g5, g6, g7);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6,
+    typename Generator7, typename Generator8>
+internal::CartesianProductHolder8<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6, Generator7, Generator8> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6,
+        const Generator7& g7, const Generator8& g8) {
+  return internal::CartesianProductHolder8<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6, Generator7, Generator8>(
+      g1, g2, g3, g4, g5, g6, g7, g8);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6,
+    typename Generator7, typename Generator8, typename Generator9>
+internal::CartesianProductHolder9<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6, Generator7, Generator8,
+    Generator9> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6,
+        const Generator7& g7, const Generator8& g8, const Generator9& g9) {
+  return internal::CartesianProductHolder9<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6, Generator7, Generator8, Generator9>(
+      g1, g2, g3, g4, g5, g6, g7, g8, g9);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6,
+    typename Generator7, typename Generator8, typename Generator9,
+    typename Generator10>
+internal::CartesianProductHolder10<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6, Generator7, Generator8, Generator9,
+    Generator10> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6,
+        const Generator7& g7, const Generator8& g8, const Generator9& g9,
+        const Generator10& g10) {
+  return internal::CartesianProductHolder10<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6, Generator7, Generator8, Generator9,
+      Generator10>(
+      g1, g2, g3, g4, g5, g6, g7, g8, g9, g10);
+}
+# endif  // GTEST_HAS_COMBINE
+
+
+
+# define TEST_P(test_case_name, test_name) \
+  class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
+      : public test_case_name { \
+   public: \
+    GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \
+    virtual void TestBody(); \
+   private: \
+    static int AddToRegistry() { \
+      ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
+          GetTestCasePatternHolder<test_case_name>(\
+              #test_case_name, \
+              ::testing::internal::CodeLocation(\
+                  __FILE__, __LINE__))->AddTestPattern(\
+                      #test_case_name, \
+                      #test_name, \
+                      new ::testing::internal::TestMetaFactory< \
+                          GTEST_TEST_CLASS_NAME_(\
+                              test_case_name, test_name)>()); \
+      return 0; \
+    } \
+    static int gtest_registering_dummy_ GTEST_ATTRIBUTE_UNUSED_; \
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(\
+        GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \
+  }; \
+  int GTEST_TEST_CLASS_NAME_(test_case_name, \
+                             test_name)::gtest_registering_dummy_ = \
+      GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \
+  void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
+
+// The optional last argument to INSTANTIATE_TEST_CASE_P allows the user
+// to specify a function or functor that generates custom test name suffixes
+// based on the test parameters. The function should accept one argument of
+// type testing::TestParamInfo<class ParamType>, and return std::string.
+//
+// testing::PrintToStringParamName is a builtin test suffix generator that
+// returns the value of testing::PrintToString(GetParam()). It does not work
+// for std::string or C strings.
+//
+// Note: test names must be non-empty, unique, and may only contain ASCII
+// alphanumeric characters or underscore.
+
+# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator, ...) \
+  ::testing::internal::ParamGenerator<test_case_name::ParamType> \
+      gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \
+  ::std::string gtest_##prefix##test_case_name##_EvalGenerateName_( \
+      const ::testing::TestParamInfo<test_case_name::ParamType>& info) { \
+    return ::testing::internal::GetParamNameGen<test_case_name::ParamType> \
+        (__VA_ARGS__)(info); \
+  } \
+  int gtest_##prefix##test_case_name##_dummy_ GTEST_ATTRIBUTE_UNUSED_ = \
+      ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
+          GetTestCasePatternHolder<test_case_name>(\
+              #test_case_name, \
+              ::testing::internal::CodeLocation(\
+                  __FILE__, __LINE__))->AddTestCaseInstantiation(\
+                      #prefix, \
+                      &gtest_##prefix##test_case_name##_EvalGenerator_, \
+                      &gtest_##prefix##test_case_name##_EvalGenerateName_, \
+                      __FILE__, __LINE__)
+
+}  // namespace testing
+
+#endif  // GTEST_HAS_PARAM_TEST
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
diff --git a/third_party/googletest/googletest/include/gtest/gtest-param-test.h.pump b/third_party/googletest/googletest/include/gtest/gtest-param-test.h.pump
new file mode 100644
index 0000000..3078d6d
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/gtest-param-test.h.pump
@@ -0,0 +1,510 @@
+$$ -*- mode: c++; -*-
+$var n = 50  $$ Maximum length of Values arguments we want to support.
+$var maxtuple = 10  $$ Maximum number of Combine arguments we want to support.
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: vladl@google.com (Vlad Losev)
+//
+// Macros and functions for implementing parameterized tests
+// in Google C++ Testing Framework (Google Test)
+//
+// This file is generated by a SCRIPT.  DO NOT EDIT BY HAND!
+//
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+
+
+// Value-parameterized tests allow you to test your code with different
+// parameters without writing multiple copies of the same test.
+//
+// Here is how you use value-parameterized tests:
+
+#if 0
+
+// To write value-parameterized tests, first you should define a fixture
+// class. It is usually derived from testing::TestWithParam<T> (see below for
+// another inheritance scheme that's sometimes useful in more complicated
+// class hierarchies), where the type of your parameter values.
+// TestWithParam<T> is itself derived from testing::Test. T can be any
+// copyable type. If it's a raw pointer, you are responsible for managing the
+// lifespan of the pointed values.
+
+class FooTest : public ::testing::TestWithParam<const char*> {
+  // You can implement all the usual class fixture members here.
+};
+
+// Then, use the TEST_P macro to define as many parameterized tests
+// for this fixture as you want. The _P suffix is for "parameterized"
+// or "pattern", whichever you prefer to think.
+
+TEST_P(FooTest, DoesBlah) {
+  // Inside a test, access the test parameter with the GetParam() method
+  // of the TestWithParam<T> class:
+  EXPECT_TRUE(foo.Blah(GetParam()));
+  ...
+}
+
+TEST_P(FooTest, HasBlahBlah) {
+  ...
+}
+
+// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test
+// case with any set of parameters you want. Google Test defines a number
+// of functions for generating test parameters. They return what we call
+// (surprise!) parameter generators. Here is a  summary of them, which
+// are all in the testing namespace:
+//
+//
+//  Range(begin, end [, step]) - Yields values {begin, begin+step,
+//                               begin+step+step, ...}. The values do not
+//                               include end. step defaults to 1.
+//  Values(v1, v2, ..., vN)    - Yields values {v1, v2, ..., vN}.
+//  ValuesIn(container)        - Yields values from a C-style array, an STL
+//  ValuesIn(begin,end)          container, or an iterator range [begin, end).
+//  Bool()                     - Yields sequence {false, true}.
+//  Combine(g1, g2, ..., gN)   - Yields all combinations (the Cartesian product
+//                               for the math savvy) of the values generated
+//                               by the N generators.
+//
+// For more details, see comments at the definitions of these functions below
+// in this file.
+//
+// The following statement will instantiate tests from the FooTest test case
+// each with parameter values "meeny", "miny", and "moe".
+
+INSTANTIATE_TEST_CASE_P(InstantiationName,
+                        FooTest,
+                        Values("meeny", "miny", "moe"));
+
+// To distinguish different instances of the pattern, (yes, you
+// can instantiate it more then once) the first argument to the
+// INSTANTIATE_TEST_CASE_P macro is a prefix that will be added to the
+// actual test case name. Remember to pick unique prefixes for different
+// instantiations. The tests from the instantiation above will have
+// these names:
+//
+//    * InstantiationName/FooTest.DoesBlah/0 for "meeny"
+//    * InstantiationName/FooTest.DoesBlah/1 for "miny"
+//    * InstantiationName/FooTest.DoesBlah/2 for "moe"
+//    * InstantiationName/FooTest.HasBlahBlah/0 for "meeny"
+//    * InstantiationName/FooTest.HasBlahBlah/1 for "miny"
+//    * InstantiationName/FooTest.HasBlahBlah/2 for "moe"
+//
+// You can use these names in --gtest_filter.
+//
+// This statement will instantiate all tests from FooTest again, each
+// with parameter values "cat" and "dog":
+
+const char* pets[] = {"cat", "dog"};
+INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets));
+
+// The tests from the instantiation above will have these names:
+//
+//    * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat"
+//    * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog"
+//    * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat"
+//    * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog"
+//
+// Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests
+// in the given test case, whether their definitions come before or
+// AFTER the INSTANTIATE_TEST_CASE_P statement.
+//
+// Please also note that generator expressions (including parameters to the
+// generators) are evaluated in InitGoogleTest(), after main() has started.
+// This allows the user on one hand, to adjust generator parameters in order
+// to dynamically determine a set of tests to run and on the other hand,
+// give the user a chance to inspect the generated tests with Google Test
+// reflection API before RUN_ALL_TESTS() is executed.
+//
+// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc
+// for more examples.
+//
+// In the future, we plan to publish the API for defining new parameter
+// generators. But for now this interface remains part of the internal
+// implementation and is subject to change.
+//
+//
+// A parameterized test fixture must be derived from testing::Test and from
+// testing::WithParamInterface<T>, where T is the type of the parameter
+// values. Inheriting from TestWithParam<T> satisfies that requirement because
+// TestWithParam<T> inherits from both Test and WithParamInterface. In more
+// complicated hierarchies, however, it is occasionally useful to inherit
+// separately from Test and WithParamInterface. For example:
+
+class BaseTest : public ::testing::Test {
+  // You can inherit all the usual members for a non-parameterized test
+  // fixture here.
+};
+
+class DerivedTest : public BaseTest, public ::testing::WithParamInterface<int> {
+  // The usual test fixture members go here too.
+};
+
+TEST_F(BaseTest, HasFoo) {
+  // This is an ordinary non-parameterized test.
+}
+
+TEST_P(DerivedTest, DoesBlah) {
+  // GetParam works just the same here as if you inherit from TestWithParam.
+  EXPECT_TRUE(foo.Blah(GetParam()));
+}
+
+#endif  // 0
+
+#include "gtest/internal/gtest-port.h"
+
+#if !GTEST_OS_SYMBIAN
+# include <utility>
+#endif
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*.  Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-param-util.h"
+#include "gtest/internal/gtest-param-util-generated.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+
+// Functions producing parameter generators.
+//
+// Google Test uses these generators to produce parameters for value-
+// parameterized tests. When a parameterized test case is instantiated
+// with a particular generator, Google Test creates and runs tests
+// for each element in the sequence produced by the generator.
+//
+// In the following sample, tests from test case FooTest are instantiated
+// each three times with parameter values 3, 5, and 8:
+//
+// class FooTest : public TestWithParam<int> { ... };
+//
+// TEST_P(FooTest, TestThis) {
+// }
+// TEST_P(FooTest, TestThat) {
+// }
+// INSTANTIATE_TEST_CASE_P(TestSequence, FooTest, Values(3, 5, 8));
+//
+
+// Range() returns generators providing sequences of values in a range.
+//
+// Synopsis:
+// Range(start, end)
+//   - returns a generator producing a sequence of values {start, start+1,
+//     start+2, ..., }.
+// Range(start, end, step)
+//   - returns a generator producing a sequence of values {start, start+step,
+//     start+step+step, ..., }.
+// Notes:
+//   * The generated sequences never include end. For example, Range(1, 5)
+//     returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2)
+//     returns a generator producing {1, 3, 5, 7}.
+//   * start and end must have the same type. That type may be any integral or
+//     floating-point type or a user defined type satisfying these conditions:
+//     * It must be assignable (have operator=() defined).
+//     * It must have operator+() (operator+(int-compatible type) for
+//       two-operand version).
+//     * It must have operator<() defined.
+//     Elements in the resulting sequences will also have that type.
+//   * Condition start < end must be satisfied in order for resulting sequences
+//     to contain any elements.
+//
+template <typename T, typename IncrementT>
+internal::ParamGenerator<T> Range(T start, T end, IncrementT step) {
+  return internal::ParamGenerator<T>(
+      new internal::RangeGenerator<T, IncrementT>(start, end, step));
+}
+
+template <typename T>
+internal::ParamGenerator<T> Range(T start, T end) {
+  return Range(start, end, 1);
+}
+
+// ValuesIn() function allows generation of tests with parameters coming from
+// a container.
+//
+// Synopsis:
+// ValuesIn(const T (&array)[N])
+//   - returns a generator producing sequences with elements from
+//     a C-style array.
+// ValuesIn(const Container& container)
+//   - returns a generator producing sequences with elements from
+//     an STL-style container.
+// ValuesIn(Iterator begin, Iterator end)
+//   - returns a generator producing sequences with elements from
+//     a range [begin, end) defined by a pair of STL-style iterators. These
+//     iterators can also be plain C pointers.
+//
+// Please note that ValuesIn copies the values from the containers
+// passed in and keeps them to generate tests in RUN_ALL_TESTS().
+//
+// Examples:
+//
+// This instantiates tests from test case StringTest
+// each with C-string values of "foo", "bar", and "baz":
+//
+// const char* strings[] = {"foo", "bar", "baz"};
+// INSTANTIATE_TEST_CASE_P(StringSequence, SrtingTest, ValuesIn(strings));
+//
+// This instantiates tests from test case StlStringTest
+// each with STL strings with values "a" and "b":
+//
+// ::std::vector< ::std::string> GetParameterStrings() {
+//   ::std::vector< ::std::string> v;
+//   v.push_back("a");
+//   v.push_back("b");
+//   return v;
+// }
+//
+// INSTANTIATE_TEST_CASE_P(CharSequence,
+//                         StlStringTest,
+//                         ValuesIn(GetParameterStrings()));
+//
+//
+// This will also instantiate tests from CharTest
+// each with parameter values 'a' and 'b':
+//
+// ::std::list<char> GetParameterChars() {
+//   ::std::list<char> list;
+//   list.push_back('a');
+//   list.push_back('b');
+//   return list;
+// }
+// ::std::list<char> l = GetParameterChars();
+// INSTANTIATE_TEST_CASE_P(CharSequence2,
+//                         CharTest,
+//                         ValuesIn(l.begin(), l.end()));
+//
+template <typename ForwardIterator>
+internal::ParamGenerator<
+  typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end) {
+  typedef typename ::testing::internal::IteratorTraits<ForwardIterator>
+      ::value_type ParamType;
+  return internal::ParamGenerator<ParamType>(
+      new internal::ValuesInIteratorRangeGenerator<ParamType>(begin, end));
+}
+
+template <typename T, size_t N>
+internal::ParamGenerator<T> ValuesIn(const T (&array)[N]) {
+  return ValuesIn(array, array + N);
+}
+
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+    const Container& container) {
+  return ValuesIn(container.begin(), container.end());
+}
+
+// Values() allows generating tests from explicitly specified list of
+// parameters.
+//
+// Synopsis:
+// Values(T v1, T v2, ..., T vN)
+//   - returns a generator producing sequences with elements v1, v2, ..., vN.
+//
+// For example, this instantiates tests from test case BarTest each
+// with values "one", "two", and "three":
+//
+// INSTANTIATE_TEST_CASE_P(NumSequence, BarTest, Values("one", "two", "three"));
+//
+// This instantiates tests from test case BazTest each with values 1, 2, 3.5.
+// The exact type of values will depend on the type of parameter in BazTest.
+//
+// INSTANTIATE_TEST_CASE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5));
+//
+// Currently, Values() supports from 1 to $n parameters.
+//
+$range i 1..n
+$for i [[
+$range j 1..i
+
+template <$for j, [[typename T$j]]>
+internal::ValueArray$i<$for j, [[T$j]]> Values($for j, [[T$j v$j]]) {
+  return internal::ValueArray$i<$for j, [[T$j]]>($for j, [[v$j]]);
+}
+
+]]
+
+// Bool() allows generating tests with parameters in a set of (false, true).
+//
+// Synopsis:
+// Bool()
+//   - returns a generator producing sequences with elements {false, true}.
+//
+// It is useful when testing code that depends on Boolean flags. Combinations
+// of multiple flags can be tested when several Bool()'s are combined using
+// Combine() function.
+//
+// In the following example all tests in the test case FlagDependentTest
+// will be instantiated twice with parameters false and true.
+//
+// class FlagDependentTest : public testing::TestWithParam<bool> {
+//   virtual void SetUp() {
+//     external_flag = GetParam();
+//   }
+// }
+// INSTANTIATE_TEST_CASE_P(BoolSequence, FlagDependentTest, Bool());
+//
+inline internal::ParamGenerator<bool> Bool() {
+  return Values(false, true);
+}
+
+# if GTEST_HAS_COMBINE
+// Combine() allows the user to combine two or more sequences to produce
+// values of a Cartesian product of those sequences' elements.
+//
+// Synopsis:
+// Combine(gen1, gen2, ..., genN)
+//   - returns a generator producing sequences with elements coming from
+//     the Cartesian product of elements from the sequences generated by
+//     gen1, gen2, ..., genN. The sequence elements will have a type of
+//     tuple<T1, T2, ..., TN> where T1, T2, ..., TN are the types
+//     of elements from sequences produces by gen1, gen2, ..., genN.
+//
+// Combine can have up to $maxtuple arguments. This number is currently limited
+// by the maximum number of elements in the tuple implementation used by Google
+// Test.
+//
+// Example:
+//
+// This will instantiate tests in test case AnimalTest each one with
+// the parameter values tuple("cat", BLACK), tuple("cat", WHITE),
+// tuple("dog", BLACK), and tuple("dog", WHITE):
+//
+// enum Color { BLACK, GRAY, WHITE };
+// class AnimalTest
+//     : public testing::TestWithParam<tuple<const char*, Color> > {...};
+//
+// TEST_P(AnimalTest, AnimalLooksNice) {...}
+//
+// INSTANTIATE_TEST_CASE_P(AnimalVariations, AnimalTest,
+//                         Combine(Values("cat", "dog"),
+//                                 Values(BLACK, WHITE)));
+//
+// This will instantiate tests in FlagDependentTest with all variations of two
+// Boolean flags:
+//
+// class FlagDependentTest
+//     : public testing::TestWithParam<tuple<bool, bool> > {
+//   virtual void SetUp() {
+//     // Assigns external_flag_1 and external_flag_2 values from the tuple.
+//     tie(external_flag_1, external_flag_2) = GetParam();
+//   }
+// };
+//
+// TEST_P(FlagDependentTest, TestFeature1) {
+//   // Test your code using external_flag_1 and external_flag_2 here.
+// }
+// INSTANTIATE_TEST_CASE_P(TwoBoolSequence, FlagDependentTest,
+//                         Combine(Bool(), Bool()));
+//
+$range i 2..maxtuple
+$for i [[
+$range j 1..i
+
+template <$for j, [[typename Generator$j]]>
+internal::CartesianProductHolder$i<$for j, [[Generator$j]]> Combine(
+    $for j, [[const Generator$j& g$j]]) {
+  return internal::CartesianProductHolder$i<$for j, [[Generator$j]]>(
+      $for j, [[g$j]]);
+}
+
+]]
+# endif  // GTEST_HAS_COMBINE
+
+
+
+# define TEST_P(test_case_name, test_name) \
+  class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
+      : public test_case_name { \
+   public: \
+    GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \
+    virtual void TestBody(); \
+   private: \
+    static int AddToRegistry() { \
+      ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
+          GetTestCasePatternHolder<test_case_name>(\
+              #test_case_name, \
+              ::testing::internal::CodeLocation(\
+                  __FILE__, __LINE__))->AddTestPattern(\
+                      #test_case_name, \
+                      #test_name, \
+                      new ::testing::internal::TestMetaFactory< \
+                          GTEST_TEST_CLASS_NAME_(\
+                              test_case_name, test_name)>()); \
+      return 0; \
+    } \
+    static int gtest_registering_dummy_ GTEST_ATTRIBUTE_UNUSED_; \
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(\
+        GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \
+  }; \
+  int GTEST_TEST_CLASS_NAME_(test_case_name, \
+                             test_name)::gtest_registering_dummy_ = \
+      GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \
+  void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
+
+// The optional last argument to INSTANTIATE_TEST_CASE_P allows the user
+// to specify a function or functor that generates custom test name suffixes
+// based on the test parameters. The function should accept one argument of
+// type testing::TestParamInfo<class ParamType>, and return std::string.
+//
+// testing::PrintToStringParamName is a builtin test suffix generator that
+// returns the value of testing::PrintToString(GetParam()).
+//
+// Note: test names must be non-empty, unique, and may only contain ASCII
+// alphanumeric characters or underscore. Because PrintToString adds quotes
+// to std::string and C strings, it won't work for these types.
+
+# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator, ...) \
+  ::testing::internal::ParamGenerator<test_case_name::ParamType> \
+      gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \
+  ::std::string gtest_##prefix##test_case_name##_EvalGenerateName_( \
+      const ::testing::TestParamInfo<test_case_name::ParamType>& info) { \
+    return ::testing::internal::GetParamNameGen<test_case_name::ParamType> \
+        (__VA_ARGS__)(info); \
+  } \
+  int gtest_##prefix##test_case_name##_dummy_ GTEST_ATTRIBUTE_UNUSED_ = \
+      ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
+          GetTestCasePatternHolder<test_case_name>(\
+              #test_case_name, \
+              ::testing::internal::CodeLocation(\
+                  __FILE__, __LINE__))->AddTestCaseInstantiation(\
+                      #prefix, \
+                      &gtest_##prefix##test_case_name##_EvalGenerator_, \
+                      &gtest_##prefix##test_case_name##_EvalGenerateName_, \
+                      __FILE__, __LINE__)
+
+}  // namespace testing
+
+#endif  // GTEST_HAS_PARAM_TEST
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
diff --git a/third_party/googletest/googletest/include/gtest/gtest-printers.h b/third_party/googletest/googletest/include/gtest/gtest-printers.h
new file mode 100644
index 0000000..8a33164
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/gtest-printers.h
@@ -0,0 +1,993 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Test - The Google C++ Testing Framework
+//
+// This file implements a universal value printer that can print a
+// value of any type T:
+//
+//   void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
+//
+// A user can teach this function how to print a class type T by
+// defining either operator<<() or PrintTo() in the namespace that
+// defines T.  More specifically, the FIRST defined function in the
+// following list will be used (assuming T is defined in namespace
+// foo):
+//
+//   1. foo::PrintTo(const T&, ostream*)
+//   2. operator<<(ostream&, const T&) defined in either foo or the
+//      global namespace.
+//
+// If none of the above is defined, it will print the debug string of
+// the value if it is a protocol buffer, or print the raw bytes in the
+// value otherwise.
+//
+// To aid debugging: when T is a reference type, the address of the
+// value is also printed; when T is a (const) char pointer, both the
+// pointer value and the NUL-terminated string it points to are
+// printed.
+//
+// We also provide some convenient wrappers:
+//
+//   // Prints a value to a string.  For a (const or not) char
+//   // pointer, the NUL-terminated string (but not the pointer) is
+//   // printed.
+//   std::string ::testing::PrintToString(const T& value);
+//
+//   // Prints a value tersely: for a reference type, the referenced
+//   // value (but not the address) is printed; for a (const or not) char
+//   // pointer, the NUL-terminated string (but not the pointer) is
+//   // printed.
+//   void ::testing::internal::UniversalTersePrint(const T& value, ostream*);
+//
+//   // Prints value using the type inferred by the compiler.  The difference
+//   // from UniversalTersePrint() is that this function prints both the
+//   // pointer and the NUL-terminated string for a (const or not) char pointer.
+//   void ::testing::internal::UniversalPrint(const T& value, ostream*);
+//
+//   // Prints the fields of a tuple tersely to a string vector, one
+//   // element for each field. Tuple support must be enabled in
+//   // gtest-port.h.
+//   std::vector<string> UniversalTersePrintTupleFieldsToStrings(
+//       const Tuple& value);
+//
+// Known limitation:
+//
+// The print primitives print the elements of an STL-style container
+// using the compiler-inferred type of *iter where iter is a
+// const_iterator of the container.  When const_iterator is an input
+// iterator but not a forward iterator, this inferred type may not
+// match value_type, and the print output may be incorrect.  In
+// practice, this is rarely a problem as for most containers
+// const_iterator is a forward iterator.  We'll fix this if there's an
+// actual need for it.  Note that this fix cannot rely on value_type
+// being defined as many user-defined container types don't have
+// value_type.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
+
+#include <ostream>  // NOLINT
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+#include "gtest/internal/gtest-port.h"
+#include "gtest/internal/gtest-internal.h"
+
+#if GTEST_HAS_STD_TUPLE_
+# include <tuple>
+#endif
+
+namespace testing {
+
+// Definitions in the 'internal' and 'internal2' name spaces are
+// subject to change without notice.  DO NOT USE THEM IN USER CODE!
+namespace internal2 {
+
+// Prints the given number of bytes in the given object to the given
+// ostream.
+GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes,
+                                     size_t count,
+                                     ::std::ostream* os);
+
+// For selecting which printer to use when a given type has neither <<
+// nor PrintTo().
+enum TypeKind {
+  kProtobuf,              // a protobuf type
+  kConvertibleToInteger,  // a type implicitly convertible to BiggestInt
+                          // (e.g. a named or unnamed enum type)
+  kOtherType              // anything else
+};
+
+// TypeWithoutFormatter<T, kTypeKind>::PrintValue(value, os) is called
+// by the universal printer to print a value of type T when neither
+// operator<< nor PrintTo() is defined for T, where kTypeKind is the
+// "kind" of T as defined by enum TypeKind.
+template <typename T, TypeKind kTypeKind>
+class TypeWithoutFormatter {
+ public:
+  // This default version is called when kTypeKind is kOtherType.
+  static void PrintValue(const T& value, ::std::ostream* os) {
+    PrintBytesInObjectTo(reinterpret_cast<const unsigned char*>(&value),
+                         sizeof(value), os);
+  }
+};
+
+// We print a protobuf using its ShortDebugString() when the string
+// doesn't exceed this many characters; otherwise we print it using
+// DebugString() for better readability.
+const size_t kProtobufOneLinerMaxLength = 50;
+
+template <typename T>
+class TypeWithoutFormatter<T, kProtobuf> {
+ public:
+  static void PrintValue(const T& value, ::std::ostream* os) {
+    const ::testing::internal::string short_str = value.ShortDebugString();
+    const ::testing::internal::string pretty_str =
+        short_str.length() <= kProtobufOneLinerMaxLength ?
+        short_str : ("\n" + value.DebugString());
+    *os << ("<" + pretty_str + ">");
+  }
+};
+
+template <typename T>
+class TypeWithoutFormatter<T, kConvertibleToInteger> {
+ public:
+  // Since T has no << operator or PrintTo() but can be implicitly
+  // converted to BiggestInt, we print it as a BiggestInt.
+  //
+  // Most likely T is an enum type (either named or unnamed), in which
+  // case printing it as an integer is the desired behavior.  In case
+  // T is not an enum, printing it as an integer is the best we can do
+  // given that it has no user-defined printer.
+  static void PrintValue(const T& value, ::std::ostream* os) {
+    const internal::BiggestInt kBigInt = value;
+    *os << kBigInt;
+  }
+};
+
+// Prints the given value to the given ostream.  If the value is a
+// protocol message, its debug string is printed; if it's an enum or
+// of a type implicitly convertible to BiggestInt, it's printed as an
+// integer; otherwise the bytes in the value are printed.  This is
+// what UniversalPrinter<T>::Print() does when it knows nothing about
+// type T and T has neither << operator nor PrintTo().
+//
+// A user can override this behavior for a class type Foo by defining
+// a << operator in the namespace where Foo is defined.
+//
+// We put this operator in namespace 'internal2' instead of 'internal'
+// to simplify the implementation, as much code in 'internal' needs to
+// use << in STL, which would conflict with our own << were it defined
+// in 'internal'.
+//
+// Note that this operator<< takes a generic std::basic_ostream<Char,
+// CharTraits> type instead of the more restricted std::ostream.  If
+// we define it to take an std::ostream instead, we'll get an
+// "ambiguous overloads" compiler error when trying to print a type
+// Foo that supports streaming to std::basic_ostream<Char,
+// CharTraits>, as the compiler cannot tell whether
+// operator<<(std::ostream&, const T&) or
+// operator<<(std::basic_stream<Char, CharTraits>, const Foo&) is more
+// specific.
+template <typename Char, typename CharTraits, typename T>
+::std::basic_ostream<Char, CharTraits>& operator<<(
+    ::std::basic_ostream<Char, CharTraits>& os, const T& x) {
+  TypeWithoutFormatter<T,
+      (internal::IsAProtocolMessage<T>::value ? kProtobuf :
+       internal::ImplicitlyConvertible<const T&, internal::BiggestInt>::value ?
+       kConvertibleToInteger : kOtherType)>::PrintValue(x, &os);
+  return os;
+}
+
+}  // namespace internal2
+}  // namespace testing
+
+// This namespace MUST NOT BE NESTED IN ::testing, or the name look-up
+// magic needed for implementing UniversalPrinter won't work.
+namespace testing_internal {
+
+// Used to print a value that is not an STL-style container when the
+// user doesn't define PrintTo() for it.
+template <typename T>
+void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) {
+  // With the following statement, during unqualified name lookup,
+  // testing::internal2::operator<< appears as if it was declared in
+  // the nearest enclosing namespace that contains both
+  // ::testing_internal and ::testing::internal2, i.e. the global
+  // namespace.  For more details, refer to the C++ Standard section
+  // 7.3.4-1 [namespace.udir].  This allows us to fall back onto
+  // testing::internal2::operator<< in case T doesn't come with a <<
+  // operator.
+  //
+  // We cannot write 'using ::testing::internal2::operator<<;', which
+  // gcc 3.3 fails to compile due to a compiler bug.
+  using namespace ::testing::internal2;  // NOLINT
+
+  // Assuming T is defined in namespace foo, in the next statement,
+  // the compiler will consider all of:
+  //
+  //   1. foo::operator<< (thanks to Koenig look-up),
+  //   2. ::operator<< (as the current namespace is enclosed in ::),
+  //   3. testing::internal2::operator<< (thanks to the using statement above).
+  //
+  // The operator<< whose type matches T best will be picked.
+  //
+  // We deliberately allow #2 to be a candidate, as sometimes it's
+  // impossible to define #1 (e.g. when foo is ::std, defining
+  // anything in it is undefined behavior unless you are a compiler
+  // vendor.).
+  *os << value;
+}
+
+}  // namespace testing_internal
+
+namespace testing {
+namespace internal {
+
+// FormatForComparison<ToPrint, OtherOperand>::Format(value) formats a
+// value of type ToPrint that is an operand of a comparison assertion
+// (e.g. ASSERT_EQ).  OtherOperand is the type of the other operand in
+// the comparison, and is used to help determine the best way to
+// format the value.  In particular, when the value is a C string
+// (char pointer) and the other operand is an STL string object, we
+// want to format the C string as a string, since we know it is
+// compared by value with the string object.  If the value is a char
+// pointer but the other operand is not an STL string object, we don't
+// know whether the pointer is supposed to point to a NUL-terminated
+// string, and thus want to print it as a pointer to be safe.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+
+// The default case.
+template <typename ToPrint, typename OtherOperand>
+class FormatForComparison {
+ public:
+  static ::std::string Format(const ToPrint& value) {
+    return ::testing::PrintToString(value);
+  }
+};
+
+// Array.
+template <typename ToPrint, size_t N, typename OtherOperand>
+class FormatForComparison<ToPrint[N], OtherOperand> {
+ public:
+  static ::std::string Format(const ToPrint* value) {
+    return FormatForComparison<const ToPrint*, OtherOperand>::Format(value);
+  }
+};
+
+// By default, print C string as pointers to be safe, as we don't know
+// whether they actually point to a NUL-terminated string.
+
+#define GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(CharType)                \
+  template <typename OtherOperand>                                      \
+  class FormatForComparison<CharType*, OtherOperand> {                  \
+   public:                                                              \
+    static ::std::string Format(CharType* value) {                      \
+      return ::testing::PrintToString(static_cast<const void*>(value)); \
+    }                                                                   \
+  }
+
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char);
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char);
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(wchar_t);
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t);
+
+#undef GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_
+
+// If a C string is compared with an STL string object, we know it's meant
+// to point to a NUL-terminated string, and thus can print it as a string.
+
+#define GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(CharType, OtherStringType) \
+  template <>                                                           \
+  class FormatForComparison<CharType*, OtherStringType> {               \
+   public:                                                              \
+    static ::std::string Format(CharType* value) {                      \
+      return ::testing::PrintToString(value);                           \
+    }                                                                   \
+  }
+
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::std::string);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::std::string);
+
+#if GTEST_HAS_GLOBAL_STRING
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::string);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::string);
+#endif
+
+#if GTEST_HAS_GLOBAL_WSTRING
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::wstring);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::wstring);
+#endif
+
+#if GTEST_HAS_STD_WSTRING
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::std::wstring);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::std::wstring);
+#endif
+
+#undef GTEST_IMPL_FORMAT_C_STRING_AS_STRING_
+
+// Formats a comparison assertion (e.g. ASSERT_EQ, EXPECT_LT, and etc)
+// operand to be used in a failure message.  The type (but not value)
+// of the other operand may affect the format.  This allows us to
+// print a char* as a raw pointer when it is compared against another
+// char* or void*, and print it as a C string when it is compared
+// against an std::string object, for example.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+template <typename T1, typename T2>
+std::string FormatForComparisonFailureMessage(
+    const T1& value, const T2& /* other_operand */) {
+  return FormatForComparison<T1, T2>::Format(value);
+}
+
+// UniversalPrinter<T>::Print(value, ostream_ptr) prints the given
+// value to the given ostream.  The caller must ensure that
+// 'ostream_ptr' is not NULL, or the behavior is undefined.
+//
+// We define UniversalPrinter as a class template (as opposed to a
+// function template), as we need to partially specialize it for
+// reference types, which cannot be done with function templates.
+template <typename T>
+class UniversalPrinter;
+
+template <typename T>
+void UniversalPrint(const T& value, ::std::ostream* os);
+
+// Used to print an STL-style container when the user doesn't define
+// a PrintTo() for it.
+template <typename C>
+void DefaultPrintTo(IsContainer /* dummy */,
+                    false_type /* is not a pointer */,
+                    const C& container, ::std::ostream* os) {
+  const size_t kMaxCount = 32;  // The maximum number of elements to print.
+  *os << '{';
+  size_t count = 0;
+  for (typename C::const_iterator it = container.begin();
+       it != container.end(); ++it, ++count) {
+    if (count > 0) {
+      *os << ',';
+      if (count == kMaxCount) {  // Enough has been printed.
+        *os << " ...";
+        break;
+      }
+    }
+    *os << ' ';
+    // We cannot call PrintTo(*it, os) here as PrintTo() doesn't
+    // handle *it being a native array.
+    internal::UniversalPrint(*it, os);
+  }
+
+  if (count > 0) {
+    *os << ' ';
+  }
+  *os << '}';
+}
+
+// Used to print a pointer that is neither a char pointer nor a member
+// pointer, when the user doesn't define PrintTo() for it.  (A member
+// variable pointer or member function pointer doesn't really point to
+// a location in the address space.  Their representation is
+// implementation-defined.  Therefore they will be printed as raw
+// bytes.)
+template <typename T>
+void DefaultPrintTo(IsNotContainer /* dummy */,
+                    true_type /* is a pointer */,
+                    T* p, ::std::ostream* os) {
+  if (p == NULL) {
+    *os << "NULL";
+  } else {
+    // C++ doesn't allow casting from a function pointer to any object
+    // pointer.
+    //
+    // IsTrue() silences warnings: "Condition is always true",
+    // "unreachable code".
+    if (IsTrue(ImplicitlyConvertible<T*, const void*>::value)) {
+      // T is not a function type.  We just call << to print p,
+      // relying on ADL to pick up user-defined << for their pointer
+      // types, if any.
+      *os << p;
+    } else {
+      // T is a function type, so '*os << p' doesn't do what we want
+      // (it just prints p as bool).  We want to print p as a const
+      // void*.  However, we cannot cast it to const void* directly,
+      // even using reinterpret_cast, as earlier versions of gcc
+      // (e.g. 3.4.5) cannot compile the cast when p is a function
+      // pointer.  Casting to UInt64 first solves the problem.
+      *os << reinterpret_cast<const void*>(
+          reinterpret_cast<internal::UInt64>(p));
+    }
+  }
+}
+
+// Used to print a non-container, non-pointer value when the user
+// doesn't define PrintTo() for it.
+template <typename T>
+void DefaultPrintTo(IsNotContainer /* dummy */,
+                    false_type /* is not a pointer */,
+                    const T& value, ::std::ostream* os) {
+  ::testing_internal::DefaultPrintNonContainerTo(value, os);
+}
+
+// Prints the given value using the << operator if it has one;
+// otherwise prints the bytes in it.  This is what
+// UniversalPrinter<T>::Print() does when PrintTo() is not specialized
+// or overloaded for type T.
+//
+// A user can override this behavior for a class type Foo by defining
+// an overload of PrintTo() in the namespace where Foo is defined.  We
+// give the user this option as sometimes defining a << operator for
+// Foo is not desirable (e.g. the coding style may prevent doing it,
+// or there is already a << operator but it doesn't do what the user
+// wants).
+template <typename T>
+void PrintTo(const T& value, ::std::ostream* os) {
+  // DefaultPrintTo() is overloaded.  The type of its first two
+  // arguments determine which version will be picked.  If T is an
+  // STL-style container, the version for container will be called; if
+  // T is a pointer, the pointer version will be called; otherwise the
+  // generic version will be called.
+  //
+  // Note that we check for container types here, prior to we check
+  // for protocol message types in our operator<<.  The rationale is:
+  //
+  // For protocol messages, we want to give people a chance to
+  // override Google Mock's format by defining a PrintTo() or
+  // operator<<.  For STL containers, other formats can be
+  // incompatible with Google Mock's format for the container
+  // elements; therefore we check for container types here to ensure
+  // that our format is used.
+  //
+  // The second argument of DefaultPrintTo() is needed to bypass a bug
+  // in Symbian's C++ compiler that prevents it from picking the right
+  // overload between:
+  //
+  //   PrintTo(const T& x, ...);
+  //   PrintTo(T* x, ...);
+  DefaultPrintTo(IsContainerTest<T>(0), is_pointer<T>(), value, os);
+}
+
+// The following list of PrintTo() overloads tells
+// UniversalPrinter<T>::Print() how to print standard types (built-in
+// types, strings, plain arrays, and pointers).
+
+// Overloads for various char types.
+GTEST_API_ void PrintTo(unsigned char c, ::std::ostream* os);
+GTEST_API_ void PrintTo(signed char c, ::std::ostream* os);
+inline void PrintTo(char c, ::std::ostream* os) {
+  // When printing a plain char, we always treat it as unsigned.  This
+  // way, the output won't be affected by whether the compiler thinks
+  // char is signed or not.
+  PrintTo(static_cast<unsigned char>(c), os);
+}
+
+// Overloads for other simple built-in types.
+inline void PrintTo(bool x, ::std::ostream* os) {
+  *os << (x ? "true" : "false");
+}
+
+// Overload for wchar_t type.
+// Prints a wchar_t as a symbol if it is printable or as its internal
+// code otherwise and also as its decimal code (except for L'\0').
+// The L'\0' char is printed as "L'\\0'". The decimal code is printed
+// as signed integer when wchar_t is implemented by the compiler
+// as a signed type and is printed as an unsigned integer when wchar_t
+// is implemented as an unsigned type.
+GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os);
+
+// Overloads for C strings.
+GTEST_API_ void PrintTo(const char* s, ::std::ostream* os);
+inline void PrintTo(char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const char*>(s), os);
+}
+
+// signed/unsigned char is often used for representing binary data, so
+// we print pointers to it as void* to be safe.
+inline void PrintTo(const signed char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(signed char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(const unsigned char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(unsigned char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+
+// MSVC can be configured to define wchar_t as a typedef of unsigned
+// short.  It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native
+// type.  When wchar_t is a typedef, defining an overload for const
+// wchar_t* would cause unsigned short* be printed as a wide string,
+// possibly causing invalid memory accesses.
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+// Overloads for wide C strings
+GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os);
+inline void PrintTo(wchar_t* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const wchar_t*>(s), os);
+}
+#endif
+
+// Overload for C arrays.  Multi-dimensional arrays are printed
+// properly.
+
+// Prints the given number of elements in an array, without printing
+// the curly braces.
+template <typename T>
+void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) {
+  UniversalPrint(a[0], os);
+  for (size_t i = 1; i != count; i++) {
+    *os << ", ";
+    UniversalPrint(a[i], os);
+  }
+}
+
+// Overloads for ::string and ::std::string.
+#if GTEST_HAS_GLOBAL_STRING
+GTEST_API_ void PrintStringTo(const ::string&s, ::std::ostream* os);
+inline void PrintTo(const ::string& s, ::std::ostream* os) {
+  PrintStringTo(s, os);
+}
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os);
+inline void PrintTo(const ::std::string& s, ::std::ostream* os) {
+  PrintStringTo(s, os);
+}
+
+// Overloads for ::wstring and ::std::wstring.
+#if GTEST_HAS_GLOBAL_WSTRING
+GTEST_API_ void PrintWideStringTo(const ::wstring&s, ::std::ostream* os);
+inline void PrintTo(const ::wstring& s, ::std::ostream* os) {
+  PrintWideStringTo(s, os);
+}
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+#if GTEST_HAS_STD_WSTRING
+GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os);
+inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
+  PrintWideStringTo(s, os);
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_TR1_TUPLE || GTEST_HAS_STD_TUPLE_
+// Helper function for printing a tuple.  T must be instantiated with
+// a tuple type.
+template <typename T>
+void PrintTupleTo(const T& t, ::std::ostream* os);
+#endif  // GTEST_HAS_TR1_TUPLE || GTEST_HAS_STD_TUPLE_
+
+#if GTEST_HAS_TR1_TUPLE
+// Overload for ::std::tr1::tuple.  Needed for printing function arguments,
+// which are packed as tuples.
+
+// Overloaded PrintTo() for tuples of various arities.  We support
+// tuples of up-to 10 fields.  The following implementation works
+// regardless of whether tr1::tuple is implemented using the
+// non-standard variadic template feature or not.
+
+inline void PrintTo(const ::std::tr1::tuple<>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1>
+void PrintTo(const ::std::tr1::tuple<T1>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2>
+void PrintTo(const ::std::tr1::tuple<T1, T2>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6, typename T7>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6, typename T7, typename T8>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6, typename T7, typename T8, typename T9>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6, typename T7, typename T8, typename T9, typename T10>
+void PrintTo(
+    const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>& t,
+    ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+#endif  // GTEST_HAS_TR1_TUPLE
+
+#if GTEST_HAS_STD_TUPLE_
+template <typename... Types>
+void PrintTo(const ::std::tuple<Types...>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+#endif  // GTEST_HAS_STD_TUPLE_
+
+// Overload for std::pair.
+template <typename T1, typename T2>
+void PrintTo(const ::std::pair<T1, T2>& value, ::std::ostream* os) {
+  *os << '(';
+  // We cannot use UniversalPrint(value.first, os) here, as T1 may be
+  // a reference type.  The same for printing value.second.
+  UniversalPrinter<T1>::Print(value.first, os);
+  *os << ", ";
+  UniversalPrinter<T2>::Print(value.second, os);
+  *os << ')';
+}
+
+// Implements printing a non-reference type T by letting the compiler
+// pick the right overload of PrintTo() for T.
+template <typename T>
+class UniversalPrinter {
+ public:
+  // MSVC warns about adding const to a function type, so we want to
+  // disable the warning.
+  GTEST_DISABLE_MSC_WARNINGS_PUSH_(4180)
+
+  // Note: we deliberately don't call this PrintTo(), as that name
+  // conflicts with ::testing::internal::PrintTo in the body of the
+  // function.
+  static void Print(const T& value, ::std::ostream* os) {
+    // By default, ::testing::internal::PrintTo() is used for printing
+    // the value.
+    //
+    // Thanks to Koenig look-up, if T is a class and has its own
+    // PrintTo() function defined in its namespace, that function will
+    // be visible here.  Since it is more specific than the generic ones
+    // in ::testing::internal, it will be picked by the compiler in the
+    // following statement - exactly what we want.
+    PrintTo(value, os);
+  }
+
+  GTEST_DISABLE_MSC_WARNINGS_POP_()
+};
+
+// UniversalPrintArray(begin, len, os) prints an array of 'len'
+// elements, starting at address 'begin'.
+template <typename T>
+void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) {
+  if (len == 0) {
+    *os << "{}";
+  } else {
+    *os << "{ ";
+    const size_t kThreshold = 18;
+    const size_t kChunkSize = 8;
+    // If the array has more than kThreshold elements, we'll have to
+    // omit some details by printing only the first and the last
+    // kChunkSize elements.
+    // TODO(wan@google.com): let the user control the threshold using a flag.
+    if (len <= kThreshold) {
+      PrintRawArrayTo(begin, len, os);
+    } else {
+      PrintRawArrayTo(begin, kChunkSize, os);
+      *os << ", ..., ";
+      PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os);
+    }
+    *os << " }";
+  }
+}
+// This overload prints a (const) char array compactly.
+GTEST_API_ void UniversalPrintArray(
+    const char* begin, size_t len, ::std::ostream* os);
+
+// This overload prints a (const) wchar_t array compactly.
+GTEST_API_ void UniversalPrintArray(
+    const wchar_t* begin, size_t len, ::std::ostream* os);
+
+// Implements printing an array type T[N].
+template <typename T, size_t N>
+class UniversalPrinter<T[N]> {
+ public:
+  // Prints the given array, omitting some elements when there are too
+  // many.
+  static void Print(const T (&a)[N], ::std::ostream* os) {
+    UniversalPrintArray(a, N, os);
+  }
+};
+
+// Implements printing a reference type T&.
+template <typename T>
+class UniversalPrinter<T&> {
+ public:
+  // MSVC warns about adding const to a function type, so we want to
+  // disable the warning.
+  GTEST_DISABLE_MSC_WARNINGS_PUSH_(4180)
+
+  static void Print(const T& value, ::std::ostream* os) {
+    // Prints the address of the value.  We use reinterpret_cast here
+    // as static_cast doesn't compile when T is a function type.
+    *os << "@" << reinterpret_cast<const void*>(&value) << " ";
+
+    // Then prints the value itself.
+    UniversalPrint(value, os);
+  }
+
+  GTEST_DISABLE_MSC_WARNINGS_POP_()
+};
+
+// Prints a value tersely: for a reference type, the referenced value
+// (but not the address) is printed; for a (const) char pointer, the
+// NUL-terminated string (but not the pointer) is printed.
+
+template <typename T>
+class UniversalTersePrinter {
+ public:
+  static void Print(const T& value, ::std::ostream* os) {
+    UniversalPrint(value, os);
+  }
+};
+template <typename T>
+class UniversalTersePrinter<T&> {
+ public:
+  static void Print(const T& value, ::std::ostream* os) {
+    UniversalPrint(value, os);
+  }
+};
+template <typename T, size_t N>
+class UniversalTersePrinter<T[N]> {
+ public:
+  static void Print(const T (&value)[N], ::std::ostream* os) {
+    UniversalPrinter<T[N]>::Print(value, os);
+  }
+};
+template <>
+class UniversalTersePrinter<const char*> {
+ public:
+  static void Print(const char* str, ::std::ostream* os) {
+    if (str == NULL) {
+      *os << "NULL";
+    } else {
+      UniversalPrint(string(str), os);
+    }
+  }
+};
+template <>
+class UniversalTersePrinter<char*> {
+ public:
+  static void Print(char* str, ::std::ostream* os) {
+    UniversalTersePrinter<const char*>::Print(str, os);
+  }
+};
+
+#if GTEST_HAS_STD_WSTRING
+template <>
+class UniversalTersePrinter<const wchar_t*> {
+ public:
+  static void Print(const wchar_t* str, ::std::ostream* os) {
+    if (str == NULL) {
+      *os << "NULL";
+    } else {
+      UniversalPrint(::std::wstring(str), os);
+    }
+  }
+};
+#endif
+
+template <>
+class UniversalTersePrinter<wchar_t*> {
+ public:
+  static void Print(wchar_t* str, ::std::ostream* os) {
+    UniversalTersePrinter<const wchar_t*>::Print(str, os);
+  }
+};
+
+template <typename T>
+void UniversalTersePrint(const T& value, ::std::ostream* os) {
+  UniversalTersePrinter<T>::Print(value, os);
+}
+
+// Prints a value using the type inferred by the compiler.  The
+// difference between this and UniversalTersePrint() is that for a
+// (const) char pointer, this prints both the pointer and the
+// NUL-terminated string.
+template <typename T>
+void UniversalPrint(const T& value, ::std::ostream* os) {
+  // A workarond for the bug in VC++ 7.1 that prevents us from instantiating
+  // UniversalPrinter with T directly.
+  typedef T T1;
+  UniversalPrinter<T1>::Print(value, os);
+}
+
+typedef ::std::vector<string> Strings;
+
+// TuplePolicy<TupleT> must provide:
+// - tuple_size
+//     size of tuple TupleT.
+// - get<size_t I>(const TupleT& t)
+//     static function extracting element I of tuple TupleT.
+// - tuple_element<size_t I>::type
+//     type of element I of tuple TupleT.
+template <typename TupleT>
+struct TuplePolicy;
+
+#if GTEST_HAS_TR1_TUPLE
+template <typename TupleT>
+struct TuplePolicy {
+  typedef TupleT Tuple;
+  static const size_t tuple_size = ::std::tr1::tuple_size<Tuple>::value;
+
+  template <size_t I>
+  struct tuple_element : ::std::tr1::tuple_element<I, Tuple> {};
+
+  template <size_t I>
+  static typename AddReference<
+      const typename ::std::tr1::tuple_element<I, Tuple>::type>::type get(
+      const Tuple& tuple) {
+    return ::std::tr1::get<I>(tuple);
+  }
+};
+template <typename TupleT>
+const size_t TuplePolicy<TupleT>::tuple_size;
+#endif  // GTEST_HAS_TR1_TUPLE
+
+#if GTEST_HAS_STD_TUPLE_
+template <typename... Types>
+struct TuplePolicy< ::std::tuple<Types...> > {
+  typedef ::std::tuple<Types...> Tuple;
+  static const size_t tuple_size = ::std::tuple_size<Tuple>::value;
+
+  template <size_t I>
+  struct tuple_element : ::std::tuple_element<I, Tuple> {};
+
+  template <size_t I>
+  static const typename ::std::tuple_element<I, Tuple>::type& get(
+      const Tuple& tuple) {
+    return ::std::get<I>(tuple);
+  }
+};
+template <typename... Types>
+const size_t TuplePolicy< ::std::tuple<Types...> >::tuple_size;
+#endif  // GTEST_HAS_STD_TUPLE_
+
+#if GTEST_HAS_TR1_TUPLE || GTEST_HAS_STD_TUPLE_
+// This helper template allows PrintTo() for tuples and
+// UniversalTersePrintTupleFieldsToStrings() to be defined by
+// induction on the number of tuple fields.  The idea is that
+// TuplePrefixPrinter<N>::PrintPrefixTo(t, os) prints the first N
+// fields in tuple t, and can be defined in terms of
+// TuplePrefixPrinter<N - 1>.
+//
+// The inductive case.
+template <size_t N>
+struct TuplePrefixPrinter {
+  // Prints the first N fields of a tuple.
+  template <typename Tuple>
+  static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
+    TuplePrefixPrinter<N - 1>::PrintPrefixTo(t, os);
+    GTEST_INTENTIONAL_CONST_COND_PUSH_()
+    if (N > 1) {
+    GTEST_INTENTIONAL_CONST_COND_POP_()
+      *os << ", ";
+    }
+    UniversalPrinter<
+        typename TuplePolicy<Tuple>::template tuple_element<N - 1>::type>
+        ::Print(TuplePolicy<Tuple>::template get<N - 1>(t), os);
+  }
+
+  // Tersely prints the first N fields of a tuple to a string vector,
+  // one element for each field.
+  template <typename Tuple>
+  static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) {
+    TuplePrefixPrinter<N - 1>::TersePrintPrefixToStrings(t, strings);
+    ::std::stringstream ss;
+    UniversalTersePrint(TuplePolicy<Tuple>::template get<N - 1>(t), &ss);
+    strings->push_back(ss.str());
+  }
+};
+
+// Base case.
+template <>
+struct TuplePrefixPrinter<0> {
+  template <typename Tuple>
+  static void PrintPrefixTo(const Tuple&, ::std::ostream*) {}
+
+  template <typename Tuple>
+  static void TersePrintPrefixToStrings(const Tuple&, Strings*) {}
+};
+
+// Helper function for printing a tuple.
+// Tuple must be either std::tr1::tuple or std::tuple type.
+template <typename Tuple>
+void PrintTupleTo(const Tuple& t, ::std::ostream* os) {
+  *os << "(";
+  TuplePrefixPrinter<TuplePolicy<Tuple>::tuple_size>::PrintPrefixTo(t, os);
+  *os << ")";
+}
+
+// Prints the fields of a tuple tersely to a string vector, one
+// element for each field.  See the comment before
+// UniversalTersePrint() for how we define "tersely".
+template <typename Tuple>
+Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
+  Strings result;
+  TuplePrefixPrinter<TuplePolicy<Tuple>::tuple_size>::
+      TersePrintPrefixToStrings(value, &result);
+  return result;
+}
+#endif  // GTEST_HAS_TR1_TUPLE || GTEST_HAS_STD_TUPLE_
+
+}  // namespace internal
+
+template <typename T>
+::std::string PrintToString(const T& value) {
+  ::std::stringstream ss;
+  internal::UniversalTersePrinter<T>::Print(value, &ss);
+  return ss.str();
+}
+
+}  // namespace testing
+
+// Include any custom printer added by the local installation.
+// We must include this header at the end to make sure it can use the
+// declarations from this file.
+#include "gtest/internal/custom/gtest-printers.h"
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
diff --git a/third_party/googletest/googletest/include/gtest/gtest-spi.h b/third_party/googletest/googletest/include/gtest/gtest-spi.h
new file mode 100644
index 0000000..f63fa9a
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/gtest-spi.h
@@ -0,0 +1,232 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// Utilities for testing Google Test itself and code that uses Google Test
+// (e.g. frameworks built on top of Google Test).
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_
+#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_
+
+#include "gtest/gtest.h"
+
+namespace testing {
+
+// This helper class can be used to mock out Google Test failure reporting
+// so that we can test Google Test or code that builds on Google Test.
+//
+// An object of this class appends a TestPartResult object to the
+// TestPartResultArray object given in the constructor whenever a Google Test
+// failure is reported. It can either intercept only failures that are
+// generated in the same thread that created this object or it can intercept
+// all generated failures. The scope of this mock object can be controlled with
+// the second argument to the two arguments constructor.
+class GTEST_API_ ScopedFakeTestPartResultReporter
+    : public TestPartResultReporterInterface {
+ public:
+  // The two possible mocking modes of this object.
+  enum InterceptMode {
+    INTERCEPT_ONLY_CURRENT_THREAD,  // Intercepts only thread local failures.
+    INTERCEPT_ALL_THREADS           // Intercepts all failures.
+  };
+
+  // The c'tor sets this object as the test part result reporter used
+  // by Google Test.  The 'result' parameter specifies where to report the
+  // results. This reporter will only catch failures generated in the current
+  // thread. DEPRECATED
+  explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result);
+
+  // Same as above, but you can choose the interception scope of this object.
+  ScopedFakeTestPartResultReporter(InterceptMode intercept_mode,
+                                   TestPartResultArray* result);
+
+  // The d'tor restores the previous test part result reporter.
+  virtual ~ScopedFakeTestPartResultReporter();
+
+  // Appends the TestPartResult object to the TestPartResultArray
+  // received in the constructor.
+  //
+  // This method is from the TestPartResultReporterInterface
+  // interface.
+  virtual void ReportTestPartResult(const TestPartResult& result);
+ private:
+  void Init();
+
+  const InterceptMode intercept_mode_;
+  TestPartResultReporterInterface* old_reporter_;
+  TestPartResultArray* const result_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter);
+};
+
+namespace internal {
+
+// A helper class for implementing EXPECT_FATAL_FAILURE() and
+// EXPECT_NONFATAL_FAILURE().  Its destructor verifies that the given
+// TestPartResultArray contains exactly one failure that has the given
+// type and contains the given substring.  If that's not the case, a
+// non-fatal failure will be generated.
+class GTEST_API_ SingleFailureChecker {
+ public:
+  // The constructor remembers the arguments.
+  SingleFailureChecker(const TestPartResultArray* results,
+                       TestPartResult::Type type,
+                       const string& substr);
+  ~SingleFailureChecker();
+ private:
+  const TestPartResultArray* const results_;
+  const TestPartResult::Type type_;
+  const string substr_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker);
+};
+
+}  // namespace internal
+
+}  // namespace testing
+
+// A set of macros for testing Google Test assertions or code that's expected
+// to generate Google Test fatal failures.  It verifies that the given
+// statement will cause exactly one fatal Google Test failure with 'substr'
+// being part of the failure message.
+//
+// There are two different versions of this macro. EXPECT_FATAL_FAILURE only
+// affects and considers failures generated in the current thread and
+// EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
+//
+// The verification of the assertion is done correctly even when the statement
+// throws an exception or aborts the current function.
+//
+// Known restrictions:
+//   - 'statement' cannot reference local non-static variables or
+//     non-static members of the current object.
+//   - 'statement' cannot return a value.
+//   - You cannot stream a failure message to this macro.
+//
+// Note that even though the implementations of the following two
+// macros are much alike, we cannot refactor them to use a common
+// helper macro, due to some peculiarity in how the preprocessor
+// works.  The AcceptsMacroThatExpandsToUnprotectedComma test in
+// gtest_unittest.cc will fail to compile if we do that.
+#define EXPECT_FATAL_FAILURE(statement, substr) \
+  do { \
+    class GTestExpectFatalFailureHelper {\
+     public:\
+      static void Execute() { statement; }\
+    };\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter:: \
+          INTERCEPT_ONLY_CURRENT_THREAD, &gtest_failures);\
+      GTestExpectFatalFailureHelper::Execute();\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
+  do { \
+    class GTestExpectFatalFailureHelper {\
+     public:\
+      static void Execute() { statement; }\
+    };\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter:: \
+          INTERCEPT_ALL_THREADS, &gtest_failures);\
+      GTestExpectFatalFailureHelper::Execute();\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+// A macro for testing Google Test assertions or code that's expected to
+// generate Google Test non-fatal failures.  It asserts that the given
+// statement will cause exactly one non-fatal Google Test failure with 'substr'
+// being part of the failure message.
+//
+// There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only
+// affects and considers failures generated in the current thread and
+// EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
+//
+// 'statement' is allowed to reference local variables and members of
+// the current object.
+//
+// The verification of the assertion is done correctly even when the statement
+// throws an exception or aborts the current function.
+//
+// Known restrictions:
+//   - You cannot stream a failure message to this macro.
+//
+// Note that even though the implementations of the following two
+// macros are much alike, we cannot refactor them to use a common
+// helper macro, due to some peculiarity in how the preprocessor
+// works.  If we do that, the code won't compile when the user gives
+// EXPECT_NONFATAL_FAILURE() a statement that contains a macro that
+// expands to code containing an unprotected comma.  The
+// AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc
+// catches that.
+//
+// For the same reason, we have to write
+//   if (::testing::internal::AlwaysTrue()) { statement; }
+// instead of
+//   GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
+// to avoid an MSVC warning on unreachable code.
+#define EXPECT_NONFATAL_FAILURE(statement, substr) \
+  do {\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \
+        (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter:: \
+          INTERCEPT_ONLY_CURRENT_THREAD, &gtest_failures);\
+      if (::testing::internal::AlwaysTrue()) { statement; }\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
+  do {\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \
+        (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \
+          &gtest_failures);\
+      if (::testing::internal::AlwaysTrue()) { statement; }\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_SPI_H_
diff --git a/third_party/googletest/googletest/include/gtest/gtest-test-part.h b/third_party/googletest/googletest/include/gtest/gtest-test-part.h
new file mode 100644
index 0000000..77eb844
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/gtest-test-part.h
@@ -0,0 +1,179 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: mheule@google.com (Markus Heule)
+//
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
+#define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
+
+#include <iosfwd>
+#include <vector>
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
+
+namespace testing {
+
+// A copyable object representing the result of a test part (i.e. an
+// assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()).
+//
+// Don't inherit from TestPartResult as its destructor is not virtual.
+class GTEST_API_ TestPartResult {
+ public:
+  // The possible outcomes of a test part (i.e. an assertion or an
+  // explicit SUCCEED(), FAIL(), or ADD_FAILURE()).
+  enum Type {
+    kSuccess,          // Succeeded.
+    kNonFatalFailure,  // Failed but the test can continue.
+    kFatalFailure      // Failed and the test should be terminated.
+  };
+
+  // C'tor.  TestPartResult does NOT have a default constructor.
+  // Always use this constructor (with parameters) to create a
+  // TestPartResult object.
+  TestPartResult(Type a_type,
+                 const char* a_file_name,
+                 int a_line_number,
+                 const char* a_message)
+      : type_(a_type),
+        file_name_(a_file_name == NULL ? "" : a_file_name),
+        line_number_(a_line_number),
+        summary_(ExtractSummary(a_message)),
+        message_(a_message) {
+  }
+
+  // Gets the outcome of the test part.
+  Type type() const { return type_; }
+
+  // Gets the name of the source file where the test part took place, or
+  // NULL if it's unknown.
+  const char* file_name() const {
+    return file_name_.empty() ? NULL : file_name_.c_str();
+  }
+
+  // Gets the line in the source file where the test part took place,
+  // or -1 if it's unknown.
+  int line_number() const { return line_number_; }
+
+  // Gets the summary of the failure message.
+  const char* summary() const { return summary_.c_str(); }
+
+  // Gets the message associated with the test part.
+  const char* message() const { return message_.c_str(); }
+
+  // Returns true iff the test part passed.
+  bool passed() const { return type_ == kSuccess; }
+
+  // Returns true iff the test part failed.
+  bool failed() const { return type_ != kSuccess; }
+
+  // Returns true iff the test part non-fatally failed.
+  bool nonfatally_failed() const { return type_ == kNonFatalFailure; }
+
+  // Returns true iff the test part fatally failed.
+  bool fatally_failed() const { return type_ == kFatalFailure; }
+
+ private:
+  Type type_;
+
+  // Gets the summary of the failure message by omitting the stack
+  // trace in it.
+  static std::string ExtractSummary(const char* message);
+
+  // The name of the source file where the test part took place, or
+  // "" if the source file is unknown.
+  std::string file_name_;
+  // The line in the source file where the test part took place, or -1
+  // if the line number is unknown.
+  int line_number_;
+  std::string summary_;  // The test failure summary.
+  std::string message_;  // The test failure message.
+};
+
+// Prints a TestPartResult object.
+std::ostream& operator<<(std::ostream& os, const TestPartResult& result);
+
+// An array of TestPartResult objects.
+//
+// Don't inherit from TestPartResultArray as its destructor is not
+// virtual.
+class GTEST_API_ TestPartResultArray {
+ public:
+  TestPartResultArray() {}
+
+  // Appends the given TestPartResult to the array.
+  void Append(const TestPartResult& result);
+
+  // Returns the TestPartResult at the given index (0-based).
+  const TestPartResult& GetTestPartResult(int index) const;
+
+  // Returns the number of TestPartResult objects in the array.
+  int size() const;
+
+ private:
+  std::vector<TestPartResult> array_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray);
+};
+
+// This interface knows how to report a test part result.
+class TestPartResultReporterInterface {
+ public:
+  virtual ~TestPartResultReporterInterface() {}
+
+  virtual void ReportTestPartResult(const TestPartResult& result) = 0;
+};
+
+namespace internal {
+
+// This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a
+// statement generates new fatal failures. To do so it registers itself as the
+// current test part result reporter. Besides checking if fatal failures were
+// reported, it only delegates the reporting to the former result reporter.
+// The original result reporter is restored in the destructor.
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+class GTEST_API_ HasNewFatalFailureHelper
+    : public TestPartResultReporterInterface {
+ public:
+  HasNewFatalFailureHelper();
+  virtual ~HasNewFatalFailureHelper();
+  virtual void ReportTestPartResult(const TestPartResult& result);
+  bool has_new_fatal_failure() const { return has_new_fatal_failure_; }
+ private:
+  bool has_new_fatal_failure_;
+  TestPartResultReporterInterface* original_reporter_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper);
+};
+
+}  // namespace internal
+
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
diff --git a/third_party/googletest/googletest/include/gtest/gtest-typed-test.h b/third_party/googletest/googletest/include/gtest/gtest-typed-test.h
new file mode 100644
index 0000000..5f69d56
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/gtest-typed-test.h
@@ -0,0 +1,263 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
+
+// This header implements typed tests and type-parameterized tests.
+
+// Typed (aka type-driven) tests repeat the same test for types in a
+// list.  You must know which types you want to test with when writing
+// typed tests. Here's how you do it:
+
+#if 0
+
+// First, define a fixture class template.  It should be parameterized
+// by a type.  Remember to derive it from testing::Test.
+template <typename T>
+class FooTest : public testing::Test {
+ public:
+  ...
+  typedef std::list<T> List;
+  static T shared_;
+  T value_;
+};
+
+// Next, associate a list of types with the test case, which will be
+// repeated for each type in the list.  The typedef is necessary for
+// the macro to parse correctly.
+typedef testing::Types<char, int, unsigned int> MyTypes;
+TYPED_TEST_CASE(FooTest, MyTypes);
+
+// If the type list contains only one type, you can write that type
+// directly without Types<...>:
+//   TYPED_TEST_CASE(FooTest, int);
+
+// Then, use TYPED_TEST() instead of TEST_F() to define as many typed
+// tests for this test case as you want.
+TYPED_TEST(FooTest, DoesBlah) {
+  // Inside a test, refer to TypeParam to get the type parameter.
+  // Since we are inside a derived class template, C++ requires use to
+  // visit the members of FooTest via 'this'.
+  TypeParam n = this->value_;
+
+  // To visit static members of the fixture, add the TestFixture::
+  // prefix.
+  n += TestFixture::shared_;
+
+  // To refer to typedefs in the fixture, add the "typename
+  // TestFixture::" prefix.
+  typename TestFixture::List values;
+  values.push_back(n);
+  ...
+}
+
+TYPED_TEST(FooTest, HasPropertyA) { ... }
+
+#endif  // 0
+
+// Type-parameterized tests are abstract test patterns parameterized
+// by a type.  Compared with typed tests, type-parameterized tests
+// allow you to define the test pattern without knowing what the type
+// parameters are.  The defined pattern can be instantiated with
+// different types any number of times, in any number of translation
+// units.
+//
+// If you are designing an interface or concept, you can define a
+// suite of type-parameterized tests to verify properties that any
+// valid implementation of the interface/concept should have.  Then,
+// each implementation can easily instantiate the test suite to verify
+// that it conforms to the requirements, without having to write
+// similar tests repeatedly.  Here's an example:
+
+#if 0
+
+// First, define a fixture class template.  It should be parameterized
+// by a type.  Remember to derive it from testing::Test.
+template <typename T>
+class FooTest : public testing::Test {
+  ...
+};
+
+// Next, declare that you will define a type-parameterized test case
+// (the _P suffix is for "parameterized" or "pattern", whichever you
+// prefer):
+TYPED_TEST_CASE_P(FooTest);
+
+// Then, use TYPED_TEST_P() to define as many type-parameterized tests
+// for this type-parameterized test case as you want.
+TYPED_TEST_P(FooTest, DoesBlah) {
+  // Inside a test, refer to TypeParam to get the type parameter.
+  TypeParam n = 0;
+  ...
+}
+
+TYPED_TEST_P(FooTest, HasPropertyA) { ... }
+
+// Now the tricky part: you need to register all test patterns before
+// you can instantiate them.  The first argument of the macro is the
+// test case name; the rest are the names of the tests in this test
+// case.
+REGISTER_TYPED_TEST_CASE_P(FooTest,
+                           DoesBlah, HasPropertyA);
+
+// Finally, you are free to instantiate the pattern with the types you
+// want.  If you put the above code in a header file, you can #include
+// it in multiple C++ source files and instantiate it multiple times.
+//
+// To distinguish different instances of the pattern, the first
+// argument to the INSTANTIATE_* macro is a prefix that will be added
+// to the actual test case name.  Remember to pick unique prefixes for
+// different instances.
+typedef testing::Types<char, int, unsigned int> MyTypes;
+INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
+
+// If the type list contains only one type, you can write that type
+// directly without Types<...>:
+//   INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int);
+
+#endif  // 0
+
+#include "gtest/internal/gtest-port.h"
+#include "gtest/internal/gtest-type-util.h"
+
+// Implements typed tests.
+
+#if GTEST_HAS_TYPED_TEST
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Expands to the name of the typedef for the type parameters of the
+// given test case.
+# define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_
+
+// The 'Types' template argument below must have spaces around it
+// since some compilers may choke on '>>' when passing a template
+// instance (e.g. Types<int>)
+# define TYPED_TEST_CASE(CaseName, Types) \
+  typedef ::testing::internal::TypeList< Types >::type \
+      GTEST_TYPE_PARAMS_(CaseName)
+
+# define TYPED_TEST(CaseName, TestName) \
+  template <typename gtest_TypeParam_> \
+  class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
+      : public CaseName<gtest_TypeParam_> { \
+   private: \
+    typedef CaseName<gtest_TypeParam_> TestFixture; \
+    typedef gtest_TypeParam_ TypeParam; \
+    virtual void TestBody(); \
+  }; \
+  bool gtest_##CaseName##_##TestName##_registered_ GTEST_ATTRIBUTE_UNUSED_ = \
+      ::testing::internal::TypeParameterizedTest< \
+          CaseName, \
+          ::testing::internal::TemplateSel< \
+              GTEST_TEST_CLASS_NAME_(CaseName, TestName)>, \
+          GTEST_TYPE_PARAMS_(CaseName)>::Register(\
+              "", ::testing::internal::CodeLocation(__FILE__, __LINE__), \
+              #CaseName, #TestName, 0); \
+  template <typename gtest_TypeParam_> \
+  void GTEST_TEST_CLASS_NAME_(CaseName, TestName)<gtest_TypeParam_>::TestBody()
+
+#endif  // GTEST_HAS_TYPED_TEST
+
+// Implements type-parameterized tests.
+
+#if GTEST_HAS_TYPED_TEST_P
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Expands to the namespace name that the type-parameterized tests for
+// the given type-parameterized test case are defined in.  The exact
+// name of the namespace is subject to change without notice.
+# define GTEST_CASE_NAMESPACE_(TestCaseName) \
+  gtest_case_##TestCaseName##_
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Expands to the name of the variable used to remember the names of
+// the defined tests in the given test case.
+# define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \
+  gtest_typed_test_case_p_state_##TestCaseName##_
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY.
+//
+// Expands to the name of the variable used to remember the names of
+// the registered tests in the given test case.
+# define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \
+  gtest_registered_test_names_##TestCaseName##_
+
+// The variables defined in the type-parameterized test macros are
+// static as typically these macros are used in a .h file that can be
+// #included in multiple translation units linked together.
+# define TYPED_TEST_CASE_P(CaseName) \
+  static ::testing::internal::TypedTestCasePState \
+      GTEST_TYPED_TEST_CASE_P_STATE_(CaseName)
+
+# define TYPED_TEST_P(CaseName, TestName) \
+  namespace GTEST_CASE_NAMESPACE_(CaseName) { \
+  template <typename gtest_TypeParam_> \
+  class TestName : public CaseName<gtest_TypeParam_> { \
+   private: \
+    typedef CaseName<gtest_TypeParam_> TestFixture; \
+    typedef gtest_TypeParam_ TypeParam; \
+    virtual void TestBody(); \
+  }; \
+  static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \
+      GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).AddTestName(\
+          __FILE__, __LINE__, #CaseName, #TestName); \
+  } \
+  template <typename gtest_TypeParam_> \
+  void GTEST_CASE_NAMESPACE_(CaseName)::TestName<gtest_TypeParam_>::TestBody()
+
+# define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \
+  namespace GTEST_CASE_NAMESPACE_(CaseName) { \
+  typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \
+  } \
+  static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) = \
+      GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\
+          __FILE__, __LINE__, #__VA_ARGS__)
+
+// The 'Types' template argument below must have spaces around it
+// since some compilers may choke on '>>' when passing a template
+// instance (e.g. Types<int>)
+# define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \
+  bool gtest_##Prefix##_##CaseName GTEST_ATTRIBUTE_UNUSED_ = \
+      ::testing::internal::TypeParameterizedTestCase<CaseName, \
+          GTEST_CASE_NAMESPACE_(CaseName)::gtest_AllTests_, \
+          ::testing::internal::TypeList< Types >::type>::Register(\
+              #Prefix, \
+              ::testing::internal::CodeLocation(__FILE__, __LINE__), \
+              &GTEST_TYPED_TEST_CASE_P_STATE_(CaseName), \
+              #CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName))
+
+#endif  // GTEST_HAS_TYPED_TEST_P
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
diff --git a/third_party/googletest/googletest/include/gtest/gtest.h b/third_party/googletest/googletest/include/gtest/gtest.h
new file mode 100644
index 0000000..7b59c49
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/gtest.h
@@ -0,0 +1,2240 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines the public API for Google Test.  It should be
+// included by any test program that uses Google Test.
+//
+// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
+// leave some internal implementation details in this header file.
+// They are clearly marked by comments like this:
+//
+//   // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+//
+// Such code is NOT meant to be used by a user directly, and is subject
+// to CHANGE WITHOUT NOTICE.  Therefore DO NOT DEPEND ON IT in a user
+// program!
+//
+// Acknowledgment: Google Test borrowed the idea of automatic test
+// registration from Barthelemy Dagenais' (barthelemy@prologique.com)
+// easyUnit framework.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_H_
+
+#include <limits>
+#include <ostream>
+#include <vector>
+
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
+#include "gtest/gtest-death-test.h"
+#include "gtest/gtest-message.h"
+#include "gtest/gtest-param-test.h"
+#include "gtest/gtest-printers.h"
+#include "gtest/gtest_prod.h"
+#include "gtest/gtest-test-part.h"
+#include "gtest/gtest-typed-test.h"
+
+// Depending on the platform, different string classes are available.
+// On Linux, in addition to ::std::string, Google also makes use of
+// class ::string, which has the same interface as ::std::string, but
+// has a different implementation.
+//
+// You can define GTEST_HAS_GLOBAL_STRING to 1 to indicate that
+// ::string is available AND is a distinct type to ::std::string, or
+// define it to 0 to indicate otherwise.
+//
+// If ::std::string and ::string are the same class on your platform
+// due to aliasing, you should define GTEST_HAS_GLOBAL_STRING to 0.
+//
+// If you do not define GTEST_HAS_GLOBAL_STRING, it is defined
+// heuristically.
+
+namespace testing {
+
+// Declares the flags.
+
+// This flag temporary enables the disabled tests.
+GTEST_DECLARE_bool_(also_run_disabled_tests);
+
+// This flag brings the debugger on an assertion failure.
+GTEST_DECLARE_bool_(break_on_failure);
+
+// This flag controls whether Google Test catches all test-thrown exceptions
+// and logs them as failures.
+GTEST_DECLARE_bool_(catch_exceptions);
+
+// This flag enables using colors in terminal output. Available values are
+// "yes" to enable colors, "no" (disable colors), or "auto" (the default)
+// to let Google Test decide.
+GTEST_DECLARE_string_(color);
+
+// This flag sets up the filter to select by name using a glob pattern
+// the tests to run. If the filter is not given all tests are executed.
+GTEST_DECLARE_string_(filter);
+
+// This flag causes the Google Test to list tests. None of the tests listed
+// are actually run if the flag is provided.
+GTEST_DECLARE_bool_(list_tests);
+
+// This flag controls whether Google Test emits a detailed XML report to a file
+// in addition to its normal textual output.
+GTEST_DECLARE_string_(output);
+
+// This flags control whether Google Test prints the elapsed time for each
+// test.
+GTEST_DECLARE_bool_(print_time);
+
+// This flag specifies the random number seed.
+GTEST_DECLARE_int32_(random_seed);
+
+// This flag sets how many times the tests are repeated. The default value
+// is 1. If the value is -1 the tests are repeating forever.
+GTEST_DECLARE_int32_(repeat);
+
+// This flag controls whether Google Test includes Google Test internal
+// stack frames in failure stack traces.
+GTEST_DECLARE_bool_(show_internal_stack_frames);
+
+// When this flag is specified, tests' order is randomized on every iteration.
+GTEST_DECLARE_bool_(shuffle);
+
+// This flag specifies the maximum number of stack frames to be
+// printed in a failure message.
+GTEST_DECLARE_int32_(stack_trace_depth);
+
+// When this flag is specified, a failed assertion will throw an
+// exception if exceptions are enabled, or exit the program with a
+// non-zero code otherwise.
+GTEST_DECLARE_bool_(throw_on_failure);
+
+// When this flag is set with a "host:port" string, on supported
+// platforms test results are streamed to the specified port on
+// the specified host machine.
+GTEST_DECLARE_string_(stream_result_to);
+
+// The upper limit for valid stack trace depths.
+const int kMaxStackTraceDepth = 100;
+
+namespace internal {
+
+class AssertHelper;
+class DefaultGlobalTestPartResultReporter;
+class ExecDeathTest;
+class NoExecDeathTest;
+class FinalSuccessChecker;
+class GTestFlagSaver;
+class StreamingListenerTest;
+class TestResultAccessor;
+class TestEventListenersAccessor;
+class TestEventRepeater;
+class UnitTestRecordPropertyTestHelper;
+class WindowsDeathTest;
+class UnitTestImpl* GetUnitTestImpl();
+void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
+                                    const std::string& message);
+
+}  // namespace internal
+
+// The friend relationship of some of these classes is cyclic.
+// If we don't forward declare them the compiler might confuse the classes
+// in friendship clauses with same named classes on the scope.
+class Test;
+class TestCase;
+class TestInfo;
+class UnitTest;
+
+// A class for indicating whether an assertion was successful.  When
+// the assertion wasn't successful, the AssertionResult object
+// remembers a non-empty message that describes how it failed.
+//
+// To create an instance of this class, use one of the factory functions
+// (AssertionSuccess() and AssertionFailure()).
+//
+// This class is useful for two purposes:
+//   1. Defining predicate functions to be used with Boolean test assertions
+//      EXPECT_TRUE/EXPECT_FALSE and their ASSERT_ counterparts
+//   2. Defining predicate-format functions to be
+//      used with predicate assertions (ASSERT_PRED_FORMAT*, etc).
+//
+// For example, if you define IsEven predicate:
+//
+//   testing::AssertionResult IsEven(int n) {
+//     if ((n % 2) == 0)
+//       return testing::AssertionSuccess();
+//     else
+//       return testing::AssertionFailure() << n << " is odd";
+//   }
+//
+// Then the failed expectation EXPECT_TRUE(IsEven(Fib(5)))
+// will print the message
+//
+//   Value of: IsEven(Fib(5))
+//     Actual: false (5 is odd)
+//   Expected: true
+//
+// instead of a more opaque
+//
+//   Value of: IsEven(Fib(5))
+//     Actual: false
+//   Expected: true
+//
+// in case IsEven is a simple Boolean predicate.
+//
+// If you expect your predicate to be reused and want to support informative
+// messages in EXPECT_FALSE and ASSERT_FALSE (negative assertions show up
+// about half as often as positive ones in our tests), supply messages for
+// both success and failure cases:
+//
+//   testing::AssertionResult IsEven(int n) {
+//     if ((n % 2) == 0)
+//       return testing::AssertionSuccess() << n << " is even";
+//     else
+//       return testing::AssertionFailure() << n << " is odd";
+//   }
+//
+// Then a statement EXPECT_FALSE(IsEven(Fib(6))) will print
+//
+//   Value of: IsEven(Fib(6))
+//     Actual: true (8 is even)
+//   Expected: false
+//
+// NB: Predicates that support negative Boolean assertions have reduced
+// performance in positive ones so be careful not to use them in tests
+// that have lots (tens of thousands) of positive Boolean assertions.
+//
+// To use this class with EXPECT_PRED_FORMAT assertions such as:
+//
+//   // Verifies that Foo() returns an even number.
+//   EXPECT_PRED_FORMAT1(IsEven, Foo());
+//
+// you need to define:
+//
+//   testing::AssertionResult IsEven(const char* expr, int n) {
+//     if ((n % 2) == 0)
+//       return testing::AssertionSuccess();
+//     else
+//       return testing::AssertionFailure()
+//         << "Expected: " << expr << " is even\n  Actual: it's " << n;
+//   }
+//
+// If Foo() returns 5, you will see the following message:
+//
+//   Expected: Foo() is even
+//     Actual: it's 5
+//
+class GTEST_API_ AssertionResult {
+ public:
+  // Copy constructor.
+  // Used in EXPECT_TRUE/FALSE(assertion_result).
+  AssertionResult(const AssertionResult& other);
+
+  GTEST_DISABLE_MSC_WARNINGS_PUSH_(4800 /* forcing value to bool */)
+
+  // Used in the EXPECT_TRUE/FALSE(bool_expression).
+  //
+  // T must be contextually convertible to bool.
+  //
+  // The second parameter prevents this overload from being considered if
+  // the argument is implicitly convertible to AssertionResult. In that case
+  // we want AssertionResult's copy constructor to be used.
+  template <typename T>
+  explicit AssertionResult(
+      const T& success,
+      typename internal::EnableIf<
+          !internal::ImplicitlyConvertible<T, AssertionResult>::value>::type*
+          /*enabler*/ = NULL)
+      : success_(success) {}
+
+  GTEST_DISABLE_MSC_WARNINGS_POP_()
+
+  // Assignment operator.
+  AssertionResult& operator=(AssertionResult other) {
+    swap(other);
+    return *this;
+  }
+
+  // Returns true iff the assertion succeeded.
+  operator bool() const { return success_; }  // NOLINT
+
+  // Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
+  AssertionResult operator!() const;
+
+  // Returns the text streamed into this AssertionResult. Test assertions
+  // use it when they fail (i.e., the predicate's outcome doesn't match the
+  // assertion's expectation). When nothing has been streamed into the
+  // object, returns an empty string.
+  const char* message() const {
+    return message_.get() != NULL ?  message_->c_str() : "";
+  }
+  // TODO(vladl@google.com): Remove this after making sure no clients use it.
+  // Deprecated; please use message() instead.
+  const char* failure_message() const { return message(); }
+
+  // Streams a custom failure message into this object.
+  template <typename T> AssertionResult& operator<<(const T& value) {
+    AppendMessage(Message() << value);
+    return *this;
+  }
+
+  // Allows streaming basic output manipulators such as endl or flush into
+  // this object.
+  AssertionResult& operator<<(
+      ::std::ostream& (*basic_manipulator)(::std::ostream& stream)) {
+    AppendMessage(Message() << basic_manipulator);
+    return *this;
+  }
+
+ private:
+  // Appends the contents of message to message_.
+  void AppendMessage(const Message& a_message) {
+    if (message_.get() == NULL)
+      message_.reset(new ::std::string);
+    message_->append(a_message.GetString().c_str());
+  }
+
+  // Swap the contents of this AssertionResult with other.
+  void swap(AssertionResult& other);
+
+  // Stores result of the assertion predicate.
+  bool success_;
+  // Stores the message describing the condition in case the expectation
+  // construct is not satisfied with the predicate's outcome.
+  // Referenced via a pointer to avoid taking too much stack frame space
+  // with test assertions.
+  internal::scoped_ptr< ::std::string> message_;
+};
+
+// Makes a successful assertion result.
+GTEST_API_ AssertionResult AssertionSuccess();
+
+// Makes a failed assertion result.
+GTEST_API_ AssertionResult AssertionFailure();
+
+// Makes a failed assertion result with the given failure message.
+// Deprecated; use AssertionFailure() << msg.
+GTEST_API_ AssertionResult AssertionFailure(const Message& msg);
+
+// The abstract class that all tests inherit from.
+//
+// In Google Test, a unit test program contains one or many TestCases, and
+// each TestCase contains one or many Tests.
+//
+// When you define a test using the TEST macro, you don't need to
+// explicitly derive from Test - the TEST macro automatically does
+// this for you.
+//
+// The only time you derive from Test is when defining a test fixture
+// to be used a TEST_F.  For example:
+//
+//   class FooTest : public testing::Test {
+//    protected:
+//     void SetUp() override { ... }
+//     void TearDown() override { ... }
+//     ...
+//   };
+//
+//   TEST_F(FooTest, Bar) { ... }
+//   TEST_F(FooTest, Baz) { ... }
+//
+// Test is not copyable.
+class GTEST_API_ Test {
+ public:
+  friend class TestInfo;
+
+  // Defines types for pointers to functions that set up and tear down
+  // a test case.
+  typedef internal::SetUpTestCaseFunc SetUpTestCaseFunc;
+  typedef internal::TearDownTestCaseFunc TearDownTestCaseFunc;
+
+  // The d'tor is virtual as we intend to inherit from Test.
+  virtual ~Test();
+
+  // Sets up the stuff shared by all tests in this test case.
+  //
+  // Google Test will call Foo::SetUpTestCase() before running the first
+  // test in test case Foo.  Hence a sub-class can define its own
+  // SetUpTestCase() method to shadow the one defined in the super
+  // class.
+  static void SetUpTestCase() {}
+
+  // Tears down the stuff shared by all tests in this test case.
+  //
+  // Google Test will call Foo::TearDownTestCase() after running the last
+  // test in test case Foo.  Hence a sub-class can define its own
+  // TearDownTestCase() method to shadow the one defined in the super
+  // class.
+  static void TearDownTestCase() {}
+
+  // Returns true iff the current test has a fatal failure.
+  static bool HasFatalFailure();
+
+  // Returns true iff the current test has a non-fatal failure.
+  static bool HasNonfatalFailure();
+
+  // Returns true iff the current test has a (either fatal or
+  // non-fatal) failure.
+  static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailure(); }
+
+  // Logs a property for the current test, test case, or for the entire
+  // invocation of the test program when used outside of the context of a
+  // test case.  Only the last value for a given key is remembered.  These
+  // are public static so they can be called from utility functions that are
+  // not members of the test fixture.  Calls to RecordProperty made during
+  // lifespan of the test (from the moment its constructor starts to the
+  // moment its destructor finishes) will be output in XML as attributes of
+  // the <testcase> element.  Properties recorded from fixture's
+  // SetUpTestCase or TearDownTestCase are logged as attributes of the
+  // corresponding <testsuite> element.  Calls to RecordProperty made in the
+  // global context (before or after invocation of RUN_ALL_TESTS and from
+  // SetUp/TearDown method of Environment objects registered with Google
+  // Test) will be output as attributes of the <testsuites> element.
+  static void RecordProperty(const std::string& key, const std::string& value);
+  static void RecordProperty(const std::string& key, int value);
+
+ protected:
+  // Creates a Test object.
+  Test();
+
+  // Sets up the test fixture.
+  virtual void SetUp();
+
+  // Tears down the test fixture.
+  virtual void TearDown();
+
+ private:
+  // Returns true iff the current test has the same fixture class as
+  // the first test in the current test case.
+  static bool HasSameFixtureClass();
+
+  // Runs the test after the test fixture has been set up.
+  //
+  // A sub-class must implement this to define the test logic.
+  //
+  // DO NOT OVERRIDE THIS FUNCTION DIRECTLY IN A USER PROGRAM.
+  // Instead, use the TEST or TEST_F macro.
+  virtual void TestBody() = 0;
+
+  // Sets up, executes, and tears down the test.
+  void Run();
+
+  // Deletes self.  We deliberately pick an unusual name for this
+  // internal method to avoid clashing with names used in user TESTs.
+  void DeleteSelf_() { delete this; }
+
+  const internal::scoped_ptr< GTEST_FLAG_SAVER_ > gtest_flag_saver_;
+
+  // Often a user misspells SetUp() as Setup() and spends a long time
+  // wondering why it is never called by Google Test.  The declaration of
+  // the following method is solely for catching such an error at
+  // compile time:
+  //
+  //   - The return type is deliberately chosen to be not void, so it
+  //   will be a conflict if void Setup() is declared in the user's
+  //   test fixture.
+  //
+  //   - This method is private, so it will be another compiler error
+  //   if the method is called from the user's test fixture.
+  //
+  // DO NOT OVERRIDE THIS FUNCTION.
+  //
+  // If you see an error about overriding the following function or
+  // about it being private, you have mis-spelled SetUp() as Setup().
+  struct Setup_should_be_spelled_SetUp {};
+  virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; }
+
+  // We disallow copying Tests.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Test);
+};
+
+typedef internal::TimeInMillis TimeInMillis;
+
+// A copyable object representing a user specified test property which can be
+// output as a key/value string pair.
+//
+// Don't inherit from TestProperty as its destructor is not virtual.
+class TestProperty {
+ public:
+  // C'tor.  TestProperty does NOT have a default constructor.
+  // Always use this constructor (with parameters) to create a
+  // TestProperty object.
+  TestProperty(const std::string& a_key, const std::string& a_value) :
+    key_(a_key), value_(a_value) {
+  }
+
+  // Gets the user supplied key.
+  const char* key() const {
+    return key_.c_str();
+  }
+
+  // Gets the user supplied value.
+  const char* value() const {
+    return value_.c_str();
+  }
+
+  // Sets a new value, overriding the one supplied in the constructor.
+  void SetValue(const std::string& new_value) {
+    value_ = new_value;
+  }
+
+ private:
+  // The key supplied by the user.
+  std::string key_;
+  // The value supplied by the user.
+  std::string value_;
+};
+
+// The result of a single Test.  This includes a list of
+// TestPartResults, a list of TestProperties, a count of how many
+// death tests there are in the Test, and how much time it took to run
+// the Test.
+//
+// TestResult is not copyable.
+class GTEST_API_ TestResult {
+ public:
+  // Creates an empty TestResult.
+  TestResult();
+
+  // D'tor.  Do not inherit from TestResult.
+  ~TestResult();
+
+  // Gets the number of all test parts.  This is the sum of the number
+  // of successful test parts and the number of failed test parts.
+  int total_part_count() const;
+
+  // Returns the number of the test properties.
+  int test_property_count() const;
+
+  // Returns true iff the test passed (i.e. no test part failed).
+  bool Passed() const { return !Failed(); }
+
+  // Returns true iff the test failed.
+  bool Failed() const;
+
+  // Returns true iff the test fatally failed.
+  bool HasFatalFailure() const;
+
+  // Returns true iff the test has a non-fatal failure.
+  bool HasNonfatalFailure() const;
+
+  // Returns the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+  // Returns the i-th test part result among all the results. i can range
+  // from 0 to test_property_count() - 1. If i is not in that range, aborts
+  // the program.
+  const TestPartResult& GetTestPartResult(int i) const;
+
+  // Returns the i-th test property. i can range from 0 to
+  // test_property_count() - 1. If i is not in that range, aborts the
+  // program.
+  const TestProperty& GetTestProperty(int i) const;
+
+ private:
+  friend class TestInfo;
+  friend class TestCase;
+  friend class UnitTest;
+  friend class internal::DefaultGlobalTestPartResultReporter;
+  friend class internal::ExecDeathTest;
+  friend class internal::TestResultAccessor;
+  friend class internal::UnitTestImpl;
+  friend class internal::WindowsDeathTest;
+
+  // Gets the vector of TestPartResults.
+  const std::vector<TestPartResult>& test_part_results() const {
+    return test_part_results_;
+  }
+
+  // Gets the vector of TestProperties.
+  const std::vector<TestProperty>& test_properties() const {
+    return test_properties_;
+  }
+
+  // Sets the elapsed time.
+  void set_elapsed_time(TimeInMillis elapsed) { elapsed_time_ = elapsed; }
+
+  // Adds a test property to the list. The property is validated and may add
+  // a non-fatal failure if invalid (e.g., if it conflicts with reserved
+  // key names). If a property is already recorded for the same key, the
+  // value will be updated, rather than storing multiple values for the same
+  // key.  xml_element specifies the element for which the property is being
+  // recorded and is used for validation.
+  void RecordProperty(const std::string& xml_element,
+                      const TestProperty& test_property);
+
+  // Adds a failure if the key is a reserved attribute of Google Test
+  // testcase tags.  Returns true if the property is valid.
+  // TODO(russr): Validate attribute names are legal and human readable.
+  static bool ValidateTestProperty(const std::string& xml_element,
+                                   const TestProperty& test_property);
+
+  // Adds a test part result to the list.
+  void AddTestPartResult(const TestPartResult& test_part_result);
+
+  // Returns the death test count.
+  int death_test_count() const { return death_test_count_; }
+
+  // Increments the death test count, returning the new count.
+  int increment_death_test_count() { return ++death_test_count_; }
+
+  // Clears the test part results.
+  void ClearTestPartResults();
+
+  // Clears the object.
+  void Clear();
+
+  // Protects mutable state of the property vector and of owned
+  // properties, whose values may be updated.
+  internal::Mutex test_properites_mutex_;
+
+  // The vector of TestPartResults
+  std::vector<TestPartResult> test_part_results_;
+  // The vector of TestProperties
+  std::vector<TestProperty> test_properties_;
+  // Running count of death tests.
+  int death_test_count_;
+  // The elapsed time, in milliseconds.
+  TimeInMillis elapsed_time_;
+
+  // We disallow copying TestResult.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestResult);
+};  // class TestResult
+
+// A TestInfo object stores the following information about a test:
+//
+//   Test case name
+//   Test name
+//   Whether the test should be run
+//   A function pointer that creates the test object when invoked
+//   Test result
+//
+// The constructor of TestInfo registers itself with the UnitTest
+// singleton such that the RUN_ALL_TESTS() macro knows which tests to
+// run.
+class GTEST_API_ TestInfo {
+ public:
+  // Destructs a TestInfo object.  This function is not virtual, so
+  // don't inherit from TestInfo.
+  ~TestInfo();
+
+  // Returns the test case name.
+  const char* test_case_name() const { return test_case_name_.c_str(); }
+
+  // Returns the test name.
+  const char* name() const { return name_.c_str(); }
+
+  // Returns the name of the parameter type, or NULL if this is not a typed
+  // or a type-parameterized test.
+  const char* type_param() const {
+    if (type_param_.get() != NULL)
+      return type_param_->c_str();
+    return NULL;
+  }
+
+  // Returns the text representation of the value parameter, or NULL if this
+  // is not a value-parameterized test.
+  const char* value_param() const {
+    if (value_param_.get() != NULL)
+      return value_param_->c_str();
+    return NULL;
+  }
+
+  // Returns the file name where this test is defined.
+  const char* file() const { return location_.file.c_str(); }
+
+  // Returns the line where this test is defined.
+  int line() const { return location_.line; }
+
+  // Returns true if this test should run, that is if the test is not
+  // disabled (or it is disabled but the also_run_disabled_tests flag has
+  // been specified) and its full name matches the user-specified filter.
+  //
+  // Google Test allows the user to filter the tests by their full names.
+  // The full name of a test Bar in test case Foo is defined as
+  // "Foo.Bar".  Only the tests that match the filter will run.
+  //
+  // A filter is a colon-separated list of glob (not regex) patterns,
+  // optionally followed by a '-' and a colon-separated list of
+  // negative patterns (tests to exclude).  A test is run if it
+  // matches one of the positive patterns and does not match any of
+  // the negative patterns.
+  //
+  // For example, *A*:Foo.* is a filter that matches any string that
+  // contains the character 'A' or starts with "Foo.".
+  bool should_run() const { return should_run_; }
+
+  // Returns true iff this test will appear in the XML report.
+  bool is_reportable() const {
+    // For now, the XML report includes all tests matching the filter.
+    // In the future, we may trim tests that are excluded because of
+    // sharding.
+    return matches_filter_;
+  }
+
+  // Returns the result of the test.
+  const TestResult* result() const { return &result_; }
+
+ private:
+#if GTEST_HAS_DEATH_TEST
+  friend class internal::DefaultDeathTestFactory;
+#endif  // GTEST_HAS_DEATH_TEST
+  friend class Test;
+  friend class TestCase;
+  friend class internal::UnitTestImpl;
+  friend class internal::StreamingListenerTest;
+  friend TestInfo* internal::MakeAndRegisterTestInfo(
+      const char* test_case_name,
+      const char* name,
+      const char* type_param,
+      const char* value_param,
+      internal::CodeLocation code_location,
+      internal::TypeId fixture_class_id,
+      Test::SetUpTestCaseFunc set_up_tc,
+      Test::TearDownTestCaseFunc tear_down_tc,
+      internal::TestFactoryBase* factory);
+
+  // Constructs a TestInfo object. The newly constructed instance assumes
+  // ownership of the factory object.
+  TestInfo(const std::string& test_case_name,
+           const std::string& name,
+           const char* a_type_param,   // NULL if not a type-parameterized test
+           const char* a_value_param,  // NULL if not a value-parameterized test
+           internal::CodeLocation a_code_location,
+           internal::TypeId fixture_class_id,
+           internal::TestFactoryBase* factory);
+
+  // Increments the number of death tests encountered in this test so
+  // far.
+  int increment_death_test_count() {
+    return result_.increment_death_test_count();
+  }
+
+  // Creates the test object, runs it, records its result, and then
+  // deletes it.
+  void Run();
+
+  static void ClearTestResult(TestInfo* test_info) {
+    test_info->result_.Clear();
+  }
+
+  // These fields are immutable properties of the test.
+  const std::string test_case_name_;     // Test case name
+  const std::string name_;               // Test name
+  // Name of the parameter type, or NULL if this is not a typed or a
+  // type-parameterized test.
+  const internal::scoped_ptr<const ::std::string> type_param_;
+  // Text representation of the value parameter, or NULL if this is not a
+  // value-parameterized test.
+  const internal::scoped_ptr<const ::std::string> value_param_;
+  internal::CodeLocation location_;
+  const internal::TypeId fixture_class_id_;   // ID of the test fixture class
+  bool should_run_;                 // True iff this test should run
+  bool is_disabled_;                // True iff this test is disabled
+  bool matches_filter_;             // True if this test matches the
+                                    // user-specified filter.
+  internal::TestFactoryBase* const factory_;  // The factory that creates
+                                              // the test object
+
+  // This field is mutable and needs to be reset before running the
+  // test for the second time.
+  TestResult result_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfo);
+};
+
+// A test case, which consists of a vector of TestInfos.
+//
+// TestCase is not copyable.
+class GTEST_API_ TestCase {
+ public:
+  // Creates a TestCase with the given name.
+  //
+  // TestCase does NOT have a default constructor.  Always use this
+  // constructor to create a TestCase object.
+  //
+  // Arguments:
+  //
+  //   name:         name of the test case
+  //   a_type_param: the name of the test's type parameter, or NULL if
+  //                 this is not a type-parameterized test.
+  //   set_up_tc:    pointer to the function that sets up the test case
+  //   tear_down_tc: pointer to the function that tears down the test case
+  TestCase(const char* name, const char* a_type_param,
+           Test::SetUpTestCaseFunc set_up_tc,
+           Test::TearDownTestCaseFunc tear_down_tc);
+
+  // Destructor of TestCase.
+  virtual ~TestCase();
+
+  // Gets the name of the TestCase.
+  const char* name() const { return name_.c_str(); }
+
+  // Returns the name of the parameter type, or NULL if this is not a
+  // type-parameterized test case.
+  const char* type_param() const {
+    if (type_param_.get() != NULL)
+      return type_param_->c_str();
+    return NULL;
+  }
+
+  // Returns true if any test in this test case should run.
+  bool should_run() const { return should_run_; }
+
+  // Gets the number of successful tests in this test case.
+  int successful_test_count() const;
+
+  // Gets the number of failed tests in this test case.
+  int failed_test_count() const;
+
+  // Gets the number of disabled tests that will be reported in the XML report.
+  int reportable_disabled_test_count() const;
+
+  // Gets the number of disabled tests in this test case.
+  int disabled_test_count() const;
+
+  // Gets the number of tests to be printed in the XML report.
+  int reportable_test_count() const;
+
+  // Get the number of tests in this test case that should run.
+  int test_to_run_count() const;
+
+  // Gets the number of all tests in this test case.
+  int total_test_count() const;
+
+  // Returns true iff the test case passed.
+  bool Passed() const { return !Failed(); }
+
+  // Returns true iff the test case failed.
+  bool Failed() const { return failed_test_count() > 0; }
+
+  // Returns the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+  // Returns the i-th test among all the tests. i can range from 0 to
+  // total_test_count() - 1. If i is not in that range, returns NULL.
+  const TestInfo* GetTestInfo(int i) const;
+
+  // Returns the TestResult that holds test properties recorded during
+  // execution of SetUpTestCase and TearDownTestCase.
+  const TestResult& ad_hoc_test_result() const { return ad_hoc_test_result_; }
+
+ private:
+  friend class Test;
+  friend class internal::UnitTestImpl;
+
+  // Gets the (mutable) vector of TestInfos in this TestCase.
+  std::vector<TestInfo*>& test_info_list() { return test_info_list_; }
+
+  // Gets the (immutable) vector of TestInfos in this TestCase.
+  const std::vector<TestInfo*>& test_info_list() const {
+    return test_info_list_;
+  }
+
+  // Returns the i-th test among all the tests. i can range from 0 to
+  // total_test_count() - 1. If i is not in that range, returns NULL.
+  TestInfo* GetMutableTestInfo(int i);
+
+  // Sets the should_run member.
+  void set_should_run(bool should) { should_run_ = should; }
+
+  // Adds a TestInfo to this test case.  Will delete the TestInfo upon
+  // destruction of the TestCase object.
+  void AddTestInfo(TestInfo * test_info);
+
+  // Clears the results of all tests in this test case.
+  void ClearResult();
+
+  // Clears the results of all tests in the given test case.
+  static void ClearTestCaseResult(TestCase* test_case) {
+    test_case->ClearResult();
+  }
+
+  // Runs every test in this TestCase.
+  void Run();
+
+  // Runs SetUpTestCase() for this TestCase.  This wrapper is needed
+  // for catching exceptions thrown from SetUpTestCase().
+  void RunSetUpTestCase() { (*set_up_tc_)(); }
+
+  // Runs TearDownTestCase() for this TestCase.  This wrapper is
+  // needed for catching exceptions thrown from TearDownTestCase().
+  void RunTearDownTestCase() { (*tear_down_tc_)(); }
+
+  // Returns true iff test passed.
+  static bool TestPassed(const TestInfo* test_info) {
+    return test_info->should_run() && test_info->result()->Passed();
+  }
+
+  // Returns true iff test failed.
+  static bool TestFailed(const TestInfo* test_info) {
+    return test_info->should_run() && test_info->result()->Failed();
+  }
+
+  // Returns true iff the test is disabled and will be reported in the XML
+  // report.
+  static bool TestReportableDisabled(const TestInfo* test_info) {
+    return test_info->is_reportable() && test_info->is_disabled_;
+  }
+
+  // Returns true iff test is disabled.
+  static bool TestDisabled(const TestInfo* test_info) {
+    return test_info->is_disabled_;
+  }
+
+  // Returns true iff this test will appear in the XML report.
+  static bool TestReportable(const TestInfo* test_info) {
+    return test_info->is_reportable();
+  }
+
+  // Returns true if the given test should run.
+  static bool ShouldRunTest(const TestInfo* test_info) {
+    return test_info->should_run();
+  }
+
+  // Shuffles the tests in this test case.
+  void ShuffleTests(internal::Random* random);
+
+  // Restores the test order to before the first shuffle.
+  void UnshuffleTests();
+
+  // Name of the test case.
+  std::string name_;
+  // Name of the parameter type, or NULL if this is not a typed or a
+  // type-parameterized test.
+  const internal::scoped_ptr<const ::std::string> type_param_;
+  // The vector of TestInfos in their original order.  It owns the
+  // elements in the vector.
+  std::vector<TestInfo*> test_info_list_;
+  // Provides a level of indirection for the test list to allow easy
+  // shuffling and restoring the test order.  The i-th element in this
+  // vector is the index of the i-th test in the shuffled test list.
+  std::vector<int> test_indices_;
+  // Pointer to the function that sets up the test case.
+  Test::SetUpTestCaseFunc set_up_tc_;
+  // Pointer to the function that tears down the test case.
+  Test::TearDownTestCaseFunc tear_down_tc_;
+  // True iff any test in this test case should run.
+  bool should_run_;
+  // Elapsed time, in milliseconds.
+  TimeInMillis elapsed_time_;
+  // Holds test properties recorded during execution of SetUpTestCase and
+  // TearDownTestCase.
+  TestResult ad_hoc_test_result_;
+
+  // We disallow copying TestCases.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestCase);
+};
+
+// An Environment object is capable of setting up and tearing down an
+// environment.  You should subclass this to define your own
+// environment(s).
+//
+// An Environment object does the set-up and tear-down in virtual
+// methods SetUp() and TearDown() instead of the constructor and the
+// destructor, as:
+//
+//   1. You cannot safely throw from a destructor.  This is a problem
+//      as in some cases Google Test is used where exceptions are enabled, and
+//      we may want to implement ASSERT_* using exceptions where they are
+//      available.
+//   2. You cannot use ASSERT_* directly in a constructor or
+//      destructor.
+class Environment {
+ public:
+  // The d'tor is virtual as we need to subclass Environment.
+  virtual ~Environment() {}
+
+  // Override this to define how to set up the environment.
+  virtual void SetUp() {}
+
+  // Override this to define how to tear down the environment.
+  virtual void TearDown() {}
+ private:
+  // If you see an error about overriding the following function or
+  // about it being private, you have mis-spelled SetUp() as Setup().
+  struct Setup_should_be_spelled_SetUp {};
+  virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; }
+};
+
+// The interface for tracing execution of tests. The methods are organized in
+// the order the corresponding events are fired.
+class TestEventListener {
+ public:
+  virtual ~TestEventListener() {}
+
+  // Fired before any test activity starts.
+  virtual void OnTestProgramStart(const UnitTest& unit_test) = 0;
+
+  // Fired before each iteration of tests starts.  There may be more than
+  // one iteration if GTEST_FLAG(repeat) is set. iteration is the iteration
+  // index, starting from 0.
+  virtual void OnTestIterationStart(const UnitTest& unit_test,
+                                    int iteration) = 0;
+
+  // Fired before environment set-up for each iteration of tests starts.
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) = 0;
+
+  // Fired after environment set-up for each iteration of tests ends.
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) = 0;
+
+  // Fired before the test case starts.
+  virtual void OnTestCaseStart(const TestCase& test_case) = 0;
+
+  // Fired before the test starts.
+  virtual void OnTestStart(const TestInfo& test_info) = 0;
+
+  // Fired after a failed assertion or a SUCCEED() invocation.
+  virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0;
+
+  // Fired after the test ends.
+  virtual void OnTestEnd(const TestInfo& test_info) = 0;
+
+  // Fired after the test case ends.
+  virtual void OnTestCaseEnd(const TestCase& test_case) = 0;
+
+  // Fired before environment tear-down for each iteration of tests starts.
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) = 0;
+
+  // Fired after environment tear-down for each iteration of tests ends.
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) = 0;
+
+  // Fired after each iteration of tests finishes.
+  virtual void OnTestIterationEnd(const UnitTest& unit_test,
+                                  int iteration) = 0;
+
+  // Fired after all test activities have ended.
+  virtual void OnTestProgramEnd(const UnitTest& unit_test) = 0;
+};
+
+// The convenience class for users who need to override just one or two
+// methods and are not concerned that a possible change to a signature of
+// the methods they override will not be caught during the build.  For
+// comments about each method please see the definition of TestEventListener
+// above.
+class EmptyTestEventListener : public TestEventListener {
+ public:
+  virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestIterationStart(const UnitTest& /*unit_test*/,
+                                    int /*iteration*/) {}
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) {}
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestCaseStart(const TestCase& /*test_case*/) {}
+  virtual void OnTestStart(const TestInfo& /*test_info*/) {}
+  virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) {}
+  virtual void OnTestEnd(const TestInfo& /*test_info*/) {}
+  virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {}
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) {}
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/,
+                                  int /*iteration*/) {}
+  virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {}
+};
+
+// TestEventListeners lets users add listeners to track events in Google Test.
+class GTEST_API_ TestEventListeners {
+ public:
+  TestEventListeners();
+  ~TestEventListeners();
+
+  // Appends an event listener to the end of the list. Google Test assumes
+  // the ownership of the listener (i.e. it will delete the listener when
+  // the test program finishes).
+  void Append(TestEventListener* listener);
+
+  // Removes the given event listener from the list and returns it.  It then
+  // becomes the caller's responsibility to delete the listener. Returns
+  // NULL if the listener is not found in the list.
+  TestEventListener* Release(TestEventListener* listener);
+
+  // Returns the standard listener responsible for the default console
+  // output.  Can be removed from the listeners list to shut down default
+  // console output.  Note that removing this object from the listener list
+  // with Release transfers its ownership to the caller and makes this
+  // function return NULL the next time.
+  TestEventListener* default_result_printer() const {
+    return default_result_printer_;
+  }
+
+  // Returns the standard listener responsible for the default XML output
+  // controlled by the --gtest_output=xml flag.  Can be removed from the
+  // listeners list by users who want to shut down the default XML output
+  // controlled by this flag and substitute it with custom one.  Note that
+  // removing this object from the listener list with Release transfers its
+  // ownership to the caller and makes this function return NULL the next
+  // time.
+  TestEventListener* default_xml_generator() const {
+    return default_xml_generator_;
+  }
+
+ private:
+  friend class TestCase;
+  friend class TestInfo;
+  friend class internal::DefaultGlobalTestPartResultReporter;
+  friend class internal::NoExecDeathTest;
+  friend class internal::TestEventListenersAccessor;
+  friend class internal::UnitTestImpl;
+
+  // Returns repeater that broadcasts the TestEventListener events to all
+  // subscribers.
+  TestEventListener* repeater();
+
+  // Sets the default_result_printer attribute to the provided listener.
+  // The listener is also added to the listener list and previous
+  // default_result_printer is removed from it and deleted. The listener can
+  // also be NULL in which case it will not be added to the list. Does
+  // nothing if the previous and the current listener objects are the same.
+  void SetDefaultResultPrinter(TestEventListener* listener);
+
+  // Sets the default_xml_generator attribute to the provided listener.  The
+  // listener is also added to the listener list and previous
+  // default_xml_generator is removed from it and deleted. The listener can
+  // also be NULL in which case it will not be added to the list. Does
+  // nothing if the previous and the current listener objects are the same.
+  void SetDefaultXmlGenerator(TestEventListener* listener);
+
+  // Controls whether events will be forwarded by the repeater to the
+  // listeners in the list.
+  bool EventForwardingEnabled() const;
+  void SuppressEventForwarding();
+
+  // The actual list of listeners.
+  internal::TestEventRepeater* repeater_;
+  // Listener responsible for the standard result output.
+  TestEventListener* default_result_printer_;
+  // Listener responsible for the creation of the XML output file.
+  TestEventListener* default_xml_generator_;
+
+  // We disallow copying TestEventListeners.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventListeners);
+};
+
+// A UnitTest consists of a vector of TestCases.
+//
+// This is a singleton class.  The only instance of UnitTest is
+// created when UnitTest::GetInstance() is first called.  This
+// instance is never deleted.
+//
+// UnitTest is not copyable.
+//
+// This class is thread-safe as long as the methods are called
+// according to their specification.
+class GTEST_API_ UnitTest {
+ public:
+  // Gets the singleton UnitTest object.  The first time this method
+  // is called, a UnitTest object is constructed and returned.
+  // Consecutive calls will return the same object.
+  static UnitTest* GetInstance();
+
+  // Runs all tests in this UnitTest object and prints the result.
+  // Returns 0 if successful, or 1 otherwise.
+  //
+  // This method can only be called from the main thread.
+  //
+  // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+  int Run() GTEST_MUST_USE_RESULT_;
+
+  // Returns the working directory when the first TEST() or TEST_F()
+  // was executed.  The UnitTest object owns the string.
+  const char* original_working_dir() const;
+
+  // Returns the TestCase object for the test that's currently running,
+  // or NULL if no test is running.
+  const TestCase* current_test_case() const
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Returns the TestInfo object for the test that's currently running,
+  // or NULL if no test is running.
+  const TestInfo* current_test_info() const
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Returns the random seed used at the start of the current test run.
+  int random_seed() const;
+
+#if GTEST_HAS_PARAM_TEST
+  // Returns the ParameterizedTestCaseRegistry object used to keep track of
+  // value-parameterized tests and instantiate and register them.
+  //
+  // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+  internal::ParameterizedTestCaseRegistry& parameterized_test_registry()
+      GTEST_LOCK_EXCLUDED_(mutex_);
+#endif  // GTEST_HAS_PARAM_TEST
+
+  // Gets the number of successful test cases.
+  int successful_test_case_count() const;
+
+  // Gets the number of failed test cases.
+  int failed_test_case_count() const;
+
+  // Gets the number of all test cases.
+  int total_test_case_count() const;
+
+  // Gets the number of all test cases that contain at least one test
+  // that should run.
+  int test_case_to_run_count() const;
+
+  // Gets the number of successful tests.
+  int successful_test_count() const;
+
+  // Gets the number of failed tests.
+  int failed_test_count() const;
+
+  // Gets the number of disabled tests that will be reported in the XML report.
+  int reportable_disabled_test_count() const;
+
+  // Gets the number of disabled tests.
+  int disabled_test_count() const;
+
+  // Gets the number of tests to be printed in the XML report.
+  int reportable_test_count() const;
+
+  // Gets the number of all tests.
+  int total_test_count() const;
+
+  // Gets the number of tests that should run.
+  int test_to_run_count() const;
+
+  // Gets the time of the test program start, in ms from the start of the
+  // UNIX epoch.
+  TimeInMillis start_timestamp() const;
+
+  // Gets the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const;
+
+  // Returns true iff the unit test passed (i.e. all test cases passed).
+  bool Passed() const;
+
+  // Returns true iff the unit test failed (i.e. some test case failed
+  // or something outside of all tests failed).
+  bool Failed() const;
+
+  // Gets the i-th test case among all the test cases. i can range from 0 to
+  // total_test_case_count() - 1. If i is not in that range, returns NULL.
+  const TestCase* GetTestCase(int i) const;
+
+  // Returns the TestResult containing information on test failures and
+  // properties logged outside of individual test cases.
+  const TestResult& ad_hoc_test_result() const;
+
+  // Returns the list of event listeners that can be used to track events
+  // inside Google Test.
+  TestEventListeners& listeners();
+
+ private:
+  // Registers and returns a global test environment.  When a test
+  // program is run, all global test environments will be set-up in
+  // the order they were registered.  After all tests in the program
+  // have finished, all global test environments will be torn-down in
+  // the *reverse* order they were registered.
+  //
+  // The UnitTest object takes ownership of the given environment.
+  //
+  // This method can only be called from the main thread.
+  Environment* AddEnvironment(Environment* env);
+
+  // Adds a TestPartResult to the current TestResult object.  All
+  // Google Test assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc)
+  // eventually call this to report their results.  The user code
+  // should use the assertion macros instead of calling this directly.
+  void AddTestPartResult(TestPartResult::Type result_type,
+                         const char* file_name,
+                         int line_number,
+                         const std::string& message,
+                         const std::string& os_stack_trace)
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Adds a TestProperty to the current TestResult object when invoked from
+  // inside a test, to current TestCase's ad_hoc_test_result_ when invoked
+  // from SetUpTestCase or TearDownTestCase, or to the global property set
+  // when invoked elsewhere.  If the result already contains a property with
+  // the same key, the value will be updated.
+  void RecordProperty(const std::string& key, const std::string& value);
+
+  // Gets the i-th test case among all the test cases. i can range from 0 to
+  // total_test_case_count() - 1. If i is not in that range, returns NULL.
+  TestCase* GetMutableTestCase(int i);
+
+  // Accessors for the implementation object.
+  internal::UnitTestImpl* impl() { return impl_; }
+  const internal::UnitTestImpl* impl() const { return impl_; }
+
+  // These classes and funcions are friends as they need to access private
+  // members of UnitTest.
+  friend class Test;
+  friend class internal::AssertHelper;
+  friend class internal::ScopedTrace;
+  friend class internal::StreamingListenerTest;
+  friend class internal::UnitTestRecordPropertyTestHelper;
+  friend Environment* AddGlobalTestEnvironment(Environment* env);
+  friend internal::UnitTestImpl* internal::GetUnitTestImpl();
+  friend void internal::ReportFailureInUnknownLocation(
+      TestPartResult::Type result_type,
+      const std::string& message);
+
+  // Creates an empty UnitTest.
+  UnitTest();
+
+  // D'tor
+  virtual ~UnitTest();
+
+  // Pushes a trace defined by SCOPED_TRACE() on to the per-thread
+  // Google Test trace stack.
+  void PushGTestTrace(const internal::TraceInfo& trace)
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Pops a trace from the per-thread Google Test trace stack.
+  void PopGTestTrace()
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Protects mutable state in *impl_.  This is mutable as some const
+  // methods need to lock it too.
+  mutable internal::Mutex mutex_;
+
+  // Opaque implementation object.  This field is never changed once
+  // the object is constructed.  We don't mark it as const here, as
+  // doing so will cause a warning in the constructor of UnitTest.
+  // Mutable state in *impl_ is protected by mutex_.
+  internal::UnitTestImpl* impl_;
+
+  // We disallow copying UnitTest.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTest);
+};
+
+// A convenient wrapper for adding an environment for the test
+// program.
+//
+// You should call this before RUN_ALL_TESTS() is called, probably in
+// main().  If you use gtest_main, you need to call this before main()
+// starts for it to take effect.  For example, you can define a global
+// variable like this:
+//
+//   testing::Environment* const foo_env =
+//       testing::AddGlobalTestEnvironment(new FooEnvironment);
+//
+// However, we strongly recommend you to write your own main() and
+// call AddGlobalTestEnvironment() there, as relying on initialization
+// of global variables makes the code harder to read and may cause
+// problems when you register multiple environments from different
+// translation units and the environments have dependencies among them
+// (remember that the compiler doesn't guarantee the order in which
+// global variables from different translation units are initialized).
+inline Environment* AddGlobalTestEnvironment(Environment* env) {
+  return UnitTest::GetInstance()->AddEnvironment(env);
+}
+
+// Initializes Google Test.  This must be called before calling
+// RUN_ALL_TESTS().  In particular, it parses a command line for the
+// flags that Google Test recognizes.  Whenever a Google Test flag is
+// seen, it is removed from argv, and *argc is decremented.
+//
+// No value is returned.  Instead, the Google Test flag variables are
+// updated.
+//
+// Calling the function for the second time has no user-visible effect.
+GTEST_API_ void InitGoogleTest(int* argc, char** argv);
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+GTEST_API_ void InitGoogleTest(int* argc, wchar_t** argv);
+
+namespace internal {
+
+// Separate the error generating code from the code path to reduce the stack
+// frame size of CmpHelperEQ. This helps reduce the overhead of some sanitizers
+// when calling EXPECT_* in a tight loop.
+template <typename T1, typename T2>
+AssertionResult CmpHelperEQFailure(const char* expected_expression,
+                                   const char* actual_expression,
+                                   const T1& expected, const T2& actual) {
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   FormatForComparisonFailureMessage(expected, actual),
+                   FormatForComparisonFailureMessage(actual, expected),
+                   false);
+}
+
+// The helper function for {ASSERT|EXPECT}_EQ.
+template <typename T1, typename T2>
+AssertionResult CmpHelperEQ(const char* expected_expression,
+                            const char* actual_expression,
+                            const T1& expected,
+                            const T2& actual) {
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4389 /* signed/unsigned mismatch */)
+  if (expected == actual) {
+    return AssertionSuccess();
+  }
+GTEST_DISABLE_MSC_WARNINGS_POP_()
+
+  return CmpHelperEQFailure(expected_expression, actual_expression, expected,
+                            actual);
+}
+
+// With this overloaded version, we allow anonymous enums to be used
+// in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous enums
+// can be implicitly cast to BiggestInt.
+GTEST_API_ AssertionResult CmpHelperEQ(const char* expected_expression,
+                                       const char* actual_expression,
+                                       BiggestInt expected,
+                                       BiggestInt actual);
+
+// The helper class for {ASSERT|EXPECT}_EQ.  The template argument
+// lhs_is_null_literal is true iff the first argument to ASSERT_EQ()
+// is a null pointer literal.  The following default implementation is
+// for lhs_is_null_literal being false.
+template <bool lhs_is_null_literal>
+class EqHelper {
+ public:
+  // This templatized version is for the general case.
+  template <typename T1, typename T2>
+  static AssertionResult Compare(const char* expected_expression,
+                                 const char* actual_expression,
+                                 const T1& expected,
+                                 const T2& actual) {
+    return CmpHelperEQ(expected_expression, actual_expression, expected,
+                       actual);
+  }
+
+  // With this overloaded version, we allow anonymous enums to be used
+  // in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous
+  // enums can be implicitly cast to BiggestInt.
+  //
+  // Even though its body looks the same as the above version, we
+  // cannot merge the two, as it will make anonymous enums unhappy.
+  static AssertionResult Compare(const char* expected_expression,
+                                 const char* actual_expression,
+                                 BiggestInt expected,
+                                 BiggestInt actual) {
+    return CmpHelperEQ(expected_expression, actual_expression, expected,
+                       actual);
+  }
+};
+
+// This specialization is used when the first argument to ASSERT_EQ()
+// is a null pointer literal, like NULL, false, or 0.
+template <>
+class EqHelper<true> {
+ public:
+  // We define two overloaded versions of Compare().  The first
+  // version will be picked when the second argument to ASSERT_EQ() is
+  // NOT a pointer, e.g. ASSERT_EQ(0, AnIntFunction()) or
+  // EXPECT_EQ(false, a_bool).
+  template <typename T1, typename T2>
+  static AssertionResult Compare(
+      const char* expected_expression,
+      const char* actual_expression,
+      const T1& expected,
+      const T2& actual,
+      // The following line prevents this overload from being considered if T2
+      // is not a pointer type.  We need this because ASSERT_EQ(NULL, my_ptr)
+      // expands to Compare("", "", NULL, my_ptr), which requires a conversion
+      // to match the Secret* in the other overload, which would otherwise make
+      // this template match better.
+      typename EnableIf<!is_pointer<T2>::value>::type* = 0) {
+    return CmpHelperEQ(expected_expression, actual_expression, expected,
+                       actual);
+  }
+
+  // This version will be picked when the second argument to ASSERT_EQ() is a
+  // pointer, e.g. ASSERT_EQ(NULL, a_pointer).
+  template <typename T>
+  static AssertionResult Compare(
+      const char* expected_expression,
+      const char* actual_expression,
+      // We used to have a second template parameter instead of Secret*.  That
+      // template parameter would deduce to 'long', making this a better match
+      // than the first overload even without the first overload's EnableIf.
+      // Unfortunately, gcc with -Wconversion-null warns when "passing NULL to
+      // non-pointer argument" (even a deduced integral argument), so the old
+      // implementation caused warnings in user code.
+      Secret* /* expected (NULL) */,
+      T* actual) {
+    // We already know that 'expected' is a null pointer.
+    return CmpHelperEQ(expected_expression, actual_expression,
+                       static_cast<T*>(NULL), actual);
+  }
+};
+
+// Separate the error generating code from the code path to reduce the stack
+// frame size of CmpHelperOP. This helps reduce the overhead of some sanitizers
+// when calling EXPECT_OP in a tight loop.
+template <typename T1, typename T2>
+AssertionResult CmpHelperOpFailure(const char* expr1, const char* expr2,
+                                   const T1& val1, const T2& val2,
+                                   const char* op) {
+  return AssertionFailure()
+         << "Expected: (" << expr1 << ") " << op << " (" << expr2
+         << "), actual: " << FormatForComparisonFailureMessage(val1, val2)
+         << " vs " << FormatForComparisonFailureMessage(val2, val1);
+}
+
+// A macro for implementing the helper functions needed to implement
+// ASSERT_?? and EXPECT_??.  It is here just to avoid copy-and-paste
+// of similar code.
+//
+// For each templatized helper function, we also define an overloaded
+// version for BiggestInt in order to reduce code bloat and allow
+// anonymous enums to be used with {ASSERT|EXPECT}_?? when compiled
+// with gcc 4.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+
+#define GTEST_IMPL_CMP_HELPER_(op_name, op)\
+template <typename T1, typename T2>\
+AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
+                                   const T1& val1, const T2& val2) {\
+  if (val1 op val2) {\
+    return AssertionSuccess();\
+  } else {\
+    return CmpHelperOpFailure(expr1, expr2, val1, val2, #op);\
+  }\
+}\
+GTEST_API_ AssertionResult CmpHelper##op_name(\
+    const char* expr1, const char* expr2, BiggestInt val1, BiggestInt val2)
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+
+// Implements the helper function for {ASSERT|EXPECT}_NE
+GTEST_IMPL_CMP_HELPER_(NE, !=);
+// Implements the helper function for {ASSERT|EXPECT}_LE
+GTEST_IMPL_CMP_HELPER_(LE, <=);
+// Implements the helper function for {ASSERT|EXPECT}_LT
+GTEST_IMPL_CMP_HELPER_(LT, <);
+// Implements the helper function for {ASSERT|EXPECT}_GE
+GTEST_IMPL_CMP_HELPER_(GE, >=);
+// Implements the helper function for {ASSERT|EXPECT}_GT
+GTEST_IMPL_CMP_HELPER_(GT, >);
+
+#undef GTEST_IMPL_CMP_HELPER_
+
+// The helper function for {ASSERT|EXPECT}_STREQ.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression,
+                                          const char* actual_expression,
+                                          const char* expected,
+                                          const char* actual);
+
+// The helper function for {ASSERT|EXPECT}_STRCASEEQ.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression,
+                                              const char* actual_expression,
+                                              const char* expected,
+                                              const char* actual);
+
+// The helper function for {ASSERT|EXPECT}_STRNE.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                                          const char* s2_expression,
+                                          const char* s1,
+                                          const char* s2);
+
+// The helper function for {ASSERT|EXPECT}_STRCASENE.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
+                                              const char* s2_expression,
+                                              const char* s1,
+                                              const char* s2);
+
+
+// Helper function for *_STREQ on wide strings.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression,
+                                          const char* actual_expression,
+                                          const wchar_t* expected,
+                                          const wchar_t* actual);
+
+// Helper function for *_STRNE on wide strings.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                                          const char* s2_expression,
+                                          const wchar_t* s1,
+                                          const wchar_t* s2);
+
+}  // namespace internal
+
+// IsSubstring() and IsNotSubstring() are intended to be used as the
+// first argument to {EXPECT,ASSERT}_PRED_FORMAT2(), not by
+// themselves.  They check whether needle is a substring of haystack
+// (NULL is considered a substring of itself only), and return an
+// appropriate error message when they fail.
+//
+// The {needle,haystack}_expr arguments are the stringified
+// expressions that generated the two real arguments.
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack);
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack);
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack);
+
+#if GTEST_HAS_STD_WSTRING
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack);
+#endif  // GTEST_HAS_STD_WSTRING
+
+namespace internal {
+
+// Helper template function for comparing floating-points.
+//
+// Template parameter:
+//
+//   RawType: the raw floating-point type (either float or double)
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+template <typename RawType>
+AssertionResult CmpHelperFloatingPointEQ(const char* expected_expression,
+                                         const char* actual_expression,
+                                         RawType expected,
+                                         RawType actual) {
+  const FloatingPoint<RawType> lhs(expected), rhs(actual);
+
+  if (lhs.AlmostEquals(rhs)) {
+    return AssertionSuccess();
+  }
+
+  ::std::stringstream expected_ss;
+  expected_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+              << expected;
+
+  ::std::stringstream actual_ss;
+  actual_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+            << actual;
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   StringStreamToString(&expected_ss),
+                   StringStreamToString(&actual_ss),
+                   false);
+}
+
+// Helper function for implementing ASSERT_NEAR.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1,
+                                                const char* expr2,
+                                                const char* abs_error_expr,
+                                                double val1,
+                                                double val2,
+                                                double abs_error);
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+// A class that enables one to stream messages to assertion macros
+class GTEST_API_ AssertHelper {
+ public:
+  // Constructor.
+  AssertHelper(TestPartResult::Type type,
+               const char* file,
+               int line,
+               const char* message);
+  ~AssertHelper();
+
+  // Message assignment is a semantic trick to enable assertion
+  // streaming; see the GTEST_MESSAGE_ macro below.
+  void operator=(const Message& message) const;
+
+ private:
+  // We put our data in a struct so that the size of the AssertHelper class can
+  // be as small as possible.  This is important because gcc is incapable of
+  // re-using stack space even for temporary variables, so every EXPECT_EQ
+  // reserves stack space for another AssertHelper.
+  struct AssertHelperData {
+    AssertHelperData(TestPartResult::Type t,
+                     const char* srcfile,
+                     int line_num,
+                     const char* msg)
+        : type(t), file(srcfile), line(line_num), message(msg) { }
+
+    TestPartResult::Type const type;
+    const char* const file;
+    int const line;
+    std::string const message;
+
+   private:
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelperData);
+  };
+
+  AssertHelperData* const data_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper);
+};
+
+}  // namespace internal
+
+#if GTEST_HAS_PARAM_TEST
+// The pure interface class that all value-parameterized tests inherit from.
+// A value-parameterized class must inherit from both ::testing::Test and
+// ::testing::WithParamInterface. In most cases that just means inheriting
+// from ::testing::TestWithParam, but more complicated test hierarchies
+// may need to inherit from Test and WithParamInterface at different levels.
+//
+// This interface has support for accessing the test parameter value via
+// the GetParam() method.
+//
+// Use it with one of the parameter generator defining functions, like Range(),
+// Values(), ValuesIn(), Bool(), and Combine().
+//
+// class FooTest : public ::testing::TestWithParam<int> {
+//  protected:
+//   FooTest() {
+//     // Can use GetParam() here.
+//   }
+//   virtual ~FooTest() {
+//     // Can use GetParam() here.
+//   }
+//   virtual void SetUp() {
+//     // Can use GetParam() here.
+//   }
+//   virtual void TearDown {
+//     // Can use GetParam() here.
+//   }
+// };
+// TEST_P(FooTest, DoesBar) {
+//   // Can use GetParam() method here.
+//   Foo foo;
+//   ASSERT_TRUE(foo.DoesBar(GetParam()));
+// }
+// INSTANTIATE_TEST_CASE_P(OneToTenRange, FooTest, ::testing::Range(1, 10));
+
+template <typename T>
+class WithParamInterface {
+ public:
+  typedef T ParamType;
+  virtual ~WithParamInterface() {}
+
+  // The current parameter value. Is also available in the test fixture's
+  // constructor. This member function is non-static, even though it only
+  // references static data, to reduce the opportunity for incorrect uses
+  // like writing 'WithParamInterface<bool>::GetParam()' for a test that
+  // uses a fixture whose parameter type is int.
+  const ParamType& GetParam() const {
+    GTEST_CHECK_(parameter_ != NULL)
+        << "GetParam() can only be called inside a value-parameterized test "
+        << "-- did you intend to write TEST_P instead of TEST_F?";
+    return *parameter_;
+  }
+
+ private:
+  // Sets parameter value. The caller is responsible for making sure the value
+  // remains alive and unchanged throughout the current test.
+  static void SetParam(const ParamType* parameter) {
+    parameter_ = parameter;
+  }
+
+  // Static value used for accessing parameter during a test lifetime.
+  static const ParamType* parameter_;
+
+  // TestClass must be a subclass of WithParamInterface<T> and Test.
+  template <class TestClass> friend class internal::ParameterizedTestFactory;
+};
+
+template <typename T>
+const T* WithParamInterface<T>::parameter_ = NULL;
+
+// Most value-parameterized classes can ignore the existence of
+// WithParamInterface, and can just inherit from ::testing::TestWithParam.
+
+template <typename T>
+class TestWithParam : public Test, public WithParamInterface<T> {
+};
+
+#endif  // GTEST_HAS_PARAM_TEST
+
+// Macros for indicating success/failure in test code.
+
+// ADD_FAILURE unconditionally adds a failure to the current test.
+// SUCCEED generates a success - it doesn't automatically make the
+// current test successful, as a test is only successful when it has
+// no failure.
+//
+// EXPECT_* verifies that a certain condition is satisfied.  If not,
+// it behaves like ADD_FAILURE.  In particular:
+//
+//   EXPECT_TRUE  verifies that a Boolean condition is true.
+//   EXPECT_FALSE verifies that a Boolean condition is false.
+//
+// FAIL and ASSERT_* are similar to ADD_FAILURE and EXPECT_*, except
+// that they will also abort the current function on failure.  People
+// usually want the fail-fast behavior of FAIL and ASSERT_*, but those
+// writing data-driven tests often find themselves using ADD_FAILURE
+// and EXPECT_* more.
+
+// Generates a nonfatal failure with a generic message.
+#define ADD_FAILURE() GTEST_NONFATAL_FAILURE_("Failed")
+
+// Generates a nonfatal failure at the given source file location with
+// a generic message.
+#define ADD_FAILURE_AT(file, line) \
+  GTEST_MESSAGE_AT_(file, line, "Failed", \
+                    ::testing::TestPartResult::kNonFatalFailure)
+
+// Generates a fatal failure with a generic message.
+#define GTEST_FAIL() GTEST_FATAL_FAILURE_("Failed")
+
+// Define this macro to 1 to omit the definition of FAIL(), which is a
+// generic name and clashes with some other libraries.
+#if !GTEST_DONT_DEFINE_FAIL
+# define FAIL() GTEST_FAIL()
+#endif
+
+// Generates a success with a generic message.
+#define GTEST_SUCCEED() GTEST_SUCCESS_("Succeeded")
+
+// Define this macro to 1 to omit the definition of SUCCEED(), which
+// is a generic name and clashes with some other libraries.
+#if !GTEST_DONT_DEFINE_SUCCEED
+# define SUCCEED() GTEST_SUCCEED()
+#endif
+
+// Macros for testing exceptions.
+//
+//    * {ASSERT|EXPECT}_THROW(statement, expected_exception):
+//         Tests that the statement throws the expected exception.
+//    * {ASSERT|EXPECT}_NO_THROW(statement):
+//         Tests that the statement doesn't throw any exception.
+//    * {ASSERT|EXPECT}_ANY_THROW(statement):
+//         Tests that the statement throws an exception.
+
+#define EXPECT_THROW(statement, expected_exception) \
+  GTEST_TEST_THROW_(statement, expected_exception, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_NO_THROW(statement) \
+  GTEST_TEST_NO_THROW_(statement, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_ANY_THROW(statement) \
+  GTEST_TEST_ANY_THROW_(statement, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_THROW(statement, expected_exception) \
+  GTEST_TEST_THROW_(statement, expected_exception, GTEST_FATAL_FAILURE_)
+#define ASSERT_NO_THROW(statement) \
+  GTEST_TEST_NO_THROW_(statement, GTEST_FATAL_FAILURE_)
+#define ASSERT_ANY_THROW(statement) \
+  GTEST_TEST_ANY_THROW_(statement, GTEST_FATAL_FAILURE_)
+
+// Boolean assertions. Condition can be either a Boolean expression or an
+// AssertionResult. For more information on how to use AssertionResult with
+// these macros see comments on that class.
+#define EXPECT_TRUE(condition) \
+  GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
+                      GTEST_NONFATAL_FAILURE_)
+#define EXPECT_FALSE(condition) \
+  GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
+                      GTEST_NONFATAL_FAILURE_)
+#define ASSERT_TRUE(condition) \
+  GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
+                      GTEST_FATAL_FAILURE_)
+#define ASSERT_FALSE(condition) \
+  GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
+                      GTEST_FATAL_FAILURE_)
+
+// Includes the auto-generated header that implements a family of
+// generic predicate assertion macros.
+#include "gtest/gtest_pred_impl.h"
+
+// Macros for testing equalities and inequalities.
+//
+//    * {ASSERT|EXPECT}_EQ(expected, actual): Tests that expected == actual
+//    * {ASSERT|EXPECT}_NE(v1, v2):           Tests that v1 != v2
+//    * {ASSERT|EXPECT}_LT(v1, v2):           Tests that v1 < v2
+//    * {ASSERT|EXPECT}_LE(v1, v2):           Tests that v1 <= v2
+//    * {ASSERT|EXPECT}_GT(v1, v2):           Tests that v1 > v2
+//    * {ASSERT|EXPECT}_GE(v1, v2):           Tests that v1 >= v2
+//
+// When they are not, Google Test prints both the tested expressions and
+// their actual values.  The values must be compatible built-in types,
+// or you will get a compiler error.  By "compatible" we mean that the
+// values can be compared by the respective operator.
+//
+// Note:
+//
+//   1. It is possible to make a user-defined type work with
+//   {ASSERT|EXPECT}_??(), but that requires overloading the
+//   comparison operators and is thus discouraged by the Google C++
+//   Usage Guide.  Therefore, you are advised to use the
+//   {ASSERT|EXPECT}_TRUE() macro to assert that two objects are
+//   equal.
+//
+//   2. The {ASSERT|EXPECT}_??() macros do pointer comparisons on
+//   pointers (in particular, C strings).  Therefore, if you use it
+//   with two C strings, you are testing how their locations in memory
+//   are related, not how their content is related.  To compare two C
+//   strings by content, use {ASSERT|EXPECT}_STR*().
+//
+//   3. {ASSERT|EXPECT}_EQ(expected, actual) is preferred to
+//   {ASSERT|EXPECT}_TRUE(expected == actual), as the former tells you
+//   what the actual value is when it fails, and similarly for the
+//   other comparisons.
+//
+//   4. Do not depend on the order in which {ASSERT|EXPECT}_??()
+//   evaluate their arguments, which is undefined.
+//
+//   5. These macros evaluate their arguments exactly once.
+//
+// Examples:
+//
+//   EXPECT_NE(5, Foo());
+//   EXPECT_EQ(NULL, a_pointer);
+//   ASSERT_LT(i, array_size);
+//   ASSERT_GT(records.size(), 0) << "There is no record left.";
+
+#define EXPECT_EQ(expected, actual) \
+  EXPECT_PRED_FORMAT2(::testing::internal:: \
+                      EqHelper<GTEST_IS_NULL_LITERAL_(expected)>::Compare, \
+                      expected, actual)
+#define EXPECT_NE(expected, actual) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperNE, expected, actual)
+#define EXPECT_LE(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2)
+#define EXPECT_LT(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2)
+#define EXPECT_GE(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2)
+#define EXPECT_GT(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
+
+#define GTEST_ASSERT_EQ(expected, actual) \
+  ASSERT_PRED_FORMAT2(::testing::internal:: \
+                      EqHelper<GTEST_IS_NULL_LITERAL_(expected)>::Compare, \
+                      expected, actual)
+#define GTEST_ASSERT_NE(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2)
+#define GTEST_ASSERT_LE(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2)
+#define GTEST_ASSERT_LT(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2)
+#define GTEST_ASSERT_GE(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2)
+#define GTEST_ASSERT_GT(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
+
+// Define macro GTEST_DONT_DEFINE_ASSERT_XY to 1 to omit the definition of
+// ASSERT_XY(), which clashes with some users' own code.
+
+#if !GTEST_DONT_DEFINE_ASSERT_EQ
+# define ASSERT_EQ(val1, val2) GTEST_ASSERT_EQ(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_NE
+# define ASSERT_NE(val1, val2) GTEST_ASSERT_NE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_LE
+# define ASSERT_LE(val1, val2) GTEST_ASSERT_LE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_LT
+# define ASSERT_LT(val1, val2) GTEST_ASSERT_LT(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_GE
+# define ASSERT_GE(val1, val2) GTEST_ASSERT_GE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_GT
+# define ASSERT_GT(val1, val2) GTEST_ASSERT_GT(val1, val2)
+#endif
+
+// C-string Comparisons.  All tests treat NULL and any non-NULL string
+// as different.  Two NULLs are equal.
+//
+//    * {ASSERT|EXPECT}_STREQ(s1, s2):     Tests that s1 == s2
+//    * {ASSERT|EXPECT}_STRNE(s1, s2):     Tests that s1 != s2
+//    * {ASSERT|EXPECT}_STRCASEEQ(s1, s2): Tests that s1 == s2, ignoring case
+//    * {ASSERT|EXPECT}_STRCASENE(s1, s2): Tests that s1 != s2, ignoring case
+//
+// For wide or narrow string objects, you can use the
+// {ASSERT|EXPECT}_??() macros.
+//
+// Don't depend on the order in which the arguments are evaluated,
+// which is undefined.
+//
+// These macros evaluate their arguments exactly once.
+
+#define EXPECT_STREQ(expected, actual) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual)
+#define EXPECT_STRNE(s1, s2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
+#define EXPECT_STRCASEEQ(expected, actual) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual)
+#define EXPECT_STRCASENE(s1, s2)\
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
+
+#define ASSERT_STREQ(expected, actual) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual)
+#define ASSERT_STRNE(s1, s2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
+#define ASSERT_STRCASEEQ(expected, actual) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual)
+#define ASSERT_STRCASENE(s1, s2)\
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
+
+// Macros for comparing floating-point numbers.
+//
+//    * {ASSERT|EXPECT}_FLOAT_EQ(expected, actual):
+//         Tests that two float values are almost equal.
+//    * {ASSERT|EXPECT}_DOUBLE_EQ(expected, actual):
+//         Tests that two double values are almost equal.
+//    * {ASSERT|EXPECT}_NEAR(v1, v2, abs_error):
+//         Tests that v1 and v2 are within the given distance to each other.
+//
+// Google Test uses ULP-based comparison to automatically pick a default
+// error bound that is appropriate for the operands.  See the
+// FloatingPoint template class in gtest-internal.h if you are
+// interested in the implementation details.
+
+#define EXPECT_FLOAT_EQ(expected, actual)\
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
+                      expected, actual)
+
+#define EXPECT_DOUBLE_EQ(expected, actual)\
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
+                      expected, actual)
+
+#define ASSERT_FLOAT_EQ(expected, actual)\
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
+                      expected, actual)
+
+#define ASSERT_DOUBLE_EQ(expected, actual)\
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
+                      expected, actual)
+
+#define EXPECT_NEAR(val1, val2, abs_error)\
+  EXPECT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \
+                      val1, val2, abs_error)
+
+#define ASSERT_NEAR(val1, val2, abs_error)\
+  ASSERT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \
+                      val1, val2, abs_error)
+
+// These predicate format functions work on floating-point values, and
+// can be used in {ASSERT|EXPECT}_PRED_FORMAT2*(), e.g.
+//
+//   EXPECT_PRED_FORMAT2(testing::DoubleLE, Foo(), 5.0);
+
+// Asserts that val1 is less than, or almost equal to, val2.  Fails
+// otherwise.  In particular, it fails if either val1 or val2 is NaN.
+GTEST_API_ AssertionResult FloatLE(const char* expr1, const char* expr2,
+                                   float val1, float val2);
+GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2,
+                                    double val1, double val2);
+
+
+#if GTEST_OS_WINDOWS
+
+// Macros that test for HRESULT failure and success, these are only useful
+// on Windows, and rely on Windows SDK macros and APIs to compile.
+//
+//    * {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}(expr)
+//
+// When expr unexpectedly fails or succeeds, Google Test prints the
+// expected result and the actual result with both a human-readable
+// string representation of the error, if available, as well as the
+// hex result code.
+# define EXPECT_HRESULT_SUCCEEDED(expr) \
+    EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
+
+# define ASSERT_HRESULT_SUCCEEDED(expr) \
+    ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
+
+# define EXPECT_HRESULT_FAILED(expr) \
+    EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
+
+# define ASSERT_HRESULT_FAILED(expr) \
+    ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
+
+#endif  // GTEST_OS_WINDOWS
+
+// Macros that execute statement and check that it doesn't generate new fatal
+// failures in the current thread.
+//
+//   * {ASSERT|EXPECT}_NO_FATAL_FAILURE(statement);
+//
+// Examples:
+//
+//   EXPECT_NO_FATAL_FAILURE(Process());
+//   ASSERT_NO_FATAL_FAILURE(Process()) << "Process() failed";
+//
+#define ASSERT_NO_FATAL_FAILURE(statement) \
+    GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_FATAL_FAILURE_)
+#define EXPECT_NO_FATAL_FAILURE(statement) \
+    GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_NONFATAL_FAILURE_)
+
+// Causes a trace (including the source file path, the current line
+// number, and the given message) to be included in every test failure
+// message generated by code in the current scope.  The effect is
+// undone when the control leaves the current scope.
+//
+// The message argument can be anything streamable to std::ostream.
+//
+// In the implementation, we include the current line number as part
+// of the dummy variable name, thus allowing multiple SCOPED_TRACE()s
+// to appear in the same block - as long as they are on different
+// lines.
+#define SCOPED_TRACE(message) \
+  ::testing::internal::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\
+    __FILE__, __LINE__, ::testing::Message() << (message))
+
+// Compile-time assertion for type equality.
+// StaticAssertTypeEq<type1, type2>() compiles iff type1 and type2 are
+// the same type.  The value it returns is not interesting.
+//
+// Instead of making StaticAssertTypeEq a class template, we make it a
+// function template that invokes a helper class template.  This
+// prevents a user from misusing StaticAssertTypeEq<T1, T2> by
+// defining objects of that type.
+//
+// CAVEAT:
+//
+// When used inside a method of a class template,
+// StaticAssertTypeEq<T1, T2>() is effective ONLY IF the method is
+// instantiated.  For example, given:
+//
+//   template <typename T> class Foo {
+//    public:
+//     void Bar() { testing::StaticAssertTypeEq<int, T>(); }
+//   };
+//
+// the code:
+//
+//   void Test1() { Foo<bool> foo; }
+//
+// will NOT generate a compiler error, as Foo<bool>::Bar() is never
+// actually instantiated.  Instead, you need:
+//
+//   void Test2() { Foo<bool> foo; foo.Bar(); }
+//
+// to cause a compiler error.
+template <typename T1, typename T2>
+bool StaticAssertTypeEq() {
+  (void)internal::StaticAssertTypeEqHelper<T1, T2>();
+  return true;
+}
+
+// Defines a test.
+//
+// The first parameter is the name of the test case, and the second
+// parameter is the name of the test within the test case.
+//
+// The convention is to end the test case name with "Test".  For
+// example, a test case for the Foo class can be named FooTest.
+//
+// Test code should appear between braces after an invocation of
+// this macro.  Example:
+//
+//   TEST(FooTest, InitializesCorrectly) {
+//     Foo foo;
+//     EXPECT_TRUE(foo.StatusIsOK());
+//   }
+
+// Note that we call GetTestTypeId() instead of GetTypeId<
+// ::testing::Test>() here to get the type ID of testing::Test.  This
+// is to work around a suspected linker bug when using Google Test as
+// a framework on Mac OS X.  The bug causes GetTypeId<
+// ::testing::Test>() to return different values depending on whether
+// the call is from the Google Test framework itself or from user test
+// code.  GetTestTypeId() is guaranteed to always return the same
+// value, as it always calls GetTypeId<>() from the Google Test
+// framework.
+#define GTEST_TEST(test_case_name, test_name)\
+  GTEST_TEST_(test_case_name, test_name, \
+              ::testing::Test, ::testing::internal::GetTestTypeId())
+
+// Define this macro to 1 to omit the definition of TEST(), which
+// is a generic name and clashes with some other libraries.
+#if !GTEST_DONT_DEFINE_TEST
+# define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name)
+#endif
+
+// Defines a test that uses a test fixture.
+//
+// The first parameter is the name of the test fixture class, which
+// also doubles as the test case name.  The second parameter is the
+// name of the test within the test case.
+//
+// A test fixture class must be declared earlier.  The user should put
+// his test code between braces after using this macro.  Example:
+//
+//   class FooTest : public testing::Test {
+//    protected:
+//     virtual void SetUp() { b_.AddElement(3); }
+//
+//     Foo a_;
+//     Foo b_;
+//   };
+//
+//   TEST_F(FooTest, InitializesCorrectly) {
+//     EXPECT_TRUE(a_.StatusIsOK());
+//   }
+//
+//   TEST_F(FooTest, ReturnsElementCountCorrectly) {
+//     EXPECT_EQ(0, a_.size());
+//     EXPECT_EQ(1, b_.size());
+//   }
+
+#define TEST_F(test_fixture, test_name)\
+  GTEST_TEST_(test_fixture, test_name, test_fixture, \
+              ::testing::internal::GetTypeId<test_fixture>())
+
+}  // namespace testing
+
+// Use this function in main() to run all tests.  It returns 0 if all
+// tests are successful, or 1 otherwise.
+//
+// RUN_ALL_TESTS() should be invoked after the command line has been
+// parsed by InitGoogleTest().
+//
+// This function was formerly a macro; thus, it is in the global
+// namespace and has an all-caps name.
+int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_;
+
+inline int RUN_ALL_TESTS() {
+  return ::testing::UnitTest::GetInstance()->Run();
+}
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_H_
diff --git a/third_party/googletest/googletest/include/gtest/gtest_pred_impl.h b/third_party/googletest/googletest/include/gtest/gtest_pred_impl.h
new file mode 100644
index 0000000..30ae712
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/gtest_pred_impl.h
@@ -0,0 +1,358 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This file is AUTOMATICALLY GENERATED on 10/31/2011 by command
+// 'gen_gtest_pred_impl.py 5'.  DO NOT EDIT BY HAND!
+//
+// Implements a family of generic predicate assertion macros.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+
+// Makes sure this header is not included before gtest.h.
+#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
+# error Do not include gtest_pred_impl.h directly.  Include gtest.h instead.
+#endif  // GTEST_INCLUDE_GTEST_GTEST_H_
+
+// This header implements a family of generic predicate assertion
+// macros:
+//
+//   ASSERT_PRED_FORMAT1(pred_format, v1)
+//   ASSERT_PRED_FORMAT2(pred_format, v1, v2)
+//   ...
+//
+// where pred_format is a function or functor that takes n (in the
+// case of ASSERT_PRED_FORMATn) values and their source expression
+// text, and returns a testing::AssertionResult.  See the definition
+// of ASSERT_EQ in gtest.h for an example.
+//
+// If you don't care about formatting, you can use the more
+// restrictive version:
+//
+//   ASSERT_PRED1(pred, v1)
+//   ASSERT_PRED2(pred, v1, v2)
+//   ...
+//
+// where pred is an n-ary function or functor that returns bool,
+// and the values v1, v2, ..., must support the << operator for
+// streaming to std::ostream.
+//
+// We also define the EXPECT_* variations.
+//
+// For now we only support predicates whose arity is at most 5.
+// Please email googletestframework@googlegroups.com if you need
+// support for higher arities.
+
+// GTEST_ASSERT_ is the basic statement to which all of the assertions
+// in this file reduce.  Don't use this in your code.
+
+#define GTEST_ASSERT_(expression, on_failure) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (const ::testing::AssertionResult gtest_ar = (expression)) \
+    ; \
+  else \
+    on_failure(gtest_ar.failure_message())
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED1.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1>
+AssertionResult AssertPred1Helper(const char* pred_text,
+                                  const char* e1,
+                                  Pred pred,
+                                  const T1& v1) {
+  if (pred(v1)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, v1), \
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED1.  Don't use
+// this in your code.
+#define GTEST_PRED1_(pred, v1, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, \
+                                             #v1, \
+                                             pred, \
+                                             v1), on_failure)
+
+// Unary predicate assertion macros.
+#define EXPECT_PRED_FORMAT1(pred_format, v1) \
+  GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED1(pred, v1) \
+  GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT1(pred_format, v1) \
+  GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED1(pred, v1) \
+  GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED2.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2>
+AssertionResult AssertPred2Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2) {
+  if (pred(v1, v2)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ", "
+                            << e2 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1
+                            << "\n" << e2 << " evaluates to " << v2;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2), \
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED2.  Don't use
+// this in your code.
+#define GTEST_PRED2_(pred, v1, v2, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             pred, \
+                                             v1, \
+                                             v2), on_failure)
+
+// Binary predicate assertion macros.
+#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \
+  GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED2(pred, v1, v2) \
+  GTEST_PRED2_(pred, v1, v2, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT2(pred_format, v1, v2) \
+  GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED2(pred, v1, v2) \
+  GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED3.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2,
+          typename T3>
+AssertionResult AssertPred3Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  const char* e3,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2,
+                                  const T3& v3) {
+  if (pred(v1, v2, v3)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ", "
+                            << e2 << ", "
+                            << e3 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1
+                            << "\n" << e2 << " evaluates to " << v2
+                            << "\n" << e3 << " evaluates to " << v3;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3), \
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED3.  Don't use
+// this in your code.
+#define GTEST_PRED3_(pred, v1, v2, v3, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred3Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             #v3, \
+                                             pred, \
+                                             v1, \
+                                             v2, \
+                                             v3), on_failure)
+
+// Ternary predicate assertion macros.
+#define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \
+  GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED3(pred, v1, v2, v3) \
+  GTEST_PRED3_(pred, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT3(pred_format, v1, v2, v3) \
+  GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED3(pred, v1, v2, v3) \
+  GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED4.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2,
+          typename T3,
+          typename T4>
+AssertionResult AssertPred4Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  const char* e3,
+                                  const char* e4,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2,
+                                  const T3& v3,
+                                  const T4& v4) {
+  if (pred(v1, v2, v3, v4)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ", "
+                            << e2 << ", "
+                            << e3 << ", "
+                            << e4 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1
+                            << "\n" << e2 << " evaluates to " << v2
+                            << "\n" << e3 << " evaluates to " << v3
+                            << "\n" << e4 << " evaluates to " << v4;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4), \
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED4.  Don't use
+// this in your code.
+#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             #v3, \
+                                             #v4, \
+                                             pred, \
+                                             v1, \
+                                             v2, \
+                                             v3, \
+                                             v4), on_failure)
+
+// 4-ary predicate assertion macros.
+#define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
+  GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED4(pred, v1, v2, v3, v4) \
+  GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
+  GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED4(pred, v1, v2, v3, v4) \
+  GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED5.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2,
+          typename T3,
+          typename T4,
+          typename T5>
+AssertionResult AssertPred5Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  const char* e3,
+                                  const char* e4,
+                                  const char* e5,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2,
+                                  const T3& v3,
+                                  const T4& v4,
+                                  const T5& v5) {
+  if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ", "
+                            << e2 << ", "
+                            << e3 << ", "
+                            << e4 << ", "
+                            << e5 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1
+                            << "\n" << e2 << " evaluates to " << v2
+                            << "\n" << e3 << " evaluates to " << v3
+                            << "\n" << e4 << " evaluates to " << v4
+                            << "\n" << e5 << " evaluates to " << v5;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5), \
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED5.  Don't use
+// this in your code.
+#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             #v3, \
+                                             #v4, \
+                                             #v5, \
+                                             pred, \
+                                             v1, \
+                                             v2, \
+                                             v3, \
+                                             v4, \
+                                             v5), on_failure)
+
+// 5-ary predicate assertion macros.
+#define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
+  GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED5(pred, v1, v2, v3, v4, v5) \
+  GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
+  GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \
+  GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
+
+
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
diff --git a/third_party/googletest/googletest/include/gtest/gtest_prod.h b/third_party/googletest/googletest/include/gtest/gtest_prod.h
new file mode 100644
index 0000000..da80ddc
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/gtest_prod.h
@@ -0,0 +1,58 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// Google C++ Testing Framework definitions useful in production code.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PROD_H_
+
+// When you need to test the private or protected members of a class,
+// use the FRIEND_TEST macro to declare your tests as friends of the
+// class.  For example:
+//
+// class MyClass {
+//  private:
+//   void MyMethod();
+//   FRIEND_TEST(MyClassTest, MyMethod);
+// };
+//
+// class MyClassTest : public testing::Test {
+//   // ...
+// };
+//
+// TEST_F(MyClassTest, MyMethod) {
+//   // Can call MyClass::MyMethod() here.
+// }
+
+#define FRIEND_TEST(test_case_name, test_name)\
+friend class test_case_name##_##test_name##_Test
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PROD_H_
diff --git a/third_party/googletest/googletest/include/gtest/internal/custom/gtest-port.h b/third_party/googletest/googletest/include/gtest/internal/custom/gtest-port.h
new file mode 100644
index 0000000..7e744bd
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/internal/custom/gtest-port.h
@@ -0,0 +1,69 @@
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Injection point for custom user configurations.
+// The following macros can be defined:
+//
+//   Flag related macros:
+//     GTEST_FLAG(flag_name)
+//     GTEST_USE_OWN_FLAGFILE_FLAG_  - Define to 0 when the system provides its
+//                                     own flagfile flag parsing.
+//     GTEST_DECLARE_bool_(name)
+//     GTEST_DECLARE_int32_(name)
+//     GTEST_DECLARE_string_(name)
+//     GTEST_DEFINE_bool_(name, default_val, doc)
+//     GTEST_DEFINE_int32_(name, default_val, doc)
+//     GTEST_DEFINE_string_(name, default_val, doc)
+//
+//   Test filtering:
+//     GTEST_TEST_FILTER_ENV_VAR_ - The name of an environment variable that
+//                                  will be used if --GTEST_FLAG(test_filter)
+//                                  is not provided.
+//
+//   Logging:
+//     GTEST_LOG_(severity)
+//     GTEST_CHECK_(condition)
+//     Functions LogToStderr() and FlushInfoLog() have to be provided too.
+//
+//   Threading:
+//     GTEST_HAS_NOTIFICATION_ - Enabled if Notification is already provided.
+//     GTEST_HAS_MUTEX_AND_THREAD_LOCAL_ - Enabled if Mutex and ThreadLocal are
+//                                         already provided.
+//     Must also provide GTEST_DECLARE_STATIC_MUTEX_(mutex) and
+//     GTEST_DEFINE_STATIC_MUTEX_(mutex)
+//
+//     GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks)
+//     GTEST_LOCK_EXCLUDED_(locks)
+//
+// ** Custom implementation starts here **
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
diff --git a/third_party/googletest/googletest/include/gtest/internal/custom/gtest-printers.h b/third_party/googletest/googletest/include/gtest/internal/custom/gtest-printers.h
new file mode 100644
index 0000000..60c1ea0
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/internal/custom/gtest-printers.h
@@ -0,0 +1,42 @@
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// This file provides an injection point for custom printers in a local
+// installation of gTest.
+// It will be included from gtest-printers.h and the overrides in this file
+// will be visible to everyone.
+// See documentation at gtest/gtest-printers.h for details on how to define a
+// custom printer.
+//
+// ** Custom implementation starts here **
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
diff --git a/third_party/googletest/googletest/include/gtest/internal/custom/gtest.h b/third_party/googletest/googletest/include/gtest/internal/custom/gtest.h
new file mode 100644
index 0000000..c27412a
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/internal/custom/gtest.h
@@ -0,0 +1,41 @@
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Injection point for custom user configurations.
+// The following macros can be defined:
+//
+// GTEST_OS_STACK_TRACE_GETTER_  - The name of an implementation of
+//                                 OsStackTraceGetterInterface.
+//
+// ** Custom implementation starts here **
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
diff --git a/third_party/googletest/googletest/include/gtest/internal/gtest-death-test-internal.h b/third_party/googletest/googletest/include/gtest/internal/gtest-death-test-internal.h
new file mode 100644
index 0000000..2b3a78f
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/internal/gtest-death-test-internal.h
@@ -0,0 +1,319 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines internal utilities needed for implementing
+// death tests.  They are subject to change without notice.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
+
+#include "gtest/internal/gtest-internal.h"
+
+#include <stdio.h>
+
+namespace testing {
+namespace internal {
+
+GTEST_DECLARE_string_(internal_run_death_test);
+
+// Names of the flags (needed for parsing Google Test flags).
+const char kDeathTestStyleFlag[] = "death_test_style";
+const char kDeathTestUseFork[] = "death_test_use_fork";
+const char kInternalRunDeathTestFlag[] = "internal_run_death_test";
+
+#if GTEST_HAS_DEATH_TEST
+
+// DeathTest is a class that hides much of the complexity of the
+// GTEST_DEATH_TEST_ macro.  It is abstract; its static Create method
+// returns a concrete class that depends on the prevailing death test
+// style, as defined by the --gtest_death_test_style and/or
+// --gtest_internal_run_death_test flags.
+
+// In describing the results of death tests, these terms are used with
+// the corresponding definitions:
+//
+// exit status:  The integer exit information in the format specified
+//               by wait(2)
+// exit code:    The integer code passed to exit(3), _exit(2), or
+//               returned from main()
+class GTEST_API_ DeathTest {
+ public:
+  // Create returns false if there was an error determining the
+  // appropriate action to take for the current death test; for example,
+  // if the gtest_death_test_style flag is set to an invalid value.
+  // The LastMessage method will return a more detailed message in that
+  // case.  Otherwise, the DeathTest pointer pointed to by the "test"
+  // argument is set.  If the death test should be skipped, the pointer
+  // is set to NULL; otherwise, it is set to the address of a new concrete
+  // DeathTest object that controls the execution of the current test.
+  static bool Create(const char* statement, const RE* regex,
+                     const char* file, int line, DeathTest** test);
+  DeathTest();
+  virtual ~DeathTest() { }
+
+  // A helper class that aborts a death test when it's deleted.
+  class ReturnSentinel {
+   public:
+    explicit ReturnSentinel(DeathTest* test) : test_(test) { }
+    ~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); }
+   private:
+    DeathTest* const test_;
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(ReturnSentinel);
+  } GTEST_ATTRIBUTE_UNUSED_;
+
+  // An enumeration of possible roles that may be taken when a death
+  // test is encountered.  EXECUTE means that the death test logic should
+  // be executed immediately.  OVERSEE means that the program should prepare
+  // the appropriate environment for a child process to execute the death
+  // test, then wait for it to complete.
+  enum TestRole { OVERSEE_TEST, EXECUTE_TEST };
+
+  // An enumeration of the three reasons that a test might be aborted.
+  enum AbortReason {
+    TEST_ENCOUNTERED_RETURN_STATEMENT,
+    TEST_THREW_EXCEPTION,
+    TEST_DID_NOT_DIE
+  };
+
+  // Assumes one of the above roles.
+  virtual TestRole AssumeRole() = 0;
+
+  // Waits for the death test to finish and returns its status.
+  virtual int Wait() = 0;
+
+  // Returns true if the death test passed; that is, the test process
+  // exited during the test, its exit status matches a user-supplied
+  // predicate, and its stderr output matches a user-supplied regular
+  // expression.
+  // The user-supplied predicate may be a macro expression rather
+  // than a function pointer or functor, or else Wait and Passed could
+  // be combined.
+  virtual bool Passed(bool exit_status_ok) = 0;
+
+  // Signals that the death test did not die as expected.
+  virtual void Abort(AbortReason reason) = 0;
+
+  // Returns a human-readable outcome message regarding the outcome of
+  // the last death test.
+  static const char* LastMessage();
+
+  static void set_last_death_test_message(const std::string& message);
+
+ private:
+  // A string containing a description of the outcome of the last death test.
+  static std::string last_death_test_message_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest);
+};
+
+// Factory interface for death tests.  May be mocked out for testing.
+class DeathTestFactory {
+ public:
+  virtual ~DeathTestFactory() { }
+  virtual bool Create(const char* statement, const RE* regex,
+                      const char* file, int line, DeathTest** test) = 0;
+};
+
+// A concrete DeathTestFactory implementation for normal use.
+class DefaultDeathTestFactory : public DeathTestFactory {
+ public:
+  virtual bool Create(const char* statement, const RE* regex,
+                      const char* file, int line, DeathTest** test);
+};
+
+// Returns true if exit_status describes a process that was terminated
+// by a signal, or exited normally with a nonzero exit code.
+GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
+
+// Traps C++ exceptions escaping statement and reports them as test
+// failures. Note that trapping SEH exceptions is not implemented here.
+# if GTEST_HAS_EXCEPTIONS
+#  define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
+  try { \
+    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+  } catch (const ::std::exception& gtest_exception) { \
+    fprintf(\
+        stderr, \
+        "\n%s: Caught std::exception-derived exception escaping the " \
+        "death test statement. Exception message: %s\n", \
+        ::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \
+        gtest_exception.what()); \
+    fflush(stderr); \
+    death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
+  } catch (...) { \
+    death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
+  }
+
+# else
+#  define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
+  GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
+
+# endif
+
+// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
+// ASSERT_EXIT*, and EXPECT_EXIT*.
+# define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+    const ::testing::internal::RE& gtest_regex = (regex); \
+    ::testing::internal::DeathTest* gtest_dt; \
+    if (!::testing::internal::DeathTest::Create(#statement, &gtest_regex, \
+        __FILE__, __LINE__, &gtest_dt)) { \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
+    } \
+    if (gtest_dt != NULL) { \
+      ::testing::internal::scoped_ptr< ::testing::internal::DeathTest> \
+          gtest_dt_ptr(gtest_dt); \
+      switch (gtest_dt->AssumeRole()) { \
+        case ::testing::internal::DeathTest::OVERSEE_TEST: \
+          if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \
+            goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
+          } \
+          break; \
+        case ::testing::internal::DeathTest::EXECUTE_TEST: { \
+          ::testing::internal::DeathTest::ReturnSentinel \
+              gtest_sentinel(gtest_dt); \
+          GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \
+          gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
+          break; \
+        } \
+        default: \
+          break; \
+      } \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__): \
+      fail(::testing::internal::DeathTest::LastMessage())
+// The symbol "fail" here expands to something into which a message
+// can be streamed.
+
+// This macro is for implementing ASSERT/EXPECT_DEBUG_DEATH when compiled in
+// NDEBUG mode. In this case we need the statements to be executed, the regex is
+// ignored, and the macro must accept a streamed message even though the message
+// is never printed.
+# define GTEST_EXECUTE_STATEMENT_(statement, regex) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+     GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+  } else \
+    ::testing::Message()
+
+// A class representing the parsed contents of the
+// --gtest_internal_run_death_test flag, as it existed when
+// RUN_ALL_TESTS was called.
+class InternalRunDeathTestFlag {
+ public:
+  InternalRunDeathTestFlag(const std::string& a_file,
+                           int a_line,
+                           int an_index,
+                           int a_write_fd)
+      : file_(a_file), line_(a_line), index_(an_index),
+        write_fd_(a_write_fd) {}
+
+  ~InternalRunDeathTestFlag() {
+    if (write_fd_ >= 0)
+      posix::Close(write_fd_);
+  }
+
+  const std::string& file() const { return file_; }
+  int line() const { return line_; }
+  int index() const { return index_; }
+  int write_fd() const { return write_fd_; }
+
+ private:
+  std::string file_;
+  int line_;
+  int index_;
+  int write_fd_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag);
+};
+
+// Returns a newly created InternalRunDeathTestFlag object with fields
+// initialized from the GTEST_FLAG(internal_run_death_test) flag if
+// the flag is specified; otherwise returns NULL.
+InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag();
+
+#else  // GTEST_HAS_DEATH_TEST
+
+// This macro is used for implementing macros such as
+// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where
+// death tests are not supported. Those macros must compile on such systems
+// iff EXPECT_DEATH and ASSERT_DEATH compile with the same parameters on
+// systems that support death tests. This allows one to write such a macro
+// on a system that does not support death tests and be sure that it will
+// compile on a death-test supporting system.
+//
+// Parameters:
+//   statement -  A statement that a macro such as EXPECT_DEATH would test
+//                for program termination. This macro has to make sure this
+//                statement is compiled but not executed, to ensure that
+//                EXPECT_DEATH_IF_SUPPORTED compiles with a certain
+//                parameter iff EXPECT_DEATH compiles with it.
+//   regex     -  A regex that a macro such as EXPECT_DEATH would use to test
+//                the output of statement.  This parameter has to be
+//                compiled but not evaluated by this macro, to ensure that
+//                this macro only accepts expressions that a macro such as
+//                EXPECT_DEATH would accept.
+//   terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED
+//                and a return statement for ASSERT_DEATH_IF_SUPPORTED.
+//                This ensures that ASSERT_DEATH_IF_SUPPORTED will not
+//                compile inside functions where ASSERT_DEATH doesn't
+//                compile.
+//
+//  The branch that has an always false condition is used to ensure that
+//  statement and regex are compiled (and thus syntactically correct) but
+//  never executed. The unreachable code macro protects the terminator
+//  statement from generating an 'unreachable code' warning in case
+//  statement unconditionally returns or throws. The Message constructor at
+//  the end allows the syntax of streaming additional messages into the
+//  macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH.
+# define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \
+    GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+    if (::testing::internal::AlwaysTrue()) { \
+      GTEST_LOG_(WARNING) \
+          << "Death tests are not supported on this platform.\n" \
+          << "Statement '" #statement "' cannot be verified."; \
+    } else if (::testing::internal::AlwaysFalse()) { \
+      ::testing::internal::RE::PartialMatch(".*", (regex)); \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+      terminator; \
+    } else \
+      ::testing::Message()
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
diff --git a/third_party/googletest/googletest/include/gtest/internal/gtest-filepath.h b/third_party/googletest/googletest/include/gtest/internal/gtest-filepath.h
new file mode 100644
index 0000000..7a13b4b
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/internal/gtest-filepath.h
@@ -0,0 +1,206 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: keith.ray@gmail.com (Keith Ray)
+//
+// Google Test filepath utilities
+//
+// This header file declares classes and functions used internally by
+// Google Test.  They are subject to change without notice.
+//
+// This file is #included in <gtest/internal/gtest-internal.h>.
+// Do not include this header file separately!
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
+
+#include "gtest/internal/gtest-string.h"
+
+namespace testing {
+namespace internal {
+
+// FilePath - a class for file and directory pathname manipulation which
+// handles platform-specific conventions (like the pathname separator).
+// Used for helper functions for naming files in a directory for xml output.
+// Except for Set methods, all methods are const or static, which provides an
+// "immutable value object" -- useful for peace of mind.
+// A FilePath with a value ending in a path separator ("like/this/") represents
+// a directory, otherwise it is assumed to represent a file. In either case,
+// it may or may not represent an actual file or directory in the file system.
+// Names are NOT checked for syntax correctness -- no checking for illegal
+// characters, malformed paths, etc.
+
+class GTEST_API_ FilePath {
+ public:
+  FilePath() : pathname_("") { }
+  FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { }
+
+  explicit FilePath(const std::string& pathname) : pathname_(pathname) {
+    Normalize();
+  }
+
+  FilePath& operator=(const FilePath& rhs) {
+    Set(rhs);
+    return *this;
+  }
+
+  void Set(const FilePath& rhs) {
+    pathname_ = rhs.pathname_;
+  }
+
+  const std::string& string() const { return pathname_; }
+  const char* c_str() const { return pathname_.c_str(); }
+
+  // Returns the current working directory, or "" if unsuccessful.
+  static FilePath GetCurrentDir();
+
+  // Given directory = "dir", base_name = "test", number = 0,
+  // extension = "xml", returns "dir/test.xml". If number is greater
+  // than zero (e.g., 12), returns "dir/test_12.xml".
+  // On Windows platform, uses \ as the separator rather than /.
+  static FilePath MakeFileName(const FilePath& directory,
+                               const FilePath& base_name,
+                               int number,
+                               const char* extension);
+
+  // Given directory = "dir", relative_path = "test.xml",
+  // returns "dir/test.xml".
+  // On Windows, uses \ as the separator rather than /.
+  static FilePath ConcatPaths(const FilePath& directory,
+                              const FilePath& relative_path);
+
+  // Returns a pathname for a file that does not currently exist. The pathname
+  // will be directory/base_name.extension or
+  // directory/base_name_<number>.extension if directory/base_name.extension
+  // already exists. The number will be incremented until a pathname is found
+  // that does not already exist.
+  // Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
+  // There could be a race condition if two or more processes are calling this
+  // function at the same time -- they could both pick the same filename.
+  static FilePath GenerateUniqueFileName(const FilePath& directory,
+                                         const FilePath& base_name,
+                                         const char* extension);
+
+  // Returns true iff the path is "".
+  bool IsEmpty() const { return pathname_.empty(); }
+
+  // If input name has a trailing separator character, removes it and returns
+  // the name, otherwise return the name string unmodified.
+  // On Windows platform, uses \ as the separator, other platforms use /.
+  FilePath RemoveTrailingPathSeparator() const;
+
+  // Returns a copy of the FilePath with the directory part removed.
+  // Example: FilePath("path/to/file").RemoveDirectoryName() returns
+  // FilePath("file"). If there is no directory part ("just_a_file"), it returns
+  // the FilePath unmodified. If there is no file part ("just_a_dir/") it
+  // returns an empty FilePath ("").
+  // On Windows platform, '\' is the path separator, otherwise it is '/'.
+  FilePath RemoveDirectoryName() const;
+
+  // RemoveFileName returns the directory path with the filename removed.
+  // Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
+  // If the FilePath is "a_file" or "/a_file", RemoveFileName returns
+  // FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
+  // not have a file, like "just/a/dir/", it returns the FilePath unmodified.
+  // On Windows platform, '\' is the path separator, otherwise it is '/'.
+  FilePath RemoveFileName() const;
+
+  // Returns a copy of the FilePath with the case-insensitive extension removed.
+  // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
+  // FilePath("dir/file"). If a case-insensitive extension is not
+  // found, returns a copy of the original FilePath.
+  FilePath RemoveExtension(const char* extension) const;
+
+  // Creates directories so that path exists. Returns true if successful or if
+  // the directories already exist; returns false if unable to create
+  // directories for any reason. Will also return false if the FilePath does
+  // not represent a directory (that is, it doesn't end with a path separator).
+  bool CreateDirectoriesRecursively() const;
+
+  // Create the directory so that path exists. Returns true if successful or
+  // if the directory already exists; returns false if unable to create the
+  // directory for any reason, including if the parent directory does not
+  // exist. Not named "CreateDirectory" because that's a macro on Windows.
+  bool CreateFolder() const;
+
+  // Returns true if FilePath describes something in the file-system,
+  // either a file, directory, or whatever, and that something exists.
+  bool FileOrDirectoryExists() const;
+
+  // Returns true if pathname describes a directory in the file-system
+  // that exists.
+  bool DirectoryExists() const;
+
+  // Returns true if FilePath ends with a path separator, which indicates that
+  // it is intended to represent a directory. Returns false otherwise.
+  // This does NOT check that a directory (or file) actually exists.
+  bool IsDirectory() const;
+
+  // Returns true if pathname describes a root directory. (Windows has one
+  // root directory per disk drive.)
+  bool IsRootDirectory() const;
+
+  // Returns true if pathname describes an absolute path.
+  bool IsAbsolutePath() const;
+
+ private:
+  // Replaces multiple consecutive separators with a single separator.
+  // For example, "bar///foo" becomes "bar/foo". Does not eliminate other
+  // redundancies that might be in a pathname involving "." or "..".
+  //
+  // A pathname with multiple consecutive separators may occur either through
+  // user error or as a result of some scripts or APIs that generate a pathname
+  // with a trailing separator. On other platforms the same API or script
+  // may NOT generate a pathname with a trailing "/". Then elsewhere that
+  // pathname may have another "/" and pathname components added to it,
+  // without checking for the separator already being there.
+  // The script language and operating system may allow paths like "foo//bar"
+  // but some of the functions in FilePath will not handle that correctly. In
+  // particular, RemoveTrailingPathSeparator() only removes one separator, and
+  // it is called in CreateDirectoriesRecursively() assuming that it will change
+  // a pathname from directory syntax (trailing separator) to filename syntax.
+  //
+  // On Windows this method also replaces the alternate path separator '/' with
+  // the primary path separator '\\', so that for example "bar\\/\\foo" becomes
+  // "bar\\foo".
+
+  void Normalize();
+
+  // Returns a pointer to the last occurence of a valid path separator in
+  // the FilePath. On Windows, for example, both '/' and '\' are valid path
+  // separators. Returns NULL if no path separator was found.
+  const char* FindLastPathSeparator() const;
+
+  std::string pathname_;
+};  // class FilePath
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
diff --git a/third_party/googletest/googletest/include/gtest/internal/gtest-internal.h b/third_party/googletest/googletest/include/gtest/internal/gtest-internal.h
new file mode 100644
index 0000000..ebd1cf6
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/internal/gtest-internal.h
@@ -0,0 +1,1238 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file declares functions and macros used internally by
+// Google Test.  They are subject to change without notice.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
+
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_OS_LINUX
+# include <stdlib.h>
+# include <sys/types.h>
+# include <sys/wait.h>
+# include <unistd.h>
+#endif  // GTEST_OS_LINUX
+
+#if GTEST_HAS_EXCEPTIONS
+# include <stdexcept>
+#endif
+
+#include <ctype.h>
+#include <float.h>
+#include <string.h>
+#include <iomanip>
+#include <limits>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-string.h"
+#include "gtest/internal/gtest-filepath.h"
+#include "gtest/internal/gtest-type-util.h"
+
+// Due to C++ preprocessor weirdness, we need double indirection to
+// concatenate two tokens when one of them is __LINE__.  Writing
+//
+//   foo ## __LINE__
+//
+// will result in the token foo__LINE__, instead of foo followed by
+// the current line number.  For more details, see
+// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6
+#define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar)
+#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar
+
+class ProtocolMessage;
+namespace proto2 { class Message; }
+
+namespace testing {
+
+// Forward declarations.
+
+class AssertionResult;                 // Result of an assertion.
+class Message;                         // Represents a failure message.
+class Test;                            // Represents a test.
+class TestInfo;                        // Information about a test.
+class TestPartResult;                  // Result of a test part.
+class UnitTest;                        // A collection of test cases.
+
+template <typename T>
+::std::string PrintToString(const T& value);
+
+namespace internal {
+
+struct TraceInfo;                      // Information about a trace point.
+class ScopedTrace;                     // Implements scoped trace.
+class TestInfoImpl;                    // Opaque implementation of TestInfo
+class UnitTestImpl;                    // Opaque implementation of UnitTest
+
+// The text used in failure messages to indicate the start of the
+// stack trace.
+GTEST_API_ extern const char kStackTraceMarker[];
+
+// Two overloaded helpers for checking at compile time whether an
+// expression is a null pointer literal (i.e. NULL or any 0-valued
+// compile-time integral constant).  Their return values have
+// different sizes, so we can use sizeof() to test which version is
+// picked by the compiler.  These helpers have no implementations, as
+// we only need their signatures.
+//
+// Given IsNullLiteralHelper(x), the compiler will pick the first
+// version if x can be implicitly converted to Secret*, and pick the
+// second version otherwise.  Since Secret is a secret and incomplete
+// type, the only expression a user can write that has type Secret* is
+// a null pointer literal.  Therefore, we know that x is a null
+// pointer literal if and only if the first version is picked by the
+// compiler.
+char IsNullLiteralHelper(Secret* p);
+char (&IsNullLiteralHelper(...))[2];  // NOLINT
+
+// A compile-time bool constant that is true if and only if x is a
+// null pointer literal (i.e. NULL or any 0-valued compile-time
+// integral constant).
+#ifdef GTEST_ELLIPSIS_NEEDS_POD_
+// We lose support for NULL detection where the compiler doesn't like
+// passing non-POD classes through ellipsis (...).
+# define GTEST_IS_NULL_LITERAL_(x) false
+#else
+# define GTEST_IS_NULL_LITERAL_(x) \
+    (sizeof(::testing::internal::IsNullLiteralHelper(x)) == 1)
+#endif  // GTEST_ELLIPSIS_NEEDS_POD_
+
+// Appends the user-supplied message to the Google-Test-generated message.
+GTEST_API_ std::string AppendUserMessage(
+    const std::string& gtest_msg, const Message& user_msg);
+
+#if GTEST_HAS_EXCEPTIONS
+
+// This exception is thrown by (and only by) a failed Google Test
+// assertion when GTEST_FLAG(throw_on_failure) is true (if exceptions
+// are enabled).  We derive it from std::runtime_error, which is for
+// errors presumably detectable only at run time.  Since
+// std::runtime_error inherits from std::exception, many testing
+// frameworks know how to extract and print the message inside it.
+class GTEST_API_ GoogleTestFailureException : public ::std::runtime_error {
+ public:
+  explicit GoogleTestFailureException(const TestPartResult& failure);
+};
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// A helper class for creating scoped traces in user programs.
+class GTEST_API_ ScopedTrace {
+ public:
+  // The c'tor pushes the given source file location and message onto
+  // a trace stack maintained by Google Test.
+  ScopedTrace(const char* file, int line, const Message& message);
+
+  // The d'tor pops the info pushed by the c'tor.
+  //
+  // Note that the d'tor is not virtual in order to be efficient.
+  // Don't inherit from ScopedTrace!
+  ~ScopedTrace();
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedTrace);
+} GTEST_ATTRIBUTE_UNUSED_;  // A ScopedTrace object does its job in its
+                            // c'tor and d'tor.  Therefore it doesn't
+                            // need to be used otherwise.
+
+namespace edit_distance {
+// Returns the optimal edits to go from 'left' to 'right'.
+// All edits cost the same, with replace having lower priority than
+// add/remove.
+// Simple implementation of the Wagner–Fischer algorithm.
+// See http://en.wikipedia.org/wiki/Wagner-Fischer_algorithm
+enum EditType { kMatch, kAdd, kRemove, kReplace };
+GTEST_API_ std::vector<EditType> CalculateOptimalEdits(
+    const std::vector<size_t>& left, const std::vector<size_t>& right);
+
+// Same as above, but the input is represented as strings.
+GTEST_API_ std::vector<EditType> CalculateOptimalEdits(
+    const std::vector<std::string>& left,
+    const std::vector<std::string>& right);
+
+// Create a diff of the input strings in Unified diff format.
+GTEST_API_ std::string CreateUnifiedDiff(const std::vector<std::string>& left,
+                                         const std::vector<std::string>& right,
+                                         size_t context = 2);
+
+}  // namespace edit_distance
+
+// Calculate the diff between 'left' and 'right' and return it in unified diff
+// format.
+// If not null, stores in 'total_line_count' the total number of lines found
+// in left + right.
+GTEST_API_ std::string DiffStrings(const std::string& left,
+                                   const std::string& right,
+                                   size_t* total_line_count);
+
+// Constructs and returns the message for an equality assertion
+// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
+//
+// The first four parameters are the expressions used in the assertion
+// and their values, as strings.  For example, for ASSERT_EQ(foo, bar)
+// where foo is 5 and bar is 6, we have:
+//
+//   expected_expression: "foo"
+//   actual_expression:   "bar"
+//   expected_value:      "5"
+//   actual_value:        "6"
+//
+// The ignoring_case parameter is true iff the assertion is a
+// *_STRCASEEQ*.  When it's true, the string " (ignoring case)" will
+// be inserted into the message.
+GTEST_API_ AssertionResult EqFailure(const char* expected_expression,
+                                     const char* actual_expression,
+                                     const std::string& expected_value,
+                                     const std::string& actual_value,
+                                     bool ignoring_case);
+
+// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
+GTEST_API_ std::string GetBoolAssertionFailureMessage(
+    const AssertionResult& assertion_result,
+    const char* expression_text,
+    const char* actual_predicate_value,
+    const char* expected_predicate_value);
+
+// This template class represents an IEEE floating-point number
+// (either single-precision or double-precision, depending on the
+// template parameters).
+//
+// The purpose of this class is to do more sophisticated number
+// comparison.  (Due to round-off error, etc, it's very unlikely that
+// two floating-points will be equal exactly.  Hence a naive
+// comparison by the == operation often doesn't work.)
+//
+// Format of IEEE floating-point:
+//
+//   The most-significant bit being the leftmost, an IEEE
+//   floating-point looks like
+//
+//     sign_bit exponent_bits fraction_bits
+//
+//   Here, sign_bit is a single bit that designates the sign of the
+//   number.
+//
+//   For float, there are 8 exponent bits and 23 fraction bits.
+//
+//   For double, there are 11 exponent bits and 52 fraction bits.
+//
+//   More details can be found at
+//   http://en.wikipedia.org/wiki/IEEE_floating-point_standard.
+//
+// Template parameter:
+//
+//   RawType: the raw floating-point type (either float or double)
+template <typename RawType>
+class FloatingPoint {
+ public:
+  // Defines the unsigned integer type that has the same size as the
+  // floating point number.
+  typedef typename TypeWithSize<sizeof(RawType)>::UInt Bits;
+
+  // Constants.
+
+  // # of bits in a number.
+  static const size_t kBitCount = 8*sizeof(RawType);
+
+  // # of fraction bits in a number.
+  static const size_t kFractionBitCount =
+    std::numeric_limits<RawType>::digits - 1;
+
+  // # of exponent bits in a number.
+  static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount;
+
+  // The mask for the sign bit.
+  static const Bits kSignBitMask = static_cast<Bits>(1) << (kBitCount - 1);
+
+  // The mask for the fraction bits.
+  static const Bits kFractionBitMask =
+    ~static_cast<Bits>(0) >> (kExponentBitCount + 1);
+
+  // The mask for the exponent bits.
+  static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask);
+
+  // How many ULP's (Units in the Last Place) we want to tolerate when
+  // comparing two numbers.  The larger the value, the more error we
+  // allow.  A 0 value means that two numbers must be exactly the same
+  // to be considered equal.
+  //
+  // The maximum error of a single floating-point operation is 0.5
+  // units in the last place.  On Intel CPU's, all floating-point
+  // calculations are done with 80-bit precision, while double has 64
+  // bits.  Therefore, 4 should be enough for ordinary use.
+  //
+  // See the following article for more details on ULP:
+  // http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
+  static const size_t kMaxUlps = 4;
+
+  // Constructs a FloatingPoint from a raw floating-point number.
+  //
+  // On an Intel CPU, passing a non-normalized NAN (Not a Number)
+  // around may change its bits, although the new value is guaranteed
+  // to be also a NAN.  Therefore, don't expect this constructor to
+  // preserve the bits in x when x is a NAN.
+  explicit FloatingPoint(const RawType& x) { u_.value_ = x; }
+
+  // Static methods
+
+  // Reinterprets a bit pattern as a floating-point number.
+  //
+  // This function is needed to test the AlmostEquals() method.
+  static RawType ReinterpretBits(const Bits bits) {
+    FloatingPoint fp(0);
+    fp.u_.bits_ = bits;
+    return fp.u_.value_;
+  }
+
+  // Returns the floating-point number that represent positive infinity.
+  static RawType Infinity() {
+    return ReinterpretBits(kExponentBitMask);
+  }
+
+  // Returns the maximum representable finite floating-point number.
+  static RawType Max();
+
+  // Non-static methods
+
+  // Returns the bits that represents this number.
+  const Bits &bits() const { return u_.bits_; }
+
+  // Returns the exponent bits of this number.
+  Bits exponent_bits() const { return kExponentBitMask & u_.bits_; }
+
+  // Returns the fraction bits of this number.
+  Bits fraction_bits() const { return kFractionBitMask & u_.bits_; }
+
+  // Returns the sign bit of this number.
+  Bits sign_bit() const { return kSignBitMask & u_.bits_; }
+
+  // Returns true iff this is NAN (not a number).
+  bool is_nan() const {
+    // It's a NAN if the exponent bits are all ones and the fraction
+    // bits are not entirely zeros.
+    return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0);
+  }
+
+  // Returns true iff this number is at most kMaxUlps ULP's away from
+  // rhs.  In particular, this function:
+  //
+  //   - returns false if either number is (or both are) NAN.
+  //   - treats really large numbers as almost equal to infinity.
+  //   - thinks +0.0 and -0.0 are 0 DLP's apart.
+  bool AlmostEquals(const FloatingPoint& rhs) const {
+    // The IEEE standard says that any comparison operation involving
+    // a NAN must return false.
+    if (is_nan() || rhs.is_nan()) return false;
+
+    return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_)
+        <= kMaxUlps;
+  }
+
+ private:
+  // The data type used to store the actual floating-point number.
+  union FloatingPointUnion {
+    RawType value_;  // The raw floating-point number.
+    Bits bits_;      // The bits that represent the number.
+  };
+
+  // Converts an integer from the sign-and-magnitude representation to
+  // the biased representation.  More precisely, let N be 2 to the
+  // power of (kBitCount - 1), an integer x is represented by the
+  // unsigned number x + N.
+  //
+  // For instance,
+  //
+  //   -N + 1 (the most negative number representable using
+  //          sign-and-magnitude) is represented by 1;
+  //   0      is represented by N; and
+  //   N - 1  (the biggest number representable using
+  //          sign-and-magnitude) is represented by 2N - 1.
+  //
+  // Read http://en.wikipedia.org/wiki/Signed_number_representations
+  // for more details on signed number representations.
+  static Bits SignAndMagnitudeToBiased(const Bits &sam) {
+    if (kSignBitMask & sam) {
+      // sam represents a negative number.
+      return ~sam + 1;
+    } else {
+      // sam represents a positive number.
+      return kSignBitMask | sam;
+    }
+  }
+
+  // Given two numbers in the sign-and-magnitude representation,
+  // returns the distance between them as an unsigned number.
+  static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1,
+                                                     const Bits &sam2) {
+    const Bits biased1 = SignAndMagnitudeToBiased(sam1);
+    const Bits biased2 = SignAndMagnitudeToBiased(sam2);
+    return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
+  }
+
+  FloatingPointUnion u_;
+};
+
+// We cannot use std::numeric_limits<T>::max() as it clashes with the max()
+// macro defined by <windows.h>.
+template <>
+inline float FloatingPoint<float>::Max() { return FLT_MAX; }
+template <>
+inline double FloatingPoint<double>::Max() { return DBL_MAX; }
+
+// Typedefs the instances of the FloatingPoint template class that we
+// care to use.
+typedef FloatingPoint<float> Float;
+typedef FloatingPoint<double> Double;
+
+// In order to catch the mistake of putting tests that use different
+// test fixture classes in the same test case, we need to assign
+// unique IDs to fixture classes and compare them.  The TypeId type is
+// used to hold such IDs.  The user should treat TypeId as an opaque
+// type: the only operation allowed on TypeId values is to compare
+// them for equality using the == operator.
+typedef const void* TypeId;
+
+template <typename T>
+class TypeIdHelper {
+ public:
+  // dummy_ must not have a const type.  Otherwise an overly eager
+  // compiler (e.g. MSVC 7.1 & 8.0) may try to merge
+  // TypeIdHelper<T>::dummy_ for different Ts as an "optimization".
+  static bool dummy_;
+};
+
+template <typename T>
+bool TypeIdHelper<T>::dummy_ = false;
+
+// GetTypeId<T>() returns the ID of type T.  Different values will be
+// returned for different types.  Calling the function twice with the
+// same type argument is guaranteed to return the same ID.
+template <typename T>
+TypeId GetTypeId() {
+  // The compiler is required to allocate a different
+  // TypeIdHelper<T>::dummy_ variable for each T used to instantiate
+  // the template.  Therefore, the address of dummy_ is guaranteed to
+  // be unique.
+  return &(TypeIdHelper<T>::dummy_);
+}
+
+// Returns the type ID of ::testing::Test.  Always call this instead
+// of GetTypeId< ::testing::Test>() to get the type ID of
+// ::testing::Test, as the latter may give the wrong result due to a
+// suspected linker bug when compiling Google Test as a Mac OS X
+// framework.
+GTEST_API_ TypeId GetTestTypeId();
+
+// Defines the abstract factory interface that creates instances
+// of a Test object.
+class TestFactoryBase {
+ public:
+  virtual ~TestFactoryBase() {}
+
+  // Creates a test instance to run. The instance is both created and destroyed
+  // within TestInfoImpl::Run()
+  virtual Test* CreateTest() = 0;
+
+ protected:
+  TestFactoryBase() {}
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestFactoryBase);
+};
+
+// This class provides implementation of TeastFactoryBase interface.
+// It is used in TEST and TEST_F macros.
+template <class TestClass>
+class TestFactoryImpl : public TestFactoryBase {
+ public:
+  virtual Test* CreateTest() { return new TestClass; }
+};
+
+#if GTEST_OS_WINDOWS
+
+// Predicate-formatters for implementing the HRESULT checking macros
+// {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}
+// We pass a long instead of HRESULT to avoid causing an
+// include dependency for the HRESULT type.
+GTEST_API_ AssertionResult IsHRESULTSuccess(const char* expr,
+                                            long hr);  // NOLINT
+GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr,
+                                            long hr);  // NOLINT
+
+#endif  // GTEST_OS_WINDOWS
+
+// Types of SetUpTestCase() and TearDownTestCase() functions.
+typedef void (*SetUpTestCaseFunc)();
+typedef void (*TearDownTestCaseFunc)();
+
+struct CodeLocation {
+  CodeLocation(const string& a_file, int a_line) : file(a_file), line(a_line) {}
+
+  string file;
+  int line;
+};
+
+// Creates a new TestInfo object and registers it with Google Test;
+// returns the created object.
+//
+// Arguments:
+//
+//   test_case_name:   name of the test case
+//   name:             name of the test
+//   type_param        the name of the test's type parameter, or NULL if
+//                     this is not a typed or a type-parameterized test.
+//   value_param       text representation of the test's value parameter,
+//                     or NULL if this is not a type-parameterized test.
+//   code_location:    code location where the test is defined
+//   fixture_class_id: ID of the test fixture class
+//   set_up_tc:        pointer to the function that sets up the test case
+//   tear_down_tc:     pointer to the function that tears down the test case
+//   factory:          pointer to the factory that creates a test object.
+//                     The newly created TestInfo instance will assume
+//                     ownership of the factory object.
+GTEST_API_ TestInfo* MakeAndRegisterTestInfo(
+    const char* test_case_name,
+    const char* name,
+    const char* type_param,
+    const char* value_param,
+    CodeLocation code_location,
+    TypeId fixture_class_id,
+    SetUpTestCaseFunc set_up_tc,
+    TearDownTestCaseFunc tear_down_tc,
+    TestFactoryBase* factory);
+
+// If *pstr starts with the given prefix, modifies *pstr to be right
+// past the prefix and returns true; otherwise leaves *pstr unchanged
+// and returns false.  None of pstr, *pstr, and prefix can be NULL.
+GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr);
+
+#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// State of the definition of a type-parameterized test case.
+class GTEST_API_ TypedTestCasePState {
+ public:
+  TypedTestCasePState() : registered_(false) {}
+
+  // Adds the given test name to defined_test_names_ and return true
+  // if the test case hasn't been registered; otherwise aborts the
+  // program.
+  bool AddTestName(const char* file, int line, const char* case_name,
+                   const char* test_name) {
+    if (registered_) {
+      fprintf(stderr, "%s Test %s must be defined before "
+              "REGISTER_TYPED_TEST_CASE_P(%s, ...).\n",
+              FormatFileLocation(file, line).c_str(), test_name, case_name);
+      fflush(stderr);
+      posix::Abort();
+    }
+    registered_tests_.insert(
+        ::std::make_pair(test_name, CodeLocation(file, line)));
+    return true;
+  }
+
+  bool TestExists(const std::string& test_name) const {
+    return registered_tests_.count(test_name) > 0;
+  }
+
+  const CodeLocation& GetCodeLocation(const std::string& test_name) const {
+    RegisteredTestsMap::const_iterator it = registered_tests_.find(test_name);
+    GTEST_CHECK_(it != registered_tests_.end());
+    return it->second;
+  }
+
+  // Verifies that registered_tests match the test names in
+  // defined_test_names_; returns registered_tests if successful, or
+  // aborts the program otherwise.
+  const char* VerifyRegisteredTestNames(
+      const char* file, int line, const char* registered_tests);
+
+ private:
+  typedef ::std::map<std::string, CodeLocation> RegisteredTestsMap;
+
+  bool registered_;
+  RegisteredTestsMap registered_tests_;
+};
+
+// Skips to the first non-space char after the first comma in 'str';
+// returns NULL if no comma is found in 'str'.
+inline const char* SkipComma(const char* str) {
+  const char* comma = strchr(str, ',');
+  if (comma == NULL) {
+    return NULL;
+  }
+  while (IsSpace(*(++comma))) {}
+  return comma;
+}
+
+// Returns the prefix of 'str' before the first comma in it; returns
+// the entire string if it contains no comma.
+inline std::string GetPrefixUntilComma(const char* str) {
+  const char* comma = strchr(str, ',');
+  return comma == NULL ? str : std::string(str, comma);
+}
+
+// Splits a given string on a given delimiter, populating a given
+// vector with the fields.
+void SplitString(const ::std::string& str, char delimiter,
+                 ::std::vector< ::std::string>* dest);
+
+// TypeParameterizedTest<Fixture, TestSel, Types>::Register()
+// registers a list of type-parameterized tests with Google Test.  The
+// return value is insignificant - we just need to return something
+// such that we can call this function in a namespace scope.
+//
+// Implementation note: The GTEST_TEMPLATE_ macro declares a template
+// template parameter.  It's defined in gtest-type-util.h.
+template <GTEST_TEMPLATE_ Fixture, class TestSel, typename Types>
+class TypeParameterizedTest {
+ public:
+  // 'index' is the index of the test in the type list 'Types'
+  // specified in INSTANTIATE_TYPED_TEST_CASE_P(Prefix, TestCase,
+  // Types).  Valid values for 'index' are [0, N - 1] where N is the
+  // length of Types.
+  static bool Register(const char* prefix,
+                       CodeLocation code_location,
+                       const char* case_name, const char* test_names,
+                       int index) {
+    typedef typename Types::Head Type;
+    typedef Fixture<Type> FixtureClass;
+    typedef typename GTEST_BIND_(TestSel, Type) TestClass;
+
+    // First, registers the first type-parameterized test in the type
+    // list.
+    MakeAndRegisterTestInfo(
+        (std::string(prefix) + (prefix[0] == '\0' ? "" : "/") + case_name + "/"
+         + StreamableToString(index)).c_str(),
+        StripTrailingSpaces(GetPrefixUntilComma(test_names)).c_str(),
+        GetTypeName<Type>().c_str(),
+        NULL,  // No value parameter.
+        code_location,
+        GetTypeId<FixtureClass>(),
+        TestClass::SetUpTestCase,
+        TestClass::TearDownTestCase,
+        new TestFactoryImpl<TestClass>);
+
+    // Next, recurses (at compile time) with the tail of the type list.
+    return TypeParameterizedTest<Fixture, TestSel, typename Types::Tail>
+        ::Register(prefix, code_location, case_name, test_names, index + 1);
+  }
+};
+
+// The base case for the compile time recursion.
+template <GTEST_TEMPLATE_ Fixture, class TestSel>
+class TypeParameterizedTest<Fixture, TestSel, Types0> {
+ public:
+  static bool Register(const char* /*prefix*/, CodeLocation,
+                       const char* /*case_name*/, const char* /*test_names*/,
+                       int /*index*/) {
+    return true;
+  }
+};
+
+// TypeParameterizedTestCase<Fixture, Tests, Types>::Register()
+// registers *all combinations* of 'Tests' and 'Types' with Google
+// Test.  The return value is insignificant - we just need to return
+// something such that we can call this function in a namespace scope.
+template <GTEST_TEMPLATE_ Fixture, typename Tests, typename Types>
+class TypeParameterizedTestCase {
+ public:
+  static bool Register(const char* prefix, CodeLocation code_location,
+                       const TypedTestCasePState* state,
+                       const char* case_name, const char* test_names) {
+    std::string test_name = StripTrailingSpaces(
+        GetPrefixUntilComma(test_names));
+    if (!state->TestExists(test_name)) {
+      fprintf(stderr, "Failed to get code location for test %s.%s at %s.",
+              case_name, test_name.c_str(),
+              FormatFileLocation(code_location.file.c_str(),
+                                 code_location.line).c_str());
+      fflush(stderr);
+      posix::Abort();
+    }
+    const CodeLocation& test_location = state->GetCodeLocation(test_name);
+
+    typedef typename Tests::Head Head;
+
+    // First, register the first test in 'Test' for each type in 'Types'.
+    TypeParameterizedTest<Fixture, Head, Types>::Register(
+        prefix, test_location, case_name, test_names, 0);
+
+    // Next, recurses (at compile time) with the tail of the test list.
+    return TypeParameterizedTestCase<Fixture, typename Tests::Tail, Types>
+        ::Register(prefix, code_location, state,
+                   case_name, SkipComma(test_names));
+  }
+};
+
+// The base case for the compile time recursion.
+template <GTEST_TEMPLATE_ Fixture, typename Types>
+class TypeParameterizedTestCase<Fixture, Templates0, Types> {
+ public:
+  static bool Register(const char* /*prefix*/, CodeLocation,
+                       const TypedTestCasePState* /*state*/,
+                       const char* /*case_name*/, const char* /*test_names*/) {
+    return true;
+  }
+};
+
+#endif  // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// Returns the current OS stack trace as an std::string.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag.  The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in
+// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't.
+GTEST_API_ std::string GetCurrentOsStackTraceExceptTop(
+    UnitTest* unit_test, int skip_count);
+
+// Helpers for suppressing warnings on unreachable code or constant
+// condition.
+
+// Always returns true.
+GTEST_API_ bool AlwaysTrue();
+
+// Always returns false.
+inline bool AlwaysFalse() { return !AlwaysTrue(); }
+
+// Helper for suppressing false warning from Clang on a const char*
+// variable declared in a conditional expression always being NULL in
+// the else branch.
+struct GTEST_API_ ConstCharPtr {
+  ConstCharPtr(const char* str) : value(str) {}
+  operator bool() const { return true; }
+  const char* value;
+};
+
+// A simple Linear Congruential Generator for generating random
+// numbers with a uniform distribution.  Unlike rand() and srand(), it
+// doesn't use global state (and therefore can't interfere with user
+// code).  Unlike rand_r(), it's portable.  An LCG isn't very random,
+// but it's good enough for our purposes.
+class GTEST_API_ Random {
+ public:
+  static const UInt32 kMaxRange = 1u << 31;
+
+  explicit Random(UInt32 seed) : state_(seed) {}
+
+  void Reseed(UInt32 seed) { state_ = seed; }
+
+  // Generates a random number from [0, range).  Crashes if 'range' is
+  // 0 or greater than kMaxRange.
+  UInt32 Generate(UInt32 range);
+
+ private:
+  UInt32 state_;
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Random);
+};
+
+// Defining a variable of type CompileAssertTypesEqual<T1, T2> will cause a
+// compiler error iff T1 and T2 are different types.
+template <typename T1, typename T2>
+struct CompileAssertTypesEqual;
+
+template <typename T>
+struct CompileAssertTypesEqual<T, T> {
+};
+
+// Removes the reference from a type if it is a reference type,
+// otherwise leaves it unchanged.  This is the same as
+// tr1::remove_reference, which is not widely available yet.
+template <typename T>
+struct RemoveReference { typedef T type; };  // NOLINT
+template <typename T>
+struct RemoveReference<T&> { typedef T type; };  // NOLINT
+
+// A handy wrapper around RemoveReference that works when the argument
+// T depends on template parameters.
+#define GTEST_REMOVE_REFERENCE_(T) \
+    typename ::testing::internal::RemoveReference<T>::type
+
+// Removes const from a type if it is a const type, otherwise leaves
+// it unchanged.  This is the same as tr1::remove_const, which is not
+// widely available yet.
+template <typename T>
+struct RemoveConst { typedef T type; };  // NOLINT
+template <typename T>
+struct RemoveConst<const T> { typedef T type; };  // NOLINT
+
+// MSVC 8.0, Sun C++, and IBM XL C++ have a bug which causes the above
+// definition to fail to remove the const in 'const int[3]' and 'const
+// char[3][4]'.  The following specialization works around the bug.
+template <typename T, size_t N>
+struct RemoveConst<const T[N]> {
+  typedef typename RemoveConst<T>::type type[N];
+};
+
+#if defined(_MSC_VER) && _MSC_VER < 1400
+// This is the only specialization that allows VC++ 7.1 to remove const in
+// 'const int[3] and 'const int[3][4]'.  However, it causes trouble with GCC
+// and thus needs to be conditionally compiled.
+template <typename T, size_t N>
+struct RemoveConst<T[N]> {
+  typedef typename RemoveConst<T>::type type[N];
+};
+#endif
+
+// A handy wrapper around RemoveConst that works when the argument
+// T depends on template parameters.
+#define GTEST_REMOVE_CONST_(T) \
+    typename ::testing::internal::RemoveConst<T>::type
+
+// Turns const U&, U&, const U, and U all into U.
+#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \
+    GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(T))
+
+// Adds reference to a type if it is not a reference type,
+// otherwise leaves it unchanged.  This is the same as
+// tr1::add_reference, which is not widely available yet.
+template <typename T>
+struct AddReference { typedef T& type; };  // NOLINT
+template <typename T>
+struct AddReference<T&> { typedef T& type; };  // NOLINT
+
+// A handy wrapper around AddReference that works when the argument T
+// depends on template parameters.
+#define GTEST_ADD_REFERENCE_(T) \
+    typename ::testing::internal::AddReference<T>::type
+
+// Adds a reference to const on top of T as necessary.  For example,
+// it transforms
+//
+//   char         ==> const char&
+//   const char   ==> const char&
+//   char&        ==> const char&
+//   const char&  ==> const char&
+//
+// The argument T must depend on some template parameters.
+#define GTEST_REFERENCE_TO_CONST_(T) \
+    GTEST_ADD_REFERENCE_(const GTEST_REMOVE_REFERENCE_(T))
+
+// ImplicitlyConvertible<From, To>::value is a compile-time bool
+// constant that's true iff type From can be implicitly converted to
+// type To.
+template <typename From, typename To>
+class ImplicitlyConvertible {
+ private:
+  // We need the following helper functions only for their types.
+  // They have no implementations.
+
+  // MakeFrom() is an expression whose type is From.  We cannot simply
+  // use From(), as the type From may not have a public default
+  // constructor.
+  static typename AddReference<From>::type MakeFrom();
+
+  // These two functions are overloaded.  Given an expression
+  // Helper(x), the compiler will pick the first version if x can be
+  // implicitly converted to type To; otherwise it will pick the
+  // second version.
+  //
+  // The first version returns a value of size 1, and the second
+  // version returns a value of size 2.  Therefore, by checking the
+  // size of Helper(x), which can be done at compile time, we can tell
+  // which version of Helper() is used, and hence whether x can be
+  // implicitly converted to type To.
+  static char Helper(To);
+  static char (&Helper(...))[2];  // NOLINT
+
+  // We have to put the 'public' section after the 'private' section,
+  // or MSVC refuses to compile the code.
+ public:
+#if defined(__BORLANDC__)
+  // C++Builder cannot use member overload resolution during template
+  // instantiation.  The simplest workaround is to use its C++0x type traits
+  // functions (C++Builder 2009 and above only).
+  static const bool value = __is_convertible(From, To);
+#else
+  // MSVC warns about implicitly converting from double to int for
+  // possible loss of data, so we need to temporarily disable the
+  // warning.
+  GTEST_DISABLE_MSC_WARNINGS_PUSH_(4244)
+  static const bool value =
+      sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
+  GTEST_DISABLE_MSC_WARNINGS_POP_()
+#endif  // __BORLANDC__
+};
+template <typename From, typename To>
+const bool ImplicitlyConvertible<From, To>::value;
+
+// IsAProtocolMessage<T>::value is a compile-time bool constant that's
+// true iff T is type ProtocolMessage, proto2::Message, or a subclass
+// of those.
+template <typename T>
+struct IsAProtocolMessage
+    : public bool_constant<
+  ImplicitlyConvertible<const T*, const ::ProtocolMessage*>::value ||
+  ImplicitlyConvertible<const T*, const ::proto2::Message*>::value> {
+};
+
+// When the compiler sees expression IsContainerTest<C>(0), if C is an
+// STL-style container class, the first overload of IsContainerTest
+// will be viable (since both C::iterator* and C::const_iterator* are
+// valid types and NULL can be implicitly converted to them).  It will
+// be picked over the second overload as 'int' is a perfect match for
+// the type of argument 0.  If C::iterator or C::const_iterator is not
+// a valid type, the first overload is not viable, and the second
+// overload will be picked.  Therefore, we can determine whether C is
+// a container class by checking the type of IsContainerTest<C>(0).
+// The value of the expression is insignificant.
+//
+// Note that we look for both C::iterator and C::const_iterator.  The
+// reason is that C++ injects the name of a class as a member of the
+// class itself (e.g. you can refer to class iterator as either
+// 'iterator' or 'iterator::iterator').  If we look for C::iterator
+// only, for example, we would mistakenly think that a class named
+// iterator is an STL container.
+//
+// Also note that the simpler approach of overloading
+// IsContainerTest(typename C::const_iterator*) and
+// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++.
+typedef int IsContainer;
+template <class C>
+IsContainer IsContainerTest(int /* dummy */,
+                            typename C::iterator* /* it */ = NULL,
+                            typename C::const_iterator* /* const_it */ = NULL) {
+  return 0;
+}
+
+typedef char IsNotContainer;
+template <class C>
+IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; }
+
+// EnableIf<condition>::type is void when 'Cond' is true, and
+// undefined when 'Cond' is false.  To use SFINAE to make a function
+// overload only apply when a particular expression is true, add
+// "typename EnableIf<expression>::type* = 0" as the last parameter.
+template<bool> struct EnableIf;
+template<> struct EnableIf<true> { typedef void type; };  // NOLINT
+
+// Utilities for native arrays.
+
+// ArrayEq() compares two k-dimensional native arrays using the
+// elements' operator==, where k can be any integer >= 0.  When k is
+// 0, ArrayEq() degenerates into comparing a single pair of values.
+
+template <typename T, typename U>
+bool ArrayEq(const T* lhs, size_t size, const U* rhs);
+
+// This generic version is used when k is 0.
+template <typename T, typename U>
+inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; }
+
+// This overload is used when k >= 1.
+template <typename T, typename U, size_t N>
+inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) {
+  return internal::ArrayEq(lhs, N, rhs);
+}
+
+// This helper reduces code bloat.  If we instead put its logic inside
+// the previous ArrayEq() function, arrays with different sizes would
+// lead to different copies of the template code.
+template <typename T, typename U>
+bool ArrayEq(const T* lhs, size_t size, const U* rhs) {
+  for (size_t i = 0; i != size; i++) {
+    if (!internal::ArrayEq(lhs[i], rhs[i]))
+      return false;
+  }
+  return true;
+}
+
+// Finds the first element in the iterator range [begin, end) that
+// equals elem.  Element may be a native array type itself.
+template <typename Iter, typename Element>
+Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) {
+  for (Iter it = begin; it != end; ++it) {
+    if (internal::ArrayEq(*it, elem))
+      return it;
+  }
+  return end;
+}
+
+// CopyArray() copies a k-dimensional native array using the elements'
+// operator=, where k can be any integer >= 0.  When k is 0,
+// CopyArray() degenerates into copying a single value.
+
+template <typename T, typename U>
+void CopyArray(const T* from, size_t size, U* to);
+
+// This generic version is used when k is 0.
+template <typename T, typename U>
+inline void CopyArray(const T& from, U* to) { *to = from; }
+
+// This overload is used when k >= 1.
+template <typename T, typename U, size_t N>
+inline void CopyArray(const T(&from)[N], U(*to)[N]) {
+  internal::CopyArray(from, N, *to);
+}
+
+// This helper reduces code bloat.  If we instead put its logic inside
+// the previous CopyArray() function, arrays with different sizes
+// would lead to different copies of the template code.
+template <typename T, typename U>
+void CopyArray(const T* from, size_t size, U* to) {
+  for (size_t i = 0; i != size; i++) {
+    internal::CopyArray(from[i], to + i);
+  }
+}
+
+// The relation between an NativeArray object (see below) and the
+// native array it represents.
+// We use 2 different structs to allow non-copyable types to be used, as long
+// as RelationToSourceReference() is passed.
+struct RelationToSourceReference {};
+struct RelationToSourceCopy {};
+
+// Adapts a native array to a read-only STL-style container.  Instead
+// of the complete STL container concept, this adaptor only implements
+// members useful for Google Mock's container matchers.  New members
+// should be added as needed.  To simplify the implementation, we only
+// support Element being a raw type (i.e. having no top-level const or
+// reference modifier).  It's the client's responsibility to satisfy
+// this requirement.  Element can be an array type itself (hence
+// multi-dimensional arrays are supported).
+template <typename Element>
+class NativeArray {
+ public:
+  // STL-style container typedefs.
+  typedef Element value_type;
+  typedef Element* iterator;
+  typedef const Element* const_iterator;
+
+  // Constructs from a native array. References the source.
+  NativeArray(const Element* array, size_t count, RelationToSourceReference) {
+    InitRef(array, count);
+  }
+
+  // Constructs from a native array. Copies the source.
+  NativeArray(const Element* array, size_t count, RelationToSourceCopy) {
+    InitCopy(array, count);
+  }
+
+  // Copy constructor.
+  NativeArray(const NativeArray& rhs) {
+    (this->*rhs.clone_)(rhs.array_, rhs.size_);
+  }
+
+  ~NativeArray() {
+    if (clone_ != &NativeArray::InitRef)
+      delete[] array_;
+  }
+
+  // STL-style container methods.
+  size_t size() const { return size_; }
+  const_iterator begin() const { return array_; }
+  const_iterator end() const { return array_ + size_; }
+  bool operator==(const NativeArray& rhs) const {
+    return size() == rhs.size() &&
+        ArrayEq(begin(), size(), rhs.begin());
+  }
+
+ private:
+  enum {
+    kCheckTypeIsNotConstOrAReference = StaticAssertTypeEqHelper<
+        Element, GTEST_REMOVE_REFERENCE_AND_CONST_(Element)>::value,
+  };
+
+  // Initializes this object with a copy of the input.
+  void InitCopy(const Element* array, size_t a_size) {
+    Element* const copy = new Element[a_size];
+    CopyArray(array, a_size, copy);
+    array_ = copy;
+    size_ = a_size;
+    clone_ = &NativeArray::InitCopy;
+  }
+
+  // Initializes this object with a reference of the input.
+  void InitRef(const Element* array, size_t a_size) {
+    array_ = array;
+    size_ = a_size;
+    clone_ = &NativeArray::InitRef;
+  }
+
+  const Element* array_;
+  size_t size_;
+  void (NativeArray::*clone_)(const Element*, size_t);
+
+  GTEST_DISALLOW_ASSIGN_(NativeArray);
+};
+
+}  // namespace internal
+}  // namespace testing
+
+#define GTEST_MESSAGE_AT_(file, line, message, result_type) \
+  ::testing::internal::AssertHelper(result_type, file, line, message) \
+    = ::testing::Message()
+
+#define GTEST_MESSAGE_(message, result_type) \
+  GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type)
+
+#define GTEST_FATAL_FAILURE_(message) \
+  return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure)
+
+#define GTEST_NONFATAL_FAILURE_(message) \
+  GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure)
+
+#define GTEST_SUCCESS_(message) \
+  GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess)
+
+// Suppresses MSVC warnings 4072 (unreachable code) for the code following
+// statement if it returns or throws (or doesn't return or throw in some
+// situations).
+#define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \
+  if (::testing::internal::AlwaysTrue()) { statement; }
+
+#define GTEST_TEST_THROW_(statement, expected_exception, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::ConstCharPtr gtest_msg = "") { \
+    bool gtest_caught_expected = false; \
+    try { \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+    } \
+    catch (expected_exception const&) { \
+      gtest_caught_expected = true; \
+    } \
+    catch (...) { \
+      gtest_msg.value = \
+          "Expected: " #statement " throws an exception of type " \
+          #expected_exception ".\n  Actual: it throws a different type."; \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
+    } \
+    if (!gtest_caught_expected) { \
+      gtest_msg.value = \
+          "Expected: " #statement " throws an exception of type " \
+          #expected_exception ".\n  Actual: it throws nothing."; \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \
+      fail(gtest_msg.value)
+
+#define GTEST_TEST_NO_THROW_(statement, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+    try { \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+    } \
+    catch (...) { \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \
+      fail("Expected: " #statement " doesn't throw an exception.\n" \
+           "  Actual: it throws.")
+
+#define GTEST_TEST_ANY_THROW_(statement, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+    bool gtest_caught_any = false; \
+    try { \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+    } \
+    catch (...) { \
+      gtest_caught_any = true; \
+    } \
+    if (!gtest_caught_any) { \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__): \
+      fail("Expected: " #statement " throws an exception.\n" \
+           "  Actual: it doesn't.")
+
+
+// Implements Boolean test assertions such as EXPECT_TRUE. expression can be
+// either a boolean expression or an AssertionResult. text is a textual
+// represenation of expression as it was passed into the EXPECT_TRUE.
+#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (const ::testing::AssertionResult gtest_ar_ = \
+      ::testing::AssertionResult(expression)) \
+    ; \
+  else \
+    fail(::testing::internal::GetBoolAssertionFailureMessage(\
+        gtest_ar_, text, #actual, #expected).c_str())
+
+#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+    ::testing::internal::HasNewFatalFailureHelper gtest_fatal_failure_checker; \
+    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+    if (gtest_fatal_failure_checker.has_new_fatal_failure()) { \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__); \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__): \
+      fail("Expected: " #statement " doesn't generate new fatal " \
+           "failures in the current thread.\n" \
+           "  Actual: it does.")
+
+// Expands to the name of the class that implements the given test.
+#define GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
+  test_case_name##_##test_name##_Test
+
+// Helper macro for defining tests.
+#define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\
+class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\
+ public:\
+  GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\
+ private:\
+  virtual void TestBody();\
+  static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(\
+      GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\
+};\
+\
+::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\
+  ::test_info_ =\
+    ::testing::internal::MakeAndRegisterTestInfo(\
+        #test_case_name, #test_name, NULL, NULL, \
+        ::testing::internal::CodeLocation(__FILE__, __LINE__), \
+        (parent_id), \
+        parent_class::SetUpTestCase, \
+        parent_class::TearDownTestCase, \
+        new ::testing::internal::TestFactoryImpl<\
+            GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\
+void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
+
diff --git a/third_party/googletest/googletest/include/gtest/internal/gtest-linked_ptr.h b/third_party/googletest/googletest/include/gtest/internal/gtest-linked_ptr.h
new file mode 100644
index 0000000..3602942
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/internal/gtest-linked_ptr.h
@@ -0,0 +1,243 @@
+// Copyright 2003 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: Dan Egnor (egnor@google.com)
+//
+// A "smart" pointer type with reference tracking.  Every pointer to a
+// particular object is kept on a circular linked list.  When the last pointer
+// to an object is destroyed or reassigned, the object is deleted.
+//
+// Used properly, this deletes the object when the last reference goes away.
+// There are several caveats:
+// - Like all reference counting schemes, cycles lead to leaks.
+// - Each smart pointer is actually two pointers (8 bytes instead of 4).
+// - Every time a pointer is assigned, the entire list of pointers to that
+//   object is traversed.  This class is therefore NOT SUITABLE when there
+//   will often be more than two or three pointers to a particular object.
+// - References are only tracked as long as linked_ptr<> objects are copied.
+//   If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS
+//   will happen (double deletion).
+//
+// A good use of this class is storing object references in STL containers.
+// You can safely put linked_ptr<> in a vector<>.
+// Other uses may not be as good.
+//
+// Note: If you use an incomplete type with linked_ptr<>, the class
+// *containing* linked_ptr<> must have a constructor and destructor (even
+// if they do nothing!).
+//
+// Bill Gibbons suggested we use something like this.
+//
+// Thread Safety:
+//   Unlike other linked_ptr implementations, in this implementation
+//   a linked_ptr object is thread-safe in the sense that:
+//     - it's safe to copy linked_ptr objects concurrently,
+//     - it's safe to copy *from* a linked_ptr and read its underlying
+//       raw pointer (e.g. via get()) concurrently, and
+//     - it's safe to write to two linked_ptrs that point to the same
+//       shared object concurrently.
+// TODO(wan@google.com): rename this to safe_linked_ptr to avoid
+// confusion with normal linked_ptr.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
+
+#include <stdlib.h>
+#include <assert.h>
+
+#include "gtest/internal/gtest-port.h"
+
+namespace testing {
+namespace internal {
+
+// Protects copying of all linked_ptr objects.
+GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex);
+
+// This is used internally by all instances of linked_ptr<>.  It needs to be
+// a non-template class because different types of linked_ptr<> can refer to
+// the same object (linked_ptr<Superclass>(obj) vs linked_ptr<Subclass>(obj)).
+// So, it needs to be possible for different types of linked_ptr to participate
+// in the same circular linked list, so we need a single class type here.
+//
+// DO NOT USE THIS CLASS DIRECTLY YOURSELF.  Use linked_ptr<T>.
+class linked_ptr_internal {
+ public:
+  // Create a new circle that includes only this instance.
+  void join_new() {
+    next_ = this;
+  }
+
+  // Many linked_ptr operations may change p.link_ for some linked_ptr
+  // variable p in the same circle as this object.  Therefore we need
+  // to prevent two such operations from occurring concurrently.
+  //
+  // Note that different types of linked_ptr objects can coexist in a
+  // circle (e.g. linked_ptr<Base>, linked_ptr<Derived1>, and
+  // linked_ptr<Derived2>).  Therefore we must use a single mutex to
+  // protect all linked_ptr objects.  This can create serious
+  // contention in production code, but is acceptable in a testing
+  // framework.
+
+  // Join an existing circle.
+  void join(linked_ptr_internal const* ptr)
+      GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) {
+    MutexLock lock(&g_linked_ptr_mutex);
+
+    linked_ptr_internal const* p = ptr;
+    while (p->next_ != ptr) {
+      assert(p->next_ != this &&
+             "Trying to join() a linked ring we are already in. "
+             "Is GMock thread safety enabled?");
+      p = p->next_;
+    }
+    p->next_ = this;
+    next_ = ptr;
+  }
+
+  // Leave whatever circle we're part of.  Returns true if we were the
+  // last member of the circle.  Once this is done, you can join() another.
+  bool depart()
+      GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) {
+    MutexLock lock(&g_linked_ptr_mutex);
+
+    if (next_ == this) return true;
+    linked_ptr_internal const* p = next_;
+    while (p->next_ != this) {
+      assert(p->next_ != next_ &&
+             "Trying to depart() a linked ring we are not in. "
+             "Is GMock thread safety enabled?");
+      p = p->next_;
+    }
+    p->next_ = next_;
+    return false;
+  }
+
+ private:
+  mutable linked_ptr_internal const* next_;
+};
+
+template <typename T>
+class linked_ptr {
+ public:
+  typedef T element_type;
+
+  // Take over ownership of a raw pointer.  This should happen as soon as
+  // possible after the object is created.
+  explicit linked_ptr(T* ptr = NULL) { capture(ptr); }
+  ~linked_ptr() { depart(); }
+
+  // Copy an existing linked_ptr<>, adding ourselves to the list of references.
+  template <typename U> linked_ptr(linked_ptr<U> const& ptr) { copy(&ptr); }
+  linked_ptr(linked_ptr const& ptr) {  // NOLINT
+    assert(&ptr != this);
+    copy(&ptr);
+  }
+
+  // Assignment releases the old value and acquires the new.
+  template <typename U> linked_ptr& operator=(linked_ptr<U> const& ptr) {
+    depart();
+    copy(&ptr);
+    return *this;
+  }
+
+  linked_ptr& operator=(linked_ptr const& ptr) {
+    if (&ptr != this) {
+      depart();
+      copy(&ptr);
+    }
+    return *this;
+  }
+
+  // Smart pointer members.
+  void reset(T* ptr = NULL) {
+    depart();
+    capture(ptr);
+  }
+  T* get() const { return value_; }
+  T* operator->() const { return value_; }
+  T& operator*() const { return *value_; }
+
+  bool operator==(T* p) const { return value_ == p; }
+  bool operator!=(T* p) const { return value_ != p; }
+  template <typename U>
+  bool operator==(linked_ptr<U> const& ptr) const {
+    return value_ == ptr.get();
+  }
+  template <typename U>
+  bool operator!=(linked_ptr<U> const& ptr) const {
+    return value_ != ptr.get();
+  }
+
+ private:
+  template <typename U>
+  friend class linked_ptr;
+
+  T* value_;
+  linked_ptr_internal link_;
+
+  void depart() {
+    if (link_.depart()) delete value_;
+  }
+
+  void capture(T* ptr) {
+    value_ = ptr;
+    link_.join_new();
+  }
+
+  template <typename U> void copy(linked_ptr<U> const* ptr) {
+    value_ = ptr->get();
+    if (value_)
+      link_.join(&ptr->link_);
+    else
+      link_.join_new();
+  }
+};
+
+template<typename T> inline
+bool operator==(T* ptr, const linked_ptr<T>& x) {
+  return ptr == x.get();
+}
+
+template<typename T> inline
+bool operator!=(T* ptr, const linked_ptr<T>& x) {
+  return ptr != x.get();
+}
+
+// A function to convert T* into linked_ptr<T>
+// Doing e.g. make_linked_ptr(new FooBarBaz<type>(arg)) is a shorter notation
+// for linked_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg))
+template <typename T>
+linked_ptr<T> make_linked_ptr(T* ptr) {
+  return linked_ptr<T>(ptr);
+}
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
diff --git a/third_party/googletest/googletest/include/gtest/internal/gtest-param-util-generated.h b/third_party/googletest/googletest/include/gtest/internal/gtest-param-util-generated.h
new file mode 100644
index 0000000..4d1d81d
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/internal/gtest-param-util-generated.h
@@ -0,0 +1,5146 @@
+// This file was GENERATED by command:
+//     pump.py gtest-param-util-generated.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vladl@google.com (Vlad Losev)
+
+// Type and function utilities for implementing parameterized tests.
+// This file is generated by a SCRIPT.  DO NOT EDIT BY HAND!
+//
+// Currently Google Test supports at most 50 arguments in Values,
+// and at most 10 arguments in Combine. Please contact
+// googletestframework@googlegroups.com if you need more.
+// Please note that the number of arguments to Combine is limited
+// by the maximum arity of the implementation of tuple which is
+// currently set at 10.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*.  Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+#include "gtest/internal/gtest-param-util.h"
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+
+// Forward declarations of ValuesIn(), which is implemented in
+// include/gtest/gtest-param-test.h.
+template <typename ForwardIterator>
+internal::ParamGenerator<
+  typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end);
+
+template <typename T, size_t N>
+internal::ParamGenerator<T> ValuesIn(const T (&array)[N]);
+
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+    const Container& container);
+
+namespace internal {
+
+// Used in the Values() function to provide polymorphic capabilities.
+template <typename T1>
+class ValueArray1 {
+ public:
+  explicit ValueArray1(T1 v1) : v1_(v1) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray1& other);
+
+  const T1 v1_;
+};
+
+template <typename T1, typename T2>
+class ValueArray2 {
+ public:
+  ValueArray2(T1 v1, T2 v2) : v1_(v1), v2_(v2) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray2& other);
+
+  const T1 v1_;
+  const T2 v2_;
+};
+
+template <typename T1, typename T2, typename T3>
+class ValueArray3 {
+ public:
+  ValueArray3(T1 v1, T2 v2, T3 v3) : v1_(v1), v2_(v2), v3_(v3) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray3& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4>
+class ValueArray4 {
+ public:
+  ValueArray4(T1 v1, T2 v2, T3 v3, T4 v4) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray4& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+class ValueArray5 {
+ public:
+  ValueArray5(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray5& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+class ValueArray6 {
+ public:
+  ValueArray6(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray6& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+class ValueArray7 {
+ public:
+  ValueArray7(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray7& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+class ValueArray8 {
+ public:
+  ValueArray8(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+      T8 v8) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray8& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+class ValueArray9 {
+ public:
+  ValueArray9(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+      T9 v9) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray9& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+class ValueArray10 {
+ public:
+  ValueArray10(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray10& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11>
+class ValueArray11 {
+ public:
+  ValueArray11(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray11& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12>
+class ValueArray12 {
+ public:
+  ValueArray12(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray12& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13>
+class ValueArray13 {
+ public:
+  ValueArray13(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray13& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14>
+class ValueArray14 {
+ public:
+  ValueArray14(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray14& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15>
+class ValueArray15 {
+ public:
+  ValueArray15(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray15& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16>
+class ValueArray16 {
+ public:
+  ValueArray16(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray16& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17>
+class ValueArray17 {
+ public:
+  ValueArray17(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16,
+      T17 v17) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray17& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18>
+class ValueArray18 {
+ public:
+  ValueArray18(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray18& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19>
+class ValueArray19 {
+ public:
+  ValueArray19(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+      v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray19& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20>
+class ValueArray20 {
+ public:
+  ValueArray20(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+      v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+      v19_(v19), v20_(v20) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray20& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21>
+class ValueArray21 {
+ public:
+  ValueArray21(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+      v18_(v18), v19_(v19), v20_(v20), v21_(v21) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray21& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22>
+class ValueArray22 {
+ public:
+  ValueArray22(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray22& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23>
+class ValueArray23 {
+ public:
+  ValueArray23(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray23& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24>
+class ValueArray24 {
+ public:
+  ValueArray24(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+      v22_(v22), v23_(v23), v24_(v24) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray24& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25>
+class ValueArray25 {
+ public:
+  ValueArray25(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24,
+      T25 v25) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray25& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26>
+class ValueArray26 {
+ public:
+  ValueArray26(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray26& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27>
+class ValueArray27 {
+ public:
+  ValueArray27(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+      v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19),
+      v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25),
+      v26_(v26), v27_(v27) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray27& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28>
+class ValueArray28 {
+ public:
+  ValueArray28(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+      v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+      v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24),
+      v25_(v25), v26_(v26), v27_(v27), v28_(v28) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray28& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29>
+class ValueArray29 {
+ public:
+  ValueArray29(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+      v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23),
+      v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray29& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30>
+class ValueArray30 {
+ public:
+  ValueArray30(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray30& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31>
+class ValueArray31 {
+ public:
+  ValueArray31(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray31& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32>
+class ValueArray32 {
+ public:
+  ValueArray32(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+      v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27),
+      v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray32& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33>
+class ValueArray33 {
+ public:
+  ValueArray33(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32,
+      T33 v33) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray33& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34>
+class ValueArray34 {
+ public:
+  ValueArray34(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray34& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35>
+class ValueArray35 {
+ public:
+  ValueArray35(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+      v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19),
+      v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25),
+      v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31),
+      v32_(v32), v33_(v33), v34_(v34), v35_(v35) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray35& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36>
+class ValueArray36 {
+ public:
+  ValueArray36(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+      v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+      v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24),
+      v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30),
+      v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray36& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37>
+class ValueArray37 {
+ public:
+  ValueArray37(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+      v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23),
+      v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29),
+      v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35),
+      v36_(v36), v37_(v37) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray37& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38>
+class ValueArray38 {
+ public:
+  ValueArray38(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+      v35_(v35), v36_(v36), v37_(v37), v38_(v38) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray38& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39>
+class ValueArray39 {
+ public:
+  ValueArray39(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+      v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray39& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40>
+class ValueArray40 {
+ public:
+  ValueArray40(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+      v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27),
+      v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33),
+      v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39),
+      v40_(v40) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray40& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41>
+class ValueArray41 {
+ public:
+  ValueArray41(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40,
+      T41 v41) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+      v39_(v39), v40_(v40), v41_(v41) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray41& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42>
+class ValueArray42 {
+ public:
+  ValueArray42(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+      v39_(v39), v40_(v40), v41_(v41), v42_(v42) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+        static_cast<T>(v42_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray42& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43>
+class ValueArray43 {
+ public:
+  ValueArray43(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+      v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19),
+      v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25),
+      v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31),
+      v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37),
+      v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+        static_cast<T>(v42_), static_cast<T>(v43_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray43& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44>
+class ValueArray44 {
+ public:
+  ValueArray44(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+      v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+      v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24),
+      v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30),
+      v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36),
+      v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42),
+      v43_(v43), v44_(v44) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+        static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray44& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45>
+class ValueArray45 {
+ public:
+  ValueArray45(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+      v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23),
+      v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29),
+      v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35),
+      v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41),
+      v42_(v42), v43_(v43), v44_(v44), v45_(v45) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+        static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_),
+        static_cast<T>(v45_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray45& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46>
+class ValueArray46 {
+ public:
+  ValueArray46(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+      v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40),
+      v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+        static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_),
+        static_cast<T>(v45_), static_cast<T>(v46_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray46& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47>
+class ValueArray47 {
+ public:
+  ValueArray47(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+      v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40),
+      v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46),
+      v47_(v47) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+        static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_),
+        static_cast<T>(v45_), static_cast<T>(v46_), static_cast<T>(v47_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray47& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+  const T47 v47_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48>
+class ValueArray48 {
+ public:
+  ValueArray48(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+      v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27),
+      v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33),
+      v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39),
+      v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45),
+      v46_(v46), v47_(v47), v48_(v48) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+        static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_),
+        static_cast<T>(v45_), static_cast<T>(v46_), static_cast<T>(v47_),
+        static_cast<T>(v48_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray48& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+  const T47 v47_;
+  const T48 v48_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49>
+class ValueArray49 {
+ public:
+  ValueArray49(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48,
+      T49 v49) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+      v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44),
+      v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+        static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_),
+        static_cast<T>(v45_), static_cast<T>(v46_), static_cast<T>(v47_),
+        static_cast<T>(v48_), static_cast<T>(v49_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray49& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+  const T47 v47_;
+  const T48 v48_;
+  const T49 v49_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49, typename T50>
+class ValueArray50 {
+ public:
+  ValueArray50(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, T49 v49,
+      T50 v50) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+      v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44),
+      v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49), v50_(v50) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+        static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_),
+        static_cast<T>(v45_), static_cast<T>(v46_), static_cast<T>(v47_),
+        static_cast<T>(v48_), static_cast<T>(v49_), static_cast<T>(v50_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray50& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+  const T47 v47_;
+  const T48 v48_;
+  const T49 v49_;
+  const T50 v50_;
+};
+
+# if GTEST_HAS_COMBINE
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Generates values from the Cartesian product of values produced
+// by the argument generators.
+//
+template <typename T1, typename T2>
+class CartesianProductGenerator2
+    : public ParamGeneratorInterface< ::testing::tuple<T1, T2> > {
+ public:
+  typedef ::testing::tuple<T1, T2> ParamType;
+
+  CartesianProductGenerator2(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2)
+      : g1_(g1), g2_(g2) {}
+  virtual ~CartesianProductGenerator2() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current2_;
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator2::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator2& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+};  // class CartesianProductGenerator2
+
+
+template <typename T1, typename T2, typename T3>
+class CartesianProductGenerator3
+    : public ParamGeneratorInterface< ::testing::tuple<T1, T2, T3> > {
+ public:
+  typedef ::testing::tuple<T1, T2, T3> ParamType;
+
+  CartesianProductGenerator3(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3)
+      : g1_(g1), g2_(g2), g3_(g3) {}
+  virtual ~CartesianProductGenerator3() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current3_;
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator3::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator3& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+};  // class CartesianProductGenerator3
+
+
+template <typename T1, typename T2, typename T3, typename T4>
+class CartesianProductGenerator4
+    : public ParamGeneratorInterface< ::testing::tuple<T1, T2, T3, T4> > {
+ public:
+  typedef ::testing::tuple<T1, T2, T3, T4> ParamType;
+
+  CartesianProductGenerator4(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {}
+  virtual ~CartesianProductGenerator4() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current4_;
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator4::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator4& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+};  // class CartesianProductGenerator4
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+class CartesianProductGenerator5
+    : public ParamGeneratorInterface< ::testing::tuple<T1, T2, T3, T4, T5> > {
+ public:
+  typedef ::testing::tuple<T1, T2, T3, T4, T5> ParamType;
+
+  CartesianProductGenerator5(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {}
+  virtual ~CartesianProductGenerator5() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current5_;
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator5::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator5& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+};  // class CartesianProductGenerator5
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+class CartesianProductGenerator6
+    : public ParamGeneratorInterface< ::testing::tuple<T1, T2, T3, T4, T5,
+        T6> > {
+ public:
+  typedef ::testing::tuple<T1, T2, T3, T4, T5, T6> ParamType;
+
+  CartesianProductGenerator6(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {}
+  virtual ~CartesianProductGenerator6() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current6_;
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator6::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator6& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+};  // class CartesianProductGenerator6
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+class CartesianProductGenerator7
+    : public ParamGeneratorInterface< ::testing::tuple<T1, T2, T3, T4, T5, T6,
+        T7> > {
+ public:
+  typedef ::testing::tuple<T1, T2, T3, T4, T5, T6, T7> ParamType;
+
+  CartesianProductGenerator7(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {}
+  virtual ~CartesianProductGenerator7() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+        g7_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6,
+      const ParamGenerator<T7>& g7,
+      const typename ParamGenerator<T7>::iterator& current7)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+          begin7_(g7.begin()), end7_(g7.end()), current7_(current7)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current7_;
+      if (current7_ == end7_) {
+        current7_ = begin7_;
+        ++current6_;
+      }
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_ &&
+          current7_ == typed_other->current7_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_),
+        begin7_(other.begin7_),
+        end7_(other.end7_),
+        current7_(other.current7_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_, *current7_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_ ||
+          current7_ == end7_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    const typename ParamGenerator<T7>::iterator begin7_;
+    const typename ParamGenerator<T7>::iterator end7_;
+    typename ParamGenerator<T7>::iterator current7_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator7::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator7& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+  const ParamGenerator<T7> g7_;
+};  // class CartesianProductGenerator7
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+class CartesianProductGenerator8
+    : public ParamGeneratorInterface< ::testing::tuple<T1, T2, T3, T4, T5, T6,
+        T7, T8> > {
+ public:
+  typedef ::testing::tuple<T1, T2, T3, T4, T5, T6, T7, T8> ParamType;
+
+  CartesianProductGenerator8(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7,
+      const ParamGenerator<T8>& g8)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7),
+          g8_(g8) {}
+  virtual ~CartesianProductGenerator8() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+        g7_.begin(), g8_, g8_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_,
+        g8_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6,
+      const ParamGenerator<T7>& g7,
+      const typename ParamGenerator<T7>::iterator& current7,
+      const ParamGenerator<T8>& g8,
+      const typename ParamGenerator<T8>::iterator& current8)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+          begin7_(g7.begin()), end7_(g7.end()), current7_(current7),
+          begin8_(g8.begin()), end8_(g8.end()), current8_(current8)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current8_;
+      if (current8_ == end8_) {
+        current8_ = begin8_;
+        ++current7_;
+      }
+      if (current7_ == end7_) {
+        current7_ = begin7_;
+        ++current6_;
+      }
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_ &&
+          current7_ == typed_other->current7_ &&
+          current8_ == typed_other->current8_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_),
+        begin7_(other.begin7_),
+        end7_(other.end7_),
+        current7_(other.current7_),
+        begin8_(other.begin8_),
+        end8_(other.end8_),
+        current8_(other.current8_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_, *current7_, *current8_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_ ||
+          current7_ == end7_ ||
+          current8_ == end8_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    const typename ParamGenerator<T7>::iterator begin7_;
+    const typename ParamGenerator<T7>::iterator end7_;
+    typename ParamGenerator<T7>::iterator current7_;
+    const typename ParamGenerator<T8>::iterator begin8_;
+    const typename ParamGenerator<T8>::iterator end8_;
+    typename ParamGenerator<T8>::iterator current8_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator8::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator8& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+  const ParamGenerator<T7> g7_;
+  const ParamGenerator<T8> g8_;
+};  // class CartesianProductGenerator8
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+class CartesianProductGenerator9
+    : public ParamGeneratorInterface< ::testing::tuple<T1, T2, T3, T4, T5, T6,
+        T7, T8, T9> > {
+ public:
+  typedef ::testing::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9> ParamType;
+
+  CartesianProductGenerator9(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7,
+      const ParamGenerator<T8>& g8, const ParamGenerator<T9>& g9)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+          g9_(g9) {}
+  virtual ~CartesianProductGenerator9() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+        g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_,
+        g8_.end(), g9_, g9_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6,
+      const ParamGenerator<T7>& g7,
+      const typename ParamGenerator<T7>::iterator& current7,
+      const ParamGenerator<T8>& g8,
+      const typename ParamGenerator<T8>::iterator& current8,
+      const ParamGenerator<T9>& g9,
+      const typename ParamGenerator<T9>::iterator& current9)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+          begin7_(g7.begin()), end7_(g7.end()), current7_(current7),
+          begin8_(g8.begin()), end8_(g8.end()), current8_(current8),
+          begin9_(g9.begin()), end9_(g9.end()), current9_(current9)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current9_;
+      if (current9_ == end9_) {
+        current9_ = begin9_;
+        ++current8_;
+      }
+      if (current8_ == end8_) {
+        current8_ = begin8_;
+        ++current7_;
+      }
+      if (current7_ == end7_) {
+        current7_ = begin7_;
+        ++current6_;
+      }
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_ &&
+          current7_ == typed_other->current7_ &&
+          current8_ == typed_other->current8_ &&
+          current9_ == typed_other->current9_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_),
+        begin7_(other.begin7_),
+        end7_(other.end7_),
+        current7_(other.current7_),
+        begin8_(other.begin8_),
+        end8_(other.end8_),
+        current8_(other.current8_),
+        begin9_(other.begin9_),
+        end9_(other.end9_),
+        current9_(other.current9_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_, *current7_, *current8_,
+            *current9_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_ ||
+          current7_ == end7_ ||
+          current8_ == end8_ ||
+          current9_ == end9_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    const typename ParamGenerator<T7>::iterator begin7_;
+    const typename ParamGenerator<T7>::iterator end7_;
+    typename ParamGenerator<T7>::iterator current7_;
+    const typename ParamGenerator<T8>::iterator begin8_;
+    const typename ParamGenerator<T8>::iterator end8_;
+    typename ParamGenerator<T8>::iterator current8_;
+    const typename ParamGenerator<T9>::iterator begin9_;
+    const typename ParamGenerator<T9>::iterator end9_;
+    typename ParamGenerator<T9>::iterator current9_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator9::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator9& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+  const ParamGenerator<T7> g7_;
+  const ParamGenerator<T8> g8_;
+  const ParamGenerator<T9> g9_;
+};  // class CartesianProductGenerator9
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+class CartesianProductGenerator10
+    : public ParamGeneratorInterface< ::testing::tuple<T1, T2, T3, T4, T5, T6,
+        T7, T8, T9, T10> > {
+ public:
+  typedef ::testing::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ParamType;
+
+  CartesianProductGenerator10(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7,
+      const ParamGenerator<T8>& g8, const ParamGenerator<T9>& g9,
+      const ParamGenerator<T10>& g10)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+          g9_(g9), g10_(g10) {}
+  virtual ~CartesianProductGenerator10() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+        g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin(), g10_, g10_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_,
+        g8_.end(), g9_, g9_.end(), g10_, g10_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6,
+      const ParamGenerator<T7>& g7,
+      const typename ParamGenerator<T7>::iterator& current7,
+      const ParamGenerator<T8>& g8,
+      const typename ParamGenerator<T8>::iterator& current8,
+      const ParamGenerator<T9>& g9,
+      const typename ParamGenerator<T9>::iterator& current9,
+      const ParamGenerator<T10>& g10,
+      const typename ParamGenerator<T10>::iterator& current10)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+          begin7_(g7.begin()), end7_(g7.end()), current7_(current7),
+          begin8_(g8.begin()), end8_(g8.end()), current8_(current8),
+          begin9_(g9.begin()), end9_(g9.end()), current9_(current9),
+          begin10_(g10.begin()), end10_(g10.end()), current10_(current10)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current10_;
+      if (current10_ == end10_) {
+        current10_ = begin10_;
+        ++current9_;
+      }
+      if (current9_ == end9_) {
+        current9_ = begin9_;
+        ++current8_;
+      }
+      if (current8_ == end8_) {
+        current8_ = begin8_;
+        ++current7_;
+      }
+      if (current7_ == end7_) {
+        current7_ = begin7_;
+        ++current6_;
+      }
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_ &&
+          current7_ == typed_other->current7_ &&
+          current8_ == typed_other->current8_ &&
+          current9_ == typed_other->current9_ &&
+          current10_ == typed_other->current10_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_),
+        begin7_(other.begin7_),
+        end7_(other.end7_),
+        current7_(other.current7_),
+        begin8_(other.begin8_),
+        end8_(other.end8_),
+        current8_(other.current8_),
+        begin9_(other.begin9_),
+        end9_(other.end9_),
+        current9_(other.current9_),
+        begin10_(other.begin10_),
+        end10_(other.end10_),
+        current10_(other.current10_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_, *current7_, *current8_,
+            *current9_, *current10_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_ ||
+          current7_ == end7_ ||
+          current8_ == end8_ ||
+          current9_ == end9_ ||
+          current10_ == end10_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    const typename ParamGenerator<T7>::iterator begin7_;
+    const typename ParamGenerator<T7>::iterator end7_;
+    typename ParamGenerator<T7>::iterator current7_;
+    const typename ParamGenerator<T8>::iterator begin8_;
+    const typename ParamGenerator<T8>::iterator end8_;
+    typename ParamGenerator<T8>::iterator current8_;
+    const typename ParamGenerator<T9>::iterator begin9_;
+    const typename ParamGenerator<T9>::iterator end9_;
+    typename ParamGenerator<T9>::iterator current9_;
+    const typename ParamGenerator<T10>::iterator begin10_;
+    const typename ParamGenerator<T10>::iterator end10_;
+    typename ParamGenerator<T10>::iterator current10_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator10::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator10& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+  const ParamGenerator<T7> g7_;
+  const ParamGenerator<T8> g8_;
+  const ParamGenerator<T9> g9_;
+  const ParamGenerator<T10> g10_;
+};  // class CartesianProductGenerator10
+
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Helper classes providing Combine() with polymorphic features. They allow
+// casting CartesianProductGeneratorN<T> to ParamGenerator<U> if T is
+// convertible to U.
+//
+template <class Generator1, class Generator2>
+class CartesianProductHolder2 {
+ public:
+CartesianProductHolder2(const Generator1& g1, const Generator2& g2)
+      : g1_(g1), g2_(g2) {}
+  template <typename T1, typename T2>
+  operator ParamGenerator< ::testing::tuple<T1, T2> >() const {
+    return ParamGenerator< ::testing::tuple<T1, T2> >(
+        new CartesianProductGenerator2<T1, T2>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder2& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+};  // class CartesianProductHolder2
+
+template <class Generator1, class Generator2, class Generator3>
+class CartesianProductHolder3 {
+ public:
+CartesianProductHolder3(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3)
+      : g1_(g1), g2_(g2), g3_(g3) {}
+  template <typename T1, typename T2, typename T3>
+  operator ParamGenerator< ::testing::tuple<T1, T2, T3> >() const {
+    return ParamGenerator< ::testing::tuple<T1, T2, T3> >(
+        new CartesianProductGenerator3<T1, T2, T3>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder3& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+};  // class CartesianProductHolder3
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4>
+class CartesianProductHolder4 {
+ public:
+CartesianProductHolder4(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {}
+  template <typename T1, typename T2, typename T3, typename T4>
+  operator ParamGenerator< ::testing::tuple<T1, T2, T3, T4> >() const {
+    return ParamGenerator< ::testing::tuple<T1, T2, T3, T4> >(
+        new CartesianProductGenerator4<T1, T2, T3, T4>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder4& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+};  // class CartesianProductHolder4
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5>
+class CartesianProductHolder5 {
+ public:
+CartesianProductHolder5(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5>
+  operator ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5> >() const {
+    return ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5> >(
+        new CartesianProductGenerator5<T1, T2, T3, T4, T5>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder5& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+};  // class CartesianProductHolder5
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6>
+class CartesianProductHolder6 {
+ public:
+CartesianProductHolder6(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6>
+  operator ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6> >() const {
+    return ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6> >(
+        new CartesianProductGenerator6<T1, T2, T3, T4, T5, T6>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder6& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+};  // class CartesianProductHolder6
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6, class Generator7>
+class CartesianProductHolder7 {
+ public:
+CartesianProductHolder7(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6, const Generator7& g7)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6, typename T7>
+  operator ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6,
+      T7> >() const {
+    return ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6, T7> >(
+        new CartesianProductGenerator7<T1, T2, T3, T4, T5, T6, T7>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_),
+        static_cast<ParamGenerator<T7> >(g7_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder7& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+  const Generator7 g7_;
+};  // class CartesianProductHolder7
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6, class Generator7,
+    class Generator8>
+class CartesianProductHolder8 {
+ public:
+CartesianProductHolder8(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6, const Generator7& g7, const Generator8& g8)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7),
+          g8_(g8) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6, typename T7, typename T8>
+  operator ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6, T7,
+      T8> >() const {
+    return ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6, T7, T8> >(
+        new CartesianProductGenerator8<T1, T2, T3, T4, T5, T6, T7, T8>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_),
+        static_cast<ParamGenerator<T7> >(g7_),
+        static_cast<ParamGenerator<T8> >(g8_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder8& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+  const Generator7 g7_;
+  const Generator8 g8_;
+};  // class CartesianProductHolder8
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6, class Generator7,
+    class Generator8, class Generator9>
+class CartesianProductHolder9 {
+ public:
+CartesianProductHolder9(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6, const Generator7& g7, const Generator8& g8,
+    const Generator9& g9)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+          g9_(g9) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6, typename T7, typename T8, typename T9>
+  operator ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+      T9> >() const {
+    return ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+        T9> >(
+        new CartesianProductGenerator9<T1, T2, T3, T4, T5, T6, T7, T8, T9>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_),
+        static_cast<ParamGenerator<T7> >(g7_),
+        static_cast<ParamGenerator<T8> >(g8_),
+        static_cast<ParamGenerator<T9> >(g9_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder9& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+  const Generator7 g7_;
+  const Generator8 g8_;
+  const Generator9 g9_;
+};  // class CartesianProductHolder9
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6, class Generator7,
+    class Generator8, class Generator9, class Generator10>
+class CartesianProductHolder10 {
+ public:
+CartesianProductHolder10(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6, const Generator7& g7, const Generator8& g8,
+    const Generator9& g9, const Generator10& g10)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+          g9_(g9), g10_(g10) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6, typename T7, typename T8, typename T9, typename T10>
+  operator ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9,
+      T10> >() const {
+    return ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9,
+        T10> >(
+        new CartesianProductGenerator10<T1, T2, T3, T4, T5, T6, T7, T8, T9,
+            T10>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_),
+        static_cast<ParamGenerator<T7> >(g7_),
+        static_cast<ParamGenerator<T8> >(g8_),
+        static_cast<ParamGenerator<T9> >(g9_),
+        static_cast<ParamGenerator<T10> >(g10_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder10& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+  const Generator7 g7_;
+  const Generator8 g8_;
+  const Generator9 g9_;
+  const Generator10 g10_;
+};  // class CartesianProductHolder10
+
+# endif  // GTEST_HAS_COMBINE
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  //  GTEST_HAS_PARAM_TEST
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
diff --git a/third_party/googletest/googletest/include/gtest/internal/gtest-param-util-generated.h.pump b/third_party/googletest/googletest/include/gtest/internal/gtest-param-util-generated.h.pump
new file mode 100644
index 0000000..5c7c47a
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/internal/gtest-param-util-generated.h.pump
@@ -0,0 +1,286 @@
+$$ -*- mode: c++; -*-
+$var n = 50  $$ Maximum length of Values arguments we want to support.
+$var maxtuple = 10  $$ Maximum number of Combine arguments we want to support.
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vladl@google.com (Vlad Losev)
+
+// Type and function utilities for implementing parameterized tests.
+// This file is generated by a SCRIPT.  DO NOT EDIT BY HAND!
+//
+// Currently Google Test supports at most $n arguments in Values,
+// and at most $maxtuple arguments in Combine. Please contact
+// googletestframework@googlegroups.com if you need more.
+// Please note that the number of arguments to Combine is limited
+// by the maximum arity of the implementation of tuple which is
+// currently set at $maxtuple.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*.  Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+#include "gtest/internal/gtest-param-util.h"
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+
+// Forward declarations of ValuesIn(), which is implemented in
+// include/gtest/gtest-param-test.h.
+template <typename ForwardIterator>
+internal::ParamGenerator<
+  typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end);
+
+template <typename T, size_t N>
+internal::ParamGenerator<T> ValuesIn(const T (&array)[N]);
+
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+    const Container& container);
+
+namespace internal {
+
+// Used in the Values() function to provide polymorphic capabilities.
+$range i 1..n
+$for i [[
+$range j 1..i
+
+template <$for j, [[typename T$j]]>
+class ValueArray$i {
+ public:
+  $if i==1 [[explicit ]]ValueArray$i($for j, [[T$j v$j]]) : $for j, [[v$(j)_(v$j)]] {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {$for j, [[static_cast<T>(v$(j)_)]]};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray$i& other);
+
+$for j [[
+
+  const T$j v$(j)_;
+]]
+
+};
+
+]]
+
+# if GTEST_HAS_COMBINE
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Generates values from the Cartesian product of values produced
+// by the argument generators.
+//
+$range i 2..maxtuple
+$for i [[
+$range j 1..i
+$range k 2..i
+
+template <$for j, [[typename T$j]]>
+class CartesianProductGenerator$i
+    : public ParamGeneratorInterface< ::testing::tuple<$for j, [[T$j]]> > {
+ public:
+  typedef ::testing::tuple<$for j, [[T$j]]> ParamType;
+
+  CartesianProductGenerator$i($for j, [[const ParamGenerator<T$j>& g$j]])
+      : $for j, [[g$(j)_(g$j)]] {}
+  virtual ~CartesianProductGenerator$i() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, $for j, [[g$(j)_, g$(j)_.begin()]]);
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, $for j, [[g$(j)_, g$(j)_.end()]]);
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base, $for j, [[
+
+      const ParamGenerator<T$j>& g$j,
+      const typename ParamGenerator<T$j>::iterator& current$(j)]])
+        : base_(base),
+$for j, [[
+
+          begin$(j)_(g$j.begin()), end$(j)_(g$j.end()), current$(j)_(current$j)
+]]    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current$(i)_;
+
+$for k [[
+      if (current$(i+2-k)_ == end$(i+2-k)_) {
+        current$(i+2-k)_ = begin$(i+2-k)_;
+        ++current$(i+2-k-1)_;
+      }
+
+]]
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         ($for j  && [[
+
+          current$(j)_ == typed_other->current$(j)_
+]]);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_), $for j, [[
+
+        begin$(j)_(other.begin$(j)_),
+        end$(j)_(other.end$(j)_),
+        current$(j)_(other.current$(j)_)
+]] {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType($for j, [[*current$(j)_]]);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+$for j  || [[
+
+          current$(j)_ == end$(j)_
+]];
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+$for j [[
+
+    const typename ParamGenerator<T$j>::iterator begin$(j)_;
+    const typename ParamGenerator<T$j>::iterator end$(j)_;
+    typename ParamGenerator<T$j>::iterator current$(j)_;
+]]
+
+    ParamType current_value_;
+  };  // class CartesianProductGenerator$i::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator$i& other);
+
+
+$for j [[
+  const ParamGenerator<T$j> g$(j)_;
+
+]]
+};  // class CartesianProductGenerator$i
+
+
+]]
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Helper classes providing Combine() with polymorphic features. They allow
+// casting CartesianProductGeneratorN<T> to ParamGenerator<U> if T is
+// convertible to U.
+//
+$range i 2..maxtuple
+$for i [[
+$range j 1..i
+
+template <$for j, [[class Generator$j]]>
+class CartesianProductHolder$i {
+ public:
+CartesianProductHolder$i($for j, [[const Generator$j& g$j]])
+      : $for j, [[g$(j)_(g$j)]] {}
+  template <$for j, [[typename T$j]]>
+  operator ParamGenerator< ::testing::tuple<$for j, [[T$j]]> >() const {
+    return ParamGenerator< ::testing::tuple<$for j, [[T$j]]> >(
+        new CartesianProductGenerator$i<$for j, [[T$j]]>(
+$for j,[[
+
+        static_cast<ParamGenerator<T$j> >(g$(j)_)
+]]));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder$i& other);
+
+
+$for j [[
+  const Generator$j g$(j)_;
+
+]]
+};  // class CartesianProductHolder$i
+
+]]
+
+# endif  // GTEST_HAS_COMBINE
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  //  GTEST_HAS_PARAM_TEST
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
diff --git a/third_party/googletest/googletest/include/gtest/internal/gtest-param-util.h b/third_party/googletest/googletest/include/gtest/internal/gtest-param-util.h
new file mode 100644
index 0000000..82cab9b
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/internal/gtest-param-util.h
@@ -0,0 +1,731 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vladl@google.com (Vlad Losev)
+
+// Type and function utilities for implementing parameterized tests.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
+
+#include <ctype.h>
+
+#include <iterator>
+#include <set>
+#include <utility>
+#include <vector>
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*.  Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-linked_ptr.h"
+#include "gtest/internal/gtest-port.h"
+#include "gtest/gtest-printers.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+
+// Input to a parameterized test name generator, describing a test parameter.
+// Consists of the parameter value and the integer parameter index.
+template <class ParamType>
+struct TestParamInfo {
+  TestParamInfo(const ParamType& a_param, size_t an_index) :
+    param(a_param),
+    index(an_index) {}
+  ParamType param;
+  size_t index;
+};
+
+// A builtin parameterized test name generator which returns the result of
+// testing::PrintToString.
+struct PrintToStringParamName {
+  template <class ParamType>
+  std::string operator()(const TestParamInfo<ParamType>& info) const {
+    return PrintToString(info.param);
+  }
+};
+
+namespace internal {
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Outputs a message explaining invalid registration of different
+// fixture class for the same test case. This may happen when
+// TEST_P macro is used to define two tests with the same name
+// but in different namespaces.
+GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name,
+                                          CodeLocation code_location);
+
+template <typename> class ParamGeneratorInterface;
+template <typename> class ParamGenerator;
+
+// Interface for iterating over elements provided by an implementation
+// of ParamGeneratorInterface<T>.
+template <typename T>
+class ParamIteratorInterface {
+ public:
+  virtual ~ParamIteratorInterface() {}
+  // A pointer to the base generator instance.
+  // Used only for the purposes of iterator comparison
+  // to make sure that two iterators belong to the same generator.
+  virtual const ParamGeneratorInterface<T>* BaseGenerator() const = 0;
+  // Advances iterator to point to the next element
+  // provided by the generator. The caller is responsible
+  // for not calling Advance() on an iterator equal to
+  // BaseGenerator()->End().
+  virtual void Advance() = 0;
+  // Clones the iterator object. Used for implementing copy semantics
+  // of ParamIterator<T>.
+  virtual ParamIteratorInterface* Clone() const = 0;
+  // Dereferences the current iterator and provides (read-only) access
+  // to the pointed value. It is the caller's responsibility not to call
+  // Current() on an iterator equal to BaseGenerator()->End().
+  // Used for implementing ParamGenerator<T>::operator*().
+  virtual const T* Current() const = 0;
+  // Determines whether the given iterator and other point to the same
+  // element in the sequence generated by the generator.
+  // Used for implementing ParamGenerator<T>::operator==().
+  virtual bool Equals(const ParamIteratorInterface& other) const = 0;
+};
+
+// Class iterating over elements provided by an implementation of
+// ParamGeneratorInterface<T>. It wraps ParamIteratorInterface<T>
+// and implements the const forward iterator concept.
+template <typename T>
+class ParamIterator {
+ public:
+  typedef T value_type;
+  typedef const T& reference;
+  typedef ptrdiff_t difference_type;
+
+  // ParamIterator assumes ownership of the impl_ pointer.
+  ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {}
+  ParamIterator& operator=(const ParamIterator& other) {
+    if (this != &other)
+      impl_.reset(other.impl_->Clone());
+    return *this;
+  }
+
+  const T& operator*() const { return *impl_->Current(); }
+  const T* operator->() const { return impl_->Current(); }
+  // Prefix version of operator++.
+  ParamIterator& operator++() {
+    impl_->Advance();
+    return *this;
+  }
+  // Postfix version of operator++.
+  ParamIterator operator++(int /*unused*/) {
+    ParamIteratorInterface<T>* clone = impl_->Clone();
+    impl_->Advance();
+    return ParamIterator(clone);
+  }
+  bool operator==(const ParamIterator& other) const {
+    return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_);
+  }
+  bool operator!=(const ParamIterator& other) const {
+    return !(*this == other);
+  }
+
+ private:
+  friend class ParamGenerator<T>;
+  explicit ParamIterator(ParamIteratorInterface<T>* impl) : impl_(impl) {}
+  scoped_ptr<ParamIteratorInterface<T> > impl_;
+};
+
+// ParamGeneratorInterface<T> is the binary interface to access generators
+// defined in other translation units.
+template <typename T>
+class ParamGeneratorInterface {
+ public:
+  typedef T ParamType;
+
+  virtual ~ParamGeneratorInterface() {}
+
+  // Generator interface definition
+  virtual ParamIteratorInterface<T>* Begin() const = 0;
+  virtual ParamIteratorInterface<T>* End() const = 0;
+};
+
+// Wraps ParamGeneratorInterface<T> and provides general generator syntax
+// compatible with the STL Container concept.
+// This class implements copy initialization semantics and the contained
+// ParamGeneratorInterface<T> instance is shared among all copies
+// of the original object. This is possible because that instance is immutable.
+template<typename T>
+class ParamGenerator {
+ public:
+  typedef ParamIterator<T> iterator;
+
+  explicit ParamGenerator(ParamGeneratorInterface<T>* impl) : impl_(impl) {}
+  ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {}
+
+  ParamGenerator& operator=(const ParamGenerator& other) {
+    impl_ = other.impl_;
+    return *this;
+  }
+
+  iterator begin() const { return iterator(impl_->Begin()); }
+  iterator end() const { return iterator(impl_->End()); }
+
+ private:
+  linked_ptr<const ParamGeneratorInterface<T> > impl_;
+};
+
+// Generates values from a range of two comparable values. Can be used to
+// generate sequences of user-defined types that implement operator+() and
+// operator<().
+// This class is used in the Range() function.
+template <typename T, typename IncrementT>
+class RangeGenerator : public ParamGeneratorInterface<T> {
+ public:
+  RangeGenerator(T begin, T end, IncrementT step)
+      : begin_(begin), end_(end),
+        step_(step), end_index_(CalculateEndIndex(begin, end, step)) {}
+  virtual ~RangeGenerator() {}
+
+  virtual ParamIteratorInterface<T>* Begin() const {
+    return new Iterator(this, begin_, 0, step_);
+  }
+  virtual ParamIteratorInterface<T>* End() const {
+    return new Iterator(this, end_, end_index_, step_);
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<T> {
+   public:
+    Iterator(const ParamGeneratorInterface<T>* base, T value, int index,
+             IncrementT step)
+        : base_(base), value_(value), index_(index), step_(step) {}
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
+      return base_;
+    }
+    virtual void Advance() {
+      value_ = static_cast<T>(value_ + step_);
+      index_++;
+    }
+    virtual ParamIteratorInterface<T>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const T* Current() const { return &value_; }
+    virtual bool Equals(const ParamIteratorInterface<T>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const int other_index =
+          CheckedDowncastToActualType<const Iterator>(&other)->index_;
+      return index_ == other_index;
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : ParamIteratorInterface<T>(),
+          base_(other.base_), value_(other.value_), index_(other.index_),
+          step_(other.step_) {}
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<T>* const base_;
+    T value_;
+    int index_;
+    const IncrementT step_;
+  };  // class RangeGenerator::Iterator
+
+  static int CalculateEndIndex(const T& begin,
+                               const T& end,
+                               const IncrementT& step) {
+    int end_index = 0;
+    for (T i = begin; i < end; i = static_cast<T>(i + step))
+      end_index++;
+    return end_index;
+  }
+
+  // No implementation - assignment is unsupported.
+  void operator=(const RangeGenerator& other);
+
+  const T begin_;
+  const T end_;
+  const IncrementT step_;
+  // The index for the end() iterator. All the elements in the generated
+  // sequence are indexed (0-based) to aid iterator comparison.
+  const int end_index_;
+};  // class RangeGenerator
+
+
+// Generates values from a pair of STL-style iterators. Used in the
+// ValuesIn() function. The elements are copied from the source range
+// since the source can be located on the stack, and the generator
+// is likely to persist beyond that stack frame.
+template <typename T>
+class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
+ public:
+  template <typename ForwardIterator>
+  ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end)
+      : container_(begin, end) {}
+  virtual ~ValuesInIteratorRangeGenerator() {}
+
+  virtual ParamIteratorInterface<T>* Begin() const {
+    return new Iterator(this, container_.begin());
+  }
+  virtual ParamIteratorInterface<T>* End() const {
+    return new Iterator(this, container_.end());
+  }
+
+ private:
+  typedef typename ::std::vector<T> ContainerType;
+
+  class Iterator : public ParamIteratorInterface<T> {
+   public:
+    Iterator(const ParamGeneratorInterface<T>* base,
+             typename ContainerType::const_iterator iterator)
+        : base_(base), iterator_(iterator) {}
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
+      return base_;
+    }
+    virtual void Advance() {
+      ++iterator_;
+      value_.reset();
+    }
+    virtual ParamIteratorInterface<T>* Clone() const {
+      return new Iterator(*this);
+    }
+    // We need to use cached value referenced by iterator_ because *iterator_
+    // can return a temporary object (and of type other then T), so just
+    // having "return &*iterator_;" doesn't work.
+    // value_ is updated here and not in Advance() because Advance()
+    // can advance iterator_ beyond the end of the range, and we cannot
+    // detect that fact. The client code, on the other hand, is
+    // responsible for not calling Current() on an out-of-range iterator.
+    virtual const T* Current() const {
+      if (value_.get() == NULL)
+        value_.reset(new T(*iterator_));
+      return value_.get();
+    }
+    virtual bool Equals(const ParamIteratorInterface<T>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      return iterator_ ==
+          CheckedDowncastToActualType<const Iterator>(&other)->iterator_;
+    }
+
+   private:
+    Iterator(const Iterator& other)
+          // The explicit constructor call suppresses a false warning
+          // emitted by gcc when supplied with the -Wextra option.
+        : ParamIteratorInterface<T>(),
+          base_(other.base_),
+          iterator_(other.iterator_) {}
+
+    const ParamGeneratorInterface<T>* const base_;
+    typename ContainerType::const_iterator iterator_;
+    // A cached value of *iterator_. We keep it here to allow access by
+    // pointer in the wrapping iterator's operator->().
+    // value_ needs to be mutable to be accessed in Current().
+    // Use of scoped_ptr helps manage cached value's lifetime,
+    // which is bound by the lifespan of the iterator itself.
+    mutable scoped_ptr<const T> value_;
+  };  // class ValuesInIteratorRangeGenerator::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const ValuesInIteratorRangeGenerator& other);
+
+  const ContainerType container_;
+};  // class ValuesInIteratorRangeGenerator
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Default parameterized test name generator, returns a string containing the
+// integer test parameter index.
+template <class ParamType>
+std::string DefaultParamName(const TestParamInfo<ParamType>& info) {
+  Message name_stream;
+  name_stream << info.index;
+  return name_stream.GetString();
+}
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Parameterized test name overload helpers, which help the
+// INSTANTIATE_TEST_CASE_P macro choose between the default parameterized
+// test name generator and user param name generator.
+template <class ParamType, class ParamNameGenFunctor>
+ParamNameGenFunctor GetParamNameGen(ParamNameGenFunctor func) {
+  return func;
+}
+
+template <class ParamType>
+struct ParamNameGenFunc {
+  typedef std::string Type(const TestParamInfo<ParamType>&);
+};
+
+template <class ParamType>
+typename ParamNameGenFunc<ParamType>::Type *GetParamNameGen() {
+  return DefaultParamName;
+}
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Stores a parameter value and later creates tests parameterized with that
+// value.
+template <class TestClass>
+class ParameterizedTestFactory : public TestFactoryBase {
+ public:
+  typedef typename TestClass::ParamType ParamType;
+  explicit ParameterizedTestFactory(ParamType parameter) :
+      parameter_(parameter) {}
+  virtual Test* CreateTest() {
+    TestClass::SetParam(&parameter_);
+    return new TestClass();
+  }
+
+ private:
+  const ParamType parameter_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory);
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// TestMetaFactoryBase is a base class for meta-factories that create
+// test factories for passing into MakeAndRegisterTestInfo function.
+template <class ParamType>
+class TestMetaFactoryBase {
+ public:
+  virtual ~TestMetaFactoryBase() {}
+
+  virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0;
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// TestMetaFactory creates test factories for passing into
+// MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives
+// ownership of test factory pointer, same factory object cannot be passed
+// into that method twice. But ParameterizedTestCaseInfo is going to call
+// it for each Test/Parameter value combination. Thus it needs meta factory
+// creator class.
+template <class TestCase>
+class TestMetaFactory
+    : public TestMetaFactoryBase<typename TestCase::ParamType> {
+ public:
+  typedef typename TestCase::ParamType ParamType;
+
+  TestMetaFactory() {}
+
+  virtual TestFactoryBase* CreateTestFactory(ParamType parameter) {
+    return new ParameterizedTestFactory<TestCase>(parameter);
+  }
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory);
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestCaseInfoBase is a generic interface
+// to ParameterizedTestCaseInfo classes. ParameterizedTestCaseInfoBase
+// accumulates test information provided by TEST_P macro invocations
+// and generators provided by INSTANTIATE_TEST_CASE_P macro invocations
+// and uses that information to register all resulting test instances
+// in RegisterTests method. The ParameterizeTestCaseRegistry class holds
+// a collection of pointers to the ParameterizedTestCaseInfo objects
+// and calls RegisterTests() on each of them when asked.
+class ParameterizedTestCaseInfoBase {
+ public:
+  virtual ~ParameterizedTestCaseInfoBase() {}
+
+  // Base part of test case name for display purposes.
+  virtual const string& GetTestCaseName() const = 0;
+  // Test case id to verify identity.
+  virtual TypeId GetTestCaseTypeId() const = 0;
+  // UnitTest class invokes this method to register tests in this
+  // test case right before running them in RUN_ALL_TESTS macro.
+  // This method should not be called more then once on any single
+  // instance of a ParameterizedTestCaseInfoBase derived class.
+  virtual void RegisterTests() = 0;
+
+ protected:
+  ParameterizedTestCaseInfoBase() {}
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfoBase);
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestCaseInfo accumulates tests obtained from TEST_P
+// macro invocations for a particular test case and generators
+// obtained from INSTANTIATE_TEST_CASE_P macro invocations for that
+// test case. It registers tests with all values generated by all
+// generators when asked.
+template <class TestCase>
+class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
+ public:
+  // ParamType and GeneratorCreationFunc are private types but are required
+  // for declarations of public methods AddTestPattern() and
+  // AddTestCaseInstantiation().
+  typedef typename TestCase::ParamType ParamType;
+  // A function that returns an instance of appropriate generator type.
+  typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
+  typedef typename ParamNameGenFunc<ParamType>::Type ParamNameGeneratorFunc;
+
+  explicit ParameterizedTestCaseInfo(
+      const char* name, CodeLocation code_location)
+      : test_case_name_(name), code_location_(code_location) {}
+
+  // Test case base name for display purposes.
+  virtual const string& GetTestCaseName() const { return test_case_name_; }
+  // Test case id to verify identity.
+  virtual TypeId GetTestCaseTypeId() const { return GetTypeId<TestCase>(); }
+  // TEST_P macro uses AddTestPattern() to record information
+  // about a single test in a LocalTestInfo structure.
+  // test_case_name is the base name of the test case (without invocation
+  // prefix). test_base_name is the name of an individual test without
+  // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
+  // test case base name and DoBar is test base name.
+  void AddTestPattern(const char* test_case_name,
+                      const char* test_base_name,
+                      TestMetaFactoryBase<ParamType>* meta_factory) {
+    tests_.push_back(linked_ptr<TestInfo>(new TestInfo(test_case_name,
+                                                       test_base_name,
+                                                       meta_factory)));
+  }
+  // INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information
+  // about a generator.
+  int AddTestCaseInstantiation(const string& instantiation_name,
+                               GeneratorCreationFunc* func,
+                               ParamNameGeneratorFunc* name_func,
+                               const char* file,
+                               int line) {
+    instantiations_.push_back(
+        InstantiationInfo(instantiation_name, func, name_func, file, line));
+    return 0;  // Return value used only to run this method in namespace scope.
+  }
+  // UnitTest class invokes this method to register tests in this test case
+  // test cases right before running tests in RUN_ALL_TESTS macro.
+  // This method should not be called more then once on any single
+  // instance of a ParameterizedTestCaseInfoBase derived class.
+  // UnitTest has a guard to prevent from calling this method more then once.
+  virtual void RegisterTests() {
+    for (typename TestInfoContainer::iterator test_it = tests_.begin();
+         test_it != tests_.end(); ++test_it) {
+      linked_ptr<TestInfo> test_info = *test_it;
+      for (typename InstantiationContainer::iterator gen_it =
+               instantiations_.begin(); gen_it != instantiations_.end();
+               ++gen_it) {
+        const string& instantiation_name = gen_it->name;
+        ParamGenerator<ParamType> generator((*gen_it->generator)());
+        ParamNameGeneratorFunc* name_func = gen_it->name_func;
+        const char* file = gen_it->file;
+        int line = gen_it->line;
+
+        string test_case_name;
+        if ( !instantiation_name.empty() )
+          test_case_name = instantiation_name + "/";
+        test_case_name += test_info->test_case_base_name;
+
+        size_t i = 0;
+        std::set<std::string> test_param_names;
+        for (typename ParamGenerator<ParamType>::iterator param_it =
+                 generator.begin();
+             param_it != generator.end(); ++param_it, ++i) {
+          Message test_name_stream;
+
+          std::string param_name = name_func(
+              TestParamInfo<ParamType>(*param_it, i));
+
+          GTEST_CHECK_(IsValidParamName(param_name))
+              << "Parameterized test name '" << param_name
+              << "' is invalid, in " << file
+              << " line " << line << std::endl;
+
+          GTEST_CHECK_(test_param_names.count(param_name) == 0)
+              << "Duplicate parameterized test name '" << param_name
+              << "', in " << file << " line " << line << std::endl;
+
+          test_param_names.insert(param_name);
+
+          test_name_stream << test_info->test_base_name << "/" << param_name;
+          MakeAndRegisterTestInfo(
+              test_case_name.c_str(),
+              test_name_stream.GetString().c_str(),
+              NULL,  // No type parameter.
+              PrintToString(*param_it).c_str(),
+              code_location_,
+              GetTestCaseTypeId(),
+              TestCase::SetUpTestCase,
+              TestCase::TearDownTestCase,
+              test_info->test_meta_factory->CreateTestFactory(*param_it));
+        }  // for param_it
+      }  // for gen_it
+    }  // for test_it
+  }  // RegisterTests
+
+ private:
+  // LocalTestInfo structure keeps information about a single test registered
+  // with TEST_P macro.
+  struct TestInfo {
+    TestInfo(const char* a_test_case_base_name,
+             const char* a_test_base_name,
+             TestMetaFactoryBase<ParamType>* a_test_meta_factory) :
+        test_case_base_name(a_test_case_base_name),
+        test_base_name(a_test_base_name),
+        test_meta_factory(a_test_meta_factory) {}
+
+    const string test_case_base_name;
+    const string test_base_name;
+    const scoped_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory;
+  };
+  typedef ::std::vector<linked_ptr<TestInfo> > TestInfoContainer;
+  // Records data received from INSTANTIATE_TEST_CASE_P macros:
+  //  <Instantiation name, Sequence generator creation function,
+  //     Name generator function, Source file, Source line>
+  struct InstantiationInfo {
+      InstantiationInfo(const std::string &name_in,
+                        GeneratorCreationFunc* generator_in,
+                        ParamNameGeneratorFunc* name_func_in,
+                        const char* file_in,
+                        int line_in)
+          : name(name_in),
+            generator(generator_in),
+            name_func(name_func_in),
+            file(file_in),
+            line(line_in) {}
+
+      std::string name;
+      GeneratorCreationFunc* generator;
+      ParamNameGeneratorFunc* name_func;
+      const char* file;
+      int line;
+  };
+  typedef ::std::vector<InstantiationInfo> InstantiationContainer;
+
+  static bool IsValidParamName(const std::string& name) {
+    // Check for empty string
+    if (name.empty())
+      return false;
+
+    // Check for invalid characters
+    for (std::string::size_type index = 0; index < name.size(); ++index) {
+      if (!isalnum(name[index]) && name[index] != '_')
+        return false;
+    }
+
+    return true;
+  }
+
+  const string test_case_name_;
+  CodeLocation code_location_;
+  TestInfoContainer tests_;
+  InstantiationContainer instantiations_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfo);
+};  // class ParameterizedTestCaseInfo
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestCaseRegistry contains a map of ParameterizedTestCaseInfoBase
+// classes accessed by test case names. TEST_P and INSTANTIATE_TEST_CASE_P
+// macros use it to locate their corresponding ParameterizedTestCaseInfo
+// descriptors.
+class ParameterizedTestCaseRegistry {
+ public:
+  ParameterizedTestCaseRegistry() {}
+  ~ParameterizedTestCaseRegistry() {
+    for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
+         it != test_case_infos_.end(); ++it) {
+      delete *it;
+    }
+  }
+
+  // Looks up or creates and returns a structure containing information about
+  // tests and instantiations of a particular test case.
+  template <class TestCase>
+  ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
+      const char* test_case_name,
+      CodeLocation code_location) {
+    ParameterizedTestCaseInfo<TestCase>* typed_test_info = NULL;
+    for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
+         it != test_case_infos_.end(); ++it) {
+      if ((*it)->GetTestCaseName() == test_case_name) {
+        if ((*it)->GetTestCaseTypeId() != GetTypeId<TestCase>()) {
+          // Complain about incorrect usage of Google Test facilities
+          // and terminate the program since we cannot guaranty correct
+          // test case setup and tear-down in this case.
+          ReportInvalidTestCaseType(test_case_name, code_location);
+          posix::Abort();
+        } else {
+          // At this point we are sure that the object we found is of the same
+          // type we are looking for, so we downcast it to that type
+          // without further checks.
+          typed_test_info = CheckedDowncastToActualType<
+              ParameterizedTestCaseInfo<TestCase> >(*it);
+        }
+        break;
+      }
+    }
+    if (typed_test_info == NULL) {
+      typed_test_info = new ParameterizedTestCaseInfo<TestCase>(
+          test_case_name, code_location);
+      test_case_infos_.push_back(typed_test_info);
+    }
+    return typed_test_info;
+  }
+  void RegisterTests() {
+    for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
+         it != test_case_infos_.end(); ++it) {
+      (*it)->RegisterTests();
+    }
+  }
+
+ private:
+  typedef ::std::vector<ParameterizedTestCaseInfoBase*> TestCaseInfoContainer;
+
+  TestCaseInfoContainer test_case_infos_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseRegistry);
+};
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  //  GTEST_HAS_PARAM_TEST
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
diff --git a/third_party/googletest/googletest/include/gtest/internal/gtest-port-arch.h b/third_party/googletest/googletest/include/gtest/internal/gtest-port-arch.h
new file mode 100644
index 0000000..74ab949
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/internal/gtest-port-arch.h
@@ -0,0 +1,93 @@
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines the GTEST_OS_* macro.
+// It is separate from gtest-port.h so that custom/gtest-port.h can include it.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
+
+// Determines the platform on which Google Test is compiled.
+#ifdef __CYGWIN__
+# define GTEST_OS_CYGWIN 1
+#elif defined __SYMBIAN32__
+# define GTEST_OS_SYMBIAN 1
+#elif defined _WIN32
+# define GTEST_OS_WINDOWS 1
+# ifdef _WIN32_WCE
+#  define GTEST_OS_WINDOWS_MOBILE 1
+# elif defined(__MINGW__) || defined(__MINGW32__)
+#  define GTEST_OS_WINDOWS_MINGW 1
+# elif defined(WINAPI_FAMILY)
+#  include <winapifamily.h>
+#  if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+#   define GTEST_OS_WINDOWS_DESKTOP 1
+#  elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
+#   define GTEST_OS_WINDOWS_PHONE 1
+#  elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
+#   define GTEST_OS_WINDOWS_RT 1
+#  else
+    // WINAPI_FAMILY defined but no known partition matched.
+    // Default to desktop.
+#   define GTEST_OS_WINDOWS_DESKTOP 1
+#  endif
+# else
+#  define GTEST_OS_WINDOWS_DESKTOP 1
+# endif  // _WIN32_WCE
+#elif defined __APPLE__
+# define GTEST_OS_MAC 1
+# if TARGET_OS_IPHONE
+#  define GTEST_OS_IOS 1
+# endif
+#elif defined __FreeBSD__
+# define GTEST_OS_FREEBSD 1
+#elif defined __linux__
+# define GTEST_OS_LINUX 1
+# if defined __ANDROID__
+#  define GTEST_OS_LINUX_ANDROID 1
+# endif
+#elif defined __MVS__
+# define GTEST_OS_ZOS 1
+#elif defined(__sun) && defined(__SVR4)
+# define GTEST_OS_SOLARIS 1
+#elif defined(_AIX)
+# define GTEST_OS_AIX 1
+#elif defined(__hpux)
+# define GTEST_OS_HPUX 1
+#elif defined __native_client__
+# define GTEST_OS_NACL 1
+#elif defined __OpenBSD__
+# define GTEST_OS_OPENBSD 1
+#elif defined __QNX__
+# define GTEST_OS_QNX 1
+#endif  // __CYGWIN__
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
diff --git a/third_party/googletest/googletest/include/gtest/internal/gtest-port.h b/third_party/googletest/googletest/include/gtest/internal/gtest-port.h
new file mode 100644
index 0000000..141d457
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/internal/gtest-port.h
@@ -0,0 +1,2559 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: wan@google.com (Zhanyong Wan)
+//
+// Low-level types and utilities for porting Google Test to various
+// platforms.  All macros ending with _ and symbols defined in an
+// internal namespace are subject to change without notice.  Code
+// outside Google Test MUST NOT USE THEM DIRECTLY.  Macros that don't
+// end with _ are part of Google Test's public API and can be used by
+// code outside Google Test.
+//
+// This file is fundamental to Google Test.  All other Google Test source
+// files are expected to #include this.  Therefore, it cannot #include
+// any other Google Test header.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
+
+// Environment-describing macros
+// -----------------------------
+//
+// Google Test can be used in many different environments.  Macros in
+// this section tell Google Test what kind of environment it is being
+// used in, such that Google Test can provide environment-specific
+// features and implementations.
+//
+// Google Test tries to automatically detect the properties of its
+// environment, so users usually don't need to worry about these
+// macros.  However, the automatic detection is not perfect.
+// Sometimes it's necessary for a user to define some of the following
+// macros in the build script to override Google Test's decisions.
+//
+// If the user doesn't define a macro in the list, Google Test will
+// provide a default definition.  After this header is #included, all
+// macros in this list will be defined to either 1 or 0.
+//
+// Notes to maintainers:
+//   - Each macro here is a user-tweakable knob; do not grow the list
+//     lightly.
+//   - Use #if to key off these macros.  Don't use #ifdef or "#if
+//     defined(...)", which will not work as these macros are ALWAYS
+//     defined.
+//
+//   GTEST_HAS_CLONE          - Define it to 1/0 to indicate that clone(2)
+//                              is/isn't available.
+//   GTEST_HAS_EXCEPTIONS     - Define it to 1/0 to indicate that exceptions
+//                              are enabled.
+//   GTEST_HAS_GLOBAL_STRING  - Define it to 1/0 to indicate that ::string
+//                              is/isn't available (some systems define
+//                              ::string, which is different to std::string).
+//   GTEST_HAS_GLOBAL_WSTRING - Define it to 1/0 to indicate that ::string
+//                              is/isn't available (some systems define
+//                              ::wstring, which is different to std::wstring).
+//   GTEST_HAS_POSIX_RE       - Define it to 1/0 to indicate that POSIX regular
+//                              expressions are/aren't available.
+//   GTEST_HAS_PTHREAD        - Define it to 1/0 to indicate that <pthread.h>
+//                              is/isn't available.
+//   GTEST_HAS_RTTI           - Define it to 1/0 to indicate that RTTI is/isn't
+//                              enabled.
+//   GTEST_HAS_STD_WSTRING    - Define it to 1/0 to indicate that
+//                              std::wstring does/doesn't work (Google Test can
+//                              be used where std::wstring is unavailable).
+//   GTEST_HAS_TR1_TUPLE      - Define it to 1/0 to indicate tr1::tuple
+//                              is/isn't available.
+//   GTEST_HAS_SEH            - Define it to 1/0 to indicate whether the
+//                              compiler supports Microsoft's "Structured
+//                              Exception Handling".
+//   GTEST_HAS_STREAM_REDIRECTION
+//                            - Define it to 1/0 to indicate whether the
+//                              platform supports I/O stream redirection using
+//                              dup() and dup2().
+//   GTEST_USE_OWN_TR1_TUPLE  - Define it to 1/0 to indicate whether Google
+//                              Test's own tr1 tuple implementation should be
+//                              used.  Unused when the user sets
+//                              GTEST_HAS_TR1_TUPLE to 0.
+//   GTEST_LANG_CXX11         - Define it to 1/0 to indicate that Google Test
+//                              is building in C++11/C++98 mode.
+//   GTEST_LINKED_AS_SHARED_LIBRARY
+//                            - Define to 1 when compiling tests that use
+//                              Google Test as a shared library (known as
+//                              DLL on Windows).
+//   GTEST_CREATE_SHARED_LIBRARY
+//                            - Define to 1 when compiling Google Test itself
+//                              as a shared library.
+
+// Platform-indicating macros
+// --------------------------
+//
+// Macros indicating the platform on which Google Test is being used
+// (a macro is defined to 1 if compiled on the given platform;
+// otherwise UNDEFINED -- it's never defined to 0.).  Google Test
+// defines these macros automatically.  Code outside Google Test MUST
+// NOT define them.
+//
+//   GTEST_OS_AIX      - IBM AIX
+//   GTEST_OS_CYGWIN   - Cygwin
+//   GTEST_OS_FREEBSD  - FreeBSD
+//   GTEST_OS_HPUX     - HP-UX
+//   GTEST_OS_LINUX    - Linux
+//     GTEST_OS_LINUX_ANDROID - Google Android
+//   GTEST_OS_MAC      - Mac OS X
+//     GTEST_OS_IOS    - iOS
+//   GTEST_OS_NACL     - Google Native Client (NaCl)
+//   GTEST_OS_OPENBSD  - OpenBSD
+//   GTEST_OS_QNX      - QNX
+//   GTEST_OS_SOLARIS  - Sun Solaris
+//   GTEST_OS_SYMBIAN  - Symbian
+//   GTEST_OS_WINDOWS  - Windows (Desktop, MinGW, or Mobile)
+//     GTEST_OS_WINDOWS_DESKTOP  - Windows Desktop
+//     GTEST_OS_WINDOWS_MINGW    - MinGW
+//     GTEST_OS_WINDOWS_MOBILE   - Windows Mobile
+//     GTEST_OS_WINDOWS_PHONE    - Windows Phone
+//     GTEST_OS_WINDOWS_RT       - Windows Store App/WinRT
+//   GTEST_OS_ZOS      - z/OS
+//
+// Among the platforms, Cygwin, Linux, Max OS X, and Windows have the
+// most stable support.  Since core members of the Google Test project
+// don't have access to other platforms, support for them may be less
+// stable.  If you notice any problems on your platform, please notify
+// googletestframework@googlegroups.com (patches for fixing them are
+// even more welcome!).
+//
+// It is possible that none of the GTEST_OS_* macros are defined.
+
+// Feature-indicating macros
+// -------------------------
+//
+// Macros indicating which Google Test features are available (a macro
+// is defined to 1 if the corresponding feature is supported;
+// otherwise UNDEFINED -- it's never defined to 0.).  Google Test
+// defines these macros automatically.  Code outside Google Test MUST
+// NOT define them.
+//
+// These macros are public so that portable tests can be written.
+// Such tests typically surround code using a feature with an #if
+// which controls that code.  For example:
+//
+// #if GTEST_HAS_DEATH_TEST
+//   EXPECT_DEATH(DoSomethingDeadly());
+// #endif
+//
+//   GTEST_HAS_COMBINE      - the Combine() function (for value-parameterized
+//                            tests)
+//   GTEST_HAS_DEATH_TEST   - death tests
+//   GTEST_HAS_PARAM_TEST   - value-parameterized tests
+//   GTEST_HAS_TYPED_TEST   - typed tests
+//   GTEST_HAS_TYPED_TEST_P - type-parameterized tests
+//   GTEST_IS_THREADSAFE    - Google Test is thread-safe.
+//   GTEST_USES_POSIX_RE    - enhanced POSIX regex is used. Do not confuse with
+//                            GTEST_HAS_POSIX_RE (see above) which users can
+//                            define themselves.
+//   GTEST_USES_SIMPLE_RE   - our own simple regex is used;
+//                            the above two are mutually exclusive.
+//   GTEST_CAN_COMPARE_NULL - accepts untyped NULL in EXPECT_EQ().
+
+// Misc public macros
+// ------------------
+//
+//   GTEST_FLAG(flag_name)  - references the variable corresponding to
+//                            the given Google Test flag.
+
+// Internal utilities
+// ------------------
+//
+// The following macros and utilities are for Google Test's INTERNAL
+// use only.  Code outside Google Test MUST NOT USE THEM DIRECTLY.
+//
+// Macros for basic C++ coding:
+//   GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning.
+//   GTEST_ATTRIBUTE_UNUSED_  - declares that a class' instances or a
+//                              variable don't have to be used.
+//   GTEST_DISALLOW_ASSIGN_   - disables operator=.
+//   GTEST_DISALLOW_COPY_AND_ASSIGN_ - disables copy ctor and operator=.
+//   GTEST_MUST_USE_RESULT_   - declares that a function's result must be used.
+//   GTEST_INTENTIONAL_CONST_COND_PUSH_ - start code section where MSVC C4127 is
+//                                        suppressed (constant conditional).
+//   GTEST_INTENTIONAL_CONST_COND_POP_  - finish code section where MSVC C4127
+//                                        is suppressed.
+//
+// C++11 feature wrappers:
+//
+//   testing::internal::move  - portability wrapper for std::move.
+//
+// Synchronization:
+//   Mutex, MutexLock, ThreadLocal, GetThreadCount()
+//                            - synchronization primitives.
+//
+// Template meta programming:
+//   is_pointer     - as in TR1; needed on Symbian and IBM XL C/C++ only.
+//   IteratorTraits - partial implementation of std::iterator_traits, which
+//                    is not available in libCstd when compiled with Sun C++.
+//
+// Smart pointers:
+//   scoped_ptr     - as in TR2.
+//
+// Regular expressions:
+//   RE             - a simple regular expression class using the POSIX
+//                    Extended Regular Expression syntax on UNIX-like
+//                    platforms, or a reduced regular exception syntax on
+//                    other platforms, including Windows.
+//
+// Logging:
+//   GTEST_LOG_()   - logs messages at the specified severity level.
+//   LogToStderr()  - directs all log messages to stderr.
+//   FlushInfoLog() - flushes informational log messages.
+//
+// Stdout and stderr capturing:
+//   CaptureStdout()     - starts capturing stdout.
+//   GetCapturedStdout() - stops capturing stdout and returns the captured
+//                         string.
+//   CaptureStderr()     - starts capturing stderr.
+//   GetCapturedStderr() - stops capturing stderr and returns the captured
+//                         string.
+//
+// Integer types:
+//   TypeWithSize   - maps an integer to a int type.
+//   Int32, UInt32, Int64, UInt64, TimeInMillis
+//                  - integers of known sizes.
+//   BiggestInt     - the biggest signed integer type.
+//
+// Command-line utilities:
+//   GTEST_DECLARE_*()  - declares a flag.
+//   GTEST_DEFINE_*()   - defines a flag.
+//   GetInjectableArgvs() - returns the command line as a vector of strings.
+//
+// Environment variable utilities:
+//   GetEnv()             - gets the value of an environment variable.
+//   BoolFromGTestEnv()   - parses a bool environment variable.
+//   Int32FromGTestEnv()  - parses an Int32 environment variable.
+//   StringFromGTestEnv() - parses a string environment variable.
+
+#include <ctype.h>   // for isspace, etc
+#include <stddef.h>  // for ptrdiff_t
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#ifndef _WIN32_WCE
+# include <sys/types.h>
+# include <sys/stat.h>
+#endif  // !_WIN32_WCE
+
+#if defined __APPLE__
+# include <AvailabilityMacros.h>
+# include <TargetConditionals.h>
+#endif
+
+#include <algorithm>  // NOLINT
+#include <iostream>  // NOLINT
+#include <sstream>  // NOLINT
+#include <string>  // NOLINT
+#include <utility>
+#include <vector>  // NOLINT
+
+#include "gtest/internal/gtest-port-arch.h"
+#include "gtest/internal/custom/gtest-port.h"
+
+#if !defined(GTEST_DEV_EMAIL_)
+# define GTEST_DEV_EMAIL_ "googletestframework@@googlegroups.com"
+# define GTEST_FLAG_PREFIX_ "gtest_"
+# define GTEST_FLAG_PREFIX_DASH_ "gtest-"
+# define GTEST_FLAG_PREFIX_UPPER_ "GTEST_"
+# define GTEST_NAME_ "Google Test"
+# define GTEST_PROJECT_URL_ "http://code.google.com/p/googletest/"
+#endif  // !defined(GTEST_DEV_EMAIL_)
+
+#if !defined(GTEST_INIT_GOOGLE_TEST_NAME_)
+# define GTEST_INIT_GOOGLE_TEST_NAME_ "testing::InitGoogleTest"
+#endif  // !defined(GTEST_INIT_GOOGLE_TEST_NAME_)
+
+// Determines the version of gcc that is used to compile this.
+#ifdef __GNUC__
+// 40302 means version 4.3.2.
+# define GTEST_GCC_VER_ \
+    (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__)
+#endif  // __GNUC__
+
+// Macros for disabling Microsoft Visual C++ warnings.
+//
+//   GTEST_DISABLE_MSC_WARNINGS_PUSH_(4800 4385)
+//   /* code that triggers warnings C4800 and C4385 */
+//   GTEST_DISABLE_MSC_WARNINGS_POP_()
+#if _MSC_VER >= 1500
+# define GTEST_DISABLE_MSC_WARNINGS_PUSH_(warnings) \
+    __pragma(warning(push))                        \
+    __pragma(warning(disable: warnings))
+# define GTEST_DISABLE_MSC_WARNINGS_POP_()          \
+    __pragma(warning(pop))
+#else
+// Older versions of MSVC don't have __pragma.
+# define GTEST_DISABLE_MSC_WARNINGS_PUSH_(warnings)
+# define GTEST_DISABLE_MSC_WARNINGS_POP_()
+#endif
+
+#ifndef GTEST_LANG_CXX11
+// gcc and clang define __GXX_EXPERIMENTAL_CXX0X__ when
+// -std={c,gnu}++{0x,11} is passed.  The C++11 standard specifies a
+// value for __cplusplus, and recent versions of clang, gcc, and
+// probably other compilers set that too in C++11 mode.
+# if __GXX_EXPERIMENTAL_CXX0X__ || __cplusplus >= 201103L
+// Compiling in at least C++11 mode.
+#  define GTEST_LANG_CXX11 1
+# else
+#  define GTEST_LANG_CXX11 0
+# endif
+#endif
+
+// Distinct from C++11 language support, some environments don't provide
+// proper C++11 library support. Notably, it's possible to build in
+// C++11 mode when targeting Mac OS X 10.6, which has an old libstdc++
+// with no C++11 support.
+//
+// libstdc++ has sufficient C++11 support as of GCC 4.6.0, __GLIBCXX__
+// 20110325, but maintenance releases in the 4.4 and 4.5 series followed
+// this date, so check for those versions by their date stamps.
+// https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html#abi.versioning
+#if GTEST_LANG_CXX11 && \
+    (!defined(__GLIBCXX__) || ( \
+        __GLIBCXX__ >= 20110325ul &&  /* GCC >= 4.6.0 */ \
+        /* Blacklist of patch releases of older branches: */ \
+        __GLIBCXX__ != 20110416ul &&  /* GCC 4.4.6 */ \
+        __GLIBCXX__ != 20120313ul &&  /* GCC 4.4.7 */ \
+        __GLIBCXX__ != 20110428ul &&  /* GCC 4.5.3 */ \
+        __GLIBCXX__ != 20120702ul))   /* GCC 4.5.4 */
+# define GTEST_STDLIB_CXX11 1
+#endif
+
+// Only use C++11 library features if the library provides them.
+#if GTEST_STDLIB_CXX11
+# define GTEST_HAS_STD_BEGIN_AND_END_ 1
+# define GTEST_HAS_STD_FORWARD_LIST_ 1
+# define GTEST_HAS_STD_FUNCTION_ 1
+# define GTEST_HAS_STD_INITIALIZER_LIST_ 1
+# define GTEST_HAS_STD_MOVE_ 1
+# define GTEST_HAS_STD_UNIQUE_PTR_ 1
+# define GTEST_HAS_STD_SHARED_PTR_ 1
+#endif
+
+// C++11 specifies that <tuple> provides std::tuple.
+// Some platforms still might not have it, however.
+#if GTEST_LANG_CXX11
+# define GTEST_HAS_STD_TUPLE_ 1
+# if defined(__clang__)
+// Inspired by http://clang.llvm.org/docs/LanguageExtensions.html#__has_include
+#  if defined(__has_include) && !__has_include(<tuple>)
+#   undef GTEST_HAS_STD_TUPLE_
+#  endif
+# elif defined(_MSC_VER)
+// Inspired by boost/config/stdlib/dinkumware.hpp
+#  if defined(_CPPLIB_VER) && _CPPLIB_VER < 520
+#   undef GTEST_HAS_STD_TUPLE_
+#  endif
+# elif defined(__GLIBCXX__)
+// Inspired by boost/config/stdlib/libstdcpp3.hpp,
+// http://gcc.gnu.org/gcc-4.2/changes.html and
+// http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt01ch01.html#manual.intro.status.standard.200x
+#  if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2)
+#   undef GTEST_HAS_STD_TUPLE_
+#  endif
+# endif
+#endif
+
+// Brings in definitions for functions used in the testing::internal::posix
+// namespace (read, write, close, chdir, isatty, stat). We do not currently
+// use them on Windows Mobile.
+#if GTEST_OS_WINDOWS
+# if !GTEST_OS_WINDOWS_MOBILE
+#  include <direct.h>
+#  include <io.h>
+# endif
+// In order to avoid having to include <windows.h>, use forward declaration
+// assuming CRITICAL_SECTION is a typedef of _RTL_CRITICAL_SECTION.
+// This assumption is verified by
+// WindowsTypesTest.CRITICAL_SECTIONIs_RTL_CRITICAL_SECTION.
+struct _RTL_CRITICAL_SECTION;
+#else
+// This assumes that non-Windows OSes provide unistd.h. For OSes where this
+// is not the case, we need to include headers that provide the functions
+// mentioned above.
+# include <unistd.h>
+# include <strings.h>
+#endif  // GTEST_OS_WINDOWS
+
+#if GTEST_OS_LINUX_ANDROID
+// Used to define __ANDROID_API__ matching the target NDK API level.
+#  include <android/api-level.h>  // NOLINT
+#endif
+
+// Defines this to true iff Google Test can use POSIX regular expressions.
+#ifndef GTEST_HAS_POSIX_RE
+# if GTEST_OS_LINUX_ANDROID
+// On Android, <regex.h> is only available starting with Gingerbread.
+#  define GTEST_HAS_POSIX_RE (__ANDROID_API__ >= 9)
+# else
+#  define GTEST_HAS_POSIX_RE (!GTEST_OS_WINDOWS)
+# endif
+#endif
+
+#if GTEST_USES_PCRE
+// The appropriate headers have already been included.
+
+#elif GTEST_HAS_POSIX_RE
+
+// On some platforms, <regex.h> needs someone to define size_t, and
+// won't compile otherwise.  We can #include it here as we already
+// included <stdlib.h>, which is guaranteed to define size_t through
+// <stddef.h>.
+# include <regex.h>  // NOLINT
+
+# define GTEST_USES_POSIX_RE 1
+
+#elif GTEST_OS_WINDOWS
+
+// <regex.h> is not available on Windows.  Use our own simple regex
+// implementation instead.
+# define GTEST_USES_SIMPLE_RE 1
+
+#else
+
+// <regex.h> may not be available on this platform.  Use our own
+// simple regex implementation instead.
+# define GTEST_USES_SIMPLE_RE 1
+
+#endif  // GTEST_USES_PCRE
+
+#ifndef GTEST_HAS_EXCEPTIONS
+// The user didn't tell us whether exceptions are enabled, so we need
+// to figure it out.
+# if defined(_MSC_VER) || defined(__BORLANDC__)
+// MSVC's and C++Builder's implementations of the STL use the _HAS_EXCEPTIONS
+// macro to enable exceptions, so we'll do the same.
+// Assumes that exceptions are enabled by default.
+#  ifndef _HAS_EXCEPTIONS
+#   define _HAS_EXCEPTIONS 1
+#  endif  // _HAS_EXCEPTIONS
+#  define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS
+# elif defined(__clang__)
+// clang defines __EXCEPTIONS iff exceptions are enabled before clang 220714,
+// but iff cleanups are enabled after that. In Obj-C++ files, there can be
+// cleanups for ObjC exceptions which also need cleanups, even if C++ exceptions
+// are disabled. clang has __has_feature(cxx_exceptions) which checks for C++
+// exceptions starting at clang r206352, but which checked for cleanups prior to
+// that. To reliably check for C++ exception availability with clang, check for
+// __EXCEPTIONS && __has_feature(cxx_exceptions).
+#  define GTEST_HAS_EXCEPTIONS (__EXCEPTIONS && __has_feature(cxx_exceptions))
+# elif defined(__GNUC__) && __EXCEPTIONS
+// gcc defines __EXCEPTIONS to 1 iff exceptions are enabled.
+#  define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__SUNPRO_CC)
+// Sun Pro CC supports exceptions.  However, there is no compile-time way of
+// detecting whether they are enabled or not.  Therefore, we assume that
+// they are enabled unless the user tells us otherwise.
+#  define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__IBMCPP__) && __EXCEPTIONS
+// xlC defines __EXCEPTIONS to 1 iff exceptions are enabled.
+#  define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__HP_aCC)
+// Exception handling is in effect by default in HP aCC compiler. It has to
+// be turned of by +noeh compiler option if desired.
+#  define GTEST_HAS_EXCEPTIONS 1
+# else
+// For other compilers, we assume exceptions are disabled to be
+// conservative.
+#  define GTEST_HAS_EXCEPTIONS 0
+# endif  // defined(_MSC_VER) || defined(__BORLANDC__)
+#endif  // GTEST_HAS_EXCEPTIONS
+
+#if !defined(GTEST_HAS_STD_STRING)
+// Even though we don't use this macro any longer, we keep it in case
+// some clients still depend on it.
+# define GTEST_HAS_STD_STRING 1
+#elif !GTEST_HAS_STD_STRING
+// The user told us that ::std::string isn't available.
+# error "Google Test cannot be used where ::std::string isn't available."
+#endif  // !defined(GTEST_HAS_STD_STRING)
+
+#ifndef GTEST_HAS_GLOBAL_STRING
+// The user didn't tell us whether ::string is available, so we need
+// to figure it out.
+
+# define GTEST_HAS_GLOBAL_STRING 0
+
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+#ifndef GTEST_HAS_STD_WSTRING
+// The user didn't tell us whether ::std::wstring is available, so we need
+// to figure it out.
+// TODO(wan@google.com): uses autoconf to detect whether ::std::wstring
+//   is available.
+
+// Cygwin 1.7 and below doesn't support ::std::wstring.
+// Solaris' libc++ doesn't support it either.  Android has
+// no support for it at least as recent as Froyo (2.2).
+# define GTEST_HAS_STD_WSTRING \
+    (!(GTEST_OS_LINUX_ANDROID || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS))
+
+#endif  // GTEST_HAS_STD_WSTRING
+
+#ifndef GTEST_HAS_GLOBAL_WSTRING
+// The user didn't tell us whether ::wstring is available, so we need
+// to figure it out.
+# define GTEST_HAS_GLOBAL_WSTRING \
+    (GTEST_HAS_STD_WSTRING && GTEST_HAS_GLOBAL_STRING)
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+// Determines whether RTTI is available.
+#ifndef GTEST_HAS_RTTI
+// The user didn't tell us whether RTTI is enabled, so we need to
+// figure it out.
+
+# ifdef _MSC_VER
+
+#  ifdef _CPPRTTI  // MSVC defines this macro iff RTTI is enabled.
+#   define GTEST_HAS_RTTI 1
+#  else
+#   define GTEST_HAS_RTTI 0
+#  endif
+
+// Starting with version 4.3.2, gcc defines __GXX_RTTI iff RTTI is enabled.
+# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40302)
+
+#  ifdef __GXX_RTTI
+// When building against STLport with the Android NDK and with
+// -frtti -fno-exceptions, the build fails at link time with undefined
+// references to __cxa_bad_typeid. Note sure if STL or toolchain bug,
+// so disable RTTI when detected.
+#   if GTEST_OS_LINUX_ANDROID && defined(_STLPORT_MAJOR) && \
+       !defined(__EXCEPTIONS)
+#    define GTEST_HAS_RTTI 0
+#   else
+#    define GTEST_HAS_RTTI 1
+#   endif  // GTEST_OS_LINUX_ANDROID && __STLPORT_MAJOR && !__EXCEPTIONS
+#  else
+#   define GTEST_HAS_RTTI 0
+#  endif  // __GXX_RTTI
+
+// Clang defines __GXX_RTTI starting with version 3.0, but its manual recommends
+// using has_feature instead. has_feature(cxx_rtti) is supported since 2.7, the
+// first version with C++ support.
+# elif defined(__clang__)
+
+#  define GTEST_HAS_RTTI __has_feature(cxx_rtti)
+
+// Starting with version 9.0 IBM Visual Age defines __RTTI_ALL__ to 1 if
+// both the typeid and dynamic_cast features are present.
+# elif defined(__IBMCPP__) && (__IBMCPP__ >= 900)
+
+#  ifdef __RTTI_ALL__
+#   define GTEST_HAS_RTTI 1
+#  else
+#   define GTEST_HAS_RTTI 0
+#  endif
+
+# else
+
+// For all other compilers, we assume RTTI is enabled.
+#  define GTEST_HAS_RTTI 1
+
+# endif  // _MSC_VER
+
+#endif  // GTEST_HAS_RTTI
+
+// It's this header's responsibility to #include <typeinfo> when RTTI
+// is enabled.
+#if GTEST_HAS_RTTI
+# include <typeinfo>
+#endif
+
+// Determines whether Google Test can use the pthreads library.
+#ifndef GTEST_HAS_PTHREAD
+// The user didn't tell us explicitly, so we make reasonable assumptions about
+// which platforms have pthreads support.
+//
+// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0
+// to your compiler flags.
+# define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX \
+    || GTEST_OS_QNX || GTEST_OS_FREEBSD || GTEST_OS_NACL)
+#endif  // GTEST_HAS_PTHREAD
+
+#if GTEST_HAS_PTHREAD
+// gtest-port.h guarantees to #include <pthread.h> when GTEST_HAS_PTHREAD is
+// true.
+# include <pthread.h>  // NOLINT
+
+// For timespec and nanosleep, used below.
+# include <time.h>  // NOLINT
+#endif
+
+// Determines if hash_map/hash_set are available.
+// Only used for testing against those containers.
+#if !defined(GTEST_HAS_HASH_MAP_)
+# if _MSC_VER
+#  define GTEST_HAS_HASH_MAP_ 1  // Indicates that hash_map is available.
+#  define GTEST_HAS_HASH_SET_ 1  // Indicates that hash_set is available.
+# endif  // _MSC_VER
+#endif  // !defined(GTEST_HAS_HASH_MAP_)
+
+// Determines whether Google Test can use tr1/tuple.  You can define
+// this macro to 0 to prevent Google Test from using tuple (any
+// feature depending on tuple with be disabled in this mode).
+#ifndef GTEST_HAS_TR1_TUPLE
+# if GTEST_OS_LINUX_ANDROID && defined(_STLPORT_MAJOR)
+// STLport, provided with the Android NDK, has neither <tr1/tuple> or <tuple>.
+#  define GTEST_HAS_TR1_TUPLE 0
+# else
+// The user didn't tell us not to do it, so we assume it's OK.
+#  define GTEST_HAS_TR1_TUPLE 1
+# endif
+#endif  // GTEST_HAS_TR1_TUPLE
+
+// Determines whether Google Test's own tr1 tuple implementation
+// should be used.
+#ifndef GTEST_USE_OWN_TR1_TUPLE
+// The user didn't tell us, so we need to figure it out.
+
+// We use our own TR1 tuple if we aren't sure the user has an
+// implementation of it already.  At this time, libstdc++ 4.0.0+ and
+// MSVC 2010 are the only mainstream standard libraries that come
+// with a TR1 tuple implementation.  NVIDIA's CUDA NVCC compiler
+// pretends to be GCC by defining __GNUC__ and friends, but cannot
+// compile GCC's tuple implementation.  MSVC 2008 (9.0) provides TR1
+// tuple in a 323 MB Feature Pack download, which we cannot assume the
+// user has.  QNX's QCC compiler is a modified GCC but it doesn't
+// support TR1 tuple.  libc++ only provides std::tuple, in C++11 mode,
+// and it can be used with some compilers that define __GNUC__.
+# if (defined(__GNUC__) && !defined(__CUDACC__) && (GTEST_GCC_VER_ >= 40000) \
+      && !GTEST_OS_QNX && !defined(_LIBCPP_VERSION)) || _MSC_VER >= 1600
+#  define GTEST_ENV_HAS_TR1_TUPLE_ 1
+# endif
+
+// C++11 specifies that <tuple> provides std::tuple. Use that if gtest is used
+// in C++11 mode and libstdc++ isn't very old (binaries targeting OS X 10.6
+// can build with clang but need to use gcc4.2's libstdc++).
+# if GTEST_LANG_CXX11 && (!defined(__GLIBCXX__) || __GLIBCXX__ > 20110325)
+#  define GTEST_ENV_HAS_STD_TUPLE_ 1
+# endif
+
+# if GTEST_ENV_HAS_TR1_TUPLE_ || GTEST_ENV_HAS_STD_TUPLE_
+#  define GTEST_USE_OWN_TR1_TUPLE 0
+# else
+#  define GTEST_USE_OWN_TR1_TUPLE 1
+# endif
+
+#endif  // GTEST_USE_OWN_TR1_TUPLE
+
+// To avoid conditional compilation everywhere, we make it
+// gtest-port.h's responsibility to #include the header implementing
+// tuple.
+#if GTEST_HAS_STD_TUPLE_
+# include <tuple>  // IWYU pragma: export
+# define GTEST_TUPLE_NAMESPACE_ ::std
+#endif  // GTEST_HAS_STD_TUPLE_
+
+// We include tr1::tuple even if std::tuple is available to define printers for
+// them.
+#if GTEST_HAS_TR1_TUPLE
+# ifndef GTEST_TUPLE_NAMESPACE_
+#  define GTEST_TUPLE_NAMESPACE_ ::std::tr1
+# endif  // GTEST_TUPLE_NAMESPACE_
+
+# if GTEST_USE_OWN_TR1_TUPLE
+#  include "gtest/internal/gtest-tuple.h"  // IWYU pragma: export  // NOLINT
+# elif GTEST_ENV_HAS_STD_TUPLE_
+#  include <tuple>
+// C++11 puts its tuple into the ::std namespace rather than
+// ::std::tr1.  gtest expects tuple to live in ::std::tr1, so put it there.
+// This causes undefined behavior, but supported compilers react in
+// the way we intend.
+namespace std {
+namespace tr1 {
+using ::std::get;
+using ::std::make_tuple;
+using ::std::tuple;
+using ::std::tuple_element;
+using ::std::tuple_size;
+}
+}
+
+# elif GTEST_OS_SYMBIAN
+
+// On Symbian, BOOST_HAS_TR1_TUPLE causes Boost's TR1 tuple library to
+// use STLport's tuple implementation, which unfortunately doesn't
+// work as the copy of STLport distributed with Symbian is incomplete.
+// By making sure BOOST_HAS_TR1_TUPLE is undefined, we force Boost to
+// use its own tuple implementation.
+#  ifdef BOOST_HAS_TR1_TUPLE
+#   undef BOOST_HAS_TR1_TUPLE
+#  endif  // BOOST_HAS_TR1_TUPLE
+
+// This prevents <boost/tr1/detail/config.hpp>, which defines
+// BOOST_HAS_TR1_TUPLE, from being #included by Boost's <tuple>.
+#  define BOOST_TR1_DETAIL_CONFIG_HPP_INCLUDED
+#  include <tuple>  // IWYU pragma: export  // NOLINT
+
+# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000)
+// GCC 4.0+ implements tr1/tuple in the <tr1/tuple> header.  This does
+// not conform to the TR1 spec, which requires the header to be <tuple>.
+
+#  if !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
+// Until version 4.3.2, gcc has a bug that causes <tr1/functional>,
+// which is #included by <tr1/tuple>, to not compile when RTTI is
+// disabled.  _TR1_FUNCTIONAL is the header guard for
+// <tr1/functional>.  Hence the following #define is a hack to prevent
+// <tr1/functional> from being included.
+#   define _TR1_FUNCTIONAL 1
+#   include <tr1/tuple>
+#   undef _TR1_FUNCTIONAL  // Allows the user to #include
+                        // <tr1/functional> if he chooses to.
+#  else
+#   include <tr1/tuple>  // NOLINT
+#  endif  // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
+
+# else
+// If the compiler is not GCC 4.0+, we assume the user is using a
+// spec-conforming TR1 implementation.
+#  include <tuple>  // IWYU pragma: export  // NOLINT
+# endif  // GTEST_USE_OWN_TR1_TUPLE
+
+#endif  // GTEST_HAS_TR1_TUPLE
+
+// Determines whether clone(2) is supported.
+// Usually it will only be available on Linux, excluding
+// Linux on the Itanium architecture.
+// Also see http://linux.die.net/man/2/clone.
+#ifndef GTEST_HAS_CLONE
+// The user didn't tell us, so we need to figure it out.
+
+# if GTEST_OS_LINUX && !defined(__ia64__)
+#  if GTEST_OS_LINUX_ANDROID
+// On Android, clone() is only available on ARM starting with Gingerbread.
+#    if defined(__arm__) && __ANDROID_API__ >= 9
+#     define GTEST_HAS_CLONE 1
+#    else
+#     define GTEST_HAS_CLONE 0
+#    endif
+#  else
+#   define GTEST_HAS_CLONE 1
+#  endif
+# else
+#  define GTEST_HAS_CLONE 0
+# endif  // GTEST_OS_LINUX && !defined(__ia64__)
+
+#endif  // GTEST_HAS_CLONE
+
+// Determines whether to support stream redirection. This is used to test
+// output correctness and to implement death tests.
+#ifndef GTEST_HAS_STREAM_REDIRECTION
+// By default, we assume that stream redirection is supported on all
+// platforms except known mobile ones.
+# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || \
+    GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT
+#  define GTEST_HAS_STREAM_REDIRECTION 0
+# else
+#  define GTEST_HAS_STREAM_REDIRECTION 1
+# endif  // !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_SYMBIAN
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+// Determines whether to support death tests.
+// Google Test does not support death tests for VC 7.1 and earlier as
+// abort() in a VC 7.1 application compiled as GUI in debug config
+// pops up a dialog window that cannot be suppressed programmatically.
+#if (GTEST_OS_LINUX || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \
+     (GTEST_OS_MAC && !GTEST_OS_IOS) || \
+     (GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || \
+     GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || GTEST_OS_HPUX || \
+     GTEST_OS_OPENBSD || GTEST_OS_QNX || GTEST_OS_FREEBSD)
+# define GTEST_HAS_DEATH_TEST 1
+#endif
+
+// We don't support MSVC 7.1 with exceptions disabled now.  Therefore
+// all the compilers we care about are adequate for supporting
+// value-parameterized tests.
+#define GTEST_HAS_PARAM_TEST 1
+
+// Determines whether to support type-driven tests.
+
+// Typed tests need <typeinfo> and variadic macros, which GCC, VC++ 8.0,
+// Sun Pro CC, IBM Visual Age, and HP aCC support.
+#if defined(__GNUC__) || (_MSC_VER >= 1400) || defined(__SUNPRO_CC) || \
+    defined(__IBMCPP__) || defined(__HP_aCC)
+# define GTEST_HAS_TYPED_TEST 1
+# define GTEST_HAS_TYPED_TEST_P 1
+#endif
+
+// Determines whether to support Combine(). This only makes sense when
+// value-parameterized tests are enabled.  The implementation doesn't
+// work on Sun Studio since it doesn't understand templated conversion
+// operators.
+#if GTEST_HAS_PARAM_TEST && GTEST_HAS_TR1_TUPLE && !defined(__SUNPRO_CC)
+# define GTEST_HAS_COMBINE 1
+#endif
+
+// Determines whether the system compiler uses UTF-16 for encoding wide strings.
+#define GTEST_WIDE_STRING_USES_UTF16_ \
+    (GTEST_OS_WINDOWS || GTEST_OS_CYGWIN || GTEST_OS_SYMBIAN || GTEST_OS_AIX)
+
+// Determines whether test results can be streamed to a socket.
+#if GTEST_OS_LINUX
+# define GTEST_CAN_STREAM_RESULTS_ 1
+#endif
+
+// Defines some utility macros.
+
+// The GNU compiler emits a warning if nested "if" statements are followed by
+// an "else" statement and braces are not used to explicitly disambiguate the
+// "else" binding.  This leads to problems with code like:
+//
+//   if (gate)
+//     ASSERT_*(condition) << "Some message";
+//
+// The "switch (0) case 0:" idiom is used to suppress this.
+#ifdef __INTEL_COMPILER
+# define GTEST_AMBIGUOUS_ELSE_BLOCKER_
+#else
+# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: default:  // NOLINT
+#endif
+
+// Use this annotation at the end of a struct/class definition to
+// prevent the compiler from optimizing away instances that are never
+// used.  This is useful when all interesting logic happens inside the
+// c'tor and / or d'tor.  Example:
+//
+//   struct Foo {
+//     Foo() { ... }
+//   } GTEST_ATTRIBUTE_UNUSED_;
+//
+// Also use it after a variable or parameter declaration to tell the
+// compiler the variable/parameter does not have to be used.
+#if defined(__GNUC__) && !defined(COMPILER_ICC)
+# define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused))
+#elif defined(__clang__)
+# if __has_attribute(unused)
+#  define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused))
+# endif
+#endif
+#ifndef GTEST_ATTRIBUTE_UNUSED_
+# define GTEST_ATTRIBUTE_UNUSED_
+#endif
+
+// A macro to disallow operator=
+// This should be used in the private: declarations for a class.
+#define GTEST_DISALLOW_ASSIGN_(type)\
+  void operator=(type const &)
+
+// A macro to disallow copy constructor and operator=
+// This should be used in the private: declarations for a class.
+#define GTEST_DISALLOW_COPY_AND_ASSIGN_(type)\
+  type(type const &);\
+  GTEST_DISALLOW_ASSIGN_(type)
+
+// Tell the compiler to warn about unused return values for functions declared
+// with this macro.  The macro should be used on function declarations
+// following the argument list:
+//
+//   Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_;
+#if defined(__GNUC__) && (GTEST_GCC_VER_ >= 30400) && !defined(COMPILER_ICC)
+# define GTEST_MUST_USE_RESULT_ __attribute__ ((warn_unused_result))
+#else
+# define GTEST_MUST_USE_RESULT_
+#endif  // __GNUC__ && (GTEST_GCC_VER_ >= 30400) && !COMPILER_ICC
+
+// MS C++ compiler emits warning when a conditional expression is compile time
+// constant. In some contexts this warning is false positive and needs to be
+// suppressed. Use the following two macros in such cases:
+//
+// GTEST_INTENTIONAL_CONST_COND_PUSH_()
+// while (true) {
+// GTEST_INTENTIONAL_CONST_COND_POP_()
+// }
+# define GTEST_INTENTIONAL_CONST_COND_PUSH_() \
+    GTEST_DISABLE_MSC_WARNINGS_PUSH_(4127)
+# define GTEST_INTENTIONAL_CONST_COND_POP_() \
+    GTEST_DISABLE_MSC_WARNINGS_POP_()
+
+// Determine whether the compiler supports Microsoft's Structured Exception
+// Handling.  This is supported by several Windows compilers but generally
+// does not exist on any other system.
+#ifndef GTEST_HAS_SEH
+// The user didn't tell us, so we need to figure it out.
+
+# if defined(_MSC_VER) || defined(__BORLANDC__)
+// These two compilers are known to support SEH.
+#  define GTEST_HAS_SEH 1
+# else
+// Assume no SEH.
+#  define GTEST_HAS_SEH 0
+# endif
+
+#define GTEST_IS_THREADSAFE \
+    (GTEST_HAS_MUTEX_AND_THREAD_LOCAL_ \
+     || (GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT) \
+     || GTEST_HAS_PTHREAD)
+
+#endif  // GTEST_HAS_SEH
+
+#ifdef _MSC_VER
+
+# if GTEST_LINKED_AS_SHARED_LIBRARY
+#  define GTEST_API_ __declspec(dllimport)
+# elif GTEST_CREATE_SHARED_LIBRARY
+#  define GTEST_API_ __declspec(dllexport)
+# endif
+
+#endif  // _MSC_VER
+
+#ifndef GTEST_API_
+# define GTEST_API_
+#endif
+
+#ifdef __GNUC__
+// Ask the compiler to never inline a given function.
+# define GTEST_NO_INLINE_ __attribute__((noinline))
+#else
+# define GTEST_NO_INLINE_
+#endif
+
+// _LIBCPP_VERSION is defined by the libc++ library from the LLVM project.
+#if defined(__GLIBCXX__) || defined(_LIBCPP_VERSION)
+# define GTEST_HAS_CXXABI_H_ 1
+#else
+# define GTEST_HAS_CXXABI_H_ 0
+#endif
+
+// A function level attribute to disable checking for use of uninitialized
+// memory when built with MemorySanitizer.
+#if defined(__clang__)
+# if __has_feature(memory_sanitizer)
+#  define GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ \
+       __attribute__((no_sanitize_memory))
+# else
+#  define GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
+# endif  // __has_feature(memory_sanitizer)
+#else
+# define GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
+#endif  // __clang__
+
+// A function level attribute to disable AddressSanitizer instrumentation.
+#if defined(__clang__)
+# if __has_feature(address_sanitizer)
+#  define GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ \
+       __attribute__((no_sanitize_address))
+# else
+#  define GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
+# endif  // __has_feature(address_sanitizer)
+#else
+# define GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
+#endif  // __clang__
+
+// A function level attribute to disable ThreadSanitizer instrumentation.
+#if defined(__clang__)
+# if __has_feature(thread_sanitizer)
+#  define GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ \
+       __attribute__((no_sanitize_thread))
+# else
+#  define GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
+# endif  // __has_feature(thread_sanitizer)
+#else
+# define GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
+#endif  // __clang__
+
+namespace testing {
+
+class Message;
+
+#if defined(GTEST_TUPLE_NAMESPACE_)
+// Import tuple and friends into the ::testing namespace.
+// It is part of our interface, having them in ::testing allows us to change
+// their types as needed.
+using GTEST_TUPLE_NAMESPACE_::get;
+using GTEST_TUPLE_NAMESPACE_::make_tuple;
+using GTEST_TUPLE_NAMESPACE_::tuple;
+using GTEST_TUPLE_NAMESPACE_::tuple_size;
+using GTEST_TUPLE_NAMESPACE_::tuple_element;
+#endif  // defined(GTEST_TUPLE_NAMESPACE_)
+
+namespace internal {
+
+// A secret type that Google Test users don't know about.  It has no
+// definition on purpose.  Therefore it's impossible to create a
+// Secret object, which is what we want.
+class Secret;
+
+// The GTEST_COMPILE_ASSERT_ macro can be used to verify that a compile time
+// expression is true. For example, you could use it to verify the
+// size of a static array:
+//
+//   GTEST_COMPILE_ASSERT_(GTEST_ARRAY_SIZE_(names) == NUM_NAMES,
+//                         names_incorrect_size);
+//
+// or to make sure a struct is smaller than a certain size:
+//
+//   GTEST_COMPILE_ASSERT_(sizeof(foo) < 128, foo_too_large);
+//
+// The second argument to the macro is the name of the variable. If
+// the expression is false, most compilers will issue a warning/error
+// containing the name of the variable.
+
+#if GTEST_LANG_CXX11
+# define GTEST_COMPILE_ASSERT_(expr, msg) static_assert(expr, #msg)
+#else  // !GTEST_LANG_CXX11
+template <bool>
+  struct CompileAssert {
+};
+
+# define GTEST_COMPILE_ASSERT_(expr, msg) \
+  typedef ::testing::internal::CompileAssert<(static_cast<bool>(expr))> \
+      msg[static_cast<bool>(expr) ? 1 : -1] GTEST_ATTRIBUTE_UNUSED_
+#endif  // !GTEST_LANG_CXX11
+
+// Implementation details of GTEST_COMPILE_ASSERT_:
+//
+// (In C++11, we simply use static_assert instead of the following)
+//
+// - GTEST_COMPILE_ASSERT_ works by defining an array type that has -1
+//   elements (and thus is invalid) when the expression is false.
+//
+// - The simpler definition
+//
+//    #define GTEST_COMPILE_ASSERT_(expr, msg) typedef char msg[(expr) ? 1 : -1]
+//
+//   does not work, as gcc supports variable-length arrays whose sizes
+//   are determined at run-time (this is gcc's extension and not part
+//   of the C++ standard).  As a result, gcc fails to reject the
+//   following code with the simple definition:
+//
+//     int foo;
+//     GTEST_COMPILE_ASSERT_(foo, msg); // not supposed to compile as foo is
+//                                      // not a compile-time constant.
+//
+// - By using the type CompileAssert<(bool(expr))>, we ensures that
+//   expr is a compile-time constant.  (Template arguments must be
+//   determined at compile-time.)
+//
+// - The outter parentheses in CompileAssert<(bool(expr))> are necessary
+//   to work around a bug in gcc 3.4.4 and 4.0.1.  If we had written
+//
+//     CompileAssert<bool(expr)>
+//
+//   instead, these compilers will refuse to compile
+//
+//     GTEST_COMPILE_ASSERT_(5 > 0, some_message);
+//
+//   (They seem to think the ">" in "5 > 0" marks the end of the
+//   template argument list.)
+//
+// - The array size is (bool(expr) ? 1 : -1), instead of simply
+//
+//     ((expr) ? 1 : -1).
+//
+//   This is to avoid running into a bug in MS VC 7.1, which
+//   causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
+
+// StaticAssertTypeEqHelper is used by StaticAssertTypeEq defined in gtest.h.
+//
+// This template is declared, but intentionally undefined.
+template <typename T1, typename T2>
+struct StaticAssertTypeEqHelper;
+
+template <typename T>
+struct StaticAssertTypeEqHelper<T, T> {
+  enum { value = true };
+};
+
+// Evaluates to the number of elements in 'array'.
+#define GTEST_ARRAY_SIZE_(array) (sizeof(array) / sizeof(array[0]))
+
+#if GTEST_HAS_GLOBAL_STRING
+typedef ::string string;
+#else
+typedef ::std::string string;
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+typedef ::wstring wstring;
+#elif GTEST_HAS_STD_WSTRING
+typedef ::std::wstring wstring;
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+// A helper for suppressing warnings on constant condition.  It just
+// returns 'condition'.
+GTEST_API_ bool IsTrue(bool condition);
+
+// Defines scoped_ptr.
+
+// This implementation of scoped_ptr is PARTIAL - it only contains
+// enough stuff to satisfy Google Test's need.
+template <typename T>
+class scoped_ptr {
+ public:
+  typedef T element_type;
+
+  explicit scoped_ptr(T* p = NULL) : ptr_(p) {}
+  ~scoped_ptr() { reset(); }
+
+  T& operator*() const { return *ptr_; }
+  T* operator->() const { return ptr_; }
+  T* get() const { return ptr_; }
+
+  T* release() {
+    T* const ptr = ptr_;
+    ptr_ = NULL;
+    return ptr;
+  }
+
+  void reset(T* p = NULL) {
+    if (p != ptr_) {
+      if (IsTrue(sizeof(T) > 0)) {  // Makes sure T is a complete type.
+        delete ptr_;
+      }
+      ptr_ = p;
+    }
+  }
+
+  friend void swap(scoped_ptr& a, scoped_ptr& b) {
+    using std::swap;
+    swap(a.ptr_, b.ptr_);
+  }
+
+ private:
+  T* ptr_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(scoped_ptr);
+};
+
+// Defines RE.
+
+// A simple C++ wrapper for <regex.h>.  It uses the POSIX Extended
+// Regular Expression syntax.
+class GTEST_API_ RE {
+ public:
+  // A copy constructor is required by the Standard to initialize object
+  // references from r-values.
+  RE(const RE& other) { Init(other.pattern()); }
+
+  // Constructs an RE from a string.
+  RE(const ::std::string& regex) { Init(regex.c_str()); }  // NOLINT
+
+#if GTEST_HAS_GLOBAL_STRING
+
+  RE(const ::string& regex) { Init(regex.c_str()); }  // NOLINT
+
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+  RE(const char* regex) { Init(regex); }  // NOLINT
+  ~RE();
+
+  // Returns the string representation of the regex.
+  const char* pattern() const { return pattern_; }
+
+  // FullMatch(str, re) returns true iff regular expression re matches
+  // the entire str.
+  // PartialMatch(str, re) returns true iff regular expression re
+  // matches a substring of str (including str itself).
+  //
+  // TODO(wan@google.com): make FullMatch() and PartialMatch() work
+  // when str contains NUL characters.
+  static bool FullMatch(const ::std::string& str, const RE& re) {
+    return FullMatch(str.c_str(), re);
+  }
+  static bool PartialMatch(const ::std::string& str, const RE& re) {
+    return PartialMatch(str.c_str(), re);
+  }
+
+#if GTEST_HAS_GLOBAL_STRING
+
+  static bool FullMatch(const ::string& str, const RE& re) {
+    return FullMatch(str.c_str(), re);
+  }
+  static bool PartialMatch(const ::string& str, const RE& re) {
+    return PartialMatch(str.c_str(), re);
+  }
+
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+  static bool FullMatch(const char* str, const RE& re);
+  static bool PartialMatch(const char* str, const RE& re);
+
+ private:
+  void Init(const char* regex);
+
+  // We use a const char* instead of an std::string, as Google Test used to be
+  // used where std::string is not available.  TODO(wan@google.com): change to
+  // std::string.
+  const char* pattern_;
+  bool is_valid_;
+
+#if GTEST_USES_POSIX_RE
+
+  regex_t full_regex_;     // For FullMatch().
+  regex_t partial_regex_;  // For PartialMatch().
+
+#else  // GTEST_USES_SIMPLE_RE
+
+  const char* full_pattern_;  // For FullMatch();
+
+#endif
+
+  GTEST_DISALLOW_ASSIGN_(RE);
+};
+
+// Formats a source file path and a line number as they would appear
+// in an error message from the compiler used to compile this code.
+GTEST_API_ ::std::string FormatFileLocation(const char* file, int line);
+
+// Formats a file location for compiler-independent XML output.
+// Although this function is not platform dependent, we put it next to
+// FormatFileLocation in order to contrast the two functions.
+GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(const char* file,
+                                                               int line);
+
+// Defines logging utilities:
+//   GTEST_LOG_(severity) - logs messages at the specified severity level. The
+//                          message itself is streamed into the macro.
+//   LogToStderr()  - directs all log messages to stderr.
+//   FlushInfoLog() - flushes informational log messages.
+
+enum GTestLogSeverity {
+  GTEST_INFO,
+  GTEST_WARNING,
+  GTEST_ERROR,
+  GTEST_FATAL
+};
+
+// Formats log entry severity, provides a stream object for streaming the
+// log message, and terminates the message with a newline when going out of
+// scope.
+class GTEST_API_ GTestLog {
+ public:
+  GTestLog(GTestLogSeverity severity, const char* file, int line);
+
+  // Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
+  ~GTestLog();
+
+  ::std::ostream& GetStream() { return ::std::cerr; }
+
+ private:
+  const GTestLogSeverity severity_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestLog);
+};
+
+#if !defined(GTEST_LOG_)
+
+# define GTEST_LOG_(severity) \
+    ::testing::internal::GTestLog(::testing::internal::GTEST_##severity, \
+                                  __FILE__, __LINE__).GetStream()
+
+inline void LogToStderr() {}
+inline void FlushInfoLog() { fflush(NULL); }
+
+#endif  // !defined(GTEST_LOG_)
+
+#if !defined(GTEST_CHECK_)
+// INTERNAL IMPLEMENTATION - DO NOT USE.
+//
+// GTEST_CHECK_ is an all-mode assert. It aborts the program if the condition
+// is not satisfied.
+//  Synopsys:
+//    GTEST_CHECK_(boolean_condition);
+//     or
+//    GTEST_CHECK_(boolean_condition) << "Additional message";
+//
+//    This checks the condition and if the condition is not satisfied
+//    it prints message about the condition violation, including the
+//    condition itself, plus additional message streamed into it, if any,
+//    and then it aborts the program. It aborts the program irrespective of
+//    whether it is built in the debug mode or not.
+# define GTEST_CHECK_(condition) \
+    GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+    if (::testing::internal::IsTrue(condition)) \
+      ; \
+    else \
+      GTEST_LOG_(FATAL) << "Condition " #condition " failed. "
+#endif  // !defined(GTEST_CHECK_)
+
+// An all-mode assert to verify that the given POSIX-style function
+// call returns 0 (indicating success).  Known limitation: this
+// doesn't expand to a balanced 'if' statement, so enclose the macro
+// in {} if you need to use it as the only statement in an 'if'
+// branch.
+#define GTEST_CHECK_POSIX_SUCCESS_(posix_call) \
+  if (const int gtest_error = (posix_call)) \
+    GTEST_LOG_(FATAL) << #posix_call << "failed with error " \
+                      << gtest_error
+
+#if GTEST_HAS_STD_MOVE_
+using std::move;
+#else  // GTEST_HAS_STD_MOVE_
+template <typename T>
+const T& move(const T& t) {
+  return t;
+}
+#endif  // GTEST_HAS_STD_MOVE_
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Use ImplicitCast_ as a safe version of static_cast for upcasting in
+// the type hierarchy (e.g. casting a Foo* to a SuperclassOfFoo* or a
+// const Foo*).  When you use ImplicitCast_, the compiler checks that
+// the cast is safe.  Such explicit ImplicitCast_s are necessary in
+// surprisingly many situations where C++ demands an exact type match
+// instead of an argument type convertable to a target type.
+//
+// The syntax for using ImplicitCast_ is the same as for static_cast:
+//
+//   ImplicitCast_<ToType>(expr)
+//
+// ImplicitCast_ would have been part of the C++ standard library,
+// but the proposal was submitted too late.  It will probably make
+// its way into the language in the future.
+//
+// This relatively ugly name is intentional. It prevents clashes with
+// similar functions users may have (e.g., implicit_cast). The internal
+// namespace alone is not enough because the function can be found by ADL.
+template<typename To>
+inline To ImplicitCast_(To x) { return x; }
+
+// When you upcast (that is, cast a pointer from type Foo to type
+// SuperclassOfFoo), it's fine to use ImplicitCast_<>, since upcasts
+// always succeed.  When you downcast (that is, cast a pointer from
+// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because
+// how do you know the pointer is really of type SubclassOfFoo?  It
+// could be a bare Foo, or of type DifferentSubclassOfFoo.  Thus,
+// when you downcast, you should use this macro.  In debug mode, we
+// use dynamic_cast<> to double-check the downcast is legal (we die
+// if it's not).  In normal mode, we do the efficient static_cast<>
+// instead.  Thus, it's important to test in debug mode to make sure
+// the cast is legal!
+//    This is the only place in the code we should use dynamic_cast<>.
+// In particular, you SHOULDN'T be using dynamic_cast<> in order to
+// do RTTI (eg code like this:
+//    if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo);
+//    if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo);
+// You should design the code some other way not to need this.
+//
+// This relatively ugly name is intentional. It prevents clashes with
+// similar functions users may have (e.g., down_cast). The internal
+// namespace alone is not enough because the function can be found by ADL.
+template<typename To, typename From>  // use like this: DownCast_<T*>(foo);
+inline To DownCast_(From* f) {  // so we only accept pointers
+  // Ensures that To is a sub-type of From *.  This test is here only
+  // for compile-time type checking, and has no overhead in an
+  // optimized build at run-time, as it will be optimized away
+  // completely.
+  GTEST_INTENTIONAL_CONST_COND_PUSH_()
+  if (false) {
+  GTEST_INTENTIONAL_CONST_COND_POP_()
+    const To to = NULL;
+    ::testing::internal::ImplicitCast_<From*>(to);
+  }
+
+#if GTEST_HAS_RTTI
+  // RTTI: debug mode only!
+  GTEST_CHECK_(f == NULL || dynamic_cast<To>(f) != NULL);
+#endif
+  return static_cast<To>(f);
+}
+
+// Downcasts the pointer of type Base to Derived.
+// Derived must be a subclass of Base. The parameter MUST
+// point to a class of type Derived, not any subclass of it.
+// When RTTI is available, the function performs a runtime
+// check to enforce this.
+template <class Derived, class Base>
+Derived* CheckedDowncastToActualType(Base* base) {
+#if GTEST_HAS_RTTI
+  GTEST_CHECK_(typeid(*base) == typeid(Derived));
+#endif
+
+#if GTEST_HAS_DOWNCAST_
+  return ::down_cast<Derived*>(base);
+#elif GTEST_HAS_RTTI
+  return dynamic_cast<Derived*>(base);  // NOLINT
+#else
+  return static_cast<Derived*>(base);  // Poor man's downcast.
+#endif
+}
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Defines the stderr capturer:
+//   CaptureStdout     - starts capturing stdout.
+//   GetCapturedStdout - stops capturing stdout and returns the captured string.
+//   CaptureStderr     - starts capturing stderr.
+//   GetCapturedStderr - stops capturing stderr and returns the captured string.
+//
+GTEST_API_ void CaptureStdout();
+GTEST_API_ std::string GetCapturedStdout();
+GTEST_API_ void CaptureStderr();
+GTEST_API_ std::string GetCapturedStderr();
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+// Returns a path to temporary directory.
+GTEST_API_ std::string TempDir();
+
+// Returns the size (in bytes) of a file.
+GTEST_API_ size_t GetFileSize(FILE* file);
+
+// Reads the entire content of a file as a string.
+GTEST_API_ std::string ReadEntireFile(FILE* file);
+
+// All command line arguments.
+GTEST_API_ const ::std::vector<testing::internal::string>& GetArgvs();
+
+#if GTEST_HAS_DEATH_TEST
+
+const ::std::vector<testing::internal::string>& GetInjectableArgvs();
+void SetInjectableArgvs(const ::std::vector<testing::internal::string>*
+                             new_argvs);
+
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+// Defines synchronization primitives.
+#if GTEST_IS_THREADSAFE
+# if GTEST_HAS_PTHREAD
+// Sleeps for (roughly) n milliseconds.  This function is only for testing
+// Google Test's own constructs.  Don't use it in user tests, either
+// directly or indirectly.
+inline void SleepMilliseconds(int n) {
+  const timespec time = {
+    0,                  // 0 seconds.
+    n * 1000L * 1000L,  // And n ms.
+  };
+  nanosleep(&time, NULL);
+}
+# endif  // GTEST_HAS_PTHREAD
+
+# if GTEST_HAS_NOTIFICATION_
+// Notification has already been imported into the namespace.
+// Nothing to do here.
+
+# elif GTEST_HAS_PTHREAD
+// Allows a controller thread to pause execution of newly created
+// threads until notified.  Instances of this class must be created
+// and destroyed in the controller thread.
+//
+// This class is only for testing Google Test's own constructs. Do not
+// use it in user tests, either directly or indirectly.
+class Notification {
+ public:
+  Notification() : notified_(false) {
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL));
+  }
+  ~Notification() {
+    pthread_mutex_destroy(&mutex_);
+  }
+
+  // Notifies all threads created with this notification to start. Must
+  // be called from the controller thread.
+  void Notify() {
+    pthread_mutex_lock(&mutex_);
+    notified_ = true;
+    pthread_mutex_unlock(&mutex_);
+  }
+
+  // Blocks until the controller thread notifies. Must be called from a test
+  // thread.
+  void WaitForNotification() {
+    for (;;) {
+      pthread_mutex_lock(&mutex_);
+      const bool notified = notified_;
+      pthread_mutex_unlock(&mutex_);
+      if (notified)
+        break;
+      SleepMilliseconds(10);
+    }
+  }
+
+ private:
+  pthread_mutex_t mutex_;
+  bool notified_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification);
+};
+
+# elif GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT
+
+GTEST_API_ void SleepMilliseconds(int n);
+
+// Provides leak-safe Windows kernel handle ownership.
+// Used in death tests and in threading support.
+class GTEST_API_ AutoHandle {
+ public:
+  // Assume that Win32 HANDLE type is equivalent to void*. Doing so allows us to
+  // avoid including <windows.h> in this header file. Including <windows.h> is
+  // undesirable because it defines a lot of symbols and macros that tend to
+  // conflict with client code. This assumption is verified by
+  // WindowsTypesTest.HANDLEIsVoidStar.
+  typedef void* Handle;
+  AutoHandle();
+  explicit AutoHandle(Handle handle);
+
+  ~AutoHandle();
+
+  Handle Get() const;
+  void Reset();
+  void Reset(Handle handle);
+
+ private:
+  // Returns true iff the handle is a valid handle object that can be closed.
+  bool IsCloseable() const;
+
+  Handle handle_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(AutoHandle);
+};
+
+// Allows a controller thread to pause execution of newly created
+// threads until notified.  Instances of this class must be created
+// and destroyed in the controller thread.
+//
+// This class is only for testing Google Test's own constructs. Do not
+// use it in user tests, either directly or indirectly.
+class GTEST_API_ Notification {
+ public:
+  Notification();
+  void Notify();
+  void WaitForNotification();
+
+ private:
+  AutoHandle event_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification);
+};
+# endif  // GTEST_HAS_NOTIFICATION_
+
+// On MinGW, we can have both GTEST_OS_WINDOWS and GTEST_HAS_PTHREAD
+// defined, but we don't want to use MinGW's pthreads implementation, which
+// has conformance problems with some versions of the POSIX standard.
+# if GTEST_HAS_PTHREAD && !GTEST_OS_WINDOWS_MINGW
+
+// As a C-function, ThreadFuncWithCLinkage cannot be templated itself.
+// Consequently, it cannot select a correct instantiation of ThreadWithParam
+// in order to call its Run(). Introducing ThreadWithParamBase as a
+// non-templated base class for ThreadWithParam allows us to bypass this
+// problem.
+class ThreadWithParamBase {
+ public:
+  virtual ~ThreadWithParamBase() {}
+  virtual void Run() = 0;
+};
+
+// pthread_create() accepts a pointer to a function type with the C linkage.
+// According to the Standard (7.5/1), function types with different linkages
+// are different even if they are otherwise identical.  Some compilers (for
+// example, SunStudio) treat them as different types.  Since class methods
+// cannot be defined with C-linkage we need to define a free C-function to
+// pass into pthread_create().
+extern "C" inline void* ThreadFuncWithCLinkage(void* thread) {
+  static_cast<ThreadWithParamBase*>(thread)->Run();
+  return NULL;
+}
+
+// Helper class for testing Google Test's multi-threading constructs.
+// To use it, write:
+//
+//   void ThreadFunc(int param) { /* Do things with param */ }
+//   Notification thread_can_start;
+//   ...
+//   // The thread_can_start parameter is optional; you can supply NULL.
+//   ThreadWithParam<int> thread(&ThreadFunc, 5, &thread_can_start);
+//   thread_can_start.Notify();
+//
+// These classes are only for testing Google Test's own constructs. Do
+// not use them in user tests, either directly or indirectly.
+template <typename T>
+class ThreadWithParam : public ThreadWithParamBase {
+ public:
+  typedef void UserThreadFunc(T);
+
+  ThreadWithParam(UserThreadFunc* func, T param, Notification* thread_can_start)
+      : func_(func),
+        param_(param),
+        thread_can_start_(thread_can_start),
+        finished_(false) {
+    ThreadWithParamBase* const base = this;
+    // The thread can be created only after all fields except thread_
+    // have been initialized.
+    GTEST_CHECK_POSIX_SUCCESS_(
+        pthread_create(&thread_, 0, &ThreadFuncWithCLinkage, base));
+  }
+  ~ThreadWithParam() { Join(); }
+
+  void Join() {
+    if (!finished_) {
+      GTEST_CHECK_POSIX_SUCCESS_(pthread_join(thread_, 0));
+      finished_ = true;
+    }
+  }
+
+  virtual void Run() {
+    if (thread_can_start_ != NULL)
+      thread_can_start_->WaitForNotification();
+    func_(param_);
+  }
+
+ private:
+  UserThreadFunc* const func_;  // User-supplied thread function.
+  const T param_;  // User-supplied parameter to the thread function.
+  // When non-NULL, used to block execution until the controller thread
+  // notifies.
+  Notification* const thread_can_start_;
+  bool finished_;  // true iff we know that the thread function has finished.
+  pthread_t thread_;  // The native thread object.
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam);
+};
+# endif  // !GTEST_OS_WINDOWS && GTEST_HAS_PTHREAD ||
+         // GTEST_HAS_MUTEX_AND_THREAD_LOCAL_
+
+# if GTEST_HAS_MUTEX_AND_THREAD_LOCAL_
+// Mutex and ThreadLocal have already been imported into the namespace.
+// Nothing to do here.
+
+# elif GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT
+
+// Mutex implements mutex on Windows platforms.  It is used in conjunction
+// with class MutexLock:
+//
+//   Mutex mutex;
+//   ...
+//   MutexLock lock(&mutex);  // Acquires the mutex and releases it at the
+//                            // end of the current scope.
+//
+// A static Mutex *must* be defined or declared using one of the following
+// macros:
+//   GTEST_DEFINE_STATIC_MUTEX_(g_some_mutex);
+//   GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex);
+//
+// (A non-static Mutex is defined/declared in the usual way).
+class GTEST_API_ Mutex {
+ public:
+  enum MutexType { kStatic = 0, kDynamic = 1 };
+  // We rely on kStaticMutex being 0 as it is to what the linker initializes
+  // type_ in static mutexes.  critical_section_ will be initialized lazily
+  // in ThreadSafeLazyInit().
+  enum StaticConstructorSelector { kStaticMutex = 0 };
+
+  // This constructor intentionally does nothing.  It relies on type_ being
+  // statically initialized to 0 (effectively setting it to kStatic) and on
+  // ThreadSafeLazyInit() to lazily initialize the rest of the members.
+  explicit Mutex(StaticConstructorSelector /*dummy*/) {}
+
+  Mutex();
+  ~Mutex();
+
+  void Lock();
+
+  void Unlock();
+
+  // Does nothing if the current thread holds the mutex. Otherwise, crashes
+  // with high probability.
+  void AssertHeld();
+
+ private:
+  // Initializes owner_thread_id_ and critical_section_ in static mutexes.
+  void ThreadSafeLazyInit();
+
+  // Per http://blogs.msdn.com/b/oldnewthing/archive/2004/02/23/78395.aspx,
+  // we assume that 0 is an invalid value for thread IDs.
+  unsigned int owner_thread_id_;
+
+  // For static mutexes, we rely on these members being initialized to zeros
+  // by the linker.
+  MutexType type_;
+  long critical_section_init_phase_;  // NOLINT
+  _RTL_CRITICAL_SECTION* critical_section_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex);
+};
+
+# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+    extern ::testing::internal::Mutex mutex
+
+# define GTEST_DEFINE_STATIC_MUTEX_(mutex) \
+    ::testing::internal::Mutex mutex(::testing::internal::Mutex::kStaticMutex)
+
+// We cannot name this class MutexLock because the ctor declaration would
+// conflict with a macro named MutexLock, which is defined on some
+// platforms. That macro is used as a defensive measure to prevent against
+// inadvertent misuses of MutexLock like "MutexLock(&mu)" rather than
+// "MutexLock l(&mu)".  Hence the typedef trick below.
+class GTestMutexLock {
+ public:
+  explicit GTestMutexLock(Mutex* mutex)
+      : mutex_(mutex) { mutex_->Lock(); }
+
+  ~GTestMutexLock() { mutex_->Unlock(); }
+
+ private:
+  Mutex* const mutex_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestMutexLock);
+};
+
+typedef GTestMutexLock MutexLock;
+
+// Base class for ValueHolder<T>.  Allows a caller to hold and delete a value
+// without knowing its type.
+class ThreadLocalValueHolderBase {
+ public:
+  virtual ~ThreadLocalValueHolderBase() {}
+};
+
+// Provides a way for a thread to send notifications to a ThreadLocal
+// regardless of its parameter type.
+class ThreadLocalBase {
+ public:
+  // Creates a new ValueHolder<T> object holding a default value passed to
+  // this ThreadLocal<T>'s constructor and returns it.  It is the caller's
+  // responsibility not to call this when the ThreadLocal<T> instance already
+  // has a value on the current thread.
+  virtual ThreadLocalValueHolderBase* NewValueForCurrentThread() const = 0;
+
+ protected:
+  ThreadLocalBase() {}
+  virtual ~ThreadLocalBase() {}
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocalBase);
+};
+
+// Maps a thread to a set of ThreadLocals that have values instantiated on that
+// thread and notifies them when the thread exits.  A ThreadLocal instance is
+// expected to persist until all threads it has values on have terminated.
+class GTEST_API_ ThreadLocalRegistry {
+ public:
+  // Registers thread_local_instance as having value on the current thread.
+  // Returns a value that can be used to identify the thread from other threads.
+  static ThreadLocalValueHolderBase* GetValueOnCurrentThread(
+      const ThreadLocalBase* thread_local_instance);
+
+  // Invoked when a ThreadLocal instance is destroyed.
+  static void OnThreadLocalDestroyed(
+      const ThreadLocalBase* thread_local_instance);
+};
+
+class GTEST_API_ ThreadWithParamBase {
+ public:
+  void Join();
+
+ protected:
+  class Runnable {
+   public:
+    virtual ~Runnable() {}
+    virtual void Run() = 0;
+  };
+
+  ThreadWithParamBase(Runnable *runnable, Notification* thread_can_start);
+  virtual ~ThreadWithParamBase();
+
+ private:
+  AutoHandle thread_;
+};
+
+// Helper class for testing Google Test's multi-threading constructs.
+template <typename T>
+class ThreadWithParam : public ThreadWithParamBase {
+ public:
+  typedef void UserThreadFunc(T);
+
+  ThreadWithParam(UserThreadFunc* func, T param, Notification* thread_can_start)
+      : ThreadWithParamBase(new RunnableImpl(func, param), thread_can_start) {
+  }
+  virtual ~ThreadWithParam() {}
+
+ private:
+  class RunnableImpl : public Runnable {
+   public:
+    RunnableImpl(UserThreadFunc* func, T param)
+        : func_(func),
+          param_(param) {
+    }
+    virtual ~RunnableImpl() {}
+    virtual void Run() {
+      func_(param_);
+    }
+
+   private:
+    UserThreadFunc* const func_;
+    const T param_;
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(RunnableImpl);
+  };
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam);
+};
+
+// Implements thread-local storage on Windows systems.
+//
+//   // Thread 1
+//   ThreadLocal<int> tl(100);  // 100 is the default value for each thread.
+//
+//   // Thread 2
+//   tl.set(150);  // Changes the value for thread 2 only.
+//   EXPECT_EQ(150, tl.get());
+//
+//   // Thread 1
+//   EXPECT_EQ(100, tl.get());  // In thread 1, tl has the original value.
+//   tl.set(200);
+//   EXPECT_EQ(200, tl.get());
+//
+// The template type argument T must have a public copy constructor.
+// In addition, the default ThreadLocal constructor requires T to have
+// a public default constructor.
+//
+// The users of a TheadLocal instance have to make sure that all but one
+// threads (including the main one) using that instance have exited before
+// destroying it. Otherwise, the per-thread objects managed for them by the
+// ThreadLocal instance are not guaranteed to be destroyed on all platforms.
+//
+// Google Test only uses global ThreadLocal objects.  That means they
+// will die after main() has returned.  Therefore, no per-thread
+// object managed by Google Test will be leaked as long as all threads
+// using Google Test have exited when main() returns.
+template <typename T>
+class ThreadLocal : public ThreadLocalBase {
+ public:
+  ThreadLocal() : default_factory_(new DefaultValueHolderFactory()) {}
+  explicit ThreadLocal(const T& value)
+      : default_factory_(new InstanceValueHolderFactory(value)) {}
+
+  ~ThreadLocal() { ThreadLocalRegistry::OnThreadLocalDestroyed(this); }
+
+  T* pointer() { return GetOrCreateValue(); }
+  const T* pointer() const { return GetOrCreateValue(); }
+  const T& get() const { return *pointer(); }
+  void set(const T& value) { *pointer() = value; }
+
+ private:
+  // Holds a value of T.  Can be deleted via its base class without the caller
+  // knowing the type of T.
+  class ValueHolder : public ThreadLocalValueHolderBase {
+   public:
+    ValueHolder() : value_() {}
+    explicit ValueHolder(const T& value) : value_(value) {}
+
+    T* pointer() { return &value_; }
+
+   private:
+    T value_;
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolder);
+  };
+
+
+  T* GetOrCreateValue() const {
+    return static_cast<ValueHolder*>(
+        ThreadLocalRegistry::GetValueOnCurrentThread(this))->pointer();
+  }
+
+  virtual ThreadLocalValueHolderBase* NewValueForCurrentThread() const {
+    return default_factory_->MakeNewHolder();
+  }
+
+  class ValueHolderFactory {
+   public:
+    ValueHolderFactory() {}
+    virtual ~ValueHolderFactory() {}
+    virtual ValueHolder* MakeNewHolder() const = 0;
+
+   private:
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolderFactory);
+  };
+
+  class DefaultValueHolderFactory : public ValueHolderFactory {
+   public:
+    DefaultValueHolderFactory() {}
+    virtual ValueHolder* MakeNewHolder() const { return new ValueHolder(); }
+
+   private:
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultValueHolderFactory);
+  };
+
+  class InstanceValueHolderFactory : public ValueHolderFactory {
+   public:
+    explicit InstanceValueHolderFactory(const T& value) : value_(value) {}
+    virtual ValueHolder* MakeNewHolder() const {
+      return new ValueHolder(value_);
+    }
+
+   private:
+    const T value_;  // The value for each thread.
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(InstanceValueHolderFactory);
+  };
+
+  scoped_ptr<ValueHolderFactory> default_factory_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal);
+};
+
+# elif GTEST_HAS_PTHREAD
+
+// MutexBase and Mutex implement mutex on pthreads-based platforms.
+class MutexBase {
+ public:
+  // Acquires this mutex.
+  void Lock() {
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_));
+    owner_ = pthread_self();
+    has_owner_ = true;
+  }
+
+  // Releases this mutex.
+  void Unlock() {
+    // Since the lock is being released the owner_ field should no longer be
+    // considered valid. We don't protect writing to has_owner_ here, as it's
+    // the caller's responsibility to ensure that the current thread holds the
+    // mutex when this is called.
+    has_owner_ = false;
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&mutex_));
+  }
+
+  // Does nothing if the current thread holds the mutex. Otherwise, crashes
+  // with high probability.
+  void AssertHeld() const {
+    GTEST_CHECK_(has_owner_ && pthread_equal(owner_, pthread_self()))
+        << "The current thread is not holding the mutex @" << this;
+  }
+
+  // A static mutex may be used before main() is entered.  It may even
+  // be used before the dynamic initialization stage.  Therefore we
+  // must be able to initialize a static mutex object at link time.
+  // This means MutexBase has to be a POD and its member variables
+  // have to be public.
+ public:
+  pthread_mutex_t mutex_;  // The underlying pthread mutex.
+  // has_owner_ indicates whether the owner_ field below contains a valid thread
+  // ID and is therefore safe to inspect (e.g., to use in pthread_equal()). All
+  // accesses to the owner_ field should be protected by a check of this field.
+  // An alternative might be to memset() owner_ to all zeros, but there's no
+  // guarantee that a zero'd pthread_t is necessarily invalid or even different
+  // from pthread_self().
+  bool has_owner_;
+  pthread_t owner_;  // The thread holding the mutex.
+};
+
+// Forward-declares a static mutex.
+#  define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+     extern ::testing::internal::MutexBase mutex
+
+// Defines and statically (i.e. at link time) initializes a static mutex.
+// The initialization list here does not explicitly initialize each field,
+// instead relying on default initialization for the unspecified fields. In
+// particular, the owner_ field (a pthread_t) is not explicitly initialized.
+// This allows initialization to work whether pthread_t is a scalar or struct.
+// The flag -Wmissing-field-initializers must not be specified for this to work.
+#  define GTEST_DEFINE_STATIC_MUTEX_(mutex) \
+     ::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, false }
+
+// The Mutex class can only be used for mutexes created at runtime. It
+// shares its API with MutexBase otherwise.
+class Mutex : public MutexBase {
+ public:
+  Mutex() {
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL));
+    has_owner_ = false;
+  }
+  ~Mutex() {
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&mutex_));
+  }
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex);
+};
+
+// We cannot name this class MutexLock because the ctor declaration would
+// conflict with a macro named MutexLock, which is defined on some
+// platforms. That macro is used as a defensive measure to prevent against
+// inadvertent misuses of MutexLock like "MutexLock(&mu)" rather than
+// "MutexLock l(&mu)".  Hence the typedef trick below.
+class GTestMutexLock {
+ public:
+  explicit GTestMutexLock(MutexBase* mutex)
+      : mutex_(mutex) { mutex_->Lock(); }
+
+  ~GTestMutexLock() { mutex_->Unlock(); }
+
+ private:
+  MutexBase* const mutex_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestMutexLock);
+};
+
+typedef GTestMutexLock MutexLock;
+
+// Helpers for ThreadLocal.
+
+// pthread_key_create() requires DeleteThreadLocalValue() to have
+// C-linkage.  Therefore it cannot be templatized to access
+// ThreadLocal<T>.  Hence the need for class
+// ThreadLocalValueHolderBase.
+class ThreadLocalValueHolderBase {
+ public:
+  virtual ~ThreadLocalValueHolderBase() {}
+};
+
+// Called by pthread to delete thread-local data stored by
+// pthread_setspecific().
+extern "C" inline void DeleteThreadLocalValue(void* value_holder) {
+  delete static_cast<ThreadLocalValueHolderBase*>(value_holder);
+}
+
+// Implements thread-local storage on pthreads-based systems.
+template <typename T>
+class ThreadLocal {
+ public:
+  ThreadLocal()
+      : key_(CreateKey()), default_factory_(new DefaultValueHolderFactory()) {}
+  explicit ThreadLocal(const T& value)
+      : key_(CreateKey()),
+        default_factory_(new InstanceValueHolderFactory(value)) {}
+
+  ~ThreadLocal() {
+    // Destroys the managed object for the current thread, if any.
+    DeleteThreadLocalValue(pthread_getspecific(key_));
+
+    // Releases resources associated with the key.  This will *not*
+    // delete managed objects for other threads.
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_key_delete(key_));
+  }
+
+  T* pointer() { return GetOrCreateValue(); }
+  const T* pointer() const { return GetOrCreateValue(); }
+  const T& get() const { return *pointer(); }
+  void set(const T& value) { *pointer() = value; }
+
+ private:
+  // Holds a value of type T.
+  class ValueHolder : public ThreadLocalValueHolderBase {
+   public:
+    ValueHolder() : value_() {}
+    explicit ValueHolder(const T& value) : value_(value) {}
+
+    T* pointer() { return &value_; }
+
+   private:
+    T value_;
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolder);
+  };
+
+  static pthread_key_t CreateKey() {
+    pthread_key_t key;
+    // When a thread exits, DeleteThreadLocalValue() will be called on
+    // the object managed for that thread.
+    GTEST_CHECK_POSIX_SUCCESS_(
+        pthread_key_create(&key, &DeleteThreadLocalValue));
+    return key;
+  }
+
+  T* GetOrCreateValue() const {
+    ThreadLocalValueHolderBase* const holder =
+        static_cast<ThreadLocalValueHolderBase*>(pthread_getspecific(key_));
+    if (holder != NULL) {
+      return CheckedDowncastToActualType<ValueHolder>(holder)->pointer();
+    }
+
+    ValueHolder* const new_holder = default_factory_->MakeNewHolder();
+    ThreadLocalValueHolderBase* const holder_base = new_holder;
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_setspecific(key_, holder_base));
+    return new_holder->pointer();
+  }
+
+  class ValueHolderFactory {
+   public:
+    ValueHolderFactory() {}
+    virtual ~ValueHolderFactory() {}
+    virtual ValueHolder* MakeNewHolder() const = 0;
+
+   private:
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolderFactory);
+  };
+
+  class DefaultValueHolderFactory : public ValueHolderFactory {
+   public:
+    DefaultValueHolderFactory() {}
+    virtual ValueHolder* MakeNewHolder() const { return new ValueHolder(); }
+
+   private:
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultValueHolderFactory);
+  };
+
+  class InstanceValueHolderFactory : public ValueHolderFactory {
+   public:
+    explicit InstanceValueHolderFactory(const T& value) : value_(value) {}
+    virtual ValueHolder* MakeNewHolder() const {
+      return new ValueHolder(value_);
+    }
+
+   private:
+    const T value_;  // The value for each thread.
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(InstanceValueHolderFactory);
+  };
+
+  // A key pthreads uses for looking up per-thread values.
+  const pthread_key_t key_;
+  scoped_ptr<ValueHolderFactory> default_factory_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal);
+};
+
+# endif  // GTEST_HAS_MUTEX_AND_THREAD_LOCAL_
+
+#else  // GTEST_IS_THREADSAFE
+
+// A dummy implementation of synchronization primitives (mutex, lock,
+// and thread-local variable).  Necessary for compiling Google Test where
+// mutex is not supported - using Google Test in multiple threads is not
+// supported on such platforms.
+
+class Mutex {
+ public:
+  Mutex() {}
+  void Lock() {}
+  void Unlock() {}
+  void AssertHeld() const {}
+};
+
+# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+  extern ::testing::internal::Mutex mutex
+
+# define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex
+
+// We cannot name this class MutexLock because the ctor declaration would
+// conflict with a macro named MutexLock, which is defined on some
+// platforms. That macro is used as a defensive measure to prevent against
+// inadvertent misuses of MutexLock like "MutexLock(&mu)" rather than
+// "MutexLock l(&mu)".  Hence the typedef trick below.
+class GTestMutexLock {
+ public:
+  explicit GTestMutexLock(Mutex*) {}  // NOLINT
+};
+
+typedef GTestMutexLock MutexLock;
+
+template <typename T>
+class ThreadLocal {
+ public:
+  ThreadLocal() : value_() {}
+  explicit ThreadLocal(const T& value) : value_(value) {}
+  T* pointer() { return &value_; }
+  const T* pointer() const { return &value_; }
+  const T& get() const { return value_; }
+  void set(const T& value) { value_ = value; }
+ private:
+  T value_;
+};
+
+#endif  // GTEST_IS_THREADSAFE
+
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+GTEST_API_ size_t GetThreadCount();
+
+// Passing non-POD classes through ellipsis (...) crashes the ARM
+// compiler and generates a warning in Sun Studio.  The Nokia Symbian
+// and the IBM XL C/C++ compiler try to instantiate a copy constructor
+// for objects passed through ellipsis (...), failing for uncopyable
+// objects.  We define this to ensure that only POD is passed through
+// ellipsis on these systems.
+#if defined(__SYMBIAN32__) || defined(__IBMCPP__) || defined(__SUNPRO_CC)
+// We lose support for NULL detection where the compiler doesn't like
+// passing non-POD classes through ellipsis (...).
+# define GTEST_ELLIPSIS_NEEDS_POD_ 1
+#else
+# define GTEST_CAN_COMPARE_NULL 1
+#endif
+
+// The Nokia Symbian and IBM XL C/C++ compilers cannot decide between
+// const T& and const T* in a function template.  These compilers
+// _can_ decide between class template specializations for T and T*,
+// so a tr1::type_traits-like is_pointer works.
+#if defined(__SYMBIAN32__) || defined(__IBMCPP__)
+# define GTEST_NEEDS_IS_POINTER_ 1
+#endif
+
+template <bool bool_value>
+struct bool_constant {
+  typedef bool_constant<bool_value> type;
+  static const bool value = bool_value;
+};
+template <bool bool_value> const bool bool_constant<bool_value>::value;
+
+typedef bool_constant<false> false_type;
+typedef bool_constant<true> true_type;
+
+template <typename T>
+struct is_pointer : public false_type {};
+
+template <typename T>
+struct is_pointer<T*> : public true_type {};
+
+template <typename Iterator>
+struct IteratorTraits {
+  typedef typename Iterator::value_type value_type;
+};
+
+template <typename T>
+struct IteratorTraits<T*> {
+  typedef T value_type;
+};
+
+template <typename T>
+struct IteratorTraits<const T*> {
+  typedef T value_type;
+};
+
+#if GTEST_OS_WINDOWS
+# define GTEST_PATH_SEP_ "\\"
+# define GTEST_HAS_ALT_PATH_SEP_ 1
+// The biggest signed integer type the compiler supports.
+typedef __int64 BiggestInt;
+#else
+# define GTEST_PATH_SEP_ "/"
+# define GTEST_HAS_ALT_PATH_SEP_ 0
+typedef long long BiggestInt;  // NOLINT
+#endif  // GTEST_OS_WINDOWS
+
+// Utilities for char.
+
+// isspace(int ch) and friends accept an unsigned char or EOF.  char
+// may be signed, depending on the compiler (or compiler flags).
+// Therefore we need to cast a char to unsigned char before calling
+// isspace(), etc.
+
+inline bool IsAlpha(char ch) {
+  return isalpha(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsAlNum(char ch) {
+  return isalnum(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsDigit(char ch) {
+  return isdigit(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsLower(char ch) {
+  return islower(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsSpace(char ch) {
+  return isspace(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsUpper(char ch) {
+  return isupper(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsXDigit(char ch) {
+  return isxdigit(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsXDigit(wchar_t ch) {
+  const unsigned char low_byte = static_cast<unsigned char>(ch);
+  return ch == low_byte && isxdigit(low_byte) != 0;
+}
+
+inline char ToLower(char ch) {
+  return static_cast<char>(tolower(static_cast<unsigned char>(ch)));
+}
+inline char ToUpper(char ch) {
+  return static_cast<char>(toupper(static_cast<unsigned char>(ch)));
+}
+
+inline std::string StripTrailingSpaces(std::string str) {
+  std::string::iterator it = str.end();
+  while (it != str.begin() && IsSpace(*--it))
+    it = str.erase(it);
+  return str;
+}
+
+// The testing::internal::posix namespace holds wrappers for common
+// POSIX functions.  These wrappers hide the differences between
+// Windows/MSVC and POSIX systems.  Since some compilers define these
+// standard functions as macros, the wrapper cannot have the same name
+// as the wrapped function.
+
+namespace posix {
+
+// Functions with a different name on Windows.
+
+#if GTEST_OS_WINDOWS
+
+typedef struct _stat StatStruct;
+
+# ifdef __BORLANDC__
+inline int IsATTY(int fd) { return isatty(fd); }
+inline int StrCaseCmp(const char* s1, const char* s2) {
+  return stricmp(s1, s2);
+}
+inline char* StrDup(const char* src) { return strdup(src); }
+# else  // !__BORLANDC__
+#  if GTEST_OS_WINDOWS_MOBILE
+inline int IsATTY(int /* fd */) { return 0; }
+#  else
+inline int IsATTY(int fd) { return _isatty(fd); }
+#  endif  // GTEST_OS_WINDOWS_MOBILE
+inline int StrCaseCmp(const char* s1, const char* s2) {
+  return _stricmp(s1, s2);
+}
+inline char* StrDup(const char* src) { return _strdup(src); }
+# endif  // __BORLANDC__
+
+# if GTEST_OS_WINDOWS_MOBILE
+inline int FileNo(FILE* file) { return reinterpret_cast<int>(_fileno(file)); }
+// Stat(), RmDir(), and IsDir() are not needed on Windows CE at this
+// time and thus not defined there.
+# else
+inline int FileNo(FILE* file) { return _fileno(file); }
+inline int Stat(const char* path, StatStruct* buf) { return _stat(path, buf); }
+inline int RmDir(const char* dir) { return _rmdir(dir); }
+inline bool IsDir(const StatStruct& st) {
+  return (_S_IFDIR & st.st_mode) != 0;
+}
+# endif  // GTEST_OS_WINDOWS_MOBILE
+
+#else
+
+typedef struct stat StatStruct;
+
+inline int FileNo(FILE* file) { return fileno(file); }
+inline int IsATTY(int fd) { return isatty(fd); }
+inline int Stat(const char* path, StatStruct* buf) { return stat(path, buf); }
+inline int StrCaseCmp(const char* s1, const char* s2) {
+  return strcasecmp(s1, s2);
+}
+inline char* StrDup(const char* src) { return strdup(src); }
+inline int RmDir(const char* dir) { return rmdir(dir); }
+inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); }
+
+#endif  // GTEST_OS_WINDOWS
+
+// Functions deprecated by MSVC 8.0.
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996 /* deprecated function */)
+
+inline const char* StrNCpy(char* dest, const char* src, size_t n) {
+  return strncpy(dest, src, n);
+}
+
+// ChDir(), FReopen(), FDOpen(), Read(), Write(), Close(), and
+// StrError() aren't needed on Windows CE at this time and thus not
+// defined there.
+
+#if !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT
+inline int ChDir(const char* dir) { return chdir(dir); }
+#endif
+inline FILE* FOpen(const char* path, const char* mode) {
+  return fopen(path, mode);
+}
+#if !GTEST_OS_WINDOWS_MOBILE
+inline FILE *FReopen(const char* path, const char* mode, FILE* stream) {
+  return freopen(path, mode, stream);
+}
+inline FILE* FDOpen(int fd, const char* mode) { return fdopen(fd, mode); }
+#endif
+inline int FClose(FILE* fp) { return fclose(fp); }
+#if !GTEST_OS_WINDOWS_MOBILE
+inline int Read(int fd, void* buf, unsigned int count) {
+  return static_cast<int>(read(fd, buf, count));
+}
+inline int Write(int fd, const void* buf, unsigned int count) {
+  return static_cast<int>(write(fd, buf, count));
+}
+inline int Close(int fd) { return close(fd); }
+inline const char* StrError(int errnum) { return strerror(errnum); }
+#endif
+inline const char* GetEnv(const char* name) {
+#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE | GTEST_OS_WINDOWS_RT
+  // We are on Windows CE, which has no environment variables.
+  static_cast<void>(name);  // To prevent 'unused argument' warning.
+  return NULL;
+#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9)
+  // Environment variables which we programmatically clear will be set to the
+  // empty string rather than unset (NULL).  Handle that case.
+  const char* const env = getenv(name);
+  return (env != NULL && env[0] != '\0') ? env : NULL;
+#else
+  return getenv(name);
+#endif
+}
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()
+
+#if GTEST_OS_WINDOWS_MOBILE
+// Windows CE has no C library. The abort() function is used in
+// several places in Google Test. This implementation provides a reasonable
+// imitation of standard behaviour.
+void Abort();
+#else
+inline void Abort() { abort(); }
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+}  // namespace posix
+
+// MSVC "deprecates" snprintf and issues warnings wherever it is used.  In
+// order to avoid these warnings, we need to use _snprintf or _snprintf_s on
+// MSVC-based platforms.  We map the GTEST_SNPRINTF_ macro to the appropriate
+// function in order to achieve that.  We use macro definition here because
+// snprintf is a variadic function.
+#if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE
+// MSVC 2005 and above support variadic macros.
+# define GTEST_SNPRINTF_(buffer, size, format, ...) \
+     _snprintf_s(buffer, size, size, format, __VA_ARGS__)
+#elif defined(_MSC_VER)
+// Windows CE does not define _snprintf_s and MSVC prior to 2005 doesn't
+// complain about _snprintf.
+# define GTEST_SNPRINTF_ _snprintf
+#else
+# define GTEST_SNPRINTF_ snprintf
+#endif
+
+// The maximum number a BiggestInt can represent.  This definition
+// works no matter BiggestInt is represented in one's complement or
+// two's complement.
+//
+// We cannot rely on numeric_limits in STL, as __int64 and long long
+// are not part of standard C++ and numeric_limits doesn't need to be
+// defined for them.
+const BiggestInt kMaxBiggestInt =
+    ~(static_cast<BiggestInt>(1) << (8*sizeof(BiggestInt) - 1));
+
+// This template class serves as a compile-time function from size to
+// type.  It maps a size in bytes to a primitive type with that
+// size. e.g.
+//
+//   TypeWithSize<4>::UInt
+//
+// is typedef-ed to be unsigned int (unsigned integer made up of 4
+// bytes).
+//
+// Such functionality should belong to STL, but I cannot find it
+// there.
+//
+// Google Test uses this class in the implementation of floating-point
+// comparison.
+//
+// For now it only handles UInt (unsigned int) as that's all Google Test
+// needs.  Other types can be easily added in the future if need
+// arises.
+template <size_t size>
+class TypeWithSize {
+ public:
+  // This prevents the user from using TypeWithSize<N> with incorrect
+  // values of N.
+  typedef void UInt;
+};
+
+// The specialization for size 4.
+template <>
+class TypeWithSize<4> {
+ public:
+  // unsigned int has size 4 in both gcc and MSVC.
+  //
+  // As base/basictypes.h doesn't compile on Windows, we cannot use
+  // uint32, uint64, and etc here.
+  typedef int Int;
+  typedef unsigned int UInt;
+};
+
+// The specialization for size 8.
+template <>
+class TypeWithSize<8> {
+ public:
+#if GTEST_OS_WINDOWS
+  typedef __int64 Int;
+  typedef unsigned __int64 UInt;
+#else
+  typedef long long Int;  // NOLINT
+  typedef unsigned long long UInt;  // NOLINT
+#endif  // GTEST_OS_WINDOWS
+};
+
+// Integer types of known sizes.
+typedef TypeWithSize<4>::Int Int32;
+typedef TypeWithSize<4>::UInt UInt32;
+typedef TypeWithSize<8>::Int Int64;
+typedef TypeWithSize<8>::UInt UInt64;
+typedef TypeWithSize<8>::Int TimeInMillis;  // Represents time in milliseconds.
+
+// Utilities for command line flags and environment variables.
+
+// Macro for referencing flags.
+#if !defined(GTEST_FLAG)
+# define GTEST_FLAG(name) FLAGS_gtest_##name
+#endif  // !defined(GTEST_FLAG)
+
+#if !defined(GTEST_USE_OWN_FLAGFILE_FLAG_)
+# define GTEST_USE_OWN_FLAGFILE_FLAG_ 1
+#endif  // !defined(GTEST_USE_OWN_FLAGFILE_FLAG_)
+
+#if !defined(GTEST_DECLARE_bool_)
+# define GTEST_FLAG_SAVER_ ::testing::internal::GTestFlagSaver
+
+// Macros for declaring flags.
+# define GTEST_DECLARE_bool_(name) GTEST_API_ extern bool GTEST_FLAG(name)
+# define GTEST_DECLARE_int32_(name) \
+    GTEST_API_ extern ::testing::internal::Int32 GTEST_FLAG(name)
+#define GTEST_DECLARE_string_(name) \
+    GTEST_API_ extern ::std::string GTEST_FLAG(name)
+
+// Macros for defining flags.
+#define GTEST_DEFINE_bool_(name, default_val, doc) \
+    GTEST_API_ bool GTEST_FLAG(name) = (default_val)
+#define GTEST_DEFINE_int32_(name, default_val, doc) \
+    GTEST_API_ ::testing::internal::Int32 GTEST_FLAG(name) = (default_val)
+#define GTEST_DEFINE_string_(name, default_val, doc) \
+    GTEST_API_ ::std::string GTEST_FLAG(name) = (default_val)
+
+#endif  // !defined(GTEST_DECLARE_bool_)
+
+// Thread annotations
+#if !defined(GTEST_EXCLUSIVE_LOCK_REQUIRED_)
+# define GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks)
+# define GTEST_LOCK_EXCLUDED_(locks)
+#endif  // !defined(GTEST_EXCLUSIVE_LOCK_REQUIRED_)
+
+// Parses 'str' for a 32-bit signed integer.  If successful, writes the result
+// to *value and returns true; otherwise leaves *value unchanged and returns
+// false.
+// TODO(chandlerc): Find a better way to refactor flag and environment parsing
+// out of both gtest-port.cc and gtest.cc to avoid exporting this utility
+// function.
+bool ParseInt32(const Message& src_text, const char* str, Int32* value);
+
+// Parses a bool/Int32/string from the environment variable
+// corresponding to the given Google Test flag.
+bool BoolFromGTestEnv(const char* flag, bool default_val);
+GTEST_API_ Int32 Int32FromGTestEnv(const char* flag, Int32 default_val);
+const char* StringFromGTestEnv(const char* flag, const char* default_val);
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
+
diff --git a/third_party/googletest/googletest/include/gtest/internal/gtest-string.h b/third_party/googletest/googletest/include/gtest/internal/gtest-string.h
new file mode 100644
index 0000000..97f1a7f
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/internal/gtest-string.h
@@ -0,0 +1,167 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file declares the String class and functions used internally by
+// Google Test.  They are subject to change without notice. They should not used
+// by code external to Google Test.
+//
+// This header file is #included by <gtest/internal/gtest-internal.h>.
+// It should not be #included by other files.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
+
+#ifdef __BORLANDC__
+// string.h is not guaranteed to provide strcpy on C++ Builder.
+# include <mem.h>
+#endif
+
+#include <string.h>
+#include <string>
+
+#include "gtest/internal/gtest-port.h"
+
+namespace testing {
+namespace internal {
+
+// String - an abstract class holding static string utilities.
+class GTEST_API_ String {
+ public:
+  // Static utility methods
+
+  // Clones a 0-terminated C string, allocating memory using new.  The
+  // caller is responsible for deleting the return value using
+  // delete[].  Returns the cloned string, or NULL if the input is
+  // NULL.
+  //
+  // This is different from strdup() in string.h, which allocates
+  // memory using malloc().
+  static const char* CloneCString(const char* c_str);
+
+#if GTEST_OS_WINDOWS_MOBILE
+  // Windows CE does not have the 'ANSI' versions of Win32 APIs. To be
+  // able to pass strings to Win32 APIs on CE we need to convert them
+  // to 'Unicode', UTF-16.
+
+  // Creates a UTF-16 wide string from the given ANSI string, allocating
+  // memory using new. The caller is responsible for deleting the return
+  // value using delete[]. Returns the wide string, or NULL if the
+  // input is NULL.
+  //
+  // The wide string is created using the ANSI codepage (CP_ACP) to
+  // match the behaviour of the ANSI versions of Win32 calls and the
+  // C runtime.
+  static LPCWSTR AnsiToUtf16(const char* c_str);
+
+  // Creates an ANSI string from the given wide string, allocating
+  // memory using new. The caller is responsible for deleting the return
+  // value using delete[]. Returns the ANSI string, or NULL if the
+  // input is NULL.
+  //
+  // The returned string is created using the ANSI codepage (CP_ACP) to
+  // match the behaviour of the ANSI versions of Win32 calls and the
+  // C runtime.
+  static const char* Utf16ToAnsi(LPCWSTR utf16_str);
+#endif
+
+  // Compares two C strings.  Returns true iff they have the same content.
+  //
+  // Unlike strcmp(), this function can handle NULL argument(s).  A
+  // NULL C string is considered different to any non-NULL C string,
+  // including the empty string.
+  static bool CStringEquals(const char* lhs, const char* rhs);
+
+  // Converts a wide C string to a String using the UTF-8 encoding.
+  // NULL will be converted to "(null)".  If an error occurred during
+  // the conversion, "(failed to convert from wide string)" is
+  // returned.
+  static std::string ShowWideCString(const wchar_t* wide_c_str);
+
+  // Compares two wide C strings.  Returns true iff they have the same
+  // content.
+  //
+  // Unlike wcscmp(), this function can handle NULL argument(s).  A
+  // NULL C string is considered different to any non-NULL C string,
+  // including the empty string.
+  static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs);
+
+  // Compares two C strings, ignoring case.  Returns true iff they
+  // have the same content.
+  //
+  // Unlike strcasecmp(), this function can handle NULL argument(s).
+  // A NULL C string is considered different to any non-NULL C string,
+  // including the empty string.
+  static bool CaseInsensitiveCStringEquals(const char* lhs,
+                                           const char* rhs);
+
+  // Compares two wide C strings, ignoring case.  Returns true iff they
+  // have the same content.
+  //
+  // Unlike wcscasecmp(), this function can handle NULL argument(s).
+  // A NULL C string is considered different to any non-NULL wide C string,
+  // including the empty string.
+  // NB: The implementations on different platforms slightly differ.
+  // On windows, this method uses _wcsicmp which compares according to LC_CTYPE
+  // environment variable. On GNU platform this method uses wcscasecmp
+  // which compares according to LC_CTYPE category of the current locale.
+  // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
+  // current locale.
+  static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
+                                               const wchar_t* rhs);
+
+  // Returns true iff the given string ends with the given suffix, ignoring
+  // case. Any string is considered to end with an empty suffix.
+  static bool EndsWithCaseInsensitive(
+      const std::string& str, const std::string& suffix);
+
+  // Formats an int value as "%02d".
+  static std::string FormatIntWidth2(int value);  // "%02d" for width == 2
+
+  // Formats an int value as "%X".
+  static std::string FormatHexInt(int value);
+
+  // Formats a byte as "%02X".
+  static std::string FormatByte(unsigned char value);
+
+ private:
+  String();  // Not meant to be instantiated.
+};  // class String
+
+// Gets the content of the stringstream's buffer as an std::string.  Each '\0'
+// character in the buffer is replaced with "\\0".
+GTEST_API_ std::string StringStreamToString(::std::stringstream* stream);
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
diff --git a/third_party/googletest/googletest/include/gtest/internal/gtest-tuple.h b/third_party/googletest/googletest/include/gtest/internal/gtest-tuple.h
new file mode 100644
index 0000000..e9b4053
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/internal/gtest-tuple.h
@@ -0,0 +1,1020 @@
+// This file was GENERATED by command:
+//     pump.py gtest-tuple.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2009 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Implements a subset of TR1 tuple needed by Google Test and Google Mock.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
+
+#include <utility>  // For ::std::pair.
+
+// The compiler used in Symbian has a bug that prevents us from declaring the
+// tuple template as a friend (it complains that tuple is redefined).  This
+// hack bypasses the bug by declaring the members that should otherwise be
+// private as public.
+// Sun Studio versions < 12 also have the above bug.
+#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
+#else
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
+    template <GTEST_10_TYPENAMES_(U)> friend class tuple; \
+   private:
+#endif
+
+// Visual Studio 2010, 2012, and 2013 define symbols in std::tr1 that conflict
+// with our own definitions. Therefore using our own tuple does not work on
+// those compilers.
+#if defined(_MSC_VER) && _MSC_VER >= 1600  /* 1600 is Visual Studio 2010 */
+# error "gtest's tuple doesn't compile on Visual Studio 2010 or later. \
+GTEST_USE_OWN_TR1_TUPLE must be set to 0 on those compilers."
+#endif
+
+// GTEST_n_TUPLE_(T) is the type of an n-tuple.
+#define GTEST_0_TUPLE_(T) tuple<>
+#define GTEST_1_TUPLE_(T) tuple<T##0, void, void, void, void, void, void, \
+    void, void, void>
+#define GTEST_2_TUPLE_(T) tuple<T##0, T##1, void, void, void, void, void, \
+    void, void, void>
+#define GTEST_3_TUPLE_(T) tuple<T##0, T##1, T##2, void, void, void, void, \
+    void, void, void>
+#define GTEST_4_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, void, void, void, \
+    void, void, void>
+#define GTEST_5_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, void, void, \
+    void, void, void>
+#define GTEST_6_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, void, \
+    void, void, void>
+#define GTEST_7_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+    void, void, void>
+#define GTEST_8_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+    T##7, void, void>
+#define GTEST_9_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+    T##7, T##8, void>
+#define GTEST_10_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+    T##7, T##8, T##9>
+
+// GTEST_n_TYPENAMES_(T) declares a list of n typenames.
+#define GTEST_0_TYPENAMES_(T)
+#define GTEST_1_TYPENAMES_(T) typename T##0
+#define GTEST_2_TYPENAMES_(T) typename T##0, typename T##1
+#define GTEST_3_TYPENAMES_(T) typename T##0, typename T##1, typename T##2
+#define GTEST_4_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3
+#define GTEST_5_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4
+#define GTEST_6_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5
+#define GTEST_7_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5, typename T##6
+#define GTEST_8_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5, typename T##6, typename T##7
+#define GTEST_9_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5, typename T##6, \
+    typename T##7, typename T##8
+#define GTEST_10_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5, typename T##6, \
+    typename T##7, typename T##8, typename T##9
+
+// In theory, defining stuff in the ::std namespace is undefined
+// behavior.  We can do this as we are playing the role of a standard
+// library vendor.
+namespace std {
+namespace tr1 {
+
+template <typename T0 = void, typename T1 = void, typename T2 = void,
+    typename T3 = void, typename T4 = void, typename T5 = void,
+    typename T6 = void, typename T7 = void, typename T8 = void,
+    typename T9 = void>
+class tuple;
+
+// Anything in namespace gtest_internal is Google Test's INTERNAL
+// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code.
+namespace gtest_internal {
+
+// ByRef<T>::type is T if T is a reference; otherwise it's const T&.
+template <typename T>
+struct ByRef { typedef const T& type; };  // NOLINT
+template <typename T>
+struct ByRef<T&> { typedef T& type; };  // NOLINT
+
+// A handy wrapper for ByRef.
+#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef<T>::type
+
+// AddRef<T>::type is T if T is a reference; otherwise it's T&.  This
+// is the same as tr1::add_reference<T>::type.
+template <typename T>
+struct AddRef { typedef T& type; };  // NOLINT
+template <typename T>
+struct AddRef<T&> { typedef T& type; };  // NOLINT
+
+// A handy wrapper for AddRef.
+#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef<T>::type
+
+// A helper for implementing get<k>().
+template <int k> class Get;
+
+// A helper for implementing tuple_element<k, T>.  kIndexValid is true
+// iff k < the number of fields in tuple type T.
+template <bool kIndexValid, int kIndex, class Tuple>
+struct TupleElement;
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 0, GTEST_10_TUPLE_(T) > {
+  typedef T0 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 1, GTEST_10_TUPLE_(T) > {
+  typedef T1 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 2, GTEST_10_TUPLE_(T) > {
+  typedef T2 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 3, GTEST_10_TUPLE_(T) > {
+  typedef T3 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 4, GTEST_10_TUPLE_(T) > {
+  typedef T4 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 5, GTEST_10_TUPLE_(T) > {
+  typedef T5 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 6, GTEST_10_TUPLE_(T) > {
+  typedef T6 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 7, GTEST_10_TUPLE_(T) > {
+  typedef T7 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 8, GTEST_10_TUPLE_(T) > {
+  typedef T8 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 9, GTEST_10_TUPLE_(T) > {
+  typedef T9 type;
+};
+
+}  // namespace gtest_internal
+
+template <>
+class tuple<> {
+ public:
+  tuple() {}
+  tuple(const tuple& /* t */)  {}
+  tuple& operator=(const tuple& /* t */) { return *this; }
+};
+
+template <GTEST_1_TYPENAMES_(T)>
+class GTEST_1_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0) : f0_(f0) {}
+
+  tuple(const tuple& t) : f0_(t.f0_) {}
+
+  template <GTEST_1_TYPENAMES_(U)>
+  tuple(const GTEST_1_TUPLE_(U)& t) : f0_(t.f0_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_1_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_1_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_1_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_1_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    return *this;
+  }
+
+  T0 f0_;
+};
+
+template <GTEST_2_TYPENAMES_(T)>
+class GTEST_2_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1) : f0_(f0),
+      f1_(f1) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_) {}
+
+  template <GTEST_2_TYPENAMES_(U)>
+  tuple(const GTEST_2_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_) {}
+  template <typename U0, typename U1>
+  tuple(const ::std::pair<U0, U1>& p) : f0_(p.first), f1_(p.second) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_2_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_2_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+  template <typename U0, typename U1>
+  tuple& operator=(const ::std::pair<U0, U1>& p) {
+    f0_ = p.first;
+    f1_ = p.second;
+    return *this;
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_2_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_2_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+};
+
+template <GTEST_3_TYPENAMES_(T)>
+class GTEST_3_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2) : f0_(f0), f1_(f1), f2_(f2) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {}
+
+  template <GTEST_3_TYPENAMES_(U)>
+  tuple(const GTEST_3_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_3_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_3_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_3_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_3_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+};
+
+template <GTEST_4_TYPENAMES_(T)>
+class GTEST_4_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3) : f0_(f0), f1_(f1), f2_(f2),
+      f3_(f3) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_) {}
+
+  template <GTEST_4_TYPENAMES_(U)>
+  tuple(const GTEST_4_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_4_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_4_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_4_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_4_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+};
+
+template <GTEST_5_TYPENAMES_(T)>
+class GTEST_5_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3,
+      GTEST_BY_REF_(T4) f4) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_) {}
+
+  template <GTEST_5_TYPENAMES_(U)>
+  tuple(const GTEST_5_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_5_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_5_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_5_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_5_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+};
+
+template <GTEST_6_TYPENAMES_(T)>
+class GTEST_6_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
+      f5_(f5) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_) {}
+
+  template <GTEST_6_TYPENAMES_(U)>
+  tuple(const GTEST_6_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_6_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_6_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_6_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_6_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+};
+
+template <GTEST_7_TYPENAMES_(T)>
+class GTEST_7_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6) : f0_(f0), f1_(f1), f2_(f2),
+      f3_(f3), f4_(f4), f5_(f5), f6_(f6) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {}
+
+  template <GTEST_7_TYPENAMES_(U)>
+  tuple(const GTEST_7_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_7_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_7_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_7_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_7_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    f6_ = t.f6_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+  T6 f6_;
+};
+
+template <GTEST_8_TYPENAMES_(T)>
+class GTEST_8_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6,
+      GTEST_BY_REF_(T7) f7) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
+      f5_(f5), f6_(f6), f7_(f7) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {}
+
+  template <GTEST_8_TYPENAMES_(U)>
+  tuple(const GTEST_8_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_8_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_8_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_8_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_8_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    f6_ = t.f6_;
+    f7_ = t.f7_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+  T6 f6_;
+  T7 f7_;
+};
+
+template <GTEST_9_TYPENAMES_(T)>
+class GTEST_9_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7,
+      GTEST_BY_REF_(T8) f8) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
+      f5_(f5), f6_(f6), f7_(f7), f8_(f8) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {}
+
+  template <GTEST_9_TYPENAMES_(U)>
+  tuple(const GTEST_9_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_9_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_9_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_9_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_9_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    f6_ = t.f6_;
+    f7_ = t.f7_;
+    f8_ = t.f8_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+  T6 f6_;
+  T7 f7_;
+  T8 f8_;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+class tuple {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_(),
+      f9_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7,
+      GTEST_BY_REF_(T8) f8, GTEST_BY_REF_(T9) f9) : f0_(f0), f1_(f1), f2_(f2),
+      f3_(f3), f4_(f4), f5_(f5), f6_(f6), f7_(f7), f8_(f8), f9_(f9) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), f9_(t.f9_) {}
+
+  template <GTEST_10_TYPENAMES_(U)>
+  tuple(const GTEST_10_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_),
+      f9_(t.f9_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_10_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_10_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_10_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_10_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    f6_ = t.f6_;
+    f7_ = t.f7_;
+    f8_ = t.f8_;
+    f9_ = t.f9_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+  T6 f6_;
+  T7 f7_;
+  T8 f8_;
+  T9 f9_;
+};
+
+// 6.1.3.2 Tuple creation functions.
+
+// Known limitations: we don't support passing an
+// std::tr1::reference_wrapper<T> to make_tuple().  And we don't
+// implement tie().
+
+inline tuple<> make_tuple() { return tuple<>(); }
+
+template <GTEST_1_TYPENAMES_(T)>
+inline GTEST_1_TUPLE_(T) make_tuple(const T0& f0) {
+  return GTEST_1_TUPLE_(T)(f0);
+}
+
+template <GTEST_2_TYPENAMES_(T)>
+inline GTEST_2_TUPLE_(T) make_tuple(const T0& f0, const T1& f1) {
+  return GTEST_2_TUPLE_(T)(f0, f1);
+}
+
+template <GTEST_3_TYPENAMES_(T)>
+inline GTEST_3_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2) {
+  return GTEST_3_TUPLE_(T)(f0, f1, f2);
+}
+
+template <GTEST_4_TYPENAMES_(T)>
+inline GTEST_4_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3) {
+  return GTEST_4_TUPLE_(T)(f0, f1, f2, f3);
+}
+
+template <GTEST_5_TYPENAMES_(T)>
+inline GTEST_5_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4) {
+  return GTEST_5_TUPLE_(T)(f0, f1, f2, f3, f4);
+}
+
+template <GTEST_6_TYPENAMES_(T)>
+inline GTEST_6_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5) {
+  return GTEST_6_TUPLE_(T)(f0, f1, f2, f3, f4, f5);
+}
+
+template <GTEST_7_TYPENAMES_(T)>
+inline GTEST_7_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5, const T6& f6) {
+  return GTEST_7_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6);
+}
+
+template <GTEST_8_TYPENAMES_(T)>
+inline GTEST_8_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7) {
+  return GTEST_8_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7);
+}
+
+template <GTEST_9_TYPENAMES_(T)>
+inline GTEST_9_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7,
+    const T8& f8) {
+  return GTEST_9_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8);
+}
+
+template <GTEST_10_TYPENAMES_(T)>
+inline GTEST_10_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7,
+    const T8& f8, const T9& f9) {
+  return GTEST_10_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9);
+}
+
+// 6.1.3.3 Tuple helper classes.
+
+template <typename Tuple> struct tuple_size;
+
+template <GTEST_0_TYPENAMES_(T)>
+struct tuple_size<GTEST_0_TUPLE_(T) > {
+  static const int value = 0;
+};
+
+template <GTEST_1_TYPENAMES_(T)>
+struct tuple_size<GTEST_1_TUPLE_(T) > {
+  static const int value = 1;
+};
+
+template <GTEST_2_TYPENAMES_(T)>
+struct tuple_size<GTEST_2_TUPLE_(T) > {
+  static const int value = 2;
+};
+
+template <GTEST_3_TYPENAMES_(T)>
+struct tuple_size<GTEST_3_TUPLE_(T) > {
+  static const int value = 3;
+};
+
+template <GTEST_4_TYPENAMES_(T)>
+struct tuple_size<GTEST_4_TUPLE_(T) > {
+  static const int value = 4;
+};
+
+template <GTEST_5_TYPENAMES_(T)>
+struct tuple_size<GTEST_5_TUPLE_(T) > {
+  static const int value = 5;
+};
+
+template <GTEST_6_TYPENAMES_(T)>
+struct tuple_size<GTEST_6_TUPLE_(T) > {
+  static const int value = 6;
+};
+
+template <GTEST_7_TYPENAMES_(T)>
+struct tuple_size<GTEST_7_TUPLE_(T) > {
+  static const int value = 7;
+};
+
+template <GTEST_8_TYPENAMES_(T)>
+struct tuple_size<GTEST_8_TUPLE_(T) > {
+  static const int value = 8;
+};
+
+template <GTEST_9_TYPENAMES_(T)>
+struct tuple_size<GTEST_9_TUPLE_(T) > {
+  static const int value = 9;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct tuple_size<GTEST_10_TUPLE_(T) > {
+  static const int value = 10;
+};
+
+template <int k, class Tuple>
+struct tuple_element {
+  typedef typename gtest_internal::TupleElement<
+      k < (tuple_size<Tuple>::value), k, Tuple>::type type;
+};
+
+#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element<k, Tuple >::type
+
+// 6.1.3.4 Element access.
+
+namespace gtest_internal {
+
+template <>
+class Get<0> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple))
+  Field(Tuple& t) { return t.f0_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple))
+  ConstField(const Tuple& t) { return t.f0_; }
+};
+
+template <>
+class Get<1> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple))
+  Field(Tuple& t) { return t.f1_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple))
+  ConstField(const Tuple& t) { return t.f1_; }
+};
+
+template <>
+class Get<2> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple))
+  Field(Tuple& t) { return t.f2_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple))
+  ConstField(const Tuple& t) { return t.f2_; }
+};
+
+template <>
+class Get<3> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple))
+  Field(Tuple& t) { return t.f3_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple))
+  ConstField(const Tuple& t) { return t.f3_; }
+};
+
+template <>
+class Get<4> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple))
+  Field(Tuple& t) { return t.f4_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple))
+  ConstField(const Tuple& t) { return t.f4_; }
+};
+
+template <>
+class Get<5> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple))
+  Field(Tuple& t) { return t.f5_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple))
+  ConstField(const Tuple& t) { return t.f5_; }
+};
+
+template <>
+class Get<6> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple))
+  Field(Tuple& t) { return t.f6_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple))
+  ConstField(const Tuple& t) { return t.f6_; }
+};
+
+template <>
+class Get<7> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple))
+  Field(Tuple& t) { return t.f7_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple))
+  ConstField(const Tuple& t) { return t.f7_; }
+};
+
+template <>
+class Get<8> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple))
+  Field(Tuple& t) { return t.f8_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple))
+  ConstField(const Tuple& t) { return t.f8_; }
+};
+
+template <>
+class Get<9> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple))
+  Field(Tuple& t) { return t.f9_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple))
+  ConstField(const Tuple& t) { return t.f9_; }
+};
+
+}  // namespace gtest_internal
+
+template <int k, GTEST_10_TYPENAMES_(T)>
+GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T)))
+get(GTEST_10_TUPLE_(T)& t) {
+  return gtest_internal::Get<k>::Field(t);
+}
+
+template <int k, GTEST_10_TYPENAMES_(T)>
+GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k,  GTEST_10_TUPLE_(T)))
+get(const GTEST_10_TUPLE_(T)& t) {
+  return gtest_internal::Get<k>::ConstField(t);
+}
+
+// 6.1.3.5 Relational operators
+
+// We only implement == and !=, as we don't have a need for the rest yet.
+
+namespace gtest_internal {
+
+// SameSizeTuplePrefixComparator<k, k>::Eq(t1, t2) returns true if the
+// first k fields of t1 equals the first k fields of t2.
+// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if
+// k1 != k2.
+template <int kSize1, int kSize2>
+struct SameSizeTuplePrefixComparator;
+
+template <>
+struct SameSizeTuplePrefixComparator<0, 0> {
+  template <class Tuple1, class Tuple2>
+  static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) {
+    return true;
+  }
+};
+
+template <int k>
+struct SameSizeTuplePrefixComparator<k, k> {
+  template <class Tuple1, class Tuple2>
+  static bool Eq(const Tuple1& t1, const Tuple2& t2) {
+    return SameSizeTuplePrefixComparator<k - 1, k - 1>::Eq(t1, t2) &&
+        ::std::tr1::get<k - 1>(t1) == ::std::tr1::get<k - 1>(t2);
+  }
+};
+
+}  // namespace gtest_internal
+
+template <GTEST_10_TYPENAMES_(T), GTEST_10_TYPENAMES_(U)>
+inline bool operator==(const GTEST_10_TUPLE_(T)& t,
+                       const GTEST_10_TUPLE_(U)& u) {
+  return gtest_internal::SameSizeTuplePrefixComparator<
+      tuple_size<GTEST_10_TUPLE_(T) >::value,
+      tuple_size<GTEST_10_TUPLE_(U) >::value>::Eq(t, u);
+}
+
+template <GTEST_10_TYPENAMES_(T), GTEST_10_TYPENAMES_(U)>
+inline bool operator!=(const GTEST_10_TUPLE_(T)& t,
+                       const GTEST_10_TUPLE_(U)& u) { return !(t == u); }
+
+// 6.1.4 Pairs.
+// Unimplemented.
+
+}  // namespace tr1
+}  // namespace std
+
+#undef GTEST_0_TUPLE_
+#undef GTEST_1_TUPLE_
+#undef GTEST_2_TUPLE_
+#undef GTEST_3_TUPLE_
+#undef GTEST_4_TUPLE_
+#undef GTEST_5_TUPLE_
+#undef GTEST_6_TUPLE_
+#undef GTEST_7_TUPLE_
+#undef GTEST_8_TUPLE_
+#undef GTEST_9_TUPLE_
+#undef GTEST_10_TUPLE_
+
+#undef GTEST_0_TYPENAMES_
+#undef GTEST_1_TYPENAMES_
+#undef GTEST_2_TYPENAMES_
+#undef GTEST_3_TYPENAMES_
+#undef GTEST_4_TYPENAMES_
+#undef GTEST_5_TYPENAMES_
+#undef GTEST_6_TYPENAMES_
+#undef GTEST_7_TYPENAMES_
+#undef GTEST_8_TYPENAMES_
+#undef GTEST_9_TYPENAMES_
+#undef GTEST_10_TYPENAMES_
+
+#undef GTEST_DECLARE_TUPLE_AS_FRIEND_
+#undef GTEST_BY_REF_
+#undef GTEST_ADD_REF_
+#undef GTEST_TUPLE_ELEMENT_
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
diff --git a/third_party/googletest/googletest/include/gtest/internal/gtest-tuple.h.pump b/third_party/googletest/googletest/include/gtest/internal/gtest-tuple.h.pump
new file mode 100644
index 0000000..429ddfe
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/internal/gtest-tuple.h.pump
@@ -0,0 +1,347 @@
+$$ -*- mode: c++; -*-
+$var n = 10  $$ Maximum number of tuple fields we want to support.
+$$ This meta comment fixes auto-indentation in Emacs. }}
+// Copyright 2009 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Implements a subset of TR1 tuple needed by Google Test and Google Mock.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
+
+#include <utility>  // For ::std::pair.
+
+// The compiler used in Symbian has a bug that prevents us from declaring the
+// tuple template as a friend (it complains that tuple is redefined).  This
+// hack bypasses the bug by declaring the members that should otherwise be
+// private as public.
+// Sun Studio versions < 12 also have the above bug.
+#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
+#else
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
+    template <GTEST_$(n)_TYPENAMES_(U)> friend class tuple; \
+   private:
+#endif
+
+// Visual Studio 2010, 2012, and 2013 define symbols in std::tr1 that conflict
+// with our own definitions. Therefore using our own tuple does not work on
+// those compilers.
+#if defined(_MSC_VER) && _MSC_VER >= 1600  /* 1600 is Visual Studio 2010 */
+# error "gtest's tuple doesn't compile on Visual Studio 2010 or later. \
+GTEST_USE_OWN_TR1_TUPLE must be set to 0 on those compilers."
+#endif
+
+
+$range i 0..n-1
+$range j 0..n
+$range k 1..n
+// GTEST_n_TUPLE_(T) is the type of an n-tuple.
+#define GTEST_0_TUPLE_(T) tuple<>
+
+$for k [[
+$range m 0..k-1
+$range m2 k..n-1
+#define GTEST_$(k)_TUPLE_(T) tuple<$for m, [[T##$m]]$for m2 [[, void]]>
+
+]]
+
+// GTEST_n_TYPENAMES_(T) declares a list of n typenames.
+
+$for j [[
+$range m 0..j-1
+#define GTEST_$(j)_TYPENAMES_(T) $for m, [[typename T##$m]]
+
+
+]]
+
+// In theory, defining stuff in the ::std namespace is undefined
+// behavior.  We can do this as we are playing the role of a standard
+// library vendor.
+namespace std {
+namespace tr1 {
+
+template <$for i, [[typename T$i = void]]>
+class tuple;
+
+// Anything in namespace gtest_internal is Google Test's INTERNAL
+// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code.
+namespace gtest_internal {
+
+// ByRef<T>::type is T if T is a reference; otherwise it's const T&.
+template <typename T>
+struct ByRef { typedef const T& type; };  // NOLINT
+template <typename T>
+struct ByRef<T&> { typedef T& type; };  // NOLINT
+
+// A handy wrapper for ByRef.
+#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef<T>::type
+
+// AddRef<T>::type is T if T is a reference; otherwise it's T&.  This
+// is the same as tr1::add_reference<T>::type.
+template <typename T>
+struct AddRef { typedef T& type; };  // NOLINT
+template <typename T>
+struct AddRef<T&> { typedef T& type; };  // NOLINT
+
+// A handy wrapper for AddRef.
+#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef<T>::type
+
+// A helper for implementing get<k>().
+template <int k> class Get;
+
+// A helper for implementing tuple_element<k, T>.  kIndexValid is true
+// iff k < the number of fields in tuple type T.
+template <bool kIndexValid, int kIndex, class Tuple>
+struct TupleElement;
+
+
+$for i [[
+template <GTEST_$(n)_TYPENAMES_(T)>
+struct TupleElement<true, $i, GTEST_$(n)_TUPLE_(T) > {
+  typedef T$i type;
+};
+
+
+]]
+}  // namespace gtest_internal
+
+template <>
+class tuple<> {
+ public:
+  tuple() {}
+  tuple(const tuple& /* t */)  {}
+  tuple& operator=(const tuple& /* t */) { return *this; }
+};
+
+
+$for k [[
+$range m 0..k-1
+template <GTEST_$(k)_TYPENAMES_(T)>
+class $if k < n [[GTEST_$(k)_TUPLE_(T)]] $else [[tuple]] {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : $for m, [[f$(m)_()]] {}
+
+  explicit tuple($for m, [[GTEST_BY_REF_(T$m) f$m]]) : [[]]
+$for m, [[f$(m)_(f$m)]] {}
+
+  tuple(const tuple& t) : $for m, [[f$(m)_(t.f$(m)_)]] {}
+
+  template <GTEST_$(k)_TYPENAMES_(U)>
+  tuple(const GTEST_$(k)_TUPLE_(U)& t) : $for m, [[f$(m)_(t.f$(m)_)]] {}
+
+$if k == 2 [[
+  template <typename U0, typename U1>
+  tuple(const ::std::pair<U0, U1>& p) : f0_(p.first), f1_(p.second) {}
+
+]]
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_$(k)_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_$(k)_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+$if k == 2 [[
+  template <typename U0, typename U1>
+  tuple& operator=(const ::std::pair<U0, U1>& p) {
+    f0_ = p.first;
+    f1_ = p.second;
+    return *this;
+  }
+
+]]
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_$(k)_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_$(k)_TUPLE_(U)& t) {
+
+$for m [[
+    f$(m)_ = t.f$(m)_;
+
+]]
+    return *this;
+  }
+
+
+$for m [[
+  T$m f$(m)_;
+
+]]
+};
+
+
+]]
+// 6.1.3.2 Tuple creation functions.
+
+// Known limitations: we don't support passing an
+// std::tr1::reference_wrapper<T> to make_tuple().  And we don't
+// implement tie().
+
+inline tuple<> make_tuple() { return tuple<>(); }
+
+$for k [[
+$range m 0..k-1
+
+template <GTEST_$(k)_TYPENAMES_(T)>
+inline GTEST_$(k)_TUPLE_(T) make_tuple($for m, [[const T$m& f$m]]) {
+  return GTEST_$(k)_TUPLE_(T)($for m, [[f$m]]);
+}
+
+]]
+
+// 6.1.3.3 Tuple helper classes.
+
+template <typename Tuple> struct tuple_size;
+
+
+$for j [[
+template <GTEST_$(j)_TYPENAMES_(T)>
+struct tuple_size<GTEST_$(j)_TUPLE_(T) > {
+  static const int value = $j;
+};
+
+
+]]
+template <int k, class Tuple>
+struct tuple_element {
+  typedef typename gtest_internal::TupleElement<
+      k < (tuple_size<Tuple>::value), k, Tuple>::type type;
+};
+
+#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element<k, Tuple >::type
+
+// 6.1.3.4 Element access.
+
+namespace gtest_internal {
+
+
+$for i [[
+template <>
+class Get<$i> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple))
+  Field(Tuple& t) { return t.f$(i)_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple))
+  ConstField(const Tuple& t) { return t.f$(i)_; }
+};
+
+
+]]
+}  // namespace gtest_internal
+
+template <int k, GTEST_$(n)_TYPENAMES_(T)>
+GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T)))
+get(GTEST_$(n)_TUPLE_(T)& t) {
+  return gtest_internal::Get<k>::Field(t);
+}
+
+template <int k, GTEST_$(n)_TYPENAMES_(T)>
+GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k,  GTEST_$(n)_TUPLE_(T)))
+get(const GTEST_$(n)_TUPLE_(T)& t) {
+  return gtest_internal::Get<k>::ConstField(t);
+}
+
+// 6.1.3.5 Relational operators
+
+// We only implement == and !=, as we don't have a need for the rest yet.
+
+namespace gtest_internal {
+
+// SameSizeTuplePrefixComparator<k, k>::Eq(t1, t2) returns true if the
+// first k fields of t1 equals the first k fields of t2.
+// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if
+// k1 != k2.
+template <int kSize1, int kSize2>
+struct SameSizeTuplePrefixComparator;
+
+template <>
+struct SameSizeTuplePrefixComparator<0, 0> {
+  template <class Tuple1, class Tuple2>
+  static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) {
+    return true;
+  }
+};
+
+template <int k>
+struct SameSizeTuplePrefixComparator<k, k> {
+  template <class Tuple1, class Tuple2>
+  static bool Eq(const Tuple1& t1, const Tuple2& t2) {
+    return SameSizeTuplePrefixComparator<k - 1, k - 1>::Eq(t1, t2) &&
+        ::std::tr1::get<k - 1>(t1) == ::std::tr1::get<k - 1>(t2);
+  }
+};
+
+}  // namespace gtest_internal
+
+template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)>
+inline bool operator==(const GTEST_$(n)_TUPLE_(T)& t,
+                       const GTEST_$(n)_TUPLE_(U)& u) {
+  return gtest_internal::SameSizeTuplePrefixComparator<
+      tuple_size<GTEST_$(n)_TUPLE_(T) >::value,
+      tuple_size<GTEST_$(n)_TUPLE_(U) >::value>::Eq(t, u);
+}
+
+template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)>
+inline bool operator!=(const GTEST_$(n)_TUPLE_(T)& t,
+                       const GTEST_$(n)_TUPLE_(U)& u) { return !(t == u); }
+
+// 6.1.4 Pairs.
+// Unimplemented.
+
+}  // namespace tr1
+}  // namespace std
+
+
+$for j [[
+#undef GTEST_$(j)_TUPLE_
+
+]]
+
+
+$for j [[
+#undef GTEST_$(j)_TYPENAMES_
+
+]]
+
+#undef GTEST_DECLARE_TUPLE_AS_FRIEND_
+#undef GTEST_BY_REF_
+#undef GTEST_ADD_REF_
+#undef GTEST_TUPLE_ELEMENT_
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
diff --git a/third_party/googletest/googletest/include/gtest/internal/gtest-type-util.h b/third_party/googletest/googletest/include/gtest/internal/gtest-type-util.h
new file mode 100644
index 0000000..e46f7cf
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/internal/gtest-type-util.h
@@ -0,0 +1,3331 @@
+// This file was GENERATED by command:
+//     pump.py gtest-type-util.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Type utilities needed for implementing typed and type-parameterized
+// tests.  This file is generated by a SCRIPT.  DO NOT EDIT BY HAND!
+//
+// Currently we support at most 50 types in a list, and at most 50
+// type-parameterized tests in one type-parameterized test case.
+// Please contact googletestframework@googlegroups.com if you need
+// more.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+
+#include "gtest/internal/gtest-port.h"
+
+// #ifdef __GNUC__ is too general here.  It is possible to use gcc without using
+// libstdc++ (which is where cxxabi.h comes from).
+# if GTEST_HAS_CXXABI_H_
+#  include <cxxabi.h>
+# elif defined(__HP_aCC)
+#  include <acxx_demangle.h>
+# endif  // GTEST_HASH_CXXABI_H_
+
+namespace testing {
+namespace internal {
+
+// GetTypeName<T>() returns a human-readable name of type T.
+// NB: This function is also used in Google Mock, so don't move it inside of
+// the typed-test-only section below.
+template <typename T>
+std::string GetTypeName() {
+# if GTEST_HAS_RTTI
+
+  const char* const name = typeid(T).name();
+#  if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC)
+  int status = 0;
+  // gcc's implementation of typeid(T).name() mangles the type name,
+  // so we have to demangle it.
+#   if GTEST_HAS_CXXABI_H_
+  using abi::__cxa_demangle;
+#   endif  // GTEST_HAS_CXXABI_H_
+  char* const readable_name = __cxa_demangle(name, 0, 0, &status);
+  const std::string name_str(status == 0 ? readable_name : name);
+  free(readable_name);
+  return name_str;
+#  else
+  return name;
+#  endif  // GTEST_HAS_CXXABI_H_ || __HP_aCC
+
+# else
+
+  return "<type>";
+
+# endif  // GTEST_HAS_RTTI
+}
+
+#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// AssertyTypeEq<T1, T2>::type is defined iff T1 and T2 are the same
+// type.  This can be used as a compile-time assertion to ensure that
+// two types are equal.
+
+template <typename T1, typename T2>
+struct AssertTypeEq;
+
+template <typename T>
+struct AssertTypeEq<T, T> {
+  typedef bool type;
+};
+
+// A unique type used as the default value for the arguments of class
+// template Types.  This allows us to simulate variadic templates
+// (e.g. Types<int>, Type<int, double>, and etc), which C++ doesn't
+// support directly.
+struct None {};
+
+// The following family of struct and struct templates are used to
+// represent type lists.  In particular, TypesN<T1, T2, ..., TN>
+// represents a type list with N types (T1, T2, ..., and TN) in it.
+// Except for Types0, every struct in the family has two member types:
+// Head for the first type in the list, and Tail for the rest of the
+// list.
+
+// The empty type list.
+struct Types0 {};
+
+// Type lists of length 1, 2, 3, and so on.
+
+template <typename T1>
+struct Types1 {
+  typedef T1 Head;
+  typedef Types0 Tail;
+};
+template <typename T1, typename T2>
+struct Types2 {
+  typedef T1 Head;
+  typedef Types1<T2> Tail;
+};
+
+template <typename T1, typename T2, typename T3>
+struct Types3 {
+  typedef T1 Head;
+  typedef Types2<T2, T3> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4>
+struct Types4 {
+  typedef T1 Head;
+  typedef Types3<T2, T3, T4> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+struct Types5 {
+  typedef T1 Head;
+  typedef Types4<T2, T3, T4, T5> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+struct Types6 {
+  typedef T1 Head;
+  typedef Types5<T2, T3, T4, T5, T6> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+struct Types7 {
+  typedef T1 Head;
+  typedef Types6<T2, T3, T4, T5, T6, T7> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+struct Types8 {
+  typedef T1 Head;
+  typedef Types7<T2, T3, T4, T5, T6, T7, T8> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+struct Types9 {
+  typedef T1 Head;
+  typedef Types8<T2, T3, T4, T5, T6, T7, T8, T9> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+struct Types10 {
+  typedef T1 Head;
+  typedef Types9<T2, T3, T4, T5, T6, T7, T8, T9, T10> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11>
+struct Types11 {
+  typedef T1 Head;
+  typedef Types10<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12>
+struct Types12 {
+  typedef T1 Head;
+  typedef Types11<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13>
+struct Types13 {
+  typedef T1 Head;
+  typedef Types12<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14>
+struct Types14 {
+  typedef T1 Head;
+  typedef Types13<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Types15 {
+  typedef T1 Head;
+  typedef Types14<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16>
+struct Types16 {
+  typedef T1 Head;
+  typedef Types15<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17>
+struct Types17 {
+  typedef T1 Head;
+  typedef Types16<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18>
+struct Types18 {
+  typedef T1 Head;
+  typedef Types17<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19>
+struct Types19 {
+  typedef T1 Head;
+  typedef Types18<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20>
+struct Types20 {
+  typedef T1 Head;
+  typedef Types19<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21>
+struct Types21 {
+  typedef T1 Head;
+  typedef Types20<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22>
+struct Types22 {
+  typedef T1 Head;
+  typedef Types21<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23>
+struct Types23 {
+  typedef T1 Head;
+  typedef Types22<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24>
+struct Types24 {
+  typedef T1 Head;
+  typedef Types23<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25>
+struct Types25 {
+  typedef T1 Head;
+  typedef Types24<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26>
+struct Types26 {
+  typedef T1 Head;
+  typedef Types25<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27>
+struct Types27 {
+  typedef T1 Head;
+  typedef Types26<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28>
+struct Types28 {
+  typedef T1 Head;
+  typedef Types27<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29>
+struct Types29 {
+  typedef T1 Head;
+  typedef Types28<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30>
+struct Types30 {
+  typedef T1 Head;
+  typedef Types29<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31>
+struct Types31 {
+  typedef T1 Head;
+  typedef Types30<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32>
+struct Types32 {
+  typedef T1 Head;
+  typedef Types31<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33>
+struct Types33 {
+  typedef T1 Head;
+  typedef Types32<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34>
+struct Types34 {
+  typedef T1 Head;
+  typedef Types33<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35>
+struct Types35 {
+  typedef T1 Head;
+  typedef Types34<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36>
+struct Types36 {
+  typedef T1 Head;
+  typedef Types35<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37>
+struct Types37 {
+  typedef T1 Head;
+  typedef Types36<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38>
+struct Types38 {
+  typedef T1 Head;
+  typedef Types37<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39>
+struct Types39 {
+  typedef T1 Head;
+  typedef Types38<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40>
+struct Types40 {
+  typedef T1 Head;
+  typedef Types39<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41>
+struct Types41 {
+  typedef T1 Head;
+  typedef Types40<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42>
+struct Types42 {
+  typedef T1 Head;
+  typedef Types41<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43>
+struct Types43 {
+  typedef T1 Head;
+  typedef Types42<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44>
+struct Types44 {
+  typedef T1 Head;
+  typedef Types43<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45>
+struct Types45 {
+  typedef T1 Head;
+  typedef Types44<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46>
+struct Types46 {
+  typedef T1 Head;
+  typedef Types45<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47>
+struct Types47 {
+  typedef T1 Head;
+  typedef Types46<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46, T47> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48>
+struct Types48 {
+  typedef T1 Head;
+  typedef Types47<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46, T47, T48> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49>
+struct Types49 {
+  typedef T1 Head;
+  typedef Types48<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46, T47, T48, T49> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49, typename T50>
+struct Types50 {
+  typedef T1 Head;
+  typedef Types49<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46, T47, T48, T49, T50> Tail;
+};
+
+
+}  // namespace internal
+
+// We don't want to require the users to write TypesN<...> directly,
+// as that would require them to count the length.  Types<...> is much
+// easier to write, but generates horrible messages when there is a
+// compiler error, as gcc insists on printing out each template
+// argument, even if it has the default value (this means Types<int>
+// will appear as Types<int, None, None, ..., None> in the compiler
+// errors).
+//
+// Our solution is to combine the best part of the two approaches: a
+// user would write Types<T1, ..., TN>, and Google Test will translate
+// that to TypesN<T1, ..., TN> internally to make error messages
+// readable.  The translation is done by the 'type' member of the
+// Types template.
+template <typename T1 = internal::None, typename T2 = internal::None,
+    typename T3 = internal::None, typename T4 = internal::None,
+    typename T5 = internal::None, typename T6 = internal::None,
+    typename T7 = internal::None, typename T8 = internal::None,
+    typename T9 = internal::None, typename T10 = internal::None,
+    typename T11 = internal::None, typename T12 = internal::None,
+    typename T13 = internal::None, typename T14 = internal::None,
+    typename T15 = internal::None, typename T16 = internal::None,
+    typename T17 = internal::None, typename T18 = internal::None,
+    typename T19 = internal::None, typename T20 = internal::None,
+    typename T21 = internal::None, typename T22 = internal::None,
+    typename T23 = internal::None, typename T24 = internal::None,
+    typename T25 = internal::None, typename T26 = internal::None,
+    typename T27 = internal::None, typename T28 = internal::None,
+    typename T29 = internal::None, typename T30 = internal::None,
+    typename T31 = internal::None, typename T32 = internal::None,
+    typename T33 = internal::None, typename T34 = internal::None,
+    typename T35 = internal::None, typename T36 = internal::None,
+    typename T37 = internal::None, typename T38 = internal::None,
+    typename T39 = internal::None, typename T40 = internal::None,
+    typename T41 = internal::None, typename T42 = internal::None,
+    typename T43 = internal::None, typename T44 = internal::None,
+    typename T45 = internal::None, typename T46 = internal::None,
+    typename T47 = internal::None, typename T48 = internal::None,
+    typename T49 = internal::None, typename T50 = internal::None>
+struct Types {
+  typedef internal::Types50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47, T48, T49, T50> type;
+};
+
+template <>
+struct Types<internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types0 type;
+};
+template <typename T1>
+struct Types<T1, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types1<T1> type;
+};
+template <typename T1, typename T2>
+struct Types<T1, T2, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types2<T1, T2> type;
+};
+template <typename T1, typename T2, typename T3>
+struct Types<T1, T2, T3, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types3<T1, T2, T3> type;
+};
+template <typename T1, typename T2, typename T3, typename T4>
+struct Types<T1, T2, T3, T4, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types4<T1, T2, T3, T4> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+struct Types<T1, T2, T3, T4, T5, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types5<T1, T2, T3, T4, T5> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+struct Types<T1, T2, T3, T4, T5, T6, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types6<T1, T2, T3, T4, T5, T6> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+struct Types<T1, T2, T3, T4, T5, T6, T7, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types7<T1, T2, T3, T4, T5, T6, T7> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types8<T1, T2, T3, T4, T5, T6, T7, T8> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types9<T1, T2, T3, T4, T5, T6, T7, T8, T9> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    T46, internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    T46, T47, internal::None, internal::None, internal::None> {
+  typedef internal::Types47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    T46, T47, T48, internal::None, internal::None> {
+  typedef internal::Types48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47, T48> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    T46, T47, T48, T49, internal::None> {
+  typedef internal::Types49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47, T48, T49> type;
+};
+
+namespace internal {
+
+# define GTEST_TEMPLATE_ template <typename T> class
+
+// The template "selector" struct TemplateSel<Tmpl> is used to
+// represent Tmpl, which must be a class template with one type
+// parameter, as a type.  TemplateSel<Tmpl>::Bind<T>::type is defined
+// as the type Tmpl<T>.  This allows us to actually instantiate the
+// template "selected" by TemplateSel<Tmpl>.
+//
+// This trick is necessary for simulating typedef for class templates,
+// which C++ doesn't support directly.
+template <GTEST_TEMPLATE_ Tmpl>
+struct TemplateSel {
+  template <typename T>
+  struct Bind {
+    typedef Tmpl<T> type;
+  };
+};
+
+# define GTEST_BIND_(TmplSel, T) \
+  TmplSel::template Bind<T>::type
+
+// A unique struct template used as the default value for the
+// arguments of class template Templates.  This allows us to simulate
+// variadic templates (e.g. Templates<int>, Templates<int, double>,
+// and etc), which C++ doesn't support directly.
+template <typename T>
+struct NoneT {};
+
+// The following family of struct and struct templates are used to
+// represent template lists.  In particular, TemplatesN<T1, T2, ...,
+// TN> represents a list of N templates (T1, T2, ..., and TN).  Except
+// for Templates0, every struct in the family has two member types:
+// Head for the selector of the first template in the list, and Tail
+// for the rest of the list.
+
+// The empty template list.
+struct Templates0 {};
+
+// Template lists of length 1, 2, 3, and so on.
+
+template <GTEST_TEMPLATE_ T1>
+struct Templates1 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates0 Tail;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2>
+struct Templates2 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates1<T2> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3>
+struct Templates3 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates2<T2, T3> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4>
+struct Templates4 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates3<T2, T3, T4> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5>
+struct Templates5 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates4<T2, T3, T4, T5> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6>
+struct Templates6 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates5<T2, T3, T4, T5, T6> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7>
+struct Templates7 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates6<T2, T3, T4, T5, T6, T7> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8>
+struct Templates8 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates7<T2, T3, T4, T5, T6, T7, T8> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9>
+struct Templates9 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates8<T2, T3, T4, T5, T6, T7, T8, T9> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10>
+struct Templates10 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates9<T2, T3, T4, T5, T6, T7, T8, T9, T10> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11>
+struct Templates11 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates10<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12>
+struct Templates12 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates11<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13>
+struct Templates13 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates12<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14>
+struct Templates14 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates13<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15>
+struct Templates15 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates14<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16>
+struct Templates16 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates15<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17>
+struct Templates17 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates16<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18>
+struct Templates18 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates17<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19>
+struct Templates19 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates18<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20>
+struct Templates20 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates19<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21>
+struct Templates21 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates20<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22>
+struct Templates22 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates21<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23>
+struct Templates23 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates22<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24>
+struct Templates24 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates23<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25>
+struct Templates25 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates24<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26>
+struct Templates26 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates25<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27>
+struct Templates27 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates26<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28>
+struct Templates28 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates27<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29>
+struct Templates29 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates28<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30>
+struct Templates30 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates29<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31>
+struct Templates31 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates30<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32>
+struct Templates32 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates31<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33>
+struct Templates33 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates32<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34>
+struct Templates34 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates33<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35>
+struct Templates35 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates34<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36>
+struct Templates36 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates35<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37>
+struct Templates37 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates36<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38>
+struct Templates38 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates37<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39>
+struct Templates39 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates38<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40>
+struct Templates40 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates39<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41>
+struct Templates41 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates40<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42>
+struct Templates42 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates41<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43>
+struct Templates43 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates42<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44>
+struct Templates44 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates43<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45>
+struct Templates45 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates44<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46>
+struct Templates46 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates45<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47>
+struct Templates47 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates46<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46, T47> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48>
+struct Templates48 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates47<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46, T47, T48> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48,
+    GTEST_TEMPLATE_ T49>
+struct Templates49 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates48<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46, T47, T48, T49> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48,
+    GTEST_TEMPLATE_ T49, GTEST_TEMPLATE_ T50>
+struct Templates50 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates49<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46, T47, T48, T49, T50> Tail;
+};
+
+
+// We don't want to require the users to write TemplatesN<...> directly,
+// as that would require them to count the length.  Templates<...> is much
+// easier to write, but generates horrible messages when there is a
+// compiler error, as gcc insists on printing out each template
+// argument, even if it has the default value (this means Templates<list>
+// will appear as Templates<list, NoneT, NoneT, ..., NoneT> in the compiler
+// errors).
+//
+// Our solution is to combine the best part of the two approaches: a
+// user would write Templates<T1, ..., TN>, and Google Test will translate
+// that to TemplatesN<T1, ..., TN> internally to make error messages
+// readable.  The translation is done by the 'type' member of the
+// Templates template.
+template <GTEST_TEMPLATE_ T1 = NoneT, GTEST_TEMPLATE_ T2 = NoneT,
+    GTEST_TEMPLATE_ T3 = NoneT, GTEST_TEMPLATE_ T4 = NoneT,
+    GTEST_TEMPLATE_ T5 = NoneT, GTEST_TEMPLATE_ T6 = NoneT,
+    GTEST_TEMPLATE_ T7 = NoneT, GTEST_TEMPLATE_ T8 = NoneT,
+    GTEST_TEMPLATE_ T9 = NoneT, GTEST_TEMPLATE_ T10 = NoneT,
+    GTEST_TEMPLATE_ T11 = NoneT, GTEST_TEMPLATE_ T12 = NoneT,
+    GTEST_TEMPLATE_ T13 = NoneT, GTEST_TEMPLATE_ T14 = NoneT,
+    GTEST_TEMPLATE_ T15 = NoneT, GTEST_TEMPLATE_ T16 = NoneT,
+    GTEST_TEMPLATE_ T17 = NoneT, GTEST_TEMPLATE_ T18 = NoneT,
+    GTEST_TEMPLATE_ T19 = NoneT, GTEST_TEMPLATE_ T20 = NoneT,
+    GTEST_TEMPLATE_ T21 = NoneT, GTEST_TEMPLATE_ T22 = NoneT,
+    GTEST_TEMPLATE_ T23 = NoneT, GTEST_TEMPLATE_ T24 = NoneT,
+    GTEST_TEMPLATE_ T25 = NoneT, GTEST_TEMPLATE_ T26 = NoneT,
+    GTEST_TEMPLATE_ T27 = NoneT, GTEST_TEMPLATE_ T28 = NoneT,
+    GTEST_TEMPLATE_ T29 = NoneT, GTEST_TEMPLATE_ T30 = NoneT,
+    GTEST_TEMPLATE_ T31 = NoneT, GTEST_TEMPLATE_ T32 = NoneT,
+    GTEST_TEMPLATE_ T33 = NoneT, GTEST_TEMPLATE_ T34 = NoneT,
+    GTEST_TEMPLATE_ T35 = NoneT, GTEST_TEMPLATE_ T36 = NoneT,
+    GTEST_TEMPLATE_ T37 = NoneT, GTEST_TEMPLATE_ T38 = NoneT,
+    GTEST_TEMPLATE_ T39 = NoneT, GTEST_TEMPLATE_ T40 = NoneT,
+    GTEST_TEMPLATE_ T41 = NoneT, GTEST_TEMPLATE_ T42 = NoneT,
+    GTEST_TEMPLATE_ T43 = NoneT, GTEST_TEMPLATE_ T44 = NoneT,
+    GTEST_TEMPLATE_ T45 = NoneT, GTEST_TEMPLATE_ T46 = NoneT,
+    GTEST_TEMPLATE_ T47 = NoneT, GTEST_TEMPLATE_ T48 = NoneT,
+    GTEST_TEMPLATE_ T49 = NoneT, GTEST_TEMPLATE_ T50 = NoneT>
+struct Templates {
+  typedef Templates50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46, T47, T48, T49, T50> type;
+};
+
+template <>
+struct Templates<NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT> {
+  typedef Templates0 type;
+};
+template <GTEST_TEMPLATE_ T1>
+struct Templates<T1, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT> {
+  typedef Templates1<T1> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2>
+struct Templates<T1, T2, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT> {
+  typedef Templates2<T1, T2> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3>
+struct Templates<T1, T2, T3, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates3<T1, T2, T3> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4>
+struct Templates<T1, T2, T3, T4, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates4<T1, T2, T3, T4> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5>
+struct Templates<T1, T2, T3, T4, T5, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates5<T1, T2, T3, T4, T5> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6>
+struct Templates<T1, T2, T3, T4, T5, T6, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates6<T1, T2, T3, T4, T5, T6> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates7<T1, T2, T3, T4, T5, T6, T7> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates8<T1, T2, T3, T4, T5, T6, T7, T8> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates9<T1, T2, T3, T4, T5, T6, T7, T8, T9> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT> {
+  typedef Templates22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT> {
+  typedef Templates23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT> {
+  typedef Templates24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT> {
+  typedef Templates25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT> {
+  typedef Templates26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT> {
+  typedef Templates27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT> {
+  typedef Templates28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT> {
+  typedef Templates29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, T46, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, T46, T47, NoneT, NoneT, NoneT> {
+  typedef Templates47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46, T47> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, T46, T47, T48, NoneT, NoneT> {
+  typedef Templates48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46, T47, T48> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48,
+    GTEST_TEMPLATE_ T49>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, T46, T47, T48, T49, NoneT> {
+  typedef Templates49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46, T47, T48, T49> type;
+};
+
+// The TypeList template makes it possible to use either a single type
+// or a Types<...> list in TYPED_TEST_CASE() and
+// INSTANTIATE_TYPED_TEST_CASE_P().
+
+template <typename T>
+struct TypeList {
+  typedef Types1<T> type;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49, typename T50>
+struct TypeList<Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47, T48, T49, T50> > {
+  typedef typename Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47, T48, T49, T50>::type type;
+};
+
+#endif  // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
diff --git a/third_party/googletest/googletest/include/gtest/internal/gtest-type-util.h.pump b/third_party/googletest/googletest/include/gtest/internal/gtest-type-util.h.pump
new file mode 100644
index 0000000..251fdf0
--- /dev/null
+++ b/third_party/googletest/googletest/include/gtest/internal/gtest-type-util.h.pump
@@ -0,0 +1,297 @@
+$$ -*- mode: c++; -*-
+$var n = 50  $$ Maximum length of type lists we want to support.
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Type utilities needed for implementing typed and type-parameterized
+// tests.  This file is generated by a SCRIPT.  DO NOT EDIT BY HAND!
+//
+// Currently we support at most $n types in a list, and at most $n
+// type-parameterized tests in one type-parameterized test case.
+// Please contact googletestframework@googlegroups.com if you need
+// more.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+
+#include "gtest/internal/gtest-port.h"
+
+// #ifdef __GNUC__ is too general here.  It is possible to use gcc without using
+// libstdc++ (which is where cxxabi.h comes from).
+# if GTEST_HAS_CXXABI_H_
+#  include <cxxabi.h>
+# elif defined(__HP_aCC)
+#  include <acxx_demangle.h>
+# endif  // GTEST_HASH_CXXABI_H_
+
+namespace testing {
+namespace internal {
+
+// GetTypeName<T>() returns a human-readable name of type T.
+// NB: This function is also used in Google Mock, so don't move it inside of
+// the typed-test-only section below.
+template <typename T>
+std::string GetTypeName() {
+# if GTEST_HAS_RTTI
+
+  const char* const name = typeid(T).name();
+#  if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC)
+  int status = 0;
+  // gcc's implementation of typeid(T).name() mangles the type name,
+  // so we have to demangle it.
+#   if GTEST_HAS_CXXABI_H_
+  using abi::__cxa_demangle;
+#   endif  // GTEST_HAS_CXXABI_H_
+  char* const readable_name = __cxa_demangle(name, 0, 0, &status);
+  const std::string name_str(status == 0 ? readable_name : name);
+  free(readable_name);
+  return name_str;
+#  else
+  return name;
+#  endif  // GTEST_HAS_CXXABI_H_ || __HP_aCC
+
+# else
+
+  return "<type>";
+
+# endif  // GTEST_HAS_RTTI
+}
+
+#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// AssertyTypeEq<T1, T2>::type is defined iff T1 and T2 are the same
+// type.  This can be used as a compile-time assertion to ensure that
+// two types are equal.
+
+template <typename T1, typename T2>
+struct AssertTypeEq;
+
+template <typename T>
+struct AssertTypeEq<T, T> {
+  typedef bool type;
+};
+
+// A unique type used as the default value for the arguments of class
+// template Types.  This allows us to simulate variadic templates
+// (e.g. Types<int>, Type<int, double>, and etc), which C++ doesn't
+// support directly.
+struct None {};
+
+// The following family of struct and struct templates are used to
+// represent type lists.  In particular, TypesN<T1, T2, ..., TN>
+// represents a type list with N types (T1, T2, ..., and TN) in it.
+// Except for Types0, every struct in the family has two member types:
+// Head for the first type in the list, and Tail for the rest of the
+// list.
+
+// The empty type list.
+struct Types0 {};
+
+// Type lists of length 1, 2, 3, and so on.
+
+template <typename T1>
+struct Types1 {
+  typedef T1 Head;
+  typedef Types0 Tail;
+};
+
+$range i 2..n
+
+$for i [[
+$range j 1..i
+$range k 2..i
+template <$for j, [[typename T$j]]>
+struct Types$i {
+  typedef T1 Head;
+  typedef Types$(i-1)<$for k, [[T$k]]> Tail;
+};
+
+
+]]
+
+}  // namespace internal
+
+// We don't want to require the users to write TypesN<...> directly,
+// as that would require them to count the length.  Types<...> is much
+// easier to write, but generates horrible messages when there is a
+// compiler error, as gcc insists on printing out each template
+// argument, even if it has the default value (this means Types<int>
+// will appear as Types<int, None, None, ..., None> in the compiler
+// errors).
+//
+// Our solution is to combine the best part of the two approaches: a
+// user would write Types<T1, ..., TN>, and Google Test will translate
+// that to TypesN<T1, ..., TN> internally to make error messages
+// readable.  The translation is done by the 'type' member of the
+// Types template.
+
+$range i 1..n
+template <$for i, [[typename T$i = internal::None]]>
+struct Types {
+  typedef internal::Types$n<$for i, [[T$i]]> type;
+};
+
+template <>
+struct Types<$for i, [[internal::None]]> {
+  typedef internal::Types0 type;
+};
+
+$range i 1..n-1
+$for i [[
+$range j 1..i
+$range k i+1..n
+template <$for j, [[typename T$j]]>
+struct Types<$for j, [[T$j]]$for k[[, internal::None]]> {
+  typedef internal::Types$i<$for j, [[T$j]]> type;
+};
+
+]]
+
+namespace internal {
+
+# define GTEST_TEMPLATE_ template <typename T> class
+
+// The template "selector" struct TemplateSel<Tmpl> is used to
+// represent Tmpl, which must be a class template with one type
+// parameter, as a type.  TemplateSel<Tmpl>::Bind<T>::type is defined
+// as the type Tmpl<T>.  This allows us to actually instantiate the
+// template "selected" by TemplateSel<Tmpl>.
+//
+// This trick is necessary for simulating typedef for class templates,
+// which C++ doesn't support directly.
+template <GTEST_TEMPLATE_ Tmpl>
+struct TemplateSel {
+  template <typename T>
+  struct Bind {
+    typedef Tmpl<T> type;
+  };
+};
+
+# define GTEST_BIND_(TmplSel, T) \
+  TmplSel::template Bind<T>::type
+
+// A unique struct template used as the default value for the
+// arguments of class template Templates.  This allows us to simulate
+// variadic templates (e.g. Templates<int>, Templates<int, double>,
+// and etc), which C++ doesn't support directly.
+template <typename T>
+struct NoneT {};
+
+// The following family of struct and struct templates are used to
+// represent template lists.  In particular, TemplatesN<T1, T2, ...,
+// TN> represents a list of N templates (T1, T2, ..., and TN).  Except
+// for Templates0, every struct in the family has two member types:
+// Head for the selector of the first template in the list, and Tail
+// for the rest of the list.
+
+// The empty template list.
+struct Templates0 {};
+
+// Template lists of length 1, 2, 3, and so on.
+
+template <GTEST_TEMPLATE_ T1>
+struct Templates1 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates0 Tail;
+};
+
+$range i 2..n
+
+$for i [[
+$range j 1..i
+$range k 2..i
+template <$for j, [[GTEST_TEMPLATE_ T$j]]>
+struct Templates$i {
+  typedef TemplateSel<T1> Head;
+  typedef Templates$(i-1)<$for k, [[T$k]]> Tail;
+};
+
+
+]]
+
+// We don't want to require the users to write TemplatesN<...> directly,
+// as that would require them to count the length.  Templates<...> is much
+// easier to write, but generates horrible messages when there is a
+// compiler error, as gcc insists on printing out each template
+// argument, even if it has the default value (this means Templates<list>
+// will appear as Templates<list, NoneT, NoneT, ..., NoneT> in the compiler
+// errors).
+//
+// Our solution is to combine the best part of the two approaches: a
+// user would write Templates<T1, ..., TN>, and Google Test will translate
+// that to TemplatesN<T1, ..., TN> internally to make error messages
+// readable.  The translation is done by the 'type' member of the
+// Templates template.
+
+$range i 1..n
+template <$for i, [[GTEST_TEMPLATE_ T$i = NoneT]]>
+struct Templates {
+  typedef Templates$n<$for i, [[T$i]]> type;
+};
+
+template <>
+struct Templates<$for i, [[NoneT]]> {
+  typedef Templates0 type;
+};
+
+$range i 1..n-1
+$for i [[
+$range j 1..i
+$range k i+1..n
+template <$for j, [[GTEST_TEMPLATE_ T$j]]>
+struct Templates<$for j, [[T$j]]$for k[[, NoneT]]> {
+  typedef Templates$i<$for j, [[T$j]]> type;
+};
+
+]]
+
+// The TypeList template makes it possible to use either a single type
+// or a Types<...> list in TYPED_TEST_CASE() and
+// INSTANTIATE_TYPED_TEST_CASE_P().
+
+template <typename T>
+struct TypeList {
+  typedef Types1<T> type;
+};
+
+
+$range i 1..n
+template <$for i, [[typename T$i]]>
+struct TypeList<Types<$for i, [[T$i]]> > {
+  typedef typename Types<$for i, [[T$i]]>::type type;
+};
+
+#endif  // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
diff --git a/third_party/googletest/googletest/m4/acx_pthread.m4 b/third_party/googletest/googletest/m4/acx_pthread.m4
new file mode 100644
index 0000000..2cf20de
--- /dev/null
+++ b/third_party/googletest/googletest/m4/acx_pthread.m4
@@ -0,0 +1,363 @@
+# This was retrieved from
+#    http://svn.0pointer.de/viewvc/trunk/common/acx_pthread.m4?revision=1277&root=avahi
+# See also (perhaps for new versions?)
+#    http://svn.0pointer.de/viewvc/trunk/common/acx_pthread.m4?root=avahi
+#
+# We've rewritten the inconsistency check code (from avahi), to work
+# more broadly.  In particular, it no longer assumes ld accepts -zdefs.
+# This caused a restructing of the code, but the functionality has only
+# changed a little.
+
+dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+dnl
+dnl @summary figure out how to build C programs using POSIX threads
+dnl
+dnl This macro figures out how to build C programs using POSIX threads.
+dnl It sets the PTHREAD_LIBS output variable to the threads library and
+dnl linker flags, and the PTHREAD_CFLAGS output variable to any special
+dnl C compiler flags that are needed. (The user can also force certain
+dnl compiler flags/libs to be tested by setting these environment
+dnl variables.)
+dnl
+dnl Also sets PTHREAD_CC to any special C compiler that is needed for
+dnl multi-threaded programs (defaults to the value of CC otherwise).
+dnl (This is necessary on AIX to use the special cc_r compiler alias.)
+dnl
+dnl NOTE: You are assumed to not only compile your program with these
+dnl flags, but also link it with them as well. e.g. you should link
+dnl with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS
+dnl $LIBS
+dnl
+dnl If you are only building threads programs, you may wish to use
+dnl these variables in your default LIBS, CFLAGS, and CC:
+dnl
+dnl        LIBS="$PTHREAD_LIBS $LIBS"
+dnl        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+dnl        CC="$PTHREAD_CC"
+dnl
+dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute
+dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to
+dnl that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
+dnl
+dnl ACTION-IF-FOUND is a list of shell commands to run if a threads
+dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands to
+dnl run it if it is not found. If ACTION-IF-FOUND is not specified, the
+dnl default action will define HAVE_PTHREAD.
+dnl
+dnl Please let the authors know if this macro fails on any platform, or
+dnl if you have any other suggestions or comments. This macro was based
+dnl on work by SGJ on autoconf scripts for FFTW (www.fftw.org) (with
+dnl help from M. Frigo), as well as ac_pthread and hb_pthread macros
+dnl posted by Alejandro Forero Cuervo to the autoconf macro repository.
+dnl We are also grateful for the helpful feedback of numerous users.
+dnl
+dnl @category InstalledPackages
+dnl @author Steven G. Johnson <stevenj@alum.mit.edu>
+dnl @version 2006-05-29
+dnl @license GPLWithACException
+dnl 
+dnl Checks for GCC shared/pthread inconsistency based on work by
+dnl Marcin Owsiany <marcin@owsiany.pl>
+
+
+AC_DEFUN([ACX_PTHREAD], [
+AC_REQUIRE([AC_CANONICAL_HOST])
+AC_LANG_SAVE
+AC_LANG_C
+acx_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on True64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
+        save_CFLAGS="$CFLAGS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+        save_LIBS="$LIBS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
+        AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)
+        AC_MSG_RESULT($acx_pthread_ok)
+        if test x"$acx_pthread_ok" = xno; then
+                PTHREAD_LIBS=""
+                PTHREAD_CFLAGS=""
+        fi
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try.  Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all, and "pthread-config"
+# which is a program returning the flags for the Pth emulation library.
+
+acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
+
+# The ordering *is* (sometimes) important.  Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+#       other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
+# -pthreads: Solaris/gcc
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+#      doesn't hurt to check since this sometimes defines pthreads too;
+#      also defines -D_REENTRANT)
+#      ... -mt is also the pthreads flag for HP/aCC
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+# pthread-config: use pthread-config program (for GNU Pth library)
+
+case "${host_cpu}-${host_os}" in
+        *solaris*)
+
+        # On Solaris (at least, for some versions), libc contains stubbed
+        # (non-functional) versions of the pthreads routines, so link-based
+        # tests will erroneously succeed.  (We need to link with -pthreads/-mt/
+        # -lpthread.)  (The stubs are missing pthread_cleanup_push, or rather
+        # a function called by this macro, so we could check for that, but
+        # who knows whether they'll stub that too in a future libc.)  So,
+        # we'll just look for -pthreads and -lpthread first:
+
+        acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags"
+        ;;
+esac
+
+if test x"$acx_pthread_ok" = xno; then
+for flag in $acx_pthread_flags; do
+
+        case $flag in
+                none)
+                AC_MSG_CHECKING([whether pthreads work without any flags])
+                ;;
+
+                -*)
+                AC_MSG_CHECKING([whether pthreads work with $flag])
+                PTHREAD_CFLAGS="$flag"
+                ;;
+
+		pthread-config)
+		AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no)
+		if test x"$acx_pthread_config" = xno; then continue; fi
+		PTHREAD_CFLAGS="`pthread-config --cflags`"
+		PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+		;;
+
+                *)
+                AC_MSG_CHECKING([for the pthreads library -l$flag])
+                PTHREAD_LIBS="-l$flag"
+                ;;
+        esac
+
+        save_LIBS="$LIBS"
+        save_CFLAGS="$CFLAGS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+        # Check for various functions.  We must include pthread.h,
+        # since some functions may be macros.  (On the Sequent, we
+        # need a special flag -Kthread to make this header compile.)
+        # We check for pthread_join because it is in -lpthread on IRIX
+        # while pthread_create is in libc.  We check for pthread_attr_init
+        # due to DEC craziness with -lpthreads.  We check for
+        # pthread_cleanup_push because it is one of the few pthread
+        # functions on Solaris that doesn't have a non-functional libc stub.
+        # We try pthread_create on general principles.
+        AC_TRY_LINK([#include <pthread.h>],
+                    [pthread_t th; pthread_join(th, 0);
+                     pthread_attr_init(0); pthread_cleanup_push(0, 0);
+                     pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+                    [acx_pthread_ok=yes])
+
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+
+        AC_MSG_RESULT($acx_pthread_ok)
+        if test "x$acx_pthread_ok" = xyes; then
+                break;
+        fi
+
+        PTHREAD_LIBS=""
+        PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$acx_pthread_ok" = xyes; then
+        save_LIBS="$LIBS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        save_CFLAGS="$CFLAGS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+        # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
+	AC_MSG_CHECKING([for joinable pthread attribute])
+	attr_name=unknown
+	for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+	    AC_TRY_LINK([#include <pthread.h>], [int attr=$attr; return attr;],
+                        [attr_name=$attr; break])
+	done
+        AC_MSG_RESULT($attr_name)
+        if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
+            AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
+                               [Define to necessary symbol if this constant
+                                uses a non-standard name on your system.])
+        fi
+
+        AC_MSG_CHECKING([if more special flags are required for pthreads])
+        flag=no
+        case "${host_cpu}-${host_os}" in
+            *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
+            *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
+        esac
+        AC_MSG_RESULT(${flag})
+        if test "x$flag" != xno; then
+            PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
+        fi
+
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+        # More AIX lossage: must compile with xlc_r or cc_r
+	if test x"$GCC" != xyes; then
+          AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC})
+        else
+          PTHREAD_CC=$CC
+	fi
+
+	# The next part tries to detect GCC inconsistency with -shared on some
+	# architectures and systems. The problem is that in certain
+	# configurations, when -shared is specified, GCC "forgets" to
+	# internally use various flags which are still necessary.
+	
+	#
+	# Prepare the flags
+	#
+	save_CFLAGS="$CFLAGS"
+	save_LIBS="$LIBS"
+	save_CC="$CC"
+	
+	# Try with the flags determined by the earlier checks.
+	#
+	# -Wl,-z,defs forces link-time symbol resolution, so that the
+	# linking checks with -shared actually have any value
+	#
+	# FIXME: -fPIC is required for -shared on many architectures,
+	# so we specify it here, but the right way would probably be to
+	# properly detect whether it is actually required.
+	CFLAGS="-shared -fPIC -Wl,-z,defs $CFLAGS $PTHREAD_CFLAGS"
+	LIBS="$PTHREAD_LIBS $LIBS"
+	CC="$PTHREAD_CC"
+	
+	# In order not to create several levels of indentation, we test
+	# the value of "$done" until we find the cure or run out of ideas.
+	done="no"
+	
+	# First, make sure the CFLAGS we added are actually accepted by our
+	# compiler.  If not (and OS X's ld, for instance, does not accept -z),
+	# then we can't do this test.
+	if test x"$done" = xno; then
+	   AC_MSG_CHECKING([whether to check for GCC pthread/shared inconsistencies])
+	   AC_TRY_LINK(,, , [done=yes])
+	
+	   if test "x$done" = xyes ; then
+	      AC_MSG_RESULT([no])
+	   else
+	      AC_MSG_RESULT([yes])
+	   fi
+	fi
+	
+	if test x"$done" = xno; then
+	   AC_MSG_CHECKING([whether -pthread is sufficient with -shared])
+	   AC_TRY_LINK([#include <pthread.h>],
+	      [pthread_t th; pthread_join(th, 0);
+	      pthread_attr_init(0); pthread_cleanup_push(0, 0);
+	      pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+	      [done=yes])
+	   
+	   if test "x$done" = xyes; then
+	      AC_MSG_RESULT([yes])
+	   else
+	      AC_MSG_RESULT([no])
+	   fi
+	fi
+	
+	#
+	# Linux gcc on some architectures such as mips/mipsel forgets
+	# about -lpthread
+	#
+	if test x"$done" = xno; then
+	   AC_MSG_CHECKING([whether -lpthread fixes that])
+	   LIBS="-lpthread $PTHREAD_LIBS $save_LIBS"
+	   AC_TRY_LINK([#include <pthread.h>],
+	      [pthread_t th; pthread_join(th, 0);
+	      pthread_attr_init(0); pthread_cleanup_push(0, 0);
+	      pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+	      [done=yes])
+	
+	   if test "x$done" = xyes; then
+	      AC_MSG_RESULT([yes])
+	      PTHREAD_LIBS="-lpthread $PTHREAD_LIBS"
+	   else
+	      AC_MSG_RESULT([no])
+	   fi
+	fi
+	#
+	# FreeBSD 4.10 gcc forgets to use -lc_r instead of -lc
+	#
+	if test x"$done" = xno; then
+	   AC_MSG_CHECKING([whether -lc_r fixes that])
+	   LIBS="-lc_r $PTHREAD_LIBS $save_LIBS"
+	   AC_TRY_LINK([#include <pthread.h>],
+	       [pthread_t th; pthread_join(th, 0);
+	        pthread_attr_init(0); pthread_cleanup_push(0, 0);
+	        pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+	       [done=yes])
+	
+	   if test "x$done" = xyes; then
+	      AC_MSG_RESULT([yes])
+	      PTHREAD_LIBS="-lc_r $PTHREAD_LIBS"
+	   else
+	      AC_MSG_RESULT([no])
+	   fi
+	fi
+	if test x"$done" = xno; then
+	   # OK, we have run out of ideas
+	   AC_MSG_WARN([Impossible to determine how to use pthreads with shared libraries])
+	
+	   # so it's not safe to assume that we may use pthreads
+	   acx_pthread_ok=no
+	fi
+	
+	CFLAGS="$save_CFLAGS"
+	LIBS="$save_LIBS"
+	CC="$save_CC"
+else
+        PTHREAD_CC="$CC"
+fi
+
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(PTHREAD_CFLAGS)
+AC_SUBST(PTHREAD_CC)
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$acx_pthread_ok" = xyes; then
+        ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
+        :
+else
+        acx_pthread_ok=no
+        $2
+fi
+AC_LANG_RESTORE
+])dnl ACX_PTHREAD
diff --git a/third_party/googletest/googletest/m4/gtest.m4 b/third_party/googletest/googletest/m4/gtest.m4
new file mode 100644
index 0000000..6598ba7
--- /dev/null
+++ b/third_party/googletest/googletest/m4/gtest.m4
@@ -0,0 +1,74 @@
+dnl GTEST_LIB_CHECK([minimum version [,
+dnl                  action if found [,action if not found]]])
+dnl
+dnl Check for the presence of the Google Test library, optionally at a minimum
+dnl version, and indicate a viable version with the HAVE_GTEST flag. It defines
+dnl standard variables for substitution including GTEST_CPPFLAGS,
+dnl GTEST_CXXFLAGS, GTEST_LDFLAGS, and GTEST_LIBS. It also defines
+dnl GTEST_VERSION as the version of Google Test found. Finally, it provides
+dnl optional custom action slots in the event GTEST is found or not.
+AC_DEFUN([GTEST_LIB_CHECK],
+[
+dnl Provide a flag to enable or disable Google Test usage.
+AC_ARG_ENABLE([gtest],
+  [AS_HELP_STRING([--enable-gtest],
+                  [Enable tests using the Google C++ Testing Framework.
+                  (Default is enabled.)])],
+  [],
+  [enable_gtest=])
+AC_ARG_VAR([GTEST_CONFIG],
+           [The exact path of Google Test's 'gtest-config' script.])
+AC_ARG_VAR([GTEST_CPPFLAGS],
+           [C-like preprocessor flags for Google Test.])
+AC_ARG_VAR([GTEST_CXXFLAGS],
+           [C++ compile flags for Google Test.])
+AC_ARG_VAR([GTEST_LDFLAGS],
+           [Linker path and option flags for Google Test.])
+AC_ARG_VAR([GTEST_LIBS],
+           [Library linking flags for Google Test.])
+AC_ARG_VAR([GTEST_VERSION],
+           [The version of Google Test available.])
+HAVE_GTEST="no"
+AS_IF([test "x${enable_gtest}" != "xno"],
+  [AC_MSG_CHECKING([for 'gtest-config'])
+   AS_IF([test "x${enable_gtest}" != "xyes"],
+     [AS_IF([test -x "${enable_gtest}/scripts/gtest-config"],
+        [GTEST_CONFIG="${enable_gtest}/scripts/gtest-config"],
+        [GTEST_CONFIG="${enable_gtest}/bin/gtest-config"])
+      AS_IF([test -x "${GTEST_CONFIG}"], [],
+        [AC_MSG_RESULT([no])
+         AC_MSG_ERROR([dnl
+Unable to locate either a built or installed Google Test.
+The specific location '${enable_gtest}' was provided for a built or installed
+Google Test, but no 'gtest-config' script could be found at this location.])
+         ])],
+     [AC_PATH_PROG([GTEST_CONFIG], [gtest-config])])
+   AS_IF([test -x "${GTEST_CONFIG}"],
+     [AC_MSG_RESULT([${GTEST_CONFIG}])
+      m4_ifval([$1],
+        [_gtest_min_version="--min-version=$1"
+         AC_MSG_CHECKING([for Google Test at least version >= $1])],
+        [_gtest_min_version="--min-version=0"
+         AC_MSG_CHECKING([for Google Test])])
+      AS_IF([${GTEST_CONFIG} ${_gtest_min_version}],
+        [AC_MSG_RESULT([yes])
+         HAVE_GTEST='yes'],
+        [AC_MSG_RESULT([no])])],
+     [AC_MSG_RESULT([no])])
+   AS_IF([test "x${HAVE_GTEST}" = "xyes"],
+     [GTEST_CPPFLAGS=`${GTEST_CONFIG} --cppflags`
+      GTEST_CXXFLAGS=`${GTEST_CONFIG} --cxxflags`
+      GTEST_LDFLAGS=`${GTEST_CONFIG} --ldflags`
+      GTEST_LIBS=`${GTEST_CONFIG} --libs`
+      GTEST_VERSION=`${GTEST_CONFIG} --version`
+      AC_DEFINE([HAVE_GTEST],[1],[Defined when Google Test is available.])],
+     [AS_IF([test "x${enable_gtest}" = "xyes"],
+        [AC_MSG_ERROR([dnl
+Google Test was enabled, but no viable version could be found.])
+         ])])])
+AC_SUBST([HAVE_GTEST])
+AM_CONDITIONAL([HAVE_GTEST],[test "x$HAVE_GTEST" = "xyes"])
+AS_IF([test "x$HAVE_GTEST" = "xyes"],
+  [m4_ifval([$2], [$2])],
+  [m4_ifval([$3], [$3])])
+])
diff --git a/third_party/googletest/googletest/make/Makefile b/third_party/googletest/googletest/make/Makefile
new file mode 100644
index 0000000..9ac7449
--- /dev/null
+++ b/third_party/googletest/googletest/make/Makefile
@@ -0,0 +1,82 @@
+# A sample Makefile for building Google Test and using it in user
+# tests.  Please tweak it to suit your environment and project.  You
+# may want to move it to your project's root directory.
+#
+# SYNOPSIS:
+#
+#   make [all]  - makes everything.
+#   make TARGET - makes the given target.
+#   make clean  - removes all files generated by make.
+
+# Please tweak the following variable definitions as needed by your
+# project, except GTEST_HEADERS, which you can use in your own targets
+# but shouldn't modify.
+
+# Points to the root of Google Test, relative to where this file is.
+# Remember to tweak this if you move this file.
+GTEST_DIR = ..
+
+# Where to find user code.
+USER_DIR = ../samples
+
+# Flags passed to the preprocessor.
+# Set Google Test's header directory as a system directory, such that
+# the compiler doesn't generate warnings in Google Test headers.
+CPPFLAGS += -isystem $(GTEST_DIR)/include
+
+# Flags passed to the C++ compiler.
+CXXFLAGS += -g -Wall -Wextra -pthread
+
+# All tests produced by this Makefile.  Remember to add new tests you
+# created to the list.
+TESTS = sample1_unittest
+
+# All Google Test headers.  Usually you shouldn't change this
+# definition.
+GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \
+                $(GTEST_DIR)/include/gtest/internal/*.h
+
+# House-keeping build targets.
+
+all : $(TESTS)
+
+clean :
+	rm -f $(TESTS) gtest.a gtest_main.a *.o
+
+# Builds gtest.a and gtest_main.a.
+
+# Usually you shouldn't tweak such internal variables, indicated by a
+# trailing _.
+GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS)
+
+# For simplicity and to avoid depending on Google Test's
+# implementation details, the dependencies specified below are
+# conservative and not optimized.  This is fine as Google Test
+# compiles fast and for ordinary users its source rarely changes.
+gtest-all.o : $(GTEST_SRCS_)
+	$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
+            $(GTEST_DIR)/src/gtest-all.cc
+
+gtest_main.o : $(GTEST_SRCS_)
+	$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
+            $(GTEST_DIR)/src/gtest_main.cc
+
+gtest.a : gtest-all.o
+	$(AR) $(ARFLAGS) $@ $^
+
+gtest_main.a : gtest-all.o gtest_main.o
+	$(AR) $(ARFLAGS) $@ $^
+
+# Builds a sample test.  A test should link with either gtest.a or
+# gtest_main.a, depending on whether it defines its own main()
+# function.
+
+sample1.o : $(USER_DIR)/sample1.cc $(USER_DIR)/sample1.h $(GTEST_HEADERS)
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/sample1.cc
+
+sample1_unittest.o : $(USER_DIR)/sample1_unittest.cc \
+                     $(USER_DIR)/sample1.h $(GTEST_HEADERS)
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/sample1_unittest.cc
+
+sample1_unittest : sample1.o sample1_unittest.o gtest_main.a
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
diff --git a/third_party/googletest/googletest/msvc/gtest-md.sln b/third_party/googletest/googletest/msvc/gtest-md.sln
new file mode 100644
index 0000000..f7908da
--- /dev/null
+++ b/third_party/googletest/googletest/msvc/gtest-md.sln
@@ -0,0 +1,45 @@
+Microsoft Visual Studio Solution File, Format Version 8.00

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest-md", "gtest-md.vcproj", "{C8F6C172-56F2-4E76-B5FA-C3B423B31BE8}"

+	ProjectSection(ProjectDependencies) = postProject

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest_main-md", "gtest_main-md.vcproj", "{3AF54C8A-10BF-4332-9147-F68ED9862033}"

+	ProjectSection(ProjectDependencies) = postProject

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest_prod_test-md", "gtest_prod_test-md.vcproj", "{24848551-EF4F-47E8-9A9D-EA4D49BC3ECB}"

+	ProjectSection(ProjectDependencies) = postProject

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest_unittest-md", "gtest_unittest-md.vcproj", "{4D9FDFB5-986A-4139-823C-F4EE0ED481A2}"

+	ProjectSection(ProjectDependencies) = postProject

+	EndProjectSection

+EndProject

+Global

+	GlobalSection(SolutionConfiguration) = preSolution

+		Debug = Debug

+		Release = Release

+	EndGlobalSection

+	GlobalSection(ProjectConfiguration) = postSolution

+		{C8F6C172-56F2-4E76-B5FA-C3B423B31BE8}.Debug.ActiveCfg = Debug|Win32

+		{C8F6C172-56F2-4E76-B5FA-C3B423B31BE8}.Debug.Build.0 = Debug|Win32

+		{C8F6C172-56F2-4E76-B5FA-C3B423B31BE8}.Release.ActiveCfg = Release|Win32

+		{C8F6C172-56F2-4E76-B5FA-C3B423B31BE8}.Release.Build.0 = Release|Win32

+		{3AF54C8A-10BF-4332-9147-F68ED9862033}.Debug.ActiveCfg = Debug|Win32

+		{3AF54C8A-10BF-4332-9147-F68ED9862033}.Debug.Build.0 = Debug|Win32

+		{3AF54C8A-10BF-4332-9147-F68ED9862033}.Release.ActiveCfg = Release|Win32

+		{3AF54C8A-10BF-4332-9147-F68ED9862033}.Release.Build.0 = Release|Win32

+		{24848551-EF4F-47E8-9A9D-EA4D49BC3ECB}.Debug.ActiveCfg = Debug|Win32

+		{24848551-EF4F-47E8-9A9D-EA4D49BC3ECB}.Debug.Build.0 = Debug|Win32

+		{24848551-EF4F-47E8-9A9D-EA4D49BC3ECB}.Release.ActiveCfg = Release|Win32

+		{24848551-EF4F-47E8-9A9D-EA4D49BC3ECB}.Release.Build.0 = Release|Win32

+		{4D9FDFB5-986A-4139-823C-F4EE0ED481A2}.Debug.ActiveCfg = Debug|Win32

+		{4D9FDFB5-986A-4139-823C-F4EE0ED481A2}.Debug.Build.0 = Debug|Win32

+		{4D9FDFB5-986A-4139-823C-F4EE0ED481A2}.Release.ActiveCfg = Release|Win32

+		{4D9FDFB5-986A-4139-823C-F4EE0ED481A2}.Release.Build.0 = Release|Win32

+	EndGlobalSection

+	GlobalSection(ExtensibilityGlobals) = postSolution

+	EndGlobalSection

+	GlobalSection(ExtensibilityAddIns) = postSolution

+	EndGlobalSection

+EndGlobal

diff --git a/third_party/googletest/googletest/msvc/gtest-md.vcproj b/third_party/googletest/googletest/msvc/gtest-md.vcproj
new file mode 100644
index 0000000..1c35c3a
--- /dev/null
+++ b/third_party/googletest/googletest/msvc/gtest-md.vcproj
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="7.10"

+	Name="gtest-md"

+	ProjectGUID="{C8F6C172-56F2-4E76-B5FA-C3B423B31BE8}"

+	Keyword="Win32Proj">

+	<Platforms>

+		<Platform

+			Name="Win32"/>

+	</Platforms>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="$(SolutionName)/$(ConfigurationName)"

+			IntermediateDirectory="$(OutDir)/$(ProjectName)"

+			ConfigurationType="4"

+			CharacterSet="2"

+			ReferencesPath="">

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="0"

+				PreprocessorDefinitions="WIN32;_DEBUG;_LIB"

+				MinimalRebuild="TRUE"

+				BasicRuntimeChecks="3"

+				RuntimeLibrary="3"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="FALSE"

+				DebugInformationFormat="4"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLibrarianTool"

+				OutputFile="$(OutDir)/gtestd.lib"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"/>

+			<Tool

+				Name="VCManagedWrapperGeneratorTool"/>

+			<Tool

+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory="$(SolutionName)/$(ConfigurationName)"

+			IntermediateDirectory="$(OutDir)/$(ProjectName)"

+			ConfigurationType="4"

+			CharacterSet="2"

+			ReferencesPath="&quot;..\include&quot;;&quot;..&quot;">

+			<Tool

+				Name="VCCLCompilerTool"

+				PreprocessorDefinitions="WIN32;NDEBUG;_LIB"

+				RuntimeLibrary="2"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="FALSE"

+				DebugInformationFormat="3"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLibrarianTool"

+				OutputFile="$(OutDir)/gtest.lib"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"/>

+			<Tool

+				Name="VCManagedWrapperGeneratorTool"/>

+			<Tool

+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>

+		</Configuration>

+	</Configurations>

+	<References>

+	</References>

+	<Files>

+		<Filter

+			Name="Source Files"

+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"

+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">

+			<File

+				RelativePath="..\src\gtest-all.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"/>

+				</FileConfiguration>

+			</File>

+		</Filter>

+		<Filter

+			Name="Header Files"

+			Filter="h;hpp;hxx;hm;inl;inc;xsd"

+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">

+		</Filter>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/third_party/googletest/googletest/msvc/gtest.sln b/third_party/googletest/googletest/msvc/gtest.sln
new file mode 100644
index 0000000..ef4b057
--- /dev/null
+++ b/third_party/googletest/googletest/msvc/gtest.sln
@@ -0,0 +1,45 @@
+Microsoft Visual Studio Solution File, Format Version 8.00

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest", "gtest.vcproj", "{C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}"

+	ProjectSection(ProjectDependencies) = postProject

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest_main", "gtest_main.vcproj", "{3AF54C8A-10BF-4332-9147-F68ED9862032}"

+	ProjectSection(ProjectDependencies) = postProject

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest_unittest", "gtest_unittest.vcproj", "{4D9FDFB5-986A-4139-823C-F4EE0ED481A1}"

+	ProjectSection(ProjectDependencies) = postProject

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest_prod_test", "gtest_prod_test.vcproj", "{24848551-EF4F-47E8-9A9D-EA4D49BC3ECA}"

+	ProjectSection(ProjectDependencies) = postProject

+	EndProjectSection

+EndProject

+Global

+	GlobalSection(SolutionConfiguration) = preSolution

+		Debug = Debug

+		Release = Release

+	EndGlobalSection

+	GlobalSection(ProjectConfiguration) = postSolution

+		{C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Debug.ActiveCfg = Debug|Win32

+		{C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Debug.Build.0 = Debug|Win32

+		{C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Release.ActiveCfg = Release|Win32

+		{C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Release.Build.0 = Release|Win32

+		{3AF54C8A-10BF-4332-9147-F68ED9862032}.Debug.ActiveCfg = Debug|Win32

+		{3AF54C8A-10BF-4332-9147-F68ED9862032}.Debug.Build.0 = Debug|Win32

+		{3AF54C8A-10BF-4332-9147-F68ED9862032}.Release.ActiveCfg = Release|Win32

+		{3AF54C8A-10BF-4332-9147-F68ED9862032}.Release.Build.0 = Release|Win32

+		{4D9FDFB5-986A-4139-823C-F4EE0ED481A1}.Debug.ActiveCfg = Debug|Win32

+		{4D9FDFB5-986A-4139-823C-F4EE0ED481A1}.Debug.Build.0 = Debug|Win32

+		{4D9FDFB5-986A-4139-823C-F4EE0ED481A1}.Release.ActiveCfg = Release|Win32

+		{4D9FDFB5-986A-4139-823C-F4EE0ED481A1}.Release.Build.0 = Release|Win32

+		{24848551-EF4F-47E8-9A9D-EA4D49BC3ECA}.Debug.ActiveCfg = Debug|Win32

+		{24848551-EF4F-47E8-9A9D-EA4D49BC3ECA}.Debug.Build.0 = Debug|Win32

+		{24848551-EF4F-47E8-9A9D-EA4D49BC3ECA}.Release.ActiveCfg = Release|Win32

+		{24848551-EF4F-47E8-9A9D-EA4D49BC3ECA}.Release.Build.0 = Release|Win32

+	EndGlobalSection

+	GlobalSection(ExtensibilityGlobals) = postSolution

+	EndGlobalSection

+	GlobalSection(ExtensibilityAddIns) = postSolution

+	EndGlobalSection

+EndGlobal

diff --git a/third_party/googletest/googletest/msvc/gtest.vcproj b/third_party/googletest/googletest/msvc/gtest.vcproj
new file mode 100644
index 0000000..a8373ce
--- /dev/null
+++ b/third_party/googletest/googletest/msvc/gtest.vcproj
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="7.10"

+	Name="gtest"

+	ProjectGUID="{C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}"

+	Keyword="Win32Proj">

+	<Platforms>

+		<Platform

+			Name="Win32"/>

+	</Platforms>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="$(SolutionName)/$(ConfigurationName)"

+			IntermediateDirectory="$(OutDir)/$(ProjectName)"

+			ConfigurationType="4"

+			CharacterSet="2"

+			ReferencesPath="">

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="0"

+				PreprocessorDefinitions="WIN32;_DEBUG;_LIB"

+				MinimalRebuild="TRUE"

+				BasicRuntimeChecks="3"

+				RuntimeLibrary="5"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="FALSE"

+				DebugInformationFormat="4"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLibrarianTool"

+				OutputFile="$(OutDir)/gtestd.lib"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"/>

+			<Tool

+				Name="VCManagedWrapperGeneratorTool"/>

+			<Tool

+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory="$(SolutionName)/$(ConfigurationName)"

+			IntermediateDirectory="$(OutDir)/$(ProjectName)"

+			ConfigurationType="4"

+			CharacterSet="2"

+			ReferencesPath="&quot;..\include&quot;;&quot;..&quot;">

+			<Tool

+				Name="VCCLCompilerTool"

+				PreprocessorDefinitions="WIN32;NDEBUG;_LIB"

+				RuntimeLibrary="4"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="FALSE"

+				DebugInformationFormat="3"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLibrarianTool"

+				OutputFile="$(OutDir)/gtest.lib"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"/>

+			<Tool

+				Name="VCManagedWrapperGeneratorTool"/>

+			<Tool

+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>

+		</Configuration>

+	</Configurations>

+	<References>

+	</References>

+	<Files>

+		<Filter

+			Name="Source Files"

+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"

+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">

+			<File

+				RelativePath="..\src\gtest-all.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"/>

+				</FileConfiguration>

+			</File>

+		</Filter>

+		<Filter

+			Name="Header Files"

+			Filter="h;hpp;hxx;hm;inl;inc;xsd"

+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">

+		</Filter>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/third_party/googletest/googletest/msvc/gtest_main-md.vcproj b/third_party/googletest/googletest/msvc/gtest_main-md.vcproj
new file mode 100644
index 0000000..b5379fe
--- /dev/null
+++ b/third_party/googletest/googletest/msvc/gtest_main-md.vcproj
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="7.10"

+	Name="gtest_main-md"

+	ProjectGUID="{3AF54C8A-10BF-4332-9147-F68ED9862033}"

+	Keyword="Win32Proj">

+	<Platforms>

+		<Platform

+			Name="Win32"/>

+	</Platforms>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="$(SolutionName)/$(ConfigurationName)"

+			IntermediateDirectory="$(OutDir)/$(ProjectName)"

+			ConfigurationType="4"

+			CharacterSet="2"

+			ReferencesPath="">

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="0"

+				PreprocessorDefinitions="WIN32;_DEBUG;_LIB"

+				MinimalRebuild="TRUE"

+				BasicRuntimeChecks="3"

+				RuntimeLibrary="3"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="FALSE"

+				DebugInformationFormat="4"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLibrarianTool"

+				OutputFile="$(OutDir)/$(ProjectName)d.lib"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"/>

+			<Tool

+				Name="VCManagedWrapperGeneratorTool"/>

+			<Tool

+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory="$(SolutionName)/$(ConfigurationName)"

+			IntermediateDirectory="$(OutDir)/$(ProjectName)"

+			ConfigurationType="4"

+			CharacterSet="2"

+			ReferencesPath="&quot;..\include&quot;;&quot;..&quot;">

+			<Tool

+				Name="VCCLCompilerTool"

+				PreprocessorDefinitions="WIN32;NDEBUG;_LIB"

+				RuntimeLibrary="2"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="FALSE"

+				DebugInformationFormat="3"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLibrarianTool"

+				OutputFile="$(OutDir)/$(ProjectName).lib"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"/>

+			<Tool

+				Name="VCManagedWrapperGeneratorTool"/>

+			<Tool

+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>

+		</Configuration>

+	</Configurations>

+	<References>

+		<ProjectReference

+			ReferencedProjectIdentifier="{C8F6C172-56F2-4E76-B5FA-C3B423B31BE8}"

+			Name="gtest-md"/>

+	</References>

+	<Files>

+		<Filter

+			Name="Source Files"

+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"

+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">

+			<File

+				RelativePath="..\src\gtest_main.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"/>

+				</FileConfiguration>

+			</File>

+		</Filter>

+		<Filter

+			Name="Header Files"

+			Filter="h;hpp;hxx;hm;inl;inc;xsd"

+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">

+		</Filter>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/third_party/googletest/googletest/msvc/gtest_main.vcproj b/third_party/googletest/googletest/msvc/gtest_main.vcproj
new file mode 100644
index 0000000..e8b763c
--- /dev/null
+++ b/third_party/googletest/googletest/msvc/gtest_main.vcproj
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="7.10"

+	Name="gtest_main"

+	ProjectGUID="{3AF54C8A-10BF-4332-9147-F68ED9862032}"

+	Keyword="Win32Proj">

+	<Platforms>

+		<Platform

+			Name="Win32"/>

+	</Platforms>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="$(SolutionName)/$(ConfigurationName)"

+			IntermediateDirectory="$(OutDir)/$(ProjectName)"

+			ConfigurationType="4"

+			CharacterSet="2"

+			ReferencesPath="">

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="0"

+				PreprocessorDefinitions="WIN32;_DEBUG;_LIB"

+				MinimalRebuild="TRUE"

+				BasicRuntimeChecks="3"

+				RuntimeLibrary="5"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="FALSE"

+				DebugInformationFormat="4"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLibrarianTool"

+				OutputFile="$(OutDir)/$(ProjectName)d.lib"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"/>

+			<Tool

+				Name="VCManagedWrapperGeneratorTool"/>

+			<Tool

+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory="$(SolutionName)/$(ConfigurationName)"

+			IntermediateDirectory="$(OutDir)/$(ProjectName)"

+			ConfigurationType="4"

+			CharacterSet="2"

+			ReferencesPath="&quot;..\include&quot;;&quot;..&quot;">

+			<Tool

+				Name="VCCLCompilerTool"

+				PreprocessorDefinitions="WIN32;NDEBUG;_LIB"

+				RuntimeLibrary="4"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="FALSE"

+				DebugInformationFormat="3"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLibrarianTool"

+				OutputFile="$(OutDir)/$(ProjectName).lib"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"/>

+			<Tool

+				Name="VCManagedWrapperGeneratorTool"/>

+			<Tool

+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>

+		</Configuration>

+	</Configurations>

+	<References>

+		<ProjectReference

+			ReferencedProjectIdentifier="{C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}"

+			Name="gtest"/>

+	</References>

+	<Files>

+		<Filter

+			Name="Source Files"

+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"

+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">

+			<File

+				RelativePath="..\src\gtest_main.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"/>

+				</FileConfiguration>

+			</File>

+		</Filter>

+		<Filter

+			Name="Header Files"

+			Filter="h;hpp;hxx;hm;inl;inc;xsd"

+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">

+		</Filter>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/third_party/googletest/googletest/msvc/gtest_prod_test-md.vcproj b/third_party/googletest/googletest/msvc/gtest_prod_test-md.vcproj
new file mode 100644
index 0000000..05b05d9
--- /dev/null
+++ b/third_party/googletest/googletest/msvc/gtest_prod_test-md.vcproj
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="7.10"

+	Name="gtest_prod_test-md"

+	ProjectGUID="{24848551-EF4F-47E8-9A9D-EA4D49BC3ECB}"

+	Keyword="Win32Proj">

+	<Platforms>

+		<Platform

+			Name="Win32"/>

+	</Platforms>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="$(SolutionName)/$(ConfigurationName)"

+			IntermediateDirectory="$(OutDir)/$(ProjectName)"

+			ConfigurationType="1"

+			CharacterSet="2">

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="0"

+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"

+				MinimalRebuild="TRUE"

+				BasicRuntimeChecks="3"

+				RuntimeLibrary="3"

+				UsePrecompiledHeader="3"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="FALSE"

+				DebugInformationFormat="4"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLinkerTool"

+				OutputFile="$(OutDir)/gtest_prod_test.exe"

+				LinkIncremental="2"

+				GenerateDebugInformation="TRUE"

+				ProgramDatabaseFile="$(OutDir)/gtest_prod_test.pdb"

+				SubSystem="1"

+				TargetMachine="1"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"/>

+			<Tool

+				Name="VCWebDeploymentTool"/>

+			<Tool

+				Name="VCManagedWrapperGeneratorTool"/>

+			<Tool

+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory="$(SolutionName)/$(ConfigurationName)"

+			IntermediateDirectory="$(OutDir)/$(ProjectName)"

+			ConfigurationType="1"

+			CharacterSet="2">

+			<Tool

+				Name="VCCLCompilerTool"

+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"

+				RuntimeLibrary="2"

+				UsePrecompiledHeader="3"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="FALSE"

+				DebugInformationFormat="3"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLinkerTool"

+				OutputFile="$(OutDir)/gtest_prod_test.exe"

+				LinkIncremental="1"

+				GenerateDebugInformation="TRUE"

+				SubSystem="1"

+				OptimizeReferences="2"

+				EnableCOMDATFolding="2"

+				TargetMachine="1"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"/>

+			<Tool

+				Name="VCWebDeploymentTool"/>

+			<Tool

+				Name="VCManagedWrapperGeneratorTool"/>

+			<Tool

+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>

+		</Configuration>

+	</Configurations>

+	<References>

+		<ProjectReference

+			ReferencedProjectIdentifier="{3AF54C8A-10BF-4332-9147-F68ED9862033}"

+			Name="gtest_main-md"/>

+	</References>

+	<Files>

+		<Filter

+			Name="Source Files"

+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"

+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">

+			<File

+				RelativePath="..\test\gtest_prod_test.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"

+						UsePrecompiledHeader="0"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"

+						UsePrecompiledHeader="0"/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath="..\test\production.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"

+						UsePrecompiledHeader="0"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"

+						UsePrecompiledHeader="0"/>

+				</FileConfiguration>

+			</File>

+		</Filter>

+		<Filter

+			Name="Header Files"

+			Filter="h;hpp;hxx;hm;inl;inc;xsd"

+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">

+			<File

+				RelativePath="..\test\production.h">

+			</File>

+		</Filter>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/third_party/googletest/googletest/msvc/gtest_prod_test.vcproj b/third_party/googletest/googletest/msvc/gtest_prod_test.vcproj
new file mode 100644
index 0000000..6d7a2f0
--- /dev/null
+++ b/third_party/googletest/googletest/msvc/gtest_prod_test.vcproj
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="7.10"

+	Name="gtest_prod_test"

+	ProjectGUID="{24848551-EF4F-47E8-9A9D-EA4D49BC3ECA}"

+	Keyword="Win32Proj">

+	<Platforms>

+		<Platform

+			Name="Win32"/>

+	</Platforms>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="$(SolutionName)/$(ConfigurationName)"

+			IntermediateDirectory="$(OutDir)/$(ProjectName)"

+			ConfigurationType="1"

+			CharacterSet="2">

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="0"

+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"

+				MinimalRebuild="TRUE"

+				BasicRuntimeChecks="3"

+				RuntimeLibrary="5"

+				UsePrecompiledHeader="3"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="FALSE"

+				DebugInformationFormat="4"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLinkerTool"

+				OutputFile="$(OutDir)/gtest_prod_test.exe"

+				LinkIncremental="2"

+				GenerateDebugInformation="TRUE"

+				ProgramDatabaseFile="$(OutDir)/gtest_prod_test.pdb"

+				SubSystem="1"

+				TargetMachine="1"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"/>

+			<Tool

+				Name="VCWebDeploymentTool"/>

+			<Tool

+				Name="VCManagedWrapperGeneratorTool"/>

+			<Tool

+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory="$(SolutionName)/$(ConfigurationName)"

+			IntermediateDirectory="$(OutDir)/$(ProjectName)"

+			ConfigurationType="1"

+			CharacterSet="2">

+			<Tool

+				Name="VCCLCompilerTool"

+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"

+				RuntimeLibrary="4"

+				UsePrecompiledHeader="3"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="FALSE"

+				DebugInformationFormat="3"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLinkerTool"

+				OutputFile="$(OutDir)/gtest_prod_test.exe"

+				LinkIncremental="1"

+				GenerateDebugInformation="TRUE"

+				SubSystem="1"

+				OptimizeReferences="2"

+				EnableCOMDATFolding="2"

+				TargetMachine="1"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"/>

+			<Tool

+				Name="VCWebDeploymentTool"/>

+			<Tool

+				Name="VCManagedWrapperGeneratorTool"/>

+			<Tool

+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>

+		</Configuration>

+	</Configurations>

+	<References>

+		<ProjectReference

+			ReferencedProjectIdentifier="{3AF54C8A-10BF-4332-9147-F68ED9862032}"

+			Name="gtest_main"/>

+	</References>

+	<Files>

+		<Filter

+			Name="Source Files"

+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"

+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">

+			<File

+				RelativePath="..\test\gtest_prod_test.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"

+						UsePrecompiledHeader="0"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"

+						UsePrecompiledHeader="0"/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath="..\test\production.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"

+						UsePrecompiledHeader="0"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"

+						UsePrecompiledHeader="0"/>

+				</FileConfiguration>

+			</File>

+		</Filter>

+		<Filter

+			Name="Header Files"

+			Filter="h;hpp;hxx;hm;inl;inc;xsd"

+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">

+			<File

+				RelativePath="..\test\production.h">

+			</File>

+		</Filter>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/third_party/googletest/googletest/msvc/gtest_unittest-md.vcproj b/third_party/googletest/googletest/msvc/gtest_unittest-md.vcproj
new file mode 100644
index 0000000..38a5e56
--- /dev/null
+++ b/third_party/googletest/googletest/msvc/gtest_unittest-md.vcproj
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="7.10"

+	Name="gtest_unittest-md"

+	ProjectGUID="{4D9FDFB5-986A-4139-823C-F4EE0ED481A2}"

+	Keyword="Win32Proj">

+	<Platforms>

+		<Platform

+			Name="Win32"/>

+	</Platforms>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="$(SolutionName)/$(ConfigurationName)"

+			IntermediateDirectory="$(OutDir)/$(ProjectName)"

+			ConfigurationType="1"

+			CharacterSet="2">

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="0"

+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"

+				MinimalRebuild="TRUE"

+				BasicRuntimeChecks="3"

+				RuntimeLibrary="3"

+				UsePrecompiledHeader="3"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="FALSE"

+				DebugInformationFormat="4"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLinkerTool"

+				OutputFile="$(OutDir)/gtest_unittest.exe"

+				LinkIncremental="2"

+				GenerateDebugInformation="TRUE"

+				ProgramDatabaseFile="$(OutDir)/gtest_unittest.pdb"

+				SubSystem="1"

+				TargetMachine="1"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"/>

+			<Tool

+				Name="VCWebDeploymentTool"/>

+			<Tool

+				Name="VCManagedWrapperGeneratorTool"/>

+			<Tool

+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory="$(SolutionName)/$(ConfigurationName)"

+			IntermediateDirectory="$(OutDir)/$(ProjectName)"

+			ConfigurationType="1"

+			CharacterSet="2">

+			<Tool

+				Name="VCCLCompilerTool"

+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"

+				RuntimeLibrary="2"

+				UsePrecompiledHeader="3"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="FALSE"

+				DebugInformationFormat="3"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLinkerTool"

+				OutputFile="$(OutDir)/gtest_unittest.exe"

+				LinkIncremental="1"

+				GenerateDebugInformation="TRUE"

+				SubSystem="1"

+				OptimizeReferences="2"

+				EnableCOMDATFolding="2"

+				TargetMachine="1"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"/>

+			<Tool

+				Name="VCWebDeploymentTool"/>

+			<Tool

+				Name="VCManagedWrapperGeneratorTool"/>

+			<Tool

+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>

+		</Configuration>

+	</Configurations>

+	<References>

+		<ProjectReference

+			ReferencedProjectIdentifier="{3AF54C8A-10BF-4332-9147-F68ED9862033}"

+			Name="gtest_main-md"/>

+	</References>

+	<Files>

+		<Filter

+			Name="Source Files"

+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"

+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">

+			<File

+				RelativePath="..\test\gtest_unittest.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						Optimization="1"

+						AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"

+						BasicRuntimeChecks="0"

+						UsePrecompiledHeader="0"

+						DebugInformationFormat="3"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"

+						UsePrecompiledHeader="0"/>

+				</FileConfiguration>

+			</File>

+		</Filter>

+		<Filter

+			Name="Header Files"

+			Filter="h;hpp;hxx;hm;inl;inc;xsd"

+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">

+		</Filter>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/third_party/googletest/googletest/msvc/gtest_unittest.vcproj b/third_party/googletest/googletest/msvc/gtest_unittest.vcproj
new file mode 100644
index 0000000..cb1f52b
--- /dev/null
+++ b/third_party/googletest/googletest/msvc/gtest_unittest.vcproj
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="7.10"

+	Name="gtest_unittest"

+	ProjectGUID="{4D9FDFB5-986A-4139-823C-F4EE0ED481A1}"

+	Keyword="Win32Proj">

+	<Platforms>

+		<Platform

+			Name="Win32"/>

+	</Platforms>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="$(SolutionName)/$(ConfigurationName)"

+			IntermediateDirectory="$(OutDir)/$(ProjectName)"

+			ConfigurationType="1"

+			CharacterSet="2">

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="0"

+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"

+				MinimalRebuild="TRUE"

+				BasicRuntimeChecks="3"

+				RuntimeLibrary="5"

+				UsePrecompiledHeader="3"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="FALSE"

+				DebugInformationFormat="4"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLinkerTool"

+				OutputFile="$(OutDir)/gtest_unittest.exe"

+				LinkIncremental="2"

+				GenerateDebugInformation="TRUE"

+				ProgramDatabaseFile="$(OutDir)/gtest_unittest.pdb"

+				SubSystem="1"

+				TargetMachine="1"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"/>

+			<Tool

+				Name="VCWebDeploymentTool"/>

+			<Tool

+				Name="VCManagedWrapperGeneratorTool"/>

+			<Tool

+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory="$(SolutionName)/$(ConfigurationName)"

+			IntermediateDirectory="$(OutDir)/$(ProjectName)"

+			ConfigurationType="1"

+			CharacterSet="2">

+			<Tool

+				Name="VCCLCompilerTool"

+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"

+				RuntimeLibrary="4"

+				UsePrecompiledHeader="3"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="FALSE"

+				DebugInformationFormat="3"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLinkerTool"

+				OutputFile="$(OutDir)/gtest_unittest.exe"

+				LinkIncremental="1"

+				GenerateDebugInformation="TRUE"

+				SubSystem="1"

+				OptimizeReferences="2"

+				EnableCOMDATFolding="2"

+				TargetMachine="1"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"/>

+			<Tool

+				Name="VCWebDeploymentTool"/>

+			<Tool

+				Name="VCManagedWrapperGeneratorTool"/>

+			<Tool

+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>

+		</Configuration>

+	</Configurations>

+	<References>

+		<ProjectReference

+			ReferencedProjectIdentifier="{3AF54C8A-10BF-4332-9147-F68ED9862032}"

+			Name="gtest_main"/>

+	</References>

+	<Files>

+		<Filter

+			Name="Source Files"

+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"

+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">

+			<File

+				RelativePath="..\test\gtest_unittest.cc">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						Optimization="1"

+						AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"

+						BasicRuntimeChecks="0"

+						UsePrecompiledHeader="0"

+						DebugInformationFormat="3"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"

+						UsePrecompiledHeader="0"/>

+				</FileConfiguration>

+			</File>

+		</Filter>

+		<Filter

+			Name="Header Files"

+			Filter="h;hpp;hxx;hm;inl;inc;xsd"

+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">

+		</Filter>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/third_party/googletest/googletest/samples/prime_tables.h b/third_party/googletest/googletest/samples/prime_tables.h
new file mode 100644
index 0000000..92ce16a
--- /dev/null
+++ b/third_party/googletest/googletest/samples/prime_tables.h
@@ -0,0 +1,123 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+// Author: vladl@google.com (Vlad Losev)
+
+// This provides interface PrimeTable that determines whether a number is a
+// prime and determines a next prime number. This interface is used
+// in Google Test samples demonstrating use of parameterized tests.
+
+#ifndef GTEST_SAMPLES_PRIME_TABLES_H_
+#define GTEST_SAMPLES_PRIME_TABLES_H_
+
+#include <algorithm>
+
+// The prime table interface.
+class PrimeTable {
+ public:
+  virtual ~PrimeTable() {}
+
+  // Returns true iff n is a prime number.
+  virtual bool IsPrime(int n) const = 0;
+
+  // Returns the smallest prime number greater than p; or returns -1
+  // if the next prime is beyond the capacity of the table.
+  virtual int GetNextPrime(int p) const = 0;
+};
+
+// Implementation #1 calculates the primes on-the-fly.
+class OnTheFlyPrimeTable : public PrimeTable {
+ public:
+  virtual bool IsPrime(int n) const {
+    if (n <= 1) return false;
+
+    for (int i = 2; i*i <= n; i++) {
+      // n is divisible by an integer other than 1 and itself.
+      if ((n % i) == 0) return false;
+    }
+
+    return true;
+  }
+
+  virtual int GetNextPrime(int p) const {
+    for (int n = p + 1; n > 0; n++) {
+      if (IsPrime(n)) return n;
+    }
+
+    return -1;
+  }
+};
+
+// Implementation #2 pre-calculates the primes and stores the result
+// in an array.
+class PreCalculatedPrimeTable : public PrimeTable {
+ public:
+  // 'max' specifies the maximum number the prime table holds.
+  explicit PreCalculatedPrimeTable(int max)
+      : is_prime_size_(max + 1), is_prime_(new bool[max + 1]) {
+    CalculatePrimesUpTo(max);
+  }
+  virtual ~PreCalculatedPrimeTable() { delete[] is_prime_; }
+
+  virtual bool IsPrime(int n) const {
+    return 0 <= n && n < is_prime_size_ && is_prime_[n];
+  }
+
+  virtual int GetNextPrime(int p) const {
+    for (int n = p + 1; n < is_prime_size_; n++) {
+      if (is_prime_[n]) return n;
+    }
+
+    return -1;
+  }
+
+ private:
+  void CalculatePrimesUpTo(int max) {
+    ::std::fill(is_prime_, is_prime_ + is_prime_size_, true);
+    is_prime_[0] = is_prime_[1] = false;
+
+    for (int i = 2; i <= max; i++) {
+      if (!is_prime_[i]) continue;
+
+      // Marks all multiples of i (except i itself) as non-prime.
+      for (int j = 2*i; j <= max; j += i) {
+        is_prime_[j] = false;
+      }
+    }
+  }
+
+  const int is_prime_size_;
+  bool* const is_prime_;
+
+  // Disables compiler warning "assignment operator could not be generated."
+  void operator=(const PreCalculatedPrimeTable& rhs);
+};
+
+#endif  // GTEST_SAMPLES_PRIME_TABLES_H_
diff --git a/third_party/googletest/googletest/samples/sample1.cc b/third_party/googletest/googletest/samples/sample1.cc
new file mode 100644
index 0000000..f171e26
--- /dev/null
+++ b/third_party/googletest/googletest/samples/sample1.cc
@@ -0,0 +1,68 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A sample program demonstrating using Google C++ testing framework.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include "sample1.h"
+
+// Returns n! (the factorial of n).  For negative n, n! is defined to be 1.
+int Factorial(int n) {
+  int result = 1;
+  for (int i = 1; i <= n; i++) {
+    result *= i;
+  }
+
+  return result;
+}
+
+// Returns true iff n is a prime number.
+bool IsPrime(int n) {
+  // Trivial case 1: small numbers
+  if (n <= 1) return false;
+
+  // Trivial case 2: even numbers
+  if (n % 2 == 0) return n == 2;
+
+  // Now, we have that n is odd and n >= 3.
+
+  // Try to divide n by every odd number i, starting from 3
+  for (int i = 3; ; i += 2) {
+    // We only have to try i up to the squre root of n
+    if (i > n/i) break;
+
+    // Now, we have i <= n/i < n.
+    // If n is divisible by i, n is not prime.
+    if (n % i == 0) return false;
+  }
+
+  // n has no integer factor in the range (1, n), and thus is prime.
+  return true;
+}
diff --git a/third_party/googletest/googletest/samples/sample1.h b/third_party/googletest/googletest/samples/sample1.h
new file mode 100644
index 0000000..3dfeb98
--- /dev/null
+++ b/third_party/googletest/googletest/samples/sample1.h
@@ -0,0 +1,43 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A sample program demonstrating using Google C++ testing framework.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#ifndef GTEST_SAMPLES_SAMPLE1_H_
+#define GTEST_SAMPLES_SAMPLE1_H_
+
+// Returns n! (the factorial of n).  For negative n, n! is defined to be 1.
+int Factorial(int n);
+
+// Returns true iff n is a prime number.
+bool IsPrime(int n);
+
+#endif  // GTEST_SAMPLES_SAMPLE1_H_
diff --git a/third_party/googletest/googletest/samples/sample10_unittest.cc b/third_party/googletest/googletest/samples/sample10_unittest.cc
new file mode 100644
index 0000000..0051cd5
--- /dev/null
+++ b/third_party/googletest/googletest/samples/sample10_unittest.cc
@@ -0,0 +1,144 @@
+// Copyright 2009 Google Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vladl@google.com (Vlad Losev)
+
+// This sample shows how to use Google Test listener API to implement
+// a primitive leak checker.
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "gtest/gtest.h"
+
+using ::testing::EmptyTestEventListener;
+using ::testing::InitGoogleTest;
+using ::testing::Test;
+using ::testing::TestCase;
+using ::testing::TestEventListeners;
+using ::testing::TestInfo;
+using ::testing::TestPartResult;
+using ::testing::UnitTest;
+
+namespace {
+
+// We will track memory used by this class.
+class Water {
+ public:
+  // Normal Water declarations go here.
+
+  // operator new and operator delete help us control water allocation.
+  void* operator new(size_t allocation_size) {
+    allocated_++;
+    return malloc(allocation_size);
+  }
+
+  void operator delete(void* block, size_t /* allocation_size */) {
+    allocated_--;
+    free(block);
+  }
+
+  static int allocated() { return allocated_; }
+
+ private:
+  static int allocated_;
+};
+
+int Water::allocated_ = 0;
+
+// This event listener monitors how many Water objects are created and
+// destroyed by each test, and reports a failure if a test leaks some Water
+// objects. It does this by comparing the number of live Water objects at
+// the beginning of a test and at the end of a test.
+class LeakChecker : public EmptyTestEventListener {
+ private:
+  // Called before a test starts.
+  virtual void OnTestStart(const TestInfo& /* test_info */) {
+    initially_allocated_ = Water::allocated();
+  }
+
+  // Called after a test ends.
+  virtual void OnTestEnd(const TestInfo& /* test_info */) {
+    int difference = Water::allocated() - initially_allocated_;
+
+    // You can generate a failure in any event handler except
+    // OnTestPartResult. Just use an appropriate Google Test assertion to do
+    // it.
+    EXPECT_LE(difference, 0) << "Leaked " << difference << " unit(s) of Water!";
+  }
+
+  int initially_allocated_;
+};
+
+TEST(ListenersTest, DoesNotLeak) {
+  Water* water = new Water;
+  delete water;
+}
+
+// This should fail when the --check_for_leaks command line flag is
+// specified.
+TEST(ListenersTest, LeaksWater) {
+  Water* water = new Water;
+  EXPECT_TRUE(water != NULL);
+}
+
+}  // namespace
+
+int main(int argc, char **argv) {
+  InitGoogleTest(&argc, argv);
+
+  bool check_for_leaks = false;
+  if (argc > 1 && strcmp(argv[1], "--check_for_leaks") == 0 )
+    check_for_leaks = true;
+  else
+    printf("%s\n", "Run this program with --check_for_leaks to enable "
+           "custom leak checking in the tests.");
+
+  // If we are given the --check_for_leaks command line flag, installs the
+  // leak checker.
+  if (check_for_leaks) {
+    TestEventListeners& listeners = UnitTest::GetInstance()->listeners();
+
+    // Adds the leak checker to the end of the test event listener list,
+    // after the default text output printer and the default XML report
+    // generator.
+    //
+    // The order is important - it ensures that failures generated in the
+    // leak checker's OnTestEnd() method are processed by the text and XML
+    // printers *before* their OnTestEnd() methods are called, such that
+    // they are attributed to the right test. Remember that a listener
+    // receives an OnXyzStart event *after* listeners preceding it in the
+    // list received that event, and receives an OnXyzEnd event *before*
+    // listeners preceding it.
+    //
+    // We don't need to worry about deleting the new listener later, as
+    // Google Test will do it.
+    listeners.Append(new LeakChecker);
+  }
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/googletest/googletest/samples/sample1_unittest.cc b/third_party/googletest/googletest/samples/sample1_unittest.cc
new file mode 100644
index 0000000..aefc4f1
--- /dev/null
+++ b/third_party/googletest/googletest/samples/sample1_unittest.cc
@@ -0,0 +1,153 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A sample program demonstrating using Google C++ testing framework.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+
+// This sample shows how to write a simple unit test for a function,
+// using Google C++ testing framework.
+//
+// Writing a unit test using Google C++ testing framework is easy as 1-2-3:
+
+
+// Step 1. Include necessary header files such that the stuff your
+// test logic needs is declared.
+//
+// Don't forget gtest.h, which declares the testing framework.
+
+#include <limits.h>
+#include "sample1.h"
+#include "gtest/gtest.h"
+
+
+// Step 2. Use the TEST macro to define your tests.
+//
+// TEST has two parameters: the test case name and the test name.
+// After using the macro, you should define your test logic between a
+// pair of braces.  You can use a bunch of macros to indicate the
+// success or failure of a test.  EXPECT_TRUE and EXPECT_EQ are
+// examples of such macros.  For a complete list, see gtest.h.
+//
+// <TechnicalDetails>
+//
+// In Google Test, tests are grouped into test cases.  This is how we
+// keep test code organized.  You should put logically related tests
+// into the same test case.
+//
+// The test case name and the test name should both be valid C++
+// identifiers.  And you should not use underscore (_) in the names.
+//
+// Google Test guarantees that each test you define is run exactly
+// once, but it makes no guarantee on the order the tests are
+// executed.  Therefore, you should write your tests in such a way
+// that their results don't depend on their order.
+//
+// </TechnicalDetails>
+
+
+// Tests Factorial().
+
+// Tests factorial of negative numbers.
+TEST(FactorialTest, Negative) {
+  // This test is named "Negative", and belongs to the "FactorialTest"
+  // test case.
+  EXPECT_EQ(1, Factorial(-5));
+  EXPECT_EQ(1, Factorial(-1));
+  EXPECT_GT(Factorial(-10), 0);
+
+  // <TechnicalDetails>
+  //
+  // EXPECT_EQ(expected, actual) is the same as
+  //
+  //   EXPECT_TRUE((expected) == (actual))
+  //
+  // except that it will print both the expected value and the actual
+  // value when the assertion fails.  This is very helpful for
+  // debugging.  Therefore in this case EXPECT_EQ is preferred.
+  //
+  // On the other hand, EXPECT_TRUE accepts any Boolean expression,
+  // and is thus more general.
+  //
+  // </TechnicalDetails>
+}
+
+// Tests factorial of 0.
+TEST(FactorialTest, Zero) {
+  EXPECT_EQ(1, Factorial(0));
+}
+
+// Tests factorial of positive numbers.
+TEST(FactorialTest, Positive) {
+  EXPECT_EQ(1, Factorial(1));
+  EXPECT_EQ(2, Factorial(2));
+  EXPECT_EQ(6, Factorial(3));
+  EXPECT_EQ(40320, Factorial(8));
+}
+
+
+// Tests IsPrime()
+
+// Tests negative input.
+TEST(IsPrimeTest, Negative) {
+  // This test belongs to the IsPrimeTest test case.
+
+  EXPECT_FALSE(IsPrime(-1));
+  EXPECT_FALSE(IsPrime(-2));
+  EXPECT_FALSE(IsPrime(INT_MIN));
+}
+
+// Tests some trivial cases.
+TEST(IsPrimeTest, Trivial) {
+  EXPECT_FALSE(IsPrime(0));
+  EXPECT_FALSE(IsPrime(1));
+  EXPECT_TRUE(IsPrime(2));
+  EXPECT_TRUE(IsPrime(3));
+}
+
+// Tests positive input.
+TEST(IsPrimeTest, Positive) {
+  EXPECT_FALSE(IsPrime(4));
+  EXPECT_TRUE(IsPrime(5));
+  EXPECT_FALSE(IsPrime(6));
+  EXPECT_TRUE(IsPrime(23));
+}
+
+// Step 3. Call RUN_ALL_TESTS() in main().
+//
+// We do this by linking in src/gtest_main.cc file, which consists of
+// a main() function which calls RUN_ALL_TESTS() for us.
+//
+// This runs all the tests you've defined, prints the result, and
+// returns 0 if successful, or 1 otherwise.
+//
+// Did you notice that we didn't register the tests?  The
+// RUN_ALL_TESTS() macro magically knows about all the tests we
+// defined.  Isn't this convenient?
diff --git a/third_party/googletest/googletest/samples/sample2.cc b/third_party/googletest/googletest/samples/sample2.cc
new file mode 100644
index 0000000..5f763b9
--- /dev/null
+++ b/third_party/googletest/googletest/samples/sample2.cc
@@ -0,0 +1,56 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A sample program demonstrating using Google C++ testing framework.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include "sample2.h"
+
+#include <string.h>
+
+// Clones a 0-terminated C string, allocating memory using new.
+const char* MyString::CloneCString(const char* a_c_string) {
+  if (a_c_string == NULL) return NULL;
+
+  const size_t len = strlen(a_c_string);
+  char* const clone = new char[ len + 1 ];
+  memcpy(clone, a_c_string, len + 1);
+
+  return clone;
+}
+
+// Sets the 0-terminated C string this MyString object
+// represents.
+void MyString::Set(const char* a_c_string) {
+  // Makes sure this works when c_string == c_string_
+  const char* const temp = MyString::CloneCString(a_c_string);
+  delete[] c_string_;
+  c_string_ = temp;
+}
diff --git a/third_party/googletest/googletest/samples/sample2.h b/third_party/googletest/googletest/samples/sample2.h
new file mode 100644
index 0000000..cb485c7
--- /dev/null
+++ b/third_party/googletest/googletest/samples/sample2.h
@@ -0,0 +1,85 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A sample program demonstrating using Google C++ testing framework.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#ifndef GTEST_SAMPLES_SAMPLE2_H_
+#define GTEST_SAMPLES_SAMPLE2_H_
+
+#include <string.h>
+
+
+// A simple string class.
+class MyString {
+ private:
+  const char* c_string_;
+  const MyString& operator=(const MyString& rhs);
+
+ public:
+  // Clones a 0-terminated C string, allocating memory using new.
+  static const char* CloneCString(const char* a_c_string);
+
+  ////////////////////////////////////////////////////////////
+  //
+  // C'tors
+
+  // The default c'tor constructs a NULL string.
+  MyString() : c_string_(NULL) {}
+
+  // Constructs a MyString by cloning a 0-terminated C string.
+  explicit MyString(const char* a_c_string) : c_string_(NULL) {
+    Set(a_c_string);
+  }
+
+  // Copy c'tor
+  MyString(const MyString& string) : c_string_(NULL) {
+    Set(string.c_string_);
+  }
+
+  ////////////////////////////////////////////////////////////
+  //
+  // D'tor.  MyString is intended to be a final class, so the d'tor
+  // doesn't need to be virtual.
+  ~MyString() { delete[] c_string_; }
+
+  // Gets the 0-terminated C string this MyString object represents.
+  const char* c_string() const { return c_string_; }
+
+  size_t Length() const {
+    return c_string_ == NULL ? 0 : strlen(c_string_);
+  }
+
+  // Sets the 0-terminated C string this MyString object represents.
+  void Set(const char* c_string);
+};
+
+
+#endif  // GTEST_SAMPLES_SAMPLE2_H_
diff --git a/third_party/googletest/googletest/samples/sample2_unittest.cc b/third_party/googletest/googletest/samples/sample2_unittest.cc
new file mode 100644
index 0000000..4fa19b7
--- /dev/null
+++ b/third_party/googletest/googletest/samples/sample2_unittest.cc
@@ -0,0 +1,109 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A sample program demonstrating using Google C++ testing framework.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+
+// This sample shows how to write a more complex unit test for a class
+// that has multiple member functions.
+//
+// Usually, it's a good idea to have one test for each method in your
+// class.  You don't have to do that exactly, but it helps to keep
+// your tests organized.  You may also throw in additional tests as
+// needed.
+
+#include "sample2.h"
+#include "gtest/gtest.h"
+
+// In this example, we test the MyString class (a simple string).
+
+// Tests the default c'tor.
+TEST(MyString, DefaultConstructor) {
+  const MyString s;
+
+  // Asserts that s.c_string() returns NULL.
+  //
+  // <TechnicalDetails>
+  //
+  // If we write NULL instead of
+  //
+  //   static_cast<const char *>(NULL)
+  //
+  // in this assertion, it will generate a warning on gcc 3.4.  The
+  // reason is that EXPECT_EQ needs to know the types of its
+  // arguments in order to print them when it fails.  Since NULL is
+  // #defined as 0, the compiler will use the formatter function for
+  // int to print it.  However, gcc thinks that NULL should be used as
+  // a pointer, not an int, and therefore complains.
+  //
+  // The root of the problem is C++'s lack of distinction between the
+  // integer number 0 and the null pointer constant.  Unfortunately,
+  // we have to live with this fact.
+  //
+  // </TechnicalDetails>
+  EXPECT_STREQ(NULL, s.c_string());
+
+  EXPECT_EQ(0u, s.Length());
+}
+
+const char kHelloString[] = "Hello, world!";
+
+// Tests the c'tor that accepts a C string.
+TEST(MyString, ConstructorFromCString) {
+  const MyString s(kHelloString);
+  EXPECT_EQ(0, strcmp(s.c_string(), kHelloString));
+  EXPECT_EQ(sizeof(kHelloString)/sizeof(kHelloString[0]) - 1,
+            s.Length());
+}
+
+// Tests the copy c'tor.
+TEST(MyString, CopyConstructor) {
+  const MyString s1(kHelloString);
+  const MyString s2 = s1;
+  EXPECT_EQ(0, strcmp(s2.c_string(), kHelloString));
+}
+
+// Tests the Set method.
+TEST(MyString, Set) {
+  MyString s;
+
+  s.Set(kHelloString);
+  EXPECT_EQ(0, strcmp(s.c_string(), kHelloString));
+
+  // Set should work when the input pointer is the same as the one
+  // already in the MyString object.
+  s.Set(s.c_string());
+  EXPECT_EQ(0, strcmp(s.c_string(), kHelloString));
+
+  // Can we set the MyString to NULL?
+  s.Set(NULL);
+  EXPECT_STREQ(NULL, s.c_string());
+}
diff --git a/third_party/googletest/googletest/samples/sample3-inl.h b/third_party/googletest/googletest/samples/sample3-inl.h
new file mode 100644
index 0000000..7e3084d
--- /dev/null
+++ b/third_party/googletest/googletest/samples/sample3-inl.h
@@ -0,0 +1,172 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A sample program demonstrating using Google C++ testing framework.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#ifndef GTEST_SAMPLES_SAMPLE3_INL_H_
+#define GTEST_SAMPLES_SAMPLE3_INL_H_
+
+#include <stddef.h>
+
+
+// Queue is a simple queue implemented as a singled-linked list.
+//
+// The element type must support copy constructor.
+template <typename E>  // E is the element type
+class Queue;
+
+// QueueNode is a node in a Queue, which consists of an element of
+// type E and a pointer to the next node.
+template <typename E>  // E is the element type
+class QueueNode {
+  friend class Queue<E>;
+
+ public:
+  // Gets the element in this node.
+  const E& element() const { return element_; }
+
+  // Gets the next node in the queue.
+  QueueNode* next() { return next_; }
+  const QueueNode* next() const { return next_; }
+
+ private:
+  // Creates a node with a given element value.  The next pointer is
+  // set to NULL.
+  explicit QueueNode(const E& an_element) : element_(an_element), next_(NULL) {}
+
+  // We disable the default assignment operator and copy c'tor.
+  const QueueNode& operator = (const QueueNode&);
+  QueueNode(const QueueNode&);
+
+  E element_;
+  QueueNode* next_;
+};
+
+template <typename E>  // E is the element type.
+class Queue {
+ public:
+  // Creates an empty queue.
+  Queue() : head_(NULL), last_(NULL), size_(0) {}
+
+  // D'tor.  Clears the queue.
+  ~Queue() { Clear(); }
+
+  // Clears the queue.
+  void Clear() {
+    if (size_ > 0) {
+      // 1. Deletes every node.
+      QueueNode<E>* node = head_;
+      QueueNode<E>* next = node->next();
+      for (; ;) {
+        delete node;
+        node = next;
+        if (node == NULL) break;
+        next = node->next();
+      }
+
+      // 2. Resets the member variables.
+      head_ = last_ = NULL;
+      size_ = 0;
+    }
+  }
+
+  // Gets the number of elements.
+  size_t Size() const { return size_; }
+
+  // Gets the first element of the queue, or NULL if the queue is empty.
+  QueueNode<E>* Head() { return head_; }
+  const QueueNode<E>* Head() const { return head_; }
+
+  // Gets the last element of the queue, or NULL if the queue is empty.
+  QueueNode<E>* Last() { return last_; }
+  const QueueNode<E>* Last() const { return last_; }
+
+  // Adds an element to the end of the queue.  A copy of the element is
+  // created using the copy constructor, and then stored in the queue.
+  // Changes made to the element in the queue doesn't affect the source
+  // object, and vice versa.
+  void Enqueue(const E& element) {
+    QueueNode<E>* new_node = new QueueNode<E>(element);
+
+    if (size_ == 0) {
+      head_ = last_ = new_node;
+      size_ = 1;
+    } else {
+      last_->next_ = new_node;
+      last_ = new_node;
+      size_++;
+    }
+  }
+
+  // Removes the head of the queue and returns it.  Returns NULL if
+  // the queue is empty.
+  E* Dequeue() {
+    if (size_ == 0) {
+      return NULL;
+    }
+
+    const QueueNode<E>* const old_head = head_;
+    head_ = head_->next_;
+    size_--;
+    if (size_ == 0) {
+      last_ = NULL;
+    }
+
+    E* element = new E(old_head->element());
+    delete old_head;
+
+    return element;
+  }
+
+  // Applies a function/functor on each element of the queue, and
+  // returns the result in a new queue.  The original queue is not
+  // affected.
+  template <typename F>
+  Queue* Map(F function) const {
+    Queue* new_queue = new Queue();
+    for (const QueueNode<E>* node = head_; node != NULL; node = node->next_) {
+      new_queue->Enqueue(function(node->element()));
+    }
+
+    return new_queue;
+  }
+
+ private:
+  QueueNode<E>* head_;  // The first node of the queue.
+  QueueNode<E>* last_;  // The last node of the queue.
+  size_t size_;  // The number of elements in the queue.
+
+  // We disallow copying a queue.
+  Queue(const Queue&);
+  const Queue& operator = (const Queue&);
+};
+
+#endif  // GTEST_SAMPLES_SAMPLE3_INL_H_
diff --git a/third_party/googletest/googletest/samples/sample3_unittest.cc b/third_party/googletest/googletest/samples/sample3_unittest.cc
new file mode 100644
index 0000000..bf3877d
--- /dev/null
+++ b/third_party/googletest/googletest/samples/sample3_unittest.cc
@@ -0,0 +1,151 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A sample program demonstrating using Google C++ testing framework.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+
+// In this example, we use a more advanced feature of Google Test called
+// test fixture.
+//
+// A test fixture is a place to hold objects and functions shared by
+// all tests in a test case.  Using a test fixture avoids duplicating
+// the test code necessary to initialize and cleanup those common
+// objects for each test.  It is also useful for defining sub-routines
+// that your tests need to invoke a lot.
+//
+// <TechnicalDetails>
+//
+// The tests share the test fixture in the sense of code sharing, not
+// data sharing.  Each test is given its own fresh copy of the
+// fixture.  You cannot expect the data modified by one test to be
+// passed on to another test, which is a bad idea.
+//
+// The reason for this design is that tests should be independent and
+// repeatable.  In particular, a test should not fail as the result of
+// another test's failure.  If one test depends on info produced by
+// another test, then the two tests should really be one big test.
+//
+// The macros for indicating the success/failure of a test
+// (EXPECT_TRUE, FAIL, etc) need to know what the current test is
+// (when Google Test prints the test result, it tells you which test
+// each failure belongs to).  Technically, these macros invoke a
+// member function of the Test class.  Therefore, you cannot use them
+// in a global function.  That's why you should put test sub-routines
+// in a test fixture.
+//
+// </TechnicalDetails>
+
+#include "sample3-inl.h"
+#include "gtest/gtest.h"
+
+// To use a test fixture, derive a class from testing::Test.
+class QueueTest : public testing::Test {
+ protected:  // You should make the members protected s.t. they can be
+             // accessed from sub-classes.
+
+  // virtual void SetUp() will be called before each test is run.  You
+  // should define it if you need to initialize the varaibles.
+  // Otherwise, this can be skipped.
+  virtual void SetUp() {
+    q1_.Enqueue(1);
+    q2_.Enqueue(2);
+    q2_.Enqueue(3);
+  }
+
+  // virtual void TearDown() will be called after each test is run.
+  // You should define it if there is cleanup work to do.  Otherwise,
+  // you don't have to provide it.
+  //
+  // virtual void TearDown() {
+  // }
+
+  // A helper function that some test uses.
+  static int Double(int n) {
+    return 2*n;
+  }
+
+  // A helper function for testing Queue::Map().
+  void MapTester(const Queue<int> * q) {
+    // Creates a new queue, where each element is twice as big as the
+    // corresponding one in q.
+    const Queue<int> * const new_q = q->Map(Double);
+
+    // Verifies that the new queue has the same size as q.
+    ASSERT_EQ(q->Size(), new_q->Size());
+
+    // Verifies the relationship between the elements of the two queues.
+    for ( const QueueNode<int> * n1 = q->Head(), * n2 = new_q->Head();
+          n1 != NULL; n1 = n1->next(), n2 = n2->next() ) {
+      EXPECT_EQ(2 * n1->element(), n2->element());
+    }
+
+    delete new_q;
+  }
+
+  // Declares the variables your tests want to use.
+  Queue<int> q0_;
+  Queue<int> q1_;
+  Queue<int> q2_;
+};
+
+// When you have a test fixture, you define a test using TEST_F
+// instead of TEST.
+
+// Tests the default c'tor.
+TEST_F(QueueTest, DefaultConstructor) {
+  // You can access data in the test fixture here.
+  EXPECT_EQ(0u, q0_.Size());
+}
+
+// Tests Dequeue().
+TEST_F(QueueTest, Dequeue) {
+  int * n = q0_.Dequeue();
+  EXPECT_TRUE(n == NULL);
+
+  n = q1_.Dequeue();
+  ASSERT_TRUE(n != NULL);
+  EXPECT_EQ(1, *n);
+  EXPECT_EQ(0u, q1_.Size());
+  delete n;
+
+  n = q2_.Dequeue();
+  ASSERT_TRUE(n != NULL);
+  EXPECT_EQ(2, *n);
+  EXPECT_EQ(1u, q2_.Size());
+  delete n;
+}
+
+// Tests the Queue::Map() function.
+TEST_F(QueueTest, Map) {
+  MapTester(&q0_);
+  MapTester(&q1_);
+  MapTester(&q2_);
+}
diff --git a/third_party/googletest/googletest/samples/sample4.cc b/third_party/googletest/googletest/samples/sample4.cc
new file mode 100644
index 0000000..ae44bda
--- /dev/null
+++ b/third_party/googletest/googletest/samples/sample4.cc
@@ -0,0 +1,46 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A sample program demonstrating using Google C++ testing framework.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include <stdio.h>
+
+#include "sample4.h"
+
+// Returns the current counter value, and increments it.
+int Counter::Increment() {
+  return counter_++;
+}
+
+// Prints the current counter value to STDOUT.
+void Counter::Print() const {
+  printf("%d", counter_);
+}
diff --git a/third_party/googletest/googletest/samples/sample4.h b/third_party/googletest/googletest/samples/sample4.h
new file mode 100644
index 0000000..cd60f0d
--- /dev/null
+++ b/third_party/googletest/googletest/samples/sample4.h
@@ -0,0 +1,53 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A sample program demonstrating using Google C++ testing framework.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#ifndef GTEST_SAMPLES_SAMPLE4_H_
+#define GTEST_SAMPLES_SAMPLE4_H_
+
+// A simple monotonic counter.
+class Counter {
+ private:
+  int counter_;
+
+ public:
+  // Creates a counter that starts at 0.
+  Counter() : counter_(0) {}
+
+  // Returns the current counter value, and increments it.
+  int Increment();
+
+  // Prints the current counter value to STDOUT.
+  void Print() const;
+};
+
+#endif  // GTEST_SAMPLES_SAMPLE4_H_
diff --git a/third_party/googletest/googletest/samples/sample4_unittest.cc b/third_party/googletest/googletest/samples/sample4_unittest.cc
new file mode 100644
index 0000000..fa5afc7
--- /dev/null
+++ b/third_party/googletest/googletest/samples/sample4_unittest.cc
@@ -0,0 +1,45 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include "gtest/gtest.h"
+#include "sample4.h"
+
+// Tests the Increment() method.
+TEST(Counter, Increment) {
+  Counter c;
+
+  // EXPECT_EQ() evaluates its arguments exactly once, so they
+  // can have side effects.
+
+  EXPECT_EQ(0, c.Increment());
+  EXPECT_EQ(1, c.Increment());
+  EXPECT_EQ(2, c.Increment());
+}
diff --git a/third_party/googletest/googletest/samples/sample5_unittest.cc b/third_party/googletest/googletest/samples/sample5_unittest.cc
new file mode 100644
index 0000000..43d8e57
--- /dev/null
+++ b/third_party/googletest/googletest/samples/sample5_unittest.cc
@@ -0,0 +1,199 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// This sample teaches how to reuse a test fixture in multiple test
+// cases by deriving sub-fixtures from it.
+//
+// When you define a test fixture, you specify the name of the test
+// case that will use this fixture.  Therefore, a test fixture can
+// be used by only one test case.
+//
+// Sometimes, more than one test cases may want to use the same or
+// slightly different test fixtures.  For example, you may want to
+// make sure that all tests for a GUI library don't leak important
+// system resources like fonts and brushes.  In Google Test, you do
+// this by putting the shared logic in a super (as in "super class")
+// test fixture, and then have each test case use a fixture derived
+// from this super fixture.
+
+#include <limits.h>
+#include <time.h>
+#include "sample3-inl.h"
+#include "gtest/gtest.h"
+#include "sample1.h"
+
+// In this sample, we want to ensure that every test finishes within
+// ~5 seconds.  If a test takes longer to run, we consider it a
+// failure.
+//
+// We put the code for timing a test in a test fixture called
+// "QuickTest".  QuickTest is intended to be the super fixture that
+// other fixtures derive from, therefore there is no test case with
+// the name "QuickTest".  This is OK.
+//
+// Later, we will derive multiple test fixtures from QuickTest.
+class QuickTest : public testing::Test {
+ protected:
+  // Remember that SetUp() is run immediately before a test starts.
+  // This is a good place to record the start time.
+  virtual void SetUp() {
+    start_time_ = time(NULL);
+  }
+
+  // TearDown() is invoked immediately after a test finishes.  Here we
+  // check if the test was too slow.
+  virtual void TearDown() {
+    // Gets the time when the test finishes
+    const time_t end_time = time(NULL);
+
+    // Asserts that the test took no more than ~5 seconds.  Did you
+    // know that you can use assertions in SetUp() and TearDown() as
+    // well?
+    EXPECT_TRUE(end_time - start_time_ <= 5) << "The test took too long.";
+  }
+
+  // The UTC time (in seconds) when the test starts
+  time_t start_time_;
+};
+
+
+// We derive a fixture named IntegerFunctionTest from the QuickTest
+// fixture.  All tests using this fixture will be automatically
+// required to be quick.
+class IntegerFunctionTest : public QuickTest {
+  // We don't need any more logic than already in the QuickTest fixture.
+  // Therefore the body is empty.
+};
+
+
+// Now we can write tests in the IntegerFunctionTest test case.
+
+// Tests Factorial()
+TEST_F(IntegerFunctionTest, Factorial) {
+  // Tests factorial of negative numbers.
+  EXPECT_EQ(1, Factorial(-5));
+  EXPECT_EQ(1, Factorial(-1));
+  EXPECT_GT(Factorial(-10), 0);
+
+  // Tests factorial of 0.
+  EXPECT_EQ(1, Factorial(0));
+
+  // Tests factorial of positive numbers.
+  EXPECT_EQ(1, Factorial(1));
+  EXPECT_EQ(2, Factorial(2));
+  EXPECT_EQ(6, Factorial(3));
+  EXPECT_EQ(40320, Factorial(8));
+}
+
+
+// Tests IsPrime()
+TEST_F(IntegerFunctionTest, IsPrime) {
+  // Tests negative input.
+  EXPECT_FALSE(IsPrime(-1));
+  EXPECT_FALSE(IsPrime(-2));
+  EXPECT_FALSE(IsPrime(INT_MIN));
+
+  // Tests some trivial cases.
+  EXPECT_FALSE(IsPrime(0));
+  EXPECT_FALSE(IsPrime(1));
+  EXPECT_TRUE(IsPrime(2));
+  EXPECT_TRUE(IsPrime(3));
+
+  // Tests positive input.
+  EXPECT_FALSE(IsPrime(4));
+  EXPECT_TRUE(IsPrime(5));
+  EXPECT_FALSE(IsPrime(6));
+  EXPECT_TRUE(IsPrime(23));
+}
+
+
+// The next test case (named "QueueTest") also needs to be quick, so
+// we derive another fixture from QuickTest.
+//
+// The QueueTest test fixture has some logic and shared objects in
+// addition to what's in QuickTest already.  We define the additional
+// stuff inside the body of the test fixture, as usual.
+class QueueTest : public QuickTest {
+ protected:
+  virtual void SetUp() {
+    // First, we need to set up the super fixture (QuickTest).
+    QuickTest::SetUp();
+
+    // Second, some additional setup for this fixture.
+    q1_.Enqueue(1);
+    q2_.Enqueue(2);
+    q2_.Enqueue(3);
+  }
+
+  // By default, TearDown() inherits the behavior of
+  // QuickTest::TearDown().  As we have no additional cleaning work
+  // for QueueTest, we omit it here.
+  //
+  // virtual void TearDown() {
+  //   QuickTest::TearDown();
+  // }
+
+  Queue<int> q0_;
+  Queue<int> q1_;
+  Queue<int> q2_;
+};
+
+
+// Now, let's write tests using the QueueTest fixture.
+
+// Tests the default constructor.
+TEST_F(QueueTest, DefaultConstructor) {
+  EXPECT_EQ(0u, q0_.Size());
+}
+
+// Tests Dequeue().
+TEST_F(QueueTest, Dequeue) {
+  int* n = q0_.Dequeue();
+  EXPECT_TRUE(n == NULL);
+
+  n = q1_.Dequeue();
+  EXPECT_TRUE(n != NULL);
+  EXPECT_EQ(1, *n);
+  EXPECT_EQ(0u, q1_.Size());
+  delete n;
+
+  n = q2_.Dequeue();
+  EXPECT_TRUE(n != NULL);
+  EXPECT_EQ(2, *n);
+  EXPECT_EQ(1u, q2_.Size());
+  delete n;
+}
+
+// If necessary, you can derive further test fixtures from a derived
+// fixture itself.  For example, you can derive another fixture from
+// QueueTest.  Google Test imposes no limit on how deep the hierarchy
+// can be.  In practice, however, you probably don't want it to be too
+// deep as to be confusing.
diff --git a/third_party/googletest/googletest/samples/sample6_unittest.cc b/third_party/googletest/googletest/samples/sample6_unittest.cc
new file mode 100644
index 0000000..8f2036a
--- /dev/null
+++ b/third_party/googletest/googletest/samples/sample6_unittest.cc
@@ -0,0 +1,224 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// This sample shows how to test common properties of multiple
+// implementations of the same interface (aka interface tests).
+
+// The interface and its implementations are in this header.
+#include "prime_tables.h"
+
+#include "gtest/gtest.h"
+
+// First, we define some factory functions for creating instances of
+// the implementations.  You may be able to skip this step if all your
+// implementations can be constructed the same way.
+
+template <class T>
+PrimeTable* CreatePrimeTable();
+
+template <>
+PrimeTable* CreatePrimeTable<OnTheFlyPrimeTable>() {
+  return new OnTheFlyPrimeTable;
+}
+
+template <>
+PrimeTable* CreatePrimeTable<PreCalculatedPrimeTable>() {
+  return new PreCalculatedPrimeTable(10000);
+}
+
+// Then we define a test fixture class template.
+template <class T>
+class PrimeTableTest : public testing::Test {
+ protected:
+  // The ctor calls the factory function to create a prime table
+  // implemented by T.
+  PrimeTableTest() : table_(CreatePrimeTable<T>()) {}
+
+  virtual ~PrimeTableTest() { delete table_; }
+
+  // Note that we test an implementation via the base interface
+  // instead of the actual implementation class.  This is important
+  // for keeping the tests close to the real world scenario, where the
+  // implementation is invoked via the base interface.  It avoids
+  // got-yas where the implementation class has a method that shadows
+  // a method with the same name (but slightly different argument
+  // types) in the base interface, for example.
+  PrimeTable* const table_;
+};
+
+#if GTEST_HAS_TYPED_TEST
+
+using testing::Types;
+
+// Google Test offers two ways for reusing tests for different types.
+// The first is called "typed tests".  You should use it if you
+// already know *all* the types you are gonna exercise when you write
+// the tests.
+
+// To write a typed test case, first use
+//
+//   TYPED_TEST_CASE(TestCaseName, TypeList);
+//
+// to declare it and specify the type parameters.  As with TEST_F,
+// TestCaseName must match the test fixture name.
+
+// The list of types we want to test.
+typedef Types<OnTheFlyPrimeTable, PreCalculatedPrimeTable> Implementations;
+
+TYPED_TEST_CASE(PrimeTableTest, Implementations);
+
+// Then use TYPED_TEST(TestCaseName, TestName) to define a typed test,
+// similar to TEST_F.
+TYPED_TEST(PrimeTableTest, ReturnsFalseForNonPrimes) {
+  // Inside the test body, you can refer to the type parameter by
+  // TypeParam, and refer to the fixture class by TestFixture.  We
+  // don't need them in this example.
+
+  // Since we are in the template world, C++ requires explicitly
+  // writing 'this->' when referring to members of the fixture class.
+  // This is something you have to learn to live with.
+  EXPECT_FALSE(this->table_->IsPrime(-5));
+  EXPECT_FALSE(this->table_->IsPrime(0));
+  EXPECT_FALSE(this->table_->IsPrime(1));
+  EXPECT_FALSE(this->table_->IsPrime(4));
+  EXPECT_FALSE(this->table_->IsPrime(6));
+  EXPECT_FALSE(this->table_->IsPrime(100));
+}
+
+TYPED_TEST(PrimeTableTest, ReturnsTrueForPrimes) {
+  EXPECT_TRUE(this->table_->IsPrime(2));
+  EXPECT_TRUE(this->table_->IsPrime(3));
+  EXPECT_TRUE(this->table_->IsPrime(5));
+  EXPECT_TRUE(this->table_->IsPrime(7));
+  EXPECT_TRUE(this->table_->IsPrime(11));
+  EXPECT_TRUE(this->table_->IsPrime(131));
+}
+
+TYPED_TEST(PrimeTableTest, CanGetNextPrime) {
+  EXPECT_EQ(2, this->table_->GetNextPrime(0));
+  EXPECT_EQ(3, this->table_->GetNextPrime(2));
+  EXPECT_EQ(5, this->table_->GetNextPrime(3));
+  EXPECT_EQ(7, this->table_->GetNextPrime(5));
+  EXPECT_EQ(11, this->table_->GetNextPrime(7));
+  EXPECT_EQ(131, this->table_->GetNextPrime(128));
+}
+
+// That's it!  Google Test will repeat each TYPED_TEST for each type
+// in the type list specified in TYPED_TEST_CASE.  Sit back and be
+// happy that you don't have to define them multiple times.
+
+#endif  // GTEST_HAS_TYPED_TEST
+
+#if GTEST_HAS_TYPED_TEST_P
+
+using testing::Types;
+
+// Sometimes, however, you don't yet know all the types that you want
+// to test when you write the tests.  For example, if you are the
+// author of an interface and expect other people to implement it, you
+// might want to write a set of tests to make sure each implementation
+// conforms to some basic requirements, but you don't know what
+// implementations will be written in the future.
+//
+// How can you write the tests without committing to the type
+// parameters?  That's what "type-parameterized tests" can do for you.
+// It is a bit more involved than typed tests, but in return you get a
+// test pattern that can be reused in many contexts, which is a big
+// win.  Here's how you do it:
+
+// First, define a test fixture class template.  Here we just reuse
+// the PrimeTableTest fixture defined earlier:
+
+template <class T>
+class PrimeTableTest2 : public PrimeTableTest<T> {
+};
+
+// Then, declare the test case.  The argument is the name of the test
+// fixture, and also the name of the test case (as usual).  The _P
+// suffix is for "parameterized" or "pattern".
+TYPED_TEST_CASE_P(PrimeTableTest2);
+
+// Next, use TYPED_TEST_P(TestCaseName, TestName) to define a test,
+// similar to what you do with TEST_F.
+TYPED_TEST_P(PrimeTableTest2, ReturnsFalseForNonPrimes) {
+  EXPECT_FALSE(this->table_->IsPrime(-5));
+  EXPECT_FALSE(this->table_->IsPrime(0));
+  EXPECT_FALSE(this->table_->IsPrime(1));
+  EXPECT_FALSE(this->table_->IsPrime(4));
+  EXPECT_FALSE(this->table_->IsPrime(6));
+  EXPECT_FALSE(this->table_->IsPrime(100));
+}
+
+TYPED_TEST_P(PrimeTableTest2, ReturnsTrueForPrimes) {
+  EXPECT_TRUE(this->table_->IsPrime(2));
+  EXPECT_TRUE(this->table_->IsPrime(3));
+  EXPECT_TRUE(this->table_->IsPrime(5));
+  EXPECT_TRUE(this->table_->IsPrime(7));
+  EXPECT_TRUE(this->table_->IsPrime(11));
+  EXPECT_TRUE(this->table_->IsPrime(131));
+}
+
+TYPED_TEST_P(PrimeTableTest2, CanGetNextPrime) {
+  EXPECT_EQ(2, this->table_->GetNextPrime(0));
+  EXPECT_EQ(3, this->table_->GetNextPrime(2));
+  EXPECT_EQ(5, this->table_->GetNextPrime(3));
+  EXPECT_EQ(7, this->table_->GetNextPrime(5));
+  EXPECT_EQ(11, this->table_->GetNextPrime(7));
+  EXPECT_EQ(131, this->table_->GetNextPrime(128));
+}
+
+// Type-parameterized tests involve one extra step: you have to
+// enumerate the tests you defined:
+REGISTER_TYPED_TEST_CASE_P(
+    PrimeTableTest2,  // The first argument is the test case name.
+    // The rest of the arguments are the test names.
+    ReturnsFalseForNonPrimes, ReturnsTrueForPrimes, CanGetNextPrime);
+
+// At this point the test pattern is done.  However, you don't have
+// any real test yet as you haven't said which types you want to run
+// the tests with.
+
+// To turn the abstract test pattern into real tests, you instantiate
+// it with a list of types.  Usually the test pattern will be defined
+// in a .h file, and anyone can #include and instantiate it.  You can
+// even instantiate it more than once in the same program.  To tell
+// different instances apart, you give each of them a name, which will
+// become part of the test case name and can be used in test filters.
+
+// The list of types we want to test.  Note that it doesn't have to be
+// defined at the time we write the TYPED_TEST_P()s.
+typedef Types<OnTheFlyPrimeTable, PreCalculatedPrimeTable>
+    PrimeTableImplementations;
+INSTANTIATE_TYPED_TEST_CASE_P(OnTheFlyAndPreCalculated,    // Instance name
+                              PrimeTableTest2,             // Test case name
+                              PrimeTableImplementations);  // Type list
+
+#endif  // GTEST_HAS_TYPED_TEST_P
diff --git a/third_party/googletest/googletest/samples/sample7_unittest.cc b/third_party/googletest/googletest/samples/sample7_unittest.cc
new file mode 100644
index 0000000..1b651a2
--- /dev/null
+++ b/third_party/googletest/googletest/samples/sample7_unittest.cc
@@ -0,0 +1,130 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vladl@google.com (Vlad Losev)
+
+// This sample shows how to test common properties of multiple
+// implementations of an interface (aka interface tests) using
+// value-parameterized tests. Each test in the test case has
+// a parameter that is an interface pointer to an implementation
+// tested.
+
+// The interface and its implementations are in this header.
+#include "prime_tables.h"
+
+#include "gtest/gtest.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+using ::testing::TestWithParam;
+using ::testing::Values;
+
+// As a general rule, to prevent a test from affecting the tests that come
+// after it, you should create and destroy the tested objects for each test
+// instead of reusing them.  In this sample we will define a simple factory
+// function for PrimeTable objects.  We will instantiate objects in test's
+// SetUp() method and delete them in TearDown() method.
+typedef PrimeTable* CreatePrimeTableFunc();
+
+PrimeTable* CreateOnTheFlyPrimeTable() {
+  return new OnTheFlyPrimeTable();
+}
+
+template <size_t max_precalculated>
+PrimeTable* CreatePreCalculatedPrimeTable() {
+  return new PreCalculatedPrimeTable(max_precalculated);
+}
+
+// Inside the test body, fixture constructor, SetUp(), and TearDown() you
+// can refer to the test parameter by GetParam().  In this case, the test
+// parameter is a factory function which we call in fixture's SetUp() to
+// create and store an instance of PrimeTable.
+class PrimeTableTest : public TestWithParam<CreatePrimeTableFunc*> {
+ public:
+  virtual ~PrimeTableTest() { delete table_; }
+  virtual void SetUp() { table_ = (*GetParam())(); }
+  virtual void TearDown() {
+    delete table_;
+    table_ = NULL;
+  }
+
+ protected:
+  PrimeTable* table_;
+};
+
+TEST_P(PrimeTableTest, ReturnsFalseForNonPrimes) {
+  EXPECT_FALSE(table_->IsPrime(-5));
+  EXPECT_FALSE(table_->IsPrime(0));
+  EXPECT_FALSE(table_->IsPrime(1));
+  EXPECT_FALSE(table_->IsPrime(4));
+  EXPECT_FALSE(table_->IsPrime(6));
+  EXPECT_FALSE(table_->IsPrime(100));
+}
+
+TEST_P(PrimeTableTest, ReturnsTrueForPrimes) {
+  EXPECT_TRUE(table_->IsPrime(2));
+  EXPECT_TRUE(table_->IsPrime(3));
+  EXPECT_TRUE(table_->IsPrime(5));
+  EXPECT_TRUE(table_->IsPrime(7));
+  EXPECT_TRUE(table_->IsPrime(11));
+  EXPECT_TRUE(table_->IsPrime(131));
+}
+
+TEST_P(PrimeTableTest, CanGetNextPrime) {
+  EXPECT_EQ(2, table_->GetNextPrime(0));
+  EXPECT_EQ(3, table_->GetNextPrime(2));
+  EXPECT_EQ(5, table_->GetNextPrime(3));
+  EXPECT_EQ(7, table_->GetNextPrime(5));
+  EXPECT_EQ(11, table_->GetNextPrime(7));
+  EXPECT_EQ(131, table_->GetNextPrime(128));
+}
+
+// In order to run value-parameterized tests, you need to instantiate them,
+// or bind them to a list of values which will be used as test parameters.
+// You can instantiate them in a different translation module, or even
+// instantiate them several times.
+//
+// Here, we instantiate our tests with a list of two PrimeTable object
+// factory functions:
+INSTANTIATE_TEST_CASE_P(
+    OnTheFlyAndPreCalculated,
+    PrimeTableTest,
+    Values(&CreateOnTheFlyPrimeTable, &CreatePreCalculatedPrimeTable<1000>));
+
+#else
+
+// Google Test may not support value-parameterized tests with some
+// compilers. If we use conditional compilation to compile out all
+// code referring to the gtest_main library, MSVC linker will not link
+// that library at all and consequently complain about missing entry
+// point defined in that library (fatal error LNK1561: entry point
+// must be defined). This dummy test keeps gtest_main linked in.
+TEST(DummyTest, ValueParameterizedTestsAreNotSupportedOnThisPlatform) {}
+
+#endif  // GTEST_HAS_PARAM_TEST
diff --git a/third_party/googletest/googletest/samples/sample8_unittest.cc b/third_party/googletest/googletest/samples/sample8_unittest.cc
new file mode 100644
index 0000000..7274334
--- /dev/null
+++ b/third_party/googletest/googletest/samples/sample8_unittest.cc
@@ -0,0 +1,173 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vladl@google.com (Vlad Losev)
+
+// This sample shows how to test code relying on some global flag variables.
+// Combine() helps with generating all possible combinations of such flags,
+// and each test is given one combination as a parameter.
+
+// Use class definitions to test from this header.
+#include "prime_tables.h"
+
+#include "gtest/gtest.h"
+
+#if GTEST_HAS_COMBINE
+
+// Suppose we want to introduce a new, improved implementation of PrimeTable
+// which combines speed of PrecalcPrimeTable and versatility of
+// OnTheFlyPrimeTable (see prime_tables.h). Inside it instantiates both
+// PrecalcPrimeTable and OnTheFlyPrimeTable and uses the one that is more
+// appropriate under the circumstances. But in low memory conditions, it can be
+// told to instantiate without PrecalcPrimeTable instance at all and use only
+// OnTheFlyPrimeTable.
+class HybridPrimeTable : public PrimeTable {
+ public:
+  HybridPrimeTable(bool force_on_the_fly, int max_precalculated)
+      : on_the_fly_impl_(new OnTheFlyPrimeTable),
+        precalc_impl_(force_on_the_fly ? NULL :
+                          new PreCalculatedPrimeTable(max_precalculated)),
+        max_precalculated_(max_precalculated) {}
+  virtual ~HybridPrimeTable() {
+    delete on_the_fly_impl_;
+    delete precalc_impl_;
+  }
+
+  virtual bool IsPrime(int n) const {
+    if (precalc_impl_ != NULL && n < max_precalculated_)
+      return precalc_impl_->IsPrime(n);
+    else
+      return on_the_fly_impl_->IsPrime(n);
+  }
+
+  virtual int GetNextPrime(int p) const {
+    int next_prime = -1;
+    if (precalc_impl_ != NULL && p < max_precalculated_)
+      next_prime = precalc_impl_->GetNextPrime(p);
+
+    return next_prime != -1 ? next_prime : on_the_fly_impl_->GetNextPrime(p);
+  }
+
+ private:
+  OnTheFlyPrimeTable* on_the_fly_impl_;
+  PreCalculatedPrimeTable* precalc_impl_;
+  int max_precalculated_;
+};
+
+using ::testing::TestWithParam;
+using ::testing::Bool;
+using ::testing::Values;
+using ::testing::Combine;
+
+// To test all code paths for HybridPrimeTable we must test it with numbers
+// both within and outside PreCalculatedPrimeTable's capacity and also with
+// PreCalculatedPrimeTable disabled. We do this by defining fixture which will
+// accept different combinations of parameters for instantiating a
+// HybridPrimeTable instance.
+class PrimeTableTest : public TestWithParam< ::testing::tuple<bool, int> > {
+ protected:
+  virtual void SetUp() {
+    // This can be written as
+    //
+    // bool force_on_the_fly;
+    // int max_precalculated;
+    // tie(force_on_the_fly, max_precalculated) = GetParam();
+    //
+    // once the Google C++ Style Guide allows use of ::std::tr1::tie.
+    //
+    bool force_on_the_fly = ::testing::get<0>(GetParam());
+    int max_precalculated = ::testing::get<1>(GetParam());
+    table_ = new HybridPrimeTable(force_on_the_fly, max_precalculated);
+  }
+  virtual void TearDown() {
+    delete table_;
+    table_ = NULL;
+  }
+  HybridPrimeTable* table_;
+};
+
+TEST_P(PrimeTableTest, ReturnsFalseForNonPrimes) {
+  // Inside the test body, you can refer to the test parameter by GetParam().
+  // In this case, the test parameter is a PrimeTable interface pointer which
+  // we can use directly.
+  // Please note that you can also save it in the fixture's SetUp() method
+  // or constructor and use saved copy in the tests.
+
+  EXPECT_FALSE(table_->IsPrime(-5));
+  EXPECT_FALSE(table_->IsPrime(0));
+  EXPECT_FALSE(table_->IsPrime(1));
+  EXPECT_FALSE(table_->IsPrime(4));
+  EXPECT_FALSE(table_->IsPrime(6));
+  EXPECT_FALSE(table_->IsPrime(100));
+}
+
+TEST_P(PrimeTableTest, ReturnsTrueForPrimes) {
+  EXPECT_TRUE(table_->IsPrime(2));
+  EXPECT_TRUE(table_->IsPrime(3));
+  EXPECT_TRUE(table_->IsPrime(5));
+  EXPECT_TRUE(table_->IsPrime(7));
+  EXPECT_TRUE(table_->IsPrime(11));
+  EXPECT_TRUE(table_->IsPrime(131));
+}
+
+TEST_P(PrimeTableTest, CanGetNextPrime) {
+  EXPECT_EQ(2, table_->GetNextPrime(0));
+  EXPECT_EQ(3, table_->GetNextPrime(2));
+  EXPECT_EQ(5, table_->GetNextPrime(3));
+  EXPECT_EQ(7, table_->GetNextPrime(5));
+  EXPECT_EQ(11, table_->GetNextPrime(7));
+  EXPECT_EQ(131, table_->GetNextPrime(128));
+}
+
+// In order to run value-parameterized tests, you need to instantiate them,
+// or bind them to a list of values which will be used as test parameters.
+// You can instantiate them in a different translation module, or even
+// instantiate them several times.
+//
+// Here, we instantiate our tests with a list of parameters. We must combine
+// all variations of the boolean flag suppressing PrecalcPrimeTable and some
+// meaningful values for tests. We choose a small value (1), and a value that
+// will put some of the tested numbers beyond the capability of the
+// PrecalcPrimeTable instance and some inside it (10). Combine will produce all
+// possible combinations.
+INSTANTIATE_TEST_CASE_P(MeaningfulTestParameters,
+                        PrimeTableTest,
+                        Combine(Bool(), Values(1, 10)));
+
+#else
+
+// Google Test may not support Combine() with some compilers. If we
+// use conditional compilation to compile out all code referring to
+// the gtest_main library, MSVC linker will not link that library at
+// all and consequently complain about missing entry point defined in
+// that library (fatal error LNK1561: entry point must be
+// defined). This dummy test keeps gtest_main linked in.
+TEST(DummyTest, CombineIsNotSupportedOnThisPlatform) {}
+
+#endif  // GTEST_HAS_COMBINE
diff --git a/third_party/googletest/googletest/samples/sample9_unittest.cc b/third_party/googletest/googletest/samples/sample9_unittest.cc
new file mode 100644
index 0000000..b2e2079
--- /dev/null
+++ b/third_party/googletest/googletest/samples/sample9_unittest.cc
@@ -0,0 +1,160 @@
+// Copyright 2009 Google Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vladl@google.com (Vlad Losev)
+
+// This sample shows how to use Google Test listener API to implement
+// an alternative console output and how to use the UnitTest reflection API
+// to enumerate test cases and tests and to inspect their results.
+
+#include <stdio.h>
+
+#include "gtest/gtest.h"
+
+using ::testing::EmptyTestEventListener;
+using ::testing::InitGoogleTest;
+using ::testing::Test;
+using ::testing::TestCase;
+using ::testing::TestEventListeners;
+using ::testing::TestInfo;
+using ::testing::TestPartResult;
+using ::testing::UnitTest;
+
+namespace {
+
+// Provides alternative output mode which produces minimal amount of
+// information about tests.
+class TersePrinter : public EmptyTestEventListener {
+ private:
+  // Called before any test activity starts.
+  virtual void OnTestProgramStart(const UnitTest& /* unit_test */) {}
+
+  // Called after all test activities have ended.
+  virtual void OnTestProgramEnd(const UnitTest& unit_test) {
+    fprintf(stdout, "TEST %s\n", unit_test.Passed() ? "PASSED" : "FAILED");
+    fflush(stdout);
+  }
+
+  // Called before a test starts.
+  virtual void OnTestStart(const TestInfo& test_info) {
+    fprintf(stdout,
+            "*** Test %s.%s starting.\n",
+            test_info.test_case_name(),
+            test_info.name());
+    fflush(stdout);
+  }
+
+  // Called after a failed assertion or a SUCCEED() invocation.
+  virtual void OnTestPartResult(const TestPartResult& test_part_result) {
+    fprintf(stdout,
+            "%s in %s:%d\n%s\n",
+            test_part_result.failed() ? "*** Failure" : "Success",
+            test_part_result.file_name(),
+            test_part_result.line_number(),
+            test_part_result.summary());
+    fflush(stdout);
+  }
+
+  // Called after a test ends.
+  virtual void OnTestEnd(const TestInfo& test_info) {
+    fprintf(stdout,
+            "*** Test %s.%s ending.\n",
+            test_info.test_case_name(),
+            test_info.name());
+    fflush(stdout);
+  }
+};  // class TersePrinter
+
+TEST(CustomOutputTest, PrintsMessage) {
+  printf("Printing something from the test body...\n");
+}
+
+TEST(CustomOutputTest, Succeeds) {
+  SUCCEED() << "SUCCEED() has been invoked from here";
+}
+
+TEST(CustomOutputTest, Fails) {
+  EXPECT_EQ(1, 2)
+      << "This test fails in order to demonstrate alternative failure messages";
+}
+
+}  // namespace
+
+int main(int argc, char **argv) {
+  InitGoogleTest(&argc, argv);
+
+  bool terse_output = false;
+  if (argc > 1 && strcmp(argv[1], "--terse_output") == 0 )
+    terse_output = true;
+  else
+    printf("%s\n", "Run this program with --terse_output to change the way "
+           "it prints its output.");
+
+  UnitTest& unit_test = *UnitTest::GetInstance();
+
+  // If we are given the --terse_output command line flag, suppresses the
+  // standard output and attaches own result printer.
+  if (terse_output) {
+    TestEventListeners& listeners = unit_test.listeners();
+
+    // Removes the default console output listener from the list so it will
+    // not receive events from Google Test and won't print any output. Since
+    // this operation transfers ownership of the listener to the caller we
+    // have to delete it as well.
+    delete listeners.Release(listeners.default_result_printer());
+
+    // Adds the custom output listener to the list. It will now receive
+    // events from Google Test and print the alternative output. We don't
+    // have to worry about deleting it since Google Test assumes ownership
+    // over it after adding it to the list.
+    listeners.Append(new TersePrinter);
+  }
+  int ret_val = RUN_ALL_TESTS();
+
+  // This is an example of using the UnitTest reflection API to inspect test
+  // results. Here we discount failures from the tests we expected to fail.
+  int unexpectedly_failed_tests = 0;
+  for (int i = 0; i < unit_test.total_test_case_count(); ++i) {
+    const TestCase& test_case = *unit_test.GetTestCase(i);
+    for (int j = 0; j < test_case.total_test_count(); ++j) {
+      const TestInfo& test_info = *test_case.GetTestInfo(j);
+      // Counts failed tests that were not meant to fail (those without
+      // 'Fails' in the name).
+      if (test_info.result()->Failed() &&
+          strcmp(test_info.name(), "Fails") != 0) {
+        unexpectedly_failed_tests++;
+      }
+    }
+  }
+
+  // Test that were meant to fail should not affect the test program outcome.
+  if (unexpectedly_failed_tests == 0)
+    ret_val = 0;
+
+  return ret_val;
+}
diff --git a/third_party/googletest/googletest/scripts/common.py b/third_party/googletest/googletest/scripts/common.py
new file mode 100644
index 0000000..3c0347a
--- /dev/null
+++ b/third_party/googletest/googletest/scripts/common.py
@@ -0,0 +1,83 @@
+# Copyright 2013 Google Inc. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Shared utilities for writing scripts for Google Test/Mock."""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+
+import os
+import re
+
+
+# Matches the line from 'svn info .' output that describes what SVN
+# path the current local directory corresponds to.  For example, in
+# a googletest SVN workspace's trunk/test directory, the output will be:
+#
+# URL: https://googletest.googlecode.com/svn/trunk/test
+_SVN_INFO_URL_RE = re.compile(r'^URL: https://(\w+)\.googlecode\.com/svn(.*)')
+
+
+def GetCommandOutput(command):
+  """Runs the shell command and returns its stdout as a list of lines."""
+
+  f = os.popen(command, 'r')
+  lines = [line.strip() for line in f.readlines()]
+  f.close()
+  return lines
+
+
+def GetSvnInfo():
+  """Returns the project name and the current SVN workspace's root path."""
+
+  for line in GetCommandOutput('svn info .'):
+    m = _SVN_INFO_URL_RE.match(line)
+    if m:
+      project = m.group(1)  # googletest or googlemock
+      rel_path = m.group(2)
+      root = os.path.realpath(rel_path.count('/') * '../')
+      return project, root
+
+  return None, None
+
+
+def GetSvnTrunk():
+  """Returns the current SVN workspace's trunk root path."""
+
+  _, root = GetSvnInfo()
+  return root + '/trunk' if root else None
+
+
+def IsInGTestSvn():
+  project, _ = GetSvnInfo()
+  return project == 'googletest'
+
+
+def IsInGMockSvn():
+  project, _ = GetSvnInfo()
+  return project == 'googlemock'
diff --git a/third_party/googletest/googletest/scripts/fuse_gtest_files.py b/third_party/googletest/googletest/scripts/fuse_gtest_files.py
new file mode 100755
index 0000000..57ef72f
--- /dev/null
+++ b/third_party/googletest/googletest/scripts/fuse_gtest_files.py
@@ -0,0 +1,250 @@
+#!/usr/bin/env python
+#
+# Copyright 2009, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""fuse_gtest_files.py v0.2.0
+Fuses Google Test source code into a .h file and a .cc file.
+
+SYNOPSIS
+       fuse_gtest_files.py [GTEST_ROOT_DIR] OUTPUT_DIR
+
+       Scans GTEST_ROOT_DIR for Google Test source code, and generates
+       two files: OUTPUT_DIR/gtest/gtest.h and OUTPUT_DIR/gtest/gtest-all.cc.
+       Then you can build your tests by adding OUTPUT_DIR to the include
+       search path and linking with OUTPUT_DIR/gtest/gtest-all.cc.  These
+       two files contain everything you need to use Google Test.  Hence
+       you can "install" Google Test by copying them to wherever you want.
+
+       GTEST_ROOT_DIR can be omitted and defaults to the parent
+       directory of the directory holding this script.
+
+EXAMPLES
+       ./fuse_gtest_files.py fused_gtest
+       ./fuse_gtest_files.py path/to/unpacked/gtest fused_gtest
+
+This tool is experimental.  In particular, it assumes that there is no
+conditional inclusion of Google Test headers.  Please report any
+problems to googletestframework@googlegroups.com.  You can read
+http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide for
+more information.
+"""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import os
+import re
+import sets
+import sys
+
+# We assume that this file is in the scripts/ directory in the Google
+# Test root directory.
+DEFAULT_GTEST_ROOT_DIR = os.path.join(os.path.dirname(__file__), '..')
+
+# Regex for matching '#include "gtest/..."'.
+INCLUDE_GTEST_FILE_REGEX = re.compile(r'^\s*#\s*include\s*"(gtest/.+)"')
+
+# Regex for matching '#include "src/..."'.
+INCLUDE_SRC_FILE_REGEX = re.compile(r'^\s*#\s*include\s*"(src/.+)"')
+
+# Where to find the source seed files.
+GTEST_H_SEED = 'include/gtest/gtest.h'
+GTEST_SPI_H_SEED = 'include/gtest/gtest-spi.h'
+GTEST_ALL_CC_SEED = 'src/gtest-all.cc'
+
+# Where to put the generated files.
+GTEST_H_OUTPUT = 'gtest/gtest.h'
+GTEST_ALL_CC_OUTPUT = 'gtest/gtest-all.cc'
+
+
+def VerifyFileExists(directory, relative_path):
+  """Verifies that the given file exists; aborts on failure.
+
+  relative_path is the file path relative to the given directory.
+  """
+
+  if not os.path.isfile(os.path.join(directory, relative_path)):
+    print 'ERROR: Cannot find %s in directory %s.' % (relative_path,
+                                                      directory)
+    print ('Please either specify a valid project root directory '
+           'or omit it on the command line.')
+    sys.exit(1)
+
+
+def ValidateGTestRootDir(gtest_root):
+  """Makes sure gtest_root points to a valid gtest root directory.
+
+  The function aborts the program on failure.
+  """
+
+  VerifyFileExists(gtest_root, GTEST_H_SEED)
+  VerifyFileExists(gtest_root, GTEST_ALL_CC_SEED)
+
+
+def VerifyOutputFile(output_dir, relative_path):
+  """Verifies that the given output file path is valid.
+
+  relative_path is relative to the output_dir directory.
+  """
+
+  # Makes sure the output file either doesn't exist or can be overwritten.
+  output_file = os.path.join(output_dir, relative_path)
+  if os.path.exists(output_file):
+    # TODO(wan@google.com): The following user-interaction doesn't
+    # work with automated processes.  We should provide a way for the
+    # Makefile to force overwriting the files.
+    print ('%s already exists in directory %s - overwrite it? (y/N) ' %
+           (relative_path, output_dir))
+    answer = sys.stdin.readline().strip()
+    if answer not in ['y', 'Y']:
+      print 'ABORTED.'
+      sys.exit(1)
+
+  # Makes sure the directory holding the output file exists; creates
+  # it and all its ancestors if necessary.
+  parent_directory = os.path.dirname(output_file)
+  if not os.path.isdir(parent_directory):
+    os.makedirs(parent_directory)
+
+
+def ValidateOutputDir(output_dir):
+  """Makes sure output_dir points to a valid output directory.
+
+  The function aborts the program on failure.
+  """
+
+  VerifyOutputFile(output_dir, GTEST_H_OUTPUT)
+  VerifyOutputFile(output_dir, GTEST_ALL_CC_OUTPUT)
+
+
+def FuseGTestH(gtest_root, output_dir):
+  """Scans folder gtest_root to generate gtest/gtest.h in output_dir."""
+
+  output_file = file(os.path.join(output_dir, GTEST_H_OUTPUT), 'w')
+  processed_files = sets.Set()  # Holds all gtest headers we've processed.
+
+  def ProcessFile(gtest_header_path):
+    """Processes the given gtest header file."""
+
+    # We don't process the same header twice.
+    if gtest_header_path in processed_files:
+      return
+
+    processed_files.add(gtest_header_path)
+
+    # Reads each line in the given gtest header.
+    for line in file(os.path.join(gtest_root, gtest_header_path), 'r'):
+      m = INCLUDE_GTEST_FILE_REGEX.match(line)
+      if m:
+        # It's '#include "gtest/..."' - let's process it recursively.
+        ProcessFile('include/' + m.group(1))
+      else:
+        # Otherwise we copy the line unchanged to the output file.
+        output_file.write(line)
+
+  ProcessFile(GTEST_H_SEED)
+  output_file.close()
+
+
+def FuseGTestAllCcToFile(gtest_root, output_file):
+  """Scans folder gtest_root to generate gtest/gtest-all.cc in output_file."""
+
+  processed_files = sets.Set()
+
+  def ProcessFile(gtest_source_file):
+    """Processes the given gtest source file."""
+
+    # We don't process the same #included file twice.
+    if gtest_source_file in processed_files:
+      return
+
+    processed_files.add(gtest_source_file)
+
+    # Reads each line in the given gtest source file.
+    for line in file(os.path.join(gtest_root, gtest_source_file), 'r'):
+      m = INCLUDE_GTEST_FILE_REGEX.match(line)
+      if m:
+        if 'include/' + m.group(1) == GTEST_SPI_H_SEED:
+          # It's '#include "gtest/gtest-spi.h"'.  This file is not
+          # #included by "gtest/gtest.h", so we need to process it.
+          ProcessFile(GTEST_SPI_H_SEED)
+        else:
+          # It's '#include "gtest/foo.h"' where foo is not gtest-spi.
+          # We treat it as '#include "gtest/gtest.h"', as all other
+          # gtest headers are being fused into gtest.h and cannot be
+          # #included directly.
+
+          # There is no need to #include "gtest/gtest.h" more than once.
+          if not GTEST_H_SEED in processed_files:
+            processed_files.add(GTEST_H_SEED)
+            output_file.write('#include "%s"\n' % (GTEST_H_OUTPUT,))
+      else:
+        m = INCLUDE_SRC_FILE_REGEX.match(line)
+        if m:
+          # It's '#include "src/foo"' - let's process it recursively.
+          ProcessFile(m.group(1))
+        else:
+          output_file.write(line)
+
+  ProcessFile(GTEST_ALL_CC_SEED)
+
+
+def FuseGTestAllCc(gtest_root, output_dir):
+  """Scans folder gtest_root to generate gtest/gtest-all.cc in output_dir."""
+
+  output_file = file(os.path.join(output_dir, GTEST_ALL_CC_OUTPUT), 'w')
+  FuseGTestAllCcToFile(gtest_root, output_file)
+  output_file.close()
+
+
+def FuseGTest(gtest_root, output_dir):
+  """Fuses gtest.h and gtest-all.cc."""
+
+  ValidateGTestRootDir(gtest_root)
+  ValidateOutputDir(output_dir)
+
+  FuseGTestH(gtest_root, output_dir)
+  FuseGTestAllCc(gtest_root, output_dir)
+
+
+def main():
+  argc = len(sys.argv)
+  if argc == 2:
+    # fuse_gtest_files.py OUTPUT_DIR
+    FuseGTest(DEFAULT_GTEST_ROOT_DIR, sys.argv[1])
+  elif argc == 3:
+    # fuse_gtest_files.py GTEST_ROOT_DIR OUTPUT_DIR
+    FuseGTest(sys.argv[1], sys.argv[2])
+  else:
+    print __doc__
+    sys.exit(1)
+
+
+if __name__ == '__main__':
+  main()
diff --git a/third_party/googletest/googletest/scripts/gen_gtest_pred_impl.py b/third_party/googletest/googletest/scripts/gen_gtest_pred_impl.py
new file mode 100755
index 0000000..3e7ab04
--- /dev/null
+++ b/third_party/googletest/googletest/scripts/gen_gtest_pred_impl.py
@@ -0,0 +1,730 @@
+#!/usr/bin/env python
+#
+# Copyright 2006, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""gen_gtest_pred_impl.py v0.1
+
+Generates the implementation of Google Test predicate assertions and
+accompanying tests.
+
+Usage:
+
+  gen_gtest_pred_impl.py MAX_ARITY
+
+where MAX_ARITY is a positive integer.
+
+The command generates the implementation of up-to MAX_ARITY-ary
+predicate assertions, and writes it to file gtest_pred_impl.h in the
+directory where the script is.  It also generates the accompanying
+unit test in file gtest_pred_impl_unittest.cc.
+"""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import os
+import sys
+import time
+
+# Where this script is.
+SCRIPT_DIR = os.path.dirname(sys.argv[0])
+
+# Where to store the generated header.
+HEADER = os.path.join(SCRIPT_DIR, '../include/gtest/gtest_pred_impl.h')
+
+# Where to store the generated unit test.
+UNIT_TEST = os.path.join(SCRIPT_DIR, '../test/gtest_pred_impl_unittest.cc')
+
+
+def HeaderPreamble(n):
+  """Returns the preamble for the header file.
+
+  Args:
+    n:  the maximum arity of the predicate macros to be generated.
+  """
+
+  # A map that defines the values used in the preamble template.
+  DEFS = {
+    'today' : time.strftime('%m/%d/%Y'),
+    'year' : time.strftime('%Y'),
+    'command' : '%s %s' % (os.path.basename(sys.argv[0]), n),
+    'n' : n
+    }
+
+  return (
+"""// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This file is AUTOMATICALLY GENERATED on %(today)s by command
+// '%(command)s'.  DO NOT EDIT BY HAND!
+//
+// Implements a family of generic predicate assertion macros.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+
+// Makes sure this header is not included before gtest.h.
+#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
+# error Do not include gtest_pred_impl.h directly.  Include gtest.h instead.
+#endif  // GTEST_INCLUDE_GTEST_GTEST_H_
+
+// This header implements a family of generic predicate assertion
+// macros:
+//
+//   ASSERT_PRED_FORMAT1(pred_format, v1)
+//   ASSERT_PRED_FORMAT2(pred_format, v1, v2)
+//   ...
+//
+// where pred_format is a function or functor that takes n (in the
+// case of ASSERT_PRED_FORMATn) values and their source expression
+// text, and returns a testing::AssertionResult.  See the definition
+// of ASSERT_EQ in gtest.h for an example.
+//
+// If you don't care about formatting, you can use the more
+// restrictive version:
+//
+//   ASSERT_PRED1(pred, v1)
+//   ASSERT_PRED2(pred, v1, v2)
+//   ...
+//
+// where pred is an n-ary function or functor that returns bool,
+// and the values v1, v2, ..., must support the << operator for
+// streaming to std::ostream.
+//
+// We also define the EXPECT_* variations.
+//
+// For now we only support predicates whose arity is at most %(n)s.
+// Please email googletestframework@googlegroups.com if you need
+// support for higher arities.
+
+// GTEST_ASSERT_ is the basic statement to which all of the assertions
+// in this file reduce.  Don't use this in your code.
+
+#define GTEST_ASSERT_(expression, on_failure) \\
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \\
+  if (const ::testing::AssertionResult gtest_ar = (expression)) \\
+    ; \\
+  else \\
+    on_failure(gtest_ar.failure_message())
+""" % DEFS)
+
+
+def Arity(n):
+  """Returns the English name of the given arity."""
+
+  if n < 0:
+    return None
+  elif n <= 3:
+    return ['nullary', 'unary', 'binary', 'ternary'][n]
+  else:
+    return '%s-ary' % n
+
+
+def Title(word):
+  """Returns the given word in title case.  The difference between
+  this and string's title() method is that Title('4-ary') is '4-ary'
+  while '4-ary'.title() is '4-Ary'."""
+
+  return word[0].upper() + word[1:]
+
+
+def OneTo(n):
+  """Returns the list [1, 2, 3, ..., n]."""
+
+  return range(1, n + 1)
+
+
+def Iter(n, format, sep=''):
+  """Given a positive integer n, a format string that contains 0 or
+  more '%s' format specs, and optionally a separator string, returns
+  the join of n strings, each formatted with the format string on an
+  iterator ranged from 1 to n.
+
+  Example:
+
+  Iter(3, 'v%s', sep=', ') returns 'v1, v2, v3'.
+  """
+
+  # How many '%s' specs are in format?
+  spec_count = len(format.split('%s')) - 1
+  return sep.join([format % (spec_count * (i,)) for i in OneTo(n)])
+
+
+def ImplementationForArity(n):
+  """Returns the implementation of n-ary predicate assertions."""
+
+  # A map the defines the values used in the implementation template.
+  DEFS = {
+    'n' : str(n),
+    'vs' : Iter(n, 'v%s', sep=', '),
+    'vts' : Iter(n, '#v%s', sep=', '),
+    'arity' : Arity(n),
+    'Arity' : Title(Arity(n))
+    }
+
+  impl = """
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED%(n)s.  Don't use
+// this in your code.
+template <typename Pred""" % DEFS
+
+  impl += Iter(n, """,
+          typename T%s""")
+
+  impl += """>
+AssertionResult AssertPred%(n)sHelper(const char* pred_text""" % DEFS
+
+  impl += Iter(n, """,
+                                  const char* e%s""")
+
+  impl += """,
+                                  Pred pred"""
+
+  impl += Iter(n, """,
+                                  const T%s& v%s""")
+
+  impl += """) {
+  if (pred(%(vs)s)) return AssertionSuccess();
+
+""" % DEFS
+
+  impl += '  return AssertionFailure() << pred_text << "("'
+
+  impl += Iter(n, """
+                            << e%s""", sep=' << ", "')
+
+  impl += ' << ") evaluates to false, where"'
+
+  impl += Iter(n, """
+                            << "\\n" << e%s << " evaluates to " << v%s""")
+
+  impl += """;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT%(n)s.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT%(n)s_(pred_format, %(vs)s, on_failure)\\
+  GTEST_ASSERT_(pred_format(%(vts)s, %(vs)s), \\
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED%(n)s.  Don't use
+// this in your code.
+#define GTEST_PRED%(n)s_(pred, %(vs)s, on_failure)\\
+  GTEST_ASSERT_(::testing::AssertPred%(n)sHelper(#pred""" % DEFS
+
+  impl += Iter(n, """, \\
+                                             #v%s""")
+
+  impl += """, \\
+                                             pred"""
+
+  impl += Iter(n, """, \\
+                                             v%s""")
+
+  impl += """), on_failure)
+
+// %(Arity)s predicate assertion macros.
+#define EXPECT_PRED_FORMAT%(n)s(pred_format, %(vs)s) \\
+  GTEST_PRED_FORMAT%(n)s_(pred_format, %(vs)s, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED%(n)s(pred, %(vs)s) \\
+  GTEST_PRED%(n)s_(pred, %(vs)s, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT%(n)s(pred_format, %(vs)s) \\
+  GTEST_PRED_FORMAT%(n)s_(pred_format, %(vs)s, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED%(n)s(pred, %(vs)s) \\
+  GTEST_PRED%(n)s_(pred, %(vs)s, GTEST_FATAL_FAILURE_)
+
+""" % DEFS
+
+  return impl
+
+
+def HeaderPostamble():
+  """Returns the postamble for the header file."""
+
+  return """
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+"""
+
+
+def GenerateFile(path, content):
+  """Given a file path and a content string, overwrites it with the
+  given content."""
+
+  print 'Updating file %s . . .' % path
+
+  f = file(path, 'w+')
+  print >>f, content,
+  f.close()
+
+  print 'File %s has been updated.' % path
+
+
+def GenerateHeader(n):
+  """Given the maximum arity n, updates the header file that implements
+  the predicate assertions."""
+
+  GenerateFile(HEADER,
+               HeaderPreamble(n)
+               + ''.join([ImplementationForArity(i) for i in OneTo(n)])
+               + HeaderPostamble())
+
+
+def UnitTestPreamble():
+  """Returns the preamble for the unit test file."""
+
+  # A map that defines the values used in the preamble template.
+  DEFS = {
+    'today' : time.strftime('%m/%d/%Y'),
+    'year' : time.strftime('%Y'),
+    'command' : '%s %s' % (os.path.basename(sys.argv[0]), sys.argv[1]),
+    }
+
+  return (
+"""// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This file is AUTOMATICALLY GENERATED on %(today)s by command
+// '%(command)s'.  DO NOT EDIT BY HAND!
+
+// Regression test for gtest_pred_impl.h
+//
+// This file is generated by a script and quite long.  If you intend to
+// learn how Google Test works by reading its unit tests, read
+// gtest_unittest.cc instead.
+//
+// This is intended as a regression test for the Google Test predicate
+// assertions.  We compile it as part of the gtest_unittest target
+// only to keep the implementation tidy and compact, as it is quite
+// involved to set up the stage for testing Google Test using Google
+// Test itself.
+//
+// Currently, gtest_unittest takes ~11 seconds to run in the testing
+// daemon.  In the future, if it grows too large and needs much more
+// time to finish, we should consider separating this file into a
+// stand-alone regression test.
+
+#include <iostream>
+
+#include "gtest/gtest.h"
+#include "gtest/gtest-spi.h"
+
+// A user-defined data type.
+struct Bool {
+  explicit Bool(int val) : value(val != 0) {}
+
+  bool operator>(int n) const { return value > Bool(n).value; }
+
+  Bool operator+(const Bool& rhs) const { return Bool(value + rhs.value); }
+
+  bool operator==(const Bool& rhs) const { return value == rhs.value; }
+
+  bool value;
+};
+
+// Enables Bool to be used in assertions.
+std::ostream& operator<<(std::ostream& os, const Bool& x) {
+  return os << (x.value ? "true" : "false");
+}
+
+""" % DEFS)
+
+
+def TestsForArity(n):
+  """Returns the tests for n-ary predicate assertions."""
+
+  # A map that defines the values used in the template for the tests.
+  DEFS = {
+    'n' : n,
+    'es' : Iter(n, 'e%s', sep=', '),
+    'vs' : Iter(n, 'v%s', sep=', '),
+    'vts' : Iter(n, '#v%s', sep=', '),
+    'tvs' : Iter(n, 'T%s v%s', sep=', '),
+    'int_vs' : Iter(n, 'int v%s', sep=', '),
+    'Bool_vs' : Iter(n, 'Bool v%s', sep=', '),
+    'types' : Iter(n, 'typename T%s', sep=', '),
+    'v_sum' : Iter(n, 'v%s', sep=' + '),
+    'arity' : Arity(n),
+    'Arity' : Title(Arity(n)),
+    }
+
+  tests = (
+"""// Sample functions/functors for testing %(arity)s predicate assertions.
+
+// A %(arity)s predicate function.
+template <%(types)s>
+bool PredFunction%(n)s(%(tvs)s) {
+  return %(v_sum)s > 0;
+}
+
+// The following two functions are needed to circumvent a bug in
+// gcc 2.95.3, which sometimes has problem with the above template
+// function.
+bool PredFunction%(n)sInt(%(int_vs)s) {
+  return %(v_sum)s > 0;
+}
+bool PredFunction%(n)sBool(%(Bool_vs)s) {
+  return %(v_sum)s > 0;
+}
+""" % DEFS)
+
+  tests += """
+// A %(arity)s predicate functor.
+struct PredFunctor%(n)s {
+  template <%(types)s>
+  bool operator()(""" % DEFS
+
+  tests += Iter(n, 'const T%s& v%s', sep=""",
+                  """)
+
+  tests += """) {
+    return %(v_sum)s > 0;
+  }
+};
+""" % DEFS
+
+  tests += """
+// A %(arity)s predicate-formatter function.
+template <%(types)s>
+testing::AssertionResult PredFormatFunction%(n)s(""" % DEFS
+
+  tests += Iter(n, 'const char* e%s', sep=""",
+                                             """)
+
+  tests += Iter(n, """,
+                                             const T%s& v%s""")
+
+  tests += """) {
+  if (PredFunction%(n)s(%(vs)s))
+    return testing::AssertionSuccess();
+
+  return testing::AssertionFailure()
+      << """ % DEFS
+
+  tests += Iter(n, 'e%s', sep=' << " + " << ')
+
+  tests += """
+      << " is expected to be positive, but evaluates to "
+      << %(v_sum)s << ".";
+}
+""" % DEFS
+
+  tests += """
+// A %(arity)s predicate-formatter functor.
+struct PredFormatFunctor%(n)s {
+  template <%(types)s>
+  testing::AssertionResult operator()(""" % DEFS
+
+  tests += Iter(n, 'const char* e%s', sep=""",
+                                      """)
+
+  tests += Iter(n, """,
+                                      const T%s& v%s""")
+
+  tests += """) const {
+    return PredFormatFunction%(n)s(%(es)s, %(vs)s);
+  }
+};
+""" % DEFS
+
+  tests += """
+// Tests for {EXPECT|ASSERT}_PRED_FORMAT%(n)s.
+
+class Predicate%(n)sTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    expected_to_finish_ = true;
+    finished_ = false;""" % DEFS
+
+  tests += """
+    """ + Iter(n, 'n%s_ = ') + """0;
+  }
+"""
+
+  tests += """
+  virtual void TearDown() {
+    // Verifies that each of the predicate's arguments was evaluated
+    // exactly once."""
+
+  tests += ''.join(["""
+    EXPECT_EQ(1, n%s_) <<
+        "The predicate assertion didn't evaluate argument %s "
+        "exactly once.";""" % (i, i + 1) for i in OneTo(n)])
+
+  tests += """
+
+    // Verifies that the control flow in the test function is expected.
+    if (expected_to_finish_ && !finished_) {
+      FAIL() << "The predicate assertion unexpactedly aborted the test.";
+    } else if (!expected_to_finish_ && finished_) {
+      FAIL() << "The failed predicate assertion didn't abort the test "
+                "as expected.";
+    }
+  }
+
+  // true iff the test function is expected to run to finish.
+  static bool expected_to_finish_;
+
+  // true iff the test function did run to finish.
+  static bool finished_;
+""" % DEFS
+
+  tests += Iter(n, """
+  static int n%s_;""")
+
+  tests += """
+};
+
+bool Predicate%(n)sTest::expected_to_finish_;
+bool Predicate%(n)sTest::finished_;
+""" % DEFS
+
+  tests += Iter(n, """int Predicate%%(n)sTest::n%s_;
+""") % DEFS
+
+  tests += """
+typedef Predicate%(n)sTest EXPECT_PRED_FORMAT%(n)sTest;
+typedef Predicate%(n)sTest ASSERT_PRED_FORMAT%(n)sTest;
+typedef Predicate%(n)sTest EXPECT_PRED%(n)sTest;
+typedef Predicate%(n)sTest ASSERT_PRED%(n)sTest;
+""" % DEFS
+
+  def GenTest(use_format, use_assert, expect_failure,
+              use_functor, use_user_type):
+    """Returns the test for a predicate assertion macro.
+
+    Args:
+      use_format:     true iff the assertion is a *_PRED_FORMAT*.
+      use_assert:     true iff the assertion is a ASSERT_*.
+      expect_failure: true iff the assertion is expected to fail.
+      use_functor:    true iff the first argument of the assertion is
+                      a functor (as opposed to a function)
+      use_user_type:  true iff the predicate functor/function takes
+                      argument(s) of a user-defined type.
+
+    Example:
+
+      GenTest(1, 0, 0, 1, 0) returns a test that tests the behavior
+      of a successful EXPECT_PRED_FORMATn() that takes a functor
+      whose arguments have built-in types."""
+
+    if use_assert:
+      assrt = 'ASSERT'  # 'assert' is reserved, so we cannot use
+                        # that identifier here.
+    else:
+      assrt = 'EXPECT'
+
+    assertion = assrt + '_PRED'
+
+    if use_format:
+      pred_format = 'PredFormat'
+      assertion += '_FORMAT'
+    else:
+      pred_format = 'Pred'
+
+    assertion += '%(n)s' % DEFS
+
+    if use_functor:
+      pred_format_type = 'functor'
+      pred_format += 'Functor%(n)s()'
+    else:
+      pred_format_type = 'function'
+      pred_format += 'Function%(n)s'
+      if not use_format:
+        if use_user_type:
+          pred_format += 'Bool'
+        else:
+          pred_format += 'Int'
+
+    test_name = pred_format_type.title()
+
+    if use_user_type:
+      arg_type = 'user-defined type (Bool)'
+      test_name += 'OnUserType'
+      if expect_failure:
+        arg = 'Bool(n%s_++)'
+      else:
+        arg = 'Bool(++n%s_)'
+    else:
+      arg_type = 'built-in type (int)'
+      test_name += 'OnBuiltInType'
+      if expect_failure:
+        arg = 'n%s_++'
+      else:
+        arg = '++n%s_'
+
+    if expect_failure:
+      successful_or_failed = 'failed'
+      expected_or_not = 'expected.'
+      test_name +=  'Failure'
+    else:
+      successful_or_failed = 'successful'
+      expected_or_not = 'UNEXPECTED!'
+      test_name +=  'Success'
+
+    # A map that defines the values used in the test template.
+    defs = DEFS.copy()
+    defs.update({
+      'assert' : assrt,
+      'assertion' : assertion,
+      'test_name' : test_name,
+      'pf_type' : pred_format_type,
+      'pf' : pred_format,
+      'arg_type' : arg_type,
+      'arg' : arg,
+      'successful' : successful_or_failed,
+      'expected' : expected_or_not,
+      })
+
+    test = """
+// Tests a %(successful)s %(assertion)s where the
+// predicate-formatter is a %(pf_type)s on a %(arg_type)s.
+TEST_F(%(assertion)sTest, %(test_name)s) {""" % defs
+
+    indent = (len(assertion) + 3)*' '
+    extra_indent = ''
+
+    if expect_failure:
+      extra_indent = '  '
+      if use_assert:
+        test += """
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT"""
+      else:
+        test += """
+  EXPECT_NONFATAL_FAILURE({  // NOLINT"""
+
+    test += '\n' + extra_indent + """  %(assertion)s(%(pf)s""" % defs
+
+    test = test % defs
+    test += Iter(n, ',\n' + indent + extra_indent + '%(arg)s' % defs)
+    test += ');\n' + extra_indent + '  finished_ = true;\n'
+
+    if expect_failure:
+      test += '  }, "");\n'
+
+    test += '}\n'
+    return test
+
+  # Generates tests for all 2**6 = 64 combinations.
+  tests += ''.join([GenTest(use_format, use_assert, expect_failure,
+                            use_functor, use_user_type)
+                    for use_format in [0, 1]
+                    for use_assert in [0, 1]
+                    for expect_failure in [0, 1]
+                    for use_functor in [0, 1]
+                    for use_user_type in [0, 1]
+                    ])
+
+  return tests
+
+
+def UnitTestPostamble():
+  """Returns the postamble for the tests."""
+
+  return ''
+
+
+def GenerateUnitTest(n):
+  """Returns the tests for up-to n-ary predicate assertions."""
+
+  GenerateFile(UNIT_TEST,
+               UnitTestPreamble()
+               + ''.join([TestsForArity(i) for i in OneTo(n)])
+               + UnitTestPostamble())
+
+
+def _Main():
+  """The entry point of the script.  Generates the header file and its
+  unit test."""
+
+  if len(sys.argv) != 2:
+    print __doc__
+    print 'Author: ' + __author__
+    sys.exit(1)
+
+  n = int(sys.argv[1])
+  GenerateHeader(n)
+  GenerateUnitTest(n)
+
+
+if __name__ == '__main__':
+  _Main()
diff --git a/third_party/googletest/googletest/scripts/gtest-config.in b/third_party/googletest/googletest/scripts/gtest-config.in
new file mode 100755
index 0000000..780f843
--- /dev/null
+++ b/third_party/googletest/googletest/scripts/gtest-config.in
@@ -0,0 +1,274 @@
+#!/bin/sh
+
+# These variables are automatically filled in by the configure script.
+name="@PACKAGE_TARNAME@"
+version="@PACKAGE_VERSION@"
+
+show_usage()
+{
+  echo "Usage: gtest-config [OPTIONS...]"
+}
+
+show_help()
+{
+  show_usage
+  cat <<\EOF
+
+The `gtest-config' script provides access to the necessary compile and linking
+flags to connect with Google C++ Testing Framework, both in a build prior to
+installation, and on the system proper after installation. The installation
+overrides may be issued in combination with any other queries, but will only
+affect installation queries if called on a built but not installed gtest. The
+installation queries may not be issued with any other types of queries, and
+only one installation query may be made at a time. The version queries and
+compiler flag queries may be combined as desired but not mixed. Different
+version queries are always combined with logical "and" semantics, and only the
+last of any particular query is used while all previous ones ignored. All
+versions must be specified as a sequence of numbers separated by periods.
+Compiler flag queries output the union of the sets of flags when combined.
+
+ Examples:
+  gtest-config --min-version=1.0 || echo "Insufficient Google Test version."
+
+  g++ $(gtest-config --cppflags --cxxflags) -o foo.o -c foo.cpp
+  g++ $(gtest-config --ldflags --libs) -o foo foo.o
+
+  # When using a built but not installed Google Test:
+  g++ $(../../my_gtest_build/scripts/gtest-config ...) ...
+
+  # When using an installed Google Test, but with installation overrides:
+  export GTEST_PREFIX="/opt"
+  g++ $(gtest-config --libdir="/opt/lib64" ...) ...
+
+ Help:
+  --usage                    brief usage information
+  --help                     display this help message
+
+ Installation Overrides:
+  --prefix=<dir>             overrides the installation prefix
+  --exec-prefix=<dir>        overrides the executable installation prefix
+  --libdir=<dir>             overrides the library installation prefix
+  --includedir=<dir>         overrides the header file installation prefix
+
+ Installation Queries:
+  --prefix                   installation prefix
+  --exec-prefix              executable installation prefix
+  --libdir                   library installation directory
+  --includedir               header file installation directory
+  --version                  the version of the Google Test installation
+
+ Version Queries:
+  --min-version=VERSION      return 0 if the version is at least VERSION
+  --exact-version=VERSION    return 0 if the version is exactly VERSION
+  --max-version=VERSION      return 0 if the version is at most VERSION
+
+ Compilation Flag Queries:
+  --cppflags                 compile flags specific to the C-like preprocessors
+  --cxxflags                 compile flags appropriate for C++ programs
+  --ldflags                  linker flags
+  --libs                     libraries for linking
+
+EOF
+}
+
+# This function bounds our version with a min and a max. It uses some clever
+# POSIX-compliant variable expansion to portably do all the work in the shell
+# and avoid any dependency on a particular "sed" or "awk" implementation.
+# Notable is that it will only ever compare the first 3 components of versions.
+# Further components will be cleanly stripped off. All versions must be
+# unadorned, so "v1.0" will *not* work. The minimum version must be in $1, and
+# the max in $2. TODO(chandlerc@google.com): If this ever breaks, we should
+# investigate expanding this via autom4te from AS_VERSION_COMPARE rather than
+# continuing to maintain our own shell version.
+check_versions()
+{
+  major_version=${version%%.*}
+  minor_version="0"
+  point_version="0"
+  if test "${version#*.}" != "${version}"; then
+    minor_version=${version#*.}
+    minor_version=${minor_version%%.*}
+  fi
+  if test "${version#*.*.}" != "${version}"; then
+    point_version=${version#*.*.}
+    point_version=${point_version%%.*}
+  fi
+
+  min_version="$1"
+  min_major_version=${min_version%%.*}
+  min_minor_version="0"
+  min_point_version="0"
+  if test "${min_version#*.}" != "${min_version}"; then
+    min_minor_version=${min_version#*.}
+    min_minor_version=${min_minor_version%%.*}
+  fi
+  if test "${min_version#*.*.}" != "${min_version}"; then
+    min_point_version=${min_version#*.*.}
+    min_point_version=${min_point_version%%.*}
+  fi
+
+  max_version="$2"
+  max_major_version=${max_version%%.*}
+  max_minor_version="0"
+  max_point_version="0"
+  if test "${max_version#*.}" != "${max_version}"; then
+    max_minor_version=${max_version#*.}
+    max_minor_version=${max_minor_version%%.*}
+  fi
+  if test "${max_version#*.*.}" != "${max_version}"; then
+    max_point_version=${max_version#*.*.}
+    max_point_version=${max_point_version%%.*}
+  fi
+
+  test $(($major_version)) -lt $(($min_major_version)) && exit 1
+  if test $(($major_version)) -eq $(($min_major_version)); then
+    test $(($minor_version)) -lt $(($min_minor_version)) && exit 1
+    if test $(($minor_version)) -eq $(($min_minor_version)); then
+      test $(($point_version)) -lt $(($min_point_version)) && exit 1
+    fi
+  fi
+
+  test $(($major_version)) -gt $(($max_major_version)) && exit 1
+  if test $(($major_version)) -eq $(($max_major_version)); then
+    test $(($minor_version)) -gt $(($max_minor_version)) && exit 1
+    if test $(($minor_version)) -eq $(($max_minor_version)); then
+      test $(($point_version)) -gt $(($max_point_version)) && exit 1
+    fi
+  fi
+
+  exit 0
+}
+
+# Show the usage line when no arguments are specified.
+if test $# -eq 0; then
+  show_usage
+  exit 1
+fi
+
+while test $# -gt 0; do
+  case $1 in
+    --usage)          show_usage;         exit 0;;
+    --help)           show_help;          exit 0;;
+
+    # Installation overrides
+    --prefix=*)       GTEST_PREFIX=${1#--prefix=};;
+    --exec-prefix=*)  GTEST_EXEC_PREFIX=${1#--exec-prefix=};;
+    --libdir=*)       GTEST_LIBDIR=${1#--libdir=};;
+    --includedir=*)   GTEST_INCLUDEDIR=${1#--includedir=};;
+
+    # Installation queries
+    --prefix|--exec-prefix|--libdir|--includedir|--version)
+      if test -n "${do_query}"; then
+        show_usage
+        exit 1
+      fi
+      do_query=${1#--}
+      ;;
+
+    # Version checking
+    --min-version=*)
+      do_check_versions=yes
+      min_version=${1#--min-version=}
+      ;;
+    --max-version=*)
+      do_check_versions=yes
+      max_version=${1#--max-version=}
+      ;;
+    --exact-version=*)
+      do_check_versions=yes
+      exact_version=${1#--exact-version=}
+      ;;
+
+    # Compiler flag output
+    --cppflags)       echo_cppflags=yes;;
+    --cxxflags)       echo_cxxflags=yes;;
+    --ldflags)        echo_ldflags=yes;;
+    --libs)           echo_libs=yes;;
+
+    # Everything else is an error
+    *)                show_usage;         exit 1;;
+  esac
+  shift
+done
+
+# These have defaults filled in by the configure script but can also be
+# overridden by environment variables or command line parameters.
+prefix="${GTEST_PREFIX:-@prefix@}"
+exec_prefix="${GTEST_EXEC_PREFIX:-@exec_prefix@}"
+libdir="${GTEST_LIBDIR:-@libdir@}"
+includedir="${GTEST_INCLUDEDIR:-@includedir@}"
+
+# We try and detect if our binary is not located at its installed location. If
+# it's not, we provide variables pointing to the source and build tree rather
+# than to the install tree. This allows building against a just-built gtest
+# rather than an installed gtest.
+bindir="@bindir@"
+this_relative_bindir=`dirname $0`
+this_bindir=`cd ${this_relative_bindir}; pwd -P`
+if test "${this_bindir}" = "${this_bindir%${bindir}}"; then
+  # The path to the script doesn't end in the bindir sequence from Autoconf,
+  # assume that we are in a build tree.
+  build_dir=`dirname ${this_bindir}`
+  src_dir=`cd ${this_bindir}; cd @top_srcdir@; pwd -P`
+
+  # TODO(chandlerc@google.com): This is a dangerous dependency on libtool, we
+  # should work to remove it, and/or remove libtool altogether, replacing it
+  # with direct references to the library and a link path.
+  gtest_libs="${build_dir}/lib/libgtest.la @PTHREAD_CFLAGS@ @PTHREAD_LIBS@"
+  gtest_ldflags=""
+
+  # We provide hooks to include from either the source or build dir, where the
+  # build dir is always preferred. This will potentially allow us to write
+  # build rules for generated headers and have them automatically be preferred
+  # over provided versions.
+  gtest_cppflags="-I${build_dir}/include -I${src_dir}/include"
+  gtest_cxxflags="@PTHREAD_CFLAGS@"
+else
+  # We're using an installed gtest, although it may be staged under some
+  # prefix. Assume (as our own libraries do) that we can resolve the prefix,
+  # and are present in the dynamic link paths.
+  gtest_ldflags="-L${libdir}"
+  gtest_libs="-l${name} @PTHREAD_CFLAGS@ @PTHREAD_LIBS@"
+  gtest_cppflags="-I${includedir}"
+  gtest_cxxflags="@PTHREAD_CFLAGS@"
+fi
+
+# Do an installation query if requested.
+if test -n "$do_query"; then
+  case $do_query in
+    prefix)           echo $prefix;       exit 0;;
+    exec-prefix)      echo $exec_prefix;  exit 0;;
+    libdir)           echo $libdir;       exit 0;;
+    includedir)       echo $includedir;   exit 0;;
+    version)          echo $version;      exit 0;;
+    *)                show_usage;         exit 1;;
+  esac
+fi
+
+# Do a version check if requested.
+if test "$do_check_versions" = "yes"; then
+  # Make sure we didn't receive a bad combination of parameters.
+  test "$echo_cppflags" = "yes" && show_usage && exit 1
+  test "$echo_cxxflags" = "yes" && show_usage && exit 1
+  test "$echo_ldflags" = "yes"  && show_usage && exit 1
+  test "$echo_libs" = "yes"     && show_usage && exit 1
+
+  if test "$exact_version" != ""; then
+    check_versions $exact_version $exact_version
+    # unreachable
+  else
+    check_versions ${min_version:-0.0.0} ${max_version:-9999.9999.9999}
+    # unreachable
+  fi
+fi
+
+# Do the output in the correct order so that these can be used in-line of
+# a compiler invocation.
+output=""
+test "$echo_cppflags" = "yes" && output="$output $gtest_cppflags"
+test "$echo_cxxflags" = "yes" && output="$output $gtest_cxxflags"
+test "$echo_ldflags" = "yes"  && output="$output $gtest_ldflags"
+test "$echo_libs" = "yes"     && output="$output $gtest_libs"
+echo $output
+
+exit 0
diff --git a/third_party/googletest/googletest/scripts/pump.py b/third_party/googletest/googletest/scripts/pump.py
new file mode 100755
index 0000000..5efb653
--- /dev/null
+++ b/third_party/googletest/googletest/scripts/pump.py
@@ -0,0 +1,855 @@
+#!/usr/bin/env python
+#
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""pump v0.2.0 - Pretty Useful for Meta Programming.
+
+A tool for preprocessor meta programming.  Useful for generating
+repetitive boilerplate code.  Especially useful for writing C++
+classes, functions, macros, and templates that need to work with
+various number of arguments.
+
+USAGE:
+       pump.py SOURCE_FILE
+
+EXAMPLES:
+       pump.py foo.cc.pump
+         Converts foo.cc.pump to foo.cc.
+
+GRAMMAR:
+       CODE ::= ATOMIC_CODE*
+       ATOMIC_CODE ::= $var ID = EXPRESSION
+           | $var ID = [[ CODE ]]
+           | $range ID EXPRESSION..EXPRESSION
+           | $for ID SEPARATOR [[ CODE ]]
+           | $($)
+           | $ID
+           | $(EXPRESSION)
+           | $if EXPRESSION [[ CODE ]] ELSE_BRANCH
+           | [[ CODE ]]
+           | RAW_CODE
+       SEPARATOR ::= RAW_CODE | EMPTY
+       ELSE_BRANCH ::= $else [[ CODE ]]
+           | $elif EXPRESSION [[ CODE ]] ELSE_BRANCH
+           | EMPTY
+       EXPRESSION has Python syntax.
+"""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import os
+import re
+import sys
+
+
+TOKEN_TABLE = [
+    (re.compile(r'\$var\s+'), '$var'),
+    (re.compile(r'\$elif\s+'), '$elif'),
+    (re.compile(r'\$else\s+'), '$else'),
+    (re.compile(r'\$for\s+'), '$for'),
+    (re.compile(r'\$if\s+'), '$if'),
+    (re.compile(r'\$range\s+'), '$range'),
+    (re.compile(r'\$[_A-Za-z]\w*'), '$id'),
+    (re.compile(r'\$\(\$\)'), '$($)'),
+    (re.compile(r'\$'), '$'),
+    (re.compile(r'\[\[\n?'), '[['),
+    (re.compile(r'\]\]\n?'), ']]'),
+    ]
+
+
+class Cursor:
+  """Represents a position (line and column) in a text file."""
+
+  def __init__(self, line=-1, column=-1):
+    self.line = line
+    self.column = column
+
+  def __eq__(self, rhs):
+    return self.line == rhs.line and self.column == rhs.column
+
+  def __ne__(self, rhs):
+    return not self == rhs
+
+  def __lt__(self, rhs):
+    return self.line < rhs.line or (
+        self.line == rhs.line and self.column < rhs.column)
+
+  def __le__(self, rhs):
+    return self < rhs or self == rhs
+
+  def __gt__(self, rhs):
+    return rhs < self
+
+  def __ge__(self, rhs):
+    return rhs <= self
+
+  def __str__(self):
+    if self == Eof():
+      return 'EOF'
+    else:
+      return '%s(%s)' % (self.line + 1, self.column)
+
+  def __add__(self, offset):
+    return Cursor(self.line, self.column + offset)
+
+  def __sub__(self, offset):
+    return Cursor(self.line, self.column - offset)
+
+  def Clone(self):
+    """Returns a copy of self."""
+
+    return Cursor(self.line, self.column)
+
+
+# Special cursor to indicate the end-of-file.
+def Eof():
+  """Returns the special cursor to denote the end-of-file."""
+  return Cursor(-1, -1)
+
+
+class Token:
+  """Represents a token in a Pump source file."""
+
+  def __init__(self, start=None, end=None, value=None, token_type=None):
+    if start is None:
+      self.start = Eof()
+    else:
+      self.start = start
+    if end is None:
+      self.end = Eof()
+    else:
+      self.end = end
+    self.value = value
+    self.token_type = token_type
+
+  def __str__(self):
+    return 'Token @%s: \'%s\' type=%s' % (
+        self.start, self.value, self.token_type)
+
+  def Clone(self):
+    """Returns a copy of self."""
+
+    return Token(self.start.Clone(), self.end.Clone(), self.value,
+                 self.token_type)
+
+
+def StartsWith(lines, pos, string):
+  """Returns True iff the given position in lines starts with 'string'."""
+
+  return lines[pos.line][pos.column:].startswith(string)
+
+
+def FindFirstInLine(line, token_table):
+  best_match_start = -1
+  for (regex, token_type) in token_table:
+    m = regex.search(line)
+    if m:
+      # We found regex in lines
+      if best_match_start < 0 or m.start() < best_match_start:
+        best_match_start = m.start()
+        best_match_length = m.end() - m.start()
+        best_match_token_type = token_type
+
+  if best_match_start < 0:
+    return None
+
+  return (best_match_start, best_match_length, best_match_token_type)
+
+
+def FindFirst(lines, token_table, cursor):
+  """Finds the first occurrence of any string in strings in lines."""
+
+  start = cursor.Clone()
+  cur_line_number = cursor.line
+  for line in lines[start.line:]:
+    if cur_line_number == start.line:
+      line = line[start.column:]
+    m = FindFirstInLine(line, token_table)
+    if m:
+      # We found a regex in line.
+      (start_column, length, token_type) = m
+      if cur_line_number == start.line:
+        start_column += start.column
+      found_start = Cursor(cur_line_number, start_column)
+      found_end = found_start + length
+      return MakeToken(lines, found_start, found_end, token_type)
+    cur_line_number += 1
+  # We failed to find str in lines
+  return None
+
+
+def SubString(lines, start, end):
+  """Returns a substring in lines."""
+
+  if end == Eof():
+    end = Cursor(len(lines) - 1, len(lines[-1]))
+
+  if start >= end:
+    return ''
+
+  if start.line == end.line:
+    return lines[start.line][start.column:end.column]
+
+  result_lines = ([lines[start.line][start.column:]] +
+                  lines[start.line + 1:end.line] +
+                  [lines[end.line][:end.column]])
+  return ''.join(result_lines)
+
+
+def StripMetaComments(str):
+  """Strip meta comments from each line in the given string."""
+
+  # First, completely remove lines containing nothing but a meta
+  # comment, including the trailing \n.
+  str = re.sub(r'^\s*\$\$.*\n', '', str)
+
+  # Then, remove meta comments from contentful lines.
+  return re.sub(r'\s*\$\$.*', '', str)
+
+
+def MakeToken(lines, start, end, token_type):
+  """Creates a new instance of Token."""
+
+  return Token(start, end, SubString(lines, start, end), token_type)
+
+
+def ParseToken(lines, pos, regex, token_type):
+  line = lines[pos.line][pos.column:]
+  m = regex.search(line)
+  if m and not m.start():
+    return MakeToken(lines, pos, pos + m.end(), token_type)
+  else:
+    print 'ERROR: %s expected at %s.' % (token_type, pos)
+    sys.exit(1)
+
+
+ID_REGEX = re.compile(r'[_A-Za-z]\w*')
+EQ_REGEX = re.compile(r'=')
+REST_OF_LINE_REGEX = re.compile(r'.*?(?=$|\$\$)')
+OPTIONAL_WHITE_SPACES_REGEX = re.compile(r'\s*')
+WHITE_SPACE_REGEX = re.compile(r'\s')
+DOT_DOT_REGEX = re.compile(r'\.\.')
+
+
+def Skip(lines, pos, regex):
+  line = lines[pos.line][pos.column:]
+  m = re.search(regex, line)
+  if m and not m.start():
+    return pos + m.end()
+  else:
+    return pos
+
+
+def SkipUntil(lines, pos, regex, token_type):
+  line = lines[pos.line][pos.column:]
+  m = re.search(regex, line)
+  if m:
+    return pos + m.start()
+  else:
+    print ('ERROR: %s expected on line %s after column %s.' %
+           (token_type, pos.line + 1, pos.column))
+    sys.exit(1)
+
+
+def ParseExpTokenInParens(lines, pos):
+  def ParseInParens(pos):
+    pos = Skip(lines, pos, OPTIONAL_WHITE_SPACES_REGEX)
+    pos = Skip(lines, pos, r'\(')
+    pos = Parse(pos)
+    pos = Skip(lines, pos, r'\)')
+    return pos
+
+  def Parse(pos):
+    pos = SkipUntil(lines, pos, r'\(|\)', ')')
+    if SubString(lines, pos, pos + 1) == '(':
+      pos = Parse(pos + 1)
+      pos = Skip(lines, pos, r'\)')
+      return Parse(pos)
+    else:
+      return pos
+
+  start = pos.Clone()
+  pos = ParseInParens(pos)
+  return MakeToken(lines, start, pos, 'exp')
+
+
+def RStripNewLineFromToken(token):
+  if token.value.endswith('\n'):
+    return Token(token.start, token.end, token.value[:-1], token.token_type)
+  else:
+    return token
+
+
+def TokenizeLines(lines, pos):
+  while True:
+    found = FindFirst(lines, TOKEN_TABLE, pos)
+    if not found:
+      yield MakeToken(lines, pos, Eof(), 'code')
+      return
+
+    if found.start == pos:
+      prev_token = None
+      prev_token_rstripped = None
+    else:
+      prev_token = MakeToken(lines, pos, found.start, 'code')
+      prev_token_rstripped = RStripNewLineFromToken(prev_token)
+
+    if found.token_type == '$var':
+      if prev_token_rstripped:
+        yield prev_token_rstripped
+      yield found
+      id_token = ParseToken(lines, found.end, ID_REGEX, 'id')
+      yield id_token
+      pos = Skip(lines, id_token.end, OPTIONAL_WHITE_SPACES_REGEX)
+
+      eq_token = ParseToken(lines, pos, EQ_REGEX, '=')
+      yield eq_token
+      pos = Skip(lines, eq_token.end, r'\s*')
+
+      if SubString(lines, pos, pos + 2) != '[[':
+        exp_token = ParseToken(lines, pos, REST_OF_LINE_REGEX, 'exp')
+        yield exp_token
+        pos = Cursor(exp_token.end.line + 1, 0)
+    elif found.token_type == '$for':
+      if prev_token_rstripped:
+        yield prev_token_rstripped
+      yield found
+      id_token = ParseToken(lines, found.end, ID_REGEX, 'id')
+      yield id_token
+      pos = Skip(lines, id_token.end, WHITE_SPACE_REGEX)
+    elif found.token_type == '$range':
+      if prev_token_rstripped:
+        yield prev_token_rstripped
+      yield found
+      id_token = ParseToken(lines, found.end, ID_REGEX, 'id')
+      yield id_token
+      pos = Skip(lines, id_token.end, OPTIONAL_WHITE_SPACES_REGEX)
+
+      dots_pos = SkipUntil(lines, pos, DOT_DOT_REGEX, '..')
+      yield MakeToken(lines, pos, dots_pos, 'exp')
+      yield MakeToken(lines, dots_pos, dots_pos + 2, '..')
+      pos = dots_pos + 2
+      new_pos = Cursor(pos.line + 1, 0)
+      yield MakeToken(lines, pos, new_pos, 'exp')
+      pos = new_pos
+    elif found.token_type == '$':
+      if prev_token:
+        yield prev_token
+      yield found
+      exp_token = ParseExpTokenInParens(lines, found.end)
+      yield exp_token
+      pos = exp_token.end
+    elif (found.token_type == ']]' or found.token_type == '$if' or
+          found.token_type == '$elif' or found.token_type == '$else'):
+      if prev_token_rstripped:
+        yield prev_token_rstripped
+      yield found
+      pos = found.end
+    else:
+      if prev_token:
+        yield prev_token
+      yield found
+      pos = found.end
+
+
+def Tokenize(s):
+  """A generator that yields the tokens in the given string."""
+  if s != '':
+    lines = s.splitlines(True)
+    for token in TokenizeLines(lines, Cursor(0, 0)):
+      yield token
+
+
+class CodeNode:
+  def __init__(self, atomic_code_list=None):
+    self.atomic_code = atomic_code_list
+
+
+class VarNode:
+  def __init__(self, identifier=None, atomic_code=None):
+    self.identifier = identifier
+    self.atomic_code = atomic_code
+
+
+class RangeNode:
+  def __init__(self, identifier=None, exp1=None, exp2=None):
+    self.identifier = identifier
+    self.exp1 = exp1
+    self.exp2 = exp2
+
+
+class ForNode:
+  def __init__(self, identifier=None, sep=None, code=None):
+    self.identifier = identifier
+    self.sep = sep
+    self.code = code
+
+
+class ElseNode:
+  def __init__(self, else_branch=None):
+    self.else_branch = else_branch
+
+
+class IfNode:
+  def __init__(self, exp=None, then_branch=None, else_branch=None):
+    self.exp = exp
+    self.then_branch = then_branch
+    self.else_branch = else_branch
+
+
+class RawCodeNode:
+  def __init__(self, token=None):
+    self.raw_code = token
+
+
+class LiteralDollarNode:
+  def __init__(self, token):
+    self.token = token
+
+
+class ExpNode:
+  def __init__(self, token, python_exp):
+    self.token = token
+    self.python_exp = python_exp
+
+
+def PopFront(a_list):
+  head = a_list[0]
+  a_list[:1] = []
+  return head
+
+
+def PushFront(a_list, elem):
+  a_list[:0] = [elem]
+
+
+def PopToken(a_list, token_type=None):
+  token = PopFront(a_list)
+  if token_type is not None and token.token_type != token_type:
+    print 'ERROR: %s expected at %s' % (token_type, token.start)
+    print 'ERROR: %s found instead' % (token,)
+    sys.exit(1)
+
+  return token
+
+
+def PeekToken(a_list):
+  if not a_list:
+    return None
+
+  return a_list[0]
+
+
+def ParseExpNode(token):
+  python_exp = re.sub(r'([_A-Za-z]\w*)', r'self.GetValue("\1")', token.value)
+  return ExpNode(token, python_exp)
+
+
+def ParseElseNode(tokens):
+  def Pop(token_type=None):
+    return PopToken(tokens, token_type)
+
+  next = PeekToken(tokens)
+  if not next:
+    return None
+  if next.token_type == '$else':
+    Pop('$else')
+    Pop('[[')
+    code_node = ParseCodeNode(tokens)
+    Pop(']]')
+    return code_node
+  elif next.token_type == '$elif':
+    Pop('$elif')
+    exp = Pop('code')
+    Pop('[[')
+    code_node = ParseCodeNode(tokens)
+    Pop(']]')
+    inner_else_node = ParseElseNode(tokens)
+    return CodeNode([IfNode(ParseExpNode(exp), code_node, inner_else_node)])
+  elif not next.value.strip():
+    Pop('code')
+    return ParseElseNode(tokens)
+  else:
+    return None
+
+
+def ParseAtomicCodeNode(tokens):
+  def Pop(token_type=None):
+    return PopToken(tokens, token_type)
+
+  head = PopFront(tokens)
+  t = head.token_type
+  if t == 'code':
+    return RawCodeNode(head)
+  elif t == '$var':
+    id_token = Pop('id')
+    Pop('=')
+    next = PeekToken(tokens)
+    if next.token_type == 'exp':
+      exp_token = Pop()
+      return VarNode(id_token, ParseExpNode(exp_token))
+    Pop('[[')
+    code_node = ParseCodeNode(tokens)
+    Pop(']]')
+    return VarNode(id_token, code_node)
+  elif t == '$for':
+    id_token = Pop('id')
+    next_token = PeekToken(tokens)
+    if next_token.token_type == 'code':
+      sep_token = next_token
+      Pop('code')
+    else:
+      sep_token = None
+    Pop('[[')
+    code_node = ParseCodeNode(tokens)
+    Pop(']]')
+    return ForNode(id_token, sep_token, code_node)
+  elif t == '$if':
+    exp_token = Pop('code')
+    Pop('[[')
+    code_node = ParseCodeNode(tokens)
+    Pop(']]')
+    else_node = ParseElseNode(tokens)
+    return IfNode(ParseExpNode(exp_token), code_node, else_node)
+  elif t == '$range':
+    id_token = Pop('id')
+    exp1_token = Pop('exp')
+    Pop('..')
+    exp2_token = Pop('exp')
+    return RangeNode(id_token, ParseExpNode(exp1_token),
+                     ParseExpNode(exp2_token))
+  elif t == '$id':
+    return ParseExpNode(Token(head.start + 1, head.end, head.value[1:], 'id'))
+  elif t == '$($)':
+    return LiteralDollarNode(head)
+  elif t == '$':
+    exp_token = Pop('exp')
+    return ParseExpNode(exp_token)
+  elif t == '[[':
+    code_node = ParseCodeNode(tokens)
+    Pop(']]')
+    return code_node
+  else:
+    PushFront(tokens, head)
+    return None
+
+
+def ParseCodeNode(tokens):
+  atomic_code_list = []
+  while True:
+    if not tokens:
+      break
+    atomic_code_node = ParseAtomicCodeNode(tokens)
+    if atomic_code_node:
+      atomic_code_list.append(atomic_code_node)
+    else:
+      break
+  return CodeNode(atomic_code_list)
+
+
+def ParseToAST(pump_src_text):
+  """Convert the given Pump source text into an AST."""
+  tokens = list(Tokenize(pump_src_text))
+  code_node = ParseCodeNode(tokens)
+  return code_node
+
+
+class Env:
+  def __init__(self):
+    self.variables = []
+    self.ranges = []
+
+  def Clone(self):
+    clone = Env()
+    clone.variables = self.variables[:]
+    clone.ranges = self.ranges[:]
+    return clone
+
+  def PushVariable(self, var, value):
+    # If value looks like an int, store it as an int.
+    try:
+      int_value = int(value)
+      if ('%s' % int_value) == value:
+        value = int_value
+    except Exception:
+      pass
+    self.variables[:0] = [(var, value)]
+
+  def PopVariable(self):
+    self.variables[:1] = []
+
+  def PushRange(self, var, lower, upper):
+    self.ranges[:0] = [(var, lower, upper)]
+
+  def PopRange(self):
+    self.ranges[:1] = []
+
+  def GetValue(self, identifier):
+    for (var, value) in self.variables:
+      if identifier == var:
+        return value
+
+    print 'ERROR: meta variable %s is undefined.' % (identifier,)
+    sys.exit(1)
+
+  def EvalExp(self, exp):
+    try:
+      result = eval(exp.python_exp)
+    except Exception, e:
+      print 'ERROR: caught exception %s: %s' % (e.__class__.__name__, e)
+      print ('ERROR: failed to evaluate meta expression %s at %s' %
+             (exp.python_exp, exp.token.start))
+      sys.exit(1)
+    return result
+
+  def GetRange(self, identifier):
+    for (var, lower, upper) in self.ranges:
+      if identifier == var:
+        return (lower, upper)
+
+    print 'ERROR: range %s is undefined.' % (identifier,)
+    sys.exit(1)
+
+
+class Output:
+  def __init__(self):
+    self.string = ''
+
+  def GetLastLine(self):
+    index = self.string.rfind('\n')
+    if index < 0:
+      return ''
+
+    return self.string[index + 1:]
+
+  def Append(self, s):
+    self.string += s
+
+
+def RunAtomicCode(env, node, output):
+  if isinstance(node, VarNode):
+    identifier = node.identifier.value.strip()
+    result = Output()
+    RunAtomicCode(env.Clone(), node.atomic_code, result)
+    value = result.string
+    env.PushVariable(identifier, value)
+  elif isinstance(node, RangeNode):
+    identifier = node.identifier.value.strip()
+    lower = int(env.EvalExp(node.exp1))
+    upper = int(env.EvalExp(node.exp2))
+    env.PushRange(identifier, lower, upper)
+  elif isinstance(node, ForNode):
+    identifier = node.identifier.value.strip()
+    if node.sep is None:
+      sep = ''
+    else:
+      sep = node.sep.value
+    (lower, upper) = env.GetRange(identifier)
+    for i in range(lower, upper + 1):
+      new_env = env.Clone()
+      new_env.PushVariable(identifier, i)
+      RunCode(new_env, node.code, output)
+      if i != upper:
+        output.Append(sep)
+  elif isinstance(node, RawCodeNode):
+    output.Append(node.raw_code.value)
+  elif isinstance(node, IfNode):
+    cond = env.EvalExp(node.exp)
+    if cond:
+      RunCode(env.Clone(), node.then_branch, output)
+    elif node.else_branch is not None:
+      RunCode(env.Clone(), node.else_branch, output)
+  elif isinstance(node, ExpNode):
+    value = env.EvalExp(node)
+    output.Append('%s' % (value,))
+  elif isinstance(node, LiteralDollarNode):
+    output.Append('$')
+  elif isinstance(node, CodeNode):
+    RunCode(env.Clone(), node, output)
+  else:
+    print 'BAD'
+    print node
+    sys.exit(1)
+
+
+def RunCode(env, code_node, output):
+  for atomic_code in code_node.atomic_code:
+    RunAtomicCode(env, atomic_code, output)
+
+
+def IsSingleLineComment(cur_line):
+  return '//' in cur_line
+
+
+def IsInPreprocessorDirective(prev_lines, cur_line):
+  if cur_line.lstrip().startswith('#'):
+    return True
+  return prev_lines and prev_lines[-1].endswith('\\')
+
+
+def WrapComment(line, output):
+  loc = line.find('//')
+  before_comment = line[:loc].rstrip()
+  if before_comment == '':
+    indent = loc
+  else:
+    output.append(before_comment)
+    indent = len(before_comment) - len(before_comment.lstrip())
+  prefix = indent*' ' + '// '
+  max_len = 80 - len(prefix)
+  comment = line[loc + 2:].strip()
+  segs = [seg for seg in re.split(r'(\w+\W*)', comment) if seg != '']
+  cur_line = ''
+  for seg in segs:
+    if len((cur_line + seg).rstrip()) < max_len:
+      cur_line += seg
+    else:
+      if cur_line.strip() != '':
+        output.append(prefix + cur_line.rstrip())
+      cur_line = seg.lstrip()
+  if cur_line.strip() != '':
+    output.append(prefix + cur_line.strip())
+
+
+def WrapCode(line, line_concat, output):
+  indent = len(line) - len(line.lstrip())
+  prefix = indent*' '  # Prefix of the current line
+  max_len = 80 - indent - len(line_concat)  # Maximum length of the current line
+  new_prefix = prefix + 4*' '  # Prefix of a continuation line
+  new_max_len = max_len - 4  # Maximum length of a continuation line
+  # Prefers to wrap a line after a ',' or ';'.
+  segs = [seg for seg in re.split(r'([^,;]+[,;]?)', line.strip()) if seg != '']
+  cur_line = ''  # The current line without leading spaces.
+  for seg in segs:
+    # If the line is still too long, wrap at a space.
+    while cur_line == '' and len(seg.strip()) > max_len:
+      seg = seg.lstrip()
+      split_at = seg.rfind(' ', 0, max_len)
+      output.append(prefix + seg[:split_at].strip() + line_concat)
+      seg = seg[split_at + 1:]
+      prefix = new_prefix
+      max_len = new_max_len
+
+    if len((cur_line + seg).rstrip()) < max_len:
+      cur_line = (cur_line + seg).lstrip()
+    else:
+      output.append(prefix + cur_line.rstrip() + line_concat)
+      prefix = new_prefix
+      max_len = new_max_len
+      cur_line = seg.lstrip()
+  if cur_line.strip() != '':
+    output.append(prefix + cur_line.strip())
+
+
+def WrapPreprocessorDirective(line, output):
+  WrapCode(line, ' \\', output)
+
+
+def WrapPlainCode(line, output):
+  WrapCode(line, '', output)
+
+
+def IsMultiLineIWYUPragma(line):
+  return re.search(r'/\* IWYU pragma: ', line)
+
+
+def IsHeaderGuardIncludeOrOneLineIWYUPragma(line):
+  return (re.match(r'^#(ifndef|define|endif\s*//)\s*[\w_]+\s*$', line) or
+          re.match(r'^#include\s', line) or
+          # Don't break IWYU pragmas, either; that causes iwyu.py problems.
+          re.search(r'// IWYU pragma: ', line))
+
+
+def WrapLongLine(line, output):
+  line = line.rstrip()
+  if len(line) <= 80:
+    output.append(line)
+  elif IsSingleLineComment(line):
+    if IsHeaderGuardIncludeOrOneLineIWYUPragma(line):
+      # The style guide made an exception to allow long header guard lines,
+      # includes and IWYU pragmas.
+      output.append(line)
+    else:
+      WrapComment(line, output)
+  elif IsInPreprocessorDirective(output, line):
+    if IsHeaderGuardIncludeOrOneLineIWYUPragma(line):
+      # The style guide made an exception to allow long header guard lines,
+      # includes and IWYU pragmas.
+      output.append(line)
+    else:
+      WrapPreprocessorDirective(line, output)
+  elif IsMultiLineIWYUPragma(line):
+    output.append(line)
+  else:
+    WrapPlainCode(line, output)
+
+
+def BeautifyCode(string):
+  lines = string.splitlines()
+  output = []
+  for line in lines:
+    WrapLongLine(line, output)
+  output2 = [line.rstrip() for line in output]
+  return '\n'.join(output2) + '\n'
+
+
+def ConvertFromPumpSource(src_text):
+  """Return the text generated from the given Pump source text."""
+  ast = ParseToAST(StripMetaComments(src_text))
+  output = Output()
+  RunCode(Env(), ast, output)
+  return BeautifyCode(output.string)
+
+
+def main(argv):
+  if len(argv) == 1:
+    print __doc__
+    sys.exit(1)
+
+  file_path = argv[-1]
+  output_str = ConvertFromPumpSource(file(file_path, 'r').read())
+  if file_path.endswith('.pump'):
+    output_file_path = file_path[:-5]
+  else:
+    output_file_path = '-'
+  if output_file_path == '-':
+    print output_str,
+  else:
+    output_file = file(output_file_path, 'w')
+    output_file.write('// This file was GENERATED by command:\n')
+    output_file.write('//     %s %s\n' %
+                      (os.path.basename(__file__), os.path.basename(file_path)))
+    output_file.write('// DO NOT EDIT BY HAND!!!\n\n')
+    output_file.write(output_str)
+    output_file.close()
+
+
+if __name__ == '__main__':
+  main(sys.argv)
diff --git a/third_party/googletest/googletest/scripts/release_docs.py b/third_party/googletest/googletest/scripts/release_docs.py
new file mode 100755
index 0000000..1291347
--- /dev/null
+++ b/third_party/googletest/googletest/scripts/release_docs.py
@@ -0,0 +1,158 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 Google Inc. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Script for branching Google Test/Mock wiki pages for a new version.
+
+SYNOPSIS
+       release_docs.py NEW_RELEASE_VERSION
+
+       Google Test and Google Mock's external user documentation is in
+       interlinked wiki files.  When we release a new version of
+       Google Test or Google Mock, we need to branch the wiki files
+       such that users of a specific version of Google Test/Mock can
+       look up documenation relevant for that version.  This script
+       automates that process by:
+
+         - branching the current wiki pages (which document the
+           behavior of the SVN trunk head) to pages for the specified
+           version (e.g. branching FAQ.wiki to V2_6_FAQ.wiki when
+           NEW_RELEASE_VERSION is 2.6);
+         - updating the links in the branched files to point to the branched
+           version (e.g. a link in V2_6_FAQ.wiki that pointed to
+           Primer.wiki#Anchor will now point to V2_6_Primer.wiki#Anchor).
+
+       NOTE: NEW_RELEASE_VERSION must be a NEW version number for
+       which the wiki pages don't yet exist; otherwise you'll get SVN
+       errors like "svn: Path 'V1_7_PumpManual.wiki' is not a
+       directory" when running the script.
+
+EXAMPLE
+       $ cd PATH/TO/GTEST_SVN_WORKSPACE/trunk
+       $ scripts/release_docs.py 2.6  # create wiki pages for v2.6
+       $ svn status                   # verify the file list
+       $ svn diff                     # verify the file contents
+       $ svn commit -m "release wiki pages for v2.6"
+"""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import os
+import re
+import sys
+
+import common
+
+
+# Wiki pages that shouldn't be branched for every gtest/gmock release.
+GTEST_UNVERSIONED_WIKIS = ['DevGuide.wiki']
+GMOCK_UNVERSIONED_WIKIS = [
+    'DesignDoc.wiki',
+    'DevGuide.wiki',
+    'KnownIssues.wiki'
+    ]
+
+
+def DropWikiSuffix(wiki_filename):
+  """Removes the .wiki suffix (if any) from the given filename."""
+
+  return (wiki_filename[:-len('.wiki')] if wiki_filename.endswith('.wiki')
+          else wiki_filename)
+
+
+class WikiBrancher(object):
+  """Branches ..."""
+
+  def __init__(self, dot_version):
+    self.project, svn_root_path = common.GetSvnInfo()
+    if self.project not in ('googletest', 'googlemock'):
+      sys.exit('This script must be run in a gtest or gmock SVN workspace.')
+    self.wiki_dir = svn_root_path + '/wiki'
+    # Turn '2.6' to 'V2_6_'.
+    self.version_prefix = 'V' + dot_version.replace('.', '_') + '_'
+    self.files_to_branch = self.GetFilesToBranch()
+    page_names = [DropWikiSuffix(f) for f in self.files_to_branch]
+    # A link to Foo.wiki is in one of the following forms:
+    #   [Foo words]
+    #   [Foo#Anchor words]
+    #   [http://code.google.com/.../wiki/Foo words]
+    #   [http://code.google.com/.../wiki/Foo#Anchor words]
+    # We want to replace 'Foo' with 'V2_6_Foo' in the above cases.
+    self.search_for_re = re.compile(
+        # This regex matches either
+        #   [Foo
+        # or
+        #   /wiki/Foo
+        # followed by a space or a #, where Foo is the name of an
+        # unversioned wiki page.
+        r'(\[|/wiki/)(%s)([ #])' % '|'.join(page_names))
+    self.replace_with = r'\1%s\2\3' % (self.version_prefix,)
+
+  def GetFilesToBranch(self):
+    """Returns a list of .wiki file names that need to be branched."""
+
+    unversioned_wikis = (GTEST_UNVERSIONED_WIKIS if self.project == 'googletest'
+                         else GMOCK_UNVERSIONED_WIKIS)
+    return [f for f in os.listdir(self.wiki_dir)
+            if (f.endswith('.wiki') and
+                not re.match(r'^V\d', f) and  # Excluded versioned .wiki files.
+                f not in unversioned_wikis)]
+
+  def BranchFiles(self):
+    """Branches the .wiki files needed to be branched."""
+
+    print 'Branching %d .wiki files:' % (len(self.files_to_branch),)
+    os.chdir(self.wiki_dir)
+    for f in self.files_to_branch:
+      command = 'svn cp %s %s%s' % (f, self.version_prefix, f)
+      print command
+      os.system(command)
+
+  def UpdateLinksInBranchedFiles(self):
+
+    for f in self.files_to_branch:
+      source_file = os.path.join(self.wiki_dir, f)
+      versioned_file = os.path.join(self.wiki_dir, self.version_prefix + f)
+      print 'Updating links in %s.' % (versioned_file,)
+      text = file(source_file, 'r').read()
+      new_text = self.search_for_re.sub(self.replace_with, text)
+      file(versioned_file, 'w').write(new_text)
+
+
+def main():
+  if len(sys.argv) != 2:
+    sys.exit(__doc__)
+
+  brancher = WikiBrancher(sys.argv[1])
+  brancher.BranchFiles()
+  brancher.UpdateLinksInBranchedFiles()
+
+
+if __name__ == '__main__':
+  main()
diff --git a/third_party/googletest/googletest/scripts/test/Makefile b/third_party/googletest/googletest/scripts/test/Makefile
new file mode 100644
index 0000000..cdff584
--- /dev/null
+++ b/third_party/googletest/googletest/scripts/test/Makefile
@@ -0,0 +1,59 @@
+# A Makefile for fusing Google Test and building a sample test against it.
+#
+# SYNOPSIS:
+#
+#   make [all]  - makes everything.
+#   make TARGET - makes the given target.
+#   make check  - makes everything and runs the built sample test.
+#   make clean  - removes all files generated by make.
+
+# Points to the root of fused Google Test, relative to where this file is.
+FUSED_GTEST_DIR = output
+
+# Paths to the fused gtest files.
+FUSED_GTEST_H = $(FUSED_GTEST_DIR)/gtest/gtest.h
+FUSED_GTEST_ALL_CC = $(FUSED_GTEST_DIR)/gtest/gtest-all.cc
+
+# Where to find the sample test.
+SAMPLE_DIR = ../../samples
+
+# Where to find gtest_main.cc.
+GTEST_MAIN_CC = ../../src/gtest_main.cc
+
+# Flags passed to the preprocessor.
+# We have no idea here whether pthreads is available in the system, so
+# disable its use.
+CPPFLAGS += -I$(FUSED_GTEST_DIR) -DGTEST_HAS_PTHREAD=0
+
+# Flags passed to the C++ compiler.
+CXXFLAGS += -g
+
+all : sample1_unittest
+
+check : all
+	./sample1_unittest
+
+clean :
+	rm -rf $(FUSED_GTEST_DIR) sample1_unittest *.o
+
+$(FUSED_GTEST_H) :
+	../fuse_gtest_files.py $(FUSED_GTEST_DIR)
+
+$(FUSED_GTEST_ALL_CC) :
+	../fuse_gtest_files.py $(FUSED_GTEST_DIR)
+
+gtest-all.o : $(FUSED_GTEST_H) $(FUSED_GTEST_ALL_CC)
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(FUSED_GTEST_DIR)/gtest/gtest-all.cc
+
+gtest_main.o : $(FUSED_GTEST_H) $(GTEST_MAIN_CC)
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(GTEST_MAIN_CC)
+
+sample1.o : $(SAMPLE_DIR)/sample1.cc $(SAMPLE_DIR)/sample1.h
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(SAMPLE_DIR)/sample1.cc
+
+sample1_unittest.o : $(SAMPLE_DIR)/sample1_unittest.cc \
+                     $(SAMPLE_DIR)/sample1.h $(FUSED_GTEST_H)
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(SAMPLE_DIR)/sample1_unittest.cc
+
+sample1_unittest : sample1.o sample1_unittest.o gtest-all.o gtest_main.o
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) $^ -o $@
diff --git a/third_party/googletest/googletest/scripts/upload.py b/third_party/googletest/googletest/scripts/upload.py
new file mode 100755
index 0000000..6e6f9a1
--- /dev/null
+++ b/third_party/googletest/googletest/scripts/upload.py
@@ -0,0 +1,1387 @@
+#!/usr/bin/env python
+#
+# Copyright 2007 Google Inc.
+#
+# 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.
+
+"""Tool for uploading diffs from a version control system to the codereview app.
+
+Usage summary: upload.py [options] [-- diff_options]
+
+Diff options are passed to the diff command of the underlying system.
+
+Supported version control systems:
+  Git
+  Mercurial
+  Subversion
+
+It is important for Git/Mercurial users to specify a tree/node/branch to diff
+against by using the '--rev' option.
+"""
+# This code is derived from appcfg.py in the App Engine SDK (open source),
+# and from ASPN recipe #146306.
+
+import cookielib
+import getpass
+import logging
+import md5
+import mimetypes
+import optparse
+import os
+import re
+import socket
+import subprocess
+import sys
+import urllib
+import urllib2
+import urlparse
+
+try:
+  import readline
+except ImportError:
+  pass
+
+# The logging verbosity:
+#  0: Errors only.
+#  1: Status messages.
+#  2: Info logs.
+#  3: Debug logs.
+verbosity = 1
+
+# Max size of patch or base file.
+MAX_UPLOAD_SIZE = 900 * 1024
+
+
+def GetEmail(prompt):
+  """Prompts the user for their email address and returns it.
+
+  The last used email address is saved to a file and offered up as a suggestion
+  to the user. If the user presses enter without typing in anything the last
+  used email address is used. If the user enters a new address, it is saved
+  for next time we prompt.
+
+  """
+  last_email_file_name = os.path.expanduser("~/.last_codereview_email_address")
+  last_email = ""
+  if os.path.exists(last_email_file_name):
+    try:
+      last_email_file = open(last_email_file_name, "r")
+      last_email = last_email_file.readline().strip("\n")
+      last_email_file.close()
+      prompt += " [%s]" % last_email
+    except IOError, e:
+      pass
+  email = raw_input(prompt + ": ").strip()
+  if email:
+    try:
+      last_email_file = open(last_email_file_name, "w")
+      last_email_file.write(email)
+      last_email_file.close()
+    except IOError, e:
+      pass
+  else:
+    email = last_email
+  return email
+
+
+def StatusUpdate(msg):
+  """Print a status message to stdout.
+
+  If 'verbosity' is greater than 0, print the message.
+
+  Args:
+    msg: The string to print.
+  """
+  if verbosity > 0:
+    print msg
+
+
+def ErrorExit(msg):
+  """Print an error message to stderr and exit."""
+  print >>sys.stderr, msg
+  sys.exit(1)
+
+
+class ClientLoginError(urllib2.HTTPError):
+  """Raised to indicate there was an error authenticating with ClientLogin."""
+
+  def __init__(self, url, code, msg, headers, args):
+    urllib2.HTTPError.__init__(self, url, code, msg, headers, None)
+    self.args = args
+    self.reason = args["Error"]
+
+
+class AbstractRpcServer(object):
+  """Provides a common interface for a simple RPC server."""
+
+  def __init__(self, host, auth_function, host_override=None, extra_headers={},
+               save_cookies=False):
+    """Creates a new HttpRpcServer.
+
+    Args:
+      host: The host to send requests to.
+      auth_function: A function that takes no arguments and returns an
+        (email, password) tuple when called. Will be called if authentication
+        is required.
+      host_override: The host header to send to the server (defaults to host).
+      extra_headers: A dict of extra headers to append to every request.
+      save_cookies: If True, save the authentication cookies to local disk.
+        If False, use an in-memory cookiejar instead.  Subclasses must
+        implement this functionality.  Defaults to False.
+    """
+    self.host = host
+    self.host_override = host_override
+    self.auth_function = auth_function
+    self.authenticated = False
+    self.extra_headers = extra_headers
+    self.save_cookies = save_cookies
+    self.opener = self._GetOpener()
+    if self.host_override:
+      logging.info("Server: %s; Host: %s", self.host, self.host_override)
+    else:
+      logging.info("Server: %s", self.host)
+
+  def _GetOpener(self):
+    """Returns an OpenerDirector for making HTTP requests.
+
+    Returns:
+      A urllib2.OpenerDirector object.
+    """
+    raise NotImplementedError()
+
+  def _CreateRequest(self, url, data=None):
+    """Creates a new urllib request."""
+    logging.debug("Creating request for: '%s' with payload:\n%s", url, data)
+    req = urllib2.Request(url, data=data)
+    if self.host_override:
+      req.add_header("Host", self.host_override)
+    for key, value in self.extra_headers.iteritems():
+      req.add_header(key, value)
+    return req
+
+  def _GetAuthToken(self, email, password):
+    """Uses ClientLogin to authenticate the user, returning an auth token.
+
+    Args:
+      email:    The user's email address
+      password: The user's password
+
+    Raises:
+      ClientLoginError: If there was an error authenticating with ClientLogin.
+      HTTPError: If there was some other form of HTTP error.
+
+    Returns:
+      The authentication token returned by ClientLogin.
+    """
+    account_type = "GOOGLE"
+    if self.host.endswith(".google.com"):
+      # Needed for use inside Google.
+      account_type = "HOSTED"
+    req = self._CreateRequest(
+        url="https://www.google.com/accounts/ClientLogin",
+        data=urllib.urlencode({
+            "Email": email,
+            "Passwd": password,
+            "service": "ah",
+            "source": "rietveld-codereview-upload",
+            "accountType": account_type,
+        }),
+    )
+    try:
+      response = self.opener.open(req)
+      response_body = response.read()
+      response_dict = dict(x.split("=")
+                           for x in response_body.split("\n") if x)
+      return response_dict["Auth"]
+    except urllib2.HTTPError, e:
+      if e.code == 403:
+        body = e.read()
+        response_dict = dict(x.split("=", 1) for x in body.split("\n") if x)
+        raise ClientLoginError(req.get_full_url(), e.code, e.msg,
+                               e.headers, response_dict)
+      else:
+        raise
+
+  def _GetAuthCookie(self, auth_token):
+    """Fetches authentication cookies for an authentication token.
+
+    Args:
+      auth_token: The authentication token returned by ClientLogin.
+
+    Raises:
+      HTTPError: If there was an error fetching the authentication cookies.
+    """
+    # This is a dummy value to allow us to identify when we're successful.
+    continue_location = "http://localhost/"
+    args = {"continue": continue_location, "auth": auth_token}
+    req = self._CreateRequest("http://%s/_ah/login?%s" %
+                              (self.host, urllib.urlencode(args)))
+    try:
+      response = self.opener.open(req)
+    except urllib2.HTTPError, e:
+      response = e
+    if (response.code != 302 or
+        response.info()["location"] != continue_location):
+      raise urllib2.HTTPError(req.get_full_url(), response.code, response.msg,
+                              response.headers, response.fp)
+    self.authenticated = True
+
+  def _Authenticate(self):
+    """Authenticates the user.
+
+    The authentication process works as follows:
+     1) We get a username and password from the user
+     2) We use ClientLogin to obtain an AUTH token for the user
+        (see http://code.google.com/apis/accounts/AuthForInstalledApps.html).
+     3) We pass the auth token to /_ah/login on the server to obtain an
+        authentication cookie. If login was successful, it tries to redirect
+        us to the URL we provided.
+
+    If we attempt to access the upload API without first obtaining an
+    authentication cookie, it returns a 401 response and directs us to
+    authenticate ourselves with ClientLogin.
+    """
+    for i in range(3):
+      credentials = self.auth_function()
+      try:
+        auth_token = self._GetAuthToken(credentials[0], credentials[1])
+      except ClientLoginError, e:
+        if e.reason == "BadAuthentication":
+          print >>sys.stderr, "Invalid username or password."
+          continue
+        if e.reason == "CaptchaRequired":
+          print >>sys.stderr, (
+              "Please go to\n"
+              "https://www.google.com/accounts/DisplayUnlockCaptcha\n"
+              "and verify you are a human.  Then try again.")
+          break
+        if e.reason == "NotVerified":
+          print >>sys.stderr, "Account not verified."
+          break
+        if e.reason == "TermsNotAgreed":
+          print >>sys.stderr, "User has not agreed to TOS."
+          break
+        if e.reason == "AccountDeleted":
+          print >>sys.stderr, "The user account has been deleted."
+          break
+        if e.reason == "AccountDisabled":
+          print >>sys.stderr, "The user account has been disabled."
+          break
+        if e.reason == "ServiceDisabled":
+          print >>sys.stderr, ("The user's access to the service has been "
+                               "disabled.")
+          break
+        if e.reason == "ServiceUnavailable":
+          print >>sys.stderr, "The service is not available; try again later."
+          break
+        raise
+      self._GetAuthCookie(auth_token)
+      return
+
+  def Send(self, request_path, payload=None,
+           content_type="application/octet-stream",
+           timeout=None,
+           **kwargs):
+    """Sends an RPC and returns the response.
+
+    Args:
+      request_path: The path to send the request to, eg /api/appversion/create.
+      payload: The body of the request, or None to send an empty request.
+      content_type: The Content-Type header to use.
+      timeout: timeout in seconds; default None i.e. no timeout.
+        (Note: for large requests on OS X, the timeout doesn't work right.)
+      kwargs: Any keyword arguments are converted into query string parameters.
+
+    Returns:
+      The response body, as a string.
+    """
+    # TODO: Don't require authentication.  Let the server say
+    # whether it is necessary.
+    if not self.authenticated:
+      self._Authenticate()
+
+    old_timeout = socket.getdefaulttimeout()
+    socket.setdefaulttimeout(timeout)
+    try:
+      tries = 0
+      while True:
+        tries += 1
+        args = dict(kwargs)
+        url = "http://%s%s" % (self.host, request_path)
+        if args:
+          url += "?" + urllib.urlencode(args)
+        req = self._CreateRequest(url=url, data=payload)
+        req.add_header("Content-Type", content_type)
+        try:
+          f = self.opener.open(req)
+          response = f.read()
+          f.close()
+          return response
+        except urllib2.HTTPError, e:
+          if tries > 3:
+            raise
+          elif e.code == 401:
+            self._Authenticate()
+##           elif e.code >= 500 and e.code < 600:
+##             # Server Error - try again.
+##             continue
+          else:
+            raise
+    finally:
+      socket.setdefaulttimeout(old_timeout)
+
+
+class HttpRpcServer(AbstractRpcServer):
+  """Provides a simplified RPC-style interface for HTTP requests."""
+
+  def _Authenticate(self):
+    """Save the cookie jar after authentication."""
+    super(HttpRpcServer, self)._Authenticate()
+    if self.save_cookies:
+      StatusUpdate("Saving authentication cookies to %s" % self.cookie_file)
+      self.cookie_jar.save()
+
+  def _GetOpener(self):
+    """Returns an OpenerDirector that supports cookies and ignores redirects.
+
+    Returns:
+      A urllib2.OpenerDirector object.
+    """
+    opener = urllib2.OpenerDirector()
+    opener.add_handler(urllib2.ProxyHandler())
+    opener.add_handler(urllib2.UnknownHandler())
+    opener.add_handler(urllib2.HTTPHandler())
+    opener.add_handler(urllib2.HTTPDefaultErrorHandler())
+    opener.add_handler(urllib2.HTTPSHandler())
+    opener.add_handler(urllib2.HTTPErrorProcessor())
+    if self.save_cookies:
+      self.cookie_file = os.path.expanduser("~/.codereview_upload_cookies")
+      self.cookie_jar = cookielib.MozillaCookieJar(self.cookie_file)
+      if os.path.exists(self.cookie_file):
+        try:
+          self.cookie_jar.load()
+          self.authenticated = True
+          StatusUpdate("Loaded authentication cookies from %s" %
+                       self.cookie_file)
+        except (cookielib.LoadError, IOError):
+          # Failed to load cookies - just ignore them.
+          pass
+      else:
+        # Create an empty cookie file with mode 600
+        fd = os.open(self.cookie_file, os.O_CREAT, 0600)
+        os.close(fd)
+      # Always chmod the cookie file
+      os.chmod(self.cookie_file, 0600)
+    else:
+      # Don't save cookies across runs of update.py.
+      self.cookie_jar = cookielib.CookieJar()
+    opener.add_handler(urllib2.HTTPCookieProcessor(self.cookie_jar))
+    return opener
+
+
+parser = optparse.OptionParser(usage="%prog [options] [-- diff_options]")
+parser.add_option("-y", "--assume_yes", action="store_true",
+                  dest="assume_yes", default=False,
+                  help="Assume that the answer to yes/no questions is 'yes'.")
+# Logging
+group = parser.add_option_group("Logging options")
+group.add_option("-q", "--quiet", action="store_const", const=0,
+                 dest="verbose", help="Print errors only.")
+group.add_option("-v", "--verbose", action="store_const", const=2,
+                 dest="verbose", default=1,
+                 help="Print info level logs (default).")
+group.add_option("--noisy", action="store_const", const=3,
+                 dest="verbose", help="Print all logs.")
+# Review server
+group = parser.add_option_group("Review server options")
+group.add_option("-s", "--server", action="store", dest="server",
+                 default="codereview.appspot.com",
+                 metavar="SERVER",
+                 help=("The server to upload to. The format is host[:port]. "
+                       "Defaults to 'codereview.appspot.com'."))
+group.add_option("-e", "--email", action="store", dest="email",
+                 metavar="EMAIL", default=None,
+                 help="The username to use. Will prompt if omitted.")
+group.add_option("-H", "--host", action="store", dest="host",
+                 metavar="HOST", default=None,
+                 help="Overrides the Host header sent with all RPCs.")
+group.add_option("--no_cookies", action="store_false",
+                 dest="save_cookies", default=True,
+                 help="Do not save authentication cookies to local disk.")
+# Issue
+group = parser.add_option_group("Issue options")
+group.add_option("-d", "--description", action="store", dest="description",
+                 metavar="DESCRIPTION", default=None,
+                 help="Optional description when creating an issue.")
+group.add_option("-f", "--description_file", action="store",
+                 dest="description_file", metavar="DESCRIPTION_FILE",
+                 default=None,
+                 help="Optional path of a file that contains "
+                      "the description when creating an issue.")
+group.add_option("-r", "--reviewers", action="store", dest="reviewers",
+                 metavar="REVIEWERS", default=None,
+                 help="Add reviewers (comma separated email addresses).")
+group.add_option("--cc", action="store", dest="cc",
+                 metavar="CC", default=None,
+                 help="Add CC (comma separated email addresses).")
+# Upload options
+group = parser.add_option_group("Patch options")
+group.add_option("-m", "--message", action="store", dest="message",
+                 metavar="MESSAGE", default=None,
+                 help="A message to identify the patch. "
+                      "Will prompt if omitted.")
+group.add_option("-i", "--issue", type="int", action="store",
+                 metavar="ISSUE", default=None,
+                 help="Issue number to which to add. Defaults to new issue.")
+group.add_option("--download_base", action="store_true",
+                 dest="download_base", default=False,
+                 help="Base files will be downloaded by the server "
+                 "(side-by-side diffs may not work on files with CRs).")
+group.add_option("--rev", action="store", dest="revision",
+                 metavar="REV", default=None,
+                 help="Branch/tree/revision to diff against (used by DVCS).")
+group.add_option("--send_mail", action="store_true",
+                 dest="send_mail", default=False,
+                 help="Send notification email to reviewers.")
+
+
+def GetRpcServer(options):
+  """Returns an instance of an AbstractRpcServer.
+
+  Returns:
+    A new AbstractRpcServer, on which RPC calls can be made.
+  """
+
+  rpc_server_class = HttpRpcServer
+
+  def GetUserCredentials():
+    """Prompts the user for a username and password."""
+    email = options.email
+    if email is None:
+      email = GetEmail("Email (login for uploading to %s)" % options.server)
+    password = getpass.getpass("Password for %s: " % email)
+    return (email, password)
+
+  # If this is the dev_appserver, use fake authentication.
+  host = (options.host or options.server).lower()
+  if host == "localhost" or host.startswith("localhost:"):
+    email = options.email
+    if email is None:
+      email = "test@example.com"
+      logging.info("Using debug user %s.  Override with --email" % email)
+    server = rpc_server_class(
+        options.server,
+        lambda: (email, "password"),
+        host_override=options.host,
+        extra_headers={"Cookie":
+                       'dev_appserver_login="%s:False"' % email},
+        save_cookies=options.save_cookies)
+    # Don't try to talk to ClientLogin.
+    server.authenticated = True
+    return server
+
+  return rpc_server_class(options.server, GetUserCredentials,
+                          host_override=options.host,
+                          save_cookies=options.save_cookies)
+
+
+def EncodeMultipartFormData(fields, files):
+  """Encode form fields for multipart/form-data.
+
+  Args:
+    fields: A sequence of (name, value) elements for regular form fields.
+    files: A sequence of (name, filename, value) elements for data to be
+           uploaded as files.
+  Returns:
+    (content_type, body) ready for httplib.HTTP instance.
+
+  Source:
+    http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/146306
+  """
+  BOUNDARY = '-M-A-G-I-C---B-O-U-N-D-A-R-Y-'
+  CRLF = '\r\n'
+  lines = []
+  for (key, value) in fields:
+    lines.append('--' + BOUNDARY)
+    lines.append('Content-Disposition: form-data; name="%s"' % key)
+    lines.append('')
+    lines.append(value)
+  for (key, filename, value) in files:
+    lines.append('--' + BOUNDARY)
+    lines.append('Content-Disposition: form-data; name="%s"; filename="%s"' %
+             (key, filename))
+    lines.append('Content-Type: %s' % GetContentType(filename))
+    lines.append('')
+    lines.append(value)
+  lines.append('--' + BOUNDARY + '--')
+  lines.append('')
+  body = CRLF.join(lines)
+  content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
+  return content_type, body
+
+
+def GetContentType(filename):
+  """Helper to guess the content-type from the filename."""
+  return mimetypes.guess_type(filename)[0] or 'application/octet-stream'
+
+
+# Use a shell for subcommands on Windows to get a PATH search.
+use_shell = sys.platform.startswith("win")
+
+def RunShellWithReturnCode(command, print_output=False,
+                           universal_newlines=True):
+  """Executes a command and returns the output from stdout and the return code.
+
+  Args:
+    command: Command to execute.
+    print_output: If True, the output is printed to stdout.
+                  If False, both stdout and stderr are ignored.
+    universal_newlines: Use universal_newlines flag (default: True).
+
+  Returns:
+    Tuple (output, return code)
+  """
+  logging.info("Running %s", command)
+  p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+                       shell=use_shell, universal_newlines=universal_newlines)
+  if print_output:
+    output_array = []
+    while True:
+      line = p.stdout.readline()
+      if not line:
+        break
+      print line.strip("\n")
+      output_array.append(line)
+    output = "".join(output_array)
+  else:
+    output = p.stdout.read()
+  p.wait()
+  errout = p.stderr.read()
+  if print_output and errout:
+    print >>sys.stderr, errout
+  p.stdout.close()
+  p.stderr.close()
+  return output, p.returncode
+
+
+def RunShell(command, silent_ok=False, universal_newlines=True,
+             print_output=False):
+  data, retcode = RunShellWithReturnCode(command, print_output,
+                                         universal_newlines)
+  if retcode:
+    ErrorExit("Got error status from %s:\n%s" % (command, data))
+  if not silent_ok and not data:
+    ErrorExit("No output from %s" % command)
+  return data
+
+
+class VersionControlSystem(object):
+  """Abstract base class providing an interface to the VCS."""
+
+  def __init__(self, options):
+    """Constructor.
+
+    Args:
+      options: Command line options.
+    """
+    self.options = options
+
+  def GenerateDiff(self, args):
+    """Return the current diff as a string.
+
+    Args:
+      args: Extra arguments to pass to the diff command.
+    """
+    raise NotImplementedError(
+        "abstract method -- subclass %s must override" % self.__class__)
+
+  def GetUnknownFiles(self):
+    """Return a list of files unknown to the VCS."""
+    raise NotImplementedError(
+        "abstract method -- subclass %s must override" % self.__class__)
+
+  def CheckForUnknownFiles(self):
+    """Show an "are you sure?" prompt if there are unknown files."""
+    unknown_files = self.GetUnknownFiles()
+    if unknown_files:
+      print "The following files are not added to version control:"
+      for line in unknown_files:
+        print line
+      prompt = "Are you sure to continue?(y/N) "
+      answer = raw_input(prompt).strip()
+      if answer != "y":
+        ErrorExit("User aborted")
+
+  def GetBaseFile(self, filename):
+    """Get the content of the upstream version of a file.
+
+    Returns:
+      A tuple (base_content, new_content, is_binary, status)
+        base_content: The contents of the base file.
+        new_content: For text files, this is empty.  For binary files, this is
+          the contents of the new file, since the diff output won't contain
+          information to reconstruct the current file.
+        is_binary: True iff the file is binary.
+        status: The status of the file.
+    """
+
+    raise NotImplementedError(
+        "abstract method -- subclass %s must override" % self.__class__)
+
+
+  def GetBaseFiles(self, diff):
+    """Helper that calls GetBase file for each file in the patch.
+
+    Returns:
+      A dictionary that maps from filename to GetBaseFile's tuple.  Filenames
+      are retrieved based on lines that start with "Index:" or
+      "Property changes on:".
+    """
+    files = {}
+    for line in diff.splitlines(True):
+      if line.startswith('Index:') or line.startswith('Property changes on:'):
+        unused, filename = line.split(':', 1)
+        # On Windows if a file has property changes its filename uses '\'
+        # instead of '/'.
+        filename = filename.strip().replace('\\', '/')
+        files[filename] = self.GetBaseFile(filename)
+    return files
+
+
+  def UploadBaseFiles(self, issue, rpc_server, patch_list, patchset, options,
+                      files):
+    """Uploads the base files (and if necessary, the current ones as well)."""
+
+    def UploadFile(filename, file_id, content, is_binary, status, is_base):
+      """Uploads a file to the server."""
+      file_too_large = False
+      if is_base:
+        type = "base"
+      else:
+        type = "current"
+      if len(content) > MAX_UPLOAD_SIZE:
+        print ("Not uploading the %s file for %s because it's too large." %
+               (type, filename))
+        file_too_large = True
+        content = ""
+      checksum = md5.new(content).hexdigest()
+      if options.verbose > 0 and not file_too_large:
+        print "Uploading %s file for %s" % (type, filename)
+      url = "/%d/upload_content/%d/%d" % (int(issue), int(patchset), file_id)
+      form_fields = [("filename", filename),
+                     ("status", status),
+                     ("checksum", checksum),
+                     ("is_binary", str(is_binary)),
+                     ("is_current", str(not is_base)),
+                    ]
+      if file_too_large:
+        form_fields.append(("file_too_large", "1"))
+      if options.email:
+        form_fields.append(("user", options.email))
+      ctype, body = EncodeMultipartFormData(form_fields,
+                                            [("data", filename, content)])
+      response_body = rpc_server.Send(url, body,
+                                      content_type=ctype)
+      if not response_body.startswith("OK"):
+        StatusUpdate("  --> %s" % response_body)
+        sys.exit(1)
+
+    patches = dict()
+    [patches.setdefault(v, k) for k, v in patch_list]
+    for filename in patches.keys():
+      base_content, new_content, is_binary, status = files[filename]
+      file_id_str = patches.get(filename)
+      if file_id_str.find("nobase") != -1:
+        base_content = None
+        file_id_str = file_id_str[file_id_str.rfind("_") + 1:]
+      file_id = int(file_id_str)
+      if base_content != None:
+        UploadFile(filename, file_id, base_content, is_binary, status, True)
+      if new_content != None:
+        UploadFile(filename, file_id, new_content, is_binary, status, False)
+
+  def IsImage(self, filename):
+    """Returns true if the filename has an image extension."""
+    mimetype =  mimetypes.guess_type(filename)[0]
+    if not mimetype:
+      return False
+    return mimetype.startswith("image/")
+
+
+class SubversionVCS(VersionControlSystem):
+  """Implementation of the VersionControlSystem interface for Subversion."""
+
+  def __init__(self, options):
+    super(SubversionVCS, self).__init__(options)
+    if self.options.revision:
+      match = re.match(r"(\d+)(:(\d+))?", self.options.revision)
+      if not match:
+        ErrorExit("Invalid Subversion revision %s." % self.options.revision)
+      self.rev_start = match.group(1)
+      self.rev_end = match.group(3)
+    else:
+      self.rev_start = self.rev_end = None
+    # Cache output from "svn list -r REVNO dirname".
+    # Keys: dirname, Values: 2-tuple (ouput for start rev and end rev).
+    self.svnls_cache = {}
+    # SVN base URL is required to fetch files deleted in an older revision.
+    # Result is cached to not guess it over and over again in GetBaseFile().
+    required = self.options.download_base or self.options.revision is not None
+    self.svn_base = self._GuessBase(required)
+
+  def GuessBase(self, required):
+    """Wrapper for _GuessBase."""
+    return self.svn_base
+
+  def _GuessBase(self, required):
+    """Returns the SVN base URL.
+
+    Args:
+      required: If true, exits if the url can't be guessed, otherwise None is
+        returned.
+    """
+    info = RunShell(["svn", "info"])
+    for line in info.splitlines():
+      words = line.split()
+      if len(words) == 2 and words[0] == "URL:":
+        url = words[1]
+        scheme, netloc, path, params, query, fragment = urlparse.urlparse(url)
+        username, netloc = urllib.splituser(netloc)
+        if username:
+          logging.info("Removed username from base URL")
+        if netloc.endswith("svn.python.org"):
+          if netloc == "svn.python.org":
+            if path.startswith("/projects/"):
+              path = path[9:]
+          elif netloc != "pythondev@svn.python.org":
+            ErrorExit("Unrecognized Python URL: %s" % url)
+          base = "http://svn.python.org/view/*checkout*%s/" % path
+          logging.info("Guessed Python base = %s", base)
+        elif netloc.endswith("svn.collab.net"):
+          if path.startswith("/repos/"):
+            path = path[6:]
+          base = "http://svn.collab.net/viewvc/*checkout*%s/" % path
+          logging.info("Guessed CollabNet base = %s", base)
+        elif netloc.endswith(".googlecode.com"):
+          path = path + "/"
+          base = urlparse.urlunparse(("http", netloc, path, params,
+                                      query, fragment))
+          logging.info("Guessed Google Code base = %s", base)
+        else:
+          path = path + "/"
+          base = urlparse.urlunparse((scheme, netloc, path, params,
+                                      query, fragment))
+          logging.info("Guessed base = %s", base)
+        return base
+    if required:
+      ErrorExit("Can't find URL in output from svn info")
+    return None
+
+  def GenerateDiff(self, args):
+    cmd = ["svn", "diff"]
+    if self.options.revision:
+      cmd += ["-r", self.options.revision]
+    cmd.extend(args)
+    data = RunShell(cmd)
+    count = 0
+    for line in data.splitlines():
+      if line.startswith("Index:") or line.startswith("Property changes on:"):
+        count += 1
+        logging.info(line)
+    if not count:
+      ErrorExit("No valid patches found in output from svn diff")
+    return data
+
+  def _CollapseKeywords(self, content, keyword_str):
+    """Collapses SVN keywords."""
+    # svn cat translates keywords but svn diff doesn't. As a result of this
+    # behavior patching.PatchChunks() fails with a chunk mismatch error.
+    # This part was originally written by the Review Board development team
+    # who had the same problem (http://reviews.review-board.org/r/276/).
+    # Mapping of keywords to known aliases
+    svn_keywords = {
+      # Standard keywords
+      'Date':                ['Date', 'LastChangedDate'],
+      'Revision':            ['Revision', 'LastChangedRevision', 'Rev'],
+      'Author':              ['Author', 'LastChangedBy'],
+      'HeadURL':             ['HeadURL', 'URL'],
+      'Id':                  ['Id'],
+
+      # Aliases
+      'LastChangedDate':     ['LastChangedDate', 'Date'],
+      'LastChangedRevision': ['LastChangedRevision', 'Rev', 'Revision'],
+      'LastChangedBy':       ['LastChangedBy', 'Author'],
+      'URL':                 ['URL', 'HeadURL'],
+    }
+
+    def repl(m):
+       if m.group(2):
+         return "$%s::%s$" % (m.group(1), " " * len(m.group(3)))
+       return "$%s$" % m.group(1)
+    keywords = [keyword
+                for name in keyword_str.split(" ")
+                for keyword in svn_keywords.get(name, [])]
+    return re.sub(r"\$(%s):(:?)([^\$]+)\$" % '|'.join(keywords), repl, content)
+
+  def GetUnknownFiles(self):
+    status = RunShell(["svn", "status", "--ignore-externals"], silent_ok=True)
+    unknown_files = []
+    for line in status.split("\n"):
+      if line and line[0] == "?":
+        unknown_files.append(line)
+    return unknown_files
+
+  def ReadFile(self, filename):
+    """Returns the contents of a file."""
+    file = open(filename, 'rb')
+    result = ""
+    try:
+      result = file.read()
+    finally:
+      file.close()
+    return result
+
+  def GetStatus(self, filename):
+    """Returns the status of a file."""
+    if not self.options.revision:
+      status = RunShell(["svn", "status", "--ignore-externals", filename])
+      if not status:
+        ErrorExit("svn status returned no output for %s" % filename)
+      status_lines = status.splitlines()
+      # If file is in a cl, the output will begin with
+      # "\n--- Changelist 'cl_name':\n".  See
+      # http://svn.collab.net/repos/svn/trunk/notes/changelist-design.txt
+      if (len(status_lines) == 3 and
+          not status_lines[0] and
+          status_lines[1].startswith("--- Changelist")):
+        status = status_lines[2]
+      else:
+        status = status_lines[0]
+    # If we have a revision to diff against we need to run "svn list"
+    # for the old and the new revision and compare the results to get
+    # the correct status for a file.
+    else:
+      dirname, relfilename = os.path.split(filename)
+      if dirname not in self.svnls_cache:
+        cmd = ["svn", "list", "-r", self.rev_start, dirname or "."]
+        out, returncode = RunShellWithReturnCode(cmd)
+        if returncode:
+          ErrorExit("Failed to get status for %s." % filename)
+        old_files = out.splitlines()
+        args = ["svn", "list"]
+        if self.rev_end:
+          args += ["-r", self.rev_end]
+        cmd = args + [dirname or "."]
+        out, returncode = RunShellWithReturnCode(cmd)
+        if returncode:
+          ErrorExit("Failed to run command %s" % cmd)
+        self.svnls_cache[dirname] = (old_files, out.splitlines())
+      old_files, new_files = self.svnls_cache[dirname]
+      if relfilename in old_files and relfilename not in new_files:
+        status = "D   "
+      elif relfilename in old_files and relfilename in new_files:
+        status = "M   "
+      else:
+        status = "A   "
+    return status
+
+  def GetBaseFile(self, filename):
+    status = self.GetStatus(filename)
+    base_content = None
+    new_content = None
+
+    # If a file is copied its status will be "A  +", which signifies
+    # "addition-with-history".  See "svn st" for more information.  We need to
+    # upload the original file or else diff parsing will fail if the file was
+    # edited.
+    if status[0] == "A" and status[3] != "+":
+      # We'll need to upload the new content if we're adding a binary file
+      # since diff's output won't contain it.
+      mimetype = RunShell(["svn", "propget", "svn:mime-type", filename],
+                          silent_ok=True)
+      base_content = ""
+      is_binary = mimetype and not mimetype.startswith("text/")
+      if is_binary and self.IsImage(filename):
+        new_content = self.ReadFile(filename)
+    elif (status[0] in ("M", "D", "R") or
+          (status[0] == "A" and status[3] == "+") or  # Copied file.
+          (status[0] == " " and status[1] == "M")):  # Property change.
+      args = []
+      if self.options.revision:
+        url = "%s/%s@%s" % (self.svn_base, filename, self.rev_start)
+      else:
+        # Don't change filename, it's needed later.
+        url = filename
+        args += ["-r", "BASE"]
+      cmd = ["svn"] + args + ["propget", "svn:mime-type", url]
+      mimetype, returncode = RunShellWithReturnCode(cmd)
+      if returncode:
+        # File does not exist in the requested revision.
+        # Reset mimetype, it contains an error message.
+        mimetype = ""
+      get_base = False
+      is_binary = mimetype and not mimetype.startswith("text/")
+      if status[0] == " ":
+        # Empty base content just to force an upload.
+        base_content = ""
+      elif is_binary:
+        if self.IsImage(filename):
+          get_base = True
+          if status[0] == "M":
+            if not self.rev_end:
+              new_content = self.ReadFile(filename)
+            else:
+              url = "%s/%s@%s" % (self.svn_base, filename, self.rev_end)
+              new_content = RunShell(["svn", "cat", url],
+                                     universal_newlines=True, silent_ok=True)
+        else:
+          base_content = ""
+      else:
+        get_base = True
+
+      if get_base:
+        if is_binary:
+          universal_newlines = False
+        else:
+          universal_newlines = True
+        if self.rev_start:
+          # "svn cat -r REV delete_file.txt" doesn't work. cat requires
+          # the full URL with "@REV" appended instead of using "-r" option.
+          url = "%s/%s@%s" % (self.svn_base, filename, self.rev_start)
+          base_content = RunShell(["svn", "cat", url],
+                                  universal_newlines=universal_newlines,
+                                  silent_ok=True)
+        else:
+          base_content = RunShell(["svn", "cat", filename],
+                                  universal_newlines=universal_newlines,
+                                  silent_ok=True)
+        if not is_binary:
+          args = []
+          if self.rev_start:
+            url = "%s/%s@%s" % (self.svn_base, filename, self.rev_start)
+          else:
+            url = filename
+            args += ["-r", "BASE"]
+          cmd = ["svn"] + args + ["propget", "svn:keywords", url]
+          keywords, returncode = RunShellWithReturnCode(cmd)
+          if keywords and not returncode:
+            base_content = self._CollapseKeywords(base_content, keywords)
+    else:
+      StatusUpdate("svn status returned unexpected output: %s" % status)
+      sys.exit(1)
+    return base_content, new_content, is_binary, status[0:5]
+
+
+class GitVCS(VersionControlSystem):
+  """Implementation of the VersionControlSystem interface for Git."""
+
+  def __init__(self, options):
+    super(GitVCS, self).__init__(options)
+    # Map of filename -> hash of base file.
+    self.base_hashes = {}
+
+  def GenerateDiff(self, extra_args):
+    # This is more complicated than svn's GenerateDiff because we must convert
+    # the diff output to include an svn-style "Index:" line as well as record
+    # the hashes of the base files, so we can upload them along with our diff.
+    if self.options.revision:
+      extra_args = [self.options.revision] + extra_args
+    gitdiff = RunShell(["git", "diff", "--full-index"] + extra_args)
+    svndiff = []
+    filecount = 0
+    filename = None
+    for line in gitdiff.splitlines():
+      match = re.match(r"diff --git a/(.*) b/.*$", line)
+      if match:
+        filecount += 1
+        filename = match.group(1)
+        svndiff.append("Index: %s\n" % filename)
+      else:
+        # The "index" line in a git diff looks like this (long hashes elided):
+        #   index 82c0d44..b2cee3f 100755
+        # We want to save the left hash, as that identifies the base file.
+        match = re.match(r"index (\w+)\.\.", line)
+        if match:
+          self.base_hashes[filename] = match.group(1)
+      svndiff.append(line + "\n")
+    if not filecount:
+      ErrorExit("No valid patches found in output from git diff")
+    return "".join(svndiff)
+
+  def GetUnknownFiles(self):
+    status = RunShell(["git", "ls-files", "--exclude-standard", "--others"],
+                      silent_ok=True)
+    return status.splitlines()
+
+  def GetBaseFile(self, filename):
+    hash = self.base_hashes[filename]
+    base_content = None
+    new_content = None
+    is_binary = False
+    if hash == "0" * 40:  # All-zero hash indicates no base file.
+      status = "A"
+      base_content = ""
+    else:
+      status = "M"
+      base_content, returncode = RunShellWithReturnCode(["git", "show", hash])
+      if returncode:
+        ErrorExit("Got error status from 'git show %s'" % hash)
+    return (base_content, new_content, is_binary, status)
+
+
+class MercurialVCS(VersionControlSystem):
+  """Implementation of the VersionControlSystem interface for Mercurial."""
+
+  def __init__(self, options, repo_dir):
+    super(MercurialVCS, self).__init__(options)
+    # Absolute path to repository (we can be in a subdir)
+    self.repo_dir = os.path.normpath(repo_dir)
+    # Compute the subdir
+    cwd = os.path.normpath(os.getcwd())
+    assert cwd.startswith(self.repo_dir)
+    self.subdir = cwd[len(self.repo_dir):].lstrip(r"\/")
+    if self.options.revision:
+      self.base_rev = self.options.revision
+    else:
+      self.base_rev = RunShell(["hg", "parent", "-q"]).split(':')[1].strip()
+
+  def _GetRelPath(self, filename):
+    """Get relative path of a file according to the current directory,
+    given its logical path in the repo."""
+    assert filename.startswith(self.subdir), filename
+    return filename[len(self.subdir):].lstrip(r"\/")
+
+  def GenerateDiff(self, extra_args):
+    # If no file specified, restrict to the current subdir
+    extra_args = extra_args or ["."]
+    cmd = ["hg", "diff", "--git", "-r", self.base_rev] + extra_args
+    data = RunShell(cmd, silent_ok=True)
+    svndiff = []
+    filecount = 0
+    for line in data.splitlines():
+      m = re.match("diff --git a/(\S+) b/(\S+)", line)
+      if m:
+        # Modify line to make it look like as it comes from svn diff.
+        # With this modification no changes on the server side are required
+        # to make upload.py work with Mercurial repos.
+        # NOTE: for proper handling of moved/copied files, we have to use
+        # the second filename.
+        filename = m.group(2)
+        svndiff.append("Index: %s" % filename)
+        svndiff.append("=" * 67)
+        filecount += 1
+        logging.info(line)
+      else:
+        svndiff.append(line)
+    if not filecount:
+      ErrorExit("No valid patches found in output from hg diff")
+    return "\n".join(svndiff) + "\n"
+
+  def GetUnknownFiles(self):
+    """Return a list of files unknown to the VCS."""
+    args = []
+    status = RunShell(["hg", "status", "--rev", self.base_rev, "-u", "."],
+        silent_ok=True)
+    unknown_files = []
+    for line in status.splitlines():
+      st, fn = line.split(" ", 1)
+      if st == "?":
+        unknown_files.append(fn)
+    return unknown_files
+
+  def GetBaseFile(self, filename):
+    # "hg status" and "hg cat" both take a path relative to the current subdir
+    # rather than to the repo root, but "hg diff" has given us the full path
+    # to the repo root.
+    base_content = ""
+    new_content = None
+    is_binary = False
+    oldrelpath = relpath = self._GetRelPath(filename)
+    # "hg status -C" returns two lines for moved/copied files, one otherwise
+    out = RunShell(["hg", "status", "-C", "--rev", self.base_rev, relpath])
+    out = out.splitlines()
+    # HACK: strip error message about missing file/directory if it isn't in
+    # the working copy
+    if out[0].startswith('%s: ' % relpath):
+      out = out[1:]
+    if len(out) > 1:
+      # Moved/copied => considered as modified, use old filename to
+      # retrieve base contents
+      oldrelpath = out[1].strip()
+      status = "M"
+    else:
+      status, _ = out[0].split(' ', 1)
+    if status != "A":
+      base_content = RunShell(["hg", "cat", "-r", self.base_rev, oldrelpath],
+        silent_ok=True)
+      is_binary = "\0" in base_content  # Mercurial's heuristic
+    if status != "R":
+      new_content = open(relpath, "rb").read()
+      is_binary = is_binary or "\0" in new_content
+    if is_binary and base_content:
+      # Fetch again without converting newlines
+      base_content = RunShell(["hg", "cat", "-r", self.base_rev, oldrelpath],
+        silent_ok=True, universal_newlines=False)
+    if not is_binary or not self.IsImage(relpath):
+      new_content = None
+    return base_content, new_content, is_binary, status
+
+
+# NOTE: The SplitPatch function is duplicated in engine.py, keep them in sync.
+def SplitPatch(data):
+  """Splits a patch into separate pieces for each file.
+
+  Args:
+    data: A string containing the output of svn diff.
+
+  Returns:
+    A list of 2-tuple (filename, text) where text is the svn diff output
+      pertaining to filename.
+  """
+  patches = []
+  filename = None
+  diff = []
+  for line in data.splitlines(True):
+    new_filename = None
+    if line.startswith('Index:'):
+      unused, new_filename = line.split(':', 1)
+      new_filename = new_filename.strip()
+    elif line.startswith('Property changes on:'):
+      unused, temp_filename = line.split(':', 1)
+      # When a file is modified, paths use '/' between directories, however
+      # when a property is modified '\' is used on Windows.  Make them the same
+      # otherwise the file shows up twice.
+      temp_filename = temp_filename.strip().replace('\\', '/')
+      if temp_filename != filename:
+        # File has property changes but no modifications, create a new diff.
+        new_filename = temp_filename
+    if new_filename:
+      if filename and diff:
+        patches.append((filename, ''.join(diff)))
+      filename = new_filename
+      diff = [line]
+      continue
+    if diff is not None:
+      diff.append(line)
+  if filename and diff:
+    patches.append((filename, ''.join(diff)))
+  return patches
+
+
+def UploadSeparatePatches(issue, rpc_server, patchset, data, options):
+  """Uploads a separate patch for each file in the diff output.
+
+  Returns a list of [patch_key, filename] for each file.
+  """
+  patches = SplitPatch(data)
+  rv = []
+  for patch in patches:
+    if len(patch[1]) > MAX_UPLOAD_SIZE:
+      print ("Not uploading the patch for " + patch[0] +
+             " because the file is too large.")
+      continue
+    form_fields = [("filename", patch[0])]
+    if not options.download_base:
+      form_fields.append(("content_upload", "1"))
+    files = [("data", "data.diff", patch[1])]
+    ctype, body = EncodeMultipartFormData(form_fields, files)
+    url = "/%d/upload_patch/%d" % (int(issue), int(patchset))
+    print "Uploading patch for " + patch[0]
+    response_body = rpc_server.Send(url, body, content_type=ctype)
+    lines = response_body.splitlines()
+    if not lines or lines[0] != "OK":
+      StatusUpdate("  --> %s" % response_body)
+      sys.exit(1)
+    rv.append([lines[1], patch[0]])
+  return rv
+
+
+def GuessVCS(options):
+  """Helper to guess the version control system.
+
+  This examines the current directory, guesses which VersionControlSystem
+  we're using, and returns an instance of the appropriate class.  Exit with an
+  error if we can't figure it out.
+
+  Returns:
+    A VersionControlSystem instance. Exits if the VCS can't be guessed.
+  """
+  # Mercurial has a command to get the base directory of a repository
+  # Try running it, but don't die if we don't have hg installed.
+  # NOTE: we try Mercurial first as it can sit on top of an SVN working copy.
+  try:
+    out, returncode = RunShellWithReturnCode(["hg", "root"])
+    if returncode == 0:
+      return MercurialVCS(options, out.strip())
+  except OSError, (errno, message):
+    if errno != 2:  # ENOENT -- they don't have hg installed.
+      raise
+
+  # Subversion has a .svn in all working directories.
+  if os.path.isdir('.svn'):
+    logging.info("Guessed VCS = Subversion")
+    return SubversionVCS(options)
+
+  # Git has a command to test if you're in a git tree.
+  # Try running it, but don't die if we don't have git installed.
+  try:
+    out, returncode = RunShellWithReturnCode(["git", "rev-parse",
+                                              "--is-inside-work-tree"])
+    if returncode == 0:
+      return GitVCS(options)
+  except OSError, (errno, message):
+    if errno != 2:  # ENOENT -- they don't have git installed.
+      raise
+
+  ErrorExit(("Could not guess version control system. "
+             "Are you in a working copy directory?"))
+
+
+def RealMain(argv, data=None):
+  """The real main function.
+
+  Args:
+    argv: Command line arguments.
+    data: Diff contents. If None (default) the diff is generated by
+      the VersionControlSystem implementation returned by GuessVCS().
+
+  Returns:
+    A 2-tuple (issue id, patchset id).
+    The patchset id is None if the base files are not uploaded by this
+    script (applies only to SVN checkouts).
+  """
+  logging.basicConfig(format=("%(asctime).19s %(levelname)s %(filename)s:"
+                              "%(lineno)s %(message)s "))
+  os.environ['LC_ALL'] = 'C'
+  options, args = parser.parse_args(argv[1:])
+  global verbosity
+  verbosity = options.verbose
+  if verbosity >= 3:
+    logging.getLogger().setLevel(logging.DEBUG)
+  elif verbosity >= 2:
+    logging.getLogger().setLevel(logging.INFO)
+  vcs = GuessVCS(options)
+  if isinstance(vcs, SubversionVCS):
+    # base field is only allowed for Subversion.
+    # Note: Fetching base files may become deprecated in future releases.
+    base = vcs.GuessBase(options.download_base)
+  else:
+    base = None
+  if not base and options.download_base:
+    options.download_base = True
+    logging.info("Enabled upload of base file")
+  if not options.assume_yes:
+    vcs.CheckForUnknownFiles()
+  if data is None:
+    data = vcs.GenerateDiff(args)
+  files = vcs.GetBaseFiles(data)
+  if verbosity >= 1:
+    print "Upload server:", options.server, "(change with -s/--server)"
+  if options.issue:
+    prompt = "Message describing this patch set: "
+  else:
+    prompt = "New issue subject: "
+  message = options.message or raw_input(prompt).strip()
+  if not message:
+    ErrorExit("A non-empty message is required")
+  rpc_server = GetRpcServer(options)
+  form_fields = [("subject", message)]
+  if base:
+    form_fields.append(("base", base))
+  if options.issue:
+    form_fields.append(("issue", str(options.issue)))
+  if options.email:
+    form_fields.append(("user", options.email))
+  if options.reviewers:
+    for reviewer in options.reviewers.split(','):
+      if "@" in reviewer and not reviewer.split("@")[1].count(".") == 1:
+        ErrorExit("Invalid email address: %s" % reviewer)
+    form_fields.append(("reviewers", options.reviewers))
+  if options.cc:
+    for cc in options.cc.split(','):
+      if "@" in cc and not cc.split("@")[1].count(".") == 1:
+        ErrorExit("Invalid email address: %s" % cc)
+    form_fields.append(("cc", options.cc))
+  description = options.description
+  if options.description_file:
+    if options.description:
+      ErrorExit("Can't specify description and description_file")
+    file = open(options.description_file, 'r')
+    description = file.read()
+    file.close()
+  if description:
+    form_fields.append(("description", description))
+  # Send a hash of all the base file so the server can determine if a copy
+  # already exists in an earlier patchset.
+  base_hashes = ""
+  for file, info in files.iteritems():
+    if not info[0] is None:
+      checksum = md5.new(info[0]).hexdigest()
+      if base_hashes:
+        base_hashes += "|"
+      base_hashes += checksum + ":" + file
+  form_fields.append(("base_hashes", base_hashes))
+  # If we're uploading base files, don't send the email before the uploads, so
+  # that it contains the file status.
+  if options.send_mail and options.download_base:
+    form_fields.append(("send_mail", "1"))
+  if not options.download_base:
+    form_fields.append(("content_upload", "1"))
+  if len(data) > MAX_UPLOAD_SIZE:
+    print "Patch is large, so uploading file patches separately."
+    uploaded_diff_file = []
+    form_fields.append(("separate_patches", "1"))
+  else:
+    uploaded_diff_file = [("data", "data.diff", data)]
+  ctype, body = EncodeMultipartFormData(form_fields, uploaded_diff_file)
+  response_body = rpc_server.Send("/upload", body, content_type=ctype)
+  patchset = None
+  if not options.download_base or not uploaded_diff_file:
+    lines = response_body.splitlines()
+    if len(lines) >= 2:
+      msg = lines[0]
+      patchset = lines[1].strip()
+      patches = [x.split(" ", 1) for x in lines[2:]]
+    else:
+      msg = response_body
+  else:
+    msg = response_body
+  StatusUpdate(msg)
+  if not response_body.startswith("Issue created.") and \
+  not response_body.startswith("Issue updated."):
+    sys.exit(0)
+  issue = msg[msg.rfind("/")+1:]
+
+  if not uploaded_diff_file:
+    result = UploadSeparatePatches(issue, rpc_server, patchset, data, options)
+    if not options.download_base:
+      patches = result
+
+  if not options.download_base:
+    vcs.UploadBaseFiles(issue, rpc_server, patches, patchset, options, files)
+    if options.send_mail:
+      rpc_server.Send("/" + issue + "/mail", payload="")
+  return issue, patchset
+
+
+def main():
+  try:
+    RealMain(sys.argv)
+  except KeyboardInterrupt:
+    print
+    StatusUpdate("Interrupted.")
+    sys.exit(1)
+
+
+if __name__ == "__main__":
+  main()
diff --git a/third_party/googletest/googletest/scripts/upload_gtest.py b/third_party/googletest/googletest/scripts/upload_gtest.py
new file mode 100755
index 0000000..be19ae8
--- /dev/null
+++ b/third_party/googletest/googletest/scripts/upload_gtest.py
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+#
+# Copyright 2009, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""upload_gtest.py v0.1.0 -- uploads a Google Test patch for review.
+
+This simple wrapper passes all command line flags and
+--cc=googletestframework@googlegroups.com to upload.py.
+
+USAGE: upload_gtest.py [options for upload.py]
+"""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import os
+import sys
+
+CC_FLAG = '--cc='
+GTEST_GROUP = 'googletestframework@googlegroups.com'
+
+
+def main():
+  # Finds the path to upload.py, assuming it is in the same directory
+  # as this file.
+  my_dir = os.path.dirname(os.path.abspath(__file__))
+  upload_py_path = os.path.join(my_dir, 'upload.py')
+
+  # Adds Google Test discussion group to the cc line if it's not there
+  # already.
+  upload_py_argv = [upload_py_path]
+  found_cc_flag = False
+  for arg in sys.argv[1:]:
+    if arg.startswith(CC_FLAG):
+      found_cc_flag = True
+      cc_line = arg[len(CC_FLAG):]
+      cc_list = [addr for addr in cc_line.split(',') if addr]
+      if GTEST_GROUP not in cc_list:
+        cc_list.append(GTEST_GROUP)
+      upload_py_argv.append(CC_FLAG + ','.join(cc_list))
+    else:
+      upload_py_argv.append(arg)
+
+  if not found_cc_flag:
+    upload_py_argv.append(CC_FLAG + GTEST_GROUP)
+
+  # Invokes upload.py with the modified command line flags.
+  os.execv(upload_py_path, upload_py_argv)
+
+
+if __name__ == '__main__':
+  main()
diff --git a/third_party/googletest/googletest/src/gtest-all.cc b/third_party/googletest/googletest/src/gtest-all.cc
new file mode 100644
index 0000000..0a9cee5
--- /dev/null
+++ b/third_party/googletest/googletest/src/gtest-all.cc
@@ -0,0 +1,48 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: mheule@google.com (Markus Heule)
+//
+// Google C++ Testing Framework (Google Test)
+//
+// Sometimes it's desirable to build Google Test by compiling a single file.
+// This file serves this purpose.
+
+// This line ensures that gtest.h can be compiled on its own, even
+// when it's fused.
+#include "gtest/gtest.h"
+
+// The following lines pull in the real gtest *.cc files.
+#include "src/gtest.cc"
+#include "src/gtest-death-test.cc"
+#include "src/gtest-filepath.cc"
+#include "src/gtest-port.cc"
+#include "src/gtest-printers.cc"
+#include "src/gtest-test-part.cc"
+#include "src/gtest-typed-test.cc"
diff --git a/third_party/googletest/googletest/src/gtest-death-test.cc b/third_party/googletest/googletest/src/gtest-death-test.cc
new file mode 100644
index 0000000..c076d07
--- /dev/null
+++ b/third_party/googletest/googletest/src/gtest-death-test.cc
@@ -0,0 +1,1340 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan), vladl@google.com (Vlad Losev)
+//
+// This file implements death tests.
+
+#include "gtest/gtest-death-test.h"
+#include "gtest/internal/gtest-port.h"
+#include "gtest/internal/custom/gtest.h"
+
+#if GTEST_HAS_DEATH_TEST
+
+# if GTEST_OS_MAC
+#  include <crt_externs.h>
+# endif  // GTEST_OS_MAC
+
+# include <errno.h>
+# include <fcntl.h>
+# include <limits.h>
+
+# if GTEST_OS_LINUX
+#  include <signal.h>
+# endif  // GTEST_OS_LINUX
+
+# include <stdarg.h>
+
+# if GTEST_OS_WINDOWS
+#  include <windows.h>
+# else
+#  include <sys/mman.h>
+#  include <sys/wait.h>
+# endif  // GTEST_OS_WINDOWS
+
+# if GTEST_OS_QNX
+#  include <spawn.h>
+# endif  // GTEST_OS_QNX
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-string.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick exists to
+// prevent the accidental inclusion of gtest-internal-inl.h in the
+// user's code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+
+// Constants.
+
+// The default death test style.
+static const char kDefaultDeathTestStyle[] = "fast";
+
+GTEST_DEFINE_string_(
+    death_test_style,
+    internal::StringFromGTestEnv("death_test_style", kDefaultDeathTestStyle),
+    "Indicates how to run a death test in a forked child process: "
+    "\"threadsafe\" (child process re-executes the test binary "
+    "from the beginning, running only the specific death test) or "
+    "\"fast\" (child process runs the death test immediately "
+    "after forking).");
+
+GTEST_DEFINE_bool_(
+    death_test_use_fork,
+    internal::BoolFromGTestEnv("death_test_use_fork", false),
+    "Instructs to use fork()/_exit() instead of clone() in death tests. "
+    "Ignored and always uses fork() on POSIX systems where clone() is not "
+    "implemented. Useful when running under valgrind or similar tools if "
+    "those do not support clone(). Valgrind 3.3.1 will just fail if "
+    "it sees an unsupported combination of clone() flags. "
+    "It is not recommended to use this flag w/o valgrind though it will "
+    "work in 99% of the cases. Once valgrind is fixed, this flag will "
+    "most likely be removed.");
+
+namespace internal {
+GTEST_DEFINE_string_(
+    internal_run_death_test, "",
+    "Indicates the file, line number, temporal index of "
+    "the single death test to run, and a file descriptor to "
+    "which a success code may be sent, all separated by "
+    "the '|' characters.  This flag is specified if and only if the current "
+    "process is a sub-process launched for running a thread-safe "
+    "death test.  FOR INTERNAL USE ONLY.");
+}  // namespace internal
+
+#if GTEST_HAS_DEATH_TEST
+
+namespace internal {
+
+// Valid only for fast death tests. Indicates the code is running in the
+// child process of a fast style death test.
+static bool g_in_fast_death_test_child = false;
+
+// Returns a Boolean value indicating whether the caller is currently
+// executing in the context of the death test child process.  Tools such as
+// Valgrind heap checkers may need this to modify their behavior in death
+// tests.  IMPORTANT: This is an internal utility.  Using it may break the
+// implementation of death tests.  User code MUST NOT use it.
+bool InDeathTestChild() {
+# if GTEST_OS_WINDOWS
+
+  // On Windows, death tests are thread-safe regardless of the value of the
+  // death_test_style flag.
+  return !GTEST_FLAG(internal_run_death_test).empty();
+
+# else
+
+  if (GTEST_FLAG(death_test_style) == "threadsafe")
+    return !GTEST_FLAG(internal_run_death_test).empty();
+  else
+    return g_in_fast_death_test_child;
+#endif
+}
+
+}  // namespace internal
+
+// ExitedWithCode constructor.
+ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) {
+}
+
+// ExitedWithCode function-call operator.
+bool ExitedWithCode::operator()(int exit_status) const {
+# if GTEST_OS_WINDOWS
+
+  return exit_status == exit_code_;
+
+# else
+
+  return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_;
+
+# endif  // GTEST_OS_WINDOWS
+}
+
+# if !GTEST_OS_WINDOWS
+// KilledBySignal constructor.
+KilledBySignal::KilledBySignal(int signum) : signum_(signum) {
+}
+
+// KilledBySignal function-call operator.
+bool KilledBySignal::operator()(int exit_status) const {
+#  if defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_)
+  {
+    bool result;
+    if (GTEST_KILLED_BY_SIGNAL_OVERRIDE_(signum_, exit_status, &result)) {
+      return result;
+    }
+  }
+#  endif  // defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_)
+  return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_;
+}
+# endif  // !GTEST_OS_WINDOWS
+
+namespace internal {
+
+// Utilities needed for death tests.
+
+// Generates a textual description of a given exit code, in the format
+// specified by wait(2).
+static std::string ExitSummary(int exit_code) {
+  Message m;
+
+# if GTEST_OS_WINDOWS
+
+  m << "Exited with exit status " << exit_code;
+
+# else
+
+  if (WIFEXITED(exit_code)) {
+    m << "Exited with exit status " << WEXITSTATUS(exit_code);
+  } else if (WIFSIGNALED(exit_code)) {
+    m << "Terminated by signal " << WTERMSIG(exit_code);
+  }
+#  ifdef WCOREDUMP
+  if (WCOREDUMP(exit_code)) {
+    m << " (core dumped)";
+  }
+#  endif
+# endif  // GTEST_OS_WINDOWS
+
+  return m.GetString();
+}
+
+// Returns true if exit_status describes a process that was terminated
+// by a signal, or exited normally with a nonzero exit code.
+bool ExitedUnsuccessfully(int exit_status) {
+  return !ExitedWithCode(0)(exit_status);
+}
+
+# if !GTEST_OS_WINDOWS
+// Generates a textual failure message when a death test finds more than
+// one thread running, or cannot determine the number of threads, prior
+// to executing the given statement.  It is the responsibility of the
+// caller not to pass a thread_count of 1.
+static std::string DeathTestThreadWarning(size_t thread_count) {
+  Message msg;
+  msg << "Death tests use fork(), which is unsafe particularly"
+      << " in a threaded context. For this test, " << GTEST_NAME_ << " ";
+  if (thread_count == 0)
+    msg << "couldn't detect the number of threads.";
+  else
+    msg << "detected " << thread_count << " threads.";
+  return msg.GetString();
+}
+# endif  // !GTEST_OS_WINDOWS
+
+// Flag characters for reporting a death test that did not die.
+static const char kDeathTestLived = 'L';
+static const char kDeathTestReturned = 'R';
+static const char kDeathTestThrew = 'T';
+static const char kDeathTestInternalError = 'I';
+
+// An enumeration describing all of the possible ways that a death test can
+// conclude.  DIED means that the process died while executing the test
+// code; LIVED means that process lived beyond the end of the test code;
+// RETURNED means that the test statement attempted to execute a return
+// statement, which is not allowed; THREW means that the test statement
+// returned control by throwing an exception.  IN_PROGRESS means the test
+// has not yet concluded.
+// TODO(vladl@google.com): Unify names and possibly values for
+// AbortReason, DeathTestOutcome, and flag characters above.
+enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW };
+
+// Routine for aborting the program which is safe to call from an
+// exec-style death test child process, in which case the error
+// message is propagated back to the parent process.  Otherwise, the
+// message is simply printed to stderr.  In either case, the program
+// then exits with status 1.
+void DeathTestAbort(const std::string& message) {
+  // On a POSIX system, this function may be called from a threadsafe-style
+  // death test child process, which operates on a very small stack.  Use
+  // the heap for any additional non-minuscule memory requirements.
+  const InternalRunDeathTestFlag* const flag =
+      GetUnitTestImpl()->internal_run_death_test_flag();
+  if (flag != NULL) {
+    FILE* parent = posix::FDOpen(flag->write_fd(), "w");
+    fputc(kDeathTestInternalError, parent);
+    fprintf(parent, "%s", message.c_str());
+    fflush(parent);
+    _exit(1);
+  } else {
+    fprintf(stderr, "%s", message.c_str());
+    fflush(stderr);
+    posix::Abort();
+  }
+}
+
+// A replacement for CHECK that calls DeathTestAbort if the assertion
+// fails.
+# define GTEST_DEATH_TEST_CHECK_(expression) \
+  do { \
+    if (!::testing::internal::IsTrue(expression)) { \
+      DeathTestAbort( \
+          ::std::string("CHECK failed: File ") + __FILE__ +  ", line " \
+          + ::testing::internal::StreamableToString(__LINE__) + ": " \
+          + #expression); \
+    } \
+  } while (::testing::internal::AlwaysFalse())
+
+// This macro is similar to GTEST_DEATH_TEST_CHECK_, but it is meant for
+// evaluating any system call that fulfills two conditions: it must return
+// -1 on failure, and set errno to EINTR when it is interrupted and
+// should be tried again.  The macro expands to a loop that repeatedly
+// evaluates the expression as long as it evaluates to -1 and sets
+// errno to EINTR.  If the expression evaluates to -1 but errno is
+// something other than EINTR, DeathTestAbort is called.
+# define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \
+  do { \
+    int gtest_retval; \
+    do { \
+      gtest_retval = (expression); \
+    } while (gtest_retval == -1 && errno == EINTR); \
+    if (gtest_retval == -1) { \
+      DeathTestAbort( \
+          ::std::string("CHECK failed: File ") + __FILE__ + ", line " \
+          + ::testing::internal::StreamableToString(__LINE__) + ": " \
+          + #expression + " != -1"); \
+    } \
+  } while (::testing::internal::AlwaysFalse())
+
+// Returns the message describing the last system error in errno.
+std::string GetLastErrnoDescription() {
+    return errno == 0 ? "" : posix::StrError(errno);
+}
+
+// This is called from a death test parent process to read a failure
+// message from the death test child process and log it with the FATAL
+// severity. On Windows, the message is read from a pipe handle. On other
+// platforms, it is read from a file descriptor.
+static void FailFromInternalError(int fd) {
+  Message error;
+  char buffer[256];
+  int num_read;
+
+  do {
+    while ((num_read = posix::Read(fd, buffer, 255)) > 0) {
+      buffer[num_read] = '\0';
+      error << buffer;
+    }
+  } while (num_read == -1 && errno == EINTR);
+
+  if (num_read == 0) {
+    GTEST_LOG_(FATAL) << error.GetString();
+  } else {
+    const int last_error = errno;
+    GTEST_LOG_(FATAL) << "Error while reading death test internal: "
+                      << GetLastErrnoDescription() << " [" << last_error << "]";
+  }
+}
+
+// Death test constructor.  Increments the running death test count
+// for the current test.
+DeathTest::DeathTest() {
+  TestInfo* const info = GetUnitTestImpl()->current_test_info();
+  if (info == NULL) {
+    DeathTestAbort("Cannot run a death test outside of a TEST or "
+                   "TEST_F construct");
+  }
+}
+
+// Creates and returns a death test by dispatching to the current
+// death test factory.
+bool DeathTest::Create(const char* statement, const RE* regex,
+                       const char* file, int line, DeathTest** test) {
+  return GetUnitTestImpl()->death_test_factory()->Create(
+      statement, regex, file, line, test);
+}
+
+const char* DeathTest::LastMessage() {
+  return last_death_test_message_.c_str();
+}
+
+void DeathTest::set_last_death_test_message(const std::string& message) {
+  last_death_test_message_ = message;
+}
+
+std::string DeathTest::last_death_test_message_;
+
+// Provides cross platform implementation for some death functionality.
+class DeathTestImpl : public DeathTest {
+ protected:
+  DeathTestImpl(const char* a_statement, const RE* a_regex)
+      : statement_(a_statement),
+        regex_(a_regex),
+        spawned_(false),
+        status_(-1),
+        outcome_(IN_PROGRESS),
+        read_fd_(-1),
+        write_fd_(-1) {}
+
+  // read_fd_ is expected to be closed and cleared by a derived class.
+  ~DeathTestImpl() { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); }
+
+  void Abort(AbortReason reason);
+  virtual bool Passed(bool status_ok);
+
+  const char* statement() const { return statement_; }
+  const RE* regex() const { return regex_; }
+  bool spawned() const { return spawned_; }
+  void set_spawned(bool is_spawned) { spawned_ = is_spawned; }
+  int status() const { return status_; }
+  void set_status(int a_status) { status_ = a_status; }
+  DeathTestOutcome outcome() const { return outcome_; }
+  void set_outcome(DeathTestOutcome an_outcome) { outcome_ = an_outcome; }
+  int read_fd() const { return read_fd_; }
+  void set_read_fd(int fd) { read_fd_ = fd; }
+  int write_fd() const { return write_fd_; }
+  void set_write_fd(int fd) { write_fd_ = fd; }
+
+  // Called in the parent process only. Reads the result code of the death
+  // test child process via a pipe, interprets it to set the outcome_
+  // member, and closes read_fd_.  Outputs diagnostics and terminates in
+  // case of unexpected codes.
+  void ReadAndInterpretStatusByte();
+
+ private:
+  // The textual content of the code this object is testing.  This class
+  // doesn't own this string and should not attempt to delete it.
+  const char* const statement_;
+  // The regular expression which test output must match.  DeathTestImpl
+  // doesn't own this object and should not attempt to delete it.
+  const RE* const regex_;
+  // True if the death test child process has been successfully spawned.
+  bool spawned_;
+  // The exit status of the child process.
+  int status_;
+  // How the death test concluded.
+  DeathTestOutcome outcome_;
+  // Descriptor to the read end of the pipe to the child process.  It is
+  // always -1 in the child process.  The child keeps its write end of the
+  // pipe in write_fd_.
+  int read_fd_;
+  // Descriptor to the child's write end of the pipe to the parent process.
+  // It is always -1 in the parent process.  The parent keeps its end of the
+  // pipe in read_fd_.
+  int write_fd_;
+};
+
+// Called in the parent process only. Reads the result code of the death
+// test child process via a pipe, interprets it to set the outcome_
+// member, and closes read_fd_.  Outputs diagnostics and terminates in
+// case of unexpected codes.
+void DeathTestImpl::ReadAndInterpretStatusByte() {
+  char flag;
+  int bytes_read;
+
+  // The read() here blocks until data is available (signifying the
+  // failure of the death test) or until the pipe is closed (signifying
+  // its success), so it's okay to call this in the parent before
+  // the child process has exited.
+  do {
+    bytes_read = posix::Read(read_fd(), &flag, 1);
+  } while (bytes_read == -1 && errno == EINTR);
+
+  if (bytes_read == 0) {
+    set_outcome(DIED);
+  } else if (bytes_read == 1) {
+    switch (flag) {
+      case kDeathTestReturned:
+        set_outcome(RETURNED);
+        break;
+      case kDeathTestThrew:
+        set_outcome(THREW);
+        break;
+      case kDeathTestLived:
+        set_outcome(LIVED);
+        break;
+      case kDeathTestInternalError:
+        FailFromInternalError(read_fd());  // Does not return.
+        break;
+      default:
+        GTEST_LOG_(FATAL) << "Death test child process reported "
+                          << "unexpected status byte ("
+                          << static_cast<unsigned int>(flag) << ")";
+    }
+  } else {
+    GTEST_LOG_(FATAL) << "Read from death test child process failed: "
+                      << GetLastErrnoDescription();
+  }
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(read_fd()));
+  set_read_fd(-1);
+}
+
+// Signals that the death test code which should have exited, didn't.
+// Should be called only in a death test child process.
+// Writes a status byte to the child's status file descriptor, then
+// calls _exit(1).
+void DeathTestImpl::Abort(AbortReason reason) {
+  // The parent process considers the death test to be a failure if
+  // it finds any data in our pipe.  So, here we write a single flag byte
+  // to the pipe, then exit.
+  const char status_ch =
+      reason == TEST_DID_NOT_DIE ? kDeathTestLived :
+      reason == TEST_THREW_EXCEPTION ? kDeathTestThrew : kDeathTestReturned;
+
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1));
+  // We are leaking the descriptor here because on some platforms (i.e.,
+  // when built as Windows DLL), destructors of global objects will still
+  // run after calling _exit(). On such systems, write_fd_ will be
+  // indirectly closed from the destructor of UnitTestImpl, causing double
+  // close if it is also closed here. On debug configurations, double close
+  // may assert. As there are no in-process buffers to flush here, we are
+  // relying on the OS to close the descriptor after the process terminates
+  // when the destructors are not run.
+  _exit(1);  // Exits w/o any normal exit hooks (we were supposed to crash)
+}
+
+// Returns an indented copy of stderr output for a death test.
+// This makes distinguishing death test output lines from regular log lines
+// much easier.
+static ::std::string FormatDeathTestOutput(const ::std::string& output) {
+  ::std::string ret;
+  for (size_t at = 0; ; ) {
+    const size_t line_end = output.find('\n', at);
+    ret += "[  DEATH   ] ";
+    if (line_end == ::std::string::npos) {
+      ret += output.substr(at);
+      break;
+    }
+    ret += output.substr(at, line_end + 1 - at);
+    at = line_end + 1;
+  }
+  return ret;
+}
+
+// Assesses the success or failure of a death test, using both private
+// members which have previously been set, and one argument:
+//
+// Private data members:
+//   outcome:  An enumeration describing how the death test
+//             concluded: DIED, LIVED, THREW, or RETURNED.  The death test
+//             fails in the latter three cases.
+//   status:   The exit status of the child process. On *nix, it is in the
+//             in the format specified by wait(2). On Windows, this is the
+//             value supplied to the ExitProcess() API or a numeric code
+//             of the exception that terminated the program.
+//   regex:    A regular expression object to be applied to
+//             the test's captured standard error output; the death test
+//             fails if it does not match.
+//
+// Argument:
+//   status_ok: true if exit_status is acceptable in the context of
+//              this particular death test, which fails if it is false
+//
+// Returns true iff all of the above conditions are met.  Otherwise, the
+// first failing condition, in the order given above, is the one that is
+// reported. Also sets the last death test message string.
+bool DeathTestImpl::Passed(bool status_ok) {
+  if (!spawned())
+    return false;
+
+  const std::string error_message = GetCapturedStderr();
+
+  bool success = false;
+  Message buffer;
+
+  buffer << "Death test: " << statement() << "\n";
+  switch (outcome()) {
+    case LIVED:
+      buffer << "    Result: failed to die.\n"
+             << " Error msg:\n" << FormatDeathTestOutput(error_message);
+      break;
+    case THREW:
+      buffer << "    Result: threw an exception.\n"
+             << " Error msg:\n" << FormatDeathTestOutput(error_message);
+      break;
+    case RETURNED:
+      buffer << "    Result: illegal return in test statement.\n"
+             << " Error msg:\n" << FormatDeathTestOutput(error_message);
+      break;
+    case DIED:
+      if (status_ok) {
+        const bool matched = RE::PartialMatch(error_message.c_str(), *regex());
+        if (matched) {
+          success = true;
+        } else {
+          buffer << "    Result: died but not with expected error.\n"
+                 << "  Expected: " << regex()->pattern() << "\n"
+                 << "Actual msg:\n" << FormatDeathTestOutput(error_message);
+        }
+      } else {
+        buffer << "    Result: died but not with expected exit code:\n"
+               << "            " << ExitSummary(status()) << "\n"
+               << "Actual msg:\n" << FormatDeathTestOutput(error_message);
+      }
+      break;
+    case IN_PROGRESS:
+    default:
+      GTEST_LOG_(FATAL)
+          << "DeathTest::Passed somehow called before conclusion of test";
+  }
+
+  DeathTest::set_last_death_test_message(buffer.GetString());
+  return success;
+}
+
+# if GTEST_OS_WINDOWS
+// WindowsDeathTest implements death tests on Windows. Due to the
+// specifics of starting new processes on Windows, death tests there are
+// always threadsafe, and Google Test considers the
+// --gtest_death_test_style=fast setting to be equivalent to
+// --gtest_death_test_style=threadsafe there.
+//
+// A few implementation notes:  Like the Linux version, the Windows
+// implementation uses pipes for child-to-parent communication. But due to
+// the specifics of pipes on Windows, some extra steps are required:
+//
+// 1. The parent creates a communication pipe and stores handles to both
+//    ends of it.
+// 2. The parent starts the child and provides it with the information
+//    necessary to acquire the handle to the write end of the pipe.
+// 3. The child acquires the write end of the pipe and signals the parent
+//    using a Windows event.
+// 4. Now the parent can release the write end of the pipe on its side. If
+//    this is done before step 3, the object's reference count goes down to
+//    0 and it is destroyed, preventing the child from acquiring it. The
+//    parent now has to release it, or read operations on the read end of
+//    the pipe will not return when the child terminates.
+// 5. The parent reads child's output through the pipe (outcome code and
+//    any possible error messages) from the pipe, and its stderr and then
+//    determines whether to fail the test.
+//
+// Note: to distinguish Win32 API calls from the local method and function
+// calls, the former are explicitly resolved in the global namespace.
+//
+class WindowsDeathTest : public DeathTestImpl {
+ public:
+  WindowsDeathTest(const char* a_statement,
+                   const RE* a_regex,
+                   const char* file,
+                   int line)
+      : DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {}
+
+  // All of these virtual functions are inherited from DeathTest.
+  virtual int Wait();
+  virtual TestRole AssumeRole();
+
+ private:
+  // The name of the file in which the death test is located.
+  const char* const file_;
+  // The line number on which the death test is located.
+  const int line_;
+  // Handle to the write end of the pipe to the child process.
+  AutoHandle write_handle_;
+  // Child process handle.
+  AutoHandle child_handle_;
+  // Event the child process uses to signal the parent that it has
+  // acquired the handle to the write end of the pipe. After seeing this
+  // event the parent can release its own handles to make sure its
+  // ReadFile() calls return when the child terminates.
+  AutoHandle event_handle_;
+};
+
+// Waits for the child in a death test to exit, returning its exit
+// status, or 0 if no child process exists.  As a side effect, sets the
+// outcome data member.
+int WindowsDeathTest::Wait() {
+  if (!spawned())
+    return 0;
+
+  // Wait until the child either signals that it has acquired the write end
+  // of the pipe or it dies.
+  const HANDLE wait_handles[2] = { child_handle_.Get(), event_handle_.Get() };
+  switch (::WaitForMultipleObjects(2,
+                                   wait_handles,
+                                   FALSE,  // Waits for any of the handles.
+                                   INFINITE)) {
+    case WAIT_OBJECT_0:
+    case WAIT_OBJECT_0 + 1:
+      break;
+    default:
+      GTEST_DEATH_TEST_CHECK_(false);  // Should not get here.
+  }
+
+  // The child has acquired the write end of the pipe or exited.
+  // We release the handle on our side and continue.
+  write_handle_.Reset();
+  event_handle_.Reset();
+
+  ReadAndInterpretStatusByte();
+
+  // Waits for the child process to exit if it haven't already. This
+  // returns immediately if the child has already exited, regardless of
+  // whether previous calls to WaitForMultipleObjects synchronized on this
+  // handle or not.
+  GTEST_DEATH_TEST_CHECK_(
+      WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(),
+                                             INFINITE));
+  DWORD status_code;
+  GTEST_DEATH_TEST_CHECK_(
+      ::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE);
+  child_handle_.Reset();
+  set_status(static_cast<int>(status_code));
+  return status();
+}
+
+// The AssumeRole process for a Windows death test.  It creates a child
+// process with the same executable as the current process to run the
+// death test.  The child process is given the --gtest_filter and
+// --gtest_internal_run_death_test flags such that it knows to run the
+// current death test only.
+DeathTest::TestRole WindowsDeathTest::AssumeRole() {
+  const UnitTestImpl* const impl = GetUnitTestImpl();
+  const InternalRunDeathTestFlag* const flag =
+      impl->internal_run_death_test_flag();
+  const TestInfo* const info = impl->current_test_info();
+  const int death_test_index = info->result()->death_test_count();
+
+  if (flag != NULL) {
+    // ParseInternalRunDeathTestFlag() has performed all the necessary
+    // processing.
+    set_write_fd(flag->write_fd());
+    return EXECUTE_TEST;
+  }
+
+  // WindowsDeathTest uses an anonymous pipe to communicate results of
+  // a death test.
+  SECURITY_ATTRIBUTES handles_are_inheritable = {
+    sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
+  HANDLE read_handle, write_handle;
+  GTEST_DEATH_TEST_CHECK_(
+      ::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable,
+                   0)  // Default buffer size.
+      != FALSE);
+  set_read_fd(::_open_osfhandle(reinterpret_cast<intptr_t>(read_handle),
+                                O_RDONLY));
+  write_handle_.Reset(write_handle);
+  event_handle_.Reset(::CreateEvent(
+      &handles_are_inheritable,
+      TRUE,    // The event will automatically reset to non-signaled state.
+      FALSE,   // The initial state is non-signalled.
+      NULL));  // The even is unnamed.
+  GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != NULL);
+  const std::string filter_flag =
+      std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "=" +
+      info->test_case_name() + "." + info->name();
+  const std::string internal_flag =
+      std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag +
+      "=" + file_ + "|" + StreamableToString(line_) + "|" +
+      StreamableToString(death_test_index) + "|" +
+      StreamableToString(static_cast<unsigned int>(::GetCurrentProcessId())) +
+      // size_t has the same width as pointers on both 32-bit and 64-bit
+      // Windows platforms.
+      // See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx.
+      "|" + StreamableToString(reinterpret_cast<size_t>(write_handle)) +
+      "|" + StreamableToString(reinterpret_cast<size_t>(event_handle_.Get()));
+
+  char executable_path[_MAX_PATH + 1];  // NOLINT
+  GTEST_DEATH_TEST_CHECK_(
+      _MAX_PATH + 1 != ::GetModuleFileNameA(NULL,
+                                            executable_path,
+                                            _MAX_PATH));
+
+  std::string command_line =
+      std::string(::GetCommandLineA()) + " " + filter_flag + " \"" +
+      internal_flag + "\"";
+
+  DeathTest::set_last_death_test_message("");
+
+  CaptureStderr();
+  // Flush the log buffers since the log streams are shared with the child.
+  FlushInfoLog();
+
+  // The child process will share the standard handles with the parent.
+  STARTUPINFOA startup_info;
+  memset(&startup_info, 0, sizeof(STARTUPINFO));
+  startup_info.dwFlags = STARTF_USESTDHANDLES;
+  startup_info.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE);
+  startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
+  startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
+
+  PROCESS_INFORMATION process_info;
+  GTEST_DEATH_TEST_CHECK_(::CreateProcessA(
+      executable_path,
+      const_cast<char*>(command_line.c_str()),
+      NULL,   // Retuned process handle is not inheritable.
+      NULL,   // Retuned thread handle is not inheritable.
+      TRUE,   // Child inherits all inheritable handles (for write_handle_).
+      0x0,    // Default creation flags.
+      NULL,   // Inherit the parent's environment.
+      UnitTest::GetInstance()->original_working_dir(),
+      &startup_info,
+      &process_info) != FALSE);
+  child_handle_.Reset(process_info.hProcess);
+  ::CloseHandle(process_info.hThread);
+  set_spawned(true);
+  return OVERSEE_TEST;
+}
+# else  // We are not on Windows.
+
+// ForkingDeathTest provides implementations for most of the abstract
+// methods of the DeathTest interface.  Only the AssumeRole method is
+// left undefined.
+class ForkingDeathTest : public DeathTestImpl {
+ public:
+  ForkingDeathTest(const char* statement, const RE* regex);
+
+  // All of these virtual functions are inherited from DeathTest.
+  virtual int Wait();
+
+ protected:
+  void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; }
+
+ private:
+  // PID of child process during death test; 0 in the child process itself.
+  pid_t child_pid_;
+};
+
+// Constructs a ForkingDeathTest.
+ForkingDeathTest::ForkingDeathTest(const char* a_statement, const RE* a_regex)
+    : DeathTestImpl(a_statement, a_regex),
+      child_pid_(-1) {}
+
+// Waits for the child in a death test to exit, returning its exit
+// status, or 0 if no child process exists.  As a side effect, sets the
+// outcome data member.
+int ForkingDeathTest::Wait() {
+  if (!spawned())
+    return 0;
+
+  ReadAndInterpretStatusByte();
+
+  int status_value;
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_value, 0));
+  set_status(status_value);
+  return status_value;
+}
+
+// A concrete death test class that forks, then immediately runs the test
+// in the child process.
+class NoExecDeathTest : public ForkingDeathTest {
+ public:
+  NoExecDeathTest(const char* a_statement, const RE* a_regex) :
+      ForkingDeathTest(a_statement, a_regex) { }
+  virtual TestRole AssumeRole();
+};
+
+// The AssumeRole process for a fork-and-run death test.  It implements a
+// straightforward fork, with a simple pipe to transmit the status byte.
+DeathTest::TestRole NoExecDeathTest::AssumeRole() {
+  const size_t thread_count = GetThreadCount();
+  if (thread_count != 1) {
+    GTEST_LOG_(WARNING) << DeathTestThreadWarning(thread_count);
+  }
+
+  int pipe_fd[2];
+  GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1);
+
+  DeathTest::set_last_death_test_message("");
+  CaptureStderr();
+  // When we fork the process below, the log file buffers are copied, but the
+  // file descriptors are shared.  We flush all log files here so that closing
+  // the file descriptors in the child process doesn't throw off the
+  // synchronization between descriptors and buffers in the parent process.
+  // This is as close to the fork as possible to avoid a race condition in case
+  // there are multiple threads running before the death test, and another
+  // thread writes to the log file.
+  FlushInfoLog();
+
+  const pid_t child_pid = fork();
+  GTEST_DEATH_TEST_CHECK_(child_pid != -1);
+  set_child_pid(child_pid);
+  if (child_pid == 0) {
+    GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[0]));
+    set_write_fd(pipe_fd[1]);
+    // Redirects all logging to stderr in the child process to prevent
+    // concurrent writes to the log files.  We capture stderr in the parent
+    // process and append the child process' output to a log.
+    LogToStderr();
+    // Event forwarding to the listeners of event listener API mush be shut
+    // down in death test subprocesses.
+    GetUnitTestImpl()->listeners()->SuppressEventForwarding();
+    g_in_fast_death_test_child = true;
+    return EXECUTE_TEST;
+  } else {
+    GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
+    set_read_fd(pipe_fd[0]);
+    set_spawned(true);
+    return OVERSEE_TEST;
+  }
+}
+
+// A concrete death test class that forks and re-executes the main
+// program from the beginning, with command-line flags set that cause
+// only this specific death test to be run.
+class ExecDeathTest : public ForkingDeathTest {
+ public:
+  ExecDeathTest(const char* a_statement, const RE* a_regex,
+                const char* file, int line) :
+      ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { }
+  virtual TestRole AssumeRole();
+ private:
+  static ::std::vector<testing::internal::string>
+  GetArgvsForDeathTestChildProcess() {
+    ::std::vector<testing::internal::string> args = GetInjectableArgvs();
+#  if defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_)
+    ::std::vector<testing::internal::string> extra_args =
+        GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_();
+    args.insert(args.end(), extra_args.begin(), extra_args.end());
+#  endif  // defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_)
+    return args;
+  }
+  // The name of the file in which the death test is located.
+  const char* const file_;
+  // The line number on which the death test is located.
+  const int line_;
+};
+
+// Utility class for accumulating command-line arguments.
+class Arguments {
+ public:
+  Arguments() {
+    args_.push_back(NULL);
+  }
+
+  ~Arguments() {
+    for (std::vector<char*>::iterator i = args_.begin(); i != args_.end();
+         ++i) {
+      free(*i);
+    }
+  }
+  void AddArgument(const char* argument) {
+    args_.insert(args_.end() - 1, posix::StrDup(argument));
+  }
+
+  template <typename Str>
+  void AddArguments(const ::std::vector<Str>& arguments) {
+    for (typename ::std::vector<Str>::const_iterator i = arguments.begin();
+         i != arguments.end();
+         ++i) {
+      args_.insert(args_.end() - 1, posix::StrDup(i->c_str()));
+    }
+  }
+  char* const* Argv() {
+    return &args_[0];
+  }
+
+ private:
+  std::vector<char*> args_;
+};
+
+// A struct that encompasses the arguments to the child process of a
+// threadsafe-style death test process.
+struct ExecDeathTestArgs {
+  char* const* argv;  // Command-line arguments for the child's call to exec
+  int close_fd;       // File descriptor to close; the read end of a pipe
+};
+
+#  if GTEST_OS_MAC
+inline char** GetEnviron() {
+  // When Google Test is built as a framework on MacOS X, the environ variable
+  // is unavailable. Apple's documentation (man environ) recommends using
+  // _NSGetEnviron() instead.
+  return *_NSGetEnviron();
+}
+#  else
+// Some POSIX platforms expect you to declare environ. extern "C" makes
+// it reside in the global namespace.
+extern "C" char** environ;
+inline char** GetEnviron() { return environ; }
+#  endif  // GTEST_OS_MAC
+
+#  if !GTEST_OS_QNX
+// The main function for a threadsafe-style death test child process.
+// This function is called in a clone()-ed process and thus must avoid
+// any potentially unsafe operations like malloc or libc functions.
+static int ExecDeathTestChildMain(void* child_arg) {
+  ExecDeathTestArgs* const args = static_cast<ExecDeathTestArgs*>(child_arg);
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(close(args->close_fd));
+
+  // We need to execute the test program in the same environment where
+  // it was originally invoked.  Therefore we change to the original
+  // working directory first.
+  const char* const original_dir =
+      UnitTest::GetInstance()->original_working_dir();
+  // We can safely call chdir() as it's a direct system call.
+  if (chdir(original_dir) != 0) {
+    DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " +
+                   GetLastErrnoDescription());
+    return EXIT_FAILURE;
+  }
+
+  // We can safely call execve() as it's a direct system call.  We
+  // cannot use execvp() as it's a libc function and thus potentially
+  // unsafe.  Since execve() doesn't search the PATH, the user must
+  // invoke the test program via a valid path that contains at least
+  // one path separator.
+  execve(args->argv[0], args->argv, GetEnviron());
+  DeathTestAbort(std::string("execve(") + args->argv[0] + ", ...) in " +
+                 original_dir + " failed: " +
+                 GetLastErrnoDescription());
+  return EXIT_FAILURE;
+}
+#  endif  // !GTEST_OS_QNX
+
+// Two utility routines that together determine the direction the stack
+// grows.
+// This could be accomplished more elegantly by a single recursive
+// function, but we want to guard against the unlikely possibility of
+// a smart compiler optimizing the recursion away.
+//
+// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining
+// StackLowerThanAddress into StackGrowsDown, which then doesn't give
+// correct answer.
+void StackLowerThanAddress(const void* ptr, bool* result) GTEST_NO_INLINE_;
+void StackLowerThanAddress(const void* ptr, bool* result) {
+  int dummy;
+  *result = (&dummy < ptr);
+}
+
+// Make sure AddressSanitizer does not tamper with the stack here.
+GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
+bool StackGrowsDown() {
+  int dummy;
+  bool result;
+  StackLowerThanAddress(&dummy, &result);
+  return result;
+}
+
+// Spawns a child process with the same executable as the current process in
+// a thread-safe manner and instructs it to run the death test.  The
+// implementation uses fork(2) + exec.  On systems where clone(2) is
+// available, it is used instead, being slightly more thread-safe.  On QNX,
+// fork supports only single-threaded environments, so this function uses
+// spawn(2) there instead.  The function dies with an error message if
+// anything goes wrong.
+static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
+  ExecDeathTestArgs args = { argv, close_fd };
+  pid_t child_pid = -1;
+
+#  if GTEST_OS_QNX
+  // Obtains the current directory and sets it to be closed in the child
+  // process.
+  const int cwd_fd = open(".", O_RDONLY);
+  GTEST_DEATH_TEST_CHECK_(cwd_fd != -1);
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(cwd_fd, F_SETFD, FD_CLOEXEC));
+  // We need to execute the test program in the same environment where
+  // it was originally invoked.  Therefore we change to the original
+  // working directory first.
+  const char* const original_dir =
+      UnitTest::GetInstance()->original_working_dir();
+  // We can safely call chdir() as it's a direct system call.
+  if (chdir(original_dir) != 0) {
+    DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " +
+                   GetLastErrnoDescription());
+    return EXIT_FAILURE;
+  }
+
+  int fd_flags;
+  // Set close_fd to be closed after spawn.
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(fd_flags = fcntl(close_fd, F_GETFD));
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(close_fd, F_SETFD,
+                                        fd_flags | FD_CLOEXEC));
+  struct inheritance inherit = {0};
+  // spawn is a system call.
+  child_pid = spawn(args.argv[0], 0, NULL, &inherit, args.argv, GetEnviron());
+  // Restores the current working directory.
+  GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1);
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd));
+
+#  else   // GTEST_OS_QNX
+#   if GTEST_OS_LINUX
+  // When a SIGPROF signal is received while fork() or clone() are executing,
+  // the process may hang. To avoid this, we ignore SIGPROF here and re-enable
+  // it after the call to fork()/clone() is complete.
+  struct sigaction saved_sigprof_action;
+  struct sigaction ignore_sigprof_action;
+  memset(&ignore_sigprof_action, 0, sizeof(ignore_sigprof_action));
+  sigemptyset(&ignore_sigprof_action.sa_mask);
+  ignore_sigprof_action.sa_handler = SIG_IGN;
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(sigaction(
+      SIGPROF, &ignore_sigprof_action, &saved_sigprof_action));
+#   endif  // GTEST_OS_LINUX
+
+#   if GTEST_HAS_CLONE
+  const bool use_fork = GTEST_FLAG(death_test_use_fork);
+
+  if (!use_fork) {
+    static const bool stack_grows_down = StackGrowsDown();
+    const size_t stack_size = getpagesize();
+    // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead.
+    void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,
+                             MAP_ANON | MAP_PRIVATE, -1, 0);
+    GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED);
+
+    // Maximum stack alignment in bytes:  For a downward-growing stack, this
+    // amount is subtracted from size of the stack space to get an address
+    // that is within the stack space and is aligned on all systems we care
+    // about.  As far as I know there is no ABI with stack alignment greater
+    // than 64.  We assume stack and stack_size already have alignment of
+    // kMaxStackAlignment.
+    const size_t kMaxStackAlignment = 64;
+    void* const stack_top =
+        static_cast<char*>(stack) +
+            (stack_grows_down ? stack_size - kMaxStackAlignment : 0);
+    GTEST_DEATH_TEST_CHECK_(stack_size > kMaxStackAlignment &&
+        reinterpret_cast<intptr_t>(stack_top) % kMaxStackAlignment == 0);
+
+    child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args);
+
+    GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
+  }
+#   else
+  const bool use_fork = true;
+#   endif  // GTEST_HAS_CLONE
+
+  if (use_fork && (child_pid = fork()) == 0) {
+      ExecDeathTestChildMain(&args);
+      _exit(0);
+  }
+#  endif  // GTEST_OS_QNX
+#  if GTEST_OS_LINUX
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(
+      sigaction(SIGPROF, &saved_sigprof_action, NULL));
+#  endif  // GTEST_OS_LINUX
+
+  GTEST_DEATH_TEST_CHECK_(child_pid != -1);
+  return child_pid;
+}
+
+// The AssumeRole process for a fork-and-exec death test.  It re-executes the
+// main program from the beginning, setting the --gtest_filter
+// and --gtest_internal_run_death_test flags to cause only the current
+// death test to be re-run.
+DeathTest::TestRole ExecDeathTest::AssumeRole() {
+  const UnitTestImpl* const impl = GetUnitTestImpl();
+  const InternalRunDeathTestFlag* const flag =
+      impl->internal_run_death_test_flag();
+  const TestInfo* const info = impl->current_test_info();
+  const int death_test_index = info->result()->death_test_count();
+
+  if (flag != NULL) {
+    set_write_fd(flag->write_fd());
+    return EXECUTE_TEST;
+  }
+
+  int pipe_fd[2];
+  GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1);
+  // Clear the close-on-exec flag on the write end of the pipe, lest
+  // it be closed when the child process does an exec:
+  GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1);
+
+  const std::string filter_flag =
+      std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "="
+      + info->test_case_name() + "." + info->name();
+  const std::string internal_flag =
+      std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "="
+      + file_ + "|" + StreamableToString(line_) + "|"
+      + StreamableToString(death_test_index) + "|"
+      + StreamableToString(pipe_fd[1]);
+  Arguments args;
+  args.AddArguments(GetArgvsForDeathTestChildProcess());
+  args.AddArgument(filter_flag.c_str());
+  args.AddArgument(internal_flag.c_str());
+
+  DeathTest::set_last_death_test_message("");
+
+  CaptureStderr();
+  // See the comment in NoExecDeathTest::AssumeRole for why the next line
+  // is necessary.
+  FlushInfoLog();
+
+  const pid_t child_pid = ExecDeathTestSpawnChild(args.Argv(), pipe_fd[0]);
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
+  set_child_pid(child_pid);
+  set_read_fd(pipe_fd[0]);
+  set_spawned(true);
+  return OVERSEE_TEST;
+}
+
+# endif  // !GTEST_OS_WINDOWS
+
+// Creates a concrete DeathTest-derived class that depends on the
+// --gtest_death_test_style flag, and sets the pointer pointed to
+// by the "test" argument to its address.  If the test should be
+// skipped, sets that pointer to NULL.  Returns true, unless the
+// flag is set to an invalid value.
+bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
+                                     const char* file, int line,
+                                     DeathTest** test) {
+  UnitTestImpl* const impl = GetUnitTestImpl();
+  const InternalRunDeathTestFlag* const flag =
+      impl->internal_run_death_test_flag();
+  const int death_test_index = impl->current_test_info()
+      ->increment_death_test_count();
+
+  if (flag != NULL) {
+    if (death_test_index > flag->index()) {
+      DeathTest::set_last_death_test_message(
+          "Death test count (" + StreamableToString(death_test_index)
+          + ") somehow exceeded expected maximum ("
+          + StreamableToString(flag->index()) + ")");
+      return false;
+    }
+
+    if (!(flag->file() == file && flag->line() == line &&
+          flag->index() == death_test_index)) {
+      *test = NULL;
+      return true;
+    }
+  }
+
+# if GTEST_OS_WINDOWS
+
+  if (GTEST_FLAG(death_test_style) == "threadsafe" ||
+      GTEST_FLAG(death_test_style) == "fast") {
+    *test = new WindowsDeathTest(statement, regex, file, line);
+  }
+
+# else
+
+  if (GTEST_FLAG(death_test_style) == "threadsafe") {
+    *test = new ExecDeathTest(statement, regex, file, line);
+  } else if (GTEST_FLAG(death_test_style) == "fast") {
+    *test = new NoExecDeathTest(statement, regex);
+  }
+
+# endif  // GTEST_OS_WINDOWS
+
+  else {  // NOLINT - this is more readable than unbalanced brackets inside #if.
+    DeathTest::set_last_death_test_message(
+        "Unknown death test style \"" + GTEST_FLAG(death_test_style)
+        + "\" encountered");
+    return false;
+  }
+
+  return true;
+}
+
+# if GTEST_OS_WINDOWS
+// Recreates the pipe and event handles from the provided parameters,
+// signals the event, and returns a file descriptor wrapped around the pipe
+// handle. This function is called in the child process only.
+int GetStatusFileDescriptor(unsigned int parent_process_id,
+                            size_t write_handle_as_size_t,
+                            size_t event_handle_as_size_t) {
+  AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE,
+                                                   FALSE,  // Non-inheritable.
+                                                   parent_process_id));
+  if (parent_process_handle.Get() == INVALID_HANDLE_VALUE) {
+    DeathTestAbort("Unable to open parent process " +
+                   StreamableToString(parent_process_id));
+  }
+
+  // TODO(vladl@google.com): Replace the following check with a
+  // compile-time assertion when available.
+  GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t));
+
+  const HANDLE write_handle =
+      reinterpret_cast<HANDLE>(write_handle_as_size_t);
+  HANDLE dup_write_handle;
+
+  // The newly initialized handle is accessible only in in the parent
+  // process. To obtain one accessible within the child, we need to use
+  // DuplicateHandle.
+  if (!::DuplicateHandle(parent_process_handle.Get(), write_handle,
+                         ::GetCurrentProcess(), &dup_write_handle,
+                         0x0,    // Requested privileges ignored since
+                                 // DUPLICATE_SAME_ACCESS is used.
+                         FALSE,  // Request non-inheritable handler.
+                         DUPLICATE_SAME_ACCESS)) {
+    DeathTestAbort("Unable to duplicate the pipe handle " +
+                   StreamableToString(write_handle_as_size_t) +
+                   " from the parent process " +
+                   StreamableToString(parent_process_id));
+  }
+
+  const HANDLE event_handle = reinterpret_cast<HANDLE>(event_handle_as_size_t);
+  HANDLE dup_event_handle;
+
+  if (!::DuplicateHandle(parent_process_handle.Get(), event_handle,
+                         ::GetCurrentProcess(), &dup_event_handle,
+                         0x0,
+                         FALSE,
+                         DUPLICATE_SAME_ACCESS)) {
+    DeathTestAbort("Unable to duplicate the event handle " +
+                   StreamableToString(event_handle_as_size_t) +
+                   " from the parent process " +
+                   StreamableToString(parent_process_id));
+  }
+
+  const int write_fd =
+      ::_open_osfhandle(reinterpret_cast<intptr_t>(dup_write_handle), O_APPEND);
+  if (write_fd == -1) {
+    DeathTestAbort("Unable to convert pipe handle " +
+                   StreamableToString(write_handle_as_size_t) +
+                   " to a file descriptor");
+  }
+
+  // Signals the parent that the write end of the pipe has been acquired
+  // so the parent can release its own write end.
+  ::SetEvent(dup_event_handle);
+
+  return write_fd;
+}
+# endif  // GTEST_OS_WINDOWS
+
+// Returns a newly created InternalRunDeathTestFlag object with fields
+// initialized from the GTEST_FLAG(internal_run_death_test) flag if
+// the flag is specified; otherwise returns NULL.
+InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() {
+  if (GTEST_FLAG(internal_run_death_test) == "") return NULL;
+
+  // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we
+  // can use it here.
+  int line = -1;
+  int index = -1;
+  ::std::vector< ::std::string> fields;
+  SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields);
+  int write_fd = -1;
+
+# if GTEST_OS_WINDOWS
+
+  unsigned int parent_process_id = 0;
+  size_t write_handle_as_size_t = 0;
+  size_t event_handle_as_size_t = 0;
+
+  if (fields.size() != 6
+      || !ParseNaturalNumber(fields[1], &line)
+      || !ParseNaturalNumber(fields[2], &index)
+      || !ParseNaturalNumber(fields[3], &parent_process_id)
+      || !ParseNaturalNumber(fields[4], &write_handle_as_size_t)
+      || !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) {
+    DeathTestAbort("Bad --gtest_internal_run_death_test flag: " +
+                   GTEST_FLAG(internal_run_death_test));
+  }
+  write_fd = GetStatusFileDescriptor(parent_process_id,
+                                     write_handle_as_size_t,
+                                     event_handle_as_size_t);
+# else
+
+  if (fields.size() != 4
+      || !ParseNaturalNumber(fields[1], &line)
+      || !ParseNaturalNumber(fields[2], &index)
+      || !ParseNaturalNumber(fields[3], &write_fd)) {
+    DeathTestAbort("Bad --gtest_internal_run_death_test flag: "
+        + GTEST_FLAG(internal_run_death_test));
+  }
+
+# endif  // GTEST_OS_WINDOWS
+
+  return new InternalRunDeathTestFlag(fields[0], line, index, write_fd);
+}
+
+}  // namespace internal
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+}  // namespace testing
diff --git a/third_party/googletest/googletest/src/gtest-filepath.cc b/third_party/googletest/googletest/src/gtest-filepath.cc
new file mode 100644
index 0000000..0292dc1
--- /dev/null
+++ b/third_party/googletest/googletest/src/gtest-filepath.cc
@@ -0,0 +1,387 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: keith.ray@gmail.com (Keith Ray)
+
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-filepath.h"
+#include "gtest/internal/gtest-port.h"
+
+#include <stdlib.h>
+
+#if GTEST_OS_WINDOWS_MOBILE
+# include <windows.h>
+#elif GTEST_OS_WINDOWS
+# include <direct.h>
+# include <io.h>
+#elif GTEST_OS_SYMBIAN
+// Symbian OpenC has PATH_MAX in sys/syslimits.h
+# include <sys/syslimits.h>
+#else
+# include <limits.h>
+# include <climits>  // Some Linux distributions define PATH_MAX here.
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+#if GTEST_OS_WINDOWS
+# define GTEST_PATH_MAX_ _MAX_PATH
+#elif defined(PATH_MAX)
+# define GTEST_PATH_MAX_ PATH_MAX
+#elif defined(_XOPEN_PATH_MAX)
+# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
+#else
+# define GTEST_PATH_MAX_ _POSIX_PATH_MAX
+#endif  // GTEST_OS_WINDOWS
+
+#include "gtest/internal/gtest-string.h"
+
+namespace testing {
+namespace internal {
+
+#if GTEST_OS_WINDOWS
+// On Windows, '\\' is the standard path separator, but many tools and the
+// Windows API also accept '/' as an alternate path separator. Unless otherwise
+// noted, a file path can contain either kind of path separators, or a mixture
+// of them.
+const char kPathSeparator = '\\';
+const char kAlternatePathSeparator = '/';
+const char kAlternatePathSeparatorString[] = "/";
+# if GTEST_OS_WINDOWS_MOBILE
+// Windows CE doesn't have a current directory. You should not use
+// the current directory in tests on Windows CE, but this at least
+// provides a reasonable fallback.
+const char kCurrentDirectoryString[] = "\\";
+// Windows CE doesn't define INVALID_FILE_ATTRIBUTES
+const DWORD kInvalidFileAttributes = 0xffffffff;
+# else
+const char kCurrentDirectoryString[] = ".\\";
+# endif  // GTEST_OS_WINDOWS_MOBILE
+#else
+const char kPathSeparator = '/';
+const char kCurrentDirectoryString[] = "./";
+#endif  // GTEST_OS_WINDOWS
+
+// Returns whether the given character is a valid path separator.
+static bool IsPathSeparator(char c) {
+#if GTEST_HAS_ALT_PATH_SEP_
+  return (c == kPathSeparator) || (c == kAlternatePathSeparator);
+#else
+  return c == kPathSeparator;
+#endif
+}
+
+// Returns the current working directory, or "" if unsuccessful.
+FilePath FilePath::GetCurrentDir() {
+#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT
+  // Windows CE doesn't have a current directory, so we just return
+  // something reasonable.
+  return FilePath(kCurrentDirectoryString);
+#elif GTEST_OS_WINDOWS
+  char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
+  return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
+#else
+  char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
+  char* result = getcwd(cwd, sizeof(cwd));
+# if GTEST_OS_NACL
+  // getcwd will likely fail in NaCl due to the sandbox, so return something
+  // reasonable. The user may have provided a shim implementation for getcwd,
+  // however, so fallback only when failure is detected.
+  return FilePath(result == NULL ? kCurrentDirectoryString : cwd);
+# endif  // GTEST_OS_NACL
+  return FilePath(result == NULL ? "" : cwd);
+#endif  // GTEST_OS_WINDOWS_MOBILE
+}
+
+// Returns a copy of the FilePath with the case-insensitive extension removed.
+// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
+// FilePath("dir/file"). If a case-insensitive extension is not
+// found, returns a copy of the original FilePath.
+FilePath FilePath::RemoveExtension(const char* extension) const {
+  const std::string dot_extension = std::string(".") + extension;
+  if (String::EndsWithCaseInsensitive(pathname_, dot_extension)) {
+    return FilePath(pathname_.substr(
+        0, pathname_.length() - dot_extension.length()));
+  }
+  return *this;
+}
+
+// Returns a pointer to the last occurence of a valid path separator in
+// the FilePath. On Windows, for example, both '/' and '\' are valid path
+// separators. Returns NULL if no path separator was found.
+const char* FilePath::FindLastPathSeparator() const {
+  const char* const last_sep = strrchr(c_str(), kPathSeparator);
+#if GTEST_HAS_ALT_PATH_SEP_
+  const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator);
+  // Comparing two pointers of which only one is NULL is undefined.
+  if (last_alt_sep != NULL &&
+      (last_sep == NULL || last_alt_sep > last_sep)) {
+    return last_alt_sep;
+  }
+#endif
+  return last_sep;
+}
+
+// Returns a copy of the FilePath with the directory part removed.
+// Example: FilePath("path/to/file").RemoveDirectoryName() returns
+// FilePath("file"). If there is no directory part ("just_a_file"), it returns
+// the FilePath unmodified. If there is no file part ("just_a_dir/") it
+// returns an empty FilePath ("").
+// On Windows platform, '\' is the path separator, otherwise it is '/'.
+FilePath FilePath::RemoveDirectoryName() const {
+  const char* const last_sep = FindLastPathSeparator();
+  return last_sep ? FilePath(last_sep + 1) : *this;
+}
+
+// RemoveFileName returns the directory path with the filename removed.
+// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
+// If the FilePath is "a_file" or "/a_file", RemoveFileName returns
+// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
+// not have a file, like "just/a/dir/", it returns the FilePath unmodified.
+// On Windows platform, '\' is the path separator, otherwise it is '/'.
+FilePath FilePath::RemoveFileName() const {
+  const char* const last_sep = FindLastPathSeparator();
+  std::string dir;
+  if (last_sep) {
+    dir = std::string(c_str(), last_sep + 1 - c_str());
+  } else {
+    dir = kCurrentDirectoryString;
+  }
+  return FilePath(dir);
+}
+
+// Helper functions for naming files in a directory for xml output.
+
+// Given directory = "dir", base_name = "test", number = 0,
+// extension = "xml", returns "dir/test.xml". If number is greater
+// than zero (e.g., 12), returns "dir/test_12.xml".
+// On Windows platform, uses \ as the separator rather than /.
+FilePath FilePath::MakeFileName(const FilePath& directory,
+                                const FilePath& base_name,
+                                int number,
+                                const char* extension) {
+  std::string file;
+  if (number == 0) {
+    file = base_name.string() + "." + extension;
+  } else {
+    file = base_name.string() + "_" + StreamableToString(number)
+        + "." + extension;
+  }
+  return ConcatPaths(directory, FilePath(file));
+}
+
+// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml".
+// On Windows, uses \ as the separator rather than /.
+FilePath FilePath::ConcatPaths(const FilePath& directory,
+                               const FilePath& relative_path) {
+  if (directory.IsEmpty())
+    return relative_path;
+  const FilePath dir(directory.RemoveTrailingPathSeparator());
+  return FilePath(dir.string() + kPathSeparator + relative_path.string());
+}
+
+// Returns true if pathname describes something findable in the file-system,
+// either a file, directory, or whatever.
+bool FilePath::FileOrDirectoryExists() const {
+#if GTEST_OS_WINDOWS_MOBILE
+  LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str());
+  const DWORD attributes = GetFileAttributes(unicode);
+  delete [] unicode;
+  return attributes != kInvalidFileAttributes;
+#else
+  posix::StatStruct file_stat;
+  return posix::Stat(pathname_.c_str(), &file_stat) == 0;
+#endif  // GTEST_OS_WINDOWS_MOBILE
+}
+
+// Returns true if pathname describes a directory in the file-system
+// that exists.
+bool FilePath::DirectoryExists() const {
+  bool result = false;
+#if GTEST_OS_WINDOWS
+  // Don't strip off trailing separator if path is a root directory on
+  // Windows (like "C:\\").
+  const FilePath& path(IsRootDirectory() ? *this :
+                                           RemoveTrailingPathSeparator());
+#else
+  const FilePath& path(*this);
+#endif
+
+#if GTEST_OS_WINDOWS_MOBILE
+  LPCWSTR unicode = String::AnsiToUtf16(path.c_str());
+  const DWORD attributes = GetFileAttributes(unicode);
+  delete [] unicode;
+  if ((attributes != kInvalidFileAttributes) &&
+      (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
+    result = true;
+  }
+#else
+  posix::StatStruct file_stat;
+  result = posix::Stat(path.c_str(), &file_stat) == 0 &&
+      posix::IsDir(file_stat);
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+  return result;
+}
+
+// Returns true if pathname describes a root directory. (Windows has one
+// root directory per disk drive.)
+bool FilePath::IsRootDirectory() const {
+#if GTEST_OS_WINDOWS
+  // TODO(wan@google.com): on Windows a network share like
+  // \\server\share can be a root directory, although it cannot be the
+  // current directory.  Handle this properly.
+  return pathname_.length() == 3 && IsAbsolutePath();
+#else
+  return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]);
+#endif
+}
+
+// Returns true if pathname describes an absolute path.
+bool FilePath::IsAbsolutePath() const {
+  const char* const name = pathname_.c_str();
+#if GTEST_OS_WINDOWS
+  return pathname_.length() >= 3 &&
+     ((name[0] >= 'a' && name[0] <= 'z') ||
+      (name[0] >= 'A' && name[0] <= 'Z')) &&
+     name[1] == ':' &&
+     IsPathSeparator(name[2]);
+#else
+  return IsPathSeparator(name[0]);
+#endif
+}
+
+// Returns a pathname for a file that does not currently exist. The pathname
+// will be directory/base_name.extension or
+// directory/base_name_<number>.extension if directory/base_name.extension
+// already exists. The number will be incremented until a pathname is found
+// that does not already exist.
+// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
+// There could be a race condition if two or more processes are calling this
+// function at the same time -- they could both pick the same filename.
+FilePath FilePath::GenerateUniqueFileName(const FilePath& directory,
+                                          const FilePath& base_name,
+                                          const char* extension) {
+  FilePath full_pathname;
+  int number = 0;
+  do {
+    full_pathname.Set(MakeFileName(directory, base_name, number++, extension));
+  } while (full_pathname.FileOrDirectoryExists());
+  return full_pathname;
+}
+
+// Returns true if FilePath ends with a path separator, which indicates that
+// it is intended to represent a directory. Returns false otherwise.
+// This does NOT check that a directory (or file) actually exists.
+bool FilePath::IsDirectory() const {
+  return !pathname_.empty() &&
+         IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]);
+}
+
+// Create directories so that path exists. Returns true if successful or if
+// the directories already exist; returns false if unable to create directories
+// for any reason.
+bool FilePath::CreateDirectoriesRecursively() const {
+  if (!this->IsDirectory()) {
+    return false;
+  }
+
+  if (pathname_.length() == 0 || this->DirectoryExists()) {
+    return true;
+  }
+
+  const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName());
+  return parent.CreateDirectoriesRecursively() && this->CreateFolder();
+}
+
+// Create the directory so that path exists. Returns true if successful or
+// if the directory already exists; returns false if unable to create the
+// directory for any reason, including if the parent directory does not
+// exist. Not named "CreateDirectory" because that's a macro on Windows.
+bool FilePath::CreateFolder() const {
+#if GTEST_OS_WINDOWS_MOBILE
+  FilePath removed_sep(this->RemoveTrailingPathSeparator());
+  LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
+  int result = CreateDirectory(unicode, NULL) ? 0 : -1;
+  delete [] unicode;
+#elif GTEST_OS_WINDOWS
+  int result = _mkdir(pathname_.c_str());
+#else
+  int result = mkdir(pathname_.c_str(), 0777);
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+  if (result == -1) {
+    return this->DirectoryExists();  // An error is OK if the directory exists.
+  }
+  return true;  // No error.
+}
+
+// If input name has a trailing separator character, remove it and return the
+// name, otherwise return the name string unmodified.
+// On Windows platform, uses \ as the separator, other platforms use /.
+FilePath FilePath::RemoveTrailingPathSeparator() const {
+  return IsDirectory()
+      ? FilePath(pathname_.substr(0, pathname_.length() - 1))
+      : *this;
+}
+
+// Removes any redundant separators that might be in the pathname.
+// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
+// redundancies that might be in a pathname involving "." or "..".
+// TODO(wan@google.com): handle Windows network shares (e.g. \\server\share).
+void FilePath::Normalize() {
+  if (pathname_.c_str() == NULL) {
+    pathname_ = "";
+    return;
+  }
+  const char* src = pathname_.c_str();
+  char* const dest = new char[pathname_.length() + 1];
+  char* dest_ptr = dest;
+  memset(dest_ptr, 0, pathname_.length() + 1);
+
+  while (*src != '\0') {
+    *dest_ptr = *src;
+    if (!IsPathSeparator(*src)) {
+      src++;
+    } else {
+#if GTEST_HAS_ALT_PATH_SEP_
+      if (*dest_ptr == kAlternatePathSeparator) {
+        *dest_ptr = kPathSeparator;
+      }
+#endif
+      while (IsPathSeparator(*src))
+        src++;
+    }
+    dest_ptr++;
+  }
+  *dest_ptr = '\0';
+  pathname_ = dest;
+  delete[] dest;
+}
+
+}  // namespace internal
+}  // namespace testing
diff --git a/third_party/googletest/googletest/src/gtest-internal-inl.h b/third_party/googletest/googletest/src/gtest-internal-inl.h
new file mode 100644
index 0000000..56c8a20
--- /dev/null
+++ b/third_party/googletest/googletest/src/gtest-internal-inl.h
@@ -0,0 +1,1183 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Utility functions and classes used by the Google C++ testing framework.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// This file contains purely Google Test's internal implementation.  Please
+// DO NOT #INCLUDE IT IN A USER PROGRAM.
+
+#ifndef GTEST_SRC_GTEST_INTERNAL_INL_H_
+#define GTEST_SRC_GTEST_INTERNAL_INL_H_
+
+// GTEST_IMPLEMENTATION_ is defined to 1 iff the current translation unit is
+// part of Google Test's implementation; otherwise it's undefined.
+#if !GTEST_IMPLEMENTATION_
+// If this file is included from the user's code, just say no.
+# error "gtest-internal-inl.h is part of Google Test's internal implementation."
+# error "It must not be included except by Google Test itself."
+#endif  // GTEST_IMPLEMENTATION_
+
+#ifndef _WIN32_WCE
+# include <errno.h>
+#endif  // !_WIN32_WCE
+#include <stddef.h>
+#include <stdlib.h>  // For strtoll/_strtoul64/malloc/free.
+#include <string.h>  // For memmove.
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_CAN_STREAM_RESULTS_
+# include <arpa/inet.h>  // NOLINT
+# include <netdb.h>  // NOLINT
+#endif
+
+#if GTEST_OS_WINDOWS
+# include <windows.h>  // NOLINT
+#endif  // GTEST_OS_WINDOWS
+
+#include "gtest/gtest.h"  // NOLINT
+#include "gtest/gtest-spi.h"
+
+namespace testing {
+
+// Declares the flags.
+//
+// We don't want the users to modify this flag in the code, but want
+// Google Test's own unit tests to be able to access it. Therefore we
+// declare it here as opposed to in gtest.h.
+GTEST_DECLARE_bool_(death_test_use_fork);
+
+namespace internal {
+
+// The value of GetTestTypeId() as seen from within the Google Test
+// library.  This is solely for testing GetTestTypeId().
+GTEST_API_ extern const TypeId kTestTypeIdInGoogleTest;
+
+// Names of the flags (needed for parsing Google Test flags).
+const char kAlsoRunDisabledTestsFlag[] = "also_run_disabled_tests";
+const char kBreakOnFailureFlag[] = "break_on_failure";
+const char kCatchExceptionsFlag[] = "catch_exceptions";
+const char kColorFlag[] = "color";
+const char kFilterFlag[] = "filter";
+const char kListTestsFlag[] = "list_tests";
+const char kOutputFlag[] = "output";
+const char kPrintTimeFlag[] = "print_time";
+const char kRandomSeedFlag[] = "random_seed";
+const char kRepeatFlag[] = "repeat";
+const char kShuffleFlag[] = "shuffle";
+const char kStackTraceDepthFlag[] = "stack_trace_depth";
+const char kStreamResultToFlag[] = "stream_result_to";
+const char kThrowOnFailureFlag[] = "throw_on_failure";
+const char kFlagfileFlag[] = "flagfile";
+
+// A valid random seed must be in [1, kMaxRandomSeed].
+const int kMaxRandomSeed = 99999;
+
+// g_help_flag is true iff the --help flag or an equivalent form is
+// specified on the command line.
+GTEST_API_ extern bool g_help_flag;
+
+// Returns the current time in milliseconds.
+GTEST_API_ TimeInMillis GetTimeInMillis();
+
+// Returns true iff Google Test should use colors in the output.
+GTEST_API_ bool ShouldUseColor(bool stdout_is_tty);
+
+// Formats the given time in milliseconds as seconds.
+GTEST_API_ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms);
+
+// Converts the given time in milliseconds to a date string in the ISO 8601
+// format, without the timezone information.  N.B.: due to the use the
+// non-reentrant localtime() function, this function is not thread safe.  Do
+// not use it in any code that can be called from multiple threads.
+GTEST_API_ std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms);
+
+// Parses a string for an Int32 flag, in the form of "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+GTEST_API_ bool ParseInt32Flag(
+    const char* str, const char* flag, Int32* value);
+
+// Returns a random seed in range [1, kMaxRandomSeed] based on the
+// given --gtest_random_seed flag value.
+inline int GetRandomSeedFromFlag(Int32 random_seed_flag) {
+  const unsigned int raw_seed = (random_seed_flag == 0) ?
+      static_cast<unsigned int>(GetTimeInMillis()) :
+      static_cast<unsigned int>(random_seed_flag);
+
+  // Normalizes the actual seed to range [1, kMaxRandomSeed] such that
+  // it's easy to type.
+  const int normalized_seed =
+      static_cast<int>((raw_seed - 1U) %
+                       static_cast<unsigned int>(kMaxRandomSeed)) + 1;
+  return normalized_seed;
+}
+
+// Returns the first valid random seed after 'seed'.  The behavior is
+// undefined if 'seed' is invalid.  The seed after kMaxRandomSeed is
+// considered to be 1.
+inline int GetNextRandomSeed(int seed) {
+  GTEST_CHECK_(1 <= seed && seed <= kMaxRandomSeed)
+      << "Invalid random seed " << seed << " - must be in [1, "
+      << kMaxRandomSeed << "].";
+  const int next_seed = seed + 1;
+  return (next_seed > kMaxRandomSeed) ? 1 : next_seed;
+}
+
+// This class saves the values of all Google Test flags in its c'tor, and
+// restores them in its d'tor.
+class GTestFlagSaver {
+ public:
+  // The c'tor.
+  GTestFlagSaver() {
+    also_run_disabled_tests_ = GTEST_FLAG(also_run_disabled_tests);
+    break_on_failure_ = GTEST_FLAG(break_on_failure);
+    catch_exceptions_ = GTEST_FLAG(catch_exceptions);
+    color_ = GTEST_FLAG(color);
+    death_test_style_ = GTEST_FLAG(death_test_style);
+    death_test_use_fork_ = GTEST_FLAG(death_test_use_fork);
+    filter_ = GTEST_FLAG(filter);
+    internal_run_death_test_ = GTEST_FLAG(internal_run_death_test);
+    list_tests_ = GTEST_FLAG(list_tests);
+    output_ = GTEST_FLAG(output);
+    print_time_ = GTEST_FLAG(print_time);
+    random_seed_ = GTEST_FLAG(random_seed);
+    repeat_ = GTEST_FLAG(repeat);
+    shuffle_ = GTEST_FLAG(shuffle);
+    stack_trace_depth_ = GTEST_FLAG(stack_trace_depth);
+    stream_result_to_ = GTEST_FLAG(stream_result_to);
+    throw_on_failure_ = GTEST_FLAG(throw_on_failure);
+  }
+
+  // The d'tor is not virtual.  DO NOT INHERIT FROM THIS CLASS.
+  ~GTestFlagSaver() {
+    GTEST_FLAG(also_run_disabled_tests) = also_run_disabled_tests_;
+    GTEST_FLAG(break_on_failure) = break_on_failure_;
+    GTEST_FLAG(catch_exceptions) = catch_exceptions_;
+    GTEST_FLAG(color) = color_;
+    GTEST_FLAG(death_test_style) = death_test_style_;
+    GTEST_FLAG(death_test_use_fork) = death_test_use_fork_;
+    GTEST_FLAG(filter) = filter_;
+    GTEST_FLAG(internal_run_death_test) = internal_run_death_test_;
+    GTEST_FLAG(list_tests) = list_tests_;
+    GTEST_FLAG(output) = output_;
+    GTEST_FLAG(print_time) = print_time_;
+    GTEST_FLAG(random_seed) = random_seed_;
+    GTEST_FLAG(repeat) = repeat_;
+    GTEST_FLAG(shuffle) = shuffle_;
+    GTEST_FLAG(stack_trace_depth) = stack_trace_depth_;
+    GTEST_FLAG(stream_result_to) = stream_result_to_;
+    GTEST_FLAG(throw_on_failure) = throw_on_failure_;
+  }
+
+ private:
+  // Fields for saving the original values of flags.
+  bool also_run_disabled_tests_;
+  bool break_on_failure_;
+  bool catch_exceptions_;
+  std::string color_;
+  std::string death_test_style_;
+  bool death_test_use_fork_;
+  std::string filter_;
+  std::string internal_run_death_test_;
+  bool list_tests_;
+  std::string output_;
+  bool print_time_;
+  internal::Int32 random_seed_;
+  internal::Int32 repeat_;
+  bool shuffle_;
+  internal::Int32 stack_trace_depth_;
+  std::string stream_result_to_;
+  bool throw_on_failure_;
+} GTEST_ATTRIBUTE_UNUSED_;
+
+// Converts a Unicode code point to a narrow string in UTF-8 encoding.
+// code_point parameter is of type UInt32 because wchar_t may not be
+// wide enough to contain a code point.
+// If the code_point is not a valid Unicode code point
+// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted
+// to "(Invalid Unicode 0xXXXXXXXX)".
+GTEST_API_ std::string CodePointToUtf8(UInt32 code_point);
+
+// Converts a wide string to a narrow string in UTF-8 encoding.
+// The wide string is assumed to have the following encoding:
+//   UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS)
+//   UTF-32 if sizeof(wchar_t) == 4 (on Linux)
+// Parameter str points to a null-terminated wide string.
+// Parameter num_chars may additionally limit the number
+// of wchar_t characters processed. -1 is used when the entire string
+// should be processed.
+// If the string contains code points that are not valid Unicode code points
+// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding
+// and contains invalid UTF-16 surrogate pairs, values in those pairs
+// will be encoded as individual Unicode characters from Basic Normal Plane.
+GTEST_API_ std::string WideStringToUtf8(const wchar_t* str, int num_chars);
+
+// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
+// if the variable is present. If a file already exists at this location, this
+// function will write over it. If the variable is present, but the file cannot
+// be created, prints an error and exits.
+void WriteToShardStatusFileIfNeeded();
+
+// Checks whether sharding is enabled by examining the relevant
+// environment variable values. If the variables are present,
+// but inconsistent (e.g., shard_index >= total_shards), prints
+// an error and exits. If in_subprocess_for_death_test, sharding is
+// disabled because it must only be applied to the original test
+// process. Otherwise, we could filter out death tests we intended to execute.
+GTEST_API_ bool ShouldShard(const char* total_shards_str,
+                            const char* shard_index_str,
+                            bool in_subprocess_for_death_test);
+
+// Parses the environment variable var as an Int32. If it is unset,
+// returns default_val. If it is not an Int32, prints an error and
+// and aborts.
+GTEST_API_ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val);
+
+// Given the total number of shards, the shard index, and the test id,
+// returns true iff the test should be run on this shard. The test id is
+// some arbitrary but unique non-negative integer assigned to each test
+// method. Assumes that 0 <= shard_index < total_shards.
+GTEST_API_ bool ShouldRunTestOnShard(
+    int total_shards, int shard_index, int test_id);
+
+// STL container utilities.
+
+// Returns the number of elements in the given container that satisfy
+// the given predicate.
+template <class Container, typename Predicate>
+inline int CountIf(const Container& c, Predicate predicate) {
+  // Implemented as an explicit loop since std::count_if() in libCstd on
+  // Solaris has a non-standard signature.
+  int count = 0;
+  for (typename Container::const_iterator it = c.begin(); it != c.end(); ++it) {
+    if (predicate(*it))
+      ++count;
+  }
+  return count;
+}
+
+// Applies a function/functor to each element in the container.
+template <class Container, typename Functor>
+void ForEach(const Container& c, Functor functor) {
+  std::for_each(c.begin(), c.end(), functor);
+}
+
+// Returns the i-th element of the vector, or default_value if i is not
+// in range [0, v.size()).
+template <typename E>
+inline E GetElementOr(const std::vector<E>& v, int i, E default_value) {
+  return (i < 0 || i >= static_cast<int>(v.size())) ? default_value : v[i];
+}
+
+// Performs an in-place shuffle of a range of the vector's elements.
+// 'begin' and 'end' are element indices as an STL-style range;
+// i.e. [begin, end) are shuffled, where 'end' == size() means to
+// shuffle to the end of the vector.
+template <typename E>
+void ShuffleRange(internal::Random* random, int begin, int end,
+                  std::vector<E>* v) {
+  const int size = static_cast<int>(v->size());
+  GTEST_CHECK_(0 <= begin && begin <= size)
+      << "Invalid shuffle range start " << begin << ": must be in range [0, "
+      << size << "].";
+  GTEST_CHECK_(begin <= end && end <= size)
+      << "Invalid shuffle range finish " << end << ": must be in range ["
+      << begin << ", " << size << "].";
+
+  // Fisher-Yates shuffle, from
+  // http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
+  for (int range_width = end - begin; range_width >= 2; range_width--) {
+    const int last_in_range = begin + range_width - 1;
+    const int selected = begin + random->Generate(range_width);
+    std::swap((*v)[selected], (*v)[last_in_range]);
+  }
+}
+
+// Performs an in-place shuffle of the vector's elements.
+template <typename E>
+inline void Shuffle(internal::Random* random, std::vector<E>* v) {
+  ShuffleRange(random, 0, static_cast<int>(v->size()), v);
+}
+
+// A function for deleting an object.  Handy for being used as a
+// functor.
+template <typename T>
+static void Delete(T* x) {
+  delete x;
+}
+
+// A predicate that checks the key of a TestProperty against a known key.
+//
+// TestPropertyKeyIs is copyable.
+class TestPropertyKeyIs {
+ public:
+  // Constructor.
+  //
+  // TestPropertyKeyIs has NO default constructor.
+  explicit TestPropertyKeyIs(const std::string& key) : key_(key) {}
+
+  // Returns true iff the test name of test property matches on key_.
+  bool operator()(const TestProperty& test_property) const {
+    return test_property.key() == key_;
+  }
+
+ private:
+  std::string key_;
+};
+
+// Class UnitTestOptions.
+//
+// This class contains functions for processing options the user
+// specifies when running the tests.  It has only static members.
+//
+// In most cases, the user can specify an option using either an
+// environment variable or a command line flag.  E.g. you can set the
+// test filter using either GTEST_FILTER or --gtest_filter.  If both
+// the variable and the flag are present, the latter overrides the
+// former.
+class GTEST_API_ UnitTestOptions {
+ public:
+  // Functions for processing the gtest_output flag.
+
+  // Returns the output format, or "" for normal printed output.
+  static std::string GetOutputFormat();
+
+  // Returns the absolute path of the requested output file, or the
+  // default (test_detail.xml in the original working directory) if
+  // none was explicitly specified.
+  static std::string GetAbsolutePathToOutputFile();
+
+  // Functions for processing the gtest_filter flag.
+
+  // Returns true iff the wildcard pattern matches the string.  The
+  // first ':' or '\0' character in pattern marks the end of it.
+  //
+  // This recursive algorithm isn't very efficient, but is clear and
+  // works well enough for matching test names, which are short.
+  static bool PatternMatchesString(const char *pattern, const char *str);
+
+  // Returns true iff the user-specified filter matches the test case
+  // name and the test name.
+  static bool FilterMatchesTest(const std::string &test_case_name,
+                                const std::string &test_name);
+
+#if GTEST_OS_WINDOWS
+  // Function for supporting the gtest_catch_exception flag.
+
+  // Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
+  // given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
+  // This function is useful as an __except condition.
+  static int GTestShouldProcessSEH(DWORD exception_code);
+#endif  // GTEST_OS_WINDOWS
+
+  // Returns true if "name" matches the ':' separated list of glob-style
+  // filters in "filter".
+  static bool MatchesFilter(const std::string& name, const char* filter);
+};
+
+// Returns the current application's name, removing directory path if that
+// is present.  Used by UnitTestOptions::GetOutputFile.
+GTEST_API_ FilePath GetCurrentExecutableName();
+
+// The role interface for getting the OS stack trace as a string.
+class OsStackTraceGetterInterface {
+ public:
+  OsStackTraceGetterInterface() {}
+  virtual ~OsStackTraceGetterInterface() {}
+
+  // Returns the current OS stack trace as an std::string.  Parameters:
+  //
+  //   max_depth  - the maximum number of stack frames to be included
+  //                in the trace.
+  //   skip_count - the number of top frames to be skipped; doesn't count
+  //                against max_depth.
+  virtual string CurrentStackTrace(int max_depth, int skip_count) = 0;
+
+  // UponLeavingGTest() should be called immediately before Google Test calls
+  // user code. It saves some information about the current stack that
+  // CurrentStackTrace() will use to find and hide Google Test stack frames.
+  virtual void UponLeavingGTest() = 0;
+
+  // This string is inserted in place of stack frames that are part of
+  // Google Test's implementation.
+  static const char* const kElidedFramesMarker;
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetterInterface);
+};
+
+// A working implementation of the OsStackTraceGetterInterface interface.
+class OsStackTraceGetter : public OsStackTraceGetterInterface {
+ public:
+  OsStackTraceGetter() {}
+
+  virtual string CurrentStackTrace(int max_depth, int skip_count);
+  virtual void UponLeavingGTest();
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetter);
+};
+
+// Information about a Google Test trace point.
+struct TraceInfo {
+  const char* file;
+  int line;
+  std::string message;
+};
+
+// This is the default global test part result reporter used in UnitTestImpl.
+// This class should only be used by UnitTestImpl.
+class DefaultGlobalTestPartResultReporter
+  : public TestPartResultReporterInterface {
+ public:
+  explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test);
+  // Implements the TestPartResultReporterInterface. Reports the test part
+  // result in the current test.
+  virtual void ReportTestPartResult(const TestPartResult& result);
+
+ private:
+  UnitTestImpl* const unit_test_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultGlobalTestPartResultReporter);
+};
+
+// This is the default per thread test part result reporter used in
+// UnitTestImpl. This class should only be used by UnitTestImpl.
+class DefaultPerThreadTestPartResultReporter
+    : public TestPartResultReporterInterface {
+ public:
+  explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test);
+  // Implements the TestPartResultReporterInterface. The implementation just
+  // delegates to the current global test part result reporter of *unit_test_.
+  virtual void ReportTestPartResult(const TestPartResult& result);
+
+ private:
+  UnitTestImpl* const unit_test_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultPerThreadTestPartResultReporter);
+};
+
+// The private implementation of the UnitTest class.  We don't protect
+// the methods under a mutex, as this class is not accessible by a
+// user and the UnitTest class that delegates work to this class does
+// proper locking.
+class GTEST_API_ UnitTestImpl {
+ public:
+  explicit UnitTestImpl(UnitTest* parent);
+  virtual ~UnitTestImpl();
+
+  // There are two different ways to register your own TestPartResultReporter.
+  // You can register your own repoter to listen either only for test results
+  // from the current thread or for results from all threads.
+  // By default, each per-thread test result repoter just passes a new
+  // TestPartResult to the global test result reporter, which registers the
+  // test part result for the currently running test.
+
+  // Returns the global test part result reporter.
+  TestPartResultReporterInterface* GetGlobalTestPartResultReporter();
+
+  // Sets the global test part result reporter.
+  void SetGlobalTestPartResultReporter(
+      TestPartResultReporterInterface* reporter);
+
+  // Returns the test part result reporter for the current thread.
+  TestPartResultReporterInterface* GetTestPartResultReporterForCurrentThread();
+
+  // Sets the test part result reporter for the current thread.
+  void SetTestPartResultReporterForCurrentThread(
+      TestPartResultReporterInterface* reporter);
+
+  // Gets the number of successful test cases.
+  int successful_test_case_count() const;
+
+  // Gets the number of failed test cases.
+  int failed_test_case_count() const;
+
+  // Gets the number of all test cases.
+  int total_test_case_count() const;
+
+  // Gets the number of all test cases that contain at least one test
+  // that should run.
+  int test_case_to_run_count() const;
+
+  // Gets the number of successful tests.
+  int successful_test_count() const;
+
+  // Gets the number of failed tests.
+  int failed_test_count() const;
+
+  // Gets the number of disabled tests that will be reported in the XML report.
+  int reportable_disabled_test_count() const;
+
+  // Gets the number of disabled tests.
+  int disabled_test_count() const;
+
+  // Gets the number of tests to be printed in the XML report.
+  int reportable_test_count() const;
+
+  // Gets the number of all tests.
+  int total_test_count() const;
+
+  // Gets the number of tests that should run.
+  int test_to_run_count() const;
+
+  // Gets the time of the test program start, in ms from the start of the
+  // UNIX epoch.
+  TimeInMillis start_timestamp() const { return start_timestamp_; }
+
+  // Gets the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+  // Returns true iff the unit test passed (i.e. all test cases passed).
+  bool Passed() const { return !Failed(); }
+
+  // Returns true iff the unit test failed (i.e. some test case failed
+  // or something outside of all tests failed).
+  bool Failed() const {
+    return failed_test_case_count() > 0 || ad_hoc_test_result()->Failed();
+  }
+
+  // Gets the i-th test case among all the test cases. i can range from 0 to
+  // total_test_case_count() - 1. If i is not in that range, returns NULL.
+  const TestCase* GetTestCase(int i) const {
+    const int index = GetElementOr(test_case_indices_, i, -1);
+    return index < 0 ? NULL : test_cases_[i];
+  }
+
+  // Gets the i-th test case among all the test cases. i can range from 0 to
+  // total_test_case_count() - 1. If i is not in that range, returns NULL.
+  TestCase* GetMutableTestCase(int i) {
+    const int index = GetElementOr(test_case_indices_, i, -1);
+    return index < 0 ? NULL : test_cases_[index];
+  }
+
+  // Provides access to the event listener list.
+  TestEventListeners* listeners() { return &listeners_; }
+
+  // Returns the TestResult for the test that's currently running, or
+  // the TestResult for the ad hoc test if no test is running.
+  TestResult* current_test_result();
+
+  // Returns the TestResult for the ad hoc test.
+  const TestResult* ad_hoc_test_result() const { return &ad_hoc_test_result_; }
+
+  // Sets the OS stack trace getter.
+  //
+  // Does nothing if the input and the current OS stack trace getter
+  // are the same; otherwise, deletes the old getter and makes the
+  // input the current getter.
+  void set_os_stack_trace_getter(OsStackTraceGetterInterface* getter);
+
+  // Returns the current OS stack trace getter if it is not NULL;
+  // otherwise, creates an OsStackTraceGetter, makes it the current
+  // getter, and returns it.
+  OsStackTraceGetterInterface* os_stack_trace_getter();
+
+  // Returns the current OS stack trace as an std::string.
+  //
+  // The maximum number of stack frames to be included is specified by
+  // the gtest_stack_trace_depth flag.  The skip_count parameter
+  // specifies the number of top frames to be skipped, which doesn't
+  // count against the number of frames to be included.
+  //
+  // For example, if Foo() calls Bar(), which in turn calls
+  // CurrentOsStackTraceExceptTop(1), Foo() will be included in the
+  // trace but Bar() and CurrentOsStackTraceExceptTop() won't.
+  std::string CurrentOsStackTraceExceptTop(int skip_count) GTEST_NO_INLINE_;
+
+  // Finds and returns a TestCase with the given name.  If one doesn't
+  // exist, creates one and returns it.
+  //
+  // Arguments:
+  //
+  //   test_case_name: name of the test case
+  //   type_param:     the name of the test's type parameter, or NULL if
+  //                   this is not a typed or a type-parameterized test.
+  //   set_up_tc:      pointer to the function that sets up the test case
+  //   tear_down_tc:   pointer to the function that tears down the test case
+  TestCase* GetTestCase(const char* test_case_name,
+                        const char* type_param,
+                        Test::SetUpTestCaseFunc set_up_tc,
+                        Test::TearDownTestCaseFunc tear_down_tc);
+
+  // Adds a TestInfo to the unit test.
+  //
+  // Arguments:
+  //
+  //   set_up_tc:    pointer to the function that sets up the test case
+  //   tear_down_tc: pointer to the function that tears down the test case
+  //   test_info:    the TestInfo object
+  void AddTestInfo(Test::SetUpTestCaseFunc set_up_tc,
+                   Test::TearDownTestCaseFunc tear_down_tc,
+                   TestInfo* test_info) {
+    // In order to support thread-safe death tests, we need to
+    // remember the original working directory when the test program
+    // was first invoked.  We cannot do this in RUN_ALL_TESTS(), as
+    // the user may have changed the current directory before calling
+    // RUN_ALL_TESTS().  Therefore we capture the current directory in
+    // AddTestInfo(), which is called to register a TEST or TEST_F
+    // before main() is reached.
+    if (original_working_dir_.IsEmpty()) {
+      original_working_dir_.Set(FilePath::GetCurrentDir());
+      GTEST_CHECK_(!original_working_dir_.IsEmpty())
+          << "Failed to get the current working directory.";
+    }
+
+    GetTestCase(test_info->test_case_name(),
+                test_info->type_param(),
+                set_up_tc,
+                tear_down_tc)->AddTestInfo(test_info);
+  }
+
+#if GTEST_HAS_PARAM_TEST
+  // Returns ParameterizedTestCaseRegistry object used to keep track of
+  // value-parameterized tests and instantiate and register them.
+  internal::ParameterizedTestCaseRegistry& parameterized_test_registry() {
+    return parameterized_test_registry_;
+  }
+#endif  // GTEST_HAS_PARAM_TEST
+
+  // Sets the TestCase object for the test that's currently running.
+  void set_current_test_case(TestCase* a_current_test_case) {
+    current_test_case_ = a_current_test_case;
+  }
+
+  // Sets the TestInfo object for the test that's currently running.  If
+  // current_test_info is NULL, the assertion results will be stored in
+  // ad_hoc_test_result_.
+  void set_current_test_info(TestInfo* a_current_test_info) {
+    current_test_info_ = a_current_test_info;
+  }
+
+  // Registers all parameterized tests defined using TEST_P and
+  // INSTANTIATE_TEST_CASE_P, creating regular tests for each test/parameter
+  // combination. This method can be called more then once; it has guards
+  // protecting from registering the tests more then once.  If
+  // value-parameterized tests are disabled, RegisterParameterizedTests is
+  // present but does nothing.
+  void RegisterParameterizedTests();
+
+  // Runs all tests in this UnitTest object, prints the result, and
+  // returns true if all tests are successful.  If any exception is
+  // thrown during a test, this test is considered to be failed, but
+  // the rest of the tests will still be run.
+  bool RunAllTests();
+
+  // Clears the results of all tests, except the ad hoc tests.
+  void ClearNonAdHocTestResult() {
+    ForEach(test_cases_, TestCase::ClearTestCaseResult);
+  }
+
+  // Clears the results of ad-hoc test assertions.
+  void ClearAdHocTestResult() {
+    ad_hoc_test_result_.Clear();
+  }
+
+  // Adds a TestProperty to the current TestResult object when invoked in a
+  // context of a test or a test case, or to the global property set. If the
+  // result already contains a property with the same key, the value will be
+  // updated.
+  void RecordProperty(const TestProperty& test_property);
+
+  enum ReactionToSharding {
+    HONOR_SHARDING_PROTOCOL,
+    IGNORE_SHARDING_PROTOCOL
+  };
+
+  // Matches the full name of each test against the user-specified
+  // filter to decide whether the test should run, then records the
+  // result in each TestCase and TestInfo object.
+  // If shard_tests == HONOR_SHARDING_PROTOCOL, further filters tests
+  // based on sharding variables in the environment.
+  // Returns the number of tests that should run.
+  int FilterTests(ReactionToSharding shard_tests);
+
+  // Prints the names of the tests matching the user-specified filter flag.
+  void ListTestsMatchingFilter();
+
+  const TestCase* current_test_case() const { return current_test_case_; }
+  TestInfo* current_test_info() { return current_test_info_; }
+  const TestInfo* current_test_info() const { return current_test_info_; }
+
+  // Returns the vector of environments that need to be set-up/torn-down
+  // before/after the tests are run.
+  std::vector<Environment*>& environments() { return environments_; }
+
+  // Getters for the per-thread Google Test trace stack.
+  std::vector<TraceInfo>& gtest_trace_stack() {
+    return *(gtest_trace_stack_.pointer());
+  }
+  const std::vector<TraceInfo>& gtest_trace_stack() const {
+    return gtest_trace_stack_.get();
+  }
+
+#if GTEST_HAS_DEATH_TEST
+  void InitDeathTestSubprocessControlInfo() {
+    internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag());
+  }
+  // Returns a pointer to the parsed --gtest_internal_run_death_test
+  // flag, or NULL if that flag was not specified.
+  // This information is useful only in a death test child process.
+  // Must not be called before a call to InitGoogleTest.
+  const InternalRunDeathTestFlag* internal_run_death_test_flag() const {
+    return internal_run_death_test_flag_.get();
+  }
+
+  // Returns a pointer to the current death test factory.
+  internal::DeathTestFactory* death_test_factory() {
+    return death_test_factory_.get();
+  }
+
+  void SuppressTestEventsIfInSubprocess();
+
+  friend class ReplaceDeathTestFactory;
+#endif  // GTEST_HAS_DEATH_TEST
+
+  // Initializes the event listener performing XML output as specified by
+  // UnitTestOptions. Must not be called before InitGoogleTest.
+  void ConfigureXmlOutput();
+
+#if GTEST_CAN_STREAM_RESULTS_
+  // Initializes the event listener for streaming test results to a socket.
+  // Must not be called before InitGoogleTest.
+  void ConfigureStreamingOutput();
+#endif
+
+  // Performs initialization dependent upon flag values obtained in
+  // ParseGoogleTestFlagsOnly.  Is called from InitGoogleTest after the call to
+  // ParseGoogleTestFlagsOnly.  In case a user neglects to call InitGoogleTest
+  // this function is also called from RunAllTests.  Since this function can be
+  // called more than once, it has to be idempotent.
+  void PostFlagParsingInit();
+
+  // Gets the random seed used at the start of the current test iteration.
+  int random_seed() const { return random_seed_; }
+
+  // Gets the random number generator.
+  internal::Random* random() { return &random_; }
+
+  // Shuffles all test cases, and the tests within each test case,
+  // making sure that death tests are still run first.
+  void ShuffleTests();
+
+  // Restores the test cases and tests to their order before the first shuffle.
+  void UnshuffleTests();
+
+  // Returns the value of GTEST_FLAG(catch_exceptions) at the moment
+  // UnitTest::Run() starts.
+  bool catch_exceptions() const { return catch_exceptions_; }
+
+ private:
+  friend class ::testing::UnitTest;
+
+  // Used by UnitTest::Run() to capture the state of
+  // GTEST_FLAG(catch_exceptions) at the moment it starts.
+  void set_catch_exceptions(bool value) { catch_exceptions_ = value; }
+
+  // The UnitTest object that owns this implementation object.
+  UnitTest* const parent_;
+
+  // The working directory when the first TEST() or TEST_F() was
+  // executed.
+  internal::FilePath original_working_dir_;
+
+  // The default test part result reporters.
+  DefaultGlobalTestPartResultReporter default_global_test_part_result_reporter_;
+  DefaultPerThreadTestPartResultReporter
+      default_per_thread_test_part_result_reporter_;
+
+  // Points to (but doesn't own) the global test part result reporter.
+  TestPartResultReporterInterface* global_test_part_result_repoter_;
+
+  // Protects read and write access to global_test_part_result_reporter_.
+  internal::Mutex global_test_part_result_reporter_mutex_;
+
+  // Points to (but doesn't own) the per-thread test part result reporter.
+  internal::ThreadLocal<TestPartResultReporterInterface*>
+      per_thread_test_part_result_reporter_;
+
+  // The vector of environments that need to be set-up/torn-down
+  // before/after the tests are run.
+  std::vector<Environment*> environments_;
+
+  // The vector of TestCases in their original order.  It owns the
+  // elements in the vector.
+  std::vector<TestCase*> test_cases_;
+
+  // Provides a level of indirection for the test case list to allow
+  // easy shuffling and restoring the test case order.  The i-th
+  // element of this vector is the index of the i-th test case in the
+  // shuffled order.
+  std::vector<int> test_case_indices_;
+
+#if GTEST_HAS_PARAM_TEST
+  // ParameterizedTestRegistry object used to register value-parameterized
+  // tests.
+  internal::ParameterizedTestCaseRegistry parameterized_test_registry_;
+
+  // Indicates whether RegisterParameterizedTests() has been called already.
+  bool parameterized_tests_registered_;
+#endif  // GTEST_HAS_PARAM_TEST
+
+  // Index of the last death test case registered.  Initially -1.
+  int last_death_test_case_;
+
+  // This points to the TestCase for the currently running test.  It
+  // changes as Google Test goes through one test case after another.
+  // When no test is running, this is set to NULL and Google Test
+  // stores assertion results in ad_hoc_test_result_.  Initially NULL.
+  TestCase* current_test_case_;
+
+  // This points to the TestInfo for the currently running test.  It
+  // changes as Google Test goes through one test after another.  When
+  // no test is running, this is set to NULL and Google Test stores
+  // assertion results in ad_hoc_test_result_.  Initially NULL.
+  TestInfo* current_test_info_;
+
+  // Normally, a user only writes assertions inside a TEST or TEST_F,
+  // or inside a function called by a TEST or TEST_F.  Since Google
+  // Test keeps track of which test is current running, it can
+  // associate such an assertion with the test it belongs to.
+  //
+  // If an assertion is encountered when no TEST or TEST_F is running,
+  // Google Test attributes the assertion result to an imaginary "ad hoc"
+  // test, and records the result in ad_hoc_test_result_.
+  TestResult ad_hoc_test_result_;
+
+  // The list of event listeners that can be used to track events inside
+  // Google Test.
+  TestEventListeners listeners_;
+
+  // The OS stack trace getter.  Will be deleted when the UnitTest
+  // object is destructed.  By default, an OsStackTraceGetter is used,
+  // but the user can set this field to use a custom getter if that is
+  // desired.
+  OsStackTraceGetterInterface* os_stack_trace_getter_;
+
+  // True iff PostFlagParsingInit() has been called.
+  bool post_flag_parse_init_performed_;
+
+  // The random number seed used at the beginning of the test run.
+  int random_seed_;
+
+  // Our random number generator.
+  internal::Random random_;
+
+  // The time of the test program start, in ms from the start of the
+  // UNIX epoch.
+  TimeInMillis start_timestamp_;
+
+  // How long the test took to run, in milliseconds.
+  TimeInMillis elapsed_time_;
+
+#if GTEST_HAS_DEATH_TEST
+  // The decomposed components of the gtest_internal_run_death_test flag,
+  // parsed when RUN_ALL_TESTS is called.
+  internal::scoped_ptr<InternalRunDeathTestFlag> internal_run_death_test_flag_;
+  internal::scoped_ptr<internal::DeathTestFactory> death_test_factory_;
+#endif  // GTEST_HAS_DEATH_TEST
+
+  // A per-thread stack of traces created by the SCOPED_TRACE() macro.
+  internal::ThreadLocal<std::vector<TraceInfo> > gtest_trace_stack_;
+
+  // The value of GTEST_FLAG(catch_exceptions) at the moment RunAllTests()
+  // starts.
+  bool catch_exceptions_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestImpl);
+};  // class UnitTestImpl
+
+// Convenience function for accessing the global UnitTest
+// implementation object.
+inline UnitTestImpl* GetUnitTestImpl() {
+  return UnitTest::GetInstance()->impl();
+}
+
+#if GTEST_USES_SIMPLE_RE
+
+// Internal helper functions for implementing the simple regular
+// expression matcher.
+GTEST_API_ bool IsInSet(char ch, const char* str);
+GTEST_API_ bool IsAsciiDigit(char ch);
+GTEST_API_ bool IsAsciiPunct(char ch);
+GTEST_API_ bool IsRepeat(char ch);
+GTEST_API_ bool IsAsciiWhiteSpace(char ch);
+GTEST_API_ bool IsAsciiWordChar(char ch);
+GTEST_API_ bool IsValidEscape(char ch);
+GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch);
+GTEST_API_ bool ValidateRegex(const char* regex);
+GTEST_API_ bool MatchRegexAtHead(const char* regex, const char* str);
+GTEST_API_ bool MatchRepetitionAndRegexAtHead(
+    bool escaped, char ch, char repeat, const char* regex, const char* str);
+GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str);
+
+#endif  // GTEST_USES_SIMPLE_RE
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test.
+GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, char** argv);
+GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv);
+
+#if GTEST_HAS_DEATH_TEST
+
+// Returns the message describing the last system error, regardless of the
+// platform.
+GTEST_API_ std::string GetLastErrnoDescription();
+
+// Attempts to parse a string into a positive integer pointed to by the
+// number parameter.  Returns true if that is possible.
+// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can use
+// it here.
+template <typename Integer>
+bool ParseNaturalNumber(const ::std::string& str, Integer* number) {
+  // Fail fast if the given string does not begin with a digit;
+  // this bypasses strtoXXX's "optional leading whitespace and plus
+  // or minus sign" semantics, which are undesirable here.
+  if (str.empty() || !IsDigit(str[0])) {
+    return false;
+  }
+  errno = 0;
+
+  char* end;
+  // BiggestConvertible is the largest integer type that system-provided
+  // string-to-number conversion routines can return.
+
+# if GTEST_OS_WINDOWS && !defined(__GNUC__)
+
+  // MSVC and C++ Builder define __int64 instead of the standard long long.
+  typedef unsigned __int64 BiggestConvertible;
+  const BiggestConvertible parsed = _strtoui64(str.c_str(), &end, 10);
+
+# else
+
+  typedef unsigned long long BiggestConvertible;  // NOLINT
+  const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10);
+
+# endif  // GTEST_OS_WINDOWS && !defined(__GNUC__)
+
+  const bool parse_success = *end == '\0' && errno == 0;
+
+  // TODO(vladl@google.com): Convert this to compile time assertion when it is
+  // available.
+  GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed));
+
+  const Integer result = static_cast<Integer>(parsed);
+  if (parse_success && static_cast<BiggestConvertible>(result) == parsed) {
+    *number = result;
+    return true;
+  }
+  return false;
+}
+#endif  // GTEST_HAS_DEATH_TEST
+
+// TestResult contains some private methods that should be hidden from
+// Google Test user but are required for testing. This class allow our tests
+// to access them.
+//
+// This class is supplied only for the purpose of testing Google Test's own
+// constructs. Do not use it in user tests, either directly or indirectly.
+class TestResultAccessor {
+ public:
+  static void RecordProperty(TestResult* test_result,
+                             const std::string& xml_element,
+                             const TestProperty& property) {
+    test_result->RecordProperty(xml_element, property);
+  }
+
+  static void ClearTestPartResults(TestResult* test_result) {
+    test_result->ClearTestPartResults();
+  }
+
+  static const std::vector<testing::TestPartResult>& test_part_results(
+      const TestResult& test_result) {
+    return test_result.test_part_results();
+  }
+};
+
+#if GTEST_CAN_STREAM_RESULTS_
+
+// Streams test results to the given port on the given host machine.
+class StreamingListener : public EmptyTestEventListener {
+ public:
+  // Abstract base class for writing strings to a socket.
+  class AbstractSocketWriter {
+   public:
+    virtual ~AbstractSocketWriter() {}
+
+    // Sends a string to the socket.
+    virtual void Send(const string& message) = 0;
+
+    // Closes the socket.
+    virtual void CloseConnection() {}
+
+    // Sends a string and a newline to the socket.
+    void SendLn(const string& message) {
+      Send(message + "\n");
+    }
+  };
+
+  // Concrete class for actually writing strings to a socket.
+  class SocketWriter : public AbstractSocketWriter {
+   public:
+    SocketWriter(const string& host, const string& port)
+        : sockfd_(-1), host_name_(host), port_num_(port) {
+      MakeConnection();
+    }
+
+    virtual ~SocketWriter() {
+      if (sockfd_ != -1)
+        CloseConnection();
+    }
+
+    // Sends a string to the socket.
+    virtual void Send(const string& message) {
+      GTEST_CHECK_(sockfd_ != -1)
+          << "Send() can be called only when there is a connection.";
+
+      const int len = static_cast<int>(message.length());
+      if (write(sockfd_, message.c_str(), len) != len) {
+        GTEST_LOG_(WARNING)
+            << "stream_result_to: failed to stream to "
+            << host_name_ << ":" << port_num_;
+      }
+    }
+
+   private:
+    // Creates a client socket and connects to the server.
+    void MakeConnection();
+
+    // Closes the socket.
+    void CloseConnection() {
+      GTEST_CHECK_(sockfd_ != -1)
+          << "CloseConnection() can be called only when there is a connection.";
+
+      close(sockfd_);
+      sockfd_ = -1;
+    }
+
+    int sockfd_;  // socket file descriptor
+    const string host_name_;
+    const string port_num_;
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(SocketWriter);
+  };  // class SocketWriter
+
+  // Escapes '=', '&', '%', and '\n' characters in str as "%xx".
+  static string UrlEncode(const char* str);
+
+  StreamingListener(const string& host, const string& port)
+      : socket_writer_(new SocketWriter(host, port)) { Start(); }
+
+  explicit StreamingListener(AbstractSocketWriter* socket_writer)
+      : socket_writer_(socket_writer) { Start(); }
+
+  void OnTestProgramStart(const UnitTest& /* unit_test */) {
+    SendLn("event=TestProgramStart");
+  }
+
+  void OnTestProgramEnd(const UnitTest& unit_test) {
+    // Note that Google Test current only report elapsed time for each
+    // test iteration, not for the entire test program.
+    SendLn("event=TestProgramEnd&passed=" + FormatBool(unit_test.Passed()));
+
+    // Notify the streaming server to stop.
+    socket_writer_->CloseConnection();
+  }
+
+  void OnTestIterationStart(const UnitTest& /* unit_test */, int iteration) {
+    SendLn("event=TestIterationStart&iteration=" +
+           StreamableToString(iteration));
+  }
+
+  void OnTestIterationEnd(const UnitTest& unit_test, int /* iteration */) {
+    SendLn("event=TestIterationEnd&passed=" +
+           FormatBool(unit_test.Passed()) + "&elapsed_time=" +
+           StreamableToString(unit_test.elapsed_time()) + "ms");
+  }
+
+  void OnTestCaseStart(const TestCase& test_case) {
+    SendLn(std::string("event=TestCaseStart&name=") + test_case.name());
+  }
+
+  void OnTestCaseEnd(const TestCase& test_case) {
+    SendLn("event=TestCaseEnd&passed=" + FormatBool(test_case.Passed())
+           + "&elapsed_time=" + StreamableToString(test_case.elapsed_time())
+           + "ms");
+  }
+
+  void OnTestStart(const TestInfo& test_info) {
+    SendLn(std::string("event=TestStart&name=") + test_info.name());
+  }
+
+  void OnTestEnd(const TestInfo& test_info) {
+    SendLn("event=TestEnd&passed=" +
+           FormatBool((test_info.result())->Passed()) +
+           "&elapsed_time=" +
+           StreamableToString((test_info.result())->elapsed_time()) + "ms");
+  }
+
+  void OnTestPartResult(const TestPartResult& test_part_result) {
+    const char* file_name = test_part_result.file_name();
+    if (file_name == NULL)
+      file_name = "";
+    SendLn("event=TestPartResult&file=" + UrlEncode(file_name) +
+           "&line=" + StreamableToString(test_part_result.line_number()) +
+           "&message=" + UrlEncode(test_part_result.message()));
+  }
+
+ private:
+  // Sends the given message and a newline to the socket.
+  void SendLn(const string& message) { socket_writer_->SendLn(message); }
+
+  // Called at the start of streaming to notify the receiver what
+  // protocol we are using.
+  void Start() { SendLn("gtest_streaming_protocol_version=1.0"); }
+
+  string FormatBool(bool value) { return value ? "1" : "0"; }
+
+  const scoped_ptr<AbstractSocketWriter> socket_writer_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamingListener);
+};  // class StreamingListener
+
+#endif  // GTEST_CAN_STREAM_RESULTS_
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_SRC_GTEST_INTERNAL_INL_H_
diff --git a/third_party/googletest/googletest/src/gtest-port.cc b/third_party/googletest/googletest/src/gtest-port.cc
new file mode 100644
index 0000000..3842c41
--- /dev/null
+++ b/third_party/googletest/googletest/src/gtest-port.cc
@@ -0,0 +1,1221 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include "gtest/internal/gtest-port.h"
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fstream>
+
+#if GTEST_OS_WINDOWS
+# include <windows.h>
+# include <io.h>
+# include <sys/stat.h>
+# include <map>  // Used in ThreadLocal.
+#else
+# include <unistd.h>
+#endif  // GTEST_OS_WINDOWS
+
+#if GTEST_OS_MAC
+# include <mach/mach_init.h>
+# include <mach/task.h>
+# include <mach/vm_map.h>
+#endif  // GTEST_OS_MAC
+
+#if GTEST_OS_QNX
+# include <devctl.h>
+# include <fcntl.h>
+# include <sys/procfs.h>
+#endif  // GTEST_OS_QNX
+
+#include "gtest/gtest-spi.h"
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick exists to
+// prevent the accidental inclusion of gtest-internal-inl.h in the
+// user's code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+namespace internal {
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+// MSVC and C++Builder do not provide a definition of STDERR_FILENO.
+const int kStdOutFileno = 1;
+const int kStdErrFileno = 2;
+#else
+const int kStdOutFileno = STDOUT_FILENO;
+const int kStdErrFileno = STDERR_FILENO;
+#endif  // _MSC_VER
+
+#if GTEST_OS_LINUX
+
+namespace {
+template <typename T>
+T ReadProcFileField(const string& filename, int field) {
+  std::string dummy;
+  std::ifstream file(filename.c_str());
+  while (field-- > 0) {
+    file >> dummy;
+  }
+  T output = 0;
+  file >> output;
+  return output;
+}
+}  // namespace
+
+// Returns the number of active threads, or 0 when there is an error.
+size_t GetThreadCount() {
+  const string filename =
+      (Message() << "/proc/" << getpid() << "/stat").GetString();
+  return ReadProcFileField<int>(filename, 19);
+}
+
+#elif GTEST_OS_MAC
+
+size_t GetThreadCount() {
+  const task_t task = mach_task_self();
+  mach_msg_type_number_t thread_count;
+  thread_act_array_t thread_list;
+  const kern_return_t status = task_threads(task, &thread_list, &thread_count);
+  if (status == KERN_SUCCESS) {
+    // task_threads allocates resources in thread_list and we need to free them
+    // to avoid leaks.
+    vm_deallocate(task,
+                  reinterpret_cast<vm_address_t>(thread_list),
+                  sizeof(thread_t) * thread_count);
+    return static_cast<size_t>(thread_count);
+  } else {
+    return 0;
+  }
+}
+
+#elif GTEST_OS_QNX
+
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+size_t GetThreadCount() {
+  const int fd = open("/proc/self/as", O_RDONLY);
+  if (fd < 0) {
+    return 0;
+  }
+  procfs_info process_info;
+  const int status =
+      devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), NULL);
+  close(fd);
+  if (status == EOK) {
+    return static_cast<size_t>(process_info.num_threads);
+  } else {
+    return 0;
+  }
+}
+
+#else
+
+size_t GetThreadCount() {
+  // There's no portable way to detect the number of threads, so we just
+  // return 0 to indicate that we cannot detect it.
+  return 0;
+}
+
+#endif  // GTEST_OS_LINUX
+
+#if GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS
+
+void SleepMilliseconds(int n) {
+  ::Sleep(n);
+}
+
+AutoHandle::AutoHandle()
+    : handle_(INVALID_HANDLE_VALUE) {}
+
+AutoHandle::AutoHandle(Handle handle)
+    : handle_(handle) {}
+
+AutoHandle::~AutoHandle() {
+  Reset();
+}
+
+AutoHandle::Handle AutoHandle::Get() const {
+  return handle_;
+}
+
+void AutoHandle::Reset() {
+  Reset(INVALID_HANDLE_VALUE);
+}
+
+void AutoHandle::Reset(HANDLE handle) {
+  // Resetting with the same handle we already own is invalid.
+  if (handle_ != handle) {
+    if (IsCloseable()) {
+      ::CloseHandle(handle_);
+    }
+    handle_ = handle;
+  } else {
+    GTEST_CHECK_(!IsCloseable())
+        << "Resetting a valid handle to itself is likely a programmer error "
+            "and thus not allowed.";
+  }
+}
+
+bool AutoHandle::IsCloseable() const {
+  // Different Windows APIs may use either of these values to represent an
+  // invalid handle.
+  return handle_ != NULL && handle_ != INVALID_HANDLE_VALUE;
+}
+
+Notification::Notification()
+    : event_(::CreateEvent(NULL,   // Default security attributes.
+                           TRUE,   // Do not reset automatically.
+                           FALSE,  // Initially unset.
+                           NULL)) {  // Anonymous event.
+  GTEST_CHECK_(event_.Get() != NULL);
+}
+
+void Notification::Notify() {
+  GTEST_CHECK_(::SetEvent(event_.Get()) != FALSE);
+}
+
+void Notification::WaitForNotification() {
+  GTEST_CHECK_(
+      ::WaitForSingleObject(event_.Get(), INFINITE) == WAIT_OBJECT_0);
+}
+
+Mutex::Mutex()
+    : owner_thread_id_(0),
+      type_(kDynamic),
+      critical_section_init_phase_(0),
+      critical_section_(new CRITICAL_SECTION) {
+  ::InitializeCriticalSection(critical_section_);
+}
+
+Mutex::~Mutex() {
+  // Static mutexes are leaked intentionally. It is not thread-safe to try
+  // to clean them up.
+  // TODO(yukawa): Switch to Slim Reader/Writer (SRW) Locks, which requires
+  // nothing to clean it up but is available only on Vista and later.
+  // http://msdn.microsoft.com/en-us/library/windows/desktop/aa904937.aspx
+  if (type_ == kDynamic) {
+    ::DeleteCriticalSection(critical_section_);
+    delete critical_section_;
+    critical_section_ = NULL;
+  }
+}
+
+void Mutex::Lock() {
+  ThreadSafeLazyInit();
+  ::EnterCriticalSection(critical_section_);
+  owner_thread_id_ = ::GetCurrentThreadId();
+}
+
+void Mutex::Unlock() {
+  ThreadSafeLazyInit();
+  // We don't protect writing to owner_thread_id_ here, as it's the
+  // caller's responsibility to ensure that the current thread holds the
+  // mutex when this is called.
+  owner_thread_id_ = 0;
+  ::LeaveCriticalSection(critical_section_);
+}
+
+// Does nothing if the current thread holds the mutex. Otherwise, crashes
+// with high probability.
+void Mutex::AssertHeld() {
+  ThreadSafeLazyInit();
+  GTEST_CHECK_(owner_thread_id_ == ::GetCurrentThreadId())
+      << "The current thread is not holding the mutex @" << this;
+}
+
+// Initializes owner_thread_id_ and critical_section_ in static mutexes.
+void Mutex::ThreadSafeLazyInit() {
+  // Dynamic mutexes are initialized in the constructor.
+  if (type_ == kStatic) {
+    switch (
+        ::InterlockedCompareExchange(&critical_section_init_phase_, 1L, 0L)) {
+      case 0:
+        // If critical_section_init_phase_ was 0 before the exchange, we
+        // are the first to test it and need to perform the initialization.
+        owner_thread_id_ = 0;
+        critical_section_ = new CRITICAL_SECTION;
+        ::InitializeCriticalSection(critical_section_);
+        // Updates the critical_section_init_phase_ to 2 to signal
+        // initialization complete.
+        GTEST_CHECK_(::InterlockedCompareExchange(
+                          &critical_section_init_phase_, 2L, 1L) ==
+                      1L);
+        break;
+      case 1:
+        // Somebody else is already initializing the mutex; spin until they
+        // are done.
+        while (::InterlockedCompareExchange(&critical_section_init_phase_,
+                                            2L,
+                                            2L) != 2L) {
+          // Possibly yields the rest of the thread's time slice to other
+          // threads.
+          ::Sleep(0);
+        }
+        break;
+
+      case 2:
+        break;  // The mutex is already initialized and ready for use.
+
+      default:
+        GTEST_CHECK_(false)
+            << "Unexpected value of critical_section_init_phase_ "
+            << "while initializing a static mutex.";
+    }
+  }
+}
+
+namespace {
+
+class ThreadWithParamSupport : public ThreadWithParamBase {
+ public:
+  static HANDLE CreateThread(Runnable* runnable,
+                             Notification* thread_can_start) {
+    ThreadMainParam* param = new ThreadMainParam(runnable, thread_can_start);
+    DWORD thread_id;
+    // TODO(yukawa): Consider to use _beginthreadex instead.
+    HANDLE thread_handle = ::CreateThread(
+        NULL,    // Default security.
+        0,       // Default stack size.
+        &ThreadWithParamSupport::ThreadMain,
+        param,   // Parameter to ThreadMainStatic
+        0x0,     // Default creation flags.
+        &thread_id);  // Need a valid pointer for the call to work under Win98.
+    GTEST_CHECK_(thread_handle != NULL) << "CreateThread failed with error "
+                                        << ::GetLastError() << ".";
+    if (thread_handle == NULL) {
+      delete param;
+    }
+    return thread_handle;
+  }
+
+ private:
+  struct ThreadMainParam {
+    ThreadMainParam(Runnable* runnable, Notification* thread_can_start)
+        : runnable_(runnable),
+          thread_can_start_(thread_can_start) {
+    }
+    scoped_ptr<Runnable> runnable_;
+    // Does not own.
+    Notification* thread_can_start_;
+  };
+
+  static DWORD WINAPI ThreadMain(void* ptr) {
+    // Transfers ownership.
+    scoped_ptr<ThreadMainParam> param(static_cast<ThreadMainParam*>(ptr));
+    if (param->thread_can_start_ != NULL)
+      param->thread_can_start_->WaitForNotification();
+    param->runnable_->Run();
+    return 0;
+  }
+
+  // Prohibit instantiation.
+  ThreadWithParamSupport();
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParamSupport);
+};
+
+}  // namespace
+
+ThreadWithParamBase::ThreadWithParamBase(Runnable *runnable,
+                                         Notification* thread_can_start)
+      : thread_(ThreadWithParamSupport::CreateThread(runnable,
+                                                     thread_can_start)) {
+}
+
+ThreadWithParamBase::~ThreadWithParamBase() {
+  Join();
+}
+
+void ThreadWithParamBase::Join() {
+  GTEST_CHECK_(::WaitForSingleObject(thread_.Get(), INFINITE) == WAIT_OBJECT_0)
+      << "Failed to join the thread with error " << ::GetLastError() << ".";
+}
+
+// Maps a thread to a set of ThreadIdToThreadLocals that have values
+// instantiated on that thread and notifies them when the thread exits.  A
+// ThreadLocal instance is expected to persist until all threads it has
+// values on have terminated.
+class ThreadLocalRegistryImpl {
+ public:
+  // Registers thread_local_instance as having value on the current thread.
+  // Returns a value that can be used to identify the thread from other threads.
+  static ThreadLocalValueHolderBase* GetValueOnCurrentThread(
+      const ThreadLocalBase* thread_local_instance) {
+    DWORD current_thread = ::GetCurrentThreadId();
+    MutexLock lock(&mutex_);
+    ThreadIdToThreadLocals* const thread_to_thread_locals =
+        GetThreadLocalsMapLocked();
+    ThreadIdToThreadLocals::iterator thread_local_pos =
+        thread_to_thread_locals->find(current_thread);
+    if (thread_local_pos == thread_to_thread_locals->end()) {
+      thread_local_pos = thread_to_thread_locals->insert(
+          std::make_pair(current_thread, ThreadLocalValues())).first;
+      StartWatcherThreadFor(current_thread);
+    }
+    ThreadLocalValues& thread_local_values = thread_local_pos->second;
+    ThreadLocalValues::iterator value_pos =
+        thread_local_values.find(thread_local_instance);
+    if (value_pos == thread_local_values.end()) {
+      value_pos =
+          thread_local_values
+              .insert(std::make_pair(
+                  thread_local_instance,
+                  linked_ptr<ThreadLocalValueHolderBase>(
+                      thread_local_instance->NewValueForCurrentThread())))
+              .first;
+    }
+    return value_pos->second.get();
+  }
+
+  static void OnThreadLocalDestroyed(
+      const ThreadLocalBase* thread_local_instance) {
+    std::vector<linked_ptr<ThreadLocalValueHolderBase> > value_holders;
+    // Clean up the ThreadLocalValues data structure while holding the lock, but
+    // defer the destruction of the ThreadLocalValueHolderBases.
+    {
+      MutexLock lock(&mutex_);
+      ThreadIdToThreadLocals* const thread_to_thread_locals =
+          GetThreadLocalsMapLocked();
+      for (ThreadIdToThreadLocals::iterator it =
+          thread_to_thread_locals->begin();
+          it != thread_to_thread_locals->end();
+          ++it) {
+        ThreadLocalValues& thread_local_values = it->second;
+        ThreadLocalValues::iterator value_pos =
+            thread_local_values.find(thread_local_instance);
+        if (value_pos != thread_local_values.end()) {
+          value_holders.push_back(value_pos->second);
+          thread_local_values.erase(value_pos);
+          // This 'if' can only be successful at most once, so theoretically we
+          // could break out of the loop here, but we don't bother doing so.
+        }
+      }
+    }
+    // Outside the lock, let the destructor for 'value_holders' deallocate the
+    // ThreadLocalValueHolderBases.
+  }
+
+  static void OnThreadExit(DWORD thread_id) {
+    GTEST_CHECK_(thread_id != 0) << ::GetLastError();
+    std::vector<linked_ptr<ThreadLocalValueHolderBase> > value_holders;
+    // Clean up the ThreadIdToThreadLocals data structure while holding the
+    // lock, but defer the destruction of the ThreadLocalValueHolderBases.
+    {
+      MutexLock lock(&mutex_);
+      ThreadIdToThreadLocals* const thread_to_thread_locals =
+          GetThreadLocalsMapLocked();
+      ThreadIdToThreadLocals::iterator thread_local_pos =
+          thread_to_thread_locals->find(thread_id);
+      if (thread_local_pos != thread_to_thread_locals->end()) {
+        ThreadLocalValues& thread_local_values = thread_local_pos->second;
+        for (ThreadLocalValues::iterator value_pos =
+            thread_local_values.begin();
+            value_pos != thread_local_values.end();
+            ++value_pos) {
+          value_holders.push_back(value_pos->second);
+        }
+        thread_to_thread_locals->erase(thread_local_pos);
+      }
+    }
+    // Outside the lock, let the destructor for 'value_holders' deallocate the
+    // ThreadLocalValueHolderBases.
+  }
+
+ private:
+  // In a particular thread, maps a ThreadLocal object to its value.
+  typedef std::map<const ThreadLocalBase*,
+                   linked_ptr<ThreadLocalValueHolderBase> > ThreadLocalValues;
+  // Stores all ThreadIdToThreadLocals having values in a thread, indexed by
+  // thread's ID.
+  typedef std::map<DWORD, ThreadLocalValues> ThreadIdToThreadLocals;
+
+  // Holds the thread id and thread handle that we pass from
+  // StartWatcherThreadFor to WatcherThreadFunc.
+  typedef std::pair<DWORD, HANDLE> ThreadIdAndHandle;
+
+  static void StartWatcherThreadFor(DWORD thread_id) {
+    // The returned handle will be kept in thread_map and closed by
+    // watcher_thread in WatcherThreadFunc.
+    HANDLE thread = ::OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
+                                 FALSE,
+                                 thread_id);
+    GTEST_CHECK_(thread != NULL);
+    // We need to to pass a valid thread ID pointer into CreateThread for it
+    // to work correctly under Win98.
+    DWORD watcher_thread_id;
+    HANDLE watcher_thread = ::CreateThread(
+        NULL,   // Default security.
+        0,      // Default stack size
+        &ThreadLocalRegistryImpl::WatcherThreadFunc,
+        reinterpret_cast<LPVOID>(new ThreadIdAndHandle(thread_id, thread)),
+        CREATE_SUSPENDED,
+        &watcher_thread_id);
+    GTEST_CHECK_(watcher_thread != NULL);
+    // Give the watcher thread the same priority as ours to avoid being
+    // blocked by it.
+    ::SetThreadPriority(watcher_thread,
+                        ::GetThreadPriority(::GetCurrentThread()));
+    ::ResumeThread(watcher_thread);
+    ::CloseHandle(watcher_thread);
+  }
+
+  // Monitors exit from a given thread and notifies those
+  // ThreadIdToThreadLocals about thread termination.
+  static DWORD WINAPI WatcherThreadFunc(LPVOID param) {
+    const ThreadIdAndHandle* tah =
+        reinterpret_cast<const ThreadIdAndHandle*>(param);
+    GTEST_CHECK_(
+        ::WaitForSingleObject(tah->second, INFINITE) == WAIT_OBJECT_0);
+    OnThreadExit(tah->first);
+    ::CloseHandle(tah->second);
+    delete tah;
+    return 0;
+  }
+
+  // Returns map of thread local instances.
+  static ThreadIdToThreadLocals* GetThreadLocalsMapLocked() {
+    mutex_.AssertHeld();
+    static ThreadIdToThreadLocals* map = new ThreadIdToThreadLocals;
+    return map;
+  }
+
+  // Protects access to GetThreadLocalsMapLocked() and its return value.
+  static Mutex mutex_;
+  // Protects access to GetThreadMapLocked() and its return value.
+  static Mutex thread_map_mutex_;
+};
+
+Mutex ThreadLocalRegistryImpl::mutex_(Mutex::kStaticMutex);
+Mutex ThreadLocalRegistryImpl::thread_map_mutex_(Mutex::kStaticMutex);
+
+ThreadLocalValueHolderBase* ThreadLocalRegistry::GetValueOnCurrentThread(
+      const ThreadLocalBase* thread_local_instance) {
+  return ThreadLocalRegistryImpl::GetValueOnCurrentThread(
+      thread_local_instance);
+}
+
+void ThreadLocalRegistry::OnThreadLocalDestroyed(
+      const ThreadLocalBase* thread_local_instance) {
+  ThreadLocalRegistryImpl::OnThreadLocalDestroyed(thread_local_instance);
+}
+
+#endif  // GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS
+
+#if GTEST_USES_POSIX_RE
+
+// Implements RE.  Currently only needed for death tests.
+
+RE::~RE() {
+  if (is_valid_) {
+    // regfree'ing an invalid regex might crash because the content
+    // of the regex is undefined. Since the regex's are essentially
+    // the same, one cannot be valid (or invalid) without the other
+    // being so too.
+    regfree(&partial_regex_);
+    regfree(&full_regex_);
+  }
+  free(const_cast<char*>(pattern_));
+}
+
+// Returns true iff regular expression re matches the entire str.
+bool RE::FullMatch(const char* str, const RE& re) {
+  if (!re.is_valid_) return false;
+
+  regmatch_t match;
+  return regexec(&re.full_regex_, str, 1, &match, 0) == 0;
+}
+
+// Returns true iff regular expression re matches a substring of str
+// (including str itself).
+bool RE::PartialMatch(const char* str, const RE& re) {
+  if (!re.is_valid_) return false;
+
+  regmatch_t match;
+  return regexec(&re.partial_regex_, str, 1, &match, 0) == 0;
+}
+
+// Initializes an RE from its string representation.
+void RE::Init(const char* regex) {
+  pattern_ = posix::StrDup(regex);
+
+  // Reserves enough bytes to hold the regular expression used for a
+  // full match.
+  const size_t full_regex_len = strlen(regex) + 10;
+  char* const full_pattern = new char[full_regex_len];
+
+  snprintf(full_pattern, full_regex_len, "^(%s)$", regex);
+  is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0;
+  // We want to call regcomp(&partial_regex_, ...) even if the
+  // previous expression returns false.  Otherwise partial_regex_ may
+  // not be properly initialized can may cause trouble when it's
+  // freed.
+  //
+  // Some implementation of POSIX regex (e.g. on at least some
+  // versions of Cygwin) doesn't accept the empty string as a valid
+  // regex.  We change it to an equivalent form "()" to be safe.
+  if (is_valid_) {
+    const char* const partial_regex = (*regex == '\0') ? "()" : regex;
+    is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0;
+  }
+  EXPECT_TRUE(is_valid_)
+      << "Regular expression \"" << regex
+      << "\" is not a valid POSIX Extended regular expression.";
+
+  delete[] full_pattern;
+}
+
+#elif GTEST_USES_SIMPLE_RE
+
+// Returns true iff ch appears anywhere in str (excluding the
+// terminating '\0' character).
+bool IsInSet(char ch, const char* str) {
+  return ch != '\0' && strchr(str, ch) != NULL;
+}
+
+// Returns true iff ch belongs to the given classification.  Unlike
+// similar functions in <ctype.h>, these aren't affected by the
+// current locale.
+bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; }
+bool IsAsciiPunct(char ch) {
+  return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~");
+}
+bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); }
+bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); }
+bool IsAsciiWordChar(char ch) {
+  return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') ||
+      ('0' <= ch && ch <= '9') || ch == '_';
+}
+
+// Returns true iff "\\c" is a supported escape sequence.
+bool IsValidEscape(char c) {
+  return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW"));
+}
+
+// Returns true iff the given atom (specified by escaped and pattern)
+// matches ch.  The result is undefined if the atom is invalid.
+bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
+  if (escaped) {  // "\\p" where p is pattern_char.
+    switch (pattern_char) {
+      case 'd': return IsAsciiDigit(ch);
+      case 'D': return !IsAsciiDigit(ch);
+      case 'f': return ch == '\f';
+      case 'n': return ch == '\n';
+      case 'r': return ch == '\r';
+      case 's': return IsAsciiWhiteSpace(ch);
+      case 'S': return !IsAsciiWhiteSpace(ch);
+      case 't': return ch == '\t';
+      case 'v': return ch == '\v';
+      case 'w': return IsAsciiWordChar(ch);
+      case 'W': return !IsAsciiWordChar(ch);
+    }
+    return IsAsciiPunct(pattern_char) && pattern_char == ch;
+  }
+
+  return (pattern_char == '.' && ch != '\n') || pattern_char == ch;
+}
+
+// Helper function used by ValidateRegex() to format error messages.
+std::string FormatRegexSyntaxError(const char* regex, int index) {
+  return (Message() << "Syntax error at index " << index
+          << " in simple regular expression \"" << regex << "\": ").GetString();
+}
+
+// Generates non-fatal failures and returns false if regex is invalid;
+// otherwise returns true.
+bool ValidateRegex(const char* regex) {
+  if (regex == NULL) {
+    // TODO(wan@google.com): fix the source file location in the
+    // assertion failures to match where the regex is used in user
+    // code.
+    ADD_FAILURE() << "NULL is not a valid simple regular expression.";
+    return false;
+  }
+
+  bool is_valid = true;
+
+  // True iff ?, *, or + can follow the previous atom.
+  bool prev_repeatable = false;
+  for (int i = 0; regex[i]; i++) {
+    if (regex[i] == '\\') {  // An escape sequence
+      i++;
+      if (regex[i] == '\0') {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
+                      << "'\\' cannot appear at the end.";
+        return false;
+      }
+
+      if (!IsValidEscape(regex[i])) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
+                      << "invalid escape sequence \"\\" << regex[i] << "\".";
+        is_valid = false;
+      }
+      prev_repeatable = true;
+    } else {  // Not an escape sequence.
+      const char ch = regex[i];
+
+      if (ch == '^' && i > 0) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'^' can only appear at the beginning.";
+        is_valid = false;
+      } else if (ch == '$' && regex[i + 1] != '\0') {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'$' can only appear at the end.";
+        is_valid = false;
+      } else if (IsInSet(ch, "()[]{}|")) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'" << ch << "' is unsupported.";
+        is_valid = false;
+      } else if (IsRepeat(ch) && !prev_repeatable) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'" << ch << "' can only follow a repeatable token.";
+        is_valid = false;
+      }
+
+      prev_repeatable = !IsInSet(ch, "^$?*+");
+    }
+  }
+
+  return is_valid;
+}
+
+// Matches a repeated regex atom followed by a valid simple regular
+// expression.  The regex atom is defined as c if escaped is false,
+// or \c otherwise.  repeat is the repetition meta character (?, *,
+// or +).  The behavior is undefined if str contains too many
+// characters to be indexable by size_t, in which case the test will
+// probably time out anyway.  We are fine with this limitation as
+// std::string has it too.
+bool MatchRepetitionAndRegexAtHead(
+    bool escaped, char c, char repeat, const char* regex,
+    const char* str) {
+  const size_t min_count = (repeat == '+') ? 1 : 0;
+  const size_t max_count = (repeat == '?') ? 1 :
+      static_cast<size_t>(-1) - 1;
+  // We cannot call numeric_limits::max() as it conflicts with the
+  // max() macro on Windows.
+
+  for (size_t i = 0; i <= max_count; ++i) {
+    // We know that the atom matches each of the first i characters in str.
+    if (i >= min_count && MatchRegexAtHead(regex, str + i)) {
+      // We have enough matches at the head, and the tail matches too.
+      // Since we only care about *whether* the pattern matches str
+      // (as opposed to *how* it matches), there is no need to find a
+      // greedy match.
+      return true;
+    }
+    if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i]))
+      return false;
+  }
+  return false;
+}
+
+// Returns true iff regex matches a prefix of str.  regex must be a
+// valid simple regular expression and not start with "^", or the
+// result is undefined.
+bool MatchRegexAtHead(const char* regex, const char* str) {
+  if (*regex == '\0')  // An empty regex matches a prefix of anything.
+    return true;
+
+  // "$" only matches the end of a string.  Note that regex being
+  // valid guarantees that there's nothing after "$" in it.
+  if (*regex == '$')
+    return *str == '\0';
+
+  // Is the first thing in regex an escape sequence?
+  const bool escaped = *regex == '\\';
+  if (escaped)
+    ++regex;
+  if (IsRepeat(regex[1])) {
+    // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so
+    // here's an indirect recursion.  It terminates as the regex gets
+    // shorter in each recursion.
+    return MatchRepetitionAndRegexAtHead(
+        escaped, regex[0], regex[1], regex + 2, str);
+  } else {
+    // regex isn't empty, isn't "$", and doesn't start with a
+    // repetition.  We match the first atom of regex with the first
+    // character of str and recurse.
+    return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) &&
+        MatchRegexAtHead(regex + 1, str + 1);
+  }
+}
+
+// Returns true iff regex matches any substring of str.  regex must be
+// a valid simple regular expression, or the result is undefined.
+//
+// The algorithm is recursive, but the recursion depth doesn't exceed
+// the regex length, so we won't need to worry about running out of
+// stack space normally.  In rare cases the time complexity can be
+// exponential with respect to the regex length + the string length,
+// but usually it's must faster (often close to linear).
+bool MatchRegexAnywhere(const char* regex, const char* str) {
+  if (regex == NULL || str == NULL)
+    return false;
+
+  if (*regex == '^')
+    return MatchRegexAtHead(regex + 1, str);
+
+  // A successful match can be anywhere in str.
+  do {
+    if (MatchRegexAtHead(regex, str))
+      return true;
+  } while (*str++ != '\0');
+  return false;
+}
+
+// Implements the RE class.
+
+RE::~RE() {
+  free(const_cast<char*>(pattern_));
+  free(const_cast<char*>(full_pattern_));
+}
+
+// Returns true iff regular expression re matches the entire str.
+bool RE::FullMatch(const char* str, const RE& re) {
+  return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str);
+}
+
+// Returns true iff regular expression re matches a substring of str
+// (including str itself).
+bool RE::PartialMatch(const char* str, const RE& re) {
+  return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str);
+}
+
+// Initializes an RE from its string representation.
+void RE::Init(const char* regex) {
+  pattern_ = full_pattern_ = NULL;
+  if (regex != NULL) {
+    pattern_ = posix::StrDup(regex);
+  }
+
+  is_valid_ = ValidateRegex(regex);
+  if (!is_valid_) {
+    // No need to calculate the full pattern when the regex is invalid.
+    return;
+  }
+
+  const size_t len = strlen(regex);
+  // Reserves enough bytes to hold the regular expression used for a
+  // full match: we need space to prepend a '^', append a '$', and
+  // terminate the string with '\0'.
+  char* buffer = static_cast<char*>(malloc(len + 3));
+  full_pattern_ = buffer;
+
+  if (*regex != '^')
+    *buffer++ = '^';  // Makes sure full_pattern_ starts with '^'.
+
+  // We don't use snprintf or strncpy, as they trigger a warning when
+  // compiled with VC++ 8.0.
+  memcpy(buffer, regex, len);
+  buffer += len;
+
+  if (len == 0 || regex[len - 1] != '$')
+    *buffer++ = '$';  // Makes sure full_pattern_ ends with '$'.
+
+  *buffer = '\0';
+}
+
+#endif  // GTEST_USES_POSIX_RE
+
+const char kUnknownFile[] = "unknown file";
+
+// Formats a source file path and a line number as they would appear
+// in an error message from the compiler used to compile this code.
+GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) {
+  const std::string file_name(file == NULL ? kUnknownFile : file);
+
+  if (line < 0) {
+    return file_name + ":";
+  }
+#ifdef _MSC_VER
+  return file_name + "(" + StreamableToString(line) + "):";
+#else
+  return file_name + ":" + StreamableToString(line) + ":";
+#endif  // _MSC_VER
+}
+
+// Formats a file location for compiler-independent XML output.
+// Although this function is not platform dependent, we put it next to
+// FormatFileLocation in order to contrast the two functions.
+// Note that FormatCompilerIndependentFileLocation() does NOT append colon
+// to the file location it produces, unlike FormatFileLocation().
+GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(
+    const char* file, int line) {
+  const std::string file_name(file == NULL ? kUnknownFile : file);
+
+  if (line < 0)
+    return file_name;
+  else
+    return file_name + ":" + StreamableToString(line);
+}
+
+GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line)
+    : severity_(severity) {
+  const char* const marker =
+      severity == GTEST_INFO ?    "[  INFO ]" :
+      severity == GTEST_WARNING ? "[WARNING]" :
+      severity == GTEST_ERROR ?   "[ ERROR ]" : "[ FATAL ]";
+  GetStream() << ::std::endl << marker << " "
+              << FormatFileLocation(file, line).c_str() << ": ";
+}
+
+// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
+GTestLog::~GTestLog() {
+  GetStream() << ::std::endl;
+  if (severity_ == GTEST_FATAL) {
+    fflush(stderr);
+    posix::Abort();
+  }
+}
+// Disable Microsoft deprecation warnings for POSIX functions called from
+// this class (creat, dup, dup2, and close)
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996)
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Object that captures an output stream (stdout/stderr).
+class CapturedStream {
+ public:
+  // The ctor redirects the stream to a temporary file.
+  explicit CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) {
+# if GTEST_OS_WINDOWS
+    char temp_dir_path[MAX_PATH + 1] = { '\0' };  // NOLINT
+    char temp_file_path[MAX_PATH + 1] = { '\0' };  // NOLINT
+
+    ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path);
+    const UINT success = ::GetTempFileNameA(temp_dir_path,
+                                            "gtest_redir",
+                                            0,  // Generate unique file name.
+                                            temp_file_path);
+    GTEST_CHECK_(success != 0)
+        << "Unable to create a temporary file in " << temp_dir_path;
+    const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE);
+    GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file "
+                                    << temp_file_path;
+    filename_ = temp_file_path;
+# else
+    // There's no guarantee that a test has write access to the current
+    // directory, so we create the temporary file in the /tmp directory
+    // instead. We use /tmp on most systems, and /sdcard on Android.
+    // That's because Android doesn't have /tmp.
+#  if GTEST_OS_LINUX_ANDROID
+    // Note: Android applications are expected to call the framework's
+    // Context.getExternalStorageDirectory() method through JNI to get
+    // the location of the world-writable SD Card directory. However,
+    // this requires a Context handle, which cannot be retrieved
+    // globally from native code. Doing so also precludes running the
+    // code as part of a regular standalone executable, which doesn't
+    // run in a Dalvik process (e.g. when running it through 'adb shell').
+    //
+    // The location /sdcard is directly accessible from native code
+    // and is the only location (unofficially) supported by the Android
+    // team. It's generally a symlink to the real SD Card mount point
+    // which can be /mnt/sdcard, /mnt/sdcard0, /system/media/sdcard, or
+    // other OEM-customized locations. Never rely on these, and always
+    // use /sdcard.
+    char name_template[] = "/sdcard/gtest_captured_stream.XXXXXX";
+#  else
+    char name_template[] = "/tmp/captured_stream.XXXXXX";
+#  endif  // GTEST_OS_LINUX_ANDROID
+    const int captured_fd = mkstemp(name_template);
+    filename_ = name_template;
+# endif  // GTEST_OS_WINDOWS
+    fflush(NULL);
+    dup2(captured_fd, fd_);
+    close(captured_fd);
+  }
+
+  ~CapturedStream() {
+    remove(filename_.c_str());
+  }
+
+  std::string GetCapturedString() {
+    if (uncaptured_fd_ != -1) {
+      // Restores the original stream.
+      fflush(NULL);
+      dup2(uncaptured_fd_, fd_);
+      close(uncaptured_fd_);
+      uncaptured_fd_ = -1;
+    }
+
+    FILE* const file = posix::FOpen(filename_.c_str(), "r");
+    const std::string content = ReadEntireFile(file);
+    posix::FClose(file);
+    return content;
+  }
+
+ private:
+  const int fd_;  // A stream to capture.
+  int uncaptured_fd_;
+  // Name of the temporary file holding the stderr output.
+  ::std::string filename_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream);
+};
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()
+
+static CapturedStream* g_captured_stderr = NULL;
+static CapturedStream* g_captured_stdout = NULL;
+
+// Starts capturing an output stream (stdout/stderr).
+void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) {
+  if (*stream != NULL) {
+    GTEST_LOG_(FATAL) << "Only one " << stream_name
+                      << " capturer can exist at a time.";
+  }
+  *stream = new CapturedStream(fd);
+}
+
+// Stops capturing the output stream and returns the captured string.
+std::string GetCapturedStream(CapturedStream** captured_stream) {
+  const std::string content = (*captured_stream)->GetCapturedString();
+
+  delete *captured_stream;
+  *captured_stream = NULL;
+
+  return content;
+}
+
+// Starts capturing stdout.
+void CaptureStdout() {
+  CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout);
+}
+
+// Starts capturing stderr.
+void CaptureStderr() {
+  CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr);
+}
+
+// Stops capturing stdout and returns the captured string.
+std::string GetCapturedStdout() {
+  return GetCapturedStream(&g_captured_stdout);
+}
+
+// Stops capturing stderr and returns the captured string.
+std::string GetCapturedStderr() {
+  return GetCapturedStream(&g_captured_stderr);
+}
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+std::string TempDir() {
+#if GTEST_OS_WINDOWS_MOBILE
+  return "\\temp\\";
+#elif GTEST_OS_WINDOWS
+  const char* temp_dir = posix::GetEnv("TEMP");
+  if (temp_dir == NULL || temp_dir[0] == '\0')
+    return "\\temp\\";
+  else if (temp_dir[strlen(temp_dir) - 1] == '\\')
+    return temp_dir;
+  else
+    return std::string(temp_dir) + "\\";
+#elif GTEST_OS_LINUX_ANDROID
+  return "/sdcard/";
+#else
+  return "/tmp/";
+#endif  // GTEST_OS_WINDOWS_MOBILE
+}
+
+size_t GetFileSize(FILE* file) {
+  fseek(file, 0, SEEK_END);
+  return static_cast<size_t>(ftell(file));
+}
+
+std::string ReadEntireFile(FILE* file) {
+  const size_t file_size = GetFileSize(file);
+  char* const buffer = new char[file_size];
+
+  size_t bytes_last_read = 0;  // # of bytes read in the last fread()
+  size_t bytes_read = 0;       // # of bytes read so far
+
+  fseek(file, 0, SEEK_SET);
+
+  // Keeps reading the file until we cannot read further or the
+  // pre-determined file size is reached.
+  do {
+    bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
+    bytes_read += bytes_last_read;
+  } while (bytes_last_read > 0 && bytes_read < file_size);
+
+  const std::string content(buffer, bytes_read);
+  delete[] buffer;
+
+  return content;
+}
+
+#if GTEST_HAS_DEATH_TEST
+
+static const ::std::vector<testing::internal::string>* g_injected_test_argvs =
+                                        NULL;  // Owned.
+
+void SetInjectableArgvs(const ::std::vector<testing::internal::string>* argvs) {
+  if (g_injected_test_argvs != argvs)
+    delete g_injected_test_argvs;
+  g_injected_test_argvs = argvs;
+}
+
+const ::std::vector<testing::internal::string>& GetInjectableArgvs() {
+  if (g_injected_test_argvs != NULL) {
+    return *g_injected_test_argvs;
+  }
+  return GetArgvs();
+}
+#endif  // GTEST_HAS_DEATH_TEST
+
+#if GTEST_OS_WINDOWS_MOBILE
+namespace posix {
+void Abort() {
+  DebugBreak();
+  TerminateProcess(GetCurrentProcess(), 1);
+}
+}  // namespace posix
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+// Returns the name of the environment variable corresponding to the
+// given flag.  For example, FlagToEnvVar("foo") will return
+// "GTEST_FOO" in the open-source version.
+static std::string FlagToEnvVar(const char* flag) {
+  const std::string full_flag =
+      (Message() << GTEST_FLAG_PREFIX_ << flag).GetString();
+
+  Message env_var;
+  for (size_t i = 0; i != full_flag.length(); i++) {
+    env_var << ToUpper(full_flag.c_str()[i]);
+  }
+
+  return env_var.GetString();
+}
+
+// Parses 'str' for a 32-bit signed integer.  If successful, writes
+// the result to *value and returns true; otherwise leaves *value
+// unchanged and returns false.
+bool ParseInt32(const Message& src_text, const char* str, Int32* value) {
+  // Parses the environment variable as a decimal integer.
+  char* end = NULL;
+  const long long_value = strtol(str, &end, 10);  // NOLINT
+
+  // Has strtol() consumed all characters in the string?
+  if (*end != '\0') {
+    // No - an invalid character was encountered.
+    Message msg;
+    msg << "WARNING: " << src_text
+        << " is expected to be a 32-bit integer, but actually"
+        << " has value \"" << str << "\".\n";
+    printf("%s", msg.GetString().c_str());
+    fflush(stdout);
+    return false;
+  }
+
+  // Is the parsed value in the range of an Int32?
+  const Int32 result = static_cast<Int32>(long_value);
+  if (long_value == LONG_MAX || long_value == LONG_MIN ||
+      // The parsed value overflows as a long.  (strtol() returns
+      // LONG_MAX or LONG_MIN when the input overflows.)
+      result != long_value
+      // The parsed value overflows as an Int32.
+      ) {
+    Message msg;
+    msg << "WARNING: " << src_text
+        << " is expected to be a 32-bit integer, but actually"
+        << " has value " << str << ", which overflows.\n";
+    printf("%s", msg.GetString().c_str());
+    fflush(stdout);
+    return false;
+  }
+
+  *value = result;
+  return true;
+}
+
+// Reads and returns the Boolean environment variable corresponding to
+// the given flag; if it's not set, returns default_value.
+//
+// The value is considered true iff it's not "0".
+bool BoolFromGTestEnv(const char* flag, bool default_value) {
+#if defined(GTEST_GET_BOOL_FROM_ENV_)
+  return GTEST_GET_BOOL_FROM_ENV_(flag, default_value);
+#endif  // defined(GTEST_GET_BOOL_FROM_ENV_)
+  const std::string env_var = FlagToEnvVar(flag);
+  const char* const string_value = posix::GetEnv(env_var.c_str());
+  return string_value == NULL ?
+      default_value : strcmp(string_value, "0") != 0;
+}
+
+// Reads and returns a 32-bit integer stored in the environment
+// variable corresponding to the given flag; if it isn't set or
+// doesn't represent a valid 32-bit integer, returns default_value.
+Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
+#if defined(GTEST_GET_INT32_FROM_ENV_)
+  return GTEST_GET_INT32_FROM_ENV_(flag, default_value);
+#endif  // defined(GTEST_GET_INT32_FROM_ENV_)
+  const std::string env_var = FlagToEnvVar(flag);
+  const char* const string_value = posix::GetEnv(env_var.c_str());
+  if (string_value == NULL) {
+    // The environment variable is not set.
+    return default_value;
+  }
+
+  Int32 result = default_value;
+  if (!ParseInt32(Message() << "Environment variable " << env_var,
+                  string_value, &result)) {
+    printf("The default value %s is used.\n",
+           (Message() << default_value).GetString().c_str());
+    fflush(stdout);
+    return default_value;
+  }
+
+  return result;
+}
+
+// Reads and returns the string environment variable corresponding to
+// the given flag; if it's not set, returns default_value.
+const char* StringFromGTestEnv(const char* flag, const char* default_value) {
+#if defined(GTEST_GET_STRING_FROM_ENV_)
+  return GTEST_GET_STRING_FROM_ENV_(flag, default_value);
+#endif  // defined(GTEST_GET_STRING_FROM_ENV_)
+  const std::string env_var = FlagToEnvVar(flag);
+  const char* const value = posix::GetEnv(env_var.c_str());
+  return value == NULL ? default_value : value;
+}
+
+}  // namespace internal
+}  // namespace testing
diff --git a/third_party/googletest/googletest/src/gtest-printers.cc b/third_party/googletest/googletest/src/gtest-printers.cc
new file mode 100644
index 0000000..a2df412
--- /dev/null
+++ b/third_party/googletest/googletest/src/gtest-printers.cc
@@ -0,0 +1,373 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Test - The Google C++ Testing Framework
+//
+// This file implements a universal value printer that can print a
+// value of any type T:
+//
+//   void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
+//
+// It uses the << operator when possible, and prints the bytes in the
+// object otherwise.  A user can override its behavior for a class
+// type Foo by defining either operator<<(::std::ostream&, const Foo&)
+// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that
+// defines Foo.
+
+#include "gtest/gtest-printers.h"
+#include <ctype.h>
+#include <stdio.h>
+#include <cwchar>
+#include <ostream>  // NOLINT
+#include <string>
+#include "gtest/internal/gtest-port.h"
+
+namespace testing {
+
+namespace {
+
+using ::std::ostream;
+
+// Prints a segment of bytes in the given object.
+GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
+GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
+GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
+void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
+                                size_t count, ostream* os) {
+  char text[5] = "";
+  for (size_t i = 0; i != count; i++) {
+    const size_t j = start + i;
+    if (i != 0) {
+      // Organizes the bytes into groups of 2 for easy parsing by
+      // human.
+      if ((j % 2) == 0)
+        *os << ' ';
+      else
+        *os << '-';
+    }
+    GTEST_SNPRINTF_(text, sizeof(text), "%02X", obj_bytes[j]);
+    *os << text;
+  }
+}
+
+// Prints the bytes in the given value to the given ostream.
+void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
+                              ostream* os) {
+  // Tells the user how big the object is.
+  *os << count << "-byte object <";
+
+  const size_t kThreshold = 132;
+  const size_t kChunkSize = 64;
+  // If the object size is bigger than kThreshold, we'll have to omit
+  // some details by printing only the first and the last kChunkSize
+  // bytes.
+  // TODO(wan): let the user control the threshold using a flag.
+  if (count < kThreshold) {
+    PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
+  } else {
+    PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os);
+    *os << " ... ";
+    // Rounds up to 2-byte boundary.
+    const size_t resume_pos = (count - kChunkSize + 1)/2*2;
+    PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os);
+  }
+  *os << ">";
+}
+
+}  // namespace
+
+namespace internal2 {
+
+// Delegates to PrintBytesInObjectToImpl() to print the bytes in the
+// given object.  The delegation simplifies the implementation, which
+// uses the << operator and thus is easier done outside of the
+// ::testing::internal namespace, which contains a << operator that
+// sometimes conflicts with the one in STL.
+void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count,
+                          ostream* os) {
+  PrintBytesInObjectToImpl(obj_bytes, count, os);
+}
+
+}  // namespace internal2
+
+namespace internal {
+
+// Depending on the value of a char (or wchar_t), we print it in one
+// of three formats:
+//   - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
+//   - as a hexidecimal escape sequence (e.g. '\x7F'), or
+//   - as a special escape sequence (e.g. '\r', '\n').
+enum CharFormat {
+  kAsIs,
+  kHexEscape,
+  kSpecialEscape
+};
+
+// Returns true if c is a printable ASCII character.  We test the
+// value of c directly instead of calling isprint(), which is buggy on
+// Windows Mobile.
+inline bool IsPrintableAscii(wchar_t c) {
+  return 0x20 <= c && c <= 0x7E;
+}
+
+// Prints a wide or narrow char c as a character literal without the
+// quotes, escaping it when necessary; returns how c was formatted.
+// The template argument UnsignedChar is the unsigned version of Char,
+// which is the type of c.
+template <typename UnsignedChar, typename Char>
+static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
+  switch (static_cast<wchar_t>(c)) {
+    case L'\0':
+      *os << "\\0";
+      break;
+    case L'\'':
+      *os << "\\'";
+      break;
+    case L'\\':
+      *os << "\\\\";
+      break;
+    case L'\a':
+      *os << "\\a";
+      break;
+    case L'\b':
+      *os << "\\b";
+      break;
+    case L'\f':
+      *os << "\\f";
+      break;
+    case L'\n':
+      *os << "\\n";
+      break;
+    case L'\r':
+      *os << "\\r";
+      break;
+    case L'\t':
+      *os << "\\t";
+      break;
+    case L'\v':
+      *os << "\\v";
+      break;
+    default:
+      if (IsPrintableAscii(c)) {
+        *os << static_cast<char>(c);
+        return kAsIs;
+      } else {
+        *os << "\\x" + String::FormatHexInt(static_cast<UnsignedChar>(c));
+        return kHexEscape;
+      }
+  }
+  return kSpecialEscape;
+}
+
+// Prints a wchar_t c as if it's part of a string literal, escaping it when
+// necessary; returns how c was formatted.
+static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) {
+  switch (c) {
+    case L'\'':
+      *os << "'";
+      return kAsIs;
+    case L'"':
+      *os << "\\\"";
+      return kSpecialEscape;
+    default:
+      return PrintAsCharLiteralTo<wchar_t>(c, os);
+  }
+}
+
+// Prints a char c as if it's part of a string literal, escaping it when
+// necessary; returns how c was formatted.
+static CharFormat PrintAsStringLiteralTo(char c, ostream* os) {
+  return PrintAsStringLiteralTo(
+      static_cast<wchar_t>(static_cast<unsigned char>(c)), os);
+}
+
+// Prints a wide or narrow character c and its code.  '\0' is printed
+// as "'\\0'", other unprintable characters are also properly escaped
+// using the standard C++ escape sequence.  The template argument
+// UnsignedChar is the unsigned version of Char, which is the type of c.
+template <typename UnsignedChar, typename Char>
+void PrintCharAndCodeTo(Char c, ostream* os) {
+  // First, print c as a literal in the most readable form we can find.
+  *os << ((sizeof(c) > 1) ? "L'" : "'");
+  const CharFormat format = PrintAsCharLiteralTo<UnsignedChar>(c, os);
+  *os << "'";
+
+  // To aid user debugging, we also print c's code in decimal, unless
+  // it's 0 (in which case c was printed as '\\0', making the code
+  // obvious).
+  if (c == 0)
+    return;
+  *os << " (" << static_cast<int>(c);
+
+  // For more convenience, we print c's code again in hexidecimal,
+  // unless c was already printed in the form '\x##' or the code is in
+  // [1, 9].
+  if (format == kHexEscape || (1 <= c && c <= 9)) {
+    // Do nothing.
+  } else {
+    *os << ", 0x" << String::FormatHexInt(static_cast<UnsignedChar>(c));
+  }
+  *os << ")";
+}
+
+void PrintTo(unsigned char c, ::std::ostream* os) {
+  PrintCharAndCodeTo<unsigned char>(c, os);
+}
+void PrintTo(signed char c, ::std::ostream* os) {
+  PrintCharAndCodeTo<unsigned char>(c, os);
+}
+
+// Prints a wchar_t as a symbol if it is printable or as its internal
+// code otherwise and also as its code.  L'\0' is printed as "L'\\0'".
+void PrintTo(wchar_t wc, ostream* os) {
+  PrintCharAndCodeTo<wchar_t>(wc, os);
+}
+
+// Prints the given array of characters to the ostream.  CharType must be either
+// char or wchar_t.
+// The array starts at begin, the length is len, it may include '\0' characters
+// and may not be NUL-terminated.
+template <typename CharType>
+GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
+GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
+GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
+static void PrintCharsAsStringTo(
+    const CharType* begin, size_t len, ostream* os) {
+  const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\"";
+  *os << kQuoteBegin;
+  bool is_previous_hex = false;
+  for (size_t index = 0; index < len; ++index) {
+    const CharType cur = begin[index];
+    if (is_previous_hex && IsXDigit(cur)) {
+      // Previous character is of '\x..' form and this character can be
+      // interpreted as another hexadecimal digit in its number. Break string to
+      // disambiguate.
+      *os << "\" " << kQuoteBegin;
+    }
+    is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape;
+  }
+  *os << "\"";
+}
+
+// Prints a (const) char/wchar_t array of 'len' elements, starting at address
+// 'begin'.  CharType must be either char or wchar_t.
+template <typename CharType>
+GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
+GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
+GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
+static void UniversalPrintCharArray(
+    const CharType* begin, size_t len, ostream* os) {
+  // The code
+  //   const char kFoo[] = "foo";
+  // generates an array of 4, not 3, elements, with the last one being '\0'.
+  //
+  // Therefore when printing a char array, we don't print the last element if
+  // it's '\0', such that the output matches the string literal as it's
+  // written in the source code.
+  if (len > 0 && begin[len - 1] == '\0') {
+    PrintCharsAsStringTo(begin, len - 1, os);
+    return;
+  }
+
+  // If, however, the last element in the array is not '\0', e.g.
+  //    const char kFoo[] = { 'f', 'o', 'o' };
+  // we must print the entire array.  We also print a message to indicate
+  // that the array is not NUL-terminated.
+  PrintCharsAsStringTo(begin, len, os);
+  *os << " (no terminating NUL)";
+}
+
+// Prints a (const) char array of 'len' elements, starting at address 'begin'.
+void UniversalPrintArray(const char* begin, size_t len, ostream* os) {
+  UniversalPrintCharArray(begin, len, os);
+}
+
+// Prints a (const) wchar_t array of 'len' elements, starting at address
+// 'begin'.
+void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) {
+  UniversalPrintCharArray(begin, len, os);
+}
+
+// Prints the given C string to the ostream.
+void PrintTo(const char* s, ostream* os) {
+  if (s == NULL) {
+    *os << "NULL";
+  } else {
+    *os << ImplicitCast_<const void*>(s) << " pointing to ";
+    PrintCharsAsStringTo(s, strlen(s), os);
+  }
+}
+
+// MSVC compiler can be configured to define whar_t as a typedef
+// of unsigned short. Defining an overload for const wchar_t* in that case
+// would cause pointers to unsigned shorts be printed as wide strings,
+// possibly accessing more memory than intended and causing invalid
+// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
+// wchar_t is implemented as a native type.
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+// Prints the given wide C string to the ostream.
+void PrintTo(const wchar_t* s, ostream* os) {
+  if (s == NULL) {
+    *os << "NULL";
+  } else {
+    *os << ImplicitCast_<const void*>(s) << " pointing to ";
+    PrintCharsAsStringTo(s, std::wcslen(s), os);
+  }
+}
+#endif  // wchar_t is native
+
+// Prints a ::string object.
+#if GTEST_HAS_GLOBAL_STRING
+void PrintStringTo(const ::string& s, ostream* os) {
+  PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+void PrintStringTo(const ::std::string& s, ostream* os) {
+  PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+
+// Prints a ::wstring object.
+#if GTEST_HAS_GLOBAL_WSTRING
+void PrintWideStringTo(const ::wstring& s, ostream* os) {
+  PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+#if GTEST_HAS_STD_WSTRING
+void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
+  PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+}  // namespace internal
+
+}  // namespace testing
diff --git a/third_party/googletest/googletest/src/gtest-test-part.cc b/third_party/googletest/googletest/src/gtest-test-part.cc
new file mode 100644
index 0000000..fb0e354
--- /dev/null
+++ b/third_party/googletest/googletest/src/gtest-test-part.cc
@@ -0,0 +1,110 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: mheule@google.com (Markus Heule)
+//
+// The Google C++ Testing Framework (Google Test)
+
+#include "gtest/gtest-test-part.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick exists to
+// prevent the accidental inclusion of gtest-internal-inl.h in the
+// user's code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+
+using internal::GetUnitTestImpl;
+
+// Gets the summary of the failure message by omitting the stack trace
+// in it.
+std::string TestPartResult::ExtractSummary(const char* message) {
+  const char* const stack_trace = strstr(message, internal::kStackTraceMarker);
+  return stack_trace == NULL ? message :
+      std::string(message, stack_trace);
+}
+
+// Prints a TestPartResult object.
+std::ostream& operator<<(std::ostream& os, const TestPartResult& result) {
+  return os
+      << result.file_name() << ":" << result.line_number() << ": "
+      << (result.type() == TestPartResult::kSuccess ? "Success" :
+          result.type() == TestPartResult::kFatalFailure ? "Fatal failure" :
+          "Non-fatal failure") << ":\n"
+      << result.message() << std::endl;
+}
+
+// Appends a TestPartResult to the array.
+void TestPartResultArray::Append(const TestPartResult& result) {
+  array_.push_back(result);
+}
+
+// Returns the TestPartResult at the given index (0-based).
+const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const {
+  if (index < 0 || index >= size()) {
+    printf("\nInvalid index (%d) into TestPartResultArray.\n", index);
+    internal::posix::Abort();
+  }
+
+  return array_[index];
+}
+
+// Returns the number of TestPartResult objects in the array.
+int TestPartResultArray::size() const {
+  return static_cast<int>(array_.size());
+}
+
+namespace internal {
+
+HasNewFatalFailureHelper::HasNewFatalFailureHelper()
+    : has_new_fatal_failure_(false),
+      original_reporter_(GetUnitTestImpl()->
+                         GetTestPartResultReporterForCurrentThread()) {
+  GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this);
+}
+
+HasNewFatalFailureHelper::~HasNewFatalFailureHelper() {
+  GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(
+      original_reporter_);
+}
+
+void HasNewFatalFailureHelper::ReportTestPartResult(
+    const TestPartResult& result) {
+  if (result.fatally_failed())
+    has_new_fatal_failure_ = true;
+  original_reporter_->ReportTestPartResult(result);
+}
+
+}  // namespace internal
+
+}  // namespace testing
diff --git a/third_party/googletest/googletest/src/gtest-typed-test.cc b/third_party/googletest/googletest/src/gtest-typed-test.cc
new file mode 100644
index 0000000..df1eef4
--- /dev/null
+++ b/third_party/googletest/googletest/src/gtest-typed-test.cc
@@ -0,0 +1,118 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include "gtest/gtest-typed-test.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+namespace internal {
+
+#if GTEST_HAS_TYPED_TEST_P
+
+// Skips to the first non-space char in str. Returns an empty string if str
+// contains only whitespace characters.
+static const char* SkipSpaces(const char* str) {
+  while (IsSpace(*str))
+    str++;
+  return str;
+}
+
+static std::vector<std::string> SplitIntoTestNames(const char* src) {
+  std::vector<std::string> name_vec;
+  src = SkipSpaces(src);
+  for (; src != NULL; src = SkipComma(src)) {
+    name_vec.push_back(StripTrailingSpaces(GetPrefixUntilComma(src)));
+  }
+  return name_vec;
+}
+
+// Verifies that registered_tests match the test names in
+// registered_tests_; returns registered_tests if successful, or
+// aborts the program otherwise.
+const char* TypedTestCasePState::VerifyRegisteredTestNames(
+    const char* file, int line, const char* registered_tests) {
+  typedef RegisteredTestsMap::const_iterator RegisteredTestIter;
+  registered_ = true;
+
+  std::vector<std::string> name_vec = SplitIntoTestNames(registered_tests);
+
+  Message errors;
+
+  std::set<std::string> tests;
+  for (std::vector<std::string>::const_iterator name_it = name_vec.begin();
+       name_it != name_vec.end(); ++name_it) {
+    const std::string& name = *name_it;
+    if (tests.count(name) != 0) {
+      errors << "Test " << name << " is listed more than once.\n";
+      continue;
+    }
+
+    bool found = false;
+    for (RegisteredTestIter it = registered_tests_.begin();
+         it != registered_tests_.end();
+         ++it) {
+      if (name == it->first) {
+        found = true;
+        break;
+      }
+    }
+
+    if (found) {
+      tests.insert(name);
+    } else {
+      errors << "No test named " << name
+             << " can be found in this test case.\n";
+    }
+  }
+
+  for (RegisteredTestIter it = registered_tests_.begin();
+       it != registered_tests_.end();
+       ++it) {
+    if (tests.count(it->first) == 0) {
+      errors << "You forgot to list test " << it->first << ".\n";
+    }
+  }
+
+  const std::string& errors_str = errors.GetString();
+  if (errors_str != "") {
+    fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(),
+            errors_str.c_str());
+    fflush(stderr);
+    posix::Abort();
+  }
+
+  return registered_tests;
+}
+
+#endif  // GTEST_HAS_TYPED_TEST_P
+
+}  // namespace internal
+}  // namespace testing
diff --git a/third_party/googletest/googletest/src/gtest.cc b/third_party/googletest/googletest/src/gtest.cc
new file mode 100644
index 0000000..4170e5c
--- /dev/null
+++ b/third_party/googletest/googletest/src/gtest.cc
@@ -0,0 +1,5386 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+
+#include "gtest/gtest.h"
+#include "gtest/internal/custom/gtest.h"
+#include "gtest/gtest-spi.h"
+
+#include <ctype.h>
+#include <math.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include <algorithm>
+#include <iomanip>
+#include <limits>
+#include <list>
+#include <map>
+#include <ostream>  // NOLINT
+#include <sstream>
+#include <vector>
+
+#if GTEST_OS_LINUX
+
+// TODO(kenton@google.com): Use autoconf to detect availability of
+// gettimeofday().
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+
+# include <fcntl.h>  // NOLINT
+# include <limits.h>  // NOLINT
+# include <sched.h>  // NOLINT
+// Declares vsnprintf().  This header is not available on Windows.
+# include <strings.h>  // NOLINT
+# include <sys/mman.h>  // NOLINT
+# include <sys/time.h>  // NOLINT
+# include <unistd.h>  // NOLINT
+# include <string>
+
+#elif GTEST_OS_SYMBIAN
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+# include <sys/time.h>  // NOLINT
+
+#elif GTEST_OS_ZOS
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+# include <sys/time.h>  // NOLINT
+
+// On z/OS we additionally need strings.h for strcasecmp.
+# include <strings.h>  // NOLINT
+
+#elif GTEST_OS_WINDOWS_MOBILE  // We are on Windows CE.
+
+# include <windows.h>  // NOLINT
+# undef min
+
+#elif GTEST_OS_WINDOWS  // We are on Windows proper.
+
+# include <io.h>  // NOLINT
+# include <sys/timeb.h>  // NOLINT
+# include <sys/types.h>  // NOLINT
+# include <sys/stat.h>  // NOLINT
+
+# if GTEST_OS_WINDOWS_MINGW
+// MinGW has gettimeofday() but not _ftime64().
+// TODO(kenton@google.com): Use autoconf to detect availability of
+//   gettimeofday().
+// TODO(kenton@google.com): There are other ways to get the time on
+//   Windows, like GetTickCount() or GetSystemTimeAsFileTime().  MinGW
+//   supports these.  consider using them instead.
+#  define GTEST_HAS_GETTIMEOFDAY_ 1
+#  include <sys/time.h>  // NOLINT
+# endif  // GTEST_OS_WINDOWS_MINGW
+
+// cpplint thinks that the header is already included, so we want to
+// silence it.
+# include <windows.h>  // NOLINT
+# undef min
+
+#else
+
+// Assume other platforms have gettimeofday().
+// TODO(kenton@google.com): Use autoconf to detect availability of
+//   gettimeofday().
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+
+// cpplint thinks that the header is already included, so we want to
+// silence it.
+# include <sys/time.h>  // NOLINT
+# include <unistd.h>  // NOLINT
+
+#endif  // GTEST_OS_LINUX
+
+#if GTEST_HAS_EXCEPTIONS
+# include <stdexcept>
+#endif
+
+#if GTEST_CAN_STREAM_RESULTS_
+# include <arpa/inet.h>  // NOLINT
+# include <netdb.h>  // NOLINT
+# include <sys/socket.h>  // NOLINT
+# include <sys/types.h>  // NOLINT
+#endif
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+#if GTEST_OS_WINDOWS
+# define vsnprintf _vsnprintf
+#endif  // GTEST_OS_WINDOWS
+
+namespace testing {
+
+using internal::CountIf;
+using internal::ForEach;
+using internal::GetElementOr;
+using internal::Shuffle;
+
+// Constants.
+
+// A test whose test case name or test name matches this filter is
+// disabled and not run.
+static const char kDisableTestFilter[] = "DISABLED_*:*/DISABLED_*";
+
+// A test case whose name matches this filter is considered a death
+// test case and will be run before test cases whose name doesn't
+// match this filter.
+static const char kDeathTestCaseFilter[] = "*DeathTest:*DeathTest/*";
+
+// A test filter that matches everything.
+static const char kUniversalFilter[] = "*";
+
+// The default output file for XML output.
+static const char kDefaultOutputFile[] = "test_detail.xml";
+
+// The environment variable name for the test shard index.
+static const char kTestShardIndex[] = "GTEST_SHARD_INDEX";
+// The environment variable name for the total number of test shards.
+static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS";
+// The environment variable name for the test shard status file.
+static const char kTestShardStatusFile[] = "GTEST_SHARD_STATUS_FILE";
+
+namespace internal {
+
+// The text used in failure messages to indicate the start of the
+// stack trace.
+const char kStackTraceMarker[] = "\nStack trace:\n";
+
+// g_help_flag is true iff the --help flag or an equivalent form is
+// specified on the command line.
+bool g_help_flag = false;
+
+}  // namespace internal
+
+static const char* GetDefaultFilter() {
+#ifdef GTEST_TEST_FILTER_ENV_VAR_
+  const char* const testbridge_test_only = getenv(GTEST_TEST_FILTER_ENV_VAR_);
+  if (testbridge_test_only != NULL) {
+    return testbridge_test_only;
+  }
+#endif  // GTEST_TEST_FILTER_ENV_VAR_
+  return kUniversalFilter;
+}
+
+GTEST_DEFINE_bool_(
+    also_run_disabled_tests,
+    internal::BoolFromGTestEnv("also_run_disabled_tests", false),
+    "Run disabled tests too, in addition to the tests normally being run.");
+
+GTEST_DEFINE_bool_(
+    break_on_failure,
+    internal::BoolFromGTestEnv("break_on_failure", false),
+    "True iff a failed assertion should be a debugger break-point.");
+
+GTEST_DEFINE_bool_(
+    catch_exceptions,
+    internal::BoolFromGTestEnv("catch_exceptions", true),
+    "True iff " GTEST_NAME_
+    " should catch exceptions and treat them as test failures.");
+
+GTEST_DEFINE_string_(
+    color,
+    internal::StringFromGTestEnv("color", "auto"),
+    "Whether to use colors in the output.  Valid values: yes, no, "
+    "and auto.  'auto' means to use colors if the output is "
+    "being sent to a terminal and the TERM environment variable "
+    "is set to a terminal type that supports colors.");
+
+GTEST_DEFINE_string_(
+    filter,
+    internal::StringFromGTestEnv("filter", GetDefaultFilter()),
+    "A colon-separated list of glob (not regex) patterns "
+    "for filtering the tests to run, optionally followed by a "
+    "'-' and a : separated list of negative patterns (tests to "
+    "exclude).  A test is run if it matches one of the positive "
+    "patterns and does not match any of the negative patterns.");
+
+GTEST_DEFINE_bool_(list_tests, false,
+                   "List all tests without running them.");
+
+GTEST_DEFINE_string_(
+    output,
+    internal::StringFromGTestEnv("output", ""),
+    "A format (currently must be \"xml\"), optionally followed "
+    "by a colon and an output file name or directory. A directory "
+    "is indicated by a trailing pathname separator. "
+    "Examples: \"xml:filename.xml\", \"xml::directoryname/\". "
+    "If a directory is specified, output files will be created "
+    "within that directory, with file-names based on the test "
+    "executable's name and, if necessary, made unique by adding "
+    "digits.");
+
+GTEST_DEFINE_bool_(
+    print_time,
+    internal::BoolFromGTestEnv("print_time", true),
+    "True iff " GTEST_NAME_
+    " should display elapsed time in text output.");
+
+GTEST_DEFINE_int32_(
+    random_seed,
+    internal::Int32FromGTestEnv("random_seed", 0),
+    "Random number seed to use when shuffling test orders.  Must be in range "
+    "[1, 99999], or 0 to use a seed based on the current time.");
+
+GTEST_DEFINE_int32_(
+    repeat,
+    internal::Int32FromGTestEnv("repeat", 1),
+    "How many times to repeat each test.  Specify a negative number "
+    "for repeating forever.  Useful for shaking out flaky tests.");
+
+GTEST_DEFINE_bool_(
+    show_internal_stack_frames, false,
+    "True iff " GTEST_NAME_ " should include internal stack frames when "
+    "printing test failure stack traces.");
+
+GTEST_DEFINE_bool_(
+    shuffle,
+    internal::BoolFromGTestEnv("shuffle", false),
+    "True iff " GTEST_NAME_
+    " should randomize tests' order on every run.");
+
+GTEST_DEFINE_int32_(
+    stack_trace_depth,
+    internal::Int32FromGTestEnv("stack_trace_depth", kMaxStackTraceDepth),
+    "The maximum number of stack frames to print when an "
+    "assertion fails.  The valid range is 0 through 100, inclusive.");
+
+GTEST_DEFINE_string_(
+    stream_result_to,
+    internal::StringFromGTestEnv("stream_result_to", ""),
+    "This flag specifies the host name and the port number on which to stream "
+    "test results. Example: \"localhost:555\". The flag is effective only on "
+    "Linux.");
+
+GTEST_DEFINE_bool_(
+    throw_on_failure,
+    internal::BoolFromGTestEnv("throw_on_failure", false),
+    "When this flag is specified, a failed assertion will throw an exception "
+    "if exceptions are enabled or exit the program with a non-zero code "
+    "otherwise.");
+
+#if GTEST_USE_OWN_FLAGFILE_FLAG_
+GTEST_DEFINE_string_(
+    flagfile,
+    internal::StringFromGTestEnv("flagfile", ""),
+    "This flag specifies the flagfile to read command-line flags from.");
+#endif  // GTEST_USE_OWN_FLAGFILE_FLAG_
+
+namespace internal {
+
+// Generates a random number from [0, range), using a Linear
+// Congruential Generator (LCG).  Crashes if 'range' is 0 or greater
+// than kMaxRange.
+UInt32 Random::Generate(UInt32 range) {
+  // These constants are the same as are used in glibc's rand(3).
+  state_ = (1103515245U*state_ + 12345U) % kMaxRange;
+
+  GTEST_CHECK_(range > 0)
+      << "Cannot generate a number in the range [0, 0).";
+  GTEST_CHECK_(range <= kMaxRange)
+      << "Generation of a number in [0, " << range << ") was requested, "
+      << "but this can only generate numbers in [0, " << kMaxRange << ").";
+
+  // Converting via modulus introduces a bit of downward bias, but
+  // it's simple, and a linear congruential generator isn't too good
+  // to begin with.
+  return state_ % range;
+}
+
+// GTestIsInitialized() returns true iff the user has initialized
+// Google Test.  Useful for catching the user mistake of not initializing
+// Google Test before calling RUN_ALL_TESTS().
+static bool GTestIsInitialized() { return GetArgvs().size() > 0; }
+
+// Iterates over a vector of TestCases, keeping a running sum of the
+// results of calling a given int-returning method on each.
+// Returns the sum.
+static int SumOverTestCaseList(const std::vector<TestCase*>& case_list,
+                               int (TestCase::*method)() const) {
+  int sum = 0;
+  for (size_t i = 0; i < case_list.size(); i++) {
+    sum += (case_list[i]->*method)();
+  }
+  return sum;
+}
+
+// Returns true iff the test case passed.
+static bool TestCasePassed(const TestCase* test_case) {
+  return test_case->should_run() && test_case->Passed();
+}
+
+// Returns true iff the test case failed.
+static bool TestCaseFailed(const TestCase* test_case) {
+  return test_case->should_run() && test_case->Failed();
+}
+
+// Returns true iff test_case contains at least one test that should
+// run.
+static bool ShouldRunTestCase(const TestCase* test_case) {
+  return test_case->should_run();
+}
+
+// AssertHelper constructor.
+AssertHelper::AssertHelper(TestPartResult::Type type,
+                           const char* file,
+                           int line,
+                           const char* message)
+    : data_(new AssertHelperData(type, file, line, message)) {
+}
+
+AssertHelper::~AssertHelper() {
+  delete data_;
+}
+
+// Message assignment, for assertion streaming support.
+void AssertHelper::operator=(const Message& message) const {
+  UnitTest::GetInstance()->
+    AddTestPartResult(data_->type, data_->file, data_->line,
+                      AppendUserMessage(data_->message, message),
+                      UnitTest::GetInstance()->impl()
+                      ->CurrentOsStackTraceExceptTop(1)
+                      // Skips the stack frame for this function itself.
+                      );  // NOLINT
+}
+
+// Mutex for linked pointers.
+GTEST_API_ GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex);
+
+// A copy of all command line arguments.  Set by InitGoogleTest().
+::std::vector<testing::internal::string> g_argvs;
+
+const ::std::vector<testing::internal::string>& GetArgvs() {
+#if defined(GTEST_CUSTOM_GET_ARGVS_)
+  return GTEST_CUSTOM_GET_ARGVS_();
+#else  // defined(GTEST_CUSTOM_GET_ARGVS_)
+  return g_argvs;
+#endif  // defined(GTEST_CUSTOM_GET_ARGVS_)
+}
+
+// Returns the current application's name, removing directory path if that
+// is present.
+FilePath GetCurrentExecutableName() {
+  FilePath result;
+
+#if GTEST_OS_WINDOWS
+  result.Set(FilePath(GetArgvs()[0]).RemoveExtension("exe"));
+#else
+  result.Set(FilePath(GetArgvs()[0]));
+#endif  // GTEST_OS_WINDOWS
+
+  return result.RemoveDirectoryName();
+}
+
+// Functions for processing the gtest_output flag.
+
+// Returns the output format, or "" for normal printed output.
+std::string UnitTestOptions::GetOutputFormat() {
+  const char* const gtest_output_flag = GTEST_FLAG(output).c_str();
+  if (gtest_output_flag == NULL) return std::string("");
+
+  const char* const colon = strchr(gtest_output_flag, ':');
+  return (colon == NULL) ?
+      std::string(gtest_output_flag) :
+      std::string(gtest_output_flag, colon - gtest_output_flag);
+}
+
+// Returns the name of the requested output file, or the default if none
+// was explicitly specified.
+std::string UnitTestOptions::GetAbsolutePathToOutputFile() {
+  const char* const gtest_output_flag = GTEST_FLAG(output).c_str();
+  if (gtest_output_flag == NULL)
+    return "";
+
+  const char* const colon = strchr(gtest_output_flag, ':');
+  if (colon == NULL)
+    return internal::FilePath::ConcatPaths(
+        internal::FilePath(
+            UnitTest::GetInstance()->original_working_dir()),
+        internal::FilePath(kDefaultOutputFile)).string();
+
+  internal::FilePath output_name(colon + 1);
+  if (!output_name.IsAbsolutePath())
+    // TODO(wan@google.com): on Windows \some\path is not an absolute
+    // path (as its meaning depends on the current drive), yet the
+    // following logic for turning it into an absolute path is wrong.
+    // Fix it.
+    output_name = internal::FilePath::ConcatPaths(
+        internal::FilePath(UnitTest::GetInstance()->original_working_dir()),
+        internal::FilePath(colon + 1));
+
+  if (!output_name.IsDirectory())
+    return output_name.string();
+
+  internal::FilePath result(internal::FilePath::GenerateUniqueFileName(
+      output_name, internal::GetCurrentExecutableName(),
+      GetOutputFormat().c_str()));
+  return result.string();
+}
+
+// Returns true iff the wildcard pattern matches the string.  The
+// first ':' or '\0' character in pattern marks the end of it.
+//
+// This recursive algorithm isn't very efficient, but is clear and
+// works well enough for matching test names, which are short.
+bool UnitTestOptions::PatternMatchesString(const char *pattern,
+                                           const char *str) {
+  switch (*pattern) {
+    case '\0':
+    case ':':  // Either ':' or '\0' marks the end of the pattern.
+      return *str == '\0';
+    case '?':  // Matches any single character.
+      return *str != '\0' && PatternMatchesString(pattern + 1, str + 1);
+    case '*':  // Matches any string (possibly empty) of characters.
+      return (*str != '\0' && PatternMatchesString(pattern, str + 1)) ||
+          PatternMatchesString(pattern + 1, str);
+    default:  // Non-special character.  Matches itself.
+      return *pattern == *str &&
+          PatternMatchesString(pattern + 1, str + 1);
+  }
+}
+
+bool UnitTestOptions::MatchesFilter(
+    const std::string& name, const char* filter) {
+  const char *cur_pattern = filter;
+  for (;;) {
+    if (PatternMatchesString(cur_pattern, name.c_str())) {
+      return true;
+    }
+
+    // Finds the next pattern in the filter.
+    cur_pattern = strchr(cur_pattern, ':');
+
+    // Returns if no more pattern can be found.
+    if (cur_pattern == NULL) {
+      return false;
+    }
+
+    // Skips the pattern separater (the ':' character).
+    cur_pattern++;
+  }
+}
+
+// Returns true iff the user-specified filter matches the test case
+// name and the test name.
+bool UnitTestOptions::FilterMatchesTest(const std::string &test_case_name,
+                                        const std::string &test_name) {
+  const std::string& full_name = test_case_name + "." + test_name.c_str();
+
+  // Split --gtest_filter at '-', if there is one, to separate into
+  // positive filter and negative filter portions
+  const char* const p = GTEST_FLAG(filter).c_str();
+  const char* const dash = strchr(p, '-');
+  std::string positive;
+  std::string negative;
+  if (dash == NULL) {
+    positive = GTEST_FLAG(filter).c_str();  // Whole string is a positive filter
+    negative = "";
+  } else {
+    positive = std::string(p, dash);   // Everything up to the dash
+    negative = std::string(dash + 1);  // Everything after the dash
+    if (positive.empty()) {
+      // Treat '-test1' as the same as '*-test1'
+      positive = kUniversalFilter;
+    }
+  }
+
+  // A filter is a colon-separated list of patterns.  It matches a
+  // test if any pattern in it matches the test.
+  return (MatchesFilter(full_name, positive.c_str()) &&
+          !MatchesFilter(full_name, negative.c_str()));
+}
+
+#if GTEST_HAS_SEH
+// Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
+// given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
+// This function is useful as an __except condition.
+int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) {
+  // Google Test should handle a SEH exception if:
+  //   1. the user wants it to, AND
+  //   2. this is not a breakpoint exception, AND
+  //   3. this is not a C++ exception (VC++ implements them via SEH,
+  //      apparently).
+  //
+  // SEH exception code for C++ exceptions.
+  // (see http://support.microsoft.com/kb/185294 for more information).
+  const DWORD kCxxExceptionCode = 0xe06d7363;
+
+  bool should_handle = true;
+
+  if (!GTEST_FLAG(catch_exceptions))
+    should_handle = false;
+  else if (exception_code == EXCEPTION_BREAKPOINT)
+    should_handle = false;
+  else if (exception_code == kCxxExceptionCode)
+    should_handle = false;
+
+  return should_handle ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
+}
+#endif  // GTEST_HAS_SEH
+
+}  // namespace internal
+
+// The c'tor sets this object as the test part result reporter used by
+// Google Test.  The 'result' parameter specifies where to report the
+// results. Intercepts only failures from the current thread.
+ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter(
+    TestPartResultArray* result)
+    : intercept_mode_(INTERCEPT_ONLY_CURRENT_THREAD),
+      result_(result) {
+  Init();
+}
+
+// The c'tor sets this object as the test part result reporter used by
+// Google Test.  The 'result' parameter specifies where to report the
+// results.
+ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter(
+    InterceptMode intercept_mode, TestPartResultArray* result)
+    : intercept_mode_(intercept_mode),
+      result_(result) {
+  Init();
+}
+
+void ScopedFakeTestPartResultReporter::Init() {
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  if (intercept_mode_ == INTERCEPT_ALL_THREADS) {
+    old_reporter_ = impl->GetGlobalTestPartResultReporter();
+    impl->SetGlobalTestPartResultReporter(this);
+  } else {
+    old_reporter_ = impl->GetTestPartResultReporterForCurrentThread();
+    impl->SetTestPartResultReporterForCurrentThread(this);
+  }
+}
+
+// The d'tor restores the test part result reporter used by Google Test
+// before.
+ScopedFakeTestPartResultReporter::~ScopedFakeTestPartResultReporter() {
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  if (intercept_mode_ == INTERCEPT_ALL_THREADS) {
+    impl->SetGlobalTestPartResultReporter(old_reporter_);
+  } else {
+    impl->SetTestPartResultReporterForCurrentThread(old_reporter_);
+  }
+}
+
+// Increments the test part result count and remembers the result.
+// This method is from the TestPartResultReporterInterface interface.
+void ScopedFakeTestPartResultReporter::ReportTestPartResult(
+    const TestPartResult& result) {
+  result_->Append(result);
+}
+
+namespace internal {
+
+// Returns the type ID of ::testing::Test.  We should always call this
+// instead of GetTypeId< ::testing::Test>() to get the type ID of
+// testing::Test.  This is to work around a suspected linker bug when
+// using Google Test as a framework on Mac OS X.  The bug causes
+// GetTypeId< ::testing::Test>() to return different values depending
+// on whether the call is from the Google Test framework itself or
+// from user test code.  GetTestTypeId() is guaranteed to always
+// return the same value, as it always calls GetTypeId<>() from the
+// gtest.cc, which is within the Google Test framework.
+TypeId GetTestTypeId() {
+  return GetTypeId<Test>();
+}
+
+// The value of GetTestTypeId() as seen from within the Google Test
+// library.  This is solely for testing GetTestTypeId().
+extern const TypeId kTestTypeIdInGoogleTest = GetTestTypeId();
+
+// This predicate-formatter checks that 'results' contains a test part
+// failure of the given type and that the failure message contains the
+// given substring.
+AssertionResult HasOneFailure(const char* /* results_expr */,
+                              const char* /* type_expr */,
+                              const char* /* substr_expr */,
+                              const TestPartResultArray& results,
+                              TestPartResult::Type type,
+                              const string& substr) {
+  const std::string expected(type == TestPartResult::kFatalFailure ?
+                        "1 fatal failure" :
+                        "1 non-fatal failure");
+  Message msg;
+  if (results.size() != 1) {
+    msg << "Expected: " << expected << "\n"
+        << "  Actual: " << results.size() << " failures";
+    for (int i = 0; i < results.size(); i++) {
+      msg << "\n" << results.GetTestPartResult(i);
+    }
+    return AssertionFailure() << msg;
+  }
+
+  const TestPartResult& r = results.GetTestPartResult(0);
+  if (r.type() != type) {
+    return AssertionFailure() << "Expected: " << expected << "\n"
+                              << "  Actual:\n"
+                              << r;
+  }
+
+  if (strstr(r.message(), substr.c_str()) == NULL) {
+    return AssertionFailure() << "Expected: " << expected << " containing \""
+                              << substr << "\"\n"
+                              << "  Actual:\n"
+                              << r;
+  }
+
+  return AssertionSuccess();
+}
+
+// The constructor of SingleFailureChecker remembers where to look up
+// test part results, what type of failure we expect, and what
+// substring the failure message should contain.
+SingleFailureChecker:: SingleFailureChecker(
+    const TestPartResultArray* results,
+    TestPartResult::Type type,
+    const string& substr)
+    : results_(results),
+      type_(type),
+      substr_(substr) {}
+
+// The destructor of SingleFailureChecker verifies that the given
+// TestPartResultArray contains exactly one failure that has the given
+// type and contains the given substring.  If that's not the case, a
+// non-fatal failure will be generated.
+SingleFailureChecker::~SingleFailureChecker() {
+  EXPECT_PRED_FORMAT3(HasOneFailure, *results_, type_, substr_);
+}
+
+DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter(
+    UnitTestImpl* unit_test) : unit_test_(unit_test) {}
+
+void DefaultGlobalTestPartResultReporter::ReportTestPartResult(
+    const TestPartResult& result) {
+  unit_test_->current_test_result()->AddTestPartResult(result);
+  unit_test_->listeners()->repeater()->OnTestPartResult(result);
+}
+
+DefaultPerThreadTestPartResultReporter::DefaultPerThreadTestPartResultReporter(
+    UnitTestImpl* unit_test) : unit_test_(unit_test) {}
+
+void DefaultPerThreadTestPartResultReporter::ReportTestPartResult(
+    const TestPartResult& result) {
+  unit_test_->GetGlobalTestPartResultReporter()->ReportTestPartResult(result);
+}
+
+// Returns the global test part result reporter.
+TestPartResultReporterInterface*
+UnitTestImpl::GetGlobalTestPartResultReporter() {
+  internal::MutexLock lock(&global_test_part_result_reporter_mutex_);
+  return global_test_part_result_repoter_;
+}
+
+// Sets the global test part result reporter.
+void UnitTestImpl::SetGlobalTestPartResultReporter(
+    TestPartResultReporterInterface* reporter) {
+  internal::MutexLock lock(&global_test_part_result_reporter_mutex_);
+  global_test_part_result_repoter_ = reporter;
+}
+
+// Returns the test part result reporter for the current thread.
+TestPartResultReporterInterface*
+UnitTestImpl::GetTestPartResultReporterForCurrentThread() {
+  return per_thread_test_part_result_reporter_.get();
+}
+
+// Sets the test part result reporter for the current thread.
+void UnitTestImpl::SetTestPartResultReporterForCurrentThread(
+    TestPartResultReporterInterface* reporter) {
+  per_thread_test_part_result_reporter_.set(reporter);
+}
+
+// Gets the number of successful test cases.
+int UnitTestImpl::successful_test_case_count() const {
+  return CountIf(test_cases_, TestCasePassed);
+}
+
+// Gets the number of failed test cases.
+int UnitTestImpl::failed_test_case_count() const {
+  return CountIf(test_cases_, TestCaseFailed);
+}
+
+// Gets the number of all test cases.
+int UnitTestImpl::total_test_case_count() const {
+  return static_cast<int>(test_cases_.size());
+}
+
+// Gets the number of all test cases that contain at least one test
+// that should run.
+int UnitTestImpl::test_case_to_run_count() const {
+  return CountIf(test_cases_, ShouldRunTestCase);
+}
+
+// Gets the number of successful tests.
+int UnitTestImpl::successful_test_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::successful_test_count);
+}
+
+// Gets the number of failed tests.
+int UnitTestImpl::failed_test_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::failed_test_count);
+}
+
+// Gets the number of disabled tests that will be reported in the XML report.
+int UnitTestImpl::reportable_disabled_test_count() const {
+  return SumOverTestCaseList(test_cases_,
+                             &TestCase::reportable_disabled_test_count);
+}
+
+// Gets the number of disabled tests.
+int UnitTestImpl::disabled_test_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::disabled_test_count);
+}
+
+// Gets the number of tests to be printed in the XML report.
+int UnitTestImpl::reportable_test_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::reportable_test_count);
+}
+
+// Gets the number of all tests.
+int UnitTestImpl::total_test_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::total_test_count);
+}
+
+// Gets the number of tests that should run.
+int UnitTestImpl::test_to_run_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::test_to_run_count);
+}
+
+// Returns the current OS stack trace as an std::string.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag.  The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// CurrentOsStackTraceExceptTop(1), Foo() will be included in the
+// trace but Bar() and CurrentOsStackTraceExceptTop() won't.
+std::string UnitTestImpl::CurrentOsStackTraceExceptTop(int skip_count) {
+  return os_stack_trace_getter()->CurrentStackTrace(
+      static_cast<int>(GTEST_FLAG(stack_trace_depth)),
+      skip_count + 1
+      // Skips the user-specified number of frames plus this function
+      // itself.
+      );  // NOLINT
+}
+
+// Returns the current time in milliseconds.
+TimeInMillis GetTimeInMillis() {
+#if GTEST_OS_WINDOWS_MOBILE || defined(__BORLANDC__)
+  // Difference between 1970-01-01 and 1601-01-01 in milliseconds.
+  // http://analogous.blogspot.com/2005/04/epoch.html
+  const TimeInMillis kJavaEpochToWinFileTimeDelta =
+    static_cast<TimeInMillis>(116444736UL) * 100000UL;
+  const DWORD kTenthMicrosInMilliSecond = 10000;
+
+  SYSTEMTIME now_systime;
+  FILETIME now_filetime;
+  ULARGE_INTEGER now_int64;
+  // TODO(kenton@google.com): Shouldn't this just use
+  //   GetSystemTimeAsFileTime()?
+  GetSystemTime(&now_systime);
+  if (SystemTimeToFileTime(&now_systime, &now_filetime)) {
+    now_int64.LowPart = now_filetime.dwLowDateTime;
+    now_int64.HighPart = now_filetime.dwHighDateTime;
+    now_int64.QuadPart = (now_int64.QuadPart / kTenthMicrosInMilliSecond) -
+      kJavaEpochToWinFileTimeDelta;
+    return now_int64.QuadPart;
+  }
+  return 0;
+#elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_
+  __timeb64 now;
+
+  // MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996
+  // (deprecated function) there.
+  // TODO(kenton@google.com): Use GetTickCount()?  Or use
+  //   SystemTimeToFileTime()
+  GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996)
+  _ftime64(&now);
+  GTEST_DISABLE_MSC_WARNINGS_POP_()
+
+  return static_cast<TimeInMillis>(now.time) * 1000 + now.millitm;
+#elif GTEST_HAS_GETTIMEOFDAY_
+  struct timeval now;
+  gettimeofday(&now, NULL);
+  return static_cast<TimeInMillis>(now.tv_sec) * 1000 + now.tv_usec / 1000;
+#else
+# error "Don't know how to get the current time on your system."
+#endif
+}
+
+// Utilities
+
+// class String.
+
+#if GTEST_OS_WINDOWS_MOBILE
+// Creates a UTF-16 wide string from the given ANSI string, allocating
+// memory using new. The caller is responsible for deleting the return
+// value using delete[]. Returns the wide string, or NULL if the
+// input is NULL.
+LPCWSTR String::AnsiToUtf16(const char* ansi) {
+  if (!ansi) return NULL;
+  const int length = strlen(ansi);
+  const int unicode_length =
+      MultiByteToWideChar(CP_ACP, 0, ansi, length,
+                          NULL, 0);
+  WCHAR* unicode = new WCHAR[unicode_length + 1];
+  MultiByteToWideChar(CP_ACP, 0, ansi, length,
+                      unicode, unicode_length);
+  unicode[unicode_length] = 0;
+  return unicode;
+}
+
+// Creates an ANSI string from the given wide string, allocating
+// memory using new. The caller is responsible for deleting the return
+// value using delete[]. Returns the ANSI string, or NULL if the
+// input is NULL.
+const char* String::Utf16ToAnsi(LPCWSTR utf16_str)  {
+  if (!utf16_str) return NULL;
+  const int ansi_length =
+      WideCharToMultiByte(CP_ACP, 0, utf16_str, -1,
+                          NULL, 0, NULL, NULL);
+  char* ansi = new char[ansi_length + 1];
+  WideCharToMultiByte(CP_ACP, 0, utf16_str, -1,
+                      ansi, ansi_length, NULL, NULL);
+  ansi[ansi_length] = 0;
+  return ansi;
+}
+
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+// Compares two C strings.  Returns true iff they have the same content.
+//
+// Unlike strcmp(), this function can handle NULL argument(s).  A NULL
+// C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::CStringEquals(const char * lhs, const char * rhs) {
+  if ( lhs == NULL ) return rhs == NULL;
+
+  if ( rhs == NULL ) return false;
+
+  return strcmp(lhs, rhs) == 0;
+}
+
+#if GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING
+
+// Converts an array of wide chars to a narrow string using the UTF-8
+// encoding, and streams the result to the given Message object.
+static void StreamWideCharsToMessage(const wchar_t* wstr, size_t length,
+                                     Message* msg) {
+  for (size_t i = 0; i != length; ) {  // NOLINT
+    if (wstr[i] != L'\0') {
+      *msg << WideStringToUtf8(wstr + i, static_cast<int>(length - i));
+      while (i != length && wstr[i] != L'\0')
+        i++;
+    } else {
+      *msg << '\0';
+      i++;
+    }
+  }
+}
+
+#endif  // GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING
+
+void SplitString(const ::std::string& str, char delimiter,
+                 ::std::vector< ::std::string>* dest) {
+  ::std::vector< ::std::string> parsed;
+  ::std::string::size_type pos = 0;
+  while (::testing::internal::AlwaysTrue()) {
+    const ::std::string::size_type colon = str.find(delimiter, pos);
+    if (colon == ::std::string::npos) {
+      parsed.push_back(str.substr(pos));
+      break;
+    } else {
+      parsed.push_back(str.substr(pos, colon - pos));
+      pos = colon + 1;
+    }
+  }
+  dest->swap(parsed);
+}
+
+}  // namespace internal
+
+// Constructs an empty Message.
+// We allocate the stringstream separately because otherwise each use of
+// ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's
+// stack frame leading to huge stack frames in some cases; gcc does not reuse
+// the stack space.
+Message::Message() : ss_(new ::std::stringstream) {
+  // By default, we want there to be enough precision when printing
+  // a double to a Message.
+  *ss_ << std::setprecision(std::numeric_limits<double>::digits10 + 2);
+}
+
+// These two overloads allow streaming a wide C string to a Message
+// using the UTF-8 encoding.
+Message& Message::operator <<(const wchar_t* wide_c_str) {
+  return *this << internal::String::ShowWideCString(wide_c_str);
+}
+Message& Message::operator <<(wchar_t* wide_c_str) {
+  return *this << internal::String::ShowWideCString(wide_c_str);
+}
+
+#if GTEST_HAS_STD_WSTRING
+// Converts the given wide string to a narrow string using the UTF-8
+// encoding, and streams the result to this Message object.
+Message& Message::operator <<(const ::std::wstring& wstr) {
+  internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this);
+  return *this;
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+// Converts the given wide string to a narrow string using the UTF-8
+// encoding, and streams the result to this Message object.
+Message& Message::operator <<(const ::wstring& wstr) {
+  internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this);
+  return *this;
+}
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+// Gets the text streamed to this object so far as an std::string.
+// Each '\0' character in the buffer is replaced with "\\0".
+std::string Message::GetString() const {
+  return internal::StringStreamToString(ss_.get());
+}
+
+// AssertionResult constructors.
+// Used in EXPECT_TRUE/FALSE(assertion_result).
+AssertionResult::AssertionResult(const AssertionResult& other)
+    : success_(other.success_),
+      message_(other.message_.get() != NULL ?
+               new ::std::string(*other.message_) :
+               static_cast< ::std::string*>(NULL)) {
+}
+
+// Swaps two AssertionResults.
+void AssertionResult::swap(AssertionResult& other) {
+  using std::swap;
+  swap(success_, other.success_);
+  swap(message_, other.message_);
+}
+
+// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
+AssertionResult AssertionResult::operator!() const {
+  AssertionResult negation(!success_);
+  if (message_.get() != NULL)
+    negation << *message_;
+  return negation;
+}
+
+// Makes a successful assertion result.
+AssertionResult AssertionSuccess() {
+  return AssertionResult(true);
+}
+
+// Makes a failed assertion result.
+AssertionResult AssertionFailure() {
+  return AssertionResult(false);
+}
+
+// Makes a failed assertion result with the given failure message.
+// Deprecated; use AssertionFailure() << message.
+AssertionResult AssertionFailure(const Message& message) {
+  return AssertionFailure() << message;
+}
+
+namespace internal {
+
+namespace edit_distance {
+std::vector<EditType> CalculateOptimalEdits(const std::vector<size_t>& left,
+                                            const std::vector<size_t>& right) {
+  std::vector<std::vector<double> > costs(
+      left.size() + 1, std::vector<double>(right.size() + 1));
+  std::vector<std::vector<EditType> > best_move(
+      left.size() + 1, std::vector<EditType>(right.size() + 1));
+
+  // Populate for empty right.
+  for (size_t l_i = 0; l_i < costs.size(); ++l_i) {
+    costs[l_i][0] = static_cast<double>(l_i);
+    best_move[l_i][0] = kRemove;
+  }
+  // Populate for empty left.
+  for (size_t r_i = 1; r_i < costs[0].size(); ++r_i) {
+    costs[0][r_i] = static_cast<double>(r_i);
+    best_move[0][r_i] = kAdd;
+  }
+
+  for (size_t l_i = 0; l_i < left.size(); ++l_i) {
+    for (size_t r_i = 0; r_i < right.size(); ++r_i) {
+      if (left[l_i] == right[r_i]) {
+        // Found a match. Consume it.
+        costs[l_i + 1][r_i + 1] = costs[l_i][r_i];
+        best_move[l_i + 1][r_i + 1] = kMatch;
+        continue;
+      }
+
+      const double add = costs[l_i + 1][r_i];
+      const double remove = costs[l_i][r_i + 1];
+      const double replace = costs[l_i][r_i];
+      if (add < remove && add < replace) {
+        costs[l_i + 1][r_i + 1] = add + 1;
+        best_move[l_i + 1][r_i + 1] = kAdd;
+      } else if (remove < add && remove < replace) {
+        costs[l_i + 1][r_i + 1] = remove + 1;
+        best_move[l_i + 1][r_i + 1] = kRemove;
+      } else {
+        // We make replace a little more expensive than add/remove to lower
+        // their priority.
+        costs[l_i + 1][r_i + 1] = replace + 1.00001;
+        best_move[l_i + 1][r_i + 1] = kReplace;
+      }
+    }
+  }
+
+  // Reconstruct the best path. We do it in reverse order.
+  std::vector<EditType> best_path;
+  for (size_t l_i = left.size(), r_i = right.size(); l_i > 0 || r_i > 0;) {
+    EditType move = best_move[l_i][r_i];
+    best_path.push_back(move);
+    l_i -= move != kAdd;
+    r_i -= move != kRemove;
+  }
+  std::reverse(best_path.begin(), best_path.end());
+  return best_path;
+}
+
+namespace {
+
+// Helper class to convert string into ids with deduplication.
+class InternalStrings {
+ public:
+  size_t GetId(const std::string& str) {
+    IdMap::iterator it = ids_.find(str);
+    if (it != ids_.end()) return it->second;
+    size_t id = ids_.size();
+    return ids_[str] = id;
+  }
+
+ private:
+  typedef std::map<std::string, size_t> IdMap;
+  IdMap ids_;
+};
+
+}  // namespace
+
+std::vector<EditType> CalculateOptimalEdits(
+    const std::vector<std::string>& left,
+    const std::vector<std::string>& right) {
+  std::vector<size_t> left_ids, right_ids;
+  {
+    InternalStrings intern_table;
+    for (size_t i = 0; i < left.size(); ++i) {
+      left_ids.push_back(intern_table.GetId(left[i]));
+    }
+    for (size_t i = 0; i < right.size(); ++i) {
+      right_ids.push_back(intern_table.GetId(right[i]));
+    }
+  }
+  return CalculateOptimalEdits(left_ids, right_ids);
+}
+
+namespace {
+
+// Helper class that holds the state for one hunk and prints it out to the
+// stream.
+// It reorders adds/removes when possible to group all removes before all
+// adds. It also adds the hunk header before printint into the stream.
+class Hunk {
+ public:
+  Hunk(size_t left_start, size_t right_start)
+      : left_start_(left_start),
+        right_start_(right_start),
+        adds_(),
+        removes_(),
+        common_() {}
+
+  void PushLine(char edit, const char* line) {
+    switch (edit) {
+      case ' ':
+        ++common_;
+        FlushEdits();
+        hunk_.push_back(std::make_pair(' ', line));
+        break;
+      case '-':
+        ++removes_;
+        hunk_removes_.push_back(std::make_pair('-', line));
+        break;
+      case '+':
+        ++adds_;
+        hunk_adds_.push_back(std::make_pair('+', line));
+        break;
+    }
+  }
+
+  void PrintTo(std::ostream* os) {
+    PrintHeader(os);
+    FlushEdits();
+    for (std::list<std::pair<char, const char*> >::const_iterator it =
+             hunk_.begin();
+         it != hunk_.end(); ++it) {
+      *os << it->first << it->second << "\n";
+    }
+  }
+
+  bool has_edits() const { return adds_ || removes_; }
+
+ private:
+  void FlushEdits() {
+    hunk_.splice(hunk_.end(), hunk_removes_);
+    hunk_.splice(hunk_.end(), hunk_adds_);
+  }
+
+  // Print a unified diff header for one hunk.
+  // The format is
+  //   "@@ -<left_start>,<left_length> +<right_start>,<right_length> @@"
+  // where the left/right parts are ommitted if unnecessary.
+  void PrintHeader(std::ostream* ss) const {
+    *ss << "@@ ";
+    if (removes_) {
+      *ss << "-" << left_start_ << "," << (removes_ + common_);
+    }
+    if (removes_ && adds_) {
+      *ss << " ";
+    }
+    if (adds_) {
+      *ss << "+" << right_start_ << "," << (adds_ + common_);
+    }
+    *ss << " @@\n";
+  }
+
+  size_t left_start_, right_start_;
+  size_t adds_, removes_, common_;
+  std::list<std::pair<char, const char*> > hunk_, hunk_adds_, hunk_removes_;
+};
+
+}  // namespace
+
+// Create a list of diff hunks in Unified diff format.
+// Each hunk has a header generated by PrintHeader above plus a body with
+// lines prefixed with ' ' for no change, '-' for deletion and '+' for
+// addition.
+// 'context' represents the desired unchanged prefix/suffix around the diff.
+// If two hunks are close enough that their contexts overlap, then they are
+// joined into one hunk.
+std::string CreateUnifiedDiff(const std::vector<std::string>& left,
+                              const std::vector<std::string>& right,
+                              size_t context) {
+  const std::vector<EditType> edits = CalculateOptimalEdits(left, right);
+
+  size_t l_i = 0, r_i = 0, edit_i = 0;
+  std::stringstream ss;
+  while (edit_i < edits.size()) {
+    // Find first edit.
+    while (edit_i < edits.size() && edits[edit_i] == kMatch) {
+      ++l_i;
+      ++r_i;
+      ++edit_i;
+    }
+
+    // Find the first line to include in the hunk.
+    const size_t prefix_context = std::min(l_i, context);
+    Hunk hunk(l_i - prefix_context + 1, r_i - prefix_context + 1);
+    for (size_t i = prefix_context; i > 0; --i) {
+      hunk.PushLine(' ', left[l_i - i].c_str());
+    }
+
+    // Iterate the edits until we found enough suffix for the hunk or the input
+    // is over.
+    size_t n_suffix = 0;
+    for (; edit_i < edits.size(); ++edit_i) {
+      if (n_suffix >= context) {
+        // Continue only if the next hunk is very close.
+        std::vector<EditType>::const_iterator it = edits.begin() + edit_i;
+        while (it != edits.end() && *it == kMatch) ++it;
+        if (it == edits.end() || (it - edits.begin()) - edit_i >= context) {
+          // There is no next edit or it is too far away.
+          break;
+        }
+      }
+
+      EditType edit = edits[edit_i];
+      // Reset count when a non match is found.
+      n_suffix = edit == kMatch ? n_suffix + 1 : 0;
+
+      if (edit == kMatch || edit == kRemove || edit == kReplace) {
+        hunk.PushLine(edit == kMatch ? ' ' : '-', left[l_i].c_str());
+      }
+      if (edit == kAdd || edit == kReplace) {
+        hunk.PushLine('+', right[r_i].c_str());
+      }
+
+      // Advance indices, depending on edit type.
+      l_i += edit != kAdd;
+      r_i += edit != kRemove;
+    }
+
+    if (!hunk.has_edits()) {
+      // We are done. We don't want this hunk.
+      break;
+    }
+
+    hunk.PrintTo(&ss);
+  }
+  return ss.str();
+}
+
+}  // namespace edit_distance
+
+namespace {
+
+// The string representation of the values received in EqFailure() are already
+// escaped. Split them on escaped '\n' boundaries. Leave all other escaped
+// characters the same.
+std::vector<std::string> SplitEscapedString(const std::string& str) {
+  std::vector<std::string> lines;
+  size_t start = 0, end = str.size();
+  if (end > 2 && str[0] == '"' && str[end - 1] == '"') {
+    ++start;
+    --end;
+  }
+  bool escaped = false;
+  for (size_t i = start; i + 1 < end; ++i) {
+    if (escaped) {
+      escaped = false;
+      if (str[i] == 'n') {
+        lines.push_back(str.substr(start, i - start - 1));
+        start = i + 1;
+      }
+    } else {
+      escaped = str[i] == '\\';
+    }
+  }
+  lines.push_back(str.substr(start, end - start));
+  return lines;
+}
+
+}  // namespace
+
+// Constructs and returns the message for an equality assertion
+// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
+//
+// The first four parameters are the expressions used in the assertion
+// and their values, as strings.  For example, for ASSERT_EQ(foo, bar)
+// where foo is 5 and bar is 6, we have:
+//
+//   expected_expression: "foo"
+//   actual_expression:   "bar"
+//   expected_value:      "5"
+//   actual_value:        "6"
+//
+// The ignoring_case parameter is true iff the assertion is a
+// *_STRCASEEQ*.  When it's true, the string " (ignoring case)" will
+// be inserted into the message.
+AssertionResult EqFailure(const char* expected_expression,
+                          const char* actual_expression,
+                          const std::string& expected_value,
+                          const std::string& actual_value,
+                          bool ignoring_case) {
+  Message msg;
+  msg << "Value of: " << actual_expression;
+  if (actual_value != actual_expression) {
+    msg << "\n  Actual: " << actual_value;
+  }
+
+  msg << "\nExpected: " << expected_expression;
+  if (ignoring_case) {
+    msg << " (ignoring case)";
+  }
+  if (expected_value != expected_expression) {
+    msg << "\nWhich is: " << expected_value;
+  }
+
+  if (!expected_value.empty() && !actual_value.empty()) {
+    const std::vector<std::string> expected_lines =
+        SplitEscapedString(expected_value);
+    const std::vector<std::string> actual_lines =
+        SplitEscapedString(actual_value);
+    if (expected_lines.size() > 1 || actual_lines.size() > 1) {
+      msg << "\nWith diff:\n"
+          << edit_distance::CreateUnifiedDiff(expected_lines, actual_lines);
+    }
+  }
+
+  return AssertionFailure() << msg;
+}
+
+// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
+std::string GetBoolAssertionFailureMessage(
+    const AssertionResult& assertion_result,
+    const char* expression_text,
+    const char* actual_predicate_value,
+    const char* expected_predicate_value) {
+  const char* actual_message = assertion_result.message();
+  Message msg;
+  msg << "Value of: " << expression_text
+      << "\n  Actual: " << actual_predicate_value;
+  if (actual_message[0] != '\0')
+    msg << " (" << actual_message << ")";
+  msg << "\nExpected: " << expected_predicate_value;
+  return msg.GetString();
+}
+
+// Helper function for implementing ASSERT_NEAR.
+AssertionResult DoubleNearPredFormat(const char* expr1,
+                                     const char* expr2,
+                                     const char* abs_error_expr,
+                                     double val1,
+                                     double val2,
+                                     double abs_error) {
+  const double diff = fabs(val1 - val2);
+  if (diff <= abs_error) return AssertionSuccess();
+
+  // TODO(wan): do not print the value of an expression if it's
+  // already a literal.
+  return AssertionFailure()
+      << "The difference between " << expr1 << " and " << expr2
+      << " is " << diff << ", which exceeds " << abs_error_expr << ", where\n"
+      << expr1 << " evaluates to " << val1 << ",\n"
+      << expr2 << " evaluates to " << val2 << ", and\n"
+      << abs_error_expr << " evaluates to " << abs_error << ".";
+}
+
+
+// Helper template for implementing FloatLE() and DoubleLE().
+template <typename RawType>
+AssertionResult FloatingPointLE(const char* expr1,
+                                const char* expr2,
+                                RawType val1,
+                                RawType val2) {
+  // Returns success if val1 is less than val2,
+  if (val1 < val2) {
+    return AssertionSuccess();
+  }
+
+  // or if val1 is almost equal to val2.
+  const FloatingPoint<RawType> lhs(val1), rhs(val2);
+  if (lhs.AlmostEquals(rhs)) {
+    return AssertionSuccess();
+  }
+
+  // Note that the above two checks will both fail if either val1 or
+  // val2 is NaN, as the IEEE floating-point standard requires that
+  // any predicate involving a NaN must return false.
+
+  ::std::stringstream val1_ss;
+  val1_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+          << val1;
+
+  ::std::stringstream val2_ss;
+  val2_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+          << val2;
+
+  return AssertionFailure()
+      << "Expected: (" << expr1 << ") <= (" << expr2 << ")\n"
+      << "  Actual: " << StringStreamToString(&val1_ss) << " vs "
+      << StringStreamToString(&val2_ss);
+}
+
+}  // namespace internal
+
+// Asserts that val1 is less than, or almost equal to, val2.  Fails
+// otherwise.  In particular, it fails if either val1 or val2 is NaN.
+AssertionResult FloatLE(const char* expr1, const char* expr2,
+                        float val1, float val2) {
+  return internal::FloatingPointLE<float>(expr1, expr2, val1, val2);
+}
+
+// Asserts that val1 is less than, or almost equal to, val2.  Fails
+// otherwise.  In particular, it fails if either val1 or val2 is NaN.
+AssertionResult DoubleLE(const char* expr1, const char* expr2,
+                         double val1, double val2) {
+  return internal::FloatingPointLE<double>(expr1, expr2, val1, val2);
+}
+
+namespace internal {
+
+// The helper function for {ASSERT|EXPECT}_EQ with int or enum
+// arguments.
+AssertionResult CmpHelperEQ(const char* expected_expression,
+                            const char* actual_expression,
+                            BiggestInt expected,
+                            BiggestInt actual) {
+  if (expected == actual) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   FormatForComparisonFailureMessage(expected, actual),
+                   FormatForComparisonFailureMessage(actual, expected),
+                   false);
+}
+
+// A macro for implementing the helper functions needed to implement
+// ASSERT_?? and EXPECT_?? with integer or enum arguments.  It is here
+// just to avoid copy-and-paste of similar code.
+#define GTEST_IMPL_CMP_HELPER_(op_name, op)\
+AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
+                                   BiggestInt val1, BiggestInt val2) {\
+  if (val1 op val2) {\
+    return AssertionSuccess();\
+  } else {\
+    return AssertionFailure() \
+        << "Expected: (" << expr1 << ") " #op " (" << expr2\
+        << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\
+        << " vs " << FormatForComparisonFailureMessage(val2, val1);\
+  }\
+}
+
+// Implements the helper function for {ASSERT|EXPECT}_NE with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(NE, !=)
+// Implements the helper function for {ASSERT|EXPECT}_LE with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(LE, <=)
+// Implements the helper function for {ASSERT|EXPECT}_LT with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(LT, < )
+// Implements the helper function for {ASSERT|EXPECT}_GE with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(GE, >=)
+// Implements the helper function for {ASSERT|EXPECT}_GT with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(GT, > )
+
+#undef GTEST_IMPL_CMP_HELPER_
+
+// The helper function for {ASSERT|EXPECT}_STREQ.
+AssertionResult CmpHelperSTREQ(const char* expected_expression,
+                               const char* actual_expression,
+                               const char* expected,
+                               const char* actual) {
+  if (String::CStringEquals(expected, actual)) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   PrintToString(expected),
+                   PrintToString(actual),
+                   false);
+}
+
+// The helper function for {ASSERT|EXPECT}_STRCASEEQ.
+AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression,
+                                   const char* actual_expression,
+                                   const char* expected,
+                                   const char* actual) {
+  if (String::CaseInsensitiveCStringEquals(expected, actual)) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   PrintToString(expected),
+                   PrintToString(actual),
+                   true);
+}
+
+// The helper function for {ASSERT|EXPECT}_STRNE.
+AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                               const char* s2_expression,
+                               const char* s1,
+                               const char* s2) {
+  if (!String::CStringEquals(s1, s2)) {
+    return AssertionSuccess();
+  } else {
+    return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
+                              << s2_expression << "), actual: \""
+                              << s1 << "\" vs \"" << s2 << "\"";
+  }
+}
+
+// The helper function for {ASSERT|EXPECT}_STRCASENE.
+AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
+                                   const char* s2_expression,
+                                   const char* s1,
+                                   const char* s2) {
+  if (!String::CaseInsensitiveCStringEquals(s1, s2)) {
+    return AssertionSuccess();
+  } else {
+    return AssertionFailure()
+        << "Expected: (" << s1_expression << ") != ("
+        << s2_expression << ") (ignoring case), actual: \""
+        << s1 << "\" vs \"" << s2 << "\"";
+  }
+}
+
+}  // namespace internal
+
+namespace {
+
+// Helper functions for implementing IsSubString() and IsNotSubstring().
+
+// This group of overloaded functions return true iff needle is a
+// substring of haystack.  NULL is considered a substring of itself
+// only.
+
+bool IsSubstringPred(const char* needle, const char* haystack) {
+  if (needle == NULL || haystack == NULL)
+    return needle == haystack;
+
+  return strstr(haystack, needle) != NULL;
+}
+
+bool IsSubstringPred(const wchar_t* needle, const wchar_t* haystack) {
+  if (needle == NULL || haystack == NULL)
+    return needle == haystack;
+
+  return wcsstr(haystack, needle) != NULL;
+}
+
+// StringType here can be either ::std::string or ::std::wstring.
+template <typename StringType>
+bool IsSubstringPred(const StringType& needle,
+                     const StringType& haystack) {
+  return haystack.find(needle) != StringType::npos;
+}
+
+// This function implements either IsSubstring() or IsNotSubstring(),
+// depending on the value of the expected_to_be_substring parameter.
+// StringType here can be const char*, const wchar_t*, ::std::string,
+// or ::std::wstring.
+template <typename StringType>
+AssertionResult IsSubstringImpl(
+    bool expected_to_be_substring,
+    const char* needle_expr, const char* haystack_expr,
+    const StringType& needle, const StringType& haystack) {
+  if (IsSubstringPred(needle, haystack) == expected_to_be_substring)
+    return AssertionSuccess();
+
+  const bool is_wide_string = sizeof(needle[0]) > 1;
+  const char* const begin_string_quote = is_wide_string ? "L\"" : "\"";
+  return AssertionFailure()
+      << "Value of: " << needle_expr << "\n"
+      << "  Actual: " << begin_string_quote << needle << "\"\n"
+      << "Expected: " << (expected_to_be_substring ? "" : "not ")
+      << "a substring of " << haystack_expr << "\n"
+      << "Which is: " << begin_string_quote << haystack << "\"";
+}
+
+}  // namespace
+
+// IsSubstring() and IsNotSubstring() check whether needle is a
+// substring of haystack (NULL is considered a substring of itself
+// only), and return an appropriate error message when they fail.
+
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+#if GTEST_HAS_STD_WSTRING
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+namespace internal {
+
+#if GTEST_OS_WINDOWS
+
+namespace {
+
+// Helper function for IsHRESULT{SuccessFailure} predicates
+AssertionResult HRESULTFailureHelper(const char* expr,
+                                     const char* expected,
+                                     long hr) {  // NOLINT
+# if GTEST_OS_WINDOWS_MOBILE
+
+  // Windows CE doesn't support FormatMessage.
+  const char error_text[] = "";
+
+# else
+
+  // Looks up the human-readable system message for the HRESULT code
+  // and since we're not passing any params to FormatMessage, we don't
+  // want inserts expanded.
+  const DWORD kFlags = FORMAT_MESSAGE_FROM_SYSTEM |
+                       FORMAT_MESSAGE_IGNORE_INSERTS;
+  const DWORD kBufSize = 4096;
+  // Gets the system's human readable message string for this HRESULT.
+  char error_text[kBufSize] = { '\0' };
+  DWORD message_length = ::FormatMessageA(kFlags,
+                                          0,  // no source, we're asking system
+                                          hr,  // the error
+                                          0,  // no line width restrictions
+                                          error_text,  // output buffer
+                                          kBufSize,  // buf size
+                                          NULL);  // no arguments for inserts
+  // Trims tailing white space (FormatMessage leaves a trailing CR-LF)
+  for (; message_length && IsSpace(error_text[message_length - 1]);
+          --message_length) {
+    error_text[message_length - 1] = '\0';
+  }
+
+# endif  // GTEST_OS_WINDOWS_MOBILE
+
+  const std::string error_hex("0x" + String::FormatHexInt(hr));
+  return ::testing::AssertionFailure()
+      << "Expected: " << expr << " " << expected << ".\n"
+      << "  Actual: " << error_hex << " " << error_text << "\n";
+}
+
+}  // namespace
+
+AssertionResult IsHRESULTSuccess(const char* expr, long hr) {  // NOLINT
+  if (SUCCEEDED(hr)) {
+    return AssertionSuccess();
+  }
+  return HRESULTFailureHelper(expr, "succeeds", hr);
+}
+
+AssertionResult IsHRESULTFailure(const char* expr, long hr) {  // NOLINT
+  if (FAILED(hr)) {
+    return AssertionSuccess();
+  }
+  return HRESULTFailureHelper(expr, "fails", hr);
+}
+
+#endif  // GTEST_OS_WINDOWS
+
+// Utility functions for encoding Unicode text (wide strings) in
+// UTF-8.
+
+// A Unicode code-point can have upto 21 bits, and is encoded in UTF-8
+// like this:
+//
+// Code-point length   Encoding
+//   0 -  7 bits       0xxxxxxx
+//   8 - 11 bits       110xxxxx 10xxxxxx
+//  12 - 16 bits       1110xxxx 10xxxxxx 10xxxxxx
+//  17 - 21 bits       11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+
+// The maximum code-point a one-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint1 = (static_cast<UInt32>(1) <<  7) - 1;
+
+// The maximum code-point a two-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint2 = (static_cast<UInt32>(1) << (5 + 6)) - 1;
+
+// The maximum code-point a three-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint3 = (static_cast<UInt32>(1) << (4 + 2*6)) - 1;
+
+// The maximum code-point a four-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint4 = (static_cast<UInt32>(1) << (3 + 3*6)) - 1;
+
+// Chops off the n lowest bits from a bit pattern.  Returns the n
+// lowest bits.  As a side effect, the original bit pattern will be
+// shifted to the right by n bits.
+inline UInt32 ChopLowBits(UInt32* bits, int n) {
+  const UInt32 low_bits = *bits & ((static_cast<UInt32>(1) << n) - 1);
+  *bits >>= n;
+  return low_bits;
+}
+
+// Converts a Unicode code point to a narrow string in UTF-8 encoding.
+// code_point parameter is of type UInt32 because wchar_t may not be
+// wide enough to contain a code point.
+// If the code_point is not a valid Unicode code point
+// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted
+// to "(Invalid Unicode 0xXXXXXXXX)".
+std::string CodePointToUtf8(UInt32 code_point) {
+  if (code_point > kMaxCodePoint4) {
+    return "(Invalid Unicode 0x" + String::FormatHexInt(code_point) + ")";
+  }
+
+  char str[5];  // Big enough for the largest valid code point.
+  if (code_point <= kMaxCodePoint1) {
+    str[1] = '\0';
+    str[0] = static_cast<char>(code_point);                          // 0xxxxxxx
+  } else if (code_point <= kMaxCodePoint2) {
+    str[2] = '\0';
+    str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[0] = static_cast<char>(0xC0 | code_point);                   // 110xxxxx
+  } else if (code_point <= kMaxCodePoint3) {
+    str[3] = '\0';
+    str[2] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[0] = static_cast<char>(0xE0 | code_point);                   // 1110xxxx
+  } else {  // code_point <= kMaxCodePoint4
+    str[4] = '\0';
+    str[3] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[2] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[0] = static_cast<char>(0xF0 | code_point);                   // 11110xxx
+  }
+  return str;
+}
+
+// The following two functions only make sense if the the system
+// uses UTF-16 for wide string encoding. All supported systems
+// with 16 bit wchar_t (Windows, Cygwin, Symbian OS) do use UTF-16.
+
+// Determines if the arguments constitute UTF-16 surrogate pair
+// and thus should be combined into a single Unicode code point
+// using CreateCodePointFromUtf16SurrogatePair.
+inline bool IsUtf16SurrogatePair(wchar_t first, wchar_t second) {
+  return sizeof(wchar_t) == 2 &&
+      (first & 0xFC00) == 0xD800 && (second & 0xFC00) == 0xDC00;
+}
+
+// Creates a Unicode code point from UTF16 surrogate pair.
+inline UInt32 CreateCodePointFromUtf16SurrogatePair(wchar_t first,
+                                                    wchar_t second) {
+  const UInt32 mask = (1 << 10) - 1;
+  return (sizeof(wchar_t) == 2) ?
+      (((first & mask) << 10) | (second & mask)) + 0x10000 :
+      // This function should not be called when the condition is
+      // false, but we provide a sensible default in case it is.
+      static_cast<UInt32>(first);
+}
+
+// Converts a wide string to a narrow string in UTF-8 encoding.
+// The wide string is assumed to have the following encoding:
+//   UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS)
+//   UTF-32 if sizeof(wchar_t) == 4 (on Linux)
+// Parameter str points to a null-terminated wide string.
+// Parameter num_chars may additionally limit the number
+// of wchar_t characters processed. -1 is used when the entire string
+// should be processed.
+// If the string contains code points that are not valid Unicode code points
+// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding
+// and contains invalid UTF-16 surrogate pairs, values in those pairs
+// will be encoded as individual Unicode characters from Basic Normal Plane.
+std::string WideStringToUtf8(const wchar_t* str, int num_chars) {
+  if (num_chars == -1)
+    num_chars = static_cast<int>(wcslen(str));
+
+  ::std::stringstream stream;
+  for (int i = 0; i < num_chars; ++i) {
+    UInt32 unicode_code_point;
+
+    if (str[i] == L'\0') {
+      break;
+    } else if (i + 1 < num_chars && IsUtf16SurrogatePair(str[i], str[i + 1])) {
+      unicode_code_point = CreateCodePointFromUtf16SurrogatePair(str[i],
+                                                                 str[i + 1]);
+      i++;
+    } else {
+      unicode_code_point = static_cast<UInt32>(str[i]);
+    }
+
+    stream << CodePointToUtf8(unicode_code_point);
+  }
+  return StringStreamToString(&stream);
+}
+
+// Converts a wide C string to an std::string using the UTF-8 encoding.
+// NULL will be converted to "(null)".
+std::string String::ShowWideCString(const wchar_t * wide_c_str) {
+  if (wide_c_str == NULL)  return "(null)";
+
+  return internal::WideStringToUtf8(wide_c_str, -1);
+}
+
+// Compares two wide C strings.  Returns true iff they have the same
+// content.
+//
+// Unlike wcscmp(), this function can handle NULL argument(s).  A NULL
+// C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::WideCStringEquals(const wchar_t * lhs, const wchar_t * rhs) {
+  if (lhs == NULL) return rhs == NULL;
+
+  if (rhs == NULL) return false;
+
+  return wcscmp(lhs, rhs) == 0;
+}
+
+// Helper function for *_STREQ on wide strings.
+AssertionResult CmpHelperSTREQ(const char* expected_expression,
+                               const char* actual_expression,
+                               const wchar_t* expected,
+                               const wchar_t* actual) {
+  if (String::WideCStringEquals(expected, actual)) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   PrintToString(expected),
+                   PrintToString(actual),
+                   false);
+}
+
+// Helper function for *_STRNE on wide strings.
+AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                               const char* s2_expression,
+                               const wchar_t* s1,
+                               const wchar_t* s2) {
+  if (!String::WideCStringEquals(s1, s2)) {
+    return AssertionSuccess();
+  }
+
+  return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
+                            << s2_expression << "), actual: "
+                            << PrintToString(s1)
+                            << " vs " << PrintToString(s2);
+}
+
+// Compares two C strings, ignoring case.  Returns true iff they have
+// the same content.
+//
+// Unlike strcasecmp(), this function can handle NULL argument(s).  A
+// NULL C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::CaseInsensitiveCStringEquals(const char * lhs, const char * rhs) {
+  if (lhs == NULL)
+    return rhs == NULL;
+  if (rhs == NULL)
+    return false;
+  return posix::StrCaseCmp(lhs, rhs) == 0;
+}
+
+  // Compares two wide C strings, ignoring case.  Returns true iff they
+  // have the same content.
+  //
+  // Unlike wcscasecmp(), this function can handle NULL argument(s).
+  // A NULL C string is considered different to any non-NULL wide C string,
+  // including the empty string.
+  // NB: The implementations on different platforms slightly differ.
+  // On windows, this method uses _wcsicmp which compares according to LC_CTYPE
+  // environment variable. On GNU platform this method uses wcscasecmp
+  // which compares according to LC_CTYPE category of the current locale.
+  // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
+  // current locale.
+bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
+                                              const wchar_t* rhs) {
+  if (lhs == NULL) return rhs == NULL;
+
+  if (rhs == NULL) return false;
+
+#if GTEST_OS_WINDOWS
+  return _wcsicmp(lhs, rhs) == 0;
+#elif GTEST_OS_LINUX && !GTEST_OS_LINUX_ANDROID
+  return wcscasecmp(lhs, rhs) == 0;
+#else
+  // Android, Mac OS X and Cygwin don't define wcscasecmp.
+  // Other unknown OSes may not define it either.
+  wint_t left, right;
+  do {
+    left = towlower(*lhs++);
+    right = towlower(*rhs++);
+  } while (left && left == right);
+  return left == right;
+#endif  // OS selector
+}
+
+// Returns true iff str ends with the given suffix, ignoring case.
+// Any string is considered to end with an empty suffix.
+bool String::EndsWithCaseInsensitive(
+    const std::string& str, const std::string& suffix) {
+  const size_t str_len = str.length();
+  const size_t suffix_len = suffix.length();
+  return (str_len >= suffix_len) &&
+         CaseInsensitiveCStringEquals(str.c_str() + str_len - suffix_len,
+                                      suffix.c_str());
+}
+
+// Formats an int value as "%02d".
+std::string String::FormatIntWidth2(int value) {
+  std::stringstream ss;
+  ss << std::setfill('0') << std::setw(2) << value;
+  return ss.str();
+}
+
+// Formats an int value as "%X".
+std::string String::FormatHexInt(int value) {
+  std::stringstream ss;
+  ss << std::hex << std::uppercase << value;
+  return ss.str();
+}
+
+// Formats a byte as "%02X".
+std::string String::FormatByte(unsigned char value) {
+  std::stringstream ss;
+  ss << std::setfill('0') << std::setw(2) << std::hex << std::uppercase
+     << static_cast<unsigned int>(value);
+  return ss.str();
+}
+
+// Converts the buffer in a stringstream to an std::string, converting NUL
+// bytes to "\\0" along the way.
+std::string StringStreamToString(::std::stringstream* ss) {
+  const ::std::string& str = ss->str();
+  const char* const start = str.c_str();
+  const char* const end = start + str.length();
+
+  std::string result;
+  result.reserve(2 * (end - start));
+  for (const char* ch = start; ch != end; ++ch) {
+    if (*ch == '\0') {
+      result += "\\0";  // Replaces NUL with "\\0";
+    } else {
+      result += *ch;
+    }
+  }
+
+  return result;
+}
+
+// Appends the user-supplied message to the Google-Test-generated message.
+std::string AppendUserMessage(const std::string& gtest_msg,
+                              const Message& user_msg) {
+  // Appends the user message if it's non-empty.
+  const std::string user_msg_string = user_msg.GetString();
+  if (user_msg_string.empty()) {
+    return gtest_msg;
+  }
+
+  return gtest_msg + "\n" + user_msg_string;
+}
+
+}  // namespace internal
+
+// class TestResult
+
+// Creates an empty TestResult.
+TestResult::TestResult()
+    : death_test_count_(0),
+      elapsed_time_(0) {
+}
+
+// D'tor.
+TestResult::~TestResult() {
+}
+
+// Returns the i-th test part result among all the results. i can
+// range from 0 to total_part_count() - 1. If i is not in that range,
+// aborts the program.
+const TestPartResult& TestResult::GetTestPartResult(int i) const {
+  if (i < 0 || i >= total_part_count())
+    internal::posix::Abort();
+  return test_part_results_.at(i);
+}
+
+// Returns the i-th test property. i can range from 0 to
+// test_property_count() - 1. If i is not in that range, aborts the
+// program.
+const TestProperty& TestResult::GetTestProperty(int i) const {
+  if (i < 0 || i >= test_property_count())
+    internal::posix::Abort();
+  return test_properties_.at(i);
+}
+
+// Clears the test part results.
+void TestResult::ClearTestPartResults() {
+  test_part_results_.clear();
+}
+
+// Adds a test part result to the list.
+void TestResult::AddTestPartResult(const TestPartResult& test_part_result) {
+  test_part_results_.push_back(test_part_result);
+}
+
+// Adds a test property to the list. If a property with the same key as the
+// supplied property is already represented, the value of this test_property
+// replaces the old value for that key.
+void TestResult::RecordProperty(const std::string& xml_element,
+                                const TestProperty& test_property) {
+  if (!ValidateTestProperty(xml_element, test_property)) {
+    return;
+  }
+  internal::MutexLock lock(&test_properites_mutex_);
+  const std::vector<TestProperty>::iterator property_with_matching_key =
+      std::find_if(test_properties_.begin(), test_properties_.end(),
+                   internal::TestPropertyKeyIs(test_property.key()));
+  if (property_with_matching_key == test_properties_.end()) {
+    test_properties_.push_back(test_property);
+    return;
+  }
+  property_with_matching_key->SetValue(test_property.value());
+}
+
+// The list of reserved attributes used in the <testsuites> element of XML
+// output.
+static const char* const kReservedTestSuitesAttributes[] = {
+  "disabled",
+  "errors",
+  "failures",
+  "name",
+  "random_seed",
+  "tests",
+  "time",
+  "timestamp"
+};
+
+// The list of reserved attributes used in the <testsuite> element of XML
+// output.
+static const char* const kReservedTestSuiteAttributes[] = {
+  "disabled",
+  "errors",
+  "failures",
+  "name",
+  "tests",
+  "time"
+};
+
+// The list of reserved attributes used in the <testcase> element of XML output.
+static const char* const kReservedTestCaseAttributes[] = {
+  "classname",
+  "name",
+  "status",
+  "time",
+  "type_param",
+  "value_param"
+};
+
+template <int kSize>
+std::vector<std::string> ArrayAsVector(const char* const (&array)[kSize]) {
+  return std::vector<std::string>(array, array + kSize);
+}
+
+static std::vector<std::string> GetReservedAttributesForElement(
+    const std::string& xml_element) {
+  if (xml_element == "testsuites") {
+    return ArrayAsVector(kReservedTestSuitesAttributes);
+  } else if (xml_element == "testsuite") {
+    return ArrayAsVector(kReservedTestSuiteAttributes);
+  } else if (xml_element == "testcase") {
+    return ArrayAsVector(kReservedTestCaseAttributes);
+  } else {
+    GTEST_CHECK_(false) << "Unrecognized xml_element provided: " << xml_element;
+  }
+  // This code is unreachable but some compilers may not realizes that.
+  return std::vector<std::string>();
+}
+
+static std::string FormatWordList(const std::vector<std::string>& words) {
+  Message word_list;
+  for (size_t i = 0; i < words.size(); ++i) {
+    if (i > 0 && words.size() > 2) {
+      word_list << ", ";
+    }
+    if (i == words.size() - 1) {
+      word_list << "and ";
+    }
+    word_list << "'" << words[i] << "'";
+  }
+  return word_list.GetString();
+}
+
+bool ValidateTestPropertyName(const std::string& property_name,
+                              const std::vector<std::string>& reserved_names) {
+  if (std::find(reserved_names.begin(), reserved_names.end(), property_name) !=
+          reserved_names.end()) {
+    ADD_FAILURE() << "Reserved key used in RecordProperty(): " << property_name
+                  << " (" << FormatWordList(reserved_names)
+                  << " are reserved by " << GTEST_NAME_ << ")";
+    return false;
+  }
+  return true;
+}
+
+// Adds a failure if the key is a reserved attribute of the element named
+// xml_element.  Returns true if the property is valid.
+bool TestResult::ValidateTestProperty(const std::string& xml_element,
+                                      const TestProperty& test_property) {
+  return ValidateTestPropertyName(test_property.key(),
+                                  GetReservedAttributesForElement(xml_element));
+}
+
+// Clears the object.
+void TestResult::Clear() {
+  test_part_results_.clear();
+  test_properties_.clear();
+  death_test_count_ = 0;
+  elapsed_time_ = 0;
+}
+
+// Returns true iff the test failed.
+bool TestResult::Failed() const {
+  for (int i = 0; i < total_part_count(); ++i) {
+    if (GetTestPartResult(i).failed())
+      return true;
+  }
+  return false;
+}
+
+// Returns true iff the test part fatally failed.
+static bool TestPartFatallyFailed(const TestPartResult& result) {
+  return result.fatally_failed();
+}
+
+// Returns true iff the test fatally failed.
+bool TestResult::HasFatalFailure() const {
+  return CountIf(test_part_results_, TestPartFatallyFailed) > 0;
+}
+
+// Returns true iff the test part non-fatally failed.
+static bool TestPartNonfatallyFailed(const TestPartResult& result) {
+  return result.nonfatally_failed();
+}
+
+// Returns true iff the test has a non-fatal failure.
+bool TestResult::HasNonfatalFailure() const {
+  return CountIf(test_part_results_, TestPartNonfatallyFailed) > 0;
+}
+
+// Gets the number of all test parts.  This is the sum of the number
+// of successful test parts and the number of failed test parts.
+int TestResult::total_part_count() const {
+  return static_cast<int>(test_part_results_.size());
+}
+
+// Returns the number of the test properties.
+int TestResult::test_property_count() const {
+  return static_cast<int>(test_properties_.size());
+}
+
+// class Test
+
+// Creates a Test object.
+
+// The c'tor saves the states of all flags.
+Test::Test()
+    : gtest_flag_saver_(new GTEST_FLAG_SAVER_) {
+}
+
+// The d'tor restores the states of all flags.  The actual work is
+// done by the d'tor of the gtest_flag_saver_ field, and thus not
+// visible here.
+Test::~Test() {
+}
+
+// Sets up the test fixture.
+//
+// A sub-class may override this.
+void Test::SetUp() {
+}
+
+// Tears down the test fixture.
+//
+// A sub-class may override this.
+void Test::TearDown() {
+}
+
+// Allows user supplied key value pairs to be recorded for later output.
+void Test::RecordProperty(const std::string& key, const std::string& value) {
+  UnitTest::GetInstance()->RecordProperty(key, value);
+}
+
+// Allows user supplied key value pairs to be recorded for later output.
+void Test::RecordProperty(const std::string& key, int value) {
+  Message value_message;
+  value_message << value;
+  RecordProperty(key, value_message.GetString().c_str());
+}
+
+namespace internal {
+
+void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
+                                    const std::string& message) {
+  // This function is a friend of UnitTest and as such has access to
+  // AddTestPartResult.
+  UnitTest::GetInstance()->AddTestPartResult(
+      result_type,
+      NULL,  // No info about the source file where the exception occurred.
+      -1,    // We have no info on which line caused the exception.
+      message,
+      "");   // No stack trace, either.
+}
+
+}  // namespace internal
+
+// Google Test requires all tests in the same test case to use the same test
+// fixture class.  This function checks if the current test has the
+// same fixture class as the first test in the current test case.  If
+// yes, it returns true; otherwise it generates a Google Test failure and
+// returns false.
+bool Test::HasSameFixtureClass() {
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  const TestCase* const test_case = impl->current_test_case();
+
+  // Info about the first test in the current test case.
+  const TestInfo* const first_test_info = test_case->test_info_list()[0];
+  const internal::TypeId first_fixture_id = first_test_info->fixture_class_id_;
+  const char* const first_test_name = first_test_info->name();
+
+  // Info about the current test.
+  const TestInfo* const this_test_info = impl->current_test_info();
+  const internal::TypeId this_fixture_id = this_test_info->fixture_class_id_;
+  const char* const this_test_name = this_test_info->name();
+
+  if (this_fixture_id != first_fixture_id) {
+    // Is the first test defined using TEST?
+    const bool first_is_TEST = first_fixture_id == internal::GetTestTypeId();
+    // Is this test defined using TEST?
+    const bool this_is_TEST = this_fixture_id == internal::GetTestTypeId();
+
+    if (first_is_TEST || this_is_TEST) {
+      // Both TEST and TEST_F appear in same test case, which is incorrect.
+      // Tell the user how to fix this.
+
+      // Gets the name of the TEST and the name of the TEST_F.  Note
+      // that first_is_TEST and this_is_TEST cannot both be true, as
+      // the fixture IDs are different for the two tests.
+      const char* const TEST_name =
+          first_is_TEST ? first_test_name : this_test_name;
+      const char* const TEST_F_name =
+          first_is_TEST ? this_test_name : first_test_name;
+
+      ADD_FAILURE()
+          << "All tests in the same test case must use the same test fixture\n"
+          << "class, so mixing TEST_F and TEST in the same test case is\n"
+          << "illegal.  In test case " << this_test_info->test_case_name()
+          << ",\n"
+          << "test " << TEST_F_name << " is defined using TEST_F but\n"
+          << "test " << TEST_name << " is defined using TEST.  You probably\n"
+          << "want to change the TEST to TEST_F or move it to another test\n"
+          << "case.";
+    } else {
+      // Two fixture classes with the same name appear in two different
+      // namespaces, which is not allowed. Tell the user how to fix this.
+      ADD_FAILURE()
+          << "All tests in the same test case must use the same test fixture\n"
+          << "class.  However, in test case "
+          << this_test_info->test_case_name() << ",\n"
+          << "you defined test " << first_test_name
+          << " and test " << this_test_name << "\n"
+          << "using two different test fixture classes.  This can happen if\n"
+          << "the two classes are from different namespaces or translation\n"
+          << "units and have the same name.  You should probably rename one\n"
+          << "of the classes to put the tests into different test cases.";
+    }
+    return false;
+  }
+
+  return true;
+}
+
+#if GTEST_HAS_SEH
+
+// Adds an "exception thrown" fatal failure to the current test.  This
+// function returns its result via an output parameter pointer because VC++
+// prohibits creation of objects with destructors on stack in functions
+// using __try (see error C2712).
+static std::string* FormatSehExceptionMessage(DWORD exception_code,
+                                              const char* location) {
+  Message message;
+  message << "SEH exception with code 0x" << std::setbase(16) <<
+    exception_code << std::setbase(10) << " thrown in " << location << ".";
+
+  return new std::string(message.GetString());
+}
+
+#endif  // GTEST_HAS_SEH
+
+namespace internal {
+
+#if GTEST_HAS_EXCEPTIONS
+
+// Adds an "exception thrown" fatal failure to the current test.
+static std::string FormatCxxExceptionMessage(const char* description,
+                                             const char* location) {
+  Message message;
+  if (description != NULL) {
+    message << "C++ exception with description \"" << description << "\"";
+  } else {
+    message << "Unknown C++ exception";
+  }
+  message << " thrown in " << location << ".";
+
+  return message.GetString();
+}
+
+static std::string PrintTestPartResultToString(
+    const TestPartResult& test_part_result);
+
+GoogleTestFailureException::GoogleTestFailureException(
+    const TestPartResult& failure)
+    : ::std::runtime_error(PrintTestPartResultToString(failure).c_str()) {}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// We put these helper functions in the internal namespace as IBM's xlC
+// compiler rejects the code if they were declared static.
+
+// Runs the given method and handles SEH exceptions it throws, when
+// SEH is supported; returns the 0-value for type Result in case of an
+// SEH exception.  (Microsoft compilers cannot handle SEH and C++
+// exceptions in the same function.  Therefore, we provide a separate
+// wrapper function for handling SEH exceptions.)
+template <class T, typename Result>
+Result HandleSehExceptionsInMethodIfSupported(
+    T* object, Result (T::*method)(), const char* location) {
+#if GTEST_HAS_SEH
+  __try {
+    return (object->*method)();
+  } __except (internal::UnitTestOptions::GTestShouldProcessSEH(  // NOLINT
+      GetExceptionCode())) {
+    // We create the exception message on the heap because VC++ prohibits
+    // creation of objects with destructors on stack in functions using __try
+    // (see error C2712).
+    std::string* exception_message = FormatSehExceptionMessage(
+        GetExceptionCode(), location);
+    internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure,
+                                             *exception_message);
+    delete exception_message;
+    return static_cast<Result>(0);
+  }
+#else
+  (void)location;
+  return (object->*method)();
+#endif  // GTEST_HAS_SEH
+}
+
+// Runs the given method and catches and reports C++ and/or SEH-style
+// exceptions, if they are supported; returns the 0-value for type
+// Result in case of an SEH exception.
+template <class T, typename Result>
+Result HandleExceptionsInMethodIfSupported(
+    T* object, Result (T::*method)(), const char* location) {
+  // NOTE: The user code can affect the way in which Google Test handles
+  // exceptions by setting GTEST_FLAG(catch_exceptions), but only before
+  // RUN_ALL_TESTS() starts. It is technically possible to check the flag
+  // after the exception is caught and either report or re-throw the
+  // exception based on the flag's value:
+  //
+  // try {
+  //   // Perform the test method.
+  // } catch (...) {
+  //   if (GTEST_FLAG(catch_exceptions))
+  //     // Report the exception as failure.
+  //   else
+  //     throw;  // Re-throws the original exception.
+  // }
+  //
+  // However, the purpose of this flag is to allow the program to drop into
+  // the debugger when the exception is thrown. On most platforms, once the
+  // control enters the catch block, the exception origin information is
+  // lost and the debugger will stop the program at the point of the
+  // re-throw in this function -- instead of at the point of the original
+  // throw statement in the code under test.  For this reason, we perform
+  // the check early, sacrificing the ability to affect Google Test's
+  // exception handling in the method where the exception is thrown.
+  if (internal::GetUnitTestImpl()->catch_exceptions()) {
+#if GTEST_HAS_EXCEPTIONS
+    try {
+      return HandleSehExceptionsInMethodIfSupported(object, method, location);
+    } catch (const internal::GoogleTestFailureException&) {  // NOLINT
+      // This exception type can only be thrown by a failed Google
+      // Test assertion with the intention of letting another testing
+      // framework catch it.  Therefore we just re-throw it.
+      throw;
+    } catch (const std::exception& e) {  // NOLINT
+      internal::ReportFailureInUnknownLocation(
+          TestPartResult::kFatalFailure,
+          FormatCxxExceptionMessage(e.what(), location));
+    } catch (...) {  // NOLINT
+      internal::ReportFailureInUnknownLocation(
+          TestPartResult::kFatalFailure,
+          FormatCxxExceptionMessage(NULL, location));
+    }
+    return static_cast<Result>(0);
+#else
+    return HandleSehExceptionsInMethodIfSupported(object, method, location);
+#endif  // GTEST_HAS_EXCEPTIONS
+  } else {
+    return (object->*method)();
+  }
+}
+
+}  // namespace internal
+
+// Runs the test and updates the test result.
+void Test::Run() {
+  if (!HasSameFixtureClass()) return;
+
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()");
+  // We will run the test only if SetUp() was successful.
+  if (!HasFatalFailure()) {
+    impl->os_stack_trace_getter()->UponLeavingGTest();
+    internal::HandleExceptionsInMethodIfSupported(
+        this, &Test::TestBody, "the test body");
+  }
+
+  // However, we want to clean up as much as possible.  Hence we will
+  // always call TearDown(), even if SetUp() or the test body has
+  // failed.
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      this, &Test::TearDown, "TearDown()");
+}
+
+// Returns true iff the current test has a fatal failure.
+bool Test::HasFatalFailure() {
+  return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure();
+}
+
+// Returns true iff the current test has a non-fatal failure.
+bool Test::HasNonfatalFailure() {
+  return internal::GetUnitTestImpl()->current_test_result()->
+      HasNonfatalFailure();
+}
+
+// class TestInfo
+
+// Constructs a TestInfo object. It assumes ownership of the test factory
+// object.
+TestInfo::TestInfo(const std::string& a_test_case_name,
+                   const std::string& a_name,
+                   const char* a_type_param,
+                   const char* a_value_param,
+                   internal::CodeLocation a_code_location,
+                   internal::TypeId fixture_class_id,
+                   internal::TestFactoryBase* factory)
+    : test_case_name_(a_test_case_name),
+      name_(a_name),
+      type_param_(a_type_param ? new std::string(a_type_param) : NULL),
+      value_param_(a_value_param ? new std::string(a_value_param) : NULL),
+      location_(a_code_location),
+      fixture_class_id_(fixture_class_id),
+      should_run_(false),
+      is_disabled_(false),
+      matches_filter_(false),
+      factory_(factory),
+      result_() {}
+
+// Destructs a TestInfo object.
+TestInfo::~TestInfo() { delete factory_; }
+
+namespace internal {
+
+// Creates a new TestInfo object and registers it with Google Test;
+// returns the created object.
+//
+// Arguments:
+//
+//   test_case_name:   name of the test case
+//   name:             name of the test
+//   type_param:       the name of the test's type parameter, or NULL if
+//                     this is not a typed or a type-parameterized test.
+//   value_param:      text representation of the test's value parameter,
+//                     or NULL if this is not a value-parameterized test.
+//   code_location:    code location where the test is defined
+//   fixture_class_id: ID of the test fixture class
+//   set_up_tc:        pointer to the function that sets up the test case
+//   tear_down_tc:     pointer to the function that tears down the test case
+//   factory:          pointer to the factory that creates a test object.
+//                     The newly created TestInfo instance will assume
+//                     ownership of the factory object.
+TestInfo* MakeAndRegisterTestInfo(
+    const char* test_case_name,
+    const char* name,
+    const char* type_param,
+    const char* value_param,
+    CodeLocation code_location,
+    TypeId fixture_class_id,
+    SetUpTestCaseFunc set_up_tc,
+    TearDownTestCaseFunc tear_down_tc,
+    TestFactoryBase* factory) {
+  TestInfo* const test_info =
+      new TestInfo(test_case_name, name, type_param, value_param,
+                   code_location, fixture_class_id, factory);
+  GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info);
+  return test_info;
+}
+
+#if GTEST_HAS_PARAM_TEST
+void ReportInvalidTestCaseType(const char* test_case_name,
+                               CodeLocation code_location) {
+  Message errors;
+  errors
+      << "Attempted redefinition of test case " << test_case_name << ".\n"
+      << "All tests in the same test case must use the same test fixture\n"
+      << "class.  However, in test case " << test_case_name << ", you tried\n"
+      << "to define a test using a fixture class different from the one\n"
+      << "used earlier. This can happen if the two fixture classes are\n"
+      << "from different namespaces and have the same name. You should\n"
+      << "probably rename one of the classes to put the tests into different\n"
+      << "test cases.";
+
+  fprintf(stderr, "%s %s",
+          FormatFileLocation(code_location.file.c_str(),
+                             code_location.line).c_str(),
+          errors.GetString().c_str());
+}
+#endif  // GTEST_HAS_PARAM_TEST
+
+}  // namespace internal
+
+namespace {
+
+// A predicate that checks the test name of a TestInfo against a known
+// value.
+//
+// This is used for implementation of the TestCase class only.  We put
+// it in the anonymous namespace to prevent polluting the outer
+// namespace.
+//
+// TestNameIs is copyable.
+class TestNameIs {
+ public:
+  // Constructor.
+  //
+  // TestNameIs has NO default constructor.
+  explicit TestNameIs(const char* name)
+      : name_(name) {}
+
+  // Returns true iff the test name of test_info matches name_.
+  bool operator()(const TestInfo * test_info) const {
+    return test_info && test_info->name() == name_;
+  }
+
+ private:
+  std::string name_;
+};
+
+}  // namespace
+
+namespace internal {
+
+// This method expands all parameterized tests registered with macros TEST_P
+// and INSTANTIATE_TEST_CASE_P into regular tests and registers those.
+// This will be done just once during the program runtime.
+void UnitTestImpl::RegisterParameterizedTests() {
+#if GTEST_HAS_PARAM_TEST
+  if (!parameterized_tests_registered_) {
+    parameterized_test_registry_.RegisterTests();
+    parameterized_tests_registered_ = true;
+  }
+#endif
+}
+
+}  // namespace internal
+
+// Creates the test object, runs it, records its result, and then
+// deletes it.
+void TestInfo::Run() {
+  if (!should_run_) return;
+
+  // Tells UnitTest where to store test result.
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  impl->set_current_test_info(this);
+
+  TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
+
+  // Notifies the unit test event listeners that a test is about to start.
+  repeater->OnTestStart(*this);
+
+  const TimeInMillis start = internal::GetTimeInMillis();
+
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+
+  // Creates the test object.
+  Test* const test = internal::HandleExceptionsInMethodIfSupported(
+      factory_, &internal::TestFactoryBase::CreateTest,
+      "the test fixture's constructor");
+
+  // Runs the test only if the test object was created and its
+  // constructor didn't generate a fatal failure.
+  if ((test != NULL) && !Test::HasFatalFailure()) {
+    // This doesn't throw as all user code that can throw are wrapped into
+    // exception handling code.
+    test->Run();
+  }
+
+  // Deletes the test object.
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      test, &Test::DeleteSelf_, "the test fixture's destructor");
+
+  result_.set_elapsed_time(internal::GetTimeInMillis() - start);
+
+  // Notifies the unit test event listener that a test has just finished.
+  repeater->OnTestEnd(*this);
+
+  // Tells UnitTest to stop associating assertion results to this
+  // test.
+  impl->set_current_test_info(NULL);
+}
+
+// class TestCase
+
+// Gets the number of successful tests in this test case.
+int TestCase::successful_test_count() const {
+  return CountIf(test_info_list_, TestPassed);
+}
+
+// Gets the number of failed tests in this test case.
+int TestCase::failed_test_count() const {
+  return CountIf(test_info_list_, TestFailed);
+}
+
+// Gets the number of disabled tests that will be reported in the XML report.
+int TestCase::reportable_disabled_test_count() const {
+  return CountIf(test_info_list_, TestReportableDisabled);
+}
+
+// Gets the number of disabled tests in this test case.
+int TestCase::disabled_test_count() const {
+  return CountIf(test_info_list_, TestDisabled);
+}
+
+// Gets the number of tests to be printed in the XML report.
+int TestCase::reportable_test_count() const {
+  return CountIf(test_info_list_, TestReportable);
+}
+
+// Get the number of tests in this test case that should run.
+int TestCase::test_to_run_count() const {
+  return CountIf(test_info_list_, ShouldRunTest);
+}
+
+// Gets the number of all tests.
+int TestCase::total_test_count() const {
+  return static_cast<int>(test_info_list_.size());
+}
+
+// Creates a TestCase with the given name.
+//
+// Arguments:
+//
+//   name:         name of the test case
+//   a_type_param: the name of the test case's type parameter, or NULL if
+//                 this is not a typed or a type-parameterized test case.
+//   set_up_tc:    pointer to the function that sets up the test case
+//   tear_down_tc: pointer to the function that tears down the test case
+TestCase::TestCase(const char* a_name, const char* a_type_param,
+                   Test::SetUpTestCaseFunc set_up_tc,
+                   Test::TearDownTestCaseFunc tear_down_tc)
+    : name_(a_name),
+      type_param_(a_type_param ? new std::string(a_type_param) : NULL),
+      set_up_tc_(set_up_tc),
+      tear_down_tc_(tear_down_tc),
+      should_run_(false),
+      elapsed_time_(0) {
+}
+
+// Destructor of TestCase.
+TestCase::~TestCase() {
+  // Deletes every Test in the collection.
+  ForEach(test_info_list_, internal::Delete<TestInfo>);
+}
+
+// Returns the i-th test among all the tests. i can range from 0 to
+// total_test_count() - 1. If i is not in that range, returns NULL.
+const TestInfo* TestCase::GetTestInfo(int i) const {
+  const int index = GetElementOr(test_indices_, i, -1);
+  return index < 0 ? NULL : test_info_list_[index];
+}
+
+// Returns the i-th test among all the tests. i can range from 0 to
+// total_test_count() - 1. If i is not in that range, returns NULL.
+TestInfo* TestCase::GetMutableTestInfo(int i) {
+  const int index = GetElementOr(test_indices_, i, -1);
+  return index < 0 ? NULL : test_info_list_[index];
+}
+
+// Adds a test to this test case.  Will delete the test upon
+// destruction of the TestCase object.
+void TestCase::AddTestInfo(TestInfo * test_info) {
+  test_info_list_.push_back(test_info);
+  test_indices_.push_back(static_cast<int>(test_indices_.size()));
+}
+
+// Runs every test in this TestCase.
+void TestCase::Run() {
+  if (!should_run_) return;
+
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  impl->set_current_test_case(this);
+
+  TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
+
+  repeater->OnTestCaseStart(*this);
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      this, &TestCase::RunSetUpTestCase, "SetUpTestCase()");
+
+  const internal::TimeInMillis start = internal::GetTimeInMillis();
+  for (int i = 0; i < total_test_count(); i++) {
+    GetMutableTestInfo(i)->Run();
+  }
+  elapsed_time_ = internal::GetTimeInMillis() - start;
+
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      this, &TestCase::RunTearDownTestCase, "TearDownTestCase()");
+
+  repeater->OnTestCaseEnd(*this);
+  impl->set_current_test_case(NULL);
+}
+
+// Clears the results of all tests in this test case.
+void TestCase::ClearResult() {
+  ad_hoc_test_result_.Clear();
+  ForEach(test_info_list_, TestInfo::ClearTestResult);
+}
+
+// Shuffles the tests in this test case.
+void TestCase::ShuffleTests(internal::Random* random) {
+  Shuffle(random, &test_indices_);
+}
+
+// Restores the test order to before the first shuffle.
+void TestCase::UnshuffleTests() {
+  for (size_t i = 0; i < test_indices_.size(); i++) {
+    test_indices_[i] = static_cast<int>(i);
+  }
+}
+
+// Formats a countable noun.  Depending on its quantity, either the
+// singular form or the plural form is used. e.g.
+//
+// FormatCountableNoun(1, "formula", "formuli") returns "1 formula".
+// FormatCountableNoun(5, "book", "books") returns "5 books".
+static std::string FormatCountableNoun(int count,
+                                       const char * singular_form,
+                                       const char * plural_form) {
+  return internal::StreamableToString(count) + " " +
+      (count == 1 ? singular_form : plural_form);
+}
+
+// Formats the count of tests.
+static std::string FormatTestCount(int test_count) {
+  return FormatCountableNoun(test_count, "test", "tests");
+}
+
+// Formats the count of test cases.
+static std::string FormatTestCaseCount(int test_case_count) {
+  return FormatCountableNoun(test_case_count, "test case", "test cases");
+}
+
+// Converts a TestPartResult::Type enum to human-friendly string
+// representation.  Both kNonFatalFailure and kFatalFailure are translated
+// to "Failure", as the user usually doesn't care about the difference
+// between the two when viewing the test result.
+static const char * TestPartResultTypeToString(TestPartResult::Type type) {
+  switch (type) {
+    case TestPartResult::kSuccess:
+      return "Success";
+
+    case TestPartResult::kNonFatalFailure:
+    case TestPartResult::kFatalFailure:
+#ifdef _MSC_VER
+      return "error: ";
+#else
+      return "Failure\n";
+#endif
+    default:
+      return "Unknown result type";
+  }
+}
+
+namespace internal {
+
+// Prints a TestPartResult to an std::string.
+static std::string PrintTestPartResultToString(
+    const TestPartResult& test_part_result) {
+  return (Message()
+          << internal::FormatFileLocation(test_part_result.file_name(),
+                                          test_part_result.line_number())
+          << " " << TestPartResultTypeToString(test_part_result.type())
+          << test_part_result.message()).GetString();
+}
+
+// Prints a TestPartResult.
+static void PrintTestPartResult(const TestPartResult& test_part_result) {
+  const std::string& result =
+      PrintTestPartResultToString(test_part_result);
+  printf("%s\n", result.c_str());
+  fflush(stdout);
+  // If the test program runs in Visual Studio or a debugger, the
+  // following statements add the test part result message to the Output
+  // window such that the user can double-click on it to jump to the
+  // corresponding source code location; otherwise they do nothing.
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+  // We don't call OutputDebugString*() on Windows Mobile, as printing
+  // to stdout is done by OutputDebugString() there already - we don't
+  // want the same message printed twice.
+  ::OutputDebugStringA(result.c_str());
+  ::OutputDebugStringA("\n");
+#endif
+}
+
+// class PrettyUnitTestResultPrinter
+
+enum GTestColor {
+  COLOR_DEFAULT,
+  COLOR_RED,
+  COLOR_GREEN,
+  COLOR_YELLOW
+};
+
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE && \
+    !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT
+
+// Returns the character attribute for the given color.
+WORD GetColorAttribute(GTestColor color) {
+  switch (color) {
+    case COLOR_RED:    return FOREGROUND_RED;
+    case COLOR_GREEN:  return FOREGROUND_GREEN;
+    case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN;
+    default:           return 0;
+  }
+}
+
+#else
+
+// Returns the ANSI color code for the given color.  COLOR_DEFAULT is
+// an invalid input.
+const char* GetAnsiColorCode(GTestColor color) {
+  switch (color) {
+    case COLOR_RED:     return "1";
+    case COLOR_GREEN:   return "2";
+    case COLOR_YELLOW:  return "3";
+    default:            return NULL;
+  };
+}
+
+#endif  // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+
+// Returns true iff Google Test should use colors in the output.
+bool ShouldUseColor(bool stdout_is_tty) {
+  const char* const gtest_color = GTEST_FLAG(color).c_str();
+
+  if (String::CaseInsensitiveCStringEquals(gtest_color, "auto")) {
+#if GTEST_OS_WINDOWS
+    // On Windows the TERM variable is usually not set, but the
+    // console there does support colors.
+    return stdout_is_tty;
+#else
+    // On non-Windows platforms, we rely on the TERM variable.
+    const char* const term = posix::GetEnv("TERM");
+    const bool term_supports_color =
+        String::CStringEquals(term, "xterm") ||
+        String::CStringEquals(term, "xterm-color") ||
+        String::CStringEquals(term, "xterm-256color") ||
+        String::CStringEquals(term, "screen") ||
+        String::CStringEquals(term, "screen-256color") ||
+        String::CStringEquals(term, "rxvt-unicode") ||
+        String::CStringEquals(term, "rxvt-unicode-256color") ||
+        String::CStringEquals(term, "linux") ||
+        String::CStringEquals(term, "cygwin");
+    return stdout_is_tty && term_supports_color;
+#endif  // GTEST_OS_WINDOWS
+  }
+
+  return String::CaseInsensitiveCStringEquals(gtest_color, "yes") ||
+      String::CaseInsensitiveCStringEquals(gtest_color, "true") ||
+      String::CaseInsensitiveCStringEquals(gtest_color, "t") ||
+      String::CStringEquals(gtest_color, "1");
+  // We take "yes", "true", "t", and "1" as meaning "yes".  If the
+  // value is neither one of these nor "auto", we treat it as "no" to
+  // be conservative.
+}
+
+// Helpers for printing colored strings to stdout. Note that on Windows, we
+// cannot simply emit special characters and have the terminal change colors.
+// This routine must actually emit the characters rather than return a string
+// that would be colored when printed, as can be done on Linux.
+void ColoredPrintf(GTestColor color, const char* fmt, ...) {
+  va_list args;
+  va_start(args, fmt);
+
+#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS || \
+    GTEST_OS_IOS || GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT
+  const bool use_color = AlwaysFalse();
+#else
+  static const bool in_color_mode =
+      ShouldUseColor(posix::IsATTY(posix::FileNo(stdout)) != 0);
+  const bool use_color = in_color_mode && (color != COLOR_DEFAULT);
+#endif  // GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS
+  // The '!= 0' comparison is necessary to satisfy MSVC 7.1.
+
+  if (!use_color) {
+    vprintf(fmt, args);
+    va_end(args);
+    return;
+  }
+
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE && \
+    !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT
+  const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
+
+  // Gets the current text color.
+  CONSOLE_SCREEN_BUFFER_INFO buffer_info;
+  GetConsoleScreenBufferInfo(stdout_handle, &buffer_info);
+  const WORD old_color_attrs = buffer_info.wAttributes;
+
+  // We need to flush the stream buffers into the console before each
+  // SetConsoleTextAttribute call lest it affect the text that is already
+  // printed but has not yet reached the console.
+  fflush(stdout);
+  SetConsoleTextAttribute(stdout_handle,
+                          GetColorAttribute(color) | FOREGROUND_INTENSITY);
+  vprintf(fmt, args);
+
+  fflush(stdout);
+  // Restores the text color.
+  SetConsoleTextAttribute(stdout_handle, old_color_attrs);
+#else
+  printf("\033[0;3%sm", GetAnsiColorCode(color));
+  vprintf(fmt, args);
+  printf("\033[m");  // Resets the terminal to default.
+#endif  // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+  va_end(args);
+}
+
+// Text printed in Google Test's text output and --gunit_list_tests
+// output to label the type parameter and value parameter for a test.
+static const char kTypeParamLabel[] = "TypeParam";
+static const char kValueParamLabel[] = "GetParam()";
+
+void PrintFullTestCommentIfPresent(const TestInfo& test_info) {
+  const char* const type_param = test_info.type_param();
+  const char* const value_param = test_info.value_param();
+
+  if (type_param != NULL || value_param != NULL) {
+    printf(", where ");
+    if (type_param != NULL) {
+      printf("%s = %s", kTypeParamLabel, type_param);
+      if (value_param != NULL)
+        printf(" and ");
+    }
+    if (value_param != NULL) {
+      printf("%s = %s", kValueParamLabel, value_param);
+    }
+  }
+}
+
+// This class implements the TestEventListener interface.
+//
+// Class PrettyUnitTestResultPrinter is copyable.
+class PrettyUnitTestResultPrinter : public TestEventListener {
+ public:
+  PrettyUnitTestResultPrinter() {}
+  static void PrintTestName(const char * test_case, const char * test) {
+    printf("%s.%s", test_case, test);
+  }
+
+  // The following methods override what's in the TestEventListener class.
+  virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration);
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test);
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestCaseStart(const TestCase& test_case);
+  virtual void OnTestStart(const TestInfo& test_info);
+  virtual void OnTestPartResult(const TestPartResult& result);
+  virtual void OnTestEnd(const TestInfo& test_info);
+  virtual void OnTestCaseEnd(const TestCase& test_case);
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test);
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
+  virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {}
+
+ private:
+  static void PrintFailedTests(const UnitTest& unit_test);
+};
+
+  // Fired before each iteration of tests starts.
+void PrettyUnitTestResultPrinter::OnTestIterationStart(
+    const UnitTest& unit_test, int iteration) {
+  if (GTEST_FLAG(repeat) != 1)
+    printf("\nRepeating all tests (iteration %d) . . .\n\n", iteration + 1);
+
+  const char* const filter = GTEST_FLAG(filter).c_str();
+
+  // Prints the filter if it's not *.  This reminds the user that some
+  // tests may be skipped.
+  if (!String::CStringEquals(filter, kUniversalFilter)) {
+    ColoredPrintf(COLOR_YELLOW,
+                  "Note: %s filter = %s\n", GTEST_NAME_, filter);
+  }
+
+  if (internal::ShouldShard(kTestTotalShards, kTestShardIndex, false)) {
+    const Int32 shard_index = Int32FromEnvOrDie(kTestShardIndex, -1);
+    ColoredPrintf(COLOR_YELLOW,
+                  "Note: This is test shard %d of %s.\n",
+                  static_cast<int>(shard_index) + 1,
+                  internal::posix::GetEnv(kTestTotalShards));
+  }
+
+  if (GTEST_FLAG(shuffle)) {
+    ColoredPrintf(COLOR_YELLOW,
+                  "Note: Randomizing tests' orders with a seed of %d .\n",
+                  unit_test.random_seed());
+  }
+
+  ColoredPrintf(COLOR_GREEN,  "[==========] ");
+  printf("Running %s from %s.\n",
+         FormatTestCount(unit_test.test_to_run_count()).c_str(),
+         FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str());
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnEnvironmentsSetUpStart(
+    const UnitTest& /*unit_test*/) {
+  ColoredPrintf(COLOR_GREEN,  "[----------] ");
+  printf("Global test environment set-up.\n");
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) {
+  const std::string counts =
+      FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
+  ColoredPrintf(COLOR_GREEN, "[----------] ");
+  printf("%s from %s", counts.c_str(), test_case.name());
+  if (test_case.type_param() == NULL) {
+    printf("\n");
+  } else {
+    printf(", where %s = %s\n", kTypeParamLabel, test_case.type_param());
+  }
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) {
+  ColoredPrintf(COLOR_GREEN,  "[ RUN      ] ");
+  PrintTestName(test_info.test_case_name(), test_info.name());
+  printf("\n");
+  fflush(stdout);
+}
+
+// Called after an assertion failure.
+void PrettyUnitTestResultPrinter::OnTestPartResult(
+    const TestPartResult& result) {
+  // If the test part succeeded, we don't need to do anything.
+  if (result.type() == TestPartResult::kSuccess)
+    return;
+
+  // Print failure message from the assertion (e.g. expected this and got that).
+  PrintTestPartResult(result);
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) {
+  if (test_info.result()->Passed()) {
+    ColoredPrintf(COLOR_GREEN, "[       OK ] ");
+  } else {
+    ColoredPrintf(COLOR_RED, "[  FAILED  ] ");
+  }
+  PrintTestName(test_info.test_case_name(), test_info.name());
+  if (test_info.result()->Failed())
+    PrintFullTestCommentIfPresent(test_info);
+
+  if (GTEST_FLAG(print_time)) {
+    printf(" (%s ms)\n", internal::StreamableToString(
+           test_info.result()->elapsed_time()).c_str());
+  } else {
+    printf("\n");
+  }
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestCaseEnd(const TestCase& test_case) {
+  if (!GTEST_FLAG(print_time)) return;
+
+  const std::string counts =
+      FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
+  ColoredPrintf(COLOR_GREEN, "[----------] ");
+  printf("%s from %s (%s ms total)\n\n",
+         counts.c_str(), test_case.name(),
+         internal::StreamableToString(test_case.elapsed_time()).c_str());
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnEnvironmentsTearDownStart(
+    const UnitTest& /*unit_test*/) {
+  ColoredPrintf(COLOR_GREEN,  "[----------] ");
+  printf("Global test environment tear-down\n");
+  fflush(stdout);
+}
+
+// Internal helper for printing the list of failed tests.
+void PrettyUnitTestResultPrinter::PrintFailedTests(const UnitTest& unit_test) {
+  const int failed_test_count = unit_test.failed_test_count();
+  if (failed_test_count == 0) {
+    return;
+  }
+
+  for (int i = 0; i < unit_test.total_test_case_count(); ++i) {
+    const TestCase& test_case = *unit_test.GetTestCase(i);
+    if (!test_case.should_run() || (test_case.failed_test_count() == 0)) {
+      continue;
+    }
+    for (int j = 0; j < test_case.total_test_count(); ++j) {
+      const TestInfo& test_info = *test_case.GetTestInfo(j);
+      if (!test_info.should_run() || test_info.result()->Passed()) {
+        continue;
+      }
+      ColoredPrintf(COLOR_RED, "[  FAILED  ] ");
+      printf("%s.%s", test_case.name(), test_info.name());
+      PrintFullTestCommentIfPresent(test_info);
+      printf("\n");
+    }
+  }
+}
+
+void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
+                                                     int /*iteration*/) {
+  ColoredPrintf(COLOR_GREEN,  "[==========] ");
+  printf("%s from %s ran.",
+         FormatTestCount(unit_test.test_to_run_count()).c_str(),
+         FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str());
+  if (GTEST_FLAG(print_time)) {
+    printf(" (%s ms total)",
+           internal::StreamableToString(unit_test.elapsed_time()).c_str());
+  }
+  printf("\n");
+  ColoredPrintf(COLOR_GREEN,  "[  PASSED  ] ");
+  printf("%s.\n", FormatTestCount(unit_test.successful_test_count()).c_str());
+
+  int num_failures = unit_test.failed_test_count();
+  if (!unit_test.Passed()) {
+    const int failed_test_count = unit_test.failed_test_count();
+    ColoredPrintf(COLOR_RED,  "[  FAILED  ] ");
+    printf("%s, listed below:\n", FormatTestCount(failed_test_count).c_str());
+    PrintFailedTests(unit_test);
+    printf("\n%2d FAILED %s\n", num_failures,
+                        num_failures == 1 ? "TEST" : "TESTS");
+  }
+
+  int num_disabled = unit_test.reportable_disabled_test_count();
+  if (num_disabled && !GTEST_FLAG(also_run_disabled_tests)) {
+    if (!num_failures) {
+      printf("\n");  // Add a spacer if no FAILURE banner is displayed.
+    }
+    ColoredPrintf(COLOR_YELLOW,
+                  "  YOU HAVE %d DISABLED %s\n\n",
+                  num_disabled,
+                  num_disabled == 1 ? "TEST" : "TESTS");
+  }
+  // Ensure that Google Test output is printed before, e.g., heapchecker output.
+  fflush(stdout);
+}
+
+// End PrettyUnitTestResultPrinter
+
+// class TestEventRepeater
+//
+// This class forwards events to other event listeners.
+class TestEventRepeater : public TestEventListener {
+ public:
+  TestEventRepeater() : forwarding_enabled_(true) {}
+  virtual ~TestEventRepeater();
+  void Append(TestEventListener *listener);
+  TestEventListener* Release(TestEventListener* listener);
+
+  // Controls whether events will be forwarded to listeners_. Set to false
+  // in death test child processes.
+  bool forwarding_enabled() const { return forwarding_enabled_; }
+  void set_forwarding_enabled(bool enable) { forwarding_enabled_ = enable; }
+
+  virtual void OnTestProgramStart(const UnitTest& unit_test);
+  virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration);
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test);
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test);
+  virtual void OnTestCaseStart(const TestCase& test_case);
+  virtual void OnTestStart(const TestInfo& test_info);
+  virtual void OnTestPartResult(const TestPartResult& result);
+  virtual void OnTestEnd(const TestInfo& test_info);
+  virtual void OnTestCaseEnd(const TestCase& test_case);
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test);
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test);
+  virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
+  virtual void OnTestProgramEnd(const UnitTest& unit_test);
+
+ private:
+  // Controls whether events will be forwarded to listeners_. Set to false
+  // in death test child processes.
+  bool forwarding_enabled_;
+  // The list of listeners that receive events.
+  std::vector<TestEventListener*> listeners_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventRepeater);
+};
+
+TestEventRepeater::~TestEventRepeater() {
+  ForEach(listeners_, Delete<TestEventListener>);
+}
+
+void TestEventRepeater::Append(TestEventListener *listener) {
+  listeners_.push_back(listener);
+}
+
+// TODO(vladl@google.com): Factor the search functionality into Vector::Find.
+TestEventListener* TestEventRepeater::Release(TestEventListener *listener) {
+  for (size_t i = 0; i < listeners_.size(); ++i) {
+    if (listeners_[i] == listener) {
+      listeners_.erase(listeners_.begin() + i);
+      return listener;
+    }
+  }
+
+  return NULL;
+}
+
+// Since most methods are very similar, use macros to reduce boilerplate.
+// This defines a member that forwards the call to all listeners.
+#define GTEST_REPEATER_METHOD_(Name, Type) \
+void TestEventRepeater::Name(const Type& parameter) { \
+  if (forwarding_enabled_) { \
+    for (size_t i = 0; i < listeners_.size(); i++) { \
+      listeners_[i]->Name(parameter); \
+    } \
+  } \
+}
+// This defines a member that forwards the call to all listeners in reverse
+// order.
+#define GTEST_REVERSE_REPEATER_METHOD_(Name, Type) \
+void TestEventRepeater::Name(const Type& parameter) { \
+  if (forwarding_enabled_) { \
+    for (int i = static_cast<int>(listeners_.size()) - 1; i >= 0; i--) { \
+      listeners_[i]->Name(parameter); \
+    } \
+  } \
+}
+
+GTEST_REPEATER_METHOD_(OnTestProgramStart, UnitTest)
+GTEST_REPEATER_METHOD_(OnEnvironmentsSetUpStart, UnitTest)
+GTEST_REPEATER_METHOD_(OnTestCaseStart, TestCase)
+GTEST_REPEATER_METHOD_(OnTestStart, TestInfo)
+GTEST_REPEATER_METHOD_(OnTestPartResult, TestPartResult)
+GTEST_REPEATER_METHOD_(OnEnvironmentsTearDownStart, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsSetUpEnd, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsTearDownEnd, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestEnd, TestInfo)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestCaseEnd, TestCase)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestProgramEnd, UnitTest)
+
+#undef GTEST_REPEATER_METHOD_
+#undef GTEST_REVERSE_REPEATER_METHOD_
+
+void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test,
+                                             int iteration) {
+  if (forwarding_enabled_) {
+    for (size_t i = 0; i < listeners_.size(); i++) {
+      listeners_[i]->OnTestIterationStart(unit_test, iteration);
+    }
+  }
+}
+
+void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test,
+                                           int iteration) {
+  if (forwarding_enabled_) {
+    for (int i = static_cast<int>(listeners_.size()) - 1; i >= 0; i--) {
+      listeners_[i]->OnTestIterationEnd(unit_test, iteration);
+    }
+  }
+}
+
+// End TestEventRepeater
+
+// This class generates an XML output file.
+class XmlUnitTestResultPrinter : public EmptyTestEventListener {
+ public:
+  explicit XmlUnitTestResultPrinter(const char* output_file);
+
+  virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
+
+ private:
+  // Is c a whitespace character that is normalized to a space character
+  // when it appears in an XML attribute value?
+  static bool IsNormalizableWhitespace(char c) {
+    return c == 0x9 || c == 0xA || c == 0xD;
+  }
+
+  // May c appear in a well-formed XML document?
+  static bool IsValidXmlCharacter(char c) {
+    return IsNormalizableWhitespace(c) || c >= 0x20;
+  }
+
+  // Returns an XML-escaped copy of the input string str.  If
+  // is_attribute is true, the text is meant to appear as an attribute
+  // value, and normalizable whitespace is preserved by replacing it
+  // with character references.
+  static std::string EscapeXml(const std::string& str, bool is_attribute);
+
+  // Returns the given string with all characters invalid in XML removed.
+  static std::string RemoveInvalidXmlCharacters(const std::string& str);
+
+  // Convenience wrapper around EscapeXml when str is an attribute value.
+  static std::string EscapeXmlAttribute(const std::string& str) {
+    return EscapeXml(str, true);
+  }
+
+  // Convenience wrapper around EscapeXml when str is not an attribute value.
+  static std::string EscapeXmlText(const char* str) {
+    return EscapeXml(str, false);
+  }
+
+  // Verifies that the given attribute belongs to the given element and
+  // streams the attribute as XML.
+  static void OutputXmlAttribute(std::ostream* stream,
+                                 const std::string& element_name,
+                                 const std::string& name,
+                                 const std::string& value);
+
+  // Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
+  static void OutputXmlCDataSection(::std::ostream* stream, const char* data);
+
+  // Streams an XML representation of a TestInfo object.
+  static void OutputXmlTestInfo(::std::ostream* stream,
+                                const char* test_case_name,
+                                const TestInfo& test_info);
+
+  // Prints an XML representation of a TestCase object
+  static void PrintXmlTestCase(::std::ostream* stream,
+                               const TestCase& test_case);
+
+  // Prints an XML summary of unit_test to output stream out.
+  static void PrintXmlUnitTest(::std::ostream* stream,
+                               const UnitTest& unit_test);
+
+  // Produces a string representing the test properties in a result as space
+  // delimited XML attributes based on the property key="value" pairs.
+  // When the std::string is not empty, it includes a space at the beginning,
+  // to delimit this attribute from prior attributes.
+  static std::string TestPropertiesAsXmlAttributes(const TestResult& result);
+
+  // The output file.
+  const std::string output_file_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(XmlUnitTestResultPrinter);
+};
+
+// Creates a new XmlUnitTestResultPrinter.
+XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file)
+    : output_file_(output_file) {
+  if (output_file_.c_str() == NULL || output_file_.empty()) {
+    fprintf(stderr, "XML output file may not be null\n");
+    fflush(stderr);
+    exit(EXIT_FAILURE);
+  }
+}
+
+// Called after the unit test ends.
+void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
+                                                  int /*iteration*/) {
+  FILE* xmlout = NULL;
+  FilePath output_file(output_file_);
+  FilePath output_dir(output_file.RemoveFileName());
+
+  if (output_dir.CreateDirectoriesRecursively()) {
+    xmlout = posix::FOpen(output_file_.c_str(), "w");
+  }
+  if (xmlout == NULL) {
+    // TODO(wan): report the reason of the failure.
+    //
+    // We don't do it for now as:
+    //
+    //   1. There is no urgent need for it.
+    //   2. It's a bit involved to make the errno variable thread-safe on
+    //      all three operating systems (Linux, Windows, and Mac OS).
+    //   3. To interpret the meaning of errno in a thread-safe way,
+    //      we need the strerror_r() function, which is not available on
+    //      Windows.
+    fprintf(stderr,
+            "Unable to open file \"%s\"\n",
+            output_file_.c_str());
+    fflush(stderr);
+    exit(EXIT_FAILURE);
+  }
+  std::stringstream stream;
+  PrintXmlUnitTest(&stream, unit_test);
+  fprintf(xmlout, "%s", StringStreamToString(&stream).c_str());
+  fclose(xmlout);
+}
+
+// Returns an XML-escaped copy of the input string str.  If is_attribute
+// is true, the text is meant to appear as an attribute value, and
+// normalizable whitespace is preserved by replacing it with character
+// references.
+//
+// Invalid XML characters in str, if any, are stripped from the output.
+// It is expected that most, if not all, of the text processed by this
+// module will consist of ordinary English text.
+// If this module is ever modified to produce version 1.1 XML output,
+// most invalid characters can be retained using character references.
+// TODO(wan): It might be nice to have a minimally invasive, human-readable
+// escaping scheme for invalid characters, rather than dropping them.
+std::string XmlUnitTestResultPrinter::EscapeXml(
+    const std::string& str, bool is_attribute) {
+  Message m;
+
+  for (size_t i = 0; i < str.size(); ++i) {
+    const char ch = str[i];
+    switch (ch) {
+      case '<':
+        m << "&lt;";
+        break;
+      case '>':
+        m << "&gt;";
+        break;
+      case '&':
+        m << "&amp;";
+        break;
+      case '\'':
+        if (is_attribute)
+          m << "&apos;";
+        else
+          m << '\'';
+        break;
+      case '"':
+        if (is_attribute)
+          m << "&quot;";
+        else
+          m << '"';
+        break;
+      default:
+        if (IsValidXmlCharacter(ch)) {
+          if (is_attribute && IsNormalizableWhitespace(ch))
+            m << "&#x" << String::FormatByte(static_cast<unsigned char>(ch))
+              << ";";
+          else
+            m << ch;
+        }
+        break;
+    }
+  }
+
+  return m.GetString();
+}
+
+// Returns the given string with all characters invalid in XML removed.
+// Currently invalid characters are dropped from the string. An
+// alternative is to replace them with certain characters such as . or ?.
+std::string XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters(
+    const std::string& str) {
+  std::string output;
+  output.reserve(str.size());
+  for (std::string::const_iterator it = str.begin(); it != str.end(); ++it)
+    if (IsValidXmlCharacter(*it))
+      output.push_back(*it);
+
+  return output;
+}
+
+// The following routines generate an XML representation of a UnitTest
+// object.
+//
+// This is how Google Test concepts map to the DTD:
+//
+// <testsuites name="AllTests">        <-- corresponds to a UnitTest object
+//   <testsuite name="testcase-name">  <-- corresponds to a TestCase object
+//     <testcase name="test-name">     <-- corresponds to a TestInfo object
+//       <failure message="...">...</failure>
+//       <failure message="...">...</failure>
+//       <failure message="...">...</failure>
+//                                     <-- individual assertion failures
+//     </testcase>
+//   </testsuite>
+// </testsuites>
+
+// Formats the given time in milliseconds as seconds.
+std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) {
+  ::std::stringstream ss;
+  ss << (static_cast<double>(ms) * 1e-3);
+  return ss.str();
+}
+
+static bool PortableLocaltime(time_t seconds, struct tm* out) {
+#if defined(_MSC_VER)
+  return localtime_s(out, &seconds) == 0;
+#elif defined(__MINGW32__) || defined(__MINGW64__)
+  // MINGW <time.h> provides neither localtime_r nor localtime_s, but uses
+  // Windows' localtime(), which has a thread-local tm buffer.
+  struct tm* tm_ptr = localtime(&seconds);  // NOLINT
+  if (tm_ptr == NULL)
+    return false;
+  *out = *tm_ptr;
+  return true;
+#else
+  return localtime_r(&seconds, out) != NULL;
+#endif
+}
+
+// Converts the given epoch time in milliseconds to a date string in the ISO
+// 8601 format, without the timezone information.
+std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms) {
+  struct tm time_struct;
+  if (!PortableLocaltime(static_cast<time_t>(ms / 1000), &time_struct))
+    return "";
+  // YYYY-MM-DDThh:mm:ss
+  return StreamableToString(time_struct.tm_year + 1900) + "-" +
+      String::FormatIntWidth2(time_struct.tm_mon + 1) + "-" +
+      String::FormatIntWidth2(time_struct.tm_mday) + "T" +
+      String::FormatIntWidth2(time_struct.tm_hour) + ":" +
+      String::FormatIntWidth2(time_struct.tm_min) + ":" +
+      String::FormatIntWidth2(time_struct.tm_sec);
+}
+
+// Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
+void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream,
+                                                     const char* data) {
+  const char* segment = data;
+  *stream << "<![CDATA[";
+  for (;;) {
+    const char* const next_segment = strstr(segment, "]]>");
+    if (next_segment != NULL) {
+      stream->write(
+          segment, static_cast<std::streamsize>(next_segment - segment));
+      *stream << "]]>]]&gt;<![CDATA[";
+      segment = next_segment + strlen("]]>");
+    } else {
+      *stream << segment;
+      break;
+    }
+  }
+  *stream << "]]>";
+}
+
+void XmlUnitTestResultPrinter::OutputXmlAttribute(
+    std::ostream* stream,
+    const std::string& element_name,
+    const std::string& name,
+    const std::string& value) {
+  const std::vector<std::string>& allowed_names =
+      GetReservedAttributesForElement(element_name);
+
+  GTEST_CHECK_(std::find(allowed_names.begin(), allowed_names.end(), name) !=
+                   allowed_names.end())
+      << "Attribute " << name << " is not allowed for element <" << element_name
+      << ">.";
+
+  *stream << " " << name << "=\"" << EscapeXmlAttribute(value) << "\"";
+}
+
+// Prints an XML representation of a TestInfo object.
+// TODO(wan): There is also value in printing properties with the plain printer.
+void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream,
+                                                 const char* test_case_name,
+                                                 const TestInfo& test_info) {
+  const TestResult& result = *test_info.result();
+  const std::string kTestcase = "testcase";
+
+  *stream << "    <testcase";
+  OutputXmlAttribute(stream, kTestcase, "name", test_info.name());
+
+  if (test_info.value_param() != NULL) {
+    OutputXmlAttribute(stream, kTestcase, "value_param",
+                       test_info.value_param());
+  }
+  if (test_info.type_param() != NULL) {
+    OutputXmlAttribute(stream, kTestcase, "type_param", test_info.type_param());
+  }
+
+  OutputXmlAttribute(stream, kTestcase, "status",
+                     test_info.should_run() ? "run" : "notrun");
+  OutputXmlAttribute(stream, kTestcase, "time",
+                     FormatTimeInMillisAsSeconds(result.elapsed_time()));
+  OutputXmlAttribute(stream, kTestcase, "classname", test_case_name);
+  *stream << TestPropertiesAsXmlAttributes(result);
+
+  int failures = 0;
+  for (int i = 0; i < result.total_part_count(); ++i) {
+    const TestPartResult& part = result.GetTestPartResult(i);
+    if (part.failed()) {
+      if (++failures == 1) {
+        *stream << ">\n";
+      }
+      const string location = internal::FormatCompilerIndependentFileLocation(
+          part.file_name(), part.line_number());
+      const string summary = location + "\n" + part.summary();
+      *stream << "      <failure message=\""
+              << EscapeXmlAttribute(summary.c_str())
+              << "\" type=\"\">";
+      const string detail = location + "\n" + part.message();
+      OutputXmlCDataSection(stream, RemoveInvalidXmlCharacters(detail).c_str());
+      *stream << "</failure>\n";
+    }
+  }
+
+  if (failures == 0)
+    *stream << " />\n";
+  else
+    *stream << "    </testcase>\n";
+}
+
+// Prints an XML representation of a TestCase object
+void XmlUnitTestResultPrinter::PrintXmlTestCase(std::ostream* stream,
+                                                const TestCase& test_case) {
+  const std::string kTestsuite = "testsuite";
+  *stream << "  <" << kTestsuite;
+  OutputXmlAttribute(stream, kTestsuite, "name", test_case.name());
+  OutputXmlAttribute(stream, kTestsuite, "tests",
+                     StreamableToString(test_case.reportable_test_count()));
+  OutputXmlAttribute(stream, kTestsuite, "failures",
+                     StreamableToString(test_case.failed_test_count()));
+  OutputXmlAttribute(
+      stream, kTestsuite, "disabled",
+      StreamableToString(test_case.reportable_disabled_test_count()));
+  OutputXmlAttribute(stream, kTestsuite, "errors", "0");
+  OutputXmlAttribute(stream, kTestsuite, "time",
+                     FormatTimeInMillisAsSeconds(test_case.elapsed_time()));
+  *stream << TestPropertiesAsXmlAttributes(test_case.ad_hoc_test_result())
+          << ">\n";
+
+  for (int i = 0; i < test_case.total_test_count(); ++i) {
+    if (test_case.GetTestInfo(i)->is_reportable())
+      OutputXmlTestInfo(stream, test_case.name(), *test_case.GetTestInfo(i));
+  }
+  *stream << "  </" << kTestsuite << ">\n";
+}
+
+// Prints an XML summary of unit_test to output stream out.
+void XmlUnitTestResultPrinter::PrintXmlUnitTest(std::ostream* stream,
+                                                const UnitTest& unit_test) {
+  const std::string kTestsuites = "testsuites";
+
+  *stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+  *stream << "<" << kTestsuites;
+
+  OutputXmlAttribute(stream, kTestsuites, "tests",
+                     StreamableToString(unit_test.reportable_test_count()));
+  OutputXmlAttribute(stream, kTestsuites, "failures",
+                     StreamableToString(unit_test.failed_test_count()));
+  OutputXmlAttribute(
+      stream, kTestsuites, "disabled",
+      StreamableToString(unit_test.reportable_disabled_test_count()));
+  OutputXmlAttribute(stream, kTestsuites, "errors", "0");
+  OutputXmlAttribute(
+      stream, kTestsuites, "timestamp",
+      FormatEpochTimeInMillisAsIso8601(unit_test.start_timestamp()));
+  OutputXmlAttribute(stream, kTestsuites, "time",
+                     FormatTimeInMillisAsSeconds(unit_test.elapsed_time()));
+
+  if (GTEST_FLAG(shuffle)) {
+    OutputXmlAttribute(stream, kTestsuites, "random_seed",
+                       StreamableToString(unit_test.random_seed()));
+  }
+
+  *stream << TestPropertiesAsXmlAttributes(unit_test.ad_hoc_test_result());
+
+  OutputXmlAttribute(stream, kTestsuites, "name", "AllTests");
+  *stream << ">\n";
+
+  for (int i = 0; i < unit_test.total_test_case_count(); ++i) {
+    if (unit_test.GetTestCase(i)->reportable_test_count() > 0)
+      PrintXmlTestCase(stream, *unit_test.GetTestCase(i));
+  }
+  *stream << "</" << kTestsuites << ">\n";
+}
+
+// Produces a string representing the test properties in a result as space
+// delimited XML attributes based on the property key="value" pairs.
+std::string XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
+    const TestResult& result) {
+  Message attributes;
+  for (int i = 0; i < result.test_property_count(); ++i) {
+    const TestProperty& property = result.GetTestProperty(i);
+    attributes << " " << property.key() << "="
+        << "\"" << EscapeXmlAttribute(property.value()) << "\"";
+  }
+  return attributes.GetString();
+}
+
+// End XmlUnitTestResultPrinter
+
+#if GTEST_CAN_STREAM_RESULTS_
+
+// Checks if str contains '=', '&', '%' or '\n' characters. If yes,
+// replaces them by "%xx" where xx is their hexadecimal value. For
+// example, replaces "=" with "%3D".  This algorithm is O(strlen(str))
+// in both time and space -- important as the input str may contain an
+// arbitrarily long test failure message and stack trace.
+string StreamingListener::UrlEncode(const char* str) {
+  string result;
+  result.reserve(strlen(str) + 1);
+  for (char ch = *str; ch != '\0'; ch = *++str) {
+    switch (ch) {
+      case '%':
+      case '=':
+      case '&':
+      case '\n':
+        result.append("%" + String::FormatByte(static_cast<unsigned char>(ch)));
+        break;
+      default:
+        result.push_back(ch);
+        break;
+    }
+  }
+  return result;
+}
+
+void StreamingListener::SocketWriter::MakeConnection() {
+  GTEST_CHECK_(sockfd_ == -1)
+      << "MakeConnection() can't be called when there is already a connection.";
+
+  addrinfo hints;
+  memset(&hints, 0, sizeof(hints));
+  hints.ai_family = AF_UNSPEC;    // To allow both IPv4 and IPv6 addresses.
+  hints.ai_socktype = SOCK_STREAM;
+  addrinfo* servinfo = NULL;
+
+  // Use the getaddrinfo() to get a linked list of IP addresses for
+  // the given host name.
+  const int error_num = getaddrinfo(
+      host_name_.c_str(), port_num_.c_str(), &hints, &servinfo);
+  if (error_num != 0) {
+    GTEST_LOG_(WARNING) << "stream_result_to: getaddrinfo() failed: "
+                        << gai_strerror(error_num);
+  }
+
+  // Loop through all the results and connect to the first we can.
+  for (addrinfo* cur_addr = servinfo; sockfd_ == -1 && cur_addr != NULL;
+       cur_addr = cur_addr->ai_next) {
+    sockfd_ = socket(
+        cur_addr->ai_family, cur_addr->ai_socktype, cur_addr->ai_protocol);
+    if (sockfd_ != -1) {
+      // Connect the client socket to the server socket.
+      if (connect(sockfd_, cur_addr->ai_addr, cur_addr->ai_addrlen) == -1) {
+        close(sockfd_);
+        sockfd_ = -1;
+      }
+    }
+  }
+
+  freeaddrinfo(servinfo);  // all done with this structure
+
+  if (sockfd_ == -1) {
+    GTEST_LOG_(WARNING) << "stream_result_to: failed to connect to "
+                        << host_name_ << ":" << port_num_;
+  }
+}
+
+// End of class Streaming Listener
+#endif  // GTEST_CAN_STREAM_RESULTS__
+
+// Class ScopedTrace
+
+// Pushes the given source file location and message onto a per-thread
+// trace stack maintained by Google Test.
+ScopedTrace::ScopedTrace(const char* file, int line, const Message& message)
+    GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) {
+  TraceInfo trace;
+  trace.file = file;
+  trace.line = line;
+  trace.message = message.GetString();
+
+  UnitTest::GetInstance()->PushGTestTrace(trace);
+}
+
+// Pops the info pushed by the c'tor.
+ScopedTrace::~ScopedTrace()
+    GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) {
+  UnitTest::GetInstance()->PopGTestTrace();
+}
+
+
+// class OsStackTraceGetter
+
+const char* const OsStackTraceGetterInterface::kElidedFramesMarker =
+    "... " GTEST_NAME_ " internal frames ...";
+
+string OsStackTraceGetter::CurrentStackTrace(int /*max_depth*/,
+                                             int /*skip_count*/) {
+  return "";
+}
+
+void OsStackTraceGetter::UponLeavingGTest() {}
+
+// A helper class that creates the premature-exit file in its
+// constructor and deletes the file in its destructor.
+class ScopedPrematureExitFile {
+ public:
+  explicit ScopedPrematureExitFile(const char* premature_exit_filepath)
+      : premature_exit_filepath_(premature_exit_filepath) {
+    // If a path to the premature-exit file is specified...
+    if (premature_exit_filepath != NULL && *premature_exit_filepath != '\0') {
+      // create the file with a single "0" character in it.  I/O
+      // errors are ignored as there's nothing better we can do and we
+      // don't want to fail the test because of this.
+      FILE* pfile = posix::FOpen(premature_exit_filepath, "w");
+      fwrite("0", 1, 1, pfile);
+      fclose(pfile);
+    }
+  }
+
+  ~ScopedPrematureExitFile() {
+    if (premature_exit_filepath_ != NULL && *premature_exit_filepath_ != '\0') {
+      remove(premature_exit_filepath_);
+    }
+  }
+
+ private:
+  const char* const premature_exit_filepath_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedPrematureExitFile);
+};
+
+}  // namespace internal
+
+// class TestEventListeners
+
+TestEventListeners::TestEventListeners()
+    : repeater_(new internal::TestEventRepeater()),
+      default_result_printer_(NULL),
+      default_xml_generator_(NULL) {
+}
+
+TestEventListeners::~TestEventListeners() { delete repeater_; }
+
+// Returns the standard listener responsible for the default console
+// output.  Can be removed from the listeners list to shut down default
+// console output.  Note that removing this object from the listener list
+// with Release transfers its ownership to the user.
+void TestEventListeners::Append(TestEventListener* listener) {
+  repeater_->Append(listener);
+}
+
+// Removes the given event listener from the list and returns it.  It then
+// becomes the caller's responsibility to delete the listener. Returns
+// NULL if the listener is not found in the list.
+TestEventListener* TestEventListeners::Release(TestEventListener* listener) {
+  if (listener == default_result_printer_)
+    default_result_printer_ = NULL;
+  else if (listener == default_xml_generator_)
+    default_xml_generator_ = NULL;
+  return repeater_->Release(listener);
+}
+
+// Returns repeater that broadcasts the TestEventListener events to all
+// subscribers.
+TestEventListener* TestEventListeners::repeater() { return repeater_; }
+
+// Sets the default_result_printer attribute to the provided listener.
+// The listener is also added to the listener list and previous
+// default_result_printer is removed from it and deleted. The listener can
+// also be NULL in which case it will not be added to the list. Does
+// nothing if the previous and the current listener objects are the same.
+void TestEventListeners::SetDefaultResultPrinter(TestEventListener* listener) {
+  if (default_result_printer_ != listener) {
+    // It is an error to pass this method a listener that is already in the
+    // list.
+    delete Release(default_result_printer_);
+    default_result_printer_ = listener;
+    if (listener != NULL)
+      Append(listener);
+  }
+}
+
+// Sets the default_xml_generator attribute to the provided listener.  The
+// listener is also added to the listener list and previous
+// default_xml_generator is removed from it and deleted. The listener can
+// also be NULL in which case it will not be added to the list. Does
+// nothing if the previous and the current listener objects are the same.
+void TestEventListeners::SetDefaultXmlGenerator(TestEventListener* listener) {
+  if (default_xml_generator_ != listener) {
+    // It is an error to pass this method a listener that is already in the
+    // list.
+    delete Release(default_xml_generator_);
+    default_xml_generator_ = listener;
+    if (listener != NULL)
+      Append(listener);
+  }
+}
+
+// Controls whether events will be forwarded by the repeater to the
+// listeners in the list.
+bool TestEventListeners::EventForwardingEnabled() const {
+  return repeater_->forwarding_enabled();
+}
+
+void TestEventListeners::SuppressEventForwarding() {
+  repeater_->set_forwarding_enabled(false);
+}
+
+// class UnitTest
+
+// Gets the singleton UnitTest object.  The first time this method is
+// called, a UnitTest object is constructed and returned.  Consecutive
+// calls will return the same object.
+//
+// We don't protect this under mutex_ as a user is not supposed to
+// call this before main() starts, from which point on the return
+// value will never change.
+UnitTest* UnitTest::GetInstance() {
+  // When compiled with MSVC 7.1 in optimized mode, destroying the
+  // UnitTest object upon exiting the program messes up the exit code,
+  // causing successful tests to appear failed.  We have to use a
+  // different implementation in this case to bypass the compiler bug.
+  // This implementation makes the compiler happy, at the cost of
+  // leaking the UnitTest object.
+
+  // CodeGear C++Builder insists on a public destructor for the
+  // default implementation.  Use this implementation to keep good OO
+  // design with private destructor.
+
+#if (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__)
+  static UnitTest* const instance = new UnitTest;
+  return instance;
+#else
+  static UnitTest instance;
+  return &instance;
+#endif  // (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__)
+}
+
+// Gets the number of successful test cases.
+int UnitTest::successful_test_case_count() const {
+  return impl()->successful_test_case_count();
+}
+
+// Gets the number of failed test cases.
+int UnitTest::failed_test_case_count() const {
+  return impl()->failed_test_case_count();
+}
+
+// Gets the number of all test cases.
+int UnitTest::total_test_case_count() const {
+  return impl()->total_test_case_count();
+}
+
+// Gets the number of all test cases that contain at least one test
+// that should run.
+int UnitTest::test_case_to_run_count() const {
+  return impl()->test_case_to_run_count();
+}
+
+// Gets the number of successful tests.
+int UnitTest::successful_test_count() const {
+  return impl()->successful_test_count();
+}
+
+// Gets the number of failed tests.
+int UnitTest::failed_test_count() const { return impl()->failed_test_count(); }
+
+// Gets the number of disabled tests that will be reported in the XML report.
+int UnitTest::reportable_disabled_test_count() const {
+  return impl()->reportable_disabled_test_count();
+}
+
+// Gets the number of disabled tests.
+int UnitTest::disabled_test_count() const {
+  return impl()->disabled_test_count();
+}
+
+// Gets the number of tests to be printed in the XML report.
+int UnitTest::reportable_test_count() const {
+  return impl()->reportable_test_count();
+}
+
+// Gets the number of all tests.
+int UnitTest::total_test_count() const { return impl()->total_test_count(); }
+
+// Gets the number of tests that should run.
+int UnitTest::test_to_run_count() const { return impl()->test_to_run_count(); }
+
+// Gets the time of the test program start, in ms from the start of the
+// UNIX epoch.
+internal::TimeInMillis UnitTest::start_timestamp() const {
+    return impl()->start_timestamp();
+}
+
+// Gets the elapsed time, in milliseconds.
+internal::TimeInMillis UnitTest::elapsed_time() const {
+  return impl()->elapsed_time();
+}
+
+// Returns true iff the unit test passed (i.e. all test cases passed).
+bool UnitTest::Passed() const { return impl()->Passed(); }
+
+// Returns true iff the unit test failed (i.e. some test case failed
+// or something outside of all tests failed).
+bool UnitTest::Failed() const { return impl()->Failed(); }
+
+// Gets the i-th test case among all the test cases. i can range from 0 to
+// total_test_case_count() - 1. If i is not in that range, returns NULL.
+const TestCase* UnitTest::GetTestCase(int i) const {
+  return impl()->GetTestCase(i);
+}
+
+// Returns the TestResult containing information on test failures and
+// properties logged outside of individual test cases.
+const TestResult& UnitTest::ad_hoc_test_result() const {
+  return *impl()->ad_hoc_test_result();
+}
+
+// Gets the i-th test case among all the test cases. i can range from 0 to
+// total_test_case_count() - 1. If i is not in that range, returns NULL.
+TestCase* UnitTest::GetMutableTestCase(int i) {
+  return impl()->GetMutableTestCase(i);
+}
+
+// Returns the list of event listeners that can be used to track events
+// inside Google Test.
+TestEventListeners& UnitTest::listeners() {
+  return *impl()->listeners();
+}
+
+// Registers and returns a global test environment.  When a test
+// program is run, all global test environments will be set-up in the
+// order they were registered.  After all tests in the program have
+// finished, all global test environments will be torn-down in the
+// *reverse* order they were registered.
+//
+// The UnitTest object takes ownership of the given environment.
+//
+// We don't protect this under mutex_, as we only support calling it
+// from the main thread.
+Environment* UnitTest::AddEnvironment(Environment* env) {
+  if (env == NULL) {
+    return NULL;
+  }
+
+  impl_->environments().push_back(env);
+  return env;
+}
+
+// Adds a TestPartResult to the current TestResult object.  All Google Test
+// assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call
+// this to report their results.  The user code should use the
+// assertion macros instead of calling this directly.
+void UnitTest::AddTestPartResult(
+    TestPartResult::Type result_type,
+    const char* file_name,
+    int line_number,
+    const std::string& message,
+    const std::string& os_stack_trace) GTEST_LOCK_EXCLUDED_(mutex_) {
+  Message msg;
+  msg << message;
+
+  internal::MutexLock lock(&mutex_);
+  if (impl_->gtest_trace_stack().size() > 0) {
+    msg << "\n" << GTEST_NAME_ << " trace:";
+
+    for (int i = static_cast<int>(impl_->gtest_trace_stack().size());
+         i > 0; --i) {
+      const internal::TraceInfo& trace = impl_->gtest_trace_stack()[i - 1];
+      msg << "\n" << internal::FormatFileLocation(trace.file, trace.line)
+          << " " << trace.message;
+    }
+  }
+
+  if (os_stack_trace.c_str() != NULL && !os_stack_trace.empty()) {
+    msg << internal::kStackTraceMarker << os_stack_trace;
+  }
+
+  const TestPartResult result =
+    TestPartResult(result_type, file_name, line_number,
+                   msg.GetString().c_str());
+  impl_->GetTestPartResultReporterForCurrentThread()->
+      ReportTestPartResult(result);
+
+  if (result_type != TestPartResult::kSuccess) {
+    // gtest_break_on_failure takes precedence over
+    // gtest_throw_on_failure.  This allows a user to set the latter
+    // in the code (perhaps in order to use Google Test assertions
+    // with another testing framework) and specify the former on the
+    // command line for debugging.
+    if (GTEST_FLAG(break_on_failure)) {
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT
+      // Using DebugBreak on Windows allows gtest to still break into a debugger
+      // when a failure happens and both the --gtest_break_on_failure and
+      // the --gtest_catch_exceptions flags are specified.
+      DebugBreak();
+#else
+      // Dereference NULL through a volatile pointer to prevent the compiler
+      // from removing. We use this rather than abort() or __builtin_trap() for
+      // portability: Symbian doesn't implement abort() well, and some debuggers
+      // don't correctly trap abort().
+      *static_cast<volatile int*>(NULL) = 1;
+#endif  // GTEST_OS_WINDOWS
+    } else if (GTEST_FLAG(throw_on_failure)) {
+#if GTEST_HAS_EXCEPTIONS
+      throw internal::GoogleTestFailureException(result);
+#else
+      // We cannot call abort() as it generates a pop-up in debug mode
+      // that cannot be suppressed in VC 7.1 or below.
+      exit(1);
+#endif
+    }
+  }
+}
+
+// Adds a TestProperty to the current TestResult object when invoked from
+// inside a test, to current TestCase's ad_hoc_test_result_ when invoked
+// from SetUpTestCase or TearDownTestCase, or to the global property set
+// when invoked elsewhere.  If the result already contains a property with
+// the same key, the value will be updated.
+void UnitTest::RecordProperty(const std::string& key,
+                              const std::string& value) {
+  impl_->RecordProperty(TestProperty(key, value));
+}
+
+// Runs all tests in this UnitTest object and prints the result.
+// Returns 0 if successful, or 1 otherwise.
+//
+// We don't protect this under mutex_, as we only support calling it
+// from the main thread.
+int UnitTest::Run() {
+  const bool in_death_test_child_process =
+      internal::GTEST_FLAG(internal_run_death_test).length() > 0;
+
+  // Google Test implements this protocol for catching that a test
+  // program exits before returning control to Google Test:
+  //
+  //   1. Upon start, Google Test creates a file whose absolute path
+  //      is specified by the environment variable
+  //      TEST_PREMATURE_EXIT_FILE.
+  //   2. When Google Test has finished its work, it deletes the file.
+  //
+  // This allows a test runner to set TEST_PREMATURE_EXIT_FILE before
+  // running a Google-Test-based test program and check the existence
+  // of the file at the end of the test execution to see if it has
+  // exited prematurely.
+
+  // If we are in the child process of a death test, don't
+  // create/delete the premature exit file, as doing so is unnecessary
+  // and will confuse the parent process.  Otherwise, create/delete
+  // the file upon entering/leaving this function.  If the program
+  // somehow exits before this function has a chance to return, the
+  // premature-exit file will be left undeleted, causing a test runner
+  // that understands the premature-exit-file protocol to report the
+  // test as having failed.
+  const internal::ScopedPrematureExitFile premature_exit_file(
+      in_death_test_child_process ?
+      NULL : internal::posix::GetEnv("TEST_PREMATURE_EXIT_FILE"));
+
+  // Captures the value of GTEST_FLAG(catch_exceptions).  This value will be
+  // used for the duration of the program.
+  impl()->set_catch_exceptions(GTEST_FLAG(catch_exceptions));
+
+#if GTEST_HAS_SEH
+  // Either the user wants Google Test to catch exceptions thrown by the
+  // tests or this is executing in the context of death test child
+  // process. In either case the user does not want to see pop-up dialogs
+  // about crashes - they are expected.
+  if (impl()->catch_exceptions() || in_death_test_child_process) {
+# if !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT
+    // SetErrorMode doesn't exist on CE.
+    SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
+                 SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
+# endif  // !GTEST_OS_WINDOWS_MOBILE
+
+# if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE
+    // Death test children can be terminated with _abort().  On Windows,
+    // _abort() can show a dialog with a warning message.  This forces the
+    // abort message to go to stderr instead.
+    _set_error_mode(_OUT_TO_STDERR);
+# endif
+
+# if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE
+    // In the debug version, Visual Studio pops up a separate dialog
+    // offering a choice to debug the aborted program. We need to suppress
+    // this dialog or it will pop up for every EXPECT/ASSERT_DEATH statement
+    // executed. Google Test will notify the user of any unexpected
+    // failure via stderr.
+    //
+    // VC++ doesn't define _set_abort_behavior() prior to the version 8.0.
+    // Users of prior VC versions shall suffer the agony and pain of
+    // clicking through the countless debug dialogs.
+    // TODO(vladl@google.com): find a way to suppress the abort dialog() in the
+    // debug mode when compiled with VC 7.1 or lower.
+    if (!GTEST_FLAG(break_on_failure))
+      _set_abort_behavior(
+          0x0,                                    // Clear the following flags:
+          _WRITE_ABORT_MSG | _CALL_REPORTFAULT);  // pop-up window, core dump.
+# endif
+  }
+#endif  // GTEST_HAS_SEH
+
+  return internal::HandleExceptionsInMethodIfSupported(
+      impl(),
+      &internal::UnitTestImpl::RunAllTests,
+      "auxiliary test code (environments or event listeners)") ? 0 : 1;
+}
+
+// Returns the working directory when the first TEST() or TEST_F() was
+// executed.
+const char* UnitTest::original_working_dir() const {
+  return impl_->original_working_dir_.c_str();
+}
+
+// Returns the TestCase object for the test that's currently running,
+// or NULL if no test is running.
+const TestCase* UnitTest::current_test_case() const
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+  internal::MutexLock lock(&mutex_);
+  return impl_->current_test_case();
+}
+
+// Returns the TestInfo object for the test that's currently running,
+// or NULL if no test is running.
+const TestInfo* UnitTest::current_test_info() const
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+  internal::MutexLock lock(&mutex_);
+  return impl_->current_test_info();
+}
+
+// Returns the random seed used at the start of the current test run.
+int UnitTest::random_seed() const { return impl_->random_seed(); }
+
+#if GTEST_HAS_PARAM_TEST
+// Returns ParameterizedTestCaseRegistry object used to keep track of
+// value-parameterized tests and instantiate and register them.
+internal::ParameterizedTestCaseRegistry&
+    UnitTest::parameterized_test_registry()
+        GTEST_LOCK_EXCLUDED_(mutex_) {
+  return impl_->parameterized_test_registry();
+}
+#endif  // GTEST_HAS_PARAM_TEST
+
+// Creates an empty UnitTest.
+UnitTest::UnitTest() {
+  impl_ = new internal::UnitTestImpl(this);
+}
+
+// Destructor of UnitTest.
+UnitTest::~UnitTest() {
+  delete impl_;
+}
+
+// Pushes a trace defined by SCOPED_TRACE() on to the per-thread
+// Google Test trace stack.
+void UnitTest::PushGTestTrace(const internal::TraceInfo& trace)
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+  internal::MutexLock lock(&mutex_);
+  impl_->gtest_trace_stack().push_back(trace);
+}
+
+// Pops a trace from the per-thread Google Test trace stack.
+void UnitTest::PopGTestTrace()
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+  internal::MutexLock lock(&mutex_);
+  impl_->gtest_trace_stack().pop_back();
+}
+
+namespace internal {
+
+UnitTestImpl::UnitTestImpl(UnitTest* parent)
+    : parent_(parent),
+      GTEST_DISABLE_MSC_WARNINGS_PUSH_(4355 /* using this in initializer */)
+      default_global_test_part_result_reporter_(this),
+      default_per_thread_test_part_result_reporter_(this),
+      GTEST_DISABLE_MSC_WARNINGS_POP_()
+      global_test_part_result_repoter_(
+          &default_global_test_part_result_reporter_),
+      per_thread_test_part_result_reporter_(
+          &default_per_thread_test_part_result_reporter_),
+#if GTEST_HAS_PARAM_TEST
+      parameterized_test_registry_(),
+      parameterized_tests_registered_(false),
+#endif  // GTEST_HAS_PARAM_TEST
+      last_death_test_case_(-1),
+      current_test_case_(NULL),
+      current_test_info_(NULL),
+      ad_hoc_test_result_(),
+      os_stack_trace_getter_(NULL),
+      post_flag_parse_init_performed_(false),
+      random_seed_(0),  // Will be overridden by the flag before first use.
+      random_(0),  // Will be reseeded before first use.
+      start_timestamp_(0),
+      elapsed_time_(0),
+#if GTEST_HAS_DEATH_TEST
+      death_test_factory_(new DefaultDeathTestFactory),
+#endif
+      // Will be overridden by the flag before first use.
+      catch_exceptions_(false) {
+  listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter);
+}
+
+UnitTestImpl::~UnitTestImpl() {
+  // Deletes every TestCase.
+  ForEach(test_cases_, internal::Delete<TestCase>);
+
+  // Deletes every Environment.
+  ForEach(environments_, internal::Delete<Environment>);
+
+  delete os_stack_trace_getter_;
+}
+
+// Adds a TestProperty to the current TestResult object when invoked in a
+// context of a test, to current test case's ad_hoc_test_result when invoke
+// from SetUpTestCase/TearDownTestCase, or to the global property set
+// otherwise.  If the result already contains a property with the same key,
+// the value will be updated.
+void UnitTestImpl::RecordProperty(const TestProperty& test_property) {
+  std::string xml_element;
+  TestResult* test_result;  // TestResult appropriate for property recording.
+
+  if (current_test_info_ != NULL) {
+    xml_element = "testcase";
+    test_result = &(current_test_info_->result_);
+  } else if (current_test_case_ != NULL) {
+    xml_element = "testsuite";
+    test_result = &(current_test_case_->ad_hoc_test_result_);
+  } else {
+    xml_element = "testsuites";
+    test_result = &ad_hoc_test_result_;
+  }
+  test_result->RecordProperty(xml_element, test_property);
+}
+
+#if GTEST_HAS_DEATH_TEST
+// Disables event forwarding if the control is currently in a death test
+// subprocess. Must not be called before InitGoogleTest.
+void UnitTestImpl::SuppressTestEventsIfInSubprocess() {
+  if (internal_run_death_test_flag_.get() != NULL)
+    listeners()->SuppressEventForwarding();
+}
+#endif  // GTEST_HAS_DEATH_TEST
+
+// Initializes event listeners performing XML output as specified by
+// UnitTestOptions. Must not be called before InitGoogleTest.
+void UnitTestImpl::ConfigureXmlOutput() {
+  const std::string& output_format = UnitTestOptions::GetOutputFormat();
+  if (output_format == "xml") {
+    listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter(
+        UnitTestOptions::GetAbsolutePathToOutputFile().c_str()));
+  } else if (output_format != "") {
+    printf("WARNING: unrecognized output format \"%s\" ignored.\n",
+           output_format.c_str());
+    fflush(stdout);
+  }
+}
+
+#if GTEST_CAN_STREAM_RESULTS_
+// Initializes event listeners for streaming test results in string form.
+// Must not be called before InitGoogleTest.
+void UnitTestImpl::ConfigureStreamingOutput() {
+  const std::string& target = GTEST_FLAG(stream_result_to);
+  if (!target.empty()) {
+    const size_t pos = target.find(':');
+    if (pos != std::string::npos) {
+      listeners()->Append(new StreamingListener(target.substr(0, pos),
+                                                target.substr(pos+1)));
+    } else {
+      printf("WARNING: unrecognized streaming target \"%s\" ignored.\n",
+             target.c_str());
+      fflush(stdout);
+    }
+  }
+}
+#endif  // GTEST_CAN_STREAM_RESULTS_
+
+// Performs initialization dependent upon flag values obtained in
+// ParseGoogleTestFlagsOnly.  Is called from InitGoogleTest after the call to
+// ParseGoogleTestFlagsOnly.  In case a user neglects to call InitGoogleTest
+// this function is also called from RunAllTests.  Since this function can be
+// called more than once, it has to be idempotent.
+void UnitTestImpl::PostFlagParsingInit() {
+  // Ensures that this function does not execute more than once.
+  if (!post_flag_parse_init_performed_) {
+    post_flag_parse_init_performed_ = true;
+
+#if defined(GTEST_CUSTOM_TEST_EVENT_LISTENER_)
+    // Register to send notifications about key process state changes.
+    listeners()->Append(new GTEST_CUSTOM_TEST_EVENT_LISTENER_());
+#endif  // defined(GTEST_CUSTOM_TEST_EVENT_LISTENER_)
+
+#if GTEST_HAS_DEATH_TEST
+    InitDeathTestSubprocessControlInfo();
+    SuppressTestEventsIfInSubprocess();
+#endif  // GTEST_HAS_DEATH_TEST
+
+    // Registers parameterized tests. This makes parameterized tests
+    // available to the UnitTest reflection API without running
+    // RUN_ALL_TESTS.
+    RegisterParameterizedTests();
+
+    // Configures listeners for XML output. This makes it possible for users
+    // to shut down the default XML output before invoking RUN_ALL_TESTS.
+    ConfigureXmlOutput();
+
+#if GTEST_CAN_STREAM_RESULTS_
+    // Configures listeners for streaming test results to the specified server.
+    ConfigureStreamingOutput();
+#endif  // GTEST_CAN_STREAM_RESULTS_
+  }
+}
+
+// A predicate that checks the name of a TestCase against a known
+// value.
+//
+// This is used for implementation of the UnitTest class only.  We put
+// it in the anonymous namespace to prevent polluting the outer
+// namespace.
+//
+// TestCaseNameIs is copyable.
+class TestCaseNameIs {
+ public:
+  // Constructor.
+  explicit TestCaseNameIs(const std::string& name)
+      : name_(name) {}
+
+  // Returns true iff the name of test_case matches name_.
+  bool operator()(const TestCase* test_case) const {
+    return test_case != NULL && strcmp(test_case->name(), name_.c_str()) == 0;
+  }
+
+ private:
+  std::string name_;
+};
+
+// Finds and returns a TestCase with the given name.  If one doesn't
+// exist, creates one and returns it.  It's the CALLER'S
+// RESPONSIBILITY to ensure that this function is only called WHEN THE
+// TESTS ARE NOT SHUFFLED.
+//
+// Arguments:
+//
+//   test_case_name: name of the test case
+//   type_param:     the name of the test case's type parameter, or NULL if
+//                   this is not a typed or a type-parameterized test case.
+//   set_up_tc:      pointer to the function that sets up the test case
+//   tear_down_tc:   pointer to the function that tears down the test case
+TestCase* UnitTestImpl::GetTestCase(const char* test_case_name,
+                                    const char* type_param,
+                                    Test::SetUpTestCaseFunc set_up_tc,
+                                    Test::TearDownTestCaseFunc tear_down_tc) {
+  // Can we find a TestCase with the given name?
+  const std::vector<TestCase*>::const_iterator test_case =
+      std::find_if(test_cases_.begin(), test_cases_.end(),
+                   TestCaseNameIs(test_case_name));
+
+  if (test_case != test_cases_.end())
+    return *test_case;
+
+  // No.  Let's create one.
+  TestCase* const new_test_case =
+      new TestCase(test_case_name, type_param, set_up_tc, tear_down_tc);
+
+  // Is this a death test case?
+  if (internal::UnitTestOptions::MatchesFilter(test_case_name,
+                                               kDeathTestCaseFilter)) {
+    // Yes.  Inserts the test case after the last death test case
+    // defined so far.  This only works when the test cases haven't
+    // been shuffled.  Otherwise we may end up running a death test
+    // after a non-death test.
+    ++last_death_test_case_;
+    test_cases_.insert(test_cases_.begin() + last_death_test_case_,
+                       new_test_case);
+  } else {
+    // No.  Appends to the end of the list.
+    test_cases_.push_back(new_test_case);
+  }
+
+  test_case_indices_.push_back(static_cast<int>(test_case_indices_.size()));
+  return new_test_case;
+}
+
+// Helpers for setting up / tearing down the given environment.  They
+// are for use in the ForEach() function.
+static void SetUpEnvironment(Environment* env) { env->SetUp(); }
+static void TearDownEnvironment(Environment* env) { env->TearDown(); }
+
+// Runs all tests in this UnitTest object, prints the result, and
+// returns true if all tests are successful.  If any exception is
+// thrown during a test, the test is considered to be failed, but the
+// rest of the tests will still be run.
+//
+// When parameterized tests are enabled, it expands and registers
+// parameterized tests first in RegisterParameterizedTests().
+// All other functions called from RunAllTests() may safely assume that
+// parameterized tests are ready to be counted and run.
+bool UnitTestImpl::RunAllTests() {
+  // Makes sure InitGoogleTest() was called.
+  if (!GTestIsInitialized()) {
+    printf("%s",
+           "\nThis test program did NOT call ::testing::InitGoogleTest "
+           "before calling RUN_ALL_TESTS().  Please fix it.\n");
+    return false;
+  }
+
+  // Do not run any test if the --help flag was specified.
+  if (g_help_flag)
+    return true;
+
+  // Repeats the call to the post-flag parsing initialization in case the
+  // user didn't call InitGoogleTest.
+  PostFlagParsingInit();
+
+  // Even if sharding is not on, test runners may want to use the
+  // GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding
+  // protocol.
+  internal::WriteToShardStatusFileIfNeeded();
+
+  // True iff we are in a subprocess for running a thread-safe-style
+  // death test.
+  bool in_subprocess_for_death_test = false;
+
+#if GTEST_HAS_DEATH_TEST
+  in_subprocess_for_death_test = (internal_run_death_test_flag_.get() != NULL);
+# if defined(GTEST_EXTRA_DEATH_TEST_CHILD_SETUP_)
+  if (in_subprocess_for_death_test) {
+    GTEST_EXTRA_DEATH_TEST_CHILD_SETUP_();
+  }
+# endif  // defined(GTEST_EXTRA_DEATH_TEST_CHILD_SETUP_)
+#endif  // GTEST_HAS_DEATH_TEST
+
+  const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex,
+                                        in_subprocess_for_death_test);
+
+  // Compares the full test names with the filter to decide which
+  // tests to run.
+  const bool has_tests_to_run = FilterTests(should_shard
+                                              ? HONOR_SHARDING_PROTOCOL
+                                              : IGNORE_SHARDING_PROTOCOL) > 0;
+
+  // Lists the tests and exits if the --gtest_list_tests flag was specified.
+  if (GTEST_FLAG(list_tests)) {
+    // This must be called *after* FilterTests() has been called.
+    ListTestsMatchingFilter();
+    return true;
+  }
+
+  random_seed_ = GTEST_FLAG(shuffle) ?
+      GetRandomSeedFromFlag(GTEST_FLAG(random_seed)) : 0;
+
+  // True iff at least one test has failed.
+  bool failed = false;
+
+  TestEventListener* repeater = listeners()->repeater();
+
+  start_timestamp_ = GetTimeInMillis();
+  repeater->OnTestProgramStart(*parent_);
+
+  // How many times to repeat the tests?  We don't want to repeat them
+  // when we are inside the subprocess of a death test.
+  const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat);
+  // Repeats forever if the repeat count is negative.
+  const bool forever = repeat < 0;
+  for (int i = 0; forever || i != repeat; i++) {
+    // We want to preserve failures generated by ad-hoc test
+    // assertions executed before RUN_ALL_TESTS().
+    ClearNonAdHocTestResult();
+
+    const TimeInMillis start = GetTimeInMillis();
+
+    // Shuffles test cases and tests if requested.
+    if (has_tests_to_run && GTEST_FLAG(shuffle)) {
+      random()->Reseed(random_seed_);
+      // This should be done before calling OnTestIterationStart(),
+      // such that a test event listener can see the actual test order
+      // in the event.
+      ShuffleTests();
+    }
+
+    // Tells the unit test event listeners that the tests are about to start.
+    repeater->OnTestIterationStart(*parent_, i);
+
+    // Runs each test case if there is at least one test to run.
+    if (has_tests_to_run) {
+      // Sets up all environments beforehand.
+      repeater->OnEnvironmentsSetUpStart(*parent_);
+      ForEach(environments_, SetUpEnvironment);
+      repeater->OnEnvironmentsSetUpEnd(*parent_);
+
+      // Runs the tests only if there was no fatal failure during global
+      // set-up.
+      if (!Test::HasFatalFailure()) {
+        for (int test_index = 0; test_index < total_test_case_count();
+             test_index++) {
+          GetMutableTestCase(test_index)->Run();
+        }
+      }
+
+      // Tears down all environments in reverse order afterwards.
+      repeater->OnEnvironmentsTearDownStart(*parent_);
+      std::for_each(environments_.rbegin(), environments_.rend(),
+                    TearDownEnvironment);
+      repeater->OnEnvironmentsTearDownEnd(*parent_);
+    }
+
+    elapsed_time_ = GetTimeInMillis() - start;
+
+    // Tells the unit test event listener that the tests have just finished.
+    repeater->OnTestIterationEnd(*parent_, i);
+
+    // Gets the result and clears it.
+    if (!Passed()) {
+      failed = true;
+    }
+
+    // Restores the original test order after the iteration.  This
+    // allows the user to quickly repro a failure that happens in the
+    // N-th iteration without repeating the first (N - 1) iterations.
+    // This is not enclosed in "if (GTEST_FLAG(shuffle)) { ... }", in
+    // case the user somehow changes the value of the flag somewhere
+    // (it's always safe to unshuffle the tests).
+    UnshuffleTests();
+
+    if (GTEST_FLAG(shuffle)) {
+      // Picks a new random seed for each iteration.
+      random_seed_ = GetNextRandomSeed(random_seed_);
+    }
+  }
+
+  repeater->OnTestProgramEnd(*parent_);
+
+  return !failed;
+}
+
+// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
+// if the variable is present. If a file already exists at this location, this
+// function will write over it. If the variable is present, but the file cannot
+// be created, prints an error and exits.
+void WriteToShardStatusFileIfNeeded() {
+  const char* const test_shard_file = posix::GetEnv(kTestShardStatusFile);
+  if (test_shard_file != NULL) {
+    FILE* const file = posix::FOpen(test_shard_file, "w");
+    if (file == NULL) {
+      ColoredPrintf(COLOR_RED,
+                    "Could not write to the test shard status file \"%s\" "
+                    "specified by the %s environment variable.\n",
+                    test_shard_file, kTestShardStatusFile);
+      fflush(stdout);
+      exit(EXIT_FAILURE);
+    }
+    fclose(file);
+  }
+}
+
+// Checks whether sharding is enabled by examining the relevant
+// environment variable values. If the variables are present,
+// but inconsistent (i.e., shard_index >= total_shards), prints
+// an error and exits. If in_subprocess_for_death_test, sharding is
+// disabled because it must only be applied to the original test
+// process. Otherwise, we could filter out death tests we intended to execute.
+bool ShouldShard(const char* total_shards_env,
+                 const char* shard_index_env,
+                 bool in_subprocess_for_death_test) {
+  if (in_subprocess_for_death_test) {
+    return false;
+  }
+
+  const Int32 total_shards = Int32FromEnvOrDie(total_shards_env, -1);
+  const Int32 shard_index = Int32FromEnvOrDie(shard_index_env, -1);
+
+  if (total_shards == -1 && shard_index == -1) {
+    return false;
+  } else if (total_shards == -1 && shard_index != -1) {
+    const Message msg = Message()
+      << "Invalid environment variables: you have "
+      << kTestShardIndex << " = " << shard_index
+      << ", but have left " << kTestTotalShards << " unset.\n";
+    ColoredPrintf(COLOR_RED, msg.GetString().c_str());
+    fflush(stdout);
+    exit(EXIT_FAILURE);
+  } else if (total_shards != -1 && shard_index == -1) {
+    const Message msg = Message()
+      << "Invalid environment variables: you have "
+      << kTestTotalShards << " = " << total_shards
+      << ", but have left " << kTestShardIndex << " unset.\n";
+    ColoredPrintf(COLOR_RED, msg.GetString().c_str());
+    fflush(stdout);
+    exit(EXIT_FAILURE);
+  } else if (shard_index < 0 || shard_index >= total_shards) {
+    const Message msg = Message()
+      << "Invalid environment variables: we require 0 <= "
+      << kTestShardIndex << " < " << kTestTotalShards
+      << ", but you have " << kTestShardIndex << "=" << shard_index
+      << ", " << kTestTotalShards << "=" << total_shards << ".\n";
+    ColoredPrintf(COLOR_RED, msg.GetString().c_str());
+    fflush(stdout);
+    exit(EXIT_FAILURE);
+  }
+
+  return total_shards > 1;
+}
+
+// Parses the environment variable var as an Int32. If it is unset,
+// returns default_val. If it is not an Int32, prints an error
+// and aborts.
+Int32 Int32FromEnvOrDie(const char* var, Int32 default_val) {
+  const char* str_val = posix::GetEnv(var);
+  if (str_val == NULL) {
+    return default_val;
+  }
+
+  Int32 result;
+  if (!ParseInt32(Message() << "The value of environment variable " << var,
+                  str_val, &result)) {
+    exit(EXIT_FAILURE);
+  }
+  return result;
+}
+
+// Given the total number of shards, the shard index, and the test id,
+// returns true iff the test should be run on this shard. The test id is
+// some arbitrary but unique non-negative integer assigned to each test
+// method. Assumes that 0 <= shard_index < total_shards.
+bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) {
+  return (test_id % total_shards) == shard_index;
+}
+
+// Compares the name of each test with the user-specified filter to
+// decide whether the test should be run, then records the result in
+// each TestCase and TestInfo object.
+// If shard_tests == true, further filters tests based on sharding
+// variables in the environment - see
+// http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide.
+// Returns the number of tests that should run.
+int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
+  const Int32 total_shards = shard_tests == HONOR_SHARDING_PROTOCOL ?
+      Int32FromEnvOrDie(kTestTotalShards, -1) : -1;
+  const Int32 shard_index = shard_tests == HONOR_SHARDING_PROTOCOL ?
+      Int32FromEnvOrDie(kTestShardIndex, -1) : -1;
+
+  // num_runnable_tests are the number of tests that will
+  // run across all shards (i.e., match filter and are not disabled).
+  // num_selected_tests are the number of tests to be run on
+  // this shard.
+  int num_runnable_tests = 0;
+  int num_selected_tests = 0;
+  for (size_t i = 0; i < test_cases_.size(); i++) {
+    TestCase* const test_case = test_cases_[i];
+    const std::string &test_case_name = test_case->name();
+    test_case->set_should_run(false);
+
+    for (size_t j = 0; j < test_case->test_info_list().size(); j++) {
+      TestInfo* const test_info = test_case->test_info_list()[j];
+      const std::string test_name(test_info->name());
+      // A test is disabled if test case name or test name matches
+      // kDisableTestFilter.
+      const bool is_disabled =
+          internal::UnitTestOptions::MatchesFilter(test_case_name,
+                                                   kDisableTestFilter) ||
+          internal::UnitTestOptions::MatchesFilter(test_name,
+                                                   kDisableTestFilter);
+      test_info->is_disabled_ = is_disabled;
+
+      const bool matches_filter =
+          internal::UnitTestOptions::FilterMatchesTest(test_case_name,
+                                                       test_name);
+      test_info->matches_filter_ = matches_filter;
+
+      const bool is_runnable =
+          (GTEST_FLAG(also_run_disabled_tests) || !is_disabled) &&
+          matches_filter;
+
+      const bool is_selected = is_runnable &&
+          (shard_tests == IGNORE_SHARDING_PROTOCOL ||
+           ShouldRunTestOnShard(total_shards, shard_index,
+                                num_runnable_tests));
+
+      num_runnable_tests += is_runnable;
+      num_selected_tests += is_selected;
+
+      test_info->should_run_ = is_selected;
+      test_case->set_should_run(test_case->should_run() || is_selected);
+    }
+  }
+  return num_selected_tests;
+}
+
+// Prints the given C-string on a single line by replacing all '\n'
+// characters with string "\\n".  If the output takes more than
+// max_length characters, only prints the first max_length characters
+// and "...".
+static void PrintOnOneLine(const char* str, int max_length) {
+  if (str != NULL) {
+    for (int i = 0; *str != '\0'; ++str) {
+      if (i >= max_length) {
+        printf("...");
+        break;
+      }
+      if (*str == '\n') {
+        printf("\\n");
+        i += 2;
+      } else {
+        printf("%c", *str);
+        ++i;
+      }
+    }
+  }
+}
+
+// Prints the names of the tests matching the user-specified filter flag.
+void UnitTestImpl::ListTestsMatchingFilter() {
+  // Print at most this many characters for each type/value parameter.
+  const int kMaxParamLength = 250;
+
+  for (size_t i = 0; i < test_cases_.size(); i++) {
+    const TestCase* const test_case = test_cases_[i];
+    bool printed_test_case_name = false;
+
+    for (size_t j = 0; j < test_case->test_info_list().size(); j++) {
+      const TestInfo* const test_info =
+          test_case->test_info_list()[j];
+      if (test_info->matches_filter_) {
+        if (!printed_test_case_name) {
+          printed_test_case_name = true;
+          printf("%s.", test_case->name());
+          if (test_case->type_param() != NULL) {
+            printf("  # %s = ", kTypeParamLabel);
+            // We print the type parameter on a single line to make
+            // the output easy to parse by a program.
+            PrintOnOneLine(test_case->type_param(), kMaxParamLength);
+          }
+          printf("\n");
+        }
+        printf("  %s", test_info->name());
+        if (test_info->value_param() != NULL) {
+          printf("  # %s = ", kValueParamLabel);
+          // We print the value parameter on a single line to make the
+          // output easy to parse by a program.
+          PrintOnOneLine(test_info->value_param(), kMaxParamLength);
+        }
+        printf("\n");
+      }
+    }
+  }
+  fflush(stdout);
+}
+
+// Sets the OS stack trace getter.
+//
+// Does nothing if the input and the current OS stack trace getter are
+// the same; otherwise, deletes the old getter and makes the input the
+// current getter.
+void UnitTestImpl::set_os_stack_trace_getter(
+    OsStackTraceGetterInterface* getter) {
+  if (os_stack_trace_getter_ != getter) {
+    delete os_stack_trace_getter_;
+    os_stack_trace_getter_ = getter;
+  }
+}
+
+// Returns the current OS stack trace getter if it is not NULL;
+// otherwise, creates an OsStackTraceGetter, makes it the current
+// getter, and returns it.
+OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() {
+  if (os_stack_trace_getter_ == NULL) {
+#ifdef GTEST_OS_STACK_TRACE_GETTER_
+    os_stack_trace_getter_ = new GTEST_OS_STACK_TRACE_GETTER_;
+#else
+    os_stack_trace_getter_ = new OsStackTraceGetter;
+#endif  // GTEST_OS_STACK_TRACE_GETTER_
+  }
+
+  return os_stack_trace_getter_;
+}
+
+// Returns the TestResult for the test that's currently running, or
+// the TestResult for the ad hoc test if no test is running.
+TestResult* UnitTestImpl::current_test_result() {
+  return current_test_info_ ?
+      &(current_test_info_->result_) : &ad_hoc_test_result_;
+}
+
+// Shuffles all test cases, and the tests within each test case,
+// making sure that death tests are still run first.
+void UnitTestImpl::ShuffleTests() {
+  // Shuffles the death test cases.
+  ShuffleRange(random(), 0, last_death_test_case_ + 1, &test_case_indices_);
+
+  // Shuffles the non-death test cases.
+  ShuffleRange(random(), last_death_test_case_ + 1,
+               static_cast<int>(test_cases_.size()), &test_case_indices_);
+
+  // Shuffles the tests inside each test case.
+  for (size_t i = 0; i < test_cases_.size(); i++) {
+    test_cases_[i]->ShuffleTests(random());
+  }
+}
+
+// Restores the test cases and tests to their order before the first shuffle.
+void UnitTestImpl::UnshuffleTests() {
+  for (size_t i = 0; i < test_cases_.size(); i++) {
+    // Unshuffles the tests in each test case.
+    test_cases_[i]->UnshuffleTests();
+    // Resets the index of each test case.
+    test_case_indices_[i] = static_cast<int>(i);
+  }
+}
+
+// Returns the current OS stack trace as an std::string.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag.  The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in
+// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't.
+std::string GetCurrentOsStackTraceExceptTop(UnitTest* /*unit_test*/,
+                                            int skip_count) {
+  // We pass skip_count + 1 to skip this wrapper function in addition
+  // to what the user really wants to skip.
+  return GetUnitTestImpl()->CurrentOsStackTraceExceptTop(skip_count + 1);
+}
+
+// Used by the GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_ macro to
+// suppress unreachable code warnings.
+namespace {
+class ClassUniqueToAlwaysTrue {};
+}
+
+bool IsTrue(bool condition) { return condition; }
+
+bool AlwaysTrue() {
+#if GTEST_HAS_EXCEPTIONS
+  // This condition is always false so AlwaysTrue() never actually throws,
+  // but it makes the compiler think that it may throw.
+  if (IsTrue(false))
+    throw ClassUniqueToAlwaysTrue();
+#endif  // GTEST_HAS_EXCEPTIONS
+  return true;
+}
+
+// If *pstr starts with the given prefix, modifies *pstr to be right
+// past the prefix and returns true; otherwise leaves *pstr unchanged
+// and returns false.  None of pstr, *pstr, and prefix can be NULL.
+bool SkipPrefix(const char* prefix, const char** pstr) {
+  const size_t prefix_len = strlen(prefix);
+  if (strncmp(*pstr, prefix, prefix_len) == 0) {
+    *pstr += prefix_len;
+    return true;
+  }
+  return false;
+}
+
+// Parses a string as a command line flag.  The string should have
+// the format "--flag=value".  When def_optional is true, the "=value"
+// part can be omitted.
+//
+// Returns the value of the flag, or NULL if the parsing failed.
+const char* ParseFlagValue(const char* str,
+                           const char* flag,
+                           bool def_optional) {
+  // str and flag must not be NULL.
+  if (str == NULL || flag == NULL) return NULL;
+
+  // The flag must start with "--" followed by GTEST_FLAG_PREFIX_.
+  const std::string flag_str = std::string("--") + GTEST_FLAG_PREFIX_ + flag;
+  const size_t flag_len = flag_str.length();
+  if (strncmp(str, flag_str.c_str(), flag_len) != 0) return NULL;
+
+  // Skips the flag name.
+  const char* flag_end = str + flag_len;
+
+  // When def_optional is true, it's OK to not have a "=value" part.
+  if (def_optional && (flag_end[0] == '\0')) {
+    return flag_end;
+  }
+
+  // If def_optional is true and there are more characters after the
+  // flag name, or if def_optional is false, there must be a '=' after
+  // the flag name.
+  if (flag_end[0] != '=') return NULL;
+
+  // Returns the string after "=".
+  return flag_end + 1;
+}
+
+// Parses a string for a bool flag, in the form of either
+// "--flag=value" or "--flag".
+//
+// In the former case, the value is taken as true as long as it does
+// not start with '0', 'f', or 'F'.
+//
+// In the latter case, the value is taken as true.
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+bool ParseBoolFlag(const char* str, const char* flag, bool* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseFlagValue(str, flag, true);
+
+  // Aborts if the parsing failed.
+  if (value_str == NULL) return false;
+
+  // Converts the string value to a bool.
+  *value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F');
+  return true;
+}
+
+// Parses a string for an Int32 flag, in the form of
+// "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+bool ParseInt32Flag(const char* str, const char* flag, Int32* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseFlagValue(str, flag, false);
+
+  // Aborts if the parsing failed.
+  if (value_str == NULL) return false;
+
+  // Sets *value to the value of the flag.
+  return ParseInt32(Message() << "The value of flag --" << flag,
+                    value_str, value);
+}
+
+// Parses a string for a string flag, in the form of
+// "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+bool ParseStringFlag(const char* str, const char* flag, std::string* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseFlagValue(str, flag, false);
+
+  // Aborts if the parsing failed.
+  if (value_str == NULL) return false;
+
+  // Sets *value to the value of the flag.
+  *value = value_str;
+  return true;
+}
+
+// Determines whether a string has a prefix that Google Test uses for its
+// flags, i.e., starts with GTEST_FLAG_PREFIX_ or GTEST_FLAG_PREFIX_DASH_.
+// If Google Test detects that a command line flag has its prefix but is not
+// recognized, it will print its help message. Flags starting with
+// GTEST_INTERNAL_PREFIX_ followed by "internal_" are considered Google Test
+// internal flags and do not trigger the help message.
+static bool HasGoogleTestFlagPrefix(const char* str) {
+  return (SkipPrefix("--", &str) ||
+          SkipPrefix("-", &str) ||
+          SkipPrefix("/", &str)) &&
+         !SkipPrefix(GTEST_FLAG_PREFIX_ "internal_", &str) &&
+         (SkipPrefix(GTEST_FLAG_PREFIX_, &str) ||
+          SkipPrefix(GTEST_FLAG_PREFIX_DASH_, &str));
+}
+
+// Prints a string containing code-encoded text.  The following escape
+// sequences can be used in the string to control the text color:
+//
+//   @@    prints a single '@' character.
+//   @R    changes the color to red.
+//   @G    changes the color to green.
+//   @Y    changes the color to yellow.
+//   @D    changes to the default terminal text color.
+//
+// TODO(wan@google.com): Write tests for this once we add stdout
+// capturing to Google Test.
+static void PrintColorEncoded(const char* str) {
+  GTestColor color = COLOR_DEFAULT;  // The current color.
+
+  // Conceptually, we split the string into segments divided by escape
+  // sequences.  Then we print one segment at a time.  At the end of
+  // each iteration, the str pointer advances to the beginning of the
+  // next segment.
+  for (;;) {
+    const char* p = strchr(str, '@');
+    if (p == NULL) {
+      ColoredPrintf(color, "%s", str);
+      return;
+    }
+
+    ColoredPrintf(color, "%s", std::string(str, p).c_str());
+
+    const char ch = p[1];
+    str = p + 2;
+    if (ch == '@') {
+      ColoredPrintf(color, "@");
+    } else if (ch == 'D') {
+      color = COLOR_DEFAULT;
+    } else if (ch == 'R') {
+      color = COLOR_RED;
+    } else if (ch == 'G') {
+      color = COLOR_GREEN;
+    } else if (ch == 'Y') {
+      color = COLOR_YELLOW;
+    } else {
+      --str;
+    }
+  }
+}
+
+static const char kColorEncodedHelpMessage[] =
+"This program contains tests written using " GTEST_NAME_ ". You can use the\n"
+"following command line flags to control its behavior:\n"
+"\n"
+"Test Selection:\n"
+"  @G--" GTEST_FLAG_PREFIX_ "list_tests@D\n"
+"      List the names of all tests instead of running them. The name of\n"
+"      TEST(Foo, Bar) is \"Foo.Bar\".\n"
+"  @G--" GTEST_FLAG_PREFIX_ "filter=@YPOSTIVE_PATTERNS"
+    "[@G-@YNEGATIVE_PATTERNS]@D\n"
+"      Run only the tests whose name matches one of the positive patterns but\n"
+"      none of the negative patterns. '?' matches any single character; '*'\n"
+"      matches any substring; ':' separates two patterns.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "also_run_disabled_tests@D\n"
+"      Run all disabled tests too.\n"
+"\n"
+"Test Execution:\n"
+"  @G--" GTEST_FLAG_PREFIX_ "repeat=@Y[COUNT]@D\n"
+"      Run the tests repeatedly; use a negative count to repeat forever.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "shuffle@D\n"
+"      Randomize tests' orders on every iteration.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "random_seed=@Y[NUMBER]@D\n"
+"      Random number seed to use for shuffling test orders (between 1 and\n"
+"      99999, or 0 to use a seed based on the current time).\n"
+"\n"
+"Test Output:\n"
+"  @G--" GTEST_FLAG_PREFIX_ "color=@Y(@Gyes@Y|@Gno@Y|@Gauto@Y)@D\n"
+"      Enable/disable colored output. The default is @Gauto@D.\n"
+"  -@G-" GTEST_FLAG_PREFIX_ "print_time=0@D\n"
+"      Don't print the elapsed time of each test.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "output=xml@Y[@G:@YDIRECTORY_PATH@G"
+    GTEST_PATH_SEP_ "@Y|@G:@YFILE_PATH]@D\n"
+"      Generate an XML report in the given directory or with the given file\n"
+"      name. @YFILE_PATH@D defaults to @Gtest_details.xml@D.\n"
+#if GTEST_CAN_STREAM_RESULTS_
+"  @G--" GTEST_FLAG_PREFIX_ "stream_result_to=@YHOST@G:@YPORT@D\n"
+"      Stream test results to the given server.\n"
+#endif  // GTEST_CAN_STREAM_RESULTS_
+"\n"
+"Assertion Behavior:\n"
+#if GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS
+"  @G--" GTEST_FLAG_PREFIX_ "death_test_style=@Y(@Gfast@Y|@Gthreadsafe@Y)@D\n"
+"      Set the default death test style.\n"
+#endif  // GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS
+"  @G--" GTEST_FLAG_PREFIX_ "break_on_failure@D\n"
+"      Turn assertion failures into debugger break-points.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "throw_on_failure@D\n"
+"      Turn assertion failures into C++ exceptions.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "catch_exceptions=0@D\n"
+"      Do not report exceptions as test failures. Instead, allow them\n"
+"      to crash the program or throw a pop-up (on Windows).\n"
+"\n"
+"Except for @G--" GTEST_FLAG_PREFIX_ "list_tests@D, you can alternatively set "
+    "the corresponding\n"
+"environment variable of a flag (all letters in upper-case). For example, to\n"
+"disable colored text output, you can either specify @G--" GTEST_FLAG_PREFIX_
+    "color=no@D or set\n"
+"the @G" GTEST_FLAG_PREFIX_UPPER_ "COLOR@D environment variable to @Gno@D.\n"
+"\n"
+"For more information, please read the " GTEST_NAME_ " documentation at\n"
+"@G" GTEST_PROJECT_URL_ "@D. If you find a bug in " GTEST_NAME_ "\n"
+"(not one in your own code or tests), please report it to\n"
+"@G<" GTEST_DEV_EMAIL_ ">@D.\n";
+
+bool ParseGoogleTestFlag(const char* const arg) {
+  return ParseBoolFlag(arg, kAlsoRunDisabledTestsFlag,
+                       &GTEST_FLAG(also_run_disabled_tests)) ||
+      ParseBoolFlag(arg, kBreakOnFailureFlag,
+                    &GTEST_FLAG(break_on_failure)) ||
+      ParseBoolFlag(arg, kCatchExceptionsFlag,
+                    &GTEST_FLAG(catch_exceptions)) ||
+      ParseStringFlag(arg, kColorFlag, &GTEST_FLAG(color)) ||
+      ParseStringFlag(arg, kDeathTestStyleFlag,
+                      &GTEST_FLAG(death_test_style)) ||
+      ParseBoolFlag(arg, kDeathTestUseFork,
+                    &GTEST_FLAG(death_test_use_fork)) ||
+      ParseStringFlag(arg, kFilterFlag, &GTEST_FLAG(filter)) ||
+      ParseStringFlag(arg, kInternalRunDeathTestFlag,
+                      &GTEST_FLAG(internal_run_death_test)) ||
+      ParseBoolFlag(arg, kListTestsFlag, &GTEST_FLAG(list_tests)) ||
+      ParseStringFlag(arg, kOutputFlag, &GTEST_FLAG(output)) ||
+      ParseBoolFlag(arg, kPrintTimeFlag, &GTEST_FLAG(print_time)) ||
+      ParseInt32Flag(arg, kRandomSeedFlag, &GTEST_FLAG(random_seed)) ||
+      ParseInt32Flag(arg, kRepeatFlag, &GTEST_FLAG(repeat)) ||
+      ParseBoolFlag(arg, kShuffleFlag, &GTEST_FLAG(shuffle)) ||
+      ParseInt32Flag(arg, kStackTraceDepthFlag,
+                     &GTEST_FLAG(stack_trace_depth)) ||
+      ParseStringFlag(arg, kStreamResultToFlag,
+                      &GTEST_FLAG(stream_result_to)) ||
+      ParseBoolFlag(arg, kThrowOnFailureFlag,
+                    &GTEST_FLAG(throw_on_failure));
+}
+
+#if GTEST_USE_OWN_FLAGFILE_FLAG_
+void LoadFlagsFromFile(const std::string& path) {
+  FILE* flagfile = posix::FOpen(path.c_str(), "r");
+  if (!flagfile) {
+    fprintf(stderr,
+            "Unable to open file \"%s\"\n",
+            GTEST_FLAG(flagfile).c_str());
+    fflush(stderr);
+    exit(EXIT_FAILURE);
+  }
+  std::string contents(ReadEntireFile(flagfile));
+  posix::FClose(flagfile);
+  std::vector<std::string> lines;
+  SplitString(contents, '\n', &lines);
+  for (size_t i = 0; i < lines.size(); ++i) {
+    if (lines[i].empty())
+      continue;
+    if (!ParseGoogleTestFlag(lines[i].c_str()))
+      g_help_flag = true;
+  }
+}
+#endif  // GTEST_USE_OWN_FLAGFILE_FLAG_
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test.  The type parameter CharType can be
+// instantiated to either char or wchar_t.
+template <typename CharType>
+void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) {
+  for (int i = 1; i < *argc; i++) {
+    const std::string arg_string = StreamableToString(argv[i]);
+    const char* const arg = arg_string.c_str();
+
+    using internal::ParseBoolFlag;
+    using internal::ParseInt32Flag;
+    using internal::ParseStringFlag;
+
+    bool remove_flag = false;
+    if (ParseGoogleTestFlag(arg)) {
+      remove_flag = true;
+#if GTEST_USE_OWN_FLAGFILE_FLAG_
+    } else if (ParseStringFlag(arg, kFlagfileFlag, &GTEST_FLAG(flagfile))) {
+      LoadFlagsFromFile(GTEST_FLAG(flagfile));
+      remove_flag = true;
+#endif  // GTEST_USE_OWN_FLAGFILE_FLAG_
+    } else if (arg_string == "--help" || arg_string == "-h" ||
+               arg_string == "-?" || arg_string == "/?" ||
+               HasGoogleTestFlagPrefix(arg)) {
+      // Both help flag and unrecognized Google Test flags (excluding
+      // internal ones) trigger help display.
+      g_help_flag = true;
+    }
+
+    if (remove_flag) {
+      // Shift the remainder of the argv list left by one.  Note
+      // that argv has (*argc + 1) elements, the last one always being
+      // NULL.  The following loop moves the trailing NULL element as
+      // well.
+      for (int j = i; j != *argc; j++) {
+        argv[j] = argv[j + 1];
+      }
+
+      // Decrements the argument count.
+      (*argc)--;
+
+      // We also need to decrement the iterator as we just removed
+      // an element.
+      i--;
+    }
+  }
+
+  if (g_help_flag) {
+    // We print the help here instead of in RUN_ALL_TESTS(), as the
+    // latter may not be called at all if the user is using Google
+    // Test with another testing framework.
+    PrintColorEncoded(kColorEncodedHelpMessage);
+  }
+}
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test.
+void ParseGoogleTestFlagsOnly(int* argc, char** argv) {
+  ParseGoogleTestFlagsOnlyImpl(argc, argv);
+}
+void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv) {
+  ParseGoogleTestFlagsOnlyImpl(argc, argv);
+}
+
+// The internal implementation of InitGoogleTest().
+//
+// The type parameter CharType can be instantiated to either char or
+// wchar_t.
+template <typename CharType>
+void InitGoogleTestImpl(int* argc, CharType** argv) {
+  // We don't want to run the initialization code twice.
+  if (GTestIsInitialized()) return;
+
+  if (*argc <= 0) return;
+
+  g_argvs.clear();
+  for (int i = 0; i != *argc; i++) {
+    g_argvs.push_back(StreamableToString(argv[i]));
+  }
+
+  ParseGoogleTestFlagsOnly(argc, argv);
+  GetUnitTestImpl()->PostFlagParsingInit();
+}
+
+}  // namespace internal
+
+// Initializes Google Test.  This must be called before calling
+// RUN_ALL_TESTS().  In particular, it parses a command line for the
+// flags that Google Test recognizes.  Whenever a Google Test flag is
+// seen, it is removed from argv, and *argc is decremented.
+//
+// No value is returned.  Instead, the Google Test flag variables are
+// updated.
+//
+// Calling the function for the second time has no user-visible effect.
+void InitGoogleTest(int* argc, char** argv) {
+#if defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+  GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_(argc, argv);
+#else  // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+  internal::InitGoogleTestImpl(argc, argv);
+#endif  // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+}
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+void InitGoogleTest(int* argc, wchar_t** argv) {
+#if defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+  GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_(argc, argv);
+#else  // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+  internal::InitGoogleTestImpl(argc, argv);
+#endif  // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+}
+
+}  // namespace testing
diff --git a/third_party/googletest/googletest/src/gtest_main.cc b/third_party/googletest/googletest/src/gtest_main.cc
new file mode 100644
index 0000000..f302822
--- /dev/null
+++ b/third_party/googletest/googletest/src/gtest_main.cc
@@ -0,0 +1,38 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <stdio.h>
+
+#include "gtest/gtest.h"
+
+GTEST_API_ int main(int argc, char **argv) {
+  printf("Running main() from gtest_main.cc\n");
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/googletest/googletest/test/gtest-death-test_ex_test.cc b/third_party/googletest/googletest/test/gtest-death-test_ex_test.cc
new file mode 100644
index 0000000..b50a13d
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest-death-test_ex_test.cc
@@ -0,0 +1,93 @@
+// Copyright 2010, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vladl@google.com (Vlad Losev)
+//
+// Tests that verify interaction of exceptions and death tests.
+
+#include "gtest/gtest-death-test.h"
+#include "gtest/gtest.h"
+
+#if GTEST_HAS_DEATH_TEST
+
+# if GTEST_HAS_SEH
+#  include <windows.h>          // For RaiseException().
+# endif
+
+# include "gtest/gtest-spi.h"
+
+# if GTEST_HAS_EXCEPTIONS
+
+#  include <exception>  // For std::exception.
+
+// Tests that death tests report thrown exceptions as failures and that the
+// exceptions do not escape death test macros.
+TEST(CxxExceptionDeathTest, ExceptionIsFailure) {
+  try {
+    EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(throw 1, ""), "threw an exception");
+  } catch (...) {  // NOLINT
+    FAIL() << "An exception escaped a death test macro invocation "
+           << "with catch_exceptions "
+           << (testing::GTEST_FLAG(catch_exceptions) ? "enabled" : "disabled");
+  }
+}
+
+class TestException : public std::exception {
+ public:
+  virtual const char* what() const throw() { return "exceptional message"; }
+};
+
+TEST(CxxExceptionDeathTest, PrintsMessageForStdExceptions) {
+  // Verifies that the exception message is quoted in the failure text.
+  EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(throw TestException(), ""),
+                          "exceptional message");
+  // Verifies that the location is mentioned in the failure text.
+  EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(throw TestException(), ""),
+                          "gtest-death-test_ex_test.cc");
+}
+# endif  // GTEST_HAS_EXCEPTIONS
+
+# if GTEST_HAS_SEH
+// Tests that enabling interception of SEH exceptions with the
+// catch_exceptions flag does not interfere with SEH exceptions being
+// treated as death by death tests.
+TEST(SehExceptionDeasTest, CatchExceptionsDoesNotInterfere) {
+  EXPECT_DEATH(RaiseException(42, 0x0, 0, NULL), "")
+      << "with catch_exceptions "
+      << (testing::GTEST_FLAG(catch_exceptions) ? "enabled" : "disabled");
+}
+# endif
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+  testing::GTEST_FLAG(catch_exceptions) = GTEST_ENABLE_CATCH_EXCEPTIONS_ != 0;
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/googletest/googletest/test/gtest-death-test_test.cc b/third_party/googletest/googletest/test/gtest-death-test_test.cc
new file mode 100644
index 0000000..bb4a3d1
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest-death-test_test.cc
@@ -0,0 +1,1427 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// Tests for death tests.
+
+#include "gtest/gtest-death-test.h"
+#include "gtest/gtest.h"
+#include "gtest/internal/gtest-filepath.h"
+
+using testing::internal::AlwaysFalse;
+using testing::internal::AlwaysTrue;
+
+#if GTEST_HAS_DEATH_TEST
+
+# if GTEST_OS_WINDOWS
+#  include <direct.h>          // For chdir().
+# else
+#  include <unistd.h>
+#  include <sys/wait.h>        // For waitpid.
+# endif  // GTEST_OS_WINDOWS
+
+# include <limits.h>
+# include <signal.h>
+# include <stdio.h>
+
+# if GTEST_OS_LINUX
+#  include <sys/time.h>
+# endif  // GTEST_OS_LINUX
+
+# include "gtest/gtest-spi.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+# define GTEST_IMPLEMENTATION_ 1
+# include "src/gtest-internal-inl.h"
+# undef GTEST_IMPLEMENTATION_
+
+namespace posix = ::testing::internal::posix;
+
+using testing::Message;
+using testing::internal::DeathTest;
+using testing::internal::DeathTestFactory;
+using testing::internal::FilePath;
+using testing::internal::GetLastErrnoDescription;
+using testing::internal::GetUnitTestImpl;
+using testing::internal::InDeathTestChild;
+using testing::internal::ParseNaturalNumber;
+
+namespace testing {
+namespace internal {
+
+// A helper class whose objects replace the death test factory for a
+// single UnitTest object during their lifetimes.
+class ReplaceDeathTestFactory {
+ public:
+  explicit ReplaceDeathTestFactory(DeathTestFactory* new_factory)
+      : unit_test_impl_(GetUnitTestImpl()) {
+    old_factory_ = unit_test_impl_->death_test_factory_.release();
+    unit_test_impl_->death_test_factory_.reset(new_factory);
+  }
+
+  ~ReplaceDeathTestFactory() {
+    unit_test_impl_->death_test_factory_.release();
+    unit_test_impl_->death_test_factory_.reset(old_factory_);
+  }
+ private:
+  // Prevents copying ReplaceDeathTestFactory objects.
+  ReplaceDeathTestFactory(const ReplaceDeathTestFactory&);
+  void operator=(const ReplaceDeathTestFactory&);
+
+  UnitTestImpl* unit_test_impl_;
+  DeathTestFactory* old_factory_;
+};
+
+}  // namespace internal
+}  // namespace testing
+
+void DieWithMessage(const ::std::string& message) {
+  fprintf(stderr, "%s", message.c_str());
+  fflush(stderr);  // Make sure the text is printed before the process exits.
+
+  // We call _exit() instead of exit(), as the former is a direct
+  // system call and thus safer in the presence of threads.  exit()
+  // will invoke user-defined exit-hooks, which may do dangerous
+  // things that conflict with death tests.
+  //
+  // Some compilers can recognize that _exit() never returns and issue the
+  // 'unreachable code' warning for code following this function, unless
+  // fooled by a fake condition.
+  if (AlwaysTrue())
+    _exit(1);
+}
+
+void DieInside(const ::std::string& function) {
+  DieWithMessage("death inside " + function + "().");
+}
+
+// Tests that death tests work.
+
+class TestForDeathTest : public testing::Test {
+ protected:
+  TestForDeathTest() : original_dir_(FilePath::GetCurrentDir()) {}
+
+  virtual ~TestForDeathTest() {
+    posix::ChDir(original_dir_.c_str());
+  }
+
+  // A static member function that's expected to die.
+  static void StaticMemberFunction() { DieInside("StaticMemberFunction"); }
+
+  // A method of the test fixture that may die.
+  void MemberFunction() {
+    if (should_die_)
+      DieInside("MemberFunction");
+  }
+
+  // True iff MemberFunction() should die.
+  bool should_die_;
+  const FilePath original_dir_;
+};
+
+// A class with a member function that may die.
+class MayDie {
+ public:
+  explicit MayDie(bool should_die) : should_die_(should_die) {}
+
+  // A member function that may die.
+  void MemberFunction() const {
+    if (should_die_)
+      DieInside("MayDie::MemberFunction");
+  }
+
+ private:
+  // True iff MemberFunction() should die.
+  bool should_die_;
+};
+
+// A global function that's expected to die.
+void GlobalFunction() { DieInside("GlobalFunction"); }
+
+// A non-void function that's expected to die.
+int NonVoidFunction() {
+  DieInside("NonVoidFunction");
+  return 1;
+}
+
+// A unary function that may die.
+void DieIf(bool should_die) {
+  if (should_die)
+    DieInside("DieIf");
+}
+
+// A binary function that may die.
+bool DieIfLessThan(int x, int y) {
+  if (x < y) {
+    DieInside("DieIfLessThan");
+  }
+  return true;
+}
+
+// Tests that ASSERT_DEATH can be used outside a TEST, TEST_F, or test fixture.
+void DeathTestSubroutine() {
+  EXPECT_DEATH(GlobalFunction(), "death.*GlobalFunction");
+  ASSERT_DEATH(GlobalFunction(), "death.*GlobalFunction");
+}
+
+// Death in dbg, not opt.
+int DieInDebugElse12(int* sideeffect) {
+  if (sideeffect) *sideeffect = 12;
+
+# ifndef NDEBUG
+
+  DieInside("DieInDebugElse12");
+
+# endif  // NDEBUG
+
+  return 12;
+}
+
+# if GTEST_OS_WINDOWS
+
+// Tests the ExitedWithCode predicate.
+TEST(ExitStatusPredicateTest, ExitedWithCode) {
+  // On Windows, the process's exit code is the same as its exit status,
+  // so the predicate just compares the its input with its parameter.
+  EXPECT_TRUE(testing::ExitedWithCode(0)(0));
+  EXPECT_TRUE(testing::ExitedWithCode(1)(1));
+  EXPECT_TRUE(testing::ExitedWithCode(42)(42));
+  EXPECT_FALSE(testing::ExitedWithCode(0)(1));
+  EXPECT_FALSE(testing::ExitedWithCode(1)(0));
+}
+
+# else
+
+// Returns the exit status of a process that calls _exit(2) with a
+// given exit code.  This is a helper function for the
+// ExitStatusPredicateTest test suite.
+static int NormalExitStatus(int exit_code) {
+  pid_t child_pid = fork();
+  if (child_pid == 0) {
+    _exit(exit_code);
+  }
+  int status;
+  waitpid(child_pid, &status, 0);
+  return status;
+}
+
+// Returns the exit status of a process that raises a given signal.
+// If the signal does not cause the process to die, then it returns
+// instead the exit status of a process that exits normally with exit
+// code 1.  This is a helper function for the ExitStatusPredicateTest
+// test suite.
+static int KilledExitStatus(int signum) {
+  pid_t child_pid = fork();
+  if (child_pid == 0) {
+    raise(signum);
+    _exit(1);
+  }
+  int status;
+  waitpid(child_pid, &status, 0);
+  return status;
+}
+
+// Tests the ExitedWithCode predicate.
+TEST(ExitStatusPredicateTest, ExitedWithCode) {
+  const int status0  = NormalExitStatus(0);
+  const int status1  = NormalExitStatus(1);
+  const int status42 = NormalExitStatus(42);
+  const testing::ExitedWithCode pred0(0);
+  const testing::ExitedWithCode pred1(1);
+  const testing::ExitedWithCode pred42(42);
+  EXPECT_PRED1(pred0,  status0);
+  EXPECT_PRED1(pred1,  status1);
+  EXPECT_PRED1(pred42, status42);
+  EXPECT_FALSE(pred0(status1));
+  EXPECT_FALSE(pred42(status0));
+  EXPECT_FALSE(pred1(status42));
+}
+
+// Tests the KilledBySignal predicate.
+TEST(ExitStatusPredicateTest, KilledBySignal) {
+  const int status_segv = KilledExitStatus(SIGSEGV);
+  const int status_kill = KilledExitStatus(SIGKILL);
+  const testing::KilledBySignal pred_segv(SIGSEGV);
+  const testing::KilledBySignal pred_kill(SIGKILL);
+  EXPECT_PRED1(pred_segv, status_segv);
+  EXPECT_PRED1(pred_kill, status_kill);
+  EXPECT_FALSE(pred_segv(status_kill));
+  EXPECT_FALSE(pred_kill(status_segv));
+}
+
+# endif  // GTEST_OS_WINDOWS
+
+// Tests that the death test macros expand to code which may or may not
+// be followed by operator<<, and that in either case the complete text
+// comprises only a single C++ statement.
+TEST_F(TestForDeathTest, SingleStatement) {
+  if (AlwaysFalse())
+    // This would fail if executed; this is a compilation test only
+    ASSERT_DEATH(return, "");
+
+  if (AlwaysTrue())
+    EXPECT_DEATH(_exit(1), "");
+  else
+    // This empty "else" branch is meant to ensure that EXPECT_DEATH
+    // doesn't expand into an "if" statement without an "else"
+    ;
+
+  if (AlwaysFalse())
+    ASSERT_DEATH(return, "") << "did not die";
+
+  if (AlwaysFalse())
+    ;
+  else
+    EXPECT_DEATH(_exit(1), "") << 1 << 2 << 3;
+}
+
+void DieWithEmbeddedNul() {
+  fprintf(stderr, "Hello%cmy null world.\n", '\0');
+  fflush(stderr);
+  _exit(1);
+}
+
+# if GTEST_USES_PCRE
+// Tests that EXPECT_DEATH and ASSERT_DEATH work when the error
+// message has a NUL character in it.
+TEST_F(TestForDeathTest, EmbeddedNulInMessage) {
+  // TODO(wan@google.com): <regex.h> doesn't support matching strings
+  // with embedded NUL characters - find a way to workaround it.
+  EXPECT_DEATH(DieWithEmbeddedNul(), "my null world");
+  ASSERT_DEATH(DieWithEmbeddedNul(), "my null world");
+}
+# endif  // GTEST_USES_PCRE
+
+// Tests that death test macros expand to code which interacts well with switch
+// statements.
+TEST_F(TestForDeathTest, SwitchStatement) {
+  // Microsoft compiler usually complains about switch statements without
+  // case labels. We suppress that warning for this test.
+  GTEST_DISABLE_MSC_WARNINGS_PUSH_(4065)
+
+  switch (0)
+    default:
+      ASSERT_DEATH(_exit(1), "") << "exit in default switch handler";
+
+  switch (0)
+    case 0:
+      EXPECT_DEATH(_exit(1), "") << "exit in switch case";
+
+  GTEST_DISABLE_MSC_WARNINGS_POP_()
+}
+
+// Tests that a static member function can be used in a "fast" style
+// death test.
+TEST_F(TestForDeathTest, StaticMemberFunctionFastStyle) {
+  testing::GTEST_FLAG(death_test_style) = "fast";
+  ASSERT_DEATH(StaticMemberFunction(), "death.*StaticMember");
+}
+
+// Tests that a method of the test fixture can be used in a "fast"
+// style death test.
+TEST_F(TestForDeathTest, MemberFunctionFastStyle) {
+  testing::GTEST_FLAG(death_test_style) = "fast";
+  should_die_ = true;
+  EXPECT_DEATH(MemberFunction(), "inside.*MemberFunction");
+}
+
+void ChangeToRootDir() { posix::ChDir(GTEST_PATH_SEP_); }
+
+// Tests that death tests work even if the current directory has been
+// changed.
+TEST_F(TestForDeathTest, FastDeathTestInChangedDir) {
+  testing::GTEST_FLAG(death_test_style) = "fast";
+
+  ChangeToRootDir();
+  EXPECT_EXIT(_exit(1), testing::ExitedWithCode(1), "");
+
+  ChangeToRootDir();
+  ASSERT_DEATH(_exit(1), "");
+}
+
+# if GTEST_OS_LINUX
+void SigprofAction(int, siginfo_t*, void*) { /* no op */ }
+
+// Sets SIGPROF action and ITIMER_PROF timer (interval: 1ms).
+void SetSigprofActionAndTimer() {
+  struct itimerval timer;
+  timer.it_interval.tv_sec = 0;
+  timer.it_interval.tv_usec = 1;
+  timer.it_value = timer.it_interval;
+  ASSERT_EQ(0, setitimer(ITIMER_PROF, &timer, NULL));
+  struct sigaction signal_action;
+  memset(&signal_action, 0, sizeof(signal_action));
+  sigemptyset(&signal_action.sa_mask);
+  signal_action.sa_sigaction = SigprofAction;
+  signal_action.sa_flags = SA_RESTART | SA_SIGINFO;
+  ASSERT_EQ(0, sigaction(SIGPROF, &signal_action, NULL));
+}
+
+// Disables ITIMER_PROF timer and ignores SIGPROF signal.
+void DisableSigprofActionAndTimer(struct sigaction* old_signal_action) {
+  struct itimerval timer;
+  timer.it_interval.tv_sec = 0;
+  timer.it_interval.tv_usec = 0;
+  timer.it_value = timer.it_interval;
+  ASSERT_EQ(0, setitimer(ITIMER_PROF, &timer, NULL));
+  struct sigaction signal_action;
+  memset(&signal_action, 0, sizeof(signal_action));
+  sigemptyset(&signal_action.sa_mask);
+  signal_action.sa_handler = SIG_IGN;
+  ASSERT_EQ(0, sigaction(SIGPROF, &signal_action, old_signal_action));
+}
+
+// Tests that death tests work when SIGPROF handler and timer are set.
+TEST_F(TestForDeathTest, FastSigprofActionSet) {
+  testing::GTEST_FLAG(death_test_style) = "fast";
+  SetSigprofActionAndTimer();
+  EXPECT_DEATH(_exit(1), "");
+  struct sigaction old_signal_action;
+  DisableSigprofActionAndTimer(&old_signal_action);
+  EXPECT_TRUE(old_signal_action.sa_sigaction == SigprofAction);
+}
+
+TEST_F(TestForDeathTest, ThreadSafeSigprofActionSet) {
+  testing::GTEST_FLAG(death_test_style) = "threadsafe";
+  SetSigprofActionAndTimer();
+  EXPECT_DEATH(_exit(1), "");
+  struct sigaction old_signal_action;
+  DisableSigprofActionAndTimer(&old_signal_action);
+  EXPECT_TRUE(old_signal_action.sa_sigaction == SigprofAction);
+}
+# endif  // GTEST_OS_LINUX
+
+// Repeats a representative sample of death tests in the "threadsafe" style:
+
+TEST_F(TestForDeathTest, StaticMemberFunctionThreadsafeStyle) {
+  testing::GTEST_FLAG(death_test_style) = "threadsafe";
+  ASSERT_DEATH(StaticMemberFunction(), "death.*StaticMember");
+}
+
+TEST_F(TestForDeathTest, MemberFunctionThreadsafeStyle) {
+  testing::GTEST_FLAG(death_test_style) = "threadsafe";
+  should_die_ = true;
+  EXPECT_DEATH(MemberFunction(), "inside.*MemberFunction");
+}
+
+TEST_F(TestForDeathTest, ThreadsafeDeathTestInLoop) {
+  testing::GTEST_FLAG(death_test_style) = "threadsafe";
+
+  for (int i = 0; i < 3; ++i)
+    EXPECT_EXIT(_exit(i), testing::ExitedWithCode(i), "") << ": i = " << i;
+}
+
+TEST_F(TestForDeathTest, ThreadsafeDeathTestInChangedDir) {
+  testing::GTEST_FLAG(death_test_style) = "threadsafe";
+
+  ChangeToRootDir();
+  EXPECT_EXIT(_exit(1), testing::ExitedWithCode(1), "");
+
+  ChangeToRootDir();
+  ASSERT_DEATH(_exit(1), "");
+}
+
+TEST_F(TestForDeathTest, MixedStyles) {
+  testing::GTEST_FLAG(death_test_style) = "threadsafe";
+  EXPECT_DEATH(_exit(1), "");
+  testing::GTEST_FLAG(death_test_style) = "fast";
+  EXPECT_DEATH(_exit(1), "");
+}
+
+# if GTEST_HAS_CLONE && GTEST_HAS_PTHREAD
+
+namespace {
+
+bool pthread_flag;
+
+void SetPthreadFlag() {
+  pthread_flag = true;
+}
+
+}  // namespace
+
+TEST_F(TestForDeathTest, DoesNotExecuteAtforkHooks) {
+  if (!testing::GTEST_FLAG(death_test_use_fork)) {
+    testing::GTEST_FLAG(death_test_style) = "threadsafe";
+    pthread_flag = false;
+    ASSERT_EQ(0, pthread_atfork(&SetPthreadFlag, NULL, NULL));
+    ASSERT_DEATH(_exit(1), "");
+    ASSERT_FALSE(pthread_flag);
+  }
+}
+
+# endif  // GTEST_HAS_CLONE && GTEST_HAS_PTHREAD
+
+// Tests that a method of another class can be used in a death test.
+TEST_F(TestForDeathTest, MethodOfAnotherClass) {
+  const MayDie x(true);
+  ASSERT_DEATH(x.MemberFunction(), "MayDie\\:\\:MemberFunction");
+}
+
+// Tests that a global function can be used in a death test.
+TEST_F(TestForDeathTest, GlobalFunction) {
+  EXPECT_DEATH(GlobalFunction(), "GlobalFunction");
+}
+
+// Tests that any value convertible to an RE works as a second
+// argument to EXPECT_DEATH.
+TEST_F(TestForDeathTest, AcceptsAnythingConvertibleToRE) {
+  static const char regex_c_str[] = "GlobalFunction";
+  EXPECT_DEATH(GlobalFunction(), regex_c_str);
+
+  const testing::internal::RE regex(regex_c_str);
+  EXPECT_DEATH(GlobalFunction(), regex);
+
+# if GTEST_HAS_GLOBAL_STRING
+
+  const string regex_str(regex_c_str);
+  EXPECT_DEATH(GlobalFunction(), regex_str);
+
+# endif  // GTEST_HAS_GLOBAL_STRING
+
+# if !GTEST_USES_PCRE
+
+  const ::std::string regex_std_str(regex_c_str);
+  EXPECT_DEATH(GlobalFunction(), regex_std_str);
+
+# endif  // !GTEST_USES_PCRE
+}
+
+// Tests that a non-void function can be used in a death test.
+TEST_F(TestForDeathTest, NonVoidFunction) {
+  ASSERT_DEATH(NonVoidFunction(), "NonVoidFunction");
+}
+
+// Tests that functions that take parameter(s) can be used in a death test.
+TEST_F(TestForDeathTest, FunctionWithParameter) {
+  EXPECT_DEATH(DieIf(true), "DieIf\\(\\)");
+  EXPECT_DEATH(DieIfLessThan(2, 3), "DieIfLessThan");
+}
+
+// Tests that ASSERT_DEATH can be used outside a TEST, TEST_F, or test fixture.
+TEST_F(TestForDeathTest, OutsideFixture) {
+  DeathTestSubroutine();
+}
+
+// Tests that death tests can be done inside a loop.
+TEST_F(TestForDeathTest, InsideLoop) {
+  for (int i = 0; i < 5; i++) {
+    EXPECT_DEATH(DieIfLessThan(-1, i), "DieIfLessThan") << "where i == " << i;
+  }
+}
+
+// Tests that a compound statement can be used in a death test.
+TEST_F(TestForDeathTest, CompoundStatement) {
+  EXPECT_DEATH({  // NOLINT
+    const int x = 2;
+    const int y = x + 1;
+    DieIfLessThan(x, y);
+  },
+  "DieIfLessThan");
+}
+
+// Tests that code that doesn't die causes a death test to fail.
+TEST_F(TestForDeathTest, DoesNotDie) {
+  EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(DieIf(false), "DieIf"),
+                          "failed to die");
+}
+
+// Tests that a death test fails when the error message isn't expected.
+TEST_F(TestForDeathTest, ErrorMessageMismatch) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_DEATH(DieIf(true), "DieIfLessThan") << "End of death test message.";
+  }, "died but not with expected error");
+}
+
+// On exit, *aborted will be true iff the EXPECT_DEATH() statement
+// aborted the function.
+void ExpectDeathTestHelper(bool* aborted) {
+  *aborted = true;
+  EXPECT_DEATH(DieIf(false), "DieIf");  // This assertion should fail.
+  *aborted = false;
+}
+
+// Tests that EXPECT_DEATH doesn't abort the test on failure.
+TEST_F(TestForDeathTest, EXPECT_DEATH) {
+  bool aborted = true;
+  EXPECT_NONFATAL_FAILURE(ExpectDeathTestHelper(&aborted),
+                          "failed to die");
+  EXPECT_FALSE(aborted);
+}
+
+// Tests that ASSERT_DEATH does abort the test on failure.
+TEST_F(TestForDeathTest, ASSERT_DEATH) {
+  static bool aborted;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    aborted = true;
+    ASSERT_DEATH(DieIf(false), "DieIf");  // This assertion should fail.
+    aborted = false;
+  }, "failed to die");
+  EXPECT_TRUE(aborted);
+}
+
+// Tests that EXPECT_DEATH evaluates the arguments exactly once.
+TEST_F(TestForDeathTest, SingleEvaluation) {
+  int x = 3;
+  EXPECT_DEATH(DieIf((++x) == 4), "DieIf");
+
+  const char* regex = "DieIf";
+  const char* regex_save = regex;
+  EXPECT_DEATH(DieIfLessThan(3, 4), regex++);
+  EXPECT_EQ(regex_save + 1, regex);
+}
+
+// Tests that run-away death tests are reported as failures.
+TEST_F(TestForDeathTest, RunawayIsFailure) {
+  EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(static_cast<void>(0), "Foo"),
+                          "failed to die.");
+}
+
+// Tests that death tests report executing 'return' in the statement as
+// failure.
+TEST_F(TestForDeathTest, ReturnIsFailure) {
+  EXPECT_FATAL_FAILURE(ASSERT_DEATH(return, "Bar"),
+                       "illegal return in test statement.");
+}
+
+// Tests that EXPECT_DEBUG_DEATH works as expected, that is, you can stream a
+// message to it, and in debug mode it:
+// 1. Asserts on death.
+// 2. Has no side effect.
+//
+// And in opt mode, it:
+// 1.  Has side effects but does not assert.
+TEST_F(TestForDeathTest, TestExpectDebugDeath) {
+  int sideeffect = 0;
+
+  EXPECT_DEBUG_DEATH(DieInDebugElse12(&sideeffect), "death.*DieInDebugElse12")
+      << "Must accept a streamed message";
+
+# ifdef NDEBUG
+
+  // Checks that the assignment occurs in opt mode (sideeffect).
+  EXPECT_EQ(12, sideeffect);
+
+# else
+
+  // Checks that the assignment does not occur in dbg mode (no sideeffect).
+  EXPECT_EQ(0, sideeffect);
+
+# endif
+}
+
+// Tests that ASSERT_DEBUG_DEATH works as expected, that is, you can stream a
+// message to it, and in debug mode it:
+// 1. Asserts on death.
+// 2. Has no side effect.
+//
+// And in opt mode, it:
+// 1.  Has side effects but does not assert.
+TEST_F(TestForDeathTest, TestAssertDebugDeath) {
+  int sideeffect = 0;
+
+  ASSERT_DEBUG_DEATH(DieInDebugElse12(&sideeffect), "death.*DieInDebugElse12")
+      << "Must accept a streamed message";
+
+# ifdef NDEBUG
+
+  // Checks that the assignment occurs in opt mode (sideeffect).
+  EXPECT_EQ(12, sideeffect);
+
+# else
+
+  // Checks that the assignment does not occur in dbg mode (no sideeffect).
+  EXPECT_EQ(0, sideeffect);
+
+# endif
+}
+
+# ifndef NDEBUG
+
+void ExpectDebugDeathHelper(bool* aborted) {
+  *aborted = true;
+  EXPECT_DEBUG_DEATH(return, "") << "This is expected to fail.";
+  *aborted = false;
+}
+
+#  if GTEST_OS_WINDOWS
+TEST(PopUpDeathTest, DoesNotShowPopUpOnAbort) {
+  printf("This test should be considered failing if it shows "
+         "any pop-up dialogs.\n");
+  fflush(stdout);
+
+  EXPECT_DEATH({
+    testing::GTEST_FLAG(catch_exceptions) = false;
+    abort();
+  }, "");
+}
+#  endif  // GTEST_OS_WINDOWS
+
+// Tests that EXPECT_DEBUG_DEATH in debug mode does not abort
+// the function.
+TEST_F(TestForDeathTest, ExpectDebugDeathDoesNotAbort) {
+  bool aborted = true;
+  EXPECT_NONFATAL_FAILURE(ExpectDebugDeathHelper(&aborted), "");
+  EXPECT_FALSE(aborted);
+}
+
+void AssertDebugDeathHelper(bool* aborted) {
+  *aborted = true;
+  GTEST_LOG_(INFO) << "Before ASSERT_DEBUG_DEATH";
+  ASSERT_DEBUG_DEATH(GTEST_LOG_(INFO) << "In ASSERT_DEBUG_DEATH"; return, "")
+      << "This is expected to fail.";
+  GTEST_LOG_(INFO) << "After ASSERT_DEBUG_DEATH";
+  *aborted = false;
+}
+
+// Tests that ASSERT_DEBUG_DEATH in debug mode aborts the function on
+// failure.
+TEST_F(TestForDeathTest, AssertDebugDeathAborts) {
+  static bool aborted;
+  aborted = false;
+  EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
+  EXPECT_TRUE(aborted);
+}
+
+TEST_F(TestForDeathTest, AssertDebugDeathAborts2) {
+  static bool aborted;
+  aborted = false;
+  EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
+  EXPECT_TRUE(aborted);
+}
+
+TEST_F(TestForDeathTest, AssertDebugDeathAborts3) {
+  static bool aborted;
+  aborted = false;
+  EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
+  EXPECT_TRUE(aborted);
+}
+
+TEST_F(TestForDeathTest, AssertDebugDeathAborts4) {
+  static bool aborted;
+  aborted = false;
+  EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
+  EXPECT_TRUE(aborted);
+}
+
+TEST_F(TestForDeathTest, AssertDebugDeathAborts5) {
+  static bool aborted;
+  aborted = false;
+  EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
+  EXPECT_TRUE(aborted);
+}
+
+TEST_F(TestForDeathTest, AssertDebugDeathAborts6) {
+  static bool aborted;
+  aborted = false;
+  EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
+  EXPECT_TRUE(aborted);
+}
+
+TEST_F(TestForDeathTest, AssertDebugDeathAborts7) {
+  static bool aborted;
+  aborted = false;
+  EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
+  EXPECT_TRUE(aborted);
+}
+
+TEST_F(TestForDeathTest, AssertDebugDeathAborts8) {
+  static bool aborted;
+  aborted = false;
+  EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
+  EXPECT_TRUE(aborted);
+}
+
+TEST_F(TestForDeathTest, AssertDebugDeathAborts9) {
+  static bool aborted;
+  aborted = false;
+  EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
+  EXPECT_TRUE(aborted);
+}
+
+TEST_F(TestForDeathTest, AssertDebugDeathAborts10) {
+  static bool aborted;
+  aborted = false;
+  EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
+  EXPECT_TRUE(aborted);
+}
+
+# endif  // _NDEBUG
+
+// Tests the *_EXIT family of macros, using a variety of predicates.
+static void TestExitMacros() {
+  EXPECT_EXIT(_exit(1),  testing::ExitedWithCode(1),  "");
+  ASSERT_EXIT(_exit(42), testing::ExitedWithCode(42), "");
+
+# if GTEST_OS_WINDOWS
+
+  // Of all signals effects on the process exit code, only those of SIGABRT
+  // are documented on Windows.
+  // See http://msdn.microsoft.com/en-us/library/dwwzkt4c(VS.71).aspx.
+  EXPECT_EXIT(raise(SIGABRT), testing::ExitedWithCode(3), "") << "b_ar";
+
+# else
+
+  EXPECT_EXIT(raise(SIGKILL), testing::KilledBySignal(SIGKILL), "") << "foo";
+  ASSERT_EXIT(raise(SIGUSR2), testing::KilledBySignal(SIGUSR2), "") << "bar";
+
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_EXIT(_exit(0), testing::KilledBySignal(SIGSEGV), "")
+      << "This failure is expected, too.";
+  }, "This failure is expected, too.");
+
+# endif  // GTEST_OS_WINDOWS
+
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_EXIT(raise(SIGSEGV), testing::ExitedWithCode(0), "")
+      << "This failure is expected.";
+  }, "This failure is expected.");
+}
+
+TEST_F(TestForDeathTest, ExitMacros) {
+  TestExitMacros();
+}
+
+TEST_F(TestForDeathTest, ExitMacrosUsingFork) {
+  testing::GTEST_FLAG(death_test_use_fork) = true;
+  TestExitMacros();
+}
+
+TEST_F(TestForDeathTest, InvalidStyle) {
+  testing::GTEST_FLAG(death_test_style) = "rococo";
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_DEATH(_exit(0), "") << "This failure is expected.";
+  }, "This failure is expected.");
+}
+
+TEST_F(TestForDeathTest, DeathTestFailedOutput) {
+  testing::GTEST_FLAG(death_test_style) = "fast";
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_DEATH(DieWithMessage("death\n"),
+                   "expected message"),
+      "Actual msg:\n"
+      "[  DEATH   ] death\n");
+}
+
+TEST_F(TestForDeathTest, DeathTestUnexpectedReturnOutput) {
+  testing::GTEST_FLAG(death_test_style) = "fast";
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_DEATH({
+          fprintf(stderr, "returning\n");
+          fflush(stderr);
+          return;
+        }, ""),
+      "    Result: illegal return in test statement.\n"
+      " Error msg:\n"
+      "[  DEATH   ] returning\n");
+}
+
+TEST_F(TestForDeathTest, DeathTestBadExitCodeOutput) {
+  testing::GTEST_FLAG(death_test_style) = "fast";
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_EXIT(DieWithMessage("exiting with rc 1\n"),
+                  testing::ExitedWithCode(3),
+                  "expected message"),
+      "    Result: died but not with expected exit code:\n"
+      "            Exited with exit status 1\n"
+      "Actual msg:\n"
+      "[  DEATH   ] exiting with rc 1\n");
+}
+
+TEST_F(TestForDeathTest, DeathTestMultiLineMatchFail) {
+  testing::GTEST_FLAG(death_test_style) = "fast";
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_DEATH(DieWithMessage("line 1\nline 2\nline 3\n"),
+                   "line 1\nxyz\nline 3\n"),
+      "Actual msg:\n"
+      "[  DEATH   ] line 1\n"
+      "[  DEATH   ] line 2\n"
+      "[  DEATH   ] line 3\n");
+}
+
+TEST_F(TestForDeathTest, DeathTestMultiLineMatchPass) {
+  testing::GTEST_FLAG(death_test_style) = "fast";
+  EXPECT_DEATH(DieWithMessage("line 1\nline 2\nline 3\n"),
+               "line 1\nline 2\nline 3\n");
+}
+
+// A DeathTestFactory that returns MockDeathTests.
+class MockDeathTestFactory : public DeathTestFactory {
+ public:
+  MockDeathTestFactory();
+  virtual bool Create(const char* statement,
+                      const ::testing::internal::RE* regex,
+                      const char* file, int line, DeathTest** test);
+
+  // Sets the parameters for subsequent calls to Create.
+  void SetParameters(bool create, DeathTest::TestRole role,
+                     int status, bool passed);
+
+  // Accessors.
+  int AssumeRoleCalls() const { return assume_role_calls_; }
+  int WaitCalls() const { return wait_calls_; }
+  size_t PassedCalls() const { return passed_args_.size(); }
+  bool PassedArgument(int n) const { return passed_args_[n]; }
+  size_t AbortCalls() const { return abort_args_.size(); }
+  DeathTest::AbortReason AbortArgument(int n) const {
+    return abort_args_[n];
+  }
+  bool TestDeleted() const { return test_deleted_; }
+
+ private:
+  friend class MockDeathTest;
+  // If true, Create will return a MockDeathTest; otherwise it returns
+  // NULL.
+  bool create_;
+  // The value a MockDeathTest will return from its AssumeRole method.
+  DeathTest::TestRole role_;
+  // The value a MockDeathTest will return from its Wait method.
+  int status_;
+  // The value a MockDeathTest will return from its Passed method.
+  bool passed_;
+
+  // Number of times AssumeRole was called.
+  int assume_role_calls_;
+  // Number of times Wait was called.
+  int wait_calls_;
+  // The arguments to the calls to Passed since the last call to
+  // SetParameters.
+  std::vector<bool> passed_args_;
+  // The arguments to the calls to Abort since the last call to
+  // SetParameters.
+  std::vector<DeathTest::AbortReason> abort_args_;
+  // True if the last MockDeathTest returned by Create has been
+  // deleted.
+  bool test_deleted_;
+};
+
+
+// A DeathTest implementation useful in testing.  It returns values set
+// at its creation from its various inherited DeathTest methods, and
+// reports calls to those methods to its parent MockDeathTestFactory
+// object.
+class MockDeathTest : public DeathTest {
+ public:
+  MockDeathTest(MockDeathTestFactory *parent,
+                TestRole role, int status, bool passed) :
+      parent_(parent), role_(role), status_(status), passed_(passed) {
+  }
+  virtual ~MockDeathTest() {
+    parent_->test_deleted_ = true;
+  }
+  virtual TestRole AssumeRole() {
+    ++parent_->assume_role_calls_;
+    return role_;
+  }
+  virtual int Wait() {
+    ++parent_->wait_calls_;
+    return status_;
+  }
+  virtual bool Passed(bool exit_status_ok) {
+    parent_->passed_args_.push_back(exit_status_ok);
+    return passed_;
+  }
+  virtual void Abort(AbortReason reason) {
+    parent_->abort_args_.push_back(reason);
+  }
+
+ private:
+  MockDeathTestFactory* const parent_;
+  const TestRole role_;
+  const int status_;
+  const bool passed_;
+};
+
+
+// MockDeathTestFactory constructor.
+MockDeathTestFactory::MockDeathTestFactory()
+    : create_(true),
+      role_(DeathTest::OVERSEE_TEST),
+      status_(0),
+      passed_(true),
+      assume_role_calls_(0),
+      wait_calls_(0),
+      passed_args_(),
+      abort_args_() {
+}
+
+
+// Sets the parameters for subsequent calls to Create.
+void MockDeathTestFactory::SetParameters(bool create,
+                                         DeathTest::TestRole role,
+                                         int status, bool passed) {
+  create_ = create;
+  role_ = role;
+  status_ = status;
+  passed_ = passed;
+
+  assume_role_calls_ = 0;
+  wait_calls_ = 0;
+  passed_args_.clear();
+  abort_args_.clear();
+}
+
+
+// Sets test to NULL (if create_ is false) or to the address of a new
+// MockDeathTest object with parameters taken from the last call
+// to SetParameters (if create_ is true).  Always returns true.
+bool MockDeathTestFactory::Create(const char* /*statement*/,
+                                  const ::testing::internal::RE* /*regex*/,
+                                  const char* /*file*/,
+                                  int /*line*/,
+                                  DeathTest** test) {
+  test_deleted_ = false;
+  if (create_) {
+    *test = new MockDeathTest(this, role_, status_, passed_);
+  } else {
+    *test = NULL;
+  }
+  return true;
+}
+
+// A test fixture for testing the logic of the GTEST_DEATH_TEST_ macro.
+// It installs a MockDeathTestFactory that is used for the duration
+// of the test case.
+class MacroLogicDeathTest : public testing::Test {
+ protected:
+  static testing::internal::ReplaceDeathTestFactory* replacer_;
+  static MockDeathTestFactory* factory_;
+
+  static void SetUpTestCase() {
+    factory_ = new MockDeathTestFactory;
+    replacer_ = new testing::internal::ReplaceDeathTestFactory(factory_);
+  }
+
+  static void TearDownTestCase() {
+    delete replacer_;
+    replacer_ = NULL;
+    delete factory_;
+    factory_ = NULL;
+  }
+
+  // Runs a death test that breaks the rules by returning.  Such a death
+  // test cannot be run directly from a test routine that uses a
+  // MockDeathTest, or the remainder of the routine will not be executed.
+  static void RunReturningDeathTest(bool* flag) {
+    ASSERT_DEATH({  // NOLINT
+      *flag = true;
+      return;
+    }, "");
+  }
+};
+
+testing::internal::ReplaceDeathTestFactory* MacroLogicDeathTest::replacer_
+    = NULL;
+MockDeathTestFactory* MacroLogicDeathTest::factory_ = NULL;
+
+
+// Test that nothing happens when the factory doesn't return a DeathTest:
+TEST_F(MacroLogicDeathTest, NothingHappens) {
+  bool flag = false;
+  factory_->SetParameters(false, DeathTest::OVERSEE_TEST, 0, true);
+  EXPECT_DEATH(flag = true, "");
+  EXPECT_FALSE(flag);
+  EXPECT_EQ(0, factory_->AssumeRoleCalls());
+  EXPECT_EQ(0, factory_->WaitCalls());
+  EXPECT_EQ(0U, factory_->PassedCalls());
+  EXPECT_EQ(0U, factory_->AbortCalls());
+  EXPECT_FALSE(factory_->TestDeleted());
+}
+
+// Test that the parent process doesn't run the death test code,
+// and that the Passed method returns false when the (simulated)
+// child process exits with status 0:
+TEST_F(MacroLogicDeathTest, ChildExitsSuccessfully) {
+  bool flag = false;
+  factory_->SetParameters(true, DeathTest::OVERSEE_TEST, 0, true);
+  EXPECT_DEATH(flag = true, "");
+  EXPECT_FALSE(flag);
+  EXPECT_EQ(1, factory_->AssumeRoleCalls());
+  EXPECT_EQ(1, factory_->WaitCalls());
+  ASSERT_EQ(1U, factory_->PassedCalls());
+  EXPECT_FALSE(factory_->PassedArgument(0));
+  EXPECT_EQ(0U, factory_->AbortCalls());
+  EXPECT_TRUE(factory_->TestDeleted());
+}
+
+// Tests that the Passed method was given the argument "true" when
+// the (simulated) child process exits with status 1:
+TEST_F(MacroLogicDeathTest, ChildExitsUnsuccessfully) {
+  bool flag = false;
+  factory_->SetParameters(true, DeathTest::OVERSEE_TEST, 1, true);
+  EXPECT_DEATH(flag = true, "");
+  EXPECT_FALSE(flag);
+  EXPECT_EQ(1, factory_->AssumeRoleCalls());
+  EXPECT_EQ(1, factory_->WaitCalls());
+  ASSERT_EQ(1U, factory_->PassedCalls());
+  EXPECT_TRUE(factory_->PassedArgument(0));
+  EXPECT_EQ(0U, factory_->AbortCalls());
+  EXPECT_TRUE(factory_->TestDeleted());
+}
+
+// Tests that the (simulated) child process executes the death test
+// code, and is aborted with the correct AbortReason if it
+// executes a return statement.
+TEST_F(MacroLogicDeathTest, ChildPerformsReturn) {
+  bool flag = false;
+  factory_->SetParameters(true, DeathTest::EXECUTE_TEST, 0, true);
+  RunReturningDeathTest(&flag);
+  EXPECT_TRUE(flag);
+  EXPECT_EQ(1, factory_->AssumeRoleCalls());
+  EXPECT_EQ(0, factory_->WaitCalls());
+  EXPECT_EQ(0U, factory_->PassedCalls());
+  EXPECT_EQ(1U, factory_->AbortCalls());
+  EXPECT_EQ(DeathTest::TEST_ENCOUNTERED_RETURN_STATEMENT,
+            factory_->AbortArgument(0));
+  EXPECT_TRUE(factory_->TestDeleted());
+}
+
+// Tests that the (simulated) child process is aborted with the
+// correct AbortReason if it does not die.
+TEST_F(MacroLogicDeathTest, ChildDoesNotDie) {
+  bool flag = false;
+  factory_->SetParameters(true, DeathTest::EXECUTE_TEST, 0, true);
+  EXPECT_DEATH(flag = true, "");
+  EXPECT_TRUE(flag);
+  EXPECT_EQ(1, factory_->AssumeRoleCalls());
+  EXPECT_EQ(0, factory_->WaitCalls());
+  EXPECT_EQ(0U, factory_->PassedCalls());
+  // This time there are two calls to Abort: one since the test didn't
+  // die, and another from the ReturnSentinel when it's destroyed.  The
+  // sentinel normally isn't destroyed if a test doesn't die, since
+  // _exit(2) is called in that case by ForkingDeathTest, but not by
+  // our MockDeathTest.
+  ASSERT_EQ(2U, factory_->AbortCalls());
+  EXPECT_EQ(DeathTest::TEST_DID_NOT_DIE,
+            factory_->AbortArgument(0));
+  EXPECT_EQ(DeathTest::TEST_ENCOUNTERED_RETURN_STATEMENT,
+            factory_->AbortArgument(1));
+  EXPECT_TRUE(factory_->TestDeleted());
+}
+
+// Tests that a successful death test does not register a successful
+// test part.
+TEST(SuccessRegistrationDeathTest, NoSuccessPart) {
+  EXPECT_DEATH(_exit(1), "");
+  EXPECT_EQ(0, GetUnitTestImpl()->current_test_result()->total_part_count());
+}
+
+TEST(StreamingAssertionsDeathTest, DeathTest) {
+  EXPECT_DEATH(_exit(1), "") << "unexpected failure";
+  ASSERT_DEATH(_exit(1), "") << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_DEATH(_exit(0), "") << "expected failure";
+  }, "expected failure");
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_DEATH(_exit(0), "") << "expected failure";
+  }, "expected failure");
+}
+
+// Tests that GetLastErrnoDescription returns an empty string when the
+// last error is 0 and non-empty string when it is non-zero.
+TEST(GetLastErrnoDescription, GetLastErrnoDescriptionWorks) {
+  errno = ENOENT;
+  EXPECT_STRNE("", GetLastErrnoDescription().c_str());
+  errno = 0;
+  EXPECT_STREQ("", GetLastErrnoDescription().c_str());
+}
+
+# if GTEST_OS_WINDOWS
+TEST(AutoHandleTest, AutoHandleWorks) {
+  HANDLE handle = ::CreateEvent(NULL, FALSE, FALSE, NULL);
+  ASSERT_NE(INVALID_HANDLE_VALUE, handle);
+
+  // Tests that the AutoHandle is correctly initialized with a handle.
+  testing::internal::AutoHandle auto_handle(handle);
+  EXPECT_EQ(handle, auto_handle.Get());
+
+  // Tests that Reset assigns INVALID_HANDLE_VALUE.
+  // Note that this cannot verify whether the original handle is closed.
+  auto_handle.Reset();
+  EXPECT_EQ(INVALID_HANDLE_VALUE, auto_handle.Get());
+
+  // Tests that Reset assigns the new handle.
+  // Note that this cannot verify whether the original handle is closed.
+  handle = ::CreateEvent(NULL, FALSE, FALSE, NULL);
+  ASSERT_NE(INVALID_HANDLE_VALUE, handle);
+  auto_handle.Reset(handle);
+  EXPECT_EQ(handle, auto_handle.Get());
+
+  // Tests that AutoHandle contains INVALID_HANDLE_VALUE by default.
+  testing::internal::AutoHandle auto_handle2;
+  EXPECT_EQ(INVALID_HANDLE_VALUE, auto_handle2.Get());
+}
+# endif  // GTEST_OS_WINDOWS
+
+# if GTEST_OS_WINDOWS
+typedef unsigned __int64 BiggestParsable;
+typedef signed __int64 BiggestSignedParsable;
+# else
+typedef unsigned long long BiggestParsable;
+typedef signed long long BiggestSignedParsable;
+# endif  // GTEST_OS_WINDOWS
+
+// We cannot use std::numeric_limits<T>::max() as it clashes with the
+// max() macro defined by <windows.h>.
+const BiggestParsable kBiggestParsableMax = ULLONG_MAX;
+const BiggestSignedParsable kBiggestSignedParsableMax = LLONG_MAX;
+
+TEST(ParseNaturalNumberTest, RejectsInvalidFormat) {
+  BiggestParsable result = 0;
+
+  // Rejects non-numbers.
+  EXPECT_FALSE(ParseNaturalNumber("non-number string", &result));
+
+  // Rejects numbers with whitespace prefix.
+  EXPECT_FALSE(ParseNaturalNumber(" 123", &result));
+
+  // Rejects negative numbers.
+  EXPECT_FALSE(ParseNaturalNumber("-123", &result));
+
+  // Rejects numbers starting with a plus sign.
+  EXPECT_FALSE(ParseNaturalNumber("+123", &result));
+  errno = 0;
+}
+
+TEST(ParseNaturalNumberTest, RejectsOverflownNumbers) {
+  BiggestParsable result = 0;
+
+  EXPECT_FALSE(ParseNaturalNumber("99999999999999999999999", &result));
+
+  signed char char_result = 0;
+  EXPECT_FALSE(ParseNaturalNumber("200", &char_result));
+  errno = 0;
+}
+
+TEST(ParseNaturalNumberTest, AcceptsValidNumbers) {
+  BiggestParsable result = 0;
+
+  result = 0;
+  ASSERT_TRUE(ParseNaturalNumber("123", &result));
+  EXPECT_EQ(123U, result);
+
+  // Check 0 as an edge case.
+  result = 1;
+  ASSERT_TRUE(ParseNaturalNumber("0", &result));
+  EXPECT_EQ(0U, result);
+
+  result = 1;
+  ASSERT_TRUE(ParseNaturalNumber("00000", &result));
+  EXPECT_EQ(0U, result);
+}
+
+TEST(ParseNaturalNumberTest, AcceptsTypeLimits) {
+  Message msg;
+  msg << kBiggestParsableMax;
+
+  BiggestParsable result = 0;
+  EXPECT_TRUE(ParseNaturalNumber(msg.GetString(), &result));
+  EXPECT_EQ(kBiggestParsableMax, result);
+
+  Message msg2;
+  msg2 << kBiggestSignedParsableMax;
+
+  BiggestSignedParsable signed_result = 0;
+  EXPECT_TRUE(ParseNaturalNumber(msg2.GetString(), &signed_result));
+  EXPECT_EQ(kBiggestSignedParsableMax, signed_result);
+
+  Message msg3;
+  msg3 << INT_MAX;
+
+  int int_result = 0;
+  EXPECT_TRUE(ParseNaturalNumber(msg3.GetString(), &int_result));
+  EXPECT_EQ(INT_MAX, int_result);
+
+  Message msg4;
+  msg4 << UINT_MAX;
+
+  unsigned int uint_result = 0;
+  EXPECT_TRUE(ParseNaturalNumber(msg4.GetString(), &uint_result));
+  EXPECT_EQ(UINT_MAX, uint_result);
+}
+
+TEST(ParseNaturalNumberTest, WorksForShorterIntegers) {
+  short short_result = 0;
+  ASSERT_TRUE(ParseNaturalNumber("123", &short_result));
+  EXPECT_EQ(123, short_result);
+
+  signed char char_result = 0;
+  ASSERT_TRUE(ParseNaturalNumber("123", &char_result));
+  EXPECT_EQ(123, char_result);
+}
+
+# if GTEST_OS_WINDOWS
+TEST(EnvironmentTest, HandleFitsIntoSizeT) {
+  // TODO(vladl@google.com): Remove this test after this condition is verified
+  // in a static assertion in gtest-death-test.cc in the function
+  // GetStatusFileDescriptor.
+  ASSERT_TRUE(sizeof(HANDLE) <= sizeof(size_t));
+}
+# endif  // GTEST_OS_WINDOWS
+
+// Tests that EXPECT_DEATH_IF_SUPPORTED/ASSERT_DEATH_IF_SUPPORTED trigger
+// failures when death tests are available on the system.
+TEST(ConditionalDeathMacrosDeathTest, ExpectsDeathWhenDeathTestsAvailable) {
+  EXPECT_DEATH_IF_SUPPORTED(DieInside("CondDeathTestExpectMacro"),
+                            "death inside CondDeathTestExpectMacro");
+  ASSERT_DEATH_IF_SUPPORTED(DieInside("CondDeathTestAssertMacro"),
+                            "death inside CondDeathTestAssertMacro");
+
+  // Empty statement will not crash, which must trigger a failure.
+  EXPECT_NONFATAL_FAILURE(EXPECT_DEATH_IF_SUPPORTED(;, ""), "");
+  EXPECT_FATAL_FAILURE(ASSERT_DEATH_IF_SUPPORTED(;, ""), "");
+}
+
+TEST(InDeathTestChildDeathTest, ReportsDeathTestCorrectlyInFastStyle) {
+  testing::GTEST_FLAG(death_test_style) = "fast";
+  EXPECT_FALSE(InDeathTestChild());
+  EXPECT_DEATH({
+    fprintf(stderr, InDeathTestChild() ? "Inside" : "Outside");
+    fflush(stderr);
+    _exit(1);
+  }, "Inside");
+}
+
+TEST(InDeathTestChildDeathTest, ReportsDeathTestCorrectlyInThreadSafeStyle) {
+  testing::GTEST_FLAG(death_test_style) = "threadsafe";
+  EXPECT_FALSE(InDeathTestChild());
+  EXPECT_DEATH({
+    fprintf(stderr, InDeathTestChild() ? "Inside" : "Outside");
+    fflush(stderr);
+    _exit(1);
+  }, "Inside");
+}
+
+#else  // !GTEST_HAS_DEATH_TEST follows
+
+using testing::internal::CaptureStderr;
+using testing::internal::GetCapturedStderr;
+
+// Tests that EXPECT_DEATH_IF_SUPPORTED/ASSERT_DEATH_IF_SUPPORTED are still
+// defined but do not trigger failures when death tests are not available on
+// the system.
+TEST(ConditionalDeathMacrosTest, WarnsWhenDeathTestsNotAvailable) {
+  // Empty statement will not crash, but that should not trigger a failure
+  // when death tests are not supported.
+  CaptureStderr();
+  EXPECT_DEATH_IF_SUPPORTED(;, "");
+  std::string output = GetCapturedStderr();
+  ASSERT_TRUE(NULL != strstr(output.c_str(),
+                             "Death tests are not supported on this platform"));
+  ASSERT_TRUE(NULL != strstr(output.c_str(), ";"));
+
+  // The streamed message should not be printed as there is no test failure.
+  CaptureStderr();
+  EXPECT_DEATH_IF_SUPPORTED(;, "") << "streamed message";
+  output = GetCapturedStderr();
+  ASSERT_TRUE(NULL == strstr(output.c_str(), "streamed message"));
+
+  CaptureStderr();
+  ASSERT_DEATH_IF_SUPPORTED(;, "");  // NOLINT
+  output = GetCapturedStderr();
+  ASSERT_TRUE(NULL != strstr(output.c_str(),
+                             "Death tests are not supported on this platform"));
+  ASSERT_TRUE(NULL != strstr(output.c_str(), ";"));
+
+  CaptureStderr();
+  ASSERT_DEATH_IF_SUPPORTED(;, "") << "streamed message";  // NOLINT
+  output = GetCapturedStderr();
+  ASSERT_TRUE(NULL == strstr(output.c_str(), "streamed message"));
+}
+
+void FuncWithAssert(int* n) {
+  ASSERT_DEATH_IF_SUPPORTED(return;, "");
+  (*n)++;
+}
+
+// Tests that ASSERT_DEATH_IF_SUPPORTED does not return from the current
+// function (as ASSERT_DEATH does) if death tests are not supported.
+TEST(ConditionalDeathMacrosTest, AssertDeatDoesNotReturnhIfUnsupported) {
+  int n = 0;
+  FuncWithAssert(&n);
+  EXPECT_EQ(1, n);
+}
+
+#endif  // !GTEST_HAS_DEATH_TEST
+
+// Tests that the death test macros expand to code which may or may not
+// be followed by operator<<, and that in either case the complete text
+// comprises only a single C++ statement.
+//
+// The syntax should work whether death tests are available or not.
+TEST(ConditionalDeathMacrosSyntaxDeathTest, SingleStatement) {
+  if (AlwaysFalse())
+    // This would fail if executed; this is a compilation test only
+    ASSERT_DEATH_IF_SUPPORTED(return, "");
+
+  if (AlwaysTrue())
+    EXPECT_DEATH_IF_SUPPORTED(_exit(1), "");
+  else
+    // This empty "else" branch is meant to ensure that EXPECT_DEATH
+    // doesn't expand into an "if" statement without an "else"
+    ;  // NOLINT
+
+  if (AlwaysFalse())
+    ASSERT_DEATH_IF_SUPPORTED(return, "") << "did not die";
+
+  if (AlwaysFalse())
+    ;  // NOLINT
+  else
+    EXPECT_DEATH_IF_SUPPORTED(_exit(1), "") << 1 << 2 << 3;
+}
+
+// Tests that conditional death test macros expand to code which interacts
+// well with switch statements.
+TEST(ConditionalDeathMacrosSyntaxDeathTest, SwitchStatement) {
+  // Microsoft compiler usually complains about switch statements without
+  // case labels. We suppress that warning for this test.
+  GTEST_DISABLE_MSC_WARNINGS_PUSH_(4065)
+
+  switch (0)
+    default:
+      ASSERT_DEATH_IF_SUPPORTED(_exit(1), "")
+          << "exit in default switch handler";
+
+  switch (0)
+    case 0:
+      EXPECT_DEATH_IF_SUPPORTED(_exit(1), "") << "exit in switch case";
+
+  GTEST_DISABLE_MSC_WARNINGS_POP_()
+}
+
+// Tests that a test case whose name ends with "DeathTest" works fine
+// on Windows.
+TEST(NotADeathTest, Test) {
+  SUCCEED();
+}
diff --git a/third_party/googletest/googletest/test/gtest-filepath_test.cc b/third_party/googletest/googletest/test/gtest-filepath_test.cc
new file mode 100644
index 0000000..da72986
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest-filepath_test.cc
@@ -0,0 +1,662 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: keith.ray@gmail.com (Keith Ray)
+//
+// Google Test filepath utilities
+//
+// This file tests classes and functions used internally by
+// Google Test.  They are subject to change without notice.
+//
+// This file is #included from gtest_unittest.cc, to avoid changing
+// build or make-files for some existing Google Test clients. Do not
+// #include this file anywhere else!
+
+#include "gtest/internal/gtest-filepath.h"
+#include "gtest/gtest.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+#if GTEST_OS_WINDOWS_MOBILE
+# include <windows.h>  // NOLINT
+#elif GTEST_OS_WINDOWS
+# include <direct.h>  // NOLINT
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+namespace testing {
+namespace internal {
+namespace {
+
+#if GTEST_OS_WINDOWS_MOBILE
+// TODO(wan@google.com): Move these to the POSIX adapter section in
+// gtest-port.h.
+
+// Windows CE doesn't have the remove C function.
+int remove(const char* path) {
+  LPCWSTR wpath = String::AnsiToUtf16(path);
+  int ret = DeleteFile(wpath) ? 0 : -1;
+  delete [] wpath;
+  return ret;
+}
+// Windows CE doesn't have the _rmdir C function.
+int _rmdir(const char* path) {
+  FilePath filepath(path);
+  LPCWSTR wpath = String::AnsiToUtf16(
+      filepath.RemoveTrailingPathSeparator().c_str());
+  int ret = RemoveDirectory(wpath) ? 0 : -1;
+  delete [] wpath;
+  return ret;
+}
+
+#else
+
+TEST(GetCurrentDirTest, ReturnsCurrentDir) {
+  const FilePath original_dir = FilePath::GetCurrentDir();
+  EXPECT_FALSE(original_dir.IsEmpty());
+
+  posix::ChDir(GTEST_PATH_SEP_);
+  const FilePath cwd = FilePath::GetCurrentDir();
+  posix::ChDir(original_dir.c_str());
+
+# if GTEST_OS_WINDOWS
+
+  // Skips the ":".
+  const char* const cwd_without_drive = strchr(cwd.c_str(), ':');
+  ASSERT_TRUE(cwd_without_drive != NULL);
+  EXPECT_STREQ(GTEST_PATH_SEP_, cwd_without_drive + 1);
+
+# else
+
+  EXPECT_EQ(GTEST_PATH_SEP_, cwd.string());
+
+# endif
+}
+
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+TEST(IsEmptyTest, ReturnsTrueForEmptyPath) {
+  EXPECT_TRUE(FilePath("").IsEmpty());
+}
+
+TEST(IsEmptyTest, ReturnsFalseForNonEmptyPath) {
+  EXPECT_FALSE(FilePath("a").IsEmpty());
+  EXPECT_FALSE(FilePath(".").IsEmpty());
+  EXPECT_FALSE(FilePath("a/b").IsEmpty());
+  EXPECT_FALSE(FilePath("a\\b\\").IsEmpty());
+}
+
+// RemoveDirectoryName "" -> ""
+TEST(RemoveDirectoryNameTest, WhenEmptyName) {
+  EXPECT_EQ("", FilePath("").RemoveDirectoryName().string());
+}
+
+// RemoveDirectoryName "afile" -> "afile"
+TEST(RemoveDirectoryNameTest, ButNoDirectory) {
+  EXPECT_EQ("afile",
+      FilePath("afile").RemoveDirectoryName().string());
+}
+
+// RemoveDirectoryName "/afile" -> "afile"
+TEST(RemoveDirectoryNameTest, RootFileShouldGiveFileName) {
+  EXPECT_EQ("afile",
+      FilePath(GTEST_PATH_SEP_ "afile").RemoveDirectoryName().string());
+}
+
+// RemoveDirectoryName "adir/" -> ""
+TEST(RemoveDirectoryNameTest, WhereThereIsNoFileName) {
+  EXPECT_EQ("",
+      FilePath("adir" GTEST_PATH_SEP_).RemoveDirectoryName().string());
+}
+
+// RemoveDirectoryName "adir/afile" -> "afile"
+TEST(RemoveDirectoryNameTest, ShouldGiveFileName) {
+  EXPECT_EQ("afile",
+      FilePath("adir" GTEST_PATH_SEP_ "afile").RemoveDirectoryName().string());
+}
+
+// RemoveDirectoryName "adir/subdir/afile" -> "afile"
+TEST(RemoveDirectoryNameTest, ShouldAlsoGiveFileName) {
+  EXPECT_EQ("afile",
+      FilePath("adir" GTEST_PATH_SEP_ "subdir" GTEST_PATH_SEP_ "afile")
+      .RemoveDirectoryName().string());
+}
+
+#if GTEST_HAS_ALT_PATH_SEP_
+
+// Tests that RemoveDirectoryName() works with the alternate separator
+// on Windows.
+
+// RemoveDirectoryName("/afile") -> "afile"
+TEST(RemoveDirectoryNameTest, RootFileShouldGiveFileNameForAlternateSeparator) {
+  EXPECT_EQ("afile", FilePath("/afile").RemoveDirectoryName().string());
+}
+
+// RemoveDirectoryName("adir/") -> ""
+TEST(RemoveDirectoryNameTest, WhereThereIsNoFileNameForAlternateSeparator) {
+  EXPECT_EQ("", FilePath("adir/").RemoveDirectoryName().string());
+}
+
+// RemoveDirectoryName("adir/afile") -> "afile"
+TEST(RemoveDirectoryNameTest, ShouldGiveFileNameForAlternateSeparator) {
+  EXPECT_EQ("afile", FilePath("adir/afile").RemoveDirectoryName().string());
+}
+
+// RemoveDirectoryName("adir/subdir/afile") -> "afile"
+TEST(RemoveDirectoryNameTest, ShouldAlsoGiveFileNameForAlternateSeparator) {
+  EXPECT_EQ("afile",
+            FilePath("adir/subdir/afile").RemoveDirectoryName().string());
+}
+
+#endif
+
+// RemoveFileName "" -> "./"
+TEST(RemoveFileNameTest, EmptyName) {
+#if GTEST_OS_WINDOWS_MOBILE
+  // On Windows CE, we use the root as the current directory.
+  EXPECT_EQ(GTEST_PATH_SEP_, FilePath("").RemoveFileName().string());
+#else
+  EXPECT_EQ("." GTEST_PATH_SEP_, FilePath("").RemoveFileName().string());
+#endif
+}
+
+// RemoveFileName "adir/" -> "adir/"
+TEST(RemoveFileNameTest, ButNoFile) {
+  EXPECT_EQ("adir" GTEST_PATH_SEP_,
+      FilePath("adir" GTEST_PATH_SEP_).RemoveFileName().string());
+}
+
+// RemoveFileName "adir/afile" -> "adir/"
+TEST(RemoveFileNameTest, GivesDirName) {
+  EXPECT_EQ("adir" GTEST_PATH_SEP_,
+            FilePath("adir" GTEST_PATH_SEP_ "afile").RemoveFileName().string());
+}
+
+// RemoveFileName "adir/subdir/afile" -> "adir/subdir/"
+TEST(RemoveFileNameTest, GivesDirAndSubDirName) {
+  EXPECT_EQ("adir" GTEST_PATH_SEP_ "subdir" GTEST_PATH_SEP_,
+      FilePath("adir" GTEST_PATH_SEP_ "subdir" GTEST_PATH_SEP_ "afile")
+      .RemoveFileName().string());
+}
+
+// RemoveFileName "/afile" -> "/"
+TEST(RemoveFileNameTest, GivesRootDir) {
+  EXPECT_EQ(GTEST_PATH_SEP_,
+      FilePath(GTEST_PATH_SEP_ "afile").RemoveFileName().string());
+}
+
+#if GTEST_HAS_ALT_PATH_SEP_
+
+// Tests that RemoveFileName() works with the alternate separator on
+// Windows.
+
+// RemoveFileName("adir/") -> "adir/"
+TEST(RemoveFileNameTest, ButNoFileForAlternateSeparator) {
+  EXPECT_EQ("adir" GTEST_PATH_SEP_,
+            FilePath("adir/").RemoveFileName().string());
+}
+
+// RemoveFileName("adir/afile") -> "adir/"
+TEST(RemoveFileNameTest, GivesDirNameForAlternateSeparator) {
+  EXPECT_EQ("adir" GTEST_PATH_SEP_,
+            FilePath("adir/afile").RemoveFileName().string());
+}
+
+// RemoveFileName("adir/subdir/afile") -> "adir/subdir/"
+TEST(RemoveFileNameTest, GivesDirAndSubDirNameForAlternateSeparator) {
+  EXPECT_EQ("adir" GTEST_PATH_SEP_ "subdir" GTEST_PATH_SEP_,
+            FilePath("adir/subdir/afile").RemoveFileName().string());
+}
+
+// RemoveFileName("/afile") -> "\"
+TEST(RemoveFileNameTest, GivesRootDirForAlternateSeparator) {
+  EXPECT_EQ(GTEST_PATH_SEP_, FilePath("/afile").RemoveFileName().string());
+}
+
+#endif
+
+TEST(MakeFileNameTest, GenerateWhenNumberIsZero) {
+  FilePath actual = FilePath::MakeFileName(FilePath("foo"), FilePath("bar"),
+      0, "xml");
+  EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar.xml", actual.string());
+}
+
+TEST(MakeFileNameTest, GenerateFileNameNumberGtZero) {
+  FilePath actual = FilePath::MakeFileName(FilePath("foo"), FilePath("bar"),
+      12, "xml");
+  EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar_12.xml", actual.string());
+}
+
+TEST(MakeFileNameTest, GenerateFileNameWithSlashNumberIsZero) {
+  FilePath actual = FilePath::MakeFileName(FilePath("foo" GTEST_PATH_SEP_),
+      FilePath("bar"), 0, "xml");
+  EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar.xml", actual.string());
+}
+
+TEST(MakeFileNameTest, GenerateFileNameWithSlashNumberGtZero) {
+  FilePath actual = FilePath::MakeFileName(FilePath("foo" GTEST_PATH_SEP_),
+      FilePath("bar"), 12, "xml");
+  EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar_12.xml", actual.string());
+}
+
+TEST(MakeFileNameTest, GenerateWhenNumberIsZeroAndDirIsEmpty) {
+  FilePath actual = FilePath::MakeFileName(FilePath(""), FilePath("bar"),
+      0, "xml");
+  EXPECT_EQ("bar.xml", actual.string());
+}
+
+TEST(MakeFileNameTest, GenerateWhenNumberIsNotZeroAndDirIsEmpty) {
+  FilePath actual = FilePath::MakeFileName(FilePath(""), FilePath("bar"),
+      14, "xml");
+  EXPECT_EQ("bar_14.xml", actual.string());
+}
+
+TEST(ConcatPathsTest, WorksWhenDirDoesNotEndWithPathSep) {
+  FilePath actual = FilePath::ConcatPaths(FilePath("foo"),
+                                          FilePath("bar.xml"));
+  EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar.xml", actual.string());
+}
+
+TEST(ConcatPathsTest, WorksWhenPath1EndsWithPathSep) {
+  FilePath actual = FilePath::ConcatPaths(FilePath("foo" GTEST_PATH_SEP_),
+                                          FilePath("bar.xml"));
+  EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar.xml", actual.string());
+}
+
+TEST(ConcatPathsTest, Path1BeingEmpty) {
+  FilePath actual = FilePath::ConcatPaths(FilePath(""),
+                                          FilePath("bar.xml"));
+  EXPECT_EQ("bar.xml", actual.string());
+}
+
+TEST(ConcatPathsTest, Path2BeingEmpty) {
+  FilePath actual = FilePath::ConcatPaths(FilePath("foo"), FilePath(""));
+  EXPECT_EQ("foo" GTEST_PATH_SEP_, actual.string());
+}
+
+TEST(ConcatPathsTest, BothPathBeingEmpty) {
+  FilePath actual = FilePath::ConcatPaths(FilePath(""),
+                                          FilePath(""));
+  EXPECT_EQ("", actual.string());
+}
+
+TEST(ConcatPathsTest, Path1ContainsPathSep) {
+  FilePath actual = FilePath::ConcatPaths(FilePath("foo" GTEST_PATH_SEP_ "bar"),
+                                          FilePath("foobar.xml"));
+  EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar" GTEST_PATH_SEP_ "foobar.xml",
+            actual.string());
+}
+
+TEST(ConcatPathsTest, Path2ContainsPathSep) {
+  FilePath actual = FilePath::ConcatPaths(
+      FilePath("foo" GTEST_PATH_SEP_),
+      FilePath("bar" GTEST_PATH_SEP_ "bar.xml"));
+  EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar" GTEST_PATH_SEP_ "bar.xml",
+            actual.string());
+}
+
+TEST(ConcatPathsTest, Path2EndsWithPathSep) {
+  FilePath actual = FilePath::ConcatPaths(FilePath("foo"),
+                                          FilePath("bar" GTEST_PATH_SEP_));
+  EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar" GTEST_PATH_SEP_, actual.string());
+}
+
+// RemoveTrailingPathSeparator "" -> ""
+TEST(RemoveTrailingPathSeparatorTest, EmptyString) {
+  EXPECT_EQ("", FilePath("").RemoveTrailingPathSeparator().string());
+}
+
+// RemoveTrailingPathSeparator "foo" -> "foo"
+TEST(RemoveTrailingPathSeparatorTest, FileNoSlashString) {
+  EXPECT_EQ("foo", FilePath("foo").RemoveTrailingPathSeparator().string());
+}
+
+// RemoveTrailingPathSeparator "foo/" -> "foo"
+TEST(RemoveTrailingPathSeparatorTest, ShouldRemoveTrailingSeparator) {
+  EXPECT_EQ("foo",
+      FilePath("foo" GTEST_PATH_SEP_).RemoveTrailingPathSeparator().string());
+#if GTEST_HAS_ALT_PATH_SEP_
+  EXPECT_EQ("foo", FilePath("foo/").RemoveTrailingPathSeparator().string());
+#endif
+}
+
+// RemoveTrailingPathSeparator "foo/bar/" -> "foo/bar/"
+TEST(RemoveTrailingPathSeparatorTest, ShouldRemoveLastSeparator) {
+  EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar",
+            FilePath("foo" GTEST_PATH_SEP_ "bar" GTEST_PATH_SEP_)
+                .RemoveTrailingPathSeparator().string());
+}
+
+// RemoveTrailingPathSeparator "foo/bar" -> "foo/bar"
+TEST(RemoveTrailingPathSeparatorTest, ShouldReturnUnmodified) {
+  EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar",
+            FilePath("foo" GTEST_PATH_SEP_ "bar")
+                .RemoveTrailingPathSeparator().string());
+}
+
+TEST(DirectoryTest, RootDirectoryExists) {
+#if GTEST_OS_WINDOWS  // We are on Windows.
+  char current_drive[_MAX_PATH];  // NOLINT
+  current_drive[0] = static_cast<char>(_getdrive() + 'A' - 1);
+  current_drive[1] = ':';
+  current_drive[2] = '\\';
+  current_drive[3] = '\0';
+  EXPECT_TRUE(FilePath(current_drive).DirectoryExists());
+#else
+  EXPECT_TRUE(FilePath("/").DirectoryExists());
+#endif  // GTEST_OS_WINDOWS
+}
+
+#if GTEST_OS_WINDOWS
+TEST(DirectoryTest, RootOfWrongDriveDoesNotExists) {
+  const int saved_drive_ = _getdrive();
+  // Find a drive that doesn't exist. Start with 'Z' to avoid common ones.
+  for (char drive = 'Z'; drive >= 'A'; drive--)
+    if (_chdrive(drive - 'A' + 1) == -1) {
+      char non_drive[_MAX_PATH];  // NOLINT
+      non_drive[0] = drive;
+      non_drive[1] = ':';
+      non_drive[2] = '\\';
+      non_drive[3] = '\0';
+      EXPECT_FALSE(FilePath(non_drive).DirectoryExists());
+      break;
+    }
+  _chdrive(saved_drive_);
+}
+#endif  // GTEST_OS_WINDOWS
+
+#if !GTEST_OS_WINDOWS_MOBILE
+// Windows CE _does_ consider an empty directory to exist.
+TEST(DirectoryTest, EmptyPathDirectoryDoesNotExist) {
+  EXPECT_FALSE(FilePath("").DirectoryExists());
+}
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+TEST(DirectoryTest, CurrentDirectoryExists) {
+#if GTEST_OS_WINDOWS  // We are on Windows.
+# ifndef _WIN32_CE  // Windows CE doesn't have a current directory.
+
+  EXPECT_TRUE(FilePath(".").DirectoryExists());
+  EXPECT_TRUE(FilePath(".\\").DirectoryExists());
+
+# endif  // _WIN32_CE
+#else
+  EXPECT_TRUE(FilePath(".").DirectoryExists());
+  EXPECT_TRUE(FilePath("./").DirectoryExists());
+#endif  // GTEST_OS_WINDOWS
+}
+
+// "foo/bar" == foo//bar" == "foo///bar"
+TEST(NormalizeTest, MultipleConsecutiveSepaparatorsInMidstring) {
+  EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar",
+            FilePath("foo" GTEST_PATH_SEP_ "bar").string());
+  EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar",
+            FilePath("foo" GTEST_PATH_SEP_ GTEST_PATH_SEP_ "bar").string());
+  EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar",
+            FilePath("foo" GTEST_PATH_SEP_ GTEST_PATH_SEP_
+                     GTEST_PATH_SEP_ "bar").string());
+}
+
+// "/bar" == //bar" == "///bar"
+TEST(NormalizeTest, MultipleConsecutiveSepaparatorsAtStringStart) {
+  EXPECT_EQ(GTEST_PATH_SEP_ "bar",
+    FilePath(GTEST_PATH_SEP_ "bar").string());
+  EXPECT_EQ(GTEST_PATH_SEP_ "bar",
+    FilePath(GTEST_PATH_SEP_ GTEST_PATH_SEP_ "bar").string());
+  EXPECT_EQ(GTEST_PATH_SEP_ "bar",
+    FilePath(GTEST_PATH_SEP_ GTEST_PATH_SEP_ GTEST_PATH_SEP_ "bar").string());
+}
+
+// "foo/" == foo//" == "foo///"
+TEST(NormalizeTest, MultipleConsecutiveSepaparatorsAtStringEnd) {
+  EXPECT_EQ("foo" GTEST_PATH_SEP_,
+    FilePath("foo" GTEST_PATH_SEP_).string());
+  EXPECT_EQ("foo" GTEST_PATH_SEP_,
+    FilePath("foo" GTEST_PATH_SEP_ GTEST_PATH_SEP_).string());
+  EXPECT_EQ("foo" GTEST_PATH_SEP_,
+    FilePath("foo" GTEST_PATH_SEP_ GTEST_PATH_SEP_ GTEST_PATH_SEP_).string());
+}
+
+#if GTEST_HAS_ALT_PATH_SEP_
+
+// Tests that separators at the end of the string are normalized
+// regardless of their combination (e.g. "foo\" =="foo/\" ==
+// "foo\\/").
+TEST(NormalizeTest, MixAlternateSeparatorAtStringEnd) {
+  EXPECT_EQ("foo" GTEST_PATH_SEP_,
+            FilePath("foo/").string());
+  EXPECT_EQ("foo" GTEST_PATH_SEP_,
+            FilePath("foo" GTEST_PATH_SEP_ "/").string());
+  EXPECT_EQ("foo" GTEST_PATH_SEP_,
+            FilePath("foo//" GTEST_PATH_SEP_).string());
+}
+
+#endif
+
+TEST(AssignmentOperatorTest, DefaultAssignedToNonDefault) {
+  FilePath default_path;
+  FilePath non_default_path("path");
+  non_default_path = default_path;
+  EXPECT_EQ("", non_default_path.string());
+  EXPECT_EQ("", default_path.string());  // RHS var is unchanged.
+}
+
+TEST(AssignmentOperatorTest, NonDefaultAssignedToDefault) {
+  FilePath non_default_path("path");
+  FilePath default_path;
+  default_path = non_default_path;
+  EXPECT_EQ("path", default_path.string());
+  EXPECT_EQ("path", non_default_path.string());  // RHS var is unchanged.
+}
+
+TEST(AssignmentOperatorTest, ConstAssignedToNonConst) {
+  const FilePath const_default_path("const_path");
+  FilePath non_default_path("path");
+  non_default_path = const_default_path;
+  EXPECT_EQ("const_path", non_default_path.string());
+}
+
+class DirectoryCreationTest : public Test {
+ protected:
+  virtual void SetUp() {
+    testdata_path_.Set(FilePath(
+        TempDir() + GetCurrentExecutableName().string() +
+        "_directory_creation" GTEST_PATH_SEP_ "test" GTEST_PATH_SEP_));
+    testdata_file_.Set(testdata_path_.RemoveTrailingPathSeparator());
+
+    unique_file0_.Set(FilePath::MakeFileName(testdata_path_, FilePath("unique"),
+        0, "txt"));
+    unique_file1_.Set(FilePath::MakeFileName(testdata_path_, FilePath("unique"),
+        1, "txt"));
+
+    remove(testdata_file_.c_str());
+    remove(unique_file0_.c_str());
+    remove(unique_file1_.c_str());
+    posix::RmDir(testdata_path_.c_str());
+  }
+
+  virtual void TearDown() {
+    remove(testdata_file_.c_str());
+    remove(unique_file0_.c_str());
+    remove(unique_file1_.c_str());
+    posix::RmDir(testdata_path_.c_str());
+  }
+
+  void CreateTextFile(const char* filename) {
+    FILE* f = posix::FOpen(filename, "w");
+    fprintf(f, "text\n");
+    fclose(f);
+  }
+
+  // Strings representing a directory and a file, with identical paths
+  // except for the trailing separator character that distinquishes
+  // a directory named 'test' from a file named 'test'. Example names:
+  FilePath testdata_path_;  // "/tmp/directory_creation/test/"
+  FilePath testdata_file_;  // "/tmp/directory_creation/test"
+  FilePath unique_file0_;  // "/tmp/directory_creation/test/unique.txt"
+  FilePath unique_file1_;  // "/tmp/directory_creation/test/unique_1.txt"
+};
+
+TEST_F(DirectoryCreationTest, CreateDirectoriesRecursively) {
+  EXPECT_FALSE(testdata_path_.DirectoryExists()) << testdata_path_.string();
+  EXPECT_TRUE(testdata_path_.CreateDirectoriesRecursively());
+  EXPECT_TRUE(testdata_path_.DirectoryExists());
+}
+
+TEST_F(DirectoryCreationTest, CreateDirectoriesForAlreadyExistingPath) {
+  EXPECT_FALSE(testdata_path_.DirectoryExists()) << testdata_path_.string();
+  EXPECT_TRUE(testdata_path_.CreateDirectoriesRecursively());
+  // Call 'create' again... should still succeed.
+  EXPECT_TRUE(testdata_path_.CreateDirectoriesRecursively());
+}
+
+TEST_F(DirectoryCreationTest, CreateDirectoriesAndUniqueFilename) {
+  FilePath file_path(FilePath::GenerateUniqueFileName(testdata_path_,
+      FilePath("unique"), "txt"));
+  EXPECT_EQ(unique_file0_.string(), file_path.string());
+  EXPECT_FALSE(file_path.FileOrDirectoryExists());  // file not there
+
+  testdata_path_.CreateDirectoriesRecursively();
+  EXPECT_FALSE(file_path.FileOrDirectoryExists());  // file still not there
+  CreateTextFile(file_path.c_str());
+  EXPECT_TRUE(file_path.FileOrDirectoryExists());
+
+  FilePath file_path2(FilePath::GenerateUniqueFileName(testdata_path_,
+      FilePath("unique"), "txt"));
+  EXPECT_EQ(unique_file1_.string(), file_path2.string());
+  EXPECT_FALSE(file_path2.FileOrDirectoryExists());  // file not there
+  CreateTextFile(file_path2.c_str());
+  EXPECT_TRUE(file_path2.FileOrDirectoryExists());
+}
+
+TEST_F(DirectoryCreationTest, CreateDirectoriesFail) {
+  // force a failure by putting a file where we will try to create a directory.
+  CreateTextFile(testdata_file_.c_str());
+  EXPECT_TRUE(testdata_file_.FileOrDirectoryExists());
+  EXPECT_FALSE(testdata_file_.DirectoryExists());
+  EXPECT_FALSE(testdata_file_.CreateDirectoriesRecursively());
+}
+
+TEST(NoDirectoryCreationTest, CreateNoDirectoriesForDefaultXmlFile) {
+  const FilePath test_detail_xml("test_detail.xml");
+  EXPECT_FALSE(test_detail_xml.CreateDirectoriesRecursively());
+}
+
+TEST(FilePathTest, DefaultConstructor) {
+  FilePath fp;
+  EXPECT_EQ("", fp.string());
+}
+
+TEST(FilePathTest, CharAndCopyConstructors) {
+  const FilePath fp("spicy");
+  EXPECT_EQ("spicy", fp.string());
+
+  const FilePath fp_copy(fp);
+  EXPECT_EQ("spicy", fp_copy.string());
+}
+
+TEST(FilePathTest, StringConstructor) {
+  const FilePath fp(std::string("cider"));
+  EXPECT_EQ("cider", fp.string());
+}
+
+TEST(FilePathTest, Set) {
+  const FilePath apple("apple");
+  FilePath mac("mac");
+  mac.Set(apple);  // Implement Set() since overloading operator= is forbidden.
+  EXPECT_EQ("apple", mac.string());
+  EXPECT_EQ("apple", apple.string());
+}
+
+TEST(FilePathTest, ToString) {
+  const FilePath file("drink");
+  EXPECT_EQ("drink", file.string());
+}
+
+TEST(FilePathTest, RemoveExtension) {
+  EXPECT_EQ("app", FilePath("app.cc").RemoveExtension("cc").string());
+  EXPECT_EQ("app", FilePath("app.exe").RemoveExtension("exe").string());
+  EXPECT_EQ("APP", FilePath("APP.EXE").RemoveExtension("exe").string());
+}
+
+TEST(FilePathTest, RemoveExtensionWhenThereIsNoExtension) {
+  EXPECT_EQ("app", FilePath("app").RemoveExtension("exe").string());
+}
+
+TEST(FilePathTest, IsDirectory) {
+  EXPECT_FALSE(FilePath("cola").IsDirectory());
+  EXPECT_TRUE(FilePath("koala" GTEST_PATH_SEP_).IsDirectory());
+#if GTEST_HAS_ALT_PATH_SEP_
+  EXPECT_TRUE(FilePath("koala/").IsDirectory());
+#endif
+}
+
+TEST(FilePathTest, IsAbsolutePath) {
+  EXPECT_FALSE(FilePath("is" GTEST_PATH_SEP_ "relative").IsAbsolutePath());
+  EXPECT_FALSE(FilePath("").IsAbsolutePath());
+#if GTEST_OS_WINDOWS
+  EXPECT_TRUE(FilePath("c:\\" GTEST_PATH_SEP_ "is_not"
+                       GTEST_PATH_SEP_ "relative").IsAbsolutePath());
+  EXPECT_FALSE(FilePath("c:foo" GTEST_PATH_SEP_ "bar").IsAbsolutePath());
+  EXPECT_TRUE(FilePath("c:/" GTEST_PATH_SEP_ "is_not"
+                       GTEST_PATH_SEP_ "relative").IsAbsolutePath());
+#else
+  EXPECT_TRUE(FilePath(GTEST_PATH_SEP_ "is_not" GTEST_PATH_SEP_ "relative")
+              .IsAbsolutePath());
+#endif  // GTEST_OS_WINDOWS
+}
+
+TEST(FilePathTest, IsRootDirectory) {
+#if GTEST_OS_WINDOWS
+  EXPECT_TRUE(FilePath("a:\\").IsRootDirectory());
+  EXPECT_TRUE(FilePath("Z:/").IsRootDirectory());
+  EXPECT_TRUE(FilePath("e://").IsRootDirectory());
+  EXPECT_FALSE(FilePath("").IsRootDirectory());
+  EXPECT_FALSE(FilePath("b:").IsRootDirectory());
+  EXPECT_FALSE(FilePath("b:a").IsRootDirectory());
+  EXPECT_FALSE(FilePath("8:/").IsRootDirectory());
+  EXPECT_FALSE(FilePath("c|/").IsRootDirectory());
+#else
+  EXPECT_TRUE(FilePath("/").IsRootDirectory());
+  EXPECT_TRUE(FilePath("//").IsRootDirectory());
+  EXPECT_FALSE(FilePath("").IsRootDirectory());
+  EXPECT_FALSE(FilePath("\\").IsRootDirectory());
+  EXPECT_FALSE(FilePath("/x").IsRootDirectory());
+#endif
+}
+
+}  // namespace
+}  // namespace internal
+}  // namespace testing
diff --git a/third_party/googletest/googletest/test/gtest-linked_ptr_test.cc b/third_party/googletest/googletest/test/gtest-linked_ptr_test.cc
new file mode 100644
index 0000000..6fcf512
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest-linked_ptr_test.cc
@@ -0,0 +1,154 @@
+// Copyright 2003, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: Dan Egnor (egnor@google.com)
+// Ported to Windows: Vadim Berman (vadimb@google.com)
+
+#include "gtest/internal/gtest-linked_ptr.h"
+
+#include <stdlib.h>
+#include "gtest/gtest.h"
+
+namespace {
+
+using testing::Message;
+using testing::internal::linked_ptr;
+
+int num;
+Message* history = NULL;
+
+// Class which tracks allocation/deallocation
+class A {
+ public:
+  A(): mynum(num++) { *history << "A" << mynum << " ctor\n"; }
+  virtual ~A() { *history << "A" << mynum << " dtor\n"; }
+  virtual void Use() { *history << "A" << mynum << " use\n"; }
+ protected:
+  int mynum;
+};
+
+// Subclass
+class B : public A {
+ public:
+  B() { *history << "B" << mynum << " ctor\n"; }
+  ~B() { *history << "B" << mynum << " dtor\n"; }
+  virtual void Use() { *history << "B" << mynum << " use\n"; }
+};
+
+class LinkedPtrTest : public testing::Test {
+ public:
+  LinkedPtrTest() {
+    num = 0;
+    history = new Message;
+  }
+
+  virtual ~LinkedPtrTest() {
+    delete history;
+    history = NULL;
+  }
+};
+
+TEST_F(LinkedPtrTest, GeneralTest) {
+  {
+    linked_ptr<A> a0, a1, a2;
+    // Use explicit function call notation here to suppress self-assign warning.
+    a0.operator=(a0);
+    a1 = a2;
+    ASSERT_EQ(a0.get(), static_cast<A*>(NULL));
+    ASSERT_EQ(a1.get(), static_cast<A*>(NULL));
+    ASSERT_EQ(a2.get(), static_cast<A*>(NULL));
+    ASSERT_TRUE(a0 == NULL);
+    ASSERT_TRUE(a1 == NULL);
+    ASSERT_TRUE(a2 == NULL);
+
+    {
+      linked_ptr<A> a3(new A);
+      a0 = a3;
+      ASSERT_TRUE(a0 == a3);
+      ASSERT_TRUE(a0 != NULL);
+      ASSERT_TRUE(a0.get() == a3);
+      ASSERT_TRUE(a0 == a3.get());
+      linked_ptr<A> a4(a0);
+      a1 = a4;
+      linked_ptr<A> a5(new A);
+      ASSERT_TRUE(a5.get() != a3);
+      ASSERT_TRUE(a5 != a3.get());
+      a2 = a5;
+      linked_ptr<B> b0(new B);
+      linked_ptr<A> a6(b0);
+      ASSERT_TRUE(b0 == a6);
+      ASSERT_TRUE(a6 == b0);
+      ASSERT_TRUE(b0 != NULL);
+      a5 = b0;
+      a5 = b0;
+      a3->Use();
+      a4->Use();
+      a5->Use();
+      a6->Use();
+      b0->Use();
+      (*b0).Use();
+      b0.get()->Use();
+    }
+
+    a0->Use();
+    a1->Use();
+    a2->Use();
+
+    a1 = a2;
+    a2.reset(new A);
+    a0.reset();
+
+    linked_ptr<A> a7;
+  }
+
+  ASSERT_STREQ(
+    "A0 ctor\n"
+    "A1 ctor\n"
+    "A2 ctor\n"
+    "B2 ctor\n"
+    "A0 use\n"
+    "A0 use\n"
+    "B2 use\n"
+    "B2 use\n"
+    "B2 use\n"
+    "B2 use\n"
+    "B2 use\n"
+    "B2 dtor\n"
+    "A2 dtor\n"
+    "A0 use\n"
+    "A0 use\n"
+    "A1 use\n"
+    "A3 ctor\n"
+    "A0 dtor\n"
+    "A3 dtor\n"
+    "A1 dtor\n",
+    history->GetString().c_str());
+}
+
+}  // Unnamed namespace
diff --git a/third_party/googletest/googletest/test/gtest-listener_test.cc b/third_party/googletest/googletest/test/gtest-listener_test.cc
new file mode 100644
index 0000000..9074768
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest-listener_test.cc
@@ -0,0 +1,311 @@
+// Copyright 2009 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vladl@google.com (Vlad Losev)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This file verifies Google Test event listeners receive events at the
+// right times.
+
+#include "gtest/gtest.h"
+#include <vector>
+
+using ::testing::AddGlobalTestEnvironment;
+using ::testing::Environment;
+using ::testing::InitGoogleTest;
+using ::testing::Test;
+using ::testing::TestCase;
+using ::testing::TestEventListener;
+using ::testing::TestInfo;
+using ::testing::TestPartResult;
+using ::testing::UnitTest;
+
+// Used by tests to register their events.
+std::vector<std::string>* g_events = NULL;
+
+namespace testing {
+namespace internal {
+
+class EventRecordingListener : public TestEventListener {
+ public:
+  explicit EventRecordingListener(const char* name) : name_(name) {}
+
+ protected:
+  virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {
+    g_events->push_back(GetFullMethodName("OnTestProgramStart"));
+  }
+
+  virtual void OnTestIterationStart(const UnitTest& /*unit_test*/,
+                                    int iteration) {
+    Message message;
+    message << GetFullMethodName("OnTestIterationStart")
+            << "(" << iteration << ")";
+    g_events->push_back(message.GetString());
+  }
+
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) {
+    g_events->push_back(GetFullMethodName("OnEnvironmentsSetUpStart"));
+  }
+
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {
+    g_events->push_back(GetFullMethodName("OnEnvironmentsSetUpEnd"));
+  }
+
+  virtual void OnTestCaseStart(const TestCase& /*test_case*/) {
+    g_events->push_back(GetFullMethodName("OnTestCaseStart"));
+  }
+
+  virtual void OnTestStart(const TestInfo& /*test_info*/) {
+    g_events->push_back(GetFullMethodName("OnTestStart"));
+  }
+
+  virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) {
+    g_events->push_back(GetFullMethodName("OnTestPartResult"));
+  }
+
+  virtual void OnTestEnd(const TestInfo& /*test_info*/) {
+    g_events->push_back(GetFullMethodName("OnTestEnd"));
+  }
+
+  virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {
+    g_events->push_back(GetFullMethodName("OnTestCaseEnd"));
+  }
+
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) {
+    g_events->push_back(GetFullMethodName("OnEnvironmentsTearDownStart"));
+  }
+
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {
+    g_events->push_back(GetFullMethodName("OnEnvironmentsTearDownEnd"));
+  }
+
+  virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/,
+                                  int iteration) {
+    Message message;
+    message << GetFullMethodName("OnTestIterationEnd")
+            << "("  << iteration << ")";
+    g_events->push_back(message.GetString());
+  }
+
+  virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {
+    g_events->push_back(GetFullMethodName("OnTestProgramEnd"));
+  }
+
+ private:
+  std::string GetFullMethodName(const char* name) {
+    return name_ + "." + name;
+  }
+
+  std::string name_;
+};
+
+class EnvironmentInvocationCatcher : public Environment {
+ protected:
+  virtual void SetUp() {
+    g_events->push_back("Environment::SetUp");
+  }
+
+  virtual void TearDown() {
+    g_events->push_back("Environment::TearDown");
+  }
+};
+
+class ListenerTest : public Test {
+ protected:
+  static void SetUpTestCase() {
+    g_events->push_back("ListenerTest::SetUpTestCase");
+  }
+
+  static void TearDownTestCase() {
+    g_events->push_back("ListenerTest::TearDownTestCase");
+  }
+
+  virtual void SetUp() {
+    g_events->push_back("ListenerTest::SetUp");
+  }
+
+  virtual void TearDown() {
+    g_events->push_back("ListenerTest::TearDown");
+  }
+};
+
+TEST_F(ListenerTest, DoesFoo) {
+  // Test execution order within a test case is not guaranteed so we are not
+  // recording the test name.
+  g_events->push_back("ListenerTest::* Test Body");
+  SUCCEED();  // Triggers OnTestPartResult.
+}
+
+TEST_F(ListenerTest, DoesBar) {
+  g_events->push_back("ListenerTest::* Test Body");
+  SUCCEED();  // Triggers OnTestPartResult.
+}
+
+}  // namespace internal
+
+}  // namespace testing
+
+using ::testing::internal::EnvironmentInvocationCatcher;
+using ::testing::internal::EventRecordingListener;
+
+void VerifyResults(const std::vector<std::string>& data,
+                   const char* const* expected_data,
+                   size_t expected_data_size) {
+  const size_t actual_size = data.size();
+  // If the following assertion fails, a new entry will be appended to
+  // data.  Hence we save data.size() first.
+  EXPECT_EQ(expected_data_size, actual_size);
+
+  // Compares the common prefix.
+  const size_t shorter_size = expected_data_size <= actual_size ?
+      expected_data_size : actual_size;
+  size_t i = 0;
+  for (; i < shorter_size; ++i) {
+    ASSERT_STREQ(expected_data[i], data[i].c_str())
+        << "at position " << i;
+  }
+
+  // Prints extra elements in the actual data.
+  for (; i < actual_size; ++i) {
+    printf("  Actual event #%lu: %s\n",
+        static_cast<unsigned long>(i), data[i].c_str());
+  }
+}
+
+int main(int argc, char **argv) {
+  std::vector<std::string> events;
+  g_events = &events;
+  InitGoogleTest(&argc, argv);
+
+  UnitTest::GetInstance()->listeners().Append(
+      new EventRecordingListener("1st"));
+  UnitTest::GetInstance()->listeners().Append(
+      new EventRecordingListener("2nd"));
+
+  AddGlobalTestEnvironment(new EnvironmentInvocationCatcher);
+
+  GTEST_CHECK_(events.size() == 0)
+      << "AddGlobalTestEnvironment should not generate any events itself.";
+
+  ::testing::GTEST_FLAG(repeat) = 2;
+  int ret_val = RUN_ALL_TESTS();
+
+  const char* const expected_events[] = {
+    "1st.OnTestProgramStart",
+    "2nd.OnTestProgramStart",
+    "1st.OnTestIterationStart(0)",
+    "2nd.OnTestIterationStart(0)",
+    "1st.OnEnvironmentsSetUpStart",
+    "2nd.OnEnvironmentsSetUpStart",
+    "Environment::SetUp",
+    "2nd.OnEnvironmentsSetUpEnd",
+    "1st.OnEnvironmentsSetUpEnd",
+    "1st.OnTestCaseStart",
+    "2nd.OnTestCaseStart",
+    "ListenerTest::SetUpTestCase",
+    "1st.OnTestStart",
+    "2nd.OnTestStart",
+    "ListenerTest::SetUp",
+    "ListenerTest::* Test Body",
+    "1st.OnTestPartResult",
+    "2nd.OnTestPartResult",
+    "ListenerTest::TearDown",
+    "2nd.OnTestEnd",
+    "1st.OnTestEnd",
+    "1st.OnTestStart",
+    "2nd.OnTestStart",
+    "ListenerTest::SetUp",
+    "ListenerTest::* Test Body",
+    "1st.OnTestPartResult",
+    "2nd.OnTestPartResult",
+    "ListenerTest::TearDown",
+    "2nd.OnTestEnd",
+    "1st.OnTestEnd",
+    "ListenerTest::TearDownTestCase",
+    "2nd.OnTestCaseEnd",
+    "1st.OnTestCaseEnd",
+    "1st.OnEnvironmentsTearDownStart",
+    "2nd.OnEnvironmentsTearDownStart",
+    "Environment::TearDown",
+    "2nd.OnEnvironmentsTearDownEnd",
+    "1st.OnEnvironmentsTearDownEnd",
+    "2nd.OnTestIterationEnd(0)",
+    "1st.OnTestIterationEnd(0)",
+    "1st.OnTestIterationStart(1)",
+    "2nd.OnTestIterationStart(1)",
+    "1st.OnEnvironmentsSetUpStart",
+    "2nd.OnEnvironmentsSetUpStart",
+    "Environment::SetUp",
+    "2nd.OnEnvironmentsSetUpEnd",
+    "1st.OnEnvironmentsSetUpEnd",
+    "1st.OnTestCaseStart",
+    "2nd.OnTestCaseStart",
+    "ListenerTest::SetUpTestCase",
+    "1st.OnTestStart",
+    "2nd.OnTestStart",
+    "ListenerTest::SetUp",
+    "ListenerTest::* Test Body",
+    "1st.OnTestPartResult",
+    "2nd.OnTestPartResult",
+    "ListenerTest::TearDown",
+    "2nd.OnTestEnd",
+    "1st.OnTestEnd",
+    "1st.OnTestStart",
+    "2nd.OnTestStart",
+    "ListenerTest::SetUp",
+    "ListenerTest::* Test Body",
+    "1st.OnTestPartResult",
+    "2nd.OnTestPartResult",
+    "ListenerTest::TearDown",
+    "2nd.OnTestEnd",
+    "1st.OnTestEnd",
+    "ListenerTest::TearDownTestCase",
+    "2nd.OnTestCaseEnd",
+    "1st.OnTestCaseEnd",
+    "1st.OnEnvironmentsTearDownStart",
+    "2nd.OnEnvironmentsTearDownStart",
+    "Environment::TearDown",
+    "2nd.OnEnvironmentsTearDownEnd",
+    "1st.OnEnvironmentsTearDownEnd",
+    "2nd.OnTestIterationEnd(1)",
+    "1st.OnTestIterationEnd(1)",
+    "2nd.OnTestProgramEnd",
+    "1st.OnTestProgramEnd"
+  };
+  VerifyResults(events,
+                expected_events,
+                sizeof(expected_events)/sizeof(expected_events[0]));
+
+  // We need to check manually for ad hoc test failures that happen after
+  // RUN_ALL_TESTS finishes.
+  if (UnitTest::GetInstance()->Failed())
+    ret_val = 1;
+
+  return ret_val;
+}
diff --git a/third_party/googletest/googletest/test/gtest-message_test.cc b/third_party/googletest/googletest/test/gtest-message_test.cc
new file mode 100644
index 0000000..175238e
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest-message_test.cc
@@ -0,0 +1,159 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// Tests for the Message class.
+
+#include "gtest/gtest-message.h"
+
+#include "gtest/gtest.h"
+
+namespace {
+
+using ::testing::Message;
+
+// Tests the testing::Message class
+
+// Tests the default constructor.
+TEST(MessageTest, DefaultConstructor) {
+  const Message msg;
+  EXPECT_EQ("", msg.GetString());
+}
+
+// Tests the copy constructor.
+TEST(MessageTest, CopyConstructor) {
+  const Message msg1("Hello");
+  const Message msg2(msg1);
+  EXPECT_EQ("Hello", msg2.GetString());
+}
+
+// Tests constructing a Message from a C-string.
+TEST(MessageTest, ConstructsFromCString) {
+  Message msg("Hello");
+  EXPECT_EQ("Hello", msg.GetString());
+}
+
+// Tests streaming a float.
+TEST(MessageTest, StreamsFloat) {
+  const std::string s = (Message() << 1.23456F << " " << 2.34567F).GetString();
+  // Both numbers should be printed with enough precision.
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "1.234560", s.c_str());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, " 2.345669", s.c_str());
+}
+
+// Tests streaming a double.
+TEST(MessageTest, StreamsDouble) {
+  const std::string s = (Message() << 1260570880.4555497 << " "
+                                  << 1260572265.1954534).GetString();
+  // Both numbers should be printed with enough precision.
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "1260570880.45", s.c_str());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, " 1260572265.19", s.c_str());
+}
+
+// Tests streaming a non-char pointer.
+TEST(MessageTest, StreamsPointer) {
+  int n = 0;
+  int* p = &n;
+  EXPECT_NE("(null)", (Message() << p).GetString());
+}
+
+// Tests streaming a NULL non-char pointer.
+TEST(MessageTest, StreamsNullPointer) {
+  int* p = NULL;
+  EXPECT_EQ("(null)", (Message() << p).GetString());
+}
+
+// Tests streaming a C string.
+TEST(MessageTest, StreamsCString) {
+  EXPECT_EQ("Foo", (Message() << "Foo").GetString());
+}
+
+// Tests streaming a NULL C string.
+TEST(MessageTest, StreamsNullCString) {
+  char* p = NULL;
+  EXPECT_EQ("(null)", (Message() << p).GetString());
+}
+
+// Tests streaming std::string.
+TEST(MessageTest, StreamsString) {
+  const ::std::string str("Hello");
+  EXPECT_EQ("Hello", (Message() << str).GetString());
+}
+
+// Tests that we can output strings containing embedded NULs.
+TEST(MessageTest, StreamsStringWithEmbeddedNUL) {
+  const char char_array_with_nul[] =
+      "Here's a NUL\0 and some more string";
+  const ::std::string string_with_nul(char_array_with_nul,
+                                      sizeof(char_array_with_nul) - 1);
+  EXPECT_EQ("Here's a NUL\\0 and some more string",
+            (Message() << string_with_nul).GetString());
+}
+
+// Tests streaming a NUL char.
+TEST(MessageTest, StreamsNULChar) {
+  EXPECT_EQ("\\0", (Message() << '\0').GetString());
+}
+
+// Tests streaming int.
+TEST(MessageTest, StreamsInt) {
+  EXPECT_EQ("123", (Message() << 123).GetString());
+}
+
+// Tests that basic IO manipulators (endl, ends, and flush) can be
+// streamed to Message.
+TEST(MessageTest, StreamsBasicIoManip) {
+  EXPECT_EQ("Line 1.\nA NUL char \\0 in line 2.",
+               (Message() << "Line 1." << std::endl
+                         << "A NUL char " << std::ends << std::flush
+                         << " in line 2.").GetString());
+}
+
+// Tests Message::GetString()
+TEST(MessageTest, GetString) {
+  Message msg;
+  msg << 1 << " lamb";
+  EXPECT_EQ("1 lamb", msg.GetString());
+}
+
+// Tests streaming a Message object to an ostream.
+TEST(MessageTest, StreamsToOStream) {
+  Message msg("Hello");
+  ::std::stringstream ss;
+  ss << msg;
+  EXPECT_EQ("Hello", testing::internal::StringStreamToString(&ss));
+}
+
+// Tests that a Message object doesn't take up too much stack space.
+TEST(MessageTest, DoesNotTakeUpMuchStackSpace) {
+  EXPECT_LE(sizeof(Message), 16U);
+}
+
+}  // namespace
diff --git a/third_party/googletest/googletest/test/gtest-options_test.cc b/third_party/googletest/googletest/test/gtest-options_test.cc
new file mode 100644
index 0000000..5586dc3
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest-options_test.cc
@@ -0,0 +1,215 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: keith.ray@gmail.com (Keith Ray)
+//
+// Google Test UnitTestOptions tests
+//
+// This file tests classes and functions used internally by
+// Google Test.  They are subject to change without notice.
+//
+// This file is #included from gtest.cc, to avoid changing build or
+// make-files on Windows and other platforms. Do not #include this file
+// anywhere else!
+
+#include "gtest/gtest.h"
+
+#if GTEST_OS_WINDOWS_MOBILE
+# include <windows.h>
+#elif GTEST_OS_WINDOWS
+# include <direct.h>
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+namespace internal {
+namespace {
+
+// Turns the given relative path into an absolute path.
+FilePath GetAbsolutePathOf(const FilePath& relative_path) {
+  return FilePath::ConcatPaths(FilePath::GetCurrentDir(), relative_path);
+}
+
+// Testing UnitTestOptions::GetOutputFormat/GetOutputFile.
+
+TEST(XmlOutputTest, GetOutputFormatDefault) {
+  GTEST_FLAG(output) = "";
+  EXPECT_STREQ("", UnitTestOptions::GetOutputFormat().c_str());
+}
+
+TEST(XmlOutputTest, GetOutputFormat) {
+  GTEST_FLAG(output) = "xml:filename";
+  EXPECT_STREQ("xml", UnitTestOptions::GetOutputFormat().c_str());
+}
+
+TEST(XmlOutputTest, GetOutputFileDefault) {
+  GTEST_FLAG(output) = "";
+  EXPECT_EQ(GetAbsolutePathOf(FilePath("test_detail.xml")).string(),
+            UnitTestOptions::GetAbsolutePathToOutputFile());
+}
+
+TEST(XmlOutputTest, GetOutputFileSingleFile) {
+  GTEST_FLAG(output) = "xml:filename.abc";
+  EXPECT_EQ(GetAbsolutePathOf(FilePath("filename.abc")).string(),
+            UnitTestOptions::GetAbsolutePathToOutputFile());
+}
+
+TEST(XmlOutputTest, GetOutputFileFromDirectoryPath) {
+  GTEST_FLAG(output) = "xml:path" GTEST_PATH_SEP_;
+  const std::string expected_output_file =
+      GetAbsolutePathOf(
+          FilePath(std::string("path") + GTEST_PATH_SEP_ +
+                   GetCurrentExecutableName().string() + ".xml")).string();
+  const std::string& output_file =
+      UnitTestOptions::GetAbsolutePathToOutputFile();
+#if GTEST_OS_WINDOWS
+  EXPECT_STRCASEEQ(expected_output_file.c_str(), output_file.c_str());
+#else
+  EXPECT_EQ(expected_output_file, output_file.c_str());
+#endif
+}
+
+TEST(OutputFileHelpersTest, GetCurrentExecutableName) {
+  const std::string exe_str = GetCurrentExecutableName().string();
+#if GTEST_OS_WINDOWS
+  const bool success =
+      _strcmpi("gtest-options_test", exe_str.c_str()) == 0 ||
+      _strcmpi("gtest-options-ex_test", exe_str.c_str()) == 0 ||
+      _strcmpi("gtest_all_test", exe_str.c_str()) == 0 ||
+      _strcmpi("gtest_dll_test", exe_str.c_str()) == 0;
+#else
+  // TODO(wan@google.com): remove the hard-coded "lt-" prefix when
+  //   Chandler Carruth's libtool replacement is ready.
+  const bool success =
+      exe_str == "gtest-options_test" ||
+      exe_str == "gtest_all_test" ||
+      exe_str == "lt-gtest_all_test" ||
+      exe_str == "gtest_dll_test";
+#endif  // GTEST_OS_WINDOWS
+  if (!success)
+    FAIL() << "GetCurrentExecutableName() returns " << exe_str;
+}
+
+class XmlOutputChangeDirTest : public Test {
+ protected:
+  virtual void SetUp() {
+    original_working_dir_ = FilePath::GetCurrentDir();
+    posix::ChDir("..");
+    // This will make the test fail if run from the root directory.
+    EXPECT_NE(original_working_dir_.string(),
+              FilePath::GetCurrentDir().string());
+  }
+
+  virtual void TearDown() {
+    posix::ChDir(original_working_dir_.string().c_str());
+  }
+
+  FilePath original_working_dir_;
+};
+
+TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithDefault) {
+  GTEST_FLAG(output) = "";
+  EXPECT_EQ(FilePath::ConcatPaths(original_working_dir_,
+                                  FilePath("test_detail.xml")).string(),
+            UnitTestOptions::GetAbsolutePathToOutputFile());
+}
+
+TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithDefaultXML) {
+  GTEST_FLAG(output) = "xml";
+  EXPECT_EQ(FilePath::ConcatPaths(original_working_dir_,
+                                  FilePath("test_detail.xml")).string(),
+            UnitTestOptions::GetAbsolutePathToOutputFile());
+}
+
+TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithRelativeFile) {
+  GTEST_FLAG(output) = "xml:filename.abc";
+  EXPECT_EQ(FilePath::ConcatPaths(original_working_dir_,
+                                  FilePath("filename.abc")).string(),
+            UnitTestOptions::GetAbsolutePathToOutputFile());
+}
+
+TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithRelativePath) {
+  GTEST_FLAG(output) = "xml:path" GTEST_PATH_SEP_;
+  const std::string expected_output_file =
+      FilePath::ConcatPaths(
+          original_working_dir_,
+          FilePath(std::string("path") + GTEST_PATH_SEP_ +
+                   GetCurrentExecutableName().string() + ".xml")).string();
+  const std::string& output_file =
+      UnitTestOptions::GetAbsolutePathToOutputFile();
+#if GTEST_OS_WINDOWS
+  EXPECT_STRCASEEQ(expected_output_file.c_str(), output_file.c_str());
+#else
+  EXPECT_EQ(expected_output_file, output_file.c_str());
+#endif
+}
+
+TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithAbsoluteFile) {
+#if GTEST_OS_WINDOWS
+  GTEST_FLAG(output) = "xml:c:\\tmp\\filename.abc";
+  EXPECT_EQ(FilePath("c:\\tmp\\filename.abc").string(),
+            UnitTestOptions::GetAbsolutePathToOutputFile());
+#else
+  GTEST_FLAG(output) ="xml:/tmp/filename.abc";
+  EXPECT_EQ(FilePath("/tmp/filename.abc").string(),
+            UnitTestOptions::GetAbsolutePathToOutputFile());
+#endif
+}
+
+TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithAbsolutePath) {
+#if GTEST_OS_WINDOWS
+  const std::string path = "c:\\tmp\\";
+#else
+  const std::string path = "/tmp/";
+#endif
+
+  GTEST_FLAG(output) = "xml:" + path;
+  const std::string expected_output_file =
+      path + GetCurrentExecutableName().string() + ".xml";
+  const std::string& output_file =
+      UnitTestOptions::GetAbsolutePathToOutputFile();
+
+#if GTEST_OS_WINDOWS
+  EXPECT_STRCASEEQ(expected_output_file.c_str(), output_file.c_str());
+#else
+  EXPECT_EQ(expected_output_file, output_file.c_str());
+#endif
+}
+
+}  // namespace
+}  // namespace internal
+}  // namespace testing
diff --git a/third_party/googletest/googletest/test/gtest-param-test2_test.cc b/third_party/googletest/googletest/test/gtest-param-test2_test.cc
new file mode 100644
index 0000000..4a782fe
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest-param-test2_test.cc
@@ -0,0 +1,65 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vladl@google.com (Vlad Losev)
+//
+// Tests for Google Test itself.  This verifies that the basic constructs of
+// Google Test work.
+
+#include "gtest/gtest.h"
+
+#include "test/gtest-param-test_test.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+using ::testing::Values;
+using ::testing::internal::ParamGenerator;
+
+// Tests that generators defined in a different translation unit
+// are functional. The test using extern_gen is defined
+// in gtest-param-test_test.cc.
+ParamGenerator<int> extern_gen = Values(33);
+
+// Tests that a parameterized test case can be defined in one translation unit
+// and instantiated in another. The test is defined in gtest-param-test_test.cc
+// and ExternalInstantiationTest fixture class is defined in
+// gtest-param-test_test.h.
+INSTANTIATE_TEST_CASE_P(MultiplesOf33,
+                        ExternalInstantiationTest,
+                        Values(33, 66));
+
+// Tests that a parameterized test case can be instantiated
+// in multiple translation units. Another instantiation is defined
+// in gtest-param-test_test.cc and InstantiationInMultipleTranslaionUnitsTest
+// fixture is defined in gtest-param-test_test.h
+INSTANTIATE_TEST_CASE_P(Sequence2,
+                        InstantiationInMultipleTranslaionUnitsTest,
+                        Values(42*3, 42*4, 42*5));
+
+#endif  // GTEST_HAS_PARAM_TEST
diff --git a/third_party/googletest/googletest/test/gtest-param-test_test.cc b/third_party/googletest/googletest/test/gtest-param-test_test.cc
new file mode 100644
index 0000000..8b278bb
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest-param-test_test.cc
@@ -0,0 +1,1055 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vladl@google.com (Vlad Losev)
+//
+// Tests for Google Test itself. This file verifies that the parameter
+// generators objects produce correct parameter sequences and that
+// Google Test runtime instantiates correct tests from those sequences.
+
+#include "gtest/gtest.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+# include <algorithm>
+# include <iostream>
+# include <list>
+# include <sstream>
+# include <string>
+# include <vector>
+
+// To include gtest-internal-inl.h.
+# define GTEST_IMPLEMENTATION_ 1
+# include "src/gtest-internal-inl.h"  // for UnitTestOptions
+# undef GTEST_IMPLEMENTATION_
+
+# include "test/gtest-param-test_test.h"
+
+using ::std::vector;
+using ::std::sort;
+
+using ::testing::AddGlobalTestEnvironment;
+using ::testing::Bool;
+using ::testing::Message;
+using ::testing::Range;
+using ::testing::TestWithParam;
+using ::testing::Values;
+using ::testing::ValuesIn;
+
+# if GTEST_HAS_COMBINE
+using ::testing::Combine;
+using ::testing::get;
+using ::testing::make_tuple;
+using ::testing::tuple;
+# endif  // GTEST_HAS_COMBINE
+
+using ::testing::internal::ParamGenerator;
+using ::testing::internal::UnitTestOptions;
+
+// Prints a value to a string.
+//
+// TODO(wan@google.com): remove PrintValue() when we move matchers and
+// EXPECT_THAT() from Google Mock to Google Test.  At that time, we
+// can write EXPECT_THAT(x, Eq(y)) to compare two tuples x and y, as
+// EXPECT_THAT() and the matchers know how to print tuples.
+template <typename T>
+::std::string PrintValue(const T& value) {
+  ::std::stringstream stream;
+  stream << value;
+  return stream.str();
+}
+
+# if GTEST_HAS_COMBINE
+
+// These overloads allow printing tuples in our tests.  We cannot
+// define an operator<< for tuples, as that definition needs to be in
+// the std namespace in order to be picked up by Google Test via
+// Argument-Dependent Lookup, yet defining anything in the std
+// namespace in non-STL code is undefined behavior.
+
+template <typename T1, typename T2>
+::std::string PrintValue(const tuple<T1, T2>& value) {
+  ::std::stringstream stream;
+  stream << "(" << get<0>(value) << ", " << get<1>(value) << ")";
+  return stream.str();
+}
+
+template <typename T1, typename T2, typename T3>
+::std::string PrintValue(const tuple<T1, T2, T3>& value) {
+  ::std::stringstream stream;
+  stream << "(" << get<0>(value) << ", " << get<1>(value)
+         << ", "<< get<2>(value) << ")";
+  return stream.str();
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6, typename T7, typename T8, typename T9, typename T10>
+::std::string PrintValue(
+    const tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>& value) {
+  ::std::stringstream stream;
+  stream << "(" << get<0>(value) << ", " << get<1>(value)
+         << ", "<< get<2>(value) << ", " << get<3>(value)
+         << ", "<< get<4>(value) << ", " << get<5>(value)
+         << ", "<< get<6>(value) << ", " << get<7>(value)
+         << ", "<< get<8>(value) << ", " << get<9>(value) << ")";
+  return stream.str();
+}
+
+# endif  // GTEST_HAS_COMBINE
+
+// Verifies that a sequence generated by the generator and accessed
+// via the iterator object matches the expected one using Google Test
+// assertions.
+template <typename T, size_t N>
+void VerifyGenerator(const ParamGenerator<T>& generator,
+                     const T (&expected_values)[N]) {
+  typename ParamGenerator<T>::iterator it = generator.begin();
+  for (size_t i = 0; i < N; ++i) {
+    ASSERT_FALSE(it == generator.end())
+        << "At element " << i << " when accessing via an iterator "
+        << "created with the copy constructor.\n";
+    // We cannot use EXPECT_EQ() here as the values may be tuples,
+    // which don't support <<.
+    EXPECT_TRUE(expected_values[i] == *it)
+        << "where i is " << i
+        << ", expected_values[i] is " << PrintValue(expected_values[i])
+        << ", *it is " << PrintValue(*it)
+        << ", and 'it' is an iterator created with the copy constructor.\n";
+    it++;
+  }
+  EXPECT_TRUE(it == generator.end())
+        << "At the presumed end of sequence when accessing via an iterator "
+        << "created with the copy constructor.\n";
+
+  // Test the iterator assignment. The following lines verify that
+  // the sequence accessed via an iterator initialized via the
+  // assignment operator (as opposed to a copy constructor) matches
+  // just the same.
+  it = generator.begin();
+  for (size_t i = 0; i < N; ++i) {
+    ASSERT_FALSE(it == generator.end())
+        << "At element " << i << " when accessing via an iterator "
+        << "created with the assignment operator.\n";
+    EXPECT_TRUE(expected_values[i] == *it)
+        << "where i is " << i
+        << ", expected_values[i] is " << PrintValue(expected_values[i])
+        << ", *it is " << PrintValue(*it)
+        << ", and 'it' is an iterator created with the copy constructor.\n";
+    it++;
+  }
+  EXPECT_TRUE(it == generator.end())
+        << "At the presumed end of sequence when accessing via an iterator "
+        << "created with the assignment operator.\n";
+}
+
+template <typename T>
+void VerifyGeneratorIsEmpty(const ParamGenerator<T>& generator) {
+  typename ParamGenerator<T>::iterator it = generator.begin();
+  EXPECT_TRUE(it == generator.end());
+
+  it = generator.begin();
+  EXPECT_TRUE(it == generator.end());
+}
+
+// Generator tests. They test that each of the provided generator functions
+// generates an expected sequence of values. The general test pattern
+// instantiates a generator using one of the generator functions,
+// checks the sequence produced by the generator using its iterator API,
+// and then resets the iterator back to the beginning of the sequence
+// and checks the sequence again.
+
+// Tests that iterators produced by generator functions conform to the
+// ForwardIterator concept.
+TEST(IteratorTest, ParamIteratorConformsToForwardIteratorConcept) {
+  const ParamGenerator<int> gen = Range(0, 10);
+  ParamGenerator<int>::iterator it = gen.begin();
+
+  // Verifies that iterator initialization works as expected.
+  ParamGenerator<int>::iterator it2 = it;
+  EXPECT_TRUE(*it == *it2) << "Initialized iterators must point to the "
+                           << "element same as its source points to";
+
+  // Verifies that iterator assignment works as expected.
+  it++;
+  EXPECT_FALSE(*it == *it2);
+  it2 = it;
+  EXPECT_TRUE(*it == *it2) << "Assigned iterators must point to the "
+                           << "element same as its source points to";
+
+  // Verifies that prefix operator++() returns *this.
+  EXPECT_EQ(&it, &(++it)) << "Result of the prefix operator++ must be "
+                          << "refer to the original object";
+
+  // Verifies that the result of the postfix operator++ points to the value
+  // pointed to by the original iterator.
+  int original_value = *it;  // Have to compute it outside of macro call to be
+                             // unaffected by the parameter evaluation order.
+  EXPECT_EQ(original_value, *(it++));
+
+  // Verifies that prefix and postfix operator++() advance an iterator
+  // all the same.
+  it2 = it;
+  it++;
+  ++it2;
+  EXPECT_TRUE(*it == *it2);
+}
+
+// Tests that Range() generates the expected sequence.
+TEST(RangeTest, IntRangeWithDefaultStep) {
+  const ParamGenerator<int> gen = Range(0, 3);
+  const int expected_values[] = {0, 1, 2};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Edge case. Tests that Range() generates the single element sequence
+// as expected when provided with range limits that are equal.
+TEST(RangeTest, IntRangeSingleValue) {
+  const ParamGenerator<int> gen = Range(0, 1);
+  const int expected_values[] = {0};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Edge case. Tests that Range() with generates empty sequence when
+// supplied with an empty range.
+TEST(RangeTest, IntRangeEmpty) {
+  const ParamGenerator<int> gen = Range(0, 0);
+  VerifyGeneratorIsEmpty(gen);
+}
+
+// Tests that Range() with custom step (greater then one) generates
+// the expected sequence.
+TEST(RangeTest, IntRangeWithCustomStep) {
+  const ParamGenerator<int> gen = Range(0, 9, 3);
+  const int expected_values[] = {0, 3, 6};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Tests that Range() with custom step (greater then one) generates
+// the expected sequence when the last element does not fall on the
+// upper range limit. Sequences generated by Range() must not have
+// elements beyond the range limits.
+TEST(RangeTest, IntRangeWithCustomStepOverUpperBound) {
+  const ParamGenerator<int> gen = Range(0, 4, 3);
+  const int expected_values[] = {0, 3};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Verifies that Range works with user-defined types that define
+// copy constructor, operator=(), operator+(), and operator<().
+class DogAdder {
+ public:
+  explicit DogAdder(const char* a_value) : value_(a_value) {}
+  DogAdder(const DogAdder& other) : value_(other.value_.c_str()) {}
+
+  DogAdder operator=(const DogAdder& other) {
+    if (this != &other)
+      value_ = other.value_;
+    return *this;
+  }
+  DogAdder operator+(const DogAdder& other) const {
+    Message msg;
+    msg << value_.c_str() << other.value_.c_str();
+    return DogAdder(msg.GetString().c_str());
+  }
+  bool operator<(const DogAdder& other) const {
+    return value_ < other.value_;
+  }
+  const std::string& value() const { return value_; }
+
+ private:
+  std::string value_;
+};
+
+TEST(RangeTest, WorksWithACustomType) {
+  const ParamGenerator<DogAdder> gen =
+      Range(DogAdder("cat"), DogAdder("catdogdog"), DogAdder("dog"));
+  ParamGenerator<DogAdder>::iterator it = gen.begin();
+
+  ASSERT_FALSE(it == gen.end());
+  EXPECT_STREQ("cat", it->value().c_str());
+
+  ASSERT_FALSE(++it == gen.end());
+  EXPECT_STREQ("catdog", it->value().c_str());
+
+  EXPECT_TRUE(++it == gen.end());
+}
+
+class IntWrapper {
+ public:
+  explicit IntWrapper(int a_value) : value_(a_value) {}
+  IntWrapper(const IntWrapper& other) : value_(other.value_) {}
+
+  IntWrapper operator=(const IntWrapper& other) {
+    value_ = other.value_;
+    return *this;
+  }
+  // operator+() adds a different type.
+  IntWrapper operator+(int other) const { return IntWrapper(value_ + other); }
+  bool operator<(const IntWrapper& other) const {
+    return value_ < other.value_;
+  }
+  int value() const { return value_; }
+
+ private:
+  int value_;
+};
+
+TEST(RangeTest, WorksWithACustomTypeWithDifferentIncrementType) {
+  const ParamGenerator<IntWrapper> gen = Range(IntWrapper(0), IntWrapper(2));
+  ParamGenerator<IntWrapper>::iterator it = gen.begin();
+
+  ASSERT_FALSE(it == gen.end());
+  EXPECT_EQ(0, it->value());
+
+  ASSERT_FALSE(++it == gen.end());
+  EXPECT_EQ(1, it->value());
+
+  EXPECT_TRUE(++it == gen.end());
+}
+
+// Tests that ValuesIn() with an array parameter generates
+// the expected sequence.
+TEST(ValuesInTest, ValuesInArray) {
+  int array[] = {3, 5, 8};
+  const ParamGenerator<int> gen = ValuesIn(array);
+  VerifyGenerator(gen, array);
+}
+
+// Tests that ValuesIn() with a const array parameter generates
+// the expected sequence.
+TEST(ValuesInTest, ValuesInConstArray) {
+  const int array[] = {3, 5, 8};
+  const ParamGenerator<int> gen = ValuesIn(array);
+  VerifyGenerator(gen, array);
+}
+
+// Edge case. Tests that ValuesIn() with an array parameter containing a
+// single element generates the single element sequence.
+TEST(ValuesInTest, ValuesInSingleElementArray) {
+  int array[] = {42};
+  const ParamGenerator<int> gen = ValuesIn(array);
+  VerifyGenerator(gen, array);
+}
+
+// Tests that ValuesIn() generates the expected sequence for an STL
+// container (vector).
+TEST(ValuesInTest, ValuesInVector) {
+  typedef ::std::vector<int> ContainerType;
+  ContainerType values;
+  values.push_back(3);
+  values.push_back(5);
+  values.push_back(8);
+  const ParamGenerator<int> gen = ValuesIn(values);
+
+  const int expected_values[] = {3, 5, 8};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Tests that ValuesIn() generates the expected sequence.
+TEST(ValuesInTest, ValuesInIteratorRange) {
+  typedef ::std::vector<int> ContainerType;
+  ContainerType values;
+  values.push_back(3);
+  values.push_back(5);
+  values.push_back(8);
+  const ParamGenerator<int> gen = ValuesIn(values.begin(), values.end());
+
+  const int expected_values[] = {3, 5, 8};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Edge case. Tests that ValuesIn() provided with an iterator range specifying a
+// single value generates a single-element sequence.
+TEST(ValuesInTest, ValuesInSingleElementIteratorRange) {
+  typedef ::std::vector<int> ContainerType;
+  ContainerType values;
+  values.push_back(42);
+  const ParamGenerator<int> gen = ValuesIn(values.begin(), values.end());
+
+  const int expected_values[] = {42};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Edge case. Tests that ValuesIn() provided with an empty iterator range
+// generates an empty sequence.
+TEST(ValuesInTest, ValuesInEmptyIteratorRange) {
+  typedef ::std::vector<int> ContainerType;
+  ContainerType values;
+  const ParamGenerator<int> gen = ValuesIn(values.begin(), values.end());
+
+  VerifyGeneratorIsEmpty(gen);
+}
+
+// Tests that the Values() generates the expected sequence.
+TEST(ValuesTest, ValuesWorks) {
+  const ParamGenerator<int> gen = Values(3, 5, 8);
+
+  const int expected_values[] = {3, 5, 8};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Tests that Values() generates the expected sequences from elements of
+// different types convertible to ParamGenerator's parameter type.
+TEST(ValuesTest, ValuesWorksForValuesOfCompatibleTypes) {
+  const ParamGenerator<double> gen = Values(3, 5.0f, 8.0);
+
+  const double expected_values[] = {3.0, 5.0, 8.0};
+  VerifyGenerator(gen, expected_values);
+}
+
+TEST(ValuesTest, ValuesWorksForMaxLengthList) {
+  const ParamGenerator<int> gen = Values(
+      10, 20, 30, 40, 50, 60, 70, 80, 90, 100,
+      110, 120, 130, 140, 150, 160, 170, 180, 190, 200,
+      210, 220, 230, 240, 250, 260, 270, 280, 290, 300,
+      310, 320, 330, 340, 350, 360, 370, 380, 390, 400,
+      410, 420, 430, 440, 450, 460, 470, 480, 490, 500);
+
+  const int expected_values[] = {
+      10, 20, 30, 40, 50, 60, 70, 80, 90, 100,
+      110, 120, 130, 140, 150, 160, 170, 180, 190, 200,
+      210, 220, 230, 240, 250, 260, 270, 280, 290, 300,
+      310, 320, 330, 340, 350, 360, 370, 380, 390, 400,
+      410, 420, 430, 440, 450, 460, 470, 480, 490, 500};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Edge case test. Tests that single-parameter Values() generates the sequence
+// with the single value.
+TEST(ValuesTest, ValuesWithSingleParameter) {
+  const ParamGenerator<int> gen = Values(42);
+
+  const int expected_values[] = {42};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Tests that Bool() generates sequence (false, true).
+TEST(BoolTest, BoolWorks) {
+  const ParamGenerator<bool> gen = Bool();
+
+  const bool expected_values[] = {false, true};
+  VerifyGenerator(gen, expected_values);
+}
+
+# if GTEST_HAS_COMBINE
+
+// Tests that Combine() with two parameters generates the expected sequence.
+TEST(CombineTest, CombineWithTwoParameters) {
+  const char* foo = "foo";
+  const char* bar = "bar";
+  const ParamGenerator<tuple<const char*, int> > gen =
+      Combine(Values(foo, bar), Values(3, 4));
+
+  tuple<const char*, int> expected_values[] = {
+    make_tuple(foo, 3), make_tuple(foo, 4),
+    make_tuple(bar, 3), make_tuple(bar, 4)};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Tests that Combine() with three parameters generates the expected sequence.
+TEST(CombineTest, CombineWithThreeParameters) {
+  const ParamGenerator<tuple<int, int, int> > gen = Combine(Values(0, 1),
+                                                            Values(3, 4),
+                                                            Values(5, 6));
+  tuple<int, int, int> expected_values[] = {
+    make_tuple(0, 3, 5), make_tuple(0, 3, 6),
+    make_tuple(0, 4, 5), make_tuple(0, 4, 6),
+    make_tuple(1, 3, 5), make_tuple(1, 3, 6),
+    make_tuple(1, 4, 5), make_tuple(1, 4, 6)};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Tests that the Combine() with the first parameter generating a single value
+// sequence generates a sequence with the number of elements equal to the
+// number of elements in the sequence generated by the second parameter.
+TEST(CombineTest, CombineWithFirstParameterSingleValue) {
+  const ParamGenerator<tuple<int, int> > gen = Combine(Values(42),
+                                                       Values(0, 1));
+
+  tuple<int, int> expected_values[] = {make_tuple(42, 0), make_tuple(42, 1)};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Tests that the Combine() with the second parameter generating a single value
+// sequence generates a sequence with the number of elements equal to the
+// number of elements in the sequence generated by the first parameter.
+TEST(CombineTest, CombineWithSecondParameterSingleValue) {
+  const ParamGenerator<tuple<int, int> > gen = Combine(Values(0, 1),
+                                                       Values(42));
+
+  tuple<int, int> expected_values[] = {make_tuple(0, 42), make_tuple(1, 42)};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Tests that when the first parameter produces an empty sequence,
+// Combine() produces an empty sequence, too.
+TEST(CombineTest, CombineWithFirstParameterEmptyRange) {
+  const ParamGenerator<tuple<int, int> > gen = Combine(Range(0, 0),
+                                                       Values(0, 1));
+  VerifyGeneratorIsEmpty(gen);
+}
+
+// Tests that when the second parameter produces an empty sequence,
+// Combine() produces an empty sequence, too.
+TEST(CombineTest, CombineWithSecondParameterEmptyRange) {
+  const ParamGenerator<tuple<int, int> > gen = Combine(Values(0, 1),
+                                                       Range(1, 1));
+  VerifyGeneratorIsEmpty(gen);
+}
+
+// Edge case. Tests that combine works with the maximum number
+// of parameters supported by Google Test (currently 10).
+TEST(CombineTest, CombineWithMaxNumberOfParameters) {
+  const char* foo = "foo";
+  const char* bar = "bar";
+  const ParamGenerator<tuple<const char*, int, int, int, int, int, int, int,
+                             int, int> > gen = Combine(Values(foo, bar),
+                                                       Values(1), Values(2),
+                                                       Values(3), Values(4),
+                                                       Values(5), Values(6),
+                                                       Values(7), Values(8),
+                                                       Values(9));
+
+  tuple<const char*, int, int, int, int, int, int, int, int, int>
+      expected_values[] = {make_tuple(foo, 1, 2, 3, 4, 5, 6, 7, 8, 9),
+                           make_tuple(bar, 1, 2, 3, 4, 5, 6, 7, 8, 9)};
+  VerifyGenerator(gen, expected_values);
+}
+
+# endif  // GTEST_HAS_COMBINE
+
+// Tests that an generator produces correct sequence after being
+// assigned from another generator.
+TEST(ParamGeneratorTest, AssignmentWorks) {
+  ParamGenerator<int> gen = Values(1, 2);
+  const ParamGenerator<int> gen2 = Values(3, 4);
+  gen = gen2;
+
+  const int expected_values[] = {3, 4};
+  VerifyGenerator(gen, expected_values);
+}
+
+// This test verifies that the tests are expanded and run as specified:
+// one test per element from the sequence produced by the generator
+// specified in INSTANTIATE_TEST_CASE_P. It also verifies that the test's
+// fixture constructor, SetUp(), and TearDown() have run and have been
+// supplied with the correct parameters.
+
+// The use of environment object allows detection of the case where no test
+// case functionality is run at all. In this case TestCaseTearDown will not
+// be able to detect missing tests, naturally.
+template <int kExpectedCalls>
+class TestGenerationEnvironment : public ::testing::Environment {
+ public:
+  static TestGenerationEnvironment* Instance() {
+    static TestGenerationEnvironment* instance = new TestGenerationEnvironment;
+    return instance;
+  }
+
+  void FixtureConstructorExecuted() { fixture_constructor_count_++; }
+  void SetUpExecuted() { set_up_count_++; }
+  void TearDownExecuted() { tear_down_count_++; }
+  void TestBodyExecuted() { test_body_count_++; }
+
+  virtual void TearDown() {
+    // If all MultipleTestGenerationTest tests have been de-selected
+    // by the filter flag, the following checks make no sense.
+    bool perform_check = false;
+
+    for (int i = 0; i < kExpectedCalls; ++i) {
+      Message msg;
+      msg << "TestsExpandedAndRun/" << i;
+      if (UnitTestOptions::FilterMatchesTest(
+             "TestExpansionModule/MultipleTestGenerationTest",
+              msg.GetString().c_str())) {
+        perform_check = true;
+      }
+    }
+    if (perform_check) {
+      EXPECT_EQ(kExpectedCalls, fixture_constructor_count_)
+          << "Fixture constructor of ParamTestGenerationTest test case "
+          << "has not been run as expected.";
+      EXPECT_EQ(kExpectedCalls, set_up_count_)
+          << "Fixture SetUp method of ParamTestGenerationTest test case "
+          << "has not been run as expected.";
+      EXPECT_EQ(kExpectedCalls, tear_down_count_)
+          << "Fixture TearDown method of ParamTestGenerationTest test case "
+          << "has not been run as expected.";
+      EXPECT_EQ(kExpectedCalls, test_body_count_)
+          << "Test in ParamTestGenerationTest test case "
+          << "has not been run as expected.";
+    }
+  }
+
+ private:
+  TestGenerationEnvironment() : fixture_constructor_count_(0), set_up_count_(0),
+                                tear_down_count_(0), test_body_count_(0) {}
+
+  int fixture_constructor_count_;
+  int set_up_count_;
+  int tear_down_count_;
+  int test_body_count_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestGenerationEnvironment);
+};
+
+const int test_generation_params[] = {36, 42, 72};
+
+class TestGenerationTest : public TestWithParam<int> {
+ public:
+  enum {
+    PARAMETER_COUNT =
+        sizeof(test_generation_params)/sizeof(test_generation_params[0])
+  };
+
+  typedef TestGenerationEnvironment<PARAMETER_COUNT> Environment;
+
+  TestGenerationTest() {
+    Environment::Instance()->FixtureConstructorExecuted();
+    current_parameter_ = GetParam();
+  }
+  virtual void SetUp() {
+    Environment::Instance()->SetUpExecuted();
+    EXPECT_EQ(current_parameter_, GetParam());
+  }
+  virtual void TearDown() {
+    Environment::Instance()->TearDownExecuted();
+    EXPECT_EQ(current_parameter_, GetParam());
+  }
+
+  static void SetUpTestCase() {
+    bool all_tests_in_test_case_selected = true;
+
+    for (int i = 0; i < PARAMETER_COUNT; ++i) {
+      Message test_name;
+      test_name << "TestsExpandedAndRun/" << i;
+      if ( !UnitTestOptions::FilterMatchesTest(
+                "TestExpansionModule/MultipleTestGenerationTest",
+                test_name.GetString())) {
+        all_tests_in_test_case_selected = false;
+      }
+    }
+    EXPECT_TRUE(all_tests_in_test_case_selected)
+        << "When running the TestGenerationTest test case all of its tests\n"
+        << "must be selected by the filter flag for the test case to pass.\n"
+        << "If not all of them are enabled, we can't reliably conclude\n"
+        << "that the correct number of tests have been generated.";
+
+    collected_parameters_.clear();
+  }
+
+  static void TearDownTestCase() {
+    vector<int> expected_values(test_generation_params,
+                                test_generation_params + PARAMETER_COUNT);
+    // Test execution order is not guaranteed by Google Test,
+    // so the order of values in collected_parameters_ can be
+    // different and we have to sort to compare.
+    sort(expected_values.begin(), expected_values.end());
+    sort(collected_parameters_.begin(), collected_parameters_.end());
+
+    EXPECT_TRUE(collected_parameters_ == expected_values);
+  }
+
+ protected:
+  int current_parameter_;
+  static vector<int> collected_parameters_;
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestGenerationTest);
+};
+vector<int> TestGenerationTest::collected_parameters_;
+
+TEST_P(TestGenerationTest, TestsExpandedAndRun) {
+  Environment::Instance()->TestBodyExecuted();
+  EXPECT_EQ(current_parameter_, GetParam());
+  collected_parameters_.push_back(GetParam());
+}
+INSTANTIATE_TEST_CASE_P(TestExpansionModule, TestGenerationTest,
+                        ValuesIn(test_generation_params));
+
+// This test verifies that the element sequence (third parameter of
+// INSTANTIATE_TEST_CASE_P) is evaluated in InitGoogleTest() and neither at
+// the call site of INSTANTIATE_TEST_CASE_P nor in RUN_ALL_TESTS().  For
+// that, we declare param_value_ to be a static member of
+// GeneratorEvaluationTest and initialize it to 0.  We set it to 1 in
+// main(), just before invocation of InitGoogleTest().  After calling
+// InitGoogleTest(), we set the value to 2.  If the sequence is evaluated
+// before or after InitGoogleTest, INSTANTIATE_TEST_CASE_P will create a
+// test with parameter other than 1, and the test body will fail the
+// assertion.
+class GeneratorEvaluationTest : public TestWithParam<int> {
+ public:
+  static int param_value() { return param_value_; }
+  static void set_param_value(int param_value) { param_value_ = param_value; }
+
+ private:
+  static int param_value_;
+};
+int GeneratorEvaluationTest::param_value_ = 0;
+
+TEST_P(GeneratorEvaluationTest, GeneratorsEvaluatedInMain) {
+  EXPECT_EQ(1, GetParam());
+}
+INSTANTIATE_TEST_CASE_P(GenEvalModule,
+                        GeneratorEvaluationTest,
+                        Values(GeneratorEvaluationTest::param_value()));
+
+// Tests that generators defined in a different translation unit are
+// functional. Generator extern_gen is defined in gtest-param-test_test2.cc.
+extern ParamGenerator<int> extern_gen;
+class ExternalGeneratorTest : public TestWithParam<int> {};
+TEST_P(ExternalGeneratorTest, ExternalGenerator) {
+  // Sequence produced by extern_gen contains only a single value
+  // which we verify here.
+  EXPECT_EQ(GetParam(), 33);
+}
+INSTANTIATE_TEST_CASE_P(ExternalGeneratorModule,
+                        ExternalGeneratorTest,
+                        extern_gen);
+
+// Tests that a parameterized test case can be defined in one translation
+// unit and instantiated in another. This test will be instantiated in
+// gtest-param-test_test2.cc. ExternalInstantiationTest fixture class is
+// defined in gtest-param-test_test.h.
+TEST_P(ExternalInstantiationTest, IsMultipleOf33) {
+  EXPECT_EQ(0, GetParam() % 33);
+}
+
+// Tests that a parameterized test case can be instantiated with multiple
+// generators.
+class MultipleInstantiationTest : public TestWithParam<int> {};
+TEST_P(MultipleInstantiationTest, AllowsMultipleInstances) {
+}
+INSTANTIATE_TEST_CASE_P(Sequence1, MultipleInstantiationTest, Values(1, 2));
+INSTANTIATE_TEST_CASE_P(Sequence2, MultipleInstantiationTest, Range(3, 5));
+
+// Tests that a parameterized test case can be instantiated
+// in multiple translation units. This test will be instantiated
+// here and in gtest-param-test_test2.cc.
+// InstantiationInMultipleTranslationUnitsTest fixture class
+// is defined in gtest-param-test_test.h.
+TEST_P(InstantiationInMultipleTranslaionUnitsTest, IsMultipleOf42) {
+  EXPECT_EQ(0, GetParam() % 42);
+}
+INSTANTIATE_TEST_CASE_P(Sequence1,
+                        InstantiationInMultipleTranslaionUnitsTest,
+                        Values(42, 42*2));
+
+// Tests that each iteration of parameterized test runs in a separate test
+// object.
+class SeparateInstanceTest : public TestWithParam<int> {
+ public:
+  SeparateInstanceTest() : count_(0) {}
+
+  static void TearDownTestCase() {
+    EXPECT_GE(global_count_, 2)
+        << "If some (but not all) SeparateInstanceTest tests have been "
+        << "filtered out this test will fail. Make sure that all "
+        << "GeneratorEvaluationTest are selected or de-selected together "
+        << "by the test filter.";
+  }
+
+ protected:
+  int count_;
+  static int global_count_;
+};
+int SeparateInstanceTest::global_count_ = 0;
+
+TEST_P(SeparateInstanceTest, TestsRunInSeparateInstances) {
+  EXPECT_EQ(0, count_++);
+  global_count_++;
+}
+INSTANTIATE_TEST_CASE_P(FourElemSequence, SeparateInstanceTest, Range(1, 4));
+
+// Tests that all instantiations of a test have named appropriately. Test
+// defined with TEST_P(TestCaseName, TestName) and instantiated with
+// INSTANTIATE_TEST_CASE_P(SequenceName, TestCaseName, generator) must be named
+// SequenceName/TestCaseName.TestName/i, where i is the 0-based index of the
+// sequence element used to instantiate the test.
+class NamingTest : public TestWithParam<int> {};
+
+TEST_P(NamingTest, TestsReportCorrectNamesAndParameters) {
+  const ::testing::TestInfo* const test_info =
+     ::testing::UnitTest::GetInstance()->current_test_info();
+
+  EXPECT_STREQ("ZeroToFiveSequence/NamingTest", test_info->test_case_name());
+
+  Message index_stream;
+  index_stream << "TestsReportCorrectNamesAndParameters/" << GetParam();
+  EXPECT_STREQ(index_stream.GetString().c_str(), test_info->name());
+
+  EXPECT_EQ(::testing::PrintToString(GetParam()), test_info->value_param());
+}
+
+INSTANTIATE_TEST_CASE_P(ZeroToFiveSequence, NamingTest, Range(0, 5));
+
+// Tests that user supplied custom parameter names are working correctly.
+// Runs the test with a builtin helper method which uses PrintToString,
+// as well as a custom function and custom functor to ensure all possible
+// uses work correctly.
+class CustomFunctorNamingTest : public TestWithParam<std::string> {};
+TEST_P(CustomFunctorNamingTest, CustomTestNames) {}
+
+struct CustomParamNameFunctor {
+  std::string operator()(const ::testing::TestParamInfo<std::string>& info) {
+    return info.param;
+  }
+};
+
+INSTANTIATE_TEST_CASE_P(CustomParamNameFunctor,
+                        CustomFunctorNamingTest,
+                        Values(std::string("FunctorName")),
+                        CustomParamNameFunctor());
+
+INSTANTIATE_TEST_CASE_P(AllAllowedCharacters,
+                        CustomFunctorNamingTest,
+                        Values("abcdefghijklmnopqrstuvwxyz",
+                               "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
+                               "01234567890_"),
+                        CustomParamNameFunctor());
+
+inline std::string CustomParamNameFunction(
+    const ::testing::TestParamInfo<std::string>& info) {
+  return info.param;
+}
+
+class CustomFunctionNamingTest : public TestWithParam<std::string> {};
+TEST_P(CustomFunctionNamingTest, CustomTestNames) {}
+
+INSTANTIATE_TEST_CASE_P(CustomParamNameFunction,
+                        CustomFunctionNamingTest,
+                        Values(std::string("FunctionName")),
+                        CustomParamNameFunction);
+
+#if GTEST_LANG_CXX11
+
+// Test custom naming with a lambda
+
+class CustomLambdaNamingTest : public TestWithParam<std::string> {};
+TEST_P(CustomLambdaNamingTest, CustomTestNames) {}
+
+INSTANTIATE_TEST_CASE_P(CustomParamNameLambda,
+                        CustomLambdaNamingTest,
+                        Values(std::string("LambdaName")),
+                        [](const ::testing::TestParamInfo<std::string>& info) {
+                          return info.param;
+                        });
+
+#endif  // GTEST_LANG_CXX11
+
+TEST(CustomNamingTest, CheckNameRegistry) {
+  ::testing::UnitTest* unit_test = ::testing::UnitTest::GetInstance();
+  std::set<std::string> test_names;
+  for (int case_num = 0;
+       case_num < unit_test->total_test_case_count();
+       ++case_num) {
+    const ::testing::TestCase* test_case = unit_test->GetTestCase(case_num);
+    for (int test_num = 0;
+         test_num < test_case->total_test_count();
+         ++test_num) {
+      const ::testing::TestInfo* test_info = test_case->GetTestInfo(test_num);
+      test_names.insert(std::string(test_info->name()));
+    }
+  }
+  EXPECT_EQ(1u, test_names.count("CustomTestNames/FunctorName"));
+  EXPECT_EQ(1u, test_names.count("CustomTestNames/FunctionName"));
+#if GTEST_LANG_CXX11
+  EXPECT_EQ(1u, test_names.count("CustomTestNames/LambdaName"));
+#endif  // GTEST_LANG_CXX11
+}
+
+// Test a numeric name to ensure PrintToStringParamName works correctly.
+
+class CustomIntegerNamingTest : public TestWithParam<int> {};
+
+TEST_P(CustomIntegerNamingTest, TestsReportCorrectNames) {
+  const ::testing::TestInfo* const test_info =
+     ::testing::UnitTest::GetInstance()->current_test_info();
+  Message test_name_stream;
+  test_name_stream << "TestsReportCorrectNames/" << GetParam();
+  EXPECT_STREQ(test_name_stream.GetString().c_str(), test_info->name());
+}
+
+INSTANTIATE_TEST_CASE_P(PrintToString,
+                        CustomIntegerNamingTest,
+                        Range(0, 5),
+                        ::testing::PrintToStringParamName());
+
+// Test a custom struct with PrintToString.
+
+struct CustomStruct {
+  explicit CustomStruct(int value) : x(value) {}
+  int x;
+};
+
+std::ostream& operator<<(std::ostream& stream, const CustomStruct& val) {
+  stream << val.x;
+  return stream;
+}
+
+class CustomStructNamingTest : public TestWithParam<CustomStruct> {};
+
+TEST_P(CustomStructNamingTest, TestsReportCorrectNames) {
+  const ::testing::TestInfo* const test_info =
+     ::testing::UnitTest::GetInstance()->current_test_info();
+  Message test_name_stream;
+  test_name_stream << "TestsReportCorrectNames/" << GetParam();
+  EXPECT_STREQ(test_name_stream.GetString().c_str(), test_info->name());
+}
+
+INSTANTIATE_TEST_CASE_P(PrintToString,
+                        CustomStructNamingTest,
+                        Values(CustomStruct(0), CustomStruct(1)),
+                        ::testing::PrintToStringParamName());
+
+// Test that using a stateful parameter naming function works as expected.
+
+struct StatefulNamingFunctor {
+  StatefulNamingFunctor() : sum(0) {}
+  std::string operator()(const ::testing::TestParamInfo<int>& info) {
+    int value = info.param + sum;
+    sum += info.param;
+    return ::testing::PrintToString(value);
+  }
+  int sum;
+};
+
+class StatefulNamingTest : public ::testing::TestWithParam<int> {
+ protected:
+  StatefulNamingTest() : sum_(0) {}
+  int sum_;
+};
+
+TEST_P(StatefulNamingTest, TestsReportCorrectNames) {
+  const ::testing::TestInfo* const test_info =
+     ::testing::UnitTest::GetInstance()->current_test_info();
+  sum_ += GetParam();
+  Message test_name_stream;
+  test_name_stream << "TestsReportCorrectNames/" << sum_;
+  EXPECT_STREQ(test_name_stream.GetString().c_str(), test_info->name());
+}
+
+INSTANTIATE_TEST_CASE_P(StatefulNamingFunctor,
+                        StatefulNamingTest,
+                        Range(0, 5),
+                        StatefulNamingFunctor());
+
+// Class that cannot be streamed into an ostream.  It needs to be copyable
+// (and, in case of MSVC, also assignable) in order to be a test parameter
+// type.  Its default copy constructor and assignment operator do exactly
+// what we need.
+class Unstreamable {
+ public:
+  explicit Unstreamable(int value) : value_(value) {}
+
+ private:
+  int value_;
+};
+
+class CommentTest : public TestWithParam<Unstreamable> {};
+
+TEST_P(CommentTest, TestsCorrectlyReportUnstreamableParams) {
+  const ::testing::TestInfo* const test_info =
+     ::testing::UnitTest::GetInstance()->current_test_info();
+
+  EXPECT_EQ(::testing::PrintToString(GetParam()), test_info->value_param());
+}
+
+INSTANTIATE_TEST_CASE_P(InstantiationWithComments,
+                        CommentTest,
+                        Values(Unstreamable(1)));
+
+// Verify that we can create a hierarchy of test fixtures, where the base
+// class fixture is not parameterized and the derived class is. In this case
+// ParameterizedDerivedTest inherits from NonParameterizedBaseTest.  We
+// perform simple tests on both.
+class NonParameterizedBaseTest : public ::testing::Test {
+ public:
+  NonParameterizedBaseTest() : n_(17) { }
+ protected:
+  int n_;
+};
+
+class ParameterizedDerivedTest : public NonParameterizedBaseTest,
+                                 public ::testing::WithParamInterface<int> {
+ protected:
+  ParameterizedDerivedTest() : count_(0) { }
+  int count_;
+  static int global_count_;
+};
+
+int ParameterizedDerivedTest::global_count_ = 0;
+
+TEST_F(NonParameterizedBaseTest, FixtureIsInitialized) {
+  EXPECT_EQ(17, n_);
+}
+
+TEST_P(ParameterizedDerivedTest, SeesSequence) {
+  EXPECT_EQ(17, n_);
+  EXPECT_EQ(0, count_++);
+  EXPECT_EQ(GetParam(), global_count_++);
+}
+
+class ParameterizedDeathTest : public ::testing::TestWithParam<int> { };
+
+TEST_F(ParameterizedDeathTest, GetParamDiesFromTestF) {
+  EXPECT_DEATH_IF_SUPPORTED(GetParam(),
+                            ".* value-parameterized test .*");
+}
+
+INSTANTIATE_TEST_CASE_P(RangeZeroToFive, ParameterizedDerivedTest, Range(0, 5));
+
+#endif  // GTEST_HAS_PARAM_TEST
+
+TEST(CompileTest, CombineIsDefinedOnlyWhenGtestHasParamTestIsDefined) {
+#if GTEST_HAS_COMBINE && !GTEST_HAS_PARAM_TEST
+  FAIL() << "GTEST_HAS_COMBINE is defined while GTEST_HAS_PARAM_TEST is not\n"
+#endif
+}
+
+int main(int argc, char **argv) {
+#if GTEST_HAS_PARAM_TEST
+  // Used in TestGenerationTest test case.
+  AddGlobalTestEnvironment(TestGenerationTest::Environment::Instance());
+  // Used in GeneratorEvaluationTest test case. Tests that the updated value
+  // will be picked up for instantiating tests in GeneratorEvaluationTest.
+  GeneratorEvaluationTest::set_param_value(1);
+#endif  // GTEST_HAS_PARAM_TEST
+
+  ::testing::InitGoogleTest(&argc, argv);
+
+#if GTEST_HAS_PARAM_TEST
+  // Used in GeneratorEvaluationTest test case. Tests that value updated
+  // here will NOT be used for instantiating tests in
+  // GeneratorEvaluationTest.
+  GeneratorEvaluationTest::set_param_value(2);
+#endif  // GTEST_HAS_PARAM_TEST
+
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/googletest/googletest/test/gtest-param-test_test.h b/third_party/googletest/googletest/test/gtest-param-test_test.h
new file mode 100644
index 0000000..26ea122
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest-param-test_test.h
@@ -0,0 +1,57 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: vladl@google.com (Vlad Losev)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file provides classes and functions used internally
+// for testing Google Test itself.
+
+#ifndef GTEST_TEST_GTEST_PARAM_TEST_TEST_H_
+#define GTEST_TEST_GTEST_PARAM_TEST_TEST_H_
+
+#include "gtest/gtest.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+// Test fixture for testing definition and instantiation of a test
+// in separate translation units.
+class ExternalInstantiationTest : public ::testing::TestWithParam<int> {
+};
+
+// Test fixture for testing instantiation of a test in multiple
+// translation units.
+class InstantiationInMultipleTranslaionUnitsTest
+    : public ::testing::TestWithParam<int> {
+};
+
+#endif  // GTEST_HAS_PARAM_TEST
+
+#endif  // GTEST_TEST_GTEST_PARAM_TEST_TEST_H_
diff --git a/third_party/googletest/googletest/test/gtest-port_test.cc b/third_party/googletest/googletest/test/gtest-port_test.cc
new file mode 100644
index 0000000..d17bad0
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest-port_test.cc
@@ -0,0 +1,1304 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: vladl@google.com (Vlad Losev), wan@google.com (Zhanyong Wan)
+//
+// This file tests the internal cross-platform support utilities.
+
+#include "gtest/internal/gtest-port.h"
+
+#include <stdio.h>
+
+#if GTEST_OS_MAC
+# include <time.h>
+#endif  // GTEST_OS_MAC
+
+#include <list>
+#include <utility>  // For std::pair and std::make_pair.
+#include <vector>
+
+#include "gtest/gtest.h"
+#include "gtest/gtest-spi.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+using std::make_pair;
+using std::pair;
+
+namespace testing {
+namespace internal {
+
+TEST(IsXDigitTest, WorksForNarrowAscii) {
+  EXPECT_TRUE(IsXDigit('0'));
+  EXPECT_TRUE(IsXDigit('9'));
+  EXPECT_TRUE(IsXDigit('A'));
+  EXPECT_TRUE(IsXDigit('F'));
+  EXPECT_TRUE(IsXDigit('a'));
+  EXPECT_TRUE(IsXDigit('f'));
+
+  EXPECT_FALSE(IsXDigit('-'));
+  EXPECT_FALSE(IsXDigit('g'));
+  EXPECT_FALSE(IsXDigit('G'));
+}
+
+TEST(IsXDigitTest, ReturnsFalseForNarrowNonAscii) {
+  EXPECT_FALSE(IsXDigit(static_cast<char>(0x80)));
+  EXPECT_FALSE(IsXDigit(static_cast<char>('0' | 0x80)));
+}
+
+TEST(IsXDigitTest, WorksForWideAscii) {
+  EXPECT_TRUE(IsXDigit(L'0'));
+  EXPECT_TRUE(IsXDigit(L'9'));
+  EXPECT_TRUE(IsXDigit(L'A'));
+  EXPECT_TRUE(IsXDigit(L'F'));
+  EXPECT_TRUE(IsXDigit(L'a'));
+  EXPECT_TRUE(IsXDigit(L'f'));
+
+  EXPECT_FALSE(IsXDigit(L'-'));
+  EXPECT_FALSE(IsXDigit(L'g'));
+  EXPECT_FALSE(IsXDigit(L'G'));
+}
+
+TEST(IsXDigitTest, ReturnsFalseForWideNonAscii) {
+  EXPECT_FALSE(IsXDigit(static_cast<wchar_t>(0x80)));
+  EXPECT_FALSE(IsXDigit(static_cast<wchar_t>(L'0' | 0x80)));
+  EXPECT_FALSE(IsXDigit(static_cast<wchar_t>(L'0' | 0x100)));
+}
+
+class Base {
+ public:
+  // Copy constructor and assignment operator do exactly what we need, so we
+  // use them.
+  Base() : member_(0) {}
+  explicit Base(int n) : member_(n) {}
+  virtual ~Base() {}
+  int member() { return member_; }
+
+ private:
+  int member_;
+};
+
+class Derived : public Base {
+ public:
+  explicit Derived(int n) : Base(n) {}
+};
+
+TEST(ImplicitCastTest, ConvertsPointers) {
+  Derived derived(0);
+  EXPECT_TRUE(&derived == ::testing::internal::ImplicitCast_<Base*>(&derived));
+}
+
+TEST(ImplicitCastTest, CanUseInheritance) {
+  Derived derived(1);
+  Base base = ::testing::internal::ImplicitCast_<Base>(derived);
+  EXPECT_EQ(derived.member(), base.member());
+}
+
+class Castable {
+ public:
+  explicit Castable(bool* converted) : converted_(converted) {}
+  operator Base() {
+    *converted_ = true;
+    return Base();
+  }
+
+ private:
+  bool* converted_;
+};
+
+TEST(ImplicitCastTest, CanUseNonConstCastOperator) {
+  bool converted = false;
+  Castable castable(&converted);
+  Base base = ::testing::internal::ImplicitCast_<Base>(castable);
+  EXPECT_TRUE(converted);
+}
+
+class ConstCastable {
+ public:
+  explicit ConstCastable(bool* converted) : converted_(converted) {}
+  operator Base() const {
+    *converted_ = true;
+    return Base();
+  }
+
+ private:
+  bool* converted_;
+};
+
+TEST(ImplicitCastTest, CanUseConstCastOperatorOnConstValues) {
+  bool converted = false;
+  const ConstCastable const_castable(&converted);
+  Base base = ::testing::internal::ImplicitCast_<Base>(const_castable);
+  EXPECT_TRUE(converted);
+}
+
+class ConstAndNonConstCastable {
+ public:
+  ConstAndNonConstCastable(bool* converted, bool* const_converted)
+      : converted_(converted), const_converted_(const_converted) {}
+  operator Base() {
+    *converted_ = true;
+    return Base();
+  }
+  operator Base() const {
+    *const_converted_ = true;
+    return Base();
+  }
+
+ private:
+  bool* converted_;
+  bool* const_converted_;
+};
+
+TEST(ImplicitCastTest, CanSelectBetweenConstAndNonConstCasrAppropriately) {
+  bool converted = false;
+  bool const_converted = false;
+  ConstAndNonConstCastable castable(&converted, &const_converted);
+  Base base = ::testing::internal::ImplicitCast_<Base>(castable);
+  EXPECT_TRUE(converted);
+  EXPECT_FALSE(const_converted);
+
+  converted = false;
+  const_converted = false;
+  const ConstAndNonConstCastable const_castable(&converted, &const_converted);
+  base = ::testing::internal::ImplicitCast_<Base>(const_castable);
+  EXPECT_FALSE(converted);
+  EXPECT_TRUE(const_converted);
+}
+
+class To {
+ public:
+  To(bool* converted) { *converted = true; }  // NOLINT
+};
+
+TEST(ImplicitCastTest, CanUseImplicitConstructor) {
+  bool converted = false;
+  To to = ::testing::internal::ImplicitCast_<To>(&converted);
+  (void)to;
+  EXPECT_TRUE(converted);
+}
+
+TEST(IteratorTraitsTest, WorksForSTLContainerIterators) {
+  StaticAssertTypeEq<int,
+      IteratorTraits< ::std::vector<int>::const_iterator>::value_type>();
+  StaticAssertTypeEq<bool,
+      IteratorTraits< ::std::list<bool>::iterator>::value_type>();
+}
+
+TEST(IteratorTraitsTest, WorksForPointerToNonConst) {
+  StaticAssertTypeEq<char, IteratorTraits<char*>::value_type>();
+  StaticAssertTypeEq<const void*, IteratorTraits<const void**>::value_type>();
+}
+
+TEST(IteratorTraitsTest, WorksForPointerToConst) {
+  StaticAssertTypeEq<char, IteratorTraits<const char*>::value_type>();
+  StaticAssertTypeEq<const void*,
+      IteratorTraits<const void* const*>::value_type>();
+}
+
+// Tests that the element_type typedef is available in scoped_ptr and refers
+// to the parameter type.
+TEST(ScopedPtrTest, DefinesElementType) {
+  StaticAssertTypeEq<int, ::testing::internal::scoped_ptr<int>::element_type>();
+}
+
+// TODO(vladl@google.com): Implement THE REST of scoped_ptr tests.
+
+TEST(GtestCheckSyntaxTest, BehavesLikeASingleStatement) {
+  if (AlwaysFalse())
+    GTEST_CHECK_(false) << "This should never be executed; "
+                           "It's a compilation test only.";
+
+  if (AlwaysTrue())
+    GTEST_CHECK_(true);
+  else
+    ;  // NOLINT
+
+  if (AlwaysFalse())
+    ;  // NOLINT
+  else
+    GTEST_CHECK_(true) << "";
+}
+
+TEST(GtestCheckSyntaxTest, WorksWithSwitch) {
+  switch (0) {
+    case 1:
+      break;
+    default:
+      GTEST_CHECK_(true);
+  }
+
+  switch (0)
+    case 0:
+      GTEST_CHECK_(true) << "Check failed in switch case";
+}
+
+// Verifies behavior of FormatFileLocation.
+TEST(FormatFileLocationTest, FormatsFileLocation) {
+  EXPECT_PRED_FORMAT2(IsSubstring, "foo.cc", FormatFileLocation("foo.cc", 42));
+  EXPECT_PRED_FORMAT2(IsSubstring, "42", FormatFileLocation("foo.cc", 42));
+}
+
+TEST(FormatFileLocationTest, FormatsUnknownFile) {
+  EXPECT_PRED_FORMAT2(
+      IsSubstring, "unknown file", FormatFileLocation(NULL, 42));
+  EXPECT_PRED_FORMAT2(IsSubstring, "42", FormatFileLocation(NULL, 42));
+}
+
+TEST(FormatFileLocationTest, FormatsUknownLine) {
+  EXPECT_EQ("foo.cc:", FormatFileLocation("foo.cc", -1));
+}
+
+TEST(FormatFileLocationTest, FormatsUknownFileAndLine) {
+  EXPECT_EQ("unknown file:", FormatFileLocation(NULL, -1));
+}
+
+// Verifies behavior of FormatCompilerIndependentFileLocation.
+TEST(FormatCompilerIndependentFileLocationTest, FormatsFileLocation) {
+  EXPECT_EQ("foo.cc:42", FormatCompilerIndependentFileLocation("foo.cc", 42));
+}
+
+TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownFile) {
+  EXPECT_EQ("unknown file:42",
+            FormatCompilerIndependentFileLocation(NULL, 42));
+}
+
+TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownLine) {
+  EXPECT_EQ("foo.cc", FormatCompilerIndependentFileLocation("foo.cc", -1));
+}
+
+TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownFileAndLine) {
+  EXPECT_EQ("unknown file", FormatCompilerIndependentFileLocation(NULL, -1));
+}
+
+#if GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_QNX
+void* ThreadFunc(void* data) {
+  internal::Mutex* mutex = static_cast<internal::Mutex*>(data);
+  mutex->Lock();
+  mutex->Unlock();
+  return NULL;
+}
+
+TEST(GetThreadCountTest, ReturnsCorrectValue) {
+  const size_t starting_count = GetThreadCount();
+  pthread_t       thread_id;
+
+  internal::Mutex mutex;
+  {
+    internal::MutexLock lock(&mutex);
+    pthread_attr_t  attr;
+    ASSERT_EQ(0, pthread_attr_init(&attr));
+    ASSERT_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE));
+
+    const int status = pthread_create(&thread_id, &attr, &ThreadFunc, &mutex);
+    ASSERT_EQ(0, pthread_attr_destroy(&attr));
+    ASSERT_EQ(0, status);
+    EXPECT_EQ(starting_count + 1, GetThreadCount());
+  }
+
+  void* dummy;
+  ASSERT_EQ(0, pthread_join(thread_id, &dummy));
+
+  // The OS may not immediately report the updated thread count after
+  // joining a thread, causing flakiness in this test. To counter that, we
+  // wait for up to .5 seconds for the OS to report the correct value.
+  for (int i = 0; i < 5; ++i) {
+    if (GetThreadCount() == starting_count)
+      break;
+
+    SleepMilliseconds(100);
+  }
+
+  EXPECT_EQ(starting_count, GetThreadCount());
+}
+#else
+TEST(GetThreadCountTest, ReturnsZeroWhenUnableToCountThreads) {
+  EXPECT_EQ(0U, GetThreadCount());
+}
+#endif  // GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_QNX
+
+TEST(GtestCheckDeathTest, DiesWithCorrectOutputOnFailure) {
+  const bool a_false_condition = false;
+  const char regex[] =
+#ifdef _MSC_VER
+     "gtest-port_test\\.cc\\(\\d+\\):"
+#elif GTEST_USES_POSIX_RE
+     "gtest-port_test\\.cc:[0-9]+"
+#else
+     "gtest-port_test\\.cc:\\d+"
+#endif  // _MSC_VER
+     ".*a_false_condition.*Extra info.*";
+
+  EXPECT_DEATH_IF_SUPPORTED(GTEST_CHECK_(a_false_condition) << "Extra info",
+                            regex);
+}
+
+#if GTEST_HAS_DEATH_TEST
+
+TEST(GtestCheckDeathTest, LivesSilentlyOnSuccess) {
+  EXPECT_EXIT({
+      GTEST_CHECK_(true) << "Extra info";
+      ::std::cerr << "Success\n";
+      exit(0); },
+      ::testing::ExitedWithCode(0), "Success");
+}
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+// Verifies that Google Test choose regular expression engine appropriate to
+// the platform. The test will produce compiler errors in case of failure.
+// For simplicity, we only cover the most important platforms here.
+TEST(RegexEngineSelectionTest, SelectsCorrectRegexEngine) {
+#if !GTEST_USES_PCRE
+# if GTEST_HAS_POSIX_RE
+
+  EXPECT_TRUE(GTEST_USES_POSIX_RE);
+
+# else
+
+  EXPECT_TRUE(GTEST_USES_SIMPLE_RE);
+
+# endif
+#endif  // !GTEST_USES_PCRE
+}
+
+#if GTEST_USES_POSIX_RE
+
+# if GTEST_HAS_TYPED_TEST
+
+template <typename Str>
+class RETest : public ::testing::Test {};
+
+// Defines StringTypes as the list of all string types that class RE
+// supports.
+typedef testing::Types<
+    ::std::string,
+#  if GTEST_HAS_GLOBAL_STRING
+    ::string,
+#  endif  // GTEST_HAS_GLOBAL_STRING
+    const char*> StringTypes;
+
+TYPED_TEST_CASE(RETest, StringTypes);
+
+// Tests RE's implicit constructors.
+TYPED_TEST(RETest, ImplicitConstructorWorks) {
+  const RE empty(TypeParam(""));
+  EXPECT_STREQ("", empty.pattern());
+
+  const RE simple(TypeParam("hello"));
+  EXPECT_STREQ("hello", simple.pattern());
+
+  const RE normal(TypeParam(".*(\\w+)"));
+  EXPECT_STREQ(".*(\\w+)", normal.pattern());
+}
+
+// Tests that RE's constructors reject invalid regular expressions.
+TYPED_TEST(RETest, RejectsInvalidRegex) {
+  EXPECT_NONFATAL_FAILURE({
+    const RE invalid(TypeParam("?"));
+  }, "\"?\" is not a valid POSIX Extended regular expression.");
+}
+
+// Tests RE::FullMatch().
+TYPED_TEST(RETest, FullMatchWorks) {
+  const RE empty(TypeParam(""));
+  EXPECT_TRUE(RE::FullMatch(TypeParam(""), empty));
+  EXPECT_FALSE(RE::FullMatch(TypeParam("a"), empty));
+
+  const RE re(TypeParam("a.*z"));
+  EXPECT_TRUE(RE::FullMatch(TypeParam("az"), re));
+  EXPECT_TRUE(RE::FullMatch(TypeParam("axyz"), re));
+  EXPECT_FALSE(RE::FullMatch(TypeParam("baz"), re));
+  EXPECT_FALSE(RE::FullMatch(TypeParam("azy"), re));
+}
+
+// Tests RE::PartialMatch().
+TYPED_TEST(RETest, PartialMatchWorks) {
+  const RE empty(TypeParam(""));
+  EXPECT_TRUE(RE::PartialMatch(TypeParam(""), empty));
+  EXPECT_TRUE(RE::PartialMatch(TypeParam("a"), empty));
+
+  const RE re(TypeParam("a.*z"));
+  EXPECT_TRUE(RE::PartialMatch(TypeParam("az"), re));
+  EXPECT_TRUE(RE::PartialMatch(TypeParam("axyz"), re));
+  EXPECT_TRUE(RE::PartialMatch(TypeParam("baz"), re));
+  EXPECT_TRUE(RE::PartialMatch(TypeParam("azy"), re));
+  EXPECT_FALSE(RE::PartialMatch(TypeParam("zza"), re));
+}
+
+# endif  // GTEST_HAS_TYPED_TEST
+
+#elif GTEST_USES_SIMPLE_RE
+
+TEST(IsInSetTest, NulCharIsNotInAnySet) {
+  EXPECT_FALSE(IsInSet('\0', ""));
+  EXPECT_FALSE(IsInSet('\0', "\0"));
+  EXPECT_FALSE(IsInSet('\0', "a"));
+}
+
+TEST(IsInSetTest, WorksForNonNulChars) {
+  EXPECT_FALSE(IsInSet('a', "Ab"));
+  EXPECT_FALSE(IsInSet('c', ""));
+
+  EXPECT_TRUE(IsInSet('b', "bcd"));
+  EXPECT_TRUE(IsInSet('b', "ab"));
+}
+
+TEST(IsAsciiDigitTest, IsFalseForNonDigit) {
+  EXPECT_FALSE(IsAsciiDigit('\0'));
+  EXPECT_FALSE(IsAsciiDigit(' '));
+  EXPECT_FALSE(IsAsciiDigit('+'));
+  EXPECT_FALSE(IsAsciiDigit('-'));
+  EXPECT_FALSE(IsAsciiDigit('.'));
+  EXPECT_FALSE(IsAsciiDigit('a'));
+}
+
+TEST(IsAsciiDigitTest, IsTrueForDigit) {
+  EXPECT_TRUE(IsAsciiDigit('0'));
+  EXPECT_TRUE(IsAsciiDigit('1'));
+  EXPECT_TRUE(IsAsciiDigit('5'));
+  EXPECT_TRUE(IsAsciiDigit('9'));
+}
+
+TEST(IsAsciiPunctTest, IsFalseForNonPunct) {
+  EXPECT_FALSE(IsAsciiPunct('\0'));
+  EXPECT_FALSE(IsAsciiPunct(' '));
+  EXPECT_FALSE(IsAsciiPunct('\n'));
+  EXPECT_FALSE(IsAsciiPunct('a'));
+  EXPECT_FALSE(IsAsciiPunct('0'));
+}
+
+TEST(IsAsciiPunctTest, IsTrueForPunct) {
+  for (const char* p = "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~"; *p; p++) {
+    EXPECT_PRED1(IsAsciiPunct, *p);
+  }
+}
+
+TEST(IsRepeatTest, IsFalseForNonRepeatChar) {
+  EXPECT_FALSE(IsRepeat('\0'));
+  EXPECT_FALSE(IsRepeat(' '));
+  EXPECT_FALSE(IsRepeat('a'));
+  EXPECT_FALSE(IsRepeat('1'));
+  EXPECT_FALSE(IsRepeat('-'));
+}
+
+TEST(IsRepeatTest, IsTrueForRepeatChar) {
+  EXPECT_TRUE(IsRepeat('?'));
+  EXPECT_TRUE(IsRepeat('*'));
+  EXPECT_TRUE(IsRepeat('+'));
+}
+
+TEST(IsAsciiWhiteSpaceTest, IsFalseForNonWhiteSpace) {
+  EXPECT_FALSE(IsAsciiWhiteSpace('\0'));
+  EXPECT_FALSE(IsAsciiWhiteSpace('a'));
+  EXPECT_FALSE(IsAsciiWhiteSpace('1'));
+  EXPECT_FALSE(IsAsciiWhiteSpace('+'));
+  EXPECT_FALSE(IsAsciiWhiteSpace('_'));
+}
+
+TEST(IsAsciiWhiteSpaceTest, IsTrueForWhiteSpace) {
+  EXPECT_TRUE(IsAsciiWhiteSpace(' '));
+  EXPECT_TRUE(IsAsciiWhiteSpace('\n'));
+  EXPECT_TRUE(IsAsciiWhiteSpace('\r'));
+  EXPECT_TRUE(IsAsciiWhiteSpace('\t'));
+  EXPECT_TRUE(IsAsciiWhiteSpace('\v'));
+  EXPECT_TRUE(IsAsciiWhiteSpace('\f'));
+}
+
+TEST(IsAsciiWordCharTest, IsFalseForNonWordChar) {
+  EXPECT_FALSE(IsAsciiWordChar('\0'));
+  EXPECT_FALSE(IsAsciiWordChar('+'));
+  EXPECT_FALSE(IsAsciiWordChar('.'));
+  EXPECT_FALSE(IsAsciiWordChar(' '));
+  EXPECT_FALSE(IsAsciiWordChar('\n'));
+}
+
+TEST(IsAsciiWordCharTest, IsTrueForLetter) {
+  EXPECT_TRUE(IsAsciiWordChar('a'));
+  EXPECT_TRUE(IsAsciiWordChar('b'));
+  EXPECT_TRUE(IsAsciiWordChar('A'));
+  EXPECT_TRUE(IsAsciiWordChar('Z'));
+}
+
+TEST(IsAsciiWordCharTest, IsTrueForDigit) {
+  EXPECT_TRUE(IsAsciiWordChar('0'));
+  EXPECT_TRUE(IsAsciiWordChar('1'));
+  EXPECT_TRUE(IsAsciiWordChar('7'));
+  EXPECT_TRUE(IsAsciiWordChar('9'));
+}
+
+TEST(IsAsciiWordCharTest, IsTrueForUnderscore) {
+  EXPECT_TRUE(IsAsciiWordChar('_'));
+}
+
+TEST(IsValidEscapeTest, IsFalseForNonPrintable) {
+  EXPECT_FALSE(IsValidEscape('\0'));
+  EXPECT_FALSE(IsValidEscape('\007'));
+}
+
+TEST(IsValidEscapeTest, IsFalseForDigit) {
+  EXPECT_FALSE(IsValidEscape('0'));
+  EXPECT_FALSE(IsValidEscape('9'));
+}
+
+TEST(IsValidEscapeTest, IsFalseForWhiteSpace) {
+  EXPECT_FALSE(IsValidEscape(' '));
+  EXPECT_FALSE(IsValidEscape('\n'));
+}
+
+TEST(IsValidEscapeTest, IsFalseForSomeLetter) {
+  EXPECT_FALSE(IsValidEscape('a'));
+  EXPECT_FALSE(IsValidEscape('Z'));
+}
+
+TEST(IsValidEscapeTest, IsTrueForPunct) {
+  EXPECT_TRUE(IsValidEscape('.'));
+  EXPECT_TRUE(IsValidEscape('-'));
+  EXPECT_TRUE(IsValidEscape('^'));
+  EXPECT_TRUE(IsValidEscape('$'));
+  EXPECT_TRUE(IsValidEscape('('));
+  EXPECT_TRUE(IsValidEscape(']'));
+  EXPECT_TRUE(IsValidEscape('{'));
+  EXPECT_TRUE(IsValidEscape('|'));
+}
+
+TEST(IsValidEscapeTest, IsTrueForSomeLetter) {
+  EXPECT_TRUE(IsValidEscape('d'));
+  EXPECT_TRUE(IsValidEscape('D'));
+  EXPECT_TRUE(IsValidEscape('s'));
+  EXPECT_TRUE(IsValidEscape('S'));
+  EXPECT_TRUE(IsValidEscape('w'));
+  EXPECT_TRUE(IsValidEscape('W'));
+}
+
+TEST(AtomMatchesCharTest, EscapedPunct) {
+  EXPECT_FALSE(AtomMatchesChar(true, '\\', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(true, '\\', ' '));
+  EXPECT_FALSE(AtomMatchesChar(true, '_', '.'));
+  EXPECT_FALSE(AtomMatchesChar(true, '.', 'a'));
+
+  EXPECT_TRUE(AtomMatchesChar(true, '\\', '\\'));
+  EXPECT_TRUE(AtomMatchesChar(true, '_', '_'));
+  EXPECT_TRUE(AtomMatchesChar(true, '+', '+'));
+  EXPECT_TRUE(AtomMatchesChar(true, '.', '.'));
+}
+
+TEST(AtomMatchesCharTest, Escaped_d) {
+  EXPECT_FALSE(AtomMatchesChar(true, 'd', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'd', 'a'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'd', '.'));
+
+  EXPECT_TRUE(AtomMatchesChar(true, 'd', '0'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'd', '9'));
+}
+
+TEST(AtomMatchesCharTest, Escaped_D) {
+  EXPECT_FALSE(AtomMatchesChar(true, 'D', '0'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'D', '9'));
+
+  EXPECT_TRUE(AtomMatchesChar(true, 'D', '\0'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'D', 'a'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'D', '-'));
+}
+
+TEST(AtomMatchesCharTest, Escaped_s) {
+  EXPECT_FALSE(AtomMatchesChar(true, 's', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(true, 's', 'a'));
+  EXPECT_FALSE(AtomMatchesChar(true, 's', '.'));
+  EXPECT_FALSE(AtomMatchesChar(true, 's', '9'));
+
+  EXPECT_TRUE(AtomMatchesChar(true, 's', ' '));
+  EXPECT_TRUE(AtomMatchesChar(true, 's', '\n'));
+  EXPECT_TRUE(AtomMatchesChar(true, 's', '\t'));
+}
+
+TEST(AtomMatchesCharTest, Escaped_S) {
+  EXPECT_FALSE(AtomMatchesChar(true, 'S', ' '));
+  EXPECT_FALSE(AtomMatchesChar(true, 'S', '\r'));
+
+  EXPECT_TRUE(AtomMatchesChar(true, 'S', '\0'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'S', 'a'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'S', '9'));
+}
+
+TEST(AtomMatchesCharTest, Escaped_w) {
+  EXPECT_FALSE(AtomMatchesChar(true, 'w', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'w', '+'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'w', ' '));
+  EXPECT_FALSE(AtomMatchesChar(true, 'w', '\n'));
+
+  EXPECT_TRUE(AtomMatchesChar(true, 'w', '0'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'w', 'b'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'w', 'C'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'w', '_'));
+}
+
+TEST(AtomMatchesCharTest, Escaped_W) {
+  EXPECT_FALSE(AtomMatchesChar(true, 'W', 'A'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'W', 'b'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'W', '9'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'W', '_'));
+
+  EXPECT_TRUE(AtomMatchesChar(true, 'W', '\0'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'W', '*'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'W', '\n'));
+}
+
+TEST(AtomMatchesCharTest, EscapedWhiteSpace) {
+  EXPECT_FALSE(AtomMatchesChar(true, 'f', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'f', '\n'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'n', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'n', '\r'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'r', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'r', 'a'));
+  EXPECT_FALSE(AtomMatchesChar(true, 't', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(true, 't', 't'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'v', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'v', '\f'));
+
+  EXPECT_TRUE(AtomMatchesChar(true, 'f', '\f'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'n', '\n'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'r', '\r'));
+  EXPECT_TRUE(AtomMatchesChar(true, 't', '\t'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'v', '\v'));
+}
+
+TEST(AtomMatchesCharTest, UnescapedDot) {
+  EXPECT_FALSE(AtomMatchesChar(false, '.', '\n'));
+
+  EXPECT_TRUE(AtomMatchesChar(false, '.', '\0'));
+  EXPECT_TRUE(AtomMatchesChar(false, '.', '.'));
+  EXPECT_TRUE(AtomMatchesChar(false, '.', 'a'));
+  EXPECT_TRUE(AtomMatchesChar(false, '.', ' '));
+}
+
+TEST(AtomMatchesCharTest, UnescapedChar) {
+  EXPECT_FALSE(AtomMatchesChar(false, 'a', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(false, 'a', 'b'));
+  EXPECT_FALSE(AtomMatchesChar(false, '$', 'a'));
+
+  EXPECT_TRUE(AtomMatchesChar(false, '$', '$'));
+  EXPECT_TRUE(AtomMatchesChar(false, '5', '5'));
+  EXPECT_TRUE(AtomMatchesChar(false, 'Z', 'Z'));
+}
+
+TEST(ValidateRegexTest, GeneratesFailureAndReturnsFalseForInvalid) {
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex(NULL)),
+                          "NULL is not a valid simple regular expression");
+  EXPECT_NONFATAL_FAILURE(
+      ASSERT_FALSE(ValidateRegex("a\\")),
+      "Syntax error at index 1 in simple regular expression \"a\\\": ");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("a\\")),
+                          "'\\' cannot appear at the end");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("\\n\\")),
+                          "'\\' cannot appear at the end");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("\\s\\hb")),
+                          "invalid escape sequence \"\\h\"");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("^^")),
+                          "'^' can only appear at the beginning");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex(".*^b")),
+                          "'^' can only appear at the beginning");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("$$")),
+                          "'$' can only appear at the end");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("^$a")),
+                          "'$' can only appear at the end");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("a(b")),
+                          "'(' is unsupported");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("ab)")),
+                          "')' is unsupported");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("[ab")),
+                          "'[' is unsupported");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("a{2")),
+                          "'{' is unsupported");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("?")),
+                          "'?' can only follow a repeatable token");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("^*")),
+                          "'*' can only follow a repeatable token");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("5*+")),
+                          "'+' can only follow a repeatable token");
+}
+
+TEST(ValidateRegexTest, ReturnsTrueForValid) {
+  EXPECT_TRUE(ValidateRegex(""));
+  EXPECT_TRUE(ValidateRegex("a"));
+  EXPECT_TRUE(ValidateRegex(".*"));
+  EXPECT_TRUE(ValidateRegex("^a_+"));
+  EXPECT_TRUE(ValidateRegex("^a\\t\\&?"));
+  EXPECT_TRUE(ValidateRegex("09*$"));
+  EXPECT_TRUE(ValidateRegex("^Z$"));
+  EXPECT_TRUE(ValidateRegex("a\\^Z\\$\\(\\)\\|\\[\\]\\{\\}"));
+}
+
+TEST(MatchRepetitionAndRegexAtHeadTest, WorksForZeroOrOne) {
+  EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, 'a', '?', "a", "ba"));
+  // Repeating more than once.
+  EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, 'a', '?', "b", "aab"));
+
+  // Repeating zero times.
+  EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, 'a', '?', "b", "ba"));
+  // Repeating once.
+  EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, 'a', '?', "b", "ab"));
+  EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, '#', '?', ".", "##"));
+}
+
+TEST(MatchRepetitionAndRegexAtHeadTest, WorksForZeroOrMany) {
+  EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, '.', '*', "a$", "baab"));
+
+  // Repeating zero times.
+  EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, '.', '*', "b", "bc"));
+  // Repeating once.
+  EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, '.', '*', "b", "abc"));
+  // Repeating more than once.
+  EXPECT_TRUE(MatchRepetitionAndRegexAtHead(true, 'w', '*', "-", "ab_1-g"));
+}
+
+TEST(MatchRepetitionAndRegexAtHeadTest, WorksForOneOrMany) {
+  EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, '.', '+', "a$", "baab"));
+  // Repeating zero times.
+  EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, '.', '+', "b", "bc"));
+
+  // Repeating once.
+  EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, '.', '+', "b", "abc"));
+  // Repeating more than once.
+  EXPECT_TRUE(MatchRepetitionAndRegexAtHead(true, 'w', '+', "-", "ab_1-g"));
+}
+
+TEST(MatchRegexAtHeadTest, ReturnsTrueForEmptyRegex) {
+  EXPECT_TRUE(MatchRegexAtHead("", ""));
+  EXPECT_TRUE(MatchRegexAtHead("", "ab"));
+}
+
+TEST(MatchRegexAtHeadTest, WorksWhenDollarIsInRegex) {
+  EXPECT_FALSE(MatchRegexAtHead("$", "a"));
+
+  EXPECT_TRUE(MatchRegexAtHead("$", ""));
+  EXPECT_TRUE(MatchRegexAtHead("a$", "a"));
+}
+
+TEST(MatchRegexAtHeadTest, WorksWhenRegexStartsWithEscapeSequence) {
+  EXPECT_FALSE(MatchRegexAtHead("\\w", "+"));
+  EXPECT_FALSE(MatchRegexAtHead("\\W", "ab"));
+
+  EXPECT_TRUE(MatchRegexAtHead("\\sa", "\nab"));
+  EXPECT_TRUE(MatchRegexAtHead("\\d", "1a"));
+}
+
+TEST(MatchRegexAtHeadTest, WorksWhenRegexStartsWithRepetition) {
+  EXPECT_FALSE(MatchRegexAtHead(".+a", "abc"));
+  EXPECT_FALSE(MatchRegexAtHead("a?b", "aab"));
+
+  EXPECT_TRUE(MatchRegexAtHead(".*a", "bc12-ab"));
+  EXPECT_TRUE(MatchRegexAtHead("a?b", "b"));
+  EXPECT_TRUE(MatchRegexAtHead("a?b", "ab"));
+}
+
+TEST(MatchRegexAtHeadTest,
+     WorksWhenRegexStartsWithRepetionOfEscapeSequence) {
+  EXPECT_FALSE(MatchRegexAtHead("\\.+a", "abc"));
+  EXPECT_FALSE(MatchRegexAtHead("\\s?b", "  b"));
+
+  EXPECT_TRUE(MatchRegexAtHead("\\(*a", "((((ab"));
+  EXPECT_TRUE(MatchRegexAtHead("\\^?b", "^b"));
+  EXPECT_TRUE(MatchRegexAtHead("\\\\?b", "b"));
+  EXPECT_TRUE(MatchRegexAtHead("\\\\?b", "\\b"));
+}
+
+TEST(MatchRegexAtHeadTest, MatchesSequentially) {
+  EXPECT_FALSE(MatchRegexAtHead("ab.*c", "acabc"));
+
+  EXPECT_TRUE(MatchRegexAtHead("ab.*c", "ab-fsc"));
+}
+
+TEST(MatchRegexAnywhereTest, ReturnsFalseWhenStringIsNull) {
+  EXPECT_FALSE(MatchRegexAnywhere("", NULL));
+}
+
+TEST(MatchRegexAnywhereTest, WorksWhenRegexStartsWithCaret) {
+  EXPECT_FALSE(MatchRegexAnywhere("^a", "ba"));
+  EXPECT_FALSE(MatchRegexAnywhere("^$", "a"));
+
+  EXPECT_TRUE(MatchRegexAnywhere("^a", "ab"));
+  EXPECT_TRUE(MatchRegexAnywhere("^", "ab"));
+  EXPECT_TRUE(MatchRegexAnywhere("^$", ""));
+}
+
+TEST(MatchRegexAnywhereTest, ReturnsFalseWhenNoMatch) {
+  EXPECT_FALSE(MatchRegexAnywhere("a", "bcde123"));
+  EXPECT_FALSE(MatchRegexAnywhere("a.+a", "--aa88888888"));
+}
+
+TEST(MatchRegexAnywhereTest, ReturnsTrueWhenMatchingPrefix) {
+  EXPECT_TRUE(MatchRegexAnywhere("\\w+", "ab1_ - 5"));
+  EXPECT_TRUE(MatchRegexAnywhere(".*=", "="));
+  EXPECT_TRUE(MatchRegexAnywhere("x.*ab?.*bc", "xaaabc"));
+}
+
+TEST(MatchRegexAnywhereTest, ReturnsTrueWhenMatchingNonPrefix) {
+  EXPECT_TRUE(MatchRegexAnywhere("\\w+", "$$$ ab1_ - 5"));
+  EXPECT_TRUE(MatchRegexAnywhere("\\.+=", "=  ...="));
+}
+
+// Tests RE's implicit constructors.
+TEST(RETest, ImplicitConstructorWorks) {
+  const RE empty("");
+  EXPECT_STREQ("", empty.pattern());
+
+  const RE simple("hello");
+  EXPECT_STREQ("hello", simple.pattern());
+}
+
+// Tests that RE's constructors reject invalid regular expressions.
+TEST(RETest, RejectsInvalidRegex) {
+  EXPECT_NONFATAL_FAILURE({
+    const RE normal(NULL);
+  }, "NULL is not a valid simple regular expression");
+
+  EXPECT_NONFATAL_FAILURE({
+    const RE normal(".*(\\w+");
+  }, "'(' is unsupported");
+
+  EXPECT_NONFATAL_FAILURE({
+    const RE invalid("^?");
+  }, "'?' can only follow a repeatable token");
+}
+
+// Tests RE::FullMatch().
+TEST(RETest, FullMatchWorks) {
+  const RE empty("");
+  EXPECT_TRUE(RE::FullMatch("", empty));
+  EXPECT_FALSE(RE::FullMatch("a", empty));
+
+  const RE re1("a");
+  EXPECT_TRUE(RE::FullMatch("a", re1));
+
+  const RE re("a.*z");
+  EXPECT_TRUE(RE::FullMatch("az", re));
+  EXPECT_TRUE(RE::FullMatch("axyz", re));
+  EXPECT_FALSE(RE::FullMatch("baz", re));
+  EXPECT_FALSE(RE::FullMatch("azy", re));
+}
+
+// Tests RE::PartialMatch().
+TEST(RETest, PartialMatchWorks) {
+  const RE empty("");
+  EXPECT_TRUE(RE::PartialMatch("", empty));
+  EXPECT_TRUE(RE::PartialMatch("a", empty));
+
+  const RE re("a.*z");
+  EXPECT_TRUE(RE::PartialMatch("az", re));
+  EXPECT_TRUE(RE::PartialMatch("axyz", re));
+  EXPECT_TRUE(RE::PartialMatch("baz", re));
+  EXPECT_TRUE(RE::PartialMatch("azy", re));
+  EXPECT_FALSE(RE::PartialMatch("zza", re));
+}
+
+#endif  // GTEST_USES_POSIX_RE
+
+#if !GTEST_OS_WINDOWS_MOBILE
+
+TEST(CaptureTest, CapturesStdout) {
+  CaptureStdout();
+  fprintf(stdout, "abc");
+  EXPECT_STREQ("abc", GetCapturedStdout().c_str());
+
+  CaptureStdout();
+  fprintf(stdout, "def%cghi", '\0');
+  EXPECT_EQ(::std::string("def\0ghi", 7), ::std::string(GetCapturedStdout()));
+}
+
+TEST(CaptureTest, CapturesStderr) {
+  CaptureStderr();
+  fprintf(stderr, "jkl");
+  EXPECT_STREQ("jkl", GetCapturedStderr().c_str());
+
+  CaptureStderr();
+  fprintf(stderr, "jkl%cmno", '\0');
+  EXPECT_EQ(::std::string("jkl\0mno", 7), ::std::string(GetCapturedStderr()));
+}
+
+// Tests that stdout and stderr capture don't interfere with each other.
+TEST(CaptureTest, CapturesStdoutAndStderr) {
+  CaptureStdout();
+  CaptureStderr();
+  fprintf(stdout, "pqr");
+  fprintf(stderr, "stu");
+  EXPECT_STREQ("pqr", GetCapturedStdout().c_str());
+  EXPECT_STREQ("stu", GetCapturedStderr().c_str());
+}
+
+TEST(CaptureDeathTest, CannotReenterStdoutCapture) {
+  CaptureStdout();
+  EXPECT_DEATH_IF_SUPPORTED(CaptureStdout(),
+                            "Only one stdout capturer can exist at a time");
+  GetCapturedStdout();
+
+  // We cannot test stderr capturing using death tests as they use it
+  // themselves.
+}
+
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+TEST(ThreadLocalTest, DefaultConstructorInitializesToDefaultValues) {
+  ThreadLocal<int> t1;
+  EXPECT_EQ(0, t1.get());
+
+  ThreadLocal<void*> t2;
+  EXPECT_TRUE(t2.get() == NULL);
+}
+
+TEST(ThreadLocalTest, SingleParamConstructorInitializesToParam) {
+  ThreadLocal<int> t1(123);
+  EXPECT_EQ(123, t1.get());
+
+  int i = 0;
+  ThreadLocal<int*> t2(&i);
+  EXPECT_EQ(&i, t2.get());
+}
+
+class NoDefaultContructor {
+ public:
+  explicit NoDefaultContructor(const char*) {}
+  NoDefaultContructor(const NoDefaultContructor&) {}
+};
+
+TEST(ThreadLocalTest, ValueDefaultContructorIsNotRequiredForParamVersion) {
+  ThreadLocal<NoDefaultContructor> bar(NoDefaultContructor("foo"));
+  bar.pointer();
+}
+
+TEST(ThreadLocalTest, GetAndPointerReturnSameValue) {
+  ThreadLocal<std::string> thread_local_string;
+
+  EXPECT_EQ(thread_local_string.pointer(), &(thread_local_string.get()));
+
+  // Verifies the condition still holds after calling set.
+  thread_local_string.set("foo");
+  EXPECT_EQ(thread_local_string.pointer(), &(thread_local_string.get()));
+}
+
+TEST(ThreadLocalTest, PointerAndConstPointerReturnSameValue) {
+  ThreadLocal<std::string> thread_local_string;
+  const ThreadLocal<std::string>& const_thread_local_string =
+      thread_local_string;
+
+  EXPECT_EQ(thread_local_string.pointer(), const_thread_local_string.pointer());
+
+  thread_local_string.set("foo");
+  EXPECT_EQ(thread_local_string.pointer(), const_thread_local_string.pointer());
+}
+
+#if GTEST_IS_THREADSAFE
+
+void AddTwo(int* param) { *param += 2; }
+
+TEST(ThreadWithParamTest, ConstructorExecutesThreadFunc) {
+  int i = 40;
+  ThreadWithParam<int*> thread(&AddTwo, &i, NULL);
+  thread.Join();
+  EXPECT_EQ(42, i);
+}
+
+TEST(MutexDeathTest, AssertHeldShouldAssertWhenNotLocked) {
+  // AssertHeld() is flaky only in the presence of multiple threads accessing
+  // the lock. In this case, the test is robust.
+  EXPECT_DEATH_IF_SUPPORTED({
+    Mutex m;
+    { MutexLock lock(&m); }
+    m.AssertHeld();
+  },
+  "thread .*hold");
+}
+
+TEST(MutexTest, AssertHeldShouldNotAssertWhenLocked) {
+  Mutex m;
+  MutexLock lock(&m);
+  m.AssertHeld();
+}
+
+class AtomicCounterWithMutex {
+ public:
+  explicit AtomicCounterWithMutex(Mutex* mutex) :
+    value_(0), mutex_(mutex), random_(42) {}
+
+  void Increment() {
+    MutexLock lock(mutex_);
+    int temp = value_;
+    {
+      // We need to put up a memory barrier to prevent reads and writes to
+      // value_ rearranged with the call to SleepMilliseconds when observed
+      // from other threads.
+#if GTEST_HAS_PTHREAD
+      // On POSIX, locking a mutex puts up a memory barrier.  We cannot use
+      // Mutex and MutexLock here or rely on their memory barrier
+      // functionality as we are testing them here.
+      pthread_mutex_t memory_barrier_mutex;
+      GTEST_CHECK_POSIX_SUCCESS_(
+          pthread_mutex_init(&memory_barrier_mutex, NULL));
+      GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&memory_barrier_mutex));
+
+      SleepMilliseconds(random_.Generate(30));
+
+      GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&memory_barrier_mutex));
+      GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&memory_barrier_mutex));
+#elif GTEST_OS_WINDOWS
+      // On Windows, performing an interlocked access puts up a memory barrier.
+      volatile LONG dummy = 0;
+      ::InterlockedIncrement(&dummy);
+      SleepMilliseconds(random_.Generate(30));
+      ::InterlockedIncrement(&dummy);
+#else
+# error "Memory barrier not implemented on this platform."
+#endif  // GTEST_HAS_PTHREAD
+    }
+    value_ = temp + 1;
+  }
+  int value() const { return value_; }
+
+ private:
+  volatile int value_;
+  Mutex* const mutex_;  // Protects value_.
+  Random       random_;
+};
+
+void CountingThreadFunc(pair<AtomicCounterWithMutex*, int> param) {
+  for (int i = 0; i < param.second; ++i)
+      param.first->Increment();
+}
+
+// Tests that the mutex only lets one thread at a time to lock it.
+TEST(MutexTest, OnlyOneThreadCanLockAtATime) {
+  Mutex mutex;
+  AtomicCounterWithMutex locked_counter(&mutex);
+
+  typedef ThreadWithParam<pair<AtomicCounterWithMutex*, int> > ThreadType;
+  const int kCycleCount = 20;
+  const int kThreadCount = 7;
+  scoped_ptr<ThreadType> counting_threads[kThreadCount];
+  Notification threads_can_start;
+  // Creates and runs kThreadCount threads that increment locked_counter
+  // kCycleCount times each.
+  for (int i = 0; i < kThreadCount; ++i) {
+    counting_threads[i].reset(new ThreadType(&CountingThreadFunc,
+                                             make_pair(&locked_counter,
+                                                       kCycleCount),
+                                             &threads_can_start));
+  }
+  threads_can_start.Notify();
+  for (int i = 0; i < kThreadCount; ++i)
+    counting_threads[i]->Join();
+
+  // If the mutex lets more than one thread to increment the counter at a
+  // time, they are likely to encounter a race condition and have some
+  // increments overwritten, resulting in the lower then expected counter
+  // value.
+  EXPECT_EQ(kCycleCount * kThreadCount, locked_counter.value());
+}
+
+template <typename T>
+void RunFromThread(void (func)(T), T param) {
+  ThreadWithParam<T> thread(func, param, NULL);
+  thread.Join();
+}
+
+void RetrieveThreadLocalValue(
+    pair<ThreadLocal<std::string>*, std::string*> param) {
+  *param.second = param.first->get();
+}
+
+TEST(ThreadLocalTest, ParameterizedConstructorSetsDefault) {
+  ThreadLocal<std::string> thread_local_string("foo");
+  EXPECT_STREQ("foo", thread_local_string.get().c_str());
+
+  thread_local_string.set("bar");
+  EXPECT_STREQ("bar", thread_local_string.get().c_str());
+
+  std::string result;
+  RunFromThread(&RetrieveThreadLocalValue,
+                make_pair(&thread_local_string, &result));
+  EXPECT_STREQ("foo", result.c_str());
+}
+
+// Keeps track of whether of destructors being called on instances of
+// DestructorTracker.  On Windows, waits for the destructor call reports.
+class DestructorCall {
+ public:
+  DestructorCall() {
+    invoked_ = false;
+#if GTEST_OS_WINDOWS
+    wait_event_.Reset(::CreateEvent(NULL, TRUE, FALSE, NULL));
+    GTEST_CHECK_(wait_event_.Get() != NULL);
+#endif
+  }
+
+  bool CheckDestroyed() const {
+#if GTEST_OS_WINDOWS
+    if (::WaitForSingleObject(wait_event_.Get(), 1000) != WAIT_OBJECT_0)
+      return false;
+#endif
+    return invoked_;
+  }
+
+  void ReportDestroyed() {
+    invoked_ = true;
+#if GTEST_OS_WINDOWS
+    ::SetEvent(wait_event_.Get());
+#endif
+  }
+
+  static std::vector<DestructorCall*>& List() { return *list_; }
+
+  static void ResetList() {
+    for (size_t i = 0; i < list_->size(); ++i) {
+      delete list_->at(i);
+    }
+    list_->clear();
+  }
+
+ private:
+  bool invoked_;
+#if GTEST_OS_WINDOWS
+  AutoHandle wait_event_;
+#endif
+  static std::vector<DestructorCall*>* const list_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(DestructorCall);
+};
+
+std::vector<DestructorCall*>* const DestructorCall::list_ =
+    new std::vector<DestructorCall*>;
+
+// DestructorTracker keeps track of whether its instances have been
+// destroyed.
+class DestructorTracker {
+ public:
+  DestructorTracker() : index_(GetNewIndex()) {}
+  DestructorTracker(const DestructorTracker& /* rhs */)
+      : index_(GetNewIndex()) {}
+  ~DestructorTracker() {
+    // We never access DestructorCall::List() concurrently, so we don't need
+    // to protect this acccess with a mutex.
+    DestructorCall::List()[index_]->ReportDestroyed();
+  }
+
+ private:
+  static size_t GetNewIndex() {
+    DestructorCall::List().push_back(new DestructorCall);
+    return DestructorCall::List().size() - 1;
+  }
+  const size_t index_;
+
+  GTEST_DISALLOW_ASSIGN_(DestructorTracker);
+};
+
+typedef ThreadLocal<DestructorTracker>* ThreadParam;
+
+void CallThreadLocalGet(ThreadParam thread_local_param) {
+  thread_local_param->get();
+}
+
+// Tests that when a ThreadLocal object dies in a thread, it destroys
+// the managed object for that thread.
+TEST(ThreadLocalTest, DestroysManagedObjectForOwnThreadWhenDying) {
+  DestructorCall::ResetList();
+
+  {
+    ThreadLocal<DestructorTracker> thread_local_tracker;
+    ASSERT_EQ(0U, DestructorCall::List().size());
+
+    // This creates another DestructorTracker object for the main thread.
+    thread_local_tracker.get();
+    ASSERT_EQ(1U, DestructorCall::List().size());
+    ASSERT_FALSE(DestructorCall::List()[0]->CheckDestroyed());
+  }
+
+  // Now thread_local_tracker has died.
+  ASSERT_EQ(1U, DestructorCall::List().size());
+  EXPECT_TRUE(DestructorCall::List()[0]->CheckDestroyed());
+
+  DestructorCall::ResetList();
+}
+
+// Tests that when a thread exits, the thread-local object for that
+// thread is destroyed.
+TEST(ThreadLocalTest, DestroysManagedObjectAtThreadExit) {
+  DestructorCall::ResetList();
+
+  {
+    ThreadLocal<DestructorTracker> thread_local_tracker;
+    ASSERT_EQ(0U, DestructorCall::List().size());
+
+    // This creates another DestructorTracker object in the new thread.
+    ThreadWithParam<ThreadParam> thread(
+        &CallThreadLocalGet, &thread_local_tracker, NULL);
+    thread.Join();
+
+    // The thread has exited, and we should have a DestroyedTracker
+    // instance created for it. But it may not have been destroyed yet.
+    ASSERT_EQ(1U, DestructorCall::List().size());
+  }
+
+  // The thread has exited and thread_local_tracker has died.
+  ASSERT_EQ(1U, DestructorCall::List().size());
+  EXPECT_TRUE(DestructorCall::List()[0]->CheckDestroyed());
+
+  DestructorCall::ResetList();
+}
+
+TEST(ThreadLocalTest, ThreadLocalMutationsAffectOnlyCurrentThread) {
+  ThreadLocal<std::string> thread_local_string;
+  thread_local_string.set("Foo");
+  EXPECT_STREQ("Foo", thread_local_string.get().c_str());
+
+  std::string result;
+  RunFromThread(&RetrieveThreadLocalValue,
+                make_pair(&thread_local_string, &result));
+  EXPECT_TRUE(result.empty());
+}
+
+#endif  // GTEST_IS_THREADSAFE
+
+#if GTEST_OS_WINDOWS
+TEST(WindowsTypesTest, HANDLEIsVoidStar) {
+  StaticAssertTypeEq<HANDLE, void*>();
+}
+
+TEST(WindowsTypesTest, CRITICAL_SECTIONIs_RTL_CRITICAL_SECTION) {
+  StaticAssertTypeEq<CRITICAL_SECTION, _RTL_CRITICAL_SECTION>();
+}
+#endif  // GTEST_OS_WINDOWS
+
+}  // namespace internal
+}  // namespace testing
diff --git a/third_party/googletest/googletest/test/gtest-printers_test.cc b/third_party/googletest/googletest/test/gtest-printers_test.cc
new file mode 100644
index 0000000..3e97cc2
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest-printers_test.cc
@@ -0,0 +1,1635 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Test - The Google C++ Testing Framework
+//
+// This file tests the universal value printer.
+
+#include "gtest/gtest-printers.h"
+
+#include <ctype.h>
+#include <limits.h>
+#include <string.h>
+#include <algorithm>
+#include <deque>
+#include <list>
+#include <map>
+#include <set>
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "gtest/gtest.h"
+
+// hash_map and hash_set are available under Visual C++, or on Linux.
+#if GTEST_HAS_HASH_MAP_
+# include <hash_map>            // NOLINT
+#endif  // GTEST_HAS_HASH_MAP_
+#if GTEST_HAS_HASH_SET_
+# include <hash_set>            // NOLINT
+#endif  // GTEST_HAS_HASH_SET_
+
+#if GTEST_HAS_STD_FORWARD_LIST_
+# include <forward_list> // NOLINT
+#endif  // GTEST_HAS_STD_FORWARD_LIST_
+
+// Some user-defined types for testing the universal value printer.
+
+// An anonymous enum type.
+enum AnonymousEnum {
+  kAE1 = -1,
+  kAE2 = 1
+};
+
+// An enum without a user-defined printer.
+enum EnumWithoutPrinter {
+  kEWP1 = -2,
+  kEWP2 = 42
+};
+
+// An enum with a << operator.
+enum EnumWithStreaming {
+  kEWS1 = 10
+};
+
+std::ostream& operator<<(std::ostream& os, EnumWithStreaming e) {
+  return os << (e == kEWS1 ? "kEWS1" : "invalid");
+}
+
+// An enum with a PrintTo() function.
+enum EnumWithPrintTo {
+  kEWPT1 = 1
+};
+
+void PrintTo(EnumWithPrintTo e, std::ostream* os) {
+  *os << (e == kEWPT1 ? "kEWPT1" : "invalid");
+}
+
+// A class implicitly convertible to BiggestInt.
+class BiggestIntConvertible {
+ public:
+  operator ::testing::internal::BiggestInt() const { return 42; }
+};
+
+// A user-defined unprintable class template in the global namespace.
+template <typename T>
+class UnprintableTemplateInGlobal {
+ public:
+  UnprintableTemplateInGlobal() : value_() {}
+ private:
+  T value_;
+};
+
+// A user-defined streamable type in the global namespace.
+class StreamableInGlobal {
+ public:
+  virtual ~StreamableInGlobal() {}
+};
+
+inline void operator<<(::std::ostream& os, const StreamableInGlobal& /* x */) {
+  os << "StreamableInGlobal";
+}
+
+void operator<<(::std::ostream& os, const StreamableInGlobal* /* x */) {
+  os << "StreamableInGlobal*";
+}
+
+namespace foo {
+
+// A user-defined unprintable type in a user namespace.
+class UnprintableInFoo {
+ public:
+  UnprintableInFoo() : z_(0) { memcpy(xy_, "\xEF\x12\x0\x0\x34\xAB\x0\x0", 8); }
+  double z() const { return z_; }
+ private:
+  char xy_[8];
+  double z_;
+};
+
+// A user-defined printable type in a user-chosen namespace.
+struct PrintableViaPrintTo {
+  PrintableViaPrintTo() : value() {}
+  int value;
+};
+
+void PrintTo(const PrintableViaPrintTo& x, ::std::ostream* os) {
+  *os << "PrintableViaPrintTo: " << x.value;
+}
+
+// A type with a user-defined << for printing its pointer.
+struct PointerPrintable {
+};
+
+::std::ostream& operator<<(::std::ostream& os,
+                           const PointerPrintable* /* x */) {
+  return os << "PointerPrintable*";
+}
+
+// A user-defined printable class template in a user-chosen namespace.
+template <typename T>
+class PrintableViaPrintToTemplate {
+ public:
+  explicit PrintableViaPrintToTemplate(const T& a_value) : value_(a_value) {}
+
+  const T& value() const { return value_; }
+ private:
+  T value_;
+};
+
+template <typename T>
+void PrintTo(const PrintableViaPrintToTemplate<T>& x, ::std::ostream* os) {
+  *os << "PrintableViaPrintToTemplate: " << x.value();
+}
+
+// A user-defined streamable class template in a user namespace.
+template <typename T>
+class StreamableTemplateInFoo {
+ public:
+  StreamableTemplateInFoo() : value_() {}
+
+  const T& value() const { return value_; }
+ private:
+  T value_;
+};
+
+template <typename T>
+inline ::std::ostream& operator<<(::std::ostream& os,
+                                  const StreamableTemplateInFoo<T>& x) {
+  return os << "StreamableTemplateInFoo: " << x.value();
+}
+
+}  // namespace foo
+
+namespace testing {
+namespace gtest_printers_test {
+
+using ::std::deque;
+using ::std::list;
+using ::std::make_pair;
+using ::std::map;
+using ::std::multimap;
+using ::std::multiset;
+using ::std::pair;
+using ::std::set;
+using ::std::vector;
+using ::testing::PrintToString;
+using ::testing::internal::FormatForComparisonFailureMessage;
+using ::testing::internal::ImplicitCast_;
+using ::testing::internal::NativeArray;
+using ::testing::internal::RE;
+using ::testing::internal::RelationToSourceReference;
+using ::testing::internal::Strings;
+using ::testing::internal::UniversalPrint;
+using ::testing::internal::UniversalPrinter;
+using ::testing::internal::UniversalTersePrint;
+using ::testing::internal::UniversalTersePrintTupleFieldsToStrings;
+using ::testing::internal::string;
+
+// The hash_* classes are not part of the C++ standard.  STLport
+// defines them in namespace std.  MSVC defines them in ::stdext.  GCC
+// defines them in ::.
+#ifdef _STLP_HASH_MAP  // We got <hash_map> from STLport.
+using ::std::hash_map;
+using ::std::hash_set;
+using ::std::hash_multimap;
+using ::std::hash_multiset;
+#elif _MSC_VER
+using ::stdext::hash_map;
+using ::stdext::hash_set;
+using ::stdext::hash_multimap;
+using ::stdext::hash_multiset;
+#endif
+
+// Prints a value to a string using the universal value printer.  This
+// is a helper for testing UniversalPrinter<T>::Print() for various types.
+template <typename T>
+string Print(const T& value) {
+  ::std::stringstream ss;
+  UniversalPrinter<T>::Print(value, &ss);
+  return ss.str();
+}
+
+// Prints a value passed by reference to a string, using the universal
+// value printer.  This is a helper for testing
+// UniversalPrinter<T&>::Print() for various types.
+template <typename T>
+string PrintByRef(const T& value) {
+  ::std::stringstream ss;
+  UniversalPrinter<T&>::Print(value, &ss);
+  return ss.str();
+}
+
+// Tests printing various enum types.
+
+TEST(PrintEnumTest, AnonymousEnum) {
+  EXPECT_EQ("-1", Print(kAE1));
+  EXPECT_EQ("1", Print(kAE2));
+}
+
+TEST(PrintEnumTest, EnumWithoutPrinter) {
+  EXPECT_EQ("-2", Print(kEWP1));
+  EXPECT_EQ("42", Print(kEWP2));
+}
+
+TEST(PrintEnumTest, EnumWithStreaming) {
+  EXPECT_EQ("kEWS1", Print(kEWS1));
+  EXPECT_EQ("invalid", Print(static_cast<EnumWithStreaming>(0)));
+}
+
+TEST(PrintEnumTest, EnumWithPrintTo) {
+  EXPECT_EQ("kEWPT1", Print(kEWPT1));
+  EXPECT_EQ("invalid", Print(static_cast<EnumWithPrintTo>(0)));
+}
+
+// Tests printing a class implicitly convertible to BiggestInt.
+
+TEST(PrintClassTest, BiggestIntConvertible) {
+  EXPECT_EQ("42", Print(BiggestIntConvertible()));
+}
+
+// Tests printing various char types.
+
+// char.
+TEST(PrintCharTest, PlainChar) {
+  EXPECT_EQ("'\\0'", Print('\0'));
+  EXPECT_EQ("'\\'' (39, 0x27)", Print('\''));
+  EXPECT_EQ("'\"' (34, 0x22)", Print('"'));
+  EXPECT_EQ("'?' (63, 0x3F)", Print('?'));
+  EXPECT_EQ("'\\\\' (92, 0x5C)", Print('\\'));
+  EXPECT_EQ("'\\a' (7)", Print('\a'));
+  EXPECT_EQ("'\\b' (8)", Print('\b'));
+  EXPECT_EQ("'\\f' (12, 0xC)", Print('\f'));
+  EXPECT_EQ("'\\n' (10, 0xA)", Print('\n'));
+  EXPECT_EQ("'\\r' (13, 0xD)", Print('\r'));
+  EXPECT_EQ("'\\t' (9)", Print('\t'));
+  EXPECT_EQ("'\\v' (11, 0xB)", Print('\v'));
+  EXPECT_EQ("'\\x7F' (127)", Print('\x7F'));
+  EXPECT_EQ("'\\xFF' (255)", Print('\xFF'));
+  EXPECT_EQ("' ' (32, 0x20)", Print(' '));
+  EXPECT_EQ("'a' (97, 0x61)", Print('a'));
+}
+
+// signed char.
+TEST(PrintCharTest, SignedChar) {
+  EXPECT_EQ("'\\0'", Print(static_cast<signed char>('\0')));
+  EXPECT_EQ("'\\xCE' (-50)",
+            Print(static_cast<signed char>(-50)));
+}
+
+// unsigned char.
+TEST(PrintCharTest, UnsignedChar) {
+  EXPECT_EQ("'\\0'", Print(static_cast<unsigned char>('\0')));
+  EXPECT_EQ("'b' (98, 0x62)",
+            Print(static_cast<unsigned char>('b')));
+}
+
+// Tests printing other simple, built-in types.
+
+// bool.
+TEST(PrintBuiltInTypeTest, Bool) {
+  EXPECT_EQ("false", Print(false));
+  EXPECT_EQ("true", Print(true));
+}
+
+// wchar_t.
+TEST(PrintBuiltInTypeTest, Wchar_t) {
+  EXPECT_EQ("L'\\0'", Print(L'\0'));
+  EXPECT_EQ("L'\\'' (39, 0x27)", Print(L'\''));
+  EXPECT_EQ("L'\"' (34, 0x22)", Print(L'"'));
+  EXPECT_EQ("L'?' (63, 0x3F)", Print(L'?'));
+  EXPECT_EQ("L'\\\\' (92, 0x5C)", Print(L'\\'));
+  EXPECT_EQ("L'\\a' (7)", Print(L'\a'));
+  EXPECT_EQ("L'\\b' (8)", Print(L'\b'));
+  EXPECT_EQ("L'\\f' (12, 0xC)", Print(L'\f'));
+  EXPECT_EQ("L'\\n' (10, 0xA)", Print(L'\n'));
+  EXPECT_EQ("L'\\r' (13, 0xD)", Print(L'\r'));
+  EXPECT_EQ("L'\\t' (9)", Print(L'\t'));
+  EXPECT_EQ("L'\\v' (11, 0xB)", Print(L'\v'));
+  EXPECT_EQ("L'\\x7F' (127)", Print(L'\x7F'));
+  EXPECT_EQ("L'\\xFF' (255)", Print(L'\xFF'));
+  EXPECT_EQ("L' ' (32, 0x20)", Print(L' '));
+  EXPECT_EQ("L'a' (97, 0x61)", Print(L'a'));
+  EXPECT_EQ("L'\\x576' (1398)", Print(static_cast<wchar_t>(0x576)));
+  EXPECT_EQ("L'\\xC74D' (51021)", Print(static_cast<wchar_t>(0xC74D)));
+}
+
+// Test that Int64 provides more storage than wchar_t.
+TEST(PrintTypeSizeTest, Wchar_t) {
+  EXPECT_LT(sizeof(wchar_t), sizeof(testing::internal::Int64));
+}
+
+// Various integer types.
+TEST(PrintBuiltInTypeTest, Integer) {
+  EXPECT_EQ("'\\xFF' (255)", Print(static_cast<unsigned char>(255)));  // uint8
+  EXPECT_EQ("'\\x80' (-128)", Print(static_cast<signed char>(-128)));  // int8
+  EXPECT_EQ("65535", Print(USHRT_MAX));  // uint16
+  EXPECT_EQ("-32768", Print(SHRT_MIN));  // int16
+  EXPECT_EQ("4294967295", Print(UINT_MAX));  // uint32
+  EXPECT_EQ("-2147483648", Print(INT_MIN));  // int32
+  EXPECT_EQ("18446744073709551615",
+            Print(static_cast<testing::internal::UInt64>(-1)));  // uint64
+  EXPECT_EQ("-9223372036854775808",
+            Print(static_cast<testing::internal::Int64>(1) << 63));  // int64
+}
+
+// Size types.
+TEST(PrintBuiltInTypeTest, Size_t) {
+  EXPECT_EQ("1", Print(sizeof('a')));  // size_t.
+#if !GTEST_OS_WINDOWS
+  // Windows has no ssize_t type.
+  EXPECT_EQ("-2", Print(static_cast<ssize_t>(-2)));  // ssize_t.
+#endif  // !GTEST_OS_WINDOWS
+}
+
+// Floating-points.
+TEST(PrintBuiltInTypeTest, FloatingPoints) {
+  EXPECT_EQ("1.5", Print(1.5f));   // float
+  EXPECT_EQ("-2.5", Print(-2.5));  // double
+}
+
+// Since ::std::stringstream::operator<<(const void *) formats the pointer
+// output differently with different compilers, we have to create the expected
+// output first and use it as our expectation.
+static string PrintPointer(const void *p) {
+  ::std::stringstream expected_result_stream;
+  expected_result_stream << p;
+  return expected_result_stream.str();
+}
+
+// Tests printing C strings.
+
+// const char*.
+TEST(PrintCStringTest, Const) {
+  const char* p = "World";
+  EXPECT_EQ(PrintPointer(p) + " pointing to \"World\"", Print(p));
+}
+
+// char*.
+TEST(PrintCStringTest, NonConst) {
+  char p[] = "Hi";
+  EXPECT_EQ(PrintPointer(p) + " pointing to \"Hi\"",
+            Print(static_cast<char*>(p)));
+}
+
+// NULL C string.
+TEST(PrintCStringTest, Null) {
+  const char* p = NULL;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// Tests that C strings are escaped properly.
+TEST(PrintCStringTest, EscapesProperly) {
+  const char* p = "'\"?\\\a\b\f\n\r\t\v\x7F\xFF a";
+  EXPECT_EQ(PrintPointer(p) + " pointing to \"'\\\"?\\\\\\a\\b\\f"
+            "\\n\\r\\t\\v\\x7F\\xFF a\"",
+            Print(p));
+}
+
+// MSVC compiler can be configured to define whar_t as a typedef
+// of unsigned short. Defining an overload for const wchar_t* in that case
+// would cause pointers to unsigned shorts be printed as wide strings,
+// possibly accessing more memory than intended and causing invalid
+// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
+// wchar_t is implemented as a native type.
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+
+// const wchar_t*.
+TEST(PrintWideCStringTest, Const) {
+  const wchar_t* p = L"World";
+  EXPECT_EQ(PrintPointer(p) + " pointing to L\"World\"", Print(p));
+}
+
+// wchar_t*.
+TEST(PrintWideCStringTest, NonConst) {
+  wchar_t p[] = L"Hi";
+  EXPECT_EQ(PrintPointer(p) + " pointing to L\"Hi\"",
+            Print(static_cast<wchar_t*>(p)));
+}
+
+// NULL wide C string.
+TEST(PrintWideCStringTest, Null) {
+  const wchar_t* p = NULL;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// Tests that wide C strings are escaped properly.
+TEST(PrintWideCStringTest, EscapesProperly) {
+  const wchar_t s[] = {'\'', '"', '?', '\\', '\a', '\b', '\f', '\n', '\r',
+                       '\t', '\v', 0xD3, 0x576, 0x8D3, 0xC74D, ' ', 'a', '\0'};
+  EXPECT_EQ(PrintPointer(s) + " pointing to L\"'\\\"?\\\\\\a\\b\\f"
+            "\\n\\r\\t\\v\\xD3\\x576\\x8D3\\xC74D a\"",
+            Print(static_cast<const wchar_t*>(s)));
+}
+#endif  // native wchar_t
+
+// Tests printing pointers to other char types.
+
+// signed char*.
+TEST(PrintCharPointerTest, SignedChar) {
+  signed char* p = reinterpret_cast<signed char*>(0x1234);
+  EXPECT_EQ(PrintPointer(p), Print(p));
+  p = NULL;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// const signed char*.
+TEST(PrintCharPointerTest, ConstSignedChar) {
+  signed char* p = reinterpret_cast<signed char*>(0x1234);
+  EXPECT_EQ(PrintPointer(p), Print(p));
+  p = NULL;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// unsigned char*.
+TEST(PrintCharPointerTest, UnsignedChar) {
+  unsigned char* p = reinterpret_cast<unsigned char*>(0x1234);
+  EXPECT_EQ(PrintPointer(p), Print(p));
+  p = NULL;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// const unsigned char*.
+TEST(PrintCharPointerTest, ConstUnsignedChar) {
+  const unsigned char* p = reinterpret_cast<const unsigned char*>(0x1234);
+  EXPECT_EQ(PrintPointer(p), Print(p));
+  p = NULL;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// Tests printing pointers to simple, built-in types.
+
+// bool*.
+TEST(PrintPointerToBuiltInTypeTest, Bool) {
+  bool* p = reinterpret_cast<bool*>(0xABCD);
+  EXPECT_EQ(PrintPointer(p), Print(p));
+  p = NULL;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// void*.
+TEST(PrintPointerToBuiltInTypeTest, Void) {
+  void* p = reinterpret_cast<void*>(0xABCD);
+  EXPECT_EQ(PrintPointer(p), Print(p));
+  p = NULL;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// const void*.
+TEST(PrintPointerToBuiltInTypeTest, ConstVoid) {
+  const void* p = reinterpret_cast<const void*>(0xABCD);
+  EXPECT_EQ(PrintPointer(p), Print(p));
+  p = NULL;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// Tests printing pointers to pointers.
+TEST(PrintPointerToPointerTest, IntPointerPointer) {
+  int** p = reinterpret_cast<int**>(0xABCD);
+  EXPECT_EQ(PrintPointer(p), Print(p));
+  p = NULL;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// Tests printing (non-member) function pointers.
+
+void MyFunction(int /* n */) {}
+
+TEST(PrintPointerTest, NonMemberFunctionPointer) {
+  // We cannot directly cast &MyFunction to const void* because the
+  // standard disallows casting between pointers to functions and
+  // pointers to objects, and some compilers (e.g. GCC 3.4) enforce
+  // this limitation.
+  EXPECT_EQ(
+      PrintPointer(reinterpret_cast<const void*>(
+          reinterpret_cast<internal::BiggestInt>(&MyFunction))),
+      Print(&MyFunction));
+  int (*p)(bool) = NULL;  // NOLINT
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// An assertion predicate determining whether a one string is a prefix for
+// another.
+template <typename StringType>
+AssertionResult HasPrefix(const StringType& str, const StringType& prefix) {
+  if (str.find(prefix, 0) == 0)
+    return AssertionSuccess();
+
+  const bool is_wide_string = sizeof(prefix[0]) > 1;
+  const char* const begin_string_quote = is_wide_string ? "L\"" : "\"";
+  return AssertionFailure()
+      << begin_string_quote << prefix << "\" is not a prefix of "
+      << begin_string_quote << str << "\"\n";
+}
+
+// Tests printing member variable pointers.  Although they are called
+// pointers, they don't point to a location in the address space.
+// Their representation is implementation-defined.  Thus they will be
+// printed as raw bytes.
+
+struct Foo {
+ public:
+  virtual ~Foo() {}
+  int MyMethod(char x) { return x + 1; }
+  virtual char MyVirtualMethod(int /* n */) { return 'a'; }
+
+  int value;
+};
+
+TEST(PrintPointerTest, MemberVariablePointer) {
+  EXPECT_TRUE(HasPrefix(Print(&Foo::value),
+                        Print(sizeof(&Foo::value)) + "-byte object "));
+  int (Foo::*p) = NULL;  // NOLINT
+  EXPECT_TRUE(HasPrefix(Print(p),
+                        Print(sizeof(p)) + "-byte object "));
+}
+
+// Tests printing member function pointers.  Although they are called
+// pointers, they don't point to a location in the address space.
+// Their representation is implementation-defined.  Thus they will be
+// printed as raw bytes.
+TEST(PrintPointerTest, MemberFunctionPointer) {
+  EXPECT_TRUE(HasPrefix(Print(&Foo::MyMethod),
+                        Print(sizeof(&Foo::MyMethod)) + "-byte object "));
+  EXPECT_TRUE(
+      HasPrefix(Print(&Foo::MyVirtualMethod),
+                Print(sizeof((&Foo::MyVirtualMethod))) + "-byte object "));
+  int (Foo::*p)(char) = NULL;  // NOLINT
+  EXPECT_TRUE(HasPrefix(Print(p),
+                        Print(sizeof(p)) + "-byte object "));
+}
+
+// Tests printing C arrays.
+
+// The difference between this and Print() is that it ensures that the
+// argument is a reference to an array.
+template <typename T, size_t N>
+string PrintArrayHelper(T (&a)[N]) {
+  return Print(a);
+}
+
+// One-dimensional array.
+TEST(PrintArrayTest, OneDimensionalArray) {
+  int a[5] = { 1, 2, 3, 4, 5 };
+  EXPECT_EQ("{ 1, 2, 3, 4, 5 }", PrintArrayHelper(a));
+}
+
+// Two-dimensional array.
+TEST(PrintArrayTest, TwoDimensionalArray) {
+  int a[2][5] = {
+    { 1, 2, 3, 4, 5 },
+    { 6, 7, 8, 9, 0 }
+  };
+  EXPECT_EQ("{ { 1, 2, 3, 4, 5 }, { 6, 7, 8, 9, 0 } }", PrintArrayHelper(a));
+}
+
+// Array of const elements.
+TEST(PrintArrayTest, ConstArray) {
+  const bool a[1] = { false };
+  EXPECT_EQ("{ false }", PrintArrayHelper(a));
+}
+
+// char array without terminating NUL.
+TEST(PrintArrayTest, CharArrayWithNoTerminatingNul) {
+  // Array a contains '\0' in the middle and doesn't end with '\0'.
+  char a[] = { 'H', '\0', 'i' };
+  EXPECT_EQ("\"H\\0i\" (no terminating NUL)", PrintArrayHelper(a));
+}
+
+// const char array with terminating NUL.
+TEST(PrintArrayTest, ConstCharArrayWithTerminatingNul) {
+  const char a[] = "\0Hi";
+  EXPECT_EQ("\"\\0Hi\"", PrintArrayHelper(a));
+}
+
+// const wchar_t array without terminating NUL.
+TEST(PrintArrayTest, WCharArrayWithNoTerminatingNul) {
+  // Array a contains '\0' in the middle and doesn't end with '\0'.
+  const wchar_t a[] = { L'H', L'\0', L'i' };
+  EXPECT_EQ("L\"H\\0i\" (no terminating NUL)", PrintArrayHelper(a));
+}
+
+// wchar_t array with terminating NUL.
+TEST(PrintArrayTest, WConstCharArrayWithTerminatingNul) {
+  const wchar_t a[] = L"\0Hi";
+  EXPECT_EQ("L\"\\0Hi\"", PrintArrayHelper(a));
+}
+
+// Array of objects.
+TEST(PrintArrayTest, ObjectArray) {
+  string a[3] = { "Hi", "Hello", "Ni hao" };
+  EXPECT_EQ("{ \"Hi\", \"Hello\", \"Ni hao\" }", PrintArrayHelper(a));
+}
+
+// Array with many elements.
+TEST(PrintArrayTest, BigArray) {
+  int a[100] = { 1, 2, 3 };
+  EXPECT_EQ("{ 1, 2, 3, 0, 0, 0, 0, 0, ..., 0, 0, 0, 0, 0, 0, 0, 0 }",
+            PrintArrayHelper(a));
+}
+
+// Tests printing ::string and ::std::string.
+
+#if GTEST_HAS_GLOBAL_STRING
+// ::string.
+TEST(PrintStringTest, StringInGlobalNamespace) {
+  const char s[] = "'\"?\\\a\b\f\n\0\r\t\v\x7F\xFF a";
+  const ::string str(s, sizeof(s));
+  EXPECT_EQ("\"'\\\"?\\\\\\a\\b\\f\\n\\0\\r\\t\\v\\x7F\\xFF a\\0\"",
+            Print(str));
+}
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+// ::std::string.
+TEST(PrintStringTest, StringInStdNamespace) {
+  const char s[] = "'\"?\\\a\b\f\n\0\r\t\v\x7F\xFF a";
+  const ::std::string str(s, sizeof(s));
+  EXPECT_EQ("\"'\\\"?\\\\\\a\\b\\f\\n\\0\\r\\t\\v\\x7F\\xFF a\\0\"",
+            Print(str));
+}
+
+TEST(PrintStringTest, StringAmbiguousHex) {
+  // "\x6BANANA" is ambiguous, it can be interpreted as starting with either of:
+  // '\x6', '\x6B', or '\x6BA'.
+
+  // a hex escaping sequence following by a decimal digit
+  EXPECT_EQ("\"0\\x12\" \"3\"", Print(::std::string("0\x12" "3")));
+  // a hex escaping sequence following by a hex digit (lower-case)
+  EXPECT_EQ("\"mm\\x6\" \"bananas\"", Print(::std::string("mm\x6" "bananas")));
+  // a hex escaping sequence following by a hex digit (upper-case)
+  EXPECT_EQ("\"NOM\\x6\" \"BANANA\"", Print(::std::string("NOM\x6" "BANANA")));
+  // a hex escaping sequence following by a non-xdigit
+  EXPECT_EQ("\"!\\x5-!\"", Print(::std::string("!\x5-!")));
+}
+
+// Tests printing ::wstring and ::std::wstring.
+
+#if GTEST_HAS_GLOBAL_WSTRING
+// ::wstring.
+TEST(PrintWideStringTest, StringInGlobalNamespace) {
+  const wchar_t s[] = L"'\"?\\\a\b\f\n\0\r\t\v\xD3\x576\x8D3\xC74D a";
+  const ::wstring str(s, sizeof(s)/sizeof(wchar_t));
+  EXPECT_EQ("L\"'\\\"?\\\\\\a\\b\\f\\n\\0\\r\\t\\v"
+            "\\xD3\\x576\\x8D3\\xC74D a\\0\"",
+            Print(str));
+}
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+#if GTEST_HAS_STD_WSTRING
+// ::std::wstring.
+TEST(PrintWideStringTest, StringInStdNamespace) {
+  const wchar_t s[] = L"'\"?\\\a\b\f\n\0\r\t\v\xD3\x576\x8D3\xC74D a";
+  const ::std::wstring str(s, sizeof(s)/sizeof(wchar_t));
+  EXPECT_EQ("L\"'\\\"?\\\\\\a\\b\\f\\n\\0\\r\\t\\v"
+            "\\xD3\\x576\\x8D3\\xC74D a\\0\"",
+            Print(str));
+}
+
+TEST(PrintWideStringTest, StringAmbiguousHex) {
+  // same for wide strings.
+  EXPECT_EQ("L\"0\\x12\" L\"3\"", Print(::std::wstring(L"0\x12" L"3")));
+  EXPECT_EQ("L\"mm\\x6\" L\"bananas\"",
+            Print(::std::wstring(L"mm\x6" L"bananas")));
+  EXPECT_EQ("L\"NOM\\x6\" L\"BANANA\"",
+            Print(::std::wstring(L"NOM\x6" L"BANANA")));
+  EXPECT_EQ("L\"!\\x5-!\"", Print(::std::wstring(L"!\x5-!")));
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+// Tests printing types that support generic streaming (i.e. streaming
+// to std::basic_ostream<Char, CharTraits> for any valid Char and
+// CharTraits types).
+
+// Tests printing a non-template type that supports generic streaming.
+
+class AllowsGenericStreaming {};
+
+template <typename Char, typename CharTraits>
+std::basic_ostream<Char, CharTraits>& operator<<(
+    std::basic_ostream<Char, CharTraits>& os,
+    const AllowsGenericStreaming& /* a */) {
+  return os << "AllowsGenericStreaming";
+}
+
+TEST(PrintTypeWithGenericStreamingTest, NonTemplateType) {
+  AllowsGenericStreaming a;
+  EXPECT_EQ("AllowsGenericStreaming", Print(a));
+}
+
+// Tests printing a template type that supports generic streaming.
+
+template <typename T>
+class AllowsGenericStreamingTemplate {};
+
+template <typename Char, typename CharTraits, typename T>
+std::basic_ostream<Char, CharTraits>& operator<<(
+    std::basic_ostream<Char, CharTraits>& os,
+    const AllowsGenericStreamingTemplate<T>& /* a */) {
+  return os << "AllowsGenericStreamingTemplate";
+}
+
+TEST(PrintTypeWithGenericStreamingTest, TemplateType) {
+  AllowsGenericStreamingTemplate<int> a;
+  EXPECT_EQ("AllowsGenericStreamingTemplate", Print(a));
+}
+
+// Tests printing a type that supports generic streaming and can be
+// implicitly converted to another printable type.
+
+template <typename T>
+class AllowsGenericStreamingAndImplicitConversionTemplate {
+ public:
+  operator bool() const { return false; }
+};
+
+template <typename Char, typename CharTraits, typename T>
+std::basic_ostream<Char, CharTraits>& operator<<(
+    std::basic_ostream<Char, CharTraits>& os,
+    const AllowsGenericStreamingAndImplicitConversionTemplate<T>& /* a */) {
+  return os << "AllowsGenericStreamingAndImplicitConversionTemplate";
+}
+
+TEST(PrintTypeWithGenericStreamingTest, TypeImplicitlyConvertible) {
+  AllowsGenericStreamingAndImplicitConversionTemplate<int> a;
+  EXPECT_EQ("AllowsGenericStreamingAndImplicitConversionTemplate", Print(a));
+}
+
+#if GTEST_HAS_STRING_PIECE_
+
+// Tests printing StringPiece.
+
+TEST(PrintStringPieceTest, SimpleStringPiece) {
+  const StringPiece sp = "Hello";
+  EXPECT_EQ("\"Hello\"", Print(sp));
+}
+
+TEST(PrintStringPieceTest, UnprintableCharacters) {
+  const char str[] = "NUL (\0) and \r\t";
+  const StringPiece sp(str, sizeof(str) - 1);
+  EXPECT_EQ("\"NUL (\\0) and \\r\\t\"", Print(sp));
+}
+
+#endif  // GTEST_HAS_STRING_PIECE_
+
+// Tests printing STL containers.
+
+TEST(PrintStlContainerTest, EmptyDeque) {
+  deque<char> empty;
+  EXPECT_EQ("{}", Print(empty));
+}
+
+TEST(PrintStlContainerTest, NonEmptyDeque) {
+  deque<int> non_empty;
+  non_empty.push_back(1);
+  non_empty.push_back(3);
+  EXPECT_EQ("{ 1, 3 }", Print(non_empty));
+}
+
+#if GTEST_HAS_HASH_MAP_
+
+TEST(PrintStlContainerTest, OneElementHashMap) {
+  hash_map<int, char> map1;
+  map1[1] = 'a';
+  EXPECT_EQ("{ (1, 'a' (97, 0x61)) }", Print(map1));
+}
+
+TEST(PrintStlContainerTest, HashMultiMap) {
+  hash_multimap<int, bool> map1;
+  map1.insert(make_pair(5, true));
+  map1.insert(make_pair(5, false));
+
+  // Elements of hash_multimap can be printed in any order.
+  const string result = Print(map1);
+  EXPECT_TRUE(result == "{ (5, true), (5, false) }" ||
+              result == "{ (5, false), (5, true) }")
+                  << " where Print(map1) returns \"" << result << "\".";
+}
+
+#endif  // GTEST_HAS_HASH_MAP_
+
+#if GTEST_HAS_HASH_SET_
+
+TEST(PrintStlContainerTest, HashSet) {
+  hash_set<string> set1;
+  set1.insert("hello");
+  EXPECT_EQ("{ \"hello\" }", Print(set1));
+}
+
+TEST(PrintStlContainerTest, HashMultiSet) {
+  const int kSize = 5;
+  int a[kSize] = { 1, 1, 2, 5, 1 };
+  hash_multiset<int> set1(a, a + kSize);
+
+  // Elements of hash_multiset can be printed in any order.
+  const string result = Print(set1);
+  const string expected_pattern = "{ d, d, d, d, d }";  // d means a digit.
+
+  // Verifies the result matches the expected pattern; also extracts
+  // the numbers in the result.
+  ASSERT_EQ(expected_pattern.length(), result.length());
+  std::vector<int> numbers;
+  for (size_t i = 0; i != result.length(); i++) {
+    if (expected_pattern[i] == 'd') {
+      ASSERT_NE(isdigit(static_cast<unsigned char>(result[i])), 0);
+      numbers.push_back(result[i] - '0');
+    } else {
+      EXPECT_EQ(expected_pattern[i], result[i]) << " where result is "
+                                                << result;
+    }
+  }
+
+  // Makes sure the result contains the right numbers.
+  std::sort(numbers.begin(), numbers.end());
+  std::sort(a, a + kSize);
+  EXPECT_TRUE(std::equal(a, a + kSize, numbers.begin()));
+}
+
+#endif  // GTEST_HAS_HASH_SET_
+
+TEST(PrintStlContainerTest, List) {
+  const string a[] = {
+    "hello",
+    "world"
+  };
+  const list<string> strings(a, a + 2);
+  EXPECT_EQ("{ \"hello\", \"world\" }", Print(strings));
+}
+
+TEST(PrintStlContainerTest, Map) {
+  map<int, bool> map1;
+  map1[1] = true;
+  map1[5] = false;
+  map1[3] = true;
+  EXPECT_EQ("{ (1, true), (3, true), (5, false) }", Print(map1));
+}
+
+TEST(PrintStlContainerTest, MultiMap) {
+  multimap<bool, int> map1;
+  // The make_pair template function would deduce the type as
+  // pair<bool, int> here, and since the key part in a multimap has to
+  // be constant, without a templated ctor in the pair class (as in
+  // libCstd on Solaris), make_pair call would fail to compile as no
+  // implicit conversion is found.  Thus explicit typename is used
+  // here instead.
+  map1.insert(pair<const bool, int>(true, 0));
+  map1.insert(pair<const bool, int>(true, 1));
+  map1.insert(pair<const bool, int>(false, 2));
+  EXPECT_EQ("{ (false, 2), (true, 0), (true, 1) }", Print(map1));
+}
+
+TEST(PrintStlContainerTest, Set) {
+  const unsigned int a[] = { 3, 0, 5 };
+  set<unsigned int> set1(a, a + 3);
+  EXPECT_EQ("{ 0, 3, 5 }", Print(set1));
+}
+
+TEST(PrintStlContainerTest, MultiSet) {
+  const int a[] = { 1, 1, 2, 5, 1 };
+  multiset<int> set1(a, a + 5);
+  EXPECT_EQ("{ 1, 1, 1, 2, 5 }", Print(set1));
+}
+
+#if GTEST_HAS_STD_FORWARD_LIST_
+// <slist> is available on Linux in the google3 mode, but not on
+// Windows or Mac OS X.
+
+TEST(PrintStlContainerTest, SinglyLinkedList) {
+  int a[] = { 9, 2, 8 };
+  const std::forward_list<int> ints(a, a + 3);
+  EXPECT_EQ("{ 9, 2, 8 }", Print(ints));
+}
+#endif  // GTEST_HAS_STD_FORWARD_LIST_
+
+TEST(PrintStlContainerTest, Pair) {
+  pair<const bool, int> p(true, 5);
+  EXPECT_EQ("(true, 5)", Print(p));
+}
+
+TEST(PrintStlContainerTest, Vector) {
+  vector<int> v;
+  v.push_back(1);
+  v.push_back(2);
+  EXPECT_EQ("{ 1, 2 }", Print(v));
+}
+
+TEST(PrintStlContainerTest, LongSequence) {
+  const int a[100] = { 1, 2, 3 };
+  const vector<int> v(a, a + 100);
+  EXPECT_EQ("{ 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "
+            "0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... }", Print(v));
+}
+
+TEST(PrintStlContainerTest, NestedContainer) {
+  const int a1[] = { 1, 2 };
+  const int a2[] = { 3, 4, 5 };
+  const list<int> l1(a1, a1 + 2);
+  const list<int> l2(a2, a2 + 3);
+
+  vector<list<int> > v;
+  v.push_back(l1);
+  v.push_back(l2);
+  EXPECT_EQ("{ { 1, 2 }, { 3, 4, 5 } }", Print(v));
+}
+
+TEST(PrintStlContainerTest, OneDimensionalNativeArray) {
+  const int a[3] = { 1, 2, 3 };
+  NativeArray<int> b(a, 3, RelationToSourceReference());
+  EXPECT_EQ("{ 1, 2, 3 }", Print(b));
+}
+
+TEST(PrintStlContainerTest, TwoDimensionalNativeArray) {
+  const int a[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
+  NativeArray<int[3]> b(a, 2, RelationToSourceReference());
+  EXPECT_EQ("{ { 1, 2, 3 }, { 4, 5, 6 } }", Print(b));
+}
+
+// Tests that a class named iterator isn't treated as a container.
+
+struct iterator {
+  char x;
+};
+
+TEST(PrintStlContainerTest, Iterator) {
+  iterator it = {};
+  EXPECT_EQ("1-byte object <00>", Print(it));
+}
+
+// Tests that a class named const_iterator isn't treated as a container.
+
+struct const_iterator {
+  char x;
+};
+
+TEST(PrintStlContainerTest, ConstIterator) {
+  const_iterator it = {};
+  EXPECT_EQ("1-byte object <00>", Print(it));
+}
+
+#if GTEST_HAS_TR1_TUPLE
+// Tests printing ::std::tr1::tuples.
+
+// Tuples of various arities.
+TEST(PrintTr1TupleTest, VariousSizes) {
+  ::std::tr1::tuple<> t0;
+  EXPECT_EQ("()", Print(t0));
+
+  ::std::tr1::tuple<int> t1(5);
+  EXPECT_EQ("(5)", Print(t1));
+
+  ::std::tr1::tuple<char, bool> t2('a', true);
+  EXPECT_EQ("('a' (97, 0x61), true)", Print(t2));
+
+  ::std::tr1::tuple<bool, int, int> t3(false, 2, 3);
+  EXPECT_EQ("(false, 2, 3)", Print(t3));
+
+  ::std::tr1::tuple<bool, int, int, int> t4(false, 2, 3, 4);
+  EXPECT_EQ("(false, 2, 3, 4)", Print(t4));
+
+  ::std::tr1::tuple<bool, int, int, int, bool> t5(false, 2, 3, 4, true);
+  EXPECT_EQ("(false, 2, 3, 4, true)", Print(t5));
+
+  ::std::tr1::tuple<bool, int, int, int, bool, int> t6(false, 2, 3, 4, true, 6);
+  EXPECT_EQ("(false, 2, 3, 4, true, 6)", Print(t6));
+
+  ::std::tr1::tuple<bool, int, int, int, bool, int, int> t7(
+      false, 2, 3, 4, true, 6, 7);
+  EXPECT_EQ("(false, 2, 3, 4, true, 6, 7)", Print(t7));
+
+  ::std::tr1::tuple<bool, int, int, int, bool, int, int, bool> t8(
+      false, 2, 3, 4, true, 6, 7, true);
+  EXPECT_EQ("(false, 2, 3, 4, true, 6, 7, true)", Print(t8));
+
+  ::std::tr1::tuple<bool, int, int, int, bool, int, int, bool, int> t9(
+      false, 2, 3, 4, true, 6, 7, true, 9);
+  EXPECT_EQ("(false, 2, 3, 4, true, 6, 7, true, 9)", Print(t9));
+
+  const char* const str = "8";
+  // VC++ 2010's implementation of tuple of C++0x is deficient, requiring
+  // an explicit type cast of NULL to be used.
+  ::std::tr1::tuple<bool, char, short, testing::internal::Int32,  // NOLINT
+      testing::internal::Int64, float, double, const char*, void*, string>
+      t10(false, 'a', 3, 4, 5, 1.5F, -2.5, str,
+          ImplicitCast_<void*>(NULL), "10");
+  EXPECT_EQ("(false, 'a' (97, 0x61), 3, 4, 5, 1.5, -2.5, " + PrintPointer(str) +
+            " pointing to \"8\", NULL, \"10\")",
+            Print(t10));
+}
+
+// Nested tuples.
+TEST(PrintTr1TupleTest, NestedTuple) {
+  ::std::tr1::tuple< ::std::tr1::tuple<int, bool>, char> nested(
+      ::std::tr1::make_tuple(5, true), 'a');
+  EXPECT_EQ("((5, true), 'a' (97, 0x61))", Print(nested));
+}
+
+#endif  // GTEST_HAS_TR1_TUPLE
+
+#if GTEST_HAS_STD_TUPLE_
+// Tests printing ::std::tuples.
+
+// Tuples of various arities.
+TEST(PrintStdTupleTest, VariousSizes) {
+  ::std::tuple<> t0;
+  EXPECT_EQ("()", Print(t0));
+
+  ::std::tuple<int> t1(5);
+  EXPECT_EQ("(5)", Print(t1));
+
+  ::std::tuple<char, bool> t2('a', true);
+  EXPECT_EQ("('a' (97, 0x61), true)", Print(t2));
+
+  ::std::tuple<bool, int, int> t3(false, 2, 3);
+  EXPECT_EQ("(false, 2, 3)", Print(t3));
+
+  ::std::tuple<bool, int, int, int> t4(false, 2, 3, 4);
+  EXPECT_EQ("(false, 2, 3, 4)", Print(t4));
+
+  ::std::tuple<bool, int, int, int, bool> t5(false, 2, 3, 4, true);
+  EXPECT_EQ("(false, 2, 3, 4, true)", Print(t5));
+
+  ::std::tuple<bool, int, int, int, bool, int> t6(false, 2, 3, 4, true, 6);
+  EXPECT_EQ("(false, 2, 3, 4, true, 6)", Print(t6));
+
+  ::std::tuple<bool, int, int, int, bool, int, int> t7(
+      false, 2, 3, 4, true, 6, 7);
+  EXPECT_EQ("(false, 2, 3, 4, true, 6, 7)", Print(t7));
+
+  ::std::tuple<bool, int, int, int, bool, int, int, bool> t8(
+      false, 2, 3, 4, true, 6, 7, true);
+  EXPECT_EQ("(false, 2, 3, 4, true, 6, 7, true)", Print(t8));
+
+  ::std::tuple<bool, int, int, int, bool, int, int, bool, int> t9(
+      false, 2, 3, 4, true, 6, 7, true, 9);
+  EXPECT_EQ("(false, 2, 3, 4, true, 6, 7, true, 9)", Print(t9));
+
+  const char* const str = "8";
+  // VC++ 2010's implementation of tuple of C++0x is deficient, requiring
+  // an explicit type cast of NULL to be used.
+  ::std::tuple<bool, char, short, testing::internal::Int32,  // NOLINT
+      testing::internal::Int64, float, double, const char*, void*, string>
+      t10(false, 'a', 3, 4, 5, 1.5F, -2.5, str,
+          ImplicitCast_<void*>(NULL), "10");
+  EXPECT_EQ("(false, 'a' (97, 0x61), 3, 4, 5, 1.5, -2.5, " + PrintPointer(str) +
+            " pointing to \"8\", NULL, \"10\")",
+            Print(t10));
+}
+
+// Nested tuples.
+TEST(PrintStdTupleTest, NestedTuple) {
+  ::std::tuple< ::std::tuple<int, bool>, char> nested(
+      ::std::make_tuple(5, true), 'a');
+  EXPECT_EQ("((5, true), 'a' (97, 0x61))", Print(nested));
+}
+
+#endif  // GTEST_LANG_CXX11
+
+// Tests printing user-defined unprintable types.
+
+// Unprintable types in the global namespace.
+TEST(PrintUnprintableTypeTest, InGlobalNamespace) {
+  EXPECT_EQ("1-byte object <00>",
+            Print(UnprintableTemplateInGlobal<char>()));
+}
+
+// Unprintable types in a user namespace.
+TEST(PrintUnprintableTypeTest, InUserNamespace) {
+  EXPECT_EQ("16-byte object <EF-12 00-00 34-AB 00-00 00-00 00-00 00-00 00-00>",
+            Print(::foo::UnprintableInFoo()));
+}
+
+// Unprintable types are that too big to be printed completely.
+
+struct Big {
+  Big() { memset(array, 0, sizeof(array)); }
+  char array[257];
+};
+
+TEST(PrintUnpritableTypeTest, BigObject) {
+  EXPECT_EQ("257-byte object <00-00 00-00 00-00 00-00 00-00 00-00 "
+            "00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 "
+            "00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 "
+            "00-00 00-00 00-00 00-00 00-00 00-00 ... 00-00 00-00 00-00 "
+            "00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 "
+            "00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 "
+            "00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00>",
+            Print(Big()));
+}
+
+// Tests printing user-defined streamable types.
+
+// Streamable types in the global namespace.
+TEST(PrintStreamableTypeTest, InGlobalNamespace) {
+  StreamableInGlobal x;
+  EXPECT_EQ("StreamableInGlobal", Print(x));
+  EXPECT_EQ("StreamableInGlobal*", Print(&x));
+}
+
+// Printable template types in a user namespace.
+TEST(PrintStreamableTypeTest, TemplateTypeInUserNamespace) {
+  EXPECT_EQ("StreamableTemplateInFoo: 0",
+            Print(::foo::StreamableTemplateInFoo<int>()));
+}
+
+// Tests printing user-defined types that have a PrintTo() function.
+TEST(PrintPrintableTypeTest, InUserNamespace) {
+  EXPECT_EQ("PrintableViaPrintTo: 0",
+            Print(::foo::PrintableViaPrintTo()));
+}
+
+// Tests printing a pointer to a user-defined type that has a <<
+// operator for its pointer.
+TEST(PrintPrintableTypeTest, PointerInUserNamespace) {
+  ::foo::PointerPrintable x;
+  EXPECT_EQ("PointerPrintable*", Print(&x));
+}
+
+// Tests printing user-defined class template that have a PrintTo() function.
+TEST(PrintPrintableTypeTest, TemplateInUserNamespace) {
+  EXPECT_EQ("PrintableViaPrintToTemplate: 5",
+            Print(::foo::PrintableViaPrintToTemplate<int>(5)));
+}
+
+// Tests that the universal printer prints both the address and the
+// value of a reference.
+TEST(PrintReferenceTest, PrintsAddressAndValue) {
+  int n = 5;
+  EXPECT_EQ("@" + PrintPointer(&n) + " 5", PrintByRef(n));
+
+  int a[2][3] = {
+    { 0, 1, 2 },
+    { 3, 4, 5 }
+  };
+  EXPECT_EQ("@" + PrintPointer(a) + " { { 0, 1, 2 }, { 3, 4, 5 } }",
+            PrintByRef(a));
+
+  const ::foo::UnprintableInFoo x;
+  EXPECT_EQ("@" + PrintPointer(&x) + " 16-byte object "
+            "<EF-12 00-00 34-AB 00-00 00-00 00-00 00-00 00-00>",
+            PrintByRef(x));
+}
+
+// Tests that the universal printer prints a function pointer passed by
+// reference.
+TEST(PrintReferenceTest, HandlesFunctionPointer) {
+  void (*fp)(int n) = &MyFunction;
+  const string fp_pointer_string =
+      PrintPointer(reinterpret_cast<const void*>(&fp));
+  // We cannot directly cast &MyFunction to const void* because the
+  // standard disallows casting between pointers to functions and
+  // pointers to objects, and some compilers (e.g. GCC 3.4) enforce
+  // this limitation.
+  const string fp_string = PrintPointer(reinterpret_cast<const void*>(
+      reinterpret_cast<internal::BiggestInt>(fp)));
+  EXPECT_EQ("@" + fp_pointer_string + " " + fp_string,
+            PrintByRef(fp));
+}
+
+// Tests that the universal printer prints a member function pointer
+// passed by reference.
+TEST(PrintReferenceTest, HandlesMemberFunctionPointer) {
+  int (Foo::*p)(char ch) = &Foo::MyMethod;
+  EXPECT_TRUE(HasPrefix(
+      PrintByRef(p),
+      "@" + PrintPointer(reinterpret_cast<const void*>(&p)) + " " +
+          Print(sizeof(p)) + "-byte object "));
+
+  char (Foo::*p2)(int n) = &Foo::MyVirtualMethod;
+  EXPECT_TRUE(HasPrefix(
+      PrintByRef(p2),
+      "@" + PrintPointer(reinterpret_cast<const void*>(&p2)) + " " +
+          Print(sizeof(p2)) + "-byte object "));
+}
+
+// Tests that the universal printer prints a member variable pointer
+// passed by reference.
+TEST(PrintReferenceTest, HandlesMemberVariablePointer) {
+  int (Foo::*p) = &Foo::value;  // NOLINT
+  EXPECT_TRUE(HasPrefix(
+      PrintByRef(p),
+      "@" + PrintPointer(&p) + " " + Print(sizeof(p)) + "-byte object "));
+}
+
+// Tests that FormatForComparisonFailureMessage(), which is used to print
+// an operand in a comparison assertion (e.g. ASSERT_EQ) when the assertion
+// fails, formats the operand in the desired way.
+
+// scalar
+TEST(FormatForComparisonFailureMessageTest, WorksForScalar) {
+  EXPECT_STREQ("123",
+               FormatForComparisonFailureMessage(123, 124).c_str());
+}
+
+// non-char pointer
+TEST(FormatForComparisonFailureMessageTest, WorksForNonCharPointer) {
+  int n = 0;
+  EXPECT_EQ(PrintPointer(&n),
+            FormatForComparisonFailureMessage(&n, &n).c_str());
+}
+
+// non-char array
+TEST(FormatForComparisonFailureMessageTest, FormatsNonCharArrayAsPointer) {
+  // In expression 'array == x', 'array' is compared by pointer.
+  // Therefore we want to print an array operand as a pointer.
+  int n[] = { 1, 2, 3 };
+  EXPECT_EQ(PrintPointer(n),
+            FormatForComparisonFailureMessage(n, n).c_str());
+}
+
+// Tests formatting a char pointer when it's compared with another pointer.
+// In this case we want to print it as a raw pointer, as the comparision is by
+// pointer.
+
+// char pointer vs pointer
+TEST(FormatForComparisonFailureMessageTest, WorksForCharPointerVsPointer) {
+  // In expression 'p == x', where 'p' and 'x' are (const or not) char
+  // pointers, the operands are compared by pointer.  Therefore we
+  // want to print 'p' as a pointer instead of a C string (we don't
+  // even know if it's supposed to point to a valid C string).
+
+  // const char*
+  const char* s = "hello";
+  EXPECT_EQ(PrintPointer(s),
+            FormatForComparisonFailureMessage(s, s).c_str());
+
+  // char*
+  char ch = 'a';
+  EXPECT_EQ(PrintPointer(&ch),
+            FormatForComparisonFailureMessage(&ch, &ch).c_str());
+}
+
+// wchar_t pointer vs pointer
+TEST(FormatForComparisonFailureMessageTest, WorksForWCharPointerVsPointer) {
+  // In expression 'p == x', where 'p' and 'x' are (const or not) char
+  // pointers, the operands are compared by pointer.  Therefore we
+  // want to print 'p' as a pointer instead of a wide C string (we don't
+  // even know if it's supposed to point to a valid wide C string).
+
+  // const wchar_t*
+  const wchar_t* s = L"hello";
+  EXPECT_EQ(PrintPointer(s),
+            FormatForComparisonFailureMessage(s, s).c_str());
+
+  // wchar_t*
+  wchar_t ch = L'a';
+  EXPECT_EQ(PrintPointer(&ch),
+            FormatForComparisonFailureMessage(&ch, &ch).c_str());
+}
+
+// Tests formatting a char pointer when it's compared to a string object.
+// In this case we want to print the char pointer as a C string.
+
+#if GTEST_HAS_GLOBAL_STRING
+// char pointer vs ::string
+TEST(FormatForComparisonFailureMessageTest, WorksForCharPointerVsString) {
+  const char* s = "hello \"world";
+  EXPECT_STREQ("\"hello \\\"world\"",  // The string content should be escaped.
+               FormatForComparisonFailureMessage(s, ::string()).c_str());
+
+  // char*
+  char str[] = "hi\1";
+  char* p = str;
+  EXPECT_STREQ("\"hi\\x1\"",  // The string content should be escaped.
+               FormatForComparisonFailureMessage(p, ::string()).c_str());
+}
+#endif
+
+// char pointer vs std::string
+TEST(FormatForComparisonFailureMessageTest, WorksForCharPointerVsStdString) {
+  const char* s = "hello \"world";
+  EXPECT_STREQ("\"hello \\\"world\"",  // The string content should be escaped.
+               FormatForComparisonFailureMessage(s, ::std::string()).c_str());
+
+  // char*
+  char str[] = "hi\1";
+  char* p = str;
+  EXPECT_STREQ("\"hi\\x1\"",  // The string content should be escaped.
+               FormatForComparisonFailureMessage(p, ::std::string()).c_str());
+}
+
+#if GTEST_HAS_GLOBAL_WSTRING
+// wchar_t pointer vs ::wstring
+TEST(FormatForComparisonFailureMessageTest, WorksForWCharPointerVsWString) {
+  const wchar_t* s = L"hi \"world";
+  EXPECT_STREQ("L\"hi \\\"world\"",  // The string content should be escaped.
+               FormatForComparisonFailureMessage(s, ::wstring()).c_str());
+
+  // wchar_t*
+  wchar_t str[] = L"hi\1";
+  wchar_t* p = str;
+  EXPECT_STREQ("L\"hi\\x1\"",  // The string content should be escaped.
+               FormatForComparisonFailureMessage(p, ::wstring()).c_str());
+}
+#endif
+
+#if GTEST_HAS_STD_WSTRING
+// wchar_t pointer vs std::wstring
+TEST(FormatForComparisonFailureMessageTest, WorksForWCharPointerVsStdWString) {
+  const wchar_t* s = L"hi \"world";
+  EXPECT_STREQ("L\"hi \\\"world\"",  // The string content should be escaped.
+               FormatForComparisonFailureMessage(s, ::std::wstring()).c_str());
+
+  // wchar_t*
+  wchar_t str[] = L"hi\1";
+  wchar_t* p = str;
+  EXPECT_STREQ("L\"hi\\x1\"",  // The string content should be escaped.
+               FormatForComparisonFailureMessage(p, ::std::wstring()).c_str());
+}
+#endif
+
+// Tests formatting a char array when it's compared with a pointer or array.
+// In this case we want to print the array as a row pointer, as the comparison
+// is by pointer.
+
+// char array vs pointer
+TEST(FormatForComparisonFailureMessageTest, WorksForCharArrayVsPointer) {
+  char str[] = "hi \"world\"";
+  char* p = NULL;
+  EXPECT_EQ(PrintPointer(str),
+            FormatForComparisonFailureMessage(str, p).c_str());
+}
+
+// char array vs char array
+TEST(FormatForComparisonFailureMessageTest, WorksForCharArrayVsCharArray) {
+  const char str[] = "hi \"world\"";
+  EXPECT_EQ(PrintPointer(str),
+            FormatForComparisonFailureMessage(str, str).c_str());
+}
+
+// wchar_t array vs pointer
+TEST(FormatForComparisonFailureMessageTest, WorksForWCharArrayVsPointer) {
+  wchar_t str[] = L"hi \"world\"";
+  wchar_t* p = NULL;
+  EXPECT_EQ(PrintPointer(str),
+            FormatForComparisonFailureMessage(str, p).c_str());
+}
+
+// wchar_t array vs wchar_t array
+TEST(FormatForComparisonFailureMessageTest, WorksForWCharArrayVsWCharArray) {
+  const wchar_t str[] = L"hi \"world\"";
+  EXPECT_EQ(PrintPointer(str),
+            FormatForComparisonFailureMessage(str, str).c_str());
+}
+
+// Tests formatting a char array when it's compared with a string object.
+// In this case we want to print the array as a C string.
+
+#if GTEST_HAS_GLOBAL_STRING
+// char array vs string
+TEST(FormatForComparisonFailureMessageTest, WorksForCharArrayVsString) {
+  const char str[] = "hi \"w\0rld\"";
+  EXPECT_STREQ("\"hi \\\"w\"",  // The content should be escaped.
+                                // Embedded NUL terminates the string.
+               FormatForComparisonFailureMessage(str, ::string()).c_str());
+}
+#endif
+
+// char array vs std::string
+TEST(FormatForComparisonFailureMessageTest, WorksForCharArrayVsStdString) {
+  const char str[] = "hi \"world\"";
+  EXPECT_STREQ("\"hi \\\"world\\\"\"",  // The content should be escaped.
+               FormatForComparisonFailureMessage(str, ::std::string()).c_str());
+}
+
+#if GTEST_HAS_GLOBAL_WSTRING
+// wchar_t array vs wstring
+TEST(FormatForComparisonFailureMessageTest, WorksForWCharArrayVsWString) {
+  const wchar_t str[] = L"hi \"world\"";
+  EXPECT_STREQ("L\"hi \\\"world\\\"\"",  // The content should be escaped.
+               FormatForComparisonFailureMessage(str, ::wstring()).c_str());
+}
+#endif
+
+#if GTEST_HAS_STD_WSTRING
+// wchar_t array vs std::wstring
+TEST(FormatForComparisonFailureMessageTest, WorksForWCharArrayVsStdWString) {
+  const wchar_t str[] = L"hi \"w\0rld\"";
+  EXPECT_STREQ(
+      "L\"hi \\\"w\"",  // The content should be escaped.
+                        // Embedded NUL terminates the string.
+      FormatForComparisonFailureMessage(str, ::std::wstring()).c_str());
+}
+#endif
+
+// Useful for testing PrintToString().  We cannot use EXPECT_EQ()
+// there as its implementation uses PrintToString().  The caller must
+// ensure that 'value' has no side effect.
+#define EXPECT_PRINT_TO_STRING_(value, expected_string)         \
+  EXPECT_TRUE(PrintToString(value) == (expected_string))        \
+      << " where " #value " prints as " << (PrintToString(value))
+
+TEST(PrintToStringTest, WorksForScalar) {
+  EXPECT_PRINT_TO_STRING_(123, "123");
+}
+
+TEST(PrintToStringTest, WorksForPointerToConstChar) {
+  const char* p = "hello";
+  EXPECT_PRINT_TO_STRING_(p, "\"hello\"");
+}
+
+TEST(PrintToStringTest, WorksForPointerToNonConstChar) {
+  char s[] = "hello";
+  char* p = s;
+  EXPECT_PRINT_TO_STRING_(p, "\"hello\"");
+}
+
+TEST(PrintToStringTest, EscapesForPointerToConstChar) {
+  const char* p = "hello\n";
+  EXPECT_PRINT_TO_STRING_(p, "\"hello\\n\"");
+}
+
+TEST(PrintToStringTest, EscapesForPointerToNonConstChar) {
+  char s[] = "hello\1";
+  char* p = s;
+  EXPECT_PRINT_TO_STRING_(p, "\"hello\\x1\"");
+}
+
+TEST(PrintToStringTest, WorksForArray) {
+  int n[3] = { 1, 2, 3 };
+  EXPECT_PRINT_TO_STRING_(n, "{ 1, 2, 3 }");
+}
+
+TEST(PrintToStringTest, WorksForCharArray) {
+  char s[] = "hello";
+  EXPECT_PRINT_TO_STRING_(s, "\"hello\"");
+}
+
+TEST(PrintToStringTest, WorksForCharArrayWithEmbeddedNul) {
+  const char str_with_nul[] = "hello\0 world";
+  EXPECT_PRINT_TO_STRING_(str_with_nul, "\"hello\\0 world\"");
+
+  char mutable_str_with_nul[] = "hello\0 world";
+  EXPECT_PRINT_TO_STRING_(mutable_str_with_nul, "\"hello\\0 world\"");
+}
+
+#undef EXPECT_PRINT_TO_STRING_
+
+TEST(UniversalTersePrintTest, WorksForNonReference) {
+  ::std::stringstream ss;
+  UniversalTersePrint(123, &ss);
+  EXPECT_EQ("123", ss.str());
+}
+
+TEST(UniversalTersePrintTest, WorksForReference) {
+  const int& n = 123;
+  ::std::stringstream ss;
+  UniversalTersePrint(n, &ss);
+  EXPECT_EQ("123", ss.str());
+}
+
+TEST(UniversalTersePrintTest, WorksForCString) {
+  const char* s1 = "abc";
+  ::std::stringstream ss1;
+  UniversalTersePrint(s1, &ss1);
+  EXPECT_EQ("\"abc\"", ss1.str());
+
+  char* s2 = const_cast<char*>(s1);
+  ::std::stringstream ss2;
+  UniversalTersePrint(s2, &ss2);
+  EXPECT_EQ("\"abc\"", ss2.str());
+
+  const char* s3 = NULL;
+  ::std::stringstream ss3;
+  UniversalTersePrint(s3, &ss3);
+  EXPECT_EQ("NULL", ss3.str());
+}
+
+TEST(UniversalPrintTest, WorksForNonReference) {
+  ::std::stringstream ss;
+  UniversalPrint(123, &ss);
+  EXPECT_EQ("123", ss.str());
+}
+
+TEST(UniversalPrintTest, WorksForReference) {
+  const int& n = 123;
+  ::std::stringstream ss;
+  UniversalPrint(n, &ss);
+  EXPECT_EQ("123", ss.str());
+}
+
+TEST(UniversalPrintTest, WorksForCString) {
+  const char* s1 = "abc";
+  ::std::stringstream ss1;
+  UniversalPrint(s1, &ss1);
+  EXPECT_EQ(PrintPointer(s1) + " pointing to \"abc\"", string(ss1.str()));
+
+  char* s2 = const_cast<char*>(s1);
+  ::std::stringstream ss2;
+  UniversalPrint(s2, &ss2);
+  EXPECT_EQ(PrintPointer(s2) + " pointing to \"abc\"", string(ss2.str()));
+
+  const char* s3 = NULL;
+  ::std::stringstream ss3;
+  UniversalPrint(s3, &ss3);
+  EXPECT_EQ("NULL", ss3.str());
+}
+
+TEST(UniversalPrintTest, WorksForCharArray) {
+  const char str[] = "\"Line\0 1\"\nLine 2";
+  ::std::stringstream ss1;
+  UniversalPrint(str, &ss1);
+  EXPECT_EQ("\"\\\"Line\\0 1\\\"\\nLine 2\"", ss1.str());
+
+  const char mutable_str[] = "\"Line\0 1\"\nLine 2";
+  ::std::stringstream ss2;
+  UniversalPrint(mutable_str, &ss2);
+  EXPECT_EQ("\"\\\"Line\\0 1\\\"\\nLine 2\"", ss2.str());
+}
+
+#if GTEST_HAS_TR1_TUPLE
+
+TEST(UniversalTersePrintTupleFieldsToStringsTestWithTr1, PrintsEmptyTuple) {
+  Strings result = UniversalTersePrintTupleFieldsToStrings(
+      ::std::tr1::make_tuple());
+  EXPECT_EQ(0u, result.size());
+}
+
+TEST(UniversalTersePrintTupleFieldsToStringsTestWithTr1, PrintsOneTuple) {
+  Strings result = UniversalTersePrintTupleFieldsToStrings(
+      ::std::tr1::make_tuple(1));
+  ASSERT_EQ(1u, result.size());
+  EXPECT_EQ("1", result[0]);
+}
+
+TEST(UniversalTersePrintTupleFieldsToStringsTestWithTr1, PrintsTwoTuple) {
+  Strings result = UniversalTersePrintTupleFieldsToStrings(
+      ::std::tr1::make_tuple(1, 'a'));
+  ASSERT_EQ(2u, result.size());
+  EXPECT_EQ("1", result[0]);
+  EXPECT_EQ("'a' (97, 0x61)", result[1]);
+}
+
+TEST(UniversalTersePrintTupleFieldsToStringsTestWithTr1, PrintsTersely) {
+  const int n = 1;
+  Strings result = UniversalTersePrintTupleFieldsToStrings(
+      ::std::tr1::tuple<const int&, const char*>(n, "a"));
+  ASSERT_EQ(2u, result.size());
+  EXPECT_EQ("1", result[0]);
+  EXPECT_EQ("\"a\"", result[1]);
+}
+
+#endif  // GTEST_HAS_TR1_TUPLE
+
+#if GTEST_HAS_STD_TUPLE_
+
+TEST(UniversalTersePrintTupleFieldsToStringsTestWithStd, PrintsEmptyTuple) {
+  Strings result = UniversalTersePrintTupleFieldsToStrings(::std::make_tuple());
+  EXPECT_EQ(0u, result.size());
+}
+
+TEST(UniversalTersePrintTupleFieldsToStringsTestWithStd, PrintsOneTuple) {
+  Strings result = UniversalTersePrintTupleFieldsToStrings(
+      ::std::make_tuple(1));
+  ASSERT_EQ(1u, result.size());
+  EXPECT_EQ("1", result[0]);
+}
+
+TEST(UniversalTersePrintTupleFieldsToStringsTestWithStd, PrintsTwoTuple) {
+  Strings result = UniversalTersePrintTupleFieldsToStrings(
+      ::std::make_tuple(1, 'a'));
+  ASSERT_EQ(2u, result.size());
+  EXPECT_EQ("1", result[0]);
+  EXPECT_EQ("'a' (97, 0x61)", result[1]);
+}
+
+TEST(UniversalTersePrintTupleFieldsToStringsTestWithStd, PrintsTersely) {
+  const int n = 1;
+  Strings result = UniversalTersePrintTupleFieldsToStrings(
+      ::std::tuple<const int&, const char*>(n, "a"));
+  ASSERT_EQ(2u, result.size());
+  EXPECT_EQ("1", result[0]);
+  EXPECT_EQ("\"a\"", result[1]);
+}
+
+#endif  // GTEST_HAS_STD_TUPLE_
+
+}  // namespace gtest_printers_test
+}  // namespace testing
+
diff --git a/third_party/googletest/googletest/test/gtest-test-part_test.cc b/third_party/googletest/googletest/test/gtest-test-part_test.cc
new file mode 100644
index 0000000..ca8ba93
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest-test-part_test.cc
@@ -0,0 +1,208 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: mheule@google.com (Markus Heule)
+//
+
+#include "gtest/gtest-test-part.h"
+
+#include "gtest/gtest.h"
+
+using testing::Message;
+using testing::Test;
+using testing::TestPartResult;
+using testing::TestPartResultArray;
+
+namespace {
+
+// Tests the TestPartResult class.
+
+// The test fixture for testing TestPartResult.
+class TestPartResultTest : public Test {
+ protected:
+  TestPartResultTest()
+      : r1_(TestPartResult::kSuccess, "foo/bar.cc", 10, "Success!"),
+        r2_(TestPartResult::kNonFatalFailure, "foo/bar.cc", -1, "Failure!"),
+        r3_(TestPartResult::kFatalFailure, NULL, -1, "Failure!") {}
+
+  TestPartResult r1_, r2_, r3_;
+};
+
+
+TEST_F(TestPartResultTest, ConstructorWorks) {
+  Message message;
+  message << "something is terribly wrong";
+  message << static_cast<const char*>(testing::internal::kStackTraceMarker);
+  message << "some unimportant stack trace";
+
+  const TestPartResult result(TestPartResult::kNonFatalFailure,
+                              "some_file.cc",
+                              42,
+                              message.GetString().c_str());
+
+  EXPECT_EQ(TestPartResult::kNonFatalFailure, result.type());
+  EXPECT_STREQ("some_file.cc", result.file_name());
+  EXPECT_EQ(42, result.line_number());
+  EXPECT_STREQ(message.GetString().c_str(), result.message());
+  EXPECT_STREQ("something is terribly wrong", result.summary());
+}
+
+TEST_F(TestPartResultTest, ResultAccessorsWork) {
+  const TestPartResult success(TestPartResult::kSuccess,
+                               "file.cc",
+                               42,
+                               "message");
+  EXPECT_TRUE(success.passed());
+  EXPECT_FALSE(success.failed());
+  EXPECT_FALSE(success.nonfatally_failed());
+  EXPECT_FALSE(success.fatally_failed());
+
+  const TestPartResult nonfatal_failure(TestPartResult::kNonFatalFailure,
+                                        "file.cc",
+                                        42,
+                                        "message");
+  EXPECT_FALSE(nonfatal_failure.passed());
+  EXPECT_TRUE(nonfatal_failure.failed());
+  EXPECT_TRUE(nonfatal_failure.nonfatally_failed());
+  EXPECT_FALSE(nonfatal_failure.fatally_failed());
+
+  const TestPartResult fatal_failure(TestPartResult::kFatalFailure,
+                                     "file.cc",
+                                     42,
+                                     "message");
+  EXPECT_FALSE(fatal_failure.passed());
+  EXPECT_TRUE(fatal_failure.failed());
+  EXPECT_FALSE(fatal_failure.nonfatally_failed());
+  EXPECT_TRUE(fatal_failure.fatally_failed());
+}
+
+// Tests TestPartResult::type().
+TEST_F(TestPartResultTest, type) {
+  EXPECT_EQ(TestPartResult::kSuccess, r1_.type());
+  EXPECT_EQ(TestPartResult::kNonFatalFailure, r2_.type());
+  EXPECT_EQ(TestPartResult::kFatalFailure, r3_.type());
+}
+
+// Tests TestPartResult::file_name().
+TEST_F(TestPartResultTest, file_name) {
+  EXPECT_STREQ("foo/bar.cc", r1_.file_name());
+  EXPECT_STREQ(NULL, r3_.file_name());
+}
+
+// Tests TestPartResult::line_number().
+TEST_F(TestPartResultTest, line_number) {
+  EXPECT_EQ(10, r1_.line_number());
+  EXPECT_EQ(-1, r2_.line_number());
+}
+
+// Tests TestPartResult::message().
+TEST_F(TestPartResultTest, message) {
+  EXPECT_STREQ("Success!", r1_.message());
+}
+
+// Tests TestPartResult::passed().
+TEST_F(TestPartResultTest, Passed) {
+  EXPECT_TRUE(r1_.passed());
+  EXPECT_FALSE(r2_.passed());
+  EXPECT_FALSE(r3_.passed());
+}
+
+// Tests TestPartResult::failed().
+TEST_F(TestPartResultTest, Failed) {
+  EXPECT_FALSE(r1_.failed());
+  EXPECT_TRUE(r2_.failed());
+  EXPECT_TRUE(r3_.failed());
+}
+
+// Tests TestPartResult::fatally_failed().
+TEST_F(TestPartResultTest, FatallyFailed) {
+  EXPECT_FALSE(r1_.fatally_failed());
+  EXPECT_FALSE(r2_.fatally_failed());
+  EXPECT_TRUE(r3_.fatally_failed());
+}
+
+// Tests TestPartResult::nonfatally_failed().
+TEST_F(TestPartResultTest, NonfatallyFailed) {
+  EXPECT_FALSE(r1_.nonfatally_failed());
+  EXPECT_TRUE(r2_.nonfatally_failed());
+  EXPECT_FALSE(r3_.nonfatally_failed());
+}
+
+// Tests the TestPartResultArray class.
+
+class TestPartResultArrayTest : public Test {
+ protected:
+  TestPartResultArrayTest()
+      : r1_(TestPartResult::kNonFatalFailure, "foo/bar.cc", -1, "Failure 1"),
+        r2_(TestPartResult::kFatalFailure, "foo/bar.cc", -1, "Failure 2") {}
+
+  const TestPartResult r1_, r2_;
+};
+
+// Tests that TestPartResultArray initially has size 0.
+TEST_F(TestPartResultArrayTest, InitialSizeIsZero) {
+  TestPartResultArray results;
+  EXPECT_EQ(0, results.size());
+}
+
+// Tests that TestPartResultArray contains the given TestPartResult
+// after one Append() operation.
+TEST_F(TestPartResultArrayTest, ContainsGivenResultAfterAppend) {
+  TestPartResultArray results;
+  results.Append(r1_);
+  EXPECT_EQ(1, results.size());
+  EXPECT_STREQ("Failure 1", results.GetTestPartResult(0).message());
+}
+
+// Tests that TestPartResultArray contains the given TestPartResults
+// after two Append() operations.
+TEST_F(TestPartResultArrayTest, ContainsGivenResultsAfterTwoAppends) {
+  TestPartResultArray results;
+  results.Append(r1_);
+  results.Append(r2_);
+  EXPECT_EQ(2, results.size());
+  EXPECT_STREQ("Failure 1", results.GetTestPartResult(0).message());
+  EXPECT_STREQ("Failure 2", results.GetTestPartResult(1).message());
+}
+
+typedef TestPartResultArrayTest TestPartResultArrayDeathTest;
+
+// Tests that the program dies when GetTestPartResult() is called with
+// an invalid index.
+TEST_F(TestPartResultArrayDeathTest, DiesWhenIndexIsOutOfBound) {
+  TestPartResultArray results;
+  results.Append(r1_);
+
+  EXPECT_DEATH_IF_SUPPORTED(results.GetTestPartResult(-1), "");
+  EXPECT_DEATH_IF_SUPPORTED(results.GetTestPartResult(1), "");
+}
+
+// TODO(mheule@google.com): Add a test for the class HasNewFatalFailureHelper.
+
+}  // namespace
diff --git a/third_party/googletest/googletest/test/gtest-tuple_test.cc b/third_party/googletest/googletest/test/gtest-tuple_test.cc
new file mode 100644
index 0000000..bfaa3e0
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest-tuple_test.cc
@@ -0,0 +1,320 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include "gtest/internal/gtest-tuple.h"
+#include <utility>
+#include "gtest/gtest.h"
+
+namespace {
+
+using ::std::tr1::get;
+using ::std::tr1::make_tuple;
+using ::std::tr1::tuple;
+using ::std::tr1::tuple_element;
+using ::std::tr1::tuple_size;
+using ::testing::StaticAssertTypeEq;
+
+// Tests that tuple_element<K, tuple<T0, T1, ..., TN> >::type returns TK.
+TEST(tuple_element_Test, ReturnsElementType) {
+  StaticAssertTypeEq<int, tuple_element<0, tuple<int, char> >::type>();
+  StaticAssertTypeEq<int&, tuple_element<1, tuple<double, int&> >::type>();
+  StaticAssertTypeEq<bool, tuple_element<2, tuple<double, int, bool> >::type>();
+}
+
+// Tests that tuple_size<T>::value gives the number of fields in tuple
+// type T.
+TEST(tuple_size_Test, ReturnsNumberOfFields) {
+  EXPECT_EQ(0, +tuple_size<tuple<> >::value);
+  EXPECT_EQ(1, +tuple_size<tuple<void*> >::value);
+  EXPECT_EQ(1, +tuple_size<tuple<char> >::value);
+  EXPECT_EQ(1, +(tuple_size<tuple<tuple<int, double> > >::value));
+  EXPECT_EQ(2, +(tuple_size<tuple<int&, const char> >::value));
+  EXPECT_EQ(3, +(tuple_size<tuple<char*, void, const bool&> >::value));
+}
+
+// Tests comparing a tuple with itself.
+TEST(ComparisonTest, ComparesWithSelf) {
+  const tuple<int, char, bool> a(5, 'a', false);
+
+  EXPECT_TRUE(a == a);
+  EXPECT_FALSE(a != a);
+}
+
+// Tests comparing two tuples with the same value.
+TEST(ComparisonTest, ComparesEqualTuples) {
+  const tuple<int, bool> a(5, true), b(5, true);
+
+  EXPECT_TRUE(a == b);
+  EXPECT_FALSE(a != b);
+}
+
+// Tests comparing two different tuples that have no reference fields.
+TEST(ComparisonTest, ComparesUnequalTuplesWithoutReferenceFields) {
+  typedef tuple<const int, char> FooTuple;
+
+  const FooTuple a(0, 'x');
+  const FooTuple b(1, 'a');
+
+  EXPECT_TRUE(a != b);
+  EXPECT_FALSE(a == b);
+
+  const FooTuple c(1, 'b');
+
+  EXPECT_TRUE(b != c);
+  EXPECT_FALSE(b == c);
+}
+
+// Tests comparing two different tuples that have reference fields.
+TEST(ComparisonTest, ComparesUnequalTuplesWithReferenceFields) {
+  typedef tuple<int&, const char&> FooTuple;
+
+  int i = 5;
+  const char ch = 'a';
+  const FooTuple a(i, ch);
+
+  int j = 6;
+  const FooTuple b(j, ch);
+
+  EXPECT_TRUE(a != b);
+  EXPECT_FALSE(a == b);
+
+  j = 5;
+  const char ch2 = 'b';
+  const FooTuple c(j, ch2);
+
+  EXPECT_TRUE(b != c);
+  EXPECT_FALSE(b == c);
+}
+
+// Tests that a tuple field with a reference type is an alias of the
+// variable it's supposed to reference.
+TEST(ReferenceFieldTest, IsAliasOfReferencedVariable) {
+  int n = 0;
+  tuple<bool, int&> t(true, n);
+
+  n = 1;
+  EXPECT_EQ(n, get<1>(t))
+      << "Changing a underlying variable should update the reference field.";
+
+  // Makes sure that the implementation doesn't do anything funny with
+  // the & operator for the return type of get<>().
+  EXPECT_EQ(&n, &(get<1>(t)))
+      << "The address of a reference field should equal the address of "
+      << "the underlying variable.";
+
+  get<1>(t) = 2;
+  EXPECT_EQ(2, n)
+      << "Changing a reference field should update the underlying variable.";
+}
+
+// Tests that tuple's default constructor default initializes each field.
+// This test needs to compile without generating warnings.
+TEST(TupleConstructorTest, DefaultConstructorDefaultInitializesEachField) {
+  // The TR1 report requires that tuple's default constructor default
+  // initializes each field, even if it's a primitive type.  If the
+  // implementation forgets to do this, this test will catch it by
+  // generating warnings about using uninitialized variables (assuming
+  // a decent compiler).
+
+  tuple<> empty;
+
+  tuple<int> a1, b1;
+  b1 = a1;
+  EXPECT_EQ(0, get<0>(b1));
+
+  tuple<int, double> a2, b2;
+  b2 = a2;
+  EXPECT_EQ(0, get<0>(b2));
+  EXPECT_EQ(0.0, get<1>(b2));
+
+  tuple<double, char, bool*> a3, b3;
+  b3 = a3;
+  EXPECT_EQ(0.0, get<0>(b3));
+  EXPECT_EQ('\0', get<1>(b3));
+  EXPECT_TRUE(get<2>(b3) == NULL);
+
+  tuple<int, int, int, int, int, int, int, int, int, int> a10, b10;
+  b10 = a10;
+  EXPECT_EQ(0, get<0>(b10));
+  EXPECT_EQ(0, get<1>(b10));
+  EXPECT_EQ(0, get<2>(b10));
+  EXPECT_EQ(0, get<3>(b10));
+  EXPECT_EQ(0, get<4>(b10));
+  EXPECT_EQ(0, get<5>(b10));
+  EXPECT_EQ(0, get<6>(b10));
+  EXPECT_EQ(0, get<7>(b10));
+  EXPECT_EQ(0, get<8>(b10));
+  EXPECT_EQ(0, get<9>(b10));
+}
+
+// Tests constructing a tuple from its fields.
+TEST(TupleConstructorTest, ConstructsFromFields) {
+  int n = 1;
+  // Reference field.
+  tuple<int&> a(n);
+  EXPECT_EQ(&n, &(get<0>(a)));
+
+  // Non-reference fields.
+  tuple<int, char> b(5, 'a');
+  EXPECT_EQ(5, get<0>(b));
+  EXPECT_EQ('a', get<1>(b));
+
+  // Const reference field.
+  const int m = 2;
+  tuple<bool, const int&> c(true, m);
+  EXPECT_TRUE(get<0>(c));
+  EXPECT_EQ(&m, &(get<1>(c)));
+}
+
+// Tests tuple's copy constructor.
+TEST(TupleConstructorTest, CopyConstructor) {
+  tuple<double, bool> a(0.0, true);
+  tuple<double, bool> b(a);
+
+  EXPECT_DOUBLE_EQ(0.0, get<0>(b));
+  EXPECT_TRUE(get<1>(b));
+}
+
+// Tests constructing a tuple from another tuple that has a compatible
+// but different type.
+TEST(TupleConstructorTest, ConstructsFromDifferentTupleType) {
+  tuple<int, int, char> a(0, 1, 'a');
+  tuple<double, long, int> b(a);
+
+  EXPECT_DOUBLE_EQ(0.0, get<0>(b));
+  EXPECT_EQ(1, get<1>(b));
+  EXPECT_EQ('a', get<2>(b));
+}
+
+// Tests constructing a 2-tuple from an std::pair.
+TEST(TupleConstructorTest, ConstructsFromPair) {
+  ::std::pair<int, char> a(1, 'a');
+  tuple<int, char> b(a);
+  tuple<int, const char&> c(a);
+}
+
+// Tests assigning a tuple to another tuple with the same type.
+TEST(TupleAssignmentTest, AssignsToSameTupleType) {
+  const tuple<int, long> a(5, 7L);
+  tuple<int, long> b;
+  b = a;
+  EXPECT_EQ(5, get<0>(b));
+  EXPECT_EQ(7L, get<1>(b));
+}
+
+// Tests assigning a tuple to another tuple with a different but
+// compatible type.
+TEST(TupleAssignmentTest, AssignsToDifferentTupleType) {
+  const tuple<int, long, bool> a(1, 7L, true);
+  tuple<long, int, bool> b;
+  b = a;
+  EXPECT_EQ(1L, get<0>(b));
+  EXPECT_EQ(7, get<1>(b));
+  EXPECT_TRUE(get<2>(b));
+}
+
+// Tests assigning an std::pair to a 2-tuple.
+TEST(TupleAssignmentTest, AssignsFromPair) {
+  const ::std::pair<int, bool> a(5, true);
+  tuple<int, bool> b;
+  b = a;
+  EXPECT_EQ(5, get<0>(b));
+  EXPECT_TRUE(get<1>(b));
+
+  tuple<long, bool> c;
+  c = a;
+  EXPECT_EQ(5L, get<0>(c));
+  EXPECT_TRUE(get<1>(c));
+}
+
+// A fixture for testing big tuples.
+class BigTupleTest : public testing::Test {
+ protected:
+  typedef tuple<int, int, int, int, int, int, int, int, int, int> BigTuple;
+
+  BigTupleTest() :
+      a_(1, 0, 0, 0, 0, 0, 0, 0, 0, 2),
+      b_(1, 0, 0, 0, 0, 0, 0, 0, 0, 3) {}
+
+  BigTuple a_, b_;
+};
+
+// Tests constructing big tuples.
+TEST_F(BigTupleTest, Construction) {
+  BigTuple a;
+  BigTuple b(b_);
+}
+
+// Tests that get<N>(t) returns the N-th (0-based) field of tuple t.
+TEST_F(BigTupleTest, get) {
+  EXPECT_EQ(1, get<0>(a_));
+  EXPECT_EQ(2, get<9>(a_));
+
+  // Tests that get() works on a const tuple too.
+  const BigTuple a(a_);
+  EXPECT_EQ(1, get<0>(a));
+  EXPECT_EQ(2, get<9>(a));
+}
+
+// Tests comparing big tuples.
+TEST_F(BigTupleTest, Comparisons) {
+  EXPECT_TRUE(a_ == a_);
+  EXPECT_FALSE(a_ != a_);
+
+  EXPECT_TRUE(a_ != b_);
+  EXPECT_FALSE(a_ == b_);
+}
+
+TEST(MakeTupleTest, WorksForScalarTypes) {
+  tuple<bool, int> a;
+  a = make_tuple(true, 5);
+  EXPECT_TRUE(get<0>(a));
+  EXPECT_EQ(5, get<1>(a));
+
+  tuple<char, int, long> b;
+  b = make_tuple('a', 'b', 5);
+  EXPECT_EQ('a', get<0>(b));
+  EXPECT_EQ('b', get<1>(b));
+  EXPECT_EQ(5, get<2>(b));
+}
+
+TEST(MakeTupleTest, WorksForPointers) {
+  int a[] = { 1, 2, 3, 4 };
+  const char* const str = "hi";
+  int* const p = a;
+
+  tuple<const char*, int*> t;
+  t = make_tuple(str, p);
+  EXPECT_EQ(str, get<0>(t));
+  EXPECT_EQ(p, get<1>(t));
+}
+
+}  // namespace
diff --git a/third_party/googletest/googletest/test/gtest-typed-test2_test.cc b/third_party/googletest/googletest/test/gtest-typed-test2_test.cc
new file mode 100644
index 0000000..c284700
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest-typed-test2_test.cc
@@ -0,0 +1,45 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include <vector>
+
+#include "test/gtest-typed-test_test.h"
+#include "gtest/gtest.h"
+
+#if GTEST_HAS_TYPED_TEST_P
+
+// Tests that the same type-parameterized test case can be
+// instantiated in different translation units linked together.
+// (ContainerTest is also instantiated in gtest-typed-test_test.cc.)
+INSTANTIATE_TYPED_TEST_CASE_P(Vector, ContainerTest,
+                              testing::Types<std::vector<int> >);
+
+#endif  // GTEST_HAS_TYPED_TEST_P
diff --git a/third_party/googletest/googletest/test/gtest-typed-test_test.cc b/third_party/googletest/googletest/test/gtest-typed-test_test.cc
new file mode 100644
index 0000000..93628ba
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest-typed-test_test.cc
@@ -0,0 +1,380 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include "test/gtest-typed-test_test.h"
+
+#include <set>
+#include <vector>
+
+#include "gtest/gtest.h"
+
+using testing::Test;
+
+// Used for testing that SetUpTestCase()/TearDownTestCase(), fixture
+// ctor/dtor, and SetUp()/TearDown() work correctly in typed tests and
+// type-parameterized test.
+template <typename T>
+class CommonTest : public Test {
+  // For some technical reason, SetUpTestCase() and TearDownTestCase()
+  // must be public.
+ public:
+  static void SetUpTestCase() {
+    shared_ = new T(5);
+  }
+
+  static void TearDownTestCase() {
+    delete shared_;
+    shared_ = NULL;
+  }
+
+  // This 'protected:' is optional.  There's no harm in making all
+  // members of this fixture class template public.
+ protected:
+  // We used to use std::list here, but switched to std::vector since
+  // MSVC's <list> doesn't compile cleanly with /W4.
+  typedef std::vector<T> Vector;
+  typedef std::set<int> IntSet;
+
+  CommonTest() : value_(1) {}
+
+  virtual ~CommonTest() { EXPECT_EQ(3, value_); }
+
+  virtual void SetUp() {
+    EXPECT_EQ(1, value_);
+    value_++;
+  }
+
+  virtual void TearDown() {
+    EXPECT_EQ(2, value_);
+    value_++;
+  }
+
+  T value_;
+  static T* shared_;
+};
+
+template <typename T>
+T* CommonTest<T>::shared_ = NULL;
+
+// This #ifdef block tests typed tests.
+#if GTEST_HAS_TYPED_TEST
+
+using testing::Types;
+
+// Tests that SetUpTestCase()/TearDownTestCase(), fixture ctor/dtor,
+// and SetUp()/TearDown() work correctly in typed tests
+
+typedef Types<char, int> TwoTypes;
+TYPED_TEST_CASE(CommonTest, TwoTypes);
+
+TYPED_TEST(CommonTest, ValuesAreCorrect) {
+  // Static members of the fixture class template can be visited via
+  // the TestFixture:: prefix.
+  EXPECT_EQ(5, *TestFixture::shared_);
+
+  // Typedefs in the fixture class template can be visited via the
+  // "typename TestFixture::" prefix.
+  typename TestFixture::Vector empty;
+  EXPECT_EQ(0U, empty.size());
+
+  typename TestFixture::IntSet empty2;
+  EXPECT_EQ(0U, empty2.size());
+
+  // Non-static members of the fixture class must be visited via
+  // 'this', as required by C++ for class templates.
+  EXPECT_EQ(2, this->value_);
+}
+
+// The second test makes sure shared_ is not deleted after the first
+// test.
+TYPED_TEST(CommonTest, ValuesAreStillCorrect) {
+  // Static members of the fixture class template can also be visited
+  // via 'this'.
+  ASSERT_TRUE(this->shared_ != NULL);
+  EXPECT_EQ(5, *this->shared_);
+
+  // TypeParam can be used to refer to the type parameter.
+  EXPECT_EQ(static_cast<TypeParam>(2), this->value_);
+}
+
+// Tests that multiple TYPED_TEST_CASE's can be defined in the same
+// translation unit.
+
+template <typename T>
+class TypedTest1 : public Test {
+};
+
+// Verifies that the second argument of TYPED_TEST_CASE can be a
+// single type.
+TYPED_TEST_CASE(TypedTest1, int);
+TYPED_TEST(TypedTest1, A) {}
+
+template <typename T>
+class TypedTest2 : public Test {
+};
+
+// Verifies that the second argument of TYPED_TEST_CASE can be a
+// Types<...> type list.
+TYPED_TEST_CASE(TypedTest2, Types<int>);
+
+// This also verifies that tests from different typed test cases can
+// share the same name.
+TYPED_TEST(TypedTest2, A) {}
+
+// Tests that a typed test case can be defined in a namespace.
+
+namespace library1 {
+
+template <typename T>
+class NumericTest : public Test {
+};
+
+typedef Types<int, long> NumericTypes;
+TYPED_TEST_CASE(NumericTest, NumericTypes);
+
+TYPED_TEST(NumericTest, DefaultIsZero) {
+  EXPECT_EQ(0, TypeParam());
+}
+
+}  // namespace library1
+
+#endif  // GTEST_HAS_TYPED_TEST
+
+// This #ifdef block tests type-parameterized tests.
+#if GTEST_HAS_TYPED_TEST_P
+
+using testing::Types;
+using testing::internal::TypedTestCasePState;
+
+// Tests TypedTestCasePState.
+
+class TypedTestCasePStateTest : public Test {
+ protected:
+  virtual void SetUp() {
+    state_.AddTestName("foo.cc", 0, "FooTest", "A");
+    state_.AddTestName("foo.cc", 0, "FooTest", "B");
+    state_.AddTestName("foo.cc", 0, "FooTest", "C");
+  }
+
+  TypedTestCasePState state_;
+};
+
+TEST_F(TypedTestCasePStateTest, SucceedsForMatchingList) {
+  const char* tests = "A, B, C";
+  EXPECT_EQ(tests,
+            state_.VerifyRegisteredTestNames("foo.cc", 1, tests));
+}
+
+// Makes sure that the order of the tests and spaces around the names
+// don't matter.
+TEST_F(TypedTestCasePStateTest, IgnoresOrderAndSpaces) {
+  const char* tests = "A,C,   B";
+  EXPECT_EQ(tests,
+            state_.VerifyRegisteredTestNames("foo.cc", 1, tests));
+}
+
+typedef TypedTestCasePStateTest TypedTestCasePStateDeathTest;
+
+TEST_F(TypedTestCasePStateDeathTest, DetectsDuplicates) {
+  EXPECT_DEATH_IF_SUPPORTED(
+      state_.VerifyRegisteredTestNames("foo.cc", 1, "A, B, A, C"),
+      "foo\\.cc.1.?: Test A is listed more than once\\.");
+}
+
+TEST_F(TypedTestCasePStateDeathTest, DetectsExtraTest) {
+  EXPECT_DEATH_IF_SUPPORTED(
+      state_.VerifyRegisteredTestNames("foo.cc", 1, "A, B, C, D"),
+      "foo\\.cc.1.?: No test named D can be found in this test case\\.");
+}
+
+TEST_F(TypedTestCasePStateDeathTest, DetectsMissedTest) {
+  EXPECT_DEATH_IF_SUPPORTED(
+      state_.VerifyRegisteredTestNames("foo.cc", 1, "A, C"),
+      "foo\\.cc.1.?: You forgot to list test B\\.");
+}
+
+// Tests that defining a test for a parameterized test case generates
+// a run-time error if the test case has been registered.
+TEST_F(TypedTestCasePStateDeathTest, DetectsTestAfterRegistration) {
+  state_.VerifyRegisteredTestNames("foo.cc", 1, "A, B, C");
+  EXPECT_DEATH_IF_SUPPORTED(
+      state_.AddTestName("foo.cc", 2, "FooTest", "D"),
+      "foo\\.cc.2.?: Test D must be defined before REGISTER_TYPED_TEST_CASE_P"
+      "\\(FooTest, \\.\\.\\.\\)\\.");
+}
+
+// Tests that SetUpTestCase()/TearDownTestCase(), fixture ctor/dtor,
+// and SetUp()/TearDown() work correctly in type-parameterized tests.
+
+template <typename T>
+class DerivedTest : public CommonTest<T> {
+};
+
+TYPED_TEST_CASE_P(DerivedTest);
+
+TYPED_TEST_P(DerivedTest, ValuesAreCorrect) {
+  // Static members of the fixture class template can be visited via
+  // the TestFixture:: prefix.
+  EXPECT_EQ(5, *TestFixture::shared_);
+
+  // Non-static members of the fixture class must be visited via
+  // 'this', as required by C++ for class templates.
+  EXPECT_EQ(2, this->value_);
+}
+
+// The second test makes sure shared_ is not deleted after the first
+// test.
+TYPED_TEST_P(DerivedTest, ValuesAreStillCorrect) {
+  // Static members of the fixture class template can also be visited
+  // via 'this'.
+  ASSERT_TRUE(this->shared_ != NULL);
+  EXPECT_EQ(5, *this->shared_);
+  EXPECT_EQ(2, this->value_);
+}
+
+REGISTER_TYPED_TEST_CASE_P(DerivedTest,
+                           ValuesAreCorrect, ValuesAreStillCorrect);
+
+typedef Types<short, long> MyTwoTypes;
+INSTANTIATE_TYPED_TEST_CASE_P(My, DerivedTest, MyTwoTypes);
+
+// Tests that multiple TYPED_TEST_CASE_P's can be defined in the same
+// translation unit.
+
+template <typename T>
+class TypedTestP1 : public Test {
+};
+
+TYPED_TEST_CASE_P(TypedTestP1);
+
+// For testing that the code between TYPED_TEST_CASE_P() and
+// TYPED_TEST_P() is not enclosed in a namespace.
+typedef int IntAfterTypedTestCaseP;
+
+TYPED_TEST_P(TypedTestP1, A) {}
+TYPED_TEST_P(TypedTestP1, B) {}
+
+// For testing that the code between TYPED_TEST_P() and
+// REGISTER_TYPED_TEST_CASE_P() is not enclosed in a namespace.
+typedef int IntBeforeRegisterTypedTestCaseP;
+
+REGISTER_TYPED_TEST_CASE_P(TypedTestP1, A, B);
+
+template <typename T>
+class TypedTestP2 : public Test {
+};
+
+TYPED_TEST_CASE_P(TypedTestP2);
+
+// This also verifies that tests from different type-parameterized
+// test cases can share the same name.
+TYPED_TEST_P(TypedTestP2, A) {}
+
+REGISTER_TYPED_TEST_CASE_P(TypedTestP2, A);
+
+// Verifies that the code between TYPED_TEST_CASE_P() and
+// REGISTER_TYPED_TEST_CASE_P() is not enclosed in a namespace.
+IntAfterTypedTestCaseP after = 0;
+IntBeforeRegisterTypedTestCaseP before = 0;
+
+// Verifies that the last argument of INSTANTIATE_TYPED_TEST_CASE_P()
+// can be either a single type or a Types<...> type list.
+INSTANTIATE_TYPED_TEST_CASE_P(Int, TypedTestP1, int);
+INSTANTIATE_TYPED_TEST_CASE_P(Int, TypedTestP2, Types<int>);
+
+// Tests that the same type-parameterized test case can be
+// instantiated more than once in the same translation unit.
+INSTANTIATE_TYPED_TEST_CASE_P(Double, TypedTestP2, Types<double>);
+
+// Tests that the same type-parameterized test case can be
+// instantiated in different translation units linked together.
+// (ContainerTest is also instantiated in gtest-typed-test_test.cc.)
+typedef Types<std::vector<double>, std::set<char> > MyContainers;
+INSTANTIATE_TYPED_TEST_CASE_P(My, ContainerTest, MyContainers);
+
+// Tests that a type-parameterized test case can be defined and
+// instantiated in a namespace.
+
+namespace library2 {
+
+template <typename T>
+class NumericTest : public Test {
+};
+
+TYPED_TEST_CASE_P(NumericTest);
+
+TYPED_TEST_P(NumericTest, DefaultIsZero) {
+  EXPECT_EQ(0, TypeParam());
+}
+
+TYPED_TEST_P(NumericTest, ZeroIsLessThanOne) {
+  EXPECT_LT(TypeParam(0), TypeParam(1));
+}
+
+REGISTER_TYPED_TEST_CASE_P(NumericTest,
+                           DefaultIsZero, ZeroIsLessThanOne);
+typedef Types<int, double> NumericTypes;
+INSTANTIATE_TYPED_TEST_CASE_P(My, NumericTest, NumericTypes);
+
+static const char* GetTestName() {
+  return testing::UnitTest::GetInstance()->current_test_info()->name();
+}
+// Test the stripping of space from test names
+template <typename T> class TrimmedTest : public Test { };
+TYPED_TEST_CASE_P(TrimmedTest);
+TYPED_TEST_P(TrimmedTest, Test1) { EXPECT_STREQ("Test1", GetTestName()); }
+TYPED_TEST_P(TrimmedTest, Test2) { EXPECT_STREQ("Test2", GetTestName()); }
+TYPED_TEST_P(TrimmedTest, Test3) { EXPECT_STREQ("Test3", GetTestName()); }
+TYPED_TEST_P(TrimmedTest, Test4) { EXPECT_STREQ("Test4", GetTestName()); }
+TYPED_TEST_P(TrimmedTest, Test5) { EXPECT_STREQ("Test5", GetTestName()); }
+REGISTER_TYPED_TEST_CASE_P(
+    TrimmedTest,
+    Test1, Test2,Test3 , Test4 ,Test5 );  // NOLINT
+template <typename T1, typename T2> struct MyPair {};
+// Be sure to try a type with a comma in its name just in case it matters.
+typedef Types<int, double, MyPair<int, int> > TrimTypes;
+INSTANTIATE_TYPED_TEST_CASE_P(My, TrimmedTest, TrimTypes);
+
+}  // namespace library2
+
+#endif  // GTEST_HAS_TYPED_TEST_P
+
+#if !defined(GTEST_HAS_TYPED_TEST) && !defined(GTEST_HAS_TYPED_TEST_P)
+
+// Google Test may not support type-parameterized tests with some
+// compilers. If we use conditional compilation to compile out all
+// code referring to the gtest_main library, MSVC linker will not link
+// that library at all and consequently complain about missing entry
+// point defined in that library (fatal error LNK1561: entry point
+// must be defined). This dummy test keeps gtest_main linked in.
+TEST(DummyTest, TypedTestsAreNotSupportedOnThisPlatform) {}
+
+#endif  // #if !defined(GTEST_HAS_TYPED_TEST) && !defined(GTEST_HAS_TYPED_TEST_P)
diff --git a/third_party/googletest/googletest/test/gtest-typed-test_test.h b/third_party/googletest/googletest/test/gtest-typed-test_test.h
new file mode 100644
index 0000000..41d7570
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest-typed-test_test.h
@@ -0,0 +1,66 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#ifndef GTEST_TEST_GTEST_TYPED_TEST_TEST_H_
+#define GTEST_TEST_GTEST_TYPED_TEST_TEST_H_
+
+#include "gtest/gtest.h"
+
+#if GTEST_HAS_TYPED_TEST_P
+
+using testing::Test;
+
+// For testing that the same type-parameterized test case can be
+// instantiated in different translation units linked together.
+// ContainerTest will be instantiated in both gtest-typed-test_test.cc
+// and gtest-typed-test2_test.cc.
+
+template <typename T>
+class ContainerTest : public Test {
+};
+
+TYPED_TEST_CASE_P(ContainerTest);
+
+TYPED_TEST_P(ContainerTest, CanBeDefaultConstructed) {
+  TypeParam container;
+}
+
+TYPED_TEST_P(ContainerTest, InitialSizeIsZero) {
+  TypeParam container;
+  EXPECT_EQ(0U, container.size());
+}
+
+REGISTER_TYPED_TEST_CASE_P(ContainerTest,
+                           CanBeDefaultConstructed, InitialSizeIsZero);
+
+#endif  // GTEST_HAS_TYPED_TEST_P
+
+#endif  // GTEST_TEST_GTEST_TYPED_TEST_TEST_H_
diff --git a/third_party/googletest/googletest/test/gtest-unittest-api_test.cc b/third_party/googletest/googletest/test/gtest-unittest-api_test.cc
new file mode 100644
index 0000000..b1f5168
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest-unittest-api_test.cc
@@ -0,0 +1,341 @@
+// Copyright 2009 Google Inc.  All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vladl@google.com (Vlad Losev)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This file contains tests verifying correctness of data provided via
+// UnitTest's public methods.
+
+#include "gtest/gtest.h"
+
+#include <string.h>  // For strcmp.
+#include <algorithm>
+
+using ::testing::InitGoogleTest;
+
+namespace testing {
+namespace internal {
+
+template <typename T>
+struct LessByName {
+  bool operator()(const T* a, const T* b) {
+    return strcmp(a->name(), b->name()) < 0;
+  }
+};
+
+class UnitTestHelper {
+ public:
+  // Returns the array of pointers to all test cases sorted by the test case
+  // name.  The caller is responsible for deleting the array.
+  static TestCase const** GetSortedTestCases() {
+    UnitTest& unit_test = *UnitTest::GetInstance();
+    TestCase const** const test_cases =
+        new const TestCase*[unit_test.total_test_case_count()];
+
+    for (int i = 0; i < unit_test.total_test_case_count(); ++i)
+      test_cases[i] = unit_test.GetTestCase(i);
+
+    std::sort(test_cases,
+              test_cases + unit_test.total_test_case_count(),
+              LessByName<TestCase>());
+    return test_cases;
+  }
+
+  // Returns the test case by its name.  The caller doesn't own the returned
+  // pointer.
+  static const TestCase* FindTestCase(const char* name) {
+    UnitTest& unit_test = *UnitTest::GetInstance();
+    for (int i = 0; i < unit_test.total_test_case_count(); ++i) {
+      const TestCase* test_case = unit_test.GetTestCase(i);
+      if (0 == strcmp(test_case->name(), name))
+        return test_case;
+    }
+    return NULL;
+  }
+
+  // Returns the array of pointers to all tests in a particular test case
+  // sorted by the test name.  The caller is responsible for deleting the
+  // array.
+  static TestInfo const** GetSortedTests(const TestCase* test_case) {
+    TestInfo const** const tests =
+        new const TestInfo*[test_case->total_test_count()];
+
+    for (int i = 0; i < test_case->total_test_count(); ++i)
+      tests[i] = test_case->GetTestInfo(i);
+
+    std::sort(tests, tests + test_case->total_test_count(),
+              LessByName<TestInfo>());
+    return tests;
+  }
+};
+
+#if GTEST_HAS_TYPED_TEST
+template <typename T> class TestCaseWithCommentTest : public Test {};
+TYPED_TEST_CASE(TestCaseWithCommentTest, Types<int>);
+TYPED_TEST(TestCaseWithCommentTest, Dummy) {}
+
+const int kTypedTestCases = 1;
+const int kTypedTests = 1;
+#else
+const int kTypedTestCases = 0;
+const int kTypedTests = 0;
+#endif  // GTEST_HAS_TYPED_TEST
+
+// We can only test the accessors that do not change value while tests run.
+// Since tests can be run in any order, the values the accessors that track
+// test execution (such as failed_test_count) can not be predicted.
+TEST(ApiTest, UnitTestImmutableAccessorsWork) {
+  UnitTest* unit_test = UnitTest::GetInstance();
+
+  ASSERT_EQ(2 + kTypedTestCases, unit_test->total_test_case_count());
+  EXPECT_EQ(1 + kTypedTestCases, unit_test->test_case_to_run_count());
+  EXPECT_EQ(2, unit_test->disabled_test_count());
+  EXPECT_EQ(5 + kTypedTests, unit_test->total_test_count());
+  EXPECT_EQ(3 + kTypedTests, unit_test->test_to_run_count());
+
+  const TestCase** const test_cases = UnitTestHelper::GetSortedTestCases();
+
+  EXPECT_STREQ("ApiTest", test_cases[0]->name());
+  EXPECT_STREQ("DISABLED_Test", test_cases[1]->name());
+#if GTEST_HAS_TYPED_TEST
+  EXPECT_STREQ("TestCaseWithCommentTest/0", test_cases[2]->name());
+#endif  // GTEST_HAS_TYPED_TEST
+
+  delete[] test_cases;
+
+  // The following lines initiate actions to verify certain methods in
+  // FinalSuccessChecker::TearDown.
+
+  // Records a test property to verify TestResult::GetTestProperty().
+  RecordProperty("key", "value");
+}
+
+AssertionResult IsNull(const char* str) {
+  if (str != NULL) {
+    return testing::AssertionFailure() << "argument is " << str;
+  }
+  return AssertionSuccess();
+}
+
+TEST(ApiTest, TestCaseImmutableAccessorsWork) {
+  const TestCase* test_case = UnitTestHelper::FindTestCase("ApiTest");
+  ASSERT_TRUE(test_case != NULL);
+
+  EXPECT_STREQ("ApiTest", test_case->name());
+  EXPECT_TRUE(IsNull(test_case->type_param()));
+  EXPECT_TRUE(test_case->should_run());
+  EXPECT_EQ(1, test_case->disabled_test_count());
+  EXPECT_EQ(3, test_case->test_to_run_count());
+  ASSERT_EQ(4, test_case->total_test_count());
+
+  const TestInfo** tests = UnitTestHelper::GetSortedTests(test_case);
+
+  EXPECT_STREQ("DISABLED_Dummy1", tests[0]->name());
+  EXPECT_STREQ("ApiTest", tests[0]->test_case_name());
+  EXPECT_TRUE(IsNull(tests[0]->value_param()));
+  EXPECT_TRUE(IsNull(tests[0]->type_param()));
+  EXPECT_FALSE(tests[0]->should_run());
+
+  EXPECT_STREQ("TestCaseDisabledAccessorsWork", tests[1]->name());
+  EXPECT_STREQ("ApiTest", tests[1]->test_case_name());
+  EXPECT_TRUE(IsNull(tests[1]->value_param()));
+  EXPECT_TRUE(IsNull(tests[1]->type_param()));
+  EXPECT_TRUE(tests[1]->should_run());
+
+  EXPECT_STREQ("TestCaseImmutableAccessorsWork", tests[2]->name());
+  EXPECT_STREQ("ApiTest", tests[2]->test_case_name());
+  EXPECT_TRUE(IsNull(tests[2]->value_param()));
+  EXPECT_TRUE(IsNull(tests[2]->type_param()));
+  EXPECT_TRUE(tests[2]->should_run());
+
+  EXPECT_STREQ("UnitTestImmutableAccessorsWork", tests[3]->name());
+  EXPECT_STREQ("ApiTest", tests[3]->test_case_name());
+  EXPECT_TRUE(IsNull(tests[3]->value_param()));
+  EXPECT_TRUE(IsNull(tests[3]->type_param()));
+  EXPECT_TRUE(tests[3]->should_run());
+
+  delete[] tests;
+  tests = NULL;
+
+#if GTEST_HAS_TYPED_TEST
+  test_case = UnitTestHelper::FindTestCase("TestCaseWithCommentTest/0");
+  ASSERT_TRUE(test_case != NULL);
+
+  EXPECT_STREQ("TestCaseWithCommentTest/0", test_case->name());
+  EXPECT_STREQ(GetTypeName<int>().c_str(), test_case->type_param());
+  EXPECT_TRUE(test_case->should_run());
+  EXPECT_EQ(0, test_case->disabled_test_count());
+  EXPECT_EQ(1, test_case->test_to_run_count());
+  ASSERT_EQ(1, test_case->total_test_count());
+
+  tests = UnitTestHelper::GetSortedTests(test_case);
+
+  EXPECT_STREQ("Dummy", tests[0]->name());
+  EXPECT_STREQ("TestCaseWithCommentTest/0", tests[0]->test_case_name());
+  EXPECT_TRUE(IsNull(tests[0]->value_param()));
+  EXPECT_STREQ(GetTypeName<int>().c_str(), tests[0]->type_param());
+  EXPECT_TRUE(tests[0]->should_run());
+
+  delete[] tests;
+#endif  // GTEST_HAS_TYPED_TEST
+}
+
+TEST(ApiTest, TestCaseDisabledAccessorsWork) {
+  const TestCase* test_case = UnitTestHelper::FindTestCase("DISABLED_Test");
+  ASSERT_TRUE(test_case != NULL);
+
+  EXPECT_STREQ("DISABLED_Test", test_case->name());
+  EXPECT_TRUE(IsNull(test_case->type_param()));
+  EXPECT_FALSE(test_case->should_run());
+  EXPECT_EQ(1, test_case->disabled_test_count());
+  EXPECT_EQ(0, test_case->test_to_run_count());
+  ASSERT_EQ(1, test_case->total_test_count());
+
+  const TestInfo* const test_info = test_case->GetTestInfo(0);
+  EXPECT_STREQ("Dummy2", test_info->name());
+  EXPECT_STREQ("DISABLED_Test", test_info->test_case_name());
+  EXPECT_TRUE(IsNull(test_info->value_param()));
+  EXPECT_TRUE(IsNull(test_info->type_param()));
+  EXPECT_FALSE(test_info->should_run());
+}
+
+// These two tests are here to provide support for testing
+// test_case_to_run_count, disabled_test_count, and test_to_run_count.
+TEST(ApiTest, DISABLED_Dummy1) {}
+TEST(DISABLED_Test, Dummy2) {}
+
+class FinalSuccessChecker : public Environment {
+ protected:
+  virtual void TearDown() {
+    UnitTest* unit_test = UnitTest::GetInstance();
+
+    EXPECT_EQ(1 + kTypedTestCases, unit_test->successful_test_case_count());
+    EXPECT_EQ(3 + kTypedTests, unit_test->successful_test_count());
+    EXPECT_EQ(0, unit_test->failed_test_case_count());
+    EXPECT_EQ(0, unit_test->failed_test_count());
+    EXPECT_TRUE(unit_test->Passed());
+    EXPECT_FALSE(unit_test->Failed());
+    ASSERT_EQ(2 + kTypedTestCases, unit_test->total_test_case_count());
+
+    const TestCase** const test_cases = UnitTestHelper::GetSortedTestCases();
+
+    EXPECT_STREQ("ApiTest", test_cases[0]->name());
+    EXPECT_TRUE(IsNull(test_cases[0]->type_param()));
+    EXPECT_TRUE(test_cases[0]->should_run());
+    EXPECT_EQ(1, test_cases[0]->disabled_test_count());
+    ASSERT_EQ(4, test_cases[0]->total_test_count());
+    EXPECT_EQ(3, test_cases[0]->successful_test_count());
+    EXPECT_EQ(0, test_cases[0]->failed_test_count());
+    EXPECT_TRUE(test_cases[0]->Passed());
+    EXPECT_FALSE(test_cases[0]->Failed());
+
+    EXPECT_STREQ("DISABLED_Test", test_cases[1]->name());
+    EXPECT_TRUE(IsNull(test_cases[1]->type_param()));
+    EXPECT_FALSE(test_cases[1]->should_run());
+    EXPECT_EQ(1, test_cases[1]->disabled_test_count());
+    ASSERT_EQ(1, test_cases[1]->total_test_count());
+    EXPECT_EQ(0, test_cases[1]->successful_test_count());
+    EXPECT_EQ(0, test_cases[1]->failed_test_count());
+
+#if GTEST_HAS_TYPED_TEST
+    EXPECT_STREQ("TestCaseWithCommentTest/0", test_cases[2]->name());
+    EXPECT_STREQ(GetTypeName<int>().c_str(), test_cases[2]->type_param());
+    EXPECT_TRUE(test_cases[2]->should_run());
+    EXPECT_EQ(0, test_cases[2]->disabled_test_count());
+    ASSERT_EQ(1, test_cases[2]->total_test_count());
+    EXPECT_EQ(1, test_cases[2]->successful_test_count());
+    EXPECT_EQ(0, test_cases[2]->failed_test_count());
+    EXPECT_TRUE(test_cases[2]->Passed());
+    EXPECT_FALSE(test_cases[2]->Failed());
+#endif  // GTEST_HAS_TYPED_TEST
+
+    const TestCase* test_case = UnitTestHelper::FindTestCase("ApiTest");
+    const TestInfo** tests = UnitTestHelper::GetSortedTests(test_case);
+    EXPECT_STREQ("DISABLED_Dummy1", tests[0]->name());
+    EXPECT_STREQ("ApiTest", tests[0]->test_case_name());
+    EXPECT_FALSE(tests[0]->should_run());
+
+    EXPECT_STREQ("TestCaseDisabledAccessorsWork", tests[1]->name());
+    EXPECT_STREQ("ApiTest", tests[1]->test_case_name());
+    EXPECT_TRUE(IsNull(tests[1]->value_param()));
+    EXPECT_TRUE(IsNull(tests[1]->type_param()));
+    EXPECT_TRUE(tests[1]->should_run());
+    EXPECT_TRUE(tests[1]->result()->Passed());
+    EXPECT_EQ(0, tests[1]->result()->test_property_count());
+
+    EXPECT_STREQ("TestCaseImmutableAccessorsWork", tests[2]->name());
+    EXPECT_STREQ("ApiTest", tests[2]->test_case_name());
+    EXPECT_TRUE(IsNull(tests[2]->value_param()));
+    EXPECT_TRUE(IsNull(tests[2]->type_param()));
+    EXPECT_TRUE(tests[2]->should_run());
+    EXPECT_TRUE(tests[2]->result()->Passed());
+    EXPECT_EQ(0, tests[2]->result()->test_property_count());
+
+    EXPECT_STREQ("UnitTestImmutableAccessorsWork", tests[3]->name());
+    EXPECT_STREQ("ApiTest", tests[3]->test_case_name());
+    EXPECT_TRUE(IsNull(tests[3]->value_param()));
+    EXPECT_TRUE(IsNull(tests[3]->type_param()));
+    EXPECT_TRUE(tests[3]->should_run());
+    EXPECT_TRUE(tests[3]->result()->Passed());
+    EXPECT_EQ(1, tests[3]->result()->test_property_count());
+    const TestProperty& property = tests[3]->result()->GetTestProperty(0);
+    EXPECT_STREQ("key", property.key());
+    EXPECT_STREQ("value", property.value());
+
+    delete[] tests;
+
+#if GTEST_HAS_TYPED_TEST
+    test_case = UnitTestHelper::FindTestCase("TestCaseWithCommentTest/0");
+    tests = UnitTestHelper::GetSortedTests(test_case);
+
+    EXPECT_STREQ("Dummy", tests[0]->name());
+    EXPECT_STREQ("TestCaseWithCommentTest/0", tests[0]->test_case_name());
+    EXPECT_TRUE(IsNull(tests[0]->value_param()));
+    EXPECT_STREQ(GetTypeName<int>().c_str(), tests[0]->type_param());
+    EXPECT_TRUE(tests[0]->should_run());
+    EXPECT_TRUE(tests[0]->result()->Passed());
+    EXPECT_EQ(0, tests[0]->result()->test_property_count());
+
+    delete[] tests;
+#endif  // GTEST_HAS_TYPED_TEST
+    delete[] test_cases;
+  }
+};
+
+}  // namespace internal
+}  // namespace testing
+
+int main(int argc, char **argv) {
+  InitGoogleTest(&argc, argv);
+
+  AddGlobalTestEnvironment(new testing::internal::FinalSuccessChecker());
+
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/googletest/googletest/test/gtest_all_test.cc b/third_party/googletest/googletest/test/gtest_all_test.cc
new file mode 100644
index 0000000..955aa62
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_all_test.cc
@@ -0,0 +1,47 @@
+// Copyright 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// Tests for Google C++ Testing Framework (Google Test)
+//
+// Sometimes it's desirable to build most of Google Test's own tests
+// by compiling a single file.  This file serves this purpose.
+#include "test/gtest-filepath_test.cc"
+#include "test/gtest-linked_ptr_test.cc"
+#include "test/gtest-message_test.cc"
+#include "test/gtest-options_test.cc"
+#include "test/gtest-port_test.cc"
+#include "test/gtest_pred_impl_unittest.cc"
+#include "test/gtest_prod_test.cc"
+#include "test/gtest-test-part_test.cc"
+#include "test/gtest-typed-test_test.cc"
+#include "test/gtest-typed-test2_test.cc"
+#include "test/gtest_unittest.cc"
+#include "test/production.cc"
diff --git a/third_party/googletest/googletest/test/gtest_break_on_failure_unittest.py b/third_party/googletest/googletest/test/gtest_break_on_failure_unittest.py
new file mode 100755
index 0000000..78f3e0f
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_break_on_failure_unittest.py
@@ -0,0 +1,212 @@
+#!/usr/bin/env python
+#
+# Copyright 2006, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Unit test for Google Test's break-on-failure mode.
+
+A user can ask Google Test to seg-fault when an assertion fails, using
+either the GTEST_BREAK_ON_FAILURE environment variable or the
+--gtest_break_on_failure flag.  This script tests such functionality
+by invoking gtest_break_on_failure_unittest_ (a program written with
+Google Test) with different environments and command line flags.
+"""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import gtest_test_utils
+import os
+import sys
+
+
+# Constants.
+
+IS_WINDOWS = os.name == 'nt'
+
+# The environment variable for enabling/disabling the break-on-failure mode.
+BREAK_ON_FAILURE_ENV_VAR = 'GTEST_BREAK_ON_FAILURE'
+
+# The command line flag for enabling/disabling the break-on-failure mode.
+BREAK_ON_FAILURE_FLAG = 'gtest_break_on_failure'
+
+# The environment variable for enabling/disabling the throw-on-failure mode.
+THROW_ON_FAILURE_ENV_VAR = 'GTEST_THROW_ON_FAILURE'
+
+# The environment variable for enabling/disabling the catch-exceptions mode.
+CATCH_EXCEPTIONS_ENV_VAR = 'GTEST_CATCH_EXCEPTIONS'
+
+# Path to the gtest_break_on_failure_unittest_ program.
+EXE_PATH = gtest_test_utils.GetTestExecutablePath(
+    'gtest_break_on_failure_unittest_')
+
+
+environ = gtest_test_utils.environ
+SetEnvVar = gtest_test_utils.SetEnvVar
+
+# Tests in this file run a Google-Test-based test program and expect it
+# to terminate prematurely.  Therefore they are incompatible with
+# the premature-exit-file protocol by design.  Unset the
+# premature-exit filepath to prevent Google Test from creating
+# the file.
+SetEnvVar(gtest_test_utils.PREMATURE_EXIT_FILE_ENV_VAR, None)
+
+
+def Run(command):
+  """Runs a command; returns 1 if it was killed by a signal, or 0 otherwise."""
+
+  p = gtest_test_utils.Subprocess(command, env=environ)
+  if p.terminated_by_signal:
+    return 1
+  else:
+    return 0
+
+
+# The tests.
+
+
+class GTestBreakOnFailureUnitTest(gtest_test_utils.TestCase):
+  """Tests using the GTEST_BREAK_ON_FAILURE environment variable or
+  the --gtest_break_on_failure flag to turn assertion failures into
+  segmentation faults.
+  """
+
+  def RunAndVerify(self, env_var_value, flag_value, expect_seg_fault):
+    """Runs gtest_break_on_failure_unittest_ and verifies that it does
+    (or does not) have a seg-fault.
+
+    Args:
+      env_var_value:    value of the GTEST_BREAK_ON_FAILURE environment
+                        variable; None if the variable should be unset.
+      flag_value:       value of the --gtest_break_on_failure flag;
+                        None if the flag should not be present.
+      expect_seg_fault: 1 if the program is expected to generate a seg-fault;
+                        0 otherwise.
+    """
+
+    SetEnvVar(BREAK_ON_FAILURE_ENV_VAR, env_var_value)
+
+    if env_var_value is None:
+      env_var_value_msg = ' is not set'
+    else:
+      env_var_value_msg = '=' + env_var_value
+
+    if flag_value is None:
+      flag = ''
+    elif flag_value == '0':
+      flag = '--%s=0' % BREAK_ON_FAILURE_FLAG
+    else:
+      flag = '--%s' % BREAK_ON_FAILURE_FLAG
+
+    command = [EXE_PATH]
+    if flag:
+      command.append(flag)
+
+    if expect_seg_fault:
+      should_or_not = 'should'
+    else:
+      should_or_not = 'should not'
+
+    has_seg_fault = Run(command)
+
+    SetEnvVar(BREAK_ON_FAILURE_ENV_VAR, None)
+
+    msg = ('when %s%s, an assertion failure in "%s" %s cause a seg-fault.' %
+           (BREAK_ON_FAILURE_ENV_VAR, env_var_value_msg, ' '.join(command),
+            should_or_not))
+    self.assert_(has_seg_fault == expect_seg_fault, msg)
+
+  def testDefaultBehavior(self):
+    """Tests the behavior of the default mode."""
+
+    self.RunAndVerify(env_var_value=None,
+                      flag_value=None,
+                      expect_seg_fault=0)
+
+  def testEnvVar(self):
+    """Tests using the GTEST_BREAK_ON_FAILURE environment variable."""
+
+    self.RunAndVerify(env_var_value='0',
+                      flag_value=None,
+                      expect_seg_fault=0)
+    self.RunAndVerify(env_var_value='1',
+                      flag_value=None,
+                      expect_seg_fault=1)
+
+  def testFlag(self):
+    """Tests using the --gtest_break_on_failure flag."""
+
+    self.RunAndVerify(env_var_value=None,
+                      flag_value='0',
+                      expect_seg_fault=0)
+    self.RunAndVerify(env_var_value=None,
+                      flag_value='1',
+                      expect_seg_fault=1)
+
+  def testFlagOverridesEnvVar(self):
+    """Tests that the flag overrides the environment variable."""
+
+    self.RunAndVerify(env_var_value='0',
+                      flag_value='0',
+                      expect_seg_fault=0)
+    self.RunAndVerify(env_var_value='0',
+                      flag_value='1',
+                      expect_seg_fault=1)
+    self.RunAndVerify(env_var_value='1',
+                      flag_value='0',
+                      expect_seg_fault=0)
+    self.RunAndVerify(env_var_value='1',
+                      flag_value='1',
+                      expect_seg_fault=1)
+
+  def testBreakOnFailureOverridesThrowOnFailure(self):
+    """Tests that gtest_break_on_failure overrides gtest_throw_on_failure."""
+
+    SetEnvVar(THROW_ON_FAILURE_ENV_VAR, '1')
+    try:
+      self.RunAndVerify(env_var_value=None,
+                        flag_value='1',
+                        expect_seg_fault=1)
+    finally:
+      SetEnvVar(THROW_ON_FAILURE_ENV_VAR, None)
+
+  if IS_WINDOWS:
+    def testCatchExceptionsDoesNotInterfere(self):
+      """Tests that gtest_catch_exceptions doesn't interfere."""
+
+      SetEnvVar(CATCH_EXCEPTIONS_ENV_VAR, '1')
+      try:
+        self.RunAndVerify(env_var_value='1',
+                          flag_value='1',
+                          expect_seg_fault=1)
+      finally:
+        SetEnvVar(CATCH_EXCEPTIONS_ENV_VAR, None)
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/third_party/googletest/googletest/test/gtest_break_on_failure_unittest_.cc b/third_party/googletest/googletest/test/gtest_break_on_failure_unittest_.cc
new file mode 100644
index 0000000..dd07478
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_break_on_failure_unittest_.cc
@@ -0,0 +1,88 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Unit test for Google Test's break-on-failure mode.
+//
+// A user can ask Google Test to seg-fault when an assertion fails, using
+// either the GTEST_BREAK_ON_FAILURE environment variable or the
+// --gtest_break_on_failure flag.  This file is used for testing such
+// functionality.
+//
+// This program will be invoked from a Python unit test.  It is
+// expected to fail.  Don't run it directly.
+
+#include "gtest/gtest.h"
+
+#if GTEST_OS_WINDOWS
+# include <windows.h>
+# include <stdlib.h>
+#endif
+
+namespace {
+
+// A test that's expected to fail.
+TEST(Foo, Bar) {
+  EXPECT_EQ(2, 3);
+}
+
+#if GTEST_HAS_SEH && !GTEST_OS_WINDOWS_MOBILE
+// On Windows Mobile global exception handlers are not supported.
+LONG WINAPI ExitWithExceptionCode(
+    struct _EXCEPTION_POINTERS* exception_pointers) {
+  exit(exception_pointers->ExceptionRecord->ExceptionCode);
+}
+#endif
+
+}  // namespace
+
+int main(int argc, char **argv) {
+#if GTEST_OS_WINDOWS
+  // Suppresses display of the Windows error dialog upon encountering
+  // a general protection fault (segment violation).
+  SetErrorMode(SEM_NOGPFAULTERRORBOX | SEM_FAILCRITICALERRORS);
+
+# if GTEST_HAS_SEH && !GTEST_OS_WINDOWS_MOBILE
+
+  // The default unhandled exception filter does not always exit
+  // with the exception code as exit code - for example it exits with
+  // 0 for EXCEPTION_ACCESS_VIOLATION and 1 for EXCEPTION_BREAKPOINT
+  // if the application is compiled in debug mode. Thus we use our own
+  // filter which always exits with the exception code for unhandled
+  // exceptions.
+  SetUnhandledExceptionFilter(ExitWithExceptionCode);
+
+# endif
+#endif
+
+  testing::InitGoogleTest(&argc, argv);
+
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/googletest/googletest/test/gtest_catch_exceptions_test.py b/third_party/googletest/googletest/test/gtest_catch_exceptions_test.py
new file mode 100755
index 0000000..e6fc22f
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_catch_exceptions_test.py
@@ -0,0 +1,237 @@
+#!/usr/bin/env python
+#
+# Copyright 2010 Google Inc.  All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Tests Google Test's exception catching behavior.
+
+This script invokes gtest_catch_exceptions_test_ and
+gtest_catch_exceptions_ex_test_ (programs written with
+Google Test) and verifies their output.
+"""
+
+__author__ = 'vladl@google.com (Vlad Losev)'
+
+import os
+
+import gtest_test_utils
+
+# Constants.
+FLAG_PREFIX = '--gtest_'
+LIST_TESTS_FLAG = FLAG_PREFIX + 'list_tests'
+NO_CATCH_EXCEPTIONS_FLAG = FLAG_PREFIX + 'catch_exceptions=0'
+FILTER_FLAG = FLAG_PREFIX + 'filter'
+
+# Path to the gtest_catch_exceptions_ex_test_ binary, compiled with
+# exceptions enabled.
+EX_EXE_PATH = gtest_test_utils.GetTestExecutablePath(
+    'gtest_catch_exceptions_ex_test_')
+
+# Path to the gtest_catch_exceptions_test_ binary, compiled with
+# exceptions disabled.
+EXE_PATH = gtest_test_utils.GetTestExecutablePath(
+    'gtest_catch_exceptions_no_ex_test_')
+
+environ = gtest_test_utils.environ
+SetEnvVar = gtest_test_utils.SetEnvVar
+
+# Tests in this file run a Google-Test-based test program and expect it
+# to terminate prematurely.  Therefore they are incompatible with
+# the premature-exit-file protocol by design.  Unset the
+# premature-exit filepath to prevent Google Test from creating
+# the file.
+SetEnvVar(gtest_test_utils.PREMATURE_EXIT_FILE_ENV_VAR, None)
+
+TEST_LIST = gtest_test_utils.Subprocess(
+    [EXE_PATH, LIST_TESTS_FLAG], env=environ).output
+
+SUPPORTS_SEH_EXCEPTIONS = 'ThrowsSehException' in TEST_LIST
+
+if SUPPORTS_SEH_EXCEPTIONS:
+  BINARY_OUTPUT = gtest_test_utils.Subprocess([EXE_PATH], env=environ).output
+
+EX_BINARY_OUTPUT = gtest_test_utils.Subprocess(
+    [EX_EXE_PATH], env=environ).output
+
+
+# The tests.
+if SUPPORTS_SEH_EXCEPTIONS:
+  # pylint:disable-msg=C6302
+  class CatchSehExceptionsTest(gtest_test_utils.TestCase):
+    """Tests exception-catching behavior."""
+
+
+    def TestSehExceptions(self, test_output):
+      self.assert_('SEH exception with code 0x2a thrown '
+                   'in the test fixture\'s constructor'
+                   in test_output)
+      self.assert_('SEH exception with code 0x2a thrown '
+                   'in the test fixture\'s destructor'
+                   in test_output)
+      self.assert_('SEH exception with code 0x2a thrown in SetUpTestCase()'
+                   in test_output)
+      self.assert_('SEH exception with code 0x2a thrown in TearDownTestCase()'
+                   in test_output)
+      self.assert_('SEH exception with code 0x2a thrown in SetUp()'
+                   in test_output)
+      self.assert_('SEH exception with code 0x2a thrown in TearDown()'
+                   in test_output)
+      self.assert_('SEH exception with code 0x2a thrown in the test body'
+                   in test_output)
+
+    def testCatchesSehExceptionsWithCxxExceptionsEnabled(self):
+      self.TestSehExceptions(EX_BINARY_OUTPUT)
+
+    def testCatchesSehExceptionsWithCxxExceptionsDisabled(self):
+      self.TestSehExceptions(BINARY_OUTPUT)
+
+
+class CatchCxxExceptionsTest(gtest_test_utils.TestCase):
+  """Tests C++ exception-catching behavior.
+
+     Tests in this test case verify that:
+     * C++ exceptions are caught and logged as C++ (not SEH) exceptions
+     * Exception thrown affect the remainder of the test work flow in the
+       expected manner.
+  """
+
+  def testCatchesCxxExceptionsInFixtureConstructor(self):
+    self.assert_('C++ exception with description '
+                 '"Standard C++ exception" thrown '
+                 'in the test fixture\'s constructor'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('unexpected' not in EX_BINARY_OUTPUT,
+                 'This failure belongs in this test only if '
+                 '"CxxExceptionInConstructorTest" (no quotes) '
+                 'appears on the same line as words "called unexpectedly"')
+
+  if ('CxxExceptionInDestructorTest.ThrowsExceptionInDestructor' in
+      EX_BINARY_OUTPUT):
+
+    def testCatchesCxxExceptionsInFixtureDestructor(self):
+      self.assert_('C++ exception with description '
+                   '"Standard C++ exception" thrown '
+                   'in the test fixture\'s destructor'
+                   in EX_BINARY_OUTPUT)
+      self.assert_('CxxExceptionInDestructorTest::TearDownTestCase() '
+                   'called as expected.'
+                   in EX_BINARY_OUTPUT)
+
+  def testCatchesCxxExceptionsInSetUpTestCase(self):
+    self.assert_('C++ exception with description "Standard C++ exception"'
+                 ' thrown in SetUpTestCase()'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInConstructorTest::TearDownTestCase() '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInSetUpTestCaseTest constructor '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInSetUpTestCaseTest destructor '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInSetUpTestCaseTest::SetUp() '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInSetUpTestCaseTest::TearDown() '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInSetUpTestCaseTest test body '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+
+  def testCatchesCxxExceptionsInTearDownTestCase(self):
+    self.assert_('C++ exception with description "Standard C++ exception"'
+                 ' thrown in TearDownTestCase()'
+                 in EX_BINARY_OUTPUT)
+
+  def testCatchesCxxExceptionsInSetUp(self):
+    self.assert_('C++ exception with description "Standard C++ exception"'
+                 ' thrown in SetUp()'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInSetUpTest::TearDownTestCase() '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInSetUpTest destructor '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInSetUpTest::TearDown() '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('unexpected' not in EX_BINARY_OUTPUT,
+                 'This failure belongs in this test only if '
+                 '"CxxExceptionInSetUpTest" (no quotes) '
+                 'appears on the same line as words "called unexpectedly"')
+
+  def testCatchesCxxExceptionsInTearDown(self):
+    self.assert_('C++ exception with description "Standard C++ exception"'
+                 ' thrown in TearDown()'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInTearDownTest::TearDownTestCase() '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInTearDownTest destructor '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+
+  def testCatchesCxxExceptionsInTestBody(self):
+    self.assert_('C++ exception with description "Standard C++ exception"'
+                 ' thrown in the test body'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInTestBodyTest::TearDownTestCase() '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInTestBodyTest destructor '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInTestBodyTest::TearDown() '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+
+  def testCatchesNonStdCxxExceptions(self):
+    self.assert_('Unknown C++ exception thrown in the test body'
+                 in EX_BINARY_OUTPUT)
+
+  def testUnhandledCxxExceptionsAbortTheProgram(self):
+    # Filters out SEH exception tests on Windows. Unhandled SEH exceptions
+    # cause tests to show pop-up windows there.
+    FITLER_OUT_SEH_TESTS_FLAG = FILTER_FLAG + '=-*Seh*'
+    # By default, Google Test doesn't catch the exceptions.
+    uncaught_exceptions_ex_binary_output = gtest_test_utils.Subprocess(
+        [EX_EXE_PATH,
+         NO_CATCH_EXCEPTIONS_FLAG,
+         FITLER_OUT_SEH_TESTS_FLAG],
+        env=environ).output
+
+    self.assert_('Unhandled C++ exception terminating the program'
+                 in uncaught_exceptions_ex_binary_output)
+    self.assert_('unexpected' not in uncaught_exceptions_ex_binary_output)
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/third_party/googletest/googletest/test/gtest_catch_exceptions_test_.cc b/third_party/googletest/googletest/test/gtest_catch_exceptions_test_.cc
new file mode 100644
index 0000000..d0fc82c
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_catch_exceptions_test_.cc
@@ -0,0 +1,311 @@
+// Copyright 2010, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vladl@google.com (Vlad Losev)
+//
+// Tests for Google Test itself. Tests in this file throw C++ or SEH
+// exceptions, and the output is verified by gtest_catch_exceptions_test.py.
+
+#include "gtest/gtest.h"
+
+#include <stdio.h>  // NOLINT
+#include <stdlib.h>  // For exit().
+
+#if GTEST_HAS_SEH
+# include <windows.h>
+#endif
+
+#if GTEST_HAS_EXCEPTIONS
+# include <exception>  // For set_terminate().
+# include <stdexcept>
+#endif
+
+using testing::Test;
+
+#if GTEST_HAS_SEH
+
+class SehExceptionInConstructorTest : public Test {
+ public:
+  SehExceptionInConstructorTest() { RaiseException(42, 0, 0, NULL); }
+};
+
+TEST_F(SehExceptionInConstructorTest, ThrowsExceptionInConstructor) {}
+
+class SehExceptionInDestructorTest : public Test {
+ public:
+  ~SehExceptionInDestructorTest() { RaiseException(42, 0, 0, NULL); }
+};
+
+TEST_F(SehExceptionInDestructorTest, ThrowsExceptionInDestructor) {}
+
+class SehExceptionInSetUpTestCaseTest : public Test {
+ public:
+  static void SetUpTestCase() { RaiseException(42, 0, 0, NULL); }
+};
+
+TEST_F(SehExceptionInSetUpTestCaseTest, ThrowsExceptionInSetUpTestCase) {}
+
+class SehExceptionInTearDownTestCaseTest : public Test {
+ public:
+  static void TearDownTestCase() { RaiseException(42, 0, 0, NULL); }
+};
+
+TEST_F(SehExceptionInTearDownTestCaseTest, ThrowsExceptionInTearDownTestCase) {}
+
+class SehExceptionInSetUpTest : public Test {
+ protected:
+  virtual void SetUp() { RaiseException(42, 0, 0, NULL); }
+};
+
+TEST_F(SehExceptionInSetUpTest, ThrowsExceptionInSetUp) {}
+
+class SehExceptionInTearDownTest : public Test {
+ protected:
+  virtual void TearDown() { RaiseException(42, 0, 0, NULL); }
+};
+
+TEST_F(SehExceptionInTearDownTest, ThrowsExceptionInTearDown) {}
+
+TEST(SehExceptionTest, ThrowsSehException) {
+  RaiseException(42, 0, 0, NULL);
+}
+
+#endif  // GTEST_HAS_SEH
+
+#if GTEST_HAS_EXCEPTIONS
+
+class CxxExceptionInConstructorTest : public Test {
+ public:
+  CxxExceptionInConstructorTest() {
+    // Without this macro VC++ complains about unreachable code at the end of
+    // the constructor.
+    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(
+        throw std::runtime_error("Standard C++ exception"));
+  }
+
+  static void TearDownTestCase() {
+    printf("%s",
+           "CxxExceptionInConstructorTest::TearDownTestCase() "
+           "called as expected.\n");
+  }
+
+ protected:
+  ~CxxExceptionInConstructorTest() {
+    ADD_FAILURE() << "CxxExceptionInConstructorTest destructor "
+                  << "called unexpectedly.";
+  }
+
+  virtual void SetUp() {
+    ADD_FAILURE() << "CxxExceptionInConstructorTest::SetUp() "
+                  << "called unexpectedly.";
+  }
+
+  virtual void TearDown() {
+    ADD_FAILURE() << "CxxExceptionInConstructorTest::TearDown() "
+                  << "called unexpectedly.";
+  }
+};
+
+TEST_F(CxxExceptionInConstructorTest, ThrowsExceptionInConstructor) {
+  ADD_FAILURE() << "CxxExceptionInConstructorTest test body "
+                << "called unexpectedly.";
+}
+
+// Exceptions in destructors are not supported in C++11.
+#if !defined(__GXX_EXPERIMENTAL_CXX0X__) &&  __cplusplus < 201103L
+class CxxExceptionInDestructorTest : public Test {
+ public:
+  static void TearDownTestCase() {
+    printf("%s",
+           "CxxExceptionInDestructorTest::TearDownTestCase() "
+           "called as expected.\n");
+  }
+
+ protected:
+  ~CxxExceptionInDestructorTest() {
+    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(
+        throw std::runtime_error("Standard C++ exception"));
+  }
+};
+
+TEST_F(CxxExceptionInDestructorTest, ThrowsExceptionInDestructor) {}
+#endif  // C++11 mode
+
+class CxxExceptionInSetUpTestCaseTest : public Test {
+ public:
+  CxxExceptionInSetUpTestCaseTest() {
+    printf("%s",
+           "CxxExceptionInSetUpTestCaseTest constructor "
+           "called as expected.\n");
+  }
+
+  static void SetUpTestCase() {
+    throw std::runtime_error("Standard C++ exception");
+  }
+
+  static void TearDownTestCase() {
+    printf("%s",
+           "CxxExceptionInSetUpTestCaseTest::TearDownTestCase() "
+           "called as expected.\n");
+  }
+
+ protected:
+  ~CxxExceptionInSetUpTestCaseTest() {
+    printf("%s",
+           "CxxExceptionInSetUpTestCaseTest destructor "
+           "called as expected.\n");
+  }
+
+  virtual void SetUp() {
+    printf("%s",
+           "CxxExceptionInSetUpTestCaseTest::SetUp() "
+           "called as expected.\n");
+  }
+
+  virtual void TearDown() {
+    printf("%s",
+           "CxxExceptionInSetUpTestCaseTest::TearDown() "
+           "called as expected.\n");
+  }
+};
+
+TEST_F(CxxExceptionInSetUpTestCaseTest, ThrowsExceptionInSetUpTestCase) {
+  printf("%s",
+         "CxxExceptionInSetUpTestCaseTest test body "
+         "called as expected.\n");
+}
+
+class CxxExceptionInTearDownTestCaseTest : public Test {
+ public:
+  static void TearDownTestCase() {
+    throw std::runtime_error("Standard C++ exception");
+  }
+};
+
+TEST_F(CxxExceptionInTearDownTestCaseTest, ThrowsExceptionInTearDownTestCase) {}
+
+class CxxExceptionInSetUpTest : public Test {
+ public:
+  static void TearDownTestCase() {
+    printf("%s",
+           "CxxExceptionInSetUpTest::TearDownTestCase() "
+           "called as expected.\n");
+  }
+
+ protected:
+  ~CxxExceptionInSetUpTest() {
+    printf("%s",
+           "CxxExceptionInSetUpTest destructor "
+           "called as expected.\n");
+  }
+
+  virtual void SetUp() { throw std::runtime_error("Standard C++ exception"); }
+
+  virtual void TearDown() {
+    printf("%s",
+           "CxxExceptionInSetUpTest::TearDown() "
+           "called as expected.\n");
+  }
+};
+
+TEST_F(CxxExceptionInSetUpTest, ThrowsExceptionInSetUp) {
+  ADD_FAILURE() << "CxxExceptionInSetUpTest test body "
+                << "called unexpectedly.";
+}
+
+class CxxExceptionInTearDownTest : public Test {
+ public:
+  static void TearDownTestCase() {
+    printf("%s",
+           "CxxExceptionInTearDownTest::TearDownTestCase() "
+           "called as expected.\n");
+  }
+
+ protected:
+  ~CxxExceptionInTearDownTest() {
+    printf("%s",
+           "CxxExceptionInTearDownTest destructor "
+           "called as expected.\n");
+  }
+
+  virtual void TearDown() {
+    throw std::runtime_error("Standard C++ exception");
+  }
+};
+
+TEST_F(CxxExceptionInTearDownTest, ThrowsExceptionInTearDown) {}
+
+class CxxExceptionInTestBodyTest : public Test {
+ public:
+  static void TearDownTestCase() {
+    printf("%s",
+           "CxxExceptionInTestBodyTest::TearDownTestCase() "
+           "called as expected.\n");
+  }
+
+ protected:
+  ~CxxExceptionInTestBodyTest() {
+    printf("%s",
+           "CxxExceptionInTestBodyTest destructor "
+           "called as expected.\n");
+  }
+
+  virtual void TearDown() {
+    printf("%s",
+           "CxxExceptionInTestBodyTest::TearDown() "
+           "called as expected.\n");
+  }
+};
+
+TEST_F(CxxExceptionInTestBodyTest, ThrowsStdCxxException) {
+  throw std::runtime_error("Standard C++ exception");
+}
+
+TEST(CxxExceptionTest, ThrowsNonStdCxxException) {
+  throw "C-string";
+}
+
+// This terminate handler aborts the program using exit() rather than abort().
+// This avoids showing pop-ups on Windows systems and core dumps on Unix-like
+// ones.
+void TerminateHandler() {
+  fprintf(stderr, "%s\n", "Unhandled C++ exception terminating the program.");
+  fflush(NULL);
+  exit(3);
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+int main(int argc, char** argv) {
+#if GTEST_HAS_EXCEPTIONS
+  std::set_terminate(&TerminateHandler);
+#endif
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/googletest/googletest/test/gtest_color_test.py b/third_party/googletest/googletest/test/gtest_color_test.py
new file mode 100755
index 0000000..d02a53e
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_color_test.py
@@ -0,0 +1,130 @@
+#!/usr/bin/env python
+#
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Verifies that Google Test correctly determines whether to use colors."""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import os
+import gtest_test_utils
+
+
+IS_WINDOWS = os.name = 'nt'
+
+COLOR_ENV_VAR = 'GTEST_COLOR'
+COLOR_FLAG = 'gtest_color'
+COMMAND = gtest_test_utils.GetTestExecutablePath('gtest_color_test_')
+
+
+def SetEnvVar(env_var, value):
+  """Sets the env variable to 'value'; unsets it when 'value' is None."""
+
+  if value is not None:
+    os.environ[env_var] = value
+  elif env_var in os.environ:
+    del os.environ[env_var]
+
+
+def UsesColor(term, color_env_var, color_flag):
+  """Runs gtest_color_test_ and returns its exit code."""
+
+  SetEnvVar('TERM', term)
+  SetEnvVar(COLOR_ENV_VAR, color_env_var)
+
+  if color_flag is None:
+    args = []
+  else:
+    args = ['--%s=%s' % (COLOR_FLAG, color_flag)]
+  p = gtest_test_utils.Subprocess([COMMAND] + args)
+  return not p.exited or p.exit_code
+
+
+class GTestColorTest(gtest_test_utils.TestCase):
+  def testNoEnvVarNoFlag(self):
+    """Tests the case when there's neither GTEST_COLOR nor --gtest_color."""
+
+    if not IS_WINDOWS:
+      self.assert_(not UsesColor('dumb', None, None))
+      self.assert_(not UsesColor('emacs', None, None))
+      self.assert_(not UsesColor('xterm-mono', None, None))
+      self.assert_(not UsesColor('unknown', None, None))
+      self.assert_(not UsesColor(None, None, None))
+    self.assert_(UsesColor('linux', None, None))
+    self.assert_(UsesColor('cygwin', None, None))
+    self.assert_(UsesColor('xterm', None, None))
+    self.assert_(UsesColor('xterm-color', None, None))
+    self.assert_(UsesColor('xterm-256color', None, None))
+
+  def testFlagOnly(self):
+    """Tests the case when there's --gtest_color but not GTEST_COLOR."""
+
+    self.assert_(not UsesColor('dumb', None, 'no'))
+    self.assert_(not UsesColor('xterm-color', None, 'no'))
+    if not IS_WINDOWS:
+      self.assert_(not UsesColor('emacs', None, 'auto'))
+    self.assert_(UsesColor('xterm', None, 'auto'))
+    self.assert_(UsesColor('dumb', None, 'yes'))
+    self.assert_(UsesColor('xterm', None, 'yes'))
+
+  def testEnvVarOnly(self):
+    """Tests the case when there's GTEST_COLOR but not --gtest_color."""
+
+    self.assert_(not UsesColor('dumb', 'no', None))
+    self.assert_(not UsesColor('xterm-color', 'no', None))
+    if not IS_WINDOWS:
+      self.assert_(not UsesColor('dumb', 'auto', None))
+    self.assert_(UsesColor('xterm-color', 'auto', None))
+    self.assert_(UsesColor('dumb', 'yes', None))
+    self.assert_(UsesColor('xterm-color', 'yes', None))
+
+  def testEnvVarAndFlag(self):
+    """Tests the case when there are both GTEST_COLOR and --gtest_color."""
+
+    self.assert_(not UsesColor('xterm-color', 'no', 'no'))
+    self.assert_(UsesColor('dumb', 'no', 'yes'))
+    self.assert_(UsesColor('xterm-color', 'no', 'auto'))
+
+  def testAliasesOfYesAndNo(self):
+    """Tests using aliases in specifying --gtest_color."""
+
+    self.assert_(UsesColor('dumb', None, 'true'))
+    self.assert_(UsesColor('dumb', None, 'YES'))
+    self.assert_(UsesColor('dumb', None, 'T'))
+    self.assert_(UsesColor('dumb', None, '1'))
+
+    self.assert_(not UsesColor('xterm', None, 'f'))
+    self.assert_(not UsesColor('xterm', None, 'false'))
+    self.assert_(not UsesColor('xterm', None, '0'))
+    self.assert_(not UsesColor('xterm', None, 'unknown'))
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/third_party/googletest/googletest/test/gtest_color_test_.cc b/third_party/googletest/googletest/test/gtest_color_test_.cc
new file mode 100644
index 0000000..f61ebb8
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_color_test_.cc
@@ -0,0 +1,71 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// A helper program for testing how Google Test determines whether to use
+// colors in the output.  It prints "YES" and returns 1 if Google Test
+// decides to use colors, and prints "NO" and returns 0 otherwise.
+
+#include <stdio.h>
+
+#include "gtest/gtest.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+using testing::internal::ShouldUseColor;
+
+// The purpose of this is to ensure that the UnitTest singleton is
+// created before main() is entered, and thus that ShouldUseColor()
+// works the same way as in a real Google-Test-based test.  We don't actual
+// run the TEST itself.
+TEST(GTestColorTest, Dummy) {
+}
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+
+  if (ShouldUseColor(true)) {
+    // Google Test decides to use colors in the output (assuming it
+    // goes to a TTY).
+    printf("YES\n");
+    return 1;
+  } else {
+    // Google Test decides not to use colors in the output.
+    printf("NO\n");
+    return 0;
+  }
+}
diff --git a/third_party/googletest/googletest/test/gtest_env_var_test.py b/third_party/googletest/googletest/test/gtest_env_var_test.py
new file mode 100755
index 0000000..ac24337
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_env_var_test.py
@@ -0,0 +1,103 @@
+#!/usr/bin/env python
+#
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Verifies that Google Test correctly parses environment variables."""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import os
+import gtest_test_utils
+
+
+IS_WINDOWS = os.name == 'nt'
+IS_LINUX = os.name == 'posix' and os.uname()[0] == 'Linux'
+
+COMMAND = gtest_test_utils.GetTestExecutablePath('gtest_env_var_test_')
+
+environ = os.environ.copy()
+
+
+def AssertEq(expected, actual):
+  if expected != actual:
+    print 'Expected: %s' % (expected,)
+    print '  Actual: %s' % (actual,)
+    raise AssertionError
+
+
+def SetEnvVar(env_var, value):
+  """Sets the env variable to 'value'; unsets it when 'value' is None."""
+
+  if value is not None:
+    environ[env_var] = value
+  elif env_var in environ:
+    del environ[env_var]
+
+
+def GetFlag(flag):
+  """Runs gtest_env_var_test_ and returns its output."""
+
+  args = [COMMAND]
+  if flag is not None:
+    args += [flag]
+  return gtest_test_utils.Subprocess(args, env=environ).output
+
+
+def TestFlag(flag, test_val, default_val):
+  """Verifies that the given flag is affected by the corresponding env var."""
+
+  env_var = 'GTEST_' + flag.upper()
+  SetEnvVar(env_var, test_val)
+  AssertEq(test_val, GetFlag(flag))
+  SetEnvVar(env_var, None)
+  AssertEq(default_val, GetFlag(flag))
+
+
+class GTestEnvVarTest(gtest_test_utils.TestCase):
+  def testEnvVarAffectsFlag(self):
+    """Tests that environment variable should affect the corresponding flag."""
+
+    TestFlag('break_on_failure', '1', '0')
+    TestFlag('color', 'yes', 'auto')
+    TestFlag('filter', 'FooTest.Bar', '*')
+    TestFlag('output', 'xml:tmp/foo.xml', '')
+    TestFlag('print_time', '0', '1')
+    TestFlag('repeat', '999', '1')
+    TestFlag('throw_on_failure', '1', '0')
+    TestFlag('death_test_style', 'threadsafe', 'fast')
+    TestFlag('catch_exceptions', '0', '1')
+
+    if IS_LINUX:
+      TestFlag('death_test_use_fork', '1', '0')
+      TestFlag('stack_trace_depth', '0', '100')
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/third_party/googletest/googletest/test/gtest_env_var_test_.cc b/third_party/googletest/googletest/test/gtest_env_var_test_.cc
new file mode 100644
index 0000000..539afc9
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_env_var_test_.cc
@@ -0,0 +1,126 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// A helper program for testing that Google Test parses the environment
+// variables correctly.
+
+#include "gtest/gtest.h"
+
+#include <iostream>
+
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+using ::std::cout;
+
+namespace testing {
+
+// The purpose of this is to make the test more realistic by ensuring
+// that the UnitTest singleton is created before main() is entered.
+// We don't actual run the TEST itself.
+TEST(GTestEnvVarTest, Dummy) {
+}
+
+void PrintFlag(const char* flag) {
+  if (strcmp(flag, "break_on_failure") == 0) {
+    cout << GTEST_FLAG(break_on_failure);
+    return;
+  }
+
+  if (strcmp(flag, "catch_exceptions") == 0) {
+    cout << GTEST_FLAG(catch_exceptions);
+    return;
+  }
+
+  if (strcmp(flag, "color") == 0) {
+    cout << GTEST_FLAG(color);
+    return;
+  }
+
+  if (strcmp(flag, "death_test_style") == 0) {
+    cout << GTEST_FLAG(death_test_style);
+    return;
+  }
+
+  if (strcmp(flag, "death_test_use_fork") == 0) {
+    cout << GTEST_FLAG(death_test_use_fork);
+    return;
+  }
+
+  if (strcmp(flag, "filter") == 0) {
+    cout << GTEST_FLAG(filter);
+    return;
+  }
+
+  if (strcmp(flag, "output") == 0) {
+    cout << GTEST_FLAG(output);
+    return;
+  }
+
+  if (strcmp(flag, "print_time") == 0) {
+    cout << GTEST_FLAG(print_time);
+    return;
+  }
+
+  if (strcmp(flag, "repeat") == 0) {
+    cout << GTEST_FLAG(repeat);
+    return;
+  }
+
+  if (strcmp(flag, "stack_trace_depth") == 0) {
+    cout << GTEST_FLAG(stack_trace_depth);
+    return;
+  }
+
+  if (strcmp(flag, "throw_on_failure") == 0) {
+    cout << GTEST_FLAG(throw_on_failure);
+    return;
+  }
+
+  cout << "Invalid flag name " << flag
+       << ".  Valid names are break_on_failure, color, filter, etc.\n";
+  exit(1);
+}
+
+}  // namespace testing
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+
+  if (argc != 2) {
+    cout << "Usage: gtest_env_var_test_ NAME_OF_FLAG\n";
+    return 1;
+  }
+
+  testing::PrintFlag(argv[1]);
+  return 0;
+}
diff --git a/third_party/googletest/googletest/test/gtest_environment_test.cc b/third_party/googletest/googletest/test/gtest_environment_test.cc
new file mode 100644
index 0000000..3cff19e
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_environment_test.cc
@@ -0,0 +1,192 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// Tests using global test environments.
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "gtest/gtest.h"
+
+#define GTEST_IMPLEMENTATION_ 1  // Required for the next #include.
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+GTEST_DECLARE_string_(filter);
+}
+
+namespace {
+
+enum FailureType {
+  NO_FAILURE, NON_FATAL_FAILURE, FATAL_FAILURE
+};
+
+// For testing using global test environments.
+class MyEnvironment : public testing::Environment {
+ public:
+  MyEnvironment() { Reset(); }
+
+  // Depending on the value of failure_in_set_up_, SetUp() will
+  // generate a non-fatal failure, generate a fatal failure, or
+  // succeed.
+  virtual void SetUp() {
+    set_up_was_run_ = true;
+
+    switch (failure_in_set_up_) {
+      case NON_FATAL_FAILURE:
+        ADD_FAILURE() << "Expected non-fatal failure in global set-up.";
+        break;
+      case FATAL_FAILURE:
+        FAIL() << "Expected fatal failure in global set-up.";
+        break;
+      default:
+        break;
+    }
+  }
+
+  // Generates a non-fatal failure.
+  virtual void TearDown() {
+    tear_down_was_run_ = true;
+    ADD_FAILURE() << "Expected non-fatal failure in global tear-down.";
+  }
+
+  // Resets the state of the environment s.t. it can be reused.
+  void Reset() {
+    failure_in_set_up_ = NO_FAILURE;
+    set_up_was_run_ = false;
+    tear_down_was_run_ = false;
+  }
+
+  // We call this function to set the type of failure SetUp() should
+  // generate.
+  void set_failure_in_set_up(FailureType type) {
+    failure_in_set_up_ = type;
+  }
+
+  // Was SetUp() run?
+  bool set_up_was_run() const { return set_up_was_run_; }
+
+  // Was TearDown() run?
+  bool tear_down_was_run() const { return tear_down_was_run_; }
+
+ private:
+  FailureType failure_in_set_up_;
+  bool set_up_was_run_;
+  bool tear_down_was_run_;
+};
+
+// Was the TEST run?
+bool test_was_run;
+
+// The sole purpose of this TEST is to enable us to check whether it
+// was run.
+TEST(FooTest, Bar) {
+  test_was_run = true;
+}
+
+// Prints the message and aborts the program if condition is false.
+void Check(bool condition, const char* msg) {
+  if (!condition) {
+    printf("FAILED: %s\n", msg);
+    testing::internal::posix::Abort();
+  }
+}
+
+// Runs the tests.  Return true iff successful.
+//
+// The 'failure' parameter specifies the type of failure that should
+// be generated by the global set-up.
+int RunAllTests(MyEnvironment* env, FailureType failure) {
+  env->Reset();
+  env->set_failure_in_set_up(failure);
+  test_was_run = false;
+  testing::internal::GetUnitTestImpl()->ClearAdHocTestResult();
+  return RUN_ALL_TESTS();
+}
+
+}  // namespace
+
+int main(int argc, char **argv) {
+  testing::InitGoogleTest(&argc, argv);
+
+  // Registers a global test environment, and verifies that the
+  // registration function returns its argument.
+  MyEnvironment* const env = new MyEnvironment;
+  Check(testing::AddGlobalTestEnvironment(env) == env,
+        "AddGlobalTestEnvironment() should return its argument.");
+
+  // Verifies that RUN_ALL_TESTS() runs the tests when the global
+  // set-up is successful.
+  Check(RunAllTests(env, NO_FAILURE) != 0,
+        "RUN_ALL_TESTS() should return non-zero, as the global tear-down "
+        "should generate a failure.");
+  Check(test_was_run,
+        "The tests should run, as the global set-up should generate no "
+        "failure");
+  Check(env->tear_down_was_run(),
+        "The global tear-down should run, as the global set-up was run.");
+
+  // Verifies that RUN_ALL_TESTS() runs the tests when the global
+  // set-up generates no fatal failure.
+  Check(RunAllTests(env, NON_FATAL_FAILURE) != 0,
+        "RUN_ALL_TESTS() should return non-zero, as both the global set-up "
+        "and the global tear-down should generate a non-fatal failure.");
+  Check(test_was_run,
+        "The tests should run, as the global set-up should generate no "
+        "fatal failure.");
+  Check(env->tear_down_was_run(),
+        "The global tear-down should run, as the global set-up was run.");
+
+  // Verifies that RUN_ALL_TESTS() runs no test when the global set-up
+  // generates a fatal failure.
+  Check(RunAllTests(env, FATAL_FAILURE) != 0,
+        "RUN_ALL_TESTS() should return non-zero, as the global set-up "
+        "should generate a fatal failure.");
+  Check(!test_was_run,
+        "The tests should not run, as the global set-up should generate "
+        "a fatal failure.");
+  Check(env->tear_down_was_run(),
+        "The global tear-down should run, as the global set-up was run.");
+
+  // Verifies that RUN_ALL_TESTS() doesn't do global set-up or
+  // tear-down when there is no test to run.
+  testing::GTEST_FLAG(filter) = "-*";
+  Check(RunAllTests(env, NO_FAILURE) == 0,
+        "RUN_ALL_TESTS() should return zero, as there is no test to run.");
+  Check(!env->set_up_was_run(),
+        "The global set-up should not run, as there is no test to run.");
+  Check(!env->tear_down_was_run(),
+        "The global tear-down should not run, "
+        "as the global set-up was not run.");
+
+  printf("PASS\n");
+  return 0;
+}
diff --git a/third_party/googletest/googletest/test/gtest_filter_unittest.py b/third_party/googletest/googletest/test/gtest_filter_unittest.py
new file mode 100755
index 0000000..0d1a770
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_filter_unittest.py
@@ -0,0 +1,633 @@
+#!/usr/bin/env python
+#
+# Copyright 2005 Google Inc. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Unit test for Google Test test filters.
+
+A user can specify which test(s) in a Google Test program to run via either
+the GTEST_FILTER environment variable or the --gtest_filter flag.
+This script tests such functionality by invoking
+gtest_filter_unittest_ (a program written with Google Test) with different
+environments and command line flags.
+
+Note that test sharding may also influence which tests are filtered. Therefore,
+we test that here also.
+"""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import os
+import re
+import sets
+import sys
+
+import gtest_test_utils
+
+# Constants.
+
+# Checks if this platform can pass empty environment variables to child
+# processes.  We set an env variable to an empty string and invoke a python
+# script in a subprocess to print whether the variable is STILL in
+# os.environ.  We then use 'eval' to parse the child's output so that an
+# exception is thrown if the input is anything other than 'True' nor 'False'.
+os.environ['EMPTY_VAR'] = ''
+child = gtest_test_utils.Subprocess(
+    [sys.executable, '-c', 'import os; print \'EMPTY_VAR\' in os.environ'])
+CAN_PASS_EMPTY_ENV = eval(child.output)
+
+
+# Check if this platform can unset environment variables in child processes.
+# We set an env variable to a non-empty string, unset it, and invoke
+# a python script in a subprocess to print whether the variable
+# is NO LONGER in os.environ.
+# We use 'eval' to parse the child's output so that an exception
+# is thrown if the input is neither 'True' nor 'False'.
+os.environ['UNSET_VAR'] = 'X'
+del os.environ['UNSET_VAR']
+child = gtest_test_utils.Subprocess(
+    [sys.executable, '-c', 'import os; print \'UNSET_VAR\' not in os.environ'])
+CAN_UNSET_ENV = eval(child.output)
+
+
+# Checks if we should test with an empty filter. This doesn't
+# make sense on platforms that cannot pass empty env variables (Win32)
+# and on platforms that cannot unset variables (since we cannot tell
+# the difference between "" and NULL -- Borland and Solaris < 5.10)
+CAN_TEST_EMPTY_FILTER = (CAN_PASS_EMPTY_ENV and CAN_UNSET_ENV)
+
+
+# The environment variable for specifying the test filters.
+FILTER_ENV_VAR = 'GTEST_FILTER'
+
+# The environment variables for test sharding.
+TOTAL_SHARDS_ENV_VAR = 'GTEST_TOTAL_SHARDS'
+SHARD_INDEX_ENV_VAR = 'GTEST_SHARD_INDEX'
+SHARD_STATUS_FILE_ENV_VAR = 'GTEST_SHARD_STATUS_FILE'
+
+# The command line flag for specifying the test filters.
+FILTER_FLAG = 'gtest_filter'
+
+# The command line flag for including disabled tests.
+ALSO_RUN_DISABED_TESTS_FLAG = 'gtest_also_run_disabled_tests'
+
+# Command to run the gtest_filter_unittest_ program.
+COMMAND = gtest_test_utils.GetTestExecutablePath('gtest_filter_unittest_')
+
+# Regex for determining whether parameterized tests are enabled in the binary.
+PARAM_TEST_REGEX = re.compile(r'/ParamTest')
+
+# Regex for parsing test case names from Google Test's output.
+TEST_CASE_REGEX = re.compile(r'^\[\-+\] \d+ tests? from (\w+(/\w+)?)')
+
+# Regex for parsing test names from Google Test's output.
+TEST_REGEX = re.compile(r'^\[\s*RUN\s*\].*\.(\w+(/\w+)?)')
+
+# The command line flag to tell Google Test to output the list of tests it
+# will run.
+LIST_TESTS_FLAG = '--gtest_list_tests'
+
+# Indicates whether Google Test supports death tests.
+SUPPORTS_DEATH_TESTS = 'HasDeathTest' in gtest_test_utils.Subprocess(
+    [COMMAND, LIST_TESTS_FLAG]).output
+
+# Full names of all tests in gtest_filter_unittests_.
+PARAM_TESTS = [
+    'SeqP/ParamTest.TestX/0',
+    'SeqP/ParamTest.TestX/1',
+    'SeqP/ParamTest.TestY/0',
+    'SeqP/ParamTest.TestY/1',
+    'SeqQ/ParamTest.TestX/0',
+    'SeqQ/ParamTest.TestX/1',
+    'SeqQ/ParamTest.TestY/0',
+    'SeqQ/ParamTest.TestY/1',
+    ]
+
+DISABLED_TESTS = [
+    'BarTest.DISABLED_TestFour',
+    'BarTest.DISABLED_TestFive',
+    'BazTest.DISABLED_TestC',
+    'DISABLED_FoobarTest.Test1',
+    'DISABLED_FoobarTest.DISABLED_Test2',
+    'DISABLED_FoobarbazTest.TestA',
+    ]
+
+if SUPPORTS_DEATH_TESTS:
+  DEATH_TESTS = [
+    'HasDeathTest.Test1',
+    'HasDeathTest.Test2',
+    ]
+else:
+  DEATH_TESTS = []
+
+# All the non-disabled tests.
+ACTIVE_TESTS = [
+    'FooTest.Abc',
+    'FooTest.Xyz',
+
+    'BarTest.TestOne',
+    'BarTest.TestTwo',
+    'BarTest.TestThree',
+
+    'BazTest.TestOne',
+    'BazTest.TestA',
+    'BazTest.TestB',
+    ] + DEATH_TESTS + PARAM_TESTS
+
+param_tests_present = None
+
+# Utilities.
+
+environ = os.environ.copy()
+
+
+def SetEnvVar(env_var, value):
+  """Sets the env variable to 'value'; unsets it when 'value' is None."""
+
+  if value is not None:
+    environ[env_var] = value
+  elif env_var in environ:
+    del environ[env_var]
+
+
+def RunAndReturnOutput(args = None):
+  """Runs the test program and returns its output."""
+
+  return gtest_test_utils.Subprocess([COMMAND] + (args or []),
+                                     env=environ).output
+
+
+def RunAndExtractTestList(args = None):
+  """Runs the test program and returns its exit code and a list of tests run."""
+
+  p = gtest_test_utils.Subprocess([COMMAND] + (args or []), env=environ)
+  tests_run = []
+  test_case = ''
+  test = ''
+  for line in p.output.split('\n'):
+    match = TEST_CASE_REGEX.match(line)
+    if match is not None:
+      test_case = match.group(1)
+    else:
+      match = TEST_REGEX.match(line)
+      if match is not None:
+        test = match.group(1)
+        tests_run.append(test_case + '.' + test)
+  return (tests_run, p.exit_code)
+
+
+def InvokeWithModifiedEnv(extra_env, function, *args, **kwargs):
+  """Runs the given function and arguments in a modified environment."""
+  try:
+    original_env = environ.copy()
+    environ.update(extra_env)
+    return function(*args, **kwargs)
+  finally:
+    environ.clear()
+    environ.update(original_env)
+
+
+def RunWithSharding(total_shards, shard_index, command):
+  """Runs a test program shard and returns exit code and a list of tests run."""
+
+  extra_env = {SHARD_INDEX_ENV_VAR: str(shard_index),
+               TOTAL_SHARDS_ENV_VAR: str(total_shards)}
+  return InvokeWithModifiedEnv(extra_env, RunAndExtractTestList, command)
+
+# The unit test.
+
+
+class GTestFilterUnitTest(gtest_test_utils.TestCase):
+  """Tests the env variable or the command line flag to filter tests."""
+
+  # Utilities.
+
+  def AssertSetEqual(self, lhs, rhs):
+    """Asserts that two sets are equal."""
+
+    for elem in lhs:
+      self.assert_(elem in rhs, '%s in %s' % (elem, rhs))
+
+    for elem in rhs:
+      self.assert_(elem in lhs, '%s in %s' % (elem, lhs))
+
+  def AssertPartitionIsValid(self, set_var, list_of_sets):
+    """Asserts that list_of_sets is a valid partition of set_var."""
+
+    full_partition = []
+    for slice_var in list_of_sets:
+      full_partition.extend(slice_var)
+    self.assertEqual(len(set_var), len(full_partition))
+    self.assertEqual(sets.Set(set_var), sets.Set(full_partition))
+
+  def AdjustForParameterizedTests(self, tests_to_run):
+    """Adjust tests_to_run in case value parameterized tests are disabled."""
+
+    global param_tests_present
+    if not param_tests_present:
+      return list(sets.Set(tests_to_run) - sets.Set(PARAM_TESTS))
+    else:
+      return tests_to_run
+
+  def RunAndVerify(self, gtest_filter, tests_to_run):
+    """Checks that the binary runs correct set of tests for a given filter."""
+
+    tests_to_run = self.AdjustForParameterizedTests(tests_to_run)
+
+    # First, tests using the environment variable.
+
+    # Windows removes empty variables from the environment when passing it
+    # to a new process.  This means it is impossible to pass an empty filter
+    # into a process using the environment variable.  However, we can still
+    # test the case when the variable is not supplied (i.e., gtest_filter is
+    # None).
+    # pylint: disable-msg=C6403
+    if CAN_TEST_EMPTY_FILTER or gtest_filter != '':
+      SetEnvVar(FILTER_ENV_VAR, gtest_filter)
+      tests_run = RunAndExtractTestList()[0]
+      SetEnvVar(FILTER_ENV_VAR, None)
+      self.AssertSetEqual(tests_run, tests_to_run)
+    # pylint: enable-msg=C6403
+
+    # Next, tests using the command line flag.
+
+    if gtest_filter is None:
+      args = []
+    else:
+      args = ['--%s=%s' % (FILTER_FLAG, gtest_filter)]
+
+    tests_run = RunAndExtractTestList(args)[0]
+    self.AssertSetEqual(tests_run, tests_to_run)
+
+  def RunAndVerifyWithSharding(self, gtest_filter, total_shards, tests_to_run,
+                               args=None, check_exit_0=False):
+    """Checks that binary runs correct tests for the given filter and shard.
+
+    Runs all shards of gtest_filter_unittest_ with the given filter, and
+    verifies that the right set of tests were run. The union of tests run
+    on each shard should be identical to tests_to_run, without duplicates.
+
+    Args:
+      gtest_filter: A filter to apply to the tests.
+      total_shards: A total number of shards to split test run into.
+      tests_to_run: A set of tests expected to run.
+      args   :      Arguments to pass to the to the test binary.
+      check_exit_0: When set to a true value, make sure that all shards
+                    return 0.
+    """
+
+    tests_to_run = self.AdjustForParameterizedTests(tests_to_run)
+
+    # Windows removes empty variables from the environment when passing it
+    # to a new process.  This means it is impossible to pass an empty filter
+    # into a process using the environment variable.  However, we can still
+    # test the case when the variable is not supplied (i.e., gtest_filter is
+    # None).
+    # pylint: disable-msg=C6403
+    if CAN_TEST_EMPTY_FILTER or gtest_filter != '':
+      SetEnvVar(FILTER_ENV_VAR, gtest_filter)
+      partition = []
+      for i in range(0, total_shards):
+        (tests_run, exit_code) = RunWithSharding(total_shards, i, args)
+        if check_exit_0:
+          self.assertEqual(0, exit_code)
+        partition.append(tests_run)
+
+      self.AssertPartitionIsValid(tests_to_run, partition)
+      SetEnvVar(FILTER_ENV_VAR, None)
+    # pylint: enable-msg=C6403
+
+  def RunAndVerifyAllowingDisabled(self, gtest_filter, tests_to_run):
+    """Checks that the binary runs correct set of tests for the given filter.
+
+    Runs gtest_filter_unittest_ with the given filter, and enables
+    disabled tests. Verifies that the right set of tests were run.
+
+    Args:
+      gtest_filter: A filter to apply to the tests.
+      tests_to_run: A set of tests expected to run.
+    """
+
+    tests_to_run = self.AdjustForParameterizedTests(tests_to_run)
+
+    # Construct the command line.
+    args = ['--%s' % ALSO_RUN_DISABED_TESTS_FLAG]
+    if gtest_filter is not None:
+      args.append('--%s=%s' % (FILTER_FLAG, gtest_filter))
+
+    tests_run = RunAndExtractTestList(args)[0]
+    self.AssertSetEqual(tests_run, tests_to_run)
+
+  def setUp(self):
+    """Sets up test case.
+
+    Determines whether value-parameterized tests are enabled in the binary and
+    sets the flags accordingly.
+    """
+
+    global param_tests_present
+    if param_tests_present is None:
+      param_tests_present = PARAM_TEST_REGEX.search(
+          RunAndReturnOutput()) is not None
+
+  def testDefaultBehavior(self):
+    """Tests the behavior of not specifying the filter."""
+
+    self.RunAndVerify(None, ACTIVE_TESTS)
+
+  def testDefaultBehaviorWithShards(self):
+    """Tests the behavior without the filter, with sharding enabled."""
+
+    self.RunAndVerifyWithSharding(None, 1, ACTIVE_TESTS)
+    self.RunAndVerifyWithSharding(None, 2, ACTIVE_TESTS)
+    self.RunAndVerifyWithSharding(None, len(ACTIVE_TESTS) - 1, ACTIVE_TESTS)
+    self.RunAndVerifyWithSharding(None, len(ACTIVE_TESTS), ACTIVE_TESTS)
+    self.RunAndVerifyWithSharding(None, len(ACTIVE_TESTS) + 1, ACTIVE_TESTS)
+
+  def testEmptyFilter(self):
+    """Tests an empty filter."""
+
+    self.RunAndVerify('', [])
+    self.RunAndVerifyWithSharding('', 1, [])
+    self.RunAndVerifyWithSharding('', 2, [])
+
+  def testBadFilter(self):
+    """Tests a filter that matches nothing."""
+
+    self.RunAndVerify('BadFilter', [])
+    self.RunAndVerifyAllowingDisabled('BadFilter', [])
+
+  def testFullName(self):
+    """Tests filtering by full name."""
+
+    self.RunAndVerify('FooTest.Xyz', ['FooTest.Xyz'])
+    self.RunAndVerifyAllowingDisabled('FooTest.Xyz', ['FooTest.Xyz'])
+    self.RunAndVerifyWithSharding('FooTest.Xyz', 5, ['FooTest.Xyz'])
+
+  def testUniversalFilters(self):
+    """Tests filters that match everything."""
+
+    self.RunAndVerify('*', ACTIVE_TESTS)
+    self.RunAndVerify('*.*', ACTIVE_TESTS)
+    self.RunAndVerifyWithSharding('*.*', len(ACTIVE_TESTS) - 3, ACTIVE_TESTS)
+    self.RunAndVerifyAllowingDisabled('*', ACTIVE_TESTS + DISABLED_TESTS)
+    self.RunAndVerifyAllowingDisabled('*.*', ACTIVE_TESTS + DISABLED_TESTS)
+
+  def testFilterByTestCase(self):
+    """Tests filtering by test case name."""
+
+    self.RunAndVerify('FooTest.*', ['FooTest.Abc', 'FooTest.Xyz'])
+
+    BAZ_TESTS = ['BazTest.TestOne', 'BazTest.TestA', 'BazTest.TestB']
+    self.RunAndVerify('BazTest.*', BAZ_TESTS)
+    self.RunAndVerifyAllowingDisabled('BazTest.*',
+                                      BAZ_TESTS + ['BazTest.DISABLED_TestC'])
+
+  def testFilterByTest(self):
+    """Tests filtering by test name."""
+
+    self.RunAndVerify('*.TestOne', ['BarTest.TestOne', 'BazTest.TestOne'])
+
+  def testFilterDisabledTests(self):
+    """Select only the disabled tests to run."""
+
+    self.RunAndVerify('DISABLED_FoobarTest.Test1', [])
+    self.RunAndVerifyAllowingDisabled('DISABLED_FoobarTest.Test1',
+                                      ['DISABLED_FoobarTest.Test1'])
+
+    self.RunAndVerify('*DISABLED_*', [])
+    self.RunAndVerifyAllowingDisabled('*DISABLED_*', DISABLED_TESTS)
+
+    self.RunAndVerify('*.DISABLED_*', [])
+    self.RunAndVerifyAllowingDisabled('*.DISABLED_*', [
+        'BarTest.DISABLED_TestFour',
+        'BarTest.DISABLED_TestFive',
+        'BazTest.DISABLED_TestC',
+        'DISABLED_FoobarTest.DISABLED_Test2',
+        ])
+
+    self.RunAndVerify('DISABLED_*', [])
+    self.RunAndVerifyAllowingDisabled('DISABLED_*', [
+        'DISABLED_FoobarTest.Test1',
+        'DISABLED_FoobarTest.DISABLED_Test2',
+        'DISABLED_FoobarbazTest.TestA',
+        ])
+
+  def testWildcardInTestCaseName(self):
+    """Tests using wildcard in the test case name."""
+
+    self.RunAndVerify('*a*.*', [
+        'BarTest.TestOne',
+        'BarTest.TestTwo',
+        'BarTest.TestThree',
+
+        'BazTest.TestOne',
+        'BazTest.TestA',
+        'BazTest.TestB', ] + DEATH_TESTS + PARAM_TESTS)
+
+  def testWildcardInTestName(self):
+    """Tests using wildcard in the test name."""
+
+    self.RunAndVerify('*.*A*', ['FooTest.Abc', 'BazTest.TestA'])
+
+  def testFilterWithoutDot(self):
+    """Tests a filter that has no '.' in it."""
+
+    self.RunAndVerify('*z*', [
+        'FooTest.Xyz',
+
+        'BazTest.TestOne',
+        'BazTest.TestA',
+        'BazTest.TestB',
+        ])
+
+  def testTwoPatterns(self):
+    """Tests filters that consist of two patterns."""
+
+    self.RunAndVerify('Foo*.*:*A*', [
+        'FooTest.Abc',
+        'FooTest.Xyz',
+
+        'BazTest.TestA',
+        ])
+
+    # An empty pattern + a non-empty one
+    self.RunAndVerify(':*A*', ['FooTest.Abc', 'BazTest.TestA'])
+
+  def testThreePatterns(self):
+    """Tests filters that consist of three patterns."""
+
+    self.RunAndVerify('*oo*:*A*:*One', [
+        'FooTest.Abc',
+        'FooTest.Xyz',
+
+        'BarTest.TestOne',
+
+        'BazTest.TestOne',
+        'BazTest.TestA',
+        ])
+
+    # The 2nd pattern is empty.
+    self.RunAndVerify('*oo*::*One', [
+        'FooTest.Abc',
+        'FooTest.Xyz',
+
+        'BarTest.TestOne',
+
+        'BazTest.TestOne',
+        ])
+
+    # The last 2 patterns are empty.
+    self.RunAndVerify('*oo*::', [
+        'FooTest.Abc',
+        'FooTest.Xyz',
+        ])
+
+  def testNegativeFilters(self):
+    self.RunAndVerify('*-BazTest.TestOne', [
+        'FooTest.Abc',
+        'FooTest.Xyz',
+
+        'BarTest.TestOne',
+        'BarTest.TestTwo',
+        'BarTest.TestThree',
+
+        'BazTest.TestA',
+        'BazTest.TestB',
+        ] + DEATH_TESTS + PARAM_TESTS)
+
+    self.RunAndVerify('*-FooTest.Abc:BazTest.*', [
+        'FooTest.Xyz',
+
+        'BarTest.TestOne',
+        'BarTest.TestTwo',
+        'BarTest.TestThree',
+        ] + DEATH_TESTS + PARAM_TESTS)
+
+    self.RunAndVerify('BarTest.*-BarTest.TestOne', [
+        'BarTest.TestTwo',
+        'BarTest.TestThree',
+        ])
+
+    # Tests without leading '*'.
+    self.RunAndVerify('-FooTest.Abc:FooTest.Xyz:BazTest.*', [
+        'BarTest.TestOne',
+        'BarTest.TestTwo',
+        'BarTest.TestThree',
+        ] + DEATH_TESTS + PARAM_TESTS)
+
+    # Value parameterized tests.
+    self.RunAndVerify('*/*', PARAM_TESTS)
+
+    # Value parameterized tests filtering by the sequence name.
+    self.RunAndVerify('SeqP/*', [
+        'SeqP/ParamTest.TestX/0',
+        'SeqP/ParamTest.TestX/1',
+        'SeqP/ParamTest.TestY/0',
+        'SeqP/ParamTest.TestY/1',
+        ])
+
+    # Value parameterized tests filtering by the test name.
+    self.RunAndVerify('*/0', [
+        'SeqP/ParamTest.TestX/0',
+        'SeqP/ParamTest.TestY/0',
+        'SeqQ/ParamTest.TestX/0',
+        'SeqQ/ParamTest.TestY/0',
+        ])
+
+  def testFlagOverridesEnvVar(self):
+    """Tests that the filter flag overrides the filtering env. variable."""
+
+    SetEnvVar(FILTER_ENV_VAR, 'Foo*')
+    args = ['--%s=%s' % (FILTER_FLAG, '*One')]
+    tests_run = RunAndExtractTestList(args)[0]
+    SetEnvVar(FILTER_ENV_VAR, None)
+
+    self.AssertSetEqual(tests_run, ['BarTest.TestOne', 'BazTest.TestOne'])
+
+  def testShardStatusFileIsCreated(self):
+    """Tests that the shard file is created if specified in the environment."""
+
+    shard_status_file = os.path.join(gtest_test_utils.GetTempDir(),
+                                     'shard_status_file')
+    self.assert_(not os.path.exists(shard_status_file))
+
+    extra_env = {SHARD_STATUS_FILE_ENV_VAR: shard_status_file}
+    try:
+      InvokeWithModifiedEnv(extra_env, RunAndReturnOutput)
+    finally:
+      self.assert_(os.path.exists(shard_status_file))
+      os.remove(shard_status_file)
+
+  def testShardStatusFileIsCreatedWithListTests(self):
+    """Tests that the shard file is created with the "list_tests" flag."""
+
+    shard_status_file = os.path.join(gtest_test_utils.GetTempDir(),
+                                     'shard_status_file2')
+    self.assert_(not os.path.exists(shard_status_file))
+
+    extra_env = {SHARD_STATUS_FILE_ENV_VAR: shard_status_file}
+    try:
+      output = InvokeWithModifiedEnv(extra_env,
+                                     RunAndReturnOutput,
+                                     [LIST_TESTS_FLAG])
+    finally:
+      # This assertion ensures that Google Test enumerated the tests as
+      # opposed to running them.
+      self.assert_('[==========]' not in output,
+                   'Unexpected output during test enumeration.\n'
+                   'Please ensure that LIST_TESTS_FLAG is assigned the\n'
+                   'correct flag value for listing Google Test tests.')
+
+      self.assert_(os.path.exists(shard_status_file))
+      os.remove(shard_status_file)
+
+  if SUPPORTS_DEATH_TESTS:
+    def testShardingWorksWithDeathTests(self):
+      """Tests integration with death tests and sharding."""
+
+      gtest_filter = 'HasDeathTest.*:SeqP/*'
+      expected_tests = [
+          'HasDeathTest.Test1',
+          'HasDeathTest.Test2',
+
+          'SeqP/ParamTest.TestX/0',
+          'SeqP/ParamTest.TestX/1',
+          'SeqP/ParamTest.TestY/0',
+          'SeqP/ParamTest.TestY/1',
+          ]
+
+      for flag in ['--gtest_death_test_style=threadsafe',
+                   '--gtest_death_test_style=fast']:
+        self.RunAndVerifyWithSharding(gtest_filter, 3, expected_tests,
+                                      check_exit_0=True, args=[flag])
+        self.RunAndVerifyWithSharding(gtest_filter, 5, expected_tests,
+                                      check_exit_0=True, args=[flag])
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/third_party/googletest/googletest/test/gtest_filter_unittest_.cc b/third_party/googletest/googletest/test/gtest_filter_unittest_.cc
new file mode 100644
index 0000000..77deffc
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_filter_unittest_.cc
@@ -0,0 +1,140 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Unit test for Google Test test filters.
+//
+// A user can specify which test(s) in a Google Test program to run via
+// either the GTEST_FILTER environment variable or the --gtest_filter
+// flag.  This is used for testing such functionality.
+//
+// The program will be invoked from a Python unit test.  Don't run it
+// directly.
+
+#include "gtest/gtest.h"
+
+namespace {
+
+// Test case FooTest.
+
+class FooTest : public testing::Test {
+};
+
+TEST_F(FooTest, Abc) {
+}
+
+TEST_F(FooTest, Xyz) {
+  FAIL() << "Expected failure.";
+}
+
+// Test case BarTest.
+
+TEST(BarTest, TestOne) {
+}
+
+TEST(BarTest, TestTwo) {
+}
+
+TEST(BarTest, TestThree) {
+}
+
+TEST(BarTest, DISABLED_TestFour) {
+  FAIL() << "Expected failure.";
+}
+
+TEST(BarTest, DISABLED_TestFive) {
+  FAIL() << "Expected failure.";
+}
+
+// Test case BazTest.
+
+TEST(BazTest, TestOne) {
+  FAIL() << "Expected failure.";
+}
+
+TEST(BazTest, TestA) {
+}
+
+TEST(BazTest, TestB) {
+}
+
+TEST(BazTest, DISABLED_TestC) {
+  FAIL() << "Expected failure.";
+}
+
+// Test case HasDeathTest
+
+TEST(HasDeathTest, Test1) {
+  EXPECT_DEATH_IF_SUPPORTED(exit(1), ".*");
+}
+
+// We need at least two death tests to make sure that the all death tests
+// aren't on the first shard.
+TEST(HasDeathTest, Test2) {
+  EXPECT_DEATH_IF_SUPPORTED(exit(1), ".*");
+}
+
+// Test case FoobarTest
+
+TEST(DISABLED_FoobarTest, Test1) {
+  FAIL() << "Expected failure.";
+}
+
+TEST(DISABLED_FoobarTest, DISABLED_Test2) {
+  FAIL() << "Expected failure.";
+}
+
+// Test case FoobarbazTest
+
+TEST(DISABLED_FoobarbazTest, TestA) {
+  FAIL() << "Expected failure.";
+}
+
+#if GTEST_HAS_PARAM_TEST
+class ParamTest : public testing::TestWithParam<int> {
+};
+
+TEST_P(ParamTest, TestX) {
+}
+
+TEST_P(ParamTest, TestY) {
+}
+
+INSTANTIATE_TEST_CASE_P(SeqP, ParamTest, testing::Values(1, 2));
+INSTANTIATE_TEST_CASE_P(SeqQ, ParamTest, testing::Values(5, 6));
+#endif  // GTEST_HAS_PARAM_TEST
+
+}  // namespace
+
+int main(int argc, char **argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/googletest/googletest/test/gtest_help_test.py b/third_party/googletest/googletest/test/gtest_help_test.py
new file mode 100755
index 0000000..093c838
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_help_test.py
@@ -0,0 +1,172 @@
+#!/usr/bin/env python
+#
+# Copyright 2009, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Tests the --help flag of Google C++ Testing Framework.
+
+SYNOPSIS
+       gtest_help_test.py --build_dir=BUILD/DIR
+         # where BUILD/DIR contains the built gtest_help_test_ file.
+       gtest_help_test.py
+"""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import os
+import re
+import gtest_test_utils
+
+
+IS_LINUX = os.name == 'posix' and os.uname()[0] == 'Linux'
+IS_WINDOWS = os.name == 'nt'
+
+PROGRAM_PATH = gtest_test_utils.GetTestExecutablePath('gtest_help_test_')
+FLAG_PREFIX = '--gtest_'
+DEATH_TEST_STYLE_FLAG = FLAG_PREFIX + 'death_test_style'
+STREAM_RESULT_TO_FLAG = FLAG_PREFIX + 'stream_result_to'
+UNKNOWN_FLAG = FLAG_PREFIX + 'unknown_flag_for_testing'
+LIST_TESTS_FLAG = FLAG_PREFIX + 'list_tests'
+INCORRECT_FLAG_VARIANTS = [re.sub('^--', '-', LIST_TESTS_FLAG),
+                           re.sub('^--', '/', LIST_TESTS_FLAG),
+                           re.sub('_', '-', LIST_TESTS_FLAG)]
+INTERNAL_FLAG_FOR_TESTING = FLAG_PREFIX + 'internal_flag_for_testing'
+
+SUPPORTS_DEATH_TESTS = "DeathTest" in gtest_test_utils.Subprocess(
+    [PROGRAM_PATH, LIST_TESTS_FLAG]).output
+
+# The help message must match this regex.
+HELP_REGEX = re.compile(
+    FLAG_PREFIX + r'list_tests.*' +
+    FLAG_PREFIX + r'filter=.*' +
+    FLAG_PREFIX + r'also_run_disabled_tests.*' +
+    FLAG_PREFIX + r'repeat=.*' +
+    FLAG_PREFIX + r'shuffle.*' +
+    FLAG_PREFIX + r'random_seed=.*' +
+    FLAG_PREFIX + r'color=.*' +
+    FLAG_PREFIX + r'print_time.*' +
+    FLAG_PREFIX + r'output=.*' +
+    FLAG_PREFIX + r'break_on_failure.*' +
+    FLAG_PREFIX + r'throw_on_failure.*' +
+    FLAG_PREFIX + r'catch_exceptions=0.*',
+    re.DOTALL)
+
+
+def RunWithFlag(flag):
+  """Runs gtest_help_test_ with the given flag.
+
+  Returns:
+    the exit code and the text output as a tuple.
+  Args:
+    flag: the command-line flag to pass to gtest_help_test_, or None.
+  """
+
+  if flag is None:
+    command = [PROGRAM_PATH]
+  else:
+    command = [PROGRAM_PATH, flag]
+  child = gtest_test_utils.Subprocess(command)
+  return child.exit_code, child.output
+
+
+class GTestHelpTest(gtest_test_utils.TestCase):
+  """Tests the --help flag and its equivalent forms."""
+
+  def TestHelpFlag(self, flag):
+    """Verifies correct behavior when help flag is specified.
+
+    The right message must be printed and the tests must
+    skipped when the given flag is specified.
+
+    Args:
+      flag:  A flag to pass to the binary or None.
+    """
+
+    exit_code, output = RunWithFlag(flag)
+    self.assertEquals(0, exit_code)
+    self.assert_(HELP_REGEX.search(output), output)
+
+    if IS_LINUX:
+      self.assert_(STREAM_RESULT_TO_FLAG in output, output)
+    else:
+      self.assert_(STREAM_RESULT_TO_FLAG not in output, output)
+
+    if SUPPORTS_DEATH_TESTS and not IS_WINDOWS:
+      self.assert_(DEATH_TEST_STYLE_FLAG in output, output)
+    else:
+      self.assert_(DEATH_TEST_STYLE_FLAG not in output, output)
+
+  def TestNonHelpFlag(self, flag):
+    """Verifies correct behavior when no help flag is specified.
+
+    Verifies that when no help flag is specified, the tests are run
+    and the help message is not printed.
+
+    Args:
+      flag:  A flag to pass to the binary or None.
+    """
+
+    exit_code, output = RunWithFlag(flag)
+    self.assert_(exit_code != 0)
+    self.assert_(not HELP_REGEX.search(output), output)
+
+  def testPrintsHelpWithFullFlag(self):
+    self.TestHelpFlag('--help')
+
+  def testPrintsHelpWithShortFlag(self):
+    self.TestHelpFlag('-h')
+
+  def testPrintsHelpWithQuestionFlag(self):
+    self.TestHelpFlag('-?')
+
+  def testPrintsHelpWithWindowsStyleQuestionFlag(self):
+    self.TestHelpFlag('/?')
+
+  def testPrintsHelpWithUnrecognizedGoogleTestFlag(self):
+    self.TestHelpFlag(UNKNOWN_FLAG)
+
+  def testPrintsHelpWithIncorrectFlagStyle(self):
+    for incorrect_flag in INCORRECT_FLAG_VARIANTS:
+      self.TestHelpFlag(incorrect_flag)
+
+  def testRunsTestsWithoutHelpFlag(self):
+    """Verifies that when no help flag is specified, the tests are run
+    and the help message is not printed."""
+
+    self.TestNonHelpFlag(None)
+
+  def testRunsTestsWithGtestInternalFlag(self):
+    """Verifies that the tests are run and no help message is printed when
+    a flag starting with Google Test prefix and 'internal_' is supplied."""
+
+    self.TestNonHelpFlag(INTERNAL_FLAG_FOR_TESTING)
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/third_party/googletest/googletest/test/gtest_help_test_.cc b/third_party/googletest/googletest/test/gtest_help_test_.cc
new file mode 100644
index 0000000..31f78c2
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_help_test_.cc
@@ -0,0 +1,46 @@
+// Copyright 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// This program is meant to be run by gtest_help_test.py.  Do not run
+// it directly.
+
+#include "gtest/gtest.h"
+
+// When a help flag is specified, this program should skip the tests
+// and exit with 0; otherwise the following test will be executed,
+// causing this program to exit with a non-zero code.
+TEST(HelpFlagTest, ShouldNotBeRun) {
+  ASSERT_TRUE(false) << "Tests shouldn't be run when --help is specified.";
+}
+
+#if GTEST_HAS_DEATH_TEST
+TEST(DeathTest, UsedByPythonScriptToDetectSupportForDeathTestsInThisBinary) {}
+#endif
diff --git a/third_party/googletest/googletest/test/gtest_list_tests_unittest.py b/third_party/googletest/googletest/test/gtest_list_tests_unittest.py
new file mode 100755
index 0000000..925b09d
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_list_tests_unittest.py
@@ -0,0 +1,207 @@
+#!/usr/bin/env python
+#
+# Copyright 2006, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Unit test for Google Test's --gtest_list_tests flag.
+
+A user can ask Google Test to list all tests by specifying the
+--gtest_list_tests flag.  This script tests such functionality
+by invoking gtest_list_tests_unittest_ (a program written with
+Google Test) the command line flags.
+"""
+
+__author__ = 'phanna@google.com (Patrick Hanna)'
+
+import gtest_test_utils
+import re
+
+
+# Constants.
+
+# The command line flag for enabling/disabling listing all tests.
+LIST_TESTS_FLAG = 'gtest_list_tests'
+
+# Path to the gtest_list_tests_unittest_ program.
+EXE_PATH = gtest_test_utils.GetTestExecutablePath('gtest_list_tests_unittest_')
+
+# The expected output when running gtest_list_tests_unittest_ with
+# --gtest_list_tests
+EXPECTED_OUTPUT_NO_FILTER_RE = re.compile(r"""FooDeathTest\.
+  Test1
+Foo\.
+  Bar1
+  Bar2
+  DISABLED_Bar3
+Abc\.
+  Xyz
+  Def
+FooBar\.
+  Baz
+FooTest\.
+  Test1
+  DISABLED_Test2
+  Test3
+TypedTest/0\.  # TypeParam = (VeryLo{245}|class VeryLo{239})\.\.\.
+  TestA
+  TestB
+TypedTest/1\.  # TypeParam = int\s*\*
+  TestA
+  TestB
+TypedTest/2\.  # TypeParam = .*MyArray<bool,\s*42>
+  TestA
+  TestB
+My/TypeParamTest/0\.  # TypeParam = (VeryLo{245}|class VeryLo{239})\.\.\.
+  TestA
+  TestB
+My/TypeParamTest/1\.  # TypeParam = int\s*\*
+  TestA
+  TestB
+My/TypeParamTest/2\.  # TypeParam = .*MyArray<bool,\s*42>
+  TestA
+  TestB
+MyInstantiation/ValueParamTest\.
+  TestA/0  # GetParam\(\) = one line
+  TestA/1  # GetParam\(\) = two\\nlines
+  TestA/2  # GetParam\(\) = a very\\nlo{241}\.\.\.
+  TestB/0  # GetParam\(\) = one line
+  TestB/1  # GetParam\(\) = two\\nlines
+  TestB/2  # GetParam\(\) = a very\\nlo{241}\.\.\.
+""")
+
+# The expected output when running gtest_list_tests_unittest_ with
+# --gtest_list_tests and --gtest_filter=Foo*.
+EXPECTED_OUTPUT_FILTER_FOO_RE = re.compile(r"""FooDeathTest\.
+  Test1
+Foo\.
+  Bar1
+  Bar2
+  DISABLED_Bar3
+FooBar\.
+  Baz
+FooTest\.
+  Test1
+  DISABLED_Test2
+  Test3
+""")
+
+# Utilities.
+
+
+def Run(args):
+  """Runs gtest_list_tests_unittest_ and returns the list of tests printed."""
+
+  return gtest_test_utils.Subprocess([EXE_PATH] + args,
+                                     capture_stderr=False).output
+
+
+# The unit test.
+
+class GTestListTestsUnitTest(gtest_test_utils.TestCase):
+  """Tests using the --gtest_list_tests flag to list all tests."""
+
+  def RunAndVerify(self, flag_value, expected_output_re, other_flag):
+    """Runs gtest_list_tests_unittest_ and verifies that it prints
+    the correct tests.
+
+    Args:
+      flag_value:         value of the --gtest_list_tests flag;
+                          None if the flag should not be present.
+      expected_output_re: regular expression that matches the expected
+                          output after running command;
+      other_flag:         a different flag to be passed to command
+                          along with gtest_list_tests;
+                          None if the flag should not be present.
+    """
+
+    if flag_value is None:
+      flag = ''
+      flag_expression = 'not set'
+    elif flag_value == '0':
+      flag = '--%s=0' % LIST_TESTS_FLAG
+      flag_expression = '0'
+    else:
+      flag = '--%s' % LIST_TESTS_FLAG
+      flag_expression = '1'
+
+    args = [flag]
+
+    if other_flag is not None:
+      args += [other_flag]
+
+    output = Run(args)
+
+    if expected_output_re:
+      self.assert_(
+          expected_output_re.match(output),
+          ('when %s is %s, the output of "%s" is "%s",\n'
+           'which does not match regex "%s"' %
+           (LIST_TESTS_FLAG, flag_expression, ' '.join(args), output,
+            expected_output_re.pattern)))
+    else:
+      self.assert_(
+          not EXPECTED_OUTPUT_NO_FILTER_RE.match(output),
+          ('when %s is %s, the output of "%s" is "%s"'%
+           (LIST_TESTS_FLAG, flag_expression, ' '.join(args), output)))
+
+  def testDefaultBehavior(self):
+    """Tests the behavior of the default mode."""
+
+    self.RunAndVerify(flag_value=None,
+                      expected_output_re=None,
+                      other_flag=None)
+
+  def testFlag(self):
+    """Tests using the --gtest_list_tests flag."""
+
+    self.RunAndVerify(flag_value='0',
+                      expected_output_re=None,
+                      other_flag=None)
+    self.RunAndVerify(flag_value='1',
+                      expected_output_re=EXPECTED_OUTPUT_NO_FILTER_RE,
+                      other_flag=None)
+
+  def testOverrideNonFilterFlags(self):
+    """Tests that --gtest_list_tests overrides the non-filter flags."""
+
+    self.RunAndVerify(flag_value='1',
+                      expected_output_re=EXPECTED_OUTPUT_NO_FILTER_RE,
+                      other_flag='--gtest_break_on_failure')
+
+  def testWithFilterFlags(self):
+    """Tests that --gtest_list_tests takes into account the
+    --gtest_filter flag."""
+
+    self.RunAndVerify(flag_value='1',
+                      expected_output_re=EXPECTED_OUTPUT_FILTER_FOO_RE,
+                      other_flag='--gtest_filter=Foo*')
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/third_party/googletest/googletest/test/gtest_list_tests_unittest_.cc b/third_party/googletest/googletest/test/gtest_list_tests_unittest_.cc
new file mode 100644
index 0000000..907c176
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_list_tests_unittest_.cc
@@ -0,0 +1,157 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: phanna@google.com (Patrick Hanna)
+
+// Unit test for Google Test's --gtest_list_tests flag.
+//
+// A user can ask Google Test to list all tests that will run
+// so that when using a filter, a user will know what
+// tests to look for. The tests will not be run after listing.
+//
+// This program will be invoked from a Python unit test.
+// Don't run it directly.
+
+#include "gtest/gtest.h"
+
+// Several different test cases and tests that will be listed.
+TEST(Foo, Bar1) {
+}
+
+TEST(Foo, Bar2) {
+}
+
+TEST(Foo, DISABLED_Bar3) {
+}
+
+TEST(Abc, Xyz) {
+}
+
+TEST(Abc, Def) {
+}
+
+TEST(FooBar, Baz) {
+}
+
+class FooTest : public testing::Test {
+};
+
+TEST_F(FooTest, Test1) {
+}
+
+TEST_F(FooTest, DISABLED_Test2) {
+}
+
+TEST_F(FooTest, Test3) {
+}
+
+TEST(FooDeathTest, Test1) {
+}
+
+// A group of value-parameterized tests.
+
+class MyType {
+ public:
+  explicit MyType(const std::string& a_value) : value_(a_value) {}
+
+  const std::string& value() const { return value_; }
+
+ private:
+  std::string value_;
+};
+
+// Teaches Google Test how to print a MyType.
+void PrintTo(const MyType& x, std::ostream* os) {
+  *os << x.value();
+}
+
+class ValueParamTest : public testing::TestWithParam<MyType> {
+};
+
+TEST_P(ValueParamTest, TestA) {
+}
+
+TEST_P(ValueParamTest, TestB) {
+}
+
+INSTANTIATE_TEST_CASE_P(
+    MyInstantiation, ValueParamTest,
+    testing::Values(MyType("one line"),
+                    MyType("two\nlines"),
+                    MyType("a very\nloooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong line")));  // NOLINT
+
+// A group of typed tests.
+
+// A deliberately long type name for testing the line-truncating
+// behavior when printing a type parameter.
+class VeryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooogName {  // NOLINT
+};
+
+template <typename T>
+class TypedTest : public testing::Test {
+};
+
+template <typename T, int kSize>
+class MyArray {
+};
+
+typedef testing::Types<VeryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooogName,  // NOLINT
+                       int*, MyArray<bool, 42> > MyTypes;
+
+TYPED_TEST_CASE(TypedTest, MyTypes);
+
+TYPED_TEST(TypedTest, TestA) {
+}
+
+TYPED_TEST(TypedTest, TestB) {
+}
+
+// A group of type-parameterized tests.
+
+template <typename T>
+class TypeParamTest : public testing::Test {
+};
+
+TYPED_TEST_CASE_P(TypeParamTest);
+
+TYPED_TEST_P(TypeParamTest, TestA) {
+}
+
+TYPED_TEST_P(TypeParamTest, TestB) {
+}
+
+REGISTER_TYPED_TEST_CASE_P(TypeParamTest, TestA, TestB);
+
+INSTANTIATE_TYPED_TEST_CASE_P(My, TypeParamTest, MyTypes);
+
+int main(int argc, char **argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/googletest/googletest/test/gtest_main_unittest.cc b/third_party/googletest/googletest/test/gtest_main_unittest.cc
new file mode 100644
index 0000000..ecd9bb8
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_main_unittest.cc
@@ -0,0 +1,45 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include "gtest/gtest.h"
+
+// Tests that we don't have to define main() when we link to
+// gtest_main instead of gtest.
+
+namespace {
+
+TEST(GTestMainTest, ShouldSucceed) {
+}
+
+}  // namespace
+
+// We are using the main() function defined in src/gtest_main.cc, so
+// we don't define it here.
diff --git a/third_party/googletest/googletest/test/gtest_no_test_unittest.cc b/third_party/googletest/googletest/test/gtest_no_test_unittest.cc
new file mode 100644
index 0000000..292599a
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_no_test_unittest.cc
@@ -0,0 +1,56 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Tests that a Google Test program that has no test defined can run
+// successfully.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include "gtest/gtest.h"
+
+int main(int argc, char **argv) {
+  testing::InitGoogleTest(&argc, argv);
+
+  // An ad-hoc assertion outside of all tests.
+  //
+  // This serves three purposes:
+  //
+  // 1. It verifies that an ad-hoc assertion can be executed even if
+  //    no test is defined.
+  // 2. It verifies that a failed ad-hoc assertion causes the test
+  //    program to fail.
+  // 3. We had a bug where the XML output won't be generated if an
+  //    assertion is executed before RUN_ALL_TESTS() is called, even
+  //    though --gtest_output=xml is specified.  This makes sure the
+  //    bug is fixed and doesn't regress.
+  EXPECT_EQ(1, 2);
+
+  // The above EXPECT_EQ() should cause RUN_ALL_TESTS() to return non-zero.
+  return RUN_ALL_TESTS() ? 0 : 1;
+}
diff --git a/third_party/googletest/googletest/test/gtest_output_test.py b/third_party/googletest/googletest/test/gtest_output_test.py
new file mode 100755
index 0000000..d5c637b
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_output_test.py
@@ -0,0 +1,340 @@
+#!/usr/bin/env python
+#
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Tests the text output of Google C++ Testing Framework.
+
+SYNOPSIS
+       gtest_output_test.py --build_dir=BUILD/DIR --gengolden
+         # where BUILD/DIR contains the built gtest_output_test_ file.
+       gtest_output_test.py --gengolden
+       gtest_output_test.py
+"""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import difflib
+import os
+import re
+import sys
+import gtest_test_utils
+
+
+# The flag for generating the golden file
+GENGOLDEN_FLAG = '--gengolden'
+CATCH_EXCEPTIONS_ENV_VAR_NAME = 'GTEST_CATCH_EXCEPTIONS'
+
+IS_WINDOWS = os.name == 'nt'
+
+# TODO(vladl@google.com): remove the _lin suffix.
+GOLDEN_NAME = 'gtest_output_test_golden_lin.txt'
+
+PROGRAM_PATH = gtest_test_utils.GetTestExecutablePath('gtest_output_test_')
+
+# At least one command we exercise must not have the
+# 'internal_skip_environment_and_ad_hoc_tests' argument.
+COMMAND_LIST_TESTS = ({}, [PROGRAM_PATH, '--gtest_list_tests'])
+COMMAND_WITH_COLOR = ({}, [PROGRAM_PATH, '--gtest_color=yes'])
+COMMAND_WITH_TIME = ({}, [PROGRAM_PATH,
+                          '--gtest_print_time',
+                          'internal_skip_environment_and_ad_hoc_tests',
+                          '--gtest_filter=FatalFailureTest.*:LoggingTest.*'])
+COMMAND_WITH_DISABLED = (
+    {}, [PROGRAM_PATH,
+         '--gtest_also_run_disabled_tests',
+         'internal_skip_environment_and_ad_hoc_tests',
+         '--gtest_filter=*DISABLED_*'])
+COMMAND_WITH_SHARDING = (
+    {'GTEST_SHARD_INDEX': '1', 'GTEST_TOTAL_SHARDS': '2'},
+    [PROGRAM_PATH,
+     'internal_skip_environment_and_ad_hoc_tests',
+     '--gtest_filter=PassingTest.*'])
+
+GOLDEN_PATH = os.path.join(gtest_test_utils.GetSourceDir(), GOLDEN_NAME)
+
+
+def ToUnixLineEnding(s):
+  """Changes all Windows/Mac line endings in s to UNIX line endings."""
+
+  return s.replace('\r\n', '\n').replace('\r', '\n')
+
+
+def RemoveLocations(test_output):
+  """Removes all file location info from a Google Test program's output.
+
+  Args:
+       test_output:  the output of a Google Test program.
+
+  Returns:
+       output with all file location info (in the form of
+       'DIRECTORY/FILE_NAME:LINE_NUMBER: 'or
+       'DIRECTORY\\FILE_NAME(LINE_NUMBER): ') replaced by
+       'FILE_NAME:#: '.
+  """
+
+  return re.sub(r'.*[/\\](.+)(\:\d+|\(\d+\))\: ', r'\1:#: ', test_output)
+
+
+def RemoveStackTraceDetails(output):
+  """Removes all stack traces from a Google Test program's output."""
+
+  # *? means "find the shortest string that matches".
+  return re.sub(r'Stack trace:(.|\n)*?\n\n',
+                'Stack trace: (omitted)\n\n', output)
+
+
+def RemoveStackTraces(output):
+  """Removes all traces of stack traces from a Google Test program's output."""
+
+  # *? means "find the shortest string that matches".
+  return re.sub(r'Stack trace:(.|\n)*?\n\n', '', output)
+
+
+def RemoveTime(output):
+  """Removes all time information from a Google Test program's output."""
+
+  return re.sub(r'\(\d+ ms', '(? ms', output)
+
+
+def RemoveTypeInfoDetails(test_output):
+  """Removes compiler-specific type info from Google Test program's output.
+
+  Args:
+       test_output:  the output of a Google Test program.
+
+  Returns:
+       output with type information normalized to canonical form.
+  """
+
+  # some compilers output the name of type 'unsigned int' as 'unsigned'
+  return re.sub(r'unsigned int', 'unsigned', test_output)
+
+
+def NormalizeToCurrentPlatform(test_output):
+  """Normalizes platform specific output details for easier comparison."""
+
+  if IS_WINDOWS:
+    # Removes the color information that is not present on Windows.
+    test_output = re.sub('\x1b\\[(0;3\d)?m', '', test_output)
+    # Changes failure message headers into the Windows format.
+    test_output = re.sub(r': Failure\n', r': error: ', test_output)
+    # Changes file(line_number) to file:line_number.
+    test_output = re.sub(r'((\w|\.)+)\((\d+)\):', r'\1:\3:', test_output)
+
+  return test_output
+
+
+def RemoveTestCounts(output):
+  """Removes test counts from a Google Test program's output."""
+
+  output = re.sub(r'\d+ tests?, listed below',
+                  '? tests, listed below', output)
+  output = re.sub(r'\d+ FAILED TESTS',
+                  '? FAILED TESTS', output)
+  output = re.sub(r'\d+ tests? from \d+ test cases?',
+                  '? tests from ? test cases', output)
+  output = re.sub(r'\d+ tests? from ([a-zA-Z_])',
+                  r'? tests from \1', output)
+  return re.sub(r'\d+ tests?\.', '? tests.', output)
+
+
+def RemoveMatchingTests(test_output, pattern):
+  """Removes output of specified tests from a Google Test program's output.
+
+  This function strips not only the beginning and the end of a test but also
+  all output in between.
+
+  Args:
+    test_output:       A string containing the test output.
+    pattern:           A regex string that matches names of test cases or
+                       tests to remove.
+
+  Returns:
+    Contents of test_output with tests whose names match pattern removed.
+  """
+
+  test_output = re.sub(
+      r'.*\[ RUN      \] .*%s(.|\n)*?\[(  FAILED  |       OK )\] .*%s.*\n' % (
+          pattern, pattern),
+      '',
+      test_output)
+  return re.sub(r'.*%s.*\n' % pattern, '', test_output)
+
+
+def NormalizeOutput(output):
+  """Normalizes output (the output of gtest_output_test_.exe)."""
+
+  output = ToUnixLineEnding(output)
+  output = RemoveLocations(output)
+  output = RemoveStackTraceDetails(output)
+  output = RemoveTime(output)
+  return output
+
+
+def GetShellCommandOutput(env_cmd):
+  """Runs a command in a sub-process, and returns its output in a string.
+
+  Args:
+    env_cmd: The shell command. A 2-tuple where element 0 is a dict of extra
+             environment variables to set, and element 1 is a string with
+             the command and any flags.
+
+  Returns:
+    A string with the command's combined standard and diagnostic output.
+  """
+
+  # Spawns cmd in a sub-process, and gets its standard I/O file objects.
+  # Set and save the environment properly.
+  environ = os.environ.copy()
+  environ.update(env_cmd[0])
+  p = gtest_test_utils.Subprocess(env_cmd[1], env=environ)
+
+  return p.output
+
+
+def GetCommandOutput(env_cmd):
+  """Runs a command and returns its output with all file location
+  info stripped off.
+
+  Args:
+    env_cmd:  The shell command. A 2-tuple where element 0 is a dict of extra
+              environment variables to set, and element 1 is a string with
+              the command and any flags.
+  """
+
+  # Disables exception pop-ups on Windows.
+  environ, cmdline = env_cmd
+  environ = dict(environ)  # Ensures we are modifying a copy.
+  environ[CATCH_EXCEPTIONS_ENV_VAR_NAME] = '1'
+  return NormalizeOutput(GetShellCommandOutput((environ, cmdline)))
+
+
+def GetOutputOfAllCommands():
+  """Returns concatenated output from several representative commands."""
+
+  return (GetCommandOutput(COMMAND_WITH_COLOR) +
+          GetCommandOutput(COMMAND_WITH_TIME) +
+          GetCommandOutput(COMMAND_WITH_DISABLED) +
+          GetCommandOutput(COMMAND_WITH_SHARDING))
+
+
+test_list = GetShellCommandOutput(COMMAND_LIST_TESTS)
+SUPPORTS_DEATH_TESTS = 'DeathTest' in test_list
+SUPPORTS_TYPED_TESTS = 'TypedTest' in test_list
+SUPPORTS_THREADS = 'ExpectFailureWithThreadsTest' in test_list
+SUPPORTS_STACK_TRACES = False
+
+CAN_GENERATE_GOLDEN_FILE = (SUPPORTS_DEATH_TESTS and
+                            SUPPORTS_TYPED_TESTS and
+                            SUPPORTS_THREADS and
+                            not IS_WINDOWS)
+
+class GTestOutputTest(gtest_test_utils.TestCase):
+  def RemoveUnsupportedTests(self, test_output):
+    if not SUPPORTS_DEATH_TESTS:
+      test_output = RemoveMatchingTests(test_output, 'DeathTest')
+    if not SUPPORTS_TYPED_TESTS:
+      test_output = RemoveMatchingTests(test_output, 'TypedTest')
+      test_output = RemoveMatchingTests(test_output, 'TypedDeathTest')
+      test_output = RemoveMatchingTests(test_output, 'TypeParamDeathTest')
+    if not SUPPORTS_THREADS:
+      test_output = RemoveMatchingTests(test_output,
+                                        'ExpectFailureWithThreadsTest')
+      test_output = RemoveMatchingTests(test_output,
+                                        'ScopedFakeTestPartResultReporterTest')
+      test_output = RemoveMatchingTests(test_output,
+                                        'WorksConcurrently')
+    if not SUPPORTS_STACK_TRACES:
+      test_output = RemoveStackTraces(test_output)
+
+    return test_output
+
+  def testOutput(self):
+    output = GetOutputOfAllCommands()
+
+    golden_file = open(GOLDEN_PATH, 'rb')
+    # A mis-configured source control system can cause \r appear in EOL
+    # sequences when we read the golden file irrespective of an operating
+    # system used. Therefore, we need to strip those \r's from newlines
+    # unconditionally.
+    golden = ToUnixLineEnding(golden_file.read())
+    golden_file.close()
+
+    # We want the test to pass regardless of certain features being
+    # supported or not.
+
+    # We still have to remove type name specifics in all cases.
+    normalized_actual = RemoveTypeInfoDetails(output)
+    normalized_golden = RemoveTypeInfoDetails(golden)
+
+    if CAN_GENERATE_GOLDEN_FILE:
+      self.assertEqual(normalized_golden, normalized_actual,
+                       '\n'.join(difflib.unified_diff(
+                           normalized_golden.split('\n'),
+                           normalized_actual.split('\n'),
+                           'golden', 'actual')))
+    else:
+      normalized_actual = NormalizeToCurrentPlatform(
+          RemoveTestCounts(normalized_actual))
+      normalized_golden = NormalizeToCurrentPlatform(
+          RemoveTestCounts(self.RemoveUnsupportedTests(normalized_golden)))
+
+      # This code is very handy when debugging golden file differences:
+      if os.getenv('DEBUG_GTEST_OUTPUT_TEST'):
+        open(os.path.join(
+            gtest_test_utils.GetSourceDir(),
+            '_gtest_output_test_normalized_actual.txt'), 'wb').write(
+                normalized_actual)
+        open(os.path.join(
+            gtest_test_utils.GetSourceDir(),
+            '_gtest_output_test_normalized_golden.txt'), 'wb').write(
+                normalized_golden)
+
+      self.assertEqual(normalized_golden, normalized_actual)
+
+
+if __name__ == '__main__':
+  if sys.argv[1:] == [GENGOLDEN_FLAG]:
+    if CAN_GENERATE_GOLDEN_FILE:
+      output = GetOutputOfAllCommands()
+      golden_file = open(GOLDEN_PATH, 'wb')
+      golden_file.write(output)
+      golden_file.close()
+    else:
+      message = (
+          """Unable to write a golden file when compiled in an environment
+that does not support all the required features (death tests, typed tests,
+and multiple threads).  Please generate the golden file using a binary built
+with those features enabled.""")
+
+      sys.stderr.write(message)
+      sys.exit(1)
+  else:
+    gtest_test_utils.Main()
diff --git a/third_party/googletest/googletest/test/gtest_output_test_.cc b/third_party/googletest/googletest/test/gtest_output_test_.cc
new file mode 100644
index 0000000..1070a9f
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_output_test_.cc
@@ -0,0 +1,1062 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The purpose of this file is to generate Google Test output under
+// various conditions.  The output will then be verified by
+// gtest_output_test.py to ensure that Google Test generates the
+// desired messages.  Therefore, most tests in this file are MEANT TO
+// FAIL.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include "gtest/gtest-spi.h"
+#include "gtest/gtest.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+#include <stdlib.h>
+
+#if GTEST_IS_THREADSAFE
+using testing::ScopedFakeTestPartResultReporter;
+using testing::TestPartResultArray;
+
+using testing::internal::Notification;
+using testing::internal::ThreadWithParam;
+#endif
+
+namespace posix = ::testing::internal::posix;
+
+// Tests catching fatal failures.
+
+// A subroutine used by the following test.
+void TestEq1(int x) {
+  ASSERT_EQ(1, x);
+}
+
+// This function calls a test subroutine, catches the fatal failure it
+// generates, and then returns early.
+void TryTestSubroutine() {
+  // Calls a subrountine that yields a fatal failure.
+  TestEq1(2);
+
+  // Catches the fatal failure and aborts the test.
+  //
+  // The testing::Test:: prefix is necessary when calling
+  // HasFatalFailure() outside of a TEST, TEST_F, or test fixture.
+  if (testing::Test::HasFatalFailure()) return;
+
+  // If we get here, something is wrong.
+  FAIL() << "This should never be reached.";
+}
+
+TEST(PassingTest, PassingTest1) {
+}
+
+TEST(PassingTest, PassingTest2) {
+}
+
+// Tests that parameters of failing parameterized tests are printed in the
+// failing test summary.
+class FailingParamTest : public testing::TestWithParam<int> {};
+
+TEST_P(FailingParamTest, Fails) {
+  EXPECT_EQ(1, GetParam());
+}
+
+// This generates a test which will fail. Google Test is expected to print
+// its parameter when it outputs the list of all failed tests.
+INSTANTIATE_TEST_CASE_P(PrintingFailingParams,
+                        FailingParamTest,
+                        testing::Values(2));
+
+static const char kGoldenString[] = "\"Line\0 1\"\nLine 2";
+
+TEST(NonfatalFailureTest, EscapesStringOperands) {
+  std::string actual = "actual \"string\"";
+  EXPECT_EQ(kGoldenString, actual);
+
+  const char* golden = kGoldenString;
+  EXPECT_EQ(golden, actual);
+}
+
+TEST(NonfatalFailureTest, DiffForLongStrings) {
+  std::string golden_str(kGoldenString, sizeof(kGoldenString) - 1);
+  EXPECT_EQ(golden_str, "Line 2");
+}
+
+// Tests catching a fatal failure in a subroutine.
+TEST(FatalFailureTest, FatalFailureInSubroutine) {
+  printf("(expecting a failure that x should be 1)\n");
+
+  TryTestSubroutine();
+}
+
+// Tests catching a fatal failure in a nested subroutine.
+TEST(FatalFailureTest, FatalFailureInNestedSubroutine) {
+  printf("(expecting a failure that x should be 1)\n");
+
+  // Calls a subrountine that yields a fatal failure.
+  TryTestSubroutine();
+
+  // Catches the fatal failure and aborts the test.
+  //
+  // When calling HasFatalFailure() inside a TEST, TEST_F, or test
+  // fixture, the testing::Test:: prefix is not needed.
+  if (HasFatalFailure()) return;
+
+  // If we get here, something is wrong.
+  FAIL() << "This should never be reached.";
+}
+
+// Tests HasFatalFailure() after a failed EXPECT check.
+TEST(FatalFailureTest, NonfatalFailureInSubroutine) {
+  printf("(expecting a failure on false)\n");
+  EXPECT_TRUE(false);  // Generates a nonfatal failure
+  ASSERT_FALSE(HasFatalFailure());  // This should succeed.
+}
+
+// Tests interleaving user logging and Google Test assertions.
+TEST(LoggingTest, InterleavingLoggingAndAssertions) {
+  static const int a[4] = {
+    3, 9, 2, 6
+  };
+
+  printf("(expecting 2 failures on (3) >= (a[i]))\n");
+  for (int i = 0; i < static_cast<int>(sizeof(a)/sizeof(*a)); i++) {
+    printf("i == %d\n", i);
+    EXPECT_GE(3, a[i]);
+  }
+}
+
+// Tests the SCOPED_TRACE macro.
+
+// A helper function for testing SCOPED_TRACE.
+void SubWithoutTrace(int n) {
+  EXPECT_EQ(1, n);
+  ASSERT_EQ(2, n);
+}
+
+// Another helper function for testing SCOPED_TRACE.
+void SubWithTrace(int n) {
+  SCOPED_TRACE(testing::Message() << "n = " << n);
+
+  SubWithoutTrace(n);
+}
+
+// Tests that SCOPED_TRACE() obeys lexical scopes.
+TEST(SCOPED_TRACETest, ObeysScopes) {
+  printf("(expected to fail)\n");
+
+  // There should be no trace before SCOPED_TRACE() is invoked.
+  ADD_FAILURE() << "This failure is expected, and shouldn't have a trace.";
+
+  {
+    SCOPED_TRACE("Expected trace");
+    // After SCOPED_TRACE(), a failure in the current scope should contain
+    // the trace.
+    ADD_FAILURE() << "This failure is expected, and should have a trace.";
+  }
+
+  // Once the control leaves the scope of the SCOPED_TRACE(), there
+  // should be no trace again.
+  ADD_FAILURE() << "This failure is expected, and shouldn't have a trace.";
+}
+
+// Tests that SCOPED_TRACE works inside a loop.
+TEST(SCOPED_TRACETest, WorksInLoop) {
+  printf("(expected to fail)\n");
+
+  for (int i = 1; i <= 2; i++) {
+    SCOPED_TRACE(testing::Message() << "i = " << i);
+
+    SubWithoutTrace(i);
+  }
+}
+
+// Tests that SCOPED_TRACE works in a subroutine.
+TEST(SCOPED_TRACETest, WorksInSubroutine) {
+  printf("(expected to fail)\n");
+
+  SubWithTrace(1);
+  SubWithTrace(2);
+}
+
+// Tests that SCOPED_TRACE can be nested.
+TEST(SCOPED_TRACETest, CanBeNested) {
+  printf("(expected to fail)\n");
+
+  SCOPED_TRACE("");  // A trace without a message.
+
+  SubWithTrace(2);
+}
+
+// Tests that multiple SCOPED_TRACEs can be used in the same scope.
+TEST(SCOPED_TRACETest, CanBeRepeated) {
+  printf("(expected to fail)\n");
+
+  SCOPED_TRACE("A");
+  ADD_FAILURE()
+      << "This failure is expected, and should contain trace point A.";
+
+  SCOPED_TRACE("B");
+  ADD_FAILURE()
+      << "This failure is expected, and should contain trace point A and B.";
+
+  {
+    SCOPED_TRACE("C");
+    ADD_FAILURE() << "This failure is expected, and should "
+                  << "contain trace point A, B, and C.";
+  }
+
+  SCOPED_TRACE("D");
+  ADD_FAILURE() << "This failure is expected, and should "
+                << "contain trace point A, B, and D.";
+}
+
+#if GTEST_IS_THREADSAFE
+// Tests that SCOPED_TRACE()s can be used concurrently from multiple
+// threads.  Namely, an assertion should be affected by
+// SCOPED_TRACE()s in its own thread only.
+
+// Here's the sequence of actions that happen in the test:
+//
+//   Thread A (main)                | Thread B (spawned)
+//   ===============================|================================
+//   spawns thread B                |
+//   -------------------------------+--------------------------------
+//   waits for n1                   | SCOPED_TRACE("Trace B");
+//                                  | generates failure #1
+//                                  | notifies n1
+//   -------------------------------+--------------------------------
+//   SCOPED_TRACE("Trace A");       | waits for n2
+//   generates failure #2           |
+//   notifies n2                    |
+//   -------------------------------|--------------------------------
+//   waits for n3                   | generates failure #3
+//                                  | trace B dies
+//                                  | generates failure #4
+//                                  | notifies n3
+//   -------------------------------|--------------------------------
+//   generates failure #5           | finishes
+//   trace A dies                   |
+//   generates failure #6           |
+//   -------------------------------|--------------------------------
+//   waits for thread B to finish   |
+
+struct CheckPoints {
+  Notification n1;
+  Notification n2;
+  Notification n3;
+};
+
+static void ThreadWithScopedTrace(CheckPoints* check_points) {
+  {
+    SCOPED_TRACE("Trace B");
+    ADD_FAILURE()
+        << "Expected failure #1 (in thread B, only trace B alive).";
+    check_points->n1.Notify();
+    check_points->n2.WaitForNotification();
+
+    ADD_FAILURE()
+        << "Expected failure #3 (in thread B, trace A & B both alive).";
+  }  // Trace B dies here.
+  ADD_FAILURE()
+      << "Expected failure #4 (in thread B, only trace A alive).";
+  check_points->n3.Notify();
+}
+
+TEST(SCOPED_TRACETest, WorksConcurrently) {
+  printf("(expecting 6 failures)\n");
+
+  CheckPoints check_points;
+  ThreadWithParam<CheckPoints*> thread(&ThreadWithScopedTrace,
+                                       &check_points,
+                                       NULL);
+  check_points.n1.WaitForNotification();
+
+  {
+    SCOPED_TRACE("Trace A");
+    ADD_FAILURE()
+        << "Expected failure #2 (in thread A, trace A & B both alive).";
+    check_points.n2.Notify();
+    check_points.n3.WaitForNotification();
+
+    ADD_FAILURE()
+        << "Expected failure #5 (in thread A, only trace A alive).";
+  }  // Trace A dies here.
+  ADD_FAILURE()
+      << "Expected failure #6 (in thread A, no trace alive).";
+  thread.Join();
+}
+#endif  // GTEST_IS_THREADSAFE
+
+TEST(DisabledTestsWarningTest,
+     DISABLED_AlsoRunDisabledTestsFlagSuppressesWarning) {
+  // This test body is intentionally empty.  Its sole purpose is for
+  // verifying that the --gtest_also_run_disabled_tests flag
+  // suppresses the "YOU HAVE 12 DISABLED TESTS" warning at the end of
+  // the test output.
+}
+
+// Tests using assertions outside of TEST and TEST_F.
+//
+// This function creates two failures intentionally.
+void AdHocTest() {
+  printf("The non-test part of the code is expected to have 2 failures.\n\n");
+  EXPECT_TRUE(false);
+  EXPECT_EQ(2, 3);
+}
+
+// Runs all TESTs, all TEST_Fs, and the ad hoc test.
+int RunAllTests() {
+  AdHocTest();
+  return RUN_ALL_TESTS();
+}
+
+// Tests non-fatal failures in the fixture constructor.
+class NonFatalFailureInFixtureConstructorTest : public testing::Test {
+ protected:
+  NonFatalFailureInFixtureConstructorTest() {
+    printf("(expecting 5 failures)\n");
+    ADD_FAILURE() << "Expected failure #1, in the test fixture c'tor.";
+  }
+
+  ~NonFatalFailureInFixtureConstructorTest() {
+    ADD_FAILURE() << "Expected failure #5, in the test fixture d'tor.";
+  }
+
+  virtual void SetUp() {
+    ADD_FAILURE() << "Expected failure #2, in SetUp().";
+  }
+
+  virtual void TearDown() {
+    ADD_FAILURE() << "Expected failure #4, in TearDown.";
+  }
+};
+
+TEST_F(NonFatalFailureInFixtureConstructorTest, FailureInConstructor) {
+  ADD_FAILURE() << "Expected failure #3, in the test body.";
+}
+
+// Tests fatal failures in the fixture constructor.
+class FatalFailureInFixtureConstructorTest : public testing::Test {
+ protected:
+  FatalFailureInFixtureConstructorTest() {
+    printf("(expecting 2 failures)\n");
+    Init();
+  }
+
+  ~FatalFailureInFixtureConstructorTest() {
+    ADD_FAILURE() << "Expected failure #2, in the test fixture d'tor.";
+  }
+
+  virtual void SetUp() {
+    ADD_FAILURE() << "UNEXPECTED failure in SetUp().  "
+                  << "We should never get here, as the test fixture c'tor "
+                  << "had a fatal failure.";
+  }
+
+  virtual void TearDown() {
+    ADD_FAILURE() << "UNEXPECTED failure in TearDown().  "
+                  << "We should never get here, as the test fixture c'tor "
+                  << "had a fatal failure.";
+  }
+
+ private:
+  void Init() {
+    FAIL() << "Expected failure #1, in the test fixture c'tor.";
+  }
+};
+
+TEST_F(FatalFailureInFixtureConstructorTest, FailureInConstructor) {
+  ADD_FAILURE() << "UNEXPECTED failure in the test body.  "
+                << "We should never get here, as the test fixture c'tor "
+                << "had a fatal failure.";
+}
+
+// Tests non-fatal failures in SetUp().
+class NonFatalFailureInSetUpTest : public testing::Test {
+ protected:
+  virtual ~NonFatalFailureInSetUpTest() {
+    Deinit();
+  }
+
+  virtual void SetUp() {
+    printf("(expecting 4 failures)\n");
+    ADD_FAILURE() << "Expected failure #1, in SetUp().";
+  }
+
+  virtual void TearDown() {
+    FAIL() << "Expected failure #3, in TearDown().";
+  }
+ private:
+  void Deinit() {
+    FAIL() << "Expected failure #4, in the test fixture d'tor.";
+  }
+};
+
+TEST_F(NonFatalFailureInSetUpTest, FailureInSetUp) {
+  FAIL() << "Expected failure #2, in the test function.";
+}
+
+// Tests fatal failures in SetUp().
+class FatalFailureInSetUpTest : public testing::Test {
+ protected:
+  virtual ~FatalFailureInSetUpTest() {
+    Deinit();
+  }
+
+  virtual void SetUp() {
+    printf("(expecting 3 failures)\n");
+    FAIL() << "Expected failure #1, in SetUp().";
+  }
+
+  virtual void TearDown() {
+    FAIL() << "Expected failure #2, in TearDown().";
+  }
+ private:
+  void Deinit() {
+    FAIL() << "Expected failure #3, in the test fixture d'tor.";
+  }
+};
+
+TEST_F(FatalFailureInSetUpTest, FailureInSetUp) {
+  FAIL() << "UNEXPECTED failure in the test function.  "
+         << "We should never get here, as SetUp() failed.";
+}
+
+TEST(AddFailureAtTest, MessageContainsSpecifiedFileAndLineNumber) {
+  ADD_FAILURE_AT("foo.cc", 42) << "Expected failure in foo.cc";
+}
+
+#if GTEST_IS_THREADSAFE
+
+// A unary function that may die.
+void DieIf(bool should_die) {
+  GTEST_CHECK_(!should_die) << " - death inside DieIf().";
+}
+
+// Tests running death tests in a multi-threaded context.
+
+// Used for coordination between the main and the spawn thread.
+struct SpawnThreadNotifications {
+  SpawnThreadNotifications() {}
+
+  Notification spawn_thread_started;
+  Notification spawn_thread_ok_to_terminate;
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(SpawnThreadNotifications);
+};
+
+// The function to be executed in the thread spawn by the
+// MultipleThreads test (below).
+static void ThreadRoutine(SpawnThreadNotifications* notifications) {
+  // Signals the main thread that this thread has started.
+  notifications->spawn_thread_started.Notify();
+
+  // Waits for permission to finish from the main thread.
+  notifications->spawn_thread_ok_to_terminate.WaitForNotification();
+}
+
+// This is a death-test test, but it's not named with a DeathTest
+// suffix.  It starts threads which might interfere with later
+// death tests, so it must run after all other death tests.
+class DeathTestAndMultiThreadsTest : public testing::Test {
+ protected:
+  // Starts a thread and waits for it to begin.
+  virtual void SetUp() {
+    thread_.reset(new ThreadWithParam<SpawnThreadNotifications*>(
+        &ThreadRoutine, &notifications_, NULL));
+    notifications_.spawn_thread_started.WaitForNotification();
+  }
+  // Tells the thread to finish, and reaps it.
+  // Depending on the version of the thread library in use,
+  // a manager thread might still be left running that will interfere
+  // with later death tests.  This is unfortunate, but this class
+  // cleans up after itself as best it can.
+  virtual void TearDown() {
+    notifications_.spawn_thread_ok_to_terminate.Notify();
+  }
+
+ private:
+  SpawnThreadNotifications notifications_;
+  testing::internal::scoped_ptr<ThreadWithParam<SpawnThreadNotifications*> >
+      thread_;
+};
+
+#endif  // GTEST_IS_THREADSAFE
+
+// The MixedUpTestCaseTest test case verifies that Google Test will fail a
+// test if it uses a different fixture class than what other tests in
+// the same test case use.  It deliberately contains two fixture
+// classes with the same name but defined in different namespaces.
+
+// The MixedUpTestCaseWithSameTestNameTest test case verifies that
+// when the user defines two tests with the same test case name AND
+// same test name (but in different namespaces), the second test will
+// fail.
+
+namespace foo {
+
+class MixedUpTestCaseTest : public testing::Test {
+};
+
+TEST_F(MixedUpTestCaseTest, FirstTestFromNamespaceFoo) {}
+TEST_F(MixedUpTestCaseTest, SecondTestFromNamespaceFoo) {}
+
+class MixedUpTestCaseWithSameTestNameTest : public testing::Test {
+};
+
+TEST_F(MixedUpTestCaseWithSameTestNameTest,
+       TheSecondTestWithThisNameShouldFail) {}
+
+}  // namespace foo
+
+namespace bar {
+
+class MixedUpTestCaseTest : public testing::Test {
+};
+
+// The following two tests are expected to fail.  We rely on the
+// golden file to check that Google Test generates the right error message.
+TEST_F(MixedUpTestCaseTest, ThisShouldFail) {}
+TEST_F(MixedUpTestCaseTest, ThisShouldFailToo) {}
+
+class MixedUpTestCaseWithSameTestNameTest : public testing::Test {
+};
+
+// Expected to fail.  We rely on the golden file to check that Google Test
+// generates the right error message.
+TEST_F(MixedUpTestCaseWithSameTestNameTest,
+       TheSecondTestWithThisNameShouldFail) {}
+
+}  // namespace bar
+
+// The following two test cases verify that Google Test catches the user
+// error of mixing TEST and TEST_F in the same test case.  The first
+// test case checks the scenario where TEST_F appears before TEST, and
+// the second one checks where TEST appears before TEST_F.
+
+class TEST_F_before_TEST_in_same_test_case : public testing::Test {
+};
+
+TEST_F(TEST_F_before_TEST_in_same_test_case, DefinedUsingTEST_F) {}
+
+// Expected to fail.  We rely on the golden file to check that Google Test
+// generates the right error message.
+TEST(TEST_F_before_TEST_in_same_test_case, DefinedUsingTESTAndShouldFail) {}
+
+class TEST_before_TEST_F_in_same_test_case : public testing::Test {
+};
+
+TEST(TEST_before_TEST_F_in_same_test_case, DefinedUsingTEST) {}
+
+// Expected to fail.  We rely on the golden file to check that Google Test
+// generates the right error message.
+TEST_F(TEST_before_TEST_F_in_same_test_case, DefinedUsingTEST_FAndShouldFail) {
+}
+
+// Used for testing EXPECT_NONFATAL_FAILURE() and EXPECT_FATAL_FAILURE().
+int global_integer = 0;
+
+// Tests that EXPECT_NONFATAL_FAILURE() can reference global variables.
+TEST(ExpectNonfatalFailureTest, CanReferenceGlobalVariables) {
+  global_integer = 0;
+  EXPECT_NONFATAL_FAILURE({
+    EXPECT_EQ(1, global_integer) << "Expected non-fatal failure.";
+  }, "Expected non-fatal failure.");
+}
+
+// Tests that EXPECT_NONFATAL_FAILURE() can reference local variables
+// (static or not).
+TEST(ExpectNonfatalFailureTest, CanReferenceLocalVariables) {
+  int m = 0;
+  static int n;
+  n = 1;
+  EXPECT_NONFATAL_FAILURE({
+    EXPECT_EQ(m, n) << "Expected non-fatal failure.";
+  }, "Expected non-fatal failure.");
+}
+
+// Tests that EXPECT_NONFATAL_FAILURE() succeeds when there is exactly
+// one non-fatal failure and no fatal failure.
+TEST(ExpectNonfatalFailureTest, SucceedsWhenThereIsOneNonfatalFailure) {
+  EXPECT_NONFATAL_FAILURE({
+    ADD_FAILURE() << "Expected non-fatal failure.";
+  }, "Expected non-fatal failure.");
+}
+
+// Tests that EXPECT_NONFATAL_FAILURE() fails when there is no
+// non-fatal failure.
+TEST(ExpectNonfatalFailureTest, FailsWhenThereIsNoNonfatalFailure) {
+  printf("(expecting a failure)\n");
+  EXPECT_NONFATAL_FAILURE({
+  }, "");
+}
+
+// Tests that EXPECT_NONFATAL_FAILURE() fails when there are two
+// non-fatal failures.
+TEST(ExpectNonfatalFailureTest, FailsWhenThereAreTwoNonfatalFailures) {
+  printf("(expecting a failure)\n");
+  EXPECT_NONFATAL_FAILURE({
+    ADD_FAILURE() << "Expected non-fatal failure 1.";
+    ADD_FAILURE() << "Expected non-fatal failure 2.";
+  }, "");
+}
+
+// Tests that EXPECT_NONFATAL_FAILURE() fails when there is one fatal
+// failure.
+TEST(ExpectNonfatalFailureTest, FailsWhenThereIsOneFatalFailure) {
+  printf("(expecting a failure)\n");
+  EXPECT_NONFATAL_FAILURE({
+    FAIL() << "Expected fatal failure.";
+  }, "");
+}
+
+// Tests that EXPECT_NONFATAL_FAILURE() fails when the statement being
+// tested returns.
+TEST(ExpectNonfatalFailureTest, FailsWhenStatementReturns) {
+  printf("(expecting a failure)\n");
+  EXPECT_NONFATAL_FAILURE({
+    return;
+  }, "");
+}
+
+#if GTEST_HAS_EXCEPTIONS
+
+// Tests that EXPECT_NONFATAL_FAILURE() fails when the statement being
+// tested throws.
+TEST(ExpectNonfatalFailureTest, FailsWhenStatementThrows) {
+  printf("(expecting a failure)\n");
+  try {
+    EXPECT_NONFATAL_FAILURE({
+      throw 0;
+    }, "");
+  } catch(int) {  // NOLINT
+  }
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// Tests that EXPECT_FATAL_FAILURE() can reference global variables.
+TEST(ExpectFatalFailureTest, CanReferenceGlobalVariables) {
+  global_integer = 0;
+  EXPECT_FATAL_FAILURE({
+    ASSERT_EQ(1, global_integer) << "Expected fatal failure.";
+  }, "Expected fatal failure.");
+}
+
+// Tests that EXPECT_FATAL_FAILURE() can reference local static
+// variables.
+TEST(ExpectFatalFailureTest, CanReferenceLocalStaticVariables) {
+  static int n;
+  n = 1;
+  EXPECT_FATAL_FAILURE({
+    ASSERT_EQ(0, n) << "Expected fatal failure.";
+  }, "Expected fatal failure.");
+}
+
+// Tests that EXPECT_FATAL_FAILURE() succeeds when there is exactly
+// one fatal failure and no non-fatal failure.
+TEST(ExpectFatalFailureTest, SucceedsWhenThereIsOneFatalFailure) {
+  EXPECT_FATAL_FAILURE({
+    FAIL() << "Expected fatal failure.";
+  }, "Expected fatal failure.");
+}
+
+// Tests that EXPECT_FATAL_FAILURE() fails when there is no fatal
+// failure.
+TEST(ExpectFatalFailureTest, FailsWhenThereIsNoFatalFailure) {
+  printf("(expecting a failure)\n");
+  EXPECT_FATAL_FAILURE({
+  }, "");
+}
+
+// A helper for generating a fatal failure.
+void FatalFailure() {
+  FAIL() << "Expected fatal failure.";
+}
+
+// Tests that EXPECT_FATAL_FAILURE() fails when there are two
+// fatal failures.
+TEST(ExpectFatalFailureTest, FailsWhenThereAreTwoFatalFailures) {
+  printf("(expecting a failure)\n");
+  EXPECT_FATAL_FAILURE({
+    FatalFailure();
+    FatalFailure();
+  }, "");
+}
+
+// Tests that EXPECT_FATAL_FAILURE() fails when there is one non-fatal
+// failure.
+TEST(ExpectFatalFailureTest, FailsWhenThereIsOneNonfatalFailure) {
+  printf("(expecting a failure)\n");
+  EXPECT_FATAL_FAILURE({
+    ADD_FAILURE() << "Expected non-fatal failure.";
+  }, "");
+}
+
+// Tests that EXPECT_FATAL_FAILURE() fails when the statement being
+// tested returns.
+TEST(ExpectFatalFailureTest, FailsWhenStatementReturns) {
+  printf("(expecting a failure)\n");
+  EXPECT_FATAL_FAILURE({
+    return;
+  }, "");
+}
+
+#if GTEST_HAS_EXCEPTIONS
+
+// Tests that EXPECT_FATAL_FAILURE() fails when the statement being
+// tested throws.
+TEST(ExpectFatalFailureTest, FailsWhenStatementThrows) {
+  printf("(expecting a failure)\n");
+  try {
+    EXPECT_FATAL_FAILURE({
+      throw 0;
+    }, "");
+  } catch(int) {  // NOLINT
+  }
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// This #ifdef block tests the output of value-parameterized tests.
+
+#if GTEST_HAS_PARAM_TEST
+
+std::string ParamNameFunc(const testing::TestParamInfo<std::string>& info) {
+  return info.param;
+}
+
+class ParamTest : public testing::TestWithParam<std::string> {
+};
+
+TEST_P(ParamTest, Success) {
+  EXPECT_EQ("a", GetParam());
+}
+
+TEST_P(ParamTest, Failure) {
+  EXPECT_EQ("b", GetParam()) << "Expected failure";
+}
+
+INSTANTIATE_TEST_CASE_P(PrintingStrings,
+                        ParamTest,
+                        testing::Values(std::string("a")),
+                        ParamNameFunc);
+
+#endif  // GTEST_HAS_PARAM_TEST
+
+// This #ifdef block tests the output of typed tests.
+#if GTEST_HAS_TYPED_TEST
+
+template <typename T>
+class TypedTest : public testing::Test {
+};
+
+TYPED_TEST_CASE(TypedTest, testing::Types<int>);
+
+TYPED_TEST(TypedTest, Success) {
+  EXPECT_EQ(0, TypeParam());
+}
+
+TYPED_TEST(TypedTest, Failure) {
+  EXPECT_EQ(1, TypeParam()) << "Expected failure";
+}
+
+#endif  // GTEST_HAS_TYPED_TEST
+
+// This #ifdef block tests the output of type-parameterized tests.
+#if GTEST_HAS_TYPED_TEST_P
+
+template <typename T>
+class TypedTestP : public testing::Test {
+};
+
+TYPED_TEST_CASE_P(TypedTestP);
+
+TYPED_TEST_P(TypedTestP, Success) {
+  EXPECT_EQ(0U, TypeParam());
+}
+
+TYPED_TEST_P(TypedTestP, Failure) {
+  EXPECT_EQ(1U, TypeParam()) << "Expected failure";
+}
+
+REGISTER_TYPED_TEST_CASE_P(TypedTestP, Success, Failure);
+
+typedef testing::Types<unsigned char, unsigned int> UnsignedTypes;
+INSTANTIATE_TYPED_TEST_CASE_P(Unsigned, TypedTestP, UnsignedTypes);
+
+#endif  // GTEST_HAS_TYPED_TEST_P
+
+#if GTEST_HAS_DEATH_TEST
+
+// We rely on the golden file to verify that tests whose test case
+// name ends with DeathTest are run first.
+
+TEST(ADeathTest, ShouldRunFirst) {
+}
+
+# if GTEST_HAS_TYPED_TEST
+
+// We rely on the golden file to verify that typed tests whose test
+// case name ends with DeathTest are run first.
+
+template <typename T>
+class ATypedDeathTest : public testing::Test {
+};
+
+typedef testing::Types<int, double> NumericTypes;
+TYPED_TEST_CASE(ATypedDeathTest, NumericTypes);
+
+TYPED_TEST(ATypedDeathTest, ShouldRunFirst) {
+}
+
+# endif  // GTEST_HAS_TYPED_TEST
+
+# if GTEST_HAS_TYPED_TEST_P
+
+
+// We rely on the golden file to verify that type-parameterized tests
+// whose test case name ends with DeathTest are run first.
+
+template <typename T>
+class ATypeParamDeathTest : public testing::Test {
+};
+
+TYPED_TEST_CASE_P(ATypeParamDeathTest);
+
+TYPED_TEST_P(ATypeParamDeathTest, ShouldRunFirst) {
+}
+
+REGISTER_TYPED_TEST_CASE_P(ATypeParamDeathTest, ShouldRunFirst);
+
+INSTANTIATE_TYPED_TEST_CASE_P(My, ATypeParamDeathTest, NumericTypes);
+
+# endif  // GTEST_HAS_TYPED_TEST_P
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+// Tests various failure conditions of
+// EXPECT_{,NON}FATAL_FAILURE{,_ON_ALL_THREADS}.
+class ExpectFailureTest : public testing::Test {
+ public:  // Must be public and not protected due to a bug in g++ 3.4.2.
+  enum FailureMode {
+    FATAL_FAILURE,
+    NONFATAL_FAILURE
+  };
+  static void AddFailure(FailureMode failure) {
+    if (failure == FATAL_FAILURE) {
+      FAIL() << "Expected fatal failure.";
+    } else {
+      ADD_FAILURE() << "Expected non-fatal failure.";
+    }
+  }
+};
+
+TEST_F(ExpectFailureTest, ExpectFatalFailure) {
+  // Expected fatal failure, but succeeds.
+  printf("(expecting 1 failure)\n");
+  EXPECT_FATAL_FAILURE(SUCCEED(), "Expected fatal failure.");
+  // Expected fatal failure, but got a non-fatal failure.
+  printf("(expecting 1 failure)\n");
+  EXPECT_FATAL_FAILURE(AddFailure(NONFATAL_FAILURE), "Expected non-fatal "
+                       "failure.");
+  // Wrong message.
+  printf("(expecting 1 failure)\n");
+  EXPECT_FATAL_FAILURE(AddFailure(FATAL_FAILURE), "Some other fatal failure "
+                       "expected.");
+}
+
+TEST_F(ExpectFailureTest, ExpectNonFatalFailure) {
+  // Expected non-fatal failure, but succeeds.
+  printf("(expecting 1 failure)\n");
+  EXPECT_NONFATAL_FAILURE(SUCCEED(), "Expected non-fatal failure.");
+  // Expected non-fatal failure, but got a fatal failure.
+  printf("(expecting 1 failure)\n");
+  EXPECT_NONFATAL_FAILURE(AddFailure(FATAL_FAILURE), "Expected fatal failure.");
+  // Wrong message.
+  printf("(expecting 1 failure)\n");
+  EXPECT_NONFATAL_FAILURE(AddFailure(NONFATAL_FAILURE), "Some other non-fatal "
+                          "failure.");
+}
+
+#if GTEST_IS_THREADSAFE
+
+class ExpectFailureWithThreadsTest : public ExpectFailureTest {
+ protected:
+  static void AddFailureInOtherThread(FailureMode failure) {
+    ThreadWithParam<FailureMode> thread(&AddFailure, failure, NULL);
+    thread.Join();
+  }
+};
+
+TEST_F(ExpectFailureWithThreadsTest, ExpectFatalFailure) {
+  // We only intercept the current thread.
+  printf("(expecting 2 failures)\n");
+  EXPECT_FATAL_FAILURE(AddFailureInOtherThread(FATAL_FAILURE),
+                       "Expected fatal failure.");
+}
+
+TEST_F(ExpectFailureWithThreadsTest, ExpectNonFatalFailure) {
+  // We only intercept the current thread.
+  printf("(expecting 2 failures)\n");
+  EXPECT_NONFATAL_FAILURE(AddFailureInOtherThread(NONFATAL_FAILURE),
+                          "Expected non-fatal failure.");
+}
+
+typedef ExpectFailureWithThreadsTest ScopedFakeTestPartResultReporterTest;
+
+// Tests that the ScopedFakeTestPartResultReporter only catches failures from
+// the current thread if it is instantiated with INTERCEPT_ONLY_CURRENT_THREAD.
+TEST_F(ScopedFakeTestPartResultReporterTest, InterceptOnlyCurrentThread) {
+  printf("(expecting 2 failures)\n");
+  TestPartResultArray results;
+  {
+    ScopedFakeTestPartResultReporter reporter(
+        ScopedFakeTestPartResultReporter::INTERCEPT_ONLY_CURRENT_THREAD,
+        &results);
+    AddFailureInOtherThread(FATAL_FAILURE);
+    AddFailureInOtherThread(NONFATAL_FAILURE);
+  }
+  // The two failures should not have been intercepted.
+  EXPECT_EQ(0, results.size()) << "This shouldn't fail.";
+}
+
+#endif  // GTEST_IS_THREADSAFE
+
+TEST_F(ExpectFailureTest, ExpectFatalFailureOnAllThreads) {
+  // Expected fatal failure, but succeeds.
+  printf("(expecting 1 failure)\n");
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS(SUCCEED(), "Expected fatal failure.");
+  // Expected fatal failure, but got a non-fatal failure.
+  printf("(expecting 1 failure)\n");
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS(AddFailure(NONFATAL_FAILURE),
+                                      "Expected non-fatal failure.");
+  // Wrong message.
+  printf("(expecting 1 failure)\n");
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS(AddFailure(FATAL_FAILURE),
+                                      "Some other fatal failure expected.");
+}
+
+TEST_F(ExpectFailureTest, ExpectNonFatalFailureOnAllThreads) {
+  // Expected non-fatal failure, but succeeds.
+  printf("(expecting 1 failure)\n");
+  EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(SUCCEED(), "Expected non-fatal "
+                                         "failure.");
+  // Expected non-fatal failure, but got a fatal failure.
+  printf("(expecting 1 failure)\n");
+  EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(AddFailure(FATAL_FAILURE),
+                                         "Expected fatal failure.");
+  // Wrong message.
+  printf("(expecting 1 failure)\n");
+  EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(AddFailure(NONFATAL_FAILURE),
+                                         "Some other non-fatal failure.");
+}
+
+
+// Two test environments for testing testing::AddGlobalTestEnvironment().
+
+class FooEnvironment : public testing::Environment {
+ public:
+  virtual void SetUp() {
+    printf("%s", "FooEnvironment::SetUp() called.\n");
+  }
+
+  virtual void TearDown() {
+    printf("%s", "FooEnvironment::TearDown() called.\n");
+    FAIL() << "Expected fatal failure.";
+  }
+};
+
+class BarEnvironment : public testing::Environment {
+ public:
+  virtual void SetUp() {
+    printf("%s", "BarEnvironment::SetUp() called.\n");
+  }
+
+  virtual void TearDown() {
+    printf("%s", "BarEnvironment::TearDown() called.\n");
+    ADD_FAILURE() << "Expected non-fatal failure.";
+  }
+};
+
+// The main function.
+//
+// The idea is to use Google Test to run all the tests we have defined (some
+// of them are intended to fail), and then compare the test results
+// with the "golden" file.
+int main(int argc, char **argv) {
+  testing::GTEST_FLAG(print_time) = false;
+
+  // We just run the tests, knowing some of them are intended to fail.
+  // We will use a separate Python script to compare the output of
+  // this program with the golden file.
+
+  // It's hard to test InitGoogleTest() directly, as it has many
+  // global side effects.  The following line serves as a sanity test
+  // for it.
+  testing::InitGoogleTest(&argc, argv);
+  bool internal_skip_environment_and_ad_hoc_tests =
+      std::count(argv, argv + argc,
+                 std::string("internal_skip_environment_and_ad_hoc_tests")) > 0;
+
+#if GTEST_HAS_DEATH_TEST
+  if (testing::internal::GTEST_FLAG(internal_run_death_test) != "") {
+    // Skip the usual output capturing if we're running as the child
+    // process of an threadsafe-style death test.
+# if GTEST_OS_WINDOWS
+    posix::FReopen("nul:", "w", stdout);
+# else
+    posix::FReopen("/dev/null", "w", stdout);
+# endif  // GTEST_OS_WINDOWS
+    return RUN_ALL_TESTS();
+  }
+#endif  // GTEST_HAS_DEATH_TEST
+
+  if (internal_skip_environment_and_ad_hoc_tests)
+    return RUN_ALL_TESTS();
+
+  // Registers two global test environments.
+  // The golden file verifies that they are set up in the order they
+  // are registered, and torn down in the reverse order.
+  testing::AddGlobalTestEnvironment(new FooEnvironment);
+  testing::AddGlobalTestEnvironment(new BarEnvironment);
+
+  return RunAllTests();
+}
diff --git a/third_party/googletest/googletest/test/gtest_output_test_golden_lin.txt b/third_party/googletest/googletest/test/gtest_output_test_golden_lin.txt
new file mode 100644
index 0000000..7fff853
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_output_test_golden_lin.txt
@@ -0,0 +1,743 @@
+The non-test part of the code is expected to have 2 failures.
+
+gtest_output_test_.cc:#: Failure
+Value of: false
+  Actual: false
+Expected: true
+gtest_output_test_.cc:#: Failure
+Value of: 3
+Expected: 2
+[==========] Running 66 tests from 29 test cases.
+[----------] Global test environment set-up.
+FooEnvironment::SetUp() called.
+BarEnvironment::SetUp() called.
+[----------] 1 test from ADeathTest
+[ RUN      ] ADeathTest.ShouldRunFirst
+[       OK ] ADeathTest.ShouldRunFirst
+[----------] 1 test from ATypedDeathTest/0, where TypeParam = int
+[ RUN      ] ATypedDeathTest/0.ShouldRunFirst
+[       OK ] ATypedDeathTest/0.ShouldRunFirst
+[----------] 1 test from ATypedDeathTest/1, where TypeParam = double
+[ RUN      ] ATypedDeathTest/1.ShouldRunFirst
+[       OK ] ATypedDeathTest/1.ShouldRunFirst
+[----------] 1 test from My/ATypeParamDeathTest/0, where TypeParam = int
+[ RUN      ] My/ATypeParamDeathTest/0.ShouldRunFirst
+[       OK ] My/ATypeParamDeathTest/0.ShouldRunFirst
+[----------] 1 test from My/ATypeParamDeathTest/1, where TypeParam = double
+[ RUN      ] My/ATypeParamDeathTest/1.ShouldRunFirst
+[       OK ] My/ATypeParamDeathTest/1.ShouldRunFirst
+[----------] 2 tests from PassingTest
+[ RUN      ] PassingTest.PassingTest1
+[       OK ] PassingTest.PassingTest1
+[ RUN      ] PassingTest.PassingTest2
+[       OK ] PassingTest.PassingTest2
+[----------] 2 tests from NonfatalFailureTest
+[ RUN      ] NonfatalFailureTest.EscapesStringOperands
+gtest_output_test_.cc:#: Failure
+Value of: actual
+  Actual: "actual \"string\""
+Expected: kGoldenString
+Which is: "\"Line"
+gtest_output_test_.cc:#: Failure
+Value of: actual
+  Actual: "actual \"string\""
+Expected: golden
+Which is: "\"Line"
+[  FAILED  ] NonfatalFailureTest.EscapesStringOperands
+[ RUN      ] NonfatalFailureTest.DiffForLongStrings
+gtest_output_test_.cc:#: Failure
+Value of: "Line 2"
+Expected: golden_str
+Which is: "\"Line\0 1\"\nLine 2"
+With diff:
+@@ -1,2 @@
+-\"Line\0 1\"
+ Line 2
+
+[  FAILED  ] NonfatalFailureTest.DiffForLongStrings
+[----------] 3 tests from FatalFailureTest
+[ RUN      ] FatalFailureTest.FatalFailureInSubroutine
+(expecting a failure that x should be 1)
+gtest_output_test_.cc:#: Failure
+Value of: x
+  Actual: 2
+Expected: 1
+[  FAILED  ] FatalFailureTest.FatalFailureInSubroutine
+[ RUN      ] FatalFailureTest.FatalFailureInNestedSubroutine
+(expecting a failure that x should be 1)
+gtest_output_test_.cc:#: Failure
+Value of: x
+  Actual: 2
+Expected: 1
+[  FAILED  ] FatalFailureTest.FatalFailureInNestedSubroutine
+[ RUN      ] FatalFailureTest.NonfatalFailureInSubroutine
+(expecting a failure on false)
+gtest_output_test_.cc:#: Failure
+Value of: false
+  Actual: false
+Expected: true
+[  FAILED  ] FatalFailureTest.NonfatalFailureInSubroutine
+[----------] 1 test from LoggingTest
+[ RUN      ] LoggingTest.InterleavingLoggingAndAssertions
+(expecting 2 failures on (3) >= (a[i]))
+i == 0
+i == 1
+gtest_output_test_.cc:#: Failure
+Expected: (3) >= (a[i]), actual: 3 vs 9
+i == 2
+i == 3
+gtest_output_test_.cc:#: Failure
+Expected: (3) >= (a[i]), actual: 3 vs 6
+[  FAILED  ] LoggingTest.InterleavingLoggingAndAssertions
+[----------] 6 tests from SCOPED_TRACETest
+[ RUN      ] SCOPED_TRACETest.ObeysScopes
+(expected to fail)
+gtest_output_test_.cc:#: Failure
+Failed
+This failure is expected, and shouldn't have a trace.
+gtest_output_test_.cc:#: Failure
+Failed
+This failure is expected, and should have a trace.
+Google Test trace:
+gtest_output_test_.cc:#: Expected trace
+gtest_output_test_.cc:#: Failure
+Failed
+This failure is expected, and shouldn't have a trace.
+[  FAILED  ] SCOPED_TRACETest.ObeysScopes
+[ RUN      ] SCOPED_TRACETest.WorksInLoop
+(expected to fail)
+gtest_output_test_.cc:#: Failure
+Value of: n
+  Actual: 1
+Expected: 2
+Google Test trace:
+gtest_output_test_.cc:#: i = 1
+gtest_output_test_.cc:#: Failure
+Value of: n
+  Actual: 2
+Expected: 1
+Google Test trace:
+gtest_output_test_.cc:#: i = 2
+[  FAILED  ] SCOPED_TRACETest.WorksInLoop
+[ RUN      ] SCOPED_TRACETest.WorksInSubroutine
+(expected to fail)
+gtest_output_test_.cc:#: Failure
+Value of: n
+  Actual: 1
+Expected: 2
+Google Test trace:
+gtest_output_test_.cc:#: n = 1
+gtest_output_test_.cc:#: Failure
+Value of: n
+  Actual: 2
+Expected: 1
+Google Test trace:
+gtest_output_test_.cc:#: n = 2
+[  FAILED  ] SCOPED_TRACETest.WorksInSubroutine
+[ RUN      ] SCOPED_TRACETest.CanBeNested
+(expected to fail)
+gtest_output_test_.cc:#: Failure
+Value of: n
+  Actual: 2
+Expected: 1
+Google Test trace:
+gtest_output_test_.cc:#: n = 2
+gtest_output_test_.cc:#: 
+[  FAILED  ] SCOPED_TRACETest.CanBeNested
+[ RUN      ] SCOPED_TRACETest.CanBeRepeated
+(expected to fail)
+gtest_output_test_.cc:#: Failure
+Failed
+This failure is expected, and should contain trace point A.
+Google Test trace:
+gtest_output_test_.cc:#: A
+gtest_output_test_.cc:#: Failure
+Failed
+This failure is expected, and should contain trace point A and B.
+Google Test trace:
+gtest_output_test_.cc:#: B
+gtest_output_test_.cc:#: A
+gtest_output_test_.cc:#: Failure
+Failed
+This failure is expected, and should contain trace point A, B, and C.
+Google Test trace:
+gtest_output_test_.cc:#: C
+gtest_output_test_.cc:#: B
+gtest_output_test_.cc:#: A
+gtest_output_test_.cc:#: Failure
+Failed
+This failure is expected, and should contain trace point A, B, and D.
+Google Test trace:
+gtest_output_test_.cc:#: D
+gtest_output_test_.cc:#: B
+gtest_output_test_.cc:#: A
+[  FAILED  ] SCOPED_TRACETest.CanBeRepeated
+[ RUN      ] SCOPED_TRACETest.WorksConcurrently
+(expecting 6 failures)
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #1 (in thread B, only trace B alive).
+Google Test trace:
+gtest_output_test_.cc:#: Trace B
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #2 (in thread A, trace A & B both alive).
+Google Test trace:
+gtest_output_test_.cc:#: Trace A
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #3 (in thread B, trace A & B both alive).
+Google Test trace:
+gtest_output_test_.cc:#: Trace B
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #4 (in thread B, only trace A alive).
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #5 (in thread A, only trace A alive).
+Google Test trace:
+gtest_output_test_.cc:#: Trace A
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #6 (in thread A, no trace alive).
+[  FAILED  ] SCOPED_TRACETest.WorksConcurrently
+[----------] 1 test from NonFatalFailureInFixtureConstructorTest
+[ RUN      ] NonFatalFailureInFixtureConstructorTest.FailureInConstructor
+(expecting 5 failures)
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #1, in the test fixture c'tor.
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #2, in SetUp().
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #3, in the test body.
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #4, in TearDown.
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #5, in the test fixture d'tor.
+[  FAILED  ] NonFatalFailureInFixtureConstructorTest.FailureInConstructor
+[----------] 1 test from FatalFailureInFixtureConstructorTest
+[ RUN      ] FatalFailureInFixtureConstructorTest.FailureInConstructor
+(expecting 2 failures)
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #1, in the test fixture c'tor.
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #2, in the test fixture d'tor.
+[  FAILED  ] FatalFailureInFixtureConstructorTest.FailureInConstructor
+[----------] 1 test from NonFatalFailureInSetUpTest
+[ RUN      ] NonFatalFailureInSetUpTest.FailureInSetUp
+(expecting 4 failures)
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #1, in SetUp().
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #2, in the test function.
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #3, in TearDown().
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #4, in the test fixture d'tor.
+[  FAILED  ] NonFatalFailureInSetUpTest.FailureInSetUp
+[----------] 1 test from FatalFailureInSetUpTest
+[ RUN      ] FatalFailureInSetUpTest.FailureInSetUp
+(expecting 3 failures)
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #1, in SetUp().
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #2, in TearDown().
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #3, in the test fixture d'tor.
+[  FAILED  ] FatalFailureInSetUpTest.FailureInSetUp
+[----------] 1 test from AddFailureAtTest
+[ RUN      ] AddFailureAtTest.MessageContainsSpecifiedFileAndLineNumber
+foo.cc:42: Failure
+Failed
+Expected failure in foo.cc
+[  FAILED  ] AddFailureAtTest.MessageContainsSpecifiedFileAndLineNumber
+[----------] 4 tests from MixedUpTestCaseTest
+[ RUN      ] MixedUpTestCaseTest.FirstTestFromNamespaceFoo
+[       OK ] MixedUpTestCaseTest.FirstTestFromNamespaceFoo
+[ RUN      ] MixedUpTestCaseTest.SecondTestFromNamespaceFoo
+[       OK ] MixedUpTestCaseTest.SecondTestFromNamespaceFoo
+[ RUN      ] MixedUpTestCaseTest.ThisShouldFail
+gtest.cc:#: Failure
+Failed
+All tests in the same test case must use the same test fixture
+class.  However, in test case MixedUpTestCaseTest,
+you defined test FirstTestFromNamespaceFoo and test ThisShouldFail
+using two different test fixture classes.  This can happen if
+the two classes are from different namespaces or translation
+units and have the same name.  You should probably rename one
+of the classes to put the tests into different test cases.
+[  FAILED  ] MixedUpTestCaseTest.ThisShouldFail
+[ RUN      ] MixedUpTestCaseTest.ThisShouldFailToo
+gtest.cc:#: Failure
+Failed
+All tests in the same test case must use the same test fixture
+class.  However, in test case MixedUpTestCaseTest,
+you defined test FirstTestFromNamespaceFoo and test ThisShouldFailToo
+using two different test fixture classes.  This can happen if
+the two classes are from different namespaces or translation
+units and have the same name.  You should probably rename one
+of the classes to put the tests into different test cases.
+[  FAILED  ] MixedUpTestCaseTest.ThisShouldFailToo
+[----------] 2 tests from MixedUpTestCaseWithSameTestNameTest
+[ RUN      ] MixedUpTestCaseWithSameTestNameTest.TheSecondTestWithThisNameShouldFail
+[       OK ] MixedUpTestCaseWithSameTestNameTest.TheSecondTestWithThisNameShouldFail
+[ RUN      ] MixedUpTestCaseWithSameTestNameTest.TheSecondTestWithThisNameShouldFail
+gtest.cc:#: Failure
+Failed
+All tests in the same test case must use the same test fixture
+class.  However, in test case MixedUpTestCaseWithSameTestNameTest,
+you defined test TheSecondTestWithThisNameShouldFail and test TheSecondTestWithThisNameShouldFail
+using two different test fixture classes.  This can happen if
+the two classes are from different namespaces or translation
+units and have the same name.  You should probably rename one
+of the classes to put the tests into different test cases.
+[  FAILED  ] MixedUpTestCaseWithSameTestNameTest.TheSecondTestWithThisNameShouldFail
+[----------] 2 tests from TEST_F_before_TEST_in_same_test_case
+[ RUN      ] TEST_F_before_TEST_in_same_test_case.DefinedUsingTEST_F
+[       OK ] TEST_F_before_TEST_in_same_test_case.DefinedUsingTEST_F
+[ RUN      ] TEST_F_before_TEST_in_same_test_case.DefinedUsingTESTAndShouldFail
+gtest.cc:#: Failure
+Failed
+All tests in the same test case must use the same test fixture
+class, so mixing TEST_F and TEST in the same test case is
+illegal.  In test case TEST_F_before_TEST_in_same_test_case,
+test DefinedUsingTEST_F is defined using TEST_F but
+test DefinedUsingTESTAndShouldFail is defined using TEST.  You probably
+want to change the TEST to TEST_F or move it to another test
+case.
+[  FAILED  ] TEST_F_before_TEST_in_same_test_case.DefinedUsingTESTAndShouldFail
+[----------] 2 tests from TEST_before_TEST_F_in_same_test_case
+[ RUN      ] TEST_before_TEST_F_in_same_test_case.DefinedUsingTEST
+[       OK ] TEST_before_TEST_F_in_same_test_case.DefinedUsingTEST
+[ RUN      ] TEST_before_TEST_F_in_same_test_case.DefinedUsingTEST_FAndShouldFail
+gtest.cc:#: Failure
+Failed
+All tests in the same test case must use the same test fixture
+class, so mixing TEST_F and TEST in the same test case is
+illegal.  In test case TEST_before_TEST_F_in_same_test_case,
+test DefinedUsingTEST_FAndShouldFail is defined using TEST_F but
+test DefinedUsingTEST is defined using TEST.  You probably
+want to change the TEST to TEST_F or move it to another test
+case.
+[  FAILED  ] TEST_before_TEST_F_in_same_test_case.DefinedUsingTEST_FAndShouldFail
+[----------] 8 tests from ExpectNonfatalFailureTest
+[ RUN      ] ExpectNonfatalFailureTest.CanReferenceGlobalVariables
+[       OK ] ExpectNonfatalFailureTest.CanReferenceGlobalVariables
+[ RUN      ] ExpectNonfatalFailureTest.CanReferenceLocalVariables
+[       OK ] ExpectNonfatalFailureTest.CanReferenceLocalVariables
+[ RUN      ] ExpectNonfatalFailureTest.SucceedsWhenThereIsOneNonfatalFailure
+[       OK ] ExpectNonfatalFailureTest.SucceedsWhenThereIsOneNonfatalFailure
+[ RUN      ] ExpectNonfatalFailureTest.FailsWhenThereIsNoNonfatalFailure
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual: 0 failures
+[  FAILED  ] ExpectNonfatalFailureTest.FailsWhenThereIsNoNonfatalFailure
+[ RUN      ] ExpectNonfatalFailureTest.FailsWhenThereAreTwoNonfatalFailures
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual: 2 failures
+gtest_output_test_.cc:#: Non-fatal failure:
+Failed
+Expected non-fatal failure 1.
+
+gtest_output_test_.cc:#: Non-fatal failure:
+Failed
+Expected non-fatal failure 2.
+
+[  FAILED  ] ExpectNonfatalFailureTest.FailsWhenThereAreTwoNonfatalFailures
+[ RUN      ] ExpectNonfatalFailureTest.FailsWhenThereIsOneFatalFailure
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual:
+gtest_output_test_.cc:#: Fatal failure:
+Failed
+Expected fatal failure.
+
+[  FAILED  ] ExpectNonfatalFailureTest.FailsWhenThereIsOneFatalFailure
+[ RUN      ] ExpectNonfatalFailureTest.FailsWhenStatementReturns
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual: 0 failures
+[  FAILED  ] ExpectNonfatalFailureTest.FailsWhenStatementReturns
+[ RUN      ] ExpectNonfatalFailureTest.FailsWhenStatementThrows
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual: 0 failures
+[  FAILED  ] ExpectNonfatalFailureTest.FailsWhenStatementThrows
+[----------] 8 tests from ExpectFatalFailureTest
+[ RUN      ] ExpectFatalFailureTest.CanReferenceGlobalVariables
+[       OK ] ExpectFatalFailureTest.CanReferenceGlobalVariables
+[ RUN      ] ExpectFatalFailureTest.CanReferenceLocalStaticVariables
+[       OK ] ExpectFatalFailureTest.CanReferenceLocalStaticVariables
+[ RUN      ] ExpectFatalFailureTest.SucceedsWhenThereIsOneFatalFailure
+[       OK ] ExpectFatalFailureTest.SucceedsWhenThereIsOneFatalFailure
+[ RUN      ] ExpectFatalFailureTest.FailsWhenThereIsNoFatalFailure
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual: 0 failures
+[  FAILED  ] ExpectFatalFailureTest.FailsWhenThereIsNoFatalFailure
+[ RUN      ] ExpectFatalFailureTest.FailsWhenThereAreTwoFatalFailures
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual: 2 failures
+gtest_output_test_.cc:#: Fatal failure:
+Failed
+Expected fatal failure.
+
+gtest_output_test_.cc:#: Fatal failure:
+Failed
+Expected fatal failure.
+
+[  FAILED  ] ExpectFatalFailureTest.FailsWhenThereAreTwoFatalFailures
+[ RUN      ] ExpectFatalFailureTest.FailsWhenThereIsOneNonfatalFailure
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual:
+gtest_output_test_.cc:#: Non-fatal failure:
+Failed
+Expected non-fatal failure.
+
+[  FAILED  ] ExpectFatalFailureTest.FailsWhenThereIsOneNonfatalFailure
+[ RUN      ] ExpectFatalFailureTest.FailsWhenStatementReturns
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual: 0 failures
+[  FAILED  ] ExpectFatalFailureTest.FailsWhenStatementReturns
+[ RUN      ] ExpectFatalFailureTest.FailsWhenStatementThrows
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual: 0 failures
+[  FAILED  ] ExpectFatalFailureTest.FailsWhenStatementThrows
+[----------] 2 tests from TypedTest/0, where TypeParam = int
+[ RUN      ] TypedTest/0.Success
+[       OK ] TypedTest/0.Success
+[ RUN      ] TypedTest/0.Failure
+gtest_output_test_.cc:#: Failure
+Value of: TypeParam()
+  Actual: 0
+Expected: 1
+Expected failure
+[  FAILED  ] TypedTest/0.Failure, where TypeParam = int
+[----------] 2 tests from Unsigned/TypedTestP/0, where TypeParam = unsigned char
+[ RUN      ] Unsigned/TypedTestP/0.Success
+[       OK ] Unsigned/TypedTestP/0.Success
+[ RUN      ] Unsigned/TypedTestP/0.Failure
+gtest_output_test_.cc:#: Failure
+Value of: TypeParam()
+  Actual: '\0'
+Expected: 1U
+Which is: 1
+Expected failure
+[  FAILED  ] Unsigned/TypedTestP/0.Failure, where TypeParam = unsigned char
+[----------] 2 tests from Unsigned/TypedTestP/1, where TypeParam = unsigned int
+[ RUN      ] Unsigned/TypedTestP/1.Success
+[       OK ] Unsigned/TypedTestP/1.Success
+[ RUN      ] Unsigned/TypedTestP/1.Failure
+gtest_output_test_.cc:#: Failure
+Value of: TypeParam()
+  Actual: 0
+Expected: 1U
+Which is: 1
+Expected failure
+[  FAILED  ] Unsigned/TypedTestP/1.Failure, where TypeParam = unsigned int
+[----------] 4 tests from ExpectFailureTest
+[ RUN      ] ExpectFailureTest.ExpectFatalFailure
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual:
+gtest_output_test_.cc:#: Success:
+Succeeded
+
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual:
+gtest_output_test_.cc:#: Non-fatal failure:
+Failed
+Expected non-fatal failure.
+
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure containing "Some other fatal failure expected."
+  Actual:
+gtest_output_test_.cc:#: Fatal failure:
+Failed
+Expected fatal failure.
+
+[  FAILED  ] ExpectFailureTest.ExpectFatalFailure
+[ RUN      ] ExpectFailureTest.ExpectNonFatalFailure
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual:
+gtest_output_test_.cc:#: Success:
+Succeeded
+
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual:
+gtest_output_test_.cc:#: Fatal failure:
+Failed
+Expected fatal failure.
+
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure containing "Some other non-fatal failure."
+  Actual:
+gtest_output_test_.cc:#: Non-fatal failure:
+Failed
+Expected non-fatal failure.
+
+[  FAILED  ] ExpectFailureTest.ExpectNonFatalFailure
+[ RUN      ] ExpectFailureTest.ExpectFatalFailureOnAllThreads
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual:
+gtest_output_test_.cc:#: Success:
+Succeeded
+
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual:
+gtest_output_test_.cc:#: Non-fatal failure:
+Failed
+Expected non-fatal failure.
+
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure containing "Some other fatal failure expected."
+  Actual:
+gtest_output_test_.cc:#: Fatal failure:
+Failed
+Expected fatal failure.
+
+[  FAILED  ] ExpectFailureTest.ExpectFatalFailureOnAllThreads
+[ RUN      ] ExpectFailureTest.ExpectNonFatalFailureOnAllThreads
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual:
+gtest_output_test_.cc:#: Success:
+Succeeded
+
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual:
+gtest_output_test_.cc:#: Fatal failure:
+Failed
+Expected fatal failure.
+
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure containing "Some other non-fatal failure."
+  Actual:
+gtest_output_test_.cc:#: Non-fatal failure:
+Failed
+Expected non-fatal failure.
+
+[  FAILED  ] ExpectFailureTest.ExpectNonFatalFailureOnAllThreads
+[----------] 2 tests from ExpectFailureWithThreadsTest
+[ RUN      ] ExpectFailureWithThreadsTest.ExpectFatalFailure
+(expecting 2 failures)
+gtest_output_test_.cc:#: Failure
+Failed
+Expected fatal failure.
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual: 0 failures
+[  FAILED  ] ExpectFailureWithThreadsTest.ExpectFatalFailure
+[ RUN      ] ExpectFailureWithThreadsTest.ExpectNonFatalFailure
+(expecting 2 failures)
+gtest_output_test_.cc:#: Failure
+Failed
+Expected non-fatal failure.
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual: 0 failures
+[  FAILED  ] ExpectFailureWithThreadsTest.ExpectNonFatalFailure
+[----------] 1 test from ScopedFakeTestPartResultReporterTest
+[ RUN      ] ScopedFakeTestPartResultReporterTest.InterceptOnlyCurrentThread
+(expecting 2 failures)
+gtest_output_test_.cc:#: Failure
+Failed
+Expected fatal failure.
+gtest_output_test_.cc:#: Failure
+Failed
+Expected non-fatal failure.
+[  FAILED  ] ScopedFakeTestPartResultReporterTest.InterceptOnlyCurrentThread
+[----------] 1 test from PrintingFailingParams/FailingParamTest
+[ RUN      ] PrintingFailingParams/FailingParamTest.Fails/0
+gtest_output_test_.cc:#: Failure
+Value of: GetParam()
+  Actual: 2
+Expected: 1
+[  FAILED  ] PrintingFailingParams/FailingParamTest.Fails/0, where GetParam() = 2
+[----------] 2 tests from PrintingStrings/ParamTest
+[ RUN      ] PrintingStrings/ParamTest.Success/a
+[       OK ] PrintingStrings/ParamTest.Success/a
+[ RUN      ] PrintingStrings/ParamTest.Failure/a
+gtest_output_test_.cc:#: Failure
+Value of: GetParam()
+  Actual: "a"
+Expected: "b"
+Expected failure
+[  FAILED  ] PrintingStrings/ParamTest.Failure/a, where GetParam() = "a"
+[----------] Global test environment tear-down
+BarEnvironment::TearDown() called.
+gtest_output_test_.cc:#: Failure
+Failed
+Expected non-fatal failure.
+FooEnvironment::TearDown() called.
+gtest_output_test_.cc:#: Failure
+Failed
+Expected fatal failure.
+[==========] 66 tests from 29 test cases ran.
+[  PASSED  ] 22 tests.
+[  FAILED  ] 44 tests, listed below:
+[  FAILED  ] NonfatalFailureTest.EscapesStringOperands
+[  FAILED  ] NonfatalFailureTest.DiffForLongStrings
+[  FAILED  ] FatalFailureTest.FatalFailureInSubroutine
+[  FAILED  ] FatalFailureTest.FatalFailureInNestedSubroutine
+[  FAILED  ] FatalFailureTest.NonfatalFailureInSubroutine
+[  FAILED  ] LoggingTest.InterleavingLoggingAndAssertions
+[  FAILED  ] SCOPED_TRACETest.ObeysScopes
+[  FAILED  ] SCOPED_TRACETest.WorksInLoop
+[  FAILED  ] SCOPED_TRACETest.WorksInSubroutine
+[  FAILED  ] SCOPED_TRACETest.CanBeNested
+[  FAILED  ] SCOPED_TRACETest.CanBeRepeated
+[  FAILED  ] SCOPED_TRACETest.WorksConcurrently
+[  FAILED  ] NonFatalFailureInFixtureConstructorTest.FailureInConstructor
+[  FAILED  ] FatalFailureInFixtureConstructorTest.FailureInConstructor
+[  FAILED  ] NonFatalFailureInSetUpTest.FailureInSetUp
+[  FAILED  ] FatalFailureInSetUpTest.FailureInSetUp
+[  FAILED  ] AddFailureAtTest.MessageContainsSpecifiedFileAndLineNumber
+[  FAILED  ] MixedUpTestCaseTest.ThisShouldFail
+[  FAILED  ] MixedUpTestCaseTest.ThisShouldFailToo
+[  FAILED  ] MixedUpTestCaseWithSameTestNameTest.TheSecondTestWithThisNameShouldFail
+[  FAILED  ] TEST_F_before_TEST_in_same_test_case.DefinedUsingTESTAndShouldFail
+[  FAILED  ] TEST_before_TEST_F_in_same_test_case.DefinedUsingTEST_FAndShouldFail
+[  FAILED  ] ExpectNonfatalFailureTest.FailsWhenThereIsNoNonfatalFailure
+[  FAILED  ] ExpectNonfatalFailureTest.FailsWhenThereAreTwoNonfatalFailures
+[  FAILED  ] ExpectNonfatalFailureTest.FailsWhenThereIsOneFatalFailure
+[  FAILED  ] ExpectNonfatalFailureTest.FailsWhenStatementReturns
+[  FAILED  ] ExpectNonfatalFailureTest.FailsWhenStatementThrows
+[  FAILED  ] ExpectFatalFailureTest.FailsWhenThereIsNoFatalFailure
+[  FAILED  ] ExpectFatalFailureTest.FailsWhenThereAreTwoFatalFailures
+[  FAILED  ] ExpectFatalFailureTest.FailsWhenThereIsOneNonfatalFailure
+[  FAILED  ] ExpectFatalFailureTest.FailsWhenStatementReturns
+[  FAILED  ] ExpectFatalFailureTest.FailsWhenStatementThrows
+[  FAILED  ] TypedTest/0.Failure, where TypeParam = int
+[  FAILED  ] Unsigned/TypedTestP/0.Failure, where TypeParam = unsigned char
+[  FAILED  ] Unsigned/TypedTestP/1.Failure, where TypeParam = unsigned int
+[  FAILED  ] ExpectFailureTest.ExpectFatalFailure
+[  FAILED  ] ExpectFailureTest.ExpectNonFatalFailure
+[  FAILED  ] ExpectFailureTest.ExpectFatalFailureOnAllThreads
+[  FAILED  ] ExpectFailureTest.ExpectNonFatalFailureOnAllThreads
+[  FAILED  ] ExpectFailureWithThreadsTest.ExpectFatalFailure
+[  FAILED  ] ExpectFailureWithThreadsTest.ExpectNonFatalFailure
+[  FAILED  ] ScopedFakeTestPartResultReporterTest.InterceptOnlyCurrentThread
+[  FAILED  ] PrintingFailingParams/FailingParamTest.Fails/0, where GetParam() = 2
+[  FAILED  ] PrintingStrings/ParamTest.Failure/a, where GetParam() = "a"
+
+44 FAILED TESTS
+  YOU HAVE 1 DISABLED TEST
+
+Note: Google Test filter = FatalFailureTest.*:LoggingTest.*
+[==========] Running 4 tests from 2 test cases.
+[----------] Global test environment set-up.
+[----------] 3 tests from FatalFailureTest
+[ RUN      ] FatalFailureTest.FatalFailureInSubroutine
+(expecting a failure that x should be 1)
+gtest_output_test_.cc:#: Failure
+Value of: x
+  Actual: 2
+Expected: 1
+[  FAILED  ] FatalFailureTest.FatalFailureInSubroutine (? ms)
+[ RUN      ] FatalFailureTest.FatalFailureInNestedSubroutine
+(expecting a failure that x should be 1)
+gtest_output_test_.cc:#: Failure
+Value of: x
+  Actual: 2
+Expected: 1
+[  FAILED  ] FatalFailureTest.FatalFailureInNestedSubroutine (? ms)
+[ RUN      ] FatalFailureTest.NonfatalFailureInSubroutine
+(expecting a failure on false)
+gtest_output_test_.cc:#: Failure
+Value of: false
+  Actual: false
+Expected: true
+[  FAILED  ] FatalFailureTest.NonfatalFailureInSubroutine (? ms)
+[----------] 3 tests from FatalFailureTest (? ms total)
+
+[----------] 1 test from LoggingTest
+[ RUN      ] LoggingTest.InterleavingLoggingAndAssertions
+(expecting 2 failures on (3) >= (a[i]))
+i == 0
+i == 1
+gtest_output_test_.cc:#: Failure
+Expected: (3) >= (a[i]), actual: 3 vs 9
+i == 2
+i == 3
+gtest_output_test_.cc:#: Failure
+Expected: (3) >= (a[i]), actual: 3 vs 6
+[  FAILED  ] LoggingTest.InterleavingLoggingAndAssertions (? ms)
+[----------] 1 test from LoggingTest (? ms total)
+
+[----------] Global test environment tear-down
+[==========] 4 tests from 2 test cases ran. (? ms total)
+[  PASSED  ] 0 tests.
+[  FAILED  ] 4 tests, listed below:
+[  FAILED  ] FatalFailureTest.FatalFailureInSubroutine
+[  FAILED  ] FatalFailureTest.FatalFailureInNestedSubroutine
+[  FAILED  ] FatalFailureTest.NonfatalFailureInSubroutine
+[  FAILED  ] LoggingTest.InterleavingLoggingAndAssertions
+
+ 4 FAILED TESTS
+Note: Google Test filter = *DISABLED_*
+[==========] Running 1 test from 1 test case.
+[----------] Global test environment set-up.
+[----------] 1 test from DisabledTestsWarningTest
+[ RUN      ] DisabledTestsWarningTest.DISABLED_AlsoRunDisabledTestsFlagSuppressesWarning
+[       OK ] DisabledTestsWarningTest.DISABLED_AlsoRunDisabledTestsFlagSuppressesWarning
+[----------] Global test environment tear-down
+[==========] 1 test from 1 test case ran.
+[  PASSED  ] 1 test.
+Note: Google Test filter = PassingTest.*
+Note: This is test shard 2 of 2.
+[==========] Running 1 test from 1 test case.
+[----------] Global test environment set-up.
+[----------] 1 test from PassingTest
+[ RUN      ] PassingTest.PassingTest2
+[       OK ] PassingTest.PassingTest2
+[----------] Global test environment tear-down
+[==========] 1 test from 1 test case ran.
+[  PASSED  ] 1 test.
diff --git a/third_party/googletest/googletest/test/gtest_pred_impl_unittest.cc b/third_party/googletest/googletest/test/gtest_pred_impl_unittest.cc
new file mode 100644
index 0000000..a84eff8
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_pred_impl_unittest.cc
@@ -0,0 +1,2427 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This file is AUTOMATICALLY GENERATED on 10/31/2011 by command
+// 'gen_gtest_pred_impl.py 5'.  DO NOT EDIT BY HAND!
+
+// Regression test for gtest_pred_impl.h
+//
+// This file is generated by a script and quite long.  If you intend to
+// learn how Google Test works by reading its unit tests, read
+// gtest_unittest.cc instead.
+//
+// This is intended as a regression test for the Google Test predicate
+// assertions.  We compile it as part of the gtest_unittest target
+// only to keep the implementation tidy and compact, as it is quite
+// involved to set up the stage for testing Google Test using Google
+// Test itself.
+//
+// Currently, gtest_unittest takes ~11 seconds to run in the testing
+// daemon.  In the future, if it grows too large and needs much more
+// time to finish, we should consider separating this file into a
+// stand-alone regression test.
+
+#include <iostream>
+
+#include "gtest/gtest.h"
+#include "gtest/gtest-spi.h"
+
+// A user-defined data type.
+struct Bool {
+  explicit Bool(int val) : value(val != 0) {}
+
+  bool operator>(int n) const { return value > Bool(n).value; }
+
+  Bool operator+(const Bool& rhs) const { return Bool(value + rhs.value); }
+
+  bool operator==(const Bool& rhs) const { return value == rhs.value; }
+
+  bool value;
+};
+
+// Enables Bool to be used in assertions.
+std::ostream& operator<<(std::ostream& os, const Bool& x) {
+  return os << (x.value ? "true" : "false");
+}
+
+// Sample functions/functors for testing unary predicate assertions.
+
+// A unary predicate function.
+template <typename T1>
+bool PredFunction1(T1 v1) {
+  return v1 > 0;
+}
+
+// The following two functions are needed to circumvent a bug in
+// gcc 2.95.3, which sometimes has problem with the above template
+// function.
+bool PredFunction1Int(int v1) {
+  return v1 > 0;
+}
+bool PredFunction1Bool(Bool v1) {
+  return v1 > 0;
+}
+
+// A unary predicate functor.
+struct PredFunctor1 {
+  template <typename T1>
+  bool operator()(const T1& v1) {
+    return v1 > 0;
+  }
+};
+
+// A unary predicate-formatter function.
+template <typename T1>
+testing::AssertionResult PredFormatFunction1(const char* e1,
+                                             const T1& v1) {
+  if (PredFunction1(v1))
+    return testing::AssertionSuccess();
+
+  return testing::AssertionFailure()
+      << e1
+      << " is expected to be positive, but evaluates to "
+      << v1 << ".";
+}
+
+// A unary predicate-formatter functor.
+struct PredFormatFunctor1 {
+  template <typename T1>
+  testing::AssertionResult operator()(const char* e1,
+                                      const T1& v1) const {
+    return PredFormatFunction1(e1, v1);
+  }
+};
+
+// Tests for {EXPECT|ASSERT}_PRED_FORMAT1.
+
+class Predicate1Test : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    expected_to_finish_ = true;
+    finished_ = false;
+    n1_ = 0;
+  }
+
+  virtual void TearDown() {
+    // Verifies that each of the predicate's arguments was evaluated
+    // exactly once.
+    EXPECT_EQ(1, n1_) <<
+        "The predicate assertion didn't evaluate argument 2 "
+        "exactly once.";
+
+    // Verifies that the control flow in the test function is expected.
+    if (expected_to_finish_ && !finished_) {
+      FAIL() << "The predicate assertion unexpactedly aborted the test.";
+    } else if (!expected_to_finish_ && finished_) {
+      FAIL() << "The failed predicate assertion didn't abort the test "
+                "as expected.";
+    }
+  }
+
+  // true iff the test function is expected to run to finish.
+  static bool expected_to_finish_;
+
+  // true iff the test function did run to finish.
+  static bool finished_;
+
+  static int n1_;
+};
+
+bool Predicate1Test::expected_to_finish_;
+bool Predicate1Test::finished_;
+int Predicate1Test::n1_;
+
+typedef Predicate1Test EXPECT_PRED_FORMAT1Test;
+typedef Predicate1Test ASSERT_PRED_FORMAT1Test;
+typedef Predicate1Test EXPECT_PRED1Test;
+typedef Predicate1Test ASSERT_PRED1Test;
+
+// Tests a successful EXPECT_PRED1 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED1Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED1(PredFunction1Int,
+               ++n1_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED1 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED1Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED1(PredFunction1Bool,
+               Bool(++n1_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED1 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED1Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED1(PredFunctor1(),
+               ++n1_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED1 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED1Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED1(PredFunctor1(),
+               Bool(++n1_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED1 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED1Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED1(PredFunction1Int,
+                 n1_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED1 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED1Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED1(PredFunction1Bool,
+                 Bool(n1_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED1 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED1Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED1(PredFunctor1(),
+                 n1_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED1 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED1Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED1(PredFunctor1(),
+                 Bool(n1_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful ASSERT_PRED1 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED1Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED1(PredFunction1Int,
+               ++n1_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED1 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED1Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED1(PredFunction1Bool,
+               Bool(++n1_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED1 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED1Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED1(PredFunctor1(),
+               ++n1_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED1 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED1Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED1(PredFunctor1(),
+               Bool(++n1_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED1 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED1Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED1(PredFunction1Int,
+                 n1_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED1 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED1Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED1(PredFunction1Bool,
+                 Bool(n1_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED1 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED1Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED1(PredFunctor1(),
+                 n1_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED1 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED1Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED1(PredFunctor1(),
+                 Bool(n1_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful EXPECT_PRED_FORMAT1 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT1Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT1(PredFormatFunction1,
+                      ++n1_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT1 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT1Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT1(PredFormatFunction1,
+                      Bool(++n1_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT1 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT1Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT1(PredFormatFunctor1(),
+                      ++n1_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT1 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT1Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT1(PredFormatFunctor1(),
+                      Bool(++n1_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED_FORMAT1 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT1Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT1(PredFormatFunction1,
+                        n1_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT1 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT1Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT1(PredFormatFunction1,
+                        Bool(n1_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT1 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT1Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT1(PredFormatFunctor1(),
+                        n1_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT1 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT1Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT1(PredFormatFunctor1(),
+                        Bool(n1_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful ASSERT_PRED_FORMAT1 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT1Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT1(PredFormatFunction1,
+                      ++n1_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT1 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT1Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT1(PredFormatFunction1,
+                      Bool(++n1_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT1 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT1Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT1(PredFormatFunctor1(),
+                      ++n1_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT1 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT1Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT1(PredFormatFunctor1(),
+                      Bool(++n1_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED_FORMAT1 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT1Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT1(PredFormatFunction1,
+                        n1_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT1 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT1Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT1(PredFormatFunction1,
+                        Bool(n1_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT1 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT1Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT1(PredFormatFunctor1(),
+                        n1_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT1 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT1Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT1(PredFormatFunctor1(),
+                        Bool(n1_++));
+    finished_ = true;
+  }, "");
+}
+// Sample functions/functors for testing binary predicate assertions.
+
+// A binary predicate function.
+template <typename T1, typename T2>
+bool PredFunction2(T1 v1, T2 v2) {
+  return v1 + v2 > 0;
+}
+
+// The following two functions are needed to circumvent a bug in
+// gcc 2.95.3, which sometimes has problem with the above template
+// function.
+bool PredFunction2Int(int v1, int v2) {
+  return v1 + v2 > 0;
+}
+bool PredFunction2Bool(Bool v1, Bool v2) {
+  return v1 + v2 > 0;
+}
+
+// A binary predicate functor.
+struct PredFunctor2 {
+  template <typename T1, typename T2>
+  bool operator()(const T1& v1,
+                  const T2& v2) {
+    return v1 + v2 > 0;
+  }
+};
+
+// A binary predicate-formatter function.
+template <typename T1, typename T2>
+testing::AssertionResult PredFormatFunction2(const char* e1,
+                                             const char* e2,
+                                             const T1& v1,
+                                             const T2& v2) {
+  if (PredFunction2(v1, v2))
+    return testing::AssertionSuccess();
+
+  return testing::AssertionFailure()
+      << e1 << " + " << e2
+      << " is expected to be positive, but evaluates to "
+      << v1 + v2 << ".";
+}
+
+// A binary predicate-formatter functor.
+struct PredFormatFunctor2 {
+  template <typename T1, typename T2>
+  testing::AssertionResult operator()(const char* e1,
+                                      const char* e2,
+                                      const T1& v1,
+                                      const T2& v2) const {
+    return PredFormatFunction2(e1, e2, v1, v2);
+  }
+};
+
+// Tests for {EXPECT|ASSERT}_PRED_FORMAT2.
+
+class Predicate2Test : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    expected_to_finish_ = true;
+    finished_ = false;
+    n1_ = n2_ = 0;
+  }
+
+  virtual void TearDown() {
+    // Verifies that each of the predicate's arguments was evaluated
+    // exactly once.
+    EXPECT_EQ(1, n1_) <<
+        "The predicate assertion didn't evaluate argument 2 "
+        "exactly once.";
+    EXPECT_EQ(1, n2_) <<
+        "The predicate assertion didn't evaluate argument 3 "
+        "exactly once.";
+
+    // Verifies that the control flow in the test function is expected.
+    if (expected_to_finish_ && !finished_) {
+      FAIL() << "The predicate assertion unexpactedly aborted the test.";
+    } else if (!expected_to_finish_ && finished_) {
+      FAIL() << "The failed predicate assertion didn't abort the test "
+                "as expected.";
+    }
+  }
+
+  // true iff the test function is expected to run to finish.
+  static bool expected_to_finish_;
+
+  // true iff the test function did run to finish.
+  static bool finished_;
+
+  static int n1_;
+  static int n2_;
+};
+
+bool Predicate2Test::expected_to_finish_;
+bool Predicate2Test::finished_;
+int Predicate2Test::n1_;
+int Predicate2Test::n2_;
+
+typedef Predicate2Test EXPECT_PRED_FORMAT2Test;
+typedef Predicate2Test ASSERT_PRED_FORMAT2Test;
+typedef Predicate2Test EXPECT_PRED2Test;
+typedef Predicate2Test ASSERT_PRED2Test;
+
+// Tests a successful EXPECT_PRED2 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED2Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED2(PredFunction2Int,
+               ++n1_,
+               ++n2_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED2 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED2Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED2(PredFunction2Bool,
+               Bool(++n1_),
+               Bool(++n2_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED2 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED2Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED2(PredFunctor2(),
+               ++n1_,
+               ++n2_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED2 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED2Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED2(PredFunctor2(),
+               Bool(++n1_),
+               Bool(++n2_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED2 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED2Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED2(PredFunction2Int,
+                 n1_++,
+                 n2_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED2 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED2Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED2(PredFunction2Bool,
+                 Bool(n1_++),
+                 Bool(n2_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED2 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED2Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED2(PredFunctor2(),
+                 n1_++,
+                 n2_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED2 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED2Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED2(PredFunctor2(),
+                 Bool(n1_++),
+                 Bool(n2_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful ASSERT_PRED2 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED2Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED2(PredFunction2Int,
+               ++n1_,
+               ++n2_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED2 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED2Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED2(PredFunction2Bool,
+               Bool(++n1_),
+               Bool(++n2_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED2 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED2Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED2(PredFunctor2(),
+               ++n1_,
+               ++n2_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED2 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED2Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED2(PredFunctor2(),
+               Bool(++n1_),
+               Bool(++n2_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED2 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED2Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED2(PredFunction2Int,
+                 n1_++,
+                 n2_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED2 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED2Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED2(PredFunction2Bool,
+                 Bool(n1_++),
+                 Bool(n2_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED2 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED2Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED2(PredFunctor2(),
+                 n1_++,
+                 n2_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED2 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED2Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED2(PredFunctor2(),
+                 Bool(n1_++),
+                 Bool(n2_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful EXPECT_PRED_FORMAT2 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT2Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT2(PredFormatFunction2,
+                      ++n1_,
+                      ++n2_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT2 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT2Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT2(PredFormatFunction2,
+                      Bool(++n1_),
+                      Bool(++n2_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT2 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT2Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT2(PredFormatFunctor2(),
+                      ++n1_,
+                      ++n2_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT2 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT2Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT2(PredFormatFunctor2(),
+                      Bool(++n1_),
+                      Bool(++n2_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED_FORMAT2 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT2Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT2(PredFormatFunction2,
+                        n1_++,
+                        n2_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT2 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT2Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT2(PredFormatFunction2,
+                        Bool(n1_++),
+                        Bool(n2_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT2 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT2Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT2(PredFormatFunctor2(),
+                        n1_++,
+                        n2_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT2 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT2Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT2(PredFormatFunctor2(),
+                        Bool(n1_++),
+                        Bool(n2_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful ASSERT_PRED_FORMAT2 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT2Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT2(PredFormatFunction2,
+                      ++n1_,
+                      ++n2_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT2 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT2Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT2(PredFormatFunction2,
+                      Bool(++n1_),
+                      Bool(++n2_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT2 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT2Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT2(PredFormatFunctor2(),
+                      ++n1_,
+                      ++n2_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT2 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT2Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT2(PredFormatFunctor2(),
+                      Bool(++n1_),
+                      Bool(++n2_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED_FORMAT2 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT2Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT2(PredFormatFunction2,
+                        n1_++,
+                        n2_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT2 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT2Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT2(PredFormatFunction2,
+                        Bool(n1_++),
+                        Bool(n2_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT2 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT2Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT2(PredFormatFunctor2(),
+                        n1_++,
+                        n2_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT2 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT2Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT2(PredFormatFunctor2(),
+                        Bool(n1_++),
+                        Bool(n2_++));
+    finished_ = true;
+  }, "");
+}
+// Sample functions/functors for testing ternary predicate assertions.
+
+// A ternary predicate function.
+template <typename T1, typename T2, typename T3>
+bool PredFunction3(T1 v1, T2 v2, T3 v3) {
+  return v1 + v2 + v3 > 0;
+}
+
+// The following two functions are needed to circumvent a bug in
+// gcc 2.95.3, which sometimes has problem with the above template
+// function.
+bool PredFunction3Int(int v1, int v2, int v3) {
+  return v1 + v2 + v3 > 0;
+}
+bool PredFunction3Bool(Bool v1, Bool v2, Bool v3) {
+  return v1 + v2 + v3 > 0;
+}
+
+// A ternary predicate functor.
+struct PredFunctor3 {
+  template <typename T1, typename T2, typename T3>
+  bool operator()(const T1& v1,
+                  const T2& v2,
+                  const T3& v3) {
+    return v1 + v2 + v3 > 0;
+  }
+};
+
+// A ternary predicate-formatter function.
+template <typename T1, typename T2, typename T3>
+testing::AssertionResult PredFormatFunction3(const char* e1,
+                                             const char* e2,
+                                             const char* e3,
+                                             const T1& v1,
+                                             const T2& v2,
+                                             const T3& v3) {
+  if (PredFunction3(v1, v2, v3))
+    return testing::AssertionSuccess();
+
+  return testing::AssertionFailure()
+      << e1 << " + " << e2 << " + " << e3
+      << " is expected to be positive, but evaluates to "
+      << v1 + v2 + v3 << ".";
+}
+
+// A ternary predicate-formatter functor.
+struct PredFormatFunctor3 {
+  template <typename T1, typename T2, typename T3>
+  testing::AssertionResult operator()(const char* e1,
+                                      const char* e2,
+                                      const char* e3,
+                                      const T1& v1,
+                                      const T2& v2,
+                                      const T3& v3) const {
+    return PredFormatFunction3(e1, e2, e3, v1, v2, v3);
+  }
+};
+
+// Tests for {EXPECT|ASSERT}_PRED_FORMAT3.
+
+class Predicate3Test : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    expected_to_finish_ = true;
+    finished_ = false;
+    n1_ = n2_ = n3_ = 0;
+  }
+
+  virtual void TearDown() {
+    // Verifies that each of the predicate's arguments was evaluated
+    // exactly once.
+    EXPECT_EQ(1, n1_) <<
+        "The predicate assertion didn't evaluate argument 2 "
+        "exactly once.";
+    EXPECT_EQ(1, n2_) <<
+        "The predicate assertion didn't evaluate argument 3 "
+        "exactly once.";
+    EXPECT_EQ(1, n3_) <<
+        "The predicate assertion didn't evaluate argument 4 "
+        "exactly once.";
+
+    // Verifies that the control flow in the test function is expected.
+    if (expected_to_finish_ && !finished_) {
+      FAIL() << "The predicate assertion unexpactedly aborted the test.";
+    } else if (!expected_to_finish_ && finished_) {
+      FAIL() << "The failed predicate assertion didn't abort the test "
+                "as expected.";
+    }
+  }
+
+  // true iff the test function is expected to run to finish.
+  static bool expected_to_finish_;
+
+  // true iff the test function did run to finish.
+  static bool finished_;
+
+  static int n1_;
+  static int n2_;
+  static int n3_;
+};
+
+bool Predicate3Test::expected_to_finish_;
+bool Predicate3Test::finished_;
+int Predicate3Test::n1_;
+int Predicate3Test::n2_;
+int Predicate3Test::n3_;
+
+typedef Predicate3Test EXPECT_PRED_FORMAT3Test;
+typedef Predicate3Test ASSERT_PRED_FORMAT3Test;
+typedef Predicate3Test EXPECT_PRED3Test;
+typedef Predicate3Test ASSERT_PRED3Test;
+
+// Tests a successful EXPECT_PRED3 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED3Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED3(PredFunction3Int,
+               ++n1_,
+               ++n2_,
+               ++n3_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED3 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED3Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED3(PredFunction3Bool,
+               Bool(++n1_),
+               Bool(++n2_),
+               Bool(++n3_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED3 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED3Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED3(PredFunctor3(),
+               ++n1_,
+               ++n2_,
+               ++n3_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED3 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED3Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED3(PredFunctor3(),
+               Bool(++n1_),
+               Bool(++n2_),
+               Bool(++n3_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED3 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED3Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED3(PredFunction3Int,
+                 n1_++,
+                 n2_++,
+                 n3_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED3 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED3Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED3(PredFunction3Bool,
+                 Bool(n1_++),
+                 Bool(n2_++),
+                 Bool(n3_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED3 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED3Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED3(PredFunctor3(),
+                 n1_++,
+                 n2_++,
+                 n3_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED3 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED3Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED3(PredFunctor3(),
+                 Bool(n1_++),
+                 Bool(n2_++),
+                 Bool(n3_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful ASSERT_PRED3 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED3Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED3(PredFunction3Int,
+               ++n1_,
+               ++n2_,
+               ++n3_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED3 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED3Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED3(PredFunction3Bool,
+               Bool(++n1_),
+               Bool(++n2_),
+               Bool(++n3_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED3 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED3Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED3(PredFunctor3(),
+               ++n1_,
+               ++n2_,
+               ++n3_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED3 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED3Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED3(PredFunctor3(),
+               Bool(++n1_),
+               Bool(++n2_),
+               Bool(++n3_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED3 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED3Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED3(PredFunction3Int,
+                 n1_++,
+                 n2_++,
+                 n3_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED3 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED3Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED3(PredFunction3Bool,
+                 Bool(n1_++),
+                 Bool(n2_++),
+                 Bool(n3_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED3 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED3Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED3(PredFunctor3(),
+                 n1_++,
+                 n2_++,
+                 n3_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED3 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED3Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED3(PredFunctor3(),
+                 Bool(n1_++),
+                 Bool(n2_++),
+                 Bool(n3_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful EXPECT_PRED_FORMAT3 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT3Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT3(PredFormatFunction3,
+                      ++n1_,
+                      ++n2_,
+                      ++n3_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT3 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT3Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT3(PredFormatFunction3,
+                      Bool(++n1_),
+                      Bool(++n2_),
+                      Bool(++n3_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT3 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT3Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT3(PredFormatFunctor3(),
+                      ++n1_,
+                      ++n2_,
+                      ++n3_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT3 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT3Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT3(PredFormatFunctor3(),
+                      Bool(++n1_),
+                      Bool(++n2_),
+                      Bool(++n3_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED_FORMAT3 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT3Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT3(PredFormatFunction3,
+                        n1_++,
+                        n2_++,
+                        n3_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT3 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT3Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT3(PredFormatFunction3,
+                        Bool(n1_++),
+                        Bool(n2_++),
+                        Bool(n3_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT3 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT3Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT3(PredFormatFunctor3(),
+                        n1_++,
+                        n2_++,
+                        n3_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT3 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT3Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT3(PredFormatFunctor3(),
+                        Bool(n1_++),
+                        Bool(n2_++),
+                        Bool(n3_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful ASSERT_PRED_FORMAT3 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT3Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT3(PredFormatFunction3,
+                      ++n1_,
+                      ++n2_,
+                      ++n3_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT3 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT3Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT3(PredFormatFunction3,
+                      Bool(++n1_),
+                      Bool(++n2_),
+                      Bool(++n3_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT3 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT3Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT3(PredFormatFunctor3(),
+                      ++n1_,
+                      ++n2_,
+                      ++n3_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT3 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT3Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT3(PredFormatFunctor3(),
+                      Bool(++n1_),
+                      Bool(++n2_),
+                      Bool(++n3_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED_FORMAT3 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT3Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT3(PredFormatFunction3,
+                        n1_++,
+                        n2_++,
+                        n3_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT3 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT3Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT3(PredFormatFunction3,
+                        Bool(n1_++),
+                        Bool(n2_++),
+                        Bool(n3_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT3 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT3Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT3(PredFormatFunctor3(),
+                        n1_++,
+                        n2_++,
+                        n3_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT3 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT3Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT3(PredFormatFunctor3(),
+                        Bool(n1_++),
+                        Bool(n2_++),
+                        Bool(n3_++));
+    finished_ = true;
+  }, "");
+}
+// Sample functions/functors for testing 4-ary predicate assertions.
+
+// A 4-ary predicate function.
+template <typename T1, typename T2, typename T3, typename T4>
+bool PredFunction4(T1 v1, T2 v2, T3 v3, T4 v4) {
+  return v1 + v2 + v3 + v4 > 0;
+}
+
+// The following two functions are needed to circumvent a bug in
+// gcc 2.95.3, which sometimes has problem with the above template
+// function.
+bool PredFunction4Int(int v1, int v2, int v3, int v4) {
+  return v1 + v2 + v3 + v4 > 0;
+}
+bool PredFunction4Bool(Bool v1, Bool v2, Bool v3, Bool v4) {
+  return v1 + v2 + v3 + v4 > 0;
+}
+
+// A 4-ary predicate functor.
+struct PredFunctor4 {
+  template <typename T1, typename T2, typename T3, typename T4>
+  bool operator()(const T1& v1,
+                  const T2& v2,
+                  const T3& v3,
+                  const T4& v4) {
+    return v1 + v2 + v3 + v4 > 0;
+  }
+};
+
+// A 4-ary predicate-formatter function.
+template <typename T1, typename T2, typename T3, typename T4>
+testing::AssertionResult PredFormatFunction4(const char* e1,
+                                             const char* e2,
+                                             const char* e3,
+                                             const char* e4,
+                                             const T1& v1,
+                                             const T2& v2,
+                                             const T3& v3,
+                                             const T4& v4) {
+  if (PredFunction4(v1, v2, v3, v4))
+    return testing::AssertionSuccess();
+
+  return testing::AssertionFailure()
+      << e1 << " + " << e2 << " + " << e3 << " + " << e4
+      << " is expected to be positive, but evaluates to "
+      << v1 + v2 + v3 + v4 << ".";
+}
+
+// A 4-ary predicate-formatter functor.
+struct PredFormatFunctor4 {
+  template <typename T1, typename T2, typename T3, typename T4>
+  testing::AssertionResult operator()(const char* e1,
+                                      const char* e2,
+                                      const char* e3,
+                                      const char* e4,
+                                      const T1& v1,
+                                      const T2& v2,
+                                      const T3& v3,
+                                      const T4& v4) const {
+    return PredFormatFunction4(e1, e2, e3, e4, v1, v2, v3, v4);
+  }
+};
+
+// Tests for {EXPECT|ASSERT}_PRED_FORMAT4.
+
+class Predicate4Test : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    expected_to_finish_ = true;
+    finished_ = false;
+    n1_ = n2_ = n3_ = n4_ = 0;
+  }
+
+  virtual void TearDown() {
+    // Verifies that each of the predicate's arguments was evaluated
+    // exactly once.
+    EXPECT_EQ(1, n1_) <<
+        "The predicate assertion didn't evaluate argument 2 "
+        "exactly once.";
+    EXPECT_EQ(1, n2_) <<
+        "The predicate assertion didn't evaluate argument 3 "
+        "exactly once.";
+    EXPECT_EQ(1, n3_) <<
+        "The predicate assertion didn't evaluate argument 4 "
+        "exactly once.";
+    EXPECT_EQ(1, n4_) <<
+        "The predicate assertion didn't evaluate argument 5 "
+        "exactly once.";
+
+    // Verifies that the control flow in the test function is expected.
+    if (expected_to_finish_ && !finished_) {
+      FAIL() << "The predicate assertion unexpactedly aborted the test.";
+    } else if (!expected_to_finish_ && finished_) {
+      FAIL() << "The failed predicate assertion didn't abort the test "
+                "as expected.";
+    }
+  }
+
+  // true iff the test function is expected to run to finish.
+  static bool expected_to_finish_;
+
+  // true iff the test function did run to finish.
+  static bool finished_;
+
+  static int n1_;
+  static int n2_;
+  static int n3_;
+  static int n4_;
+};
+
+bool Predicate4Test::expected_to_finish_;
+bool Predicate4Test::finished_;
+int Predicate4Test::n1_;
+int Predicate4Test::n2_;
+int Predicate4Test::n3_;
+int Predicate4Test::n4_;
+
+typedef Predicate4Test EXPECT_PRED_FORMAT4Test;
+typedef Predicate4Test ASSERT_PRED_FORMAT4Test;
+typedef Predicate4Test EXPECT_PRED4Test;
+typedef Predicate4Test ASSERT_PRED4Test;
+
+// Tests a successful EXPECT_PRED4 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED4Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED4(PredFunction4Int,
+               ++n1_,
+               ++n2_,
+               ++n3_,
+               ++n4_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED4 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED4Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED4(PredFunction4Bool,
+               Bool(++n1_),
+               Bool(++n2_),
+               Bool(++n3_),
+               Bool(++n4_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED4 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED4Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED4(PredFunctor4(),
+               ++n1_,
+               ++n2_,
+               ++n3_,
+               ++n4_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED4 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED4Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED4(PredFunctor4(),
+               Bool(++n1_),
+               Bool(++n2_),
+               Bool(++n3_),
+               Bool(++n4_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED4 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED4Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED4(PredFunction4Int,
+                 n1_++,
+                 n2_++,
+                 n3_++,
+                 n4_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED4 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED4Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED4(PredFunction4Bool,
+                 Bool(n1_++),
+                 Bool(n2_++),
+                 Bool(n3_++),
+                 Bool(n4_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED4 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED4Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED4(PredFunctor4(),
+                 n1_++,
+                 n2_++,
+                 n3_++,
+                 n4_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED4 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED4Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED4(PredFunctor4(),
+                 Bool(n1_++),
+                 Bool(n2_++),
+                 Bool(n3_++),
+                 Bool(n4_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful ASSERT_PRED4 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED4Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED4(PredFunction4Int,
+               ++n1_,
+               ++n2_,
+               ++n3_,
+               ++n4_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED4 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED4Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED4(PredFunction4Bool,
+               Bool(++n1_),
+               Bool(++n2_),
+               Bool(++n3_),
+               Bool(++n4_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED4 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED4Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED4(PredFunctor4(),
+               ++n1_,
+               ++n2_,
+               ++n3_,
+               ++n4_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED4 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED4Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED4(PredFunctor4(),
+               Bool(++n1_),
+               Bool(++n2_),
+               Bool(++n3_),
+               Bool(++n4_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED4 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED4Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED4(PredFunction4Int,
+                 n1_++,
+                 n2_++,
+                 n3_++,
+                 n4_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED4 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED4Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED4(PredFunction4Bool,
+                 Bool(n1_++),
+                 Bool(n2_++),
+                 Bool(n3_++),
+                 Bool(n4_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED4 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED4Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED4(PredFunctor4(),
+                 n1_++,
+                 n2_++,
+                 n3_++,
+                 n4_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED4 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED4Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED4(PredFunctor4(),
+                 Bool(n1_++),
+                 Bool(n2_++),
+                 Bool(n3_++),
+                 Bool(n4_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful EXPECT_PRED_FORMAT4 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT4Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT4(PredFormatFunction4,
+                      ++n1_,
+                      ++n2_,
+                      ++n3_,
+                      ++n4_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT4 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT4Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT4(PredFormatFunction4,
+                      Bool(++n1_),
+                      Bool(++n2_),
+                      Bool(++n3_),
+                      Bool(++n4_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT4 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT4Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT4(PredFormatFunctor4(),
+                      ++n1_,
+                      ++n2_,
+                      ++n3_,
+                      ++n4_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT4 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT4Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT4(PredFormatFunctor4(),
+                      Bool(++n1_),
+                      Bool(++n2_),
+                      Bool(++n3_),
+                      Bool(++n4_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED_FORMAT4 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT4Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT4(PredFormatFunction4,
+                        n1_++,
+                        n2_++,
+                        n3_++,
+                        n4_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT4 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT4Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT4(PredFormatFunction4,
+                        Bool(n1_++),
+                        Bool(n2_++),
+                        Bool(n3_++),
+                        Bool(n4_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT4 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT4Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT4(PredFormatFunctor4(),
+                        n1_++,
+                        n2_++,
+                        n3_++,
+                        n4_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT4 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT4Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT4(PredFormatFunctor4(),
+                        Bool(n1_++),
+                        Bool(n2_++),
+                        Bool(n3_++),
+                        Bool(n4_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful ASSERT_PRED_FORMAT4 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT4Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT4(PredFormatFunction4,
+                      ++n1_,
+                      ++n2_,
+                      ++n3_,
+                      ++n4_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT4 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT4Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT4(PredFormatFunction4,
+                      Bool(++n1_),
+                      Bool(++n2_),
+                      Bool(++n3_),
+                      Bool(++n4_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT4 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT4Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT4(PredFormatFunctor4(),
+                      ++n1_,
+                      ++n2_,
+                      ++n3_,
+                      ++n4_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT4 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT4Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT4(PredFormatFunctor4(),
+                      Bool(++n1_),
+                      Bool(++n2_),
+                      Bool(++n3_),
+                      Bool(++n4_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED_FORMAT4 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT4Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT4(PredFormatFunction4,
+                        n1_++,
+                        n2_++,
+                        n3_++,
+                        n4_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT4 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT4Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT4(PredFormatFunction4,
+                        Bool(n1_++),
+                        Bool(n2_++),
+                        Bool(n3_++),
+                        Bool(n4_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT4 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT4Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT4(PredFormatFunctor4(),
+                        n1_++,
+                        n2_++,
+                        n3_++,
+                        n4_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT4 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT4Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT4(PredFormatFunctor4(),
+                        Bool(n1_++),
+                        Bool(n2_++),
+                        Bool(n3_++),
+                        Bool(n4_++));
+    finished_ = true;
+  }, "");
+}
+// Sample functions/functors for testing 5-ary predicate assertions.
+
+// A 5-ary predicate function.
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+bool PredFunction5(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5) {
+  return v1 + v2 + v3 + v4 + v5 > 0;
+}
+
+// The following two functions are needed to circumvent a bug in
+// gcc 2.95.3, which sometimes has problem with the above template
+// function.
+bool PredFunction5Int(int v1, int v2, int v3, int v4, int v5) {
+  return v1 + v2 + v3 + v4 + v5 > 0;
+}
+bool PredFunction5Bool(Bool v1, Bool v2, Bool v3, Bool v4, Bool v5) {
+  return v1 + v2 + v3 + v4 + v5 > 0;
+}
+
+// A 5-ary predicate functor.
+struct PredFunctor5 {
+  template <typename T1, typename T2, typename T3, typename T4, typename T5>
+  bool operator()(const T1& v1,
+                  const T2& v2,
+                  const T3& v3,
+                  const T4& v4,
+                  const T5& v5) {
+    return v1 + v2 + v3 + v4 + v5 > 0;
+  }
+};
+
+// A 5-ary predicate-formatter function.
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+testing::AssertionResult PredFormatFunction5(const char* e1,
+                                             const char* e2,
+                                             const char* e3,
+                                             const char* e4,
+                                             const char* e5,
+                                             const T1& v1,
+                                             const T2& v2,
+                                             const T3& v3,
+                                             const T4& v4,
+                                             const T5& v5) {
+  if (PredFunction5(v1, v2, v3, v4, v5))
+    return testing::AssertionSuccess();
+
+  return testing::AssertionFailure()
+      << e1 << " + " << e2 << " + " << e3 << " + " << e4 << " + " << e5
+      << " is expected to be positive, but evaluates to "
+      << v1 + v2 + v3 + v4 + v5 << ".";
+}
+
+// A 5-ary predicate-formatter functor.
+struct PredFormatFunctor5 {
+  template <typename T1, typename T2, typename T3, typename T4, typename T5>
+  testing::AssertionResult operator()(const char* e1,
+                                      const char* e2,
+                                      const char* e3,
+                                      const char* e4,
+                                      const char* e5,
+                                      const T1& v1,
+                                      const T2& v2,
+                                      const T3& v3,
+                                      const T4& v4,
+                                      const T5& v5) const {
+    return PredFormatFunction5(e1, e2, e3, e4, e5, v1, v2, v3, v4, v5);
+  }
+};
+
+// Tests for {EXPECT|ASSERT}_PRED_FORMAT5.
+
+class Predicate5Test : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    expected_to_finish_ = true;
+    finished_ = false;
+    n1_ = n2_ = n3_ = n4_ = n5_ = 0;
+  }
+
+  virtual void TearDown() {
+    // Verifies that each of the predicate's arguments was evaluated
+    // exactly once.
+    EXPECT_EQ(1, n1_) <<
+        "The predicate assertion didn't evaluate argument 2 "
+        "exactly once.";
+    EXPECT_EQ(1, n2_) <<
+        "The predicate assertion didn't evaluate argument 3 "
+        "exactly once.";
+    EXPECT_EQ(1, n3_) <<
+        "The predicate assertion didn't evaluate argument 4 "
+        "exactly once.";
+    EXPECT_EQ(1, n4_) <<
+        "The predicate assertion didn't evaluate argument 5 "
+        "exactly once.";
+    EXPECT_EQ(1, n5_) <<
+        "The predicate assertion didn't evaluate argument 6 "
+        "exactly once.";
+
+    // Verifies that the control flow in the test function is expected.
+    if (expected_to_finish_ && !finished_) {
+      FAIL() << "The predicate assertion unexpactedly aborted the test.";
+    } else if (!expected_to_finish_ && finished_) {
+      FAIL() << "The failed predicate assertion didn't abort the test "
+                "as expected.";
+    }
+  }
+
+  // true iff the test function is expected to run to finish.
+  static bool expected_to_finish_;
+
+  // true iff the test function did run to finish.
+  static bool finished_;
+
+  static int n1_;
+  static int n2_;
+  static int n3_;
+  static int n4_;
+  static int n5_;
+};
+
+bool Predicate5Test::expected_to_finish_;
+bool Predicate5Test::finished_;
+int Predicate5Test::n1_;
+int Predicate5Test::n2_;
+int Predicate5Test::n3_;
+int Predicate5Test::n4_;
+int Predicate5Test::n5_;
+
+typedef Predicate5Test EXPECT_PRED_FORMAT5Test;
+typedef Predicate5Test ASSERT_PRED_FORMAT5Test;
+typedef Predicate5Test EXPECT_PRED5Test;
+typedef Predicate5Test ASSERT_PRED5Test;
+
+// Tests a successful EXPECT_PRED5 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED5Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED5(PredFunction5Int,
+               ++n1_,
+               ++n2_,
+               ++n3_,
+               ++n4_,
+               ++n5_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED5 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED5Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED5(PredFunction5Bool,
+               Bool(++n1_),
+               Bool(++n2_),
+               Bool(++n3_),
+               Bool(++n4_),
+               Bool(++n5_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED5 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED5Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED5(PredFunctor5(),
+               ++n1_,
+               ++n2_,
+               ++n3_,
+               ++n4_,
+               ++n5_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED5 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED5Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED5(PredFunctor5(),
+               Bool(++n1_),
+               Bool(++n2_),
+               Bool(++n3_),
+               Bool(++n4_),
+               Bool(++n5_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED5 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED5Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED5(PredFunction5Int,
+                 n1_++,
+                 n2_++,
+                 n3_++,
+                 n4_++,
+                 n5_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED5 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED5Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED5(PredFunction5Bool,
+                 Bool(n1_++),
+                 Bool(n2_++),
+                 Bool(n3_++),
+                 Bool(n4_++),
+                 Bool(n5_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED5 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED5Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED5(PredFunctor5(),
+                 n1_++,
+                 n2_++,
+                 n3_++,
+                 n4_++,
+                 n5_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED5 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED5Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED5(PredFunctor5(),
+                 Bool(n1_++),
+                 Bool(n2_++),
+                 Bool(n3_++),
+                 Bool(n4_++),
+                 Bool(n5_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful ASSERT_PRED5 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED5Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED5(PredFunction5Int,
+               ++n1_,
+               ++n2_,
+               ++n3_,
+               ++n4_,
+               ++n5_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED5 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED5Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED5(PredFunction5Bool,
+               Bool(++n1_),
+               Bool(++n2_),
+               Bool(++n3_),
+               Bool(++n4_),
+               Bool(++n5_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED5 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED5Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED5(PredFunctor5(),
+               ++n1_,
+               ++n2_,
+               ++n3_,
+               ++n4_,
+               ++n5_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED5 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED5Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED5(PredFunctor5(),
+               Bool(++n1_),
+               Bool(++n2_),
+               Bool(++n3_),
+               Bool(++n4_),
+               Bool(++n5_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED5 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED5Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED5(PredFunction5Int,
+                 n1_++,
+                 n2_++,
+                 n3_++,
+                 n4_++,
+                 n5_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED5 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED5Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED5(PredFunction5Bool,
+                 Bool(n1_++),
+                 Bool(n2_++),
+                 Bool(n3_++),
+                 Bool(n4_++),
+                 Bool(n5_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED5 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED5Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED5(PredFunctor5(),
+                 n1_++,
+                 n2_++,
+                 n3_++,
+                 n4_++,
+                 n5_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED5 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED5Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED5(PredFunctor5(),
+                 Bool(n1_++),
+                 Bool(n2_++),
+                 Bool(n3_++),
+                 Bool(n4_++),
+                 Bool(n5_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful EXPECT_PRED_FORMAT5 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT5Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT5(PredFormatFunction5,
+                      ++n1_,
+                      ++n2_,
+                      ++n3_,
+                      ++n4_,
+                      ++n5_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT5 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT5Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT5(PredFormatFunction5,
+                      Bool(++n1_),
+                      Bool(++n2_),
+                      Bool(++n3_),
+                      Bool(++n4_),
+                      Bool(++n5_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT5 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT5Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT5(PredFormatFunctor5(),
+                      ++n1_,
+                      ++n2_,
+                      ++n3_,
+                      ++n4_,
+                      ++n5_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT5 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT5Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT5(PredFormatFunctor5(),
+                      Bool(++n1_),
+                      Bool(++n2_),
+                      Bool(++n3_),
+                      Bool(++n4_),
+                      Bool(++n5_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED_FORMAT5 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT5Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT5(PredFormatFunction5,
+                        n1_++,
+                        n2_++,
+                        n3_++,
+                        n4_++,
+                        n5_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT5 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT5Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT5(PredFormatFunction5,
+                        Bool(n1_++),
+                        Bool(n2_++),
+                        Bool(n3_++),
+                        Bool(n4_++),
+                        Bool(n5_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT5 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT5Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT5(PredFormatFunctor5(),
+                        n1_++,
+                        n2_++,
+                        n3_++,
+                        n4_++,
+                        n5_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT5 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT5Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT5(PredFormatFunctor5(),
+                        Bool(n1_++),
+                        Bool(n2_++),
+                        Bool(n3_++),
+                        Bool(n4_++),
+                        Bool(n5_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful ASSERT_PRED_FORMAT5 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT5Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT5(PredFormatFunction5,
+                      ++n1_,
+                      ++n2_,
+                      ++n3_,
+                      ++n4_,
+                      ++n5_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT5 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT5Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT5(PredFormatFunction5,
+                      Bool(++n1_),
+                      Bool(++n2_),
+                      Bool(++n3_),
+                      Bool(++n4_),
+                      Bool(++n5_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT5 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT5Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT5(PredFormatFunctor5(),
+                      ++n1_,
+                      ++n2_,
+                      ++n3_,
+                      ++n4_,
+                      ++n5_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT5 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT5Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT5(PredFormatFunctor5(),
+                      Bool(++n1_),
+                      Bool(++n2_),
+                      Bool(++n3_),
+                      Bool(++n4_),
+                      Bool(++n5_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED_FORMAT5 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT5Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT5(PredFormatFunction5,
+                        n1_++,
+                        n2_++,
+                        n3_++,
+                        n4_++,
+                        n5_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT5 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT5Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT5(PredFormatFunction5,
+                        Bool(n1_++),
+                        Bool(n2_++),
+                        Bool(n3_++),
+                        Bool(n4_++),
+                        Bool(n5_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT5 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT5Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT5(PredFormatFunctor5(),
+                        n1_++,
+                        n2_++,
+                        n3_++,
+                        n4_++,
+                        n5_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT5 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT5Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT5(PredFormatFunctor5(),
+                        Bool(n1_++),
+                        Bool(n2_++),
+                        Bool(n3_++),
+                        Bool(n4_++),
+                        Bool(n5_++));
+    finished_ = true;
+  }, "");
+}
diff --git a/third_party/googletest/googletest/test/gtest_premature_exit_test.cc b/third_party/googletest/googletest/test/gtest_premature_exit_test.cc
new file mode 100644
index 0000000..3b4dc7d
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_premature_exit_test.cc
@@ -0,0 +1,127 @@
+// Copyright 2013, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// Tests that Google Test manipulates the premature-exit-detection
+// file correctly.
+
+#include <stdio.h>
+
+#include "gtest/gtest.h"
+
+using ::testing::InitGoogleTest;
+using ::testing::Test;
+using ::testing::internal::posix::GetEnv;
+using ::testing::internal::posix::Stat;
+using ::testing::internal::posix::StatStruct;
+
+namespace {
+
+class PrematureExitTest : public Test {
+ public:
+  // Returns true iff the given file exists.
+  static bool FileExists(const char* filepath) {
+    StatStruct stat;
+    return Stat(filepath, &stat) == 0;
+  }
+
+ protected:
+  PrematureExitTest() {
+    premature_exit_file_path_ = GetEnv("TEST_PREMATURE_EXIT_FILE");
+
+    // Normalize NULL to "" for ease of handling.
+    if (premature_exit_file_path_ == NULL) {
+      premature_exit_file_path_ = "";
+    }
+  }
+
+  // Returns true iff the premature-exit file exists.
+  bool PrematureExitFileExists() const {
+    return FileExists(premature_exit_file_path_);
+  }
+
+  const char* premature_exit_file_path_;
+};
+
+typedef PrematureExitTest PrematureExitDeathTest;
+
+// Tests that:
+//   - the premature-exit file exists during the execution of a
+//     death test (EXPECT_DEATH*), and
+//   - a death test doesn't interfere with the main test process's
+//     handling of the premature-exit file.
+TEST_F(PrematureExitDeathTest, FileExistsDuringExecutionOfDeathTest) {
+  if (*premature_exit_file_path_ == '\0') {
+    return;
+  }
+
+  EXPECT_DEATH_IF_SUPPORTED({
+      // If the file exists, crash the process such that the main test
+      // process will catch the (expected) crash and report a success;
+      // otherwise don't crash, which will cause the main test process
+      // to report that the death test has failed.
+      if (PrematureExitFileExists()) {
+        exit(1);
+      }
+    }, "");
+}
+
+// Tests that the premature-exit file exists during the execution of a
+// normal (non-death) test.
+TEST_F(PrematureExitTest, PrematureExitFileExistsDuringTestExecution) {
+  if (*premature_exit_file_path_ == '\0') {
+    return;
+  }
+
+  EXPECT_TRUE(PrematureExitFileExists())
+      << " file " << premature_exit_file_path_
+      << " should exist during test execution, but doesn't.";
+}
+
+}  // namespace
+
+int main(int argc, char **argv) {
+  InitGoogleTest(&argc, argv);
+  const int exit_code = RUN_ALL_TESTS();
+
+  // Test that the premature-exit file is deleted upon return from
+  // RUN_ALL_TESTS().
+  const char* const filepath = GetEnv("TEST_PREMATURE_EXIT_FILE");
+  if (filepath != NULL && *filepath != '\0') {
+    if (PrematureExitTest::FileExists(filepath)) {
+      printf(
+          "File %s shouldn't exist after the test program finishes, but does.",
+          filepath);
+      return 1;
+    }
+  }
+
+  return exit_code;
+}
diff --git a/third_party/googletest/googletest/test/gtest_prod_test.cc b/third_party/googletest/googletest/test/gtest_prod_test.cc
new file mode 100644
index 0000000..060abce
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_prod_test.cc
@@ -0,0 +1,57 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// Unit test for include/gtest/gtest_prod.h.
+
+#include "gtest/gtest.h"
+#include "test/production.h"
+
+// Tests that private members can be accessed from a TEST declared as
+// a friend of the class.
+TEST(PrivateCodeTest, CanAccessPrivateMembers) {
+  PrivateCode a;
+  EXPECT_EQ(0, a.x_);
+
+  a.set_x(1);
+  EXPECT_EQ(1, a.x_);
+}
+
+typedef testing::Test PrivateCodeFixtureTest;
+
+// Tests that private members can be accessed from a TEST_F declared
+// as a friend of the class.
+TEST_F(PrivateCodeFixtureTest, CanAccessPrivateMembers) {
+  PrivateCode a;
+  EXPECT_EQ(0, a.x_);
+
+  a.set_x(2);
+  EXPECT_EQ(2, a.x_);
+}
diff --git a/third_party/googletest/googletest/test/gtest_repeat_test.cc b/third_party/googletest/googletest/test/gtest_repeat_test.cc
new file mode 100644
index 0000000..481012a
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_repeat_test.cc
@@ -0,0 +1,253 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Tests the --gtest_repeat=number flag.
+
+#include <stdlib.h>
+#include <iostream>
+#include "gtest/gtest.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+
+GTEST_DECLARE_string_(death_test_style);
+GTEST_DECLARE_string_(filter);
+GTEST_DECLARE_int32_(repeat);
+
+}  // namespace testing
+
+using testing::GTEST_FLAG(death_test_style);
+using testing::GTEST_FLAG(filter);
+using testing::GTEST_FLAG(repeat);
+
+namespace {
+
+// We need this when we are testing Google Test itself and therefore
+// cannot use Google Test assertions.
+#define GTEST_CHECK_INT_EQ_(expected, actual) \
+  do {\
+    const int expected_val = (expected);\
+    const int actual_val = (actual);\
+    if (::testing::internal::IsTrue(expected_val != actual_val)) {\
+      ::std::cout << "Value of: " #actual "\n"\
+                  << "  Actual: " << actual_val << "\n"\
+                  << "Expected: " #expected "\n"\
+                  << "Which is: " << expected_val << "\n";\
+      ::testing::internal::posix::Abort();\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+
+// Used for verifying that global environment set-up and tear-down are
+// inside the gtest_repeat loop.
+
+int g_environment_set_up_count = 0;
+int g_environment_tear_down_count = 0;
+
+class MyEnvironment : public testing::Environment {
+ public:
+  MyEnvironment() {}
+  virtual void SetUp() { g_environment_set_up_count++; }
+  virtual void TearDown() { g_environment_tear_down_count++; }
+};
+
+// A test that should fail.
+
+int g_should_fail_count = 0;
+
+TEST(FooTest, ShouldFail) {
+  g_should_fail_count++;
+  EXPECT_EQ(0, 1) << "Expected failure.";
+}
+
+// A test that should pass.
+
+int g_should_pass_count = 0;
+
+TEST(FooTest, ShouldPass) {
+  g_should_pass_count++;
+}
+
+// A test that contains a thread-safe death test and a fast death
+// test.  It should pass.
+
+int g_death_test_count = 0;
+
+TEST(BarDeathTest, ThreadSafeAndFast) {
+  g_death_test_count++;
+
+  GTEST_FLAG(death_test_style) = "threadsafe";
+  EXPECT_DEATH_IF_SUPPORTED(::testing::internal::posix::Abort(), "");
+
+  GTEST_FLAG(death_test_style) = "fast";
+  EXPECT_DEATH_IF_SUPPORTED(::testing::internal::posix::Abort(), "");
+}
+
+#if GTEST_HAS_PARAM_TEST
+int g_param_test_count = 0;
+
+const int kNumberOfParamTests = 10;
+
+class MyParamTest : public testing::TestWithParam<int> {};
+
+TEST_P(MyParamTest, ShouldPass) {
+  // TODO(vladl@google.com): Make parameter value checking robust
+  //                         WRT order of tests.
+  GTEST_CHECK_INT_EQ_(g_param_test_count % kNumberOfParamTests, GetParam());
+  g_param_test_count++;
+}
+INSTANTIATE_TEST_CASE_P(MyParamSequence,
+                        MyParamTest,
+                        testing::Range(0, kNumberOfParamTests));
+#endif  // GTEST_HAS_PARAM_TEST
+
+// Resets the count for each test.
+void ResetCounts() {
+  g_environment_set_up_count = 0;
+  g_environment_tear_down_count = 0;
+  g_should_fail_count = 0;
+  g_should_pass_count = 0;
+  g_death_test_count = 0;
+#if GTEST_HAS_PARAM_TEST
+  g_param_test_count = 0;
+#endif  // GTEST_HAS_PARAM_TEST
+}
+
+// Checks that the count for each test is expected.
+void CheckCounts(int expected) {
+  GTEST_CHECK_INT_EQ_(expected, g_environment_set_up_count);
+  GTEST_CHECK_INT_EQ_(expected, g_environment_tear_down_count);
+  GTEST_CHECK_INT_EQ_(expected, g_should_fail_count);
+  GTEST_CHECK_INT_EQ_(expected, g_should_pass_count);
+  GTEST_CHECK_INT_EQ_(expected, g_death_test_count);
+#if GTEST_HAS_PARAM_TEST
+  GTEST_CHECK_INT_EQ_(expected * kNumberOfParamTests, g_param_test_count);
+#endif  // GTEST_HAS_PARAM_TEST
+}
+
+// Tests the behavior of Google Test when --gtest_repeat is not specified.
+void TestRepeatUnspecified() {
+  ResetCounts();
+  GTEST_CHECK_INT_EQ_(1, RUN_ALL_TESTS());
+  CheckCounts(1);
+}
+
+// Tests the behavior of Google Test when --gtest_repeat has the given value.
+void TestRepeat(int repeat) {
+  GTEST_FLAG(repeat) = repeat;
+
+  ResetCounts();
+  GTEST_CHECK_INT_EQ_(repeat > 0 ? 1 : 0, RUN_ALL_TESTS());
+  CheckCounts(repeat);
+}
+
+// Tests using --gtest_repeat when --gtest_filter specifies an empty
+// set of tests.
+void TestRepeatWithEmptyFilter(int repeat) {
+  GTEST_FLAG(repeat) = repeat;
+  GTEST_FLAG(filter) = "None";
+
+  ResetCounts();
+  GTEST_CHECK_INT_EQ_(0, RUN_ALL_TESTS());
+  CheckCounts(0);
+}
+
+// Tests using --gtest_repeat when --gtest_filter specifies a set of
+// successful tests.
+void TestRepeatWithFilterForSuccessfulTests(int repeat) {
+  GTEST_FLAG(repeat) = repeat;
+  GTEST_FLAG(filter) = "*-*ShouldFail";
+
+  ResetCounts();
+  GTEST_CHECK_INT_EQ_(0, RUN_ALL_TESTS());
+  GTEST_CHECK_INT_EQ_(repeat, g_environment_set_up_count);
+  GTEST_CHECK_INT_EQ_(repeat, g_environment_tear_down_count);
+  GTEST_CHECK_INT_EQ_(0, g_should_fail_count);
+  GTEST_CHECK_INT_EQ_(repeat, g_should_pass_count);
+  GTEST_CHECK_INT_EQ_(repeat, g_death_test_count);
+#if GTEST_HAS_PARAM_TEST
+  GTEST_CHECK_INT_EQ_(repeat * kNumberOfParamTests, g_param_test_count);
+#endif  // GTEST_HAS_PARAM_TEST
+}
+
+// Tests using --gtest_repeat when --gtest_filter specifies a set of
+// failed tests.
+void TestRepeatWithFilterForFailedTests(int repeat) {
+  GTEST_FLAG(repeat) = repeat;
+  GTEST_FLAG(filter) = "*ShouldFail";
+
+  ResetCounts();
+  GTEST_CHECK_INT_EQ_(1, RUN_ALL_TESTS());
+  GTEST_CHECK_INT_EQ_(repeat, g_environment_set_up_count);
+  GTEST_CHECK_INT_EQ_(repeat, g_environment_tear_down_count);
+  GTEST_CHECK_INT_EQ_(repeat, g_should_fail_count);
+  GTEST_CHECK_INT_EQ_(0, g_should_pass_count);
+  GTEST_CHECK_INT_EQ_(0, g_death_test_count);
+#if GTEST_HAS_PARAM_TEST
+  GTEST_CHECK_INT_EQ_(0, g_param_test_count);
+#endif  // GTEST_HAS_PARAM_TEST
+}
+
+}  // namespace
+
+int main(int argc, char **argv) {
+  testing::InitGoogleTest(&argc, argv);
+  testing::AddGlobalTestEnvironment(new MyEnvironment);
+
+  TestRepeatUnspecified();
+  TestRepeat(0);
+  TestRepeat(1);
+  TestRepeat(5);
+
+  TestRepeatWithEmptyFilter(2);
+  TestRepeatWithEmptyFilter(3);
+
+  TestRepeatWithFilterForSuccessfulTests(3);
+
+  TestRepeatWithFilterForFailedTests(4);
+
+  // It would be nice to verify that the tests indeed loop forever
+  // when GTEST_FLAG(repeat) is negative, but this test will be quite
+  // complicated to write.  Since this flag is for interactive
+  // debugging only and doesn't affect the normal test result, such a
+  // test would be an overkill.
+
+  printf("PASS\n");
+  return 0;
+}
diff --git a/third_party/googletest/googletest/test/gtest_shuffle_test.py b/third_party/googletest/googletest/test/gtest_shuffle_test.py
new file mode 100755
index 0000000..30d0303
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_shuffle_test.py
@@ -0,0 +1,325 @@
+#!/usr/bin/env python
+#
+# Copyright 2009 Google Inc. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Verifies that test shuffling works."""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import os
+import gtest_test_utils
+
+# Command to run the gtest_shuffle_test_ program.
+COMMAND = gtest_test_utils.GetTestExecutablePath('gtest_shuffle_test_')
+
+# The environment variables for test sharding.
+TOTAL_SHARDS_ENV_VAR = 'GTEST_TOTAL_SHARDS'
+SHARD_INDEX_ENV_VAR = 'GTEST_SHARD_INDEX'
+
+TEST_FILTER = 'A*.A:A*.B:C*'
+
+ALL_TESTS = []
+ACTIVE_TESTS = []
+FILTERED_TESTS = []
+SHARDED_TESTS = []
+
+SHUFFLED_ALL_TESTS = []
+SHUFFLED_ACTIVE_TESTS = []
+SHUFFLED_FILTERED_TESTS = []
+SHUFFLED_SHARDED_TESTS = []
+
+
+def AlsoRunDisabledTestsFlag():
+  return '--gtest_also_run_disabled_tests'
+
+
+def FilterFlag(test_filter):
+  return '--gtest_filter=%s' % (test_filter,)
+
+
+def RepeatFlag(n):
+  return '--gtest_repeat=%s' % (n,)
+
+
+def ShuffleFlag():
+  return '--gtest_shuffle'
+
+
+def RandomSeedFlag(n):
+  return '--gtest_random_seed=%s' % (n,)
+
+
+def RunAndReturnOutput(extra_env, args):
+  """Runs the test program and returns its output."""
+
+  environ_copy = os.environ.copy()
+  environ_copy.update(extra_env)
+
+  return gtest_test_utils.Subprocess([COMMAND] + args, env=environ_copy).output
+
+
+def GetTestsForAllIterations(extra_env, args):
+  """Runs the test program and returns a list of test lists.
+
+  Args:
+    extra_env: a map from environment variables to their values
+    args: command line flags to pass to gtest_shuffle_test_
+
+  Returns:
+    A list where the i-th element is the list of tests run in the i-th
+    test iteration.
+  """
+
+  test_iterations = []
+  for line in RunAndReturnOutput(extra_env, args).split('\n'):
+    if line.startswith('----'):
+      tests = []
+      test_iterations.append(tests)
+    elif line.strip():
+      tests.append(line.strip())  # 'TestCaseName.TestName'
+
+  return test_iterations
+
+
+def GetTestCases(tests):
+  """Returns a list of test cases in the given full test names.
+
+  Args:
+    tests: a list of full test names
+
+  Returns:
+    A list of test cases from 'tests', in their original order.
+    Consecutive duplicates are removed.
+  """
+
+  test_cases = []
+  for test in tests:
+    test_case = test.split('.')[0]
+    if not test_case in test_cases:
+      test_cases.append(test_case)
+
+  return test_cases
+
+
+def CalculateTestLists():
+  """Calculates the list of tests run under different flags."""
+
+  if not ALL_TESTS:
+    ALL_TESTS.extend(
+        GetTestsForAllIterations({}, [AlsoRunDisabledTestsFlag()])[0])
+
+  if not ACTIVE_TESTS:
+    ACTIVE_TESTS.extend(GetTestsForAllIterations({}, [])[0])
+
+  if not FILTERED_TESTS:
+    FILTERED_TESTS.extend(
+        GetTestsForAllIterations({}, [FilterFlag(TEST_FILTER)])[0])
+
+  if not SHARDED_TESTS:
+    SHARDED_TESTS.extend(
+        GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
+                                  SHARD_INDEX_ENV_VAR: '1'},
+                                 [])[0])
+
+  if not SHUFFLED_ALL_TESTS:
+    SHUFFLED_ALL_TESTS.extend(GetTestsForAllIterations(
+        {}, [AlsoRunDisabledTestsFlag(), ShuffleFlag(), RandomSeedFlag(1)])[0])
+
+  if not SHUFFLED_ACTIVE_TESTS:
+    SHUFFLED_ACTIVE_TESTS.extend(GetTestsForAllIterations(
+        {}, [ShuffleFlag(), RandomSeedFlag(1)])[0])
+
+  if not SHUFFLED_FILTERED_TESTS:
+    SHUFFLED_FILTERED_TESTS.extend(GetTestsForAllIterations(
+        {}, [ShuffleFlag(), RandomSeedFlag(1), FilterFlag(TEST_FILTER)])[0])
+
+  if not SHUFFLED_SHARDED_TESTS:
+    SHUFFLED_SHARDED_TESTS.extend(
+        GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
+                                  SHARD_INDEX_ENV_VAR: '1'},
+                                 [ShuffleFlag(), RandomSeedFlag(1)])[0])
+
+
+class GTestShuffleUnitTest(gtest_test_utils.TestCase):
+  """Tests test shuffling."""
+
+  def setUp(self):
+    CalculateTestLists()
+
+  def testShufflePreservesNumberOfTests(self):
+    self.assertEqual(len(ALL_TESTS), len(SHUFFLED_ALL_TESTS))
+    self.assertEqual(len(ACTIVE_TESTS), len(SHUFFLED_ACTIVE_TESTS))
+    self.assertEqual(len(FILTERED_TESTS), len(SHUFFLED_FILTERED_TESTS))
+    self.assertEqual(len(SHARDED_TESTS), len(SHUFFLED_SHARDED_TESTS))
+
+  def testShuffleChangesTestOrder(self):
+    self.assert_(SHUFFLED_ALL_TESTS != ALL_TESTS, SHUFFLED_ALL_TESTS)
+    self.assert_(SHUFFLED_ACTIVE_TESTS != ACTIVE_TESTS, SHUFFLED_ACTIVE_TESTS)
+    self.assert_(SHUFFLED_FILTERED_TESTS != FILTERED_TESTS,
+                 SHUFFLED_FILTERED_TESTS)
+    self.assert_(SHUFFLED_SHARDED_TESTS != SHARDED_TESTS,
+                 SHUFFLED_SHARDED_TESTS)
+
+  def testShuffleChangesTestCaseOrder(self):
+    self.assert_(GetTestCases(SHUFFLED_ALL_TESTS) != GetTestCases(ALL_TESTS),
+                 GetTestCases(SHUFFLED_ALL_TESTS))
+    self.assert_(
+        GetTestCases(SHUFFLED_ACTIVE_TESTS) != GetTestCases(ACTIVE_TESTS),
+        GetTestCases(SHUFFLED_ACTIVE_TESTS))
+    self.assert_(
+        GetTestCases(SHUFFLED_FILTERED_TESTS) != GetTestCases(FILTERED_TESTS),
+        GetTestCases(SHUFFLED_FILTERED_TESTS))
+    self.assert_(
+        GetTestCases(SHUFFLED_SHARDED_TESTS) != GetTestCases(SHARDED_TESTS),
+        GetTestCases(SHUFFLED_SHARDED_TESTS))
+
+  def testShuffleDoesNotRepeatTest(self):
+    for test in SHUFFLED_ALL_TESTS:
+      self.assertEqual(1, SHUFFLED_ALL_TESTS.count(test),
+                       '%s appears more than once' % (test,))
+    for test in SHUFFLED_ACTIVE_TESTS:
+      self.assertEqual(1, SHUFFLED_ACTIVE_TESTS.count(test),
+                       '%s appears more than once' % (test,))
+    for test in SHUFFLED_FILTERED_TESTS:
+      self.assertEqual(1, SHUFFLED_FILTERED_TESTS.count(test),
+                       '%s appears more than once' % (test,))
+    for test in SHUFFLED_SHARDED_TESTS:
+      self.assertEqual(1, SHUFFLED_SHARDED_TESTS.count(test),
+                       '%s appears more than once' % (test,))
+
+  def testShuffleDoesNotCreateNewTest(self):
+    for test in SHUFFLED_ALL_TESTS:
+      self.assert_(test in ALL_TESTS, '%s is an invalid test' % (test,))
+    for test in SHUFFLED_ACTIVE_TESTS:
+      self.assert_(test in ACTIVE_TESTS, '%s is an invalid test' % (test,))
+    for test in SHUFFLED_FILTERED_TESTS:
+      self.assert_(test in FILTERED_TESTS, '%s is an invalid test' % (test,))
+    for test in SHUFFLED_SHARDED_TESTS:
+      self.assert_(test in SHARDED_TESTS, '%s is an invalid test' % (test,))
+
+  def testShuffleIncludesAllTests(self):
+    for test in ALL_TESTS:
+      self.assert_(test in SHUFFLED_ALL_TESTS, '%s is missing' % (test,))
+    for test in ACTIVE_TESTS:
+      self.assert_(test in SHUFFLED_ACTIVE_TESTS, '%s is missing' % (test,))
+    for test in FILTERED_TESTS:
+      self.assert_(test in SHUFFLED_FILTERED_TESTS, '%s is missing' % (test,))
+    for test in SHARDED_TESTS:
+      self.assert_(test in SHUFFLED_SHARDED_TESTS, '%s is missing' % (test,))
+
+  def testShuffleLeavesDeathTestsAtFront(self):
+    non_death_test_found = False
+    for test in SHUFFLED_ACTIVE_TESTS:
+      if 'DeathTest.' in test:
+        self.assert_(not non_death_test_found,
+                     '%s appears after a non-death test' % (test,))
+      else:
+        non_death_test_found = True
+
+  def _VerifyTestCasesDoNotInterleave(self, tests):
+    test_cases = []
+    for test in tests:
+      [test_case, _] = test.split('.')
+      if test_cases and test_cases[-1] != test_case:
+        test_cases.append(test_case)
+        self.assertEqual(1, test_cases.count(test_case),
+                         'Test case %s is not grouped together in %s' %
+                         (test_case, tests))
+
+  def testShuffleDoesNotInterleaveTestCases(self):
+    self._VerifyTestCasesDoNotInterleave(SHUFFLED_ALL_TESTS)
+    self._VerifyTestCasesDoNotInterleave(SHUFFLED_ACTIVE_TESTS)
+    self._VerifyTestCasesDoNotInterleave(SHUFFLED_FILTERED_TESTS)
+    self._VerifyTestCasesDoNotInterleave(SHUFFLED_SHARDED_TESTS)
+
+  def testShuffleRestoresOrderAfterEachIteration(self):
+    # Get the test lists in all 3 iterations, using random seed 1, 2,
+    # and 3 respectively.  Google Test picks a different seed in each
+    # iteration, and this test depends on the current implementation
+    # picking successive numbers.  This dependency is not ideal, but
+    # makes the test much easier to write.
+    [tests_in_iteration1, tests_in_iteration2, tests_in_iteration3] = (
+        GetTestsForAllIterations(
+            {}, [ShuffleFlag(), RandomSeedFlag(1), RepeatFlag(3)]))
+
+    # Make sure running the tests with random seed 1 gets the same
+    # order as in iteration 1 above.
+    [tests_with_seed1] = GetTestsForAllIterations(
+        {}, [ShuffleFlag(), RandomSeedFlag(1)])
+    self.assertEqual(tests_in_iteration1, tests_with_seed1)
+
+    # Make sure running the tests with random seed 2 gets the same
+    # order as in iteration 2 above.  Success means that Google Test
+    # correctly restores the test order before re-shuffling at the
+    # beginning of iteration 2.
+    [tests_with_seed2] = GetTestsForAllIterations(
+        {}, [ShuffleFlag(), RandomSeedFlag(2)])
+    self.assertEqual(tests_in_iteration2, tests_with_seed2)
+
+    # Make sure running the tests with random seed 3 gets the same
+    # order as in iteration 3 above.  Success means that Google Test
+    # correctly restores the test order before re-shuffling at the
+    # beginning of iteration 3.
+    [tests_with_seed3] = GetTestsForAllIterations(
+        {}, [ShuffleFlag(), RandomSeedFlag(3)])
+    self.assertEqual(tests_in_iteration3, tests_with_seed3)
+
+  def testShuffleGeneratesNewOrderInEachIteration(self):
+    [tests_in_iteration1, tests_in_iteration2, tests_in_iteration3] = (
+        GetTestsForAllIterations(
+            {}, [ShuffleFlag(), RandomSeedFlag(1), RepeatFlag(3)]))
+
+    self.assert_(tests_in_iteration1 != tests_in_iteration2,
+                 tests_in_iteration1)
+    self.assert_(tests_in_iteration1 != tests_in_iteration3,
+                 tests_in_iteration1)
+    self.assert_(tests_in_iteration2 != tests_in_iteration3,
+                 tests_in_iteration2)
+
+  def testShuffleShardedTestsPreservesPartition(self):
+    # If we run M tests on N shards, the same M tests should be run in
+    # total, regardless of the random seeds used by the shards.
+    [tests1] = GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
+                                         SHARD_INDEX_ENV_VAR: '0'},
+                                        [ShuffleFlag(), RandomSeedFlag(1)])
+    [tests2] = GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
+                                         SHARD_INDEX_ENV_VAR: '1'},
+                                        [ShuffleFlag(), RandomSeedFlag(20)])
+    [tests3] = GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
+                                         SHARD_INDEX_ENV_VAR: '2'},
+                                        [ShuffleFlag(), RandomSeedFlag(25)])
+    sorted_sharded_tests = tests1 + tests2 + tests3
+    sorted_sharded_tests.sort()
+    sorted_active_tests = []
+    sorted_active_tests.extend(ACTIVE_TESTS)
+    sorted_active_tests.sort()
+    self.assertEqual(sorted_active_tests, sorted_sharded_tests)
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/third_party/googletest/googletest/test/gtest_shuffle_test_.cc b/third_party/googletest/googletest/test/gtest_shuffle_test_.cc
new file mode 100644
index 0000000..6fb441b
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_shuffle_test_.cc
@@ -0,0 +1,103 @@
+// Copyright 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Verifies that test shuffling works.
+
+#include "gtest/gtest.h"
+
+namespace {
+
+using ::testing::EmptyTestEventListener;
+using ::testing::InitGoogleTest;
+using ::testing::Message;
+using ::testing::Test;
+using ::testing::TestEventListeners;
+using ::testing::TestInfo;
+using ::testing::UnitTest;
+using ::testing::internal::scoped_ptr;
+
+// The test methods are empty, as the sole purpose of this program is
+// to print the test names before/after shuffling.
+
+class A : public Test {};
+TEST_F(A, A) {}
+TEST_F(A, B) {}
+
+TEST(ADeathTest, A) {}
+TEST(ADeathTest, B) {}
+TEST(ADeathTest, C) {}
+
+TEST(B, A) {}
+TEST(B, B) {}
+TEST(B, C) {}
+TEST(B, DISABLED_D) {}
+TEST(B, DISABLED_E) {}
+
+TEST(BDeathTest, A) {}
+TEST(BDeathTest, B) {}
+
+TEST(C, A) {}
+TEST(C, B) {}
+TEST(C, C) {}
+TEST(C, DISABLED_D) {}
+
+TEST(CDeathTest, A) {}
+
+TEST(DISABLED_D, A) {}
+TEST(DISABLED_D, DISABLED_B) {}
+
+// This printer prints the full test names only, starting each test
+// iteration with a "----" marker.
+class TestNamePrinter : public EmptyTestEventListener {
+ public:
+  virtual void OnTestIterationStart(const UnitTest& /* unit_test */,
+                                    int /* iteration */) {
+    printf("----\n");
+  }
+
+  virtual void OnTestStart(const TestInfo& test_info) {
+    printf("%s.%s\n", test_info.test_case_name(), test_info.name());
+  }
+};
+
+}  // namespace
+
+int main(int argc, char **argv) {
+  InitGoogleTest(&argc, argv);
+
+  // Replaces the default printer with TestNamePrinter, which prints
+  // the test name only.
+  TestEventListeners& listeners = UnitTest::GetInstance()->listeners();
+  delete listeners.Release(listeners.default_result_printer());
+  listeners.Append(new TestNamePrinter);
+
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/googletest/googletest/test/gtest_sole_header_test.cc b/third_party/googletest/googletest/test/gtest_sole_header_test.cc
new file mode 100644
index 0000000..ccd091a
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_sole_header_test.cc
@@ -0,0 +1,57 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: mheule@google.com (Markus Heule)
+//
+// This test verifies that it's possible to use Google Test by including
+// the gtest.h header file alone.
+
+#include "gtest/gtest.h"
+
+namespace {
+
+void Subroutine() {
+  EXPECT_EQ(42, 42);
+}
+
+TEST(NoFatalFailureTest, ExpectNoFatalFailure) {
+  EXPECT_NO_FATAL_FAILURE(;);
+  EXPECT_NO_FATAL_FAILURE(SUCCEED());
+  EXPECT_NO_FATAL_FAILURE(Subroutine());
+  EXPECT_NO_FATAL_FAILURE({ SUCCEED(); });
+}
+
+TEST(NoFatalFailureTest, AssertNoFatalFailure) {
+  ASSERT_NO_FATAL_FAILURE(;);
+  ASSERT_NO_FATAL_FAILURE(SUCCEED());
+  ASSERT_NO_FATAL_FAILURE(Subroutine());
+  ASSERT_NO_FATAL_FAILURE({ SUCCEED(); });
+}
+
+}  // namespace
diff --git a/third_party/googletest/googletest/test/gtest_stress_test.cc b/third_party/googletest/googletest/test/gtest_stress_test.cc
new file mode 100644
index 0000000..e7daa43
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_stress_test.cc
@@ -0,0 +1,256 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Tests that SCOPED_TRACE() and various Google Test assertions can be
+// used in a large number of threads concurrently.
+
+#include "gtest/gtest.h"
+
+#include <iostream>
+#include <vector>
+
+// We must define this macro in order to #include
+// gtest-internal-inl.h.  This is how Google Test prevents a user from
+// accidentally depending on its internal implementation.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+#if GTEST_IS_THREADSAFE
+
+namespace testing {
+namespace {
+
+using internal::Notification;
+using internal::TestPropertyKeyIs;
+using internal::ThreadWithParam;
+using internal::scoped_ptr;
+
+// In order to run tests in this file, for platforms where Google Test is
+// thread safe, implement ThreadWithParam. See the description of its API
+// in gtest-port.h, where it is defined for already supported platforms.
+
+// How many threads to create?
+const int kThreadCount = 50;
+
+std::string IdToKey(int id, const char* suffix) {
+  Message key;
+  key << "key_" << id << "_" << suffix;
+  return key.GetString();
+}
+
+std::string IdToString(int id) {
+  Message id_message;
+  id_message << id;
+  return id_message.GetString();
+}
+
+void ExpectKeyAndValueWereRecordedForId(
+    const std::vector<TestProperty>& properties,
+    int id, const char* suffix) {
+  TestPropertyKeyIs matches_key(IdToKey(id, suffix).c_str());
+  const std::vector<TestProperty>::const_iterator property =
+      std::find_if(properties.begin(), properties.end(), matches_key);
+  ASSERT_TRUE(property != properties.end())
+      << "expecting " << suffix << " value for id " << id;
+  EXPECT_STREQ(IdToString(id).c_str(), property->value());
+}
+
+// Calls a large number of Google Test assertions, where exactly one of them
+// will fail.
+void ManyAsserts(int id) {
+  GTEST_LOG_(INFO) << "Thread #" << id << " running...";
+
+  SCOPED_TRACE(Message() << "Thread #" << id);
+
+  for (int i = 0; i < kThreadCount; i++) {
+    SCOPED_TRACE(Message() << "Iteration #" << i);
+
+    // A bunch of assertions that should succeed.
+    EXPECT_TRUE(true);
+    ASSERT_FALSE(false) << "This shouldn't fail.";
+    EXPECT_STREQ("a", "a");
+    ASSERT_LE(5, 6);
+    EXPECT_EQ(i, i) << "This shouldn't fail.";
+
+    // RecordProperty() should interact safely with other threads as well.
+    // The shared_key forces property updates.
+    Test::RecordProperty(IdToKey(id, "string").c_str(), IdToString(id).c_str());
+    Test::RecordProperty(IdToKey(id, "int").c_str(), id);
+    Test::RecordProperty("shared_key", IdToString(id).c_str());
+
+    // This assertion should fail kThreadCount times per thread.  It
+    // is for testing whether Google Test can handle failed assertions in a
+    // multi-threaded context.
+    EXPECT_LT(i, 0) << "This should always fail.";
+  }
+}
+
+void CheckTestFailureCount(int expected_failures) {
+  const TestInfo* const info = UnitTest::GetInstance()->current_test_info();
+  const TestResult* const result = info->result();
+  GTEST_CHECK_(expected_failures == result->total_part_count())
+      << "Logged " << result->total_part_count() << " failures "
+      << " vs. " << expected_failures << " expected";
+}
+
+// Tests using SCOPED_TRACE() and Google Test assertions in many threads
+// concurrently.
+TEST(StressTest, CanUseScopedTraceAndAssertionsInManyThreads) {
+  {
+    scoped_ptr<ThreadWithParam<int> > threads[kThreadCount];
+    Notification threads_can_start;
+    for (int i = 0; i != kThreadCount; i++)
+      threads[i].reset(new ThreadWithParam<int>(&ManyAsserts,
+                                                i,
+                                                &threads_can_start));
+
+    threads_can_start.Notify();
+
+    // Blocks until all the threads are done.
+    for (int i = 0; i != kThreadCount; i++)
+      threads[i]->Join();
+  }
+
+  // Ensures that kThreadCount*kThreadCount failures have been reported.
+  const TestInfo* const info = UnitTest::GetInstance()->current_test_info();
+  const TestResult* const result = info->result();
+
+  std::vector<TestProperty> properties;
+  // We have no access to the TestResult's list of properties but we can
+  // copy them one by one.
+  for (int i = 0; i < result->test_property_count(); ++i)
+    properties.push_back(result->GetTestProperty(i));
+
+  EXPECT_EQ(kThreadCount * 2 + 1, result->test_property_count())
+      << "String and int values recorded on each thread, "
+      << "as well as one shared_key";
+  for (int i = 0; i < kThreadCount; ++i) {
+    ExpectKeyAndValueWereRecordedForId(properties, i, "string");
+    ExpectKeyAndValueWereRecordedForId(properties, i, "int");
+  }
+  CheckTestFailureCount(kThreadCount*kThreadCount);
+}
+
+void FailingThread(bool is_fatal) {
+  if (is_fatal)
+    FAIL() << "Fatal failure in some other thread. "
+           << "(This failure is expected.)";
+  else
+    ADD_FAILURE() << "Non-fatal failure in some other thread. "
+                  << "(This failure is expected.)";
+}
+
+void GenerateFatalFailureInAnotherThread(bool is_fatal) {
+  ThreadWithParam<bool> thread(&FailingThread, is_fatal, NULL);
+  thread.Join();
+}
+
+TEST(NoFatalFailureTest, ExpectNoFatalFailureIgnoresFailuresInOtherThreads) {
+  EXPECT_NO_FATAL_FAILURE(GenerateFatalFailureInAnotherThread(true));
+  // We should only have one failure (the one from
+  // GenerateFatalFailureInAnotherThread()), since the EXPECT_NO_FATAL_FAILURE
+  // should succeed.
+  CheckTestFailureCount(1);
+}
+
+void AssertNoFatalFailureIgnoresFailuresInOtherThreads() {
+  ASSERT_NO_FATAL_FAILURE(GenerateFatalFailureInAnotherThread(true));
+}
+TEST(NoFatalFailureTest, AssertNoFatalFailureIgnoresFailuresInOtherThreads) {
+  // Using a subroutine, to make sure, that the test continues.
+  AssertNoFatalFailureIgnoresFailuresInOtherThreads();
+  // We should only have one failure (the one from
+  // GenerateFatalFailureInAnotherThread()), since the EXPECT_NO_FATAL_FAILURE
+  // should succeed.
+  CheckTestFailureCount(1);
+}
+
+TEST(FatalFailureTest, ExpectFatalFailureIgnoresFailuresInOtherThreads) {
+  // This statement should fail, since the current thread doesn't generate a
+  // fatal failure, only another one does.
+  EXPECT_FATAL_FAILURE(GenerateFatalFailureInAnotherThread(true), "expected");
+  CheckTestFailureCount(2);
+}
+
+TEST(FatalFailureOnAllThreadsTest, ExpectFatalFailureOnAllThreads) {
+  // This statement should succeed, because failures in all threads are
+  // considered.
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS(
+      GenerateFatalFailureInAnotherThread(true), "expected");
+  CheckTestFailureCount(0);
+  // We need to add a failure, because main() checks that there are failures.
+  // But when only this test is run, we shouldn't have any failures.
+  ADD_FAILURE() << "This is an expected non-fatal failure.";
+}
+
+TEST(NonFatalFailureTest, ExpectNonFatalFailureIgnoresFailuresInOtherThreads) {
+  // This statement should fail, since the current thread doesn't generate a
+  // fatal failure, only another one does.
+  EXPECT_NONFATAL_FAILURE(GenerateFatalFailureInAnotherThread(false),
+                          "expected");
+  CheckTestFailureCount(2);
+}
+
+TEST(NonFatalFailureOnAllThreadsTest, ExpectNonFatalFailureOnAllThreads) {
+  // This statement should succeed, because failures in all threads are
+  // considered.
+  EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(
+      GenerateFatalFailureInAnotherThread(false), "expected");
+  CheckTestFailureCount(0);
+  // We need to add a failure, because main() checks that there are failures,
+  // But when only this test is run, we shouldn't have any failures.
+  ADD_FAILURE() << "This is an expected non-fatal failure.";
+}
+
+}  // namespace
+}  // namespace testing
+
+int main(int argc, char **argv) {
+  testing::InitGoogleTest(&argc, argv);
+
+  const int result = RUN_ALL_TESTS();  // Expected to fail.
+  GTEST_CHECK_(result == 1) << "RUN_ALL_TESTS() did not fail as expected";
+
+  printf("\nPASS\n");
+  return 0;
+}
+
+#else
+TEST(StressTest,
+     DISABLED_ThreadSafetyTestsAreSkippedWhenGoogleTestIsNotThreadSafe) {
+}
+
+int main(int argc, char **argv) {
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
+#endif  // GTEST_IS_THREADSAFE
diff --git a/third_party/googletest/googletest/test/gtest_test_utils.py b/third_party/googletest/googletest/test/gtest_test_utils.py
new file mode 100755
index 0000000..7e3cbca
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_test_utils.py
@@ -0,0 +1,320 @@
+#!/usr/bin/env python
+#
+# Copyright 2006, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Unit test utilities for Google C++ Testing Framework."""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import atexit
+import os
+import shutil
+import sys
+import tempfile
+import unittest
+_test_module = unittest
+
+# Suppresses the 'Import not at the top of the file' lint complaint.
+# pylint: disable-msg=C6204
+try:
+  import subprocess
+  _SUBPROCESS_MODULE_AVAILABLE = True
+except:
+  import popen2
+  _SUBPROCESS_MODULE_AVAILABLE = False
+# pylint: enable-msg=C6204
+
+GTEST_OUTPUT_VAR_NAME = 'GTEST_OUTPUT'
+
+IS_WINDOWS = os.name == 'nt'
+IS_CYGWIN = os.name == 'posix' and 'CYGWIN' in os.uname()[0]
+
+# The environment variable for specifying the path to the premature-exit file.
+PREMATURE_EXIT_FILE_ENV_VAR = 'TEST_PREMATURE_EXIT_FILE'
+
+environ = os.environ.copy()
+
+
+def SetEnvVar(env_var, value):
+  """Sets/unsets an environment variable to a given value."""
+
+  if value is not None:
+    environ[env_var] = value
+  elif env_var in environ:
+    del environ[env_var]
+
+
+# Here we expose a class from a particular module, depending on the
+# environment. The comment suppresses the 'Invalid variable name' lint
+# complaint.
+TestCase = _test_module.TestCase  # pylint: disable-msg=C6409
+
+# Initially maps a flag to its default value. After
+# _ParseAndStripGTestFlags() is called, maps a flag to its actual value.
+_flag_map = {'source_dir': os.path.dirname(sys.argv[0]),
+             'build_dir': os.path.dirname(sys.argv[0])}
+_gtest_flags_are_parsed = False
+
+
+def _ParseAndStripGTestFlags(argv):
+  """Parses and strips Google Test flags from argv.  This is idempotent."""
+
+  # Suppresses the lint complaint about a global variable since we need it
+  # here to maintain module-wide state.
+  global _gtest_flags_are_parsed  # pylint: disable-msg=W0603
+  if _gtest_flags_are_parsed:
+    return
+
+  _gtest_flags_are_parsed = True
+  for flag in _flag_map:
+    # The environment variable overrides the default value.
+    if flag.upper() in os.environ:
+      _flag_map[flag] = os.environ[flag.upper()]
+
+    # The command line flag overrides the environment variable.
+    i = 1  # Skips the program name.
+    while i < len(argv):
+      prefix = '--' + flag + '='
+      if argv[i].startswith(prefix):
+        _flag_map[flag] = argv[i][len(prefix):]
+        del argv[i]
+        break
+      else:
+        # We don't increment i in case we just found a --gtest_* flag
+        # and removed it from argv.
+        i += 1
+
+
+def GetFlag(flag):
+  """Returns the value of the given flag."""
+
+  # In case GetFlag() is called before Main(), we always call
+  # _ParseAndStripGTestFlags() here to make sure the --gtest_* flags
+  # are parsed.
+  _ParseAndStripGTestFlags(sys.argv)
+
+  return _flag_map[flag]
+
+
+def GetSourceDir():
+  """Returns the absolute path of the directory where the .py files are."""
+
+  return os.path.abspath(GetFlag('source_dir'))
+
+
+def GetBuildDir():
+  """Returns the absolute path of the directory where the test binaries are."""
+
+  return os.path.abspath(GetFlag('build_dir'))
+
+
+_temp_dir = None
+
+def _RemoveTempDir():
+  if _temp_dir:
+    shutil.rmtree(_temp_dir, ignore_errors=True)
+
+atexit.register(_RemoveTempDir)
+
+
+def GetTempDir():
+  """Returns a directory for temporary files."""
+
+  global _temp_dir
+  if not _temp_dir:
+    _temp_dir = tempfile.mkdtemp()
+  return _temp_dir
+
+
+def GetTestExecutablePath(executable_name, build_dir=None):
+  """Returns the absolute path of the test binary given its name.
+
+  The function will print a message and abort the program if the resulting file
+  doesn't exist.
+
+  Args:
+    executable_name: name of the test binary that the test script runs.
+    build_dir:       directory where to look for executables, by default
+                     the result of GetBuildDir().
+
+  Returns:
+    The absolute path of the test binary.
+  """
+
+  path = os.path.abspath(os.path.join(build_dir or GetBuildDir(),
+                                      executable_name))
+  if (IS_WINDOWS or IS_CYGWIN) and not path.endswith('.exe'):
+    path += '.exe'
+
+  if not os.path.exists(path):
+    message = (
+        'Unable to find the test binary "%s". Please make sure to provide\n'
+        'a path to the binary via the --build_dir flag or the BUILD_DIR\n'
+        'environment variable.' % path)
+    print >> sys.stderr, message
+    sys.exit(1)
+
+  return path
+
+
+def GetExitStatus(exit_code):
+  """Returns the argument to exit(), or -1 if exit() wasn't called.
+
+  Args:
+    exit_code: the result value of os.system(command).
+  """
+
+  if os.name == 'nt':
+    # On Windows, os.WEXITSTATUS() doesn't work and os.system() returns
+    # the argument to exit() directly.
+    return exit_code
+  else:
+    # On Unix, os.WEXITSTATUS() must be used to extract the exit status
+    # from the result of os.system().
+    if os.WIFEXITED(exit_code):
+      return os.WEXITSTATUS(exit_code)
+    else:
+      return -1
+
+
+class Subprocess:
+  def __init__(self, command, working_dir=None, capture_stderr=True, env=None):
+    """Changes into a specified directory, if provided, and executes a command.
+
+    Restores the old directory afterwards.
+
+    Args:
+      command:        The command to run, in the form of sys.argv.
+      working_dir:    The directory to change into.
+      capture_stderr: Determines whether to capture stderr in the output member
+                      or to discard it.
+      env:            Dictionary with environment to pass to the subprocess.
+
+    Returns:
+      An object that represents outcome of the executed process. It has the
+      following attributes:
+        terminated_by_signal   True iff the child process has been terminated
+                               by a signal.
+        signal                 Sygnal that terminated the child process.
+        exited                 True iff the child process exited normally.
+        exit_code              The code with which the child process exited.
+        output                 Child process's stdout and stderr output
+                               combined in a string.
+    """
+
+    # The subprocess module is the preferrable way of running programs
+    # since it is available and behaves consistently on all platforms,
+    # including Windows. But it is only available starting in python 2.4.
+    # In earlier python versions, we revert to the popen2 module, which is
+    # available in python 2.0 and later but doesn't provide required
+    # functionality (Popen4) under Windows. This allows us to support Mac
+    # OS X 10.4 Tiger, which has python 2.3 installed.
+    if _SUBPROCESS_MODULE_AVAILABLE:
+      if capture_stderr:
+        stderr = subprocess.STDOUT
+      else:
+        stderr = subprocess.PIPE
+
+      p = subprocess.Popen(command,
+                           stdout=subprocess.PIPE, stderr=stderr,
+                           cwd=working_dir, universal_newlines=True, env=env)
+      # communicate returns a tuple with the file obect for the child's
+      # output.
+      self.output = p.communicate()[0]
+      self._return_code = p.returncode
+    else:
+      old_dir = os.getcwd()
+
+      def _ReplaceEnvDict(dest, src):
+        # Changes made by os.environ.clear are not inheritable by child
+        # processes until Python 2.6. To produce inheritable changes we have
+        # to delete environment items with the del statement.
+        for key in dest.keys():
+          del dest[key]
+        dest.update(src)
+
+      # When 'env' is not None, backup the environment variables and replace
+      # them with the passed 'env'. When 'env' is None, we simply use the
+      # current 'os.environ' for compatibility with the subprocess.Popen
+      # semantics used above.
+      if env is not None:
+        old_environ = os.environ.copy()
+        _ReplaceEnvDict(os.environ, env)
+
+      try:
+        if working_dir is not None:
+          os.chdir(working_dir)
+        if capture_stderr:
+          p = popen2.Popen4(command)
+        else:
+          p = popen2.Popen3(command)
+        p.tochild.close()
+        self.output = p.fromchild.read()
+        ret_code = p.wait()
+      finally:
+        os.chdir(old_dir)
+
+        # Restore the old environment variables
+        # if they were replaced.
+        if env is not None:
+          _ReplaceEnvDict(os.environ, old_environ)
+
+      # Converts ret_code to match the semantics of
+      # subprocess.Popen.returncode.
+      if os.WIFSIGNALED(ret_code):
+        self._return_code = -os.WTERMSIG(ret_code)
+      else:  # os.WIFEXITED(ret_code) should return True here.
+        self._return_code = os.WEXITSTATUS(ret_code)
+
+    if self._return_code < 0:
+      self.terminated_by_signal = True
+      self.exited = False
+      self.signal = -self._return_code
+    else:
+      self.terminated_by_signal = False
+      self.exited = True
+      self.exit_code = self._return_code
+
+
+def Main():
+  """Runs the unit test."""
+
+  # We must call _ParseAndStripGTestFlags() before calling
+  # unittest.main().  Otherwise the latter will be confused by the
+  # --gtest_* flags.
+  _ParseAndStripGTestFlags(sys.argv)
+  # The tested binaries should not be writing XML output files unless the
+  # script explicitly instructs them to.
+  # TODO(vladl@google.com): Move this into Subprocess when we implement
+  # passing environment into it as a parameter.
+  if GTEST_OUTPUT_VAR_NAME in os.environ:
+    del os.environ[GTEST_OUTPUT_VAR_NAME]
+
+  _test_module.main()
diff --git a/third_party/googletest/googletest/test/gtest_throw_on_failure_ex_test.cc b/third_party/googletest/googletest/test/gtest_throw_on_failure_ex_test.cc
new file mode 100644
index 0000000..8d46c76
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_throw_on_failure_ex_test.cc
@@ -0,0 +1,92 @@
+// Copyright 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Tests Google Test's throw-on-failure mode with exceptions enabled.
+
+#include "gtest/gtest.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdexcept>
+
+// Prints the given failure message and exits the program with
+// non-zero.  We use this instead of a Google Test assertion to
+// indicate a failure, as the latter is been tested and cannot be
+// relied on.
+void Fail(const char* msg) {
+  printf("FAILURE: %s\n", msg);
+  fflush(stdout);
+  exit(1);
+}
+
+// Tests that an assertion failure throws a subclass of
+// std::runtime_error.
+void TestFailureThrowsRuntimeError() {
+  testing::GTEST_FLAG(throw_on_failure) = true;
+
+  // A successful assertion shouldn't throw.
+  try {
+    EXPECT_EQ(3, 3);
+  } catch(...) {
+    Fail("A successful assertion wrongfully threw.");
+  }
+
+  // A failed assertion should throw a subclass of std::runtime_error.
+  try {
+    EXPECT_EQ(2, 3) << "Expected failure";
+  } catch(const std::runtime_error& e) {
+    if (strstr(e.what(), "Expected failure") != NULL)
+      return;
+
+    printf("%s",
+           "A failed assertion did throw an exception of the right type, "
+           "but the message is incorrect.  Instead of containing \"Expected "
+           "failure\", it is:\n");
+    Fail(e.what());
+  } catch(...) {
+    Fail("A failed assertion threw the wrong type of exception.");
+  }
+  Fail("A failed assertion should've thrown but didn't.");
+}
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+
+  // We want to ensure that people can use Google Test assertions in
+  // other testing frameworks, as long as they initialize Google Test
+  // properly and set the thrown-on-failure mode.  Therefore, we don't
+  // use Google Test's constructs for defining and running tests
+  // (e.g. TEST and RUN_ALL_TESTS) here.
+
+  TestFailureThrowsRuntimeError();
+  return 0;
+}
diff --git a/third_party/googletest/googletest/test/gtest_throw_on_failure_test.py b/third_party/googletest/googletest/test/gtest_throw_on_failure_test.py
new file mode 100755
index 0000000..5678ffe
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_throw_on_failure_test.py
@@ -0,0 +1,171 @@
+#!/usr/bin/env python
+#
+# Copyright 2009, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Tests Google Test's throw-on-failure mode with exceptions disabled.
+
+This script invokes gtest_throw_on_failure_test_ (a program written with
+Google Test) with different environments and command line flags.
+"""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import os
+import gtest_test_utils
+
+
+# Constants.
+
+# The command line flag for enabling/disabling the throw-on-failure mode.
+THROW_ON_FAILURE = 'gtest_throw_on_failure'
+
+# Path to the gtest_throw_on_failure_test_ program, compiled with
+# exceptions disabled.
+EXE_PATH = gtest_test_utils.GetTestExecutablePath(
+    'gtest_throw_on_failure_test_')
+
+
+# Utilities.
+
+
+def SetEnvVar(env_var, value):
+  """Sets an environment variable to a given value; unsets it when the
+  given value is None.
+  """
+
+  env_var = env_var.upper()
+  if value is not None:
+    os.environ[env_var] = value
+  elif env_var in os.environ:
+    del os.environ[env_var]
+
+
+def Run(command):
+  """Runs a command; returns True/False if its exit code is/isn't 0."""
+
+  print 'Running "%s". . .' % ' '.join(command)
+  p = gtest_test_utils.Subprocess(command)
+  return p.exited and p.exit_code == 0
+
+
+# The tests.  TODO(wan@google.com): refactor the class to share common
+# logic with code in gtest_break_on_failure_unittest.py.
+class ThrowOnFailureTest(gtest_test_utils.TestCase):
+  """Tests the throw-on-failure mode."""
+
+  def RunAndVerify(self, env_var_value, flag_value, should_fail):
+    """Runs gtest_throw_on_failure_test_ and verifies that it does
+    (or does not) exit with a non-zero code.
+
+    Args:
+      env_var_value:    value of the GTEST_BREAK_ON_FAILURE environment
+                        variable; None if the variable should be unset.
+      flag_value:       value of the --gtest_break_on_failure flag;
+                        None if the flag should not be present.
+      should_fail:      True iff the program is expected to fail.
+    """
+
+    SetEnvVar(THROW_ON_FAILURE, env_var_value)
+
+    if env_var_value is None:
+      env_var_value_msg = ' is not set'
+    else:
+      env_var_value_msg = '=' + env_var_value
+
+    if flag_value is None:
+      flag = ''
+    elif flag_value == '0':
+      flag = '--%s=0' % THROW_ON_FAILURE
+    else:
+      flag = '--%s' % THROW_ON_FAILURE
+
+    command = [EXE_PATH]
+    if flag:
+      command.append(flag)
+
+    if should_fail:
+      should_or_not = 'should'
+    else:
+      should_or_not = 'should not'
+
+    failed = not Run(command)
+
+    SetEnvVar(THROW_ON_FAILURE, None)
+
+    msg = ('when %s%s, an assertion failure in "%s" %s cause a non-zero '
+           'exit code.' %
+           (THROW_ON_FAILURE, env_var_value_msg, ' '.join(command),
+            should_or_not))
+    self.assert_(failed == should_fail, msg)
+
+  def testDefaultBehavior(self):
+    """Tests the behavior of the default mode."""
+
+    self.RunAndVerify(env_var_value=None, flag_value=None, should_fail=False)
+
+  def testThrowOnFailureEnvVar(self):
+    """Tests using the GTEST_THROW_ON_FAILURE environment variable."""
+
+    self.RunAndVerify(env_var_value='0',
+                      flag_value=None,
+                      should_fail=False)
+    self.RunAndVerify(env_var_value='1',
+                      flag_value=None,
+                      should_fail=True)
+
+  def testThrowOnFailureFlag(self):
+    """Tests using the --gtest_throw_on_failure flag."""
+
+    self.RunAndVerify(env_var_value=None,
+                      flag_value='0',
+                      should_fail=False)
+    self.RunAndVerify(env_var_value=None,
+                      flag_value='1',
+                      should_fail=True)
+
+  def testThrowOnFailureFlagOverridesEnvVar(self):
+    """Tests that --gtest_throw_on_failure overrides GTEST_THROW_ON_FAILURE."""
+
+    self.RunAndVerify(env_var_value='0',
+                      flag_value='0',
+                      should_fail=False)
+    self.RunAndVerify(env_var_value='0',
+                      flag_value='1',
+                      should_fail=True)
+    self.RunAndVerify(env_var_value='1',
+                      flag_value='0',
+                      should_fail=False)
+    self.RunAndVerify(env_var_value='1',
+                      flag_value='1',
+                      should_fail=True)
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/third_party/googletest/googletest/test/gtest_throw_on_failure_test_.cc b/third_party/googletest/googletest/test/gtest_throw_on_failure_test_.cc
new file mode 100644
index 0000000..2b88fe3
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_throw_on_failure_test_.cc
@@ -0,0 +1,72 @@
+// Copyright 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Tests Google Test's throw-on-failure mode with exceptions disabled.
+//
+// This program must be compiled with exceptions disabled.  It will be
+// invoked by gtest_throw_on_failure_test.py, and is expected to exit
+// with non-zero in the throw-on-failure mode or 0 otherwise.
+
+#include "gtest/gtest.h"
+
+#include <stdio.h>                      // for fflush, fprintf, NULL, etc.
+#include <stdlib.h>                     // for exit
+#include <exception>                    // for set_terminate
+
+// This terminate handler aborts the program using exit() rather than abort().
+// This avoids showing pop-ups on Windows systems and core dumps on Unix-like
+// ones.
+void TerminateHandler() {
+  fprintf(stderr, "%s\n", "Unhandled C++ exception terminating the program.");
+  fflush(NULL);
+  exit(1);
+}
+
+int main(int argc, char** argv) {
+#if GTEST_HAS_EXCEPTIONS
+  std::set_terminate(&TerminateHandler);
+#endif
+  testing::InitGoogleTest(&argc, argv);
+
+  // We want to ensure that people can use Google Test assertions in
+  // other testing frameworks, as long as they initialize Google Test
+  // properly and set the throw-on-failure mode.  Therefore, we don't
+  // use Google Test's constructs for defining and running tests
+  // (e.g. TEST and RUN_ALL_TESTS) here.
+
+  // In the throw-on-failure mode with exceptions disabled, this
+  // assertion will cause the program to exit with a non-zero code.
+  EXPECT_EQ(2, 3);
+
+  // When not in the throw-on-failure mode, the control will reach
+  // here.
+  return 0;
+}
diff --git a/third_party/googletest/googletest/test/gtest_uninitialized_test.py b/third_party/googletest/googletest/test/gtest_uninitialized_test.py
new file mode 100755
index 0000000..6ae57ee
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_uninitialized_test.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+#
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Verifies that Google Test warns the user when not initialized properly."""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import gtest_test_utils
+
+
+COMMAND = gtest_test_utils.GetTestExecutablePath('gtest_uninitialized_test_')
+
+
+def Assert(condition):
+  if not condition:
+    raise AssertionError
+
+
+def AssertEq(expected, actual):
+  if expected != actual:
+    print 'Expected: %s' % (expected,)
+    print '  Actual: %s' % (actual,)
+    raise AssertionError
+
+
+def TestExitCodeAndOutput(command):
+  """Runs the given command and verifies its exit code and output."""
+
+  # Verifies that 'command' exits with code 1.
+  p = gtest_test_utils.Subprocess(command)
+  Assert(p.exited)
+  AssertEq(1, p.exit_code)
+  Assert('InitGoogleTest' in p.output)
+
+
+class GTestUninitializedTest(gtest_test_utils.TestCase):
+  def testExitCodeAndOutput(self):
+    TestExitCodeAndOutput(COMMAND)
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/third_party/googletest/googletest/test/gtest_uninitialized_test_.cc b/third_party/googletest/googletest/test/gtest_uninitialized_test_.cc
new file mode 100644
index 0000000..4431698
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_uninitialized_test_.cc
@@ -0,0 +1,43 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include "gtest/gtest.h"
+
+TEST(DummyTest, Dummy) {
+  // This test doesn't verify anything.  We just need it to create a
+  // realistic stage for testing the behavior of Google Test when
+  // RUN_ALL_TESTS() is called without testing::InitGoogleTest() being
+  // called first.
+}
+
+int main() {
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/googletest/googletest/test/gtest_unittest.cc b/third_party/googletest/googletest/test/gtest_unittest.cc
new file mode 100644
index 0000000..60aed35
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_unittest.cc
@@ -0,0 +1,7699 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// Tests for Google Test itself.  This verifies that the basic constructs of
+// Google Test work.
+
+#include "gtest/gtest.h"
+
+// Verifies that the command line flag variables can be accessed
+// in code once <gtest/gtest.h> has been #included.
+// Do not move it after other #includes.
+TEST(CommandLineFlagsTest, CanBeAccessedInCodeOnceGTestHIsIncluded) {
+  bool dummy = testing::GTEST_FLAG(also_run_disabled_tests)
+      || testing::GTEST_FLAG(break_on_failure)
+      || testing::GTEST_FLAG(catch_exceptions)
+      || testing::GTEST_FLAG(color) != "unknown"
+      || testing::GTEST_FLAG(filter) != "unknown"
+      || testing::GTEST_FLAG(list_tests)
+      || testing::GTEST_FLAG(output) != "unknown"
+      || testing::GTEST_FLAG(print_time)
+      || testing::GTEST_FLAG(random_seed)
+      || testing::GTEST_FLAG(repeat) > 0
+      || testing::GTEST_FLAG(show_internal_stack_frames)
+      || testing::GTEST_FLAG(shuffle)
+      || testing::GTEST_FLAG(stack_trace_depth) > 0
+      || testing::GTEST_FLAG(stream_result_to) != "unknown"
+      || testing::GTEST_FLAG(throw_on_failure);
+  EXPECT_TRUE(dummy || !dummy);  // Suppresses warning that dummy is unused.
+}
+
+#include <limits.h>  // For INT_MAX.
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <map>
+#include <vector>
+#include <ostream>
+
+#include "gtest/gtest-spi.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+namespace internal {
+
+#if GTEST_CAN_STREAM_RESULTS_
+
+class StreamingListenerTest : public Test {
+ public:
+  class FakeSocketWriter : public StreamingListener::AbstractSocketWriter {
+   public:
+    // Sends a string to the socket.
+    virtual void Send(const string& message) { output_ += message; }
+
+    string output_;
+  };
+
+  StreamingListenerTest()
+      : fake_sock_writer_(new FakeSocketWriter),
+        streamer_(fake_sock_writer_),
+        test_info_obj_("FooTest", "Bar", NULL, NULL,
+                       CodeLocation(__FILE__, __LINE__), 0, NULL) {}
+
+ protected:
+  string* output() { return &(fake_sock_writer_->output_); }
+
+  FakeSocketWriter* const fake_sock_writer_;
+  StreamingListener streamer_;
+  UnitTest unit_test_;
+  TestInfo test_info_obj_;  // The name test_info_ was taken by testing::Test.
+};
+
+TEST_F(StreamingListenerTest, OnTestProgramEnd) {
+  *output() = "";
+  streamer_.OnTestProgramEnd(unit_test_);
+  EXPECT_EQ("event=TestProgramEnd&passed=1\n", *output());
+}
+
+TEST_F(StreamingListenerTest, OnTestIterationEnd) {
+  *output() = "";
+  streamer_.OnTestIterationEnd(unit_test_, 42);
+  EXPECT_EQ("event=TestIterationEnd&passed=1&elapsed_time=0ms\n", *output());
+}
+
+TEST_F(StreamingListenerTest, OnTestCaseStart) {
+  *output() = "";
+  streamer_.OnTestCaseStart(TestCase("FooTest", "Bar", NULL, NULL));
+  EXPECT_EQ("event=TestCaseStart&name=FooTest\n", *output());
+}
+
+TEST_F(StreamingListenerTest, OnTestCaseEnd) {
+  *output() = "";
+  streamer_.OnTestCaseEnd(TestCase("FooTest", "Bar", NULL, NULL));
+  EXPECT_EQ("event=TestCaseEnd&passed=1&elapsed_time=0ms\n", *output());
+}
+
+TEST_F(StreamingListenerTest, OnTestStart) {
+  *output() = "";
+  streamer_.OnTestStart(test_info_obj_);
+  EXPECT_EQ("event=TestStart&name=Bar\n", *output());
+}
+
+TEST_F(StreamingListenerTest, OnTestEnd) {
+  *output() = "";
+  streamer_.OnTestEnd(test_info_obj_);
+  EXPECT_EQ("event=TestEnd&passed=1&elapsed_time=0ms\n", *output());
+}
+
+TEST_F(StreamingListenerTest, OnTestPartResult) {
+  *output() = "";
+  streamer_.OnTestPartResult(TestPartResult(
+      TestPartResult::kFatalFailure, "foo.cc", 42, "failed=\n&%"));
+
+  // Meta characters in the failure message should be properly escaped.
+  EXPECT_EQ(
+      "event=TestPartResult&file=foo.cc&line=42&message=failed%3D%0A%26%25\n",
+      *output());
+}
+
+#endif  // GTEST_CAN_STREAM_RESULTS_
+
+// Provides access to otherwise private parts of the TestEventListeners class
+// that are needed to test it.
+class TestEventListenersAccessor {
+ public:
+  static TestEventListener* GetRepeater(TestEventListeners* listeners) {
+    return listeners->repeater();
+  }
+
+  static void SetDefaultResultPrinter(TestEventListeners* listeners,
+                                      TestEventListener* listener) {
+    listeners->SetDefaultResultPrinter(listener);
+  }
+  static void SetDefaultXmlGenerator(TestEventListeners* listeners,
+                                     TestEventListener* listener) {
+    listeners->SetDefaultXmlGenerator(listener);
+  }
+
+  static bool EventForwardingEnabled(const TestEventListeners& listeners) {
+    return listeners.EventForwardingEnabled();
+  }
+
+  static void SuppressEventForwarding(TestEventListeners* listeners) {
+    listeners->SuppressEventForwarding();
+  }
+};
+
+class UnitTestRecordPropertyTestHelper : public Test {
+ protected:
+  UnitTestRecordPropertyTestHelper() {}
+
+  // Forwards to UnitTest::RecordProperty() to bypass access controls.
+  void UnitTestRecordProperty(const char* key, const std::string& value) {
+    unit_test_.RecordProperty(key, value);
+  }
+
+  UnitTest unit_test_;
+};
+
+}  // namespace internal
+}  // namespace testing
+
+using testing::AssertionFailure;
+using testing::AssertionResult;
+using testing::AssertionSuccess;
+using testing::DoubleLE;
+using testing::EmptyTestEventListener;
+using testing::Environment;
+using testing::FloatLE;
+using testing::GTEST_FLAG(also_run_disabled_tests);
+using testing::GTEST_FLAG(break_on_failure);
+using testing::GTEST_FLAG(catch_exceptions);
+using testing::GTEST_FLAG(color);
+using testing::GTEST_FLAG(death_test_use_fork);
+using testing::GTEST_FLAG(filter);
+using testing::GTEST_FLAG(list_tests);
+using testing::GTEST_FLAG(output);
+using testing::GTEST_FLAG(print_time);
+using testing::GTEST_FLAG(random_seed);
+using testing::GTEST_FLAG(repeat);
+using testing::GTEST_FLAG(show_internal_stack_frames);
+using testing::GTEST_FLAG(shuffle);
+using testing::GTEST_FLAG(stack_trace_depth);
+using testing::GTEST_FLAG(stream_result_to);
+using testing::GTEST_FLAG(throw_on_failure);
+using testing::IsNotSubstring;
+using testing::IsSubstring;
+using testing::Message;
+using testing::ScopedFakeTestPartResultReporter;
+using testing::StaticAssertTypeEq;
+using testing::Test;
+using testing::TestCase;
+using testing::TestEventListeners;
+using testing::TestInfo;
+using testing::TestPartResult;
+using testing::TestPartResultArray;
+using testing::TestProperty;
+using testing::TestResult;
+using testing::TimeInMillis;
+using testing::UnitTest;
+using testing::internal::AddReference;
+using testing::internal::AlwaysFalse;
+using testing::internal::AlwaysTrue;
+using testing::internal::AppendUserMessage;
+using testing::internal::ArrayAwareFind;
+using testing::internal::ArrayEq;
+using testing::internal::CodePointToUtf8;
+using testing::internal::CompileAssertTypesEqual;
+using testing::internal::CopyArray;
+using testing::internal::CountIf;
+using testing::internal::EqFailure;
+using testing::internal::FloatingPoint;
+using testing::internal::ForEach;
+using testing::internal::FormatEpochTimeInMillisAsIso8601;
+using testing::internal::FormatTimeInMillisAsSeconds;
+using testing::internal::GTestFlagSaver;
+using testing::internal::GetCurrentOsStackTraceExceptTop;
+using testing::internal::GetElementOr;
+using testing::internal::GetNextRandomSeed;
+using testing::internal::GetRandomSeedFromFlag;
+using testing::internal::GetTestTypeId;
+using testing::internal::GetTimeInMillis;
+using testing::internal::GetTypeId;
+using testing::internal::GetUnitTestImpl;
+using testing::internal::ImplicitlyConvertible;
+using testing::internal::Int32;
+using testing::internal::Int32FromEnvOrDie;
+using testing::internal::IsAProtocolMessage;
+using testing::internal::IsContainer;
+using testing::internal::IsContainerTest;
+using testing::internal::IsNotContainer;
+using testing::internal::NativeArray;
+using testing::internal::ParseInt32Flag;
+using testing::internal::RelationToSourceCopy;
+using testing::internal::RelationToSourceReference;
+using testing::internal::RemoveConst;
+using testing::internal::RemoveReference;
+using testing::internal::ShouldRunTestOnShard;
+using testing::internal::ShouldShard;
+using testing::internal::ShouldUseColor;
+using testing::internal::Shuffle;
+using testing::internal::ShuffleRange;
+using testing::internal::SkipPrefix;
+using testing::internal::StreamableToString;
+using testing::internal::String;
+using testing::internal::TestEventListenersAccessor;
+using testing::internal::TestResultAccessor;
+using testing::internal::UInt32;
+using testing::internal::WideStringToUtf8;
+using testing::internal::edit_distance::CalculateOptimalEdits;
+using testing::internal::edit_distance::CreateUnifiedDiff;
+using testing::internal::edit_distance::EditType;
+using testing::internal::kMaxRandomSeed;
+using testing::internal::kTestTypeIdInGoogleTest;
+using testing::kMaxStackTraceDepth;
+
+#if GTEST_HAS_STREAM_REDIRECTION
+using testing::internal::CaptureStdout;
+using testing::internal::GetCapturedStdout;
+#endif
+
+#if GTEST_IS_THREADSAFE
+using testing::internal::ThreadWithParam;
+#endif
+
+class TestingVector : public std::vector<int> {
+};
+
+::std::ostream& operator<<(::std::ostream& os,
+                           const TestingVector& vector) {
+  os << "{ ";
+  for (size_t i = 0; i < vector.size(); i++) {
+    os << vector[i] << " ";
+  }
+  os << "}";
+  return os;
+}
+
+// This line tests that we can define tests in an unnamed namespace.
+namespace {
+
+TEST(GetRandomSeedFromFlagTest, HandlesZero) {
+  const int seed = GetRandomSeedFromFlag(0);
+  EXPECT_LE(1, seed);
+  EXPECT_LE(seed, static_cast<int>(kMaxRandomSeed));
+}
+
+TEST(GetRandomSeedFromFlagTest, PreservesValidSeed) {
+  EXPECT_EQ(1, GetRandomSeedFromFlag(1));
+  EXPECT_EQ(2, GetRandomSeedFromFlag(2));
+  EXPECT_EQ(kMaxRandomSeed - 1, GetRandomSeedFromFlag(kMaxRandomSeed - 1));
+  EXPECT_EQ(static_cast<int>(kMaxRandomSeed),
+            GetRandomSeedFromFlag(kMaxRandomSeed));
+}
+
+TEST(GetRandomSeedFromFlagTest, NormalizesInvalidSeed) {
+  const int seed1 = GetRandomSeedFromFlag(-1);
+  EXPECT_LE(1, seed1);
+  EXPECT_LE(seed1, static_cast<int>(kMaxRandomSeed));
+
+  const int seed2 = GetRandomSeedFromFlag(kMaxRandomSeed + 1);
+  EXPECT_LE(1, seed2);
+  EXPECT_LE(seed2, static_cast<int>(kMaxRandomSeed));
+}
+
+TEST(GetNextRandomSeedTest, WorksForValidInput) {
+  EXPECT_EQ(2, GetNextRandomSeed(1));
+  EXPECT_EQ(3, GetNextRandomSeed(2));
+  EXPECT_EQ(static_cast<int>(kMaxRandomSeed),
+            GetNextRandomSeed(kMaxRandomSeed - 1));
+  EXPECT_EQ(1, GetNextRandomSeed(kMaxRandomSeed));
+
+  // We deliberately don't test GetNextRandomSeed() with invalid
+  // inputs, as that requires death tests, which are expensive.  This
+  // is fine as GetNextRandomSeed() is internal and has a
+  // straightforward definition.
+}
+
+static void ClearCurrentTestPartResults() {
+  TestResultAccessor::ClearTestPartResults(
+      GetUnitTestImpl()->current_test_result());
+}
+
+// Tests GetTypeId.
+
+TEST(GetTypeIdTest, ReturnsSameValueForSameType) {
+  EXPECT_EQ(GetTypeId<int>(), GetTypeId<int>());
+  EXPECT_EQ(GetTypeId<Test>(), GetTypeId<Test>());
+}
+
+class SubClassOfTest : public Test {};
+class AnotherSubClassOfTest : public Test {};
+
+TEST(GetTypeIdTest, ReturnsDifferentValuesForDifferentTypes) {
+  EXPECT_NE(GetTypeId<int>(), GetTypeId<const int>());
+  EXPECT_NE(GetTypeId<int>(), GetTypeId<char>());
+  EXPECT_NE(GetTypeId<int>(), GetTestTypeId());
+  EXPECT_NE(GetTypeId<SubClassOfTest>(), GetTestTypeId());
+  EXPECT_NE(GetTypeId<AnotherSubClassOfTest>(), GetTestTypeId());
+  EXPECT_NE(GetTypeId<AnotherSubClassOfTest>(), GetTypeId<SubClassOfTest>());
+}
+
+// Verifies that GetTestTypeId() returns the same value, no matter it
+// is called from inside Google Test or outside of it.
+TEST(GetTestTypeIdTest, ReturnsTheSameValueInsideOrOutsideOfGoogleTest) {
+  EXPECT_EQ(kTestTypeIdInGoogleTest, GetTestTypeId());
+}
+
+// Tests FormatTimeInMillisAsSeconds().
+
+TEST(FormatTimeInMillisAsSecondsTest, FormatsZero) {
+  EXPECT_EQ("0", FormatTimeInMillisAsSeconds(0));
+}
+
+TEST(FormatTimeInMillisAsSecondsTest, FormatsPositiveNumber) {
+  EXPECT_EQ("0.003", FormatTimeInMillisAsSeconds(3));
+  EXPECT_EQ("0.01", FormatTimeInMillisAsSeconds(10));
+  EXPECT_EQ("0.2", FormatTimeInMillisAsSeconds(200));
+  EXPECT_EQ("1.2", FormatTimeInMillisAsSeconds(1200));
+  EXPECT_EQ("3", FormatTimeInMillisAsSeconds(3000));
+}
+
+TEST(FormatTimeInMillisAsSecondsTest, FormatsNegativeNumber) {
+  EXPECT_EQ("-0.003", FormatTimeInMillisAsSeconds(-3));
+  EXPECT_EQ("-0.01", FormatTimeInMillisAsSeconds(-10));
+  EXPECT_EQ("-0.2", FormatTimeInMillisAsSeconds(-200));
+  EXPECT_EQ("-1.2", FormatTimeInMillisAsSeconds(-1200));
+  EXPECT_EQ("-3", FormatTimeInMillisAsSeconds(-3000));
+}
+
+// Tests FormatEpochTimeInMillisAsIso8601().  The correctness of conversion
+// for particular dates below was verified in Python using
+// datetime.datetime.fromutctimestamp(<timetamp>/1000).
+
+// FormatEpochTimeInMillisAsIso8601 depends on the current timezone, so we
+// have to set up a particular timezone to obtain predictable results.
+class FormatEpochTimeInMillisAsIso8601Test : public Test {
+ public:
+  // On Cygwin, GCC doesn't allow unqualified integer literals to exceed
+  // 32 bits, even when 64-bit integer types are available.  We have to
+  // force the constants to have a 64-bit type here.
+  static const TimeInMillis kMillisPerSec = 1000;
+
+ private:
+  virtual void SetUp() {
+    saved_tz_ = NULL;
+
+    GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996 /* getenv, strdup: deprecated */)
+    if (getenv("TZ"))
+      saved_tz_ = strdup(getenv("TZ"));
+    GTEST_DISABLE_MSC_WARNINGS_POP_()
+
+    // Set up the time zone for FormatEpochTimeInMillisAsIso8601 to use.  We
+    // cannot use the local time zone because the function's output depends
+    // on the time zone.
+    SetTimeZone("UTC+00");
+  }
+
+  virtual void TearDown() {
+    SetTimeZone(saved_tz_);
+    free(const_cast<char*>(saved_tz_));
+    saved_tz_ = NULL;
+  }
+
+  static void SetTimeZone(const char* time_zone) {
+    // tzset() distinguishes between the TZ variable being present and empty
+    // and not being present, so we have to consider the case of time_zone
+    // being NULL.
+#if _MSC_VER
+    // ...Unless it's MSVC, whose standard library's _putenv doesn't
+    // distinguish between an empty and a missing variable.
+    const std::string env_var =
+        std::string("TZ=") + (time_zone ? time_zone : "");
+    _putenv(env_var.c_str());
+    GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996 /* deprecated function */)
+    tzset();
+    GTEST_DISABLE_MSC_WARNINGS_POP_()
+#else
+    if (time_zone) {
+      setenv(("TZ"), time_zone, 1);
+    } else {
+      unsetenv("TZ");
+    }
+    tzset();
+#endif
+  }
+
+  const char* saved_tz_;
+};
+
+const TimeInMillis FormatEpochTimeInMillisAsIso8601Test::kMillisPerSec;
+
+TEST_F(FormatEpochTimeInMillisAsIso8601Test, PrintsTwoDigitSegments) {
+  EXPECT_EQ("2011-10-31T18:52:42",
+            FormatEpochTimeInMillisAsIso8601(1320087162 * kMillisPerSec));
+}
+
+TEST_F(FormatEpochTimeInMillisAsIso8601Test, MillisecondsDoNotAffectResult) {
+  EXPECT_EQ(
+      "2011-10-31T18:52:42",
+      FormatEpochTimeInMillisAsIso8601(1320087162 * kMillisPerSec + 234));
+}
+
+TEST_F(FormatEpochTimeInMillisAsIso8601Test, PrintsLeadingZeroes) {
+  EXPECT_EQ("2011-09-03T05:07:02",
+            FormatEpochTimeInMillisAsIso8601(1315026422 * kMillisPerSec));
+}
+
+TEST_F(FormatEpochTimeInMillisAsIso8601Test, Prints24HourTime) {
+  EXPECT_EQ("2011-09-28T17:08:22",
+            FormatEpochTimeInMillisAsIso8601(1317229702 * kMillisPerSec));
+}
+
+TEST_F(FormatEpochTimeInMillisAsIso8601Test, PrintsEpochStart) {
+  EXPECT_EQ("1970-01-01T00:00:00", FormatEpochTimeInMillisAsIso8601(0));
+}
+
+#if GTEST_CAN_COMPARE_NULL
+
+# ifdef __BORLANDC__
+// Silences warnings: "Condition is always true", "Unreachable code"
+#  pragma option push -w-ccc -w-rch
+# endif
+
+// Tests that GTEST_IS_NULL_LITERAL_(x) is true when x is a null
+// pointer literal.
+TEST(NullLiteralTest, IsTrueForNullLiterals) {
+  EXPECT_TRUE(GTEST_IS_NULL_LITERAL_(NULL));
+  EXPECT_TRUE(GTEST_IS_NULL_LITERAL_(0));
+  EXPECT_TRUE(GTEST_IS_NULL_LITERAL_(0U));
+  EXPECT_TRUE(GTEST_IS_NULL_LITERAL_(0L));
+}
+
+// Tests that GTEST_IS_NULL_LITERAL_(x) is false when x is not a null
+// pointer literal.
+TEST(NullLiteralTest, IsFalseForNonNullLiterals) {
+  EXPECT_FALSE(GTEST_IS_NULL_LITERAL_(1));
+  EXPECT_FALSE(GTEST_IS_NULL_LITERAL_(0.0));
+  EXPECT_FALSE(GTEST_IS_NULL_LITERAL_('a'));
+  EXPECT_FALSE(GTEST_IS_NULL_LITERAL_(static_cast<void*>(NULL)));
+}
+
+# ifdef __BORLANDC__
+// Restores warnings after previous "#pragma option push" suppressed them.
+#  pragma option pop
+# endif
+
+#endif  // GTEST_CAN_COMPARE_NULL
+//
+// Tests CodePointToUtf8().
+
+// Tests that the NUL character L'\0' is encoded correctly.
+TEST(CodePointToUtf8Test, CanEncodeNul) {
+  EXPECT_EQ("", CodePointToUtf8(L'\0'));
+}
+
+// Tests that ASCII characters are encoded correctly.
+TEST(CodePointToUtf8Test, CanEncodeAscii) {
+  EXPECT_EQ("a", CodePointToUtf8(L'a'));
+  EXPECT_EQ("Z", CodePointToUtf8(L'Z'));
+  EXPECT_EQ("&", CodePointToUtf8(L'&'));
+  EXPECT_EQ("\x7F", CodePointToUtf8(L'\x7F'));
+}
+
+// Tests that Unicode code-points that have 8 to 11 bits are encoded
+// as 110xxxxx 10xxxxxx.
+TEST(CodePointToUtf8Test, CanEncode8To11Bits) {
+  // 000 1101 0011 => 110-00011 10-010011
+  EXPECT_EQ("\xC3\x93", CodePointToUtf8(L'\xD3'));
+
+  // 101 0111 0110 => 110-10101 10-110110
+  // Some compilers (e.g., GCC on MinGW) cannot handle non-ASCII codepoints
+  // in wide strings and wide chars. In order to accomodate them, we have to
+  // introduce such character constants as integers.
+  EXPECT_EQ("\xD5\xB6",
+            CodePointToUtf8(static_cast<wchar_t>(0x576)));
+}
+
+// Tests that Unicode code-points that have 12 to 16 bits are encoded
+// as 1110xxxx 10xxxxxx 10xxxxxx.
+TEST(CodePointToUtf8Test, CanEncode12To16Bits) {
+  // 0000 1000 1101 0011 => 1110-0000 10-100011 10-010011
+  EXPECT_EQ("\xE0\xA3\x93",
+            CodePointToUtf8(static_cast<wchar_t>(0x8D3)));
+
+  // 1100 0111 0100 1101 => 1110-1100 10-011101 10-001101
+  EXPECT_EQ("\xEC\x9D\x8D",
+            CodePointToUtf8(static_cast<wchar_t>(0xC74D)));
+}
+
+#if !GTEST_WIDE_STRING_USES_UTF16_
+// Tests in this group require a wchar_t to hold > 16 bits, and thus
+// are skipped on Windows, Cygwin, and Symbian, where a wchar_t is
+// 16-bit wide. This code may not compile on those systems.
+
+// Tests that Unicode code-points that have 17 to 21 bits are encoded
+// as 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx.
+TEST(CodePointToUtf8Test, CanEncode17To21Bits) {
+  // 0 0001 0000 1000 1101 0011 => 11110-000 10-010000 10-100011 10-010011
+  EXPECT_EQ("\xF0\x90\xA3\x93", CodePointToUtf8(L'\x108D3'));
+
+  // 0 0001 0000 0100 0000 0000 => 11110-000 10-010000 10-010000 10-000000
+  EXPECT_EQ("\xF0\x90\x90\x80", CodePointToUtf8(L'\x10400'));
+
+  // 1 0000 1000 0110 0011 0100 => 11110-100 10-001000 10-011000 10-110100
+  EXPECT_EQ("\xF4\x88\x98\xB4", CodePointToUtf8(L'\x108634'));
+}
+
+// Tests that encoding an invalid code-point generates the expected result.
+TEST(CodePointToUtf8Test, CanEncodeInvalidCodePoint) {
+  EXPECT_EQ("(Invalid Unicode 0x1234ABCD)", CodePointToUtf8(L'\x1234ABCD'));
+}
+
+#endif  // !GTEST_WIDE_STRING_USES_UTF16_
+
+// Tests WideStringToUtf8().
+
+// Tests that the NUL character L'\0' is encoded correctly.
+TEST(WideStringToUtf8Test, CanEncodeNul) {
+  EXPECT_STREQ("", WideStringToUtf8(L"", 0).c_str());
+  EXPECT_STREQ("", WideStringToUtf8(L"", -1).c_str());
+}
+
+// Tests that ASCII strings are encoded correctly.
+TEST(WideStringToUtf8Test, CanEncodeAscii) {
+  EXPECT_STREQ("a", WideStringToUtf8(L"a", 1).c_str());
+  EXPECT_STREQ("ab", WideStringToUtf8(L"ab", 2).c_str());
+  EXPECT_STREQ("a", WideStringToUtf8(L"a", -1).c_str());
+  EXPECT_STREQ("ab", WideStringToUtf8(L"ab", -1).c_str());
+}
+
+// Tests that Unicode code-points that have 8 to 11 bits are encoded
+// as 110xxxxx 10xxxxxx.
+TEST(WideStringToUtf8Test, CanEncode8To11Bits) {
+  // 000 1101 0011 => 110-00011 10-010011
+  EXPECT_STREQ("\xC3\x93", WideStringToUtf8(L"\xD3", 1).c_str());
+  EXPECT_STREQ("\xC3\x93", WideStringToUtf8(L"\xD3", -1).c_str());
+
+  // 101 0111 0110 => 110-10101 10-110110
+  const wchar_t s[] = { 0x576, '\0' };
+  EXPECT_STREQ("\xD5\xB6", WideStringToUtf8(s, 1).c_str());
+  EXPECT_STREQ("\xD5\xB6", WideStringToUtf8(s, -1).c_str());
+}
+
+// Tests that Unicode code-points that have 12 to 16 bits are encoded
+// as 1110xxxx 10xxxxxx 10xxxxxx.
+TEST(WideStringToUtf8Test, CanEncode12To16Bits) {
+  // 0000 1000 1101 0011 => 1110-0000 10-100011 10-010011
+  const wchar_t s1[] = { 0x8D3, '\0' };
+  EXPECT_STREQ("\xE0\xA3\x93", WideStringToUtf8(s1, 1).c_str());
+  EXPECT_STREQ("\xE0\xA3\x93", WideStringToUtf8(s1, -1).c_str());
+
+  // 1100 0111 0100 1101 => 1110-1100 10-011101 10-001101
+  const wchar_t s2[] = { 0xC74D, '\0' };
+  EXPECT_STREQ("\xEC\x9D\x8D", WideStringToUtf8(s2, 1).c_str());
+  EXPECT_STREQ("\xEC\x9D\x8D", WideStringToUtf8(s2, -1).c_str());
+}
+
+// Tests that the conversion stops when the function encounters \0 character.
+TEST(WideStringToUtf8Test, StopsOnNulCharacter) {
+  EXPECT_STREQ("ABC", WideStringToUtf8(L"ABC\0XYZ", 100).c_str());
+}
+
+// Tests that the conversion stops when the function reaches the limit
+// specified by the 'length' parameter.
+TEST(WideStringToUtf8Test, StopsWhenLengthLimitReached) {
+  EXPECT_STREQ("ABC", WideStringToUtf8(L"ABCDEF", 3).c_str());
+}
+
+#if !GTEST_WIDE_STRING_USES_UTF16_
+// Tests that Unicode code-points that have 17 to 21 bits are encoded
+// as 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx. This code may not compile
+// on the systems using UTF-16 encoding.
+TEST(WideStringToUtf8Test, CanEncode17To21Bits) {
+  // 0 0001 0000 1000 1101 0011 => 11110-000 10-010000 10-100011 10-010011
+  EXPECT_STREQ("\xF0\x90\xA3\x93", WideStringToUtf8(L"\x108D3", 1).c_str());
+  EXPECT_STREQ("\xF0\x90\xA3\x93", WideStringToUtf8(L"\x108D3", -1).c_str());
+
+  // 1 0000 1000 0110 0011 0100 => 11110-100 10-001000 10-011000 10-110100
+  EXPECT_STREQ("\xF4\x88\x98\xB4", WideStringToUtf8(L"\x108634", 1).c_str());
+  EXPECT_STREQ("\xF4\x88\x98\xB4", WideStringToUtf8(L"\x108634", -1).c_str());
+}
+
+// Tests that encoding an invalid code-point generates the expected result.
+TEST(WideStringToUtf8Test, CanEncodeInvalidCodePoint) {
+  EXPECT_STREQ("(Invalid Unicode 0xABCDFF)",
+               WideStringToUtf8(L"\xABCDFF", -1).c_str());
+}
+#else  // !GTEST_WIDE_STRING_USES_UTF16_
+// Tests that surrogate pairs are encoded correctly on the systems using
+// UTF-16 encoding in the wide strings.
+TEST(WideStringToUtf8Test, CanEncodeValidUtf16SUrrogatePairs) {
+  const wchar_t s[] = { 0xD801, 0xDC00, '\0' };
+  EXPECT_STREQ("\xF0\x90\x90\x80", WideStringToUtf8(s, -1).c_str());
+}
+
+// Tests that encoding an invalid UTF-16 surrogate pair
+// generates the expected result.
+TEST(WideStringToUtf8Test, CanEncodeInvalidUtf16SurrogatePair) {
+  // Leading surrogate is at the end of the string.
+  const wchar_t s1[] = { 0xD800, '\0' };
+  EXPECT_STREQ("\xED\xA0\x80", WideStringToUtf8(s1, -1).c_str());
+  // Leading surrogate is not followed by the trailing surrogate.
+  const wchar_t s2[] = { 0xD800, 'M', '\0' };
+  EXPECT_STREQ("\xED\xA0\x80M", WideStringToUtf8(s2, -1).c_str());
+  // Trailing surrogate appearas without a leading surrogate.
+  const wchar_t s3[] = { 0xDC00, 'P', 'Q', 'R', '\0' };
+  EXPECT_STREQ("\xED\xB0\x80PQR", WideStringToUtf8(s3, -1).c_str());
+}
+#endif  // !GTEST_WIDE_STRING_USES_UTF16_
+
+// Tests that codepoint concatenation works correctly.
+#if !GTEST_WIDE_STRING_USES_UTF16_
+TEST(WideStringToUtf8Test, ConcatenatesCodepointsCorrectly) {
+  const wchar_t s[] = { 0x108634, 0xC74D, '\n', 0x576, 0x8D3, 0x108634, '\0'};
+  EXPECT_STREQ(
+      "\xF4\x88\x98\xB4"
+          "\xEC\x9D\x8D"
+          "\n"
+          "\xD5\xB6"
+          "\xE0\xA3\x93"
+          "\xF4\x88\x98\xB4",
+      WideStringToUtf8(s, -1).c_str());
+}
+#else
+TEST(WideStringToUtf8Test, ConcatenatesCodepointsCorrectly) {
+  const wchar_t s[] = { 0xC74D, '\n', 0x576, 0x8D3, '\0'};
+  EXPECT_STREQ(
+      "\xEC\x9D\x8D" "\n" "\xD5\xB6" "\xE0\xA3\x93",
+      WideStringToUtf8(s, -1).c_str());
+}
+#endif  // !GTEST_WIDE_STRING_USES_UTF16_
+
+// Tests the Random class.
+
+TEST(RandomDeathTest, GeneratesCrashesOnInvalidRange) {
+  testing::internal::Random random(42);
+  EXPECT_DEATH_IF_SUPPORTED(
+      random.Generate(0),
+      "Cannot generate a number in the range \\[0, 0\\)");
+  EXPECT_DEATH_IF_SUPPORTED(
+      random.Generate(testing::internal::Random::kMaxRange + 1),
+      "Generation of a number in \\[0, 2147483649\\) was requested, "
+      "but this can only generate numbers in \\[0, 2147483648\\)");
+}
+
+TEST(RandomTest, GeneratesNumbersWithinRange) {
+  const UInt32 kRange = 10000;
+  testing::internal::Random random(12345);
+  for (int i = 0; i < 10; i++) {
+    EXPECT_LT(random.Generate(kRange), kRange) << " for iteration " << i;
+  }
+
+  testing::internal::Random random2(testing::internal::Random::kMaxRange);
+  for (int i = 0; i < 10; i++) {
+    EXPECT_LT(random2.Generate(kRange), kRange) << " for iteration " << i;
+  }
+}
+
+TEST(RandomTest, RepeatsWhenReseeded) {
+  const int kSeed = 123;
+  const int kArraySize = 10;
+  const UInt32 kRange = 10000;
+  UInt32 values[kArraySize];
+
+  testing::internal::Random random(kSeed);
+  for (int i = 0; i < kArraySize; i++) {
+    values[i] = random.Generate(kRange);
+  }
+
+  random.Reseed(kSeed);
+  for (int i = 0; i < kArraySize; i++) {
+    EXPECT_EQ(values[i], random.Generate(kRange)) << " for iteration " << i;
+  }
+}
+
+// Tests STL container utilities.
+
+// Tests CountIf().
+
+static bool IsPositive(int n) { return n > 0; }
+
+TEST(ContainerUtilityTest, CountIf) {
+  std::vector<int> v;
+  EXPECT_EQ(0, CountIf(v, IsPositive));  // Works for an empty container.
+
+  v.push_back(-1);
+  v.push_back(0);
+  EXPECT_EQ(0, CountIf(v, IsPositive));  // Works when no value satisfies.
+
+  v.push_back(2);
+  v.push_back(-10);
+  v.push_back(10);
+  EXPECT_EQ(2, CountIf(v, IsPositive));
+}
+
+// Tests ForEach().
+
+static int g_sum = 0;
+static void Accumulate(int n) { g_sum += n; }
+
+TEST(ContainerUtilityTest, ForEach) {
+  std::vector<int> v;
+  g_sum = 0;
+  ForEach(v, Accumulate);
+  EXPECT_EQ(0, g_sum);  // Works for an empty container;
+
+  g_sum = 0;
+  v.push_back(1);
+  ForEach(v, Accumulate);
+  EXPECT_EQ(1, g_sum);  // Works for a container with one element.
+
+  g_sum = 0;
+  v.push_back(20);
+  v.push_back(300);
+  ForEach(v, Accumulate);
+  EXPECT_EQ(321, g_sum);
+}
+
+// Tests GetElementOr().
+TEST(ContainerUtilityTest, GetElementOr) {
+  std::vector<char> a;
+  EXPECT_EQ('x', GetElementOr(a, 0, 'x'));
+
+  a.push_back('a');
+  a.push_back('b');
+  EXPECT_EQ('a', GetElementOr(a, 0, 'x'));
+  EXPECT_EQ('b', GetElementOr(a, 1, 'x'));
+  EXPECT_EQ('x', GetElementOr(a, -2, 'x'));
+  EXPECT_EQ('x', GetElementOr(a, 2, 'x'));
+}
+
+TEST(ContainerUtilityDeathTest, ShuffleRange) {
+  std::vector<int> a;
+  a.push_back(0);
+  a.push_back(1);
+  a.push_back(2);
+  testing::internal::Random random(1);
+
+  EXPECT_DEATH_IF_SUPPORTED(
+      ShuffleRange(&random, -1, 1, &a),
+      "Invalid shuffle range start -1: must be in range \\[0, 3\\]");
+  EXPECT_DEATH_IF_SUPPORTED(
+      ShuffleRange(&random, 4, 4, &a),
+      "Invalid shuffle range start 4: must be in range \\[0, 3\\]");
+  EXPECT_DEATH_IF_SUPPORTED(
+      ShuffleRange(&random, 3, 2, &a),
+      "Invalid shuffle range finish 2: must be in range \\[3, 3\\]");
+  EXPECT_DEATH_IF_SUPPORTED(
+      ShuffleRange(&random, 3, 4, &a),
+      "Invalid shuffle range finish 4: must be in range \\[3, 3\\]");
+}
+
+class VectorShuffleTest : public Test {
+ protected:
+  static const int kVectorSize = 20;
+
+  VectorShuffleTest() : random_(1) {
+    for (int i = 0; i < kVectorSize; i++) {
+      vector_.push_back(i);
+    }
+  }
+
+  static bool VectorIsCorrupt(const TestingVector& vector) {
+    if (kVectorSize != static_cast<int>(vector.size())) {
+      return true;
+    }
+
+    bool found_in_vector[kVectorSize] = { false };
+    for (size_t i = 0; i < vector.size(); i++) {
+      const int e = vector[i];
+      if (e < 0 || e >= kVectorSize || found_in_vector[e]) {
+        return true;
+      }
+      found_in_vector[e] = true;
+    }
+
+    // Vector size is correct, elements' range is correct, no
+    // duplicate elements.  Therefore no corruption has occurred.
+    return false;
+  }
+
+  static bool VectorIsNotCorrupt(const TestingVector& vector) {
+    return !VectorIsCorrupt(vector);
+  }
+
+  static bool RangeIsShuffled(const TestingVector& vector, int begin, int end) {
+    for (int i = begin; i < end; i++) {
+      if (i != vector[i]) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  static bool RangeIsUnshuffled(
+      const TestingVector& vector, int begin, int end) {
+    return !RangeIsShuffled(vector, begin, end);
+  }
+
+  static bool VectorIsShuffled(const TestingVector& vector) {
+    return RangeIsShuffled(vector, 0, static_cast<int>(vector.size()));
+  }
+
+  static bool VectorIsUnshuffled(const TestingVector& vector) {
+    return !VectorIsShuffled(vector);
+  }
+
+  testing::internal::Random random_;
+  TestingVector vector_;
+};  // class VectorShuffleTest
+
+const int VectorShuffleTest::kVectorSize;
+
+TEST_F(VectorShuffleTest, HandlesEmptyRange) {
+  // Tests an empty range at the beginning...
+  ShuffleRange(&random_, 0, 0, &vector_);
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  ASSERT_PRED1(VectorIsUnshuffled, vector_);
+
+  // ...in the middle...
+  ShuffleRange(&random_, kVectorSize/2, kVectorSize/2, &vector_);
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  ASSERT_PRED1(VectorIsUnshuffled, vector_);
+
+  // ...at the end...
+  ShuffleRange(&random_, kVectorSize - 1, kVectorSize - 1, &vector_);
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  ASSERT_PRED1(VectorIsUnshuffled, vector_);
+
+  // ...and past the end.
+  ShuffleRange(&random_, kVectorSize, kVectorSize, &vector_);
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  ASSERT_PRED1(VectorIsUnshuffled, vector_);
+}
+
+TEST_F(VectorShuffleTest, HandlesRangeOfSizeOne) {
+  // Tests a size one range at the beginning...
+  ShuffleRange(&random_, 0, 1, &vector_);
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  ASSERT_PRED1(VectorIsUnshuffled, vector_);
+
+  // ...in the middle...
+  ShuffleRange(&random_, kVectorSize/2, kVectorSize/2 + 1, &vector_);
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  ASSERT_PRED1(VectorIsUnshuffled, vector_);
+
+  // ...and at the end.
+  ShuffleRange(&random_, kVectorSize - 1, kVectorSize, &vector_);
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  ASSERT_PRED1(VectorIsUnshuffled, vector_);
+}
+
+// Because we use our own random number generator and a fixed seed,
+// we can guarantee that the following "random" tests will succeed.
+
+TEST_F(VectorShuffleTest, ShufflesEntireVector) {
+  Shuffle(&random_, &vector_);
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  EXPECT_FALSE(VectorIsUnshuffled(vector_)) << vector_;
+
+  // Tests the first and last elements in particular to ensure that
+  // there are no off-by-one problems in our shuffle algorithm.
+  EXPECT_NE(0, vector_[0]);
+  EXPECT_NE(kVectorSize - 1, vector_[kVectorSize - 1]);
+}
+
+TEST_F(VectorShuffleTest, ShufflesStartOfVector) {
+  const int kRangeSize = kVectorSize/2;
+
+  ShuffleRange(&random_, 0, kRangeSize, &vector_);
+
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  EXPECT_PRED3(RangeIsShuffled, vector_, 0, kRangeSize);
+  EXPECT_PRED3(RangeIsUnshuffled, vector_, kRangeSize, kVectorSize);
+}
+
+TEST_F(VectorShuffleTest, ShufflesEndOfVector) {
+  const int kRangeSize = kVectorSize / 2;
+  ShuffleRange(&random_, kRangeSize, kVectorSize, &vector_);
+
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  EXPECT_PRED3(RangeIsUnshuffled, vector_, 0, kRangeSize);
+  EXPECT_PRED3(RangeIsShuffled, vector_, kRangeSize, kVectorSize);
+}
+
+TEST_F(VectorShuffleTest, ShufflesMiddleOfVector) {
+  int kRangeSize = kVectorSize/3;
+  ShuffleRange(&random_, kRangeSize, 2*kRangeSize, &vector_);
+
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  EXPECT_PRED3(RangeIsUnshuffled, vector_, 0, kRangeSize);
+  EXPECT_PRED3(RangeIsShuffled, vector_, kRangeSize, 2*kRangeSize);
+  EXPECT_PRED3(RangeIsUnshuffled, vector_, 2*kRangeSize, kVectorSize);
+}
+
+TEST_F(VectorShuffleTest, ShufflesRepeatably) {
+  TestingVector vector2;
+  for (int i = 0; i < kVectorSize; i++) {
+    vector2.push_back(i);
+  }
+
+  random_.Reseed(1234);
+  Shuffle(&random_, &vector_);
+  random_.Reseed(1234);
+  Shuffle(&random_, &vector2);
+
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  ASSERT_PRED1(VectorIsNotCorrupt, vector2);
+
+  for (int i = 0; i < kVectorSize; i++) {
+    EXPECT_EQ(vector_[i], vector2[i]) << " where i is " << i;
+  }
+}
+
+// Tests the size of the AssertHelper class.
+
+TEST(AssertHelperTest, AssertHelperIsSmall) {
+  // To avoid breaking clients that use lots of assertions in one
+  // function, we cannot grow the size of AssertHelper.
+  EXPECT_LE(sizeof(testing::internal::AssertHelper), sizeof(void*));
+}
+
+// Tests String::EndsWithCaseInsensitive().
+TEST(StringTest, EndsWithCaseInsensitive) {
+  EXPECT_TRUE(String::EndsWithCaseInsensitive("foobar", "BAR"));
+  EXPECT_TRUE(String::EndsWithCaseInsensitive("foobaR", "bar"));
+  EXPECT_TRUE(String::EndsWithCaseInsensitive("foobar", ""));
+  EXPECT_TRUE(String::EndsWithCaseInsensitive("", ""));
+
+  EXPECT_FALSE(String::EndsWithCaseInsensitive("Foobar", "foo"));
+  EXPECT_FALSE(String::EndsWithCaseInsensitive("foobar", "Foo"));
+  EXPECT_FALSE(String::EndsWithCaseInsensitive("", "foo"));
+}
+
+// C++Builder's preprocessor is buggy; it fails to expand macros that
+// appear in macro parameters after wide char literals.  Provide an alias
+// for NULL as a workaround.
+static const wchar_t* const kNull = NULL;
+
+// Tests String::CaseInsensitiveWideCStringEquals
+TEST(StringTest, CaseInsensitiveWideCStringEquals) {
+  EXPECT_TRUE(String::CaseInsensitiveWideCStringEquals(NULL, NULL));
+  EXPECT_FALSE(String::CaseInsensitiveWideCStringEquals(kNull, L""));
+  EXPECT_FALSE(String::CaseInsensitiveWideCStringEquals(L"", kNull));
+  EXPECT_FALSE(String::CaseInsensitiveWideCStringEquals(kNull, L"foobar"));
+  EXPECT_FALSE(String::CaseInsensitiveWideCStringEquals(L"foobar", kNull));
+  EXPECT_TRUE(String::CaseInsensitiveWideCStringEquals(L"foobar", L"foobar"));
+  EXPECT_TRUE(String::CaseInsensitiveWideCStringEquals(L"foobar", L"FOOBAR"));
+  EXPECT_TRUE(String::CaseInsensitiveWideCStringEquals(L"FOOBAR", L"foobar"));
+}
+
+#if GTEST_OS_WINDOWS
+
+// Tests String::ShowWideCString().
+TEST(StringTest, ShowWideCString) {
+  EXPECT_STREQ("(null)",
+               String::ShowWideCString(NULL).c_str());
+  EXPECT_STREQ("", String::ShowWideCString(L"").c_str());
+  EXPECT_STREQ("foo", String::ShowWideCString(L"foo").c_str());
+}
+
+# if GTEST_OS_WINDOWS_MOBILE
+TEST(StringTest, AnsiAndUtf16Null) {
+  EXPECT_EQ(NULL, String::AnsiToUtf16(NULL));
+  EXPECT_EQ(NULL, String::Utf16ToAnsi(NULL));
+}
+
+TEST(StringTest, AnsiAndUtf16ConvertBasic) {
+  const char* ansi = String::Utf16ToAnsi(L"str");
+  EXPECT_STREQ("str", ansi);
+  delete [] ansi;
+  const WCHAR* utf16 = String::AnsiToUtf16("str");
+  EXPECT_EQ(0, wcsncmp(L"str", utf16, 3));
+  delete [] utf16;
+}
+
+TEST(StringTest, AnsiAndUtf16ConvertPathChars) {
+  const char* ansi = String::Utf16ToAnsi(L".:\\ \"*?");
+  EXPECT_STREQ(".:\\ \"*?", ansi);
+  delete [] ansi;
+  const WCHAR* utf16 = String::AnsiToUtf16(".:\\ \"*?");
+  EXPECT_EQ(0, wcsncmp(L".:\\ \"*?", utf16, 3));
+  delete [] utf16;
+}
+# endif  // GTEST_OS_WINDOWS_MOBILE
+
+#endif  // GTEST_OS_WINDOWS
+
+// Tests TestProperty construction.
+TEST(TestPropertyTest, StringValue) {
+  TestProperty property("key", "1");
+  EXPECT_STREQ("key", property.key());
+  EXPECT_STREQ("1", property.value());
+}
+
+// Tests TestProperty replacing a value.
+TEST(TestPropertyTest, ReplaceStringValue) {
+  TestProperty property("key", "1");
+  EXPECT_STREQ("1", property.value());
+  property.SetValue("2");
+  EXPECT_STREQ("2", property.value());
+}
+
+// AddFatalFailure() and AddNonfatalFailure() must be stand-alone
+// functions (i.e. their definitions cannot be inlined at the call
+// sites), or C++Builder won't compile the code.
+static void AddFatalFailure() {
+  FAIL() << "Expected fatal failure.";
+}
+
+static void AddNonfatalFailure() {
+  ADD_FAILURE() << "Expected non-fatal failure.";
+}
+
+class ScopedFakeTestPartResultReporterTest : public Test {
+ public:  // Must be public and not protected due to a bug in g++ 3.4.2.
+  enum FailureMode {
+    FATAL_FAILURE,
+    NONFATAL_FAILURE
+  };
+  static void AddFailure(FailureMode failure) {
+    if (failure == FATAL_FAILURE) {
+      AddFatalFailure();
+    } else {
+      AddNonfatalFailure();
+    }
+  }
+};
+
+// Tests that ScopedFakeTestPartResultReporter intercepts test
+// failures.
+TEST_F(ScopedFakeTestPartResultReporterTest, InterceptsTestFailures) {
+  TestPartResultArray results;
+  {
+    ScopedFakeTestPartResultReporter reporter(
+        ScopedFakeTestPartResultReporter::INTERCEPT_ONLY_CURRENT_THREAD,
+        &results);
+    AddFailure(NONFATAL_FAILURE);
+    AddFailure(FATAL_FAILURE);
+  }
+
+  EXPECT_EQ(2, results.size());
+  EXPECT_TRUE(results.GetTestPartResult(0).nonfatally_failed());
+  EXPECT_TRUE(results.GetTestPartResult(1).fatally_failed());
+}
+
+TEST_F(ScopedFakeTestPartResultReporterTest, DeprecatedConstructor) {
+  TestPartResultArray results;
+  {
+    // Tests, that the deprecated constructor still works.
+    ScopedFakeTestPartResultReporter reporter(&results);
+    AddFailure(NONFATAL_FAILURE);
+  }
+  EXPECT_EQ(1, results.size());
+}
+
+#if GTEST_IS_THREADSAFE
+
+class ScopedFakeTestPartResultReporterWithThreadsTest
+  : public ScopedFakeTestPartResultReporterTest {
+ protected:
+  static void AddFailureInOtherThread(FailureMode failure) {
+    ThreadWithParam<FailureMode> thread(&AddFailure, failure, NULL);
+    thread.Join();
+  }
+};
+
+TEST_F(ScopedFakeTestPartResultReporterWithThreadsTest,
+       InterceptsTestFailuresInAllThreads) {
+  TestPartResultArray results;
+  {
+    ScopedFakeTestPartResultReporter reporter(
+        ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, &results);
+    AddFailure(NONFATAL_FAILURE);
+    AddFailure(FATAL_FAILURE);
+    AddFailureInOtherThread(NONFATAL_FAILURE);
+    AddFailureInOtherThread(FATAL_FAILURE);
+  }
+
+  EXPECT_EQ(4, results.size());
+  EXPECT_TRUE(results.GetTestPartResult(0).nonfatally_failed());
+  EXPECT_TRUE(results.GetTestPartResult(1).fatally_failed());
+  EXPECT_TRUE(results.GetTestPartResult(2).nonfatally_failed());
+  EXPECT_TRUE(results.GetTestPartResult(3).fatally_failed());
+}
+
+#endif  // GTEST_IS_THREADSAFE
+
+// Tests EXPECT_FATAL_FAILURE{,ON_ALL_THREADS}.  Makes sure that they
+// work even if the failure is generated in a called function rather than
+// the current context.
+
+typedef ScopedFakeTestPartResultReporterTest ExpectFatalFailureTest;
+
+TEST_F(ExpectFatalFailureTest, CatchesFatalFaliure) {
+  EXPECT_FATAL_FAILURE(AddFatalFailure(), "Expected fatal failure.");
+}
+
+#if GTEST_HAS_GLOBAL_STRING
+TEST_F(ExpectFatalFailureTest, AcceptsStringObject) {
+  EXPECT_FATAL_FAILURE(AddFatalFailure(), ::string("Expected fatal failure."));
+}
+#endif
+
+TEST_F(ExpectFatalFailureTest, AcceptsStdStringObject) {
+  EXPECT_FATAL_FAILURE(AddFatalFailure(),
+                       ::std::string("Expected fatal failure."));
+}
+
+TEST_F(ExpectFatalFailureTest, CatchesFatalFailureOnAllThreads) {
+  // We have another test below to verify that the macro catches fatal
+  // failures generated on another thread.
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS(AddFatalFailure(),
+                                      "Expected fatal failure.");
+}
+
+#ifdef __BORLANDC__
+// Silences warnings: "Condition is always true"
+# pragma option push -w-ccc
+#endif
+
+// Tests that EXPECT_FATAL_FAILURE() can be used in a non-void
+// function even when the statement in it contains ASSERT_*.
+
+int NonVoidFunction() {
+  EXPECT_FATAL_FAILURE(ASSERT_TRUE(false), "");
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS(FAIL(), "");
+  return 0;
+}
+
+TEST_F(ExpectFatalFailureTest, CanBeUsedInNonVoidFunction) {
+  NonVoidFunction();
+}
+
+// Tests that EXPECT_FATAL_FAILURE(statement, ...) doesn't abort the
+// current function even though 'statement' generates a fatal failure.
+
+void DoesNotAbortHelper(bool* aborted) {
+  EXPECT_FATAL_FAILURE(ASSERT_TRUE(false), "");
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS(FAIL(), "");
+
+  *aborted = false;
+}
+
+#ifdef __BORLANDC__
+// Restores warnings after previous "#pragma option push" suppressed them.
+# pragma option pop
+#endif
+
+TEST_F(ExpectFatalFailureTest, DoesNotAbort) {
+  bool aborted = true;
+  DoesNotAbortHelper(&aborted);
+  EXPECT_FALSE(aborted);
+}
+
+// Tests that the EXPECT_FATAL_FAILURE{,_ON_ALL_THREADS} accepts a
+// statement that contains a macro which expands to code containing an
+// unprotected comma.
+
+static int global_var = 0;
+#define GTEST_USE_UNPROTECTED_COMMA_ global_var++, global_var++
+
+TEST_F(ExpectFatalFailureTest, AcceptsMacroThatExpandsToUnprotectedComma) {
+#ifndef __BORLANDC__
+  // ICE's in C++Builder.
+  EXPECT_FATAL_FAILURE({
+    GTEST_USE_UNPROTECTED_COMMA_;
+    AddFatalFailure();
+  }, "");
+#endif
+
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS({
+    GTEST_USE_UNPROTECTED_COMMA_;
+    AddFatalFailure();
+  }, "");
+}
+
+// Tests EXPECT_NONFATAL_FAILURE{,ON_ALL_THREADS}.
+
+typedef ScopedFakeTestPartResultReporterTest ExpectNonfatalFailureTest;
+
+TEST_F(ExpectNonfatalFailureTest, CatchesNonfatalFailure) {
+  EXPECT_NONFATAL_FAILURE(AddNonfatalFailure(),
+                          "Expected non-fatal failure.");
+}
+
+#if GTEST_HAS_GLOBAL_STRING
+TEST_F(ExpectNonfatalFailureTest, AcceptsStringObject) {
+  EXPECT_NONFATAL_FAILURE(AddNonfatalFailure(),
+                          ::string("Expected non-fatal failure."));
+}
+#endif
+
+TEST_F(ExpectNonfatalFailureTest, AcceptsStdStringObject) {
+  EXPECT_NONFATAL_FAILURE(AddNonfatalFailure(),
+                          ::std::string("Expected non-fatal failure."));
+}
+
+TEST_F(ExpectNonfatalFailureTest, CatchesNonfatalFailureOnAllThreads) {
+  // We have another test below to verify that the macro catches
+  // non-fatal failures generated on another thread.
+  EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(AddNonfatalFailure(),
+                                         "Expected non-fatal failure.");
+}
+
+// Tests that the EXPECT_NONFATAL_FAILURE{,_ON_ALL_THREADS} accepts a
+// statement that contains a macro which expands to code containing an
+// unprotected comma.
+TEST_F(ExpectNonfatalFailureTest, AcceptsMacroThatExpandsToUnprotectedComma) {
+  EXPECT_NONFATAL_FAILURE({
+    GTEST_USE_UNPROTECTED_COMMA_;
+    AddNonfatalFailure();
+  }, "");
+
+  EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS({
+    GTEST_USE_UNPROTECTED_COMMA_;
+    AddNonfatalFailure();
+  }, "");
+}
+
+#if GTEST_IS_THREADSAFE
+
+typedef ScopedFakeTestPartResultReporterWithThreadsTest
+    ExpectFailureWithThreadsTest;
+
+TEST_F(ExpectFailureWithThreadsTest, ExpectFatalFailureOnAllThreads) {
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS(AddFailureInOtherThread(FATAL_FAILURE),
+                                      "Expected fatal failure.");
+}
+
+TEST_F(ExpectFailureWithThreadsTest, ExpectNonFatalFailureOnAllThreads) {
+  EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(
+      AddFailureInOtherThread(NONFATAL_FAILURE), "Expected non-fatal failure.");
+}
+
+#endif  // GTEST_IS_THREADSAFE
+
+// Tests the TestProperty class.
+
+TEST(TestPropertyTest, ConstructorWorks) {
+  const TestProperty property("key", "value");
+  EXPECT_STREQ("key", property.key());
+  EXPECT_STREQ("value", property.value());
+}
+
+TEST(TestPropertyTest, SetValue) {
+  TestProperty property("key", "value_1");
+  EXPECT_STREQ("key", property.key());
+  property.SetValue("value_2");
+  EXPECT_STREQ("key", property.key());
+  EXPECT_STREQ("value_2", property.value());
+}
+
+// Tests the TestResult class
+
+// The test fixture for testing TestResult.
+class TestResultTest : public Test {
+ protected:
+  typedef std::vector<TestPartResult> TPRVector;
+
+  // We make use of 2 TestPartResult objects,
+  TestPartResult * pr1, * pr2;
+
+  // ... and 3 TestResult objects.
+  TestResult * r0, * r1, * r2;
+
+  virtual void SetUp() {
+    // pr1 is for success.
+    pr1 = new TestPartResult(TestPartResult::kSuccess,
+                             "foo/bar.cc",
+                             10,
+                             "Success!");
+
+    // pr2 is for fatal failure.
+    pr2 = new TestPartResult(TestPartResult::kFatalFailure,
+                             "foo/bar.cc",
+                             -1,  // This line number means "unknown"
+                             "Failure!");
+
+    // Creates the TestResult objects.
+    r0 = new TestResult();
+    r1 = new TestResult();
+    r2 = new TestResult();
+
+    // In order to test TestResult, we need to modify its internal
+    // state, in particular the TestPartResult vector it holds.
+    // test_part_results() returns a const reference to this vector.
+    // We cast it to a non-const object s.t. it can be modified (yes,
+    // this is a hack).
+    TPRVector* results1 = const_cast<TPRVector*>(
+        &TestResultAccessor::test_part_results(*r1));
+    TPRVector* results2 = const_cast<TPRVector*>(
+        &TestResultAccessor::test_part_results(*r2));
+
+    // r0 is an empty TestResult.
+
+    // r1 contains a single SUCCESS TestPartResult.
+    results1->push_back(*pr1);
+
+    // r2 contains a SUCCESS, and a FAILURE.
+    results2->push_back(*pr1);
+    results2->push_back(*pr2);
+  }
+
+  virtual void TearDown() {
+    delete pr1;
+    delete pr2;
+
+    delete r0;
+    delete r1;
+    delete r2;
+  }
+
+  // Helper that compares two two TestPartResults.
+  static void CompareTestPartResult(const TestPartResult& expected,
+                                    const TestPartResult& actual) {
+    EXPECT_EQ(expected.type(), actual.type());
+    EXPECT_STREQ(expected.file_name(), actual.file_name());
+    EXPECT_EQ(expected.line_number(), actual.line_number());
+    EXPECT_STREQ(expected.summary(), actual.summary());
+    EXPECT_STREQ(expected.message(), actual.message());
+    EXPECT_EQ(expected.passed(), actual.passed());
+    EXPECT_EQ(expected.failed(), actual.failed());
+    EXPECT_EQ(expected.nonfatally_failed(), actual.nonfatally_failed());
+    EXPECT_EQ(expected.fatally_failed(), actual.fatally_failed());
+  }
+};
+
+// Tests TestResult::total_part_count().
+TEST_F(TestResultTest, total_part_count) {
+  ASSERT_EQ(0, r0->total_part_count());
+  ASSERT_EQ(1, r1->total_part_count());
+  ASSERT_EQ(2, r2->total_part_count());
+}
+
+// Tests TestResult::Passed().
+TEST_F(TestResultTest, Passed) {
+  ASSERT_TRUE(r0->Passed());
+  ASSERT_TRUE(r1->Passed());
+  ASSERT_FALSE(r2->Passed());
+}
+
+// Tests TestResult::Failed().
+TEST_F(TestResultTest, Failed) {
+  ASSERT_FALSE(r0->Failed());
+  ASSERT_FALSE(r1->Failed());
+  ASSERT_TRUE(r2->Failed());
+}
+
+// Tests TestResult::GetTestPartResult().
+
+typedef TestResultTest TestResultDeathTest;
+
+TEST_F(TestResultDeathTest, GetTestPartResult) {
+  CompareTestPartResult(*pr1, r2->GetTestPartResult(0));
+  CompareTestPartResult(*pr2, r2->GetTestPartResult(1));
+  EXPECT_DEATH_IF_SUPPORTED(r2->GetTestPartResult(2), "");
+  EXPECT_DEATH_IF_SUPPORTED(r2->GetTestPartResult(-1), "");
+}
+
+// Tests TestResult has no properties when none are added.
+TEST(TestResultPropertyTest, NoPropertiesFoundWhenNoneAreAdded) {
+  TestResult test_result;
+  ASSERT_EQ(0, test_result.test_property_count());
+}
+
+// Tests TestResult has the expected property when added.
+TEST(TestResultPropertyTest, OnePropertyFoundWhenAdded) {
+  TestResult test_result;
+  TestProperty property("key_1", "1");
+  TestResultAccessor::RecordProperty(&test_result, "testcase", property);
+  ASSERT_EQ(1, test_result.test_property_count());
+  const TestProperty& actual_property = test_result.GetTestProperty(0);
+  EXPECT_STREQ("key_1", actual_property.key());
+  EXPECT_STREQ("1", actual_property.value());
+}
+
+// Tests TestResult has multiple properties when added.
+TEST(TestResultPropertyTest, MultiplePropertiesFoundWhenAdded) {
+  TestResult test_result;
+  TestProperty property_1("key_1", "1");
+  TestProperty property_2("key_2", "2");
+  TestResultAccessor::RecordProperty(&test_result, "testcase", property_1);
+  TestResultAccessor::RecordProperty(&test_result, "testcase", property_2);
+  ASSERT_EQ(2, test_result.test_property_count());
+  const TestProperty& actual_property_1 = test_result.GetTestProperty(0);
+  EXPECT_STREQ("key_1", actual_property_1.key());
+  EXPECT_STREQ("1", actual_property_1.value());
+
+  const TestProperty& actual_property_2 = test_result.GetTestProperty(1);
+  EXPECT_STREQ("key_2", actual_property_2.key());
+  EXPECT_STREQ("2", actual_property_2.value());
+}
+
+// Tests TestResult::RecordProperty() overrides values for duplicate keys.
+TEST(TestResultPropertyTest, OverridesValuesForDuplicateKeys) {
+  TestResult test_result;
+  TestProperty property_1_1("key_1", "1");
+  TestProperty property_2_1("key_2", "2");
+  TestProperty property_1_2("key_1", "12");
+  TestProperty property_2_2("key_2", "22");
+  TestResultAccessor::RecordProperty(&test_result, "testcase", property_1_1);
+  TestResultAccessor::RecordProperty(&test_result, "testcase", property_2_1);
+  TestResultAccessor::RecordProperty(&test_result, "testcase", property_1_2);
+  TestResultAccessor::RecordProperty(&test_result, "testcase", property_2_2);
+
+  ASSERT_EQ(2, test_result.test_property_count());
+  const TestProperty& actual_property_1 = test_result.GetTestProperty(0);
+  EXPECT_STREQ("key_1", actual_property_1.key());
+  EXPECT_STREQ("12", actual_property_1.value());
+
+  const TestProperty& actual_property_2 = test_result.GetTestProperty(1);
+  EXPECT_STREQ("key_2", actual_property_2.key());
+  EXPECT_STREQ("22", actual_property_2.value());
+}
+
+// Tests TestResult::GetTestProperty().
+TEST(TestResultPropertyTest, GetTestProperty) {
+  TestResult test_result;
+  TestProperty property_1("key_1", "1");
+  TestProperty property_2("key_2", "2");
+  TestProperty property_3("key_3", "3");
+  TestResultAccessor::RecordProperty(&test_result, "testcase", property_1);
+  TestResultAccessor::RecordProperty(&test_result, "testcase", property_2);
+  TestResultAccessor::RecordProperty(&test_result, "testcase", property_3);
+
+  const TestProperty& fetched_property_1 = test_result.GetTestProperty(0);
+  const TestProperty& fetched_property_2 = test_result.GetTestProperty(1);
+  const TestProperty& fetched_property_3 = test_result.GetTestProperty(2);
+
+  EXPECT_STREQ("key_1", fetched_property_1.key());
+  EXPECT_STREQ("1", fetched_property_1.value());
+
+  EXPECT_STREQ("key_2", fetched_property_2.key());
+  EXPECT_STREQ("2", fetched_property_2.value());
+
+  EXPECT_STREQ("key_3", fetched_property_3.key());
+  EXPECT_STREQ("3", fetched_property_3.value());
+
+  EXPECT_DEATH_IF_SUPPORTED(test_result.GetTestProperty(3), "");
+  EXPECT_DEATH_IF_SUPPORTED(test_result.GetTestProperty(-1), "");
+}
+
+// Tests the Test class.
+//
+// It's difficult to test every public method of this class (we are
+// already stretching the limit of Google Test by using it to test itself!).
+// Fortunately, we don't have to do that, as we are already testing
+// the functionalities of the Test class extensively by using Google Test
+// alone.
+//
+// Therefore, this section only contains one test.
+
+// Tests that GTestFlagSaver works on Windows and Mac.
+
+class GTestFlagSaverTest : public Test {
+ protected:
+  // Saves the Google Test flags such that we can restore them later, and
+  // then sets them to their default values.  This will be called
+  // before the first test in this test case is run.
+  static void SetUpTestCase() {
+    saver_ = new GTestFlagSaver;
+
+    GTEST_FLAG(also_run_disabled_tests) = false;
+    GTEST_FLAG(break_on_failure) = false;
+    GTEST_FLAG(catch_exceptions) = false;
+    GTEST_FLAG(death_test_use_fork) = false;
+    GTEST_FLAG(color) = "auto";
+    GTEST_FLAG(filter) = "";
+    GTEST_FLAG(list_tests) = false;
+    GTEST_FLAG(output) = "";
+    GTEST_FLAG(print_time) = true;
+    GTEST_FLAG(random_seed) = 0;
+    GTEST_FLAG(repeat) = 1;
+    GTEST_FLAG(shuffle) = false;
+    GTEST_FLAG(stack_trace_depth) = kMaxStackTraceDepth;
+    GTEST_FLAG(stream_result_to) = "";
+    GTEST_FLAG(throw_on_failure) = false;
+  }
+
+  // Restores the Google Test flags that the tests have modified.  This will
+  // be called after the last test in this test case is run.
+  static void TearDownTestCase() {
+    delete saver_;
+    saver_ = NULL;
+  }
+
+  // Verifies that the Google Test flags have their default values, and then
+  // modifies each of them.
+  void VerifyAndModifyFlags() {
+    EXPECT_FALSE(GTEST_FLAG(also_run_disabled_tests));
+    EXPECT_FALSE(GTEST_FLAG(break_on_failure));
+    EXPECT_FALSE(GTEST_FLAG(catch_exceptions));
+    EXPECT_STREQ("auto", GTEST_FLAG(color).c_str());
+    EXPECT_FALSE(GTEST_FLAG(death_test_use_fork));
+    EXPECT_STREQ("", GTEST_FLAG(filter).c_str());
+    EXPECT_FALSE(GTEST_FLAG(list_tests));
+    EXPECT_STREQ("", GTEST_FLAG(output).c_str());
+    EXPECT_TRUE(GTEST_FLAG(print_time));
+    EXPECT_EQ(0, GTEST_FLAG(random_seed));
+    EXPECT_EQ(1, GTEST_FLAG(repeat));
+    EXPECT_FALSE(GTEST_FLAG(shuffle));
+    EXPECT_EQ(kMaxStackTraceDepth, GTEST_FLAG(stack_trace_depth));
+    EXPECT_STREQ("", GTEST_FLAG(stream_result_to).c_str());
+    EXPECT_FALSE(GTEST_FLAG(throw_on_failure));
+
+    GTEST_FLAG(also_run_disabled_tests) = true;
+    GTEST_FLAG(break_on_failure) = true;
+    GTEST_FLAG(catch_exceptions) = true;
+    GTEST_FLAG(color) = "no";
+    GTEST_FLAG(death_test_use_fork) = true;
+    GTEST_FLAG(filter) = "abc";
+    GTEST_FLAG(list_tests) = true;
+    GTEST_FLAG(output) = "xml:foo.xml";
+    GTEST_FLAG(print_time) = false;
+    GTEST_FLAG(random_seed) = 1;
+    GTEST_FLAG(repeat) = 100;
+    GTEST_FLAG(shuffle) = true;
+    GTEST_FLAG(stack_trace_depth) = 1;
+    GTEST_FLAG(stream_result_to) = "localhost:1234";
+    GTEST_FLAG(throw_on_failure) = true;
+  }
+
+ private:
+  // For saving Google Test flags during this test case.
+  static GTestFlagSaver* saver_;
+};
+
+GTestFlagSaver* GTestFlagSaverTest::saver_ = NULL;
+
+// Google Test doesn't guarantee the order of tests.  The following two
+// tests are designed to work regardless of their order.
+
+// Modifies the Google Test flags in the test body.
+TEST_F(GTestFlagSaverTest, ModifyGTestFlags) {
+  VerifyAndModifyFlags();
+}
+
+// Verifies that the Google Test flags in the body of the previous test were
+// restored to their original values.
+TEST_F(GTestFlagSaverTest, VerifyGTestFlags) {
+  VerifyAndModifyFlags();
+}
+
+// Sets an environment variable with the given name to the given
+// value.  If the value argument is "", unsets the environment
+// variable.  The caller must ensure that both arguments are not NULL.
+static void SetEnv(const char* name, const char* value) {
+#if GTEST_OS_WINDOWS_MOBILE
+  // Environment variables are not supported on Windows CE.
+  return;
+#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9)
+  // C++Builder's putenv only stores a pointer to its parameter; we have to
+  // ensure that the string remains valid as long as it might be needed.
+  // We use an std::map to do so.
+  static std::map<std::string, std::string*> added_env;
+
+  // Because putenv stores a pointer to the string buffer, we can't delete the
+  // previous string (if present) until after it's replaced.
+  std::string *prev_env = NULL;
+  if (added_env.find(name) != added_env.end()) {
+    prev_env = added_env[name];
+  }
+  added_env[name] = new std::string(
+      (Message() << name << "=" << value).GetString());
+
+  // The standard signature of putenv accepts a 'char*' argument. Other
+  // implementations, like C++Builder's, accept a 'const char*'.
+  // We cast away the 'const' since that would work for both variants.
+  putenv(const_cast<char*>(added_env[name]->c_str()));
+  delete prev_env;
+#elif GTEST_OS_WINDOWS  // If we are on Windows proper.
+  _putenv((Message() << name << "=" << value).GetString().c_str());
+#else
+  if (*value == '\0') {
+    unsetenv(name);
+  } else {
+    setenv(name, value, 1);
+  }
+#endif  // GTEST_OS_WINDOWS_MOBILE
+}
+
+#if !GTEST_OS_WINDOWS_MOBILE
+// Environment variables are not supported on Windows CE.
+
+using testing::internal::Int32FromGTestEnv;
+
+// Tests Int32FromGTestEnv().
+
+// Tests that Int32FromGTestEnv() returns the default value when the
+// environment variable is not set.
+TEST(Int32FromGTestEnvTest, ReturnsDefaultWhenVariableIsNotSet) {
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "");
+  EXPECT_EQ(10, Int32FromGTestEnv("temp", 10));
+}
+
+# if !defined(GTEST_GET_INT32_FROM_ENV_)
+
+// Tests that Int32FromGTestEnv() returns the default value when the
+// environment variable overflows as an Int32.
+TEST(Int32FromGTestEnvTest, ReturnsDefaultWhenValueOverflows) {
+  printf("(expecting 2 warnings)\n");
+
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "12345678987654321");
+  EXPECT_EQ(20, Int32FromGTestEnv("temp", 20));
+
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "-12345678987654321");
+  EXPECT_EQ(30, Int32FromGTestEnv("temp", 30));
+}
+
+// Tests that Int32FromGTestEnv() returns the default value when the
+// environment variable does not represent a valid decimal integer.
+TEST(Int32FromGTestEnvTest, ReturnsDefaultWhenValueIsInvalid) {
+  printf("(expecting 2 warnings)\n");
+
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "A1");
+  EXPECT_EQ(40, Int32FromGTestEnv("temp", 40));
+
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "12X");
+  EXPECT_EQ(50, Int32FromGTestEnv("temp", 50));
+}
+
+# endif  // !defined(GTEST_GET_INT32_FROM_ENV_)
+
+// Tests that Int32FromGTestEnv() parses and returns the value of the
+// environment variable when it represents a valid decimal integer in
+// the range of an Int32.
+TEST(Int32FromGTestEnvTest, ParsesAndReturnsValidValue) {
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "123");
+  EXPECT_EQ(123, Int32FromGTestEnv("temp", 0));
+
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "-321");
+  EXPECT_EQ(-321, Int32FromGTestEnv("temp", 0));
+}
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+// Tests ParseInt32Flag().
+
+// Tests that ParseInt32Flag() returns false and doesn't change the
+// output value when the flag has wrong format
+TEST(ParseInt32FlagTest, ReturnsFalseForInvalidFlag) {
+  Int32 value = 123;
+  EXPECT_FALSE(ParseInt32Flag("--a=100", "b", &value));
+  EXPECT_EQ(123, value);
+
+  EXPECT_FALSE(ParseInt32Flag("a=100", "a", &value));
+  EXPECT_EQ(123, value);
+}
+
+// Tests that ParseInt32Flag() returns false and doesn't change the
+// output value when the flag overflows as an Int32.
+TEST(ParseInt32FlagTest, ReturnsDefaultWhenValueOverflows) {
+  printf("(expecting 2 warnings)\n");
+
+  Int32 value = 123;
+  EXPECT_FALSE(ParseInt32Flag("--abc=12345678987654321", "abc", &value));
+  EXPECT_EQ(123, value);
+
+  EXPECT_FALSE(ParseInt32Flag("--abc=-12345678987654321", "abc", &value));
+  EXPECT_EQ(123, value);
+}
+
+// Tests that ParseInt32Flag() returns false and doesn't change the
+// output value when the flag does not represent a valid decimal
+// integer.
+TEST(ParseInt32FlagTest, ReturnsDefaultWhenValueIsInvalid) {
+  printf("(expecting 2 warnings)\n");
+
+  Int32 value = 123;
+  EXPECT_FALSE(ParseInt32Flag("--abc=A1", "abc", &value));
+  EXPECT_EQ(123, value);
+
+  EXPECT_FALSE(ParseInt32Flag("--abc=12X", "abc", &value));
+  EXPECT_EQ(123, value);
+}
+
+// Tests that ParseInt32Flag() parses the value of the flag and
+// returns true when the flag represents a valid decimal integer in
+// the range of an Int32.
+TEST(ParseInt32FlagTest, ParsesAndReturnsValidValue) {
+  Int32 value = 123;
+  EXPECT_TRUE(ParseInt32Flag("--" GTEST_FLAG_PREFIX_ "abc=456", "abc", &value));
+  EXPECT_EQ(456, value);
+
+  EXPECT_TRUE(ParseInt32Flag("--" GTEST_FLAG_PREFIX_ "abc=-789",
+                             "abc", &value));
+  EXPECT_EQ(-789, value);
+}
+
+// Tests that Int32FromEnvOrDie() parses the value of the var or
+// returns the correct default.
+// Environment variables are not supported on Windows CE.
+#if !GTEST_OS_WINDOWS_MOBILE
+TEST(Int32FromEnvOrDieTest, ParsesAndReturnsValidValue) {
+  EXPECT_EQ(333, Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", 333));
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", "123");
+  EXPECT_EQ(123, Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", 333));
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", "-123");
+  EXPECT_EQ(-123, Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", 333));
+}
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+// Tests that Int32FromEnvOrDie() aborts with an error message
+// if the variable is not an Int32.
+TEST(Int32FromEnvOrDieDeathTest, AbortsOnFailure) {
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "VAR", "xxx");
+  EXPECT_DEATH_IF_SUPPORTED(
+      Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "VAR", 123),
+      ".*");
+}
+
+// Tests that Int32FromEnvOrDie() aborts with an error message
+// if the variable cannot be represnted by an Int32.
+TEST(Int32FromEnvOrDieDeathTest, AbortsOnInt32Overflow) {
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "VAR", "1234567891234567891234");
+  EXPECT_DEATH_IF_SUPPORTED(
+      Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "VAR", 123),
+      ".*");
+}
+
+// Tests that ShouldRunTestOnShard() selects all tests
+// where there is 1 shard.
+TEST(ShouldRunTestOnShardTest, IsPartitionWhenThereIsOneShard) {
+  EXPECT_TRUE(ShouldRunTestOnShard(1, 0, 0));
+  EXPECT_TRUE(ShouldRunTestOnShard(1, 0, 1));
+  EXPECT_TRUE(ShouldRunTestOnShard(1, 0, 2));
+  EXPECT_TRUE(ShouldRunTestOnShard(1, 0, 3));
+  EXPECT_TRUE(ShouldRunTestOnShard(1, 0, 4));
+}
+
+class ShouldShardTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    index_var_ = GTEST_FLAG_PREFIX_UPPER_ "INDEX";
+    total_var_ = GTEST_FLAG_PREFIX_UPPER_ "TOTAL";
+  }
+
+  virtual void TearDown() {
+    SetEnv(index_var_, "");
+    SetEnv(total_var_, "");
+  }
+
+  const char* index_var_;
+  const char* total_var_;
+};
+
+// Tests that sharding is disabled if neither of the environment variables
+// are set.
+TEST_F(ShouldShardTest, ReturnsFalseWhenNeitherEnvVarIsSet) {
+  SetEnv(index_var_, "");
+  SetEnv(total_var_, "");
+
+  EXPECT_FALSE(ShouldShard(total_var_, index_var_, false));
+  EXPECT_FALSE(ShouldShard(total_var_, index_var_, true));
+}
+
+// Tests that sharding is not enabled if total_shards  == 1.
+TEST_F(ShouldShardTest, ReturnsFalseWhenTotalShardIsOne) {
+  SetEnv(index_var_, "0");
+  SetEnv(total_var_, "1");
+  EXPECT_FALSE(ShouldShard(total_var_, index_var_, false));
+  EXPECT_FALSE(ShouldShard(total_var_, index_var_, true));
+}
+
+// Tests that sharding is enabled if total_shards > 1 and
+// we are not in a death test subprocess.
+// Environment variables are not supported on Windows CE.
+#if !GTEST_OS_WINDOWS_MOBILE
+TEST_F(ShouldShardTest, WorksWhenShardEnvVarsAreValid) {
+  SetEnv(index_var_, "4");
+  SetEnv(total_var_, "22");
+  EXPECT_TRUE(ShouldShard(total_var_, index_var_, false));
+  EXPECT_FALSE(ShouldShard(total_var_, index_var_, true));
+
+  SetEnv(index_var_, "8");
+  SetEnv(total_var_, "9");
+  EXPECT_TRUE(ShouldShard(total_var_, index_var_, false));
+  EXPECT_FALSE(ShouldShard(total_var_, index_var_, true));
+
+  SetEnv(index_var_, "0");
+  SetEnv(total_var_, "9");
+  EXPECT_TRUE(ShouldShard(total_var_, index_var_, false));
+  EXPECT_FALSE(ShouldShard(total_var_, index_var_, true));
+}
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+// Tests that we exit in error if the sharding values are not valid.
+
+typedef ShouldShardTest ShouldShardDeathTest;
+
+TEST_F(ShouldShardDeathTest, AbortsWhenShardingEnvVarsAreInvalid) {
+  SetEnv(index_var_, "4");
+  SetEnv(total_var_, "4");
+  EXPECT_DEATH_IF_SUPPORTED(ShouldShard(total_var_, index_var_, false), ".*");
+
+  SetEnv(index_var_, "4");
+  SetEnv(total_var_, "-2");
+  EXPECT_DEATH_IF_SUPPORTED(ShouldShard(total_var_, index_var_, false), ".*");
+
+  SetEnv(index_var_, "5");
+  SetEnv(total_var_, "");
+  EXPECT_DEATH_IF_SUPPORTED(ShouldShard(total_var_, index_var_, false), ".*");
+
+  SetEnv(index_var_, "");
+  SetEnv(total_var_, "5");
+  EXPECT_DEATH_IF_SUPPORTED(ShouldShard(total_var_, index_var_, false), ".*");
+}
+
+// Tests that ShouldRunTestOnShard is a partition when 5
+// shards are used.
+TEST(ShouldRunTestOnShardTest, IsPartitionWhenThereAreFiveShards) {
+  // Choose an arbitrary number of tests and shards.
+  const int num_tests = 17;
+  const int num_shards = 5;
+
+  // Check partitioning: each test should be on exactly 1 shard.
+  for (int test_id = 0; test_id < num_tests; test_id++) {
+    int prev_selected_shard_index = -1;
+    for (int shard_index = 0; shard_index < num_shards; shard_index++) {
+      if (ShouldRunTestOnShard(num_shards, shard_index, test_id)) {
+        if (prev_selected_shard_index < 0) {
+          prev_selected_shard_index = shard_index;
+        } else {
+          ADD_FAILURE() << "Shard " << prev_selected_shard_index << " and "
+            << shard_index << " are both selected to run test " << test_id;
+        }
+      }
+    }
+  }
+
+  // Check balance: This is not required by the sharding protocol, but is a
+  // desirable property for performance.
+  for (int shard_index = 0; shard_index < num_shards; shard_index++) {
+    int num_tests_on_shard = 0;
+    for (int test_id = 0; test_id < num_tests; test_id++) {
+      num_tests_on_shard +=
+        ShouldRunTestOnShard(num_shards, shard_index, test_id);
+    }
+    EXPECT_GE(num_tests_on_shard, num_tests / num_shards);
+  }
+}
+
+// For the same reason we are not explicitly testing everything in the
+// Test class, there are no separate tests for the following classes
+// (except for some trivial cases):
+//
+//   TestCase, UnitTest, UnitTestResultPrinter.
+//
+// Similarly, there are no separate tests for the following macros:
+//
+//   TEST, TEST_F, RUN_ALL_TESTS
+
+TEST(UnitTestTest, CanGetOriginalWorkingDir) {
+  ASSERT_TRUE(UnitTest::GetInstance()->original_working_dir() != NULL);
+  EXPECT_STRNE(UnitTest::GetInstance()->original_working_dir(), "");
+}
+
+TEST(UnitTestTest, ReturnsPlausibleTimestamp) {
+  EXPECT_LT(0, UnitTest::GetInstance()->start_timestamp());
+  EXPECT_LE(UnitTest::GetInstance()->start_timestamp(), GetTimeInMillis());
+}
+
+// When a property using a reserved key is supplied to this function, it
+// tests that a non-fatal failure is added, a fatal failure is not added,
+// and that the property is not recorded.
+void ExpectNonFatalFailureRecordingPropertyWithReservedKey(
+    const TestResult& test_result, const char* key) {
+  EXPECT_NONFATAL_FAILURE(Test::RecordProperty(key, "1"), "Reserved key");
+  ASSERT_EQ(0, test_result.test_property_count()) << "Property for key '" << key
+                                                  << "' recorded unexpectedly.";
+}
+
+void ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest(
+    const char* key) {
+  const TestInfo* test_info = UnitTest::GetInstance()->current_test_info();
+  ASSERT_TRUE(test_info != NULL);
+  ExpectNonFatalFailureRecordingPropertyWithReservedKey(*test_info->result(),
+                                                        key);
+}
+
+void ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestCase(
+    const char* key) {
+  const TestCase* test_case = UnitTest::GetInstance()->current_test_case();
+  ASSERT_TRUE(test_case != NULL);
+  ExpectNonFatalFailureRecordingPropertyWithReservedKey(
+      test_case->ad_hoc_test_result(), key);
+}
+
+void ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestCase(
+    const char* key) {
+  ExpectNonFatalFailureRecordingPropertyWithReservedKey(
+      UnitTest::GetInstance()->ad_hoc_test_result(), key);
+}
+
+// Tests that property recording functions in UnitTest outside of tests
+// functions correcly.  Creating a separate instance of UnitTest ensures it
+// is in a state similar to the UnitTest's singleton's between tests.
+class UnitTestRecordPropertyTest :
+    public testing::internal::UnitTestRecordPropertyTestHelper {
+ public:
+  static void SetUpTestCase() {
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestCase(
+        "disabled");
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestCase(
+        "errors");
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestCase(
+        "failures");
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestCase(
+        "name");
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestCase(
+        "tests");
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestCase(
+        "time");
+
+    Test::RecordProperty("test_case_key_1", "1");
+    const TestCase* test_case = UnitTest::GetInstance()->current_test_case();
+    ASSERT_TRUE(test_case != NULL);
+
+    ASSERT_EQ(1, test_case->ad_hoc_test_result().test_property_count());
+    EXPECT_STREQ("test_case_key_1",
+                 test_case->ad_hoc_test_result().GetTestProperty(0).key());
+    EXPECT_STREQ("1",
+                 test_case->ad_hoc_test_result().GetTestProperty(0).value());
+  }
+};
+
+// Tests TestResult has the expected property when added.
+TEST_F(UnitTestRecordPropertyTest, OnePropertyFoundWhenAdded) {
+  UnitTestRecordProperty("key_1", "1");
+
+  ASSERT_EQ(1, unit_test_.ad_hoc_test_result().test_property_count());
+
+  EXPECT_STREQ("key_1",
+               unit_test_.ad_hoc_test_result().GetTestProperty(0).key());
+  EXPECT_STREQ("1",
+               unit_test_.ad_hoc_test_result().GetTestProperty(0).value());
+}
+
+// Tests TestResult has multiple properties when added.
+TEST_F(UnitTestRecordPropertyTest, MultiplePropertiesFoundWhenAdded) {
+  UnitTestRecordProperty("key_1", "1");
+  UnitTestRecordProperty("key_2", "2");
+
+  ASSERT_EQ(2, unit_test_.ad_hoc_test_result().test_property_count());
+
+  EXPECT_STREQ("key_1",
+               unit_test_.ad_hoc_test_result().GetTestProperty(0).key());
+  EXPECT_STREQ("1", unit_test_.ad_hoc_test_result().GetTestProperty(0).value());
+
+  EXPECT_STREQ("key_2",
+               unit_test_.ad_hoc_test_result().GetTestProperty(1).key());
+  EXPECT_STREQ("2", unit_test_.ad_hoc_test_result().GetTestProperty(1).value());
+}
+
+// Tests TestResult::RecordProperty() overrides values for duplicate keys.
+TEST_F(UnitTestRecordPropertyTest, OverridesValuesForDuplicateKeys) {
+  UnitTestRecordProperty("key_1", "1");
+  UnitTestRecordProperty("key_2", "2");
+  UnitTestRecordProperty("key_1", "12");
+  UnitTestRecordProperty("key_2", "22");
+
+  ASSERT_EQ(2, unit_test_.ad_hoc_test_result().test_property_count());
+
+  EXPECT_STREQ("key_1",
+               unit_test_.ad_hoc_test_result().GetTestProperty(0).key());
+  EXPECT_STREQ("12",
+               unit_test_.ad_hoc_test_result().GetTestProperty(0).value());
+
+  EXPECT_STREQ("key_2",
+               unit_test_.ad_hoc_test_result().GetTestProperty(1).key());
+  EXPECT_STREQ("22",
+               unit_test_.ad_hoc_test_result().GetTestProperty(1).value());
+}
+
+TEST_F(UnitTestRecordPropertyTest,
+       AddFailureInsideTestsWhenUsingTestCaseReservedKeys) {
+  ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest(
+      "name");
+  ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest(
+      "value_param");
+  ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest(
+      "type_param");
+  ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest(
+      "status");
+  ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest(
+      "time");
+  ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest(
+      "classname");
+}
+
+TEST_F(UnitTestRecordPropertyTest,
+       AddRecordWithReservedKeysGeneratesCorrectPropertyList) {
+  EXPECT_NONFATAL_FAILURE(
+      Test::RecordProperty("name", "1"),
+      "'classname', 'name', 'status', 'time', 'type_param', and 'value_param'"
+      " are reserved");
+}
+
+class UnitTestRecordPropertyTestEnvironment : public Environment {
+ public:
+  virtual void TearDown() {
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestCase(
+        "tests");
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestCase(
+        "failures");
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestCase(
+        "disabled");
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestCase(
+        "errors");
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestCase(
+        "name");
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestCase(
+        "timestamp");
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestCase(
+        "time");
+    ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestCase(
+        "random_seed");
+  }
+};
+
+// This will test property recording outside of any test or test case.
+static Environment* record_property_env =
+    AddGlobalTestEnvironment(new UnitTestRecordPropertyTestEnvironment);
+
+// This group of tests is for predicate assertions (ASSERT_PRED*, etc)
+// of various arities.  They do not attempt to be exhaustive.  Rather,
+// view them as smoke tests that can be easily reviewed and verified.
+// A more complete set of tests for predicate assertions can be found
+// in gtest_pred_impl_unittest.cc.
+
+// First, some predicates and predicate-formatters needed by the tests.
+
+// Returns true iff the argument is an even number.
+bool IsEven(int n) {
+  return (n % 2) == 0;
+}
+
+// A functor that returns true iff the argument is an even number.
+struct IsEvenFunctor {
+  bool operator()(int n) { return IsEven(n); }
+};
+
+// A predicate-formatter function that asserts the argument is an even
+// number.
+AssertionResult AssertIsEven(const char* expr, int n) {
+  if (IsEven(n)) {
+    return AssertionSuccess();
+  }
+
+  Message msg;
+  msg << expr << " evaluates to " << n << ", which is not even.";
+  return AssertionFailure(msg);
+}
+
+// A predicate function that returns AssertionResult for use in
+// EXPECT/ASSERT_TRUE/FALSE.
+AssertionResult ResultIsEven(int n) {
+  if (IsEven(n))
+    return AssertionSuccess() << n << " is even";
+  else
+    return AssertionFailure() << n << " is odd";
+}
+
+// A predicate function that returns AssertionResult but gives no
+// explanation why it succeeds. Needed for testing that
+// EXPECT/ASSERT_FALSE handles such functions correctly.
+AssertionResult ResultIsEvenNoExplanation(int n) {
+  if (IsEven(n))
+    return AssertionSuccess();
+  else
+    return AssertionFailure() << n << " is odd";
+}
+
+// A predicate-formatter functor that asserts the argument is an even
+// number.
+struct AssertIsEvenFunctor {
+  AssertionResult operator()(const char* expr, int n) {
+    return AssertIsEven(expr, n);
+  }
+};
+
+// Returns true iff the sum of the arguments is an even number.
+bool SumIsEven2(int n1, int n2) {
+  return IsEven(n1 + n2);
+}
+
+// A functor that returns true iff the sum of the arguments is an even
+// number.
+struct SumIsEven3Functor {
+  bool operator()(int n1, int n2, int n3) {
+    return IsEven(n1 + n2 + n3);
+  }
+};
+
+// A predicate-formatter function that asserts the sum of the
+// arguments is an even number.
+AssertionResult AssertSumIsEven4(
+    const char* e1, const char* e2, const char* e3, const char* e4,
+    int n1, int n2, int n3, int n4) {
+  const int sum = n1 + n2 + n3 + n4;
+  if (IsEven(sum)) {
+    return AssertionSuccess();
+  }
+
+  Message msg;
+  msg << e1 << " + " << e2 << " + " << e3 << " + " << e4
+      << " (" << n1 << " + " << n2 << " + " << n3 << " + " << n4
+      << ") evaluates to " << sum << ", which is not even.";
+  return AssertionFailure(msg);
+}
+
+// A predicate-formatter functor that asserts the sum of the arguments
+// is an even number.
+struct AssertSumIsEven5Functor {
+  AssertionResult operator()(
+      const char* e1, const char* e2, const char* e3, const char* e4,
+      const char* e5, int n1, int n2, int n3, int n4, int n5) {
+    const int sum = n1 + n2 + n3 + n4 + n5;
+    if (IsEven(sum)) {
+      return AssertionSuccess();
+    }
+
+    Message msg;
+    msg << e1 << " + " << e2 << " + " << e3 << " + " << e4 << " + " << e5
+        << " ("
+        << n1 << " + " << n2 << " + " << n3 << " + " << n4 << " + " << n5
+        << ") evaluates to " << sum << ", which is not even.";
+    return AssertionFailure(msg);
+  }
+};
+
+
+// Tests unary predicate assertions.
+
+// Tests unary predicate assertions that don't use a custom formatter.
+TEST(Pred1Test, WithoutFormat) {
+  // Success cases.
+  EXPECT_PRED1(IsEvenFunctor(), 2) << "This failure is UNEXPECTED!";
+  ASSERT_PRED1(IsEven, 4);
+
+  // Failure cases.
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED1(IsEven, 5) << "This failure is expected.";
+  }, "This failure is expected.");
+  EXPECT_FATAL_FAILURE(ASSERT_PRED1(IsEvenFunctor(), 5),
+                       "evaluates to false");
+}
+
+// Tests unary predicate assertions that use a custom formatter.
+TEST(Pred1Test, WithFormat) {
+  // Success cases.
+  EXPECT_PRED_FORMAT1(AssertIsEven, 2);
+  ASSERT_PRED_FORMAT1(AssertIsEvenFunctor(), 4)
+    << "This failure is UNEXPECTED!";
+
+  // Failure cases.
+  const int n = 5;
+  EXPECT_NONFATAL_FAILURE(EXPECT_PRED_FORMAT1(AssertIsEvenFunctor(), n),
+                          "n evaluates to 5, which is not even.");
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT1(AssertIsEven, 5) << "This failure is expected.";
+  }, "This failure is expected.");
+}
+
+// Tests that unary predicate assertions evaluates their arguments
+// exactly once.
+TEST(Pred1Test, SingleEvaluationOnFailure) {
+  // A success case.
+  static int n = 0;
+  EXPECT_PRED1(IsEven, n++);
+  EXPECT_EQ(1, n) << "The argument is not evaluated exactly once.";
+
+  // A failure case.
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT1(AssertIsEvenFunctor(), n++)
+        << "This failure is expected.";
+  }, "This failure is expected.");
+  EXPECT_EQ(2, n) << "The argument is not evaluated exactly once.";
+}
+
+
+// Tests predicate assertions whose arity is >= 2.
+
+// Tests predicate assertions that don't use a custom formatter.
+TEST(PredTest, WithoutFormat) {
+  // Success cases.
+  ASSERT_PRED2(SumIsEven2, 2, 4) << "This failure is UNEXPECTED!";
+  EXPECT_PRED3(SumIsEven3Functor(), 4, 6, 8);
+
+  // Failure cases.
+  const int n1 = 1;
+  const int n2 = 2;
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED2(SumIsEven2, n1, n2) << "This failure is expected.";
+  }, "This failure is expected.");
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED3(SumIsEven3Functor(), 1, 2, 4);
+  }, "evaluates to false");
+}
+
+// Tests predicate assertions that use a custom formatter.
+TEST(PredTest, WithFormat) {
+  // Success cases.
+  ASSERT_PRED_FORMAT4(AssertSumIsEven4, 4, 6, 8, 10) <<
+    "This failure is UNEXPECTED!";
+  EXPECT_PRED_FORMAT5(AssertSumIsEven5Functor(), 2, 4, 6, 8, 10);
+
+  // Failure cases.
+  const int n1 = 1;
+  const int n2 = 2;
+  const int n3 = 4;
+  const int n4 = 6;
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT4(AssertSumIsEven4, n1, n2, n3, n4);
+  }, "evaluates to 13, which is not even.");
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT5(AssertSumIsEven5Functor(), 1, 2, 4, 6, 8)
+        << "This failure is expected.";
+  }, "This failure is expected.");
+}
+
+// Tests that predicate assertions evaluates their arguments
+// exactly once.
+TEST(PredTest, SingleEvaluationOnFailure) {
+  // A success case.
+  int n1 = 0;
+  int n2 = 0;
+  EXPECT_PRED2(SumIsEven2, n1++, n2++);
+  EXPECT_EQ(1, n1) << "Argument 1 is not evaluated exactly once.";
+  EXPECT_EQ(1, n2) << "Argument 2 is not evaluated exactly once.";
+
+  // Another success case.
+  n1 = n2 = 0;
+  int n3 = 0;
+  int n4 = 0;
+  int n5 = 0;
+  ASSERT_PRED_FORMAT5(AssertSumIsEven5Functor(),
+                      n1++, n2++, n3++, n4++, n5++)
+                        << "This failure is UNEXPECTED!";
+  EXPECT_EQ(1, n1) << "Argument 1 is not evaluated exactly once.";
+  EXPECT_EQ(1, n2) << "Argument 2 is not evaluated exactly once.";
+  EXPECT_EQ(1, n3) << "Argument 3 is not evaluated exactly once.";
+  EXPECT_EQ(1, n4) << "Argument 4 is not evaluated exactly once.";
+  EXPECT_EQ(1, n5) << "Argument 5 is not evaluated exactly once.";
+
+  // A failure case.
+  n1 = n2 = n3 = 0;
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED3(SumIsEven3Functor(), ++n1, n2++, n3++)
+        << "This failure is expected.";
+  }, "This failure is expected.");
+  EXPECT_EQ(1, n1) << "Argument 1 is not evaluated exactly once.";
+  EXPECT_EQ(1, n2) << "Argument 2 is not evaluated exactly once.";
+  EXPECT_EQ(1, n3) << "Argument 3 is not evaluated exactly once.";
+
+  // Another failure case.
+  n1 = n2 = n3 = n4 = 0;
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT4(AssertSumIsEven4, ++n1, n2++, n3++, n4++);
+  }, "evaluates to 1, which is not even.");
+  EXPECT_EQ(1, n1) << "Argument 1 is not evaluated exactly once.";
+  EXPECT_EQ(1, n2) << "Argument 2 is not evaluated exactly once.";
+  EXPECT_EQ(1, n3) << "Argument 3 is not evaluated exactly once.";
+  EXPECT_EQ(1, n4) << "Argument 4 is not evaluated exactly once.";
+}
+
+
+// Some helper functions for testing using overloaded/template
+// functions with ASSERT_PREDn and EXPECT_PREDn.
+
+bool IsPositive(double x) {
+  return x > 0;
+}
+
+template <typename T>
+bool IsNegative(T x) {
+  return x < 0;
+}
+
+template <typename T1, typename T2>
+bool GreaterThan(T1 x1, T2 x2) {
+  return x1 > x2;
+}
+
+// Tests that overloaded functions can be used in *_PRED* as long as
+// their types are explicitly specified.
+TEST(PredicateAssertionTest, AcceptsOverloadedFunction) {
+  // C++Builder requires C-style casts rather than static_cast.
+  EXPECT_PRED1((bool (*)(int))(IsPositive), 5);  // NOLINT
+  ASSERT_PRED1((bool (*)(double))(IsPositive), 6.0);  // NOLINT
+}
+
+// Tests that template functions can be used in *_PRED* as long as
+// their types are explicitly specified.
+TEST(PredicateAssertionTest, AcceptsTemplateFunction) {
+  EXPECT_PRED1(IsNegative<int>, -5);
+  // Makes sure that we can handle templates with more than one
+  // parameter.
+  ASSERT_PRED2((GreaterThan<int, int>), 5, 0);
+}
+
+
+// Some helper functions for testing using overloaded/template
+// functions with ASSERT_PRED_FORMATn and EXPECT_PRED_FORMATn.
+
+AssertionResult IsPositiveFormat(const char* /* expr */, int n) {
+  return n > 0 ? AssertionSuccess() :
+      AssertionFailure(Message() << "Failure");
+}
+
+AssertionResult IsPositiveFormat(const char* /* expr */, double x) {
+  return x > 0 ? AssertionSuccess() :
+      AssertionFailure(Message() << "Failure");
+}
+
+template <typename T>
+AssertionResult IsNegativeFormat(const char* /* expr */, T x) {
+  return x < 0 ? AssertionSuccess() :
+      AssertionFailure(Message() << "Failure");
+}
+
+template <typename T1, typename T2>
+AssertionResult EqualsFormat(const char* /* expr1 */, const char* /* expr2 */,
+                             const T1& x1, const T2& x2) {
+  return x1 == x2 ? AssertionSuccess() :
+      AssertionFailure(Message() << "Failure");
+}
+
+// Tests that overloaded functions can be used in *_PRED_FORMAT*
+// without explicitly specifying their types.
+TEST(PredicateFormatAssertionTest, AcceptsOverloadedFunction) {
+  EXPECT_PRED_FORMAT1(IsPositiveFormat, 5);
+  ASSERT_PRED_FORMAT1(IsPositiveFormat, 6.0);
+}
+
+// Tests that template functions can be used in *_PRED_FORMAT* without
+// explicitly specifying their types.
+TEST(PredicateFormatAssertionTest, AcceptsTemplateFunction) {
+  EXPECT_PRED_FORMAT1(IsNegativeFormat, -5);
+  ASSERT_PRED_FORMAT2(EqualsFormat, 3, 3);
+}
+
+
+// Tests string assertions.
+
+// Tests ASSERT_STREQ with non-NULL arguments.
+TEST(StringAssertionTest, ASSERT_STREQ) {
+  const char * const p1 = "good";
+  ASSERT_STREQ(p1, p1);
+
+  // Let p2 have the same content as p1, but be at a different address.
+  const char p2[] = "good";
+  ASSERT_STREQ(p1, p2);
+
+  EXPECT_FATAL_FAILURE(ASSERT_STREQ("bad", "good"),
+                       "Expected: \"bad\"");
+}
+
+// Tests ASSERT_STREQ with NULL arguments.
+TEST(StringAssertionTest, ASSERT_STREQ_Null) {
+  ASSERT_STREQ(static_cast<const char *>(NULL), NULL);
+  EXPECT_FATAL_FAILURE(ASSERT_STREQ(NULL, "non-null"),
+                       "non-null");
+}
+
+// Tests ASSERT_STREQ with NULL arguments.
+TEST(StringAssertionTest, ASSERT_STREQ_Null2) {
+  EXPECT_FATAL_FAILURE(ASSERT_STREQ("non-null", NULL),
+                       "non-null");
+}
+
+// Tests ASSERT_STRNE.
+TEST(StringAssertionTest, ASSERT_STRNE) {
+  ASSERT_STRNE("hi", "Hi");
+  ASSERT_STRNE("Hi", NULL);
+  ASSERT_STRNE(NULL, "Hi");
+  ASSERT_STRNE("", NULL);
+  ASSERT_STRNE(NULL, "");
+  ASSERT_STRNE("", "Hi");
+  ASSERT_STRNE("Hi", "");
+  EXPECT_FATAL_FAILURE(ASSERT_STRNE("Hi", "Hi"),
+                       "\"Hi\" vs \"Hi\"");
+}
+
+// Tests ASSERT_STRCASEEQ.
+TEST(StringAssertionTest, ASSERT_STRCASEEQ) {
+  ASSERT_STRCASEEQ("hi", "Hi");
+  ASSERT_STRCASEEQ(static_cast<const char *>(NULL), NULL);
+
+  ASSERT_STRCASEEQ("", "");
+  EXPECT_FATAL_FAILURE(ASSERT_STRCASEEQ("Hi", "hi2"),
+                       "(ignoring case)");
+}
+
+// Tests ASSERT_STRCASENE.
+TEST(StringAssertionTest, ASSERT_STRCASENE) {
+  ASSERT_STRCASENE("hi1", "Hi2");
+  ASSERT_STRCASENE("Hi", NULL);
+  ASSERT_STRCASENE(NULL, "Hi");
+  ASSERT_STRCASENE("", NULL);
+  ASSERT_STRCASENE(NULL, "");
+  ASSERT_STRCASENE("", "Hi");
+  ASSERT_STRCASENE("Hi", "");
+  EXPECT_FATAL_FAILURE(ASSERT_STRCASENE("Hi", "hi"),
+                       "(ignoring case)");
+}
+
+// Tests *_STREQ on wide strings.
+TEST(StringAssertionTest, STREQ_Wide) {
+  // NULL strings.
+  ASSERT_STREQ(static_cast<const wchar_t *>(NULL), NULL);
+
+  // Empty strings.
+  ASSERT_STREQ(L"", L"");
+
+  // Non-null vs NULL.
+  EXPECT_NONFATAL_FAILURE(EXPECT_STREQ(L"non-null", NULL),
+                          "non-null");
+
+  // Equal strings.
+  EXPECT_STREQ(L"Hi", L"Hi");
+
+  // Unequal strings.
+  EXPECT_NONFATAL_FAILURE(EXPECT_STREQ(L"abc", L"Abc"),
+                          "Abc");
+
+  // Strings containing wide characters.
+  EXPECT_NONFATAL_FAILURE(EXPECT_STREQ(L"abc\x8119", L"abc\x8120"),
+                          "abc");
+
+  // The streaming variation.
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_STREQ(L"abc\x8119", L"abc\x8121") << "Expected failure";
+  }, "Expected failure");
+}
+
+// Tests *_STRNE on wide strings.
+TEST(StringAssertionTest, STRNE_Wide) {
+  // NULL strings.
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_STRNE(static_cast<const wchar_t *>(NULL), NULL);
+  }, "");
+
+  // Empty strings.
+  EXPECT_NONFATAL_FAILURE(EXPECT_STRNE(L"", L""),
+                          "L\"\"");
+
+  // Non-null vs NULL.
+  ASSERT_STRNE(L"non-null", NULL);
+
+  // Equal strings.
+  EXPECT_NONFATAL_FAILURE(EXPECT_STRNE(L"Hi", L"Hi"),
+                          "L\"Hi\"");
+
+  // Unequal strings.
+  EXPECT_STRNE(L"abc", L"Abc");
+
+  // Strings containing wide characters.
+  EXPECT_NONFATAL_FAILURE(EXPECT_STRNE(L"abc\x8119", L"abc\x8119"),
+                          "abc");
+
+  // The streaming variation.
+  ASSERT_STRNE(L"abc\x8119", L"abc\x8120") << "This shouldn't happen";
+}
+
+// Tests for ::testing::IsSubstring().
+
+// Tests that IsSubstring() returns the correct result when the input
+// argument type is const char*.
+TEST(IsSubstringTest, ReturnsCorrectResultForCString) {
+  EXPECT_FALSE(IsSubstring("", "", NULL, "a"));
+  EXPECT_FALSE(IsSubstring("", "", "b", NULL));
+  EXPECT_FALSE(IsSubstring("", "", "needle", "haystack"));
+
+  EXPECT_TRUE(IsSubstring("", "", static_cast<const char*>(NULL), NULL));
+  EXPECT_TRUE(IsSubstring("", "", "needle", "two needles"));
+}
+
+// Tests that IsSubstring() returns the correct result when the input
+// argument type is const wchar_t*.
+TEST(IsSubstringTest, ReturnsCorrectResultForWideCString) {
+  EXPECT_FALSE(IsSubstring("", "", kNull, L"a"));
+  EXPECT_FALSE(IsSubstring("", "", L"b", kNull));
+  EXPECT_FALSE(IsSubstring("", "", L"needle", L"haystack"));
+
+  EXPECT_TRUE(IsSubstring("", "", static_cast<const wchar_t*>(NULL), NULL));
+  EXPECT_TRUE(IsSubstring("", "", L"needle", L"two needles"));
+}
+
+// Tests that IsSubstring() generates the correct message when the input
+// argument type is const char*.
+TEST(IsSubstringTest, GeneratesCorrectMessageForCString) {
+  EXPECT_STREQ("Value of: needle_expr\n"
+               "  Actual: \"needle\"\n"
+               "Expected: a substring of haystack_expr\n"
+               "Which is: \"haystack\"",
+               IsSubstring("needle_expr", "haystack_expr",
+                           "needle", "haystack").failure_message());
+}
+
+// Tests that IsSubstring returns the correct result when the input
+// argument type is ::std::string.
+TEST(IsSubstringTest, ReturnsCorrectResultsForStdString) {
+  EXPECT_TRUE(IsSubstring("", "", std::string("hello"), "ahellob"));
+  EXPECT_FALSE(IsSubstring("", "", "hello", std::string("world")));
+}
+
+#if GTEST_HAS_STD_WSTRING
+// Tests that IsSubstring returns the correct result when the input
+// argument type is ::std::wstring.
+TEST(IsSubstringTest, ReturnsCorrectResultForStdWstring) {
+  EXPECT_TRUE(IsSubstring("", "", ::std::wstring(L"needle"), L"two needles"));
+  EXPECT_FALSE(IsSubstring("", "", L"needle", ::std::wstring(L"haystack")));
+}
+
+// Tests that IsSubstring() generates the correct message when the input
+// argument type is ::std::wstring.
+TEST(IsSubstringTest, GeneratesCorrectMessageForWstring) {
+  EXPECT_STREQ("Value of: needle_expr\n"
+               "  Actual: L\"needle\"\n"
+               "Expected: a substring of haystack_expr\n"
+               "Which is: L\"haystack\"",
+               IsSubstring(
+                   "needle_expr", "haystack_expr",
+                   ::std::wstring(L"needle"), L"haystack").failure_message());
+}
+
+#endif  // GTEST_HAS_STD_WSTRING
+
+// Tests for ::testing::IsNotSubstring().
+
+// Tests that IsNotSubstring() returns the correct result when the input
+// argument type is const char*.
+TEST(IsNotSubstringTest, ReturnsCorrectResultForCString) {
+  EXPECT_TRUE(IsNotSubstring("", "", "needle", "haystack"));
+  EXPECT_FALSE(IsNotSubstring("", "", "needle", "two needles"));
+}
+
+// Tests that IsNotSubstring() returns the correct result when the input
+// argument type is const wchar_t*.
+TEST(IsNotSubstringTest, ReturnsCorrectResultForWideCString) {
+  EXPECT_TRUE(IsNotSubstring("", "", L"needle", L"haystack"));
+  EXPECT_FALSE(IsNotSubstring("", "", L"needle", L"two needles"));
+}
+
+// Tests that IsNotSubstring() generates the correct message when the input
+// argument type is const wchar_t*.
+TEST(IsNotSubstringTest, GeneratesCorrectMessageForWideCString) {
+  EXPECT_STREQ("Value of: needle_expr\n"
+               "  Actual: L\"needle\"\n"
+               "Expected: not a substring of haystack_expr\n"
+               "Which is: L\"two needles\"",
+               IsNotSubstring(
+                   "needle_expr", "haystack_expr",
+                   L"needle", L"two needles").failure_message());
+}
+
+// Tests that IsNotSubstring returns the correct result when the input
+// argument type is ::std::string.
+TEST(IsNotSubstringTest, ReturnsCorrectResultsForStdString) {
+  EXPECT_FALSE(IsNotSubstring("", "", std::string("hello"), "ahellob"));
+  EXPECT_TRUE(IsNotSubstring("", "", "hello", std::string("world")));
+}
+
+// Tests that IsNotSubstring() generates the correct message when the input
+// argument type is ::std::string.
+TEST(IsNotSubstringTest, GeneratesCorrectMessageForStdString) {
+  EXPECT_STREQ("Value of: needle_expr\n"
+               "  Actual: \"needle\"\n"
+               "Expected: not a substring of haystack_expr\n"
+               "Which is: \"two needles\"",
+               IsNotSubstring(
+                   "needle_expr", "haystack_expr",
+                   ::std::string("needle"), "two needles").failure_message());
+}
+
+#if GTEST_HAS_STD_WSTRING
+
+// Tests that IsNotSubstring returns the correct result when the input
+// argument type is ::std::wstring.
+TEST(IsNotSubstringTest, ReturnsCorrectResultForStdWstring) {
+  EXPECT_FALSE(
+      IsNotSubstring("", "", ::std::wstring(L"needle"), L"two needles"));
+  EXPECT_TRUE(IsNotSubstring("", "", L"needle", ::std::wstring(L"haystack")));
+}
+
+#endif  // GTEST_HAS_STD_WSTRING
+
+// Tests floating-point assertions.
+
+template <typename RawType>
+class FloatingPointTest : public Test {
+ protected:
+  // Pre-calculated numbers to be used by the tests.
+  struct TestValues {
+    RawType close_to_positive_zero;
+    RawType close_to_negative_zero;
+    RawType further_from_negative_zero;
+
+    RawType close_to_one;
+    RawType further_from_one;
+
+    RawType infinity;
+    RawType close_to_infinity;
+    RawType further_from_infinity;
+
+    RawType nan1;
+    RawType nan2;
+  };
+
+  typedef typename testing::internal::FloatingPoint<RawType> Floating;
+  typedef typename Floating::Bits Bits;
+
+  virtual void SetUp() {
+    const size_t max_ulps = Floating::kMaxUlps;
+
+    // The bits that represent 0.0.
+    const Bits zero_bits = Floating(0).bits();
+
+    // Makes some numbers close to 0.0.
+    values_.close_to_positive_zero = Floating::ReinterpretBits(
+        zero_bits + max_ulps/2);
+    values_.close_to_negative_zero = -Floating::ReinterpretBits(
+        zero_bits + max_ulps - max_ulps/2);
+    values_.further_from_negative_zero = -Floating::ReinterpretBits(
+        zero_bits + max_ulps + 1 - max_ulps/2);
+
+    // The bits that represent 1.0.
+    const Bits one_bits = Floating(1).bits();
+
+    // Makes some numbers close to 1.0.
+    values_.close_to_one = Floating::ReinterpretBits(one_bits + max_ulps);
+    values_.further_from_one = Floating::ReinterpretBits(
+        one_bits + max_ulps + 1);
+
+    // +infinity.
+    values_.infinity = Floating::Infinity();
+
+    // The bits that represent +infinity.
+    const Bits infinity_bits = Floating(values_.infinity).bits();
+
+    // Makes some numbers close to infinity.
+    values_.close_to_infinity = Floating::ReinterpretBits(
+        infinity_bits - max_ulps);
+    values_.further_from_infinity = Floating::ReinterpretBits(
+        infinity_bits - max_ulps - 1);
+
+    // Makes some NAN's.  Sets the most significant bit of the fraction so that
+    // our NaN's are quiet; trying to process a signaling NaN would raise an
+    // exception if our environment enables floating point exceptions.
+    values_.nan1 = Floating::ReinterpretBits(Floating::kExponentBitMask
+        | (static_cast<Bits>(1) << (Floating::kFractionBitCount - 1)) | 1);
+    values_.nan2 = Floating::ReinterpretBits(Floating::kExponentBitMask
+        | (static_cast<Bits>(1) << (Floating::kFractionBitCount - 1)) | 200);
+  }
+
+  void TestSize() {
+    EXPECT_EQ(sizeof(RawType), sizeof(Bits));
+  }
+
+  static TestValues values_;
+};
+
+template <typename RawType>
+typename FloatingPointTest<RawType>::TestValues
+    FloatingPointTest<RawType>::values_;
+
+// Instantiates FloatingPointTest for testing *_FLOAT_EQ.
+typedef FloatingPointTest<float> FloatTest;
+
+// Tests that the size of Float::Bits matches the size of float.
+TEST_F(FloatTest, Size) {
+  TestSize();
+}
+
+// Tests comparing with +0 and -0.
+TEST_F(FloatTest, Zeros) {
+  EXPECT_FLOAT_EQ(0.0, -0.0);
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(-0.0, 1.0),
+                          "1.0");
+  EXPECT_FATAL_FAILURE(ASSERT_FLOAT_EQ(0.0, 1.5),
+                       "1.5");
+}
+
+// Tests comparing numbers close to 0.
+//
+// This ensures that *_FLOAT_EQ handles the sign correctly and no
+// overflow occurs when comparing numbers whose absolute value is very
+// small.
+TEST_F(FloatTest, AlmostZeros) {
+  // In C++Builder, names within local classes (such as used by
+  // EXPECT_FATAL_FAILURE) cannot be resolved against static members of the
+  // scoping class.  Use a static local alias as a workaround.
+  // We use the assignment syntax since some compilers, like Sun Studio,
+  // don't allow initializing references using construction syntax
+  // (parentheses).
+  static const FloatTest::TestValues& v = this->values_;
+
+  EXPECT_FLOAT_EQ(0.0, v.close_to_positive_zero);
+  EXPECT_FLOAT_EQ(-0.0, v.close_to_negative_zero);
+  EXPECT_FLOAT_EQ(v.close_to_positive_zero, v.close_to_negative_zero);
+
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_FLOAT_EQ(v.close_to_positive_zero,
+                    v.further_from_negative_zero);
+  }, "v.further_from_negative_zero");
+}
+
+// Tests comparing numbers close to each other.
+TEST_F(FloatTest, SmallDiff) {
+  EXPECT_FLOAT_EQ(1.0, values_.close_to_one);
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(1.0, values_.further_from_one),
+                          "values_.further_from_one");
+}
+
+// Tests comparing numbers far apart.
+TEST_F(FloatTest, LargeDiff) {
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(2.5, 3.0),
+                          "3.0");
+}
+
+// Tests comparing with infinity.
+//
+// This ensures that no overflow occurs when comparing numbers whose
+// absolute value is very large.
+TEST_F(FloatTest, Infinity) {
+  EXPECT_FLOAT_EQ(values_.infinity, values_.close_to_infinity);
+  EXPECT_FLOAT_EQ(-values_.infinity, -values_.close_to_infinity);
+#if !GTEST_OS_SYMBIAN
+  // Nokia's STLport crashes if we try to output infinity or NaN.
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(values_.infinity, -values_.infinity),
+                          "-values_.infinity");
+
+  // This is interesting as the representations of infinity and nan1
+  // are only 1 DLP apart.
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(values_.infinity, values_.nan1),
+                          "values_.nan1");
+#endif  // !GTEST_OS_SYMBIAN
+}
+
+// Tests that comparing with NAN always returns false.
+TEST_F(FloatTest, NaN) {
+#if !GTEST_OS_SYMBIAN
+// Nokia's STLport crashes if we try to output infinity or NaN.
+
+  // In C++Builder, names within local classes (such as used by
+  // EXPECT_FATAL_FAILURE) cannot be resolved against static members of the
+  // scoping class.  Use a static local alias as a workaround.
+  // We use the assignment syntax since some compilers, like Sun Studio,
+  // don't allow initializing references using construction syntax
+  // (parentheses).
+  static const FloatTest::TestValues& v = this->values_;
+
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(v.nan1, v.nan1),
+                          "v.nan1");
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(v.nan1, v.nan2),
+                          "v.nan2");
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(1.0, v.nan1),
+                          "v.nan1");
+
+  EXPECT_FATAL_FAILURE(ASSERT_FLOAT_EQ(v.nan1, v.infinity),
+                       "v.infinity");
+#endif  // !GTEST_OS_SYMBIAN
+}
+
+// Tests that *_FLOAT_EQ are reflexive.
+TEST_F(FloatTest, Reflexive) {
+  EXPECT_FLOAT_EQ(0.0, 0.0);
+  EXPECT_FLOAT_EQ(1.0, 1.0);
+  ASSERT_FLOAT_EQ(values_.infinity, values_.infinity);
+}
+
+// Tests that *_FLOAT_EQ are commutative.
+TEST_F(FloatTest, Commutative) {
+  // We already tested EXPECT_FLOAT_EQ(1.0, values_.close_to_one).
+  EXPECT_FLOAT_EQ(values_.close_to_one, 1.0);
+
+  // We already tested EXPECT_FLOAT_EQ(1.0, values_.further_from_one).
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(values_.further_from_one, 1.0),
+                          "1.0");
+}
+
+// Tests EXPECT_NEAR.
+TEST_F(FloatTest, EXPECT_NEAR) {
+  EXPECT_NEAR(-1.0f, -1.1f, 0.2f);
+  EXPECT_NEAR(2.0f, 3.0f, 1.0f);
+  EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0f,1.5f, 0.25f),  // NOLINT
+                          "The difference between 1.0f and 1.5f is 0.5, "
+                          "which exceeds 0.25f");
+  // To work around a bug in gcc 2.95.0, there is intentionally no
+  // space after the first comma in the previous line.
+}
+
+// Tests ASSERT_NEAR.
+TEST_F(FloatTest, ASSERT_NEAR) {
+  ASSERT_NEAR(-1.0f, -1.1f, 0.2f);
+  ASSERT_NEAR(2.0f, 3.0f, 1.0f);
+  EXPECT_FATAL_FAILURE(ASSERT_NEAR(1.0f,1.5f, 0.25f),  // NOLINT
+                       "The difference between 1.0f and 1.5f is 0.5, "
+                       "which exceeds 0.25f");
+  // To work around a bug in gcc 2.95.0, there is intentionally no
+  // space after the first comma in the previous line.
+}
+
+// Tests the cases where FloatLE() should succeed.
+TEST_F(FloatTest, FloatLESucceeds) {
+  EXPECT_PRED_FORMAT2(FloatLE, 1.0f, 2.0f);  // When val1 < val2,
+  ASSERT_PRED_FORMAT2(FloatLE, 1.0f, 1.0f);  // val1 == val2,
+
+  // or when val1 is greater than, but almost equals to, val2.
+  EXPECT_PRED_FORMAT2(FloatLE, values_.close_to_positive_zero, 0.0f);
+}
+
+// Tests the cases where FloatLE() should fail.
+TEST_F(FloatTest, FloatLEFails) {
+  // When val1 is greater than val2 by a large margin,
+  EXPECT_NONFATAL_FAILURE(EXPECT_PRED_FORMAT2(FloatLE, 2.0f, 1.0f),
+                          "(2.0f) <= (1.0f)");
+
+  // or by a small yet non-negligible margin,
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT2(FloatLE, values_.further_from_one, 1.0f);
+  }, "(values_.further_from_one) <= (1.0f)");
+
+#if !GTEST_OS_SYMBIAN && !defined(__BORLANDC__)
+  // Nokia's STLport crashes if we try to output infinity or NaN.
+  // C++Builder gives bad results for ordered comparisons involving NaNs
+  // due to compiler bugs.
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT2(FloatLE, values_.nan1, values_.infinity);
+  }, "(values_.nan1) <= (values_.infinity)");
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT2(FloatLE, -values_.infinity, values_.nan1);
+  }, "(-values_.infinity) <= (values_.nan1)");
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT2(FloatLE, values_.nan1, values_.nan1);
+  }, "(values_.nan1) <= (values_.nan1)");
+#endif  // !GTEST_OS_SYMBIAN && !defined(__BORLANDC__)
+}
+
+// Instantiates FloatingPointTest for testing *_DOUBLE_EQ.
+typedef FloatingPointTest<double> DoubleTest;
+
+// Tests that the size of Double::Bits matches the size of double.
+TEST_F(DoubleTest, Size) {
+  TestSize();
+}
+
+// Tests comparing with +0 and -0.
+TEST_F(DoubleTest, Zeros) {
+  EXPECT_DOUBLE_EQ(0.0, -0.0);
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(-0.0, 1.0),
+                          "1.0");
+  EXPECT_FATAL_FAILURE(ASSERT_DOUBLE_EQ(0.0, 1.0),
+                       "1.0");
+}
+
+// Tests comparing numbers close to 0.
+//
+// This ensures that *_DOUBLE_EQ handles the sign correctly and no
+// overflow occurs when comparing numbers whose absolute value is very
+// small.
+TEST_F(DoubleTest, AlmostZeros) {
+  // In C++Builder, names within local classes (such as used by
+  // EXPECT_FATAL_FAILURE) cannot be resolved against static members of the
+  // scoping class.  Use a static local alias as a workaround.
+  // We use the assignment syntax since some compilers, like Sun Studio,
+  // don't allow initializing references using construction syntax
+  // (parentheses).
+  static const DoubleTest::TestValues& v = this->values_;
+
+  EXPECT_DOUBLE_EQ(0.0, v.close_to_positive_zero);
+  EXPECT_DOUBLE_EQ(-0.0, v.close_to_negative_zero);
+  EXPECT_DOUBLE_EQ(v.close_to_positive_zero, v.close_to_negative_zero);
+
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_DOUBLE_EQ(v.close_to_positive_zero,
+                     v.further_from_negative_zero);
+  }, "v.further_from_negative_zero");
+}
+
+// Tests comparing numbers close to each other.
+TEST_F(DoubleTest, SmallDiff) {
+  EXPECT_DOUBLE_EQ(1.0, values_.close_to_one);
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(1.0, values_.further_from_one),
+                          "values_.further_from_one");
+}
+
+// Tests comparing numbers far apart.
+TEST_F(DoubleTest, LargeDiff) {
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(2.0, 3.0),
+                          "3.0");
+}
+
+// Tests comparing with infinity.
+//
+// This ensures that no overflow occurs when comparing numbers whose
+// absolute value is very large.
+TEST_F(DoubleTest, Infinity) {
+  EXPECT_DOUBLE_EQ(values_.infinity, values_.close_to_infinity);
+  EXPECT_DOUBLE_EQ(-values_.infinity, -values_.close_to_infinity);
+#if !GTEST_OS_SYMBIAN
+  // Nokia's STLport crashes if we try to output infinity or NaN.
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(values_.infinity, -values_.infinity),
+                          "-values_.infinity");
+
+  // This is interesting as the representations of infinity_ and nan1_
+  // are only 1 DLP apart.
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(values_.infinity, values_.nan1),
+                          "values_.nan1");
+#endif  // !GTEST_OS_SYMBIAN
+}
+
+// Tests that comparing with NAN always returns false.
+TEST_F(DoubleTest, NaN) {
+#if !GTEST_OS_SYMBIAN
+  // In C++Builder, names within local classes (such as used by
+  // EXPECT_FATAL_FAILURE) cannot be resolved against static members of the
+  // scoping class.  Use a static local alias as a workaround.
+  // We use the assignment syntax since some compilers, like Sun Studio,
+  // don't allow initializing references using construction syntax
+  // (parentheses).
+  static const DoubleTest::TestValues& v = this->values_;
+
+  // Nokia's STLport crashes if we try to output infinity or NaN.
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(v.nan1, v.nan1),
+                          "v.nan1");
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(v.nan1, v.nan2), "v.nan2");
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(1.0, v.nan1), "v.nan1");
+  EXPECT_FATAL_FAILURE(ASSERT_DOUBLE_EQ(v.nan1, v.infinity),
+                       "v.infinity");
+#endif  // !GTEST_OS_SYMBIAN
+}
+
+// Tests that *_DOUBLE_EQ are reflexive.
+TEST_F(DoubleTest, Reflexive) {
+  EXPECT_DOUBLE_EQ(0.0, 0.0);
+  EXPECT_DOUBLE_EQ(1.0, 1.0);
+#if !GTEST_OS_SYMBIAN
+  // Nokia's STLport crashes if we try to output infinity or NaN.
+  ASSERT_DOUBLE_EQ(values_.infinity, values_.infinity);
+#endif  // !GTEST_OS_SYMBIAN
+}
+
+// Tests that *_DOUBLE_EQ are commutative.
+TEST_F(DoubleTest, Commutative) {
+  // We already tested EXPECT_DOUBLE_EQ(1.0, values_.close_to_one).
+  EXPECT_DOUBLE_EQ(values_.close_to_one, 1.0);
+
+  // We already tested EXPECT_DOUBLE_EQ(1.0, values_.further_from_one).
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(values_.further_from_one, 1.0),
+                          "1.0");
+}
+
+// Tests EXPECT_NEAR.
+TEST_F(DoubleTest, EXPECT_NEAR) {
+  EXPECT_NEAR(-1.0, -1.1, 0.2);
+  EXPECT_NEAR(2.0, 3.0, 1.0);
+  EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0, 1.5, 0.25),  // NOLINT
+                          "The difference between 1.0 and 1.5 is 0.5, "
+                          "which exceeds 0.25");
+  // To work around a bug in gcc 2.95.0, there is intentionally no
+  // space after the first comma in the previous statement.
+}
+
+// Tests ASSERT_NEAR.
+TEST_F(DoubleTest, ASSERT_NEAR) {
+  ASSERT_NEAR(-1.0, -1.1, 0.2);
+  ASSERT_NEAR(2.0, 3.0, 1.0);
+  EXPECT_FATAL_FAILURE(ASSERT_NEAR(1.0, 1.5, 0.25),  // NOLINT
+                       "The difference between 1.0 and 1.5 is 0.5, "
+                       "which exceeds 0.25");
+  // To work around a bug in gcc 2.95.0, there is intentionally no
+  // space after the first comma in the previous statement.
+}
+
+// Tests the cases where DoubleLE() should succeed.
+TEST_F(DoubleTest, DoubleLESucceeds) {
+  EXPECT_PRED_FORMAT2(DoubleLE, 1.0, 2.0);  // When val1 < val2,
+  ASSERT_PRED_FORMAT2(DoubleLE, 1.0, 1.0);  // val1 == val2,
+
+  // or when val1 is greater than, but almost equals to, val2.
+  EXPECT_PRED_FORMAT2(DoubleLE, values_.close_to_positive_zero, 0.0);
+}
+
+// Tests the cases where DoubleLE() should fail.
+TEST_F(DoubleTest, DoubleLEFails) {
+  // When val1 is greater than val2 by a large margin,
+  EXPECT_NONFATAL_FAILURE(EXPECT_PRED_FORMAT2(DoubleLE, 2.0, 1.0),
+                          "(2.0) <= (1.0)");
+
+  // or by a small yet non-negligible margin,
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT2(DoubleLE, values_.further_from_one, 1.0);
+  }, "(values_.further_from_one) <= (1.0)");
+
+#if !GTEST_OS_SYMBIAN && !defined(__BORLANDC__)
+  // Nokia's STLport crashes if we try to output infinity or NaN.
+  // C++Builder gives bad results for ordered comparisons involving NaNs
+  // due to compiler bugs.
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT2(DoubleLE, values_.nan1, values_.infinity);
+  }, "(values_.nan1) <= (values_.infinity)");
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT2(DoubleLE, -values_.infinity, values_.nan1);
+  }, " (-values_.infinity) <= (values_.nan1)");
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT2(DoubleLE, values_.nan1, values_.nan1);
+  }, "(values_.nan1) <= (values_.nan1)");
+#endif  // !GTEST_OS_SYMBIAN && !defined(__BORLANDC__)
+}
+
+
+// Verifies that a test or test case whose name starts with DISABLED_ is
+// not run.
+
+// A test whose name starts with DISABLED_.
+// Should not run.
+TEST(DisabledTest, DISABLED_TestShouldNotRun) {
+  FAIL() << "Unexpected failure: Disabled test should not be run.";
+}
+
+// A test whose name does not start with DISABLED_.
+// Should run.
+TEST(DisabledTest, NotDISABLED_TestShouldRun) {
+  EXPECT_EQ(1, 1);
+}
+
+// A test case whose name starts with DISABLED_.
+// Should not run.
+TEST(DISABLED_TestCase, TestShouldNotRun) {
+  FAIL() << "Unexpected failure: Test in disabled test case should not be run.";
+}
+
+// A test case and test whose names start with DISABLED_.
+// Should not run.
+TEST(DISABLED_TestCase, DISABLED_TestShouldNotRun) {
+  FAIL() << "Unexpected failure: Test in disabled test case should not be run.";
+}
+
+// Check that when all tests in a test case are disabled, SetupTestCase() and
+// TearDownTestCase() are not called.
+class DisabledTestsTest : public Test {
+ protected:
+  static void SetUpTestCase() {
+    FAIL() << "Unexpected failure: All tests disabled in test case. "
+              "SetupTestCase() should not be called.";
+  }
+
+  static void TearDownTestCase() {
+    FAIL() << "Unexpected failure: All tests disabled in test case. "
+              "TearDownTestCase() should not be called.";
+  }
+};
+
+TEST_F(DisabledTestsTest, DISABLED_TestShouldNotRun_1) {
+  FAIL() << "Unexpected failure: Disabled test should not be run.";
+}
+
+TEST_F(DisabledTestsTest, DISABLED_TestShouldNotRun_2) {
+  FAIL() << "Unexpected failure: Disabled test should not be run.";
+}
+
+// Tests that disabled typed tests aren't run.
+
+#if GTEST_HAS_TYPED_TEST
+
+template <typename T>
+class TypedTest : public Test {
+};
+
+typedef testing::Types<int, double> NumericTypes;
+TYPED_TEST_CASE(TypedTest, NumericTypes);
+
+TYPED_TEST(TypedTest, DISABLED_ShouldNotRun) {
+  FAIL() << "Unexpected failure: Disabled typed test should not run.";
+}
+
+template <typename T>
+class DISABLED_TypedTest : public Test {
+};
+
+TYPED_TEST_CASE(DISABLED_TypedTest, NumericTypes);
+
+TYPED_TEST(DISABLED_TypedTest, ShouldNotRun) {
+  FAIL() << "Unexpected failure: Disabled typed test should not run.";
+}
+
+#endif  // GTEST_HAS_TYPED_TEST
+
+// Tests that disabled type-parameterized tests aren't run.
+
+#if GTEST_HAS_TYPED_TEST_P
+
+template <typename T>
+class TypedTestP : public Test {
+};
+
+TYPED_TEST_CASE_P(TypedTestP);
+
+TYPED_TEST_P(TypedTestP, DISABLED_ShouldNotRun) {
+  FAIL() << "Unexpected failure: "
+         << "Disabled type-parameterized test should not run.";
+}
+
+REGISTER_TYPED_TEST_CASE_P(TypedTestP, DISABLED_ShouldNotRun);
+
+INSTANTIATE_TYPED_TEST_CASE_P(My, TypedTestP, NumericTypes);
+
+template <typename T>
+class DISABLED_TypedTestP : public Test {
+};
+
+TYPED_TEST_CASE_P(DISABLED_TypedTestP);
+
+TYPED_TEST_P(DISABLED_TypedTestP, ShouldNotRun) {
+  FAIL() << "Unexpected failure: "
+         << "Disabled type-parameterized test should not run.";
+}
+
+REGISTER_TYPED_TEST_CASE_P(DISABLED_TypedTestP, ShouldNotRun);
+
+INSTANTIATE_TYPED_TEST_CASE_P(My, DISABLED_TypedTestP, NumericTypes);
+
+#endif  // GTEST_HAS_TYPED_TEST_P
+
+// Tests that assertion macros evaluate their arguments exactly once.
+
+class SingleEvaluationTest : public Test {
+ public:  // Must be public and not protected due to a bug in g++ 3.4.2.
+  // This helper function is needed by the FailedASSERT_STREQ test
+  // below.  It's public to work around C++Builder's bug with scoping local
+  // classes.
+  static void CompareAndIncrementCharPtrs() {
+    ASSERT_STREQ(p1_++, p2_++);
+  }
+
+  // This helper function is needed by the FailedASSERT_NE test below.  It's
+  // public to work around C++Builder's bug with scoping local classes.
+  static void CompareAndIncrementInts() {
+    ASSERT_NE(a_++, b_++);
+  }
+
+ protected:
+  SingleEvaluationTest() {
+    p1_ = s1_;
+    p2_ = s2_;
+    a_ = 0;
+    b_ = 0;
+  }
+
+  static const char* const s1_;
+  static const char* const s2_;
+  static const char* p1_;
+  static const char* p2_;
+
+  static int a_;
+  static int b_;
+};
+
+const char* const SingleEvaluationTest::s1_ = "01234";
+const char* const SingleEvaluationTest::s2_ = "abcde";
+const char* SingleEvaluationTest::p1_;
+const char* SingleEvaluationTest::p2_;
+int SingleEvaluationTest::a_;
+int SingleEvaluationTest::b_;
+
+// Tests that when ASSERT_STREQ fails, it evaluates its arguments
+// exactly once.
+TEST_F(SingleEvaluationTest, FailedASSERT_STREQ) {
+  EXPECT_FATAL_FAILURE(SingleEvaluationTest::CompareAndIncrementCharPtrs(),
+                       "p2_++");
+  EXPECT_EQ(s1_ + 1, p1_);
+  EXPECT_EQ(s2_ + 1, p2_);
+}
+
+// Tests that string assertion arguments are evaluated exactly once.
+TEST_F(SingleEvaluationTest, ASSERT_STR) {
+  // successful EXPECT_STRNE
+  EXPECT_STRNE(p1_++, p2_++);
+  EXPECT_EQ(s1_ + 1, p1_);
+  EXPECT_EQ(s2_ + 1, p2_);
+
+  // failed EXPECT_STRCASEEQ
+  EXPECT_NONFATAL_FAILURE(EXPECT_STRCASEEQ(p1_++, p2_++),
+                          "ignoring case");
+  EXPECT_EQ(s1_ + 2, p1_);
+  EXPECT_EQ(s2_ + 2, p2_);
+}
+
+// Tests that when ASSERT_NE fails, it evaluates its arguments exactly
+// once.
+TEST_F(SingleEvaluationTest, FailedASSERT_NE) {
+  EXPECT_FATAL_FAILURE(SingleEvaluationTest::CompareAndIncrementInts(),
+                       "(a_++) != (b_++)");
+  EXPECT_EQ(1, a_);
+  EXPECT_EQ(1, b_);
+}
+
+// Tests that assertion arguments are evaluated exactly once.
+TEST_F(SingleEvaluationTest, OtherCases) {
+  // successful EXPECT_TRUE
+  EXPECT_TRUE(0 == a_++);  // NOLINT
+  EXPECT_EQ(1, a_);
+
+  // failed EXPECT_TRUE
+  EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(-1 == a_++), "-1 == a_++");
+  EXPECT_EQ(2, a_);
+
+  // successful EXPECT_GT
+  EXPECT_GT(a_++, b_++);
+  EXPECT_EQ(3, a_);
+  EXPECT_EQ(1, b_);
+
+  // failed EXPECT_LT
+  EXPECT_NONFATAL_FAILURE(EXPECT_LT(a_++, b_++), "(a_++) < (b_++)");
+  EXPECT_EQ(4, a_);
+  EXPECT_EQ(2, b_);
+
+  // successful ASSERT_TRUE
+  ASSERT_TRUE(0 < a_++);  // NOLINT
+  EXPECT_EQ(5, a_);
+
+  // successful ASSERT_GT
+  ASSERT_GT(a_++, b_++);
+  EXPECT_EQ(6, a_);
+  EXPECT_EQ(3, b_);
+}
+
+#if GTEST_HAS_EXCEPTIONS
+
+void ThrowAnInteger() {
+  throw 1;
+}
+
+// Tests that assertion arguments are evaluated exactly once.
+TEST_F(SingleEvaluationTest, ExceptionTests) {
+  // successful EXPECT_THROW
+  EXPECT_THROW({  // NOLINT
+    a_++;
+    ThrowAnInteger();
+  }, int);
+  EXPECT_EQ(1, a_);
+
+  // failed EXPECT_THROW, throws different
+  EXPECT_NONFATAL_FAILURE(EXPECT_THROW({  // NOLINT
+    a_++;
+    ThrowAnInteger();
+  }, bool), "throws a different type");
+  EXPECT_EQ(2, a_);
+
+  // failed EXPECT_THROW, throws nothing
+  EXPECT_NONFATAL_FAILURE(EXPECT_THROW(a_++, bool), "throws nothing");
+  EXPECT_EQ(3, a_);
+
+  // successful EXPECT_NO_THROW
+  EXPECT_NO_THROW(a_++);
+  EXPECT_EQ(4, a_);
+
+  // failed EXPECT_NO_THROW
+  EXPECT_NONFATAL_FAILURE(EXPECT_NO_THROW({  // NOLINT
+    a_++;
+    ThrowAnInteger();
+  }), "it throws");
+  EXPECT_EQ(5, a_);
+
+  // successful EXPECT_ANY_THROW
+  EXPECT_ANY_THROW({  // NOLINT
+    a_++;
+    ThrowAnInteger();
+  });
+  EXPECT_EQ(6, a_);
+
+  // failed EXPECT_ANY_THROW
+  EXPECT_NONFATAL_FAILURE(EXPECT_ANY_THROW(a_++), "it doesn't");
+  EXPECT_EQ(7, a_);
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// Tests {ASSERT|EXPECT}_NO_FATAL_FAILURE.
+class NoFatalFailureTest : public Test {
+ protected:
+  void Succeeds() {}
+  void FailsNonFatal() {
+    ADD_FAILURE() << "some non-fatal failure";
+  }
+  void Fails() {
+    FAIL() << "some fatal failure";
+  }
+
+  void DoAssertNoFatalFailureOnFails() {
+    ASSERT_NO_FATAL_FAILURE(Fails());
+    ADD_FAILURE() << "shold not reach here.";
+  }
+
+  void DoExpectNoFatalFailureOnFails() {
+    EXPECT_NO_FATAL_FAILURE(Fails());
+    ADD_FAILURE() << "other failure";
+  }
+};
+
+TEST_F(NoFatalFailureTest, NoFailure) {
+  EXPECT_NO_FATAL_FAILURE(Succeeds());
+  ASSERT_NO_FATAL_FAILURE(Succeeds());
+}
+
+TEST_F(NoFatalFailureTest, NonFatalIsNoFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_NO_FATAL_FAILURE(FailsNonFatal()),
+      "some non-fatal failure");
+  EXPECT_NONFATAL_FAILURE(
+      ASSERT_NO_FATAL_FAILURE(FailsNonFatal()),
+      "some non-fatal failure");
+}
+
+TEST_F(NoFatalFailureTest, AssertNoFatalFailureOnFatalFailure) {
+  TestPartResultArray gtest_failures;
+  {
+    ScopedFakeTestPartResultReporter gtest_reporter(&gtest_failures);
+    DoAssertNoFatalFailureOnFails();
+  }
+  ASSERT_EQ(2, gtest_failures.size());
+  EXPECT_EQ(TestPartResult::kFatalFailure,
+            gtest_failures.GetTestPartResult(0).type());
+  EXPECT_EQ(TestPartResult::kFatalFailure,
+            gtest_failures.GetTestPartResult(1).type());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "some fatal failure",
+                      gtest_failures.GetTestPartResult(0).message());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "it does",
+                      gtest_failures.GetTestPartResult(1).message());
+}
+
+TEST_F(NoFatalFailureTest, ExpectNoFatalFailureOnFatalFailure) {
+  TestPartResultArray gtest_failures;
+  {
+    ScopedFakeTestPartResultReporter gtest_reporter(&gtest_failures);
+    DoExpectNoFatalFailureOnFails();
+  }
+  ASSERT_EQ(3, gtest_failures.size());
+  EXPECT_EQ(TestPartResult::kFatalFailure,
+            gtest_failures.GetTestPartResult(0).type());
+  EXPECT_EQ(TestPartResult::kNonFatalFailure,
+            gtest_failures.GetTestPartResult(1).type());
+  EXPECT_EQ(TestPartResult::kNonFatalFailure,
+            gtest_failures.GetTestPartResult(2).type());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "some fatal failure",
+                      gtest_failures.GetTestPartResult(0).message());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "it does",
+                      gtest_failures.GetTestPartResult(1).message());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "other failure",
+                      gtest_failures.GetTestPartResult(2).message());
+}
+
+TEST_F(NoFatalFailureTest, MessageIsStreamable) {
+  TestPartResultArray gtest_failures;
+  {
+    ScopedFakeTestPartResultReporter gtest_reporter(&gtest_failures);
+    EXPECT_NO_FATAL_FAILURE(FAIL() << "foo") << "my message";
+  }
+  ASSERT_EQ(2, gtest_failures.size());
+  EXPECT_EQ(TestPartResult::kNonFatalFailure,
+            gtest_failures.GetTestPartResult(0).type());
+  EXPECT_EQ(TestPartResult::kNonFatalFailure,
+            gtest_failures.GetTestPartResult(1).type());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "foo",
+                      gtest_failures.GetTestPartResult(0).message());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "my message",
+                      gtest_failures.GetTestPartResult(1).message());
+}
+
+// Tests non-string assertions.
+
+std::string EditsToString(const std::vector<EditType>& edits) {
+  std::string out;
+  for (size_t i = 0; i < edits.size(); ++i) {
+    static const char kEdits[] = " +-/";
+    out.append(1, kEdits[edits[i]]);
+  }
+  return out;
+}
+
+std::vector<size_t> CharsToIndices(const std::string& str) {
+  std::vector<size_t> out;
+  for (size_t i = 0; i < str.size(); ++i) {
+    out.push_back(str[i]);
+  }
+  return out;
+}
+
+std::vector<std::string> CharsToLines(const std::string& str) {
+  std::vector<std::string> out;
+  for (size_t i = 0; i < str.size(); ++i) {
+    out.push_back(str.substr(i, 1));
+  }
+  return out;
+}
+
+TEST(EditDistance, TestCases) {
+  struct Case {
+    int line;
+    const char* left;
+    const char* right;
+    const char* expected_edits;
+    const char* expected_diff;
+  };
+  static const Case kCases[] = {
+      // No change.
+      {__LINE__, "A", "A", " ", ""},
+      {__LINE__, "ABCDE", "ABCDE", "     ", ""},
+      // Simple adds.
+      {__LINE__, "X", "XA", " +", "@@ +1,2 @@\n X\n+A\n"},
+      {__LINE__, "X", "XABCD", " ++++", "@@ +1,5 @@\n X\n+A\n+B\n+C\n+D\n"},
+      // Simple removes.
+      {__LINE__, "XA", "X", " -", "@@ -1,2 @@\n X\n-A\n"},
+      {__LINE__, "XABCD", "X", " ----", "@@ -1,5 @@\n X\n-A\n-B\n-C\n-D\n"},
+      // Simple replaces.
+      {__LINE__, "A", "a", "/", "@@ -1,1 +1,1 @@\n-A\n+a\n"},
+      {__LINE__, "ABCD", "abcd", "////",
+       "@@ -1,4 +1,4 @@\n-A\n-B\n-C\n-D\n+a\n+b\n+c\n+d\n"},
+      // Path finding.
+      {__LINE__, "ABCDEFGH", "ABXEGH1", "  -/ -  +",
+       "@@ -1,8 +1,7 @@\n A\n B\n-C\n-D\n+X\n E\n-F\n G\n H\n+1\n"},
+      {__LINE__, "AAAABCCCC", "ABABCDCDC", "- /   + / ",
+       "@@ -1,9 +1,9 @@\n-A\n A\n-A\n+B\n A\n B\n C\n+D\n C\n-C\n+D\n C\n"},
+      {__LINE__, "ABCDE", "BCDCD", "-   +/",
+       "@@ -1,5 +1,5 @@\n-A\n B\n C\n D\n-E\n+C\n+D\n"},
+      {__LINE__, "ABCDEFGHIJKL", "BCDCDEFGJKLJK", "- ++     --   ++",
+       "@@ -1,4 +1,5 @@\n-A\n B\n+C\n+D\n C\n D\n"
+       "@@ -6,7 +7,7 @@\n F\n G\n-H\n-I\n J\n K\n L\n+J\n+K\n"},
+      {}};
+  for (const Case* c = kCases; c->left; ++c) {
+    EXPECT_TRUE(c->expected_edits ==
+                EditsToString(CalculateOptimalEdits(CharsToIndices(c->left),
+                                                    CharsToIndices(c->right))))
+        << "Left <" << c->left << "> Right <" << c->right << "> Edits <"
+        << EditsToString(CalculateOptimalEdits(
+               CharsToIndices(c->left), CharsToIndices(c->right))) << ">";
+    EXPECT_TRUE(c->expected_diff == CreateUnifiedDiff(CharsToLines(c->left),
+                                                      CharsToLines(c->right)))
+        << "Left <" << c->left << "> Right <" << c->right << "> Diff <"
+        << CreateUnifiedDiff(CharsToLines(c->left), CharsToLines(c->right))
+        << ">";
+  }
+}
+
+// Tests EqFailure(), used for implementing *EQ* assertions.
+TEST(AssertionTest, EqFailure) {
+  const std::string foo_val("5"), bar_val("6");
+  const std::string msg1(
+      EqFailure("foo", "bar", foo_val, bar_val, false)
+      .failure_message());
+  EXPECT_STREQ(
+      "Value of: bar\n"
+      "  Actual: 6\n"
+      "Expected: foo\n"
+      "Which is: 5",
+      msg1.c_str());
+
+  const std::string msg2(
+      EqFailure("foo", "6", foo_val, bar_val, false)
+      .failure_message());
+  EXPECT_STREQ(
+      "Value of: 6\n"
+      "Expected: foo\n"
+      "Which is: 5",
+      msg2.c_str());
+
+  const std::string msg3(
+      EqFailure("5", "bar", foo_val, bar_val, false)
+      .failure_message());
+  EXPECT_STREQ(
+      "Value of: bar\n"
+      "  Actual: 6\n"
+      "Expected: 5",
+      msg3.c_str());
+
+  const std::string msg4(
+      EqFailure("5", "6", foo_val, bar_val, false).failure_message());
+  EXPECT_STREQ(
+      "Value of: 6\n"
+      "Expected: 5",
+      msg4.c_str());
+
+  const std::string msg5(
+      EqFailure("foo", "bar",
+                std::string("\"x\""), std::string("\"y\""),
+                true).failure_message());
+  EXPECT_STREQ(
+      "Value of: bar\n"
+      "  Actual: \"y\"\n"
+      "Expected: foo (ignoring case)\n"
+      "Which is: \"x\"",
+      msg5.c_str());
+}
+
+TEST(AssertionTest, EqFailureWithDiff) {
+  const std::string left(
+      "1\\n2XXX\\n3\\n5\\n6\\n7\\n8\\n9\\n10\\n11\\n12XXX\\n13\\n14\\n15");
+  const std::string right(
+      "1\\n2\\n3\\n4\\n5\\n6\\n7\\n8\\n9\\n11\\n12\\n13\\n14");
+  const std::string msg1(
+      EqFailure("left", "right", left, right, false).failure_message());
+  EXPECT_STREQ(
+      "Value of: right\n"
+      "  Actual: 1\\n2\\n3\\n4\\n5\\n6\\n7\\n8\\n9\\n11\\n12\\n13\\n14\n"
+      "Expected: left\n"
+      "Which is: "
+      "1\\n2XXX\\n3\\n5\\n6\\n7\\n8\\n9\\n10\\n11\\n12XXX\\n13\\n14\\n15\n"
+      "With diff:\n@@ -1,5 +1,6 @@\n 1\n-2XXX\n+2\n 3\n+4\n 5\n 6\n"
+      "@@ -7,8 +8,6 @@\n 8\n 9\n-10\n 11\n-12XXX\n+12\n 13\n 14\n-15\n",
+      msg1.c_str());
+}
+
+// Tests AppendUserMessage(), used for implementing the *EQ* macros.
+TEST(AssertionTest, AppendUserMessage) {
+  const std::string foo("foo");
+
+  Message msg;
+  EXPECT_STREQ("foo",
+               AppendUserMessage(foo, msg).c_str());
+
+  msg << "bar";
+  EXPECT_STREQ("foo\nbar",
+               AppendUserMessage(foo, msg).c_str());
+}
+
+#ifdef __BORLANDC__
+// Silences warnings: "Condition is always true", "Unreachable code"
+# pragma option push -w-ccc -w-rch
+#endif
+
+// Tests ASSERT_TRUE.
+TEST(AssertionTest, ASSERT_TRUE) {
+  ASSERT_TRUE(2 > 1);  // NOLINT
+  EXPECT_FATAL_FAILURE(ASSERT_TRUE(2 < 1),
+                       "2 < 1");
+}
+
+// Tests ASSERT_TRUE(predicate) for predicates returning AssertionResult.
+TEST(AssertionTest, AssertTrueWithAssertionResult) {
+  ASSERT_TRUE(ResultIsEven(2));
+#ifndef __BORLANDC__
+  // ICE's in C++Builder.
+  EXPECT_FATAL_FAILURE(ASSERT_TRUE(ResultIsEven(3)),
+                       "Value of: ResultIsEven(3)\n"
+                       "  Actual: false (3 is odd)\n"
+                       "Expected: true");
+#endif
+  ASSERT_TRUE(ResultIsEvenNoExplanation(2));
+  EXPECT_FATAL_FAILURE(ASSERT_TRUE(ResultIsEvenNoExplanation(3)),
+                       "Value of: ResultIsEvenNoExplanation(3)\n"
+                       "  Actual: false (3 is odd)\n"
+                       "Expected: true");
+}
+
+// Tests ASSERT_FALSE.
+TEST(AssertionTest, ASSERT_FALSE) {
+  ASSERT_FALSE(2 < 1);  // NOLINT
+  EXPECT_FATAL_FAILURE(ASSERT_FALSE(2 > 1),
+                       "Value of: 2 > 1\n"
+                       "  Actual: true\n"
+                       "Expected: false");
+}
+
+// Tests ASSERT_FALSE(predicate) for predicates returning AssertionResult.
+TEST(AssertionTest, AssertFalseWithAssertionResult) {
+  ASSERT_FALSE(ResultIsEven(3));
+#ifndef __BORLANDC__
+  // ICE's in C++Builder.
+  EXPECT_FATAL_FAILURE(ASSERT_FALSE(ResultIsEven(2)),
+                       "Value of: ResultIsEven(2)\n"
+                       "  Actual: true (2 is even)\n"
+                       "Expected: false");
+#endif
+  ASSERT_FALSE(ResultIsEvenNoExplanation(3));
+  EXPECT_FATAL_FAILURE(ASSERT_FALSE(ResultIsEvenNoExplanation(2)),
+                       "Value of: ResultIsEvenNoExplanation(2)\n"
+                       "  Actual: true\n"
+                       "Expected: false");
+}
+
+#ifdef __BORLANDC__
+// Restores warnings after previous "#pragma option push" supressed them
+# pragma option pop
+#endif
+
+// Tests using ASSERT_EQ on double values.  The purpose is to make
+// sure that the specialization we did for integer and anonymous enums
+// isn't used for double arguments.
+TEST(ExpectTest, ASSERT_EQ_Double) {
+  // A success.
+  ASSERT_EQ(5.6, 5.6);
+
+  // A failure.
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(5.1, 5.2),
+                       "5.1");
+}
+
+// Tests ASSERT_EQ.
+TEST(AssertionTest, ASSERT_EQ) {
+  ASSERT_EQ(5, 2 + 3);
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(5, 2*3),
+                       "Value of: 2*3\n"
+                       "  Actual: 6\n"
+                       "Expected: 5");
+}
+
+// Tests ASSERT_EQ(NULL, pointer).
+#if GTEST_CAN_COMPARE_NULL
+TEST(AssertionTest, ASSERT_EQ_NULL) {
+  // A success.
+  const char* p = NULL;
+  // Some older GCC versions may issue a spurious waring in this or the next
+  // assertion statement. This warning should not be suppressed with
+  // static_cast since the test verifies the ability to use bare NULL as the
+  // expected parameter to the macro.
+  ASSERT_EQ(NULL, p);
+
+  // A failure.
+  static int n = 0;
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(NULL, &n),
+                       "Value of: &n\n");
+}
+#endif  // GTEST_CAN_COMPARE_NULL
+
+// Tests ASSERT_EQ(0, non_pointer).  Since the literal 0 can be
+// treated as a null pointer by the compiler, we need to make sure
+// that ASSERT_EQ(0, non_pointer) isn't interpreted by Google Test as
+// ASSERT_EQ(static_cast<void*>(NULL), non_pointer).
+TEST(ExpectTest, ASSERT_EQ_0) {
+  int n = 0;
+
+  // A success.
+  ASSERT_EQ(0, n);
+
+  // A failure.
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(0, 5.6),
+                       "Expected: 0");
+}
+
+// Tests ASSERT_NE.
+TEST(AssertionTest, ASSERT_NE) {
+  ASSERT_NE(6, 7);
+  EXPECT_FATAL_FAILURE(ASSERT_NE('a', 'a'),
+                       "Expected: ('a') != ('a'), "
+                       "actual: 'a' (97, 0x61) vs 'a' (97, 0x61)");
+}
+
+// Tests ASSERT_LE.
+TEST(AssertionTest, ASSERT_LE) {
+  ASSERT_LE(2, 3);
+  ASSERT_LE(2, 2);
+  EXPECT_FATAL_FAILURE(ASSERT_LE(2, 0),
+                       "Expected: (2) <= (0), actual: 2 vs 0");
+}
+
+// Tests ASSERT_LT.
+TEST(AssertionTest, ASSERT_LT) {
+  ASSERT_LT(2, 3);
+  EXPECT_FATAL_FAILURE(ASSERT_LT(2, 2),
+                       "Expected: (2) < (2), actual: 2 vs 2");
+}
+
+// Tests ASSERT_GE.
+TEST(AssertionTest, ASSERT_GE) {
+  ASSERT_GE(2, 1);
+  ASSERT_GE(2, 2);
+  EXPECT_FATAL_FAILURE(ASSERT_GE(2, 3),
+                       "Expected: (2) >= (3), actual: 2 vs 3");
+}
+
+// Tests ASSERT_GT.
+TEST(AssertionTest, ASSERT_GT) {
+  ASSERT_GT(2, 1);
+  EXPECT_FATAL_FAILURE(ASSERT_GT(2, 2),
+                       "Expected: (2) > (2), actual: 2 vs 2");
+}
+
+#if GTEST_HAS_EXCEPTIONS
+
+void ThrowNothing() {}
+
+// Tests ASSERT_THROW.
+TEST(AssertionTest, ASSERT_THROW) {
+  ASSERT_THROW(ThrowAnInteger(), int);
+
+# ifndef __BORLANDC__
+
+  // ICE's in C++Builder 2007 and 2009.
+  EXPECT_FATAL_FAILURE(
+      ASSERT_THROW(ThrowAnInteger(), bool),
+      "Expected: ThrowAnInteger() throws an exception of type bool.\n"
+      "  Actual: it throws a different type.");
+# endif
+
+  EXPECT_FATAL_FAILURE(
+      ASSERT_THROW(ThrowNothing(), bool),
+      "Expected: ThrowNothing() throws an exception of type bool.\n"
+      "  Actual: it throws nothing.");
+}
+
+// Tests ASSERT_NO_THROW.
+TEST(AssertionTest, ASSERT_NO_THROW) {
+  ASSERT_NO_THROW(ThrowNothing());
+  EXPECT_FATAL_FAILURE(ASSERT_NO_THROW(ThrowAnInteger()),
+                       "Expected: ThrowAnInteger() doesn't throw an exception."
+                       "\n  Actual: it throws.");
+}
+
+// Tests ASSERT_ANY_THROW.
+TEST(AssertionTest, ASSERT_ANY_THROW) {
+  ASSERT_ANY_THROW(ThrowAnInteger());
+  EXPECT_FATAL_FAILURE(
+      ASSERT_ANY_THROW(ThrowNothing()),
+      "Expected: ThrowNothing() throws an exception.\n"
+      "  Actual: it doesn't.");
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// Makes sure we deal with the precedence of <<.  This test should
+// compile.
+TEST(AssertionTest, AssertPrecedence) {
+  ASSERT_EQ(1 < 2, true);
+  bool false_value = false;
+  ASSERT_EQ(true && false_value, false);
+}
+
+// A subroutine used by the following test.
+void TestEq1(int x) {
+  ASSERT_EQ(1, x);
+}
+
+// Tests calling a test subroutine that's not part of a fixture.
+TEST(AssertionTest, NonFixtureSubroutine) {
+  EXPECT_FATAL_FAILURE(TestEq1(2),
+                       "Value of: x");
+}
+
+// An uncopyable class.
+class Uncopyable {
+ public:
+  explicit Uncopyable(int a_value) : value_(a_value) {}
+
+  int value() const { return value_; }
+  bool operator==(const Uncopyable& rhs) const {
+    return value() == rhs.value();
+  }
+ private:
+  // This constructor deliberately has no implementation, as we don't
+  // want this class to be copyable.
+  Uncopyable(const Uncopyable&);  // NOLINT
+
+  int value_;
+};
+
+::std::ostream& operator<<(::std::ostream& os, const Uncopyable& value) {
+  return os << value.value();
+}
+
+
+bool IsPositiveUncopyable(const Uncopyable& x) {
+  return x.value() > 0;
+}
+
+// A subroutine used by the following test.
+void TestAssertNonPositive() {
+  Uncopyable y(-1);
+  ASSERT_PRED1(IsPositiveUncopyable, y);
+}
+// A subroutine used by the following test.
+void TestAssertEqualsUncopyable() {
+  Uncopyable x(5);
+  Uncopyable y(-1);
+  ASSERT_EQ(x, y);
+}
+
+// Tests that uncopyable objects can be used in assertions.
+TEST(AssertionTest, AssertWorksWithUncopyableObject) {
+  Uncopyable x(5);
+  ASSERT_PRED1(IsPositiveUncopyable, x);
+  ASSERT_EQ(x, x);
+  EXPECT_FATAL_FAILURE(TestAssertNonPositive(),
+    "IsPositiveUncopyable(y) evaluates to false, where\ny evaluates to -1");
+  EXPECT_FATAL_FAILURE(TestAssertEqualsUncopyable(),
+    "Value of: y\n  Actual: -1\nExpected: x\nWhich is: 5");
+}
+
+// Tests that uncopyable objects can be used in expects.
+TEST(AssertionTest, ExpectWorksWithUncopyableObject) {
+  Uncopyable x(5);
+  EXPECT_PRED1(IsPositiveUncopyable, x);
+  Uncopyable y(-1);
+  EXPECT_NONFATAL_FAILURE(EXPECT_PRED1(IsPositiveUncopyable, y),
+    "IsPositiveUncopyable(y) evaluates to false, where\ny evaluates to -1");
+  EXPECT_EQ(x, x);
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(x, y),
+    "Value of: y\n  Actual: -1\nExpected: x\nWhich is: 5");
+}
+
+enum NamedEnum {
+  kE1 = 0,
+  kE2 = 1
+};
+
+TEST(AssertionTest, NamedEnum) {
+  EXPECT_EQ(kE1, kE1);
+  EXPECT_LT(kE1, kE2);
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(kE1, kE2), "Which is: 0");
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(kE1, kE2), "Actual: 1");
+}
+
+// The version of gcc used in XCode 2.2 has a bug and doesn't allow
+// anonymous enums in assertions.  Therefore the following test is not
+// done on Mac.
+// Sun Studio and HP aCC also reject this code.
+#if !GTEST_OS_MAC && !defined(__SUNPRO_CC) && !defined(__HP_aCC)
+
+// Tests using assertions with anonymous enums.
+enum {
+  kCaseA = -1,
+
+# if GTEST_OS_LINUX
+
+  // We want to test the case where the size of the anonymous enum is
+  // larger than sizeof(int), to make sure our implementation of the
+  // assertions doesn't truncate the enums.  However, MSVC
+  // (incorrectly) doesn't allow an enum value to exceed the range of
+  // an int, so this has to be conditionally compiled.
+  //
+  // On Linux, kCaseB and kCaseA have the same value when truncated to
+  // int size.  We want to test whether this will confuse the
+  // assertions.
+  kCaseB = testing::internal::kMaxBiggestInt,
+
+# else
+
+  kCaseB = INT_MAX,
+
+# endif  // GTEST_OS_LINUX
+
+  kCaseC = 42
+};
+
+TEST(AssertionTest, AnonymousEnum) {
+# if GTEST_OS_LINUX
+
+  EXPECT_EQ(static_cast<int>(kCaseA), static_cast<int>(kCaseB));
+
+# endif  // GTEST_OS_LINUX
+
+  EXPECT_EQ(kCaseA, kCaseA);
+  EXPECT_NE(kCaseA, kCaseB);
+  EXPECT_LT(kCaseA, kCaseB);
+  EXPECT_LE(kCaseA, kCaseB);
+  EXPECT_GT(kCaseB, kCaseA);
+  EXPECT_GE(kCaseA, kCaseA);
+  EXPECT_NONFATAL_FAILURE(EXPECT_GE(kCaseA, kCaseB),
+                          "(kCaseA) >= (kCaseB)");
+  EXPECT_NONFATAL_FAILURE(EXPECT_GE(kCaseA, kCaseC),
+                          "-1 vs 42");
+
+  ASSERT_EQ(kCaseA, kCaseA);
+  ASSERT_NE(kCaseA, kCaseB);
+  ASSERT_LT(kCaseA, kCaseB);
+  ASSERT_LE(kCaseA, kCaseB);
+  ASSERT_GT(kCaseB, kCaseA);
+  ASSERT_GE(kCaseA, kCaseA);
+
+# ifndef __BORLANDC__
+
+  // ICE's in C++Builder.
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(kCaseA, kCaseB),
+                       "Value of: kCaseB");
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(kCaseA, kCaseC),
+                       "Actual: 42");
+# endif
+
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(kCaseA, kCaseC),
+                       "Which is: -1");
+}
+
+#endif  // !GTEST_OS_MAC && !defined(__SUNPRO_CC)
+
+#if GTEST_OS_WINDOWS
+
+static HRESULT UnexpectedHRESULTFailure() {
+  return E_UNEXPECTED;
+}
+
+static HRESULT OkHRESULTSuccess() {
+  return S_OK;
+}
+
+static HRESULT FalseHRESULTSuccess() {
+  return S_FALSE;
+}
+
+// HRESULT assertion tests test both zero and non-zero
+// success codes as well as failure message for each.
+//
+// Windows CE doesn't support message texts.
+TEST(HRESULTAssertionTest, EXPECT_HRESULT_SUCCEEDED) {
+  EXPECT_HRESULT_SUCCEEDED(S_OK);
+  EXPECT_HRESULT_SUCCEEDED(S_FALSE);
+
+  EXPECT_NONFATAL_FAILURE(EXPECT_HRESULT_SUCCEEDED(UnexpectedHRESULTFailure()),
+    "Expected: (UnexpectedHRESULTFailure()) succeeds.\n"
+    "  Actual: 0x8000FFFF");
+}
+
+TEST(HRESULTAssertionTest, ASSERT_HRESULT_SUCCEEDED) {
+  ASSERT_HRESULT_SUCCEEDED(S_OK);
+  ASSERT_HRESULT_SUCCEEDED(S_FALSE);
+
+  EXPECT_FATAL_FAILURE(ASSERT_HRESULT_SUCCEEDED(UnexpectedHRESULTFailure()),
+    "Expected: (UnexpectedHRESULTFailure()) succeeds.\n"
+    "  Actual: 0x8000FFFF");
+}
+
+TEST(HRESULTAssertionTest, EXPECT_HRESULT_FAILED) {
+  EXPECT_HRESULT_FAILED(E_UNEXPECTED);
+
+  EXPECT_NONFATAL_FAILURE(EXPECT_HRESULT_FAILED(OkHRESULTSuccess()),
+    "Expected: (OkHRESULTSuccess()) fails.\n"
+    "  Actual: 0x0");
+  EXPECT_NONFATAL_FAILURE(EXPECT_HRESULT_FAILED(FalseHRESULTSuccess()),
+    "Expected: (FalseHRESULTSuccess()) fails.\n"
+    "  Actual: 0x1");
+}
+
+TEST(HRESULTAssertionTest, ASSERT_HRESULT_FAILED) {
+  ASSERT_HRESULT_FAILED(E_UNEXPECTED);
+
+# ifndef __BORLANDC__
+
+  // ICE's in C++Builder 2007 and 2009.
+  EXPECT_FATAL_FAILURE(ASSERT_HRESULT_FAILED(OkHRESULTSuccess()),
+    "Expected: (OkHRESULTSuccess()) fails.\n"
+    "  Actual: 0x0");
+# endif
+
+  EXPECT_FATAL_FAILURE(ASSERT_HRESULT_FAILED(FalseHRESULTSuccess()),
+    "Expected: (FalseHRESULTSuccess()) fails.\n"
+    "  Actual: 0x1");
+}
+
+// Tests that streaming to the HRESULT macros works.
+TEST(HRESULTAssertionTest, Streaming) {
+  EXPECT_HRESULT_SUCCEEDED(S_OK) << "unexpected failure";
+  ASSERT_HRESULT_SUCCEEDED(S_OK) << "unexpected failure";
+  EXPECT_HRESULT_FAILED(E_UNEXPECTED) << "unexpected failure";
+  ASSERT_HRESULT_FAILED(E_UNEXPECTED) << "unexpected failure";
+
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_HRESULT_SUCCEEDED(E_UNEXPECTED) << "expected failure",
+      "expected failure");
+
+# ifndef __BORLANDC__
+
+  // ICE's in C++Builder 2007 and 2009.
+  EXPECT_FATAL_FAILURE(
+      ASSERT_HRESULT_SUCCEEDED(E_UNEXPECTED) << "expected failure",
+      "expected failure");
+# endif
+
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_HRESULT_FAILED(S_OK) << "expected failure",
+      "expected failure");
+
+  EXPECT_FATAL_FAILURE(
+      ASSERT_HRESULT_FAILED(S_OK) << "expected failure",
+      "expected failure");
+}
+
+#endif  // GTEST_OS_WINDOWS
+
+#ifdef __BORLANDC__
+// Silences warnings: "Condition is always true", "Unreachable code"
+# pragma option push -w-ccc -w-rch
+#endif
+
+// Tests that the assertion macros behave like single statements.
+TEST(AssertionSyntaxTest, BasicAssertionsBehavesLikeSingleStatement) {
+  if (AlwaysFalse())
+    ASSERT_TRUE(false) << "This should never be executed; "
+                          "It's a compilation test only.";
+
+  if (AlwaysTrue())
+    EXPECT_FALSE(false);
+  else
+    ;  // NOLINT
+
+  if (AlwaysFalse())
+    ASSERT_LT(1, 3);
+
+  if (AlwaysFalse())
+    ;  // NOLINT
+  else
+    EXPECT_GT(3, 2) << "";
+}
+
+#if GTEST_HAS_EXCEPTIONS
+// Tests that the compiler will not complain about unreachable code in the
+// EXPECT_THROW/EXPECT_ANY_THROW/EXPECT_NO_THROW macros.
+TEST(ExpectThrowTest, DoesNotGenerateUnreachableCodeWarning) {
+  int n = 0;
+
+  EXPECT_THROW(throw 1, int);
+  EXPECT_NONFATAL_FAILURE(EXPECT_THROW(n++, int), "");
+  EXPECT_NONFATAL_FAILURE(EXPECT_THROW(throw 1, const char*), "");
+  EXPECT_NO_THROW(n++);
+  EXPECT_NONFATAL_FAILURE(EXPECT_NO_THROW(throw 1), "");
+  EXPECT_ANY_THROW(throw 1);
+  EXPECT_NONFATAL_FAILURE(EXPECT_ANY_THROW(n++), "");
+}
+
+TEST(AssertionSyntaxTest, ExceptionAssertionsBehavesLikeSingleStatement) {
+  if (AlwaysFalse())
+    EXPECT_THROW(ThrowNothing(), bool);
+
+  if (AlwaysTrue())
+    EXPECT_THROW(ThrowAnInteger(), int);
+  else
+    ;  // NOLINT
+
+  if (AlwaysFalse())
+    EXPECT_NO_THROW(ThrowAnInteger());
+
+  if (AlwaysTrue())
+    EXPECT_NO_THROW(ThrowNothing());
+  else
+    ;  // NOLINT
+
+  if (AlwaysFalse())
+    EXPECT_ANY_THROW(ThrowNothing());
+
+  if (AlwaysTrue())
+    EXPECT_ANY_THROW(ThrowAnInteger());
+  else
+    ;  // NOLINT
+}
+#endif  // GTEST_HAS_EXCEPTIONS
+
+TEST(AssertionSyntaxTest, NoFatalFailureAssertionsBehavesLikeSingleStatement) {
+  if (AlwaysFalse())
+    EXPECT_NO_FATAL_FAILURE(FAIL()) << "This should never be executed. "
+                                    << "It's a compilation test only.";
+  else
+    ;  // NOLINT
+
+  if (AlwaysFalse())
+    ASSERT_NO_FATAL_FAILURE(FAIL()) << "";
+  else
+    ;  // NOLINT
+
+  if (AlwaysTrue())
+    EXPECT_NO_FATAL_FAILURE(SUCCEED());
+  else
+    ;  // NOLINT
+
+  if (AlwaysFalse())
+    ;  // NOLINT
+  else
+    ASSERT_NO_FATAL_FAILURE(SUCCEED());
+}
+
+// Tests that the assertion macros work well with switch statements.
+TEST(AssertionSyntaxTest, WorksWithSwitch) {
+  switch (0) {
+    case 1:
+      break;
+    default:
+      ASSERT_TRUE(true);
+  }
+
+  switch (0)
+    case 0:
+      EXPECT_FALSE(false) << "EXPECT_FALSE failed in switch case";
+
+  // Binary assertions are implemented using a different code path
+  // than the Boolean assertions.  Hence we test them separately.
+  switch (0) {
+    case 1:
+    default:
+      ASSERT_EQ(1, 1) << "ASSERT_EQ failed in default switch handler";
+  }
+
+  switch (0)
+    case 0:
+      EXPECT_NE(1, 2);
+}
+
+#if GTEST_HAS_EXCEPTIONS
+
+void ThrowAString() {
+    throw "std::string";
+}
+
+// Test that the exception assertion macros compile and work with const
+// type qualifier.
+TEST(AssertionSyntaxTest, WorksWithConst) {
+    ASSERT_THROW(ThrowAString(), const char*);
+
+    EXPECT_THROW(ThrowAString(), const char*);
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+}  // namespace
+
+namespace testing {
+
+// Tests that Google Test tracks SUCCEED*.
+TEST(SuccessfulAssertionTest, SUCCEED) {
+  SUCCEED();
+  SUCCEED() << "OK";
+  EXPECT_EQ(2, GetUnitTestImpl()->current_test_result()->total_part_count());
+}
+
+// Tests that Google Test doesn't track successful EXPECT_*.
+TEST(SuccessfulAssertionTest, EXPECT) {
+  EXPECT_TRUE(true);
+  EXPECT_EQ(0, GetUnitTestImpl()->current_test_result()->total_part_count());
+}
+
+// Tests that Google Test doesn't track successful EXPECT_STR*.
+TEST(SuccessfulAssertionTest, EXPECT_STR) {
+  EXPECT_STREQ("", "");
+  EXPECT_EQ(0, GetUnitTestImpl()->current_test_result()->total_part_count());
+}
+
+// Tests that Google Test doesn't track successful ASSERT_*.
+TEST(SuccessfulAssertionTest, ASSERT) {
+  ASSERT_TRUE(true);
+  EXPECT_EQ(0, GetUnitTestImpl()->current_test_result()->total_part_count());
+}
+
+// Tests that Google Test doesn't track successful ASSERT_STR*.
+TEST(SuccessfulAssertionTest, ASSERT_STR) {
+  ASSERT_STREQ("", "");
+  EXPECT_EQ(0, GetUnitTestImpl()->current_test_result()->total_part_count());
+}
+
+}  // namespace testing
+
+namespace {
+
+// Tests the message streaming variation of assertions.
+
+TEST(AssertionWithMessageTest, EXPECT) {
+  EXPECT_EQ(1, 1) << "This should succeed.";
+  EXPECT_NONFATAL_FAILURE(EXPECT_NE(1, 1) << "Expected failure #1.",
+                          "Expected failure #1");
+  EXPECT_LE(1, 2) << "This should succeed.";
+  EXPECT_NONFATAL_FAILURE(EXPECT_LT(1, 0) << "Expected failure #2.",
+                          "Expected failure #2.");
+  EXPECT_GE(1, 0) << "This should succeed.";
+  EXPECT_NONFATAL_FAILURE(EXPECT_GT(1, 2) << "Expected failure #3.",
+                          "Expected failure #3.");
+
+  EXPECT_STREQ("1", "1") << "This should succeed.";
+  EXPECT_NONFATAL_FAILURE(EXPECT_STRNE("1", "1") << "Expected failure #4.",
+                          "Expected failure #4.");
+  EXPECT_STRCASEEQ("a", "A") << "This should succeed.";
+  EXPECT_NONFATAL_FAILURE(EXPECT_STRCASENE("a", "A") << "Expected failure #5.",
+                          "Expected failure #5.");
+
+  EXPECT_FLOAT_EQ(1, 1) << "This should succeed.";
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(1, 1.2) << "Expected failure #6.",
+                          "Expected failure #6.");
+  EXPECT_NEAR(1, 1.1, 0.2) << "This should succeed.";
+}
+
+TEST(AssertionWithMessageTest, ASSERT) {
+  ASSERT_EQ(1, 1) << "This should succeed.";
+  ASSERT_NE(1, 2) << "This should succeed.";
+  ASSERT_LE(1, 2) << "This should succeed.";
+  ASSERT_LT(1, 2) << "This should succeed.";
+  ASSERT_GE(1, 0) << "This should succeed.";
+  EXPECT_FATAL_FAILURE(ASSERT_GT(1, 2) << "Expected failure.",
+                       "Expected failure.");
+}
+
+TEST(AssertionWithMessageTest, ASSERT_STR) {
+  ASSERT_STREQ("1", "1") << "This should succeed.";
+  ASSERT_STRNE("1", "2") << "This should succeed.";
+  ASSERT_STRCASEEQ("a", "A") << "This should succeed.";
+  EXPECT_FATAL_FAILURE(ASSERT_STRCASENE("a", "A") << "Expected failure.",
+                       "Expected failure.");
+}
+
+TEST(AssertionWithMessageTest, ASSERT_FLOATING) {
+  ASSERT_FLOAT_EQ(1, 1) << "This should succeed.";
+  ASSERT_DOUBLE_EQ(1, 1) << "This should succeed.";
+  EXPECT_FATAL_FAILURE(ASSERT_NEAR(1,1.2, 0.1) << "Expect failure.",  // NOLINT
+                       "Expect failure.");
+  // To work around a bug in gcc 2.95.0, there is intentionally no
+  // space after the first comma in the previous statement.
+}
+
+// Tests using ASSERT_FALSE with a streamed message.
+TEST(AssertionWithMessageTest, ASSERT_FALSE) {
+  ASSERT_FALSE(false) << "This shouldn't fail.";
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_FALSE(true) << "Expected failure: " << 2 << " > " << 1
+                       << " evaluates to " << true;
+  }, "Expected failure");
+}
+
+// Tests using FAIL with a streamed message.
+TEST(AssertionWithMessageTest, FAIL) {
+  EXPECT_FATAL_FAILURE(FAIL() << 0,
+                       "0");
+}
+
+// Tests using SUCCEED with a streamed message.
+TEST(AssertionWithMessageTest, SUCCEED) {
+  SUCCEED() << "Success == " << 1;
+}
+
+// Tests using ASSERT_TRUE with a streamed message.
+TEST(AssertionWithMessageTest, ASSERT_TRUE) {
+  ASSERT_TRUE(true) << "This should succeed.";
+  ASSERT_TRUE(true) << true;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_TRUE(false) << static_cast<const char *>(NULL)
+                       << static_cast<char *>(NULL);
+  }, "(null)(null)");
+}
+
+#if GTEST_OS_WINDOWS
+// Tests using wide strings in assertion messages.
+TEST(AssertionWithMessageTest, WideStringMessage) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_TRUE(false) << L"This failure is expected.\x8119";
+  }, "This failure is expected.");
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_EQ(1, 2) << "This failure is "
+                    << L"expected too.\x8120";
+  }, "This failure is expected too.");
+}
+#endif  // GTEST_OS_WINDOWS
+
+// Tests EXPECT_TRUE.
+TEST(ExpectTest, EXPECT_TRUE) {
+  EXPECT_TRUE(true) << "Intentional success";
+  EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(false) << "Intentional failure #1.",
+                          "Intentional failure #1.");
+  EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(false) << "Intentional failure #2.",
+                          "Intentional failure #2.");
+  EXPECT_TRUE(2 > 1);  // NOLINT
+  EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(2 < 1),
+                          "Value of: 2 < 1\n"
+                          "  Actual: false\n"
+                          "Expected: true");
+  EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(2 > 3),
+                          "2 > 3");
+}
+
+// Tests EXPECT_TRUE(predicate) for predicates returning AssertionResult.
+TEST(ExpectTest, ExpectTrueWithAssertionResult) {
+  EXPECT_TRUE(ResultIsEven(2));
+  EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(ResultIsEven(3)),
+                          "Value of: ResultIsEven(3)\n"
+                          "  Actual: false (3 is odd)\n"
+                          "Expected: true");
+  EXPECT_TRUE(ResultIsEvenNoExplanation(2));
+  EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(ResultIsEvenNoExplanation(3)),
+                          "Value of: ResultIsEvenNoExplanation(3)\n"
+                          "  Actual: false (3 is odd)\n"
+                          "Expected: true");
+}
+
+// Tests EXPECT_FALSE with a streamed message.
+TEST(ExpectTest, EXPECT_FALSE) {
+  EXPECT_FALSE(2 < 1);  // NOLINT
+  EXPECT_FALSE(false) << "Intentional success";
+  EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(true) << "Intentional failure #1.",
+                          "Intentional failure #1.");
+  EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(true) << "Intentional failure #2.",
+                          "Intentional failure #2.");
+  EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(2 > 1),
+                          "Value of: 2 > 1\n"
+                          "  Actual: true\n"
+                          "Expected: false");
+  EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(2 < 3),
+                          "2 < 3");
+}
+
+// Tests EXPECT_FALSE(predicate) for predicates returning AssertionResult.
+TEST(ExpectTest, ExpectFalseWithAssertionResult) {
+  EXPECT_FALSE(ResultIsEven(3));
+  EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(ResultIsEven(2)),
+                          "Value of: ResultIsEven(2)\n"
+                          "  Actual: true (2 is even)\n"
+                          "Expected: false");
+  EXPECT_FALSE(ResultIsEvenNoExplanation(3));
+  EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(ResultIsEvenNoExplanation(2)),
+                          "Value of: ResultIsEvenNoExplanation(2)\n"
+                          "  Actual: true\n"
+                          "Expected: false");
+}
+
+#ifdef __BORLANDC__
+// Restores warnings after previous "#pragma option push" supressed them
+# pragma option pop
+#endif
+
+// Tests EXPECT_EQ.
+TEST(ExpectTest, EXPECT_EQ) {
+  EXPECT_EQ(5, 2 + 3);
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(5, 2*3),
+                          "Value of: 2*3\n"
+                          "  Actual: 6\n"
+                          "Expected: 5");
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(5, 2 - 3),
+                          "2 - 3");
+}
+
+// Tests using EXPECT_EQ on double values.  The purpose is to make
+// sure that the specialization we did for integer and anonymous enums
+// isn't used for double arguments.
+TEST(ExpectTest, EXPECT_EQ_Double) {
+  // A success.
+  EXPECT_EQ(5.6, 5.6);
+
+  // A failure.
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(5.1, 5.2),
+                          "5.1");
+}
+
+#if GTEST_CAN_COMPARE_NULL
+// Tests EXPECT_EQ(NULL, pointer).
+TEST(ExpectTest, EXPECT_EQ_NULL) {
+  // A success.
+  const char* p = NULL;
+  // Some older GCC versions may issue a spurious warning in this or the next
+  // assertion statement. This warning should not be suppressed with
+  // static_cast since the test verifies the ability to use bare NULL as the
+  // expected parameter to the macro.
+  EXPECT_EQ(NULL, p);
+
+  // A failure.
+  int n = 0;
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(NULL, &n),
+                          "Value of: &n\n");
+}
+#endif  // GTEST_CAN_COMPARE_NULL
+
+// Tests EXPECT_EQ(0, non_pointer).  Since the literal 0 can be
+// treated as a null pointer by the compiler, we need to make sure
+// that EXPECT_EQ(0, non_pointer) isn't interpreted by Google Test as
+// EXPECT_EQ(static_cast<void*>(NULL), non_pointer).
+TEST(ExpectTest, EXPECT_EQ_0) {
+  int n = 0;
+
+  // A success.
+  EXPECT_EQ(0, n);
+
+  // A failure.
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(0, 5.6),
+                          "Expected: 0");
+}
+
+// Tests EXPECT_NE.
+TEST(ExpectTest, EXPECT_NE) {
+  EXPECT_NE(6, 7);
+
+  EXPECT_NONFATAL_FAILURE(EXPECT_NE('a', 'a'),
+                          "Expected: ('a') != ('a'), "
+                          "actual: 'a' (97, 0x61) vs 'a' (97, 0x61)");
+  EXPECT_NONFATAL_FAILURE(EXPECT_NE(2, 2),
+                          "2");
+  char* const p0 = NULL;
+  EXPECT_NONFATAL_FAILURE(EXPECT_NE(p0, p0),
+                          "p0");
+  // Only way to get the Nokia compiler to compile the cast
+  // is to have a separate void* variable first. Putting
+  // the two casts on the same line doesn't work, neither does
+  // a direct C-style to char*.
+  void* pv1 = (void*)0x1234;  // NOLINT
+  char* const p1 = reinterpret_cast<char*>(pv1);
+  EXPECT_NONFATAL_FAILURE(EXPECT_NE(p1, p1),
+                          "p1");
+}
+
+// Tests EXPECT_LE.
+TEST(ExpectTest, EXPECT_LE) {
+  EXPECT_LE(2, 3);
+  EXPECT_LE(2, 2);
+  EXPECT_NONFATAL_FAILURE(EXPECT_LE(2, 0),
+                          "Expected: (2) <= (0), actual: 2 vs 0");
+  EXPECT_NONFATAL_FAILURE(EXPECT_LE(1.1, 0.9),
+                          "(1.1) <= (0.9)");
+}
+
+// Tests EXPECT_LT.
+TEST(ExpectTest, EXPECT_LT) {
+  EXPECT_LT(2, 3);
+  EXPECT_NONFATAL_FAILURE(EXPECT_LT(2, 2),
+                          "Expected: (2) < (2), actual: 2 vs 2");
+  EXPECT_NONFATAL_FAILURE(EXPECT_LT(2, 1),
+                          "(2) < (1)");
+}
+
+// Tests EXPECT_GE.
+TEST(ExpectTest, EXPECT_GE) {
+  EXPECT_GE(2, 1);
+  EXPECT_GE(2, 2);
+  EXPECT_NONFATAL_FAILURE(EXPECT_GE(2, 3),
+                          "Expected: (2) >= (3), actual: 2 vs 3");
+  EXPECT_NONFATAL_FAILURE(EXPECT_GE(0.9, 1.1),
+                          "(0.9) >= (1.1)");
+}
+
+// Tests EXPECT_GT.
+TEST(ExpectTest, EXPECT_GT) {
+  EXPECT_GT(2, 1);
+  EXPECT_NONFATAL_FAILURE(EXPECT_GT(2, 2),
+                          "Expected: (2) > (2), actual: 2 vs 2");
+  EXPECT_NONFATAL_FAILURE(EXPECT_GT(2, 3),
+                          "(2) > (3)");
+}
+
+#if GTEST_HAS_EXCEPTIONS
+
+// Tests EXPECT_THROW.
+TEST(ExpectTest, EXPECT_THROW) {
+  EXPECT_THROW(ThrowAnInteger(), int);
+  EXPECT_NONFATAL_FAILURE(EXPECT_THROW(ThrowAnInteger(), bool),
+                          "Expected: ThrowAnInteger() throws an exception of "
+                          "type bool.\n  Actual: it throws a different type.");
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_THROW(ThrowNothing(), bool),
+      "Expected: ThrowNothing() throws an exception of type bool.\n"
+      "  Actual: it throws nothing.");
+}
+
+// Tests EXPECT_NO_THROW.
+TEST(ExpectTest, EXPECT_NO_THROW) {
+  EXPECT_NO_THROW(ThrowNothing());
+  EXPECT_NONFATAL_FAILURE(EXPECT_NO_THROW(ThrowAnInteger()),
+                          "Expected: ThrowAnInteger() doesn't throw an "
+                          "exception.\n  Actual: it throws.");
+}
+
+// Tests EXPECT_ANY_THROW.
+TEST(ExpectTest, EXPECT_ANY_THROW) {
+  EXPECT_ANY_THROW(ThrowAnInteger());
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_ANY_THROW(ThrowNothing()),
+      "Expected: ThrowNothing() throws an exception.\n"
+      "  Actual: it doesn't.");
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// Make sure we deal with the precedence of <<.
+TEST(ExpectTest, ExpectPrecedence) {
+  EXPECT_EQ(1 < 2, true);
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(true, true && false),
+                          "Value of: true && false");
+}
+
+
+// Tests the StreamableToString() function.
+
+// Tests using StreamableToString() on a scalar.
+TEST(StreamableToStringTest, Scalar) {
+  EXPECT_STREQ("5", StreamableToString(5).c_str());
+}
+
+// Tests using StreamableToString() on a non-char pointer.
+TEST(StreamableToStringTest, Pointer) {
+  int n = 0;
+  int* p = &n;
+  EXPECT_STRNE("(null)", StreamableToString(p).c_str());
+}
+
+// Tests using StreamableToString() on a NULL non-char pointer.
+TEST(StreamableToStringTest, NullPointer) {
+  int* p = NULL;
+  EXPECT_STREQ("(null)", StreamableToString(p).c_str());
+}
+
+// Tests using StreamableToString() on a C string.
+TEST(StreamableToStringTest, CString) {
+  EXPECT_STREQ("Foo", StreamableToString("Foo").c_str());
+}
+
+// Tests using StreamableToString() on a NULL C string.
+TEST(StreamableToStringTest, NullCString) {
+  char* p = NULL;
+  EXPECT_STREQ("(null)", StreamableToString(p).c_str());
+}
+
+// Tests using streamable values as assertion messages.
+
+// Tests using std::string as an assertion message.
+TEST(StreamableTest, string) {
+  static const std::string str(
+      "This failure message is a std::string, and is expected.");
+  EXPECT_FATAL_FAILURE(FAIL() << str,
+                       str.c_str());
+}
+
+// Tests that we can output strings containing embedded NULs.
+// Limited to Linux because we can only do this with std::string's.
+TEST(StreamableTest, stringWithEmbeddedNUL) {
+  static const char char_array_with_nul[] =
+      "Here's a NUL\0 and some more string";
+  static const std::string string_with_nul(char_array_with_nul,
+                                           sizeof(char_array_with_nul)
+                                           - 1);  // drops the trailing NUL
+  EXPECT_FATAL_FAILURE(FAIL() << string_with_nul,
+                       "Here's a NUL\\0 and some more string");
+}
+
+// Tests that we can output a NUL char.
+TEST(StreamableTest, NULChar) {
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    FAIL() << "A NUL" << '\0' << " and some more string";
+  }, "A NUL\\0 and some more string");
+}
+
+// Tests using int as an assertion message.
+TEST(StreamableTest, int) {
+  EXPECT_FATAL_FAILURE(FAIL() << 900913,
+                       "900913");
+}
+
+// Tests using NULL char pointer as an assertion message.
+//
+// In MSVC, streaming a NULL char * causes access violation.  Google Test
+// implemented a workaround (substituting "(null)" for NULL).  This
+// tests whether the workaround works.
+TEST(StreamableTest, NullCharPtr) {
+  EXPECT_FATAL_FAILURE(FAIL() << static_cast<const char*>(NULL),
+                       "(null)");
+}
+
+// Tests that basic IO manipulators (endl, ends, and flush) can be
+// streamed to testing::Message.
+TEST(StreamableTest, BasicIoManip) {
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    FAIL() << "Line 1." << std::endl
+           << "A NUL char " << std::ends << std::flush << " in line 2.";
+  }, "Line 1.\nA NUL char \\0 in line 2.");
+}
+
+// Tests the macros that haven't been covered so far.
+
+void AddFailureHelper(bool* aborted) {
+  *aborted = true;
+  ADD_FAILURE() << "Intentional failure.";
+  *aborted = false;
+}
+
+// Tests ADD_FAILURE.
+TEST(MacroTest, ADD_FAILURE) {
+  bool aborted = true;
+  EXPECT_NONFATAL_FAILURE(AddFailureHelper(&aborted),
+                          "Intentional failure.");
+  EXPECT_FALSE(aborted);
+}
+
+// Tests ADD_FAILURE_AT.
+TEST(MacroTest, ADD_FAILURE_AT) {
+  // Verifies that ADD_FAILURE_AT does generate a nonfatal failure and
+  // the failure message contains the user-streamed part.
+  EXPECT_NONFATAL_FAILURE(ADD_FAILURE_AT("foo.cc", 42) << "Wrong!", "Wrong!");
+
+  // Verifies that the user-streamed part is optional.
+  EXPECT_NONFATAL_FAILURE(ADD_FAILURE_AT("foo.cc", 42), "Failed");
+
+  // Unfortunately, we cannot verify that the failure message contains
+  // the right file path and line number the same way, as
+  // EXPECT_NONFATAL_FAILURE() doesn't get to see the file path and
+  // line number.  Instead, we do that in gtest_output_test_.cc.
+}
+
+// Tests FAIL.
+TEST(MacroTest, FAIL) {
+  EXPECT_FATAL_FAILURE(FAIL(),
+                       "Failed");
+  EXPECT_FATAL_FAILURE(FAIL() << "Intentional failure.",
+                       "Intentional failure.");
+}
+
+// Tests SUCCEED
+TEST(MacroTest, SUCCEED) {
+  SUCCEED();
+  SUCCEED() << "Explicit success.";
+}
+
+// Tests for EXPECT_EQ() and ASSERT_EQ().
+//
+// These tests fail *intentionally*, s.t. the failure messages can be
+// generated and tested.
+//
+// We have different tests for different argument types.
+
+// Tests using bool values in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, Bool) {
+  EXPECT_EQ(true,  true);
+  EXPECT_FATAL_FAILURE({
+      bool false_value = false;
+      ASSERT_EQ(false_value, true);
+    }, "Value of: true");
+}
+
+// Tests using int values in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, Int) {
+  ASSERT_EQ(32, 32);
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(32, 33),
+                          "33");
+}
+
+// Tests using time_t values in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, Time_T) {
+  EXPECT_EQ(static_cast<time_t>(0),
+            static_cast<time_t>(0));
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(static_cast<time_t>(0),
+                                 static_cast<time_t>(1234)),
+                       "1234");
+}
+
+// Tests using char values in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, Char) {
+  ASSERT_EQ('z', 'z');
+  const char ch = 'b';
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ('\0', ch),
+                          "ch");
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ('a', ch),
+                          "ch");
+}
+
+// Tests using wchar_t values in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, WideChar) {
+  EXPECT_EQ(L'b', L'b');
+
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(L'\0', L'x'),
+                          "Value of: L'x'\n"
+                          "  Actual: L'x' (120, 0x78)\n"
+                          "Expected: L'\0'\n"
+                          "Which is: L'\0' (0, 0x0)");
+
+  static wchar_t wchar;
+  wchar = L'b';
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(L'a', wchar),
+                          "wchar");
+  wchar = 0x8119;
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(static_cast<wchar_t>(0x8120), wchar),
+                       "Value of: wchar");
+}
+
+// Tests using ::std::string values in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, StdString) {
+  // Compares a const char* to an std::string that has identical
+  // content.
+  ASSERT_EQ("Test", ::std::string("Test"));
+
+  // Compares two identical std::strings.
+  static const ::std::string str1("A * in the middle");
+  static const ::std::string str2(str1);
+  EXPECT_EQ(str1, str2);
+
+  // Compares a const char* to an std::string that has different
+  // content
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ("Test", ::std::string("test")),
+                          "\"test\"");
+
+  // Compares an std::string to a char* that has different content.
+  char* const p1 = const_cast<char*>("foo");
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(::std::string("bar"), p1),
+                          "p1");
+
+  // Compares two std::strings that have different contents, one of
+  // which having a NUL character in the middle.  This should fail.
+  static ::std::string str3(str1);
+  str3.at(2) = '\0';
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(str1, str3),
+                       "Value of: str3\n"
+                       "  Actual: \"A \\0 in the middle\"");
+}
+
+#if GTEST_HAS_STD_WSTRING
+
+// Tests using ::std::wstring values in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, StdWideString) {
+  // Compares two identical std::wstrings.
+  const ::std::wstring wstr1(L"A * in the middle");
+  const ::std::wstring wstr2(wstr1);
+  ASSERT_EQ(wstr1, wstr2);
+
+  // Compares an std::wstring to a const wchar_t* that has identical
+  // content.
+  const wchar_t kTestX8119[] = { 'T', 'e', 's', 't', 0x8119, '\0' };
+  EXPECT_EQ(::std::wstring(kTestX8119), kTestX8119);
+
+  // Compares an std::wstring to a const wchar_t* that has different
+  // content.
+  const wchar_t kTestX8120[] = { 'T', 'e', 's', 't', 0x8120, '\0' };
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_EQ(::std::wstring(kTestX8119), kTestX8120);
+  }, "kTestX8120");
+
+  // Compares two std::wstrings that have different contents, one of
+  // which having a NUL character in the middle.
+  ::std::wstring wstr3(wstr1);
+  wstr3.at(2) = L'\0';
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(wstr1, wstr3),
+                          "wstr3");
+
+  // Compares a wchar_t* to an std::wstring that has different
+  // content.
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_EQ(const_cast<wchar_t*>(L"foo"), ::std::wstring(L"bar"));
+  }, "");
+}
+
+#endif  // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_GLOBAL_STRING
+// Tests using ::string values in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, GlobalString) {
+  // Compares a const char* to a ::string that has identical content.
+  EXPECT_EQ("Test", ::string("Test"));
+
+  // Compares two identical ::strings.
+  const ::string str1("A * in the middle");
+  const ::string str2(str1);
+  ASSERT_EQ(str1, str2);
+
+  // Compares a ::string to a const char* that has different content.
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(::string("Test"), "test"),
+                          "test");
+
+  // Compares two ::strings that have different contents, one of which
+  // having a NUL character in the middle.
+  ::string str3(str1);
+  str3.at(2) = '\0';
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(str1, str3),
+                          "str3");
+
+  // Compares a ::string to a char* that has different content.
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_EQ(::string("bar"), const_cast<char*>("foo"));
+  }, "");
+}
+
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+
+// Tests using ::wstring values in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, GlobalWideString) {
+  // Compares two identical ::wstrings.
+  static const ::wstring wstr1(L"A * in the middle");
+  static const ::wstring wstr2(wstr1);
+  EXPECT_EQ(wstr1, wstr2);
+
+  // Compares a const wchar_t* to a ::wstring that has identical content.
+  const wchar_t kTestX8119[] = { 'T', 'e', 's', 't', 0x8119, '\0' };
+  ASSERT_EQ(kTestX8119, ::wstring(kTestX8119));
+
+  // Compares a const wchar_t* to a ::wstring that has different
+  // content.
+  const wchar_t kTestX8120[] = { 'T', 'e', 's', 't', 0x8120, '\0' };
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_EQ(kTestX8120, ::wstring(kTestX8119));
+  }, "Test\\x8119");
+
+  // Compares a wchar_t* to a ::wstring that has different content.
+  wchar_t* const p1 = const_cast<wchar_t*>(L"foo");
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p1, ::wstring(L"bar")),
+                          "bar");
+
+  // Compares two ::wstrings that have different contents, one of which
+  // having a NUL character in the middle.
+  static ::wstring wstr3;
+  wstr3 = wstr1;
+  wstr3.at(2) = L'\0';
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(wstr1, wstr3),
+                       "wstr3");
+}
+
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+// Tests using char pointers in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, CharPointer) {
+  char* const p0 = NULL;
+  // Only way to get the Nokia compiler to compile the cast
+  // is to have a separate void* variable first. Putting
+  // the two casts on the same line doesn't work, neither does
+  // a direct C-style to char*.
+  void* pv1 = (void*)0x1234;  // NOLINT
+  void* pv2 = (void*)0xABC0;  // NOLINT
+  char* const p1 = reinterpret_cast<char*>(pv1);
+  char* const p2 = reinterpret_cast<char*>(pv2);
+  ASSERT_EQ(p1, p1);
+
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p0, p2),
+                          "Value of: p2");
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p1, p2),
+                          "p2");
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(reinterpret_cast<char*>(0x1234),
+                                 reinterpret_cast<char*>(0xABC0)),
+                       "ABC0");
+}
+
+// Tests using wchar_t pointers in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, WideCharPointer) {
+  wchar_t* const p0 = NULL;
+  // Only way to get the Nokia compiler to compile the cast
+  // is to have a separate void* variable first. Putting
+  // the two casts on the same line doesn't work, neither does
+  // a direct C-style to char*.
+  void* pv1 = (void*)0x1234;  // NOLINT
+  void* pv2 = (void*)0xABC0;  // NOLINT
+  wchar_t* const p1 = reinterpret_cast<wchar_t*>(pv1);
+  wchar_t* const p2 = reinterpret_cast<wchar_t*>(pv2);
+  EXPECT_EQ(p0, p0);
+
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p0, p2),
+                          "Value of: p2");
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p1, p2),
+                          "p2");
+  void* pv3 = (void*)0x1234;  // NOLINT
+  void* pv4 = (void*)0xABC0;  // NOLINT
+  const wchar_t* p3 = reinterpret_cast<const wchar_t*>(pv3);
+  const wchar_t* p4 = reinterpret_cast<const wchar_t*>(pv4);
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p3, p4),
+                          "p4");
+}
+
+// Tests using other types of pointers in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, OtherPointer) {
+  ASSERT_EQ(static_cast<const int*>(NULL),
+            static_cast<const int*>(NULL));
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(static_cast<const int*>(NULL),
+                                 reinterpret_cast<const int*>(0x1234)),
+                       "0x1234");
+}
+
+// A class that supports binary comparison operators but not streaming.
+class UnprintableChar {
+ public:
+  explicit UnprintableChar(char ch) : char_(ch) {}
+
+  bool operator==(const UnprintableChar& rhs) const {
+    return char_ == rhs.char_;
+  }
+  bool operator!=(const UnprintableChar& rhs) const {
+    return char_ != rhs.char_;
+  }
+  bool operator<(const UnprintableChar& rhs) const {
+    return char_ < rhs.char_;
+  }
+  bool operator<=(const UnprintableChar& rhs) const {
+    return char_ <= rhs.char_;
+  }
+  bool operator>(const UnprintableChar& rhs) const {
+    return char_ > rhs.char_;
+  }
+  bool operator>=(const UnprintableChar& rhs) const {
+    return char_ >= rhs.char_;
+  }
+
+ private:
+  char char_;
+};
+
+// Tests that ASSERT_EQ() and friends don't require the arguments to
+// be printable.
+TEST(ComparisonAssertionTest, AcceptsUnprintableArgs) {
+  const UnprintableChar x('x'), y('y');
+  ASSERT_EQ(x, x);
+  EXPECT_NE(x, y);
+  ASSERT_LT(x, y);
+  EXPECT_LE(x, y);
+  ASSERT_GT(y, x);
+  EXPECT_GE(x, x);
+
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(x, y), "1-byte object <78>");
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(x, y), "1-byte object <79>");
+  EXPECT_NONFATAL_FAILURE(EXPECT_LT(y, y), "1-byte object <79>");
+  EXPECT_NONFATAL_FAILURE(EXPECT_GT(x, y), "1-byte object <78>");
+  EXPECT_NONFATAL_FAILURE(EXPECT_GT(x, y), "1-byte object <79>");
+
+  // Code tested by EXPECT_FATAL_FAILURE cannot reference local
+  // variables, so we have to write UnprintableChar('x') instead of x.
+#ifndef __BORLANDC__
+  // ICE's in C++Builder.
+  EXPECT_FATAL_FAILURE(ASSERT_NE(UnprintableChar('x'), UnprintableChar('x')),
+                       "1-byte object <78>");
+  EXPECT_FATAL_FAILURE(ASSERT_LE(UnprintableChar('y'), UnprintableChar('x')),
+                       "1-byte object <78>");
+#endif
+  EXPECT_FATAL_FAILURE(ASSERT_LE(UnprintableChar('y'), UnprintableChar('x')),
+                       "1-byte object <79>");
+  EXPECT_FATAL_FAILURE(ASSERT_GE(UnprintableChar('x'), UnprintableChar('y')),
+                       "1-byte object <78>");
+  EXPECT_FATAL_FAILURE(ASSERT_GE(UnprintableChar('x'), UnprintableChar('y')),
+                       "1-byte object <79>");
+}
+
+// Tests the FRIEND_TEST macro.
+
+// This class has a private member we want to test.  We will test it
+// both in a TEST and in a TEST_F.
+class Foo {
+ public:
+  Foo() {}
+
+ private:
+  int Bar() const { return 1; }
+
+  // Declares the friend tests that can access the private member
+  // Bar().
+  FRIEND_TEST(FRIEND_TEST_Test, TEST);
+  FRIEND_TEST(FRIEND_TEST_Test2, TEST_F);
+};
+
+// Tests that the FRIEND_TEST declaration allows a TEST to access a
+// class's private members.  This should compile.
+TEST(FRIEND_TEST_Test, TEST) {
+  ASSERT_EQ(1, Foo().Bar());
+}
+
+// The fixture needed to test using FRIEND_TEST with TEST_F.
+class FRIEND_TEST_Test2 : public Test {
+ protected:
+  Foo foo;
+};
+
+// Tests that the FRIEND_TEST declaration allows a TEST_F to access a
+// class's private members.  This should compile.
+TEST_F(FRIEND_TEST_Test2, TEST_F) {
+  ASSERT_EQ(1, foo.Bar());
+}
+
+// Tests the life cycle of Test objects.
+
+// The test fixture for testing the life cycle of Test objects.
+//
+// This class counts the number of live test objects that uses this
+// fixture.
+class TestLifeCycleTest : public Test {
+ protected:
+  // Constructor.  Increments the number of test objects that uses
+  // this fixture.
+  TestLifeCycleTest() { count_++; }
+
+  // Destructor.  Decrements the number of test objects that uses this
+  // fixture.
+  ~TestLifeCycleTest() { count_--; }
+
+  // Returns the number of live test objects that uses this fixture.
+  int count() const { return count_; }
+
+ private:
+  static int count_;
+};
+
+int TestLifeCycleTest::count_ = 0;
+
+// Tests the life cycle of test objects.
+TEST_F(TestLifeCycleTest, Test1) {
+  // There should be only one test object in this test case that's
+  // currently alive.
+  ASSERT_EQ(1, count());
+}
+
+// Tests the life cycle of test objects.
+TEST_F(TestLifeCycleTest, Test2) {
+  // After Test1 is done and Test2 is started, there should still be
+  // only one live test object, as the object for Test1 should've been
+  // deleted.
+  ASSERT_EQ(1, count());
+}
+
+}  // namespace
+
+// Tests that the copy constructor works when it is NOT optimized away by
+// the compiler.
+TEST(AssertionResultTest, CopyConstructorWorksWhenNotOptimied) {
+  // Checks that the copy constructor doesn't try to dereference NULL pointers
+  // in the source object.
+  AssertionResult r1 = AssertionSuccess();
+  AssertionResult r2 = r1;
+  // The following line is added to prevent the compiler from optimizing
+  // away the constructor call.
+  r1 << "abc";
+
+  AssertionResult r3 = r1;
+  EXPECT_EQ(static_cast<bool>(r3), static_cast<bool>(r1));
+  EXPECT_STREQ("abc", r1.message());
+}
+
+// Tests that AssertionSuccess and AssertionFailure construct
+// AssertionResult objects as expected.
+TEST(AssertionResultTest, ConstructionWorks) {
+  AssertionResult r1 = AssertionSuccess();
+  EXPECT_TRUE(r1);
+  EXPECT_STREQ("", r1.message());
+
+  AssertionResult r2 = AssertionSuccess() << "abc";
+  EXPECT_TRUE(r2);
+  EXPECT_STREQ("abc", r2.message());
+
+  AssertionResult r3 = AssertionFailure();
+  EXPECT_FALSE(r3);
+  EXPECT_STREQ("", r3.message());
+
+  AssertionResult r4 = AssertionFailure() << "def";
+  EXPECT_FALSE(r4);
+  EXPECT_STREQ("def", r4.message());
+
+  AssertionResult r5 = AssertionFailure(Message() << "ghi");
+  EXPECT_FALSE(r5);
+  EXPECT_STREQ("ghi", r5.message());
+}
+
+// Tests that the negation flips the predicate result but keeps the message.
+TEST(AssertionResultTest, NegationWorks) {
+  AssertionResult r1 = AssertionSuccess() << "abc";
+  EXPECT_FALSE(!r1);
+  EXPECT_STREQ("abc", (!r1).message());
+
+  AssertionResult r2 = AssertionFailure() << "def";
+  EXPECT_TRUE(!r2);
+  EXPECT_STREQ("def", (!r2).message());
+}
+
+TEST(AssertionResultTest, StreamingWorks) {
+  AssertionResult r = AssertionSuccess();
+  r << "abc" << 'd' << 0 << true;
+  EXPECT_STREQ("abcd0true", r.message());
+}
+
+TEST(AssertionResultTest, CanStreamOstreamManipulators) {
+  AssertionResult r = AssertionSuccess();
+  r << "Data" << std::endl << std::flush << std::ends << "Will be visible";
+  EXPECT_STREQ("Data\n\\0Will be visible", r.message());
+}
+
+// The next test uses explicit conversion operators -- a C++11 feature.
+#if GTEST_LANG_CXX11
+
+TEST(AssertionResultTest, ConstructibleFromContextuallyConvertibleToBool) {
+  struct ExplicitlyConvertibleToBool {
+    explicit operator bool() const { return value; }
+    bool value;
+  };
+  ExplicitlyConvertibleToBool v1 = {false};
+  ExplicitlyConvertibleToBool v2 = {true};
+  EXPECT_FALSE(v1);
+  EXPECT_TRUE(v2);
+}
+
+#endif  // GTEST_LANG_CXX11
+
+struct ConvertibleToAssertionResult {
+  operator AssertionResult() const { return AssertionResult(true); }
+};
+
+TEST(AssertionResultTest, ConstructibleFromImplicitlyConvertible) {
+  ConvertibleToAssertionResult obj;
+  EXPECT_TRUE(obj);
+}
+
+// Tests streaming a user type whose definition and operator << are
+// both in the global namespace.
+class Base {
+ public:
+  explicit Base(int an_x) : x_(an_x) {}
+  int x() const { return x_; }
+ private:
+  int x_;
+};
+std::ostream& operator<<(std::ostream& os,
+                         const Base& val) {
+  return os << val.x();
+}
+std::ostream& operator<<(std::ostream& os,
+                         const Base* pointer) {
+  return os << "(" << pointer->x() << ")";
+}
+
+TEST(MessageTest, CanStreamUserTypeInGlobalNameSpace) {
+  Message msg;
+  Base a(1);
+
+  msg << a << &a;  // Uses ::operator<<.
+  EXPECT_STREQ("1(1)", msg.GetString().c_str());
+}
+
+// Tests streaming a user type whose definition and operator<< are
+// both in an unnamed namespace.
+namespace {
+class MyTypeInUnnamedNameSpace : public Base {
+ public:
+  explicit MyTypeInUnnamedNameSpace(int an_x): Base(an_x) {}
+};
+std::ostream& operator<<(std::ostream& os,
+                         const MyTypeInUnnamedNameSpace& val) {
+  return os << val.x();
+}
+std::ostream& operator<<(std::ostream& os,
+                         const MyTypeInUnnamedNameSpace* pointer) {
+  return os << "(" << pointer->x() << ")";
+}
+}  // namespace
+
+TEST(MessageTest, CanStreamUserTypeInUnnamedNameSpace) {
+  Message msg;
+  MyTypeInUnnamedNameSpace a(1);
+
+  msg << a << &a;  // Uses <unnamed_namespace>::operator<<.
+  EXPECT_STREQ("1(1)", msg.GetString().c_str());
+}
+
+// Tests streaming a user type whose definition and operator<< are
+// both in a user namespace.
+namespace namespace1 {
+class MyTypeInNameSpace1 : public Base {
+ public:
+  explicit MyTypeInNameSpace1(int an_x): Base(an_x) {}
+};
+std::ostream& operator<<(std::ostream& os,
+                         const MyTypeInNameSpace1& val) {
+  return os << val.x();
+}
+std::ostream& operator<<(std::ostream& os,
+                         const MyTypeInNameSpace1* pointer) {
+  return os << "(" << pointer->x() << ")";
+}
+}  // namespace namespace1
+
+TEST(MessageTest, CanStreamUserTypeInUserNameSpace) {
+  Message msg;
+  namespace1::MyTypeInNameSpace1 a(1);
+
+  msg << a << &a;  // Uses namespace1::operator<<.
+  EXPECT_STREQ("1(1)", msg.GetString().c_str());
+}
+
+// Tests streaming a user type whose definition is in a user namespace
+// but whose operator<< is in the global namespace.
+namespace namespace2 {
+class MyTypeInNameSpace2 : public ::Base {
+ public:
+  explicit MyTypeInNameSpace2(int an_x): Base(an_x) {}
+};
+}  // namespace namespace2
+std::ostream& operator<<(std::ostream& os,
+                         const namespace2::MyTypeInNameSpace2& val) {
+  return os << val.x();
+}
+std::ostream& operator<<(std::ostream& os,
+                         const namespace2::MyTypeInNameSpace2* pointer) {
+  return os << "(" << pointer->x() << ")";
+}
+
+TEST(MessageTest, CanStreamUserTypeInUserNameSpaceWithStreamOperatorInGlobal) {
+  Message msg;
+  namespace2::MyTypeInNameSpace2 a(1);
+
+  msg << a << &a;  // Uses ::operator<<.
+  EXPECT_STREQ("1(1)", msg.GetString().c_str());
+}
+
+// Tests streaming NULL pointers to testing::Message.
+TEST(MessageTest, NullPointers) {
+  Message msg;
+  char* const p1 = NULL;
+  unsigned char* const p2 = NULL;
+  int* p3 = NULL;
+  double* p4 = NULL;
+  bool* p5 = NULL;
+  Message* p6 = NULL;
+
+  msg << p1 << p2 << p3 << p4 << p5 << p6;
+  ASSERT_STREQ("(null)(null)(null)(null)(null)(null)",
+               msg.GetString().c_str());
+}
+
+// Tests streaming wide strings to testing::Message.
+TEST(MessageTest, WideStrings) {
+  // Streams a NULL of type const wchar_t*.
+  const wchar_t* const_wstr = NULL;
+  EXPECT_STREQ("(null)",
+               (Message() << const_wstr).GetString().c_str());
+
+  // Streams a NULL of type wchar_t*.
+  wchar_t* wstr = NULL;
+  EXPECT_STREQ("(null)",
+               (Message() << wstr).GetString().c_str());
+
+  // Streams a non-NULL of type const wchar_t*.
+  const_wstr = L"abc\x8119";
+  EXPECT_STREQ("abc\xe8\x84\x99",
+               (Message() << const_wstr).GetString().c_str());
+
+  // Streams a non-NULL of type wchar_t*.
+  wstr = const_cast<wchar_t*>(const_wstr);
+  EXPECT_STREQ("abc\xe8\x84\x99",
+               (Message() << wstr).GetString().c_str());
+}
+
+
+// This line tests that we can define tests in the testing namespace.
+namespace testing {
+
+// Tests the TestInfo class.
+
+class TestInfoTest : public Test {
+ protected:
+  static const TestInfo* GetTestInfo(const char* test_name) {
+    const TestCase* const test_case = GetUnitTestImpl()->
+        GetTestCase("TestInfoTest", "", NULL, NULL);
+
+    for (int i = 0; i < test_case->total_test_count(); ++i) {
+      const TestInfo* const test_info = test_case->GetTestInfo(i);
+      if (strcmp(test_name, test_info->name()) == 0)
+        return test_info;
+    }
+    return NULL;
+  }
+
+  static const TestResult* GetTestResult(
+      const TestInfo* test_info) {
+    return test_info->result();
+  }
+};
+
+// Tests TestInfo::test_case_name() and TestInfo::name().
+TEST_F(TestInfoTest, Names) {
+  const TestInfo* const test_info = GetTestInfo("Names");
+
+  ASSERT_STREQ("TestInfoTest", test_info->test_case_name());
+  ASSERT_STREQ("Names", test_info->name());
+}
+
+// Tests TestInfo::result().
+TEST_F(TestInfoTest, result) {
+  const TestInfo* const test_info = GetTestInfo("result");
+
+  // Initially, there is no TestPartResult for this test.
+  ASSERT_EQ(0, GetTestResult(test_info)->total_part_count());
+
+  // After the previous assertion, there is still none.
+  ASSERT_EQ(0, GetTestResult(test_info)->total_part_count());
+}
+
+#define VERIFY_CODE_LOCATION \
+  const int expected_line = __LINE__ - 1; \
+  const TestInfo* const test_info = GetUnitTestImpl()->current_test_info(); \
+  ASSERT_TRUE(test_info); \
+  EXPECT_STREQ(__FILE__, test_info->file()); \
+  EXPECT_EQ(expected_line, test_info->line())
+
+TEST(CodeLocationForTEST, Verify) {
+  VERIFY_CODE_LOCATION;
+}
+
+class CodeLocationForTESTF : public Test {
+};
+
+TEST_F(CodeLocationForTESTF, Verify) {
+  VERIFY_CODE_LOCATION;
+}
+
+class CodeLocationForTESTP : public TestWithParam<int> {
+};
+
+TEST_P(CodeLocationForTESTP, Verify) {
+  VERIFY_CODE_LOCATION;
+}
+
+INSTANTIATE_TEST_CASE_P(, CodeLocationForTESTP, Values(0));
+
+template <typename T>
+class CodeLocationForTYPEDTEST : public Test {
+};
+
+TYPED_TEST_CASE(CodeLocationForTYPEDTEST, int);
+
+TYPED_TEST(CodeLocationForTYPEDTEST, Verify) {
+  VERIFY_CODE_LOCATION;
+}
+
+template <typename T>
+class CodeLocationForTYPEDTESTP : public Test {
+};
+
+TYPED_TEST_CASE_P(CodeLocationForTYPEDTESTP);
+
+TYPED_TEST_P(CodeLocationForTYPEDTESTP, Verify) {
+  VERIFY_CODE_LOCATION;
+}
+
+REGISTER_TYPED_TEST_CASE_P(CodeLocationForTYPEDTESTP, Verify);
+
+INSTANTIATE_TYPED_TEST_CASE_P(My, CodeLocationForTYPEDTESTP, int);
+
+#undef VERIFY_CODE_LOCATION
+
+// Tests setting up and tearing down a test case.
+
+class SetUpTestCaseTest : public Test {
+ protected:
+  // This will be called once before the first test in this test case
+  // is run.
+  static void SetUpTestCase() {
+    printf("Setting up the test case . . .\n");
+
+    // Initializes some shared resource.  In this simple example, we
+    // just create a C string.  More complex stuff can be done if
+    // desired.
+    shared_resource_ = "123";
+
+    // Increments the number of test cases that have been set up.
+    counter_++;
+
+    // SetUpTestCase() should be called only once.
+    EXPECT_EQ(1, counter_);
+  }
+
+  // This will be called once after the last test in this test case is
+  // run.
+  static void TearDownTestCase() {
+    printf("Tearing down the test case . . .\n");
+
+    // Decrements the number of test cases that have been set up.
+    counter_--;
+
+    // TearDownTestCase() should be called only once.
+    EXPECT_EQ(0, counter_);
+
+    // Cleans up the shared resource.
+    shared_resource_ = NULL;
+  }
+
+  // This will be called before each test in this test case.
+  virtual void SetUp() {
+    // SetUpTestCase() should be called only once, so counter_ should
+    // always be 1.
+    EXPECT_EQ(1, counter_);
+  }
+
+  // Number of test cases that have been set up.
+  static int counter_;
+
+  // Some resource to be shared by all tests in this test case.
+  static const char* shared_resource_;
+};
+
+int SetUpTestCaseTest::counter_ = 0;
+const char* SetUpTestCaseTest::shared_resource_ = NULL;
+
+// A test that uses the shared resource.
+TEST_F(SetUpTestCaseTest, Test1) {
+  EXPECT_STRNE(NULL, shared_resource_);
+}
+
+// Another test that uses the shared resource.
+TEST_F(SetUpTestCaseTest, Test2) {
+  EXPECT_STREQ("123", shared_resource_);
+}
+
+// The InitGoogleTestTest test case tests testing::InitGoogleTest().
+
+// The Flags struct stores a copy of all Google Test flags.
+struct Flags {
+  // Constructs a Flags struct where each flag has its default value.
+  Flags() : also_run_disabled_tests(false),
+            break_on_failure(false),
+            catch_exceptions(false),
+            death_test_use_fork(false),
+            filter(""),
+            list_tests(false),
+            output(""),
+            print_time(true),
+            random_seed(0),
+            repeat(1),
+            shuffle(false),
+            stack_trace_depth(kMaxStackTraceDepth),
+            stream_result_to(""),
+            throw_on_failure(false) {}
+
+  // Factory methods.
+
+  // Creates a Flags struct where the gtest_also_run_disabled_tests flag has
+  // the given value.
+  static Flags AlsoRunDisabledTests(bool also_run_disabled_tests) {
+    Flags flags;
+    flags.also_run_disabled_tests = also_run_disabled_tests;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_break_on_failure flag has
+  // the given value.
+  static Flags BreakOnFailure(bool break_on_failure) {
+    Flags flags;
+    flags.break_on_failure = break_on_failure;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_catch_exceptions flag has
+  // the given value.
+  static Flags CatchExceptions(bool catch_exceptions) {
+    Flags flags;
+    flags.catch_exceptions = catch_exceptions;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_death_test_use_fork flag has
+  // the given value.
+  static Flags DeathTestUseFork(bool death_test_use_fork) {
+    Flags flags;
+    flags.death_test_use_fork = death_test_use_fork;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_filter flag has the given
+  // value.
+  static Flags Filter(const char* filter) {
+    Flags flags;
+    flags.filter = filter;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_list_tests flag has the
+  // given value.
+  static Flags ListTests(bool list_tests) {
+    Flags flags;
+    flags.list_tests = list_tests;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_output flag has the given
+  // value.
+  static Flags Output(const char* output) {
+    Flags flags;
+    flags.output = output;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_print_time flag has the given
+  // value.
+  static Flags PrintTime(bool print_time) {
+    Flags flags;
+    flags.print_time = print_time;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_random_seed flag has
+  // the given value.
+  static Flags RandomSeed(Int32 random_seed) {
+    Flags flags;
+    flags.random_seed = random_seed;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_repeat flag has the given
+  // value.
+  static Flags Repeat(Int32 repeat) {
+    Flags flags;
+    flags.repeat = repeat;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_shuffle flag has
+  // the given value.
+  static Flags Shuffle(bool shuffle) {
+    Flags flags;
+    flags.shuffle = shuffle;
+    return flags;
+  }
+
+  // Creates a Flags struct where the GTEST_FLAG(stack_trace_depth) flag has
+  // the given value.
+  static Flags StackTraceDepth(Int32 stack_trace_depth) {
+    Flags flags;
+    flags.stack_trace_depth = stack_trace_depth;
+    return flags;
+  }
+
+  // Creates a Flags struct where the GTEST_FLAG(stream_result_to) flag has
+  // the given value.
+  static Flags StreamResultTo(const char* stream_result_to) {
+    Flags flags;
+    flags.stream_result_to = stream_result_to;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_throw_on_failure flag has
+  // the given value.
+  static Flags ThrowOnFailure(bool throw_on_failure) {
+    Flags flags;
+    flags.throw_on_failure = throw_on_failure;
+    return flags;
+  }
+
+  // These fields store the flag values.
+  bool also_run_disabled_tests;
+  bool break_on_failure;
+  bool catch_exceptions;
+  bool death_test_use_fork;
+  const char* filter;
+  bool list_tests;
+  const char* output;
+  bool print_time;
+  Int32 random_seed;
+  Int32 repeat;
+  bool shuffle;
+  Int32 stack_trace_depth;
+  const char* stream_result_to;
+  bool throw_on_failure;
+};
+
+// Fixture for testing InitGoogleTest().
+class InitGoogleTestTest : public Test {
+ protected:
+  // Clears the flags before each test.
+  virtual void SetUp() {
+    GTEST_FLAG(also_run_disabled_tests) = false;
+    GTEST_FLAG(break_on_failure) = false;
+    GTEST_FLAG(catch_exceptions) = false;
+    GTEST_FLAG(death_test_use_fork) = false;
+    GTEST_FLAG(filter) = "";
+    GTEST_FLAG(list_tests) = false;
+    GTEST_FLAG(output) = "";
+    GTEST_FLAG(print_time) = true;
+    GTEST_FLAG(random_seed) = 0;
+    GTEST_FLAG(repeat) = 1;
+    GTEST_FLAG(shuffle) = false;
+    GTEST_FLAG(stack_trace_depth) = kMaxStackTraceDepth;
+    GTEST_FLAG(stream_result_to) = "";
+    GTEST_FLAG(throw_on_failure) = false;
+  }
+
+  // Asserts that two narrow or wide string arrays are equal.
+  template <typename CharType>
+  static void AssertStringArrayEq(size_t size1, CharType** array1,
+                                  size_t size2, CharType** array2) {
+    ASSERT_EQ(size1, size2) << " Array sizes different.";
+
+    for (size_t i = 0; i != size1; i++) {
+      ASSERT_STREQ(array1[i], array2[i]) << " where i == " << i;
+    }
+  }
+
+  // Verifies that the flag values match the expected values.
+  static void CheckFlags(const Flags& expected) {
+    EXPECT_EQ(expected.also_run_disabled_tests,
+              GTEST_FLAG(also_run_disabled_tests));
+    EXPECT_EQ(expected.break_on_failure, GTEST_FLAG(break_on_failure));
+    EXPECT_EQ(expected.catch_exceptions, GTEST_FLAG(catch_exceptions));
+    EXPECT_EQ(expected.death_test_use_fork, GTEST_FLAG(death_test_use_fork));
+    EXPECT_STREQ(expected.filter, GTEST_FLAG(filter).c_str());
+    EXPECT_EQ(expected.list_tests, GTEST_FLAG(list_tests));
+    EXPECT_STREQ(expected.output, GTEST_FLAG(output).c_str());
+    EXPECT_EQ(expected.print_time, GTEST_FLAG(print_time));
+    EXPECT_EQ(expected.random_seed, GTEST_FLAG(random_seed));
+    EXPECT_EQ(expected.repeat, GTEST_FLAG(repeat));
+    EXPECT_EQ(expected.shuffle, GTEST_FLAG(shuffle));
+    EXPECT_EQ(expected.stack_trace_depth, GTEST_FLAG(stack_trace_depth));
+    EXPECT_STREQ(expected.stream_result_to,
+                 GTEST_FLAG(stream_result_to).c_str());
+    EXPECT_EQ(expected.throw_on_failure, GTEST_FLAG(throw_on_failure));
+  }
+
+  // Parses a command line (specified by argc1 and argv1), then
+  // verifies that the flag values are expected and that the
+  // recognized flags are removed from the command line.
+  template <typename CharType>
+  static void TestParsingFlags(int argc1, const CharType** argv1,
+                               int argc2, const CharType** argv2,
+                               const Flags& expected, bool should_print_help) {
+    const bool saved_help_flag = ::testing::internal::g_help_flag;
+    ::testing::internal::g_help_flag = false;
+
+#if GTEST_HAS_STREAM_REDIRECTION
+    CaptureStdout();
+#endif
+
+    // Parses the command line.
+    internal::ParseGoogleTestFlagsOnly(&argc1, const_cast<CharType**>(argv1));
+
+#if GTEST_HAS_STREAM_REDIRECTION
+    const std::string captured_stdout = GetCapturedStdout();
+#endif
+
+    // Verifies the flag values.
+    CheckFlags(expected);
+
+    // Verifies that the recognized flags are removed from the command
+    // line.
+    AssertStringArrayEq(argc1 + 1, argv1, argc2 + 1, argv2);
+
+    // ParseGoogleTestFlagsOnly should neither set g_help_flag nor print the
+    // help message for the flags it recognizes.
+    EXPECT_EQ(should_print_help, ::testing::internal::g_help_flag);
+
+#if GTEST_HAS_STREAM_REDIRECTION
+    const char* const expected_help_fragment =
+        "This program contains tests written using";
+    if (should_print_help) {
+      EXPECT_PRED_FORMAT2(IsSubstring, expected_help_fragment, captured_stdout);
+    } else {
+      EXPECT_PRED_FORMAT2(IsNotSubstring,
+                          expected_help_fragment, captured_stdout);
+    }
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+    ::testing::internal::g_help_flag = saved_help_flag;
+  }
+
+  // This macro wraps TestParsingFlags s.t. the user doesn't need
+  // to specify the array sizes.
+
+#define GTEST_TEST_PARSING_FLAGS_(argv1, argv2, expected, should_print_help) \
+  TestParsingFlags(sizeof(argv1)/sizeof(*argv1) - 1, argv1, \
+                   sizeof(argv2)/sizeof(*argv2) - 1, argv2, \
+                   expected, should_print_help)
+};
+
+// Tests parsing an empty command line.
+TEST_F(InitGoogleTestTest, Empty) {
+  const char* argv[] = {
+    NULL
+  };
+
+  const char* argv2[] = {
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags(), false);
+}
+
+// Tests parsing a command line that has no flag.
+TEST_F(InitGoogleTestTest, NoFlag) {
+  const char* argv[] = {
+    "foo.exe",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags(), false);
+}
+
+// Tests parsing a bad --gtest_filter flag.
+TEST_F(InitGoogleTestTest, FilterBad) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_filter",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    "--gtest_filter",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Filter(""), true);
+}
+
+// Tests parsing an empty --gtest_filter flag.
+TEST_F(InitGoogleTestTest, FilterEmpty) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_filter=",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Filter(""), false);
+}
+
+// Tests parsing a non-empty --gtest_filter flag.
+TEST_F(InitGoogleTestTest, FilterNonEmpty) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_filter=abc",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Filter("abc"), false);
+}
+
+// Tests parsing --gtest_break_on_failure.
+TEST_F(InitGoogleTestTest, BreakOnFailureWithoutValue) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_break_on_failure",
+    NULL
+};
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::BreakOnFailure(true), false);
+}
+
+// Tests parsing --gtest_break_on_failure=0.
+TEST_F(InitGoogleTestTest, BreakOnFailureFalse_0) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_break_on_failure=0",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::BreakOnFailure(false), false);
+}
+
+// Tests parsing --gtest_break_on_failure=f.
+TEST_F(InitGoogleTestTest, BreakOnFailureFalse_f) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_break_on_failure=f",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::BreakOnFailure(false), false);
+}
+
+// Tests parsing --gtest_break_on_failure=F.
+TEST_F(InitGoogleTestTest, BreakOnFailureFalse_F) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_break_on_failure=F",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::BreakOnFailure(false), false);
+}
+
+// Tests parsing a --gtest_break_on_failure flag that has a "true"
+// definition.
+TEST_F(InitGoogleTestTest, BreakOnFailureTrue) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_break_on_failure=1",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::BreakOnFailure(true), false);
+}
+
+// Tests parsing --gtest_catch_exceptions.
+TEST_F(InitGoogleTestTest, CatchExceptions) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_catch_exceptions",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::CatchExceptions(true), false);
+}
+
+// Tests parsing --gtest_death_test_use_fork.
+TEST_F(InitGoogleTestTest, DeathTestUseFork) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_death_test_use_fork",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::DeathTestUseFork(true), false);
+}
+
+// Tests having the same flag twice with different values.  The
+// expected behavior is that the one coming last takes precedence.
+TEST_F(InitGoogleTestTest, DuplicatedFlags) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_filter=a",
+    "--gtest_filter=b",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Filter("b"), false);
+}
+
+// Tests having an unrecognized flag on the command line.
+TEST_F(InitGoogleTestTest, UnrecognizedFlag) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_break_on_failure",
+    "bar",  // Unrecognized by Google Test.
+    "--gtest_filter=b",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    "bar",
+    NULL
+  };
+
+  Flags flags;
+  flags.break_on_failure = true;
+  flags.filter = "b";
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, flags, false);
+}
+
+// Tests having a --gtest_list_tests flag
+TEST_F(InitGoogleTestTest, ListTestsFlag) {
+    const char* argv[] = {
+      "foo.exe",
+      "--gtest_list_tests",
+      NULL
+    };
+
+    const char* argv2[] = {
+      "foo.exe",
+      NULL
+    };
+
+    GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ListTests(true), false);
+}
+
+// Tests having a --gtest_list_tests flag with a "true" value
+TEST_F(InitGoogleTestTest, ListTestsTrue) {
+    const char* argv[] = {
+      "foo.exe",
+      "--gtest_list_tests=1",
+      NULL
+    };
+
+    const char* argv2[] = {
+      "foo.exe",
+      NULL
+    };
+
+    GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ListTests(true), false);
+}
+
+// Tests having a --gtest_list_tests flag with a "false" value
+TEST_F(InitGoogleTestTest, ListTestsFalse) {
+    const char* argv[] = {
+      "foo.exe",
+      "--gtest_list_tests=0",
+      NULL
+    };
+
+    const char* argv2[] = {
+      "foo.exe",
+      NULL
+    };
+
+    GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ListTests(false), false);
+}
+
+// Tests parsing --gtest_list_tests=f.
+TEST_F(InitGoogleTestTest, ListTestsFalse_f) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_list_tests=f",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ListTests(false), false);
+}
+
+// Tests parsing --gtest_list_tests=F.
+TEST_F(InitGoogleTestTest, ListTestsFalse_F) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_list_tests=F",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ListTests(false), false);
+}
+
+// Tests parsing --gtest_output (invalid).
+TEST_F(InitGoogleTestTest, OutputEmpty) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_output",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    "--gtest_output",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags(), true);
+}
+
+// Tests parsing --gtest_output=xml
+TEST_F(InitGoogleTestTest, OutputXml) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_output=xml",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Output("xml"), false);
+}
+
+// Tests parsing --gtest_output=xml:file
+TEST_F(InitGoogleTestTest, OutputXmlFile) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_output=xml:file",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Output("xml:file"), false);
+}
+
+// Tests parsing --gtest_output=xml:directory/path/
+TEST_F(InitGoogleTestTest, OutputXmlDirectory) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_output=xml:directory/path/",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2,
+                            Flags::Output("xml:directory/path/"), false);
+}
+
+// Tests having a --gtest_print_time flag
+TEST_F(InitGoogleTestTest, PrintTimeFlag) {
+    const char* argv[] = {
+      "foo.exe",
+      "--gtest_print_time",
+      NULL
+    };
+
+    const char* argv2[] = {
+      "foo.exe",
+      NULL
+    };
+
+    GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::PrintTime(true), false);
+}
+
+// Tests having a --gtest_print_time flag with a "true" value
+TEST_F(InitGoogleTestTest, PrintTimeTrue) {
+    const char* argv[] = {
+      "foo.exe",
+      "--gtest_print_time=1",
+      NULL
+    };
+
+    const char* argv2[] = {
+      "foo.exe",
+      NULL
+    };
+
+    GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::PrintTime(true), false);
+}
+
+// Tests having a --gtest_print_time flag with a "false" value
+TEST_F(InitGoogleTestTest, PrintTimeFalse) {
+    const char* argv[] = {
+      "foo.exe",
+      "--gtest_print_time=0",
+      NULL
+    };
+
+    const char* argv2[] = {
+      "foo.exe",
+      NULL
+    };
+
+    GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::PrintTime(false), false);
+}
+
+// Tests parsing --gtest_print_time=f.
+TEST_F(InitGoogleTestTest, PrintTimeFalse_f) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_print_time=f",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::PrintTime(false), false);
+}
+
+// Tests parsing --gtest_print_time=F.
+TEST_F(InitGoogleTestTest, PrintTimeFalse_F) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_print_time=F",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::PrintTime(false), false);
+}
+
+// Tests parsing --gtest_random_seed=number
+TEST_F(InitGoogleTestTest, RandomSeed) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_random_seed=1000",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::RandomSeed(1000), false);
+}
+
+// Tests parsing --gtest_repeat=number
+TEST_F(InitGoogleTestTest, Repeat) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_repeat=1000",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Repeat(1000), false);
+}
+
+// Tests having a --gtest_also_run_disabled_tests flag
+TEST_F(InitGoogleTestTest, AlsoRunDisabledTestsFlag) {
+    const char* argv[] = {
+      "foo.exe",
+      "--gtest_also_run_disabled_tests",
+      NULL
+    };
+
+    const char* argv2[] = {
+      "foo.exe",
+      NULL
+    };
+
+    GTEST_TEST_PARSING_FLAGS_(argv, argv2,
+                              Flags::AlsoRunDisabledTests(true), false);
+}
+
+// Tests having a --gtest_also_run_disabled_tests flag with a "true" value
+TEST_F(InitGoogleTestTest, AlsoRunDisabledTestsTrue) {
+    const char* argv[] = {
+      "foo.exe",
+      "--gtest_also_run_disabled_tests=1",
+      NULL
+    };
+
+    const char* argv2[] = {
+      "foo.exe",
+      NULL
+    };
+
+    GTEST_TEST_PARSING_FLAGS_(argv, argv2,
+                              Flags::AlsoRunDisabledTests(true), false);
+}
+
+// Tests having a --gtest_also_run_disabled_tests flag with a "false" value
+TEST_F(InitGoogleTestTest, AlsoRunDisabledTestsFalse) {
+    const char* argv[] = {
+      "foo.exe",
+      "--gtest_also_run_disabled_tests=0",
+      NULL
+    };
+
+    const char* argv2[] = {
+      "foo.exe",
+      NULL
+    };
+
+    GTEST_TEST_PARSING_FLAGS_(argv, argv2,
+                              Flags::AlsoRunDisabledTests(false), false);
+}
+
+// Tests parsing --gtest_shuffle.
+TEST_F(InitGoogleTestTest, ShuffleWithoutValue) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_shuffle",
+    NULL
+};
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Shuffle(true), false);
+}
+
+// Tests parsing --gtest_shuffle=0.
+TEST_F(InitGoogleTestTest, ShuffleFalse_0) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_shuffle=0",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Shuffle(false), false);
+}
+
+// Tests parsing a --gtest_shuffle flag that has a "true"
+// definition.
+TEST_F(InitGoogleTestTest, ShuffleTrue) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_shuffle=1",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Shuffle(true), false);
+}
+
+// Tests parsing --gtest_stack_trace_depth=number.
+TEST_F(InitGoogleTestTest, StackTraceDepth) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_stack_trace_depth=5",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::StackTraceDepth(5), false);
+}
+
+TEST_F(InitGoogleTestTest, StreamResultTo) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_stream_result_to=localhost:1234",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(
+      argv, argv2, Flags::StreamResultTo("localhost:1234"), false);
+}
+
+// Tests parsing --gtest_throw_on_failure.
+TEST_F(InitGoogleTestTest, ThrowOnFailureWithoutValue) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_throw_on_failure",
+    NULL
+};
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ThrowOnFailure(true), false);
+}
+
+// Tests parsing --gtest_throw_on_failure=0.
+TEST_F(InitGoogleTestTest, ThrowOnFailureFalse_0) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_throw_on_failure=0",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ThrowOnFailure(false), false);
+}
+
+// Tests parsing a --gtest_throw_on_failure flag that has a "true"
+// definition.
+TEST_F(InitGoogleTestTest, ThrowOnFailureTrue) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_throw_on_failure=1",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ThrowOnFailure(true), false);
+}
+
+#if GTEST_OS_WINDOWS
+// Tests parsing wide strings.
+TEST_F(InitGoogleTestTest, WideStrings) {
+  const wchar_t* argv[] = {
+    L"foo.exe",
+    L"--gtest_filter=Foo*",
+    L"--gtest_list_tests=1",
+    L"--gtest_break_on_failure",
+    L"--non_gtest_flag",
+    NULL
+  };
+
+  const wchar_t* argv2[] = {
+    L"foo.exe",
+    L"--non_gtest_flag",
+    NULL
+  };
+
+  Flags expected_flags;
+  expected_flags.break_on_failure = true;
+  expected_flags.filter = "Foo*";
+  expected_flags.list_tests = true;
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, expected_flags, false);
+}
+# endif  // GTEST_OS_WINDOWS
+
+#if GTEST_USE_OWN_FLAGFILE_FLAG_
+class FlagfileTest : public InitGoogleTestTest {
+ public:
+  virtual void SetUp() {
+    InitGoogleTestTest::SetUp();
+
+    testdata_path_.Set(internal::FilePath(
+        internal::TempDir() + internal::GetCurrentExecutableName().string() +
+        "_flagfile_test"));
+    testing::internal::posix::RmDir(testdata_path_.c_str());
+    EXPECT_TRUE(testdata_path_.CreateFolder());
+  }
+
+  virtual void TearDown() {
+    testing::internal::posix::RmDir(testdata_path_.c_str());
+    InitGoogleTestTest::TearDown();
+  }
+
+  internal::FilePath CreateFlagfile(const char* contents) {
+    internal::FilePath file_path(internal::FilePath::GenerateUniqueFileName(
+        testdata_path_, internal::FilePath("unique"), "txt"));
+    FILE* f = testing::internal::posix::FOpen(file_path.c_str(), "w");
+    fprintf(f, "%s", contents);
+    fclose(f);
+    return file_path;
+  }
+
+ private:
+  internal::FilePath testdata_path_;
+};
+
+// Tests an empty flagfile.
+TEST_F(FlagfileTest, Empty) {
+  internal::FilePath flagfile_path(CreateFlagfile(""));
+  std::string flagfile_flag =
+      std::string("--" GTEST_FLAG_PREFIX_ "flagfile=") + flagfile_path.c_str();
+
+  const char* argv[] = {
+    "foo.exe",
+    flagfile_flag.c_str(),
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags(), false);
+}
+
+// Tests passing a non-empty --gtest_filter flag via --gtest_flagfile.
+TEST_F(FlagfileTest, FilterNonEmpty) {
+  internal::FilePath flagfile_path(CreateFlagfile(
+      "--"  GTEST_FLAG_PREFIX_  "filter=abc"));
+  std::string flagfile_flag =
+      std::string("--" GTEST_FLAG_PREFIX_ "flagfile=") + flagfile_path.c_str();
+
+  const char* argv[] = {
+    "foo.exe",
+    flagfile_flag.c_str(),
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Filter("abc"), false);
+}
+
+// Tests passing several flags via --gtest_flagfile.
+TEST_F(FlagfileTest, SeveralFlags) {
+  internal::FilePath flagfile_path(CreateFlagfile(
+      "--"  GTEST_FLAG_PREFIX_  "filter=abc\n"
+      "--"  GTEST_FLAG_PREFIX_  "break_on_failure\n"
+      "--"  GTEST_FLAG_PREFIX_  "list_tests"));
+  std::string flagfile_flag =
+      std::string("--" GTEST_FLAG_PREFIX_ "flagfile=") + flagfile_path.c_str();
+
+  const char* argv[] = {
+    "foo.exe",
+    flagfile_flag.c_str(),
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  Flags expected_flags;
+  expected_flags.break_on_failure = true;
+  expected_flags.filter = "abc";
+  expected_flags.list_tests = true;
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, expected_flags, false);
+}
+#endif  // GTEST_USE_OWN_FLAGFILE_FLAG_
+
+// Tests current_test_info() in UnitTest.
+class CurrentTestInfoTest : public Test {
+ protected:
+  // Tests that current_test_info() returns NULL before the first test in
+  // the test case is run.
+  static void SetUpTestCase() {
+    // There should be no tests running at this point.
+    const TestInfo* test_info =
+      UnitTest::GetInstance()->current_test_info();
+    EXPECT_TRUE(test_info == NULL)
+        << "There should be no tests running at this point.";
+  }
+
+  // Tests that current_test_info() returns NULL after the last test in
+  // the test case has run.
+  static void TearDownTestCase() {
+    const TestInfo* test_info =
+      UnitTest::GetInstance()->current_test_info();
+    EXPECT_TRUE(test_info == NULL)
+        << "There should be no tests running at this point.";
+  }
+};
+
+// Tests that current_test_info() returns TestInfo for currently running
+// test by checking the expected test name against the actual one.
+TEST_F(CurrentTestInfoTest, WorksForFirstTestInATestCase) {
+  const TestInfo* test_info =
+    UnitTest::GetInstance()->current_test_info();
+  ASSERT_TRUE(NULL != test_info)
+      << "There is a test running so we should have a valid TestInfo.";
+  EXPECT_STREQ("CurrentTestInfoTest", test_info->test_case_name())
+      << "Expected the name of the currently running test case.";
+  EXPECT_STREQ("WorksForFirstTestInATestCase", test_info->name())
+      << "Expected the name of the currently running test.";
+}
+
+// Tests that current_test_info() returns TestInfo for currently running
+// test by checking the expected test name against the actual one.  We
+// use this test to see that the TestInfo object actually changed from
+// the previous invocation.
+TEST_F(CurrentTestInfoTest, WorksForSecondTestInATestCase) {
+  const TestInfo* test_info =
+    UnitTest::GetInstance()->current_test_info();
+  ASSERT_TRUE(NULL != test_info)
+      << "There is a test running so we should have a valid TestInfo.";
+  EXPECT_STREQ("CurrentTestInfoTest", test_info->test_case_name())
+      << "Expected the name of the currently running test case.";
+  EXPECT_STREQ("WorksForSecondTestInATestCase", test_info->name())
+      << "Expected the name of the currently running test.";
+}
+
+}  // namespace testing
+
+// These two lines test that we can define tests in a namespace that
+// has the name "testing" and is nested in another namespace.
+namespace my_namespace {
+namespace testing {
+
+// Makes sure that TEST knows to use ::testing::Test instead of
+// ::my_namespace::testing::Test.
+class Test {};
+
+// Makes sure that an assertion knows to use ::testing::Message instead of
+// ::my_namespace::testing::Message.
+class Message {};
+
+// Makes sure that an assertion knows to use
+// ::testing::AssertionResult instead of
+// ::my_namespace::testing::AssertionResult.
+class AssertionResult {};
+
+// Tests that an assertion that should succeed works as expected.
+TEST(NestedTestingNamespaceTest, Success) {
+  EXPECT_EQ(1, 1) << "This shouldn't fail.";
+}
+
+// Tests that an assertion that should fail works as expected.
+TEST(NestedTestingNamespaceTest, Failure) {
+  EXPECT_FATAL_FAILURE(FAIL() << "This failure is expected.",
+                       "This failure is expected.");
+}
+
+}  // namespace testing
+}  // namespace my_namespace
+
+// Tests that one can call superclass SetUp and TearDown methods--
+// that is, that they are not private.
+// No tests are based on this fixture; the test "passes" if it compiles
+// successfully.
+class ProtectedFixtureMethodsTest : public Test {
+ protected:
+  virtual void SetUp() {
+    Test::SetUp();
+  }
+  virtual void TearDown() {
+    Test::TearDown();
+  }
+};
+
+// StreamingAssertionsTest tests the streaming versions of a representative
+// sample of assertions.
+TEST(StreamingAssertionsTest, Unconditional) {
+  SUCCEED() << "expected success";
+  EXPECT_NONFATAL_FAILURE(ADD_FAILURE() << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(FAIL() << "expected failure",
+                       "expected failure");
+}
+
+#ifdef __BORLANDC__
+// Silences warnings: "Condition is always true", "Unreachable code"
+# pragma option push -w-ccc -w-rch
+#endif
+
+TEST(StreamingAssertionsTest, Truth) {
+  EXPECT_TRUE(true) << "unexpected failure";
+  ASSERT_TRUE(true) << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(false) << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_TRUE(false) << "expected failure",
+                       "expected failure");
+}
+
+TEST(StreamingAssertionsTest, Truth2) {
+  EXPECT_FALSE(false) << "unexpected failure";
+  ASSERT_FALSE(false) << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(true) << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_FALSE(true) << "expected failure",
+                       "expected failure");
+}
+
+#ifdef __BORLANDC__
+// Restores warnings after previous "#pragma option push" supressed them
+# pragma option pop
+#endif
+
+TEST(StreamingAssertionsTest, IntegerEquals) {
+  EXPECT_EQ(1, 1) << "unexpected failure";
+  ASSERT_EQ(1, 1) << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(1, 2) << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(1, 2) << "expected failure",
+                       "expected failure");
+}
+
+TEST(StreamingAssertionsTest, IntegerLessThan) {
+  EXPECT_LT(1, 2) << "unexpected failure";
+  ASSERT_LT(1, 2) << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_LT(2, 1) << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_LT(2, 1) << "expected failure",
+                       "expected failure");
+}
+
+TEST(StreamingAssertionsTest, StringsEqual) {
+  EXPECT_STREQ("foo", "foo") << "unexpected failure";
+  ASSERT_STREQ("foo", "foo") << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_STREQ("foo", "bar") << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_STREQ("foo", "bar") << "expected failure",
+                       "expected failure");
+}
+
+TEST(StreamingAssertionsTest, StringsNotEqual) {
+  EXPECT_STRNE("foo", "bar") << "unexpected failure";
+  ASSERT_STRNE("foo", "bar") << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_STRNE("foo", "foo") << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_STRNE("foo", "foo") << "expected failure",
+                       "expected failure");
+}
+
+TEST(StreamingAssertionsTest, StringsEqualIgnoringCase) {
+  EXPECT_STRCASEEQ("foo", "FOO") << "unexpected failure";
+  ASSERT_STRCASEEQ("foo", "FOO") << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_STRCASEEQ("foo", "bar") << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_STRCASEEQ("foo", "bar") << "expected failure",
+                       "expected failure");
+}
+
+TEST(StreamingAssertionsTest, StringNotEqualIgnoringCase) {
+  EXPECT_STRCASENE("foo", "bar") << "unexpected failure";
+  ASSERT_STRCASENE("foo", "bar") << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_STRCASENE("foo", "FOO") << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_STRCASENE("bar", "BAR") << "expected failure",
+                       "expected failure");
+}
+
+TEST(StreamingAssertionsTest, FloatingPointEquals) {
+  EXPECT_FLOAT_EQ(1.0, 1.0) << "unexpected failure";
+  ASSERT_FLOAT_EQ(1.0, 1.0) << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(0.0, 1.0) << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_FLOAT_EQ(0.0, 1.0) << "expected failure",
+                       "expected failure");
+}
+
+#if GTEST_HAS_EXCEPTIONS
+
+TEST(StreamingAssertionsTest, Throw) {
+  EXPECT_THROW(ThrowAnInteger(), int) << "unexpected failure";
+  ASSERT_THROW(ThrowAnInteger(), int) << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_THROW(ThrowAnInteger(), bool) <<
+                          "expected failure", "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_THROW(ThrowAnInteger(), bool) <<
+                       "expected failure", "expected failure");
+}
+
+TEST(StreamingAssertionsTest, NoThrow) {
+  EXPECT_NO_THROW(ThrowNothing()) << "unexpected failure";
+  ASSERT_NO_THROW(ThrowNothing()) << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_NO_THROW(ThrowAnInteger()) <<
+                          "expected failure", "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_NO_THROW(ThrowAnInteger()) <<
+                       "expected failure", "expected failure");
+}
+
+TEST(StreamingAssertionsTest, AnyThrow) {
+  EXPECT_ANY_THROW(ThrowAnInteger()) << "unexpected failure";
+  ASSERT_ANY_THROW(ThrowAnInteger()) << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_ANY_THROW(ThrowNothing()) <<
+                          "expected failure", "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_ANY_THROW(ThrowNothing()) <<
+                       "expected failure", "expected failure");
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// Tests that Google Test correctly decides whether to use colors in the output.
+
+TEST(ColoredOutputTest, UsesColorsWhenGTestColorFlagIsYes) {
+  GTEST_FLAG(color) = "yes";
+
+  SetEnv("TERM", "xterm");  // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+  EXPECT_TRUE(ShouldUseColor(false));  // Stdout is not a TTY.
+
+  SetEnv("TERM", "dumb");  // TERM doesn't support colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+  EXPECT_TRUE(ShouldUseColor(false));  // Stdout is not a TTY.
+}
+
+TEST(ColoredOutputTest, UsesColorsWhenGTestColorFlagIsAliasOfYes) {
+  SetEnv("TERM", "dumb");  // TERM doesn't support colors.
+
+  GTEST_FLAG(color) = "True";
+  EXPECT_TRUE(ShouldUseColor(false));  // Stdout is not a TTY.
+
+  GTEST_FLAG(color) = "t";
+  EXPECT_TRUE(ShouldUseColor(false));  // Stdout is not a TTY.
+
+  GTEST_FLAG(color) = "1";
+  EXPECT_TRUE(ShouldUseColor(false));  // Stdout is not a TTY.
+}
+
+TEST(ColoredOutputTest, UsesNoColorWhenGTestColorFlagIsNo) {
+  GTEST_FLAG(color) = "no";
+
+  SetEnv("TERM", "xterm");  // TERM supports colors.
+  EXPECT_FALSE(ShouldUseColor(true));  // Stdout is a TTY.
+  EXPECT_FALSE(ShouldUseColor(false));  // Stdout is not a TTY.
+
+  SetEnv("TERM", "dumb");  // TERM doesn't support colors.
+  EXPECT_FALSE(ShouldUseColor(true));  // Stdout is a TTY.
+  EXPECT_FALSE(ShouldUseColor(false));  // Stdout is not a TTY.
+}
+
+TEST(ColoredOutputTest, UsesNoColorWhenGTestColorFlagIsInvalid) {
+  SetEnv("TERM", "xterm");  // TERM supports colors.
+
+  GTEST_FLAG(color) = "F";
+  EXPECT_FALSE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  GTEST_FLAG(color) = "0";
+  EXPECT_FALSE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  GTEST_FLAG(color) = "unknown";
+  EXPECT_FALSE(ShouldUseColor(true));  // Stdout is a TTY.
+}
+
+TEST(ColoredOutputTest, UsesColorsWhenStdoutIsTty) {
+  GTEST_FLAG(color) = "auto";
+
+  SetEnv("TERM", "xterm");  // TERM supports colors.
+  EXPECT_FALSE(ShouldUseColor(false));  // Stdout is not a TTY.
+  EXPECT_TRUE(ShouldUseColor(true));    // Stdout is a TTY.
+}
+
+TEST(ColoredOutputTest, UsesColorsWhenTermSupportsColors) {
+  GTEST_FLAG(color) = "auto";
+
+#if GTEST_OS_WINDOWS
+  // On Windows, we ignore the TERM variable as it's usually not set.
+
+  SetEnv("TERM", "dumb");
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "");
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "xterm");
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+#else
+  // On non-Windows platforms, we rely on TERM to determine if the
+  // terminal supports colors.
+
+  SetEnv("TERM", "dumb");  // TERM doesn't support colors.
+  EXPECT_FALSE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "emacs");  // TERM doesn't support colors.
+  EXPECT_FALSE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "vt100");  // TERM doesn't support colors.
+  EXPECT_FALSE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "xterm-mono");  // TERM doesn't support colors.
+  EXPECT_FALSE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "xterm");  // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "xterm-color");  // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "xterm-256color");  // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "screen");  // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "screen-256color");  // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "rxvt-unicode");  // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "rxvt-unicode-256color");  // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "linux");  // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "cygwin");  // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+#endif  // GTEST_OS_WINDOWS
+}
+
+// Verifies that StaticAssertTypeEq works in a namespace scope.
+
+static bool dummy1 GTEST_ATTRIBUTE_UNUSED_ = StaticAssertTypeEq<bool, bool>();
+static bool dummy2 GTEST_ATTRIBUTE_UNUSED_ =
+    StaticAssertTypeEq<const int, const int>();
+
+// Verifies that StaticAssertTypeEq works in a class.
+
+template <typename T>
+class StaticAssertTypeEqTestHelper {
+ public:
+  StaticAssertTypeEqTestHelper() { StaticAssertTypeEq<bool, T>(); }
+};
+
+TEST(StaticAssertTypeEqTest, WorksInClass) {
+  StaticAssertTypeEqTestHelper<bool>();
+}
+
+// Verifies that StaticAssertTypeEq works inside a function.
+
+typedef int IntAlias;
+
+TEST(StaticAssertTypeEqTest, CompilesForEqualTypes) {
+  StaticAssertTypeEq<int, IntAlias>();
+  StaticAssertTypeEq<int*, IntAlias*>();
+}
+
+TEST(GetCurrentOsStackTraceExceptTopTest, ReturnsTheStackTrace) {
+  testing::UnitTest* const unit_test = testing::UnitTest::GetInstance();
+
+  // We don't have a stack walker in Google Test yet.
+  EXPECT_STREQ("", GetCurrentOsStackTraceExceptTop(unit_test, 0).c_str());
+  EXPECT_STREQ("", GetCurrentOsStackTraceExceptTop(unit_test, 1).c_str());
+}
+
+TEST(HasNonfatalFailureTest, ReturnsFalseWhenThereIsNoFailure) {
+  EXPECT_FALSE(HasNonfatalFailure());
+}
+
+static void FailFatally() { FAIL(); }
+
+TEST(HasNonfatalFailureTest, ReturnsFalseWhenThereIsOnlyFatalFailure) {
+  FailFatally();
+  const bool has_nonfatal_failure = HasNonfatalFailure();
+  ClearCurrentTestPartResults();
+  EXPECT_FALSE(has_nonfatal_failure);
+}
+
+TEST(HasNonfatalFailureTest, ReturnsTrueWhenThereIsNonfatalFailure) {
+  ADD_FAILURE();
+  const bool has_nonfatal_failure = HasNonfatalFailure();
+  ClearCurrentTestPartResults();
+  EXPECT_TRUE(has_nonfatal_failure);
+}
+
+TEST(HasNonfatalFailureTest, ReturnsTrueWhenThereAreFatalAndNonfatalFailures) {
+  FailFatally();
+  ADD_FAILURE();
+  const bool has_nonfatal_failure = HasNonfatalFailure();
+  ClearCurrentTestPartResults();
+  EXPECT_TRUE(has_nonfatal_failure);
+}
+
+// A wrapper for calling HasNonfatalFailure outside of a test body.
+static bool HasNonfatalFailureHelper() {
+  return testing::Test::HasNonfatalFailure();
+}
+
+TEST(HasNonfatalFailureTest, WorksOutsideOfTestBody) {
+  EXPECT_FALSE(HasNonfatalFailureHelper());
+}
+
+TEST(HasNonfatalFailureTest, WorksOutsideOfTestBody2) {
+  ADD_FAILURE();
+  const bool has_nonfatal_failure = HasNonfatalFailureHelper();
+  ClearCurrentTestPartResults();
+  EXPECT_TRUE(has_nonfatal_failure);
+}
+
+TEST(HasFailureTest, ReturnsFalseWhenThereIsNoFailure) {
+  EXPECT_FALSE(HasFailure());
+}
+
+TEST(HasFailureTest, ReturnsTrueWhenThereIsFatalFailure) {
+  FailFatally();
+  const bool has_failure = HasFailure();
+  ClearCurrentTestPartResults();
+  EXPECT_TRUE(has_failure);
+}
+
+TEST(HasFailureTest, ReturnsTrueWhenThereIsNonfatalFailure) {
+  ADD_FAILURE();
+  const bool has_failure = HasFailure();
+  ClearCurrentTestPartResults();
+  EXPECT_TRUE(has_failure);
+}
+
+TEST(HasFailureTest, ReturnsTrueWhenThereAreFatalAndNonfatalFailures) {
+  FailFatally();
+  ADD_FAILURE();
+  const bool has_failure = HasFailure();
+  ClearCurrentTestPartResults();
+  EXPECT_TRUE(has_failure);
+}
+
+// A wrapper for calling HasFailure outside of a test body.
+static bool HasFailureHelper() { return testing::Test::HasFailure(); }
+
+TEST(HasFailureTest, WorksOutsideOfTestBody) {
+  EXPECT_FALSE(HasFailureHelper());
+}
+
+TEST(HasFailureTest, WorksOutsideOfTestBody2) {
+  ADD_FAILURE();
+  const bool has_failure = HasFailureHelper();
+  ClearCurrentTestPartResults();
+  EXPECT_TRUE(has_failure);
+}
+
+class TestListener : public EmptyTestEventListener {
+ public:
+  TestListener() : on_start_counter_(NULL), is_destroyed_(NULL) {}
+  TestListener(int* on_start_counter, bool* is_destroyed)
+      : on_start_counter_(on_start_counter),
+        is_destroyed_(is_destroyed) {}
+
+  virtual ~TestListener() {
+    if (is_destroyed_)
+      *is_destroyed_ = true;
+  }
+
+ protected:
+  virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {
+    if (on_start_counter_ != NULL)
+      (*on_start_counter_)++;
+  }
+
+ private:
+  int* on_start_counter_;
+  bool* is_destroyed_;
+};
+
+// Tests the constructor.
+TEST(TestEventListenersTest, ConstructionWorks) {
+  TestEventListeners listeners;
+
+  EXPECT_TRUE(TestEventListenersAccessor::GetRepeater(&listeners) != NULL);
+  EXPECT_TRUE(listeners.default_result_printer() == NULL);
+  EXPECT_TRUE(listeners.default_xml_generator() == NULL);
+}
+
+// Tests that the TestEventListeners destructor deletes all the listeners it
+// owns.
+TEST(TestEventListenersTest, DestructionWorks) {
+  bool default_result_printer_is_destroyed = false;
+  bool default_xml_printer_is_destroyed = false;
+  bool extra_listener_is_destroyed = false;
+  TestListener* default_result_printer = new TestListener(
+      NULL, &default_result_printer_is_destroyed);
+  TestListener* default_xml_printer = new TestListener(
+      NULL, &default_xml_printer_is_destroyed);
+  TestListener* extra_listener = new TestListener(
+      NULL, &extra_listener_is_destroyed);
+
+  {
+    TestEventListeners listeners;
+    TestEventListenersAccessor::SetDefaultResultPrinter(&listeners,
+                                                        default_result_printer);
+    TestEventListenersAccessor::SetDefaultXmlGenerator(&listeners,
+                                                       default_xml_printer);
+    listeners.Append(extra_listener);
+  }
+  EXPECT_TRUE(default_result_printer_is_destroyed);
+  EXPECT_TRUE(default_xml_printer_is_destroyed);
+  EXPECT_TRUE(extra_listener_is_destroyed);
+}
+
+// Tests that a listener Append'ed to a TestEventListeners list starts
+// receiving events.
+TEST(TestEventListenersTest, Append) {
+  int on_start_counter = 0;
+  bool is_destroyed = false;
+  TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+  {
+    TestEventListeners listeners;
+    listeners.Append(listener);
+    TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+        *UnitTest::GetInstance());
+    EXPECT_EQ(1, on_start_counter);
+  }
+  EXPECT_TRUE(is_destroyed);
+}
+
+// Tests that listeners receive events in the order they were appended to
+// the list, except for *End requests, which must be received in the reverse
+// order.
+class SequenceTestingListener : public EmptyTestEventListener {
+ public:
+  SequenceTestingListener(std::vector<std::string>* vector, const char* id)
+      : vector_(vector), id_(id) {}
+
+ protected:
+  virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {
+    vector_->push_back(GetEventDescription("OnTestProgramStart"));
+  }
+
+  virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {
+    vector_->push_back(GetEventDescription("OnTestProgramEnd"));
+  }
+
+  virtual void OnTestIterationStart(const UnitTest& /*unit_test*/,
+                                    int /*iteration*/) {
+    vector_->push_back(GetEventDescription("OnTestIterationStart"));
+  }
+
+  virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/,
+                                  int /*iteration*/) {
+    vector_->push_back(GetEventDescription("OnTestIterationEnd"));
+  }
+
+ private:
+  std::string GetEventDescription(const char* method) {
+    Message message;
+    message << id_ << "." << method;
+    return message.GetString();
+  }
+
+  std::vector<std::string>* vector_;
+  const char* const id_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(SequenceTestingListener);
+};
+
+TEST(EventListenerTest, AppendKeepsOrder) {
+  std::vector<std::string> vec;
+  TestEventListeners listeners;
+  listeners.Append(new SequenceTestingListener(&vec, "1st"));
+  listeners.Append(new SequenceTestingListener(&vec, "2nd"));
+  listeners.Append(new SequenceTestingListener(&vec, "3rd"));
+
+  TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+      *UnitTest::GetInstance());
+  ASSERT_EQ(3U, vec.size());
+  EXPECT_STREQ("1st.OnTestProgramStart", vec[0].c_str());
+  EXPECT_STREQ("2nd.OnTestProgramStart", vec[1].c_str());
+  EXPECT_STREQ("3rd.OnTestProgramStart", vec[2].c_str());
+
+  vec.clear();
+  TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramEnd(
+      *UnitTest::GetInstance());
+  ASSERT_EQ(3U, vec.size());
+  EXPECT_STREQ("3rd.OnTestProgramEnd", vec[0].c_str());
+  EXPECT_STREQ("2nd.OnTestProgramEnd", vec[1].c_str());
+  EXPECT_STREQ("1st.OnTestProgramEnd", vec[2].c_str());
+
+  vec.clear();
+  TestEventListenersAccessor::GetRepeater(&listeners)->OnTestIterationStart(
+      *UnitTest::GetInstance(), 0);
+  ASSERT_EQ(3U, vec.size());
+  EXPECT_STREQ("1st.OnTestIterationStart", vec[0].c_str());
+  EXPECT_STREQ("2nd.OnTestIterationStart", vec[1].c_str());
+  EXPECT_STREQ("3rd.OnTestIterationStart", vec[2].c_str());
+
+  vec.clear();
+  TestEventListenersAccessor::GetRepeater(&listeners)->OnTestIterationEnd(
+      *UnitTest::GetInstance(), 0);
+  ASSERT_EQ(3U, vec.size());
+  EXPECT_STREQ("3rd.OnTestIterationEnd", vec[0].c_str());
+  EXPECT_STREQ("2nd.OnTestIterationEnd", vec[1].c_str());
+  EXPECT_STREQ("1st.OnTestIterationEnd", vec[2].c_str());
+}
+
+// Tests that a listener removed from a TestEventListeners list stops receiving
+// events and is not deleted when the list is destroyed.
+TEST(TestEventListenersTest, Release) {
+  int on_start_counter = 0;
+  bool is_destroyed = false;
+  // Although Append passes the ownership of this object to the list,
+  // the following calls release it, and we need to delete it before the
+  // test ends.
+  TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+  {
+    TestEventListeners listeners;
+    listeners.Append(listener);
+    EXPECT_EQ(listener, listeners.Release(listener));
+    TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+        *UnitTest::GetInstance());
+    EXPECT_TRUE(listeners.Release(listener) == NULL);
+  }
+  EXPECT_EQ(0, on_start_counter);
+  EXPECT_FALSE(is_destroyed);
+  delete listener;
+}
+
+// Tests that no events are forwarded when event forwarding is disabled.
+TEST(EventListenerTest, SuppressEventForwarding) {
+  int on_start_counter = 0;
+  TestListener* listener = new TestListener(&on_start_counter, NULL);
+
+  TestEventListeners listeners;
+  listeners.Append(listener);
+  ASSERT_TRUE(TestEventListenersAccessor::EventForwardingEnabled(listeners));
+  TestEventListenersAccessor::SuppressEventForwarding(&listeners);
+  ASSERT_FALSE(TestEventListenersAccessor::EventForwardingEnabled(listeners));
+  TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+      *UnitTest::GetInstance());
+  EXPECT_EQ(0, on_start_counter);
+}
+
+// Tests that events generated by Google Test are not forwarded in
+// death test subprocesses.
+TEST(EventListenerDeathTest, EventsNotForwardedInDeathTestSubprecesses) {
+  EXPECT_DEATH_IF_SUPPORTED({
+      GTEST_CHECK_(TestEventListenersAccessor::EventForwardingEnabled(
+          *GetUnitTestImpl()->listeners())) << "expected failure";},
+      "expected failure");
+}
+
+// Tests that a listener installed via SetDefaultResultPrinter() starts
+// receiving events and is returned via default_result_printer() and that
+// the previous default_result_printer is removed from the list and deleted.
+TEST(EventListenerTest, default_result_printer) {
+  int on_start_counter = 0;
+  bool is_destroyed = false;
+  TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+
+  TestEventListeners listeners;
+  TestEventListenersAccessor::SetDefaultResultPrinter(&listeners, listener);
+
+  EXPECT_EQ(listener, listeners.default_result_printer());
+
+  TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+      *UnitTest::GetInstance());
+
+  EXPECT_EQ(1, on_start_counter);
+
+  // Replacing default_result_printer with something else should remove it
+  // from the list and destroy it.
+  TestEventListenersAccessor::SetDefaultResultPrinter(&listeners, NULL);
+
+  EXPECT_TRUE(listeners.default_result_printer() == NULL);
+  EXPECT_TRUE(is_destroyed);
+
+  // After broadcasting an event the counter is still the same, indicating
+  // the listener is not in the list anymore.
+  TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+      *UnitTest::GetInstance());
+  EXPECT_EQ(1, on_start_counter);
+}
+
+// Tests that the default_result_printer listener stops receiving events
+// when removed via Release and that is not owned by the list anymore.
+TEST(EventListenerTest, RemovingDefaultResultPrinterWorks) {
+  int on_start_counter = 0;
+  bool is_destroyed = false;
+  // Although Append passes the ownership of this object to the list,
+  // the following calls release it, and we need to delete it before the
+  // test ends.
+  TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+  {
+    TestEventListeners listeners;
+    TestEventListenersAccessor::SetDefaultResultPrinter(&listeners, listener);
+
+    EXPECT_EQ(listener, listeners.Release(listener));
+    EXPECT_TRUE(listeners.default_result_printer() == NULL);
+    EXPECT_FALSE(is_destroyed);
+
+    // Broadcasting events now should not affect default_result_printer.
+    TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+        *UnitTest::GetInstance());
+    EXPECT_EQ(0, on_start_counter);
+  }
+  // Destroying the list should not affect the listener now, too.
+  EXPECT_FALSE(is_destroyed);
+  delete listener;
+}
+
+// Tests that a listener installed via SetDefaultXmlGenerator() starts
+// receiving events and is returned via default_xml_generator() and that
+// the previous default_xml_generator is removed from the list and deleted.
+TEST(EventListenerTest, default_xml_generator) {
+  int on_start_counter = 0;
+  bool is_destroyed = false;
+  TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+
+  TestEventListeners listeners;
+  TestEventListenersAccessor::SetDefaultXmlGenerator(&listeners, listener);
+
+  EXPECT_EQ(listener, listeners.default_xml_generator());
+
+  TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+      *UnitTest::GetInstance());
+
+  EXPECT_EQ(1, on_start_counter);
+
+  // Replacing default_xml_generator with something else should remove it
+  // from the list and destroy it.
+  TestEventListenersAccessor::SetDefaultXmlGenerator(&listeners, NULL);
+
+  EXPECT_TRUE(listeners.default_xml_generator() == NULL);
+  EXPECT_TRUE(is_destroyed);
+
+  // After broadcasting an event the counter is still the same, indicating
+  // the listener is not in the list anymore.
+  TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+      *UnitTest::GetInstance());
+  EXPECT_EQ(1, on_start_counter);
+}
+
+// Tests that the default_xml_generator listener stops receiving events
+// when removed via Release and that is not owned by the list anymore.
+TEST(EventListenerTest, RemovingDefaultXmlGeneratorWorks) {
+  int on_start_counter = 0;
+  bool is_destroyed = false;
+  // Although Append passes the ownership of this object to the list,
+  // the following calls release it, and we need to delete it before the
+  // test ends.
+  TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+  {
+    TestEventListeners listeners;
+    TestEventListenersAccessor::SetDefaultXmlGenerator(&listeners, listener);
+
+    EXPECT_EQ(listener, listeners.Release(listener));
+    EXPECT_TRUE(listeners.default_xml_generator() == NULL);
+    EXPECT_FALSE(is_destroyed);
+
+    // Broadcasting events now should not affect default_xml_generator.
+    TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+        *UnitTest::GetInstance());
+    EXPECT_EQ(0, on_start_counter);
+  }
+  // Destroying the list should not affect the listener now, too.
+  EXPECT_FALSE(is_destroyed);
+  delete listener;
+}
+
+// Sanity tests to ensure that the alternative, verbose spellings of
+// some of the macros work.  We don't test them thoroughly as that
+// would be quite involved.  Since their implementations are
+// straightforward, and they are rarely used, we'll just rely on the
+// users to tell us when they are broken.
+GTEST_TEST(AlternativeNameTest, Works) {  // GTEST_TEST is the same as TEST.
+  GTEST_SUCCEED() << "OK";  // GTEST_SUCCEED is the same as SUCCEED.
+
+  // GTEST_FAIL is the same as FAIL.
+  EXPECT_FATAL_FAILURE(GTEST_FAIL() << "An expected failure",
+                       "An expected failure");
+
+  // GTEST_ASSERT_XY is the same as ASSERT_XY.
+
+  GTEST_ASSERT_EQ(0, 0);
+  EXPECT_FATAL_FAILURE(GTEST_ASSERT_EQ(0, 1) << "An expected failure",
+                       "An expected failure");
+  EXPECT_FATAL_FAILURE(GTEST_ASSERT_EQ(1, 0) << "An expected failure",
+                       "An expected failure");
+
+  GTEST_ASSERT_NE(0, 1);
+  GTEST_ASSERT_NE(1, 0);
+  EXPECT_FATAL_FAILURE(GTEST_ASSERT_NE(0, 0) << "An expected failure",
+                       "An expected failure");
+
+  GTEST_ASSERT_LE(0, 0);
+  GTEST_ASSERT_LE(0, 1);
+  EXPECT_FATAL_FAILURE(GTEST_ASSERT_LE(1, 0) << "An expected failure",
+                       "An expected failure");
+
+  GTEST_ASSERT_LT(0, 1);
+  EXPECT_FATAL_FAILURE(GTEST_ASSERT_LT(0, 0) << "An expected failure",
+                       "An expected failure");
+  EXPECT_FATAL_FAILURE(GTEST_ASSERT_LT(1, 0) << "An expected failure",
+                       "An expected failure");
+
+  GTEST_ASSERT_GE(0, 0);
+  GTEST_ASSERT_GE(1, 0);
+  EXPECT_FATAL_FAILURE(GTEST_ASSERT_GE(0, 1) << "An expected failure",
+                       "An expected failure");
+
+  GTEST_ASSERT_GT(1, 0);
+  EXPECT_FATAL_FAILURE(GTEST_ASSERT_GT(0, 1) << "An expected failure",
+                       "An expected failure");
+  EXPECT_FATAL_FAILURE(GTEST_ASSERT_GT(1, 1) << "An expected failure",
+                       "An expected failure");
+}
+
+// Tests for internal utilities necessary for implementation of the universal
+// printing.
+// TODO(vladl@google.com): Find a better home for them.
+
+class ConversionHelperBase {};
+class ConversionHelperDerived : public ConversionHelperBase {};
+
+// Tests that IsAProtocolMessage<T>::value is a compile-time constant.
+TEST(IsAProtocolMessageTest, ValueIsCompileTimeConstant) {
+  GTEST_COMPILE_ASSERT_(IsAProtocolMessage<ProtocolMessage>::value,
+                        const_true);
+  GTEST_COMPILE_ASSERT_(!IsAProtocolMessage<int>::value, const_false);
+}
+
+// Tests that IsAProtocolMessage<T>::value is true when T is
+// proto2::Message or a sub-class of it.
+TEST(IsAProtocolMessageTest, ValueIsTrueWhenTypeIsAProtocolMessage) {
+  EXPECT_TRUE(IsAProtocolMessage< ::proto2::Message>::value);
+  EXPECT_TRUE(IsAProtocolMessage<ProtocolMessage>::value);
+}
+
+// Tests that IsAProtocolMessage<T>::value is false when T is neither
+// ProtocolMessage nor a sub-class of it.
+TEST(IsAProtocolMessageTest, ValueIsFalseWhenTypeIsNotAProtocolMessage) {
+  EXPECT_FALSE(IsAProtocolMessage<int>::value);
+  EXPECT_FALSE(IsAProtocolMessage<const ConversionHelperBase>::value);
+}
+
+// Tests that CompileAssertTypesEqual compiles when the type arguments are
+// equal.
+TEST(CompileAssertTypesEqual, CompilesWhenTypesAreEqual) {
+  CompileAssertTypesEqual<void, void>();
+  CompileAssertTypesEqual<int*, int*>();
+}
+
+// Tests that RemoveReference does not affect non-reference types.
+TEST(RemoveReferenceTest, DoesNotAffectNonReferenceType) {
+  CompileAssertTypesEqual<int, RemoveReference<int>::type>();
+  CompileAssertTypesEqual<const char, RemoveReference<const char>::type>();
+}
+
+// Tests that RemoveReference removes reference from reference types.
+TEST(RemoveReferenceTest, RemovesReference) {
+  CompileAssertTypesEqual<int, RemoveReference<int&>::type>();
+  CompileAssertTypesEqual<const char, RemoveReference<const char&>::type>();
+}
+
+// Tests GTEST_REMOVE_REFERENCE_.
+
+template <typename T1, typename T2>
+void TestGTestRemoveReference() {
+  CompileAssertTypesEqual<T1, GTEST_REMOVE_REFERENCE_(T2)>();
+}
+
+TEST(RemoveReferenceTest, MacroVersion) {
+  TestGTestRemoveReference<int, int>();
+  TestGTestRemoveReference<const char, const char&>();
+}
+
+
+// Tests that RemoveConst does not affect non-const types.
+TEST(RemoveConstTest, DoesNotAffectNonConstType) {
+  CompileAssertTypesEqual<int, RemoveConst<int>::type>();
+  CompileAssertTypesEqual<char&, RemoveConst<char&>::type>();
+}
+
+// Tests that RemoveConst removes const from const types.
+TEST(RemoveConstTest, RemovesConst) {
+  CompileAssertTypesEqual<int, RemoveConst<const int>::type>();
+  CompileAssertTypesEqual<char[2], RemoveConst<const char[2]>::type>();
+  CompileAssertTypesEqual<char[2][3], RemoveConst<const char[2][3]>::type>();
+}
+
+// Tests GTEST_REMOVE_CONST_.
+
+template <typename T1, typename T2>
+void TestGTestRemoveConst() {
+  CompileAssertTypesEqual<T1, GTEST_REMOVE_CONST_(T2)>();
+}
+
+TEST(RemoveConstTest, MacroVersion) {
+  TestGTestRemoveConst<int, int>();
+  TestGTestRemoveConst<double&, double&>();
+  TestGTestRemoveConst<char, const char>();
+}
+
+// Tests GTEST_REMOVE_REFERENCE_AND_CONST_.
+
+template <typename T1, typename T2>
+void TestGTestRemoveReferenceAndConst() {
+  CompileAssertTypesEqual<T1, GTEST_REMOVE_REFERENCE_AND_CONST_(T2)>();
+}
+
+TEST(RemoveReferenceToConstTest, Works) {
+  TestGTestRemoveReferenceAndConst<int, int>();
+  TestGTestRemoveReferenceAndConst<double, double&>();
+  TestGTestRemoveReferenceAndConst<char, const char>();
+  TestGTestRemoveReferenceAndConst<char, const char&>();
+  TestGTestRemoveReferenceAndConst<const char*, const char*>();
+}
+
+// Tests that AddReference does not affect reference types.
+TEST(AddReferenceTest, DoesNotAffectReferenceType) {
+  CompileAssertTypesEqual<int&, AddReference<int&>::type>();
+  CompileAssertTypesEqual<const char&, AddReference<const char&>::type>();
+}
+
+// Tests that AddReference adds reference to non-reference types.
+TEST(AddReferenceTest, AddsReference) {
+  CompileAssertTypesEqual<int&, AddReference<int>::type>();
+  CompileAssertTypesEqual<const char&, AddReference<const char>::type>();
+}
+
+// Tests GTEST_ADD_REFERENCE_.
+
+template <typename T1, typename T2>
+void TestGTestAddReference() {
+  CompileAssertTypesEqual<T1, GTEST_ADD_REFERENCE_(T2)>();
+}
+
+TEST(AddReferenceTest, MacroVersion) {
+  TestGTestAddReference<int&, int>();
+  TestGTestAddReference<const char&, const char&>();
+}
+
+// Tests GTEST_REFERENCE_TO_CONST_.
+
+template <typename T1, typename T2>
+void TestGTestReferenceToConst() {
+  CompileAssertTypesEqual<T1, GTEST_REFERENCE_TO_CONST_(T2)>();
+}
+
+TEST(GTestReferenceToConstTest, Works) {
+  TestGTestReferenceToConst<const char&, char>();
+  TestGTestReferenceToConst<const int&, const int>();
+  TestGTestReferenceToConst<const double&, double>();
+  TestGTestReferenceToConst<const std::string&, const std::string&>();
+}
+
+// Tests that ImplicitlyConvertible<T1, T2>::value is a compile-time constant.
+TEST(ImplicitlyConvertibleTest, ValueIsCompileTimeConstant) {
+  GTEST_COMPILE_ASSERT_((ImplicitlyConvertible<int, int>::value), const_true);
+  GTEST_COMPILE_ASSERT_((!ImplicitlyConvertible<void*, int*>::value),
+                        const_false);
+}
+
+// Tests that ImplicitlyConvertible<T1, T2>::value is true when T1 can
+// be implicitly converted to T2.
+TEST(ImplicitlyConvertibleTest, ValueIsTrueWhenConvertible) {
+  EXPECT_TRUE((ImplicitlyConvertible<int, double>::value));
+  EXPECT_TRUE((ImplicitlyConvertible<double, int>::value));
+  EXPECT_TRUE((ImplicitlyConvertible<int*, void*>::value));
+  EXPECT_TRUE((ImplicitlyConvertible<int*, const int*>::value));
+  EXPECT_TRUE((ImplicitlyConvertible<ConversionHelperDerived&,
+                                     const ConversionHelperBase&>::value));
+  EXPECT_TRUE((ImplicitlyConvertible<const ConversionHelperBase,
+                                     ConversionHelperBase>::value));
+}
+
+// Tests that ImplicitlyConvertible<T1, T2>::value is false when T1
+// cannot be implicitly converted to T2.
+TEST(ImplicitlyConvertibleTest, ValueIsFalseWhenNotConvertible) {
+  EXPECT_FALSE((ImplicitlyConvertible<double, int*>::value));
+  EXPECT_FALSE((ImplicitlyConvertible<void*, int*>::value));
+  EXPECT_FALSE((ImplicitlyConvertible<const int*, int*>::value));
+  EXPECT_FALSE((ImplicitlyConvertible<ConversionHelperBase&,
+                                      ConversionHelperDerived&>::value));
+}
+
+// Tests IsContainerTest.
+
+class NonContainer {};
+
+TEST(IsContainerTestTest, WorksForNonContainer) {
+  EXPECT_EQ(sizeof(IsNotContainer), sizeof(IsContainerTest<int>(0)));
+  EXPECT_EQ(sizeof(IsNotContainer), sizeof(IsContainerTest<char[5]>(0)));
+  EXPECT_EQ(sizeof(IsNotContainer), sizeof(IsContainerTest<NonContainer>(0)));
+}
+
+TEST(IsContainerTestTest, WorksForContainer) {
+  EXPECT_EQ(sizeof(IsContainer),
+            sizeof(IsContainerTest<std::vector<bool> >(0)));
+  EXPECT_EQ(sizeof(IsContainer),
+            sizeof(IsContainerTest<std::map<int, double> >(0)));
+}
+
+// Tests ArrayEq().
+
+TEST(ArrayEqTest, WorksForDegeneratedArrays) {
+  EXPECT_TRUE(ArrayEq(5, 5L));
+  EXPECT_FALSE(ArrayEq('a', 0));
+}
+
+TEST(ArrayEqTest, WorksForOneDimensionalArrays) {
+  // Note that a and b are distinct but compatible types.
+  const int a[] = { 0, 1 };
+  long b[] = { 0, 1 };
+  EXPECT_TRUE(ArrayEq(a, b));
+  EXPECT_TRUE(ArrayEq(a, 2, b));
+
+  b[0] = 2;
+  EXPECT_FALSE(ArrayEq(a, b));
+  EXPECT_FALSE(ArrayEq(a, 1, b));
+}
+
+TEST(ArrayEqTest, WorksForTwoDimensionalArrays) {
+  const char a[][3] = { "hi", "lo" };
+  const char b[][3] = { "hi", "lo" };
+  const char c[][3] = { "hi", "li" };
+
+  EXPECT_TRUE(ArrayEq(a, b));
+  EXPECT_TRUE(ArrayEq(a, 2, b));
+
+  EXPECT_FALSE(ArrayEq(a, c));
+  EXPECT_FALSE(ArrayEq(a, 2, c));
+}
+
+// Tests ArrayAwareFind().
+
+TEST(ArrayAwareFindTest, WorksForOneDimensionalArray) {
+  const char a[] = "hello";
+  EXPECT_EQ(a + 4, ArrayAwareFind(a, a + 5, 'o'));
+  EXPECT_EQ(a + 5, ArrayAwareFind(a, a + 5, 'x'));
+}
+
+TEST(ArrayAwareFindTest, WorksForTwoDimensionalArray) {
+  int a[][2] = { { 0, 1 }, { 2, 3 }, { 4, 5 } };
+  const int b[2] = { 2, 3 };
+  EXPECT_EQ(a + 1, ArrayAwareFind(a, a + 3, b));
+
+  const int c[2] = { 6, 7 };
+  EXPECT_EQ(a + 3, ArrayAwareFind(a, a + 3, c));
+}
+
+// Tests CopyArray().
+
+TEST(CopyArrayTest, WorksForDegeneratedArrays) {
+  int n = 0;
+  CopyArray('a', &n);
+  EXPECT_EQ('a', n);
+}
+
+TEST(CopyArrayTest, WorksForOneDimensionalArrays) {
+  const char a[3] = "hi";
+  int b[3];
+#ifndef __BORLANDC__  // C++Builder cannot compile some array size deductions.
+  CopyArray(a, &b);
+  EXPECT_TRUE(ArrayEq(a, b));
+#endif
+
+  int c[3];
+  CopyArray(a, 3, c);
+  EXPECT_TRUE(ArrayEq(a, c));
+}
+
+TEST(CopyArrayTest, WorksForTwoDimensionalArrays) {
+  const int a[2][3] = { { 0, 1, 2 }, { 3, 4, 5 } };
+  int b[2][3];
+#ifndef __BORLANDC__  // C++Builder cannot compile some array size deductions.
+  CopyArray(a, &b);
+  EXPECT_TRUE(ArrayEq(a, b));
+#endif
+
+  int c[2][3];
+  CopyArray(a, 2, c);
+  EXPECT_TRUE(ArrayEq(a, c));
+}
+
+// Tests NativeArray.
+
+TEST(NativeArrayTest, ConstructorFromArrayWorks) {
+  const int a[3] = { 0, 1, 2 };
+  NativeArray<int> na(a, 3, RelationToSourceReference());
+  EXPECT_EQ(3U, na.size());
+  EXPECT_EQ(a, na.begin());
+}
+
+TEST(NativeArrayTest, CreatesAndDeletesCopyOfArrayWhenAskedTo) {
+  typedef int Array[2];
+  Array* a = new Array[1];
+  (*a)[0] = 0;
+  (*a)[1] = 1;
+  NativeArray<int> na(*a, 2, RelationToSourceCopy());
+  EXPECT_NE(*a, na.begin());
+  delete[] a;
+  EXPECT_EQ(0, na.begin()[0]);
+  EXPECT_EQ(1, na.begin()[1]);
+
+  // We rely on the heap checker to verify that na deletes the copy of
+  // array.
+}
+
+TEST(NativeArrayTest, TypeMembersAreCorrect) {
+  StaticAssertTypeEq<char, NativeArray<char>::value_type>();
+  StaticAssertTypeEq<int[2], NativeArray<int[2]>::value_type>();
+
+  StaticAssertTypeEq<const char*, NativeArray<char>::const_iterator>();
+  StaticAssertTypeEq<const bool(*)[2], NativeArray<bool[2]>::const_iterator>();
+}
+
+TEST(NativeArrayTest, MethodsWork) {
+  const int a[3] = { 0, 1, 2 };
+  NativeArray<int> na(a, 3, RelationToSourceCopy());
+  ASSERT_EQ(3U, na.size());
+  EXPECT_EQ(3, na.end() - na.begin());
+
+  NativeArray<int>::const_iterator it = na.begin();
+  EXPECT_EQ(0, *it);
+  ++it;
+  EXPECT_EQ(1, *it);
+  it++;
+  EXPECT_EQ(2, *it);
+  ++it;
+  EXPECT_EQ(na.end(), it);
+
+  EXPECT_TRUE(na == na);
+
+  NativeArray<int> na2(a, 3, RelationToSourceReference());
+  EXPECT_TRUE(na == na2);
+
+  const int b1[3] = { 0, 1, 1 };
+  const int b2[4] = { 0, 1, 2, 3 };
+  EXPECT_FALSE(na == NativeArray<int>(b1, 3, RelationToSourceReference()));
+  EXPECT_FALSE(na == NativeArray<int>(b2, 4, RelationToSourceCopy()));
+}
+
+TEST(NativeArrayTest, WorksForTwoDimensionalArray) {
+  const char a[2][3] = { "hi", "lo" };
+  NativeArray<char[3]> na(a, 2, RelationToSourceReference());
+  ASSERT_EQ(2U, na.size());
+  EXPECT_EQ(a, na.begin());
+}
+
+// Tests SkipPrefix().
+
+TEST(SkipPrefixTest, SkipsWhenPrefixMatches) {
+  const char* const str = "hello";
+
+  const char* p = str;
+  EXPECT_TRUE(SkipPrefix("", &p));
+  EXPECT_EQ(str, p);
+
+  p = str;
+  EXPECT_TRUE(SkipPrefix("hell", &p));
+  EXPECT_EQ(str + 4, p);
+}
+
+TEST(SkipPrefixTest, DoesNotSkipWhenPrefixDoesNotMatch) {
+  const char* const str = "world";
+
+  const char* p = str;
+  EXPECT_FALSE(SkipPrefix("W", &p));
+  EXPECT_EQ(str, p);
+
+  p = str;
+  EXPECT_FALSE(SkipPrefix("world!", &p));
+  EXPECT_EQ(str, p);
+}
+
diff --git a/third_party/googletest/googletest/test/gtest_xml_outfile1_test_.cc b/third_party/googletest/googletest/test/gtest_xml_outfile1_test_.cc
new file mode 100644
index 0000000..531ced4
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_xml_outfile1_test_.cc
@@ -0,0 +1,49 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: keith.ray@gmail.com (Keith Ray)
+//
+// gtest_xml_outfile1_test_ writes some xml via TestProperty used by
+// gtest_xml_outfiles_test.py
+
+#include "gtest/gtest.h"
+
+class PropertyOne : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    RecordProperty("SetUpProp", 1);
+  }
+  virtual void TearDown() {
+    RecordProperty("TearDownProp", 1);
+  }
+};
+
+TEST_F(PropertyOne, TestSomeProperties) {
+  RecordProperty("TestSomeProperty", 1);
+}
diff --git a/third_party/googletest/googletest/test/gtest_xml_outfile2_test_.cc b/third_party/googletest/googletest/test/gtest_xml_outfile2_test_.cc
new file mode 100644
index 0000000..7b400b2
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_xml_outfile2_test_.cc
@@ -0,0 +1,49 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: keith.ray@gmail.com (Keith Ray)
+//
+// gtest_xml_outfile2_test_ writes some xml via TestProperty used by
+// gtest_xml_outfiles_test.py
+
+#include "gtest/gtest.h"
+
+class PropertyTwo : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    RecordProperty("SetUpProp", 2);
+  }
+  virtual void TearDown() {
+    RecordProperty("TearDownProp", 2);
+  }
+};
+
+TEST_F(PropertyTwo, TestSomeProperties) {
+  RecordProperty("TestSomeProperty", 2);
+}
diff --git a/third_party/googletest/googletest/test/gtest_xml_outfiles_test.py b/third_party/googletest/googletest/test/gtest_xml_outfiles_test.py
new file mode 100755
index 0000000..524e437
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_xml_outfiles_test.py
@@ -0,0 +1,132 @@
+#!/usr/bin/env python
+#
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Unit test for the gtest_xml_output module."""
+
+__author__ = "keith.ray@gmail.com (Keith Ray)"
+
+import os
+from xml.dom import minidom, Node
+
+import gtest_test_utils
+import gtest_xml_test_utils
+
+
+GTEST_OUTPUT_SUBDIR = "xml_outfiles"
+GTEST_OUTPUT_1_TEST = "gtest_xml_outfile1_test_"
+GTEST_OUTPUT_2_TEST = "gtest_xml_outfile2_test_"
+
+EXPECTED_XML_1 = """<?xml version="1.0" encoding="UTF-8"?>
+<testsuites tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*" name="AllTests">
+  <testsuite name="PropertyOne" tests="1" failures="0" disabled="0" errors="0" time="*">
+    <testcase name="TestSomeProperties" status="run" time="*" classname="PropertyOne" SetUpProp="1" TestSomeProperty="1" TearDownProp="1" />
+  </testsuite>
+</testsuites>
+"""
+
+EXPECTED_XML_2 = """<?xml version="1.0" encoding="UTF-8"?>
+<testsuites tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*" name="AllTests">
+  <testsuite name="PropertyTwo" tests="1" failures="0" disabled="0" errors="0" time="*">
+    <testcase name="TestSomeProperties" status="run" time="*" classname="PropertyTwo" SetUpProp="2" TestSomeProperty="2" TearDownProp="2" />
+  </testsuite>
+</testsuites>
+"""
+
+
+class GTestXMLOutFilesTest(gtest_xml_test_utils.GTestXMLTestCase):
+  """Unit test for Google Test's XML output functionality."""
+
+  def setUp(self):
+    # We want the trailing '/' that the last "" provides in os.path.join, for
+    # telling Google Test to create an output directory instead of a single file
+    # for xml output.
+    self.output_dir_ = os.path.join(gtest_test_utils.GetTempDir(),
+                                    GTEST_OUTPUT_SUBDIR, "")
+    self.DeleteFilesAndDir()
+
+  def tearDown(self):
+    self.DeleteFilesAndDir()
+
+  def DeleteFilesAndDir(self):
+    try:
+      os.remove(os.path.join(self.output_dir_, GTEST_OUTPUT_1_TEST + ".xml"))
+    except os.error:
+      pass
+    try:
+      os.remove(os.path.join(self.output_dir_, GTEST_OUTPUT_2_TEST + ".xml"))
+    except os.error:
+      pass
+    try:
+      os.rmdir(self.output_dir_)
+    except os.error:
+      pass
+
+  def testOutfile1(self):
+    self._TestOutFile(GTEST_OUTPUT_1_TEST, EXPECTED_XML_1)
+
+  def testOutfile2(self):
+    self._TestOutFile(GTEST_OUTPUT_2_TEST, EXPECTED_XML_2)
+
+  def _TestOutFile(self, test_name, expected_xml):
+    gtest_prog_path = gtest_test_utils.GetTestExecutablePath(test_name)
+    command = [gtest_prog_path, "--gtest_output=xml:%s" % self.output_dir_]
+    p = gtest_test_utils.Subprocess(command,
+                                    working_dir=gtest_test_utils.GetTempDir())
+    self.assert_(p.exited)
+    self.assertEquals(0, p.exit_code)
+
+    # TODO(wan@google.com): libtool causes the built test binary to be
+    #   named lt-gtest_xml_outfiles_test_ instead of
+    #   gtest_xml_outfiles_test_.  To account for this possibillity, we
+    #   allow both names in the following code.  We should remove this
+    #   hack when Chandler Carruth's libtool replacement tool is ready.
+    output_file_name1 = test_name + ".xml"
+    output_file1 = os.path.join(self.output_dir_, output_file_name1)
+    output_file_name2 = 'lt-' + output_file_name1
+    output_file2 = os.path.join(self.output_dir_, output_file_name2)
+    self.assert_(os.path.isfile(output_file1) or os.path.isfile(output_file2),
+                 output_file1)
+
+    expected = minidom.parseString(expected_xml)
+    if os.path.isfile(output_file1):
+      actual = minidom.parse(output_file1)
+    else:
+      actual = minidom.parse(output_file2)
+    self.NormalizeXml(actual.documentElement)
+    self.AssertEquivalentNodes(expected.documentElement,
+                               actual.documentElement)
+    expected.unlink()
+    actual.unlink()
+
+
+if __name__ == "__main__":
+  os.environ["GTEST_STACK_TRACE_DEPTH"] = "0"
+  gtest_test_utils.Main()
diff --git a/third_party/googletest/googletest/test/gtest_xml_output_unittest.py b/third_party/googletest/googletest/test/gtest_xml_output_unittest.py
new file mode 100755
index 0000000..f605d4e
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_xml_output_unittest.py
@@ -0,0 +1,307 @@
+#!/usr/bin/env python
+#
+# Copyright 2006, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Unit test for the gtest_xml_output module"""
+
+__author__ = 'eefacm@gmail.com (Sean Mcafee)'
+
+import datetime
+import errno
+import os
+import re
+import sys
+from xml.dom import minidom, Node
+
+import gtest_test_utils
+import gtest_xml_test_utils
+
+
+GTEST_FILTER_FLAG = '--gtest_filter'
+GTEST_LIST_TESTS_FLAG = '--gtest_list_tests'
+GTEST_OUTPUT_FLAG         = "--gtest_output"
+GTEST_DEFAULT_OUTPUT_FILE = "test_detail.xml"
+GTEST_PROGRAM_NAME = "gtest_xml_output_unittest_"
+
+SUPPORTS_STACK_TRACES = False
+
+if SUPPORTS_STACK_TRACES:
+  STACK_TRACE_TEMPLATE = '\nStack trace:\n*'
+else:
+  STACK_TRACE_TEMPLATE = ''
+
+EXPECTED_NON_EMPTY_XML = """<?xml version="1.0" encoding="UTF-8"?>
+<testsuites tests="23" failures="4" disabled="2" errors="0" time="*" timestamp="*" name="AllTests" ad_hoc_property="42">
+  <testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" errors="0" time="*">
+    <testcase name="Succeeds" status="run" time="*" classname="SuccessfulTest"/>
+  </testsuite>
+  <testsuite name="FailedTest" tests="1" failures="1" disabled="0" errors="0" time="*">
+    <testcase name="Fails" status="run" time="*" classname="FailedTest">
+      <failure message="gtest_xml_output_unittest_.cc:*&#x0A;Value of: 2&#x0A;Expected: 1" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
+Value of: 2
+Expected: 1%(stack)s]]></failure>
+    </testcase>
+  </testsuite>
+  <testsuite name="MixedResultTest" tests="3" failures="1" disabled="1" errors="0" time="*">
+    <testcase name="Succeeds" status="run" time="*" classname="MixedResultTest"/>
+    <testcase name="Fails" status="run" time="*" classname="MixedResultTest">
+      <failure message="gtest_xml_output_unittest_.cc:*&#x0A;Value of: 2&#x0A;Expected: 1" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
+Value of: 2
+Expected: 1%(stack)s]]></failure>
+      <failure message="gtest_xml_output_unittest_.cc:*&#x0A;Value of: 3&#x0A;Expected: 2" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
+Value of: 3
+Expected: 2%(stack)s]]></failure>
+    </testcase>
+    <testcase name="DISABLED_test" status="notrun" time="*" classname="MixedResultTest"/>
+  </testsuite>
+  <testsuite name="XmlQuotingTest" tests="1" failures="1" disabled="0" errors="0" time="*">
+    <testcase name="OutputsCData" status="run" time="*" classname="XmlQuotingTest">
+      <failure message="gtest_xml_output_unittest_.cc:*&#x0A;Failed&#x0A;XML output: &lt;?xml encoding=&quot;utf-8&quot;&gt;&lt;top&gt;&lt;![CDATA[cdata text]]&gt;&lt;/top&gt;" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
+Failed
+XML output: <?xml encoding="utf-8"><top><![CDATA[cdata text]]>]]&gt;<![CDATA[</top>%(stack)s]]></failure>
+    </testcase>
+  </testsuite>
+  <testsuite name="InvalidCharactersTest" tests="1" failures="1" disabled="0" errors="0" time="*">
+    <testcase name="InvalidCharactersInMessage" status="run" time="*" classname="InvalidCharactersTest">
+      <failure message="gtest_xml_output_unittest_.cc:*&#x0A;Failed&#x0A;Invalid characters in brackets []" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
+Failed
+Invalid characters in brackets []%(stack)s]]></failure>
+    </testcase>
+  </testsuite>
+  <testsuite name="DisabledTest" tests="1" failures="0" disabled="1" errors="0" time="*">
+    <testcase name="DISABLED_test_not_run" status="notrun" time="*" classname="DisabledTest"/>
+  </testsuite>
+  <testsuite name="PropertyRecordingTest" tests="4" failures="0" disabled="0" errors="0" time="*" SetUpTestCase="yes" TearDownTestCase="aye">
+    <testcase name="OneProperty" status="run" time="*" classname="PropertyRecordingTest" key_1="1"/>
+    <testcase name="IntValuedProperty" status="run" time="*" classname="PropertyRecordingTest" key_int="1"/>
+    <testcase name="ThreeProperties" status="run" time="*" classname="PropertyRecordingTest" key_1="1" key_2="2" key_3="3"/>
+    <testcase name="TwoValuesForOneKeyUsesLastValue" status="run" time="*" classname="PropertyRecordingTest" key_1="2"/>
+  </testsuite>
+  <testsuite name="NoFixtureTest" tests="3" failures="0" disabled="0" errors="0" time="*">
+     <testcase name="RecordProperty" status="run" time="*" classname="NoFixtureTest" key="1"/>
+     <testcase name="ExternalUtilityThatCallsRecordIntValuedProperty" status="run" time="*" classname="NoFixtureTest" key_for_utility_int="1"/>
+     <testcase name="ExternalUtilityThatCallsRecordStringValuedProperty" status="run" time="*" classname="NoFixtureTest" key_for_utility_string="1"/>
+  </testsuite>
+  <testsuite name="Single/ValueParamTest" tests="4" failures="0" disabled="0" errors="0" time="*">
+    <testcase name="HasValueParamAttribute/0" value_param="33" status="run" time="*" classname="Single/ValueParamTest" />
+    <testcase name="HasValueParamAttribute/1" value_param="42" status="run" time="*" classname="Single/ValueParamTest" />
+    <testcase name="AnotherTestThatHasValueParamAttribute/0" value_param="33" status="run" time="*" classname="Single/ValueParamTest" />
+    <testcase name="AnotherTestThatHasValueParamAttribute/1" value_param="42" status="run" time="*" classname="Single/ValueParamTest" />
+  </testsuite>
+  <testsuite name="TypedTest/0" tests="1" failures="0" disabled="0" errors="0" time="*">
+    <testcase name="HasTypeParamAttribute" type_param="*" status="run" time="*" classname="TypedTest/0" />
+  </testsuite>
+  <testsuite name="TypedTest/1" tests="1" failures="0" disabled="0" errors="0" time="*">
+    <testcase name="HasTypeParamAttribute" type_param="*" status="run" time="*" classname="TypedTest/1" />
+  </testsuite>
+  <testsuite name="Single/TypeParameterizedTestCase/0" tests="1" failures="0" disabled="0" errors="0" time="*">
+    <testcase name="HasTypeParamAttribute" type_param="*" status="run" time="*" classname="Single/TypeParameterizedTestCase/0" />
+  </testsuite>
+  <testsuite name="Single/TypeParameterizedTestCase/1" tests="1" failures="0" disabled="0" errors="0" time="*">
+    <testcase name="HasTypeParamAttribute" type_param="*" status="run" time="*" classname="Single/TypeParameterizedTestCase/1" />
+  </testsuite>
+</testsuites>""" % {'stack': STACK_TRACE_TEMPLATE}
+
+EXPECTED_FILTERED_TEST_XML = """<?xml version="1.0" encoding="UTF-8"?>
+<testsuites tests="1" failures="0" disabled="0" errors="0" time="*"
+            timestamp="*" name="AllTests" ad_hoc_property="42">
+  <testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0"
+             errors="0" time="*">
+    <testcase name="Succeeds" status="run" time="*" classname="SuccessfulTest"/>
+  </testsuite>
+</testsuites>"""
+
+EXPECTED_EMPTY_XML = """<?xml version="1.0" encoding="UTF-8"?>
+<testsuites tests="0" failures="0" disabled="0" errors="0" time="*"
+            timestamp="*" name="AllTests">
+</testsuites>"""
+
+GTEST_PROGRAM_PATH = gtest_test_utils.GetTestExecutablePath(GTEST_PROGRAM_NAME)
+
+SUPPORTS_TYPED_TESTS = 'TypedTest' in gtest_test_utils.Subprocess(
+    [GTEST_PROGRAM_PATH, GTEST_LIST_TESTS_FLAG], capture_stderr=False).output
+
+
+class GTestXMLOutputUnitTest(gtest_xml_test_utils.GTestXMLTestCase):
+  """
+  Unit test for Google Test's XML output functionality.
+  """
+
+  # This test currently breaks on platforms that do not support typed and
+  # type-parameterized tests, so we don't run it under them.
+  if SUPPORTS_TYPED_TESTS:
+    def testNonEmptyXmlOutput(self):
+      """
+      Runs a test program that generates a non-empty XML output, and
+      tests that the XML output is expected.
+      """
+      self._TestXmlOutput(GTEST_PROGRAM_NAME, EXPECTED_NON_EMPTY_XML, 1)
+
+  def testEmptyXmlOutput(self):
+    """Verifies XML output for a Google Test binary without actual tests.
+
+    Runs a test program that generates an empty XML output, and
+    tests that the XML output is expected.
+    """
+
+    self._TestXmlOutput('gtest_no_test_unittest', EXPECTED_EMPTY_XML, 0)
+
+  def testTimestampValue(self):
+    """Checks whether the timestamp attribute in the XML output is valid.
+
+    Runs a test program that generates an empty XML output, and checks if
+    the timestamp attribute in the testsuites tag is valid.
+    """
+    actual = self._GetXmlOutput('gtest_no_test_unittest', [], 0)
+    date_time_str = actual.documentElement.getAttributeNode('timestamp').value
+    # datetime.strptime() is only available in Python 2.5+ so we have to
+    # parse the expected datetime manually.
+    match = re.match(r'(\d+)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)', date_time_str)
+    self.assertTrue(
+        re.match,
+        'XML datettime string %s has incorrect format' % date_time_str)
+    date_time_from_xml = datetime.datetime(
+        year=int(match.group(1)), month=int(match.group(2)),
+        day=int(match.group(3)), hour=int(match.group(4)),
+        minute=int(match.group(5)), second=int(match.group(6)))
+
+    time_delta = abs(datetime.datetime.now() - date_time_from_xml)
+    # timestamp value should be near the current local time
+    self.assertTrue(time_delta < datetime.timedelta(seconds=600),
+                    'time_delta is %s' % time_delta)
+    actual.unlink()
+
+  def testDefaultOutputFile(self):
+    """
+    Confirms that Google Test produces an XML output file with the expected
+    default name if no name is explicitly specified.
+    """
+    output_file = os.path.join(gtest_test_utils.GetTempDir(),
+                               GTEST_DEFAULT_OUTPUT_FILE)
+    gtest_prog_path = gtest_test_utils.GetTestExecutablePath(
+        'gtest_no_test_unittest')
+    try:
+      os.remove(output_file)
+    except OSError, e:
+      if e.errno != errno.ENOENT:
+        raise
+
+    p = gtest_test_utils.Subprocess(
+        [gtest_prog_path, '%s=xml' % GTEST_OUTPUT_FLAG],
+        working_dir=gtest_test_utils.GetTempDir())
+    self.assert_(p.exited)
+    self.assertEquals(0, p.exit_code)
+    self.assert_(os.path.isfile(output_file))
+
+  def testSuppressedXmlOutput(self):
+    """
+    Tests that no XML file is generated if the default XML listener is
+    shut down before RUN_ALL_TESTS is invoked.
+    """
+
+    xml_path = os.path.join(gtest_test_utils.GetTempDir(),
+                            GTEST_PROGRAM_NAME + 'out.xml')
+    if os.path.isfile(xml_path):
+      os.remove(xml_path)
+
+    command = [GTEST_PROGRAM_PATH,
+               '%s=xml:%s' % (GTEST_OUTPUT_FLAG, xml_path),
+               '--shut_down_xml']
+    p = gtest_test_utils.Subprocess(command)
+    if p.terminated_by_signal:
+      # p.signal is avalable only if p.terminated_by_signal is True.
+      self.assertFalse(
+          p.terminated_by_signal,
+          '%s was killed by signal %d' % (GTEST_PROGRAM_NAME, p.signal))
+    else:
+      self.assert_(p.exited)
+      self.assertEquals(1, p.exit_code,
+                        "'%s' exited with code %s, which doesn't match "
+                        'the expected exit code %s.'
+                        % (command, p.exit_code, 1))
+
+    self.assert_(not os.path.isfile(xml_path))
+
+  def testFilteredTestXmlOutput(self):
+    """Verifies XML output when a filter is applied.
+
+    Runs a test program that executes only some tests and verifies that
+    non-selected tests do not show up in the XML output.
+    """
+
+    self._TestXmlOutput(GTEST_PROGRAM_NAME, EXPECTED_FILTERED_TEST_XML, 0,
+                        extra_args=['%s=SuccessfulTest.*' % GTEST_FILTER_FLAG])
+
+  def _GetXmlOutput(self, gtest_prog_name, extra_args, expected_exit_code):
+    """
+    Returns the xml output generated by running the program gtest_prog_name.
+    Furthermore, the program's exit code must be expected_exit_code.
+    """
+    xml_path = os.path.join(gtest_test_utils.GetTempDir(),
+                            gtest_prog_name + 'out.xml')
+    gtest_prog_path = gtest_test_utils.GetTestExecutablePath(gtest_prog_name)
+
+    command = ([gtest_prog_path, '%s=xml:%s' % (GTEST_OUTPUT_FLAG, xml_path)] +
+               extra_args)
+    p = gtest_test_utils.Subprocess(command)
+    if p.terminated_by_signal:
+      self.assert_(False,
+                   '%s was killed by signal %d' % (gtest_prog_name, p.signal))
+    else:
+      self.assert_(p.exited)
+      self.assertEquals(expected_exit_code, p.exit_code,
+                        "'%s' exited with code %s, which doesn't match "
+                        'the expected exit code %s.'
+                        % (command, p.exit_code, expected_exit_code))
+    actual = minidom.parse(xml_path)
+    return actual
+
+  def _TestXmlOutput(self, gtest_prog_name, expected_xml,
+                     expected_exit_code, extra_args=None):
+    """
+    Asserts that the XML document generated by running the program
+    gtest_prog_name matches expected_xml, a string containing another
+    XML document.  Furthermore, the program's exit code must be
+    expected_exit_code.
+    """
+
+    actual = self._GetXmlOutput(gtest_prog_name, extra_args or [],
+                                expected_exit_code)
+    expected = minidom.parseString(expected_xml)
+    self.NormalizeXml(actual.documentElement)
+    self.AssertEquivalentNodes(expected.documentElement,
+                               actual.documentElement)
+    expected.unlink()
+    actual.unlink()
+
+
+if __name__ == '__main__':
+  os.environ['GTEST_STACK_TRACE_DEPTH'] = '1'
+  gtest_test_utils.Main()
diff --git a/third_party/googletest/googletest/test/gtest_xml_output_unittest_.cc b/third_party/googletest/googletest/test/gtest_xml_output_unittest_.cc
new file mode 100644
index 0000000..48b8771
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_xml_output_unittest_.cc
@@ -0,0 +1,181 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: eefacm@gmail.com (Sean Mcafee)
+
+// Unit test for Google Test XML output.
+//
+// A user can specify XML output in a Google Test program to run via
+// either the GTEST_OUTPUT environment variable or the --gtest_output
+// flag.  This is used for testing such functionality.
+//
+// This program will be invoked from a Python unit test.  Don't run it
+// directly.
+
+#include "gtest/gtest.h"
+
+using ::testing::InitGoogleTest;
+using ::testing::TestEventListeners;
+using ::testing::TestWithParam;
+using ::testing::UnitTest;
+using ::testing::Test;
+using ::testing::Values;
+
+class SuccessfulTest : public Test {
+};
+
+TEST_F(SuccessfulTest, Succeeds) {
+  SUCCEED() << "This is a success.";
+  ASSERT_EQ(1, 1);
+}
+
+class FailedTest : public Test {
+};
+
+TEST_F(FailedTest, Fails) {
+  ASSERT_EQ(1, 2);
+}
+
+class DisabledTest : public Test {
+};
+
+TEST_F(DisabledTest, DISABLED_test_not_run) {
+  FAIL() << "Unexpected failure: Disabled test should not be run";
+}
+
+TEST(MixedResultTest, Succeeds) {
+  EXPECT_EQ(1, 1);
+  ASSERT_EQ(1, 1);
+}
+
+TEST(MixedResultTest, Fails) {
+  EXPECT_EQ(1, 2);
+  ASSERT_EQ(2, 3);
+}
+
+TEST(MixedResultTest, DISABLED_test) {
+  FAIL() << "Unexpected failure: Disabled test should not be run";
+}
+
+TEST(XmlQuotingTest, OutputsCData) {
+  FAIL() << "XML output: "
+            "<?xml encoding=\"utf-8\"><top><![CDATA[cdata text]]></top>";
+}
+
+// Helps to test that invalid characters produced by test code do not make
+// it into the XML file.
+TEST(InvalidCharactersTest, InvalidCharactersInMessage) {
+  FAIL() << "Invalid characters in brackets [\x1\x2]";
+}
+
+class PropertyRecordingTest : public Test {
+ public:
+  static void SetUpTestCase() { RecordProperty("SetUpTestCase", "yes"); }
+  static void TearDownTestCase() { RecordProperty("TearDownTestCase", "aye"); }
+};
+
+TEST_F(PropertyRecordingTest, OneProperty) {
+  RecordProperty("key_1", "1");
+}
+
+TEST_F(PropertyRecordingTest, IntValuedProperty) {
+  RecordProperty("key_int", 1);
+}
+
+TEST_F(PropertyRecordingTest, ThreeProperties) {
+  RecordProperty("key_1", "1");
+  RecordProperty("key_2", "2");
+  RecordProperty("key_3", "3");
+}
+
+TEST_F(PropertyRecordingTest, TwoValuesForOneKeyUsesLastValue) {
+  RecordProperty("key_1", "1");
+  RecordProperty("key_1", "2");
+}
+
+TEST(NoFixtureTest, RecordProperty) {
+  RecordProperty("key", "1");
+}
+
+void ExternalUtilityThatCallsRecordProperty(const std::string& key, int value) {
+  testing::Test::RecordProperty(key, value);
+}
+
+void ExternalUtilityThatCallsRecordProperty(const std::string& key,
+                                            const std::string& value) {
+  testing::Test::RecordProperty(key, value);
+}
+
+TEST(NoFixtureTest, ExternalUtilityThatCallsRecordIntValuedProperty) {
+  ExternalUtilityThatCallsRecordProperty("key_for_utility_int", 1);
+}
+
+TEST(NoFixtureTest, ExternalUtilityThatCallsRecordStringValuedProperty) {
+  ExternalUtilityThatCallsRecordProperty("key_for_utility_string", "1");
+}
+
+// Verifies that the test parameter value is output in the 'value_param'
+// XML attribute for value-parameterized tests.
+class ValueParamTest : public TestWithParam<int> {};
+TEST_P(ValueParamTest, HasValueParamAttribute) {}
+TEST_P(ValueParamTest, AnotherTestThatHasValueParamAttribute) {}
+INSTANTIATE_TEST_CASE_P(Single, ValueParamTest, Values(33, 42));
+
+#if GTEST_HAS_TYPED_TEST
+// Verifies that the type parameter name is output in the 'type_param'
+// XML attribute for typed tests.
+template <typename T> class TypedTest : public Test {};
+typedef testing::Types<int, long> TypedTestTypes;
+TYPED_TEST_CASE(TypedTest, TypedTestTypes);
+TYPED_TEST(TypedTest, HasTypeParamAttribute) {}
+#endif
+
+#if GTEST_HAS_TYPED_TEST_P
+// Verifies that the type parameter name is output in the 'type_param'
+// XML attribute for type-parameterized tests.
+template <typename T> class TypeParameterizedTestCase : public Test {};
+TYPED_TEST_CASE_P(TypeParameterizedTestCase);
+TYPED_TEST_P(TypeParameterizedTestCase, HasTypeParamAttribute) {}
+REGISTER_TYPED_TEST_CASE_P(TypeParameterizedTestCase, HasTypeParamAttribute);
+typedef testing::Types<int, long> TypeParameterizedTestCaseTypes;
+INSTANTIATE_TYPED_TEST_CASE_P(Single,
+                              TypeParameterizedTestCase,
+                              TypeParameterizedTestCaseTypes);
+#endif
+
+int main(int argc, char** argv) {
+  InitGoogleTest(&argc, argv);
+
+  if (argc > 1 && strcmp(argv[1], "--shut_down_xml") == 0) {
+    TestEventListeners& listeners = UnitTest::GetInstance()->listeners();
+    delete listeners.Release(listeners.default_xml_generator());
+  }
+  testing::Test::RecordProperty("ad_hoc_property", "42");
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/googletest/googletest/test/gtest_xml_test_utils.py b/third_party/googletest/googletest/test/gtest_xml_test_utils.py
new file mode 100755
index 0000000..3d0c3b2
--- /dev/null
+++ b/third_party/googletest/googletest/test/gtest_xml_test_utils.py
@@ -0,0 +1,194 @@
+#!/usr/bin/env python
+#
+# Copyright 2006, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Unit test utilities for gtest_xml_output"""
+
+__author__ = 'eefacm@gmail.com (Sean Mcafee)'
+
+import re
+from xml.dom import minidom, Node
+
+import gtest_test_utils
+
+
+GTEST_OUTPUT_FLAG         = '--gtest_output'
+GTEST_DEFAULT_OUTPUT_FILE = 'test_detail.xml'
+
+class GTestXMLTestCase(gtest_test_utils.TestCase):
+  """
+  Base class for tests of Google Test's XML output functionality.
+  """
+
+
+  def AssertEquivalentNodes(self, expected_node, actual_node):
+    """
+    Asserts that actual_node (a DOM node object) is equivalent to
+    expected_node (another DOM node object), in that either both of
+    them are CDATA nodes and have the same value, or both are DOM
+    elements and actual_node meets all of the following conditions:
+
+    *  It has the same tag name as expected_node.
+    *  It has the same set of attributes as expected_node, each with
+       the same value as the corresponding attribute of expected_node.
+       Exceptions are any attribute named "time", which needs only be
+       convertible to a floating-point number and any attribute named
+       "type_param" which only has to be non-empty.
+    *  It has an equivalent set of child nodes (including elements and
+       CDATA sections) as expected_node.  Note that we ignore the
+       order of the children as they are not guaranteed to be in any
+       particular order.
+    """
+
+    if expected_node.nodeType == Node.CDATA_SECTION_NODE:
+      self.assertEquals(Node.CDATA_SECTION_NODE, actual_node.nodeType)
+      self.assertEquals(expected_node.nodeValue, actual_node.nodeValue)
+      return
+
+    self.assertEquals(Node.ELEMENT_NODE, actual_node.nodeType)
+    self.assertEquals(Node.ELEMENT_NODE, expected_node.nodeType)
+    self.assertEquals(expected_node.tagName, actual_node.tagName)
+
+    expected_attributes = expected_node.attributes
+    actual_attributes   = actual_node  .attributes
+    self.assertEquals(
+        expected_attributes.length, actual_attributes.length,
+        'attribute numbers differ in element %s:\nExpected: %r\nActual: %r' % (
+            actual_node.tagName, expected_attributes.keys(),
+            actual_attributes.keys()))
+    for i in range(expected_attributes.length):
+      expected_attr = expected_attributes.item(i)
+      actual_attr   = actual_attributes.get(expected_attr.name)
+      self.assert_(
+          actual_attr is not None,
+          'expected attribute %s not found in element %s' %
+          (expected_attr.name, actual_node.tagName))
+      self.assertEquals(
+          expected_attr.value, actual_attr.value,
+          ' values of attribute %s in element %s differ: %s vs %s' %
+          (expected_attr.name, actual_node.tagName,
+           expected_attr.value, actual_attr.value))
+
+    expected_children = self._GetChildren(expected_node)
+    actual_children = self._GetChildren(actual_node)
+    self.assertEquals(
+        len(expected_children), len(actual_children),
+        'number of child elements differ in element ' + actual_node.tagName)
+    for child_id, child in expected_children.iteritems():
+      self.assert_(child_id in actual_children,
+                   '<%s> is not in <%s> (in element %s)' %
+                   (child_id, actual_children, actual_node.tagName))
+      self.AssertEquivalentNodes(child, actual_children[child_id])
+
+  identifying_attribute = {
+    'testsuites': 'name',
+    'testsuite': 'name',
+    'testcase':  'name',
+    'failure':   'message',
+    }
+
+  def _GetChildren(self, element):
+    """
+    Fetches all of the child nodes of element, a DOM Element object.
+    Returns them as the values of a dictionary keyed by the IDs of the
+    children.  For <testsuites>, <testsuite> and <testcase> elements, the ID
+    is the value of their "name" attribute; for <failure> elements, it is
+    the value of the "message" attribute; CDATA sections and non-whitespace
+    text nodes are concatenated into a single CDATA section with ID
+    "detail".  An exception is raised if any element other than the above
+    four is encountered, if two child elements with the same identifying
+    attributes are encountered, or if any other type of node is encountered.
+    """
+
+    children = {}
+    for child in element.childNodes:
+      if child.nodeType == Node.ELEMENT_NODE:
+        self.assert_(child.tagName in self.identifying_attribute,
+                     'Encountered unknown element <%s>' % child.tagName)
+        childID = child.getAttribute(self.identifying_attribute[child.tagName])
+        self.assert_(childID not in children)
+        children[childID] = child
+      elif child.nodeType in [Node.TEXT_NODE, Node.CDATA_SECTION_NODE]:
+        if 'detail' not in children:
+          if (child.nodeType == Node.CDATA_SECTION_NODE or
+              not child.nodeValue.isspace()):
+            children['detail'] = child.ownerDocument.createCDATASection(
+                child.nodeValue)
+        else:
+          children['detail'].nodeValue += child.nodeValue
+      else:
+        self.fail('Encountered unexpected node type %d' % child.nodeType)
+    return children
+
+  def NormalizeXml(self, element):
+    """
+    Normalizes Google Test's XML output to eliminate references to transient
+    information that may change from run to run.
+
+    *  The "time" attribute of <testsuites>, <testsuite> and <testcase>
+       elements is replaced with a single asterisk, if it contains
+       only digit characters.
+    *  The "timestamp" attribute of <testsuites> elements is replaced with a
+       single asterisk, if it contains a valid ISO8601 datetime value.
+    *  The "type_param" attribute of <testcase> elements is replaced with a
+       single asterisk (if it sn non-empty) as it is the type name returned
+       by the compiler and is platform dependent.
+    *  The line info reported in the first line of the "message"
+       attribute and CDATA section of <failure> elements is replaced with the
+       file's basename and a single asterisk for the line number.
+    *  The directory names in file paths are removed.
+    *  The stack traces are removed.
+    """
+
+    if element.tagName == 'testsuites':
+      timestamp = element.getAttributeNode('timestamp')
+      timestamp.value = re.sub(r'^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d$',
+                               '*', timestamp.value)
+    if element.tagName in ('testsuites', 'testsuite', 'testcase'):
+      time = element.getAttributeNode('time')
+      time.value = re.sub(r'^\d+(\.\d+)?$', '*', time.value)
+      type_param = element.getAttributeNode('type_param')
+      if type_param and type_param.value:
+        type_param.value = '*'
+    elif element.tagName == 'failure':
+      source_line_pat = r'^.*[/\\](.*:)\d+\n'
+      # Replaces the source line information with a normalized form.
+      message = element.getAttributeNode('message')
+      message.value = re.sub(source_line_pat, '\\1*\n', message.value)
+      for child in element.childNodes:
+        if child.nodeType == Node.CDATA_SECTION_NODE:
+          # Replaces the source line information with a normalized form.
+          cdata = re.sub(source_line_pat, '\\1*\n', child.nodeValue)
+          # Removes the actual stack trace.
+          child.nodeValue = re.sub(r'\nStack trace:\n(.|\n)*',
+                                   '', cdata)
+    for child in element.childNodes:
+      if child.nodeType == Node.ELEMENT_NODE:
+        self.NormalizeXml(child)
diff --git a/third_party/googletest/googletest/test/production.cc b/third_party/googletest/googletest/test/production.cc
new file mode 100644
index 0000000..8b8a40b
--- /dev/null
+++ b/third_party/googletest/googletest/test/production.cc
@@ -0,0 +1,36 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// This is part of the unit test for include/gtest/gtest_prod.h.
+
+#include "production.h"
+
+PrivateCode::PrivateCode() : x_(0) {}
diff --git a/third_party/googletest/googletest/test/production.h b/third_party/googletest/googletest/test/production.h
new file mode 100644
index 0000000..98fd5e4
--- /dev/null
+++ b/third_party/googletest/googletest/test/production.h
@@ -0,0 +1,55 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// This is part of the unit test for include/gtest/gtest_prod.h.
+
+#ifndef GTEST_TEST_PRODUCTION_H_
+#define GTEST_TEST_PRODUCTION_H_
+
+#include "gtest/gtest_prod.h"
+
+class PrivateCode {
+ public:
+  // Declares a friend test that does not use a fixture.
+  FRIEND_TEST(PrivateCodeTest, CanAccessPrivateMembers);
+
+  // Declares a friend test that uses a fixture.
+  FRIEND_TEST(PrivateCodeFixtureTest, CanAccessPrivateMembers);
+
+  PrivateCode();
+
+  int x() const { return x_; }
+ private:
+  void set_x(int an_x) { x_ = an_x; }
+  int x_;
+};
+
+#endif  // GTEST_TEST_PRODUCTION_H_
diff --git a/third_party/googletest/googletest/xcode/Config/DebugProject.xcconfig b/third_party/googletest/googletest/xcode/Config/DebugProject.xcconfig
new file mode 100644
index 0000000..3d68157
--- /dev/null
+++ b/third_party/googletest/googletest/xcode/Config/DebugProject.xcconfig
@@ -0,0 +1,30 @@
+//
+//  DebugProject.xcconfig
+//
+//  These are Debug Configuration project settings for the gtest framework and
+//  examples. It is set in the "Based On:" dropdown in the "Project" info
+//  dialog.
+//  This file is based on the Xcode Configuration files in:
+//  http://code.google.com/p/google-toolbox-for-mac/
+// 
+
+#include "General.xcconfig"
+
+// No optimization
+GCC_OPTIMIZATION_LEVEL = 0
+
+// Deployment postprocessing is what triggers Xcode to strip, turn it off
+DEPLOYMENT_POSTPROCESSING = NO
+
+// Dead code stripping off
+DEAD_CODE_STRIPPING = NO
+
+// Debug symbols should be on obviously
+GCC_GENERATE_DEBUGGING_SYMBOLS = YES
+
+// Define the DEBUG macro in all debug builds
+OTHER_CFLAGS = $(OTHER_CFLAGS) -DDEBUG=1
+
+// These are turned off to avoid STL incompatibilities with client code
+// // Turns on special C++ STL checks to "encourage" good STL use
+// GCC_PREPROCESSOR_DEFINITIONS = $(GCC_PREPROCESSOR_DEFINITIONS) _GLIBCXX_DEBUG_PEDANTIC _GLIBCXX_DEBUG _GLIBCPP_CONCEPT_CHECKS
diff --git a/third_party/googletest/googletest/xcode/Config/FrameworkTarget.xcconfig b/third_party/googletest/googletest/xcode/Config/FrameworkTarget.xcconfig
new file mode 100644
index 0000000..357b1c8
--- /dev/null
+++ b/third_party/googletest/googletest/xcode/Config/FrameworkTarget.xcconfig
@@ -0,0 +1,17 @@
+//
+//  FrameworkTarget.xcconfig
+//
+//  These are Framework target settings for the gtest framework and examples. It
+//  is set in the "Based On:" dropdown in the "Target" info dialog.
+//  This file is based on the Xcode Configuration files in:
+//  http://code.google.com/p/google-toolbox-for-mac/
+// 
+
+// Dynamic libs need to be position independent
+GCC_DYNAMIC_NO_PIC = NO
+
+// Dynamic libs should not have their external symbols stripped.
+STRIP_STYLE = non-global
+
+// Let the user install by specifying the $DSTROOT with xcodebuild
+SKIP_INSTALL = NO
diff --git a/third_party/googletest/googletest/xcode/Config/General.xcconfig b/third_party/googletest/googletest/xcode/Config/General.xcconfig
new file mode 100644
index 0000000..f23e322
--- /dev/null
+++ b/third_party/googletest/googletest/xcode/Config/General.xcconfig
@@ -0,0 +1,41 @@
+//
+//  General.xcconfig
+//
+//  These are General configuration settings for the gtest framework and
+//  examples.
+//  This file is based on the Xcode Configuration files in:
+//  http://code.google.com/p/google-toolbox-for-mac/
+// 
+
+// Build for PPC and Intel, 32- and 64-bit
+ARCHS = i386 x86_64 ppc ppc64
+
+// Zerolink prevents link warnings so turn it off
+ZERO_LINK = NO
+
+// Prebinding considered unhelpful in 10.3 and later
+PREBINDING = NO
+
+// Strictest warning policy
+WARNING_CFLAGS = -Wall -Werror -Wendif-labels -Wnewline-eof -Wno-sign-compare -Wshadow
+
+// Work around Xcode bugs by using external strip. See:
+// http://lists.apple.com/archives/Xcode-users/2006/Feb/msg00050.html
+SEPARATE_STRIP = YES
+
+// Force C99 dialect
+GCC_C_LANGUAGE_STANDARD = c99
+
+// not sure why apple defaults this on, but it's pretty risky
+ALWAYS_SEARCH_USER_PATHS = NO
+
+// Turn on position dependent code for most cases (overridden where appropriate)
+GCC_DYNAMIC_NO_PIC = YES
+
+// Default SDK and minimum OS version is 10.4
+SDKROOT = $(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk
+MACOSX_DEPLOYMENT_TARGET = 10.4
+GCC_VERSION = 4.0
+
+// VERSIONING BUILD SETTINGS (used in Info.plist)
+GTEST_VERSIONINFO_ABOUT =  © 2008 Google Inc.
diff --git a/third_party/googletest/googletest/xcode/Config/ReleaseProject.xcconfig b/third_party/googletest/googletest/xcode/Config/ReleaseProject.xcconfig
new file mode 100644
index 0000000..5349f0a
--- /dev/null
+++ b/third_party/googletest/googletest/xcode/Config/ReleaseProject.xcconfig
@@ -0,0 +1,32 @@
+//
+//  ReleaseProject.xcconfig
+//
+//  These are Release Configuration project settings for the gtest framework
+//  and examples. It is set in the "Based On:" dropdown in the "Project" info
+//  dialog.
+//  This file is based on the Xcode Configuration files in:
+//  http://code.google.com/p/google-toolbox-for-mac/
+// 
+
+#include "General.xcconfig"
+
+// subconfig/Release.xcconfig
+
+// Optimize for space and size (Apple recommendation)
+GCC_OPTIMIZATION_LEVEL = s
+
+// Deploment postprocessing is what triggers Xcode to strip
+DEPLOYMENT_POSTPROCESSING = YES
+
+// No symbols
+GCC_GENERATE_DEBUGGING_SYMBOLS = NO
+
+// Dead code strip does not affect ObjC code but can help for C
+DEAD_CODE_STRIPPING = YES
+
+// NDEBUG is used by things like assert.h, so define it for general compat.
+// ASSERT going away in release tends to create unused vars.
+OTHER_CFLAGS = $(OTHER_CFLAGS) -DNDEBUG=1 -Wno-unused-variable
+
+// When we strip we want to strip all symbols in release, but save externals.
+STRIP_STYLE = all
diff --git a/third_party/googletest/googletest/xcode/Config/StaticLibraryTarget.xcconfig b/third_party/googletest/googletest/xcode/Config/StaticLibraryTarget.xcconfig
new file mode 100644
index 0000000..3922fa5
--- /dev/null
+++ b/third_party/googletest/googletest/xcode/Config/StaticLibraryTarget.xcconfig
@@ -0,0 +1,18 @@
+//
+//  StaticLibraryTarget.xcconfig
+//
+//  These are static library target settings for libgtest.a. It
+//  is set in the "Based On:" dropdown in the "Target" info dialog.
+//  This file is based on the Xcode Configuration files in:
+//  http://code.google.com/p/google-toolbox-for-mac/
+// 
+
+// Static libs can be included in bundles so make them position independent
+GCC_DYNAMIC_NO_PIC = NO
+
+// Static libs should not have their internal globals or external symbols
+// stripped.
+STRIP_STYLE = debugging
+
+// Let the user install by specifying the $DSTROOT with xcodebuild
+SKIP_INSTALL = NO
diff --git a/third_party/googletest/googletest/xcode/Config/TestTarget.xcconfig b/third_party/googletest/googletest/xcode/Config/TestTarget.xcconfig
new file mode 100644
index 0000000..e6652ba
--- /dev/null
+++ b/third_party/googletest/googletest/xcode/Config/TestTarget.xcconfig
@@ -0,0 +1,8 @@
+//
+//  TestTarget.xcconfig
+//
+//  These are Test target settings for the gtest framework and examples. It
+//  is set in the "Based On:" dropdown in the "Target" info dialog.
+
+PRODUCT_NAME = $(TARGET_NAME)
+HEADER_SEARCH_PATHS = ../include
diff --git a/third_party/googletest/googletest/xcode/Resources/Info.plist b/third_party/googletest/googletest/xcode/Resources/Info.plist
new file mode 100644
index 0000000..9dd28ea
--- /dev/null
+++ b/third_party/googletest/googletest/xcode/Resources/Info.plist
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleIconFile</key>
+	<string></string>
+	<key>CFBundleIdentifier</key>
+	<string>com.google.${PRODUCT_NAME}</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundlePackageType</key>
+	<string>FMWK</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>GTEST_VERSIONINFO_LONG</string>
+	<key>CFBundleShortVersionString</key>
+	<string>GTEST_VERSIONINFO_SHORT</string>
+	<key>CFBundleGetInfoString</key>
+	<string>${PRODUCT_NAME} GTEST_VERSIONINFO_LONG, ${GTEST_VERSIONINFO_ABOUT}</string>
+	<key>NSHumanReadableCopyright</key>
+	<string>${GTEST_VERSIONINFO_ABOUT}</string>
+	<key>CSResourcesFileMapped</key>
+	<true/>
+</dict>
+</plist>
diff --git a/third_party/googletest/googletest/xcode/Samples/FrameworkSample/Info.plist b/third_party/googletest/googletest/xcode/Samples/FrameworkSample/Info.plist
new file mode 100644
index 0000000..f3852ed
--- /dev/null
+++ b/third_party/googletest/googletest/xcode/Samples/FrameworkSample/Info.plist
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleIconFile</key>
+	<string></string>
+	<key>CFBundleIdentifier</key>
+	<string>com.google.gtest.${PRODUCT_NAME:identifier}</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>${PRODUCT_NAME}</string>
+	<key>CFBundlePackageType</key>
+	<string>FMWK</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1.0</string>
+	<key>CSResourcesFileMapped</key>
+	<true/>
+</dict>
+</plist>
diff --git a/third_party/googletest/googletest/xcode/Samples/FrameworkSample/WidgetFramework.xcodeproj/project.pbxproj b/third_party/googletest/googletest/xcode/Samples/FrameworkSample/WidgetFramework.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..497617e
--- /dev/null
+++ b/third_party/googletest/googletest/xcode/Samples/FrameworkSample/WidgetFramework.xcodeproj/project.pbxproj
@@ -0,0 +1,457 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 42;
+	objects = {
+
+/* Begin PBXAggregateTarget section */
+		4024D162113D7D2400C7059E /* Test */ = {
+			isa = PBXAggregateTarget;
+			buildConfigurationList = 4024D169113D7D4600C7059E /* Build configuration list for PBXAggregateTarget "Test" */;
+			buildPhases = (
+				4024D161113D7D2400C7059E /* ShellScript */,
+			);
+			dependencies = (
+				4024D166113D7D3100C7059E /* PBXTargetDependency */,
+			);
+			name = Test;
+			productName = TestAndBuild;
+		};
+		4024D1E9113D83FF00C7059E /* TestAndBuild */ = {
+			isa = PBXAggregateTarget;
+			buildConfigurationList = 4024D1F0113D842B00C7059E /* Build configuration list for PBXAggregateTarget "TestAndBuild" */;
+			buildPhases = (
+			);
+			dependencies = (
+				4024D1ED113D840900C7059E /* PBXTargetDependency */,
+				4024D1EF113D840D00C7059E /* PBXTargetDependency */,
+			);
+			name = TestAndBuild;
+			productName = TestAndBuild;
+		};
+/* End PBXAggregateTarget section */
+
+/* Begin PBXBuildFile section */
+		3B7EB1250E5AEE3500C7F239 /* widget.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3B7EB1230E5AEE3500C7F239 /* widget.cc */; };
+		3B7EB1260E5AEE3500C7F239 /* widget.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B7EB1240E5AEE3500C7F239 /* widget.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3B7EB1280E5AEE4600C7F239 /* widget_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3B7EB1270E5AEE4600C7F239 /* widget_test.cc */; };
+		3B7EB1480E5AF3B400C7F239 /* Widget.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D07F2C80486CC7A007CD1D0 /* Widget.framework */; };
+		4024D188113D7D7800C7059E /* libgtest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4024D185113D7D5500C7059E /* libgtest.a */; };
+		4024D189113D7D7A00C7059E /* libgtest_main.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4024D183113D7D5500C7059E /* libgtest_main.a */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+		3B07BDF00E3F3FAE00647869 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 8D07F2BC0486CC7A007CD1D0;
+			remoteInfo = gTestExample;
+		};
+		4024D165113D7D3100C7059E /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 3B07BDE90E3F3F9E00647869;
+			remoteInfo = WidgetFrameworkTest;
+		};
+		4024D1EC113D840900C7059E /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 8D07F2BC0486CC7A007CD1D0;
+			remoteInfo = WidgetFramework;
+		};
+		4024D1EE113D840D00C7059E /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 4024D162113D7D2400C7059E;
+			remoteInfo = Test;
+		};
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+		3B07BDEA0E3F3F9E00647869 /* WidgetFrameworkTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = WidgetFrameworkTest; sourceTree = BUILT_PRODUCTS_DIR; };
+		3B7EB1230E5AEE3500C7F239 /* widget.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = widget.cc; sourceTree = "<group>"; };
+		3B7EB1240E5AEE3500C7F239 /* widget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = widget.h; sourceTree = "<group>"; };
+		3B7EB1270E5AEE4600C7F239 /* widget_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = widget_test.cc; sourceTree = "<group>"; };
+		4024D183113D7D5500C7059E /* libgtest_main.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libgtest_main.a; path = /usr/local/lib/libgtest_main.a; sourceTree = "<absolute>"; };
+		4024D185113D7D5500C7059E /* libgtest.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libgtest.a; path = /usr/local/lib/libgtest.a; sourceTree = "<absolute>"; };
+		4024D1E2113D838200C7059E /* runtests.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = runtests.sh; sourceTree = "<group>"; };
+		8D07F2C70486CC7A007CD1D0 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
+		8D07F2C80486CC7A007CD1D0 /* Widget.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Widget.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		3B07BDE80E3F3F9E00647869 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				4024D189113D7D7A00C7059E /* libgtest_main.a in Frameworks */,
+				4024D188113D7D7800C7059E /* libgtest.a in Frameworks */,
+				3B7EB1480E5AF3B400C7F239 /* Widget.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		8D07F2C30486CC7A007CD1D0 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		034768DDFF38A45A11DB9C8B /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				8D07F2C80486CC7A007CD1D0 /* Widget.framework */,
+				3B07BDEA0E3F3F9E00647869 /* WidgetFrameworkTest */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		0867D691FE84028FC02AAC07 /* gTestExample */ = {
+			isa = PBXGroup;
+			children = (
+				4024D1E1113D836C00C7059E /* Scripts */,
+				08FB77ACFE841707C02AAC07 /* Source */,
+				089C1665FE841158C02AAC07 /* Resources */,
+				3B07BE350E4094E400647869 /* Test */,
+				0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */,
+				034768DDFF38A45A11DB9C8B /* Products */,
+			);
+			name = gTestExample;
+			sourceTree = "<group>";
+		};
+		0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */ = {
+			isa = PBXGroup;
+			children = (
+				4024D183113D7D5500C7059E /* libgtest_main.a */,
+				4024D185113D7D5500C7059E /* libgtest.a */,
+			);
+			name = "External Frameworks and Libraries";
+			sourceTree = "<group>";
+		};
+		089C1665FE841158C02AAC07 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				8D07F2C70486CC7A007CD1D0 /* Info.plist */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		08FB77ACFE841707C02AAC07 /* Source */ = {
+			isa = PBXGroup;
+			children = (
+				3B7EB1230E5AEE3500C7F239 /* widget.cc */,
+				3B7EB1240E5AEE3500C7F239 /* widget.h */,
+			);
+			name = Source;
+			sourceTree = "<group>";
+		};
+		3B07BE350E4094E400647869 /* Test */ = {
+			isa = PBXGroup;
+			children = (
+				3B7EB1270E5AEE4600C7F239 /* widget_test.cc */,
+			);
+			name = Test;
+			sourceTree = "<group>";
+		};
+		4024D1E1113D836C00C7059E /* Scripts */ = {
+			isa = PBXGroup;
+			children = (
+				4024D1E2113D838200C7059E /* runtests.sh */,
+			);
+			name = Scripts;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+		8D07F2BD0486CC7A007CD1D0 /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				3B7EB1260E5AEE3500C7F239 /* widget.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+		3B07BDE90E3F3F9E00647869 /* WidgetFrameworkTest */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 3B07BDF40E3F3FB600647869 /* Build configuration list for PBXNativeTarget "WidgetFrameworkTest" */;
+			buildPhases = (
+				3B07BDE70E3F3F9E00647869 /* Sources */,
+				3B07BDE80E3F3F9E00647869 /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				3B07BDF10E3F3FAE00647869 /* PBXTargetDependency */,
+			);
+			name = WidgetFrameworkTest;
+			productName = gTestExampleTest;
+			productReference = 3B07BDEA0E3F3F9E00647869 /* WidgetFrameworkTest */;
+			productType = "com.apple.product-type.tool";
+		};
+		8D07F2BC0486CC7A007CD1D0 /* WidgetFramework */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 4FADC24208B4156D00ABE55E /* Build configuration list for PBXNativeTarget "WidgetFramework" */;
+			buildPhases = (
+				8D07F2C10486CC7A007CD1D0 /* Sources */,
+				8D07F2C30486CC7A007CD1D0 /* Frameworks */,
+				8D07F2BD0486CC7A007CD1D0 /* Headers */,
+				8D07F2BF0486CC7A007CD1D0 /* Resources */,
+				8D07F2C50486CC7A007CD1D0 /* Rez */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = WidgetFramework;
+			productInstallPath = "$(HOME)/Library/Frameworks";
+			productName = gTestExample;
+			productReference = 8D07F2C80486CC7A007CD1D0 /* Widget.framework */;
+			productType = "com.apple.product-type.framework";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		0867D690FE84028FC02AAC07 /* Project object */ = {
+			isa = PBXProject;
+			buildConfigurationList = 4FADC24608B4156D00ABE55E /* Build configuration list for PBXProject "WidgetFramework" */;
+			compatibilityVersion = "Xcode 2.4";
+			hasScannedForEncodings = 1;
+			mainGroup = 0867D691FE84028FC02AAC07 /* gTestExample */;
+			productRefGroup = 034768DDFF38A45A11DB9C8B /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				8D07F2BC0486CC7A007CD1D0 /* WidgetFramework */,
+				3B07BDE90E3F3F9E00647869 /* WidgetFrameworkTest */,
+				4024D162113D7D2400C7059E /* Test */,
+				4024D1E9113D83FF00C7059E /* TestAndBuild */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		8D07F2BF0486CC7A007CD1D0 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXRezBuildPhase section */
+		8D07F2C50486CC7A007CD1D0 /* Rez */ = {
+			isa = PBXRezBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXRezBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		4024D161113D7D2400C7059E /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "/bin/bash $SRCROOT/runtests.sh $BUILT_PRODUCTS_DIR/WidgetFrameworkTest\n";
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		3B07BDE70E3F3F9E00647869 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				3B7EB1280E5AEE4600C7F239 /* widget_test.cc in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		8D07F2C10486CC7A007CD1D0 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				3B7EB1250E5AEE3500C7F239 /* widget.cc in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+		3B07BDF10E3F3FAE00647869 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 8D07F2BC0486CC7A007CD1D0 /* WidgetFramework */;
+			targetProxy = 3B07BDF00E3F3FAE00647869 /* PBXContainerItemProxy */;
+		};
+		4024D166113D7D3100C7059E /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 3B07BDE90E3F3F9E00647869 /* WidgetFrameworkTest */;
+			targetProxy = 4024D165113D7D3100C7059E /* PBXContainerItemProxy */;
+		};
+		4024D1ED113D840900C7059E /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 8D07F2BC0486CC7A007CD1D0 /* WidgetFramework */;
+			targetProxy = 4024D1EC113D840900C7059E /* PBXContainerItemProxy */;
+		};
+		4024D1EF113D840D00C7059E /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 4024D162113D7D2400C7059E /* Test */;
+			targetProxy = 4024D1EE113D840D00C7059E /* PBXContainerItemProxy */;
+		};
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+		3B07BDEC0E3F3F9F00647869 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				PRODUCT_NAME = WidgetFrameworkTest;
+			};
+			name = Debug;
+		};
+		3B07BDED0E3F3F9F00647869 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				PRODUCT_NAME = WidgetFrameworkTest;
+			};
+			name = Release;
+		};
+		4024D163113D7D2400C7059E /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				PRODUCT_NAME = TestAndBuild;
+			};
+			name = Debug;
+		};
+		4024D164113D7D2400C7059E /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				PRODUCT_NAME = TestAndBuild;
+			};
+			name = Release;
+		};
+		4024D1EA113D83FF00C7059E /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				PRODUCT_NAME = TestAndBuild;
+			};
+			name = Debug;
+		};
+		4024D1EB113D83FF00C7059E /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				PRODUCT_NAME = TestAndBuild;
+			};
+			name = Release;
+		};
+		4FADC24308B4156D00ABE55E /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				FRAMEWORK_VERSION = A;
+				INFOPLIST_FILE = Info.plist;
+				INSTALL_PATH = "@loader_path/../Frameworks";
+				PRODUCT_NAME = Widget;
+			};
+			name = Debug;
+		};
+		4FADC24408B4156D00ABE55E /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				FRAMEWORK_VERSION = A;
+				INFOPLIST_FILE = Info.plist;
+				INSTALL_PATH = "@loader_path/../Frameworks";
+				PRODUCT_NAME = Widget;
+			};
+			name = Release;
+		};
+		4FADC24708B4156D00ABE55E /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				GCC_VERSION = 4.0;
+				SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
+			};
+			name = Debug;
+		};
+		4FADC24808B4156D00ABE55E /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				GCC_VERSION = 4.0;
+				SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		3B07BDF40E3F3FB600647869 /* Build configuration list for PBXNativeTarget "WidgetFrameworkTest" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				3B07BDEC0E3F3F9F00647869 /* Debug */,
+				3B07BDED0E3F3F9F00647869 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		4024D169113D7D4600C7059E /* Build configuration list for PBXAggregateTarget "Test" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				4024D163113D7D2400C7059E /* Debug */,
+				4024D164113D7D2400C7059E /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		4024D1F0113D842B00C7059E /* Build configuration list for PBXAggregateTarget "TestAndBuild" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				4024D1EA113D83FF00C7059E /* Debug */,
+				4024D1EB113D83FF00C7059E /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		4FADC24208B4156D00ABE55E /* Build configuration list for PBXNativeTarget "WidgetFramework" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				4FADC24308B4156D00ABE55E /* Debug */,
+				4FADC24408B4156D00ABE55E /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		4FADC24608B4156D00ABE55E /* Build configuration list for PBXProject "WidgetFramework" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				4FADC24708B4156D00ABE55E /* Debug */,
+				4FADC24808B4156D00ABE55E /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 0867D690FE84028FC02AAC07 /* Project object */;
+}
diff --git a/third_party/googletest/googletest/xcode/Samples/FrameworkSample/runtests.sh b/third_party/googletest/googletest/xcode/Samples/FrameworkSample/runtests.sh
new file mode 100644
index 0000000..4a0d413
--- /dev/null
+++ b/third_party/googletest/googletest/xcode/Samples/FrameworkSample/runtests.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+#
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Executes the samples and tests for the Google Test Framework.
+
+# Help the dynamic linker find the path to the libraries.
+export DYLD_FRAMEWORK_PATH=$BUILT_PRODUCTS_DIR
+export DYLD_LIBRARY_PATH=$BUILT_PRODUCTS_DIR
+
+# Create some executables.
+test_executables=$@
+
+# Now execute each one in turn keeping track of how many succeeded and failed.
+succeeded=0
+failed=0
+failed_list=()
+for test in ${test_executables[*]}; do
+  "$test"
+  result=$?
+  if [ $result -eq 0 ]; then
+    succeeded=$(( $succeeded + 1 ))
+  else
+    failed=$(( failed + 1 ))
+    failed_list="$failed_list $test"
+  fi
+done
+
+# Report the successes and failures to the console.
+echo "Tests complete with $succeeded successes and $failed failures."
+if [ $failed -ne 0 ]; then
+  echo "The following tests failed:"
+  echo $failed_list
+fi
+exit $failed
diff --git a/third_party/googletest/googletest/xcode/Samples/FrameworkSample/widget.cc b/third_party/googletest/googletest/xcode/Samples/FrameworkSample/widget.cc
new file mode 100644
index 0000000..bfc4e7f
--- /dev/null
+++ b/third_party/googletest/googletest/xcode/Samples/FrameworkSample/widget.cc
@@ -0,0 +1,63 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: preston.a.jackson@gmail.com (Preston Jackson)
+//
+// Google Test - FrameworkSample
+// widget.cc
+//
+
+// Widget is a very simple class used for demonstrating the use of gtest
+
+#include "widget.h"
+
+Widget::Widget(int number, const std::string& name)
+    : number_(number),
+      name_(name) {}
+
+Widget::~Widget() {}
+
+float Widget::GetFloatValue() const {
+  return number_;
+}
+
+int Widget::GetIntValue() const {
+  return static_cast<int>(number_);
+}
+
+std::string Widget::GetStringValue() const {
+  return name_;
+}
+
+void Widget::GetCharPtrValue(char* buffer, size_t max_size) const {
+  // Copy the char* representation of name_ into buffer, up to max_size.
+  strncpy(buffer, name_.c_str(), max_size-1);
+  buffer[max_size-1] = '\0';
+  return;
+}
diff --git a/third_party/googletest/googletest/xcode/Samples/FrameworkSample/widget.h b/third_party/googletest/googletest/xcode/Samples/FrameworkSample/widget.h
new file mode 100644
index 0000000..0c55cdc
--- /dev/null
+++ b/third_party/googletest/googletest/xcode/Samples/FrameworkSample/widget.h
@@ -0,0 +1,59 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: preston.a.jackson@gmail.com (Preston Jackson)
+//
+// Google Test - FrameworkSample
+// widget.h
+//
+
+// Widget is a very simple class used for demonstrating the use of gtest. It
+// simply stores two values a string and an integer, which are returned via
+// public accessors in multiple forms.
+
+#import <string>
+
+class Widget {
+ public:
+  Widget(int number, const std::string& name);
+  ~Widget();
+
+  // Public accessors to number data
+  float GetFloatValue() const;
+  int GetIntValue() const;
+
+  // Public accessors to the string data
+  std::string GetStringValue() const;
+  void GetCharPtrValue(char* buffer, size_t max_size) const;
+
+ private:
+  // Data members
+  float number_;
+  std::string name_;
+};
diff --git a/third_party/googletest/googletest/xcode/Samples/FrameworkSample/widget_test.cc b/third_party/googletest/googletest/xcode/Samples/FrameworkSample/widget_test.cc
new file mode 100644
index 0000000..8725994
--- /dev/null
+++ b/third_party/googletest/googletest/xcode/Samples/FrameworkSample/widget_test.cc
@@ -0,0 +1,68 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: preston.a.jackson@gmail.com (Preston Jackson)
+//
+// Google Test - FrameworkSample
+// widget_test.cc
+//
+
+// This is a simple test file for the Widget class in the Widget.framework
+
+#include <string>
+#include "gtest/gtest.h"
+
+#include <Widget/widget.h>
+
+// This test verifies that the constructor sets the internal state of the
+// Widget class correctly.
+TEST(WidgetInitializerTest, TestConstructor) {
+  Widget widget(1.0f, "name");
+  EXPECT_FLOAT_EQ(1.0f, widget.GetFloatValue());
+  EXPECT_EQ(std::string("name"), widget.GetStringValue());
+}
+
+// This test verifies the conversion of the float and string values to int and
+// char*, respectively.
+TEST(WidgetInitializerTest, TestConversion) {
+  Widget widget(1.0f, "name");
+  EXPECT_EQ(1, widget.GetIntValue());
+
+  size_t max_size = 128;
+  char buffer[max_size];
+  widget.GetCharPtrValue(buffer, max_size);
+  EXPECT_STREQ("name", buffer);
+}
+
+// Use the Google Test main that is linked into the framework. It does something
+// like this:
+// int main(int argc, char** argv) {
+//   testing::InitGoogleTest(&argc, argv);
+//   return RUN_ALL_TESTS();
+// }
diff --git a/third_party/googletest/googletest/xcode/Scripts/runtests.sh b/third_party/googletest/googletest/xcode/Scripts/runtests.sh
new file mode 100644
index 0000000..3fc229f
--- /dev/null
+++ b/third_party/googletest/googletest/xcode/Scripts/runtests.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+#
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Executes the samples and tests for the Google Test Framework.
+
+# Help the dynamic linker find the path to the libraries.
+export DYLD_FRAMEWORK_PATH=$BUILT_PRODUCTS_DIR
+export DYLD_LIBRARY_PATH=$BUILT_PRODUCTS_DIR
+
+# Create some executables.
+test_executables=("$BUILT_PRODUCTS_DIR/gtest_unittest-framework"
+                  "$BUILT_PRODUCTS_DIR/gtest_unittest"
+                  "$BUILT_PRODUCTS_DIR/sample1_unittest-framework"
+                  "$BUILT_PRODUCTS_DIR/sample1_unittest-static")
+
+# Now execute each one in turn keeping track of how many succeeded and failed. 
+succeeded=0
+failed=0
+failed_list=()
+for test in ${test_executables[*]}; do
+  "$test"
+  result=$?
+  if [ $result -eq 0 ]; then
+    succeeded=$(( $succeeded + 1 ))
+  else
+    failed=$(( failed + 1 ))
+    failed_list="$failed_list $test"
+  fi
+done
+
+# Report the successes and failures to the console.
+echo "Tests complete with $succeeded successes and $failed failures."
+if [ $failed -ne 0 ]; then
+  echo "The following tests failed:"
+  echo $failed_list
+fi
+exit $failed
diff --git a/third_party/googletest/googletest/xcode/Scripts/versiongenerate.py b/third_party/googletest/googletest/xcode/Scripts/versiongenerate.py
new file mode 100755
index 0000000..81de8c9
--- /dev/null
+++ b/third_party/googletest/googletest/xcode/Scripts/versiongenerate.py
@@ -0,0 +1,100 @@
+#!/usr/bin/env python
+#
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""A script to prepare version informtion for use the gtest Info.plist file.
+
+  This script extracts the version information from the configure.ac file and
+  uses it to generate a header file containing the same information. The
+  #defines in this header file will be included in during the generation of
+  the Info.plist of the framework, giving the correct value to the version
+  shown in the Finder.
+
+  This script makes the following assumptions (these are faults of the script,
+  not problems with the Autoconf):
+    1. The AC_INIT macro will be contained within the first 1024 characters
+       of configure.ac
+    2. The version string will be 3 integers separated by periods and will be
+       surrounded by squre brackets, "[" and "]" (e.g. [1.0.1]). The first
+       segment represents the major version, the second represents the minor
+       version and the third represents the fix version.
+    3. No ")" character exists between the opening "(" and closing ")" of
+       AC_INIT, including in comments and character strings.
+"""
+
+import sys
+import re
+
+# Read the command line argument (the output directory for Version.h)
+if (len(sys.argv) < 3):
+  print "Usage: versiongenerate.py input_dir output_dir"
+  sys.exit(1)
+else:
+  input_dir = sys.argv[1]
+  output_dir = sys.argv[2]
+
+# Read the first 1024 characters of the configure.ac file
+config_file = open("%s/configure.ac" % input_dir, 'r')
+buffer_size = 1024
+opening_string = config_file.read(buffer_size)
+config_file.close()
+
+# Extract the version string from the AC_INIT macro
+#   The following init_expression means:
+#     Extract three integers separated by periods and surrounded by squre
+#     brackets(e.g. "[1.0.1]") between "AC_INIT(" and ")". Do not be greedy
+#     (*? is the non-greedy flag) since that would pull in everything between
+#     the first "(" and the last ")" in the file.
+version_expression = re.compile(r"AC_INIT\(.*?\[(\d+)\.(\d+)\.(\d+)\].*?\)",
+                                re.DOTALL)
+version_values = version_expression.search(opening_string)
+major_version = version_values.group(1)
+minor_version = version_values.group(2)
+fix_version = version_values.group(3)
+
+# Write the version information to a header file to be included in the
+# Info.plist file.
+file_data = """//
+// DO NOT MODIFY THIS FILE (but you can delete it)
+//
+// This file is autogenerated by the versiongenerate.py script. This script
+// is executed in a "Run Script" build phase when creating gtest.framework. This
+// header file is not used during compilation of C-source. Rather, it simply
+// defines some version strings for substitution in the Info.plist. Because of
+// this, we are not not restricted to C-syntax nor are we using include guards.
+//
+
+#define GTEST_VERSIONINFO_SHORT %s.%s
+#define GTEST_VERSIONINFO_LONG %s.%s.%s
+
+""" % (major_version, minor_version, major_version, minor_version, fix_version)
+version_file = open("%s/Version.h" % output_dir, 'w')
+version_file.write(file_data)
+version_file.close()
diff --git a/third_party/googletest/googletest/xcode/gtest.xcodeproj/project.pbxproj b/third_party/googletest/googletest/xcode/gtest.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..aefaa88
--- /dev/null
+++ b/third_party/googletest/googletest/xcode/gtest.xcodeproj/project.pbxproj
@@ -0,0 +1,1135 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXAggregateTarget section */
+		3B238F5F0E828B5400846E11 /* Check */ = {
+			isa = PBXAggregateTarget;
+			buildConfigurationList = 3B238FA30E828BB600846E11 /* Build configuration list for PBXAggregateTarget "Check" */;
+			buildPhases = (
+				3B238F5E0E828B5400846E11 /* ShellScript */,
+			);
+			dependencies = (
+				40899F9D0FFA740F000B29AE /* PBXTargetDependency */,
+				40C849F7101A43440083642A /* PBXTargetDependency */,
+				4089A0980FFAD34A000B29AE /* PBXTargetDependency */,
+				40C849F9101A43490083642A /* PBXTargetDependency */,
+			);
+			name = Check;
+			productName = Check;
+		};
+		40C44ADC0E3798F4008FCC51 /* Version Info */ = {
+			isa = PBXAggregateTarget;
+			buildConfigurationList = 40C44AE40E379905008FCC51 /* Build configuration list for PBXAggregateTarget "Version Info" */;
+			buildPhases = (
+				40C44ADB0E3798F4008FCC51 /* Generate Version.h */,
+			);
+			comments = "The generation of Version.h must be performed in its own target. Since the Info.plist is preprocessed before any of the other build phases in gtest, the Version.h file would not be ready if included as a build phase of that target.";
+			dependencies = (
+			);
+			name = "Version Info";
+			productName = Version.h;
+		};
+/* End PBXAggregateTarget section */
+
+/* Begin PBXBuildFile section */
+		224A12A30E9EADCC00BD17FD /* gtest-test-part.h in Headers */ = {isa = PBXBuildFile; fileRef = 224A12A20E9EADCC00BD17FD /* gtest-test-part.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3BF6F2A00E79B5AD000F2EEE /* gtest-type-util.h in Copy Headers Internal */ = {isa = PBXBuildFile; fileRef = 3BF6F29F0E79B5AD000F2EEE /* gtest-type-util.h */; };
+		3BF6F2A50E79B616000F2EEE /* gtest-typed-test.h in Headers */ = {isa = PBXBuildFile; fileRef = 3BF6F2A40E79B616000F2EEE /* gtest-typed-test.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		404884380E2F799B00CF7658 /* gtest-death-test.h in Headers */ = {isa = PBXBuildFile; fileRef = 404883DB0E2F799B00CF7658 /* gtest-death-test.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		404884390E2F799B00CF7658 /* gtest-message.h in Headers */ = {isa = PBXBuildFile; fileRef = 404883DC0E2F799B00CF7658 /* gtest-message.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		4048843A0E2F799B00CF7658 /* gtest-spi.h in Headers */ = {isa = PBXBuildFile; fileRef = 404883DD0E2F799B00CF7658 /* gtest-spi.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		4048843B0E2F799B00CF7658 /* gtest.h in Headers */ = {isa = PBXBuildFile; fileRef = 404883DE0E2F799B00CF7658 /* gtest.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		4048843C0E2F799B00CF7658 /* gtest_pred_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = 404883DF0E2F799B00CF7658 /* gtest_pred_impl.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		4048843D0E2F799B00CF7658 /* gtest_prod.h in Headers */ = {isa = PBXBuildFile; fileRef = 404883E00E2F799B00CF7658 /* gtest_prod.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		404884500E2F799B00CF7658 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 404883F60E2F799B00CF7658 /* README.md */; };
+		404884A00E2F7BE600CF7658 /* gtest-death-test-internal.h in Copy Headers Internal */ = {isa = PBXBuildFile; fileRef = 404883E20E2F799B00CF7658 /* gtest-death-test-internal.h */; };
+		404884A10E2F7BE600CF7658 /* gtest-filepath.h in Copy Headers Internal */ = {isa = PBXBuildFile; fileRef = 404883E30E2F799B00CF7658 /* gtest-filepath.h */; };
+		404884A20E2F7BE600CF7658 /* gtest-internal.h in Copy Headers Internal */ = {isa = PBXBuildFile; fileRef = 404883E40E2F799B00CF7658 /* gtest-internal.h */; };
+		404884A30E2F7BE600CF7658 /* gtest-port.h in Copy Headers Internal */ = {isa = PBXBuildFile; fileRef = 404883E50E2F799B00CF7658 /* gtest-port.h */; };
+		404884A40E2F7BE600CF7658 /* gtest-string.h in Copy Headers Internal */ = {isa = PBXBuildFile; fileRef = 404883E60E2F799B00CF7658 /* gtest-string.h */; };
+		404884AC0E2F7CD900CF7658 /* CHANGES in Resources */ = {isa = PBXBuildFile; fileRef = 404884A90E2F7CD900CF7658 /* CHANGES */; };
+		404884AD0E2F7CD900CF7658 /* CONTRIBUTORS in Resources */ = {isa = PBXBuildFile; fileRef = 404884AA0E2F7CD900CF7658 /* CONTRIBUTORS */; };
+		404884AE0E2F7CD900CF7658 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 404884AB0E2F7CD900CF7658 /* LICENSE */; };
+		40899F3A0FFA70D4000B29AE /* gtest-all.cc in Sources */ = {isa = PBXBuildFile; fileRef = 224A12A10E9EADA700BD17FD /* gtest-all.cc */; };
+		40899F500FFA7281000B29AE /* gtest-tuple.h in Copy Headers Internal */ = {isa = PBXBuildFile; fileRef = 40899F4D0FFA7271000B29AE /* gtest-tuple.h */; };
+		40899F530FFA72A0000B29AE /* gtest_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3B238C120E7FE13C00846E11 /* gtest_unittest.cc */; };
+		4089A0440FFAD1BE000B29AE /* sample1.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4089A02C0FFACF7F000B29AE /* sample1.cc */; };
+		4089A0460FFAD1BE000B29AE /* sample1_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4089A02E0FFACF7F000B29AE /* sample1_unittest.cc */; };
+		40C848FF101A21150083642A /* gtest-all.cc in Sources */ = {isa = PBXBuildFile; fileRef = 224A12A10E9EADA700BD17FD /* gtest-all.cc */; };
+		40C84915101A21DF0083642A /* gtest_main.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4048840D0E2F799B00CF7658 /* gtest_main.cc */; };
+		40C84916101A235B0083642A /* libgtest_main.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 40C8490B101A217E0083642A /* libgtest_main.a */; };
+		40C84921101A23AD0083642A /* libgtest_main.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 40C8490B101A217E0083642A /* libgtest_main.a */; };
+		40C84978101A36540083642A /* libgtest_main.a in Resources */ = {isa = PBXBuildFile; fileRef = 40C8490B101A217E0083642A /* libgtest_main.a */; };
+		40C84980101A36850083642A /* gtest_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3B238C120E7FE13C00846E11 /* gtest_unittest.cc */; };
+		40C84982101A36850083642A /* libgtest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 40C848FA101A209C0083642A /* libgtest.a */; };
+		40C84983101A36850083642A /* libgtest_main.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 40C8490B101A217E0083642A /* libgtest_main.a */; };
+		40C8498F101A36A60083642A /* sample1.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4089A02C0FFACF7F000B29AE /* sample1.cc */; };
+		40C84990101A36A60083642A /* sample1_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4089A02E0FFACF7F000B29AE /* sample1_unittest.cc */; };
+		40C84992101A36A60083642A /* libgtest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 40C848FA101A209C0083642A /* libgtest.a */; };
+		40C84993101A36A60083642A /* libgtest_main.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 40C8490B101A217E0083642A /* libgtest_main.a */; };
+		40C849A2101A37050083642A /* gtest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4539C8FF0EC27F6400A70F4C /* gtest.framework */; };
+		40C849A4101A37150083642A /* gtest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4539C8FF0EC27F6400A70F4C /* gtest.framework */; };
+		4539C9340EC280AE00A70F4C /* gtest-param-test.h in Headers */ = {isa = PBXBuildFile; fileRef = 4539C9330EC280AE00A70F4C /* gtest-param-test.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		4539C9380EC280E200A70F4C /* gtest-linked_ptr.h in Copy Headers Internal */ = {isa = PBXBuildFile; fileRef = 4539C9350EC280E200A70F4C /* gtest-linked_ptr.h */; };
+		4539C9390EC280E200A70F4C /* gtest-param-util-generated.h in Copy Headers Internal */ = {isa = PBXBuildFile; fileRef = 4539C9360EC280E200A70F4C /* gtest-param-util-generated.h */; };
+		4539C93A0EC280E200A70F4C /* gtest-param-util.h in Copy Headers Internal */ = {isa = PBXBuildFile; fileRef = 4539C9370EC280E200A70F4C /* gtest-param-util.h */; };
+		4567C8181264FF71007740BE /* gtest-printers.h in Headers */ = {isa = PBXBuildFile; fileRef = 4567C8171264FF71007740BE /* gtest-printers.h */; settings = {ATTRIBUTES = (Public, ); }; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+		40899F9C0FFA740F000B29AE /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 40899F420FFA7184000B29AE;
+			remoteInfo = gtest_unittest;
+		};
+		4089A0970FFAD34A000B29AE /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 4089A0120FFACEFC000B29AE;
+			remoteInfo = sample1_unittest;
+		};
+		408BEC0F1046CFE900DEF522 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 40C848F9101A209C0083642A;
+			remoteInfo = "gtest-static";
+		};
+		40C44AE50E379922008FCC51 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 40C44ADC0E3798F4008FCC51;
+			remoteInfo = Version.h;
+		};
+		40C8497C101A36850083642A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 40C848F9101A209C0083642A;
+			remoteInfo = "gtest-static";
+		};
+		40C8497E101A36850083642A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 40C8490A101A217E0083642A;
+			remoteInfo = "gtest_main-static";
+		};
+		40C8498B101A36A60083642A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 40C848F9101A209C0083642A;
+			remoteInfo = "gtest-static";
+		};
+		40C8498D101A36A60083642A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 40C8490A101A217E0083642A;
+			remoteInfo = "gtest_main-static";
+		};
+		40C8499B101A36DC0083642A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 40C8490A101A217E0083642A;
+			remoteInfo = "gtest_main-static";
+		};
+		40C8499D101A36E50083642A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 8D07F2BC0486CC7A007CD1D0;
+			remoteInfo = "gtest-framework";
+		};
+		40C8499F101A36F10083642A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 8D07F2BC0486CC7A007CD1D0;
+			remoteInfo = "gtest-framework";
+		};
+		40C849F6101A43440083642A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 40C8497A101A36850083642A;
+			remoteInfo = "gtest_unittest-static";
+		};
+		40C849F8101A43490083642A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 40C84989101A36A60083642A;
+			remoteInfo = "sample1_unittest-static";
+		};
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+		404884A50E2F7C0400CF7658 /* Copy Headers Internal */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = Headers/internal;
+			dstSubfolderSpec = 6;
+			files = (
+				404884A00E2F7BE600CF7658 /* gtest-death-test-internal.h in Copy Headers Internal */,
+				404884A10E2F7BE600CF7658 /* gtest-filepath.h in Copy Headers Internal */,
+				404884A20E2F7BE600CF7658 /* gtest-internal.h in Copy Headers Internal */,
+				4539C9380EC280E200A70F4C /* gtest-linked_ptr.h in Copy Headers Internal */,
+				4539C9390EC280E200A70F4C /* gtest-param-util-generated.h in Copy Headers Internal */,
+				4539C93A0EC280E200A70F4C /* gtest-param-util.h in Copy Headers Internal */,
+				404884A30E2F7BE600CF7658 /* gtest-port.h in Copy Headers Internal */,
+				404884A40E2F7BE600CF7658 /* gtest-string.h in Copy Headers Internal */,
+				40899F500FFA7281000B29AE /* gtest-tuple.h in Copy Headers Internal */,
+				3BF6F2A00E79B5AD000F2EEE /* gtest-type-util.h in Copy Headers Internal */,
+			);
+			name = "Copy Headers Internal";
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+		224A12A10E9EADA700BD17FD /* gtest-all.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = "gtest-all.cc"; sourceTree = "<group>"; };
+		224A12A20E9EADCC00BD17FD /* gtest-test-part.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "gtest-test-part.h"; sourceTree = "<group>"; };
+		3B238C120E7FE13C00846E11 /* gtest_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gtest_unittest.cc; sourceTree = "<group>"; };
+		3B87D2100E96B92E000D1852 /* runtests.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = runtests.sh; sourceTree = "<group>"; };
+		3BF6F29F0E79B5AD000F2EEE /* gtest-type-util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-type-util.h"; sourceTree = "<group>"; };
+		3BF6F2A40E79B616000F2EEE /* gtest-typed-test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-typed-test.h"; sourceTree = "<group>"; };
+		403EE37C0E377822004BD1E2 /* versiongenerate.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = versiongenerate.py; sourceTree = "<group>"; };
+		404883DB0E2F799B00CF7658 /* gtest-death-test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-death-test.h"; sourceTree = "<group>"; };
+		404883DC0E2F799B00CF7658 /* gtest-message.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-message.h"; sourceTree = "<group>"; };
+		404883DD0E2F799B00CF7658 /* gtest-spi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-spi.h"; sourceTree = "<group>"; };
+		404883DE0E2F799B00CF7658 /* gtest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gtest.h; sourceTree = "<group>"; };
+		404883DF0E2F799B00CF7658 /* gtest_pred_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gtest_pred_impl.h; sourceTree = "<group>"; };
+		404883E00E2F799B00CF7658 /* gtest_prod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gtest_prod.h; sourceTree = "<group>"; };
+		404883E20E2F799B00CF7658 /* gtest-death-test-internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-death-test-internal.h"; sourceTree = "<group>"; };
+		404883E30E2F799B00CF7658 /* gtest-filepath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-filepath.h"; sourceTree = "<group>"; };
+		404883E40E2F799B00CF7658 /* gtest-internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-internal.h"; sourceTree = "<group>"; };
+		404883E50E2F799B00CF7658 /* gtest-port.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-port.h"; sourceTree = "<group>"; };
+		404883E60E2F799B00CF7658 /* gtest-string.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-string.h"; sourceTree = "<group>"; };
+		404883F60E2F799B00CF7658 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = README.md; path = ../README.md; sourceTree = SOURCE_ROOT; };
+		4048840D0E2F799B00CF7658 /* gtest_main.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gtest_main.cc; sourceTree = "<group>"; };
+		404884A90E2F7CD900CF7658 /* CHANGES */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = CHANGES; path = ../CHANGES; sourceTree = SOURCE_ROOT; };
+		404884AA0E2F7CD900CF7658 /* CONTRIBUTORS */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = CONTRIBUTORS; path = ../CONTRIBUTORS; sourceTree = SOURCE_ROOT; };
+		404884AB0E2F7CD900CF7658 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = SOURCE_ROOT; };
+		40899F430FFA7184000B29AE /* gtest_unittest-framework */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "gtest_unittest-framework"; sourceTree = BUILT_PRODUCTS_DIR; };
+		40899F4D0FFA7271000B29AE /* gtest-tuple.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-tuple.h"; sourceTree = "<group>"; };
+		40899FB30FFA7567000B29AE /* StaticLibraryTarget.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = StaticLibraryTarget.xcconfig; sourceTree = "<group>"; };
+		4089A0130FFACEFC000B29AE /* sample1_unittest-framework */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "sample1_unittest-framework"; sourceTree = BUILT_PRODUCTS_DIR; };
+		4089A02C0FFACF7F000B29AE /* sample1.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sample1.cc; sourceTree = "<group>"; };
+		4089A02D0FFACF7F000B29AE /* sample1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sample1.h; sourceTree = "<group>"; };
+		4089A02E0FFACF7F000B29AE /* sample1_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sample1_unittest.cc; sourceTree = "<group>"; };
+		40C848FA101A209C0083642A /* libgtest.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libgtest.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		40C8490B101A217E0083642A /* libgtest_main.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libgtest_main.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		40C84987101A36850083642A /* gtest_unittest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = gtest_unittest; sourceTree = BUILT_PRODUCTS_DIR; };
+		40C84997101A36A60083642A /* sample1_unittest-static */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "sample1_unittest-static"; sourceTree = BUILT_PRODUCTS_DIR; };
+		40D4CDF10E30E07400294801 /* DebugProject.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = DebugProject.xcconfig; sourceTree = "<group>"; };
+		40D4CDF20E30E07400294801 /* FrameworkTarget.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = FrameworkTarget.xcconfig; sourceTree = "<group>"; };
+		40D4CDF30E30E07400294801 /* General.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = General.xcconfig; sourceTree = "<group>"; };
+		40D4CDF40E30E07400294801 /* ReleaseProject.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = ReleaseProject.xcconfig; sourceTree = "<group>"; };
+		40D4CF510E30F5E200294801 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		4539C8FF0EC27F6400A70F4C /* gtest.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = gtest.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		4539C9330EC280AE00A70F4C /* gtest-param-test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-param-test.h"; sourceTree = "<group>"; };
+		4539C9350EC280E200A70F4C /* gtest-linked_ptr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-linked_ptr.h"; sourceTree = "<group>"; };
+		4539C9360EC280E200A70F4C /* gtest-param-util-generated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-param-util-generated.h"; sourceTree = "<group>"; };
+		4539C9370EC280E200A70F4C /* gtest-param-util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-param-util.h"; sourceTree = "<group>"; };
+		4567C8171264FF71007740BE /* gtest-printers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-printers.h"; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		40899F410FFA7184000B29AE /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				40C849A4101A37150083642A /* gtest.framework in Frameworks */,
+				40C84916101A235B0083642A /* libgtest_main.a in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		4089A0110FFACEFC000B29AE /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				40C849A2101A37050083642A /* gtest.framework in Frameworks */,
+				40C84921101A23AD0083642A /* libgtest_main.a in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		40C84981101A36850083642A /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				40C84982101A36850083642A /* libgtest.a in Frameworks */,
+				40C84983101A36850083642A /* libgtest_main.a in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		40C84991101A36A60083642A /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				40C84992101A36A60083642A /* libgtest.a in Frameworks */,
+				40C84993101A36A60083642A /* libgtest_main.a in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		034768DDFF38A45A11DB9C8B /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				4539C8FF0EC27F6400A70F4C /* gtest.framework */,
+				40C848FA101A209C0083642A /* libgtest.a */,
+				40C8490B101A217E0083642A /* libgtest_main.a */,
+				40899F430FFA7184000B29AE /* gtest_unittest-framework */,
+				40C84987101A36850083642A /* gtest_unittest */,
+				4089A0130FFACEFC000B29AE /* sample1_unittest-framework */,
+				40C84997101A36A60083642A /* sample1_unittest-static */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		0867D691FE84028FC02AAC07 /* gtest */ = {
+			isa = PBXGroup;
+			children = (
+				40D4CDF00E30E07400294801 /* Config */,
+				08FB77ACFE841707C02AAC07 /* Source */,
+				40D4CF4E0E30F5E200294801 /* Resources */,
+				403EE37B0E377822004BD1E2 /* Scripts */,
+				034768DDFF38A45A11DB9C8B /* Products */,
+			);
+			name = gtest;
+			sourceTree = "<group>";
+		};
+		08FB77ACFE841707C02AAC07 /* Source */ = {
+			isa = PBXGroup;
+			children = (
+				404884A90E2F7CD900CF7658 /* CHANGES */,
+				404884AA0E2F7CD900CF7658 /* CONTRIBUTORS */,
+				404884AB0E2F7CD900CF7658 /* LICENSE */,
+				404883F60E2F799B00CF7658 /* README.md */,
+				404883D90E2F799B00CF7658 /* include */,
+				4089A02F0FFACF84000B29AE /* samples */,
+				404884070E2F799B00CF7658 /* src */,
+				3B238BF00E7FE13B00846E11 /* test */,
+			);
+			name = Source;
+			sourceTree = "<group>";
+		};
+		3B238BF00E7FE13B00846E11 /* test */ = {
+			isa = PBXGroup;
+			children = (
+				3B238C120E7FE13C00846E11 /* gtest_unittest.cc */,
+			);
+			name = test;
+			path = ../test;
+			sourceTree = SOURCE_ROOT;
+		};
+		403EE37B0E377822004BD1E2 /* Scripts */ = {
+			isa = PBXGroup;
+			children = (
+				403EE37C0E377822004BD1E2 /* versiongenerate.py */,
+				3B87D2100E96B92E000D1852 /* runtests.sh */,
+			);
+			path = Scripts;
+			sourceTree = "<group>";
+		};
+		404883D90E2F799B00CF7658 /* include */ = {
+			isa = PBXGroup;
+			children = (
+				404883DA0E2F799B00CF7658 /* gtest */,
+			);
+			name = include;
+			path = ../include;
+			sourceTree = SOURCE_ROOT;
+		};
+		404883DA0E2F799B00CF7658 /* gtest */ = {
+			isa = PBXGroup;
+			children = (
+				404883E10E2F799B00CF7658 /* internal */,
+				224A12A20E9EADCC00BD17FD /* gtest-test-part.h */,
+				404883DB0E2F799B00CF7658 /* gtest-death-test.h */,
+				404883DC0E2F799B00CF7658 /* gtest-message.h */,
+				4539C9330EC280AE00A70F4C /* gtest-param-test.h */,
+				4567C8171264FF71007740BE /* gtest-printers.h */,
+				404883DD0E2F799B00CF7658 /* gtest-spi.h */,
+				404883DE0E2F799B00CF7658 /* gtest.h */,
+				404883DF0E2F799B00CF7658 /* gtest_pred_impl.h */,
+				404883E00E2F799B00CF7658 /* gtest_prod.h */,
+				3BF6F2A40E79B616000F2EEE /* gtest-typed-test.h */,
+			);
+			path = gtest;
+			sourceTree = "<group>";
+		};
+		404883E10E2F799B00CF7658 /* internal */ = {
+			isa = PBXGroup;
+			children = (
+				404883E20E2F799B00CF7658 /* gtest-death-test-internal.h */,
+				404883E30E2F799B00CF7658 /* gtest-filepath.h */,
+				404883E40E2F799B00CF7658 /* gtest-internal.h */,
+				4539C9350EC280E200A70F4C /* gtest-linked_ptr.h */,
+				4539C9360EC280E200A70F4C /* gtest-param-util-generated.h */,
+				4539C9370EC280E200A70F4C /* gtest-param-util.h */,
+				404883E50E2F799B00CF7658 /* gtest-port.h */,
+				404883E60E2F799B00CF7658 /* gtest-string.h */,
+				40899F4D0FFA7271000B29AE /* gtest-tuple.h */,
+				3BF6F29F0E79B5AD000F2EEE /* gtest-type-util.h */,
+			);
+			path = internal;
+			sourceTree = "<group>";
+		};
+		404884070E2F799B00CF7658 /* src */ = {
+			isa = PBXGroup;
+			children = (
+				224A12A10E9EADA700BD17FD /* gtest-all.cc */,
+				4048840D0E2F799B00CF7658 /* gtest_main.cc */,
+			);
+			name = src;
+			path = ../src;
+			sourceTree = SOURCE_ROOT;
+		};
+		4089A02F0FFACF84000B29AE /* samples */ = {
+			isa = PBXGroup;
+			children = (
+				4089A02C0FFACF7F000B29AE /* sample1.cc */,
+				4089A02D0FFACF7F000B29AE /* sample1.h */,
+				4089A02E0FFACF7F000B29AE /* sample1_unittest.cc */,
+			);
+			name = samples;
+			path = ../samples;
+			sourceTree = SOURCE_ROOT;
+		};
+		40D4CDF00E30E07400294801 /* Config */ = {
+			isa = PBXGroup;
+			children = (
+				40D4CDF10E30E07400294801 /* DebugProject.xcconfig */,
+				40D4CDF20E30E07400294801 /* FrameworkTarget.xcconfig */,
+				40D4CDF30E30E07400294801 /* General.xcconfig */,
+				40D4CDF40E30E07400294801 /* ReleaseProject.xcconfig */,
+				40899FB30FFA7567000B29AE /* StaticLibraryTarget.xcconfig */,
+			);
+			path = Config;
+			sourceTree = "<group>";
+		};
+		40D4CF4E0E30F5E200294801 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				40D4CF510E30F5E200294801 /* Info.plist */,
+			);
+			path = Resources;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+		8D07F2BD0486CC7A007CD1D0 /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				404884380E2F799B00CF7658 /* gtest-death-test.h in Headers */,
+				404884390E2F799B00CF7658 /* gtest-message.h in Headers */,
+				4539C9340EC280AE00A70F4C /* gtest-param-test.h in Headers */,
+				4567C8181264FF71007740BE /* gtest-printers.h in Headers */,
+				3BF6F2A50E79B616000F2EEE /* gtest-typed-test.h in Headers */,
+				4048843A0E2F799B00CF7658 /* gtest-spi.h in Headers */,
+				4048843B0E2F799B00CF7658 /* gtest.h in Headers */,
+				4048843C0E2F799B00CF7658 /* gtest_pred_impl.h in Headers */,
+				4048843D0E2F799B00CF7658 /* gtest_prod.h in Headers */,
+				224A12A30E9EADCC00BD17FD /* gtest-test-part.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+		40899F420FFA7184000B29AE /* gtest_unittest-framework */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 40899F4A0FFA71BC000B29AE /* Build configuration list for PBXNativeTarget "gtest_unittest-framework" */;
+			buildPhases = (
+				40899F400FFA7184000B29AE /* Sources */,
+				40899F410FFA7184000B29AE /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				40C849A0101A36F10083642A /* PBXTargetDependency */,
+			);
+			name = "gtest_unittest-framework";
+			productName = gtest_unittest;
+			productReference = 40899F430FFA7184000B29AE /* gtest_unittest-framework */;
+			productType = "com.apple.product-type.tool";
+		};
+		4089A0120FFACEFC000B29AE /* sample1_unittest-framework */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 4089A0240FFACF01000B29AE /* Build configuration list for PBXNativeTarget "sample1_unittest-framework" */;
+			buildPhases = (
+				4089A0100FFACEFC000B29AE /* Sources */,
+				4089A0110FFACEFC000B29AE /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				40C8499E101A36E50083642A /* PBXTargetDependency */,
+			);
+			name = "sample1_unittest-framework";
+			productName = sample1_unittest;
+			productReference = 4089A0130FFACEFC000B29AE /* sample1_unittest-framework */;
+			productType = "com.apple.product-type.tool";
+		};
+		40C848F9101A209C0083642A /* gtest-static */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 40C84902101A212E0083642A /* Build configuration list for PBXNativeTarget "gtest-static" */;
+			buildPhases = (
+				40C848F7101A209C0083642A /* Sources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "gtest-static";
+			productName = "gtest-static";
+			productReference = 40C848FA101A209C0083642A /* libgtest.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+		40C8490A101A217E0083642A /* gtest_main-static */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 40C84912101A21D20083642A /* Build configuration list for PBXNativeTarget "gtest_main-static" */;
+			buildPhases = (
+				40C84908101A217E0083642A /* Sources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "gtest_main-static";
+			productName = "gtest_main-static";
+			productReference = 40C8490B101A217E0083642A /* libgtest_main.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+		40C8497A101A36850083642A /* gtest_unittest-static */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 40C84984101A36850083642A /* Build configuration list for PBXNativeTarget "gtest_unittest-static" */;
+			buildPhases = (
+				40C8497F101A36850083642A /* Sources */,
+				40C84981101A36850083642A /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				40C8497B101A36850083642A /* PBXTargetDependency */,
+				40C8497D101A36850083642A /* PBXTargetDependency */,
+			);
+			name = "gtest_unittest-static";
+			productName = gtest_unittest;
+			productReference = 40C84987101A36850083642A /* gtest_unittest */;
+			productType = "com.apple.product-type.tool";
+		};
+		40C84989101A36A60083642A /* sample1_unittest-static */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 40C84994101A36A60083642A /* Build configuration list for PBXNativeTarget "sample1_unittest-static" */;
+			buildPhases = (
+				40C8498E101A36A60083642A /* Sources */,
+				40C84991101A36A60083642A /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				40C8498A101A36A60083642A /* PBXTargetDependency */,
+				40C8498C101A36A60083642A /* PBXTargetDependency */,
+			);
+			name = "sample1_unittest-static";
+			productName = sample1_unittest;
+			productReference = 40C84997101A36A60083642A /* sample1_unittest-static */;
+			productType = "com.apple.product-type.tool";
+		};
+		8D07F2BC0486CC7A007CD1D0 /* gtest-framework */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 4FADC24208B4156D00ABE55E /* Build configuration list for PBXNativeTarget "gtest-framework" */;
+			buildPhases = (
+				8D07F2C10486CC7A007CD1D0 /* Sources */,
+				8D07F2BD0486CC7A007CD1D0 /* Headers */,
+				404884A50E2F7C0400CF7658 /* Copy Headers Internal */,
+				8D07F2BF0486CC7A007CD1D0 /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				40C44AE60E379922008FCC51 /* PBXTargetDependency */,
+				408BEC101046CFE900DEF522 /* PBXTargetDependency */,
+				40C8499C101A36DC0083642A /* PBXTargetDependency */,
+			);
+			name = "gtest-framework";
+			productInstallPath = "$(HOME)/Library/Frameworks";
+			productName = gtest;
+			productReference = 4539C8FF0EC27F6400A70F4C /* gtest.framework */;
+			productType = "com.apple.product-type.framework";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		0867D690FE84028FC02AAC07 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 0460;
+			};
+			buildConfigurationList = 4FADC24608B4156D00ABE55E /* Build configuration list for PBXProject "gtest" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 1;
+			knownRegions = (
+				English,
+				Japanese,
+				French,
+				German,
+				en,
+			);
+			mainGroup = 0867D691FE84028FC02AAC07 /* gtest */;
+			productRefGroup = 034768DDFF38A45A11DB9C8B /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				8D07F2BC0486CC7A007CD1D0 /* gtest-framework */,
+				40C848F9101A209C0083642A /* gtest-static */,
+				40C8490A101A217E0083642A /* gtest_main-static */,
+				40899F420FFA7184000B29AE /* gtest_unittest-framework */,
+				40C8497A101A36850083642A /* gtest_unittest-static */,
+				4089A0120FFACEFC000B29AE /* sample1_unittest-framework */,
+				40C84989101A36A60083642A /* sample1_unittest-static */,
+				3B238F5F0E828B5400846E11 /* Check */,
+				40C44ADC0E3798F4008FCC51 /* Version Info */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		8D07F2BF0486CC7A007CD1D0 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				404884500E2F799B00CF7658 /* README.md in Resources */,
+				404884AC0E2F7CD900CF7658 /* CHANGES in Resources */,
+				404884AD0E2F7CD900CF7658 /* CONTRIBUTORS in Resources */,
+				404884AE0E2F7CD900CF7658 /* LICENSE in Resources */,
+				40C84978101A36540083642A /* libgtest_main.a in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		3B238F5E0E828B5400846E11 /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "# Remember, this \"Run Script\" build phase will be executed from $SRCROOT\n/bin/bash Scripts/runtests.sh";
+		};
+		40C44ADB0E3798F4008FCC51 /* Generate Version.h */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+				"$(SRCROOT)/Scripts/versiongenerate.py",
+				"$(SRCROOT)/../configure.ac",
+			);
+			name = "Generate Version.h";
+			outputPaths = (
+				"$(PROJECT_TEMP_DIR)/Version.h",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "# Remember, this \"Run Script\" build phase will be executed from $SRCROOT\n/usr/bin/python Scripts/versiongenerate.py ../ $PROJECT_TEMP_DIR";
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		40899F400FFA7184000B29AE /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				40899F530FFA72A0000B29AE /* gtest_unittest.cc in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		4089A0100FFACEFC000B29AE /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				4089A0440FFAD1BE000B29AE /* sample1.cc in Sources */,
+				4089A0460FFAD1BE000B29AE /* sample1_unittest.cc in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		40C848F7101A209C0083642A /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				40C848FF101A21150083642A /* gtest-all.cc in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		40C84908101A217E0083642A /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				40C84915101A21DF0083642A /* gtest_main.cc in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		40C8497F101A36850083642A /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				40C84980101A36850083642A /* gtest_unittest.cc in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		40C8498E101A36A60083642A /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				40C8498F101A36A60083642A /* sample1.cc in Sources */,
+				40C84990101A36A60083642A /* sample1_unittest.cc in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		8D07F2C10486CC7A007CD1D0 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				40899F3A0FFA70D4000B29AE /* gtest-all.cc in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+		40899F9D0FFA740F000B29AE /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 40899F420FFA7184000B29AE /* gtest_unittest-framework */;
+			targetProxy = 40899F9C0FFA740F000B29AE /* PBXContainerItemProxy */;
+		};
+		4089A0980FFAD34A000B29AE /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 4089A0120FFACEFC000B29AE /* sample1_unittest-framework */;
+			targetProxy = 4089A0970FFAD34A000B29AE /* PBXContainerItemProxy */;
+		};
+		408BEC101046CFE900DEF522 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 40C848F9101A209C0083642A /* gtest-static */;
+			targetProxy = 408BEC0F1046CFE900DEF522 /* PBXContainerItemProxy */;
+		};
+		40C44AE60E379922008FCC51 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 40C44ADC0E3798F4008FCC51 /* Version Info */;
+			targetProxy = 40C44AE50E379922008FCC51 /* PBXContainerItemProxy */;
+		};
+		40C8497B101A36850083642A /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 40C848F9101A209C0083642A /* gtest-static */;
+			targetProxy = 40C8497C101A36850083642A /* PBXContainerItemProxy */;
+		};
+		40C8497D101A36850083642A /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 40C8490A101A217E0083642A /* gtest_main-static */;
+			targetProxy = 40C8497E101A36850083642A /* PBXContainerItemProxy */;
+		};
+		40C8498A101A36A60083642A /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 40C848F9101A209C0083642A /* gtest-static */;
+			targetProxy = 40C8498B101A36A60083642A /* PBXContainerItemProxy */;
+		};
+		40C8498C101A36A60083642A /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 40C8490A101A217E0083642A /* gtest_main-static */;
+			targetProxy = 40C8498D101A36A60083642A /* PBXContainerItemProxy */;
+		};
+		40C8499C101A36DC0083642A /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 40C8490A101A217E0083642A /* gtest_main-static */;
+			targetProxy = 40C8499B101A36DC0083642A /* PBXContainerItemProxy */;
+		};
+		40C8499E101A36E50083642A /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 8D07F2BC0486CC7A007CD1D0 /* gtest-framework */;
+			targetProxy = 40C8499D101A36E50083642A /* PBXContainerItemProxy */;
+		};
+		40C849A0101A36F10083642A /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 8D07F2BC0486CC7A007CD1D0 /* gtest-framework */;
+			targetProxy = 40C8499F101A36F10083642A /* PBXContainerItemProxy */;
+		};
+		40C849F7101A43440083642A /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 40C8497A101A36850083642A /* gtest_unittest-static */;
+			targetProxy = 40C849F6101A43440083642A /* PBXContainerItemProxy */;
+		};
+		40C849F9101A43490083642A /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 40C84989101A36A60083642A /* sample1_unittest-static */;
+			targetProxy = 40C849F8101A43490083642A /* PBXContainerItemProxy */;
+		};
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+		3B238F600E828B5400846E11 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COMBINE_HIDPI_IMAGES = YES;
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				PRODUCT_NAME = Check;
+				SDKROOT = macosx;
+			};
+			name = Debug;
+		};
+		3B238F610E828B5400846E11 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COMBINE_HIDPI_IMAGES = YES;
+				COPY_PHASE_STRIP = YES;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				PRODUCT_NAME = Check;
+				SDKROOT = macosx;
+				ZERO_LINK = NO;
+			};
+			name = Release;
+		};
+		40899F450FFA7185000B29AE /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				HEADER_SEARCH_PATHS = ../;
+				PRODUCT_NAME = "gtest_unittest-framework";
+				SDKROOT = macosx;
+			};
+			name = Debug;
+		};
+		40899F460FFA7185000B29AE /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				HEADER_SEARCH_PATHS = ../;
+				PRODUCT_NAME = "gtest_unittest-framework";
+				SDKROOT = macosx;
+			};
+			name = Release;
+		};
+		4089A0150FFACEFD000B29AE /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				PRODUCT_NAME = "sample1_unittest-framework";
+				SDKROOT = macosx;
+			};
+			name = Debug;
+		};
+		4089A0160FFACEFD000B29AE /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				PRODUCT_NAME = "sample1_unittest-framework";
+				SDKROOT = macosx;
+			};
+			name = Release;
+		};
+		40C44ADF0E3798F4008FCC51 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COMBINE_HIDPI_IMAGES = YES;
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				MACOSX_DEPLOYMENT_TARGET = 10.7;
+				PRODUCT_NAME = gtest;
+				SDKROOT = macosx;
+				TARGET_NAME = gtest;
+			};
+			name = Debug;
+		};
+		40C44AE00E3798F4008FCC51 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COMBINE_HIDPI_IMAGES = YES;
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				MACOSX_DEPLOYMENT_TARGET = 10.7;
+				PRODUCT_NAME = gtest;
+				SDKROOT = macosx;
+				TARGET_NAME = gtest;
+			};
+			name = Release;
+		};
+		40C848FB101A209D0083642A /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 40899FB30FFA7567000B29AE /* StaticLibraryTarget.xcconfig */;
+			buildSettings = {
+				COMBINE_HIDPI_IMAGES = YES;
+				GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
+				GCC_SYMBOLS_PRIVATE_EXTERN = YES;
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				HEADER_SEARCH_PATHS = (
+					../,
+					../include/,
+				);
+				PRODUCT_NAME = gtest;
+				SDKROOT = macosx;
+			};
+			name = Debug;
+		};
+		40C848FC101A209D0083642A /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 40899FB30FFA7567000B29AE /* StaticLibraryTarget.xcconfig */;
+			buildSettings = {
+				COMBINE_HIDPI_IMAGES = YES;
+				GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
+				GCC_SYMBOLS_PRIVATE_EXTERN = YES;
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				HEADER_SEARCH_PATHS = (
+					../,
+					../include/,
+				);
+				PRODUCT_NAME = gtest;
+				SDKROOT = macosx;
+			};
+			name = Release;
+		};
+		40C8490E101A217F0083642A /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 40899FB30FFA7567000B29AE /* StaticLibraryTarget.xcconfig */;
+			buildSettings = {
+				COMBINE_HIDPI_IMAGES = YES;
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				HEADER_SEARCH_PATHS = (
+					../,
+					../include/,
+				);
+				PRODUCT_NAME = gtest_main;
+				SDKROOT = macosx;
+			};
+			name = Debug;
+		};
+		40C8490F101A217F0083642A /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 40899FB30FFA7567000B29AE /* StaticLibraryTarget.xcconfig */;
+			buildSettings = {
+				COMBINE_HIDPI_IMAGES = YES;
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				HEADER_SEARCH_PATHS = (
+					../,
+					../include/,
+				);
+				PRODUCT_NAME = gtest_main;
+				SDKROOT = macosx;
+			};
+			name = Release;
+		};
+		40C84985101A36850083642A /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				HEADER_SEARCH_PATHS = ../;
+				PRODUCT_NAME = gtest_unittest;
+				SDKROOT = macosx;
+			};
+			name = Debug;
+		};
+		40C84986101A36850083642A /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				HEADER_SEARCH_PATHS = ../;
+				PRODUCT_NAME = gtest_unittest;
+				SDKROOT = macosx;
+			};
+			name = Release;
+		};
+		40C84995101A36A60083642A /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				PRODUCT_NAME = "sample1_unittest-static";
+				SDKROOT = macosx;
+			};
+			name = Debug;
+		};
+		40C84996101A36A60083642A /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				PRODUCT_NAME = "sample1_unittest-static";
+				SDKROOT = macosx;
+			};
+			name = Release;
+		};
+		4FADC24308B4156D00ABE55E /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 40D4CDF20E30E07400294801 /* FrameworkTarget.xcconfig */;
+			buildSettings = {
+				COMBINE_HIDPI_IMAGES = YES;
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				HEADER_SEARCH_PATHS = (
+					../,
+					../include/,
+				);
+				INFOPLIST_FILE = Resources/Info.plist;
+				INFOPLIST_PREFIX_HEADER = "$(PROJECT_TEMP_DIR)/Version.h";
+				INFOPLIST_PREPROCESS = YES;
+				PRODUCT_NAME = gtest;
+				SDKROOT = macosx;
+				VERSIONING_SYSTEM = "apple-generic";
+			};
+			name = Debug;
+		};
+		4FADC24408B4156D00ABE55E /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 40D4CDF20E30E07400294801 /* FrameworkTarget.xcconfig */;
+			buildSettings = {
+				COMBINE_HIDPI_IMAGES = YES;
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				HEADER_SEARCH_PATHS = (
+					../,
+					../include/,
+				);
+				INFOPLIST_FILE = Resources/Info.plist;
+				INFOPLIST_PREFIX_HEADER = "$(PROJECT_TEMP_DIR)/Version.h";
+				INFOPLIST_PREPROCESS = YES;
+				PRODUCT_NAME = gtest;
+				SDKROOT = macosx;
+				VERSIONING_SYSTEM = "apple-generic";
+			};
+			name = Release;
+		};
+		4FADC24708B4156D00ABE55E /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 40D4CDF10E30E07400294801 /* DebugProject.xcconfig */;
+			buildSettings = {
+			};
+			name = Debug;
+		};
+		4FADC24808B4156D00ABE55E /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 40D4CDF40E30E07400294801 /* ReleaseProject.xcconfig */;
+			buildSettings = {
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		3B238FA30E828BB600846E11 /* Build configuration list for PBXAggregateTarget "Check" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				3B238F600E828B5400846E11 /* Debug */,
+				3B238F610E828B5400846E11 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		40899F4A0FFA71BC000B29AE /* Build configuration list for PBXNativeTarget "gtest_unittest-framework" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				40899F450FFA7185000B29AE /* Debug */,
+				40899F460FFA7185000B29AE /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		4089A0240FFACF01000B29AE /* Build configuration list for PBXNativeTarget "sample1_unittest-framework" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				4089A0150FFACEFD000B29AE /* Debug */,
+				4089A0160FFACEFD000B29AE /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		40C44AE40E379905008FCC51 /* Build configuration list for PBXAggregateTarget "Version Info" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				40C44ADF0E3798F4008FCC51 /* Debug */,
+				40C44AE00E3798F4008FCC51 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		40C84902101A212E0083642A /* Build configuration list for PBXNativeTarget "gtest-static" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				40C848FB101A209D0083642A /* Debug */,
+				40C848FC101A209D0083642A /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		40C84912101A21D20083642A /* Build configuration list for PBXNativeTarget "gtest_main-static" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				40C8490E101A217F0083642A /* Debug */,
+				40C8490F101A217F0083642A /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		40C84984101A36850083642A /* Build configuration list for PBXNativeTarget "gtest_unittest-static" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				40C84985101A36850083642A /* Debug */,
+				40C84986101A36850083642A /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		40C84994101A36A60083642A /* Build configuration list for PBXNativeTarget "sample1_unittest-static" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				40C84995101A36A60083642A /* Debug */,
+				40C84996101A36A60083642A /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		4FADC24208B4156D00ABE55E /* Build configuration list for PBXNativeTarget "gtest-framework" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				4FADC24308B4156D00ABE55E /* Debug */,
+				4FADC24408B4156D00ABE55E /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		4FADC24608B4156D00ABE55E /* Build configuration list for PBXProject "gtest" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				4FADC24708B4156D00ABE55E /* Debug */,
+				4FADC24808B4156D00ABE55E /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 0867D690FE84028FC02AAC07 /* Project object */;
+}
diff --git a/third_party/googletest/travis.sh b/third_party/googletest/travis.sh
new file mode 100755
index 0000000..6d381e9
--- /dev/null
+++ b/third_party/googletest/travis.sh
@@ -0,0 +1,14 @@
+#!/usr/bin/env sh
+set -evx
+env | sort
+
+mkdir build || true
+mkdir build/$GTEST_TARGET || true
+cd build/$GTEST_TARGET
+cmake -Dgtest_build_samples=ON \
+      -Dgmock_build_samples=ON \
+      -Dgtest_build_tests=ON \
+      -Dgmock_build_tests=ON \
+      ../../$GTEST_TARGET
+make
+make test
diff --git a/third_party/libevent/.gitignore b/third_party/libevent/.gitignore
new file mode 100644
index 0000000..622ab17
--- /dev/null
+++ b/third_party/libevent/.gitignore
@@ -0,0 +1,98 @@
+### These files should get ignored no matter where they appear.
+
+# Editors leave these lying around
+\#*\#
+.#*
+*~
+*.swp
+
+# C stuff
+*.o
+
+# Windows stuff
+*.obj
+*.exe
+*.lib
+
+# Patch leaves these lying arround
+*.orig
+*.rej
+
+# gcov stuff
+*.gcno
+*.gcov
+*.gcda
+
+# Autotools stuff
+.deps
+Makefile
+Makefile.in
+
+# Libtool stuff
+.libs
+*.lo
+*.la
+
+# ctags stuff
+TAGS
+
+# Stuff made by our makefiles
+libevent.pc
+libevent_pthreads.pc
+libevent_openssl.pc
+*.log
+*.trs
+
+## The initial / makes these files only get ignored in particular directories.
+/autom4te.cache
+
+# Libtool adds these, at least sometimes
+/m4/libtool.m4
+/m4/ltoptions.m4
+/m4/ltsugar.m4
+/m4/ltversion.m4
+/m4/lt~obsolete.m4
+
+/aclocal.m4
+/compile
+/doxygen
+/config.guess
+/config.log
+/config.status
+/config.sub
+/configure
+/depcomp
+/config.h
+/config.h.in
+/install-sh
+/libtool
+/ltmain.sh
+/missing
+/stamp-h1
+
+/include/event2/event-config.h
+
+/sample/dns-example
+/sample/event-test
+/sample/hello-world
+/sample/http-server
+/sample/le-proxy
+/sample/signal-test
+/sample/time-test
+
+/test/bench
+/test/bench_cascade
+/test/bench_http
+/test/bench_httpclient
+/test/regress
+/test/regress.gen.c
+/test/regress.gen.h
+/test/rpcgen-attempted
+/test/test-eof
+/test/test-init
+/test/test-ratelim
+/test/test-script.sh
+/test/test-time
+/test/test-weof
+/test/test-changelist
+
diff --git a/ChangeLog b/third_party/libevent/ChangeLog
similarity index 100%
rename from ChangeLog
rename to third_party/libevent/ChangeLog
diff --git a/Doxyfile b/third_party/libevent/Doxyfile
similarity index 100%
rename from Doxyfile
rename to third_party/libevent/Doxyfile
diff --git a/LICENSE b/third_party/libevent/LICENSE
similarity index 100%
rename from LICENSE
rename to third_party/libevent/LICENSE
diff --git a/Makefile.am b/third_party/libevent/Makefile.am
similarity index 100%
rename from Makefile.am
rename to third_party/libevent/Makefile.am
diff --git a/Makefile.nmake b/third_party/libevent/Makefile.nmake
similarity index 100%
rename from Makefile.nmake
rename to third_party/libevent/Makefile.nmake
diff --git a/README b/third_party/libevent/README
similarity index 100%
rename from README
rename to third_party/libevent/README
diff --git a/WIN32-Code/event2/event-config.h b/third_party/libevent/WIN32-Code/event2/event-config.h
similarity index 100%
rename from WIN32-Code/event2/event-config.h
rename to third_party/libevent/WIN32-Code/event2/event-config.h
diff --git a/WIN32-Code/tree.h b/third_party/libevent/WIN32-Code/tree.h
similarity index 100%
rename from WIN32-Code/tree.h
rename to third_party/libevent/WIN32-Code/tree.h
diff --git a/arc4random.c b/third_party/libevent/arc4random.c
similarity index 100%
rename from arc4random.c
rename to third_party/libevent/arc4random.c
diff --git a/autogen.sh b/third_party/libevent/autogen.sh
similarity index 100%
rename from autogen.sh
rename to third_party/libevent/autogen.sh
diff --git a/buffer.c b/third_party/libevent/buffer.c
similarity index 100%
rename from buffer.c
rename to third_party/libevent/buffer.c
diff --git a/buffer_iocp.c b/third_party/libevent/buffer_iocp.c
similarity index 100%
rename from buffer_iocp.c
rename to third_party/libevent/buffer_iocp.c
diff --git a/bufferevent-internal.h b/third_party/libevent/bufferevent-internal.h
similarity index 100%
rename from bufferevent-internal.h
rename to third_party/libevent/bufferevent-internal.h
diff --git a/bufferevent.c b/third_party/libevent/bufferevent.c
similarity index 100%
rename from bufferevent.c
rename to third_party/libevent/bufferevent.c
diff --git a/bufferevent_async.c b/third_party/libevent/bufferevent_async.c
similarity index 100%
rename from bufferevent_async.c
rename to third_party/libevent/bufferevent_async.c
diff --git a/bufferevent_filter.c b/third_party/libevent/bufferevent_filter.c
similarity index 100%
rename from bufferevent_filter.c
rename to third_party/libevent/bufferevent_filter.c
diff --git a/bufferevent_openssl.c b/third_party/libevent/bufferevent_openssl.c
similarity index 100%
rename from bufferevent_openssl.c
rename to third_party/libevent/bufferevent_openssl.c
diff --git a/bufferevent_pair.c b/third_party/libevent/bufferevent_pair.c
similarity index 100%
rename from bufferevent_pair.c
rename to third_party/libevent/bufferevent_pair.c
diff --git a/bufferevent_ratelim.c b/third_party/libevent/bufferevent_ratelim.c
similarity index 100%
rename from bufferevent_ratelim.c
rename to third_party/libevent/bufferevent_ratelim.c
diff --git a/bufferevent_sock.c b/third_party/libevent/bufferevent_sock.c
similarity index 100%
rename from bufferevent_sock.c
rename to third_party/libevent/bufferevent_sock.c
diff --git a/changelist-internal.h b/third_party/libevent/changelist-internal.h
similarity index 100%
rename from changelist-internal.h
rename to third_party/libevent/changelist-internal.h
diff --git a/compat/sys/queue.h b/third_party/libevent/compat/sys/queue.h
similarity index 100%
rename from compat/sys/queue.h
rename to third_party/libevent/compat/sys/queue.h
diff --git a/configure.ac b/third_party/libevent/configure.ac
similarity index 100%
rename from configure.ac
rename to third_party/libevent/configure.ac
diff --git a/defer-internal.h b/third_party/libevent/defer-internal.h
similarity index 100%
rename from defer-internal.h
rename to third_party/libevent/defer-internal.h
diff --git a/devpoll.c b/third_party/libevent/devpoll.c
similarity index 100%
rename from devpoll.c
rename to third_party/libevent/devpoll.c
diff --git a/epoll.c b/third_party/libevent/epoll.c
similarity index 100%
rename from epoll.c
rename to third_party/libevent/epoll.c
diff --git a/epoll_sub.c b/third_party/libevent/epoll_sub.c
similarity index 100%
rename from epoll_sub.c
rename to third_party/libevent/epoll_sub.c
diff --git a/evbuffer-internal.h b/third_party/libevent/evbuffer-internal.h
similarity index 100%
rename from evbuffer-internal.h
rename to third_party/libevent/evbuffer-internal.h
diff --git a/evdns.3 b/third_party/libevent/evdns.3
similarity index 100%
rename from evdns.3
rename to third_party/libevent/evdns.3
diff --git a/evdns.c b/third_party/libevent/evdns.c
similarity index 100%
rename from evdns.c
rename to third_party/libevent/evdns.c
diff --git a/evdns.h b/third_party/libevent/evdns.h
similarity index 100%
rename from evdns.h
rename to third_party/libevent/evdns.h
diff --git a/event-internal.h b/third_party/libevent/event-internal.h
similarity index 100%
rename from event-internal.h
rename to third_party/libevent/event-internal.h
diff --git a/event.3 b/third_party/libevent/event.3
similarity index 100%
rename from event.3
rename to third_party/libevent/event.3
diff --git a/event.c b/third_party/libevent/event.c
similarity index 100%
rename from event.c
rename to third_party/libevent/event.c
diff --git a/event.h b/third_party/libevent/event.h
similarity index 100%
rename from event.h
rename to third_party/libevent/event.h
diff --git a/event_iocp.c b/third_party/libevent/event_iocp.c
similarity index 100%
rename from event_iocp.c
rename to third_party/libevent/event_iocp.c
diff --git a/event_rpcgen.py b/third_party/libevent/event_rpcgen.py
similarity index 100%
rename from event_rpcgen.py
rename to third_party/libevent/event_rpcgen.py
diff --git a/event_tagging.c b/third_party/libevent/event_tagging.c
similarity index 100%
rename from event_tagging.c
rename to third_party/libevent/event_tagging.c
diff --git a/evhttp.h b/third_party/libevent/evhttp.h
similarity index 100%
rename from evhttp.h
rename to third_party/libevent/evhttp.h
diff --git a/evmap-internal.h b/third_party/libevent/evmap-internal.h
similarity index 100%
rename from evmap-internal.h
rename to third_party/libevent/evmap-internal.h
diff --git a/evmap.c b/third_party/libevent/evmap.c
similarity index 100%
rename from evmap.c
rename to third_party/libevent/evmap.c
diff --git a/evport.c b/third_party/libevent/evport.c
similarity index 100%
rename from evport.c
rename to third_party/libevent/evport.c
diff --git a/evrpc-internal.h b/third_party/libevent/evrpc-internal.h
similarity index 100%
rename from evrpc-internal.h
rename to third_party/libevent/evrpc-internal.h
diff --git a/evrpc.c b/third_party/libevent/evrpc.c
similarity index 100%
rename from evrpc.c
rename to third_party/libevent/evrpc.c
diff --git a/evrpc.h b/third_party/libevent/evrpc.h
similarity index 100%
rename from evrpc.h
rename to third_party/libevent/evrpc.h
diff --git a/evsignal-internal.h b/third_party/libevent/evsignal-internal.h
similarity index 100%
rename from evsignal-internal.h
rename to third_party/libevent/evsignal-internal.h
diff --git a/evthread-internal.h b/third_party/libevent/evthread-internal.h
similarity index 100%
rename from evthread-internal.h
rename to third_party/libevent/evthread-internal.h
diff --git a/evthread.c b/third_party/libevent/evthread.c
similarity index 100%
rename from evthread.c
rename to third_party/libevent/evthread.c
diff --git a/evthread_pthread.c b/third_party/libevent/evthread_pthread.c
similarity index 100%
rename from evthread_pthread.c
rename to third_party/libevent/evthread_pthread.c
diff --git a/evthread_win32.c b/third_party/libevent/evthread_win32.c
similarity index 100%
rename from evthread_win32.c
rename to third_party/libevent/evthread_win32.c
diff --git a/evutil.c b/third_party/libevent/evutil.c
similarity index 100%
rename from evutil.c
rename to third_party/libevent/evutil.c
diff --git a/evutil.h b/third_party/libevent/evutil.h
similarity index 100%
rename from evutil.h
rename to third_party/libevent/evutil.h
diff --git a/evutil_rand.c b/third_party/libevent/evutil_rand.c
similarity index 100%
rename from evutil_rand.c
rename to third_party/libevent/evutil_rand.c
diff --git a/ht-internal.h b/third_party/libevent/ht-internal.h
similarity index 100%
rename from ht-internal.h
rename to third_party/libevent/ht-internal.h
diff --git a/http-internal.h b/third_party/libevent/http-internal.h
similarity index 100%
rename from http-internal.h
rename to third_party/libevent/http-internal.h
diff --git a/http.c b/third_party/libevent/http.c
similarity index 100%
rename from http.c
rename to third_party/libevent/http.c
diff --git a/include/Makefile.am b/third_party/libevent/include/Makefile.am
similarity index 100%
rename from include/Makefile.am
rename to third_party/libevent/include/Makefile.am
diff --git a/include/event2/buffer.h b/third_party/libevent/include/event2/buffer.h
similarity index 100%
rename from include/event2/buffer.h
rename to third_party/libevent/include/event2/buffer.h
diff --git a/include/event2/buffer_compat.h b/third_party/libevent/include/event2/buffer_compat.h
similarity index 100%
rename from include/event2/buffer_compat.h
rename to third_party/libevent/include/event2/buffer_compat.h
diff --git a/include/event2/bufferevent.h b/third_party/libevent/include/event2/bufferevent.h
similarity index 100%
rename from include/event2/bufferevent.h
rename to third_party/libevent/include/event2/bufferevent.h
diff --git a/include/event2/bufferevent_compat.h b/third_party/libevent/include/event2/bufferevent_compat.h
similarity index 100%
rename from include/event2/bufferevent_compat.h
rename to third_party/libevent/include/event2/bufferevent_compat.h
diff --git a/include/event2/bufferevent_ssl.h b/third_party/libevent/include/event2/bufferevent_ssl.h
similarity index 100%
rename from include/event2/bufferevent_ssl.h
rename to third_party/libevent/include/event2/bufferevent_ssl.h
diff --git a/include/event2/bufferevent_struct.h b/third_party/libevent/include/event2/bufferevent_struct.h
similarity index 100%
rename from include/event2/bufferevent_struct.h
rename to third_party/libevent/include/event2/bufferevent_struct.h
diff --git a/include/event2/dns.h b/third_party/libevent/include/event2/dns.h
similarity index 100%
rename from include/event2/dns.h
rename to third_party/libevent/include/event2/dns.h
diff --git a/include/event2/dns_compat.h b/third_party/libevent/include/event2/dns_compat.h
similarity index 100%
rename from include/event2/dns_compat.h
rename to third_party/libevent/include/event2/dns_compat.h
diff --git a/include/event2/dns_struct.h b/third_party/libevent/include/event2/dns_struct.h
similarity index 100%
rename from include/event2/dns_struct.h
rename to third_party/libevent/include/event2/dns_struct.h
diff --git a/include/event2/event.h b/third_party/libevent/include/event2/event.h
similarity index 100%
rename from include/event2/event.h
rename to third_party/libevent/include/event2/event.h
diff --git a/include/event2/event_compat.h b/third_party/libevent/include/event2/event_compat.h
similarity index 100%
rename from include/event2/event_compat.h
rename to third_party/libevent/include/event2/event_compat.h
diff --git a/include/event2/event_struct.h b/third_party/libevent/include/event2/event_struct.h
similarity index 100%
rename from include/event2/event_struct.h
rename to third_party/libevent/include/event2/event_struct.h
diff --git a/include/event2/http.h b/third_party/libevent/include/event2/http.h
similarity index 100%
rename from include/event2/http.h
rename to third_party/libevent/include/event2/http.h
diff --git a/include/event2/http_compat.h b/third_party/libevent/include/event2/http_compat.h
similarity index 100%
rename from include/event2/http_compat.h
rename to third_party/libevent/include/event2/http_compat.h
diff --git a/include/event2/http_struct.h b/third_party/libevent/include/event2/http_struct.h
similarity index 100%
rename from include/event2/http_struct.h
rename to third_party/libevent/include/event2/http_struct.h
diff --git a/include/event2/keyvalq_struct.h b/third_party/libevent/include/event2/keyvalq_struct.h
similarity index 100%
rename from include/event2/keyvalq_struct.h
rename to third_party/libevent/include/event2/keyvalq_struct.h
diff --git a/include/event2/listener.h b/third_party/libevent/include/event2/listener.h
similarity index 100%
rename from include/event2/listener.h
rename to third_party/libevent/include/event2/listener.h
diff --git a/include/event2/rpc.h b/third_party/libevent/include/event2/rpc.h
similarity index 100%
rename from include/event2/rpc.h
rename to third_party/libevent/include/event2/rpc.h
diff --git a/include/event2/rpc_compat.h b/third_party/libevent/include/event2/rpc_compat.h
similarity index 100%
rename from include/event2/rpc_compat.h
rename to third_party/libevent/include/event2/rpc_compat.h
diff --git a/include/event2/rpc_struct.h b/third_party/libevent/include/event2/rpc_struct.h
similarity index 100%
rename from include/event2/rpc_struct.h
rename to third_party/libevent/include/event2/rpc_struct.h
diff --git a/include/event2/tag.h b/third_party/libevent/include/event2/tag.h
similarity index 100%
rename from include/event2/tag.h
rename to third_party/libevent/include/event2/tag.h
diff --git a/include/event2/tag_compat.h b/third_party/libevent/include/event2/tag_compat.h
similarity index 100%
rename from include/event2/tag_compat.h
rename to third_party/libevent/include/event2/tag_compat.h
diff --git a/include/event2/thread.h b/third_party/libevent/include/event2/thread.h
similarity index 100%
rename from include/event2/thread.h
rename to third_party/libevent/include/event2/thread.h
diff --git a/include/event2/util.h b/third_party/libevent/include/event2/util.h
similarity index 100%
rename from include/event2/util.h
rename to third_party/libevent/include/event2/util.h
diff --git a/iocp-internal.h b/third_party/libevent/iocp-internal.h
similarity index 100%
rename from iocp-internal.h
rename to third_party/libevent/iocp-internal.h
diff --git a/ipv6-internal.h b/third_party/libevent/ipv6-internal.h
similarity index 100%
rename from ipv6-internal.h
rename to third_party/libevent/ipv6-internal.h
diff --git a/kqueue.c b/third_party/libevent/kqueue.c
similarity index 100%
rename from kqueue.c
rename to third_party/libevent/kqueue.c
diff --git a/libevent.pc.in b/third_party/libevent/libevent.pc.in
similarity index 100%
rename from libevent.pc.in
rename to third_party/libevent/libevent.pc.in
diff --git a/libevent_openssl.pc.in b/third_party/libevent/libevent_openssl.pc.in
similarity index 100%
rename from libevent_openssl.pc.in
rename to third_party/libevent/libevent_openssl.pc.in
diff --git a/libevent_pthreads.pc.in b/third_party/libevent/libevent_pthreads.pc.in
similarity index 100%
rename from libevent_pthreads.pc.in
rename to third_party/libevent/libevent_pthreads.pc.in
diff --git a/listener.c b/third_party/libevent/listener.c
similarity index 100%
rename from listener.c
rename to third_party/libevent/listener.c
diff --git a/log-internal.h b/third_party/libevent/log-internal.h
similarity index 100%
rename from log-internal.h
rename to third_party/libevent/log-internal.h
diff --git a/log.c b/third_party/libevent/log.c
similarity index 100%
rename from log.c
rename to third_party/libevent/log.c
diff --git a/m4/ac_backport_259_ssizet.m4 b/third_party/libevent/m4/ac_backport_259_ssizet.m4
similarity index 100%
rename from m4/ac_backport_259_ssizet.m4
rename to third_party/libevent/m4/ac_backport_259_ssizet.m4
diff --git a/m4/acx_pthread.m4 b/third_party/libevent/m4/acx_pthread.m4
similarity index 100%
rename from m4/acx_pthread.m4
rename to third_party/libevent/m4/acx_pthread.m4
diff --git a/make-event-config.sed b/third_party/libevent/make-event-config.sed
similarity index 100%
rename from make-event-config.sed
rename to third_party/libevent/make-event-config.sed
diff --git a/minheap-internal.h b/third_party/libevent/minheap-internal.h
similarity index 100%
rename from minheap-internal.h
rename to third_party/libevent/minheap-internal.h
diff --git a/mm-internal.h b/third_party/libevent/mm-internal.h
similarity index 100%
rename from mm-internal.h
rename to third_party/libevent/mm-internal.h
diff --git a/poll.c b/third_party/libevent/poll.c
similarity index 100%
rename from poll.c
rename to third_party/libevent/poll.c
diff --git a/ratelim-internal.h b/third_party/libevent/ratelim-internal.h
similarity index 100%
rename from ratelim-internal.h
rename to third_party/libevent/ratelim-internal.h
diff --git a/sample/Makefile.am b/third_party/libevent/sample/Makefile.am
similarity index 100%
rename from sample/Makefile.am
rename to third_party/libevent/sample/Makefile.am
diff --git a/sample/dns-example.c b/third_party/libevent/sample/dns-example.c
similarity index 100%
rename from sample/dns-example.c
rename to third_party/libevent/sample/dns-example.c
diff --git a/sample/event-test.c b/third_party/libevent/sample/event-test.c
similarity index 100%
rename from sample/event-test.c
rename to third_party/libevent/sample/event-test.c
diff --git a/sample/hello-world.c b/third_party/libevent/sample/hello-world.c
similarity index 100%
rename from sample/hello-world.c
rename to third_party/libevent/sample/hello-world.c
diff --git a/sample/http-server.c b/third_party/libevent/sample/http-server.c
similarity index 100%
rename from sample/http-server.c
rename to third_party/libevent/sample/http-server.c
diff --git a/sample/le-proxy.c b/third_party/libevent/sample/le-proxy.c
similarity index 100%
rename from sample/le-proxy.c
rename to third_party/libevent/sample/le-proxy.c
diff --git a/sample/signal-test.c b/third_party/libevent/sample/signal-test.c
similarity index 100%
rename from sample/signal-test.c
rename to third_party/libevent/sample/signal-test.c
diff --git a/sample/time-test.c b/third_party/libevent/sample/time-test.c
similarity index 100%
rename from sample/time-test.c
rename to third_party/libevent/sample/time-test.c
diff --git a/select.c b/third_party/libevent/select.c
similarity index 100%
rename from select.c
rename to third_party/libevent/select.c
diff --git a/signal.c b/third_party/libevent/signal.c
similarity index 100%
rename from signal.c
rename to third_party/libevent/signal.c
diff --git a/strlcpy-internal.h b/third_party/libevent/strlcpy-internal.h
similarity index 100%
rename from strlcpy-internal.h
rename to third_party/libevent/strlcpy-internal.h
diff --git a/strlcpy.c b/third_party/libevent/strlcpy.c
similarity index 100%
rename from strlcpy.c
rename to third_party/libevent/strlcpy.c
diff --git a/test/Makefile.am b/third_party/libevent/test/Makefile.am
similarity index 100%
rename from test/Makefile.am
rename to third_party/libevent/test/Makefile.am
diff --git a/test/Makefile.nmake b/third_party/libevent/test/Makefile.nmake
similarity index 100%
rename from test/Makefile.nmake
rename to third_party/libevent/test/Makefile.nmake
diff --git a/test/bench.c b/third_party/libevent/test/bench.c
similarity index 100%
rename from test/bench.c
rename to third_party/libevent/test/bench.c
diff --git a/test/bench_cascade.c b/third_party/libevent/test/bench_cascade.c
similarity index 100%
rename from test/bench_cascade.c
rename to third_party/libevent/test/bench_cascade.c
diff --git a/test/bench_http.c b/third_party/libevent/test/bench_http.c
similarity index 100%
rename from test/bench_http.c
rename to third_party/libevent/test/bench_http.c
diff --git a/test/bench_httpclient.c b/third_party/libevent/test/bench_httpclient.c
similarity index 100%
rename from test/bench_httpclient.c
rename to third_party/libevent/test/bench_httpclient.c
diff --git a/test/regress.c b/third_party/libevent/test/regress.c
similarity index 100%
rename from test/regress.c
rename to third_party/libevent/test/regress.c
diff --git a/test/regress.h b/third_party/libevent/test/regress.h
similarity index 100%
rename from test/regress.h
rename to third_party/libevent/test/regress.h
diff --git a/test/regress.rpc b/third_party/libevent/test/regress.rpc
similarity index 100%
rename from test/regress.rpc
rename to third_party/libevent/test/regress.rpc
diff --git a/test/regress_buffer.c b/third_party/libevent/test/regress_buffer.c
similarity index 100%
rename from test/regress_buffer.c
rename to third_party/libevent/test/regress_buffer.c
diff --git a/test/regress_bufferevent.c b/third_party/libevent/test/regress_bufferevent.c
similarity index 100%
rename from test/regress_bufferevent.c
rename to third_party/libevent/test/regress_bufferevent.c
diff --git a/test/regress_dns.c b/third_party/libevent/test/regress_dns.c
similarity index 100%
rename from test/regress_dns.c
rename to third_party/libevent/test/regress_dns.c
diff --git a/test/regress_et.c b/third_party/libevent/test/regress_et.c
similarity index 100%
rename from test/regress_et.c
rename to third_party/libevent/test/regress_et.c
diff --git a/test/regress_http.c b/third_party/libevent/test/regress_http.c
similarity index 100%
rename from test/regress_http.c
rename to third_party/libevent/test/regress_http.c
diff --git a/test/regress_iocp.c b/third_party/libevent/test/regress_iocp.c
similarity index 100%
rename from test/regress_iocp.c
rename to third_party/libevent/test/regress_iocp.c
diff --git a/test/regress_listener.c b/third_party/libevent/test/regress_listener.c
similarity index 100%
rename from test/regress_listener.c
rename to third_party/libevent/test/regress_listener.c
diff --git a/test/regress_main.c b/third_party/libevent/test/regress_main.c
similarity index 100%
rename from test/regress_main.c
rename to third_party/libevent/test/regress_main.c
diff --git a/test/regress_minheap.c b/third_party/libevent/test/regress_minheap.c
similarity index 100%
rename from test/regress_minheap.c
rename to third_party/libevent/test/regress_minheap.c
diff --git a/test/regress_rpc.c b/third_party/libevent/test/regress_rpc.c
similarity index 100%
rename from test/regress_rpc.c
rename to third_party/libevent/test/regress_rpc.c
diff --git a/test/regress_ssl.c b/third_party/libevent/test/regress_ssl.c
similarity index 100%
rename from test/regress_ssl.c
rename to third_party/libevent/test/regress_ssl.c
diff --git a/test/regress_testutils.c b/third_party/libevent/test/regress_testutils.c
similarity index 100%
rename from test/regress_testutils.c
rename to third_party/libevent/test/regress_testutils.c
diff --git a/test/regress_testutils.h b/third_party/libevent/test/regress_testutils.h
similarity index 100%
rename from test/regress_testutils.h
rename to third_party/libevent/test/regress_testutils.h
diff --git a/test/regress_thread.c b/third_party/libevent/test/regress_thread.c
similarity index 100%
rename from test/regress_thread.c
rename to third_party/libevent/test/regress_thread.c
diff --git a/test/regress_util.c b/third_party/libevent/test/regress_util.c
similarity index 100%
rename from test/regress_util.c
rename to third_party/libevent/test/regress_util.c
diff --git a/test/regress_zlib.c b/third_party/libevent/test/regress_zlib.c
similarity index 100%
rename from test/regress_zlib.c
rename to third_party/libevent/test/regress_zlib.c
diff --git a/test/rpcgen_wrapper.sh b/third_party/libevent/test/rpcgen_wrapper.sh
similarity index 100%
rename from test/rpcgen_wrapper.sh
rename to third_party/libevent/test/rpcgen_wrapper.sh
diff --git a/test/test-changelist.c b/third_party/libevent/test/test-changelist.c
similarity index 100%
rename from test/test-changelist.c
rename to third_party/libevent/test/test-changelist.c
diff --git a/test/test-eof.c b/third_party/libevent/test/test-eof.c
similarity index 100%
rename from test/test-eof.c
rename to third_party/libevent/test/test-eof.c
diff --git a/test/test-init.c b/third_party/libevent/test/test-init.c
similarity index 100%
rename from test/test-init.c
rename to third_party/libevent/test/test-init.c
diff --git a/test/test-ratelim.c b/third_party/libevent/test/test-ratelim.c
similarity index 100%
rename from test/test-ratelim.c
rename to third_party/libevent/test/test-ratelim.c
diff --git a/test/test-ratelim.sh b/third_party/libevent/test/test-ratelim.sh
similarity index 100%
rename from test/test-ratelim.sh
rename to third_party/libevent/test/test-ratelim.sh
diff --git a/test/test-time.c b/third_party/libevent/test/test-time.c
similarity index 100%
rename from test/test-time.c
rename to third_party/libevent/test/test-time.c
diff --git a/test/test-weof.c b/third_party/libevent/test/test-weof.c
similarity index 100%
rename from test/test-weof.c
rename to third_party/libevent/test/test-weof.c
diff --git a/test/test.sh b/third_party/libevent/test/test.sh
similarity index 100%
rename from test/test.sh
rename to third_party/libevent/test/test.sh
diff --git a/test/tinytest.c b/third_party/libevent/test/tinytest.c
similarity index 100%
rename from test/tinytest.c
rename to third_party/libevent/test/tinytest.c
diff --git a/test/tinytest.h b/third_party/libevent/test/tinytest.h
similarity index 100%
rename from test/tinytest.h
rename to third_party/libevent/test/tinytest.h
diff --git a/test/tinytest_demo.c b/third_party/libevent/test/tinytest_demo.c
similarity index 100%
rename from test/tinytest_demo.c
rename to third_party/libevent/test/tinytest_demo.c
diff --git a/test/tinytest_local.h b/third_party/libevent/test/tinytest_local.h
similarity index 100%
rename from test/tinytest_local.h
rename to third_party/libevent/test/tinytest_local.h
diff --git a/test/tinytest_macros.h b/third_party/libevent/test/tinytest_macros.h
similarity index 100%
rename from test/tinytest_macros.h
rename to third_party/libevent/test/tinytest_macros.h
diff --git a/util-internal.h b/third_party/libevent/util-internal.h
similarity index 100%
rename from util-internal.h
rename to third_party/libevent/util-internal.h
diff --git a/whatsnew-2.0.txt b/third_party/libevent/whatsnew-2.0.txt
similarity index 100%
rename from whatsnew-2.0.txt
rename to third_party/libevent/whatsnew-2.0.txt
diff --git a/win32select.c b/third_party/libevent/win32select.c
similarity index 100%
rename from win32select.c
rename to third_party/libevent/win32select.c
diff --git a/third_party/seasocks/.cproject b/third_party/seasocks/.cproject
new file mode 100644
index 0000000..bb30704
--- /dev/null
+++ b/third_party/seasocks/.cproject
@@ -0,0 +1,227 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?>
+
+<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+	<storageModule moduleId="org.eclipse.cdt.core.settings">
+		<cconfiguration id="cdt.managedbuild.toolchain.gnu.base.903226628">
+			<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.base.903226628" moduleId="org.eclipse.cdt.core.settings" name="Default">
+				<externalSettings/>
+				<extensions>
+					<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+					<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+				</extensions>
+			</storageModule>
+			<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+				<configuration buildProperties="" description="" id="cdt.managedbuild.toolchain.gnu.base.903226628" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
+					<folderInfo id="cdt.managedbuild.toolchain.gnu.base.903226628.1687962773" name="/" resourcePath="">
+						<toolChain id="cdt.managedbuild.toolchain.gnu.base.1591639875" name="cdt.managedbuild.toolchain.gnu.base" resourceTypeBasedDiscovery="false" superClass="cdt.managedbuild.toolchain.gnu.base">
+							<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.target.gnu.platform.base.352152422" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/>
+							<builder id="cdt.managedbuild.target.gnu.builder.base.1124847220" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.archiver.base.367185803" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.1562953463" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base">
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.397287263" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.2039402166" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base">
+								<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.9141713" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.linker.base.795265278" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.622001646" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base">
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1346167953" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+									<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+									<additionalInput kind="additionalinput" paths="$(LIBS)"/>
+								</inputType>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.assembler.base.1822764252" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base">
+								<inputType id="cdt.managedbuild.tool.gnu.assembler.input.370515455" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+							</tool>
+						</toolChain>
+					</folderInfo>
+				</configuration>
+			</storageModule>
+			<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+			<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
+			<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
+		</cconfiguration>
+	</storageModule>
+	<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+		<project id="seasocks.null.1756460269" name="seasocks"/>
+	</storageModule>
+	<storageModule moduleId="refreshScope"/>
+	<storageModule moduleId="scannerConfiguration">
+		<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"/>
+		<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+			<buildOutputProvider>
+				<openAction enabled="true" filePath=""/>
+				<parser enabled="true"/>
+			</buildOutputProvider>
+			<scannerInfoProvider id="specsFile">
+				<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+				<parser enabled="true"/>
+			</scannerInfoProvider>
+		</profile>
+		<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+			<buildOutputProvider>
+				<openAction enabled="true" filePath=""/>
+				<parser enabled="true"/>
+			</buildOutputProvider>
+			<scannerInfoProvider id="makefileGenerator">
+				<runAction arguments="-f ${project_name}_scd.mk" command="make" useDefault="true"/>
+				<parser enabled="true"/>
+			</scannerInfoProvider>
+		</profile>
+		<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+			<buildOutputProvider>
+				<openAction enabled="true" filePath=""/>
+				<parser enabled="true"/>
+			</buildOutputProvider>
+			<scannerInfoProvider id="specsFile">
+				<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+				<parser enabled="true"/>
+			</scannerInfoProvider>
+		</profile>
+		<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+			<buildOutputProvider>
+				<openAction enabled="true" filePath=""/>
+				<parser enabled="true"/>
+			</buildOutputProvider>
+			<scannerInfoProvider id="specsFile">
+				<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+				<parser enabled="true"/>
+			</scannerInfoProvider>
+		</profile>
+		<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+			<buildOutputProvider>
+				<openAction enabled="true" filePath=""/>
+				<parser enabled="true"/>
+			</buildOutputProvider>
+			<scannerInfoProvider id="specsFile">
+				<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+				<parser enabled="true"/>
+			</scannerInfoProvider>
+		</profile>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.903226628;cdt.managedbuild.toolchain.gnu.base.903226628.1687962773;cdt.managedbuild.tool.gnu.cpp.compiler.base.1562953463;cdt.managedbuild.tool.gnu.cpp.compiler.input.397287263">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"/>
+			<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+				<buildOutputProvider>
+					<openAction enabled="true" filePath=""/>
+					<parser enabled="true"/>
+				</buildOutputProvider>
+				<scannerInfoProvider id="specsFile">
+					<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+					<parser enabled="true"/>
+				</scannerInfoProvider>
+			</profile>
+			<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+				<buildOutputProvider>
+					<openAction enabled="true" filePath=""/>
+					<parser enabled="true"/>
+				</buildOutputProvider>
+				<scannerInfoProvider id="makefileGenerator">
+					<runAction arguments="-f ${project_name}_scd.mk" command="make" useDefault="true"/>
+					<parser enabled="true"/>
+				</scannerInfoProvider>
+			</profile>
+			<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+				<buildOutputProvider>
+					<openAction enabled="true" filePath=""/>
+					<parser enabled="true"/>
+				</buildOutputProvider>
+				<scannerInfoProvider id="specsFile">
+					<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+					<parser enabled="true"/>
+				</scannerInfoProvider>
+			</profile>
+			<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+				<buildOutputProvider>
+					<openAction enabled="true" filePath=""/>
+					<parser enabled="true"/>
+				</buildOutputProvider>
+				<scannerInfoProvider id="specsFile">
+					<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+					<parser enabled="true"/>
+				</scannerInfoProvider>
+			</profile>
+			<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+				<buildOutputProvider>
+					<openAction enabled="true" filePath=""/>
+					<parser enabled="true"/>
+				</buildOutputProvider>
+				<scannerInfoProvider id="specsFile">
+					<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+					<parser enabled="true"/>
+				</scannerInfoProvider>
+			</profile>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.903226628">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"/>
+			<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+				<buildOutputProvider>
+					<openAction enabled="true" filePath=""/>
+					<parser enabled="true"/>
+				</buildOutputProvider>
+				<scannerInfoProvider id="specsFile">
+					<runAction arguments="-std=c++11 -E -P -v -dD &quot;${plugin_state_location}/specs.cpp&quot;" command="/site/apps/gcc-4.7.2-drw.patched.6/bin/g++" useDefault="true"/>
+					<parser enabled="true"/>
+				</scannerInfoProvider>
+			</profile>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.903226628;cdt.managedbuild.toolchain.gnu.base.903226628.1687962773;cdt.managedbuild.tool.gnu.c.compiler.base.2039402166;cdt.managedbuild.tool.gnu.c.compiler.input.9141713">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/>
+			<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+				<buildOutputProvider>
+					<openAction enabled="true" filePath=""/>
+					<parser enabled="true"/>
+				</buildOutputProvider>
+				<scannerInfoProvider id="specsFile">
+					<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+					<parser enabled="true"/>
+				</scannerInfoProvider>
+			</profile>
+			<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+				<buildOutputProvider>
+					<openAction enabled="true" filePath=""/>
+					<parser enabled="true"/>
+				</buildOutputProvider>
+				<scannerInfoProvider id="makefileGenerator">
+					<runAction arguments="-f ${project_name}_scd.mk" command="make" useDefault="true"/>
+					<parser enabled="true"/>
+				</scannerInfoProvider>
+			</profile>
+			<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+				<buildOutputProvider>
+					<openAction enabled="true" filePath=""/>
+					<parser enabled="true"/>
+				</buildOutputProvider>
+				<scannerInfoProvider id="specsFile">
+					<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+					<parser enabled="true"/>
+				</scannerInfoProvider>
+			</profile>
+			<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
+				<buildOutputProvider>
+					<openAction enabled="true" filePath=""/>
+					<parser enabled="true"/>
+				</buildOutputProvider>
+				<scannerInfoProvider id="specsFile">
+					<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
+					<parser enabled="true"/>
+				</scannerInfoProvider>
+			</profile>
+			<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
+				<buildOutputProvider>
+					<openAction enabled="true" filePath=""/>
+					<parser enabled="true"/>
+				</buildOutputProvider>
+				<scannerInfoProvider id="specsFile">
+					<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
+					<parser enabled="true"/>
+				</scannerInfoProvider>
+			</profile>
+		</scannerConfigBuildInfo>
+	</storageModule>
+	<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
+</cproject>
diff --git a/third_party/seasocks/.gitignore b/third_party/seasocks/.gitignore
new file mode 100644
index 0000000..65512ab
--- /dev/null
+++ b/third_party/seasocks/.gitignore
@@ -0,0 +1,15 @@
+*.swp
+/.fig
+/.tests-pass
+/.tests-pass-valgrind
+/Makefile
+/autom4te.cache
+/bin
+/config.log
+/config.status
+/configure
+/obj
+/tags
+/.gmock
+.gdb_history
+gdb.txt
diff --git a/third_party/seasocks/.project b/third_party/seasocks/.project
new file mode 100644
index 0000000..da15833
--- /dev/null
+++ b/third_party/seasocks/.project
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>seasocks</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
+			<triggers>clean,full,incremental,</triggers>
+			<arguments>
+				<dictionary>
+					<key>?name?</key>
+					<value></value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.append_environment</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.autoBuildTarget</key>
+					<value>all</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.buildArguments</key>
+					<value></value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.buildCommand</key>
+					<value>make</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.cleanBuildTarget</key>
+					<value>clean</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.contents</key>
+					<value>org.eclipse.cdt.make.core.activeConfigSettings</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.enableAutoBuild</key>
+					<value>false</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.enableCleanBuild</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.enableFullBuild</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.fullBuildTarget</key>
+					<value>all</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.stopOnError</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
+					<value>true</value>
+				</dictionary>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.cdt.core.cnature</nature>
+		<nature>org.eclipse.cdt.core.ccnature</nature>
+		<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+		<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+	</natures>
+</projectDescription>
diff --git a/third_party/seasocks/.settings/language.settings.xml b/third_party/seasocks/.settings/language.settings.xml
new file mode 100644
index 0000000..adffb7c
--- /dev/null
+++ b/third_party/seasocks/.settings/language.settings.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<project>
+	<configuration id="cdt.managedbuild.toolchain.gnu.base.903226628" name="Default">
+		<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
+			<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
+			<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
+		</extension>
+	</configuration>
+</project>
diff --git a/third_party/seasocks/.travis.yml b/third_party/seasocks/.travis.yml
new file mode 100644
index 0000000..9df4ab8
--- /dev/null
+++ b/third_party/seasocks/.travis.yml
@@ -0,0 +1,21 @@
+language: cpp
+compiler:
+  - gcc
+  - clang
+before_install:
+  - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
+  - sudo add-apt-repository ppa:h-rayflood/llvm -y
+  - sudo apt-get update -qq
+install:
+  - if [ "$CXX" = "g++" ]; then sudo apt-get install -qq g++-4.7; fi
+  - if [ "$CXX" = "g++" ]; then export CXX="g++-4.7" CC="gcc-4.7"; fi
+  - if [ "$CXX" = "clang++" ]; then sudo apt-get install -qq --allow-unauthenticated clang-3.4; fi
+  - if [ "$CXX" = "clang++" ]; then export CXX="clang++-3.4" CC="clang-3.4"; fi
+  - wget "https://googlemock.googlecode.com/files/gmock-1.7.0.zip"
+  - unzip gmock-1.7.0.zip
+  - sudo apt-get install valgrind
+script:
+  - autoconf
+  - ./configure --with-gmock=gmock-1.7.0
+  - make
+  - make test
diff --git a/third_party/seasocks/LICENSE b/third_party/seasocks/LICENSE
new file mode 100644
index 0000000..2798024
--- /dev/null
+++ b/third_party/seasocks/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2013, Matt Godbolt
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this 
+list of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this 
+list of conditions and the following disclaimer in the documentation and/or 
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/third_party/seasocks/Makefile.in b/third_party/seasocks/Makefile.in
new file mode 100644
index 0000000..6261306
--- /dev/null
+++ b/third_party/seasocks/Makefile.in
@@ -0,0 +1,145 @@
+default: all
+
+AR=ar
+ARFLAGS=cru
+CXX=@CXX@
+CXXFLAGS=@CXXFLAGS@
+VALGRIND=@VALGRIND@
+LDFLAGS=@LDFLAGS@
+# hack for drw gcc on ubuntu
+GCC_MULTIARCH := $(shell gcc -print-multiarch 2>/dev/null)
+ifneq ($(GCC_MULTIARCH),)
+  export LIBRARY_PATH = /usr/lib/$(GCC_MULTIARCH)
+  export C_INCLUDE_PATH = /usr/include/$(GCC_MULTIARCH)
+  export CPLUS_INCLUDE_PATH = /usr/include/$(GCC_MULTIARCH)
+endif
+
+C_SRC=src/main/c
+TEST_SRC=src/test/c
+APPS_SRC=src/app/c
+
+VERSION_STRING:=SeaSocks/$(or $(VERSION),unversioned) ($(shell git describe --always --dirty || echo non-git))
+
+CXXFLAGS += -fPIC -Wall -Werror '-DSEASOCKS_VERSION_STRING="$(VERSION_STRING)"' -I$(C_SRC)
+
+.PHONY: all clean run test spotless header-checks valgrind-test
+
+OBJ_DIR=obj
+BIN_DIR=bin
+
+CPP_SRCS=$(shell find $(C_SRC) -name '*.cpp')
+H_SRCS=$(shell find $(C_SRC) -name '*.h')
+TEST_SRCS=$(shell find $(TEST_SRC) -name '*.cpp')
+APPS_CPP_SRCS=$(shell find $(APPS_SRC) -name '*.cpp')
+TARGETS=$(patsubst $(APPS_SRC)/%.cpp,$(BIN_DIR)/%,$(APPS_CPP_SRCS))
+
+apps: $(TARGETS)
+all: apps $(BIN_DIR)/libseasocks.so $(BIN_DIR)/libseasocks.a test header-checks valgrind-test
+
+debug:
+	echo $($(DEBUG_VAR))
+
+OBJS=$(patsubst $(C_SRC)/%.cpp,$(OBJ_DIR)/%.o,$(CPP_SRCS))
+HCS=$(patsubst $(C_SRC)/%.h,$(OBJ_DIR)/%.hc,$(H_SRCS))
+TEST_OBJS=$(patsubst $(TEST_SRC)/%.cpp,$(OBJ_DIR)/%.o,$(TEST_SRCS))
+APPS_OBJS=$(patsubst $(APPS_SRC)/%.cpp,$(OBJ_DIR)/%.o,$(APPS_CPP_SRCS))
+ALL_OBJS=$(OBJS) $(APPS_OBJS) $(TEST_OBJS)
+GEN_OBJS=$(OBJ_DIR)/embedded.o
+
+-include $(ALL_OBJS:.o=.d)
+
+$(APPS_OBJS) : $(OBJ_DIR)/%.o : $(APPS_SRC)/%.cpp
+	@mkdir -p $(dir $@)
+	$(CXX) $(CXXFLAGS) -MMD -MP -MF"$(@:%.o=%.d)" -MT"$@" -c -o "$@" "$<"
+
+$(OBJS) : $(OBJ_DIR)/%.o : $(C_SRC)/%.cpp
+	@mkdir -p $(dir $@)
+	$(CXX) $(CXXFLAGS) -MMD -MP -MF"$(@:%.o=%.d)" -MT"$@" -c -o "$@" "$<"
+
+$(HCS) : $(OBJ_DIR)/%.hc : $(C_SRC)/%.h
+	@mkdir -p $(dir $@)
+	@echo "Checking header file is self-contained: $<"
+	@$(CXX) -fsyntax-only $(CXXFLAGS) -o /dev/null -c -w $<
+	@touch $@
+
+$(TEST_OBJS) : $(OBJ_DIR)/%.o : $(TEST_SRC)/%.cpp
+	@mkdir -p $(dir $@)
+	$(CXX) $(CXXFLAGS) -MMD -MP -MF"$(@:%.o=%.d)" -MT"$@" -c -o "$@" "$<"
+
+$(TARGETS) : $(BIN_DIR)/% : $(OBJ_DIR)/%.o $(OBJS) $(GEN_OBJS)
+	@mkdir -p $(BIN_DIR)
+	$(CXX) $(CXXFLAGS) -o $@ $^
+
+$(BIN_DIR)/libseasocks.so: $(OBJS) $(GEN_OBJS)
+	@mkdir -p $(BIN_DIR)
+	$(CXX) -shared $(CXXFLAGS) -o $@ $^
+
+$(BIN_DIR)/libseasocks.a: $(OBJS) $(GEN_OBJS)
+	@mkdir -p $(BIN_DIR)
+	@-rm -f $(BIN_DIR)/libseasocks.a
+	$(AR) $(ARFLAGS) $@ $^
+
+EMBEDDED_CONTENT:=$(shell find src/main/web -type f)
+$(OBJ_DIR)/embedded.o: scripts/gen_embedded.py $(EMBEDDED_CONTENT) src/main/c/internal/Embedded.h
+	@mkdir -p $(dir $@)
+	scripts/gen_embedded.py $(EMBEDDED_CONTENT) | $(CXX) $(CXXFLAGS) -x c++ -c -o "$@" -
+
+header-checks: $(HCS)
+
+run: $(BIN_DIR)/ws_test
+	$(BIN_DIR)/ws_test
+
+ifneq ("@GMOCK_DIR@", "")
+GMOCK_DIR = @GMOCK_DIR@
+GTEST_DIR = $(GMOCK_DIR)/gtest
+CXXFLAGS += -isystem $(GTEST_DIR)/include -isystem $(GMOCK_DIR)/include
+GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \
+				$(GTEST_DIR)/include/gtest/internal/*.h
+GMOCK_HEADERS = $(GMOCK_DIR)/include/gmock/*.h \
+				$(GMOCK_DIR)/include/gmock/internal/*.h \
+				$(GTEST_HEADERS)
+GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS)
+GMOCK_SRCS_ = $(GMOCK_DIR)/src/*.cc $(GMOCK_HEADERS)
+
+$(OBJ_DIR)/gtest-all.o : $(GTEST_SRCS_)
+	$(CXX) $(CXXFLAGS) -I$(GTEST_DIR) -I$(GMOCK_DIR) $(CXXFLAGS) \
+		-c $(GTEST_DIR)/src/gtest-all.cc -o $@
+
+$(OBJ_DIR)/gmock-all.o : $(GMOCK_SRCS_)
+	$(CXX) $(CXXFLAGS) -I$(GTEST_DIR) -I$(GMOCK_DIR) $(CXXFLAGS) \
+		-c $(GMOCK_DIR)/src/gmock-all.cc -o $@
+
+$(BIN_DIR)/tests: $(TEST_OBJS) $(BIN_DIR)/libseasocks.a \
+	$(OBJ_DIR)/gmock-all.o $(OBJ_DIR)/gtest-all.o
+	$(CXX) $(LDFLAGS) $(CXXFLAGS) -I $(TEST_SRC) -o $@ $^ 
+
+.tests-pass: $(BIN_DIR)/tests
+	@rm -f .tests-pass
+	$(BIN_DIR)/tests
+	@touch .tests-pass
+
+test: .tests-pass
+
+ifneq ("@VALGRIND@", "")
+valgrind-test: .tests-pass
+	$(VALGRIND) --leak-check=full --error-exitcode=2 -- $(BIN_DIR)/tests
+else
+valgrind-test:
+	@echo "Not running valgrind-test as no valgrind binary found during configure"
+endif
+
+else
+
+test:
+	@echo "Not running tests as no gmock/gtest specified during configure"
+	@echo "To configure, specify with --with-gmock=PATH_TO_GMOCK"
+test-valgrind: test
+
+endif
+
+clean:
+	rm -rf $(OBJ_DIR) $(BIN_DIR) *.tar.gz .tests-pass
+
+spotless: clean
+	rm -rf lib include config.log configure config.status src/main/c/internal/Config.h Makefile autom4te.cache
+
diff --git a/third_party/seasocks/README.md b/third_party/seasocks/README.md
new file mode 100644
index 0000000..1201f49
--- /dev/null
+++ b/third_party/seasocks/README.md
@@ -0,0 +1,24 @@
+SeaSocks - A tiny embeddable C++ HTTP and WebSocket server
+==========================================================
+
+[![Build Status](https://travis-ci.org/mattgodbolt/seasocks.svg?branch=master)](https://travis-ci.org/mattgodbolt/seasocks)
+
+Features
+--------
+*   Simple C++ API
+*   Serves static content from disk
+*   API for building WebSocket servers
+*   Simple command line binary for quick serving of static files only
+*   Supports newer Hybi-10 and Hybi-16 WebSockets as well as the older Hixie style.
+
+Stuff it doesn't do
+-------------------
+It's not nearly as configurable as Apache, Lighttpd, Nginx, Jetty, etc.
+It provides only very limited support for custom content generation (e.g. Servlets).
+It has been optimized for WebSocket based control.
+
+Getting started
+---------------
+Check out the [tutorial](https://github.com/mattgodbolt/seasocks/wiki/SeaSocks-quick-tutorial) on the wiki.
+
+See [src/app/c/ws_test.cpp](https://github.com/mattgodbolt/seasocks/blob/master/src/app/c/ws_test.cpp) for an example.
diff --git a/third_party/seasocks/TODO.md b/third_party/seasocks/TODO.md
new file mode 100644
index 0000000..b56a7a6
--- /dev/null
+++ b/third_party/seasocks/TODO.md
@@ -0,0 +1,16 @@
+General list of things todo
+---------------------------
+
+* git grep 'TODO' and fix
+* include what you use: lots of headers rely on ambient includes
+* add more tests
+* move more things over to the Request/Response way of doing things
+* Double check it's ok to remove hixie, and do so.  Currently no way of testing it anyway
+  (with reference to http://en.wikipedia.org/wiki/WebSocket#Browser_support it's been dead
+  since before Chrome 14)
+
+Further out things
+------------------
+* Generalise the request/response so that persistent connections can be phrased
+  as them.
+* Benchmark and add benchmarks to the tests.
diff --git a/third_party/seasocks/configure.ac b/third_party/seasocks/configure.ac
new file mode 100644
index 0000000..7c6e51b
--- /dev/null
+++ b/third_party/seasocks/configure.ac
@@ -0,0 +1,71 @@
+m4_include([scripts/c++11.m4])
+
+AC_PREREQ(2.63)
+AC_INIT([SeaSocks], [0.1], [matt@godbolt.org], [], [https://github.com/mattgodbolt/seasocks])
+AC_CONFIG_SRCDIR([src/main/c/seasocks/Server.h])
+
+AC_ARG_WITH([gmock],
+            [AS_HELP_STRING([--with-gmock],
+                            [Build tests too, with supplied gmock directory.  SeaSocks will
+                             build gmock and its embedded gtest automatically])],
+                             [],
+                             [AC_MSG_WARN([dnl
+Building without tests enabled. Use --with-gmock=PATH_TO_GMOCK])])
+
+AS_IF([test "x${with_gmock}" != "xno" -a "x${with_gmock}" != "x"],
+      [
+       AS_IF([test -e "${with_gmock}/include/gmock/gmock.h"],
+             [GMOCK_DIR="${with_gmock}"],
+             [AC_MSG_ERROR([dnl
+              Unable to locate gmock source at '${with_gmock}'.])])
+       ])
+AC_SUBST(GMOCK_DIR)
+
+dnl Basic setup
+AC_LANG(C++)
+AC_PROG_CC
+AC_PROG_CPP
+AC_PROG_CXX
+AX_CXX_COMPILE_STDCXX_11([noext])
+AC_DEFUN([AX_CXX_CHECK_UNORDERED_MAP_EMPLACE], [
+          AC_LANG_PUSH([C++])
+          AC_MSG_CHECKING([whether std::unordered_map supports emplace])
+          AC_COMPILE_IFELSE([AC_LANG_SOURCE[
+                             #include <unordered_map>
+                             void test() { std::unordered_map<int, int> a; a.emplace(2,3); }
+                             ]],
+                             [eval unordered_map_emplace=yes],[eval unordered_map_emplace=no])
+          AC_MSG_RESULT([$unordered_map_emplace])
+          AC_LANG_POP([C++])
+          if test x$unordered_map_emplace = xyes; then
+              AC_DEFINE(HAVE_UNORDERED_MAP_EMPLACE,1, [define if unordered_map supports emplace])
+          fi
+          AC_SUBST(HAVE_UNORDERED_MAP_EMPLACE)
+          ])
+AX_CXX_CHECK_UNORDERED_MAP_EMPLACE
+AC_PATH_PROG(VALGRIND, valgrind)
+
+dnl Basic headers and features
+AC_HEADER_STDBOOL
+AC_C_INLINE
+AC_TYPE_PID_T
+AC_C_RESTRICT
+AC_TYPE_SIZE_T
+AC_TYPE_UINT16_T
+AC_TYPE_UINT32_T
+AC_TYPE_UINT64_T
+AC_TYPE_UINT8_T
+AC_FUNC_ERROR_AT_LINE
+AC_FUNC_FORK
+AC_FUNC_STRERROR_R
+AC_CHECK_TYPES([ptrdiff_t])
+
+dnl pthreads; better if we detect this somehow
+CXXFLAGS="$CXXFLAGS -pthread"
+
+dnl System headers and functions used
+AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h limits.h netinet/in.h stddef.h stdlib.h string.h strings.h sys/ioctl.h sys/socket.h unistd.h getopt.h])
+AC_CHECK_FUNCS([dup2 eventfd syscall gethostname memset rmdir socket sqrt strcasecmp strchr strdup strerror getopt])
+
+AC_CONFIG_HEADERS([src/main/c/internal/Config.h])
+AC_OUTPUT([Makefile])
diff --git a/third_party/seasocks/scripts/c++11.m4 b/third_party/seasocks/scripts/c++11.m4
new file mode 100644
index 0000000..f3e5fce
--- /dev/null
+++ b/third_party/seasocks/scripts/c++11.m4
@@ -0,0 +1,136 @@
+# ============================================================================
+#  http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html
+# ============================================================================
+#
+# SYNOPSIS
+#
+#   AX_CXX_COMPILE_STDCXX_11([ext|noext],[mandatory|optional])
+#
+# DESCRIPTION
+#
+#   Check for baseline language coverage in the compiler for the C++11
+#   standard; if necessary, add switches to CXXFLAGS to enable support.
+#
+#   The first argument, if specified, indicates whether you insist on an
+#   extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
+#   -std=c++11).  If neither is specified, you get whatever works, with
+#   preference for an extended mode.
+#
+#   The second argument, if specified 'mandatory' or if left unspecified,
+#   indicates that baseline C++11 support is required and that the macro
+#   should error out if no mode with that support is found.  If specified
+#   'optional', then configuration proceeds regardless, after defining
+#   HAVE_CXX11 if and only if a supporting mode is found.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
+#   Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
+#   Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved. This file is offered as-is, without any
+#   warranty.
+
+#serial 3
+
+m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [
+  template <typename T>
+    struct check
+    {
+      static_assert(sizeof(int) <= sizeof(T), "not big enough");
+    };
+
+    struct base { virtual void func() = 0; };
+    struct override : base { virtual void func() override {}; };
+
+    typedef check<check<bool>> right_angle_brackets;
+
+    int a;
+    decltype(a) b;
+
+    typedef check<int> check_type;
+    check_type c;
+    check_type&& cr = static_cast<check_type&&>(c);
+
+    auto d = a;
+])
+
+AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl
+  m4_if([$1], [], [],
+        [$1], [ext], [],
+        [$1], [noext], [],
+        [m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_11])])
+  m4_if([$2], [], [ax_cxx_compile_cxx11_required=true],
+        [$2], [mandatory], [ax_cxx_compile_cxx11_required=true],
+        [$2], [optional], [ax_cxx_compile_cxx11_required=false],
+        [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX_11])])
+  AC_LANG_PUSH([C++])
+  ac_success=no
+  AC_CACHE_CHECK(whether $CXX supports C++11 features by default,
+  ax_cv_cxx_compile_cxx11,
+  [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
+    [ax_cv_cxx_compile_cxx11=yes],
+    [ax_cv_cxx_compile_cxx11=no])])
+  if test x$ax_cv_cxx_compile_cxx11 = xyes; then
+    ac_success=yes
+  fi
+
+  m4_if([$1], [noext], [], [dnl
+  if test x$ac_success = xno; then
+    for switch in -std=gnu++11 -std=gnu++0x; do
+      cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch])
+      AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch,
+                     $cachevar,
+        [ac_save_CXXFLAGS="$CXXFLAGS"
+         CXXFLAGS="$CXXFLAGS $switch"
+         AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
+          [eval $cachevar=yes],
+          [eval $cachevar=no])
+         CXXFLAGS="$ac_save_CXXFLAGS"])
+      if eval test x\$$cachevar = xyes; then
+        CXXFLAGS="$CXXFLAGS $switch"
+        ac_success=yes
+        break
+      fi
+    done
+  fi])
+
+  m4_if([$1], [ext], [], [dnl
+  if test x$ac_success = xno; then
+    for switch in -std=c++11 -std=c++0x; do
+      cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch])
+      AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch,
+                     $cachevar,
+        [ac_save_CXXFLAGS="$CXXFLAGS"
+         CXXFLAGS="$CXXFLAGS $switch"
+         AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
+          [eval $cachevar=yes],
+          [eval $cachevar=no])
+         CXXFLAGS="$ac_save_CXXFLAGS"])
+      if eval test x\$$cachevar = xyes; then
+        CXXFLAGS="$CXXFLAGS $switch"
+        ac_success=yes
+        break
+      fi
+    done
+  fi])
+  AC_LANG_POP([C++])
+  if test x$ax_cxx_compile_cxx11_required = xtrue; then
+    if test x$ac_success = xno; then
+      AC_MSG_ERROR([*** A compiler with support for C++11 language features is required.])
+    fi
+  else
+    if test x$ac_success = xno; then
+      HAVE_CXX11=0
+      AC_MSG_NOTICE([No compiler with C++11 support was found])
+    else
+      HAVE_CXX11=1
+      AC_DEFINE(HAVE_CXX11,1,
+                [define if the compiler supports basic C++11 syntax])
+    fi
+
+    AC_SUBST(HAVE_CXX11)
+  fi
+])
diff --git a/third_party/seasocks/scripts/config-for-drw b/third_party/seasocks/scripts/config-for-drw
new file mode 100755
index 0000000..388bc5a
--- /dev/null
+++ b/third_party/seasocks/scripts/config-for-drw
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+set -e
+
+autoconf 
+
+GMOCK_DIR=.gmock/gmock-1.7.0
+
+if [ ! -d "${GMOCK_DIR}" ]; then
+    echo "Grabbing gmock"
+    mkdir -p .gmock
+    pushd .gmock
+    wget https://googlemock.googlecode.com/files/gmock-1.7.0.zip
+    unzip gmock-1.7.0.zip
+    popd
+fi
+
+GCC_HOME=$(fig -m gcc/4.9.0-2 -g GCC_HOME)
+LDFLAGS="-Wl,--rpath,${GCC_HOME}/lib64" CXX=${GCC_HOME}/bin/g++ ./configure --with-gmock=${GMOCK_DIR}
diff --git a/third_party/seasocks/scripts/gen_embedded.py b/third_party/seasocks/scripts/gen_embedded.py
new file mode 100755
index 0000000..f715b1d
--- /dev/null
+++ b/third_party/seasocks/scripts/gen_embedded.py
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+
+import os, os.path, sys
+
+print """
+#include "internal/Embedded.h"
+
+#include <string>
+#include <unordered_map>
+
+namespace {
+
+std::unordered_map<std::string, EmbeddedContent> embedded = {
+"""
+
+for f in sys.argv[1:]:
+	bytes = open(f, 'rb').read()
+	print '{"/%s", {' % os.path.basename(f)
+	print '"' + "".join(['\\x%02x' % ord(x) for x in bytes]) + '"'
+	print ',%d }},' % len(bytes)
+
+print """
+};
+
+}  // namespace
+
+const EmbeddedContent* findEmbeddedContent(const std::string& name) {
+	auto found = embedded.find(name);
+	if (found == embedded.end()) {
+		return NULL;
+	}
+	return &found->second;
+}
+"""
+
diff --git a/third_party/seasocks/src/app/c/ph_test.cpp b/third_party/seasocks/src/app/c/ph_test.cpp
new file mode 100644
index 0000000..4398e04
--- /dev/null
+++ b/third_party/seasocks/src/app/c/ph_test.cpp
@@ -0,0 +1,68 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "seasocks/PageHandler.h"
+#include "seasocks/PrintfLogger.h"
+#include "seasocks/Server.h"
+#include "seasocks/StringUtil.h"
+
+#include <cstring>
+#include <iostream>
+#include <memory>
+#include <set>
+#include <sstream>
+#include <string>
+
+using namespace seasocks;
+
+class MyPageHandler: public PageHandler {
+public:
+    virtual std::shared_ptr<Response> handle(const Request& request) {
+        if (request.verb() == Request::Post) {
+            std::string content(request.content(), request.content() + request.contentLength());
+            return Response::textResponse("Thanks for the post. You said: " + content);
+        }
+        if (request.verb() != Request::Get) return Response::unhandled();
+        std::ostringstream ostr;
+        ostr << "<html><head><title>seasocks example</title></head>"
+                "<body>Hello, " << request.credentials()->attributes["fullName"] << "! You asked for " << request.getRequestUri()
+                << " and your ip is " << request.getRemoteAddress().sin_addr.s_addr
+                << " and a random number is " << rand()
+                << "<form action=/post method=post><input type=text name=value1></input><br>"
+                << "<input type=submit value=Submit></input></form>"
+                << "</body></html>";
+        return Response::htmlResponse(ostr.str());
+    }
+};
+
+int main(int argc, const char* argv[]) {
+    std::shared_ptr<Logger> logger(new PrintfLogger(Logger::INFO));
+
+    Server server(logger);
+    server.addPageHandler(std::make_shared<MyPageHandler>());
+
+    server.serve("src/ws_test_web", 9090);
+    return 0;
+}
diff --git a/third_party/seasocks/src/app/c/serve.cpp b/third_party/seasocks/src/app/c/serve.cpp
new file mode 100644
index 0000000..a45501c
--- /dev/null
+++ b/third_party/seasocks/src/app/c/serve.cpp
@@ -0,0 +1,70 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "internal/Version.h"
+
+#include "seasocks/PrintfLogger.h"
+#include "seasocks/Server.h"
+#include "seasocks/StringUtil.h"
+
+#include <cstdio>
+#include <cstdlib>
+#include <getopt.h>
+#include <memory>
+
+using namespace seasocks;
+
+namespace {
+
+const char usage[] = "Usage: %s [-p PORT] [-v] DIR\n"
+                      "   Serves files from DIR over HTTP on port PORT\n";
+
+}
+
+int main(int argc, char* const argv[]) {
+    int port = 80;
+    bool verbose = false;
+    int opt;
+    while ((opt = getopt(argc, argv, "vp:")) != -1) {
+        switch (opt) {
+        case 'v': verbose = true; break;
+        case 'p': port = atoi(optarg); break;
+        default:
+            fprintf(stderr, usage, argv[0]);
+            exit(1);
+        }
+    }
+    if (optind >= argc) {
+        fprintf(stderr, usage, argv[0]);
+        exit(1);
+    }
+
+    auto logger = std::make_shared<PrintfLogger>(
+            verbose ? Logger::DEBUG : Logger::ACCESS);
+    Server server(logger);
+    auto root = argv[optind];
+    server.serve(root, port);
+    return 0;
+}
diff --git a/third_party/seasocks/src/app/c/ws_echo.cpp b/third_party/seasocks/src/app/c/ws_echo.cpp
new file mode 100644
index 0000000..9464a63
--- /dev/null
+++ b/third_party/seasocks/src/app/c/ws_echo.cpp
@@ -0,0 +1,67 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "seasocks/PrintfLogger.h"
+#include "seasocks/Server.h"
+#include "seasocks/StringUtil.h"
+#include "seasocks/WebSocket.h"
+
+#include <cstring>
+#include <iostream>
+#include <memory>
+#include <set>
+#include <sstream>
+#include <string>
+
+/* Simple server that echo any text or binary WebSocket messages back. */
+
+using namespace seasocks;
+
+class EchoHandler: public WebSocket::Handler {
+public:
+    virtual void onConnect(WebSocket* connection) {
+    }
+
+    virtual void onData(WebSocket* connection, const uint8_t* data, size_t length) {
+    connection->send(data, length); // binary
+    }
+
+    virtual void onData(WebSocket* connection, const char* data) {
+    connection->send(data); // text
+    }
+
+    virtual void onDisconnect(WebSocket* connection) {
+    }
+};
+
+int main(int argc, const char* argv[]) {
+    std::shared_ptr<Logger> logger(new PrintfLogger(Logger::DEBUG));
+
+    Server server(logger);
+    std::shared_ptr<EchoHandler> handler(new EchoHandler());
+    server.addWebSocketHandler("/", handler);
+    server.serve("/dev/null", 8000);
+    return 0;
+}
diff --git a/third_party/seasocks/src/app/c/ws_test.cpp b/third_party/seasocks/src/app/c/ws_test.cpp
new file mode 100644
index 0000000..2a8823a
--- /dev/null
+++ b/third_party/seasocks/src/app/c/ws_test.cpp
@@ -0,0 +1,112 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+// An extraordinarily simple test which presents a web page with some buttons.
+// Clicking on the numbered button increments the number, which is visible to
+// other connected clients.  WebSockets are used to do this: by the rather
+// suspicious means of sending raw JavaScript commands to be executed on other
+// clients.
+
+#include "seasocks/PrintfLogger.h"
+#include "seasocks/Server.h"
+#include "seasocks/StringUtil.h"
+#include "seasocks/WebSocket.h"
+#include "seasocks/util/Json.h"
+
+#include <cstring>
+#include <iostream>
+#include <memory>
+#include <set>
+#include <sstream>
+#include <string>
+
+using namespace seasocks;
+using namespace std;
+
+class MyHandler: public WebSocket::Handler {
+public:
+    MyHandler(Server* server) : _server(server), _currentValue(0) {
+        setValue(1);
+    }
+
+    virtual void onConnect(WebSocket* connection) {
+        _connections.insert(connection);
+        connection->send(_currentSetValue.c_str());
+        cout << "Connected: " << connection->getRequestUri()
+                << " : " << formatAddress(connection->getRemoteAddress())
+                << endl;
+        cout << "Credentials: " << *(connection->credentials()) << endl;
+    }
+
+    virtual void onData(WebSocket* connection, const char* data) {
+        if (0 == strcmp("die", data)) {
+            _server->terminate();
+            return;
+        }
+        if (0 == strcmp("close", data)) {
+            cout << "Closing.." << endl;
+            connection->close();
+            cout << "Closed." << endl;
+            return;
+        }
+
+        int value = atoi(data) + 1;
+        if (value > _currentValue) {
+            setValue(value);
+            for (auto connection : _connections) {
+                connection->send(_currentSetValue.c_str());
+            }
+        }
+    }
+
+    virtual void onDisconnect(WebSocket* connection) {
+        _connections.erase(connection);
+        cout << "Disconnected: " << connection->getRequestUri()
+                << " : " << formatAddress(connection->getRemoteAddress())
+                << endl;
+    }
+
+private:
+    set<WebSocket*> _connections;
+    Server* _server;
+    int _currentValue;
+    string _currentSetValue;
+
+    void setValue(int value) {
+        _currentValue = value;
+        _currentSetValue = makeExecString("set", _currentValue);
+    }
+};
+
+int main(int argc, const char* argv[]) {
+    shared_ptr<Logger> logger(new PrintfLogger(Logger::DEBUG));
+
+    Server server(logger);
+
+    shared_ptr<MyHandler> handler(new MyHandler(&server));
+    server.addWebSocketHandler("/ws", handler);
+    server.serve("src/ws_test_web", 9090);
+    return 0;
+}
diff --git a/third_party/seasocks/src/app/c/ws_test_poll.cpp b/third_party/seasocks/src/app/c/ws_test_poll.cpp
new file mode 100644
index 0000000..fd5805e
--- /dev/null
+++ b/third_party/seasocks/src/app/c/ws_test_poll.cpp
@@ -0,0 +1,170 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+// An extraordinarily simple test which presents a web page with some buttons.
+// Clicking on the numbered button increments the number, which is visible to
+// other connected clients.  WebSockets are used to do this: by the rather
+// suspicious means of sending raw JavaScript commands to be executed on other
+// clients.
+
+// Same as ws_test, but uses the poll() method and a separate epoll set to
+// demonstrate how Seasocks can be used with another polling system.
+
+#include "seasocks/PrintfLogger.h"
+#include "seasocks/Server.h"
+#include "seasocks/StringUtil.h"
+#include "seasocks/WebSocket.h"
+#include "seasocks/util/Json.h"
+
+#include <cstring>
+#include <iostream>
+#include <memory>
+#include <set>
+#include <sstream>
+#include <string>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/epoll.h>
+
+using namespace seasocks;
+using namespace std;
+
+class MyHandler: public WebSocket::Handler {
+public:
+    MyHandler(Server* server) : _server(server), _currentValue(0) {
+        setValue(1);
+    }
+
+    virtual void onConnect(WebSocket* connection) {
+        _connections.insert(connection);
+        connection->send(_currentSetValue.c_str());
+        cout << "Connected: " << connection->getRequestUri()
+                << " : " << formatAddress(connection->getRemoteAddress())
+                << endl;
+        cout << "Credentials: " << *(connection->credentials()) << endl;
+    }
+
+    virtual void onData(WebSocket* connection, const char* data) {
+        if (0 == strcmp("die", data)) {
+            _server->terminate();
+            return;
+        }
+        if (0 == strcmp("close", data)) {
+            cout << "Closing.." << endl;
+            connection->close();
+            cout << "Closed." << endl;
+            return;
+        }
+
+        int value = atoi(data) + 1;
+        if (value > _currentValue) {
+            setValue(value);
+            for (auto connection : _connections) {
+                connection->send(_currentSetValue.c_str());
+            }
+        }
+    }
+
+    virtual void onDisconnect(WebSocket* connection) {
+        _connections.erase(connection);
+        cout << "Disconnected: " << connection->getRequestUri()
+                << " : " << formatAddress(connection->getRemoteAddress())
+                << endl;
+    }
+
+private:
+    set<WebSocket*> _connections;
+    Server* _server;
+    int _currentValue;
+    string _currentSetValue;
+
+    void setValue(int value) {
+        _currentValue = value;
+        _currentSetValue = makeExecString("set", _currentValue);
+    }
+};
+
+int main(int argc, const char* argv[]) {
+    shared_ptr<Logger> logger(new PrintfLogger(Logger::DEBUG));
+
+    Server server(logger);
+
+    shared_ptr<MyHandler> handler(new MyHandler(&server));
+    server.addWebSocketHandler("/ws", handler);
+    server.setStaticPath("src/ws_test_web");
+    if (!server.startListening(9090)) {
+        cerr << "couldn't start listening" << endl;
+        return 1;
+    }
+    int myEpoll = epoll_create(10);
+    epoll_event wakeSeasocks = { EPOLLIN|EPOLLOUT|EPOLLERR, { &server } };
+    epoll_ctl(myEpoll, EPOLL_CTL_ADD, server.fd(), &wakeSeasocks);
+
+    // Also poll stdin
+    epoll_event wakeStdin = { EPOLLIN, { nullptr } };
+    epoll_ctl(myEpoll, EPOLL_CTL_ADD, STDIN_FILENO, &wakeStdin);
+    auto prevFlags = fcntl(STDIN_FILENO, F_GETFL, 0);
+    fcntl(STDIN_FILENO, F_SETFL, prevFlags | O_NONBLOCK);
+
+    cout << "Will echo anything typed in stdin: " << flush;
+    while (true) {
+        constexpr auto maxEvents = 2;
+        epoll_event events[maxEvents];
+        auto res = epoll_wait(myEpoll, events, maxEvents, -1);
+        if (res < 0) {
+            cerr << "epoll returned an error" << endl;
+            return 1;
+        }
+        for (auto i = 0; i < res; ++i) {
+            if (events[i].data.ptr == &server) {
+                auto seasocksResult = server.poll(0);
+                if (seasocksResult == Server::PollResult::Terminated) return 0;
+                if (seasocksResult == Server::PollResult::Error) return 1;
+            } else if (events[i].data.ptr == nullptr) {
+                // Echo stdin to stdout to show we can read from that too.
+                for (;;) {
+                    char buf[1024];
+                    auto numRead = ::read(STDIN_FILENO, buf, sizeof(buf));
+                    if (numRead < 0) {
+                        if (errno != EWOULDBLOCK && errno != EAGAIN) {
+                            cerr << "Error reading stdin" << endl;
+                            return 1;
+                        }
+                        break;
+                    } else if (numRead > 0) {
+                        auto written = write(STDOUT_FILENO, buf, numRead);
+                        if (written != numRead) {
+                            cerr << "Truncated write" << endl;
+                        }
+                    } else if (numRead == 0) {
+                        cerr << "EOF on stdin" << endl;
+                        return 0;
+                    }
+                }
+            }
+        }
+    }
+    return 0;
+}
diff --git a/third_party/seasocks/src/main/c/Connection.cpp b/third_party/seasocks/src/main/c/Connection.cpp
new file mode 100644
index 0000000..9c250a0
--- /dev/null
+++ b/third_party/seasocks/src/main/c/Connection.cpp
@@ -0,0 +1,1075 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "internal/Config.h"
+#include "internal/Embedded.h"
+#include "internal/HeaderMap.h"
+#include "internal/HybiAccept.h"
+#include "internal/HybiPacketDecoder.h"
+#include "internal/LogStream.h"
+#include "internal/PageRequest.h"
+#include "internal/Version.h"
+
+#include "md5/md5.h"
+
+#include "seasocks/Connection.h"
+#include "seasocks/Credentials.h"
+#include "seasocks/Logger.h"
+#include "seasocks/PageHandler.h"
+#include "seasocks/Server.h"
+#include "seasocks/StringUtil.h"
+#include "seasocks/ToString.h"
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fstream>
+#include <iostream>
+#include <limits>
+#include <sstream>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <unordered_map>
+
+namespace {
+
+uint32_t parseWebSocketKey(const std::string& key) {
+    uint32_t keyNumber = 0;
+    uint32_t numSpaces = 0;
+    for (auto c : key) {
+        if (c >= '0' && c <= '9') {
+            keyNumber = keyNumber * 10 + c - '0';
+        } else if (c == ' ') {
+            ++numSpaces;
+        }
+    }
+    return numSpaces > 0 ? keyNumber / numSpaces : 0;
+}
+
+char* extractLine(uint8_t*& first, uint8_t* last, char** colon = NULL) {
+    for (uint8_t* ptr = first; ptr < last - 1; ++ptr) {
+        if (ptr[0] == '\r' && ptr[1] == '\n') {
+            ptr[0] = 0;
+            uint8_t* result = first;
+            first = ptr + 2;
+            return reinterpret_cast<char*> (result);
+        }
+        if (colon && ptr[0] == ':' && *colon == NULL) {
+            *colon = reinterpret_cast<char*> (ptr);
+        }
+    }
+    return NULL;
+}
+
+std::string webtime(time_t time) {
+    struct tm tm;
+    gmtime_r(&time, &tm);
+    char buf[1024];
+    // Wed, 20 Apr 2011 17:31:28 GMT
+    strftime(buf, sizeof(buf)-1, "%a, %d %b %Y %H:%M:%S %Z", &tm);
+    return buf;
+}
+
+std::string now() {
+    return webtime(time(NULL));
+}
+
+class RaiiFd {
+    int _fd;
+public:
+    RaiiFd(const char* filename) {
+        _fd = ::open(filename, O_RDONLY);
+    }
+    RaiiFd(const RaiiFd&) = delete;
+    RaiiFd& operator=(const RaiiFd&) = delete;
+    ~RaiiFd() {
+        if (_fd != -1) {
+            ::close(_fd);
+        }
+    }
+    bool ok() const {
+        return _fd != -1;
+    }
+    operator int() const {
+        return _fd;
+    }
+};
+
+const std::unordered_map<std::string, std::string> contentTypes = {
+    { "txt", "text/plain" },
+    { "css", "text/css" },
+    { "csv", "text/csv" },
+    { "htm", "text/html" },
+    { "html", "text/html" },
+    { "xml", "text/xml" },
+    { "js", "text/javascript" }, // Technically it should be application/javascript (RFC 4329), but IE8 struggles with that
+    { "xhtml", "application/xhtml+xml" },
+    { "json", "application/json" },
+    { "pdf", "application/pdf" },
+    { "zip", "application/zip" },
+    { "tar", "application/x-tar" },
+    { "gif", "image/gif" },
+    { "jpeg", "image/jpeg" },
+    { "jpg", "image/jpeg" },
+    { "tiff", "image/tiff" },
+    { "tif", "image/tiff" },
+    { "png", "image/png" },
+    { "svg", "image/svg+xml" },
+    { "ico", "image/x-icon" },
+    { "swf", "application/x-shockwave-flash" },
+    { "mp3", "audio/mpeg" },
+    { "wav", "audio/x-wav" },
+    { "ttf", "font/ttf" },
+};
+
+std::string getExt(const std::string& path) {
+    auto lastDot = path.find_last_of('.');
+    if (lastDot != path.npos) {
+        return path.substr(lastDot + 1);
+    }
+    return "";
+}
+
+const std::string& getContentType(const std::string& path) {
+    auto it = contentTypes.find(getExt(path));
+    if (it != contentTypes.end()) {
+        return it->second;
+    }
+    static const std::string defaultType("text/html");
+    return defaultType;
+}
+
+// Cacheability is only set for resources that *REQUIRE* caching for browser support reasons.
+// It's off for everything else to save on browser reload headaches during development, at
+// least until we support ETags or If-Modified-Since: type checking, which we may never do.
+bool isCacheable(const std::string& path) {
+    std::string extension = getExt(path);
+    if (extension == "mp3" || extension == "wav") {
+        return true;
+    }
+    return false;
+}
+
+const size_t MaxBufferSize = 16 * 1024 * 1024;
+const size_t ReadWriteBufferSize = 16 * 1024;
+const size_t MaxWebsocketMessageSize = 16384;
+const size_t MaxHeadersSize = 64 * 1024;
+
+class PrefixWrapper : public seasocks::Logger {
+    std::string _prefix;
+    std::shared_ptr<Logger> _logger;
+public:
+    PrefixWrapper(const std::string& prefix, std::shared_ptr<Logger> logger)
+    : _prefix(prefix), _logger(logger) {}
+
+    virtual void log(Level level, const char* message) {
+        _logger->log(level, (_prefix + message).c_str());
+    }
+};
+
+bool hasConnectionType(const std::string &connection, const std::string &type) {
+    for (auto conType : seasocks::split(connection, ',')) {
+        while (!conType.empty() && isspace(conType[0]))
+            conType = conType.substr(1);
+        if (seasocks::caseInsensitiveSame(conType, type))
+            return true;
+    }
+    return false;
+}
+
+}  // namespace
+
+namespace seasocks {
+
+Connection::Connection(
+        std::shared_ptr<Logger> logger,
+        ServerImpl& server,
+        int fd,
+        const sockaddr_in& address)
+    : _logger(new PrefixWrapper(formatAddress(address) + " : ", logger)),
+      _server(server),
+      _fd(fd),
+      _shutdown(false),
+      _hadSendError(false),
+      _closeOnEmpty(false),
+      _registeredForWriteEvents(false),
+      _address(address),
+      _bytesSent(0),
+      _bytesReceived(0),
+      _shutdownByUser(false),
+      _state(READING_HEADERS) {
+}
+
+Connection::~Connection() {
+    _server.checkThread();
+    finalise();
+}
+
+void Connection::close() {
+    // This is the user-side close requests ONLY! You should Call closeInternal
+    _shutdownByUser = true;
+    closeInternal();
+}
+
+void Connection::closeWhenEmpty() {
+    if (_outBuf.empty()) {
+        closeInternal();
+    } else {
+        _closeOnEmpty = true;
+    }
+}
+
+void Connection::closeInternal() {
+    // It only actually only calls shutdown on the socket,
+    // leaving the close of the FD and the cleanup until the destructor runs.
+    _server.checkThread();
+    if (_fd != -1 && !_shutdown && ::shutdown(_fd, SHUT_RDWR) == -1) {
+        LS_WARNING(_logger, "Unable to shutdown socket : " << getLastError());
+    }
+    _shutdown = true;
+}
+
+
+void Connection::finalise() {
+    if (_webSocketHandler) {
+        _webSocketHandler->onDisconnect(this);
+        _webSocketHandler.reset();
+    }
+    if (_fd != -1) {
+        _server.remove(this);
+        LS_DEBUG(_logger, "Closing socket");
+        ::close(_fd);
+    }
+    _fd = -1;
+}
+
+int Connection::safeSend(const void* data, size_t size) {
+    if (_fd == -1 || _hadSendError || _shutdown) {
+        // Ignore further writes to the socket, it's already closed or has been shutdown
+        return -1;
+    }
+    int sendResult = ::send(_fd, data, size, MSG_NOSIGNAL);
+    if (sendResult == -1) {
+        if (errno == EAGAIN || errno == EWOULDBLOCK) {
+            // Treat this as if zero bytes were written.
+            return 0;
+        }
+        LS_WARNING(_logger, "Unable to write to socket : " << getLastError() << " - disabling further writes");
+        closeInternal();
+    } else {
+        _bytesSent += sendResult;
+    }
+    return sendResult;
+}
+
+bool Connection::write(const void* data, size_t size, bool flushIt) {
+    if (closed() || _closeOnEmpty) {
+        return false;
+    }
+    if (size) {
+        int bytesSent = 0;
+        if (_outBuf.empty() && flushIt) {
+            // Attempt fast path, send directly.
+            bytesSent = safeSend(data, size);
+            if (bytesSent == static_cast<int>(size)) {
+                // We sent directly.
+                return true;
+            }
+            if (bytesSent == -1) {
+                return false;
+            }
+        }
+        size_t bytesToBuffer = size - bytesSent;
+        size_t endOfBuffer = _outBuf.size();
+        size_t newBufferSize = endOfBuffer + bytesToBuffer;
+        if (newBufferSize >= MaxBufferSize) {
+            LS_WARNING(_logger, "Closing connection: buffer size too large (" 
+                    << newBufferSize << " >= " << MaxBufferSize << ")");
+            closeInternal();
+            return false;
+        }
+        _outBuf.resize(newBufferSize);
+        memcpy(&_outBuf[endOfBuffer], reinterpret_cast<const uint8_t*>(data) + bytesSent, bytesToBuffer);
+    }
+    if (flushIt) {
+        return flush();
+    }
+    return true;
+}
+
+bool Connection::bufferLine(const char* line) {
+    static const char crlf[] = { '\r', '\n' };
+    if (!write(line, strlen(line), false)) return false;
+    return write(crlf, 2, false);
+}
+
+bool Connection::bufferLine(const std::string& line) {
+    std::string lineAndCrlf = line + "\r\n";
+    return write(lineAndCrlf.c_str(), lineAndCrlf.length(), false);
+}
+
+void Connection::handleDataReadyForRead() {
+    if (closed()) {
+        return;
+    }
+    size_t curSize = _inBuf.size();
+    _inBuf.resize(curSize + ReadWriteBufferSize);
+    int result = ::read(_fd, &_inBuf[curSize], ReadWriteBufferSize);
+    if (result == -1) {
+        LS_WARNING(_logger, "Unable to read from socket : " << getLastError());
+        return;
+    }
+    if (result == 0) {
+        LS_DEBUG(_logger, "Remote end closed connection");
+        closeInternal();
+        return;
+    }
+    _bytesReceived += result;
+    _inBuf.resize(curSize + result);
+    handleNewData();
+}
+
+void Connection::handleDataReadyForWrite() {
+    if (closed()) {
+        return;
+    }
+    flush();
+}
+
+bool Connection::flush() {
+    if (_outBuf.empty()) {
+        return true;
+    }
+    int numSent = safeSend(&_outBuf[0], _outBuf.size());
+    if (numSent == -1) {
+        return false;
+    }
+    _outBuf.erase(_outBuf.begin(), _outBuf.begin() + numSent);
+    if (_outBuf.size() > 0 && !_registeredForWriteEvents) {
+        if (!_server.subscribeToWriteEvents(this)) {
+            return false;
+        }
+        _registeredForWriteEvents = true;
+    } else if (_outBuf.empty() && _registeredForWriteEvents) {
+        if (!_server.unsubscribeFromWriteEvents(this)) {
+            return false;
+        }
+        _registeredForWriteEvents = false;
+    }
+    if (_outBuf.empty() && !closed() && _closeOnEmpty) {
+        LS_DEBUG(_logger, "Ready for close, now empty");
+        closeInternal();
+    }
+    return true;
+}
+
+bool Connection::closed() const {
+    return _fd == -1 || _shutdown;
+}
+
+void Connection::handleNewData() {
+    switch (_state) {
+    case READING_HEADERS:
+        handleHeaders();
+        break;
+    case READING_WEBSOCKET_KEY3:
+        handleWebSocketKey3();
+        break;
+    case HANDLING_HIXIE_WEBSOCKET:
+        handleHixieWebSocket();
+        break;
+    case HANDLING_HYBI_WEBSOCKET:
+        handleHybiWebSocket();
+        break;
+    case BUFFERING_POST_DATA:
+        handleBufferingPostData();
+        break;
+    default:
+        assert(false);
+        break;
+    }
+}
+
+void Connection::handleHeaders() {
+    if (_inBuf.size() < 4) {
+        return;
+    }
+    for (size_t i = 0; i <= _inBuf.size() - 4; ++i) {
+        if (_inBuf[i] == '\r' &&
+            _inBuf[i+1] == '\n' &&
+            _inBuf[i+2] == '\r' &&
+            _inBuf[i+3] == '\n') {
+            if (!processHeaders(&_inBuf[0], &_inBuf[i + 2])) {
+                closeInternal();
+                return;
+            }
+            _inBuf.erase(_inBuf.begin(), _inBuf.begin() + i + 4);
+            handleNewData();
+            return;
+        }
+    }
+    if (_inBuf.size() > MaxHeadersSize) {
+        sendUnsupportedError("Headers too big");
+    }
+}
+
+void Connection::handleWebSocketKey3() {
+    constexpr auto WebSocketKeyLen = 8u;
+    if (_inBuf.size() < WebSocketKeyLen) {
+        return;
+    }
+
+    struct {
+        uint32_t key1;
+        uint32_t key2;
+        char key3[WebSocketKeyLen];
+    } md5Source;
+
+    auto key1 = parseWebSocketKey(_request->getHeader("Sec-WebSocket-Key1"));
+    auto key2 = parseWebSocketKey(_request->getHeader("Sec-WebSocket-Key2"));
+
+    LS_DEBUG(_logger, "Got a hixie websocket with key1=0x" << std::hex << key1 << ", key2=0x" << key2);
+
+    md5Source.key1 = htonl(key1);
+    md5Source.key2 = htonl(key2);
+    memcpy(&md5Source.key3, &_inBuf[0], WebSocketKeyLen);
+
+    uint8_t digest[16];
+    md5_state_t md5state;
+    md5_init(&md5state);
+    md5_append(&md5state, reinterpret_cast<const uint8_t*>(&md5Source), sizeof(md5Source));
+    md5_finish(&md5state, digest);
+
+    LS_DEBUG(_logger, "Attempting websocket upgrade");
+
+    bufferResponseAndCommonHeaders(ResponseCode::WebSocketProtocolHandshake);
+    bufferLine("Upgrade: websocket");
+    bufferLine("Connection: Upgrade");
+    bool allowCrossOrigin = _server.isCrossOriginAllowed(_request->getRequestUri());
+    if (_request->hasHeader("Origin") && allowCrossOrigin) {
+        bufferLine("Sec-WebSocket-Origin: " +  _request->getHeader("Origin"));
+    }
+    if (_request->hasHeader("Host")) {
+        auto host = _request->getHeader("Host");
+        if (!allowCrossOrigin) {
+            bufferLine("Sec-WebSocket-Origin: http://" + host);
+        }
+        bufferLine("Sec-WebSocket-Location: ws://" + host + _request->getRequestUri());
+    }
+    bufferLine("");
+
+    write(&digest, 16, true);
+
+    _state = HANDLING_HIXIE_WEBSOCKET;
+    _inBuf.erase(_inBuf.begin(), _inBuf.begin() + 8);
+    if (_webSocketHandler) {
+        _webSocketHandler->onConnect(this);
+    }
+}
+
+void Connection::handleBufferingPostData() {
+    if (_request->consumeContent(_inBuf)) {
+        _state = READING_HEADERS;
+        if (!handlePageRequest()) {
+            closeInternal();
+        }
+    }
+}
+
+void Connection::send(const char* webSocketResponse) {
+    _server.checkThread();
+    if (_shutdown) {
+        if (_shutdownByUser) {
+            LS_ERROR(_logger, "Server wrote to connection after closing it");
+        }
+        return;
+    }
+    auto messageLength = strlen(webSocketResponse);
+    if (_state == HANDLING_HIXIE_WEBSOCKET) {
+        uint8_t zero = 0;
+        if (!write(&zero, 1, false)) return;
+        if (!write(webSocketResponse, messageLength, false)) return;
+        uint8_t effeff = 0xff;
+        write(&effeff, 1, true);
+        return;
+    }
+    sendHybi(HybiPacketDecoder::OPCODE_TEXT, reinterpret_cast<const uint8_t*>(webSocketResponse), messageLength);
+}
+
+void Connection::send(const uint8_t* data, size_t length) {
+    _server.checkThread();
+    if (_shutdown) {
+        if (_shutdownByUser) {
+            LS_ERROR(_logger, "Client wrote to connection after closing it");
+        }
+        return;
+    }
+    if (_state == HANDLING_HIXIE_WEBSOCKET) {
+        LS_ERROR(_logger, "Hixie does not support binary");
+        return;
+    }
+    sendHybi(HybiPacketDecoder::OPCODE_BINARY, data, length);
+}
+
+void Connection::sendHybi(int opcode, const uint8_t* webSocketResponse, size_t messageLength) {
+    uint8_t firstByte = 0x80 | opcode;
+    if (!write(&firstByte, 1, false)) return;
+    if (messageLength < 126) {
+        uint8_t nextByte = messageLength; // No MASK bit set.
+        if (!write(&nextByte, 1, false)) return;
+    } else if (messageLength < 65536) {
+        uint8_t nextByte = 126; // No MASK bit set.
+        if (!write(&nextByte, 1, false)) return;
+        auto lengthBytes = htons(messageLength);
+        if (!write(&lengthBytes, 2, false)) return;
+    } else {
+        uint8_t nextByte = 127; // No MASK bit set.
+        if (!write(&nextByte, 1, false)) return;
+        uint64_t lengthBytes = __bswap_64(messageLength);
+        if (!write(&lengthBytes, 8, false)) return;
+    }
+    write(webSocketResponse, messageLength, true);
+}
+
+std::shared_ptr<Credentials> Connection::credentials() const {
+    _server.checkThread();
+    return _request ? _request->credentials() : std::shared_ptr<Credentials>();
+}
+
+void Connection::handleHixieWebSocket() {
+    if (_inBuf.empty()) {
+        return;
+    }
+    size_t messageStart = 0;
+    while (messageStart < _inBuf.size()) {
+        if (_inBuf[messageStart] != 0) {
+            LS_WARNING(_logger, "Error in WebSocket input stream (got " << (int)_inBuf[messageStart] << ")");
+            closeInternal();
+            return;
+        }
+        // TODO: UTF-8
+        size_t endOfMessage = 0;
+        for (size_t i = messageStart + 1; i < _inBuf.size(); ++i) {
+            if (_inBuf[i] == 0xff) {
+                endOfMessage = i;
+                break;
+            }
+        }
+        if (endOfMessage != 0) {
+            _inBuf[endOfMessage] = 0;
+            handleWebSocketTextMessage(reinterpret_cast<const char*>(&_inBuf[messageStart + 1]));
+            messageStart = endOfMessage + 1;
+        } else {
+            break;
+        }
+    }
+    if (messageStart != 0) {
+        _inBuf.erase(_inBuf.begin(), _inBuf.begin() + messageStart);
+    }
+    if (_inBuf.size() > MaxWebsocketMessageSize) {
+        LS_WARNING(_logger, "WebSocket message too long");
+        closeInternal();
+    }
+}
+
+void Connection::handleHybiWebSocket() {
+    if (_inBuf.empty()) {
+        return;
+    }
+    HybiPacketDecoder decoder(*_logger, _inBuf);
+    bool done = false;
+    while (!done) {
+        std::vector<uint8_t> decodedMessage;
+        switch (decoder.decodeNextMessage(decodedMessage)) {
+        default:
+            closeInternal();
+            LS_WARNING(_logger, "Unknown HybiPacketDecoder state");
+            return;
+        case HybiPacketDecoder::Error:
+            closeInternal();
+            return;
+        case HybiPacketDecoder::TextMessage:
+            decodedMessage.push_back(0);  // avoids a copy
+            handleWebSocketTextMessage(reinterpret_cast<const char*>(&decodedMessage[0]));
+            break;
+        case HybiPacketDecoder::BinaryMessage:
+            handleWebSocketBinaryMessage(decodedMessage);
+            break;
+        case HybiPacketDecoder::Ping:
+            sendHybi(HybiPacketDecoder::OPCODE_PONG, &decodedMessage[0], decodedMessage.size());
+            break;
+        case HybiPacketDecoder::NoMessage:
+            done = true;
+            break;
+        case HybiPacketDecoder::Close:
+            LS_DEBUG(_logger, "Received WebSocket close");
+            closeInternal();
+            return;
+        }
+    }
+    if (decoder.numBytesDecoded() != 0) {
+        _inBuf.erase(_inBuf.begin(), _inBuf.begin() + decoder.numBytesDecoded());
+    }
+    if (_inBuf.size() > MaxWebsocketMessageSize) {
+        LS_WARNING(_logger, "WebSocket message too long");
+        closeInternal();
+    }
+}
+
+void Connection::handleWebSocketTextMessage(const char* message) {
+    LS_DEBUG(_logger, "Got text web socket message: '" << message << "'");
+    if (_webSocketHandler) {
+        _webSocketHandler->onData(this, message);
+    }
+}
+
+void Connection::handleWebSocketBinaryMessage(const std::vector<uint8_t>& message) {
+    LS_DEBUG(_logger, "Got binary web socket message (size: " << message.size() << ")");
+    if (_webSocketHandler) {
+        _webSocketHandler->onData(this, &message[0], message.size());
+    }
+}
+
+bool Connection::sendError(ResponseCode errorCode, const std::string& body) {
+    assert(_state != HANDLING_HIXIE_WEBSOCKET);
+    auto errorNumber = static_cast<int>(errorCode);
+    auto message = ::name(errorCode);
+    bufferResponseAndCommonHeaders(errorCode);
+    auto errorContent = findEmbeddedContent("/_error.html");
+    std::string document;
+    if (errorContent) {
+        document.assign(errorContent->data, errorContent->data + errorContent->length);
+        replace(document, "%%ERRORCODE%%", toString(errorNumber));
+        replace(document, "%%MESSAGE%%", message);
+        replace(document, "%%BODY%%", body);
+    } else {
+        std::stringstream documentStr;
+        documentStr << "<html><head><title>" << errorNumber << " - " << message << "</title></head>"
+                << "<body><h1>" << errorNumber << " - " << message << "</h1>"
+                << "<div>" << body << "</div><hr/><div><i>Powered by seasocks</i></div></body></html>";
+        document = documentStr.str();
+    }
+    bufferLine("Content-Length: " + toString(document.length()));
+    bufferLine("Connection: close");
+    bufferLine("");
+    bufferLine(document);
+    if (!flush()) {
+        return false;
+    }
+    closeWhenEmpty();
+    return true;
+}
+
+bool Connection::sendUnsupportedError(const std::string& reason) {
+    return sendError(ResponseCode::NotImplemented, reason);
+}
+
+bool Connection::send404() {
+    auto path = getRequestUri();
+    auto embedded = findEmbeddedContent(path);
+    if (embedded) {
+        return sendData(getContentType(path), embedded->data, embedded->length);
+    } else if (strcmp(path.c_str(), "/_livestats.js") == 0) {
+        auto stats = _server.getStatsDocument();
+        return sendData("text/javascript", stats.c_str(), stats.length());
+    } else {
+        return sendError(ResponseCode::NotFound, "Unable to find resource for: " + path);
+    }
+}
+
+bool Connection::sendBadRequest(const std::string& reason) {
+    return sendError(ResponseCode::BadRequest, reason);
+}
+
+bool Connection::sendISE(const std::string& error) {
+    return sendError(ResponseCode::InternalServerError, error);
+}
+
+bool Connection::processHeaders(uint8_t* first, uint8_t* last) {
+    // Ideally we'd copy off [first, last] now into a header structure here.
+    // Be careful about lifetimes though and multiple requests coming in, should
+    // we ever support HTTP pipelining and/or long-lived requests.
+    char* requestLine = extractLine(first, last);
+    assert(requestLine != NULL);
+
+    LS_ACCESS(_logger, "Request: " << requestLine);
+
+    const char* verbText = shift(requestLine);
+    if (!verbText) {
+        return sendBadRequest("Malformed request line");
+    }
+    auto verb = Request::verb(verbText);
+    if (verb == Request::Verb::Invalid) {
+        return sendBadRequest("Malformed request line");
+    }
+    const char* requestUri = shift(requestLine);
+    if (requestUri == NULL) {
+        return sendBadRequest("Malformed request line");
+    }
+
+    const char* httpVersion = shift(requestLine);
+    if (httpVersion == NULL) {
+        return sendBadRequest("Malformed request line");
+    }
+    if (strcmp(httpVersion, "HTTP/1.1") != 0) {
+        return sendUnsupportedError("Unsupported HTTP version");
+    }
+    if (*requestLine != 0) {
+        return sendBadRequest("Trailing crap after http version");
+    }
+
+    HeaderMap headers(31);
+    while (first < last) {
+        char* colonPos = NULL;
+        char* headerLine = extractLine(first, last, &colonPos);
+        assert(headerLine != NULL);
+        if (colonPos == NULL) {
+            return sendBadRequest("Malformed header");
+        }
+        *colonPos = 0;
+        const char* key = headerLine;
+        const char* value = skipWhitespace(colonPos + 1);
+        LS_DEBUG(_logger, "Key: " << key << " || " << value);
+#if HAVE_UNORDERED_MAP_EMPLACE
+        headers.emplace(key, value);
+#else
+        headers.insert(std::make_pair(key, value));
+#endif
+    }
+
+    if (headers.count("Connection") && headers.count("Upgrade")
+            && hasConnectionType(headers["Connection"], "Upgrade")
+            && caseInsensitiveSame(headers["Upgrade"], "websocket")) {
+        LS_INFO(_logger, "Websocket request for " << requestUri << "'");
+        if (verb != Request::Verb::Get) {
+            return sendBadRequest("Non-GET WebSocket request");
+        }
+        _webSocketHandler = _server.getWebSocketHandler(requestUri);
+        if (!_webSocketHandler) {
+            LS_WARNING(_logger, "Couldn't find WebSocket end point for '" << requestUri << "'");
+            return send404();
+        }
+        verb = Request::Verb::WebSocket;
+    }
+
+    _request.reset(new PageRequest(_address, requestUri, verb, std::move(headers)));
+
+    const EmbeddedContent *embedded = findEmbeddedContent(requestUri);
+    if (verb == Request::Verb::Get && embedded) {
+        // MRG: one day, this could be a request handler.
+        return sendData(getContentType(requestUri), embedded->data, embedded->length);
+    }
+
+    if (_request->contentLength() > MaxBufferSize) {
+        return sendBadRequest("Content length too long");
+    }
+    if (_request->contentLength() == 0) {
+        return handlePageRequest();
+    }
+    _state = BUFFERING_POST_DATA;
+    return true;
+}
+
+bool Connection::handlePageRequest() {
+    std::shared_ptr<Response> response;
+    try {
+        response = _server.handle(*_request);
+    } catch (const std::exception& e) {
+        LS_ERROR(_logger, "page error: " << e.what());
+        return sendISE(e.what());
+    } catch (...) {
+        LS_ERROR(_logger, "page error: (unknown)");
+        return sendISE("(unknown)");
+    }
+    auto uri = _request->getRequestUri();
+    if (!response && _request->verb() == Request::Verb::WebSocket) {
+        _webSocketHandler = _server.getWebSocketHandler(uri.c_str());
+        auto webSocketVersion = atoi(_request->getHeader("Sec-WebSocket-Version").c_str());
+        if (!_webSocketHandler) {
+            LS_WARNING(_logger, "Couldn't find WebSocket end point for '" << uri << "'");
+            return send404();
+        }
+        if (webSocketVersion == 0) {
+            // Hixie
+            _state = READING_WEBSOCKET_KEY3;
+            return true;
+        }
+        auto hybiKey = _request->getHeader("Sec-WebSocket-Key");
+        return handleHybiHandshake(webSocketVersion, hybiKey);
+    }
+    return sendResponse(response);
+}
+
+bool Connection::sendResponse(std::shared_ptr<Response> response) {
+    const auto requestUri = _request->getRequestUri();
+    if (response == Response::unhandled()) {
+        return sendStaticData();
+    }
+    if (response->responseCode() == ResponseCode::NotFound) {
+        // TODO: better here; we use this purely to serve our own embedded content.
+        return send404();
+    } else if (!isOk(response->responseCode())) {
+        return sendError(response->responseCode(), response->payload());
+    }
+
+    bufferResponseAndCommonHeaders(response->responseCode());
+    bufferLine("Content-Length: " + toString(response->payloadSize()));
+    bufferLine("Content-Type: " + response->contentType());
+    if (response->keepConnectionAlive()) {
+        bufferLine("Connection: keep-alive");
+    } else {
+        bufferLine("Connection: close");
+    }
+    bufferLine("Last-Modified: " + now());
+    bufferLine("Cache-Control: no-store");
+    bufferLine("Pragma: no-cache");
+    bufferLine("Expires: " + now());
+    auto headers = response->getAdditionalHeaders();
+    for (auto it = headers.begin(); it != headers.end(); ++it) {
+        bufferLine(it->first + ": " + it->second);
+    }
+    bufferLine("");
+
+    if (!write(response->payload(), response->payloadSize(), true)) {
+        return false;
+    }
+    if (!response->keepConnectionAlive()) {
+        closeWhenEmpty();
+    }
+    return true;
+}
+
+bool Connection::handleHybiHandshake(
+        int webSocketVersion,
+        const std::string& webSocketKey) {
+    if (webSocketVersion != 8 && webSocketVersion != 13) {
+        return sendBadRequest("Invalid websocket version");
+    }
+    LS_DEBUG(_logger, "Got a hybi-8 websocket with key=" << webSocketKey);
+
+    LS_DEBUG(_logger, "Attempting websocket upgrade");
+
+    bufferResponseAndCommonHeaders(ResponseCode::WebSocketProtocolHandshake);
+    bufferLine("Upgrade: websocket");
+    bufferLine("Connection: Upgrade");
+    bufferLine("Sec-WebSocket-Accept: " + getAcceptKey(webSocketKey));
+    bufferLine("");
+    flush();
+
+    if (_webSocketHandler) {
+        _webSocketHandler->onConnect(this);
+    }
+    _state = HANDLING_HYBI_WEBSOCKET;
+    return true;
+}
+
+bool Connection::parseRange(const std::string& rangeStr, Range& range) const {
+    size_t minusPos = rangeStr.find('-');
+    if (minusPos == std::string::npos) {
+        LS_WARNING(_logger, "Bad range: '" << rangeStr << "'");
+        return false;
+    }
+    if (minusPos == 0) {
+        // A range like "-500" means 500 bytes from end of file to end.
+        range.start = atoi(rangeStr.c_str());
+        range.end = std::numeric_limits<long>::max();
+        return true;
+    } else {
+        range.start = atoi(rangeStr.substr(0, minusPos).c_str());
+        if (minusPos == rangeStr.size()-1) {
+            range.end = std::numeric_limits<long>::max();
+        } else {
+            range.end = atoi(rangeStr.substr(minusPos + 1).c_str());
+        }
+        return true;
+    }
+    return false;
+}
+
+bool Connection::parseRanges(const std::string& range, std::list<Range>& ranges) const {
+    static const std::string expectedPrefix = "bytes=";
+    if (range.length() < expectedPrefix.length() || range.substr(0, expectedPrefix.length()) != expectedPrefix) {
+        LS_WARNING(_logger, "Bad range request prefix: '" << range << "'");
+        return false;
+    }
+    auto rangesText = split(range.substr(expectedPrefix.length()), ',');
+    for (auto it = rangesText.begin(); it != rangesText.end(); ++it) {
+        Range r;
+        if (!parseRange(*it, r)) {
+            return false;
+        }
+        ranges.push_back(r);
+    }
+    return !ranges.empty();
+}
+
+// Sends HTTP 200 or 206, content-length, and range info as needed. Returns the actual file ranges
+// needing sending.
+std::list<Connection::Range> Connection::processRangesForStaticData(const std::list<Range>& origRanges, long fileSize) {
+    if (origRanges.empty()) {
+        // Easy case: a non-range request.
+        bufferResponseAndCommonHeaders(ResponseCode::Ok);
+        bufferLine("Content-Length: " + toString(fileSize));
+        return { Range { 0, fileSize - 1 } };
+    }
+
+    // Partial content request.
+    bufferResponseAndCommonHeaders(ResponseCode::PartialContent);
+    int contentLength = 0;
+    std::ostringstream rangeLine;
+    rangeLine << "Content-Range: bytes ";
+    std::list<Range> sendRanges;
+    for (auto rangeIter = origRanges.cbegin(); rangeIter != origRanges.cend(); ++rangeIter) {
+        Range actualRange = *rangeIter;
+        if (actualRange.start < 0) {
+            actualRange.start += fileSize;
+        }
+        if (actualRange.start >= fileSize) {
+            actualRange.start = fileSize - 1;
+        }
+        if (actualRange.end >= fileSize) {
+            actualRange.end = fileSize - 1;
+        }
+        contentLength += actualRange.length();
+        sendRanges.push_back(actualRange);
+        rangeLine << actualRange.start << "-" << actualRange.end;
+    }
+    rangeLine << "/" << fileSize;
+    bufferLine(rangeLine.str());
+    bufferLine("Content-Length: " + toString(contentLength));
+    return sendRanges;
+}
+
+bool Connection::sendStaticData() {
+    // TODO: fold this into the handler way of doing things.
+    std::string path = _server.getStaticPath() + getRequestUri();
+    auto rangeHeader = getHeader("Range");
+    // Trim any trailing queries.
+    size_t queryPos = path.find('?');
+    if (queryPos != path.npos) {
+        path.resize(queryPos);
+    }
+    if (*path.rbegin() == '/') {
+        path += "index.html";
+    }
+    RaiiFd input(path.c_str());
+    struct stat stat;
+    if (!input.ok() || ::fstat(input, &stat) == -1) {
+        return send404();
+    }
+    std::list<Range> ranges;
+    if (!rangeHeader.empty() && !parseRanges(rangeHeader, ranges)) {
+        return sendBadRequest("Bad range header");
+    }
+    ranges = processRangesForStaticData(ranges, stat.st_size);
+    bufferLine("Content-Type: " + getContentType(path));
+    bufferLine("Connection: keep-alive");
+    bufferLine("Accept-Ranges: bytes");
+    bufferLine("Last-Modified: " + webtime(stat.st_mtime));
+    if (!isCacheable(path)) {
+        bufferLine("Cache-Control: no-store");
+        bufferLine("Pragma: no-cache");
+        bufferLine("Expires: " + now());
+    }
+    bufferLine("");
+    if (!flush()) {
+        return false;
+    }
+
+    for (auto rangeIter = ranges.cbegin(); rangeIter != ranges.cend(); ++rangeIter) {
+        if (::lseek(input, rangeIter->start, SEEK_SET) == -1) {
+            // We've (probably) already sent data.
+            return false;
+        }
+        auto bytesLeft = rangeIter->length();
+        while (bytesLeft) {
+            char buf[ReadWriteBufferSize];
+            auto bytesRead = ::read(input, buf, std::min(sizeof(buf), bytesLeft));
+            if (bytesRead <= 0) {
+                const static std::string unexpectedEof("Unexpected EOF");
+                LS_ERROR(_logger, "Error reading file: " << (bytesRead == 0 ? unexpectedEof : getLastError()));
+                // We can't send an error document as we've sent the header.
+                return false;
+            }
+            bytesLeft -= bytesRead;
+            if (!write(buf, bytesRead, true)) {
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+bool Connection::sendData(const std::string& type, const char* start, size_t size) {
+    bufferResponseAndCommonHeaders(ResponseCode::Ok);
+    bufferLine("Content-Type: " + type);
+    bufferLine("Content-Length: " + toString(size));
+    bufferLine("Connection: keep-alive");
+    bufferLine("");
+    bool result = write(start, size, true);
+    return result;
+}
+
+void Connection::bufferResponseAndCommonHeaders(ResponseCode code) {
+    auto responseCodeInt = static_cast<int>(code);
+    auto responseCodeName = ::name(code);
+    auto response = std::string("HTTP/1.1 " + toString(responseCodeInt) + " " + responseCodeName);
+    LS_ACCESS(_logger, "Response: " << response);
+    bufferLine(response);
+    bufferLine("Server: " SEASOCKS_VERSION_STRING);
+    bufferLine("Date: " + now());
+    bufferLine("Access-Control-Allow-Origin: *");
+}
+
+void Connection::setLinger() {
+    if (_fd == -1) {
+        return;
+    }
+    const int secondsToLinger = 1;
+    struct linger linger = { true, secondsToLinger };
+    if (::setsockopt(_fd, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)) == -1) {
+        LS_INFO(_logger, "Unable to set linger on socket");
+    }
+}
+
+bool Connection::hasHeader(const std::string& header) const {
+    return _request ? _request->hasHeader(header) : false;
+}
+
+std::string Connection::getHeader(const std::string& header) const {
+    return _request ? _request->getHeader(header) : "";
+}
+
+const std::string& Connection::getRequestUri() const {
+    static const std::string empty;
+    return _request ? _request->getRequestUri() : empty;
+}
+
+}  // seasocks
diff --git a/third_party/seasocks/src/main/c/HybiAccept.cpp b/third_party/seasocks/src/main/c/HybiAccept.cpp
new file mode 100644
index 0000000..8c2dbde
--- /dev/null
+++ b/third_party/seasocks/src/main/c/HybiAccept.cpp
@@ -0,0 +1,49 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "internal/Base64.h"
+#include "internal/HybiAccept.h"
+
+#include "sha1/sha1.h"
+
+#include <arpa/inet.h>
+
+namespace seasocks {
+
+static const std::string magicString("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
+
+std::string getAcceptKey(const std::string& challenge) {
+    auto fullString = challenge + magicString;
+    SHA1 hasher;
+    hasher.Input(fullString.c_str(), fullString.size());
+    unsigned hash[5];
+    hasher.Result(hash);
+    for (int i = 0; i < 5; ++i) {
+        hash[i] = htonl(hash[i]);
+    }
+    return base64Encode(hash, sizeof(hash));
+}
+
+}
diff --git a/third_party/seasocks/src/main/c/HybiPacketDecoder.cpp b/third_party/seasocks/src/main/c/HybiPacketDecoder.cpp
new file mode 100644
index 0000000..f0fdefe
--- /dev/null
+++ b/third_party/seasocks/src/main/c/HybiPacketDecoder.cpp
@@ -0,0 +1,102 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "internal/HybiPacketDecoder.h"
+#include "internal/LogStream.h"
+
+#include <arpa/inet.h>
+
+namespace seasocks {
+
+HybiPacketDecoder::HybiPacketDecoder(Logger& logger, const std::vector<uint8_t>& buffer) :
+    _logger(logger),
+    _buffer(buffer),
+    _messageStart(0) {
+}
+
+HybiPacketDecoder::MessageState HybiPacketDecoder::decodeNextMessage(std::vector<uint8_t>& messageOut) {
+    if (_messageStart + 1 >= _buffer.size()) {
+        return NoMessage;
+    }
+    if ((_buffer[_messageStart] & 0x80) == 0) {
+        // FIN bit is not clear...
+        // TODO: support
+        LS_WARNING(&_logger, "Received hybi frame without FIN bit set - unsupported");
+        return Error;
+    }
+    if ((_buffer[_messageStart] & (7<<4)) != 0) {
+        LS_WARNING(&_logger, "Received hybi frame with reserved bits set - error");
+        return Error;
+    }
+    auto opcode = _buffer[_messageStart] & 0xf;
+    size_t payloadLength = _buffer[_messageStart + 1] & 0x7f;
+    auto maskBit = _buffer[_messageStart + 1] & 0x80;
+    auto ptr = _messageStart + 2;
+    if (payloadLength == 126) {
+        if (_buffer.size() < 4) { return NoMessage; }
+        payloadLength = htons(*reinterpret_cast<const uint16_t*>(&_buffer[ptr]));
+        ptr += 2;
+    } else if (payloadLength == 127) {
+        if (_buffer.size() < 10) { return NoMessage; }
+        payloadLength = __bswap_64(*reinterpret_cast<const uint64_t*>(&_buffer[ptr]));
+        ptr += 8;
+    }
+    uint32_t mask = 0;
+    if (maskBit) {
+        // MASK is set.
+        if (_buffer.size() < ptr + 4) { return NoMessage; }
+        mask = htonl(*reinterpret_cast<const uint32_t*>(&_buffer[ptr]));
+        ptr += 4;
+    }
+    auto bytesLeftInBuffer = _buffer.size() - ptr;
+    if (payloadLength > bytesLeftInBuffer) { return NoMessage; }
+
+    messageOut.clear();
+    messageOut.reserve(payloadLength);
+    for (auto i = 0u; i < payloadLength; ++i) {
+        auto byteShift = (3 - (i & 3)) * 8;
+        messageOut.push_back(static_cast<char>((_buffer[ptr++] ^ (mask >> byteShift)) & 0xff));
+    }
+    _messageStart = ptr;
+    switch (opcode) {
+    default:
+        LS_WARNING(&_logger, "Received hybi frame with unknown opcode " << opcode);
+        return Error;
+    case OPCODE_TEXT:
+        return TextMessage;
+    case OPCODE_BINARY:
+        return BinaryMessage;
+    case OPCODE_PING:
+        return Ping;
+    case OPCODE_CLOSE:
+        return Close;
+    }
+}
+
+size_t HybiPacketDecoder::numBytesDecoded() const {
+    return _messageStart;
+}
+
+}
diff --git a/third_party/seasocks/src/main/c/Logger.cpp b/third_party/seasocks/src/main/c/Logger.cpp
new file mode 100644
index 0000000..347ae30
--- /dev/null
+++ b/third_party/seasocks/src/main/c/Logger.cpp
@@ -0,0 +1,76 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "internal/Debug.h"
+
+#include "seasocks/Logger.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+
+namespace seasocks {
+
+const int MAX_MESSAGE_LENGTH = 1024;
+
+#define PRINT_TO_MESSAGEBUF() \
+    char messageBuf[MAX_MESSAGE_LENGTH]; \
+    va_list args; \
+    va_start(args, message); \
+    vsnprintf(messageBuf, MAX_MESSAGE_LENGTH, message, args); \
+    va_end(args)
+
+void Logger::debug(const char* message, ...) {
+#ifdef LOG_DEBUG_INFO
+    PRINT_TO_MESSAGEBUF();
+    log(DEBUG, messageBuf);
+#endif
+}
+
+void Logger::access(const char* message, ...) {
+    PRINT_TO_MESSAGEBUF();
+    log(ACCESS, messageBuf);
+}
+
+void Logger::info(const char* message, ...) {
+    PRINT_TO_MESSAGEBUF();
+    log(INFO, messageBuf);
+}
+
+void Logger::warning(const char* message, ...) {
+    PRINT_TO_MESSAGEBUF();
+    log(WARNING, messageBuf);
+}
+
+void Logger::error(const char* message, ...) {
+    PRINT_TO_MESSAGEBUF();
+    log(ERROR, messageBuf);
+}
+
+void Logger::severe(const char* message, ...) {
+    PRINT_TO_MESSAGEBUF();
+    log(SEVERE, messageBuf);
+}
+
+}  // namespace seasocks
diff --git a/third_party/seasocks/src/main/c/PageRequest.cpp b/third_party/seasocks/src/main/c/PageRequest.cpp
new file mode 100644
index 0000000..a2a5313
--- /dev/null
+++ b/third_party/seasocks/src/main/c/PageRequest.cpp
@@ -0,0 +1,62 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "internal/PageRequest.h"
+
+#include <cstdlib>
+#include <cstring>
+
+namespace seasocks {
+
+PageRequest::PageRequest(
+        const sockaddr_in& remoteAddress,
+        const std::string& requestUri,
+        Verb verb,
+        HeaderMap&& headers) :
+            _credentials(std::shared_ptr<Credentials>(new Credentials())),
+            _remoteAddress(remoteAddress),
+            _requestUri(requestUri),
+            _verb(verb),
+            _headers(std::move(headers)),
+            _contentLength(getIntHeader("Content-Length")) {
+}
+
+bool PageRequest::consumeContent(std::vector<uint8_t>& buffer) {
+    if (buffer.size() < _contentLength) return false;
+    if (buffer.size() == _contentLength) {
+        _content.swap(buffer);
+    } else {
+        _content.assign(buffer.begin(), buffer.begin() + _contentLength);
+        buffer.erase(buffer.begin(), buffer.begin() + _contentLength);
+    }
+    return true;
+}
+
+int PageRequest::getIntHeader(const std::string& name) const {
+    auto iter = _headers.find(name);
+    return iter == _headers.end() ? 0 : atoi(iter->second.c_str());
+}
+
+}  // namespace seasocks
diff --git a/third_party/seasocks/src/main/c/Response.cpp b/third_party/seasocks/src/main/c/Response.cpp
new file mode 100644
index 0000000..2eddfe2
--- /dev/null
+++ b/third_party/seasocks/src/main/c/Response.cpp
@@ -0,0 +1,63 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "internal/ConcreteResponse.h"
+
+#include "seasocks/Response.h"
+
+using namespace seasocks;
+
+namespace seasocks {
+
+std::shared_ptr<Response> Response::unhandled() {
+    static std::shared_ptr<Response> unhandled;
+    return unhandled;
+}
+
+std::shared_ptr<Response> Response::notFound() {
+    static std::shared_ptr<Response> notFound(new ConcreteResponse(ResponseCode::NotFound, "Not found", "text/plain", Response::Headers(), false));
+    return notFound;
+}
+
+std::shared_ptr<Response> Response::error(ResponseCode code, const std::string& reason) {
+    return std::shared_ptr<Response>(new ConcreteResponse(code, reason, "text/plain", Response::Headers(), false));
+}
+
+std::shared_ptr<Response> Response::textResponse(const std::string& response) {
+    return std::shared_ptr<Response>(
+            new ConcreteResponse(ResponseCode::Ok, response, "text/plain", Response::Headers(), true));
+}
+
+std::shared_ptr<Response> Response::jsonResponse(const std::string& response) {
+    return std::shared_ptr<Response>(
+            new ConcreteResponse(ResponseCode::Ok, response, "application/json", Response::Headers(), true));
+}
+
+std::shared_ptr<Response> Response::htmlResponse(const std::string& response) {
+    return std::shared_ptr<Response>(
+            new ConcreteResponse(ResponseCode::Ok, response, "text/html", Response::Headers(), true));
+}
+
+}
diff --git a/third_party/seasocks/src/main/c/Server.cpp b/third_party/seasocks/src/main/c/Server.cpp
new file mode 100644
index 0000000..5ad1c30
--- /dev/null
+++ b/third_party/seasocks/src/main/c/Server.cpp
@@ -0,0 +1,568 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "internal/LogStream.h"
+
+#include "seasocks/Connection.h"
+#include "seasocks/Logger.h"
+#include "seasocks/Server.h"
+#include "seasocks/PageHandler.h"
+#include "seasocks/StringUtil.h"
+#include "seasocks/util/Json.h"
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#include <sys/epoll.h>
+#include <sys/eventfd.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/syscall.h>
+
+#include <memory>
+#include <stdexcept>
+#include <string.h>
+#include <unistd.h>
+
+namespace {
+
+struct EventBits {
+    uint32_t bits;
+    explicit EventBits(uint32_t bits) : bits(bits) {}
+};
+
+std::ostream& operator <<(std::ostream& o, const EventBits& b) {
+    uint32_t bits = b.bits;
+#define DO_BIT(NAME) \
+        do { if (bits & (NAME)) { if (bits != b.bits) {o << ", "; } o << #NAME; bits &= ~(NAME); } } while (0)
+    DO_BIT(EPOLLIN);
+    DO_BIT(EPOLLPRI);
+    DO_BIT(EPOLLOUT);
+    DO_BIT(EPOLLRDNORM);
+    DO_BIT(EPOLLRDBAND);
+    DO_BIT(EPOLLWRNORM);
+    DO_BIT(EPOLLWRBAND);
+    DO_BIT(EPOLLMSG);
+    DO_BIT(EPOLLERR);
+    DO_BIT(EPOLLHUP);
+#ifdef EPOLLRDHUP
+    DO_BIT(EPOLLRDHUP);
+#endif
+    DO_BIT(EPOLLONESHOT);
+    DO_BIT(EPOLLET);
+#undef DO_BIT
+    return o;
+}
+
+const int EpollTimeoutMillis = 500;  // Twice a second is ample.
+const int DefaultLameConnectionTimeoutSeconds = 10;
+int gettid() {
+    return syscall(SYS_gettid);
+}
+
+}
+
+namespace seasocks {
+
+Server::Server(std::shared_ptr<Logger> logger)
+: _logger(logger), _listenSock(-1), _epollFd(-1), _eventFd(-1),
+  _maxKeepAliveDrops(0),
+  _lameConnectionTimeoutSeconds(DefaultLameConnectionTimeoutSeconds),
+  _nextDeadConnectionCheck(0), _threadId(0), _terminate(false),
+  _expectedTerminate(false) {
+
+    _epollFd = epoll_create(10);
+    if (_epollFd == -1) {
+        LS_ERROR(_logger, "Unable to create epoll: " << getLastError());
+        return;
+    }
+
+    _eventFd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
+    if (_eventFd == -1) {
+        LS_ERROR(_logger, "Unable to create event FD: " << getLastError());
+        return;
+    }
+
+    epoll_event eventWake = { EPOLLIN, { &_eventFd } };
+    if (epoll_ctl(_epollFd, EPOLL_CTL_ADD, _eventFd, &eventWake) == -1) {
+        LS_ERROR(_logger, "Unable to add wake socket to epoll: " << getLastError());
+        return;
+    }
+}
+
+Server::~Server() {
+    LS_INFO(_logger, "Server destruction");
+    shutdown();
+    // Only shut the eventfd and epoll at the very end
+    if (_eventFd != -1) {
+        close(_eventFd);
+    }
+    if (_epollFd != -1) {
+        close(_epollFd);
+    }
+}
+
+void Server::shutdown() {
+    // Stop listening to any further incoming connections.
+    if (_listenSock != -1) {
+        close(_listenSock);
+        _listenSock = -1;
+    }
+    // Disconnect and close any current connections.
+    while (!_connections.empty()) {
+        // Deleting the connection closes it and removes it from 'this'.
+        Connection* toBeClosed = _connections.begin()->first;
+        toBeClosed->setLinger();
+        delete toBeClosed;
+    }
+}
+
+bool Server::makeNonBlocking(int fd) const {
+    int yesPlease = 1;
+    if (ioctl(fd, FIONBIO, &yesPlease) != 0) {
+        LS_ERROR(_logger, "Unable to make FD non-blocking: " << getLastError());
+        return false;
+    }
+    return true;
+}
+
+bool Server::configureSocket(int fd) const {
+    if (!makeNonBlocking(fd)) {
+        return false;
+    }
+    const int yesPlease = 1;
+    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yesPlease, sizeof(yesPlease)) == -1) {
+        LS_ERROR(_logger, "Unable to set reuse socket option: " << getLastError());
+        return false;
+    }
+    if (_maxKeepAliveDrops > 0) {
+        if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &yesPlease, sizeof(yesPlease)) == -1) {
+            LS_ERROR(_logger, "Unable to enable keepalive: " << getLastError());
+            return false;
+        }
+        const int oneSecond = 1;
+        if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &oneSecond, sizeof(oneSecond)) == -1) {
+            LS_ERROR(_logger, "Unable to set idle probe: " << getLastError());
+            return false;
+        }
+        if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &oneSecond, sizeof(oneSecond)) == -1) {
+            LS_ERROR(_logger, "Unable to set idle interval: " << getLastError());
+            return false;
+        }
+        if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &_maxKeepAliveDrops, sizeof(_maxKeepAliveDrops)) == -1) {
+            LS_ERROR(_logger, "Unable to set keep alive count: " << getLastError());
+            return false;
+        }
+    }
+    return true;
+}
+
+void Server::terminate() {
+    _expectedTerminate = true;
+    _terminate = true;
+    uint64_t one = 1;
+    if (_eventFd != -1 && ::write(_eventFd, &one, sizeof(one)) == -1) {
+        LS_ERROR(_logger, "Unable to post a wake event: " << getLastError());
+    }
+}
+
+bool Server::startListening(int port) {
+    return startListening(INADDR_ANY, port);
+}
+
+bool Server::startListening(uint32_t hostAddr, int port) {
+    if (_epollFd == -1 || _eventFd == -1) {
+        LS_ERROR(_logger, "Unable to serve, did not initialize properly.");
+        return false;
+    }
+
+    _listenSock = socket(AF_INET, SOCK_STREAM, 0);
+    if (_listenSock == -1) {
+        LS_ERROR(_logger, "Unable to create listen socket: " << getLastError());
+        return false;
+    }
+    if (!configureSocket(_listenSock)) {
+        return false;
+    }
+    sockaddr_in sock;
+    memset(&sock, 0, sizeof(sock));
+    sock.sin_port = htons(port);
+    sock.sin_addr.s_addr = htonl(hostAddr);
+    sock.sin_family = AF_INET;
+    if (bind(_listenSock, reinterpret_cast<const sockaddr*>(&sock), sizeof(sock)) == -1) {
+        LS_ERROR(_logger, "Unable to bind socket: " << getLastError());
+        return false;
+    }
+    if (listen(_listenSock, 5) == -1) {
+        LS_ERROR(_logger, "Unable to listen on socket: " << getLastError());
+        return false;
+    }
+    epoll_event event = { EPOLLIN, { this } };
+    if (epoll_ctl(_epollFd, EPOLL_CTL_ADD, _listenSock, &event) == -1) {
+        LS_ERROR(_logger, "Unable to add listen socket to epoll: " << getLastError());
+        return false;
+    }
+
+    char buf[1024];
+    ::gethostname(buf, sizeof(buf));
+    LS_INFO(_logger, "Listening on http://" << buf << ":" << port << "/");
+
+    return true;
+}
+
+void Server::handlePipe() {
+    uint64_t dummy;
+    while (::read(_eventFd, &dummy, sizeof(dummy)) != -1) {
+        // Spin, draining the pipe until it returns EWOULDBLOCK or similar.
+    }
+    if (errno != EAGAIN || errno != EWOULDBLOCK) {
+        LS_ERROR(_logger, "Error from wakeFd read: " << getLastError());
+        _terminate = true;
+    }
+    // It's a "wake up" event; this will just cause the epoll loop to wake up.
+}
+
+Server::NewState Server::handleConnectionEvents(Connection* connection, uint32_t events) {
+    if (events & ~(EPOLLIN|EPOLLOUT|EPOLLHUP|EPOLLERR)) {
+        LS_WARNING(_logger, "Got unhandled epoll event (" << EventBits(events) << ") on connection: "
+                << formatAddress(connection->getRemoteAddress()));
+        return Close;
+    } else if (events & EPOLLERR) {
+        LS_INFO(_logger, "Error on socket (" << EventBits(events) << "): "
+                << formatAddress(connection->getRemoteAddress()));
+        return Close;
+    } else if (events & EPOLLHUP) {
+        LS_DEBUG(_logger, "Graceful hang-up (" << EventBits(events) << ") of socket: "
+                << formatAddress(connection->getRemoteAddress()));
+        return Close;
+    } else {
+        if (events & EPOLLOUT) {
+            connection->handleDataReadyForWrite();
+        }
+        if (events & EPOLLIN) {
+            connection->handleDataReadyForRead();
+        }
+    }
+    return KeepOpen;
+}
+
+void Server::checkAndDispatchEpoll(int epollMillis) {
+    const int maxEvents = 256;
+    epoll_event events[maxEvents];
+
+    std::list<Connection*> toBeDeleted;
+    int numEvents = epoll_wait(_epollFd, events, maxEvents, epollMillis);
+    if (numEvents == -1) {
+        if (errno != EINTR) {
+            LS_ERROR(_logger, "Error from epoll_wait: " << getLastError());
+        }
+        return;
+    }
+    if (numEvents == maxEvents) {
+        static time_t lastWarnTime = 0;
+        time_t now = time(NULL);
+        if (now - lastWarnTime >= 60) {
+            LS_WARNING(_logger, "Full event queue; may start starving connections. "
+                    "Will warn at most once a minute");
+            lastWarnTime = now;
+        }
+    }
+    for (int i = 0; i < numEvents; ++i) {
+        if (events[i].data.ptr == this) {
+            if (events[i].events & ~EPOLLIN) {
+                LS_SEVERE(_logger, "Got unexpected event on listening socket ("
+                        << EventBits(events[i].events) << ") - terminating");
+                _terminate = true;
+                break;
+            }
+            handleAccept();
+        } else if (events[i].data.ptr == &_eventFd) {
+            if (events[i].events & ~EPOLLIN) {
+                LS_SEVERE(_logger, "Got unexpected event on management pipe ("
+                        << EventBits(events[i].events) << ") - terminating");
+                _terminate = true;
+                break;
+            }
+            handlePipe();
+        } else {
+            auto connection = reinterpret_cast<Connection*>(events[i].data.ptr);
+            if (handleConnectionEvents(connection, events[i].events) == Close) {
+                toBeDeleted.push_back(connection);
+            }
+        }
+    }
+    // The connections are all deleted at the end so we've processed any other subject's
+    // closes etc before we call onDisconnect().
+    for (auto it = toBeDeleted.begin(); it != toBeDeleted.end(); ++it) {
+        auto connection = *it;
+        if (_connections.find(connection) == _connections.end()) {
+            LS_SEVERE(_logger, "Attempt to delete connection we didn't know about: " << (void*)connection
+                    << formatAddress(connection->getRemoteAddress()));
+            _terminate = true;
+            break;
+        }
+        LS_DEBUG(_logger, "Deleting connection: " << formatAddress(connection->getRemoteAddress()));
+        delete connection;
+    }
+}
+
+void Server::setStaticPath(const char* staticPath) {
+    LS_INFO(_logger, "Serving content from " << staticPath);
+    _staticPath = staticPath;
+}
+
+bool Server::serve(const char* staticPath, int port) {
+    setStaticPath(staticPath);
+    if (!startListening(port)) {
+        return false;
+    }
+
+    return loop();
+}
+
+bool Server::loop() {
+    if (_listenSock == -1) {
+        LS_ERROR(_logger, "Server not initialised");
+        return false;
+    }
+
+    // Stash away "the" server thread id.
+    _threadId = gettid();
+
+    while (!_terminate) {
+        // Always process events first to catch start up events.
+        processEventQueue();
+        checkAndDispatchEpoll(EpollTimeoutMillis);
+    }
+    // Reasonable effort to ensure anything enqueued during terminate has a chance to run.
+    processEventQueue();
+    LS_INFO(_logger, "Server terminating");
+    shutdown();
+    return _expectedTerminate;
+}
+
+Server::PollResult Server::poll(int millis) {
+    // Grab the thread ID on the first poll.
+    if (_threadId == 0) _threadId = gettid();
+    if (_threadId != gettid()) {
+        LS_ERROR(_logger, "poll() called from the wrong thread");
+        return PollResult::Error;
+    }
+    if (_listenSock == -1) {
+        LS_ERROR(_logger, "Server not initialised");
+        return PollResult::Error;
+    }
+    processEventQueue();
+    checkAndDispatchEpoll(millis);
+    if (!_terminate) return PollResult::Continue;
+
+    // Reasonable effort to ensure anything enqueued during terminate has a chance to run.
+    processEventQueue();
+    LS_INFO(_logger, "Server terminating");
+    shutdown();
+
+    return _expectedTerminate ? PollResult::Terminated : PollResult::Error;
+}
+
+void Server::processEventQueue() {
+    for (;;) {
+        std::shared_ptr<Runnable> runnable = popNextRunnable();
+        if (!runnable) break;
+        runnable->run();
+    }
+    time_t now = time(NULL);
+    if (now >= _nextDeadConnectionCheck) {
+        std::list<Connection*> toRemove;
+        for (auto it = _connections.cbegin(); it != _connections.cend(); ++it) {
+            time_t numSecondsSinceConnection = now - it->second;
+            auto connection = it->first;
+            if (connection->bytesReceived() == 0 && numSecondsSinceConnection >= _lameConnectionTimeoutSeconds) {
+                LS_INFO(_logger, formatAddress(connection->getRemoteAddress())
+                        << " : Killing lame connection - no bytes received after " << numSecondsSinceConnection << "s");
+                toRemove.push_back(connection);
+            }
+        }
+        for (auto it = toRemove.begin(); it != toRemove.end(); ++it) {
+            delete *it;
+        }
+    }
+}
+
+void Server::handleAccept() {
+    sockaddr_in address;
+    socklen_t addrLen = sizeof(address);
+    int fd = ::accept(_listenSock,
+            reinterpret_cast<sockaddr*>(&address),
+            &addrLen);
+    if (fd == -1) {
+        LS_ERROR(_logger, "Unable to accept: " << getLastError());
+        return;
+    }
+    if (!configureSocket(fd)) {
+        ::close(fd);
+        return;
+    }
+    LS_INFO(_logger, formatAddress(address) << " : Accepted on descriptor " << fd);
+    Connection* newConnection = new Connection(_logger, *this, fd, address);
+    epoll_event event = { EPOLLIN, { newConnection } };
+    if (epoll_ctl(_epollFd, EPOLL_CTL_ADD, fd, &event) == -1) {
+        LS_ERROR(_logger, "Unable to add socket to epoll: " << getLastError());
+        delete newConnection;
+        ::close(fd);
+        return;
+    }
+    _connections.insert(std::make_pair(newConnection, time(NULL)));
+}
+
+void Server::remove(Connection* connection) {
+    checkThread();
+    epoll_event event = { 0, { connection } };
+    if (epoll_ctl(_epollFd, EPOLL_CTL_DEL, connection->getFd(), &event) == -1) {
+        LS_ERROR(_logger, "Unable to remove from epoll: " << getLastError());
+    }
+    _connections.erase(connection);
+}
+
+bool Server::subscribeToWriteEvents(Connection* connection) {
+    epoll_event event = { EPOLLIN | EPOLLOUT, { connection } };
+    if (epoll_ctl(_epollFd, EPOLL_CTL_MOD, connection->getFd(), &event) == -1) {
+        LS_ERROR(_logger, "Unable to subscribe to write events: " << getLastError());
+        return false;
+    }
+    return true;
+}
+
+bool Server::unsubscribeFromWriteEvents(Connection* connection) {
+    epoll_event event = { EPOLLIN, { connection } };
+    if (epoll_ctl(_epollFd, EPOLL_CTL_MOD, connection->getFd(), &event) == -1) {
+        LS_ERROR(_logger, "Unable to unsubscribe from write events: " << getLastError());
+        return false;
+    }
+    return true;
+}
+
+void Server::addWebSocketHandler(const char* endpoint, std::shared_ptr<WebSocket::Handler> handler,
+        bool allowCrossOriginRequests) {
+    _webSocketHandlerMap[endpoint] = { handler, allowCrossOriginRequests };
+}
+
+void Server::addPageHandler(std::shared_ptr<PageHandler> handler) {
+    _pageHandlers.emplace_back(handler);
+}
+
+bool Server::isCrossOriginAllowed(const std::string &endpoint) const {
+    auto splits = split(endpoint, '?');
+    auto iter = _webSocketHandlerMap.find(splits[0]);
+    if (iter == _webSocketHandlerMap.end()) {
+        return false;
+    }
+    return iter->second.allowCrossOrigin;
+}
+
+std::shared_ptr<WebSocket::Handler> Server::getWebSocketHandler(const char* endpoint) const {
+    auto splits = split(endpoint, '?');
+    auto iter = _webSocketHandlerMap.find(splits[0]);
+    if (iter == _webSocketHandlerMap.end()) {
+        return std::shared_ptr<WebSocket::Handler>();
+    }
+    return iter->second.handler;
+}
+
+void Server::execute(std::shared_ptr<Runnable> runnable) {
+    std::unique_lock<decltype(_pendingRunnableMutex)> lock(_pendingRunnableMutex);
+    _pendingRunnables.push_back(runnable);
+    lock.unlock();
+
+    uint64_t one = 1;
+    if (_eventFd != -1 && ::write(_eventFd, &one, sizeof(one)) == -1) {
+        if (errno != EAGAIN && errno != EWOULDBLOCK) {
+            LS_ERROR(_logger, "Unable to post a wake event: " << getLastError());
+        }
+    }
+}
+
+std::shared_ptr<Server::Runnable> Server::popNextRunnable() {
+    std::lock_guard<decltype(_pendingRunnableMutex)> lock(_pendingRunnableMutex);
+    std::shared_ptr<Runnable> runnable;
+    if (!_pendingRunnables.empty()) {
+        runnable = _pendingRunnables.front();
+        _pendingRunnables.pop_front();
+    }
+    return runnable;
+}
+
+std::string Server::getStatsDocument() const {
+    std::ostringstream doc;
+    doc << "clear();" << std::endl;
+    for (auto it = _connections.begin(); it != _connections.end(); ++it) {
+        doc << "connection({";
+        auto connection = it->first;
+        jsonKeyPairToStream(doc,
+                "since", EpochTimeAsLocal(it->second),
+                "fd", connection->getFd(),
+                "id", reinterpret_cast<uint64_t>(connection),
+                "uri", connection->getRequestUri(),
+                "addr", formatAddress(connection->getRemoteAddress()),
+                "user", connection->credentials() ?
+                        connection->credentials()->username : "(not authed)",
+                "input", connection->inputBufferSize(),
+                "read", connection->bytesReceived(),
+                "output", connection->outputBufferSize(),
+                "written", connection->bytesSent()
+        );
+        doc << "});" << std::endl;
+    }
+    return doc.str();
+}
+
+void Server::setLameConnectionTimeoutSeconds(int seconds) {
+    LS_INFO(_logger, "Setting lame connection timeout to " << seconds);
+    _lameConnectionTimeoutSeconds = seconds;
+}
+
+void Server::setMaxKeepAliveDrops(int maxKeepAliveDrops) {
+    LS_INFO(_logger, "Setting max keep alive drops to " << maxKeepAliveDrops);
+    _maxKeepAliveDrops = maxKeepAliveDrops;
+}
+
+void Server::checkThread() const {
+    auto thisTid = gettid();
+    if (thisTid != _threadId) {
+        std::ostringstream o;
+        o << "seasocks called on wrong thread : " << thisTid << " instead of " << _threadId;
+        LS_SEVERE(_logger, o.str());
+        throw std::runtime_error(o.str());
+    }
+}
+
+std::shared_ptr<Response> Server::handle(const Request &request) {
+    for (auto handler : _pageHandlers) {
+        auto result = handler->handle(request);
+        if (result != Response::unhandled()) return result;
+    }
+    return Response::unhandled();
+}
+
+}  // namespace seasocks
diff --git a/third_party/seasocks/src/main/c/StringUtil.cpp b/third_party/seasocks/src/main/c/StringUtil.cpp
new file mode 100644
index 0000000..b7177ce
--- /dev/null
+++ b/third_party/seasocks/src/main/c/StringUtil.cpp
@@ -0,0 +1,109 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "seasocks/StringUtil.h"
+
+#include <cctype>
+#include <cerrno>
+#include <cstddef>
+#include <cstdio>
+#include <cstring>
+
+namespace seasocks {
+
+char* skipWhitespace(char* str) {
+    while (isspace(*str)) ++str;
+    return str;
+}
+
+char* skipNonWhitespace(char* str) {
+    while (*str && !isspace(*str)) {
+        ++str;
+    }
+    return str;
+}
+
+char* shift(char*& str) {
+    if (str == NULL) {
+        return NULL;
+    }
+    char* startOfWord = skipWhitespace(str);
+    if (*startOfWord == 0) {
+        str = startOfWord;
+        return NULL;
+    }
+    char* endOfWord = skipNonWhitespace(startOfWord);
+    if (*endOfWord != 0) {
+        *endOfWord++ = 0;
+    }
+    str = endOfWord;
+    return startOfWord;
+}
+
+std::string getLastError(){
+    char errbuf[1024];
+    return strerror_r(errno, errbuf, sizeof(errbuf));
+}
+
+std::string formatAddress(const sockaddr_in& address) {
+    char ipBuffer[24];
+    sprintf(ipBuffer,
+            "%d.%d.%d.%d:%d",
+            (address.sin_addr.s_addr >> 0) & 0xff,
+            (address.sin_addr.s_addr >> 8) & 0xff,
+            (address.sin_addr.s_addr >> 16) & 0xff,
+            (address.sin_addr.s_addr >> 24) & 0xff,
+            htons(address.sin_port));
+    return ipBuffer;
+}
+
+std::vector<std::string> split(const std::string& input, char splitChar) {
+    if (input.empty()) return std::vector<std::string>();
+    std::vector<std::string> result;
+    size_t pos = 0;
+    size_t newPos;
+    while ((newPos = input.find(splitChar, pos)) != std::string::npos) {
+        result.push_back(input.substr(pos, newPos - pos));
+        pos = newPos + 1;
+    }
+    result.push_back(input.substr(pos));
+    return result;
+}
+
+void replace(std::string& string, const std::string& find, const std::string& replace) {
+    size_t pos = 0;
+    const size_t findLen = find.length();
+    const size_t replaceLen = replace.length();
+    while ((pos = string.find(find, pos)) != std::string::npos) {
+        string = string.substr(0, pos) + replace + string.substr(pos + findLen);
+        pos += replaceLen;
+    }
+}
+
+bool caseInsensitiveSame(const std::string &lhs, const std::string &rhs) {
+    return strcasecmp(lhs.c_str(), rhs.c_str()) == 0;
+}
+
+}
diff --git a/third_party/seasocks/src/main/c/internal/.gitignore b/third_party/seasocks/src/main/c/internal/.gitignore
new file mode 100644
index 0000000..40ee485
--- /dev/null
+++ b/third_party/seasocks/src/main/c/internal/.gitignore
@@ -0,0 +1 @@
+/Config.h
diff --git a/third_party/seasocks/src/main/c/internal/Base64.cpp b/third_party/seasocks/src/main/c/internal/Base64.cpp
new file mode 100644
index 0000000..3b1cf20
--- /dev/null
+++ b/third_party/seasocks/src/main/c/internal/Base64.cpp
@@ -0,0 +1,50 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "internal/Base64.h"
+
+#include <cstdint>
+
+namespace seasocks {
+
+const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+std::string base64Encode(const void* dataVoid, size_t length) {
+    std::string output;
+    auto data = reinterpret_cast<const uint8_t*>(dataVoid);
+    for (auto i = 0u; i < length; i += 3) {
+        auto bytesLeft = length - i;
+        auto b0 = data[i];
+        auto b1 = bytesLeft > 1 ? data[i + 1] : 0;
+        auto b2 = bytesLeft > 2 ? data[i + 2] : 0;
+        output.push_back(cb64[b0 >> 2]);
+        output.push_back(cb64[((b0 & 0x03) << 4) | ((b1 & 0xf0) >> 4)]);
+        output.push_back((bytesLeft > 1 ? cb64[((b1 & 0x0f) << 2) | ((b2 & 0xc0) >> 6)] : '='));
+        output.push_back((bytesLeft > 2 ? cb64[b2 & 0x3f] : '='));
+    }
+    return output;
+}
+
+} // namespace seasocks
diff --git a/third_party/seasocks/src/main/c/internal/Base64.h b/third_party/seasocks/src/main/c/internal/Base64.h
new file mode 100644
index 0000000..b6dc014
--- /dev/null
+++ b/third_party/seasocks/src/main/c/internal/Base64.h
@@ -0,0 +1,34 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include <string>
+
+namespace seasocks {
+
+extern std::string base64Encode(const void* data, size_t length);
+
+}
diff --git a/third_party/seasocks/src/main/c/internal/ConcreteResponse.h b/third_party/seasocks/src/main/c/internal/ConcreteResponse.h
new file mode 100644
index 0000000..d4a68b3
--- /dev/null
+++ b/third_party/seasocks/src/main/c/internal/ConcreteResponse.h
@@ -0,0 +1,67 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include "seasocks/Response.h"
+
+namespace seasocks {
+
+class ConcreteResponse : public Response {
+    ResponseCode _responseCode;
+    const std::string _payload;
+    const std::string _contentType;
+    const Headers _headers;
+    const bool _keepAlive;
+public:
+    ConcreteResponse(ResponseCode responseCode, const std::string& payload, const std::string& contentType, const Headers& headers, bool keepAlive) :
+        _responseCode(responseCode), _payload(payload), _contentType(contentType), _headers(headers), _keepAlive(keepAlive) {}
+
+    virtual ResponseCode responseCode() const {
+        return _responseCode;
+    }
+
+    virtual const char* payload() const {
+        return _payload.c_str();
+    }
+
+    virtual size_t payloadSize() const {
+        return _payload.size();
+    }
+
+    virtual bool keepConnectionAlive() const {
+        return _keepAlive;
+    }
+
+    virtual std::string contentType() const {
+        return _contentType;
+    }
+
+    virtual Headers getAdditionalHeaders() const {
+        return _headers;
+    }
+};
+
+}
diff --git a/third_party/seasocks/src/main/c/internal/Config.h.in b/third_party/seasocks/src/main/c/internal/Config.h.in
new file mode 100644
index 0000000..48c5421
--- /dev/null
+++ b/third_party/seasocks/src/main/c/internal/Config.h.in
@@ -0,0 +1,219 @@
+/* src/main/c/internal/Config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#undef HAVE_ARPA_INET_H
+
+/* define if the compiler supports basic C++11 syntax */
+#undef HAVE_CXX11
+
+/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you
+   don't. */
+#undef HAVE_DECL_STRERROR_R
+
+/* Define to 1 if you have the `dup2' function. */
+#undef HAVE_DUP2
+
+/* Define to 1 if you have the `eventfd' function. */
+#undef HAVE_EVENTFD
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the `fork' function. */
+#undef HAVE_FORK
+
+/* Define to 1 if you have the `gethostname' function. */
+#undef HAVE_GETHOSTNAME
+
+/* Define to 1 if you have the `getopt' function. */
+#undef HAVE_GETOPT
+
+/* Define to 1 if you have the <getopt.h> header file. */
+#undef HAVE_GETOPT_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+   to 0 otherwise. */
+#undef HAVE_MALLOC
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `memset' function. */
+#undef HAVE_MEMSET
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#undef HAVE_NETINET_IN_H
+
+/* Define to 1 if the system has the type `ptrdiff_t'. */
+#undef HAVE_PTRDIFF_T
+
+/* Define to 1 if you have the `rmdir' function. */
+#undef HAVE_RMDIR
+
+/* Define to 1 if you have the `socket' function. */
+#undef HAVE_SOCKET
+
+/* Define to 1 if you have the `sqrt' function. */
+#undef HAVE_SQRT
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#undef HAVE_STDBOOL_H
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#undef HAVE_STDDEF_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#undef HAVE_STRCASECMP
+
+/* Define to 1 if you have the `strchr' function. */
+#undef HAVE_STRCHR
+
+/* Define to 1 if you have the `strdup' function. */
+#undef HAVE_STRDUP
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* Define to 1 if you have the `strerror_r' function. */
+#undef HAVE_STRERROR_R
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `syscall' function. */
+#undef HAVE_SYSCALL
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#undef HAVE_SYS_IOCTL_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* define if unordered_map supports emplace */
+#undef HAVE_UNORDERED_MAP_EMPLACE
+
+/* Define to 1 if you have the `vfork' function. */
+#undef HAVE_VFORK
+
+/* Define to 1 if you have the <vfork.h> header file. */
+#undef HAVE_VFORK_H
+
+/* Define to 1 if `fork' works. */
+#undef HAVE_WORKING_FORK
+
+/* Define to 1 if `vfork' works. */
+#undef HAVE_WORKING_VFORK
+
+/* Define to 1 if the system has the type `_Bool'. */
+#undef HAVE__BOOL
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to 1 if strerror_r returns char *. */
+#undef STRERROR_R_CHAR_P
+
+/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
+   <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
+   #define below would cause a syntax error. */
+#undef _UINT32_T
+
+/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
+   <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
+   #define below would cause a syntax error. */
+#undef _UINT64_T
+
+/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
+   <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
+   #define below would cause a syntax error. */
+#undef _UINT8_T
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to rpl_malloc if the replacement function should be used. */
+#undef malloc
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef pid_t
+
+/* Define to the equivalent of the C99 'restrict' keyword, or to
+   nothing if this is not supported.  Do not define if restrict is
+   supported directly.  */
+#undef restrict
+/* Work around a bug in Sun C++: it does not support _Restrict or
+   __restrict__, even though the corresponding Sun C compiler ends up with
+   "#define restrict _Restrict" or "#define restrict __restrict__" in the
+   previous line.  Perhaps some future version of Sun C++ will work with
+   restrict; if so, hopefully it defines __RESTRICT like Sun C does.  */
+#if defined __SUNPRO_CC && !defined __RESTRICT
+# define _Restrict
+# define __restrict__
+#endif
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define to the type of an unsigned integer type of width exactly 16 bits if
+   such a type exists and the standard includes do not define it. */
+#undef uint16_t
+
+/* Define to the type of an unsigned integer type of width exactly 32 bits if
+   such a type exists and the standard includes do not define it. */
+#undef uint32_t
+
+/* Define to the type of an unsigned integer type of width exactly 64 bits if
+   such a type exists and the standard includes do not define it. */
+#undef uint64_t
+
+/* Define to the type of an unsigned integer type of width exactly 8 bits if
+   such a type exists and the standard includes do not define it. */
+#undef uint8_t
+
+/* Define as `fork' if `vfork' does not work. */
+#undef vfork
diff --git a/third_party/seasocks/src/main/c/internal/Debug.h b/third_party/seasocks/src/main/c/internal/Debug.h
new file mode 100644
index 0000000..304e141
--- /dev/null
+++ b/third_party/seasocks/src/main/c/internal/Debug.h
@@ -0,0 +1,29 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+// Uncomment to actually log at DEBUG level.
+//#define LOG_DEBUG_INFO
diff --git a/third_party/seasocks/src/main/c/internal/Embedded.h b/third_party/seasocks/src/main/c/internal/Embedded.h
new file mode 100644
index 0000000..5741c62
--- /dev/null
+++ b/third_party/seasocks/src/main/c/internal/Embedded.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include <string>
+
+struct EmbeddedContent {
+   const char* data;
+   size_t length;
+};
+
+const EmbeddedContent* findEmbeddedContent(const std::string& name);
diff --git a/third_party/seasocks/src/main/c/internal/HeaderMap.h b/third_party/seasocks/src/main/c/internal/HeaderMap.h
new file mode 100644
index 0000000..ba5ed35
--- /dev/null
+++ b/third_party/seasocks/src/main/c/internal/HeaderMap.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include <cctype>
+#include <cstring>
+#include <string>
+#include <unordered_map>
+
+namespace seasocks {
+
+struct CaseInsensitiveHash {
+    size_t operator()(const std::string &string) const {
+        size_t h = 0;
+        for (auto c: string) {
+            h = h * 13 + tolower(c);
+        }
+        return h;
+    }
+};
+
+struct CaseInsensitiveComparison {
+    bool operator()(const std::string &lhs, const std::string &rhs) const {
+        return strcasecmp(lhs.c_str(), rhs.c_str()) == 0;
+    }
+};
+
+using HeaderMap = std::unordered_map<std::string, std::string,
+        CaseInsensitiveHash, CaseInsensitiveComparison>;
+
+}
diff --git a/third_party/seasocks/src/main/c/internal/HybiAccept.h b/third_party/seasocks/src/main/c/internal/HybiAccept.h
new file mode 100644
index 0000000..d02833b
--- /dev/null
+++ b/third_party/seasocks/src/main/c/internal/HybiAccept.h
@@ -0,0 +1,34 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include <string>
+
+namespace seasocks {
+
+extern std::string getAcceptKey(const std::string& challenge);
+
+}
diff --git a/third_party/seasocks/src/main/c/internal/HybiPacketDecoder.h b/third_party/seasocks/src/main/c/internal/HybiPacketDecoder.h
new file mode 100644
index 0000000..528bbf9
--- /dev/null
+++ b/third_party/seasocks/src/main/c/internal/HybiPacketDecoder.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include "seasocks/Logger.h"
+
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace seasocks {
+
+class HybiPacketDecoder {
+    Logger& _logger;
+    const std::vector<uint8_t>& _buffer;
+    size_t _messageStart;
+public:
+    HybiPacketDecoder(Logger& logger, const std::vector<uint8_t>& buffer);
+
+    enum {
+        OPCODE_CONT = 0x0,  // Deprecated in latest hybi spec, here anyway.
+        OPCODE_TEXT = 0x1,
+        OPCODE_BINARY = 0x2,
+        OPCODE_CLOSE = 0x8,
+        OPCODE_PING = 0x9,
+        OPCODE_PONG = 0xA,
+    };
+
+    enum MessageState {
+        NoMessage,
+        TextMessage,
+        BinaryMessage,
+        Error,
+        Ping,
+        Close
+    };
+    MessageState decodeNextMessage(std::vector<uint8_t>& messageOut);
+
+    size_t numBytesDecoded() const;
+};
+
+}
diff --git a/third_party/seasocks/src/main/c/internal/LogStream.h b/third_party/seasocks/src/main/c/internal/LogStream.h
new file mode 100644
index 0000000..16612ba
--- /dev/null
+++ b/third_party/seasocks/src/main/c/internal/LogStream.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include "internal/Debug.h"
+
+// Internal stream helpers for logging.
+#include <sstream>
+
+#define LS_LOG(LOG, LEVEL, STUFF) \
+{ \
+    std::ostringstream o; \
+    o << STUFF; \
+    (LOG)->log(Logger::LEVEL, o.str().c_str()); \
+}
+
+#define LS_DEBUG(LOG, STUFF)     LS_LOG(LOG, DEBUG, STUFF)
+#define LS_ACCESS(LOG, STUFF)     LS_LOG(LOG, ACCESS, STUFF)
+#define LS_INFO(LOG, STUFF)     LS_LOG(LOG, INFO, STUFF)
+#define LS_WARNING(LOG, STUFF)     LS_LOG(LOG, WARNING, STUFF)
+#define LS_ERROR(LOG, STUFF)     LS_LOG(LOG, ERROR, STUFF)
+#define LS_SEVERE(LOG, STUFF)     LS_LOG(LOG, SEVERE, STUFF)
diff --git a/third_party/seasocks/src/main/c/internal/PageRequest.h b/third_party/seasocks/src/main/c/internal/PageRequest.h
new file mode 100644
index 0000000..6fea7fb
--- /dev/null
+++ b/third_party/seasocks/src/main/c/internal/PageRequest.h
@@ -0,0 +1,90 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include "internal/HeaderMap.h"
+#include "seasocks/Request.h"
+
+#include <unordered_map>
+#include <vector>
+
+namespace seasocks {
+
+class PageRequest : public Request {
+    std::shared_ptr<Credentials> _credentials;
+    const sockaddr_in _remoteAddress;
+    const std::string _requestUri;
+    const Verb _verb;
+    std::vector<uint8_t> _content;
+    HeaderMap _headers;
+    const size_t _contentLength;
+
+public:
+    PageRequest(
+            const sockaddr_in& remoteAddress,
+            const std::string& requestUri,
+            Verb verb,
+            HeaderMap&& headers);
+
+    virtual Verb verb() const {
+        return _verb;
+    }
+
+    virtual std::shared_ptr<Credentials> credentials() const {
+        return _credentials;
+    }
+
+    virtual const sockaddr_in& getRemoteAddress() const {
+        return _remoteAddress;
+    }
+
+    virtual const std::string& getRequestUri() const {
+        return _requestUri;
+    }
+
+    virtual size_t contentLength() const {
+        return _contentLength;
+    }
+
+    virtual const uint8_t* content() const {
+        return _contentLength > 0 ? &_content[0] : NULL;
+    }
+
+    virtual bool hasHeader(const std::string& name) const {
+        return _headers.find(name) != _headers.end();
+    }
+
+    virtual std::string getHeader(const std::string& name) const {
+        auto iter = _headers.find(name);
+        return iter == _headers.end() ? std::string() : iter->second;
+    }
+
+    bool consumeContent(std::vector<uint8_t>& buffer);
+
+    int getIntHeader(const std::string& name) const;
+};
+
+}  // namespace seasocks
diff --git a/third_party/seasocks/src/main/c/internal/Version.h b/third_party/seasocks/src/main/c/internal/Version.h
new file mode 100644
index 0000000..366f8ea
--- /dev/null
+++ b/third_party/seasocks/src/main/c/internal/Version.h
@@ -0,0 +1,31 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#ifndef SEASOCKS_VERSION_STRING
+// This stops Eclipse freaking out as it doesn't know this is set on GCC command line.
+#define SEASOCKS_VERSION_STRING "SeaSocks/unversioned"
+#endif
\ No newline at end of file
diff --git a/third_party/seasocks/src/main/c/md5/md5.cpp b/third_party/seasocks/src/main/c/md5/md5.cpp
new file mode 100644
index 0000000..4ad3606
--- /dev/null
+++ b/third_party/seasocks/src/main/c/md5/md5.cpp
@@ -0,0 +1,416 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+/*
+  Copyright (C) 1999, 2000, 2002 Aladdin Enterprises.  All rights reserved.
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  L. Peter Deutsch
+  ghost@aladdin.com
+
+ */
+/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
+/*
+  Independent implementation of MD5 (RFC 1321).
+
+  This code implements the MD5 Algorithm defined in RFC 1321, whose
+  text is available at
+    http://www.ietf.org/rfc/rfc1321.txt
+  The code is derived from the text of the RFC, including the test suite
+  (section A.5) but excluding the rest of Appendix A.  It does not include
+  any code or documentation that is identified in the RFC as being
+  copyrighted.
+
+  The original and principal author of md5.c is L. Peter Deutsch
+  <ghost@aladdin.com>.  Other authors are noted in the change history
+  that follows (in reverse chronological order):
+
+  2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
+    either statically or dynamically; added missing #include <string.h>
+    in library.
+  2002-03-11 lpd Corrected argument list for main(), and added int return
+    type, in test program and T value program.
+  2002-02-21 lpd Added missing #include <stdio.h> in test program.
+  2000-07-03 lpd Patched to eliminate warnings about "constant is
+    unsigned in ANSI C, signed in traditional"; made test program
+    self-checking.
+  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
+  1999-05-03 lpd Original version.
+ */
+
+#include "md5/md5.h"
+
+#include <string.h>
+
+#undef BYTE_ORDER    /* 1 = big-endian, -1 = little-endian, 0 = unknown */
+#ifdef ARCH_IS_BIG_ENDIAN
+#  define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
+#else
+#  define BYTE_ORDER 0
+#endif
+
+#define T_MASK ((md5_word_t)~0)
+#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
+#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
+#define T3    0x242070db
+#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
+#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
+#define T6    0x4787c62a
+#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
+#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
+#define T9    0x698098d8
+#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
+#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
+#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
+#define T13    0x6b901122
+#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
+#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
+#define T16    0x49b40821
+#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
+#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
+#define T19    0x265e5a51
+#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
+#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
+#define T22    0x02441453
+#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
+#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
+#define T25    0x21e1cde6
+#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
+#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
+#define T28    0x455a14ed
+#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
+#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
+#define T31    0x676f02d9
+#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
+#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
+#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
+#define T35    0x6d9d6122
+#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
+#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
+#define T38    0x4bdecfa9
+#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
+#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
+#define T41    0x289b7ec6
+#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
+#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
+#define T44    0x04881d05
+#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
+#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
+#define T47    0x1fa27cf8
+#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
+#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
+#define T50    0x432aff97
+#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
+#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
+#define T53    0x655b59c3
+#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
+#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
+#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
+#define T57    0x6fa87e4f
+#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
+#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
+#define T60    0x4e0811a1
+#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
+#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
+#define T63    0x2ad7d2bb
+#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
+
+
+static void
+md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
+{
+    md5_word_t
+    a = pms->abcd[0], b = pms->abcd[1],
+    c = pms->abcd[2], d = pms->abcd[3];
+    md5_word_t t;
+#if BYTE_ORDER > 0
+    /* Define storage only for big-endian CPUs. */
+    md5_word_t X[16];
+#else
+    /* Define storage for little-endian or both types of CPUs. */
+    md5_word_t xbuf[16];
+    const md5_word_t *X;
+#endif
+
+    {
+#if BYTE_ORDER == 0
+    /*
+     * Determine dynamically whether this is a big-endian or
+     * little-endian machine, since we can use a more efficient
+     * algorithm on the latter.
+     */
+    static const int w = 1;
+
+    if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
+#endif
+#if BYTE_ORDER <= 0        /* little-endian */
+    {
+        /*
+         * On little-endian machines, we can process properly aligned
+         * data without copying it.
+         */
+        if (!((data - (const md5_byte_t *)0) & 3)) {
+        /* data are properly aligned */
+        X = (const md5_word_t *)data;
+        } else {
+        /* not aligned */
+        memcpy(xbuf, data, 64);
+        X = xbuf;
+        }
+    }
+#endif
+#if BYTE_ORDER == 0
+    else            /* dynamic big-endian */
+#endif
+#if BYTE_ORDER >= 0        /* big-endian */
+    {
+        /*
+         * On big-endian machines, we must arrange the bytes in the
+         * right order.
+         */
+        const md5_byte_t *xp = data;
+        int i;
+
+#  if BYTE_ORDER == 0
+        X = xbuf;        /* (dynamic only) */
+#  else
+#    define xbuf X        /* (static only) */
+#  endif
+        for (i = 0; i < 16; ++i, xp += 4)
+        xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
+    }
+#endif
+    }
+
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+    /* Round 1. */
+    /* Let [abcd k s i] denote the operation
+       a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
+#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + F(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+    /* Do the following 16 operations. */
+    SET(a, b, c, d,  0,  7,  T1);
+    SET(d, a, b, c,  1, 12,  T2);
+    SET(c, d, a, b,  2, 17,  T3);
+    SET(b, c, d, a,  3, 22,  T4);
+    SET(a, b, c, d,  4,  7,  T5);
+    SET(d, a, b, c,  5, 12,  T6);
+    SET(c, d, a, b,  6, 17,  T7);
+    SET(b, c, d, a,  7, 22,  T8);
+    SET(a, b, c, d,  8,  7,  T9);
+    SET(d, a, b, c,  9, 12, T10);
+    SET(c, d, a, b, 10, 17, T11);
+    SET(b, c, d, a, 11, 22, T12);
+    SET(a, b, c, d, 12,  7, T13);
+    SET(d, a, b, c, 13, 12, T14);
+    SET(c, d, a, b, 14, 17, T15);
+    SET(b, c, d, a, 15, 22, T16);
+#undef SET
+
+     /* Round 2. */
+     /* Let [abcd k s i] denote the operation
+          a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
+#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + G(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+     /* Do the following 16 operations. */
+    SET(a, b, c, d,  1,  5, T17);
+    SET(d, a, b, c,  6,  9, T18);
+    SET(c, d, a, b, 11, 14, T19);
+    SET(b, c, d, a,  0, 20, T20);
+    SET(a, b, c, d,  5,  5, T21);
+    SET(d, a, b, c, 10,  9, T22);
+    SET(c, d, a, b, 15, 14, T23);
+    SET(b, c, d, a,  4, 20, T24);
+    SET(a, b, c, d,  9,  5, T25);
+    SET(d, a, b, c, 14,  9, T26);
+    SET(c, d, a, b,  3, 14, T27);
+    SET(b, c, d, a,  8, 20, T28);
+    SET(a, b, c, d, 13,  5, T29);
+    SET(d, a, b, c,  2,  9, T30);
+    SET(c, d, a, b,  7, 14, T31);
+    SET(b, c, d, a, 12, 20, T32);
+#undef SET
+
+     /* Round 3. */
+     /* Let [abcd k s t] denote the operation
+          a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + H(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+     /* Do the following 16 operations. */
+    SET(a, b, c, d,  5,  4, T33);
+    SET(d, a, b, c,  8, 11, T34);
+    SET(c, d, a, b, 11, 16, T35);
+    SET(b, c, d, a, 14, 23, T36);
+    SET(a, b, c, d,  1,  4, T37);
+    SET(d, a, b, c,  4, 11, T38);
+    SET(c, d, a, b,  7, 16, T39);
+    SET(b, c, d, a, 10, 23, T40);
+    SET(a, b, c, d, 13,  4, T41);
+    SET(d, a, b, c,  0, 11, T42);
+    SET(c, d, a, b,  3, 16, T43);
+    SET(b, c, d, a,  6, 23, T44);
+    SET(a, b, c, d,  9,  4, T45);
+    SET(d, a, b, c, 12, 11, T46);
+    SET(c, d, a, b, 15, 16, T47);
+    SET(b, c, d, a,  2, 23, T48);
+#undef SET
+
+     /* Round 4. */
+     /* Let [abcd k s t] denote the operation
+          a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + I(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+     /* Do the following 16 operations. */
+    SET(a, b, c, d,  0,  6, T49);
+    SET(d, a, b, c,  7, 10, T50);
+    SET(c, d, a, b, 14, 15, T51);
+    SET(b, c, d, a,  5, 21, T52);
+    SET(a, b, c, d, 12,  6, T53);
+    SET(d, a, b, c,  3, 10, T54);
+    SET(c, d, a, b, 10, 15, T55);
+    SET(b, c, d, a,  1, 21, T56);
+    SET(a, b, c, d,  8,  6, T57);
+    SET(d, a, b, c, 15, 10, T58);
+    SET(c, d, a, b,  6, 15, T59);
+    SET(b, c, d, a, 13, 21, T60);
+    SET(a, b, c, d,  4,  6, T61);
+    SET(d, a, b, c, 11, 10, T62);
+    SET(c, d, a, b,  2, 15, T63);
+    SET(b, c, d, a,  9, 21, T64);
+#undef SET
+
+     /* Then perform the following additions. (That is increment each
+        of the four registers by the value it had before this block
+        was started.) */
+    pms->abcd[0] += a;
+    pms->abcd[1] += b;
+    pms->abcd[2] += c;
+    pms->abcd[3] += d;
+}
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+void
+md5_init(md5_state_t *pms)
+{
+    pms->count[0] = pms->count[1] = 0;
+    pms->abcd[0] = 0x67452301;
+    pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
+    pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
+    pms->abcd[3] = 0x10325476;
+}
+
+void
+md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
+{
+    const md5_byte_t *p = data;
+    int left = nbytes;
+    int offset = (pms->count[0] >> 3) & 63;
+    md5_word_t nbits = (md5_word_t)(nbytes << 3);
+
+    if (nbytes <= 0)
+    return;
+
+    /* Update the message length. */
+    pms->count[1] += nbytes >> 29;
+    pms->count[0] += nbits;
+    if (pms->count[0] < nbits)
+    pms->count[1]++;
+
+    /* Process an initial partial block. */
+    if (offset) {
+    int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+    memcpy(pms->buf + offset, p, copy);
+    if (offset + copy < 64)
+        return;
+    p += copy;
+    left -= copy;
+    md5_process(pms, pms->buf);
+    }
+
+    /* Process full blocks. */
+    for (; left >= 64; p += 64, left -= 64)
+    md5_process(pms, p);
+
+    /* Process a final partial block. */
+    if (left)
+    memcpy(pms->buf, p, left);
+}
+
+void
+md5_finish(md5_state_t *pms, md5_byte_t digest[16])
+{
+    static const md5_byte_t pad[64] = {
+    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+    };
+    md5_byte_t data[8];
+    int i;
+
+    /* Save the length before padding. */
+    for (i = 0; i < 8; ++i)
+    data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
+    /* Pad to 56 bytes mod 64. */
+    md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
+    /* Append the length. */
+    md5_append(pms, data, 8);
+    for (i = 0; i < 16; ++i)
+    digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
+}
+
+#ifdef __cplusplus
+}  /* end extern "C" */
+#endif
diff --git a/third_party/seasocks/src/main/c/md5/md5.h b/third_party/seasocks/src/main/c/md5/md5.h
new file mode 100644
index 0000000..3b88587
--- /dev/null
+++ b/third_party/seasocks/src/main/c/md5/md5.h
@@ -0,0 +1,116 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+/*
+  Copyright (C) 1999, 2002 Aladdin Enterprises.  All rights reserved.
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  L. Peter Deutsch
+  ghost@aladdin.com
+
+ */
+/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */
+/*
+  Independent implementation of MD5 (RFC 1321).
+
+  This code implements the MD5 Algorithm defined in RFC 1321, whose
+  text is available at
+    http://www.ietf.org/rfc/rfc1321.txt
+  The code is derived from the text of the RFC, including the test suite
+  (section A.5) but excluding the rest of Appendix A.  It does not include
+  any code or documentation that is identified in the RFC as being
+  copyrighted.
+
+  The original and principal author of md5.h is L. Peter Deutsch
+  <ghost@aladdin.com>.  Other authors are noted in the change history
+  that follows (in reverse chronological order):
+
+  2002-04-13 lpd Removed support for non-ANSI compilers; removed
+    references to Ghostscript; clarified derivation from RFC 1321;
+    now handles byte order either statically or dynamically.
+  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
+    added conditionalization for C++ compilation from Martin
+    Purschke <purschke@bnl.gov>.
+  1999-05-03 lpd Original version.
+ */
+
+#ifndef md5_INCLUDED
+#  define md5_INCLUDED
+
+/*
+ * This package supports both compile-time and run-time determination of CPU
+ * byte order.  If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
+ * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
+ * defined as non-zero, the code will be compiled to run only on big-endian
+ * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
+ * run on either big- or little-endian CPUs, but will run slightly less
+ * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
+ */
+
+typedef unsigned char md5_byte_t; /* 8-bit byte */
+typedef unsigned int md5_word_t; /* 32-bit word */
+
+/* Define the state of the MD5 Algorithm. */
+typedef struct md5_state_s {
+    md5_word_t count[2];    /* message length in bits, lsw first */
+    md5_word_t abcd[4];        /* digest buffer */
+    md5_byte_t buf[64];        /* accumulate block */
+} md5_state_t;
+
+#ifdef __cplusplus
+extern "C" 
+{
+#endif
+
+/* Initialize the algorithm. */
+void md5_init(md5_state_t *pms);
+
+/* Append a string to the message. */
+void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
+
+/* Finish the message and return the digest. */
+void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
+
+#ifdef __cplusplus
+}  /* end extern "C" */
+#endif
+
+#endif /* md5_INCLUDED */
diff --git a/third_party/seasocks/src/main/c/seasocks/Connection.h b/third_party/seasocks/src/main/c/seasocks/Connection.h
new file mode 100644
index 0000000..c1aa996
--- /dev/null
+++ b/third_party/seasocks/src/main/c/seasocks/Connection.h
@@ -0,0 +1,177 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include "seasocks/ResponseCode.h"
+#include "seasocks/WebSocket.h"
+
+#include <netinet/in.h>
+
+#include <sys/socket.h>
+
+#include <inttypes.h>
+#include <list>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace seasocks {
+
+class Logger;
+class ServerImpl;
+class PageRequest;
+class Response;
+
+class Connection : public WebSocket {
+public:
+    Connection(
+            std::shared_ptr<Logger> logger,
+            ServerImpl& server,
+            int fd,
+            const sockaddr_in& address);
+    virtual ~Connection();
+
+    bool write(const void* data, size_t size, bool flush);
+    void handleDataReadyForRead();
+    void handleDataReadyForWrite();
+
+    int getFd() const { return _fd; }
+
+    // From WebSocket.
+    virtual void send(const char* webSocketResponse) override;
+    virtual void send(const uint8_t* webSocketResponse, size_t length) override;
+    virtual void close() override;
+
+    // From Request.
+    virtual std::shared_ptr<Credentials> credentials() const override;
+    virtual const sockaddr_in& getRemoteAddress() const override { return _address; }
+    virtual const std::string& getRequestUri() const override;
+    virtual Request::Verb verb() const override { return Request::WebSocket; }
+    virtual size_t contentLength() const override { return 0; }
+    virtual const uint8_t* content() const override { return NULL; }
+    virtual bool hasHeader(const std::string&) const override;
+    virtual std::string getHeader(const std::string&) const override;
+
+    void setLinger();
+
+    size_t inputBufferSize() const { return _inBuf.size(); }
+    size_t outputBufferSize() const { return _outBuf.size(); }
+
+    size_t bytesReceived() const { return _bytesReceived; }
+    size_t bytesSent() const { return _bytesSent; }
+
+    // For testing:
+    std::vector<uint8_t>& getInputBuffer() { return _inBuf; }
+    void handleHixieWebSocket();
+    void handleHybiWebSocket();
+    void setHandler(std::shared_ptr<WebSocket::Handler> handler) {
+        _webSocketHandler = handler;
+    }
+    void handleNewData();
+
+private:
+    void finalise();
+    bool closed() const;
+
+    void closeWhenEmpty();
+    void closeInternal();
+
+    void handleHeaders();
+    void handleWebSocketKey3();
+    void handleWebSocketTextMessage(const char* message);
+    void handleWebSocketBinaryMessage(const std::vector<uint8_t>& message);
+    void handleBufferingPostData();
+    bool handlePageRequest();
+
+    bool bufferLine(const char* line);
+    bool bufferLine(const std::string& line);
+    bool flush();
+
+    bool handleHybiHandshake(int webSocketVersion, const std::string& webSocketKey);
+
+    // Send an error document. Returns 'true' for convenience in handle*() routines.
+    bool sendError(ResponseCode errorCode, const std::string& document);
+
+    // Send individual errors. Again all return true for convenience.
+    bool sendUnsupportedError(const std::string& reason);
+    bool send404();
+    bool sendBadRequest(const std::string& reason);
+    bool sendISE(const std::string& error);
+
+    void sendHybi(int opcode, const uint8_t* webSocketResponse, size_t messageLength);
+
+    bool sendResponse(std::shared_ptr<Response> response);
+
+    bool processHeaders(uint8_t* first, uint8_t* last);
+    bool sendData(const std::string& type, const char* start, size_t size);
+
+    struct Range {
+        long start;
+        long end;
+        size_t length() const { return end - start + 1; }
+    };
+
+    bool parseRange(const std::string& rangeStr, Range& range) const;
+    bool parseRanges(const std::string& range, std::list<Range>& ranges) const;
+    bool sendStaticData();
+
+    int safeSend(const void* data, size_t size);
+
+    void bufferResponseAndCommonHeaders(ResponseCode code);
+
+    std::list<Range> processRangesForStaticData(const std::list<Range>& ranges, long fileSize);
+
+    std::shared_ptr<Logger> _logger;
+    ServerImpl &_server;
+    int _fd;
+    bool _shutdown;
+    bool _hadSendError;
+    bool _closeOnEmpty;
+    bool _registeredForWriteEvents;
+    sockaddr_in _address;
+    size_t _bytesSent;
+    size_t _bytesReceived;
+    std::vector<uint8_t> _inBuf;
+    std::vector<uint8_t> _outBuf;
+    std::shared_ptr<WebSocket::Handler> _webSocketHandler;
+    bool _shutdownByUser;
+    std::unique_ptr<PageRequest> _request;
+
+    enum State {
+        INVALID,
+        READING_HEADERS,
+        READING_WEBSOCKET_KEY3,
+        HANDLING_HIXIE_WEBSOCKET,
+        HANDLING_HYBI_WEBSOCKET,
+        BUFFERING_POST_DATA,
+    };
+    State _state;
+
+    Connection(Connection& other) = delete;
+    Connection& operator =(Connection& other) = delete;
+};
+
+}  // namespace seasocks
diff --git a/third_party/seasocks/src/main/c/seasocks/Credentials.h b/third_party/seasocks/src/main/c/seasocks/Credentials.h
new file mode 100644
index 0000000..06532c2
--- /dev/null
+++ b/third_party/seasocks/src/main/c/seasocks/Credentials.h
@@ -0,0 +1,73 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include <iostream>
+#include <map>
+#include <set>
+#include <string>
+
+namespace seasocks {
+
+struct Credentials {
+    /**
+     * Whether user was successfuly authenticated.
+     */
+    bool authenticated;
+
+    /**
+     * e.g. "mgodbolt" (or "" for unauthenticated users)
+     */
+    std::string username;
+
+    /**
+     * Groups the user is in.
+     */
+    std::set<std::string> groups;
+
+    /**
+     * Attributes for the user.
+     */
+    std::map<std::string, std::string> attributes;
+
+    Credentials(): authenticated(false) {}
+};
+
+inline std::ostream &operator<<(std::ostream &os, const Credentials& credentials) {
+    os << "{authenticated:" << credentials.authenticated << ", username:'" << credentials.username << "', groups: {";
+    for (auto it = credentials.groups.begin(); it != credentials.groups.end(); ++it) {
+        if (it != credentials.groups.begin()) os << ", ";
+        os << *it;
+    }
+    os << "}, attrs: {";
+    for (auto it = credentials.attributes.begin(); it != credentials.attributes.end(); ++it) {
+        if (it != credentials.attributes.begin()) os << ", ";
+        os << it->first << "=" << it->second;
+    }
+    return os << "}}";
+}
+
+}  // namespace seasocks
diff --git a/third_party/seasocks/src/main/c/seasocks/IgnoringLogger.h b/third_party/seasocks/src/main/c/seasocks/IgnoringLogger.h
new file mode 100644
index 0000000..c1d4b1e
--- /dev/null
+++ b/third_party/seasocks/src/main/c/seasocks/IgnoringLogger.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include "seasocks/Logger.h"
+
+namespace seasocks {
+
+class IgnoringLogger : public Logger {
+public:
+    virtual void log(Level level, const char* message) {
+    }
+};
+
+}  // namespace seasocks
diff --git a/third_party/seasocks/src/main/c/seasocks/Logger.h b/third_party/seasocks/src/main/c/seasocks/Logger.h
new file mode 100644
index 0000000..317c54a
--- /dev/null
+++ b/third_party/seasocks/src/main/c/seasocks/Logger.h
@@ -0,0 +1,68 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+namespace seasocks {
+
+/**
+ * Class to send debug logging information to.
+ */
+class Logger {
+public:
+    virtual ~Logger() {}
+
+    enum Level {
+        DEBUG,  // NB DEBUG is usually opted-out of at compile-time.
+        ACCESS, // Used to log page requests etc
+        INFO,
+        WARNING,
+        ERROR,
+        SEVERE,
+    };
+
+    virtual void log(Level level, const char* message) = 0;
+
+    void debug(const char* message, ...);
+    void access(const char* message, ...);
+    void info(const char* message, ...);
+    void warning(const char* message, ...);
+    void error(const char* message, ...);
+    void severe(const char* message, ...);
+
+    static const char* levelToString(Level level) {
+        switch (level) {
+        case DEBUG: return "debug";
+        case ACCESS: return "access";
+        case INFO: return "info";
+        case WARNING: return "warning";
+        case ERROR: return "ERROR";
+        case SEVERE: return "SEVERE";
+        default: return "???";
+        }
+    }
+};
+
+}  // namespace seasocks
diff --git a/third_party/seasocks/src/main/c/seasocks/PageHandler.h b/third_party/seasocks/src/main/c/seasocks/PageHandler.h
new file mode 100644
index 0000000..d9e671d
--- /dev/null
+++ b/third_party/seasocks/src/main/c/seasocks/PageHandler.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include "seasocks/Credentials.h"
+#include "seasocks/Response.h"
+
+#include <memory>
+#include <string>
+
+namespace seasocks {
+
+class Request;
+
+class PageHandler {
+public:
+    virtual ~PageHandler() {}
+
+    virtual std::shared_ptr<Response> handle(const Request& request) = 0;
+};
+
+}
diff --git a/third_party/seasocks/src/main/c/seasocks/PrintfLogger.h b/third_party/seasocks/src/main/c/seasocks/PrintfLogger.h
new file mode 100644
index 0000000..f08b1b0
--- /dev/null
+++ b/third_party/seasocks/src/main/c/seasocks/PrintfLogger.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include "seasocks/Logger.h"
+
+#include <stdio.h>
+
+namespace seasocks {
+
+class PrintfLogger : public Logger {
+public:
+    PrintfLogger(Level minLevelToLog = Level::DEBUG) : minLevelToLog(minLevelToLog) {
+    }
+
+    ~PrintfLogger() {
+    }
+
+    virtual void log(Level level, const char* message) {
+        if (level >= minLevelToLog) {
+            printf("%s: %s\n", levelToString(level), message);
+        }
+    }
+
+    Level minLevelToLog;
+};
+
+}  // namespace seasocks
diff --git a/third_party/seasocks/src/main/c/seasocks/Request.cpp b/third_party/seasocks/src/main/c/seasocks/Request.cpp
new file mode 100644
index 0000000..63be5a6
--- /dev/null
+++ b/third_party/seasocks/src/main/c/seasocks/Request.cpp
@@ -0,0 +1,52 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "seasocks/Request.h"
+
+#include <cstring>
+
+namespace seasocks {
+
+const char* Request::name(Verb v) {
+    switch(v) {
+    case Invalid: return "Invalid";
+    case WebSocket: return "WebSocket";
+    case Get: return "Get";
+    case Put: return "Put";
+    case Post: return "Post";
+    case Delete: return "Delete";
+    default: return "???";
+    }
+}
+
+Request::Verb Request::verb(const char* verb) {
+    if (std::strcmp(verb, "GET") == 0) return Request::Get;
+    if (std::strcmp(verb, "PUT") == 0) return Request::Put;
+    if (std::strcmp(verb, "POST") == 0) return Request::Post;
+    if (std::strcmp(verb, "DELETE") == 0) return Request::Delete;
+    return Request::Invalid;
+}
+
+}  // namespace seasocks
diff --git a/third_party/seasocks/src/main/c/seasocks/Request.h b/third_party/seasocks/src/main/c/seasocks/Request.h
new file mode 100644
index 0000000..7c0e78a
--- /dev/null
+++ b/third_party/seasocks/src/main/c/seasocks/Request.h
@@ -0,0 +1,73 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include "seasocks/Credentials.h"
+
+#include <netinet/in.h>
+
+#include <cstdint>
+#include <memory>
+
+namespace seasocks {
+
+class Request {
+public:
+    virtual ~Request() {}
+
+    enum Verb {
+        Invalid,
+        WebSocket,
+        Get,
+        Put,
+        Post,
+        Delete,
+    };
+
+    virtual Verb verb() const = 0;
+
+    static const char* name(Verb v);
+    static Verb verb(const char *verb);
+
+    /**
+     * Returns the credentials associated with this request.
+     */
+    virtual std::shared_ptr<Credentials> credentials() const = 0;
+
+    virtual const sockaddr_in& getRemoteAddress() const = 0;
+
+    virtual const std::string& getRequestUri() const = 0;
+
+    virtual size_t contentLength() const = 0;
+
+    virtual const uint8_t* content() const = 0;
+
+    virtual bool hasHeader(const std::string& name) const = 0;
+
+    virtual std::string getHeader(const std::string& name) const = 0;
+};
+
+}  // namespace seasocks
diff --git a/third_party/seasocks/src/main/c/seasocks/Response.h b/third_party/seasocks/src/main/c/seasocks/Response.h
new file mode 100644
index 0000000..02cf03b
--- /dev/null
+++ b/third_party/seasocks/src/main/c/seasocks/Response.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include "seasocks/ResponseCode.h"
+
+#include <map>
+#include <memory>
+#include <string>
+
+namespace seasocks {
+
+class Response {
+public:
+    virtual ~Response() {}
+    virtual ResponseCode responseCode() const = 0;
+
+    virtual const char* payload() const = 0;
+    virtual size_t payloadSize() const = 0;
+
+    virtual std::string contentType() const = 0;
+
+    virtual bool keepConnectionAlive() const = 0;
+
+    typedef std::multimap<std::string, std::string> Headers;
+    virtual Headers getAdditionalHeaders() const = 0;
+
+    static std::shared_ptr<Response> unhandled();
+
+    static std::shared_ptr<Response> notFound();
+
+    static std::shared_ptr<Response> error(ResponseCode code, const std::string& error);
+
+    static std::shared_ptr<Response> textResponse(const std::string& response);
+    static std::shared_ptr<Response> jsonResponse(const std::string& response);
+    static std::shared_ptr<Response> htmlResponse(const std::string& response);
+};
+
+}
diff --git a/third_party/seasocks/src/main/c/seasocks/ResponseBuilder.cpp b/third_party/seasocks/src/main/c/seasocks/ResponseBuilder.cpp
new file mode 100644
index 0000000..f9f9b29
--- /dev/null
+++ b/third_party/seasocks/src/main/c/seasocks/ResponseBuilder.cpp
@@ -0,0 +1,90 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "seasocks/ResponseBuilder.h"
+
+#include "internal/ConcreteResponse.h"
+
+namespace seasocks {
+
+ResponseBuilder::ResponseBuilder(ResponseCode code) :
+        _code(code),
+        _contentType("text/plain"),
+        _keepAlive(true),
+        _stream(new std::ostringstream) {
+
+}
+
+ResponseBuilder& ResponseBuilder::asHtml() {
+    return withContentType("text/html");
+}
+
+ResponseBuilder& ResponseBuilder::asText() {
+    return withContentType("text/plain");
+}
+
+ResponseBuilder& ResponseBuilder::asJson() {
+    return withContentType("application/json");
+}
+
+ResponseBuilder& ResponseBuilder::withContentType(const std::string& contentType) {
+    _contentType = contentType;
+    return *this;
+}
+
+ResponseBuilder& ResponseBuilder::keepsConnectionAlive() {
+    _keepAlive = true;
+    return *this;
+}
+
+ResponseBuilder& ResponseBuilder::closesConnection() {
+    _keepAlive = false;
+    return *this;
+}
+
+ResponseBuilder& ResponseBuilder::withLocation(const std::string& location) {
+    return withHeader("Location", location);
+}
+
+ResponseBuilder& ResponseBuilder::setsCookie(const std::string& cookie, const std::string& value) {
+    return addHeader("Set-Cookie", cookie + "=" + value);
+}
+
+ResponseBuilder& ResponseBuilder::withHeader(const std::string& name, const std::string& value) {
+    _headers.erase(name);
+    _headers.insert(std::make_pair(name, value));
+    return *this;
+}
+
+ResponseBuilder& ResponseBuilder::addHeader(const std::string& name, const std::string& value) {
+    _headers.insert(std::make_pair(name, value));
+    return *this;
+}
+
+std::shared_ptr<Response> ResponseBuilder::build() {
+    return std::shared_ptr<Response>(new ConcreteResponse(_code, _stream->str(), _contentType, _headers, _keepAlive));
+}
+
+}
diff --git a/third_party/seasocks/src/main/c/seasocks/ResponseBuilder.h b/third_party/seasocks/src/main/c/seasocks/ResponseBuilder.h
new file mode 100644
index 0000000..0a268e8
--- /dev/null
+++ b/third_party/seasocks/src/main/c/seasocks/ResponseBuilder.h
@@ -0,0 +1,77 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include "seasocks/Response.h"
+
+#include <sstream>
+#include <string>
+
+namespace seasocks {
+
+class ResponseBuilder {
+    ResponseCode _code;
+    std::string _contentType;
+    bool _keepAlive;
+    Response::Headers _headers;
+    std::shared_ptr<std::ostringstream> _stream;
+public:
+    ResponseBuilder(ResponseCode code = ResponseCode::Ok);
+
+    ResponseBuilder& asHtml();
+    ResponseBuilder& asText();
+    ResponseBuilder& asJson();
+    ResponseBuilder& withContentType(const std::string& contentType);
+
+    ResponseBuilder& keepsConnectionAlive();
+    ResponseBuilder& closesConnection();
+
+    ResponseBuilder& withLocation(const std::string& location);
+
+    ResponseBuilder& setsCookie(const std::string& cookie, const std::string& value);
+
+    ResponseBuilder& withHeader(const std::string& name, const std::string& value);
+    template<typename T>
+    ResponseBuilder& withHeader(const std::string& name, const T& t) {
+        return withHeader(name, toString(t));
+    }
+
+    ResponseBuilder& addHeader(const std::string& name, const std::string& value);
+    template<typename T>
+    ResponseBuilder& addHeader(const std::string& name, const T& t) {
+        return addHeader(name, toString(t));
+    }
+
+    template<typename T>
+    ResponseBuilder& operator << (T&& t) {
+        (*_stream) << std::forward(t);
+        return *this;
+    }
+
+    std::shared_ptr<Response> build();
+};
+
+}
diff --git a/third_party/seasocks/src/main/c/seasocks/ResponseCode.cpp b/third_party/seasocks/src/main/c/seasocks/ResponseCode.cpp
new file mode 100644
index 0000000..71e88f6
--- /dev/null
+++ b/third_party/seasocks/src/main/c/seasocks/ResponseCode.cpp
@@ -0,0 +1,42 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "seasocks/ResponseCode.h"
+
+using namespace seasocks;
+
+bool isOk(seasocks::ResponseCode code) {
+    return static_cast<int>(code) < 400;
+}
+
+const char* name(ResponseCode code) {
+    switch (code) {
+#define SEASOCKS_DEFINE_RESPONSECODE(CODE,SYMBOLICNAME,STRINGNAME) case ResponseCode::SYMBOLICNAME: return STRINGNAME;
+#include "seasocks/ResponseCodeDefs.h"
+
+#undef SEASOCKS_DEFINE_RESPONSECODE
+    }
+    return "Unknown";
+}
diff --git a/third_party/seasocks/src/main/c/seasocks/ResponseCode.h b/third_party/seasocks/src/main/c/seasocks/ResponseCode.h
new file mode 100644
index 0000000..eab3463
--- /dev/null
+++ b/third_party/seasocks/src/main/c/seasocks/ResponseCode.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include <string>
+
+namespace seasocks {
+
+#define SEASOCKS_DEFINE_RESPONSECODE(CODE,SYMBOLICNAME,STRINGNAME) SYMBOLICNAME = CODE,
+enum class ResponseCode {
+#include "seasocks/ResponseCodeDefs.h"
+
+};
+#undef SEASOCKS_DEFINE_RESPONSECODE
+
+}
+
+const char* name(seasocks::ResponseCode code);
+bool isOk(seasocks::ResponseCode code);
diff --git a/third_party/seasocks/src/main/c/seasocks/ResponseCodeDefs.h b/third_party/seasocks/src/main/c/seasocks/ResponseCodeDefs.h
new file mode 100644
index 0000000..9b9878d
--- /dev/null
+++ b/third_party/seasocks/src/main/c/seasocks/ResponseCodeDefs.h
@@ -0,0 +1,68 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+// Not a normal header file - no header guards on purpose.
+// Do not directly include! Use ResponseCode.h instead
+
+#ifdef SEASOCKS_DEFINE_RESPONSECODE  // workaround for header check
+
+SEASOCKS_DEFINE_RESPONSECODE(100, Continue, "Continue")
+SEASOCKS_DEFINE_RESPONSECODE(101, WebSocketProtocolHandshake, "WebSocket Protocol Handshake")
+SEASOCKS_DEFINE_RESPONSECODE(102, Processing, "Processing")
+SEASOCKS_DEFINE_RESPONSECODE(103, Checkpoint, "Checkpoint")
+
+SEASOCKS_DEFINE_RESPONSECODE(200, Ok, "OK")
+SEASOCKS_DEFINE_RESPONSECODE(201, Created, "Created")
+SEASOCKS_DEFINE_RESPONSECODE(202, Accepted, "Accepted")
+SEASOCKS_DEFINE_RESPONSECODE(203, NonAuthoritativeInformation, "Non Authoritative Information")
+SEASOCKS_DEFINE_RESPONSECODE(204, NoContent, "No Content")
+SEASOCKS_DEFINE_RESPONSECODE(205, ResetContent, "Reset Content")
+SEASOCKS_DEFINE_RESPONSECODE(206, PartialContent, "Partial Content")
+SEASOCKS_DEFINE_RESPONSECODE(207, MultiStatus, "Multi-Status")
+SEASOCKS_DEFINE_RESPONSECODE(208, AlreadyReported, "Already Reported")
+SEASOCKS_DEFINE_RESPONSECODE(226, IMUsed, "IM Used")
+
+SEASOCKS_DEFINE_RESPONSECODE(300, MultipleChoices, "Multiple Choices")
+SEASOCKS_DEFINE_RESPONSECODE(301, MovedPermanently, "Moved Permanently")
+SEASOCKS_DEFINE_RESPONSECODE(302, Found, "Found")
+SEASOCKS_DEFINE_RESPONSECODE(303, SeeOther, "See Other")
+SEASOCKS_DEFINE_RESPONSECODE(304, NotModified, "Not Modified")
+SEASOCKS_DEFINE_RESPONSECODE(305, UseProxy, "Use Proxy")
+SEASOCKS_DEFINE_RESPONSECODE(306, SwitchProxy, "Switch Proxy")
+SEASOCKS_DEFINE_RESPONSECODE(307, TemporaryRedirect, "Temporary Redirect")
+SEASOCKS_DEFINE_RESPONSECODE(308, ResumeIncomplete, "Resume Incomplete")
+
+SEASOCKS_DEFINE_RESPONSECODE(400, BadRequest, "Bad Request")
+SEASOCKS_DEFINE_RESPONSECODE(401, Unauthorized, "Unauthorized")
+SEASOCKS_DEFINE_RESPONSECODE(402, PaymentRequired, "Payment Required")
+SEASOCKS_DEFINE_RESPONSECODE(403, Forbidden, "Forbidden")
+SEASOCKS_DEFINE_RESPONSECODE(404, NotFound, "Not Found")
+SEASOCKS_DEFINE_RESPONSECODE(405, MethodNotAllowed, "Method Not Allowed")
+// more here...
+
+SEASOCKS_DEFINE_RESPONSECODE(500, InternalServerError, "Internal Server Error")
+SEASOCKS_DEFINE_RESPONSECODE(501, NotImplemented, "Not Implemented")
+
+#endif
diff --git a/third_party/seasocks/src/main/c/seasocks/Server.h b/third_party/seasocks/src/main/c/seasocks/Server.h
new file mode 100644
index 0000000..4629a43
--- /dev/null
+++ b/third_party/seasocks/src/main/c/seasocks/Server.h
@@ -0,0 +1,172 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include "seasocks/ServerImpl.h"
+#include "seasocks/WebSocket.h"
+
+#include <sys/types.h>
+
+#include <atomic>
+#include <cstdint>
+#include <list>
+#include <map>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <unordered_map>
+
+namespace seasocks {
+
+class Connection;
+class Logger;
+class PageHandler;
+class Request;
+class Response;
+
+class Server : private ServerImpl {
+public:
+    Server(std::shared_ptr<Logger> logger);
+    virtual ~Server();
+
+    void addPageHandler(std::shared_ptr<PageHandler> handler);
+
+    void addWebSocketHandler(const char* endpoint, std::shared_ptr<WebSocket::Handler> handler,
+            bool allowCrossOriginRequests = false);
+
+    // If we haven't heard anything ever on a connection for this long, kill it.
+    // This is possibly caused by bad WebSocket implementation in Chrome.
+    void setLameConnectionTimeoutSeconds(int seconds);
+
+    // Sets the maximum number of TCP level keepalives that we can miss before
+    // we let the OS consider the connection dead. We configure keepalives every second,
+    // so this is also the minimum number of seconds it takes to notice a badly-behaved
+    // dead connection, e.g. a laptop going into sleep mode or a hard-crashed machine.
+    // A value of 0 disables keep alives, which is the default.
+    void setMaxKeepAliveDrops(int maxKeepAliveDrops);
+
+    // Serves static content from the given port on the current thread, until terminate is called.
+    // Roughly equivalent to startListening(port); setStaticPath(staticPath); loop();
+    // Returns whether exiting was expected.
+    bool serve(const char* staticPath, int port);
+
+    // Starts listening on a given interface (in host order) and port.
+    // Returns true if all was ok.
+    bool startListening(uint32_t ipInHostOrder, int port);
+
+    // Starts listening on a port on all interfaces.
+    // Returns true if all was ok.
+    bool startListening(int port);
+
+    // Sets the path to server static content from.
+    void setStaticPath(const char* staticPath);
+
+    // Loop (until terminate called from another thread).
+    // Returns true if terminate() was used to exit the loop, false if there
+    // was an error.
+    bool loop();
+
+    // Runs a single iteration of the main loop, blocking for a given time.
+    // Returns immediately if terminate() has been called. Must be consistently
+    // called from the same thread. Returns an enum describing why it returned.
+    enum class PollResult {
+        Continue,
+        Terminated,
+        Error,
+    };
+    PollResult poll(int millisToBlock);
+
+    // Returns a file descriptor that can be polled for changes (e.g. by
+    // placing it in an epoll set. The poll() method above only need be called
+    // when this file descriptor is readable.
+    int fd() const { return _epollFd; }
+
+    // Terminate any loop() or poll(). May be called from any thread.
+    void terminate();
+
+    class Runnable {
+    public:
+        virtual ~Runnable() {}
+        virtual void run() = 0;
+    };
+    // Execute a task on the SeaSocks thread.
+    void execute(std::shared_ptr<Runnable> runnable);
+
+private:
+    // From ServerImpl
+    virtual void remove(Connection* connection) override;
+    virtual bool subscribeToWriteEvents(Connection* connection) override;
+    virtual bool unsubscribeFromWriteEvents(Connection* connection) override;
+    virtual const std::string& getStaticPath() const override { return _staticPath; }
+    virtual std::shared_ptr<WebSocket::Handler> getWebSocketHandler(const char* endpoint) const override;
+    virtual bool isCrossOriginAllowed(const std::string &endpoint) const override;
+    virtual std::shared_ptr<Response> handle(const Request &request) override;
+    virtual std::string getStatsDocument() const override;
+    virtual void checkThread() const override;
+
+    bool makeNonBlocking(int fd) const;
+    bool configureSocket(int fd) const;
+    void handleAccept();
+    std::shared_ptr<Runnable> popNextRunnable();
+    void processEventQueue();
+
+    void shutdown();
+
+    void checkAndDispatchEpoll(int epollMillis);
+    void handlePipe();
+    enum NewState { KeepOpen, Close };
+    NewState handleConnectionEvents(Connection* connection, uint32_t events);
+
+    // Connections, mapped to initial connection time.
+    std::map<Connection*, time_t> _connections;
+    std::shared_ptr<Logger> _logger;
+    int _listenSock;
+    int _epollFd;
+    int _eventFd;
+    int _maxKeepAliveDrops;
+    int _lameConnectionTimeoutSeconds;
+    time_t _nextDeadConnectionCheck;
+
+    struct WebSocketHandlerEntry {
+        std::shared_ptr<WebSocket::Handler> handler;
+        bool allowCrossOrigin;
+    };
+    typedef std::unordered_map<std::string, WebSocketHandlerEntry> WebSocketHandlerMap;
+    WebSocketHandlerMap _webSocketHandlerMap;
+
+    std::list<std::shared_ptr<PageHandler>> _pageHandlers;
+
+    std::mutex _pendingRunnableMutex;
+    std::list<std::shared_ptr<Runnable>> _pendingRunnables;
+
+    pid_t _threadId;
+
+    std::string _staticPath;
+    std::atomic<bool> _terminate;
+    std::atomic<bool> _expectedTerminate;
+};
+
+}  // namespace seasocks
diff --git a/third_party/seasocks/src/main/c/seasocks/ServerImpl.h b/third_party/seasocks/src/main/c/seasocks/ServerImpl.h
new file mode 100644
index 0000000..e7dd46a
--- /dev/null
+++ b/third_party/seasocks/src/main/c/seasocks/ServerImpl.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include "seasocks/WebSocket.h"
+
+#include <string>
+
+namespace seasocks {
+
+class Connection;
+class Request;
+class Response;
+
+// Internal implementation used to give access to internals to Connections.
+class ServerImpl {
+public:
+    virtual ~ServerImpl() {}
+
+    virtual void remove(Connection* connection) = 0;
+    virtual bool subscribeToWriteEvents(Connection* connection) = 0;
+    virtual bool unsubscribeFromWriteEvents(Connection* connection) = 0;
+    virtual const std::string& getStaticPath() const = 0;
+    virtual std::shared_ptr<WebSocket::Handler> getWebSocketHandler(const char* endpoint) const = 0;
+    virtual bool isCrossOriginAllowed(const std::string &endpoint) const = 0;
+    virtual std::shared_ptr<Response> handle(const Request &request) = 0;
+    virtual std::string getStatsDocument() const = 0;
+    virtual void checkThread() const = 0;
+};
+
+}
diff --git a/third_party/seasocks/src/main/c/seasocks/StringUtil.h b/third_party/seasocks/src/main/c/seasocks/StringUtil.h
new file mode 100644
index 0000000..3109104
--- /dev/null
+++ b/third_party/seasocks/src/main/c/seasocks/StringUtil.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include <netinet/in.h>
+
+#include <string>
+#include <vector>
+
+namespace seasocks {
+
+char* skipWhitespace(char* str);
+char* skipNonWhitespace(char* str);
+char* shift(char*& str);
+
+std::string getLastError();
+std::string formatAddress(const sockaddr_in& address);
+
+std::vector<std::string> split(const std::string& input, char splitChar);
+
+void replace(std::string& string, const std::string& find, const std::string& replace);
+
+bool caseInsensitiveSame(const std::string &lhs, const std::string &rhs);
+
+}  // namespace seasocks
diff --git a/third_party/seasocks/src/main/c/seasocks/ToString.h b/third_party/seasocks/src/main/c/seasocks/ToString.h
new file mode 100644
index 0000000..40f607e
--- /dev/null
+++ b/third_party/seasocks/src/main/c/seasocks/ToString.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include <sstream>
+#include <string>
+
+namespace seasocks {
+
+template<typename T>
+std::string toString(const T& obj) {
+    std::stringstream str;
+    str << obj;
+    return str.str();
+}
+
+}
diff --git a/third_party/seasocks/src/main/c/seasocks/WebSocket.h b/third_party/seasocks/src/main/c/seasocks/WebSocket.h
new file mode 100644
index 0000000..f52509a
--- /dev/null
+++ b/third_party/seasocks/src/main/c/seasocks/WebSocket.h
@@ -0,0 +1,86 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include "seasocks/Request.h"
+
+#include <vector>
+
+namespace seasocks {
+
+class WebSocket : public Request {
+public:
+    /**
+     * Send the given text data. Must be called on the seasocks thread.
+     * See Server::execute for how to run work on the seasocks
+     * thread externally.
+     */
+    virtual void send(const char* data) = 0;
+    /**
+     * Send the given binary data. Must be called on the seasocks thread.
+     * See Server::execute for how to run work on the seasocks
+     * thread externally.
+     */
+    virtual void send(const uint8_t* data, size_t length) = 0;
+    /**
+     * Close the socket. It's invalid to access the socket after
+     * calling close(). The Handler::onDisconnect() call may occur
+     * at a later time.
+     */
+    virtual void close() = 0;
+
+    /**
+     * Interface to dealing with WebSocket connections.
+     */
+    class Handler {
+    public:
+        virtual ~Handler() { }
+
+        /**
+         * Called on the seasocks thread during initial connection.
+         */
+        virtual void onConnect(WebSocket* connection) = 0;
+        /**
+         * Called on the seasocks thread with upon receipt of a full text WebSocket message.
+         */
+        virtual void onData(WebSocket* connection, const char* data) {}
+        /**
+         * Called on the seasocks thread with upon receipt of a full binary WebSocket message.
+         */
+        virtual void onData(WebSocket* connection, const uint8_t* data, size_t length) {}
+        /**
+         * Called on the seasocks thread when the socket has been
+         */
+        virtual void onDisconnect(WebSocket* connection) = 0;
+    };
+
+protected:
+    // To delete a WebSocket, just close it. It is owned by the Server, and
+    // the server will delete it when it's finished.
+    virtual ~WebSocket() {}
+};
+
+}  // namespace seasocks
diff --git a/third_party/seasocks/src/main/c/seasocks/util/CrackedUri.h b/third_party/seasocks/src/main/c/seasocks/util/CrackedUri.h
new file mode 100644
index 0000000..681ea42
--- /dev/null
+++ b/third_party/seasocks/src/main/c/seasocks/util/CrackedUri.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+namespace seasocks {
+
+class CrackedUri {
+    std::vector<std::string> _path;
+    std::unordered_multimap<std::string, std::string> _queryParams;
+
+public:
+    CrackedUri(const std::string& uri);
+
+    const std::vector<std::string>& path() const { return _path; }
+    const std::unordered_multimap<std::string, std::string> queryParams() const { return _queryParams; }
+
+    bool hasParam(const std::string& param) const;
+
+    // Returns the user-supplied default if not present. Returns the first found in the case of multiple params.
+    std::string queryParam(const std::string& param, const std::string& def = std::string()) const;
+
+    std::vector<std::string> allQueryParams(const std::string& param) const;
+
+    // Returns a new uri with the frontmost path item shifted off.  The path
+    // is always guaranteed to be non-empty. In the case of shifting the last
+    // path element, returns a path of {""}.
+    CrackedUri shift() const;
+};
+
+}
diff --git a/third_party/seasocks/src/main/c/seasocks/util/CrackedUriPageHandler.h b/third_party/seasocks/src/main/c/seasocks/util/CrackedUriPageHandler.h
new file mode 100644
index 0000000..cf8c362
--- /dev/null
+++ b/third_party/seasocks/src/main/c/seasocks/util/CrackedUriPageHandler.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include "seasocks/Request.h"
+#include "seasocks/Response.h"
+#include "seasocks/util/CrackedUri.h"
+
+#include <memory>
+
+namespace seasocks {
+
+class CrackedUriPageHandler {
+public:
+    virtual ~CrackedUriPageHandler() {}
+
+    virtual std::shared_ptr<Response> handle(const CrackedUri& uri, const Request& request) = 0;
+
+    typedef std::shared_ptr<CrackedUriPageHandler> Ptr;
+};
+
+}
diff --git a/third_party/seasocks/src/main/c/seasocks/util/Html.h b/third_party/seasocks/src/main/c/seasocks/util/Html.h
new file mode 100644
index 0000000..6b3e887
--- /dev/null
+++ b/third_party/seasocks/src/main/c/seasocks/util/Html.h
@@ -0,0 +1,206 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include "seasocks/ToString.h"
+
+#include <functional>
+#include <iostream>
+#include <list>
+#include <sstream>
+#include <string>
+
+namespace seasocks {
+
+namespace html {
+
+class Element {
+    bool _isTextNode;
+    bool _needsClose;
+    std::string _nameOrText;
+    std::string _attributes;
+    std::list<Element> _children;
+
+    void append() {
+    }
+
+    template<typename T, typename... Args>
+    void append(const T& t, Args&& ...args) {
+        operator<<(t);
+        append(std::forward<Args>(args)...);
+    }
+
+    Element() : _isTextNode(true), _needsClose(false) {}
+public:
+    template<typename... Args>
+    Element(const std::string& name, bool needsClose, Args&&... args) :
+        _isTextNode(false),
+        _needsClose(needsClose),
+        _nameOrText(name) {
+        append(std::forward<Args>(args)...);
+    }
+
+    template<typename T>
+    static Element textElement(const T& text) {
+        Element e;
+        e._nameOrText = toString(text);
+        return e;
+    }
+
+    template<typename T>
+    Element& addAttribute(const char* attr, const T& value) {
+        _attributes += std::string(" ") + attr + "=\"" + toString(value) + "\"";
+        return *this;
+    }
+
+    Element& clazz(const std::string& clazz) {
+        return addAttribute("class", clazz);
+    }
+
+    Element& title(const std::string& title) {
+        return addAttribute("title", title);
+    }
+
+    Element& style(const std::string& style) {
+        return addAttribute("style", style);
+    }
+
+    Element& alt(const std::string& alt) {
+        return addAttribute("alt", alt);
+    }
+
+    Element& hidden() {
+        return addAttribute("style", "display:none;");
+    }
+
+    Element& id(const std::string& id) {
+        return addAttribute("id", id);
+    }
+
+    Element& operator <<(const char* child) {
+        _children.push_back(textElement(child));
+        return *this;
+    }
+
+    Element& operator <<(const std::string& child) {
+        _children.push_back(textElement(child));
+        return *this;
+    }
+
+    Element& operator <<(const Element& child) {
+        _children.push_back(child);
+        return *this;
+    }
+
+    template<class T>
+    typename std::enable_if<std::is_integral<T>::value || std::is_floating_point<T>::value, Element&>::type
+    operator <<(const T& child) {
+        _children.push_back(textElement(child));
+        return *this;
+    }
+
+    friend std::ostream& operator << (std::ostream& os, const Element& elem) {
+        if (elem._isTextNode) {
+            os << elem._nameOrText;
+            for (auto it = elem._children.cbegin(); it != elem._children.cend(); ++it) {
+                os << *it;
+            }
+            return os;
+        }
+        os << "<" << elem._nameOrText << elem._attributes << ">";
+        for (auto it = elem._children.cbegin(); it != elem._children.cend(); ++it) {
+            os << *it;
+        }
+        if (elem._needsClose) {
+            os << "</" << elem._nameOrText << ">";
+        }
+        return os;
+    }
+
+    template<typename C, typename F>
+    Element& addAll(const C& container, F functor) {
+        for (auto it = container.cbegin(); it != container.cend(); ++it) {
+            operator<<(functor(*it));
+        }
+        return *this;
+    }
+
+    std::string str() const {
+        std::ostringstream os;
+        os << *this;
+        return os.str();
+    }
+};
+
+#define HTMLELEM(XX) template<typename... Args> inline Element XX(Args&&... args) { return Element(#XX, true, std::forward<Args>(args)...); }
+HTMLELEM(html)
+HTMLELEM(head)
+HTMLELEM(title)
+HTMLELEM(body)
+HTMLELEM(h1)
+HTMLELEM(h2)
+HTMLELEM(h3)
+HTMLELEM(h4)
+HTMLELEM(h5)
+HTMLELEM(table)
+HTMLELEM(thead)
+HTMLELEM(tbody)
+HTMLELEM(tr)
+HTMLELEM(td)
+HTMLELEM(th)
+HTMLELEM(div)
+HTMLELEM(span)
+HTMLELEM(ul)
+HTMLELEM(ol)
+HTMLELEM(li)
+HTMLELEM(label)
+HTMLELEM(button)
+#undef HTMLELEM
+
+inline Element empty() { return Element::textElement(""); }
+
+template<typename T>
+inline Element text(const T& t) { return Element::textElement(t); }
+
+inline Element img(const std::string& src) { return Element("img", false).addAttribute("src", src); }
+
+inline Element checkbox() { return Element("input", false).addAttribute("type", "checkbox"); }
+
+inline Element externalScript(const std::string& src) { return Element("script", true).addAttribute("src", src).addAttribute("type", "text/javascript"); }
+
+inline Element inlineScript(const std::string& script) { return Element("script", true, script).addAttribute("type", "text/javascript"); }
+
+inline Element link(const std::string& href, const std::string& rel) {
+    return Element("link", false).addAttribute("href", href).addAttribute("rel", rel);
+}
+
+template<typename...Args> inline Element a(const std::string& href, Args&&... args) {
+    return Element("a", true, std::forward<Args>(args)...).addAttribute("href", href);
+}
+
+}  // namespace html
+
+}  // namespace seasocks
diff --git a/third_party/seasocks/src/main/c/seasocks/util/Json.h b/third_party/seasocks/src/main/c/seasocks/util/Json.h
new file mode 100644
index 0000000..c8a69dc
--- /dev/null
+++ b/third_party/seasocks/src/main/c/seasocks/util/Json.h
@@ -0,0 +1,233 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include <algorithm>
+#include <ctime>
+#include <iostream>
+#include <map>
+#include <sstream>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+namespace seasocks {
+
+///////////////////////////////////
+
+inline void jsonToStream(std::ostream& str) {}
+
+void jsonToStream(std::ostream& str, const char* t);
+
+void jsonToStream(std::ostream& str, bool b);
+
+inline void jsonToStream(std::ostream& str, const std::string& t) {
+    jsonToStream(str, t.c_str());
+}
+
+template<typename O>
+class is_jsonable {
+    template<typename OO>
+    static auto test(int)
+    -> decltype(&OO::jsonToStream, std::true_type());
+
+    template<typename>
+    static auto test(...) -> std::false_type;
+
+public:
+    static constexpr bool value = decltype(test<O>(0))::value;
+};
+
+template<typename T>
+class is_streamable {
+    template<typename TT>
+    static auto test(int)
+    -> decltype(std::declval<std::ostream&>() << std::declval<TT>(), std::true_type());
+
+    template<typename>
+    static auto test(...) -> std::false_type;
+
+public:
+    static constexpr bool value = decltype(test<T>(0))::value;
+};
+
+template<typename T>
+typename std::enable_if<std::is_fundamental<T>::value, void>::type
+jsonToStream(std::ostream& str, const T& t) {
+    str << t;
+}
+
+template<typename T>
+typename std::enable_if<is_jsonable<T>::value, void>::type
+jsonToStream(std::ostream& str, const T& t) {
+    t.jsonToStream(str);
+}
+
+template<typename T>
+typename std::enable_if<
+    !std::is_fundamental<T>::value
+    && is_streamable<T>::value
+    && !is_jsonable<T>::value, void>::type
+jsonToStream(std::ostream& str, const T& t) {
+    str << '"' << t << '"';
+}
+
+template<typename T, typename ... Args>
+void jsonToStream(std::ostream& str, const T& t, Args&&... args) {
+    static_assert(sizeof...(Args) > 0, "Cannot stream an object with no jsonToStream or operator<< method.");
+    jsonToStream(str, t);
+    str << ",";
+    jsonToStream(str, std::forward<Args>(args)...);
+}
+
+///////////////////////////////////
+
+inline void jsonKeyPairToStream(std::ostream& str) {}
+
+template<typename T>
+void jsonKeyPairToStream(std::ostream& str, const char* key, const T& value) {
+    jsonToStream(str, key);
+    str << ":";
+    jsonToStream(str, value);
+}
+
+template<typename T>
+void jsonKeyPairToStream(std::ostream& str, const std::string& key, const T& value) {
+    jsonKeyPairToStream(str, key.c_str(), value);
+}
+
+template<typename T>
+void jsonKeyPairToStream(std::ostream& str, const T&) {
+    static_assert(!std::is_same<T, T>::value,  // To make the assertion depend on T
+            "Requires an even number of parameters. If you're trying to build a map from an existing std::map or similar, use makeMapFromContainer");
+}
+
+template<typename K, typename V, typename... Args>
+void jsonKeyPairToStream(std::ostream& str, const K& key, const V& value, Args&&... args) {
+    jsonKeyPairToStream(str, key, value);
+    str << ",";
+    jsonKeyPairToStream(str, std::forward<Args>(args)...);
+}
+
+struct JsonnedString : std::string {
+    JsonnedString() {}
+    JsonnedString(const std::string& s) : std::string(s) {}
+    JsonnedString(const std::stringstream& str) : std::string(str.str()) {}
+    void jsonToStream(std::ostream &o) const {
+        o << *this;
+    }
+};
+static_assert(is_streamable<JsonnedString>::value, "Internal stream problem");
+static_assert(is_jsonable<JsonnedString>::value, "Internal stream problem");
+
+struct EpochTimeAsLocal {
+    time_t t;
+    EpochTimeAsLocal(time_t t) : t(t) {}
+    void jsonToStream(std::ostream &o) const;
+};
+static_assert(is_jsonable<EpochTimeAsLocal>::value, "Internal stream problem");
+
+template<typename... Args>
+JsonnedString makeMap(Args&&... args) {
+    std::stringstream str;
+    str << '{';
+    jsonKeyPairToStream(str, std::forward<Args>(args)...);
+    str << '}';
+    return JsonnedString(str);
+}
+
+template<typename T>
+JsonnedString makeMapFromContainer(const T& m) {
+    std::stringstream str;
+    str << "{";
+    bool first = true;
+    for (const auto &it : m) {
+        if (!first) str << ",";
+        first = false;
+        jsonKeyPairToStream(str, it.first, it.second);
+    }
+    str << "}";
+    return JsonnedString(str);
+}
+
+template<typename ... Args>
+JsonnedString makeArray(Args&&... args) {
+    std::stringstream str;
+    str << '[';
+    jsonToStream(str, std::forward<Args>(args)...);
+    str << ']';
+    return JsonnedString(str);
+}
+
+template<typename T>
+JsonnedString makeArrayFromContainer(const T &list) {
+    std::stringstream str;
+    str << '[';
+    bool first = true;
+    for (const auto &s : list) {
+        if (!first) {
+            str << ',';
+        }
+        first = false;
+        jsonToStream(str, s);
+    };
+    str << ']';
+    return JsonnedString(str);
+}
+
+template<typename T>
+JsonnedString makeArray(const std::initializer_list<T> &list) {
+    std::stringstream str;
+    str << '[';
+    bool first = true;
+    for (const auto &s : list) {
+        if (!first) {
+            str << ',';
+        }
+        first = false;
+        jsonToStream(str, s);
+    };
+    str << ']';
+    return JsonnedString(str);
+}
+
+template<typename ... Args>
+JsonnedString makeExecString(const char* function, Args&&... args) {
+    std::stringstream str;
+    str << function << '(';
+    jsonToStream(str, std::forward<Args>(args)...);
+    str << ')';
+    return JsonnedString(str);
+}
+
+template<typename T>
+JsonnedString to_json(const T &obj) {
+    std::stringstream str;
+    jsonToStream(str, obj);
+    return str.str();
+}
+
+}
diff --git a/third_party/seasocks/src/main/c/seasocks/util/PathHandler.h b/third_party/seasocks/src/main/c/seasocks/util/PathHandler.h
new file mode 100644
index 0000000..275f829
--- /dev/null
+++ b/third_party/seasocks/src/main/c/seasocks/util/PathHandler.h
@@ -0,0 +1,68 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include "seasocks/util/CrackedUriPageHandler.h"
+
+#include <string>
+
+namespace seasocks {
+
+// Handles a subpath of a website.  Passes on a shifted path to the registered
+// subhandlers.  Useful, for example, to place a bunch of handlers beneath a
+// common subpath on the server, e.g.
+// PathHandler("debug")
+//   .add(make_shared<DebugStatsHandler>())
+//   .add(make_shared<AnotherDebugThing>())
+//   .add(...) etc
+// Each handler's CrackedUri will be shifted (i.e. won't have the "debug"
+// prefix)
+class PathHandler : public CrackedUriPageHandler {
+    std::string _path;
+    std::vector<CrackedUriPageHandler::Ptr> _handlers;
+
+public:
+    PathHandler(const std::string &path) : _path(path) {}
+    template<typename... Args>
+    PathHandler(const std::string &path, Args&&... args) : _path(path) {
+        addMany(std::forward<Args>(args)...);
+    }
+
+    CrackedUriPageHandler::Ptr add(const CrackedUriPageHandler::Ptr& handler);
+
+    void addMany() {}
+    void addMany(const CrackedUriPageHandler::Ptr& handler) { add(handler); }
+    template<typename... Rest>
+    void addMany(const CrackedUriPageHandler::Ptr& handler, Rest&&... rest) {
+        add(handler);
+        addMany(std::forward<Rest>(rest)...);
+    }
+
+    virtual std::shared_ptr<Response> handle(
+            const CrackedUri& uri, const Request& request) override;
+};
+
+}
diff --git a/third_party/seasocks/src/main/c/seasocks/util/RootPageHandler.h b/third_party/seasocks/src/main/c/seasocks/util/RootPageHandler.h
new file mode 100644
index 0000000..2c2ce1a
--- /dev/null
+++ b/third_party/seasocks/src/main/c/seasocks/util/RootPageHandler.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include "seasocks/PageHandler.h"
+#include "seasocks/util/CrackedUriPageHandler.h"
+
+#include <memory>
+#include <vector>
+
+namespace seasocks {
+
+class RootPageHandler : public PageHandler {
+    std::vector<CrackedUriPageHandler::Ptr> _handlers;
+
+public:
+    RootPageHandler();
+    virtual ~RootPageHandler();
+
+    CrackedUriPageHandler::Ptr add(const CrackedUriPageHandler::Ptr& handler);
+
+    // From PageHandler.
+    virtual std::shared_ptr<Response> handle(const Request& request) override;
+};
+
+}
diff --git a/third_party/seasocks/src/main/c/seasocks/util/StaticResponseHandler.h b/third_party/seasocks/src/main/c/seasocks/util/StaticResponseHandler.h
new file mode 100644
index 0000000..ff6c5e7
--- /dev/null
+++ b/third_party/seasocks/src/main/c/seasocks/util/StaticResponseHandler.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include <seasocks/util/CrackedUriPageHandler.h>
+#include <seasocks/Response.h>
+
+#include <memory>
+
+namespace seasocks {
+
+// Returns a canned response for a given pathname.
+class StaticResponseHandler : public CrackedUriPageHandler {
+    std::string _path;
+    std::shared_ptr<Response> _response;
+
+public:
+    StaticResponseHandler(const std::string& path, std::shared_ptr<Response> response)
+    : _path(path), _response(response) {}
+
+    virtual std::shared_ptr<Response> handle(
+            const CrackedUri& uri,
+            const Request&) override {
+        if (uri.path().size() != 1 || uri.path()[0] != _path)
+            return Response::unhandled();
+        return _response;
+    }
+};
+
+}
diff --git a/third_party/seasocks/src/main/c/sha1/Makefile b/third_party/seasocks/src/main/c/sha1/Makefile
new file mode 100644
index 0000000..66aaf2b
--- /dev/null
+++ b/third_party/seasocks/src/main/c/sha1/Makefile
@@ -0,0 +1,41 @@
+#
+#  Makefile
+#  
+#  Copyright (C) 1998, 2009
+#  Paul E. Jones <paulej@packetizer.com>
+#  All Rights Reserved.
+#
+#############################################################################
+#  $Id: Makefile 12 2009-06-22 19:34:25Z paulej $
+#############################################################################
+#
+#  Description:
+#	This is a makefile for UNIX to build the programs sha, shacmp, and
+#	shatest
+#
+#
+
+CC	= g++
+
+CFLAGS	= -c -O2 -Wall -D_FILE_OFFSET_BITS=64
+
+LIBS	=
+
+OBJS	= sha1.o
+
+all: sha shacmp shatest
+
+sha: sha.o $(OBJS)
+	$(CC) -o $@ sha.o $(OBJS) $(LIBS)
+
+shacmp: shacmp.o $(OBJS)
+	$(CC) -o $@ shacmp.o $(OBJS) $(LIBS)
+
+shatest: shatest.o $(OBJS)
+	$(CC) -o $@ shatest.o $(OBJS) $(LIBS)
+
+%.o: %.cpp
+	$(CC) $(CFLAGS) -o $@ $<
+
+clean:
+	$(RM) *.o sha shacmp shatest
diff --git a/third_party/seasocks/src/main/c/sha1/Makefile.nt b/third_party/seasocks/src/main/c/sha1/Makefile.nt
new file mode 100644
index 0000000..9bacf64
--- /dev/null
+++ b/third_party/seasocks/src/main/c/sha1/Makefile.nt
@@ -0,0 +1,48 @@
+#

+#  Makefile.nt

+#  

+#  Copyright (C) 1998, 2009

+#  Paul E. Jones <paulej@packetizer.com>

+#  All Rights Reserved.

+#

+#############################################################################

+#  $Id: Makefile.nt 13 2009-06-22 20:20:32Z paulej $

+#############################################################################

+#

+#  Description:

+#	This is a makefile for Win32 to build the programs sha, shacmp, and

+#	shatest

+#

+#  Portability Issues:

+#	Designed to work with Visual C++

+#

+#

+

+.silent:

+

+!include <win32.mak>

+

+RM	= del /q

+

+LIBS	= $(conlibs) setargv.obj

+

+CFLAGS	= -D _CRT_SECURE_NO_WARNINGS /EHsc /O2 /W3

+

+OBJS	= sha1.obj

+

+all: sha.exe shacmp.exe shatest.exe

+

+sha.exe: sha.obj $(OBJS)

+	$(link) $(conflags) -out:$@ sha.obj $(OBJS) $(LIBS)

+

+shacmp.exe: shacmp.obj $(OBJS)

+	$(link) $(conflags) -out:$@ shacmp.obj $(OBJS) $(LIBS)

+

+shatest.exe: shatest.obj $(OBJS)

+	$(link) $(conflags) -out:$@ shatest.obj $(OBJS) $(LIBS)

+

+.cpp.obj:

+	$(cc) $(CFLAGS) $(cflags) $(cvars) $<

+

+clean:

+	$(RM) *.obj sha.exe shacmp.exe shatest.exe

diff --git a/third_party/seasocks/src/main/c/sha1/license.txt b/third_party/seasocks/src/main/c/sha1/license.txt
new file mode 100644
index 0000000..8d7f394
--- /dev/null
+++ b/third_party/seasocks/src/main/c/sha1/license.txt
@@ -0,0 +1,14 @@
+Copyright (C) 1998, 2009

+Paul E. Jones <paulej@packetizer.com>

+

+Freeware Public License (FPL)

+

+This software is licensed as "freeware."  Permission to distribute

+this software in source and binary forms, including incorporation 

+into other products, is hereby granted without a fee.  THIS SOFTWARE 

+IS PROVIDED 'AS IS' AND WITHOUT ANY EXPRESSED OR IMPLIED WARRANTIES, 

+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 

+AND FITNESS FOR A PARTICULAR PURPOSE.  THE AUTHOR SHALL NOT BE HELD 

+LIABLE FOR ANY DAMAGES RESULTING FROM THE USE OF THIS SOFTWARE, EITHER 

+DIRECTLY OR INDIRECTLY, INCLUDING, BUT NOT LIMITED TO, LOSS OF DATA 

+OR DATA BEING RENDERED INACCURATE.

diff --git a/third_party/seasocks/src/main/c/sha1/sha1.cpp b/third_party/seasocks/src/main/c/sha1/sha1.cpp
new file mode 100644
index 0000000..9a42766
--- /dev/null
+++ b/third_party/seasocks/src/main/c/sha1/sha1.cpp
@@ -0,0 +1,615 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+// DO NOT REFORMAT <- for tidy
+/*
+ *  sha1.cpp
+ *
+ *  Copyright (C) 1998, 2009
+ *  Paul E. Jones <paulej@packetizer.com>
+ *  All Rights Reserved.
+ *
+ *****************************************************************************
+ *  $Id: sha1.cpp 12 2009-06-22 19:34:25Z paulej $
+ *****************************************************************************
+ *
+ *  Description:
+ *      This class implements the Secure Hashing Standard as defined
+ *      in FIPS PUB 180-1 published April 17, 1995.
+ *
+ *      The Secure Hashing Standard, which uses the Secure Hashing
+ *      Algorithm (SHA), produces a 160-bit message digest for a
+ *      given data stream.  In theory, it is highly improbable that
+ *      two messages will produce the same message digest.  Therefore,
+ *      this algorithm can serve as a means of providing a "fingerprint"
+ *      for a message.
+ *
+ *  Portability Issues:
+ *      SHA-1 is defined in terms of 32-bit "words".  This code was
+ *      written with the expectation that the processor has at least
+ *      a 32-bit machine word size.  If the machine word size is larger,
+ *      the code should still function properly.  One caveat to that
+ *      is that the input functions taking characters and character arrays
+ *      assume that only 8 bits of information are stored in each character.
+ *
+ *  Caveats:
+ *      SHA-1 is designed to work with messages less than 2^64 bits long.
+ *      Although SHA-1 allows a message digest to be generated for
+ *      messages of any number of bits less than 2^64, this implementation
+ *      only works with messages with a length that is a multiple of 8
+ *      bits.
+ *
+ */
+
+
+#include "sha1.h"
+
+/*  
+ *  SHA1
+ *
+ *  Description:
+ *      This is the constructor for the sha1 class.
+ *
+ *  Parameters:
+ *      None.
+ *
+ *  Returns:
+ *      Nothing.
+ *
+ *  Comments:
+ *
+ */
+SHA1::SHA1()
+{
+    Reset();
+}
+
+/*  
+ *  ~SHA1
+ *
+ *  Description:
+ *      This is the destructor for the sha1 class
+ *
+ *  Parameters:
+ *      None.
+ *
+ *  Returns:
+ *      Nothing.
+ *
+ *  Comments:
+ *
+ */
+SHA1::~SHA1()
+{
+    // The destructor does nothing
+}
+
+/*  
+ *  Reset
+ *
+ *  Description:
+ *      This function will initialize the sha1 class member variables
+ *      in preparation for computing a new message digest.
+ *
+ *  Parameters:
+ *      None.
+ *
+ *  Returns:
+ *      Nothing.
+ *
+ *  Comments:
+ *
+ */
+void SHA1::Reset()
+{
+    Length_Low          = 0;
+    Length_High         = 0;
+    Message_Block_Index = 0;
+
+    H[0]        = 0x67452301;
+    H[1]        = 0xEFCDAB89;
+    H[2]        = 0x98BADCFE;
+    H[3]        = 0x10325476;
+    H[4]        = 0xC3D2E1F0;
+
+    Computed    = false;
+    Corrupted   = false;
+}
+
+/*  
+ *  Result
+ *
+ *  Description:
+ *      This function will return the 160-bit message digest into the
+ *      array provided.
+ *
+ *  Parameters:
+ *      message_digest_array: [out]
+ *          This is an array of five unsigned integers which will be filled
+ *          with the message digest that has been computed.
+ *
+ *  Returns:
+ *      True if successful, false if it failed.
+ *
+ *  Comments:
+ *
+ */
+bool SHA1::Result(unsigned *message_digest_array)
+{
+    int i;                                  // Counter
+
+    if (Corrupted)
+    {
+        return false;
+    }
+
+    if (!Computed)
+    {
+        PadMessage();
+        Computed = true;
+    }
+
+    for(i = 0; i < 5; i++)
+    {
+        message_digest_array[i] = H[i];
+    }
+
+    return true;
+}
+
+/*  
+ *  Input
+ *
+ *  Description:
+ *      This function accepts an array of octets as the next portion of
+ *      the message.
+ *
+ *  Parameters:
+ *      message_array: [in]
+ *          An array of characters representing the next portion of the
+ *          message.
+ *
+ *  Returns:
+ *      Nothing.
+ *
+ *  Comments:
+ *
+ */
+void SHA1::Input(   const unsigned char *message_array,
+                    unsigned            length)
+{
+    if (!length)
+    {
+        return;
+    }
+
+    if (Computed || Corrupted)
+    {
+        Corrupted = true;
+        return;
+    }
+
+    while(length-- && !Corrupted)
+    {
+        Message_Block[Message_Block_Index++] = (*message_array & 0xFF);
+
+        Length_Low += 8;
+        Length_Low &= 0xFFFFFFFF;               // Force it to 32 bits
+        if (Length_Low == 0)
+        {
+            Length_High++;
+            Length_High &= 0xFFFFFFFF;          // Force it to 32 bits
+            if (Length_High == 0)
+            {
+                Corrupted = true;               // Message is too long
+            }
+        }
+
+        if (Message_Block_Index == 64)
+        {
+            ProcessMessageBlock();
+        }
+
+        message_array++;
+    }
+}
+
+/*  
+ *  Input
+ *
+ *  Description:
+ *      This function accepts an array of octets as the next portion of
+ *      the message.
+ *
+ *  Parameters:
+ *      message_array: [in]
+ *          An array of characters representing the next portion of the
+ *          message.
+ *      length: [in]
+ *          The length of the message_array
+ *
+ *  Returns:
+ *      Nothing.
+ *
+ *  Comments:
+ *
+ */
+void SHA1::Input(   const char  *message_array,
+                    unsigned    length)
+{
+    Input((unsigned char *) message_array, length);
+}
+
+/*  
+ *  Input
+ *
+ *  Description:
+ *      This function accepts a single octets as the next message element.
+ *
+ *  Parameters:
+ *      message_element: [in]
+ *          The next octet in the message.
+ *
+ *  Returns:
+ *      Nothing.
+ *
+ *  Comments:
+ *
+ */
+void SHA1::Input(unsigned char message_element)
+{
+    Input(&message_element, 1);
+}
+
+/*  
+ *  Input
+ *
+ *  Description:
+ *      This function accepts a single octet as the next message element.
+ *
+ *  Parameters:
+ *      message_element: [in]
+ *          The next octet in the message.
+ *
+ *  Returns:
+ *      Nothing.
+ *
+ *  Comments:
+ *
+ */
+void SHA1::Input(char message_element)
+{
+    Input((unsigned char *) &message_element, 1);
+}
+
+/*  
+ *  operator<<
+ *
+ *  Description:
+ *      This operator makes it convenient to provide character strings to
+ *      the SHA1 object for processing.
+ *
+ *  Parameters:
+ *      message_array: [in]
+ *          The character array to take as input.
+ *
+ *  Returns:
+ *      A reference to the SHA1 object.
+ *
+ *  Comments:
+ *      Each character is assumed to hold 8 bits of information.
+ *
+ */
+SHA1& SHA1::operator<<(const char *message_array)
+{
+    const char *p = message_array;
+
+    while(*p)
+    {
+        Input(*p);
+        p++;
+    }
+
+    return *this;
+}
+
+/*  
+ *  operator<<
+ *
+ *  Description:
+ *      This operator makes it convenient to provide character strings to
+ *      the SHA1 object for processing.
+ *
+ *  Parameters:
+ *      message_array: [in]
+ *          The character array to take as input.
+ *
+ *  Returns:
+ *      A reference to the SHA1 object.
+ *
+ *  Comments:
+ *      Each character is assumed to hold 8 bits of information.
+ *
+ */
+SHA1& SHA1::operator<<(const unsigned char *message_array)
+{
+    const unsigned char *p = message_array;
+
+    while(*p)
+    {
+        Input(*p);
+        p++;
+    }
+
+    return *this;
+}
+
+/*  
+ *  operator<<
+ *
+ *  Description:
+ *      This function provides the next octet in the message.
+ *
+ *  Parameters:
+ *      message_element: [in]
+ *          The next octet in the message
+ *
+ *  Returns:
+ *      A reference to the SHA1 object.
+ *
+ *  Comments:
+ *      The character is assumed to hold 8 bits of information.
+ *
+ */
+SHA1& SHA1::operator<<(const char message_element)
+{
+    Input((unsigned char *) &message_element, 1);
+
+    return *this;
+}
+
+/*  
+ *  operator<<
+ *
+ *  Description:
+ *      This function provides the next octet in the message.
+ *
+ *  Parameters:
+ *      message_element: [in]
+ *          The next octet in the message
+ *
+ *  Returns:
+ *      A reference to the SHA1 object.
+ *
+ *  Comments:
+ *      The character is assumed to hold 8 bits of information.
+ *
+ */
+SHA1& SHA1::operator<<(const unsigned char message_element)
+{
+    Input(&message_element, 1);
+
+    return *this;
+}
+
+/*  
+ *  ProcessMessageBlock
+ *
+ *  Description:
+ *      This function will process the next 512 bits of the message
+ *      stored in the Message_Block array.
+ *
+ *  Parameters:
+ *      None.
+ *
+ *  Returns:
+ *      Nothing.
+ *
+ *  Comments:
+ *      Many of the variable names in this function, especially the single
+ *      character names, were used because those were the names used
+ *      in the publication.
+ *
+ */
+void SHA1::ProcessMessageBlock()
+{
+    const unsigned K[] =    {               // Constants defined for SHA-1
+                                0x5A827999,
+                                0x6ED9EBA1,
+                                0x8F1BBCDC,
+                                0xCA62C1D6
+                            };
+    int         t;                          // Loop counter
+    unsigned    temp;                       // Temporary word value
+    unsigned    W[80];                      // Word sequence
+    unsigned    A, B, C, D, E;              // Word buffers
+
+    /*
+     *  Initialize the first 16 words in the array W
+     */
+    for(t = 0; t < 16; t++)
+    {
+        W[t] = ((unsigned) Message_Block[t * 4]) << 24;
+        W[t] |= ((unsigned) Message_Block[t * 4 + 1]) << 16;
+        W[t] |= ((unsigned) Message_Block[t * 4 + 2]) << 8;
+        W[t] |= ((unsigned) Message_Block[t * 4 + 3]);
+    }
+
+    for(t = 16; t < 80; t++)
+    {
+       W[t] = CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
+    }
+
+    A = H[0];
+    B = H[1];
+    C = H[2];
+    D = H[3];
+    E = H[4];
+
+    for(t = 0; t < 20; t++)
+    {
+        temp = CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0];
+        temp &= 0xFFFFFFFF;
+        E = D;
+        D = C;
+        C = CircularShift(30,B);
+        B = A;
+        A = temp;
+    }
+
+    for(t = 20; t < 40; t++)
+    {
+        temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
+        temp &= 0xFFFFFFFF;
+        E = D;
+        D = C;
+        C = CircularShift(30,B);
+        B = A;
+        A = temp;
+    }
+
+    for(t = 40; t < 60; t++)
+    {
+        temp = CircularShift(5,A) +
+               ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
+        temp &= 0xFFFFFFFF;
+        E = D;
+        D = C;
+        C = CircularShift(30,B);
+        B = A;
+        A = temp;
+    }
+
+    for(t = 60; t < 80; t++)
+    {
+        temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
+        temp &= 0xFFFFFFFF;
+        E = D;
+        D = C;
+        C = CircularShift(30,B);
+        B = A;
+        A = temp;
+    }
+
+    H[0] = (H[0] + A) & 0xFFFFFFFF;
+    H[1] = (H[1] + B) & 0xFFFFFFFF;
+    H[2] = (H[2] + C) & 0xFFFFFFFF;
+    H[3] = (H[3] + D) & 0xFFFFFFFF;
+    H[4] = (H[4] + E) & 0xFFFFFFFF;
+
+    Message_Block_Index = 0;
+}
+
+/*  
+ *  PadMessage
+ *
+ *  Description:
+ *      According to the standard, the message must be padded to an even
+ *      512 bits.  The first padding bit must be a '1'.  The last 64 bits
+ *      represent the length of the original message.  All bits in between
+ *      should be 0.  This function will pad the message according to those
+ *      rules by filling the message_block array accordingly.  It will also
+ *      call ProcessMessageBlock() appropriately.  When it returns, it
+ *      can be assumed that the message digest has been computed.
+ *
+ *  Parameters:
+ *      None.
+ *
+ *  Returns:
+ *      Nothing.
+ *
+ *  Comments:
+ *
+ */
+void SHA1::PadMessage()
+{
+    /*
+     *  Check to see if the current message block is too small to hold
+     *  the initial padding bits and length.  If so, we will pad the
+     *  block, process it, and then continue padding into a second block.
+     */
+    if (Message_Block_Index > 55)
+    {
+        Message_Block[Message_Block_Index++] = 0x80;
+        while(Message_Block_Index < 64)
+        {
+            Message_Block[Message_Block_Index++] = 0;
+        }
+
+        ProcessMessageBlock();
+
+        while(Message_Block_Index < 56)
+        {
+            Message_Block[Message_Block_Index++] = 0;
+        }
+    }
+    else
+    {
+        Message_Block[Message_Block_Index++] = 0x80;
+        while(Message_Block_Index < 56)
+        {
+            Message_Block[Message_Block_Index++] = 0;
+        }
+
+    }
+
+    /*
+     *  Store the message length as the last 8 octets
+     */
+    Message_Block[56] = (Length_High >> 24) & 0xFF;
+    Message_Block[57] = (Length_High >> 16) & 0xFF;
+    Message_Block[58] = (Length_High >> 8) & 0xFF;
+    Message_Block[59] = (Length_High) & 0xFF;
+    Message_Block[60] = (Length_Low >> 24) & 0xFF;
+    Message_Block[61] = (Length_Low >> 16) & 0xFF;
+    Message_Block[62] = (Length_Low >> 8) & 0xFF;
+    Message_Block[63] = (Length_Low) & 0xFF;
+
+    ProcessMessageBlock();
+}
+
+
+/*  
+ *  CircularShift
+ *
+ *  Description:
+ *      This member function will perform a circular shifting operation.
+ *
+ *  Parameters:
+ *      bits: [in]
+ *          The number of bits to shift (1-31)
+ *      word: [in]
+ *          The value to shift (assumes a 32-bit integer)
+ *
+ *  Returns:
+ *      The shifted value.
+ *
+ *  Comments:
+ *
+ */
+unsigned SHA1::CircularShift(int bits, unsigned word)
+{
+    return ((word << bits) & 0xFFFFFFFF) | ((word & 0xFFFFFFFF) >> (32-bits));
+}
diff --git a/third_party/seasocks/src/main/c/sha1/sha1.h b/third_party/seasocks/src/main/c/sha1/sha1.h
new file mode 100644
index 0000000..3c7d896
--- /dev/null
+++ b/third_party/seasocks/src/main/c/sha1/sha1.h
@@ -0,0 +1,114 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+// DO NOT REFORMAT <- for tidy
+/*
+ *  sha1.h
+ *
+ *  Copyright (C) 1998, 2009
+ *  Paul E. Jones <paulej@packetizer.com>
+ *  All Rights Reserved.
+ *
+ *****************************************************************************
+ *  $Id: sha1.h 12 2009-06-22 19:34:25Z paulej $
+ *****************************************************************************
+ *
+ *  Description:
+ *      This class implements the Secure Hashing Standard as defined
+ *      in FIPS PUB 180-1 published April 17, 1995.
+ *
+ *      Many of the variable names in this class, especially the single
+ *      character names, were used because those were the names used
+ *      in the publication.
+ *
+ *      Please read the file sha1.cpp for more information.
+ *
+ */
+
+#ifndef _SHA1_H_
+#define _SHA1_H_
+
+class SHA1
+{
+
+    public:
+
+        SHA1();
+        virtual ~SHA1();
+
+        /*
+         *  Re-initialize the class
+         */
+        void Reset();
+
+        /*
+         *  Returns the message digest
+         */
+        bool Result(unsigned *message_digest_array);
+
+        /*
+         *  Provide input to SHA1
+         */
+        void Input( const unsigned char *message_array,
+                    unsigned            length);
+        void Input( const char  *message_array,
+                    unsigned    length);
+        void Input(unsigned char message_element);
+        void Input(char message_element);
+        SHA1& operator<<(const char *message_array);
+        SHA1& operator<<(const unsigned char *message_array);
+        SHA1& operator<<(const char message_element);
+        SHA1& operator<<(const unsigned char message_element);
+
+    private:
+
+        /*
+         *  Process the next 512 bits of the message
+         */
+        void ProcessMessageBlock();
+
+        /*
+         *  Pads the current message block to 512 bits
+         */
+        void PadMessage();
+
+        /*
+         *  Performs a circular left shift operation
+         */
+        inline unsigned CircularShift(int bits, unsigned word);
+
+        unsigned H[5];                      // Message digest buffers
+
+        unsigned Length_Low;                // Message length in bits
+        unsigned Length_High;               // Message length in bits
+
+        unsigned char Message_Block[64];    // 512-bit message blocks
+        int Message_Block_Index;            // Index into message block array
+
+        bool Computed;                      // Is the digest computed?
+        bool Corrupted;                     // Is the message digest corruped?
+
+};
+#endif
diff --git a/third_party/seasocks/src/main/c/util/CrackedUri.cpp b/third_party/seasocks/src/main/c/util/CrackedUri.cpp
new file mode 100644
index 0000000..1da757f
--- /dev/null
+++ b/third_party/seasocks/src/main/c/util/CrackedUri.cpp
@@ -0,0 +1,129 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "seasocks/StringUtil.h"
+#include "seasocks/util/CrackedUri.h"
+
+#include <algorithm>
+#include <sstream>
+#include <stdexcept>
+
+#define THROW(stuff) \
+    do {\
+        std::ostringstream err; \
+        err << stuff; \
+        throw std::runtime_error(err.str()); \
+    } while (0);
+
+namespace {
+
+char fromHex(char c) {
+    c = tolower(c);
+    return c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10;
+}
+
+std::string unescape(std::string uri) {
+    seasocks::replace(uri, "+", " ");
+    size_t pos = 0;
+    while (pos < uri.size()) {
+        pos = uri.find('%', pos);
+        if (pos == uri.npos) break;
+        if (pos + 2 > uri.size()) {
+            THROW("Truncated uri: '" << uri << "'");
+        }
+        if (!isxdigit(uri[pos + 1]) || !isxdigit(uri[pos + 2])) {
+            THROW("Bad digit in uri: '" << uri << "'");
+        }
+        auto hex = (fromHex(uri[pos + 1]) << 4) | fromHex(uri[pos + 2]);
+        uri = uri.substr(0, pos) + std::string(1, hex) + uri.substr(pos + 3);
+        ++pos;
+    }
+    return uri;
+}
+
+}
+
+namespace seasocks {
+
+CrackedUri::CrackedUri(const std::string& uri) {
+    if (uri.empty() || uri[0] != '/') {
+        THROW("Malformed URI: '" << uri << "'");
+    }
+    auto endOfPath = uri.find('?');
+    std::string path;
+    std::string remainder;
+    if (endOfPath == uri.npos) {
+        path = uri.substr(1);
+    } else {
+        path = uri.substr(1, endOfPath - 1);
+        remainder = uri.substr(endOfPath + 1);
+    }
+
+    _path = split(path, '/');
+    std::transform(_path.begin(), _path.end(), _path.begin(), unescape);
+
+    auto splitRemainder = split(remainder, '&');
+    for (auto iter = splitRemainder.cbegin(); iter != splitRemainder.cend(); ++iter) {
+        if (iter->empty()) continue;
+        auto split = seasocks::split(*iter, '=');
+        std::transform(split.begin(), split.end(), split.begin(), unescape);
+        if (split.size() == 1) {
+            _queryParams.insert(std::make_pair(split[0], std::string()));
+        } else if (split.size() == 2) {
+            _queryParams.insert(std::make_pair(split[0], split[1]));
+        } else {
+            THROW("Malformed URI, two many = in query: '" << uri << "'");
+        }
+    }
+}
+
+bool CrackedUri::hasParam(const std::string& param) const {
+    return _queryParams.find(param) != _queryParams.end();
+}
+
+std::string CrackedUri::queryParam(const std::string& param, const std::string& def) const {
+    auto found = _queryParams.find(param);
+    return found == _queryParams.end() ? def : found->second;
+}
+
+std::vector<std::string> CrackedUri::allQueryParams(const std::string& param) const {
+    std::vector<std::string> params;
+    for (auto iter = _queryParams.find(param); iter != _queryParams.end() && iter->first == param; ++iter)
+        params.push_back(iter->second);
+    return params;
+}
+
+CrackedUri CrackedUri::shift() const {
+    CrackedUri shifted(*this);
+    if (_path.size() > 1) {
+        shifted._path = std::vector<std::string>(_path.begin() + 1, _path.end());
+    } else {
+        shifted._path = {""};
+    }
+
+    return shifted;
+}
+
+}
diff --git a/third_party/seasocks/src/main/c/util/Json.cpp b/third_party/seasocks/src/main/c/util/Json.cpp
new file mode 100644
index 0000000..48c74d7
--- /dev/null
+++ b/third_party/seasocks/src/main/c/util/Json.cpp
@@ -0,0 +1,66 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "seasocks/util/Json.h"
+
+#include <iomanip>
+
+namespace seasocks {
+
+void jsonToStream(std::ostream& str, const char* t) {
+    str << '"';
+    for (; *t; ++t) {
+        switch (*t) {
+        default:
+            if (*t >= 32) {
+                str << *t;
+            } else {
+                str << "\\u" << std::setw(4)
+                    << std::setfill('0') << std::hex << (int)*t;
+            }
+            break;
+        case 8: str << "\\b"; break;
+        case 9: str << "\\t"; break;
+        case 10: str << "\\n"; break;
+        case 12: str << "\\f"; break;
+        case 13: str << "\\r"; break;
+        case '"': case '\\':
+            str << '\\';
+            str << *t;
+            break;
+        }
+    }
+    str << '"';
+}
+
+void jsonToStream(std::ostream& str, bool b) {
+    str << (b ? "true" : "false");
+}
+
+void EpochTimeAsLocal::jsonToStream(std::ostream &o) const {
+    o << "new Date(" << t * 1000 << ").toLocaleString()";
+}
+
+}
diff --git a/third_party/seasocks/src/main/c/util/PathHandler.cpp b/third_party/seasocks/src/main/c/util/PathHandler.cpp
new file mode 100644
index 0000000..4f9b60f
--- /dev/null
+++ b/third_party/seasocks/src/main/c/util/PathHandler.cpp
@@ -0,0 +1,51 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "seasocks/util/PathHandler.h"
+
+#include "seasocks/Request.h"
+#include "seasocks/Response.h"
+#include "seasocks/util/CrackedUri.h"
+
+using namespace seasocks;
+
+CrackedUriPageHandler::Ptr PathHandler::add(const CrackedUriPageHandler::Ptr& handler) {
+    _handlers.emplace_back(handler);
+    return _handlers.back();
+}
+
+std::shared_ptr<Response> PathHandler::handle(
+        const CrackedUri& uri, const Request& request) {
+    const auto &path = uri.path();
+    if (path.empty() || path[0] != _path) return Response::unhandled();
+
+    auto shiftedUri = uri.shift();
+
+    for (const auto &it : _handlers) {
+        auto response = it->handle(shiftedUri, request);
+        if (response != Response::unhandled()) return response;
+    }
+    return Response::unhandled();
+}
diff --git a/third_party/seasocks/src/main/c/util/RootPageHandler.cpp b/third_party/seasocks/src/main/c/util/RootPageHandler.cpp
new file mode 100644
index 0000000..f6b4f52
--- /dev/null
+++ b/third_party/seasocks/src/main/c/util/RootPageHandler.cpp
@@ -0,0 +1,52 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "seasocks/util/RootPageHandler.h"
+
+#include "seasocks/Request.h"
+#include "seasocks/Response.h"
+#include "seasocks/util/CrackedUri.h"
+
+using namespace seasocks;
+
+RootPageHandler::RootPageHandler() {
+}
+
+RootPageHandler::~RootPageHandler() {
+}
+
+CrackedUriPageHandler::Ptr RootPageHandler::add(const CrackedUriPageHandler::Ptr& handler) {
+    _handlers.emplace_back(handler);
+    return _handlers.back();
+}
+
+std::shared_ptr<Response> RootPageHandler::handle(const Request& request) {
+    CrackedUri uri(request.getRequestUri());
+    for (const auto &it : _handlers) {
+        auto response = it->handle(uri, request);
+        if (response != Response::unhandled()) return response;
+    }
+    return Response::unhandled();
+}
diff --git a/third_party/seasocks/src/main/web/_404.png b/third_party/seasocks/src/main/web/_404.png
new file mode 100644
index 0000000..8a43cb8
--- /dev/null
+++ b/third_party/seasocks/src/main/web/_404.png
Binary files differ
diff --git a/third_party/seasocks/src/main/web/_error.css b/third_party/seasocks/src/main/web/_error.css
new file mode 100644
index 0000000..8238d6d
--- /dev/null
+++ b/third_party/seasocks/src/main/web/_error.css
@@ -0,0 +1,33 @@
+body {
+    font-family: segoe ui, tahoma, arial, sans-serif;
+    color: #ffffff;
+    background-color: #c21e29;
+    text-align: center;
+}
+
+a {
+    color: #ffff00;
+}
+
+.footer {
+    font-style: italic;
+}
+
+.message {
+    display: inline-block;
+    border: 1px solid white;
+    padding: 50px;
+    font-size: 20px;
+}
+
+.headline {
+    padding: 50px;
+    font-weight: bold;
+    font-size: 32px;
+}
+
+.footer {
+    padding-top: 50px;
+    font-size: 12px;
+}
+
diff --git a/third_party/seasocks/src/main/web/_error.html b/third_party/seasocks/src/main/web/_error.html
new file mode 100644
index 0000000..ecf5e32
--- /dev/null
+++ b/third_party/seasocks/src/main/web/_error.html
@@ -0,0 +1,15 @@
+<html DOCTYPE=html>
+<head>
+  <title>%%ERRORCODE%% - %%MESSAGE%% - Keep Calm And Carry On!</title>
+  <link href="/_error.css" rel="stylesheet">
+</head>
+<body>
+  <div class="message">
+    <img src="/_404.png" height="200" width="107">
+    <div class="headline">%%ERRORCODE%% &#8212; %%MESSAGE%%</div>
+    <div class="info">%%BODY%%</div>
+  </div>
+
+  <div class="footer">Powered by <a href="https://github.com/mattgodbolt/seasocks">SeaSocks</a></div>
+</body>
+</html>
diff --git a/third_party/seasocks/src/main/web/_jquery.min.js b/third_party/seasocks/src/main/web/_jquery.min.js
new file mode 100644
index 0000000..f78f96a
--- /dev/null
+++ b/third_party/seasocks/src/main/web/_jquery.min.js
@@ -0,0 +1,16 @@
+/*!
+ * jQuery JavaScript Library v1.5.2
+ * http://jquery.com/
+ *
+ * Copyright 2011, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2011, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Thu Mar 31 15:28:23 2011 -0400
+ */
+(function(a,b){function ci(a){return d.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cf(a){if(!b_[a]){var b=d("<"+a+">").appendTo("body"),c=b.css("display");b.remove();if(c==="none"||c==="")c="block";b_[a]=c}return b_[a]}function ce(a,b){var c={};d.each(cd.concat.apply([],cd.slice(0,b)),function(){c[this]=a});return c}function b$(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function bZ(){try{return new a.XMLHttpRequest}catch(b){}}function bY(){d(a).unload(function(){for(var a in bW)bW[a](0,1)})}function bS(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var e=a.dataTypes,f={},g,h,i=e.length,j,k=e[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h==="string"&&(f[h.toLowerCase()]=a.converters[h]);l=k,k=e[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=f[m]||f["* "+k];if(!n){p=b;for(o in f){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=f[j[1]+" "+k];if(p){o=f[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&d.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function bR(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function bQ(a,b,c,e){if(d.isArray(b)&&b.length)d.each(b,function(b,f){c||bs.test(a)?e(a,f):bQ(a+"["+(typeof f==="object"||d.isArray(f)?b:"")+"]",f,c,e)});else if(c||b==null||typeof b!=="object")e(a,b);else if(d.isArray(b)||d.isEmptyObject(b))e(a,"");else for(var f in b)bQ(a+"["+f+"]",b[f],c,e)}function bP(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bJ,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l==="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bP(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bP(a,c,d,e,"*",g));return l}function bO(a){return function(b,c){typeof b!=="string"&&(c=b,b="*");if(d.isFunction(c)){var e=b.toLowerCase().split(bD),f=0,g=e.length,h,i,j;for(;f<g;f++)h=e[f],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bq(a,b,c){var e=b==="width"?bk:bl,f=b==="width"?a.offsetWidth:a.offsetHeight;if(c==="border")return f;d.each(e,function(){c||(f-=parseFloat(d.css(a,"padding"+this))||0),c==="margin"?f+=parseFloat(d.css(a,"margin"+this))||0:f-=parseFloat(d.css(a,"border"+this+"Width"))||0});return f}function bc(a,b){b.src?d.ajax({url:b.src,async:!1,dataType:"script"}):d.globalEval(b.text||b.textContent||b.innerHTML||""),b.parentNode&&b.parentNode.removeChild(b)}function bb(a){return"getElementsByTagName"in a?a.getElementsByTagName("*"):"querySelectorAll"in a?a.querySelectorAll("*"):[]}function ba(a,b){if(b.nodeType===1){var c=b.nodeName.toLowerCase();b.clearAttributes(),b.mergeAttributes(a);if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(d.expando)}}function _(a,b){if(b.nodeType===1&&d.hasData(a)){var c=d.expando,e=d.data(a),f=d.data(b,e);if(e=e[c]){var g=e.events;f=f[c]=d.extend({},e);if(g){delete f.handle,f.events={};for(var h in g)for(var i=0,j=g[h].length;i<j;i++)d.event.add(b,h+(g[h][i].namespace?".":"")+g[h][i].namespace,g[h][i],g[h][i].data)}}}}function $(a,b){return d.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function Q(a,b,c){if(d.isFunction(b))return d.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return d.grep(a,function(a,d){return a===b===c});if(typeof b==="string"){var e=d.grep(a,function(a){return a.nodeType===1});if(L.test(b))return d.filter(b,e,!c);b=d.filter(b,e)}return d.grep(a,function(a,e){return d.inArray(a,b)>=0===c})}function P(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function H(a,b){return(a&&a!=="*"?a+".":"")+b.replace(t,"`").replace(u,"&")}function G(a){var b,c,e,f,g,h,i,j,k,l,m,n,o,p=[],q=[],s=d._data(this,"events");if(a.liveFired!==this&&s&&s.live&&!a.target.disabled&&(!a.button||a.type!=="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var t=s.live.slice(0);for(i=0;i<t.length;i++)g=t[i],g.origType.replace(r,"")===a.type?q.push(g.selector):t.splice(i--,1);f=d(a.target).closest(q,a.currentTarget);for(j=0,k=f.length;j<k;j++){m=f[j];for(i=0;i<t.length;i++){g=t[i];if(m.selector===g.selector&&(!n||n.test(g.namespace))&&!m.elem.disabled){h=m.elem,e=null;if(g.preType==="mouseenter"||g.preType==="mouseleave")a.type=g.preType,e=d(a.relatedTarget).closest(g.selector)[0];(!e||e!==h)&&p.push({elem:h,handleObj:g,level:m.level})}}}for(j=0,k=p.length;j<k;j++){f=p[j];if(c&&f.level>c)break;a.currentTarget=f.elem,a.data=f.handleObj.data,a.handleObj=f.handleObj,o=f.handleObj.origHandler.apply(f.elem,arguments);if(o===!1||a.isPropagationStopped()){c=f.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function E(a,c,e){var f=d.extend({},e[0]);f.type=a,f.originalEvent={},f.liveFired=b,d.event.handle.call(c,f),f.isDefaultPrevented()&&e[0].preventDefault()}function y(){return!0}function x(){return!1}function i(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function h(a,c,e){if(e===b&&a.nodeType===1){e=a.getAttribute("data-"+c);if(typeof e==="string"){try{e=e==="true"?!0:e==="false"?!1:e==="null"?null:d.isNaN(e)?g.test(e)?d.parseJSON(e):e:parseFloat(e)}catch(f){}d.data(a,c,e)}else e=b}return e}var c=a.document,d=function(){function G(){if(!d.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(G,1);return}d.ready()}}var d=function(a,b){return new d.fn.init(a,b,g)},e=a.jQuery,f=a.$,g,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,i=/\S/,j=/^\s+/,k=/\s+$/,l=/\d/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=navigator.userAgent,w,x,y,z=Object.prototype.toString,A=Object.prototype.hasOwnProperty,B=Array.prototype.push,C=Array.prototype.slice,D=String.prototype.trim,E=Array.prototype.indexOf,F={};d.fn=d.prototype={constructor:d,init:function(a,e,f){var g,i,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!e&&c.body){this.context=c,this[0]=c.body,this.selector="body",this.length=1;return this}if(typeof a==="string"){g=h.exec(a);if(!g||!g[1]&&e)return!e||e.jquery?(e||f).find(a):this.constructor(e).find(a);if(g[1]){e=e instanceof d?e[0]:e,k=e?e.ownerDocument||e:c,j=m.exec(a),j?d.isPlainObject(e)?(a=[c.createElement(j[1])],d.fn.attr.call(a,e,!0)):a=[k.createElement(j[1])]:(j=d.buildFragment([g[1]],[k]),a=(j.cacheable?d.clone(j.fragment):j.fragment).childNodes);return d.merge(this,a)}i=c.getElementById(g[2]);if(i&&i.parentNode){if(i.id!==g[2])return f.find(a);this.length=1,this[0]=i}this.context=c,this.selector=a;return this}if(d.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return d.makeArray(a,this)},selector:"",jquery:"1.5.2",length:0,size:function(){return this.length},toArray:function(){return C.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var e=this.constructor();d.isArray(a)?B.apply(e,a):d.merge(e,a),e.prevObject=this,e.context=this.context,b==="find"?e.selector=this.selector+(this.selector?" ":"")+c:b&&(e.selector=this.selector+"."+b+"("+c+")");return e},each:function(a,b){return d.each(this,a,b)},ready:function(a){d.bindReady(),x.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(C.apply(this,arguments),"slice",C.call(arguments).join(","))},map:function(a){return this.pushStack(d.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:B,sort:[].sort,splice:[].splice},d.fn.init.prototype=d.fn,d.extend=d.fn.extend=function(){var a,c,e,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i==="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!=="object"&&!d.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){e=i[c],f=a[c];if(i===f)continue;l&&f&&(d.isPlainObject(f)||(g=d.isArray(f)))?(g?(g=!1,h=e&&d.isArray(e)?e:[]):h=e&&d.isPlainObject(e)?e:{},i[c]=d.extend(l,h,f)):f!==b&&(i[c]=f)}return i},d.extend({noConflict:function(b){a.$=f,b&&(a.jQuery=e);return d},isReady:!1,readyWait:1,ready:function(a){a===!0&&d.readyWait--;if(!d.readyWait||a!==!0&&!d.isReady){if(!c.body)return setTimeout(d.ready,1);d.isReady=!0;if(a!==!0&&--d.readyWait>0)return;x.resolveWith(c,[d]),d.fn.trigger&&d(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!x){x=d._Deferred();if(c.readyState==="complete")return setTimeout(d.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",y,!1),a.addEventListener("load",d.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",y),a.attachEvent("onload",d.ready);var b=!1;try{b=a.frameElement==null}catch(e){}c.documentElement.doScroll&&b&&G()}}},isFunction:function(a){return d.type(a)==="function"},isArray:Array.isArray||function(a){return d.type(a)==="array"},isWindow:function(a){return a&&typeof a==="object"&&"setInterval"in a},isNaN:function(a){return a==null||!l.test(a)||isNaN(a)},type:function(a){return a==null?String(a):F[z.call(a)]||"object"},isPlainObject:function(a){if(!a||d.type(a)!=="object"||a.nodeType||d.isWindow(a))return!1;if(a.constructor&&!A.call(a,"constructor")&&!A.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a){}return c===b||A.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!=="string"||!b)return null;b=d.trim(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return a.JSON&&a.JSON.parse?a.JSON.parse(b):(new Function("return "+b))();d.error("Invalid JSON: "+b)},parseXML:function(b,c,e){a.DOMParser?(e=new DOMParser,c=e.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),e=c.documentElement,(!e||!e.nodeName||e.nodeName==="parsererror")&&d.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(a){if(a&&i.test(a)){var b=c.head||c.getElementsByTagName("head")[0]||c.documentElement,e=c.createElement("script");d.support.scriptEval()?e.appendChild(c.createTextNode(a)):e.text=a,b.insertBefore(e,b.firstChild),b.removeChild(e)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,e){var f,g=0,h=a.length,i=h===b||d.isFunction(a);if(e){if(i){for(f in a)if(c.apply(a[f],e)===!1)break}else for(;g<h;)if(c.apply(a[g++],e)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(var j=a[0];g<h&&c.call(j,g,j)!==!1;j=a[++g]){}return a},trim:D?function(a){return a==null?"":D.call(a)}:function(a){return a==null?"":(a+"").replace(j,"").replace(k,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var e=d.type(a);a.length==null||e==="string"||e==="function"||e==="regexp"||d.isWindow(a)?B.call(c,a):d.merge(c,a)}return c},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var c=0,d=b.length;c<d;c++)if(b[c]===a)return c;return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length==="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,b,c){var d=[],e;for(var f=0,g=a.length;f<g;f++)e=b(a[f],f,c),e!=null&&(d[d.length]=e);return d.concat.apply([],d)},guid:1,proxy:function(a,c,e){arguments.length===2&&(typeof c==="string"?(e=a,a=e[c],c=b):c&&!d.isFunction(c)&&(e=c,c=b)),!c&&a&&(c=function(){return a.apply(e||this,arguments)}),a&&(c.guid=a.guid=a.guid||c.guid||d.guid++);return c},access:function(a,c,e,f,g,h){var i=a.length;if(typeof c==="object"){for(var j in c)d.access(a,j,c[j],f,g,e);return a}if(e!==b){f=!h&&f&&d.isFunction(e);for(var k=0;k<i;k++)g(a[k],c,f?e.call(a[k],k,g(a[k],c)):e,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}d.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.subclass=this.subclass,a.fn.init=function b(b,c){c&&c instanceof d&&!(c instanceof a)&&(c=a(c));return d.fn.init.call(this,b,c,e)},a.fn.init.prototype=a.fn;var e=a(c);return a},browser:{}}),d.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){F["[object "+b+"]"]=b.toLowerCase()}),w=d.uaMatch(v),w.browser&&(d.browser[w.browser]=!0,d.browser.version=w.version),d.browser.webkit&&(d.browser.safari=!0),E&&(d.inArray=function(a,b){return E.call(b,a)}),i.test(" ")&&(j=/^[\s\xA0]+/,k=/[\s\xA0]+$/),g=d(c),c.addEventListener?y=function(){c.removeEventListener("DOMContentLoaded",y,!1),d.ready()}:c.attachEvent&&(y=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",y),d.ready())});return d}(),e="then done fail isResolved isRejected promise".split(" "),f=[].slice;d.extend({_Deferred:function(){var a=[],b,c,e,f={done:function(){if(!e){var c=arguments,g,h,i,j,k;b&&(k=b,b=0);for(g=0,h=c.length;g<h;g++)i=c[g],j=d.type(i),j==="array"?f.done.apply(f,i):j==="function"&&a.push(i);k&&f.resolveWith(k[0],k[1])}return this},resolveWith:function(d,f){if(!e&&!b&&!c){f=f||[],c=1;try{while(a[0])a.shift().apply(d,f)}finally{b=[d,f],c=0}}return this},resolve:function(){f.resolveWith(this,arguments);return this},isResolved:function(){return c||b},cancel:function(){e=1,a=[];return this}};return f},Deferred:function(a){var b=d._Deferred(),c=d._Deferred(),f;d.extend(b,{then:function(a,c){b.done(a).fail(c);return this},fail:c.done,rejectWith:c.resolveWith,reject:c.resolve,isRejected:c.isResolved,promise:function(a){if(a==null){if(f)return f;f=a={}}var c=e.length;while(c--)a[e[c]]=b[e[c]];return a}}),b.done(c.cancel).fail(b.cancel),delete b.cancel,a&&a.call(b,b);return b},when:function(a){function i(a){return function(c){b[a]=arguments.length>1?f.call(arguments,0):c,--g||h.resolveWith(h,f.call(b,0))}}var b=arguments,c=0,e=b.length,g=e,h=e<=1&&a&&d.isFunction(a.promise)?a:d.Deferred();if(e>1){for(;c<e;c++)b[c]&&d.isFunction(b[c].promise)?b[c].promise().then(i(c),h.reject):--g;g||h.resolveWith(h,b)}else h!==a&&h.resolveWith(h,e?[a]:[]);return h.promise()}}),function(){d.support={};var b=c.createElement("div");b.style.display="none",b.innerHTML="   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";var e=b.getElementsByTagName("*"),f=b.getElementsByTagName("a")[0],g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=b.getElementsByTagName("input")[0];if(e&&e.length&&f){d.support={leadingWhitespace:b.firstChild.nodeType===3,tbody:!b.getElementsByTagName("tbody").length,htmlSerialize:!!b.getElementsByTagName("link").length,style:/red/.test(f.getAttribute("style")),hrefNormalized:f.getAttribute("href")==="/a",opacity:/^0.55$/.test(f.style.opacity),cssFloat:!!f.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,deleteExpando:!0,optDisabled:!1,checkClone:!1,noCloneEvent:!0,noCloneChecked:!0,boxModel:null,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableHiddenOffsets:!0,reliableMarginRight:!0},i.checked=!0,d.support.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,d.support.optDisabled=!h.disabled;var j=null;d.support.scriptEval=function(){if(j===null){var b=c.documentElement,e=c.createElement("script"),f="script"+d.now();try{e.appendChild(c.createTextNode("window."+f+"=1;"))}catch(g){}b.insertBefore(e,b.firstChild),a[f]?(j=!0,delete a[f]):j=!1,b.removeChild(e)}return j};try{delete b.test}catch(k){d.support.deleteExpando=!1}!b.addEventListener&&b.attachEvent&&b.fireEvent&&(b.attachEvent("onclick",function l(){d.support.noCloneEvent=!1,b.detachEvent("onclick",l)}),b.cloneNode(!0).fireEvent("onclick")),b=c.createElement("div"),b.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";var m=c.createDocumentFragment();m.appendChild(b.firstChild),d.support.checkClone=m.cloneNode(!0).cloneNode(!0).lastChild.checked,d(function(){var a=c.createElement("div"),b=c.getElementsByTagName("body")[0];if(b){a.style.width=a.style.paddingLeft="1px",b.appendChild(a),d.boxModel=d.support.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,d.support.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="<div style='width:4px;'></div>",d.support.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";var e=a.getElementsByTagName("td");d.support.reliableHiddenOffsets=e[0].offsetHeight===0,e[0].style.display="",e[1].style.display="none",d.support.reliableHiddenOffsets=d.support.reliableHiddenOffsets&&e[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(a.style.width="1px",a.style.marginRight="0",d.support.reliableMarginRight=(parseInt(c.defaultView.getComputedStyle(a,null).marginRight,10)||0)===0),b.removeChild(a).style.display="none",a=e=null}});var n=function(a){var b=c.createElement("div");a="on"+a;if(!b.attachEvent)return!0;var d=a in b;d||(b.setAttribute(a,"return;"),d=typeof b[a]==="function");return d};d.support.submitBubbles=n("submit"),d.support.changeBubbles=n("change"),b=e=f=null}}();var g=/^(?:\{.*\}|\[.*\])$/;d.extend({cache:{},uuid:0,expando:"jQuery"+(d.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?d.cache[a[d.expando]]:a[d.expando];return!!a&&!i(a)},data:function(a,c,e,f){if(d.acceptData(a)){var g=d.expando,h=typeof c==="string",i,j=a.nodeType,k=j?d.cache:a,l=j?a[d.expando]:a[d.expando]&&d.expando;if((!l||f&&l&&!k[l][g])&&h&&e===b)return;l||(j?a[d.expando]=l=++d.uuid:l=d.expando),k[l]||(k[l]={},j||(k[l].toJSON=d.noop));if(typeof c==="object"||typeof c==="function")f?k[l][g]=d.extend(k[l][g],c):k[l]=d.extend(k[l],c);i=k[l],f&&(i[g]||(i[g]={}),i=i[g]),e!==b&&(i[c]=e);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[c]:i}},removeData:function(b,c,e){if(d.acceptData(b)){var f=d.expando,g=b.nodeType,h=g?d.cache:b,j=g?b[d.expando]:d.expando;if(!h[j])return;if(c){var k=e?h[j][f]:h[j];if(k){delete k[c];if(!i(k))return}}if(e){delete h[j][f];if(!i(h[j]))return}var l=h[j][f];d.support.deleteExpando||h!=a?delete h[j]:h[j]=null,l?(h[j]={},g||(h[j].toJSON=d.noop),h[j][f]=l):g&&(d.support.deleteExpando?delete b[d.expando]:b.removeAttribute?b.removeAttribute(d.expando):b[d.expando]=null)}},_data:function(a,b,c){return d.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=d.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),d.fn.extend({data:function(a,c){var e=null;if(typeof a==="undefined"){if(this.length){e=d.data(this[0]);if(this[0].nodeType===1){var f=this[0].attributes,g;for(var i=0,j=f.length;i<j;i++)g=f[i].name,g.indexOf("data-")===0&&(g=g.substr(5),h(this[0],g,e[g]))}}return e}if(typeof a==="object")return this.each(function(){d.data(this,a)});var k=a.split(".");k[1]=k[1]?"."+k[1]:"";if(c===b){e=this.triggerHandler("getData"+k[1]+"!",[k[0]]),e===b&&this.length&&(e=d.data(this[0],a),e=h(this[0],a,e));return e===b&&k[1]?this.data(k[0]):e}return this.each(function(){var b=d(this),e=[k[0],c];b.triggerHandler("setData"+k[1]+"!",e),d.data(this,a,c),b.triggerHandler("changeData"+k[1]+"!",e)})},removeData:function(a){return this.each(function(){d.removeData(this,a)})}}),d.extend({queue:function(a,b,c){if(a){b=(b||"fx")+"queue";var e=d._data(a,b);if(!c)return e||[];!e||d.isArray(c)?e=d._data(a,b,d.makeArray(c)):e.push(c);return e}},dequeue:function(a,b){b=b||"fx";var c=d.queue(a,b),e=c.shift();e==="inprogress"&&(e=c.shift()),e&&(b==="fx"&&c.unshift("inprogress"),e.call(a,function(){d.dequeue(a,b)})),c.length||d.removeData(a,b+"queue",!0)}}),d.fn.extend({queue:function(a,c){typeof a!=="string"&&(c=a,a="fx");if(c===b)return d.queue(this[0],a);return this.each(function(b){var e=d.queue(this,a,c);a==="fx"&&e[0]!=="inprogress"&&d.dequeue(this,a)})},dequeue:function(a){return this.each(function(){d.dequeue(this,a)})},delay:function(a,b){a=d.fx?d.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(){var c=this;setTimeout(function(){d.dequeue(c,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var j=/[\n\t\r]/g,k=/\s+/,l=/\r/g,m=/^(?:href|src|style)$/,n=/^(?:button|input)$/i,o=/^(?:button|input|object|select|textarea)$/i,p=/^a(?:rea)?$/i,q=/^(?:radio|checkbox)$/i;d.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"},d.fn.extend({attr:function(a,b){return d.access(this,a,b,!0,d.attr)},removeAttr:function(a,b){return this.each(function(){d.attr(this,a,""),this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(d.isFunction(a))return this.each(function(b){var c=d(this);c.addClass(a.call(this,b,c.attr("class")))});if(a&&typeof a==="string"){var b=(a||"").split(k);for(var c=0,e=this.length;c<e;c++){var f=this[c];if(f.nodeType===1)if(f.className){var g=" "+f.className+" ",h=f.className;for(var i=0,j=b.length;i<j;i++)g.indexOf(" "+b[i]+" ")<0&&(h+=" "+b[i]);f.className=d.trim(h)}else f.className=a}}return this},removeClass:function(a){if(d.isFunction(a))return this.each(function(b){var c=d(this);c.removeClass(a.call(this,b,c.attr("class")))});if(a&&typeof a==="string"||a===b){var c=(a||"").split(k);for(var e=0,f=this.length;e<f;e++){var g=this[e];if(g.nodeType===1&&g.className)if(a){var h=(" "+g.className+" ").replace(j," ");for(var i=0,l=c.length;i<l;i++)h=h.replace(" "+c[i]+" "," ");g.className=d.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,e=typeof b==="boolean";if(d.isFunction(a))return this.each(function(c){var e=d(this);e.toggleClass(a.call(this,c,e.attr("class"),b),b)});return this.each(function(){if(c==="string"){var f,g=0,h=d(this),i=b,j=a.split(k);while(f=j[g++])i=e?i:!h.hasClass(f),h[i?"addClass":"removeClass"](f)}else if(c==="undefined"||c==="boolean")this.className&&d._data(this,"__className__",this.className),this.className=this.className||a===!1?"":d._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ";for(var c=0,d=this.length;c<d;c++)if((" "+this[c].className+" ").replace(j," ").indexOf(b)>-1)return!0;return!1},val:function(a){if(!arguments.length){var c=this[0];if(c){if(d.nodeName(c,"option")){var e=c.attributes.value;return!e||e.specified?c.value:c.text}if(d.nodeName(c,"select")){var f=c.selectedIndex,g=[],h=c.options,i=c.type==="select-one";if(f<0)return null;for(var j=i?f:0,k=i?f+1:h.length;j<k;j++){var m=h[j];if(m.selected&&(d.support.optDisabled?!m.disabled:m.getAttribute("disabled")===null)&&(!m.parentNode.disabled||!d.nodeName(m.parentNode,"optgroup"))){a=d(m).val();if(i)return a;g.push(a)}}if(i&&!g.length&&h.length)return d(h[f]).val();return g}if(q.test(c.type)&&!d.support.checkOn)return c.getAttribute("value")===null?"on":c.value;return(c.value||"").replace(l,"")}return b}var n=d.isFunction(a);return this.each(function(b){var c=d(this),e=a;if(this.nodeType===1){n&&(e=a.call(this,b,c.val())),e==null?e="":typeof e==="number"?e+="":d.isArray(e)&&(e=d.map(e,function(a){return a==null?"":a+""}));if(d.isArray(e)&&q.test(this.type))this.checked=d.inArray(c.val(),e)>=0;else if(d.nodeName(this,"select")){var f=d.makeArray(e);d("option",this).each(function(){this.selected=d.inArray(d(this).val(),f)>=0}),f.length||(this.selectedIndex=-1)}else this.value=e}})}}),d.extend({attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,e,f){if(!a||a.nodeType===3||a.nodeType===8||a.nodeType===2)return b;if(f&&c in d.attrFn)return d(a)[c](e);var g=a.nodeType!==1||!d.isXMLDoc(a),h=e!==b;c=g&&d.props[c]||c;if(a.nodeType===1){var i=m.test(c);if(c==="selected"&&!d.support.optSelected){var j=a.parentNode;j&&(j.selectedIndex,j.parentNode&&j.parentNode.selectedIndex)}if((c in a||a[c]!==b)&&g&&!i){h&&(c==="type"&&n.test(a.nodeName)&&a.parentNode&&d.error("type property can't be changed"),e===null?a.nodeType===1&&a.removeAttribute(c):a[c]=e);if(d.nodeName(a,"form")&&a.getAttributeNode(c))return a.getAttributeNode(c).nodeValue;if(c==="tabIndex"){var k=a.getAttributeNode("tabIndex");return k&&k.specified?k.value:o.test(a.nodeName)||p.test(a.nodeName)&&a.href?0:b}return a[c]}if(!d.support.style&&g&&c==="style"){h&&(a.style.cssText=""+e);return a.style.cssText}h&&a.setAttribute(c,""+e);if(!a.attributes[c]&&(a.hasAttribute&&!a.hasAttribute(c)))return b;var l=!d.support.hrefNormalized&&g&&i?a.getAttribute(c,2):a.getAttribute(c);return l===null?b:l}h&&(a[c]=e);return a[c]}});var r=/\.(.*)$/,s=/^(?:textarea|input|select)$/i,t=/\./g,u=/ /g,v=/[^\w\s.|`]/g,w=function(a){return a.replace(v,"\\$&")};d.event={add:function(c,e,f,g){if(c.nodeType!==3&&c.nodeType!==8){try{d.isWindow(c)&&(c!==a&&!c.frameElement)&&(c=a)}catch(h){}if(f===!1)f=x;else if(!f)return;var i,j;f.handler&&(i=f,f=i.handler),f.guid||(f.guid=d.guid++);var k=d._data(c);if(!k)return;var l=k.events,m=k.handle;l||(k.events=l={}),m||(k.handle=m=function(a){return typeof d!=="undefined"&&d.event.triggered!==a.type?d.event.handle.apply(m.elem,arguments):b}),m.elem=c,e=e.split(" ");var n,o=0,p;while(n=e[o++]){j=i?d.extend({},i):{handler:f,data:g},n.indexOf(".")>-1?(p=n.split("."),n=p.shift(),j.namespace=p.slice(0).sort().join(".")):(p=[],j.namespace=""),j.type=n,j.guid||(j.guid=f.guid);var q=l[n],r=d.event.special[n]||{};if(!q){q=l[n]=[];if(!r.setup||r.setup.call(c,g,p,m)===!1)c.addEventListener?c.addEventListener(n,m,!1):c.attachEvent&&c.attachEvent("on"+n,m)}r.add&&(r.add.call(c,j),j.handler.guid||(j.handler.guid=f.guid)),q.push(j),d.event.global[n]=!0}c=null}},global:{},remove:function(a,c,e,f){if(a.nodeType!==3&&a.nodeType!==8){e===!1&&(e=x);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=d.hasData(a)&&d._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(e=c.handler,c=c.type);if(!c||typeof c==="string"&&c.charAt(0)==="."){c=c||"";for(h in t)d.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+d.map(m.slice(0).sort(),w).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!e){for(j=0;j<p.length;j++){q=p[j];if(l||n.test(q.namespace))d.event.remove(a,r,q.handler,j),p.splice(j--,1)}continue}o=d.event.special[h]||{};for(j=f||0;j<p.length;j++){q=p[j];if(e.guid===q.guid){if(l||n.test(q.namespace))f==null&&p.splice(j--,1),o.remove&&o.remove.call(a,q);if(f!=null)break}}if(p.length===0||f!=null&&p.length===1)(!o.teardown||o.teardown.call(a,m)===!1)&&d.removeEvent(a,h,s.handle),g=null,delete t[h]}if(d.isEmptyObject(t)){var u=s.handle;u&&(u.elem=null),delete s.events,delete s.handle,d.isEmptyObject(s)&&d.removeData(a,b,!0)}}},trigger:function(a,c,e){var f=a.type||a,g=arguments[3];if(!g){a=typeof a==="object"?a[d.expando]?a:d.extend(d.Event(f),a):d.Event(f),f.indexOf("!")>=0&&(a.type=f=f.slice(0,-1),a.exclusive=!0),e||(a.stopPropagation(),d.event.global[f]&&d.each(d.cache,function(){var b=d.expando,e=this[b];e&&e.events&&e.events[f]&&d.event.trigger(a,c,e.handle.elem)}));if(!e||e.nodeType===3||e.nodeType===8)return b;a.result=b,a.target=e,c=d.makeArray(c),c.unshift(a)}a.currentTarget=e;var h=d._data(e,"handle");h&&h.apply(e,c);var i=e.parentNode||e.ownerDocument;try{e&&e.nodeName&&d.noData[e.nodeName.toLowerCase()]||e["on"+f]&&e["on"+f].apply(e,c)===!1&&(a.result=!1,a.preventDefault())}catch(j){}if(!a.isPropagationStopped()&&i)d.event.trigger(a,c,i,!0);else if(!a.isDefaultPrevented()){var k,l=a.target,m=f.replace(r,""),n=d.nodeName(l,"a")&&m==="click",o=d.event.special[m]||{};if((!o._default||o._default.call(e,a)===!1)&&!n&&!(l&&l.nodeName&&d.noData[l.nodeName.toLowerCase()])){try{l[m]&&(k=l["on"+m],k&&(l["on"+m]=null),d.event.triggered=a.type,l[m]())}catch(p){}k&&(l["on"+m]=k),d.event.triggered=b}}},handle:function(c){var e,f,g,h,i,j=[],k=d.makeArray(arguments);c=k[0]=d.event.fix(c||a.event),c.currentTarget=this,e=c.type.indexOf(".")<0&&!c.exclusive,e||(g=c.type.split("."),c.type=g.shift(),j=g.slice(0).sort(),h=new RegExp("(^|\\.)"+j.join("\\.(?:.*\\.)?")+"(\\.|$)")),c.namespace=c.namespace||j.join("."),i=d._data(this,"events"),f=(i||{})[c.type];if(i&&f){f=f.slice(0);for(var l=0,m=f.length;l<m;l++){var n=f[l];if(e||h.test(n.namespace)){c.handler=n.handler,c.data=n.data,c.handleObj=n;var o=n.handler.apply(this,k);o!==b&&(c.result=o,o===!1&&(c.preventDefault(),c.stopPropagation()));if(c.isImmediatePropagationStopped())break}}}return c.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(a){if(a[d.expando])return a;var e=a;a=d.Event(e);for(var f=this.props.length,g;f;)g=this.props[--f],a[g]=e[g];a.target||(a.target=a.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),!a.relatedTarget&&a.fromElement&&(a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement);if(a.pageX==null&&a.clientX!=null){var h=c.documentElement,i=c.body;a.pageX=a.clientX+(h&&h.scrollLeft||i&&i.scrollLeft||0)-(h&&h.clientLeft||i&&i.clientLeft||0),a.pageY=a.clientY+(h&&h.scrollTop||i&&i.scrollTop||0)-(h&&h.clientTop||i&&i.clientTop||0)}a.which==null&&(a.charCode!=null||a.keyCode!=null)&&(a.which=a.charCode!=null?a.charCode:a.keyCode),!a.metaKey&&a.ctrlKey&&(a.metaKey=a.ctrlKey),!a.which&&a.button!==b&&(a.which=a.button&1?1:a.button&2?3:a.button&4?2:0);return a},guid:1e8,proxy:d.proxy,special:{ready:{setup:d.bindReady,teardown:d.noop},live:{add:function(a){d.event.add(this,H(a.origType,a.selector),d.extend({},a,{handler:G,guid:a.handler.guid}))},remove:function(a){d.event.remove(this,H(a.origType,a.selector),a)}},beforeunload:{setup:function(a,b,c){d.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}}},d.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},d.Event=function(a){if(!this.preventDefault)return new d.Event(a);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?y:x):this.type=a,this.timeStamp=d.now(),this[d.expando]=!0},d.Event.prototype={preventDefault:function(){this.isDefaultPrevented=y;var a=this.originalEvent;a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=y;var a=this.originalEvent;a&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=y,this.stopPropagation()},isDefaultPrevented:x,isPropagationStopped:x,isImmediatePropagationStopped:x};var z=function(a){var b=a.relatedTarget;try{if(b&&b!==c&&!b.parentNode)return;while(b&&b!==this)b=b.parentNode;b!==this&&(a.type=a.data,d.event.handle.apply(this,arguments))}catch(e){}},A=function(a){a.type=a.data,d.event.handle.apply(this,arguments)};d.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){d.event.special[a]={setup:function(c){d.event.add(this,b,c&&c.selector?A:z,a)},teardown:function(a){d.event.remove(this,b,a&&a.selector?A:z)}}}),d.support.submitBubbles||(d.event.special.submit={setup:function(a,b){if(this.nodeName&&this.nodeName.toLowerCase()!=="form")d.event.add(this,"click.specialSubmit",function(a){var b=a.target,c=b.type;(c==="submit"||c==="image")&&d(b).closest("form").length&&E("submit",this,arguments)}),d.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,c=b.type;(c==="text"||c==="password")&&d(b).closest("form").length&&a.keyCode===13&&E("submit",this,arguments)});else return!1},teardown:function(a){d.event.remove(this,".specialSubmit")}});if(!d.support.changeBubbles){var B,C=function(a){var b=a.type,c=a.value;b==="radio"||b==="checkbox"?c=a.checked:b==="select-multiple"?c=a.selectedIndex>-1?d.map(a.options,function(a){return a.selected}).join("-"):"":a.nodeName.toLowerCase()==="select"&&(c=a.selectedIndex);return c},D=function D(a){var c=a.target,e,f;if(s.test(c.nodeName)&&!c.readOnly){e=d._data(c,"_change_data"),f=C(c),(a.type!=="focusout"||c.type!=="radio")&&d._data(c,"_change_data",f);if(e===b||f===e)return;if(e!=null||f)a.type="change",a.liveFired=b,d.event.trigger(a,arguments[1],c)}};d.event.special.change={filters:{focusout:D,beforedeactivate:D,click:function(a){var b=a.target,c=b.type;(c==="radio"||c==="checkbox"||b.nodeName.toLowerCase()==="select")&&D.call(this,a)},keydown:function(a){var b=a.target,c=b.type;(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&D.call(this,a)},beforeactivate:function(a){var b=a.target;d._data(b,"_change_data",C(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in B)d.event.add(this,c+".specialChange",B[c]);return s.test(this.nodeName)},teardown:function(a){d.event.remove(this,".specialChange");return s.test(this.nodeName)}},B=d.event.special.change.filters,B.focus=B.beforeactivate}c.addEventListener&&d.each({focus:"focusin",blur:"focusout"},function(a,b){function f(a){var c=d.event.fix(a);c.type=b,c.originalEvent={},d.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var e=0;d.event.special[b]={setup:function(){e++===0&&c.addEventListener(a,f,!0)},teardown:function(){--e===0&&c.removeEventListener(a,f,!0)}}}),d.each(["bind","one"],function(a,c){d.fn[c]=function(a,e,f){if(typeof a==="object"){for(var g in a)this[c](g,e,a[g],f);return this}if(d.isFunction(e)||e===!1)f=e,e=b;var h=c==="one"?d.proxy(f,function(a){d(this).unbind(a,h);return f.apply(this,arguments)}):f;if(a==="unload"&&c!=="one")this.one(a,e,f);else for(var i=0,j=this.length;i<j;i++)d.event.add(this[i],a,h,e);return this}}),d.fn.extend({unbind:function(a,b){if(typeof a!=="object"||a.preventDefault)for(var e=0,f=this.length;e<f;e++)d.event.remove(this[e],a,b);else for(var c in a)this.unbind(c,a[c]);return this},delegate:function(a,b,c,d){return this.live(b,c,d,a)},undelegate:function(a,b,c){return arguments.length===0?this.unbind("live"):this.die(b,null,c,a)},trigger:function(a,b){return this.each(function(){d.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){var c=d.Event(a);c.preventDefault(),c.stopPropagation(),d.event.trigger(c,b,this[0]);return c.result}},toggle:function(a){var b=arguments,c=1;while(c<b.length)d.proxy(a,b[c++]);return this.click(d.proxy(a,function(e){var f=(d._data(this,"lastToggle"+a.guid)||0)%c;d._data(this,"lastToggle"+a.guid,f+1),e.preventDefault();return b[f].apply(this,arguments)||!1}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var F={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};d.each(["live","die"],function(a,c){d.fn[c]=function(a,e,f,g){var h,i=0,j,k,l,m=g||this.selector,n=g?this:d(this.context);if(typeof a==="object"&&!a.preventDefault){for(var o in a)n[c](o,e,a[o],m);return this}d.isFunction(e)&&(f=e,e=b),a=(a||"").split(" ");while((h=a[i++])!=null){j=r.exec(h),k="",j&&(k=j[0],h=h.replace(r,""));if(h==="hover"){a.push("mouseenter"+k,"mouseleave"+k);continue}l=h,h==="focus"||h==="blur"?(a.push(F[h]+k),h=h+k):h=(F[h]||h)+k;if(c==="live")for(var p=0,q=n.length;p<q;p++)d.event.add(n[p],"live."+H(h,m),{data:e,selector:m,handler:f,origType:h,origHandler:f,preType:l});else n.unbind("live."+H(h,m),f)}return this}}),d.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){d.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.bind(b,a,c):this.trigger(b)},d.attrFn&&(d.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}if(i.nodeType===1){f||(i.sizcache=c,i.sizset=g);if(typeof b!=="string"){if(i===b){j=!0;break}}else if(k.filter(b,[i]).length>0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}i.nodeType===1&&!f&&(i.sizcache=c,i.sizset=g);if(i.nodeName.toLowerCase()===b){j=i;break}i=i[a]}d[g]=j}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,e,g){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!=="string")return e;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(f.call(n)==="[object Array]")if(u)if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&e.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&e.push(j[t]);else e.push.apply(e,n);else p(n,e);o&&(k(o,h,e,g),k.uniqueSort(e));return e};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},k.matches=function(a,b){return k(a,null,null,b)},k.matchesSelector=function(a,b){return k(b,null,null,[a]).length>0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e<f;e++){var g,h=l.order[e];if(g=l.leftMatch[h].exec(a)){var j=g[1];g.splice(1,1);if(j.substr(j.length-1)!=="\\"){g[1]=(g[1]||"").replace(i,""),d=l.find[h](g,b,c);if(d!=null){a=a.replace(l.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!=="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},k.filter=function(a,c,d,e){var f,g,h=a,i=[],j=c,m=c&&c[0]&&k.isXML(c[0]);while(a&&c.length){for(var n in l.filter)if((f=l.leftMatch[n].exec(a))!=null&&f[2]){var o,p,q=l.filter[n],r=f[1];g=!1,f.splice(1,1);if(r.substr(r.length-1)==="\\")continue;j===i&&(i=[]);if(l.preFilter[n]){f=l.preFilter[n](f,j,d,i,e,m);if(f){if(f===!0)continue}else g=o=!0}if(f)for(var s=0;(p=j[s])!=null;s++)if(p){o=q(p,f,s,j);var t=e^!!o;d&&o!=null?t?g=!0:j[s]=!1:t&&(i.push(p),g=!0)}if(o!==b){d||(j=i),a=a.replace(l.match[n],"");if(!g)return[];break}}if(a===h)if(g==null)k.error(a);else break;h=a}return j},k.error=function(a){throw"Syntax error, unrecognized expression: "+a};var l=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b==="string",d=c&&!j.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1){}a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&k.filter(b,a,!0)},">":function(a,b){var c,d=typeof b==="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&k.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=u;typeof b==="string"&&!j.test(b)&&(b=b.toLowerCase(),d=b,g=t),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=u;typeof b==="string"&&!j.test(b)&&(b=b.toLowerCase(),d=b,g=t),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!=="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!=="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!=="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(i,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return"text"===c&&(b===c||b===null)},radio:function(a){return"radio"===a.type},checkbox:function(a){return"checkbox"===a.type},file:function(a){return"file"===a.type},password:function(a){return"password"===a.type},submit:function(a){return"submit"===a.type},image:function(a){return"image"===a.type},reset:function(a){return"reset"===a.type},button:function(a){return"button"===a.type||a.nodeName.toLowerCase()==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}k.error(e)},CHILD:function(a,b){var c=b[1],d=a;switch(c){case"only":case"first":while(d=d.previousSibling)if(d.nodeType===1)return!1;if(c==="first")return!0;d=a;case"last":while(d=d.nextSibling)if(d.nodeType===1)return!1;return!0;case"nth":var e=b[2],f=b[3];if(e===1&&f===0)return!0;var g=b[0],h=a.parentNode;if(h&&(h.sizcache!==g||!a.nodeIndex)){var i=0;for(d=h.firstChild;d;d=d.nextSibling)d.nodeType===1&&(d.nodeIndex=++i);h.sizcache=g}var j=a.nodeIndex-f;return e===0?j===0:j%e===0&&j/e>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(f.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length==="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var r,s;c.documentElement.compareDocumentPosition?r=function(a,b){if(a===b){g=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(r=function(a,b){var c,d,e=[],f=[],h=a.parentNode,i=b.parentNode,j=h;if(a===b){g=!0;return 0}if(h===i)return s(a,b);if(!h)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return s(e[k],f[k]);return k===c?s(a,f[k],-1):s(e[k],b,1)},s=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),k.getText=function(a){var b="",c;for(var d=0;a[d];d++)c=a[d],c.nodeType===3||c.nodeType===4?b+=c.nodeValue:c.nodeType!==8&&(b+=k.getText(c.childNodes));return b},function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!=="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!=="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!=="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!=="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!=="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g<h;g++)k(a,f[g],d);return k.filter(e,d)};d.find=k,d.expr=k.selectors,d.expr[":"]=d.expr.filters,d.unique=k.uniqueSort,d.text=k.getText,d.isXMLDoc=k.isXML,d.contains=k.contains}();var I=/Until$/,J=/^(?:parents|prevUntil|prevAll)/,K=/,/,L=/^.[^:#\[\.,]*$/,M=Array.prototype.slice,N=d.expr.match.POS,O={children:!0,contents:!0,next:!0,prev:!0};d.fn.extend({find:function(a){var b=this.pushStack("","find",a),c=0;for(var e=0,f=this.length;e<f;e++){c=b.length,d.find(a,this[e],b);if(e>0)for(var g=c;g<b.length;g++)for(var h=0;h<c;h++)if(b[h]===b[g]){b.splice(g--,1);break}}return b},has:function(a){var b=d(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(d.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(Q(this,a,!1),"not",a)},filter:function(a){return this.pushStack(Q(this,a,!0),"filter",a)},is:function(a){return!!a&&d.filter(a,this).length>0},closest:function(a,b){var c=[],e,f,g=this[0];if(d.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(e=0,f=a.length;e<f;e++)i=a[e],j[i]||(j[i]=d.expr.match.POS.test(i)?d(i,b||this.context):i);while(g&&g.ownerDocument&&g!==b){for(i in j)h=j[i],(h.jquery?h.index(g)>-1:d(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=N.test(a)?d(a,b||this.context):null;for(e=0,f=this.length;e<f;e++){g=this[e];while(g){if(l?l.index(g)>-1:d.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b)break}}c=c.length>1?d.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a==="string")return d.inArray(this[0],a?d(a):this.parent().children());return d.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a==="string"?d(a,b):d.makeArray(a),e=d.merge(this.get(),c);return this.pushStack(P(c[0])||P(e[0])?e:d.unique(e))},andSelf:function(){return this.add(this.prevObject)}}),d.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return d.dir(a,"parentNode")},parentsUntil:function(a,b,c){return d.dir(a,"parentNode",c)},next:function(a){return d.nth(a,2,"nextSibling")},prev:function(a){return d.nth(a,2,"previousSibling")},nextAll:function(a){return d.dir(a,"nextSibling")},prevAll:function(a){return d.dir(a,"previousSibling")},nextUntil:function(a,b,c){return d.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return d.dir(a,"previousSibling",c)},siblings:function(a){return d.sibling(a.parentNode.firstChild,a)},children:function(a){return d.sibling(a.firstChild)},contents:function(a){return d.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:d.makeArray(a.childNodes)}},function(a,b){d.fn[a]=function(c,e){var f=d.map(this,b,c),g=M.call(arguments);I.test(a)||(e=c),e&&typeof e==="string"&&(f=d.filter(e,f)),f=this.length>1&&!O[a]?d.unique(f):f,(this.length>1||K.test(e))&&J.test(a)&&(f=f.reverse());return this.pushStack(f,a,g.join(","))}}),d.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?d.find.matchesSelector(b[0],a)?[b[0]]:[]:d.find.matches(a,b)},dir:function(a,c,e){var f=[],g=a[c];while(g&&g.nodeType!==9&&(e===b||g.nodeType!==1||!d(g).is(e)))g.nodeType===1&&f.push(g),g=g[c];return f},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var R=/ jQuery\d+="(?:\d+|null)"/g,S=/^\s+/,T=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,U=/<([\w:]+)/,V=/<tbody/i,W=/<|&#?\w+;/,X=/<(?:script|object|embed|option|style)/i,Y=/checked\s*(?:[^=]|=\s*.checked.)/i,Z={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};Z.optgroup=Z.option,Z.tbody=Z.tfoot=Z.colgroup=Z.caption=Z.thead,Z.th=Z.td,d.support.htmlSerialize||(Z._default=[1,"div<div>","</div>"]),d.fn.extend({text:function(a){if(d.isFunction(a))return this.each(function(b){var c=d(this);c.text(a.call(this,b,c.text()))});if(typeof a!=="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return d.text(this)},wrapAll:function(a){if(d.isFunction(a))return this.each(function(b){d(this).wrapAll(a.call(this,b))});if(this[0]){var b=d(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(d.isFunction(a))return this.each(function(b){d(this).wrapInner(a.call(this,b))});return this.each(function(){var b=d(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){d(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){d.nodeName(this,"body")||d(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=d(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,d(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,e;(e=this[c])!=null;c++)if(!a||d.filter(a,[e]).length)!b&&e.nodeType===1&&(d.cleanData(e.getElementsByTagName("*")),d.cleanData([e])),e.parentNode&&e.parentNode.removeChild(e);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&d.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return d.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(R,""):null;if(typeof a!=="string"||X.test(a)||!d.support.leadingWhitespace&&S.test(a)||Z[(U.exec(a)||["",""])[1].toLowerCase()])d.isFunction(a)?this.each(function(b){var c=d(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);else{a=a.replace(T,"<$1></$2>");try{for(var c=0,e=this.length;c<e;c++)this[c].nodeType===1&&(d.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(f){this.empty().append(a)}}return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(d.isFunction(a))return this.each(function(b){var c=d(this),e=c.html();c.replaceWith(a.call(this,b,e))});typeof a!=="string"&&(a=d(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;d(this).remove(),b?d(b).before(a):d(c).append(a)})}return this.length?this.pushStack(d(d.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,e){var f,g,h,i,j=a[0],k=[];if(!d.support.checkClone&&arguments.length===3&&typeof j==="string"&&Y.test(j))return this.each(function(){d(this).domManip(a,c,e,!0)});if(d.isFunction(j))return this.each(function(f){var g=d(this);a[0]=j.call(this,f,c?g.html():b),g.domManip(a,c,e)});if(this[0]){i=j&&j.parentNode,d.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?f={fragment:i}:f=d.buildFragment(a,this,k),h=f.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&d.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)e.call(c?$(this[l],g):this[l],f.cacheable||m>1&&l<n?d.clone(h,!0,!0):h)}k.length&&d.each(k,bc)}return this}}),d.buildFragment=function(a,b,e){var f,g,h,i=b&&b[0]?b[0].ownerDocument||b[0]:c;a.length===1&&typeof a[0]==="string"&&a[0].length<512&&i===c&&a[0].charAt(0)==="<"&&!X.test(a[0])&&(d.support.checkClone||!Y.test(a[0]))&&(g=!0,h=d.fragments[a[0]],h&&(h!==1&&(f=h))),f||(f=i.createDocumentFragment(),d.clean(a,i,f,e)),g&&(d.fragments[a[0]]=h?f:1);return{fragment:f,cacheable:g}},d.fragments={},d.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){d.fn[a]=function(c){var e=[],f=d(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&f.length===1){f[b](this[0]);return this}for(var h=0,i=f.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();d(f[h])[b](j),e=e.concat(j)}return this.pushStack(e,a,f.selector)}}),d.extend({clone:function(a,b,c){var e=a.cloneNode(!0),f,g,h;if((!d.support.noCloneEvent||!d.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!d.isXMLDoc(a)){ba(a,e),f=bb(a),g=bb(e);for(h=0;f[h];++h)ba(f[h],g[h])}if(b){_(a,e);if(c){f=bb(a),g=bb(e);for(h=0;f[h];++h)_(f[h],g[h])}}return e},clean:function(a,b,e,f){b=b||c,typeof b.createElement==="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var g=[];for(var h=0,i;(i=a[h])!=null;h++){typeof i==="number"&&(i+="");if(!i)continue;if(typeof i!=="string"||W.test(i)){if(typeof i==="string"){i=i.replace(T,"<$1></$2>");var j=(U.exec(i)||["",""])[1].toLowerCase(),k=Z[j]||Z._default,l=k[0],m=b.createElement("div");m.innerHTML=k[1]+i+k[2];while(l--)m=m.lastChild;if(!d.support.tbody){var n=V.test(i),o=j==="table"&&!n?m.firstChild&&m.firstChild.childNodes:k[1]==="<table>"&&!n?m.childNodes:[];for(var p=o.length-1;p>=0;--p)d.nodeName(o[p],"tbody")&&!o[p].childNodes.length&&o[p].parentNode.removeChild(o[p])}!d.support.leadingWhitespace&&S.test(i)&&m.insertBefore(b.createTextNode(S.exec(i)[0]),m.firstChild),i=m.childNodes}}else i=b.createTextNode(i);i.nodeType?g.push(i):g=d.merge(g,i)}if(e)for(h=0;g[h];h++)!f||!d.nodeName(g[h],"script")||g[h].type&&g[h].type.toLowerCase()!=="text/javascript"?(g[h].nodeType===1&&g.splice.apply(g,[h+1,0].concat(d.makeArray(g[h].getElementsByTagName("script")))),e.appendChild(g[h])):f.push(g[h].parentNode?g[h].parentNode.removeChild(g[h]):g[h]);return g},cleanData:function(a){var b,c,e=d.cache,f=d.expando,g=d.event.special,h=d.support.deleteExpando;for(var i=0,j;(j=a[i])!=null;i++){if(j.nodeName&&d.noData[j.nodeName.toLowerCase()])continue;c=j[d.expando];if(c){b=e[c]&&e[c][f];if(b&&b.events){for(var k in b.events)g[k]?d.event.remove(j,k):d.removeEvent(j,k,b.handle);b.handle&&(b.handle.elem=null)}h?delete j[d.expando]:j.removeAttribute&&j.removeAttribute(d.expando),delete e[c]}}}});var bd=/alpha\([^)]*\)/i,be=/opacity=([^)]*)/,bf=/-([a-z])/ig,bg=/([A-Z]|^ms)/g,bh=/^-?\d+(?:px)?$/i,bi=/^-?\d/,bj={position:"absolute",visibility:"hidden",display:"block"},bk=["Left","Right"],bl=["Top","Bottom"],bm,bn,bo,bp=function(a,b){return b.toUpperCase()};d.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return d.access(this,a,c,!0,function(a,c,e){return e!==b?d.style(a,c,e):d.css(a,c)})},d.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bm(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{zIndex:!0,fontWeight:!0,opacity:!0,zoom:!0,lineHeight:!0},cssProps:{"float":d.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,e,f){if(a&&a.nodeType!==3&&a.nodeType!==8&&a.style){var g,h=d.camelCase(c),i=a.style,j=d.cssHooks[h];c=d.cssProps[h]||h;if(e===b){if(j&&"get"in j&&(g=j.get(a,!1,f))!==b)return g;return i[c]}if(typeof e==="number"&&isNaN(e)||e==null)return;typeof e==="number"&&!d.cssNumber[h]&&(e+="px");if(!j||!("set"in j)||(e=j.set(a,e))!==b)try{i[c]=e}catch(k){}}},css:function(a,c,e){var f,g=d.camelCase(c),h=d.cssHooks[g];c=d.cssProps[g]||g;if(h&&"get"in h&&(f=h.get(a,!0,e))!==b)return f;if(bm)return bm(a,c,g)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]},camelCase:function(a){return a.replace(bf,bp)}}),d.curCSS=d.css,d.each(["height","width"],function(a,b){d.cssHooks[b]={get:function(a,c,e){var f;if(c){a.offsetWidth!==0?f=bq(a,b,e):d.swap(a,bj,function(){f=bq(a,b,e)});if(f<=0){f=bm(a,b,b),f==="0px"&&bo&&(f=bo(a,b,b));if(f!=null)return f===""||f==="auto"?"0px":f}if(f<0||f==null){f=a.style[b];return f===""||f==="auto"?"0px":f}return typeof f==="string"?f:f+"px"}},set:function(a,b){if(!bh.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),d.support.opacity||(d.cssHooks.opacity={get:function(a,b){return be.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style;c.zoom=1;var e=d.isNaN(b)?"":"alpha(opacity="+b*100+")",f=c.filter||"";c.filter=bd.test(f)?f.replace(bd,e):c.filter+" "+e}}),d(function(){d.support.reliableMarginRight||(d.cssHooks.marginRight={get:function(a,b){var c;d.swap(a,{display:"inline-block"},function(){b?c=bm(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bn=function(a,c,e){var f,g,h;e=e.replace(bg,"-$1").toLowerCase();if(!(g=a.ownerDocument.defaultView))return b;if(h=g.getComputedStyle(a,null))f=h.getPropertyValue(e),f===""&&!d.contains(a.ownerDocument.documentElement,a)&&(f=d.style(a,e));return f}),c.documentElement.currentStyle&&(bo=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bh.test(d)&&bi.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bm=bn||bo,d.expr&&d.expr.filters&&(d.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!d.support.reliableHiddenOffsets&&(a.style.display||d.css(a,"display"))==="none"},d.expr.filters.visible=function(a){return!d.expr.filters.hidden(a)});var br=/%20/g,bs=/\[\]$/,bt=/\r?\n/g,bu=/#.*$/,bv=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bw=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bx=/^(?:about|app|app\-storage|.+\-extension|file|widget):$/,by=/^(?:GET|HEAD)$/,bz=/^\/\//,bA=/\?/,bB=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bC=/^(?:select|textarea)/i,bD=/\s+/,bE=/([?&])_=[^&]*/,bF=/(^|\-)([a-z])/g,bG=function(a,b,c){return b+c.toUpperCase()},bH=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bI=d.fn.load,bJ={},bK={},bL,bM;try{bL=c.location.href}catch(bN){bL=c.createElement("a"),bL.href="",bL=bL.href}bM=bH.exec(bL.toLowerCase())||[],d.fn.extend({load:function(a,c,e){if(typeof a!=="string"&&bI)return bI.apply(this,arguments);if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var g=a.slice(f,a.length);a=a.slice(0,f)}var h="GET";c&&(d.isFunction(c)?(e=c,c=b):typeof c==="object"&&(c=d.param(c,d.ajaxSettings.traditional),h="POST"));var i=this;d.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?d("<div>").append(c.replace(bB,"")).find(g):c)),e&&i.each(e,[c,b,a])}});return this},serialize:function(){return d.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?d.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bC.test(this.nodeName)||bw.test(this.type))}).map(function(a,b){var c=d(this).val();return c==null?null:d.isArray(c)?d.map(c,function(a,c){return{name:b.name,value:a.replace(bt,"\r\n")}}):{name:b.name,value:c.replace(bt,"\r\n")}}).get()}}),d.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){d.fn[b]=function(a){return this.bind(b,a)}}),d.each(["get","post"],function(a,c){d[c]=function(a,e,f,g){d.isFunction(e)&&(g=g||f,f=e,e=b);return d.ajax({type:c,url:a,data:e,success:f,dataType:g})}}),d.extend({getScript:function(a,c){return d.get(a,b,c,"script")},getJSON:function(a,b,c){return d.get(a,b,c,"json")},ajaxSetup:function(a,b){b?d.extend(!0,a,d.ajaxSettings,b):(b=a,a=d.extend(!0,d.ajaxSettings,b));for(var c in {context:1,url:1})c in b?a[c]=b[c]:c in d.ajaxSettings&&(a[c]=d.ajaxSettings[c]);return a},ajaxSettings:{url:bL,isLocal:bx.test(bM[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":d.parseJSON,"text xml":d.parseXML}},ajaxPrefilter:bO(bJ),ajaxTransport:bO(bK),ajax:function(a,c){function v(a,c,l,n){if(r!==2){r=2,p&&clearTimeout(p),o=b,m=n||"",u.readyState=a?4:0;var q,t,v,w=l?bR(e,u,l):b,x,y;if(a>=200&&a<300||a===304){if(e.ifModified){if(x=u.getResponseHeader("Last-Modified"))d.lastModified[k]=x;if(y=u.getResponseHeader("Etag"))d.etag[k]=y}if(a===304)c="notmodified",q=!0;else try{t=bS(e,w),c="success",q=!0}catch(z){c="parsererror",v=z}}else{v=c;if(!c||a)c="error",a<0&&(a=0)}u.status=a,u.statusText=c,q?h.resolveWith(f,[t,c,u]):h.rejectWith(f,[u,c,v]),u.statusCode(j),j=b,s&&g.trigger("ajax"+(q?"Success":"Error"),[u,e,q?t:v]),i.resolveWith(f,[u,c]),s&&(g.trigger("ajaxComplete",[u,e]),--d.active||d.event.trigger("ajaxStop"))}}typeof a==="object"&&(c=a,a=b),c=c||{};var e=d.ajaxSetup({},c),f=e.context||e,g=f!==e&&(f.nodeType||f instanceof d)?d(f):d.event,h=d.Deferred(),i=d._Deferred(),j=e.statusCode||{},k,l={},m,n,o,p,q,r=0,s,t,u={readyState:0,setRequestHeader:function(a,b){r||(l[a.toLowerCase().replace(bF,bG)]=b);return this},getAllResponseHeaders:function(){return r===2?m:null},getResponseHeader:function(a){var c;if(r===2){if(!n){n={};while(c=bv.exec(m))n[c[1].toLowerCase()]=c[2]}c=n[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){r||(e.mimeType=a);return this},abort:function(a){a=a||"abort",o&&o.abort(a),v(0,a);return this}};h.promise(u),u.success=u.done,u.error=u.fail,u.complete=i.done,u.statusCode=function(a){if(a){var b;if(r<2)for(b in a)j[b]=[j[b],a[b]];else b=a[u.status],u.then(b,b)}return this},e.url=((a||e.url)+"").replace(bu,"").replace(bz,bM[1]+"//"),e.dataTypes=d.trim(e.dataType||"*").toLowerCase().split(bD),e.crossDomain==null&&(q=bH.exec(e.url.toLowerCase()),e.crossDomain=q&&(q[1]!=bM[1]||q[2]!=bM[2]||(q[3]||(q[1]==="http:"?80:443))!=(bM[3]||(bM[1]==="http:"?80:443)))),e.data&&e.processData&&typeof e.data!=="string"&&(e.data=d.param(e.data,e.traditional)),bP(bJ,e,c,u);if(r===2)return!1;s=e.global,e.type=e.type.toUpperCase(),e.hasContent=!by.test(e.type),s&&d.active++===0&&d.event.trigger("ajaxStart");if(!e.hasContent){e.data&&(e.url+=(bA.test(e.url)?"&":"?")+e.data),k=e.url;if(e.cache===!1){var w=d.now(),x=e.url.replace(bE,"$1_="+w);e.url=x+(x===e.url?(bA.test(e.url)?"&":"?")+"_="+w:"")}}if(e.data&&e.hasContent&&e.contentType!==!1||c.contentType)l["Content-Type"]=e.contentType;e.ifModified&&(k=k||e.url,d.lastModified[k]&&(l["If-Modified-Since"]=d.lastModified[k]),d.etag[k]&&(l["If-None-Match"]=d.etag[k])),l.Accept=e.dataTypes[0]&&e.accepts[e.dataTypes[0]]?e.accepts[e.dataTypes[0]]+(e.dataTypes[0]!=="*"?", */*; q=0.01":""):e.accepts["*"];for(t in e.headers)u.setRequestHeader(t,e.headers[t]);if(e.beforeSend&&(e.beforeSend.call(f,u,e)===!1||r===2)){u.abort();return!1}for(t in {success:1,error:1,complete:1})u[t](e[t]);o=bP(bK,e,c,u);if(o){u.readyState=1,s&&g.trigger("ajaxSend",[u,e]),e.async&&e.timeout>0&&(p=setTimeout(function(){u.abort("timeout")},e.timeout));try{r=1,o.send(l,v)}catch(y){status<2?v(-1,y):d.error(y)}}else v(-1,"No Transport");return u},param:function(a,c){var e=[],f=function(a,b){b=d.isFunction(b)?b():b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=d.ajaxSettings.traditional);if(d.isArray(a)||a.jquery&&!d.isPlainObject(a))d.each(a,function(){f(this.name,this.value)});else for(var g in a)bQ(g,a[g],c,f);return e.join("&").replace(br,"+")}}),d.extend({active:0,lastModified:{},etag:{}});var bT=d.now(),bU=/(\=)\?(&|$)|\?\?/i;d.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return d.expando+"_"+bT++}}),d.ajaxPrefilter("json jsonp",function(b,c,e){var f=typeof b.data==="string";if(b.dataTypes[0]==="jsonp"||c.jsonpCallback||c.jsonp!=null||b.jsonp!==!1&&(bU.test(b.url)||f&&bU.test(b.data))){var g,h=b.jsonpCallback=d.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2",m=function(){a[h]=i,g&&d.isFunction(i)&&a[h](g[0])};b.jsonp!==!1&&(j=j.replace(bU,l),b.url===j&&(f&&(k=k.replace(bU,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},e.then(m,m),b.converters["script json"]=function(){g||d.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),d.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){d.globalEval(a);return a}}}),d.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),d.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var bV=d.now(),bW,bX;d.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&bZ()||b$()}:bZ,bX=d.ajaxSettings.xhr(),d.support.ajax=!!bX,d.support.cors=bX&&"withCredentials"in bX,bX=b,d.support.ajax&&d.ajaxTransport(function(a){if(!a.crossDomain||d.support.cors){var c;return{send:function(e,f){var g=a.xhr(),h,i;a.username?g.open(a.type,a.url,a.async,a.username,a.password):g.open(a.type,a.url,a.async);if(a.xhrFields)for(i in a.xhrFields)g[i]=a.xhrFields[i];a.mimeType&&g.overrideMimeType&&g.overrideMimeType(a.mimeType),!a.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(i in e)g.setRequestHeader(i,e[i])}catch(j){}g.send(a.hasContent&&a.data||null),c=function(e,i){var j,k,l,m,n;try{if(c&&(i||g.readyState===4)){c=b,h&&(g.onreadystatechange=d.noop,delete bW[h]);if(i)g.readyState!==4&&g.abort();else{j=g.status,l=g.getAllResponseHeaders(),m={},n=g.responseXML,n&&n.documentElement&&(m.xml=n),m.text=g.responseText;try{k=g.statusText}catch(o){k=""}j||!a.isLocal||a.crossDomain?j===1223&&(j=204):j=m.text?200:404}}}catch(p){i||f(-1,p)}m&&f(j,k,m,l)},a.async&&g.readyState!==4?(bW||(bW={},bY()),h=bV++,g.onreadystatechange=bW[h]=c):c()},abort:function(){c&&c(0,1)}}}});var b_={},ca=/^(?:toggle|show|hide)$/,cb=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cc,cd=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];d.fn.extend({show:function(a,b,c){var e,f;if(a||a===0)return this.animate(ce("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)e=this[g],f=e.style.display,!d._data(e,"olddisplay")&&f==="none"&&(f=e.style.display=""),f===""&&d.css(e,"display")==="none"&&d._data(e,"olddisplay",cf(e.nodeName));for(g=0;g<h;g++){e=this[g],f=e.style.display;if(f===""||f==="none")e.style.display=d._data(e,"olddisplay")||""}return this},hide:function(a,b,c){if(a||a===0)return this.animate(ce("hide",3),a,b,c);for(var e=0,f=this.length;e<f;e++){var g=d.css(this[e],"display");g!=="none"&&!d._data(this[e],"olddisplay")&&d._data(this[e],"olddisplay",g)}for(e=0;e<f;e++)this[e].style.display="none";return this},_toggle:d.fn.toggle,toggle:function(a,b,c){var e=typeof a==="boolean";d.isFunction(a)&&d.isFunction(b)?this._toggle.apply(this,arguments):a==null||e?this.each(function(){var b=e?a:d(this).is(":hidden");d(this)[b?"show":"hide"]()}):this.animate(ce("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,e){var f=d.speed(b,c,e);if(d.isEmptyObject(a))return this.each(f.complete);return this[f.queue===!1?"each":"queue"](function(){var b=d.extend({},f),c,e=this.nodeType===1,g=e&&d(this).is(":hidden"),h=this;for(c in a){var i=d.camelCase(c);c!==i&&(a[i]=a[c],delete a[c],c=i);if(a[c]==="hide"&&g||a[c]==="show"&&!g)return b.complete.call(this);if(e&&(c==="height"||c==="width")){b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY];if(d.css(this,"display")==="inline"&&d.css(this,"float")==="none")if(d.support.inlineBlockNeedsLayout){var j=cf(this.nodeName);j==="inline"?this.style.display="inline-block":(this.style.display="inline",this.style.zoom=1)}else this.style.display="inline-block"}d.isArray(a[c])&&((b.specialEasing=b.specialEasing||{})[c]=a[c][1],a[c]=a[c][0])}b.overflow!=null&&(this.style.overflow="hidden"),b.curAnim=d.extend({},a),d.each(a,function(c,e){var f=new d.fx(h,b,c);if(ca.test(e))f[e==="toggle"?g?"show":"hide":e](a);else{var i=cb.exec(e),j=f.cur();if(i){var k=parseFloat(i[2]),l=i[3]||(d.cssNumber[c]?"":"px");l!=="px"&&(d.style(h,c,(k||1)+l),j=(k||1)/f.cur()*j,d.style(h,c,j+l)),i[1]&&(k=(i[1]==="-="?-1:1)*k+j),f.custom(j,k,l)}else f.custom(j,e,"")}});return!0})},stop:function(a,b){var c=d.timers;a&&this.queue([]),this.each(function(){for(var a=c.length-1;a>=0;a--)c[a].elem===this&&(b&&c[a](!0),c.splice(a,1))}),b||this.dequeue();return this}}),d.each({slideDown:ce("show",1),slideUp:ce("hide",1),slideToggle:ce("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){d.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),d.extend({speed:function(a,b,c){var e=a&&typeof a==="object"?d.extend({},a):{complete:c||!c&&b||d.isFunction(a)&&a,duration:a,easing:c&&b||b&&!d.isFunction(b)&&b};e.duration=d.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in d.fx.speeds?d.fx.speeds[e.duration]:d.fx.speeds._default,e.old=e.complete,e.complete=function(){e.queue!==!1&&d(this).dequeue(),d.isFunction(e.old)&&e.old.call(this)};return e},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig||(b.orig={})}}),d.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(d.fx.step[this.prop]||d.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=d.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,b,c){function g(a){return e.step(a)}var e=this,f=d.fx;this.startTime=d.now(),this.start=a,this.end=b,this.unit=c||this.unit||(d.cssNumber[this.prop]?"":"px"),this.now=this.start,this.pos=this.state=0,g.elem=this.elem,g()&&d.timers.push(g)&&!cc&&(cc=setInterval(f.tick,f.interval))},show:function(){this.options.orig[this.prop]=d.style(this.elem,this.prop),this.options.show=!0,this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),d(this.elem).show()},hide:function(){this.options.orig[this.prop]=d.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b=d.now(),c=!0;if(a||b>=this.options.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),this.options.curAnim[this.prop]=!0;for(var e in this.options.curAnim)this.options.curAnim[e]!==!0&&(c=!1);if(c){if(this.options.overflow!=null&&!d.support.shrinkWrapBlocks){var f=this.elem,g=this.options;d.each(["","X","Y"],function(a,b){f.style["overflow"+b]=g.overflow[a]})}this.options.hide&&d(this.elem).hide();if(this.options.hide||this.options.show)for(var h in this.options.curAnim)d.style(this.elem,h,this.options.orig[h]);this.options.complete.call(this.elem)}return!1}var i=b-this.startTime;this.state=i/this.options.duration;var j=this.options.specialEasing&&this.options.specialEasing[this.prop],k=this.options.easing||(d.easing.swing?"swing":"linear");this.pos=d.easing[j||k](this.state,i,0,1,this.options.duration),this.now=this.start+(this.end-this.start)*this.pos,this.update();return!0}},d.extend(d.fx,{tick:function(){var a=d.timers;for(var b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||d.fx.stop()},interval:13,stop:function(){clearInterval(cc),cc=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){d.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit:a.elem[a.prop]=a.now}}}),d.expr&&d.expr.filters&&(d.expr.filters.animated=function(a){return d.grep(d.timers,function(b){return a===b.elem}).length});var cg=/^t(?:able|d|h)$/i,ch=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?d.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){d.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return d.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(e){}var f=b.ownerDocument,g=f.documentElement;if(!c||!d.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=f.body,i=ci(f),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||d.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||d.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:d.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){d.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return d.offset.bodyOffset(b);d.offset.initialize();var c,e=b.offsetParent,f=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(d.offset.supportsFixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===e&&(l+=b.offsetTop,m+=b.offsetLeft,d.offset.doesNotAddBorder&&(!d.offset.doesAddBorderForTableAndCells||!cg.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),f=e,e=b.offsetParent),d.offset.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;d.offset.supportsFixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},d.offset={initialize:function(){var a=c.body,b=c.createElement("div"),e,f,g,h,i=parseFloat(d.css(a,"marginTop"))||0,j="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";d.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),e=b.firstChild,f=e.firstChild,h=e.nextSibling.firstChild.firstChild,this.doesNotAddBorder=f.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,f.style.position="fixed",f.style.top="20px",this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15,f.style.position=f.style.top="",e.style.overflow="hidden",e.style.position="relative",this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),d.offset.initialize=d.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;d.offset.initialize(),d.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(d.css(a,"marginTop"))||0,c+=parseFloat(d.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var e=d.css(a,"position");e==="static"&&(a.style.position="relative");var f=d(a),g=f.offset(),h=d.css(a,"top"),i=d.css(a,"left"),j=(e==="absolute"||e==="fixed")&&d.inArray("auto",[h,i])>-1,k={},l={},m,n;j&&(l=f.position()),m=j?l.top:parseInt(h,10)||0,n=j?l.left:parseInt(i,10)||0,d.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):f.css(k)}},d.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),e=ch.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(d.css(a,"marginTop"))||0,c.left-=parseFloat(d.css(a,"marginLeft"))||0,e.top+=parseFloat(d.css(b[0],"borderTopWidth"))||0,e.left+=parseFloat(d.css(b[0],"borderLeftWidth"))||0;return{top:c.top-e.top,left:c.left-e.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&(!ch.test(a.nodeName)&&d.css(a,"position")==="static"))a=a.offsetParent;return a})}}),d.each(["Left","Top"],function(a,c){var e="scroll"+c;d.fn[e]=function(c){var f=this[0],g;if(!f)return null;if(c!==b)return this.each(function(){g=ci(this),g?g.scrollTo(a?d(g).scrollLeft():c,a?c:d(g).scrollTop()):this[e]=c});g=ci(f);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:d.support.boxModel&&g.document.documentElement[e]||g.document.body[e]:f[e]}}),d.each(["Height","Width"],function(a,c){var e=c.toLowerCase();d.fn["inner"+c]=function(){return this[0]?parseFloat(d.css(this[0],e,"padding")):null},d.fn["outer"+c]=function(a){return this[0]?parseFloat(d.css(this[0],e,a?"margin":"border")):null},d.fn[e]=function(a){var f=this[0];if(!f)return a==null?null:this;if(d.isFunction(a))return this.each(function(b){var c=d(this);c[e](a.call(this,b,c[e]()))});if(d.isWindow(f)){var g=f.document.documentElement["client"+c];return f.document.compatMode==="CSS1Compat"&&g||f.document.body["client"+c]||g}if(f.nodeType===9)return Math.max(f.documentElement["client"+c],f.body["scroll"+c],f.documentElement["scroll"+c],f.body["offset"+c],f.documentElement["offset"+c]);if(a===b){var h=d.css(f,e),i=parseFloat(h);return d.isNaN(i)?h:i}return this.css(e,typeof a==="string"?a:a+"px")}}),a.jQuery=a.$=d})(window);
\ No newline at end of file
diff --git a/third_party/seasocks/src/main/web/_seasocks.css b/third_party/seasocks/src/main/web/_seasocks.css
new file mode 100644
index 0000000..03a7287
--- /dev/null
+++ b/third_party/seasocks/src/main/web/_seasocks.css
@@ -0,0 +1,22 @@
+body {
+    font-family: segoe ui, tahoma, arial, sans-serif;
+    font-size: 12px;
+    color: #ffffff;
+    background-color: #333333;
+    margin: 0;
+}
+
+a {
+    color: #ffff00;
+}
+
+table {
+    border-collapse: collapse;
+    width: 100%;
+    text-align: center;
+}
+
+.template {
+    display: none;
+}
+
diff --git a/third_party/seasocks/src/main/web/_stats.html b/third_party/seasocks/src/main/web/_stats.html
new file mode 100644
index 0000000..d34e932
--- /dev/null
+++ b/third_party/seasocks/src/main/web/_stats.html
@@ -0,0 +1,60 @@
+<html DOCTYPE=html>
+<head>
+  <title>SeaSocks Stats</title>
+  <link href="/_seasocks.css" rel="stylesheet">
+  <script src="/_jquery.min.js" type="text/javascript"></script>
+  <script>
+  function clear() {
+    $('#cx tbody tr:visible').remove();
+  }
+  function connection(stats) {
+  	c = $('#cx .template').clone().removeClass('template').appendTo('#cx');
+  	for (stat in stats) {
+  	  c.find('.' + stat).text(stats[stat]);
+    }
+  }
+  function refresh() {
+  		var stats = new XMLHttpRequest();
+		stats.open("GET", "/_livestats.js", false);
+		stats.send(null);
+		eval(stats.responseText);
+  }
+  $(function() {
+  	setInterval(refresh, 1000);
+  	refresh();		
+  });
+  </script>
+</head>
+<body><h1>SeaSocks Stats</h1></body>
+
+<h2>Connections</h2>
+<table id="cx">
+  <thead>
+    <tr>
+      <th>Connection time</th>
+      <th>Fd</th>
+      <th>Addr</th>
+      <th>URI</th>
+      <th>Username</th>
+      <th>Pending read</th>
+      <th>Bytes read</th>
+      <th>Pending send</th>
+      <th>Bytes sent</th>
+    </tr>
+  </thead>
+  <tbody>
+    <tr class="template">
+      <td class="since"></td>
+      <td class="fd"></td>
+      <td class="addr"></td>
+      <td class="uri"></td>
+      <td class="user"></td>
+      <td class="input"></td>
+      <td class="read"></td>
+      <td class="output"></td>
+      <td class="written"></td>
+    </tr>
+  </tbody>
+</table>
+
+</body></html>
diff --git a/third_party/seasocks/src/main/web/favicon.ico b/third_party/seasocks/src/main/web/favicon.ico
new file mode 100644
index 0000000..30a95b9
--- /dev/null
+++ b/third_party/seasocks/src/main/web/favicon.ico
Binary files differ
diff --git a/third_party/seasocks/src/test/c/ConnectionTests.cpp b/third_party/seasocks/src/test/c/ConnectionTests.cpp
new file mode 100644
index 0000000..ee73681
--- /dev/null
+++ b/third_party/seasocks/src/test/c/ConnectionTests.cpp
@@ -0,0 +1,89 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "MockServerImpl.h"
+#include "seasocks/Connection.h"
+#include "seasocks/IgnoringLogger.h"
+
+#include <gmock/gmock.h>
+
+#include <iostream>
+#include <sstream>
+#include <string.h>
+#include <string>
+
+using namespace seasocks;
+
+class TestHandler: public WebSocket::Handler {
+public:
+    int _stage;
+    TestHandler() :
+        _stage(0) {
+    }
+    ~TestHandler() {
+        if (_stage != 2) {
+            ADD_FAILURE() << "Invalid state";
+        }
+    }
+    virtual void onConnect(WebSocket*) {
+    }
+    virtual void onData(WebSocket*, const char* data) {
+        if (_stage == 0) {
+            ASSERT_STREQ(data, "a");
+        } else if (_stage == 1) {
+            ASSERT_STREQ(data, "b");
+        } else {
+            FAIL() << "unexpected state";
+        }
+        ++_stage;
+    }
+    virtual void onDisconnect(WebSocket*) {
+    }
+};
+
+TEST(ConnectionTests, shouldBreakHixieMessagesApartInSameBuffer) {
+    sockaddr_in addr = { AF_INET, 0x1234, { 0x01020304 } };
+    std::shared_ptr<Logger> logger(new IgnoringLogger);
+    testing::NiceMock<MockServerImpl> mockServer;
+    Connection connection(logger, mockServer, -1, addr);
+    connection.setHandler(
+            std::shared_ptr<WebSocket::Handler>(new TestHandler));
+    uint8_t foo[] = { 0x00, 'a', 0xff, 0x00, 'b', 0xff };
+    connection.getInputBuffer().assign(&foo[0], &foo[sizeof(foo)]);
+    connection.handleHixieWebSocket();
+    SUCCEED();
+}
+
+TEST(ConnectionTests, shouldAcceptMultipleConnectionTypes) {
+    sockaddr_in addr = { AF_INET, 0x1234, { 0x01020304 } };
+    std::shared_ptr<Logger> logger(new IgnoringLogger);
+    testing::NiceMock<MockServerImpl> mockServer;
+    Connection connection(logger, mockServer, -1, addr);
+    const uint8_t message[] = "GET /ws-test HTTP/1.1\r\nConnection: keep-alive, Upgrade\r\nUpgrade: websocket\r\n\r\n";
+    connection.getInputBuffer().assign(&message[0], &message[sizeof(message)]);
+    EXPECT_CALL(mockServer, getWebSocketHandler(testing::StrEq("/ws-test")))
+        .WillOnce(testing::Return(std::shared_ptr<WebSocket::Handler>()));
+    connection.handleNewData();
+}
diff --git a/third_party/seasocks/src/test/c/CrackedUriTests.cpp b/third_party/seasocks/src/test/c/CrackedUriTests.cpp
new file mode 100644
index 0000000..a9243f6
--- /dev/null
+++ b/third_party/seasocks/src/test/c/CrackedUriTests.cpp
@@ -0,0 +1,147 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "seasocks/util/CrackedUri.h"
+
+#include <gmock/gmock.h>
+
+using namespace testing;
+using namespace seasocks;
+using namespace std;
+
+namespace {
+
+TEST(CrackedUriTests, shouldHandleRoot) {
+    CrackedUri uri("/");
+    EXPECT_EQ(vector<string>(), uri.path());
+    EXPECT_TRUE(uri.queryParams().empty());
+}
+
+TEST(CrackedUriTests, shouldHandleTopLevel) {
+    CrackedUri uri("/monkey");
+    vector<string> expected = { "monkey" };
+    EXPECT_EQ(expected, uri.path());
+    EXPECT_TRUE(uri.queryParams().empty());
+}
+
+TEST(CrackedUriTests, shouldHandleSimplePaths) {
+    CrackedUri uri("/foo/bar/baz/bungo");
+    vector<string> expected = { "foo", "bar", "baz", "bungo" };
+    EXPECT_EQ(expected, uri.path());
+    EXPECT_TRUE(uri.queryParams().empty());
+}
+
+TEST(CrackedUriTests, shouldTreatTrailingSlashAsNewPage) {
+    CrackedUri uri("/ooh/a/directory/");
+    vector<string> expected = { "ooh", "a", "directory", "" };
+    EXPECT_EQ(expected, uri.path());
+    EXPECT_TRUE(uri.queryParams().empty());
+}
+
+TEST(CrackedUriTests, shouldHandleRootWithQuery) {
+    CrackedUri uri("/?a=spotch");
+    EXPECT_EQ(vector<string>(), uri.path());
+    ASSERT_FALSE(uri.queryParams().empty());
+    EXPECT_TRUE(uri.hasParam("a"));
+    EXPECT_EQ("spotch", uri.queryParam("a"));
+}
+
+TEST(CrackedUriTests, shouldHonorDefaults) {
+    CrackedUri uri("/?a=spotch");
+    EXPECT_EQ("monkey", uri.queryParam("notThere", "monkey"));
+}
+
+TEST(CrackedUriTests, shouldHandleEmptyParams) {
+    CrackedUri uri("/?a&b&c");
+    EXPECT_EQ("", uri.queryParam("a", "notEmptyDefault"));
+    EXPECT_EQ("", uri.queryParam("b", "notEmptyDefault"));
+    EXPECT_EQ("", uri.queryParam("c", "notEmptyDefault"));
+}
+
+TEST(CrackedUriTests, shouldHandleDuplicateParams) {
+    CrackedUri uri("/?a=a&q=10&q=5&z=yibble&q=100&q=blam");
+    vector<string> expected = { "10", "5", "100", "blam" };
+    sort(expected.begin(), expected.end());
+    auto params = uri.allQueryParams("q");
+    sort(params.begin(), params.end());
+    EXPECT_EQ(expected, params);
+}
+
+
+TEST(CrackedUriTests, shouldHandlePathWithQuery) {
+    CrackedUri uri("/badger/badger/badger/mushroom?q=snake");
+    vector<string> expected = { "badger", "badger", "badger", "mushroom" };
+    EXPECT_EQ(expected, uri.path());
+    ASSERT_FALSE(uri.queryParams().empty());
+    EXPECT_TRUE(uri.hasParam("q"));
+    EXPECT_EQ("snake", uri.queryParam("q"));
+}
+
+TEST(CrackedUriTests, shouldUnescapePaths) {
+    CrackedUri uri("/foo+bar/baz%2f/%40%4F");
+    vector<string> expected = { "foo bar", "baz/", "@O" };
+    EXPECT_EQ(expected, uri.path());
+}
+
+TEST(CrackedUriTests, shouldUnescapeQueries) {
+    CrackedUri uri("/?q=a+b&t=%20%20&p=%41");
+    EXPECT_EQ("a b", uri.queryParam("q"));
+    EXPECT_EQ("  ", uri.queryParam("t"));
+    EXPECT_EQ("A", uri.queryParam("p"));
+}
+
+
+TEST(CrackedUriTests, shouldThrowOnRubbish) {
+    EXPECT_THROW(CrackedUri(""), exception);
+    EXPECT_THROW(CrackedUri("rubbish"), exception);
+    EXPECT_THROW(CrackedUri("../../.."), exception);
+    EXPECT_THROW(CrackedUri("/?a===b"), exception);
+    EXPECT_THROW(CrackedUri("/%"), exception);
+    EXPECT_THROW(CrackedUri("/%a"), exception);
+    EXPECT_THROW(CrackedUri("/%qq"), exception);
+}
+
+TEST(CrackedUriTests, shouldShift) {
+    CrackedUri uri("/a/b/c.html");
+    vector<string> expected1 = {"a", "b", "c.html"};
+    EXPECT_EQ(expected1, uri.path());
+
+    uri = uri.shift();
+    vector<string> expected2 = {"b", "c.html"};
+    EXPECT_EQ(expected2, uri.path());
+
+    uri = uri.shift();
+    vector<string> expected3 = {"c.html"};
+    EXPECT_EQ(expected3, uri.path());
+
+    uri = uri.shift();
+    vector<string> expected4 = {""};
+    EXPECT_EQ(expected4, uri.path());
+
+    uri = uri.shift();
+    EXPECT_EQ(expected4, uri.path());
+}
+
+}
diff --git a/third_party/seasocks/src/test/c/HeaderMapTests.cpp b/third_party/seasocks/src/test/c/HeaderMapTests.cpp
new file mode 100644
index 0000000..a889739
--- /dev/null
+++ b/third_party/seasocks/src/test/c/HeaderMapTests.cpp
@@ -0,0 +1,49 @@
+#include "internal/HeaderMap.h"
+
+#include "internal/Config.h"
+
+#include <gmock/gmock.h>
+
+using namespace seasocks;
+
+namespace {
+
+void emplace(HeaderMap &map, const char *header, const char *value) {
+#if HAVE_UNORDERED_MAP_EMPLACE
+    map.emplace(header, value);
+#else
+    map.insert(std::make_pair(header, value));
+#endif
+}
+
+TEST(HeaderMapTests, shouldConstruct) {
+    HeaderMap map;
+    EXPECT_TRUE(map.empty());
+}
+
+TEST(HeaderMapTests, shouldStoreAndRetrieve) {
+    HeaderMap map;
+    emplace(map, "Foo", "Bar");
+    EXPECT_EQ(1, map.size());
+    EXPECT_EQ("Bar", map.at("Foo"));
+    emplace(map, "Baz", "Moo");
+    EXPECT_EQ(2, map.size());
+    EXPECT_EQ("Bar", map.at("Foo"));
+    EXPECT_EQ("Moo", map.at("Baz"));
+}
+
+TEST(HeaderMapTests, shouldBeCaseInsensitive) {
+    HeaderMap map;
+    emplace(map, "Foo", "Bar");
+    EXPECT_EQ("Bar", map.at("FOO"));
+    EXPECT_EQ("Bar", map.at("foO"));
+}
+
+TEST(HeaderMapTests, shouldPreserveOriginalCase) {
+    HeaderMap map;
+    emplace(map, "Foo", "Bar");
+    auto it = map.find("Foo");
+    EXPECT_EQ("Foo", it->first);
+}
+
+}
diff --git a/third_party/seasocks/src/test/c/HtmlTests.cpp b/third_party/seasocks/src/test/c/HtmlTests.cpp
new file mode 100644
index 0000000..1df7156
--- /dev/null
+++ b/third_party/seasocks/src/test/c/HtmlTests.cpp
@@ -0,0 +1,74 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "seasocks/util/Html.h"
+
+#include <gmock/gmock.h>
+
+using namespace seasocks;
+using namespace seasocks::html;
+
+TEST(HtmlTests, shouldRenderASimpleDocument) {
+    auto document = html::html(head(title("Hello")), body(h1("A header"), "This is a document"));
+    EXPECT_EQ("<html><head><title>Hello</title></head><body><h1>A header</h1>This is a document</body></html>", document.str());
+}
+
+TEST(HtmlTests, shouldAllowAppending) {
+    auto list = ul();
+    list << li("Element 1") << li("Element 2");
+    EXPECT_EQ("<ul><li>Element 1</li><li>Element 2</li></ul>", list.str());
+}
+
+TEST(HtmlTests, shouldAllowCommaSeparation) {
+    auto list = ul(li("Element 1"), li("Element 2"));
+    EXPECT_EQ("<ul><li>Element 1</li><li>Element 2</li></ul>", list.str());
+}
+
+TEST(HtmlTests, shouldHandleAttributes) {
+    auto elem = span("Some text").clazz("class");
+    EXPECT_EQ("<span class=\"class\">Some text</span>", elem.str());
+}
+
+TEST(HtmlTests, shouldAppendLikeAStreamFromEmpty) {
+    auto elem = empty() << "Text " << 1 << ' ' << 10.23;
+    EXPECT_EQ("Text 1 10.23", elem.str());
+}
+
+TEST(HtmlTests, shouldNotNeedExtraMarkupForTextNodes) {
+    auto elem = text("This ") << text("is") << text(" a test") << ".";
+    EXPECT_EQ("This is a test.", elem.str());
+}
+
+TEST(HtmlTests, shouldWorkWithAnchors) {
+    auto elem = a("http://google.com/?q=badgers", div(span("foo")));
+    EXPECT_EQ("<a href=\"http://google.com/?q=badgers\"><div><span>foo</span></div></a>", elem.str());
+}
+
+TEST(HtmlTests, shouldAddAll) {
+    std::vector<std::string> strings = { "Hi", "Moo", "Foo" };
+    auto list = ul().addAll(strings, [](const std::string& s) { return li(s); });
+    EXPECT_EQ("<ul><li>Hi</li><li>Moo</li><li>Foo</li></ul>", list.str());
+
+}
diff --git a/third_party/seasocks/src/test/c/HybiTests.cpp b/third_party/seasocks/src/test/c/HybiTests.cpp
new file mode 100644
index 0000000..ab270eb
--- /dev/null
+++ b/third_party/seasocks/src/test/c/HybiTests.cpp
@@ -0,0 +1,145 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "internal/HybiAccept.h"
+#include "internal/HybiPacketDecoder.h"
+
+#include "seasocks/IgnoringLogger.h"
+
+#include <gmock/gmock.h>
+
+#include <iostream>
+#include <sstream>
+#include <string.h>
+#include <string>
+
+using namespace seasocks;
+
+static IgnoringLogger ignore;
+
+void testSingleString(
+        HybiPacketDecoder::MessageState expectedState,
+        const char* expectedPayload,
+        const std::vector<uint8_t>& v,
+        uint32_t size = 0) {
+    HybiPacketDecoder decoder(ignore, v);
+    std::vector<uint8_t> decoded;
+    ASSERT_EQ(expectedState, decoder.decodeNextMessage(decoded));
+    ASSERT_EQ(expectedPayload, std::string(reinterpret_cast<const char*>(&decoded[0]), decoded.size()));
+    ASSERT_EQ(HybiPacketDecoder::NoMessage, decoder.decodeNextMessage(decoded));
+    ASSERT_EQ(size ? size : v.size(), decoder.numBytesDecoded());
+}
+
+void testLongString(size_t size, std::vector<uint8_t> v) {
+    for (size_t i = 0; i < size; ++i) {
+        v.push_back('A');
+    }
+    HybiPacketDecoder decoder(ignore, v);
+    std::vector<uint8_t> decoded;
+    ASSERT_EQ(HybiPacketDecoder::TextMessage, decoder.decodeNextMessage(decoded));
+    ASSERT_EQ(size, decoded.size());
+    for (size_t i = 0; i < size; ++i) {
+        ASSERT_EQ('A', decoded[i]);
+    }
+    ASSERT_EQ(HybiPacketDecoder::NoMessage, decoder.decodeNextMessage(decoded));
+    ASSERT_EQ(v.size(), decoder.numBytesDecoded());
+}
+
+TEST(HybiTests, textExamples) {
+    // CF. http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-10 #4.7
+    testSingleString(HybiPacketDecoder::TextMessage, "Hello", {0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f});
+    testSingleString(HybiPacketDecoder::TextMessage, "Hello", {0x81, 0x85, 0x37, 0xfa, 0x21, 0x3d, 0x7f, 0x9f, 0x4d, 0x51, 0x58});
+    testSingleString(HybiPacketDecoder::Ping, "Hello", {0x89, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f});
+}
+
+TEST(HybiTests, withPartialMessageFollowing) {
+    testSingleString(HybiPacketDecoder::TextMessage, "Hello", {0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x81}, 7);
+    testSingleString(HybiPacketDecoder::TextMessage, "Hello", {0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x81, 0x05}, 7);
+    testSingleString(HybiPacketDecoder::TextMessage, "Hello", {0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x81, 0x05, 0x48}, 7);
+    testSingleString(HybiPacketDecoder::TextMessage, "Hello", {0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c}, 7);
+}
+
+TEST(HybiTests, binaryMessage) {
+    std::vector<uint8_t> packet { 0x82, 0x03, 0x00, 0x01, 0x02 };
+    std::vector<uint8_t> expected_body { 0x00, 0x01, 0x02 };
+    HybiPacketDecoder decoder(ignore, packet);
+    std::vector<uint8_t> decoded;
+    ASSERT_EQ(HybiPacketDecoder::BinaryMessage, decoder.decodeNextMessage(decoded));
+    ASSERT_EQ(expected_body, decoded);
+    ASSERT_EQ(HybiPacketDecoder::NoMessage, decoder.decodeNextMessage(decoded));
+    ASSERT_EQ(packet.size(), decoder.numBytesDecoded());
+}
+
+TEST(HybiTests, withTwoMessages) {
+    std::vector<uint8_t> data {
+        0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f,
+        0x81, 0x07, 0x47, 0x6f, 0x6f, 0x64, 0x62, 0x79, 0x65};
+    HybiPacketDecoder decoder(ignore, data);
+    std::vector<uint8_t> decoded;
+    ASSERT_EQ(HybiPacketDecoder::TextMessage, decoder.decodeNextMessage(decoded));
+    ASSERT_EQ("Hello", std::string(reinterpret_cast<const char*>(&decoded[0]), decoded.size()));
+    ASSERT_EQ(HybiPacketDecoder::TextMessage, decoder.decodeNextMessage(decoded));
+    ASSERT_EQ("Goodbye", std::string(reinterpret_cast<const char*>(&decoded[0]), decoded.size()));
+    ASSERT_EQ(HybiPacketDecoder::NoMessage, decoder.decodeNextMessage(decoded));
+    ASSERT_EQ(data.size(), decoder.numBytesDecoded());
+}
+
+TEST(HybiTests, withTwoMessagesOneBeingMaskedd) {
+    std::vector<uint8_t> data {
+        0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f,  // hello
+        0x81, 0x85, 0x37, 0xfa, 0x21, 0x3d, 0x7f, 0x9f, 0x4d, 0x51, 0x58  // also hello
+    };
+    HybiPacketDecoder decoder(ignore, data);
+    std::vector<uint8_t> decoded;
+    ASSERT_EQ(HybiPacketDecoder::TextMessage, decoder.decodeNextMessage(decoded));
+    ASSERT_EQ("Hello", std::string(reinterpret_cast<const char*>(&decoded[0]), decoded.size()));
+    ASSERT_EQ(HybiPacketDecoder::TextMessage, decoder.decodeNextMessage(decoded));
+    ASSERT_EQ("Hello", std::string(reinterpret_cast<const char*>(&decoded[0]), decoded.size()));
+    ASSERT_EQ(HybiPacketDecoder::NoMessage, decoder.decodeNextMessage(decoded));
+    ASSERT_EQ(data.size(), decoder.numBytesDecoded());
+}
+
+TEST(HybiTests, regressionBug) {
+    // top bit set of second byte of message used to trigger a MASK decode of the remainder
+    std::vector<uint8_t> data {
+        0x82, 0x05, 0x80, 0x81, 0x82, 0x83, 0x84  
+    };
+    std::vector<uint8_t> expected_body { 0x80, 0x81, 0x82, 0x83, 0x84 };
+    HybiPacketDecoder decoder(ignore, data);
+    std::vector<uint8_t> decoded;
+    ASSERT_EQ(HybiPacketDecoder::BinaryMessage, decoder.decodeNextMessage(decoded));
+    ASSERT_EQ(expected_body, decoded);
+    ASSERT_EQ(data.size(), decoder.numBytesDecoded());
+}
+
+TEST(HybiTests, longStringExamples) {
+    // These are the binary examples, but cast as strings.
+    testLongString(256, {0x81, 0x7E, 0x01, 0x00});
+    testLongString(65536, {0x81, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00});
+}
+
+TEST(HybiTests, accept) {
+    ASSERT_EQ("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=", getAcceptKey("dGhlIHNhbXBsZSBub25jZQ=="));
+}
diff --git a/third_party/seasocks/src/test/c/JsonTests.cpp b/third_party/seasocks/src/test/c/JsonTests.cpp
new file mode 100644
index 0000000..b284b50
--- /dev/null
+++ b/third_party/seasocks/src/test/c/JsonTests.cpp
@@ -0,0 +1,131 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "seasocks/util/Json.h"
+
+#include <gmock/gmock.h>
+#include <ostream>
+#include <map>
+#include <unordered_map>
+
+using namespace testing;
+using namespace seasocks;
+
+namespace {
+
+TEST(JsonTests, shouldHandleMaps) {
+    EXPECT_EQ("{\"monkey\":12}", makeMap("monkey", 12));
+}
+
+TEST(JsonTests, shouldHandleQuotedStrings) {
+    EXPECT_EQ("{\"key\":\"I have \\\"quotes\\\"\"}",
+            makeMap("key", "I have \"quotes\""));
+}
+
+TEST(JsonTests, shouldHandleNewLinesInStrings) {
+    std::stringstream str;
+    jsonToStream(str, "I have\nnew\rlines");
+    EXPECT_EQ("\"I have\\nnew\\rlines\"", str.str());
+}
+
+TEST(JsonTests, shouldHandleCrazyChars) {
+    std::stringstream str;
+    jsonToStream(str, "\x01\x02\x1f");
+    EXPECT_EQ("\"\\u0001\\u0002\\u001f\"", str.str());
+}
+
+TEST(JsonTests, shouldHandleDate) {
+    std::stringstream str;
+    jsonToStream(str, EpochTimeAsLocal(209001600));
+    EXPECT_EQ("new Date(209001600000).toLocaleString()", str.str());
+}
+
+struct Object {
+    void jsonToStream(std::ostream &ostr) const {
+        ostr << makeMap("object", true);
+    }
+    // Clang is pernickity about this. We don't want use this function
+    // but it's here to catch errors where we accidentally use it instead of the
+    // jsonToStream.
+    friend std::ostream &operator << (std::ostream &o, const Object &ob) {
+        return o << "Not this one";
+    }
+};
+
+struct Object2 {
+    friend std::ostream &operator << (std::ostream &o, const Object2 &ob) {
+        return o << "This is object 2";
+    }
+};
+
+static_assert(is_streamable<Object2>::value, "Should be streamable");
+
+TEST(JsonTests, shouldHandleCustomObjects) {
+    EXPECT_EQ(R"({"obj":{"object":true}})", makeMap("obj", Object()));
+    Object o;
+    EXPECT_EQ(R"({"obj":{"object":true}})", makeMap("obj", o));
+    EXPECT_EQ(R"({"obj":"This is object 2"})", makeMap("obj", Object2()));
+    Object2 o2;
+    EXPECT_EQ(R"({"obj":"This is object 2"})", makeMap("obj", o2));
+    // Putting a clang-specific pragma to thwart the unused warning in Object
+    // upsets GCC...so we just put a test for this to ensure it's used.
+    std::ostringstream ost;
+    ost << Object();
+    EXPECT_EQ("Not this one", ost.str()); // See comment
+}
+
+TEST(JsonTests, to_json) {
+    EXPECT_EQ("1", to_json(1));
+    EXPECT_EQ("3.14", to_json(3.14));
+    EXPECT_EQ("\"hello\"", to_json("hello"));
+    EXPECT_EQ(R"({"object":true})", to_json(Object()));
+    EXPECT_EQ(R"("This is object 2")", to_json(Object2()));
+}
+TEST(JsonTests, handlesArrays) {
+    EXPECT_EQ(R"([])", makeArray());
+    EXPECT_EQ(R"([1])", makeArray(1));
+    EXPECT_EQ(R"([1,2,3])", makeArray(1, 2, 3));
+    EXPECT_EQ(R"([1,2,3])", makeArray({1, 2, 3}));
+    EXPECT_EQ(R"(["abc"])", makeArray("abc"));
+    EXPECT_EQ(R"(["a","b","c"])", makeArray("a", "b", "c"));
+    EXPECT_EQ(R"(["a","b","c"])", makeArray({"a", "b", "c"}));
+    std::vector<JsonnedString> strs = { to_json(false), to_json(true) };
+    EXPECT_EQ(R"([false,true])", makeArrayFromContainer(strs));
+}
+
+TEST(JsonTests, handlesMaps) {
+    std::map<std::string, JsonnedString> ordMap;
+    ordMap["hello"] = to_json(true);
+    ordMap["goodbye"] = to_json(false);
+    EXPECT_EQ(R"({"goodbye":false,"hello":true})", makeMapFromContainer(ordMap));
+    std::map<std::string, JsonnedString> unordMap;
+    unordMap["hello"] = to_json(true);
+    unordMap["goodbye"] = to_json(false);
+    EXPECT_THAT(makeMapFromContainer(unordMap), AnyOf(
+            Eq(R"({"goodbye":false,"hello":true})"),
+            Eq(R"({"hello":true,"goodbye":false})")));
+}
+
+}
diff --git a/third_party/seasocks/src/test/c/MockServerImpl.h b/third_party/seasocks/src/test/c/MockServerImpl.h
new file mode 100644
index 0000000..42546b5
--- /dev/null
+++ b/third_party/seasocks/src/test/c/MockServerImpl.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include "seasocks/ServerImpl.h"
+
+#include <gmock/gmock.h>
+
+namespace seasocks {
+
+class MockServerImpl : public ServerImpl {
+public:
+    virtual ~MockServerImpl() {}
+
+    MOCK_METHOD1(remove, void(Connection* connection));
+    MOCK_METHOD1(subscribeToWriteEvents, bool(Connection* connection));
+    MOCK_METHOD1(unsubscribeFromWriteEvents, bool(Connection* connection));
+    MOCK_CONST_METHOD0(getStaticPath, const std::string&());
+    MOCK_CONST_METHOD1(getWebSocketHandler, std::shared_ptr<WebSocket::Handler>(const char *));
+    MOCK_CONST_METHOD1(isCrossOriginAllowed, bool(const std::string&));
+    MOCK_METHOD1(handle, std::shared_ptr<Response>(const Request &));
+    MOCK_CONST_METHOD0(getStatsDocument, std::string());
+    MOCK_CONST_METHOD0(checkThread, void());
+};
+
+}
diff --git a/third_party/seasocks/src/test/c/test_main.cpp b/third_party/seasocks/src/test/c/test_main.cpp
new file mode 100644
index 0000000..11624ac
--- /dev/null
+++ b/third_party/seasocks/src/test/c/test_main.cpp
@@ -0,0 +1,31 @@
+// Copyright (c) 2013, Matt Godbolt
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+// 
+// Redistributions of source code must retain the above copyright notice, this 
+// list of conditions and the following disclaimer.
+// 
+// Redistributions in binary form must reproduce the above copyright notice, 
+// this list of conditions and the following disclaimer in the documentation 
+// and/or other materials provided with the distribution.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include <gmock/gmock.h>
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}
diff --git a/third_party/seasocks/src/ws_test_web/app.js b/third_party/seasocks/src/ws_test_web/app.js
new file mode 100644
index 0000000..d6aa266
--- /dev/null
+++ b/third_party/seasocks/src/ws_test_web/app.js
@@ -0,0 +1,33 @@
+var ws;
+
+$(function() {
+    ws = new WebSocket('ws://' + document.location.host + '/ws');
+    ws.onopen = function() {
+        console.log('onopen');
+    };
+    ws.onclose = function() {
+        $('#message').text('Lost connection.');
+        console.log('onclose');
+    };
+    ws.onmessage = function(message) {
+        console.log("got '" + message.data + "'");
+        eval(message.data);
+    };
+    ws.onerror = function(error) {
+        console.log('onerror ' + error);
+        console.log(error);
+    };
+    $('#count').click(function() {
+    	ws.send($('#count').val());
+    });
+    $('#close').click(function() {
+      ws.send('close');
+    });
+    $('#die').click(function() {
+      ws.send('die');
+    });
+});
+
+set = function(value) {
+	$('#count').val(value)
+}
diff --git a/third_party/seasocks/src/ws_test_web/index.html b/third_party/seasocks/src/ws_test_web/index.html
new file mode 100644
index 0000000..455b827
--- /dev/null
+++ b/third_party/seasocks/src/ws_test_web/index.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Hello, world</title>
+    <script src='lib/jquery-1.4.4.js'></script>
+    <script src='app.js'></script>
+  </head>
+  <body>
+	<input id="count" type="button" value="..."></input>
+	<input id="close" type="button" value="Close"></input>
+	<input id="die" type="button" value="Die"></input>
+  </body>
+</html>
+
diff --git a/third_party/seasocks/src/ws_test_web/lib/jquery-1.4.4.js b/third_party/seasocks/src/ws_test_web/lib/jquery-1.4.4.js
new file mode 100644
index 0000000..a4f1145
--- /dev/null
+++ b/third_party/seasocks/src/ws_test_web/lib/jquery-1.4.4.js
@@ -0,0 +1,7179 @@
+/*!
+ * jQuery JavaScript Library v1.4.4
+ * http://jquery.com/
+ *
+ * Copyright 2010, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2010, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Thu Nov 11 19:04:53 2010 -0500
+ */
+(function( window, undefined ) {
+
+// Use the correct document accordingly with window argument (sandbox)
+var document = window.document;
+var jQuery = (function() {
+
+// Define a local copy of jQuery
+var jQuery = function( selector, context ) {
+		// The jQuery object is actually just the init constructor 'enhanced'
+		return new jQuery.fn.init( selector, context );
+	},
+
+	// Map over jQuery in case of overwrite
+	_jQuery = window.jQuery,
+
+	// Map over the $ in case of overwrite
+	_$ = window.$,
+
+	// A central reference to the root jQuery(document)
+	rootjQuery,
+
+	// A simple way to check for HTML strings or ID strings
+	// (both of which we optimize for)
+	quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,
+
+	// Is it a simple selector
+	isSimple = /^.[^:#\[\.,]*$/,
+
+	// Check if a string has a non-whitespace character in it
+	rnotwhite = /\S/,
+	rwhite = /\s/,
+
+	// Used for trimming whitespace
+	trimLeft = /^\s+/,
+	trimRight = /\s+$/,
+
+	// Check for non-word characters
+	rnonword = /\W/,
+
+	// Check for digits
+	rdigit = /\d/,
+
+	// Match a standalone tag
+	rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
+
+	// JSON RegExp
+	rvalidchars = /^[\],:{}\s]*$/,
+	rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
+	rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
+	rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
+
+	// Useragent RegExp
+	rwebkit = /(webkit)[ \/]([\w.]+)/,
+	ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
+	rmsie = /(msie) ([\w.]+)/,
+	rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
+
+	// Keep a UserAgent string for use with jQuery.browser
+	userAgent = navigator.userAgent,
+
+	// For matching the engine and version of the browser
+	browserMatch,
+	
+	// Has the ready events already been bound?
+	readyBound = false,
+	
+	// The functions to execute on DOM ready
+	readyList = [],
+
+	// The ready event handler
+	DOMContentLoaded,
+
+	// Save a reference to some core methods
+	toString = Object.prototype.toString,
+	hasOwn = Object.prototype.hasOwnProperty,
+	push = Array.prototype.push,
+	slice = Array.prototype.slice,
+	trim = String.prototype.trim,
+	indexOf = Array.prototype.indexOf,
+	
+	// [[Class]] -> type pairs
+	class2type = {};
+
+jQuery.fn = jQuery.prototype = {
+	init: function( selector, context ) {
+		var match, elem, ret, doc;
+
+		// Handle $(""), $(null), or $(undefined)
+		if ( !selector ) {
+			return this;
+		}
+
+		// Handle $(DOMElement)
+		if ( selector.nodeType ) {
+			this.context = this[0] = selector;
+			this.length = 1;
+			return this;
+		}
+		
+		// The body element only exists once, optimize finding it
+		if ( selector === "body" && !context && document.body ) {
+			this.context = document;
+			this[0] = document.body;
+			this.selector = "body";
+			this.length = 1;
+			return this;
+		}
+
+		// Handle HTML strings
+		if ( typeof selector === "string" ) {
+			// Are we dealing with HTML string or an ID?
+			match = quickExpr.exec( selector );
+
+			// Verify a match, and that no context was specified for #id
+			if ( match && (match[1] || !context) ) {
+
+				// HANDLE: $(html) -> $(array)
+				if ( match[1] ) {
+					doc = (context ? context.ownerDocument || context : document);
+
+					// If a single string is passed in and it's a single tag
+					// just do a createElement and skip the rest
+					ret = rsingleTag.exec( selector );
+
+					if ( ret ) {
+						if ( jQuery.isPlainObject( context ) ) {
+							selector = [ document.createElement( ret[1] ) ];
+							jQuery.fn.attr.call( selector, context, true );
+
+						} else {
+							selector = [ doc.createElement( ret[1] ) ];
+						}
+
+					} else {
+						ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
+						selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes;
+					}
+					
+					return jQuery.merge( this, selector );
+					
+				// HANDLE: $("#id")
+				} else {
+					elem = document.getElementById( match[2] );
+
+					// Check parentNode to catch when Blackberry 4.6 returns
+					// nodes that are no longer in the document #6963
+					if ( elem && elem.parentNode ) {
+						// Handle the case where IE and Opera return items
+						// by name instead of ID
+						if ( elem.id !== match[2] ) {
+							return rootjQuery.find( selector );
+						}
+
+						// Otherwise, we inject the element directly into the jQuery object
+						this.length = 1;
+						this[0] = elem;
+					}
+
+					this.context = document;
+					this.selector = selector;
+					return this;
+				}
+
+			// HANDLE: $("TAG")
+			} else if ( !context && !rnonword.test( selector ) ) {
+				this.selector = selector;
+				this.context = document;
+				selector = document.getElementsByTagName( selector );
+				return jQuery.merge( this, selector );
+
+			// HANDLE: $(expr, $(...))
+			} else if ( !context || context.jquery ) {
+				return (context || rootjQuery).find( selector );
+
+			// HANDLE: $(expr, context)
+			// (which is just equivalent to: $(context).find(expr)
+			} else {
+				return jQuery( context ).find( selector );
+			}
+
+		// HANDLE: $(function)
+		// Shortcut for document ready
+		} else if ( jQuery.isFunction( selector ) ) {
+			return rootjQuery.ready( selector );
+		}
+
+		if (selector.selector !== undefined) {
+			this.selector = selector.selector;
+			this.context = selector.context;
+		}
+
+		return jQuery.makeArray( selector, this );
+	},
+
+	// Start with an empty selector
+	selector: "",
+
+	// The current version of jQuery being used
+	jquery: "1.4.4",
+
+	// The default length of a jQuery object is 0
+	length: 0,
+
+	// The number of elements contained in the matched element set
+	size: function() {
+		return this.length;
+	},
+
+	toArray: function() {
+		return slice.call( this, 0 );
+	},
+
+	// Get the Nth element in the matched element set OR
+	// Get the whole matched element set as a clean array
+	get: function( num ) {
+		return num == null ?
+
+			// Return a 'clean' array
+			this.toArray() :
+
+			// Return just the object
+			( num < 0 ? this.slice(num)[ 0 ] : this[ num ] );
+	},
+
+	// Take an array of elements and push it onto the stack
+	// (returning the new matched element set)
+	pushStack: function( elems, name, selector ) {
+		// Build a new jQuery matched element set
+		var ret = jQuery();
+
+		if ( jQuery.isArray( elems ) ) {
+			push.apply( ret, elems );
+		
+		} else {
+			jQuery.merge( ret, elems );
+		}
+
+		// Add the old object onto the stack (as a reference)
+		ret.prevObject = this;
+
+		ret.context = this.context;
+
+		if ( name === "find" ) {
+			ret.selector = this.selector + (this.selector ? " " : "") + selector;
+		} else if ( name ) {
+			ret.selector = this.selector + "." + name + "(" + selector + ")";
+		}
+
+		// Return the newly-formed element set
+		return ret;
+	},
+
+	// Execute a callback for every element in the matched set.
+	// (You can seed the arguments with an array of args, but this is
+	// only used internally.)
+	each: function( callback, args ) {
+		return jQuery.each( this, callback, args );
+	},
+	
+	ready: function( fn ) {
+		// Attach the listeners
+		jQuery.bindReady();
+
+		// If the DOM is already ready
+		if ( jQuery.isReady ) {
+			// Execute the function immediately
+			fn.call( document, jQuery );
+
+		// Otherwise, remember the function for later
+		} else if ( readyList ) {
+			// Add the function to the wait list
+			readyList.push( fn );
+		}
+
+		return this;
+	},
+	
+	eq: function( i ) {
+		return i === -1 ?
+			this.slice( i ) :
+			this.slice( i, +i + 1 );
+	},
+
+	first: function() {
+		return this.eq( 0 );
+	},
+
+	last: function() {
+		return this.eq( -1 );
+	},
+
+	slice: function() {
+		return this.pushStack( slice.apply( this, arguments ),
+			"slice", slice.call(arguments).join(",") );
+	},
+
+	map: function( callback ) {
+		return this.pushStack( jQuery.map(this, function( elem, i ) {
+			return callback.call( elem, i, elem );
+		}));
+	},
+	
+	end: function() {
+		return this.prevObject || jQuery(null);
+	},
+
+	// For internal use only.
+	// Behaves like an Array's method, not like a jQuery method.
+	push: push,
+	sort: [].sort,
+	splice: [].splice
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+jQuery.extend = jQuery.fn.extend = function() {
+	 var options, name, src, copy, copyIsArray, clone,
+		target = arguments[0] || {},
+		i = 1,
+		length = arguments.length,
+		deep = false;
+
+	// Handle a deep copy situation
+	if ( typeof target === "boolean" ) {
+		deep = target;
+		target = arguments[1] || {};
+		// skip the boolean and the target
+		i = 2;
+	}
+
+	// Handle case when target is a string or something (possible in deep copy)
+	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+		target = {};
+	}
+
+	// extend jQuery itself if only one argument is passed
+	if ( length === i ) {
+		target = this;
+		--i;
+	}
+
+	for ( ; i < length; i++ ) {
+		// Only deal with non-null/undefined values
+		if ( (options = arguments[ i ]) != null ) {
+			// Extend the base object
+			for ( name in options ) {
+				src = target[ name ];
+				copy = options[ name ];
+
+				// Prevent never-ending loop
+				if ( target === copy ) {
+					continue;
+				}
+
+				// Recurse if we're merging plain objects or arrays
+				if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+					if ( copyIsArray ) {
+						copyIsArray = false;
+						clone = src && jQuery.isArray(src) ? src : [];
+
+					} else {
+						clone = src && jQuery.isPlainObject(src) ? src : {};
+					}
+
+					// Never move original objects, clone them
+					target[ name ] = jQuery.extend( deep, clone, copy );
+
+				// Don't bring in undefined values
+				} else if ( copy !== undefined ) {
+					target[ name ] = copy;
+				}
+			}
+		}
+	}
+
+	// Return the modified object
+	return target;
+};
+
+jQuery.extend({
+	noConflict: function( deep ) {
+		window.$ = _$;
+
+		if ( deep ) {
+			window.jQuery = _jQuery;
+		}
+
+		return jQuery;
+	},
+	
+	// Is the DOM ready to be used? Set to true once it occurs.
+	isReady: false,
+
+	// A counter to track how many items to wait for before
+	// the ready event fires. See #6781
+	readyWait: 1,
+	
+	// Handle when the DOM is ready
+	ready: function( wait ) {
+		// A third-party is pushing the ready event forwards
+		if ( wait === true ) {
+			jQuery.readyWait--;
+		}
+
+		// Make sure that the DOM is not already loaded
+		if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) {
+			// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+			if ( !document.body ) {
+				return setTimeout( jQuery.ready, 1 );
+			}
+
+			// Remember that the DOM is ready
+			jQuery.isReady = true;
+
+			// If a normal DOM Ready event fired, decrement, and wait if need be
+			if ( wait !== true && --jQuery.readyWait > 0 ) {
+				return;
+			}
+
+			// If there are functions bound, to execute
+			if ( readyList ) {
+				// Execute all of them
+				var fn,
+					i = 0,
+					ready = readyList;
+
+				// Reset the list of functions
+				readyList = null;
+
+				while ( (fn = ready[ i++ ]) ) {
+					fn.call( document, jQuery );
+				}
+
+				// Trigger any bound ready events
+				if ( jQuery.fn.trigger ) {
+					jQuery( document ).trigger( "ready" ).unbind( "ready" );
+				}
+			}
+		}
+	},
+	
+	bindReady: function() {
+		if ( readyBound ) {
+			return;
+		}
+
+		readyBound = true;
+
+		// Catch cases where $(document).ready() is called after the
+		// browser event has already occurred.
+		if ( document.readyState === "complete" ) {
+			// Handle it asynchronously to allow scripts the opportunity to delay ready
+			return setTimeout( jQuery.ready, 1 );
+		}
+
+		// Mozilla, Opera and webkit nightlies currently support this event
+		if ( document.addEventListener ) {
+			// Use the handy event callback
+			document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+			
+			// A fallback to window.onload, that will always work
+			window.addEventListener( "load", jQuery.ready, false );
+
+		// If IE event model is used
+		} else if ( document.attachEvent ) {
+			// ensure firing before onload,
+			// maybe late but safe also for iframes
+			document.attachEvent("onreadystatechange", DOMContentLoaded);
+			
+			// A fallback to window.onload, that will always work
+			window.attachEvent( "onload", jQuery.ready );
+
+			// If IE and not a frame
+			// continually check to see if the document is ready
+			var toplevel = false;
+
+			try {
+				toplevel = window.frameElement == null;
+			} catch(e) {}
+
+			if ( document.documentElement.doScroll && toplevel ) {
+				doScrollCheck();
+			}
+		}
+	},
+
+	// See test/unit/core.js for details concerning isFunction.
+	// Since version 1.3, DOM methods and functions like alert
+	// aren't supported. They return false on IE (#2968).
+	isFunction: function( obj ) {
+		return jQuery.type(obj) === "function";
+	},
+
+	isArray: Array.isArray || function( obj ) {
+		return jQuery.type(obj) === "array";
+	},
+
+	// A crude way of determining if an object is a window
+	isWindow: function( obj ) {
+		return obj && typeof obj === "object" && "setInterval" in obj;
+	},
+
+	isNaN: function( obj ) {
+		return obj == null || !rdigit.test( obj ) || isNaN( obj );
+	},
+
+	type: function( obj ) {
+		return obj == null ?
+			String( obj ) :
+			class2type[ toString.call(obj) ] || "object";
+	},
+
+	isPlainObject: function( obj ) {
+		// Must be an Object.
+		// Because of IE, we also have to check the presence of the constructor property.
+		// Make sure that DOM nodes and window objects don't pass through, as well
+		if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+			return false;
+		}
+		
+		// Not own constructor property must be Object
+		if ( obj.constructor &&
+			!hasOwn.call(obj, "constructor") &&
+			!hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+			return false;
+		}
+		
+		// Own properties are enumerated firstly, so to speed up,
+		// if last one is own, then all properties are own.
+	
+		var key;
+		for ( key in obj ) {}
+		
+		return key === undefined || hasOwn.call( obj, key );
+	},
+
+	isEmptyObject: function( obj ) {
+		for ( var name in obj ) {
+			return false;
+		}
+		return true;
+	},
+	
+	error: function( msg ) {
+		throw msg;
+	},
+	
+	parseJSON: function( data ) {
+		if ( typeof data !== "string" || !data ) {
+			return null;
+		}
+
+		// Make sure leading/trailing whitespace is removed (IE can't handle it)
+		data = jQuery.trim( data );
+		
+		// Make sure the incoming data is actual JSON
+		// Logic borrowed from http://json.org/json2.js
+		if ( rvalidchars.test(data.replace(rvalidescape, "@")
+			.replace(rvalidtokens, "]")
+			.replace(rvalidbraces, "")) ) {
+
+			// Try to use the native JSON parser first
+			return window.JSON && window.JSON.parse ?
+				window.JSON.parse( data ) :
+				(new Function("return " + data))();
+
+		} else {
+			jQuery.error( "Invalid JSON: " + data );
+		}
+	},
+
+	noop: function() {},
+
+	// Evalulates a script in a global context
+	globalEval: function( data ) {
+		if ( data && rnotwhite.test(data) ) {
+			// Inspired by code by Andrea Giammarchi
+			// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
+			var head = document.getElementsByTagName("head")[0] || document.documentElement,
+				script = document.createElement("script");
+
+			script.type = "text/javascript";
+
+			if ( jQuery.support.scriptEval ) {
+				script.appendChild( document.createTextNode( data ) );
+			} else {
+				script.text = data;
+			}
+
+			// Use insertBefore instead of appendChild to circumvent an IE6 bug.
+			// This arises when a base node is used (#2709).
+			head.insertBefore( script, head.firstChild );
+			head.removeChild( script );
+		}
+	},
+
+	nodeName: function( elem, name ) {
+		return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
+	},
+
+	// args is for internal usage only
+	each: function( object, callback, args ) {
+		var name, i = 0,
+			length = object.length,
+			isObj = length === undefined || jQuery.isFunction(object);
+
+		if ( args ) {
+			if ( isObj ) {
+				for ( name in object ) {
+					if ( callback.apply( object[ name ], args ) === false ) {
+						break;
+					}
+				}
+			} else {
+				for ( ; i < length; ) {
+					if ( callback.apply( object[ i++ ], args ) === false ) {
+						break;
+					}
+				}
+			}
+
+		// A special, fast, case for the most common use of each
+		} else {
+			if ( isObj ) {
+				for ( name in object ) {
+					if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
+						break;
+					}
+				}
+			} else {
+				for ( var value = object[0];
+					i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {}
+			}
+		}
+
+		return object;
+	},
+
+	// Use native String.trim function wherever possible
+	trim: trim ?
+		function( text ) {
+			return text == null ?
+				"" :
+				trim.call( text );
+		} :
+
+		// Otherwise use our own trimming functionality
+		function( text ) {
+			return text == null ?
+				"" :
+				text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
+		},
+
+	// results is for internal usage only
+	makeArray: function( array, results ) {
+		var ret = results || [];
+
+		if ( array != null ) {
+			// The window, strings (and functions) also have 'length'
+			// The extra typeof function check is to prevent crashes
+			// in Safari 2 (See: #3039)
+			// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
+			var type = jQuery.type(array);
+
+			if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
+				push.call( ret, array );
+			} else {
+				jQuery.merge( ret, array );
+			}
+		}
+
+		return ret;
+	},
+
+	inArray: function( elem, array ) {
+		if ( array.indexOf ) {
+			return array.indexOf( elem );
+		}
+
+		for ( var i = 0, length = array.length; i < length; i++ ) {
+			if ( array[ i ] === elem ) {
+				return i;
+			}
+		}
+
+		return -1;
+	},
+
+	merge: function( first, second ) {
+		var i = first.length,
+			j = 0;
+
+		if ( typeof second.length === "number" ) {
+			for ( var l = second.length; j < l; j++ ) {
+				first[ i++ ] = second[ j ];
+			}
+		
+		} else {
+			while ( second[j] !== undefined ) {
+				first[ i++ ] = second[ j++ ];
+			}
+		}
+
+		first.length = i;
+
+		return first;
+	},
+
+	grep: function( elems, callback, inv ) {
+		var ret = [], retVal;
+		inv = !!inv;
+
+		// Go through the array, only saving the items
+		// that pass the validator function
+		for ( var i = 0, length = elems.length; i < length; i++ ) {
+			retVal = !!callback( elems[ i ], i );
+			if ( inv !== retVal ) {
+				ret.push( elems[ i ] );
+			}
+		}
+
+		return ret;
+	},
+
+	// arg is for internal usage only
+	map: function( elems, callback, arg ) {
+		var ret = [], value;
+
+		// Go through the array, translating each of the items to their
+		// new value (or values).
+		for ( var i = 0, length = elems.length; i < length; i++ ) {
+			value = callback( elems[ i ], i, arg );
+
+			if ( value != null ) {
+				ret[ ret.length ] = value;
+			}
+		}
+
+		return ret.concat.apply( [], ret );
+	},
+
+	// A global GUID counter for objects
+	guid: 1,
+
+	proxy: function( fn, proxy, thisObject ) {
+		if ( arguments.length === 2 ) {
+			if ( typeof proxy === "string" ) {
+				thisObject = fn;
+				fn = thisObject[ proxy ];
+				proxy = undefined;
+
+			} else if ( proxy && !jQuery.isFunction( proxy ) ) {
+				thisObject = proxy;
+				proxy = undefined;
+			}
+		}
+
+		if ( !proxy && fn ) {
+			proxy = function() {
+				return fn.apply( thisObject || this, arguments );
+			};
+		}
+
+		// Set the guid of unique handler to the same of original handler, so it can be removed
+		if ( fn ) {
+			proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
+		}
+
+		// So proxy can be declared as an argument
+		return proxy;
+	},
+
+	// Mutifunctional method to get and set values to a collection
+	// The value/s can be optionally by executed if its a function
+	access: function( elems, key, value, exec, fn, pass ) {
+		var length = elems.length;
+	
+		// Setting many attributes
+		if ( typeof key === "object" ) {
+			for ( var k in key ) {
+				jQuery.access( elems, k, key[k], exec, fn, value );
+			}
+			return elems;
+		}
+	
+		// Setting one attribute
+		if ( value !== undefined ) {
+			// Optionally, function values get executed if exec is true
+			exec = !pass && exec && jQuery.isFunction(value);
+		
+			for ( var i = 0; i < length; i++ ) {
+				fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
+			}
+		
+			return elems;
+		}
+	
+		// Getting an attribute
+		return length ? fn( elems[0], key ) : undefined;
+	},
+
+	now: function() {
+		return (new Date()).getTime();
+	},
+
+	// Use of jQuery.browser is frowned upon.
+	// More details: http://docs.jquery.com/Utilities/jQuery.browser
+	uaMatch: function( ua ) {
+		ua = ua.toLowerCase();
+
+		var match = rwebkit.exec( ua ) ||
+			ropera.exec( ua ) ||
+			rmsie.exec( ua ) ||
+			ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
+			[];
+
+		return { browser: match[1] || "", version: match[2] || "0" };
+	},
+
+	browser: {}
+});
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
+	class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+browserMatch = jQuery.uaMatch( userAgent );
+if ( browserMatch.browser ) {
+	jQuery.browser[ browserMatch.browser ] = true;
+	jQuery.browser.version = browserMatch.version;
+}
+
+// Deprecated, use jQuery.browser.webkit instead
+if ( jQuery.browser.webkit ) {
+	jQuery.browser.safari = true;
+}
+
+if ( indexOf ) {
+	jQuery.inArray = function( elem, array ) {
+		return indexOf.call( array, elem );
+	};
+}
+
+// Verify that \s matches non-breaking spaces
+// (IE fails on this test)
+if ( !rwhite.test( "\xA0" ) ) {
+	trimLeft = /^[\s\xA0]+/;
+	trimRight = /[\s\xA0]+$/;
+}
+
+// All jQuery objects should point back to these
+rootjQuery = jQuery(document);
+
+// Cleanup functions for the document ready method
+if ( document.addEventListener ) {
+	DOMContentLoaded = function() {
+		document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+		jQuery.ready();
+	};
+
+} else if ( document.attachEvent ) {
+	DOMContentLoaded = function() {
+		// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+		if ( document.readyState === "complete" ) {
+			document.detachEvent( "onreadystatechange", DOMContentLoaded );
+			jQuery.ready();
+		}
+	};
+}
+
+// The DOM ready check for Internet Explorer
+function doScrollCheck() {
+	if ( jQuery.isReady ) {
+		return;
+	}
+
+	try {
+		// If IE is used, use the trick by Diego Perini
+		// http://javascript.nwbox.com/IEContentLoaded/
+		document.documentElement.doScroll("left");
+	} catch(e) {
+		setTimeout( doScrollCheck, 1 );
+		return;
+	}
+
+	// and execute any waiting functions
+	jQuery.ready();
+}
+
+// Expose jQuery to the global object
+return (window.jQuery = window.$ = jQuery);
+
+})();
+
+
+(function() {
+
+	jQuery.support = {};
+
+	var root = document.documentElement,
+		script = document.createElement("script"),
+		div = document.createElement("div"),
+		id = "script" + jQuery.now();
+
+	div.style.display = "none";
+	div.innerHTML = "   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
+
+	var all = div.getElementsByTagName("*"),
+		a = div.getElementsByTagName("a")[0],
+		select = document.createElement("select"),
+		opt = select.appendChild( document.createElement("option") );
+
+	// Can't get basic test support
+	if ( !all || !all.length || !a ) {
+		return;
+	}
+
+	jQuery.support = {
+		// IE strips leading whitespace when .innerHTML is used
+		leadingWhitespace: div.firstChild.nodeType === 3,
+
+		// Make sure that tbody elements aren't automatically inserted
+		// IE will insert them into empty tables
+		tbody: !div.getElementsByTagName("tbody").length,
+
+		// Make sure that link elements get serialized correctly by innerHTML
+		// This requires a wrapper element in IE
+		htmlSerialize: !!div.getElementsByTagName("link").length,
+
+		// Get the style information from getAttribute
+		// (IE uses .cssText insted)
+		style: /red/.test( a.getAttribute("style") ),
+
+		// Make sure that URLs aren't manipulated
+		// (IE normalizes it by default)
+		hrefNormalized: a.getAttribute("href") === "/a",
+
+		// Make sure that element opacity exists
+		// (IE uses filter instead)
+		// Use a regex to work around a WebKit issue. See #5145
+		opacity: /^0.55$/.test( a.style.opacity ),
+
+		// Verify style float existence
+		// (IE uses styleFloat instead of cssFloat)
+		cssFloat: !!a.style.cssFloat,
+
+		// Make sure that if no value is specified for a checkbox
+		// that it defaults to "on".
+		// (WebKit defaults to "" instead)
+		checkOn: div.getElementsByTagName("input")[0].value === "on",
+
+		// Make sure that a selected-by-default option has a working selected property.
+		// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+		optSelected: opt.selected,
+
+		// Will be defined later
+		deleteExpando: true,
+		optDisabled: false,
+		checkClone: false,
+		scriptEval: false,
+		noCloneEvent: true,
+		boxModel: null,
+		inlineBlockNeedsLayout: false,
+		shrinkWrapBlocks: false,
+		reliableHiddenOffsets: true
+	};
+
+	// Make sure that the options inside disabled selects aren't marked as disabled
+	// (WebKit marks them as diabled)
+	select.disabled = true;
+	jQuery.support.optDisabled = !opt.disabled;
+
+	script.type = "text/javascript";
+	try {
+		script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
+	} catch(e) {}
+
+	root.insertBefore( script, root.firstChild );
+
+	// Make sure that the execution of code works by injecting a script
+	// tag with appendChild/createTextNode
+	// (IE doesn't support this, fails, and uses .text instead)
+	if ( window[ id ] ) {
+		jQuery.support.scriptEval = true;
+		delete window[ id ];
+	}
+
+	// Test to see if it's possible to delete an expando from an element
+	// Fails in Internet Explorer
+	try {
+		delete script.test;
+
+	} catch(e) {
+		jQuery.support.deleteExpando = false;
+	}
+
+	root.removeChild( script );
+
+	if ( div.attachEvent && div.fireEvent ) {
+		div.attachEvent("onclick", function click() {
+			// Cloning a node shouldn't copy over any
+			// bound event handlers (IE does this)
+			jQuery.support.noCloneEvent = false;
+			div.detachEvent("onclick", click);
+		});
+		div.cloneNode(true).fireEvent("onclick");
+	}
+
+	div = document.createElement("div");
+	div.innerHTML = "<input type='radio' name='radiotest' checked='checked'/>";
+
+	var fragment = document.createDocumentFragment();
+	fragment.appendChild( div.firstChild );
+
+	// WebKit doesn't clone checked state correctly in fragments
+	jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked;
+
+	// Figure out if the W3C box model works as expected
+	// document.body must exist before we can do this
+	jQuery(function() {
+		var div = document.createElement("div");
+		div.style.width = div.style.paddingLeft = "1px";
+
+		document.body.appendChild( div );
+		jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
+
+		if ( "zoom" in div.style ) {
+			// Check if natively block-level elements act like inline-block
+			// elements when setting their display to 'inline' and giving
+			// them layout
+			// (IE < 8 does this)
+			div.style.display = "inline";
+			div.style.zoom = 1;
+			jQuery.support.inlineBlockNeedsLayout = div.offsetWidth === 2;
+
+			// Check if elements with layout shrink-wrap their children
+			// (IE 6 does this)
+			div.style.display = "";
+			div.innerHTML = "<div style='width:4px;'></div>";
+			jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2;
+		}
+
+		div.innerHTML = "<table><tr><td style='padding:0;display:none'></td><td>t</td></tr></table>";
+		var tds = div.getElementsByTagName("td");
+
+		// Check if table cells still have offsetWidth/Height when they are set
+		// to display:none and there are still other visible table cells in a
+		// table row; if so, offsetWidth/Height are not reliable for use when
+		// determining if an element has been hidden directly using
+		// display:none (it is still safe to use offsets if a parent element is
+		// hidden; don safety goggles and see bug #4512 for more information).
+		// (only IE 8 fails this test)
+		jQuery.support.reliableHiddenOffsets = tds[0].offsetHeight === 0;
+
+		tds[0].style.display = "";
+		tds[1].style.display = "none";
+
+		// Check if empty table cells still have offsetWidth/Height
+		// (IE < 8 fail this test)
+		jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets && tds[0].offsetHeight === 0;
+		div.innerHTML = "";
+
+		document.body.removeChild( div ).style.display = "none";
+		div = tds = null;
+	});
+
+	// Technique from Juriy Zaytsev
+	// http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
+	var eventSupported = function( eventName ) {
+		var el = document.createElement("div");
+		eventName = "on" + eventName;
+
+		var isSupported = (eventName in el);
+		if ( !isSupported ) {
+			el.setAttribute(eventName, "return;");
+			isSupported = typeof el[eventName] === "function";
+		}
+		el = null;
+
+		return isSupported;
+	};
+
+	jQuery.support.submitBubbles = eventSupported("submit");
+	jQuery.support.changeBubbles = eventSupported("change");
+
+	// release memory in IE
+	root = script = div = all = a = null;
+})();
+
+
+
+var windowData = {},
+	rbrace = /^(?:\{.*\}|\[.*\])$/;
+
+jQuery.extend({
+	cache: {},
+
+	// Please use with caution
+	uuid: 0,
+
+	// Unique for each copy of jQuery on the page	
+	expando: "jQuery" + jQuery.now(),
+
+	// The following elements throw uncatchable exceptions if you
+	// attempt to add expando properties to them.
+	noData: {
+		"embed": true,
+		// Ban all objects except for Flash (which handle expandos)
+		"object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
+		"applet": true
+	},
+
+	data: function( elem, name, data ) {
+		if ( !jQuery.acceptData( elem ) ) {
+			return;
+		}
+
+		elem = elem == window ?
+			windowData :
+			elem;
+
+		var isNode = elem.nodeType,
+			id = isNode ? elem[ jQuery.expando ] : null,
+			cache = jQuery.cache, thisCache;
+
+		if ( isNode && !id && typeof name === "string" && data === undefined ) {
+			return;
+		}
+
+		// Get the data from the object directly
+		if ( !isNode ) {
+			cache = elem;
+
+		// Compute a unique ID for the element
+		} else if ( !id ) {
+			elem[ jQuery.expando ] = id = ++jQuery.uuid;
+		}
+
+		// Avoid generating a new cache unless none exists and we
+		// want to manipulate it.
+		if ( typeof name === "object" ) {
+			if ( isNode ) {
+				cache[ id ] = jQuery.extend(cache[ id ], name);
+
+			} else {
+				jQuery.extend( cache, name );
+			}
+
+		} else if ( isNode && !cache[ id ] ) {
+			cache[ id ] = {};
+		}
+
+		thisCache = isNode ? cache[ id ] : cache;
+
+		// Prevent overriding the named cache with undefined values
+		if ( data !== undefined ) {
+			thisCache[ name ] = data;
+		}
+
+		return typeof name === "string" ? thisCache[ name ] : thisCache;
+	},
+
+	removeData: function( elem, name ) {
+		if ( !jQuery.acceptData( elem ) ) {
+			return;
+		}
+
+		elem = elem == window ?
+			windowData :
+			elem;
+
+		var isNode = elem.nodeType,
+			id = isNode ? elem[ jQuery.expando ] : elem,
+			cache = jQuery.cache,
+			thisCache = isNode ? cache[ id ] : id;
+
+		// If we want to remove a specific section of the element's data
+		if ( name ) {
+			if ( thisCache ) {
+				// Remove the section of cache data
+				delete thisCache[ name ];
+
+				// If we've removed all the data, remove the element's cache
+				if ( isNode && jQuery.isEmptyObject(thisCache) ) {
+					jQuery.removeData( elem );
+				}
+			}
+
+		// Otherwise, we want to remove all of the element's data
+		} else {
+			if ( isNode && jQuery.support.deleteExpando ) {
+				delete elem[ jQuery.expando ];
+
+			} else if ( elem.removeAttribute ) {
+				elem.removeAttribute( jQuery.expando );
+
+			// Completely remove the data cache
+			} else if ( isNode ) {
+				delete cache[ id ];
+
+			// Remove all fields from the object
+			} else {
+				for ( var n in elem ) {
+					delete elem[ n ];
+				}
+			}
+		}
+	},
+
+	// A method for determining if a DOM node can handle the data expando
+	acceptData: function( elem ) {
+		if ( elem.nodeName ) {
+			var match = jQuery.noData[ elem.nodeName.toLowerCase() ];
+
+			if ( match ) {
+				return !(match === true || elem.getAttribute("classid") !== match);
+			}
+		}
+
+		return true;
+	}
+});
+
+jQuery.fn.extend({
+	data: function( key, value ) {
+		var data = null;
+
+		if ( typeof key === "undefined" ) {
+			if ( this.length ) {
+				var attr = this[0].attributes, name;
+				data = jQuery.data( this[0] );
+
+				for ( var i = 0, l = attr.length; i < l; i++ ) {
+					name = attr[i].name;
+
+					if ( name.indexOf( "data-" ) === 0 ) {
+						name = name.substr( 5 );
+						dataAttr( this[0], name, data[ name ] );
+					}
+				}
+			}
+
+			return data;
+
+		} else if ( typeof key === "object" ) {
+			return this.each(function() {
+				jQuery.data( this, key );
+			});
+		}
+
+		var parts = key.split(".");
+		parts[1] = parts[1] ? "." + parts[1] : "";
+
+		if ( value === undefined ) {
+			data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
+
+			// Try to fetch any internally stored data first
+			if ( data === undefined && this.length ) {
+				data = jQuery.data( this[0], key );
+				data = dataAttr( this[0], key, data );
+			}
+
+			return data === undefined && parts[1] ?
+				this.data( parts[0] ) :
+				data;
+
+		} else {
+			return this.each(function() {
+				var $this = jQuery( this ),
+					args = [ parts[0], value ];
+
+				$this.triggerHandler( "setData" + parts[1] + "!", args );
+				jQuery.data( this, key, value );
+				$this.triggerHandler( "changeData" + parts[1] + "!", args );
+			});
+		}
+	},
+
+	removeData: function( key ) {
+		return this.each(function() {
+			jQuery.removeData( this, key );
+		});
+	}
+});
+
+function dataAttr( elem, key, data ) {
+	// If nothing was found internally, try to fetch any
+	// data from the HTML5 data-* attribute
+	if ( data === undefined && elem.nodeType === 1 ) {
+		data = elem.getAttribute( "data-" + key );
+
+		if ( typeof data === "string" ) {
+			try {
+				data = data === "true" ? true :
+				data === "false" ? false :
+				data === "null" ? null :
+				!jQuery.isNaN( data ) ? parseFloat( data ) :
+					rbrace.test( data ) ? jQuery.parseJSON( data ) :
+					data;
+			} catch( e ) {}
+
+			// Make sure we set the data so it isn't changed later
+			jQuery.data( elem, key, data );
+
+		} else {
+			data = undefined;
+		}
+	}
+
+	return data;
+}
+
+
+
+
+jQuery.extend({
+	queue: function( elem, type, data ) {
+		if ( !elem ) {
+			return;
+		}
+
+		type = (type || "fx") + "queue";
+		var q = jQuery.data( elem, type );
+
+		// Speed up dequeue by getting out quickly if this is just a lookup
+		if ( !data ) {
+			return q || [];
+		}
+
+		if ( !q || jQuery.isArray(data) ) {
+			q = jQuery.data( elem, type, jQuery.makeArray(data) );
+
+		} else {
+			q.push( data );
+		}
+
+		return q;
+	},
+
+	dequeue: function( elem, type ) {
+		type = type || "fx";
+
+		var queue = jQuery.queue( elem, type ),
+			fn = queue.shift();
+
+		// If the fx queue is dequeued, always remove the progress sentinel
+		if ( fn === "inprogress" ) {
+			fn = queue.shift();
+		}
+
+		if ( fn ) {
+			// Add a progress sentinel to prevent the fx queue from being
+			// automatically dequeued
+			if ( type === "fx" ) {
+				queue.unshift("inprogress");
+			}
+
+			fn.call(elem, function() {
+				jQuery.dequeue(elem, type);
+			});
+		}
+	}
+});
+
+jQuery.fn.extend({
+	queue: function( type, data ) {
+		if ( typeof type !== "string" ) {
+			data = type;
+			type = "fx";
+		}
+
+		if ( data === undefined ) {
+			return jQuery.queue( this[0], type );
+		}
+		return this.each(function( i ) {
+			var queue = jQuery.queue( this, type, data );
+
+			if ( type === "fx" && queue[0] !== "inprogress" ) {
+				jQuery.dequeue( this, type );
+			}
+		});
+	},
+	dequeue: function( type ) {
+		return this.each(function() {
+			jQuery.dequeue( this, type );
+		});
+	},
+
+	// Based off of the plugin by Clint Helfers, with permission.
+	// http://blindsignals.com/index.php/2009/07/jquery-delay/
+	delay: function( time, type ) {
+		time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
+		type = type || "fx";
+
+		return this.queue( type, function() {
+			var elem = this;
+			setTimeout(function() {
+				jQuery.dequeue( elem, type );
+			}, time );
+		});
+	},
+
+	clearQueue: function( type ) {
+		return this.queue( type || "fx", [] );
+	}
+});
+
+
+
+
+var rclass = /[\n\t]/g,
+	rspaces = /\s+/,
+	rreturn = /\r/g,
+	rspecialurl = /^(?:href|src|style)$/,
+	rtype = /^(?:button|input)$/i,
+	rfocusable = /^(?:button|input|object|select|textarea)$/i,
+	rclickable = /^a(?:rea)?$/i,
+	rradiocheck = /^(?:radio|checkbox)$/i;
+
+jQuery.props = {
+	"for": "htmlFor",
+	"class": "className",
+	readonly: "readOnly",
+	maxlength: "maxLength",
+	cellspacing: "cellSpacing",
+	rowspan: "rowSpan",
+	colspan: "colSpan",
+	tabindex: "tabIndex",
+	usemap: "useMap",
+	frameborder: "frameBorder"
+};
+
+jQuery.fn.extend({
+	attr: function( name, value ) {
+		return jQuery.access( this, name, value, true, jQuery.attr );
+	},
+
+	removeAttr: function( name, fn ) {
+		return this.each(function(){
+			jQuery.attr( this, name, "" );
+			if ( this.nodeType === 1 ) {
+				this.removeAttribute( name );
+			}
+		});
+	},
+
+	addClass: function( value ) {
+		if ( jQuery.isFunction(value) ) {
+			return this.each(function(i) {
+				var self = jQuery(this);
+				self.addClass( value.call(this, i, self.attr("class")) );
+			});
+		}
+
+		if ( value && typeof value === "string" ) {
+			var classNames = (value || "").split( rspaces );
+
+			for ( var i = 0, l = this.length; i < l; i++ ) {
+				var elem = this[i];
+
+				if ( elem.nodeType === 1 ) {
+					if ( !elem.className ) {
+						elem.className = value;
+
+					} else {
+						var className = " " + elem.className + " ",
+							setClass = elem.className;
+
+						for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
+							if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) {
+								setClass += " " + classNames[c];
+							}
+						}
+						elem.className = jQuery.trim( setClass );
+					}
+				}
+			}
+		}
+
+		return this;
+	},
+
+	removeClass: function( value ) {
+		if ( jQuery.isFunction(value) ) {
+			return this.each(function(i) {
+				var self = jQuery(this);
+				self.removeClass( value.call(this, i, self.attr("class")) );
+			});
+		}
+
+		if ( (value && typeof value === "string") || value === undefined ) {
+			var classNames = (value || "").split( rspaces );
+
+			for ( var i = 0, l = this.length; i < l; i++ ) {
+				var elem = this[i];
+
+				if ( elem.nodeType === 1 && elem.className ) {
+					if ( value ) {
+						var className = (" " + elem.className + " ").replace(rclass, " ");
+						for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
+							className = className.replace(" " + classNames[c] + " ", " ");
+						}
+						elem.className = jQuery.trim( className );
+
+					} else {
+						elem.className = "";
+					}
+				}
+			}
+		}
+
+		return this;
+	},
+
+	toggleClass: function( value, stateVal ) {
+		var type = typeof value,
+			isBool = typeof stateVal === "boolean";
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function(i) {
+				var self = jQuery(this);
+				self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal );
+			});
+		}
+
+		return this.each(function() {
+			if ( type === "string" ) {
+				// toggle individual class names
+				var className,
+					i = 0,
+					self = jQuery( this ),
+					state = stateVal,
+					classNames = value.split( rspaces );
+
+				while ( (className = classNames[ i++ ]) ) {
+					// check each className given, space seperated list
+					state = isBool ? state : !self.hasClass( className );
+					self[ state ? "addClass" : "removeClass" ]( className );
+				}
+
+			} else if ( type === "undefined" || type === "boolean" ) {
+				if ( this.className ) {
+					// store className if set
+					jQuery.data( this, "__className__", this.className );
+				}
+
+				// toggle whole className
+				this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || "";
+			}
+		});
+	},
+
+	hasClass: function( selector ) {
+		var className = " " + selector + " ";
+		for ( var i = 0, l = this.length; i < l; i++ ) {
+			if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
+				return true;
+			}
+		}
+
+		return false;
+	},
+
+	val: function( value ) {
+		if ( !arguments.length ) {
+			var elem = this[0];
+
+			if ( elem ) {
+				if ( jQuery.nodeName( elem, "option" ) ) {
+					// attributes.value is undefined in Blackberry 4.7 but
+					// uses .value. See #6932
+					var val = elem.attributes.value;
+					return !val || val.specified ? elem.value : elem.text;
+				}
+
+				// We need to handle select boxes special
+				if ( jQuery.nodeName( elem, "select" ) ) {
+					var index = elem.selectedIndex,
+						values = [],
+						options = elem.options,
+						one = elem.type === "select-one";
+
+					// Nothing was selected
+					if ( index < 0 ) {
+						return null;
+					}
+
+					// Loop through all the selected options
+					for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
+						var option = options[ i ];
+
+						// Don't return options that are disabled or in a disabled optgroup
+						if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && 
+								(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
+
+							// Get the specific value for the option
+							value = jQuery(option).val();
+
+							// We don't need an array for one selects
+							if ( one ) {
+								return value;
+							}
+
+							// Multi-Selects return an array
+							values.push( value );
+						}
+					}
+
+					return values;
+				}
+
+				// Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
+				if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) {
+					return elem.getAttribute("value") === null ? "on" : elem.value;
+				}
+				
+
+				// Everything else, we just grab the value
+				return (elem.value || "").replace(rreturn, "");
+
+			}
+
+			return undefined;
+		}
+
+		var isFunction = jQuery.isFunction(value);
+
+		return this.each(function(i) {
+			var self = jQuery(this), val = value;
+
+			if ( this.nodeType !== 1 ) {
+				return;
+			}
+
+			if ( isFunction ) {
+				val = value.call(this, i, self.val());
+			}
+
+			// Treat null/undefined as ""; convert numbers to string
+			if ( val == null ) {
+				val = "";
+			} else if ( typeof val === "number" ) {
+				val += "";
+			} else if ( jQuery.isArray(val) ) {
+				val = jQuery.map(val, function (value) {
+					return value == null ? "" : value + "";
+				});
+			}
+
+			if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) {
+				this.checked = jQuery.inArray( self.val(), val ) >= 0;
+
+			} else if ( jQuery.nodeName( this, "select" ) ) {
+				var values = jQuery.makeArray(val);
+
+				jQuery( "option", this ).each(function() {
+					this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
+				});
+
+				if ( !values.length ) {
+					this.selectedIndex = -1;
+				}
+
+			} else {
+				this.value = val;
+			}
+		});
+	}
+});
+
+jQuery.extend({
+	attrFn: {
+		val: true,
+		css: true,
+		html: true,
+		text: true,
+		data: true,
+		width: true,
+		height: true,
+		offset: true
+	},
+		
+	attr: function( elem, name, value, pass ) {
+		// don't set attributes on text and comment nodes
+		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
+			return undefined;
+		}
+
+		if ( pass && name in jQuery.attrFn ) {
+			return jQuery(elem)[name](value);
+		}
+
+		var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ),
+			// Whether we are setting (or getting)
+			set = value !== undefined;
+
+		// Try to normalize/fix the name
+		name = notxml && jQuery.props[ name ] || name;
+
+		// These attributes require special treatment
+		var special = rspecialurl.test( name );
+
+		// Safari mis-reports the default selected property of an option
+		// Accessing the parent's selectedIndex property fixes it
+		if ( name === "selected" && !jQuery.support.optSelected ) {
+			var parent = elem.parentNode;
+			if ( parent ) {
+				parent.selectedIndex;
+
+				// Make sure that it also works with optgroups, see #5701
+				if ( parent.parentNode ) {
+					parent.parentNode.selectedIndex;
+				}
+			}
+		}
+
+		// If applicable, access the attribute via the DOM 0 way
+		// 'in' checks fail in Blackberry 4.7 #6931
+		if ( (name in elem || elem[ name ] !== undefined) && notxml && !special ) {
+			if ( set ) {
+				// We can't allow the type property to be changed (since it causes problems in IE)
+				if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) {
+					jQuery.error( "type property can't be changed" );
+				}
+
+				if ( value === null ) {
+					if ( elem.nodeType === 1 ) {
+						elem.removeAttribute( name );
+					}
+
+				} else {
+					elem[ name ] = value;
+				}
+			}
+
+			// browsers index elements by id/name on forms, give priority to attributes.
+			if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) {
+				return elem.getAttributeNode( name ).nodeValue;
+			}
+
+			// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+			// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+			if ( name === "tabIndex" ) {
+				var attributeNode = elem.getAttributeNode( "tabIndex" );
+
+				return attributeNode && attributeNode.specified ?
+					attributeNode.value :
+					rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
+						0 :
+						undefined;
+			}
+
+			return elem[ name ];
+		}
+
+		if ( !jQuery.support.style && notxml && name === "style" ) {
+			if ( set ) {
+				elem.style.cssText = "" + value;
+			}
+
+			return elem.style.cssText;
+		}
+
+		if ( set ) {
+			// convert the value to a string (all browsers do this but IE) see #1070
+			elem.setAttribute( name, "" + value );
+		}
+
+		// Ensure that missing attributes return undefined
+		// Blackberry 4.7 returns "" from getAttribute #6938
+		if ( !elem.attributes[ name ] && (elem.hasAttribute && !elem.hasAttribute( name )) ) {
+			return undefined;
+		}
+
+		var attr = !jQuery.support.hrefNormalized && notxml && special ?
+				// Some attributes require a special call on IE
+				elem.getAttribute( name, 2 ) :
+				elem.getAttribute( name );
+
+		// Non-existent attributes return null, we normalize to undefined
+		return attr === null ? undefined : attr;
+	}
+});
+
+
+
+
+var rnamespaces = /\.(.*)$/,
+	rformElems = /^(?:textarea|input|select)$/i,
+	rperiod = /\./g,
+	rspace = / /g,
+	rescape = /[^\w\s.|`]/g,
+	fcleanup = function( nm ) {
+		return nm.replace(rescape, "\\$&");
+	},
+	focusCounts = { focusin: 0, focusout: 0 };
+
+/*
+ * A number of helper functions used for managing events.
+ * Many of the ideas behind this code originated from
+ * Dean Edwards' addEvent library.
+ */
+jQuery.event = {
+
+	// Bind an event to an element
+	// Original by Dean Edwards
+	add: function( elem, types, handler, data ) {
+		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+			return;
+		}
+
+		// For whatever reason, IE has trouble passing the window object
+		// around, causing it to be cloned in the process
+		if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) {
+			elem = window;
+		}
+
+		if ( handler === false ) {
+			handler = returnFalse;
+		} else if ( !handler ) {
+			// Fixes bug #7229. Fix recommended by jdalton
+		  return;
+		}
+
+		var handleObjIn, handleObj;
+
+		if ( handler.handler ) {
+			handleObjIn = handler;
+			handler = handleObjIn.handler;
+		}
+
+		// Make sure that the function being executed has a unique ID
+		if ( !handler.guid ) {
+			handler.guid = jQuery.guid++;
+		}
+
+		// Init the element's event structure
+		var elemData = jQuery.data( elem );
+
+		// If no elemData is found then we must be trying to bind to one of the
+		// banned noData elements
+		if ( !elemData ) {
+			return;
+		}
+
+		// Use a key less likely to result in collisions for plain JS objects.
+		// Fixes bug #7150.
+		var eventKey = elem.nodeType ? "events" : "__events__",
+			events = elemData[ eventKey ],
+			eventHandle = elemData.handle;
+			
+		if ( typeof events === "function" ) {
+			// On plain objects events is a fn that holds the the data
+			// which prevents this data from being JSON serialized
+			// the function does not need to be called, it just contains the data
+			eventHandle = events.handle;
+			events = events.events;
+
+		} else if ( !events ) {
+			if ( !elem.nodeType ) {
+				// On plain objects, create a fn that acts as the holder
+				// of the values to avoid JSON serialization of event data
+				elemData[ eventKey ] = elemData = function(){};
+			}
+
+			elemData.events = events = {};
+		}
+
+		if ( !eventHandle ) {
+			elemData.handle = eventHandle = function() {
+				// Handle the second event of a trigger and when
+				// an event is called after a page has unloaded
+				return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
+					jQuery.event.handle.apply( eventHandle.elem, arguments ) :
+					undefined;
+			};
+		}
+
+		// Add elem as a property of the handle function
+		// This is to prevent a memory leak with non-native events in IE.
+		eventHandle.elem = elem;
+
+		// Handle multiple events separated by a space
+		// jQuery(...).bind("mouseover mouseout", fn);
+		types = types.split(" ");
+
+		var type, i = 0, namespaces;
+
+		while ( (type = types[ i++ ]) ) {
+			handleObj = handleObjIn ?
+				jQuery.extend({}, handleObjIn) :
+				{ handler: handler, data: data };
+
+			// Namespaced event handlers
+			if ( type.indexOf(".") > -1 ) {
+				namespaces = type.split(".");
+				type = namespaces.shift();
+				handleObj.namespace = namespaces.slice(0).sort().join(".");
+
+			} else {
+				namespaces = [];
+				handleObj.namespace = "";
+			}
+
+			handleObj.type = type;
+			if ( !handleObj.guid ) {
+				handleObj.guid = handler.guid;
+			}
+
+			// Get the current list of functions bound to this event
+			var handlers = events[ type ],
+				special = jQuery.event.special[ type ] || {};
+
+			// Init the event handler queue
+			if ( !handlers ) {
+				handlers = events[ type ] = [];
+
+				// Check for a special event handler
+				// Only use addEventListener/attachEvent if the special
+				// events handler returns false
+				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+					// Bind the global event handler to the element
+					if ( elem.addEventListener ) {
+						elem.addEventListener( type, eventHandle, false );
+
+					} else if ( elem.attachEvent ) {
+						elem.attachEvent( "on" + type, eventHandle );
+					}
+				}
+			}
+			
+			if ( special.add ) { 
+				special.add.call( elem, handleObj ); 
+
+				if ( !handleObj.handler.guid ) {
+					handleObj.handler.guid = handler.guid;
+				}
+			}
+
+			// Add the function to the element's handler list
+			handlers.push( handleObj );
+
+			// Keep track of which events have been used, for global triggering
+			jQuery.event.global[ type ] = true;
+		}
+
+		// Nullify elem to prevent memory leaks in IE
+		elem = null;
+	},
+
+	global: {},
+
+	// Detach an event or set of events from an element
+	remove: function( elem, types, handler, pos ) {
+		// don't do events on text and comment nodes
+		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+			return;
+		}
+
+		if ( handler === false ) {
+			handler = returnFalse;
+		}
+
+		var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
+			eventKey = elem.nodeType ? "events" : "__events__",
+			elemData = jQuery.data( elem ),
+			events = elemData && elemData[ eventKey ];
+
+		if ( !elemData || !events ) {
+			return;
+		}
+		
+		if ( typeof events === "function" ) {
+			elemData = events;
+			events = events.events;
+		}
+
+		// types is actually an event object here
+		if ( types && types.type ) {
+			handler = types.handler;
+			types = types.type;
+		}
+
+		// Unbind all events for the element
+		if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
+			types = types || "";
+
+			for ( type in events ) {
+				jQuery.event.remove( elem, type + types );
+			}
+
+			return;
+		}
+
+		// Handle multiple events separated by a space
+		// jQuery(...).unbind("mouseover mouseout", fn);
+		types = types.split(" ");
+
+		while ( (type = types[ i++ ]) ) {
+			origType = type;
+			handleObj = null;
+			all = type.indexOf(".") < 0;
+			namespaces = [];
+
+			if ( !all ) {
+				// Namespaced event handlers
+				namespaces = type.split(".");
+				type = namespaces.shift();
+
+				namespace = new RegExp("(^|\\.)" + 
+					jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)");
+			}
+
+			eventType = events[ type ];
+
+			if ( !eventType ) {
+				continue;
+			}
+
+			if ( !handler ) {
+				for ( j = 0; j < eventType.length; j++ ) {
+					handleObj = eventType[ j ];
+
+					if ( all || namespace.test( handleObj.namespace ) ) {
+						jQuery.event.remove( elem, origType, handleObj.handler, j );
+						eventType.splice( j--, 1 );
+					}
+				}
+
+				continue;
+			}
+
+			special = jQuery.event.special[ type ] || {};
+
+			for ( j = pos || 0; j < eventType.length; j++ ) {
+				handleObj = eventType[ j ];
+
+				if ( handler.guid === handleObj.guid ) {
+					// remove the given handler for the given type
+					if ( all || namespace.test( handleObj.namespace ) ) {
+						if ( pos == null ) {
+							eventType.splice( j--, 1 );
+						}
+
+						if ( special.remove ) {
+							special.remove.call( elem, handleObj );
+						}
+					}
+
+					if ( pos != null ) {
+						break;
+					}
+				}
+			}
+
+			// remove generic event handler if no more handlers exist
+			if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
+				if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
+					jQuery.removeEvent( elem, type, elemData.handle );
+				}
+
+				ret = null;
+				delete events[ type ];
+			}
+		}
+
+		// Remove the expando if it's no longer used
+		if ( jQuery.isEmptyObject( events ) ) {
+			var handle = elemData.handle;
+			if ( handle ) {
+				handle.elem = null;
+			}
+
+			delete elemData.events;
+			delete elemData.handle;
+
+			if ( typeof elemData === "function" ) {
+				jQuery.removeData( elem, eventKey );
+
+			} else if ( jQuery.isEmptyObject( elemData ) ) {
+				jQuery.removeData( elem );
+			}
+		}
+	},
+
+	// bubbling is internal
+	trigger: function( event, data, elem /*, bubbling */ ) {
+		// Event object or event type
+		var type = event.type || event,
+			bubbling = arguments[3];
+
+		if ( !bubbling ) {
+			event = typeof event === "object" ?
+				// jQuery.Event object
+				event[ jQuery.expando ] ? event :
+				// Object literal
+				jQuery.extend( jQuery.Event(type), event ) :
+				// Just the event type (string)
+				jQuery.Event(type);
+
+			if ( type.indexOf("!") >= 0 ) {
+				event.type = type = type.slice(0, -1);
+				event.exclusive = true;
+			}
+
+			// Handle a global trigger
+			if ( !elem ) {
+				// Don't bubble custom events when global (to avoid too much overhead)
+				event.stopPropagation();
+
+				// Only trigger if we've ever bound an event for it
+				if ( jQuery.event.global[ type ] ) {
+					jQuery.each( jQuery.cache, function() {
+						if ( this.events && this.events[type] ) {
+							jQuery.event.trigger( event, data, this.handle.elem );
+						}
+					});
+				}
+			}
+
+			// Handle triggering a single element
+
+			// don't do events on text and comment nodes
+			if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
+				return undefined;
+			}
+
+			// Clean up in case it is reused
+			event.result = undefined;
+			event.target = elem;
+
+			// Clone the incoming data, if any
+			data = jQuery.makeArray( data );
+			data.unshift( event );
+		}
+
+		event.currentTarget = elem;
+
+		// Trigger the event, it is assumed that "handle" is a function
+		var handle = elem.nodeType ?
+			jQuery.data( elem, "handle" ) :
+			(jQuery.data( elem, "__events__" ) || {}).handle;
+
+		if ( handle ) {
+			handle.apply( elem, data );
+		}
+
+		var parent = elem.parentNode || elem.ownerDocument;
+
+		// Trigger an inline bound script
+		try {
+			if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
+				if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
+					event.result = false;
+					event.preventDefault();
+				}
+			}
+
+		// prevent IE from throwing an error for some elements with some event types, see #3533
+		} catch (inlineError) {}
+
+		if ( !event.isPropagationStopped() && parent ) {
+			jQuery.event.trigger( event, data, parent, true );
+
+		} else if ( !event.isDefaultPrevented() ) {
+			var old,
+				target = event.target,
+				targetType = type.replace( rnamespaces, "" ),
+				isClick = jQuery.nodeName( target, "a" ) && targetType === "click",
+				special = jQuery.event.special[ targetType ] || {};
+
+			if ( (!special._default || special._default.call( elem, event ) === false) && 
+				!isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
+
+				try {
+					if ( target[ targetType ] ) {
+						// Make sure that we don't accidentally re-trigger the onFOO events
+						old = target[ "on" + targetType ];
+
+						if ( old ) {
+							target[ "on" + targetType ] = null;
+						}
+
+						jQuery.event.triggered = true;
+						target[ targetType ]();
+					}
+
+				// prevent IE from throwing an error for some elements with some event types, see #3533
+				} catch (triggerError) {}
+
+				if ( old ) {
+					target[ "on" + targetType ] = old;
+				}
+
+				jQuery.event.triggered = false;
+			}
+		}
+	},
+
+	handle: function( event ) {
+		var all, handlers, namespaces, namespace_re, events,
+			namespace_sort = [],
+			args = jQuery.makeArray( arguments );
+
+		event = args[0] = jQuery.event.fix( event || window.event );
+		event.currentTarget = this;
+
+		// Namespaced event handlers
+		all = event.type.indexOf(".") < 0 && !event.exclusive;
+
+		if ( !all ) {
+			namespaces = event.type.split(".");
+			event.type = namespaces.shift();
+			namespace_sort = namespaces.slice(0).sort();
+			namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)");
+		}
+
+		event.namespace = event.namespace || namespace_sort.join(".");
+
+		events = jQuery.data(this, this.nodeType ? "events" : "__events__");
+
+		if ( typeof events === "function" ) {
+			events = events.events;
+		}
+
+		handlers = (events || {})[ event.type ];
+
+		if ( events && handlers ) {
+			// Clone the handlers to prevent manipulation
+			handlers = handlers.slice(0);
+
+			for ( var j = 0, l = handlers.length; j < l; j++ ) {
+				var handleObj = handlers[ j ];
+
+				// Filter the functions by class
+				if ( all || namespace_re.test( handleObj.namespace ) ) {
+					// Pass in a reference to the handler function itself
+					// So that we can later remove it
+					event.handler = handleObj.handler;
+					event.data = handleObj.data;
+					event.handleObj = handleObj;
+	
+					var ret = handleObj.handler.apply( this, args );
+
+					if ( ret !== undefined ) {
+						event.result = ret;
+						if ( ret === false ) {
+							event.preventDefault();
+							event.stopPropagation();
+						}
+					}
+
+					if ( event.isImmediatePropagationStopped() ) {
+						break;
+					}
+				}
+			}
+		}
+
+		return event.result;
+	},
+
+	props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
+
+	fix: function( event ) {
+		if ( event[ jQuery.expando ] ) {
+			return event;
+		}
+
+		// store a copy of the original event object
+		// and "clone" to set read-only properties
+		var originalEvent = event;
+		event = jQuery.Event( originalEvent );
+
+		for ( var i = this.props.length, prop; i; ) {
+			prop = this.props[ --i ];
+			event[ prop ] = originalEvent[ prop ];
+		}
+
+		// Fix target property, if necessary
+		if ( !event.target ) {
+			// Fixes #1925 where srcElement might not be defined either
+			event.target = event.srcElement || document;
+		}
+
+		// check if target is a textnode (safari)
+		if ( event.target.nodeType === 3 ) {
+			event.target = event.target.parentNode;
+		}
+
+		// Add relatedTarget, if necessary
+		if ( !event.relatedTarget && event.fromElement ) {
+			event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
+		}
+
+		// Calculate pageX/Y if missing and clientX/Y available
+		if ( event.pageX == null && event.clientX != null ) {
+			var doc = document.documentElement,
+				body = document.body;
+
+			event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
+			event.pageY = event.clientY + (doc && doc.scrollTop  || body && body.scrollTop  || 0) - (doc && doc.clientTop  || body && body.clientTop  || 0);
+		}
+
+		// Add which for key events
+		if ( event.which == null && (event.charCode != null || event.keyCode != null) ) {
+			event.which = event.charCode != null ? event.charCode : event.keyCode;
+		}
+
+		// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
+		if ( !event.metaKey && event.ctrlKey ) {
+			event.metaKey = event.ctrlKey;
+		}
+
+		// Add which for click: 1 === left; 2 === middle; 3 === right
+		// Note: button is not normalized, so don't use it
+		if ( !event.which && event.button !== undefined ) {
+			event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
+		}
+
+		return event;
+	},
+
+	// Deprecated, use jQuery.guid instead
+	guid: 1E8,
+
+	// Deprecated, use jQuery.proxy instead
+	proxy: jQuery.proxy,
+
+	special: {
+		ready: {
+			// Make sure the ready event is setup
+			setup: jQuery.bindReady,
+			teardown: jQuery.noop
+		},
+
+		live: {
+			add: function( handleObj ) {
+				jQuery.event.add( this,
+					liveConvert( handleObj.origType, handleObj.selector ),
+					jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); 
+			},
+
+			remove: function( handleObj ) {
+				jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );
+			}
+		},
+
+		beforeunload: {
+			setup: function( data, namespaces, eventHandle ) {
+				// We only want to do this special case on windows
+				if ( jQuery.isWindow( this ) ) {
+					this.onbeforeunload = eventHandle;
+				}
+			},
+
+			teardown: function( namespaces, eventHandle ) {
+				if ( this.onbeforeunload === eventHandle ) {
+					this.onbeforeunload = null;
+				}
+			}
+		}
+	}
+};
+
+jQuery.removeEvent = document.removeEventListener ?
+	function( elem, type, handle ) {
+		if ( elem.removeEventListener ) {
+			elem.removeEventListener( type, handle, false );
+		}
+	} : 
+	function( elem, type, handle ) {
+		if ( elem.detachEvent ) {
+			elem.detachEvent( "on" + type, handle );
+		}
+	};
+
+jQuery.Event = function( src ) {
+	// Allow instantiation without the 'new' keyword
+	if ( !this.preventDefault ) {
+		return new jQuery.Event( src );
+	}
+
+	// Event object
+	if ( src && src.type ) {
+		this.originalEvent = src;
+		this.type = src.type;
+	// Event type
+	} else {
+		this.type = src;
+	}
+
+	// timeStamp is buggy for some events on Firefox(#3843)
+	// So we won't rely on the native value
+	this.timeStamp = jQuery.now();
+
+	// Mark it as fixed
+	this[ jQuery.expando ] = true;
+};
+
+function returnFalse() {
+	return false;
+}
+function returnTrue() {
+	return true;
+}
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+	preventDefault: function() {
+		this.isDefaultPrevented = returnTrue;
+
+		var e = this.originalEvent;
+		if ( !e ) {
+			return;
+		}
+		
+		// if preventDefault exists run it on the original event
+		if ( e.preventDefault ) {
+			e.preventDefault();
+
+		// otherwise set the returnValue property of the original event to false (IE)
+		} else {
+			e.returnValue = false;
+		}
+	},
+	stopPropagation: function() {
+		this.isPropagationStopped = returnTrue;
+
+		var e = this.originalEvent;
+		if ( !e ) {
+			return;
+		}
+		// if stopPropagation exists run it on the original event
+		if ( e.stopPropagation ) {
+			e.stopPropagation();
+		}
+		// otherwise set the cancelBubble property of the original event to true (IE)
+		e.cancelBubble = true;
+	},
+	stopImmediatePropagation: function() {
+		this.isImmediatePropagationStopped = returnTrue;
+		this.stopPropagation();
+	},
+	isDefaultPrevented: returnFalse,
+	isPropagationStopped: returnFalse,
+	isImmediatePropagationStopped: returnFalse
+};
+
+// Checks if an event happened on an element within another element
+// Used in jQuery.event.special.mouseenter and mouseleave handlers
+var withinElement = function( event ) {
+	// Check if mouse(over|out) are still within the same parent element
+	var parent = event.relatedTarget;
+
+	// Firefox sometimes assigns relatedTarget a XUL element
+	// which we cannot access the parentNode property of
+	try {
+		// Traverse up the tree
+		while ( parent && parent !== this ) {
+			parent = parent.parentNode;
+		}
+
+		if ( parent !== this ) {
+			// set the correct event type
+			event.type = event.data;
+
+			// handle event if we actually just moused on to a non sub-element
+			jQuery.event.handle.apply( this, arguments );
+		}
+
+	// assuming we've left the element since we most likely mousedover a xul element
+	} catch(e) { }
+},
+
+// In case of event delegation, we only need to rename the event.type,
+// liveHandler will take care of the rest.
+delegate = function( event ) {
+	event.type = event.data;
+	jQuery.event.handle.apply( this, arguments );
+};
+
+// Create mouseenter and mouseleave events
+jQuery.each({
+	mouseenter: "mouseover",
+	mouseleave: "mouseout"
+}, function( orig, fix ) {
+	jQuery.event.special[ orig ] = {
+		setup: function( data ) {
+			jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
+		},
+		teardown: function( data ) {
+			jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
+		}
+	};
+});
+
+// submit delegation
+if ( !jQuery.support.submitBubbles ) {
+
+	jQuery.event.special.submit = {
+		setup: function( data, namespaces ) {
+			if ( this.nodeName.toLowerCase() !== "form" ) {
+				jQuery.event.add(this, "click.specialSubmit", function( e ) {
+					var elem = e.target,
+						type = elem.type;
+
+					if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
+						e.liveFired = undefined;
+						return trigger( "submit", this, arguments );
+					}
+				});
+	 
+				jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
+					var elem = e.target,
+						type = elem.type;
+
+					if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
+						e.liveFired = undefined;
+						return trigger( "submit", this, arguments );
+					}
+				});
+
+			} else {
+				return false;
+			}
+		},
+
+		teardown: function( namespaces ) {
+			jQuery.event.remove( this, ".specialSubmit" );
+		}
+	};
+
+}
+
+// change delegation, happens here so we have bind.
+if ( !jQuery.support.changeBubbles ) {
+
+	var changeFilters,
+
+	getVal = function( elem ) {
+		var type = elem.type, val = elem.value;
+
+		if ( type === "radio" || type === "checkbox" ) {
+			val = elem.checked;
+
+		} else if ( type === "select-multiple" ) {
+			val = elem.selectedIndex > -1 ?
+				jQuery.map( elem.options, function( elem ) {
+					return elem.selected;
+				}).join("-") :
+				"";
+
+		} else if ( elem.nodeName.toLowerCase() === "select" ) {
+			val = elem.selectedIndex;
+		}
+
+		return val;
+	},
+
+	testChange = function testChange( e ) {
+		var elem = e.target, data, val;
+
+		if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {
+			return;
+		}
+
+		data = jQuery.data( elem, "_change_data" );
+		val = getVal(elem);
+
+		// the current data will be also retrieved by beforeactivate
+		if ( e.type !== "focusout" || elem.type !== "radio" ) {
+			jQuery.data( elem, "_change_data", val );
+		}
+		
+		if ( data === undefined || val === data ) {
+			return;
+		}
+
+		if ( data != null || val ) {
+			e.type = "change";
+			e.liveFired = undefined;
+			return jQuery.event.trigger( e, arguments[1], elem );
+		}
+	};
+
+	jQuery.event.special.change = {
+		filters: {
+			focusout: testChange, 
+
+			beforedeactivate: testChange,
+
+			click: function( e ) {
+				var elem = e.target, type = elem.type;
+
+				if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
+					return testChange.call( this, e );
+				}
+			},
+
+			// Change has to be called before submit
+			// Keydown will be called before keypress, which is used in submit-event delegation
+			keydown: function( e ) {
+				var elem = e.target, type = elem.type;
+
+				if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
+					(e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
+					type === "select-multiple" ) {
+					return testChange.call( this, e );
+				}
+			},
+
+			// Beforeactivate happens also before the previous element is blurred
+			// with this event you can't trigger a change event, but you can store
+			// information
+			beforeactivate: function( e ) {
+				var elem = e.target;
+				jQuery.data( elem, "_change_data", getVal(elem) );
+			}
+		},
+
+		setup: function( data, namespaces ) {
+			if ( this.type === "file" ) {
+				return false;
+			}
+
+			for ( var type in changeFilters ) {
+				jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
+			}
+
+			return rformElems.test( this.nodeName );
+		},
+
+		teardown: function( namespaces ) {
+			jQuery.event.remove( this, ".specialChange" );
+
+			return rformElems.test( this.nodeName );
+		}
+	};
+
+	changeFilters = jQuery.event.special.change.filters;
+
+	// Handle when the input is .focus()'d
+	changeFilters.focus = changeFilters.beforeactivate;
+}
+
+function trigger( type, elem, args ) {
+	args[0].type = type;
+	return jQuery.event.handle.apply( elem, args );
+}
+
+// Create "bubbling" focus and blur events
+if ( document.addEventListener ) {
+	jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+		jQuery.event.special[ fix ] = {
+			setup: function() {
+				if ( focusCounts[fix]++ === 0 ) {
+					document.addEventListener( orig, handler, true );
+				}
+			}, 
+			teardown: function() { 
+				if ( --focusCounts[fix] === 0 ) {
+					document.removeEventListener( orig, handler, true );
+				}
+			}
+		};
+
+		function handler( e ) { 
+			e = jQuery.event.fix( e );
+			e.type = fix;
+			return jQuery.event.trigger( e, null, e.target );
+		}
+	});
+}
+
+jQuery.each(["bind", "one"], function( i, name ) {
+	jQuery.fn[ name ] = function( type, data, fn ) {
+		// Handle object literals
+		if ( typeof type === "object" ) {
+			for ( var key in type ) {
+				this[ name ](key, data, type[key], fn);
+			}
+			return this;
+		}
+		
+		if ( jQuery.isFunction( data ) || data === false ) {
+			fn = data;
+			data = undefined;
+		}
+
+		var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
+			jQuery( this ).unbind( event, handler );
+			return fn.apply( this, arguments );
+		}) : fn;
+
+		if ( type === "unload" && name !== "one" ) {
+			this.one( type, data, fn );
+
+		} else {
+			for ( var i = 0, l = this.length; i < l; i++ ) {
+				jQuery.event.add( this[i], type, handler, data );
+			}
+		}
+
+		return this;
+	};
+});
+
+jQuery.fn.extend({
+	unbind: function( type, fn ) {
+		// Handle object literals
+		if ( typeof type === "object" && !type.preventDefault ) {
+			for ( var key in type ) {
+				this.unbind(key, type[key]);
+			}
+
+		} else {
+			for ( var i = 0, l = this.length; i < l; i++ ) {
+				jQuery.event.remove( this[i], type, fn );
+			}
+		}
+
+		return this;
+	},
+	
+	delegate: function( selector, types, data, fn ) {
+		return this.live( types, data, fn, selector );
+	},
+	
+	undelegate: function( selector, types, fn ) {
+		if ( arguments.length === 0 ) {
+				return this.unbind( "live" );
+		
+		} else {
+			return this.die( types, null, fn, selector );
+		}
+	},
+	
+	trigger: function( type, data ) {
+		return this.each(function() {
+			jQuery.event.trigger( type, data, this );
+		});
+	},
+
+	triggerHandler: function( type, data ) {
+		if ( this[0] ) {
+			var event = jQuery.Event( type );
+			event.preventDefault();
+			event.stopPropagation();
+			jQuery.event.trigger( event, data, this[0] );
+			return event.result;
+		}
+	},
+
+	toggle: function( fn ) {
+		// Save reference to arguments for access in closure
+		var args = arguments,
+			i = 1;
+
+		// link all the functions, so any of them can unbind this click handler
+		while ( i < args.length ) {
+			jQuery.proxy( fn, args[ i++ ] );
+		}
+
+		return this.click( jQuery.proxy( fn, function( event ) {
+			// Figure out which function to execute
+			var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
+			jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
+
+			// Make sure that clicks stop
+			event.preventDefault();
+
+			// and execute the function
+			return args[ lastToggle ].apply( this, arguments ) || false;
+		}));
+	},
+
+	hover: function( fnOver, fnOut ) {
+		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+	}
+});
+
+var liveMap = {
+	focus: "focusin",
+	blur: "focusout",
+	mouseenter: "mouseover",
+	mouseleave: "mouseout"
+};
+
+jQuery.each(["live", "die"], function( i, name ) {
+	jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
+		var type, i = 0, match, namespaces, preType,
+			selector = origSelector || this.selector,
+			context = origSelector ? this : jQuery( this.context );
+		
+		if ( typeof types === "object" && !types.preventDefault ) {
+			for ( var key in types ) {
+				context[ name ]( key, data, types[key], selector );
+			}
+			
+			return this;
+		}
+
+		if ( jQuery.isFunction( data ) ) {
+			fn = data;
+			data = undefined;
+		}
+
+		types = (types || "").split(" ");
+
+		while ( (type = types[ i++ ]) != null ) {
+			match = rnamespaces.exec( type );
+			namespaces = "";
+
+			if ( match )  {
+				namespaces = match[0];
+				type = type.replace( rnamespaces, "" );
+			}
+
+			if ( type === "hover" ) {
+				types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
+				continue;
+			}
+
+			preType = type;
+
+			if ( type === "focus" || type === "blur" ) {
+				types.push( liveMap[ type ] + namespaces );
+				type = type + namespaces;
+
+			} else {
+				type = (liveMap[ type ] || type) + namespaces;
+			}
+
+			if ( name === "live" ) {
+				// bind live handler
+				for ( var j = 0, l = context.length; j < l; j++ ) {
+					jQuery.event.add( context[j], "live." + liveConvert( type, selector ),
+						{ data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
+				}
+
+			} else {
+				// unbind live handler
+				context.unbind( "live." + liveConvert( type, selector ), fn );
+			}
+		}
+		
+		return this;
+	};
+});
+
+function liveHandler( event ) {
+	var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
+		elems = [],
+		selectors = [],
+		events = jQuery.data( this, this.nodeType ? "events" : "__events__" );
+
+	if ( typeof events === "function" ) {
+		events = events.events;
+	}
+
+	// Make sure we avoid non-left-click bubbling in Firefox (#3861)
+	if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) {
+		return;
+	}
+	
+	if ( event.namespace ) {
+		namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)");
+	}
+
+	event.liveFired = this;
+
+	var live = events.live.slice(0);
+
+	for ( j = 0; j < live.length; j++ ) {
+		handleObj = live[j];
+
+		if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
+			selectors.push( handleObj.selector );
+
+		} else {
+			live.splice( j--, 1 );
+		}
+	}
+
+	match = jQuery( event.target ).closest( selectors, event.currentTarget );
+
+	for ( i = 0, l = match.length; i < l; i++ ) {
+		close = match[i];
+
+		for ( j = 0; j < live.length; j++ ) {
+			handleObj = live[j];
+
+			if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) ) {
+				elem = close.elem;
+				related = null;
+
+				// Those two events require additional checking
+				if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
+					event.type = handleObj.preType;
+					related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
+				}
+
+				if ( !related || related !== elem ) {
+					elems.push({ elem: elem, handleObj: handleObj, level: close.level });
+				}
+			}
+		}
+	}
+
+	for ( i = 0, l = elems.length; i < l; i++ ) {
+		match = elems[i];
+
+		if ( maxLevel && match.level > maxLevel ) {
+			break;
+		}
+
+		event.currentTarget = match.elem;
+		event.data = match.handleObj.data;
+		event.handleObj = match.handleObj;
+
+		ret = match.handleObj.origHandler.apply( match.elem, arguments );
+
+		if ( ret === false || event.isPropagationStopped() ) {
+			maxLevel = match.level;
+
+			if ( ret === false ) {
+				stop = false;
+			}
+			if ( event.isImmediatePropagationStopped() ) {
+				break;
+			}
+		}
+	}
+
+	return stop;
+}
+
+function liveConvert( type, selector ) {
+	return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&");
+}
+
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
+	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+	"change select submit keydown keypress keyup error").split(" "), function( i, name ) {
+
+	// Handle event binding
+	jQuery.fn[ name ] = function( data, fn ) {
+		if ( fn == null ) {
+			fn = data;
+			data = null;
+		}
+
+		return arguments.length > 0 ?
+			this.bind( name, data, fn ) :
+			this.trigger( name );
+	};
+
+	if ( jQuery.attrFn ) {
+		jQuery.attrFn[ name ] = true;
+	}
+});
+
+// Prevent memory leaks in IE
+// Window isn't included so as not to unbind existing unload events
+// More info:
+//  - http://isaacschlueter.com/2006/10/msie-memory-leaks/
+if ( window.attachEvent && !window.addEventListener ) {
+	jQuery(window).bind("unload", function() {
+		for ( var id in jQuery.cache ) {
+			if ( jQuery.cache[ id ].handle ) {
+				// Try/Catch is to handle iframes being unloaded, see #4280
+				try {
+					jQuery.event.remove( jQuery.cache[ id ].handle.elem );
+				} catch(e) {}
+			}
+		}
+	});
+}
+
+
+/*!
+ * Sizzle CSS Selector Engine - v1.0
+ *  Copyright 2009, The Dojo Foundation
+ *  Released under the MIT, BSD, and GPL Licenses.
+ *  More information: http://sizzlejs.com/
+ */
+(function(){
+
+var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
+	done = 0,
+	toString = Object.prototype.toString,
+	hasDuplicate = false,
+	baseHasDuplicate = true;
+
+// Here we check if the JavaScript engine is using some sort of
+// optimization where it does not always call our comparision
+// function. If that is the case, discard the hasDuplicate value.
+//   Thus far that includes Google Chrome.
+[0, 0].sort(function() {
+	baseHasDuplicate = false;
+	return 0;
+});
+
+var Sizzle = function( selector, context, results, seed ) {
+	results = results || [];
+	context = context || document;
+
+	var origContext = context;
+
+	if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
+		return [];
+	}
+	
+	if ( !selector || typeof selector !== "string" ) {
+		return results;
+	}
+
+	var m, set, checkSet, extra, ret, cur, pop, i,
+		prune = true,
+		contextXML = Sizzle.isXML( context ),
+		parts = [],
+		soFar = selector;
+	
+	// Reset the position of the chunker regexp (start from head)
+	do {
+		chunker.exec( "" );
+		m = chunker.exec( soFar );
+
+		if ( m ) {
+			soFar = m[3];
+		
+			parts.push( m[1] );
+		
+			if ( m[2] ) {
+				extra = m[3];
+				break;
+			}
+		}
+	} while ( m );
+
+	if ( parts.length > 1 && origPOS.exec( selector ) ) {
+
+		if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
+			set = posProcess( parts[0] + parts[1], context );
+
+		} else {
+			set = Expr.relative[ parts[0] ] ?
+				[ context ] :
+				Sizzle( parts.shift(), context );
+
+			while ( parts.length ) {
+				selector = parts.shift();
+
+				if ( Expr.relative[ selector ] ) {
+					selector += parts.shift();
+				}
+				
+				set = posProcess( selector, set );
+			}
+		}
+
+	} else {
+		// Take a shortcut and set the context if the root selector is an ID
+		// (but not if it'll be faster if the inner selector is an ID)
+		if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
+				Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
+
+			ret = Sizzle.find( parts.shift(), context, contextXML );
+			context = ret.expr ?
+				Sizzle.filter( ret.expr, ret.set )[0] :
+				ret.set[0];
+		}
+
+		if ( context ) {
+			ret = seed ?
+				{ expr: parts.pop(), set: makeArray(seed) } :
+				Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
+
+			set = ret.expr ?
+				Sizzle.filter( ret.expr, ret.set ) :
+				ret.set;
+
+			if ( parts.length > 0 ) {
+				checkSet = makeArray( set );
+
+			} else {
+				prune = false;
+			}
+
+			while ( parts.length ) {
+				cur = parts.pop();
+				pop = cur;
+
+				if ( !Expr.relative[ cur ] ) {
+					cur = "";
+				} else {
+					pop = parts.pop();
+				}
+
+				if ( pop == null ) {
+					pop = context;
+				}
+
+				Expr.relative[ cur ]( checkSet, pop, contextXML );
+			}
+
+		} else {
+			checkSet = parts = [];
+		}
+	}
+
+	if ( !checkSet ) {
+		checkSet = set;
+	}
+
+	if ( !checkSet ) {
+		Sizzle.error( cur || selector );
+	}
+
+	if ( toString.call(checkSet) === "[object Array]" ) {
+		if ( !prune ) {
+			results.push.apply( results, checkSet );
+
+		} else if ( context && context.nodeType === 1 ) {
+			for ( i = 0; checkSet[i] != null; i++ ) {
+				if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
+					results.push( set[i] );
+				}
+			}
+
+		} else {
+			for ( i = 0; checkSet[i] != null; i++ ) {
+				if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
+					results.push( set[i] );
+				}
+			}
+		}
+
+	} else {
+		makeArray( checkSet, results );
+	}
+
+	if ( extra ) {
+		Sizzle( extra, origContext, results, seed );
+		Sizzle.uniqueSort( results );
+	}
+
+	return results;
+};
+
+Sizzle.uniqueSort = function( results ) {
+	if ( sortOrder ) {
+		hasDuplicate = baseHasDuplicate;
+		results.sort( sortOrder );
+
+		if ( hasDuplicate ) {
+			for ( var i = 1; i < results.length; i++ ) {
+				if ( results[i] === results[ i - 1 ] ) {
+					results.splice( i--, 1 );
+				}
+			}
+		}
+	}
+
+	return results;
+};
+
+Sizzle.matches = function( expr, set ) {
+	return Sizzle( expr, null, null, set );
+};
+
+Sizzle.matchesSelector = function( node, expr ) {
+	return Sizzle( expr, null, null, [node] ).length > 0;
+};
+
+Sizzle.find = function( expr, context, isXML ) {
+	var set;
+
+	if ( !expr ) {
+		return [];
+	}
+
+	for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
+		var match,
+			type = Expr.order[i];
+		
+		if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
+			var left = match[1];
+			match.splice( 1, 1 );
+
+			if ( left.substr( left.length - 1 ) !== "\\" ) {
+				match[1] = (match[1] || "").replace(/\\/g, "");
+				set = Expr.find[ type ]( match, context, isXML );
+
+				if ( set != null ) {
+					expr = expr.replace( Expr.match[ type ], "" );
+					break;
+				}
+			}
+		}
+	}
+
+	if ( !set ) {
+		set = context.getElementsByTagName( "*" );
+	}
+
+	return { set: set, expr: expr };
+};
+
+Sizzle.filter = function( expr, set, inplace, not ) {
+	var match, anyFound,
+		old = expr,
+		result = [],
+		curLoop = set,
+		isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
+
+	while ( expr && set.length ) {
+		for ( var type in Expr.filter ) {
+			if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
+				var found, item,
+					filter = Expr.filter[ type ],
+					left = match[1];
+
+				anyFound = false;
+
+				match.splice(1,1);
+
+				if ( left.substr( left.length - 1 ) === "\\" ) {
+					continue;
+				}
+
+				if ( curLoop === result ) {
+					result = [];
+				}
+
+				if ( Expr.preFilter[ type ] ) {
+					match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
+
+					if ( !match ) {
+						anyFound = found = true;
+
+					} else if ( match === true ) {
+						continue;
+					}
+				}
+
+				if ( match ) {
+					for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
+						if ( item ) {
+							found = filter( item, match, i, curLoop );
+							var pass = not ^ !!found;
+
+							if ( inplace && found != null ) {
+								if ( pass ) {
+									anyFound = true;
+
+								} else {
+									curLoop[i] = false;
+								}
+
+							} else if ( pass ) {
+								result.push( item );
+								anyFound = true;
+							}
+						}
+					}
+				}
+
+				if ( found !== undefined ) {
+					if ( !inplace ) {
+						curLoop = result;
+					}
+
+					expr = expr.replace( Expr.match[ type ], "" );
+
+					if ( !anyFound ) {
+						return [];
+					}
+
+					break;
+				}
+			}
+		}
+
+		// Improper expression
+		if ( expr === old ) {
+			if ( anyFound == null ) {
+				Sizzle.error( expr );
+
+			} else {
+				break;
+			}
+		}
+
+		old = expr;
+	}
+
+	return curLoop;
+};
+
+Sizzle.error = function( msg ) {
+	throw "Syntax error, unrecognized expression: " + msg;
+};
+
+var Expr = Sizzle.selectors = {
+	order: [ "ID", "NAME", "TAG" ],
+
+	match: {
+		ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
+		CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
+		NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
+		ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
+		TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
+		CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+\-]*)\))?/,
+		POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
+		PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
+	},
+
+	leftMatch: {},
+
+	attrMap: {
+		"class": "className",
+		"for": "htmlFor"
+	},
+
+	attrHandle: {
+		href: function( elem ) {
+			return elem.getAttribute( "href" );
+		}
+	},
+
+	relative: {
+		"+": function(checkSet, part){
+			var isPartStr = typeof part === "string",
+				isTag = isPartStr && !/\W/.test( part ),
+				isPartStrNotTag = isPartStr && !isTag;
+
+			if ( isTag ) {
+				part = part.toLowerCase();
+			}
+
+			for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
+				if ( (elem = checkSet[i]) ) {
+					while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
+
+					checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
+						elem || false :
+						elem === part;
+				}
+			}
+
+			if ( isPartStrNotTag ) {
+				Sizzle.filter( part, checkSet, true );
+			}
+		},
+
+		">": function( checkSet, part ) {
+			var elem,
+				isPartStr = typeof part === "string",
+				i = 0,
+				l = checkSet.length;
+
+			if ( isPartStr && !/\W/.test( part ) ) {
+				part = part.toLowerCase();
+
+				for ( ; i < l; i++ ) {
+					elem = checkSet[i];
+
+					if ( elem ) {
+						var parent = elem.parentNode;
+						checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
+					}
+				}
+
+			} else {
+				for ( ; i < l; i++ ) {
+					elem = checkSet[i];
+
+					if ( elem ) {
+						checkSet[i] = isPartStr ?
+							elem.parentNode :
+							elem.parentNode === part;
+					}
+				}
+
+				if ( isPartStr ) {
+					Sizzle.filter( part, checkSet, true );
+				}
+			}
+		},
+
+		"": function(checkSet, part, isXML){
+			var nodeCheck,
+				doneName = done++,
+				checkFn = dirCheck;
+
+			if ( typeof part === "string" && !/\W/.test(part) ) {
+				part = part.toLowerCase();
+				nodeCheck = part;
+				checkFn = dirNodeCheck;
+			}
+
+			checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
+		},
+
+		"~": function( checkSet, part, isXML ) {
+			var nodeCheck,
+				doneName = done++,
+				checkFn = dirCheck;
+
+			if ( typeof part === "string" && !/\W/.test( part ) ) {
+				part = part.toLowerCase();
+				nodeCheck = part;
+				checkFn = dirNodeCheck;
+			}
+
+			checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
+		}
+	},
+
+	find: {
+		ID: function( match, context, isXML ) {
+			if ( typeof context.getElementById !== "undefined" && !isXML ) {
+				var m = context.getElementById(match[1]);
+				// Check parentNode to catch when Blackberry 4.6 returns
+				// nodes that are no longer in the document #6963
+				return m && m.parentNode ? [m] : [];
+			}
+		},
+
+		NAME: function( match, context ) {
+			if ( typeof context.getElementsByName !== "undefined" ) {
+				var ret = [],
+					results = context.getElementsByName( match[1] );
+
+				for ( var i = 0, l = results.length; i < l; i++ ) {
+					if ( results[i].getAttribute("name") === match[1] ) {
+						ret.push( results[i] );
+					}
+				}
+
+				return ret.length === 0 ? null : ret;
+			}
+		},
+
+		TAG: function( match, context ) {
+			return context.getElementsByTagName( match[1] );
+		}
+	},
+	preFilter: {
+		CLASS: function( match, curLoop, inplace, result, not, isXML ) {
+			match = " " + match[1].replace(/\\/g, "") + " ";
+
+			if ( isXML ) {
+				return match;
+			}
+
+			for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
+				if ( elem ) {
+					if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) {
+						if ( !inplace ) {
+							result.push( elem );
+						}
+
+					} else if ( inplace ) {
+						curLoop[i] = false;
+					}
+				}
+			}
+
+			return false;
+		},
+
+		ID: function( match ) {
+			return match[1].replace(/\\/g, "");
+		},
+
+		TAG: function( match, curLoop ) {
+			return match[1].toLowerCase();
+		},
+
+		CHILD: function( match ) {
+			if ( match[1] === "nth" ) {
+				// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
+				var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
+					match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
+					!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
+
+				// calculate the numbers (first)n+(last) including if they are negative
+				match[2] = (test[1] + (test[2] || 1)) - 0;
+				match[3] = test[3] - 0;
+			}
+
+			// TODO: Move to normal caching system
+			match[0] = done++;
+
+			return match;
+		},
+
+		ATTR: function( match, curLoop, inplace, result, not, isXML ) {
+			var name = match[1].replace(/\\/g, "");
+			
+			if ( !isXML && Expr.attrMap[name] ) {
+				match[1] = Expr.attrMap[name];
+			}
+
+			if ( match[2] === "~=" ) {
+				match[4] = " " + match[4] + " ";
+			}
+
+			return match;
+		},
+
+		PSEUDO: function( match, curLoop, inplace, result, not ) {
+			if ( match[1] === "not" ) {
+				// If we're dealing with a complex expression, or a simple one
+				if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
+					match[3] = Sizzle(match[3], null, null, curLoop);
+
+				} else {
+					var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
+
+					if ( !inplace ) {
+						result.push.apply( result, ret );
+					}
+
+					return false;
+				}
+
+			} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
+				return true;
+			}
+			
+			return match;
+		},
+
+		POS: function( match ) {
+			match.unshift( true );
+
+			return match;
+		}
+	},
+	
+	filters: {
+		enabled: function( elem ) {
+			return elem.disabled === false && elem.type !== "hidden";
+		},
+
+		disabled: function( elem ) {
+			return elem.disabled === true;
+		},
+
+		checked: function( elem ) {
+			return elem.checked === true;
+		},
+		
+		selected: function( elem ) {
+			// Accessing this property makes selected-by-default
+			// options in Safari work properly
+			elem.parentNode.selectedIndex;
+			
+			return elem.selected === true;
+		},
+
+		parent: function( elem ) {
+			return !!elem.firstChild;
+		},
+
+		empty: function( elem ) {
+			return !elem.firstChild;
+		},
+
+		has: function( elem, i, match ) {
+			return !!Sizzle( match[3], elem ).length;
+		},
+
+		header: function( elem ) {
+			return (/h\d/i).test( elem.nodeName );
+		},
+
+		text: function( elem ) {
+			return "text" === elem.type;
+		},
+		radio: function( elem ) {
+			return "radio" === elem.type;
+		},
+
+		checkbox: function( elem ) {
+			return "checkbox" === elem.type;
+		},
+
+		file: function( elem ) {
+			return "file" === elem.type;
+		},
+		password: function( elem ) {
+			return "password" === elem.type;
+		},
+
+		submit: function( elem ) {
+			return "submit" === elem.type;
+		},
+
+		image: function( elem ) {
+			return "image" === elem.type;
+		},
+
+		reset: function( elem ) {
+			return "reset" === elem.type;
+		},
+
+		button: function( elem ) {
+			return "button" === elem.type || elem.nodeName.toLowerCase() === "button";
+		},
+
+		input: function( elem ) {
+			return (/input|select|textarea|button/i).test( elem.nodeName );
+		}
+	},
+	setFilters: {
+		first: function( elem, i ) {
+			return i === 0;
+		},
+
+		last: function( elem, i, match, array ) {
+			return i === array.length - 1;
+		},
+
+		even: function( elem, i ) {
+			return i % 2 === 0;
+		},
+
+		odd: function( elem, i ) {
+			return i % 2 === 1;
+		},
+
+		lt: function( elem, i, match ) {
+			return i < match[3] - 0;
+		},
+
+		gt: function( elem, i, match ) {
+			return i > match[3] - 0;
+		},
+
+		nth: function( elem, i, match ) {
+			return match[3] - 0 === i;
+		},
+
+		eq: function( elem, i, match ) {
+			return match[3] - 0 === i;
+		}
+	},
+	filter: {
+		PSEUDO: function( elem, match, i, array ) {
+			var name = match[1],
+				filter = Expr.filters[ name ];
+
+			if ( filter ) {
+				return filter( elem, i, match, array );
+
+			} else if ( name === "contains" ) {
+				return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0;
+
+			} else if ( name === "not" ) {
+				var not = match[3];
+
+				for ( var j = 0, l = not.length; j < l; j++ ) {
+					if ( not[j] === elem ) {
+						return false;
+					}
+				}
+
+				return true;
+
+			} else {
+				Sizzle.error( "Syntax error, unrecognized expression: " + name );
+			}
+		},
+
+		CHILD: function( elem, match ) {
+			var type = match[1],
+				node = elem;
+
+			switch ( type ) {
+				case "only":
+				case "first":
+					while ( (node = node.previousSibling) )	 {
+						if ( node.nodeType === 1 ) { 
+							return false; 
+						}
+					}
+
+					if ( type === "first" ) { 
+						return true; 
+					}
+
+					node = elem;
+
+				case "last":
+					while ( (node = node.nextSibling) )	 {
+						if ( node.nodeType === 1 ) { 
+							return false; 
+						}
+					}
+
+					return true;
+
+				case "nth":
+					var first = match[2],
+						last = match[3];
+
+					if ( first === 1 && last === 0 ) {
+						return true;
+					}
+					
+					var doneName = match[0],
+						parent = elem.parentNode;
+	
+					if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
+						var count = 0;
+						
+						for ( node = parent.firstChild; node; node = node.nextSibling ) {
+							if ( node.nodeType === 1 ) {
+								node.nodeIndex = ++count;
+							}
+						} 
+
+						parent.sizcache = doneName;
+					}
+					
+					var diff = elem.nodeIndex - last;
+
+					if ( first === 0 ) {
+						return diff === 0;
+
+					} else {
+						return ( diff % first === 0 && diff / first >= 0 );
+					}
+			}
+		},
+
+		ID: function( elem, match ) {
+			return elem.nodeType === 1 && elem.getAttribute("id") === match;
+		},
+
+		TAG: function( elem, match ) {
+			return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;
+		},
+		
+		CLASS: function( elem, match ) {
+			return (" " + (elem.className || elem.getAttribute("class")) + " ")
+				.indexOf( match ) > -1;
+		},
+
+		ATTR: function( elem, match ) {
+			var name = match[1],
+				result = Expr.attrHandle[ name ] ?
+					Expr.attrHandle[ name ]( elem ) :
+					elem[ name ] != null ?
+						elem[ name ] :
+						elem.getAttribute( name ),
+				value = result + "",
+				type = match[2],
+				check = match[4];
+
+			return result == null ?
+				type === "!=" :
+				type === "=" ?
+				value === check :
+				type === "*=" ?
+				value.indexOf(check) >= 0 :
+				type === "~=" ?
+				(" " + value + " ").indexOf(check) >= 0 :
+				!check ?
+				value && result !== false :
+				type === "!=" ?
+				value !== check :
+				type === "^=" ?
+				value.indexOf(check) === 0 :
+				type === "$=" ?
+				value.substr(value.length - check.length) === check :
+				type === "|=" ?
+				value === check || value.substr(0, check.length + 1) === check + "-" :
+				false;
+		},
+
+		POS: function( elem, match, i, array ) {
+			var name = match[2],
+				filter = Expr.setFilters[ name ];
+
+			if ( filter ) {
+				return filter( elem, i, match, array );
+			}
+		}
+	}
+};
+
+var origPOS = Expr.match.POS,
+	fescape = function(all, num){
+		return "\\" + (num - 0 + 1);
+	};
+
+for ( var type in Expr.match ) {
+	Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
+	Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
+}
+
+var makeArray = function( array, results ) {
+	array = Array.prototype.slice.call( array, 0 );
+
+	if ( results ) {
+		results.push.apply( results, array );
+		return results;
+	}
+	
+	return array;
+};
+
+// Perform a simple check to determine if the browser is capable of
+// converting a NodeList to an array using builtin methods.
+// Also verifies that the returned array holds DOM nodes
+// (which is not the case in the Blackberry browser)
+try {
+	Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
+
+// Provide a fallback method if it does not work
+} catch( e ) {
+	makeArray = function( array, results ) {
+		var i = 0,
+			ret = results || [];
+
+		if ( toString.call(array) === "[object Array]" ) {
+			Array.prototype.push.apply( ret, array );
+
+		} else {
+			if ( typeof array.length === "number" ) {
+				for ( var l = array.length; i < l; i++ ) {
+					ret.push( array[i] );
+				}
+
+			} else {
+				for ( ; array[i]; i++ ) {
+					ret.push( array[i] );
+				}
+			}
+		}
+
+		return ret;
+	};
+}
+
+var sortOrder, siblingCheck;
+
+if ( document.documentElement.compareDocumentPosition ) {
+	sortOrder = function( a, b ) {
+		if ( a === b ) {
+			hasDuplicate = true;
+			return 0;
+		}
+
+		if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
+			return a.compareDocumentPosition ? -1 : 1;
+		}
+
+		return a.compareDocumentPosition(b) & 4 ? -1 : 1;
+	};
+
+} else {
+	sortOrder = function( a, b ) {
+		var al, bl,
+			ap = [],
+			bp = [],
+			aup = a.parentNode,
+			bup = b.parentNode,
+			cur = aup;
+
+		// The nodes are identical, we can exit early
+		if ( a === b ) {
+			hasDuplicate = true;
+			return 0;
+
+		// If the nodes are siblings (or identical) we can do a quick check
+		} else if ( aup === bup ) {
+			return siblingCheck( a, b );
+
+		// If no parents were found then the nodes are disconnected
+		} else if ( !aup ) {
+			return -1;
+
+		} else if ( !bup ) {
+			return 1;
+		}
+
+		// Otherwise they're somewhere else in the tree so we need
+		// to build up a full list of the parentNodes for comparison
+		while ( cur ) {
+			ap.unshift( cur );
+			cur = cur.parentNode;
+		}
+
+		cur = bup;
+
+		while ( cur ) {
+			bp.unshift( cur );
+			cur = cur.parentNode;
+		}
+
+		al = ap.length;
+		bl = bp.length;
+
+		// Start walking down the tree looking for a discrepancy
+		for ( var i = 0; i < al && i < bl; i++ ) {
+			if ( ap[i] !== bp[i] ) {
+				return siblingCheck( ap[i], bp[i] );
+			}
+		}
+
+		// We ended someplace up the tree so do a sibling check
+		return i === al ?
+			siblingCheck( a, bp[i], -1 ) :
+			siblingCheck( ap[i], b, 1 );
+	};
+
+	siblingCheck = function( a, b, ret ) {
+		if ( a === b ) {
+			return ret;
+		}
+
+		var cur = a.nextSibling;
+
+		while ( cur ) {
+			if ( cur === b ) {
+				return -1;
+			}
+
+			cur = cur.nextSibling;
+		}
+
+		return 1;
+	};
+}
+
+// Utility function for retreiving the text value of an array of DOM nodes
+Sizzle.getText = function( elems ) {
+	var ret = "", elem;
+
+	for ( var i = 0; elems[i]; i++ ) {
+		elem = elems[i];
+
+		// Get the text from text nodes and CDATA nodes
+		if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
+			ret += elem.nodeValue;
+
+		// Traverse everything else, except comment nodes
+		} else if ( elem.nodeType !== 8 ) {
+			ret += Sizzle.getText( elem.childNodes );
+		}
+	}
+
+	return ret;
+};
+
+// Check to see if the browser returns elements by name when
+// querying by getElementById (and provide a workaround)
+(function(){
+	// We're going to inject a fake input element with a specified name
+	var form = document.createElement("div"),
+		id = "script" + (new Date()).getTime(),
+		root = document.documentElement;
+
+	form.innerHTML = "<a name='" + id + "'/>";
+
+	// Inject it into the root element, check its status, and remove it quickly
+	root.insertBefore( form, root.firstChild );
+
+	// The workaround has to do additional checks after a getElementById
+	// Which slows things down for other browsers (hence the branching)
+	if ( document.getElementById( id ) ) {
+		Expr.find.ID = function( match, context, isXML ) {
+			if ( typeof context.getElementById !== "undefined" && !isXML ) {
+				var m = context.getElementById(match[1]);
+
+				return m ?
+					m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
+						[m] :
+						undefined :
+					[];
+			}
+		};
+
+		Expr.filter.ID = function( elem, match ) {
+			var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
+
+			return elem.nodeType === 1 && node && node.nodeValue === match;
+		};
+	}
+
+	root.removeChild( form );
+
+	// release memory in IE
+	root = form = null;
+})();
+
+(function(){
+	// Check to see if the browser returns only elements
+	// when doing getElementsByTagName("*")
+
+	// Create a fake element
+	var div = document.createElement("div");
+	div.appendChild( document.createComment("") );
+
+	// Make sure no comments are found
+	if ( div.getElementsByTagName("*").length > 0 ) {
+		Expr.find.TAG = function( match, context ) {
+			var results = context.getElementsByTagName( match[1] );
+
+			// Filter out possible comments
+			if ( match[1] === "*" ) {
+				var tmp = [];
+
+				for ( var i = 0; results[i]; i++ ) {
+					if ( results[i].nodeType === 1 ) {
+						tmp.push( results[i] );
+					}
+				}
+
+				results = tmp;
+			}
+
+			return results;
+		};
+	}
+
+	// Check to see if an attribute returns normalized href attributes
+	div.innerHTML = "<a href='#'></a>";
+
+	if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
+			div.firstChild.getAttribute("href") !== "#" ) {
+
+		Expr.attrHandle.href = function( elem ) {
+			return elem.getAttribute( "href", 2 );
+		};
+	}
+
+	// release memory in IE
+	div = null;
+})();
+
+if ( document.querySelectorAll ) {
+	(function(){
+		var oldSizzle = Sizzle,
+			div = document.createElement("div"),
+			id = "__sizzle__";
+
+		div.innerHTML = "<p class='TEST'></p>";
+
+		// Safari can't handle uppercase or unicode characters when
+		// in quirks mode.
+		if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
+			return;
+		}
+	
+		Sizzle = function( query, context, extra, seed ) {
+			context = context || document;
+
+			// Make sure that attribute selectors are quoted
+			query = query.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
+
+			// Only use querySelectorAll on non-XML documents
+			// (ID selectors don't work in non-HTML documents)
+			if ( !seed && !Sizzle.isXML(context) ) {
+				if ( context.nodeType === 9 ) {
+					try {
+						return makeArray( context.querySelectorAll(query), extra );
+					} catch(qsaError) {}
+
+				// qSA works strangely on Element-rooted queries
+				// We can work around this by specifying an extra ID on the root
+				// and working up from there (Thanks to Andrew Dupont for the technique)
+				// IE 8 doesn't work on object elements
+				} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
+					var old = context.getAttribute( "id" ),
+						nid = old || id;
+
+					if ( !old ) {
+						context.setAttribute( "id", nid );
+					}
+
+					try {
+						return makeArray( context.querySelectorAll( "#" + nid + " " + query ), extra );
+
+					} catch(pseudoError) {
+					} finally {
+						if ( !old ) {
+							context.removeAttribute( "id" );
+						}
+					}
+				}
+			}
+		
+			return oldSizzle(query, context, extra, seed);
+		};
+
+		for ( var prop in oldSizzle ) {
+			Sizzle[ prop ] = oldSizzle[ prop ];
+		}
+
+		// release memory in IE
+		div = null;
+	})();
+}
+
+(function(){
+	var html = document.documentElement,
+		matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector,
+		pseudoWorks = false;
+
+	try {
+		// This should fail with an exception
+		// Gecko does not error, returns false instead
+		matches.call( document.documentElement, "[test!='']:sizzle" );
+	
+	} catch( pseudoError ) {
+		pseudoWorks = true;
+	}
+
+	if ( matches ) {
+		Sizzle.matchesSelector = function( node, expr ) {
+			// Make sure that attribute selectors are quoted
+			expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
+
+			if ( !Sizzle.isXML( node ) ) {
+				try { 
+					if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
+						return matches.call( node, expr );
+					}
+				} catch(e) {}
+			}
+
+			return Sizzle(expr, null, null, [node]).length > 0;
+		};
+	}
+})();
+
+(function(){
+	var div = document.createElement("div");
+
+	div.innerHTML = "<div class='test e'></div><div class='test'></div>";
+
+	// Opera can't find a second classname (in 9.6)
+	// Also, make sure that getElementsByClassName actually exists
+	if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
+		return;
+	}
+
+	// Safari caches class attributes, doesn't catch changes (in 3.2)
+	div.lastChild.className = "e";
+
+	if ( div.getElementsByClassName("e").length === 1 ) {
+		return;
+	}
+	
+	Expr.order.splice(1, 0, "CLASS");
+	Expr.find.CLASS = function( match, context, isXML ) {
+		if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
+			return context.getElementsByClassName(match[1]);
+		}
+	};
+
+	// release memory in IE
+	div = null;
+})();
+
+function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+		var elem = checkSet[i];
+
+		if ( elem ) {
+			var match = false;
+
+			elem = elem[dir];
+
+			while ( elem ) {
+				if ( elem.sizcache === doneName ) {
+					match = checkSet[elem.sizset];
+					break;
+				}
+
+				if ( elem.nodeType === 1 && !isXML ){
+					elem.sizcache = doneName;
+					elem.sizset = i;
+				}
+
+				if ( elem.nodeName.toLowerCase() === cur ) {
+					match = elem;
+					break;
+				}
+
+				elem = elem[dir];
+			}
+
+			checkSet[i] = match;
+		}
+	}
+}
+
+function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+		var elem = checkSet[i];
+
+		if ( elem ) {
+			var match = false;
+			
+			elem = elem[dir];
+
+			while ( elem ) {
+				if ( elem.sizcache === doneName ) {
+					match = checkSet[elem.sizset];
+					break;
+				}
+
+				if ( elem.nodeType === 1 ) {
+					if ( !isXML ) {
+						elem.sizcache = doneName;
+						elem.sizset = i;
+					}
+
+					if ( typeof cur !== "string" ) {
+						if ( elem === cur ) {
+							match = true;
+							break;
+						}
+
+					} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
+						match = elem;
+						break;
+					}
+				}
+
+				elem = elem[dir];
+			}
+
+			checkSet[i] = match;
+		}
+	}
+}
+
+if ( document.documentElement.contains ) {
+	Sizzle.contains = function( a, b ) {
+		return a !== b && (a.contains ? a.contains(b) : true);
+	};
+
+} else if ( document.documentElement.compareDocumentPosition ) {
+	Sizzle.contains = function( a, b ) {
+		return !!(a.compareDocumentPosition(b) & 16);
+	};
+
+} else {
+	Sizzle.contains = function() {
+		return false;
+	};
+}
+
+Sizzle.isXML = function( elem ) {
+	// documentElement is verified for cases where it doesn't yet exist
+	// (such as loading iframes in IE - #4833) 
+	var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
+
+	return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+var posProcess = function( selector, context ) {
+	var match,
+		tmpSet = [],
+		later = "",
+		root = context.nodeType ? [context] : context;
+
+	// Position selectors must be done after the filter
+	// And so must :not(positional) so we move all PSEUDOs to the end
+	while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
+		later += match[0];
+		selector = selector.replace( Expr.match.PSEUDO, "" );
+	}
+
+	selector = Expr.relative[selector] ? selector + "*" : selector;
+
+	for ( var i = 0, l = root.length; i < l; i++ ) {
+		Sizzle( selector, root[i], tmpSet );
+	}
+
+	return Sizzle.filter( later, tmpSet );
+};
+
+// EXPOSE
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.filters;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+})();
+
+
+var runtil = /Until$/,
+	rparentsprev = /^(?:parents|prevUntil|prevAll)/,
+	// Note: This RegExp should be improved, or likely pulled from Sizzle
+	rmultiselector = /,/,
+	isSimple = /^.[^:#\[\.,]*$/,
+	slice = Array.prototype.slice,
+	POS = jQuery.expr.match.POS;
+
+jQuery.fn.extend({
+	find: function( selector ) {
+		var ret = this.pushStack( "", "find", selector ),
+			length = 0;
+
+		for ( var i = 0, l = this.length; i < l; i++ ) {
+			length = ret.length;
+			jQuery.find( selector, this[i], ret );
+
+			if ( i > 0 ) {
+				// Make sure that the results are unique
+				for ( var n = length; n < ret.length; n++ ) {
+					for ( var r = 0; r < length; r++ ) {
+						if ( ret[r] === ret[n] ) {
+							ret.splice(n--, 1);
+							break;
+						}
+					}
+				}
+			}
+		}
+
+		return ret;
+	},
+
+	has: function( target ) {
+		var targets = jQuery( target );
+		return this.filter(function() {
+			for ( var i = 0, l = targets.length; i < l; i++ ) {
+				if ( jQuery.contains( this, targets[i] ) ) {
+					return true;
+				}
+			}
+		});
+	},
+
+	not: function( selector ) {
+		return this.pushStack( winnow(this, selector, false), "not", selector);
+	},
+
+	filter: function( selector ) {
+		return this.pushStack( winnow(this, selector, true), "filter", selector );
+	},
+	
+	is: function( selector ) {
+		return !!selector && jQuery.filter( selector, this ).length > 0;
+	},
+
+	closest: function( selectors, context ) {
+		var ret = [], i, l, cur = this[0];
+
+		if ( jQuery.isArray( selectors ) ) {
+			var match, selector,
+				matches = {},
+				level = 1;
+
+			if ( cur && selectors.length ) {
+				for ( i = 0, l = selectors.length; i < l; i++ ) {
+					selector = selectors[i];
+
+					if ( !matches[selector] ) {
+						matches[selector] = jQuery.expr.match.POS.test( selector ) ? 
+							jQuery( selector, context || this.context ) :
+							selector;
+					}
+				}
+
+				while ( cur && cur.ownerDocument && cur !== context ) {
+					for ( selector in matches ) {
+						match = matches[selector];
+
+						if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) {
+							ret.push({ selector: selector, elem: cur, level: level });
+						}
+					}
+
+					cur = cur.parentNode;
+					level++;
+				}
+			}
+
+			return ret;
+		}
+
+		var pos = POS.test( selectors ) ? 
+			jQuery( selectors, context || this.context ) : null;
+
+		for ( i = 0, l = this.length; i < l; i++ ) {
+			cur = this[i];
+
+			while ( cur ) {
+				if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
+					ret.push( cur );
+					break;
+
+				} else {
+					cur = cur.parentNode;
+					if ( !cur || !cur.ownerDocument || cur === context ) {
+						break;
+					}
+				}
+			}
+		}
+
+		ret = ret.length > 1 ? jQuery.unique(ret) : ret;
+		
+		return this.pushStack( ret, "closest", selectors );
+	},
+	
+	// Determine the position of an element within
+	// the matched set of elements
+	index: function( elem ) {
+		if ( !elem || typeof elem === "string" ) {
+			return jQuery.inArray( this[0],
+				// If it receives a string, the selector is used
+				// If it receives nothing, the siblings are used
+				elem ? jQuery( elem ) : this.parent().children() );
+		}
+		// Locate the position of the desired element
+		return jQuery.inArray(
+			// If it receives a jQuery object, the first element is used
+			elem.jquery ? elem[0] : elem, this );
+	},
+
+	add: function( selector, context ) {
+		var set = typeof selector === "string" ?
+				jQuery( selector, context || this.context ) :
+				jQuery.makeArray( selector ),
+			all = jQuery.merge( this.get(), set );
+
+		return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
+			all :
+			jQuery.unique( all ) );
+	},
+
+	andSelf: function() {
+		return this.add( this.prevObject );
+	}
+});
+
+// A painfully simple check to see if an element is disconnected
+// from a document (should be improved, where feasible).
+function isDisconnected( node ) {
+	return !node || !node.parentNode || node.parentNode.nodeType === 11;
+}
+
+jQuery.each({
+	parent: function( elem ) {
+		var parent = elem.parentNode;
+		return parent && parent.nodeType !== 11 ? parent : null;
+	},
+	parents: function( elem ) {
+		return jQuery.dir( elem, "parentNode" );
+	},
+	parentsUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "parentNode", until );
+	},
+	next: function( elem ) {
+		return jQuery.nth( elem, 2, "nextSibling" );
+	},
+	prev: function( elem ) {
+		return jQuery.nth( elem, 2, "previousSibling" );
+	},
+	nextAll: function( elem ) {
+		return jQuery.dir( elem, "nextSibling" );
+	},
+	prevAll: function( elem ) {
+		return jQuery.dir( elem, "previousSibling" );
+	},
+	nextUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "nextSibling", until );
+	},
+	prevUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "previousSibling", until );
+	},
+	siblings: function( elem ) {
+		return jQuery.sibling( elem.parentNode.firstChild, elem );
+	},
+	children: function( elem ) {
+		return jQuery.sibling( elem.firstChild );
+	},
+	contents: function( elem ) {
+		return jQuery.nodeName( elem, "iframe" ) ?
+			elem.contentDocument || elem.contentWindow.document :
+			jQuery.makeArray( elem.childNodes );
+	}
+}, function( name, fn ) {
+	jQuery.fn[ name ] = function( until, selector ) {
+		var ret = jQuery.map( this, fn, until );
+		
+		if ( !runtil.test( name ) ) {
+			selector = until;
+		}
+
+		if ( selector && typeof selector === "string" ) {
+			ret = jQuery.filter( selector, ret );
+		}
+
+		ret = this.length > 1 ? jQuery.unique( ret ) : ret;
+
+		if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
+			ret = ret.reverse();
+		}
+
+		return this.pushStack( ret, name, slice.call(arguments).join(",") );
+	};
+});
+
+jQuery.extend({
+	filter: function( expr, elems, not ) {
+		if ( not ) {
+			expr = ":not(" + expr + ")";
+		}
+
+		return elems.length === 1 ?
+			jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
+			jQuery.find.matches(expr, elems);
+	},
+	
+	dir: function( elem, dir, until ) {
+		var matched = [],
+			cur = elem[ dir ];
+
+		while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
+			if ( cur.nodeType === 1 ) {
+				matched.push( cur );
+			}
+			cur = cur[dir];
+		}
+		return matched;
+	},
+
+	nth: function( cur, result, dir, elem ) {
+		result = result || 1;
+		var num = 0;
+
+		for ( ; cur; cur = cur[dir] ) {
+			if ( cur.nodeType === 1 && ++num === result ) {
+				break;
+			}
+		}
+
+		return cur;
+	},
+
+	sibling: function( n, elem ) {
+		var r = [];
+
+		for ( ; n; n = n.nextSibling ) {
+			if ( n.nodeType === 1 && n !== elem ) {
+				r.push( n );
+			}
+		}
+
+		return r;
+	}
+});
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, keep ) {
+	if ( jQuery.isFunction( qualifier ) ) {
+		return jQuery.grep(elements, function( elem, i ) {
+			var retVal = !!qualifier.call( elem, i, elem );
+			return retVal === keep;
+		});
+
+	} else if ( qualifier.nodeType ) {
+		return jQuery.grep(elements, function( elem, i ) {
+			return (elem === qualifier) === keep;
+		});
+
+	} else if ( typeof qualifier === "string" ) {
+		var filtered = jQuery.grep(elements, function( elem ) {
+			return elem.nodeType === 1;
+		});
+
+		if ( isSimple.test( qualifier ) ) {
+			return jQuery.filter(qualifier, filtered, !keep);
+		} else {
+			qualifier = jQuery.filter( qualifier, filtered );
+		}
+	}
+
+	return jQuery.grep(elements, function( elem, i ) {
+		return (jQuery.inArray( elem, qualifier ) >= 0) === keep;
+	});
+}
+
+
+
+
+var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
+	rleadingWhitespace = /^\s+/,
+	rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
+	rtagName = /<([\w:]+)/,
+	rtbody = /<tbody/i,
+	rhtml = /<|&#?\w+;/,
+	rnocache = /<(?:script|object|embed|option|style)/i,
+	// checked="checked" or checked (html5)
+	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+	raction = /\=([^="'>\s]+\/)>/g,
+	wrapMap = {
+		option: [ 1, "<select multiple='multiple'>", "</select>" ],
+		legend: [ 1, "<fieldset>", "</fieldset>" ],
+		thead: [ 1, "<table>", "</table>" ],
+		tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+		td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+		col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
+		area: [ 1, "<map>", "</map>" ],
+		_default: [ 0, "", "" ]
+	};
+
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+// IE can't serialize <link> and <script> tags normally
+if ( !jQuery.support.htmlSerialize ) {
+	wrapMap._default = [ 1, "div<div>", "</div>" ];
+}
+
+jQuery.fn.extend({
+	text: function( text ) {
+		if ( jQuery.isFunction(text) ) {
+			return this.each(function(i) {
+				var self = jQuery( this );
+
+				self.text( text.call(this, i, self.text()) );
+			});
+		}
+
+		if ( typeof text !== "object" && text !== undefined ) {
+			return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
+		}
+
+		return jQuery.text( this );
+	},
+
+	wrapAll: function( html ) {
+		if ( jQuery.isFunction( html ) ) {
+			return this.each(function(i) {
+				jQuery(this).wrapAll( html.call(this, i) );
+			});
+		}
+
+		if ( this[0] ) {
+			// The elements to wrap the target around
+			var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
+
+			if ( this[0].parentNode ) {
+				wrap.insertBefore( this[0] );
+			}
+
+			wrap.map(function() {
+				var elem = this;
+
+				while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
+					elem = elem.firstChild;
+				}
+
+				return elem;
+			}).append(this);
+		}
+
+		return this;
+	},
+
+	wrapInner: function( html ) {
+		if ( jQuery.isFunction( html ) ) {
+			return this.each(function(i) {
+				jQuery(this).wrapInner( html.call(this, i) );
+			});
+		}
+
+		return this.each(function() {
+			var self = jQuery( this ),
+				contents = self.contents();
+
+			if ( contents.length ) {
+				contents.wrapAll( html );
+
+			} else {
+				self.append( html );
+			}
+		});
+	},
+
+	wrap: function( html ) {
+		return this.each(function() {
+			jQuery( this ).wrapAll( html );
+		});
+	},
+
+	unwrap: function() {
+		return this.parent().each(function() {
+			if ( !jQuery.nodeName( this, "body" ) ) {
+				jQuery( this ).replaceWith( this.childNodes );
+			}
+		}).end();
+	},
+
+	append: function() {
+		return this.domManip(arguments, true, function( elem ) {
+			if ( this.nodeType === 1 ) {
+				this.appendChild( elem );
+			}
+		});
+	},
+
+	prepend: function() {
+		return this.domManip(arguments, true, function( elem ) {
+			if ( this.nodeType === 1 ) {
+				this.insertBefore( elem, this.firstChild );
+			}
+		});
+	},
+
+	before: function() {
+		if ( this[0] && this[0].parentNode ) {
+			return this.domManip(arguments, false, function( elem ) {
+				this.parentNode.insertBefore( elem, this );
+			});
+		} else if ( arguments.length ) {
+			var set = jQuery(arguments[0]);
+			set.push.apply( set, this.toArray() );
+			return this.pushStack( set, "before", arguments );
+		}
+	},
+
+	after: function() {
+		if ( this[0] && this[0].parentNode ) {
+			return this.domManip(arguments, false, function( elem ) {
+				this.parentNode.insertBefore( elem, this.nextSibling );
+			});
+		} else if ( arguments.length ) {
+			var set = this.pushStack( this, "after", arguments );
+			set.push.apply( set, jQuery(arguments[0]).toArray() );
+			return set;
+		}
+	},
+	
+	// keepData is for internal use only--do not document
+	remove: function( selector, keepData ) {
+		for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
+			if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
+				if ( !keepData && elem.nodeType === 1 ) {
+					jQuery.cleanData( elem.getElementsByTagName("*") );
+					jQuery.cleanData( [ elem ] );
+				}
+
+				if ( elem.parentNode ) {
+					 elem.parentNode.removeChild( elem );
+				}
+			}
+		}
+		
+		return this;
+	},
+
+	empty: function() {
+		for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
+			// Remove element nodes and prevent memory leaks
+			if ( elem.nodeType === 1 ) {
+				jQuery.cleanData( elem.getElementsByTagName("*") );
+			}
+
+			// Remove any remaining nodes
+			while ( elem.firstChild ) {
+				elem.removeChild( elem.firstChild );
+			}
+		}
+		
+		return this;
+	},
+
+	clone: function( events ) {
+		// Do the clone
+		var ret = this.map(function() {
+			if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
+				// IE copies events bound via attachEvent when
+				// using cloneNode. Calling detachEvent on the
+				// clone will also remove the events from the orignal
+				// In order to get around this, we use innerHTML.
+				// Unfortunately, this means some modifications to
+				// attributes in IE that are actually only stored
+				// as properties will not be copied (such as the
+				// the name attribute on an input).
+				var html = this.outerHTML,
+					ownerDocument = this.ownerDocument;
+
+				if ( !html ) {
+					var div = ownerDocument.createElement("div");
+					div.appendChild( this.cloneNode(true) );
+					html = div.innerHTML;
+				}
+
+				return jQuery.clean([html.replace(rinlinejQuery, "")
+					// Handle the case in IE 8 where action=/test/> self-closes a tag
+					.replace(raction, '="$1">')
+					.replace(rleadingWhitespace, "")], ownerDocument)[0];
+			} else {
+				return this.cloneNode(true);
+			}
+		});
+
+		// Copy the events from the original to the clone
+		if ( events === true ) {
+			cloneCopyEvent( this, ret );
+			cloneCopyEvent( this.find("*"), ret.find("*") );
+		}
+
+		// Return the cloned set
+		return ret;
+	},
+
+	html: function( value ) {
+		if ( value === undefined ) {
+			return this[0] && this[0].nodeType === 1 ?
+				this[0].innerHTML.replace(rinlinejQuery, "") :
+				null;
+
+		// See if we can take a shortcut and just use innerHTML
+		} else if ( typeof value === "string" && !rnocache.test( value ) &&
+			(jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
+			!wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
+
+			value = value.replace(rxhtmlTag, "<$1></$2>");
+
+			try {
+				for ( var i = 0, l = this.length; i < l; i++ ) {
+					// Remove element nodes and prevent memory leaks
+					if ( this[i].nodeType === 1 ) {
+						jQuery.cleanData( this[i].getElementsByTagName("*") );
+						this[i].innerHTML = value;
+					}
+				}
+
+			// If using innerHTML throws an exception, use the fallback method
+			} catch(e) {
+				this.empty().append( value );
+			}
+
+		} else if ( jQuery.isFunction( value ) ) {
+			this.each(function(i){
+				var self = jQuery( this );
+
+				self.html( value.call(this, i, self.html()) );
+			});
+
+		} else {
+			this.empty().append( value );
+		}
+
+		return this;
+	},
+
+	replaceWith: function( value ) {
+		if ( this[0] && this[0].parentNode ) {
+			// Make sure that the elements are removed from the DOM before they are inserted
+			// this can help fix replacing a parent with child elements
+			if ( jQuery.isFunction( value ) ) {
+				return this.each(function(i) {
+					var self = jQuery(this), old = self.html();
+					self.replaceWith( value.call( this, i, old ) );
+				});
+			}
+
+			if ( typeof value !== "string" ) {
+				value = jQuery( value ).detach();
+			}
+
+			return this.each(function() {
+				var next = this.nextSibling,
+					parent = this.parentNode;
+
+				jQuery( this ).remove();
+
+				if ( next ) {
+					jQuery(next).before( value );
+				} else {
+					jQuery(parent).append( value );
+				}
+			});
+		} else {
+			return this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value );
+		}
+	},
+
+	detach: function( selector ) {
+		return this.remove( selector, true );
+	},
+
+	domManip: function( args, table, callback ) {
+		var results, first, fragment, parent,
+			value = args[0],
+			scripts = [];
+
+		// We can't cloneNode fragments that contain checked, in WebKit
+		if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
+			return this.each(function() {
+				jQuery(this).domManip( args, table, callback, true );
+			});
+		}
+
+		if ( jQuery.isFunction(value) ) {
+			return this.each(function(i) {
+				var self = jQuery(this);
+				args[0] = value.call(this, i, table ? self.html() : undefined);
+				self.domManip( args, table, callback );
+			});
+		}
+
+		if ( this[0] ) {
+			parent = value && value.parentNode;
+
+			// If we're in a fragment, just use that instead of building a new one
+			if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
+				results = { fragment: parent };
+
+			} else {
+				results = jQuery.buildFragment( args, this, scripts );
+			}
+			
+			fragment = results.fragment;
+			
+			if ( fragment.childNodes.length === 1 ) {
+				first = fragment = fragment.firstChild;
+			} else {
+				first = fragment.firstChild;
+			}
+
+			if ( first ) {
+				table = table && jQuery.nodeName( first, "tr" );
+
+				for ( var i = 0, l = this.length; i < l; i++ ) {
+					callback.call(
+						table ?
+							root(this[i], first) :
+							this[i],
+						i > 0 || results.cacheable || this.length > 1  ?
+							fragment.cloneNode(true) :
+							fragment
+					);
+				}
+			}
+
+			if ( scripts.length ) {
+				jQuery.each( scripts, evalScript );
+			}
+		}
+
+		return this;
+	}
+});
+
+function root( elem, cur ) {
+	return jQuery.nodeName(elem, "table") ?
+		(elem.getElementsByTagName("tbody")[0] ||
+		elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
+		elem;
+}
+
+function cloneCopyEvent(orig, ret) {
+	var i = 0;
+
+	ret.each(function() {
+		if ( this.nodeName !== (orig[i] && orig[i].nodeName) ) {
+			return;
+		}
+
+		var oldData = jQuery.data( orig[i++] ),
+			curData = jQuery.data( this, oldData ),
+			events = oldData && oldData.events;
+
+		if ( events ) {
+			delete curData.handle;
+			curData.events = {};
+
+			for ( var type in events ) {
+				for ( var handler in events[ type ] ) {
+					jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
+				}
+			}
+		}
+	});
+}
+
+jQuery.buildFragment = function( args, nodes, scripts ) {
+	var fragment, cacheable, cacheresults,
+		doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);
+
+	// Only cache "small" (1/2 KB) strings that are associated with the main document
+	// Cloning options loses the selected state, so don't cache them
+	// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
+	// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
+	if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document &&
+		!rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {
+
+		cacheable = true;
+		cacheresults = jQuery.fragments[ args[0] ];
+		if ( cacheresults ) {
+			if ( cacheresults !== 1 ) {
+				fragment = cacheresults;
+			}
+		}
+	}
+
+	if ( !fragment ) {
+		fragment = doc.createDocumentFragment();
+		jQuery.clean( args, doc, fragment, scripts );
+	}
+
+	if ( cacheable ) {
+		jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;
+	}
+
+	return { fragment: fragment, cacheable: cacheable };
+};
+
+jQuery.fragments = {};
+
+jQuery.each({
+	appendTo: "append",
+	prependTo: "prepend",
+	insertBefore: "before",
+	insertAfter: "after",
+	replaceAll: "replaceWith"
+}, function( name, original ) {
+	jQuery.fn[ name ] = function( selector ) {
+		var ret = [],
+			insert = jQuery( selector ),
+			parent = this.length === 1 && this[0].parentNode;
+		
+		if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
+			insert[ original ]( this[0] );
+			return this;
+			
+		} else {
+			for ( var i = 0, l = insert.length; i < l; i++ ) {
+				var elems = (i > 0 ? this.clone(true) : this).get();
+				jQuery( insert[i] )[ original ]( elems );
+				ret = ret.concat( elems );
+			}
+		
+			return this.pushStack( ret, name, insert.selector );
+		}
+	};
+});
+
+jQuery.extend({
+	clean: function( elems, context, fragment, scripts ) {
+		context = context || document;
+
+		// !context.createElement fails in IE with an error but returns typeof 'object'
+		if ( typeof context.createElement === "undefined" ) {
+			context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
+		}
+
+		var ret = [];
+
+		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+			if ( typeof elem === "number" ) {
+				elem += "";
+			}
+
+			if ( !elem ) {
+				continue;
+			}
+
+			// Convert html string into DOM nodes
+			if ( typeof elem === "string" && !rhtml.test( elem ) ) {
+				elem = context.createTextNode( elem );
+
+			} else if ( typeof elem === "string" ) {
+				// Fix "XHTML"-style tags in all browsers
+				elem = elem.replace(rxhtmlTag, "<$1></$2>");
+
+				// Trim whitespace, otherwise indexOf won't work as expected
+				var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(),
+					wrap = wrapMap[ tag ] || wrapMap._default,
+					depth = wrap[0],
+					div = context.createElement("div");
+
+				// Go to html and back, then peel off extra wrappers
+				div.innerHTML = wrap[1] + elem + wrap[2];
+
+				// Move to the right depth
+				while ( depth-- ) {
+					div = div.lastChild;
+				}
+
+				// Remove IE's autoinserted <tbody> from table fragments
+				if ( !jQuery.support.tbody ) {
+
+					// String was a <table>, *may* have spurious <tbody>
+					var hasBody = rtbody.test(elem),
+						tbody = tag === "table" && !hasBody ?
+							div.firstChild && div.firstChild.childNodes :
+
+							// String was a bare <thead> or <tfoot>
+							wrap[1] === "<table>" && !hasBody ?
+								div.childNodes :
+								[];
+
+					for ( var j = tbody.length - 1; j >= 0 ; --j ) {
+						if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
+							tbody[ j ].parentNode.removeChild( tbody[ j ] );
+						}
+					}
+
+				}
+
+				// IE completely kills leading whitespace when innerHTML is used
+				if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
+					div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
+				}
+
+				elem = div.childNodes;
+			}
+
+			if ( elem.nodeType ) {
+				ret.push( elem );
+			} else {
+				ret = jQuery.merge( ret, elem );
+			}
+		}
+
+		if ( fragment ) {
+			for ( i = 0; ret[i]; i++ ) {
+				if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
+					scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
+				
+				} else {
+					if ( ret[i].nodeType === 1 ) {
+						ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
+					}
+					fragment.appendChild( ret[i] );
+				}
+			}
+		}
+
+		return ret;
+	},
+	
+	cleanData: function( elems ) {
+		var data, id, cache = jQuery.cache,
+			special = jQuery.event.special,
+			deleteExpando = jQuery.support.deleteExpando;
+		
+		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+			if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
+				continue;
+			}
+
+			id = elem[ jQuery.expando ];
+			
+			if ( id ) {
+				data = cache[ id ];
+				
+				if ( data && data.events ) {
+					for ( var type in data.events ) {
+						if ( special[ type ] ) {
+							jQuery.event.remove( elem, type );
+
+						} else {
+							jQuery.removeEvent( elem, type, data.handle );
+						}
+					}
+				}
+				
+				if ( deleteExpando ) {
+					delete elem[ jQuery.expando ];
+
+				} else if ( elem.removeAttribute ) {
+					elem.removeAttribute( jQuery.expando );
+				}
+				
+				delete cache[ id ];
+			}
+		}
+	}
+});
+
+function evalScript( i, elem ) {
+	if ( elem.src ) {
+		jQuery.ajax({
+			url: elem.src,
+			async: false,
+			dataType: "script"
+		});
+	} else {
+		jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
+	}
+
+	if ( elem.parentNode ) {
+		elem.parentNode.removeChild( elem );
+	}
+}
+
+
+
+
+var ralpha = /alpha\([^)]*\)/i,
+	ropacity = /opacity=([^)]*)/,
+	rdashAlpha = /-([a-z])/ig,
+	rupper = /([A-Z])/g,
+	rnumpx = /^-?\d+(?:px)?$/i,
+	rnum = /^-?\d/,
+
+	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+	cssWidth = [ "Left", "Right" ],
+	cssHeight = [ "Top", "Bottom" ],
+	curCSS,
+
+	getComputedStyle,
+	currentStyle,
+
+	fcamelCase = function( all, letter ) {
+		return letter.toUpperCase();
+	};
+
+jQuery.fn.css = function( name, value ) {
+	// Setting 'undefined' is a no-op
+	if ( arguments.length === 2 && value === undefined ) {
+		return this;
+	}
+
+	return jQuery.access( this, name, value, true, function( elem, name, value ) {
+		return value !== undefined ?
+			jQuery.style( elem, name, value ) :
+			jQuery.css( elem, name );
+	});
+};
+
+jQuery.extend({
+	// Add in style property hooks for overriding the default
+	// behavior of getting and setting a style property
+	cssHooks: {
+		opacity: {
+			get: function( elem, computed ) {
+				if ( computed ) {
+					// We should always get a number back from opacity
+					var ret = curCSS( elem, "opacity", "opacity" );
+					return ret === "" ? "1" : ret;
+
+				} else {
+					return elem.style.opacity;
+				}
+			}
+		}
+	},
+
+	// Exclude the following css properties to add px
+	cssNumber: {
+		"zIndex": true,
+		"fontWeight": true,
+		"opacity": true,
+		"zoom": true,
+		"lineHeight": true
+	},
+
+	// Add in properties whose names you wish to fix before
+	// setting or getting the value
+	cssProps: {
+		// normalize float css property
+		"float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
+	},
+
+	// Get and set the style property on a DOM Node
+	style: function( elem, name, value, extra ) {
+		// Don't set styles on text and comment nodes
+		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+			return;
+		}
+
+		// Make sure that we're working with the right name
+		var ret, origName = jQuery.camelCase( name ),
+			style = elem.style, hooks = jQuery.cssHooks[ origName ];
+
+		name = jQuery.cssProps[ origName ] || origName;
+
+		// Check if we're setting a value
+		if ( value !== undefined ) {
+			// Make sure that NaN and null values aren't set. See: #7116
+			if ( typeof value === "number" && isNaN( value ) || value == null ) {
+				return;
+			}
+
+			// If a number was passed in, add 'px' to the (except for certain CSS properties)
+			if ( typeof value === "number" && !jQuery.cssNumber[ origName ] ) {
+				value += "px";
+			}
+
+			// If a hook was provided, use that value, otherwise just set the specified value
+			if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {
+				// Wrapped to prevent IE from throwing errors when 'invalid' values are provided
+				// Fixes bug #5509
+				try {
+					style[ name ] = value;
+				} catch(e) {}
+			}
+
+		} else {
+			// If a hook was provided get the non-computed value from there
+			if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
+				return ret;
+			}
+
+			// Otherwise just get the value from the style object
+			return style[ name ];
+		}
+	},
+
+	css: function( elem, name, extra ) {
+		// Make sure that we're working with the right name
+		var ret, origName = jQuery.camelCase( name ),
+			hooks = jQuery.cssHooks[ origName ];
+
+		name = jQuery.cssProps[ origName ] || origName;
+
+		// If a hook was provided get the computed value from there
+		if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {
+			return ret;
+
+		// Otherwise, if a way to get the computed value exists, use that
+		} else if ( curCSS ) {
+			return curCSS( elem, name, origName );
+		}
+	},
+
+	// A method for quickly swapping in/out CSS properties to get correct calculations
+	swap: function( elem, options, callback ) {
+		var old = {};
+
+		// Remember the old values, and insert the new ones
+		for ( var name in options ) {
+			old[ name ] = elem.style[ name ];
+			elem.style[ name ] = options[ name ];
+		}
+
+		callback.call( elem );
+
+		// Revert the old values
+		for ( name in options ) {
+			elem.style[ name ] = old[ name ];
+		}
+	},
+
+	camelCase: function( string ) {
+		return string.replace( rdashAlpha, fcamelCase );
+	}
+});
+
+// DEPRECATED, Use jQuery.css() instead
+jQuery.curCSS = jQuery.css;
+
+jQuery.each(["height", "width"], function( i, name ) {
+	jQuery.cssHooks[ name ] = {
+		get: function( elem, computed, extra ) {
+			var val;
+
+			if ( computed ) {
+				if ( elem.offsetWidth !== 0 ) {
+					val = getWH( elem, name, extra );
+
+				} else {
+					jQuery.swap( elem, cssShow, function() {
+						val = getWH( elem, name, extra );
+					});
+				}
+
+				if ( val <= 0 ) {
+					val = curCSS( elem, name, name );
+
+					if ( val === "0px" && currentStyle ) {
+						val = currentStyle( elem, name, name );
+					}
+
+					if ( val != null ) {
+						// Should return "auto" instead of 0, use 0 for
+						// temporary backwards-compat
+						return val === "" || val === "auto" ? "0px" : val;
+					}
+				}
+
+				if ( val < 0 || val == null ) {
+					val = elem.style[ name ];
+
+					// Should return "auto" instead of 0, use 0 for
+					// temporary backwards-compat
+					return val === "" || val === "auto" ? "0px" : val;
+				}
+
+				return typeof val === "string" ? val : val + "px";
+			}
+		},
+
+		set: function( elem, value ) {
+			if ( rnumpx.test( value ) ) {
+				// ignore negative width and height values #1599
+				value = parseFloat(value);
+
+				if ( value >= 0 ) {
+					return value + "px";
+				}
+
+			} else {
+				return value;
+			}
+		}
+	};
+});
+
+if ( !jQuery.support.opacity ) {
+	jQuery.cssHooks.opacity = {
+		get: function( elem, computed ) {
+			// IE uses filters for opacity
+			return ropacity.test((computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "") ?
+				(parseFloat(RegExp.$1) / 100) + "" :
+				computed ? "1" : "";
+		},
+
+		set: function( elem, value ) {
+			var style = elem.style;
+
+			// IE has trouble with opacity if it does not have layout
+			// Force it by setting the zoom level
+			style.zoom = 1;
+
+			// Set the alpha filter to set the opacity
+			var opacity = jQuery.isNaN(value) ?
+				"" :
+				"alpha(opacity=" + value * 100 + ")",
+				filter = style.filter || "";
+
+			style.filter = ralpha.test(filter) ?
+				filter.replace(ralpha, opacity) :
+				style.filter + ' ' + opacity;
+		}
+	};
+}
+
+if ( document.defaultView && document.defaultView.getComputedStyle ) {
+	getComputedStyle = function( elem, newName, name ) {
+		var ret, defaultView, computedStyle;
+
+		name = name.replace( rupper, "-$1" ).toLowerCase();
+
+		if ( !(defaultView = elem.ownerDocument.defaultView) ) {
+			return undefined;
+		}
+
+		if ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) {
+			ret = computedStyle.getPropertyValue( name );
+			if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
+				ret = jQuery.style( elem, name );
+			}
+		}
+
+		return ret;
+	};
+}
+
+if ( document.documentElement.currentStyle ) {
+	currentStyle = function( elem, name ) {
+		var left, rsLeft,
+			ret = elem.currentStyle && elem.currentStyle[ name ],
+			style = elem.style;
+
+		// From the awesome hack by Dean Edwards
+		// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+		// If we're not dealing with a regular pixel number
+		// but a number that has a weird ending, we need to convert it to pixels
+		if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
+			// Remember the original values
+			left = style.left;
+			rsLeft = elem.runtimeStyle.left;
+
+			// Put in the new values to get a computed value out
+			elem.runtimeStyle.left = elem.currentStyle.left;
+			style.left = name === "fontSize" ? "1em" : (ret || 0);
+			ret = style.pixelLeft + "px";
+
+			// Revert the changed values
+			style.left = left;
+			elem.runtimeStyle.left = rsLeft;
+		}
+
+		return ret === "" ? "auto" : ret;
+	};
+}
+
+curCSS = getComputedStyle || currentStyle;
+
+function getWH( elem, name, extra ) {
+	var which = name === "width" ? cssWidth : cssHeight,
+		val = name === "width" ? elem.offsetWidth : elem.offsetHeight;
+
+	if ( extra === "border" ) {
+		return val;
+	}
+
+	jQuery.each( which, function() {
+		if ( !extra ) {
+			val -= parseFloat(jQuery.css( elem, "padding" + this )) || 0;
+		}
+
+		if ( extra === "margin" ) {
+			val += parseFloat(jQuery.css( elem, "margin" + this )) || 0;
+
+		} else {
+			val -= parseFloat(jQuery.css( elem, "border" + this + "Width" )) || 0;
+		}
+	});
+
+	return val;
+}
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+	jQuery.expr.filters.hidden = function( elem ) {
+		var width = elem.offsetWidth,
+			height = elem.offsetHeight;
+
+		return (width === 0 && height === 0) || (!jQuery.support.reliableHiddenOffsets && (elem.style.display || jQuery.css( elem, "display" )) === "none");
+	};
+
+	jQuery.expr.filters.visible = function( elem ) {
+		return !jQuery.expr.filters.hidden( elem );
+	};
+}
+
+
+
+
+var jsc = jQuery.now(),
+	rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
+	rselectTextarea = /^(?:select|textarea)/i,
+	rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
+	rnoContent = /^(?:GET|HEAD)$/,
+	rbracket = /\[\]$/,
+	jsre = /\=\?(&|$)/,
+	rquery = /\?/,
+	rts = /([?&])_=[^&]*/,
+	rurl = /^(\w+:)?\/\/([^\/?#]+)/,
+	r20 = /%20/g,
+	rhash = /#.*$/,
+
+	// Keep a copy of the old load method
+	_load = jQuery.fn.load;
+
+jQuery.fn.extend({
+	load: function( url, params, callback ) {
+		if ( typeof url !== "string" && _load ) {
+			return _load.apply( this, arguments );
+
+		// Don't do a request if no elements are being requested
+		} else if ( !this.length ) {
+			return this;
+		}
+
+		var off = url.indexOf(" ");
+		if ( off >= 0 ) {
+			var selector = url.slice(off, url.length);
+			url = url.slice(0, off);
+		}
+
+		// Default to a GET request
+		var type = "GET";
+
+		// If the second parameter was provided
+		if ( params ) {
+			// If it's a function
+			if ( jQuery.isFunction( params ) ) {
+				// We assume that it's the callback
+				callback = params;
+				params = null;
+
+			// Otherwise, build a param string
+			} else if ( typeof params === "object" ) {
+				params = jQuery.param( params, jQuery.ajaxSettings.traditional );
+				type = "POST";
+			}
+		}
+
+		var self = this;
+
+		// Request the remote document
+		jQuery.ajax({
+			url: url,
+			type: type,
+			dataType: "html",
+			data: params,
+			complete: function( res, status ) {
+				// If successful, inject the HTML into all the matched elements
+				if ( status === "success" || status === "notmodified" ) {
+					// See if a selector was specified
+					self.html( selector ?
+						// Create a dummy div to hold the results
+						jQuery("<div>")
+							// inject the contents of the document in, removing the scripts
+							// to avoid any 'Permission Denied' errors in IE
+							.append(res.responseText.replace(rscript, ""))
+
+							// Locate the specified elements
+							.find(selector) :
+
+						// If not, just inject the full result
+						res.responseText );
+				}
+
+				if ( callback ) {
+					self.each( callback, [res.responseText, status, res] );
+				}
+			}
+		});
+
+		return this;
+	},
+
+	serialize: function() {
+		return jQuery.param(this.serializeArray());
+	},
+
+	serializeArray: function() {
+		return this.map(function() {
+			return this.elements ? jQuery.makeArray(this.elements) : this;
+		})
+		.filter(function() {
+			return this.name && !this.disabled &&
+				(this.checked || rselectTextarea.test(this.nodeName) ||
+					rinput.test(this.type));
+		})
+		.map(function( i, elem ) {
+			var val = jQuery(this).val();
+
+			return val == null ?
+				null :
+				jQuery.isArray(val) ?
+					jQuery.map( val, function( val, i ) {
+						return { name: elem.name, value: val };
+					}) :
+					{ name: elem.name, value: val };
+		}).get();
+	}
+});
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), function( i, o ) {
+	jQuery.fn[o] = function( f ) {
+		return this.bind(o, f);
+	};
+});
+
+jQuery.extend({
+	get: function( url, data, callback, type ) {
+		// shift arguments if data argument was omited
+		if ( jQuery.isFunction( data ) ) {
+			type = type || callback;
+			callback = data;
+			data = null;
+		}
+
+		return jQuery.ajax({
+			type: "GET",
+			url: url,
+			data: data,
+			success: callback,
+			dataType: type
+		});
+	},
+
+	getScript: function( url, callback ) {
+		return jQuery.get(url, null, callback, "script");
+	},
+
+	getJSON: function( url, data, callback ) {
+		return jQuery.get(url, data, callback, "json");
+	},
+
+	post: function( url, data, callback, type ) {
+		// shift arguments if data argument was omited
+		if ( jQuery.isFunction( data ) ) {
+			type = type || callback;
+			callback = data;
+			data = {};
+		}
+
+		return jQuery.ajax({
+			type: "POST",
+			url: url,
+			data: data,
+			success: callback,
+			dataType: type
+		});
+	},
+
+	ajaxSetup: function( settings ) {
+		jQuery.extend( jQuery.ajaxSettings, settings );
+	},
+
+	ajaxSettings: {
+		url: location.href,
+		global: true,
+		type: "GET",
+		contentType: "application/x-www-form-urlencoded",
+		processData: true,
+		async: true,
+		/*
+		timeout: 0,
+		data: null,
+		username: null,
+		password: null,
+		traditional: false,
+		*/
+		// This function can be overriden by calling jQuery.ajaxSetup
+		xhr: function() {
+			return new window.XMLHttpRequest();
+		},
+		accepts: {
+			xml: "application/xml, text/xml",
+			html: "text/html",
+			script: "text/javascript, application/javascript",
+			json: "application/json, text/javascript",
+			text: "text/plain",
+			_default: "*/*"
+		}
+	},
+
+	ajax: function( origSettings ) {
+		var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings),
+			jsonp, status, data, type = s.type.toUpperCase(), noContent = rnoContent.test(type);
+
+		s.url = s.url.replace( rhash, "" );
+
+		// Use original (not extended) context object if it was provided
+		s.context = origSettings && origSettings.context != null ? origSettings.context : s;
+
+		// convert data if not already a string
+		if ( s.data && s.processData && typeof s.data !== "string" ) {
+			s.data = jQuery.param( s.data, s.traditional );
+		}
+
+		// Handle JSONP Parameter Callbacks
+		if ( s.dataType === "jsonp" ) {
+			if ( type === "GET" ) {
+				if ( !jsre.test( s.url ) ) {
+					s.url += (rquery.test( s.url ) ? "&" : "?") + (s.jsonp || "callback") + "=?";
+				}
+			} else if ( !s.data || !jsre.test(s.data) ) {
+				s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
+			}
+			s.dataType = "json";
+		}
+
+		// Build temporary JSONP function
+		if ( s.dataType === "json" && (s.data && jsre.test(s.data) || jsre.test(s.url)) ) {
+			jsonp = s.jsonpCallback || ("jsonp" + jsc++);
+
+			// Replace the =? sequence both in the query string and the data
+			if ( s.data ) {
+				s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
+			}
+
+			s.url = s.url.replace(jsre, "=" + jsonp + "$1");
+
+			// We need to make sure
+			// that a JSONP style response is executed properly
+			s.dataType = "script";
+
+			// Handle JSONP-style loading
+			var customJsonp = window[ jsonp ];
+
+			window[ jsonp ] = function( tmp ) {
+				if ( jQuery.isFunction( customJsonp ) ) {
+					customJsonp( tmp );
+
+				} else {
+					// Garbage collect
+					window[ jsonp ] = undefined;
+
+					try {
+						delete window[ jsonp ];
+					} catch( jsonpError ) {}
+				}
+
+				data = tmp;
+				jQuery.handleSuccess( s, xhr, status, data );
+				jQuery.handleComplete( s, xhr, status, data );
+				
+				if ( head ) {
+					head.removeChild( script );
+				}
+			};
+		}
+
+		if ( s.dataType === "script" && s.cache === null ) {
+			s.cache = false;
+		}
+
+		if ( s.cache === false && noContent ) {
+			var ts = jQuery.now();
+
+			// try replacing _= if it is there
+			var ret = s.url.replace(rts, "$1_=" + ts);
+
+			// if nothing was replaced, add timestamp to the end
+			s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "");
+		}
+
+		// If data is available, append data to url for GET/HEAD requests
+		if ( s.data && noContent ) {
+			s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
+		}
+
+		// Watch for a new set of requests
+		if ( s.global && jQuery.active++ === 0 ) {
+			jQuery.event.trigger( "ajaxStart" );
+		}
+
+		// Matches an absolute URL, and saves the domain
+		var parts = rurl.exec( s.url ),
+			remote = parts && (parts[1] && parts[1].toLowerCase() !== location.protocol || parts[2].toLowerCase() !== location.host);
+
+		// If we're requesting a remote document
+		// and trying to load JSON or Script with a GET
+		if ( s.dataType === "script" && type === "GET" && remote ) {
+			var head = document.getElementsByTagName("head")[0] || document.documentElement;
+			var script = document.createElement("script");
+			if ( s.scriptCharset ) {
+				script.charset = s.scriptCharset;
+			}
+			script.src = s.url;
+
+			// Handle Script loading
+			if ( !jsonp ) {
+				var done = false;
+
+				// Attach handlers for all browsers
+				script.onload = script.onreadystatechange = function() {
+					if ( !done && (!this.readyState ||
+							this.readyState === "loaded" || this.readyState === "complete") ) {
+						done = true;
+						jQuery.handleSuccess( s, xhr, status, data );
+						jQuery.handleComplete( s, xhr, status, data );
+
+						// Handle memory leak in IE
+						script.onload = script.onreadystatechange = null;
+						if ( head && script.parentNode ) {
+							head.removeChild( script );
+						}
+					}
+				};
+			}
+
+			// Use insertBefore instead of appendChild  to circumvent an IE6 bug.
+			// This arises when a base node is used (#2709 and #4378).
+			head.insertBefore( script, head.firstChild );
+
+			// We handle everything using the script element injection
+			return undefined;
+		}
+
+		var requestDone = false;
+
+		// Create the request object
+		var xhr = s.xhr();
+
+		if ( !xhr ) {
+			return;
+		}
+
+		// Open the socket
+		// Passing null username, generates a login popup on Opera (#2865)
+		if ( s.username ) {
+			xhr.open(type, s.url, s.async, s.username, s.password);
+		} else {
+			xhr.open(type, s.url, s.async);
+		}
+
+		// Need an extra try/catch for cross domain requests in Firefox 3
+		try {
+			// Set content-type if data specified and content-body is valid for this type
+			if ( (s.data != null && !noContent) || (origSettings && origSettings.contentType) ) {
+				xhr.setRequestHeader("Content-Type", s.contentType);
+			}
+
+			// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+			if ( s.ifModified ) {
+				if ( jQuery.lastModified[s.url] ) {
+					xhr.setRequestHeader("If-Modified-Since", jQuery.lastModified[s.url]);
+				}
+
+				if ( jQuery.etag[s.url] ) {
+					xhr.setRequestHeader("If-None-Match", jQuery.etag[s.url]);
+				}
+			}
+
+			// Set header so the called script knows that it's an XMLHttpRequest
+			// Only send the header if it's not a remote XHR
+			if ( !remote ) {
+				xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+			}
+
+			// Set the Accepts header for the server, depending on the dataType
+			xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
+				s.accepts[ s.dataType ] + ", */*; q=0.01" :
+				s.accepts._default );
+		} catch( headerError ) {}
+
+		// Allow custom headers/mimetypes and early abort
+		if ( s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false ) {
+			// Handle the global AJAX counter
+			if ( s.global && jQuery.active-- === 1 ) {
+				jQuery.event.trigger( "ajaxStop" );
+			}
+
+			// close opended socket
+			xhr.abort();
+			return false;
+		}
+
+		if ( s.global ) {
+			jQuery.triggerGlobal( s, "ajaxSend", [xhr, s] );
+		}
+
+		// Wait for a response to come back
+		var onreadystatechange = xhr.onreadystatechange = function( isTimeout ) {
+			// The request was aborted
+			if ( !xhr || xhr.readyState === 0 || isTimeout === "abort" ) {
+				// Opera doesn't call onreadystatechange before this point
+				// so we simulate the call
+				if ( !requestDone ) {
+					jQuery.handleComplete( s, xhr, status, data );
+				}
+
+				requestDone = true;
+				if ( xhr ) {
+					xhr.onreadystatechange = jQuery.noop;
+				}
+
+			// The transfer is complete and the data is available, or the request timed out
+			} else if ( !requestDone && xhr && (xhr.readyState === 4 || isTimeout === "timeout") ) {
+				requestDone = true;
+				xhr.onreadystatechange = jQuery.noop;
+
+				status = isTimeout === "timeout" ?
+					"timeout" :
+					!jQuery.httpSuccess( xhr ) ?
+						"error" :
+						s.ifModified && jQuery.httpNotModified( xhr, s.url ) ?
+							"notmodified" :
+							"success";
+
+				var errMsg;
+
+				if ( status === "success" ) {
+					// Watch for, and catch, XML document parse errors
+					try {
+						// process the data (runs the xml through httpData regardless of callback)
+						data = jQuery.httpData( xhr, s.dataType, s );
+					} catch( parserError ) {
+						status = "parsererror";
+						errMsg = parserError;
+					}
+				}
+
+				// Make sure that the request was successful or notmodified
+				if ( status === "success" || status === "notmodified" ) {
+					// JSONP handles its own success callback
+					if ( !jsonp ) {
+						jQuery.handleSuccess( s, xhr, status, data );
+					}
+				} else {
+					jQuery.handleError( s, xhr, status, errMsg );
+				}
+
+				// Fire the complete handlers
+				if ( !jsonp ) {
+					jQuery.handleComplete( s, xhr, status, data );
+				}
+
+				if ( isTimeout === "timeout" ) {
+					xhr.abort();
+				}
+
+				// Stop memory leaks
+				if ( s.async ) {
+					xhr = null;
+				}
+			}
+		};
+
+		// Override the abort handler, if we can (IE 6 doesn't allow it, but that's OK)
+		// Opera doesn't fire onreadystatechange at all on abort
+		try {
+			var oldAbort = xhr.abort;
+			xhr.abort = function() {
+				if ( xhr ) {
+					// oldAbort has no call property in IE7 so
+					// just do it this way, which works in all
+					// browsers
+					Function.prototype.call.call( oldAbort, xhr );
+				}
+
+				onreadystatechange( "abort" );
+			};
+		} catch( abortError ) {}
+
+		// Timeout checker
+		if ( s.async && s.timeout > 0 ) {
+			setTimeout(function() {
+				// Check to see if the request is still happening
+				if ( xhr && !requestDone ) {
+					onreadystatechange( "timeout" );
+				}
+			}, s.timeout);
+		}
+
+		// Send the data
+		try {
+			xhr.send( noContent || s.data == null ? null : s.data );
+
+		} catch( sendError ) {
+			jQuery.handleError( s, xhr, null, sendError );
+
+			// Fire the complete handlers
+			jQuery.handleComplete( s, xhr, status, data );
+		}
+
+		// firefox 1.5 doesn't fire statechange for sync requests
+		if ( !s.async ) {
+			onreadystatechange();
+		}
+
+		// return XMLHttpRequest to allow aborting the request etc.
+		return xhr;
+	},
+
+	// Serialize an array of form elements or a set of
+	// key/values into a query string
+	param: function( a, traditional ) {
+		var s = [],
+			add = function( key, value ) {
+				// If value is a function, invoke it and return its value
+				value = jQuery.isFunction(value) ? value() : value;
+				s[ s.length ] = encodeURIComponent(key) + "=" + encodeURIComponent(value);
+			};
+		
+		// Set traditional to true for jQuery <= 1.3.2 behavior.
+		if ( traditional === undefined ) {
+			traditional = jQuery.ajaxSettings.traditional;
+		}
+		
+		// If an array was passed in, assume that it is an array of form elements.
+		if ( jQuery.isArray(a) || a.jquery ) {
+			// Serialize the form elements
+			jQuery.each( a, function() {
+				add( this.name, this.value );
+			});
+			
+		} else {
+			// If traditional, encode the "old" way (the way 1.3.2 or older
+			// did it), otherwise encode params recursively.
+			for ( var prefix in a ) {
+				buildParams( prefix, a[prefix], traditional, add );
+			}
+		}
+
+		// Return the resulting serialization
+		return s.join("&").replace(r20, "+");
+	}
+});
+
+function buildParams( prefix, obj, traditional, add ) {
+	if ( jQuery.isArray(obj) && obj.length ) {
+		// Serialize array item.
+		jQuery.each( obj, function( i, v ) {
+			if ( traditional || rbracket.test( prefix ) ) {
+				// Treat each array item as a scalar.
+				add( prefix, v );
+
+			} else {
+				// If array item is non-scalar (array or object), encode its
+				// numeric index to resolve deserialization ambiguity issues.
+				// Note that rack (as of 1.0.0) can't currently deserialize
+				// nested arrays properly, and attempting to do so may cause
+				// a server error. Possible fixes are to modify rack's
+				// deserialization algorithm or to provide an option or flag
+				// to force array serialization to be shallow.
+				buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add );
+			}
+		});
+			
+	} else if ( !traditional && obj != null && typeof obj === "object" ) {
+		if ( jQuery.isEmptyObject( obj ) ) {
+			add( prefix, "" );
+
+		// Serialize object item.
+		} else {
+			jQuery.each( obj, function( k, v ) {
+				buildParams( prefix + "[" + k + "]", v, traditional, add );
+			});
+		}
+					
+	} else {
+		// Serialize scalar item.
+		add( prefix, obj );
+	}
+}
+
+// This is still on the jQuery object... for now
+// Want to move this to jQuery.ajax some day
+jQuery.extend({
+
+	// Counter for holding the number of active queries
+	active: 0,
+
+	// Last-Modified header cache for next request
+	lastModified: {},
+	etag: {},
+
+	handleError: function( s, xhr, status, e ) {
+		// If a local callback was specified, fire it
+		if ( s.error ) {
+			s.error.call( s.context, xhr, status, e );
+		}
+
+		// Fire the global callback
+		if ( s.global ) {
+			jQuery.triggerGlobal( s, "ajaxError", [xhr, s, e] );
+		}
+	},
+
+	handleSuccess: function( s, xhr, status, data ) {
+		// If a local callback was specified, fire it and pass it the data
+		if ( s.success ) {
+			s.success.call( s.context, data, status, xhr );
+		}
+
+		// Fire the global callback
+		if ( s.global ) {
+			jQuery.triggerGlobal( s, "ajaxSuccess", [xhr, s] );
+		}
+	},
+
+	handleComplete: function( s, xhr, status ) {
+		// Process result
+		if ( s.complete ) {
+			s.complete.call( s.context, xhr, status );
+		}
+
+		// The request was completed
+		if ( s.global ) {
+			jQuery.triggerGlobal( s, "ajaxComplete", [xhr, s] );
+		}
+
+		// Handle the global AJAX counter
+		if ( s.global && jQuery.active-- === 1 ) {
+			jQuery.event.trigger( "ajaxStop" );
+		}
+	},
+		
+	triggerGlobal: function( s, type, args ) {
+		(s.context && s.context.url == null ? jQuery(s.context) : jQuery.event).trigger(type, args);
+	},
+
+	// Determines if an XMLHttpRequest was successful or not
+	httpSuccess: function( xhr ) {
+		try {
+			// IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
+			return !xhr.status && location.protocol === "file:" ||
+				xhr.status >= 200 && xhr.status < 300 ||
+				xhr.status === 304 || xhr.status === 1223;
+		} catch(e) {}
+
+		return false;
+	},
+
+	// Determines if an XMLHttpRequest returns NotModified
+	httpNotModified: function( xhr, url ) {
+		var lastModified = xhr.getResponseHeader("Last-Modified"),
+			etag = xhr.getResponseHeader("Etag");
+
+		if ( lastModified ) {
+			jQuery.lastModified[url] = lastModified;
+		}
+
+		if ( etag ) {
+			jQuery.etag[url] = etag;
+		}
+
+		return xhr.status === 304;
+	},
+
+	httpData: function( xhr, type, s ) {
+		var ct = xhr.getResponseHeader("content-type") || "",
+			xml = type === "xml" || !type && ct.indexOf("xml") >= 0,
+			data = xml ? xhr.responseXML : xhr.responseText;
+
+		if ( xml && data.documentElement.nodeName === "parsererror" ) {
+			jQuery.error( "parsererror" );
+		}
+
+		// Allow a pre-filtering function to sanitize the response
+		// s is checked to keep backwards compatibility
+		if ( s && s.dataFilter ) {
+			data = s.dataFilter( data, type );
+		}
+
+		// The filter can actually parse the response
+		if ( typeof data === "string" ) {
+			// Get the JavaScript object, if JSON is used.
+			if ( type === "json" || !type && ct.indexOf("json") >= 0 ) {
+				data = jQuery.parseJSON( data );
+
+			// If the type is "script", eval it in global context
+			} else if ( type === "script" || !type && ct.indexOf("javascript") >= 0 ) {
+				jQuery.globalEval( data );
+			}
+		}
+
+		return data;
+	}
+
+});
+
+/*
+ * Create the request object; Microsoft failed to properly
+ * implement the XMLHttpRequest in IE7 (can't request local files),
+ * so we use the ActiveXObject when it is available
+ * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
+ * we need a fallback.
+ */
+if ( window.ActiveXObject ) {
+	jQuery.ajaxSettings.xhr = function() {
+		if ( window.location.protocol !== "file:" ) {
+			try {
+				return new window.XMLHttpRequest();
+			} catch(xhrError) {}
+		}
+
+		try {
+			return new window.ActiveXObject("Microsoft.XMLHTTP");
+		} catch(activeError) {}
+	};
+}
+
+// Does this browser support XHR requests?
+jQuery.support.ajax = !!jQuery.ajaxSettings.xhr();
+
+
+
+
+var elemdisplay = {},
+	rfxtypes = /^(?:toggle|show|hide)$/,
+	rfxnum = /^([+\-]=)?([\d+.\-]+)(.*)$/,
+	timerId,
+	fxAttrs = [
+		// height animations
+		[ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
+		// width animations
+		[ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
+		// opacity animations
+		[ "opacity" ]
+	];
+
+jQuery.fn.extend({
+	show: function( speed, easing, callback ) {
+		var elem, display;
+
+		if ( speed || speed === 0 ) {
+			return this.animate( genFx("show", 3), speed, easing, callback);
+
+		} else {
+			for ( var i = 0, j = this.length; i < j; i++ ) {
+				elem = this[i];
+				display = elem.style.display;
+
+				// Reset the inline display of this element to learn if it is
+				// being hidden by cascaded rules or not
+				if ( !jQuery.data(elem, "olddisplay") && display === "none" ) {
+					display = elem.style.display = "";
+				}
+
+				// Set elements which have been overridden with display: none
+				// in a stylesheet to whatever the default browser style is
+				// for such an element
+				if ( display === "" && jQuery.css( elem, "display" ) === "none" ) {
+					jQuery.data(elem, "olddisplay", defaultDisplay(elem.nodeName));
+				}
+			}
+
+			// Set the display of most of the elements in a second loop
+			// to avoid the constant reflow
+			for ( i = 0; i < j; i++ ) {
+				elem = this[i];
+				display = elem.style.display;
+
+				if ( display === "" || display === "none" ) {
+					elem.style.display = jQuery.data(elem, "olddisplay") || "";
+				}
+			}
+
+			return this;
+		}
+	},
+
+	hide: function( speed, easing, callback ) {
+		if ( speed || speed === 0 ) {
+			return this.animate( genFx("hide", 3), speed, easing, callback);
+
+		} else {
+			for ( var i = 0, j = this.length; i < j; i++ ) {
+				var display = jQuery.css( this[i], "display" );
+
+				if ( display !== "none" ) {
+					jQuery.data( this[i], "olddisplay", display );
+				}
+			}
+
+			// Set the display of the elements in a second loop
+			// to avoid the constant reflow
+			for ( i = 0; i < j; i++ ) {
+				this[i].style.display = "none";
+			}
+
+			return this;
+		}
+	},
+
+	// Save the old toggle function
+	_toggle: jQuery.fn.toggle,
+
+	toggle: function( fn, fn2, callback ) {
+		var bool = typeof fn === "boolean";
+
+		if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
+			this._toggle.apply( this, arguments );
+
+		} else if ( fn == null || bool ) {
+			this.each(function() {
+				var state = bool ? fn : jQuery(this).is(":hidden");
+				jQuery(this)[ state ? "show" : "hide" ]();
+			});
+
+		} else {
+			this.animate(genFx("toggle", 3), fn, fn2, callback);
+		}
+
+		return this;
+	},
+
+	fadeTo: function( speed, to, easing, callback ) {
+		return this.filter(":hidden").css("opacity", 0).show().end()
+					.animate({opacity: to}, speed, easing, callback);
+	},
+
+	animate: function( prop, speed, easing, callback ) {
+		var optall = jQuery.speed(speed, easing, callback);
+
+		if ( jQuery.isEmptyObject( prop ) ) {
+			return this.each( optall.complete );
+		}
+
+		return this[ optall.queue === false ? "each" : "queue" ](function() {
+			// XXX 'this' does not always have a nodeName when running the
+			// test suite
+
+			var opt = jQuery.extend({}, optall), p,
+				isElement = this.nodeType === 1,
+				hidden = isElement && jQuery(this).is(":hidden"),
+				self = this;
+
+			for ( p in prop ) {
+				var name = jQuery.camelCase( p );
+
+				if ( p !== name ) {
+					prop[ name ] = prop[ p ];
+					delete prop[ p ];
+					p = name;
+				}
+
+				if ( prop[p] === "hide" && hidden || prop[p] === "show" && !hidden ) {
+					return opt.complete.call(this);
+				}
+
+				if ( isElement && ( p === "height" || p === "width" ) ) {
+					// Make sure that nothing sneaks out
+					// Record all 3 overflow attributes because IE does not
+					// change the overflow attribute when overflowX and
+					// overflowY are set to the same value
+					opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];
+
+					// Set display property to inline-block for height/width
+					// animations on inline elements that are having width/height
+					// animated
+					if ( jQuery.css( this, "display" ) === "inline" &&
+							jQuery.css( this, "float" ) === "none" ) {
+						if ( !jQuery.support.inlineBlockNeedsLayout ) {
+							this.style.display = "inline-block";
+
+						} else {
+							var display = defaultDisplay(this.nodeName);
+
+							// inline-level elements accept inline-block;
+							// block-level elements need to be inline with layout
+							if ( display === "inline" ) {
+								this.style.display = "inline-block";
+
+							} else {
+								this.style.display = "inline";
+								this.style.zoom = 1;
+							}
+						}
+					}
+				}
+
+				if ( jQuery.isArray( prop[p] ) ) {
+					// Create (if needed) and add to specialEasing
+					(opt.specialEasing = opt.specialEasing || {})[p] = prop[p][1];
+					prop[p] = prop[p][0];
+				}
+			}
+
+			if ( opt.overflow != null ) {
+				this.style.overflow = "hidden";
+			}
+
+			opt.curAnim = jQuery.extend({}, prop);
+
+			jQuery.each( prop, function( name, val ) {
+				var e = new jQuery.fx( self, opt, name );
+
+				if ( rfxtypes.test(val) ) {
+					e[ val === "toggle" ? hidden ? "show" : "hide" : val ]( prop );
+
+				} else {
+					var parts = rfxnum.exec(val),
+						start = e.cur() || 0;
+
+					if ( parts ) {
+						var end = parseFloat( parts[2] ),
+							unit = parts[3] || "px";
+
+						// We need to compute starting value
+						if ( unit !== "px" ) {
+							jQuery.style( self, name, (end || 1) + unit);
+							start = ((end || 1) / e.cur()) * start;
+							jQuery.style( self, name, start + unit);
+						}
+
+						// If a +=/-= token was provided, we're doing a relative animation
+						if ( parts[1] ) {
+							end = ((parts[1] === "-=" ? -1 : 1) * end) + start;
+						}
+
+						e.custom( start, end, unit );
+
+					} else {
+						e.custom( start, val, "" );
+					}
+				}
+			});
+
+			// For JS strict compliance
+			return true;
+		});
+	},
+
+	stop: function( clearQueue, gotoEnd ) {
+		var timers = jQuery.timers;
+
+		if ( clearQueue ) {
+			this.queue([]);
+		}
+
+		this.each(function() {
+			// go in reverse order so anything added to the queue during the loop is ignored
+			for ( var i = timers.length - 1; i >= 0; i-- ) {
+				if ( timers[i].elem === this ) {
+					if (gotoEnd) {
+						// force the next step to be the last
+						timers[i](true);
+					}
+
+					timers.splice(i, 1);
+				}
+			}
+		});
+
+		// start the next in the queue if the last step wasn't forced
+		if ( !gotoEnd ) {
+			this.dequeue();
+		}
+
+		return this;
+	}
+
+});
+
+function genFx( type, num ) {
+	var obj = {};
+
+	jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() {
+		obj[ this ] = type;
+	});
+
+	return obj;
+}
+
+// Generate shortcuts for custom animations
+jQuery.each({
+	slideDown: genFx("show", 1),
+	slideUp: genFx("hide", 1),
+	slideToggle: genFx("toggle", 1),
+	fadeIn: { opacity: "show" },
+	fadeOut: { opacity: "hide" },
+	fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+	jQuery.fn[ name ] = function( speed, easing, callback ) {
+		return this.animate( props, speed, easing, callback );
+	};
+});
+
+jQuery.extend({
+	speed: function( speed, easing, fn ) {
+		var opt = speed && typeof speed === "object" ? jQuery.extend({}, speed) : {
+			complete: fn || !fn && easing ||
+				jQuery.isFunction( speed ) && speed,
+			duration: speed,
+			easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
+		};
+
+		opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+			opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[opt.duration] : jQuery.fx.speeds._default;
+
+		// Queueing
+		opt.old = opt.complete;
+		opt.complete = function() {
+			if ( opt.queue !== false ) {
+				jQuery(this).dequeue();
+			}
+			if ( jQuery.isFunction( opt.old ) ) {
+				opt.old.call( this );
+			}
+		};
+
+		return opt;
+	},
+
+	easing: {
+		linear: function( p, n, firstNum, diff ) {
+			return firstNum + diff * p;
+		},
+		swing: function( p, n, firstNum, diff ) {
+			return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
+		}
+	},
+
+	timers: [],
+
+	fx: function( elem, options, prop ) {
+		this.options = options;
+		this.elem = elem;
+		this.prop = prop;
+
+		if ( !options.orig ) {
+			options.orig = {};
+		}
+	}
+
+});
+
+jQuery.fx.prototype = {
+	// Simple function for setting a style value
+	update: function() {
+		if ( this.options.step ) {
+			this.options.step.call( this.elem, this.now, this );
+		}
+
+		(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
+	},
+
+	// Get the current size
+	cur: function() {
+		if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) {
+			return this.elem[ this.prop ];
+		}
+
+		var r = parseFloat( jQuery.css( this.elem, this.prop ) );
+		return r && r > -10000 ? r : 0;
+	},
+
+	// Start an animation from one number to another
+	custom: function( from, to, unit ) {
+		var self = this,
+			fx = jQuery.fx;
+
+		this.startTime = jQuery.now();
+		this.start = from;
+		this.end = to;
+		this.unit = unit || this.unit || "px";
+		this.now = this.start;
+		this.pos = this.state = 0;
+
+		function t( gotoEnd ) {
+			return self.step(gotoEnd);
+		}
+
+		t.elem = this.elem;
+
+		if ( t() && jQuery.timers.push(t) && !timerId ) {
+			timerId = setInterval(fx.tick, fx.interval);
+		}
+	},
+
+	// Simple 'show' function
+	show: function() {
+		// Remember where we started, so that we can go back to it later
+		this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
+		this.options.show = true;
+
+		// Begin the animation
+		// Make sure that we start at a small width/height to avoid any
+		// flash of content
+		this.custom(this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur());
+
+		// Start by showing the element
+		jQuery( this.elem ).show();
+	},
+
+	// Simple 'hide' function
+	hide: function() {
+		// Remember where we started, so that we can go back to it later
+		this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
+		this.options.hide = true;
+
+		// Begin the animation
+		this.custom(this.cur(), 0);
+	},
+
+	// Each step of an animation
+	step: function( gotoEnd ) {
+		var t = jQuery.now(), done = true;
+
+		if ( gotoEnd || t >= this.options.duration + this.startTime ) {
+			this.now = this.end;
+			this.pos = this.state = 1;
+			this.update();
+
+			this.options.curAnim[ this.prop ] = true;
+
+			for ( var i in this.options.curAnim ) {
+				if ( this.options.curAnim[i] !== true ) {
+					done = false;
+				}
+			}
+
+			if ( done ) {
+				// Reset the overflow
+				if ( this.options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {
+					var elem = this.elem,
+						options = this.options;
+
+					jQuery.each( [ "", "X", "Y" ], function (index, value) {
+						elem.style[ "overflow" + value ] = options.overflow[index];
+					} );
+				}
+
+				// Hide the element if the "hide" operation was done
+				if ( this.options.hide ) {
+					jQuery(this.elem).hide();
+				}
+
+				// Reset the properties, if the item has been hidden or shown
+				if ( this.options.hide || this.options.show ) {
+					for ( var p in this.options.curAnim ) {
+						jQuery.style( this.elem, p, this.options.orig[p] );
+					}
+				}
+
+				// Execute the complete function
+				this.options.complete.call( this.elem );
+			}
+
+			return false;
+
+		} else {
+			var n = t - this.startTime;
+			this.state = n / this.options.duration;
+
+			// Perform the easing function, defaults to swing
+			var specialEasing = this.options.specialEasing && this.options.specialEasing[this.prop];
+			var defaultEasing = this.options.easing || (jQuery.easing.swing ? "swing" : "linear");
+			this.pos = jQuery.easing[specialEasing || defaultEasing](this.state, n, 0, 1, this.options.duration);
+			this.now = this.start + ((this.end - this.start) * this.pos);
+
+			// Perform the next step of the animation
+			this.update();
+		}
+
+		return true;
+	}
+};
+
+jQuery.extend( jQuery.fx, {
+	tick: function() {
+		var timers = jQuery.timers;
+
+		for ( var i = 0; i < timers.length; i++ ) {
+			if ( !timers[i]() ) {
+				timers.splice(i--, 1);
+			}
+		}
+
+		if ( !timers.length ) {
+			jQuery.fx.stop();
+		}
+	},
+
+	interval: 13,
+
+	stop: function() {
+		clearInterval( timerId );
+		timerId = null;
+	},
+
+	speeds: {
+		slow: 600,
+		fast: 200,
+		// Default speed
+		_default: 400
+	},
+
+	step: {
+		opacity: function( fx ) {
+			jQuery.style( fx.elem, "opacity", fx.now );
+		},
+
+		_default: function( fx ) {
+			if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
+				fx.elem.style[ fx.prop ] = (fx.prop === "width" || fx.prop === "height" ? Math.max(0, fx.now) : fx.now) + fx.unit;
+			} else {
+				fx.elem[ fx.prop ] = fx.now;
+			}
+		}
+	}
+});
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+	jQuery.expr.filters.animated = function( elem ) {
+		return jQuery.grep(jQuery.timers, function( fn ) {
+			return elem === fn.elem;
+		}).length;
+	};
+}
+
+function defaultDisplay( nodeName ) {
+	if ( !elemdisplay[ nodeName ] ) {
+		var elem = jQuery("<" + nodeName + ">").appendTo("body"),
+			display = elem.css("display");
+
+		elem.remove();
+
+		if ( display === "none" || display === "" ) {
+			display = "block";
+		}
+
+		elemdisplay[ nodeName ] = display;
+	}
+
+	return elemdisplay[ nodeName ];
+}
+
+
+
+
+var rtable = /^t(?:able|d|h)$/i,
+	rroot = /^(?:body|html)$/i;
+
+if ( "getBoundingClientRect" in document.documentElement ) {
+	jQuery.fn.offset = function( options ) {
+		var elem = this[0], box;
+
+		if ( options ) { 
+			return this.each(function( i ) {
+				jQuery.offset.setOffset( this, options, i );
+			});
+		}
+
+		if ( !elem || !elem.ownerDocument ) {
+			return null;
+		}
+
+		if ( elem === elem.ownerDocument.body ) {
+			return jQuery.offset.bodyOffset( elem );
+		}
+
+		try {
+			box = elem.getBoundingClientRect();
+		} catch(e) {}
+
+		var doc = elem.ownerDocument,
+			docElem = doc.documentElement;
+
+		// Make sure we're not dealing with a disconnected DOM node
+		if ( !box || !jQuery.contains( docElem, elem ) ) {
+			return box || { top: 0, left: 0 };
+		}
+
+		var body = doc.body,
+			win = getWindow(doc),
+			clientTop  = docElem.clientTop  || body.clientTop  || 0,
+			clientLeft = docElem.clientLeft || body.clientLeft || 0,
+			scrollTop  = (win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop ),
+			scrollLeft = (win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft),
+			top  = box.top  + scrollTop  - clientTop,
+			left = box.left + scrollLeft - clientLeft;
+
+		return { top: top, left: left };
+	};
+
+} else {
+	jQuery.fn.offset = function( options ) {
+		var elem = this[0];
+
+		if ( options ) { 
+			return this.each(function( i ) {
+				jQuery.offset.setOffset( this, options, i );
+			});
+		}
+
+		if ( !elem || !elem.ownerDocument ) {
+			return null;
+		}
+
+		if ( elem === elem.ownerDocument.body ) {
+			return jQuery.offset.bodyOffset( elem );
+		}
+
+		jQuery.offset.initialize();
+
+		var computedStyle,
+			offsetParent = elem.offsetParent,
+			prevOffsetParent = elem,
+			doc = elem.ownerDocument,
+			docElem = doc.documentElement,
+			body = doc.body,
+			defaultView = doc.defaultView,
+			prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
+			top = elem.offsetTop,
+			left = elem.offsetLeft;
+
+		while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
+			if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
+				break;
+			}
+
+			computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
+			top  -= elem.scrollTop;
+			left -= elem.scrollLeft;
+
+			if ( elem === offsetParent ) {
+				top  += elem.offsetTop;
+				left += elem.offsetLeft;
+
+				if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {
+					top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
+					left += parseFloat( computedStyle.borderLeftWidth ) || 0;
+				}
+
+				prevOffsetParent = offsetParent;
+				offsetParent = elem.offsetParent;
+			}
+
+			if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
+				top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
+				left += parseFloat( computedStyle.borderLeftWidth ) || 0;
+			}
+
+			prevComputedStyle = computedStyle;
+		}
+
+		if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
+			top  += body.offsetTop;
+			left += body.offsetLeft;
+		}
+
+		if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
+			top  += Math.max( docElem.scrollTop, body.scrollTop );
+			left += Math.max( docElem.scrollLeft, body.scrollLeft );
+		}
+
+		return { top: top, left: left };
+	};
+}
+
+jQuery.offset = {
+	initialize: function() {
+		var body = document.body, container = document.createElement("div"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.css(body, "marginTop") ) || 0,
+			html = "<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
+
+		jQuery.extend( container.style, { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" } );
+
+		container.innerHTML = html;
+		body.insertBefore( container, body.firstChild );
+		innerDiv = container.firstChild;
+		checkDiv = innerDiv.firstChild;
+		td = innerDiv.nextSibling.firstChild.firstChild;
+
+		this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
+		this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
+
+		checkDiv.style.position = "fixed";
+		checkDiv.style.top = "20px";
+
+		// safari subtracts parent border width here which is 5px
+		this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);
+		checkDiv.style.position = checkDiv.style.top = "";
+
+		innerDiv.style.overflow = "hidden";
+		innerDiv.style.position = "relative";
+
+		this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
+
+		this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);
+
+		body.removeChild( container );
+		body = container = innerDiv = checkDiv = table = td = null;
+		jQuery.offset.initialize = jQuery.noop;
+	},
+
+	bodyOffset: function( body ) {
+		var top = body.offsetTop,
+			left = body.offsetLeft;
+
+		jQuery.offset.initialize();
+
+		if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {
+			top  += parseFloat( jQuery.css(body, "marginTop") ) || 0;
+			left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
+		}
+
+		return { top: top, left: left };
+	},
+	
+	setOffset: function( elem, options, i ) {
+		var position = jQuery.css( elem, "position" );
+
+		// set position first, in-case top/left are set even on static elem
+		if ( position === "static" ) {
+			elem.style.position = "relative";
+		}
+
+		var curElem = jQuery( elem ),
+			curOffset = curElem.offset(),
+			curCSSTop = jQuery.css( elem, "top" ),
+			curCSSLeft = jQuery.css( elem, "left" ),
+			calculatePosition = (position === "absolute" && jQuery.inArray('auto', [curCSSTop, curCSSLeft]) > -1),
+			props = {}, curPosition = {}, curTop, curLeft;
+
+		// need to be able to calculate position if either top or left is auto and position is absolute
+		if ( calculatePosition ) {
+			curPosition = curElem.position();
+		}
+
+		curTop  = calculatePosition ? curPosition.top  : parseInt( curCSSTop,  10 ) || 0;
+		curLeft = calculatePosition ? curPosition.left : parseInt( curCSSLeft, 10 ) || 0;
+
+		if ( jQuery.isFunction( options ) ) {
+			options = options.call( elem, i, curOffset );
+		}
+
+		if (options.top != null) {
+			props.top = (options.top - curOffset.top) + curTop;
+		}
+		if (options.left != null) {
+			props.left = (options.left - curOffset.left) + curLeft;
+		}
+		
+		if ( "using" in options ) {
+			options.using.call( elem, props );
+		} else {
+			curElem.css( props );
+		}
+	}
+};
+
+
+jQuery.fn.extend({
+	position: function() {
+		if ( !this[0] ) {
+			return null;
+		}
+
+		var elem = this[0],
+
+		// Get *real* offsetParent
+		offsetParent = this.offsetParent(),
+
+		// Get correct offsets
+		offset       = this.offset(),
+		parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
+
+		// Subtract element margins
+		// note: when an element has margin: auto the offsetLeft and marginLeft
+		// are the same in Safari causing offset.left to incorrectly be 0
+		offset.top  -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
+		offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;
+
+		// Add offsetParent borders
+		parentOffset.top  += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
+		parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;
+
+		// Subtract the two offsets
+		return {
+			top:  offset.top  - parentOffset.top,
+			left: offset.left - parentOffset.left
+		};
+	},
+
+	offsetParent: function() {
+		return this.map(function() {
+			var offsetParent = this.offsetParent || document.body;
+			while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
+				offsetParent = offsetParent.offsetParent;
+			}
+			return offsetParent;
+		});
+	}
+});
+
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( ["Left", "Top"], function( i, name ) {
+	var method = "scroll" + name;
+
+	jQuery.fn[ method ] = function(val) {
+		var elem = this[0], win;
+		
+		if ( !elem ) {
+			return null;
+		}
+
+		if ( val !== undefined ) {
+			// Set the scroll offset
+			return this.each(function() {
+				win = getWindow( this );
+
+				if ( win ) {
+					win.scrollTo(
+						!i ? val : jQuery(win).scrollLeft(),
+						 i ? val : jQuery(win).scrollTop()
+					);
+
+				} else {
+					this[ method ] = val;
+				}
+			});
+		} else {
+			win = getWindow( elem );
+
+			// Return the scroll offset
+			return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
+				jQuery.support.boxModel && win.document.documentElement[ method ] ||
+					win.document.body[ method ] :
+				elem[ method ];
+		}
+	};
+});
+
+function getWindow( elem ) {
+	return jQuery.isWindow( elem ) ?
+		elem :
+		elem.nodeType === 9 ?
+			elem.defaultView || elem.parentWindow :
+			false;
+}
+
+
+
+
+// Create innerHeight, innerWidth, outerHeight and outerWidth methods
+jQuery.each([ "Height", "Width" ], function( i, name ) {
+
+	var type = name.toLowerCase();
+
+	// innerHeight and innerWidth
+	jQuery.fn["inner" + name] = function() {
+		return this[0] ?
+			parseFloat( jQuery.css( this[0], type, "padding" ) ) :
+			null;
+	};
+
+	// outerHeight and outerWidth
+	jQuery.fn["outer" + name] = function( margin ) {
+		return this[0] ?
+			parseFloat( jQuery.css( this[0], type, margin ? "margin" : "border" ) ) :
+			null;
+	};
+
+	jQuery.fn[ type ] = function( size ) {
+		// Get window width or height
+		var elem = this[0];
+		if ( !elem ) {
+			return size == null ? null : this;
+		}
+		
+		if ( jQuery.isFunction( size ) ) {
+			return this.each(function( i ) {
+				var self = jQuery( this );
+				self[ type ]( size.call( this, i, self[ type ]() ) );
+			});
+		}
+
+		if ( jQuery.isWindow( elem ) ) {
+			// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
+			return elem.document.compatMode === "CSS1Compat" && elem.document.documentElement[ "client" + name ] ||
+				elem.document.body[ "client" + name ];
+
+		// Get document width or height
+		} else if ( elem.nodeType === 9 ) {
+			// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
+			return Math.max(
+				elem.documentElement["client" + name],
+				elem.body["scroll" + name], elem.documentElement["scroll" + name],
+				elem.body["offset" + name], elem.documentElement["offset" + name]
+			);
+
+		// Get or set width or height on the element
+		} else if ( size === undefined ) {
+			var orig = jQuery.css( elem, type ),
+				ret = parseFloat( orig );
+
+			return jQuery.isNaN( ret ) ? orig : ret;
+
+		// Set the width or height on the element (default to pixels if value is unitless)
+		} else {
+			return this.css( type, typeof size === "string" ? size : size + "px" );
+		}
+	};
+
+});
+
+
+})(window);
diff --git a/vision/BinaryServer.cpp b/vision/BinaryServer.cpp
new file mode 100644
index 0000000..c21a8b3
--- /dev/null
+++ b/vision/BinaryServer.cpp
@@ -0,0 +1,129 @@
+#include "vision/BinaryServer.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <string.h>
+#include <vector>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+
+#include "aos/externals/libjpeg/include/jpeglib.h"
+#include "aos/linux_code/camera/Buffers.h"
+#include "aos/common/time.h"
+
+namespace frc971 {
+namespace vision {
+
+static void echo_read_cb(struct bufferevent *bev, void * /*ctx*/) {
+  struct evbuffer *input = bufferevent_get_input(bev);
+  struct evbuffer *output = bufferevent_get_output(bev);
+
+  size_t len = evbuffer_get_length(input);
+  char *data;
+  data = (char *)malloc(len);
+  evbuffer_copyout(input, data, len);
+
+  printf("we got some data: %s\n", data);
+
+  evbuffer_add_buffer(output, input);
+}
+
+void BinaryServer::ErrorEvent(struct bufferevent *bev, short events) {
+  if (events & BEV_EVENT_ERROR) perror("Error from bufferevent");
+  if (events & (BEV_EVENT_EOF | BEV_EVENT_ERROR)) {
+    have_id = false;
+    bufferevent_free(bev);
+  }
+}
+
+void BinaryServer::Accept(struct evconnlistener *listener, evutil_socket_t fd,
+                          struct sockaddr * /*address*/, int /*socklen*/) {
+  struct event_base *base = evconnlistener_get_base(listener);
+  if (!have_id) {
+    struct bufferevent *bev =
+        bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
+    _output = bufferevent_get_output(bev);
+    _bufev = bev;
+    have_id = true;
+    int no_delay_flag = 1;
+    setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &no_delay_flag,
+               sizeof(no_delay_flag));
+
+    bufferevent_setcb(bev, echo_read_cb, NULL, StaticErrorEvent, this);
+
+    bufferevent_enable(bev, EV_READ | EV_WRITE);
+  }
+}
+static void accept_error_cb(struct evconnlistener *listener, void * /*ctx*/) {
+  struct event_base *base = evconnlistener_get_base(listener);
+  int err = EVUTIL_SOCKET_ERROR();
+  fprintf(stderr, "Got an error %d (%s) on the listener. "
+                  "Shutting down.\n",
+          err, evutil_socket_error_to_string(err));
+
+  event_base_loopexit(base, NULL);
+}
+
+void BinaryServer::StartServer(uint16_t port) {
+  _fd = socket(AF_INET, SOCK_STREAM, 0);
+  struct sockaddr_in sin;
+  memset(&sin, 0, sizeof(sin));
+  sin.sin_family = AF_INET;
+  sin.sin_port = htons(port);
+  sin.sin_addr.s_addr = inet_addr("0.0.0.0");
+
+  listener = evconnlistener_new_bind(
+      _base, StaticAccept, this, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, -1,
+      (struct sockaddr *)(void *)&sin, sizeof(sin));
+
+  if (!listener) {
+    fprintf(stderr, "%s:%d: Couldn't create listener\n", __FILE__, __LINE__);
+    exit(-1);
+  }
+
+  evconnlistener_set_error_cb(listener, accept_error_cb);
+}
+
+void BinaryServer::Notify(int fd, short /*what*/) {
+  char notes[4096];
+  int count = read(fd, notes, 4096);
+  if (count == 0) {
+    close(fd);
+    fprintf(stderr, "%s:%d: Error No cheeze from OpenCV task!!!\n", __FILE__,
+            __LINE__);
+    exit(-1);
+  }
+  printf("notified!: %d\n", count);
+  if (have_id) {
+    printf("got someone to read my stuff!\n");
+    char *binary_data;
+    size_t len;
+    if (_notify->GetData(&binary_data, &len)) {
+      printf("here is for sending\n");
+      evbuffer_add_reference(_output, binary_data, len,
+                             PacketNotifier::StaticDataSent, _notify);
+      printf("this is how sending went %d\n",
+             bufferevent_flush(_bufev, EV_WRITE, BEV_FLUSH));
+    }
+  }
+}
+
+// Constructor
+BinaryServer::BinaryServer(uint16_t port,
+                           frc971::vision::PacketNotifier *notify)
+    : _base(event_base_new()) {
+  have_id = false;
+  StartServer(port);
+  _notify = notify;
+  frame_notify = event_new(_base, notify->RecieverFD(), EV_READ | EV_PERSIST,
+                           StaticNotify, this);
+  event_add(frame_notify, NULL);
+  event_base_dispatch(_base);
+}
+
+}  // namespace vision
+}  // namespace frc971
diff --git a/vision/BinaryServer.h b/vision/BinaryServer.h
new file mode 100644
index 0000000..f33ee21
--- /dev/null
+++ b/vision/BinaryServer.h
@@ -0,0 +1,57 @@
+#ifndef FRC971_VISION_BINARY_SERVER_H_
+#define FRC971_VISION_BINARY_SERVER_H_
+
+#include <sys/types.h> 
+#include <sys/socket.h>
+
+#include "event2/buffer.h"
+#include "event2/event.h"
+#include "event2/listener.h"
+#include "event2/bufferevent.h"
+
+#include "aos/common/mutex.h"
+
+#include "vision/PacketNotifier.h"
+
+namespace frc971 {
+namespace vision {
+
+/* This runs the libevent loop and interfaces in with the sockets provided from the PacketNotifier
+ * to allow a secondary process to focus primarily on doing processing and then feeding this task.
+ */
+class BinaryServer {
+ public:
+  BinaryServer(uint16_t port,PacketNotifier *notify);
+
+
+  void StartServer(uint16_t port);
+ private:
+  event_base *const _base;
+  int _fd;
+  PacketNotifier *_notify;
+  bool have_id;
+  int _client_fd;
+  struct event *frame_notify;
+  struct evbuffer *_output;
+  struct bufferevent *_bufev;
+  struct evconnlistener *listener;
+  void Accept(evconnlistener *listener, evutil_socket_t fd,
+      struct sockaddr* /*address*/, int /*socklen*/);
+  void Notify(int /*fd*/, short /*what*/);
+  void ErrorEvent(struct bufferevent *bev,short events);
+  static void StaticAccept(evconnlistener *listener, evutil_socket_t fd,
+          struct sockaddr *address, int socklen,void *self){
+    ((BinaryServer *)(self))->Accept(listener, fd, address, socklen);
+  }
+  static void StaticNotify(int fd, short what, void *self){
+    ((BinaryServer *)(self))->Notify(fd, what);
+  }
+  static void StaticErrorEvent(struct bufferevent *bev,short events,void *self){
+    ((BinaryServer *)(self))->ErrorEvent(bev,events);
+  }
+};
+
+}  // namespace vision
+}  // namespace frc971
+
+#endif  // FRC971_VISION_BINARY_SERVER_H_
diff --git a/vision/CameraProcessor.cpp b/vision/CameraProcessor.cpp
new file mode 100644
index 0000000..856e12b
--- /dev/null
+++ b/vision/CameraProcessor.cpp
@@ -0,0 +1,466 @@
+#include "vision/CameraProcessor.h"
+#include "aos/common/logging/logging.h"
+
+//#define LOCAL_DEBUG 1
+
+// create a new target
+Target::Target(std::vector<cv::Point> new_contour,
+		std::vector<cv::Point> new_raw_contour,
+		FullRect new_rect, int new_weight, bool _is_90) {
+	this_contour = new_contour;
+	raw_contour = new_raw_contour;
+	rect = new_rect;
+	weight = new_weight;
+	height = getHeight(_is_90);
+}
+
+// calculate distance to target
+double Target::getHeight(bool is_90) {
+	// The 780.3296 is at full resolution 640x480, and we need
+	// to scale back to 320x240
+	//static const double cam_l = 780.3296 / 2.0; 
+	////static const double cam_d = 20.78096;
+	double height;
+	if (is_90) {
+		height = ((rect.ul.x - rect.ur.x) +
+				(rect.bl.x - rect.br.x)) / 2.0;
+	} else {
+		height = ((rect.ur.y + rect.ul.y) -
+				(rect.br.y + rect.bl.y)) / 2.0;
+	}
+	//return cam_l * 12.0 / height;
+	return height;
+}
+
+void Target::refineTarget() {
+	printf("okay refined\n");
+}
+
+FullRect::FullRect() {
+	ur.x = -1;
+	ur.y = -1;
+	ul.x = -1;
+	ul.y = -1;
+	br.x = -1;
+	br.y = -1;
+	bl.x = -1;
+	bl.y = -1;
+}
+
+// turns a contour into easier to access structure
+FullRect calcFullRect(std::vector<cv::Point> *contour){
+	FullRect rect;
+	for(int i=0; i<4; i++){
+		cv::Point2f pt = (*contour)[i];
+		rect.centroid.x += pt.x;
+		rect.centroid.y += pt.y;
+	}
+	rect.centroid.x /= 4;
+	rect.centroid.y /= 4;
+	for(int i=0; i<4; i++){
+		cv::Point2f pt = (*contour)[i];
+		if(pt.y > rect.centroid.y ){
+			if(pt.x > rect.centroid.x){
+				if (rect.ul.x < 0) {
+					rect.ul = pt;
+				} else {
+					rect.ur = pt;
+				}
+			}else{
+				if (rect.ur.x < 0) {
+					rect.ur = pt;
+				} else {
+					rect.ul = pt;
+				}
+			}
+			if (rect.ul.x > 0 && rect.ur.x > 0) {
+				// both are set, so if we got it wrong correct it here
+				if (rect.ul.x > rect.ur.x) {
+					pt = rect.ur;
+					rect.ur = rect.ul;
+					rect.ul = pt;
+				}
+			}
+		}else{
+			if(pt.x > rect.centroid.x){
+				if (rect.bl.x < 0) {
+					rect.bl = pt;
+				} else {
+					rect.br = pt;
+				}
+			}else{
+				if (rect.br.x < 0) {
+					rect.br = pt;
+				} else {
+					rect.bl = pt;
+				}
+			}
+			if (rect.bl.x > 0 && rect.br.x > 0) {
+				// both are set, so if we got it wrong correct it here
+				if (rect.bl.x > rect.br.x) {
+					pt = rect.br;
+					rect.br = rect.bl;
+					rect.bl = pt;
+				}
+			}
+		}
+	}
+	return rect;
+}
+
+// quickly remove targets that do not fit a very broad set of constraints
+bool cullObvious(FullRect rect, double outside_size){
+	// first check that could see a target this size
+	// Calculated from dave's simulation, shloud be 850 and 72000 if filled
+	if((outside_size < 500) || (outside_size > 90000)){
+		return false;
+	}
+	// Targets on the edge are at best inaccurate.
+	// In this case, we just want to point the right way,
+	// so this is no longer a valid assumption.
+	/*if(	rect.ur.x < 2 || rect.ur.y < 2 || rect.ur.x > 637 || rect.ur.y > 477 ||
+		rect.ul.x < 2 || rect.ul.y < 2 || rect.ul.x > 637 || rect.ul.y > 477 ||
+		rect.br.x < 2 || rect.br.y < 2 || rect.br.x > 637 || rect.br.y > 477 ||
+		rect.bl.x < 2 || rect.bl.y < 2 || rect.bl.x > 637 || rect.bl.y > 477){
+		return false;
+	}*/
+	// make sure the sides are close to the right ratio of a rect
+	// some really odd shapes get confusing
+	double ratio = norm(rect.ur-rect.ul)/norm(rect.br-rect.bl);
+	if( ratio < .7 || ratio > 1.4 ) {
+		return false;
+	}
+	ratio = norm(rect.ur-rect.br)/norm(rect.ul-rect.bl);
+	if( ratio < .7 || ratio > 1.4 ) {
+		return false;
+	}
+
+	return true;
+}
+
+// sum over values between these two points and normalize
+// see Bresenham's Line Algorithm for the logic of moving
+// over all the pixels between these two points.
+double ProcessorData::calcHistComponent(
+		cv::Point2i start,
+		cv::Point2i end,
+		cv::Mat thresh_img){
+	int dx = abs(end.x - start.x);
+	int dy = abs(end.y - start.y);
+	int sx = (start.x < end.x) ? 1 : -1;
+	int sy = (start.y < end.y) ? 1 : -1;
+	int error = dx-dy;
+
+	int total = 0;
+	int value = 0;
+	int total_error;
+#if LOCAL_DEBUG
+	IplImage gd = *global_display;
+#endif
+	IplImage ti = thresh_img;
+	while(1){
+		total++;
+		
+		uchar* ptr = (uchar*) (ti.imageData + start.y * ti.widthStep + start.x);
+		if((int) *ptr) value++;
+		// draw line checked
+#if LOCAL_DEBUG
+		uchar* ptr2 = (uchar*) (gd.imageData + start.y * gd.widthStep + start.x*3);
+		*ptr2++ = 0;
+		*ptr2++ = 255;
+		*ptr2 = 0;
+#endif
+		if(start.x == end.x && start.y == end.y) break;
+		total_error = 2 * error;
+		if(total_error > -dy){
+			error -=  dy;
+			start.x += sx;
+		}
+		if(total_error < dx){
+			error += dx;
+			start.y += sy;
+		}
+	}
+	return (double)value/(double)total;
+}
+
+// just a distance function
+double chiSquared(int length, double* histA, double* histB){
+	double sum = 0;
+	for(int i=0; i<length;i++){
+		double diff = *(histB+i) - *(histA+i);
+		sum += (diff * diff) / *(histA+i);
+	}
+	return sum;
+}
+// euclidiean dist function
+double L2_dist(int length, double* histA, double* histB){
+	double sum = 0;
+	for(int i=0; i<length;i++){
+		double diff = *(histB+i) - *(histA+i);
+		sum += (diff * diff);
+	}
+	return sqrt(sum);
+}
+
+// calc and compare the histograms to the desired
+double ProcessorData::checkHistogram(FullRect rect, cv::Mat thresh_img){
+	// found horiz histogram
+	double hist_lr[HIST_SIZE];
+	// step size along left edge
+	cv::Point2f delta_left = (rect.ul - rect.bl)*HIST_SIZE_F;
+	// step size along right edge
+	cv::Point2f delta_right = (rect.ur - rect.br)*HIST_SIZE_F;
+	// sum each left to right line for the histogram
+	for(int i=0; i<HIST_SIZE; i++){
+		hist_lr[i] = calcHistComponent(rect.bl+i*delta_left,
+				rect.br+i*delta_right,thresh_img);
+	}
+	double check_vert = L2_dist(HIST_SIZE, vert_hist, hist_lr);
+	// found vert histogram
+	double hist_ub[HIST_SIZE];
+	// step size along bottom edge
+	cv::Point2f delta_bottom = (rect.bl - rect.br)*HIST_SIZE_F;
+	// step size along top edge
+	cv::Point2f delta_top = (rect.ul - rect.ur)*HIST_SIZE_F;
+	// sum each top to bottom line for the histogram
+	for(int i=0; i<HIST_SIZE; i++){
+		hist_ub[i] = calcHistComponent(rect.ur+i*delta_top,
+				rect.br+i*delta_bottom,thresh_img);
+	}
+	double check_horz = L2_dist(HIST_SIZE, horz_hist, hist_ub);
+
+	// average the two distances
+	double check = (check_vert + check_horz)/2.0;
+	return check;
+}
+
+// return smallest
+template<class T> inline T Min3(T x, T y, T z) {
+  return y <= z ? (x <= y ? x : y)
+                : (x <= z ? x : z);
+}
+
+// return largest
+template<class T> inline T Max3(T x, T y, T z) {
+  return y >= z ? (x >= y ? x : y)
+                : (x >= z ? x : z);
+}
+
+// transforms the contour
+void makeConvex(std::vector<cv::Point> *contour){
+	std::vector<cv::Point2i> hull;
+	convexHull(*contour, hull, false);
+	*contour = hull;
+}
+
+// basic init
+ProcessorData::ProcessorData(int width, int height, bool is_90_) {
+	is_90 = is_90_;
+	// series b images from nasa
+	h1=79;  s1=53;   v1=82;
+	h2=200; s2=255; v2=255;
+	// For images from Jerry
+	//h1=79;  s1=0;   v1=11;
+	//h2=160; s2=255; v2=255;
+	img_width = width;
+	img_height = height;
+	buffer_size = img_height * img_width * 3;
+#if LOCAL_DEBUG
+        global_display = cvCreateImage(cvSize(width, height),
+                                       IPL_DEPTH_8U, 3);
+#endif
+	grey_image = cvCreateImage(cvSize(width, height),
+			           IPL_DEPTH_8U, 1);
+	grey_mat = new cv::Mat(grey_image);
+	
+	// calculate a desired histogram before we start
+	int j = 0;
+	for(double i=0; j<HIST_SIZE; i+=HIST_SIZE_F){
+		if (is_90) {
+			if(i < 2.0/12.0 || i > (1.0-2.0/12.0) ) horz_hist[j] = 1;
+			else horz_hist[j] = 0.10;
+			if(i < 2.0/24.0 || i > (1.0-2.0/24.0) ) vert_hist[j] = 1;
+			else vert_hist[j] = 4.0/24.0;
+		} else {
+			if(i < 2.0/12.0 || i > (1.0-2.0/12.0) ) vert_hist[j] = 1;
+			else vert_hist[j] = 0.10;
+			if(i < 2.0/24.0 || i > (1.0-2.0/24.0) ) horz_hist[j] = 1;
+			else horz_hist[j] = 4.0/24.0;
+		}
+		j++;
+	}
+
+        src_header_image = cvCreateImage(cvSize(width, height),
+            IPL_DEPTH_8U, 3);
+}
+
+// throw stuff away
+ProcessorData::~ProcessorData() {
+	cvReleaseImage(&grey_image);
+	cvReleaseImage(&src_header_image);
+	delete(grey_mat);
+}
+
+// reset processor data freeing as little as possible.
+void ProcessorData::clear() {
+	target_list.clear();
+	contour_pairs.clear();
+	hierarchy.clear();
+}
+
+
+// r,g,b values are from 0 to 255
+// h = [0,255], s = [0,255], v = [0,255]
+//		if s == 0, then h = 0 (undefined)
+void ProcessorData::RGBtoHSV(uchar r, uchar g, uchar b,
+		uchar *h, uchar *s, uchar *v ) {
+	uchar min, max, delta;
+	min = Min3( r, g, b );
+	max = Max3( r, g, b );
+	*v = max;
+	delta = max - min;
+	if (max == 0 || delta == 0) {
+		*s = 0;
+		*h = 0;
+		return;
+	}
+	*s = (255 * long(delta))/max;
+	if (max == r) {
+		*h = 0 + 43*(g - b)/(delta);
+	} else if (max == g) {
+		*h = 85 + 43*(b - r)/(delta);
+	} else {
+		*h = 171 + 43*(r - g)/(delta);
+	}
+}
+
+// keep anything that is in our HVS wedge
+// by far the longest running function in this code
+void ProcessorData::threshold(uchar* buffer) {
+#if LOCAL_DEBUG
+  uchar * draw_buffer = (uchar *) global_display->imageData;
+#endif
+  for (int i = 0, j = 0; i < (buffer_size); i+= 3, j++) {
+    uchar r = buffer[i + 2];
+    uchar g = buffer[i + 1];
+    uchar b = buffer[i + 0];
+    uchar h, s, v;
+
+    RGBtoHSV(r, g, b, &h, &s, &v);
+
+    if (g > 128) {
+#if LOCAL_DEBUG
+      draw_buffer[i + 0] = 120;
+      draw_buffer[i + 1] = 80;
+      draw_buffer[i + 2] = 70;
+#endif
+      grey_image->imageData[j] = 255;
+    } else if (h == 0 && s == 0 && v >= v1 && v <= v2) { 
+      // Value thresholds invalid pixels.
+#if LOCAL_DEBUG
+      draw_buffer[i + 0] = 200;
+      draw_buffer[i + 1] = 50;
+      draw_buffer[i + 2] = 100;
+#endif
+      grey_image->imageData[j] = 255;
+    } else if (h >= h1 && h <= h2 && v >= v1 &&
+               v <= v2 && s >= s1 && s <= s2){
+      // HSV Thresholded image.
+#if LOCAL_DEBUG
+      draw_buffer[i + 0] = 255;
+      draw_buffer[i + 1] = 0;
+      draw_buffer[i + 2] = 0;
+#endif
+      grey_image->imageData[j] = 255;
+    } else {
+      // Display the unmodified image.
+#if LOCAL_DEBUG
+      draw_buffer[i + 0] = buffer[i + 0];
+      draw_buffer[i + 1] = buffer[i + 1];
+      draw_buffer[i + 2] = buffer[i + 2];
+#endif
+      grey_image->imageData[j] = 0;
+    }
+
+  }
+
+}
+
+// run find contours and try to make them squares
+void ProcessorData::getContours() {
+	std::vector<std::vector<cv::Point> > raw_contours;
+	//cv::findContours(*grey_mat, raw_contours, hierarchy, CV_RETR_LIST,
+	//		CV_CHAIN_APPROX_SIMPLE);
+	cv::findContours(*grey_mat, raw_contours, hierarchy, CV_RETR_EXTERNAL,
+			CV_CHAIN_APPROX_SIMPLE);
+#if LOCAL_DEBUG
+	cv::Mat global_mat(global_display);
+	cv::Scalar color(255,0,0);
+	drawContours(global_mat,raw_contours,-1,color,1);
+
+	std::vector<std::vector<cv::Point> > p_contours;
+#endif
+	if (!raw_contours.empty()) {
+		std::vector<std::vector<cv::Point2i> >::iterator contour_it;
+		for (contour_it=raw_contours.begin();
+				contour_it != raw_contours.end();
+				contour_it++) {
+			// make the contours convex
+			makeConvex(&(*contour_it));
+			std::vector<cv::Point> contour;
+			//then make them rectangle
+			approxPolyDP(*contour_it, contour, 9, true);
+			// stick the raw and processed contours together
+			std::pair<std::vector<cv::Point>,
+				std::vector<cv::Point> > a_pair(
+						*contour_it, contour);
+#if LOCAL_DEBUG
+			p_contours.push_back(contour);
+#endif
+			// and put them in a list
+			contour_pairs.push_back(a_pair);
+		}
+	}
+#if LOCAL_DEBUG
+	cv::Scalar color2(0,0,255);
+	drawContours(global_mat,p_contours,-1,color2,CV_FILLED);
+#endif
+}
+
+// filter the contours down to a list of targets
+void ProcessorData::filterToTargets() {
+  std::vector<std::pair<
+    std::vector<cv::Point>,
+    std::vector<cv::Point> > >::iterator contour_it;
+  for(contour_it=contour_pairs.begin();
+      contour_it != contour_pairs.end();
+      contour_it++){
+    double check = 0;
+    std::vector<cv::Point> raw_contour = std::get<0>(*contour_it);
+    std::vector<cv::Point> contour = std::get<1>(*contour_it);
+    FullRect rect = calcFullRect(&contour);
+    if(contour.size() == 4 &&
+        cullObvious(rect, contourArea(contour)) &&
+        (check = checkHistogram(rect, *grey_mat)) <= HIST_MATCH){
+      // now we have a target, try to improve the square
+#if LOCAL_DEBUG
+      /*	printf("________\n");
+                printf("\tcont= %d raw= %d\n",
+                (int)contour.size(), (int)raw_contour.size());
+                std::vector<cv::Point2i>::iterator point_it;
+                for(point_it=raw_contour.begin();
+                point_it != raw_contour.end(); point_it++){
+                printf("(%d,%d)", point_it->x, point_it->y);
+                }
+                printf("\n");*/
+#endif
+      target_list.push_back(Target(contour,
+            raw_contour, rect, check, is_90));
+    }
+    if (contour.size() == 4 && cullObvious(rect, contourArea(contour))) {
+    	LOG(DEBUG, "check= %.2f\n", check);
+    }
+  }
+}
+
diff --git a/vision/CameraProcessor.h b/vision/CameraProcessor.h
new file mode 100644
index 0000000..096defb
--- /dev/null
+++ b/vision/CameraProcessor.h
@@ -0,0 +1,88 @@
+#ifndef VISION_CAMERA_PROCESSOR_H_
+#define VISION_CAMERA_PROCESSOR_H_
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <utility>
+#include <vector>
+
+#include "opencv2/imgproc/imgproc.hpp"
+
+// an over described geometric representation of a rectangle
+class FullRect {
+ public:
+  FullRect();
+  cv::Point2f ur; // upper right
+  cv::Point2f ul; // upper left
+  cv::Point2f br; // bottom right
+  cv::Point2f bl; // bottom_left
+  cv::Point2f centroid; //centroid
+};
+
+// All data needed once a target is found
+class Target {
+	public:
+		Target(std::vector<cv::Point> new_contour,
+			std::vector<cv::Point> new_raw_contour,
+			FullRect new_rect, int new_weight, bool _is_90);
+		void refineTarget();
+		double getHeight(bool is_90);
+		FullRect rect; // geometric representation of the target
+		std::vector<cv::Point> this_contour; // opencv contour of target
+		std::vector<cv::Point> raw_contour; // opencv contour of target
+		double height; // top target to robot
+		double weight; // confidence in this target
+};
+
+// main class for processing image data. All relavent data should be
+// accessible through this structure.
+class ProcessorData {
+	public:
+		ProcessorData(int width, int height, bool is_90_);
+		~ProcessorData();
+		void RGBtoHSV(uchar r, uchar g, uchar b,
+			uchar *h, uchar *s, uchar *v);
+		void threshold(uchar* buffer);
+		void getContours();
+		void filterToTargets();
+		void clear();
+	//protected:
+		int img_width; // all images should be this width
+		int img_height; // and this height
+		bool is_90;
+		int buffer_size; // width * height * 3
+		IplImage *grey_image; // thresholded image
+		cv::Mat *grey_mat; // Matrix representaion (just a header)
+		std::vector<std::pair<std::vector<cv::Point>,
+			std::vector<cv::Point> > > contour_pairs;
+		//std::vector<std::vector<cv::Point> > contours; // filtered contours
+		//yystd::vector<std::vector<cv::Point> > raw_contours; //original contours
+		std::vector<cv::Vec4i> hierarchy; // ordering on contours
+		cv::MemStorage g_storage; // opencv storage
+		static const int HIST_SIZE = 20; // dimension of histogram
+								 // ie number of scan lines
+		static constexpr double HIST_SIZE_F = 1.0/20.0; // step size
+											// should be 1/HIST_SIZE
+		double vert_hist[HIST_SIZE]; // desired vertical histogram
+		double horz_hist[HIST_SIZE]; // desired horizontal histogram
+		// defines the minimum dist for a match
+		static constexpr double HIST_MATCH = 1.9;
+		double calcHistComponent(
+				cv::Point2i start,
+				cv::Point2i end,
+				cv::Mat thresh_img);
+		double checkHistogram(
+				FullRect rect,
+				cv::Mat thresh_img);
+	public:
+		int h1, s1, v1, h2, s2, v2; // HSV min and max
+									// must be public for tuning
+		IplImage * global_display;
+
+		IplImage *src_header_image; // header for main image
+		std::vector<Target> target_list; // list of found targets
+};
+
+#endif  // VISION_CAMERA_PROCESSOR_H_
diff --git a/vision/GoalMaster.cpp b/vision/GoalMaster.cpp
new file mode 100644
index 0000000..8bf1aba
--- /dev/null
+++ b/vision/GoalMaster.cpp
@@ -0,0 +1,61 @@
+#include "math.h"
+
+#include "aos/common/time.h"
+#include "aos/linux_code/init.h"
+#include "aos/common/logging/logging.h"
+
+#include "frc971/queues/GyroAngle.q.h"
+#include "frc971/queues/CameraTarget.q.h"
+
+#include "vision/RingBuffer.h"
+#include "vision/SensorProcessor.h"
+
+using ::frc971::vision::RingBuffer;
+using ::frc971::sensors::gyro;
+using ::frc971::vision::targets;
+using ::frc971::vision::target_angle;
+using ::frc971::kPixelsToMeters;
+using ::frc971::kMetersToShooterSpeeds;
+using ::frc971::kMetersToShooterAngles;
+using ::frc971::interpolate;
+
+int main() {
+  //RingBuffer< ::aos::time::Time, double> buff;
+  ::aos::InitNRT();
+  while (true) {
+    //gyro.FetchNextBlocking();
+    //buff.Sample(gyro->sent_time, gyro->angle);
+    if (targets.FetchNext()) {
+      /*::aos::time::Time stamp = ::aos::time::Time::InNS(targets->timestamp);
+      double angle_goal =
+          buff.ValueAt(stamp) -
+					M_PI / 2.0 * targets->percent_azimuth_off_center / 2.0;
+      printf("%g ",angle_goal);
+      printf("%g\n",gyro->angle);*/
+
+      double meters = interpolate(
+          sizeof(kPixelsToMeters) / sizeof(kPixelsToMeters[0]),
+          kPixelsToMeters,
+          targets->percent_elevation_off_center);
+      const double shooter_speed = interpolate(
+          sizeof(kMetersToShooterSpeeds) / sizeof(kMetersToShooterSpeeds[0]),
+          kMetersToShooterSpeeds,
+          meters);
+      const double shooter_angle = interpolate(
+           sizeof(kMetersToShooterAngles) / sizeof(kMetersToShooterAngles[0]),
+           kMetersToShooterAngles,
+           meters);
+
+      LOG(DEBUG, "%+f=> think target is %f meters away Speed %f Angle %f\n",
+          targets->percent_elevation_off_center,
+          meters, shooter_speed, shooter_angle);
+
+      target_angle.MakeWithBuilder()
+          /*.target_angle(angle_goal)*/
+          .shooter_speed(shooter_speed)
+          .shooter_angle(shooter_angle)
+          .Send();
+    }
+  }
+  ::aos::Cleanup();
+}
diff --git a/vision/JPEGRoutines.cpp b/vision/JPEGRoutines.cpp
new file mode 100644
index 0000000..e3dc254
--- /dev/null
+++ b/vision/JPEGRoutines.cpp
@@ -0,0 +1,192 @@
+#include "vision/JPEGRoutines.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <string.h>
+
+#include "aos/common/time.h"
+
+#include "vision/OpenCVWorkTask.h"
+
+namespace frc971 {
+namespace vision {
+
+/* This is also adapted from libjpeg to be used on decompression tables rather than
+ * compression tables as it was origionally intended
+ */
+void decompress_add_huff_table (j_decompress_ptr cinfo,
+    JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val)
+/* Define a Huffman table */
+{
+  int nsymbols, len;
+
+  if (*htblptr == NULL)
+    *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+
+  /* Copy the number-of-symbols-of-each-code-length counts */
+  memcpy((*htblptr)->bits, bits, sizeof((*htblptr)->bits));
+
+  /* Validate the counts.  We do this here mainly so we can copy the right
+   * number of symbols from the val[] array, without risking marching off
+   * the end of memory.  jchuff.c will do a more thorough test later.
+   */
+  nsymbols = 0;
+  for (len = 1; len <= 16; len++)
+    nsymbols += bits[len];
+  if (nsymbols < 1 || nsymbols > 256){
+    fprintf(stderr,"%s:%d: Error, bad huffman table",__FILE__,__LINE__);
+    exit(-1);
+  }
+
+  memcpy((*htblptr)->huffval, val, nsymbols * sizeof(uint8_t));
+
+}
+
+/* standard_huff_tables is taken from libjpeg compression stuff
+ * and is here used to set up the same tables in the decompression structure.
+ */
+void  standard_huff_tables (j_decompress_ptr cinfo)
+  /* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
+  /* IMPORTANT: these are only valid for 8-bit data precision! */
+{
+  static const UINT8 bits_dc_luminance[17] =
+  { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
+  static const UINT8 val_dc_luminance[] =
+  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+
+  static const UINT8 bits_dc_chrominance[17] =
+  { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
+  static const UINT8 val_dc_chrominance[] =
+  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+
+  static const UINT8 bits_ac_luminance[17] =
+  { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
+  static const UINT8 val_ac_luminance[] =
+  { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+    0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+    0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
+    0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+    0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+    0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+    0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+    0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+    0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+    0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+    0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+    0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+    0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+    0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+    0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+    0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+    0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+    0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+    0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+    0xf9, 0xfa };
+
+  static const UINT8 bits_ac_chrominance[17] =
+  { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
+  static const UINT8 val_ac_chrominance[] =
+  { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
+    0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+    0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+    0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
+    0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
+    0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
+    0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
+    0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+    0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+    0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+    0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+    0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+    0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
+    0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
+    0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
+    0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
+    0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
+    0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
+    0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+    0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+    0xf9, 0xfa };
+
+  decompress_add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0],
+      bits_dc_luminance, val_dc_luminance);
+  decompress_add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0],
+      bits_ac_luminance, val_ac_luminance);
+  decompress_add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1],
+      bits_dc_chrominance, val_dc_chrominance);
+  decompress_add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1],
+      bits_ac_chrominance, val_ac_chrominance);
+}
+
+
+
+
+void process_jpeg(unsigned char *out,unsigned char *image,size_t size){
+  struct jpeg_decompress_struct cinfo;
+  struct jpeg_error_mgr jerr;
+
+  static aos::time::Time timestamp_old = aos::time::Time::Now();
+  //aos::time::Time timestamp_start = aos::time::Time::Now();
+  
+  cinfo.err = jpeg_std_error( &jerr );
+  cinfo.out_color_space = JCS_RGB;
+  jpeg_create_decompress( &cinfo );
+  //jpeg_stdio_src( &cinfo, infile );
+  jpeg_mem_src(&cinfo,image,size);
+
+  jpeg_read_header( &cinfo, TRUE );
+  standard_huff_tables (&cinfo);
+
+
+//  printf( "JPEG File Information: \n" );
+//  printf( "Image width and height: %d pixels and %d pixels.\n", cinfo.image_width, cinfo.image_height );
+//  printf( "Color components per pixel: %d.\n", cinfo.num_components );
+//  printf( "Color space: %d.\n", cinfo.jpeg_color_space );
+  //printf("JpegDecompressed\n");
+
+  jpeg_start_decompress( &cinfo );
+
+  int offset = 0;
+  int step = cinfo.num_components * cinfo.image_width;
+  unsigned char *buffers[cinfo.image_height];
+  for (int i = cinfo.image_height - 1; i >= 0; --i) {
+    buffers[i] = &out[offset]; 
+    offset += step;
+  }
+
+  while( cinfo.output_scanline < cinfo.image_height )
+  {
+    jpeg_read_scanlines(&cinfo, &buffers[cinfo.output_scanline],
+        cinfo.image_height - cinfo.output_scanline);
+  }
+
+  /* This used to do BGR to RGB conversions inline */
+/* 
+  for (int i = 0; i < (int)(cinfo.image_height * cinfo.image_width * 3); i+= 3) {
+    uint8_t b = out[i + 0];
+    uint8_t r = out[i + 2];
+    out[i + 0] = r;
+    out[i + 2] = b;
+  }
+*/
+  jpeg_finish_decompress( &cinfo );
+  jpeg_destroy_decompress( &cinfo );
+
+  aos::time::Time timestamp_end = aos::time::Time::Now();
+
+  //double jpeg_part = ((timestamp_end - timestamp_start).nsec()) / 1000000000.0;
+  //double longer_part = ((timestamp_end - timestamp_old).nsec()) / 1000000000.0;
+
+  //printf("%g %g\n",jpeg_part / longer_part,1.0 / longer_part);
+
+  timestamp_old = timestamp_end;
+
+}
+
+}  // namespace vision
+}  // namespace frc971
+
diff --git a/vision/JPEGRoutines.h b/vision/JPEGRoutines.h
new file mode 100644
index 0000000..c3b8e13
--- /dev/null
+++ b/vision/JPEGRoutines.h
@@ -0,0 +1,17 @@
+// for jpeglib.h
+#include <stdio.h>
+
+#include "libjpeg/include/jpeglib.h"
+
+namespace frc971 {
+namespace vision {
+
+void decompress_add_huff_table (j_decompress_ptr cinfo,
+    JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val);
+
+void  standard_huff_tables (j_decompress_ptr cinfo);
+
+void process_jpeg(unsigned char *out,unsigned char *image,size_t size);
+
+}  // namespace vision
+}  // namespace frc971
diff --git a/vision/OpenCVWorkTask.cpp b/vision/OpenCVWorkTask.cpp
new file mode 100644
index 0000000..982d670
--- /dev/null
+++ b/vision/OpenCVWorkTask.cpp
@@ -0,0 +1,139 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+
+#include <vector>
+#include <iostream>
+
+#include "libjpeg/include/jpeglib.h"
+
+#include "aos/common/time.h"
+#include "aos/linux_code/camera/Buffers.h"
+#include "aos/linux_code/init.h"
+#include "aos/common/logging/logging.h"
+
+#include "vision/OpenCVWorkTask.h"
+#include "vision/CameraProcessor.h"
+#include "vision/JPEGRoutines.h"
+
+
+namespace frc971 {
+namespace vision {
+
+}  // namespace vision
+}  // namespace frc971
+
+namespace {
+void SaveImageToFile(IplImage *image, const char *filename) {
+  FILE *file = fopen(filename, "w");
+
+  fputs("P3\n320 240\n255\n", file);
+  ::cv::Mat img(image);
+  for (int i = 0; i < img.rows; i++) {
+    for (int j = 0; j < img.cols; j++) {
+      // You can now access the pixel value with cv::Vec3b
+      fprintf(file, "%d %d %d ",
+          img.at<cv::Vec3b>(i,j)[0],
+          img.at<cv::Vec3b>(i,j)[1],
+          img.at<cv::Vec3b>(i,j)[2]);
+
+    }
+    fputs("\n", file);
+  }
+  fclose(file);
+}
+}
+
+#include "frc971/queues/CameraTarget.q.h"
+using frc971::vision::targets;
+
+void sender_main(){
+  ::aos::camera::Buffers buffers;
+  CvSize size;
+  size.width = ::aos::camera::Buffers::Buffers::kWidth;
+  size.height = ::aos::camera::Buffers::Buffers::kHeight;
+  unsigned char buffer[::aos::camera::Buffers::Buffers::kWidth *
+      ::aos::camera::Buffers::Buffers::kHeight * 3];
+
+  // create processing object
+  ProcessorData processor(size.width, size.height, false);
+
+  printf("started sender main\n");
+  LOG(INFO, "Camera server started\n");
+  while(true){
+    //usleep(7500);
+    size_t data_size;
+  	timeval timestamp_timeval;
+    LOG(DEBUG, "getting new image\n");
+    const void *image = buffers.GetNext(
+		    true, &data_size, &timestamp_timeval, NULL);
+    ::aos::time::Time timestamp(timestamp_timeval);
+
+    LOG(DEBUG, "Got new image\n");
+    frc971::vision::process_jpeg(
+        buffer, static_cast<unsigned char *>(const_cast<void *>(image)),
+        data_size);
+
+    // build the headers on top of the buffer
+    cvSetData(processor.src_header_image,
+              buffer,
+              ::aos::camera::Buffers::Buffers::kWidth * 3);
+
+    // Reset.
+    processor.clear();
+    // transform the buffer into targets
+    processor.threshold(buffer);
+
+    processor.getContours();
+    processor.filterToTargets();
+
+    // could be used for debug ie drawContours
+    //std::vector<std::vector<cv::Point> > target_contours;
+    //std::vector<std::vector<cv::Point> > best_contours;
+    std::vector<Target>::iterator target_it;
+    Target *best_target = NULL;
+    // run through the targets
+    LOG(DEBUG, "Found %u targets\n", processor.target_list.size());
+    for(target_it = processor.target_list.begin();
+        target_it != processor.target_list.end(); target_it++){
+      //target_contours.push_back(*(target_it->this_contour));
+      // select the highest target
+      if (best_target == NULL) {
+        best_target = &*target_it;
+      } else {
+        if (target_it->height < best_target->height) {
+          best_target = &*target_it;
+        }
+      }
+    }
+    // if we found one then send it on
+    if (best_target != NULL) {
+      LOG(DEBUG, "Target is %f\n", best_target->rect.centroid.x);
+      targets.MakeWithBuilder()
+        .percent_azimuth_off_center(
+            best_target->rect.centroid.y / (double)::aos::camera::Buffers::kHeight - 0.5)
+        .percent_elevation_off_center(
+            best_target->rect.centroid.x / (double)::aos::camera::Buffers::kWidth - 0.5)
+        .timestamp(timestamp.ToNSec())
+        .Send();
+    }
+    //static int counter = 0;
+    //if (++counter > 2) {
+      //break;
+    //}
+  }
+}
+
+
+int main(int /*argc*/, char** /*argv*/){
+  ::aos::InitNRT();
+  sender_main();
+  ::aos::Cleanup();
+}
+
diff --git a/vision/OpenCVWorkTask.h b/vision/OpenCVWorkTask.h
new file mode 100644
index 0000000..78bda5d
--- /dev/null
+++ b/vision/OpenCVWorkTask.h
@@ -0,0 +1,20 @@
+#ifndef VISION_OPENCV_WORK_TASK_H_
+#define VISION_OPENCV_WORK_TASK_H_
+
+#include <sys/types.h> 
+#include <sys/socket.h>
+
+#include "event2/buffer.h"
+#include "event2/event.h"
+#include "event2/listener.h"
+#include "event2/bufferevent.h"
+
+#include "aos/common/mutex.h"
+
+namespace frc971 {
+namespace vision {
+
+}  // namespace vision
+}  // namespace frc971
+
+#endif  // VISION_OPENCV_WORK_TASK_H_
diff --git a/vision/PacketNotifier.cpp b/vision/PacketNotifier.cpp
new file mode 100644
index 0000000..d12872e
--- /dev/null
+++ b/vision/PacketNotifier.cpp
@@ -0,0 +1,79 @@
+#include "vision/PacketNotifier.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <string.h>
+
+namespace frc971 {
+namespace vision {
+	
+void PacketNotifier::RegisterSender(){
+	close(fd[1]);
+}
+void PacketNotifier::RegisterReciever(){
+	close(fd[0]);
+}
+PacketNotifier *PacketNotifier::MMap(size_t data_size){
+	PacketNotifier *data;
+	data = (PacketNotifier *)mmap(NULL, ((data_size * 3 + 4095 + sizeof(PacketNotifier)) / 4096) * 4096, 
+			PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+	data->data_size = data_size;
+	socketpair(PF_LOCAL, SOCK_STREAM, 0, data->fd);
+	for(int i = 0;i < 3;i++){
+		data->buffs[i] = (uint8_t *)data + (sizeof(PacketNotifier) + i * data_size);
+	}
+	void *place = &(data->mutex);
+	*((int *)place) = 0; // The Mutex class needs a placement new operator. (you know, keep the masses happy);
+	data->in_flight = false;
+	data->to_send = -1;
+	data->sending = -1;
+	return data;
+}
+void *PacketNotifier::GetBuffer(){
+	mutex.Lock();
+	for(int i = 0; i < 3 ; i++){ //search for open spot.
+		if(i != sending && i != to_send){ //open
+			filling = i;
+			mutex.Unlock();
+			//printf("leasing out to fill buff # %d\n",i);
+			return buffs[i];
+		}
+	}
+	mutex.Unlock();
+	//printf("Error in the fabric of the universe\n");
+	exit(-42);
+}
+void PacketNotifier::Notify(){
+	mutex.Lock();
+	to_send = filling;
+	filling = -1;
+	mutex.Unlock();
+	// wall error
+	if(write(fd[0],"\n",1)) {}
+}
+
+void PacketNotifier::DataSent(const void * /*data*/, size_t /*datalen*/){
+	//printf("packet_sent: %d; fill: %d; to_send: %d \n",sending,filling,to_send);
+	mutex.Lock();
+	sending = -1;
+	mutex.Unlock();
+	in_flight = false;
+}
+bool PacketNotifier::GetData(char **place_to_put,size_t *length){
+	if(in_flight) return false;
+	mutex.Lock();
+	*length = data_size;
+	*place_to_put = (char *)buffs[to_send];
+	sending = to_send;
+	to_send = -1;
+	mutex.Unlock();
+	in_flight = true;
+	return true;
+}
+
+}  // namespace vision
+}  // namespace frc971
+
diff --git a/vision/PacketNotifier.h b/vision/PacketNotifier.h
new file mode 100644
index 0000000..7aff7fa
--- /dev/null
+++ b/vision/PacketNotifier.h
@@ -0,0 +1,45 @@
+#ifndef FRC971_VISION_PACKET_NOTIFIER_H_
+#define FRC971_VISION_PACKET_NOTIFIER_H_
+#include "event2/buffer.h"
+#include "event2/event.h"
+#include "event2/listener.h"
+#include "event2/bufferevent.h"
+#include "aos/common/mutex.h"
+
+#include <sys/types.h> 
+#include <sys/socket.h>
+
+namespace frc971 {
+namespace vision {
+
+/* This class lives in shared memory (using an anonomous mmap) to transfer data between
+ * the server process and the image processing process.
+ */
+struct PacketNotifier{
+ aos::Mutex mutex;
+ int fd[2];
+ //3 things can be happening:
+ //something waiting to be sent, something sending, and something getting filled (decompressed to)
+ void *buffs[3];
+ int to_send;
+ int filling;
+ int sending;
+ bool in_flight;
+ size_t data_size;
+ void Notify();
+ void RegisterSender();
+ void RegisterReciever();
+ int RecieverFD(){ return fd[1]; }
+ static PacketNotifier *MMap(size_t data_size);
+ void DataSent(const void * /*data*/, size_t /*datalen*/);
+ void *GetBuffer();
+ static void StaticDataSent(const void *data, size_t datalen, void *self){
+	 ((PacketNotifier *)(self))->DataSent(data,datalen);
+ }
+ bool GetData(char **place_to_put,size_t *length);
+};
+}  // namespace vision
+}  // namespace frc971
+
+
+#endif  //FRC971_VISION_PACKET_NOTIFIER_H_
diff --git a/vision/RingBuffer.h b/vision/RingBuffer.h
new file mode 100644
index 0000000..f333f29
--- /dev/null
+++ b/vision/RingBuffer.h
@@ -0,0 +1,67 @@
+#ifndef VISION_RINGBUFFER_H_
+#define VISION_RINGBUFFER_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+
+namespace frc971 {
+namespace vision {
+
+template<class T,class V>
+class RingBuffer{
+  //record class to hold sampes
+	class Samples{
+		public:
+	  T time;
+		V value;
+	};  
+	Samples *samples;
+	int current_;
+	int wraps_;
+	V value_at(int index){
+		return samples[index & 255].value;
+	}
+	T time_at(int index){
+		return samples[index & 255].time;
+	}
+	public:
+	RingBuffer(){
+		current_ = 0;
+		wraps_ = 0;
+		samples = (Samples *)malloc(sizeof(Samples) * 256);
+	}
+	// Adds samples into the ringbuffer.
+	void Sample(T time,V val){
+		current_ += 1;
+		wraps_ += current_ / 256;
+		current_ = current_ % 256;
+		samples[current_].time = time;
+		samples[current_].value = val;
+	}
+	// Binary Search to find and interpolate the values.
+	V ValueAt(T time){
+		int start = current_ - 255;
+		int end = current_;
+		if(start < 0 && !wraps_){ 
+			start = 0;
+		}   
+		int max = end;
+		int min = start;
+		while(end - start > 1){
+			int mid = (start + end) / 2;
+			Samples check = samples[mid & 255];
+			if(check.time < time){
+				start = mid;
+				min = mid;
+			}else{
+				max = mid;
+				end = mid;
+			}   
+		}
+		return value_at(min) + (value_at(max) - value_at(min)) *
+		((time - time_at(min)).ToSeconds()/(time_at(max) - time_at(min)).ToSeconds());
+	}
+};
+};  // vision
+};  // frc971
+#endif // VISION_RINGBUFFER_H_
diff --git a/vision/SensorProcessor.cpp b/vision/SensorProcessor.cpp
new file mode 100644
index 0000000..2060956
--- /dev/null
+++ b/vision/SensorProcessor.cpp
@@ -0,0 +1,53 @@
+#include "vision/SensorProcessor.h"
+
+#include <stdio.h>
+
+namespace frc971 {
+
+// give a set of x -> fx pairs find a range for our value
+// then interpolate between and return an interpolated fx.
+// If the value is off the end just extend the line to
+// meet our point. If something does go wrong (and it
+// never should) it will return -1.
+double interpolate(int num_interp_vals,
+		const Interpolation *interp, double value) {
+	double dy;
+	double dx;
+	double a;
+	double intercept;
+	//printf("for val %.1f\n", value); 
+	if (value < interp[0].x) {
+		// if closer than nearest 
+		dy = interp[1].fx - interp[0].fx;
+		dx = interp[1].x - interp[0].x;
+		a = value - interp[0].x;
+		intercept = interp[0].fx;
+		//printf("LESS THAN\n");
+	} else if (value > interp[num_interp_vals-1].x){
+		// if further than furthest 
+		dy = interp[num_interp_vals-1].fx - interp[num_interp_vals-2].fx;
+		dx = interp[num_interp_vals-1].x - interp[num_interp_vals-2].x;
+		a = value - interp[num_interp_vals-2].x;
+		intercept = interp[num_interp_vals-2].fx;
+		//printf("GT THAN\n");
+	} else {
+		//printf("gh0\n");
+		// scan for range
+		for(int i=0; i<num_interp_vals-1; i++){
+			if(value >= interp[i].x && value <= interp[i+1].x){
+		//		printf("(%.1f,%.1f)=(%.1f,%.1f)\n",
+		//				interp[i].x, interp[i+1].x,
+		//				interp[i].fx, interp[i+1].fx);
+				double lambda =
+					(value - interp[i].x)/(interp[i+1].x - interp[i].x);
+				return (1-lambda)*interp[i].fx + lambda*interp[i+1].fx;
+			}
+		}
+		// this should maybe be an assert
+		return -1;
+	}
+	
+	return ( (dy/dx)*a + intercept );
+}
+
+}  // namespace frc971
diff --git a/vision/SensorProcessor.h b/vision/SensorProcessor.h
new file mode 100644
index 0000000..daf24be
--- /dev/null
+++ b/vision/SensorProcessor.h
@@ -0,0 +1,45 @@
+#ifndef VISION_SENSOR_PROCESSOR_H_
+#define VISION_SENSOR_PROCESSOR_H_
+
+namespace frc971 {
+
+// struct maps a single point x to to a value f of x
+typedef struct {
+	double x;
+	double fx;
+} Interpolation;
+
+static const Interpolation kPixelsToMeters[] = {
+  {-0.050781, 4.7498},
+  {-0.0375, 4.318},
+  {0.028125, 3.9878},
+  {0.080469, 3.51},
+  {0.126563, 3.1496},
+  {0.131, 2.9972},
+  {0.144, 2.921},
+  {0.196, 3.2258},
+  // Below here is junk because it starts coming off of the tower base.
+  {0.296875, 2.667},
+  {0.351562, 2.3876},
+};
+
+// Must be in reverse order in meters.
+static const Interpolation kMetersToShooterSpeeds[] = {
+  {2.0, 375.0},
+  {3.0, 360.0},
+  {4.5, 375.0},
+};
+
+static const Interpolation kMetersToShooterAngles[] = {
+  {3.0, 0.68},
+  {3.7, 0.635},
+  {4.15, 0.58},
+  {5.0, 0.51},
+};
+
+double interpolate(int num_interp_vals,
+		const Interpolation *interp, double value);
+
+}  // namespace frc971
+
+#endif  // VISION_SENSOR_PROCESSOR_H_
diff --git a/vision/bmp_stream/bmp.rb b/vision/bmp_stream/bmp.rb
new file mode 100644
index 0000000..122c9de
--- /dev/null
+++ b/vision/bmp_stream/bmp.rb
@@ -0,0 +1,11 @@
+class BMPHeader
+	def initialize(width,height)
+		@width = width
+		@height = height
+	end
+	def text()
+		size = @width * @height * 3
+		return ["BM",size + 54,"\0\0\0\0",54,40,@width,
+			@height,1,24,0,size,2835,2835,0,0].pack("a2Ia4IIIIssIIIIII")
+	end
+end
diff --git a/vision/bmp_stream/bmp_dump.rb b/vision/bmp_stream/bmp_dump.rb
new file mode 100644
index 0000000..6c5133c
--- /dev/null
+++ b/vision/bmp_stream/bmp_dump.rb
@@ -0,0 +1,45 @@
+require "socket"
+
+require "bmp"
+sock = TCPSocket.new(ARGV[0] || "fitpc",8020)
+$width = 640 / 2
+$height = 480 / 2
+$header = BMPHeader.new($width,$height).text()
+
+
+
+require "rubygems"
+require "gtk2"
+
+
+$image = Gtk::Image.new()
+$window = Gtk::Window.new()
+$window.add($image)
+$window.show_all()
+$window.signal_connect("delete-event") { Gtk.main_quit}
+
+loader = Gdk::PixbufLoader.new
+loader.write($header)
+data = sock.read($width * $height * 3)
+loader.last_write(data)
+loader.close
+$image.pixbuf = loader.pixbuf
+$oldtime = Time.now
+i = 0
+Gtk.idle_add do
+	loader = Gdk::PixbufLoader.new
+	loader.write($header)
+	data = sock.read($width * $height * 3)
+#	(640 * 480).times do |i| #BGR -> RGB
+#		b,g,r = data[i * 3 + 0],data[i * 3 + 1],data[i * 3 + 2]
+#		data[i * 3 + 0],data[i * 3 + 1],data[i * 3 + 2] = r,g,b
+#	end
+	loader.last_write(data)
+	loader.close
+	new_time = Time.now()
+	puts 1 / (new_time - $oldtime)
+	$oldtime = new_time
+	$image.pixbuf = loader.pixbuf
+end
+
+Gtk.main()
diff --git a/vision/bmp_stream/bmp_stream_from_file.rb b/vision/bmp_stream/bmp_stream_from_file.rb
new file mode 100644
index 0000000..3324484
--- /dev/null
+++ b/vision/bmp_stream/bmp_stream_from_file.rb
@@ -0,0 +1,43 @@
+require "socket"
+$header = File.open("header.bmp") { |f| f.read(54)} 
+
+
+sock = File.open("output.bmp_stream")
+#TCPSocket.new(ARGV[0] || "fitpc",8020)
+
+
+
+require "rubygems"
+require "gtk2"
+
+
+$image = Gtk::Image.new()
+$window = Gtk::Window.new()
+$window.add($image)
+$window.show_all()
+$window.signal_connect("delete-event") { Gtk.main_quit}
+
+loader = Gdk::PixbufLoader.new
+loader.write($header)
+data = sock.read(320 * 240 * 3)
+loader.last_write(data)
+loader.close
+$image.pixbuf = loader.pixbuf
+$oldtime = Time.now
+Gtk.timeout_add(1000) do 
+	loader = Gdk::PixbufLoader.new
+	loader.write($header)
+	data = sock.read(320 * 240 * 3)
+#	(640 * 480).times do |i| #BGR -> RGB
+#		b,g,r = data[i * 3 + 0],data[i * 3 + 1],data[i * 3 + 2]
+#		data[i * 3 + 0],data[i * 3 + 1],data[i * 3 + 2] = r,g,b
+#	end
+	loader.last_write(data)
+	loader.close
+	new_time = Time.now()
+	puts 1.0 / (new_time - $oldtime)
+	$oldtime = new_time
+	$image.pixbuf = loader.pixbuf
+end
+
+Gtk.main()
diff --git a/vision/bmp_stream/bmp_stream_to_file.rb b/vision/bmp_stream/bmp_stream_to_file.rb
new file mode 100644
index 0000000..962bb2d
--- /dev/null
+++ b/vision/bmp_stream/bmp_stream_to_file.rb
@@ -0,0 +1,20 @@
+require "socket"
+$header = File.open("header.bmp") { |f| f.read(54)} 
+
+
+sock = TCPSocket.new(ARGV[0] || "fitpc",8020)
+
+
+
+require "rubygems"
+require "gtk2"
+
+
+
+File.open("output.bmp_stream","w+") do |file|
+	400.times do |i|
+		data = sock.read(320 * 240 * 3)
+		file.print(data)
+		puts "frame: #{i}"
+	end
+end
diff --git a/vision/tests/FieldDBGCamProc.cpp b/vision/tests/FieldDBGCamProc.cpp
new file mode 100644
index 0000000..f23b541
--- /dev/null
+++ b/vision/tests/FieldDBGCamProc.cpp
@@ -0,0 +1,210 @@
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <vector>
+
+#include "../CameraProcessor.h"
+#include "../SensorProcessor.h"
+
+#include "opencv2/highgui/highgui.hpp"
+
+const int num_names = 39;
+
+
+static const bool USE_ROTATED = true;
+static const int use_width = 320;
+static const int use_height = 240;
+const char * image_names[num_names] = {
+			"NASA_bmp/img26_series_b_side_204_e65.jpg",
+			"NASA_bmp/img19_series_b_side_110_e65.jpg",
+			"NASA_bmp/img12_series_b_center_224_e65.jpg",
+			"NASA_bmp/img23_series_b_side_101_e65.jpg",
+			"NASA_bmp/img15_series_b_side_230_e65.jpg",
+			"NASA_bmp/img10_series_b_center_203_e65.jpg",
+			"NASA_bmp/img11_series_b_center_203_e65.jpg",
+			"NASA_bmp/img13_series_b_center_260_e65.jpg",
+			"NASA_bmp/img14_series_b_center_251_e65.jpg",
+			"NASA_bmp/img16_series_b_side_196_e65.jpg",
+			"NASA_bmp/img17_series_b_side_160_e65.jpg",
+			"NASA_bmp/img18_series_b_side_140_e65.jpg",
+			"NASA_bmp/img1_center_200_e65.jpg",
+			"NASA_bmp/img20_series_b_side_114_e65.jpg",
+			"NASA_bmp/img21_series_b_side_137_e65.jpg",
+			"NASA_bmp/img22_center field_e10.jpg",
+			"NASA_bmp/img22_dog Center Field_e10.jpg",
+			"NASA_bmp/img22_series_b_side_150_e65.jpg",
+			"NASA_bmp/img23_center field_e10.jpg",
+			"NASA_bmp/img24_center field_e10.jpg",
+			"NASA_bmp/img24_series_b_side_104_e65.jpg",
+			"NASA_bmp/img25_series_b_side_195_e65.jpg",
+			"NASA_bmp/img27_series_b_side_192_e65.jpg",
+			"NASA_bmp/img28_series_b_side_192_e65.jpg",
+			"NASA_bmp/img29_series_b_side_186_e65.jpg",
+			"NASA_bmp/img2_center_207_e65.jpg",
+			"NASA_bmp/img30_series_b_side_177_e65.jpg",
+			"NASA_bmp/img31_series_b_side_176_e65.jpg",
+			"NASA_bmp/img32_series_b_side_212_e65.jpg",
+			"NASA_bmp/img33_series_b_side_251_e65.jpg",
+			"NASA_bmp/img34_series_b_side_272_e65.jpg",
+			"NASA_bmp/img35_series_b_side_23+219_e65.jpg",
+			"NASA_bmp/img3_center_180_e65.jpg",
+			"NASA_bmp/img4_series_b_center_106_e65.jpg",
+			"NASA_bmp/img5_series_b_center_122_e65.jpg",
+			"NASA_bmp/img6_series_b_center_145_e65.jpg",
+			"NASA_bmp/img7_series_b_center_174_e65.jpg",
+			"NASA_bmp/img8_series_b_center_196_e65.jpg",
+			"NASA_bmp/img9_series_b_center_201_e65.jpg"};
+
+const char	* WINDOW_NAME	= "Treshhold Window";
+const char	* WINDOW_NAME2	= "Target Window";
+
+
+static void onMouse( int event, int x, int y, int, void* userData ) {
+	if( event != CV_EVENT_LBUTTONDOWN ) return;
+	ProcessorData *proc = (ProcessorData *) userData;
+	IplImage *image = proc->src_header_image;
+	uchar b = *((uchar*) (image->imageData + y*image->widthStep + 3*x));
+	uchar g = *((uchar*) (image->imageData + y*image->widthStep + 3*(x+1)));
+	uchar r = *((uchar*) (image->imageData + y*image->widthStep + 3*(x+2)));
+	
+	uchar h=0;
+	uchar s=0;
+	uchar v=0;
+	proc->RGBtoHSV(r, g, b, &h, &s, &v);
+
+	
+	*((uchar*) (image->imageData + y*image->widthStep + 3*x)) = 128;
+	*((uchar*) (image->imageData + y*image->widthStep + 3*(x+1))) = 128;
+	*((uchar*) (image->imageData + y*image->widthStep + 3*(x+2))) = 255;
+	
+	cv::Mat src(image);
+	//cv::imshow("test", src);
+
+	printf("got click (%d,%d)= <%d,%d,%d> -- [%d,%d,%d]\n",
+			x, y, r, g, b, h, s, v);
+}
+
+
+int main( int argc, char *argv[] ){
+	ProcessorData processor(use_width, use_height, USE_ROTATED);
+	int img_cycle = 0;
+	int thresh = 100;
+	
+	cvStartWindowThread();
+
+	cvNamedWindow ("cnt", CV_WINDOW_AUTOSIZE);
+	cvNamedWindow ("GLOBAL", CV_WINDOW_AUTOSIZE);
+	//cvNamedWindow ("Grey Img", CV_WINDOW_AUTOSIZE);
+	//cvNamedWindow ("test", CV_WINDOW_AUTOSIZE);
+	cvNamedWindow (WINDOW_NAME2, CV_WINDOW_AUTOSIZE);
+	cvNamedWindow (WINDOW_NAME, CV_WINDOW_AUTOSIZE);
+
+	cvMoveWindow(WINDOW_NAME,0,0);
+	cvMoveWindow("GLOBAL",325,0);
+	cvMoveWindow(WINDOW_NAME2,650,0);
+	//cvMoveWindow("Grey Img", 0, 275);
+	//cvMoveWindow("test", 325, 275);
+	cvMoveWindow("cnt",1100,100);
+	//Creating the trackbars
+	cvCreateTrackbar("H1","cnt",&processor.h1,360,0);
+	cvCreateTrackbar("H2","cnt",&processor.h2,360,0);
+	cvCreateTrackbar("S1","cnt",&processor.s1,255,0);
+	cvCreateTrackbar("S2","cnt",&processor.s2,255,0);
+	cvCreateTrackbar("V1","cnt",&processor.v1,255,0);
+	cvCreateTrackbar("V2","cnt",&processor.v2,255,0);
+	
+	while (img_cycle >= 0) {
+		processor.clear();
+		printf("%d = %s\n", img_cycle, image_names[img_cycle]);
+		processor.src_header_image = cvLoadImage(image_names[img_cycle]);
+		cvCopy(processor.src_header_image, processor.global_display);
+
+		cv::setMouseCallback( WINDOW_NAME2, onMouse,
+				(void *)&processor );
+
+		cv::Mat global_mat(processor.global_display);
+		cv::Mat src_mat(processor.src_header_image);
+
+		// These lines are the vision processing, the rest of main
+		// is just fluff
+		processor.threshold((uchar *)
+				processor.src_header_image->imageData);
+		processor.getContours();
+		processor.filterToTargets();
+
+		if(!processor.target_list.empty()){
+			std::vector<std::vector<cv::Point> > target_contours;
+			std::vector<std::vector<cv::Point> > best_contours;
+			std::vector<std::vector<cv::Point> > raw_contours;
+			std::vector<Target>::iterator target_it;
+			Target *best_target = NULL;
+			int i = 0;
+			for(target_it = processor.target_list.begin();
+					target_it != processor.target_list.end(); target_it++){
+				target_contours.push_back(target_it->this_contour);
+				raw_contours.push_back(target_it->raw_contour);
+				printf("%d: h=%.1f, interp=%.1f, <x,y>=<%.1f,%.1f>\n",
+						i++, target_it->height,
+						interpolate(4, &pixel_to_dist[0], target_it->rect.centroid.x),
+						target_it->rect.centroid.x, target_it->rect.centroid.y);
+				if (best_target == NULL) {
+					best_target = &*target_it;
+				} else {
+					if (target_it->height > best_target->height) {
+						best_target = &*target_it;
+					}
+				/*	if (processor.is_90) {
+						if (target_it->rect.centroid.x > best_target->rect.centroid.x) {
+							best_target = &*target_it;
+						}
+					} else {
+						if (target_it->rect.centroid.y < best_target->rect.centroid.y) {
+							best_target = &*target_it;
+						}
+					}*/
+				}
+			}
+			best_contours.push_back(best_target->this_contour);
+			//drawContours(global_mat,target_contours,-1,color,CV_FILLED);
+			cv::imshow(WINDOW_NAME, src_mat);
+			//cv::imshow("Grey Img", *processor.grey_mat);
+			cv::Scalar color(0,0,255);
+			cv::drawContours( src_mat, target_contours, -1, color, CV_FILLED );
+			cv::Scalar color2(128,0,255);
+			cv::drawContours( src_mat, best_contours, -1, color2, CV_FILLED );
+			cv::Scalar color3(0,255,0);
+			cv::drawContours( src_mat, raw_contours, -1, color3, 1 );
+		}
+		//cv::Mat grey_mat(grey_image);
+		//cv::imshow(WINDOW_NAME2, grey_mat);
+		cv::imshow("GLOBAL", global_mat);
+		cv::imshow(WINDOW_NAME2, src_mat);
+		char key = cvWaitKey(3000);
+		switch (key) {
+			case ' ':
+				img_cycle++;
+				img_cycle = img_cycle % num_names;
+				printf("%c %d= %s\n", key, img_cycle, image_names[img_cycle]);
+				break;
+			case 'g':
+				thresh++;
+				thresh = (thresh % 255);
+				printf("+ thresh= %d\n", thresh);
+				break;
+			case 'G':
+				thresh--;
+				thresh = (thresh % 255);
+				printf("- thresh= %d\n", thresh);
+				break;
+			case 'q':
+				img_cycle = -1;
+				break;
+			default:
+				break;
+		}
+		//redraw image cuz we drew all over it
+	}
+
+	cvDestroyWindow(WINDOW_NAME);
+}
+
diff --git a/vision/vision.gyp b/vision/vision.gyp
new file mode 100644
index 0000000..81e5562
--- /dev/null
+++ b/vision/vision.gyp
@@ -0,0 +1,38 @@
+{
+  'targets': [
+    {
+      'target_name': 'OpenCVWorkTask',
+      'type': 'executable',
+      'sources': [
+        'OpenCVWorkTask.cpp',
+        'CameraProcessor.cpp',
+        #'BinaryServer.cpp',
+        #'PacketNotifier.cpp',
+        'JPEGRoutines.cpp',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(AOS)/common/common.gyp:time',
+        '<(EXTERNALS):libevent',
+        '<(EXTERNALS):libjpeg',
+        '<(EXTERNALS):opencv',
+        '<(AOS)/linux_code/camera/camera.gyp:buffers',
+        '<(DEPTH)/frc971/queues/queues.gyp:queues',
+      ],
+    },
+    {
+      'target_name': 'GoalMaster',
+      'type': 'executable',
+      'sources': [
+        'GoalMaster.cpp',
+        'SensorProcessor.cpp',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(AOS)/common/common.gyp:time',
+        '<(DEPTH)/frc971/queues/queues.gyp:queues',
+        '<(AOS)/build/aos.gyp:logging',
+      ],
+    },
+  ],
+}
diff --git a/y2014/actors/actors.gyp b/y2014/actors/actors.gyp
new file mode 100644
index 0000000..48a03d0
--- /dev/null
+++ b/y2014/actors/actors.gyp
@@ -0,0 +1,110 @@
+{
+  'targets': [
+    {
+      'target_name': 'binaries',
+      'type': 'none',
+      'dependencies': [
+        'drivetrain_action',
+        'shoot_action',
+      ],
+    },
+    {
+      'target_name': 'shoot_action_queue',
+      'type': 'static_library',
+      'sources': ['shoot_action.q'],
+      'variables': {
+        'header_path': 'y2014/actors',
+      },
+      'dependencies': [
+        '<(AOS)/common/actions/actions.gyp:action_queue',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/actions/actions.gyp:action_queue',
+      ],
+      'includes': ['../../aos/build/queues.gypi'],
+    },
+    {
+      'target_name': 'shoot_action_lib',
+      'type': 'static_library',
+      'sources': [
+        'shoot_actor.cc',
+      ],
+      'dependencies': [
+        'shoot_action_queue',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        '<(DEPTH)/y2014/queues/queues.gyp:profile_params',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(DEPTH)/y2014/control_loops/shooter/shooter.gyp:shooter_queue',
+        '<(DEPTH)/y2014/control_loops/claw/claw.gyp:claw_queue',
+        '<(DEPTH)/y2014/control_loops/drivetrain/drivetrain.gyp:drivetrain_queue',
+        '<(DEPTH)/y2014/y2014.gyp:constants',
+      ],
+      'export_dependent_settings': [
+        'shoot_action_queue',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+      ],
+    },
+    {
+      'target_name': 'shoot_action',
+      'type': 'executable',
+      'sources': [
+        'shoot_actor_main.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        'shoot_action_lib',
+        'shoot_action_queue',
+      ],
+    },
+    {
+      'target_name': 'drivetrain_action_queue',
+      'type': 'static_library',
+      'sources': ['drivetrain_action.q'],
+      'variables': {
+        'header_path': 'y2014/actors',
+      },
+      'dependencies': [
+        '<(AOS)/common/actions/actions.gyp:action_queue',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/actions/actions.gyp:action_queue',
+      ],
+      'includes': ['../../aos/build/queues.gypi'],
+    },
+    {
+      'target_name': 'drivetrain_action_lib',
+      'type': 'static_library',
+      'sources': [
+        'drivetrain_actor.cc',
+      ],
+      'dependencies': [
+        'drivetrain_action_queue',
+        '<(DEPTH)/y2014/y2014.gyp:constants',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/common/util/util.gyp:phased_loop',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        '<(AOS)/common/logging/logging.gyp:queue_logging',
+        '<(EXTERNALS):eigen',
+        '<(AOS)/common/util/util.gyp:trapezoid_profile',
+        '<(DEPTH)/y2014/control_loops/drivetrain/drivetrain.gyp:drivetrain_queue',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        'drivetrain_action_queue',
+      ],
+    },
+    {
+      'target_name': 'drivetrain_action',
+      'type': 'executable',
+      'sources': [
+        'drivetrain_actor_main.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        'drivetrain_action_lib',
+        'drivetrain_action_queue',
+      ],
+    },
+  ],
+}
diff --git a/y2014/actors/drivetrain_action.q b/y2014/actors/drivetrain_action.q
new file mode 100644
index 0000000..9ad55d3
--- /dev/null
+++ b/y2014/actors/drivetrain_action.q
@@ -0,0 +1,29 @@
+package frc971.actors;
+
+import "aos/common/actions/actions.q";
+
+// Parameters to send with start.
+struct DrivetrainActionParams {
+  double left_initial_position;
+  double right_initial_position;
+  double y_offset;
+  double theta_offset;
+  double maximum_velocity;
+  double maximum_acceleration;
+  double maximum_turn_velocity;
+  double maximum_turn_acceleration;
+};
+
+queue_group DrivetrainActionQueueGroup {
+  implements aos.common.actions.ActionQueueGroup;
+
+  message Goal {
+    uint32_t run;
+    DrivetrainActionParams params;
+  };
+
+  queue Goal goal;
+  queue aos.common.actions.Status status;
+};
+
+queue_group DrivetrainActionQueueGroup drivetrain_action;
diff --git a/y2014/actors/drivetrain_actor.cc b/y2014/actors/drivetrain_actor.cc
new file mode 100644
index 0000000..3cf86bd
--- /dev/null
+++ b/y2014/actors/drivetrain_actor.cc
@@ -0,0 +1,168 @@
+#include "y2014/actors/drivetrain_actor.h"
+
+#include <functional>
+#include <numeric>
+
+#include <Eigen/Dense>
+
+#include "aos/common/util/phased_loop.h"
+#include "aos/common/logging/logging.h"
+#include "aos/common/util/trapezoid_profile.h"
+#include "aos/common/commonmath.h"
+#include "aos/common/time.h"
+
+#include "y2014/actors/drivetrain_actor.h"
+#include "y2014/constants.h"
+#include "y2014/control_loops/drivetrain/drivetrain.q.h"
+
+namespace frc971 {
+namespace actors {
+
+DrivetrainActor::DrivetrainActor(actors::DrivetrainActionQueueGroup* s)
+    : aos::common::actions::ActorBase<actors::DrivetrainActionQueueGroup>(s) {}
+
+bool DrivetrainActor::RunAction(const actors::DrivetrainActionParams &params) {
+  static const auto K = constants::GetValues().make_drivetrain_loop().K();
+
+  const double yoffset = params.y_offset;
+  const double turn_offset =
+      params.theta_offset * constants::GetValues().turn_width / 2.0;
+  LOG(INFO, "Going to move %f and turn %f\n", yoffset, turn_offset);
+
+  // Measured conversion to get the distance right.
+  ::aos::util::TrapezoidProfile profile(::aos::time::Time::InMS(5));
+  ::aos::util::TrapezoidProfile turn_profile(::aos::time::Time::InMS(5));
+  const double goal_velocity = 0.0;
+  const double epsilon = 0.01;
+  ::Eigen::Matrix<double, 2, 1> left_goal_state, right_goal_state;
+
+  profile.set_maximum_acceleration(params.maximum_acceleration);
+  profile.set_maximum_velocity(params.maximum_velocity);
+  turn_profile.set_maximum_acceleration(params.maximum_turn_acceleration *
+                                        constants::GetValues().turn_width /
+                                        2.0);
+  turn_profile.set_maximum_velocity(params.maximum_turn_velocity *
+                                    constants::GetValues().turn_width / 2.0);
+
+  while (true) {
+    ::aos::time::PhasedLoopXMS(10, 5000);
+
+    control_loops::drivetrain_queue.status.FetchLatest();
+    if (control_loops::drivetrain_queue.status.get()) {
+      const auto& status = *control_loops::drivetrain_queue.status;
+      if (::std::abs(status.uncapped_left_voltage -
+                     status.uncapped_right_voltage) > 24) {
+        LOG(DEBUG, "spinning in place\n");
+        // They're more than 24V apart, so stop moving forwards and let it deal
+        // with spinning first.
+        profile.SetGoal(
+            (status.filtered_left_position + status.filtered_right_position -
+             params.left_initial_position - params.right_initial_position) /
+            2.0);
+      } else {
+        static const double divisor = K(0, 0) + K(0, 2);
+        double dx_left, dx_right;
+        if (status.uncapped_left_voltage > 12.0) {
+          dx_left = (status.uncapped_left_voltage - 12.0) / divisor;
+        } else if (status.uncapped_left_voltage < -12.0) {
+          dx_left = (status.uncapped_left_voltage + 12.0) / divisor;
+        } else {
+          dx_left = 0;
+        }
+        if (status.uncapped_right_voltage > 12.0) {
+          dx_right = (status.uncapped_right_voltage - 12.0) / divisor;
+        } else if (status.uncapped_right_voltage < -12.0) {
+          dx_right = (status.uncapped_right_voltage + 12.0) / divisor;
+        } else {
+          dx_right = 0;
+        }
+        double dx;
+        if (dx_left == 0 && dx_right == 0) {
+          dx = 0;
+        } else if (dx_left != 0 && dx_right != 0 &&
+                   ::aos::sign(dx_left) != ::aos::sign(dx_right)) {
+          // Both saturating in opposite directions. Don't do anything.
+          LOG(DEBUG, "Saturating opposite ways, not adjusting\n");
+          dx = 0;
+        } else if (::std::abs(dx_left) > ::std::abs(dx_right)) {
+          dx = dx_left;
+        } else {
+          dx = dx_right;
+        }
+        if (dx != 0) {
+          LOG(DEBUG, "adjusting goal by %f\n", dx);
+          profile.MoveGoal(-dx);
+        }
+      }
+    } else {
+      // If we ever get here, that's bad and we should just give up
+      LOG(ERROR, "no drivetrain status!\n");
+      return false;
+    }
+
+    const auto drive_profile_goal_state =
+        profile.Update(yoffset, goal_velocity);
+    const auto turn_profile_goal_state = turn_profile.Update(turn_offset, 0.0);
+    left_goal_state = drive_profile_goal_state - turn_profile_goal_state;
+    right_goal_state = drive_profile_goal_state + turn_profile_goal_state;
+
+    if (::std::abs(drive_profile_goal_state(0, 0) - yoffset) < epsilon &&
+        ::std::abs(turn_profile_goal_state(0, 0) - turn_offset) < epsilon) {
+      break;
+    }
+
+    if (ShouldCancel()) return true;
+
+    LOG(DEBUG, "Driving left to %f, right to %f\n",
+        left_goal_state(0, 0) + params.left_initial_position,
+        right_goal_state(0, 0) + params.right_initial_position);
+    control_loops::drivetrain_queue.goal.MakeWithBuilder()
+        .control_loop_driving(true)
+        //.highgear(false)
+        .left_goal(left_goal_state(0, 0) + params.left_initial_position)
+        .right_goal(right_goal_state(0, 0) + params.right_initial_position)
+        .left_velocity_goal(left_goal_state(1, 0))
+        .right_velocity_goal(right_goal_state(1, 0))
+        .Send();
+  }
+  if (ShouldCancel()) return true;
+  control_loops::drivetrain_queue.status.FetchLatest();
+  while (!control_loops::drivetrain_queue.status.get()) {
+    LOG(WARNING,
+        "No previous drivetrain status packet, trying to fetch again\n");
+    control_loops::drivetrain_queue.status.FetchNextBlocking();
+    if (ShouldCancel()) return true;
+  }
+  while (true) {
+    if (ShouldCancel()) return true;
+    const double kPositionThreshold = 0.05;
+
+    const double left_error = ::std::abs(
+        control_loops::drivetrain_queue.status->filtered_left_position -
+        (left_goal_state(0, 0) + params.left_initial_position));
+    const double right_error = ::std::abs(
+        control_loops::drivetrain_queue.status->filtered_right_position -
+        (right_goal_state(0, 0) + params.right_initial_position));
+    const double velocity_error =
+        ::std::abs(control_loops::drivetrain_queue.status->robot_speed);
+    if (left_error < kPositionThreshold && right_error < kPositionThreshold &&
+        velocity_error < 0.2) {
+      break;
+    } else {
+      LOG(DEBUG, "Drivetrain error is %f, %f, %f\n", left_error, right_error,
+          velocity_error);
+    }
+    control_loops::drivetrain_queue.status.FetchNextBlocking();
+  }
+  LOG(INFO, "Done moving\n");
+  return true;
+}
+
+::std::unique_ptr<DrivetrainAction> MakeDrivetrainAction(
+    const ::frc971::actors::DrivetrainActionParams& params) {
+  return ::std::unique_ptr<DrivetrainAction>(
+      new DrivetrainAction(&::frc971::actors::drivetrain_action, params));
+}
+
+}  // namespace actors
+}  // namespace frc971
diff --git a/y2014/actors/drivetrain_actor.h b/y2014/actors/drivetrain_actor.h
new file mode 100644
index 0000000..583121b
--- /dev/null
+++ b/y2014/actors/drivetrain_actor.h
@@ -0,0 +1,32 @@
+#ifndef Y2014_ACTIONS_DRIVETRAIN_ACTION_H_
+#define Y2014_ACTIONS_DRIVETRAIN_ACTION_H_
+
+#include <memory>
+
+#include "aos/common/actions/actor.h"
+#include "aos/common/actions/actions.h"
+
+#include "y2014/actors/drivetrain_action.q.h"
+
+namespace frc971 {
+namespace actors {
+
+class DrivetrainActor
+    : public ::aos::common::actions::ActorBase<DrivetrainActionQueueGroup> {
+ public:
+  explicit DrivetrainActor(DrivetrainActionQueueGroup* s);
+
+  bool RunAction(const actors::DrivetrainActionParams &params) override;
+};
+
+typedef ::aos::common::actions::TypedAction<DrivetrainActionQueueGroup>
+    DrivetrainAction;
+
+// Makes a new DrivetrainActor action.
+::std::unique_ptr<DrivetrainAction> MakeDrivetrainAction(
+    const ::frc971::actors::DrivetrainActionParams& params);
+
+}  // namespace actors
+}  // namespace frc971
+
+#endif
diff --git a/y2014/actors/drivetrain_actor_main.cc b/y2014/actors/drivetrain_actor_main.cc
new file mode 100644
index 0000000..375e71c
--- /dev/null
+++ b/y2014/actors/drivetrain_actor_main.cc
@@ -0,0 +1,18 @@
+#include <stdio.h>
+
+#include "aos/linux_code/init.h"
+#include "y2014/actors/drivetrain_action.q.h"
+#include "y2014/actors/drivetrain_actor.h"
+
+using ::aos::time::Time;
+
+int main(int /*argc*/, char * /*argv*/[]) {
+  ::aos::Init();
+
+  frc971::actors::DrivetrainActor drivetrain(
+      &::frc971::actors::drivetrain_action);
+  drivetrain.Run();
+
+  ::aos::Cleanup();
+  return 0;
+}
diff --git a/y2014/actors/shoot_action.q b/y2014/actors/shoot_action.q
new file mode 100644
index 0000000..1c545aa
--- /dev/null
+++ b/y2014/actors/shoot_action.q
@@ -0,0 +1,12 @@
+package frc971.actors;
+
+import "aos/common/actions/actions.q";
+
+queue_group ShootActionQueueGroup {
+  implements frc971.actions.ActionQueueGroup;
+
+  queue aos.common.actions.Goal goal;
+  queue aos.common.actions.Status status;
+};
+
+queue_group ShootActionQueueGroup shoot_action;
diff --git a/y2014/actors/shoot_actor.cc b/y2014/actors/shoot_actor.cc
new file mode 100644
index 0000000..9db34c4
--- /dev/null
+++ b/y2014/actors/shoot_actor.cc
@@ -0,0 +1,178 @@
+#include "y2014/actors/shoot_actor.h"
+
+#include <functional>
+
+#include "aos/common/logging/logging.h"
+
+#include "y2014/control_loops/shooter/shooter.q.h"
+#include "y2014/control_loops/claw/claw.q.h"
+#include "y2014/constants.h"
+#include "y2014/control_loops/drivetrain/drivetrain.q.h"
+
+namespace frc971 {
+namespace actors {
+namespace {
+
+bool IntakeOff() {
+  control_loops::claw_queue.goal.FetchLatest();
+  if (!control_loops::claw_queue.goal.get()) {
+    LOG(WARNING, "no claw goal\n");
+    // If it doesn't have a goal, then the intake isn't on so we don't have to
+    // turn it off.
+    return true;
+  } else {
+    if (!control_loops::claw_queue.goal.MakeWithBuilder()
+             .bottom_angle(control_loops::claw_queue.goal->bottom_angle)
+             .separation_angle(control_loops::claw_queue.goal->separation_angle)
+             .intake(0.0)
+             .centering(0.0)
+             .Send()) {
+      LOG(WARNING, "sending claw goal failed\n");
+      return false;
+    }
+  }
+  return true;
+}
+
+}  // namespace
+
+constexpr double ShootActor::kOffsetRadians;
+constexpr double ShootActor::kClawShootingSeparation;
+constexpr double ShootActor::kClawShootingSeparationGoal;
+
+ShootActor::ShootActor(actors::ShootActionQueueGroup* s)
+    : ::aos::common::actions::ActorBase<actors::ShootActionQueueGroup>(s) {}
+
+double ShootActor::SpeedToAngleOffset(double speed) {
+  const frc971::constants::Values& values = frc971::constants::GetValues();
+  // scale speed to a [0.0-1.0] on something close to the max
+  return (speed / values.drivetrain_max_speed) * kOffsetRadians;
+}
+
+bool ShootActor::RunAction(const double&) {
+  InnerRunAction();
+
+  // Now do our 'finally' block and make sure that we aren't requesting shots
+  // continually.
+  control_loops::shooter_queue.goal.FetchLatest();
+  if (control_loops::shooter_queue.goal.get() == nullptr) {
+    return true;
+  }
+  if (!control_loops::shooter_queue.goal.MakeWithBuilder()
+           .shot_power(control_loops::shooter_queue.goal->shot_power)
+           .shot_requested(false)
+           .unload_requested(false)
+           .load_requested(false)
+           .Send()) {
+    LOG(WARNING, "sending shooter goal failed\n");
+    return false;
+  }
+
+  LOG(INFO, "finished\n");
+  return true;
+}
+
+void ShootActor::InnerRunAction() {
+  LOG(INFO, "Shooting at the current angle and power.\n");
+
+  // wait for claw to be ready
+  if (WaitUntil(::std::bind(&ShootActor::DoneSetupShot, this))) {
+    return;
+  }
+
+  if (!IntakeOff()) return;
+
+  // Make sure that we have the latest shooter status.
+  control_loops::shooter_queue.status.FetchLatest();
+  // Get the number of shots fired up to this point. This should not be updated
+  // again for another few cycles.
+  previous_shots_ = control_loops::shooter_queue.status->shots;
+  // Shoot!
+  if (!control_loops::shooter_queue.goal.MakeWithBuilder()
+           .shot_power(control_loops::shooter_queue.goal->shot_power)
+           .shot_requested(true)
+           .unload_requested(false)
+           .load_requested(false)
+           .Send()) {
+    LOG(WARNING, "sending shooter goal failed\n");
+    return;
+  }
+
+  // wait for record of shot having been fired
+  if (WaitUntil(::std::bind(&ShootActor::DoneShot, this))) return;
+
+  if (!IntakeOff()) return;
+}
+
+bool ClawIsReady() {
+  control_loops::claw_queue.goal.FetchLatest();
+
+  bool ans =
+      control_loops::claw_queue.status->zeroed &&
+      (::std::abs(control_loops::claw_queue.status->bottom_velocity) < 0.5) &&
+      (::std::abs(control_loops::claw_queue.status->bottom -
+                  control_loops::claw_queue.goal->bottom_angle) < 0.10) &&
+      (::std::abs(control_loops::claw_queue.status->separation -
+                  control_loops::claw_queue.goal->separation_angle) < 0.4);
+  LOG(DEBUG, "Claw is %sready zeroed %d bottom_velocity %f bottom %f sep %f\n",
+      ans ? "" : "not ", control_loops::claw_queue.status->zeroed,
+      ::std::abs(control_loops::claw_queue.status->bottom_velocity),
+      ::std::abs(control_loops::claw_queue.status->bottom -
+                 control_loops::claw_queue.goal->bottom_angle),
+      ::std::abs(control_loops::claw_queue.status->separation -
+                 control_loops::claw_queue.goal->separation_angle));
+  return ans;
+}
+
+bool ShooterIsReady() {
+  control_loops::shooter_queue.goal.FetchLatest();
+
+  LOG(DEBUG, "Power error is %f - %f -> %f, ready %d\n",
+      control_loops::shooter_queue.status->hard_stop_power,
+      control_loops::shooter_queue.goal->shot_power,
+      ::std::abs(control_loops::shooter_queue.status->hard_stop_power -
+                 control_loops::shooter_queue.goal->shot_power),
+      control_loops::shooter_queue.status->ready);
+  return (::std::abs(control_loops::shooter_queue.status->hard_stop_power -
+                     control_loops::shooter_queue.goal->shot_power) < 1.0) &&
+         control_loops::shooter_queue.status->ready;
+}
+
+bool ShootActor::DoneSetupShot() {
+  control_loops::shooter_queue.status.FetchAnother();
+  control_loops::claw_queue.status.FetchAnother();
+  // Make sure that both the shooter and claw have reached the necessary
+  // states.
+  if (ShooterIsReady() && ClawIsReady()) {
+    LOG(INFO, "Claw and Shooter ready for shooting.\n");
+    return true;
+  }
+
+  return false;
+}
+
+bool ShootActor::DonePreShotOpen() {
+  control_loops::claw_queue.status.FetchAnother();
+  if (control_loops::claw_queue.status->separation > kClawShootingSeparation) {
+    LOG(INFO, "Opened up enough to shoot.\n");
+    return true;
+  }
+  return false;
+}
+
+bool ShootActor::DoneShot() {
+  control_loops::shooter_queue.status.FetchAnother();
+  if (control_loops::shooter_queue.status->shots > previous_shots_) {
+    LOG(INFO, "Shot succeeded!\n");
+    return true;
+  }
+  return false;
+}
+
+::std::unique_ptr<ShootAction> MakeShootAction() {
+  return ::std::unique_ptr<ShootAction>(
+      new ShootAction(&::frc971::actors::shoot_action, 0.0));
+}
+
+}  // namespace actors
+}  // namespace frc971
diff --git a/y2014/actors/shoot_actor.h b/y2014/actors/shoot_actor.h
new file mode 100644
index 0000000..3adfe31
--- /dev/null
+++ b/y2014/actors/shoot_actor.h
@@ -0,0 +1,52 @@
+#ifndef Y2014_ACTORS_SHOOT_ACTOR_H_
+#define Y2014_ACTORS_SHOOT_ACTOR_H_
+
+#include <memory>
+
+#include "aos/common/actions/actor.h"
+#include "aos/common/actions/actions.h"
+
+#include "y2014/actors/shoot_action.q.h"
+
+namespace frc971 {
+namespace actors {
+
+class ShootActor
+    : public ::aos::common::actions::ActorBase<actors::ShootActionQueueGroup> {
+ public:
+  explicit ShootActor(actors::ShootActionQueueGroup* s);
+
+  // Actually execute the action of moving the claw and shooter into position
+  // and actually firing them.
+  bool RunAction(const double &params) override;
+  void InnerRunAction();
+
+  // calc an offset to our requested shot based on robot speed
+  double SpeedToAngleOffset(double speed);
+
+  static constexpr double kOffsetRadians = 0.4;
+  static constexpr double kClawShootingSeparation = 0.10;
+  static constexpr double kClawShootingSeparationGoal = 0.10;
+
+ protected:
+  // completed shot
+  bool DoneShot();
+  // ready for shot
+  bool DonePreShotOpen();
+  // in the right place
+  bool DoneSetupShot();
+
+  // to track when shot is complete
+  int previous_shots_;
+};
+
+typedef ::aos::common::actions::TypedAction<actors::ShootActionQueueGroup>
+    ShootAction;
+
+// Makes a new ShootActor action.
+::std::unique_ptr<ShootAction> MakeShootAction();
+
+}  // namespace actors
+}  // namespace frc971
+
+#endif  // Y2014_ACTORS_SHOOT_ACTOR_H_
diff --git a/y2014/actors/shoot_actor_main.cc b/y2014/actors/shoot_actor_main.cc
new file mode 100644
index 0000000..efa4377
--- /dev/null
+++ b/y2014/actors/shoot_actor_main.cc
@@ -0,0 +1,18 @@
+#include <stdio.h>
+
+#include "aos/linux_code/init.h"
+#include "y2014/actors/shoot_action.q.h"
+#include "y2014/actors/shoot_actor.h"
+
+using ::aos::time::Time;
+
+int main(int /*argc*/, char * /*argv*/[]) {
+  ::aos::Init();
+
+  frc971::actors::ShootActor shoot(&::frc971::actors::shoot_action);
+  shoot.Run();
+
+  ::aos::Cleanup();
+  return 0;
+}
+
diff --git a/y2014/autonomous/auto.cc b/y2014/autonomous/auto.cc
new file mode 100644
index 0000000..ab28323
--- /dev/null
+++ b/y2014/autonomous/auto.cc
@@ -0,0 +1,530 @@
+#include <stdio.h>
+
+#include <memory>
+
+#include "aos/common/util/phased_loop.h"
+#include "aos/common/time.h"
+#include "aos/common/util/trapezoid_profile.h"
+#include "aos/common/logging/logging.h"
+#include "aos/common/logging/queue_logging.h"
+#include "aos/common/actions/actions.h"
+
+#include "frc971/autonomous/auto.q.h"
+#include "y2014/constants.h"
+#include "y2014/control_loops/drivetrain/drivetrain.q.h"
+#include "y2014/control_loops/shooter/shooter.q.h"
+#include "y2014/control_loops/claw/claw.q.h"
+#include "y2014/actors/shoot_actor.h"
+#include "y2014/actors/drivetrain_actor.h"
+#include "y2014/queues/auto_mode.q.h"
+
+#include "y2014/queues/hot_goal.q.h"
+#include "y2014/queues/profile_params.q.h"
+
+using ::aos::time::Time;
+
+namespace frc971 {
+namespace autonomous {
+
+namespace time = ::aos::time;
+
+static double left_initial_position, right_initial_position;
+
+bool ShouldExitAuto() {
+  ::frc971::autonomous::autonomous.FetchLatest();
+  bool ans = !::frc971::autonomous::autonomous->run_auto;
+  if (ans) {
+    LOG(INFO, "Time to exit auto mode\n");
+  }
+  return ans;
+}
+
+void StopDrivetrain() {
+  LOG(INFO, "Stopping the drivetrain\n");
+  control_loops::drivetrain_queue.goal.MakeWithBuilder()
+      .control_loop_driving(true)
+      .left_goal(left_initial_position)
+      .left_velocity_goal(0)
+      .right_goal(right_initial_position)
+      .right_velocity_goal(0)
+      .quickturn(false)
+      .Send();
+}
+
+void ResetDrivetrain() {
+  LOG(INFO, "resetting the drivetrain\n");
+  control_loops::drivetrain_queue.goal.MakeWithBuilder()
+      .control_loop_driving(false)
+      .highgear(false)
+      .steering(0.0)
+      .throttle(0.0)
+      .left_goal(left_initial_position)
+      .left_velocity_goal(0)
+      .right_goal(right_initial_position)
+      .right_velocity_goal(0)
+      .Send();
+}
+
+void WaitUntilDoneOrCanceled(
+    ::std::unique_ptr<aos::common::actions::Action> action) {
+  if (!action) {
+    LOG(ERROR, "No action, not waiting\n");
+    return;
+  }
+  while (true) {
+    // Poll the running bit and auto done bits.
+    ::aos::time::PhasedLoopXMS(10, 5000);
+    if (!action->Running() || ShouldExitAuto()) {
+      return;
+    }
+  }
+}
+
+void StepDrive(double distance, double theta) {
+  double left_goal = (left_initial_position + distance -
+                      theta * constants::GetValues().turn_width / 2.0);
+  double right_goal = (right_initial_position + distance +
+                       theta * constants::GetValues().turn_width / 2.0);
+  control_loops::drivetrain_queue.goal.MakeWithBuilder()
+      .control_loop_driving(true)
+      .left_goal(left_goal)
+      .right_goal(right_goal)
+      .left_velocity_goal(0.0)
+      .right_velocity_goal(0.0)
+      .Send();
+  left_initial_position = left_goal;
+  right_initial_position = right_goal;
+}
+
+void PositionClawVertically(double intake_power = 0.0, double centering_power = 0.0) {
+  if (!control_loops::claw_queue.goal.MakeWithBuilder()
+           .bottom_angle(0.0)
+           .separation_angle(0.0)
+           .intake(intake_power)
+           .centering(centering_power)
+           .Send()) {
+    LOG(WARNING, "sending claw goal failed\n");
+  }
+}
+
+void PositionClawBackIntake() {
+  if (!control_loops::claw_queue.goal.MakeWithBuilder()
+           .bottom_angle(-2.273474)
+           .separation_angle(0.0)
+           .intake(12.0)
+           .centering(12.0)
+           .Send()) {
+    LOG(WARNING, "sending claw goal failed\n");
+  }
+}
+
+void PositionClawUpClosed() {
+  // Move the claw to where we're going to shoot from but keep it closed until
+  // it gets there.
+  if (!control_loops::claw_queue.goal.MakeWithBuilder()
+           .bottom_angle(0.86)
+           .separation_angle(0.0)
+           .intake(4.0)
+           .centering(1.0)
+           .Send()) {
+    LOG(WARNING, "sending claw goal failed\n");
+  }
+}
+
+void PositionClawForShot() {
+  if (!control_loops::claw_queue.goal.MakeWithBuilder()
+           .bottom_angle(0.86)
+           .separation_angle(0.10)
+           .intake(4.0)
+           .centering(1.0)
+           .Send()) {
+    LOG(WARNING, "sending claw goal failed\n");
+  }
+}
+
+void SetShotPower(double power) {
+  LOG(INFO, "Setting shot power to %f\n", power);
+  if (!control_loops::shooter_queue.goal.MakeWithBuilder()
+           .shot_power(power)
+           .shot_requested(false)
+           .unload_requested(false)
+           .load_requested(false)
+           .Send()) {
+    LOG(WARNING, "sending shooter goal failed\n");
+  }
+}
+
+void WaitUntilNear(double distance) {
+  while (true) {
+    if (ShouldExitAuto()) return;
+    control_loops::drivetrain_queue.status.FetchAnother();
+    double left_error = ::std::abs(
+        left_initial_position -
+        control_loops::drivetrain_queue.status->filtered_left_position);
+    double right_error = ::std::abs(
+        right_initial_position -
+        control_loops::drivetrain_queue.status->filtered_right_position);
+    const double kPositionThreshold = 0.05 + distance;
+    if (right_error < kPositionThreshold && left_error < kPositionThreshold) {
+      LOG(INFO, "At the goal\n");
+      return;
+    }
+  }
+}
+
+const ProfileParams kFastDrive = {3.0, 2.5};
+const ProfileParams kSlowDrive = {2.5, 2.5};
+const ProfileParams kFastWithBallDrive = {3.0, 2.0};
+const ProfileParams kSlowWithBallDrive = {2.5, 2.0};
+const ProfileParams kFastTurn = {3.0, 10.0};
+
+::std::unique_ptr<::frc971::actors::DrivetrainAction> SetDriveGoal(
+    double distance, const ProfileParams drive_params, double theta = 0,
+    const ProfileParams &turn_params = kFastTurn) {
+  LOG(INFO, "Driving to %f\n", distance);
+
+  ::frc971::actors::DrivetrainActionParams params;
+  params.left_initial_position = left_initial_position;
+  params.right_initial_position = right_initial_position;
+  params.y_offset = distance;
+  params.theta_offset = theta;
+  params.maximum_turn_acceleration = turn_params.acceleration;
+  params.maximum_turn_velocity = turn_params.velocity;
+  params.maximum_velocity = drive_params.velocity;
+  params.maximum_acceleration = drive_params.acceleration;
+  auto drivetrain_action = actors::MakeDrivetrainAction(params);
+  drivetrain_action->Start();
+  left_initial_position +=
+      distance - theta * constants::GetValues().turn_width / 2.0;
+  right_initial_position +=
+      distance + theta * constants::GetValues().turn_width / 2.0;
+  return ::std::move(drivetrain_action);
+}
+
+void Shoot() {
+  // Shoot.
+  auto shoot_action = actors::MakeShootAction();
+  shoot_action->Start();
+  WaitUntilDoneOrCanceled(::std::move(shoot_action));
+}
+
+void InitializeEncoders() {
+  control_loops::drivetrain_queue.status.FetchAnother();
+  left_initial_position =
+      control_loops::drivetrain_queue.status->filtered_left_position;
+  right_initial_position =
+      control_loops::drivetrain_queue.status->filtered_right_position;
+}
+
+void WaitUntilClawDone() {
+  while (true) {
+    // Poll the running bit and auto done bits.
+    ::aos::time::PhasedLoopXMS(10, 5000);
+    control_loops::claw_queue.status.FetchLatest();
+    control_loops::claw_queue.goal.FetchLatest();
+    if (ShouldExitAuto()) {
+      return;
+    }
+    if (control_loops::claw_queue.status.get() == nullptr ||
+        control_loops::claw_queue.goal.get() == nullptr) {
+      continue;
+    }
+    bool ans =
+        control_loops::claw_queue.status->zeroed &&
+        (::std::abs(control_loops::claw_queue.status->bottom_velocity) <
+         1.0) &&
+        (::std::abs(control_loops::claw_queue.status->bottom -
+                    control_loops::claw_queue.goal->bottom_angle) <
+         0.10) &&
+        (::std::abs(control_loops::claw_queue.status->separation -
+                    control_loops::claw_queue.goal->separation_angle) <
+         0.4);
+    if (ans) {
+      return;
+    }
+    if (ShouldExitAuto()) return;
+  }
+}
+
+class HotGoalDecoder {
+ public:
+  HotGoalDecoder() {
+    ResetCounts();
+  }
+
+  void ResetCounts() {
+    hot_goal.FetchLatest();
+    if (hot_goal.get()) {
+      start_counts_ = *hot_goal;
+      LOG_STRUCT(INFO, "counts reset to", start_counts_);
+      start_counts_valid_ = true;
+    } else {
+      LOG(WARNING, "no hot goal message. ignoring\n");
+      start_counts_valid_ = false;
+    }
+  }
+
+  void Update(bool block = false) {
+    if (block) {
+      hot_goal.FetchAnother();
+    } else {
+      hot_goal.FetchLatest();
+    }
+    if (hot_goal.get()) LOG_STRUCT(INFO, "new counts", *hot_goal);
+  }
+
+  bool left_triggered() const {
+    if (!start_counts_valid_ || !hot_goal.get()) return false;
+    return (hot_goal->left_count - start_counts_.left_count) > kThreshold;
+  }
+
+  bool right_triggered() const {
+    if (!start_counts_valid_ || !hot_goal.get()) return false;
+    return (hot_goal->right_count - start_counts_.right_count) > kThreshold;
+  }
+
+  bool is_left() const {
+    if (!start_counts_valid_ || !hot_goal.get()) return false;
+    const uint64_t left_difference =
+        hot_goal->left_count - start_counts_.left_count;
+    const uint64_t right_difference =
+        hot_goal->right_count - start_counts_.right_count;
+    if (left_difference > kThreshold) {
+      if (right_difference > kThreshold) {
+        // We've seen a lot of both, so pick the one we've seen the most of.
+        return left_difference > right_difference;
+      } else {
+        // We've seen enough left but not enough right, so go with it.
+        return true;
+      }
+    } else {
+      // We haven't seen enough left, so it's not left.
+      return false;
+    }
+  }
+
+  bool is_right() const {
+    if (!start_counts_valid_ || !hot_goal.get()) return false;
+    const uint64_t left_difference =
+        hot_goal->left_count - start_counts_.left_count;
+    const uint64_t right_difference =
+        hot_goal->right_count - start_counts_.right_count;
+    if (right_difference > kThreshold) {
+      if (left_difference > kThreshold) {
+        // We've seen a lot of both, so pick the one we've seen the most of.
+        return right_difference > left_difference;
+      } else {
+        // We've seen enough right but not enough left, so go with it.
+        return true;
+      }
+    } else {
+      // We haven't seen enough right, so it's not right.
+      return false;
+    }
+  }
+
+ private:
+  static const uint64_t kThreshold = 5;
+
+  ::frc971::HotGoal start_counts_;
+  bool start_counts_valid_;
+};
+
+void HandleAuto() {
+  enum class AutoVersion : uint8_t {
+    kStraight,
+    kDoubleHot,
+    kSingleHot,
+  };
+
+  // The front of the robot is 1.854 meters from the wall
+  static const double kShootDistance = 3.15;
+  static const double kPickupDistance = 0.5;
+  static const double kTurnAngle = 0.3;
+
+  ::aos::time::Time start_time = ::aos::time::Time::Now();
+  LOG(INFO, "Handling auto mode\n");
+
+  AutoVersion auto_version;
+  ::frc971::sensors::auto_mode.FetchLatest();
+  if (!::frc971::sensors::auto_mode.get()) {
+    LOG(WARNING, "not sure which auto mode to use\n");
+    auto_version = AutoVersion::kStraight;
+  } else {
+    static const double kSelectorMin = 0.2, kSelectorMax = 4.4;
+
+    const double kSelectorStep = (kSelectorMax - kSelectorMin) / 3.0;
+    if (::frc971::sensors::auto_mode->voltage < kSelectorStep + kSelectorMin) {
+      auto_version = AutoVersion::kSingleHot;
+    } else if (::frc971::sensors::auto_mode->voltage <
+               2 * kSelectorStep + kSelectorMin) {
+      auto_version = AutoVersion::kStraight;
+    } else {
+      auto_version = AutoVersion::kDoubleHot;
+    }
+  }
+  LOG(INFO, "running auto %" PRIu8 "\n", static_cast<uint8_t>(auto_version));
+
+  const ProfileParams &drive_params =
+      (auto_version == AutoVersion::kStraight) ? kFastDrive : kSlowDrive;
+  const ProfileParams &drive_with_ball_params =
+      (auto_version == AutoVersion::kStraight) ? kFastWithBallDrive
+                                               : kSlowWithBallDrive;
+
+  HotGoalDecoder hot_goal_decoder;
+  // True for left, false for right.
+  bool first_shot_left, second_shot_left_default, second_shot_left;
+
+  ResetDrivetrain();
+
+  time::SleepFor(time::Time::InSeconds(0.1));
+  if (ShouldExitAuto()) return;
+  InitializeEncoders();
+
+  // Turn the claw on, keep it straight up until the ball has been grabbed.
+  LOG(INFO, "Claw going up at %f\n",
+      (::aos::time::Time::Now() - start_time).ToSeconds());
+  PositionClawVertically(12.0, 4.0);
+  SetShotPower(115.0);
+
+  // Wait for the ball to enter the claw.
+  time::SleepFor(time::Time::InSeconds(0.25));
+  if (ShouldExitAuto()) return;
+  LOG(INFO, "Readying claw for shot at %f\n",
+      (::aos::time::Time::Now() - start_time).ToSeconds());
+
+  {
+    if (ShouldExitAuto()) return;
+    // Drive to the goal.
+    auto drivetrain_action = SetDriveGoal(-kShootDistance, drive_params);
+    time::SleepFor(time::Time::InSeconds(0.75));
+    PositionClawForShot();
+    LOG(INFO, "Waiting until drivetrain is finished\n");
+    WaitUntilDoneOrCanceled(::std::move(drivetrain_action));
+    if (ShouldExitAuto()) return;
+  }
+
+  hot_goal_decoder.Update();
+  if (hot_goal_decoder.is_left()) {
+    LOG(INFO, "first shot left\n");
+    first_shot_left = true;
+    second_shot_left_default = false;
+  } else if (hot_goal_decoder.is_right()) {
+    LOG(INFO, "first shot right\n");
+    first_shot_left = false;
+    second_shot_left_default = true;
+  } else {
+    LOG(INFO, "first shot defaulting left\n");
+    first_shot_left = true;
+    second_shot_left_default = true;
+  }
+  if (auto_version == AutoVersion::kDoubleHot) {
+    if (ShouldExitAuto()) return;
+    auto drivetrain_action = SetDriveGoal(
+        0, drive_with_ball_params, first_shot_left ? kTurnAngle : -kTurnAngle);
+    WaitUntilDoneOrCanceled(::std::move(drivetrain_action));
+    if (ShouldExitAuto()) return;
+  } else if (auto_version == AutoVersion::kSingleHot) {
+    do {
+      // TODO(brians): Wait for next message with timeout or something.
+      ::aos::time::SleepFor(::aos::time::Time::InSeconds(0.003));
+      hot_goal_decoder.Update(false);
+      if (ShouldExitAuto()) return;
+    } while (!hot_goal_decoder.left_triggered() &&
+             (::aos::time::Time::Now() - start_time) <
+                 ::aos::time::Time::InSeconds(9));
+  } else if (auto_version == AutoVersion::kStraight) {
+    time::SleepFor(time::Time::InSeconds(0.4));
+  }
+
+  // Shoot.
+  LOG(INFO, "Shooting at %f\n",
+      (::aos::time::Time::Now() - start_time).ToSeconds());
+  Shoot();
+  time::SleepFor(time::Time::InSeconds(0.05));
+
+  if (auto_version == AutoVersion::kDoubleHot) {
+    if (ShouldExitAuto()) return;
+    auto drivetrain_action = SetDriveGoal(
+        0, drive_with_ball_params, first_shot_left ? -kTurnAngle : kTurnAngle);
+    WaitUntilDoneOrCanceled(::std::move(drivetrain_action));
+    if (ShouldExitAuto()) return;
+  } else if (auto_version == AutoVersion::kSingleHot) {
+    LOG(INFO, "auto done at %f\n",
+        (::aos::time::Time::Now() - start_time).ToSeconds());
+    PositionClawVertically(0.0, 0.0);
+    return;
+  }
+
+  {
+    if (ShouldExitAuto()) return;
+    // Intake the new ball.
+    LOG(INFO, "Claw ready for intake at %f\n",
+        (::aos::time::Time::Now() - start_time).ToSeconds());
+    PositionClawBackIntake();
+    auto drivetrain_action =
+        SetDriveGoal(kShootDistance + kPickupDistance, drive_params);
+    LOG(INFO, "Waiting until drivetrain is finished\n");
+    WaitUntilDoneOrCanceled(::std::move(drivetrain_action));
+    if (ShouldExitAuto()) return;
+    LOG(INFO, "Wait for the claw at %f\n",
+        (::aos::time::Time::Now() - start_time).ToSeconds());
+    WaitUntilClawDone();
+    if (ShouldExitAuto()) return;
+  }
+
+  // Drive back.
+  {
+    LOG(INFO, "Driving back at %f\n",
+        (::aos::time::Time::Now() - start_time).ToSeconds());
+    auto drivetrain_action =
+        SetDriveGoal(-(kShootDistance + kPickupDistance), drive_params);
+    time::SleepFor(time::Time::InSeconds(0.3));
+    hot_goal_decoder.ResetCounts();
+    if (ShouldExitAuto()) return;
+    PositionClawUpClosed();
+    WaitUntilClawDone();
+    if (ShouldExitAuto()) return;
+    PositionClawForShot();
+    LOG(INFO, "Waiting until drivetrain is finished\n");
+    WaitUntilDoneOrCanceled(::std::move(drivetrain_action));
+    if (ShouldExitAuto()) return;
+    WaitUntilClawDone();
+    if (ShouldExitAuto()) return;
+  }
+
+  hot_goal_decoder.Update();
+  if (hot_goal_decoder.is_left()) {
+    LOG(INFO, "second shot left\n");
+    second_shot_left = true;
+  } else if (hot_goal_decoder.is_right()) {
+    LOG(INFO, "second shot right\n");
+    second_shot_left = false;
+  } else {
+    LOG(INFO, "second shot defaulting %s\n",
+        second_shot_left_default ? "left" : "right");
+    second_shot_left = second_shot_left_default;
+  }
+  if (auto_version == AutoVersion::kDoubleHot) {
+    if (ShouldExitAuto()) return;
+    auto drivetrain_action = SetDriveGoal(
+        0, drive_params, second_shot_left ? kTurnAngle : -kTurnAngle);
+    WaitUntilDoneOrCanceled(::std::move(drivetrain_action));
+    if (ShouldExitAuto()) return;
+  } else if (auto_version == AutoVersion::kStraight) {
+    time::SleepFor(time::Time::InSeconds(0.4));
+  }
+
+  LOG(INFO, "Shooting at %f\n",
+      (::aos::time::Time::Now() - start_time).ToSeconds());
+  // Shoot
+  Shoot();
+  if (ShouldExitAuto()) return;
+
+  // Get ready to zero when we come back up.
+  time::SleepFor(time::Time::InSeconds(0.05));
+  PositionClawVertically(0.0, 0.0);
+}
+
+}  // namespace autonomous
+}  // namespace frc971
diff --git a/y2014/autonomous/auto.h b/y2014/autonomous/auto.h
new file mode 100644
index 0000000..3e4885f
--- /dev/null
+++ b/y2014/autonomous/auto.h
@@ -0,0 +1,12 @@
+#ifndef Y2014_AUTONOMOUS_AUTO_H_
+#define Y2014_AUTONOMOUS_AUTO_H_
+
+namespace frc971 {
+namespace autonomous {
+
+void HandleAuto();
+
+}  // namespace autonomous
+}  // namespace frc971
+
+#endif  // Y2014_AUTONOMOUS_AUTO_H_
diff --git a/y2014/autonomous/auto_main.cc b/y2014/autonomous/auto_main.cc
new file mode 100644
index 0000000..3dbad2c
--- /dev/null
+++ b/y2014/autonomous/auto_main.cc
@@ -0,0 +1,42 @@
+#include <stdio.h>
+
+#include "aos/common/time.h"
+#include "aos/linux_code/init.h"
+#include "aos/common/logging/logging.h"
+#include "frc971/autonomous/auto.q.h"
+#include "y2014/autonomous/auto.h"
+
+using ::aos::time::Time;
+
+int main(int /*argc*/, char * /*argv*/[]) {
+  ::aos::Init();
+
+  LOG(INFO, "Auto main started\n");
+  ::frc971::autonomous::autonomous.FetchLatest();
+  while (!::frc971::autonomous::autonomous.get()) {
+    ::frc971::autonomous::autonomous.FetchNextBlocking();
+    LOG(INFO, "Got another auto packet\n");
+  }
+
+  while (true) {
+    while (!::frc971::autonomous::autonomous->run_auto) {
+      ::frc971::autonomous::autonomous.FetchNextBlocking();
+      LOG(INFO, "Got another auto packet\n");
+    }
+    LOG(INFO, "Starting auto mode\n");
+    ::aos::time::Time start_time = ::aos::time::Time::Now();
+    ::frc971::autonomous::HandleAuto();
+
+    ::aos::time::Time elapsed_time = ::aos::time::Time::Now() - start_time;
+    LOG(INFO, "Auto mode exited in %f, waiting for it to finish.\n",
+        elapsed_time.ToSeconds());
+    while (::frc971::autonomous::autonomous->run_auto) {
+      ::frc971::autonomous::autonomous.FetchNextBlocking();
+      LOG(INFO, "Got another auto packet\n");
+    }
+    LOG(INFO, "Waiting for auto to start back up.\n");
+  }
+  ::aos::Cleanup();
+  return 0;
+}
+
diff --git a/y2014/autonomous/autonomous.gyp b/y2014/autonomous/autonomous.gyp
new file mode 100644
index 0000000..8efdaec
--- /dev/null
+++ b/y2014/autonomous/autonomous.gyp
@@ -0,0 +1,45 @@
+{
+  'targets': [
+    {
+      'target_name': 'auto_lib',
+      'type': 'static_library',
+      'sources': [
+        'auto.cc',
+      ],
+      'dependencies': [
+        '<(DEPTH)/frc971/autonomous/autonomous.gyp:auto_queue',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+        '<(DEPTH)/y2014/control_loops/drivetrain/drivetrain.gyp:drivetrain_queue',
+        '<(DEPTH)/y2014/control_loops/shooter/shooter.gyp:shooter_queue',
+        '<(DEPTH)/y2014/control_loops/claw/claw.gyp:claw_queue',
+        '<(DEPTH)/y2014/y2014.gyp:constants',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/common/util/util.gyp:phased_loop',
+        '<(AOS)/common/util/util.gyp:trapezoid_profile',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        '<(DEPTH)/y2014/actors/actors.gyp:shoot_action_lib',
+        '<(DEPTH)/y2014/actors/actors.gyp:drivetrain_action_lib',
+        '<(DEPTH)/y2014/queues/queues.gyp:hot_goal',
+        '<(AOS)/common/logging/logging.gyp:queue_logging',
+        '<(DEPTH)/y2014/queues/queues.gyp:profile_params',
+        '<(DEPTH)/y2014/queues/queues.gyp:auto_mode',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+      ],
+    },
+    {
+      'target_name': 'auto',
+      'type': 'executable',
+      'sources': [
+        'auto_main.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(DEPTH)/frc971/autonomous/autonomous.gyp:auto_queue',
+        'auto_lib',
+      ],
+    },
+  ],
+}
diff --git a/y2014/constants.cc b/y2014/constants.cc
new file mode 100644
index 0000000..2c101c3
--- /dev/null
+++ b/y2014/constants.cc
@@ -0,0 +1,224 @@
+#include "y2014/constants.h"
+
+#include <math.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+#include <map>
+
+#if __has_feature(address_sanitizer)
+#include "sanitizer/lsan_interface.h"
+#endif
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/once.h"
+#include "aos/common/network/team_number.h"
+#include "aos/common/mutex.h"
+
+#include "y2014/control_loops/drivetrain/polydrivetrain_dog_motor_plant.h"
+#include "y2014/control_loops/drivetrain/drivetrain_dog_motor_plant.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+namespace frc971 {
+namespace constants {
+namespace {
+
+const uint16_t kCompTeamNumber = 971;
+const uint16_t kPracticeTeamNumber = 9971;
+const uint16_t kRoboRioTeamNumber = 254;
+
+const double kCompDrivetrainEncoderRatio =
+    (18.0 / 50.0) /*output reduction*/ * (56.0 / 30.0) /*encoder gears*/;
+const double kCompLowGearRatio = 18.0 / 60.0 * 18.0 / 50.0;
+const double kCompHighGearRatio = 28.0 / 50.0 * 18.0 / 50.0;
+
+const double kPracticeDrivetrainEncoderRatio = kCompDrivetrainEncoderRatio;
+const double kPracticeLowGearRatio = kCompLowGearRatio;
+const double kPracticeHighGearRatio = kCompHighGearRatio;
+
+const ShifterHallEffect kCompRightDriveShifter{555, 657, 660, 560, 0.2, 0.7};
+const ShifterHallEffect kCompLeftDriveShifter{555, 660, 644, 552, 0.2, 0.7};
+
+const ShifterHallEffect kPracticeRightDriveShifter{2.95, 3.95, 3.95, 2.95, 0.2, 0.7};
+const ShifterHallEffect kPracticeLeftDriveShifter{2.95, 4.2, 3.95, 3.0, 0.2, 0.7};
+
+const double kRobotWidth = 25.0 / 100.0 * 2.54;
+
+const double shooter_zeroing_speed = 0.05;
+const double shooter_unload_speed = 0.08;
+
+// Smaller (more negative) = opening.
+const double kCompTopClawOffset = -0.120;
+
+const Values *DoGetValuesForTeam(uint16_t team) {
+  switch (team) {
+    case 1:  // for tests
+      return new Values{
+          kCompDrivetrainEncoderRatio,
+          kCompLowGearRatio,
+          kCompHighGearRatio,
+          kCompLeftDriveShifter,
+          kCompRightDriveShifter,
+          false,
+          0.5,
+          control_loops::MakeVelocityDrivetrainLoop,
+          control_loops::MakeDrivetrainLoop,
+          0.02, // drivetrain done delta
+          5.0, // drivetrain max speed
+
+          // ShooterLimits
+          {-0.00127, 0.298196, -0.0017, 0.305054, 0.0149098,
+           {-0.001778, 0.000762, 0, 0},
+           {-0.001778, 0.008906, 0, 0},
+           {0.006096, 0.026416, 0, 0},
+           shooter_zeroing_speed,
+           shooter_unload_speed
+          },
+          {0.5,
+           0.1,
+           0.1,
+           0.0,
+           1.57,
+           0.05,
+           1.5,
+           {0.0, 2.05, 0.02, 2.02, {-0.1, 0.05, -0.1, 0.05}, {1.0, 1.1, 1.0, 1.1}, {2.0, 2.1, 2.0, 2.1}},
+           {0.0, 2.05, 0.02, 2.02, {-0.1, 0.05, -0.1, 0.05}, {1.0, 1.1, 1.0, 1.1}, {2.0, 2.1, 2.0, 2.1}},
+           0.01,  // claw_unimportant_epsilon
+           0.9,   // start_fine_tune_pos
+           4.0,
+          },
+          {0.07, 0.15}, // shooter_action
+      };
+      break;
+    case kCompTeamNumber:
+      return new Values{
+          kCompDrivetrainEncoderRatio,
+          kCompLowGearRatio,
+          kCompHighGearRatio,
+          kCompLeftDriveShifter,
+          kCompRightDriveShifter,
+          false,
+          kRobotWidth,
+          control_loops::MakeVelocityDrivetrainLoop,
+          control_loops::MakeDrivetrainLoop,
+          0.02, // drivetrain done delta
+          5.0, // drivetrain max speed
+
+          // ShooterLimits
+          {-0.001041, 0.296019, -0.001488, 0.302717, 0.0149098,
+           {-0.002, 0.000446, -0.002, 0.000446},
+           {-0.002, 0.009078, -0.002, 0.009078},
+           {0.003870, 0.026194, 0.003869, 0.026343},
+           shooter_zeroing_speed,
+           shooter_unload_speed
+          },
+          {0.800000,
+           0.400000,
+           0.000000,
+           -1.220821,
+           1.822142,
+           -0.849484,
+           1.42309,
+           // 0.0371
+           {-3.3284, 2.0917, -3.1661, 1.95,
+             {-3.4, -3.02 + kCompTopClawOffset, -3.4, -2.9876 + kCompTopClawOffset},
+             {-0.1433 + kCompTopClawOffset, 0.0670 + kCompTopClawOffset, -0.1460 + kCompTopClawOffset, 0.0648 + kCompTopClawOffset},
+             {1.9952 + kCompTopClawOffset, 2.2, 1.9898 + kCompTopClawOffset, 2.2}},
+           {-2.453460, 3.082960, -2.453460, 3.082960,
+             {-2.6, -2.185752, -2.6, -2.184843},
+             {-0.322249, -0.053177, -0.332248, -0.059086},
+             {2.892065, 3.2, 2.888429, 3.2}},
+           0.040000,  // claw_unimportant_epsilon
+           -0.400000,   // start_fine_tune_pos
+           4.000000,
+          },
+          //TODO(james): Get realer numbers for shooter_action.
+          {0.07, 0.15}, // shooter_action
+      };
+      break;
+    case kPracticeTeamNumber:
+    case kRoboRioTeamNumber:
+      return new Values{
+          kPracticeDrivetrainEncoderRatio,
+          kPracticeLowGearRatio,
+          kPracticeHighGearRatio,
+          kPracticeLeftDriveShifter,
+          kPracticeRightDriveShifter,
+          false,
+          kRobotWidth,
+          control_loops::MakeVelocityDrivetrainLoop,
+          control_loops::MakeDrivetrainLoop,
+          0.02, // drivetrain done delta
+          5.0, // drivetrain max speed
+
+          // ShooterLimits
+          {-0.001042, 0.294084, -0.001935, 0.303460, 0.0138401,
+           {-0.002, 0.000446, -0.002, 0.000446},
+           {-0.002, 0.009078, -0.002, 0.009078},
+           {0.003869, 0.026194, 0.003869, 0.026194},
+           shooter_zeroing_speed,
+           shooter_unload_speed
+          },
+          {0.400000 * 2.0,
+          0.200000 * 2.0,
+          0.000000 * 2.0,
+          -0.762218 * 2.0,
+          1.767146,
+          -0.849484,
+          1.42308,
+          {-3.364758, 2.086668, -3.166136, 1.95,
+            {-1.7 * 2.0, -1.544662 * 2.0, -1.7 * 2.0, -1.547616 * 2.0},
+            {-0.130218 * 2.0, -0.019771 * 2.0, -0.132036 * 2.0, -0.018862 * 2.0},
+            {1.871684, 2.2, 1.86532, 2.2}},
+          {-2.451642, 3.107504, -2.273474, 2.750,
+            {-2.6, -2.176662, -2.6, -2.176662},
+            {-0.316796, -0.054088, -0.319978, -0.062723},
+            {2.894792, 3.2, 2.887974, 3.2}},
+          0.040000,  // claw_unimportant_epsilon
+          -0.400000,   // start_fine_tune_pos
+          4.000000,
+          },
+          //TODO(james): Get realer numbers for shooter_action.
+          {0.07, 0.15}, // shooter_action
+      };
+      break;
+    default:
+      LOG(FATAL, "unknown team #%" PRIu16 "\n", team);
+  }
+}
+
+const Values *DoGetValues() {
+  uint16_t team = ::aos::network::GetTeamNumber();
+  LOG(INFO, "creating a Constants for team %" PRIu16 "\n", team);
+  return DoGetValuesForTeam(team);
+}
+
+}  // namespace
+
+const Values &GetValues() {
+  static ::aos::Once<const Values> once(DoGetValues);
+  return *once.Get();
+}
+
+const Values &GetValuesForTeam(uint16_t team_number) {
+  static ::aos::Mutex mutex;
+  ::aos::MutexLocker locker(&mutex);
+
+  // IMPORTANT: This declaration has to stay after the mutex is locked to avoid
+  // race conditions.
+  static ::std::map<uint16_t, const Values *> values;
+
+  if (values.count(team_number) == 0) {
+    values[team_number] = DoGetValuesForTeam(team_number);
+#if __has_feature(address_sanitizer)
+    __lsan_ignore_object(values[team_number]);
+#endif
+  }
+  return *values[team_number];
+}
+
+}  // namespace constants
+}  // namespace frc971
diff --git a/y2014/constants.h b/y2014/constants.h
new file mode 100644
index 0000000..79ba826
--- /dev/null
+++ b/y2014/constants.h
@@ -0,0 +1,145 @@
+#ifndef Y2014_CONSTANTS_H_
+#define Y2014_CONSTANTS_H_
+
+#include <stdint.h>
+
+#include "frc971/control_loops/state_feedback_loop.h"
+#include "frc971/shifter_hall_effect.h"
+
+namespace frc971 {
+namespace constants {
+
+// Has all of the numbers that change for both robots and makes it easy to
+// retrieve the values for the current one.
+
+// Everything is in SI units (volts, radians, meters, seconds, etc).
+// Some of these values are related to the conversion between raw values
+// (encoder counts, voltage, etc) to scaled units (radians, meters, etc).
+
+// This structure contains current values for all of the things that change.
+struct Values {
+  // This is useful for representing the 2 sides of a hall effect sensor etc.
+  struct AnglePair {
+    // The angles for increasing values (posedge on lower, negedge on upper).
+    double lower_angle, upper_angle;
+    // The angles for decreasing values (negedge on lower, posedge on upper).
+    double lower_decreasing_angle, upper_decreasing_angle;
+  };
+
+  // The ratio from the encoder shaft to the drivetrain wheels.
+  double drivetrain_encoder_ratio;
+
+  // The gear ratios from motor shafts to the drivetrain wheels for high and low
+  // gear.
+  double low_gear_ratio;
+  double high_gear_ratio;
+  ShifterHallEffect left_drive, right_drive;
+  bool clutch_transmission;
+
+  double turn_width;
+
+  ::std::function<StateFeedbackLoop<2, 2, 2>()> make_v_drivetrain_loop;
+  ::std::function<StateFeedbackLoop<4, 2, 2>()> make_drivetrain_loop;
+
+  double drivetrain_done_distance;
+  double drivetrain_max_speed;
+
+  struct ZeroingConstants {
+    // The number of samples in the moving average filter.
+    int average_filter_size;
+    // The difference in scaled units between two index pulses.
+    double index_difference;
+    // The absolute position in scaled units of one of the index pulses.
+    double measured_index_position;
+    // Value between 0 and 1 which determines a fraction of the index_diff
+    // you want to use.
+    double allowable_encoder_error;
+  };
+
+  // Defines a range of motion for a subsystem.
+  // These are all absolute positions in scaled units.
+  struct Range {
+    double lower_limit;
+    double upper_limit;
+    double lower_hard_limit;
+    double upper_hard_limit;
+  };
+
+  struct Shooter {
+    double lower_limit;
+    double upper_limit;
+    double lower_hard_limit;
+    double upper_hard_limit;
+    // If the plunger is further back than this position, it is safe for the
+    // latch to be down.  Anything else would be considered a collision.
+    double latch_max_safe_position;
+    AnglePair plunger_back;
+    AnglePair pusher_distal;
+    AnglePair pusher_proximal;
+    double zeroing_speed;
+    double unload_speed;
+  };
+
+  Shooter shooter;
+
+  struct Claws {
+    double claw_zeroing_off_speed;
+    double claw_zeroing_speed;
+    double claw_zeroing_separation;
+
+    // claw separation that would be considered a collision
+    double claw_min_separation;
+    double claw_max_separation;
+
+    // We should never get closer/farther than these.
+    double soft_min_separation;
+    double soft_max_separation;
+
+    // Three hall effects are known as front, calib and back
+    typedef Values::AnglePair AnglePair;
+
+    struct Claw {
+      double lower_hard_limit;
+      double upper_hard_limit;
+      double lower_limit;
+      double upper_limit;
+      AnglePair front;
+      AnglePair calibration;
+      AnglePair back;
+    };
+
+    Claw upper_claw;
+    Claw lower_claw;
+
+    double claw_unimportant_epsilon;
+    double start_fine_tune_pos;
+    double max_zeroing_voltage;
+  };
+  Claws claw;
+
+  // Has all the constants for the ShootAction class.
+  struct ShooterAction {
+    // Minimum separation required between the claws in order to be able to
+    // shoot.
+    double claw_shooting_separation;
+
+    // Goal to send to the claw when opening it up in preparation for shooting;
+    // should be larger than claw_shooting_separation so that we can shoot
+    // promptly.
+    double claw_separation_goal;
+   };
+  ShooterAction shooter_action;
+};
+
+// Creates (once) a Values instance for ::aos::network::GetTeamNumber() and
+// returns a reference to it.
+const Values &GetValues();
+
+// Creates Values instances for each team number it is called with and returns
+// them.
+const Values &GetValuesForTeam(uint16_t team_number);
+
+}  // namespace constants
+}  // namespace frc971
+
+#endif  // Y2014_CONSTANTS_H_
diff --git a/y2014/control_loops/claw/claw.cc b/y2014/control_loops/claw/claw.cc
new file mode 100644
index 0000000..7322b1e
--- /dev/null
+++ b/y2014/control_loops/claw/claw.cc
@@ -0,0 +1,1024 @@
+#include "y2014/control_loops/claw/claw.h"
+
+#include <algorithm>
+
+#include "aos/common/controls/control_loops.q.h"
+#include "aos/common/logging/logging.h"
+#include "aos/common/logging/queue_logging.h"
+#include "aos/common/logging/matrix_logging.h"
+#include "aos/common/commonmath.h"
+
+#include "y2014/constants.h"
+#include "y2014/control_loops/claw/claw_motor_plant.h"
+
+// Zeroing plan.
+// There are 2 types of zeros.  Enabled and disabled ones.
+// Disabled ones are only valid during auto mode, and can be used to speed up
+// the enabled zero process.  We need to re-zero during teleop in case the auto
+// zero was poor and causes us to miss all our shots.
+//
+// We need to be able to zero manually while disabled by moving the joint over
+// the zeros.
+// Zero on the down edge when disabled (gravity in the direction of motion)
+//
+// When enabled, zero on the up edge (gravity opposing the direction of motion)
+// The enabled sequence needs to work as follows.  We can crash the claw if we
+// bring them too close to each other or too far from each other.  The only safe
+// thing to do is to move them in unison.
+//
+// Start by moving them both towards the front of the bot to either find either
+// the middle hall effect on either jaw, or the front hall effect on the bottom
+// jaw.  Any edge that isn't the desired edge will provide an approximate edge
+// location that can be used for the fine tuning step.
+// Once an edge is found on the front claw, move back the other way with both
+// claws until an edge is found for the other claw.
+// Now that we have an approximate zero, we can robustify the limits to keep
+// both claws safe.  Then, we can move both claws to a position that is the
+// correct side of the zero and go zero.
+
+// Valid region plan.
+// Difference between the arms has a range, and the values of each arm has a
+// range.
+// If a claw runs up against a static limit, don't let the goal change outside
+// the limit.
+// If a claw runs up against a movable limit, move both claws outwards to get
+// out of the condition.
+
+namespace frc971 {
+namespace control_loops {
+
+static const double kZeroingVoltage = 4.0;
+static const double kMaxVoltage = 12.0;
+const double kRezeroThreshold = 0.07;
+
+ClawLimitedLoop::ClawLimitedLoop(StateFeedbackLoop<4, 2, 2> &&loop)
+    : StateFeedbackLoop<4, 2, 2>(::std::move(loop)),
+      uncapped_average_voltage_(0.0),
+      is_zeroing_(true),
+      U_Poly_((Eigen::Matrix<double, 4, 2>() << 1, 0,
+               -1, 0,
+               0, 1,
+               0, -1).finished(),
+              (Eigen::Matrix<double, 4, 1>() << kMaxVoltage, kMaxVoltage,
+               kMaxVoltage, kMaxVoltage).finished()),
+      U_Poly_zeroing_((Eigen::Matrix<double, 4, 2>() << 1, 0,
+               -1, 0,
+               0, 1,
+               0, -1).finished(),
+              (Eigen::Matrix<double, 4, 1>() <<
+               kZeroingVoltage, kZeroingVoltage,
+               kZeroingVoltage, kZeroingVoltage).finished()) {
+  ::aos::controls::HPolytope<0>::Init();
+}
+
+// Caps the voltage prioritizing reducing velocity error over reducing
+// positional error.
+// Uses the polytope libararies which we used to just use for the drivetrain.
+// Uses a region representing the maximum voltage and then transforms it such
+// that the points represent different amounts of positional error and
+// constrains the region such that, if at all possible, it will maintain its
+// current efforts to reduce velocity error.
+void ClawLimitedLoop::CapU() {
+  const Eigen::Matrix<double, 4, 1> error = R() - X_hat();
+
+  double u_top = U(1, 0);
+  double u_bottom = U(0, 0);
+
+  uncapped_average_voltage_ = (u_top + u_bottom) / 2;
+
+  double max_voltage = is_zeroing_ ? kZeroingVoltage : kMaxVoltage;
+
+  if (::std::abs(u_bottom) > max_voltage || ::std::abs(u_top) > max_voltage) {
+    LOG_MATRIX(DEBUG, "U at start", U());
+    // H * U <= k
+    // U = UPos + UVel
+    // H * (UPos + UVel) <= k
+    // H * UPos <= k - H * UVel
+
+    // Now, we can do a coordinate transformation and say the following.
+
+    // UPos = position_K * position_error
+    // (H * position_K) * position_error <= k - H * UVel
+
+    Eigen::Matrix<double, 2, 2> position_K;
+    position_K << K(0, 0), K(0, 1),
+                  K(1, 0), K(1, 1);
+    Eigen::Matrix<double, 2, 2> velocity_K;
+    velocity_K << K(0, 2), K(0, 3),
+                  K(1, 2), K(1, 3);
+
+    Eigen::Matrix<double, 2, 1> position_error;
+    position_error << error(0, 0), error(1, 0);
+    Eigen::Matrix<double, 2, 1> velocity_error;
+    velocity_error << error(2, 0), error(3, 0);
+    LOG_MATRIX(DEBUG, "error", error);
+
+    const auto &poly = is_zeroing_ ? U_Poly_zeroing_ : U_Poly_;
+    const Eigen::Matrix<double, 4, 2> pos_poly_H = poly.H() * position_K;
+    const Eigen::Matrix<double, 4, 1> pos_poly_k =
+        poly.k() - poly.H() * velocity_K * velocity_error;
+    const ::aos::controls::HPolytope<2> pos_poly(pos_poly_H, pos_poly_k);
+
+    Eigen::Matrix<double, 2, 1> adjusted_pos_error;
+    {
+      const auto &P = position_error;
+
+      // This line was at 45 degrees but is now at some angle steeper than the
+      // straight one between the points.
+      Eigen::Matrix<double, 1, 2> angle_45;
+      // If the top claw is above its soft upper limit, make the line actually
+      // 45 degrees to avoid smashing it into the limit in an attempt to fix the
+      // separation error faster than the bottom position one.
+      if (X_hat(0, 0) + X_hat(1, 0) >
+          constants::GetValues().claw.upper_claw.upper_limit) {
+        angle_45 << 1, 1;
+      } else {
+        // Fixing separation error half as fast as positional error works well
+        // because it means they both close evenly.
+        angle_45 << ::std::sqrt(3), 1;
+      }
+      Eigen::Matrix<double, 1, 2> L45_quadrant;
+      L45_quadrant << ::aos::sign(P(1, 0)), -::aos::sign(P(0, 0));
+      const auto L45 = L45_quadrant.cwiseProduct(angle_45);
+      const double w45 = 0;
+
+      Eigen::Matrix<double, 1, 2> LH;
+      if (::std::abs(P(0, 0)) > ::std::abs(P(1, 0))) {
+        LH << 0, 1;
+      } else {
+        LH << 1, 0;
+      }
+      const double wh = LH.dot(P);
+
+      Eigen::Matrix<double, 2, 2> standard;
+      standard << L45, LH;
+      Eigen::Matrix<double, 2, 1> W;
+      W << w45, wh;
+      const Eigen::Matrix<double, 2, 1> intersection = standard.inverse() * W;
+
+      bool is_inside_h;
+      const auto adjusted_pos_error_h =
+          DoCoerceGoal(pos_poly, LH, wh, position_error, &is_inside_h);
+      const auto adjusted_pos_error_45 =
+          DoCoerceGoal(pos_poly, L45, w45, intersection, nullptr);
+      if (pos_poly.IsInside(intersection)) {
+        adjusted_pos_error = adjusted_pos_error_h;
+      } else {
+        if (is_inside_h) {
+          if (adjusted_pos_error_h.norm() > adjusted_pos_error_45.norm()) {
+            adjusted_pos_error = adjusted_pos_error_h;
+          } else {
+            adjusted_pos_error = adjusted_pos_error_45;
+          }
+        } else {
+          adjusted_pos_error = adjusted_pos_error_45;
+        }
+      }
+    }
+
+    LOG_MATRIX(DEBUG, "adjusted_pos_error", adjusted_pos_error);
+    mutable_U() = velocity_K * velocity_error + position_K * adjusted_pos_error;
+    LOG_MATRIX(DEBUG, "U is now", U());
+
+    {
+      const auto values = constants::GetValues().claw;
+      if (top_known_) {
+        if (X_hat(0, 0) + X_hat(1, 0) > values.upper_claw.upper_limit && U(1, 0) > 0) {
+          LOG(WARNING, "upper claw too high and moving up\n");
+          mutable_U(1, 0) = 0;
+        } else if (X_hat(0, 0) + X_hat(1, 0) < values.upper_claw.lower_limit &&
+                   U(1, 0) < 0) {
+          LOG(WARNING, "upper claw too low and moving down\n");
+          mutable_U(1, 0) = 0;
+        }
+      }
+      if (bottom_known_) {
+        if (X_hat(0, 0) > values.lower_claw.upper_limit && U(0, 0) > 0) {
+          LOG(WARNING, "lower claw too high and moving up\n");
+          mutable_U(0, 0) = 0;
+        } else if (X_hat(0, 0) < values.lower_claw.lower_limit && U(0, 0) < 0) {
+          LOG(WARNING, "lower claw too low and moving down\n");
+          mutable_U(0, 0) = 0;
+        }
+      }
+    }
+  }
+}
+
+ZeroedStateFeedbackLoop::ZeroedStateFeedbackLoop(const char *name,
+                                                 ClawMotor *motor)
+    : offset_(0.0),
+      name_(name),
+      motor_(motor),
+      zeroing_state_(UNKNOWN_POSITION),
+      encoder_(0.0),
+      last_encoder_(0.0) {}
+
+void ZeroedStateFeedbackLoop::SetPositionValues(const HalfClawPosition &claw) {
+  front_.Update(claw.front);
+  calibration_.Update(claw.calibration);
+  back_.Update(claw.back);
+
+  bool any_sensor_triggered = any_triggered();
+  if (any_sensor_triggered && any_triggered_last_) {
+    // We are still on the hall effect and nothing has changed.
+    min_hall_effect_on_angle_ =
+        ::std::min(min_hall_effect_on_angle_, claw.position);
+    max_hall_effect_on_angle_ =
+        ::std::max(max_hall_effect_on_angle_, claw.position);
+  } else if (!any_sensor_triggered && !any_triggered_last_) {
+    // We are still off the hall effect and nothing has changed.
+    min_hall_effect_off_angle_ =
+        ::std::min(min_hall_effect_off_angle_, claw.position);
+    max_hall_effect_off_angle_ =
+        ::std::max(max_hall_effect_off_angle_, claw.position);
+  }
+
+  if (front_.is_posedge()) {
+    // Saw a posedge on the hall effect.  Reset the limits.
+    min_hall_effect_on_angle_ =
+        ::std::min(claw.front.posedge_value, claw.position);
+    max_hall_effect_on_angle_ =
+        ::std::max(claw.front.posedge_value, claw.position);
+  }
+  if (calibration_.is_posedge()) {
+    // Saw a posedge on the hall effect.  Reset the limits.
+    min_hall_effect_on_angle_ =
+        ::std::min(claw.calibration.posedge_value, claw.position);
+    max_hall_effect_on_angle_ =
+        ::std::max(claw.calibration.posedge_value, claw.position);
+  }
+  if (back_.is_posedge()) {
+    // Saw a posedge on the hall effect.  Reset the limits.
+    min_hall_effect_on_angle_ =
+        ::std::min(claw.back.posedge_value, claw.position);
+    max_hall_effect_on_angle_ =
+        ::std::max(claw.back.posedge_value, claw.position);
+  }
+
+  if (front_.is_negedge()) {
+    // Saw a negedge on the hall effect.  Reset the limits.
+    min_hall_effect_off_angle_ =
+        ::std::min(claw.front.negedge_value, claw.position);
+    max_hall_effect_off_angle_ =
+        ::std::max(claw.front.negedge_value, claw.position);
+  }
+  if (calibration_.is_negedge()) {
+    // Saw a negedge on the hall effect.  Reset the limits.
+    min_hall_effect_off_angle_ =
+        ::std::min(claw.calibration.negedge_value, claw.position);
+    max_hall_effect_off_angle_ =
+        ::std::max(claw.calibration.negedge_value, claw.position);
+  }
+  if (back_.is_negedge()) {
+    // Saw a negedge on the hall effect.  Reset the limits.
+    min_hall_effect_off_angle_ =
+        ::std::min(claw.back.negedge_value, claw.position);
+    max_hall_effect_off_angle_ =
+        ::std::max(claw.back.negedge_value, claw.position);
+  }
+
+  last_encoder_ = encoder_;
+  if (front().value() || calibration().value() || back().value()) {
+    last_on_encoder_ = encoder_;
+  } else {
+    last_off_encoder_ = encoder_;
+  }
+  encoder_ = claw.position;
+  any_triggered_last_ = any_sensor_triggered;
+}
+
+void ZeroedStateFeedbackLoop::Reset(const HalfClawPosition &claw) {
+  set_zeroing_state(ZeroedStateFeedbackLoop::UNKNOWN_POSITION);
+
+  front_.Reset(claw.front);
+  calibration_.Reset(claw.calibration);
+  back_.Reset(claw.back);
+  // close up the min and max edge positions as they are no longer valid and
+  // will be expanded in future iterations
+  min_hall_effect_on_angle_ = claw.position;
+  max_hall_effect_on_angle_ = claw.position;
+  min_hall_effect_off_angle_ = claw.position;
+  max_hall_effect_off_angle_ = claw.position;
+  any_triggered_last_ = any_triggered();
+}
+
+bool TopZeroedStateFeedbackLoop::SetCalibrationOnEdge(
+    const constants::Values::Claws::Claw &claw_values,
+    JointZeroingState zeroing_state) {
+  double edge_encoder;
+  double edge_angle;
+  if (GetPositionOfEdge(claw_values, &edge_encoder, &edge_angle)) {
+    LOG(INFO, "Calibration edge edge should be %f.\n", edge_angle);
+    SetCalibration(edge_encoder, edge_angle);
+    set_zeroing_state(zeroing_state);
+    return true;
+  }
+  return false;
+}
+
+void TopZeroedStateFeedbackLoop::HandleCalibrationError(
+    const constants::Values::Claws::Claw &claw_values) {
+  double edge_encoder;
+  double edge_angle;
+  if (GetPositionOfEdge(claw_values, &edge_encoder, &edge_angle)) {
+    const double calibration_error =
+        ComputeCalibrationChange(edge_encoder, edge_angle);
+    LOG(INFO, "Top calibration error is %f\n", calibration_error);
+    if (::std::abs(calibration_error) > kRezeroThreshold) {
+      LOG(WARNING, "rezeroing top\n");
+      SetCalibration(edge_encoder, edge_angle);
+      set_zeroing_state(ZeroedStateFeedbackLoop::UNKNOWN_POSITION);
+    }
+  }
+}
+
+
+void BottomZeroedStateFeedbackLoop::HandleCalibrationError(
+    const constants::Values::Claws::Claw &claw_values) {
+  double edge_encoder;
+  double edge_angle;
+  if (GetPositionOfEdge(claw_values, &edge_encoder, &edge_angle)) {
+    const double calibration_error =
+        ComputeCalibrationChange(edge_encoder, edge_angle);
+    LOG(INFO, "Bottom calibration error is %f\n", calibration_error);
+    if (::std::abs(calibration_error) > kRezeroThreshold) {
+      LOG(WARNING, "rezeroing bottom\n");
+      SetCalibration(edge_encoder, edge_angle);
+      set_zeroing_state(ZeroedStateFeedbackLoop::UNKNOWN_POSITION);
+    }
+  }
+}
+
+bool BottomZeroedStateFeedbackLoop::SetCalibrationOnEdge(
+    const constants::Values::Claws::Claw &claw_values,
+    JointZeroingState zeroing_state) {
+  double edge_encoder;
+  double edge_angle;
+  if (GetPositionOfEdge(claw_values, &edge_encoder, &edge_angle)) {
+    LOG(INFO, "Calibration edge.\n");
+    SetCalibration(edge_encoder, edge_angle);
+    set_zeroing_state(zeroing_state);
+    return true;
+  }
+  return false;
+}
+
+ClawMotor::ClawMotor(control_loops::ClawQueue *my_claw)
+    : aos::controls::ControlLoop<control_loops::ClawQueue>(my_claw),
+      has_top_claw_goal_(false),
+      top_claw_goal_(0.0),
+      top_claw_(this),
+      has_bottom_claw_goal_(false),
+      bottom_claw_goal_(0.0),
+      bottom_claw_(this),
+      claw_(MakeClawLoop()),
+      was_enabled_(false),
+      doing_calibration_fine_tune_(false),
+      capped_goal_(false),
+      mode_(UNKNOWN_LOCATION) {}
+
+const int ZeroedStateFeedbackLoop::kZeroingMaxVoltage;
+
+bool ZeroedStateFeedbackLoop::SawFilteredPosedge(
+    const HallEffectTracker &this_sensor, const HallEffectTracker &sensorA,
+    const HallEffectTracker &sensorB) {
+  if (posedge_filter_ == nullptr && this_sensor.posedge_count_changed() &&
+      !sensorA.posedge_count_changed() && !sensorB.posedge_count_changed() &&
+      this_sensor.value() && !this_sensor.last_value()) {
+    posedge_filter_ = &this_sensor;
+  } else if (posedge_filter_ == &this_sensor &&
+             !this_sensor.posedge_count_changed() &&
+             !sensorA.posedge_count_changed() &&
+             !sensorB.posedge_count_changed() && this_sensor.value()) {
+    posedge_filter_ = nullptr;
+    return true;
+  } else if (posedge_filter_ == &this_sensor) {
+    posedge_filter_ = nullptr;
+  }
+  return false;
+}
+
+bool ZeroedStateFeedbackLoop::SawFilteredNegedge(
+    const HallEffectTracker &this_sensor, const HallEffectTracker &sensorA,
+    const HallEffectTracker &sensorB) {
+  if (negedge_filter_ == nullptr && this_sensor.negedge_count_changed() &&
+      !sensorA.negedge_count_changed() && !sensorB.negedge_count_changed() &&
+      !this_sensor.value() && this_sensor.last_value()) {
+    negedge_filter_ = &this_sensor;
+  } else if (negedge_filter_ == &this_sensor &&
+             !this_sensor.negedge_count_changed() &&
+             !sensorA.negedge_count_changed() &&
+             !sensorB.negedge_count_changed() && !this_sensor.value()) {
+    negedge_filter_ = nullptr;
+    return true;
+  } else if (negedge_filter_ == &this_sensor) {
+    negedge_filter_ = nullptr;
+  }
+  return false;
+}
+
+bool ZeroedStateFeedbackLoop::DoGetPositionOfEdge(
+    const constants::Values::Claws::AnglePair &angles, double *edge_encoder,
+    double *edge_angle, const HallEffectTracker &this_sensor,
+    const HallEffectTracker &sensorA, const HallEffectTracker &sensorB,
+    const char *hall_effect_name) {
+  bool found_edge = false;
+
+  if (SawFilteredPosedge(this_sensor, sensorA, sensorB)) {
+    if (min_hall_effect_off_angle_ == max_hall_effect_off_angle_) {
+      LOG(WARNING, "%s: Uncertain which side, rejecting posedge\n", name_);
+    } else {
+      const double average_last_encoder =
+          (min_hall_effect_off_angle_ + max_hall_effect_off_angle_) / 2.0;
+      if (this_sensor.posedge_value() < average_last_encoder) {
+        *edge_angle = angles.upper_decreasing_angle;
+        LOG(INFO, "%s Posedge upper of %s -> %f posedge: %f avg_encoder: %f\n",
+            name_, hall_effect_name, *edge_angle, this_sensor.posedge_value(),
+            average_last_encoder);
+      } else {
+        *edge_angle = angles.lower_angle;
+        LOG(INFO, "%s Posedge lower of %s -> %f posedge: %f avg_encoder: %f\n",
+            name_, hall_effect_name, *edge_angle, this_sensor.posedge_value(),
+            average_last_encoder);
+      }
+      *edge_encoder = this_sensor.posedge_value();
+      found_edge = true;
+    }
+  }
+
+  if (SawFilteredNegedge(this_sensor, sensorA, sensorB)) {
+    if (min_hall_effect_on_angle_ == max_hall_effect_on_angle_) {
+      LOG(WARNING, "%s: Uncertain which side, rejecting negedge\n", name_);
+    } else {
+      const double average_last_encoder =
+          (min_hall_effect_on_angle_ + max_hall_effect_on_angle_) / 2.0;
+      if (this_sensor.negedge_value() > average_last_encoder) {
+        *edge_angle = angles.upper_angle;
+        LOG(INFO, "%s Negedge upper of %s -> %f negedge: %f avg_encoder: %f\n",
+            name_, hall_effect_name, *edge_angle, this_sensor.negedge_value(),
+            average_last_encoder);
+      } else {
+        *edge_angle = angles.lower_decreasing_angle;
+        LOG(INFO, "%s Negedge lower of %s -> %f negedge: %f avg_encoder: %f\n",
+            name_, hall_effect_name, *edge_angle, this_sensor.negedge_value(),
+            average_last_encoder);
+      }
+      *edge_encoder = this_sensor.negedge_value();
+      found_edge = true;
+    }
+  }
+
+  return found_edge;
+}
+
+bool ZeroedStateFeedbackLoop::GetPositionOfEdge(
+    const constants::Values::Claws::Claw &claw_values, double *edge_encoder,
+    double *edge_angle) {
+  if (DoGetPositionOfEdge(claw_values.front, edge_encoder, edge_angle, front_,
+                          calibration_, back_, "front")) {
+    return true;
+  }
+  if (DoGetPositionOfEdge(claw_values.calibration, edge_encoder, edge_angle,
+                          calibration_, front_, back_, "calibration")) {
+    return true;
+  }
+  if (DoGetPositionOfEdge(claw_values.back, edge_encoder, edge_angle, back_,
+                          calibration_, front_, "back")) {
+    return true;
+  }
+  return false;
+}
+
+void TopZeroedStateFeedbackLoop::SetCalibration(double edge_encoder,
+                                                double edge_angle) {
+  double old_offset = offset_;
+  offset_ = edge_angle - edge_encoder;
+  const double doffset = offset_ - old_offset;
+  motor_->ChangeTopOffset(doffset);
+}
+
+double TopZeroedStateFeedbackLoop::ComputeCalibrationChange(double edge_encoder,
+                                                            double edge_angle) {
+  const double offset = edge_angle - edge_encoder;
+  const double doffset = offset - offset_;
+  return doffset;
+}
+
+void BottomZeroedStateFeedbackLoop::SetCalibration(double edge_encoder,
+                                                   double edge_angle) {
+  double old_offset = offset_;
+  offset_ = edge_angle - edge_encoder;
+  const double doffset = offset_ - old_offset;
+  motor_->ChangeBottomOffset(doffset);
+}
+
+double BottomZeroedStateFeedbackLoop::ComputeCalibrationChange(
+    double edge_encoder, double edge_angle) {
+  const double offset = edge_angle - edge_encoder;
+  const double doffset = offset - offset_;
+  return doffset;
+}
+
+void ClawMotor::ChangeTopOffset(double doffset) {
+  claw_.ChangeTopOffset(doffset);
+  if (has_top_claw_goal_) {
+    top_claw_goal_ += doffset;
+  }
+}
+
+void ClawMotor::ChangeBottomOffset(double doffset) {
+  claw_.ChangeBottomOffset(doffset);
+  if (has_bottom_claw_goal_) {
+    bottom_claw_goal_ += doffset;
+  }
+}
+
+void ClawLimitedLoop::ChangeTopOffset(double doffset) {
+  mutable_X_hat()(1, 0) += doffset;
+  LOG(INFO, "Changing top offset by %f\n", doffset);
+}
+void ClawLimitedLoop::ChangeBottomOffset(double doffset) {
+  mutable_X_hat()(0, 0) += doffset;
+  mutable_X_hat()(1, 0) -= doffset;
+  LOG(INFO, "Changing bottom offset by %f\n", doffset);
+}
+
+void LimitClawGoal(double *bottom_goal, double *top_goal,
+                   const frc971::constants::Values &values) {
+  // first update position based on angle limit
+  const double separation = *top_goal - *bottom_goal;
+  if (separation > values.claw.soft_max_separation) {
+    LOG_STRUCT(DEBUG, "before", ClawPositionToLog(*top_goal, *bottom_goal));
+    const double dsep = (separation - values.claw.soft_max_separation) / 2.0;
+    *bottom_goal += dsep;
+    *top_goal -= dsep;
+    LOG_STRUCT(DEBUG, "after", ClawPositionToLog(*top_goal, *bottom_goal));
+  }
+  if (separation < values.claw.soft_min_separation) {
+    LOG_STRUCT(DEBUG, "before", ClawPositionToLog(*top_goal, *bottom_goal));
+    const double dsep = (separation - values.claw.soft_min_separation) / 2.0;
+    *bottom_goal += dsep;
+    *top_goal -= dsep;
+    LOG_STRUCT(DEBUG, "after", ClawPositionToLog(*top_goal, *bottom_goal));
+  }
+
+  // now move both goals in unison
+  if (*bottom_goal < values.claw.lower_claw.lower_limit) {
+    LOG_STRUCT(DEBUG, "before", ClawPositionToLog(*top_goal, *bottom_goal));
+    *top_goal += values.claw.lower_claw.lower_limit - *bottom_goal;
+    *bottom_goal = values.claw.lower_claw.lower_limit;
+    LOG_STRUCT(DEBUG, "after", ClawPositionToLog(*top_goal, *bottom_goal));
+  }
+  if (*bottom_goal > values.claw.lower_claw.upper_limit) {
+    LOG_STRUCT(DEBUG, "before", ClawPositionToLog(*top_goal, *bottom_goal));
+    *top_goal -= *bottom_goal - values.claw.lower_claw.upper_limit;
+    *bottom_goal = values.claw.lower_claw.upper_limit;
+    LOG_STRUCT(DEBUG, "after", ClawPositionToLog(*top_goal, *bottom_goal));
+  }
+
+  if (*top_goal < values.claw.upper_claw.lower_limit) {
+    LOG_STRUCT(DEBUG, "before", ClawPositionToLog(*top_goal, *bottom_goal));
+    *bottom_goal += values.claw.upper_claw.lower_limit - *top_goal;
+    *top_goal = values.claw.upper_claw.lower_limit;
+    LOG_STRUCT(DEBUG, "after", ClawPositionToLog(*top_goal, *bottom_goal));
+  }
+  if (*top_goal > values.claw.upper_claw.upper_limit) {
+    LOG_STRUCT(DEBUG, "before", ClawPositionToLog(*top_goal, *bottom_goal));
+    *bottom_goal -= *top_goal - values.claw.upper_claw.upper_limit;
+    *top_goal = values.claw.upper_claw.upper_limit;
+    LOG_STRUCT(DEBUG, "after", ClawPositionToLog(*top_goal, *bottom_goal));
+  }
+}
+
+bool ClawMotor::is_ready() const {
+  return (
+      (top_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED &&
+       bottom_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED) ||
+      (((::aos::joystick_state.get() == NULL)
+            ? true
+            : ::aos::joystick_state->autonomous) &&
+       ((top_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED ||
+         top_claw_.zeroing_state() ==
+             ZeroedStateFeedbackLoop::DISABLED_CALIBRATION) &&
+        (bottom_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED ||
+         bottom_claw_.zeroing_state() ==
+             ZeroedStateFeedbackLoop::DISABLED_CALIBRATION))));
+}
+
+bool ClawMotor::is_zeroing() const { return !is_ready(); }
+
+// Positive angle is up, and positive power is up.
+void ClawMotor::RunIteration(const control_loops::ClawQueue::Goal *goal,
+                             const control_loops::ClawQueue::Position *position,
+                             control_loops::ClawQueue::Output *output,
+                             control_loops::ClawQueue::Status *status) {
+  constexpr double dt = 0.01;
+
+  // Disable the motors now so that all early returns will return with the
+  // motors disabled.
+  if (output) {
+    output->top_claw_voltage = 0;
+    output->bottom_claw_voltage = 0;
+    output->intake_voltage = 0;
+    output->tusk_voltage = 0;
+  }
+
+  if (goal) {
+    if (::std::isnan(goal->bottom_angle) ||
+        ::std::isnan(goal->separation_angle) || ::std::isnan(goal->intake) ||
+        ::std::isnan(goal->centering)) {
+      return;
+    }
+  }
+
+  if (WasReset()) {
+    top_claw_.Reset(position->top);
+    bottom_claw_.Reset(position->bottom);
+  }
+
+  const frc971::constants::Values &values = constants::GetValues();
+
+  if (position) {
+    Eigen::Matrix<double, 2, 1> Y;
+    Y << position->bottom.position + bottom_claw_.offset(),
+        position->top.position + top_claw_.offset();
+    claw_.Correct(Y);
+
+    top_claw_.SetPositionValues(position->top);
+    bottom_claw_.SetPositionValues(position->bottom);
+
+    if (!has_top_claw_goal_) {
+      has_top_claw_goal_ = true;
+      top_claw_goal_ = top_claw_.absolute_position();
+      initial_separation_ =
+          top_claw_.absolute_position() - bottom_claw_.absolute_position();
+    }
+    if (!has_bottom_claw_goal_) {
+      has_bottom_claw_goal_ = true;
+      bottom_claw_goal_ = bottom_claw_.absolute_position();
+      initial_separation_ =
+          top_claw_.absolute_position() - bottom_claw_.absolute_position();
+    }
+    LOG_STRUCT(DEBUG, "absolute position",
+               ClawPositionToLog(top_claw_.absolute_position(),
+                                 bottom_claw_.absolute_position()));
+  }
+
+  bool autonomous, enabled;
+  if (::aos::joystick_state.get() == nullptr) {
+    autonomous = true;
+    enabled = false;
+  } else {
+    autonomous = ::aos::joystick_state->autonomous;
+    enabled = ::aos::joystick_state->enabled;
+  }
+
+  double bottom_claw_velocity_ = 0.0;
+  double top_claw_velocity_ = 0.0;
+
+  if (goal != NULL &&
+      ((top_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED &&
+        bottom_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED) ||
+       (autonomous &&
+        ((top_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED ||
+          top_claw_.zeroing_state() ==
+              ZeroedStateFeedbackLoop::DISABLED_CALIBRATION) &&
+         (bottom_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED ||
+          bottom_claw_.zeroing_state() ==
+              ZeroedStateFeedbackLoop::DISABLED_CALIBRATION))))) {
+    // Ready to use the claw.
+    // Limit the goals here.
+    bottom_claw_goal_ = goal->bottom_angle;
+    top_claw_goal_ = goal->bottom_angle + goal->separation_angle;
+    has_bottom_claw_goal_ = true;
+    has_top_claw_goal_ = true;
+    doing_calibration_fine_tune_ = false;
+    mode_ = READY;
+
+    bottom_claw_.HandleCalibrationError(values.claw.lower_claw);
+    top_claw_.HandleCalibrationError(values.claw.upper_claw);
+  } else if (top_claw_.zeroing_state() !=
+             ZeroedStateFeedbackLoop::UNKNOWN_POSITION &&
+             bottom_claw_.zeroing_state() !=
+             ZeroedStateFeedbackLoop::UNKNOWN_POSITION) {
+    // Time to fine tune the zero.
+    // Limit the goals here.
+    if (!enabled) {
+      // If we are disabled, start the fine tune process over again.
+      doing_calibration_fine_tune_ = false;
+    }
+    if (bottom_claw_.zeroing_state() != ZeroedStateFeedbackLoop::CALIBRATED) {
+      // always get the bottom claw to calibrated first
+      LOG(DEBUG, "Calibrating the bottom of the claw\n");
+      if (!doing_calibration_fine_tune_) {
+        if (::std::abs(bottom_absolute_position() -
+                       values.claw.start_fine_tune_pos) <
+            values.claw.claw_unimportant_epsilon) {
+          doing_calibration_fine_tune_ = true;
+          bottom_claw_goal_ += values.claw.claw_zeroing_speed * dt;
+          top_claw_velocity_ = bottom_claw_velocity_ =
+              values.claw.claw_zeroing_speed;
+          LOG(DEBUG, "Ready to fine tune the bottom\n");
+          mode_ = FINE_TUNE_BOTTOM;
+        } else {
+          // send bottom to zeroing start
+          bottom_claw_goal_ = values.claw.start_fine_tune_pos;
+          LOG(DEBUG, "Going to the start position for the bottom\n");
+          mode_ = PREP_FINE_TUNE_BOTTOM;
+        }
+      } else {
+        mode_ = FINE_TUNE_BOTTOM;
+        bottom_claw_goal_ += values.claw.claw_zeroing_speed * dt;
+        top_claw_velocity_ = bottom_claw_velocity_ =
+            values.claw.claw_zeroing_speed;
+        if (top_claw_.front_or_back_triggered() ||
+            bottom_claw_.front_or_back_triggered()) {
+          // We shouldn't hit a limit, but if we do, go back to the zeroing
+          // point and try again.
+          doing_calibration_fine_tune_ = false;
+          bottom_claw_goal_ = values.claw.start_fine_tune_pos;
+          top_claw_velocity_ = bottom_claw_velocity_ = 0.0;
+          LOG(DEBUG, "Found a limit, starting over.\n");
+          mode_ = PREP_FINE_TUNE_BOTTOM;
+        }
+
+        if (position && bottom_claw_.SawFilteredPosedge(
+                            bottom_claw_.calibration(), bottom_claw_.front(),
+                            bottom_claw_.back())) {
+          // do calibration
+          bottom_claw_.SetCalibration(
+              position->bottom.calibration.posedge_value,
+              values.claw.lower_claw.calibration.lower_angle);
+          bottom_claw_.set_zeroing_state(ZeroedStateFeedbackLoop::CALIBRATED);
+          // calibrated so we are done fine tuning bottom
+          doing_calibration_fine_tune_ = false;
+          LOG(DEBUG, "Calibrated the bottom correctly!\n");
+        } else if (bottom_claw_.calibration().last_value()) {
+          LOG(DEBUG, "Aborting bottom fine tune because sensor triggered\n");
+          doing_calibration_fine_tune_ = false;
+          bottom_claw_.set_zeroing_state(
+              ZeroedStateFeedbackLoop::UNKNOWN_POSITION);
+        } else {
+          LOG(DEBUG, "Fine tuning\n");
+        }
+      }
+      // now set the top claw to track
+
+      top_claw_goal_ = bottom_claw_goal_ + values.claw.claw_zeroing_separation;
+    } else {
+      // bottom claw must be calibrated, start on the top
+      if (!doing_calibration_fine_tune_) {
+        if (::std::abs(top_absolute_position() -
+                       values.claw.start_fine_tune_pos) <
+            values.claw.claw_unimportant_epsilon) {
+          doing_calibration_fine_tune_ = true;
+          top_claw_goal_ += values.claw.claw_zeroing_speed * dt;
+          top_claw_velocity_ = bottom_claw_velocity_ =
+              values.claw.claw_zeroing_speed;
+          LOG(DEBUG, "Ready to fine tune the top\n");
+          mode_ = FINE_TUNE_TOP;
+        } else {
+          // send top to zeroing start
+          top_claw_goal_ = values.claw.start_fine_tune_pos;
+          LOG(DEBUG, "Going to the start position for the top\n");
+          mode_ = PREP_FINE_TUNE_TOP;
+        }
+      } else {
+        mode_ = FINE_TUNE_TOP;
+        top_claw_goal_ += values.claw.claw_zeroing_speed * dt;
+        top_claw_velocity_ = bottom_claw_velocity_ =
+            values.claw.claw_zeroing_speed;
+        if (top_claw_.front_or_back_triggered() ||
+            bottom_claw_.front_or_back_triggered()) {
+          // this should not happen, but now we know it won't
+          doing_calibration_fine_tune_ = false;
+          top_claw_goal_ = values.claw.start_fine_tune_pos;
+          top_claw_velocity_ = bottom_claw_velocity_ = 0.0;
+          LOG(DEBUG, "Found a limit, starting over.\n");
+          mode_ = PREP_FINE_TUNE_TOP;
+        }
+
+        if (position &&
+            top_claw_.SawFilteredPosedge(top_claw_.calibration(),
+                                         top_claw_.front(), top_claw_.back())) {
+          // do calibration
+          top_claw_.SetCalibration(
+              position->top.calibration.posedge_value,
+              values.claw.upper_claw.calibration.lower_angle);
+          top_claw_.set_zeroing_state(ZeroedStateFeedbackLoop::CALIBRATED);
+          // calibrated so we are done fine tuning top
+          doing_calibration_fine_tune_ = false;
+          LOG(DEBUG, "Calibrated the top correctly!\n");
+        } else if (top_claw_.calibration().last_value()) {
+          LOG(DEBUG, "Aborting top fine tune because sensor triggered\n");
+          doing_calibration_fine_tune_ = false;
+          top_claw_.set_zeroing_state(
+              ZeroedStateFeedbackLoop::UNKNOWN_POSITION);
+        }
+      }
+      // now set the bottom claw to track
+      bottom_claw_goal_ = top_claw_goal_ - values.claw.claw_zeroing_separation;
+    }
+  } else {
+    doing_calibration_fine_tune_ = false;
+    if (!was_enabled_ && enabled) {
+      if (position) {
+        top_claw_goal_ = position->top.position + top_claw_.offset();
+        bottom_claw_goal_ = position->bottom.position + bottom_claw_.offset();
+        initial_separation_ =
+            position->top.position - position->bottom.position;
+      } else {
+        has_top_claw_goal_ = false;
+        has_bottom_claw_goal_ = false;
+      }
+    }
+
+    if ((bottom_claw_.zeroing_state() !=
+             ZeroedStateFeedbackLoop::UNKNOWN_POSITION ||
+         bottom_claw_.front().value() || top_claw_.front().value()) &&
+        !top_claw_.back().value() && !bottom_claw_.back().value()) {
+      if (enabled) {
+        // Time to slowly move back up to find any position to narrow down the
+        // zero.
+        top_claw_goal_ += values.claw.claw_zeroing_off_speed * dt;
+        bottom_claw_goal_ += values.claw.claw_zeroing_off_speed * dt;
+        top_claw_velocity_ = bottom_claw_velocity_ =
+            values.claw.claw_zeroing_off_speed;
+        LOG(DEBUG, "Bottom is known.\n");
+      }
+    } else {
+      // We don't know where either claw is.  Slowly start moving down to find
+      // any hall effect.
+      if (enabled) {
+        top_claw_goal_ -= values.claw.claw_zeroing_off_speed * dt;
+        bottom_claw_goal_ -= values.claw.claw_zeroing_off_speed * dt;
+        top_claw_velocity_ = bottom_claw_velocity_ =
+            -values.claw.claw_zeroing_off_speed;
+        LOG(DEBUG, "Both are unknown.\n");
+      }
+    }
+
+    if (position) {
+      if (enabled) {
+        top_claw_.SetCalibrationOnEdge(
+            values.claw.upper_claw,
+            ZeroedStateFeedbackLoop::APPROXIMATE_CALIBRATION);
+        bottom_claw_.SetCalibrationOnEdge(
+            values.claw.lower_claw,
+            ZeroedStateFeedbackLoop::APPROXIMATE_CALIBRATION);
+      } else {
+        // TODO(austin): Only calibrate on the predetermined edge.
+        // We might be able to just ignore this since the backlash is soooo
+        // low.
+        // :)
+        top_claw_.SetCalibrationOnEdge(
+            values.claw.upper_claw,
+            ZeroedStateFeedbackLoop::DISABLED_CALIBRATION);
+        bottom_claw_.SetCalibrationOnEdge(
+            values.claw.lower_claw,
+            ZeroedStateFeedbackLoop::DISABLED_CALIBRATION);
+      }
+    }
+    mode_ = UNKNOWN_LOCATION;
+  }
+
+  // Limit the goals if both claws have been (mostly) found.
+  if (mode_ != UNKNOWN_LOCATION) {
+    LimitClawGoal(&bottom_claw_goal_, &top_claw_goal_, values);
+  }
+
+  claw_.set_positions_known(
+      top_claw_.zeroing_state() != ZeroedStateFeedbackLoop::UNKNOWN_POSITION,
+      bottom_claw_.zeroing_state() !=
+          ZeroedStateFeedbackLoop::UNKNOWN_POSITION);
+  if (has_top_claw_goal_ && has_bottom_claw_goal_) {
+    claw_.mutable_R() << bottom_claw_goal_, top_claw_goal_ - bottom_claw_goal_,
+        bottom_claw_velocity_, top_claw_velocity_ - bottom_claw_velocity_;
+    LOG_MATRIX(DEBUG, "actual goal", claw_.R());
+
+    // Only cap power when one of the halves of the claw is moving slowly and
+    // could wind up.
+    claw_.set_is_zeroing(mode_ == UNKNOWN_LOCATION || mode_ == FINE_TUNE_TOP ||
+                         mode_ == FINE_TUNE_BOTTOM);
+    claw_.Update(output == nullptr);
+  } else {
+    claw_.Update(true);
+  }
+
+  capped_goal_ = false;
+  switch (mode_) {
+    case READY:
+    case PREP_FINE_TUNE_TOP:
+    case PREP_FINE_TUNE_BOTTOM:
+      break;
+    case FINE_TUNE_BOTTOM:
+    case FINE_TUNE_TOP:
+    case UNKNOWN_LOCATION: {
+      if (claw_.uncapped_average_voltage() > values.claw.max_zeroing_voltage) {
+        double dx_bot = (claw_.U_uncapped(0, 0) -
+                     values.claw.max_zeroing_voltage) /
+                    claw_.K(0, 0);
+        double dx_top = (claw_.U_uncapped(1, 0) -
+                     values.claw.max_zeroing_voltage) /
+                    claw_.K(0, 0);
+        double dx = ::std::max(dx_top, dx_bot);
+        bottom_claw_goal_ -= dx;
+        top_claw_goal_ -= dx;
+        Eigen::Matrix<double, 4, 1> R;
+        R << bottom_claw_goal_, top_claw_goal_ - bottom_claw_goal_, claw_.R(2, 0),
+            claw_.R(3, 0);
+        claw_.mutable_U() = claw_.K() * (R - claw_.X_hat());
+        capped_goal_ = true;
+        LOG(DEBUG, "Moving the goal by %f to prevent windup."
+            " Uncapped is %f, max is %f, difference is %f\n",
+            dx,
+            claw_.uncapped_average_voltage(), values.claw.max_zeroing_voltage,
+            (claw_.uncapped_average_voltage() -
+             values.claw.max_zeroing_voltage));
+      } else if (claw_.uncapped_average_voltage() <
+                 -values.claw.max_zeroing_voltage) {
+        double dx_bot = (claw_.U_uncapped(0, 0) +
+                     values.claw.max_zeroing_voltage) /
+                    claw_.K(0, 0);
+        double dx_top = (claw_.U_uncapped(1, 0) +
+                     values.claw.max_zeroing_voltage) /
+                    claw_.K(0, 0);
+        double dx = ::std::min(dx_top, dx_bot);
+        bottom_claw_goal_ -= dx;
+        top_claw_goal_ -= dx;
+        Eigen::Matrix<double, 4, 1> R;
+        R << bottom_claw_goal_, top_claw_goal_ - bottom_claw_goal_, claw_.R(2, 0),
+            claw_.R(3, 0);
+        claw_.mutable_U() = claw_.K() * (R - claw_.X_hat());
+        capped_goal_ = true;
+        LOG(DEBUG, "Moving the goal by %f to prevent windup\n", dx);
+      }
+    } break;
+  }
+
+  if (output) {
+    if (goal) {
+      //setup the intake
+      output->intake_voltage =
+          (goal->intake > 12.0) ? 12 : (goal->intake < -12.0) ? -12.0
+                                                              : goal->intake;
+      output->tusk_voltage = goal->centering;
+      output->tusk_voltage =
+          (goal->centering > 12.0) ? 12 : (goal->centering < -12.0)
+              ? -12.0
+              : goal->centering;
+    }
+    output->top_claw_voltage = claw_.U(1, 0);
+    output->bottom_claw_voltage = claw_.U(0, 0);
+
+    if (output->top_claw_voltage > kMaxVoltage) {
+      output->top_claw_voltage = kMaxVoltage;
+    } else if (output->top_claw_voltage < -kMaxVoltage) {
+      output->top_claw_voltage = -kMaxVoltage;
+    }
+
+    if (output->bottom_claw_voltage > kMaxVoltage) {
+      output->bottom_claw_voltage = kMaxVoltage;
+    } else if (output->bottom_claw_voltage < -kMaxVoltage) {
+      output->bottom_claw_voltage = -kMaxVoltage;
+    }
+  }
+
+  status->bottom = bottom_absolute_position();
+  status->separation = top_absolute_position() - bottom_absolute_position();
+  status->bottom_velocity = claw_.X_hat(2, 0);
+  status->separation_velocity = claw_.X_hat(3, 0);
+
+  if (goal) {
+    bool bottom_done =
+        ::std::abs(bottom_absolute_position() - goal->bottom_angle) < 0.020;
+    bool bottom_velocity_done = ::std::abs(status->bottom_velocity) < 0.2;
+    bool separation_done =
+        ::std::abs((top_absolute_position() - bottom_absolute_position()) -
+                   goal->separation_angle) < 0.020;
+    bool separation_done_with_ball =
+        ::std::abs((top_absolute_position() - bottom_absolute_position()) -
+                   goal->separation_angle) < 0.06;
+    status->done = is_ready() && separation_done && bottom_done && bottom_velocity_done;
+    status->done_with_ball =
+        is_ready() && separation_done_with_ball && bottom_done && bottom_velocity_done;
+  } else {
+    status->done = status->done_with_ball = false;
+  }
+
+  status->zeroed = is_ready();
+  status->zeroed_for_auto =
+      (top_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED ||
+       top_claw_.zeroing_state() ==
+           ZeroedStateFeedbackLoop::DISABLED_CALIBRATION) &&
+      (bottom_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED ||
+       bottom_claw_.zeroing_state() ==
+           ZeroedStateFeedbackLoop::DISABLED_CALIBRATION);
+
+  was_enabled_ = enabled;
+}
+
+}  // namespace control_loops
+}  // namespace frc971
+
diff --git a/y2014/control_loops/claw/claw.gyp b/y2014/control_loops/claw/claw.gyp
new file mode 100644
index 0000000..8a6a7c5
--- /dev/null
+++ b/y2014/control_loops/claw/claw.gyp
@@ -0,0 +1,99 @@
+{
+  'targets': [
+    {
+      'target_name': 'replay_claw',
+      'type': 'executable',
+      'variables': {
+        'no_rsync': 1,
+      },
+      'sources': [
+        'replay_claw.cc',
+      ],
+      'dependencies': [
+        'claw_queue',
+        '<(AOS)/common/controls/controls.gyp:replay_control_loop',
+        '<(AOS)/linux_code/linux_code.gyp:init',
+      ],
+    },
+    {
+      'target_name': 'claw_queue',
+      'type': 'static_library',
+      'sources': ['claw.q'],
+      'variables': {
+        'header_path': 'y2014/control_loops/claw',
+      },
+      'dependencies': [
+        '<(AOS)/common/controls/controls.gyp:control_loop_queues',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:queues',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/controls/controls.gyp:control_loop_queues',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:queues',
+      ],
+      'includes': ['../../../aos/build/queues.gypi'],
+    },
+    {
+      'target_name': 'claw_lib',
+      'type': 'static_library',
+      'sources': [
+        'claw.cc',
+        'claw_motor_plant.cc',
+      ],
+      'dependencies': [
+        'claw_queue',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+        '<(DEPTH)/y2014/y2014.gyp:constants',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+        '<(AOS)/common/controls/controls.gyp:polytope',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:coerce_goal',
+        '<(AOS)/common/logging/logging.gyp:queue_logging',
+        '<(AOS)/common/logging/logging.gyp:matrix_logging',
+      ],
+      'export_dependent_settings': [
+        'claw_queue',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+        '<(AOS)/common/controls/controls.gyp:polytope',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:coerce_goal',
+      ],
+    },
+    {
+      'target_name': 'claw_lib_test',
+      'type': 'executable',
+      'sources': [
+        'claw_lib_test.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+        'claw_queue',
+        'claw_lib',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+        '<(AOS)/common/controls/controls.gyp:control_loop_test',
+      ],
+    },
+    {
+      'target_name': 'claw_calibration',
+      'type': 'executable',
+      'sources': [
+        'claw_calibration.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        'claw_queue',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+        '<(DEPTH)/y2014/y2014.gyp:constants',
+      ],
+    },
+    {
+      'target_name': 'claw',
+      'type': 'executable',
+      'sources': [
+        'claw_main.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        'claw_lib',
+      ],
+    },
+  ],
+}
diff --git a/y2014/control_loops/claw/claw.h b/y2014/control_loops/claw/claw.h
new file mode 100644
index 0000000..cdd3948
--- /dev/null
+++ b/y2014/control_loops/claw/claw.h
@@ -0,0 +1,265 @@
+#ifndef Y2014_CONTROL_LOOPS_CLAW_CLAW_H_
+#define Y2014_CONTROL_LOOPS_CLAW_CLAW_H_
+
+#include <memory>
+
+#include "aos/common/controls/control_loop.h"
+#include "aos/common/controls/polytope.h"
+#include "y2014/constants.h"
+#include "frc971/control_loops/state_feedback_loop.h"
+#include "frc971/control_loops/coerce_goal.h"
+#include "y2014/control_loops/claw/claw.q.h"
+#include "y2014/control_loops/claw/claw_motor_plant.h"
+#include "frc971/control_loops/hall_effect_tracker.h"
+
+namespace frc971 {
+namespace control_loops {
+namespace testing {
+class WindupClawTest;
+};
+
+// Note: Everything in this file assumes that there is a 1 cycle delay between
+// power being requested and it showing up at the motor.  It assumes that
+// X_hat(2, 1) is the voltage being applied as well.  It will go unstable if
+// that isn't true.
+
+class ClawLimitedLoop : public StateFeedbackLoop<4, 2, 2> {
+ public:
+  ClawLimitedLoop(StateFeedbackLoop<4, 2, 2> &&loop);
+  virtual void CapU();
+
+  void set_is_zeroing(bool is_zeroing) { is_zeroing_ = is_zeroing; }
+  void set_positions_known(bool top_known, bool bottom_known) {
+    top_known_ = top_known;
+    bottom_known_ = bottom_known;
+  }
+
+  void ChangeTopOffset(double doffset);
+  void ChangeBottomOffset(double doffset);
+
+  double uncapped_average_voltage() const { return uncapped_average_voltage_; }
+
+ private:
+  double uncapped_average_voltage_;
+  bool is_zeroing_;
+
+  bool top_known_ = false, bottom_known_ = false;
+
+  const ::aos::controls::HPolytope<2> U_Poly_, U_Poly_zeroing_;
+};
+
+class ClawMotor;
+
+// This class implements the CapU function correctly given all the extra
+// information that we know about from the wrist motor.
+// It does not have any zeroing logic in it, only logic to deal with a delta U
+// controller.
+class ZeroedStateFeedbackLoop {
+ public:
+  ZeroedStateFeedbackLoop(const char *name, ClawMotor *motor);
+
+  const static int kZeroingMaxVoltage = 5;
+
+  enum JointZeroingState {
+    // We don't know where the joint is at all.
+    UNKNOWN_POSITION,
+    // We have an approximate position for where the claw is using.
+    APPROXIMATE_CALIBRATION,
+    // We observed the calibration edge while disabled. This is good enough for
+    // autonomous mode.
+    DISABLED_CALIBRATION,
+    // Ready for use during teleop.
+    CALIBRATED
+  };
+
+  void set_zeroing_state(JointZeroingState zeroing_state) {
+    zeroing_state_ = zeroing_state;
+  }
+  JointZeroingState zeroing_state() const { return zeroing_state_; }
+
+  void SetPositionValues(const HalfClawPosition &claw);
+
+  void Reset(const HalfClawPosition &claw);
+
+  double absolute_position() const { return encoder() + offset(); }
+
+  const HallEffectTracker &front() const { return front_; }
+  const HallEffectTracker &calibration() const { return calibration_; }
+  const HallEffectTracker &back() const { return back_; }
+
+  bool any_hall_effect_changed() const {
+    return front().either_count_changed() ||
+           calibration().either_count_changed() ||
+           back().either_count_changed();
+  }
+  bool front_or_back_triggered() const {
+    return front().value() || back().value();
+  }
+  bool any_triggered() const {
+    return calibration().value() || front().value() || back().value();
+  }
+
+  double encoder() const { return encoder_; }
+  double last_encoder() const { return last_encoder_; }
+
+  double offset() const { return offset_; }
+
+  // Returns true if an edge was detected in the last cycle and then sets the
+  // edge_position to the absolute position of the edge.
+  bool GetPositionOfEdge(const constants::Values::Claws::Claw &claw,
+                         double *edge_encoder, double *edge_angle);
+
+  bool SawFilteredPosedge(const HallEffectTracker &this_sensor,
+                          const HallEffectTracker &sensorA,
+                          const HallEffectTracker &sensorB);
+
+  bool SawFilteredNegedge(const HallEffectTracker &this_sensor,
+                          const HallEffectTracker &sensorA,
+                          const HallEffectTracker &sensorB);
+
+#undef COUNT_SETTER_GETTER
+
+ protected:
+  // The accumulated voltage to apply to the motor.
+  double offset_;
+  const char *name_;
+
+  ClawMotor *motor_;
+
+  HallEffectTracker front_, calibration_, back_;
+
+  JointZeroingState zeroing_state_;
+  double min_hall_effect_on_angle_;
+  double max_hall_effect_on_angle_;
+  double min_hall_effect_off_angle_;
+  double max_hall_effect_off_angle_;
+  double encoder_;
+  double last_encoder_;
+  double last_on_encoder_;
+  double last_off_encoder_;
+  bool any_triggered_last_;
+
+  const HallEffectTracker* posedge_filter_ = nullptr;
+  const HallEffectTracker* negedge_filter_ = nullptr;
+
+ private:
+  // Does the edges of 1 sensor for GetPositionOfEdge.
+  bool DoGetPositionOfEdge(const constants::Values::Claws::AnglePair &angles,
+                           double *edge_encoder, double *edge_angle,
+                           const HallEffectTracker &sensor,
+                           const HallEffectTracker &sensorA,
+                           const HallEffectTracker &sensorB,
+                           const char *hall_effect_name);
+};
+
+class TopZeroedStateFeedbackLoop : public ZeroedStateFeedbackLoop {
+ public:
+  TopZeroedStateFeedbackLoop(ClawMotor *motor)
+      : ZeroedStateFeedbackLoop("top", motor) {}
+  // Sets the calibration offset given the absolute angle and the corresponding
+  // encoder value.
+  void SetCalibration(double edge_encoder, double edge_angle);
+
+  bool SetCalibrationOnEdge(const constants::Values::Claws::Claw &claw_values,
+                            JointZeroingState zeroing_state);
+  double ComputeCalibrationChange(double edge_encoder, double edge_angle);
+  void HandleCalibrationError(
+      const constants::Values::Claws::Claw &claw_values);
+};
+
+class BottomZeroedStateFeedbackLoop : public ZeroedStateFeedbackLoop {
+ public:
+  BottomZeroedStateFeedbackLoop(ClawMotor *motor)
+      : ZeroedStateFeedbackLoop("bottom", motor) {}
+  // Sets the calibration offset given the absolute angle and the corrisponding
+  // encoder value.
+  void SetCalibration(double edge_encoder, double edge_angle);
+
+  bool SetCalibrationOnEdge(const constants::Values::Claws::Claw &claw_values,
+                            JointZeroingState zeroing_state);
+  double ComputeCalibrationChange(double edge_encoder, double edge_angle);
+  void HandleCalibrationError(
+      const constants::Values::Claws::Claw &claw_values);
+};
+
+class ClawMotor : public aos::controls::ControlLoop<control_loops::ClawQueue> {
+ public:
+  explicit ClawMotor(control_loops::ClawQueue *my_claw =
+                         &control_loops::claw_queue);
+
+  // True if the state machine is ready.
+  bool capped_goal() const { return capped_goal_; }
+
+  double uncapped_average_voltage() const {
+    return claw_.uncapped_average_voltage();
+  }
+
+  // True if the claw is zeroing.
+  bool is_zeroing() const;
+
+  // True if the state machine is ready.
+  bool is_ready() const;
+
+  void ChangeTopOffset(double doffset);
+  void ChangeBottomOffset(double doffset);
+
+  enum CalibrationMode {
+    READY,
+    PREP_FINE_TUNE_TOP,
+    FINE_TUNE_TOP,
+    PREP_FINE_TUNE_BOTTOM,
+    FINE_TUNE_BOTTOM,
+    UNKNOWN_LOCATION
+  };
+
+  CalibrationMode mode() const { return mode_; }
+
+ protected:
+  virtual void RunIteration(const control_loops::ClawQueue::Goal *goal,
+                            const control_loops::ClawQueue::Position *position,
+                            control_loops::ClawQueue::Output *output,
+                            control_loops::ClawQueue::Status *status);
+
+  double top_absolute_position() const {
+    return claw_.X_hat(1, 0) + claw_.X_hat(0, 0);
+  }
+  double bottom_absolute_position() const { return claw_.X_hat(0, 0); }
+
+ private:
+  // Friend the test classes for acces to the internal state.
+  friend class testing::WindupClawTest;
+
+  // The zeroed joint to use.
+  bool has_top_claw_goal_;
+  double top_claw_goal_;
+  TopZeroedStateFeedbackLoop top_claw_;
+
+  bool has_bottom_claw_goal_;
+  double bottom_claw_goal_;
+  BottomZeroedStateFeedbackLoop bottom_claw_;
+
+  // The claw loop.
+  ClawLimitedLoop claw_;
+
+  bool was_enabled_;
+  bool doing_calibration_fine_tune_;
+
+  // The initial separation when disabled.  Used as the safe separation
+  // distance.
+  double initial_separation_;
+
+  bool capped_goal_;
+  CalibrationMode mode_;
+
+  DISALLOW_COPY_AND_ASSIGN(ClawMotor);
+};
+
+// Modifies the bottom and top goal such that they are within the limits and
+// their separation isn't too much or little.
+void LimitClawGoal(double *bottom_goal, double *top_goal,
+                   const frc971::constants::Values &values);
+
+}  // namespace control_loops
+}  // namespace frc971
+
+#endif  // Y2014_CONTROL_LOOPS_CLAW_CLAW_H_
diff --git a/y2014/control_loops/claw/claw.q b/y2014/control_loops/claw/claw.q
new file mode 100644
index 0000000..a116970
--- /dev/null
+++ b/y2014/control_loops/claw/claw.q
@@ -0,0 +1,75 @@
+package frc971.control_loops;
+
+import "aos/common/controls/control_loops.q";
+import "frc971/control_loops/control_loops.q";
+
+struct HalfClawPosition {
+  // The current position of this half of the claw.
+  double position;
+
+  // The hall effect sensor at the front limit.
+  HallEffectStruct front;
+  // The hall effect sensor in the middle to use for real calibration.
+  HallEffectStruct calibration;
+  // The hall effect at the back limit.
+  HallEffectStruct back;
+};
+
+// All angles here are 0 vertical, positive "up" (aka backwards).
+queue_group ClawQueue {
+  implements aos.control_loops.ControlLoop;
+
+  message Goal {
+    // The angle of the bottom claw.
+    double bottom_angle;
+    // How much higher the top claw is.
+    double separation_angle;
+    // top claw intake roller
+    double intake;
+    // bottom claw tusk centering
+    double centering;
+  };
+
+  message Position {
+    // All the top claw information.
+    HalfClawPosition top;
+    // All the bottom claw information.
+    HalfClawPosition bottom;
+  };
+
+  message Output {
+    double intake_voltage;
+    double top_claw_voltage;
+    double bottom_claw_voltage;
+    double tusk_voltage;
+  };
+
+  message Status {
+    // True if zeroed enough for the current period (autonomous or teleop).
+    bool zeroed;
+    // True if zeroed as much as we will force during autonomous.
+    bool zeroed_for_auto;
+    // True if zeroed and within tolerance for separation and bottom angle.
+    bool done;
+    // True if zeroed and within tolerance for separation and bottom angle.
+    // seperation allowance much wider as a ball may be included
+    bool done_with_ball;
+    // Dump the values of the state matrix.
+    double bottom;
+    double bottom_velocity;
+    double separation;
+    double separation_velocity;
+  };
+
+  queue Goal goal;
+  queue Position position;
+  queue Output output;
+  queue Status status;
+};
+
+queue_group ClawQueue claw_queue;
+
+struct ClawPositionToLog {
+	double top;
+	double bottom;
+};
diff --git a/y2014/control_loops/claw/claw_calibration.cc b/y2014/control_loops/claw/claw_calibration.cc
new file mode 100644
index 0000000..772a940
--- /dev/null
+++ b/y2014/control_loops/claw/claw_calibration.cc
@@ -0,0 +1,315 @@
+#include "y2014/control_loops/claw/claw.q.h"
+#include "frc971/control_loops/control_loops.q.h"
+
+#include "aos/linux_code/init.h"
+#include "y2014/constants.h"
+
+namespace frc971 {
+
+typedef constants::Values::Claws Claws;
+
+class Sensor {
+ public:
+  Sensor(const double start_position,
+         const HallEffectStruct &initial_hall_effect)
+      : start_position_(start_position),
+        last_hall_effect_(initial_hall_effect),
+        last_posedge_count_(initial_hall_effect.posedge_count),
+        last_negedge_count_(initial_hall_effect.negedge_count) {
+    last_on_min_position_ = start_position;
+    last_on_max_position_ = start_position;
+    last_off_min_position_ = start_position;
+    last_off_max_position_ = start_position;
+  }
+
+  bool DoGetPositionOfEdge(
+      const control_loops::HalfClawPosition &claw_position,
+      const HallEffectStruct &hall_effect, Claws::AnglePair *limits) {
+    bool print = false;
+
+    if (hall_effect.posedge_count != last_posedge_count_) {
+      const double avg_off_position =
+          (last_off_min_position_ + last_off_max_position_) / 2.0;
+      if (hall_effect.posedge_value < avg_off_position) {
+        printf("Posedge upper current %f posedge %f avg_off %f [%f, %f]\n",
+               claw_position.position, hall_effect.posedge_value,
+               avg_off_position, last_off_min_position_,
+               last_off_max_position_);
+        limits->upper_decreasing_angle =
+            hall_effect.posedge_value - start_position_;
+      } else {
+        printf("Posedge lower current %f posedge %f avg_off %f [%f, %f]\n",
+               claw_position.position, hall_effect.posedge_value,
+               avg_off_position, last_off_min_position_,
+               last_off_max_position_);
+        limits->lower_angle =
+            hall_effect.posedge_value - start_position_;
+      }
+      print = true;
+    }
+    if (hall_effect.negedge_count != last_negedge_count_) {
+      const double avg_on_position =
+          (last_on_min_position_ + last_on_max_position_) / 2.0;
+      if (hall_effect.negedge_value > avg_on_position) {
+        printf("Negedge upper current %f negedge %f last_on %f [%f, %f]\n",
+               claw_position.position, hall_effect.negedge_value,
+               avg_on_position, last_on_min_position_,
+               last_on_max_position_);
+        limits->upper_angle =
+            hall_effect.negedge_value - start_position_;
+      } else {
+        printf("Negedge lower current %f negedge %f last_on %f [%f, %f]\n",
+               claw_position.position, hall_effect.negedge_value,
+               avg_on_position, last_on_min_position_,
+               last_on_max_position_);
+        limits->lower_decreasing_angle =
+            hall_effect.negedge_value - start_position_;
+      }
+      print = true;
+    }
+
+    if (hall_effect.current) {
+      if (!last_hall_effect_.current) {
+        last_on_min_position_ = last_on_max_position_ = claw_position.position;
+      } else {
+        last_on_min_position_ =
+            ::std::min(claw_position.position, last_on_min_position_);
+        last_on_max_position_ =
+            ::std::max(claw_position.position, last_on_max_position_);
+      }
+    } else {
+      if (last_hall_effect_.current) {
+        last_off_min_position_ = last_off_max_position_ =
+            claw_position.position;
+      } else {
+        last_off_min_position_ =
+            ::std::min(claw_position.position, last_off_min_position_);
+        last_off_max_position_ =
+            ::std::max(claw_position.position, last_off_max_position_);
+      }
+    }
+
+    last_hall_effect_ = hall_effect;
+    last_posedge_count_ = hall_effect.posedge_count;
+    last_negedge_count_ = hall_effect.negedge_count;
+
+    return print;
+  }
+
+ private:
+  const double start_position_;
+  HallEffectStruct last_hall_effect_;
+  int32_t last_posedge_count_;
+  int32_t last_negedge_count_;
+  double last_on_min_position_;
+  double last_off_min_position_;
+  double last_on_max_position_;
+  double last_off_max_position_;
+};
+
+class ClawSensors {
+ public:
+  ClawSensors(const double start_position,
+              const control_loops::HalfClawPosition &initial_claw_position)
+      : start_position_(start_position),
+        front_(start_position, initial_claw_position.front),
+        calibration_(start_position, initial_claw_position.calibration),
+        back_(start_position, initial_claw_position.back) {}
+
+  bool GetPositionOfEdge(const control_loops::HalfClawPosition &claw_position,
+                         Claws::Claw *claw) {
+
+    bool print = false;
+    if (front_.DoGetPositionOfEdge(claw_position,
+                                   claw_position.front, &claw->front)) {
+      print = true;
+    } else if (calibration_.DoGetPositionOfEdge(claw_position,
+                                                claw_position.calibration,
+                                                &claw->calibration)) {
+      print = true;
+    } else if (back_.DoGetPositionOfEdge(claw_position,
+                                         claw_position.back, &claw->back)) {
+      print = true;
+    }
+
+    double position = claw_position.position - start_position_;
+
+    if (position > claw->upper_limit) {
+      claw->upper_hard_limit = claw->upper_limit = position;
+      print = true;
+    }
+    if (position < claw->lower_limit) {
+      claw->lower_hard_limit = claw->lower_limit = position;
+      print = true;
+    }
+    return print;
+  }
+
+ private:
+  const double start_position_;
+  Sensor front_;
+  Sensor calibration_;
+  Sensor back_;
+};
+
+int Main() {
+  control_loops::claw_queue.position.FetchNextBlocking();
+
+  const double top_start_position =
+      control_loops::claw_queue.position->top.position;
+  const double bottom_start_position =
+      control_loops::claw_queue.position->bottom.position;
+
+  ClawSensors top(top_start_position,
+                  control_loops::claw_queue.position->top);
+  ClawSensors bottom(bottom_start_position,
+                     control_loops::claw_queue.position->bottom);
+
+  Claws limits;
+
+  limits.claw_zeroing_off_speed = 0.5;
+  limits.claw_zeroing_speed = 0.1;
+  limits.claw_zeroing_separation = 0.1;
+
+  // claw separation that would be considered a collision
+  limits.claw_min_separation = 0.0;
+  limits.claw_max_separation = 0.0;
+
+  // We should never get closer/farther than these.
+  limits.soft_min_separation = 0.0;
+  limits.soft_max_separation = 0.0;
+
+  limits.upper_claw.lower_hard_limit = 0.0;
+  limits.upper_claw.upper_hard_limit = 0.0;
+  limits.upper_claw.lower_limit = 0.0;
+  limits.upper_claw.upper_limit = 0.0;
+  limits.upper_claw.front.lower_angle = 0.0;
+  limits.upper_claw.front.upper_angle = 0.0;
+  limits.upper_claw.front.lower_decreasing_angle = 0.0;
+  limits.upper_claw.front.upper_decreasing_angle = 0.0;
+  limits.upper_claw.calibration.lower_angle = 0.0;
+  limits.upper_claw.calibration.upper_angle = 0.0;
+  limits.upper_claw.calibration.lower_decreasing_angle = 0.0;
+  limits.upper_claw.calibration.upper_decreasing_angle = 0.0;
+  limits.upper_claw.back.lower_angle = 0.0;
+  limits.upper_claw.back.upper_angle = 0.0;
+  limits.upper_claw.back.lower_decreasing_angle = 0.0;
+  limits.upper_claw.back.upper_decreasing_angle = 0.0;
+
+  limits.lower_claw.lower_hard_limit = 0.0;
+  limits.lower_claw.upper_hard_limit = 0.0;
+  limits.lower_claw.lower_limit = 0.0;
+  limits.lower_claw.upper_limit = 0.0;
+  limits.lower_claw.front.lower_angle = 0.0;
+  limits.lower_claw.front.upper_angle = 0.0;
+  limits.lower_claw.front.lower_decreasing_angle = 0.0;
+  limits.lower_claw.front.upper_decreasing_angle = 0.0;
+  limits.lower_claw.calibration.lower_angle = 0.0;
+  limits.lower_claw.calibration.upper_angle = 0.0;
+  limits.lower_claw.calibration.lower_decreasing_angle = 0.0;
+  limits.lower_claw.calibration.upper_decreasing_angle = 0.0;
+  limits.lower_claw.back.lower_angle = 0.0;
+  limits.lower_claw.back.upper_angle = 0.0;
+  limits.lower_claw.back.lower_decreasing_angle = 0.0;
+  limits.lower_claw.back.upper_decreasing_angle = 0.0;
+
+  limits.claw_unimportant_epsilon = 0.01;
+  limits.start_fine_tune_pos = -0.2;
+  limits.max_zeroing_voltage = 4.0;
+
+  control_loops::ClawQueue::Position last_position =
+      *control_loops::claw_queue.position;
+
+  while (true) {
+    control_loops::claw_queue.position.FetchNextBlocking();
+    bool print = false;
+    if (top.GetPositionOfEdge(control_loops::claw_queue.position->top,
+                              &limits.upper_claw)) {
+      print = true;
+      printf("Got an edge on the upper claw\n");
+    }
+    if (bottom.GetPositionOfEdge(
+            control_loops::claw_queue.position->bottom,
+            &limits.lower_claw)) {
+      print = true;
+      printf("Got an edge on the lower claw\n");
+    }
+    const double top_position =
+        control_loops::claw_queue.position->top.position -
+        top_start_position;
+    const double bottom_position =
+        control_loops::claw_queue.position->bottom.position -
+        bottom_start_position;
+    const double separation = top_position - bottom_position;
+    if (separation > limits.claw_max_separation) {
+      limits.soft_max_separation = limits.claw_max_separation = separation;
+      print = true;
+    }
+    if (separation < limits.claw_min_separation) {
+      limits.soft_min_separation = limits.claw_min_separation = separation;
+      print = true;
+    }
+
+    if (print) {
+      printf("{%f,\n", limits.claw_zeroing_off_speed);
+      printf("%f,\n", limits.claw_zeroing_speed);
+      printf("%f,\n", limits.claw_zeroing_separation);
+      printf("%f,\n", limits.claw_min_separation);
+      printf("%f,\n", limits.claw_max_separation);
+      printf("%f,\n", limits.soft_min_separation);
+      printf("%f,\n", limits.soft_max_separation);
+      printf(
+          "{%f, %f, %f, %f, {%f, %f, %f, %f}, {%f, %f, %f, %f}, {%f, %f, %f, "
+          "%f}},\n",
+          limits.upper_claw.lower_hard_limit,
+          limits.upper_claw.upper_hard_limit, limits.upper_claw.lower_limit,
+          limits.upper_claw.upper_limit, limits.upper_claw.front.lower_angle,
+          limits.upper_claw.front.upper_angle,
+          limits.upper_claw.front.lower_decreasing_angle,
+          limits.upper_claw.front.upper_decreasing_angle,
+          limits.upper_claw.calibration.lower_angle,
+          limits.upper_claw.calibration.upper_angle,
+          limits.upper_claw.calibration.lower_decreasing_angle,
+          limits.upper_claw.calibration.upper_decreasing_angle,
+          limits.upper_claw.back.lower_angle,
+          limits.upper_claw.back.upper_angle,
+          limits.upper_claw.back.lower_decreasing_angle,
+          limits.upper_claw.back.upper_decreasing_angle);
+
+      printf(
+          "{%f, %f, %f, %f, {%f, %f, %f, %f}, {%f, %f, %f, %f}, {%f, %f, %f, "
+          "%f}},\n",
+          limits.lower_claw.lower_hard_limit,
+          limits.lower_claw.upper_hard_limit, limits.lower_claw.lower_limit,
+          limits.lower_claw.upper_limit, limits.lower_claw.front.lower_angle,
+          limits.lower_claw.front.upper_angle,
+          limits.lower_claw.front.lower_decreasing_angle,
+          limits.lower_claw.front.upper_decreasing_angle,
+          limits.lower_claw.calibration.lower_angle,
+          limits.lower_claw.calibration.upper_angle,
+          limits.lower_claw.calibration.lower_decreasing_angle,
+          limits.lower_claw.calibration.upper_decreasing_angle,
+          limits.lower_claw.back.lower_angle,
+          limits.lower_claw.back.upper_angle,
+          limits.lower_claw.back.lower_decreasing_angle,
+          limits.lower_claw.back.upper_decreasing_angle);
+      printf("%f,  // claw_unimportant_epsilon\n",
+             limits.claw_unimportant_epsilon);
+      printf("%f,   // start_fine_tune_pos\n", limits.start_fine_tune_pos);
+      printf("%f,\n", limits.max_zeroing_voltage);
+      printf("}\n");
+    }
+
+    last_position = *control_loops::claw_queue.position;
+  }
+  return 0;
+}
+
+}  // namespace frc971
+
+int main() {
+  ::aos::Init();
+  int returnvalue = ::frc971::Main();
+  ::aos::Cleanup();
+  return returnvalue;
+}
diff --git a/y2014/control_loops/claw/claw_lib_test.cc b/y2014/control_loops/claw/claw_lib_test.cc
new file mode 100644
index 0000000..9eb173e
--- /dev/null
+++ b/y2014/control_loops/claw/claw_lib_test.cc
@@ -0,0 +1,608 @@
+#include <unistd.h>
+
+#include <memory>
+
+#include "aos/common/network/team_number.h"
+#include "aos/common/controls/control_loop_test.h"
+
+#include "y2014/control_loops/claw/claw.q.h"
+#include "y2014/control_loops/claw/claw.h"
+#include "y2014/constants.h"
+#include "y2014/control_loops/claw/claw_motor_plant.h"
+
+#include "gtest/gtest.h"
+
+
+namespace frc971 {
+namespace control_loops {
+namespace testing {
+
+typedef enum {
+	TOP_CLAW = 0,
+	BOTTOM_CLAW,
+
+	CLAW_COUNT
+} ClawType;
+
+class TeamNumberEnvironment : public ::testing::Environment {
+ public:
+  // Override this to define how to set up the environment.
+  virtual void SetUp() { aos::network::OverrideTeamNumber(1); }
+};
+
+::testing::Environment* const team_number_env =
+    ::testing::AddGlobalTestEnvironment(new TeamNumberEnvironment);
+
+// Class which simulates the wrist and sends out queue messages containing the
+// position.
+class ClawMotorSimulation {
+ public:
+  // Constructs a motor simulation.  initial_position is the inital angle of the
+  // wrist, which will be treated as 0 by the encoder.
+  ClawMotorSimulation(double initial_top_position,
+                      double initial_bottom_position)
+      : claw_plant_(new StateFeedbackPlant<4, 2, 2>(MakeClawPlant())),
+        claw_queue(".frc971.control_loops.claw_queue", 0x9f1a99dd,
+                   ".frc971.control_loops.claw_queue.goal",
+                   ".frc971.control_loops.claw_queue.position",
+                   ".frc971.control_loops.claw_queue.output",
+                   ".frc971.control_loops.claw_queue.status") {
+    Reinitialize(initial_top_position, initial_bottom_position);
+  }
+
+  void Reinitialize(double initial_top_position,
+                    double initial_bottom_position) {
+    LOG(INFO, "Reinitializing to {top: %f, bottom: %f}\n", initial_top_position,
+        initial_bottom_position);
+    claw_plant_->mutable_X(0, 0) = initial_bottom_position;
+    claw_plant_->mutable_X(1, 0) = initial_top_position - initial_bottom_position;
+    claw_plant_->mutable_X(2, 0) = 0.0;
+    claw_plant_->mutable_X(3, 0) = 0.0;
+    claw_plant_->mutable_Y() = claw_plant_->C() * claw_plant_->X();
+
+    ReinitializePartial(TOP_CLAW, initial_top_position);
+    ReinitializePartial(BOTTOM_CLAW, initial_bottom_position);
+    last_position_.Zero();
+    SetPhysicalSensors(&last_position_);
+  }
+
+  // Returns the absolute angle of the wrist.
+  double GetAbsolutePosition(ClawType type) const {
+    if (type == TOP_CLAW) {
+      return claw_plant_->Y(1, 0);
+    } else {
+      return claw_plant_->Y(0, 0);
+    }
+  }
+
+  // Returns the adjusted angle of the wrist.
+  double GetPosition(ClawType type) const {
+    return GetAbsolutePosition(type) - initial_position_[type];
+  }
+
+  // Makes sure pos is inside range (exclusive)
+  bool CheckRange(double pos, const constants::Values::Claws::AnglePair &pair) {
+    // Note: If the >= and <= signs are used, then the there exists a case
+    // where the wrist starts precisely on the edge and because initial
+    // position and the *edge_value_ are the same, then the comparison
+    // in ZeroedStateFeedbackLoop::DoGetPositionOfEdge will return that
+    // the lower, rather than upper, edge of the hall effect was passed.
+    return (pos > pair.lower_angle && pos < pair.upper_angle);
+  }
+
+  void SetHallEffect(double pos,
+                     const constants::Values::Claws::AnglePair &pair,
+                     HallEffectStruct *hall_effect) {
+    hall_effect->current = CheckRange(pos, pair);
+  }
+
+  void SetClawHallEffects(double pos,
+                          const constants::Values::Claws::Claw &claw,
+                          control_loops::HalfClawPosition *half_claw) {
+    SetHallEffect(pos, claw.front, &half_claw->front);
+    SetHallEffect(pos, claw.calibration, &half_claw->calibration);
+    SetHallEffect(pos, claw.back, &half_claw->back);
+  }
+
+  // Sets the values of the physical sensors that can be directly observed
+  // (encoder, hall effect).
+  void SetPhysicalSensors(control_loops::ClawQueue::Position *position) {
+    position->top.position = GetPosition(TOP_CLAW);
+    position->bottom.position = GetPosition(BOTTOM_CLAW);
+
+    double pos[2] = {GetAbsolutePosition(TOP_CLAW),
+                     GetAbsolutePosition(BOTTOM_CLAW)};
+    LOG(DEBUG, "Physical claws are at {top: %f, bottom: %f}\n", pos[TOP_CLAW],
+        pos[BOTTOM_CLAW]);
+
+    const frc971::constants::Values& values = constants::GetValues();
+
+    // Signal that each hall effect sensor has been triggered if it is within
+    // the correct range.
+    SetClawHallEffects(pos[TOP_CLAW], values.claw.upper_claw, &position->top);
+    SetClawHallEffects(pos[BOTTOM_CLAW], values.claw.lower_claw,
+                       &position->bottom);
+  }
+
+  void UpdateHallEffect(double angle,
+                        double last_angle,
+                        double initial_position,
+                        HallEffectStruct *position,
+                        const HallEffectStruct &last_position,
+                        const constants::Values::Claws::AnglePair &pair,
+                        const char *claw_name, const char *hall_effect_name) {
+    if (position->current && !last_position.current) {
+      ++position->posedge_count;
+
+      if (last_angle < pair.lower_angle) {
+        LOG(DEBUG, "%s: Positive lower edge on %s hall effect\n", claw_name,
+            hall_effect_name);
+        position->posedge_value = pair.lower_angle - initial_position;
+      } else {
+        LOG(DEBUG, "%s: Positive upper edge on %s hall effect\n", claw_name,
+            hall_effect_name);
+        position->posedge_value = pair.upper_angle - initial_position;
+      }
+    }
+    if (!position->current && last_position.current) {
+      ++position->negedge_count;
+
+      if (angle < pair.lower_angle) {
+        LOG(DEBUG, "%s: Negative lower edge on %s hall effect\n", claw_name,
+            hall_effect_name);
+        position->negedge_value = pair.lower_angle - initial_position;
+      } else {
+        LOG(DEBUG, "%s: Negative upper edge on %s hall effect\n", claw_name,
+            hall_effect_name);
+        position->negedge_value = pair.upper_angle - initial_position;
+      }
+    }
+  }
+
+  void UpdateClawHallEffects(
+      control_loops::HalfClawPosition *position,
+      const control_loops::HalfClawPosition &last_position,
+      const constants::Values::Claws::Claw &claw, double initial_position,
+      const char *claw_name) {
+    UpdateHallEffect(position->position + initial_position,
+                     last_position.position + initial_position,
+                     initial_position, &position->front, last_position.front,
+                     claw.front, claw_name, "front");
+    UpdateHallEffect(position->position + initial_position,
+                     last_position.position + initial_position,
+                     initial_position, &position->calibration,
+                     last_position.calibration, claw.calibration, claw_name,
+                     "calibration");
+    UpdateHallEffect(position->position + initial_position,
+                     last_position.position + initial_position,
+                     initial_position, &position->back, last_position.back,
+                     claw.back, claw_name, "back");
+  }
+
+  // Sends out the position queue messages.
+  void SendPositionMessage() {
+    ::aos::ScopedMessagePtr<control_loops::ClawQueue::Position> position =
+        claw_queue.position.MakeMessage();
+
+    // Initialize all the counters to their previous values.
+    *position = last_position_;
+
+    SetPhysicalSensors(position.get());
+
+    const frc971::constants::Values& values = constants::GetValues();
+
+    UpdateClawHallEffects(&position->top, last_position_.top,
+                          values.claw.upper_claw, initial_position_[TOP_CLAW],
+                          "Top");
+    UpdateClawHallEffects(&position->bottom, last_position_.bottom,
+                          values.claw.lower_claw,
+                          initial_position_[BOTTOM_CLAW], "Bottom");
+
+    // Only set calibration if it changed last cycle.  Calibration starts out
+    // with a value of 0.
+    last_position_ = *position;
+    position.Send();
+  }
+
+  // Simulates the claw moving for one timestep.
+  void Simulate() {
+    const frc971::constants::Values& v = constants::GetValues();
+    EXPECT_TRUE(claw_queue.output.FetchLatest());
+
+    claw_plant_->mutable_U() << claw_queue.output->bottom_claw_voltage,
+        claw_queue.output->top_claw_voltage;
+    claw_plant_->Update();
+
+    // Check that the claw is within the limits.
+    EXPECT_GE(v.claw.upper_claw.upper_limit, claw_plant_->Y(0, 0));
+    EXPECT_LE(v.claw.upper_claw.lower_hard_limit, claw_plant_->Y(0, 0));
+
+    EXPECT_GE(v.claw.lower_claw.upper_hard_limit, claw_plant_->Y(1, 0));
+    EXPECT_LE(v.claw.lower_claw.lower_hard_limit, claw_plant_->Y(1, 0));
+
+    EXPECT_LE(claw_plant_->Y(1, 0) - claw_plant_->Y(0, 0),
+              v.claw.claw_max_separation);
+    EXPECT_GE(claw_plant_->Y(1, 0) - claw_plant_->Y(0, 0),
+              v.claw.claw_min_separation);
+  }
+  // The whole claw.
+  ::std::unique_ptr<StateFeedbackPlant<4, 2, 2>> claw_plant_;
+
+ private:
+  // Resets the plant so that it starts at initial_position.
+  void ReinitializePartial(ClawType type, double initial_position) {
+    initial_position_[type] = initial_position;
+  }
+
+  ClawQueue claw_queue;
+  double initial_position_[CLAW_COUNT];
+
+  control_loops::ClawQueue::Position last_position_;
+};
+
+
+class ClawTest : public ::aos::testing::ControlLoopTest {
+ protected:
+  // Create a new instance of the test queue so that it invalidates the queue
+  // that it points to.  Otherwise, we will have a pointer to shared memory that
+  // is no longer valid.
+  ClawQueue claw_queue;
+
+  // Create a loop and simulation plant.
+  ClawMotor claw_motor_;
+  ClawMotorSimulation claw_motor_plant_;
+
+  // Minimum amount of acceptable separation between the top and bottom of the
+  // claw.
+  double min_separation_;
+
+  ClawTest()
+      : claw_queue(".frc971.control_loops.claw_queue", 0x9f1a99dd,
+                   ".frc971.control_loops.claw_queue.goal",
+                   ".frc971.control_loops.claw_queue.position",
+                   ".frc971.control_loops.claw_queue.output",
+                   ".frc971.control_loops.claw_queue.status"),
+        claw_motor_(&claw_queue),
+        claw_motor_plant_(0.4, 0.2),
+        min_separation_(constants::GetValues().claw.claw_min_separation) {}
+
+  void VerifyNearGoal() {
+    claw_queue.goal.FetchLatest();
+    claw_queue.position.FetchLatest();
+    double bottom = claw_motor_plant_.GetAbsolutePosition(BOTTOM_CLAW);
+    double separation =
+        claw_motor_plant_.GetAbsolutePosition(TOP_CLAW) - bottom;
+    EXPECT_NEAR(claw_queue.goal->bottom_angle, bottom, 1e-4);
+    EXPECT_NEAR(claw_queue.goal->separation_angle, separation, 1e-4);
+    EXPECT_LE(min_separation_, separation);
+  }
+};
+
+TEST_F(ClawTest, HandlesNAN) {
+  claw_queue.goal.MakeWithBuilder()
+      .bottom_angle(::std::nan(""))
+      .separation_angle(::std::nan(""))
+      .Send();
+  for (int i = 0; i < 500; ++i) {
+    claw_motor_plant_.SendPositionMessage();
+    claw_motor_.Iterate();
+    claw_motor_plant_.Simulate();
+    SimulateTimestep(true);
+  }
+}
+
+// Tests that the wrist zeros correctly and goes to a position.
+TEST_F(ClawTest, ZerosCorrectly) {
+  claw_queue.goal.MakeWithBuilder()
+      .bottom_angle(0.1)
+      .separation_angle(0.2)
+      .Send();
+  for (int i = 0; i < 500; ++i) {
+    claw_motor_plant_.SendPositionMessage();
+    claw_motor_.Iterate();
+    claw_motor_plant_.Simulate();
+    SimulateTimestep(true);
+  }
+  VerifyNearGoal();
+}
+
+// Tests that the wrist zeros correctly and goes to a position.
+TEST_F(ClawTest, LimitClawGoal) {
+  frc971::constants::Values values;
+  values.claw.claw_min_separation = -2.0;
+  values.claw.claw_max_separation = 1.0;
+  values.claw.soft_min_separation = -2.0;
+  values.claw.soft_max_separation = 1.0;
+  values.claw.upper_claw.lower_limit = -5.0;
+  values.claw.upper_claw.upper_limit = 7.5;
+  values.claw.lower_claw.lower_limit = -5.5;
+  values.claw.lower_claw.upper_limit = 8.0;
+
+  double bottom_goal = 0.0;
+  double top_goal = 0.0;
+
+  LimitClawGoal(&bottom_goal, &top_goal, values);
+  EXPECT_NEAR(0.0, bottom_goal, 1e-4);
+  EXPECT_NEAR(0.0, top_goal, 1e-4);
+
+  bottom_goal = 0.0;
+  top_goal = -4.0;
+
+  LimitClawGoal(&bottom_goal, &top_goal, values);
+  EXPECT_NEAR(-1.0, bottom_goal, 1e-4);
+  EXPECT_NEAR(-3.0, top_goal, 1e-4);
+
+  bottom_goal = 0.0;
+  top_goal = 4.0;
+
+  LimitClawGoal(&bottom_goal, &top_goal, values);
+  EXPECT_NEAR(1.5, bottom_goal, 1e-4);
+  EXPECT_NEAR(2.5, top_goal, 1e-4);
+
+  bottom_goal = -10.0;
+  top_goal = -9.5;
+
+  LimitClawGoal(&bottom_goal, &top_goal, values);
+  EXPECT_NEAR(-5.5, bottom_goal, 1e-4);
+  EXPECT_NEAR(-5.0, top_goal, 1e-4);
+
+  bottom_goal = -20.0;
+  top_goal = -4.0;
+
+  LimitClawGoal(&bottom_goal, &top_goal, values);
+  EXPECT_NEAR(-5.5, bottom_goal, 1e-4);
+  EXPECT_NEAR(-4.5, top_goal, 1e-4);
+
+  bottom_goal = -20.0;
+  top_goal = -4.0;
+
+  LimitClawGoal(&bottom_goal, &top_goal, values);
+  EXPECT_NEAR(-5.5, bottom_goal, 1e-4);
+  EXPECT_NEAR(-4.5, top_goal, 1e-4);
+
+  bottom_goal = -5.0;
+  top_goal = -10.0;
+
+  LimitClawGoal(&bottom_goal, &top_goal, values);
+  EXPECT_NEAR(-3.0, bottom_goal, 1e-4);
+  EXPECT_NEAR(-5.0, top_goal, 1e-4);
+
+  bottom_goal = 10.0;
+  top_goal = 9.0;
+
+  LimitClawGoal(&bottom_goal, &top_goal, values);
+  EXPECT_NEAR(8.0, bottom_goal, 1e-4);
+  EXPECT_NEAR(7.0, top_goal, 1e-4);
+
+  bottom_goal = 8.0;
+  top_goal = 9.0;
+
+  LimitClawGoal(&bottom_goal, &top_goal, values);
+  EXPECT_NEAR(6.5, bottom_goal, 1e-4);
+  EXPECT_NEAR(7.5, top_goal, 1e-4);
+}
+
+
+class ZeroingClawTest
+    : public ClawTest,
+      public ::testing::WithParamInterface< ::std::pair<double, double>> {};
+
+// Tests that the wrist zeros correctly starting on the hall effect sensor.
+TEST_P(ZeroingClawTest, ParameterizedZero) {
+  claw_motor_plant_.Reinitialize(GetParam().first, GetParam().second);
+
+  claw_queue.goal.MakeWithBuilder()
+      .bottom_angle(0.1)
+      .separation_angle(0.2)
+      .Send();
+  for (int i = 0; i < 700; ++i) {
+    claw_motor_plant_.SendPositionMessage();
+    claw_motor_.Iterate();
+    claw_motor_plant_.Simulate();
+
+    SimulateTimestep(true);
+  }
+  VerifyNearGoal();
+}
+
+INSTANTIATE_TEST_CASE_P(ZeroingClawTest, ZeroingClawTest,
+                        ::testing::Values(::std::make_pair(0.04, 0.02),
+                                          ::std::make_pair(0.2, 0.1),
+                                          ::std::make_pair(0.3, 0.2),
+                                          ::std::make_pair(0.4, 0.3),
+                                          ::std::make_pair(0.5, 0.4),
+                                          ::std::make_pair(0.6, 0.5),
+                                          ::std::make_pair(0.7, 0.6),
+                                          ::std::make_pair(0.8, 0.7),
+                                          ::std::make_pair(0.9, 0.8),
+                                          ::std::make_pair(1.0, 0.9),
+                                          ::std::make_pair(1.1, 1.0),
+                                          ::std::make_pair(1.15, 1.05),
+                                          ::std::make_pair(1.05, 0.95),
+                                          ::std::make_pair(1.2, 1.1),
+                                          ::std::make_pair(1.3, 1.2),
+                                          ::std::make_pair(1.4, 1.3),
+                                          ::std::make_pair(1.5, 1.4),
+                                          ::std::make_pair(1.6, 1.5),
+                                          ::std::make_pair(1.7, 1.6),
+                                          ::std::make_pair(1.8, 1.7),
+                                          ::std::make_pair(2.015, 2.01)
+));
+
+/*
+// Tests that loosing the encoder for a second triggers a re-zero.
+TEST_F(ClawTest, RezeroWithMissingPos) {
+  claw_queue.goal.MakeWithBuilder()
+      .bottom_angle(0.1)
+      .separation_angle(0.2)
+      .Send();
+  for (int i = 0; i < 800; ++i) {
+    // After 3 seconds, simulate the encoder going missing.
+    // This should trigger a re-zero.  To make sure it works, change the goal as
+    // well.
+    if (i < 300 || i > 400) {
+      claw_motor_plant_.SendPositionMessage();
+    } else {
+      if (i > 310) {
+        // Should be re-zeroing now.
+        EXPECT_TRUE(claw_motor_.is_uninitialized());
+      }
+      claw_queue.goal.MakeWithBuilder()
+          .bottom_angle(0.2)
+          .separation_angle(0.2)
+          .Send();
+    }
+    if (i == 410) {
+      EXPECT_TRUE(claw_motor_.is_zeroing());
+      // TODO(austin): Expose if the top and bototm is zeroing through
+      // functions.
+      // EXPECT_TRUE(bottom_claw_motor_.is_zeroing());
+    }
+
+    claw_motor_.Iterate();
+    claw_motor_plant_.Simulate();
+    SimulateTimestep(true);
+  }
+  VerifyNearGoal();
+}
+
+// Tests that disabling while zeroing sends the state machine into the
+// uninitialized state.
+TEST_F(ClawTest, DisableGoesUninitialized) {
+  claw_queue.goal.MakeWithBuilder()
+      .bottom_angle(0.1)
+      .separation_angle(0.2)
+      .Send();
+  for (int i = 0; i < 800; ++i) {
+    claw_motor_plant_.SendPositionMessage();
+    // After 0.5 seconds, disable the robot.
+    if (i > 50 && i < 200) {
+      SimulateTimestep(false);
+      if (i > 100) {
+        // Give the loop a couple cycled to get the message and then verify that
+        // it is in the correct state.
+        EXPECT_TRUE(claw_motor_.is_uninitialized());
+        // When disabled, we should be applying 0 power.
+        EXPECT_TRUE(claw_queue.output.FetchLatest());
+        EXPECT_EQ(0, claw_queue.output->top_claw_voltage);
+        EXPECT_EQ(0, claw_queue.output->bottom_claw_voltage);
+      }
+    } else {
+      SimulateTimestep(true);
+    }
+    if (i == 202) {
+      // Verify that we are zeroing after the bot gets enabled again.
+      EXPECT_TRUE(wrist_motor_.is_zeroing());
+      // TODO(austin): Expose if the top and bottom is zeroing through
+      // functions.
+    }
+
+    claw_motor_.Iterate();
+    claw_motor_plant_.Simulate();
+  }
+  VerifyNearGoal();
+}
+*/
+
+class WindupClawTest : public ClawTest {
+ protected:
+  void TestWindup(ClawMotor::CalibrationMode mode, int start_time, double offset) {
+    int capped_count = 0;
+    const frc971::constants::Values& values = constants::GetValues();
+    bool kicked = false;
+    bool measured = false;
+    for (int i = 0; i < 700; ++i) {
+      claw_motor_plant_.SendPositionMessage();
+      if (i >= start_time && mode == claw_motor_.mode() && !kicked) {
+        EXPECT_EQ(mode, claw_motor_.mode());
+        // Move the zeroing position far away and verify that it gets moved
+        // back.
+        claw_motor_.top_claw_goal_ += offset;
+        claw_motor_.bottom_claw_goal_ += offset;
+        kicked = true;
+      } else {
+        if (kicked && !measured) {
+          measured = true;
+          EXPECT_EQ(mode, claw_motor_.mode());
+
+          Eigen::Matrix<double, 4, 1> R;
+          R << claw_motor_.bottom_claw_goal_,
+              claw_motor_.top_claw_goal_ - claw_motor_.bottom_claw_goal_, 0.0,
+              0.0;
+          Eigen::Matrix<double, 2, 1> uncapped_voltage =
+              claw_motor_.claw_.K() * (R - claw_motor_.claw_.X_hat());
+          // Use a factor of 1.8 because so long as it isn't actually running
+          // away, the CapU function will deal with getting the actual output
+          // down.
+          EXPECT_LT(::std::abs(uncapped_voltage(0, 0)),
+                    values.claw.max_zeroing_voltage * 1.8);
+          EXPECT_LT(::std::abs(uncapped_voltage(1, 0)),
+                    values.claw.max_zeroing_voltage * 1.8);
+        }
+      }
+      if (claw_motor_.mode() == mode) {
+        if (claw_motor_.capped_goal()) {
+          ++capped_count;
+          // The cycle after we kick the zero position is the only cycle during
+          // which we should expect to see a high uncapped power during zeroing.
+          ASSERT_LT(values.claw.max_zeroing_voltage,
+                    ::std::abs(claw_motor_.uncapped_average_voltage()));
+        } else {
+          ASSERT_GT(values.claw.max_zeroing_voltage,
+                    ::std::abs(claw_motor_.uncapped_average_voltage()));
+        }
+      }
+
+      claw_motor_.Iterate();
+      claw_motor_plant_.Simulate();
+      SimulateTimestep(true);
+    }
+    EXPECT_TRUE(kicked);
+    EXPECT_TRUE(measured);
+    EXPECT_LE(1, capped_count);
+    EXPECT_GE(3, capped_count);
+  }
+};
+
+// Tests that the wrist can't get too far away from the zeroing position if the
+// zeroing position is saturating the goal.
+TEST_F(WindupClawTest, NoWindupPositive) {
+  claw_queue.goal.MakeWithBuilder()
+      .bottom_angle(0.1)
+      .separation_angle(0.2)
+      .Send();
+
+  TestWindup(ClawMotor::UNKNOWN_LOCATION, 100, 971.0);
+
+  VerifyNearGoal();
+}
+
+// Tests that the wrist can't get too far away from the zeroing position if the
+// zeroing position is saturating the goal.
+TEST_F(WindupClawTest, NoWindupNegative) {
+  claw_queue.goal.MakeWithBuilder()
+      .bottom_angle(0.1)
+      .separation_angle(0.2)
+      .Send();
+
+  TestWindup(ClawMotor::UNKNOWN_LOCATION, 100, -971.0);
+
+  VerifyNearGoal();
+}
+
+// Tests that the wrist can't get too far away from the zeroing position if the
+// zeroing position is saturating the goal.
+TEST_F(WindupClawTest, NoWindupNegativeFineTune) {
+  claw_queue.goal.MakeWithBuilder()
+      .bottom_angle(0.1)
+      .separation_angle(0.2)
+      .Send();
+
+  TestWindup(ClawMotor::FINE_TUNE_BOTTOM, 200, -971.0);
+
+  VerifyNearGoal();
+}
+
+}  // namespace testing
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/y2014/control_loops/claw/claw_main.cc b/y2014/control_loops/claw/claw_main.cc
new file mode 100644
index 0000000..e573d6f
--- /dev/null
+++ b/y2014/control_loops/claw/claw_main.cc
@@ -0,0 +1,11 @@
+#include "y2014/control_loops/claw/claw.h"
+
+#include "aos/linux_code/init.h"
+
+int main() {
+  ::aos::Init();
+  frc971::control_loops::ClawMotor claw;
+  claw.Run();
+  ::aos::Cleanup();
+  return 0;
+}
diff --git a/y2014/control_loops/claw/claw_motor_plant.cc b/y2014/control_loops/claw/claw_motor_plant.cc
new file mode 100644
index 0000000..acba8d0
--- /dev/null
+++ b/y2014/control_loops/claw/claw_motor_plant.cc
@@ -0,0 +1,49 @@
+#include "y2014/control_loops/claw/claw_motor_plant.h"
+
+#include <vector>
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace frc971 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeClawPlantCoefficients() {
+  Eigen::Matrix<double, 4, 4> A;
+  A << 1.0, 0.0, 0.00909331035298, 0.0, 0.0, 1.0, -6.04514323962e-05, 0.00903285892058, 0.0, 0.0, 0.824315642255, 0.0, 0.0, 0.0, -0.0112975266368, 0.813018115618;
+  Eigen::Matrix<double, 4, 2> B;
+  B << 0.000352527133889, 0.0, -0.000352527133889, 0.000376031064118, 0.0683072794628, 0.0, -0.0683072794628, 0.0726998350615;
+  Eigen::Matrix<double, 2, 4> C;
+  C << 1, 0, 0, 0, 1, 1, 0, 0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0, 0, 0, 0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<4, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackController<4, 2, 2> MakeClawController() {
+  Eigen::Matrix<double, 4, 2> L;
+  L << 1.72431564225, 2.70472958703e-16, -1.72431564225, 1.71301811562, 65.9456997026, 1.03478906105e-14, -65.9456997026, 64.4642687194;
+  Eigen::Matrix<double, 2, 4> K;
+  K << 106.138028875, 0.0, 4.20012492658, 0.0, 99.5038407367, 99.7251230882, 3.77683310096, 3.78980738032;
+  Eigen::Matrix<double, 4, 4> A_inv;
+  A_inv << 1.0, 0.0, -0.0110313451387, 0.0, 0.0, 1.0, -7.89348747778e-05, -0.0111102800135, 0.0, 0.0, 1.21312753118, 0.0, 0.0, 0.0, 0.016857361889, 1.22998489307;
+  return StateFeedbackController<4, 2, 2>(L, K, A_inv, MakeClawPlantCoefficients());
+}
+
+StateFeedbackPlant<4, 2, 2> MakeClawPlant() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackPlantCoefficients<4, 2, 2>>> plants(1);
+  plants[0] = ::std::unique_ptr<StateFeedbackPlantCoefficients<4, 2, 2>>(new StateFeedbackPlantCoefficients<4, 2, 2>(MakeClawPlantCoefficients()));
+  return StateFeedbackPlant<4, 2, 2>(&plants);
+}
+
+StateFeedbackLoop<4, 2, 2> MakeClawLoop() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackController<4, 2, 2>>> controllers(1);
+  controllers[0] = ::std::unique_ptr<StateFeedbackController<4, 2, 2>>(new StateFeedbackController<4, 2, 2>(MakeClawController()));
+  return StateFeedbackLoop<4, 2, 2>(&controllers);
+}
+
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/y2014/control_loops/claw/claw_motor_plant.h b/y2014/control_loops/claw/claw_motor_plant.h
new file mode 100644
index 0000000..c7de33a
--- /dev/null
+++ b/y2014/control_loops/claw/claw_motor_plant.h
@@ -0,0 +1,22 @@
+#ifndef Y2014_CONTROL_LOOPS_CLAW_CLAW_MOTOR_PLANT_H_
+#define Y2014_CONTROL_LOOPS_CLAW_CLAW_MOTOR_PLANT_H_
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace frc971 {
+namespace control_loops {
+static constexpr double kClawMomentOfInertiaRatio = 0.933333;
+
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeClawPlantCoefficients();
+
+StateFeedbackController<4, 2, 2> MakeClawController();
+
+StateFeedbackPlant<4, 2, 2> MakeClawPlant();
+
+StateFeedbackLoop<4, 2, 2> MakeClawLoop();
+
+}  // namespace control_loops
+}  // namespace frc971
+
+#endif  // Y2014_CONTROL_LOOPS_CLAW_CLAW_MOTOR_PLANT_H_
diff --git a/y2014/control_loops/claw/replay_claw.cc b/y2014/control_loops/claw/replay_claw.cc
new file mode 100644
index 0000000..70d881c
--- /dev/null
+++ b/y2014/control_loops/claw/replay_claw.cc
@@ -0,0 +1,24 @@
+#include "aos/common/controls/replay_control_loop.h"
+#include "aos/linux_code/init.h"
+
+#include "y2014/control_loops/claw/claw.q.h"
+
+// Reads one or more log files and sends out all the queue messages (in the
+// correct order and at the correct time) to feed a "live" claw process.
+
+int main(int argc, char **argv) {
+  if (argc <= 1) {
+    fprintf(stderr, "Need at least one file to replay!\n");
+    return EXIT_FAILURE;
+  }
+
+  ::aos::InitNRT();
+
+  ::aos::controls::ControlLoopReplayer<::frc971::control_loops::ClawQueue>
+      replayer(&::frc971::control_loops::claw_queue, "claw");
+  for (int i = 1; i < argc; ++i) {
+    replayer.ProcessFile(argv[i]);
+  }
+
+  ::aos::Cleanup();
+}
diff --git a/y2014/control_loops/drivetrain/drivetrain.cc b/y2014/control_loops/drivetrain/drivetrain.cc
new file mode 100644
index 0000000..ecb8ed2
--- /dev/null
+++ b/y2014/control_loops/drivetrain/drivetrain.cc
@@ -0,0 +1,775 @@
+#include "y2014/control_loops/drivetrain/drivetrain.h"
+
+#include <stdio.h>
+#include <sched.h>
+#include <cmath>
+#include <memory>
+#include "Eigen/Dense"
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/controls/polytope.h"
+#include "aos/common/commonmath.h"
+#include "aos/common/logging/queue_logging.h"
+#include "aos/common/logging/matrix_logging.h"
+
+#include "y2014/constants.h"
+#include "frc971/control_loops/state_feedback_loop.h"
+#include "frc971/control_loops/coerce_goal.h"
+#include "y2014/control_loops/drivetrain/polydrivetrain_cim_plant.h"
+#include "y2014/control_loops/drivetrain/drivetrain.q.h"
+#include "frc971/queues/gyro.q.h"
+#include "frc971/shifter_hall_effect.h"
+
+// A consistent way to mark code that goes away without shifters. It's still
+// here because we will have shifters again in the future.
+#define HAVE_SHIFTERS 1
+
+using frc971::sensors::gyro_reading;
+
+namespace frc971 {
+namespace control_loops {
+
+class DrivetrainMotorsSS {
+ public:
+  class LimitedDrivetrainLoop : public StateFeedbackLoop<4, 2, 2> {
+   public:
+    LimitedDrivetrainLoop(StateFeedbackLoop<4, 2, 2> &&loop)
+        : StateFeedbackLoop<4, 2, 2>(::std::move(loop)),
+        U_Poly_((Eigen::Matrix<double, 4, 2>() << 1, 0,
+                 -1, 0,
+                 0, 1,
+                 0, -1).finished(),
+                (Eigen::Matrix<double, 4, 1>() << 12.0, 12.0,
+                 12.0, 12.0).finished()) {
+      ::aos::controls::HPolytope<0>::Init();
+      T << 1, -1, 1, 1;
+      T_inverse = T.inverse();
+    }
+
+    bool output_was_capped() const {
+      return output_was_capped_;
+    }
+
+   private:
+    virtual void CapU() {
+      const Eigen::Matrix<double, 4, 1> error = R() - X_hat();
+
+      if (::std::abs(U(0, 0)) > 12.0 || ::std::abs(U(1, 0)) > 12.0) {
+        mutable_U() =
+            U() * 12.0 / ::std::max(::std::abs(U(0, 0)), ::std::abs(U(1, 0)));
+        LOG_MATRIX(DEBUG, "U is now", U());
+        // TODO(Austin): Figure out why the polytope stuff wasn't working and
+        // remove this hack.
+        output_was_capped_ = true;
+        return;
+
+        LOG_MATRIX(DEBUG, "U at start", U());
+        LOG_MATRIX(DEBUG, "R at start", R());
+        LOG_MATRIX(DEBUG, "Xhat at start", X_hat());
+
+        Eigen::Matrix<double, 2, 2> position_K;
+        position_K << K(0, 0), K(0, 2),
+                   K(1, 0), K(1, 2);
+        Eigen::Matrix<double, 2, 2> velocity_K;
+        velocity_K << K(0, 1), K(0, 3),
+                   K(1, 1), K(1, 3);
+
+        Eigen::Matrix<double, 2, 1> position_error;
+        position_error << error(0, 0), error(2, 0);
+        const auto drive_error = T_inverse * position_error;
+        Eigen::Matrix<double, 2, 1> velocity_error;
+        velocity_error << error(1, 0), error(3, 0);
+        LOG_MATRIX(DEBUG, "error", error);
+
+        const auto &poly = U_Poly_;
+        const Eigen::Matrix<double, 4, 2> pos_poly_H =
+            poly.H() * position_K * T;
+        const Eigen::Matrix<double, 4, 1> pos_poly_k =
+            poly.k() - poly.H() * velocity_K * velocity_error;
+        const ::aos::controls::HPolytope<2> pos_poly(pos_poly_H, pos_poly_k);
+
+        Eigen::Matrix<double, 2, 1> adjusted_pos_error;
+        {
+          const auto &P = drive_error;
+
+          Eigen::Matrix<double, 1, 2> L45;
+          L45 << ::aos::sign(P(1, 0)), -::aos::sign(P(0, 0));
+          const double w45 = 0;
+
+          Eigen::Matrix<double, 1, 2> LH;
+          if (::std::abs(P(0, 0)) > ::std::abs(P(1, 0))) {
+            LH << 0, 1;
+          } else {
+            LH << 1, 0;
+          }
+          const double wh = LH.dot(P);
+
+          Eigen::Matrix<double, 2, 2> standard;
+          standard << L45, LH;
+          Eigen::Matrix<double, 2, 1> W;
+          W << w45, wh;
+          const Eigen::Matrix<double, 2, 1> intersection =
+              standard.inverse() * W;
+
+          bool is_inside_h;
+          const auto adjusted_pos_error_h =
+              DoCoerceGoal(pos_poly, LH, wh, drive_error, &is_inside_h);
+          const auto adjusted_pos_error_45 =
+              DoCoerceGoal(pos_poly, L45, w45, intersection, nullptr);
+          if (pos_poly.IsInside(intersection)) {
+            adjusted_pos_error = adjusted_pos_error_h;
+          } else {
+            if (is_inside_h) {
+              if (adjusted_pos_error_h.norm() > adjusted_pos_error_45.norm()) {
+                adjusted_pos_error = adjusted_pos_error_h;
+              } else {
+                adjusted_pos_error = adjusted_pos_error_45;
+              }
+            } else {
+              adjusted_pos_error = adjusted_pos_error_45;
+            }
+          }
+        }
+
+        LOG_MATRIX(DEBUG, "adjusted_pos_error", adjusted_pos_error);
+        mutable_U() =
+            velocity_K * velocity_error + position_K * T * adjusted_pos_error;
+        LOG_MATRIX(DEBUG, "U is now", U());
+      } else {
+        output_was_capped_ = false;
+      }
+    }
+
+    const ::aos::controls::HPolytope<2> U_Poly_;
+    Eigen::Matrix<double, 2, 2> T, T_inverse;
+    bool output_was_capped_ = false;;
+  };
+
+  DrivetrainMotorsSS()
+      : loop_(new LimitedDrivetrainLoop(
+            constants::GetValues().make_drivetrain_loop())),
+        filtered_offset_(0.0),
+        gyro_(0.0),
+        left_goal_(0.0),
+        right_goal_(0.0),
+        raw_left_(0.0),
+        raw_right_(0.0) {
+    // Low gear on both.
+    loop_->set_controller_index(0);
+  }
+
+  void SetGoal(double left, double left_velocity, double right,
+               double right_velocity) {
+    left_goal_ = left;
+    right_goal_ = right;
+    loop_->mutable_R() << left, left_velocity, right, right_velocity;
+  }
+  void SetRawPosition(double left, double right) {
+    raw_right_ = right;
+    raw_left_ = left;
+    Eigen::Matrix<double, 2, 1> Y;
+    Y << left + filtered_offset_, right - filtered_offset_;
+    loop_->Correct(Y);
+  }
+  void SetPosition(double left, double right, double gyro) {
+    // Decay the offset quickly because this gyro is great.
+    const double offset =
+        (right - left - gyro * constants::GetValues().turn_width) / 2.0;
+    filtered_offset_ = 0.25 * offset + 0.75 * filtered_offset_;
+    gyro_ = gyro;
+    SetRawPosition(left, right);
+  }
+
+  void SetExternalMotors(double left_voltage, double right_voltage) {
+    loop_->mutable_U() << left_voltage, right_voltage;
+  }
+
+  void Update(bool stop_motors, bool enable_control_loop) {
+    if (enable_control_loop) {
+      loop_->Update(stop_motors);
+    } else {
+      if (stop_motors) {
+        loop_->mutable_U().setZero();
+        loop_->mutable_U_uncapped().setZero();
+      }
+      loop_->UpdateObserver();
+    }
+    ::Eigen::Matrix<double, 4, 1> E = loop_->R() - loop_->X_hat();
+    LOG_MATRIX(DEBUG, "E", E);
+  }
+
+  double GetEstimatedRobotSpeed() const {
+    // lets just call the average of left and right velocities close enough
+    return (loop_->X_hat(1, 0) + loop_->X_hat(3, 0)) / 2;
+  }
+
+  double GetEstimatedLeftEncoder() const {
+    return loop_->X_hat(0, 0);
+  }
+
+  double GetEstimatedRightEncoder() const {
+    return loop_->X_hat(2, 0);
+  }
+
+  bool OutputWasCapped() const {
+    return loop_->output_was_capped();
+  }
+
+  void SendMotors(DrivetrainQueue::Output *output) const {
+    if (output) {
+      output->left_voltage = loop_->U(0, 0);
+      output->right_voltage = loop_->U(1, 0);
+      output->left_high = false;
+      output->right_high = false;
+    }
+  }
+
+  const LimitedDrivetrainLoop &loop() const { return *loop_; }
+
+ private:
+  ::std::unique_ptr<LimitedDrivetrainLoop> loop_;
+
+  double filtered_offset_;
+  double gyro_;
+  double left_goal_;
+  double right_goal_;
+  double raw_left_;
+  double raw_right_;
+};
+
+class PolyDrivetrain {
+ public:
+
+  enum Gear {
+    HIGH,
+    LOW,
+    SHIFTING_UP,
+    SHIFTING_DOWN
+  };
+  // Stall Torque in N m
+  static constexpr double kStallTorque = 2.42;
+  // Stall Current in Amps
+  static constexpr double kStallCurrent = 133.0;
+  // Free Speed in RPM. Used number from last year.
+  static constexpr double kFreeSpeed = 4650.0;
+  // Free Current in Amps
+  static constexpr double kFreeCurrent = 2.7;
+  // Moment of inertia of the drivetrain in kg m^2
+  // Just borrowed from last year.
+  static constexpr double J = 6.4;
+  // Mass of the robot, in kg.
+  static constexpr double m = 68.0;
+  // Radius of the robot, in meters (from last year).
+  static constexpr double rb = 0.617998644 / 2.0;
+  static constexpr double kWheelRadius = 0.04445;
+  // Resistance of the motor, divided by the number of motors.
+  static constexpr double kR = (12.0 / kStallCurrent / 4 + 0.03) / (0.93 * 0.93);
+  // Motor velocity constant
+  static constexpr double Kv =
+      ((kFreeSpeed / 60.0 * 2.0 * M_PI) / (12.0 - kR * kFreeCurrent));
+  // Torque constant
+  static constexpr double Kt = kStallTorque / kStallCurrent;
+
+  PolyDrivetrain()
+      : U_Poly_((Eigen::Matrix<double, 4, 2>() << /*[[*/ 1, 0 /*]*/,
+                 /*[*/ -1, 0 /*]*/,
+                 /*[*/ 0, 1 /*]*/,
+                 /*[*/ 0, -1 /*]]*/).finished(),
+                (Eigen::Matrix<double, 4, 1>() << /*[[*/ 12 /*]*/,
+                 /*[*/ 12 /*]*/,
+                 /*[*/ 12 /*]*/,
+                 /*[*/ 12 /*]]*/).finished()),
+        loop_(new StateFeedbackLoop<2, 2, 2>(
+            constants::GetValues().make_v_drivetrain_loop())),
+        ttrust_(1.1),
+        wheel_(0.0),
+        throttle_(0.0),
+        quickturn_(false),
+        stale_count_(0),
+        position_time_delta_(0.01),
+        left_gear_(LOW),
+        right_gear_(LOW),
+        counter_(0) {
+
+    last_position_.Zero();
+    position_.Zero();
+  }
+  static bool IsInGear(Gear gear) { return gear == LOW || gear == HIGH; }
+
+  static double MotorSpeed(const constants::ShifterHallEffect &hall_effect,
+                           double shifter_position, double velocity) {
+    // TODO(austin): G_high, G_low and kWheelRadius
+    const double avg_hall_effect =
+        (hall_effect.clear_high + hall_effect.clear_low) / 2.0;
+
+    if (shifter_position > avg_hall_effect) {
+      return velocity / constants::GetValues().high_gear_ratio / kWheelRadius;
+    } else {
+      return velocity / constants::GetValues().low_gear_ratio / kWheelRadius;
+    }
+  }
+
+  Gear ComputeGear(const constants::ShifterHallEffect &hall_effect,
+                   double velocity, Gear current) {
+    const double low_omega = MotorSpeed(hall_effect, 0.0, ::std::abs(velocity));
+    const double high_omega =
+        MotorSpeed(hall_effect, 1.0, ::std::abs(velocity));
+
+    double high_torque = ((12.0 - high_omega / Kv) * Kt / kR);
+    double low_torque = ((12.0 - low_omega / Kv) * Kt / kR);
+    double high_power = high_torque * high_omega;
+    double low_power = low_torque * low_omega;
+
+    // TODO(aschuh): Do this right!
+    if ((current == HIGH || high_power > low_power + 160) &&
+        ::std::abs(velocity) > 0.14) {
+      return HIGH;
+    } else {
+      return LOW;
+    }
+  }
+
+  void SetGoal(double wheel, double throttle, bool quickturn, bool highgear) {
+    const double kWheelNonLinearity = 0.3;
+    // Apply a sin function that's scaled to make it feel better.
+    const double angular_range = M_PI_2 * kWheelNonLinearity;
+
+    wheel_ = sin(angular_range * wheel) / sin(angular_range);
+    wheel_ = sin(angular_range * wheel_) / sin(angular_range);
+    quickturn_ = quickturn;
+
+    static const double kThrottleDeadband = 0.05;
+    if (::std::abs(throttle) < kThrottleDeadband) {
+      throttle_ = 0;
+    } else {
+      throttle_ = copysign((::std::abs(throttle) - kThrottleDeadband) /
+                           (1.0 - kThrottleDeadband), throttle);
+    }
+
+    // TODO(austin): Fix the upshift logic to include states.
+    Gear requested_gear;
+    if (false) {
+      const auto &values = constants::GetValues();
+      const double current_left_velocity =
+          (position_.left_encoder - last_position_.left_encoder) /
+          position_time_delta_;
+      const double current_right_velocity =
+          (position_.right_encoder - last_position_.right_encoder) /
+          position_time_delta_;
+
+      Gear left_requested =
+          ComputeGear(values.left_drive, current_left_velocity, left_gear_);
+      Gear right_requested =
+          ComputeGear(values.right_drive, current_right_velocity, right_gear_);
+      requested_gear =
+          (left_requested == HIGH || right_requested == HIGH) ? HIGH : LOW;
+    } else {
+      requested_gear = highgear ? HIGH : LOW;
+    }
+
+    const Gear shift_up =
+        constants::GetValues().clutch_transmission ? HIGH : SHIFTING_UP;
+    const Gear shift_down =
+        constants::GetValues().clutch_transmission ? LOW : SHIFTING_DOWN;
+
+    if (left_gear_ != requested_gear) {
+      if (IsInGear(left_gear_)) {
+        if (requested_gear == HIGH) {
+          left_gear_ = shift_up;
+        } else {
+          left_gear_ = shift_down;
+        }
+      } else {
+        if (requested_gear == HIGH && left_gear_ == SHIFTING_DOWN) {
+          left_gear_ = SHIFTING_UP;
+        } else if (requested_gear == LOW && left_gear_ == SHIFTING_UP) {
+          left_gear_ = SHIFTING_DOWN;
+        }
+      }
+    }
+    if (right_gear_ != requested_gear) {
+      if (IsInGear(right_gear_)) {
+        if (requested_gear == HIGH) {
+          right_gear_ = shift_up;
+        } else {
+          right_gear_ = shift_down;
+        }
+      } else {
+        if (requested_gear == HIGH && right_gear_ == SHIFTING_DOWN) {
+          right_gear_ = SHIFTING_UP;
+        } else if (requested_gear == LOW && right_gear_ == SHIFTING_UP) {
+          right_gear_ = SHIFTING_DOWN;
+        }
+      }
+    }
+  }
+  void SetPosition(const DrivetrainQueue::Position *position) {
+    const auto &values = constants::GetValues();
+    if (position == NULL) {
+      ++stale_count_;
+    } else {
+      last_position_ = position_;
+      position_ = *position;
+      position_time_delta_ = (stale_count_ + 1) * 0.01;
+      stale_count_ = 0;
+    }
+
+#if HAVE_SHIFTERS
+    if (position) {
+      GearLogging gear_logging;
+      // Switch to the correct controller.
+      const double left_middle_shifter_position =
+          (values.left_drive.clear_high + values.left_drive.clear_low) / 2.0;
+      const double right_middle_shifter_position =
+          (values.right_drive.clear_high + values.right_drive.clear_low) / 2.0;
+
+      if (position->left_shifter_position < left_middle_shifter_position ||
+          left_gear_ == LOW) {
+        if (position->right_shifter_position < right_middle_shifter_position ||
+            right_gear_ == LOW) {
+          gear_logging.left_loop_high = false;
+          gear_logging.right_loop_high = false;
+          loop_->set_controller_index(gear_logging.controller_index = 0);
+        } else {
+          gear_logging.left_loop_high = false;
+          gear_logging.right_loop_high = true;
+          loop_->set_controller_index(gear_logging.controller_index = 1);
+        }
+      } else {
+        if (position->right_shifter_position < right_middle_shifter_position ||
+            right_gear_ == LOW) {
+          gear_logging.left_loop_high = true;
+          gear_logging.right_loop_high = false;
+          loop_->set_controller_index(gear_logging.controller_index = 2);
+        } else {
+          gear_logging.left_loop_high = true;
+          gear_logging.right_loop_high = true;
+          loop_->set_controller_index(gear_logging.controller_index = 3);
+        }
+      }
+
+      // TODO(austin): Constants.
+      if (position->left_shifter_position > values.left_drive.clear_high && left_gear_ == SHIFTING_UP) {
+        left_gear_ = HIGH;
+      }
+      if (position->left_shifter_position < values.left_drive.clear_low && left_gear_ == SHIFTING_DOWN) {
+        left_gear_ = LOW;
+      }
+      if (position->right_shifter_position > values.right_drive.clear_high && right_gear_ == SHIFTING_UP) {
+        right_gear_ = HIGH;
+      }
+      if (position->right_shifter_position < values.right_drive.clear_low && right_gear_ == SHIFTING_DOWN) {
+        right_gear_ = LOW;
+      }
+
+      gear_logging.left_state = left_gear_;
+      gear_logging.right_state = right_gear_;
+      LOG_STRUCT(DEBUG, "state", gear_logging);
+    }
+#else
+    (void) values;
+#endif
+  }
+
+  double FilterVelocity(double throttle) {
+    const Eigen::Matrix<double, 2, 2> FF =
+        loop_->B().inverse() *
+        (Eigen::Matrix<double, 2, 2>::Identity() - loop_->A());
+
+    constexpr int kHighGearController = 3;
+    const Eigen::Matrix<double, 2, 2> FF_high =
+        loop_->controller(kHighGearController).plant.B().inverse() *
+        (Eigen::Matrix<double, 2, 2>::Identity() -
+         loop_->controller(kHighGearController).plant.A());
+
+    ::Eigen::Matrix<double, 1, 2> FF_sum = FF.colwise().sum();
+    int min_FF_sum_index;
+    const double min_FF_sum = FF_sum.minCoeff(&min_FF_sum_index);
+    const double min_K_sum = loop_->K().col(min_FF_sum_index).sum();
+    const double high_min_FF_sum = FF_high.col(0).sum();
+
+    const double adjusted_ff_voltage = ::aos::Clip(
+        throttle * 12.0 * min_FF_sum / high_min_FF_sum, -12.0, 12.0);
+    return (adjusted_ff_voltage +
+            ttrust_ * min_K_sum * (loop_->X_hat(0, 0) + loop_->X_hat(1, 0)) /
+                2.0) /
+           (ttrust_ * min_K_sum + min_FF_sum);
+  }
+
+  double MaxVelocity() {
+    const Eigen::Matrix<double, 2, 2> FF =
+        loop_->B().inverse() *
+        (Eigen::Matrix<double, 2, 2>::Identity() - loop_->A());
+
+    constexpr int kHighGearController = 3;
+    const Eigen::Matrix<double, 2, 2> FF_high =
+        loop_->controller(kHighGearController).plant.B().inverse() *
+        (Eigen::Matrix<double, 2, 2>::Identity() -
+         loop_->controller(kHighGearController).plant.A());
+
+    ::Eigen::Matrix<double, 1, 2> FF_sum = FF.colwise().sum();
+    int min_FF_sum_index;
+    const double min_FF_sum = FF_sum.minCoeff(&min_FF_sum_index);
+    //const double min_K_sum = loop_->K().col(min_FF_sum_index).sum();
+    const double high_min_FF_sum = FF_high.col(0).sum();
+
+    const double adjusted_ff_voltage = ::aos::Clip(
+        12.0 * min_FF_sum / high_min_FF_sum, -12.0, 12.0);
+    return adjusted_ff_voltage / min_FF_sum;
+  }
+
+  void Update() {
+    const auto &values = constants::GetValues();
+    // TODO(austin): Observer for the current velocity instead of difference
+    // calculations.
+    ++counter_;
+#if HAVE_SHIFTERS
+    const double current_left_velocity =
+        (position_.left_encoder - last_position_.left_encoder) /
+        position_time_delta_;
+    const double current_right_velocity =
+        (position_.right_encoder - last_position_.right_encoder) /
+        position_time_delta_;
+    const double left_motor_speed =
+        MotorSpeed(values.left_drive, position_.left_shifter_position,
+                   current_left_velocity);
+    const double right_motor_speed =
+        MotorSpeed(values.right_drive, position_.right_shifter_position,
+                   current_right_velocity);
+
+    {
+      CIMLogging logging;
+
+      // Reset the CIM model to the current conditions to be ready for when we
+      // shift.
+      if (IsInGear(left_gear_)) {
+        logging.left_in_gear = true;
+      } else {
+        logging.left_in_gear = false;
+      }
+      logging.left_motor_speed = left_motor_speed;
+      logging.left_velocity = current_left_velocity;
+      if (IsInGear(right_gear_)) {
+        logging.right_in_gear = true;
+      } else {
+        logging.right_in_gear = false;
+      }
+      logging.right_motor_speed = right_motor_speed;
+      logging.right_velocity = current_right_velocity;
+
+      LOG_STRUCT(DEBUG, "currently", logging);
+    }
+#else
+    (void) values;
+#endif
+
+#if HAVE_SHIFTERS
+    if (IsInGear(left_gear_) && IsInGear(right_gear_)) {
+#else
+    {
+#endif
+      // FF * X = U (steady state)
+      const Eigen::Matrix<double, 2, 2> FF =
+          loop_->B().inverse() *
+          (Eigen::Matrix<double, 2, 2>::Identity() - loop_->A());
+
+      // Invert the plant to figure out how the velocity filter would have to
+      // work
+      // out in order to filter out the forwards negative inertia.
+      // This math assumes that the left and right power and velocity are
+      // equals,
+      // and that the plant is the same on the left and right.
+      const double fvel = FilterVelocity(throttle_);
+
+      const double sign_svel = wheel_ * ((fvel > 0.0) ? 1.0 : -1.0);
+      double steering_velocity;
+      if (quickturn_) {
+        steering_velocity = wheel_ * MaxVelocity();
+      } else {
+        steering_velocity = ::std::abs(fvel) * wheel_;
+      }
+      const double left_velocity = fvel - steering_velocity;
+      const double right_velocity = fvel + steering_velocity;
+
+      // Integrate velocity to get the position.
+      // This position is used to get integral control.
+      loop_->mutable_R() << left_velocity, right_velocity;
+
+      if (!quickturn_) {
+        // K * R = w
+        Eigen::Matrix<double, 1, 2> equality_k;
+        equality_k << 1 + sign_svel, -(1 - sign_svel);
+        const double equality_w = 0.0;
+
+        // Construct a constraint on R by manipulating the constraint on U
+        ::aos::controls::HPolytope<2> R_poly = ::aos::controls::HPolytope<2>(
+            U_Poly_.H() * (loop_->K() + FF),
+            U_Poly_.k() + U_Poly_.H() * loop_->K() * loop_->X_hat());
+
+        // Limit R back inside the box.
+        loop_->mutable_R() =
+            CoerceGoal(R_poly, equality_k, equality_w, loop_->R());
+      }
+
+      const Eigen::Matrix<double, 2, 1> FF_volts = FF * loop_->R();
+      const Eigen::Matrix<double, 2, 1> U_ideal =
+          loop_->K() * (loop_->R() - loop_->X_hat()) + FF_volts;
+
+      for (int i = 0; i < 2; i++) {
+        loop_->mutable_U()[i] = ::aos::Clip(U_ideal[i], -12, 12);
+      }
+
+      // TODO(austin): Model this better.
+      // TODO(austin): Feed back?
+      loop_->mutable_X_hat() =
+          loop_->A() * loop_->X_hat() + loop_->B() * loop_->U();
+#if HAVE_SHIFTERS
+    } else {
+      // Any motor is not in gear.  Speed match.
+      ::Eigen::Matrix<double, 1, 1> R_left;
+      ::Eigen::Matrix<double, 1, 1> R_right;
+      R_left(0, 0) = left_motor_speed;
+      R_right(0, 0) = right_motor_speed;
+
+      const double wiggle =
+          (static_cast<double>((counter_ % 20) / 10) - 0.5) * 5.0;
+
+      loop_->mutable_U(0, 0) = ::aos::Clip(
+          (R_left / Kv)(0, 0) + (IsInGear(left_gear_) ? 0 : wiggle),
+          -12.0, 12.0);
+      loop_->mutable_U(1, 0) = ::aos::Clip(
+          (R_right / Kv)(0, 0) + (IsInGear(right_gear_) ? 0 : wiggle),
+          -12.0, 12.0);
+      loop_->mutable_U() *= 12.0 / ::aos::robot_state->voltage_battery;
+#endif
+    }
+  }
+
+  void SendMotors(DrivetrainQueue::Output *output) {
+    if (output != NULL) {
+      output->left_voltage = loop_->U(0, 0);
+      output->right_voltage = loop_->U(1, 0);
+      output->left_high = left_gear_ == HIGH || left_gear_ == SHIFTING_UP;
+      output->right_high = right_gear_ == HIGH || right_gear_ == SHIFTING_UP;
+    }
+  }
+
+ private:
+  const ::aos::controls::HPolytope<2> U_Poly_;
+
+  ::std::unique_ptr<StateFeedbackLoop<2, 2, 2>> loop_;
+
+  const double ttrust_;
+  double wheel_;
+  double throttle_;
+  bool quickturn_;
+  int stale_count_;
+  double position_time_delta_;
+  Gear left_gear_;
+  Gear right_gear_;
+  DrivetrainQueue::Position last_position_;
+  DrivetrainQueue::Position position_;
+  int counter_;
+};
+constexpr double PolyDrivetrain::kStallTorque;
+constexpr double PolyDrivetrain::kStallCurrent;
+constexpr double PolyDrivetrain::kFreeSpeed;
+constexpr double PolyDrivetrain::kFreeCurrent;
+constexpr double PolyDrivetrain::J;
+constexpr double PolyDrivetrain::m;
+constexpr double PolyDrivetrain::rb;
+constexpr double PolyDrivetrain::kWheelRadius;
+constexpr double PolyDrivetrain::kR;
+constexpr double PolyDrivetrain::Kv;
+constexpr double PolyDrivetrain::Kt;
+
+
+void DrivetrainLoop::RunIteration(const DrivetrainQueue::Goal *goal,
+                                  const DrivetrainQueue::Position *position,
+                                  DrivetrainQueue::Output *output,
+                                  DrivetrainQueue::Status * status) {
+  // TODO(aschuh): These should be members of the class.
+  static DrivetrainMotorsSS dt_closedloop;
+  static PolyDrivetrain dt_openloop;
+
+  bool bad_pos = false;
+  if (position == nullptr) {
+    LOG_INTERVAL(no_position_);
+    bad_pos = true;
+  }
+  no_position_.Print();
+
+  bool control_loop_driving = false;
+  if (goal) {
+    double wheel = goal->steering;
+    double throttle = goal->throttle;
+    bool quickturn = goal->quickturn;
+#if HAVE_SHIFTERS
+    bool highgear = goal->highgear;
+#endif
+
+    control_loop_driving = goal->control_loop_driving;
+    double left_goal = goal->left_goal;
+    double right_goal = goal->right_goal;
+
+    dt_closedloop.SetGoal(left_goal, goal->left_velocity_goal, right_goal,
+                          goal->right_velocity_goal);
+#if HAVE_SHIFTERS
+    dt_openloop.SetGoal(wheel, throttle, quickturn, highgear);
+#else
+    dt_openloop.SetGoal(wheel, throttle, quickturn, false);
+#endif
+  }
+
+  if (!bad_pos) {
+    const double left_encoder = position->left_encoder;
+    const double right_encoder = position->right_encoder;
+    if (gyro_reading.FetchLatest()) {
+      LOG_STRUCT(DEBUG, "using", *gyro_reading.get());
+      dt_closedloop.SetPosition(left_encoder, right_encoder,
+                                gyro_reading->angle);
+    } else {
+      dt_closedloop.SetRawPosition(left_encoder, right_encoder);
+    }
+  }
+  dt_openloop.SetPosition(position);
+  dt_openloop.Update();
+
+  if (control_loop_driving) {
+    dt_closedloop.Update(output == NULL, true);
+    dt_closedloop.SendMotors(output);
+  } else {
+    dt_openloop.SendMotors(output);
+    if (output) {
+      dt_closedloop.SetExternalMotors(output->left_voltage,
+                                      output->right_voltage);
+    }
+    dt_closedloop.Update(output == NULL, false);
+  }
+
+  // set the output status of the control loop state
+  if (status) {
+    bool done = false;
+    if (goal) {
+      done = ((::std::abs(goal->left_goal -
+                          dt_closedloop.GetEstimatedLeftEncoder()) <
+               constants::GetValues().drivetrain_done_distance) &&
+              (::std::abs(goal->right_goal -
+                          dt_closedloop.GetEstimatedRightEncoder()) <
+               constants::GetValues().drivetrain_done_distance));
+    }
+    status->is_done = done;
+    status->robot_speed = dt_closedloop.GetEstimatedRobotSpeed();
+    status->filtered_left_position = dt_closedloop.GetEstimatedLeftEncoder();
+    status->filtered_right_position = dt_closedloop.GetEstimatedRightEncoder();
+
+    status->filtered_left_velocity = dt_closedloop.loop().X_hat(1, 0);
+    status->filtered_right_velocity = dt_closedloop.loop().X_hat(3, 0);
+    status->output_was_capped = dt_closedloop.OutputWasCapped();
+    status->uncapped_left_voltage = dt_closedloop.loop().U_uncapped(0, 0);
+    status->uncapped_right_voltage = dt_closedloop.loop().U_uncapped(1, 0);
+  }
+}
+
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/y2014/control_loops/drivetrain/drivetrain.gyp b/y2014/control_loops/drivetrain/drivetrain.gyp
new file mode 100644
index 0000000..ffe4337
--- /dev/null
+++ b/y2014/control_loops/drivetrain/drivetrain.gyp
@@ -0,0 +1,103 @@
+{
+  'targets': [
+    {
+      'target_name': 'replay_drivetrain',
+      'type': 'executable',
+      'variables': {
+        'no_rsync': 1,
+      },
+      'sources': [
+        'replay_drivetrain.cc',
+      ],
+      'dependencies': [
+        'drivetrain_queue',
+        '<(AOS)/common/controls/controls.gyp:replay_control_loop',
+        '<(AOS)/linux_code/linux_code.gyp:init',
+      ],
+    },
+    {
+      'target_name': 'drivetrain_queue',
+      'type': 'static_library',
+      'sources': ['drivetrain.q'],
+      'variables': {
+        'header_path': 'y2014/control_loops/drivetrain',
+      },
+      'dependencies': [
+        '<(AOS)/common/controls/controls.gyp:control_loop_queues',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/controls/controls.gyp:control_loop_queues',
+      ],
+      'includes': ['../../../aos/build/queues.gypi'],
+    },
+    {
+      'target_name': 'polydrivetrain_plants',
+      'type': 'static_library',
+      'sources': [
+        'polydrivetrain_dog_motor_plant.cc',
+        'drivetrain_dog_motor_plant.cc',
+      ],
+      'dependencies': [
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+      ],
+      'export_dependent_settings': [
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+      ],
+    },
+    {
+      'target_name': 'drivetrain_lib',
+      'type': 'static_library',
+      'sources': [
+        'drivetrain.cc',
+        'polydrivetrain_cim_plant.cc',
+      ],
+      'dependencies': [
+        'drivetrain_queue',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+        '<(DEPTH)/y2014/y2014.gyp:constants',
+        '<(AOS)/common/controls/controls.gyp:polytope',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:coerce_goal',
+        '<(DEPTH)/frc971/queues/queues.gyp:gyro',
+        '<(AOS)/common/util/util.gyp:log_interval',
+        '<(AOS)/common/logging/logging.gyp:queue_logging',
+        '<(AOS)/common/logging/logging.gyp:matrix_logging',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/controls/controls.gyp:polytope',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:coerce_goal',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+        'drivetrain_queue',
+      ],
+    },
+    {
+      'target_name': 'drivetrain_lib_test',
+      'type': 'executable',
+      'sources': [
+        'drivetrain_lib_test.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+        'drivetrain_queue',
+        'drivetrain_lib',
+        '<(AOS)/common/controls/controls.gyp:control_loop_test',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+        '<(DEPTH)/frc971/queues/queues.gyp:gyro',
+        '<(AOS)/common/common.gyp:queues',
+      ],
+    },
+    {
+      'target_name': 'drivetrain',
+      'type': 'executable',
+      'sources': [
+        'drivetrain_main.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        'drivetrain_lib',
+        'drivetrain_queue',
+      ],
+    },
+  ],
+}
diff --git a/y2014/control_loops/drivetrain/drivetrain.h b/y2014/control_loops/drivetrain/drivetrain.h
new file mode 100644
index 0000000..87e6362
--- /dev/null
+++ b/y2014/control_loops/drivetrain/drivetrain.h
@@ -0,0 +1,43 @@
+#ifndef Y2014_CONTROL_LOOPS_DRIVETRAIN_H_
+#define Y2014_CONTROL_LOOPS_DRIVETRAIN_H_
+
+#include "Eigen/Dense"
+
+#include "aos/common/controls/polytope.h"
+#include "aos/common/controls/control_loop.h"
+#include "aos/common/controls/polytope.h"
+#include "y2014/control_loops/drivetrain/drivetrain.q.h"
+#include "aos/common/util/log_interval.h"
+
+namespace frc971 {
+namespace control_loops {
+
+class DrivetrainLoop
+    : public aos::controls::ControlLoop<control_loops::DrivetrainQueue> {
+ public:
+  // Constructs a control loop which can take a Drivetrain or defaults to the
+  // drivetrain at frc971::control_loops::drivetrain
+  explicit DrivetrainLoop(control_loops::DrivetrainQueue *my_drivetrain =
+                              &control_loops::drivetrain_queue)
+      : aos::controls::ControlLoop<control_loops::DrivetrainQueue>(
+            my_drivetrain) {
+    ::aos::controls::HPolytope<0>::Init();
+  }
+
+ protected:
+  // Executes one cycle of the control loop.
+  virtual void RunIteration(
+      const control_loops::DrivetrainQueue::Goal *goal,
+      const control_loops::DrivetrainQueue::Position *position,
+      control_loops::DrivetrainQueue::Output *output,
+      control_loops::DrivetrainQueue::Status *status);
+
+  typedef ::aos::util::SimpleLogInterval SimpleLogInterval;
+  SimpleLogInterval no_position_ = SimpleLogInterval(
+      ::aos::time::Time::InSeconds(0.25), WARNING, "no position");
+};
+
+}  // namespace control_loops
+}  // namespace frc971
+
+#endif  // Y2014_CONTROL_LOOPS_DRIVETRAIN_H_
diff --git a/y2014/control_loops/drivetrain/drivetrain.q b/y2014/control_loops/drivetrain/drivetrain.q
new file mode 100644
index 0000000..872efec
--- /dev/null
+++ b/y2014/control_loops/drivetrain/drivetrain.q
@@ -0,0 +1,71 @@
+package frc971.control_loops;
+
+import "aos/common/controls/control_loops.q";
+
+struct GearLogging {
+  int8_t controller_index;
+  bool left_loop_high;
+  bool right_loop_high;
+  int8_t left_state;
+  int8_t right_state;
+};
+
+struct CIMLogging {
+  bool left_in_gear;
+  bool right_in_gear;
+  double left_motor_speed;
+  double right_motor_speed;
+  double left_velocity;
+  double right_velocity;
+};
+
+queue_group DrivetrainQueue {
+  implements aos.control_loops.ControlLoop;
+
+  message Goal {
+    double steering;
+    double throttle;
+    bool highgear;
+    bool quickturn;
+    bool control_loop_driving;
+    double left_goal;
+    double left_velocity_goal;
+    double right_goal;
+    double right_velocity_goal;
+  };
+
+  message Position {
+    double left_encoder;
+    double right_encoder;
+    double left_shifter_position;
+    double right_shifter_position;
+  };
+
+  message Output {
+    double left_voltage;
+    double right_voltage;
+    bool left_high;
+    bool right_high;
+  };
+
+  message Status {
+    double robot_speed;
+    double filtered_left_position;
+    double filtered_right_position;
+    double filtered_left_velocity;
+    double filtered_right_velocity;
+
+    double uncapped_left_voltage;
+    double uncapped_right_voltage;
+    bool output_was_capped;
+
+    bool is_done;
+  };
+
+  queue Goal goal;
+  queue Position position;
+  queue Output output;
+  queue Status status;
+};
+
+queue_group DrivetrainQueue drivetrain_queue;
diff --git a/y2014/control_loops/drivetrain/drivetrain_dog_motor_plant.cc b/y2014/control_loops/drivetrain/drivetrain_dog_motor_plant.cc
new file mode 100644
index 0000000..2bb5c94
--- /dev/null
+++ b/y2014/control_loops/drivetrain/drivetrain_dog_motor_plant.cc
@@ -0,0 +1,133 @@
+#include "y2014/control_loops/drivetrain/drivetrain_dog_motor_plant.h"
+
+#include <vector>
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace frc971 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeDrivetrainLowLowPlantCoefficients() {
+  Eigen::Matrix<double, 4, 4> A;
+  A << 1.0, 0.00860955515291, 0.0, 0.000228184998733, 0.0, 0.735841675858, 0.0, 0.0410810558113, 0.0, 0.000228184998733, 1.0, 0.00860955515291, 0.0, 0.0410810558113, 0.0, 0.735841675858;
+  Eigen::Matrix<double, 4, 2> B;
+  B << 0.000272244648044, -4.46778919705e-05, 0.0517213538779, -0.00804353916233, -4.46778919705e-05, 0.000272244648044, -0.00804353916233, 0.0517213538779;
+  Eigen::Matrix<double, 2, 4> C;
+  C << 1, 0, 0, 0, 0, 0, 1, 0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0, 0, 0, 0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<4, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeDrivetrainLowHighPlantCoefficients() {
+  Eigen::Matrix<double, 4, 4> A;
+  A << 1.0, 0.00860667098456, 0.0, 7.04111872002e-05, 0.0, 0.735048848179, 0.0, 0.0131811893199, 0.0, 0.000245343870066, 1.0, 0.00957169266049, 0.0, 0.045929121897, 0.0, 0.915703853642;
+  Eigen::Matrix<double, 4, 2> B;
+  B << 0.000272809358971, -2.57343985847e-05, 0.0518765869984, -0.00481755802263, -4.80375440247e-05, 0.00015654091672, -0.00899277497558, 0.0308091755839;
+  Eigen::Matrix<double, 2, 4> C;
+  C << 1, 0, 0, 0, 0, 0, 1, 0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0, 0, 0, 0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<4, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeDrivetrainHighLowPlantCoefficients() {
+  Eigen::Matrix<double, 4, 4> A;
+  A << 1.0, 0.00957169266049, 0.0, 0.000245343870066, 0.0, 0.915703853642, 0.0, 0.045929121897, 0.0, 7.04111872002e-05, 1.0, 0.00860667098456, 0.0, 0.0131811893199, 0.0, 0.735048848179;
+  Eigen::Matrix<double, 4, 2> B;
+  B << 0.00015654091672, -4.80375440247e-05, 0.0308091755839, -0.00899277497558, -2.57343985847e-05, 0.000272809358971, -0.00481755802263, 0.0518765869984;
+  Eigen::Matrix<double, 2, 4> C;
+  C << 1, 0, 0, 0, 0, 0, 1, 0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0, 0, 0, 0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<4, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeDrivetrainHighHighPlantCoefficients() {
+  Eigen::Matrix<double, 4, 4> A;
+  A << 1.0, 0.00957076892085, 0.0, 7.56192087769e-05, 0.0, 0.915439806567, 0.0, 0.0146814193986, 0.0, 7.56192087769e-05, 1.0, 0.00957076892085, 0.0, 0.0146814193986, 0.0, 0.915439806567;
+  Eigen::Matrix<double, 4, 2> B;
+  B << 0.000156878531877, -2.76378646165e-05, 0.0309056814511, -0.00536587314624, -2.76378646165e-05, 0.000156878531877, -0.00536587314624, 0.0309056814511;
+  Eigen::Matrix<double, 2, 4> C;
+  C << 1, 0, 0, 0, 0, 0, 1, 0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0, 0, 0, 0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<4, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackController<4, 2, 2> MakeDrivetrainLowLowController() {
+  Eigen::Matrix<double, 4, 2> L;
+  L << 1.03584167586, 0.0410810558113, 17.1117704011, 3.22861251708, 0.0410810558113, 1.03584167586, 3.22861251708, 17.1117704011;
+  Eigen::Matrix<double, 2, 4> K;
+  K << 128.210620632, 6.93828382074, 5.11036686771, 0.729493080206, 5.1103668677, 0.729493080206, 128.210620632, 6.93828382074;
+  Eigen::Matrix<double, 4, 4> A_inv;
+  A_inv << 1.0, -0.0117194973377, 0.0, 0.000344183176608, 0.0, 1.36323698074, 0.0, -0.0761076958907, 0.0, 0.000344183176608, 1.0, -0.0117194973377, 0.0, -0.0761076958907, 0.0, 1.36323698074;
+  return StateFeedbackController<4, 2, 2>(L, K, A_inv, MakeDrivetrainLowLowPlantCoefficients());
+}
+
+StateFeedbackController<4, 2, 2> MakeDrivetrainLowHighController() {
+  Eigen::Matrix<double, 4, 2> L;
+  L << 1.02891982345, 0.0143715516939, 16.6997472571, 1.23741823594, 0.0143715516939, 1.22183287838, 2.40440177527, 33.5403677132;
+  Eigen::Matrix<double, 2, 4> K;
+  K << 127.841025245, 6.90618982868, -2.11442482189, 0.171361719101, 11.257083857, 1.47190974842, 138.457761234, 11.0770574926;
+  Eigen::Matrix<double, 4, 4> A_inv;
+  A_inv << 1.0, -0.011714710309, 0.0, 9.17355833725e-05, 0.0, 1.36167854796, 0.0, -0.0196008159867, 0.0, 0.00031964754384, 1.0, -0.0104574267731, 0.0, -0.0682979543713, 0.0, 1.09303924439;
+  return StateFeedbackController<4, 2, 2>(L, K, A_inv, MakeDrivetrainLowHighPlantCoefficients());
+}
+
+StateFeedbackController<4, 2, 2> MakeDrivetrainHighLowController() {
+  Eigen::Matrix<double, 4, 2> L;
+  L << 1.21584032636, 0.045928553155, 33.3376290177, 4.12652814156, 0.045928553155, 1.03491237546, 2.45838080322, 16.967272239;
+  Eigen::Matrix<double, 2, 4> K;
+  K << 138.457761234, 11.0770574926, 11.257083857, 1.47190974842, -2.1144248219, 0.171361719101, 127.841025245, 6.90618982868;
+  Eigen::Matrix<double, 4, 4> A_inv;
+  A_inv << 1.0, -0.0104574267731, 0.0, 0.00031964754384, 0.0, 1.09303924439, 0.0, -0.0682979543713, 0.0, 9.17355833725e-05, 1.0, -0.011714710309, 0.0, -0.0196008159867, 0.0, 1.36167854796;
+  return StateFeedbackController<4, 2, 2>(L, K, A_inv, MakeDrivetrainHighLowPlantCoefficients());
+}
+
+StateFeedbackController<4, 2, 2> MakeDrivetrainHighHighController() {
+  Eigen::Matrix<double, 4, 2> L;
+  L << 1.21543980657, 0.0146814193986, 33.1557840927, 1.47278696694, 0.0146814193986, 1.21543980657, 1.47278696694, 33.1557840927;
+  Eigen::Matrix<double, 2, 4> K;
+  K << 138.52410152, 11.0779399816, 3.96842371774, 0.882728086516, 3.96842371774, 0.882728086517, 138.52410152, 11.0779399816;
+  Eigen::Matrix<double, 4, 4> A_inv;
+  A_inv << 1.0, -0.010456196092, 0.0, 8.50876166887e-05, 0.0, 1.0926521463, 0.0, -0.0175234726538, 0.0, 8.50876166887e-05, 1.0, -0.010456196092, 0.0, -0.0175234726538, 0.0, 1.0926521463;
+  return StateFeedbackController<4, 2, 2>(L, K, A_inv, MakeDrivetrainHighHighPlantCoefficients());
+}
+
+StateFeedbackPlant<4, 2, 2> MakeDrivetrainPlant() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackPlantCoefficients<4, 2, 2>>> plants(4);
+  plants[0] = ::std::unique_ptr<StateFeedbackPlantCoefficients<4, 2, 2>>(new StateFeedbackPlantCoefficients<4, 2, 2>(MakeDrivetrainLowLowPlantCoefficients()));
+  plants[1] = ::std::unique_ptr<StateFeedbackPlantCoefficients<4, 2, 2>>(new StateFeedbackPlantCoefficients<4, 2, 2>(MakeDrivetrainLowHighPlantCoefficients()));
+  plants[2] = ::std::unique_ptr<StateFeedbackPlantCoefficients<4, 2, 2>>(new StateFeedbackPlantCoefficients<4, 2, 2>(MakeDrivetrainHighLowPlantCoefficients()));
+  plants[3] = ::std::unique_ptr<StateFeedbackPlantCoefficients<4, 2, 2>>(new StateFeedbackPlantCoefficients<4, 2, 2>(MakeDrivetrainHighHighPlantCoefficients()));
+  return StateFeedbackPlant<4, 2, 2>(&plants);
+}
+
+StateFeedbackLoop<4, 2, 2> MakeDrivetrainLoop() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackController<4, 2, 2>>> controllers(4);
+  controllers[0] = ::std::unique_ptr<StateFeedbackController<4, 2, 2>>(new StateFeedbackController<4, 2, 2>(MakeDrivetrainLowLowController()));
+  controllers[1] = ::std::unique_ptr<StateFeedbackController<4, 2, 2>>(new StateFeedbackController<4, 2, 2>(MakeDrivetrainLowHighController()));
+  controllers[2] = ::std::unique_ptr<StateFeedbackController<4, 2, 2>>(new StateFeedbackController<4, 2, 2>(MakeDrivetrainHighLowController()));
+  controllers[3] = ::std::unique_ptr<StateFeedbackController<4, 2, 2>>(new StateFeedbackController<4, 2, 2>(MakeDrivetrainHighHighController()));
+  return StateFeedbackLoop<4, 2, 2>(&controllers);
+}
+
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/y2014/control_loops/drivetrain/drivetrain_dog_motor_plant.h b/y2014/control_loops/drivetrain/drivetrain_dog_motor_plant.h
new file mode 100644
index 0000000..64498dd
--- /dev/null
+++ b/y2014/control_loops/drivetrain/drivetrain_dog_motor_plant.h
@@ -0,0 +1,32 @@
+#ifndef Y2014_CONTROL_LOOPS_DRIVETRAIN_DRIVETRAIN_DOG_MOTOR_PLANT_H_
+#define Y2014_CONTROL_LOOPS_DRIVETRAIN_DRIVETRAIN_DOG_MOTOR_PLANT_H_
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace frc971 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeDrivetrainLowLowPlantCoefficients();
+
+StateFeedbackController<4, 2, 2> MakeDrivetrainLowLowController();
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeDrivetrainLowHighPlantCoefficients();
+
+StateFeedbackController<4, 2, 2> MakeDrivetrainLowHighController();
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeDrivetrainHighLowPlantCoefficients();
+
+StateFeedbackController<4, 2, 2> MakeDrivetrainHighLowController();
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeDrivetrainHighHighPlantCoefficients();
+
+StateFeedbackController<4, 2, 2> MakeDrivetrainHighHighController();
+
+StateFeedbackPlant<4, 2, 2> MakeDrivetrainPlant();
+
+StateFeedbackLoop<4, 2, 2> MakeDrivetrainLoop();
+
+}  // namespace control_loops
+}  // namespace frc971
+
+#endif  // Y2014_CONTROL_LOOPS_DRIVETRAIN_DRIVETRAIN_DOG_MOTOR_PLANT_H_
diff --git a/y2014/control_loops/drivetrain/drivetrain_lib_test.cc b/y2014/control_loops/drivetrain/drivetrain_lib_test.cc
new file mode 100644
index 0000000..e9291d8
--- /dev/null
+++ b/y2014/control_loops/drivetrain/drivetrain_lib_test.cc
@@ -0,0 +1,297 @@
+#include <unistd.h>
+
+#include <memory>
+
+#include "gtest/gtest.h"
+#include "aos/common/network/team_number.h"
+#include "aos/common/queue_testutils.h"
+#include "aos/common/controls/polytope.h"
+#include "aos/common/controls/control_loop_test.h"
+
+#include "y2014/control_loops/drivetrain/drivetrain.q.h"
+#include "y2014/control_loops/drivetrain/drivetrain.h"
+#include "frc971/control_loops/state_feedback_loop.h"
+#include "frc971/control_loops/coerce_goal.h"
+#include "y2014/control_loops/drivetrain/drivetrain_dog_motor_plant.h"
+#include "frc971/queues/gyro.q.h"
+
+
+namespace frc971 {
+namespace control_loops {
+namespace testing {
+
+class Environment : public ::testing::Environment {
+ public:
+  virtual ~Environment() {}
+  // how to set up the environment.
+  virtual void SetUp() {
+    aos::controls::HPolytope<0>::Init();
+  }
+};
+::testing::Environment* const holder_env =
+  ::testing::AddGlobalTestEnvironment(new Environment);
+
+class TeamNumberEnvironment : public ::testing::Environment {
+ public:
+  // Override this to define how to set up the environment.
+  virtual void SetUp() { aos::network::OverrideTeamNumber(971); }
+};
+
+::testing::Environment* const team_number_env =
+    ::testing::AddGlobalTestEnvironment(new TeamNumberEnvironment);
+
+// Class which simulates the drivetrain and sends out queue messages containing
+// the position.
+class DrivetrainSimulation {
+ public:
+  // Constructs a motor simulation.
+  // TODO(aschuh) Do we want to test the clutch one too?
+  DrivetrainSimulation()
+      : drivetrain_plant_(
+            new StateFeedbackPlant<4, 2, 2>(MakeDrivetrainPlant())),
+        my_drivetrain_queue_(".frc971.control_loops.drivetrain",
+                       0x8a8dde77, ".frc971.control_loops.drivetrain.goal",
+                       ".frc971.control_loops.drivetrain.position",
+                       ".frc971.control_loops.drivetrain.output",
+                       ".frc971.control_loops.drivetrain.status") {
+    Reinitialize();
+  }
+
+  // Resets the plant.
+  void Reinitialize() {
+    drivetrain_plant_->mutable_X(0, 0) = 0.0;
+    drivetrain_plant_->mutable_X(1, 0) = 0.0;
+    drivetrain_plant_->mutable_Y() =
+        drivetrain_plant_->C() * drivetrain_plant_->X();
+    last_left_position_ = drivetrain_plant_->Y(0, 0);
+    last_right_position_ = drivetrain_plant_->Y(1, 0);
+  }
+
+  // Returns the position of the drivetrain.
+  double GetLeftPosition() const { return drivetrain_plant_->Y(0, 0); }
+  double GetRightPosition() const { return drivetrain_plant_->Y(1, 0); }
+
+  // Sends out the position queue messages.
+  void SendPositionMessage() {
+    const double left_encoder = GetLeftPosition();
+    const double right_encoder = GetRightPosition();
+
+    ::aos::ScopedMessagePtr<control_loops::DrivetrainQueue::Position> position =
+        my_drivetrain_queue_.position.MakeMessage();
+    position->left_encoder = left_encoder;
+    position->right_encoder = right_encoder;
+    position.Send();
+  }
+
+  // Simulates the drivetrain moving for one timestep.
+  void Simulate() {
+    last_left_position_ = drivetrain_plant_->Y(0, 0);
+    last_right_position_ = drivetrain_plant_->Y(1, 0);
+    EXPECT_TRUE(my_drivetrain_queue_.output.FetchLatest());
+    drivetrain_plant_->mutable_U() << my_drivetrain_queue_.output->left_voltage,
+        my_drivetrain_queue_.output->right_voltage;
+    drivetrain_plant_->Update();
+  }
+
+  ::std::unique_ptr<StateFeedbackPlant<4, 2, 2>> drivetrain_plant_;
+ private:
+  DrivetrainQueue my_drivetrain_queue_;
+  double last_left_position_;
+  double last_right_position_;
+};
+
+class DrivetrainTest : public ::aos::testing::ControlLoopTest {
+ protected:
+  // Create a new instance of the test queue so that it invalidates the queue
+  // that it points to.  Otherwise, we will have a pointer to shared memory that
+  // is no longer valid.
+  DrivetrainQueue my_drivetrain_queue_;
+
+  // Create a loop and simulation plant.
+  DrivetrainLoop drivetrain_motor_;
+  DrivetrainSimulation drivetrain_motor_plant_;
+
+  DrivetrainTest() : my_drivetrain_queue_(".frc971.control_loops.drivetrain",
+                               0x8a8dde77,
+                               ".frc971.control_loops.drivetrain.goal",
+                               ".frc971.control_loops.drivetrain.position",
+                               ".frc971.control_loops.drivetrain.output",
+                               ".frc971.control_loops.drivetrain.status"),
+                drivetrain_motor_(&my_drivetrain_queue_),
+                drivetrain_motor_plant_() {
+    ::frc971::sensors::gyro_reading.Clear();
+  }
+
+  void VerifyNearGoal() {
+    my_drivetrain_queue_.goal.FetchLatest();
+    my_drivetrain_queue_.position.FetchLatest();
+    EXPECT_NEAR(my_drivetrain_queue_.goal->left_goal,
+                drivetrain_motor_plant_.GetLeftPosition(),
+                1e-2);
+    EXPECT_NEAR(my_drivetrain_queue_.goal->right_goal,
+                drivetrain_motor_plant_.GetRightPosition(),
+                1e-2);
+  }
+
+  virtual ~DrivetrainTest() {
+    ::frc971::sensors::gyro_reading.Clear();
+  }
+};
+
+// Tests that the drivetrain converges on a goal.
+TEST_F(DrivetrainTest, ConvergesCorrectly) {
+  my_drivetrain_queue_.goal.MakeWithBuilder().control_loop_driving(true)
+      .left_goal(-1.0)
+      .right_goal(1.0).Send();
+  for (int i = 0; i < 200; ++i) {
+    drivetrain_motor_plant_.SendPositionMessage();
+    drivetrain_motor_.Iterate();
+    drivetrain_motor_plant_.Simulate();
+    SimulateTimestep(true);
+  }
+  VerifyNearGoal();
+}
+
+// Tests that it survives disabling.
+TEST_F(DrivetrainTest, SurvivesDisabling) {
+  my_drivetrain_queue_.goal.MakeWithBuilder().control_loop_driving(true)
+      .left_goal(-1.0)
+      .right_goal(1.0).Send();
+  for (int i = 0; i < 500; ++i) {
+    drivetrain_motor_plant_.SendPositionMessage();
+    drivetrain_motor_.Iterate();
+    drivetrain_motor_plant_.Simulate();
+    if (i > 20 && i < 200) {
+      SimulateTimestep(false);
+    } else {
+      SimulateTimestep(true);
+    }
+  }
+  VerifyNearGoal();
+}
+
+// Tests that never having a goal doesn't break.
+TEST_F(DrivetrainTest, NoGoalStart) {
+  for (int i = 0; i < 20; ++i) {
+    drivetrain_motor_plant_.SendPositionMessage();
+    drivetrain_motor_.Iterate();
+    drivetrain_motor_plant_.Simulate();
+  }
+}
+
+// Tests that never having a goal, but having driver's station messages, doesn't
+// break.
+TEST_F(DrivetrainTest, NoGoalWithRobotState) {
+  for (int i = 0; i < 20; ++i) {
+    drivetrain_motor_plant_.SendPositionMessage();
+    drivetrain_motor_.Iterate();
+    drivetrain_motor_plant_.Simulate();
+    SimulateTimestep(true);
+  }
+}
+
+::aos::controls::HPolytope<2> MakeBox(double x1_min, double x1_max,
+                                      double x2_min, double x2_max) {
+  Eigen::Matrix<double, 4, 2> box_H;
+  box_H << /*[[*/ 1.0, 0.0 /*]*/,
+            /*[*/-1.0, 0.0 /*]*/,
+            /*[*/ 0.0, 1.0 /*]*/,
+            /*[*/ 0.0,-1.0 /*]]*/;
+  Eigen::Matrix<double, 4, 1> box_k;
+  box_k << /*[[*/ x1_max /*]*/,
+            /*[*/-x1_min /*]*/,
+            /*[*/ x2_max /*]*/,
+            /*[*/-x2_min /*]]*/;
+  ::aos::controls::HPolytope<2> t_poly(box_H, box_k);
+  return t_poly;
+}
+
+class CoerceGoalTest : public ::testing::Test {
+ public:
+  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
+};
+
+// WHOOOHH!
+TEST_F(CoerceGoalTest, Inside) {
+  ::aos::controls::HPolytope<2> box = MakeBox(1, 2, 1, 2);
+
+  Eigen::Matrix<double, 1, 2> K;
+  K << /*[[*/ 1, -1 /*]]*/;
+
+  Eigen::Matrix<double, 2, 1> R;
+  R << /*[[*/ 1.5, 1.5 /*]]*/;
+
+  Eigen::Matrix<double, 2, 1> output =
+      ::frc971::control_loops::CoerceGoal(box, K, 0, R);
+
+  EXPECT_EQ(R(0, 0), output(0, 0));
+  EXPECT_EQ(R(1, 0), output(1, 0));
+}
+
+TEST_F(CoerceGoalTest, Outside_Inside_Intersect) {
+  ::aos::controls::HPolytope<2> box = MakeBox(1, 2, 1, 2);
+
+  Eigen::Matrix<double, 1, 2> K;
+  K << 1, -1;
+
+  Eigen::Matrix<double, 2, 1> R;
+  R << 5, 5;
+
+  Eigen::Matrix<double, 2, 1> output =
+      ::frc971::control_loops::CoerceGoal(box, K, 0, R);
+
+  EXPECT_EQ(2.0, output(0, 0));
+  EXPECT_EQ(2.0, output(1, 0));
+}
+
+TEST_F(CoerceGoalTest, Outside_Inside_no_Intersect) {
+  ::aos::controls::HPolytope<2> box = MakeBox(3, 4, 1, 2);
+
+  Eigen::Matrix<double, 1, 2> K;
+  K << 1, -1;
+
+  Eigen::Matrix<double, 2, 1> R;
+  R << 5, 5;
+
+  Eigen::Matrix<double, 2, 1> output =
+      ::frc971::control_loops::CoerceGoal(box, K, 0, R);
+
+  EXPECT_EQ(3.0, output(0, 0));
+  EXPECT_EQ(2.0, output(1, 0));
+}
+
+TEST_F(CoerceGoalTest, Middle_Of_Edge) {
+  ::aos::controls::HPolytope<2> box = MakeBox(0, 4, 1, 2);
+
+  Eigen::Matrix<double, 1, 2> K;
+  K << -1, 1;
+
+  Eigen::Matrix<double, 2, 1> R;
+  R << 5, 5;
+
+  Eigen::Matrix<double, 2, 1> output =
+      ::frc971::control_loops::CoerceGoal(box, K, 0, R);
+
+  EXPECT_EQ(2.0, output(0, 0));
+  EXPECT_EQ(2.0, output(1, 0));
+}
+
+TEST_F(CoerceGoalTest, PerpendicularLine) {
+  ::aos::controls::HPolytope<2> box = MakeBox(1, 2, 1, 2);
+
+  Eigen::Matrix<double, 1, 2> K;
+  K << 1, 1;
+
+  Eigen::Matrix<double, 2, 1> R;
+  R << 5, 5;
+
+  Eigen::Matrix<double, 2, 1> output =
+      ::frc971::control_loops::CoerceGoal(box, K, 0, R);
+
+  EXPECT_EQ(1.0, output(0, 0));
+  EXPECT_EQ(1.0, output(1, 0));
+}
+
+}  // namespace testing
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/y2014/control_loops/drivetrain/drivetrain_main.cc b/y2014/control_loops/drivetrain/drivetrain_main.cc
new file mode 100644
index 0000000..9a2ebe1
--- /dev/null
+++ b/y2014/control_loops/drivetrain/drivetrain_main.cc
@@ -0,0 +1,11 @@
+#include "y2014/control_loops/drivetrain/drivetrain.h"
+
+#include "aos/linux_code/init.h"
+
+int main() {
+  ::aos::Init();
+  frc971::control_loops::DrivetrainLoop drivetrain;
+  drivetrain.Run();
+  ::aos::Cleanup();
+  return 0;
+}
diff --git a/y2014/control_loops/drivetrain/polydrivetrain_cim_plant.cc b/y2014/control_loops/drivetrain/polydrivetrain_cim_plant.cc
new file mode 100644
index 0000000..0ee9a7a
--- /dev/null
+++ b/y2014/control_loops/drivetrain/polydrivetrain_cim_plant.cc
@@ -0,0 +1,49 @@
+#include "y2014/control_loops/drivetrain/polydrivetrain_cim_plant.h"
+
+#include <vector>
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace frc971 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<1, 1, 1> MakeCIMPlantCoefficients() {
+  Eigen::Matrix<double, 1, 1> A;
+  A << 0.614537580221;
+  Eigen::Matrix<double, 1, 1> B;
+  B << 15.9657598852;
+  Eigen::Matrix<double, 1, 1> C;
+  C << 1;
+  Eigen::Matrix<double, 1, 1> D;
+  D << 0;
+  Eigen::Matrix<double, 1, 1> U_max;
+  U_max << 12.0;
+  Eigen::Matrix<double, 1, 1> U_min;
+  U_min << -12.0;
+  return StateFeedbackPlantCoefficients<1, 1, 1>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackController<1, 1, 1> MakeCIMController() {
+  Eigen::Matrix<double, 1, 1> L;
+  L << 0.604537580221;
+  Eigen::Matrix<double, 1, 1> K;
+  K << 0.0378646293422;
+  Eigen::Matrix<double, 1, 1> A_inv;
+  A_inv << 1.62723978514;
+  return StateFeedbackController<1, 1, 1>(L, K, A_inv, MakeCIMPlantCoefficients());
+}
+
+StateFeedbackPlant<1, 1, 1> MakeCIMPlant() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackPlantCoefficients<1, 1, 1>>> plants(1);
+  plants[0] = ::std::unique_ptr<StateFeedbackPlantCoefficients<1, 1, 1>>(new StateFeedbackPlantCoefficients<1, 1, 1>(MakeCIMPlantCoefficients()));
+  return StateFeedbackPlant<1, 1, 1>(&plants);
+}
+
+StateFeedbackLoop<1, 1, 1> MakeCIMLoop() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackController<1, 1, 1>>> controllers(1);
+  controllers[0] = ::std::unique_ptr<StateFeedbackController<1, 1, 1>>(new StateFeedbackController<1, 1, 1>(MakeCIMController()));
+  return StateFeedbackLoop<1, 1, 1>(&controllers);
+}
+
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/y2014/control_loops/drivetrain/polydrivetrain_cim_plant.h b/y2014/control_loops/drivetrain/polydrivetrain_cim_plant.h
new file mode 100644
index 0000000..62af188
--- /dev/null
+++ b/y2014/control_loops/drivetrain/polydrivetrain_cim_plant.h
@@ -0,0 +1,20 @@
+#ifndef Y2014_CONTROL_LOOPS_DRIVETRAIN_POLYDRIVETRAIN_CIM_PLANT_H_
+#define Y2014_CONTROL_LOOPS_DRIVETRAIN_POLYDRIVETRAIN_CIM_PLANT_H_
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace frc971 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<1, 1, 1> MakeCIMPlantCoefficients();
+
+StateFeedbackController<1, 1, 1> MakeCIMController();
+
+StateFeedbackPlant<1, 1, 1> MakeCIMPlant();
+
+StateFeedbackLoop<1, 1, 1> MakeCIMLoop();
+
+}  // namespace control_loops
+}  // namespace frc971
+
+#endif  // Y2014_CONTROL_LOOPS_DRIVETRAIN_POLYDRIVETRAIN_CIM_PLANT_H_
diff --git a/y2014/control_loops/drivetrain/polydrivetrain_dog_motor_plant.cc b/y2014/control_loops/drivetrain/polydrivetrain_dog_motor_plant.cc
new file mode 100644
index 0000000..a7d80ce
--- /dev/null
+++ b/y2014/control_loops/drivetrain/polydrivetrain_dog_motor_plant.cc
@@ -0,0 +1,133 @@
+#include "y2014/control_loops/drivetrain/polydrivetrain_dog_motor_plant.h"
+
+#include <vector>
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace frc971 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<2, 2, 2> MakeVelocityDrivetrainLowLowPlantCoefficients() {
+  Eigen::Matrix<double, 2, 2> A;
+  A << 0.735841675858, 0.0410810558113, 0.0410810558113, 0.735841675858;
+  Eigen::Matrix<double, 2, 2> B;
+  B << 0.0517213538779, -0.00804353916233, -0.00804353916233, 0.0517213538779;
+  Eigen::Matrix<double, 2, 2> C;
+  C << 1.0, 0.0, 0.0, 1.0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0.0, 0.0, 0.0, 0.0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<2, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackPlantCoefficients<2, 2, 2> MakeVelocityDrivetrainLowHighPlantCoefficients() {
+  Eigen::Matrix<double, 2, 2> A;
+  A << 0.735048848179, 0.0131811893199, 0.045929121897, 0.915703853642;
+  Eigen::Matrix<double, 2, 2> B;
+  B << 0.0518765869984, -0.00481755802263, -0.00899277497558, 0.0308091755839;
+  Eigen::Matrix<double, 2, 2> C;
+  C << 1.0, 0.0, 0.0, 1.0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0.0, 0.0, 0.0, 0.0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<2, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackPlantCoefficients<2, 2, 2> MakeVelocityDrivetrainHighLowPlantCoefficients() {
+  Eigen::Matrix<double, 2, 2> A;
+  A << 0.915703853642, 0.045929121897, 0.0131811893199, 0.735048848179;
+  Eigen::Matrix<double, 2, 2> B;
+  B << 0.0308091755839, -0.00899277497558, -0.00481755802263, 0.0518765869984;
+  Eigen::Matrix<double, 2, 2> C;
+  C << 1.0, 0.0, 0.0, 1.0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0.0, 0.0, 0.0, 0.0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<2, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackPlantCoefficients<2, 2, 2> MakeVelocityDrivetrainHighHighPlantCoefficients() {
+  Eigen::Matrix<double, 2, 2> A;
+  A << 0.915439806567, 0.0146814193986, 0.0146814193986, 0.915439806567;
+  Eigen::Matrix<double, 2, 2> B;
+  B << 0.0309056814511, -0.00536587314624, -0.00536587314624, 0.0309056814511;
+  Eigen::Matrix<double, 2, 2> C;
+  C << 1.0, 0.0, 0.0, 1.0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0.0, 0.0, 0.0, 0.0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<2, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackController<2, 2, 2> MakeVelocityDrivetrainLowLowController() {
+  Eigen::Matrix<double, 2, 2> L;
+  L << 0.715841675858, 0.0410810558113, 0.0410810558113, 0.715841675858;
+  Eigen::Matrix<double, 2, 2> K;
+  K << 2.81809403994, 1.23253744933, 1.23253744933, 2.81809403994;
+  Eigen::Matrix<double, 2, 2> A_inv;
+  A_inv << 1.36323698074, -0.0761076958907, -0.0761076958907, 1.36323698074;
+  return StateFeedbackController<2, 2, 2>(L, K, A_inv, MakeVelocityDrivetrainLowLowPlantCoefficients());
+}
+
+StateFeedbackController<2, 2, 2> MakeVelocityDrivetrainLowHighController() {
+  Eigen::Matrix<double, 2, 2> L;
+  L << 0.715885457343, 0.0459077351335, 0.0459077351335, 0.894867244478;
+  Eigen::Matrix<double, 2, 2> K;
+  K << 2.81810038978, 1.23928174475, 2.31332592354, 10.6088017388;
+  Eigen::Matrix<double, 2, 2> A_inv;
+  A_inv << 1.36167854796, -0.0196008159867, -0.0682979543713, 1.09303924439;
+  return StateFeedbackController<2, 2, 2>(L, K, A_inv, MakeVelocityDrivetrainLowHighPlantCoefficients());
+}
+
+StateFeedbackController<2, 2, 2> MakeVelocityDrivetrainHighLowController() {
+  Eigen::Matrix<double, 2, 2> L;
+  L << 0.902328849033, 0.014581304798, 0.014581304798, 0.708423852788;
+  Eigen::Matrix<double, 2, 2> K;
+  K << 10.6088017388, 2.31332592354, 1.23928174475, 2.81810038978;
+  Eigen::Matrix<double, 2, 2> A_inv;
+  A_inv << 1.09303924439, -0.0682979543713, -0.0196008159867, 1.36167854796;
+  return StateFeedbackController<2, 2, 2>(L, K, A_inv, MakeVelocityDrivetrainHighLowPlantCoefficients());
+}
+
+StateFeedbackController<2, 2, 2> MakeVelocityDrivetrainHighHighController() {
+  Eigen::Matrix<double, 2, 2> L;
+  L << 0.895439806567, 0.0146814193986, 0.0146814193986, 0.895439806567;
+  Eigen::Matrix<double, 2, 2> K;
+  K << 10.6088022944, 2.31694961514, 2.31694961514, 10.6088022944;
+  Eigen::Matrix<double, 2, 2> A_inv;
+  A_inv << 1.0926521463, -0.0175234726538, -0.0175234726538, 1.0926521463;
+  return StateFeedbackController<2, 2, 2>(L, K, A_inv, MakeVelocityDrivetrainHighHighPlantCoefficients());
+}
+
+StateFeedbackPlant<2, 2, 2> MakeVelocityDrivetrainPlant() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackPlantCoefficients<2, 2, 2>>> plants(4);
+  plants[0] = ::std::unique_ptr<StateFeedbackPlantCoefficients<2, 2, 2>>(new StateFeedbackPlantCoefficients<2, 2, 2>(MakeVelocityDrivetrainLowLowPlantCoefficients()));
+  plants[1] = ::std::unique_ptr<StateFeedbackPlantCoefficients<2, 2, 2>>(new StateFeedbackPlantCoefficients<2, 2, 2>(MakeVelocityDrivetrainLowHighPlantCoefficients()));
+  plants[2] = ::std::unique_ptr<StateFeedbackPlantCoefficients<2, 2, 2>>(new StateFeedbackPlantCoefficients<2, 2, 2>(MakeVelocityDrivetrainHighLowPlantCoefficients()));
+  plants[3] = ::std::unique_ptr<StateFeedbackPlantCoefficients<2, 2, 2>>(new StateFeedbackPlantCoefficients<2, 2, 2>(MakeVelocityDrivetrainHighHighPlantCoefficients()));
+  return StateFeedbackPlant<2, 2, 2>(&plants);
+}
+
+StateFeedbackLoop<2, 2, 2> MakeVelocityDrivetrainLoop() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackController<2, 2, 2>>> controllers(4);
+  controllers[0] = ::std::unique_ptr<StateFeedbackController<2, 2, 2>>(new StateFeedbackController<2, 2, 2>(MakeVelocityDrivetrainLowLowController()));
+  controllers[1] = ::std::unique_ptr<StateFeedbackController<2, 2, 2>>(new StateFeedbackController<2, 2, 2>(MakeVelocityDrivetrainLowHighController()));
+  controllers[2] = ::std::unique_ptr<StateFeedbackController<2, 2, 2>>(new StateFeedbackController<2, 2, 2>(MakeVelocityDrivetrainHighLowController()));
+  controllers[3] = ::std::unique_ptr<StateFeedbackController<2, 2, 2>>(new StateFeedbackController<2, 2, 2>(MakeVelocityDrivetrainHighHighController()));
+  return StateFeedbackLoop<2, 2, 2>(&controllers);
+}
+
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/y2014/control_loops/drivetrain/polydrivetrain_dog_motor_plant.h b/y2014/control_loops/drivetrain/polydrivetrain_dog_motor_plant.h
new file mode 100644
index 0000000..dfac7be
--- /dev/null
+++ b/y2014/control_loops/drivetrain/polydrivetrain_dog_motor_plant.h
@@ -0,0 +1,32 @@
+#ifndef Y2014_CONTROL_LOOPS_DRIVETRAIN_POLYDRIVETRAIN_DOG_MOTOR_PLANT_H_
+#define Y2014_CONTROL_LOOPS_DRIVETRAIN_POLYDRIVETRAIN_DOG_MOTOR_PLANT_H_
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace frc971 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<2, 2, 2> MakeVelocityDrivetrainLowLowPlantCoefficients();
+
+StateFeedbackController<2, 2, 2> MakeVelocityDrivetrainLowLowController();
+
+StateFeedbackPlantCoefficients<2, 2, 2> MakeVelocityDrivetrainLowHighPlantCoefficients();
+
+StateFeedbackController<2, 2, 2> MakeVelocityDrivetrainLowHighController();
+
+StateFeedbackPlantCoefficients<2, 2, 2> MakeVelocityDrivetrainHighLowPlantCoefficients();
+
+StateFeedbackController<2, 2, 2> MakeVelocityDrivetrainHighLowController();
+
+StateFeedbackPlantCoefficients<2, 2, 2> MakeVelocityDrivetrainHighHighPlantCoefficients();
+
+StateFeedbackController<2, 2, 2> MakeVelocityDrivetrainHighHighController();
+
+StateFeedbackPlant<2, 2, 2> MakeVelocityDrivetrainPlant();
+
+StateFeedbackLoop<2, 2, 2> MakeVelocityDrivetrainLoop();
+
+}  // namespace control_loops
+}  // namespace frc971
+
+#endif  // Y2014_CONTROL_LOOPS_DRIVETRAIN_POLYDRIVETRAIN_DOG_MOTOR_PLANT_H_
diff --git a/y2014/control_loops/drivetrain/replay_drivetrain.cc b/y2014/control_loops/drivetrain/replay_drivetrain.cc
new file mode 100644
index 0000000..26209fa
--- /dev/null
+++ b/y2014/control_loops/drivetrain/replay_drivetrain.cc
@@ -0,0 +1,24 @@
+#include "aos/common/controls/replay_control_loop.h"
+#include "aos/linux_code/init.h"
+
+#include "y2014/control_loops/drivetrain/drivetrain.q.h"
+
+// Reads one or more log files and sends out all the queue messages (in the
+// correct order and at the correct time) to feed a "live" drivetrain process.
+
+int main(int argc, char **argv) {
+  if (argc <= 1) {
+    fprintf(stderr, "Need at least one file to replay!\n");
+    return EXIT_FAILURE;
+  }
+
+  ::aos::InitNRT();
+
+  ::aos::controls::ControlLoopReplayer<::frc971::control_loops::DrivetrainQueue>
+      replayer(&::frc971::control_loops::drivetrain_queue, "drivetrain");
+  for (int i = 1; i < argc; ++i) {
+    replayer.ProcessFile(argv[i]);
+  }
+
+  ::aos::Cleanup();
+}
diff --git a/y2014/control_loops/python/arm.py b/y2014/control_loops/python/arm.py
new file mode 100755
index 0000000..e17990a
--- /dev/null
+++ b/y2014/control_loops/python/arm.py
@@ -0,0 +1,409 @@
+#!/usr/bin/python
+
+import control_loop
+import controls
+import polytope
+import polydrivetrain
+import numpy
+import math
+import sys
+import matplotlib
+from matplotlib import pylab
+
+
+class Arm(control_loop.ControlLoop):
+  def __init__(self, name="Arm", mass=None):
+    super(Arm, self).__init__(name)
+    # Stall Torque in N m
+    self.stall_torque = 0.476
+    # Stall Current in Amps
+    self.stall_current = 80.730
+    # Free Speed in RPM
+    self.free_speed = 13906.0
+    # Free Current in Amps
+    self.free_current = 5.820
+    # Mass of the arm
+    if mass is None:
+      self.mass = 13.0
+    else:
+      self.mass = mass
+
+    # Resistance of the motor
+    self.R = 12.0 / self.stall_current
+    # Motor velocity constant
+    self.Kv = ((self.free_speed / 60.0 * 2.0 * numpy.pi) /
+               (12.0 - self.R * self.free_current))
+    # Torque constant
+    self.Kt = self.stall_torque / self.stall_current
+    # Gear ratio
+    self.G = (44.0 / 12.0) * (54.0 / 14.0) * (54.0 / 14.0) * (44.0 / 20.0) * (72.0 / 16.0)
+    # Fridge arm length
+    self.r = 32 * 0.0254
+    # Control loop time step
+    self.dt = 0.005
+
+    # Arm moment of inertia
+    self.J = self.r * self.mass
+
+    # Arm left/right spring constant (N*m / radian)
+    self.spring = 100.0
+
+    # State is [average position, average velocity,
+    #           position difference/2, velocity difference/2]
+    # Position difference is 1 - 2
+    # Input is [Voltage 1, Voltage 2]
+
+    self.C1 = self.spring / (self.J * 0.5)
+    self.C2 = self.Kt * self.G / (self.J * 0.5 * self.R)
+    self.C3 = self.G * self.G * self.Kt / (self.R  * self.J * 0.5 * self.Kv)
+
+    self.A_continuous = numpy.matrix(
+        [[0, 1, 0, 0],
+         [0, -self.C3, 0, 0],
+         [0, 0, 0, 1],
+         [0, 0, -self.C1 * 2.0, -self.C3]])
+
+    print 'Full speed is', self.C2 / self.C3 * 12.0
+
+    print 'Stall arm difference is', 12.0 * self.C2 / self.C1
+    print 'Stall arm difference first principles is', self.stall_torque * self.G / self.spring
+
+    print '5 degrees of arm error is', self.spring / self.r * (math.pi * 5.0 / 180.0)
+
+    # Start with the unmodified input
+    self.B_continuous = numpy.matrix(
+        [[0, 0],
+         [self.C2 / 2.0, self.C2 / 2.0],
+         [0, 0],
+         [self.C2 / 2.0, -self.C2 / 2.0]])
+
+    self.C = numpy.matrix([[1, 0, 1, 0],
+                           [1, 0, -1, 0]])
+    self.D = numpy.matrix([[0, 0],
+                           [0, 0]])
+
+    self.A, self.B = self.ContinuousToDiscrete(
+        self.A_continuous, self.B_continuous, self.dt)
+
+    controlability = controls.ctrb(self.A, self.B);
+    print 'Rank of augmented controlability matrix.', numpy.linalg.matrix_rank(
+        controlability)
+
+    q_pos = 0.02
+    q_vel = 0.300
+    q_pos_diff = 0.005
+    q_vel_diff = 0.13
+    self.Q = numpy.matrix([[(1.0 / (q_pos ** 2.0)), 0.0, 0.0, 0.0],
+                           [0.0, (1.0 / (q_vel ** 2.0)), 0.0, 0.0],
+                           [0.0, 0.0, (1.0 / (q_pos_diff ** 2.0)), 0.0],
+                           [0.0, 0.0, 0.0, (1.0 / (q_vel_diff ** 2.0))]])
+
+    self.R = numpy.matrix([[(1.0 / (12.0 ** 2.0)), 0.0],
+                           [0.0, 1.0 / (12.0 ** 2.0)]])
+    self.K = controls.dlqr(self.A, self.B, self.Q, self.R)
+    print 'Controller'
+    print self.K
+
+    print 'Controller Poles'
+    print numpy.linalg.eig(self.A - self.B * self.K)[0]
+
+    self.rpl = 0.20
+    self.ipl = 0.05
+    self.PlaceObserverPoles([self.rpl + 1j * self.ipl,
+                             self.rpl + 1j * self.ipl,
+                             self.rpl - 1j * self.ipl,
+                             self.rpl - 1j * self.ipl])
+
+    # The box formed by U_min and U_max must encompass all possible values,
+    # or else Austin's code gets angry.
+    self.U_max = numpy.matrix([[12.0], [12.0]])
+    self.U_min = numpy.matrix([[-12.0], [-12.0]])
+
+    print 'Observer (Converted to a KF)', numpy.linalg.inv(self.A) * self.L
+
+    self.InitializeState()
+
+
+class IntegralArm(Arm):
+  def __init__(self, name="IntegralArm", mass=None):
+    super(IntegralArm, self).__init__(name=name, mass=mass)
+
+    self.A_continuous_unaugmented = self.A_continuous
+    self.A_continuous = numpy.matrix(numpy.zeros((5, 5)))
+    self.A_continuous[0:4, 0:4] = self.A_continuous_unaugmented
+    self.A_continuous[1, 4] = self.C2
+
+    # Start with the unmodified input
+    self.B_continuous_unaugmented = self.B_continuous
+    self.B_continuous = numpy.matrix(numpy.zeros((5, 2)))
+    self.B_continuous[0:4, 0:2] = self.B_continuous_unaugmented
+
+    self.C_unaugmented = self.C
+    self.C = numpy.matrix(numpy.zeros((2, 5)))
+    self.C[0:2, 0:4] = self.C_unaugmented
+
+    self.A, self.B = self.ContinuousToDiscrete(
+        self.A_continuous, self.B_continuous, self.dt)
+    print 'A cont', self.A_continuous
+    print 'B cont', self.B_continuous
+    print 'A discrete', self.A
+
+    q_pos = 0.08
+    q_vel = 0.40
+
+    q_pos_diff = 0.08
+    q_vel_diff = 0.40
+    q_voltage = 6.0
+    self.Q = numpy.matrix([[(q_pos ** 2.0), 0.0, 0.0, 0.0, 0.0],
+                           [0.0, (q_vel ** 2.0), 0.0, 0.0, 0.0],
+                           [0.0, 0.0, (q_pos_diff ** 2.0), 0.0, 0.0],
+                           [0.0, 0.0, 0.0, (q_vel_diff ** 2.0), 0.0],
+                           [0.0, 0.0, 0.0, 0.0, (q_voltage ** 2.0)]])
+
+    r_volts = 0.05
+    self.R = numpy.matrix([[(r_volts ** 2.0), 0.0],
+                           [0.0, (r_volts ** 2.0)]])
+
+    self.KalmanGain, self.Q_steady = controls.kalman(
+        A=self.A, B=self.B, C=self.C, Q=self.Q, R=self.R)
+
+    self.U_max = numpy.matrix([[12.0], [12.0]])
+    self.U_min = numpy.matrix([[-12.0], [-12.0]])
+
+    self.K_unaugmented = self.K
+    self.K = numpy.matrix(numpy.zeros((2, 5)));
+    self.K[0:2, 0:4] = self.K_unaugmented
+    self.K[0, 4] = 1;
+    self.K[1, 4] = 1;
+    print 'Kal', self.KalmanGain
+    self.L = self.A * self.KalmanGain
+
+    self.InitializeState()
+
+
+def CapU(U):
+  if U[0, 0] - U[1, 0] > 24:
+    return numpy.matrix([[12], [-12]])
+  elif U[0, 0] - U[1, 0] < -24:
+    return numpy.matrix([[-12], [12]])
+  else:
+    max_u = max(U[0, 0], U[1, 0])
+    min_u = min(U[0, 0], U[1, 0])
+    if max_u > 12:
+      return U - (max_u - 12)
+    if min_u < -12:
+      return U - (min_u + 12)
+    return U
+
+
+def run_test(arm, initial_X, goal, max_separation_error=0.01,
+             show_graph=True, iterations=200, controller_arm=None,
+             observer_arm=None):
+  """Runs the arm plant with an initial condition and goal.
+
+    The tests themselves are not terribly sophisticated; I just test for
+    whether the goal has been reached and whether the separation goes
+    outside of the initial and goal values by more than max_separation_error.
+    Prints out something for a failure of either condition and returns
+    False if tests fail.
+    Args:
+      arm: arm object to use.
+      initial_X: starting state.
+      goal: goal state.
+      show_graph: Whether or not to display a graph showing the changing
+           states and voltages.
+      iterations: Number of timesteps to run the model for.
+      controller_arm: arm object to get K from, or None if we should
+          use arm.
+      observer_arm: arm object to use for the observer, or None if we should
+          use the actual state.
+  """
+
+  arm.X = initial_X
+
+  if controller_arm is None:
+    controller_arm = arm
+
+  if observer_arm is not None:
+    observer_arm.X_hat = initial_X + 0.01
+    observer_arm.X_hat = initial_X
+
+  # Various lists for graphing things.
+  t = []
+  x_avg = []
+  x_sep = []
+  x_hat_avg = []
+  x_hat_sep = []
+  v_avg = []
+  v_sep = []
+  u_left = []
+  u_right = []
+
+  sep_plot_gain = 100.0
+
+  for i in xrange(iterations):
+    X_hat = arm.X
+    if observer_arm is not None:
+      X_hat = observer_arm.X_hat
+      x_hat_avg.append(observer_arm.X_hat[0, 0])
+      x_hat_sep.append(observer_arm.X_hat[2, 0] * sep_plot_gain)
+    U = controller_arm.K * (goal - X_hat)
+    U = CapU(U)
+    x_avg.append(arm.X[0, 0])
+    v_avg.append(arm.X[1, 0])
+    x_sep.append(arm.X[2, 0] * sep_plot_gain)
+    v_sep.append(arm.X[3, 0])
+    if observer_arm is not None:
+      observer_arm.PredictObserver(U)
+    arm.Update(U)
+    if observer_arm is not None:
+      observer_arm.Y = arm.Y
+      observer_arm.CorrectObserver(U)
+
+    t.append(i * arm.dt)
+    u_left.append(U[0, 0])
+    u_right.append(U[1, 0])
+
+  print numpy.linalg.inv(arm.A)
+  print "delta time is ", arm.dt
+  print "Velocity at t=0 is ", x_avg[0], v_avg[0], x_sep[0], v_sep[0]
+  print "Velocity at t=1+dt is ", x_avg[1], v_avg[1], x_sep[1], v_sep[1]
+
+  if show_graph:
+    pylab.subplot(2, 1, 1)
+    pylab.plot(t, x_avg, label='x avg')
+    pylab.plot(t, x_sep, label='x sep')
+    if observer_arm is not None:
+      pylab.plot(t, x_hat_avg, label='x_hat avg')
+      pylab.plot(t, x_hat_sep, label='x_hat sep')
+    pylab.legend()
+
+    pylab.subplot(2, 1, 2)
+    pylab.plot(t, u_left, label='u left')
+    pylab.plot(t, u_right, label='u right')
+    pylab.legend()
+    pylab.show()
+
+
+def run_integral_test(arm, initial_X, goal, observer_arm, disturbance,
+                      max_separation_error=0.01, show_graph=True,
+                      iterations=400):
+  """Runs the integral control arm plant with an initial condition and goal.
+
+    The tests themselves are not terribly sophisticated; I just test for
+    whether the goal has been reached and whether the separation goes
+    outside of the initial and goal values by more than max_separation_error.
+    Prints out something for a failure of either condition and returns
+    False if tests fail.
+    Args:
+      arm: arm object to use.
+      initial_X: starting state.
+      goal: goal state.
+      observer_arm: arm object to use for the observer.
+      show_graph: Whether or not to display a graph showing the changing
+           states and voltages.
+      iterations: Number of timesteps to run the model for.
+      disturbance: Voltage missmatch between controller and model.
+  """
+
+  arm.X = initial_X
+
+  # Various lists for graphing things.
+  t = []
+  x_avg = []
+  x_sep = []
+  x_hat_avg = []
+  x_hat_sep = []
+  v_avg = []
+  v_sep = []
+  u_left = []
+  u_right = []
+  u_error = []
+
+  sep_plot_gain = 100.0
+
+  unaugmented_goal = goal
+  goal = numpy.matrix(numpy.zeros((5, 1)))
+  goal[0:4, 0] = unaugmented_goal
+
+  for i in xrange(iterations):
+    X_hat = observer_arm.X_hat[0:4]
+
+    x_hat_avg.append(observer_arm.X_hat[0, 0])
+    x_hat_sep.append(observer_arm.X_hat[2, 0] * sep_plot_gain)
+
+    U = observer_arm.K * (goal - observer_arm.X_hat)
+    u_error.append(observer_arm.X_hat[4,0])
+    U = CapU(U)
+    x_avg.append(arm.X[0, 0])
+    v_avg.append(arm.X[1, 0])
+    x_sep.append(arm.X[2, 0] * sep_plot_gain)
+    v_sep.append(arm.X[3, 0])
+
+    observer_arm.PredictObserver(U)
+
+    arm.Update(U + disturbance)
+    observer_arm.Y = arm.Y
+    observer_arm.CorrectObserver(U)
+
+    t.append(i * arm.dt)
+    u_left.append(U[0, 0])
+    u_right.append(U[1, 0])
+
+  print 'End is', observer_arm.X_hat[4, 0]
+
+  if show_graph:
+    pylab.subplot(2, 1, 1)
+    pylab.plot(t, x_avg, label='x avg')
+    pylab.plot(t, x_sep, label='x sep')
+    if observer_arm is not None:
+      pylab.plot(t, x_hat_avg, label='x_hat avg')
+      pylab.plot(t, x_hat_sep, label='x_hat sep')
+    pylab.legend()
+
+    pylab.subplot(2, 1, 2)
+    pylab.plot(t, u_left, label='u left')
+    pylab.plot(t, u_right, label='u right')
+    pylab.plot(t, u_error, label='u error')
+    pylab.legend()
+    pylab.show()
+
+
+def main(argv):
+  loaded_mass = 25
+  #loaded_mass = 0
+  arm = Arm(mass=13 + loaded_mass)
+  #arm_controller = Arm(mass=13 + 15)
+  #observer_arm = Arm(mass=13 + 15)
+  #observer_arm = None
+
+  integral_arm = IntegralArm(mass=13 + loaded_mass)
+  integral_arm.X_hat[0, 0] += 0.02
+  integral_arm.X_hat[2, 0] += 0.02
+  integral_arm.X_hat[4] = 0
+
+  # Test moving the arm with constant separation.
+  initial_X = numpy.matrix([[0.0], [0.0], [0.0], [0.0]])
+  R = numpy.matrix([[0.0], [0.0], [0.0], [0.0]])
+  run_integral_test(arm, initial_X, R, integral_arm, disturbance=2)
+
+  # Write the generated constants out to a file.
+  if len(argv) != 5:
+    print "Expected .h file name and .cc file name for the arm and augmented arm."
+  else:
+    arm = Arm("Arm", mass=13)
+    loop_writer = control_loop.ControlLoopWriter("Arm", [arm])
+    if argv[1][-3:] == '.cc':
+      loop_writer.Write(argv[2], argv[1])
+    else:
+      loop_writer.Write(argv[1], argv[2])
+
+    integral_arm = IntegralArm("IntegralArm", mass=13)
+    loop_writer = control_loop.ControlLoopWriter("IntegralArm", [integral_arm])
+    if argv[3][-3:] == '.cc':
+      loop_writer.Write(argv[4], argv[3])
+    else:
+      loop_writer.Write(argv[3], argv[4])
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))
diff --git a/y2014/control_loops/python/claw.py b/y2014/control_loops/python/claw.py
new file mode 100755
index 0000000..b5ea6a1
--- /dev/null
+++ b/y2014/control_loops/python/claw.py
@@ -0,0 +1,491 @@
+#!/usr/bin/python
+
+import control_loop
+import controls
+import polytope
+import polydrivetrain
+import numpy
+import sys
+from matplotlib import pylab
+
+class Claw(control_loop.ControlLoop):
+  def __init__(self, name="RawClaw"):
+    super(Claw, self).__init__(name)
+    # Stall Torque in N m
+    self.stall_torque = 2.42
+    # Stall Current in Amps
+    self.stall_current = 133
+    # Free Speed in RPM
+    self.free_speed = 5500.0
+    # Free Current in Amps
+    self.free_current = 2.7
+    # Moment of inertia of the claw in kg m^2
+    self.J_top = 2.8
+    self.J_bottom = 3.0
+
+    # Resistance of the motor
+    self.R = 12.0 / self.stall_current
+    # Motor velocity constant
+    self.Kv = ((self.free_speed / 60.0 * 2.0 * numpy.pi) /
+               (13.5 - self.R * self.free_current))
+    # Torque constant
+    self.Kt = self.stall_torque / self.stall_current
+    # Gear ratio
+    self.G = 14.0 / 48.0 * 18.0 / 32.0 * 18.0 / 66.0 * 12.0 / 60.0
+    # Control loop time step
+    self.dt = 0.01
+
+    # State is [bottom position, bottom velocity, top - bottom position,
+    #           top - bottom velocity]
+    # Input is [bottom power, top power - bottom power * J_top / J_bottom]
+    # Motor time constants. difference_bottom refers to the constant for how the
+    # bottom velocity affects the difference of the top and bottom velocities.
+    self.common_motor_constant = -self.Kt / self.Kv / (self.G * self.G * self.R)
+    self.bottom_bottom = self.common_motor_constant / self.J_bottom
+    self.difference_bottom = -self.common_motor_constant * (1 / self.J_bottom
+                                                        - 1 / self.J_top)
+    self.difference_difference = self.common_motor_constant / self.J_top
+    # State feedback matrices
+
+    self.A_continuous = numpy.matrix(
+        [[0, 0, 1, 0],
+         [0, 0, 0, 1],
+         [0, 0, self.bottom_bottom, 0],
+         [0, 0, self.difference_bottom, self.difference_difference]])
+
+    self.A_bottom_cont = numpy.matrix(
+        [[0, 1],
+         [0, self.bottom_bottom]])
+
+    self.A_diff_cont = numpy.matrix(
+        [[0, 1],
+         [0, self.difference_difference]])
+
+    self.motor_feedforward = self.Kt / (self.G * self.R)
+    self.motor_feedforward_bottom = self.motor_feedforward / self.J_bottom
+    self.motor_feedforward_difference = self.motor_feedforward / self.J_top
+    self.motor_feedforward_difference_bottom = (
+        self.motor_feedforward * (1 / self.J_bottom - 1 / self.J_top))
+    self.B_continuous = numpy.matrix(
+        [[0, 0],
+         [0, 0],
+         [self.motor_feedforward_bottom, 0],
+         [-self.motor_feedforward_bottom, self.motor_feedforward_difference]])
+
+    print "Cont X_ss", self.motor_feedforward / -self.common_motor_constant
+
+    self.B_bottom_cont = numpy.matrix(
+        [[0],
+         [self.motor_feedforward_bottom]])
+
+    self.B_diff_cont = numpy.matrix(
+        [[0],
+         [self.motor_feedforward_difference]])
+
+    self.C = numpy.matrix([[1, 0, 0, 0],
+                           [1, 1, 0, 0]])
+    self.D = numpy.matrix([[0, 0],
+                           [0, 0]])
+
+    self.A, self.B = self.ContinuousToDiscrete(
+        self.A_continuous, self.B_continuous, self.dt)
+
+    self.A_bottom, self.B_bottom = controls.c2d(
+        self.A_bottom_cont, self.B_bottom_cont, self.dt)
+    self.A_diff, self.B_diff = controls.c2d(
+        self.A_diff_cont, self.B_diff_cont, self.dt)
+
+    self.K_bottom = controls.dplace(self.A_bottom, self.B_bottom, [.75 + 0.1j, .75 - 0.1j])
+    self.K_diff = controls.dplace(self.A_diff, self.B_diff, [.75 + 0.1j, .75 - 0.1j])
+
+    print "K_diff", self.K_diff
+    print "K_bottom", self.K_bottom
+
+    print "A"
+    print self.A
+    print "B"
+    print self.B
+
+    
+    self.Q = numpy.matrix([[(1.0 / (0.10 ** 2.0)), 0.0, 0.0, 0.0],
+                           [0.0, (1.0 / (0.06 ** 2.0)), 0.0, 0.0],
+                           [0.0, 0.0, 0.10, 0.0],
+                           [0.0, 0.0, 0.0, 0.1]])
+
+    self.R = numpy.matrix([[(1.0 / (40.0 ** 2.0)), 0.0],
+                           [0.0, (1.0 / (5.0 ** 2.0))]])
+    #self.K = controls.dlqr(self.A, self.B, self.Q, self.R)
+
+    self.K = numpy.matrix([[self.K_bottom[0, 0], 0.0, self.K_bottom[0, 1], 0.0],
+                           [0.0, self.K_diff[0, 0], 0.0, self.K_diff[0, 1]]])
+
+    # Compute the feed forwards aceleration term.
+    self.K[1, 0] = -self.B[1, 0] * self.K[0, 0] / self.B[1, 1]
+
+    lstsq_A = numpy.identity(2)
+    lstsq_A[0, :] = self.B[1, :]
+    lstsq_A[1, :] = self.B[3, :]
+    print "System of Equations coefficients:"
+    print lstsq_A
+    print "det", numpy.linalg.det(lstsq_A)
+
+    out_x = numpy.linalg.lstsq(
+                         lstsq_A,
+                         numpy.matrix([[self.A[1, 2]], [self.A[3, 2]]]))[0]
+    self.K[1, 2] = -lstsq_A[0, 0] * (self.K[0, 2] - out_x[0]) / lstsq_A[0, 1] + out_x[1]
+
+    print "K unaugmented"
+    print self.K
+    print "B * K unaugmented"
+    print self.B * self.K
+    F = self.A - self.B * self.K
+    print "A - B * K unaugmented"
+    print F
+    print "eigenvalues"
+    print numpy.linalg.eig(F)[0]
+
+    self.rpl = .05
+    self.ipl = 0.010
+    self.PlaceObserverPoles([self.rpl + 1j * self.ipl,
+                             self.rpl + 1j * self.ipl,
+                             self.rpl - 1j * self.ipl,
+                             self.rpl - 1j * self.ipl])
+
+    # The box formed by U_min and U_max must encompass all possible values,
+    # or else Austin's code gets angry.
+    self.U_max = numpy.matrix([[12.0], [12.0]])
+    self.U_min = numpy.matrix([[-12.0], [-12.0]])
+
+    # For the tests that check the limits, these are (upper, lower) for both
+    # claws.
+    self.hard_pos_limits = None
+    self.pos_limits = None
+
+    # Compute the steady state velocities for a given applied voltage.
+    # The top and bottom of the claw should spin at the same rate if the
+    # physics is right.
+    X_ss = numpy.matrix([[0], [0], [0.0], [0]])
+    
+    U = numpy.matrix([[1.0],[1.0]])
+    A = self.A
+    B = self.B
+    #X_ss[2, 0] = X_ss[2, 0] * A[2, 2] + B[2, 0] * U[0, 0]
+    X_ss[2, 0] = 1 / (1 - A[2, 2]) * B[2, 0] * U[0, 0]
+    #X_ss[3, 0] = X_ss[3, 0] * A[3, 3] + X_ss[2, 0] * A[3, 2] + B[3, 0] * U[0, 0] + B[3, 1] * U[1, 0]
+    #X_ss[3, 0] * (1 - A[3, 3]) = X_ss[2, 0] * A[3, 2] + B[3, 0] * U[0, 0] + B[3, 1] * U[1, 0]
+    X_ss[3, 0] = 1 / (1 - A[3, 3]) * (X_ss[2, 0] * A[3, 2] + B[3, 1] * U[1, 0] + B[3, 0] * U[0, 0])
+    #X_ss[3, 0] = 1 / (1 - A[3, 3]) / (1 - A[2, 2]) * B[2, 0] * U[0, 0] * A[3, 2] + B[3, 0] * U[0, 0] + B[3, 1] * U[1, 0]
+    X_ss[0, 0] = A[0, 2] * X_ss[2, 0] + B[0, 0] * U[0, 0]
+    X_ss[1, 0] = A[1, 2] * X_ss[2, 0] + A[1, 3] * X_ss[3, 0] + B[1, 0] * U[0, 0] + B[1, 1] * U[1, 0]
+
+    print "X_ss", X_ss
+
+    self.InitializeState()
+
+
+class ClawDeltaU(Claw):
+  def __init__(self, name="Claw"):
+    super(ClawDeltaU, self).__init__(name)
+    A_unaugmented = self.A
+    B_unaugmented = self.B
+    C_unaugmented = self.C
+
+    self.A = numpy.matrix([[0.0, 0.0, 0.0, 0.0, 0.0],
+                           [0.0, 0.0, 0.0, 0.0, 0.0],
+                           [0.0, 0.0, 0.0, 0.0, 0.0],
+                           [0.0, 0.0, 0.0, 0.0, 0.0],
+                           [0.0, 0.0, 0.0, 0.0, 1.0]])
+    self.A[0:4, 0:4] = A_unaugmented
+    self.A[0:4, 4] = B_unaugmented[0:4, 0]
+
+    self.B = numpy.matrix([[0.0, 0.0],
+                           [0.0, 0.0],
+                           [0.0, 0.0],
+                           [0.0, 0.0],
+                           [1.0, 0.0]])
+    self.B[0:4, 1] = B_unaugmented[0:4, 1]
+
+    self.C = numpy.concatenate((C_unaugmented, numpy.matrix([[0.0], [0.0]])),
+                               axis=1)
+    self.D = numpy.matrix([[0.0, 0.0],
+                           [0.0, 0.0]])
+
+    #self.PlaceControllerPoles([0.55, 0.35, 0.55, 0.35, 0.80])
+    self.Q = numpy.matrix([[(1.0 / (0.04 ** 2.0)), 0.0, 0.0, 0.0, 0.0],
+                           [0.0, (1.0 / (0.01 ** 2)), 0.0, 0.0, 0.0],
+                           [0.0, 0.0, 0.01, 0.0, 0.0],
+                           [0.0, 0.0, 0.0, 0.08, 0.0],
+                           [0.0, 0.0, 0.0, 0.0, (1.0 / (10.0 ** 2))]])
+
+    self.R = numpy.matrix([[0.000001, 0.0],
+                           [0.0, 1.0 / (10.0 ** 2.0)]])
+    self.K = controls.dlqr(self.A, self.B, self.Q, self.R)
+
+    self.K = numpy.matrix([[50.0, 0.0, 10.0, 0.0, 1.0],
+                           [50.0, 0.0, 10.0, 0.0, 1.0]])
+    #self.K = numpy.matrix([[50.0, -100.0, 0, -10, 0],
+    #                       [50.0,  100.0, 0, 10, 0]])
+
+    controlability = controls.ctrb(self.A, self.B);
+    print "Rank of augmented controlability matrix.", numpy.linalg.matrix_rank(controlability)
+
+    print "K"
+    print self.K
+    print "Placed controller poles are"
+    print numpy.linalg.eig(self.A - self.B * self.K)[0]
+    print [numpy.abs(x) for x in numpy.linalg.eig(self.A - self.B * self.K)[0]]
+
+    self.rpl = .05
+    self.ipl = 0.008
+    self.PlaceObserverPoles([self.rpl + 1j * self.ipl, 0.10, 0.09,
+                             self.rpl - 1j * self.ipl, 0.90])
+    #print "A is"
+    #print self.A
+    #print "L is"
+    #print self.L
+    #print "C is"
+    #print self.C
+    #print "A - LC is"
+    #print self.A - self.L * self.C
+
+    #print "Placed observer poles are"
+    #print numpy.linalg.eig(self.A - self.L * self.C)[0]
+
+    self.U_max = numpy.matrix([[12.0], [12.0]])
+    self.U_min = numpy.matrix([[-12.0], [-12.0]])
+
+    self.InitializeState()
+
+def ScaleU(claw, U, K, error):
+  """Clips U as necessary.
+
+    Args:
+      claw: claw object containing moments of inertia and U limits.
+      U: Input matrix to clip as necessary.
+  """
+
+  bottom_u = U[0, 0]
+  top_u = U[1, 0]
+  position_error = error[0:2, 0]
+  velocity_error = error[2:, 0]
+
+  U_poly = polytope.HPolytope(
+      numpy.matrix([[1, 0],
+                    [-1, 0],
+                    [0, 1],
+                    [0, -1]]),
+      numpy.matrix([[12],
+                    [12],
+                    [12],
+                    [12]]))
+
+  if (bottom_u > claw.U_max[0, 0] or bottom_u < claw.U_min[0, 0] or
+      top_u > claw.U_max[0, 0] or top_u < claw.U_min[0, 0]):
+
+    position_K = K[:, 0:2]
+    velocity_K = K[:, 2:]
+
+    # H * U <= k
+    # U = UPos + UVel
+    # H * (UPos + UVel) <= k
+    # H * UPos <= k - H * UVel
+    #
+    # Now, we can do a coordinate transformation and say the following.
+    #
+    # UPos = position_K * position_error
+    # (H * position_K) * position_error <= k - H * UVel
+    #
+    # Add in the constraint that 0 <= t <= 1
+    # Now, there are 2 ways this can go.  Either we have a region, or we don't
+    # have a region.  If we have a region, then pick the largest t and go for it.
+    # If we don't have a region, we need to pick a good comprimise.
+
+    pos_poly = polytope.HPolytope(
+        U_poly.H * position_K,
+        U_poly.k - U_poly.H * velocity_K * velocity_error)
+
+    # The actual angle for the line we call 45.
+    angle_45 = numpy.matrix([[numpy.sqrt(3), 1]])
+    if claw.pos_limits and claw.hard_pos_limits and claw.X[0, 0] + claw.X[1, 0] > claw.pos_limits[1]:
+      angle_45 = numpy.matrix([[1, 1]])
+
+    P = position_error
+    L45 = numpy.multiply(numpy.matrix([[numpy.sign(P[1, 0]), -numpy.sign(P[0, 0])]]), angle_45)
+    if L45[0, 1] == 0:
+      L45[0, 1] = 1
+    if L45[0, 0] == 0:
+      L45[0, 0] = 1
+    w45 = numpy.matrix([[0]])
+
+    if numpy.abs(P[0, 0]) > numpy.abs(P[1, 0]):
+      LH = numpy.matrix([[0, 1]])
+    else:
+      LH = numpy.matrix([[1, 0]])
+    wh = LH * P
+    standard = numpy.concatenate((L45, LH))
+    W = numpy.concatenate((w45, wh))
+    intersection = numpy.linalg.inv(standard) * W
+    adjusted_pos_error_h, is_inside_h = polydrivetrain.DoCoerceGoal(pos_poly,
+        LH, wh, position_error)
+    adjusted_pos_error_45, is_inside_45 = polydrivetrain.DoCoerceGoal(pos_poly,
+        L45, w45, intersection)
+    if pos_poly.IsInside(intersection):
+      adjusted_pos_error = adjusted_pos_error_h
+    else:
+      if is_inside_h:
+        if numpy.linalg.norm(adjusted_pos_error_h) > numpy.linalg.norm(adjusted_pos_error_45):
+          adjusted_pos_error = adjusted_pos_error_h
+        else:
+          adjusted_pos_error = adjusted_pos_error_45
+      else:
+        adjusted_pos_error = adjusted_pos_error_45
+    #print adjusted_pos_error
+
+    #print "Actual power is ", velocity_K * velocity_error + position_K * adjusted_pos_error
+    return velocity_K * velocity_error + position_K * adjusted_pos_error
+
+    #U = Kpos * poserror + Kvel * velerror
+      
+    #scalar = claw.U_max[0, 0] / max(numpy.abs(top_u), numpy.abs(bottom_u))
+
+    #top_u *= scalar
+    #bottom_u *= scalar
+
+  return numpy.matrix([[bottom_u], [top_u]])
+
+def run_test(claw, initial_X, goal, max_separation_error=0.01, show_graph=False, iterations=200):
+  """Runs the claw plant on a given claw (claw) with an initial condition (initial_X) and goal (goal).
+
+    The tests themselves are not terribly sophisticated; I just test for 
+    whether the goal has been reached and whether the separation goes
+    outside of the initial and goal values by more than max_separation_error.
+    Prints out something for a failure of either condition and returns
+    False if tests fail.
+    Args:
+      claw: claw object to use.
+      initial_X: starting state.
+      goal: goal state.
+      show_graph: Whether or not to display a graph showing the changing
+           states and voltages.
+      iterations: Number of timesteps to run the model for."""
+
+  claw.X = initial_X
+
+  # Various lists for graphing things.
+  t = []
+  x_bottom = []
+  x_top = []
+  u_bottom = []
+  u_top = []
+  x_separation = []
+
+  tests_passed = True
+
+  # Bounds which separation should not exceed.
+  lower_bound = (initial_X[1, 0] if initial_X[1, 0] < goal[1, 0]
+                 else goal[1, 0]) - max_separation_error
+  upper_bound = (initial_X[1, 0] if initial_X[1, 0] > goal[1, 0]
+                 else goal[1, 0]) + max_separation_error
+
+  for i in xrange(iterations):
+    U = claw.K * (goal - claw.X)
+    U = ScaleU(claw, U, claw.K, goal - claw.X)
+    claw.Update(U)
+
+    if claw.X[1, 0] > upper_bound or claw.X[1, 0] < lower_bound:
+      tests_passed = False
+      print "Claw separation was", claw.X[1, 0]
+      print "Should have been between", lower_bound, "and", upper_bound
+
+    if claw.hard_pos_limits and \
+      (claw.X[0, 0] > claw.hard_pos_limits[1] or
+          claw.X[0, 0] < claw.hard_pos_limits[0] or
+          claw.X[0, 0] + claw.X[1, 0] > claw.hard_pos_limits[1] or
+          claw.X[0, 0] + claw.X[1, 0] < claw.hard_pos_limits[0]):
+      tests_passed = False
+      print "Claws at %f and %f" % (claw.X[0, 0], claw.X[0, 0] + claw.X[1, 0])
+      print "Both should be in %s, definitely %s" % \
+          (claw.pos_limits, claw.hard_pos_limits)
+
+    t.append(i * claw.dt)
+    x_bottom.append(claw.X[0, 0] * 10.0)
+    x_top.append((claw.X[1, 0] + claw.X[0, 0]) * 10.0)
+    u_bottom.append(U[0, 0])
+    u_top.append(U[1, 0])
+    x_separation.append(claw.X[1, 0] * 10.0)
+
+  if show_graph:
+    pylab.plot(t, x_bottom, label='x bottom * 10')
+    pylab.plot(t, x_top, label='x top * 10')
+    pylab.plot(t, u_bottom, label='u bottom')
+    pylab.plot(t, u_top, label='u top')
+    pylab.plot(t, x_separation, label='separation * 10')
+    pylab.legend()
+    pylab.show()
+
+  # Test to make sure that we are near the goal.
+  if numpy.max(abs(claw.X - goal)) > 1e-4:
+    tests_passed = False
+    print "X was", claw.X, "Expected", goal
+
+  return tests_passed
+
+def main(argv):
+  claw = Claw()
+
+  # Test moving the claw with constant separation.
+  initial_X = numpy.matrix([[-1.0], [0.0], [0.0], [0.0]])
+  R = numpy.matrix([[1.0], [0.0], [0.0], [0.0]])
+  run_test(claw, initial_X, R)
+
+  # Test just changing separation.
+  initial_X = numpy.matrix([[0.0], [0.0], [0.0], [0.0]])
+  R = numpy.matrix([[0.0], [1.0], [0.0], [0.0]])
+  run_test(claw, initial_X, R)
+
+  # Test changing both separation and position at once.
+  initial_X = numpy.matrix([[0.0], [0.0], [0.0], [0.0]])
+  R = numpy.matrix([[1.0], [1.0], [0.0], [0.0]])
+  run_test(claw, initial_X, R)
+
+  # Test a small separation error and a large position one.
+  initial_X = numpy.matrix([[0.0], [0.0], [0.0], [0.0]])
+  R = numpy.matrix([[2.0], [0.05], [0.0], [0.0]])
+  run_test(claw, initial_X, R)
+
+  # Test a small separation error and a large position one.
+  initial_X = numpy.matrix([[0.0], [0.0], [0.0], [0.0]])
+  R = numpy.matrix([[-0.5], [1.0], [0.0], [0.0]])
+  run_test(claw, initial_X, R)
+
+  # Test opening with the top claw at the limit.
+  initial_X = numpy.matrix([[0.0], [0.0], [0.0], [0.0]])
+  R = numpy.matrix([[-1.5], [1.5], [0.0], [0.0]])
+  claw.hard_pos_limits = (-1.6, 0.1)
+  claw.pos_limits = (-1.5, 0.0)
+  run_test(claw, initial_X, R)
+  claw.pos_limits = None
+
+  # Test opening with the bottom claw at the limit.
+  initial_X = numpy.matrix([[0.0], [0.0], [0.0], [0.0]])
+  R = numpy.matrix([[0], [1.5], [0.0], [0.0]])
+  claw.hard_pos_limits = (-0.1, 1.6)
+  claw.pos_limits = (0.0, 1.6)
+  run_test(claw, initial_X, R)
+  claw.pos_limits = None
+
+  # Write the generated constants out to a file.
+  if len(argv) != 3:
+    print "Expected .h file name and .cc file name for the claw."
+  else:
+    claw = Claw("Claw")
+    loop_writer = control_loop.ControlLoopWriter("Claw", [claw])
+    loop_writer.AddConstant(control_loop.Constant("kClawMomentOfInertiaRatio",
+      "%f", claw.J_top / claw.J_bottom))
+    if argv[1][-3:] == '.cc':
+      loop_writer.Write(argv[2], argv[1])
+    else:
+      loop_writer.Write(argv[1], argv[2])
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))
diff --git a/y2014/control_loops/python/drivetrain.py b/y2014/control_loops/python/drivetrain.py
new file mode 100755
index 0000000..ac05a57
--- /dev/null
+++ b/y2014/control_loops/python/drivetrain.py
@@ -0,0 +1,239 @@
+#!/usr/bin/python
+
+import control_loop
+import controls
+import numpy
+import sys
+from matplotlib import pylab
+
+
+class CIM(control_loop.ControlLoop):
+  def __init__(self):
+    super(CIM, self).__init__("CIM")
+    # Stall Torque in N m
+    self.stall_torque = 2.42
+    # Stall Current in Amps
+    self.stall_current = 133
+    # Free Speed in RPM
+    self.free_speed = 4650.0
+    # Free Current in Amps
+    self.free_current = 2.7
+    # Moment of inertia of the CIM in kg m^2
+    self.J = 0.0001
+    # Resistance of the motor, divided by 2 to account for the 2 motors
+    self.R = 12.0 / self.stall_current
+    # Motor velocity constant
+    self.Kv = ((self.free_speed / 60.0 * 2.0 * numpy.pi) /
+              (12.0 - self.R * self.free_current))
+    # Torque constant
+    self.Kt = self.stall_torque / self.stall_current
+    # Control loop time step
+    self.dt = 0.005
+
+    # State feedback matrices
+    self.A_continuous = numpy.matrix(
+        [[-self.Kt / self.Kv / (self.J * self.R)]])
+    self.B_continuous = numpy.matrix(
+        [[self.Kt / (self.J * self.R)]])
+    self.C = numpy.matrix([[1]])
+    self.D = numpy.matrix([[0]])
+
+    self.A, self.B = self.ContinuousToDiscrete(self.A_continuous,
+                                               self.B_continuous, self.dt)
+
+    self.PlaceControllerPoles([0.01])
+    self.PlaceObserverPoles([0.01])
+
+    self.U_max = numpy.matrix([[12.0]])
+    self.U_min = numpy.matrix([[-12.0]])
+
+    self.InitializeState()
+
+
+class Drivetrain(control_loop.ControlLoop):
+  def __init__(self, name="Drivetrain", left_low=True, right_low=True):
+    super(Drivetrain, self).__init__(name)
+    # Stall Torque in N m
+    self.stall_torque = 2.42
+    # Stall Current in Amps
+    self.stall_current = 133.0
+    # Free Speed in RPM. Used number from last year.
+    self.free_speed = 4650.0
+    # Free Current in Amps
+    self.free_current = 2.7
+    # Moment of inertia of the drivetrain in kg m^2
+    # Just borrowed from last year.
+    self.J = 4.5
+    # Mass of the robot, in kg.
+    self.m = 68
+    # Radius of the robot, in meters (from last year).
+    self.rb = 0.617998644 / 2.0
+    # Radius of the wheels, in meters.
+    self.r = .04445
+    # Resistance of the motor, divided by the number of motors.
+    self.R = 12.0 / self.stall_current / 4
+    # Motor velocity constant
+    self.Kv = ((self.free_speed / 60.0 * 2.0 * numpy.pi) /
+               (12.0 - self.R * self.free_current))
+    # Torque constant
+    self.Kt = self.stall_torque / self.stall_current
+    # Gear ratios
+    self.G_low = 18.0 / 60.0 * 18.0 / 50.0
+    self.G_high = 28.0 / 50.0 * 18.0 / 50.0
+    if left_low:
+      self.Gl = self.G_low
+    else:
+      self.Gl = self.G_high
+    if right_low:
+      self.Gr = self.G_low
+    else:
+      self.Gr = self.G_high
+
+    # Control loop time step
+    self.dt = 0.005
+
+    # These describe the way that a given side of a robot will be influenced
+    # by the other side. Units of 1 / kg.
+    self.msp = 1.0 / self.m + self.rb * self.rb / self.J
+    self.msn = 1.0 / self.m - self.rb * self.rb / self.J
+    # The calculations which we will need for A and B.
+    self.tcl = -self.Kt / self.Kv / (self.Gl * self.Gl * self.R * self.r * self.r)
+    self.tcr = -self.Kt / self.Kv / (self.Gr * self.Gr * self.R * self.r * self.r)
+    self.mpl = self.Kt / (self.Gl * self.R * self.r)
+    self.mpr = self.Kt / (self.Gr * self.R * self.r)
+
+    # State feedback matrices
+    # X will be of the format
+    # [[positionl], [velocityl], [positionr], velocityr]]
+    self.A_continuous = numpy.matrix(
+        [[0, 1, 0, 0],
+         [0, self.msp * self.tcl, 0, self.msn * self.tcr],
+         [0, 0, 0, 1],
+         [0, self.msn * self.tcl, 0, self.msp * self.tcr]])
+    self.B_continuous = numpy.matrix(
+        [[0, 0],
+         [self.msp * self.mpl, self.msn * self.mpr],
+         [0, 0],
+         [self.msn * self.mpl, self.msp * self.mpr]])
+    self.C = numpy.matrix([[1, 0, 0, 0],
+                           [0, 0, 1, 0]])
+    self.D = numpy.matrix([[0, 0],
+                           [0, 0]])
+
+    #print "THE NUMBER I WANT" + str(numpy.linalg.inv(self.A_continuous) * -self.B_continuous * numpy.matrix([[12.0], [12.0]]))
+    self.A, self.B = self.ContinuousToDiscrete(
+        self.A_continuous, self.B_continuous, self.dt)
+
+    # Poles from last year.
+    self.hp = 0.65
+    self.lp = 0.83
+    self.PlaceControllerPoles([self.hp, self.lp, self.hp, self.lp])
+    print self.K
+    q_pos = 0.07
+    q_vel = 1.0
+    self.Q = numpy.matrix([[(1.0 / (q_pos ** 2.0)), 0.0, 0.0, 0.0],
+                           [0.0, (1.0 / (q_vel ** 2.0)), 0.0, 0.0],
+                           [0.0, 0.0, (1.0 / (q_pos ** 2.0)), 0.0],
+                           [0.0, 0.0, 0.0, (1.0 / (q_vel ** 2.0))]])
+
+    self.R = numpy.matrix([[(1.0 / (12.0 ** 2.0)), 0.0],
+                           [0.0, (1.0 / (12.0 ** 2.0))]])
+    self.K = controls.dlqr(self.A, self.B, self.Q, self.R)
+    print self.A
+    print self.B
+    print self.K
+    print numpy.linalg.eig(self.A - self.B * self.K)[0]
+
+    self.hlp = 0.3
+    self.llp = 0.4
+    self.PlaceObserverPoles([self.hlp, self.hlp, self.llp, self.llp])
+
+    self.U_max = numpy.matrix([[12.0], [12.0]])
+    self.U_min = numpy.matrix([[-12.0], [-12.0]])
+    self.InitializeState()
+
+def main(argv):
+  # Simulate the response of the system to a step input.
+  drivetrain = Drivetrain()
+  simulated_left = []
+  simulated_right = []
+  for _ in xrange(100):
+    drivetrain.Update(numpy.matrix([[12.0], [12.0]]))
+    simulated_left.append(drivetrain.X[0, 0])
+    simulated_right.append(drivetrain.X[2, 0])
+
+  #pylab.plot(range(100), simulated_left)
+  #pylab.plot(range(100), simulated_right)
+  #pylab.show()
+
+  # Simulate forwards motion.
+  drivetrain = Drivetrain()
+  close_loop_left = []
+  close_loop_right = []
+  R = numpy.matrix([[1.0], [0.0], [1.0], [0.0]])
+  for _ in xrange(100):
+    U = numpy.clip(drivetrain.K * (R - drivetrain.X_hat),
+                   drivetrain.U_min, drivetrain.U_max)
+    drivetrain.UpdateObserver(U)
+    drivetrain.Update(U)
+    close_loop_left.append(drivetrain.X[0, 0])
+    close_loop_right.append(drivetrain.X[2, 0])
+
+  #pylab.plot(range(100), close_loop_left)
+  #pylab.plot(range(100), close_loop_right)
+  #pylab.show()
+
+  # Try turning in place
+  drivetrain = Drivetrain()
+  close_loop_left = []
+  close_loop_right = []
+  R = numpy.matrix([[-1.0], [0.0], [1.0], [0.0]])
+  for _ in xrange(100):
+    U = numpy.clip(drivetrain.K * (R - drivetrain.X_hat),
+                   drivetrain.U_min, drivetrain.U_max)
+    drivetrain.UpdateObserver(U)
+    drivetrain.Update(U)
+    close_loop_left.append(drivetrain.X[0, 0])
+    close_loop_right.append(drivetrain.X[2, 0])
+
+  #pylab.plot(range(100), close_loop_left)
+  #pylab.plot(range(100), close_loop_right)
+  #pylab.show()
+
+  # Try turning just one side.
+  drivetrain = Drivetrain()
+  close_loop_left = []
+  close_loop_right = []
+  R = numpy.matrix([[0.0], [0.0], [1.0], [0.0]])
+  for _ in xrange(100):
+    U = numpy.clip(drivetrain.K * (R - drivetrain.X_hat),
+                   drivetrain.U_min, drivetrain.U_max)
+    drivetrain.UpdateObserver(U)
+    drivetrain.Update(U)
+    close_loop_left.append(drivetrain.X[0, 0])
+    close_loop_right.append(drivetrain.X[2, 0])
+
+  #pylab.plot(range(100), close_loop_left)
+  #pylab.plot(range(100), close_loop_right)
+  #pylab.show()
+
+  # Write the generated constants out to a file.
+  print "Output one"
+  drivetrain_low_low = Drivetrain(name="DrivetrainLowLow", left_low=True, right_low=True)
+  drivetrain_low_high = Drivetrain(name="DrivetrainLowHigh", left_low=True, right_low=False)
+  drivetrain_high_low = Drivetrain(name="DrivetrainHighLow", left_low=False, right_low=True)
+  drivetrain_high_high = Drivetrain(name="DrivetrainHighHigh", left_low=False, right_low=False)
+
+  if len(argv) != 5:
+    print "Expected .h file name and .cc file name"
+  else:
+    dog_loop_writer = control_loop.ControlLoopWriter(
+        "Drivetrain", [drivetrain_low_low, drivetrain_low_high,
+                       drivetrain_high_low, drivetrain_high_high])
+    if argv[1][-3:] == '.cc':
+      dog_loop_writer.Write(argv[2], argv[1])
+    else:
+      dog_loop_writer.Write(argv[1], argv[2])
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))
diff --git a/y2014/control_loops/python/elevator.py b/y2014/control_loops/python/elevator.py
new file mode 100755
index 0000000..fba72c8
--- /dev/null
+++ b/y2014/control_loops/python/elevator.py
@@ -0,0 +1,246 @@
+#!/usr/bin/python
+
+import control_loop
+import controls
+import polytope
+import polydrivetrain
+import numpy
+import sys
+import matplotlib
+from matplotlib import pylab
+
+class Elevator(control_loop.ControlLoop):
+  def __init__(self, name="Elevator", mass=None):
+    super(Elevator, self).__init__(name)
+    # Stall Torque in N m
+    self.stall_torque = 0.476
+    # Stall Current in Amps
+    self.stall_current = 80.730
+    # Free Speed in RPM
+    self.free_speed = 13906.0
+    # Free Current in Amps
+    self.free_current = 5.820
+    # Mass of the elevator
+    if mass is None:
+      self.mass = 13.0
+    else:
+      self.mass = mass
+
+    # Resistance of the motor
+    self.R = 12.0 / self.stall_current
+    # Motor velocity constant
+    self.Kv = ((self.free_speed / 60.0 * 2.0 * numpy.pi) /
+               (12.0 - self.R * self.free_current))
+    # Torque constant
+    self.Kt = self.stall_torque / self.stall_current
+    # Gear ratio
+    self.G = (56.0 / 12.0) * (84.0 / 14.0)
+    # Pulley diameter
+    self.r = 32 * 0.005 / numpy.pi / 2.0
+    # Control loop time step
+    self.dt = 0.005
+
+    # Elevator left/right spring constant (N/m)
+    self.spring = 800.0
+
+    # State is [average position, average velocity,
+    #           position difference/2, velocity difference/2]
+    # Input is [V_left, V_right]
+
+    C1 = self.spring / (self.mass * 0.5)
+    C2 = self.Kt * self.G / (self.mass * 0.5 * self.r * self.R)
+    C3 = self.G * self.G * self.Kt / (
+        self.R  * self.r * self.r * self.mass * 0.5 * self.Kv)
+
+    self.A_continuous = numpy.matrix(
+        [[0, 1, 0, 0],
+         [0, -C3, 0, 0],
+         [0, 0, 0, 1],
+         [0, 0, -C1 * 2.0, -C3]])
+
+    print "Full speed is", C2 / C3 * 12.0
+
+    # Start with the unmodified input
+    self.B_continuous = numpy.matrix(
+        [[0, 0],
+         [C2 / 2.0, C2 / 2.0],
+         [0, 0],
+         [C2 / 2.0, -C2 / 2.0]])
+
+    self.C = numpy.matrix([[1, 0, 1, 0],
+                           [1, 0, -1, 0]])
+    self.D = numpy.matrix([[0, 0],
+                           [0, 0]])
+
+    self.A, self.B = self.ContinuousToDiscrete(
+        self.A_continuous, self.B_continuous, self.dt)
+
+    print self.A
+
+    controlability = controls.ctrb(self.A, self.B);
+    print "Rank of augmented controlability matrix.", numpy.linalg.matrix_rank(
+        controlability)
+
+    q_pos = 0.02
+    q_vel = 0.400
+    q_pos_diff = 0.01
+    q_vel_diff = 0.45
+    self.Q = numpy.matrix([[(1.0 / (q_pos ** 2.0)), 0.0, 0.0, 0.0],
+                           [0.0, (1.0 / (q_vel ** 2.0)), 0.0, 0.0],
+                           [0.0, 0.0, (1.0 / (q_pos_diff ** 2.0)), 0.0],
+                           [0.0, 0.0, 0.0, (1.0 / (q_vel_diff ** 2.0))]])
+
+    self.R = numpy.matrix([[(1.0 / (12.0 ** 2.0)), 0.0],
+                           [0.0, 1.0 / (12.0 ** 2.0)]])
+    self.K = controls.dlqr(self.A, self.B, self.Q, self.R)
+    print self.K
+
+    print numpy.linalg.eig(self.A - self.B * self.K)[0]
+
+    self.rpl = 0.20
+    self.ipl = 0.05
+    self.PlaceObserverPoles([self.rpl + 1j * self.ipl,
+                             self.rpl + 1j * self.ipl,
+                             self.rpl - 1j * self.ipl,
+                             self.rpl - 1j * self.ipl])
+
+    # The box formed by U_min and U_max must encompass all possible values,
+    # or else Austin's code gets angry.
+    self.U_max = numpy.matrix([[12.0], [12.0]])
+    self.U_min = numpy.matrix([[-12.0], [-12.0]])
+
+    self.InitializeState()
+
+
+def CapU(U):
+  if U[0, 0] - U[1, 0] > 24:
+    return numpy.matrix([[12], [-12]])
+  elif U[0, 0] - U[1, 0] < -24:
+    return numpy.matrix([[-12], [12]])
+  else:
+    max_u = max(U[0, 0], U[1, 0])
+    min_u = min(U[0, 0], U[1, 0])
+    if max_u > 12:
+      return U - (max_u - 12)
+    if min_u < -12:
+      return U - (min_u + 12)
+    return U
+
+
+def run_test(elevator, initial_X, goal, max_separation_error=0.01,
+             show_graph=True, iterations=200, controller_elevator=None,
+             observer_elevator=None):
+  """Runs the elevator plant with an initial condition and goal.
+
+    The tests themselves are not terribly sophisticated; I just test for
+    whether the goal has been reached and whether the separation goes
+    outside of the initial and goal values by more than max_separation_error.
+    Prints out something for a failure of either condition and returns
+    False if tests fail.
+    Args:
+      elevator: elevator object to use.
+      initial_X: starting state.
+      goal: goal state.
+      show_graph: Whether or not to display a graph showing the changing
+           states and voltages.
+      iterations: Number of timesteps to run the model for.
+      controller_elevator: elevator object to get K from, or None if we should
+          use elevator.
+      observer_elevator: elevator object to use for the observer, or None if we
+          should use the actual state.
+  """
+
+  elevator.X = initial_X
+
+  if controller_elevator is None:
+    controller_elevator = elevator
+
+  if observer_elevator is not None:
+    observer_elevator.X_hat = initial_X + 0.01
+    observer_elevator.X_hat = initial_X
+
+  # Various lists for graphing things.
+  t = []
+  x_avg = []
+  x_sep = []
+  x_hat_avg = []
+  x_hat_sep = []
+  v_avg = []
+  v_sep = []
+  u_left = []
+  u_right = []
+
+  sep_plot_gain = 100.0
+
+  for i in xrange(iterations):
+    X_hat = elevator.X
+    if observer_elevator is not None:
+      X_hat = observer_elevator.X_hat
+      x_hat_avg.append(observer_elevator.X_hat[0, 0])
+      x_hat_sep.append(observer_elevator.X_hat[2, 0] * sep_plot_gain)
+    U = controller_elevator.K * (goal - X_hat)
+    U = CapU(U)
+    x_avg.append(elevator.X[0, 0])
+    v_avg.append(elevator.X[1, 0])
+    x_sep.append(elevator.X[2, 0] * sep_plot_gain)
+    v_sep.append(elevator.X[3, 0])
+    if observer_elevator is not None:
+      observer_elevator.PredictObserver(U)
+    elevator.Update(U)
+    if observer_elevator is not None:
+      observer_elevator.Y = elevator.Y
+      observer_elevator.CorrectObserver(U)
+
+    t.append(i * elevator.dt)
+    u_left.append(U[0, 0])
+    u_right.append(U[1, 0])
+
+  print numpy.linalg.inv(elevator.A)
+  print "delta time is ", elevator.dt
+  print "Velocity at t=0 is ", x_avg[0], v_avg[0], x_sep[0], v_sep[0]
+  print "Velocity at t=1+dt is ", x_avg[1], v_avg[1], x_sep[1], v_sep[1]
+
+  if show_graph:
+    pylab.subplot(2, 1, 1)
+    pylab.plot(t, x_avg, label='x avg')
+    pylab.plot(t, x_sep, label='x sep')
+    if observer_elevator is not None:
+      pylab.plot(t, x_hat_avg, label='x_hat avg')
+      pylab.plot(t, x_hat_sep, label='x_hat sep')
+    pylab.legend()
+
+    pylab.subplot(2, 1, 2)
+    pylab.plot(t, u_left, label='u left')
+    pylab.plot(t, u_right, label='u right')
+    pylab.legend()
+    pylab.show()
+
+
+def main(argv):
+  loaded_mass = 25
+  #loaded_mass = 0
+  elevator = Elevator(mass=13 + loaded_mass)
+  elevator_controller = Elevator(mass=13 + 15)
+  observer_elevator = Elevator(mass=13 + 15)
+  #observer_elevator = None
+
+  # Test moving the elevator with constant separation.
+  initial_X = numpy.matrix([[0.0], [0.0], [0.01], [0.0]])
+  #initial_X = numpy.matrix([[0.0], [0.0], [0.00], [0.0]])
+  R = numpy.matrix([[1.0], [0.0], [0.0], [0.0]])
+  run_test(elevator, initial_X, R, controller_elevator=elevator_controller,
+           observer_elevator=observer_elevator)
+
+  # Write the generated constants out to a file.
+  if len(argv) != 3:
+    print "Expected .h file name and .cc file name for the elevator."
+  else:
+    elevator = Elevator("Elevator")
+    loop_writer = control_loop.ControlLoopWriter("Elevator", [elevator])
+    if argv[1][-3:] == '.cc':
+      loop_writer.Write(argv[2], argv[1])
+    else:
+      loop_writer.Write(argv[1], argv[2])
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))
diff --git a/y2014/control_loops/python/polydrivetrain.py b/y2014/control_loops/python/polydrivetrain.py
new file mode 100755
index 0000000..a2c63fa
--- /dev/null
+++ b/y2014/control_loops/python/polydrivetrain.py
@@ -0,0 +1,503 @@
+#!/usr/bin/python
+
+import numpy
+import sys
+import polytope
+import drivetrain
+import control_loop
+import controls
+from matplotlib import pylab
+
+__author__ = 'Austin Schuh (austin.linux@gmail.com)'
+
+
+def CoerceGoal(region, K, w, R):
+  """Intersects a line with a region, and finds the closest point to R.
+
+  Finds a point that is closest to R inside the region, and on the line
+  defined by K X = w.  If it is not possible to find a point on the line,
+  finds a point that is inside the region and closest to the line.  This
+  function assumes that
+
+  Args:
+    region: HPolytope, the valid goal region.
+    K: numpy.matrix (2 x 1), the matrix for the equation [K1, K2] [x1; x2] = w
+    w: float, the offset in the equation above.
+    R: numpy.matrix (2 x 1), the point to be closest to.
+
+  Returns:
+    numpy.matrix (2 x 1), the point.
+  """
+  return DoCoerceGoal(region, K, w, R)[0]
+
+def DoCoerceGoal(region, K, w, R):
+  if region.IsInside(R):
+    return (R, True)
+
+  perpendicular_vector = K.T / numpy.linalg.norm(K)
+  parallel_vector = numpy.matrix([[perpendicular_vector[1, 0]],
+                                  [-perpendicular_vector[0, 0]]])
+
+  # We want to impose the constraint K * X = w on the polytope H * X <= k.
+  # We do this by breaking X up into parallel and perpendicular components to
+  # the half plane.  This gives us the following equation.
+  #
+  #  parallel * (parallel.T \dot X) + perpendicular * (perpendicular \dot X)) = X
+  #
+  # Then, substitute this into the polytope.
+  #
+  #  H * (parallel * (parallel.T \dot X) + perpendicular * (perpendicular \dot X)) <= k
+  #
+  # Substitute K * X = w
+  #
+  # H * parallel * (parallel.T \dot X) + H * perpendicular * w <= k
+  #
+  # Move all the knowns to the right side.
+  #
+  # H * parallel * ([parallel1 parallel2] * X) <= k - H * perpendicular * w
+  #
+  # Let t = parallel.T \dot X, the component parallel to the surface.
+  #
+  # H * parallel * t <= k - H * perpendicular * w
+  #
+  # This is a polytope which we can solve, and use to figure out the range of X
+  # that we care about!
+
+  t_poly = polytope.HPolytope(
+      region.H * parallel_vector,
+      region.k - region.H * perpendicular_vector * w)
+
+  vertices = t_poly.Vertices()
+
+  if vertices.shape[0]:
+    # The region exists!
+    # Find the closest vertex
+    min_distance = numpy.infty
+    closest_point = None
+    for vertex in vertices:
+      point = parallel_vector * vertex + perpendicular_vector * w
+      length = numpy.linalg.norm(R - point)
+      if length < min_distance:
+        min_distance = length
+        closest_point = point
+
+    return (closest_point, True)
+  else:
+    # Find the vertex of the space that is closest to the line.
+    region_vertices = region.Vertices()
+    min_distance = numpy.infty
+    closest_point = None
+    for vertex in region_vertices:
+      point = vertex.T
+      length = numpy.abs((perpendicular_vector.T * point)[0, 0])
+      if length < min_distance:
+        min_distance = length
+        closest_point = point
+
+    return (closest_point, False)
+
+
+class VelocityDrivetrainModel(control_loop.ControlLoop):
+  def __init__(self, left_low=True, right_low=True, name="VelocityDrivetrainModel"):
+    super(VelocityDrivetrainModel, self).__init__(name)
+    self._drivetrain = drivetrain.Drivetrain(left_low=left_low,
+                                             right_low=right_low)
+    self.dt = 0.01
+    self.A_continuous = numpy.matrix(
+        [[self._drivetrain.A_continuous[1, 1], self._drivetrain.A_continuous[1, 3]],
+         [self._drivetrain.A_continuous[3, 1], self._drivetrain.A_continuous[3, 3]]])
+
+    self.B_continuous = numpy.matrix(
+        [[self._drivetrain.B_continuous[1, 0], self._drivetrain.B_continuous[1, 1]],
+         [self._drivetrain.B_continuous[3, 0], self._drivetrain.B_continuous[3, 1]]])
+    self.C = numpy.matrix(numpy.eye(2));
+    self.D = numpy.matrix(numpy.zeros((2, 2)));
+
+    self.A, self.B = self.ContinuousToDiscrete(self.A_continuous,
+                                               self.B_continuous, self.dt)
+
+    # FF * X = U (steady state)
+    self.FF = self.B.I * (numpy.eye(2) - self.A)
+
+    self.PlaceControllerPoles([0.6, 0.6])
+    self.PlaceObserverPoles([0.02, 0.02])
+
+    self.G_high = self._drivetrain.G_high
+    self.G_low = self._drivetrain.G_low
+    self.R = self._drivetrain.R
+    self.r = self._drivetrain.r
+    self.Kv = self._drivetrain.Kv
+    self.Kt = self._drivetrain.Kt
+
+    self.U_max = self._drivetrain.U_max
+    self.U_min = self._drivetrain.U_min
+
+
+class VelocityDrivetrain(object):
+  HIGH = 'high'
+  LOW = 'low'
+  SHIFTING_UP = 'up'
+  SHIFTING_DOWN = 'down'
+
+  def __init__(self):
+    self.drivetrain_low_low = VelocityDrivetrainModel(
+        left_low=True, right_low=True, name='VelocityDrivetrainLowLow')
+    self.drivetrain_low_high = VelocityDrivetrainModel(left_low=True, right_low=False, name='VelocityDrivetrainLowHigh')
+    self.drivetrain_high_low = VelocityDrivetrainModel(left_low=False, right_low=True, name = 'VelocityDrivetrainHighLow')
+    self.drivetrain_high_high = VelocityDrivetrainModel(left_low=False, right_low=False, name = 'VelocityDrivetrainHighHigh')
+
+    # X is [lvel, rvel]
+    self.X = numpy.matrix(
+        [[0.0],
+         [0.0]])
+
+    self.U_poly = polytope.HPolytope(
+        numpy.matrix([[1, 0],
+                      [-1, 0],
+                      [0, 1],
+                      [0, -1]]),
+        numpy.matrix([[12],
+                      [12],
+                      [12],
+                      [12]]))
+
+    self.U_max = numpy.matrix(
+        [[12.0],
+         [12.0]])
+    self.U_min = numpy.matrix(
+        [[-12.0000000000],
+         [-12.0000000000]])
+
+    self.dt = 0.01
+
+    self.R = numpy.matrix(
+        [[0.0],
+         [0.0]])
+
+    # ttrust is the comprimise between having full throttle negative inertia,
+    # and having no throttle negative inertia.  A value of 0 is full throttle
+    # inertia.  A value of 1 is no throttle negative inertia.
+    self.ttrust = 1.0
+
+    self.left_gear = VelocityDrivetrain.LOW
+    self.right_gear = VelocityDrivetrain.LOW
+    self.left_shifter_position = 0.0
+    self.right_shifter_position = 0.0
+    self.left_cim = drivetrain.CIM()
+    self.right_cim = drivetrain.CIM()
+
+  def IsInGear(self, gear):
+    return gear is VelocityDrivetrain.HIGH or gear is VelocityDrivetrain.LOW
+
+  def MotorRPM(self, shifter_position, velocity):
+    if shifter_position > 0.5:
+      return (velocity / self.CurrentDrivetrain().G_high /
+              self.CurrentDrivetrain().r)
+    else:
+      return (velocity / self.CurrentDrivetrain().G_low /
+              self.CurrentDrivetrain().r)
+
+  def CurrentDrivetrain(self):
+    if self.left_shifter_position > 0.5:
+      if self.right_shifter_position > 0.5:
+        return self.drivetrain_high_high
+      else:
+        return self.drivetrain_high_low
+    else:
+      if self.right_shifter_position > 0.5:
+        return self.drivetrain_low_high
+      else:
+        return self.drivetrain_low_low
+
+  def SimShifter(self, gear, shifter_position):
+    if gear is VelocityDrivetrain.HIGH or gear is VelocityDrivetrain.SHIFTING_UP:
+      shifter_position = min(shifter_position + 0.5, 1.0)
+    else:
+      shifter_position = max(shifter_position - 0.5, 0.0)
+
+    if shifter_position == 1.0:
+      gear = VelocityDrivetrain.HIGH
+    elif shifter_position == 0.0:
+      gear = VelocityDrivetrain.LOW
+
+    return gear, shifter_position
+
+  def ComputeGear(self, wheel_velocity, should_print=False, current_gear=False, gear_name=None):
+    high_omega = (wheel_velocity / self.CurrentDrivetrain().G_high /
+                  self.CurrentDrivetrain().r)
+    low_omega = (wheel_velocity / self.CurrentDrivetrain().G_low /
+                 self.CurrentDrivetrain().r)
+    #print gear_name, "Motor Energy Difference.", 0.5 * 0.000140032647 * (low_omega * low_omega - high_omega * high_omega), "joules"
+    high_torque = ((12.0 - high_omega / self.CurrentDrivetrain().Kv) *
+                   self.CurrentDrivetrain().Kt / self.CurrentDrivetrain().R)
+    low_torque = ((12.0 - low_omega / self.CurrentDrivetrain().Kv) *
+                  self.CurrentDrivetrain().Kt / self.CurrentDrivetrain().R)
+    high_power = high_torque * high_omega
+    low_power = low_torque * low_omega
+    #if should_print:
+    #  print gear_name, "High omega", high_omega, "Low omega", low_omega
+    #  print gear_name, "High torque", high_torque, "Low torque", low_torque
+    #  print gear_name, "High power", high_power, "Low power", low_power
+
+    # Shift algorithm improvements.
+    # TODO(aschuh):
+    # It takes time to shift.  Shifting down for 1 cycle doesn't make sense
+    # because you will end up slower than without shifting.  Figure out how
+    # to include that info.
+    # If the driver is still in high gear, but isn't asking for the extra power
+    # from low gear, don't shift until he asks for it.
+    goal_gear_is_high = high_power > low_power
+    #goal_gear_is_high = True
+
+    if not self.IsInGear(current_gear):
+      print gear_name, 'Not in gear.'
+      return current_gear
+    else:
+      is_high = current_gear is VelocityDrivetrain.HIGH
+      if is_high != goal_gear_is_high:
+        if goal_gear_is_high:
+          print gear_name, 'Shifting up.'
+          return VelocityDrivetrain.SHIFTING_UP
+        else:
+          print gear_name, 'Shifting down.'
+          return VelocityDrivetrain.SHIFTING_DOWN
+      else:
+        return current_gear
+
+  def FilterVelocity(self, throttle):
+    # Invert the plant to figure out how the velocity filter would have to work
+    # out in order to filter out the forwards negative inertia.
+    # This math assumes that the left and right power and velocity are equal.
+
+    # The throttle filter should filter such that the motor in the highest gear
+    # should be controlling the time constant.
+    # Do this by finding the index of FF that has the lowest value, and computing
+    # the sums using that index.
+    FF_sum = self.CurrentDrivetrain().FF.sum(axis=1)
+    min_FF_sum_index = numpy.argmin(FF_sum)
+    min_FF_sum = FF_sum[min_FF_sum_index, 0]
+    min_K_sum = self.CurrentDrivetrain().K[min_FF_sum_index, :].sum()
+    # Compute the FF sum for high gear.
+    high_min_FF_sum = self.drivetrain_high_high.FF[0, :].sum()
+
+    # U = self.K[0, :].sum() * (R - x_avg) + self.FF[0, :].sum() * R
+    # throttle * 12.0 = (self.K[0, :].sum() + self.FF[0, :].sum()) * R
+    #                   - self.K[0, :].sum() * x_avg
+
+    # R = (throttle * 12.0 + self.K[0, :].sum() * x_avg) /
+    #     (self.K[0, :].sum() + self.FF[0, :].sum())
+
+    # U = (K + FF) * R - K * X
+    # (K + FF) ^-1 * (U + K * X) = R
+
+    # Scale throttle by min_FF_sum / high_min_FF_sum.  This will make low gear
+    # have the same velocity goal as high gear, and so that the robot will hold
+    # the same speed for the same throttle for all gears.
+    adjusted_ff_voltage = numpy.clip(throttle * 12.0 * min_FF_sum / high_min_FF_sum, -12.0, 12.0)
+    return ((adjusted_ff_voltage + self.ttrust * min_K_sum * (self.X[0, 0] + self.X[1, 0]) / 2.0)
+            / (self.ttrust * min_K_sum + min_FF_sum))
+
+  def Update(self, throttle, steering):
+    # Shift into the gear which sends the most power to the floor.
+    # This is the same as sending the most torque down to the floor at the
+    # wheel.
+
+    self.left_gear = self.right_gear = True
+    if True:
+      self.left_gear = self.ComputeGear(self.X[0, 0], should_print=True,
+                                        current_gear=self.left_gear,
+                                        gear_name="left")
+      self.right_gear = self.ComputeGear(self.X[1, 0], should_print=True,
+                                         current_gear=self.right_gear,
+                                         gear_name="right")
+      if self.IsInGear(self.left_gear):
+        self.left_cim.X[0, 0] = self.MotorRPM(self.left_shifter_position, self.X[0, 0])
+
+      if self.IsInGear(self.right_gear):
+        self.right_cim.X[0, 0] = self.MotorRPM(self.right_shifter_position, self.X[0, 0])
+
+    if self.IsInGear(self.left_gear) and self.IsInGear(self.right_gear):
+      # Filter the throttle to provide a nicer response.
+      fvel = self.FilterVelocity(throttle)
+
+      # Constant radius means that angualar_velocity / linear_velocity = constant.
+      # Compute the left and right velocities.
+      steering_velocity = numpy.abs(fvel) * steering
+      left_velocity = fvel - steering_velocity
+      right_velocity = fvel + steering_velocity
+
+      # Write this constraint in the form of K * R = w
+      # angular velocity / linear velocity = constant
+      # (left - right) / (left + right) = constant
+      # left - right = constant * left + constant * right
+
+      # (fvel - steering * numpy.abs(fvel) - fvel - steering * numpy.abs(fvel)) /
+      #  (fvel - steering * numpy.abs(fvel) + fvel + steering * numpy.abs(fvel)) =
+      #       constant
+      # (- 2 * steering * numpy.abs(fvel)) / (2 * fvel) = constant
+      # (-steering * sign(fvel)) = constant
+      # (-steering * sign(fvel)) * (left + right) = left - right
+      # (steering * sign(fvel) + 1) * left + (steering * sign(fvel) - 1) * right = 0
+
+      equality_k = numpy.matrix(
+          [[1 + steering * numpy.sign(fvel), -(1 - steering * numpy.sign(fvel))]])
+      equality_w = 0.0
+
+      self.R[0, 0] = left_velocity
+      self.R[1, 0] = right_velocity
+
+      # Construct a constraint on R by manipulating the constraint on U
+      # Start out with H * U <= k
+      # U = FF * R + K * (R - X)
+      # H * (FF * R + K * R - K * X) <= k
+      # H * (FF + K) * R <= k + H * K * X
+      R_poly = polytope.HPolytope(
+          self.U_poly.H * (self.CurrentDrivetrain().K + self.CurrentDrivetrain().FF),
+          self.U_poly.k + self.U_poly.H * self.CurrentDrivetrain().K * self.X)
+
+      # Limit R back inside the box.
+      self.boxed_R = CoerceGoal(R_poly, equality_k, equality_w, self.R)
+
+      FF_volts = self.CurrentDrivetrain().FF * self.boxed_R
+      self.U_ideal = self.CurrentDrivetrain().K * (self.boxed_R - self.X) + FF_volts
+    else:
+      print 'Not all in gear'
+      if not self.IsInGear(self.left_gear) and not self.IsInGear(self.right_gear):
+        # TODO(austin): Use battery volts here.
+        R_left = self.MotorRPM(self.left_shifter_position, self.X[0, 0])
+        self.U_ideal[0, 0] = numpy.clip(
+            self.left_cim.K * (R_left - self.left_cim.X) + R_left / self.left_cim.Kv,
+            self.left_cim.U_min, self.left_cim.U_max)
+        self.left_cim.Update(self.U_ideal[0, 0])
+
+        R_right = self.MotorRPM(self.right_shifter_position, self.X[1, 0])
+        self.U_ideal[1, 0] = numpy.clip(
+            self.right_cim.K * (R_right - self.right_cim.X) + R_right / self.right_cim.Kv,
+            self.right_cim.U_min, self.right_cim.U_max)
+        self.right_cim.Update(self.U_ideal[1, 0])
+      else:
+        assert False
+
+    self.U = numpy.clip(self.U_ideal, self.U_min, self.U_max)
+
+    # TODO(austin): Model the robot as not accelerating when you shift...
+    # This hack only works when you shift at the same time.
+    if self.IsInGear(self.left_gear) and self.IsInGear(self.right_gear):
+      self.X = self.CurrentDrivetrain().A * self.X + self.CurrentDrivetrain().B * self.U
+
+    self.left_gear, self.left_shifter_position = self.SimShifter(
+        self.left_gear, self.left_shifter_position)
+    self.right_gear, self.right_shifter_position = self.SimShifter(
+        self.right_gear, self.right_shifter_position)
+
+    print "U is", self.U[0, 0], self.U[1, 0]
+    print "Left shifter", self.left_gear, self.left_shifter_position, "Right shifter", self.right_gear, self.right_shifter_position
+
+
+def main(argv):
+  vdrivetrain = VelocityDrivetrain()
+
+  if len(argv) != 7:
+    print "Expected .h file name and .cc file name"
+  else:
+    dog_loop_writer = control_loop.ControlLoopWriter(
+        "VelocityDrivetrain", [vdrivetrain.drivetrain_low_low,
+                       vdrivetrain.drivetrain_low_high,
+                       vdrivetrain.drivetrain_high_low,
+                       vdrivetrain.drivetrain_high_high])
+
+    if argv[1][-3:] == '.cc':
+      dog_loop_writer.Write(argv[2], argv[1])
+    else:
+      dog_loop_writer.Write(argv[1], argv[2])
+
+    cim_writer = control_loop.ControlLoopWriter(
+        "CIM", [drivetrain.CIM()])
+
+    if argv[5][-3:] == '.cc':
+      cim_writer.Write(argv[6], argv[5])
+    else:
+      cim_writer.Write(argv[5], argv[6])
+    return
+
+  vl_plot = []
+  vr_plot = []
+  ul_plot = []
+  ur_plot = []
+  radius_plot = []
+  t_plot = []
+  left_gear_plot = []
+  right_gear_plot = []
+  vdrivetrain.left_shifter_position = 0.0
+  vdrivetrain.right_shifter_position = 0.0
+  vdrivetrain.left_gear = VelocityDrivetrain.LOW
+  vdrivetrain.right_gear = VelocityDrivetrain.LOW
+
+  print "K is", vdrivetrain.CurrentDrivetrain().K
+
+  if vdrivetrain.left_gear is VelocityDrivetrain.HIGH:
+    print "Left is high"
+  else:
+    print "Left is low"
+  if vdrivetrain.right_gear is VelocityDrivetrain.HIGH:
+    print "Right is high"
+  else:
+    print "Right is low"
+
+  for t in numpy.arange(0, 1.7, vdrivetrain.dt):
+    if t < 0.5:
+      vdrivetrain.Update(throttle=0.00, steering=1.0)
+    elif t < 1.2:
+      vdrivetrain.Update(throttle=0.5, steering=1.0)
+    else:
+      vdrivetrain.Update(throttle=0.00, steering=1.0)
+    t_plot.append(t)
+    vl_plot.append(vdrivetrain.X[0, 0])
+    vr_plot.append(vdrivetrain.X[1, 0])
+    ul_plot.append(vdrivetrain.U[0, 0])
+    ur_plot.append(vdrivetrain.U[1, 0])
+    left_gear_plot.append((vdrivetrain.left_gear is VelocityDrivetrain.HIGH) * 2.0 - 10.0)
+    right_gear_plot.append((vdrivetrain.right_gear is VelocityDrivetrain.HIGH) * 2.0 - 10.0)
+
+    fwd_velocity = (vdrivetrain.X[1, 0] + vdrivetrain.X[0, 0]) / 2
+    turn_velocity = (vdrivetrain.X[1, 0] - vdrivetrain.X[0, 0])
+    if abs(fwd_velocity) < 0.0000001:
+      radius_plot.append(turn_velocity)
+    else:
+      radius_plot.append(turn_velocity / fwd_velocity)
+
+  cim_velocity_plot = []
+  cim_voltage_plot = []
+  cim_time = []
+  cim = drivetrain.CIM()
+  R = numpy.matrix([[300]])
+  for t in numpy.arange(0, 0.5, cim.dt):
+    U = numpy.clip(cim.K * (R - cim.X) + R / cim.Kv, cim.U_min, cim.U_max)
+    cim.Update(U)
+    cim_velocity_plot.append(cim.X[0, 0])
+    cim_voltage_plot.append(U[0, 0] * 10)
+    cim_time.append(t)
+  pylab.plot(cim_time, cim_velocity_plot, label='cim spinup')
+  pylab.plot(cim_time, cim_voltage_plot, label='cim voltage')
+  pylab.legend()
+  pylab.show()
+
+  # TODO(austin):
+  # Shifting compensation.
+
+  # Tighten the turn.
+  # Closed loop drive.
+
+  pylab.plot(t_plot, vl_plot, label='left velocity')
+  pylab.plot(t_plot, vr_plot, label='right velocity')
+  pylab.plot(t_plot, ul_plot, label='left voltage')
+  pylab.plot(t_plot, ur_plot, label='right voltage')
+  pylab.plot(t_plot, radius_plot, label='radius')
+  pylab.plot(t_plot, left_gear_plot, label='left gear high')
+  pylab.plot(t_plot, right_gear_plot, label='right gear high')
+  pylab.legend()
+  pylab.show()
+  return 0
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))
diff --git a/y2014/control_loops/python/polydrivetrain_test.py b/y2014/control_loops/python/polydrivetrain_test.py
new file mode 100755
index 0000000..434cdca
--- /dev/null
+++ b/y2014/control_loops/python/polydrivetrain_test.py
@@ -0,0 +1,82 @@
+#!/usr/bin/python
+
+import polydrivetrain
+import numpy
+from numpy.testing import *
+import polytope
+import unittest
+
+__author__ = 'Austin Schuh (austin.linux@gmail.com)'
+
+
+class TestVelocityDrivetrain(unittest.TestCase):
+  def MakeBox(self, x1_min, x1_max, x2_min, x2_max):
+    H = numpy.matrix([[1, 0],
+                      [-1, 0],
+                      [0, 1],
+                      [0, -1]])
+    K = numpy.matrix([[x1_max],
+                      [-x1_min],
+                      [x2_max],
+                      [-x2_min]])
+    return polytope.HPolytope(H, K)
+
+  def test_coerce_inside(self):
+    """Tests coercion when the point is inside the box."""
+    box = self.MakeBox(1, 2, 1, 2)
+
+    # x1 = x2
+    K = numpy.matrix([[1, -1]])
+    w = 0
+
+    assert_array_equal(polydrivetrain.CoerceGoal(box, K, w,
+                                                 numpy.matrix([[1.5], [1.5]])),
+                       numpy.matrix([[1.5], [1.5]]))
+
+  def test_coerce_outside_intersect(self):
+    """Tests coercion when the line intersects the box."""
+    box = self.MakeBox(1, 2, 1, 2)
+
+    # x1 = x2
+    K = numpy.matrix([[1, -1]])
+    w = 0
+
+    assert_array_equal(polydrivetrain.CoerceGoal(box, K, w, numpy.matrix([[5], [5]])),
+                       numpy.matrix([[2.0], [2.0]]))
+
+  def test_coerce_outside_no_intersect(self):
+    """Tests coercion when the line does not intersect the box."""
+    box = self.MakeBox(3, 4, 1, 2)
+
+    # x1 = x2
+    K = numpy.matrix([[1, -1]])
+    w = 0
+
+    assert_array_equal(polydrivetrain.CoerceGoal(box, K, w, numpy.matrix([[5], [5]])),
+                       numpy.matrix([[3.0], [2.0]]))
+
+  def test_coerce_middle_of_edge(self):
+    """Tests coercion when the line intersects the middle of an edge."""
+    box = self.MakeBox(0, 4, 1, 2)
+
+    # x1 = x2
+    K = numpy.matrix([[-1, 1]])
+    w = 0
+
+    assert_array_equal(polydrivetrain.CoerceGoal(box, K, w, numpy.matrix([[5], [5]])),
+                       numpy.matrix([[2.0], [2.0]]))
+
+  def test_coerce_perpendicular_line(self):
+    """Tests coercion when the line does not intersect and is in quadrant 2."""
+    box = self.MakeBox(1, 2, 1, 2)
+
+    # x1 = -x2
+    K = numpy.matrix([[1, 1]])
+    w = 0
+
+    assert_array_equal(polydrivetrain.CoerceGoal(box, K, w, numpy.matrix([[5], [5]])),
+                       numpy.matrix([[1.0], [1.0]]))
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/y2014/control_loops/python/shooter.py b/y2014/control_loops/python/shooter.py
new file mode 100755
index 0000000..69f2599
--- /dev/null
+++ b/y2014/control_loops/python/shooter.py
@@ -0,0 +1,254 @@
+#!/usr/bin/python
+
+import control_loop
+import numpy
+import sys
+from matplotlib import pylab
+
+class SprungShooter(control_loop.ControlLoop):
+  def __init__(self, name="RawSprungShooter"):
+    super(SprungShooter, self).__init__(name)
+    # Stall Torque in N m
+    self.stall_torque = .4982
+    # Stall Current in Amps
+    self.stall_current = 85
+    # Free Speed in RPM
+    self.free_speed = 19300.0
+    # Free Current in Amps
+    self.free_current = 1.2
+    # Effective mass of the shooter in kg.
+    # This rough estimate should about include the effect of the masses
+    # of the gears. If this number is too low, the eigen values of self.A
+    # will start to become extremely small.
+    self.J = 200
+    # Resistance of the motor, divided by the number of motors.
+    self.R = 12.0 / self.stall_current / 2.0
+    # Motor velocity constant
+    self.Kv = ((self.free_speed / 60.0 * 2.0 * numpy.pi) /
+               (12.0 - self.R * self.free_current))
+    # Torque constant
+    self.Kt = self.stall_torque / self.stall_current
+    # Spring constant for the springs, N/m
+    self.Ks = 2800.0
+    # Maximum extension distance (Distance from the 0 force point on the
+    # spring to the latch position.)
+    self.max_extension = 0.32385
+    # Gear ratio multiplied by radius of final sprocket.
+    self.G = 10.0 / 40.0 * 20.0 / 54.0 * 24.0 / 54.0 * 20.0 / 84.0 * 16.0 * (3.0 / 8.0) / (2.0 * numpy.pi) * 0.0254
+
+    # Control loop time step
+    self.dt = 0.01
+
+    # State feedback matrices
+    self.A_continuous = numpy.matrix(
+        [[0, 1],
+         [-self.Ks / self.J,
+          -self.Kt / self.Kv / (self.J * self.G * self.G * self.R)]])
+    self.B_continuous = numpy.matrix(
+        [[0],
+         [self.Kt / (self.J * self.G * self.R)]])
+    self.C = numpy.matrix([[1, 0]])
+    self.D = numpy.matrix([[0]])
+
+    self.A, self.B = self.ContinuousToDiscrete(
+        self.A_continuous, self.B_continuous, self.dt)
+
+    self.PlaceControllerPoles([0.45, 0.45])
+
+    self.rpl = .05
+    self.ipl = 0.008
+    self.PlaceObserverPoles([self.rpl,
+                             self.rpl])
+
+    self.U_max = numpy.matrix([[12.0]])
+    self.U_min = numpy.matrix([[-12.0]])
+
+    self.InitializeState()
+
+
+class Shooter(SprungShooter):
+  def __init__(self, name="RawShooter"):
+    super(Shooter, self).__init__(name)
+
+    # State feedback matrices
+    self.A_continuous = numpy.matrix(
+        [[0, 1],
+         [0, -self.Kt / self.Kv / (self.J * self.G * self.G * self.R)]])
+    self.B_continuous = numpy.matrix(
+        [[0],
+         [self.Kt / (self.J * self.G * self.R)]])
+
+    self.A, self.B = self.ContinuousToDiscrete(
+        self.A_continuous, self.B_continuous, self.dt)
+
+    self.PlaceControllerPoles([0.45, 0.45])
+
+    self.rpl = .05
+    self.ipl = 0.008
+    self.PlaceObserverPoles([self.rpl,
+                             self.rpl])
+
+    self.U_max = numpy.matrix([[12.0]])
+    self.U_min = numpy.matrix([[-12.0]])
+
+    self.InitializeState()
+
+
+class SprungShooterDeltaU(SprungShooter):
+  def __init__(self, name="SprungShooter"):
+    super(SprungShooterDeltaU, self).__init__(name)
+    A_unaugmented = self.A
+    B_unaugmented = self.B
+
+    self.A = numpy.matrix([[0.0, 0.0, 0.0],
+                           [0.0, 0.0, 0.0],
+                           [0.0, 0.0, 1.0]])
+    self.A[0:2, 0:2] = A_unaugmented
+    self.A[0:2, 2] = B_unaugmented
+
+    self.B = numpy.matrix([[0.0],
+                           [0.0],
+                           [1.0]])
+
+    self.C = numpy.matrix([[1.0, 0.0, 0.0]])
+    self.D = numpy.matrix([[0.0]])
+
+    self.PlaceControllerPoles([0.50, 0.35, 0.80])
+
+    print "K"
+    print self.K
+    print "Placed controller poles are"
+    print numpy.linalg.eig(self.A - self.B * self.K)[0]
+
+    self.rpl = .05
+    self.ipl = 0.008
+    self.PlaceObserverPoles([self.rpl + 1j * self.ipl,
+                             self.rpl - 1j * self.ipl, 0.90])
+    print "Placed observer poles are"
+    print numpy.linalg.eig(self.A - self.L * self.C)[0]
+
+    self.U_max = numpy.matrix([[12.0]])
+    self.U_min = numpy.matrix([[-12.0]])
+
+    self.InitializeState()
+
+
+class ShooterDeltaU(Shooter):
+  def __init__(self, name="Shooter"):
+    super(ShooterDeltaU, self).__init__(name)
+    A_unaugmented = self.A
+    B_unaugmented = self.B
+
+    self.A = numpy.matrix([[0.0, 0.0, 0.0],
+                           [0.0, 0.0, 0.0],
+                           [0.0, 0.0, 1.0]])
+    self.A[0:2, 0:2] = A_unaugmented
+    self.A[0:2, 2] = B_unaugmented
+
+    self.B = numpy.matrix([[0.0],
+                           [0.0],
+                           [1.0]])
+
+    self.C = numpy.matrix([[1.0, 0.0, 0.0]])
+    self.D = numpy.matrix([[0.0]])
+
+    self.PlaceControllerPoles([0.55, 0.45, 0.80])
+
+    print "K"
+    print self.K
+    print "Placed controller poles are"
+    print numpy.linalg.eig(self.A - self.B * self.K)[0]
+
+    self.rpl = .05
+    self.ipl = 0.008
+    self.PlaceObserverPoles([self.rpl + 1j * self.ipl,
+                             self.rpl - 1j * self.ipl, 0.90])
+    print "Placed observer poles are"
+    print numpy.linalg.eig(self.A - self.L * self.C)[0]
+
+    self.U_max = numpy.matrix([[12.0]])
+    self.U_min = numpy.matrix([[-12.0]])
+
+    self.InitializeState()
+
+
+def ClipDeltaU(shooter, old_voltage, delta_u):
+  old_u = old_voltage
+  new_u = numpy.clip(old_u + delta_u, shooter.U_min, shooter.U_max)
+  return new_u - old_u
+
+def main(argv):
+  # Simulate the response of the system to a goal.
+  sprung_shooter = SprungShooterDeltaU()
+  raw_sprung_shooter = SprungShooter()
+  close_loop_x = []
+  close_loop_u = []
+  goal_position = -0.3
+  R = numpy.matrix([[goal_position], [0.0], [-sprung_shooter.A[1, 0] / sprung_shooter.A[1, 2] * goal_position]])
+  voltage = numpy.matrix([[0.0]])
+  for _ in xrange(500):
+    U = sprung_shooter.K * (R - sprung_shooter.X_hat)
+    U = ClipDeltaU(sprung_shooter, voltage, U)
+    sprung_shooter.Y = raw_sprung_shooter.Y + 0.01
+    sprung_shooter.UpdateObserver(U)
+    voltage += U;
+    raw_sprung_shooter.Update(voltage)
+    close_loop_x.append(raw_sprung_shooter.X[0, 0] * 10)
+    close_loop_u.append(voltage[0, 0])
+
+  pylab.plot(range(500), close_loop_x)
+  pylab.plot(range(500), close_loop_u)
+  pylab.show()
+
+  shooter = ShooterDeltaU()
+  raw_shooter = Shooter()
+  close_loop_x = []
+  close_loop_u = []
+  goal_position = -0.3
+  R = numpy.matrix([[goal_position], [0.0], [-shooter.A[1, 0] / shooter.A[1, 2] * goal_position]])
+  voltage = numpy.matrix([[0.0]])
+  for _ in xrange(500):
+    U = shooter.K * (R - shooter.X_hat)
+    U = ClipDeltaU(shooter, voltage, U)
+    shooter.Y = raw_shooter.Y + 0.01
+    shooter.UpdateObserver(U)
+    voltage += U;
+    raw_shooter.Update(voltage)
+    close_loop_x.append(raw_shooter.X[0, 0] * 10)
+    close_loop_u.append(voltage[0, 0])
+
+  pylab.plot(range(500), close_loop_x)
+  pylab.plot(range(500), close_loop_u)
+  pylab.show()
+
+  # Write the generated constants out to a file.
+  if len(argv) != 5:
+    print "Expected .h file name and .cc file name for"
+    print "both the plant and unaugmented plant"
+  else:
+    unaug_sprung_shooter = SprungShooter("RawSprungShooter")
+    unaug_shooter = Shooter("RawShooter")
+    unaug_loop_writer = control_loop.ControlLoopWriter("RawShooter",
+                                                       [unaug_sprung_shooter,
+                                                        unaug_shooter])
+    if argv[3][-3:] == '.cc':
+      unaug_loop_writer.Write(argv[4], argv[3])
+    else:
+      unaug_loop_writer.Write(argv[3], argv[4])
+
+    sprung_shooter = SprungShooterDeltaU()
+    shooter = ShooterDeltaU()
+    loop_writer = control_loop.ControlLoopWriter("Shooter", [sprung_shooter,
+                                                             shooter])
+
+    loop_writer.AddConstant(control_loop.Constant("kMaxExtension", "%f",
+                                                  sprung_shooter.max_extension))
+    loop_writer.AddConstant(control_loop.Constant("kSpringConstant", "%f",
+                                                  sprung_shooter.Ks))
+    if argv[1][-3:] == '.cc':
+      loop_writer.Write(argv[2], argv[1])
+    else:
+      loop_writer.Write(argv[1], argv[2])
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))
diff --git a/y2014/control_loops/shooter/replay_shooter.cc b/y2014/control_loops/shooter/replay_shooter.cc
new file mode 100644
index 0000000..20c953f
--- /dev/null
+++ b/y2014/control_loops/shooter/replay_shooter.cc
@@ -0,0 +1,24 @@
+#include "aos/common/controls/replay_control_loop.h"
+#include "aos/linux_code/init.h"
+
+#include "y2014/control_loops/shooter/shooter.q.h"
+
+// Reads one or more log files and sends out all the queue messages (in the
+// correct order and at the correct time) to feed a "live" shooter process.
+
+int main(int argc, char **argv) {
+  if (argc <= 1) {
+    fprintf(stderr, "Need at least one file to replay!\n");
+    return EXIT_FAILURE;
+  }
+
+  ::aos::InitNRT();
+
+  ::aos::controls::ControlLoopReplayer<::frc971::control_loops::ShooterQueue>
+      replayer(&::frc971::control_loops::shooter_queue, "shooter");
+  for (int i = 1; i < argc; ++i) {
+    replayer.ProcessFile(argv[i]);
+  }
+
+  ::aos::Cleanup();
+}
diff --git a/y2014/control_loops/shooter/shooter.cc b/y2014/control_loops/shooter/shooter.cc
new file mode 100644
index 0000000..5211967
--- /dev/null
+++ b/y2014/control_loops/shooter/shooter.cc
@@ -0,0 +1,691 @@
+#include "y2014/control_loops/shooter/shooter.h"
+
+#include <stdio.h>
+
+#include <algorithm>
+#include <limits>
+
+#include "aos/common/controls/control_loops.q.h"
+#include "aos/common/logging/logging.h"
+#include "aos/common/logging/queue_logging.h"
+
+#include "y2014/constants.h"
+#include "y2014/control_loops/shooter/shooter_motor_plant.h"
+
+namespace frc971 {
+namespace control_loops {
+
+using ::aos::time::Time;
+
+void ZeroedStateFeedbackLoop::CapU() {
+  const double old_voltage = voltage_;
+  voltage_ += U(0, 0);
+
+  uncapped_voltage_ = voltage_;
+
+  // Make sure that reality and the observer can't get too far off.  There is a
+  // delay by one cycle between the applied voltage and X_hat(2, 0), so compare
+  // against last cycle's voltage.
+  if (X_hat(2, 0) > last_voltage_ + 4.0) {
+    voltage_ -= X_hat(2, 0) - (last_voltage_ + 4.0);
+    LOG(DEBUG, "Capping due to runaway\n");
+  } else if (X_hat(2, 0) < last_voltage_ - 4.0) {
+    voltage_ += X_hat(2, 0) - (last_voltage_ - 4.0);
+    LOG(DEBUG, "Capping due to runaway\n");
+  }
+
+  voltage_ = std::min(max_voltage_, voltage_);
+  voltage_ = std::max(-max_voltage_, voltage_);
+  mutable_U(0, 0) = voltage_ - old_voltage;
+
+  LOG_STRUCT(DEBUG, "output", ShooterVoltageToLog(X_hat(2, 0), voltage_));
+
+  last_voltage_ = voltage_;
+  capped_goal_ = false;
+}
+
+void ZeroedStateFeedbackLoop::CapGoal() {
+  if (uncapped_voltage() > max_voltage_) {
+    double dx;
+    if (controller_index() == 0) {
+      dx = (uncapped_voltage() - max_voltage_) /
+           (K(0, 0) - A(1, 0) * K(0, 2) / A(1, 2));
+      mutable_R(0, 0) -= dx;
+      mutable_R(2, 0) -= -A(1, 0) / A(1, 2) * dx;
+    } else {
+      dx = (uncapped_voltage() - max_voltage_) / K(0, 0);
+      mutable_R(0, 0) -= dx;
+    }
+    capped_goal_ = true;
+    LOG_STRUCT(DEBUG, "to prevent windup", ShooterMovingGoal(dx));
+  } else if (uncapped_voltage() < -max_voltage_) {
+    double dx;
+    if (controller_index() == 0) {
+      dx = (uncapped_voltage() + max_voltage_) /
+           (K(0, 0) - A(1, 0) * K(0, 2) / A(1, 2));
+      mutable_R(0, 0) -= dx;
+      mutable_R(2, 0) -= -A(1, 0) / A(1, 2) * dx;
+    } else {
+      dx = (uncapped_voltage() + max_voltage_) / K(0, 0);
+      mutable_R(0, 0) -= dx;
+    }
+    capped_goal_ = true;
+    LOG_STRUCT(DEBUG, "to prevent windup", ShooterMovingGoal(dx));
+  } else {
+    capped_goal_ = false;
+  }
+}
+
+void ZeroedStateFeedbackLoop::RecalculatePowerGoal() {
+  if (controller_index() == 0) {
+    mutable_R(2, 0) = (-A(1, 0) / A(1, 2) * R(0, 0) - A(1, 1) / A(1, 2) * R(1, 0));
+  } else {
+    mutable_R(2, 0) = -A(1, 1) / A(1, 2) * R(1, 0);
+  }
+}
+
+void ZeroedStateFeedbackLoop::SetCalibration(double encoder_val,
+                                             double known_position) {
+  double old_position = absolute_position();
+  double previous_offset = offset_;
+  offset_ = known_position - encoder_val;
+  double doffset = offset_ - previous_offset;
+  mutable_X_hat(0, 0) += doffset;
+  // Offset the goal so we don't move.
+  mutable_R(0, 0) += doffset;
+  if (controller_index() == 0) {
+    mutable_R(2, 0) += -A(1, 0) / A(1, 2) * (doffset);
+  }
+  LOG_STRUCT(
+      DEBUG, "sensor edge (fake?)",
+      ShooterChangeCalibration(encoder_val, known_position, old_position,
+                               absolute_position(), previous_offset, offset_));
+}
+
+ShooterMotor::ShooterMotor(control_loops::ShooterQueue *my_shooter)
+    : aos::controls::ControlLoop<control_loops::ShooterQueue>(my_shooter),
+      shooter_(MakeShooterLoop()),
+      state_(STATE_INITIALIZE),
+      loading_problem_end_time_(0, 0),
+      load_timeout_(0, 0),
+      shooter_brake_set_time_(0, 0),
+      unload_timeout_(0, 0),
+      shot_end_time_(0, 0),
+      cycles_not_moved_(0),
+      shot_count_(0),
+      zeroed_(false),
+      distal_posedge_validation_cycles_left_(0),
+      proximal_posedge_validation_cycles_left_(0),
+      last_distal_current_(true),
+      last_proximal_current_(true) {}
+
+double ShooterMotor::PowerToPosition(double power) {
+  const frc971::constants::Values &values = constants::GetValues();
+  double maxpower = 0.5 * kSpringConstant *
+                    (kMaxExtension * kMaxExtension -
+                     (kMaxExtension - values.shooter.upper_limit) *
+                         (kMaxExtension - values.shooter.upper_limit));
+  if (power < 0) {
+    LOG_STRUCT(WARNING, "negative power", PowerAdjustment(power, 0));
+    power = 0;
+  } else if (power > maxpower) {
+    LOG_STRUCT(WARNING, "power too high", PowerAdjustment(power, maxpower));
+    power = maxpower;
+  }
+
+  double mp = kMaxExtension * kMaxExtension - (power + power) / kSpringConstant;
+  double new_pos = 0.10;
+  if (mp < 0) {
+    LOG(ERROR,
+        "Power calculation has negative number before square root (%f).\n", mp);
+  } else {
+    new_pos = kMaxExtension - ::std::sqrt(mp);
+  }
+
+  new_pos = ::std::min(::std::max(new_pos, values.shooter.lower_limit),
+                              values.shooter.upper_limit);
+  return new_pos;
+}
+
+double ShooterMotor::PositionToPower(double position) {
+  double power = kSpringConstant * position * (kMaxExtension - position / 2.0);
+  return power;
+}
+
+void ShooterMotor::CheckCalibrations(
+    const control_loops::ShooterQueue::Position *position) {
+  CHECK_NOTNULL(position);
+  const frc971::constants::Values &values = constants::GetValues();
+
+  // TODO(austin): Validate that this is the right edge.
+  // If we see a posedge on any of the hall effects,
+  if (position->pusher_proximal.posedge_count != last_proximal_posedge_count_ &&
+      !last_proximal_current_) {
+    proximal_posedge_validation_cycles_left_ = 2;
+  }
+  if (proximal_posedge_validation_cycles_left_ > 0) {
+    if (position->pusher_proximal.current) {
+      --proximal_posedge_validation_cycles_left_;
+      if (proximal_posedge_validation_cycles_left_ == 0) {
+        shooter_.SetCalibration(
+            position->pusher_proximal.posedge_value,
+            values.shooter.pusher_proximal.upper_angle);
+
+        LOG(DEBUG, "Setting calibration using proximal sensor\n");
+        zeroed_ = true;
+      }
+    } else {
+      proximal_posedge_validation_cycles_left_ = 0;
+    }
+  }
+
+  if (position->pusher_distal.posedge_count != last_distal_posedge_count_ &&
+      !last_distal_current_) {
+    distal_posedge_validation_cycles_left_ = 2;
+  }
+  if (distal_posedge_validation_cycles_left_ > 0) {
+    if (position->pusher_distal.current) {
+      --distal_posedge_validation_cycles_left_;
+      if (distal_posedge_validation_cycles_left_ == 0) {
+        shooter_.SetCalibration(
+            position->pusher_distal.posedge_value,
+            values.shooter.pusher_distal.upper_angle);
+
+        LOG(DEBUG, "Setting calibration using distal sensor\n");
+        zeroed_ = true;
+      }
+    } else {
+      distal_posedge_validation_cycles_left_ = 0;
+    }
+  }
+}
+
+// Positive is out, and positive power is out.
+void ShooterMotor::RunIteration(
+    const control_loops::ShooterQueue::Goal *goal,
+    const control_loops::ShooterQueue::Position *position,
+    control_loops::ShooterQueue::Output *output,
+    control_loops::ShooterQueue::Status *status) {
+  constexpr double dt = 0.01;
+
+  if (goal && ::std::isnan(goal->shot_power)) {
+	  state_ = STATE_ESTOP;
+    LOG(ERROR, "Estopping because got a shot power of NAN.\n");
+  }
+
+  // we must always have these or we have issues.
+  if (status == NULL) {
+    if (output) output->voltage = 0;
+    LOG(ERROR, "Thought I would just check for null and die.\n");
+    return;
+  }
+  status->ready = false;
+
+  if (WasReset()) {
+    state_ = STATE_INITIALIZE;
+    last_distal_current_ = position->pusher_distal.current;
+    last_proximal_current_ = position->pusher_proximal.current;
+  }
+  if (position) {
+    shooter_.CorrectPosition(position->position);
+  }
+
+  // Disable the motors now so that all early returns will return with the
+  // motors disabled.
+  if (output) output->voltage = 0;
+
+  const frc971::constants::Values &values = constants::GetValues();
+
+  // Don't even let the control loops run.
+  bool shooter_loop_disable = false;
+
+  const bool disabled =
+      !::aos::joystick_state.get() || !::aos::joystick_state->enabled;
+
+  // If true, move the goal if we saturate.
+  bool cap_goal = false;
+
+  // TODO(austin): Move the offset if we see or don't see a hall effect when we
+  // expect to see one.
+  // Probably not needed yet.
+
+  if (position) {
+    int last_controller_index = shooter_.controller_index();
+    if (position->plunger && position->latch) {
+      // Use the controller without the spring if the latch is set and the
+      // plunger is back
+      shooter_.set_controller_index(1);
+    } else {
+      // Otherwise use the controller with the spring.
+      shooter_.set_controller_index(0);
+    }
+    if (shooter_.controller_index() != last_controller_index) {
+      shooter_.RecalculatePowerGoal();
+    }
+  }
+
+  switch (state_) {
+    case STATE_INITIALIZE:
+      if (position) {
+        // Reinitialize the internal filter state.
+        shooter_.InitializeState(position->position);
+
+        // Start off with the assumption that we are at the value
+        // futhest back given our sensors.
+        if (position->pusher_distal.current) {
+          shooter_.SetCalibration(position->position,
+                                  values.shooter.pusher_distal.lower_angle);
+        } else if (position->pusher_proximal.current) {
+          shooter_.SetCalibration(position->position,
+                                  values.shooter.pusher_proximal.upper_angle);
+        } else {
+          shooter_.SetCalibration(position->position,
+                                  values.shooter.upper_limit);
+        }
+
+        // Go to the current position.
+        shooter_.SetGoalPosition(shooter_.absolute_position(), 0.0);
+        // If the plunger is all the way back, we want to be latched.
+        latch_piston_ = position->plunger;
+        brake_piston_ = false;
+        if (position->latch == latch_piston_) {
+          state_ = STATE_REQUEST_LOAD;
+        } else {
+          shooter_loop_disable = true;
+          LOG(DEBUG,
+              "Not moving on until the latch has moved to avoid a crash\n");
+        }
+      } else {
+        // If we can't start yet because we don't know where we are, set the
+        // latch and brake to their defaults.
+        latch_piston_ = true;
+        brake_piston_ = true;
+      }
+      break;
+    case STATE_REQUEST_LOAD:
+      if (position) {
+        zeroed_ = false;
+        if (position->pusher_distal.current ||
+            position->pusher_proximal.current) {
+          // We started on the sensor, back up until we are found.
+          // If the plunger is all the way back and not latched, it won't be
+          // there for long.
+          state_ = STATE_LOAD_BACKTRACK;
+
+          // The plunger is already back and latched.  Don't release it.
+          if (position->plunger && position->latch) {
+            latch_piston_ = true;
+          } else {
+            latch_piston_ = false;
+          }
+        } else if (position->plunger && position->latch) {
+          // The plunger is back and we are latched.  We most likely got here
+          // from Initialize, in which case we want to 'load' again anyways to
+          // zero.
+          Load();
+          latch_piston_ = true;
+        } else {
+          // Off the sensor, start loading.
+          Load();
+          latch_piston_ = false;
+        }
+      }
+
+      // Hold our current position.
+      shooter_.SetGoalPosition(shooter_.absolute_position(), 0.0);
+      brake_piston_ = false;
+      break;
+    case STATE_LOAD_BACKTRACK:
+      // If we are here, then that means we started past the edge where we want
+      // to zero.  Move backwards until we don't see the sensor anymore.
+      // The plunger is contacting the pusher (or will be shortly).
+
+      if (!disabled) {
+        shooter_.SetGoalPosition(
+            shooter_.goal_position() + values.shooter.zeroing_speed * dt,
+            values.shooter.zeroing_speed);
+      }
+      cap_goal = true;
+      shooter_.set_max_voltage(4.0);
+
+      if (position) {
+        if (!position->pusher_distal.current &&
+            !position->pusher_proximal.current) {
+          Load();
+        }
+        latch_piston_ = position->plunger;
+      }
+
+      brake_piston_ = false;
+      break;
+    case STATE_LOAD:
+      // If we are disabled right now, reset the timer.
+      if (disabled) {
+        Load();
+        // Latch defaults to true when disabled.  Leave it latched until we have
+        // useful sensor data.
+        latch_piston_ = true;
+      }
+      if (output == nullptr) {
+        load_timeout_ += ::aos::controls::kLoopFrequency;
+      }
+      // Go to 0, which should be the latch position, or trigger a hall effect
+      // on the way.  If we don't see edges where we are supposed to, the
+      // offset will be updated by code above.
+      shooter_.SetGoalPosition(0.0, 0.0);
+
+      if (position) {
+        CheckCalibrations(position);
+
+        // Latch if the plunger is far enough back to trigger the hall effect.
+        // This happens when the distal sensor is triggered.
+        latch_piston_ = position->pusher_distal.current || position->plunger;
+
+        // Check if we are latched and back.  Make sure the plunger is all the
+        // way back as well.
+        if (position->plunger && position->latch &&
+            position->pusher_distal.current) {
+          if (!zeroed_) {
+            state_ = STATE_REQUEST_LOAD;
+          } else {
+            state_ = STATE_PREPARE_SHOT;
+          }
+        } else if (position->plunger &&
+                   ::std::abs(shooter_.absolute_position() -
+                              shooter_.goal_position()) < 0.001) {
+          // We are at the goal, but not latched.
+          state_ = STATE_LOADING_PROBLEM;
+          loading_problem_end_time_ = Time::Now() + kLoadProblemEndTimeout;
+        }
+      }
+      if (load_timeout_ < Time::Now()) {
+        if (position) {
+          if (!position->pusher_distal.current ||
+              !position->pusher_proximal.current) {
+            state_ = STATE_ESTOP;
+            LOG(ERROR, "Estopping because took too long to load.\n");
+          }
+        }
+      }
+      brake_piston_ = false;
+      break;
+    case STATE_LOADING_PROBLEM:
+      if (disabled) {
+        state_ = STATE_REQUEST_LOAD;
+        break;
+      }
+      // We got to the goal, but the latch hasn't registered as down.  It might
+      // be stuck, or on it's way but not there yet.
+      if (Time::Now() > loading_problem_end_time_) {
+        // Timeout by unloading.
+        Unload();
+      } else if (position && position->plunger && position->latch) {
+        // If both trigger, we are latched.
+        state_ = STATE_PREPARE_SHOT;
+      }
+      // Move a bit further back to help it trigger.
+      // If the latch is slow due to the air flowing through the tubes or
+      // inertia, but is otherwise free, this won't have much time to do
+      // anything and is safe.  Otherwise this gives us a bit more room to free
+      // up the latch.
+      shooter_.SetGoalPosition(values.shooter.lower_limit, 0.0);
+      if (position) {
+        LOG(DEBUG, "Waiting on latch: plunger %d, latch: %d\n",
+            position->plunger, position->latch);
+      }
+
+      latch_piston_ = true;
+      brake_piston_ = false;
+      break;
+    case STATE_PREPARE_SHOT:
+      // Move the shooter to the shot power set point and then lock the brake.
+      // TODO(austin): Timeout.  Low priority.
+
+      if (goal) {
+        shooter_.SetGoalPosition(PowerToPosition(goal->shot_power), 0.0);
+      }
+
+      LOG(DEBUG, "PDIFF: absolute_position: %.2f, pow: %.2f\n",
+          shooter_.absolute_position(),
+          goal ? PowerToPosition(goal->shot_power)
+               : ::std::numeric_limits<double>::quiet_NaN());
+      if (goal &&
+          ::std::abs(shooter_.absolute_position() -
+                     PowerToPosition(goal->shot_power)) < 0.001 &&
+          ::std::abs(shooter_.absolute_velocity()) < 0.005) {
+        // We are there, set the brake and move on.
+        latch_piston_ = true;
+        brake_piston_ = true;
+        shooter_brake_set_time_ = Time::Now() + kShooterBrakeSetTime;
+        state_ = STATE_READY;
+      } else {
+        latch_piston_ = true;
+        brake_piston_ = false;
+      }
+      if (goal && goal->unload_requested) {
+        Unload();
+      }
+      break;
+    case STATE_READY:
+      LOG(DEBUG, "In ready\n");
+      // Wait until the brake is set, and a shot is requested or the shot power
+      // is changed.
+      if (Time::Now() > shooter_brake_set_time_) {
+        status->ready = true;
+        // We have waited long enough for the brake to set, turn the shooter
+        // control loop off.
+        shooter_loop_disable = true;
+        LOG(DEBUG, "Brake is now set\n");
+        if (goal && goal->shot_requested && !disabled) {
+          LOG(DEBUG, "Shooting now\n");
+          shooter_loop_disable = true;
+          shot_end_time_ = Time::Now() + kShotEndTimeout;
+          firing_starting_position_ = shooter_.absolute_position();
+          state_ = STATE_FIRE;
+        }
+      }
+      if (state_ == STATE_READY && goal &&
+          ::std::abs(shooter_.absolute_position() -
+                     PowerToPosition(goal->shot_power)) > 0.002) {
+        // TODO(austin): Add a state to release the brake.
+
+        // TODO(austin): Do we want to set the brake here or after shooting?
+        // Depends on air usage.
+        status->ready = false;
+        LOG(DEBUG, "Preparing shot again.\n");
+        state_ = STATE_PREPARE_SHOT;
+      }
+
+      if (goal) {
+        shooter_.SetGoalPosition(PowerToPosition(goal->shot_power), 0.0);
+      }
+
+      latch_piston_ = true;
+      brake_piston_ = true;
+
+      if (goal && goal->unload_requested) {
+        Unload();
+      }
+      break;
+
+    case STATE_FIRE:
+      if (disabled) {
+        if (position) {
+          if (position->plunger) {
+            // If disabled and the plunger is still back there, reset the
+            // timeout.
+            shot_end_time_ = Time::Now() + kShotEndTimeout;
+          }
+        }
+      }
+      shooter_loop_disable = true;
+      // Count the number of contiguous cycles during which we haven't moved.
+      if (::std::abs(last_position_.position - shooter_.absolute_position()) <
+          0.0005) {
+        ++cycles_not_moved_;
+      } else {
+        cycles_not_moved_ = 0;
+      }
+
+      // If we have moved any amount since the start and the shooter has now
+      // been still for a couple cycles, the shot finished.
+      // Also move on if it times out.
+      if ((::std::abs(firing_starting_position_ -
+                      shooter_.absolute_position()) > 0.0005 &&
+           cycles_not_moved_ > 3) ||
+          Time::Now() > shot_end_time_) {
+        state_ = STATE_REQUEST_LOAD;
+        ++shot_count_;
+      }
+      latch_piston_ = false;
+      brake_piston_ = true;
+      break;
+    case STATE_UNLOAD:
+      // Reset the timeouts.
+      if (disabled) Unload();
+
+      // If it is latched and the plunger is back, move the pusher back to catch
+      // the plunger.
+      bool all_back;
+      if (position) {
+        all_back = position->plunger && position->latch;
+      } else {
+        all_back = last_position_.plunger && last_position_.latch;
+      }
+
+      if (all_back) {
+        // Pull back to 0, 0.
+        shooter_.SetGoalPosition(0.0, 0.0);
+        if (shooter_.absolute_position() < 0.005) {
+          // When we are close enough, 'fire'.
+          latch_piston_ = false;
+        } else {
+          latch_piston_ = true;
+
+          if (position) {
+            CheckCalibrations(position);
+          }
+        }
+      } else {
+        // The plunger isn't all the way back, or it is and it is unlatched, so
+        // we can now unload.
+        shooter_.SetGoalPosition(shooter_.absolute_position(), 0.0);
+        latch_piston_ = false;
+        state_ = STATE_UNLOAD_MOVE;
+        unload_timeout_ = Time::Now() + kUnloadTimeout;
+      }
+
+      if (Time::Now() > unload_timeout_) {
+        // We have been stuck trying to unload for way too long, give up and
+        // turn everything off.
+        state_ = STATE_ESTOP;
+        LOG(ERROR, "Estopping because took too long to unload.\n");
+      }
+
+      brake_piston_ = false;
+      break;
+    case STATE_UNLOAD_MOVE: {
+      if (disabled) {
+        unload_timeout_ = Time::Now() + kUnloadTimeout;
+        shooter_.SetGoalPosition(shooter_.absolute_position(), 0.0);
+      }
+      cap_goal = true;
+      shooter_.set_max_voltage(6.0);
+
+      // Slowly move back until we hit the upper limit.
+      // If we were at the limit last cycle, we are done unloading.
+      // This is because if we saturate, we might hit the limit before we are
+      // actually there.
+      if (shooter_.goal_position() >= values.shooter.upper_limit) {
+        shooter_.SetGoalPosition(values.shooter.upper_limit, 0.0);
+        // We don't want the loop fighting the spring when we are unloaded.
+        // Turn it off.
+        shooter_loop_disable = true;
+        state_ = STATE_READY_UNLOAD;
+      } else {
+        shooter_.SetGoalPosition(
+            ::std::min(
+                values.shooter.upper_limit,
+                shooter_.goal_position() + values.shooter.unload_speed * dt),
+            values.shooter.unload_speed);
+      }
+
+      latch_piston_ = false;
+      brake_piston_ = false;
+    } break;
+    case STATE_READY_UNLOAD:
+      if (goal && goal->load_requested) {
+        state_ = STATE_REQUEST_LOAD;
+      }
+      // If we are ready to load again,
+      shooter_loop_disable = true;
+
+      latch_piston_ = false;
+      brake_piston_ = false;
+      break;
+
+    case STATE_ESTOP:
+      LOG(WARNING, "estopped\n");
+      // Totally lost, go to a safe state.
+      shooter_loop_disable = true;
+      latch_piston_ = true;
+      brake_piston_ = true;
+      break;
+  }
+
+  if (!shooter_loop_disable) {
+    LOG_STRUCT(DEBUG, "running the loop",
+               ShooterStatusToLog(shooter_.goal_position(),
+                                  shooter_.absolute_position()));
+    if (!cap_goal) {
+      shooter_.set_max_voltage(12.0);
+    }
+    shooter_.Update(output == NULL);
+    if (cap_goal) {
+      shooter_.CapGoal();
+    }
+    // We don't really want to output anything if we went through everything
+    // assuming the motors weren't working.
+    if (output) output->voltage = shooter_.voltage();
+  } else {
+    shooter_.Update(true);
+    shooter_.ZeroPower();
+    if (output) output->voltage = 0.0;
+  }
+
+  status->hard_stop_power = PositionToPower(shooter_.absolute_position());
+
+  if (output) {
+    output->latch_piston = latch_piston_;
+    output->brake_piston = brake_piston_;
+  }
+
+  if (position) {
+    LOG_STRUCT(DEBUG, "internal state",
+               ShooterStateToLog(
+                   shooter_.absolute_position(), shooter_.absolute_velocity(),
+                   state_, position->latch, position->pusher_proximal.current,
+                   position->pusher_distal.current, position->plunger,
+                   brake_piston_, latch_piston_));
+
+    last_position_ = *position;
+
+    last_distal_posedge_count_ = position->pusher_distal.posedge_count;
+    last_proximal_posedge_count_ = position->pusher_proximal.posedge_count;
+    last_distal_current_ = position->pusher_distal.current;
+    last_proximal_current_ = position->pusher_proximal.current;
+  }
+
+  status->shots = shot_count_;
+}
+
+void ShooterMotor::ZeroOutputs() {
+  queue_group()->output.MakeWithBuilder()
+      .voltage(0)
+      .latch_piston(latch_piston_)
+      .brake_piston(brake_piston_)
+      .Send();
+}
+
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/y2014/control_loops/shooter/shooter.gyp b/y2014/control_loops/shooter/shooter.gyp
new file mode 100644
index 0000000..e96b592
--- /dev/null
+++ b/y2014/control_loops/shooter/shooter.gyp
@@ -0,0 +1,82 @@
+{
+  'targets': [
+    {
+      'target_name': 'replay_shooter',
+      'type': 'executable',
+      'variables': {
+        'no_rsync': 1,
+      },
+      'sources': [
+        'replay_shooter.cc',
+      ],
+      'dependencies': [
+        'shooter_queue',
+        '<(AOS)/common/controls/controls.gyp:replay_control_loop',
+        '<(AOS)/linux_code/linux_code.gyp:init',
+      ],
+    },
+    {
+      'target_name': 'shooter_queue',
+      'type': 'static_library',
+      'sources': ['shooter.q'],
+      'variables': {
+        'header_path': 'y2014/control_loops/shooter',
+      },
+      'dependencies': [
+        '<(AOS)/common/controls/controls.gyp:control_loop_queues',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:queues',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/controls/controls.gyp:control_loop_queues',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:queues',
+      ],
+      'includes': ['../../../aos/build/queues.gypi'],
+    },
+    {
+      'target_name': 'shooter_lib',
+      'type': 'static_library',
+      'sources': [
+        'shooter.cc',
+        'shooter_motor_plant.cc',
+        'unaugmented_shooter_motor_plant.cc',
+      ],
+      'dependencies': [
+        'shooter_queue',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+        '<(DEPTH)/y2014/y2014.gyp:constants',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+        '<(AOS)/common/logging/logging.gyp:queue_logging',
+      ],
+      'export_dependent_settings': [
+        'shooter_queue',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+      ],
+    },
+    {
+      'target_name': 'shooter_lib_test',
+      'type': 'executable',
+      'sources': [
+        'shooter_lib_test.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+        'shooter_queue',
+        'shooter_lib',
+        '<(AOS)/common/controls/controls.gyp:control_loop_test',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+      ],
+    },
+    {
+      'target_name': 'shooter',
+      'type': 'executable',
+      'sources': [
+        'shooter_main.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        'shooter_lib',
+      ],
+    },
+  ],
+}
diff --git a/y2014/control_loops/shooter/shooter.h b/y2014/control_loops/shooter/shooter.h
new file mode 100644
index 0000000..71347cb
--- /dev/null
+++ b/y2014/control_loops/shooter/shooter.h
@@ -0,0 +1,224 @@
+#ifndef Y2014_CONTROL_LOOPS_shooter_shooter_H_
+#define Y2014_CONTROL_LOOPS_shooter_shooter_H_
+
+#include <memory>
+
+#include "aos/common/controls/control_loop.h"
+#include "frc971/control_loops/state_feedback_loop.h"
+#include "aos/common/time.h"
+
+#include "y2014/constants.h"
+#include "y2014/control_loops/shooter/shooter_motor_plant.h"
+#include "y2014/control_loops/shooter/shooter.q.h"
+
+namespace frc971 {
+namespace control_loops {
+namespace testing {
+class ShooterTest_UnloadWindupPositive_Test;
+class ShooterTest_UnloadWindupNegative_Test;
+class ShooterTest_RezeroWhileUnloading_Test;
+};
+
+using ::aos::time::Time;
+
+// Note: Everything in this file assumes that there is a 1 cycle delay between
+// power being requested and it showing up at the motor.  It assumes that
+// X_hat(2, 1) is the voltage being applied as well.  It will go unstable if
+// that isn't true.
+
+// This class implements the CapU function correctly given all the extra
+// information that we know about.
+// It does not have any zeroing logic in it, only logic to deal with a delta U
+// controller.
+class ZeroedStateFeedbackLoop : public StateFeedbackLoop<3, 1, 1> {
+ public:
+  ZeroedStateFeedbackLoop(StateFeedbackLoop<3, 1, 1> &&loop)
+      : StateFeedbackLoop<3, 1, 1>(::std::move(loop)),
+        voltage_(0.0),
+        last_voltage_(0.0),
+        uncapped_voltage_(0.0),
+        offset_(0.0),
+        max_voltage_(12.0),
+        capped_goal_(false) {}
+
+  const static int kZeroingMaxVoltage = 5;
+
+  virtual void CapU();
+
+  // Returns the accumulated voltage.
+  double voltage() const { return voltage_; }
+
+  // Returns the uncapped voltage.
+  double uncapped_voltage() const { return uncapped_voltage_; }
+
+  // Zeros the accumulator.
+  void ZeroPower() { voltage_ = 0.0; }
+
+  // Sets the calibration offset given the absolute angle and the corrisponding
+  // encoder value.
+  void SetCalibration(double encoder_val, double known_position);
+
+  double offset() const { return offset_; }
+
+  double absolute_position() const { return X_hat(0, 0) + kPositionOffset; }
+  double absolute_velocity() const { return X_hat(1, 0); }
+
+  void CorrectPosition(double position) {
+    Eigen::Matrix<double, 1, 1> Y;
+    Y << position + offset_ - kPositionOffset;
+    Correct(Y);
+  }
+
+  // Recomputes the power goal for the current controller and position/velocity.
+  void RecalculatePowerGoal();
+
+  double goal_position() const { return R(0, 0) + kPositionOffset; }
+  double goal_velocity() const { return R(1, 0); }
+  void InitializeState(double position) {
+    mutable_X_hat(0, 0) = position - kPositionOffset;
+    mutable_X_hat(1, 0) = 0.0;
+    mutable_X_hat(2, 0) = 0.0;
+  }
+
+  void SetGoalPosition(double desired_position, double desired_velocity) {
+    LOG(DEBUG, "Goal position: %f Goal velocity: %f\n", desired_position,
+        desired_velocity);
+
+    mutable_R() << desired_position - kPositionOffset, desired_velocity,
+        (-A(1, 0) / A(1, 2) * (desired_position - kPositionOffset) -
+         A(1, 1) / A(1, 2) * desired_velocity);
+  }
+
+  double position() const { return X_hat(0, 0) - offset_ + kPositionOffset; }
+
+  void set_max_voltage(double max_voltage) { max_voltage_ = max_voltage; }
+  bool capped_goal() const { return capped_goal_; }
+
+  void CapGoal();
+
+  // Friend the test classes for acces to the internal state.
+  friend class testing::ShooterTest_RezeroWhileUnloading_Test;
+
+ private:
+  // The offset between what is '0' (0 rate on the spring) and the 0 (all the
+  // way cocked).
+  constexpr static double kPositionOffset = kMaxExtension;
+  // The accumulated voltage to apply to the motor.
+  double voltage_;
+  double last_voltage_;
+  double uncapped_voltage_;
+  double offset_;
+  double max_voltage_;
+  bool capped_goal_;
+};
+
+const Time kUnloadTimeout = Time::InSeconds(10);
+const Time kLoadTimeout = Time::InSeconds(2);
+const Time kLoadProblemEndTimeout = Time::InSeconds(1.0);
+const Time kShooterBrakeSetTime = Time::InSeconds(0.05);
+// Time to wait after releasing the latch piston before winching back again.
+const Time kShotEndTimeout = Time::InSeconds(0.2);
+const Time kPrepareFireEndTime = Time::InMS(40);
+
+class ShooterMotor
+    : public aos::controls::ControlLoop<control_loops::ShooterQueue> {
+ public:
+  explicit ShooterMotor(control_loops::ShooterQueue *my_shooter =
+                            &control_loops::shooter_queue);
+
+  // True if the goal was moved to avoid goal windup.
+  bool capped_goal() const { return shooter_.capped_goal(); }
+
+  double PowerToPosition(double power);
+  double PositionToPower(double position);
+  void CheckCalibrations(const control_loops::ShooterQueue::Position *position);
+
+  typedef enum {
+    STATE_INITIALIZE = 0,
+    STATE_REQUEST_LOAD = 1,
+    STATE_LOAD_BACKTRACK = 2,
+    STATE_LOAD = 3,
+    STATE_LOADING_PROBLEM = 4,
+    STATE_PREPARE_SHOT = 5,
+    STATE_READY = 6,
+    STATE_FIRE = 8,
+    STATE_UNLOAD = 9,
+    STATE_UNLOAD_MOVE = 10,
+    STATE_READY_UNLOAD = 11,
+    STATE_ESTOP = 12
+  } State;
+
+  State state() { return state_; }
+
+ protected:
+  virtual void RunIteration(
+      const ShooterQueue::Goal *goal,
+      const control_loops::ShooterQueue::Position *position,
+      ShooterQueue::Output *output, ShooterQueue::Status *status);
+
+ private:
+  // We have to override this to keep the pistons in the correct positions.
+  virtual void ZeroOutputs();
+
+  // Friend the test classes for acces to the internal state.
+  friend class testing::ShooterTest_UnloadWindupPositive_Test;
+  friend class testing::ShooterTest_UnloadWindupNegative_Test;
+  friend class testing::ShooterTest_RezeroWhileUnloading_Test;
+
+  // Enter state STATE_UNLOAD
+  void Unload() {
+    state_ = STATE_UNLOAD;
+    unload_timeout_ = Time::Now() + kUnloadTimeout;
+  }
+  // Enter state STATE_LOAD
+  void Load() {
+    state_ = STATE_LOAD;
+    load_timeout_ = Time::Now() + kLoadTimeout;
+  }
+
+  control_loops::ShooterQueue::Position last_position_;
+
+  ZeroedStateFeedbackLoop shooter_;
+
+  // state machine state
+  State state_;
+
+  // time to giving up on loading problem
+  Time loading_problem_end_time_;
+
+  // The end time when loading for it to timeout.
+  Time load_timeout_;
+
+  // wait for brake to set
+  Time shooter_brake_set_time_;
+
+  // The timeout for unloading.
+  Time unload_timeout_;
+
+  // time that shot must have completed
+  Time shot_end_time_;
+
+  // track cycles that we are stuck to detect errors
+  int cycles_not_moved_;
+
+  double firing_starting_position_;
+
+  // True if the latch should be engaged and the brake should be engaged.
+  bool latch_piston_;
+  bool brake_piston_;
+  int32_t last_distal_posedge_count_;
+  int32_t last_proximal_posedge_count_;
+  uint32_t shot_count_;
+  bool zeroed_;
+  int distal_posedge_validation_cycles_left_;
+  int proximal_posedge_validation_cycles_left_;
+  bool last_distal_current_;
+  bool last_proximal_current_;
+
+  DISALLOW_COPY_AND_ASSIGN(ShooterMotor);
+};
+
+}  // namespace control_loops
+}  // namespace frc971
+
+#endif  // Y2014_CONTROL_LOOPS_shooter_shooter_H_
diff --git a/y2014/control_loops/shooter/shooter.q b/y2014/control_loops/shooter/shooter.q
new file mode 100644
index 0000000..009e20e
--- /dev/null
+++ b/y2014/control_loops/shooter/shooter.q
@@ -0,0 +1,100 @@
+package frc971.control_loops;
+
+import "aos/common/controls/control_loops.q";
+import "frc971/control_loops/control_loops.q";
+
+queue_group ShooterQueue {
+  implements aos.control_loops.ControlLoop;
+
+  message Output {
+    double voltage;
+    // true: latch engaged, false: latch open
+    bool latch_piston;
+    // true: brake engaged false: brake released
+    bool brake_piston;
+  };
+  message Goal {
+    // Shot power in joules.
+    double shot_power;
+    // Shoots as soon as this is true.
+    bool shot_requested;
+    bool unload_requested;
+    bool load_requested;
+  };
+
+  // Back is when the springs are all the way stretched.
+  message Position {
+    // In meters, out is positive.
+    double position;
+
+    // If the latch piston is fired and this hall effect has been triggered, the
+    // plunger is all the way back and latched.
+    bool plunger;
+    // Gets triggered when the pusher is all the way back.
+    PosedgeOnlyCountedHallEffectStruct pusher_distal;
+    // Triggers just before pusher_distal.
+    PosedgeOnlyCountedHallEffectStruct pusher_proximal;
+    // Triggers when the latch engages.
+    bool latch;
+  };
+  message Status {
+    // Whether it's ready to shoot right now.
+    bool ready;
+    // Whether the plunger is in and out of the way of grabbing a ball.
+    // TODO(ben): Populate these!
+    bool cocked;
+    // How many times we've shot.
+    int32_t shots;
+    bool done;
+    // What we think the current position of the hard stop on the shooter is, in
+    // shot power (Joules).
+    double hard_stop_power;
+  };
+
+  queue Goal goal;
+  queue Position position;
+  queue Output output;
+  queue Status status;
+};
+
+queue_group ShooterQueue shooter_queue;
+
+struct ShooterStateToLog {
+	double absolute_position;
+	double absolute_velocity;
+	uint32_t state;
+	bool latch_sensor;
+	bool proximal;
+	bool distal;
+	bool plunger;
+	bool brake;
+	bool latch_piston;
+};
+
+struct ShooterVoltageToLog {
+	double X_hat;
+	double applied;
+};
+
+struct ShooterMovingGoal {
+	double dx;
+};
+
+struct ShooterChangeCalibration {
+	double encoder;
+	double real_position;
+	double old_position;
+	double new_position;
+	double old_offset;
+	double new_offset;
+};
+
+struct ShooterStatusToLog {
+	double goal;
+	double position;
+};
+
+struct PowerAdjustment {
+	double requested_power;
+	double actual_power;
+};
diff --git a/y2014/control_loops/shooter/shooter_lib_test.cc b/y2014/control_loops/shooter/shooter_lib_test.cc
new file mode 100644
index 0000000..2beb705
--- /dev/null
+++ b/y2014/control_loops/shooter/shooter_lib_test.cc
@@ -0,0 +1,723 @@
+#include <unistd.h>
+
+#include <memory>
+
+#include "gtest/gtest.h"
+#include "aos/common/network/team_number.h"
+#include "aos/common/controls/control_loop_test.h"
+#include "y2014/control_loops/shooter/shooter.q.h"
+#include "y2014/control_loops/shooter/shooter.h"
+#include "y2014/control_loops/shooter/unaugmented_shooter_motor_plant.h"
+#include "y2014/constants.h"
+
+using ::aos::time::Time;
+
+namespace frc971 {
+namespace control_loops {
+namespace testing {
+
+static const int kTestTeam = 1;
+
+class TeamNumberEnvironment : public ::testing::Environment {
+ public:
+  // Override this to define how to set up the environment.
+  virtual void SetUp() { aos::network::OverrideTeamNumber(kTestTeam); }
+};
+
+::testing::Environment *const team_number_env =
+    ::testing::AddGlobalTestEnvironment(new TeamNumberEnvironment);
+
+
+// Class which simulates the shooter and sends out queue messages containing the
+// position.
+class ShooterSimulation {
+ public:
+  // Constructs a motor simulation.
+  ShooterSimulation(double initial_position)
+      : shooter_plant_(new StateFeedbackPlant<2, 1, 1>(MakeRawShooterPlant())),
+        latch_piston_state_(false),
+        latch_delay_count_(0),
+        plunger_latched_(false),
+        brake_piston_state_(true),
+        brake_delay_count_(0),
+        shooter_queue_(
+            ".frc971.control_loops.shooter_queue", 0xcbf22ba9,
+            ".frc971.control_loops.shooter_queue.goal",
+            ".frc971.control_loops.shooter_queue.position",
+            ".frc971.control_loops.shooter_queue.output",
+            ".frc971.control_loops.shooter_queue.status") {
+    Reinitialize(initial_position);
+  }
+
+  // The difference between the position with 0 at the back, and the position
+  // with 0 measured where the spring has 0 force.
+  constexpr static double kPositionOffset = kMaxExtension;
+
+  void Reinitialize(double initial_position) {
+    LOG(INFO, "Reinitializing to {pos: %f}\n", initial_position);
+    StateFeedbackPlant<2, 1, 1> *plant = shooter_plant_.get();
+    initial_position_ = initial_position;
+    plant->mutable_X(0, 0) = initial_position_ - kPositionOffset;
+    plant->mutable_X(1, 0) = 0.0;
+    plant->mutable_Y() = plant->C() * plant->X();
+    last_voltage_ = 0.0;
+    last_plant_position_ = 0.0;
+    SetPhysicalSensors(&last_position_message_);
+  }
+
+  // Returns the absolute angle of the shooter.
+  double GetAbsolutePosition() const {
+    return shooter_plant_->Y(0, 0) + kPositionOffset;
+  }
+
+  // Returns the adjusted angle of the shooter.
+  double GetPosition() const {
+    return GetAbsolutePosition() - initial_position_;
+  }
+
+  // Makes sure pos is inside range (inclusive)
+  bool CheckRange(double pos, struct constants::Values::AnglePair pair) {
+    return (pos >= pair.lower_angle && pos <= pair.upper_angle);
+  }
+
+  // Sets the values of the physical sensors that can be directly observed
+  // (encoder, hall effect).
+  void SetPhysicalSensors(control_loops::ShooterQueue::Position *position) {
+    const frc971::constants::Values &values = constants::GetValues();
+
+   	position->position = GetPosition();
+
+    LOG(DEBUG, "Physical shooter at {%f}\n", GetAbsolutePosition());
+
+    // Signal that the hall effect sensor has been triggered if it is within
+    // the correct range.
+    if (plunger_latched_) {
+      position->plunger = true;
+      // Only disengage the spring if we are greater than 0, which is where the
+      // latch will take the load off the pusher.
+      if (GetAbsolutePosition() > 0.0) {
+        shooter_plant_->set_plant_index(1);
+      } else {
+        shooter_plant_->set_plant_index(0);
+      }
+    } else {
+      shooter_plant_->set_plant_index(0);
+      position->plunger =
+          CheckRange(GetAbsolutePosition(), values.shooter.plunger_back);
+    }
+    position->pusher_distal.current =
+        CheckRange(GetAbsolutePosition(), values.shooter.pusher_distal);
+    position->pusher_proximal.current =
+        CheckRange(GetAbsolutePosition(), values.shooter.pusher_proximal);
+  }
+
+  void UpdateEffectEdge(
+      PosedgeOnlyCountedHallEffectStruct *sensor,
+      const PosedgeOnlyCountedHallEffectStruct &last_sensor,
+      const constants::Values::AnglePair &limits,
+      const control_loops::ShooterQueue::Position &last_position) {
+    sensor->posedge_count = last_sensor.posedge_count;
+    sensor->negedge_count = last_sensor.negedge_count;
+
+    sensor->posedge_value = last_sensor.posedge_value;
+
+    if (sensor->current && !last_sensor.current) {
+      ++sensor->posedge_count;
+      if (last_position.position + initial_position_ < limits.lower_angle) {
+        LOG(DEBUG, "Posedge value on lower edge of sensor, count is now %d\n",
+            sensor->posedge_count);
+        sensor->posedge_value = limits.lower_angle - initial_position_;
+      } else {
+        LOG(DEBUG, "Posedge value on upper edge of sensor, count is now %d\n",
+            sensor->posedge_count);
+        sensor->posedge_value = limits.upper_angle - initial_position_;
+      }
+    }
+    if (!sensor->current && last_sensor.current) {
+      ++sensor->negedge_count;
+    }
+  }
+
+  void SendPositionMessage() {
+    // the first bool is false
+    SendPositionMessage(false, false, false, false);
+  }
+
+  // Sends out the position queue messages.
+  // if the first bool is false then this is
+  // just the default state, otherwise will force
+  // it into a state using the passed values
+  void SendPositionMessage(bool use_passed, bool plunger_in,
+                           bool latch_in, bool brake_in) {
+    const frc971::constants::Values &values = constants::GetValues();
+    ::aos::ScopedMessagePtr<control_loops::ShooterQueue::Position> position =
+        shooter_queue_.position.MakeMessage();
+
+    if (use_passed) {
+      plunger_latched_ = latch_in && plunger_in;
+      latch_piston_state_ = plunger_latched_;
+      brake_piston_state_ = brake_in;
+    }
+
+    SetPhysicalSensors(position.get());
+
+    position->latch = latch_piston_state_;
+
+    // Handle pusher distal hall effect
+    UpdateEffectEdge(&position->pusher_distal,
+                     last_position_message_.pusher_distal,
+                     values.shooter.pusher_distal, last_position_message_);
+
+    // Handle pusher proximal hall effect
+    UpdateEffectEdge(&position->pusher_proximal,
+                     last_position_message_.pusher_proximal,
+                     values.shooter.pusher_proximal, last_position_message_);
+
+    last_position_message_ = *position;
+    position.Send();
+  }
+
+  // Simulates the claw moving for one timestep.
+  void Simulate() {
+    last_plant_position_ = GetAbsolutePosition();
+    EXPECT_TRUE(shooter_queue_.output.FetchLatest());
+    if (shooter_queue_.output->latch_piston && !latch_piston_state_ &&
+        latch_delay_count_ <= 0) {
+      ASSERT_EQ(0, latch_delay_count_) << "The test doesn't support that.";
+      latch_delay_count_ = 6;
+    } else if (!shooter_queue_.output->latch_piston &&
+               latch_piston_state_ && latch_delay_count_ >= 0) {
+      ASSERT_EQ(0, latch_delay_count_) << "The test doesn't support that.";
+      latch_delay_count_ = -6;
+    }
+
+    if (shooter_queue_.output->brake_piston && !brake_piston_state_ &&
+        brake_delay_count_ <= 0) {
+      ASSERT_EQ(0, brake_delay_count_) << "The test doesn't support that.";
+      brake_delay_count_ = 5;
+    } else if (!shooter_queue_.output->brake_piston &&
+               brake_piston_state_ && brake_delay_count_ >= 0) {
+      ASSERT_EQ(0, brake_delay_count_) << "The test doesn't support that.";
+      brake_delay_count_ = -5;
+    }
+
+    // Handle brake internal state
+    if (!brake_piston_state_ && brake_delay_count_ > 0) {
+      if (brake_delay_count_ == 1) {
+        brake_piston_state_ = true;
+      }
+      brake_delay_count_--;
+    } else if (brake_piston_state_ && brake_delay_count_ < 0) {
+      if (brake_delay_count_ == -1) {
+        brake_piston_state_ = false;
+      }
+      brake_delay_count_++;
+    }
+
+    if (brake_piston_state_) {
+      shooter_plant_->mutable_U() << 0.0;
+      shooter_plant_->mutable_X(1, 0) = 0.0;
+      shooter_plant_->mutable_Y() = shooter_plant_->C() * shooter_plant_->X() +
+                                   shooter_plant_->D() * shooter_plant_->U();
+    } else {
+      shooter_plant_->mutable_U() << last_voltage_;
+      //shooter_plant_->U << shooter_queue_.output->voltage;
+      shooter_plant_->Update();
+    }
+    LOG(DEBUG, "Plant index is %d\n", shooter_plant_->plant_index());
+
+    // Handle latch hall effect
+    if (!latch_piston_state_ && latch_delay_count_ > 0) {
+      LOG(DEBUG, "latching simulation: %dp\n", latch_delay_count_);
+      if (latch_delay_count_ == 1) {
+        latch_piston_state_ = true;
+        EXPECT_GE(constants::GetValues().shooter.latch_max_safe_position,
+                  GetAbsolutePosition());
+        plunger_latched_ = true;
+      }
+      latch_delay_count_--;
+    } else if (latch_piston_state_ && latch_delay_count_ < 0) {
+      LOG(DEBUG, "latching simulation: %dn\n", latch_delay_count_);
+      if (latch_delay_count_ == -1) {
+        latch_piston_state_ = false;
+        if (GetAbsolutePosition() > 0.002) {
+          EXPECT_TRUE(brake_piston_state_) << "Must have the brake set when "
+                                              "releasing the latch for "
+                                              "powerful shots.";
+        }
+        plunger_latched_ = false;
+        // TODO(austin): The brake should be set for a number of cycles after
+        // this as well.
+        shooter_plant_->mutable_X(0, 0) += 0.005;
+      }
+      latch_delay_count_++;
+    }
+
+    EXPECT_GE(constants::GetValues().shooter.upper_hard_limit,
+              GetAbsolutePosition());
+    EXPECT_LE(constants::GetValues().shooter.lower_hard_limit,
+              GetAbsolutePosition());
+
+    last_voltage_ = shooter_queue_.output->voltage;
+    ::aos::time::Time::IncrementMockTime(::aos::time::Time::InMS(10.0));
+  }
+
+  // pointer to plant
+  const ::std::unique_ptr<StateFeedbackPlant<2, 1, 1>> shooter_plant_;
+
+  // true latch closed
+  bool latch_piston_state_;
+  // greater than zero, delaying close. less than zero delaying open
+  int latch_delay_count_;
+
+  // Goes to true after latch_delay_count_ hits 0 while the plunger is back.
+  bool plunger_latched_;
+
+  // true brake locked
+  bool brake_piston_state_;
+  // greater than zero, delaying close. less than zero delaying open
+  int brake_delay_count_;
+
+ private:
+  ShooterQueue shooter_queue_;
+  double initial_position_;
+  double last_voltage_;
+
+  control_loops::ShooterQueue::Position last_position_message_;
+  double last_plant_position_;
+};
+
+class ShooterTest : public ::aos::testing::ControlLoopTest {
+
+ protected:
+  // Create a new instance of the test queue so that it invalidates the queue
+  // that it points to.  Otherwise, we will have a pointer to shared memory that
+  // is no longer valid.
+  ShooterQueue shooter_queue_;
+
+  // Create a loop and simulation plant.
+  ShooterMotor shooter_motor_;
+  ShooterSimulation shooter_motor_plant_;
+
+  void Reinitialize(double position) {
+    shooter_motor_plant_.Reinitialize(position);
+  }
+
+  ShooterTest()
+      : shooter_queue_(
+            ".frc971.control_loops.shooter_queue", 0xcbf22ba9,
+            ".frc971.control_loops.shooter_queue.goal",
+            ".frc971.control_loops.shooter_queue.position",
+            ".frc971.control_loops.shooter_queue.output",
+            ".frc971.control_loops.shooter_queue.status"),
+        shooter_motor_(&shooter_queue_),
+        shooter_motor_plant_(0.2) {
+  }
+
+  void VerifyNearGoal() {
+    shooter_queue_.goal.FetchLatest();
+    shooter_queue_.position.FetchLatest();
+    double pos = shooter_motor_plant_.GetAbsolutePosition();
+    EXPECT_NEAR(shooter_queue_.goal->shot_power, pos, 1e-4);
+  }
+};
+
+TEST_F(ShooterTest, PowerConversion) {
+  const frc971::constants::Values &values = constants::GetValues();
+  // test a couple of values return the right thing
+  EXPECT_NEAR(0.254001, shooter_motor_.PowerToPosition(140.0), 0.00001);
+  EXPECT_NEAR(0.00058, shooter_motor_.PowerToPosition(0.53), 0.00001);
+  EXPECT_NEAR(0.095251238129837101, shooter_motor_.PowerToPosition(73.67),
+              0.00001);
+
+  // value too large should get max
+  EXPECT_NEAR(values.shooter.upper_limit,
+              shooter_motor_.PowerToPosition(505050.99), 0.00001);
+  // negative values should zero
+  EXPECT_NEAR(0, shooter_motor_.PowerToPosition(-123.4), 0.00001);
+}
+
+// Test that PowerToPosition and PositionToPower are inverses of each other.
+// Note that PowerToPosition will cap position whereas PositionToPower will not
+// cap power.
+TEST_F(ShooterTest, InversePowerConversion) {
+  // Test a few values.
+  double power = 140.0;
+  double position = shooter_motor_.PowerToPosition(power);
+  EXPECT_NEAR(power, shooter_motor_.PositionToPower(position), 1e-5);
+  power = .53;
+  position = shooter_motor_.PowerToPosition(power);
+  EXPECT_NEAR(power, shooter_motor_.PositionToPower(position), 1e-5);
+  power = 71.971;
+  position = shooter_motor_.PowerToPosition(power);
+  EXPECT_NEAR(power, shooter_motor_.PositionToPower(position), 1e-5);
+}
+
+// Tests that the shooter zeros correctly and goes to a position.
+TEST_F(ShooterTest, GoesToValue) {
+  shooter_queue_.goal.MakeWithBuilder().shot_power(70.0).Send();
+  for (int i = 0; i < 200; ++i) {
+    shooter_motor_plant_.SendPositionMessage();
+    shooter_motor_.Iterate();
+    shooter_motor_plant_.Simulate();
+    SimulateTimestep(true);
+  }
+  // EXPECT_NEAR(0.0, shooter_motor_.GetPosition(), 0.01);
+  double pos = shooter_motor_plant_.GetAbsolutePosition();
+  EXPECT_NEAR(
+      shooter_motor_.PowerToPosition(shooter_queue_.goal->shot_power),
+      pos, 0.05);
+  EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
+}
+
+// Tests that the shooter zeros correctly and goes to a position.
+TEST_F(ShooterTest, Fire) {
+  shooter_queue_.goal.MakeWithBuilder().shot_power(70.0).Send();
+  for (int i = 0; i < 120; ++i) {
+    shooter_motor_plant_.SendPositionMessage();
+    shooter_motor_.Iterate();
+    shooter_motor_plant_.Simulate();
+    SimulateTimestep(true);
+  }
+  EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
+  shooter_queue_.goal.MakeWithBuilder()
+      .shot_power(35.0)
+      .shot_requested(true)
+      .Send();
+
+  bool hit_fire = false;
+  for (int i = 0; i < 400; ++i) {
+    shooter_motor_plant_.SendPositionMessage();
+    shooter_motor_.Iterate();
+    shooter_motor_plant_.Simulate();
+    SimulateTimestep(true);
+    if (shooter_motor_.state() == ShooterMotor::STATE_FIRE) {
+      if (!hit_fire) {
+        shooter_queue_.goal.MakeWithBuilder()
+            .shot_power(17.0)
+            .shot_requested(false)
+            .Send();
+      }
+      hit_fire = true;
+    }
+  }
+
+  double pos = shooter_motor_plant_.GetAbsolutePosition();
+  EXPECT_NEAR(
+      shooter_motor_.PowerToPosition(shooter_queue_.goal->shot_power),
+      pos, 0.05);
+  EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
+  EXPECT_TRUE(hit_fire);
+}
+
+// Tests that the shooter zeros correctly and goes to a position.
+TEST_F(ShooterTest, FireLong) {
+  shooter_queue_.goal.MakeWithBuilder().shot_power(70.0).Send();
+  for (int i = 0; i < 150; ++i) {
+    shooter_motor_plant_.SendPositionMessage();
+    shooter_motor_.Iterate();
+    shooter_motor_plant_.Simulate();
+    SimulateTimestep(true);
+  }
+  EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
+  shooter_queue_.goal.MakeWithBuilder().shot_requested(true).Send();
+
+  bool hit_fire = false;
+  for (int i = 0; i < 400; ++i) {
+    shooter_motor_plant_.SendPositionMessage();
+    shooter_motor_.Iterate();
+    shooter_motor_plant_.Simulate();
+    SimulateTimestep(true);
+    if (shooter_motor_.state() == ShooterMotor::STATE_FIRE) {
+      if (!hit_fire) {
+        shooter_queue_.goal.MakeWithBuilder()
+            .shot_requested(false)
+            .Send();
+      }
+      hit_fire = true;
+    }
+  }
+
+  double pos = shooter_motor_plant_.GetAbsolutePosition();
+  EXPECT_NEAR(shooter_motor_.PowerToPosition(shooter_queue_.goal->shot_power), pos, 0.05);
+  EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
+  EXPECT_TRUE(hit_fire);
+}
+
+// Verifies that it doesn't try to go out too far if you give it a ridicilous
+// power.
+TEST_F(ShooterTest, LoadTooFar) {
+  shooter_queue_.goal.MakeWithBuilder().shot_power(500.0).Send();
+  for (int i = 0; i < 160; ++i) {
+    shooter_motor_plant_.SendPositionMessage();
+    shooter_motor_.Iterate();
+    shooter_motor_plant_.Simulate();
+    SimulateTimestep(true);
+    EXPECT_LT(
+        shooter_motor_plant_.GetAbsolutePosition(),
+        constants::GetValuesForTeam(kTestTeam).shooter.upper_limit);
+  }
+  EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
+}
+
+// Tests that the shooter zeros correctly and goes to a position.
+TEST_F(ShooterTest, MoveGoal) {
+  shooter_queue_.goal.MakeWithBuilder().shot_power(70.0).Send();
+  for (int i = 0; i < 150; ++i) {
+    shooter_motor_plant_.SendPositionMessage();
+    shooter_motor_.Iterate();
+    shooter_motor_plant_.Simulate();
+    SimulateTimestep(true);
+  }
+  EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
+  shooter_queue_.goal.MakeWithBuilder().shot_power(14.0).Send();
+
+  for (int i = 0; i < 100; ++i) {
+    shooter_motor_plant_.SendPositionMessage();
+    shooter_motor_.Iterate();
+    shooter_motor_plant_.Simulate();
+    SimulateTimestep(true);
+  }
+
+  double pos = shooter_motor_plant_.GetAbsolutePosition();
+  EXPECT_NEAR(
+      shooter_motor_.PowerToPosition(shooter_queue_.goal->shot_power),
+      pos, 0.05);
+  EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
+}
+
+
+TEST_F(ShooterTest, Unload) {
+  shooter_queue_.goal.MakeWithBuilder().shot_power(70.0).Send();
+  for (int i = 0; i < 150; ++i) {
+    shooter_motor_plant_.SendPositionMessage();
+    shooter_motor_.Iterate();
+    shooter_motor_plant_.Simulate();
+    SimulateTimestep(true);
+  }
+  EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
+  shooter_queue_.goal.MakeWithBuilder().unload_requested(true).Send();
+
+  for (int i = 0;
+       i < 800 && shooter_motor_.state() != ShooterMotor::STATE_READY_UNLOAD;
+       ++i) {
+    shooter_motor_plant_.SendPositionMessage();
+    shooter_motor_.Iterate();
+    shooter_motor_plant_.Simulate();
+    SimulateTimestep(true);
+  }
+
+  EXPECT_NEAR(constants::GetValues().shooter.upper_limit,
+              shooter_motor_plant_.GetAbsolutePosition(), 0.015);
+  EXPECT_EQ(ShooterMotor::STATE_READY_UNLOAD, shooter_motor_.state());
+}
+
+// Tests that it rezeros while unloading.
+TEST_F(ShooterTest, RezeroWhileUnloading) {
+  shooter_queue_.goal.MakeWithBuilder().shot_power(70.0).Send();
+  for (int i = 0; i < 150; ++i) {
+    shooter_motor_plant_.SendPositionMessage();
+    shooter_motor_.Iterate();
+    shooter_motor_plant_.Simulate();
+    SimulateTimestep(true);
+  }
+  EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
+
+  shooter_motor_.shooter_.offset_ += 0.01;
+  for (int i = 0; i < 50; ++i) {
+    shooter_motor_plant_.SendPositionMessage();
+    shooter_motor_.Iterate();
+    shooter_motor_plant_.Simulate();
+    SimulateTimestep(true);
+  }
+
+  shooter_queue_.goal.MakeWithBuilder().unload_requested(true).Send();
+
+  for (int i = 0;
+       i < 800 && shooter_motor_.state() != ShooterMotor::STATE_READY_UNLOAD;
+       ++i) {
+    shooter_motor_plant_.SendPositionMessage();
+    shooter_motor_.Iterate();
+    shooter_motor_plant_.Simulate();
+    SimulateTimestep(true);
+  }
+
+  EXPECT_NEAR(constants::GetValues().shooter.upper_limit,
+              shooter_motor_plant_.GetAbsolutePosition(), 0.015);
+  EXPECT_EQ(ShooterMotor::STATE_READY_UNLOAD, shooter_motor_.state());
+}
+
+// Tests that the shooter zeros correctly and goes to a position.
+TEST_F(ShooterTest, UnloadWindupNegative) {
+  shooter_queue_.goal.MakeWithBuilder().shot_power(70.0).Send();
+  for (int i = 0; i < 150; ++i) {
+    shooter_motor_plant_.SendPositionMessage();
+    shooter_motor_.Iterate();
+    shooter_motor_plant_.Simulate();
+    SimulateTimestep(true);
+  }
+  EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
+  shooter_queue_.goal.MakeWithBuilder().unload_requested(true).Send();
+
+  int kicked_delay = 20;
+  int capped_goal_count = 0;
+  for (int i = 0;
+       i < 800 && shooter_motor_.state() != ShooterMotor::STATE_READY_UNLOAD;
+       ++i) {
+    shooter_motor_plant_.SendPositionMessage();
+    shooter_motor_.Iterate();
+    if (shooter_motor_.state() == ShooterMotor::STATE_UNLOAD_MOVE) {
+      LOG(DEBUG, "State is UnloadMove\n");
+      --kicked_delay;
+      if (kicked_delay == 0) {
+        shooter_motor_.shooter_.mutable_R(0, 0) -= 100;
+      }
+    }
+    if (shooter_motor_.capped_goal() && kicked_delay < 0) {
+      ++capped_goal_count;
+    }
+    shooter_motor_plant_.Simulate();
+    SimulateTimestep(true);
+  }
+
+  EXPECT_NEAR(constants::GetValues().shooter.upper_limit,
+              shooter_motor_plant_.GetAbsolutePosition(), 0.05);
+  EXPECT_EQ(ShooterMotor::STATE_READY_UNLOAD, shooter_motor_.state());
+  EXPECT_LE(1, capped_goal_count);
+  EXPECT_GE(3, capped_goal_count);
+}
+
+// Tests that the shooter zeros correctly and goes to a position.
+TEST_F(ShooterTest, UnloadWindupPositive) {
+  shooter_queue_.goal.MakeWithBuilder().shot_power(70.0).Send();
+  for (int i = 0; i < 150; ++i) {
+    shooter_motor_plant_.SendPositionMessage();
+    shooter_motor_.Iterate();
+    shooter_motor_plant_.Simulate();
+    SimulateTimestep(true);
+  }
+  EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
+  shooter_queue_.goal.MakeWithBuilder().unload_requested(true).Send();
+
+  int kicked_delay = 20;
+  int capped_goal_count = 0;
+  for (int i = 0;
+       i < 800 && shooter_motor_.state() != ShooterMotor::STATE_READY_UNLOAD;
+       ++i) {
+    shooter_motor_plant_.SendPositionMessage();
+    shooter_motor_.Iterate();
+    if (shooter_motor_.state() == ShooterMotor::STATE_UNLOAD_MOVE) {
+      LOG(DEBUG, "State is UnloadMove\n");
+      --kicked_delay;
+      if (kicked_delay == 0) {
+        shooter_motor_.shooter_.mutable_R(0, 0) += 0.1;
+      }
+    }
+    if (shooter_motor_.capped_goal() && kicked_delay < 0) {
+      ++capped_goal_count;
+    }
+    shooter_motor_plant_.Simulate();
+    SimulateTimestep(true);
+  }
+
+  EXPECT_NEAR(constants::GetValues().shooter.upper_limit,
+              shooter_motor_plant_.GetAbsolutePosition(), 0.05);
+  EXPECT_EQ(ShooterMotor::STATE_READY_UNLOAD, shooter_motor_.state());
+  EXPECT_LE(1, capped_goal_count);
+  EXPECT_GE(3, capped_goal_count);
+}
+
+double HallEffectMiddle(constants::Values::AnglePair pair) {
+  return (pair.lower_angle + pair.upper_angle) / 2.0;
+}
+
+// Tests that the shooter zeros correctly and goes to a position.
+TEST_F(ShooterTest, StartsOnDistal) {
+  Reinitialize(HallEffectMiddle(constants::GetValues().shooter.pusher_distal));
+  shooter_queue_.goal.MakeWithBuilder().shot_power(70.0).Send();
+  for (int i = 0; i < 200; ++i) {
+    shooter_motor_plant_.SendPositionMessage();
+    shooter_motor_.Iterate();
+    shooter_motor_plant_.Simulate();
+    SimulateTimestep(true);
+  }
+  // EXPECT_NEAR(0.0, shooter_motor_.GetPosition(), 0.01);
+  double pos = shooter_motor_plant_.GetAbsolutePosition();
+  EXPECT_NEAR(
+      shooter_motor_.PowerToPosition(shooter_queue_.goal->shot_power),
+      pos, 0.05);
+  EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
+}
+
+
+// Tests that the shooter zeros correctly and goes to a position.
+TEST_F(ShooterTest, StartsOnProximal) {
+  Reinitialize(
+      HallEffectMiddle(constants::GetValues().shooter.pusher_proximal));
+  shooter_queue_.goal.MakeWithBuilder().shot_power(70.0).Send();
+  for (int i = 0; i < 300; ++i) {
+    shooter_motor_plant_.SendPositionMessage();
+    shooter_motor_.Iterate();
+    shooter_motor_plant_.Simulate();
+    SimulateTimestep(true);
+  }
+  // EXPECT_NEAR(0.0, shooter_motor_.GetPosition(), 0.01);
+  double pos = shooter_motor_plant_.GetAbsolutePosition();
+  EXPECT_NEAR(
+      shooter_motor_.PowerToPosition(shooter_queue_.goal->shot_power),
+      pos, 0.05);
+  EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
+}
+
+class ShooterZeroingTest : public ShooterTest,
+                    public ::testing::WithParamInterface<
+                        ::std::tr1::tuple<bool, bool, bool, double>> {};
+
+TEST_P(ShooterZeroingTest, AllDisparateStartingZero) {
+  bool latch = ::std::tr1::get<0>(GetParam());
+  bool brake = ::std::tr1::get<1>(GetParam());
+  bool plunger_back = ::std::tr1::get<2>(GetParam());
+  double start_pos = ::std::tr1::get<3>(GetParam());
+  // flag to initialize test
+	//printf("@@@@ l= %d b= %d p= %d s= %.3f\n",
+	//		latch, brake, plunger_back, start_pos);
+  bool initialized = false;
+  Reinitialize(start_pos);
+  shooter_queue_.goal.MakeWithBuilder().shot_power(120.0).Send();
+  for (int i = 0; i < 200; ++i) {
+    shooter_motor_plant_.SendPositionMessage(!initialized, plunger_back, latch, brake);
+    initialized = true;
+    shooter_motor_.Iterate();
+    shooter_motor_plant_.Simulate();
+    SimulateTimestep(true);
+  }
+  // EXPECT_NEAR(0.0, shooter_motor_.GetPosition(), 0.01);
+  double pos = shooter_motor_plant_.GetAbsolutePosition();
+  EXPECT_NEAR(
+      shooter_motor_.PowerToPosition(shooter_queue_.goal->shot_power),
+      pos, 0.05);
+  ASSERT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
+}
+
+INSTANTIATE_TEST_CASE_P(
+    ShooterZeroingTest, ShooterZeroingTest,
+    ::testing::Combine(
+        ::testing::Bool(), ::testing::Bool(), ::testing::Bool(),
+        ::testing::Values(
+            0.05,
+            constants::GetValuesForTeam(kTestTeam).shooter.upper_limit - 0.05,
+            HallEffectMiddle(constants::GetValuesForTeam(kTestTeam)
+                                 .shooter.pusher_proximal),
+            HallEffectMiddle(constants::GetValuesForTeam(kTestTeam)
+                                 .shooter.pusher_distal),
+            constants::GetValuesForTeam(kTestTeam)
+                    .shooter.latch_max_safe_position -
+                0.001)));
+
+// TODO(austin): Slip the encoder somewhere.
+
+// TODO(austin): Test all the timeouts...
+
+}  // namespace testing
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/y2014/control_loops/shooter/shooter_main.cc b/y2014/control_loops/shooter/shooter_main.cc
new file mode 100644
index 0000000..31b24bf
--- /dev/null
+++ b/y2014/control_loops/shooter/shooter_main.cc
@@ -0,0 +1,11 @@
+#include "y2014/control_loops/shooter/shooter.h"
+
+#include "aos/linux_code/init.h"
+
+int main() {
+  ::aos::Init();
+  frc971::control_loops::ShooterMotor shooter;
+  shooter.Run();
+  ::aos::Cleanup();
+  return 0;
+}
diff --git a/y2014/control_loops/shooter/shooter_motor_plant.cc b/y2014/control_loops/shooter/shooter_motor_plant.cc
new file mode 100644
index 0000000..7da6407
--- /dev/null
+++ b/y2014/control_loops/shooter/shooter_motor_plant.cc
@@ -0,0 +1,77 @@
+#include "y2014/control_loops/shooter/shooter_motor_plant.h"
+
+#include <vector>
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace frc971 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<3, 1, 1> MakeSprungShooterPlantCoefficients() {
+  Eigen::Matrix<double, 3, 3> A;
+  A << 0.999391114909, 0.00811316740387, 7.59766686183e-05, -0.113584343654, 0.64780421498, 0.0141730519709, 0.0, 0.0, 1.0;
+  Eigen::Matrix<double, 3, 1> B;
+  B << 0.0, 0.0, 1.0;
+  Eigen::Matrix<double, 1, 3> C;
+  C << 1.0, 0.0, 0.0;
+  Eigen::Matrix<double, 1, 1> D;
+  D << 0.0;
+  Eigen::Matrix<double, 1, 1> U_max;
+  U_max << 12.0;
+  Eigen::Matrix<double, 1, 1> U_min;
+  U_min << -12.0;
+  return StateFeedbackPlantCoefficients<3, 1, 1>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackPlantCoefficients<3, 1, 1> MakeShooterPlantCoefficients() {
+  Eigen::Matrix<double, 3, 3> A;
+  A << 1.0, 0.00811505488455, 7.59852687598e-05, 0.0, 0.648331305446, 0.0141763492481, 0.0, 0.0, 1.0;
+  Eigen::Matrix<double, 3, 1> B;
+  B << 0.0, 0.0, 1.0;
+  Eigen::Matrix<double, 1, 3> C;
+  C << 1.0, 0.0, 0.0;
+  Eigen::Matrix<double, 1, 1> D;
+  D << 0.0;
+  Eigen::Matrix<double, 1, 1> U_max;
+  U_max << 12.0;
+  Eigen::Matrix<double, 1, 1> U_min;
+  U_min << -12.0;
+  return StateFeedbackPlantCoefficients<3, 1, 1>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackController<3, 1, 1> MakeSprungShooterController() {
+  Eigen::Matrix<double, 3, 1> L;
+  L << 1.64719532989, 57.0572680832, 636.74290365;
+  Eigen::Matrix<double, 1, 3> K;
+  K << 450.571849185, 11.8404918938, 0.997195329889;
+  Eigen::Matrix<double, 3, 3> A_inv;
+  A_inv << 0.99918700445, -0.0125139220268, 0.00010144556732, 0.175194908375, 1.54148211958, -0.0218608169185, 0.0, 0.0, 1.0;
+  return StateFeedbackController<3, 1, 1>(L, K, A_inv, MakeSprungShooterPlantCoefficients());
+}
+
+StateFeedbackController<3, 1, 1> MakeShooterController() {
+  Eigen::Matrix<double, 3, 1> L;
+  L << 1.64833130545, 57.2417604572, 636.668851906;
+  Eigen::Matrix<double, 1, 3> K;
+  K << 349.173113146, 8.65077618169, 0.848331305446;
+  Eigen::Matrix<double, 3, 3> A_inv;
+  A_inv << 1.0, -0.0125168333171, 0.000101457731824, 0.0, 1.5424212769, -0.021865902709, 0.0, 0.0, 1.0;
+  return StateFeedbackController<3, 1, 1>(L, K, A_inv, MakeShooterPlantCoefficients());
+}
+
+StateFeedbackPlant<3, 1, 1> MakeShooterPlant() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackPlantCoefficients<3, 1, 1>>> plants(2);
+  plants[0] = ::std::unique_ptr<StateFeedbackPlantCoefficients<3, 1, 1>>(new StateFeedbackPlantCoefficients<3, 1, 1>(MakeSprungShooterPlantCoefficients()));
+  plants[1] = ::std::unique_ptr<StateFeedbackPlantCoefficients<3, 1, 1>>(new StateFeedbackPlantCoefficients<3, 1, 1>(MakeShooterPlantCoefficients()));
+  return StateFeedbackPlant<3, 1, 1>(&plants);
+}
+
+StateFeedbackLoop<3, 1, 1> MakeShooterLoop() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackController<3, 1, 1>>> controllers(2);
+  controllers[0] = ::std::unique_ptr<StateFeedbackController<3, 1, 1>>(new StateFeedbackController<3, 1, 1>(MakeSprungShooterController()));
+  controllers[1] = ::std::unique_ptr<StateFeedbackController<3, 1, 1>>(new StateFeedbackController<3, 1, 1>(MakeShooterController()));
+  return StateFeedbackLoop<3, 1, 1>(&controllers);
+}
+
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/y2014/control_loops/shooter/shooter_motor_plant.h b/y2014/control_loops/shooter/shooter_motor_plant.h
new file mode 100644
index 0000000..45d6ed1
--- /dev/null
+++ b/y2014/control_loops/shooter/shooter_motor_plant.h
@@ -0,0 +1,28 @@
+#ifndef Y2014_CONTROL_LOOPS_SHOOTER_SHOOTER_MOTOR_PLANT_H_
+#define Y2014_CONTROL_LOOPS_SHOOTER_SHOOTER_MOTOR_PLANT_H_
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace frc971 {
+namespace control_loops {
+static constexpr double kMaxExtension = 0.323850;
+
+static constexpr double kSpringConstant = 2800.000000;
+
+
+StateFeedbackPlantCoefficients<3, 1, 1> MakeSprungShooterPlantCoefficients();
+
+StateFeedbackController<3, 1, 1> MakeSprungShooterController();
+
+StateFeedbackPlantCoefficients<3, 1, 1> MakeShooterPlantCoefficients();
+
+StateFeedbackController<3, 1, 1> MakeShooterController();
+
+StateFeedbackPlant<3, 1, 1> MakeShooterPlant();
+
+StateFeedbackLoop<3, 1, 1> MakeShooterLoop();
+
+}  // namespace control_loops
+}  // namespace frc971
+
+#endif  // Y2014_CONTROL_LOOPS_SHOOTER_SHOOTER_MOTOR_PLANT_H_
diff --git a/y2014/control_loops/shooter/unaugmented_shooter_motor_plant.cc b/y2014/control_loops/shooter/unaugmented_shooter_motor_plant.cc
new file mode 100644
index 0000000..8311948
--- /dev/null
+++ b/y2014/control_loops/shooter/unaugmented_shooter_motor_plant.cc
@@ -0,0 +1,77 @@
+#include "y2014/control_loops/shooter/unaugmented_shooter_motor_plant.h"
+
+#include <vector>
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace frc971 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<2, 1, 1> MakeRawSprungShooterPlantCoefficients() {
+  Eigen::Matrix<double, 2, 2> A;
+  A << 0.999391114909, 0.00811316740387, -0.113584343654, 0.64780421498;
+  Eigen::Matrix<double, 2, 1> B;
+  B << 7.59766686183e-05, 0.0141730519709;
+  Eigen::Matrix<double, 1, 2> C;
+  C << 1, 0;
+  Eigen::Matrix<double, 1, 1> D;
+  D << 0;
+  Eigen::Matrix<double, 1, 1> U_max;
+  U_max << 12.0;
+  Eigen::Matrix<double, 1, 1> U_min;
+  U_min << -12.0;
+  return StateFeedbackPlantCoefficients<2, 1, 1>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackPlantCoefficients<2, 1, 1> MakeRawShooterPlantCoefficients() {
+  Eigen::Matrix<double, 2, 2> A;
+  A << 1.0, 0.00811505488455, 0.0, 0.648331305446;
+  Eigen::Matrix<double, 2, 1> B;
+  B << 7.59852687598e-05, 0.0141763492481;
+  Eigen::Matrix<double, 1, 2> C;
+  C << 1, 0;
+  Eigen::Matrix<double, 1, 1> D;
+  D << 0;
+  Eigen::Matrix<double, 1, 1> U_max;
+  U_max << 12.0;
+  Eigen::Matrix<double, 1, 1> U_min;
+  U_min << -12.0;
+  return StateFeedbackPlantCoefficients<2, 1, 1>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackController<2, 1, 1> MakeRawSprungShooterController() {
+  Eigen::Matrix<double, 2, 1> L;
+  L << 1.54719532989, 43.9345489758;
+  Eigen::Matrix<double, 1, 2> K;
+  K << 2126.06977433, 41.3223370936;
+  Eigen::Matrix<double, 2, 2> A_inv;
+  A_inv << 0.99918700445, -0.0125139220268, 0.175194908375, 1.54148211958;
+  return StateFeedbackController<2, 1, 1>(L, K, A_inv, MakeRawSprungShooterPlantCoefficients());
+}
+
+StateFeedbackController<2, 1, 1> MakeRawShooterController() {
+  Eigen::Matrix<double, 2, 1> L;
+  L << 1.54833130545, 44.1155797675;
+  Eigen::Matrix<double, 1, 2> K;
+  K << 2133.83569145, 41.3499425476;
+  Eigen::Matrix<double, 2, 2> A_inv;
+  A_inv << 1.0, -0.0125168333171, 0.0, 1.5424212769;
+  return StateFeedbackController<2, 1, 1>(L, K, A_inv, MakeRawShooterPlantCoefficients());
+}
+
+StateFeedbackPlant<2, 1, 1> MakeRawShooterPlant() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackPlantCoefficients<2, 1, 1>>> plants(2);
+  plants[0] = ::std::unique_ptr<StateFeedbackPlantCoefficients<2, 1, 1>>(new StateFeedbackPlantCoefficients<2, 1, 1>(MakeRawSprungShooterPlantCoefficients()));
+  plants[1] = ::std::unique_ptr<StateFeedbackPlantCoefficients<2, 1, 1>>(new StateFeedbackPlantCoefficients<2, 1, 1>(MakeRawShooterPlantCoefficients()));
+  return StateFeedbackPlant<2, 1, 1>(&plants);
+}
+
+StateFeedbackLoop<2, 1, 1> MakeRawShooterLoop() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackController<2, 1, 1>>> controllers(2);
+  controllers[0] = ::std::unique_ptr<StateFeedbackController<2, 1, 1>>(new StateFeedbackController<2, 1, 1>(MakeRawSprungShooterController()));
+  controllers[1] = ::std::unique_ptr<StateFeedbackController<2, 1, 1>>(new StateFeedbackController<2, 1, 1>(MakeRawShooterController()));
+  return StateFeedbackLoop<2, 1, 1>(&controllers);
+}
+
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/y2014/control_loops/shooter/unaugmented_shooter_motor_plant.h b/y2014/control_loops/shooter/unaugmented_shooter_motor_plant.h
new file mode 100644
index 0000000..5b7de85
--- /dev/null
+++ b/y2014/control_loops/shooter/unaugmented_shooter_motor_plant.h
@@ -0,0 +1,24 @@
+#ifndef Y2014_CONTROL_LOOPS_SHOOTER_UNAUGMENTED_SHOOTER_MOTOR_PLANT_H_
+#define Y2014_CONTROL_LOOPS_SHOOTER_UNAUGMENTED_SHOOTER_MOTOR_PLANT_H_
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace frc971 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<2, 1, 1> MakeRawSprungShooterPlantCoefficients();
+
+StateFeedbackController<2, 1, 1> MakeRawSprungShooterController();
+
+StateFeedbackPlantCoefficients<2, 1, 1> MakeRawShooterPlantCoefficients();
+
+StateFeedbackController<2, 1, 1> MakeRawShooterController();
+
+StateFeedbackPlant<2, 1, 1> MakeRawShooterPlant();
+
+StateFeedbackLoop<2, 1, 1> MakeRawShooterLoop();
+
+}  // namespace control_loops
+}  // namespace frc971
+
+#endif  // Y2014_CONTROL_LOOPS_SHOOTER_UNAUGMENTED_SHOOTER_MOTOR_PLANT_H_
diff --git a/y2014/control_loops/update_arm.sh b/y2014/control_loops/update_arm.sh
new file mode 100755
index 0000000..c4c1ab9
--- /dev/null
+++ b/y2014/control_loops/update_arm.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+#
+# Updates the arm controllers (for both robots).
+
+cd $(dirname $0)
+
+./python/arm.py fridge/arm_motor_plant.cc \
+    fridge/arm_motor_plant.h \
+    fridge/integral_arm_plant.cc \
+    fridge/integral_arm_plant.h
diff --git a/y2014/control_loops/update_claw.sh b/y2014/control_loops/update_claw.sh
new file mode 100755
index 0000000..2800d2a
--- /dev/null
+++ b/y2014/control_loops/update_claw.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+#
+# Updates the claw controllers.
+
+cd $(dirname $0)
+
+./python/claw.py claw/claw_motor_plant.h \
+    claw/claw_motor_plant.cc
diff --git a/y2014/control_loops/update_drivetrain.sh b/y2014/control_loops/update_drivetrain.sh
new file mode 100755
index 0000000..bad1074
--- /dev/null
+++ b/y2014/control_loops/update_drivetrain.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+#
+# Updates the drivetrain controllers (for both robots).
+
+cd $(dirname $0)
+
+./python/drivetrain.py drivetrain/drivetrain_dog_motor_plant.h \
+    drivetrain/drivetrain_dog_motor_plant.cc \
+    drivetrain/drivetrain_clutch_motor_plant.h \
+    drivetrain/drivetrain_clutch_motor_plant.cc
diff --git a/y2014/control_loops/update_polydrivetrain.sh b/y2014/control_loops/update_polydrivetrain.sh
new file mode 100755
index 0000000..2e2748e
--- /dev/null
+++ b/y2014/control_loops/update_polydrivetrain.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+#
+# Updates the polydrivetrain controllers (for both robots) and CIM models.
+
+cd $(dirname $0)
+
+./python/polydrivetrain.py drivetrain/polydrivetrain_dog_motor_plant.h \
+    drivetrain/polydrivetrain_dog_motor_plant.cc \
+    drivetrain/polydrivetrain_clutch_motor_plant.h \
+    drivetrain/polydrivetrain_clutch_motor_plant.cc \
+    drivetrain/polydrivetrain_cim_plant.h \
+    drivetrain/polydrivetrain_cim_plant.cc
diff --git a/y2014/control_loops/update_shooter.sh b/y2014/control_loops/update_shooter.sh
new file mode 100755
index 0000000..a9c5807
--- /dev/null
+++ b/y2014/control_loops/update_shooter.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+#
+# Updates the shooter controller.
+
+cd $(dirname $0)
+
+./python/shooter.py shooter/shooter_motor_plant.h \
+    shooter/shooter_motor_plant.cc \
+    shooter/unaugmented_shooter_motor_plant.h \
+    shooter/unaugmented_shooter_motor_plant.cc
diff --git a/y2014/joystick_reader.cc b/y2014/joystick_reader.cc
new file mode 100644
index 0000000..8bbf452
--- /dev/null
+++ b/y2014/joystick_reader.cc
@@ -0,0 +1,529 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <math.h>
+
+#include "aos/linux_code/init.h"
+#include "aos/prime/input/joystick_input.h"
+#include "aos/common/input/driver_station_data.h"
+#include "aos/common/logging/logging.h"
+#include "aos/common/util/log_interval.h"
+#include "aos/common/time.h"
+#include "aos/common/actions/actions.h"
+
+#include "y2014/control_loops/drivetrain/drivetrain.q.h"
+#include "y2014/constants.h"
+#include "frc971/queues/gyro.q.h"
+#include "frc971/autonomous/auto.q.h"
+#include "y2014/control_loops/claw/claw.q.h"
+#include "y2014/control_loops/shooter/shooter.q.h"
+#include "y2014/actors/shoot_actor.h"
+
+using ::frc971::control_loops::drivetrain_queue;
+using ::frc971::sensors::gyro_reading;
+
+using ::aos::input::driver_station::ButtonLocation;
+using ::aos::input::driver_station::JoystickAxis;
+using ::aos::input::driver_station::ControlBit;
+
+#define OLD_DS 0
+
+namespace frc971 {
+namespace input {
+namespace joysticks {
+
+const ButtonLocation kDriveControlLoopEnable1(1, 7),
+                     kDriveControlLoopEnable2(1, 11);
+const JoystickAxis kSteeringWheel(1, 1), kDriveThrottle(2, 2);
+const ButtonLocation kShiftHigh(2, 1), kShiftLow(2, 3);
+const ButtonLocation kQuickTurn(1, 5);
+
+const ButtonLocation kCatch(3, 10);
+
+#if OLD_DS
+const ButtonLocation kFire(3, 11);
+const ButtonLocation kUnload(1, 4);
+const ButtonLocation kReload(1, 2);
+
+const ButtonLocation kRollersOut(3, 12);
+const ButtonLocation kRollersIn(3, 7);
+
+const ButtonLocation kTuck(3, 9);
+const ButtonLocation kIntakePosition(3, 8);
+const ButtonLocation kIntakeOpenPosition(3, 10);
+const ButtonLocation kVerticalTuck(3, 1);
+const JoystickAxis kFlipRobot(3, 3);
+
+const ButtonLocation kLongShot(3, 5);
+const ButtonLocation kCloseShot(3, 2);
+const ButtonLocation kFenderShot(3, 3);
+const ButtonLocation kTrussShot(2, 11);
+const ButtonLocation kHumanPlayerShot(3, 2);
+#else
+const ButtonLocation kFire(3, 9);
+const ButtonLocation kUnload(1, 4);
+const ButtonLocation kReload(1, 2);
+
+const ButtonLocation kRollersOut(3, 8);
+const ButtonLocation kRollersIn(3, 3);
+
+const ButtonLocation kTuck(3, 4);
+const ButtonLocation kIntakePosition(3, 5);
+const ButtonLocation kIntakeOpenPosition(3, 11);
+const ButtonLocation kVerticalTuck(2, 6);
+const JoystickAxis kFlipRobot(3, 3);
+
+const ButtonLocation kLongShot(3, 7);
+const ButtonLocation kCloseShot(3, 6);
+const ButtonLocation kFenderShot(3, 2);
+const ButtonLocation kTrussShot(2, 11);
+const ButtonLocation kHumanPlayerShot(3, 1);
+#endif
+
+const ButtonLocation kUserLeft(2, 7);
+const ButtonLocation kUserRight(2, 10);
+
+const JoystickAxis kAdjustClawGoal(3, 2);
+const JoystickAxis kAdjustClawSeparation(3, 1);
+
+struct ClawGoal {
+  double angle;
+  double separation;
+};
+
+struct ShotGoal {
+  ClawGoal claw;
+  double shot_power;
+  double velocity_compensation;
+  double intake_power;
+};
+
+const double kIntakePower = 4.0;
+// In case we have to quickly adjust it.
+const double kGrabSeparation = 0;
+const double kShootSeparation = 0.11 + kGrabSeparation;
+
+const ClawGoal kTuckGoal = {-2.273474, -0.749484};
+const ClawGoal kVerticalTuckGoal = {0, kGrabSeparation};
+const ClawGoal kIntakeGoal = {-2.24, kGrabSeparation};
+const ClawGoal kIntakeOpenGoal = {-2.0, 1.1};
+
+// TODO(austin): Tune these by hand...
+const ClawGoal kFlippedTuckGoal = {2.733474, -0.75};
+const ClawGoal kFlippedIntakeGoal = {2.0, kGrabSeparation};
+const ClawGoal kFlippedIntakeOpenGoal = {0.95, 1.0};
+
+// 34" between near edge of colored line and rear edge of bumper.
+// Only works running?
+const ShotGoal kLongShotGoal = {
+    {-1.08, kShootSeparation}, 145, 0.04, kIntakePower};
+// old 34" {-1.06, kShootSeparation}, 140, 0.04, kIntakePower};
+const ShotGoal kFlippedLongShotGoal = {
+    {0.96, kShootSeparation}, 145, 0.09, kIntakePower};
+// old 34" {0.96, kShootSeparation}, 140, 0.09, kIntakePower};
+
+// 78" between near edge of colored line and rear edge of bumper.
+const ShotGoal kCloseShotGoal = {
+    {-0.95, kShootSeparation}, 105, 0.2, kIntakePower};
+// 3/4" plunger {-0.90, kShootSeparation}, 105, 0.2, kIntakePower};
+const ShotGoal kFlippedMediumShotGoal = {
+    {0.865, kShootSeparation}, 120, 0.2, kIntakePower};
+// 3/4" plunger {0.80, kShootSeparation}, 105, 0.2, kIntakePower};
+
+// Shot from the fender.
+const ShotGoal kFenderShotGoal = {
+    {-0.68, kShootSeparation}, 115.0, 0.0, kIntakePower};
+const ShotGoal kFlippedShortShotGoal = {
+    {0.63, kShootSeparation}, 115.0, 0.0, kIntakePower};
+
+const ShotGoal kHumanShotGoal = {
+    {-0.90, kShootSeparation}, 140, 0.04, kIntakePower};
+const ShotGoal kFlippedHumanShotGoal = {
+    {0.90, kShootSeparation}, 140, 0, kIntakePower};
+const ShotGoal kTrussShotGoal = {
+    {-0.68, kShootSeparation}, 88.0, 0.4, kIntakePower};
+const ShotGoal kFlippedTrussShotGoal = {
+    {0.68, kShootSeparation}, 92.0, 0.4, kIntakePower};
+
+const ShotGoal kFlippedDemoShotGoal = {
+    {1.0, kShootSeparation}, 65.0, 0.0, kIntakePower};
+const ShotGoal kDemoShotGoal = {
+    {-1.0, kShootSeparation}, 50.0, 0.0, kIntakePower};
+
+const ClawGoal k254PassGoal = {-1.95, kGrabSeparation};
+const ClawGoal kFlipped254PassGoal = {1.96, kGrabSeparation};
+
+class Reader : public ::aos::input::JoystickInput {
+ public:
+  Reader()
+      : is_high_gear_(false),
+        shot_power_(80.0),
+        goal_angle_(0.0),
+        separation_angle_(kGrabSeparation),
+        velocity_compensation_(0.0),
+        intake_power_(0.0),
+        was_running_(false) {}
+
+  void RunIteration(const ::aos::input::driver_station::Data &data) override {
+    bool last_auto_running = auto_running_;
+    auto_running_ = data.GetControlBit(ControlBit::kAutonomous) &&
+                    data.GetControlBit(ControlBit::kEnabled);
+    if (auto_running_ != last_auto_running) {
+      if (auto_running_) {
+        StartAuto();
+      } else {
+        StopAuto();
+      }
+    }
+
+    if (!data.GetControlBit(ControlBit::kAutonomous)) {
+      HandleDrivetrain(data);
+      HandleTeleop(data);
+    }
+  }
+
+  void HandleDrivetrain(const ::aos::input::driver_station::Data &data) {
+    bool is_control_loop_driving = false;
+    double left_goal = 0.0;
+    double right_goal = 0.0;
+    const double wheel = -data.GetAxis(kSteeringWheel);
+    const double throttle = -data.GetAxis(kDriveThrottle);
+    const double kThrottleGain = 1.0 / 2.5;
+    if (false && (data.IsPressed(kDriveControlLoopEnable1) ||
+                  data.IsPressed(kDriveControlLoopEnable2))) {
+      // TODO(austin): Static sucks!
+      static double distance = 0.0;
+      static double angle = 0.0;
+      static double filtered_goal_distance = 0.0;
+      if (data.PosEdge(kDriveControlLoopEnable1) ||
+          data.PosEdge(kDriveControlLoopEnable2)) {
+        if (drivetrain_queue.position.FetchLatest() &&
+            gyro_reading.FetchLatest()) {
+          distance = (drivetrain_queue.position->left_encoder +
+                      drivetrain_queue.position->right_encoder) /
+                         2.0 -
+                     throttle * kThrottleGain / 2.0;
+          angle = gyro_reading->angle;
+          filtered_goal_distance = distance;
+        }
+      }
+      is_control_loop_driving = true;
+
+      // const double gyro_angle = Gyro.View().angle;
+      const double goal_theta = angle - wheel * 0.27;
+      const double goal_distance = distance + throttle * kThrottleGain;
+      const double robot_width = 22.0 / 100.0 * 2.54;
+      const double kMaxVelocity = 0.6;
+      if (goal_distance > kMaxVelocity * 0.02 + filtered_goal_distance) {
+        filtered_goal_distance += kMaxVelocity * 0.02;
+      } else if (goal_distance <
+                 -kMaxVelocity * 0.02 + filtered_goal_distance) {
+        filtered_goal_distance -= kMaxVelocity * 0.02;
+      } else {
+        filtered_goal_distance = goal_distance;
+      }
+      left_goal = filtered_goal_distance - robot_width * goal_theta / 2.0;
+      right_goal = filtered_goal_distance + robot_width * goal_theta / 2.0;
+      is_high_gear_ = false;
+
+      LOG(DEBUG, "Left goal %f Right goal %f\n", left_goal, right_goal);
+    }
+    if (!drivetrain_queue.goal.MakeWithBuilder()
+             .steering(wheel)
+             .throttle(throttle)
+             .highgear(is_high_gear_)
+             .quickturn(data.IsPressed(kQuickTurn))
+             .control_loop_driving(is_control_loop_driving)
+             .left_goal(left_goal)
+             .right_goal(right_goal)
+             .left_velocity_goal(0)
+             .right_velocity_goal(0)
+             .Send()) {
+      LOG(WARNING, "sending stick values failed\n");
+    }
+    if (data.PosEdge(kShiftHigh)) {
+      is_high_gear_ = false;
+    }
+    if (data.PosEdge(kShiftLow)) {
+      is_high_gear_ = true;
+    }
+  }
+
+  void SetGoal(ClawGoal goal) {
+    goal_angle_ = goal.angle;
+    separation_angle_ = goal.separation;
+    moving_for_shot_ = false;
+    velocity_compensation_ = 0.0;
+    intake_power_ = 0.0;
+  }
+
+  void SetGoal(ShotGoal goal) {
+    goal_angle_ = goal.claw.angle;
+    shot_separation_angle_ = goal.claw.separation;
+    separation_angle_ = kGrabSeparation;
+    moving_for_shot_ = true;
+    shot_power_ = goal.shot_power;
+    velocity_compensation_ = goal.velocity_compensation;
+    intake_power_ = goal.intake_power;
+  }
+
+  void HandleTeleop(const ::aos::input::driver_station::Data &data) {
+    if (!data.GetControlBit(ControlBit::kEnabled)) {
+      action_queue_.CancelAllActions();
+        LOG(DEBUG, "Canceling\n");
+    }
+    if (data.IsPressed(kRollersIn) || data.IsPressed(kRollersOut)) {
+      intake_power_ = 0.0;
+      separation_angle_ = kGrabSeparation;
+      moving_for_shot_ = false;
+    }
+
+    static const double kAdjustClawGoalDeadband = 0.08;
+    double claw_goal_adjust = data.GetAxis(kAdjustClawGoal);
+    if (OLD_DS || ::std::abs(claw_goal_adjust) < kAdjustClawGoalDeadband) {
+      claw_goal_adjust = 0;
+    } else {
+      claw_goal_adjust = (claw_goal_adjust -
+                          ((claw_goal_adjust < 0) ? -kAdjustClawGoalDeadband
+                                                  : kAdjustClawGoalDeadband)) *
+                         0.035;
+    }
+    double claw_separation_adjust = data.GetAxis(kAdjustClawSeparation);
+    if (OLD_DS ||
+        ::std::abs(claw_separation_adjust) < kAdjustClawGoalDeadband) {
+      claw_separation_adjust = 0;
+    } else {
+      claw_separation_adjust =
+          (claw_separation_adjust -
+           ((claw_separation_adjust < 0) ? -kAdjustClawGoalDeadband
+                                         : kAdjustClawGoalDeadband)) *
+          -0.035;
+    }
+
+#if OLD_DS
+    if (data.IsPressed(kFenderShot)) {
+#else
+    if (data.GetAxis(kFlipRobot) > 0.9) {
+#endif
+      claw_goal_adjust += claw_separation_adjust;
+      claw_goal_adjust *= -1;
+
+      if (data.IsPressed(kIntakeOpenPosition)) {
+        action_queue_.CancelAllActions();
+        LOG(DEBUG, "Canceling\n");
+        SetGoal(kFlippedIntakeOpenGoal);
+      } else if (data.IsPressed(kIntakePosition)) {
+        action_queue_.CancelAllActions();
+        LOG(DEBUG, "Canceling\n");
+        SetGoal(kFlippedIntakeGoal);
+      } else if (data.IsPressed(kVerticalTuck)) {
+        action_queue_.CancelAllActions();
+        LOG(DEBUG, "Canceling\n");
+        SetGoal(kVerticalTuckGoal);
+      } else if (data.IsPressed(kTuck)) {
+        action_queue_.CancelAllActions();
+        LOG(DEBUG, "Canceling\n");
+        SetGoal(kFlippedTuckGoal);
+      } else if (data.PosEdge(kLongShot)) {
+        action_queue_.CancelAllActions();
+        LOG(DEBUG, "Canceling\n");
+        SetGoal(kFlippedLongShotGoal);
+      } else if (data.PosEdge(kCloseShot)) {
+        action_queue_.CancelAllActions();
+        LOG(DEBUG, "Canceling\n");
+        SetGoal(kFlippedMediumShotGoal);
+      } else if (data.PosEdge(kFenderShot)) {
+        action_queue_.CancelAllActions();
+        LOG(DEBUG, "Canceling\n");
+        SetGoal(kFlippedShortShotGoal);
+      } else if (data.PosEdge(kHumanPlayerShot)) {
+        action_queue_.CancelAllActions();
+        LOG(DEBUG, "Canceling\n");
+        SetGoal(kFlippedHumanShotGoal);
+      } else if (data.PosEdge(kUserLeft)) {
+        action_queue_.CancelAllActions();
+        LOG(DEBUG, "Canceling\n");
+        SetGoal(kFlipped254PassGoal);
+      } else if (data.PosEdge(kUserRight)) {
+        action_queue_.CancelAllActions();
+        LOG(DEBUG, "Canceling\n");
+        SetGoal(kFlippedDemoShotGoal);
+      } else if (data.PosEdge(kTrussShot)) {
+        action_queue_.CancelAllActions();
+        LOG(DEBUG, "Canceling\n");
+        SetGoal(kFlippedTrussShotGoal);
+      }
+    } else {
+      if (data.IsPressed(kIntakeOpenPosition)) {
+        action_queue_.CancelAllActions();
+        LOG(DEBUG, "Canceling\n");
+        SetGoal(kIntakeOpenGoal);
+      } else if (data.IsPressed(kIntakePosition)) {
+        action_queue_.CancelAllActions();
+        LOG(DEBUG, "Canceling\n");
+        SetGoal(kIntakeGoal);
+      } else if (data.IsPressed(kVerticalTuck)) {
+        action_queue_.CancelAllActions();
+        LOG(DEBUG, "Canceling\n");
+        SetGoal(kVerticalTuckGoal);
+      } else if (data.IsPressed(kTuck)) {
+        action_queue_.CancelAllActions();
+        LOG(DEBUG, "Canceling\n");
+        SetGoal(kTuckGoal);
+      } else if (data.PosEdge(kLongShot)) {
+        action_queue_.CancelAllActions();
+        LOG(DEBUG, "Canceling\n");
+        SetGoal(kLongShotGoal);
+      } else if (data.PosEdge(kCloseShot)) {
+        action_queue_.CancelAllActions();
+        LOG(DEBUG, "Canceling\n");
+        SetGoal(kCloseShotGoal);
+      } else if (data.PosEdge(kFenderShot)) {
+        action_queue_.CancelAllActions();
+        LOG(DEBUG, "Canceling\n");
+        SetGoal(kFenderShotGoal);
+      } else if (data.PosEdge(kHumanPlayerShot)) {
+        action_queue_.CancelAllActions();
+        LOG(DEBUG, "Canceling\n");
+        SetGoal(kHumanShotGoal);
+      } else if (data.PosEdge(kUserLeft)) {
+        action_queue_.CancelAllActions();
+        LOG(DEBUG, "Canceling\n");
+        SetGoal(k254PassGoal);
+      } else if (data.PosEdge(kUserRight)) {
+        action_queue_.CancelAllActions();
+        LOG(DEBUG, "Canceling\n");
+        SetGoal(kDemoShotGoal);
+      } else if (data.PosEdge(kTrussShot)) {
+        action_queue_.CancelAllActions();
+        LOG(DEBUG, "Canceling\n");
+        SetGoal(kTrussShotGoal);
+      }
+    }
+
+    if (data.PosEdge(kFire)) {
+      action_queue_.EnqueueAction(actors::MakeShootAction());
+    } else if (data.NegEdge(kFire)) {
+      action_queue_.CancelCurrentAction();
+    }
+
+    action_queue_.Tick();
+    if (data.IsPressed(kUnload) || data.IsPressed(kReload)) {
+      action_queue_.CancelAllActions();
+        LOG(DEBUG, "Canceling\n");
+      intake_power_ = 0.0;
+      velocity_compensation_ = 0.0;
+    }
+
+    // Send out the claw and shooter goals if no actions are running.
+    if (!action_queue_.Running()) {
+      goal_angle_ += claw_goal_adjust;
+      separation_angle_ += claw_separation_adjust;
+
+      // If the action just ended, turn the intake off and stop velocity
+      // compensating.
+      if (was_running_) {
+        intake_power_ = 0.0;
+        velocity_compensation_ = 0.0;
+      }
+
+      control_loops::drivetrain_queue.status.FetchLatest();
+      double goal_angle = goal_angle_;
+      if (control_loops::drivetrain_queue.status.get()) {
+        goal_angle += SpeedToAngleOffset(
+            control_loops::drivetrain_queue.status->robot_speed);
+      } else {
+        LOG_INTERVAL(no_drivetrain_status_);
+      }
+
+      if (moving_for_shot_) {
+        auto &claw_status = control_loops::claw_queue.status;
+        claw_status.FetchLatest();
+        if (claw_status.get()) {
+          if (::std::abs(claw_status->bottom - goal_angle) < 0.2) {
+            moving_for_shot_ = false;
+            separation_angle_ = shot_separation_angle_;
+          }
+        }
+      }
+
+      double separation_angle = separation_angle_;
+
+      if (data.IsPressed(kCatch)) {
+        const double kCatchSeparation = 1.0;
+        goal_angle -= kCatchSeparation / 2.0;
+        separation_angle = kCatchSeparation;
+      }
+
+      bool intaking =
+          data.IsPressed(kRollersIn) || data.IsPressed(kIntakePosition) ||
+          data.IsPressed(kIntakeOpenPosition) || data.IsPressed(kCatch);
+      if (!control_loops::claw_queue.goal.MakeWithBuilder()
+               .bottom_angle(goal_angle)
+               .separation_angle(separation_angle)
+               .intake(intaking ? 12.0
+                                : (data.IsPressed(kRollersOut) ? -12.0
+                                                               : intake_power_))
+               .centering(intaking ? 12.0 : 0.0)
+               .Send()) {
+        LOG(WARNING, "sending claw goal failed\n");
+      }
+
+      if (!control_loops::shooter_queue.goal.MakeWithBuilder()
+               .shot_power(shot_power_)
+               .shot_requested(data.IsPressed(kFire))
+               .unload_requested(data.IsPressed(kUnload))
+               .load_requested(data.IsPressed(kReload))
+               .Send()) {
+        LOG(WARNING, "sending shooter goal failed\n");
+      }
+    }
+    was_running_ = action_queue_.Running();
+  }
+
+  double SpeedToAngleOffset(double speed) {
+    const frc971::constants::Values &values = frc971::constants::GetValues();
+    // scale speed to a [0.0-1.0] on something close to the max
+    // TODO(austin): Change the scale factor for different shots.
+    return (speed / values.drivetrain_max_speed) * velocity_compensation_;
+  }
+
+ private:
+  void StartAuto() {
+    LOG(INFO, "Starting auto mode\n");
+    ::frc971::autonomous::autonomous.MakeWithBuilder().run_auto(true).Send();
+  }
+
+  void StopAuto() {
+    LOG(INFO, "Stopping auto mode\n");
+    ::frc971::autonomous::autonomous.MakeWithBuilder().run_auto(false).Send();
+  }
+
+  bool is_high_gear_;
+  double shot_power_;
+  double goal_angle_;
+  double separation_angle_, shot_separation_angle_;
+  double velocity_compensation_;
+  double intake_power_;
+  bool was_running_;
+  bool moving_for_shot_ = false;
+
+  bool auto_running_ = false;
+  
+  ::aos::common::actions::ActionQueue action_queue_;
+
+  ::aos::util::SimpleLogInterval no_drivetrain_status_ =
+      ::aos::util::SimpleLogInterval(::aos::time::Time::InSeconds(0.2), WARNING,
+                                     "no drivetrain status");
+};
+
+}  // namespace joysticks
+}  // namespace input
+}  // namespace frc971
+
+int main() {
+  ::aos::Init();
+  ::frc971::input::joysticks::Reader reader;
+  reader.Run();
+  ::aos::Cleanup();
+}
diff --git a/y2014/prime/build.sh b/y2014/prime/build.sh
new file mode 100755
index 0000000..f83d9f4
--- /dev/null
+++ b/y2014/prime/build.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+cd $(dirname $0)
+
+exec ../../aos/build/build.py $0 prime y2014 prime.gyp "$@"
diff --git a/y2014/prime/compile_loop.sh b/y2014/prime/compile_loop.sh
new file mode 100755
index 0000000..de6b0d3
--- /dev/null
+++ b/y2014/prime/compile_loop.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+# Runs `build.sh all` and then waits for a file to be modified in a loop.
+# Useful for making changes to the code while continuously making sure they
+# compile.
+# Requires the util-linux and inotify-tools packages.
+
+chrt -i -p 0 $$
+ionice -c 3 -p $$
+
+while true; do
+	$(dirname $0)/build.sh all
+	echo 'compile_loop.sh: Waiting for a file modification...' 1>&2
+	inotifywait -e close_write -r aos frc971 bbb_cape
+	echo 'compile_loop.sh: Done waiting for a file modification' 1>&2
+done
diff --git a/y2014/prime/hot_goal_reader.cc b/y2014/prime/hot_goal_reader.cc
new file mode 100644
index 0000000..ffdb3a3
--- /dev/null
+++ b/y2014/prime/hot_goal_reader.cc
@@ -0,0 +1,108 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "aos/common/time.h"
+#include "aos/common/logging/queue_logging.h"
+#include "aos/common/logging/logging.h"
+#include "aos/linux_code/init.h"
+#include "aos/common/byteorder.h"
+
+#include "y2014/queues/hot_goal.q.h"
+
+int main() {
+  ::aos::InitNRT();
+
+  uint64_t left_count, right_count;
+  ::frc971::hot_goal.FetchLatest();
+  if (::frc971::hot_goal.get()) {
+    LOG_STRUCT(DEBUG, "starting with", *::frc971::hot_goal);
+    left_count = ::frc971::hot_goal->left_count;
+    right_count = ::frc971::hot_goal->left_count;
+  } else {
+    LOG(DEBUG, "no starting message\n");
+    left_count = right_count = 0;
+  }
+
+  int my_socket = -1;
+  while (true) {
+    if (my_socket == -1) {
+      my_socket = socket(AF_INET, SOCK_STREAM, 0);
+      if (my_socket == -1) {
+        PLOG(WARNING, "socket(AF_INET, SOCK_STREAM, 0) failed");
+        continue;
+      } else {
+        LOG(INFO, "opened socket (is %d)\n", my_socket);
+        sockaddr_in address, *sockaddr_pointer;
+        memset(&address, 0, sizeof(address));
+        address.sin_family = AF_INET;
+        address.sin_port = ::aos::hton<uint16_t>(1180);
+        sockaddr *address_pointer;
+        sockaddr_pointer = &address;
+        memcpy(&address_pointer, &sockaddr_pointer, sizeof(void *));
+        if (bind(my_socket, address_pointer, sizeof(address)) == -1) {
+          PLOG(WARNING, "bind(%d, %p, %zu) failed",
+               my_socket, &address, sizeof(address));
+          close(my_socket);
+          my_socket = -1;
+          continue;
+        }
+
+        if (listen(my_socket, 1) == -1) {
+          PLOG(WARNING, "listen(%d, 1) failed", my_socket);
+          close(my_socket);
+          my_socket = -1;
+          continue;
+        }
+      }
+    }
+
+    int connection = accept4(my_socket, nullptr, nullptr, SOCK_NONBLOCK);
+    if (connection == -1) {
+      PLOG(WARNING, "accept(%d, nullptr, nullptr) failed", my_socket);
+      continue;
+    }
+    LOG(INFO, "accepted (is %d)\n", connection);
+
+    while (connection != -1) {
+      fd_set fds;
+      FD_ZERO(&fds);
+      FD_SET(connection, &fds);
+      struct timeval timeout_timeval =
+          ::aos::time::Time::InSeconds(1).ToTimeval();
+      switch (
+          select(connection + 1, &fds, nullptr, nullptr, &timeout_timeval)) {
+        case 1: {
+          uint8_t data;
+          ssize_t read_bytes = read(connection, &data, sizeof(data));
+          if (read_bytes != sizeof(data)) {
+            LOG(WARNING, "read %zd bytes instead of %zd\n", read_bytes,
+                sizeof(data));
+            break;
+          }
+          if (data & 0x01) ++right_count;
+          if (data & 0x02) ++left_count;
+          auto message = ::frc971::hot_goal.MakeMessage();
+          message->left_count = left_count;
+          message->right_count = right_count;
+          LOG_STRUCT(DEBUG, "sending", *message);
+          message.Send();
+        } break;
+        case 0:
+          LOG(WARNING, "read on %d timed out\n", connection);
+          close(connection);
+          connection = -1;
+          break;
+        default:
+          PLOG(FATAL,
+               "select(%d, %p, nullptr, nullptr, %p) failed",
+               connection + 1, &fds, &timeout_timeval);
+      }
+    }
+  }
+
+  LOG(FATAL, "finished???\n");
+}
diff --git a/y2014/prime/prime.gyp b/y2014/prime/prime.gyp
new file mode 100644
index 0000000..a64fc1c
--- /dev/null
+++ b/y2014/prime/prime.gyp
@@ -0,0 +1,55 @@
+{
+  'targets': [
+    {
+      'target_name': 'All',
+      'type': 'none',
+      'dependencies': [
+        '../../frc971/frc971.gyp:All',
+
+        '../control_loops/drivetrain/drivetrain.gyp:drivetrain',
+        '../control_loops/drivetrain/drivetrain.gyp:drivetrain_lib_test',
+        '../control_loops/drivetrain/drivetrain.gyp:replay_drivetrain',
+        '../control_loops/claw/claw.gyp:claw',
+        '../control_loops/claw/claw.gyp:claw_calibration',
+        '../control_loops/claw/claw.gyp:claw_lib_test',
+        '../control_loops/claw/claw.gyp:replay_claw',
+        '../control_loops/shooter/shooter.gyp:shooter',
+        '../control_loops/shooter/shooter.gyp:shooter_lib_test',
+        '../control_loops/shooter/shooter.gyp:replay_shooter',
+        '../autonomous/autonomous.gyp:auto',
+        '../y2014.gyp:joystick_reader',
+        '../actors/actors.gyp:binaries',
+        'hot_goal_reader',
+      ],
+      'copies': [
+        {
+          'destination': '<(rsync_dir)',
+          'files': [
+            'start_list.txt',
+          ],
+        },
+      ],
+      'conditions': [
+        ['ARCHITECTURE=="arm_frc"', {
+          'dependencies': [
+            '../wpilib/wpilib.gyp:wpilib_interface',
+          ],
+        }],
+      ],
+    },
+    {
+      'target_name': 'hot_goal_reader',
+      'type': 'executable',
+      'sources': [
+        'hot_goal_reader.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/logging/logging.gyp:queue_logging',
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(DEPTH)/y2014/queues/queues.gyp:hot_goal'
+      ],
+    },
+  ],
+}
diff --git a/y2014/prime/start_list.txt b/y2014/prime/start_list.txt
new file mode 100644
index 0000000..276aca8
--- /dev/null
+++ b/y2014/prime/start_list.txt
@@ -0,0 +1,13 @@
+binary_log_writer
+motor_writer
+joystick_reader
+drivetrain
+auto
+sensor_receiver
+joystick_proxy
+claw
+shooter
+shoot_action
+drivetrain_action
+catch_action
+hot_goal_reader
diff --git a/y2014/queues/auto_mode.q b/y2014/queues/auto_mode.q
new file mode 100644
index 0000000..7922dbf
--- /dev/null
+++ b/y2014/queues/auto_mode.q
@@ -0,0 +1,6 @@
+package frc971.sensors;
+
+message AutoMode {
+	double voltage;
+};
+queue AutoMode auto_mode;
diff --git a/y2014/queues/hot_goal.q b/y2014/queues/hot_goal.q
new file mode 100644
index 0000000..3444553
--- /dev/null
+++ b/y2014/queues/hot_goal.q
@@ -0,0 +1,7 @@
+package frc971;
+
+message HotGoal {
+	uint64_t left_count;
+	uint64_t right_count;
+};
+queue HotGoal hot_goal;
diff --git a/y2014/queues/profile_params.q b/y2014/queues/profile_params.q
new file mode 100644
index 0000000..e7ffe9a
--- /dev/null
+++ b/y2014/queues/profile_params.q
@@ -0,0 +1,6 @@
+package frc971;
+
+struct ProfileParams {
+  double velocity;
+  double acceleration;
+};
diff --git a/y2014/queues/queues.gyp b/y2014/queues/queues.gyp
new file mode 100644
index 0000000..1325384
--- /dev/null
+++ b/y2014/queues/queues.gyp
@@ -0,0 +1,37 @@
+{
+  'targets': [
+    {
+      'target_name': 'profile_params',
+      'type': 'static_library',
+      'sources': [
+        'profile_params.q',
+      ],
+      'variables': {
+        'header_path': 'y2014/queues',
+      },
+      'includes': ['../../aos/build/queues.gypi'],
+    },
+    {
+      'target_name': 'hot_goal',
+      'type': 'static_library',
+      'sources': [
+        'hot_goal.q',
+      ],
+      'variables': {
+        'header_path': 'y2014/queues',
+      },
+      'includes': ['../../aos/build/queues.gypi'],
+    },
+    {
+      'target_name': 'auto_mode',
+      'type': 'static_library',
+      'sources': [
+        'auto_mode.q',
+      ],
+      'variables': {
+        'header_path': 'y2014/queues',
+      },
+      'includes': ['../../aos/build/queues.gypi'],
+    },
+  ],
+}
diff --git a/y2014/wpilib/wpilib.gyp b/y2014/wpilib/wpilib.gyp
new file mode 100644
index 0000000..798ff76
--- /dev/null
+++ b/y2014/wpilib/wpilib.gyp
@@ -0,0 +1,39 @@
+{
+  'targets': [
+    {
+      'target_name': 'wpilib_interface',
+      'type': 'executable',
+      'sources': [
+        'wpilib_interface.cc'
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(AOS)/common/common.gyp:stl_mutex',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(EXTERNALS):WPILib',
+        '<(DEPTH)/y2014/y2014.gyp:constants',
+        '<(DEPTH)/y2014/queues/queues.gyp:auto_mode',
+        '<(DEPTH)/y2014/control_loops/drivetrain/drivetrain.gyp:drivetrain_queue',
+        '<(DEPTH)/y2014/control_loops/shooter/shooter.gyp:shooter_queue',
+        '<(DEPTH)/y2014/control_loops/claw/claw.gyp:claw_queue',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+        '<(AOS)/common/util/util.gyp:log_interval',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/common/logging/logging.gyp:queue_logging',
+        '<(AOS)/common/messages/messages.gyp:robot_state',
+        '<(AOS)/common/util/util.gyp:phased_loop',
+        '<(AOS)/common/messages/messages.gyp:robot_state',
+        '<(DEPTH)/frc971/wpilib/wpilib.gyp:hall_effect',
+        '<(DEPTH)/frc971/wpilib/wpilib.gyp:joystick_sender',
+        '<(DEPTH)/frc971/wpilib/wpilib.gyp:loop_output_handler',
+        '<(DEPTH)/frc971/wpilib/wpilib.gyp:buffered_pcm',
+        '<(DEPTH)/frc971/wpilib/wpilib.gyp:gyro_sender',
+        '<(DEPTH)/frc971/wpilib/wpilib.gyp:dma_edge_counting',
+        '<(DEPTH)/frc971/wpilib/wpilib.gyp:interrupt_edge_counting',
+        '<(DEPTH)/frc971/wpilib/wpilib.gyp:encoder_and_potentiometer',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:queues',
+        '<(DEPTH)/frc971/wpilib/wpilib.gyp:logging_queue',
+      ],
+    },
+  ],
+}
diff --git a/y2014/wpilib/wpilib_interface.cc b/y2014/wpilib/wpilib_interface.cc
new file mode 100644
index 0000000..776b681
--- /dev/null
+++ b/y2014/wpilib/wpilib_interface.cc
@@ -0,0 +1,762 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <thread>
+#include <mutex>
+#include <functional>
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/logging/queue_logging.h"
+#include "aos/common/time.h"
+#include "aos/common/util/log_interval.h"
+#include "aos/common/util/phased_loop.h"
+#include "aos/common/util/wrapping_counter.h"
+#include "aos/common/stl_mutex.h"
+#include "aos/linux_code/init.h"
+#include "aos/common/messages/robot_state.q.h"
+
+#include "frc971/shifter_hall_effect.h"
+#include "y2014/control_loops/drivetrain/drivetrain.q.h"
+#include "y2014/control_loops/claw/claw.q.h"
+#include "y2014/control_loops/shooter/shooter.q.h"
+#include "y2014/constants.h"
+#include "y2014/queues/auto_mode.q.h"
+
+#include "frc971/wpilib/hall_effect.h"
+#include "frc971/wpilib/joystick_sender.h"
+#include "frc971/wpilib/loop_output_handler.h"
+#include "frc971/wpilib/buffered_solenoid.h"
+#include "frc971/wpilib/buffered_pcm.h"
+#include "frc971/wpilib/gyro_sender.h"
+#include "frc971/wpilib/dma_edge_counting.h"
+#include "frc971/wpilib/interrupt_edge_counting.h"
+#include "frc971/wpilib/encoder_and_potentiometer.h"
+#include "frc971/wpilib/logging.q.h"
+
+#include "Encoder.h"
+#include "Talon.h"
+#include "DriverStation.h"
+#include "AnalogInput.h"
+#include "Compressor.h"
+#include "Relay.h"
+#include "RobotBase.h"
+#include "dma.h"
+#include "ControllerPower.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+using ::frc971::control_loops::drivetrain_queue;
+using ::frc971::control_loops::claw_queue;
+using ::frc971::control_loops::shooter_queue;
+
+namespace frc971 {
+namespace wpilib {
+
+// TODO(brian): Replace this with ::std::make_unique once all our toolchains
+// have support.
+template <class T, class... U>
+std::unique_ptr<T> make_unique(U &&... u) {
+  return std::unique_ptr<T>(new T(std::forward<U>(u)...));
+}
+
+double drivetrain_translate(int32_t in) {
+  return static_cast<double>(in) /
+         (256.0 /*cpr*/ * 4.0 /*4x*/) *
+         constants::GetValues().drivetrain_encoder_ratio *
+         (3.5 /*wheel diameter*/ * 2.54 / 100.0 * M_PI);
+}
+
+float hall_translate(const constants::ShifterHallEffect &k, float in_low,
+                     float in_high) {
+  const float low_ratio =
+      0.5 * (in_low - static_cast<float>(k.low_gear_low)) /
+      static_cast<float>(k.low_gear_middle - k.low_gear_low);
+  const float high_ratio =
+      0.5 + 0.5 * (in_high - static_cast<float>(k.high_gear_middle)) /
+                static_cast<float>(k.high_gear_high - k.high_gear_middle);
+
+  // Return low when we are below 1/2, and high when we are above 1/2.
+  if (low_ratio + high_ratio < 1.0) {
+    return low_ratio;
+  } else {
+    return high_ratio;
+  }
+}
+
+double claw_translate(int32_t in) {
+  return static_cast<double>(in) / (256.0 /*cpr*/ * 4.0 /*quad*/) /
+         (18.0 / 48.0 /*encoder gears*/) / (12.0 / 60.0 /*chain reduction*/) *
+         (M_PI / 180.0);
+}
+
+double shooter_translate(int32_t in) {
+  return static_cast<double>(in) / (256.0 /*cpr*/ * 4.0 /*quad*/) *
+         16 /*sprocket teeth*/ * 0.375 /*chain pitch*/
+         * (2.54 / 100.0 /*in to m*/);
+}
+
+static const double kMaximumEncoderPulsesPerSecond =
+    5600.0 /* free speed RPM */ * 14.0 / 48.0 /* bottom gear reduction */ *
+    18.0 / 32.0 /* big belt reduction */ *
+    18.0 / 66.0 /* top gear reduction */ * 48.0 / 18.0 /* encoder gears */ /
+    60.0 /* seconds / minute */ * 256.0 /* CPR */;
+
+class SensorReader {
+ public:
+  SensorReader() {
+    // Set it to filter out anything shorter than 1/4 of the minimum pulse width
+    // we should ever see.
+    encoder_filter_.SetPeriodNanoSeconds(
+        static_cast<int>(1 / 4.0 / kMaximumEncoderPulsesPerSecond * 1e9 + 0.5));
+    hall_filter_.SetPeriodNanoSeconds(100000);
+  }
+
+  void set_auto_selector_analog(::std::unique_ptr<AnalogInput> analog) {
+    auto_selector_analog_ = ::std::move(analog);
+  }
+
+  void set_drivetrain_left_encoder(::std::unique_ptr<Encoder> encoder) {
+    drivetrain_left_encoder_ = ::std::move(encoder);
+  }
+
+  void set_drivetrain_right_encoder(::std::unique_ptr<Encoder> encoder) {
+    drivetrain_right_encoder_ = ::std::move(encoder);
+  }
+
+  void set_high_left_drive_hall(::std::unique_ptr<AnalogInput> analog) {
+    high_left_drive_hall_ = ::std::move(analog);
+  }
+
+  void set_low_right_drive_hall(::std::unique_ptr<AnalogInput> analog) {
+    low_right_drive_hall_ = ::std::move(analog);
+  }
+
+  void set_high_right_drive_hall(::std::unique_ptr<AnalogInput> analog) {
+    high_right_drive_hall_ = ::std::move(analog);
+  }
+
+  void set_low_left_drive_hall(::std::unique_ptr<AnalogInput> analog) {
+    low_left_drive_hall_ = ::std::move(analog);
+  }
+
+  void set_top_claw_encoder(::std::unique_ptr<Encoder> encoder) {
+    encoder_filter_.Add(encoder.get());
+    top_reader_.set_encoder(::std::move(encoder));
+  }
+
+  void set_top_claw_front_hall(::std::unique_ptr<DigitalSource> hall) {
+    hall_filter_.Add(hall.get());
+    top_reader_.set_front_hall(::std::move(hall));
+  }
+
+  void set_top_claw_calibration_hall(::std::unique_ptr<DigitalSource> hall) {
+    hall_filter_.Add(hall.get());
+    top_reader_.set_calibration_hall(::std::move(hall));
+  }
+
+  void set_top_claw_back_hall(::std::unique_ptr<DigitalSource> hall) {
+    hall_filter_.Add(hall.get());
+    top_reader_.set_back_hall(::std::move(hall));
+  }
+
+  void set_bottom_claw_encoder(::std::unique_ptr<Encoder> encoder) {
+    encoder_filter_.Add(encoder.get());
+    bottom_reader_.set_encoder(::std::move(encoder));
+  }
+
+  void set_bottom_claw_front_hall(::std::unique_ptr<DigitalSource> hall) {
+    hall_filter_.Add(hall.get());
+    bottom_reader_.set_front_hall(::std::move(hall));
+  }
+
+  void set_bottom_claw_calibration_hall(::std::unique_ptr<DigitalSource> hall) {
+    hall_filter_.Add(hall.get());
+    bottom_reader_.set_calibration_hall(::std::move(hall));
+  }
+
+  void set_bottom_claw_back_hall(::std::unique_ptr<DigitalSource> hall) {
+    hall_filter_.Add(hall.get());
+    bottom_reader_.set_back_hall(::std::move(hall));
+  }
+
+  void set_shooter_encoder(::std::unique_ptr<Encoder> encoder) {
+    encoder_filter_.Add(encoder.get());
+    shooter_encoder_ = ::std::move(encoder);
+  }
+
+  void set_shooter_proximal(::std::unique_ptr<DigitalSource> hall) {
+    hall_filter_.Add(hall.get());
+    shooter_proximal_ = ::std::move(hall);
+  }
+
+  void set_shooter_distal(::std::unique_ptr<DigitalSource> hall) {
+    hall_filter_.Add(hall.get());
+    shooter_distal_ = ::std::move(hall);
+  }
+
+  void set_shooter_plunger(::std::unique_ptr<DigitalSource> hall) {
+    hall_filter_.Add(hall.get());
+    shooter_plunger_ = ::std::move(hall);
+    shooter_plunger_reader_ =
+        make_unique<DMADigitalReader>(shooter_plunger_.get());
+  }
+
+  void set_shooter_latch(::std::unique_ptr<DigitalSource> hall) {
+    hall_filter_.Add(hall.get());
+    shooter_latch_ = ::std::move(hall);
+    shooter_latch_reader_ = make_unique<DMADigitalReader>(shooter_latch_.get());
+  }
+
+  // All of the DMA-related set_* calls must be made before this, and it doesn't
+  // hurt to do all of them.
+  void set_dma(::std::unique_ptr<DMA> dma) {
+    shooter_proximal_counter_ = make_unique<DMAEdgeCounter>(
+        shooter_encoder_.get(), shooter_proximal_.get());
+    shooter_distal_counter_ = make_unique<DMAEdgeCounter>(
+        shooter_encoder_.get(), shooter_distal_.get());
+
+    dma_synchronizer_.reset(new DMASynchronizer(::std::move(dma)));
+    dma_synchronizer_->Add(shooter_proximal_counter_.get());
+    dma_synchronizer_->Add(shooter_distal_counter_.get());
+    dma_synchronizer_->Add(shooter_plunger_reader_.get());
+    dma_synchronizer_->Add(shooter_latch_reader_.get());
+  }
+
+  void operator()() {
+    ::aos::SetCurrentThreadName("SensorReader");
+    LOG(INFO, "In sensor reader thread\n");
+
+    my_pid_ = getpid();
+    ds_ = DriverStation::GetInstance();
+
+    top_reader_.Start();
+    bottom_reader_.Start();
+    dma_synchronizer_->Start();
+    LOG(INFO, "Things are now started\n");
+
+    ::aos::SetCurrentThreadRealtimePriority(kPriority);
+    while (run_) {
+      ::aos::time::PhasedLoopXMS(10, 9000);
+      RunIteration();
+    }
+
+    top_reader_.Quit();
+    bottom_reader_.Quit();
+  }
+
+  void RunIteration() {
+    {
+      auto new_state = ::aos::robot_state.MakeMessage();
+
+      new_state->reader_pid = my_pid_;
+      new_state->outputs_enabled = ds_->IsSysActive();
+      new_state->browned_out = ds_->IsSysBrownedOut();
+
+      new_state->is_3v3_active = ControllerPower::GetEnabled3V3();
+      new_state->is_5v_active = ControllerPower::GetEnabled5V();
+      new_state->voltage_3v3 = ControllerPower::GetVoltage3V3();
+      new_state->voltage_5v = ControllerPower::GetVoltage5V();
+
+      new_state->voltage_roborio_in = ControllerPower::GetInputVoltage();
+      new_state->voltage_battery = ds_->GetBatteryVoltage();
+
+      LOG_STRUCT(DEBUG, "robot_state", *new_state);
+
+      new_state.Send();
+    }
+
+    const auto &values = constants::GetValues();
+
+    {
+      auto drivetrain_message = drivetrain_queue.position.MakeMessage();
+      drivetrain_message->right_encoder =
+          drivetrain_translate(drivetrain_right_encoder_->GetRaw());
+      drivetrain_message->left_encoder =
+          -drivetrain_translate(drivetrain_left_encoder_->GetRaw());
+      drivetrain_message->left_shifter_position =
+          hall_translate(values.left_drive, low_left_drive_hall_->GetVoltage(),
+                         high_left_drive_hall_->GetVoltage());
+      drivetrain_message->right_shifter_position = hall_translate(
+          values.right_drive, low_right_drive_hall_->GetVoltage(),
+          high_right_drive_hall_->GetVoltage());
+
+      drivetrain_message.Send();
+    }
+
+    ::frc971::sensors::auto_mode.MakeWithBuilder()
+        .voltage(auto_selector_analog_->GetVoltage())
+        .Send();
+
+    dma_synchronizer_->RunIteration();
+
+    {
+      auto shooter_message = shooter_queue.position.MakeMessage();
+      shooter_message->position = shooter_translate(shooter_encoder_->GetRaw());
+      shooter_message->plunger = shooter_plunger_reader_->value();
+      shooter_message->latch = shooter_latch_reader_->value();
+      CopyShooterPosedgeCounts(shooter_proximal_counter_.get(),
+                               &shooter_message->pusher_proximal);
+      CopyShooterPosedgeCounts(shooter_distal_counter_.get(),
+                               &shooter_message->pusher_distal);
+
+      shooter_message.Send();
+    }
+
+    {
+      auto claw_message = claw_queue.position.MakeMessage();
+      top_reader_.RunIteration(&claw_message->top);
+      bottom_reader_.RunIteration(&claw_message->bottom);
+
+      claw_message.Send();
+    }
+  }
+
+  void Quit() { run_ = false; }
+
+ private:
+  class HalfClawReader {
+   public:
+    HalfClawReader(bool reversed) : reversed_(reversed) {}
+
+    void set_encoder(::std::unique_ptr<Encoder> encoder) {
+      encoder_ = ::std::move(encoder);
+    }
+
+    void set_front_hall(::std::unique_ptr<DigitalSource> front_hall) {
+      front_hall_ = ::std::move(front_hall);
+    }
+
+    void set_calibration_hall(
+        ::std::unique_ptr<DigitalSource> calibration_hall) {
+      calibration_hall_ = ::std::move(calibration_hall);
+    }
+
+    void set_back_hall(::std::unique_ptr<DigitalSource> back_hall) {
+      back_hall_ = ::std::move(back_hall);
+    }
+
+    void Start() {
+      front_counter_ =
+          make_unique<EdgeCounter>(encoder_.get(), front_hall_.get());
+      synchronizer_.Add(front_counter_.get());
+      calibration_counter_ =
+          make_unique<EdgeCounter>(encoder_.get(), calibration_hall_.get());
+      synchronizer_.Add(calibration_counter_.get());
+      back_counter_ =
+          make_unique<EdgeCounter>(encoder_.get(), back_hall_.get());
+      synchronizer_.Add(back_counter_.get());
+      synchronized_encoder_ =
+          make_unique<InterruptSynchronizedEncoder>(encoder_.get());
+      synchronizer_.Add(synchronized_encoder_.get());
+
+      synchronizer_.Start();
+    }
+
+    void Quit() { synchronizer_.Quit(); }
+
+    void RunIteration(control_loops::HalfClawPosition *half_claw_position) {
+      const double multiplier = reversed_ ? -1.0 : 1.0;
+
+      synchronizer_.RunIteration();
+
+      CopyPosition(front_counter_.get(), &half_claw_position->front);
+      CopyPosition(calibration_counter_.get(),
+                   &half_claw_position->calibration);
+      CopyPosition(back_counter_.get(), &half_claw_position->back);
+      half_claw_position->position =
+          multiplier * claw_translate(synchronized_encoder_->get());
+    }
+
+   private:
+    void CopyPosition(const EdgeCounter *counter, HallEffectStruct *out) {
+      const double multiplier = reversed_ ? -1.0 : 1.0;
+
+      out->current = counter->polled_value();
+      out->posedge_count = counter->positive_interrupt_count();
+      out->negedge_count = counter->negative_interrupt_count();
+      out->posedge_value =
+          multiplier * claw_translate(counter->last_positive_encoder_value());
+      out->negedge_value =
+          multiplier * claw_translate(counter->last_negative_encoder_value());
+    }
+
+    InterruptSynchronizer synchronizer_{kInterruptPriority};
+
+    ::std::unique_ptr<EdgeCounter> front_counter_;
+    ::std::unique_ptr<EdgeCounter> calibration_counter_;
+    ::std::unique_ptr<EdgeCounter> back_counter_;
+    ::std::unique_ptr<InterruptSynchronizedEncoder> synchronized_encoder_;
+
+    ::std::unique_ptr<Encoder> encoder_;
+    ::std::unique_ptr<DigitalSource> front_hall_;
+    ::std::unique_ptr<DigitalSource> calibration_hall_;
+    ::std::unique_ptr<DigitalSource> back_hall_;
+
+    const bool reversed_;
+  };
+
+  static const int kPriority = 30;
+  static const int kInterruptPriority = 55;
+
+  void CopyShooterPosedgeCounts(const DMAEdgeCounter *counter,
+                                PosedgeOnlyCountedHallEffectStruct *output) {
+    output->current = counter->polled_value();
+    output->posedge_count = counter->positive_count();
+    output->negedge_count = counter->negative_count();
+    output->posedge_value =
+        shooter_translate(counter->last_positive_encoder_value());
+  }
+
+  int32_t my_pid_;
+  DriverStation *ds_;
+
+  ::std::unique_ptr<DMASynchronizer> dma_synchronizer_;
+
+  ::std::unique_ptr<AnalogInput> auto_selector_analog_;
+
+  ::std::unique_ptr<Encoder> drivetrain_left_encoder_;
+  ::std::unique_ptr<Encoder> drivetrain_right_encoder_;
+  ::std::unique_ptr<AnalogInput> low_left_drive_hall_;
+  ::std::unique_ptr<AnalogInput> high_left_drive_hall_;
+  ::std::unique_ptr<AnalogInput> low_right_drive_hall_;
+  ::std::unique_ptr<AnalogInput> high_right_drive_hall_;
+
+  HalfClawReader top_reader_{false}, bottom_reader_{true};
+
+  ::std::unique_ptr<Encoder> shooter_encoder_;
+  ::std::unique_ptr<DigitalSource> shooter_proximal_, shooter_distal_;
+  ::std::unique_ptr<DigitalSource> shooter_plunger_, shooter_latch_;
+  ::std::unique_ptr<DMAEdgeCounter> shooter_proximal_counter_,
+      shooter_distal_counter_;
+  ::std::unique_ptr<DMADigitalReader> shooter_plunger_reader_,
+      shooter_latch_reader_;
+
+  ::std::atomic<bool> run_{true};
+  DigitalGlitchFilter encoder_filter_, hall_filter_;
+};
+
+class SolenoidWriter {
+ public:
+  SolenoidWriter(const ::std::unique_ptr<BufferedPcm> &pcm)
+      : pcm_(pcm),
+        shooter_(".frc971.control_loops.shooter_queue.output"),
+        drivetrain_(".frc971.control_loops.drivetrain_queue.output") {}
+
+  void set_pressure_switch(::std::unique_ptr<DigitalSource> pressure_switch) {
+    pressure_switch_ = ::std::move(pressure_switch);
+  }
+
+  void set_compressor_relay(::std::unique_ptr<Relay> compressor_relay) {
+    compressor_relay_ = ::std::move(compressor_relay);
+  }
+
+  void set_drivetrain_left(::std::unique_ptr<BufferedSolenoid> s) {
+    drivetrain_left_ = ::std::move(s);
+  }
+
+  void set_drivetrain_right(::std::unique_ptr<BufferedSolenoid> s) {
+    drivetrain_right_ = ::std::move(s);
+  }
+
+  void set_shooter_latch(::std::unique_ptr<BufferedSolenoid> s) {
+    shooter_latch_ = ::std::move(s);
+  }
+
+  void set_shooter_brake(::std::unique_ptr<BufferedSolenoid> s) {
+    shooter_brake_ = ::std::move(s);
+  }
+
+  void operator()() {
+    ::aos::SetCurrentThreadName("Solenoids");
+    ::aos::SetCurrentThreadRealtimePriority(30);
+
+    while (run_) {
+      ::aos::time::PhasedLoopXMS(20, 1000);
+
+      {
+        shooter_.FetchLatest();
+        if (shooter_.get()) {
+          LOG_STRUCT(DEBUG, "solenoids", *shooter_);
+          shooter_latch_->Set(!shooter_->latch_piston);
+          shooter_brake_->Set(!shooter_->brake_piston);
+        }
+      }
+
+      {
+        drivetrain_.FetchLatest();
+        if (drivetrain_.get()) {
+          LOG_STRUCT(DEBUG, "solenoids", *drivetrain_);
+          drivetrain_left_->Set(drivetrain_->left_high);
+          drivetrain_right_->Set(drivetrain_->right_high);
+        }
+      }
+
+      {
+        PneumaticsToLog to_log;
+        {
+          const bool compressor_on = !pressure_switch_->Get();
+          to_log.compressor_on = compressor_on;
+          if (compressor_on) {
+            compressor_relay_->Set(Relay::kForward);
+          } else {
+            compressor_relay_->Set(Relay::kOff);
+          }
+        }
+
+        pcm_->Flush();
+        to_log.read_solenoids = pcm_->GetAll();
+        LOG_STRUCT(DEBUG, "pneumatics info", to_log);
+      }
+    }
+  }
+
+  void Quit() { run_ = false; }
+
+ private:
+  const ::std::unique_ptr<BufferedPcm> &pcm_;
+
+  ::std::unique_ptr<BufferedSolenoid> drivetrain_left_;
+  ::std::unique_ptr<BufferedSolenoid> drivetrain_right_;
+  ::std::unique_ptr<BufferedSolenoid> shooter_latch_;
+  ::std::unique_ptr<BufferedSolenoid> shooter_brake_;
+
+  ::std::unique_ptr<DigitalSource> pressure_switch_;
+  ::std::unique_ptr<Relay> compressor_relay_;
+
+  ::aos::Queue<::frc971::control_loops::ShooterQueue::Output> shooter_;
+  ::aos::Queue<::frc971::control_loops::DrivetrainQueue::Output> drivetrain_;
+
+  ::std::atomic<bool> run_{true};
+};
+
+class DrivetrainWriter : public LoopOutputHandler {
+ public:
+  void set_left_drivetrain_talon(::std::unique_ptr<Talon> t) {
+    left_drivetrain_talon_ = ::std::move(t);
+  }
+
+  void set_right_drivetrain_talon(::std::unique_ptr<Talon> t) {
+    right_drivetrain_talon_ = ::std::move(t);
+  }
+
+ private:
+  virtual void Read() override {
+    ::frc971::control_loops::drivetrain_queue.output.FetchAnother();
+  }
+
+  virtual void Write() override {
+    auto &queue = ::frc971::control_loops::drivetrain_queue.output;
+    LOG_STRUCT(DEBUG, "will output", *queue);
+    left_drivetrain_talon_->Set(queue->left_voltage / 12.0);
+    right_drivetrain_talon_->Set(-queue->right_voltage / 12.0);
+  }
+
+  virtual void Stop() override {
+    LOG(WARNING, "drivetrain output too old\n");
+    left_drivetrain_talon_->Disable();
+    right_drivetrain_talon_->Disable();
+  }
+
+  ::std::unique_ptr<Talon> left_drivetrain_talon_;
+  ::std::unique_ptr<Talon> right_drivetrain_talon_;
+};
+
+class ShooterWriter : public LoopOutputHandler {
+ public:
+  void set_shooter_talon(::std::unique_ptr<Talon> t) {
+    shooter_talon_ = ::std::move(t);
+  }
+
+ private:
+  virtual void Read() override {
+    ::frc971::control_loops::shooter_queue.output.FetchAnother();
+  }
+
+  virtual void Write() override {
+    auto &queue = ::frc971::control_loops::shooter_queue.output;
+    LOG_STRUCT(DEBUG, "will output", *queue);
+    shooter_talon_->Set(queue->voltage / 12.0);
+  }
+
+  virtual void Stop() override {
+    LOG(WARNING, "shooter output too old\n");
+    shooter_talon_->Disable();
+  }
+
+  ::std::unique_ptr<Talon> shooter_talon_;
+};
+
+class ClawWriter : public LoopOutputHandler {
+ public:
+  void set_top_claw_talon(::std::unique_ptr<Talon> t) {
+    top_claw_talon_ = ::std::move(t);
+  }
+
+  void set_bottom_claw_talon(::std::unique_ptr<Talon> t) {
+    bottom_claw_talon_ = ::std::move(t);
+  }
+
+  void set_left_tusk_talon(::std::unique_ptr<Talon> t) {
+    left_tusk_talon_ = ::std::move(t);
+  }
+
+  void set_right_tusk_talon(::std::unique_ptr<Talon> t) {
+    right_tusk_talon_ = ::std::move(t);
+  }
+
+  void set_intake1_talon(::std::unique_ptr<Talon> t) {
+    intake1_talon_ = ::std::move(t);
+  }
+
+  void set_intake2_talon(::std::unique_ptr<Talon> t) {
+    intake2_talon_ = ::std::move(t);
+  }
+
+ private:
+  virtual void Read() override {
+    ::frc971::control_loops::claw_queue.output.FetchAnother();
+  }
+
+  virtual void Write() override {
+    auto &queue = ::frc971::control_loops::claw_queue.output;
+    LOG_STRUCT(DEBUG, "will output", *queue);
+    intake1_talon_->Set(queue->intake_voltage / 12.0);
+    intake2_talon_->Set(queue->intake_voltage / 12.0);
+    bottom_claw_talon_->Set(-queue->bottom_claw_voltage / 12.0);
+    top_claw_talon_->Set(queue->top_claw_voltage / 12.0);
+    left_tusk_talon_->Set(queue->tusk_voltage / 12.0);
+    right_tusk_talon_->Set(-queue->tusk_voltage / 12.0);
+  }
+
+  virtual void Stop() override {
+    LOG(WARNING, "claw output too old\n");
+    intake1_talon_->Disable();
+    intake2_talon_->Disable();
+    bottom_claw_talon_->Disable();
+    top_claw_talon_->Disable();
+    left_tusk_talon_->Disable();
+    right_tusk_talon_->Disable();
+  }
+
+  ::std::unique_ptr<Talon> top_claw_talon_;
+  ::std::unique_ptr<Talon> bottom_claw_talon_;
+  ::std::unique_ptr<Talon> left_tusk_talon_;
+  ::std::unique_ptr<Talon> right_tusk_talon_;
+  ::std::unique_ptr<Talon> intake1_talon_;
+  ::std::unique_ptr<Talon> intake2_talon_;
+};
+
+class WPILibRobot : public RobotBase {
+ public:
+  ::std::unique_ptr<Encoder> make_encoder(int index) {
+    return make_unique<Encoder>(10 + index * 2, 11 + index * 2, false,
+                                Encoder::k4X);
+  }
+
+  virtual void StartCompetition() {
+    ::aos::InitNRT();
+    ::aos::SetCurrentThreadName("StartCompetition");
+
+    JoystickSender joystick_sender;
+    ::std::thread joystick_thread(::std::ref(joystick_sender));
+
+    SensorReader reader;
+    LOG(INFO, "Creating the reader\n");
+
+    reader.set_auto_selector_analog(make_unique<AnalogInput>(4));
+
+    reader.set_drivetrain_left_encoder(make_encoder(0));
+    reader.set_drivetrain_right_encoder(make_encoder(1));
+    reader.set_high_left_drive_hall(make_unique<AnalogInput>(1));
+    reader.set_low_left_drive_hall(make_unique<AnalogInput>(0));
+    reader.set_high_right_drive_hall(make_unique<AnalogInput>(2));
+    reader.set_low_right_drive_hall(make_unique<AnalogInput>(3));
+
+    reader.set_top_claw_encoder(make_encoder(3));
+    reader.set_top_claw_front_hall(make_unique<HallEffect>(4));  // R2
+    reader.set_top_claw_calibration_hall(make_unique<HallEffect>(3));  // R3
+    reader.set_top_claw_back_hall(make_unique<HallEffect>(5));  // R1
+
+    reader.set_bottom_claw_encoder(make_encoder(5));
+    reader.set_bottom_claw_front_hall(make_unique<HallEffect>(1));  // L2
+    reader.set_bottom_claw_calibration_hall(make_unique<HallEffect>(0));  // L3
+    reader.set_bottom_claw_back_hall(make_unique<HallEffect>(2));  // L1
+
+    reader.set_shooter_encoder(make_encoder(2));
+    reader.set_shooter_proximal(make_unique<HallEffect>(6));  // S1
+    reader.set_shooter_distal(make_unique<HallEffect>(7));  // S2
+    reader.set_shooter_plunger(make_unique<HallEffect>(8));  // S3
+    reader.set_shooter_latch(make_unique<HallEffect>(9));  // S4
+
+    reader.set_dma(make_unique<DMA>());
+    ::std::thread reader_thread(::std::ref(reader));
+
+    GyroSender gyro_sender;
+    ::std::thread gyro_thread(::std::ref(gyro_sender));
+
+    DrivetrainWriter drivetrain_writer;
+    drivetrain_writer.set_left_drivetrain_talon(
+        ::std::unique_ptr<Talon>(new Talon(5)));
+    drivetrain_writer.set_right_drivetrain_talon(
+        ::std::unique_ptr<Talon>(new Talon(2)));
+    ::std::thread drivetrain_writer_thread(::std::ref(drivetrain_writer));
+
+    ::frc971::wpilib::ClawWriter claw_writer;
+    claw_writer.set_top_claw_talon(::std::unique_ptr<Talon>(new Talon(1)));
+    claw_writer.set_bottom_claw_talon(::std::unique_ptr<Talon>(new Talon(0)));
+    claw_writer.set_left_tusk_talon(::std::unique_ptr<Talon>(new Talon(4)));
+    claw_writer.set_right_tusk_talon(::std::unique_ptr<Talon>(new Talon(3)));
+    claw_writer.set_intake1_talon(::std::unique_ptr<Talon>(new Talon(7)));
+    claw_writer.set_intake2_talon(::std::unique_ptr<Talon>(new Talon(8)));
+    ::std::thread claw_writer_thread(::std::ref(claw_writer));
+
+    ::frc971::wpilib::ShooterWriter shooter_writer;
+    shooter_writer.set_shooter_talon(::std::unique_ptr<Talon>(new Talon(6)));
+    ::std::thread shooter_writer_thread(::std::ref(shooter_writer));
+
+    ::std::unique_ptr<::frc971::wpilib::BufferedPcm> pcm(
+        new ::frc971::wpilib::BufferedPcm());
+    SolenoidWriter solenoid_writer(pcm);
+    solenoid_writer.set_drivetrain_left(pcm->MakeSolenoid(6));
+    solenoid_writer.set_drivetrain_right(pcm->MakeSolenoid(7));
+    solenoid_writer.set_shooter_latch(pcm->MakeSolenoid(5));
+    solenoid_writer.set_shooter_brake(pcm->MakeSolenoid(4));
+
+    solenoid_writer.set_pressure_switch(make_unique<DigitalInput>(9));
+    solenoid_writer.set_compressor_relay(make_unique<Relay>(0));
+    ::std::thread solenoid_thread(::std::ref(solenoid_writer));
+
+    // Wait forever. Not much else to do...
+    PCHECK(select(0, nullptr, nullptr, nullptr, nullptr));
+
+    LOG(ERROR, "Exiting WPILibRobot\n");
+
+    joystick_sender.Quit();
+    joystick_thread.join();
+    reader.Quit();
+    reader_thread.join();
+    gyro_sender.Quit();
+    gyro_thread.join();
+
+    drivetrain_writer.Quit();
+    drivetrain_writer_thread.join();
+    shooter_writer.Quit();
+    shooter_writer_thread.join();
+    claw_writer.Quit();
+    claw_writer_thread.join();
+    solenoid_writer.Quit();
+    solenoid_thread.join();
+
+    ::aos::Cleanup();
+  }
+};
+
+}  // namespace wpilib
+}  // namespace frc971
+
+
+START_ROBOT_CLASS(::frc971::wpilib::WPILibRobot);
diff --git a/y2014/y2014.gyp b/y2014/y2014.gyp
new file mode 100644
index 0000000..8787a9a
--- /dev/null
+++ b/y2014/y2014.gyp
@@ -0,0 +1,44 @@
+{
+  'targets': [
+    {
+      'target_name': 'constants',
+      'type': 'static_library',
+      'sources': [
+        'constants.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/common.gyp:once',
+        '<(AOS)/common/network/network.gyp:team_number',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+        '<(DEPTH)/y2014/control_loops/drivetrain/drivetrain.gyp:polydrivetrain_plants',
+      ],
+      'export_dependent_settings': [
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+      ],
+    },
+    {
+      'target_name': 'joystick_reader',
+      'type': 'executable',
+      'sources': [
+        'joystick_reader.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/prime/input/input.gyp:joystick_input',
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/common/util/util.gyp:log_interval',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+
+        '<(DEPTH)/y2014/control_loops/drivetrain/drivetrain.gyp:drivetrain_queue',
+        '<(DEPTH)/y2014/y2014.gyp:constants',
+        '<(DEPTH)/frc971/queues/queues.gyp:gyro',
+        '<(DEPTH)/frc971/autonomous/autonomous.gyp:auto_queue',
+        '<(DEPTH)/y2014/control_loops/claw/claw.gyp:claw_queue',
+        '<(DEPTH)/y2014/control_loops/shooter/shooter.gyp:shooter_queue',
+        '<(DEPTH)/y2014/actors/actors.gyp:shoot_action_lib',
+      ],
+    },
+  ],
+}
diff --git a/y2015/actors/actors.gyp b/y2015/actors/actors.gyp
new file mode 100644
index 0000000..f4989f0
--- /dev/null
+++ b/y2015/actors/actors.gyp
@@ -0,0 +1,630 @@
+{
+  'targets': [
+    {
+      'target_name': 'binaries',
+      'type': 'none',
+      'dependencies': [
+        'drivetrain_action',
+        'score_action',
+        'score_action_test',
+        'pickup_action',
+        'stack_action',
+        'stack_and_lift_action',
+        'stack_and_hold_action',
+        'held_to_lift_action',
+        'can_pickup_action',
+        'horizontal_can_pickup_action',
+        'lift_action',
+        'stack_action_test',
+      ],
+    },
+    {
+      'target_name': 'drivetrain_action_queue',
+      'type': 'static_library',
+      'sources': ['drivetrain_action.q'],
+      'variables': {
+        'header_path': 'y2015/actors',
+      },
+      'dependencies': [
+        '<(AOS)/common/actions/actions.gyp:action_queue',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/actions/actions.gyp:action_queue',
+      ],
+      'includes': ['../../aos/build/queues.gypi'],
+    },
+    {
+      'target_name': 'drivetrain_action_lib',
+      'type': 'static_library',
+      'sources': [
+        'drivetrain_actor.cc',
+      ],
+      'dependencies': [
+        'drivetrain_action_queue',
+        '<(DEPTH)/y2015/y2015.gyp:constants',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/common/util/util.gyp:phased_loop',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        '<(AOS)/common/logging/logging.gyp:queue_logging',
+        '<(EXTERNALS):eigen',
+        '<(AOS)/common/util/util.gyp:trapezoid_profile',
+        '<(DEPTH)/y2015/control_loops/drivetrain/drivetrain.gyp:drivetrain_queue',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        'drivetrain_action_queue',
+      ],
+    },
+    {
+      'target_name': 'drivetrain_action',
+      'type': 'executable',
+      'sources': [
+        'drivetrain_actor_main.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        'drivetrain_action_queue',
+        'drivetrain_action_lib',
+      ],
+    },
+    {
+      'target_name' : 'fridge_profile_lib',
+      'type' : 'static_library',
+      'sources' : [
+        'fridge_profile_lib.cc',
+      ],
+      'dependencies' : [
+        '<(AOS)/build/aos.gyp:logging_interface',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        '<(DEPTH)/y2015/control_loops/fridge/fridge.gyp:fridge_queue',
+      ],
+      'export_dependent_settings' : [
+        '<(AOS)/build/aos.gyp:logging_interface',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        '<(DEPTH)/y2015/control_loops/fridge/fridge.gyp:fridge_queue',
+      ],
+    },
+    {
+      'target_name': 'score_action_queue',
+      'type': 'static_library',
+      'sources': ['score_action.q'],
+      'variables': {
+        'header_path': 'y2015/actors',
+      },
+      'dependencies': [
+        '<(AOS)/common/actions/actions.gyp:action_queue',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/actions/actions.gyp:action_queue',
+      ],
+      'includes': ['../../aos/build/queues.gypi'],
+    },
+    {
+      'target_name': 'score_action_lib',
+      'type': 'static_library',
+      'sources': [
+        'score_actor.cc',
+      ],
+      'dependencies': [
+        'score_action_queue',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+        '<(DEPTH)/y2015/y2015.gyp:constants',
+        '<(DEPTH)/y2015/control_loops/fridge/fridge.gyp:fridge_queue',
+        '<(EXTERNALS):eigen',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        'score_action_queue',
+        '<(EXTERNALS):eigen',
+      ],
+    },
+    {
+      'target_name': 'score_action',
+      'type': 'executable',
+      'sources': [
+        'score_actor_main.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        'score_action_queue',
+        'score_action_lib',
+      ],
+    },
+    {
+      'target_name': 'score_action_test',
+      'type': 'executable',
+      'sources': [
+        'score_actor_test.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+        '<(AOS)/common/common.gyp:queue_testutils',
+        '<(AOS)/common/logging/logging.gyp:queue_logging',
+        '<(AOS)/common/common.gyp:queues',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        '<(DEPTH)/y2015/control_loops/fridge/fridge.gyp:fridge_queue',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:team_number_test_environment',
+        'score_action_queue',
+        'score_action_lib',
+      ],
+    },
+    {
+      'target_name': 'pickup_action_queue',
+      'type': 'static_library',
+      'sources': ['pickup_action.q'],
+      'variables': {
+        'header_path': 'y2015/actors',
+      },
+      'dependencies': [
+        '<(AOS)/common/actions/actions.gyp:action_queue',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/actions/actions.gyp:action_queue',
+      ],
+      'includes': ['../../aos/build/queues.gypi'],
+    },
+    {
+      'target_name': 'pickup_action_lib',
+      'type': 'static_library',
+      'sources': [
+        'pickup_actor.cc',
+      ],
+      'dependencies': [
+        'pickup_action_queue',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+        '<(DEPTH)/y2015/control_loops/claw/claw.gyp:claw_queue',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        'pickup_action_queue',
+      ],
+    },
+    {
+      'target_name': 'pickup_action',
+      'type': 'executable',
+      'sources': [
+        'pickup_actor_main.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        'pickup_action_queue',
+        'pickup_action_lib',
+      ],
+    },
+    {
+      'target_name': 'can_pickup_action_queue',
+      'type': 'static_library',
+      'sources': ['can_pickup_action.q'],
+      'variables': {
+        'header_path': 'y2015/actors',
+      },
+      'dependencies': [
+        '<(AOS)/common/actions/actions.gyp:action_queue',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/actions/actions.gyp:action_queue',
+      ],
+      'includes': ['../../aos/build/queues.gypi'],
+    },
+    {
+      'target_name': 'can_pickup_action_lib',
+      'type': 'static_library',
+      'sources': [
+        'can_pickup_actor.cc',
+      ],
+      'dependencies': [
+        'fridge_profile_lib',
+        'can_pickup_action_queue',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/util/util.gyp:phased_loop',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        '<(DEPTH)/y2015/y2015.gyp:constants',
+        '<(DEPTH)/y2015/control_loops/claw/claw.gyp:claw_queue',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+      ],
+      'export_dependent_settings': [
+        'fridge_profile_lib',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        'can_pickup_action_queue',
+      ],
+    },
+    {
+      'target_name': 'can_pickup_action',
+      'type': 'executable',
+      'sources': [
+        'can_pickup_actor_main.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        'can_pickup_action_queue',
+        'can_pickup_action_lib',
+      ],
+    },
+    {
+      'target_name': 'horizontal_can_pickup_action_queue',
+      'type': 'static_library',
+      'sources': ['horizontal_can_pickup_action.q'],
+      'variables': {
+        'header_path': 'y2015/actors',
+      },
+      'dependencies': [
+        '<(AOS)/common/actions/actions.gyp:action_queue',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/actions/actions.gyp:action_queue',
+      ],
+      'includes': ['../../aos/build/queues.gypi'],
+    },
+    {
+      'target_name': 'horizontal_can_pickup_action_lib',
+      'type': 'static_library',
+      'sources': [
+        'horizontal_can_pickup_actor.cc',
+      ],
+      'dependencies': [
+        'fridge_profile_lib',
+        'horizontal_can_pickup_action_queue',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/util/util.gyp:phased_loop',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        '<(DEPTH)/y2015/y2015.gyp:constants',
+        '<(DEPTH)/y2015/control_loops/claw/claw.gyp:claw_queue',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+      ],
+      'export_dependent_settings': [
+        'fridge_profile_lib',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        'horizontal_can_pickup_action_queue',
+      ],
+    },
+    {
+      'target_name': 'horizontal_can_pickup_action',
+      'type': 'executable',
+      'sources': [
+        'horizontal_can_pickup_actor_main.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        'horizontal_can_pickup_action_queue',
+        'horizontal_can_pickup_action_lib',
+      ],
+    },
+    {
+      'target_name': 'held_to_lift_action_queue',
+      'type': 'static_library',
+      'sources': ['held_to_lift_action.q'],
+      'variables': {
+        'header_path': 'y2015/actors',
+      },
+      'dependencies': [
+        '<(AOS)/common/actions/actions.gyp:action_queue',
+        'lift_action_params',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/actions/actions.gyp:action_queue',
+        'lift_action_params',
+      ],
+      'includes': ['../../aos/build/queues.gypi'],
+    },
+    {
+      'target_name': 'held_to_lift_action_lib',
+      'type': 'static_library',
+      'sources': [
+        'held_to_lift_actor.cc',
+      ],
+      'dependencies': [
+        'fridge_profile_lib',
+        'held_to_lift_action_queue',
+        'lift_action_lib',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/util/util.gyp:phased_loop',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        '<(DEPTH)/y2015/y2015.gyp:constants',
+        '<(DEPTH)/y2015/control_loops/claw/claw.gyp:claw_queue',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        'held_to_lift_action_queue',
+        'fridge_profile_lib',
+      ],
+    },
+    {
+      'target_name': 'held_to_lift_action',
+      'type': 'executable',
+      'sources': [
+        'held_to_lift_actor_main.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        'held_to_lift_action_queue',
+        'held_to_lift_action_lib',
+      ],
+    },
+    {
+      'target_name': 'stack_and_hold_action_queue',
+      'type': 'static_library',
+      'sources': ['stack_and_hold_action.q'],
+      'variables': {
+        'header_path': 'y2015/actors',
+      },
+      'dependencies': [
+        '<(AOS)/common/actions/actions.gyp:action_queue',
+        'stack_action_params',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/actions/actions.gyp:action_queue',
+        'stack_action_params',
+      ],
+      'includes': ['../../aos/build/queues.gypi'],
+    },
+    {
+      'target_name': 'stack_and_hold_action_lib',
+      'type': 'static_library',
+      'sources': [
+        'stack_and_hold_actor.cc',
+      ],
+      'dependencies': [
+        'fridge_profile_lib',
+        'stack_and_hold_action_queue',
+        'stack_action_lib',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/util/util.gyp:phased_loop',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        '<(DEPTH)/y2015/y2015.gyp:constants',
+        '<(DEPTH)/y2015/control_loops/claw/claw.gyp:claw_queue',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        'stack_and_hold_action_queue',
+        'fridge_profile_lib',
+      ],
+    },
+    {
+      'target_name': 'stack_and_hold_action',
+      'type': 'executable',
+      'sources': [
+        'stack_and_hold_actor_main.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        'stack_and_hold_action_queue',
+        'stack_and_hold_action_lib',
+      ],
+    },
+    {
+      'target_name': 'stack_and_lift_action_queue',
+      'type': 'static_library',
+      'sources': ['stack_and_lift_action.q'],
+      'variables': {
+        'header_path': 'y2015/actors',
+      },
+      'dependencies': [
+        '<(AOS)/common/actions/actions.gyp:action_queue',
+        'stack_action_params',
+        'lift_action_params',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/actions/actions.gyp:action_queue',
+        'stack_action_params',
+        'lift_action_params',
+      ],
+      'includes': ['../../aos/build/queues.gypi'],
+    },
+    {
+      'target_name': 'stack_and_lift_action_lib',
+      'type': 'static_library',
+      'sources': [
+        'stack_and_lift_actor.cc',
+      ],
+      'dependencies': [
+        'fridge_profile_lib',
+        'stack_and_lift_action_queue',
+        'stack_action_lib',
+        'lift_action_lib',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/util/util.gyp:phased_loop',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        '<(DEPTH)/y2015/y2015.gyp:constants',
+        '<(DEPTH)/y2015/control_loops/claw/claw.gyp:claw_queue',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        'stack_and_lift_action_queue',
+        'fridge_profile_lib',
+      ],
+    },
+    {
+      'target_name': 'stack_and_lift_action',
+      'type': 'executable',
+      'sources': [
+        'stack_and_lift_actor_main.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        'stack_and_lift_action_queue',
+        'stack_and_lift_action_lib',
+      ],
+    },
+    {
+      # This is a wrapper target to avoid adding the directory with a stale
+      # stack_action_params.q.h to the compiler's include path.
+      'target_name': 'stack_action_queue',
+      'type': 'none',
+      'dependencies': ['stack_action_queue_real'],
+      'export_dependent_settings': ['stack_action_queue_real'],
+    },
+    {
+      'target_name': 'stack_action_queue_real',
+      'type': 'static_library',
+      'sources': [
+        'stack_action.q',
+      ],
+      'variables': {
+        'header_path': 'y2015/actors',
+      },
+      'dependencies': [
+        '<(AOS)/common/actions/actions.gyp:action_queue',
+        'stack_action_params',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/actions/actions.gyp:action_queue',
+        'stack_action_params',
+      ],
+      'includes': ['../../aos/build/queues.gypi'],
+    },
+    {
+      'target_name': 'stack_action_params',
+      'type': 'static_library',
+      'sources': [
+        'stack_action_params.q',
+      ],
+      'variables': {
+        'header_path': 'y2015/actors',
+      },
+      'includes': ['../../aos/build/queues.gypi'],
+    },
+    {
+      'target_name': 'stack_action_test',
+      'type': 'executable',
+      'sources': [
+        'stack_actor_test.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+        '<(AOS)/common/common.gyp:queue_testutils',
+        '<(AOS)/common/logging/logging.gyp:queue_logging',
+        '<(AOS)/common/common.gyp:queues',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        '<(DEPTH)/y2015/control_loops/fridge/fridge.gyp:fridge_queue',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:team_number_test_environment',
+        'stack_action_queue',
+        'stack_action_lib',
+      ],
+    },
+    {
+      'target_name': 'stack_action_lib',
+      'type': 'static_library',
+      'sources': [
+        'stack_actor.cc',
+      ],
+      'dependencies': [
+        'fridge_profile_lib',
+        'stack_action_queue',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/util/util.gyp:phased_loop',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        '<(DEPTH)/y2015/y2015.gyp:constants',
+        '<(DEPTH)/y2015/control_loops/claw/claw.gyp:claw_queue',
+      ],
+      'export_dependent_settings': [
+        'fridge_profile_lib',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        'stack_action_queue',
+      ],
+    },
+    {
+      'target_name': 'stack_action',
+      'type': 'executable',
+      'sources': [
+        'stack_actor_main.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        'stack_action_queue',
+        'stack_action_lib',
+      ],
+    },
+    {
+      # This is a wrapper target to avoid adding the directory with a stale
+      # lift_action_params.q.h to the compiler's include path.
+      'target_name': 'lift_action_queue',
+      'type': 'none',
+      'dependencies': ['lift_action_queue_real'],
+      'export_dependent_settings': ['lift_action_queue_real'],
+    },
+    {
+      'target_name': 'lift_action_queue_real',
+      'type': 'static_library',
+      'sources': [
+        'lift_action.q',
+      ],
+      'variables': {
+        'header_path': 'y2015/actors',
+      },
+      'dependencies': [
+        '<(AOS)/common/actions/actions.gyp:action_queue',
+        'lift_action_params',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/actions/actions.gyp:action_queue',
+        'lift_action_params',
+      ],
+      'includes': ['../../aos/build/queues.gypi'],
+    },
+    {
+      'target_name': 'lift_action_params',
+      'type': 'static_library',
+      'sources': [
+        'lift_action_params.q',
+      ],
+      'variables': {
+        'header_path': 'y2015/actors',
+      },
+      'includes': ['../../aos/build/queues.gypi'],
+    },
+    {
+      'target_name': 'lift_action_lib',
+      'type': 'static_library',
+      'sources': [
+        'lift_actor.cc',
+      ],
+      'dependencies': [
+        'fridge_profile_lib',
+        'lift_action_queue',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        '<(DEPTH)/y2015/y2015.gyp:constants',
+        '<(DEPTH)/y2015/control_loops/claw/claw.gyp:claw_queue',
+      ],
+      'export_dependent_settings': [
+        'fridge_profile_lib',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        'lift_action_queue',
+      ],
+    },
+    {
+      'target_name': 'lift_action',
+      'type': 'executable',
+      'sources': [
+        'lift_actor_main.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+        'lift_action_queue',
+        'lift_action_lib',
+      ],
+    },
+  ],
+}
diff --git a/y2015/actors/can_pickup_action.q b/y2015/actors/can_pickup_action.q
new file mode 100644
index 0000000..4846722
--- /dev/null
+++ b/y2015/actors/can_pickup_action.q
@@ -0,0 +1,40 @@
+package frc971.actors;
+
+import "aos/common/actions/actions.q";
+
+// Parameters to send with start.
+// This action picks a right side up can from the claw.
+// It starts by lifting up, then moving the arm out, then lifting the can out of
+// the claw, and then ends with the can inside the bot.
+struct CanPickupParams {
+  // X position for the fridge when picking up.
+  double pickup_x;
+  // Y position for the fridge when picking up.
+  double pickup_y;
+  // Height to move the elevator to to lift the can out of the claw.
+  double lift_height;
+  // Height to use when lifting before moving it back.
+  double pickup_goal_before_move_height;
+  // The height at which to start pulling back.
+  double before_place_height;
+
+  // X at which to start lowering the can.
+  double start_lowering_x;
+  // End position with the can.
+  double end_height;
+  double end_angle;
+};
+
+queue_group CanPickupActionQueueGroup {
+  implements aos.common.actions.ActionQueueGroup;
+
+  message Goal {
+    uint32_t run;
+    CanPickupParams params;
+  };
+
+  queue Goal goal;
+  queue aos.common.actions.Status status;
+};
+
+queue_group CanPickupActionQueueGroup can_pickup_action;
diff --git a/y2015/actors/can_pickup_actor.cc b/y2015/actors/can_pickup_actor.cc
new file mode 100644
index 0000000..d2a191f
--- /dev/null
+++ b/y2015/actors/can_pickup_actor.cc
@@ -0,0 +1,122 @@
+#include <math.h>
+
+#include "aos/common/time.h"
+#include "aos/common/util/phased_loop.h"
+
+#include "y2015/actors/can_pickup_actor.h"
+#include "y2015/constants.h"
+#include "y2015/control_loops/claw/claw.q.h"
+
+using ::frc971::control_loops::fridge_queue;
+
+namespace frc971 {
+namespace actors {
+namespace {
+constexpr ProfileParams kHorizontalMove{1.1, 1.8};
+constexpr ProfileParams kVerticalMove{0.3, 2.0};
+constexpr ProfileParams kFastHorizontalMove{1.25, 5.0};
+constexpr ProfileParams kFastVerticalMove{0.40, 2.0};
+constexpr ProfileParams kPureVerticalMove{1.20, 5.0};
+}  // namespace
+
+CanPickupActor::CanPickupActor(CanPickupActionQueueGroup *queues)
+    : FridgeActorBase<CanPickupActionQueueGroup>(queues) {}
+
+double CanPickupActor::CurrentGoalX() {
+  fridge_queue.status.FetchLatest();
+  if (!fridge_queue.status.get()) {
+    LOG(ERROR, "Reading from fridge status queue failed.\n");
+    return 0.0;
+  }
+
+  return fridge_queue.status->goal_x;
+}
+
+double CanPickupActor::CurrentGoalHeight() {
+  fridge_queue.status.FetchLatest();
+  if (!fridge_queue.status.get()) {
+    LOG(ERROR, "Reading from fridge status queue failed.\n");
+    return 0.0;
+  }
+
+  return fridge_queue.status->goal_y;
+}
+
+bool CanPickupActor::RunAction(const CanPickupParams &params) {
+  // Make sure the claw is down.
+  {
+    auto message = control_loops::claw_queue.goal.MakeMessage();
+    message->angle = 0.0;
+    message->angular_velocity = 0.0;
+    message->intake = 0.0;
+    message->rollers_closed = true;
+    message->max_velocity = 6.0;
+    message->max_acceleration = 10.0;
+
+    LOG_STRUCT(DEBUG, "Sending claw down goal", *message);
+    message.Send();
+  }
+
+  // Go around the can.
+  DoFridgeXYProfile(params.pickup_x, params.pickup_y, kFastHorizontalMove,
+                    kFastVerticalMove, true, false, false);
+  if (ShouldCancel()) return true;
+
+  if (!StartFridgeXYProfile(
+          params.pickup_x, params.pickup_goal_before_move_height,
+          kHorizontalMove, kPureVerticalMove, true, true, true)) {
+    return false;
+  }
+  {
+    auto message = control_loops::claw_queue.goal.MakeMessage();
+    message->angle = 0.0;
+    message->angular_velocity = 0.0;
+    message->intake = 0.0;
+    message->rollers_closed = false;
+    message->max_velocity = 6.0;
+    message->max_acceleration = 10.0;
+
+    LOG_STRUCT(DEBUG, "Sending claw down goal", *message);
+    message.Send();
+  }
+
+  bool above_claw = false;
+  while (true) {
+    if (CurrentGoalHeight() > params.lift_height && !above_claw) {
+      if (!StartFridgeXYProfile(0.0, params.before_place_height,
+                                kHorizontalMove, kVerticalMove, true, true,
+                                true)) {
+        return false;
+      }
+      above_claw = true;
+    }
+    if (CurrentGoalX() < params.start_lowering_x) {
+      // Getting close, start lowering.
+      LOG(DEBUG, "Starting to lower the can onto the tray.\n");
+      break;
+    }
+    ProfileStatus status =
+        IterateXYProfile(0.0, params.before_place_height, kHorizontalMove,
+                         kVerticalMove, true, true, true);
+    if (status == DONE || status == CANCELED) {
+      break;
+    }
+  }
+  if (ShouldCancel()) return true;
+
+  // Lower it.
+  DoFridgeXYProfile(0.0, params.end_height, kHorizontalMove, kPureVerticalMove,
+                    true);
+  if (ShouldCancel()) return true;
+
+  return true;
+}
+
+::std::unique_ptr<CanPickupAction> MakeCanPickupAction(
+    const CanPickupParams &params) {
+  return ::std::unique_ptr<CanPickupAction>(
+      new CanPickupAction(&::frc971::actors::can_pickup_action, params));
+}
+
+}  // namespace actors
+}  // namespace frc971
diff --git a/y2015/actors/can_pickup_actor.h b/y2015/actors/can_pickup_actor.h
new file mode 100644
index 0000000..f0b1ec9
--- /dev/null
+++ b/y2015/actors/can_pickup_actor.h
@@ -0,0 +1,37 @@
+#ifndef Y2015_ACTORS_CAN_PICKUP_ACTOR_H_
+#define Y2015_ACTORS_CAN_PICKUP_ACTOR_H_
+
+#include <stdint.h>
+
+#include <memory>
+
+#include "aos/common/actions/actions.h"
+#include "aos/common/actions/actor.h"
+#include "y2015/actors/can_pickup_action.q.h"
+#include "y2015/actors/fridge_profile_lib.h"
+
+namespace frc971 {
+namespace actors {
+
+class CanPickupActor : public FridgeActorBase<CanPickupActionQueueGroup> {
+ public:
+  explicit CanPickupActor(CanPickupActionQueueGroup *queues);
+
+  bool RunAction(const CanPickupParams &params) override;
+
+ private:
+  double CurrentGoalHeight();
+  double CurrentGoalX();
+};
+
+typedef aos::common::actions::TypedAction<CanPickupActionQueueGroup>
+    CanPickupAction;
+
+// Makes a new CanPickupActor action.
+::std::unique_ptr<CanPickupAction> MakeCanPickupAction(
+    const CanPickupParams &params);
+
+}  // namespace actors
+}  // namespace frc971
+
+#endif
diff --git a/y2015/actors/can_pickup_actor_main.cc b/y2015/actors/can_pickup_actor_main.cc
new file mode 100644
index 0000000..bed9412
--- /dev/null
+++ b/y2015/actors/can_pickup_actor_main.cc
@@ -0,0 +1,15 @@
+#include <stdio.h>
+
+#include "aos/linux_code/init.h"
+#include "y2015/actors/can_pickup_action.q.h"
+#include "y2015/actors/can_pickup_actor.h"
+
+int main(int /*argc*/, char* /*argv*/ []) {
+  ::aos::Init();
+
+  ::frc971::actors::CanPickupActor can_pickup(&::frc971::actors::can_pickup_action);
+  can_pickup.Run();
+
+  ::aos::Cleanup();
+  return 0;
+}
diff --git a/y2015/actors/drivetrain_action.q b/y2015/actors/drivetrain_action.q
new file mode 100644
index 0000000..9ad55d3
--- /dev/null
+++ b/y2015/actors/drivetrain_action.q
@@ -0,0 +1,29 @@
+package frc971.actors;
+
+import "aos/common/actions/actions.q";
+
+// Parameters to send with start.
+struct DrivetrainActionParams {
+  double left_initial_position;
+  double right_initial_position;
+  double y_offset;
+  double theta_offset;
+  double maximum_velocity;
+  double maximum_acceleration;
+  double maximum_turn_velocity;
+  double maximum_turn_acceleration;
+};
+
+queue_group DrivetrainActionQueueGroup {
+  implements aos.common.actions.ActionQueueGroup;
+
+  message Goal {
+    uint32_t run;
+    DrivetrainActionParams params;
+  };
+
+  queue Goal goal;
+  queue aos.common.actions.Status status;
+};
+
+queue_group DrivetrainActionQueueGroup drivetrain_action;
diff --git a/y2015/actors/drivetrain_actor.cc b/y2015/actors/drivetrain_actor.cc
new file mode 100644
index 0000000..9ef81c5
--- /dev/null
+++ b/y2015/actors/drivetrain_actor.cc
@@ -0,0 +1,168 @@
+#include "y2015/actors/drivetrain_actor.h"
+
+#include <functional>
+#include <numeric>
+
+#include <Eigen/Dense>
+
+#include "aos/common/util/phased_loop.h"
+#include "aos/common/logging/logging.h"
+#include "aos/common/util/trapezoid_profile.h"
+#include "aos/common/commonmath.h"
+#include "aos/common/time.h"
+
+#include "y2015/actors/drivetrain_actor.h"
+#include "y2015/constants.h"
+#include "y2015/control_loops/drivetrain/drivetrain.q.h"
+
+namespace frc971 {
+namespace actors {
+
+DrivetrainActor::DrivetrainActor(actors::DrivetrainActionQueueGroup* s)
+    : aos::common::actions::ActorBase<actors::DrivetrainActionQueueGroup>(s) {}
+
+bool DrivetrainActor::RunAction(const actors::DrivetrainActionParams &params) {
+  static const auto K = constants::GetValues().make_drivetrain_loop().K();
+
+  const double yoffset = params.y_offset;
+  const double turn_offset =
+      params.theta_offset * constants::GetValues().turn_width / 2.0;
+  LOG(INFO, "Going to move %f and turn %f\n", yoffset, turn_offset);
+
+  // Measured conversion to get the distance right.
+  ::aos::util::TrapezoidProfile profile(::aos::time::Time::InMS(5));
+  ::aos::util::TrapezoidProfile turn_profile(::aos::time::Time::InMS(5));
+  const double goal_velocity = 0.0;
+  const double epsilon = 0.01;
+  ::Eigen::Matrix<double, 2, 1> left_goal_state, right_goal_state;
+
+  profile.set_maximum_acceleration(params.maximum_acceleration);
+  profile.set_maximum_velocity(params.maximum_velocity);
+  turn_profile.set_maximum_acceleration(params.maximum_turn_acceleration *
+                                        constants::GetValues().turn_width /
+                                        2.0);
+  turn_profile.set_maximum_velocity(params.maximum_turn_velocity *
+                                    constants::GetValues().turn_width / 2.0);
+
+  while (true) {
+    ::aos::time::PhasedLoopXMS(5, 2500);
+
+    control_loops::drivetrain_queue.status.FetchLatest();
+    if (control_loops::drivetrain_queue.status.get()) {
+      const auto& status = *control_loops::drivetrain_queue.status;
+      if (::std::abs(status.uncapped_left_voltage -
+                     status.uncapped_right_voltage) > 24) {
+        LOG(DEBUG, "spinning in place\n");
+        // They're more than 24V apart, so stop moving forwards and let it deal
+        // with spinning first.
+        profile.SetGoal(
+            (status.filtered_left_position + status.filtered_right_position -
+             params.left_initial_position - params.right_initial_position) /
+            2.0);
+      } else {
+        static const double divisor = K(0, 0) + K(0, 2);
+        double dx_left, dx_right;
+        if (status.uncapped_left_voltage > 12.0) {
+          dx_left = (status.uncapped_left_voltage - 12.0) / divisor;
+        } else if (status.uncapped_left_voltage < -12.0) {
+          dx_left = (status.uncapped_left_voltage + 12.0) / divisor;
+        } else {
+          dx_left = 0;
+        }
+        if (status.uncapped_right_voltage > 12.0) {
+          dx_right = (status.uncapped_right_voltage - 12.0) / divisor;
+        } else if (status.uncapped_right_voltage < -12.0) {
+          dx_right = (status.uncapped_right_voltage + 12.0) / divisor;
+        } else {
+          dx_right = 0;
+        }
+        double dx;
+        if (dx_left == 0 && dx_right == 0) {
+          dx = 0;
+        } else if (dx_left != 0 && dx_right != 0 &&
+                   ::aos::sign(dx_left) != ::aos::sign(dx_right)) {
+          // Both saturating in opposite directions. Don't do anything.
+          LOG(DEBUG, "Saturating opposite ways, not adjusting\n");
+          dx = 0;
+        } else if (::std::abs(dx_left) > ::std::abs(dx_right)) {
+          dx = dx_left;
+        } else {
+          dx = dx_right;
+        }
+        if (dx != 0) {
+          LOG(DEBUG, "adjusting goal by %f\n", dx);
+          profile.MoveGoal(-dx);
+        }
+      }
+    } else {
+      // If we ever get here, that's bad and we should just give up
+      LOG(ERROR, "no drivetrain status!\n");
+      return false;
+    }
+
+    const auto drive_profile_goal_state =
+        profile.Update(yoffset, goal_velocity);
+    const auto turn_profile_goal_state = turn_profile.Update(turn_offset, 0.0);
+    left_goal_state = drive_profile_goal_state - turn_profile_goal_state;
+    right_goal_state = drive_profile_goal_state + turn_profile_goal_state;
+
+    if (::std::abs(drive_profile_goal_state(0, 0) - yoffset) < epsilon &&
+        ::std::abs(turn_profile_goal_state(0, 0) - turn_offset) < epsilon) {
+      break;
+    }
+
+    if (ShouldCancel()) return true;
+
+    LOG(DEBUG, "Driving left to %f, right to %f\n",
+        left_goal_state(0, 0) + params.left_initial_position,
+        right_goal_state(0, 0) + params.right_initial_position);
+    control_loops::drivetrain_queue.goal.MakeWithBuilder()
+        .control_loop_driving(true)
+        //.highgear(false)
+        .left_goal(left_goal_state(0, 0) + params.left_initial_position)
+        .right_goal(right_goal_state(0, 0) + params.right_initial_position)
+        .left_velocity_goal(left_goal_state(1, 0))
+        .right_velocity_goal(right_goal_state(1, 0))
+        .Send();
+  }
+  if (ShouldCancel()) return true;
+  control_loops::drivetrain_queue.status.FetchLatest();
+  while (!control_loops::drivetrain_queue.status.get()) {
+    LOG(WARNING,
+        "No previous drivetrain status packet, trying to fetch again\n");
+    control_loops::drivetrain_queue.status.FetchNextBlocking();
+    if (ShouldCancel()) return true;
+  }
+  while (true) {
+    if (ShouldCancel()) return true;
+    const double kPositionThreshold = 0.05;
+
+    const double left_error = ::std::abs(
+        control_loops::drivetrain_queue.status->filtered_left_position -
+        (left_goal_state(0, 0) + params.left_initial_position));
+    const double right_error = ::std::abs(
+        control_loops::drivetrain_queue.status->filtered_right_position -
+        (right_goal_state(0, 0) + params.right_initial_position));
+    const double velocity_error =
+        ::std::abs(control_loops::drivetrain_queue.status->robot_speed);
+    if (left_error < kPositionThreshold && right_error < kPositionThreshold &&
+        velocity_error < 0.2) {
+      break;
+    } else {
+      LOG(DEBUG, "Drivetrain error is %f, %f, %f\n", left_error, right_error,
+          velocity_error);
+    }
+    control_loops::drivetrain_queue.status.FetchNextBlocking();
+  }
+  LOG(INFO, "Done moving\n");
+  return true;
+}
+
+::std::unique_ptr<DrivetrainAction> MakeDrivetrainAction(
+    const ::frc971::actors::DrivetrainActionParams& params) {
+  return ::std::unique_ptr<DrivetrainAction>(
+      new DrivetrainAction(&::frc971::actors::drivetrain_action, params));
+}
+
+}  // namespace actors
+}  // namespace frc971
diff --git a/y2015/actors/drivetrain_actor.h b/y2015/actors/drivetrain_actor.h
new file mode 100644
index 0000000..369c6ed
--- /dev/null
+++ b/y2015/actors/drivetrain_actor.h
@@ -0,0 +1,31 @@
+#ifndef Y2015_ACTIONS_DRIVETRAIN_ACTION_H_
+#define Y2015_ACTIONS_DRIVETRAIN_ACTION_H_
+
+#include <memory>
+
+#include "y2015/actors/drivetrain_action.q.h"
+#include "aos/common/actions/actor.h"
+#include "aos/common/actions/actions.h"
+
+namespace frc971 {
+namespace actors {
+
+class DrivetrainActor
+    : public aos::common::actions::ActorBase<DrivetrainActionQueueGroup> {
+ public:
+  explicit DrivetrainActor(DrivetrainActionQueueGroup* s);
+
+  bool RunAction(const actors::DrivetrainActionParams &params) override;
+};
+
+typedef aos::common::actions::TypedAction<DrivetrainActionQueueGroup>
+    DrivetrainAction;
+
+// Makes a new DrivetrainActor action.
+::std::unique_ptr<DrivetrainAction> MakeDrivetrainAction(
+    const ::frc971::actors::DrivetrainActionParams& params);
+
+}  // namespace actors
+}  // namespace frc971
+
+#endif
diff --git a/y2015/actors/drivetrain_actor_main.cc b/y2015/actors/drivetrain_actor_main.cc
new file mode 100644
index 0000000..7e461ff
--- /dev/null
+++ b/y2015/actors/drivetrain_actor_main.cc
@@ -0,0 +1,18 @@
+#include <stdio.h>
+
+#include "aos/linux_code/init.h"
+#include "y2015/actors/drivetrain_action.q.h"
+#include "y2015/actors/drivetrain_actor.h"
+
+using ::aos::time::Time;
+
+int main(int /*argc*/, char * /*argv*/[]) {
+  ::aos::Init();
+
+  frc971::actors::DrivetrainActor drivetrain(
+      &::frc971::actors::drivetrain_action);
+  drivetrain.Run();
+
+  ::aos::Cleanup();
+  return 0;
+}
diff --git a/y2015/actors/fridge_profile_lib.cc b/y2015/actors/fridge_profile_lib.cc
new file mode 100644
index 0000000..1a1866f
--- /dev/null
+++ b/y2015/actors/fridge_profile_lib.cc
@@ -0,0 +1 @@
+#include "y2015/actors/fridge_profile_lib.h"
diff --git a/y2015/actors/fridge_profile_lib.h b/y2015/actors/fridge_profile_lib.h
new file mode 100644
index 0000000..ce75f75
--- /dev/null
+++ b/y2015/actors/fridge_profile_lib.h
@@ -0,0 +1,285 @@
+#ifndef Y2015_ACTORS_FRIDGE_PROFILE_LIB_H_
+#define Y2015_ACTORS_FRIDGE_PROFILE_LIB_H_
+
+#include <cmath>
+
+#include "aos/common/actions/actor.h"
+#include "aos/common/util/phased_loop.h"
+#include "y2015/control_loops/fridge/fridge.q.h"
+
+namespace frc971 {
+namespace actors {
+
+struct ProfileParams {
+  double velocity;
+  double acceleration;
+};
+
+// Base class to provide helper utilities to all Actors who want to control the
+// fridge.
+template <typename T>
+class FridgeActorBase : public aos::common::actions::ActorBase<T> {
+ public:
+  FridgeActorBase(T *queues) : aos::common::actions::ActorBase<T>(queues) {}
+
+ protected:
+  void DoFridgeProfile(double height, double angle,
+                       ProfileParams elevator_parameters,
+                       ProfileParams arm_parameters, bool grabbers) {
+    DoFridgeProfile(height, angle, elevator_parameters, arm_parameters,
+                    grabbers, grabbers, grabbers);
+  }
+
+  bool StartFridgeProfile(double height, double angle,
+                          ProfileParams elevator_parameters,
+                          ProfileParams arm_parameters, bool top_grabbers,
+                          bool front_grabbers, bool back_grabbers) {
+    auto new_fridge_goal = control_loops::fridge_queue.goal.MakeMessage();
+    new_fridge_goal->profiling_type = 0;
+    new_fridge_goal->max_velocity = elevator_parameters.velocity;
+    new_fridge_goal->max_acceleration = elevator_parameters.acceleration;
+    new_fridge_goal->height = height;
+    new_fridge_goal->velocity = 0.0;
+    new_fridge_goal->max_angular_velocity = arm_parameters.velocity;
+    new_fridge_goal->max_angular_acceleration = arm_parameters.acceleration;
+    new_fridge_goal->angle = angle;
+    new_fridge_goal->angular_velocity = 0.0;
+    new_fridge_goal->grabbers.top_front = top_grabbers;
+    new_fridge_goal->grabbers.top_back = top_grabbers;
+    new_fridge_goal->grabbers.bottom_front = front_grabbers;
+    new_fridge_goal->grabbers.bottom_back = back_grabbers;
+    LOG(INFO, "Starting profile to %f, %f\n", height, angle);
+
+    if (!new_fridge_goal.Send()) {
+      LOG(ERROR, "Failed to send fridge goal\n");
+      return false;
+    }
+    return true;
+  }
+
+  enum ProfileStatus { RUNNING, DONE, CANCELED };
+
+  ProfileStatus IterateProfile(double height, double angle,
+                               ProfileParams elevator_parameters,
+                               ProfileParams arm_parameters, bool top_grabbers,
+                               bool front_grabbers, bool back_grabbers) {
+    if (this->ShouldCancel()) {
+      LOG(INFO, "Canceling fridge movement\n");
+      if (!control_loops::fridge_queue.status.get()) {
+        LOG(WARNING, "no fridge status so can't really cancel\n");
+        return CANCELED;
+      }
+
+      auto new_fridge_goal = control_loops::fridge_queue.goal.MakeMessage();
+      new_fridge_goal->profiling_type = 0;
+      new_fridge_goal->max_velocity = elevator_parameters.velocity;
+      new_fridge_goal->max_acceleration = elevator_parameters.acceleration;
+      new_fridge_goal->height =
+          control_loops::fridge_queue.status->height +
+          (control_loops::fridge_queue.status->goal_velocity *
+           ::std::abs(control_loops::fridge_queue.status->goal_velocity)) /
+              (2.0 * new_fridge_goal->max_acceleration);
+      height = new_fridge_goal->height;
+      new_fridge_goal->velocity = 0.0;
+      new_fridge_goal->max_angular_velocity = arm_parameters.velocity;
+      new_fridge_goal->max_angular_acceleration = arm_parameters.acceleration;
+      new_fridge_goal->angle =
+          control_loops::fridge_queue.status->angle +
+          (control_loops::fridge_queue.status->goal_angular_velocity *
+           ::std::abs(
+               control_loops::fridge_queue.status->goal_angular_velocity)) /
+              (2.0 * new_fridge_goal->max_angular_acceleration);
+      angle = new_fridge_goal->angle;
+      new_fridge_goal->angular_velocity = 0.0;
+      new_fridge_goal->grabbers.top_front = top_grabbers;
+      new_fridge_goal->grabbers.top_back = top_grabbers;
+      new_fridge_goal->grabbers.bottom_front = front_grabbers;
+      new_fridge_goal->grabbers.bottom_back = back_grabbers;
+
+      if (!new_fridge_goal.Send()) {
+        LOG(ERROR, "Failed to send fridge goal\n");
+      }
+      return CANCELED;
+    }
+    control_loops::fridge_queue.status.FetchAnother();
+
+    constexpr double kProfileError = 1e-5;
+    constexpr double kAngleEpsilon = 0.02, kHeightEpsilon = 0.015;
+
+    if (control_loops::fridge_queue.status->state != 4) {
+      LOG(ERROR, "Fridge no longer running, aborting action\n");
+      return CANCELED;
+    }
+
+    if (::std::abs(control_loops::fridge_queue.status->goal_angle - angle) <
+            kProfileError &&
+        ::std::abs(control_loops::fridge_queue.status->goal_height - height) <
+            kProfileError &&
+        ::std::abs(control_loops::fridge_queue.status->goal_angular_velocity) <
+            kProfileError &&
+        ::std::abs(control_loops::fridge_queue.status->goal_velocity) <
+            kProfileError) {
+      LOG(INFO, "Profile done.\n");
+      if (::std::abs(control_loops::fridge_queue.status->angle - angle) <
+                     kAngleEpsilon &&
+                 ::std::abs(control_loops::fridge_queue.status->height -
+                            height) < kHeightEpsilon) {
+        LOG(INFO, "Near goal, done.\n");
+        return DONE;
+      }
+    }
+
+    return RUNNING;
+  }
+
+  void DoFridgeProfile(double height, double angle,
+                       ProfileParams elevator_parameters,
+                       ProfileParams arm_parameters, bool top_grabbers,
+                       bool front_grabbers, bool back_grabbers) {
+    if (!StartFridgeProfile(height, angle, elevator_parameters, arm_parameters,
+                            top_grabbers, front_grabbers, back_grabbers)) {
+      return;
+    }
+
+    while (true) {
+      ProfileStatus status =
+          IterateProfile(height, angle, elevator_parameters, arm_parameters,
+                         top_grabbers, front_grabbers, back_grabbers);
+      if (status == DONE || status == CANCELED) {
+        return;
+      }
+    }
+  }
+
+  void DoFridgeXYProfile(double x, double y, ProfileParams x_parameters,
+                         ProfileParams y_parameters, bool grabbers) {
+    DoFridgeXYProfile(x, y, x_parameters, y_parameters, grabbers, grabbers,
+                      grabbers);
+  }
+
+  void DoFridgeXYProfile(double x, double y, ProfileParams x_parameters,
+                         ProfileParams y_parameters, bool top_grabbers,
+                         bool front_grabbers, bool back_grabbers) {
+    if (!StartFridgeXYProfile(x, y, x_parameters, y_parameters, top_grabbers,
+                              front_grabbers, back_grabbers)) {
+      return;
+    }
+
+    while (true) {
+      ProfileStatus status =
+          IterateXYProfile(x, y, x_parameters, y_parameters, top_grabbers,
+                           front_grabbers, back_grabbers);
+      if (status == DONE || status == CANCELED) {
+        return;
+      }
+    }
+  }
+
+  void CancelXYMotion(ProfileParams x_parameters, ProfileParams y_parameters,
+                      bool top_grabbers, bool front_grabbers,
+                      bool back_grabbers) {
+    LOG(INFO, "Canceling fridge movement\n");
+    if (!control_loops::fridge_queue.status.get()) {
+      LOG(WARNING, "no fridge status so can't really cancel\n");
+      return;
+    }
+
+    auto new_fridge_goal = control_loops::fridge_queue.goal.MakeMessage();
+    new_fridge_goal->profiling_type = 1;
+    new_fridge_goal->max_x_velocity = x_parameters.velocity;
+    new_fridge_goal->max_x_acceleration = x_parameters.acceleration;
+    new_fridge_goal->x =
+        control_loops::fridge_queue.status->x +
+        (control_loops::fridge_queue.status->goal_x_velocity *
+         ::std::abs(control_loops::fridge_queue.status->goal_x_velocity)) /
+            (2.0 * new_fridge_goal->max_x_acceleration);
+    new_fridge_goal->x_velocity = 0.0;
+
+    new_fridge_goal->max_y_velocity = y_parameters.velocity;
+    new_fridge_goal->max_y_acceleration = y_parameters.acceleration;
+    new_fridge_goal->y =
+        control_loops::fridge_queue.status->y +
+        (control_loops::fridge_queue.status->goal_y_velocity *
+         ::std::abs(control_loops::fridge_queue.status->goal_y_velocity)) /
+            (2.0 * new_fridge_goal->max_y_acceleration);
+    new_fridge_goal->y_velocity = 0.0;
+
+    new_fridge_goal->grabbers.top_front = top_grabbers;
+    new_fridge_goal->grabbers.top_back = top_grabbers;
+    new_fridge_goal->grabbers.bottom_front = front_grabbers;
+    new_fridge_goal->grabbers.bottom_back = back_grabbers;
+
+    if (!new_fridge_goal.Send()) {
+      LOG(ERROR, "Failed to send fridge goal\n");
+    }
+  }
+
+  ProfileStatus IterateXYProfile(double x, double y, ProfileParams x_parameters,
+                                 ProfileParams y_parameters, bool top_grabbers,
+                                 bool front_grabbers, bool back_grabbers) {
+    if (this->ShouldCancel()) {
+      CancelXYMotion(x_parameters, y_parameters, top_grabbers, front_grabbers,
+                     back_grabbers);
+      return CANCELED;
+    }
+    control_loops::fridge_queue.status.FetchAnother();
+
+    constexpr double kProfileError = 1e-5;
+    constexpr double kXEpsilon = 0.02, kYEpsilon = 0.02;
+
+    if (control_loops::fridge_queue.status->state != 4) {
+      LOG(ERROR, "Fridge no longer running, aborting action\n");
+      return CANCELED;
+    }
+
+    if (::std::abs(control_loops::fridge_queue.status->goal_x - x) <
+            kProfileError &&
+        ::std::abs(control_loops::fridge_queue.status->goal_y - y) <
+            kProfileError &&
+        ::std::abs(control_loops::fridge_queue.status->goal_x_velocity) <
+            kProfileError &&
+        ::std::abs(control_loops::fridge_queue.status->goal_y_velocity) <
+            kProfileError) {
+      LOG(INFO, "Profile done.\n");
+      if (::std::abs(control_loops::fridge_queue.status->x - x) < kXEpsilon &&
+          ::std::abs(control_loops::fridge_queue.status->y - y) < kYEpsilon) {
+        LOG(INFO, "Near goal, done.\n");
+        return DONE;
+      }
+    }
+
+    return RUNNING;
+  }
+
+  bool StartFridgeXYProfile(double x, double y, ProfileParams x_parameters,
+                            ProfileParams y_parameters, bool top_grabbers,
+                            bool front_grabbers, bool back_grabbers) {
+    auto new_fridge_goal = control_loops::fridge_queue.goal.MakeMessage();
+    new_fridge_goal->profiling_type = 1;
+    new_fridge_goal->max_x_velocity = x_parameters.velocity;
+    new_fridge_goal->max_x_acceleration = x_parameters.acceleration;
+    new_fridge_goal->x = x;
+    new_fridge_goal->x_velocity = 0.0;
+
+    new_fridge_goal->max_y_velocity = y_parameters.velocity;
+    new_fridge_goal->max_y_acceleration = y_parameters.acceleration;
+    new_fridge_goal->y = y;
+    new_fridge_goal->y_velocity = 0.0;
+    new_fridge_goal->grabbers.top_front = top_grabbers;
+    new_fridge_goal->grabbers.top_back = top_grabbers;
+    new_fridge_goal->grabbers.bottom_front = front_grabbers;
+    new_fridge_goal->grabbers.bottom_back = back_grabbers;
+    LOG(INFO, "Starting xy profile to %f, %f\n", x, y);
+
+    if (!new_fridge_goal.Send()) {
+      LOG(ERROR, "Failed to send fridge goal\n");
+      return false;
+    }
+    return true;
+  }
+};
+
+}  // namespace actors
+}  // namespace frc971
+
+#endif  // Y2015_ACTORS_FRIDGE_PROFILE_LIB_H_
diff --git a/y2015/actors/held_to_lift_action.q b/y2015/actors/held_to_lift_action.q
new file mode 100644
index 0000000..c2dd689
--- /dev/null
+++ b/y2015/actors/held_to_lift_action.q
@@ -0,0 +1,36 @@
+package frc971.actors;
+
+import "aos/common/actions/actions.q";
+import "y2015/actors/lift_action_params.q";
+
+// Parameters to send with start.
+struct HeldToLiftParams {
+  // The maximum claw value to avoid collisions.
+  double claw_out_angle;
+
+  // The value to move the arm forwards to clear the stack when lowering.
+  double arm_clearance;
+  // End height.
+  double bottom_height;
+  // Amount to wait for the elevator to settle before lifting.
+  double before_lift_settle_time;
+  // Amount to wait to clamp.
+  double clamp_pause_time;
+
+  // Lift parameters
+  LiftParams lift_params;
+};
+
+queue_group HeldToLiftActionQueueGroup {
+  implements aos.common.actions.ActionQueueGroup;
+
+  message Goal {
+    uint32_t run;
+    HeldToLiftParams params;
+  };
+
+  queue Goal goal;
+  queue aos.common.actions.Status status;
+};
+
+queue_group HeldToLiftActionQueueGroup held_to_lift_action;
diff --git a/y2015/actors/held_to_lift_actor.cc b/y2015/actors/held_to_lift_actor.cc
new file mode 100644
index 0000000..2336364
--- /dev/null
+++ b/y2015/actors/held_to_lift_actor.cc
@@ -0,0 +1,114 @@
+#include "y2015/actors/held_to_lift_actor.h"
+
+#include <math.h>
+
+#include "aos/common/time.h"
+#include "y2015/constants.h"
+#include "y2015/actors/fridge_profile_lib.h"
+#include "y2015/actors/lift_actor.h"
+#include "y2015/control_loops/claw/claw.q.h"
+
+namespace frc971 {
+namespace actors {
+namespace {
+constexpr ProfileParams kArmMove{0.6, 2.0};
+constexpr ProfileParams kFastArmMove{1.2, 4.0};
+constexpr ProfileParams kElevatorMove{0.9, 3.0};
+constexpr ProfileParams kFastElevatorMove{1.2, 5.0};
+}  // namespace
+
+HeldToLiftActor::HeldToLiftActor(HeldToLiftActionQueueGroup *queues)
+    : FridgeActorBase<HeldToLiftActionQueueGroup>(queues) {}
+
+bool HeldToLiftActor::RunAction(const HeldToLiftParams &params) {
+  control_loops::fridge_queue.status.FetchLatest();
+  if (!control_loops::fridge_queue.status.get()) {
+    return false;
+  }
+
+  // Move claw out of the way.
+  {
+    bool send_goal = true;
+    double claw_goal = params.claw_out_angle;
+    control_loops::claw_queue.status.FetchLatest();
+    if (control_loops::claw_queue.status.get()) {
+      if (control_loops::claw_queue.status->goal_angle < claw_goal) {
+        send_goal = false;
+      }
+    }
+    if (send_goal) {
+      auto message = control_loops::claw_queue.goal.MakeMessage();
+      message->angle = params.claw_out_angle;
+      message->angular_velocity = 0.0;
+      message->intake = 0.0;
+      message->max_velocity = 6.0;
+      message->max_acceleration = 10.0;
+      message->rollers_closed = true;
+
+      LOG_STRUCT(DEBUG, "Sending claw goal", *message);
+      message.Send();
+    }
+  }
+
+  control_loops::fridge_queue.status.FetchLatest();
+  if (!control_loops::fridge_queue.status.get()) {
+    return false;
+  }
+
+  if (control_loops::fridge_queue.status->goal_height != params.bottom_height ||
+      control_loops::fridge_queue.status->goal_angle != 0.0) {
+    // Lower with the fridge clamps open and move it forwards slightly to clear.
+    DoFridgeProfile(control_loops::fridge_queue.status->goal_height,
+                    params.arm_clearance, kFastElevatorMove, kFastArmMove,
+                    false);
+    if (ShouldCancel()) return true;
+
+    DoFridgeProfile(params.bottom_height, params.arm_clearance,
+                    kFastElevatorMove, kFastArmMove, false);
+    if (ShouldCancel()) return true;
+
+    // Move it back to the storage location.
+    DoFridgeProfile(params.bottom_height, 0.0, kElevatorMove, kArmMove, false);
+    if (ShouldCancel()) return true;
+
+    if (!WaitOrCancel(
+            aos::time::Time::InSeconds(params.before_lift_settle_time))) {
+      return true;
+    }
+
+    // Clamp
+    DoFridgeProfile(params.bottom_height, 0.0, kElevatorMove, kArmMove, true);
+    if (ShouldCancel()) return true;
+
+    if (!WaitOrCancel(aos::time::Time::InSeconds(params.clamp_pause_time))) {
+      return true;
+    }
+  }
+
+  {
+    ::std::unique_ptr<LiftAction> lift_action =
+        MakeLiftAction(params.lift_params);
+    lift_action->Start();
+    while (lift_action->Running()) {
+      ::aos::time::PhasedLoopXMS(::aos::controls::kLoopFrequency.ToMSec(),
+                                 2500);
+
+      if (ShouldCancel()) {
+        lift_action->Cancel();
+        LOG(WARNING, "Cancelling fridge and claw.\n");
+        return true;
+      }
+    }
+  }
+
+  return true;
+}
+
+::std::unique_ptr<HeldToLiftAction> MakeHeldToLiftAction(
+    const HeldToLiftParams &params) {
+  return ::std::unique_ptr<HeldToLiftAction>(
+      new HeldToLiftAction(&::frc971::actors::held_to_lift_action, params));
+}
+
+}  // namespace actors
+}  // namespace frc971
diff --git a/y2015/actors/held_to_lift_actor.h b/y2015/actors/held_to_lift_actor.h
new file mode 100644
index 0000000..369fea4
--- /dev/null
+++ b/y2015/actors/held_to_lift_actor.h
@@ -0,0 +1,33 @@
+#ifndef Y2015_ACTORS_HELD_TO_LIFT_ACTOR_H_
+#define Y2015_ACTORS_HELD_TO_LIFT_ACTOR_H_
+
+#include <stdint.h>
+
+#include <memory>
+
+#include "aos/common/actions/actions.h"
+#include "aos/common/actions/actor.h"
+#include "y2015/actors/held_to_lift_action.q.h"
+#include "y2015/actors/fridge_profile_lib.h"
+
+namespace frc971 {
+namespace actors {
+
+class HeldToLiftActor : public FridgeActorBase<HeldToLiftActionQueueGroup> {
+ public:
+  explicit HeldToLiftActor(HeldToLiftActionQueueGroup *queues);
+
+  bool RunAction(const HeldToLiftParams &params) override;
+};
+
+typedef aos::common::actions::TypedAction<HeldToLiftActionQueueGroup>
+    HeldToLiftAction;
+
+// Makes a new HeldToLiftActor action.
+::std::unique_ptr<HeldToLiftAction> MakeHeldToLiftAction(
+    const HeldToLiftParams &params);
+
+}  // namespace actors
+}  // namespace frc971
+
+#endif  // Y2015_ACTORS_HELD_TO_LIFT_ACTOR_H_
diff --git a/y2015/actors/held_to_lift_actor_main.cc b/y2015/actors/held_to_lift_actor_main.cc
new file mode 100644
index 0000000..a5d78e1
--- /dev/null
+++ b/y2015/actors/held_to_lift_actor_main.cc
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+#include "aos/linux_code/init.h"
+#include "y2015/actors/held_to_lift_action.q.h"
+#include "y2015/actors/held_to_lift_actor.h"
+
+int main(int /*argc*/, char* /*argv*/ []) {
+  ::aos::Init();
+
+  ::frc971::actors::HeldToLiftActor lift(
+      &::frc971::actors::held_to_lift_action);
+  lift.Run();
+
+  ::aos::Cleanup();
+  return 0;
+}
diff --git a/y2015/actors/horizontal_can_pickup_action.q b/y2015/actors/horizontal_can_pickup_action.q
new file mode 100644
index 0000000..c1a1c55
--- /dev/null
+++ b/y2015/actors/horizontal_can_pickup_action.q
@@ -0,0 +1,48 @@
+package frc971.actors;
+
+import "aos/common/actions/actions.q";
+
+// Parameters to send with start.
+// This action picks a horizontal can from the claw.
+struct HorizontalCanPickupParams {
+  // Elevator catch height.
+  double elevator_height;
+  // Angle to move the claw to when placing the base of the can on the robot.
+  double pickup_angle;
+
+  // Time and power to spit the can out before lifting.
+  double spit_time;
+  double spit_power;
+
+  // Time and power to pull the can in when lifted.
+  double suck_time;
+  double suck_power;
+
+  // Time to push down and suck in to slide the claw down on the can.
+  double claw_settle_time;
+  double claw_settle_power;
+
+  // Angle to lift the claw to to lift the can.
+  double claw_full_lift_angle;
+
+  // Angle to move the claw back down to.
+  double claw_end_angle;
+
+  // The end arm and elevator position once we are done lifting.
+  double elevator_end_height;
+  double arm_end_angle;
+};
+
+queue_group HorizontalCanPickupActionQueueGroup {
+  implements aos.common.actions.ActionQueueGroup;
+
+  message Goal {
+    uint32_t run;
+    HorizontalCanPickupParams params;
+  };
+
+  queue Goal goal;
+  queue aos.common.actions.Status status;
+};
+
+queue_group HorizontalCanPickupActionQueueGroup horizontal_can_pickup_action;
diff --git a/y2015/actors/horizontal_can_pickup_actor.cc b/y2015/actors/horizontal_can_pickup_actor.cc
new file mode 100644
index 0000000..fb6e542
--- /dev/null
+++ b/y2015/actors/horizontal_can_pickup_actor.cc
@@ -0,0 +1,161 @@
+#include <math.h>
+
+#include "aos/common/controls/control_loop.h"
+#include "aos/common/time.h"
+#include "aos/common/util/phased_loop.h"
+
+#include "y2015/actors/horizontal_can_pickup_actor.h"
+#include "y2015/actors/fridge_profile_lib.h"
+#include "y2015/constants.h"
+#include "y2015/control_loops/claw/claw.q.h"
+
+namespace frc971 {
+namespace actors {
+namespace {
+constexpr ProfileParams kClawPickup{3.0, 2.0};
+constexpr ProfileParams kClawBackDown{7.0, 10.0};
+constexpr ProfileParams kClawInitialLift{7.0, 8.0};
+
+constexpr ProfileParams kArmMove{1.0, 1.6};
+constexpr ProfileParams kElevatorMove{0.6, 2.2};
+
+constexpr ProfileParams kFastArmMove{2.0, 3.0};
+constexpr ProfileParams kFastElevatorMove{1.0, 3.0};
+
+constexpr double kAngleEpsilon = 0.10;
+constexpr double kGoalAngleEpsilon = 0.01;
+
+}  // namespace
+
+HorizontalCanPickupActor::HorizontalCanPickupActor(
+    HorizontalCanPickupActionQueueGroup *queues)
+    : FridgeActorBase<HorizontalCanPickupActionQueueGroup>(queues) {}
+
+bool HorizontalCanPickupActor::WaitUntilGoalNear(double angle) {
+  while (true) {
+    control_loops::claw_queue.status.FetchAnother();
+    if (ShouldCancel()) return false;
+    const double goal_angle = control_loops::claw_queue.status->goal_angle;
+    LOG_STRUCT(DEBUG, "Got claw status", *control_loops::claw_queue.status);
+
+    if (::std::abs(goal_angle - angle) < kGoalAngleEpsilon) {
+      return true;
+    }
+  }
+}
+
+bool HorizontalCanPickupActor::WaitUntilNear(double angle) {
+  while (true) {
+    control_loops::claw_queue.status.FetchAnother();
+    if (ShouldCancel()) return false;
+    const double current_angle = control_loops::claw_queue.status->angle;
+    LOG_STRUCT(DEBUG, "Got claw status", *control_loops::claw_queue.status);
+
+    if (::std::abs(current_angle - angle) < kAngleEpsilon) {
+      return true;
+    }
+  }
+}
+void HorizontalCanPickupActor::MoveArm(double angle, double intake_power) {
+  MoveArm(angle, intake_power, kClawPickup);
+}
+
+void HorizontalCanPickupActor::MoveArm(double angle, double intake_power,
+                                       const ProfileParams profile_params) {
+  auto message = control_loops::claw_queue.goal.MakeMessage();
+  message->angle = angle;
+  message->max_velocity = profile_params.velocity;
+  message->max_acceleration = profile_params.acceleration;
+  message->angular_velocity = 0.0;
+  message->intake = intake_power;
+  message->rollers_closed = true;
+
+  LOG_STRUCT(DEBUG, "Sending claw goal", *message);
+  message.Send();
+}
+
+bool HorizontalCanPickupActor::RunAction(
+    const HorizontalCanPickupParams &params) {
+  // Go around the can.
+  if (!StartFridgeProfile(params.elevator_height, 0.0, kFastElevatorMove,
+                          kFastArmMove, false, false, true)) {
+    return true;
+  }
+
+  control_loops::claw_queue.status.FetchAnother();
+
+  MoveArm(control_loops::claw_queue.status->angle, params.spit_power);
+
+  if (!WaitOrCancel(aos::time::Time::InSeconds(params.spit_time))) {
+    return true;
+  }
+
+  MoveArm(params.pickup_angle, 0.0, kClawInitialLift);
+
+  if (!WaitUntilNear(params.pickup_angle)) {
+    return true;
+  }
+
+  MoveArm(params.pickup_angle, params.suck_power);
+
+  if (!WaitOrCancel(aos::time::Time::InSeconds(params.suck_time))) {
+    return true;
+  }
+
+  MoveArm(0.0, 0.0, kClawBackDown);
+
+  if (!WaitUntilGoalNear(0.0)) {
+    return true;
+  }
+
+  MoveArm(0.0, params.claw_settle_power);
+
+  if (!WaitOrCancel(aos::time::Time::InSeconds(params.claw_settle_time))) {
+    return true;
+  }
+
+  while (true) {
+    ProfileStatus status =
+        IterateProfile(params.elevator_height, 0.0, kFastElevatorMove,
+                       kFastArmMove, false, false, true);
+    if (status == DONE) {
+      break;
+    } else if (status == CANCELED) {
+      return true;
+    }
+  }
+
+  MoveArm(params.claw_full_lift_angle, 0.0);
+
+  if (!WaitUntilNear(params.claw_full_lift_angle)) {
+    return true;
+  }
+
+  DoFridgeProfile(params.elevator_height, 0.0, kElevatorMove, kArmMove, false,
+                  true, true);
+  if (ShouldCancel()) return true;
+
+  MoveArm(params.claw_end_angle, 7.0);
+
+  if (!WaitUntilNear(params.claw_end_angle)) {
+    return true;
+  }
+  MoveArm(params.claw_end_angle, 0.0);
+
+  if (ShouldCancel()) return true;
+
+  DoFridgeProfile(params.elevator_end_height, params.arm_end_angle,
+                  kElevatorMove, kArmMove, false, true, true);
+
+  return true;
+}
+
+::std::unique_ptr<HorizontalCanPickupAction> MakeHorizontalCanPickupAction(
+    const HorizontalCanPickupParams &params) {
+  return ::std::unique_ptr<HorizontalCanPickupAction>(
+      new HorizontalCanPickupAction(
+          &::frc971::actors::horizontal_can_pickup_action, params));
+}
+
+}  // namespace actors
+}  // namespace frc971
diff --git a/y2015/actors/horizontal_can_pickup_actor.h b/y2015/actors/horizontal_can_pickup_actor.h
new file mode 100644
index 0000000..5510178
--- /dev/null
+++ b/y2015/actors/horizontal_can_pickup_actor.h
@@ -0,0 +1,45 @@
+#ifndef Y2015_ACTORS_HORIZONTAL_CAN_PICKUP_ACTOR_H_
+#define Y2015_ACTORS_HORIZONTAL_CAN_PICKUP_ACTOR_H_
+
+#include <stdint.h>
+
+#include <memory>
+
+#include "aos/common/actions/actions.h"
+#include "aos/common/actions/actor.h"
+#include "y2015/actors/horizontal_can_pickup_action.q.h"
+#include "y2015/actors/fridge_profile_lib.h"
+
+namespace frc971 {
+namespace actors {
+
+class HorizontalCanPickupActor
+    : public FridgeActorBase<HorizontalCanPickupActionQueueGroup> {
+ public:
+  explicit HorizontalCanPickupActor(
+      HorizontalCanPickupActionQueueGroup *queues);
+
+  bool RunAction(const HorizontalCanPickupParams &params) override;
+
+ private:
+  // Waits until we are near the angle.
+  // Returns false if we should cancel.
+  bool WaitUntilNear(double angle);
+  bool WaitUntilGoalNear(double angle);
+
+  void MoveArm(double angle, double intake_power);
+  void MoveArm(double angle, double intake_power,
+               const ProfileParams profile_params);
+};
+
+typedef aos::common::actions::TypedAction<HorizontalCanPickupActionQueueGroup>
+    HorizontalCanPickupAction;
+
+// Makes a new HorizontalCanPickupActor action.
+::std::unique_ptr<HorizontalCanPickupAction> MakeHorizontalCanPickupAction(
+    const HorizontalCanPickupParams &params);
+
+}  // namespace actors
+}  // namespace frc971
+
+#endif  // Y2015_ACTORS_HORIZONTAL_CAN_PICKUP_ACTOR_H_
diff --git a/y2015/actors/horizontal_can_pickup_actor_main.cc b/y2015/actors/horizontal_can_pickup_actor_main.cc
new file mode 100644
index 0000000..67f986c
--- /dev/null
+++ b/y2015/actors/horizontal_can_pickup_actor_main.cc
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+#include "aos/linux_code/init.h"
+#include "y2015/actors/horizontal_can_pickup_action.q.h"
+#include "y2015/actors/horizontal_can_pickup_actor.h"
+
+int main(int /*argc*/, char* /*argv*/ []) {
+  ::aos::Init();
+
+  ::frc971::actors::HorizontalCanPickupActor horizontal_can_pickup(
+      &::frc971::actors::horizontal_can_pickup_action);
+  horizontal_can_pickup.Run();
+
+  ::aos::Cleanup();
+  return 0;
+}
diff --git a/y2015/actors/lift_action.q b/y2015/actors/lift_action.q
new file mode 100644
index 0000000..37fba8d
--- /dev/null
+++ b/y2015/actors/lift_action.q
@@ -0,0 +1,18 @@
+package frc971.actors;
+
+import "aos/common/actions/actions.q";
+import "y2015/actors/lift_action_params.q";
+
+queue_group LiftActionQueueGroup {
+  implements aos.common.actions.ActionQueueGroup;
+
+  message Goal {
+    uint32_t run;
+    LiftParams params;
+  };
+
+  queue Goal goal;
+  queue aos.common.actions.Status status;
+};
+
+queue_group LiftActionQueueGroup lift_action;
diff --git a/y2015/actors/lift_action_params.q b/y2015/actors/lift_action_params.q
new file mode 100644
index 0000000..b31982b
--- /dev/null
+++ b/y2015/actors/lift_action_params.q
@@ -0,0 +1,19 @@
+package frc971.actors;
+
+// Parameters to send with start.
+struct LiftParams {
+  // Lift height
+  double lift_height;
+  // Arm goal.
+  double lift_arm;
+
+  // If true, do the second lift.
+  bool second_lift;
+  // Arm goal.
+  double intermediate_lift_height;
+
+  // True to move the claw in the middle of the lift.
+  bool pack_claw;
+  // Iff pack_claw is true, the angle to move the claw to.
+  double pack_claw_angle;
+};
diff --git a/y2015/actors/lift_actor.cc b/y2015/actors/lift_actor.cc
new file mode 100644
index 0000000..c057eef
--- /dev/null
+++ b/y2015/actors/lift_actor.cc
@@ -0,0 +1,92 @@
+#include <math.h>
+
+#include "aos/common/time.h"
+#include "y2015/actors/lift_actor.h"
+#include "y2015/constants.h"
+#include "y2015/actors/fridge_profile_lib.h"
+#include "y2015/control_loops/claw/claw.q.h"
+
+namespace frc971 {
+namespace actors {
+namespace {
+constexpr ProfileParams kArmMove{0.6, 1.0};
+constexpr ProfileParams kElevatorMove{0.9, 3.0};
+constexpr ProfileParams kElevatorFixMove{0.9, 2.0};
+}  // namespace
+
+LiftActor::LiftActor(LiftActionQueueGroup *queues)
+    : FridgeActorBase<LiftActionQueueGroup>(queues) {}
+
+bool LiftActor::RunAction(const LiftParams &params) {
+  control_loops::fridge_queue.status.FetchLatest();
+  if (!control_loops::fridge_queue.status.get()) {
+    return false;
+  }
+
+  double goal_height = params.lift_height;
+  double goal_angle = 0.0;
+
+  if (params.second_lift) {
+    DoFridgeProfile(params.intermediate_lift_height, 0.0, kElevatorFixMove,
+                    kArmMove,
+                    control_loops::fridge_queue.status->grabbers.top_front,
+                    control_loops::fridge_queue.status->grabbers.bottom_front,
+                    control_loops::fridge_queue.status->grabbers.bottom_back);
+    if (ShouldCancel()) return true;
+  }
+
+  if (!StartFridgeProfile(
+          params.lift_height, 0.0, kElevatorMove, kArmMove,
+          control_loops::fridge_queue.status->grabbers.top_front,
+          control_loops::fridge_queue.status->grabbers.bottom_front,
+          control_loops::fridge_queue.status->grabbers.bottom_back)) {
+    return true;
+  }
+
+  bool has_started_back = false;
+  while (true) {
+    if (control_loops::fridge_queue.status->goal_height > 0.1) {
+      if (!has_started_back) {
+        if (!StartFridgeProfile(
+                params.lift_height, params.lift_arm, kElevatorMove, kArmMove,
+                control_loops::fridge_queue.status->grabbers.top_front,
+                control_loops::fridge_queue.status->grabbers.bottom_front,
+                control_loops::fridge_queue.status->grabbers.bottom_back)) {
+          return true;
+        }
+        goal_angle = params.lift_arm;
+        has_started_back = true;
+        if (params.pack_claw) {
+          auto message = control_loops::claw_queue.goal.MakeMessage();
+          message->angle = params.pack_claw_angle;
+          message->angular_velocity = 0.0;
+          message->intake = 0.0;
+          message->rollers_closed = true;
+          message->max_velocity = 6.0;
+          message->max_acceleration = 10.0;
+
+          LOG_STRUCT(DEBUG, "Sending claw goal", *message);
+          message.Send();
+        }
+      }
+    }
+
+    ProfileStatus status = IterateProfile(
+        goal_height, goal_angle, kElevatorMove, kArmMove,
+        control_loops::fridge_queue.status->grabbers.top_front,
+        control_loops::fridge_queue.status->grabbers.bottom_front,
+        control_loops::fridge_queue.status->grabbers.bottom_back);
+    if (status == DONE || status == CANCELED) {
+      return true;
+    }
+  }
+  return true;
+}
+
+::std::unique_ptr<LiftAction> MakeLiftAction(const LiftParams &params) {
+  return ::std::unique_ptr<LiftAction>(
+      new LiftAction(&::frc971::actors::lift_action, params));
+}
+
+}  // namespace actors
+}  // namespace frc971
diff --git a/y2015/actors/lift_actor.h b/y2015/actors/lift_actor.h
new file mode 100644
index 0000000..cbd79ec
--- /dev/null
+++ b/y2015/actors/lift_actor.h
@@ -0,0 +1,31 @@
+#ifndef Y2015_ACTORS_LIFT_ACTOR_H_
+#define Y2015_ACTORS_LIFT_ACTOR_H_
+
+#include <stdint.h>
+
+#include <memory>
+
+#include "aos/common/actions/actions.h"
+#include "aos/common/actions/actor.h"
+#include "y2015/actors/lift_action.q.h"
+#include "y2015/actors/fridge_profile_lib.h"
+
+namespace frc971 {
+namespace actors {
+
+class LiftActor : public FridgeActorBase<LiftActionQueueGroup> {
+ public:
+  explicit LiftActor(LiftActionQueueGroup *queues);
+
+  bool RunAction(const LiftParams &params) override;
+};
+
+typedef aos::common::actions::TypedAction<LiftActionQueueGroup> LiftAction;
+
+// Makes a new LiftActor action.
+::std::unique_ptr<LiftAction> MakeLiftAction(const LiftParams &params);
+
+}  // namespace actors
+}  // namespace frc971
+
+#endif  // Y2015_ACTORS_LIFT_ACTOR_H_
diff --git a/y2015/actors/lift_actor_main.cc b/y2015/actors/lift_actor_main.cc
new file mode 100644
index 0000000..ed809ef
--- /dev/null
+++ b/y2015/actors/lift_actor_main.cc
@@ -0,0 +1,15 @@
+#include <stdio.h>
+
+#include "aos/linux_code/init.h"
+#include "y2015/actors/lift_action.q.h"
+#include "y2015/actors/lift_actor.h"
+
+int main(int /*argc*/, char* /*argv*/ []) {
+  ::aos::Init();
+
+  ::frc971::actors::LiftActor lift(&::frc971::actors::lift_action);
+  lift.Run();
+
+  ::aos::Cleanup();
+  return 0;
+}
diff --git a/y2015/actors/pickup_action.q b/y2015/actors/pickup_action.q
new file mode 100644
index 0000000..237337a
--- /dev/null
+++ b/y2015/actors/pickup_action.q
@@ -0,0 +1,33 @@
+package frc971.actors;
+
+import "aos/common/actions/actions.q";
+
+// Parameters to send with start.
+struct PickupParams {
+  // Angle to pull in at the top.
+  double pickup_angle;
+  // Angle to start sucking in above.
+  double suck_angle;
+  // Angle to finish sucking at.
+  double suck_angle_finish;
+  // Angle to go to once we get to the top to finish pulling in.
+  double pickup_finish_angle;
+  // Power to pull the bin in at the top.
+  double intake_voltage;
+  // Time to pull the bin in for.
+  double intake_time;
+};
+
+queue_group PickupActionQueueGroup {
+  implements aos.common.actions.ActionQueueGroup;
+
+  message Goal {
+    uint32_t run;
+    PickupParams params;
+  };
+
+  queue Goal goal;
+  queue aos.common.actions.Status status;
+};
+
+queue_group PickupActionQueueGroup pickup_action;
diff --git a/y2015/actors/pickup_actor.cc b/y2015/actors/pickup_actor.cc
new file mode 100644
index 0000000..0863ba6
--- /dev/null
+++ b/y2015/actors/pickup_actor.cc
@@ -0,0 +1,149 @@
+#include "y2015/actors/pickup_actor.h"
+
+#include <cmath>
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/controls/control_loop.h"
+#include "aos/common/util/phased_loop.h"
+#include "aos/common/time.h"
+#include "y2015/control_loops/claw/claw.q.h"
+
+namespace frc971 {
+namespace actors {
+namespace {
+constexpr double kClawPickupVelocity = 3.00;
+constexpr double kClawPickupAcceleration = 3.5;
+constexpr double kClawMoveDownVelocity = 7.00;
+constexpr double kClawMoveDownAcceleration = 15.0;
+constexpr double kClawMoveUpVelocity = 8.0;
+constexpr double kClawMoveUpAcceleration = 25.0;
+}  // namespace
+
+PickupActor::PickupActor(PickupActionQueueGroup* queues)
+    : aos::common::actions::ActorBase<PickupActionQueueGroup>(queues) {}
+
+bool PickupActor::RunAction(const PickupParams& params) {
+  constexpr double kAngleEpsilon = 0.10;
+  // Start lifting the tote.
+  {
+    auto message = control_loops::claw_queue.goal.MakeMessage();
+    message->angle = params.pickup_angle;
+    message->max_velocity = kClawPickupVelocity;
+    message->max_acceleration = kClawPickupAcceleration;
+    message->angular_velocity = 0.0;
+    message->intake = 0.0;
+    message->rollers_closed = true;
+
+    LOG_STRUCT(DEBUG, "Sending claw goal", *message);
+    message.Send();
+  }
+  while (true) {
+    control_loops::claw_queue.status.FetchAnother();
+    if (ShouldCancel()) return true;
+    const double current_angle = control_loops::claw_queue.status->angle;
+    LOG_STRUCT(DEBUG, "Got claw status", *control_loops::claw_queue.status);
+
+    if (current_angle > params.suck_angle ||
+        ::std::abs(current_angle - params.pickup_angle) < kAngleEpsilon) {
+      break;
+    }
+  }
+
+  // Once above params.suck_angle, start sucking while lifting.
+  {
+    auto message = control_loops::claw_queue.goal.MakeMessage();
+    message->angle = params.pickup_angle;
+    message->max_velocity = kClawPickupVelocity;
+    message->max_acceleration = kClawPickupAcceleration;
+    message->angular_velocity = 0.0;
+    message->intake = params.intake_voltage;
+    message->rollers_closed = true;
+
+    LOG_STRUCT(DEBUG, "Sending claw goal", *message);
+    message.Send();
+  }
+
+  while (true) {
+    control_loops::claw_queue.status.FetchAnother();
+    if (ShouldCancel()) return true;
+    const double current_angle = control_loops::claw_queue.status->angle;
+    LOG_STRUCT(DEBUG, "Got claw status", *control_loops::claw_queue.status);
+
+    if (::std::abs(current_angle - params.pickup_angle) < kAngleEpsilon) {
+      break;
+    }
+  }
+
+  // Now that we have reached the upper height, come back down while intaking.
+  {
+    auto message = control_loops::claw_queue.goal.MakeMessage();
+    message->angle = params.suck_angle_finish;
+    message->max_velocity = kClawMoveDownVelocity;
+    message->max_acceleration = kClawMoveDownAcceleration;
+    message->angular_velocity = 0.0;
+    message->intake = params.intake_voltage;
+    message->rollers_closed = true;
+
+    LOG_STRUCT(DEBUG, "Sending claw goal", *message);
+    message.Send();
+  }
+
+  // Pull in for params.intake_time.
+  ::aos::time::Time end_time =
+      ::aos::time::Time::Now() + aos::time::Time::InSeconds(params.intake_time);
+  while ( ::aos::time::Time::Now() <= end_time) {
+    ::aos::time::PhasedLoopXMS(::aos::controls::kLoopFrequency.ToMSec(), 2500);
+    if (ShouldCancel()) return true;
+  }
+
+  // Lift the claw back up to pack the box back in.
+  {
+    auto message = control_loops::claw_queue.goal.MakeMessage();
+    message->angle = params.pickup_finish_angle;
+    message->max_velocity = kClawMoveUpVelocity;
+    message->max_acceleration = kClawMoveUpAcceleration;
+    message->angular_velocity = 0.0;
+    message->intake = params.intake_voltage;
+    message->rollers_closed = true;
+
+    LOG_STRUCT(DEBUG, "Sending claw goal", *message);
+    message.Send();
+  }
+
+  while (true) {
+    control_loops::claw_queue.status.FetchAnother();
+    if (ShouldCancel()) return true;
+    const double current_angle = control_loops::claw_queue.status->angle;
+    LOG_STRUCT(DEBUG, "Got claw status", *control_loops::claw_queue.status);
+
+    if (::std::abs(current_angle - params.pickup_finish_angle) <
+        kAngleEpsilon) {
+      break;
+    }
+  }
+
+  // Stop the motors...
+  {
+    auto message = control_loops::claw_queue.goal.MakeMessage();
+    message->angle = params.pickup_finish_angle;
+    message->max_velocity = kClawMoveUpVelocity;
+    message->max_acceleration = kClawMoveUpAcceleration;
+    message->angular_velocity = 0.0;
+    message->intake = 0.0;
+    message->rollers_closed = true;
+
+    LOG_STRUCT(DEBUG, "Sending claw goal", *message);
+    message.Send();
+  }
+
+
+  return true;
+}
+
+::std::unique_ptr<PickupAction> MakePickupAction(const PickupParams& params) {
+  return ::std::unique_ptr<PickupAction>(
+      new PickupAction(&::frc971::actors::pickup_action, params));
+}
+
+}  // namespace actors
+}  // namespace frc971
diff --git a/y2015/actors/pickup_actor.h b/y2015/actors/pickup_actor.h
new file mode 100644
index 0000000..1f09718
--- /dev/null
+++ b/y2015/actors/pickup_actor.h
@@ -0,0 +1,27 @@
+#ifndef Y2015_ACTORS_PICKUP_ACTOR_H_
+#define Y2015_ACTORS_PICKUP_ACTOR_H_
+
+#include "aos/common/actions/actions.h"
+#include "aos/common/actions/actor.h"
+#include "y2015/actors/pickup_action.q.h"
+
+namespace frc971 {
+namespace actors {
+
+class PickupActor
+    : public aos::common::actions::ActorBase<PickupActionQueueGroup> {
+ public:
+  explicit PickupActor(PickupActionQueueGroup *queues);
+
+  bool RunAction(const PickupParams &params) override;
+};
+
+typedef aos::common::actions::TypedAction<PickupActionQueueGroup> PickupAction;
+
+// Makes a new PickupActor action.
+::std::unique_ptr<PickupAction> MakePickupAction(const PickupParams &params);
+
+}  // namespace actors
+}  // namespace frc971
+
+#endif  // Y2015_ACTORS_PICKUP_ACTOR_H_
diff --git a/y2015/actors/pickup_actor_main.cc b/y2015/actors/pickup_actor_main.cc
new file mode 100644
index 0000000..9c2c488
--- /dev/null
+++ b/y2015/actors/pickup_actor_main.cc
@@ -0,0 +1,15 @@
+#include <stdio.h>
+
+#include "aos/linux_code/init.h"
+#include "y2015/actors/pickup_action.q.h"
+#include "y2015/actors/pickup_actor.h"
+
+int main(int /*argc*/, char* /*argv*/ []) {
+  ::aos::Init();
+
+  frc971::actors::PickupActor pickup(&::frc971::actors::pickup_action);
+  pickup.Run();
+
+  ::aos::Cleanup();
+  return 0;
+}
diff --git a/y2015/actors/score_action.q b/y2015/actors/score_action.q
new file mode 100644
index 0000000..5b14210
--- /dev/null
+++ b/y2015/actors/score_action.q
@@ -0,0 +1,34 @@
+package frc971.actors;
+
+import "aos/common/actions/actions.q";
+
+// Parameters to send with start.
+struct ScoreParams {
+  // If true, move the stack first.
+  bool move_the_stack;
+  // If true, place the stack (possibly after moving it).
+  bool place_the_stack;
+
+  // TODO(Brian): Comments (by somebody who knows what these all mean).
+  double upper_move_height;
+  double begin_horizontal_move_height;
+  double horizontal_move_target;
+  double horizontal_start_lowering;
+  double place_height;
+  double home_lift_horizontal_start_position;
+  double home_return_height;
+};
+
+queue_group ScoreActionQueueGroup {
+  implements aos.common.actions.ActionQueueGroup;
+
+  message Goal {
+    uint32_t run;
+    ScoreParams params;
+  };
+
+  queue Goal goal;
+  queue aos.common.actions.Status status;
+};
+
+queue_group ScoreActionQueueGroup score_action;
diff --git a/y2015/actors/score_actor.cc b/y2015/actors/score_actor.cc
new file mode 100644
index 0000000..c0a398f
--- /dev/null
+++ b/y2015/actors/score_actor.cc
@@ -0,0 +1,296 @@
+#include "y2015/actors/score_actor.h"
+
+#include <cmath>
+
+#include "aos/common/controls/control_loop.h"
+#include "aos/common/logging/logging.h"
+#include "aos/common/util/phased_loop.h"
+#include "aos/common/logging/queue_logging.h"
+
+#include "y2015/constants.h"
+#include "y2015/control_loops/fridge/fridge.q.h"
+
+using ::frc971::control_loops::fridge_queue;
+
+namespace frc971 {
+namespace actors {
+namespace {
+
+const double kSlowMaxXVelocity = 0.80;
+const double kSlowMaxYVelocity = 0.40;
+const double kFastMaxXVelocity = 0.80;
+const double kFastMaxYVelocity = 0.30;
+const double kReallyFastMaxXVelocity = 1.0;
+const double kReallyFastMaxYVelocity = 0.6;
+
+const double kMaxXAcceleration = 0.5;
+const double kMaxYAcceleration = 0.7;
+const double kLiftYAcceleration = 2.0;
+const double kLowerYAcceleration = 2.0;
+const double kFastMaxXAcceleration = 1.5;
+const double kFastMaxYAcceleration = 1.5;
+const double kSlowMaxXAcceleration = 0.3;
+const double kSlowMaxYAcceleration = 0.5;
+
+}  // namespace
+
+ScoreActor::ScoreActor(ScoreActionQueueGroup* queues)
+    : aos::common::actions::ActorBase<ScoreActionQueueGroup>(queues),
+      kinematics_(constants::GetValues().fridge.arm_length,
+                  constants::GetValues().fridge.elevator.upper_limit,
+                  constants::GetValues().fridge.elevator.lower_limit,
+                  constants::GetValues().fridge.arm.upper_limit,
+                  constants::GetValues().fridge.arm.lower_limit) {}
+
+bool ScoreActor::RunAction(const ScoreParams& params) {
+  if (params.move_the_stack) {
+    LOG(INFO, "moving stack\n");
+    if (!MoveStackIntoPosition(params)) return false;
+    LOG(INFO, "done moving stack\n");
+    if (ShouldCancel()) return true;
+  }
+  if (params.place_the_stack) {
+    LOG(INFO, "placing stack\n");
+    if (!PlaceTheStack(params)) return false;
+    LOG(INFO, "done placing stack\n");
+    if (ShouldCancel()) return true;
+  }
+  return true;
+}
+
+bool ScoreActor::MoveStackIntoPosition(const ScoreParams& params) {
+  // Move the fridge up a little bit.
+  if (!SendGoal(0.0, params.upper_move_height, true, kSlowMaxXVelocity,
+                kSlowMaxYVelocity, kMaxXAcceleration, kLiftYAcceleration)) {
+    LOG(ERROR, "Sending fridge message failed.\n");
+    return false;
+  }
+
+  while (true) {
+    ::aos::time::PhasedLoopXMS(::aos::controls::kLoopFrequency.ToMSec(), 2500);
+    if (ShouldCancel()) {
+      return true;
+    }
+
+    // Move on when it is clear of the tote knobs.
+    if (CurrentGoalHeight() > params.begin_horizontal_move_height) {
+      LOG(INFO, "moving on to horizontal move\n");
+      break;
+    }
+  }
+
+  // Move the fridge out.
+  if (!SendGoal(params.horizontal_move_target,
+                params.begin_horizontal_move_height, true, kSlowMaxXVelocity,
+                kFastMaxYVelocity, kSlowMaxXAcceleration,
+                kSlowMaxYAcceleration)) {
+    LOG(ERROR, "Sending fridge message failed.\n");
+    return false;
+  }
+
+  bool started_lowering = false;
+
+  while (true) {
+    ::aos::time::PhasedLoopXMS(::aos::controls::kLoopFrequency.ToMSec(), 2500);
+    if (ShouldCancel()) {
+      return true;
+    }
+    // Round the moving out corner and start setting down.
+    if (params.place_the_stack && !started_lowering) {
+      if (CurrentGoalX() < params.horizontal_start_lowering) {
+        if (!SendGoal(params.horizontal_move_target, params.place_height, true,
+                      kSlowMaxXVelocity, kFastMaxYVelocity,
+                      kSlowMaxXAcceleration, kMaxYAcceleration)) {
+          LOG(ERROR, "Sending fridge message failed.\n");
+          return false;
+        }
+        started_lowering = true;
+      }
+    }
+
+    if (NearHorizontalGoal(params.horizontal_move_target)) {
+      LOG(INFO, "reached goal\n");
+      break;
+    }
+  }
+
+  if (ShouldCancel()) return true;
+
+  return true;
+}
+
+bool ScoreActor::PlaceTheStack(const ScoreParams& params) {
+  // Once the fridge is way out, put it on the ground.
+  if (!SendGoal(params.horizontal_move_target, params.place_height, true,
+                kFastMaxXVelocity, kFastMaxYVelocity, kMaxXAcceleration,
+                kLowerYAcceleration)) {
+    LOG(ERROR, "Sending fridge message failed.\n");
+    return false;
+  }
+
+  while (true) {
+    ::aos::time::PhasedLoopXMS(::aos::controls::kLoopFrequency.ToMSec(), 2500);
+    if (ShouldCancel()) {
+      return true;
+    }
+
+    if (NearGoal(params.horizontal_move_target, params.place_height)) {
+      break;
+    }
+  }
+
+  // Release and give the grabers a chance to get out of the way.
+  if (!SendGoal(params.horizontal_move_target, params.place_height, false,
+                kFastMaxXVelocity, kFastMaxYVelocity, kMaxXAcceleration,
+                kLowerYAcceleration)) {
+    LOG(ERROR, "Sending fridge message failed.\n");
+    return false;
+  }
+  if (!WaitOrCancel(::aos::time::Time::InSeconds(0.1))) return true;
+
+  // Go back to the home position.
+  if (!SendGoal(0.0, params.place_height, false, kReallyFastMaxXVelocity,
+                kReallyFastMaxYVelocity, kFastMaxXAcceleration,
+                kFastMaxYAcceleration)) {
+    LOG(ERROR, "Sending fridge message failed.\n");
+    return false;
+  }
+
+  bool has_lifted = false;
+  while (true) {
+    ::aos::time::PhasedLoopXMS(::aos::controls::kLoopFrequency.ToMSec(), 2500);
+    if (ShouldCancel()) {
+      return true;
+    }
+
+    if (!has_lifted &&
+        CurrentGoalX() > params.home_lift_horizontal_start_position) {
+      if (!SendGoal(0.0, params.home_return_height, false,
+                    kReallyFastMaxXVelocity, kReallyFastMaxYVelocity,
+                    kFastMaxXAcceleration, kFastMaxYAcceleration)) {
+        LOG(ERROR, "Sending fridge message failed.\n");
+        return false;
+      }
+      has_lifted = true;
+    }
+
+    if (NearGoal(0.0, params.home_return_height)) {
+      break;
+    }
+  }
+
+  return true;
+}
+
+double ScoreActor::CurrentHeight() {
+  fridge_queue.status.FetchLatest();
+  if (!fridge_queue.status.get()) {
+    LOG(ERROR, "Reading from fridge status queue failed.\n");
+    return false;
+  }
+
+  ::aos::util::ElevatorArmKinematics::KinematicResult results;
+  kinematics_.ForwardKinematic(fridge_queue.status->height,
+                               fridge_queue.status->angle, 0.0, 0.0, &results);
+
+  return results.fridge_h;
+}
+
+double ScoreActor::CurrentGoalHeight() {
+  fridge_queue.status.FetchLatest();
+  if (!fridge_queue.status.get()) {
+    LOG(ERROR, "Reading from fridge status queue failed.\n");
+    return 0.0;
+  }
+
+  ::aos::util::ElevatorArmKinematics::KinematicResult results;
+  kinematics_.ForwardKinematic(fridge_queue.status->goal_height,
+                               fridge_queue.status->goal_angle, 0.0, 0.0,
+                               &results);
+
+  return results.fridge_h;
+}
+
+double ScoreActor::CurrentX() {
+  fridge_queue.status.FetchLatest();
+  if (!fridge_queue.status.get()) {
+    LOG(ERROR, "Reading from fridge status queue failed.\n");
+    return false;
+  }
+
+  return fridge_queue.status->x;
+}
+
+double ScoreActor::CurrentGoalX() {
+  fridge_queue.status.FetchLatest();
+  if (!fridge_queue.status.get()) {
+    LOG(ERROR, "Reading from fridge status queue failed.\n");
+    return 0.0;
+  }
+
+  return fridge_queue.status->goal_x;
+}
+
+bool ScoreActor::SendGoal(double x, double y, bool grabbers_enabled,
+                          double max_x_velocity, double max_y_velocity,
+                          double max_x_acceleration,
+                          double max_y_acceleration) {
+  auto new_fridge_goal = control_loops::fridge_queue.goal.MakeMessage();
+  new_fridge_goal->x = x;
+  new_fridge_goal->y = y;
+  new_fridge_goal->profiling_type = 1;
+  new_fridge_goal->angular_velocity = 0.0;
+  new_fridge_goal->velocity = 0.0;
+  new_fridge_goal->grabbers.top_front = grabbers_enabled;
+  new_fridge_goal->grabbers.top_back = grabbers_enabled;
+  new_fridge_goal->grabbers.bottom_front = grabbers_enabled;
+  new_fridge_goal->grabbers.bottom_back = grabbers_enabled;
+  new_fridge_goal->max_x_velocity = max_x_velocity;
+  new_fridge_goal->max_y_velocity = max_y_velocity;
+  new_fridge_goal->max_x_acceleration = max_x_acceleration;
+  new_fridge_goal->max_y_acceleration = max_y_acceleration;
+  LOG_STRUCT(INFO, "sending fridge goal", *new_fridge_goal);
+
+  return new_fridge_goal.Send();
+}
+
+bool ScoreActor::NearHorizontalGoal(double x) {
+  fridge_queue.status.FetchLatest();
+  if (!fridge_queue.status.get()) {
+    LOG(ERROR, "Reading from fridge status queue failed.\n");
+    return false;
+  }
+
+  ::aos::util::ElevatorArmKinematics::KinematicResult results;
+  ::aos::util::ElevatorArmKinematics::KinematicResult goal_results;
+  kinematics_.ForwardKinematic(fridge_queue.status->height,
+                               fridge_queue.status->angle, 0.0, 0.0, &results);
+  kinematics_.ForwardKinematic(fridge_queue.status->goal_height,
+                               fridge_queue.status->goal_angle, 0.0, 0.0,
+                               &goal_results);
+
+  return (::std::abs(results.fridge_x - x) < 0.020 &&
+          ::std::abs(goal_results.fridge_x - x) < 0.0001);
+}
+
+bool ScoreActor::NearGoal(double x, double y) {
+  fridge_queue.status.FetchLatest();
+  if (!fridge_queue.status.get()) {
+    LOG(ERROR, "Reading from fridge status queue failed.\n");
+    return false;
+  }
+
+  const auto &status = *fridge_queue.status;
+  return (::std::abs(status.x - x) < 0.020 &&
+          ::std::abs(status.y - y) < 0.020 &&
+          ::std::abs(status.goal_x - x) < 0.0001 &&
+          ::std::abs(status.goal_y - y) < 0.0001);
+}
+
+::std::unique_ptr<ScoreAction> MakeScoreAction(const ScoreParams& params) {
+  return ::std::unique_ptr<ScoreAction>(
+      new ScoreAction(&::frc971::actors::score_action, params));
+}
+
+}  // namespace actors
+}  // namespace frc971
diff --git a/y2015/actors/score_actor.h b/y2015/actors/score_actor.h
new file mode 100644
index 0000000..c9ed71f
--- /dev/null
+++ b/y2015/actors/score_actor.h
@@ -0,0 +1,43 @@
+#ifndef Y2015_ACTORS_SCORE_ACTOR_H_
+#define Y2015_ACTORS_SCORE_ACTOR_H_
+
+#include "aos/common/actions/actions.h"
+#include "aos/common/actions/actor.h"
+#include "y2015/util/kinematics.h"
+#include "y2015/actors/score_action.q.h"
+
+namespace frc971 {
+namespace actors {
+
+class ScoreActor
+    : public ::aos::common::actions::ActorBase<ScoreActionQueueGroup> {
+ public:
+  explicit ScoreActor(ScoreActionQueueGroup *queues);
+
+  bool RunAction(const ScoreParams &params) override;
+
+ private:
+
+  ::aos::util::ElevatorArmKinematics kinematics_;
+  bool NearGoal(double x, double y);
+  bool NearHorizontalGoal(double x);
+  bool PlaceTheStack(const ScoreParams &params);
+  bool MoveStackIntoPosition(const ScoreParams &params);
+  bool SendGoal(double x, double y, bool grabbers_enabled,
+                double max_x_velocity, double max_y_velocity,
+                double max_x_acceleration, double max_y_acceleration);
+  double CurrentHeight();
+  double CurrentGoalHeight();
+  double CurrentX();
+  double CurrentGoalX();
+};
+
+typedef aos::common::actions::TypedAction<ScoreActionQueueGroup> ScoreAction;
+
+// Makes a new ScoreActor action.
+::std::unique_ptr<ScoreAction> MakeScoreAction(const ScoreParams &params);
+
+}  // namespace actors
+}  // namespace frc971
+
+#endif
diff --git a/y2015/actors/score_actor_main.cc b/y2015/actors/score_actor_main.cc
new file mode 100644
index 0000000..cc149e6
--- /dev/null
+++ b/y2015/actors/score_actor_main.cc
@@ -0,0 +1,15 @@
+#include <stdio.h>
+
+#include "aos/linux_code/init.h"
+#include "y2015/actors/score_action.q.h"
+#include "y2015/actors/score_actor.h"
+
+int main(int /*argc*/, char* /*argv*/ []) {
+  ::aos::Init();
+
+  frc971::actors::ScoreActor score(&::frc971::actors::score_action);
+  score.Run();
+
+  ::aos::Cleanup();
+  return 0;
+}
diff --git a/y2015/actors/score_actor_test.cc b/y2015/actors/score_actor_test.cc
new file mode 100644
index 0000000..4791f09
--- /dev/null
+++ b/y2015/actors/score_actor_test.cc
@@ -0,0 +1,98 @@
+#include <unistd.h>
+
+#include <memory>
+
+#include "gtest/gtest.h"
+#include "aos/common/queue.h"
+#include "aos/common/queue_testutils.h"
+#include "aos/common/actions/actor.h"
+#include "y2015/actors/score_action.q.h"
+#include "y2015/actors/score_actor.h"
+#include "y2015/control_loops/fridge/fridge.q.h"
+#include "frc971/control_loops/team_number_test_environment.h"
+
+using ::aos::time::Time;
+
+namespace frc971 {
+namespace actors {
+namespace testing {
+
+class ScoreActionTest : public ::testing::Test {
+ protected:
+  ScoreActionTest() {
+    frc971::actors::score_action.goal.Clear();
+    frc971::actors::score_action.status.Clear();
+    control_loops::fridge_queue.status.Clear();
+    control_loops::fridge_queue.goal.Clear();
+  }
+
+  virtual ~ScoreActionTest() {
+    frc971::actors::score_action.goal.Clear();
+    frc971::actors::score_action.status.Clear();
+    control_loops::fridge_queue.status.Clear();
+    control_loops::fridge_queue.goal.Clear();
+  }
+
+  // Bring up and down Core.
+  ::aos::common::testing::GlobalCoreInstance my_core;
+};
+
+// Tests that cancel stops not only the score action, but also the underlying
+// profile action.
+TEST_F(ScoreActionTest, PlaceTheStackCancel) {
+  ScoreActor score(&frc971::actors::score_action);
+
+  frc971::actors::score_action.goal.MakeWithBuilder().run(true).Send();
+
+  // Tell it the fridge is zeroed.
+  ASSERT_TRUE(control_loops::fridge_queue.status.MakeWithBuilder()
+                  .zeroed(true)
+                  .angle(0.0)
+                  .height(0.0)
+                  .Send());
+
+  // do the action and it will post to the goal queue
+  score.WaitForActionRequest();
+
+  // the action has started, so now cancel it and it should cancel
+  // the underlying profile
+  frc971::actors::score_action.goal.MakeWithBuilder().run(false).Send();
+
+  // let the action start running, if we return from this call it has worked.
+  const ScoreParams params = {true, true, 0.14, 0.13, -0.7, -0.7, -0.10, -0.5, 0.1};
+  score.RunAction(params);
+
+  SUCCEED();
+}
+
+// Tests that cancel stops not only the score action, but also the underlying
+// profile action.
+TEST_F(ScoreActionTest, MoveStackIntoPositionCancel) {
+  ScoreActor score(&frc971::actors::score_action);
+
+  frc971::actors::score_action.goal.MakeWithBuilder().run(true).Send();
+
+  // Tell it the fridge is zeroed.
+  ASSERT_TRUE(control_loops::fridge_queue.status.MakeWithBuilder()
+                  .zeroed(true)
+                  .angle(0.0)
+                  .height(0.0)
+                  .Send());
+
+  // do the action and it will post to the goal queue
+  score.WaitForActionRequest();
+
+  // the action has started, so now cancel it and it should cancel
+  // the underlying profile
+  frc971::actors::score_action.goal.MakeWithBuilder().run(false).Send();
+
+  // let the action start running, if we return from this call it has worked.
+  const ScoreParams params = {false, true, 0.14, 0.13, -0.7, -0.7, -0.10, -0.5, 0.1};
+  score.RunAction(params);
+
+  SUCCEED();
+}
+
+}  // namespace testing
+}  // namespace actors
+}  // namespace frc971
diff --git a/y2015/actors/stack_action.q b/y2015/actors/stack_action.q
new file mode 100644
index 0000000..b4389b8
--- /dev/null
+++ b/y2015/actors/stack_action.q
@@ -0,0 +1,18 @@
+package frc971.actors;
+
+import "aos/common/actions/actions.q";
+import "y2015/actors/stack_action_params.q";
+
+queue_group StackActionQueueGroup {
+  implements aos.common.actions.ActionQueueGroup;
+
+  message Goal {
+    uint32_t run;
+    StackParams params;
+  };
+
+  queue Goal goal;
+  queue aos.common.actions.Status status;
+};
+
+queue_group StackActionQueueGroup stack_action;
diff --git a/y2015/actors/stack_action_params.q b/y2015/actors/stack_action_params.q
new file mode 100644
index 0000000..3958f7d
--- /dev/null
+++ b/y2015/actors/stack_action_params.q
@@ -0,0 +1,17 @@
+package frc971.actors;
+
+// Parameters to send with start.
+struct StackParams {
+  // If true, don't grab the lower tote after lowering.
+  bool only_place;
+
+  // The angle to move the arm to while lowering it.
+  double arm_clearance;
+
+  double claw_out_angle;
+  // The height just above the box to move before lowering.
+  double over_box_before_place_height;
+
+  // Bottom position.
+  double bottom;
+};
diff --git a/y2015/actors/stack_actor.cc b/y2015/actors/stack_actor.cc
new file mode 100644
index 0000000..539018f
--- /dev/null
+++ b/y2015/actors/stack_actor.cc
@@ -0,0 +1,96 @@
+#include "y2015/actors/stack_actor.h"
+
+#include <math.h>
+
+#include "aos/common/time.h"
+#include "aos/common/util/phased_loop.h"
+
+#include "y2015/constants.h"
+#include "y2015/control_loops/claw/claw.q.h"
+
+namespace frc971 {
+namespace actors {
+namespace {
+constexpr ProfileParams kArmWithStackMove{1.75, 4.20};
+constexpr ProfileParams kSlowArmMove{1.3, 1.4};
+constexpr ProfileParams kSlowElevatorMove{1.0, 3.0};
+
+constexpr ProfileParams kFastArmMove{0.8, 4.0};
+constexpr ProfileParams kFastElevatorMove{1.2, 5.0};
+constexpr ProfileParams kReallyFastElevatorMove{1.2, 6.0};
+}  // namespace
+
+StackActor::StackActor(StackActionQueueGroup *queues)
+    : FridgeActorBase<StackActionQueueGroup>(queues) {}
+
+bool StackActor::RunAction(const StackParams &params) {
+  const auto &values = constants::GetValues();
+
+  control_loops::fridge_queue.status.FetchLatest();
+  if (!control_loops::fridge_queue.status.get()) {
+    LOG(ERROR, "Got no fridge status packet.\n");
+    return false;
+  }
+
+  // If we are really high, probably have a can.  Move over before down.
+  if (control_loops::fridge_queue.status->goal_height >
+      params.over_box_before_place_height + 0.1) {
+    // Set the current stack down on top of the bottom box.
+    DoFridgeProfile(control_loops::fridge_queue.status->goal_height, 0.0,
+                    kSlowElevatorMove, kArmWithStackMove, true);
+    if (ShouldCancel()) return true;
+  }
+
+  // Set the current stack down on top of the bottom box.
+  DoFridgeProfile(params.bottom + values.tote_height, 0.0, kSlowElevatorMove,
+                  kSlowArmMove, true);
+  if (ShouldCancel()) return true;
+
+  // Clamp.
+  if (!params.only_place) {
+    // Move the claw out of the way only if we are supposed to pick up.
+    bool send_goal = true;
+    control_loops::claw_queue.status.FetchLatest();
+    if (control_loops::claw_queue.status.get()) {
+      if (control_loops::claw_queue.status->goal_angle <
+          params.claw_out_angle) {
+        send_goal = false;
+      }
+    }
+    if (send_goal) {
+      auto message = control_loops::claw_queue.goal.MakeMessage();
+      message->angle = params.claw_out_angle;
+      message->angular_velocity = 0.0;
+      message->intake = 0.0;
+      message->rollers_closed = true;
+      message->max_velocity = 6.0;
+      message->max_acceleration = 10.0;
+
+      LOG_STRUCT(DEBUG, "Sending claw goal", *message);
+      message.Send();
+    }
+  }
+
+  if (params.only_place) {
+    // open grabber for place only
+    DoFridgeProfile(params.bottom + values.tote_height, 0.0, kFastElevatorMove,
+                    kFastArmMove, false);
+    // Finish early if we aren't supposed to grab.
+    return true;
+  }
+
+  if (ShouldCancel()) return true;
+  // grab can (if in fang mode the grabber stays closed)
+  DoFridgeProfile(params.bottom, 0.0, kReallyFastElevatorMove, kFastArmMove, true,
+                  true, true);
+
+  return true;
+}
+
+::std::unique_ptr<StackAction> MakeStackAction(const StackParams &params) {
+  return ::std::unique_ptr<StackAction>(
+      new StackAction(&::frc971::actors::stack_action, params));
+}
+
+}  // namespace actors
+}  // namespace frc971
diff --git a/y2015/actors/stack_actor.h b/y2015/actors/stack_actor.h
new file mode 100644
index 0000000..5f2f7fb
--- /dev/null
+++ b/y2015/actors/stack_actor.h
@@ -0,0 +1,31 @@
+#ifndef Y2015_ACTORS_STACK_ACTOR_H_
+#define Y2015_ACTORS_STACK_ACTOR_H_
+
+#include <stdint.h>
+
+#include <memory>
+
+#include "aos/common/actions/actions.h"
+#include "aos/common/actions/actor.h"
+#include "y2015/actors/stack_action.q.h"
+#include "y2015/actors/fridge_profile_lib.h"
+
+namespace frc971 {
+namespace actors {
+
+class StackActor : public FridgeActorBase<StackActionQueueGroup> {
+ public:
+  explicit StackActor(StackActionQueueGroup *queues);
+
+  bool RunAction(const StackParams &params) override;
+};
+
+typedef aos::common::actions::TypedAction<StackActionQueueGroup> StackAction;
+
+// Makes a new stackActor action.
+::std::unique_ptr<StackAction> MakeStackAction(const StackParams &params);
+
+}  // namespace actors
+}  // namespace frc971
+
+#endif
diff --git a/y2015/actors/stack_actor_main.cc b/y2015/actors/stack_actor_main.cc
new file mode 100644
index 0000000..f65733c
--- /dev/null
+++ b/y2015/actors/stack_actor_main.cc
@@ -0,0 +1,15 @@
+#include <stdio.h>
+
+#include "aos/linux_code/init.h"
+#include "y2015/actors/stack_action.q.h"
+#include "y2015/actors/stack_actor.h"
+
+int main(int /*argc*/, char* /*argv*/ []) {
+  ::aos::Init();
+
+  ::frc971::actors::StackActor stack(&::frc971::actors::stack_action);
+  stack.Run();
+
+  ::aos::Cleanup();
+  return 0;
+}
diff --git a/y2015/actors/stack_actor_test.cc b/y2015/actors/stack_actor_test.cc
new file mode 100644
index 0000000..e1b1856
--- /dev/null
+++ b/y2015/actors/stack_actor_test.cc
@@ -0,0 +1,72 @@
+#include <unistd.h>
+
+#include <memory>
+
+#include "gtest/gtest.h"
+#include "aos/common/queue.h"
+#include "aos/common/queue_testutils.h"
+#include "aos/common/actions/actor.h"
+#include "y2015/actors/stack_action.q.h"
+#include "y2015/actors/stack_actor.h"
+#include "y2015/control_loops/fridge/fridge.q.h"
+
+#include "aos/common/controls/control_loop_test.h"
+#include "frc971/control_loops/team_number_test_environment.h"
+
+using ::aos::time::Time;
+
+namespace frc971 {
+namespace actors {
+namespace testing {
+
+class StackActionTest : public ::testing::Test {
+ protected:
+  StackActionTest() {
+    frc971::actors::stack_action.goal.Clear();
+    frc971::actors::stack_action.status.Clear();
+    control_loops::fridge_queue.status.Clear();
+    control_loops::fridge_queue.goal.Clear();
+  }
+
+  virtual ~StackActionTest() {
+    frc971::actors::stack_action.goal.Clear();
+    frc971::actors::stack_action.status.Clear();
+    control_loops::fridge_queue.status.Clear();
+    control_loops::fridge_queue.goal.Clear();
+  }
+
+  // Bring up and down Core.
+  ::aos::common::testing::GlobalCoreInstance my_core;
+};
+
+// Tests that cancel stops not only the stack action, but the underlying profile
+// action.
+TEST_F(StackActionTest, StackCancel) {
+  StackActor stack(&frc971::actors::stack_action);
+
+  frc971::actors::stack_action.goal.MakeWithBuilder().run(true).Send();
+
+  // tell it the fridge is zeroed
+  control_loops::fridge_queue.status.MakeWithBuilder()
+      .zeroed(true)
+      .angle(0.0)
+      .height(0.0)
+      .Send();
+
+  // do the action and it will post to the goal queue
+  stack.WaitForActionRequest();
+
+  // the action has started, so now cancel it and it should cancel
+  // the underlying profile
+  frc971::actors::stack_action.goal.MakeWithBuilder().run(false).Send();
+
+  // let the action start running, if we return from this call it has worked.
+  StackParams s;
+  stack.RunAction(s);
+
+  SUCCEED();
+}
+
+}  // namespace testing
+}  // namespace actors
+}  // namespace frc971
diff --git a/y2015/actors/stack_and_hold_action.q b/y2015/actors/stack_and_hold_action.q
new file mode 100644
index 0000000..42e98ed
--- /dev/null
+++ b/y2015/actors/stack_and_hold_action.q
@@ -0,0 +1,42 @@
+package frc971.actors;
+
+import "aos/common/actions/actions.q";
+import "y2015/actors/stack_action_params.q";
+
+// Parameters to send with start.
+struct StackAndHoldParams {
+  // If true, there is no tote on the tray, and we should place instead.
+  bool place_not_stack;
+
+  double claw_out_angle;
+  // The height just above the box to move before lowering.
+  double over_box_before_place_height;
+
+  // Bottom position.
+  double bottom;
+
+  // If we are placing, clamp the stack with the claw.
+  double claw_clamp_angle;
+
+  // Amount to wait to release.
+  double clamp_pause_time;
+
+  // The value to move the arm forwards to clear the stack when lifting.
+  double arm_clearance;
+  // Hold height
+  double hold_height;
+};
+
+queue_group StackAndHoldActionQueueGroup {
+  implements aos.common.actions.ActionQueueGroup;
+
+  message Goal {
+    uint32_t run;
+    StackAndHoldParams params;
+  };
+
+  queue Goal goal;
+  queue aos.common.actions.Status status;
+};
+
+queue_group StackAndHoldActionQueueGroup stack_and_hold_action;
diff --git a/y2015/actors/stack_and_hold_actor.cc b/y2015/actors/stack_and_hold_actor.cc
new file mode 100644
index 0000000..ae1eeda
--- /dev/null
+++ b/y2015/actors/stack_and_hold_actor.cc
@@ -0,0 +1,132 @@
+#include "y2015/actors/stack_and_hold_actor.h"
+
+#include <math.h>
+
+#include "aos/common/time.h"
+#include "aos/common/util/phased_loop.h"
+
+#include "y2015/constants.h"
+#include "y2015/control_loops/claw/claw.q.h"
+#include "y2015/actors/stack_actor.h"
+
+namespace frc971 {
+namespace actors {
+namespace {
+constexpr ProfileParams kReallySlowArmMove{0.1, 1.0};
+constexpr ProfileParams kReallySlowElevatorMove{0.10, 1.0};
+
+constexpr ProfileParams kFastArmMove{0.8, 4.0};
+constexpr ProfileParams kFastElevatorMove{1.2, 4.0};
+}  // namespace
+
+StackAndHoldActor::StackAndHoldActor(StackAndHoldActionQueueGroup *queues)
+    : FridgeActorBase<StackAndHoldActionQueueGroup>(queues) {}
+
+bool StackAndHoldActor::RunAction(const StackAndHoldParams &params) {
+  // TODO(ben)): this action is no longer used (source Cameron) and my be broken
+  // by the stack action having the grabbers closed at the end for the fangs. So
+  // here I am disabling it until further information is provided.
+  if (params.place_not_stack) {
+    // Move the arm out of the way.
+    {
+      bool send_goal = true;
+      control_loops::claw_queue.status.FetchLatest();
+      if (control_loops::claw_queue.status.get()) {
+        if (control_loops::claw_queue.status->goal_angle <
+            params.claw_out_angle) {
+          send_goal = false;
+        }
+      }
+      if (send_goal) {
+        auto message = control_loops::claw_queue.goal.MakeMessage();
+        message->angle = params.claw_out_angle;
+        message->angular_velocity = 0.0;
+        message->intake = 0.0;
+        message->rollers_closed = true;
+        message->max_velocity = 6.0;
+        message->max_acceleration = 10.0;
+
+        LOG_STRUCT(DEBUG, "Sending claw goal", *message);
+        message.Send();
+      }
+    }
+
+    // Get close, but keep the arm forwards
+    DoFridgeProfile(params.bottom + 0.04, -0.05, kFastArmMove,
+                    kFastElevatorMove, true);
+
+    // Lower and pull back.
+    if (ShouldCancel()) return true;
+    DoFridgeProfile(params.bottom, 0.0, kReallySlowArmMove,
+                    kReallySlowElevatorMove, true, true, false);
+
+    // Release.
+    if (ShouldCancel()) return true;
+    DoFridgeProfile(params.bottom, 0.0, kReallySlowArmMove,
+                    kReallySlowElevatorMove, false);
+  } else {
+    StackParams stack_params;
+    stack_params.only_place = true;
+    stack_params.arm_clearance = params.arm_clearance;
+    stack_params.claw_out_angle = params.claw_out_angle;
+    stack_params.over_box_before_place_height =
+        params.over_box_before_place_height;
+    stack_params.bottom = params.bottom;
+    ::std::unique_ptr<StackAction> stack_action =
+        MakeStackAction(stack_params);
+    stack_action->Start();
+    while (stack_action->Running()) {
+      ::aos::time::PhasedLoopXMS(::aos::controls::kLoopFrequency.ToMSec(),
+                                 2500);
+
+      if (ShouldCancel()) {
+        stack_action->Cancel();
+        LOG(WARNING, "Cancelling fridge and claw.\n");
+        return true;
+      }
+    }
+  }
+
+  if (!WaitOrCancel(aos::time::Time::InSeconds(params.clamp_pause_time))) {
+    return true;
+  }
+
+  // Go up.
+  DoFridgeProfile(params.hold_height, params.arm_clearance, kFastArmMove,
+                  kFastElevatorMove, false);
+
+  if (ShouldCancel()) return true;
+
+  if (params.place_not_stack) {
+    // Clamp the stack with the claw.
+    auto message = control_loops::claw_queue.goal.MakeMessage();
+    message->angle = params.claw_clamp_angle;
+    message->angular_velocity = 0.0;
+    message->intake = 0.0;
+    message->rollers_closed = true;
+    message->max_velocity = 6.0;
+    message->max_acceleration = 6.0;
+
+    LOG_STRUCT(DEBUG, "Sending claw goal", *message);
+    message.Send();
+  }
+  // Move back
+  DoFridgeProfile(params.hold_height, 0.0, kFastArmMove, kFastElevatorMove,
+                  false);
+  if (ShouldCancel()) return true;
+  // Grab
+  DoFridgeProfile(params.hold_height, 0.0, kFastArmMove, kFastElevatorMove,
+                  true);
+  if (ShouldCancel()) return true;
+
+  return true;
+}
+
+::std::unique_ptr<StackAndHoldAction> MakeStackAndHoldAction(
+    const StackAndHoldParams &params) {
+  return ::std::unique_ptr<StackAndHoldAction>(
+      new StackAndHoldAction(&::frc971::actors::stack_and_hold_action, params));
+}
+
+}  // namespace actors
+}  // namespace frc971
diff --git a/y2015/actors/stack_and_hold_actor.h b/y2015/actors/stack_and_hold_actor.h
new file mode 100644
index 0000000..b3bf2c5
--- /dev/null
+++ b/y2015/actors/stack_and_hold_actor.h
@@ -0,0 +1,33 @@
+#ifndef Y2015_ACTORS_STACK_AND_HOLD_ACTOR_H_
+#define Y2015_ACTORS_STACK_AND_HOLD_ACTOR_H_
+
+#include <stdint.h>
+
+#include <memory>
+
+#include "aos/common/actions/actions.h"
+#include "aos/common/actions/actor.h"
+#include "y2015/actors/stack_and_hold_action.q.h"
+#include "y2015/actors/fridge_profile_lib.h"
+
+namespace frc971 {
+namespace actors {
+
+class StackAndHoldActor : public FridgeActorBase<StackAndHoldActionQueueGroup> {
+ public:
+  explicit StackAndHoldActor(StackAndHoldActionQueueGroup *queues);
+
+  bool RunAction(const StackAndHoldParams &params) override;
+};
+
+typedef aos::common::actions::TypedAction<StackAndHoldActionQueueGroup>
+    StackAndHoldAction;
+
+// Makes a new stackActor action.
+::std::unique_ptr<StackAndHoldAction> MakeStackAndHoldAction(
+    const StackAndHoldParams &params);
+
+}  // namespace actors
+}  // namespace frc971
+
+#endif  // Y2015_ACTORS_STACK_AND_HOLD_ACTOR_H_
diff --git a/y2015/actors/stack_and_hold_actor_main.cc b/y2015/actors/stack_and_hold_actor_main.cc
new file mode 100644
index 0000000..3d5d1c1
--- /dev/null
+++ b/y2015/actors/stack_and_hold_actor_main.cc
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+#include "aos/linux_code/init.h"
+#include "y2015/actors/stack_and_hold_action.q.h"
+#include "y2015/actors/stack_and_hold_actor.h"
+
+int main(int /*argc*/, char* /*argv*/ []) {
+  ::aos::Init();
+
+  ::frc971::actors::StackAndHoldActor stack_and_hold(
+      &::frc971::actors::stack_and_hold_action);
+  stack_and_hold.Run();
+
+  ::aos::Cleanup();
+  return 0;
+}
diff --git a/y2015/actors/stack_and_lift_action.q b/y2015/actors/stack_and_lift_action.q
new file mode 100644
index 0000000..0ec971b
--- /dev/null
+++ b/y2015/actors/stack_and_lift_action.q
@@ -0,0 +1,34 @@
+package frc971.actors;
+
+import "aos/common/actions/actions.q";
+
+import "y2015/actors/stack_action_params.q";
+import "y2015/actors/lift_action_params.q";
+
+// Parameters to send with start.
+struct StackAndLiftParams {
+  // Stack parameters
+  StackParams stack_params;
+  // True if the fridge should be clamped while lifting.
+  bool grab_after_stack;
+  // The time after clamping to pause.
+  double clamp_pause_time;
+  // Lift parameters
+  LiftParams lift_params;
+  // True if the fridge should be clamped when done.
+  bool grab_after_lift;
+};
+
+queue_group StackAndLiftActionQueueGroup {
+  implements aos.common.actions.ActionQueueGroup;
+
+  message Goal {
+    uint32_t run;
+    StackAndLiftParams params;
+  };
+
+  queue Goal goal;
+  queue aos.common.actions.Status status;
+};
+
+queue_group StackAndLiftActionQueueGroup stack_and_lift_action;
diff --git a/y2015/actors/stack_and_lift_actor.cc b/y2015/actors/stack_and_lift_actor.cc
new file mode 100644
index 0000000..32f7417
--- /dev/null
+++ b/y2015/actors/stack_and_lift_actor.cc
@@ -0,0 +1,115 @@
+#include "y2015/actors/stack_and_lift_actor.h"
+
+#include <math.h>
+
+#include "aos/common/controls/control_loop.h"
+#include "aos/common/time.h"
+#include "aos/common/util/phased_loop.h"
+
+#include "y2015/constants.h"
+#include "y2015/control_loops/claw/claw.q.h"
+#include "y2015/actors/stack_actor.h"
+#include "y2015/actors/lift_actor.h"
+
+namespace frc971 {
+namespace actors {
+
+StackAndLiftActor::StackAndLiftActor(StackAndLiftActionQueueGroup *queues)
+    : FridgeActorBase<StackAndLiftActionQueueGroup>(queues) {}
+
+bool StackAndLiftActor::RunAction(const StackAndLiftParams &params) {
+  control_loops::claw_queue.goal.FetchLatest();
+  double claw_goal_start;
+  bool have_claw_goal_start;
+  if (control_loops::claw_queue.goal.get()) {
+    claw_goal_start = control_loops::claw_queue.goal->angle;
+    have_claw_goal_start = true;
+  } else {
+    claw_goal_start = 0;
+    have_claw_goal_start = false;
+  }
+
+  {
+    StackParams stack_params = params.stack_params;
+    stack_params.only_place = false;
+    ::std::unique_ptr<StackAction> stack_action =
+        MakeStackAction(stack_params);
+    stack_action->Start();
+    while (stack_action->Running()) {
+      ::aos::time::PhasedLoopXMS(::aos::controls::kLoopFrequency.ToMSec(),
+                                 2500);
+
+      if (ShouldCancel()) {
+        stack_action->Cancel();
+        LOG(WARNING, "Cancelling fridge and claw.\n");
+        return true;
+      }
+    }
+  }
+
+  {
+    control_loops::fridge_queue.goal.FetchLatest();
+    if (!control_loops::fridge_queue.goal.get()) {
+      return false;
+    }
+    auto new_fridge_goal = control_loops::fridge_queue.goal.MakeMessage();
+    *new_fridge_goal = *control_loops::fridge_queue.goal;
+    new_fridge_goal->grabbers.top_front = params.grab_after_stack;
+    new_fridge_goal->grabbers.top_back = params.grab_after_stack;
+    new_fridge_goal->grabbers.bottom_front = params.grab_after_stack;
+    new_fridge_goal->grabbers.bottom_back = params.grab_after_stack;
+    if (!new_fridge_goal.Send()) {
+      LOG(ERROR, "Failed to send fridge close.\n");
+      return false;
+    }
+  }
+
+  if (!WaitOrCancel(aos::time::Time::InSeconds(params.clamp_pause_time))) {
+    return true;
+  }
+
+  {
+    auto lift_params = params.lift_params;
+    lift_params.pack_claw = have_claw_goal_start;
+    lift_params.pack_claw_angle = claw_goal_start;
+    ::std::unique_ptr<LiftAction> lift_action = MakeLiftAction(lift_params);
+    lift_action->Start();
+    while (lift_action->Running()) {
+      ::aos::time::PhasedLoopXMS(::aos::controls::kLoopFrequency.ToMSec(),
+                                 2500);
+
+      if (ShouldCancel()) {
+        lift_action->Cancel();
+        LOG(WARNING, "Cancelling fridge and claw.\n");
+        return true;
+      }
+    }
+  }
+
+  {
+    control_loops::fridge_queue.goal.FetchLatest();
+    if (!control_loops::fridge_queue.goal.get()) {
+      return false;
+    }
+    auto new_fridge_goal = control_loops::fridge_queue.goal.MakeMessage();
+    *new_fridge_goal = *control_loops::fridge_queue.goal;
+    new_fridge_goal->grabbers.top_front = params.grab_after_lift;
+    new_fridge_goal->grabbers.top_back = params.grab_after_lift;
+    new_fridge_goal->grabbers.bottom_front = params.grab_after_lift;
+    new_fridge_goal->grabbers.bottom_back = params.grab_after_lift;
+    if (!new_fridge_goal.Send()) {
+      LOG(ERROR, "Failed to send fridge close.\n");
+      return false;
+    }
+  }
+  return true;
+}
+
+::std::unique_ptr<StackAndLiftAction> MakeStackAndLiftAction(
+    const StackAndLiftParams &params) {
+  return ::std::unique_ptr<StackAndLiftAction>(
+      new StackAndLiftAction(&::frc971::actors::stack_and_lift_action, params));
+}
+
+}  // namespace actors
+}  // namespace frc971
diff --git a/y2015/actors/stack_and_lift_actor.h b/y2015/actors/stack_and_lift_actor.h
new file mode 100644
index 0000000..1d5fe29
--- /dev/null
+++ b/y2015/actors/stack_and_lift_actor.h
@@ -0,0 +1,33 @@
+#ifndef Y2015_ACTORS_STACK_AND_LIFT_ACTOR_H_
+#define Y2015_ACTORS_STACK_AND_LIFT_ACTOR_H_
+
+#include <stdint.h>
+
+#include <memory>
+
+#include "aos/common/actions/actions.h"
+#include "aos/common/actions/actor.h"
+#include "y2015/actors/stack_and_lift_action.q.h"
+#include "y2015/actors/fridge_profile_lib.h"
+
+namespace frc971 {
+namespace actors {
+
+class StackAndLiftActor : public FridgeActorBase<StackAndLiftActionQueueGroup> {
+ public:
+  explicit StackAndLiftActor(StackAndLiftActionQueueGroup *queues);
+
+  bool RunAction(const StackAndLiftParams &params) override;
+};
+
+typedef aos::common::actions::TypedAction<StackAndLiftActionQueueGroup>
+    StackAndLiftAction;
+
+// Makes a new stackActor action.
+::std::unique_ptr<StackAndLiftAction> MakeStackAndLiftAction(
+    const StackAndLiftParams &params);
+
+}  // namespace actors
+}  // namespace frc971
+
+#endif  // Y2015_ACTORS_STACK_AND_LIFT_ACTOR_H_
diff --git a/y2015/actors/stack_and_lift_actor_main.cc b/y2015/actors/stack_and_lift_actor_main.cc
new file mode 100644
index 0000000..fe9f4b5
--- /dev/null
+++ b/y2015/actors/stack_and_lift_actor_main.cc
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+#include "aos/linux_code/init.h"
+#include "y2015/actors/stack_and_lift_action.q.h"
+#include "y2015/actors/stack_and_lift_actor.h"
+
+int main(int /*argc*/, char* /*argv*/ []) {
+  ::aos::Init();
+
+  ::frc971::actors::StackAndLiftActor stack_and_lift(
+      &::frc971::actors::stack_and_lift_action);
+  stack_and_lift.Run();
+
+  ::aos::Cleanup();
+  return 0;
+}
diff --git a/y2015/autonomous/auto.cc b/y2015/autonomous/auto.cc
new file mode 100644
index 0000000..9ade207
--- /dev/null
+++ b/y2015/autonomous/auto.cc
@@ -0,0 +1,558 @@
+#include <stdio.h>
+
+#include <memory>
+
+#include "aos/common/util/phased_loop.h"
+#include "aos/common/time.h"
+#include "aos/common/util/trapezoid_profile.h"
+#include "aos/common/logging/logging.h"
+#include "aos/common/logging/queue_logging.h"
+
+#include "frc971/autonomous/auto.q.h"
+#include "y2015/constants.h"
+#include "y2015/control_loops/drivetrain/drivetrain.q.h"
+#include "y2015/actors/drivetrain_actor.h"
+#include "y2015/control_loops/claw/claw.q.h"
+#include "y2015/control_loops/fridge/fridge.q.h"
+#include "y2015/actors/pickup_actor.h"
+#include "y2015/actors/stack_actor.h"
+#include "y2015/actors/held_to_lift_actor.h"
+
+using ::aos::time::Time;
+using ::frc971::control_loops::claw_queue;
+using ::frc971::control_loops::fridge_queue;
+using ::frc971::control_loops::drivetrain_queue;
+
+namespace frc971 {
+namespace autonomous {
+
+constexpr double kClawAutoVelocity = 3.00;
+constexpr double kClawAutoAcceleration = 6.0;
+constexpr double kAngleEpsilon = 0.10;
+const double kClawTotePackAngle = 0.90;
+const double kArmRaiseLowerClearance = -0.08;
+const double kClawStackClearance = 0.55;
+const double kStackUpHeight = 0.60;
+const double kStackUpArm = 0.0;
+
+struct ProfileParams {
+  double velocity;
+  double acceleration;
+};
+
+namespace time = ::aos::time;
+
+static double left_initial_position, right_initial_position;
+
+bool ShouldExitAuto() {
+  ::frc971::autonomous::autonomous.FetchLatest();
+  bool ans = !::frc971::autonomous::autonomous->run_auto;
+  if (ans) {
+    LOG(INFO, "Time to exit auto mode\n");
+  }
+  return ans;
+}
+
+void StopDrivetrain() {
+  LOG(INFO, "Stopping the drivetrain\n");
+  control_loops::drivetrain_queue.goal.MakeWithBuilder()
+      .control_loop_driving(true)
+      .left_goal(left_initial_position)
+      .left_velocity_goal(0)
+      .right_goal(right_initial_position)
+      .right_velocity_goal(0)
+      .quickturn(false)
+      .Send();
+}
+
+void ResetDrivetrain() {
+  LOG(INFO, "resetting the drivetrain\n");
+  control_loops::drivetrain_queue.goal.MakeWithBuilder()
+      .control_loop_driving(false)
+      //.highgear(false)
+      .steering(0.0)
+      .throttle(0.0)
+      .left_goal(left_initial_position)
+      .left_velocity_goal(0)
+      .right_goal(right_initial_position)
+      .right_velocity_goal(0)
+      .Send();
+}
+
+void WaitUntilDoneOrCanceled(
+    ::std::unique_ptr<aos::common::actions::Action> action) {
+  if (!action) {
+    LOG(ERROR, "No action, not waiting\n");
+    return;
+  }
+  while (true) {
+    // Poll the running bit and auto done bits.
+    ::aos::time::PhasedLoopXMS(5, 2500);
+    if (!action->Running() || ShouldExitAuto()) {
+      return;
+    }
+  }
+}
+
+void StepDrive(double distance, double theta) {
+  double left_goal = (left_initial_position + distance -
+                      theta * constants::GetValues().turn_width / 2.0);
+  double right_goal = (right_initial_position + distance +
+                       theta * constants::GetValues().turn_width / 2.0);
+  control_loops::drivetrain_queue.goal.MakeWithBuilder()
+      .control_loop_driving(true)
+      .left_goal(left_goal)
+      .right_goal(right_goal)
+      .left_velocity_goal(0.0)
+      .right_velocity_goal(0.0)
+      .Send();
+  left_initial_position = left_goal;
+  right_initial_position = right_goal;
+}
+
+void WaitUntilNear(double distance) {
+  while (true) {
+    if (ShouldExitAuto()) return;
+    control_loops::drivetrain_queue.status.FetchAnother();
+    double left_error = ::std::abs(
+        left_initial_position -
+        control_loops::drivetrain_queue.status->filtered_left_position);
+    double right_error = ::std::abs(
+        right_initial_position -
+        control_loops::drivetrain_queue.status->filtered_right_position);
+    const double kPositionThreshold = 0.05 + distance;
+    if (right_error < kPositionThreshold && left_error < kPositionThreshold) {
+      LOG(INFO, "At the goal\n");
+      return;
+    }
+  }
+}
+
+const ProfileParams kFastDrive = {2.0, 3.5};
+const ProfileParams kFastKnockDrive = {2.0, 3.0};
+const ProfileParams kStackingSecondDrive = {2.0, 1.5};
+const ProfileParams kFastTurn = {3.0, 10.0};
+const ProfileParams kStackingFirstTurn = {1.0, 1.0};
+const ProfileParams kStackingSecondTurn = {2.0, 6.0};
+const ProfileParams kComboTurn = {1.2, 8.0};
+const ProfileParams kRaceTurn = {4.0, 10.0};
+const ProfileParams kRaceDrive = {2.0, 2.0};
+const ProfileParams kRaceBackupDrive = {2.0, 5.0};
+
+::std::unique_ptr<::frc971::actors::DrivetrainAction> SetDriveGoal(
+    double distance, const ProfileParams drive_params, double theta = 0, const ProfileParams &turn_params = kFastTurn) {
+  LOG(INFO, "Driving to %f\n", distance);
+
+  ::frc971::actors::DrivetrainActionParams params;
+  params.left_initial_position = left_initial_position;
+  params.right_initial_position = right_initial_position;
+  params.y_offset = distance;
+  params.theta_offset = theta;
+  params.maximum_turn_acceleration = turn_params.acceleration;
+  params.maximum_turn_velocity = turn_params.velocity;
+  params.maximum_velocity = drive_params.velocity;
+  params.maximum_acceleration = drive_params.acceleration;
+  auto drivetrain_action = actors::MakeDrivetrainAction(params);
+
+  drivetrain_action->Start();
+  left_initial_position +=
+      distance - theta * constants::GetValues().turn_width / 2.0;
+  right_initial_position +=
+      distance + theta * constants::GetValues().turn_width / 2.0;
+  return ::std::move(drivetrain_action);
+}
+
+const ProfileParams kFridgeYProfile{1.0, 4.0};
+const ProfileParams kFridgeXProfile{1.0, 2.0};
+const ProfileParams kFridgeFastXProfile{1.2, 5.0};
+
+static double fridge_goal_x = 0.0;
+static double fridge_goal_y = 0.0;
+
+void MoveFridge(double x, double y, bool grabbers, const ProfileParams x_params,
+                const ProfileParams y_params) {
+  auto new_fridge_goal = fridge_queue.goal.MakeMessage();
+  new_fridge_goal->profiling_type = 1;
+
+  new_fridge_goal->max_y_velocity = y_params.velocity;
+  new_fridge_goal->max_y_acceleration = y_params.acceleration;
+  new_fridge_goal->y = y;
+  fridge_goal_y = y;
+  new_fridge_goal->y_velocity = 0.0;
+
+  new_fridge_goal->max_x_velocity = x_params.velocity;
+  new_fridge_goal->max_x_acceleration = x_params.acceleration;
+  new_fridge_goal->x = x;
+  fridge_goal_x = x;
+  new_fridge_goal->x_velocity = 0.0;
+
+  new_fridge_goal->grabbers.top_front = grabbers;
+  new_fridge_goal->grabbers.top_back = grabbers;
+  new_fridge_goal->grabbers.bottom_front = grabbers;
+  new_fridge_goal->grabbers.bottom_back = grabbers;
+
+  if (!new_fridge_goal.Send()) {
+    LOG(ERROR, "Sending fridge goal failed.\n");
+    return;
+  }
+}
+
+void WaitForFridge() {
+  while (true) {
+    if (ShouldExitAuto()) return;
+    control_loops::fridge_queue.status.FetchAnother();
+
+    constexpr double kProfileError = 1e-5;
+    constexpr double kXEpsilon = 0.03, kYEpsilon = 0.03;
+
+    if (control_loops::fridge_queue.status->state != 4) {
+      LOG(ERROR, "Fridge no longer running, aborting action\n");
+      return;
+    }
+
+    if (::std::abs(control_loops::fridge_queue.status->goal_x - fridge_goal_x) <
+            kProfileError &&
+        ::std::abs(control_loops::fridge_queue.status->goal_y - fridge_goal_y) <
+            kProfileError &&
+        ::std::abs(control_loops::fridge_queue.status->goal_x_velocity) <
+            kProfileError &&
+        ::std::abs(control_loops::fridge_queue.status->goal_y_velocity) <
+            kProfileError) {
+      LOG(INFO, "Profile done.\n");
+      if (::std::abs(control_loops::fridge_queue.status->x - fridge_goal_x) <
+              kXEpsilon &&
+          ::std::abs(control_loops::fridge_queue.status->y - fridge_goal_y) <
+              kYEpsilon) {
+        LOG(INFO, "Near goal, done.\n");
+        return;
+      }
+    }
+  }
+}
+
+void InitializeEncoders() {
+  control_loops::drivetrain_queue.status.FetchAnother();
+  left_initial_position =
+      control_loops::drivetrain_queue.status->filtered_left_position;
+  right_initial_position =
+      control_loops::drivetrain_queue.status->filtered_right_position;
+}
+
+void WaitForClawZero() {
+  LOG(INFO, "Waiting for claw to zero.\n");
+  while (true) {
+    control_loops::claw_queue.status.FetchAnother();
+    LOG_STRUCT(DEBUG, "Got claw status", *control_loops::claw_queue.status);
+    if (control_loops::claw_queue.status->zeroed) {
+      LOG(INFO, "Claw zeroed\n");
+      return;
+    }
+
+    if (ShouldExitAuto()) return;
+  }
+}
+
+void WaitForFridgeZero() {
+  LOG(INFO, "Waiting for claw to zero.\n");
+  while (true) {
+    control_loops::fridge_queue.status.FetchAnother();
+    LOG_STRUCT(DEBUG, "Got fridge status", *control_loops::fridge_queue.status);
+    if (control_loops::fridge_queue.status->zeroed) {
+      LOG(INFO, "Fridge zeroed\n");
+      return;
+    }
+
+    if (ShouldExitAuto()) return;
+  }
+}
+
+constexpr ProfileParams kDefaultClawParams = {kClawAutoVelocity,
+                                              kClawAutoAcceleration};
+
+// Move the claw in a very small number of cycles.
+constexpr ProfileParams kInstantaneousClaw = {100.0, 100.0};
+constexpr ProfileParams kFastClaw = {8.0, 20.0};
+
+void SetClawStateNoWait(double angle, double intake_voltage,
+                        double rollers_closed,
+                        const ProfileParams &claw_params = kDefaultClawParams) {
+  auto message = control_loops::claw_queue.goal.MakeMessage();
+  message->angle = angle;
+  message->max_velocity = claw_params.velocity;
+  message->max_acceleration = claw_params.acceleration;
+  message->angular_velocity = 0.0;
+  message->intake = intake_voltage;
+  message->rollers_closed = rollers_closed;
+
+  LOG_STRUCT(DEBUG, "Sending claw goal", *message);
+  message.Send();
+}
+
+void SetClawState(double angle, double intake_voltage, double rollers_closed,
+                  const ProfileParams &claw_params = kDefaultClawParams) {
+  SetClawStateNoWait(angle, intake_voltage, rollers_closed, claw_params);
+  while (true) {
+    control_loops::claw_queue.status.FetchAnother();
+    const double current_angle = control_loops::claw_queue.status->angle;
+    LOG_STRUCT(DEBUG, "Got claw status", *control_loops::claw_queue.status);
+
+    // I believe all we can care about here is the angle. Other values will
+    // either be set or not, but there is nothing we can do about it. If it
+    // never gets there we do not care, auto is over for us.
+    if (::std::abs(current_angle - angle) < kAngleEpsilon) {
+      break;
+    }
+    if (ShouldExitAuto()) return;
+  }
+}
+
+void HandleAuto() {
+  ::aos::time::Time start_time = ::aos::time::Time::Now();
+  LOG(INFO, "Starting auto mode at %f\n", start_time.ToSeconds());
+  ::std::unique_ptr<::frc971::actors::DrivetrainAction> drive;
+  ::std::unique_ptr<::frc971::actors::PickupAction> pickup;
+  ::std::unique_ptr<::frc971::actors::StackAction> stack;
+  ::std::unique_ptr<::frc971::actors::HeldToLiftAction> lift;
+
+  actors::PickupParams pickup_params;
+  // Lift to here initially.
+  pickup_params.pickup_angle = 0.9;
+  // Start sucking here
+  pickup_params.suck_angle = 0.8;
+  // Go back down to here to finish sucking.
+  pickup_params.suck_angle_finish = 0.4;
+  // Pack the box back in here.
+  pickup_params.pickup_finish_angle = kClawTotePackAngle;
+  pickup_params.intake_time = 0.70;
+  pickup_params.intake_voltage = 7.0;
+
+  if (ShouldExitAuto()) return;
+  InitializeEncoders();
+  ResetDrivetrain();
+
+  WaitForClawZero();
+  WaitForFridgeZero();
+
+  // Initialize the fridge.
+  MoveFridge(0.0, 0.3, true, kFridgeXProfile, kFridgeYProfile);
+
+  LOG(INFO, "Lowering claw into position.\n");
+  SetClawState(0.0, 2.0, false, kInstantaneousClaw);
+
+  LOG(INFO, "Sucking in tote.\n");
+  SetClawState(0.0, 6.0, true, kInstantaneousClaw);
+
+  time::SleepFor(time::Time::InSeconds(0.7));
+  LOG(INFO, "Done sucking in tote\n");
+
+  // Now pick it up
+  pickup = actors::MakePickupAction(pickup_params);
+  pickup->Start();
+
+  time::SleepFor(time::Time::InSeconds(0.9));
+  // Start turning.
+  LOG(INFO, "Turning in place\n");
+  drive = SetDriveGoal(0.0, kFastDrive, -0.23, kStackingFirstTurn);
+
+  WaitUntilDoneOrCanceled(::std::move(drive));
+  if (ShouldExitAuto()) return;
+
+  LOG(INFO, "Now driving next to the can\n");
+  drive = SetDriveGoal(0.60, kFastDrive);
+
+  WaitUntilDoneOrCanceled(::std::move(pickup));
+  if (ShouldExitAuto()) return;
+
+  // Now grab it in the fridge.
+  {
+    actors::StackParams params;
+
+    params.claw_out_angle = kClawTotePackAngle;
+    params.bottom = 0.020;
+    params.only_place = false;
+    params.arm_clearance = kArmRaiseLowerClearance;
+    params.over_box_before_place_height = 0.39;
+
+    stack = actors::MakeStackAction(params);
+    stack->Start();
+  }
+  WaitUntilDoneOrCanceled(::std::move(stack));
+  if (ShouldExitAuto()) return;
+
+  // Lower the claw to knock the tote.
+  LOG(INFO, "Lowering the claw to knock the tote\n");
+  SetClawStateNoWait(0.0, 0.0, true, kFastClaw);
+
+  time::SleepFor(time::Time::InSeconds(0.1));
+  if (ShouldExitAuto()) return;
+
+  WaitUntilDoneOrCanceled(::std::move(drive));
+  if (ShouldExitAuto()) return;
+
+  LOG(INFO, "Knocking the can over\n");
+  drive = SetDriveGoal(0.40, kFastKnockDrive, 1.05, kComboTurn);
+  WaitUntilDoneOrCanceled(::std::move(drive));
+  if (ShouldExitAuto()) return;
+  {
+    actors::HeldToLiftParams params;
+    params.arm_clearance = kArmRaiseLowerClearance;
+    params.clamp_pause_time = 0.1;
+    params.before_lift_settle_time = 0.1;
+    params.bottom_height = 0.020;
+    params.claw_out_angle = kClawStackClearance;
+    params.lift_params.lift_height = kStackUpHeight;
+    params.lift_params.lift_arm = kStackUpArm;
+    params.lift_params.second_lift = false;
+
+    lift = actors::MakeHeldToLiftAction(params);
+    lift->Start();
+  }
+
+  LOG(INFO, "Turning back to aim\n");
+  drive = SetDriveGoal(0.0, kFastDrive, -0.70);
+  WaitUntilDoneOrCanceled(::std::move(drive));
+  if (ShouldExitAuto()) return;
+
+  SetClawStateNoWait(0.0, 4.0, false, kFastClaw);
+  LOG(INFO, "Now driving the second tote\n");
+  drive = SetDriveGoal(1.05, kFastDrive);
+
+  // Wait until we are almost at the tote, and then start intaking.
+  WaitUntilNear(0.35);
+
+  SetClawState(0.0, 6.0, true, kFastClaw);
+  WaitUntilDoneOrCanceled(::std::move(drive));
+  if (ShouldExitAuto()) return;
+
+  if (ShouldExitAuto()) return;
+  time::SleepFor(time::Time::InSeconds(0.30));
+  if (ShouldExitAuto()) return;
+
+  SetClawStateNoWait(0.0, 4.0, true, kFastClaw);
+  if (ShouldExitAuto()) return;
+  time::SleepFor(time::Time::InSeconds(0.10));
+
+  WaitUntilDoneOrCanceled(::std::move(lift));
+  if (ShouldExitAuto()) return;
+
+  LOG(INFO, "Done sucking in tote\n");
+  SetClawState(0.0, 0.0, true, kFastClaw);
+  if (ShouldExitAuto()) return;
+
+  // Now pick it up
+  pickup = actors::MakePickupAction(pickup_params);
+  pickup->Start();
+
+  time::SleepFor(time::Time::InSeconds(1.0));
+  if (ShouldExitAuto()) return;
+
+  // Start turning.
+  LOG(INFO, "Turning in place\n");
+  drive = SetDriveGoal(0.0, kStackingSecondDrive, -0.40, kStackingSecondTurn);
+
+  WaitUntilDoneOrCanceled(::std::move(pickup));
+  if (ShouldExitAuto()) return;
+
+  // Now grab it in the fridge.
+  {
+    actors::StackParams params;
+
+    params.claw_out_angle = kClawTotePackAngle;
+    params.bottom = 0.020;
+    params.only_place = false;
+    params.arm_clearance = kArmRaiseLowerClearance;
+    params.over_box_before_place_height = 0.39;
+
+    stack = actors::MakeStackAction(params);
+    stack->Start();
+  }
+
+  WaitUntilDoneOrCanceled(::std::move(drive));
+  if (ShouldExitAuto()) return;
+  LOG(INFO, "Driving next to the can.\n");
+  drive = SetDriveGoal(0.65, kStackingSecondDrive);
+
+  WaitUntilDoneOrCanceled(::std::move(stack));
+  if (ShouldExitAuto()) return;
+
+  // Lower the claw to knock the tote.
+  LOG(INFO, "Lowering the claw to knock the tote\n");
+  SetClawStateNoWait(0.0, 0.0, true, kFastClaw);
+
+  // Lift the fridge.
+  MoveFridge(0.0, 0.3, true, kFridgeXProfile, kFridgeYProfile);
+
+  time::SleepFor(time::Time::InSeconds(0.1));
+  if (ShouldExitAuto()) return;
+
+  WaitUntilDoneOrCanceled(::std::move(drive));
+  if (ShouldExitAuto()) return;
+
+  LOG(INFO, "Knocking the can over\n");
+  drive = SetDriveGoal(0.40, kFastKnockDrive, 1.05, kComboTurn);
+  WaitUntilDoneOrCanceled(::std::move(drive));
+  if (ShouldExitAuto()) return;
+
+  LOG(INFO, "Turning back to aim\n");
+  drive = SetDriveGoal(0.0, kFastDrive, -0.60);
+  WaitUntilDoneOrCanceled(::std::move(drive));
+  if (ShouldExitAuto()) return;
+
+
+  SetClawStateNoWait(0.0, 4.0, false, kFastClaw);
+  LOG(INFO, "Now driving to the last tote\n");
+  drive = SetDriveGoal(1.05, kFastDrive);
+  WaitUntilNear(0.05);
+
+  SetClawState(0.0, 7.0, true, kFastClaw);
+  if (ShouldExitAuto()) return;
+
+  time::SleepFor(time::Time::InSeconds(0.2));
+  if (ShouldExitAuto()) return;
+
+  WaitUntilDoneOrCanceled(::std::move(drive));
+  if (ShouldExitAuto()) return;
+  SetClawState(0.0, 6.0, true, kFastClaw);
+
+  LOG(INFO, "Racing over\n");
+  //StepDrive(2.5, -1.4);
+  drive = SetDriveGoal(2.5, kRaceDrive, -1.4, kRaceTurn);
+
+  time::SleepFor(time::Time::InSeconds(0.5));
+
+  LOG(INFO, "Moving totes out\n");
+  MoveFridge(0.6, 0.32, true, kFridgeXProfile, kFridgeYProfile);
+
+  WaitForFridge();
+  if (ShouldExitAuto()) return;
+
+  LOG(INFO, "Lowering totes\n");
+  MoveFridge(0.6, 0.15, false, kFridgeXProfile, kFridgeYProfile);
+
+  WaitForFridge();
+  if (ShouldExitAuto()) return;
+
+  time::SleepFor(time::Time::InSeconds(0.1));
+
+  if (ShouldExitAuto()) return;
+
+  LOG(INFO, "Retracting\n");
+  MoveFridge(0.0, 0.10, false, kFridgeFastXProfile, kFridgeYProfile);
+
+  SetClawState(0.0, 0.0, false, kFastClaw);
+
+  if (ShouldExitAuto()) return;
+
+  WaitUntilDoneOrCanceled(::std::move(drive));
+  if (ShouldExitAuto()) return;
+
+  LOG(INFO, "Backing away to let the stack ago\n");
+  drive = SetDriveGoal(-0.1, kRaceBackupDrive);
+  WaitUntilDoneOrCanceled(::std::move(drive));
+
+  WaitForFridge();
+  if (ShouldExitAuto()) return;
+}
+
+}  // namespace autonomous
+}  // namespace frc971
diff --git a/y2015/autonomous/auto.h b/y2015/autonomous/auto.h
new file mode 100644
index 0000000..7733715
--- /dev/null
+++ b/y2015/autonomous/auto.h
@@ -0,0 +1,12 @@
+#ifndef Y2015_AUTONOMOUS_AUTO_H_
+#define Y2015_AUTONOMOUS_AUTO_H_
+
+namespace frc971 {
+namespace autonomous {
+
+void HandleAuto();
+
+}  // namespace autonomous
+}  // namespace frc971
+
+#endif  // Y2015_AUTONOMOUS_AUTO_H_
diff --git a/y2015/autonomous/auto_main.cc b/y2015/autonomous/auto_main.cc
new file mode 100644
index 0000000..4a24e6c
--- /dev/null
+++ b/y2015/autonomous/auto_main.cc
@@ -0,0 +1,42 @@
+#include <stdio.h>
+
+#include "aos/common/time.h"
+#include "aos/linux_code/init.h"
+#include "aos/common/logging/logging.h"
+#include "frc971/autonomous/auto.q.h"
+#include "y2015/autonomous/auto.h"
+
+using ::aos::time::Time;
+
+int main(int /*argc*/, char * /*argv*/[]) {
+  ::aos::Init();
+
+  LOG(INFO, "Auto main started\n");
+  ::frc971::autonomous::autonomous.FetchLatest();
+  while (!::frc971::autonomous::autonomous.get()) {
+    ::frc971::autonomous::autonomous.FetchNextBlocking();
+    LOG(INFO, "Got another auto packet\n");
+  }
+
+  while (true) {
+    while (!::frc971::autonomous::autonomous->run_auto) {
+      ::frc971::autonomous::autonomous.FetchNextBlocking();
+      LOG(INFO, "Got another auto packet\n");
+    }
+    LOG(INFO, "Starting auto mode\n");
+    ::aos::time::Time start_time = ::aos::time::Time::Now();
+    ::frc971::autonomous::HandleAuto();
+
+    ::aos::time::Time elapsed_time = ::aos::time::Time::Now() - start_time;
+    LOG(INFO, "Auto mode exited in %f, waiting for it to finish.\n",
+        elapsed_time.ToSeconds());
+    while (::frc971::autonomous::autonomous->run_auto) {
+      ::frc971::autonomous::autonomous.FetchNextBlocking();
+      LOG(INFO, "Got another auto packet\n");
+    }
+    LOG(INFO, "Waiting for auto to start back up.\n");
+  }
+  ::aos::Cleanup();
+  return 0;
+}
+
diff --git a/y2015/autonomous/autonomous.gyp b/y2015/autonomous/autonomous.gyp
new file mode 100644
index 0000000..63898e8
--- /dev/null
+++ b/y2015/autonomous/autonomous.gyp
@@ -0,0 +1,43 @@
+{
+  'targets': [
+    {
+      'target_name': 'auto_lib',
+      'type': 'static_library',
+      'sources': [
+        'auto.cc',
+      ],
+      'dependencies': [
+        '<(DEPTH)/frc971/autonomous/autonomous.gyp:auto_queue',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+        '<(DEPTH)/y2015/control_loops/drivetrain/drivetrain.gyp:drivetrain_queue',
+        '<(DEPTH)/y2015/y2015.gyp:constants',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/common/util/util.gyp:phased_loop',
+        '<(AOS)/common/util/util.gyp:trapezoid_profile',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(DEPTH)/y2015/actors/actors.gyp:drivetrain_action_lib',
+        '<(AOS)/common/logging/logging.gyp:queue_logging',
+        '<(DEPTH)/y2015/control_loops/claw/claw.gyp:claw_queue',
+        '<(DEPTH)/y2015/control_loops/fridge/fridge.gyp:fridge_queue',
+        '<(DEPTH)/y2015/actors/actors.gyp:stack_action_lib',
+        '<(DEPTH)/y2015/actors/actors.gyp:held_to_lift_action_lib',
+        '<(DEPTH)/y2015/actors/actors.gyp:pickup_action_lib',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+      ],
+    },
+    {
+      'target_name': 'auto',
+      'type': 'executable',
+      'sources': [
+        'auto_main.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(DEPTH)/frc971/autonomous/autonomous.gyp:auto_queue',
+        'auto_lib',
+      ],
+    },
+  ],
+}
diff --git a/y2015/constants.cc b/y2015/constants.cc
new file mode 100644
index 0000000..50f6672
--- /dev/null
+++ b/y2015/constants.cc
@@ -0,0 +1,381 @@
+#include "y2015/constants.h"
+
+#include <math.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+#include <map>
+
+#if __has_feature(address_sanitizer)
+#include "sanitizer/lsan_interface.h"
+#endif
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/once.h"
+#include "aos/common/network/team_number.h"
+#include "aos/common/mutex.h"
+
+#include "y2015/control_loops/drivetrain/polydrivetrain_dog_motor_plant.h"
+#include "y2015/control_loops/drivetrain/drivetrain_dog_motor_plant.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+namespace frc971 {
+namespace constants {
+namespace {
+
+const uint16_t kCompTeamNumber = 971;
+const uint16_t kPracticeTeamNumber = 9971;
+
+// ///// Drivetrain Constants
+
+// These three constants were set by Daniel on 2/13/15.
+const double kDrivetrainEncoderRatio = 20.0 / 50.0;
+const double kLowGearRatio = kDrivetrainEncoderRatio * 20.0 / 50.0;
+const double kHighGearRatio = kLowGearRatio;
+
+const ShifterHallEffect kCompRightDriveShifter{555, 657, 660, 560, 0.2, 0.7};
+const ShifterHallEffect kCompLeftDriveShifter{555, 660, 644, 552, 0.2, 0.7};
+
+const ShifterHallEffect kPracticeRightDriveShifter{2.95, 3.95, 3.95,
+                                                   2.95, 0.2,  0.7};
+const ShifterHallEffect kPracticeLeftDriveShifter{2.95, 4.2, 3.95,
+                                                  3.0,  0.2, 0.7};
+const double kToteHeight = 0.3;
+
+// Set by Daniel on 2/13/15.
+// Distance from the center of the left wheel to the center of the right wheel.
+const double kRobotWidth = 37.806 /*inches*/ * 0.0254;
+
+// ///// Superstructure Constants
+
+// Elevator gearbox pulley output constants.
+const int kElevatorGearboxOutputPulleyTeeth = 32;  // 32 teeth
+const double kElevatorGearboxOutputPitch = 0.005;  // 5 mm/tooth
+const double kElevatorGearboxOutputRadianDistance =
+    kElevatorGearboxOutputPulleyTeeth * kElevatorGearboxOutputPitch /
+    (2.0 * M_PI);
+
+const double kArmZeroingHeight = 0.2;
+
+const double kMaxAllowedLeftRightArmDifference = 0.12;  // radians
+const double kMaxAllowedLeftRightElevatorDifference = 0.04;  // meters
+
+const Values::ClawGeometry kClawGeometry{
+    // Horizontal distance from the center of the grabber to the end.
+    0.5 * 18.0 * 0.0254,
+    // Vertical distance from the arm rotation center to the bottom of
+    // the
+    // grabber.  Distance measured with arm vertical (theta = 0).
+    5.1 * 0.0254,
+    // Vertical separation of the claw and arm rotation centers with the
+    // elevator at 0.0 and the arm angle set to zero.
+    10.5 * 0.0254,
+    // Horizontal separation of the claw and arm rotation centers with
+    // the
+    // elevator at 0.0 and the arm angle set to zero.
+    6.5 * 0.0254,
+    // Distance between the center of the claw to the top of the claw.
+    // 2.75 inches would work most of the time.  Using 3.5 inches because
+    // of the
+    // pnumatics fitting on the piston.
+    3.5 * 0.0254,
+    // The grabber is safe at any height if it is behind this location.
+    // The location of the grabber is used here and not the location of
+    // the end
+    // of the grabber.  The grabber location is (0, 0) when the elevator
+    // is at 0
+    // and the arm angle is 0.
+    (18.0 - 0.3) * 0.0254,
+    // The grabber is safe at any x if it is above this location.
+    // The location of the grabber is used here and not the location of
+    // the end
+    // of the grabber.  The grabber location is (0, 0) when the elevator
+    // is at 0
+    // and the arm angle is 0.
+    // The "-5.4" is the location of the bottom of the grabber when
+    // the elevator is at the bottom (-0.3 inches) and arm angle is 0.
+    -8.0 * 0.0254,
+};
+
+// Gearing ratios of the pots and encoders for the elevator and arm.
+// Ratio is output shaft rotations per encoder/pot rotation
+// Checked by Daniel on 2/13/15.
+const double kArmEncoderRatio = 18.0 / 48.0 * 16.0 / 72.0;
+const double kArmPotRatio = 48.0 / 48.0 * 16.0 / 72.0;
+const double kElevatorEncoderRatio = 14.0 / 84.0;
+const double kElevatorPotRatio = 1.0;
+const double kClawEncoderRatio = 18.0 / 72.0;
+const double kClawPotRatio = 18.0 / 72.0;
+
+// Number of radians between each index pulse on the arm.
+const double kArmEncoderIndexDifference = 2.0 * M_PI * kArmEncoderRatio;
+// Number of meters between each index pulse on the elevator.
+const double kElevatorEncoderIndexDifference =
+    kElevatorEncoderRatio * 2.0 * M_PI *  // radians
+    kElevatorGearboxOutputRadianDistance;
+// Number of radians between index pulses on the claw.
+const double kClawEncoderIndexDifference = 2.0 * M_PI * kClawEncoderRatio;
+
+const int kZeroingSampleSize = 200;
+
+// The length of the arm.
+const double kArmLength = 0.7366;
+
+// TODO(danielp): All these values might need to change.
+const double kClawPistonSwitchTime = 0.4;
+const double kClawZeroingRange = 0.3;
+
+const Values *DoGetValuesForTeam(uint16_t team) {
+  switch (team) {
+    case 1:  // for tests
+      return new Values{
+          kDrivetrainEncoderRatio,
+          kArmEncoderRatio,
+          kArmPotRatio,
+          kElevatorEncoderRatio,
+          kElevatorPotRatio,
+          kElevatorGearboxOutputRadianDistance,
+          kClawEncoderRatio,
+          kClawPotRatio,
+          kToteHeight,
+          kLowGearRatio,
+          kHighGearRatio,
+          kCompLeftDriveShifter,
+          kCompRightDriveShifter,
+          false,
+          0.5,
+          control_loops::MakeVelocityDrivetrainLoop,
+          control_loops::MakeDrivetrainLoop,
+          0.02,  // drivetrain done delta
+          5.0,   // drivetrain max speed
+
+          // Motion ranges: hard_lower_limit, hard_upper_limit,
+          //                soft_lower_limit, soft_upper_limit
+          {// Claw values, in radians.
+           // 0 is level with the ground.
+           // Positive moves in the direction of positive encoder values.
+           {-0.05, M_PI / 2.0 + 0.1, 0.0, M_PI / 2.0},
+
+           // Zeroing constants for wrist.
+           {kZeroingSampleSize, kClawEncoderIndexDifference, 0.9, 0.3},
+
+           6.308141,
+           kClawPistonSwitchTime,
+           kClawZeroingRange},
+
+          {// Elevator values, in meters.
+           // 0 is the portion of the elevator carriage that Spencer removed
+           // lining up with the bolt.
+           // Positive is up.
+           {-0.005, 0.689000, 0.010000, 0.680000},
+
+           // Arm values, in radians.
+           // 0 is sticking straight out horizontally over the intake/front.
+           // Positive is rotating up and into the robot (towards the back).
+           {-M_PI / 2 - 0.05, M_PI / 2 + 0.05, -M_PI / 2, M_PI / 2},
+
+           // Elevator zeroing constants: left, right.
+           {kZeroingSampleSize, kElevatorEncoderIndexDifference, 0.0, 0.3},
+           {kZeroingSampleSize, kElevatorEncoderIndexDifference, 0.0, 0.3},
+           // Arm zeroing constants: left, right.
+           {kZeroingSampleSize, kArmEncoderIndexDifference, 0.0, 0.3},
+           {kZeroingSampleSize, kArmEncoderIndexDifference, 0.0, 0.3},
+           0.7,
+           -0.08,
+           -3.5 - 0.01 - -0.02,
+           3.5 - 0.17 - -0.15,
+
+           kArmZeroingHeight,
+           kArmLength,
+          },
+          // End "sensor" values.
+
+          kMaxAllowedLeftRightArmDifference,
+          kMaxAllowedLeftRightElevatorDifference,
+          kClawGeometry,
+      };
+      break;
+    case kPracticeTeamNumber:
+      return new Values{
+          kDrivetrainEncoderRatio,
+          kArmEncoderRatio,
+          kArmPotRatio,
+          kElevatorEncoderRatio,
+          kElevatorPotRatio,
+          kElevatorGearboxOutputRadianDistance,
+          kClawEncoderRatio,
+          kClawPotRatio,
+          kToteHeight,
+          kLowGearRatio,
+          kHighGearRatio,
+          kCompLeftDriveShifter,
+          kCompRightDriveShifter,
+          false,
+          kRobotWidth,
+          control_loops::MakeVelocityDrivetrainLoop,
+          control_loops::MakeDrivetrainLoop,
+          0.02,  // drivetrain done delta
+          5.0,   // drivetrain max speed
+
+          // Motion ranges: hard_lower_limit, hard_upper_limit,
+          //                soft_lower_limit, soft_upper_limit
+          // TODO(sensors): Get actual bounds before turning on robot.
+          {// Claw values, in radians.
+           // 0 is level with the ground.
+           // Positive moves in the direction of positive encoder values.
+           {-0.05, M_PI / 2.0 + 0.1, 0.0, M_PI / 2.0},
+
+           // Zeroing constants for wrist.
+           {kZeroingSampleSize, kClawEncoderIndexDifference, 0.9104180000000001,
+            0.3},
+
+           6.308141,
+           kClawPistonSwitchTime,
+           kClawZeroingRange},
+
+          {// Elevator values, in meters.
+           // 0 is the portion of the elevator carriage that Spencer removed
+           // lining up with the bolt.
+           // Positive is up.
+           {-0.00500, 0.689000, 0.010000, 0.680000},
+
+           // Arm values, in radians.
+           // 0 is sticking straight out horizontally over the intake/front.
+           // Positive is rotating up and into the robot (towards the back).
+           {-M_PI / 2 - 0.05, M_PI / 2 + 0.05, -M_PI / 2, M_PI / 2},
+
+           // Elevator zeroing constants: left, right.
+           {kZeroingSampleSize, kElevatorEncoderIndexDifference, 0.110677, 0.3},  // Was 0.088984 (3 mm too high)
+           {kZeroingSampleSize, kElevatorEncoderIndexDifference, 0.109974, 0.3},  // Was 0.104557 (4 mm too low)
+           // Arm zeroing constants: left, right.
+           {kZeroingSampleSize, kArmEncoderIndexDifference, -0.324437, 0.3},
+           {kZeroingSampleSize, kArmEncoderIndexDifference, -0.064683, 0.3},
+           0.722230 - -0.000594 - -0.026183 - 0.003442,   // Left Elevator Poteniometer adjustment
+           -0.081354 - -0.000374 - -0.024793 - -0.006916, // Right Elevator Poteniometer adjustment
+           -3.509611 - 0.007415 - -0.019081,
+           3.506927 - 0.170017 - -0.147970,
+
+           kArmZeroingHeight,
+           kArmLength,
+          },
+          // End "sensor" values.
+
+          kMaxAllowedLeftRightArmDifference,
+          kMaxAllowedLeftRightElevatorDifference,
+          kClawGeometry,
+      };
+      break;
+    case kCompTeamNumber:
+      return new Values{
+          kDrivetrainEncoderRatio,
+          kArmEncoderRatio,
+          kArmPotRatio,
+          kElevatorEncoderRatio,
+          kElevatorPotRatio,
+          kElevatorGearboxOutputRadianDistance,
+          kClawEncoderRatio,
+          kClawPotRatio,
+          kToteHeight,
+          kLowGearRatio,
+          kHighGearRatio,
+          kPracticeLeftDriveShifter,
+          kPracticeRightDriveShifter,
+          false,
+          kRobotWidth,
+          control_loops::MakeVelocityDrivetrainLoop,
+          control_loops::MakeDrivetrainLoop,
+          0.02,  // drivetrain done delta
+          5.0,   // drivetrain max speed
+
+          // Motion ranges: hard_lower_limit, hard_upper_limit,
+          //                soft_lower_limit, soft_upper_limit
+          // TODO(sensors): Get actual bounds before turning on robot.
+          {// Claw values, in radians.
+           // 0 is level with the ground.
+           // Positive moves in the direction of positive encoder values.
+           {-0.05, M_PI / 2.0 + 0.1, 0.0, M_PI / 2.0},
+
+           // Zeroing constants for wrist.
+           // TODO(sensors): Get actual offsets for these.
+           {kZeroingSampleSize, kClawEncoderIndexDifference, 0.952602, 0.3},
+           6.1663463999999992 + 0.015241,
+
+           kClawPistonSwitchTime,
+           kClawZeroingRange},
+
+          {// Elevator values, in meters.
+           // 0 is at the top of the elevator frame.
+           // Positive is down towards the drivebase.
+           {-0.00500, 0.689000, 0.010000, 0.680000},
+
+           // Arm values, in radians.
+           // 0 is sticking straight out horizontally over the intake/front.
+           // Positive is rotating up and into the robot (towards the back).
+           {-M_PI / 2 - 0.05, M_PI / 2 + 0.05, -M_PI / 2, M_PI / 2},
+
+           // Elevator zeroing constants: left, right.
+           // These are the encoder offsets.
+           // TODO(sensors): Get actual offsets for these.
+           {kZeroingSampleSize, kElevatorEncoderIndexDifference,
+            0.240286 - 0.007969 - 0.025, 0.3},
+           {kZeroingSampleSize, kElevatorEncoderIndexDifference,
+            0.234583 - 0.000143, 0.3},
+           // Arm zeroing constants: left, right.
+           {kZeroingSampleSize, kArmEncoderIndexDifference, 0.060592, 0.3},
+           {kZeroingSampleSize, kArmEncoderIndexDifference, 0.210155, 0.3},
+           // These are the potentiometer offsets.
+           0.72069366666666679 - 0.026008 - 0.024948 + 0.025,
+           -0.078959636363636357 - 0.024646  - 0.020260,
+           -3.509611 - 0.007415 - -0.019081 - 0.029393 - -0.013585,
+           3.506927 - 0.170017 - -0.147970 - 0.005045 - -0.026504,
+
+           kArmZeroingHeight,
+           kArmLength,
+          },
+          // TODO(sensors): End "sensor" values.
+
+          kMaxAllowedLeftRightArmDifference,
+          kMaxAllowedLeftRightElevatorDifference,
+          kClawGeometry,
+      };
+      break;
+    default:
+      LOG(FATAL, "unknown team #%" PRIu16 "\n", team);
+  }
+}
+
+const Values *DoGetValues() {
+  uint16_t team = ::aos::network::GetTeamNumber();
+  LOG(INFO, "creating a Constants for team %" PRIu16 "\n", team);
+  return DoGetValuesForTeam(team);
+}
+
+}  // namespace
+
+const Values &GetValues() {
+  static ::aos::Once<const Values> once(DoGetValues);
+  return *once.Get();
+}
+
+const Values &GetValuesForTeam(uint16_t team_number) {
+  static ::aos::Mutex mutex;
+  ::aos::MutexLocker locker(&mutex);
+
+  // IMPORTANT: This declaration has to stay after the mutex is locked to avoid
+  // race conditions.
+  static ::std::map<uint16_t, const Values *> values;
+
+  if (values.count(team_number) == 0) {
+    values[team_number] = DoGetValuesForTeam(team_number);
+#if __has_feature(address_sanitizer)
+    __lsan_ignore_object(values[team_number]);
+#endif
+  }
+  return *values[team_number];
+}
+
+}  // namespace constants
+}  // namespace frc971
diff --git a/y2015/constants.h b/y2015/constants.h
new file mode 100644
index 0000000..a87315c
--- /dev/null
+++ b/y2015/constants.h
@@ -0,0 +1,149 @@
+#ifndef Y2015_CONSTANTS_H_
+#define Y2015_CONSTANTS_H_
+
+#include <stdint.h>
+
+#include "frc971/control_loops/state_feedback_loop.h"
+#include "frc971/shifter_hall_effect.h"
+#include "frc971/constants.h"
+
+namespace frc971 {
+namespace constants {
+
+// Has all of the numbers that change for both robots and makes it easy to
+// retrieve the values for the current one.
+
+// Everything is in SI units (volts, radians, meters, seconds, etc).
+// Some of these values are related to the conversion between raw values
+// (encoder counts, voltage, etc) to scaled units (radians, meters, etc).
+
+// This structure contains current values for all of the things that change.
+struct Values {
+  // Drivetrain Values /////
+
+  // The ratio from the encoder shaft to the drivetrain wheels.
+  double drivetrain_encoder_ratio;
+  // The ratio from the encoder shaft to the arm joint.
+  double arm_encoder_ratio;
+  // The ratio from the pot shaft to the arm joint.
+  double arm_pot_ratio;
+  // The ratio from the encoder shaft to the elevator output pulley.
+  double elev_encoder_ratio;
+  // The ratio from the pot shaft to the elevator output pulley.
+  double elev_pot_ratio;
+  // How far the elevator moves (meters) per radian on the output pulley.
+  double elev_distance_per_radian;
+  // The ratio from the encoder shaft to the claw joint.
+  double claw_encoder_ratio;
+  // The ratio from the pot shaft to the claw joint.
+  double claw_pot_ratio;
+
+  // How tall a tote is in meters.
+  double tote_height;
+
+  // The gear ratios from motor shafts to the drivetrain wheels for high and low
+  // gear.
+  double low_gear_ratio;
+  double high_gear_ratio;
+  ShifterHallEffect left_drive, right_drive;
+  bool clutch_transmission;
+
+  double turn_width;
+
+  ::std::function<StateFeedbackLoop<2, 2, 2>()> make_v_drivetrain_loop;
+  ::std::function<StateFeedbackLoop<4, 2, 2>()> make_drivetrain_loop;
+
+  double drivetrain_done_distance;
+  double drivetrain_max_speed;
+
+  // Superstructure Values /////
+
+  // Defines a range of motion for a subsystem.
+  // These are all absolute positions in scaled units.
+  struct Range {
+    double lower_hard_limit;
+    double upper_hard_limit;
+    double lower_limit;
+    double upper_limit;
+  };
+
+  struct Claw {
+    Range wrist;
+    ZeroingConstants zeroing;
+    // The value to add to potentiometer readings after they have been converted
+    // to radians so that the resulting value is 0 when the claw is at absolute
+    // 0 (horizontal straight out the front).
+    double potentiometer_offset;
+
+    // Time between sending commands to claw opening pistons and them reaching
+    // the new state.
+    double piston_switch_time;
+    // How far on either side we look for the index pulse before we give up.
+    double zeroing_range;
+  };
+  Claw claw;
+
+  struct Fridge {
+    Range elevator;
+    Range arm;
+
+    ZeroingConstants left_elev_zeroing;
+    ZeroingConstants right_elev_zeroing;
+    ZeroingConstants left_arm_zeroing;
+    ZeroingConstants right_arm_zeroing;
+
+    // Values to add to scaled potentiometer readings so 0 lines up with the
+    // physical absolute 0.
+    double left_elevator_potentiometer_offset;
+    double right_elevator_potentiometer_offset;
+    double left_arm_potentiometer_offset;
+    double right_arm_potentiometer_offset;
+
+    // How high the elevator has to be before we start zeroing the arm.
+    double arm_zeroing_height;
+
+    // The length of the arm, from the axis of the bottom pivot to the axis of
+    // the top pivot.
+    double arm_length;
+  };
+  Fridge fridge;
+
+  double max_allowed_left_right_arm_difference;
+  double max_allowed_left_right_elevator_difference;
+
+  struct ClawGeometry {
+    // Horizontal distance from the center of the grabber to the end.
+    double grabber_half_length;
+    // Vertical distance from the arm rotation center to the bottom of the
+    // grabber.  Distance measured with arm vertical (theta = 0).
+    double grabber_delta_y;
+    // Vertical separation of the claw and arm rotation centers with the
+    // elevator at 0.0 and the arm angle set to zero.
+    double grabber_arm_vert_separation;
+    // Horizontal separation of the claw and arm rotation centers with the
+    // elevator at 0.0 and the arm angle set to zero.
+    double grabber_arm_horz_separation;
+    // Distance between the center of the claw to the top of the claw.
+    // The line drawn at this distance parallel to the claw centerline is used
+    // to determine if claw interfears with the grabber.
+    double claw_top_thickness;
+    // The grabber is safe at any height if it is behind this location.
+    double grabber_always_safe_h_min;
+    // The grabber is safe at any x if it is above this location.
+    double grabber_always_safe_x_max;
+  };
+  ClawGeometry clawGeometry;
+};
+
+// Creates (once) a Values instance for ::aos::network::GetTeamNumber() and
+// returns a reference to it.
+const Values &GetValues();
+
+// Creates Values instances for each team number it is called with and returns
+// them.
+const Values &GetValuesForTeam(uint16_t team_number);
+
+}  // namespace constants
+}  // namespace frc971
+
+#endif  // Y2015_CONSTANTS_H_
diff --git a/y2015/control_loops/claw/claw.cc b/y2015/control_loops/claw/claw.cc
new file mode 100644
index 0000000..c1a734e
--- /dev/null
+++ b/y2015/control_loops/claw/claw.cc
@@ -0,0 +1,311 @@
+#include "y2015/control_loops/claw/claw.h"
+
+#include <algorithm>
+
+#include "aos/common/controls/control_loops.q.h"
+#include "aos/common/logging/logging.h"
+
+#include "y2015/constants.h"
+#include "y2015/control_loops/claw/claw_motor_plant.h"
+#include "aos/common/util/trapezoid_profile.h"
+
+namespace frc971 {
+namespace control_loops {
+
+using ::aos::time::Time;
+
+constexpr double kZeroingVoltage = 4.0;
+
+void ClawCappedStateFeedbackLoop::CapU() {
+  mutable_U(0, 0) = ::std::min(mutable_U(0, 0), max_voltage_);
+  mutable_U(0, 0) = ::std::max(mutable_U(0, 0), -max_voltage_);
+}
+
+double ClawCappedStateFeedbackLoop::UnsaturateOutputGoalChange() {
+  // Compute K matrix to compensate for position errors.
+  double Kp = K(0, 0);
+
+  // Compute how much we need to change R in order to achieve the change in U
+  // that was observed.
+  return -(1.0 / Kp) * (U_uncapped() - U())(0, 0);
+}
+
+Claw::Claw(control_loops::ClawQueue *claw)
+    : aos::controls::ControlLoop<control_loops::ClawQueue>(claw),
+      last_piston_edge_(Time::Now()),
+      claw_loop_(new ClawCappedStateFeedbackLoop(MakeClawLoop())),
+      claw_estimator_(constants::GetValues().claw.zeroing),
+      profile_(::aos::controls::kLoopFrequency) {}
+
+void Claw::UpdateZeroingState() {
+  if (claw_estimator_.offset_ratio_ready() < 1.0) {
+    state_ = INITIALIZING;
+  } else if (!claw_estimator_.zeroed()) {
+    state_ = ZEROING;
+  } else {
+    state_ = RUNNING;
+  }
+}
+
+void Claw::Correct() {
+  Eigen::Matrix<double, 1, 1> Y;
+  Y << claw_position();
+  claw_loop_->Correct(Y);
+}
+
+void Claw::SetClawOffset(double offset) {
+  LOG(INFO, "Changing claw offset from %f to %f.\n", claw_offset_, offset);
+  const double doffset = offset - claw_offset_;
+
+  // Adjust the height. The derivative should not need to be updated since the
+  // speed is not changing.
+  claw_loop_->mutable_X_hat(0, 0) += doffset;
+
+  // Modify claw zeroing goal.
+  claw_goal_ += doffset;
+  // Update the cached offset value to the actual value.
+  claw_offset_ = offset;
+}
+
+double Claw::estimated_claw_position() const {
+  return current_position_.joint.encoder + claw_estimator_.offset();
+}
+
+double Claw::claw_position() const {
+  return current_position_.joint.encoder + claw_offset_;
+}
+
+constexpr double kClawZeroingVelocity = 0.2;
+
+double Claw::claw_zeroing_velocity() {
+  const auto &values = constants::GetValues();
+
+  // Zeroing will work as following. At startup, record the offset of the claw.
+  // Then, start moving the claw towards where the index pulse should be. We
+  // search around it a little, and if we don't find anything, we estop.
+  // Otherwise, we're done.
+
+  const double target_pos = values.claw.zeroing.measured_index_position;
+  // How far away we need to stay from the ends of the range while zeroing.
+  constexpr double zeroing_limit = 0.1375;
+  // Keep the zeroing range within the bounds of the mechanism.
+  const double zeroing_range =
+      ::std::min(target_pos - values.claw.wrist.lower_limit - zeroing_limit,
+                 values.claw.zeroing_range);
+
+  if (claw_zeroing_velocity_ == 0) {
+    if (estimated_claw_position() > target_pos) {
+      claw_zeroing_velocity_ = -kClawZeroingVelocity;
+    } else {
+      claw_zeroing_velocity_ = kClawZeroingVelocity;
+    }
+  } else if (claw_zeroing_velocity_ > 0 &&
+             estimated_claw_position() > target_pos + zeroing_range) {
+    claw_zeroing_velocity_ = -kClawZeroingVelocity;
+  } else if (claw_zeroing_velocity_ < 0 &&
+             estimated_claw_position() < target_pos - zeroing_range) {
+    claw_zeroing_velocity_ = kClawZeroingVelocity;
+  }
+
+  return claw_zeroing_velocity_;
+}
+
+void Claw::RunIteration(const control_loops::ClawQueue::Goal *unsafe_goal,
+                        const control_loops::ClawQueue::Position *position,
+                        control_loops::ClawQueue::Output *output,
+                        control_loops::ClawQueue::Status *status) {
+  const auto &values = constants::GetValues();
+
+  if (WasReset()) {
+    LOG(ERROR, "WPILib reset! Restarting.\n");
+    claw_estimator_.Reset();
+    state_ = UNINITIALIZED;
+  }
+
+  current_position_ = *position;
+
+  // Bool to track if we should turn the motor on or not.
+  bool disable = output == nullptr;
+  double claw_goal_velocity = 0.0;
+
+  claw_estimator_.UpdateEstimate(position->joint);
+
+  if (state_ != UNINITIALIZED) {
+    Correct();
+  }
+
+  switch (state_) {
+    case UNINITIALIZED:
+      LOG(INFO, "Uninitialized.\n");
+      // Startup. Assume that we are at the origin.
+      claw_offset_ = -position->joint.encoder;
+      claw_loop_->mutable_X_hat().setZero();
+      Correct();
+      state_ = INITIALIZING;
+      disable = true;
+      break;
+
+    case INITIALIZING:
+      LOG(INFO, "Waiting for accurate initial position.\n");
+      disable = true;
+      // Update state_ to accurately represent the state of the zeroing
+      // estimator.
+      UpdateZeroingState();
+
+      if (state_ != INITIALIZING) {
+        // Set the goals to where we are now.
+        claw_goal_ = claw_position();
+      }
+      break;
+
+    case ZEROING:
+      LOG(DEBUG, "Zeroing.\n");
+
+      // Update state_.
+      UpdateZeroingState();
+      if (claw_estimator_.zeroed()) {
+        LOG(INFO, "Zeroed!\n");
+        SetClawOffset(claw_estimator_.offset());
+      } else if (!disable) {
+        claw_goal_velocity = claw_zeroing_velocity();
+        claw_goal_ +=
+            claw_goal_velocity * ::aos::controls::kLoopFrequency.ToSeconds();
+      }
+
+      // Clear the current profile state if we are zeroing.
+      {
+        Eigen::Matrix<double, 2, 1> current;
+        current.setZero();
+        current << claw_goal_, claw_goal_velocity;
+        profile_.MoveCurrentState(current);
+      }
+      break;
+
+    case RUNNING:
+      LOG(DEBUG, "Running!\n");
+
+      // Update state_.
+      UpdateZeroingState();
+      if (unsafe_goal) {
+        // Pick a set of sane defaults if none are specified.
+        if (unsafe_goal->max_velocity != 0.0) {
+          profile_.set_maximum_velocity(unsafe_goal->max_velocity);
+        } else {
+          profile_.set_maximum_velocity(2.5);
+        }
+        if (unsafe_goal->max_acceleration != 0.0) {
+          profile_.set_maximum_acceleration(unsafe_goal->max_acceleration);
+        } else {
+          profile_.set_maximum_acceleration(4.0);
+        }
+
+        const double unfiltered_goal = ::std::max(
+            ::std::min(unsafe_goal->angle, values.claw.wrist.upper_limit),
+            values.claw.wrist.lower_limit);
+        ::Eigen::Matrix<double, 2, 1> goal_state =
+            profile_.Update(unfiltered_goal, unsafe_goal->angular_velocity);
+        claw_goal_ = goal_state(0, 0);
+        claw_goal_velocity = goal_state(1, 0);
+      }
+
+      if (state_ != RUNNING && state_ != ESTOP) {
+        state_ = UNINITIALIZED;
+      }
+      break;
+
+    case ESTOP:
+      LOG(ERROR, "Estop!\n");
+      disable = true;
+      break;
+  }
+
+  // Make sure goal and position do not exceed the hardware limits if we are
+  // RUNNING.
+  if (state_ == RUNNING) {
+    // Limit goal.
+    claw_goal_ = ::std::min(claw_goal_, values.claw.wrist.upper_limit);
+    claw_goal_ = ::std::max(claw_goal_, values.claw.wrist.lower_limit);
+
+    // Check position.
+    if (claw_position() >= values.claw.wrist.upper_hard_limit ||
+        claw_position() <= values.claw.wrist.lower_hard_limit) {
+      LOG(ERROR, "Claw at %f out of bounds [%f, %f].\n", claw_position(),
+          values.claw.wrist.lower_limit, values.claw.wrist.upper_limit);
+    }
+  }
+
+  // Set the goals.
+  claw_loop_->mutable_R() << claw_goal_, claw_goal_velocity;
+
+  const double max_voltage = (state_ == RUNNING) ? 12.0 : kZeroingVoltage;
+  claw_loop_->set_max_voltage(max_voltage);
+
+  if (state_ == ESTOP) {
+    disable = true;
+  }
+  claw_loop_->Update(disable);
+
+  if (state_ == INITIALIZING || state_ == ZEROING) {
+    if (claw_loop_->U() != claw_loop_->U_uncapped()) {
+      double deltaR = claw_loop_->UnsaturateOutputGoalChange();
+
+      // Move the claw goal by the amount observed.
+      LOG(WARNING, "Moving claw goal by %f to handle saturation.\n", deltaR);
+      claw_goal_ += deltaR;
+    }
+  }
+
+  if (output) {
+    output->voltage = claw_loop_->U(0, 0);
+    if (state_ != RUNNING) {
+      output->intake_voltage = 0.0;
+      output->rollers_closed = false;
+    } else {
+      if (unsafe_goal) {
+        output->intake_voltage = unsafe_goal->intake;
+        output->rollers_closed = unsafe_goal->rollers_closed;
+      } else {
+        output->intake_voltage = 0.0;
+        output->rollers_closed = false;
+      }
+    }
+    if (output->rollers_closed != last_rollers_closed_) {
+      last_piston_edge_ = Time::Now();
+    }
+  }
+
+  status->zeroed = state_ == RUNNING;
+  status->estopped = state_ == ESTOP;
+  status->state = state_;
+  zeroing::PopulateEstimatorState(claw_estimator_, &status->zeroing_state);
+
+  status->angle = claw_loop_->X_hat(0, 0);
+  status->angular_velocity = claw_loop_->X_hat(1, 0);
+
+  if (output) {
+    status->intake = output->intake_voltage;
+  } else {
+    status->intake = 0;
+  }
+  status->goal_angle = claw_goal_;
+  status->goal_velocity = claw_goal_velocity;
+
+  if (output) {
+    status->rollers_open =
+        !output->rollers_closed &&
+        (Time::Now() - last_piston_edge_ >= values.claw.piston_switch_time);
+    status->rollers_closed =
+        output->rollers_closed &&
+        (Time::Now() - last_piston_edge_ >= values.claw.piston_switch_time);
+  } else {
+    status->rollers_open = false;
+    status->rollers_closed = false;
+  }
+
+  if (output) {
+    last_rollers_closed_ = output->rollers_closed;
+  }
+}
+
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/y2015/control_loops/claw/claw.gyp b/y2015/control_loops/claw/claw.gyp
new file mode 100644
index 0000000..780f065
--- /dev/null
+++ b/y2015/control_loops/claw/claw.gyp
@@ -0,0 +1,89 @@
+{
+  'targets': [
+    {
+      'target_name': 'replay_claw',
+      'type': 'executable',
+      'variables': {
+        'no_rsync': 1,
+      },
+      'sources': [
+        'replay_claw.cc',
+      ],
+      'dependencies': [
+        'claw_queue',
+        '<(AOS)/common/controls/controls.gyp:replay_control_loop',
+        '<(AOS)/linux_code/linux_code.gyp:init',
+      ],
+    },
+    {
+      'target_name': 'claw_queue',
+      'type': 'static_library',
+      'sources': ['claw.q'],
+      'variables': {
+        'header_path': 'y2015/control_loops/claw',
+      },
+      'dependencies': [
+        '<(AOS)/common/controls/controls.gyp:control_loop_queues',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:queues',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/controls/controls.gyp:control_loop_queues',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:queues',
+
+      ],
+      'includes': ['../../../aos/build/queues.gypi'],
+    },
+    {
+      'target_name': 'claw_lib',
+      'type': 'static_library',
+      'sources': [
+        'claw.cc',
+        'claw_motor_plant.cc',
+      ],
+      'dependencies': [
+        'claw_queue',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/common/util/util.gyp:trapezoid_profile',
+        '<(DEPTH)/y2015/y2015.gyp:constants',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+        '<(DEPTH)/frc971/zeroing/zeroing.gyp:zeroing',
+      ],
+      'export_dependent_settings': [
+        'claw_queue',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/common/util/util.gyp:trapezoid_profile',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+        '<(DEPTH)/frc971/zeroing/zeroing.gyp:zeroing',
+      ],
+    },
+    {
+      'target_name': 'claw_lib_test',
+      'type': 'executable',
+      'sources': [
+        'claw_lib_test.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+        'claw_lib',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+        '<(AOS)/common/controls/controls.gyp:control_loop_test',
+        '<(AOS)/common/common.gyp:time',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:position_sensor_sim',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:team_number_test_environment',
+      ],
+    },
+    {
+      'target_name': 'claw',
+      'type': 'executable',
+      'sources': [
+        'claw_main.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        'claw_lib',
+      ],
+    },
+  ],
+}
diff --git a/y2015/control_loops/claw/claw.h b/y2015/control_loops/claw/claw.h
new file mode 100644
index 0000000..02e5398
--- /dev/null
+++ b/y2015/control_loops/claw/claw.h
@@ -0,0 +1,116 @@
+#ifndef Y2015_CONTROL_LOOPS_CLAW_H_
+#define Y2015_CONTROL_LOOPS_CLAW_H_
+
+#include <memory>
+
+#include "aos/common/controls/control_loop.h"
+#include "aos/common/time.h"
+#include "aos/common/util/trapezoid_profile.h"
+#include "frc971/control_loops/state_feedback_loop.h"
+#include "y2015/control_loops/claw/claw.q.h"
+#include "y2015/control_loops/claw/claw_motor_plant.h"
+#include "frc971/zeroing/zeroing.h"
+
+namespace frc971 {
+namespace control_loops {
+namespace testing {
+class ClawTest_DisabledGoal_Test;
+class ClawTest_GoalPositiveWindup_Test;
+class ClawTest_GoalNegativeWindup_Test;
+}  // namespace testing
+
+class ClawCappedStateFeedbackLoop : public StateFeedbackLoop<2, 1, 1> {
+ public:
+  ClawCappedStateFeedbackLoop(StateFeedbackLoop<2, 1, 1> &&loop)
+      : StateFeedbackLoop<2, 1, 1>(::std::move(loop)), max_voltage_(12.0) {}
+
+  void set_max_voltage(double max_voltage) {
+    max_voltage_ = ::std::max(0.0, ::std::min(12.0, max_voltage));
+  }
+
+  void CapU() override;
+
+  // Returns the amount to change the position goal in order to no longer
+  // saturate the controller.
+  double UnsaturateOutputGoalChange();
+
+ private:
+  double max_voltage_;
+};
+
+class Claw : public aos::controls::ControlLoop<control_loops::ClawQueue> {
+ public:
+  enum State {
+    // Waiting to receive data before doing anything.
+    UNINITIALIZED = 0,
+    // Estimating the starting location.
+    INITIALIZING = 1,
+    // Moving to find an index pulse.
+    ZEROING = 2,
+    // Normal operation.
+    RUNNING = 3,
+    // Internal error caused the claw to abort.
+    ESTOP = 4,
+  };
+
+  int state() { return state_; }
+
+  explicit Claw(
+      control_loops::ClawQueue *claw_queue = &control_loops::claw_queue);
+
+ protected:
+  virtual void RunIteration(const control_loops::ClawQueue::Goal *goal,
+                            const control_loops::ClawQueue::Position *position,
+                            control_loops::ClawQueue::Output *output,
+                            control_loops::ClawQueue::Status *status);
+
+ private:
+  friend class testing::ClawTest_DisabledGoal_Test;
+  friend class testing::ClawTest_GoalPositiveWindup_Test;
+  friend class testing::ClawTest_GoalNegativeWindup_Test;
+
+  // Sets state_ to the correct state given the current state of the zeroing
+  // estimator.
+  void UpdateZeroingState();
+  void SetClawOffset(double offset);
+  // Corrects the Observer with the current position.
+  void Correct();
+
+  // Getter for the current claw position.
+  double claw_position() const;
+  // Our best guess at the current position of the claw.
+  double estimated_claw_position() const;
+  // Returns the current zeroing velocity for the claw. If the subsystem is too
+  // far away from the center, it will switch directions.
+  double claw_zeroing_velocity();
+
+  State state_ = UNINITIALIZED;
+
+  // The time when we last changed the claw piston state.
+  ::aos::time::Time last_piston_edge_;
+
+  // The state feedback control loop to talk to.
+  ::std::unique_ptr<ClawCappedStateFeedbackLoop> claw_loop_;
+
+  // Latest position from queue.
+  control_loops::ClawQueue::Position current_position_;
+  // Zeroing estimator for claw.
+  zeroing::ZeroingEstimator claw_estimator_;
+
+  // The goal for the claw.
+  double claw_goal_ = 0.0;
+  // Current velocity to move at while zeroing.
+  double claw_zeroing_velocity_ = 0.0;
+  // Offsets from the encoder position to the absolute position.
+  double claw_offset_ = 0.0;
+
+  // Whether claw was closed last cycle.
+  bool last_rollers_closed_ = false;
+
+  ::aos::util::TrapezoidProfile profile_;
+};
+
+}  // namespace control_loops
+}  // namespace frc971
+
+#endif  // Y2015_CONTROL_LOOPS_CLAW_H_
diff --git a/y2015/control_loops/claw/claw.q b/y2015/control_loops/claw/claw.q
new file mode 100644
index 0000000..8da1c20
--- /dev/null
+++ b/y2015/control_loops/claw/claw.q
@@ -0,0 +1,81 @@
+package frc971.control_loops;
+
+import "aos/common/controls/control_loops.q";
+import "frc971/control_loops/control_loops.q";
+
+queue_group ClawQueue {
+  implements aos.control_loops.ControlLoop;
+
+  // All angles are in radians with 0 sticking straight out the front. Rotating
+  // up and into the robot is positive. Positive output voltage moves in the
+  // direction of positive encoder values.
+
+  message Goal {
+    // Angle of wrist joint.
+    double angle;
+    // Angular velocity of wrist.
+    float angular_velocity;
+    // Maximum profile velocity, or 0 for the default.
+    float max_velocity;
+    // Maximum profile acceleration, or 0 for the default.
+    float max_acceleration;
+    // Voltage of intake rollers. Positive means sucking in, negative means
+    // spitting out.
+    double intake;
+
+    // true to signal the rollers to close.
+    bool rollers_closed;
+  };
+
+  message Position {
+    PotAndIndexPosition joint;
+  };
+
+  message Output {
+    // Voltage for intake motors. Positive is sucking in, negative is spitting
+    // out.
+    double intake_voltage;
+    // Voltage for claw motor.
+    double voltage;
+
+    // true to signal the rollers to close.
+    bool rollers_closed;
+  };
+
+  message Status {
+    // Is claw zeroed?
+    bool zeroed;
+    // Did the claw estop?
+    bool estopped;
+    // The internal state of the claw state machine.
+    uint32_t state;
+    EstimatorState zeroing_state;
+
+    // Estimated angle of wrist joint.
+    double angle;
+    // Estimated angular velocity of wrist.
+    float angular_velocity;
+
+    // Goal angle of wrist joint.
+    double goal_angle;
+    float goal_velocity;
+    // Voltage of intake rollers. Positive means sucking in, negative means
+    // spitting out.
+    double intake;
+
+    // True iff there has been enough time since we actuated the rollers outward
+    // that they should be there.
+    bool rollers_open;
+    // True iff there has been enough time since we actuated the rollers closed
+    // that they should be there.
+    bool rollers_closed;
+  };
+
+  queue Goal goal;
+  queue Position position;
+  queue Output output;
+  queue Status status;
+};
+
+queue_group ClawQueue claw_queue;
+
diff --git a/y2015/control_loops/claw/claw_lib_test.cc b/y2015/control_loops/claw/claw_lib_test.cc
new file mode 100644
index 0000000..10fcc07
--- /dev/null
+++ b/y2015/control_loops/claw/claw_lib_test.cc
@@ -0,0 +1,347 @@
+#include <math.h>
+#include <unistd.h>
+
+#include <memory>
+
+#include "gtest/gtest.h"
+#include "aos/common/queue.h"
+#include "aos/common/time.h"
+#include "aos/common/controls/control_loop_test.h"
+#include "y2015/control_loops/claw/claw.q.h"
+#include "y2015/control_loops/claw/claw.h"
+#include "frc971/control_loops/position_sensor_sim.h"
+#include "y2015/constants.h"
+#include "frc971/control_loops/team_number_test_environment.h"
+
+using ::aos::time::Time;
+
+namespace frc971 {
+namespace control_loops {
+namespace testing {
+
+// Class which simulates the claw and sends out queue messages with the
+// position.
+class ClawSimulation {
+ public:
+  // Constructs a claw simulation.
+  ClawSimulation()
+      : claw_plant_(new StateFeedbackPlant<2, 1, 1>(MakeClawPlant())),
+        pot_and_encoder_(constants::GetValues().claw.zeroing.index_difference),
+        claw_queue_(".frc971.control_loops.claw_queue", 0x9d7452fb,
+                    ".frc971.control_loops.claw_queue.goal",
+                    ".frc971.control_loops.claw_queue.position",
+                    ".frc971.control_loops.claw_queue.output",
+                    ".frc971.control_loops.claw_queue.status") {
+    InitializePosition(constants::GetValues().claw.wrist.lower_limit);
+  }
+
+  void InitializePosition(double start_pos) {
+    InitializePosition(start_pos,
+        constants::GetValues().claw.zeroing.measured_index_position);
+  }
+
+  void InitializePosition(double start_pos, double index_pos) {
+    InitializePosition(start_pos,
+        // This gives us a standard deviation of ~9 degrees on the pot noise.
+        constants::GetValues().claw.zeroing.index_difference / 10.0,
+        index_pos);
+  }
+
+  // Do specific initialization for the sensors.
+  void InitializePosition(double start_pos,
+                         double pot_noise_stddev,
+                         double index_pos) {
+    // Update internal state.
+    claw_plant_->mutable_X(0, 0) = start_pos;
+    // Zero velocity.
+    claw_plant_->mutable_X(1, 0) = 0.0;
+
+    pot_and_encoder_.Initialize(start_pos, pot_noise_stddev, index_pos);
+  }
+
+  // Sends a queue message with the position.
+  void SendPositionMessage() {
+    ::aos::ScopedMessagePtr<control_loops::ClawQueue::Position> position =
+      claw_queue_.position.MakeMessage();
+    pot_and_encoder_.GetSensorValues(&position->joint);
+    position.Send();
+  }
+
+  // Simulates for a single timestep.
+  void Simulate() {
+    EXPECT_TRUE(claw_queue_.output.FetchLatest());
+
+    // Feed voltages into physics simulation.
+    claw_plant_->mutable_U() << claw_queue_.output->voltage;
+    claw_plant_->Update();
+
+    const double wrist_angle = claw_plant_->Y(0, 0);
+
+    // TODO(danielp): Sanity checks.
+
+    pot_and_encoder_.MoveTo(wrist_angle);
+  }
+
+ private:
+  ::std::unique_ptr<StateFeedbackPlant<2, 1, 1>> claw_plant_;
+  PositionSensorSimulator pot_and_encoder_;
+
+  ClawQueue claw_queue_;
+};
+
+class ClawTest : public ::aos::testing::ControlLoopTest {
+ protected:
+  ClawTest()
+      : claw_queue_(".frc971.control_loops.claw_queue", 0x9d7452fb,
+                    ".frc971.control_loops.claw_queue.goal",
+                    ".frc971.control_loops.claw_queue.position",
+                    ".frc971.control_loops.claw_queue.output",
+                    ".frc971.control_loops.claw_queue.status"),
+        claw_(&claw_queue_),
+        claw_plant_() {
+    set_team_id(kTeamNumber);
+  }
+
+  void VerifyNearGoal() {
+    claw_queue_.goal.FetchLatest();
+    claw_queue_.status.FetchLatest();
+    EXPECT_NEAR(claw_queue_.goal->angle,
+                claw_queue_.status->angle,
+                10.0);
+
+    EXPECT_TRUE(claw_queue_.status->zeroed);
+    EXPECT_FALSE(claw_queue_.status->estopped);
+  }
+
+  // Runs one iteration of the whole simulation.
+  void RunIteration(bool enabled = true) {
+    SendMessages(enabled);
+
+    claw_plant_.SendPositionMessage();
+    claw_.Iterate();
+    claw_plant_.Simulate();
+
+    TickTime();
+  }
+
+  // Runs iterations until the specified amount of simulated time has elapsed.
+  void RunForTime(const Time &run_for, bool enabled = true) {
+    const auto start_time = Time::Now();
+    while (Time::Now() < start_time + run_for) {
+      RunIteration(enabled);
+    }
+  }
+
+  // Create a new instance of the test queue so that it invalidates the queue
+  // that it points to.  Otherwise, we will have a pointed to
+  // shared memory that is no longer valid.
+  ClawQueue claw_queue_;
+
+  // Create a control loop and simulation.
+  Claw claw_;
+  ClawSimulation claw_plant_;
+};
+
+// Tests that the loop does nothing when the goal is our lower limit.
+TEST_F(ClawTest, DoesNothing) {
+  const auto &values = constants::GetValues();
+  ASSERT_TRUE(claw_queue_.goal.MakeWithBuilder()
+      .angle(values.claw.wrist.lower_limit)
+      .Send());
+
+  RunForTime(Time::InSeconds(6));
+
+  // We should not have moved.
+  VerifyNearGoal();
+}
+
+// NOTE: Claw zeroing is a little annoying because we only hit one index pulse
+// in our entire range of motion.
+
+// Tests that the loop zeroing works with normal values.
+TEST_F(ClawTest, Zeroes) {
+  // It should zero itself if we run it for awhile.
+  ASSERT_TRUE(claw_queue_.goal.MakeWithBuilder()
+      .angle(M_PI / 4.0)
+      .Send());
+
+  RunForTime(Time::InSeconds(6));
+
+  ASSERT_TRUE(claw_queue_.status.FetchLatest());
+  EXPECT_TRUE(claw_queue_.status->zeroed);
+  EXPECT_EQ(Claw::RUNNING, claw_queue_.status->state);
+}
+
+// Tests that claw zeroing fails if the index pulse occurs too close to the end
+// of the range.
+TEST_F(ClawTest, BadIndexPosition) {
+  const auto values = constants::GetValues();
+  claw_plant_.InitializePosition(values.claw.wrist.lower_limit,
+                                 values.claw.wrist.upper_limit);
+
+  ASSERT_TRUE(claw_queue_.goal.MakeWithBuilder()
+      .angle(M_PI / 4.0)
+      .Send());
+
+  // The zeroing is going to take its sweet time on this one, so we had better
+  // run it for longer.
+  RunForTime(Time::InMS(12000));
+
+  ASSERT_TRUE(claw_queue_.status.FetchLatest());
+  EXPECT_FALSE(claw_queue_.status->zeroed);
+  EXPECT_FALSE(claw_queue_.status->estopped);
+}
+
+// Tests that we can reach a reasonable goal.
+TEST_F(ClawTest, ReachesGoal) {
+  ASSERT_TRUE(claw_queue_.goal.MakeWithBuilder()
+      .angle(M_PI / 4.0)
+      .Send());
+
+  RunForTime(Time::InSeconds(6));
+
+  VerifyNearGoal();
+}
+
+// Tests that it doesn't try to move past the physical range of the mechanism.
+TEST_F(ClawTest, RespectsRange) {
+  const auto &values = constants::GetValues();
+  // Upper limit
+  ASSERT_TRUE(claw_queue_.goal.MakeWithBuilder()
+      .angle(values.claw.wrist.upper_hard_limit + 5.0)
+      .Send());
+
+  RunForTime(Time::InSeconds(7));
+
+  claw_queue_.status.FetchLatest();
+  EXPECT_NEAR(values.claw.wrist.upper_limit,
+              claw_queue_.status->angle,
+              2.0 * M_PI / 180.0);
+
+  // Lower limit.
+  ASSERT_TRUE(claw_queue_.goal.MakeWithBuilder()
+      .angle(values.claw.wrist.lower_hard_limit - 5.0)
+      .Send());
+
+  RunForTime(Time::InMS(6000));
+
+  claw_queue_.status.FetchLatest();
+  EXPECT_NEAR(values.claw.wrist.lower_limit,
+              claw_queue_.status->angle,
+              2.0 * M_PI / 180.0);
+}
+
+// Tests that starting at the lower hardstop doesn't cause an abort.
+TEST_F(ClawTest, LowerHardstopStartup) {
+  claw_plant_.InitializePosition(
+      constants::GetValues().claw.wrist.lower_hard_limit);
+  ASSERT_TRUE(claw_queue_.goal.MakeWithBuilder()
+      .angle(M_PI / 4.0)
+      .Send());
+  RunForTime(Time::InSeconds(6));
+
+  VerifyNearGoal();
+}
+
+// Tests that starting at the upper hardstop doesn't cause an abort.
+TEST_F(ClawTest, UpperHardstopStartup) {
+  claw_plant_.InitializePosition(
+      constants::GetValues().claw.wrist.upper_hard_limit);
+  ASSERT_TRUE(claw_queue_.goal.MakeWithBuilder()
+      .angle(M_PI / 4.0)
+      .Send());
+  // Zeroing will take a long time here.
+  RunForTime(Time::InSeconds(15));
+
+  VerifyNearGoal();
+}
+
+
+// Tests that not having a goal doesn't break anything.
+TEST_F(ClawTest, NoGoal) {
+  RunForTime(Time::InMS(50));
+}
+
+// Tests that a WPILib reset results in rezeroing.
+TEST_F(ClawTest, WpilibReset) {
+  ASSERT_TRUE(claw_queue_.goal.MakeWithBuilder()
+      .angle(M_PI / 4.0)
+      .Send());
+
+  RunForTime(Time::InSeconds(6));
+  VerifyNearGoal();
+
+  SimulateSensorReset();
+  RunForTime(Time::InMS(100));
+  ASSERT_TRUE(claw_queue_.status.FetchLatest());
+  EXPECT_NE(Claw::RUNNING, claw_queue_.status->state);
+
+  // Once again, it's going to take us awhile to rezero since we moved away from
+  // our index pulse.
+  RunForTime(Time::InSeconds(6));
+  VerifyNearGoal();
+}
+
+// Tests that internal goals don't change while disabled.
+TEST_F(ClawTest, DisabledGoal) {
+  ASSERT_TRUE(claw_queue_.goal.MakeWithBuilder()
+      .angle(M_PI / 4.0)
+      .Send());
+
+  RunForTime(Time::InMS(100), false);
+  EXPECT_EQ(0.0, claw_.claw_goal_);
+
+  // Now make sure they move correctly.
+  RunForTime(Time::InMS(1000), true);
+  EXPECT_NE(0.0, claw_.claw_goal_);
+}
+
+// Tests that the claw zeroing goals don't wind up too far.
+TEST_F(ClawTest, GoalPositiveWindup) {
+  ASSERT_TRUE(claw_queue_.goal.MakeWithBuilder()
+      .angle(M_PI / 4.0)
+      .Send());
+
+  while (claw_.state() != Claw::ZEROING) {
+    RunIteration();
+  }
+
+  // Kick it.
+  RunForTime(Time::InMS(50));
+  const double orig_claw_goal = claw_.claw_goal_;
+  claw_.claw_goal_ += 100.0;
+
+  RunIteration();
+  EXPECT_NEAR(orig_claw_goal, claw_.claw_goal_, 0.10);
+
+  RunIteration();
+
+  EXPECT_EQ(claw_.claw_loop_->U(), claw_.claw_loop_->U_uncapped());
+}
+
+// Tests that the claw zeroing goals don't wind up too far.
+TEST_F(ClawTest, GoalNegativeWindup) {
+  ASSERT_TRUE(claw_queue_.goal.MakeWithBuilder()
+      .angle(M_PI / 4.0)
+      .Send());
+
+  while (claw_.state() != Claw::ZEROING) {
+    RunIteration();
+  }
+
+  // Kick it.
+  RunForTime(Time::InMS(50));
+  double orig_claw_goal = claw_.claw_goal_;
+  claw_.claw_goal_ -= 100.0;
+
+  RunIteration();
+  EXPECT_NEAR(orig_claw_goal, claw_.claw_goal_, 0.10);
+
+  RunIteration();
+
+  EXPECT_EQ(claw_.claw_loop_->U(), claw_.claw_loop_->U_uncapped());
+}
+
+}  // namespace testing
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/y2015/control_loops/claw/claw_main.cc b/y2015/control_loops/claw/claw_main.cc
new file mode 100644
index 0000000..d1b869c
--- /dev/null
+++ b/y2015/control_loops/claw/claw_main.cc
@@ -0,0 +1,11 @@
+#include "y2015/control_loops/claw/claw.h"
+
+#include "aos/linux_code/init.h"
+
+int main() {
+  ::aos::Init();
+  frc971::control_loops::Claw claw;
+  claw.Run();
+  ::aos::Cleanup();
+  return 0;
+}
diff --git a/y2015/control_loops/claw/claw_motor_plant.cc b/y2015/control_loops/claw/claw_motor_plant.cc
new file mode 100644
index 0000000..5f5c206
--- /dev/null
+++ b/y2015/control_loops/claw/claw_motor_plant.cc
@@ -0,0 +1,49 @@
+#include "y2015/control_loops/claw/claw_motor_plant.h"
+
+#include <vector>
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace frc971 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<2, 1, 1> MakeClawPlantCoefficients() {
+  Eigen::Matrix<double, 2, 2> A;
+  A << 1.0, 0.00482455476758, 0.0, 0.930652495326;
+  Eigen::Matrix<double, 2, 1> B;
+  B << 6.97110924671e-05, 0.0275544125308;
+  Eigen::Matrix<double, 1, 2> C;
+  C << 1, 0;
+  Eigen::Matrix<double, 1, 1> D;
+  D << 0;
+  Eigen::Matrix<double, 1, 1> U_max;
+  U_max << 12.0;
+  Eigen::Matrix<double, 1, 1> U_min;
+  U_min << -12.0;
+  return StateFeedbackPlantCoefficients<2, 1, 1>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackController<2, 1, 1> MakeClawController() {
+  Eigen::Matrix<double, 2, 1> L;
+  L << 0.998251427366, 26.9874526231;
+  Eigen::Matrix<double, 1, 2> K;
+  K << 74.4310031124, 4.72251126222;
+  Eigen::Matrix<double, 2, 2> A_inv;
+  A_inv << 1.0, -0.00518405612386, 0.0, 1.07451492907;
+  return StateFeedbackController<2, 1, 1>(L, K, A_inv, MakeClawPlantCoefficients());
+}
+
+StateFeedbackPlant<2, 1, 1> MakeClawPlant() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackPlantCoefficients<2, 1, 1>>> plants(1);
+  plants[0] = ::std::unique_ptr<StateFeedbackPlantCoefficients<2, 1, 1>>(new StateFeedbackPlantCoefficients<2, 1, 1>(MakeClawPlantCoefficients()));
+  return StateFeedbackPlant<2, 1, 1>(&plants);
+}
+
+StateFeedbackLoop<2, 1, 1> MakeClawLoop() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackController<2, 1, 1>>> controllers(1);
+  controllers[0] = ::std::unique_ptr<StateFeedbackController<2, 1, 1>>(new StateFeedbackController<2, 1, 1>(MakeClawController()));
+  return StateFeedbackLoop<2, 1, 1>(&controllers);
+}
+
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/y2015/control_loops/claw/claw_motor_plant.h b/y2015/control_loops/claw/claw_motor_plant.h
new file mode 100644
index 0000000..6cb9cdb
--- /dev/null
+++ b/y2015/control_loops/claw/claw_motor_plant.h
@@ -0,0 +1,20 @@
+#ifndef Y2015_CONTROL_LOOPS_CLAW_CLAW_MOTOR_PLANT_H_
+#define Y2015_CONTROL_LOOPS_CLAW_CLAW_MOTOR_PLANT_H_
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace frc971 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<2, 1, 1> MakeClawPlantCoefficients();
+
+StateFeedbackController<2, 1, 1> MakeClawController();
+
+StateFeedbackPlant<2, 1, 1> MakeClawPlant();
+
+StateFeedbackLoop<2, 1, 1> MakeClawLoop();
+
+}  // namespace control_loops
+}  // namespace frc971
+
+#endif  // Y2015_CONTROL_LOOPS_CLAW_CLAW_MOTOR_PLANT_H_
diff --git a/y2015/control_loops/claw/replay_claw.cc b/y2015/control_loops/claw/replay_claw.cc
new file mode 100644
index 0000000..50673e4
--- /dev/null
+++ b/y2015/control_loops/claw/replay_claw.cc
@@ -0,0 +1,24 @@
+#include "aos/common/controls/replay_control_loop.h"
+#include "aos/linux_code/init.h"
+
+#include "y2015/control_loops/claw/claw.q.h"
+
+// Reads one or more log files and sends out all the queue messages (in the
+// correct order and at the correct time) to feed a "live" claw process.
+
+int main(int argc, char **argv) {
+  if (argc <= 1) {
+    fprintf(stderr, "Need at least one file to replay!\n");
+    return EXIT_FAILURE;
+  }
+
+  ::aos::InitNRT();
+
+  ::aos::controls::ControlLoopReplayer<::frc971::control_loops::ClawQueue>
+      replayer(&::frc971::control_loops::claw_queue, "claw");
+  for (int i = 1; i < argc; ++i) {
+    replayer.ProcessFile(argv[i]);
+  }
+
+  ::aos::Cleanup();
+}
diff --git a/y2015/control_loops/drivetrain/drivetrain.cc b/y2015/control_loops/drivetrain/drivetrain.cc
new file mode 100644
index 0000000..22a5d48
--- /dev/null
+++ b/y2015/control_loops/drivetrain/drivetrain.cc
@@ -0,0 +1,777 @@
+#include "y2015/control_loops/drivetrain/drivetrain.h"
+
+#include <stdio.h>
+#include <sched.h>
+#include <cmath>
+#include <memory>
+#include "Eigen/Dense"
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/controls/polytope.h"
+#include "aos/common/commonmath.h"
+#include "aos/common/logging/queue_logging.h"
+#include "aos/common/logging/matrix_logging.h"
+
+#include "y2015/constants.h"
+#include "frc971/control_loops/state_feedback_loop.h"
+#include "frc971/control_loops/coerce_goal.h"
+#include "y2015/control_loops/drivetrain/polydrivetrain_cim_plant.h"
+#include "y2015/control_loops/drivetrain/drivetrain.q.h"
+#include "frc971/queues/gyro.q.h"
+#include "frc971/shifter_hall_effect.h"
+
+// A consistent way to mark code that goes away without shifters. It's still
+// here because we will have shifters again in the future.
+#define HAVE_SHIFTERS 0
+
+using frc971::sensors::gyro_reading;
+
+namespace frc971 {
+namespace control_loops {
+
+class DrivetrainMotorsSS {
+ public:
+  class LimitedDrivetrainLoop : public StateFeedbackLoop<4, 2, 2> {
+   public:
+    LimitedDrivetrainLoop(StateFeedbackLoop<4, 2, 2> &&loop)
+        : StateFeedbackLoop<4, 2, 2>(::std::move(loop)),
+        U_Poly_((Eigen::Matrix<double, 4, 2>() << 1, 0,
+                 -1, 0,
+                 0, 1,
+                 0, -1).finished(),
+                (Eigen::Matrix<double, 4, 1>() << 12.0, 12.0,
+                 12.0, 12.0).finished()) {
+      ::aos::controls::HPolytope<0>::Init();
+      T << 1, -1, 1, 1;
+      T_inverse = T.inverse();
+    }
+
+    bool output_was_capped() const {
+      return output_was_capped_;
+    }
+
+   private:
+    virtual void CapU() {
+      const Eigen::Matrix<double, 4, 1> error = R() - X_hat();
+
+      if (::std::abs(U(0, 0)) > 12.0 || ::std::abs(U(1, 0)) > 12.0) {
+        mutable_U() =
+            U() * 12.0 / ::std::max(::std::abs(U(0, 0)), ::std::abs(U(1, 0)));
+        LOG_MATRIX(DEBUG, "U is now", U());
+        // TODO(Austin): Figure out why the polytope stuff wasn't working and
+        // remove this hack.
+        output_was_capped_ = true;
+        return;
+
+        LOG_MATRIX(DEBUG, "U at start", U());
+        LOG_MATRIX(DEBUG, "R at start", R());
+        LOG_MATRIX(DEBUG, "Xhat at start", X_hat());
+
+        Eigen::Matrix<double, 2, 2> position_K;
+        position_K << K(0, 0), K(0, 2),
+                   K(1, 0), K(1, 2);
+        Eigen::Matrix<double, 2, 2> velocity_K;
+        velocity_K << K(0, 1), K(0, 3),
+                   K(1, 1), K(1, 3);
+
+        Eigen::Matrix<double, 2, 1> position_error;
+        position_error << error(0, 0), error(2, 0);
+        const auto drive_error = T_inverse * position_error;
+        Eigen::Matrix<double, 2, 1> velocity_error;
+        velocity_error << error(1, 0), error(3, 0);
+        LOG_MATRIX(DEBUG, "error", error);
+
+        const auto &poly = U_Poly_;
+        const Eigen::Matrix<double, 4, 2> pos_poly_H =
+            poly.H() * position_K * T;
+        const Eigen::Matrix<double, 4, 1> pos_poly_k =
+            poly.k() - poly.H() * velocity_K * velocity_error;
+        const ::aos::controls::HPolytope<2> pos_poly(pos_poly_H, pos_poly_k);
+
+        Eigen::Matrix<double, 2, 1> adjusted_pos_error;
+        {
+          const auto &P = drive_error;
+
+          Eigen::Matrix<double, 1, 2> L45;
+          L45 << ::aos::sign(P(1, 0)), -::aos::sign(P(0, 0));
+          const double w45 = 0;
+
+          Eigen::Matrix<double, 1, 2> LH;
+          if (::std::abs(P(0, 0)) > ::std::abs(P(1, 0))) {
+            LH << 0, 1;
+          } else {
+            LH << 1, 0;
+          }
+          const double wh = LH.dot(P);
+
+          Eigen::Matrix<double, 2, 2> standard;
+          standard << L45, LH;
+          Eigen::Matrix<double, 2, 1> W;
+          W << w45, wh;
+          const Eigen::Matrix<double, 2, 1> intersection =
+              standard.inverse() * W;
+
+          bool is_inside_h;
+          const auto adjusted_pos_error_h =
+              DoCoerceGoal(pos_poly, LH, wh, drive_error, &is_inside_h);
+          const auto adjusted_pos_error_45 =
+              DoCoerceGoal(pos_poly, L45, w45, intersection, nullptr);
+          if (pos_poly.IsInside(intersection)) {
+            adjusted_pos_error = adjusted_pos_error_h;
+          } else {
+            if (is_inside_h) {
+              if (adjusted_pos_error_h.norm() > adjusted_pos_error_45.norm()) {
+                adjusted_pos_error = adjusted_pos_error_h;
+              } else {
+                adjusted_pos_error = adjusted_pos_error_45;
+              }
+            } else {
+              adjusted_pos_error = adjusted_pos_error_45;
+            }
+          }
+        }
+
+        LOG_MATRIX(DEBUG, "adjusted_pos_error", adjusted_pos_error);
+        mutable_U() =
+            velocity_K * velocity_error + position_K * T * adjusted_pos_error;
+        LOG_MATRIX(DEBUG, "U is now", U());
+      } else {
+        output_was_capped_ = false;
+      }
+    }
+
+    const ::aos::controls::HPolytope<2> U_Poly_;
+    Eigen::Matrix<double, 2, 2> T, T_inverse;
+    bool output_was_capped_ = false;;
+  };
+
+  DrivetrainMotorsSS()
+      : loop_(new LimitedDrivetrainLoop(
+            constants::GetValues().make_drivetrain_loop())),
+        filtered_offset_(0.0),
+        gyro_(0.0),
+        left_goal_(0.0),
+        right_goal_(0.0),
+        raw_left_(0.0),
+        raw_right_(0.0) {
+    // Low gear on both.
+    loop_->set_controller_index(0);
+  }
+
+  void SetGoal(double left, double left_velocity, double right,
+               double right_velocity) {
+    left_goal_ = left;
+    right_goal_ = right;
+    loop_->mutable_R() << left, left_velocity, right, right_velocity;
+  }
+  void SetRawPosition(double left, double right) {
+    raw_right_ = right;
+    raw_left_ = left;
+    Eigen::Matrix<double, 2, 1> Y;
+    Y << left + filtered_offset_, right - filtered_offset_;
+    loop_->Correct(Y);
+  }
+  void SetPosition(double left, double right, double gyro) {
+    // Decay the offset quickly because this gyro is great.
+    const double offset =
+        (right - left - gyro * constants::GetValues().turn_width) / 2.0;
+    filtered_offset_ = 0.25 * offset + 0.75 * filtered_offset_;
+    gyro_ = gyro;
+    SetRawPosition(left, right);
+  }
+
+  void SetExternalMotors(double left_voltage, double right_voltage) {
+    loop_->mutable_U() << left_voltage, right_voltage;
+  }
+
+  void Update(bool stop_motors, bool enable_control_loop) {
+    if (enable_control_loop) {
+      loop_->Update(stop_motors);
+    } else {
+      if (stop_motors) {
+        loop_->mutable_U().setZero();
+        loop_->mutable_U_uncapped().setZero();
+      }
+      loop_->UpdateObserver();
+    }
+    ::Eigen::Matrix<double, 4, 1> E = loop_->R() - loop_->X_hat();
+    LOG_MATRIX(DEBUG, "E", E);
+  }
+
+  double GetEstimatedRobotSpeed() const {
+    // lets just call the average of left and right velocities close enough
+    return (loop_->X_hat(1, 0) + loop_->X_hat(3, 0)) / 2;
+  }
+
+  double GetEstimatedLeftEncoder() const {
+    return loop_->X_hat(0, 0);
+  }
+
+  double GetEstimatedRightEncoder() const {
+    return loop_->X_hat(2, 0);
+  }
+
+  bool OutputWasCapped() const {
+    return loop_->output_was_capped();
+  }
+
+  void SendMotors(DrivetrainQueue::Output *output) const {
+    if (output) {
+      output->left_voltage = loop_->U(0, 0);
+      output->right_voltage = loop_->U(1, 0);
+      output->left_high = false;
+      output->right_high = false;
+    }
+  }
+
+  const LimitedDrivetrainLoop &loop() const { return *loop_; }
+
+ private:
+  ::std::unique_ptr<LimitedDrivetrainLoop> loop_;
+
+  double filtered_offset_;
+  double gyro_;
+  double left_goal_;
+  double right_goal_;
+  double raw_left_;
+  double raw_right_;
+};
+
+class PolyDrivetrain {
+ public:
+
+  enum Gear {
+    HIGH,
+    LOW,
+    SHIFTING_UP,
+    SHIFTING_DOWN
+  };
+  // Stall Torque in N m
+  static constexpr double kStallTorque = 2.42;
+  // Stall Current in Amps
+  static constexpr double kStallCurrent = 133.0;
+  // Free Speed in RPM. Used number from last year.
+  static constexpr double kFreeSpeed = 4650.0;
+  // Free Current in Amps
+  static constexpr double kFreeCurrent = 2.7;
+  // Moment of inertia of the drivetrain in kg m^2
+  // Just borrowed from last year.
+  static constexpr double J = 10;
+  // Mass of the robot, in kg.
+  static constexpr double m = 68;
+  // Radius of the robot, in meters (from last year).
+  static constexpr double rb = 0.9603 / 2.0;
+  static constexpr double kWheelRadius = 0.0515938;
+  // Resistance of the motor, divided by the number of motors.
+  static constexpr double kR = (12.0 / kStallCurrent / 2 + 0.03) / (0.93 * 0.93);
+  // Motor velocity constant
+  static constexpr double Kv =
+      ((kFreeSpeed / 60.0 * 2.0 * M_PI) / (12.0 - kR * kFreeCurrent));
+  // Torque constant
+  static constexpr double Kt = kStallTorque / kStallCurrent;
+
+  PolyDrivetrain()
+      : U_Poly_((Eigen::Matrix<double, 4, 2>() << /*[[*/ 1, 0 /*]*/,
+                 /*[*/ -1, 0 /*]*/,
+                 /*[*/ 0, 1 /*]*/,
+                 /*[*/ 0, -1 /*]]*/).finished(),
+                (Eigen::Matrix<double, 4, 1>() << /*[[*/ 12 /*]*/,
+                 /*[*/ 12 /*]*/,
+                 /*[*/ 12 /*]*/,
+                 /*[*/ 12 /*]]*/).finished()),
+        loop_(new StateFeedbackLoop<2, 2, 2>(
+            constants::GetValues().make_v_drivetrain_loop())),
+        ttrust_(1.1),
+        wheel_(0.0),
+        throttle_(0.0),
+        quickturn_(false),
+        stale_count_(0),
+        position_time_delta_(0.01),
+        left_gear_(LOW),
+        right_gear_(LOW),
+        counter_(0) {
+
+    last_position_.Zero();
+    position_.Zero();
+  }
+  static bool IsInGear(Gear gear) { return gear == LOW || gear == HIGH; }
+
+  static double MotorSpeed(const constants::ShifterHallEffect &hall_effect,
+                           double shifter_position, double velocity) {
+    // TODO(austin): G_high, G_low and kWheelRadius
+    const double avg_hall_effect =
+        (hall_effect.clear_high + hall_effect.clear_low) / 2.0;
+
+    if (shifter_position > avg_hall_effect) {
+      return velocity / constants::GetValues().high_gear_ratio / kWheelRadius;
+    } else {
+      return velocity / constants::GetValues().low_gear_ratio / kWheelRadius;
+    }
+  }
+
+  Gear ComputeGear(const constants::ShifterHallEffect &hall_effect,
+                   double velocity, Gear current) {
+    const double low_omega = MotorSpeed(hall_effect, 0.0, ::std::abs(velocity));
+    const double high_omega =
+        MotorSpeed(hall_effect, 1.0, ::std::abs(velocity));
+
+    double high_torque = ((12.0 - high_omega / Kv) * Kt / kR);
+    double low_torque = ((12.0 - low_omega / Kv) * Kt / kR);
+    double high_power = high_torque * high_omega;
+    double low_power = low_torque * low_omega;
+
+    // TODO(aschuh): Do this right!
+    if ((current == HIGH || high_power > low_power + 160) &&
+        ::std::abs(velocity) > 0.14) {
+      return HIGH;
+    } else {
+      return LOW;
+    }
+  }
+
+  void SetGoal(double wheel, double throttle, bool quickturn, bool highgear) {
+    const double kWheelNonLinearity = 0.5;
+    // Apply a sin function that's scaled to make it feel better.
+    const double angular_range = M_PI_2 * kWheelNonLinearity;
+
+    wheel_ = sin(angular_range * wheel) / sin(angular_range);
+    wheel_ = sin(angular_range * wheel_) / sin(angular_range);
+    wheel_ *= 2.3;
+    quickturn_ = quickturn;
+
+    static const double kThrottleDeadband = 0.05;
+    if (::std::abs(throttle) < kThrottleDeadband) {
+      throttle_ = 0;
+    } else {
+      throttle_ = copysign((::std::abs(throttle) - kThrottleDeadband) /
+                           (1.0 - kThrottleDeadband), throttle);
+    }
+
+    // TODO(austin): Fix the upshift logic to include states.
+    Gear requested_gear;
+    if (false) {
+      const auto &values = constants::GetValues();
+      const double current_left_velocity =
+          (position_.left_encoder - last_position_.left_encoder) /
+          position_time_delta_;
+      const double current_right_velocity =
+          (position_.right_encoder - last_position_.right_encoder) /
+          position_time_delta_;
+
+      Gear left_requested =
+          ComputeGear(values.left_drive, current_left_velocity, left_gear_);
+      Gear right_requested =
+          ComputeGear(values.right_drive, current_right_velocity, right_gear_);
+      requested_gear =
+          (left_requested == HIGH || right_requested == HIGH) ? HIGH : LOW;
+    } else {
+      requested_gear = highgear ? HIGH : LOW;
+    }
+
+    const Gear shift_up =
+        constants::GetValues().clutch_transmission ? HIGH : SHIFTING_UP;
+    const Gear shift_down =
+        constants::GetValues().clutch_transmission ? LOW : SHIFTING_DOWN;
+
+    if (left_gear_ != requested_gear) {
+      if (IsInGear(left_gear_)) {
+        if (requested_gear == HIGH) {
+          left_gear_ = shift_up;
+        } else {
+          left_gear_ = shift_down;
+        }
+      } else {
+        if (requested_gear == HIGH && left_gear_ == SHIFTING_DOWN) {
+          left_gear_ = SHIFTING_UP;
+        } else if (requested_gear == LOW && left_gear_ == SHIFTING_UP) {
+          left_gear_ = SHIFTING_DOWN;
+        }
+      }
+    }
+    if (right_gear_ != requested_gear) {
+      if (IsInGear(right_gear_)) {
+        if (requested_gear == HIGH) {
+          right_gear_ = shift_up;
+        } else {
+          right_gear_ = shift_down;
+        }
+      } else {
+        if (requested_gear == HIGH && right_gear_ == SHIFTING_DOWN) {
+          right_gear_ = SHIFTING_UP;
+        } else if (requested_gear == LOW && right_gear_ == SHIFTING_UP) {
+          right_gear_ = SHIFTING_DOWN;
+        }
+      }
+    }
+  }
+  void SetPosition(const DrivetrainQueue::Position *position) {
+    const auto &values = constants::GetValues();
+    if (position == NULL) {
+      ++stale_count_;
+    } else {
+      last_position_ = position_;
+      position_ = *position;
+      position_time_delta_ = (stale_count_ + 1) * 0.01;
+      stale_count_ = 0;
+    }
+
+#if HAVE_SHIFTERS
+    if (position) {
+      GearLogging gear_logging;
+      // Switch to the correct controller.
+      const double left_middle_shifter_position =
+          (values.left_drive.clear_high + values.left_drive.clear_low) / 2.0;
+      const double right_middle_shifter_position =
+          (values.right_drive.clear_high + values.right_drive.clear_low) / 2.0;
+
+      if (position->left_shifter_position < left_middle_shifter_position ||
+          left_gear_ == LOW) {
+        if (position->right_shifter_position < right_middle_shifter_position ||
+            right_gear_ == LOW) {
+          gear_logging.left_loop_high = false;
+          gear_logging.right_loop_high = false;
+          loop_->set_controller_index(gear_logging.controller_index = 0);
+        } else {
+          gear_logging.left_loop_high = false;
+          gear_logging.right_loop_high = true;
+          loop_->set_controller_index(gear_logging.controller_index = 1);
+        }
+      } else {
+        if (position->right_shifter_position < right_middle_shifter_position ||
+            right_gear_ == LOW) {
+          gear_logging.left_loop_high = true;
+          gear_logging.right_loop_high = false;
+          loop_->set_controller_index(gear_logging.controller_index = 2);
+        } else {
+          gear_logging.left_loop_high = true;
+          gear_logging.right_loop_high = true;
+          loop_->set_controller_index(gear_logging.controller_index = 3);
+        }
+      }
+
+      // TODO(austin): Constants.
+      if (position->left_shifter_position > values.left_drive.clear_high && left_gear_ == SHIFTING_UP) {
+        left_gear_ = HIGH;
+      }
+      if (position->left_shifter_position < values.left_drive.clear_low && left_gear_ == SHIFTING_DOWN) {
+        left_gear_ = LOW;
+      }
+      if (position->right_shifter_position > values.right_drive.clear_high && right_gear_ == SHIFTING_UP) {
+        right_gear_ = HIGH;
+      }
+      if (position->right_shifter_position < values.right_drive.clear_low && right_gear_ == SHIFTING_DOWN) {
+        right_gear_ = LOW;
+      }
+
+      gear_logging.left_state = left_gear_;
+      gear_logging.right_state = right_gear_;
+      LOG_STRUCT(DEBUG, "state", gear_logging);
+    }
+#else
+    (void) values;
+#endif
+  }
+
+  double FilterVelocity(double throttle) {
+    const Eigen::Matrix<double, 2, 2> FF =
+        loop_->B().inverse() *
+        (Eigen::Matrix<double, 2, 2>::Identity() - loop_->A());
+
+    constexpr int kHighGearController = 3;
+    const Eigen::Matrix<double, 2, 2> FF_high =
+        loop_->controller(kHighGearController).plant.B().inverse() *
+        (Eigen::Matrix<double, 2, 2>::Identity() -
+         loop_->controller(kHighGearController).plant.A());
+
+    ::Eigen::Matrix<double, 1, 2> FF_sum = FF.colwise().sum();
+    int min_FF_sum_index;
+    const double min_FF_sum = FF_sum.minCoeff(&min_FF_sum_index);
+    const double min_K_sum = loop_->K().col(min_FF_sum_index).sum();
+    const double high_min_FF_sum = FF_high.col(0).sum();
+
+    const double adjusted_ff_voltage = ::aos::Clip(
+        throttle * 12.0 * min_FF_sum / high_min_FF_sum, -12.0, 12.0);
+    return (adjusted_ff_voltage +
+            ttrust_ * min_K_sum * (loop_->X_hat(0, 0) + loop_->X_hat(1, 0)) /
+                2.0) /
+           (ttrust_ * min_K_sum + min_FF_sum);
+  }
+
+  double MaxVelocity() {
+    const Eigen::Matrix<double, 2, 2> FF =
+        loop_->B().inverse() *
+        (Eigen::Matrix<double, 2, 2>::Identity() - loop_->A());
+
+    constexpr int kHighGearController = 3;
+    const Eigen::Matrix<double, 2, 2> FF_high =
+        loop_->controller(kHighGearController).plant.B().inverse() *
+        (Eigen::Matrix<double, 2, 2>::Identity() -
+         loop_->controller(kHighGearController).plant.A());
+
+    ::Eigen::Matrix<double, 1, 2> FF_sum = FF.colwise().sum();
+    int min_FF_sum_index;
+    const double min_FF_sum = FF_sum.minCoeff(&min_FF_sum_index);
+    //const double min_K_sum = loop_->K().col(min_FF_sum_index).sum();
+    const double high_min_FF_sum = FF_high.col(0).sum();
+
+    const double adjusted_ff_voltage = ::aos::Clip(
+        12.0 * min_FF_sum / high_min_FF_sum, -12.0, 12.0);
+    return adjusted_ff_voltage / min_FF_sum;
+  }
+
+  void Update() {
+    const auto &values = constants::GetValues();
+    // TODO(austin): Observer for the current velocity instead of difference
+    // calculations.
+    ++counter_;
+#if HAVE_SHIFTERS
+    const double current_left_velocity =
+        (position_.left_encoder - last_position_.left_encoder) /
+        position_time_delta_;
+    const double current_right_velocity =
+        (position_.right_encoder - last_position_.right_encoder) /
+        position_time_delta_;
+    const double left_motor_speed =
+        MotorSpeed(values.left_drive, position_.left_shifter_position,
+                   current_left_velocity);
+    const double right_motor_speed =
+        MotorSpeed(values.right_drive, position_.right_shifter_position,
+                   current_right_velocity);
+
+    {
+      CIMLogging logging;
+
+      // Reset the CIM model to the current conditions to be ready for when we
+      // shift.
+      if (IsInGear(left_gear_)) {
+        logging.left_in_gear = true;
+      } else {
+        logging.left_in_gear = false;
+      }
+      logging.left_motor_speed = left_motor_speed;
+      logging.left_velocity = current_left_velocity;
+      if (IsInGear(right_gear_)) {
+        logging.right_in_gear = true;
+      } else {
+        logging.right_in_gear = false;
+      }
+      logging.right_motor_speed = right_motor_speed;
+      logging.right_velocity = current_right_velocity;
+
+      LOG_STRUCT(DEBUG, "currently", logging);
+    }
+#else
+    (void) values;
+#endif
+
+#if HAVE_SHIFTERS
+    if (IsInGear(left_gear_) && IsInGear(right_gear_)) {
+#else
+    {
+#endif
+      // FF * X = U (steady state)
+      const Eigen::Matrix<double, 2, 2> FF =
+          loop_->B().inverse() *
+          (Eigen::Matrix<double, 2, 2>::Identity() - loop_->A());
+
+      // Invert the plant to figure out how the velocity filter would have to
+      // work
+      // out in order to filter out the forwards negative inertia.
+      // This math assumes that the left and right power and velocity are
+      // equals,
+      // and that the plant is the same on the left and right.
+      const double fvel = FilterVelocity(throttle_);
+
+      const double sign_svel = wheel_ * ((fvel > 0.0) ? 1.0 : -1.0);
+      double steering_velocity;
+      if (quickturn_) {
+        steering_velocity = wheel_ * MaxVelocity();
+      } else {
+        steering_velocity = ::std::abs(fvel) * wheel_;
+      }
+      const double left_velocity = fvel - steering_velocity;
+      const double right_velocity = fvel + steering_velocity;
+      LOG(DEBUG, "l=%f r=%f\n", left_velocity, right_velocity);
+
+      // Integrate velocity to get the position.
+      // This position is used to get integral control.
+      loop_->mutable_R() << left_velocity, right_velocity;
+
+      if (!quickturn_) {
+        // K * R = w
+        Eigen::Matrix<double, 1, 2> equality_k;
+        equality_k << 1 + sign_svel, -(1 - sign_svel);
+        const double equality_w = 0.0;
+
+        // Construct a constraint on R by manipulating the constraint on U
+        ::aos::controls::HPolytope<2> R_poly = ::aos::controls::HPolytope<2>(
+            U_Poly_.H() * (loop_->K() + FF),
+            U_Poly_.k() + U_Poly_.H() * loop_->K() * loop_->X_hat());
+
+        // Limit R back inside the box.
+        loop_->mutable_R() =
+            CoerceGoal(R_poly, equality_k, equality_w, loop_->R());
+      }
+
+      const Eigen::Matrix<double, 2, 1> FF_volts = FF * loop_->R();
+      const Eigen::Matrix<double, 2, 1> U_ideal =
+          loop_->K() * (loop_->R() - loop_->X_hat()) + FF_volts;
+
+      for (int i = 0; i < 2; i++) {
+        loop_->mutable_U()[i] = ::aos::Clip(U_ideal[i], -12, 12);
+      }
+
+      // TODO(austin): Model this better.
+      // TODO(austin): Feed back?
+      loop_->mutable_X_hat() =
+          loop_->A() * loop_->X_hat() + loop_->B() * loop_->U();
+#if HAVE_SHIFTERS
+    } else {
+      // Any motor is not in gear.  Speed match.
+      ::Eigen::Matrix<double, 1, 1> R_left;
+      ::Eigen::Matrix<double, 1, 1> R_right;
+      R_left(0, 0) = left_motor_speed;
+      R_right(0, 0) = right_motor_speed;
+
+      const double wiggle =
+          (static_cast<double>((counter_ % 20) / 10) - 0.5) * 5.0;
+
+      loop_->mutable_U(0, 0) = ::aos::Clip(
+          (R_left / Kv)(0, 0) + (IsInGear(left_gear_) ? 0 : wiggle),
+          -12.0, 12.0);
+      loop_->mutable_U(1, 0) = ::aos::Clip(
+          (R_right / Kv)(0, 0) + (IsInGear(right_gear_) ? 0 : wiggle),
+          -12.0, 12.0);
+      loop_->mutable_U() *= 12.0 / ::aos::robot_state->voltage_battery;
+#endif
+    }
+  }
+
+  void SendMotors(DrivetrainQueue::Output *output) {
+    if (output != NULL) {
+      output->left_voltage = loop_->U(0, 0);
+      output->right_voltage = loop_->U(1, 0);
+      output->left_high = left_gear_ == HIGH || left_gear_ == SHIFTING_UP;
+      output->right_high = right_gear_ == HIGH || right_gear_ == SHIFTING_UP;
+    }
+  }
+
+ private:
+  const ::aos::controls::HPolytope<2> U_Poly_;
+
+  ::std::unique_ptr<StateFeedbackLoop<2, 2, 2>> loop_;
+
+  const double ttrust_;
+  double wheel_;
+  double throttle_;
+  bool quickturn_;
+  int stale_count_;
+  double position_time_delta_;
+  Gear left_gear_;
+  Gear right_gear_;
+  DrivetrainQueue::Position last_position_;
+  DrivetrainQueue::Position position_;
+  int counter_;
+};
+constexpr double PolyDrivetrain::kStallTorque;
+constexpr double PolyDrivetrain::kStallCurrent;
+constexpr double PolyDrivetrain::kFreeSpeed;
+constexpr double PolyDrivetrain::kFreeCurrent;
+constexpr double PolyDrivetrain::J;
+constexpr double PolyDrivetrain::m;
+constexpr double PolyDrivetrain::rb;
+constexpr double PolyDrivetrain::kWheelRadius;
+constexpr double PolyDrivetrain::kR;
+constexpr double PolyDrivetrain::Kv;
+constexpr double PolyDrivetrain::Kt;
+
+
+void DrivetrainLoop::RunIteration(const DrivetrainQueue::Goal *goal,
+                                  const DrivetrainQueue::Position *position,
+                                  DrivetrainQueue::Output *output,
+                                  DrivetrainQueue::Status * status) {
+  // TODO(aschuh): These should be members of the class.
+  static DrivetrainMotorsSS dt_closedloop;
+  static PolyDrivetrain dt_openloop;
+
+  bool bad_pos = false;
+  if (position == nullptr) {
+    LOG_INTERVAL(no_position_);
+    bad_pos = true;
+  }
+  no_position_.Print();
+
+  bool control_loop_driving = false;
+  if (goal) {
+    double wheel = goal->steering;
+    double throttle = goal->throttle;
+    bool quickturn = goal->quickturn;
+#if HAVE_SHIFTERS
+    bool highgear = goal->highgear;
+#endif
+
+    control_loop_driving = goal->control_loop_driving;
+    double left_goal = goal->left_goal;
+    double right_goal = goal->right_goal;
+
+    dt_closedloop.SetGoal(left_goal, goal->left_velocity_goal, right_goal,
+                          goal->right_velocity_goal);
+#if HAVE_SHIFTERS
+    dt_openloop.SetGoal(wheel, throttle, quickturn, highgear);
+#else
+    dt_openloop.SetGoal(wheel, throttle, quickturn, false);
+#endif
+  }
+
+  if (!bad_pos) {
+    const double left_encoder = position->left_encoder;
+    const double right_encoder = position->right_encoder;
+    if (gyro_reading.FetchLatest()) {
+      LOG_STRUCT(DEBUG, "using", *gyro_reading.get());
+      dt_closedloop.SetPosition(left_encoder, right_encoder,
+                                gyro_reading->angle);
+    } else {
+      dt_closedloop.SetRawPosition(left_encoder, right_encoder);
+    }
+  }
+  dt_openloop.SetPosition(position);
+  dt_openloop.Update();
+
+  if (control_loop_driving) {
+    dt_closedloop.Update(output == NULL, true);
+    dt_closedloop.SendMotors(output);
+  } else {
+    dt_openloop.SendMotors(output);
+    if (output) {
+      dt_closedloop.SetExternalMotors(output->left_voltage,
+                                      output->right_voltage);
+    }
+    dt_closedloop.Update(output == NULL, false);
+  }
+
+  // set the output status of the control loop state
+  if (status) {
+    bool done = false;
+    if (goal) {
+      done = ((::std::abs(goal->left_goal -
+                          dt_closedloop.GetEstimatedLeftEncoder()) <
+               constants::GetValues().drivetrain_done_distance) &&
+              (::std::abs(goal->right_goal -
+                          dt_closedloop.GetEstimatedRightEncoder()) <
+               constants::GetValues().drivetrain_done_distance));
+    }
+    status->is_done = done;
+    status->robot_speed = dt_closedloop.GetEstimatedRobotSpeed();
+    status->filtered_left_position = dt_closedloop.GetEstimatedLeftEncoder();
+    status->filtered_right_position = dt_closedloop.GetEstimatedRightEncoder();
+
+    status->filtered_left_velocity = dt_closedloop.loop().X_hat(1, 0);
+    status->filtered_right_velocity = dt_closedloop.loop().X_hat(3, 0);
+    status->output_was_capped = dt_closedloop.OutputWasCapped();
+    status->uncapped_left_voltage = dt_closedloop.loop().U_uncapped(0, 0);
+    status->uncapped_right_voltage = dt_closedloop.loop().U_uncapped(1, 0);
+  }
+}
+
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/y2015/control_loops/drivetrain/drivetrain.gyp b/y2015/control_loops/drivetrain/drivetrain.gyp
new file mode 100644
index 0000000..4333258
--- /dev/null
+++ b/y2015/control_loops/drivetrain/drivetrain.gyp
@@ -0,0 +1,103 @@
+{
+  'targets': [
+    {
+      'target_name': 'replay_drivetrain',
+      'type': 'executable',
+      'variables': {
+        'no_rsync': 1,
+      },
+      'sources': [
+        'replay_drivetrain.cc',
+      ],
+      'dependencies': [
+        'drivetrain_queue',
+        '<(AOS)/common/controls/controls.gyp:replay_control_loop',
+        '<(AOS)/linux_code/linux_code.gyp:init',
+      ],
+    },
+    {
+      'target_name': 'drivetrain_queue',
+      'type': 'static_library',
+      'sources': ['drivetrain.q'],
+      'variables': {
+        'header_path': 'y2015/control_loops/drivetrain',
+      },
+      'dependencies': [
+        '<(AOS)/common/controls/controls.gyp:control_loop_queues',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/controls/controls.gyp:control_loop_queues',
+      ],
+      'includes': ['../../../aos/build/queues.gypi'],
+    },
+    {
+      'target_name': 'polydrivetrain_plants',
+      'type': 'static_library',
+      'sources': [
+        'polydrivetrain_dog_motor_plant.cc',
+        'drivetrain_dog_motor_plant.cc',
+      ],
+      'dependencies': [
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+      ],
+      'export_dependent_settings': [
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+      ],
+    },
+    {
+      'target_name': 'drivetrain_lib',
+      'type': 'static_library',
+      'sources': [
+        'drivetrain.cc',
+        'polydrivetrain_cim_plant.cc',
+      ],
+      'dependencies': [
+        'drivetrain_queue',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+        '<(DEPTH)/y2015/y2015.gyp:constants',
+        '<(AOS)/common/controls/controls.gyp:polytope',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:coerce_goal',
+        '<(DEPTH)/frc971/queues/queues.gyp:gyro',
+        '<(AOS)/common/util/util.gyp:log_interval',
+        '<(AOS)/common/logging/logging.gyp:queue_logging',
+        '<(AOS)/common/logging/logging.gyp:matrix_logging',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/controls/controls.gyp:polytope',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:coerce_goal',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+        'drivetrain_queue',
+      ],
+    },
+    {
+      'target_name': 'drivetrain_lib_test',
+      'type': 'executable',
+      'sources': [
+        'drivetrain_lib_test.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+        'drivetrain_queue',
+        'drivetrain_lib',
+        '<(AOS)/common/controls/controls.gyp:control_loop_test',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+        '<(DEPTH)/frc971/queues/queues.gyp:gyro',
+        '<(AOS)/common/common.gyp:queues',
+      ],
+    },
+    {
+      'target_name': 'drivetrain',
+      'type': 'executable',
+      'sources': [
+        'drivetrain_main.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        'drivetrain_lib',
+        'drivetrain_queue',
+      ],
+    },
+  ],
+}
diff --git a/y2015/control_loops/drivetrain/drivetrain.h b/y2015/control_loops/drivetrain/drivetrain.h
new file mode 100644
index 0000000..8e8768e
--- /dev/null
+++ b/y2015/control_loops/drivetrain/drivetrain.h
@@ -0,0 +1,43 @@
+#ifndef Y2015_CONTROL_LOOPS_DRIVETRAIN_H_
+#define Y2015_CONTROL_LOOPS_DRIVETRAIN_H_
+
+#include "Eigen/Dense"
+
+#include "aos/common/controls/polytope.h"
+#include "aos/common/controls/control_loop.h"
+#include "aos/common/controls/polytope.h"
+#include "y2015/control_loops/drivetrain/drivetrain.q.h"
+#include "aos/common/util/log_interval.h"
+
+namespace frc971 {
+namespace control_loops {
+
+class DrivetrainLoop
+    : public aos::controls::ControlLoop<control_loops::DrivetrainQueue> {
+ public:
+  // Constructs a control loop which can take a Drivetrain or defaults to the
+  // drivetrain at frc971::control_loops::drivetrain
+  explicit DrivetrainLoop(control_loops::DrivetrainQueue *my_drivetrain =
+                              &control_loops::drivetrain_queue)
+      : aos::controls::ControlLoop<control_loops::DrivetrainQueue>(
+            my_drivetrain) {
+    ::aos::controls::HPolytope<0>::Init();
+  }
+
+ protected:
+  // Executes one cycle of the control loop.
+  virtual void RunIteration(
+      const control_loops::DrivetrainQueue::Goal *goal,
+      const control_loops::DrivetrainQueue::Position *position,
+      control_loops::DrivetrainQueue::Output *output,
+      control_loops::DrivetrainQueue::Status *status);
+
+  typedef ::aos::util::SimpleLogInterval SimpleLogInterval;
+  SimpleLogInterval no_position_ = SimpleLogInterval(
+      ::aos::time::Time::InSeconds(0.25), WARNING, "no position");
+};
+
+}  // namespace control_loops
+}  // namespace frc971
+
+#endif  // Y2015_CONTROL_LOOPS_DRIVETRAIN_H_
diff --git a/y2015/control_loops/drivetrain/drivetrain.q b/y2015/control_loops/drivetrain/drivetrain.q
new file mode 100644
index 0000000..942c5b3
--- /dev/null
+++ b/y2015/control_loops/drivetrain/drivetrain.q
@@ -0,0 +1,71 @@
+package frc971.control_loops;
+
+import "aos/common/controls/control_loops.q";
+
+struct GearLogging {
+  int8_t controller_index;
+  bool left_loop_high;
+  bool right_loop_high;
+  int8_t left_state;
+  int8_t right_state;
+};
+
+struct CIMLogging {
+  bool left_in_gear;
+  bool right_in_gear;
+  double left_motor_speed;
+  double right_motor_speed;
+  double left_velocity;
+  double right_velocity;
+};
+
+queue_group DrivetrainQueue {
+  implements aos.control_loops.ControlLoop;
+
+  message Goal {
+    double steering;
+    double throttle;
+    //bool highgear;
+    bool quickturn;
+    bool control_loop_driving;
+    double left_goal;
+    double left_velocity_goal;
+    double right_goal;
+    double right_velocity_goal;
+  };
+
+  message Position {
+    double left_encoder;
+    double right_encoder;
+    //double left_shifter_position;
+    //double right_shifter_position;
+  };
+
+  message Output {
+    double left_voltage;
+    double right_voltage;
+    bool left_high;
+    bool right_high;
+  };
+
+  message Status {
+    double robot_speed;
+    double filtered_left_position;
+    double filtered_right_position;
+    double filtered_left_velocity;
+    double filtered_right_velocity;
+
+    double uncapped_left_voltage;
+    double uncapped_right_voltage;
+    bool output_was_capped;
+
+    bool is_done;
+  };
+
+  queue Goal goal;
+  queue Position position;
+  queue Output output;
+  queue Status status;
+};
+
+queue_group DrivetrainQueue drivetrain_queue;
diff --git a/y2015/control_loops/drivetrain/drivetrain_dog_motor_plant.cc b/y2015/control_loops/drivetrain/drivetrain_dog_motor_plant.cc
new file mode 100644
index 0000000..e2f5a9a
--- /dev/null
+++ b/y2015/control_loops/drivetrain/drivetrain_dog_motor_plant.cc
@@ -0,0 +1,133 @@
+#include "y2015/control_loops/drivetrain/drivetrain_dog_motor_plant.h"
+
+#include <vector>
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace frc971 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeDrivetrainLowLowPlantCoefficients() {
+  Eigen::Matrix<double, 4, 4> A;
+  A << 1.0, 0.00494348612824, 0.0, 1.24048455404e-05, 0.0, 0.977484092703, 0.0, 0.00492433284048, 0.0, 1.24048455404e-05, 1.0, 0.00494348612824, 0.0, 0.00492433284048, 0.0, 0.977484092703;
+  Eigen::Matrix<double, 4, 2> B;
+  B << 2.09180756177e-05, -4.59153636043e-06, 0.00833405032795, -0.00182269526971, -4.59153636043e-06, 2.09180756177e-05, -0.00182269526971, 0.00833405032795;
+  Eigen::Matrix<double, 2, 4> C;
+  C << 1, 0, 0, 0, 0, 0, 1, 0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0, 0, 0, 0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<4, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeDrivetrainLowHighPlantCoefficients() {
+  Eigen::Matrix<double, 4, 4> A;
+  A << 1.0, 0.00494348612824, 0.0, 1.24048455404e-05, 0.0, 0.977484092703, 0.0, 0.00492433284048, 0.0, 1.24048455404e-05, 1.0, 0.00494348612824, 0.0, 0.00492433284048, 0.0, 0.977484092703;
+  Eigen::Matrix<double, 4, 2> B;
+  B << 2.09180756177e-05, -4.59153636043e-06, 0.00833405032795, -0.00182269526971, -4.59153636043e-06, 2.09180756177e-05, -0.00182269526971, 0.00833405032795;
+  Eigen::Matrix<double, 2, 4> C;
+  C << 1, 0, 0, 0, 0, 0, 1, 0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0, 0, 0, 0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<4, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeDrivetrainHighLowPlantCoefficients() {
+  Eigen::Matrix<double, 4, 4> A;
+  A << 1.0, 0.00494348612824, 0.0, 1.24048455404e-05, 0.0, 0.977484092703, 0.0, 0.00492433284048, 0.0, 1.24048455404e-05, 1.0, 0.00494348612824, 0.0, 0.00492433284048, 0.0, 0.977484092703;
+  Eigen::Matrix<double, 4, 2> B;
+  B << 2.09180756177e-05, -4.59153636043e-06, 0.00833405032795, -0.00182269526971, -4.59153636043e-06, 2.09180756177e-05, -0.00182269526971, 0.00833405032795;
+  Eigen::Matrix<double, 2, 4> C;
+  C << 1, 0, 0, 0, 0, 0, 1, 0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0, 0, 0, 0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<4, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeDrivetrainHighHighPlantCoefficients() {
+  Eigen::Matrix<double, 4, 4> A;
+  A << 1.0, 0.00494348612824, 0.0, 1.24048455404e-05, 0.0, 0.977484092703, 0.0, 0.00492433284048, 0.0, 1.24048455404e-05, 1.0, 0.00494348612824, 0.0, 0.00492433284048, 0.0, 0.977484092703;
+  Eigen::Matrix<double, 4, 2> B;
+  B << 2.09180756177e-05, -4.59153636043e-06, 0.00833405032795, -0.00182269526971, -4.59153636043e-06, 2.09180756177e-05, -0.00182269526971, 0.00833405032795;
+  Eigen::Matrix<double, 2, 4> C;
+  C << 1, 0, 0, 0, 0, 0, 1, 0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0, 0, 0, 0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<4, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackController<4, 2, 2> MakeDrivetrainLowLowController() {
+  Eigen::Matrix<double, 4, 2> L;
+  L << 1.2774840927, 0.00492433284048, 79.1440456622, 1.05150722636, 0.00492433284048, 1.2774840927, 1.05150722636, 79.1440456622;
+  Eigen::Matrix<double, 2, 4> K;
+  K << 160.19677247, 15.5358468938, 1.60401194139, 1.33861213093, 1.60401194142, 1.33861213094, 160.19677247, 15.5358468938;
+  Eigen::Matrix<double, 4, 4> A_inv;
+  A_inv << 1.0, -0.00505742153256, 0.0, 1.27875036472e-05, 0.0, 1.02306051542, 0.0, -0.00515393603998, 0.0, 1.27875036472e-05, 1.0, -0.00505742153256, 0.0, -0.00515393603998, 0.0, 1.02306051542;
+  return StateFeedbackController<4, 2, 2>(L, K, A_inv, MakeDrivetrainLowLowPlantCoefficients());
+}
+
+StateFeedbackController<4, 2, 2> MakeDrivetrainLowHighController() {
+  Eigen::Matrix<double, 4, 2> L;
+  L << 1.2774840927, 0.00492433284048, 79.1440456622, 1.05150722636, 0.00492433284048, 1.2774840927, 1.05150722636, 79.1440456622;
+  Eigen::Matrix<double, 2, 4> K;
+  K << 160.19677247, 15.5358468938, 1.60401194139, 1.33861213093, 1.60401194142, 1.33861213094, 160.19677247, 15.5358468938;
+  Eigen::Matrix<double, 4, 4> A_inv;
+  A_inv << 1.0, -0.00505742153256, 0.0, 1.27875036472e-05, 0.0, 1.02306051542, 0.0, -0.00515393603998, 0.0, 1.27875036472e-05, 1.0, -0.00505742153256, 0.0, -0.00515393603998, 0.0, 1.02306051542;
+  return StateFeedbackController<4, 2, 2>(L, K, A_inv, MakeDrivetrainLowHighPlantCoefficients());
+}
+
+StateFeedbackController<4, 2, 2> MakeDrivetrainHighLowController() {
+  Eigen::Matrix<double, 4, 2> L;
+  L << 1.2774840927, 0.00492433284048, 79.1440456622, 1.05150722636, 0.00492433284048, 1.2774840927, 1.05150722636, 79.1440456622;
+  Eigen::Matrix<double, 2, 4> K;
+  K << 160.19677247, 15.5358468938, 1.60401194139, 1.33861213093, 1.60401194142, 1.33861213094, 160.19677247, 15.5358468938;
+  Eigen::Matrix<double, 4, 4> A_inv;
+  A_inv << 1.0, -0.00505742153256, 0.0, 1.27875036472e-05, 0.0, 1.02306051542, 0.0, -0.00515393603998, 0.0, 1.27875036472e-05, 1.0, -0.00505742153256, 0.0, -0.00515393603998, 0.0, 1.02306051542;
+  return StateFeedbackController<4, 2, 2>(L, K, A_inv, MakeDrivetrainHighLowPlantCoefficients());
+}
+
+StateFeedbackController<4, 2, 2> MakeDrivetrainHighHighController() {
+  Eigen::Matrix<double, 4, 2> L;
+  L << 1.2774840927, 0.00492433284048, 79.1440456622, 1.05150722636, 0.00492433284048, 1.2774840927, 1.05150722636, 79.1440456622;
+  Eigen::Matrix<double, 2, 4> K;
+  K << 160.19677247, 15.5358468938, 1.60401194139, 1.33861213093, 1.60401194142, 1.33861213094, 160.19677247, 15.5358468938;
+  Eigen::Matrix<double, 4, 4> A_inv;
+  A_inv << 1.0, -0.00505742153256, 0.0, 1.27875036472e-05, 0.0, 1.02306051542, 0.0, -0.00515393603998, 0.0, 1.27875036472e-05, 1.0, -0.00505742153256, 0.0, -0.00515393603998, 0.0, 1.02306051542;
+  return StateFeedbackController<4, 2, 2>(L, K, A_inv, MakeDrivetrainHighHighPlantCoefficients());
+}
+
+StateFeedbackPlant<4, 2, 2> MakeDrivetrainPlant() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackPlantCoefficients<4, 2, 2>>> plants(4);
+  plants[0] = ::std::unique_ptr<StateFeedbackPlantCoefficients<4, 2, 2>>(new StateFeedbackPlantCoefficients<4, 2, 2>(MakeDrivetrainLowLowPlantCoefficients()));
+  plants[1] = ::std::unique_ptr<StateFeedbackPlantCoefficients<4, 2, 2>>(new StateFeedbackPlantCoefficients<4, 2, 2>(MakeDrivetrainLowHighPlantCoefficients()));
+  plants[2] = ::std::unique_ptr<StateFeedbackPlantCoefficients<4, 2, 2>>(new StateFeedbackPlantCoefficients<4, 2, 2>(MakeDrivetrainHighLowPlantCoefficients()));
+  plants[3] = ::std::unique_ptr<StateFeedbackPlantCoefficients<4, 2, 2>>(new StateFeedbackPlantCoefficients<4, 2, 2>(MakeDrivetrainHighHighPlantCoefficients()));
+  return StateFeedbackPlant<4, 2, 2>(&plants);
+}
+
+StateFeedbackLoop<4, 2, 2> MakeDrivetrainLoop() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackController<4, 2, 2>>> controllers(4);
+  controllers[0] = ::std::unique_ptr<StateFeedbackController<4, 2, 2>>(new StateFeedbackController<4, 2, 2>(MakeDrivetrainLowLowController()));
+  controllers[1] = ::std::unique_ptr<StateFeedbackController<4, 2, 2>>(new StateFeedbackController<4, 2, 2>(MakeDrivetrainLowHighController()));
+  controllers[2] = ::std::unique_ptr<StateFeedbackController<4, 2, 2>>(new StateFeedbackController<4, 2, 2>(MakeDrivetrainHighLowController()));
+  controllers[3] = ::std::unique_ptr<StateFeedbackController<4, 2, 2>>(new StateFeedbackController<4, 2, 2>(MakeDrivetrainHighHighController()));
+  return StateFeedbackLoop<4, 2, 2>(&controllers);
+}
+
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/y2015/control_loops/drivetrain/drivetrain_dog_motor_plant.h b/y2015/control_loops/drivetrain/drivetrain_dog_motor_plant.h
new file mode 100644
index 0000000..a2848be
--- /dev/null
+++ b/y2015/control_loops/drivetrain/drivetrain_dog_motor_plant.h
@@ -0,0 +1,32 @@
+#ifndef Y2015_CONTROL_LOOPS_DRIVETRAIN_DRIVETRAIN_DOG_MOTOR_PLANT_H_
+#define Y2015_CONTROL_LOOPS_DRIVETRAIN_DRIVETRAIN_DOG_MOTOR_PLANT_H_
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace frc971 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeDrivetrainLowLowPlantCoefficients();
+
+StateFeedbackController<4, 2, 2> MakeDrivetrainLowLowController();
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeDrivetrainLowHighPlantCoefficients();
+
+StateFeedbackController<4, 2, 2> MakeDrivetrainLowHighController();
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeDrivetrainHighLowPlantCoefficients();
+
+StateFeedbackController<4, 2, 2> MakeDrivetrainHighLowController();
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeDrivetrainHighHighPlantCoefficients();
+
+StateFeedbackController<4, 2, 2> MakeDrivetrainHighHighController();
+
+StateFeedbackPlant<4, 2, 2> MakeDrivetrainPlant();
+
+StateFeedbackLoop<4, 2, 2> MakeDrivetrainLoop();
+
+}  // namespace control_loops
+}  // namespace frc971
+
+#endif  // Y2015_CONTROL_LOOPS_DRIVETRAIN_DRIVETRAIN_DOG_MOTOR_PLANT_H_
diff --git a/y2015/control_loops/drivetrain/drivetrain_lib_test.cc b/y2015/control_loops/drivetrain/drivetrain_lib_test.cc
new file mode 100644
index 0000000..d3869aa
--- /dev/null
+++ b/y2015/control_loops/drivetrain/drivetrain_lib_test.cc
@@ -0,0 +1,297 @@
+#include <unistd.h>
+
+#include <memory>
+
+#include "gtest/gtest.h"
+#include "aos/common/network/team_number.h"
+#include "aos/common/queue_testutils.h"
+#include "aos/common/controls/polytope.h"
+#include "aos/common/controls/control_loop_test.h"
+
+#include "y2015/control_loops/drivetrain/drivetrain.q.h"
+#include "y2015/control_loops/drivetrain/drivetrain.h"
+#include "frc971/control_loops/state_feedback_loop.h"
+#include "frc971/control_loops/coerce_goal.h"
+#include "y2015/control_loops/drivetrain/drivetrain_dog_motor_plant.h"
+#include "frc971/queues/gyro.q.h"
+
+
+namespace frc971 {
+namespace control_loops {
+namespace testing {
+
+class Environment : public ::testing::Environment {
+ public:
+  virtual ~Environment() {}
+  // how to set up the environment.
+  virtual void SetUp() {
+    aos::controls::HPolytope<0>::Init();
+  }
+};
+::testing::Environment* const holder_env =
+  ::testing::AddGlobalTestEnvironment(new Environment);
+
+class TeamNumberEnvironment : public ::testing::Environment {
+ public:
+  // Override this to define how to set up the environment.
+  virtual void SetUp() { aos::network::OverrideTeamNumber(971); }
+};
+
+::testing::Environment* const team_number_env =
+    ::testing::AddGlobalTestEnvironment(new TeamNumberEnvironment);
+
+// Class which simulates the drivetrain and sends out queue messages containing
+// the position.
+class DrivetrainSimulation {
+ public:
+  // Constructs a motor simulation.
+  // TODO(aschuh) Do we want to test the clutch one too?
+  DrivetrainSimulation()
+      : drivetrain_plant_(
+            new StateFeedbackPlant<4, 2, 2>(MakeDrivetrainPlant())),
+        my_drivetrain_queue_(".frc971.control_loops.drivetrain",
+                       0x8a8dde77, ".frc971.control_loops.drivetrain.goal",
+                       ".frc971.control_loops.drivetrain.position",
+                       ".frc971.control_loops.drivetrain.output",
+                       ".frc971.control_loops.drivetrain.status") {
+    Reinitialize();
+  }
+
+  // Resets the plant.
+  void Reinitialize() {
+    drivetrain_plant_->mutable_X(0, 0) = 0.0;
+    drivetrain_plant_->mutable_X(1, 0) = 0.0;
+    drivetrain_plant_->mutable_Y() =
+        drivetrain_plant_->C() * drivetrain_plant_->X();
+    last_left_position_ = drivetrain_plant_->Y(0, 0);
+    last_right_position_ = drivetrain_plant_->Y(1, 0);
+  }
+
+  // Returns the position of the drivetrain.
+  double GetLeftPosition() const { return drivetrain_plant_->Y(0, 0); }
+  double GetRightPosition() const { return drivetrain_plant_->Y(1, 0); }
+
+  // Sends out the position queue messages.
+  void SendPositionMessage() {
+    const double left_encoder = GetLeftPosition();
+    const double right_encoder = GetRightPosition();
+
+    ::aos::ScopedMessagePtr<control_loops::DrivetrainQueue::Position> position =
+        my_drivetrain_queue_.position.MakeMessage();
+    position->left_encoder = left_encoder;
+    position->right_encoder = right_encoder;
+    position.Send();
+  }
+
+  // Simulates the drivetrain moving for one timestep.
+  void Simulate() {
+    last_left_position_ = drivetrain_plant_->Y(0, 0);
+    last_right_position_ = drivetrain_plant_->Y(1, 0);
+    EXPECT_TRUE(my_drivetrain_queue_.output.FetchLatest());
+    drivetrain_plant_->mutable_U() << my_drivetrain_queue_.output->left_voltage,
+        my_drivetrain_queue_.output->right_voltage;
+    drivetrain_plant_->Update();
+  }
+
+  ::std::unique_ptr<StateFeedbackPlant<4, 2, 2>> drivetrain_plant_;
+ private:
+  DrivetrainQueue my_drivetrain_queue_;
+  double last_left_position_;
+  double last_right_position_;
+};
+
+class DrivetrainTest : public ::aos::testing::ControlLoopTest {
+ protected:
+  // Create a new instance of the test queue so that it invalidates the queue
+  // that it points to.  Otherwise, we will have a pointer to shared memory that
+  // is no longer valid.
+  DrivetrainQueue my_drivetrain_queue_;
+
+  // Create a loop and simulation plant.
+  DrivetrainLoop drivetrain_motor_;
+  DrivetrainSimulation drivetrain_motor_plant_;
+
+  DrivetrainTest() : my_drivetrain_queue_(".frc971.control_loops.drivetrain",
+                               0x8a8dde77,
+                               ".frc971.control_loops.drivetrain.goal",
+                               ".frc971.control_loops.drivetrain.position",
+                               ".frc971.control_loops.drivetrain.output",
+                               ".frc971.control_loops.drivetrain.status"),
+                drivetrain_motor_(&my_drivetrain_queue_),
+                drivetrain_motor_plant_() {
+    ::frc971::sensors::gyro_reading.Clear();
+  }
+
+  void VerifyNearGoal() {
+    my_drivetrain_queue_.goal.FetchLatest();
+    my_drivetrain_queue_.position.FetchLatest();
+    EXPECT_NEAR(my_drivetrain_queue_.goal->left_goal,
+                drivetrain_motor_plant_.GetLeftPosition(),
+                1e-2);
+    EXPECT_NEAR(my_drivetrain_queue_.goal->right_goal,
+                drivetrain_motor_plant_.GetRightPosition(),
+                1e-2);
+  }
+
+  virtual ~DrivetrainTest() {
+    ::frc971::sensors::gyro_reading.Clear();
+  }
+};
+
+// Tests that the drivetrain converges on a goal.
+TEST_F(DrivetrainTest, ConvergesCorrectly) {
+  my_drivetrain_queue_.goal.MakeWithBuilder().control_loop_driving(true)
+      .left_goal(-1.0)
+      .right_goal(1.0).Send();
+  for (int i = 0; i < 200; ++i) {
+    drivetrain_motor_plant_.SendPositionMessage();
+    drivetrain_motor_.Iterate();
+    drivetrain_motor_plant_.Simulate();
+    SimulateTimestep(true);
+  }
+  VerifyNearGoal();
+}
+
+// Tests that it survives disabling.
+TEST_F(DrivetrainTest, SurvivesDisabling) {
+  my_drivetrain_queue_.goal.MakeWithBuilder().control_loop_driving(true)
+      .left_goal(-1.0)
+      .right_goal(1.0).Send();
+  for (int i = 0; i < 500; ++i) {
+    drivetrain_motor_plant_.SendPositionMessage();
+    drivetrain_motor_.Iterate();
+    drivetrain_motor_plant_.Simulate();
+    if (i > 20 && i < 200) {
+      SimulateTimestep(false);
+    } else {
+      SimulateTimestep(true);
+    }
+  }
+  VerifyNearGoal();
+}
+
+// Tests that never having a goal doesn't break.
+TEST_F(DrivetrainTest, NoGoalStart) {
+  for (int i = 0; i < 20; ++i) {
+    drivetrain_motor_plant_.SendPositionMessage();
+    drivetrain_motor_.Iterate();
+    drivetrain_motor_plant_.Simulate();
+  }
+}
+
+// Tests that never having a goal, but having driver's station messages, doesn't
+// break.
+TEST_F(DrivetrainTest, NoGoalWithRobotState) {
+  for (int i = 0; i < 20; ++i) {
+    drivetrain_motor_plant_.SendPositionMessage();
+    drivetrain_motor_.Iterate();
+    drivetrain_motor_plant_.Simulate();
+    SimulateTimestep(true);
+  }
+}
+
+::aos::controls::HPolytope<2> MakeBox(double x1_min, double x1_max,
+                                      double x2_min, double x2_max) {
+  Eigen::Matrix<double, 4, 2> box_H;
+  box_H << /*[[*/ 1.0, 0.0 /*]*/,
+            /*[*/-1.0, 0.0 /*]*/,
+            /*[*/ 0.0, 1.0 /*]*/,
+            /*[*/ 0.0,-1.0 /*]]*/;
+  Eigen::Matrix<double, 4, 1> box_k;
+  box_k << /*[[*/ x1_max /*]*/,
+            /*[*/-x1_min /*]*/,
+            /*[*/ x2_max /*]*/,
+            /*[*/-x2_min /*]]*/;
+  ::aos::controls::HPolytope<2> t_poly(box_H, box_k);
+  return t_poly;
+}
+
+class CoerceGoalTest : public ::testing::Test {
+ public:
+  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
+};
+
+// WHOOOHH!
+TEST_F(CoerceGoalTest, Inside) {
+  ::aos::controls::HPolytope<2> box = MakeBox(1, 2, 1, 2);
+
+  Eigen::Matrix<double, 1, 2> K;
+  K << /*[[*/ 1, -1 /*]]*/;
+
+  Eigen::Matrix<double, 2, 1> R;
+  R << /*[[*/ 1.5, 1.5 /*]]*/;
+
+  Eigen::Matrix<double, 2, 1> output =
+      ::frc971::control_loops::CoerceGoal(box, K, 0, R);
+
+  EXPECT_EQ(R(0, 0), output(0, 0));
+  EXPECT_EQ(R(1, 0), output(1, 0));
+}
+
+TEST_F(CoerceGoalTest, Outside_Inside_Intersect) {
+  ::aos::controls::HPolytope<2> box = MakeBox(1, 2, 1, 2);
+
+  Eigen::Matrix<double, 1, 2> K;
+  K << 1, -1;
+
+  Eigen::Matrix<double, 2, 1> R;
+  R << 5, 5;
+
+  Eigen::Matrix<double, 2, 1> output =
+      ::frc971::control_loops::CoerceGoal(box, K, 0, R);
+
+  EXPECT_EQ(2.0, output(0, 0));
+  EXPECT_EQ(2.0, output(1, 0));
+}
+
+TEST_F(CoerceGoalTest, Outside_Inside_no_Intersect) {
+  ::aos::controls::HPolytope<2> box = MakeBox(3, 4, 1, 2);
+
+  Eigen::Matrix<double, 1, 2> K;
+  K << 1, -1;
+
+  Eigen::Matrix<double, 2, 1> R;
+  R << 5, 5;
+
+  Eigen::Matrix<double, 2, 1> output =
+      ::frc971::control_loops::CoerceGoal(box, K, 0, R);
+
+  EXPECT_EQ(3.0, output(0, 0));
+  EXPECT_EQ(2.0, output(1, 0));
+}
+
+TEST_F(CoerceGoalTest, Middle_Of_Edge) {
+  ::aos::controls::HPolytope<2> box = MakeBox(0, 4, 1, 2);
+
+  Eigen::Matrix<double, 1, 2> K;
+  K << -1, 1;
+
+  Eigen::Matrix<double, 2, 1> R;
+  R << 5, 5;
+
+  Eigen::Matrix<double, 2, 1> output =
+      ::frc971::control_loops::CoerceGoal(box, K, 0, R);
+
+  EXPECT_EQ(2.0, output(0, 0));
+  EXPECT_EQ(2.0, output(1, 0));
+}
+
+TEST_F(CoerceGoalTest, PerpendicularLine) {
+  ::aos::controls::HPolytope<2> box = MakeBox(1, 2, 1, 2);
+
+  Eigen::Matrix<double, 1, 2> K;
+  K << 1, 1;
+
+  Eigen::Matrix<double, 2, 1> R;
+  R << 5, 5;
+
+  Eigen::Matrix<double, 2, 1> output =
+      ::frc971::control_loops::CoerceGoal(box, K, 0, R);
+
+  EXPECT_EQ(1.0, output(0, 0));
+  EXPECT_EQ(1.0, output(1, 0));
+}
+
+}  // namespace testing
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/y2015/control_loops/drivetrain/drivetrain_main.cc b/y2015/control_loops/drivetrain/drivetrain_main.cc
new file mode 100644
index 0000000..10a50f3
--- /dev/null
+++ b/y2015/control_loops/drivetrain/drivetrain_main.cc
@@ -0,0 +1,11 @@
+#include "y2015/control_loops/drivetrain/drivetrain.h"
+
+#include "aos/linux_code/init.h"
+
+int main() {
+  ::aos::Init();
+  frc971::control_loops::DrivetrainLoop drivetrain;
+  drivetrain.Run();
+  ::aos::Cleanup();
+  return 0;
+}
diff --git a/y2015/control_loops/drivetrain/polydrivetrain_cim_plant.cc b/y2015/control_loops/drivetrain/polydrivetrain_cim_plant.cc
new file mode 100644
index 0000000..36ebb59
--- /dev/null
+++ b/y2015/control_loops/drivetrain/polydrivetrain_cim_plant.cc
@@ -0,0 +1,49 @@
+#include "y2015/control_loops/drivetrain/polydrivetrain_cim_plant.h"
+
+#include <vector>
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace frc971 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<1, 1, 1> MakeCIMPlantCoefficients() {
+  Eigen::Matrix<double, 1, 1> A;
+  A << 0.783924473544;
+  Eigen::Matrix<double, 1, 1> B;
+  B << 8.94979586973;
+  Eigen::Matrix<double, 1, 1> C;
+  C << 1;
+  Eigen::Matrix<double, 1, 1> D;
+  D << 0;
+  Eigen::Matrix<double, 1, 1> U_max;
+  U_max << 12.0;
+  Eigen::Matrix<double, 1, 1> U_min;
+  U_min << -12.0;
+  return StateFeedbackPlantCoefficients<1, 1, 1>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackController<1, 1, 1> MakeCIMController() {
+  Eigen::Matrix<double, 1, 1> L;
+  L << 0.773924473544;
+  Eigen::Matrix<double, 1, 1> K;
+  K << 0.086473980503;
+  Eigen::Matrix<double, 1, 1> A_inv;
+  A_inv << 1.2756330919;
+  return StateFeedbackController<1, 1, 1>(L, K, A_inv, MakeCIMPlantCoefficients());
+}
+
+StateFeedbackPlant<1, 1, 1> MakeCIMPlant() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackPlantCoefficients<1, 1, 1>>> plants(1);
+  plants[0] = ::std::unique_ptr<StateFeedbackPlantCoefficients<1, 1, 1>>(new StateFeedbackPlantCoefficients<1, 1, 1>(MakeCIMPlantCoefficients()));
+  return StateFeedbackPlant<1, 1, 1>(&plants);
+}
+
+StateFeedbackLoop<1, 1, 1> MakeCIMLoop() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackController<1, 1, 1>>> controllers(1);
+  controllers[0] = ::std::unique_ptr<StateFeedbackController<1, 1, 1>>(new StateFeedbackController<1, 1, 1>(MakeCIMController()));
+  return StateFeedbackLoop<1, 1, 1>(&controllers);
+}
+
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/y2015/control_loops/drivetrain/polydrivetrain_cim_plant.h b/y2015/control_loops/drivetrain/polydrivetrain_cim_plant.h
new file mode 100644
index 0000000..1c445a7
--- /dev/null
+++ b/y2015/control_loops/drivetrain/polydrivetrain_cim_plant.h
@@ -0,0 +1,20 @@
+#ifndef Y2015_CONTROL_LOOPS_DRIVETRAIN_POLYDRIVETRAIN_CIM_PLANT_H_
+#define Y2015_CONTROL_LOOPS_DRIVETRAIN_POLYDRIVETRAIN_CIM_PLANT_H_
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace frc971 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<1, 1, 1> MakeCIMPlantCoefficients();
+
+StateFeedbackController<1, 1, 1> MakeCIMController();
+
+StateFeedbackPlant<1, 1, 1> MakeCIMPlant();
+
+StateFeedbackLoop<1, 1, 1> MakeCIMLoop();
+
+}  // namespace control_loops
+}  // namespace frc971
+
+#endif  // Y2015_CONTROL_LOOPS_DRIVETRAIN_POLYDRIVETRAIN_CIM_PLANT_H_
diff --git a/y2015/control_loops/drivetrain/polydrivetrain_dog_motor_plant.cc b/y2015/control_loops/drivetrain/polydrivetrain_dog_motor_plant.cc
new file mode 100644
index 0000000..811991c
--- /dev/null
+++ b/y2015/control_loops/drivetrain/polydrivetrain_dog_motor_plant.cc
@@ -0,0 +1,133 @@
+#include "y2015/control_loops/drivetrain/polydrivetrain_dog_motor_plant.h"
+
+#include <vector>
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace frc971 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<2, 2, 2> MakeVelocityDrivetrainLowLowPlantCoefficients() {
+  Eigen::Matrix<double, 2, 2> A;
+  A << 0.955499400541, 0.00962691403749, 0.00962691403749, 0.955499400541;
+  Eigen::Matrix<double, 2, 2> B;
+  B << 0.0164714763931, -0.00356331126397, -0.00356331126397, 0.0164714763931;
+  Eigen::Matrix<double, 2, 2> C;
+  C << 1.0, 0.0, 0.0, 1.0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0.0, 0.0, 0.0, 0.0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<2, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackPlantCoefficients<2, 2, 2> MakeVelocityDrivetrainLowHighPlantCoefficients() {
+  Eigen::Matrix<double, 2, 2> A;
+  A << 0.955499400541, 0.00962691403749, 0.00962691403749, 0.955499400541;
+  Eigen::Matrix<double, 2, 2> B;
+  B << 0.0164714763931, -0.00356331126397, -0.00356331126397, 0.0164714763931;
+  Eigen::Matrix<double, 2, 2> C;
+  C << 1.0, 0.0, 0.0, 1.0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0.0, 0.0, 0.0, 0.0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<2, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackPlantCoefficients<2, 2, 2> MakeVelocityDrivetrainHighLowPlantCoefficients() {
+  Eigen::Matrix<double, 2, 2> A;
+  A << 0.955499400541, 0.00962691403749, 0.00962691403749, 0.955499400541;
+  Eigen::Matrix<double, 2, 2> B;
+  B << 0.0164714763931, -0.00356331126397, -0.00356331126397, 0.0164714763931;
+  Eigen::Matrix<double, 2, 2> C;
+  C << 1.0, 0.0, 0.0, 1.0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0.0, 0.0, 0.0, 0.0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<2, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackPlantCoefficients<2, 2, 2> MakeVelocityDrivetrainHighHighPlantCoefficients() {
+  Eigen::Matrix<double, 2, 2> A;
+  A << 0.955499400541, 0.00962691403749, 0.00962691403749, 0.955499400541;
+  Eigen::Matrix<double, 2, 2> B;
+  B << 0.0164714763931, -0.00356331126397, -0.00356331126397, 0.0164714763931;
+  Eigen::Matrix<double, 2, 2> C;
+  C << 1.0, 0.0, 0.0, 1.0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0.0, 0.0, 0.0, 0.0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<2, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackController<2, 2, 2> MakeVelocityDrivetrainLowLowController() {
+  Eigen::Matrix<double, 2, 2> L;
+  L << 0.935499400541, 0.00962691403749, 0.00962691403749, 0.935499400541;
+  Eigen::Matrix<double, 2, 2> K;
+  K << 22.7750288573, 5.51143253556, 5.51143253556, 22.7750288573;
+  Eigen::Matrix<double, 2, 2> A_inv;
+  A_inv << 1.04667938127, -0.010545576923, -0.010545576923, 1.04667938127;
+  return StateFeedbackController<2, 2, 2>(L, K, A_inv, MakeVelocityDrivetrainLowLowPlantCoefficients());
+}
+
+StateFeedbackController<2, 2, 2> MakeVelocityDrivetrainLowHighController() {
+  Eigen::Matrix<double, 2, 2> L;
+  L << 0.935499400541, 0.00962691403749, 0.00962691403749, 0.935499400541;
+  Eigen::Matrix<double, 2, 2> K;
+  K << 22.7750288573, 5.51143253556, 5.51143253556, 22.7750288573;
+  Eigen::Matrix<double, 2, 2> A_inv;
+  A_inv << 1.04667938127, -0.010545576923, -0.010545576923, 1.04667938127;
+  return StateFeedbackController<2, 2, 2>(L, K, A_inv, MakeVelocityDrivetrainLowHighPlantCoefficients());
+}
+
+StateFeedbackController<2, 2, 2> MakeVelocityDrivetrainHighLowController() {
+  Eigen::Matrix<double, 2, 2> L;
+  L << 0.935499400541, 0.00962691403749, 0.00962691403749, 0.935499400541;
+  Eigen::Matrix<double, 2, 2> K;
+  K << 22.7750288573, 5.51143253556, 5.51143253556, 22.7750288573;
+  Eigen::Matrix<double, 2, 2> A_inv;
+  A_inv << 1.04667938127, -0.010545576923, -0.010545576923, 1.04667938127;
+  return StateFeedbackController<2, 2, 2>(L, K, A_inv, MakeVelocityDrivetrainHighLowPlantCoefficients());
+}
+
+StateFeedbackController<2, 2, 2> MakeVelocityDrivetrainHighHighController() {
+  Eigen::Matrix<double, 2, 2> L;
+  L << 0.935499400541, 0.00962691403749, 0.00962691403749, 0.935499400541;
+  Eigen::Matrix<double, 2, 2> K;
+  K << 22.7750288573, 5.51143253556, 5.51143253556, 22.7750288573;
+  Eigen::Matrix<double, 2, 2> A_inv;
+  A_inv << 1.04667938127, -0.010545576923, -0.010545576923, 1.04667938127;
+  return StateFeedbackController<2, 2, 2>(L, K, A_inv, MakeVelocityDrivetrainHighHighPlantCoefficients());
+}
+
+StateFeedbackPlant<2, 2, 2> MakeVelocityDrivetrainPlant() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackPlantCoefficients<2, 2, 2>>> plants(4);
+  plants[0] = ::std::unique_ptr<StateFeedbackPlantCoefficients<2, 2, 2>>(new StateFeedbackPlantCoefficients<2, 2, 2>(MakeVelocityDrivetrainLowLowPlantCoefficients()));
+  plants[1] = ::std::unique_ptr<StateFeedbackPlantCoefficients<2, 2, 2>>(new StateFeedbackPlantCoefficients<2, 2, 2>(MakeVelocityDrivetrainLowHighPlantCoefficients()));
+  plants[2] = ::std::unique_ptr<StateFeedbackPlantCoefficients<2, 2, 2>>(new StateFeedbackPlantCoefficients<2, 2, 2>(MakeVelocityDrivetrainHighLowPlantCoefficients()));
+  plants[3] = ::std::unique_ptr<StateFeedbackPlantCoefficients<2, 2, 2>>(new StateFeedbackPlantCoefficients<2, 2, 2>(MakeVelocityDrivetrainHighHighPlantCoefficients()));
+  return StateFeedbackPlant<2, 2, 2>(&plants);
+}
+
+StateFeedbackLoop<2, 2, 2> MakeVelocityDrivetrainLoop() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackController<2, 2, 2>>> controllers(4);
+  controllers[0] = ::std::unique_ptr<StateFeedbackController<2, 2, 2>>(new StateFeedbackController<2, 2, 2>(MakeVelocityDrivetrainLowLowController()));
+  controllers[1] = ::std::unique_ptr<StateFeedbackController<2, 2, 2>>(new StateFeedbackController<2, 2, 2>(MakeVelocityDrivetrainLowHighController()));
+  controllers[2] = ::std::unique_ptr<StateFeedbackController<2, 2, 2>>(new StateFeedbackController<2, 2, 2>(MakeVelocityDrivetrainHighLowController()));
+  controllers[3] = ::std::unique_ptr<StateFeedbackController<2, 2, 2>>(new StateFeedbackController<2, 2, 2>(MakeVelocityDrivetrainHighHighController()));
+  return StateFeedbackLoop<2, 2, 2>(&controllers);
+}
+
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/y2015/control_loops/drivetrain/polydrivetrain_dog_motor_plant.h b/y2015/control_loops/drivetrain/polydrivetrain_dog_motor_plant.h
new file mode 100644
index 0000000..5a99caf
--- /dev/null
+++ b/y2015/control_loops/drivetrain/polydrivetrain_dog_motor_plant.h
@@ -0,0 +1,32 @@
+#ifndef Y2015_CONTROL_LOOPS_DRIVETRAIN_POLYDRIVETRAIN_DOG_MOTOR_PLANT_H_
+#define Y2015_CONTROL_LOOPS_DRIVETRAIN_POLYDRIVETRAIN_DOG_MOTOR_PLANT_H_
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace frc971 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<2, 2, 2> MakeVelocityDrivetrainLowLowPlantCoefficients();
+
+StateFeedbackController<2, 2, 2> MakeVelocityDrivetrainLowLowController();
+
+StateFeedbackPlantCoefficients<2, 2, 2> MakeVelocityDrivetrainLowHighPlantCoefficients();
+
+StateFeedbackController<2, 2, 2> MakeVelocityDrivetrainLowHighController();
+
+StateFeedbackPlantCoefficients<2, 2, 2> MakeVelocityDrivetrainHighLowPlantCoefficients();
+
+StateFeedbackController<2, 2, 2> MakeVelocityDrivetrainHighLowController();
+
+StateFeedbackPlantCoefficients<2, 2, 2> MakeVelocityDrivetrainHighHighPlantCoefficients();
+
+StateFeedbackController<2, 2, 2> MakeVelocityDrivetrainHighHighController();
+
+StateFeedbackPlant<2, 2, 2> MakeVelocityDrivetrainPlant();
+
+StateFeedbackLoop<2, 2, 2> MakeVelocityDrivetrainLoop();
+
+}  // namespace control_loops
+}  // namespace frc971
+
+#endif  // Y2015_CONTROL_LOOPS_DRIVETRAIN_POLYDRIVETRAIN_DOG_MOTOR_PLANT_H_
diff --git a/y2015/control_loops/drivetrain/replay_drivetrain.cc b/y2015/control_loops/drivetrain/replay_drivetrain.cc
new file mode 100644
index 0000000..030a945
--- /dev/null
+++ b/y2015/control_loops/drivetrain/replay_drivetrain.cc
@@ -0,0 +1,24 @@
+#include "aos/common/controls/replay_control_loop.h"
+#include "aos/linux_code/init.h"
+
+#include "y2015/control_loops/drivetrain/drivetrain.q.h"
+
+// Reads one or more log files and sends out all the queue messages (in the
+// correct order and at the correct time) to feed a "live" drivetrain process.
+
+int main(int argc, char **argv) {
+  if (argc <= 1) {
+    fprintf(stderr, "Need at least one file to replay!\n");
+    return EXIT_FAILURE;
+  }
+
+  ::aos::InitNRT();
+
+  ::aos::controls::ControlLoopReplayer<::frc971::control_loops::DrivetrainQueue>
+      replayer(&::frc971::control_loops::drivetrain_queue, "drivetrain");
+  for (int i = 1; i < argc; ++i) {
+    replayer.ProcessFile(argv[i]);
+  }
+
+  ::aos::Cleanup();
+}
diff --git a/y2015/control_loops/fridge/arm_motor_plant.cc b/y2015/control_loops/fridge/arm_motor_plant.cc
new file mode 100644
index 0000000..6e3205a
--- /dev/null
+++ b/y2015/control_loops/fridge/arm_motor_plant.cc
@@ -0,0 +1,49 @@
+#include "y2015/control_loops/fridge/arm_motor_plant.h"
+
+#include <vector>
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace frc971 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeArmPlantCoefficients() {
+  Eigen::Matrix<double, 4, 4> A;
+  A << 1.0, 0.00479642025454, 0.0, 0.0, 0.0, 0.919688585028, 0.0, 0.0, 0.0, 0.0, 0.999539771613, 0.00479566382645, 0.0, 0.0, -0.18154390621, 0.919241022297;
+  Eigen::Matrix<double, 4, 2> B;
+  B << 2.46496779984e-05, 2.46496779984e-05, 0.00972420175808, 0.00972420175808, 2.46477449538e-05, -2.46477449538e-05, 0.00972266818532, -0.00972266818532;
+  Eigen::Matrix<double, 2, 4> C;
+  C << 1, 0, 1, 0, 1, 0, -1, 0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0, 0, 0, 0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<4, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackController<4, 2, 2> MakeArmController() {
+  Eigen::Matrix<double, 4, 2> L;
+  L << 0.759844292514, 0.759844292514, 54.2541762188, 54.2541762188, 0.759390396955, -0.759390396955, 54.1048167043, -54.1048167043;
+  Eigen::Matrix<double, 2, 4> K;
+  K << 320.979606093, 21.0129517955, 884.233784759, 36.3637782119, 320.979606095, 21.0129517956, -884.233784749, -36.3637782119;
+  Eigen::Matrix<double, 4, 4> A_inv;
+  A_inv << 1.0, -0.00521526561559, 0.0, 0.0, 0.0, 1.08732457517, 0.0, 0.0, 0.0, 0.0, 0.999513354044, -0.00521444313273, 0.0, 0.0, 0.197397150694, 1.08682415753;
+  return StateFeedbackController<4, 2, 2>(L, K, A_inv, MakeArmPlantCoefficients());
+}
+
+StateFeedbackPlant<4, 2, 2> MakeArmPlant() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackPlantCoefficients<4, 2, 2>>> plants(1);
+  plants[0] = ::std::unique_ptr<StateFeedbackPlantCoefficients<4, 2, 2>>(new StateFeedbackPlantCoefficients<4, 2, 2>(MakeArmPlantCoefficients()));
+  return StateFeedbackPlant<4, 2, 2>(&plants);
+}
+
+StateFeedbackLoop<4, 2, 2> MakeArmLoop() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackController<4, 2, 2>>> controllers(1);
+  controllers[0] = ::std::unique_ptr<StateFeedbackController<4, 2, 2>>(new StateFeedbackController<4, 2, 2>(MakeArmController()));
+  return StateFeedbackLoop<4, 2, 2>(&controllers);
+}
+
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/y2015/control_loops/fridge/arm_motor_plant.h b/y2015/control_loops/fridge/arm_motor_plant.h
new file mode 100644
index 0000000..3bf8d09
--- /dev/null
+++ b/y2015/control_loops/fridge/arm_motor_plant.h
@@ -0,0 +1,20 @@
+#ifndef Y2015_CONTROL_LOOPS_FRIDGE_ARM_MOTOR_PLANT_H_
+#define Y2015_CONTROL_LOOPS_FRIDGE_ARM_MOTOR_PLANT_H_
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace frc971 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeArmPlantCoefficients();
+
+StateFeedbackController<4, 2, 2> MakeArmController();
+
+StateFeedbackPlant<4, 2, 2> MakeArmPlant();
+
+StateFeedbackLoop<4, 2, 2> MakeArmLoop();
+
+}  // namespace control_loops
+}  // namespace frc971
+
+#endif  // Y2015_CONTROL_LOOPS_FRIDGE_ARM_MOTOR_PLANT_H_
diff --git a/y2015/control_loops/fridge/elevator_motor_plant.cc b/y2015/control_loops/fridge/elevator_motor_plant.cc
new file mode 100644
index 0000000..995d838
--- /dev/null
+++ b/y2015/control_loops/fridge/elevator_motor_plant.cc
@@ -0,0 +1,49 @@
+#include "y2015/control_loops/fridge/elevator_motor_plant.h"
+
+#include <vector>
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace frc971 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeElevatorPlantCoefficients() {
+  Eigen::Matrix<double, 4, 4> A;
+  A << 1.0, 0.00435668193669, 0.0, 0.0, 0.0, 0.754212786054, 0.0, 0.0, 0.0, 0.0, 0.997194498569, 0.00435222083164, 0.0, 0.0, -1.07131589702, 0.751658962986;
+  Eigen::Matrix<double, 4, 2> B;
+  B << 3.82580284276e-05, 3.82580284276e-05, 0.0146169286307, 0.0146169286307, 3.82387898839e-05, -3.82387898839e-05, 0.0146019613563, -0.0146019613563;
+  Eigen::Matrix<double, 2, 4> C;
+  C << 1, 0, 1, 0, 1, 0, -1, 0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0, 0, 0, 0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<4, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackController<4, 2, 2> MakeElevatorController() {
+  Eigen::Matrix<double, 4, 2> L;
+  L << 0.677106393027, 0.677106393027, 35.5375738607, 35.5375738607, 0.674426730777, -0.674426730777, 34.7138874344, -34.7138874344;
+  Eigen::Matrix<double, 2, 4> K;
+  K << 321.310606763, 11.7674534233, 601.047935717, 12.6977148843, 321.310606764, 11.7674534233, -601.047935716, -12.6977148843;
+  Eigen::Matrix<double, 4, 4> A_inv;
+  A_inv << 1.0, -0.00577646258091, 0.0, 0.0, 0.0, 1.32588576923, 0.0, 0.0, 0.0, 0.0, 0.996613922337, -0.00577054766522, 0.0, 0.0, 1.42044250221, 1.32216599481;
+  return StateFeedbackController<4, 2, 2>(L, K, A_inv, MakeElevatorPlantCoefficients());
+}
+
+StateFeedbackPlant<4, 2, 2> MakeElevatorPlant() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackPlantCoefficients<4, 2, 2>>> plants(1);
+  plants[0] = ::std::unique_ptr<StateFeedbackPlantCoefficients<4, 2, 2>>(new StateFeedbackPlantCoefficients<4, 2, 2>(MakeElevatorPlantCoefficients()));
+  return StateFeedbackPlant<4, 2, 2>(&plants);
+}
+
+StateFeedbackLoop<4, 2, 2> MakeElevatorLoop() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackController<4, 2, 2>>> controllers(1);
+  controllers[0] = ::std::unique_ptr<StateFeedbackController<4, 2, 2>>(new StateFeedbackController<4, 2, 2>(MakeElevatorController()));
+  return StateFeedbackLoop<4, 2, 2>(&controllers);
+}
+
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/y2015/control_loops/fridge/elevator_motor_plant.h b/y2015/control_loops/fridge/elevator_motor_plant.h
new file mode 100644
index 0000000..e68e6d7
--- /dev/null
+++ b/y2015/control_loops/fridge/elevator_motor_plant.h
@@ -0,0 +1,20 @@
+#ifndef Y2015_CONTROL_LOOPS_FRIDGE_ELEVATOR_MOTOR_PLANT_H_
+#define Y2015_CONTROL_LOOPS_FRIDGE_ELEVATOR_MOTOR_PLANT_H_
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace frc971 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<4, 2, 2> MakeElevatorPlantCoefficients();
+
+StateFeedbackController<4, 2, 2> MakeElevatorController();
+
+StateFeedbackPlant<4, 2, 2> MakeElevatorPlant();
+
+StateFeedbackLoop<4, 2, 2> MakeElevatorLoop();
+
+}  // namespace control_loops
+}  // namespace frc971
+
+#endif  // Y2015_CONTROL_LOOPS_FRIDGE_ELEVATOR_MOTOR_PLANT_H_
diff --git a/y2015/control_loops/fridge/fridge.cc b/y2015/control_loops/fridge/fridge.cc
new file mode 100644
index 0000000..083baf2
--- /dev/null
+++ b/y2015/control_loops/fridge/fridge.cc
@@ -0,0 +1,720 @@
+#include "y2015/control_loops/fridge/fridge.h"
+
+#include <cmath>
+
+#include "aos/common/controls/control_loops.q.h"
+#include "aos/common/logging/logging.h"
+
+#include "y2015/control_loops/fridge/elevator_motor_plant.h"
+#include "y2015/control_loops/fridge/integral_arm_plant.h"
+#include "frc971/control_loops/voltage_cap/voltage_cap.h"
+#include "frc971/zeroing/zeroing.h"
+
+#include "y2015/constants.h"
+
+namespace frc971 {
+namespace control_loops {
+
+namespace {
+constexpr double kZeroingVoltage = 4.0;
+constexpr double kElevatorZeroingVelocity = 0.10;
+// What speed we move to our safe height at.
+constexpr double kElevatorSafeHeightVelocity = 0.3;
+constexpr double kArmZeroingVelocity = 0.20;
+}  // namespace
+
+template <int S>
+void CappedStateFeedbackLoop<S>::CapU() {
+  VoltageCap(max_voltage_, this->U(0, 0), this->U(1, 0), &this->mutable_U(0, 0),
+             &this->mutable_U(1, 0));
+}
+
+template <int S>
+Eigen::Matrix<double, 2, 1>
+CappedStateFeedbackLoop<S>::UnsaturateOutputGoalChange() {
+  // Compute the K matrix used to compensate for position errors.
+  Eigen::Matrix<double, 2, 2> Kp;
+  Kp.setZero();
+  Kp.col(0) = this->K().col(0);
+  Kp.col(1) = this->K().col(2);
+
+  Eigen::Matrix<double, 2, 2> Kp_inv = Kp.inverse();
+
+  // Compute how much we need to change R in order to achieve the change in U
+  // that was observed.
+  Eigen::Matrix<double, 2, 1> deltaR =
+      -Kp_inv * (this->U_uncapped() - this->U());
+  return deltaR;
+}
+
+Fridge::Fridge(control_loops::FridgeQueue *fridge)
+    : aos::controls::ControlLoop<control_loops::FridgeQueue>(fridge),
+      arm_loop_(new CappedStateFeedbackLoop<5>(
+          StateFeedbackLoop<5, 2, 2>(MakeIntegralArmLoop()))),
+      elevator_loop_(new CappedStateFeedbackLoop<4>(
+          StateFeedbackLoop<4, 2, 2>(MakeElevatorLoop()))),
+      left_arm_estimator_(constants::GetValues().fridge.left_arm_zeroing),
+      right_arm_estimator_(constants::GetValues().fridge.right_arm_zeroing),
+      left_elevator_estimator_(constants::GetValues().fridge.left_elev_zeroing),
+      right_elevator_estimator_(
+          constants::GetValues().fridge.right_elev_zeroing),
+      last_profiling_type_(ProfilingType::ANGLE_HEIGHT_PROFILING),
+      kinematics_(constants::GetValues().fridge.arm_length,
+                  constants::GetValues().fridge.elevator.upper_limit,
+                  constants::GetValues().fridge.elevator.lower_limit,
+                  constants::GetValues().fridge.arm.upper_limit,
+                  constants::GetValues().fridge.arm.lower_limit),
+      arm_profile_(::aos::controls::kLoopFrequency),
+      elevator_profile_(::aos::controls::kLoopFrequency),
+      x_profile_(::aos::controls::kLoopFrequency),
+      y_profile_(::aos::controls::kLoopFrequency) {}
+
+void Fridge::UpdateZeroingState() {
+  if (left_elevator_estimator_.offset_ratio_ready() < 1.0 ||
+      right_elevator_estimator_.offset_ratio_ready() < 1.0 ||
+      left_arm_estimator_.offset_ratio_ready() < 1.0 ||
+      right_arm_estimator_.offset_ratio_ready() < 1.0) {
+    state_ = INITIALIZING;
+  } else if (!left_elevator_estimator_.zeroed() ||
+             !right_elevator_estimator_.zeroed()) {
+    state_ = ZEROING_ELEVATOR;
+  } else if (!left_arm_estimator_.zeroed() || !right_arm_estimator_.zeroed()) {
+    state_ = ZEROING_ARM;
+  } else {
+    state_ = RUNNING;
+  }
+}
+
+void Fridge::Correct() {
+  {
+    Eigen::Matrix<double, 2, 1> Y;
+    Y << left_elevator(), right_elevator();
+    elevator_loop_->Correct(Y);
+  }
+
+  {
+    Eigen::Matrix<double, 2, 1> Y;
+    Y << left_arm(), right_arm();
+    arm_loop_->Correct(Y);
+  }
+}
+
+void Fridge::SetElevatorOffset(double left_offset, double right_offset) {
+  LOG(INFO, "Changing Elevator offset from %f, %f to %f, %f\n",
+      left_elevator_offset_, right_elevator_offset_, left_offset, right_offset);
+  double left_doffset = left_offset - left_elevator_offset_;
+  double right_doffset = right_offset - right_elevator_offset_;
+
+  // Adjust the average height and height difference between the two sides.
+  // The derivatives of both should not need to be updated since the speeds
+  // haven't changed.
+  // The height difference is calculated as left - right, not right - left.
+  elevator_loop_->mutable_X_hat(0, 0) += (left_doffset + right_doffset) / 2;
+  elevator_loop_->mutable_X_hat(2, 0) += (left_doffset - right_doffset) / 2;
+
+  // Modify the zeroing goal.
+  elevator_goal_ += (left_doffset + right_doffset) / 2;
+
+  // Update the cached offset values to the actual values.
+  left_elevator_offset_ = left_offset;
+  right_elevator_offset_ = right_offset;
+}
+
+void Fridge::SetArmOffset(double left_offset, double right_offset) {
+  LOG(INFO, "Changing Arm offset from %f, %f to %f, %f\n", left_arm_offset_,
+      right_arm_offset_, left_offset, right_offset);
+  double left_doffset = left_offset - left_arm_offset_;
+  double right_doffset = right_offset - right_arm_offset_;
+
+  // Adjust the average angle and angle difference between the two sides.
+  // The derivatives of both should not need to be updated since the speeds
+  // haven't changed.
+  arm_loop_->mutable_X_hat(0, 0) += (left_doffset + right_doffset) / 2;
+  arm_loop_->mutable_X_hat(2, 0) += (left_doffset - right_doffset) / 2;
+
+  // Modify the zeroing goal.
+  arm_goal_ += (left_doffset + right_doffset) / 2;
+
+  // Update the cached offset values to the actual values.
+  left_arm_offset_ = left_offset;
+  right_arm_offset_ = right_offset;
+}
+
+double Fridge::estimated_left_elevator() {
+  return current_position_.elevator.left.encoder +
+         left_elevator_estimator_.offset();
+}
+double Fridge::estimated_right_elevator() {
+  return current_position_.elevator.right.encoder +
+         right_elevator_estimator_.offset();
+}
+
+double Fridge::estimated_elevator() {
+  return (estimated_left_elevator() + estimated_right_elevator()) / 2.0;
+}
+
+double Fridge::estimated_left_arm() {
+  return current_position_.arm.left.encoder + left_arm_estimator_.offset();
+}
+double Fridge::estimated_right_arm() {
+  return current_position_.arm.right.encoder + right_arm_estimator_.offset();
+}
+double Fridge::estimated_arm() {
+  return (estimated_left_arm() + estimated_right_arm()) / 2.0;
+}
+
+double Fridge::left_elevator() {
+  return current_position_.elevator.left.encoder + left_elevator_offset_;
+}
+double Fridge::right_elevator() {
+  return current_position_.elevator.right.encoder + right_elevator_offset_;
+}
+
+double Fridge::elevator() { return (left_elevator() + right_elevator()) / 2.0; }
+
+double Fridge::left_arm() {
+  return current_position_.arm.left.encoder + left_arm_offset_;
+}
+double Fridge::right_arm() {
+  return current_position_.arm.right.encoder + right_arm_offset_;
+}
+double Fridge::arm() { return (left_arm() + right_arm()) / 2.0; }
+
+double Fridge::elevator_zeroing_velocity() {
+  double average_elevator =
+      (constants::GetValues().fridge.elevator.lower_limit +
+       constants::GetValues().fridge.elevator.upper_limit) /
+      2.0;
+
+  const double pulse_width = ::std::max(
+      constants::GetValues().fridge.left_elev_zeroing.index_difference,
+      constants::GetValues().fridge.right_elev_zeroing.index_difference);
+
+  if (elevator_zeroing_velocity_ == 0) {
+    if (estimated_elevator() > average_elevator) {
+      elevator_zeroing_velocity_ = -kElevatorZeroingVelocity;
+    } else {
+      elevator_zeroing_velocity_ = kElevatorZeroingVelocity;
+    }
+  } else if (elevator_zeroing_velocity_ > 0 &&
+             estimated_elevator() > average_elevator + 1.1 * pulse_width) {
+    elevator_zeroing_velocity_ = -kElevatorZeroingVelocity;
+  } else if (elevator_zeroing_velocity_ < 0 &&
+             estimated_elevator() < average_elevator - 1.1 * pulse_width) {
+    elevator_zeroing_velocity_ = kElevatorZeroingVelocity;
+  }
+  return elevator_zeroing_velocity_;
+}
+
+double Fridge::UseUnlessZero(double target_value, double default_value) {
+  if (target_value != 0.0) {
+    return target_value;
+  } else {
+    return default_value;
+  }
+}
+
+double Fridge::arm_zeroing_velocity() {
+  const double average_arm = (constants::GetValues().fridge.arm.lower_limit +
+                              constants::GetValues().fridge.arm.upper_limit) /
+                             2.0;
+  const double pulse_width = ::std::max(
+      constants::GetValues().fridge.right_arm_zeroing.index_difference,
+      constants::GetValues().fridge.left_arm_zeroing.index_difference);
+
+  if (arm_zeroing_velocity_ == 0) {
+    if (estimated_arm() > average_arm) {
+      arm_zeroing_velocity_ = -kArmZeroingVelocity;
+    } else {
+      arm_zeroing_velocity_ = kArmZeroingVelocity;
+    }
+  } else if (arm_zeroing_velocity_ > 0.0 &&
+             estimated_arm() > average_arm + 1.1 * pulse_width) {
+    arm_zeroing_velocity_ = -kArmZeroingVelocity;
+  } else if (arm_zeroing_velocity_ < 0.0 && estimated_arm() < average_arm) {
+    arm_zeroing_velocity_ = kArmZeroingVelocity;
+  }
+  return arm_zeroing_velocity_;
+}
+
+void Fridge::RunIteration(const control_loops::FridgeQueue::Goal *unsafe_goal,
+                          const control_loops::FridgeQueue::Position *position,
+                          control_loops::FridgeQueue::Output *output,
+                          control_loops::FridgeQueue::Status *status) {
+  if (WasReset()) {
+    LOG(ERROR, "WPILib reset, restarting\n");
+    left_elevator_estimator_.Reset();
+    right_elevator_estimator_.Reset();
+    left_arm_estimator_.Reset();
+    right_arm_estimator_.Reset();
+    state_ = UNINITIALIZED;
+  }
+
+  // Get a reference to the constants struct since we use it so often in this
+  // code.
+  const auto &values = constants::GetValues();
+
+  // Bool to track if we should turn the motors on or not.
+  bool disable = output == nullptr;
+
+  // Save the current position so it can be used easily in the class.
+  current_position_ = *position;
+
+  left_elevator_estimator_.UpdateEstimate(position->elevator.left);
+  right_elevator_estimator_.UpdateEstimate(position->elevator.right);
+  left_arm_estimator_.UpdateEstimate(position->arm.left);
+  right_arm_estimator_.UpdateEstimate(position->arm.right);
+
+  if (state_ != UNINITIALIZED) {
+    Correct();
+  }
+
+  // Zeroing will work as follows:
+  // At startup, record the offset of the two halves of the two subsystems.
+  // Then, start moving the elevator towards the center until both halves are
+  // zeroed.
+  // Then, start moving the claw towards the center until both halves are
+  // zeroed.
+  // Then, done!
+
+  // We'll then need code to do sanity checking on values.
+
+  // Now, we need to figure out which way to go.
+
+  switch (state_) {
+    case UNINITIALIZED:
+      LOG(DEBUG, "Uninitialized\n");
+      // Startup.  Assume that we are at the origin everywhere.
+      // This records the encoder offset between the two sides of the elevator.
+      left_elevator_offset_ = -position->elevator.left.encoder;
+      right_elevator_offset_ = -position->elevator.right.encoder;
+      left_arm_offset_ = -position->arm.left.encoder;
+      right_arm_offset_ = -position->arm.right.encoder;
+      elevator_loop_->mutable_X_hat().setZero();
+      arm_loop_->mutable_X_hat().setZero();
+      LOG(INFO, "Initializing arm offsets to %f, %f\n", left_arm_offset_,
+          right_arm_offset_);
+      LOG(INFO, "Initializing elevator offsets to %f, %f\n",
+          left_elevator_offset_, right_elevator_offset_);
+      Correct();
+      state_ = INITIALIZING;
+      disable = true;
+      break;
+
+    case INITIALIZING:
+      LOG(DEBUG, "Waiting for accurate initial position.\n");
+      disable = true;
+      // Update state_ to accurately represent the state of the zeroing
+      // estimators.
+      UpdateZeroingState();
+      if (state_ != INITIALIZING) {
+        // Set the goals to where we are now.
+        elevator_goal_ = elevator();
+        arm_goal_ = arm();
+      }
+      break;
+
+    case ZEROING_ELEVATOR:
+      LOG(DEBUG, "Zeroing elevator\n");
+
+      // Update state_ to accurately represent the state of the zeroing
+      // estimators.
+      UpdateZeroingState();
+      if (left_elevator_estimator_.zeroed() &&
+          right_elevator_estimator_.zeroed()) {
+        SetElevatorOffset(left_elevator_estimator_.offset(),
+                          right_elevator_estimator_.offset());
+        LOG(DEBUG, "Zeroed the elevator!\n");
+
+        if (elevator() < values.fridge.arm_zeroing_height &&
+            state_ != INITIALIZING) {
+          // Move the elevator to a safe height before we start zeroing the arm,
+          // so that we don't crash anything.
+          LOG(DEBUG, "Moving elevator to safe height.\n");
+          if (elevator_goal_ < values.fridge.arm_zeroing_height) {
+            elevator_goal_ += kElevatorSafeHeightVelocity *
+                              ::aos::controls::kLoopFrequency.ToSeconds();
+            elevator_goal_velocity_ = kElevatorSafeHeightVelocity;
+            state_ = ZEROING_ELEVATOR;
+          } else {
+            // We want it stopped at whatever height it's currently set to.
+            elevator_goal_velocity_ = 0;
+          }
+        }
+      } else if (!disable) {
+        elevator_goal_velocity_ = elevator_zeroing_velocity();
+        elevator_goal_ += elevator_goal_velocity_ *
+                          ::aos::controls::kLoopFrequency.ToSeconds();
+      }
+
+      // Bypass motion profiles while we are zeroing.
+      // This is also an important step right after the elevator is zeroed and
+      // we reach into the elevator's state matrix and change it based on the
+      // newly-obtained offset.
+      {
+        Eigen::Matrix<double, 2, 1> current;
+        current.setZero();
+        current << elevator_goal_, elevator_goal_velocity_;
+        elevator_profile_.MoveCurrentState(current);
+      }
+      break;
+
+    case ZEROING_ARM:
+      LOG(DEBUG, "Zeroing the arm\n");
+
+      if (elevator() < values.fridge.arm_zeroing_height - 0.10 ||
+          elevator_goal_ < values.fridge.arm_zeroing_height) {
+        LOG(INFO,
+            "Going back to ZEROING_ELEVATOR until it gets high enough to "
+            "safely zero the arm\n");
+        state_ = ZEROING_ELEVATOR;
+        break;
+      }
+
+      // Update state_ to accurately represent the state of the zeroing
+      // estimators.
+      UpdateZeroingState();
+      if (left_arm_estimator_.zeroed() && right_arm_estimator_.zeroed()) {
+        SetArmOffset(left_arm_estimator_.offset(),
+                     right_arm_estimator_.offset());
+        LOG(DEBUG, "Zeroed the arm!\n");
+      } else if (!disable) {
+        arm_goal_velocity_ = arm_zeroing_velocity();
+        arm_goal_ +=
+            arm_goal_velocity_ * ::aos::controls::kLoopFrequency.ToSeconds();
+      }
+
+      // Bypass motion profiles while we are zeroing.
+      // This is also an important step right after the arm is zeroed and
+      // we reach into the arm's state matrix and change it based on the
+      // newly-obtained offset.
+      {
+        Eigen::Matrix<double, 2, 1> current;
+        current.setZero();
+        current << arm_goal_, arm_goal_velocity_;
+        arm_profile_.MoveCurrentState(current);
+      }
+      break;
+
+    case RUNNING:
+      LOG(DEBUG, "Running!\n");
+      if (unsafe_goal) {
+        // Handle the case where we switch between the types of profiling.
+        ProfilingType new_profiling_type =
+            static_cast<ProfilingType>(unsafe_goal->profiling_type);
+
+        if (last_profiling_type_ != new_profiling_type) {
+          // Reset the height/angle profiles.
+          Eigen::Matrix<double, 2, 1> current;
+          current.setZero();
+          current << arm_goal_, arm_goal_velocity_;
+          arm_profile_.MoveCurrentState(current);
+          current << elevator_goal_, elevator_goal_velocity_;
+          elevator_profile_.MoveCurrentState(current);
+
+          // Reset the x/y profiles.
+          aos::util::ElevatorArmKinematics::KinematicResult x_y_result;
+          kinematics_.ForwardKinematic(elevator_goal_, arm_goal_,
+                                       elevator_goal_velocity_,
+                                       arm_goal_velocity_, &x_y_result);
+          current << x_y_result.fridge_x, x_y_result.fridge_x_velocity;
+          x_profile_.MoveCurrentState(current);
+          current << x_y_result.fridge_h, x_y_result.fridge_h_velocity;
+          y_profile_.MoveCurrentState(current);
+
+          last_profiling_type_ = new_profiling_type;
+        }
+
+        if (new_profiling_type == ProfilingType::ANGLE_HEIGHT_PROFILING) {
+          // Pick a set of sane arm defaults if none are specified.
+          arm_profile_.set_maximum_velocity(
+              UseUnlessZero(unsafe_goal->max_angular_velocity, 1.0));
+          arm_profile_.set_maximum_acceleration(
+              UseUnlessZero(unsafe_goal->max_angular_acceleration, 3.0));
+          elevator_profile_.set_maximum_velocity(
+              UseUnlessZero(unsafe_goal->max_velocity, 0.50));
+          elevator_profile_.set_maximum_acceleration(
+              UseUnlessZero(unsafe_goal->max_acceleration, 2.0));
+
+          // Use the profiles to limit the arm's movements.
+          const double unfiltered_arm_goal = ::std::max(
+              ::std::min(unsafe_goal->angle, values.fridge.arm.upper_limit),
+              values.fridge.arm.lower_limit);
+          ::Eigen::Matrix<double, 2, 1> arm_goal_state = arm_profile_.Update(
+              unfiltered_arm_goal, unsafe_goal->angular_velocity);
+          arm_goal_ = arm_goal_state(0, 0);
+          arm_goal_velocity_ = arm_goal_state(1, 0);
+
+          // Use the profiles to limit the elevator's movements.
+          const double unfiltered_elevator_goal =
+              ::std::max(::std::min(unsafe_goal->height,
+                                    values.fridge.elevator.upper_limit),
+                         values.fridge.elevator.lower_limit);
+          ::Eigen::Matrix<double, 2, 1> elevator_goal_state =
+              elevator_profile_.Update(unfiltered_elevator_goal,
+                                       unsafe_goal->velocity);
+          elevator_goal_ = elevator_goal_state(0, 0);
+          elevator_goal_velocity_ = elevator_goal_state(1, 0);
+        } else if (new_profiling_type == ProfilingType::X_Y_PROFILING) {
+          // Use x/y profiling
+          aos::util::ElevatorArmKinematics::KinematicResult kinematic_result;
+
+          x_profile_.set_maximum_velocity(
+              UseUnlessZero(unsafe_goal->max_x_velocity, 0.5));
+          x_profile_.set_maximum_acceleration(
+              UseUnlessZero(unsafe_goal->max_x_acceleration, 2.0));
+          y_profile_.set_maximum_velocity(
+              UseUnlessZero(unsafe_goal->max_y_velocity, 0.50));
+          y_profile_.set_maximum_acceleration(
+              UseUnlessZero(unsafe_goal->max_y_acceleration, 2.0));
+
+          // Limit the goals before we update the profiles.
+          kinematics_.InverseKinematic(
+              unsafe_goal->x, unsafe_goal->y, unsafe_goal->x_velocity,
+              unsafe_goal->y_velocity, &kinematic_result);
+
+          // Use the profiles to limit the x movements.
+          ::Eigen::Matrix<double, 2, 1> x_goal_state = x_profile_.Update(
+              kinematic_result.fridge_x, kinematic_result.fridge_x_velocity);
+
+          // Use the profiles to limit the y movements.
+          ::Eigen::Matrix<double, 2, 1> y_goal_state = y_profile_.Update(
+              kinematic_result.fridge_h, kinematic_result.fridge_h_velocity);
+
+          // Convert x/y goal states into arm/elevator goals.
+          // The inverse kinematics functions automatically perform range
+          // checking and adjust the results so that they're always valid.
+          kinematics_.InverseKinematic(x_goal_state(0, 0), y_goal_state(0, 0),
+                                       x_goal_state(1, 0), y_goal_state(1, 0),
+                                       &kinematic_result);
+
+          // Store the appropriate inverse kinematic results in the
+          // arm/elevator goals.
+          arm_goal_ = kinematic_result.arm_angle;
+          arm_goal_velocity_ = kinematic_result.arm_velocity;
+
+          elevator_goal_ = kinematic_result.elevator_height;
+          elevator_goal_velocity_ = kinematic_result.arm_velocity;
+        } else {
+          LOG(ERROR, "Unknown profiling_type: %d\n",
+              unsafe_goal->profiling_type);
+        }
+      }
+
+      // Update state_ to accurately represent the state of the zeroing
+      // estimators.
+      UpdateZeroingState();
+
+      if (state_ != RUNNING && state_ != ESTOP) {
+        state_ = UNINITIALIZED;
+      }
+      break;
+
+    case ESTOP:
+      LOG(ERROR, "Estop\n");
+      disable = true;
+      break;
+  }
+
+  // Commence death if either left/right tracking error gets too big. This
+  // should run immediately after the SetArmOffset and SetElevatorOffset
+  // functions to double-check that the hardware is in a sane state.
+  if (::std::abs(left_arm() - right_arm()) >=
+      values.max_allowed_left_right_arm_difference) {
+    LOG(ERROR, "The arms are too far apart.  |%f - %f| > %f\n", left_arm(),
+        right_arm(), values.max_allowed_left_right_arm_difference);
+
+    // Indicate an ESTOP condition and stop the motors.
+    if (output) {
+      state_ = ESTOP;
+    }
+    disable = true;
+  }
+
+  if (::std::abs(left_elevator() - right_elevator()) >=
+      values.max_allowed_left_right_elevator_difference) {
+    LOG(ERROR, "The elevators are too far apart.  |%f - %f| > %f\n",
+        left_elevator(), right_elevator(),
+        values.max_allowed_left_right_elevator_difference);
+
+    // Indicate an ESTOP condition and stop the motors.
+    if (output) {
+      state_ = ESTOP;
+    }
+    disable = true;
+  }
+
+  // Limit the goals so we can't exceed the hardware limits if we are RUNNING.
+  if (state_ == RUNNING) {
+    // Limit the arm goal to min/max allowable angles.
+    if (arm_goal_ >= values.fridge.arm.upper_limit) {
+      LOG(WARNING, "Arm goal above limit, %f > %f\n", arm_goal_,
+          values.fridge.arm.upper_limit);
+      arm_goal_ = values.fridge.arm.upper_limit;
+    }
+    if (arm_goal_ <= values.fridge.arm.lower_limit) {
+      LOG(WARNING, "Arm goal below limit, %f < %f\n", arm_goal_,
+          values.fridge.arm.lower_limit);
+      arm_goal_ = values.fridge.arm.lower_limit;
+    }
+
+    // Limit the elevator goal to min/max allowable heights.
+    if (elevator_goal_ >= values.fridge.elevator.upper_limit) {
+      LOG(WARNING, "Elevator goal above limit, %f > %f\n", elevator_goal_,
+          values.fridge.elevator.upper_limit);
+      elevator_goal_ = values.fridge.elevator.upper_limit;
+    }
+    if (elevator_goal_ <= values.fridge.elevator.lower_limit) {
+      LOG(WARNING, "Elevator goal below limit, %f < %f\n", elevator_goal_,
+          values.fridge.elevator.lower_limit);
+      elevator_goal_ = values.fridge.elevator.lower_limit;
+    }
+  }
+
+  // Check the lower level hardware limit as well.
+  if (state_ == RUNNING) {
+    if (left_arm() >= values.fridge.arm.upper_hard_limit ||
+        left_arm() <= values.fridge.arm.lower_hard_limit) {
+      LOG(ERROR, "Left arm at %f out of bounds [%f, %f], ESTOPing\n",
+          left_arm(), values.fridge.arm.lower_hard_limit,
+          values.fridge.arm.upper_hard_limit);
+      if (output) {
+        state_ = ESTOP;
+      }
+    }
+
+    if (right_arm() >= values.fridge.arm.upper_hard_limit ||
+        right_arm() <= values.fridge.arm.lower_hard_limit) {
+      LOG(ERROR, "Right arm at %f out of bounds [%f, %f], ESTOPing\n",
+          right_arm(), values.fridge.arm.lower_hard_limit,
+          values.fridge.arm.upper_hard_limit);
+      if (output) {
+        state_ = ESTOP;
+      }
+    }
+
+    if (left_elevator() >= values.fridge.elevator.upper_hard_limit) {
+      LOG(ERROR, "Left elevator at %f out of bounds [%f, %f], ESTOPing\n",
+          left_elevator(), values.fridge.elevator.lower_hard_limit,
+          values.fridge.elevator.upper_hard_limit);
+      if (output) {
+        state_ = ESTOP;
+      }
+    }
+
+    if (right_elevator() >= values.fridge.elevator.upper_hard_limit) {
+      LOG(ERROR, "Right elevator at %f out of bounds [%f, %f], ESTOPing\n",
+          right_elevator(), values.fridge.elevator.lower_hard_limit,
+          values.fridge.elevator.upper_hard_limit);
+      if (output) {
+        state_ = ESTOP;
+      }
+    }
+  }
+
+  // Set the goals.
+  arm_loop_->mutable_R() << arm_goal_, arm_goal_velocity_, 0.0, 0.0, 0.0;
+  elevator_loop_->mutable_R() << elevator_goal_, elevator_goal_velocity_, 0.0,
+      0.0;
+
+  const double max_voltage = state_ == RUNNING ? 12.0 : kZeroingVoltage;
+  arm_loop_->set_max_voltage(max_voltage);
+  elevator_loop_->set_max_voltage(max_voltage);
+
+  if (state_ == ESTOP) {
+    disable = true;
+  }
+  arm_loop_->Update(disable);
+  elevator_loop_->Update(disable);
+
+  if (state_ == INITIALIZING || state_ == ZEROING_ELEVATOR ||
+      state_ == ZEROING_ARM) {
+    if (arm_loop_->U() != arm_loop_->U_uncapped()) {
+      Eigen::Matrix<double, 2, 1> deltaR =
+          arm_loop_->UnsaturateOutputGoalChange();
+
+      // Move the average arm goal by the amount observed.
+      LOG(WARNING, "Moving arm goal by %f to handle saturation\n",
+          deltaR(0, 0));
+      arm_goal_ += deltaR(0, 0);
+    }
+
+    if (elevator_loop_->U() != elevator_loop_->U_uncapped()) {
+      Eigen::Matrix<double, 2, 1> deltaR =
+          elevator_loop_->UnsaturateOutputGoalChange();
+
+      // Move the average elevator goal by the amount observed.
+      LOG(WARNING, "Moving elevator goal by %f to handle saturation\n",
+          deltaR(0, 0));
+      elevator_goal_ += deltaR(0, 0);
+    }
+  }
+
+  if (output) {
+    output->left_arm = arm_loop_->U(0, 0);
+    output->right_arm = arm_loop_->U(1, 0);
+    output->left_elevator = elevator_loop_->U(0, 0);
+    output->right_elevator = elevator_loop_->U(1, 0);
+    if (unsafe_goal) {
+      output->grabbers = unsafe_goal->grabbers;
+    } else {
+      output->grabbers.top_front = false;
+      output->grabbers.top_back = false;
+      output->grabbers.bottom_front = false;
+      output->grabbers.bottom_back = false;
+    }
+  }
+
+  // TODO(austin): Populate these fully.
+  status->zeroed = state_ == RUNNING;
+
+  status->angle = arm_loop_->X_hat(0, 0);
+  status->angular_velocity = arm_loop_->X_hat(1, 0);
+  status->height = elevator_loop_->X_hat(0, 0);
+  status->velocity = elevator_loop_->X_hat(1, 0);
+
+  status->goal_angle = arm_goal_;
+  status->goal_angular_velocity = arm_goal_velocity_;
+  status->goal_height = elevator_goal_;
+  status->goal_velocity = elevator_goal_velocity_;
+
+  // Populate the same status, but in X/Y co-ordinates.
+  aos::util::ElevatorArmKinematics::KinematicResult x_y_status;
+  kinematics_.ForwardKinematic(status->height, status->angle,
+                               status->velocity, status->angular_velocity,
+                               &x_y_status);
+  status->x = x_y_status.fridge_x;
+  status->y = x_y_status.fridge_h;
+  status->x_velocity = x_y_status.fridge_x_velocity;
+  status->y_velocity = x_y_status.fridge_h_velocity;
+
+  kinematics_.ForwardKinematic(status->goal_height, status->goal_angle,
+                               status->goal_velocity, status->goal_angular_velocity,
+                               &x_y_status);
+  status->goal_x = x_y_status.fridge_x;
+  status->goal_y = x_y_status.fridge_h;
+  status->goal_x_velocity = x_y_status.fridge_x_velocity;
+  status->goal_y_velocity = x_y_status.fridge_h_velocity;
+
+  if (unsafe_goal) {
+    status->grabbers = unsafe_goal->grabbers;
+  } else {
+    status->grabbers.top_front = false;
+    status->grabbers.top_back = false;
+    status->grabbers.bottom_front = false;
+    status->grabbers.bottom_back = false;
+  }
+  zeroing::PopulateEstimatorState(left_arm_estimator_, &status->left_arm_state);
+  zeroing::PopulateEstimatorState(right_arm_estimator_,
+                                  &status->right_arm_state);
+  zeroing::PopulateEstimatorState(left_elevator_estimator_,
+                                  &status->left_elevator_state);
+  zeroing::PopulateEstimatorState(right_elevator_estimator_,
+                                  &status->right_elevator_state);
+  status->estopped = (state_ == ESTOP);
+  status->state = state_;
+  last_state_ = state_;
+}
+
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/y2015/control_loops/fridge/fridge.gyp b/y2015/control_loops/fridge/fridge.gyp
new file mode 100644
index 0000000..76844c4
--- /dev/null
+++ b/y2015/control_loops/fridge/fridge.gyp
@@ -0,0 +1,89 @@
+{
+  'targets': [
+    {
+      'target_name': 'replay_fridge',
+      'type': 'executable',
+      'variables': {
+        'no_rsync': 1,
+      },
+      'sources': [
+        'replay_fridge.cc',
+      ],
+      'dependencies': [
+        'fridge_queue',
+        '<(AOS)/common/controls/controls.gyp:replay_control_loop',
+        '<(AOS)/linux_code/linux_code.gyp:init',
+      ],
+    },
+    {
+      'target_name': 'fridge_queue',
+      'type': 'static_library',
+      'sources': ['fridge.q'],
+      'variables': {
+        'header_path': 'y2015/control_loops/fridge',
+      },
+      'dependencies': [
+        '<(AOS)/common/controls/controls.gyp:control_loop_queues',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:queues',
+        '<(DEPTH)/frc971/zeroing/zeroing.gyp:zeroing',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/common/controls/controls.gyp:control_loop_queues',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:queues',
+        '<(DEPTH)/frc971/zeroing/zeroing.gyp:zeroing',
+      ],
+      'includes': ['../../../aos/build/queues.gypi'],
+    },
+    {
+      'target_name': 'fridge_lib',
+      'type': 'static_library',
+      'sources': [
+        'fridge.cc',
+        'integral_arm_plant.cc',
+        'elevator_motor_plant.cc',
+      ],
+      'dependencies': [
+        'fridge_queue',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+        '<(AOS)/common/util/util.gyp:trapezoid_profile',
+        '<(DEPTH)/y2015/y2015.gyp:constants',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+        '<(DEPTH)/frc971/control_loops/voltage_cap/voltage_cap.gyp:voltage_cap',
+      ],
+      'export_dependent_settings': [
+        'fridge_queue',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+        '<(AOS)/common/util/util.gyp:trapezoid_profile',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+      ],
+    },
+    {
+      'target_name': 'fridge_lib_test',
+      'type': 'executable',
+      'sources': [
+        'fridge_lib_test.cc',
+        'arm_motor_plant.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+        'fridge_lib',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+        '<(AOS)/common/controls/controls.gyp:control_loop_test',
+        '<(AOS)/common/common.gyp:time',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:position_sensor_sim',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:team_number_test_environment',
+      ],
+    },
+    {
+      'target_name': 'fridge',
+      'type': 'executable',
+      'sources': [
+        'fridge_main.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        'fridge_lib',
+      ],
+    },
+  ],
+}
diff --git a/y2015/control_loops/fridge/fridge.h b/y2015/control_loops/fridge/fridge.h
new file mode 100644
index 0000000..0448e09
--- /dev/null
+++ b/y2015/control_loops/fridge/fridge.h
@@ -0,0 +1,172 @@
+#ifndef Y2015_CONTROL_LOOPS_FRIDGE_H_
+#define Y2015_CONTROL_LOOPS_FRIDGE_H_
+
+#include <memory>
+
+#include "aos/common/controls/control_loop.h"
+#include "aos/common/util/trapezoid_profile.h"
+#include "frc971/control_loops/state_feedback_loop.h"
+#include "y2015/control_loops/fridge/fridge.q.h"
+#include "frc971/zeroing/zeroing.h"
+#include "y2015/util/kinematics.h"
+
+namespace frc971 {
+namespace control_loops {
+namespace testing {
+class FridgeTest_DisabledGoalTest_Test;
+class FridgeTest_ArmGoalPositiveWindupTest_Test;
+class FridgeTest_ElevatorGoalPositiveWindupTest_Test;
+class FridgeTest_ArmGoalNegativeWindupTest_Test;
+class FridgeTest_ElevatorGoalNegativeWindupTest_Test;
+class FridgeTest_SafeArmZeroing_Test;
+}  // namespace testing
+
+template<int S>
+class CappedStateFeedbackLoop : public StateFeedbackLoop<S, 2, 2> {
+ public:
+  CappedStateFeedbackLoop(StateFeedbackLoop<S, 2, 2> &&loop)
+      : StateFeedbackLoop<S, 2, 2>(::std::move(loop)), max_voltage_(12.0) {}
+
+  void set_max_voltage(double max_voltage) {
+    max_voltage_ = ::std::max(0.0, ::std::min(12.0, max_voltage));
+  }
+
+  void CapU() override;
+
+  // Returns the amount to change the position goals (average and difference) in
+  // order to no longer saturate the controller.
+  Eigen::Matrix<double, 2, 1> UnsaturateOutputGoalChange();
+
+ private:
+  double max_voltage_;
+};
+
+class Fridge
+    : public aos::controls::ControlLoop<control_loops::FridgeQueue> {
+ public:
+  explicit Fridge(
+      control_loops::FridgeQueue *fridge_queue = &control_loops::fridge_queue);
+
+  enum State {
+    // Waiting to receive data before doing anything.
+    UNINITIALIZED = 0,
+    // Estimating the starting location.
+    INITIALIZING = 1,
+    // Moving the elevator to find an index pulse.
+    ZEROING_ELEVATOR = 2,
+    // Moving the arm to find an index pulse.
+    ZEROING_ARM = 3,
+    // All good!
+    RUNNING = 4,
+    // Internal error caused the fridge to abort.
+    ESTOP = 5,
+  };
+
+  enum class ProfilingType : int32_t {
+    // Use angle/height to specify the fridge goal.
+    ANGLE_HEIGHT_PROFILING = 0,
+    // Use x/y co-ordinates to specify the fridge goal.
+    X_Y_PROFILING = 1,
+  };
+
+  State state() const { return state_; }
+
+ protected:
+  void RunIteration(const control_loops::FridgeQueue::Goal *goal,
+                    const control_loops::FridgeQueue::Position *position,
+                    control_loops::FridgeQueue::Output *output,
+                    control_loops::FridgeQueue::Status *status) override;
+
+ private:
+  friend class testing::FridgeTest_DisabledGoalTest_Test;
+  friend class testing::FridgeTest_ElevatorGoalPositiveWindupTest_Test;
+  friend class testing::FridgeTest_ArmGoalPositiveWindupTest_Test;
+  friend class testing::FridgeTest_ElevatorGoalNegativeWindupTest_Test;
+  friend class testing::FridgeTest_ArmGoalNegativeWindupTest_Test;
+  friend class testing::FridgeTest_SafeArmZeroing_Test;
+
+  // Sets state_ to the correct state given the current state of the zeroing
+  // estimators.
+  void UpdateZeroingState();
+
+  void SetElevatorOffset(double left_offset, double right_offset);
+  void SetArmOffset(double left_offset, double right_offset);
+
+  // Getters for the current elevator positions.
+  double left_elevator();
+  double right_elevator();
+  double elevator();
+
+  // Getters for the current arm positions.
+  double left_arm();
+  double right_arm();
+  double arm();
+
+  // Our best guess at the current position of the elevator.
+  double estimated_left_elevator();
+  double estimated_right_elevator();
+  double estimated_elevator();
+
+  // Our best guess at the current position of the arm.
+  double estimated_left_arm();
+  double estimated_right_arm();
+  double estimated_arm();
+
+  // Returns the current zeroing velocity for either subsystem.
+  // If the subsystem is too far away from the center, these will switch
+  // directions.
+  double elevator_zeroing_velocity();
+  double arm_zeroing_velocity();
+
+  // Corrects the Observer with the current position.
+  void Correct();
+
+  double UseUnlessZero(double target_value, double default_value);
+
+  // The state feedback control loop or loops to talk to.
+  ::std::unique_ptr<CappedStateFeedbackLoop<5>> arm_loop_;
+  ::std::unique_ptr<CappedStateFeedbackLoop<4>> elevator_loop_;
+
+  zeroing::ZeroingEstimator left_arm_estimator_;
+  zeroing::ZeroingEstimator right_arm_estimator_;
+  zeroing::ZeroingEstimator left_elevator_estimator_;
+  zeroing::ZeroingEstimator right_elevator_estimator_;
+
+  // Offsets from the encoder position to the absolute position.  Add these to
+  // the encoder position to get the absolute position.
+  double left_elevator_offset_ = 0.0;
+  double right_elevator_offset_ = 0.0;
+  double left_arm_offset_ = 0.0;
+  double right_arm_offset_ = 0.0;
+
+  // Current velocity to move at while zeroing.
+  double elevator_zeroing_velocity_ = 0.0;
+  double arm_zeroing_velocity_ = 0.0;
+
+  // The goals for the elevator and arm.
+  double elevator_goal_ = 0.0;
+  double arm_goal_ = 0.0;
+
+  double arm_goal_velocity_ = 0.0;
+  double elevator_goal_velocity_ = 0.0;
+
+  State state_ = UNINITIALIZED;
+  State last_state_ = UNINITIALIZED;
+
+  control_loops::FridgeQueue::Position current_position_;
+
+  ProfilingType last_profiling_type_;
+  aos::util::ElevatorArmKinematics kinematics_;
+
+  aos::util::TrapezoidProfile arm_profile_;
+  aos::util::TrapezoidProfile elevator_profile_;
+
+  aos::util::TrapezoidProfile x_profile_;
+  aos::util::TrapezoidProfile y_profile_;
+};
+
+}  // namespace control_loops
+}  // namespace frc971
+
+#endif // Y2015_CONTROL_LOOPS_FRIDGE_H_
+
diff --git a/y2015/control_loops/fridge/fridge.q b/y2015/control_loops/fridge/fridge.q
new file mode 100644
index 0000000..257374d
--- /dev/null
+++ b/y2015/control_loops/fridge/fridge.q
@@ -0,0 +1,152 @@
+package frc971.control_loops;
+
+import "aos/common/controls/control_loops.q";
+import "frc971/control_loops/control_loops.q";
+
+// Represents states for all of the box-grabbing pistons.
+// true is grabbed and false is retracted for all of them.
+struct GrabberPistons {
+  bool top_front;
+  bool top_back;
+  bool bottom_front;
+  bool bottom_back;
+};
+
+queue_group FridgeQueue {
+  implements aos.control_loops.ControlLoop;
+
+  // All angles are in radians with 0 sticking straight up.
+  // Rotating up and into the robot (towards the back
+  // where boxes are placed) is positive. Positive output voltage moves all
+  // mechanisms in the direction with positive sensor values.
+
+  // Elevator heights are the vertical distance (in meters) from a defined zero.
+  // In this case, zero is where the portion of the carriage that Spencer
+  // removed lines up with the bolt.
+
+  // X/Y positions are distances (in meters) the fridge is away from its origin
+  // position. Origin is considered at a height of zero and an angle of zero.
+  // Positive X positions are towards the front of the robot and negative X is
+  // towards the back of the robot (which is where we score).
+  // Y is positive going up and negative when it goes below the origin.
+
+  message Goal {
+    // Profile type.
+    // Set to 0 for angle/height profiling.
+    // Set to 1 for x/y profiling.
+    int32_t profiling_type;
+
+    // Angle of the arm.
+    double angle;
+    // Height of the elevator.
+    double height;
+
+    // Angular velocity of the arm.
+    float angular_velocity;
+    // Linear velocity of the elevator.
+    float velocity;
+
+    // Maximum arm profile angular velocity or 0 for the default.
+    float max_angular_velocity;
+    // Maximum elevator profile velocity or 0 for the default.
+    float max_velocity;
+
+    // Maximum arm profile acceleration or 0 for the default.
+    float max_angular_acceleration;
+    // Maximum elevator profile acceleration or 0 for the default.
+    float max_acceleration;
+
+    // X position of the fridge.
+    double x;
+    // Y position of the fridge.
+    double y;
+
+    // Velocity of the x position of the fridge.
+    float x_velocity;
+    // Velocity of the y position of the fridge.
+    float y_velocity;
+
+    // Maximum x profile velocity or 0 for the default.
+    float max_x_velocity;
+    // Maximum y profile velocity or 0 for the default.
+    float max_y_velocity;
+
+    // Maximum x profile acceleration or 0 for the default.
+    float max_x_acceleration;
+    // Maximum y profile acceleration or 0 for the default.
+    float max_y_acceleration;
+
+    // TODO(austin): Do I need acceleration here too?
+
+    GrabberPistons grabbers;
+  };
+
+  message Position {
+    PotAndIndexPair arm;
+    PotAndIndexPair elevator;
+  };
+
+  message Status {
+    // Are both the arm and elevator zeroed?
+    bool zeroed;
+
+    // Estimated angle of the arm.
+    double angle;
+    // Estimated angular velocity of the arm.
+    float angular_velocity;
+    // Estimated height of the elevator.
+    double height;
+    // Estimated velocity of the elvator.
+    float velocity;
+    // state of the grabber pistons
+    GrabberPistons grabbers;
+
+    // Goal angle and velocity of the arm.
+    double goal_angle;
+    float goal_angular_velocity;
+    // Goal height and velocity of the elevator.
+    double goal_height;
+    float goal_velocity;
+
+    // Estimated X/Y position of the fridge.
+    // These are translated directly from the height/angle statuses.
+    double x;
+    double y;
+    float x_velocity;
+    float y_velocity;
+
+    // X/Y goals of the fridge.
+    // These are translated directly from the height/angle goals.
+    double goal_x;
+    double goal_y;
+    float goal_x_velocity;
+    float goal_y_velocity;
+
+    // If true, we have aborted.
+    bool estopped;
+
+    // The internal state of the state machine.
+    int32_t state;
+
+    EstimatorState left_elevator_state;
+    EstimatorState right_elevator_state;
+    EstimatorState left_arm_state;
+    EstimatorState right_arm_state;
+  };
+
+  message Output {
+    double left_arm;
+    double right_arm;
+    double left_elevator;
+    double right_elevator;
+
+    GrabberPistons grabbers;
+  };
+
+  queue Goal goal;
+  queue Position position;
+  queue Output output;
+  queue Status status;
+};
+
+queue_group FridgeQueue fridge_queue;
diff --git a/y2015/control_loops/fridge/fridge_lib_test.cc b/y2015/control_loops/fridge/fridge_lib_test.cc
new file mode 100644
index 0000000..7719fb4
--- /dev/null
+++ b/y2015/control_loops/fridge/fridge_lib_test.cc
@@ -0,0 +1,735 @@
+#include "y2015/control_loops/fridge/fridge.h"
+
+#include <math.h>
+#include <unistd.h>
+
+#include <memory>
+
+#include "gtest/gtest.h"
+#include "aos/common/queue.h"
+#include "aos/common/time.h"
+#include "aos/common/commonmath.h"
+#include "aos/common/controls/control_loop_test.h"
+#include "y2015/util/kinematics.h"
+#include "frc971/control_loops/position_sensor_sim.h"
+#include "y2015/control_loops/fridge/arm_motor_plant.h"
+#include "y2015/control_loops/fridge/elevator_motor_plant.h"
+#include "y2015/control_loops/fridge/fridge.q.h"
+#include "y2015/constants.h"
+#include "frc971/control_loops/team_number_test_environment.h"
+
+using ::aos::time::Time;
+
+namespace frc971 {
+namespace control_loops {
+namespace testing {
+// Class which simulates the fridge and sends out queue messages with the
+// position.
+class FridgeSimulation {
+ public:
+  static constexpr double kNoiseScalar = 0.1;
+  // Constructs a simulation.
+  FridgeSimulation()
+      : arm_plant_(new StateFeedbackPlant<4, 2, 2>(MakeArmPlant())),
+        elevator_plant_(new StateFeedbackPlant<4, 2, 2>(MakeElevatorPlant())),
+        left_arm_pot_encoder_(
+            constants::GetValues().fridge.left_arm_zeroing.index_difference),
+        right_arm_pot_encoder_(
+            constants::GetValues().fridge.right_arm_zeroing.index_difference),
+        left_elevator_pot_encoder_(
+            constants::GetValues().fridge.left_elev_zeroing.index_difference),
+        right_elevator_pot_encoder_(
+            constants::GetValues().fridge.right_elev_zeroing.index_difference),
+        fridge_queue_(".frc971.control_loops.fridge_queue", 0xe4e05855,
+                      ".frc971.control_loops.fridge_queue.goal",
+                      ".frc971.control_loops.fridge_queue.position",
+                      ".frc971.control_loops.fridge_queue.output",
+                      ".frc971.control_loops.fridge_queue.status") {
+    // Initialize the elevator.
+    InitializeElevatorPosition(
+        constants::GetValues().fridge.elevator.lower_limit);
+    // Initialize the arm.
+    InitializeArmPosition(0.0);
+  }
+
+  void InitializeElevatorPosition(double start_pos) {
+    InitializeElevatorPosition(start_pos, start_pos);
+  }
+
+  void InitializeElevatorPosition(double left_start_pos,
+                                  double right_start_pos) {
+    InitializeElevatorPosition(
+        left_start_pos, right_start_pos,
+        kNoiseScalar *
+            constants::GetValues().fridge.right_elev_zeroing.index_difference);
+  }
+
+  void InitializeElevatorPosition(double left_start_pos, double right_start_pos,
+                                  double pot_noise_stddev) {
+    // Update the internal state of the elevator plant.
+    elevator_plant_->mutable_X(0, 0) = (left_start_pos + right_start_pos) / 2.0;
+    elevator_plant_->mutable_X(1, 0) = 0.0;
+    elevator_plant_->mutable_X(2, 0) = (left_start_pos - right_start_pos) / 2.0;
+    elevator_plant_->mutable_X(3, 0) = 0.0;
+
+    right_elevator_pot_encoder_.Initialize(right_start_pos, pot_noise_stddev);
+    left_elevator_pot_encoder_.Initialize(left_start_pos, pot_noise_stddev);
+    elevator_initial_difference_ = left_start_pos - right_start_pos;
+  }
+
+  void InitializeArmPosition(double start_pos) {
+    InitializeArmPosition(start_pos, start_pos);
+  }
+
+  void InitializeArmPosition(double left_start_pos, double right_start_pos) {
+    InitializeArmPosition(
+        left_start_pos, right_start_pos,
+        kNoiseScalar *
+            constants::GetValues().fridge.right_arm_zeroing.index_difference);
+  }
+  void InitializeArmPosition(double left_start_pos, double right_start_pos,
+                             double pot_noise_stddev) {
+    // Update the internal state of the arm plant.
+    arm_plant_->mutable_X(0, 0) = (left_start_pos + right_start_pos) / 2.0;
+    arm_plant_->mutable_X(1, 0) = 0.0;
+    arm_plant_->mutable_X(2, 0) = (left_start_pos - right_start_pos) / 2.0;
+    arm_plant_->mutable_X(3, 0) = 0.0;
+
+    left_arm_pot_encoder_.Initialize(left_start_pos, pot_noise_stddev);
+    right_arm_pot_encoder_.Initialize(right_start_pos, pot_noise_stddev);
+    arm_initial_difference_ = left_start_pos - right_start_pos;
+  }
+
+  // Changes the left-right calculations in the limit checks to measure absolute
+  // differences instead of differences relative to the starting offset.
+  void ErrorOnAbsoluteDifference() {
+    arm_initial_difference_ = 0.0;
+    elevator_initial_difference_ = 0.0;
+  }
+
+  // Sends a queue message with the position.
+  void SendPositionMessage() {
+    ::aos::ScopedMessagePtr<control_loops::FridgeQueue::Position> position =
+        fridge_queue_.position.MakeMessage();
+
+    left_arm_pot_encoder_.GetSensorValues(&position->arm.left);
+    right_arm_pot_encoder_.GetSensorValues(&position->arm.right);
+    left_elevator_pot_encoder_.GetSensorValues(&position->elevator.left);
+    right_elevator_pot_encoder_.GetSensorValues(&position->elevator.right);
+
+    position.Send();
+  }
+
+  // Sets the difference between the commanded and applied power for the arm.
+  // This lets us test that the integrator for the arm works.
+  void set_arm_power_error(double arm_power_error) {
+    arm_power_error_ = arm_power_error;
+  }
+  // Simulates for a single timestep.
+  void Simulate() {
+    EXPECT_TRUE(fridge_queue_.output.FetchLatest());
+
+    // Feed voltages into physics simulation.
+    if (arm_power_error_ != 0.0) {
+      arm_plant_->mutable_U() << ::aos::Clip(
+          fridge_queue_.output->left_arm + arm_power_error_, -12, 12),
+          ::aos::Clip(fridge_queue_.output->right_arm + arm_power_error_, -12,
+                      12);
+    } else {
+      arm_plant_->mutable_U() << fridge_queue_.output->left_arm,
+          fridge_queue_.output->right_arm;
+    }
+    elevator_plant_->mutable_U() << fridge_queue_.output->left_elevator,
+        fridge_queue_.output->right_elevator;
+
+    // Use the plant to generate the next physical state given the voltages to
+    // the motors.
+    arm_plant_->Update();
+    elevator_plant_->Update();
+
+    const double left_arm_angle = arm_plant_->Y(0, 0);
+    const double right_arm_angle = arm_plant_->Y(1, 0);
+    const double left_elevator_height = elevator_plant_->Y(0, 0);
+    const double right_elevator_height = elevator_plant_->Y(1, 0);
+
+    // TODO (phil) Do some sanity tests on the arm angles and the elevator
+    // heights. For example, we need to make sure that both sides are within a
+    // certain distance of each other and they haven't crashed into the top or
+    // the bottom.
+
+    // Use the physical state to simulate sensor readings.
+    left_arm_pot_encoder_.MoveTo(left_arm_angle);
+    right_arm_pot_encoder_.MoveTo(right_arm_angle);
+    left_elevator_pot_encoder_.MoveTo(left_elevator_height);
+    right_elevator_pot_encoder_.MoveTo(right_elevator_height);
+
+    // Verify that the arm and elevator sides don't change much from their
+    // initial difference.  Use the initial difference instead of the absolute
+    // difference to handle starting too far apart to test e-stopping.
+    EXPECT_NEAR(left_arm_angle - right_arm_angle, arm_initial_difference_,
+                5.0 * M_PI / 180.0);
+    EXPECT_NEAR(left_elevator_height - right_elevator_height,
+                elevator_initial_difference_, 0.0254);
+
+    // Validate that the arm is within range.
+    EXPECT_GE(left_arm_angle,
+              constants::GetValues().fridge.arm.lower_hard_limit);
+    EXPECT_GE(right_arm_angle,
+              constants::GetValues().fridge.arm.lower_hard_limit);
+    EXPECT_LE(left_arm_angle,
+              constants::GetValues().fridge.arm.upper_hard_limit);
+    EXPECT_LE(right_arm_angle,
+              constants::GetValues().fridge.arm.upper_hard_limit);
+
+    // Validate that the elevator is within range.
+    EXPECT_GE(left_elevator_height,
+              constants::GetValues().fridge.elevator.lower_hard_limit);
+    EXPECT_GE(right_elevator_height,
+              constants::GetValues().fridge.elevator.lower_hard_limit);
+    EXPECT_LE(left_elevator_height,
+              constants::GetValues().fridge.elevator.upper_hard_limit);
+    EXPECT_LE(right_elevator_height,
+              constants::GetValues().fridge.elevator.upper_hard_limit);
+  }
+
+ private:
+  ::std::unique_ptr<StateFeedbackPlant<4, 2, 2>> arm_plant_;
+  ::std::unique_ptr<StateFeedbackPlant<4, 2, 2>> elevator_plant_;
+
+  PositionSensorSimulator left_arm_pot_encoder_;
+  PositionSensorSimulator right_arm_pot_encoder_;
+  PositionSensorSimulator left_elevator_pot_encoder_;
+  PositionSensorSimulator right_elevator_pot_encoder_;
+
+  FridgeQueue fridge_queue_;
+
+  double elevator_initial_difference_ = 0.0;
+  double arm_initial_difference_ = 0.0;
+  double arm_power_error_ = 0.0;
+};
+
+class FridgeTest : public ::aos::testing::ControlLoopTest {
+ protected:
+  FridgeTest()
+      : fridge_queue_(".frc971.control_loops.fridge_queue", 0xe4e05855,
+                      ".frc971.control_loops.fridge_queue.goal",
+                      ".frc971.control_loops.fridge_queue.position",
+                      ".frc971.control_loops.fridge_queue.output",
+                      ".frc971.control_loops.fridge_queue.status"),
+        fridge_(&fridge_queue_),
+        fridge_plant_(),
+        kinematics_(constants::GetValues().fridge.arm_length,
+                    constants::GetValues().fridge.elevator.upper_limit,
+                    constants::GetValues().fridge.elevator.lower_limit,
+                    constants::GetValues().fridge.arm.upper_limit,
+                    constants::GetValues().fridge.arm.lower_limit) {
+    set_team_id(kTeamNumber);
+  }
+
+  void VerifyNearGoal() {
+    fridge_queue_.goal.FetchLatest();
+    fridge_queue_.status.FetchLatest();
+    EXPECT_TRUE(fridge_queue_.goal.get() != nullptr);
+    EXPECT_TRUE(fridge_queue_.status.get() != nullptr);
+    if (fridge_queue_.goal->profiling_type == 0) {
+      EXPECT_NEAR(fridge_queue_.goal->angle, fridge_queue_.status->angle,
+                  0.001);
+      EXPECT_NEAR(fridge_queue_.goal->height, fridge_queue_.status->height,
+                  0.001);
+    } else if (fridge_queue_.goal->profiling_type == 1) {
+      aos::util::ElevatorArmKinematics::KinematicResult x_y_status;
+      kinematics_.ForwardKinematic(fridge_queue_.status->height,
+                                   fridge_queue_.status->angle, 0.0, 0.0, &x_y_status);
+      EXPECT_NEAR(fridge_queue_.goal->x, x_y_status.fridge_x, 0.001);
+      EXPECT_NEAR(fridge_queue_.goal->y, x_y_status.fridge_h, 0.001);
+    } else {
+      // Unhandled profiling type.
+      EXPECT_TRUE(false);
+    }
+  }
+
+  // Runs one iteration of the whole simulation and checks that separation
+  // remains reasonable.
+  void RunIteration(bool enabled = true) {
+    SendMessages(enabled);
+
+    fridge_plant_.SendPositionMessage();
+    fridge_.Iterate();
+    fridge_plant_.Simulate();
+
+    TickTime();
+  }
+
+  // Runs iterations until the specified amount of simulated time has elapsed.
+  void RunForTime(const Time &run_for, bool enabled = true) {
+    const auto start_time = Time::Now();
+    while (Time::Now() < start_time + run_for) {
+      RunIteration(enabled);
+    }
+  }
+
+  // Create a new instance of the test queue so that it invalidates the queue
+  // that it points to.  Otherwise, we will have a pointed to
+  // shared memory that is no longer valid.
+  FridgeQueue fridge_queue_;
+
+  // Create a control loop and simulation.
+  Fridge fridge_;
+  FridgeSimulation fridge_plant_;
+
+  aos::util::ElevatorArmKinematics kinematics_;
+};
+
+// Tests that the loop does nothing when the goal is zero.
+TEST_F(FridgeTest, DoesNothing) {
+  // Set the goals to the starting values. This should theoretically guarantee
+  // that the controller does nothing.
+  const auto &values = constants::GetValues();
+  ASSERT_TRUE(fridge_queue_.goal.MakeWithBuilder()
+                  .angle(0.0)
+                  .height(values.fridge.elevator.lower_limit)
+                  .max_velocity(20)
+                  .max_acceleration(20)
+                  .max_angular_velocity(20)
+                  .max_angular_acceleration(20)
+                  .Send());
+
+  // Run a few iterations.
+  RunForTime(Time::InSeconds(5));
+
+  VerifyNearGoal();
+}
+
+// Tests that the loop can reach a goal.
+TEST_F(FridgeTest, ReachesXYGoal) {
+  // Set a reasonable goal.
+  const auto &values = constants::GetValues();
+  const double soft_limit = values.fridge.elevator.lower_limit;
+  const double height = soft_limit + 0.4;
+  const double angle = M_PI / 6.0;
+
+  aos::util::ElevatorArmKinematics::KinematicResult x_y_goals;
+  kinematics_.ForwardKinematic(height, angle, 0.0, 0.0, &x_y_goals);
+
+  ASSERT_TRUE(fridge_queue_.goal.MakeWithBuilder()
+                  .profiling_type(1)
+                  .x(x_y_goals.fridge_x)
+                  .y(x_y_goals.fridge_h)
+                  .max_x_velocity(20)
+                  .max_y_velocity(20)
+                  .max_x_acceleration(20)
+                  .max_y_acceleration(20)
+                  .Send());
+
+  // Give it a lot of time to get there.
+  RunForTime(Time::InSeconds(5));
+
+  VerifyNearGoal();
+}
+
+// Tests that the loop can reach a goal.
+TEST_F(FridgeTest, ReachesGoal) {
+  // Set a reasonable goal.
+  const auto &values = constants::GetValues();
+  const double soft_limit = values.fridge.elevator.lower_limit;
+  ASSERT_TRUE(fridge_queue_.goal.MakeWithBuilder()
+                  .angle(M_PI / 4.0)
+                  .height(soft_limit + 0.5)
+                  .max_velocity(20)
+                  .max_acceleration(20)
+                  .max_angular_velocity(20)
+                  .max_angular_acceleration(20)
+                  .Send());
+
+  // Give it a lot of time to get there.
+  RunForTime(Time::InSeconds(5));
+
+  VerifyNearGoal();
+}
+
+// Tests that the loop doesn't try and go beyond the physical range of the
+// mechanisms.
+TEST_F(FridgeTest, RespectsRange) {
+  // Put the arm up to get it out of the way.
+  // We're going to send the elevator to -5, which should be significantly too
+  // low.
+  ASSERT_TRUE(fridge_queue_.goal.MakeWithBuilder()
+                  .angle(M_PI)
+                  .height(-5.0)
+                  .max_velocity(20)
+                  .max_acceleration(20)
+                  .max_angular_velocity(20)
+                  .max_angular_acceleration(20)
+                  .Send());
+
+  RunForTime(Time::InSeconds(10));
+
+  // Check that we are near our soft limit.
+  fridge_queue_.status.FetchLatest();
+  const auto &values = constants::GetValues();
+  EXPECT_NEAR(values.fridge.elevator.lower_limit, fridge_queue_.status->height,
+              0.001);
+  EXPECT_NEAR(values.fridge.arm.upper_limit, fridge_queue_.status->angle,
+              0.001);
+
+  // Put the arm down to get it out of the way.
+  // We're going to give the elevator some ridiculously high goal.
+  ASSERT_TRUE(fridge_queue_.goal.MakeWithBuilder()
+                  .angle(-M_PI)
+                  .height(50.0)
+                  .max_velocity(20)
+                  .max_acceleration(20)
+                  .max_angular_velocity(20)
+                  .max_angular_acceleration(20)
+                  .Send());
+
+  RunForTime(Time::InSeconds(10));
+
+  // Check that we are near our soft limit.
+  fridge_queue_.status.FetchLatest();
+  EXPECT_NEAR(values.fridge.elevator.upper_limit, fridge_queue_.status->height,
+              0.001);
+  EXPECT_NEAR(values.fridge.arm.lower_limit, fridge_queue_.status->angle,
+              0.001);
+}
+
+// Tests that the loop zeroes when run for a while.
+TEST_F(FridgeTest, ZeroTest) {
+  fridge_queue_.goal.MakeWithBuilder()
+      .angle(0.0)
+      .height(0.5)
+      .max_velocity(20)
+      .max_acceleration(20)
+      .max_angular_velocity(20)
+      .max_angular_acceleration(20)
+      .Send();
+  RunForTime(Time::InSeconds(5));
+
+  VerifyNearGoal();
+}
+
+// Tests that starting at the lower hardstops doesn't cause an abort.
+TEST_F(FridgeTest, LowerHardstopStartup) {
+  fridge_plant_.InitializeElevatorPosition(
+      constants::GetValues().fridge.elevator.lower_hard_limit,
+      constants::GetValues().fridge.elevator.lower_hard_limit);
+  fridge_plant_.InitializeArmPosition(
+      constants::GetValues().fridge.arm.lower_hard_limit,
+      constants::GetValues().fridge.arm.lower_hard_limit);
+  fridge_queue_.goal.MakeWithBuilder().angle(0.0).height(0.4).Send();
+  // We have to wait for it to put the elevator in a safe position as well.
+  RunForTime(Time::InMS(8000));
+
+  VerifyNearGoal();
+}
+
+// Tests that starting at the upper hardstops doesn't cause an abort.
+TEST_F(FridgeTest, UpperHardstopStartup) {
+  fridge_plant_.InitializeElevatorPosition(
+      constants::GetValues().fridge.elevator.upper_hard_limit,
+      constants::GetValues().fridge.elevator.upper_hard_limit);
+  fridge_plant_.InitializeArmPosition(
+      constants::GetValues().fridge.arm.upper_hard_limit,
+      constants::GetValues().fridge.arm.upper_hard_limit);
+  fridge_queue_.goal.MakeWithBuilder().angle(0.0).height(0.4).Send();
+  RunForTime(Time::InMS(5000));
+
+  VerifyNearGoal();
+}
+
+// Tests that starting with an initial arm difference triggers an ESTOP.
+TEST_F(FridgeTest, ArmFarApartEstop) {
+  fridge_queue_.goal.MakeWithBuilder().angle(0.0).height(0.4).Send();
+
+  do {
+    fridge_plant_.InitializeArmPosition(
+        constants::GetValues().fridge.arm.lower_limit,
+        constants::GetValues().fridge.arm.lower_limit + 0.2);
+    SendMessages(true);
+    fridge_plant_.SendPositionMessage();
+    fridge_.Iterate();
+    fridge_plant_.Simulate();
+    TickTime();
+  } while (fridge_.state() == Fridge::INITIALIZING);
+
+  EXPECT_EQ(Fridge::ZEROING_ELEVATOR, fridge_.state());
+
+  // TODO(austin): We should estop earlier once Phil's code to detect issues
+  // before the index pulse is merged.
+  while (fridge_.state() != Fridge::RUNNING &&
+         fridge_.state() != Fridge::ESTOP) {
+    SendMessages(true);
+    fridge_plant_.SendPositionMessage();
+    fridge_.Iterate();
+    fridge_plant_.Simulate();
+    TickTime();
+  }
+
+  EXPECT_EQ(Fridge::ESTOP, fridge_.state());
+}
+
+// Tests that starting with an initial elevator difference triggers an ESTOP.
+TEST_F(FridgeTest, ElevatorFarApartEstop) {
+  fridge_queue_.goal.MakeWithBuilder().angle(0.0).height(0.4).Send();
+
+  do {
+    fridge_plant_.InitializeElevatorPosition(
+        constants::GetValues().fridge.elevator.lower_limit,
+        constants::GetValues().fridge.elevator.lower_limit + 0.1);
+    SendMessages(true);
+    fridge_plant_.SendPositionMessage();
+    fridge_.Iterate();
+    fridge_plant_.Simulate();
+    TickTime();
+  } while (fridge_.state() == Fridge::INITIALIZING);
+
+  EXPECT_EQ(Fridge::ZEROING_ELEVATOR, fridge_.state());
+
+  // TODO(austin): We should estop earlier once Phil's code to detect issues
+  // before the index pulse is merged.
+  while (fridge_.state() != Fridge::RUNNING &&
+         fridge_.state() != Fridge::ESTOP) {
+    SendMessages(true);
+    fridge_plant_.SendPositionMessage();
+    fridge_.Iterate();
+    fridge_plant_.Simulate();
+    TickTime();
+  }
+
+  EXPECT_EQ(Fridge::ESTOP, fridge_.state());
+}
+
+// Tests that starting with an initial elevator difference converges back to 0
+// error when zeroed.
+TEST_F(FridgeTest, ElevatorFixError) {
+  fridge_queue_.goal.MakeWithBuilder()
+      .angle(0.0)
+      .height(0.2)
+      .max_velocity(20)
+      .max_acceleration(20)
+      .Send();
+
+  do {
+    fridge_plant_.InitializeElevatorPosition(
+        constants::GetValues().fridge.elevator.lower_limit,
+        constants::GetValues().fridge.elevator.lower_limit + 0.01);
+    fridge_plant_.ErrorOnAbsoluteDifference();
+    SendMessages(true);
+    fridge_plant_.SendPositionMessage();
+    fridge_.Iterate();
+    fridge_plant_.Simulate();
+    TickTime();
+  } while (fridge_.state() == Fridge::INITIALIZING);
+
+  EXPECT_EQ(Fridge::ZEROING_ELEVATOR, fridge_.state());
+
+  RunForTime(Time::InSeconds(5));
+  VerifyNearGoal();
+}
+
+// Tests that starting with an initial arm difference converges back to 0
+// error when zeroed.
+TEST_F(FridgeTest, ArmFixError) {
+  fridge_queue_.goal.MakeWithBuilder()
+      .angle(0.0)
+      .height(0.2)
+      .max_angular_velocity(20)
+      .max_angular_acceleration(20)
+      .Send();
+
+  do {
+    fridge_plant_.InitializeArmPosition(0.0, 0.02);
+    fridge_plant_.ErrorOnAbsoluteDifference();
+    SendMessages(true);
+    fridge_plant_.SendPositionMessage();
+    fridge_.Iterate();
+    fridge_plant_.Simulate();
+    TickTime();
+  } while (fridge_.state() == Fridge::INITIALIZING);
+
+  EXPECT_EQ(Fridge::ZEROING_ELEVATOR, fridge_.state());
+
+  RunForTime(Time::InSeconds(5));
+  VerifyNearGoal();
+}
+
+// Tests that resetting WPILib results in a rezero.
+TEST_F(FridgeTest, ResetTest) {
+  fridge_plant_.InitializeElevatorPosition(
+      constants::GetValues().fridge.elevator.upper_hard_limit,
+      constants::GetValues().fridge.elevator.upper_hard_limit);
+  fridge_plant_.InitializeArmPosition(
+      constants::GetValues().fridge.arm.upper_hard_limit,
+      constants::GetValues().fridge.arm.upper_hard_limit);
+  fridge_queue_.goal.MakeWithBuilder().angle(0.03).height(0.45).Send();
+  RunForTime(Time::InMS(5000));
+
+  EXPECT_EQ(Fridge::RUNNING, fridge_.state());
+  VerifyNearGoal();
+  SimulateSensorReset();
+  RunForTime(Time::InMS(100));
+  EXPECT_NE(Fridge::RUNNING, fridge_.state());
+  RunForTime(Time::InMS(6000));
+  EXPECT_EQ(Fridge::RUNNING, fridge_.state());
+  VerifyNearGoal();
+}
+
+// Tests that the internal goals don't change while disabled.
+TEST_F(FridgeTest, DisabledGoalTest) {
+  fridge_queue_.goal.MakeWithBuilder().angle(0.03).height(0.45).Send();
+
+  RunForTime(Time::InMS(100), false);
+  EXPECT_EQ(0.0, fridge_.elevator_goal_);
+  EXPECT_EQ(0.0, fridge_.arm_goal_);
+
+  // Now make sure they move correctly
+  RunForTime(Time::InMS(4000), true);
+  EXPECT_NE(0.0, fridge_.elevator_goal_);
+  EXPECT_NE(0.0, fridge_.arm_goal_);
+}
+
+// Tests that the elevator zeroing goals don't wind up too far.
+TEST_F(FridgeTest, ElevatorGoalPositiveWindupTest) {
+  fridge_queue_.goal.MakeWithBuilder().angle(0.03).height(0.45).Send();
+
+  while (fridge_.state() != Fridge::ZEROING_ELEVATOR) {
+    RunIteration();
+  }
+
+  // Kick it.
+  RunForTime(Time::InMS(50));
+  double orig_fridge_goal = fridge_.elevator_goal_;
+  fridge_.elevator_goal_ += 100.0;
+
+  RunIteration();
+  EXPECT_NEAR(orig_fridge_goal, fridge_.elevator_goal_, 0.05);
+
+  RunIteration();
+
+  EXPECT_EQ(fridge_.elevator_loop_->U(), fridge_.elevator_loop_->U_uncapped());
+}
+
+// Tests that the arm zeroing goals don't wind up too far.
+TEST_F(FridgeTest, ArmGoalPositiveWindupTest) {
+  fridge_queue_.goal.MakeWithBuilder().angle(0.03).height(0.45).Send();
+
+  int i = 0;
+  while (fridge_.state() != Fridge::ZEROING_ARM) {
+    RunIteration();
+    ++i;
+    ASSERT_LE(i, 10000);
+  }
+
+  // Kick it.
+  RunForTime(Time::InMS(50));
+  double orig_fridge_goal = fridge_.arm_goal_;
+  fridge_.arm_goal_ += 100.0;
+
+  RunIteration();
+  EXPECT_NEAR(orig_fridge_goal, fridge_.arm_goal_, 0.05);
+
+  RunIteration();
+
+  EXPECT_EQ(fridge_.arm_loop_->U(), fridge_.arm_loop_->U_uncapped());
+}
+
+// Tests that the elevator zeroing goals don't wind up too far.
+TEST_F(FridgeTest, ElevatorGoalNegativeWindupTest) {
+  fridge_queue_.goal.MakeWithBuilder().angle(0.03).height(0.45).Send();
+
+  while (fridge_.state() != Fridge::ZEROING_ELEVATOR) {
+    RunIteration();
+  }
+
+  // Kick it.
+  RunForTime(Time::InMS(50));
+  double orig_fridge_goal = fridge_.elevator_goal_;
+  fridge_.elevator_goal_ -= 100.0;
+
+  RunIteration();
+  EXPECT_NEAR(orig_fridge_goal, fridge_.elevator_goal_, 0.05);
+
+  RunIteration();
+
+  EXPECT_EQ(fridge_.elevator_loop_->U(), fridge_.elevator_loop_->U_uncapped());
+}
+
+// Tests that the arm zeroing goals don't wind up too far.
+TEST_F(FridgeTest, ArmGoalNegativeWindupTest) {
+  fridge_queue_.goal.MakeWithBuilder().angle(0.03).height(0.45).Send();
+
+  while (fridge_.state() != Fridge::ZEROING_ARM) {
+    RunIteration();
+  }
+
+  // Kick it.
+  RunForTime(Time::InMS(50));
+  double orig_fridge_goal = fridge_.arm_goal_;
+  fridge_.arm_goal_ -= 100.0;
+
+  RunIteration();
+  EXPECT_NEAR(orig_fridge_goal, fridge_.arm_goal_, 0.05);
+
+  RunIteration();
+
+  EXPECT_EQ(fridge_.arm_loop_->U(), fridge_.arm_loop_->U_uncapped());
+}
+
+// Tests that the loop zeroes when run for a while.
+TEST_F(FridgeTest, ZeroNoGoal) {
+  RunForTime(Time::InSeconds(5));
+
+  EXPECT_EQ(Fridge::RUNNING, fridge_.state());
+}
+
+// Tests that if we start at the bottom, the elevator moves to a safe height
+// before zeroing the arm.
+TEST_F(FridgeTest, SafeArmZeroing) {
+  auto &values = constants::GetValues();
+  fridge_plant_.InitializeElevatorPosition(
+      values.fridge.elevator.lower_hard_limit);
+  fridge_plant_.InitializeArmPosition(M_PI / 4.0);
+
+  const auto start_time = Time::Now();
+  double last_arm_goal = fridge_.arm_goal_;
+  while (Time::Now() < start_time + Time::InMS(4000)) {
+    RunIteration();
+
+    if (fridge_.state() != Fridge::ZEROING_ELEVATOR) {
+      // Wait until we are zeroing the elevator.
+      continue;
+    }
+
+    fridge_queue_.status.FetchLatest();
+    ASSERT_TRUE(fridge_queue_.status.get() != nullptr);
+    if (fridge_queue_.status->height > values.fridge.arm_zeroing_height) {
+      // We had better not be trying to zero the arm...
+      EXPECT_EQ(last_arm_goal, fridge_.arm_goal_);
+      last_arm_goal = fridge_.arm_goal_;
+    }
+  }
+}
+
+// Tests that the arm integrator works.
+TEST_F(FridgeTest, ArmIntegratorTest) {
+  fridge_plant_.InitializeArmPosition(
+      (constants::GetValues().fridge.arm.lower_hard_limit +
+       constants::GetValues().fridge.arm.lower_hard_limit) /
+      2.0);
+  fridge_plant_.set_arm_power_error(1.0);
+  fridge_queue_.goal.MakeWithBuilder().angle(0.0).height(0.4).Send();
+
+  RunForTime(Time::InMS(8000));
+
+  VerifyNearGoal();
+}
+
+// Phil:
+// TODO(austin): Check that we e-stop if encoder index pulse is not n
+// revolutions away from last one. (got extra counts from noise, etc).
+// TODO(austin): Check that we e-stop if pot disagrees too much with encoder
+// after we are zeroed.
+
+}  // namespace testing
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/y2015/control_loops/fridge/fridge_main.cc b/y2015/control_loops/fridge/fridge_main.cc
new file mode 100644
index 0000000..e0fd6ea
--- /dev/null
+++ b/y2015/control_loops/fridge/fridge_main.cc
@@ -0,0 +1,11 @@
+#include "y2015/control_loops/fridge/fridge.h"
+
+#include "aos/linux_code/init.h"
+
+int main() {
+  ::aos::Init();
+  frc971::control_loops::Fridge fridge;
+  fridge.Run();
+  ::aos::Cleanup();
+  return 0;
+}
diff --git a/y2015/control_loops/fridge/integral_arm_plant.cc b/y2015/control_loops/fridge/integral_arm_plant.cc
new file mode 100644
index 0000000..da269d7
--- /dev/null
+++ b/y2015/control_loops/fridge/integral_arm_plant.cc
@@ -0,0 +1,49 @@
+#include "y2015/control_loops/fridge/integral_arm_plant.h"
+
+#include <vector>
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace frc971 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<5, 2, 2> MakeIntegralArmPlantCoefficients() {
+  Eigen::Matrix<double, 5, 5> A;
+  A << 1.0, 0.00479642025454, 0.0, 0.0, 4.92993559969e-05, 0.0, 0.919688585028, 0.0, 0.0, 0.0194484035162, 0.0, 0.0, 0.999539771613, 0.00479566382645, 0.0, 0.0, 0.0, -0.18154390621, 0.919241022297, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0;
+  Eigen::Matrix<double, 5, 2> B;
+  B << 2.46496779984e-05, 2.46496779984e-05, 0.00972420175808, 0.00972420175808, 2.46477449538e-05, -2.46477449538e-05, 0.00972266818532, -0.00972266818532, 0.0, 0.0;
+  Eigen::Matrix<double, 2, 5> C;
+  C << 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, -1.0, 0.0, 0.0;
+  Eigen::Matrix<double, 2, 2> D;
+  D << 0, 0, 0, 0;
+  Eigen::Matrix<double, 2, 1> U_max;
+  U_max << 12.0, 12.0;
+  Eigen::Matrix<double, 2, 1> U_min;
+  U_min << -12.0, -12.0;
+  return StateFeedbackPlantCoefficients<5, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackController<5, 2, 2> MakeIntegralArmController() {
+  Eigen::Matrix<double, 5, 2> L;
+  L << 0.461805946837, 0.461805946837, 5.83483983392, 5.83483983392, 0.429725467802, -0.429725467802, 0.18044816586, -0.18044816586, 31.0623964848, 31.0623964848;
+  Eigen::Matrix<double, 2, 5> K;
+  K << 320.979606093, 21.0129517955, 884.233784759, 36.3637782119, 1.0, 320.979606095, 21.0129517956, -884.233784749, -36.3637782119, 1.0;
+  Eigen::Matrix<double, 5, 5> A_inv;
+  A_inv << 1.0, -0.00521526561559, 0.0, 0.0, 5.21292341391e-05, 0.0, 1.08732457517, 0.0, 0.0, -0.0211467270909, 0.0, 0.0, 0.999513354044, -0.00521444313273, 0.0, 0.0, 0.0, 0.197397150694, 1.08682415753, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0;
+  return StateFeedbackController<5, 2, 2>(L, K, A_inv, MakeIntegralArmPlantCoefficients());
+}
+
+StateFeedbackPlant<5, 2, 2> MakeIntegralArmPlant() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackPlantCoefficients<5, 2, 2>>> plants(1);
+  plants[0] = ::std::unique_ptr<StateFeedbackPlantCoefficients<5, 2, 2>>(new StateFeedbackPlantCoefficients<5, 2, 2>(MakeIntegralArmPlantCoefficients()));
+  return StateFeedbackPlant<5, 2, 2>(&plants);
+}
+
+StateFeedbackLoop<5, 2, 2> MakeIntegralArmLoop() {
+  ::std::vector< ::std::unique_ptr<StateFeedbackController<5, 2, 2>>> controllers(1);
+  controllers[0] = ::std::unique_ptr<StateFeedbackController<5, 2, 2>>(new StateFeedbackController<5, 2, 2>(MakeIntegralArmController()));
+  return StateFeedbackLoop<5, 2, 2>(&controllers);
+}
+
+}  // namespace control_loops
+}  // namespace frc971
diff --git a/y2015/control_loops/fridge/integral_arm_plant.h b/y2015/control_loops/fridge/integral_arm_plant.h
new file mode 100644
index 0000000..80a4876
--- /dev/null
+++ b/y2015/control_loops/fridge/integral_arm_plant.h
@@ -0,0 +1,20 @@
+#ifndef Y2015_CONTROL_LOOPS_FRIDGE_INTEGRAL_ARM_PLANT_H_
+#define Y2015_CONTROL_LOOPS_FRIDGE_INTEGRAL_ARM_PLANT_H_
+
+#include "frc971/control_loops/state_feedback_loop.h"
+
+namespace frc971 {
+namespace control_loops {
+
+StateFeedbackPlantCoefficients<5, 2, 2> MakeIntegralArmPlantCoefficients();
+
+StateFeedbackController<5, 2, 2> MakeIntegralArmController();
+
+StateFeedbackPlant<5, 2, 2> MakeIntegralArmPlant();
+
+StateFeedbackLoop<5, 2, 2> MakeIntegralArmLoop();
+
+}  // namespace control_loops
+}  // namespace frc971
+
+#endif  // Y2015_CONTROL_LOOPS_FRIDGE_INTEGRAL_ARM_PLANT_H_
diff --git a/y2015/control_loops/fridge/replay_fridge.cc b/y2015/control_loops/fridge/replay_fridge.cc
new file mode 100644
index 0000000..65cc98a
--- /dev/null
+++ b/y2015/control_loops/fridge/replay_fridge.cc
@@ -0,0 +1,24 @@
+#include "aos/common/controls/replay_control_loop.h"
+#include "aos/linux_code/init.h"
+
+#include "y2015/control_loops/fridge/fridge.q.h"
+
+// Reads one or more log files and sends out all the queue messages (in the
+// correct order and at the correct time) to feed a "live" fridge process.
+
+int main(int argc, char **argv) {
+  if (argc <= 1) {
+    fprintf(stderr, "Need at least one file to replay!\n");
+    return EXIT_FAILURE;
+  }
+
+  ::aos::InitNRT();
+
+  ::aos::controls::ControlLoopReplayer<::frc971::control_loops::FridgeQueue>
+      replayer(&::frc971::control_loops::fridge_queue, "fridge");
+  for (int i = 1; i < argc; ++i) {
+    replayer.ProcessFile(argv[i]);
+  }
+
+  ::aos::Cleanup();
+}
diff --git a/y2015/control_loops/python/arm.py b/y2015/control_loops/python/arm.py
new file mode 100755
index 0000000..e17990a
--- /dev/null
+++ b/y2015/control_loops/python/arm.py
@@ -0,0 +1,409 @@
+#!/usr/bin/python
+
+import control_loop
+import controls
+import polytope
+import polydrivetrain
+import numpy
+import math
+import sys
+import matplotlib
+from matplotlib import pylab
+
+
+class Arm(control_loop.ControlLoop):
+  def __init__(self, name="Arm", mass=None):
+    super(Arm, self).__init__(name)
+    # Stall Torque in N m
+    self.stall_torque = 0.476
+    # Stall Current in Amps
+    self.stall_current = 80.730
+    # Free Speed in RPM
+    self.free_speed = 13906.0
+    # Free Current in Amps
+    self.free_current = 5.820
+    # Mass of the arm
+    if mass is None:
+      self.mass = 13.0
+    else:
+      self.mass = mass
+
+    # Resistance of the motor
+    self.R = 12.0 / self.stall_current
+    # Motor velocity constant
+    self.Kv = ((self.free_speed / 60.0 * 2.0 * numpy.pi) /
+               (12.0 - self.R * self.free_current))
+    # Torque constant
+    self.Kt = self.stall_torque / self.stall_current
+    # Gear ratio
+    self.G = (44.0 / 12.0) * (54.0 / 14.0) * (54.0 / 14.0) * (44.0 / 20.0) * (72.0 / 16.0)
+    # Fridge arm length
+    self.r = 32 * 0.0254
+    # Control loop time step
+    self.dt = 0.005
+
+    # Arm moment of inertia
+    self.J = self.r * self.mass
+
+    # Arm left/right spring constant (N*m / radian)
+    self.spring = 100.0
+
+    # State is [average position, average velocity,
+    #           position difference/2, velocity difference/2]
+    # Position difference is 1 - 2
+    # Input is [Voltage 1, Voltage 2]
+
+    self.C1 = self.spring / (self.J * 0.5)
+    self.C2 = self.Kt * self.G / (self.J * 0.5 * self.R)
+    self.C3 = self.G * self.G * self.Kt / (self.R  * self.J * 0.5 * self.Kv)
+
+    self.A_continuous = numpy.matrix(
+        [[0, 1, 0, 0],
+         [0, -self.C3, 0, 0],
+         [0, 0, 0, 1],
+         [0, 0, -self.C1 * 2.0, -self.C3]])
+
+    print 'Full speed is', self.C2 / self.C3 * 12.0
+
+    print 'Stall arm difference is', 12.0 * self.C2 / self.C1
+    print 'Stall arm difference first principles is', self.stall_torque * self.G / self.spring
+
+    print '5 degrees of arm error is', self.spring / self.r * (math.pi * 5.0 / 180.0)
+
+    # Start with the unmodified input
+    self.B_continuous = numpy.matrix(
+        [[0, 0],
+         [self.C2 / 2.0, self.C2 / 2.0],
+         [0, 0],
+         [self.C2 / 2.0, -self.C2 / 2.0]])
+
+    self.C = numpy.matrix([[1, 0, 1, 0],
+                           [1, 0, -1, 0]])
+    self.D = numpy.matrix([[0, 0],
+                           [0, 0]])
+
+    self.A, self.B = self.ContinuousToDiscrete(
+        self.A_continuous, self.B_continuous, self.dt)
+
+    controlability = controls.ctrb(self.A, self.B);
+    print 'Rank of augmented controlability matrix.', numpy.linalg.matrix_rank(
+        controlability)
+
+    q_pos = 0.02
+    q_vel = 0.300
+    q_pos_diff = 0.005
+    q_vel_diff = 0.13
+    self.Q = numpy.matrix([[(1.0 / (q_pos ** 2.0)), 0.0, 0.0, 0.0],
+                           [0.0, (1.0 / (q_vel ** 2.0)), 0.0, 0.0],
+                           [0.0, 0.0, (1.0 / (q_pos_diff ** 2.0)), 0.0],
+                           [0.0, 0.0, 0.0, (1.0 / (q_vel_diff ** 2.0))]])
+
+    self.R = numpy.matrix([[(1.0 / (12.0 ** 2.0)), 0.0],
+                           [0.0, 1.0 / (12.0 ** 2.0)]])
+    self.K = controls.dlqr(self.A, self.B, self.Q, self.R)
+    print 'Controller'
+    print self.K
+
+    print 'Controller Poles'
+    print numpy.linalg.eig(self.A - self.B * self.K)[0]
+
+    self.rpl = 0.20
+    self.ipl = 0.05
+    self.PlaceObserverPoles([self.rpl + 1j * self.ipl,
+                             self.rpl + 1j * self.ipl,
+                             self.rpl - 1j * self.ipl,
+                             self.rpl - 1j * self.ipl])
+
+    # The box formed by U_min and U_max must encompass all possible values,
+    # or else Austin's code gets angry.
+    self.U_max = numpy.matrix([[12.0], [12.0]])
+    self.U_min = numpy.matrix([[-12.0], [-12.0]])
+
+    print 'Observer (Converted to a KF)', numpy.linalg.inv(self.A) * self.L
+
+    self.InitializeState()
+
+
+class IntegralArm(Arm):
+  def __init__(self, name="IntegralArm", mass=None):
+    super(IntegralArm, self).__init__(name=name, mass=mass)
+
+    self.A_continuous_unaugmented = self.A_continuous
+    self.A_continuous = numpy.matrix(numpy.zeros((5, 5)))
+    self.A_continuous[0:4, 0:4] = self.A_continuous_unaugmented
+    self.A_continuous[1, 4] = self.C2
+
+    # Start with the unmodified input
+    self.B_continuous_unaugmented = self.B_continuous
+    self.B_continuous = numpy.matrix(numpy.zeros((5, 2)))
+    self.B_continuous[0:4, 0:2] = self.B_continuous_unaugmented
+
+    self.C_unaugmented = self.C
+    self.C = numpy.matrix(numpy.zeros((2, 5)))
+    self.C[0:2, 0:4] = self.C_unaugmented
+
+    self.A, self.B = self.ContinuousToDiscrete(
+        self.A_continuous, self.B_continuous, self.dt)
+    print 'A cont', self.A_continuous
+    print 'B cont', self.B_continuous
+    print 'A discrete', self.A
+
+    q_pos = 0.08
+    q_vel = 0.40
+
+    q_pos_diff = 0.08
+    q_vel_diff = 0.40
+    q_voltage = 6.0
+    self.Q = numpy.matrix([[(q_pos ** 2.0), 0.0, 0.0, 0.0, 0.0],
+                           [0.0, (q_vel ** 2.0), 0.0, 0.0, 0.0],
+                           [0.0, 0.0, (q_pos_diff ** 2.0), 0.0, 0.0],
+                           [0.0, 0.0, 0.0, (q_vel_diff ** 2.0), 0.0],
+                           [0.0, 0.0, 0.0, 0.0, (q_voltage ** 2.0)]])
+
+    r_volts = 0.05
+    self.R = numpy.matrix([[(r_volts ** 2.0), 0.0],
+                           [0.0, (r_volts ** 2.0)]])
+
+    self.KalmanGain, self.Q_steady = controls.kalman(
+        A=self.A, B=self.B, C=self.C, Q=self.Q, R=self.R)
+
+    self.U_max = numpy.matrix([[12.0], [12.0]])
+    self.U_min = numpy.matrix([[-12.0], [-12.0]])
+
+    self.K_unaugmented = self.K
+    self.K = numpy.matrix(numpy.zeros((2, 5)));
+    self.K[0:2, 0:4] = self.K_unaugmented
+    self.K[0, 4] = 1;
+    self.K[1, 4] = 1;
+    print 'Kal', self.KalmanGain
+    self.L = self.A * self.KalmanGain
+
+    self.InitializeState()
+
+
+def CapU(U):
+  if U[0, 0] - U[1, 0] > 24:
+    return numpy.matrix([[12], [-12]])
+  elif U[0, 0] - U[1, 0] < -24:
+    return numpy.matrix([[-12], [12]])
+  else:
+    max_u = max(U[0, 0], U[1, 0])
+    min_u = min(U[0, 0], U[1, 0])
+    if max_u > 12:
+      return U - (max_u - 12)
+    if min_u < -12:
+      return U - (min_u + 12)
+    return U
+
+
+def run_test(arm, initial_X, goal, max_separation_error=0.01,
+             show_graph=True, iterations=200, controller_arm=None,
+             observer_arm=None):
+  """Runs the arm plant with an initial condition and goal.
+
+    The tests themselves are not terribly sophisticated; I just test for
+    whether the goal has been reached and whether the separation goes
+    outside of the initial and goal values by more than max_separation_error.
+    Prints out something for a failure of either condition and returns
+    False if tests fail.
+    Args:
+      arm: arm object to use.
+      initial_X: starting state.
+      goal: goal state.
+      show_graph: Whether or not to display a graph showing the changing
+           states and voltages.
+      iterations: Number of timesteps to run the model for.
+      controller_arm: arm object to get K from, or None if we should
+          use arm.
+      observer_arm: arm object to use for the observer, or None if we should
+          use the actual state.
+  """
+
+  arm.X = initial_X
+
+  if controller_arm is None:
+    controller_arm = arm
+
+  if observer_arm is not None:
+    observer_arm.X_hat = initial_X + 0.01
+    observer_arm.X_hat = initial_X
+
+  # Various lists for graphing things.
+  t = []
+  x_avg = []
+  x_sep = []
+  x_hat_avg = []
+  x_hat_sep = []
+  v_avg = []
+  v_sep = []
+  u_left = []
+  u_right = []
+
+  sep_plot_gain = 100.0
+
+  for i in xrange(iterations):
+    X_hat = arm.X
+    if observer_arm is not None:
+      X_hat = observer_arm.X_hat
+      x_hat_avg.append(observer_arm.X_hat[0, 0])
+      x_hat_sep.append(observer_arm.X_hat[2, 0] * sep_plot_gain)
+    U = controller_arm.K * (goal - X_hat)
+    U = CapU(U)
+    x_avg.append(arm.X[0, 0])
+    v_avg.append(arm.X[1, 0])
+    x_sep.append(arm.X[2, 0] * sep_plot_gain)
+    v_sep.append(arm.X[3, 0])
+    if observer_arm is not None:
+      observer_arm.PredictObserver(U)
+    arm.Update(U)
+    if observer_arm is not None:
+      observer_arm.Y = arm.Y
+      observer_arm.CorrectObserver(U)
+
+    t.append(i * arm.dt)
+    u_left.append(U[0, 0])
+    u_right.append(U[1, 0])
+
+  print numpy.linalg.inv(arm.A)
+  print "delta time is ", arm.dt
+  print "Velocity at t=0 is ", x_avg[0], v_avg[0], x_sep[0], v_sep[0]
+  print "Velocity at t=1+dt is ", x_avg[1], v_avg[1], x_sep[1], v_sep[1]
+
+  if show_graph:
+    pylab.subplot(2, 1, 1)
+    pylab.plot(t, x_avg, label='x avg')
+    pylab.plot(t, x_sep, label='x sep')
+    if observer_arm is not None:
+      pylab.plot(t, x_hat_avg, label='x_hat avg')
+      pylab.plot(t, x_hat_sep, label='x_hat sep')
+    pylab.legend()
+
+    pylab.subplot(2, 1, 2)
+    pylab.plot(t, u_left, label='u left')
+    pylab.plot(t, u_right, label='u right')
+    pylab.legend()
+    pylab.show()
+
+
+def run_integral_test(arm, initial_X, goal, observer_arm, disturbance,
+                      max_separation_error=0.01, show_graph=True,
+                      iterations=400):
+  """Runs the integral control arm plant with an initial condition and goal.
+
+    The tests themselves are not terribly sophisticated; I just test for
+    whether the goal has been reached and whether the separation goes
+    outside of the initial and goal values by more than max_separation_error.
+    Prints out something for a failure of either condition and returns
+    False if tests fail.
+    Args:
+      arm: arm object to use.
+      initial_X: starting state.
+      goal: goal state.
+      observer_arm: arm object to use for the observer.
+      show_graph: Whether or not to display a graph showing the changing
+           states and voltages.
+      iterations: Number of timesteps to run the model for.
+      disturbance: Voltage missmatch between controller and model.
+  """
+
+  arm.X = initial_X
+
+  # Various lists for graphing things.
+  t = []
+  x_avg = []
+  x_sep = []
+  x_hat_avg = []
+  x_hat_sep = []
+  v_avg = []
+  v_sep = []
+  u_left = []
+  u_right = []
+  u_error = []
+
+  sep_plot_gain = 100.0
+
+  unaugmented_goal = goal
+  goal = numpy.matrix(numpy.zeros((5, 1)))
+  goal[0:4, 0] = unaugmented_goal
+
+  for i in xrange(iterations):
+    X_hat = observer_arm.X_hat[0:4]
+
+    x_hat_avg.append(observer_arm.X_hat[0, 0])
+    x_hat_sep.append(observer_arm.X_hat[2, 0] * sep_plot_gain)
+
+    U = observer_arm.K * (goal - observer_arm.X_hat)
+    u_error.append(observer_arm.X_hat[4,0])
+    U = CapU(U)
+    x_avg.append(arm.X[0, 0])
+    v_avg.append(arm.X[1, 0])
+    x_sep.append(arm.X[2, 0] * sep_plot_gain)
+    v_sep.append(arm.X[3, 0])
+
+    observer_arm.PredictObserver(U)
+
+    arm.Update(U + disturbance)
+    observer_arm.Y = arm.Y
+    observer_arm.CorrectObserver(U)
+
+    t.append(i * arm.dt)
+    u_left.append(U[0, 0])
+    u_right.append(U[1, 0])
+
+  print 'End is', observer_arm.X_hat[4, 0]
+
+  if show_graph:
+    pylab.subplot(2, 1, 1)
+    pylab.plot(t, x_avg, label='x avg')
+    pylab.plot(t, x_sep, label='x sep')
+    if observer_arm is not None:
+      pylab.plot(t, x_hat_avg, label='x_hat avg')
+      pylab.plot(t, x_hat_sep, label='x_hat sep')
+    pylab.legend()
+
+    pylab.subplot(2, 1, 2)
+    pylab.plot(t, u_left, label='u left')
+    pylab.plot(t, u_right, label='u right')
+    pylab.plot(t, u_error, label='u error')
+    pylab.legend()
+    pylab.show()
+
+
+def main(argv):
+  loaded_mass = 25
+  #loaded_mass = 0
+  arm = Arm(mass=13 + loaded_mass)
+  #arm_controller = Arm(mass=13 + 15)
+  #observer_arm = Arm(mass=13 + 15)
+  #observer_arm = None
+
+  integral_arm = IntegralArm(mass=13 + loaded_mass)
+  integral_arm.X_hat[0, 0] += 0.02
+  integral_arm.X_hat[2, 0] += 0.02
+  integral_arm.X_hat[4] = 0
+
+  # Test moving the arm with constant separation.
+  initial_X = numpy.matrix([[0.0], [0.0], [0.0], [0.0]])
+  R = numpy.matrix([[0.0], [0.0], [0.0], [0.0]])
+  run_integral_test(arm, initial_X, R, integral_arm, disturbance=2)
+
+  # Write the generated constants out to a file.
+  if len(argv) != 5:
+    print "Expected .h file name and .cc file name for the arm and augmented arm."
+  else:
+    arm = Arm("Arm", mass=13)
+    loop_writer = control_loop.ControlLoopWriter("Arm", [arm])
+    if argv[1][-3:] == '.cc':
+      loop_writer.Write(argv[2], argv[1])
+    else:
+      loop_writer.Write(argv[1], argv[2])
+
+    integral_arm = IntegralArm("IntegralArm", mass=13)
+    loop_writer = control_loop.ControlLoopWriter("IntegralArm", [integral_arm])
+    if argv[3][-3:] == '.cc':
+      loop_writer.Write(argv[4], argv[3])
+    else:
+      loop_writer.Write(argv[3], argv[4])
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))
diff --git a/y2015/control_loops/python/claw.py b/y2015/control_loops/python/claw.py
new file mode 100755
index 0000000..4ca50e9
--- /dev/null
+++ b/y2015/control_loops/python/claw.py
@@ -0,0 +1,211 @@
+#!/usr/bin/python
+
+import control_loop
+import controls
+import polytope
+import polydrivetrain
+import numpy
+import sys
+import matplotlib
+from matplotlib import pylab
+
+class Claw(control_loop.ControlLoop):
+  def __init__(self, name="Claw", mass=None):
+    super(Claw, self).__init__(name)
+    # Stall Torque in N m
+    self.stall_torque = 0.476
+    # Stall Current in Amps
+    self.stall_current = 80.730
+    # Free Speed in RPM
+    self.free_speed = 13906.0
+    # Free Current in Amps
+    self.free_current = 5.820
+    # Mass of the claw
+    if mass is None:
+      self.mass = 5.0
+    else:
+      self.mass = mass
+
+    # Resistance of the motor
+    self.R = 12.0 / self.stall_current
+    # Motor velocity constant
+    self.Kv = ((self.free_speed / 60.0 * 2.0 * numpy.pi) /
+               (12.0 - self.R * self.free_current))
+    # Torque constant
+    self.Kt = self.stall_torque / self.stall_current
+    # Gear ratio
+    self.G = (56.0 / 12.0) * (54.0 / 14.0) * (64.0 / 14.0) * (72.0 / 18.0)
+    # Claw length
+    self.r = 18 * 0.0254
+
+    self.J = self.r * self.mass
+
+    # Control loop time step
+    self.dt = 0.005
+
+    # State is [position, velocity]
+    # Input is [Voltage]
+
+    C1 = self.G * self.G * self.Kt / (self.R  * self.J * self.Kv)
+    C2 = self.Kt * self.G / (self.J * self.R)
+
+    self.A_continuous = numpy.matrix(
+        [[0, 1],
+         [0, -C1]])
+
+    # Start with the unmodified input
+    self.B_continuous = numpy.matrix(
+        [[0],
+         [C2]])
+
+    self.C = numpy.matrix([[1, 0]])
+    self.D = numpy.matrix([[0]])
+
+    self.A, self.B = self.ContinuousToDiscrete(
+        self.A_continuous, self.B_continuous, self.dt)
+
+    controlability = controls.ctrb(self.A, self.B);
+
+    print "Free speed is", self.free_speed * numpy.pi * 2.0 / 60.0 / self.G
+
+    q_pos = 0.15
+    q_vel = 2.5
+    self.Q = numpy.matrix([[(1.0 / (q_pos ** 2.0)), 0.0],
+                           [0.0, (1.0 / (q_vel ** 2.0))]])
+
+    self.R = numpy.matrix([[(1.0 / (12.0 ** 2.0))]])
+    self.K = controls.dlqr(self.A, self.B, self.Q, self.R)
+
+    print 'K', self.K
+    print 'Poles are', numpy.linalg.eig(self.A - self.B * self.K)[0]
+
+    self.rpl = 0.30
+    self.ipl = 0.10
+    self.PlaceObserverPoles([self.rpl + 1j * self.ipl,
+                             self.rpl - 1j * self.ipl])
+
+    print 'L is', self.L
+
+    q_pos = 0.05
+    q_vel = 2.65
+    self.Q = numpy.matrix([[(q_pos ** 2.0), 0.0],
+                           [0.0, (q_vel ** 2.0)]])
+
+    r_volts = 0.025
+    self.R = numpy.matrix([[(r_volts ** 2.0)]])
+
+    self.KalmanGain, self.Q_steady = controls.kalman(
+        A=self.A, B=self.B, C=self.C, Q=self.Q, R=self.R)
+
+    print 'Kal', self.KalmanGain
+    self.L = self.A * self.KalmanGain
+    print 'KalL is', self.L
+
+    # The box formed by U_min and U_max must encompass all possible values,
+    # or else Austin's code gets angry.
+    self.U_max = numpy.matrix([[12.0]])
+    self.U_min = numpy.matrix([[-12.0]])
+
+    self.InitializeState()
+
+
+def run_test(claw, initial_X, goal, max_separation_error=0.01,
+             show_graph=True, iterations=200, controller_claw=None,
+             observer_claw=None):
+  """Runs the claw plant with an initial condition and goal.
+
+    The tests themselves are not terribly sophisticated; I just test for
+    whether the goal has been reached and whether the separation goes
+    outside of the initial and goal values by more than max_separation_error.
+    Prints out something for a failure of either condition and returns
+    False if tests fail.
+    Args:
+      claw: claw object to use.
+      initial_X: starting state.
+      goal: goal state.
+      show_graph: Whether or not to display a graph showing the changing
+           states and voltages.
+      iterations: Number of timesteps to run the model for.
+      controller_claw: claw object to get K from, or None if we should
+          use claw.
+      observer_claw: claw object to use for the observer, or None if we should
+          use the actual state.
+  """
+
+  claw.X = initial_X
+
+  if controller_claw is None:
+    controller_claw = claw
+
+  if observer_claw is not None:
+    observer_claw.X_hat = initial_X + 0.01
+    observer_claw.X_hat = initial_X
+
+  # Various lists for graphing things.
+  t = []
+  x = []
+  v = []
+  x_hat = []
+  u = []
+
+  sep_plot_gain = 100.0
+
+  for i in xrange(iterations):
+    X_hat = claw.X
+    if observer_claw is not None:
+      X_hat = observer_claw.X_hat
+      x_hat.append(observer_claw.X_hat[0, 0])
+    U = controller_claw.K * (goal - X_hat)
+    U[0, 0] = numpy.clip(U[0, 0], -12, 12)
+    x.append(claw.X[0, 0])
+    v.append(claw.X[1, 0])
+    if observer_claw is not None:
+      observer_claw.PredictObserver(U)
+    claw.Update(U)
+    if observer_claw is not None:
+      observer_claw.Y = claw.Y
+      observer_claw.CorrectObserver(U)
+
+    t.append(i * claw.dt)
+    u.append(U[0, 0])
+
+  if show_graph:
+    pylab.subplot(2, 1, 1)
+    pylab.plot(t, x, label='x')
+    if observer_claw is not None:
+      pylab.plot(t, x_hat, label='x_hat')
+    pylab.legend()
+
+    pylab.subplot(2, 1, 2)
+    pylab.plot(t, u, label='u')
+    pylab.legend()
+    pylab.show()
+
+
+def main(argv):
+  loaded_mass = 0
+  #loaded_mass = 0
+  claw = Claw(mass=4 + loaded_mass)
+  claw_controller = Claw(mass=5 + 0)
+  observer_claw = Claw(mass=5 + 0)
+  #observer_claw = None
+
+  # Test moving the claw with constant separation.
+  initial_X = numpy.matrix([[0.0], [0.0]])
+  R = numpy.matrix([[1.0], [0.0]])
+  run_test(claw, initial_X, R, controller_claw=claw_controller,
+           observer_claw=observer_claw)
+
+  # Write the generated constants out to a file.
+  if len(argv) != 3:
+    print "Expected .h file name and .cc file name for the claw."
+  else:
+    claw = Claw("Claw")
+    loop_writer = control_loop.ControlLoopWriter("Claw", [claw])
+    if argv[1][-3:] == '.cc':
+      loop_writer.Write(argv[2], argv[1])
+    else:
+      loop_writer.Write(argv[1], argv[2])
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))
diff --git a/y2015/control_loops/python/drivetrain.py b/y2015/control_loops/python/drivetrain.py
new file mode 100755
index 0000000..8ed62d6
--- /dev/null
+++ b/y2015/control_loops/python/drivetrain.py
@@ -0,0 +1,242 @@
+#!/usr/bin/python
+
+import control_loop
+import controls
+import numpy
+import sys
+from matplotlib import pylab
+
+
+class CIM(control_loop.ControlLoop):
+  def __init__(self):
+    super(CIM, self).__init__("CIM")
+    # Stall Torque in N m
+    self.stall_torque = 2.42
+    # Stall Current in Amps
+    self.stall_current = 133
+    # Free Speed in RPM
+    self.free_speed = 4650.0
+    # Free Current in Amps
+    self.free_current = 2.7
+    # Moment of inertia of the CIM in kg m^2
+    self.J = 0.0001
+    # Resistance of the motor, divided by 2 to account for the 2 motors
+    self.R = 12.0 / self.stall_current
+    # Motor velocity constant
+    self.Kv = ((self.free_speed / 60.0 * 2.0 * numpy.pi) /
+              (12.0 - self.R * self.free_current))
+    # Torque constant
+    self.Kt = self.stall_torque / self.stall_current
+    # Control loop time step
+    self.dt = 0.005
+
+    # State feedback matrices
+    self.A_continuous = numpy.matrix(
+        [[-self.Kt / self.Kv / (self.J * self.R)]])
+    self.B_continuous = numpy.matrix(
+        [[self.Kt / (self.J * self.R)]])
+    self.C = numpy.matrix([[1]])
+    self.D = numpy.matrix([[0]])
+
+    self.A, self.B = self.ContinuousToDiscrete(self.A_continuous,
+                                               self.B_continuous, self.dt)
+
+    self.PlaceControllerPoles([0.01])
+    self.PlaceObserverPoles([0.01])
+
+    self.U_max = numpy.matrix([[12.0]])
+    self.U_min = numpy.matrix([[-12.0]])
+
+    self.InitializeState()
+
+
+class Drivetrain(control_loop.ControlLoop):
+  def __init__(self, name="Drivetrain", left_low=True, right_low=True):
+    super(Drivetrain, self).__init__(name)
+    # Stall Torque in N m
+    self.stall_torque = 2.42
+    # Stall Current in Amps
+    self.stall_current = 133.0
+    # Free Speed in RPM. Used number from last year.
+    self.free_speed = 4650.0
+    # Free Current in Amps
+    self.free_current = 2.7
+    # Moment of inertia of the drivetrain in kg m^2
+    # Just borrowed from last year.
+    self.J = 10
+    # Mass of the robot, in kg.
+    self.m = 68
+    # Radius of the robot, in meters (from last year).
+    self.rb = 0.9603 / 2.0
+    # Radius of the wheels, in meters.
+    self.r = .0515938
+    # Resistance of the motor, divided by the number of motors.
+    self.R = 12.0 / self.stall_current / 2
+    # Motor velocity constant
+    self.Kv = ((self.free_speed / 60.0 * 2.0 * numpy.pi) /
+               (12.0 - self.R * self.free_current))
+    # Torque constant
+    self.Kt = self.stall_torque / self.stall_current
+    # Gear ratios
+    self.G_const = 28.0 / 50.0 * 20.0 / 64.0
+
+    self.G_low = self.G_const
+    self.G_high = self.G_const
+
+    if left_low:
+      self.Gl = self.G_low
+    else:
+      self.Gl = self.G_high
+    if right_low:
+      self.Gr = self.G_low
+    else:
+      self.Gr = self.G_high
+
+    # Control loop time step
+    self.dt = 0.005
+
+    # These describe the way that a given side of a robot will be influenced
+    # by the other side. Units of 1 / kg.
+    self.msp = 1.0 / self.m + self.rb * self.rb / self.J
+    self.msn = 1.0 / self.m - self.rb * self.rb / self.J
+    # The calculations which we will need for A and B.
+    self.tcl = -self.Kt / self.Kv / (self.Gl * self.Gl * self.R * self.r * self.r)
+    self.tcr = -self.Kt / self.Kv / (self.Gr * self.Gr * self.R * self.r * self.r)
+    self.mpl = self.Kt / (self.Gl * self.R * self.r)
+    self.mpr = self.Kt / (self.Gr * self.R * self.r)
+
+    # State feedback matrices
+    # X will be of the format
+    # [[positionl], [velocityl], [positionr], velocityr]]
+    self.A_continuous = numpy.matrix(
+        [[0, 1, 0, 0],
+         [0, self.msp * self.tcl, 0, self.msn * self.tcr],
+         [0, 0, 0, 1],
+         [0, self.msn * self.tcl, 0, self.msp * self.tcr]])
+    self.B_continuous = numpy.matrix(
+        [[0, 0],
+         [self.msp * self.mpl, self.msn * self.mpr],
+         [0, 0],
+         [self.msn * self.mpl, self.msp * self.mpr]])
+    self.C = numpy.matrix([[1, 0, 0, 0],
+                           [0, 0, 1, 0]])
+    self.D = numpy.matrix([[0, 0],
+                           [0, 0]])
+
+    #print "THE NUMBER I WANT" + str(numpy.linalg.inv(self.A_continuous) * -self.B_continuous * numpy.matrix([[12.0], [12.0]]))
+    self.A, self.B = self.ContinuousToDiscrete(
+        self.A_continuous, self.B_continuous, self.dt)
+
+    # Poles from last year.
+    self.hp = 0.65
+    self.lp = 0.83
+    self.PlaceControllerPoles([self.hp, self.lp, self.hp, self.lp])
+    print self.K
+    q_pos = 0.07
+    q_vel = 1.0
+    self.Q = numpy.matrix([[(1.0 / (q_pos ** 2.0)), 0.0, 0.0, 0.0],
+                           [0.0, (1.0 / (q_vel ** 2.0)), 0.0, 0.0],
+                           [0.0, 0.0, (1.0 / (q_pos ** 2.0)), 0.0],
+                           [0.0, 0.0, 0.0, (1.0 / (q_vel ** 2.0))]])
+
+    self.R = numpy.matrix([[(1.0 / (12.0 ** 2.0)), 0.0],
+                           [0.0, (1.0 / (12.0 ** 2.0))]])
+    self.K = controls.dlqr(self.A, self.B, self.Q, self.R)
+    print self.A
+    print self.B
+    print self.K
+    print numpy.linalg.eig(self.A - self.B * self.K)[0]
+
+    self.hlp = 0.3
+    self.llp = 0.4
+    self.PlaceObserverPoles([self.hlp, self.hlp, self.llp, self.llp])
+
+    self.U_max = numpy.matrix([[12.0], [12.0]])
+    self.U_min = numpy.matrix([[-12.0], [-12.0]])
+    self.InitializeState()
+
+def main(argv):
+  # Simulate the response of the system to a step input.
+  drivetrain = Drivetrain()
+  simulated_left = []
+  simulated_right = []
+  for _ in xrange(100):
+    drivetrain.Update(numpy.matrix([[12.0], [12.0]]))
+    simulated_left.append(drivetrain.X[0, 0])
+    simulated_right.append(drivetrain.X[2, 0])
+
+  #pylab.plot(range(100), simulated_left)
+  #pylab.plot(range(100), simulated_right)
+  #pylab.show()
+
+  # Simulate forwards motion.
+  drivetrain = Drivetrain()
+  close_loop_left = []
+  close_loop_right = []
+  R = numpy.matrix([[1.0], [0.0], [1.0], [0.0]])
+  for _ in xrange(100):
+    U = numpy.clip(drivetrain.K * (R - drivetrain.X_hat),
+                   drivetrain.U_min, drivetrain.U_max)
+    drivetrain.UpdateObserver(U)
+    drivetrain.Update(U)
+    close_loop_left.append(drivetrain.X[0, 0])
+    close_loop_right.append(drivetrain.X[2, 0])
+
+  #pylab.plot(range(100), close_loop_left)
+  #pylab.plot(range(100), close_loop_right)
+  #pylab.show()
+
+  # Try turning in place
+  drivetrain = Drivetrain()
+  close_loop_left = []
+  close_loop_right = []
+  R = numpy.matrix([[-1.0], [0.0], [1.0], [0.0]])
+  for _ in xrange(100):
+    U = numpy.clip(drivetrain.K * (R - drivetrain.X_hat),
+                   drivetrain.U_min, drivetrain.U_max)
+    drivetrain.UpdateObserver(U)
+    drivetrain.Update(U)
+    close_loop_left.append(drivetrain.X[0, 0])
+    close_loop_right.append(drivetrain.X[2, 0])
+
+  #pylab.plot(range(100), close_loop_left)
+  #pylab.plot(range(100), close_loop_right)
+  #pylab.show()
+
+  # Try turning just one side.
+  drivetrain = Drivetrain()
+  close_loop_left = []
+  close_loop_right = []
+  R = numpy.matrix([[0.0], [0.0], [1.0], [0.0]])
+  for _ in xrange(100):
+    U = numpy.clip(drivetrain.K * (R - drivetrain.X_hat),
+                   drivetrain.U_min, drivetrain.U_max)
+    drivetrain.UpdateObserver(U)
+    drivetrain.Update(U)
+    close_loop_left.append(drivetrain.X[0, 0])
+    close_loop_right.append(drivetrain.X[2, 0])
+
+  #pylab.plot(range(100), close_loop_left)
+  #pylab.plot(range(100), close_loop_right)
+  #pylab.show()
+
+  # Write the generated constants out to a file.
+  print "Output one"
+  drivetrain_low_low = Drivetrain(name="DrivetrainLowLow", left_low=True, right_low=True)
+  drivetrain_low_high = Drivetrain(name="DrivetrainLowHigh", left_low=True, right_low=False)
+  drivetrain_high_low = Drivetrain(name="DrivetrainHighLow", left_low=False, right_low=True)
+  drivetrain_high_high = Drivetrain(name="DrivetrainHighHigh", left_low=False, right_low=False)
+
+  if len(argv) != 5:
+    print "Expected .h file name and .cc file name"
+  else:
+    dog_loop_writer = control_loop.ControlLoopWriter(
+        "Drivetrain", [drivetrain_low_low, drivetrain_low_high,
+                       drivetrain_high_low, drivetrain_high_high])
+    if argv[1][-3:] == '.cc':
+      dog_loop_writer.Write(argv[2], argv[1])
+    else:
+      dog_loop_writer.Write(argv[1], argv[2])
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))
diff --git a/y2015/control_loops/python/elevator.py b/y2015/control_loops/python/elevator.py
new file mode 100755
index 0000000..fba72c8
--- /dev/null
+++ b/y2015/control_loops/python/elevator.py
@@ -0,0 +1,246 @@
+#!/usr/bin/python
+
+import control_loop
+import controls
+import polytope
+import polydrivetrain
+import numpy
+import sys
+import matplotlib
+from matplotlib import pylab
+
+class Elevator(control_loop.ControlLoop):
+  def __init__(self, name="Elevator", mass=None):
+    super(Elevator, self).__init__(name)
+    # Stall Torque in N m
+    self.stall_torque = 0.476
+    # Stall Current in Amps
+    self.stall_current = 80.730
+    # Free Speed in RPM
+    self.free_speed = 13906.0
+    # Free Current in Amps
+    self.free_current = 5.820
+    # Mass of the elevator
+    if mass is None:
+      self.mass = 13.0
+    else:
+      self.mass = mass
+
+    # Resistance of the motor
+    self.R = 12.0 / self.stall_current
+    # Motor velocity constant
+    self.Kv = ((self.free_speed / 60.0 * 2.0 * numpy.pi) /
+               (12.0 - self.R * self.free_current))
+    # Torque constant
+    self.Kt = self.stall_torque / self.stall_current
+    # Gear ratio
+    self.G = (56.0 / 12.0) * (84.0 / 14.0)
+    # Pulley diameter
+    self.r = 32 * 0.005 / numpy.pi / 2.0
+    # Control loop time step
+    self.dt = 0.005
+
+    # Elevator left/right spring constant (N/m)
+    self.spring = 800.0
+
+    # State is [average position, average velocity,
+    #           position difference/2, velocity difference/2]
+    # Input is [V_left, V_right]
+
+    C1 = self.spring / (self.mass * 0.5)
+    C2 = self.Kt * self.G / (self.mass * 0.5 * self.r * self.R)
+    C3 = self.G * self.G * self.Kt / (
+        self.R  * self.r * self.r * self.mass * 0.5 * self.Kv)
+
+    self.A_continuous = numpy.matrix(
+        [[0, 1, 0, 0],
+         [0, -C3, 0, 0],
+         [0, 0, 0, 1],
+         [0, 0, -C1 * 2.0, -C3]])
+
+    print "Full speed is", C2 / C3 * 12.0
+
+    # Start with the unmodified input
+    self.B_continuous = numpy.matrix(
+        [[0, 0],
+         [C2 / 2.0, C2 / 2.0],
+         [0, 0],
+         [C2 / 2.0, -C2 / 2.0]])
+
+    self.C = numpy.matrix([[1, 0, 1, 0],
+                           [1, 0, -1, 0]])
+    self.D = numpy.matrix([[0, 0],
+                           [0, 0]])
+
+    self.A, self.B = self.ContinuousToDiscrete(
+        self.A_continuous, self.B_continuous, self.dt)
+
+    print self.A
+
+    controlability = controls.ctrb(self.A, self.B);
+    print "Rank of augmented controlability matrix.", numpy.linalg.matrix_rank(
+        controlability)
+
+    q_pos = 0.02
+    q_vel = 0.400
+    q_pos_diff = 0.01
+    q_vel_diff = 0.45
+    self.Q = numpy.matrix([[(1.0 / (q_pos ** 2.0)), 0.0, 0.0, 0.0],
+                           [0.0, (1.0 / (q_vel ** 2.0)), 0.0, 0.0],
+                           [0.0, 0.0, (1.0 / (q_pos_diff ** 2.0)), 0.0],
+                           [0.0, 0.0, 0.0, (1.0 / (q_vel_diff ** 2.0))]])
+
+    self.R = numpy.matrix([[(1.0 / (12.0 ** 2.0)), 0.0],
+                           [0.0, 1.0 / (12.0 ** 2.0)]])
+    self.K = controls.dlqr(self.A, self.B, self.Q, self.R)
+    print self.K
+
+    print numpy.linalg.eig(self.A - self.B * self.K)[0]
+
+    self.rpl = 0.20
+    self.ipl = 0.05
+    self.PlaceObserverPoles([self.rpl + 1j * self.ipl,
+                             self.rpl + 1j * self.ipl,
+                             self.rpl - 1j * self.ipl,
+                             self.rpl - 1j * self.ipl])
+
+    # The box formed by U_min and U_max must encompass all possible values,
+    # or else Austin's code gets angry.
+    self.U_max = numpy.matrix([[12.0], [12.0]])
+    self.U_min = numpy.matrix([[-12.0], [-12.0]])
+
+    self.InitializeState()
+
+
+def CapU(U):
+  if U[0, 0] - U[1, 0] > 24:
+    return numpy.matrix([[12], [-12]])
+  elif U[0, 0] - U[1, 0] < -24:
+    return numpy.matrix([[-12], [12]])
+  else:
+    max_u = max(U[0, 0], U[1, 0])
+    min_u = min(U[0, 0], U[1, 0])
+    if max_u > 12:
+      return U - (max_u - 12)
+    if min_u < -12:
+      return U - (min_u + 12)
+    return U
+
+
+def run_test(elevator, initial_X, goal, max_separation_error=0.01,
+             show_graph=True, iterations=200, controller_elevator=None,
+             observer_elevator=None):
+  """Runs the elevator plant with an initial condition and goal.
+
+    The tests themselves are not terribly sophisticated; I just test for
+    whether the goal has been reached and whether the separation goes
+    outside of the initial and goal values by more than max_separation_error.
+    Prints out something for a failure of either condition and returns
+    False if tests fail.
+    Args:
+      elevator: elevator object to use.
+      initial_X: starting state.
+      goal: goal state.
+      show_graph: Whether or not to display a graph showing the changing
+           states and voltages.
+      iterations: Number of timesteps to run the model for.
+      controller_elevator: elevator object to get K from, or None if we should
+          use elevator.
+      observer_elevator: elevator object to use for the observer, or None if we
+          should use the actual state.
+  """
+
+  elevator.X = initial_X
+
+  if controller_elevator is None:
+    controller_elevator = elevator
+
+  if observer_elevator is not None:
+    observer_elevator.X_hat = initial_X + 0.01
+    observer_elevator.X_hat = initial_X
+
+  # Various lists for graphing things.
+  t = []
+  x_avg = []
+  x_sep = []
+  x_hat_avg = []
+  x_hat_sep = []
+  v_avg = []
+  v_sep = []
+  u_left = []
+  u_right = []
+
+  sep_plot_gain = 100.0
+
+  for i in xrange(iterations):
+    X_hat = elevator.X
+    if observer_elevator is not None:
+      X_hat = observer_elevator.X_hat
+      x_hat_avg.append(observer_elevator.X_hat[0, 0])
+      x_hat_sep.append(observer_elevator.X_hat[2, 0] * sep_plot_gain)
+    U = controller_elevator.K * (goal - X_hat)
+    U = CapU(U)
+    x_avg.append(elevator.X[0, 0])
+    v_avg.append(elevator.X[1, 0])
+    x_sep.append(elevator.X[2, 0] * sep_plot_gain)
+    v_sep.append(elevator.X[3, 0])
+    if observer_elevator is not None:
+      observer_elevator.PredictObserver(U)
+    elevator.Update(U)
+    if observer_elevator is not None:
+      observer_elevator.Y = elevator.Y
+      observer_elevator.CorrectObserver(U)
+
+    t.append(i * elevator.dt)
+    u_left.append(U[0, 0])
+    u_right.append(U[1, 0])
+
+  print numpy.linalg.inv(elevator.A)
+  print "delta time is ", elevator.dt
+  print "Velocity at t=0 is ", x_avg[0], v_avg[0], x_sep[0], v_sep[0]
+  print "Velocity at t=1+dt is ", x_avg[1], v_avg[1], x_sep[1], v_sep[1]
+
+  if show_graph:
+    pylab.subplot(2, 1, 1)
+    pylab.plot(t, x_avg, label='x avg')
+    pylab.plot(t, x_sep, label='x sep')
+    if observer_elevator is not None:
+      pylab.plot(t, x_hat_avg, label='x_hat avg')
+      pylab.plot(t, x_hat_sep, label='x_hat sep')
+    pylab.legend()
+
+    pylab.subplot(2, 1, 2)
+    pylab.plot(t, u_left, label='u left')
+    pylab.plot(t, u_right, label='u right')
+    pylab.legend()
+    pylab.show()
+
+
+def main(argv):
+  loaded_mass = 25
+  #loaded_mass = 0
+  elevator = Elevator(mass=13 + loaded_mass)
+  elevator_controller = Elevator(mass=13 + 15)
+  observer_elevator = Elevator(mass=13 + 15)
+  #observer_elevator = None
+
+  # Test moving the elevator with constant separation.
+  initial_X = numpy.matrix([[0.0], [0.0], [0.01], [0.0]])
+  #initial_X = numpy.matrix([[0.0], [0.0], [0.00], [0.0]])
+  R = numpy.matrix([[1.0], [0.0], [0.0], [0.0]])
+  run_test(elevator, initial_X, R, controller_elevator=elevator_controller,
+           observer_elevator=observer_elevator)
+
+  # Write the generated constants out to a file.
+  if len(argv) != 3:
+    print "Expected .h file name and .cc file name for the elevator."
+  else:
+    elevator = Elevator("Elevator")
+    loop_writer = control_loop.ControlLoopWriter("Elevator", [elevator])
+    if argv[1][-3:] == '.cc':
+      loop_writer.Write(argv[2], argv[1])
+    else:
+      loop_writer.Write(argv[1], argv[2])
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))
diff --git a/y2015/control_loops/python/polydrivetrain.py b/y2015/control_loops/python/polydrivetrain.py
new file mode 100755
index 0000000..a62c8c8
--- /dev/null
+++ b/y2015/control_loops/python/polydrivetrain.py
@@ -0,0 +1,504 @@
+#!/usr/bin/python
+
+import numpy
+import sys
+import polytope
+import drivetrain
+import control_loop
+import controls
+from matplotlib import pylab
+
+__author__ = 'Austin Schuh (austin.linux@gmail.com)'
+
+
+def CoerceGoal(region, K, w, R):
+  """Intersects a line with a region, and finds the closest point to R.
+
+  Finds a point that is closest to R inside the region, and on the line
+  defined by K X = w.  If it is not possible to find a point on the line,
+  finds a point that is inside the region and closest to the line.  This
+  function assumes that
+
+  Args:
+    region: HPolytope, the valid goal region.
+    K: numpy.matrix (2 x 1), the matrix for the equation [K1, K2] [x1; x2] = w
+    w: float, the offset in the equation above.
+    R: numpy.matrix (2 x 1), the point to be closest to.
+
+  Returns:
+    numpy.matrix (2 x 1), the point.
+  """
+  return DoCoerceGoal(region, K, w, R)[0]
+
+def DoCoerceGoal(region, K, w, R):
+  if region.IsInside(R):
+    return (R, True)
+
+  perpendicular_vector = K.T / numpy.linalg.norm(K)
+  parallel_vector = numpy.matrix([[perpendicular_vector[1, 0]],
+                                  [-perpendicular_vector[0, 0]]])
+  
+  # We want to impose the constraint K * X = w on the polytope H * X <= k.
+  # We do this by breaking X up into parallel and perpendicular components to
+  # the half plane.  This gives us the following equation.
+  #
+  #  parallel * (parallel.T \dot X) + perpendicular * (perpendicular \dot X)) = X
+  #
+  # Then, substitute this into the polytope.
+  #
+  #  H * (parallel * (parallel.T \dot X) + perpendicular * (perpendicular \dot X)) <= k
+  #
+  # Substitute K * X = w
+  #
+  # H * parallel * (parallel.T \dot X) + H * perpendicular * w <= k
+  #
+  # Move all the knowns to the right side.
+  #
+  # H * parallel * ([parallel1 parallel2] * X) <= k - H * perpendicular * w
+  #
+  # Let t = parallel.T \dot X, the component parallel to the surface.
+  #
+  # H * parallel * t <= k - H * perpendicular * w
+  #
+  # This is a polytope which we can solve, and use to figure out the range of X
+  # that we care about!
+
+  t_poly = polytope.HPolytope(
+      region.H * parallel_vector,
+      region.k - region.H * perpendicular_vector * w)
+
+  vertices = t_poly.Vertices()
+
+  if vertices.shape[0]:
+    # The region exists!
+    # Find the closest vertex
+    min_distance = numpy.infty
+    closest_point = None
+    for vertex in vertices:
+      point = parallel_vector * vertex + perpendicular_vector * w
+      length = numpy.linalg.norm(R - point)
+      if length < min_distance:
+        min_distance = length
+        closest_point = point
+
+    return (closest_point, True)
+  else:
+    # Find the vertex of the space that is closest to the line.
+    region_vertices = region.Vertices()
+    min_distance = numpy.infty
+    closest_point = None
+    for vertex in region_vertices:
+      point = vertex.T
+      length = numpy.abs((perpendicular_vector.T * point)[0, 0])
+      if length < min_distance:
+        min_distance = length
+        closest_point = point
+
+    return (closest_point, False)
+
+
+class VelocityDrivetrainModel(control_loop.ControlLoop):
+  def __init__(self, left_low=True, right_low=True, name="VelocityDrivetrainModel"):
+    super(VelocityDrivetrainModel, self).__init__(name)
+    self._drivetrain = drivetrain.Drivetrain(left_low=left_low,
+                                             right_low=right_low)
+    self.dt = 0.01
+    self.A_continuous = numpy.matrix(
+        [[self._drivetrain.A_continuous[1, 1], self._drivetrain.A_continuous[1, 3]],
+         [self._drivetrain.A_continuous[3, 1], self._drivetrain.A_continuous[3, 3]]])
+
+    self.B_continuous = numpy.matrix(
+        [[self._drivetrain.B_continuous[1, 0], self._drivetrain.B_continuous[1, 1]],
+         [self._drivetrain.B_continuous[3, 0], self._drivetrain.B_continuous[3, 1]]])
+    self.C = numpy.matrix(numpy.eye(2));
+    self.D = numpy.matrix(numpy.zeros((2, 2)));
+
+    self.A, self.B = self.ContinuousToDiscrete(self.A_continuous,
+                                               self.B_continuous, self.dt)
+
+    # FF * X = U (steady state)
+    self.FF = self.B.I * (numpy.eye(2) - self.A)
+
+    self.PlaceControllerPoles([0.6, 0.6])
+    self.PlaceObserverPoles([0.02, 0.02])
+
+    self.G_high = self._drivetrain.G_high
+    self.G_low = self._drivetrain.G_low
+    self.R = self._drivetrain.R
+    self.r = self._drivetrain.r
+    self.Kv = self._drivetrain.Kv
+    self.Kt = self._drivetrain.Kt
+
+    self.U_max = self._drivetrain.U_max
+    self.U_min = self._drivetrain.U_min
+
+
+class VelocityDrivetrain(object):
+  HIGH = 'high'
+  LOW = 'low'
+  SHIFTING_UP = 'up'
+  SHIFTING_DOWN = 'down'
+
+  def __init__(self):
+    self.drivetrain_low_low = VelocityDrivetrainModel(
+        left_low=True, right_low=True, name='VelocityDrivetrainLowLow')
+    self.drivetrain_low_high = VelocityDrivetrainModel(left_low=True, right_low=False, name='VelocityDrivetrainLowHigh')
+    self.drivetrain_high_low = VelocityDrivetrainModel(left_low=False, right_low=True, name = 'VelocityDrivetrainHighLow')
+    self.drivetrain_high_high = VelocityDrivetrainModel(left_low=False, right_low=False, name = 'VelocityDrivetrainHighHigh')
+
+    # X is [lvel, rvel]
+    self.X = numpy.matrix(
+        [[0.0],
+         [0.0]])
+
+    self.U_poly = polytope.HPolytope(
+        numpy.matrix([[1, 0],
+                      [-1, 0],
+                      [0, 1],
+                      [0, -1]]),
+        numpy.matrix([[12],
+                      [12],
+                      [12],
+                      [12]]))
+
+    self.U_max = numpy.matrix(
+        [[12.0],
+         [12.0]])
+    self.U_min = numpy.matrix(
+        [[-12.0000000000],
+         [-12.0000000000]])
+
+    self.dt = 0.01
+
+    self.R = numpy.matrix(
+        [[0.0],
+         [0.0]])
+
+    # ttrust is the comprimise between having full throttle negative inertia,
+    # and having no throttle negative inertia.  A value of 0 is full throttle
+    # inertia.  A value of 1 is no throttle negative inertia.
+    self.ttrust = 1.1
+
+    self.left_gear = VelocityDrivetrain.LOW
+    self.right_gear = VelocityDrivetrain.LOW
+    self.left_shifter_position = 0.0
+    self.right_shifter_position = 0.0
+    self.left_cim = drivetrain.CIM()
+    self.right_cim = drivetrain.CIM()
+
+  def IsInGear(self, gear):
+    return gear is VelocityDrivetrain.HIGH or gear is VelocityDrivetrain.LOW
+
+  def MotorRPM(self, shifter_position, velocity):
+    if shifter_position > 0.5:
+      return (velocity / self.CurrentDrivetrain().G_high /
+              self.CurrentDrivetrain().r)
+    else:
+      return (velocity / self.CurrentDrivetrain().G_low /
+              self.CurrentDrivetrain().r)
+
+  def CurrentDrivetrain(self):
+    if self.left_shifter_position > 0.5:
+      if self.right_shifter_position > 0.5:
+        return self.drivetrain_high_high
+      else:
+        return self.drivetrain_high_low
+    else:
+      if self.right_shifter_position > 0.5:
+        return self.drivetrain_low_high
+      else:
+        return self.drivetrain_low_low
+
+  def SimShifter(self, gear, shifter_position):
+    if gear is VelocityDrivetrain.HIGH or gear is VelocityDrivetrain.SHIFTING_UP:
+      shifter_position = min(shifter_position + 0.5, 1.0)
+    else:
+      shifter_position = max(shifter_position - 0.5, 0.0)
+
+    if shifter_position == 1.0:
+      gear = VelocityDrivetrain.HIGH
+    elif shifter_position == 0.0:
+      gear = VelocityDrivetrain.LOW
+
+    return gear, shifter_position
+
+  def ComputeGear(self, wheel_velocity, should_print=False, current_gear=False, gear_name=None):
+    high_omega = (wheel_velocity / self.CurrentDrivetrain().G_high /
+                  self.CurrentDrivetrain().r)
+    low_omega = (wheel_velocity / self.CurrentDrivetrain().G_low /
+                 self.CurrentDrivetrain().r)
+    #print gear_name, "Motor Energy Difference.", 0.5 * 0.000140032647 * (low_omega * low_omega - high_omega * high_omega), "joules"
+    high_torque = ((12.0 - high_omega / self.CurrentDrivetrain().Kv) *
+                   self.CurrentDrivetrain().Kt / self.CurrentDrivetrain().R)
+    low_torque = ((12.0 - low_omega / self.CurrentDrivetrain().Kv) *
+                  self.CurrentDrivetrain().Kt / self.CurrentDrivetrain().R)
+    high_power = high_torque * high_omega
+    low_power = low_torque * low_omega
+    #if should_print:
+    #  print gear_name, "High omega", high_omega, "Low omega", low_omega
+    #  print gear_name, "High torque", high_torque, "Low torque", low_torque
+    #  print gear_name, "High power", high_power, "Low power", low_power
+
+    # Shift algorithm improvements.
+    # TODO(aschuh):
+    # It takes time to shift.  Shifting down for 1 cycle doesn't make sense
+    # because you will end up slower than without shifting.  Figure out how
+    # to include that info.
+    # If the driver is still in high gear, but isn't asking for the extra power
+    # from low gear, don't shift until he asks for it.
+    goal_gear_is_high = high_power > low_power
+    #goal_gear_is_high = True
+
+    if not self.IsInGear(current_gear):
+      print gear_name, 'Not in gear.'
+      return current_gear
+    else:
+      is_high = current_gear is VelocityDrivetrain.HIGH
+      if is_high != goal_gear_is_high:
+        if goal_gear_is_high:
+          print gear_name, 'Shifting up.'
+          return VelocityDrivetrain.SHIFTING_UP
+        else:
+          print gear_name, 'Shifting down.'
+          return VelocityDrivetrain.SHIFTING_DOWN
+      else:
+        return current_gear
+
+  def FilterVelocity(self, throttle):
+    # Invert the plant to figure out how the velocity filter would have to work
+    # out in order to filter out the forwards negative inertia.
+    # This math assumes that the left and right power and velocity are equal.
+
+    # The throttle filter should filter such that the motor in the highest gear
+    # should be controlling the time constant.
+    # Do this by finding the index of FF that has the lowest value, and computing
+    # the sums using that index.
+    FF_sum = self.CurrentDrivetrain().FF.sum(axis=1)
+    min_FF_sum_index = numpy.argmin(FF_sum)
+    min_FF_sum = FF_sum[min_FF_sum_index, 0]
+    min_K_sum = self.CurrentDrivetrain().K[min_FF_sum_index, :].sum()
+    # Compute the FF sum for high gear.
+    high_min_FF_sum = self.drivetrain_high_high.FF[0, :].sum()
+
+    # U = self.K[0, :].sum() * (R - x_avg) + self.FF[0, :].sum() * R
+    # throttle * 12.0 = (self.K[0, :].sum() + self.FF[0, :].sum()) * R
+    #                   - self.K[0, :].sum() * x_avg
+
+    # R = (throttle * 12.0 + self.K[0, :].sum() * x_avg) /
+    #     (self.K[0, :].sum() + self.FF[0, :].sum())
+
+    # U = (K + FF) * R - K * X
+    # (K + FF) ^-1 * (U + K * X) = R
+
+    # Scale throttle by min_FF_sum / high_min_FF_sum.  This will make low gear
+    # have the same velocity goal as high gear, and so that the robot will hold
+    # the same speed for the same throttle for all gears.
+    adjusted_ff_voltage = numpy.clip(throttle * 12.0 * min_FF_sum / high_min_FF_sum, -12.0, 12.0)
+    return ((adjusted_ff_voltage + self.ttrust * min_K_sum * (self.X[0, 0] + self.X[1, 0]) / 2.0)
+            / (self.ttrust * min_K_sum + min_FF_sum))
+
+  def Update(self, throttle, steering):
+    # Shift into the gear which sends the most power to the floor.
+    # This is the same as sending the most torque down to the floor at the
+    # wheel.
+
+    self.left_gear = self.right_gear = True
+    if False:
+      self.left_gear = self.ComputeGear(self.X[0, 0], should_print=True,
+                                        current_gear=self.left_gear,
+                                        gear_name="left")
+      self.right_gear = self.ComputeGear(self.X[1, 0], should_print=True,
+                                         current_gear=self.right_gear,
+                                         gear_name="right")
+      if self.IsInGear(self.left_gear):
+        self.left_cim.X[0, 0] = self.MotorRPM(self.left_shifter_position, self.X[0, 0])
+
+      if self.IsInGear(self.right_gear):
+        self.right_cim.X[0, 0] = self.MotorRPM(self.right_shifter_position, self.X[0, 0])
+
+    steering *= 2.3
+    if True or self.IsInGear(self.left_gear) and self.IsInGear(self.right_gear):
+      # Filter the throttle to provide a nicer response.
+      fvel = self.FilterVelocity(throttle)
+
+      # Constant radius means that angualar_velocity / linear_velocity = constant.
+      # Compute the left and right velocities.
+      steering_velocity = numpy.abs(fvel) * steering
+      left_velocity = fvel - steering_velocity
+      right_velocity = fvel + steering_velocity
+
+      # Write this constraint in the form of K * R = w
+      # angular velocity / linear velocity = constant
+      # (left - right) / (left + right) = constant
+      # left - right = constant * left + constant * right
+
+      # (fvel - steering * numpy.abs(fvel) - fvel - steering * numpy.abs(fvel)) /
+      #  (fvel - steering * numpy.abs(fvel) + fvel + steering * numpy.abs(fvel)) =
+      #       constant
+      # (- 2 * steering * numpy.abs(fvel)) / (2 * fvel) = constant
+      # (-steering * sign(fvel)) = constant
+      # (-steering * sign(fvel)) * (left + right) = left - right
+      # (steering * sign(fvel) + 1) * left + (steering * sign(fvel) - 1) * right = 0
+
+      equality_k = numpy.matrix(
+          [[1 + steering * numpy.sign(fvel), -(1 - steering * numpy.sign(fvel))]])
+      equality_w = 0.0
+
+      self.R[0, 0] = left_velocity
+      self.R[1, 0] = right_velocity
+
+      # Construct a constraint on R by manipulating the constraint on U
+      # Start out with H * U <= k
+      # U = FF * R + K * (R - X)
+      # H * (FF * R + K * R - K * X) <= k
+      # H * (FF + K) * R <= k + H * K * X
+      R_poly = polytope.HPolytope(
+          self.U_poly.H * (self.CurrentDrivetrain().K + self.CurrentDrivetrain().FF),
+          self.U_poly.k + self.U_poly.H * self.CurrentDrivetrain().K * self.X)
+
+      # Limit R back inside the box.
+      self.boxed_R = CoerceGoal(R_poly, equality_k, equality_w, self.R)
+
+      FF_volts = self.CurrentDrivetrain().FF * self.boxed_R
+      self.U_ideal = self.CurrentDrivetrain().K * (self.boxed_R - self.X) + FF_volts
+    else:
+      print 'Not all in gear'
+      if not self.IsInGear(self.left_gear) and not self.IsInGear(self.right_gear):
+        # TODO(austin): Use battery volts here.
+        R_left = self.MotorRPM(self.left_shifter_position, self.X[0, 0])
+        self.U_ideal[0, 0] = numpy.clip(
+            self.left_cim.K * (R_left - self.left_cim.X) + R_left / self.left_cim.Kv,
+            self.left_cim.U_min, self.left_cim.U_max)
+        self.left_cim.Update(self.U_ideal[0, 0])
+
+        R_right = self.MotorRPM(self.right_shifter_position, self.X[1, 0])
+        self.U_ideal[1, 0] = numpy.clip(
+            self.right_cim.K * (R_right - self.right_cim.X) + R_right / self.right_cim.Kv,
+            self.right_cim.U_min, self.right_cim.U_max)
+        self.right_cim.Update(self.U_ideal[1, 0])
+      else:
+        assert False
+
+    self.U = numpy.clip(self.U_ideal, self.U_min, self.U_max)
+
+    # TODO(austin): Model the robot as not accelerating when you shift...
+    # This hack only works when you shift at the same time.
+    if True or self.IsInGear(self.left_gear) and self.IsInGear(self.right_gear):
+      self.X = self.CurrentDrivetrain().A * self.X + self.CurrentDrivetrain().B * self.U
+
+    self.left_gear, self.left_shifter_position = self.SimShifter(
+        self.left_gear, self.left_shifter_position)
+    self.right_gear, self.right_shifter_position = self.SimShifter(
+        self.right_gear, self.right_shifter_position)
+
+    print "U is", self.U[0, 0], self.U[1, 0]
+    print "Left shifter", self.left_gear, self.left_shifter_position, "Right shifter", self.right_gear, self.right_shifter_position
+
+
+def main(argv):
+  vdrivetrain = VelocityDrivetrain()
+
+  if len(argv) != 7:
+    print "Expected .h file name and .cc file name"
+  else:
+    dog_loop_writer = control_loop.ControlLoopWriter(
+        "VelocityDrivetrain", [vdrivetrain.drivetrain_low_low,
+                       vdrivetrain.drivetrain_low_high,
+                       vdrivetrain.drivetrain_high_low,
+                       vdrivetrain.drivetrain_high_high])
+
+    if argv[1][-3:] == '.cc':
+      dog_loop_writer.Write(argv[2], argv[1])
+    else:
+      dog_loop_writer.Write(argv[1], argv[2])
+
+    cim_writer = control_loop.ControlLoopWriter(
+        "CIM", [drivetrain.CIM()])
+
+    if argv[5][-3:] == '.cc':
+      cim_writer.Write(argv[6], argv[5])
+    else:
+      cim_writer.Write(argv[5], argv[6])
+    return
+
+  vl_plot = []
+  vr_plot = []
+  ul_plot = []
+  ur_plot = []
+  radius_plot = []
+  t_plot = []
+  left_gear_plot = []
+  right_gear_plot = []
+  vdrivetrain.left_shifter_position = 0.0
+  vdrivetrain.right_shifter_position = 0.0
+  vdrivetrain.left_gear = VelocityDrivetrain.LOW
+  vdrivetrain.right_gear = VelocityDrivetrain.LOW
+
+  print "K is", vdrivetrain.CurrentDrivetrain().K
+
+  if vdrivetrain.left_gear is VelocityDrivetrain.HIGH:
+    print "Left is high"
+  else:
+    print "Left is low"
+  if vdrivetrain.right_gear is VelocityDrivetrain.HIGH:
+    print "Right is high"
+  else:
+    print "Right is low"
+
+  for t in numpy.arange(0, 1.7, vdrivetrain.dt):
+    if t < 0.5:
+      vdrivetrain.Update(throttle=0.00, steering=1.0)
+    elif t < 1.2:
+      vdrivetrain.Update(throttle=0.5, steering=1.0)
+    else:
+      vdrivetrain.Update(throttle=0.00, steering=1.0)
+    t_plot.append(t)
+    vl_plot.append(vdrivetrain.X[0, 0])
+    vr_plot.append(vdrivetrain.X[1, 0])
+    ul_plot.append(vdrivetrain.U[0, 0])
+    ur_plot.append(vdrivetrain.U[1, 0])
+    left_gear_plot.append((vdrivetrain.left_gear is VelocityDrivetrain.HIGH) * 2.0 - 10.0)
+    right_gear_plot.append((vdrivetrain.right_gear is VelocityDrivetrain.HIGH) * 2.0 - 10.0)
+
+    fwd_velocity = (vdrivetrain.X[1, 0] + vdrivetrain.X[0, 0]) / 2
+    turn_velocity = (vdrivetrain.X[1, 0] - vdrivetrain.X[0, 0])
+    if abs(fwd_velocity) < 0.0000001:
+      radius_plot.append(turn_velocity)
+    else:
+      radius_plot.append(turn_velocity / fwd_velocity)
+
+  cim_velocity_plot = []
+  cim_voltage_plot = []
+  cim_time = []
+  cim = drivetrain.CIM()
+  R = numpy.matrix([[300]])
+  for t in numpy.arange(0, 0.5, cim.dt):
+    U = numpy.clip(cim.K * (R - cim.X) + R / cim.Kv, cim.U_min, cim.U_max)
+    cim.Update(U)
+    cim_velocity_plot.append(cim.X[0, 0])
+    cim_voltage_plot.append(U[0, 0] * 10)
+    cim_time.append(t)
+  pylab.plot(cim_time, cim_velocity_plot, label='cim spinup')
+  pylab.plot(cim_time, cim_voltage_plot, label='cim voltage')
+  pylab.legend()
+  pylab.show()
+
+  # TODO(austin):
+  # Shifting compensation.
+
+  # Tighten the turn.
+  # Closed loop drive.
+
+  pylab.plot(t_plot, vl_plot, label='left velocity')
+  pylab.plot(t_plot, vr_plot, label='right velocity')
+  pylab.plot(t_plot, ul_plot, label='left voltage')
+  pylab.plot(t_plot, ur_plot, label='right voltage')
+  pylab.plot(t_plot, radius_plot, label='radius')
+  pylab.plot(t_plot, left_gear_plot, label='left gear high')
+  pylab.plot(t_plot, right_gear_plot, label='right gear high')
+  pylab.legend()
+  pylab.show()
+  return 0
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))
diff --git a/y2015/control_loops/python/polydrivetrain_test.py b/y2015/control_loops/python/polydrivetrain_test.py
new file mode 100755
index 0000000..434cdca
--- /dev/null
+++ b/y2015/control_loops/python/polydrivetrain_test.py
@@ -0,0 +1,82 @@
+#!/usr/bin/python
+
+import polydrivetrain
+import numpy
+from numpy.testing import *
+import polytope
+import unittest
+
+__author__ = 'Austin Schuh (austin.linux@gmail.com)'
+
+
+class TestVelocityDrivetrain(unittest.TestCase):
+  def MakeBox(self, x1_min, x1_max, x2_min, x2_max):
+    H = numpy.matrix([[1, 0],
+                      [-1, 0],
+                      [0, 1],
+                      [0, -1]])
+    K = numpy.matrix([[x1_max],
+                      [-x1_min],
+                      [x2_max],
+                      [-x2_min]])
+    return polytope.HPolytope(H, K)
+
+  def test_coerce_inside(self):
+    """Tests coercion when the point is inside the box."""
+    box = self.MakeBox(1, 2, 1, 2)
+
+    # x1 = x2
+    K = numpy.matrix([[1, -1]])
+    w = 0
+
+    assert_array_equal(polydrivetrain.CoerceGoal(box, K, w,
+                                                 numpy.matrix([[1.5], [1.5]])),
+                       numpy.matrix([[1.5], [1.5]]))
+
+  def test_coerce_outside_intersect(self):
+    """Tests coercion when the line intersects the box."""
+    box = self.MakeBox(1, 2, 1, 2)
+
+    # x1 = x2
+    K = numpy.matrix([[1, -1]])
+    w = 0
+
+    assert_array_equal(polydrivetrain.CoerceGoal(box, K, w, numpy.matrix([[5], [5]])),
+                       numpy.matrix([[2.0], [2.0]]))
+
+  def test_coerce_outside_no_intersect(self):
+    """Tests coercion when the line does not intersect the box."""
+    box = self.MakeBox(3, 4, 1, 2)
+
+    # x1 = x2
+    K = numpy.matrix([[1, -1]])
+    w = 0
+
+    assert_array_equal(polydrivetrain.CoerceGoal(box, K, w, numpy.matrix([[5], [5]])),
+                       numpy.matrix([[3.0], [2.0]]))
+
+  def test_coerce_middle_of_edge(self):
+    """Tests coercion when the line intersects the middle of an edge."""
+    box = self.MakeBox(0, 4, 1, 2)
+
+    # x1 = x2
+    K = numpy.matrix([[-1, 1]])
+    w = 0
+
+    assert_array_equal(polydrivetrain.CoerceGoal(box, K, w, numpy.matrix([[5], [5]])),
+                       numpy.matrix([[2.0], [2.0]]))
+
+  def test_coerce_perpendicular_line(self):
+    """Tests coercion when the line does not intersect and is in quadrant 2."""
+    box = self.MakeBox(1, 2, 1, 2)
+
+    # x1 = -x2
+    K = numpy.matrix([[1, 1]])
+    w = 0
+
+    assert_array_equal(polydrivetrain.CoerceGoal(box, K, w, numpy.matrix([[5], [5]])),
+                       numpy.matrix([[1.0], [1.0]]))
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/y2015/control_loops/python/shooter.py b/y2015/control_loops/python/shooter.py
new file mode 100755
index 0000000..69f2599
--- /dev/null
+++ b/y2015/control_loops/python/shooter.py
@@ -0,0 +1,254 @@
+#!/usr/bin/python
+
+import control_loop
+import numpy
+import sys
+from matplotlib import pylab
+
+class SprungShooter(control_loop.ControlLoop):
+  def __init__(self, name="RawSprungShooter"):
+    super(SprungShooter, self).__init__(name)
+    # Stall Torque in N m
+    self.stall_torque = .4982
+    # Stall Current in Amps
+    self.stall_current = 85
+    # Free Speed in RPM
+    self.free_speed = 19300.0
+    # Free Current in Amps
+    self.free_current = 1.2
+    # Effective mass of the shooter in kg.
+    # This rough estimate should about include the effect of the masses
+    # of the gears. If this number is too low, the eigen values of self.A
+    # will start to become extremely small.
+    self.J = 200
+    # Resistance of the motor, divided by the number of motors.
+    self.R = 12.0 / self.stall_current / 2.0
+    # Motor velocity constant
+    self.Kv = ((self.free_speed / 60.0 * 2.0 * numpy.pi) /
+               (12.0 - self.R * self.free_current))
+    # Torque constant
+    self.Kt = self.stall_torque / self.stall_current
+    # Spring constant for the springs, N/m
+    self.Ks = 2800.0
+    # Maximum extension distance (Distance from the 0 force point on the
+    # spring to the latch position.)
+    self.max_extension = 0.32385
+    # Gear ratio multiplied by radius of final sprocket.
+    self.G = 10.0 / 40.0 * 20.0 / 54.0 * 24.0 / 54.0 * 20.0 / 84.0 * 16.0 * (3.0 / 8.0) / (2.0 * numpy.pi) * 0.0254
+
+    # Control loop time step
+    self.dt = 0.01
+
+    # State feedback matrices
+    self.A_continuous = numpy.matrix(
+        [[0, 1],
+         [-self.Ks / self.J,
+          -self.Kt / self.Kv / (self.J * self.G * self.G * self.R)]])
+    self.B_continuous = numpy.matrix(
+        [[0],
+         [self.Kt / (self.J * self.G * self.R)]])
+    self.C = numpy.matrix([[1, 0]])
+    self.D = numpy.matrix([[0]])
+
+    self.A, self.B = self.ContinuousToDiscrete(
+        self.A_continuous, self.B_continuous, self.dt)
+
+    self.PlaceControllerPoles([0.45, 0.45])
+
+    self.rpl = .05
+    self.ipl = 0.008
+    self.PlaceObserverPoles([self.rpl,
+                             self.rpl])
+
+    self.U_max = numpy.matrix([[12.0]])
+    self.U_min = numpy.matrix([[-12.0]])
+
+    self.InitializeState()
+
+
+class Shooter(SprungShooter):
+  def __init__(self, name="RawShooter"):
+    super(Shooter, self).__init__(name)
+
+    # State feedback matrices
+    self.A_continuous = numpy.matrix(
+        [[0, 1],
+         [0, -self.Kt / self.Kv / (self.J * self.G * self.G * self.R)]])
+    self.B_continuous = numpy.matrix(
+        [[0],
+         [self.Kt / (self.J * self.G * self.R)]])
+
+    self.A, self.B = self.ContinuousToDiscrete(
+        self.A_continuous, self.B_continuous, self.dt)
+
+    self.PlaceControllerPoles([0.45, 0.45])
+
+    self.rpl = .05
+    self.ipl = 0.008
+    self.PlaceObserverPoles([self.rpl,
+                             self.rpl])
+
+    self.U_max = numpy.matrix([[12.0]])
+    self.U_min = numpy.matrix([[-12.0]])
+
+    self.InitializeState()
+
+
+class SprungShooterDeltaU(SprungShooter):
+  def __init__(self, name="SprungShooter"):
+    super(SprungShooterDeltaU, self).__init__(name)
+    A_unaugmented = self.A
+    B_unaugmented = self.B
+
+    self.A = numpy.matrix([[0.0, 0.0, 0.0],
+                           [0.0, 0.0, 0.0],
+                           [0.0, 0.0, 1.0]])
+    self.A[0:2, 0:2] = A_unaugmented
+    self.A[0:2, 2] = B_unaugmented
+
+    self.B = numpy.matrix([[0.0],
+                           [0.0],
+                           [1.0]])
+
+    self.C = numpy.matrix([[1.0, 0.0, 0.0]])
+    self.D = numpy.matrix([[0.0]])
+
+    self.PlaceControllerPoles([0.50, 0.35, 0.80])
+
+    print "K"
+    print self.K
+    print "Placed controller poles are"
+    print numpy.linalg.eig(self.A - self.B * self.K)[0]
+
+    self.rpl = .05
+    self.ipl = 0.008
+    self.PlaceObserverPoles([self.rpl + 1j * self.ipl,
+                             self.rpl - 1j * self.ipl, 0.90])
+    print "Placed observer poles are"
+    print numpy.linalg.eig(self.A - self.L * self.C)[0]
+
+    self.U_max = numpy.matrix([[12.0]])
+    self.U_min = numpy.matrix([[-12.0]])
+
+    self.InitializeState()
+
+
+class ShooterDeltaU(Shooter):
+  def __init__(self, name="Shooter"):
+    super(ShooterDeltaU, self).__init__(name)
+    A_unaugmented = self.A
+    B_unaugmented = self.B
+
+    self.A = numpy.matrix([[0.0, 0.0, 0.0],
+                           [0.0, 0.0, 0.0],
+                           [0.0, 0.0, 1.0]])
+    self.A[0:2, 0:2] = A_unaugmented
+    self.A[0:2, 2] = B_unaugmented
+
+    self.B = numpy.matrix([[0.0],
+                           [0.0],
+                           [1.0]])
+
+    self.C = numpy.matrix([[1.0, 0.0, 0.0]])
+    self.D = numpy.matrix([[0.0]])
+
+    self.PlaceControllerPoles([0.55, 0.45, 0.80])
+
+    print "K"
+    print self.K
+    print "Placed controller poles are"
+    print numpy.linalg.eig(self.A - self.B * self.K)[0]
+
+    self.rpl = .05
+    self.ipl = 0.008
+    self.PlaceObserverPoles([self.rpl + 1j * self.ipl,
+                             self.rpl - 1j * self.ipl, 0.90])
+    print "Placed observer poles are"
+    print numpy.linalg.eig(self.A - self.L * self.C)[0]
+
+    self.U_max = numpy.matrix([[12.0]])
+    self.U_min = numpy.matrix([[-12.0]])
+
+    self.InitializeState()
+
+
+def ClipDeltaU(shooter, old_voltage, delta_u):
+  old_u = old_voltage
+  new_u = numpy.clip(old_u + delta_u, shooter.U_min, shooter.U_max)
+  return new_u - old_u
+
+def main(argv):
+  # Simulate the response of the system to a goal.
+  sprung_shooter = SprungShooterDeltaU()
+  raw_sprung_shooter = SprungShooter()
+  close_loop_x = []
+  close_loop_u = []
+  goal_position = -0.3
+  R = numpy.matrix([[goal_position], [0.0], [-sprung_shooter.A[1, 0] / sprung_shooter.A[1, 2] * goal_position]])
+  voltage = numpy.matrix([[0.0]])
+  for _ in xrange(500):
+    U = sprung_shooter.K * (R - sprung_shooter.X_hat)
+    U = ClipDeltaU(sprung_shooter, voltage, U)
+    sprung_shooter.Y = raw_sprung_shooter.Y + 0.01
+    sprung_shooter.UpdateObserver(U)
+    voltage += U;
+    raw_sprung_shooter.Update(voltage)
+    close_loop_x.append(raw_sprung_shooter.X[0, 0] * 10)
+    close_loop_u.append(voltage[0, 0])
+
+  pylab.plot(range(500), close_loop_x)
+  pylab.plot(range(500), close_loop_u)
+  pylab.show()
+
+  shooter = ShooterDeltaU()
+  raw_shooter = Shooter()
+  close_loop_x = []
+  close_loop_u = []
+  goal_position = -0.3
+  R = numpy.matrix([[goal_position], [0.0], [-shooter.A[1, 0] / shooter.A[1, 2] * goal_position]])
+  voltage = numpy.matrix([[0.0]])
+  for _ in xrange(500):
+    U = shooter.K * (R - shooter.X_hat)
+    U = ClipDeltaU(shooter, voltage, U)
+    shooter.Y = raw_shooter.Y + 0.01
+    shooter.UpdateObserver(U)
+    voltage += U;
+    raw_shooter.Update(voltage)
+    close_loop_x.append(raw_shooter.X[0, 0] * 10)
+    close_loop_u.append(voltage[0, 0])
+
+  pylab.plot(range(500), close_loop_x)
+  pylab.plot(range(500), close_loop_u)
+  pylab.show()
+
+  # Write the generated constants out to a file.
+  if len(argv) != 5:
+    print "Expected .h file name and .cc file name for"
+    print "both the plant and unaugmented plant"
+  else:
+    unaug_sprung_shooter = SprungShooter("RawSprungShooter")
+    unaug_shooter = Shooter("RawShooter")
+    unaug_loop_writer = control_loop.ControlLoopWriter("RawShooter",
+                                                       [unaug_sprung_shooter,
+                                                        unaug_shooter])
+    if argv[3][-3:] == '.cc':
+      unaug_loop_writer.Write(argv[4], argv[3])
+    else:
+      unaug_loop_writer.Write(argv[3], argv[4])
+
+    sprung_shooter = SprungShooterDeltaU()
+    shooter = ShooterDeltaU()
+    loop_writer = control_loop.ControlLoopWriter("Shooter", [sprung_shooter,
+                                                             shooter])
+
+    loop_writer.AddConstant(control_loop.Constant("kMaxExtension", "%f",
+                                                  sprung_shooter.max_extension))
+    loop_writer.AddConstant(control_loop.Constant("kSpringConstant", "%f",
+                                                  sprung_shooter.Ks))
+    if argv[1][-3:] == '.cc':
+      loop_writer.Write(argv[2], argv[1])
+    else:
+      loop_writer.Write(argv[1], argv[2])
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))
diff --git a/y2015/control_loops/update_arm.sh b/y2015/control_loops/update_arm.sh
new file mode 100755
index 0000000..2a10f93
--- /dev/null
+++ b/y2015/control_loops/update_arm.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+#
+# Updates the arm controllers (for both robots).
+
+cd $(dirname $0)
+
+export PYTHONPATH=../../frc971/control_loops/python
+
+./python/arm.py fridge/arm_motor_plant.cc \
+    fridge/arm_motor_plant.h \
+    fridge/integral_arm_plant.cc \
+    fridge/integral_arm_plant.h
diff --git a/y2015/control_loops/update_claw.sh b/y2015/control_loops/update_claw.sh
new file mode 100755
index 0000000..d37e737
--- /dev/null
+++ b/y2015/control_loops/update_claw.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+#
+# Updates the claw controllers (for both robots).
+
+cd $(dirname $0)
+
+export PYTHONPATH=../../frc971/control_loops/python
+
+./python/claw.py claw/claw_motor_plant.cc \
+    claw/claw_motor_plant.h
diff --git a/y2015/control_loops/update_drivetrain.sh b/y2015/control_loops/update_drivetrain.sh
new file mode 100755
index 0000000..ecd1c41
--- /dev/null
+++ b/y2015/control_loops/update_drivetrain.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+#
+# Updates the drivetrain controllers (for both robots).
+
+cd $(dirname $0)
+
+export PYTHONPATH=../../frc971/control_loops/python
+
+./python/drivetrain.py drivetrain/drivetrain_dog_motor_plant.h \
+    drivetrain/drivetrain_dog_motor_plant.cc \
+    drivetrain/drivetrain_clutch_motor_plant.h \
+    drivetrain/drivetrain_clutch_motor_plant.cc
diff --git a/y2015/control_loops/update_elevator.sh b/y2015/control_loops/update_elevator.sh
new file mode 100755
index 0000000..4a7edb4
--- /dev/null
+++ b/y2015/control_loops/update_elevator.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+#
+# Updates the elevator controllers (for both robots).
+
+cd $(dirname $0)
+
+export PYTHONPATH=../../frc971/control_loops/python
+
+./python/elevator.py fridge/elevator_motor_plant.cc \
+    fridge/elevator_motor_plant.h
diff --git a/y2015/control_loops/update_polydrivetrain.sh b/y2015/control_loops/update_polydrivetrain.sh
new file mode 100755
index 0000000..338e40e
--- /dev/null
+++ b/y2015/control_loops/update_polydrivetrain.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+#
+# Updates the polydrivetrain controllers (for both robots) and CIM models.
+
+cd $(dirname $0)
+
+export PYTHONPATH=../../frc971/control_loops/python
+
+./python/polydrivetrain.py drivetrain/polydrivetrain_dog_motor_plant.h \
+    drivetrain/polydrivetrain_dog_motor_plant.cc \
+    drivetrain/polydrivetrain_clutch_motor_plant.h \
+    drivetrain/polydrivetrain_clutch_motor_plant.cc \
+    drivetrain/polydrivetrain_cim_plant.h \
+    drivetrain/polydrivetrain_cim_plant.cc
diff --git a/y2015/http_status/http_status.cc b/y2015/http_status/http_status.cc
new file mode 100644
index 0000000..9c64314
--- /dev/null
+++ b/y2015/http_status/http_status.cc
@@ -0,0 +1,296 @@
+#include "y2015/http_status/http_status.h"
+
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <thread>
+#include <vector>
+
+#include "seasocks/Server.h"
+
+#include "aos/linux_code/init.h"
+#include "aos/common/logging/logging.h"
+#include "aos/common/time.h"
+#include "aos/common/util/phased_loop.h"
+#include "aos/common/mutex.h"
+
+#include "y2015/control_loops/claw/claw.q.h"
+#include "y2015/control_loops/fridge/fridge.q.h"
+
+#include "y2015/http_status/embedded.h"
+
+namespace frc971 {
+namespace http_status {
+
+// TODO(comran): Make some of these separate libraries & document them better.
+
+HTTPStatusMessage::HTTPStatusMessage()
+    : sample_id_(0),
+      measure_index_(0),
+      overflow_id_(200),
+      num_samples_per_packet_(50) {}
+
+void HTTPStatusMessage::NextSample() {
+  int32_t adjusted_index = GetIndex(sample_id_);
+
+  ::aos::time::Time time_now = ::aos::time::Time::Now();
+
+  if (sample_id_ < overflow_id_) {
+    sample_times_.emplace_back(time_now);
+    data_values_.emplace_back(::std::vector<double>());
+  } else {
+    sample_times_[adjusted_index] = time_now;
+  }
+
+  sample_id_++;
+  measure_index_ = 0;
+
+  CHECK(!mutex_.Lock());  // Lock the mutex so measures can be added.
+}
+
+void HTTPStatusMessage::EndSample() { mutex_.Unlock(); }
+
+int32_t HTTPStatusMessage::GetIndex(int32_t sample_id) {
+  return sample_id % overflow_id_;
+}
+
+void HTTPStatusMessage::AddMeasure(::std::string name, double value) {
+  // Mutex should be locked when this method is called to synchronize packets.
+  assert(mutex_.OwnedBySelf());
+
+  int32_t index = GetIndex(sample_id_ - 1);
+
+  if (measure_index_ >= static_cast<int32_t>(data_names_.size())) {
+    data_names_.emplace_back(name);
+  }
+
+  if (measure_index_ >= static_cast<int32_t>(data_values_.at(index).size())) {
+    data_values_.at(index).emplace_back(value);
+  } else {
+    data_values_.at(index).at(measure_index_) = value;
+  }
+  measure_index_++;
+}
+
+::std::string HTTPStatusMessage::Fetch(size_t from_sample) {
+  ::aos::MutexLocker locker(&mutex_);
+
+  ::std::stringstream message;
+  message.precision(10);  // Cap how precise the time/measurement data is.
+
+  // To save space, data is being sent with a custom protocol over to the
+  // client.
+  // Initially, a message containing all the names of the measurements is sent
+  // and is preceeded with a *.
+  // Names begin with a star and are split with commas.
+
+  // Example: *test,test2
+  if (static_cast<int32_t>(from_sample) == -1) {
+    message << "*";
+    for (int32_t cur_data_name = 0;
+         cur_data_name < static_cast<int32_t>(data_names_.size());
+         cur_data_name++) {
+      if (cur_data_name > 0) {
+        message << ",";
+      }
+      message << data_names_.at(cur_data_name);
+    }
+    return message.str();
+  }
+
+  // TODO(comran): Use from_sample to determine the speed packets should be sent
+  // out to avoid skipping packets.
+  from_sample = sample_id_ - num_samples_per_packet_;
+
+  // Data packets are sent, with raw data being placed at the same index as the
+  // original index of the measurement name sent in the initial packet.
+  // Samples are split with dollar signs, info with percent signs, and
+  // measurements with commas.
+  // This special format system is helpful for debugging issues and looping
+  // through the data on the client side.
+
+  // Example of two samples that correspond with the initialized example:
+  // 289%2803.135127%10,67$290%2803.140109%12,68
+  for (int32_t cur_sample = from_sample;
+       cur_sample <
+               static_cast<int32_t>(from_sample + num_samples_per_packet_) &&
+           GetIndex(cur_sample) < static_cast<int32_t>(data_values_.size());
+       cur_sample++) {
+    if (cur_sample != static_cast<int32_t>(from_sample)) {
+      message << "$";
+    }
+
+    int32_t adjusted_index = GetIndex(cur_sample);
+
+    message << cur_sample << "%" << sample_times_.at(adjusted_index).ToSeconds()
+            << "%";
+    for (int32_t cur_measure = 0;
+         cur_measure < static_cast<int32_t>(data_names_.size());
+         cur_measure++) {
+      if (cur_measure > 0) {
+        message << ",";
+      }
+      message << data_values_.at(adjusted_index).at(cur_measure);
+    }
+  }
+  return message.str();
+}
+
+DataCollector::DataCollector() : cur_raw_data_("no data") {}
+
+void DataCollector::RunIteration() {
+  auto& fridge_queue = control_loops::fridge_queue;
+  auto& claw_queue = control_loops::claw_queue;
+
+  fridge_queue.status.FetchAnother();
+  claw_queue.status.FetchAnother();
+
+  message_.NextSample();
+  // Add recorded data here. /////
+  // NOTE: Try to use fewer than 30 measures, or the whole thing will lag.
+  // Abbreviate names if long, otherwise just use the command to get the value
+  // from the queue.
+
+  // TODO(comran): Make it so that the name doesn't have to be copied as a
+  // string.
+
+  // //// Fridge
+  // Positions
+  message_.AddMeasure("(fridge position left arm encoder)",
+                      fridge_queue.position->arm.left.encoder);
+  message_.AddMeasure("(fridge position right arm encoder)",
+                      fridge_queue.position->arm.right.encoder);
+  message_.AddMeasure("(fridge position left elev encoder)",
+                      fridge_queue.position->elevator.left.encoder);
+  message_.AddMeasure("(fridge position right elev encoder)",
+                      fridge_queue.position->elevator.right.encoder);
+  // Goals
+  message_.AddMeasure("fridge_queue.goal->profiling_type",
+                      fridge_queue.goal->profiling_type);
+  message_.AddMeasure("fridge_queue.goal->angle", fridge_queue.goal->angle);
+  message_.AddMeasure("fridge_queue.goal->angular_velocity",
+                      fridge_queue.goal->angular_velocity);
+  message_.AddMeasure("fridge_queue.goal->height", fridge_queue.goal->height);
+  message_.AddMeasure("fridge_queue.goal->velocity",
+                      fridge_queue.goal->velocity);
+  message_.AddMeasure("fridge_queue.x", fridge_queue.goal->x);
+  message_.AddMeasure("fridge_queue.x_velocity", fridge_queue.goal->x_velocity);
+  message_.AddMeasure("fridge_queue.y", fridge_queue.goal->y);
+  message_.AddMeasure("fridge_queue.y_velocity", fridge_queue.goal->y_velocity);
+  // Statuses
+  message_.AddMeasure("fridge_queue.status->height",
+                      fridge_queue.status->height);
+  message_.AddMeasure("fridge_queue.status->velocity",
+                      fridge_queue.status->velocity);
+  message_.AddMeasure("fridge_queue.status->angle", fridge_queue.status->angle);
+  message_.AddMeasure("fridge_queue.status->angular_velocity",
+                      fridge_queue.status->angular_velocity);
+  message_.AddMeasure("fridge_queue.status->x", fridge_queue.status->x);
+  message_.AddMeasure("fridge_queue.status->x_velocity",
+                      fridge_queue.status->x_velocity);
+  message_.AddMeasure("fridge_queue.status->y", fridge_queue.status->y);
+  message_.AddMeasure("fridge_queue.status->y_velocity",
+                      fridge_queue.status->y_velocity);
+  message_.AddMeasure("fridge_queue.status->state", fridge_queue.status->state);
+  message_.AddMeasure("fridge_queue.status->zeroed",
+                      fridge_queue.status->zeroed);
+  message_.AddMeasure("fridge_queue.status->estopped",
+                      fridge_queue.status->estopped);
+  // Outputs
+  message_.AddMeasure("fridge_queue.output->left_arm",
+                      fridge_queue.output->left_arm);
+  message_.AddMeasure("fridge_queue.output->right_arm",
+                      fridge_queue.output->right_arm);
+  message_.AddMeasure("fridge_queue.output->left_elevator",
+                      fridge_queue.output->left_elevator);
+  message_.AddMeasure("fridge_queue.output->right_elevator",
+                      fridge_queue.output->right_elevator);
+  // End recorded data. /////
+  message_.EndSample();
+}
+
+::std::string DataCollector::GetData(int32_t from_sample) {
+  return message_.Fetch(from_sample);
+}
+
+void DataCollector::operator()() {
+  ::aos::SetCurrentThreadName("HTTPStatusData");
+
+  while (run_) {
+    ::aos::time::PhasedLoopXMS(5, 0);
+    RunIteration();
+  }
+}
+
+SocketHandler::SocketHandler()
+    : data_collector_thread_(::std::ref(data_collector_)) {}
+
+void SocketHandler::onConnect(seasocks::WebSocket* connection) {
+  connections_.insert(connection);
+  LOG(INFO, "Connected: %s : %s\n", connection->getRequestUri().c_str(),
+      seasocks::formatAddress(connection->getRemoteAddress()).c_str());
+}
+
+void SocketHandler::onData(seasocks::WebSocket* connection, const char* data) {
+  int32_t from_sample = atoi(data);
+
+  ::std::string send_data = data_collector_.GetData(from_sample);
+  connection->send(send_data.c_str());
+}
+
+void SocketHandler::onDisconnect(seasocks::WebSocket* connection) {
+  connections_.erase(connection);
+  LOG(INFO, "Disconnected: %s : %s\n", connection->getRequestUri().c_str(),
+      seasocks::formatAddress(connection->getRemoteAddress()).c_str());
+}
+
+void SocketHandler::Quit() {
+  data_collector_.Quit();
+  data_collector_thread_.join();
+}
+
+SeasocksLogger::SeasocksLogger(Level min_level_to_log)
+    : PrintfLogger(min_level_to_log) {}
+
+void SeasocksLogger::log(Level level, const char* message) {
+  log_level aos_level;
+  switch (level) {
+    case seasocks::Logger::INFO:
+      aos_level = INFO;
+      break;
+    case seasocks::Logger::WARNING:
+      aos_level = WARNING;
+      break;
+    case seasocks::Logger::ERROR:
+    case seasocks::Logger::SEVERE:
+      aos_level = ERROR;
+      break;
+    case seasocks::Logger::DEBUG:
+    case seasocks::Logger::ACCESS:
+    default:
+      aos_level = DEBUG;
+      break;
+  }
+  LOG(aos_level, "Seasocks: %s\n", message);
+}
+
+}  // namespace http_status
+}  // namespace frc971
+
+int main(int, char* []) {
+  ::aos::InitNRT();
+
+  seasocks::Server server(::std::shared_ptr<seasocks::Logger>(
+      new frc971::http_status::SeasocksLogger(seasocks::Logger::INFO)));
+  frc971::http_status::SocketHandler socket_handler;
+
+  server.addWebSocketHandler(
+      "/ws",
+      ::std::shared_ptr<frc971::http_status::SocketHandler>(&socket_handler));
+  server.serve("www", 8080);
+
+  socket_handler.Quit();
+
+  ::aos::Cleanup();
+  return 0;
+}
diff --git a/y2015/http_status/http_status.gyp b/y2015/http_status/http_status.gyp
new file mode 100644
index 0000000..c78a1fc
--- /dev/null
+++ b/y2015/http_status/http_status.gyp
@@ -0,0 +1,46 @@
+{
+  'targets': [
+    {
+      'target_name': 'http_status',
+      'type': 'executable',
+      'sources': [
+        'http_status.cc',
+      ],
+      'actions': [
+        {
+          'action_name': 'http_status_gen_embedded',
+          'inputs': [
+            '<!@(find ./www_defaults)',
+            '<(AOS)/externals/seasocks/gen_embedded.py',
+          ],
+          'outputs': [
+            '<(SHARED_INTERMEDIATE_DIR)/http_status/y2015/http_status/embedded.h',
+          ],
+          'action': [
+            'python', '<(AOS)/externals/seasocks/gen_embedded.py', '<(_outputs)',
+          ],
+        },
+      ],
+      'include_dirs': [
+        '<(SHARED_INTERMEDIATE_DIR)/http_status/'
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(EXTERNALS):seasocks',
+        '<(DEPTH)/y2015/control_loops/claw/claw.gyp:claw_queue',
+        '<(DEPTH)/y2015/control_loops/fridge/fridge.gyp:fridge_queue',
+        '<(AOS)/common/util/util.gyp:phased_loop',
+        '<(AOS)/common/common.gyp:time',
+      ],
+      'copies': [
+        {
+          'destination': '<(rsync_dir)',
+          'files': [
+            'www',
+          ],
+        },
+      ],
+    },
+  ],
+}
diff --git a/y2015/http_status/http_status.h b/y2015/http_status/http_status.h
new file mode 100644
index 0000000..2f7497d
--- /dev/null
+++ b/y2015/http_status/http_status.h
@@ -0,0 +1,106 @@
+#include <iostream>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <thread>
+#include <atomic>
+#include <vector>
+
+#include "seasocks/PageHandler.h"
+#include "seasocks/PrintfLogger.h"
+#include "seasocks/StringUtil.h"
+#include "seasocks/WebSocket.h"
+
+#include "aos/linux_code/init.h"
+#include "aos/common/time.h"
+#include "aos/common/util/phased_loop.h"
+#include "aos/common/mutex.h"
+
+namespace frc971 {
+namespace http_status {
+
+// A class for storing data from DataCollector and packaging it as a custom
+// message for the websocket.
+// Samples are stored in a vector that wraps around at a certain point to avoid
+// clogging up memory. These samples should be already on all clients before
+// they are overwritten. To avoid losing samples, there must be a balance
+// between the rate samples are being recorded at and the speed of the link
+// between the robot and client.
+
+class HTTPStatusMessage {
+ public:
+  HTTPStatusMessage();
+
+  // Stores an individual measurement in the current sample.
+  void AddMeasure(::std::string name, double value);
+
+  // Starts a new sample that contains measurements for all the states at a
+  // timestep, and lock mutex to synchronize measures.
+  void NextSample();
+
+  // Unlock mutex.
+  void EndSample();
+
+  // Method called by the websocket to get a JSON-packaged string containing,
+  // at most, a constant number of samples, starting at "from_sample".
+  // "from_sample" is a specific index for a sample that is not wrapped.
+  ::std::string Fetch(size_t from_sample);
+
+ private:
+  // Returns the vector index of the sample given.
+  // Since the vectors wrap, multiple sample_ids may refer to the same vector
+  // index.
+  int32_t GetIndex(int32_t sample_id);
+
+  // Vectors of vectors to store samples at indexes determined by GetIndex.
+  ::std::vector<::std::string> data_names_;
+  ::std::vector<::std::vector<double>> data_values_;
+  ::std::vector<::aos::time::Time> sample_times_;
+
+  int32_t sample_id_;          // Last sample id used.
+  int32_t measure_index_;      // Last measure index used.
+  const int32_t overflow_id_;  // Vector wrapping size.
+  // Number of samples to include in each JSON packet.
+  const int32_t num_samples_per_packet_;
+
+  // Mutex used to synchronize data.
+  ::aos::Mutex mutex_;
+};
+
+class DataCollector {
+ public:
+  DataCollector();
+  void RunIteration();
+  ::std::string GetData(int32_t from);
+
+  void operator()();  // Will be called by ::std::thread internally.
+  void Quit() { run_ = false; }
+
+ private:
+  ::std::string cur_raw_data_;
+  HTTPStatusMessage message_;
+  ::std::atomic<bool> run_{true};
+};
+
+class SocketHandler : public seasocks::WebSocket::Handler {
+ public:
+  SocketHandler();
+  void onConnect(seasocks::WebSocket* connection) override;
+  void onData(seasocks::WebSocket* connection, const char* data) override;
+  void onDisconnect(seasocks::WebSocket* connection) override;
+  void Quit();
+
+ private:
+  ::std::set<seasocks::WebSocket*> connections_;
+  DataCollector data_collector_;
+  ::std::thread data_collector_thread_;
+};
+
+class SeasocksLogger : public seasocks::PrintfLogger {
+ public:
+  SeasocksLogger(Level min_level_to_log);
+  void log(Level level, const char* message) override;
+};
+
+}  // namespace http_status
+}  // namespace frc971
diff --git a/y2015/http_status/www/index.html b/y2015/http_status/www/index.html
new file mode 100644
index 0000000..0fe83b4
--- /dev/null
+++ b/y2015/http_status/www/index.html
@@ -0,0 +1,160 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+<title>Hello, world</title>
+<script type="text/javascript">
+var escapable =
+  /[\x00-\x1f\ud800-\udfff\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufff0-\uffff]/g;
+var ws;
+var intervalTime = 50;
+var safetyTimeout;
+var safetyIntervalTime = 10;
+var selected = 0;
+
+// Filter out junky JSON packets that will otherwise cause nasty decoding errors.
+function filterUnicode(quoted) {
+  escapable.lastIndex = 0;
+  if (!escapable.test(quoted)) return quoted;
+
+  return quoted.replace(escapable, function(a) {
+    return '';
+  });
+}
+
+// Change the current data index to plot on the graph.
+function changeSelected(select) {
+  selected = select;
+  document.getElementById("selected").innerHTML = "Selected: " + selected;
+}
+
+// Get a new JSON packet from the websocket on the robot.
+function refresh() {
+  ws.send(lastSampleID);
+  safetyTimeout = setTimeout(safetyRefresh, safetyIntervalTime);
+}
+
+function safetyRefresh(){
+  console.log("Safety timeout exceeded. Performing additional refresh...");
+  refresh();
+}
+
+window.onload = function() {
+  var dps = [];
+  var numDatas = 0;
+  var chart = new CanvasJS.Chart("chartContainer", {
+    title: {
+      text: "Live Data"
+    },
+    axisX: {
+      title: "Time (sec)"
+    },
+    axisY: {
+      title: "Units"
+    },
+    zoomEnabled: true,
+    panEnabled: true,
+    data: [{
+      color: 'rgba(119, 152, 191, 1.0)',
+      type: "scatter",
+      dataPoints: dps
+    }],
+  });
+
+  chart.render();
+
+  $(function() {
+    ws = new WebSocket('ws://' + document.location.host + '/ws');
+    run = true;
+    xVal = 1;
+    lastSampleID = -1;
+
+    // Socket created & first opened.
+    ws.onopen = function() {
+      run = true;
+      refresh();
+    };
+
+    // Socket disconnected.
+    ws.onclose = function() {
+      console.log('onclose');
+      run = false;
+      $('#message').text('Lost connection.');
+    };
+
+    // Received message over the socket, so parse and chart it.
+    ws.onmessage = function(message) {
+      console.log(message);
+      clearTimeout(safetyTimeout);
+      message = message.data;
+      //$('#data').html(message);
+      if(message.charAt(0) == "*"){
+        message = message.substring(1);
+        var names = message.split(",");
+        for (var i = numDatas; i < names.length; i++) {
+          $('#dataTable').append('<tr onClick="changeSelected(' + i +
+            ')"><td>' + names[i] + '</td><td></td></tr>');
+          numDatas++;
+        }
+        lastSampleID = 0;
+      }else{
+        var samples = message.split("$");
+        for(var x = 0;x < samples.length;x++){
+          var info = samples[x].split("%");
+          lastSampleID = info[0];
+
+          if(!(typeof info[2] === "undefined")){
+            var values = info[2].split(",");
+            for(var y = 0;y < values.length;y++){
+              if(!(typeof info[1] === "undefined"
+                    || typeof values[y] === "undefined")){
+                $('#dataTable').find('tr').eq(y).find('td').eq(1)
+                  .text(values[y]);
+                if(y == selected){
+                  dps.push({
+                    x: parseFloat(info[1]),
+                    y: parseFloat(values[y])
+                    });
+                  if(dps.length > 10000){
+                    dps.shift();
+                  }
+                }
+              }
+            }
+          }
+        }
+
+        chart.render();
+      }
+
+      if(run){
+        setTimeout(refresh, intervalTime);
+      }
+    };
+
+    // Socket error, most likely due to a server-side error.
+    ws.onerror = function(error) {
+      console.log('onerror ' + error);
+      run = false;
+    };
+  });
+}
+</script>
+<script type="text/javascript" src='/lib/jquery-1.4.4.js'></script>
+<script type="text/javascript" src='/lib/canvasjs.min.js'></script>
+<script type="text/javascript" src='/lib/reconnecting-websocket.min.js'></script>
+</head>
+<body>
+<div style="width: 1200px;margin-left: auto;margin-right:auto">
+  <table id="dataTable" style="width: 200px;cell-spacing:0;cell-padding:0;
+    text-align:left">
+  </table>
+  <div id="chartContainer" style="height:600px; width:100%;"></div>
+  <div style="width: 1000px;float: right">
+    <p id="message" style="color: #FF0000"></p>
+    <p id="selected">Selected: 0</p>
+    <p id="data"></p>
+  </div>
+</div>
+</body>
+</html>
diff --git a/y2015/http_status/www/lib/canvasjs.min.js b/y2015/http_status/www/lib/canvasjs.min.js
new file mode 100644
index 0000000..67fc83b
--- /dev/null
+++ b/y2015/http_status/www/lib/canvasjs.min.js
@@ -0,0 +1,429 @@
+/*
+ CanvasJS HTML5 & JavaScript Charts - v1.6.1 GA- http://canvasjs.com/ 
+ Copyright 2013 fenopix
+*/
+(function(){function O(a,b){a.prototype=Aa(b.prototype);a.prototype.constructor=a;a.parent=b.prototype}function Aa(a){function b(){}b.prototype=a;return new b}function qa(a,b,c){"millisecond"===c?a.setMilliseconds(a.getMilliseconds()+1*b):"second"===c?a.setSeconds(a.getSeconds()+1*b):"minute"===c?a.setMinutes(a.getMinutes()+1*b):"hour"===c?a.setHours(a.getHours()+1*b):"day"===c?a.setDate(a.getDate()+1*b):"week"===c?a.setDate(a.getDate()+7*b):"month"===c?a.setMonth(a.getMonth()+1*b):"year"===c&&a.setFullYear(a.getFullYear()+
+1*b);return a}function Y(a,b){return z[b+"Duration"]*a}function K(a,b){var c=!1;0>a&&(c=!0,a*=-1);a=""+a;for(b=b?b:1;a.length<b;)a="0"+a;return c?"-"+a:a}function Z(a){if(!a)return a;a=a.replace(/^\s\s*/,"");for(var b=/\s/,c=a.length;b.test(a.charAt(--c)););return a.slice(0,c+1)}function Ba(a){a.roundRect=function(a,c,d,e,f,g,k,p){k&&(this.fillStyle=k);p&&(this.strokeStyle=p);"undefined"===typeof f&&(f=5);this.lineWidth=g;this.beginPath();this.moveTo(a+f,c);this.lineTo(a+d-f,c);this.quadraticCurveTo(a+
+d,c,a+d,c+f);this.lineTo(a+d,c+e-f);this.quadraticCurveTo(a+d,c+e,a+d-f,c+e);this.lineTo(a+f,c+e);this.quadraticCurveTo(a,c+e,a,c+e-f);this.lineTo(a,c+f);this.quadraticCurveTo(a,c,a+f,c);this.closePath();k&&this.fill();p&&0<g&&this.stroke()}}function ra(a,b){return a-b}function Ca(a,b){return a.x-b.x}function C(a){var b=((a&16711680)>>16).toString(16),c=((a&65280)>>8).toString(16);a=((a&255)>>0).toString(16);b=2>b.length?"0"+b:b;c=2>c.length?"0"+c:c;a=2>a.length?"0"+a:a;return"#"+b+c+a}function ca(a,
+b,c){c=c||"normal";var d=a+"_"+b+"_"+c,e=sa[d];if(isNaN(e)){try{a="position:absolute; left:0px; top:-20000px; padding:0px;margin:0px;border:none;white-space:pre;line-height:normal;font-family:"+a+"; font-size:"+b+"px; font-weight:"+c+";";if(!R){var f=document.body;R=document.createElement("span");R.innerHTML="";var g=document.createTextNode("Mpgyi");R.appendChild(g);f.appendChild(R)}R.style.display="";R.setAttribute("style",a);e=Math.round(R.offsetHeight);R.style.display="none"}catch(k){e=Math.ceil(1.1*
+b)}e=Math.max(e,b);sa[d]=e}return e}function E(a,b,c,d){if(a.addEventListener)a.addEventListener(b,c,d||!1);else if(a.attachEvent)a.attachEvent("on"+b,function(b){b=b||window.event;b.preventDefault=b.preventDefault||function(){b.returnValue=!1};b.stopPropagation=b.stopPropagation||function(){b.cancelBubble=!0};c.call(a,b)});else return!1}function ta(a,b,c){a*=H;b*=H;a=c.getImageData(a,b,2,2).data;b=!0;for(c=0;4>c;c++)if(a[c]!==a[c+4]|a[c]!==a[c+8]|a[c]!==a[c+12]){b=!1;break}return b?a[0]<<16|a[1]<<
+8|a[2]:0}function ua(a,b,c){var d;d=a?a+"FontStyle":"fontStyle";var e=a?a+"FontWeight":"fontWeight",f=a?a+"FontSize":"fontSize";a=a?a+"FontFamily":"fontFamily";d=""+(b[d]?b[d]+" ":c&&c[d]?c[d]+" ":"");d+=b[e]?b[e]+" ":c&&c[e]?c[e]+" ":"";d+=b[f]?b[f]+"px ":c&&c[f]?c[f]+"px ":"";b=b[a]?b[a]+"":c&&c[a]?c[a]+"":"";!t&&b&&(b=b.split(",")[0],"'"!==b[0]&&'"'!==b[0]&&(b="'"+b+"'"));return d+=b}function T(a,b,c){return a in b?b[a]:c[a]}function da(a,b,c){if(t&&va){var d=a.getContext("2d");ea=d.webkitBackingStorePixelRatio||
+d.mozBackingStorePixelRatio||d.msBackingStorePixelRatio||d.oBackingStorePixelRatio||d.backingStorePixelRatio||1;H=ja/ea;a.width=b*H;a.height=c*H;ja!==ea&&(a.style.width=b+"px",a.style.height=c+"px",d.scale(H,H))}else a.width=b,a.height=c}function U(a,b){var c=document.createElement("canvas");c.setAttribute("class","canvasjs-chart-canvas");da(c,a,b);t||"undefined"===typeof G_vmlCanvasManager||G_vmlCanvasManager.initElement(c);return c}function wa(a,b,c){if(a&&b&&c){c=c+"."+("jpeg"===b?"jpg":b);var d=
+"image/"+b;a=a.toDataURL(d);var e=!1,f=document.createElement("a");f.download=c;f.href=a;f.target="_blank";if("undefined"!==typeof Blob&&new Blob){for(var g=a.replace(/^data:[a-z/]*;base64,/,""),g=atob(g),k=new ArrayBuffer(g.length),p=new Uint8Array(k),h=0;h<g.length;h++)p[h]=g.charCodeAt(h);b=new Blob([k],{type:"image/"+b});try{window.navigator.msSaveBlob(b,c),e=!0}catch(l){f.dataset.downloadurl=[d,f.download,f.href].join(":"),f.href=window.URL.createObjectURL(b)}}if(!e)try{event=document.createEvent("MouseEvents"),
+event.initMouseEvent("click",!0,!1,window,0,0,0,0,0,!1,!1,!1,!1,0,null),f.dispatchEvent?f.dispatchEvent(event):f.fireEvent&&f.fireEvent("onclick")}catch(r){b=window.open(),b.document.write("<img src='"+a+"'></img><div>Please right click on the image and save it to your device</div>"),b.document.close()}}}function M(a,b,c){b.getAttribute("state")!==c&&(b.setAttribute("state",c),b.setAttribute("type","button"),b.style.position="relative",b.style.margin="0px 0px 0px 0px",b.style.padding="3px 4px 0px 4px",
+b.style.cssFloat="left",b.setAttribute("title",a._cultureInfo[c+"Text"]),b.innerHTML="<img style='height:16px;' src='"+Da[c].image+"' alt='"+a._cultureInfo[c+"Text"]+"' />")}function ka(){for(var a=null,b=0;b<arguments.length;b++)a=arguments[b],a.style&&(a.style.display="inline")}function S(){for(var a=null,b=0;b<arguments.length;b++)(a=arguments[b])&&a.style&&(a.style.display="none")}function L(a,b,c){this._defaultsKey=a;var d={};c&&(W[c]&&W[c][a])&&(d=W[c][a]);this._options=b?b:{};this.setOptions(this._options,
+d)}function v(a,b,c){this._publicChartReference=c;b=b||{};v.parent.constructor.call(this,"Chart",b,b.theme?b.theme:"theme1");var d=this;this._containerId=a;this._objectsInitialized=!1;this.overlaidCanvasCtx=this.ctx=null;this._indexLabels=[];this._panTimerId=0;this._lastTouchEventType="";this._lastTouchData=null;this.isAnimating=!1;this.renderCount=0;this.panEnabled=this.disableToolTip=this.animatedRender=!1;this._defaultCursor="default";this.plotArea={canvas:null,ctx:null,x1:0,y1:0,x2:0,y2:0,width:0,
+height:0};this._dataInRenderedOrder=[];(this._container="string"===typeof this._containerId?document.getElementById(this._containerId):this._containerId)?(this._container.innerHTML="",b=a=0,a=this._options.width?this.width:0<this._container.clientWidth?this._container.clientWidth:this.width,b=this._options.height?this.height:0<this._container.clientHeight?this._container.clientHeight:this.height,this.width=a,this.height=b,this._selectedColorSet="undefined"!==typeof V[this.colorSet]?V[this.colorSet]:
+V.colorSet1,this._canvasJSContainer=document.createElement("div"),this._canvasJSContainer.setAttribute("class","canvasjs-chart-container"),this._canvasJSContainer.style.position="relative",this._canvasJSContainer.style.textAlign="left",this._canvasJSContainer.style.cursor="auto",t||(this._canvasJSContainer.style.height="0px"),this._container.appendChild(this._canvasJSContainer),this.canvas=U(a,b),this.canvas.style.position="absolute",this.canvas.getContext&&(this._canvasJSContainer.appendChild(this.canvas),
+this.ctx=this.canvas.getContext("2d"),this.ctx.textBaseline="top",Ba(this.ctx),t?this.plotArea.ctx=this.ctx:(this.plotArea.canvas=U(a,b),this.plotArea.canvas.style.position="absolute",this.plotArea.canvas.setAttribute("class","plotAreaCanvas"),this._canvasJSContainer.appendChild(this.plotArea.canvas),this.plotArea.ctx=this.plotArea.canvas.getContext("2d")),this.overlaidCanvas=U(a,b),this.overlaidCanvas.style.position="absolute",this._canvasJSContainer.appendChild(this.overlaidCanvas),this.overlaidCanvasCtx=
+this.overlaidCanvas.getContext("2d"),this.overlaidCanvasCtx.textBaseline="top",this._eventManager=new $(this),E(window,"resize",function(){d._updateSize()&&d.render()}),this._toolBar=document.createElement("div"),this._toolBar.setAttribute("class","canvasjs-chart-toolbar"),this._toolBar.style.cssText="position: absolute; right: 2px; top: 0px;",this._canvasJSContainer.appendChild(this._toolBar),this.bounds={x1:0,y1:0,x2:this.width,y2:this.height},E(this.overlaidCanvas,"click",function(a){d._mouseEventHandler(a)}),
+E(this.overlaidCanvas,"mousemove",function(a){d._mouseEventHandler(a)}),E(this.overlaidCanvas,"mouseup",function(a){d._mouseEventHandler(a)}),E(this.overlaidCanvas,"mousedown",function(a){d._mouseEventHandler(a);S(d._dropdownMenu)}),E(this.overlaidCanvas,"mouseout",function(a){d._mouseEventHandler(a)}),E(this.overlaidCanvas,window.navigator.msPointerEnabled?"MSPointerDown":"touchstart",function(a){d._touchEventHandler(a)}),E(this.overlaidCanvas,window.navigator.msPointerEnabled?"MSPointerMove":"touchmove",
+function(a){d._touchEventHandler(a)}),E(this.overlaidCanvas,window.navigator.msPointerEnabled?"MSPointerUp":"touchend",function(a){d._touchEventHandler(a)}),E(this.overlaidCanvas,window.navigator.msPointerEnabled?"MSPointerCancel":"touchcancel",function(a){d._touchEventHandler(a)}),this._creditLink||(this._creditLink=document.createElement("a"),this._creditLink.setAttribute("class","canvasjs-chart-credit"),this._creditLink.setAttribute("style","outline:none;margin:0px;position:absolute;right:3px;top:"+
+(this.height-14)+"px;color:dimgrey;text-decoration:none;font-size:10px;font-family:Lucida Grande, Lucida Sans Unicode, Arial, sans-serif"),this._creditLink.setAttribute("tabIndex",-1),this._creditLink.setAttribute("target","_blank")),this._toolTip=new N(this,this._options.toolTip,this.theme),this.layoutManager=new aa(this),this.axisY2=this.axisY=this.axisX=this.data=null,this.sessionVariables={axisX:{internalMinimum:null,internalMaximum:null},axisY:{internalMinimum:null,internalMaximum:null},axisY2:{internalMinimum:null,
+internalMaximum:null}})):window.console&&window.console.log('CanvasJS Error: Chart Container with id "'+this._containerId+'" was not found')}function fa(a,b){for(var c=[],d=0;d<a.length;d++)if(0==d)c.push(a[0]);else{var e,f,g;g=d-1;e=0===g?0:g-1;f=g===a.length-1?g:g+1;c[c.length]={x:a[g].x+(a[f].x-a[e].x)/b/3,y:a[g].y+(a[f].y-a[e].y)/b/3};g=d;e=0===g?0:g-1;f=g===a.length-1?g:g+1;c[c.length]={x:a[g].x-(a[f].x-a[e].x)/b/3,y:a[g].y-(a[f].y-a[e].y)/b/3};c[c.length]=a[d]}return c}function aa(a){this._rightOccupied=
+this._leftOccupied=this._bottomOccupied=this._topOccupied=0;this.chart=a}function I(a,b){I.parent.constructor.call(this,"TextBlock",b);this.ctx=a;this._isDirty=!0;this._wrappedText=null;this._lineHeight=ca(this.fontFamily,this.fontSize,this.fontWeight)}function ba(a,b){ba.parent.constructor.call(this,"Title",b,a.theme);this.chart=a;this.canvas=a.canvas;this.ctx=this.chart.ctx;"undefined"===typeof this._options.fontSize&&(this.fontSize=this.chart.getAutoFontSize(this.fontSize));this.height=this.width=
+null;this.bounds={x1:null,y1:null,x2:null,y2:null}}function ga(a,b,c){ga.parent.constructor.call(this,"Legend",b,c);this.chart=a;this.canvas=a.canvas;this.ctx=this.chart.ctx;this.ghostCtx=this.chart._eventManager.ghostCtx;this.items=[];this.height=this.width=0;this.orientation=null;this.horizontalSpacing=10;this.dataSeries=[];this.bounds={x1:null,y1:null,x2:null,y2:null};"undefined"===typeof this._options.fontSize&&(this.fontSize=this.chart.getAutoFontSize(this.fontSize));this.lineHeight=ca(this.fontFamily,
+this.fontSize,this.fontWeight)}function la(a,b){la.parent.constructor.call(this,b);this.chart=a;this.canvas=a.canvas;this.ctx=this.chart.ctx}function P(a,b,c,d,e){P.parent.constructor.call(this,"DataSeries",b,c);this.chart=a;this.canvas=a.canvas;this._ctx=a.canvas.ctx;this.index=d;this.noDataPointsInPlotArea=0;this.id=e;this.chart._eventManager.objectMap[e]={id:e,objectType:"dataSeries",dataSeriesIndex:d};this.dataPointIds=[];this.plotUnit=[];this.axisY=this.axisX=null;null===this.fillOpacity&&(this.type.match(/area/i)?
+this.fillOpacity=0.7:this.fillOpacity=1);this.axisPlacement=this.getDefaultAxisPlacement();"undefined"===typeof this._options.indexLabelFontSize&&(this.indexLabelFontSize=this.chart.getAutoFontSize(this.indexLabelFontSize))}function A(a,b,c,d){A.parent.constructor.call(this,"Axis",b,a.theme);this.chart=a;this.canvas=a.canvas;this.ctx=a.ctx;this.intervalstartTimePercent=this.maxHeight=this.maxWidth=0;this.labels=[];this._labels=null;this.dataInfo={min:Infinity,max:-Infinity,viewPortMin:Infinity,viewPortMax:-Infinity,
+minDiff:Infinity};"axisX"===c?(this.sessionVariables=this.chart.sessionVariables[c],this._options.interval||(this.intervalType=null)):this.sessionVariables="left"===d||"top"===d?this.chart.sessionVariables.axisY:this.chart.sessionVariables.axisY2;"undefined"===typeof this._options.titleFontSize&&(this.titleFontSize=this.chart.getAutoFontSize(this.titleFontSize));"undefined"===typeof this._options.labelFontSize&&(this.labelFontSize=this.chart.getAutoFontSize(this.labelFontSize));this.type=c;"axisX"!==
+c||b&&"undefined"!==typeof b.gridThickness||(this.gridThickness=0);this._position=d;this.lineCoordinates={x1:null,y1:null,x2:null,y2:null,width:null};this.labelAngle=(this.labelAngle%360+360)%360;90<this.labelAngle&&270>=this.labelAngle?this.labelAngle-=180:180<this.labelAngle&&270>=this.labelAngle?this.labelAngle-=180:270<this.labelAngle&&360>=this.labelAngle&&(this.labelAngle-=360);if(this._options.stripLines&&0<this._options.stripLines.length)for(this.stripLines=[],b=0;b<this._options.stripLines.length;b++)this.stripLines.push(new ma(this.chart,
+this._options.stripLines[b],a.theme,++this.chart._eventManager.lastObjectId));this._absoluteMaximum=this._absoluteMinimum=this._titleTextBlock=null;this.hasOptionChanged("minimum")&&(this.sessionVariables.internalMinimum=this.minimum);this.hasOptionChanged("maximum")&&(this.sessionVariables.internalMaximum=this.maximum);this.trackChanges("minimum");this.trackChanges("maximum")}function ma(a,b,c,d){ma.parent.constructor.call(this,"StripLine",b,c);this._thicknessType="pixel";this.id=d;null!==this.startValue&&
+null!==this.endValue&&(this.value=((this.startValue.getTime?this.startValue.getTime():this.startValue)+(this.endValue.getTime?this.endValue.getTime():this.endValue))/2,this.thickness=Math.max(this.endValue-this.startValue),this._thicknessType="value")}function N(a,b,c){N.parent.constructor.call(this,"ToolTip",b,c);this.chart=a;this.canvas=a.canvas;this.ctx=this.chart.ctx;this.currentDataPointIndex=this.currentSeriesIndex=-1;this._timerId=0;this._prevY=this._prevX=NaN;this._initialize()}function $(a){this.chart=
+a;this.lastObjectId=0;this.objectMap=[];this.rectangularRegionEventSubscriptions=[];this.previousDataPointEventObject=null;this.ghostCanvas=U(this.chart.width,this.chart.height);this.ghostCtx=this.ghostCanvas.getContext("2d");this.mouseoveredObjectMaps=[]}function xa(a,b){var c;b&&na[b]&&(c=na[b]);ba.parent.constructor.call(this,"CultureInfo",c,a.theme);this.chart=a;this.canvas=a.canvas;this.ctx=this.chart.ctx}function oa(a){this.chart=a;this.ctx=this.chart.plotArea.ctx;this.animations=[];this.animationRequestId=
+null}var t=!!document.createElement("canvas").getContext,ha={Chart:{width:500,height:400,zoomEnabled:!1,backgroundColor:"white",theme:"theme1",animationEnabled:!1,animationDuration:1200,colorSet:"colorSet1",culture:"en",creditText:"CanvasJS.com",interactivityEnabled:!0,exportEnabled:!1,exportFileName:"Chart"},Title:{padding:0,text:null,verticalAlign:"top",horizontalAlign:"center",fontSize:20,fontFamily:"Calibri",fontWeight:"normal",fontColor:"black",fontStyle:"normal",borderThickness:0,borderColor:"black",
+cornerRadius:0,backgroundColor:null,margin:5},Legend:{name:null,verticalAlign:"center",horizontalAlign:"right",fontSize:14,fontFamily:"calibri",fontWeight:"normal",fontColor:"black",fontStyle:"normal",cursor:null,itemmouseover:null,itemmouseout:null,itemmousemove:null,itemclick:null},ToolTip:{enabled:!0,borderColor:null,shared:!1,animationEnabled:!0,content:null},Axis:{minimum:null,maximum:null,interval:null,intervalType:null,title:null,titleFontColor:"black",titleFontSize:20,titleFontFamily:"arial",
+titleFontWeight:"normal",titleFontStyle:"normal",labelAngle:0,labelFontFamily:"arial",labelFontColor:"black",labelFontSize:12,labelFontWeight:"normal",labelFontStyle:"normal",labelAutoFit:!1,labelWrap:!0,labelMaxWidth:null,prefix:"",suffix:"",includeZero:!0,tickLength:5,tickColor:"black",tickThickness:1,lineColor:"black",lineThickness:1,gridColor:"A0A0A0",gridThickness:0,interlacedColor:null,valueFormatString:null,margin:2,stripLines:[]},StripLine:{value:null,startValue:null,endValue:null,color:"orange",
+thickness:2,label:"",labelBackgroundColor:"#EEEEEE",labelFontFamily:"arial",labelFontColor:"orange",labelFontSize:12,labelFontWeight:"normal",labelFontStyle:"normal"},DataSeries:{name:null,dataPoints:null,label:"",bevelEnabled:!1,cursor:null,indexLabel:"",indexLabelPlacement:"auto",indexLabelOrientation:"horizontal",indexLabelFontColor:"black",indexLabelFontSize:12,indexLabelFontStyle:"normal",indexLabelFontFamily:"Arial",indexLabelFontWeight:"normal",indexLabelBackgroundColor:null,indexLabelLineColor:null,
+indexLabelLineThickness:1,indexLabelMaxWidth:null,indexLabelWrap:!0,lineThickness:2,color:null,risingColor:"white",fillOpacity:null,startAngle:0,type:"column",xValueType:"number",axisYType:"primary",xValueFormatString:null,yValueFormatString:null,zValueFormatString:null,percentFormatString:null,showInLegend:null,legendMarkerType:null,legendMarkerColor:null,legendText:null,legendMarkerBorderColor:null,legendMarkerBorderThickness:null,markerType:"circle",markerColor:null,markerSize:null,markerBorderColor:null,
+markerBorderThickness:null,mouseover:null,mouseout:null,mousemove:null,click:null,toolTipContent:null,visible:!0},CultureInfo:{decimalSeparator:".",digitGroupSeparator:",",zoomText:"Zoom",panText:"Pan",resetText:"Reset",menuText:"More Options",saveJPGText:"Save as JPG",savePNGText:"Save as PNG",days:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),shortDays:"Sun Mon Tue Wed Thu Fri Sat".split(" "),months:"January February March April May June July August September October November December".split(" "),
+shortMonths:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" ")},TextBlock:{x:0,y:0,width:null,height:null,maxWidth:null,maxHeight:null,padding:0,angle:0,text:"",horizontalAlign:"center",fontSize:12,fontFamily:"calibri",fontWeight:"normal",fontColor:"black",fontStyle:"normal",borderThickness:0,borderColor:"black",cornerRadius:0,backgroundColor:null,textBaseline:"top"}},na={en:{}},V={colorSet1:"#369EAD #C24642 #7F6084 #86B402 #A2D1CF #C8B631 #6DBCEB #52514E #4F81BC #A064A1 #F79647".split(" "),
+colorSet2:"#4F81BC #C0504E #9BBB58 #23BFAA #8064A1 #4AACC5 #F79647 #33558B".split(" "),colorSet3:"#8CA1BC #36845C #017E82 #8CB9D0 #708C98 #94838D #F08891 #0366A7 #008276 #EE7757 #E5BA3A #F2990B #03557B #782970".split(" ")},W={theme1:{Chart:{colorSet:"colorSet1"},Title:{fontFamily:t?"Calibri, Optima, Candara, Verdana, Geneva, sans-serif":"calibri",fontSize:33,fontColor:"#3A3A3A",fontWeight:"bold",verticalAlign:"top",margin:10},Axis:{titleFontSize:26,titleFontColor:"#666666",titleFontFamily:t?"Calibri, Optima, Candara, Verdana, Geneva, sans-serif":
+"calibri",labelFontFamily:t?"Calibri, Optima, Candara, Verdana, Geneva, sans-serif":"calibri",labelFontSize:18,labelFontColor:"grey",tickColor:"#BBBBBB",tickThickness:2,gridThickness:2,gridColor:"#BBBBBB",lineThickness:2,lineColor:"#BBBBBB"},Legend:{verticalAlign:"bottom",horizontalAlign:"center",fontFamily:t?"monospace, sans-serif,arial black":"calibri"},DataSeries:{indexLabelFontColor:"grey",indexLabelFontFamily:t?"Calibri, Optima, Candara, Verdana, Geneva, sans-serif":"calibri",indexLabelFontSize:18,
+indexLabelLineThickness:1}},theme2:{Chart:{colorSet:"colorSet2"},Title:{fontFamily:"impact, charcoal, arial black, sans-serif",fontSize:32,fontColor:"#333333",verticalAlign:"top",margin:10},Axis:{titleFontSize:22,titleFontColor:"rgb(98,98,98)",titleFontFamily:t?"monospace, sans-serif,arial black":"arial",titleFontWeight:"bold",labelFontFamily:t?"monospace, Courier New, Courier":"arial",labelFontSize:16,labelFontColor:"grey",labelFontWeight:"bold",tickColor:"grey",tickThickness:2,gridThickness:2,gridColor:"grey",
+lineThickness:0},Legend:{verticalAlign:"bottom",horizontalAlign:"center",fontFamily:t?"monospace, sans-serif,arial black":"arial"},DataSeries:{indexLabelFontColor:"grey",indexLabelFontFamily:t?"Courier New, Courier, monospace":"arial",indexLabelFontWeight:"bold",indexLabelFontSize:18,indexLabelLineThickness:1}},theme3:{Chart:{colorSet:"colorSet1"},Title:{fontFamily:t?"Candara, Optima, Trebuchet MS, Helvetica Neue, Helvetica, Trebuchet MS, serif":"calibri",fontSize:32,fontColor:"#3A3A3A",fontWeight:"bold",
+verticalAlign:"top",margin:10},Axis:{titleFontSize:22,titleFontColor:"rgb(98,98,98)",titleFontFamily:t?"Verdana, Geneva, Calibri, sans-serif":"calibri",labelFontFamily:t?"Calibri, Optima, Candara, Verdana, Geneva, sans-serif":"calibri",labelFontSize:18,labelFontColor:"grey",tickColor:"grey",tickThickness:2,gridThickness:2,gridColor:"grey",lineThickness:2,lineColor:"grey"},Legend:{verticalAlign:"bottom",horizontalAlign:"center",fontFamily:t?"monospace, sans-serif,arial black":"calibri"},DataSeries:{bevelEnabled:!0,
+indexLabelFontColor:"grey",indexLabelFontFamily:t?"Candara, Optima, Calibri, Verdana, Geneva, sans-serif":"calibri",indexLabelFontSize:18,indexLabelLineColor:"lightgrey",indexLabelLineThickness:2}}},z={numberDuration:1,yearDuration:314496E5,monthDuration:2592E6,weekDuration:6048E5,dayDuration:864E5,hourDuration:36E5,minuteDuration:6E4,secondDuration:1E3,millisecondDuration:1,dayOfWeekFromInt:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" ")},sa={},R=null,ya=function(){var a=/D{1,4}|M{1,4}|Y{1,4}|h{1,2}|H{1,2}|m{1,2}|s{1,2}|f{1,3}|t{1,2}|T{1,2}|K|z{1,3}|"[^"]*"|'[^']*'/g,
+b="Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),c="Sun Mon Tue Wed Thu Fri Sat".split(" "),d="January February March April May June July August September October November December".split(" "),e="Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),f=/\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,g=/[^-+\dA-Z]/g;return function(k,p,h){var l=h?h.days:b,r=h?h.months:d,m=h?h.shortDays:
+c,q=h?h.shortMonths:e;h="";var n=!1;k=k&&k.getTime?k:k?new Date(k):new Date;if(isNaN(k))throw SyntaxError("invalid date");"UTC:"===p.slice(0,4)&&(p=p.slice(4),n=!0);h=n?"getUTC":"get";var s=k[h+"Date"](),t=k[h+"Day"](),u=k[h+"Month"](),x=k[h+"FullYear"](),w=k[h+"Hours"](),Q=k[h+"Minutes"](),G=k[h+"Seconds"](),v=k[h+"Milliseconds"](),y=n?0:k.getTimezoneOffset();return h=p.replace(a,function(a){switch(a){case "D":return s;case "DD":return K(s,2);case "DDD":return m[t];case "DDDD":return l[t];case "M":return u+
+1;case "MM":return K(u+1,2);case "MMM":return q[u];case "MMMM":return r[u];case "Y":return parseInt(String(x).slice(-2));case "YY":return K(String(x).slice(-2),2);case "YYY":return K(String(x).slice(-3),3);case "YYYY":return K(x,4);case "h":return w%12||12;case "hh":return K(w%12||12,2);case "H":return w;case "HH":return K(w,2);case "m":return Q;case "mm":return K(Q,2);case "s":return G;case "ss":return K(G,2);case "f":return String(v).slice(0,1);case "ff":return K(String(v).slice(0,2),2);case "fff":return K(String(v).slice(0,
+3),3);case "t":return 12>w?"a":"p";case "tt":return 12>w?"am":"pm";case "T":return 12>w?"A":"P";case "TT":return 12>w?"AM":"PM";case "K":return n?"UTC":(String(k).match(f)||[""]).pop().replace(g,"");case "z":return(0<y?"-":"+")+Math.floor(Math.abs(y)/60);case "zz":return(0<y?"-":"+")+K(Math.floor(Math.abs(y)/60),2);case "zzz":return(0<y?"-":"+")+K(Math.floor(Math.abs(y)/60),2)+K(Math.abs(y)%60,2);default:return a.slice(1,a.length-1)}})}}(),X=function(a,b,c){if(null===a)return"";a=Number(a);var d=
+0>a?!0:!1;d&&(a*=-1);var e=c?c.decimalSeparator:".",f=c?c.digitGroupSeparator:",",g="";b=String(b);var g=1,k=c="",p=-1,h=[],l=[],r=0,m=0,q=0,n=!1,s=0,k=b.match(/"[^"]*"|'[^']*'|[eE][+-]*[0]+|[,]+[.]|\u2030|./g);b=null;for(var t=0;k&&t<k.length;t++)if(b=k[t],"."===b&&0>p)p=t;else{if("%"===b)g*=100;else if("\u2030"===b){g*=1E3;continue}else if(","===b[0]&&"."===b[b.length-1]){g/=Math.pow(1E3,b.length-1);p=t+b.length-1;continue}else"E"!==b[0]&&"e"!==b[0]||"0"!==b[b.length-1]||(n=!0);0>p?(h.push(b),"#"===
+b||"0"===b?r++:","===b&&q++):(l.push(b),"#"!==b&&"0"!==b||m++)}n&&(b=Math.floor(a),s=(0===b?"":String(b)).length-r,g/=Math.pow(10,s));0>p&&(p=t);g=(a*g).toFixed(m);b=g.split(".");g=(b[0]+"").split("");a=(b[1]+"").split("");g&&"0"===g[0]&&g.shift();for(t=n=k=m=p=0;0<h.length;)if(b=h.pop(),"#"===b||"0"===b)if(p++,p===r){var u=g,g=[];if("0"===b)for(b=r-m-(u?u.length:0);0<b;)u.unshift("0"),b--;for(;0<u.length;)c=u.pop()+c,t++,0===t%n&&(k===q&&0<u.length)&&(c=f+c);d&&(c="-"+c)}else 0<g.length?(c=g.pop()+
+c,m++,t++):"0"===b&&(c="0"+c,m++,t++),0===t%n&&(k===q&&0<g.length)&&(c=f+c);else"E"!==b[0]&&"e"!==b[0]||"0"!==b[b.length-1]||!/[eE][+-]*[0]+/.test(b)?","===b?(k++,n=t,t=0,0<g.length&&(c=f+c)):c=1<b.length&&('"'===b[0]&&'"'===b[b.length-1]||"'"===b[0]&&"'"===b[b.length-1])?b.slice(1,b.length-1)+c:b+c:(b=0>s?b.replace("+","").replace("-",""):b.replace("-",""),c+=b.replace(/[0]+/,function(a){return K(s,a.length)}));d="";for(f=!1;0<l.length;)b=l.shift(),"#"===b||"0"===b?0<a.length&&0!==Number(a.join(""))?
+(d+=a.shift(),f=!0):"0"===b&&(d+="0",f=!0):1<b.length&&('"'===b[0]&&'"'===b[b.length-1]||"'"===b[0]&&"'"===b[b.length-1])?d+=b.slice(1,b.length-1):"E"!==b[0]&&"e"!==b[0]||"0"!==b[b.length-1]||!/[eE][+-]*[0]+/.test(b)?d+=b:(b=0>s?b.replace("+","").replace("-",""):b.replace("-",""),d+=b.replace(/[0]+/,function(a){return K(s,a.length)}));return c+((f?e:"")+d)},ia=function(a){var b=0,c=0;a=a||window.event;a.offsetX||0===a.offsetX?(b=a.offsetX,c=a.offsetY):a.layerX||0==a.layerX?(b=a.layerX,c=a.layerY):
+(b=a.pageX-a.target.offsetLeft,c=a.pageY-a.target.offsetTop);return{x:b,y:c}},va=!0,ja=window.devicePixelRatio||1,ea=1,H=va?ja/ea:1,Da={reset:{image:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAcCAYAAAAAwr0iAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAKRSURBVEiJrdY/iF1FFMfxzwnZrGISUSR/JLGIhoh/QiRNBLWxMLIWEkwbgiAoFgoW2mhlY6dgpY2IlRBRxBSKhSAKIklWJRYuMZKAhiyopAiaTY7FvRtmZ+/ed9/zHRjezLw5v/O9d86cuZGZpmURAfdn5o9DfdZNLXpjz+LziPgyIl6MiG0jPTJzZBuyDrP4BVm0P/AKbljTb4ToY/gGewYA7KyCl+1b3DUYANvwbiHw0gCAGRzBOzjTAXEOu0cC4Ch+r5x/HrpdrcZmvIDFSucMtnYCYC++6HmNDw8FKDT34ETrf639/azOr5vwRk/g5fbeuABtgC04XWk9VQLciMP4EH/3AFzErRNC7MXlQmsesSoHsGPE23hmEoBW+61K66HMXFmIMvN8myilXS36R01ub+KfYvw43ZXwYDX+AHP4BAci4pFJomfmr/ihmNofESsBImJGk7mlncrM45n5JPbhz0kAWpsv+juxaX21YIPmVJS2uNzJMS6ZNexC0d+I7fUWXLFyz2kSZlpWPvASlmqAf/FXNXf3FAF2F/1LuFifAlionB6dRuSI2IwHi6lzmXmp6xR8XY0fiIh7psAwh+3FuDkRHQVjl+a8lkXjo0kLUKH7XaV5oO86PmZ1FTzyP4K/XGl9v/zwfbW7BriiuETGCP5ch9bc9f97HF/vcFzCa5gdEPgWq+t/4v0V63oE1uF4h0DiFJ7HnSWMppDdh1dxtsPvJ2wcBNAKbsJXa0Ck5opdaBPsRNu/usba09i1KsaAVzmLt3sghrRjuK1Tf4xkegInxwy8gKf7dKMVH2QRsV5zXR/Cftyu+aKaKbbkQrsdH+PTzLzcqzkOQAVzM+7FHdiqqe2/YT4zF/t8S/sPmawyvC974vcAAAAASUVORK5CYII="},
+pan:{image:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAJVSURBVFiFvZe7a1RBGMV/x2hWI4JpfKCIiSBKOoOCkID/wP4BFqIIFkE02ChIiC8QDKlSiI3YqRBsBVGwUNAUdiIEUgjiAzQIIsuKJsfizsXr5t7d+8jmwLDfzHz3nLOzc7+ZxTZlGyDgZiWOCuJ9wH2gCUyuqQFgF/AGcKJNrYkBYBj40CIet+muGQi/96kM4WS7C/Tm5VUg7whJg8BkEGkCR4BDYfodsADUgP6wErO5iCtswsuJb32hdbXy8qzL5TIdmzJinHdZoZIBZcSFkGlAKs1Z3YCketZcBtouuaQNkrblMiBpBrhme7mAgU4wMCvpcFsDkq4C54DFVRTH9h+i6vlE0r5UA5ImgCuh28jB28iIs7BIVCOeStoZD64P4uPAjUTygKSx2FsK2TIwkugfk9Qkfd/E+yMWHQCeSRqx/R3gOp3LazfaS2C4B5gHDgD7U9x3E3uAH7KNpC3AHHAwTL4FHgM9GQ8vAaPA0dB/Abxqk2/gBLA9MXba9r1k/d4LfA3JtwueBeM58ucS+edXnAW23wP10N3advEi9CXizTnyN4bPS7Zn4sH/dq3t18AY4e1YLYSy3g/csj2VnFshZPuOpOeSKHCodUINuGj7YetE6je1PV9QoNPJ9StNHKodx7nRbiWrGHBGXAi5DUiqtQwtpcWK0Jubt8CltA5MEV1IfwO7+VffPwGfia5m34CT4bXujIIX0Qna1/cGMNqV/wUJE2czxD8CQ4X5Sl7Jz7SILwCDpbjKPBRMHAd+EtX4HWV5Spdc2w8kDQGPbH8py/MXMygM69/FKz4AAAAASUVORK5CYII="},
+zoom:{image:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAK6wAACusBgosNWgAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAMqSURBVFiFvdfbj91TFMDxz57U6GUEMS1aYzyMtCSSDhWjCZMInpAI3khE/QHtgzdRkXgSCS8SES9epKLi0oRKNETjRahREq2KS1stdRujtDPtbA97n5zdn9+5zJxTK9k5v3POXmt991p7r71+IcaoGwkhTOIebMRqzOBTvIG3Y4zTXRmqSoyx5cAKbMJOHMFJnMZ8/jyFaXyMR7G6nb1aH22cP4BvcBxziG3GKfyTIR9D6BYg1KUghPBCDveFlb/24Av8iuUYw41YVsz5G7uxKcZ4aMEpwGt5NY3V/YbHsQ6rcAHOw/kYxigewr5CZw4fYGxBKcCLOFEYehXrMdRhr5yLETxVScsOLOkKAPfn1TYMPIvLFrShUlS2FDZm8XRHACzFAWl3R2xbqPMCYhmeLCAOYEMngAczbcTvuHYxzguIy/FesR9e6gSwU/OoPYHBHgHgviIKX2Flq7k34KhmcVnbi/PC8JX4MgMcxb118wZwdz5aISscqx7VRcox7MrPQ7i+btIAJrAkf9+bI9EPmZY2IAxiTSuAldLq4Y9+AcSUh78KP0tbAcwU35cXMD1JCIFUoGiehlqAz6TNB1f1C0DK+0h+nsNPrQC2a4bqGmlD9kOGcWt+Po6pVgDvSxfJaSkFd4UQBvoAsBYbCoB3a2flM7slA0R8iyt6rAFDeDPbm8eOTpVwGD9qVq7nLbIaZnmksPU1JtsCZMXNmpdRxFasWITzh6Xj3LCzra1OxcD2QjHiGVzdpfORnMqZio2PcF23ABdJF1Np4BPptlyPi6WzPYBzpJZtHe7A6xW9cnyP8TqA//SEIYRL8Bxul7rihvwgtVn78WcGGZXa9HGd5TDujDHuOePXNiHdKjWgZX/YbsxLx/ktqbjVzTlcjUSnvI5JrdlUVp6WesZZ6R1hRrpq9+EVTGS9jTjYAuKIouGpbcurEkIYxC051KNSamazsc+xK8b4S0VnEi/j0hqTP+M27O258egQwZuzs7pI7Mf4WQXIEDc5s9sux+5+1Py2EmP8UOq6GvWhIScxfdYjUERiAt9Jd84J6a16zf8JEKT3yCm8g1UxRv8CC4pyRhzR1uUAAAAASUVORK5CYII="},
+menu:{image:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAgCAYAAAAbifjMAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAK6wAACusBgosNWgAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAAWdEVYdENyZWF0aW9uIFRpbWUAMDcvMTUvMTTPsvU0AAAAP0lEQVRIie2SMQoAIBDDUvH/X667g8sJJ9KOhYYOkW0qGaU1MPdC0vGSbV19EACo3YMPAFH5BUBUjsqfAPpVXtNgGDfxEDCtAAAAAElFTkSuQmCC"}};L.prototype.setOptions=function(a,b){if(ha[this._defaultsKey]){var c=ha[this._defaultsKey],d;for(d in c)this[d]=a&&d in a?a[d]:b&&d in b?b[d]:c[d]}};L.prototype.updateOption=
+function(a){var b=ha[this._defaultsKey],c=this._options.theme?this._options.theme:this.chart&&this.chart._options.theme?this.chart._options.theme:"theme1",d={},e=this[a];c&&(W[c]&&W[c][this._defaultsKey])&&(d=W[c][this._defaultsKey]);a in b&&(e=a in this._options?this._options[a]:d&&a in d?d[a]:b[a]);if(e===this[a])return!1;this[a]=e;return!0};L.prototype.trackChanges=function(a){this._options._oldOptions||(this._options._oldOptions={});this._options._oldOptions[a]=this._options[a]};L.prototype.isBeingTracked=
+function(a){this._options._oldOptions||(this._options._oldOptions={});return this._options._oldOptions[a]?!0:!1};L.prototype.hasOptionChanged=function(a){this._options._oldOptions||(this._options._oldOptions={});return this._options._oldOptions[a]!==this._options[a]};O(v,L);v.prototype._updateOptions=function(){var a=this;this.updateOption("width");this.updateOption("height");this.updateOption("theme");this.updateOption("colorSet")&&(this._selectedColorSet="undefined"!==typeof V[this.colorSet]?V[this.colorSet]:
+V.colorSet1);this.updateOption("backgroundColor");this.backgroundColor||(this.backgroundColor="rgba(0,0,0,0)");this.updateOption("culture");this._cultureInfo=new xa(this,this._options.culture);this.updateOption("animationEnabled");this.animationEnabled=this.animationEnabled&&t;this._options.zoomEnabled?(this._zoomButton||(S(this._zoomButton=document.createElement("button")),M(this,this._zoomButton,"pan"),this._toolBar.appendChild(this._zoomButton),E(this._zoomButton,"click",function(){a.zoomEnabled?
+(a.zoomEnabled=!1,a.panEnabled=!0,M(a,a._zoomButton,"zoom")):(a.zoomEnabled=!0,a.panEnabled=!1,M(a,a._zoomButton,"pan"));a.render()})),this._resetButton||(S(this._resetButton=document.createElement("button")),M(this,this._resetButton,"reset"),this._toolBar.appendChild(this._resetButton),E(this._resetButton,"click",function(){a._toolTip.hide();a.zoomEnabled||a.panEnabled?(a.zoomEnabled=!0,a.panEnabled=!1,M(a,a._zoomButton,"pan"),a._defaultCursor="default",a.overlaidCanvas.style.cursor=a._defaultCursor):
+(a.zoomEnabled=!1,a.panEnabled=!1);a.sessionVariables.axisX.internalMinimum=a._options.axisX&&a._options.axisX.minimum?a._options.axisX.minimum:null;a.sessionVariables.axisX.internalMaximum=a._options.axisX&&a._options.axisX.maximum?a._options.axisX.maximum:null;a.resetOverlayedCanvas();S(a._zoomButton,a._resetButton);a.render()}),this.overlaidCanvas.style.cursor=a._defaultCursor),this.zoomEnabled||this.panEnabled||(this._zoomButton?(a._zoomButton.getAttribute("state")===a._cultureInfo.zoomText?(this.panEnabled=
+!0,this.zoomEnabled=!1):(this.zoomEnabled=!0,this.panEnabled=!1),ka(a._zoomButton,a._resetButton)):(this.zoomEnabled=!0,this.panEnabled=!1))):this.panEnabled=this.zoomEnabled=!1;"undefined"!==typeof this._options.exportFileName&&(this.exportFileName=this._options.exportFileName);"undefined"!==typeof this._options.exportEnabled&&(this.exportEnabled=this._options.exportEnabled);this._menuButton?this.exportEnabled?ka(this._menuButton):S(this._menuButton):this.exportEnabled&&t&&(this._menuButton=document.createElement("button"),
+M(this,this._menuButton,"menu"),this._toolBar.appendChild(this._menuButton),E(this._menuButton,"click",function(){"none"!==a._dropdownMenu.style.display||a._dropDownCloseTime&&500>=(new Date).getTime()-a._dropDownCloseTime.getTime()||(a._dropdownMenu.style.display="block",a._menuButton.blur(),a._dropdownMenu.focus())},!0));if(!this._dropdownMenu&&this.exportEnabled&&t){this._dropdownMenu=document.createElement("div");this._dropdownMenu.setAttribute("tabindex",-1);this._dropdownMenu.style.cssText=
+"position: absolute; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; cursor: pointer;right: 1px;top: 25px;min-width: 120px;outline: 0;border: 1px solid silver;font-size: 14px;font-family: Calibri, Verdana, sans-serif;padding: 5px 0px 5px 0px;text-align: left;background-color: #fff;line-height: 20px;box-shadow: 2px 2px 10px #888888;";a._dropdownMenu.style.display="none";this._toolBar.appendChild(this._dropdownMenu);E(this._dropdownMenu,"blur",function(){S(a._dropdownMenu);
+a._dropDownCloseTime=new Date},!0);var b=document.createElement("div");b.style.cssText="padding: 2px 15px 2px 10px";b.innerHTML=this._cultureInfo.saveJPGText;this._dropdownMenu.appendChild(b);E(b,"mouseover",function(){this.style.backgroundColor="#EEEEEE"},!0);E(b,"mouseout",function(){this.style.backgroundColor="transparent"},!0);E(b,"click",function(){wa(a.canvas,"jpg",a.exportFileName);S(a._dropdownMenu)},!0);b=document.createElement("div");b.style.cssText="padding: 2px 15px 2px 10px";b.innerHTML=
+this._cultureInfo.savePNGText;this._dropdownMenu.appendChild(b);E(b,"mouseover",function(){this.style.backgroundColor="#EEEEEE"},!0);E(b,"mouseout",function(){this.style.backgroundColor="transparent"},!0);E(b,"click",function(){wa(a.canvas,"png",a.exportFileName);S(a._dropdownMenu)},!0)}"none"!==this._toolBar.style.display&&this._zoomButton&&(this.panEnabled?M(a,a._zoomButton,"zoom"):M(a,a._zoomButton,"pan"),a._resetButton.getAttribute("state")!==a._cultureInfo.resetText&&M(a,a._resetButton,"reset"));
+if("undefined"===typeof ha.Chart.creditHref)this.creditHref="http://canvasjs.com/",this.creditText="CanvasJS.com";else var c=this.updateOption("creditText"),d=this.updateOption("creditHref");if(0===this.renderCount||c||d)this._creditLink.setAttribute("href",this.creditHref),this._creditLink.innerHTML=this.creditText;this.creditHref&&this.creditText?this._creditLink.parentElement||this._canvasJSContainer.appendChild(this._creditLink):this._creditLink.parentElement&&this._canvasJSContainer.removeChild(this._creditLink);
+this._options.toolTip&&this._toolTip._options!==this._options.toolTip&&(this._toolTip._options=this._options.toolTip);this._toolTip.updateOption("enabled");this._toolTip.updateOption("shared");this._toolTip.updateOption("animationEnabled");this._toolTip.updateOption("borderColor");this._toolTip.updateOption("content")};v.prototype._updateSize=function(){var a=0,b=0;this._options.width?a=this.width:this.width=a=0<this._container.clientWidth?this._container.clientWidth:this.width;this._options.height?
+b=this.height:this.height=b=0<this._container.clientHeight?this._container.clientHeight:this.height;return this.canvas.width!==a*H||this.canvas.height!==b*H?(da(this.canvas,a,b),da(this.overlaidCanvas,a,b),da(this._eventManager.ghostCanvas,a,b),!0):!1};v.prototype._initialize=function(){this._animator?this._animator.cancelAllAnimations():this._animator=new oa(this);this.disableToolTip=!1;this.pieDoughnutClickHandler=null;this.animationRequestId&&this.cancelRequestAnimFrame.call(window,this.animationRequestId);
+this._updateOptions();this.animatedRender=t&&this.animationEnabled&&0===this.renderCount;this._updateSize();this.clearCanvas();this.ctx.beginPath();this.axisY2=this.axisY=this.axisX=null;this._indexLabels=[];this._dataInRenderedOrder=[];this._events=[];this._eventManager&&this._eventManager.reset();this.plotInfo={axisPlacement:null,axisXValueType:null,plotTypes:[]};this.layoutManager.reset();this.data=[];for(var a=0,b=0;b<this._options.data.length;b++)if(a++,!this._options.data[b].type||0<=v._supportedChartTypes.indexOf(this._options.data[b].type)){var c=
+new P(this,this._options.data[b],this.theme,a-1,++this._eventManager.lastObjectId);null===c.name&&(c.name="DataSeries "+a);null===c.color?1<this._options.data.length?(c._colorSet=[this._selectedColorSet[c.index%this._selectedColorSet.length]],c.color=this._selectedColorSet[c.index%this._selectedColorSet.length]):c._colorSet="line"===c.type||"stepLine"===c.type||"spline"===c.type||"area"===c.type||"stepArea"===c.type||"splineArea"===c.type||"stackedArea"===c.type||"stackedArea100"===c.type||"rangeArea"===
+c.type||"rangeSplineArea"===c.type||"candlestick"===c.type||"ohlc"===c.type?[this._selectedColorSet[0]]:this._selectedColorSet:c._colorSet=[c.color];null===c.markerSize&&(("line"===c.type||"stepLine"===c.type||"spline"===c.type)&&c.dataPoints&&c.dataPoints.length<this.width/16||"scatter"===c.type)&&(c.markerSize=8);"bubble"!==c.type&&"scatter"!==c.type||!c.dataPoints||c.dataPoints.sort(Ca);this.data.push(c);var d=c.axisPlacement,e;"normal"===d?"xySwapped"===this.plotInfo.axisPlacement?e='You cannot combine "'+
+c.type+'" with bar chart':"none"===this.plotInfo.axisPlacement?e='You cannot combine "'+c.type+'" with pie chart':null===this.plotInfo.axisPlacement&&(this.plotInfo.axisPlacement="normal"):"xySwapped"===d?"normal"===this.plotInfo.axisPlacement?e='You cannot combine "'+c.type+'" with line, area, column or pie chart':"none"===this.plotInfo.axisPlacement?e='You cannot combine "'+c.type+'" with pie chart':null===this.plotInfo.axisPlacement&&(this.plotInfo.axisPlacement="xySwapped"):"none"==d&&("normal"===
+this.plotInfo.axisPlacement?e='You cannot combine "'+c.type+'" with line, area, column or bar chart':"xySwapped"===this.plotInfo.axisPlacement?e='You cannot combine "'+c.type+'" with bar chart':null===this.plotInfo.axisPlacement&&(this.plotInfo.axisPlacement="none"));if(e&&window.console){window.console.log(e);return}}this._objectsInitialized=!0};v._supportedChartTypes="line stepLine spline column area stepArea splineArea bar bubble scatter stackedColumn stackedColumn100 stackedBar stackedBar100 stackedArea stackedArea100 candlestick ohlc rangeColumn rangeBar rangeArea rangeSplineArea pie doughnut funnel".split(" ");
+v._supportedChartTypes.indexOf||(v._supportedChartTypes.indexOf=function(a,b){var c=this.length>>>0,d=Number(b)||0,d=0>d?Math.ceil(d):Math.floor(d);for(0>d&&(d+=c);d<c;d++)if(d in this&&this[d]===a)return d;return-1});v.prototype.render=function(a){a&&(this._options=a);this._initialize();for(a=0;a<this.data.length;a++)if("normal"===this.plotInfo.axisPlacement||"xySwapped"===this.plotInfo.axisPlacement)this.data[a].axisYType&&"primary"!==this.data[a].axisYType?"secondary"===this.data[a].axisYType&&
+(this.axisY2||("normal"===this.plotInfo.axisPlacement?this.axisY2=new A(this,this._options.axisY2,"axisY","right"):"xySwapped"===this.plotInfo.axisPlacement&&(this.axisY2=new A(this,this._options.axisY2,"axisY","top"))),this.data[a].axisY=this.axisY2):(this.axisY||("normal"===this.plotInfo.axisPlacement?this.axisY=new A(this,this._options.axisY,"axisY","left"):"xySwapped"===this.plotInfo.axisPlacement&&(this.axisY=new A(this,this._options.axisY,"axisY","bottom"))),this.data[a].axisY=this.axisY),this.axisX||
+("normal"===this.plotInfo.axisPlacement?this.axisX=new A(this,this._options.axisX,"axisX","bottom"):"xySwapped"===this.plotInfo.axisPlacement&&(this.axisX=new A(this,this._options.axisX,"axisX","left"))),this.data[a].axisX=this.axisX;this._processData();this._options.title&&(this._title=new ba(this,this._options.title),this._title.render());this.legend=new ga(this,this._options.legend,this.theme);for(a=0;a<this.data.length;a++)this.data[a].showInLegend&&this.legend.dataSeries.push(this.data[a]);this.legend.render();
+if("normal"===this.plotInfo.axisPlacement||"xySwapped"===this.plotInfo.axisPlacement)this.layoutManager.getFreeSpace(),A.setLayoutAndRender(this.axisX,this.axisY,this.axisY2,this.plotInfo.axisPlacement,this.layoutManager.getFreeSpace());else if("none"===this.plotInfo.axisPlacement)this.preparePlotArea();else return;var b=[];if(this.animatedRender){var c=U(this.width,this.height);c.getContext("2d").drawImage(this.canvas,0,0,this.width,this.height)}for(a=0;a<this.plotInfo.plotTypes.length;a++)for(var d=
+this.plotInfo.plotTypes[a],e=0;e<d.plotUnits.length;e++){var f=d.plotUnits[e],g=null;f.targetCanvas=null;this.animatedRender&&(f.targetCanvas=U(this.width,this.height),f.targetCanvasCtx=f.targetCanvas.getContext("2d"));"line"===f.type?g=this.renderLine(f):"stepLine"===f.type?g=this.renderStepLine(f):"spline"===f.type?g=this.renderSpline(f):"column"===f.type?g=this.renderColumn(f):"bar"===f.type?g=this.renderBar(f):"area"===f.type?g=this.renderArea(f):"stepArea"===f.type?g=this.renderStepArea(f):"splineArea"===
+f.type?g=this.renderSplineArea(f):"stackedColumn"===f.type?g=this.renderStackedColumn(f):"stackedColumn100"===f.type?g=this.renderStackedColumn100(f):"stackedBar"===f.type?g=this.renderStackedBar(f):"stackedBar100"===f.type?g=this.renderStackedBar100(f):"stackedArea"===f.type?g=this.renderStackedArea(f):"stackedArea100"===f.type?g=this.renderStackedArea100(f):"bubble"===f.type?g=g=this.renderBubble(f):"scatter"===f.type?g=this.renderScatter(f):"pie"===f.type?this.renderPie(f):"doughnut"===f.type?
+this.renderPie(f):"candlestick"===f.type?g=this.renderCandlestick(f):"ohlc"===f.type?g=this.renderCandlestick(f):"rangeColumn"===f.type?g=this.renderRangeColumn(f):"rangeBar"===f.type?g=this.renderRangeBar(f):"rangeArea"===f.type?g=this.renderRangeArea(f):"rangeSplineArea"===f.type&&(g=this.renderRangeSplineArea(f));for(var k=0;k<f.dataSeriesIndexes.length;k++)this._dataInRenderedOrder.push(this.data[f.dataSeriesIndexes[k]]);this.animatedRender&&g&&b.push(g)}this.animatedRender&&0<this._indexLabels.length&&
+(a=U(this.width,this.height).getContext("2d"),b.push(this.renderIndexLabels(a)));var p=this;0<b.length?(p.disableToolTip=!0,p._animator.animate(200,p.animationDuration,function(a){p.ctx.clearRect(0,0,p.width,p.height);p.ctx.drawImage(c,0,0,p.width*H,p.height*H,0,0,p.width,p.height);for(var d=0;d<b.length;d++)g=b[d],1>a&&"undefined"!==typeof g.startTimePercent?a>=g.startTimePercent&&g.animationCallback(g.easingFunction(a-g.startTimePercent,0,1,1-g.startTimePercent),g):g.animationCallback(g.easingFunction(a,
+0,1,1),g)},function(){b=[];for(var a=0;a<p.plotInfo.plotTypes.length;a++)for(var d=p.plotInfo.plotTypes[a],e=0;e<d.plotUnits.length;e++)d.plotUnits[e].targetCanvas=null;c=null;p.disableToolTip=!1})):0<p._indexLabels.length&&p.renderIndexLabels();this.attachPlotAreaEventHandlers();this.zoomEnabled||(this.panEnabled||!this._zoomButton||"none"===this._zoomButton.style.display)||S(this._zoomButton,this._resetButton);this._toolTip._updateToolTip();this.renderCount++};v.prototype.attachPlotAreaEventHandlers=
+function(){this.attachEvent({context:this,chart:this,mousedown:this._plotAreaMouseDown,mouseup:this._plotAreaMouseUp,mousemove:this._plotAreaMouseMove,cursor:this.zoomEnabled?"col-resize":"move",cursor:this.panEnabled?"move":"default",capture:!0,bounds:this.plotArea})};v.prototype.categoriseDataSeries=function(){for(var a="",b=0;b<this.data.length;b++)if(a=this.data[b],a.dataPoints&&(0!==a.dataPoints.length&&a.visible)&&0<=v._supportedChartTypes.indexOf(a.type)){for(var c=null,d=!1,e=null,f=!1,g=
+0;g<this.plotInfo.plotTypes.length;g++)if(this.plotInfo.plotTypes[g].type===a.type){d=!0;c=this.plotInfo.plotTypes[g];break}d||(c={type:a.type,totalDataSeries:0,plotUnits:[]},this.plotInfo.plotTypes.push(c));for(g=0;g<c.plotUnits.length;g++)if(c.plotUnits[g].axisYType===a.axisYType){f=!0;e=c.plotUnits[g];break}f||(e={type:a.type,previousDataSeriesCount:0,index:c.plotUnits.length,plotType:c,axisYType:a.axisYType,axisY:"primary"===a.axisYType?this.axisY:this.axisY2,axisX:this.axisX,dataSeriesIndexes:[],
+yTotals:[]},c.plotUnits.push(e));c.totalDataSeries++;e.dataSeriesIndexes.push(b);a.plotUnit=e}for(b=0;b<this.plotInfo.plotTypes.length;b++)for(c=this.plotInfo.plotTypes[b],g=a=0;g<c.plotUnits.length;g++)c.plotUnits[g].previousDataSeriesCount=a,a+=c.plotUnits[g].dataSeriesIndexes.length};v.prototype.assignIdToDataPoints=function(){for(var a=0;a<this.data.length;a++){var b=this.data[a];if(b.dataPoints)for(var c=b.dataPoints.length,d=0;d<c;d++)b.dataPointIds[d]=++this._eventManager.lastObjectId}};v.prototype._processData=
+function(){this.assignIdToDataPoints();this.categoriseDataSeries();for(var a=0;a<this.plotInfo.plotTypes.length;a++)for(var b=this.plotInfo.plotTypes[a],c=0;c<b.plotUnits.length;c++){var d=b.plotUnits[c];"line"===d.type||"stepLine"===d.type||"spline"===d.type||"column"===d.type||"area"===d.type||"stepArea"===d.type||"splineArea"===d.type||"bar"===d.type||"bubble"===d.type||"scatter"===d.type?this._processMultiseriesPlotUnit(d):"stackedColumn"===d.type||"stackedBar"===d.type||"stackedArea"===d.type?
+this._processStackedPlotUnit(d):"stackedColumn100"===d.type||"stackedBar100"===d.type||"stackedArea100"===d.type?this._processStacked100PlotUnit(d):"candlestick"!==d.type&&"ohlc"!==d.type&&"rangeColumn"!==d.type&&"rangeBar"!==d.type&&"rangeArea"!==d.type&&"rangeSplineArea"!==d.type||this._processMultiYPlotUnit(d)}};v.prototype._processMultiseriesPlotUnit=function(a){if(a.dataSeriesIndexes&&!(1>a.dataSeriesIndexes.length))for(var b=a.axisY.dataInfo,c=a.axisX.dataInfo,d,e,f=!1,g=0;g<a.dataSeriesIndexes.length;g++){var k=
+this.data[a.dataSeriesIndexes[g]],p=0,h=!1,l=!1;if("normal"===k.axisPlacement||"xySwapped"===k.axisPlacement)var r=this.sessionVariables.axisX.internalMinimum?this.sessionVariables.axisX.internalMinimum:this._options.axisX&&this._options.axisX.minimum?this._options.axisX.minimum:-Infinity,m=this.sessionVariables.axisX.internalMaximum?this.sessionVariables.axisX.internalMaximum:this._options.axisX&&this._options.axisX.maximum?this._options.axisX.maximum:Infinity;if(k.dataPoints[p].x&&k.dataPoints[p].x.getTime||
+"dateTime"===k.xValueType)f=!0;for(p=0;p<k.dataPoints.length;p++){"undefined"===typeof k.dataPoints[p].x&&(k.dataPoints[p].x=p);k.dataPoints[p].x.getTime?(f=!0,d=k.dataPoints[p].x.getTime()):d=k.dataPoints[p].x;e=k.dataPoints[p].y;d<c.min&&(c.min=d);d>c.max&&(c.max=d);e<b.min&&(b.min=e);e>b.max&&(b.max=e);if(0<p){var q=d-k.dataPoints[p-1].x;0>q&&(q*=-1);c.minDiff>q&&0!==q&&(c.minDiff=q)}if(!(d<r)||h){if(!h&&(h=!0,0<p)){p-=2;continue}if(d>m&&!l)l=!0;else if(d>m&&l)continue;k.dataPoints[p].label&&(a.axisX.labels[d]=
+k.dataPoints[p].label);d<c.viewPortMin&&(c.viewPortMin=d);d>c.viewPortMax&&(c.viewPortMax=d);null!==e&&(e<b.viewPortMin&&(b.viewPortMin=e),e>b.viewPortMax&&(b.viewPortMax=e))}}this.plotInfo.axisXValueType=k.xValueType=f?"dateTime":"number"}};v.prototype._processStackedPlotUnit=function(a){if(a.dataSeriesIndexes&&!(1>a.dataSeriesIndexes.length)){for(var b=a.axisY.dataInfo,c=a.axisX.dataInfo,d,e,f=!1,g=[],k=[],p=0;p<a.dataSeriesIndexes.length;p++){var h=this.data[a.dataSeriesIndexes[p]],l=0,r=!1,m=
+!1;if("normal"===h.axisPlacement||"xySwapped"===h.axisPlacement)var q=this.sessionVariables.axisX.internalMinimum?this.sessionVariables.axisX.internalMinimum:this._options.axisX&&this._options.axisX.minimum?this._options.axisX.minimum:-Infinity,n=this.sessionVariables.axisX.internalMaximum?this.sessionVariables.axisX.internalMaximum:this._options.axisX&&this._options.axisX.maximum?this._options.axisX.maximum:Infinity;if(h.dataPoints[l].x&&h.dataPoints[l].x.getTime||"dateTime"===h.xValueType)f=!0;
+for(l=0;l<h.dataPoints.length;l++){"undefined"===typeof h.dataPoints[l].x&&(h.dataPoints[l].x=l);h.dataPoints[l].x.getTime?(f=!0,d=h.dataPoints[l].x.getTime()):d=h.dataPoints[l].x;e=h.dataPoints[l].y;d<c.min&&(c.min=d);d>c.max&&(c.max=d);if(0<l){var s=d-h.dataPoints[l-1].x;0>s&&(s*=-1);c.minDiff>s&&0!==s&&(c.minDiff=s)}if(!(d<q)||r){if(!r&&(r=!0,0<l)){l-=2;continue}if(d>n&&!m)m=!0;else if(d>n&&m)continue;h.dataPoints[l].label&&(a.axisX.labels[d]=h.dataPoints[l].label);d<c.viewPortMin&&(c.viewPortMin=
+d);d>c.viewPortMax&&(c.viewPortMax=d);null!==e&&(a.yTotals[d]=(a.yTotals[d]?a.yTotals[d]:0)+Math.abs(e),0<=e?g[d]=g[d]?g[d]+e:e:k[d]=k[d]?k[d]+e:e)}}this.plotInfo.axisXValueType=h.xValueType=f?"dateTime":"number"}for(l in g)isNaN(l)||(a=g[l],a<b.min&&(b.min=a),a>b.max&&(b.max=a),l<c.viewPortMin||l>c.viewPortMax||(a<b.viewPortMin&&(b.viewPortMin=a),a>b.viewPortMax&&(b.viewPortMax=a)));for(l in k)isNaN(l)||(a=k[l],a<b.min&&(b.min=a),a>b.max&&(b.max=a),l<c.viewPortMin||l>c.viewPortMax||(a<b.viewPortMin&&
+(b.viewPortMin=a),a>b.viewPortMax&&(b.viewPortMax=a)))}};v.prototype._processStacked100PlotUnit=function(a){if(a.dataSeriesIndexes&&!(1>a.dataSeriesIndexes.length)){for(var b=a.axisY.dataInfo,c=a.axisX.dataInfo,d,e,f=!1,g=!1,k=!1,p=[],h=0;h<a.dataSeriesIndexes.length;h++){var l=this.data[a.dataSeriesIndexes[h]],r=0,m=!1,q=!1;if("normal"===l.axisPlacement||"xySwapped"===l.axisPlacement)var n=this.sessionVariables.axisX.internalMinimum?this.sessionVariables.axisX.internalMinimum:this._options.axisX&&
+this._options.axisX.minimum?this._options.axisX.minimum:-Infinity,s=this.sessionVariables.axisX.internalMaximum?this.sessionVariables.axisX.internalMaximum:this._options.axisX&&this._options.axisX.maximum?this._options.axisX.maximum:Infinity;if(l.dataPoints[r].x&&l.dataPoints[r].x.getTime||"dateTime"===l.xValueType)f=!0;for(r=0;r<l.dataPoints.length;r++){"undefined"===typeof l.dataPoints[r].x&&(l.dataPoints[r].x=r);l.dataPoints[r].x.getTime?(f=!0,d=l.dataPoints[r].x.getTime()):d=l.dataPoints[r].x;
+e=l.dataPoints[r].y;d<c.min&&(c.min=d);d>c.max&&(c.max=d);if(0<r){var t=d-l.dataPoints[r-1].x;0>t&&(t*=-1);c.minDiff>t&&0!==t&&(c.minDiff=t)}if(!(d<n)||m){if(!m&&(m=!0,0<r)){r-=2;continue}if(d>s&&!q)q=!0;else if(d>s&&q)continue;l.dataPoints[r].label&&(a.axisX.labels[d]=l.dataPoints[r].label);d<c.viewPortMin&&(c.viewPortMin=d);d>c.viewPortMax&&(c.viewPortMax=d);null!==e&&(a.yTotals[d]=(a.yTotals[d]?a.yTotals[d]:0)+Math.abs(e),0<=e?g=!0:k=!0,p[d]=p[d]?p[d]+Math.abs(e):Math.abs(e))}}this.plotInfo.axisXValueType=
+l.xValueType=f?"dateTime":"number"}g&&!k?(b.max=99,b.min=1):g&&k?(b.max=99,b.min=-99):!g&&k&&(b.max=-1,b.min=-99);b.viewPortMin=b.min;b.viewPortMax=b.max;a.dataPointYSums=p}};v.prototype._processMultiYPlotUnit=function(a){if(a.dataSeriesIndexes&&!(1>a.dataSeriesIndexes.length))for(var b=a.axisY.dataInfo,c=a.axisX.dataInfo,d,e,f,g,k=!1,p=0;p<a.dataSeriesIndexes.length;p++){var h=this.data[a.dataSeriesIndexes[p]],l=0,r=!1,m=!1;if("normal"===h.axisPlacement||"xySwapped"===h.axisPlacement)var q=this.sessionVariables.axisX.internalMinimum?
+this.sessionVariables.axisX.internalMinimum:this._options.axisX&&this._options.axisX.minimum?this._options.axisX.minimum:-Infinity,n=this.sessionVariables.axisX.internalMaximum?this.sessionVariables.axisX.internalMaximum:this._options.axisX&&this._options.axisX.maximum?this._options.axisX.maximum:Infinity;if(h.dataPoints[l].x&&h.dataPoints[l].x.getTime||"dateTime"===h.xValueType)k=!0;for(l=0;l<h.dataPoints.length;l++){"undefined"===typeof h.dataPoints[l].x&&(h.dataPoints[l].x=l);h.dataPoints[l].x.getTime?
+(k=!0,d=h.dataPoints[l].x.getTime()):d=h.dataPoints[l].x;(e=h.dataPoints[l].y)&&e.length&&(f=Math.min.apply(null,e),g=Math.max.apply(null,e));d<c.min&&(c.min=d);d>c.max&&(c.max=d);f<b.min&&(b.min=f);g>b.max&&(b.max=g);if(0<l){var s=d-h.dataPoints[l-1].x;0>s&&(s*=-1);c.minDiff>s&&0!==s&&(c.minDiff=s)}if(!(d<q)||r){if(!r&&(r=!0,0<l)){l-=2;continue}if(d>n&&!m)m=!0;else if(d>n&&m)continue;h.dataPoints[l].label&&(a.axisX.labels[d]=h.dataPoints[l].label);d<c.viewPortMin&&(c.viewPortMin=d);d>c.viewPortMax&&
+(c.viewPortMax=d);null!==e&&(f<b.viewPortMin&&(b.viewPortMin=f),g>b.viewPortMax&&(b.viewPortMax=g))}}this.plotInfo.axisXValueType=h.xValueType=k?"dateTime":"number"}};v.prototype.getDataPointAtXY=function(a,b,c){c=c||!1;for(var d=[],e=this._dataInRenderedOrder.length-1;0<=e;e--){var f=null;(f=this._dataInRenderedOrder[e].getDataPointAtXY(a,b,c))&&d.push(f)}a=null;b=!1;for(c=0;c<d.length;c++)if("line"===d[c].dataSeries.type||"stepLine"===d[c].dataSeries.type||"area"===d[c].dataSeries.type||"stepArea"===
+d[c].dataSeries.type)if(e=T("markerSize",d[c].dataPoint,d[c].dataSeries)||8,d[c].distance<=e/2){b=!0;break}for(c=0;c<d.length;c++)b&&"line"!==d[c].dataSeries.type&&"stepLine"!==d[c].dataSeries.type&&"area"!==d[c].dataSeries.type&&"stepArea"!==d[c].dataSeries.type||(a?d[c].distance<=a.distance&&(a=d[c]):a=d[c]);return a};v.prototype.getObjectAtXY=function(a,b,c){var d=null;if(c=this.getDataPointAtXY(a,b,c||!1))d=c.dataSeries.dataPointIds[c.dataPointIndex];else if(t)d=ta(a,b,this._eventManager.ghostCtx);
+else for(c=0;c<this.legend.items.length;c++){var e=this.legend.items[c];a>=e.x1&&(a<=e.x2&&b>=e.y1&&b<=e.y2)&&(d=e.id)}return d};v.prototype.getAutoFontSize=function(a,b,c){a/=400;return Math.round(Math.min(this.width,this.height)*a)};v.prototype.resetOverlayedCanvas=function(){this.overlaidCanvasCtx.clearRect(0,0,this.width,this.height)};v.prototype.clearCanvas=function(){this.ctx.clearRect(0,0,this.width,this.height);this.backgroundColor&&(this.ctx.fillStyle=this.backgroundColor,this.ctx.fillRect(0,
+0,this.width,this.height))};v.prototype.attachEvent=function(a){this._events.push(a)};v.prototype._touchEventHandler=function(a){if(a.changedTouches&&this.interactivityEnabled){var b=[],c=a.changedTouches,d=c?c[0]:a,e=null;switch(a.type){case "touchstart":case "MSPointerDown":b=["mousemove","mousedown"];this._lastTouchData=ia(d);this._lastTouchData.time=new Date;break;case "touchmove":case "MSPointerMove":b=["mousemove"];break;case "touchend":case "MSPointerUp":b="touchstart"===this._lastTouchEventType||
+"MSPointerDown"===this._lastTouchEventType?["mouseup","click"]:["mouseup"];break;default:return}if(!(c&&1<c.length)){e=ia(d);e.time=new Date;try{var f=e.y-this._lastTouchData.y,g=e.time-this._lastTouchData.time;if(15<Math.abs(f)&&(this._lastTouchData.scroll||200>g)){this._lastTouchData.scroll=!0;var k=window.parent||window;k&&k.scrollBy&&k.scrollBy(0,-f)}}catch(p){}this._lastTouchEventType=a.type;if(this._lastTouchData.scroll&&this.zoomEnabled)this.isDrag&&this.resetOverlayedCanvas(),this.isDrag=
+!1;else for(c=0;c<b.length;c++)e=b[c],f=document.createEvent("MouseEvent"),f.initMouseEvent(e,!0,!0,window,1,d.screenX,d.screenY,d.clientX,d.clientY,!1,!1,!1,!1,0,null),d.target.dispatchEvent(f),a.preventManipulation&&a.preventManipulation(),a.preventDefault&&a.preventDefault()}}};v.prototype._mouseEventHandler=function(a){if(this.interactivityEnabled)if(this._ignoreNextEvent)this._ignoreNextEvent=!1;else{a.preventManipulation&&a.preventManipulation();a.preventDefault&&a.preventDefault();"undefined"===
+typeof a.target&&a.srcElement&&(a.target=a.srcElement);var b=ia(a),c=a.type,d,e;a.which?e=3==a.which:a.button&&(e=2==a.button);if(!e){if(v.capturedEventParam)d=v.capturedEventParam,"mouseup"===c&&(v.capturedEventParam=null,d.chart.overlaidCanvas.releaseCapture?d.chart.overlaidCanvas.releaseCapture():document.body.removeEventListener("mouseup",d.chart._mouseEventHandler,!1)),d.hasOwnProperty(c)&&d[c].call(d.context,b.x,b.y);else if(this._events){for(e=0;e<this._events.length;e++)if(this._events[e].hasOwnProperty(c)){d=
+this._events[e];var f=d.bounds;if(b.x>=f.x1&&b.x<=f.x2&&b.y>=f.y1&&b.y<=f.y2){d[c].call(d.context,b.x,b.y);"mousedown"===c&&!0===d.capture?(v.capturedEventParam=d,this.overlaidCanvas.setCapture?this.overlaidCanvas.setCapture():document.body.addEventListener("mouseup",this._mouseEventHandler,!1)):"mouseup"===c&&(d.chart.overlaidCanvas.releaseCapture?d.chart.overlaidCanvas.releaseCapture():document.body.removeEventListener("mouseup",this._mouseEventHandler,!1));break}else d=null}a.target.style.cursor=
+d&&d.cursor?d.cursor:this._defaultCursor}this._toolTip&&this._toolTip.enabled&&(c=this.plotArea,(b.x<c.x1||b.x>c.x2||b.y<c.y1||b.y>c.y2)&&this._toolTip.hide());this.isDrag&&this.zoomEnabled||!this._eventManager||this._eventManager.mouseEventHandler(a)}}};v.prototype._plotAreaMouseDown=function(a,b){this.isDrag=!0;this.dragStartPoint="none"!==this.plotInfo.axisPlacement?{x:a,y:b,xMinimum:this.axisX.minimum,xMaximum:this.axisX.maximum}:{x:a,y:b}};v.prototype._plotAreaMouseUp=function(a,b){var c,d;if(("normal"===
+this.plotInfo.axisPlacement||"xySwapped"===this.plotInfo.axisPlacement)&&this.isDrag){var e=0,e=this.axisX.lineCoordinates,e="xySwapped"===this.plotInfo.axisPlacement?b-this.dragStartPoint.y:this.dragStartPoint.x-a;Math.abs(this.axisX.maximum-this.axisX.minimum);if(2<Math.abs(e)){if(this.panEnabled)e=!1,d=0,this.axisX.sessionVariables.internalMinimum<this.axisX._absoluteMinimum?(d=this.axisX._absoluteMinimum-this.axisX.sessionVariables.internalMinimum,this.axisX.sessionVariables.internalMinimum+=
+d,this.axisX.sessionVariables.internalMaximum+=d,e=!0):this.axisX.sessionVariables.internalMaximum>this.axisX._absoluteMaximum&&(d=this.axisX.sessionVariables.internalMaximum-this.axisX._absoluteMaximum,this.axisX.sessionVariables.internalMaximum-=d,this.axisX.sessionVariables.internalMinimum-=d,e=!0),e&&this.render();else if(this.zoomEnabled){this.resetOverlayedCanvas();if(!this.dragStartPoint)return;"xySwapped"===this.plotInfo.axisPlacement?(c=Math.min(this.dragStartPoint.y,b),d=Math.max(this.dragStartPoint.y,
+b),1<Math.abs(c-d)&&(e=this.axisX.lineCoordinates,d=this.axisX.maximum-(this.axisX.maximum-this.axisX.minimum)/e.height*(d-e.y1),e=this.axisX.maximum-(this.axisX.maximum-this.axisX.minimum)/e.height*(c-e.y1),d=Math.max(d,this.axisX.dataInfo.min),e=Math.min(e,this.axisX.dataInfo.max),Math.abs(e-d)>2*Math.abs(this.axisX.dataInfo.minDiff)&&(this.axisX.sessionVariables.internalMinimum=d,this.axisX.sessionVariables.internalMaximum=e,this.render()))):"normal"===this.plotInfo.axisPlacement&&(d=Math.min(this.dragStartPoint.x,
+a),c=Math.max(this.dragStartPoint.x,a),1<Math.abs(d-c)&&(e=this.axisX.lineCoordinates,d=(this.axisX.maximum-this.axisX.minimum)/e.width*(d-e.x1)+this.axisX.minimum,e=(this.axisX.maximum-this.axisX.minimum)/e.width*(c-e.x1)+this.axisX.minimum,d=Math.max(d,this.axisX.dataInfo.min),e=Math.min(e,this.axisX.dataInfo.max),Math.abs(e-d)>2*Math.abs(this.axisX.dataInfo.minDiff)&&(this.axisX.sessionVariables.internalMinimum=d,this.axisX.sessionVariables.internalMaximum=e,this.render())))}this._ignoreNextEvent=
+!0;this.zoomEnabled&&"none"===this._zoomButton.style.display&&(ka(this._zoomButton,this._resetButton),M(this,this._zoomButton,"pan"),M(this,this._resetButton,"reset"))}}this.isDrag=!1};v.prototype._plotAreaMouseMove=function(a,b){if(this.isDrag&&"none"!==this.plotInfo.axisPlacement){var c=0,d=0,d=this.axisX.lineCoordinates;"xySwapped"===this.plotInfo.axisPlacement?(c=b-this.dragStartPoint.y,d=Math.abs(this.axisX.maximum-this.axisX.minimum)/d.height*c):(c=this.dragStartPoint.x-a,d=Math.abs(this.axisX.maximum-
+this.axisX.minimum)/d.width*c);2<Math.abs(c)&&8>Math.abs(c)&&(this.panEnabled||this.zoomEnabled)?this._toolTip.hide():!this._toolTip.enabled||(this.panEnabled||this.zoomEnabled)||this._toolTip.mouseMoveHandler(a,b);if(2<Math.abs(c)&&(this.panEnabled||this.zoomEnabled))if(this.panEnabled){this.axisX.sessionVariables.internalMinimum=this.dragStartPoint.xMinimum+d;this.axisX.sessionVariables.internalMaximum=this.dragStartPoint.xMaximum+d;c=0;this.axisX.sessionVariables.internalMinimum<this.axisX._absoluteMinimum-
+Y(this.axisX.interval,this.axisX.intervalType)?(c=this.axisX._absoluteMinimum-Y(this.axisX.interval,this.axisX.intervalType)-this.axisX.sessionVariables.internalMinimum,this.axisX.sessionVariables.internalMinimum+=c,this.axisX.sessionVariables.internalMaximum+=c):this.axisX.sessionVariables.internalMaximum>this.axisX._absoluteMaximum+Y(this.axisX.interval,this.axisX.intervalType)&&(c=this.axisX.sessionVariables.internalMaximum-(this.axisX._absoluteMaximum+Y(this.axisX.interval,this.axisX.intervalType)),
+this.axisX.sessionVariables.internalMaximum-=c,this.axisX.sessionVariables.internalMinimum-=c);var e=this;clearTimeout(this._panTimerId);this._panTimerId=setTimeout(function(){e.render()},0)}else this.zoomEnabled&&(c=this.plotArea,this.resetOverlayedCanvas(),d=this.overlaidCanvasCtx.globalAlpha,this.overlaidCanvasCtx.globalAlpha=0.7,this.overlaidCanvasCtx.fillStyle="#A0ABB8","xySwapped"===this.plotInfo.axisPlacement?this.overlaidCanvasCtx.fillRect(c.x1,this.dragStartPoint.y,c.x2-c.x1,b-this.dragStartPoint.y):
+"normal"===this.plotInfo.axisPlacement&&this.overlaidCanvasCtx.fillRect(this.dragStartPoint.x,c.y1,a-this.dragStartPoint.x,c.y2-c.y1),this.overlaidCanvasCtx.globalAlpha=d)}else this._toolTip.enabled&&this._toolTip.mouseMoveHandler(a,b)};v.prototype.preparePlotArea=function(){var a=this.plotArea,b=this.axisY?this.axisY:this.axisY2;!t&&(0<a.x1||0<a.y1)&&a.ctx.translate(a.x1,a.y1);this.axisX&&b?(a.x1=this.axisX.lineCoordinates.x1<this.axisX.lineCoordinates.x2?this.axisX.lineCoordinates.x1:b.lineCoordinates.x1,
+a.y1=this.axisX.lineCoordinates.y1<b.lineCoordinates.y1?this.axisX.lineCoordinates.y1:b.lineCoordinates.y1,a.x2=this.axisX.lineCoordinates.x2>b.lineCoordinates.x2?this.axisX.lineCoordinates.x2:b.lineCoordinates.x2,a.y2=this.axisX.lineCoordinates.y2>this.axisX.lineCoordinates.y1?this.axisX.lineCoordinates.y2:b.lineCoordinates.y2,a.width=a.x2-a.x1,a.height=a.y2-a.y1):(b=this.layoutManager.getFreeSpace(),a.x1=b.x1,a.x2=b.x2,a.y1=b.y1,a.y2=b.y2,a.width=b.width,a.height=b.height);t||(a.canvas.width=a.width,
+a.canvas.height=a.height,a.canvas.style.left=a.x1+"px",a.canvas.style.top=a.y1+"px",(0<a.x1||0<a.y1)&&a.ctx.translate(-a.x1,-a.y1))};v.prototype.getPixelCoordinatesOnPlotArea=function(a,b){return{x:this.axisX.getPixelCoordinatesOnAxis(a).x,y:this.axisY.getPixelCoordinatesOnAxis(b).y}};v.prototype.renderIndexLabels=function(a){a=a||this.plotArea.ctx;a.textBaseline="middle";for(var b=this.plotArea,c=0;c<this._indexLabels.length;c++){var d=this._indexLabels[c],e,f,g;a.fillStyle=T("indexLabelFontColor",
+d.dataPoint,d.dataSeries);a.font=ua("indexLabel",d.dataPoint,d.dataSeries);var k=this.replaceKeywordsWithValue(T("indexLabel",d.dataPoint,d.dataSeries),d.dataPoint,d.dataSeries,null,d.indexKeyword),p=a.measureText(k).width,h=T("indexLabelFontSize",d.dataPoint,d.dataSeries),l=T("indexLabelPlacement",d.dataPoint,d.dataSeries),r=T("indexLabelOrientation",d.dataPoint,d.dataSeries),m=g=0,q=0,n=0,n=m=q=0,s=d.direction,m=d.dataSeries.axisX,n=d.dataSeries.axisY;d.dataPoint.x<m.minimum||(d.dataPoint.x>m.maximum||
+d.dataPoint.y<n.minimum||d.dataPoint.y>n.maximum)||("column"===d.chartType||"stackedColumn"===d.chartType||"stackedColumn100"===d.chartType||"bar"===d.chartType||"stackedBar"===d.chartType||"stackedBar100"===d.chartType||"candlestick"===d.chartType||"ohlc"===d.chartType||"rangeColumn"===d.chartType||"rangeBar"===d.chartType?(m=n=5,Math.abs(d.bounds.x1,d.bounds.x2),Math.abs(d.bounds.y1,d.bounds.y2),"normal"===this.plotInfo.axisPlacement?("inside"!==l?(m=b.y1,q=b.y2):(m=d.bounds.y1,q=d.bounds.y2),"horizontal"===
+r?(e=d.point.x-p/2,f=0<=s?d.point.y-h/2-n<m+h/2?"auto"===l?Math.min(Math.max(d.point.y,m)+h/2+1,q-h/2-n):Math.min(m+h/2+1,q-h/2-n):Math.min(d.point.y-h/2-n+1,q-h/2-n):d.point.y+h/2+n>q-h/2-1?"auto"===l?Math.max(Math.min(d.point.y,q)-h/2-1,m+h/2+n):Math.max(q-h/2-1,m+h/2+n):Math.max(d.point.y+h/2+n,m+h/2+n)):"vertical"===r&&(e=d.point.x,f=0<=s?d.point.y-n<m+p+1?"auto"===l?Math.min(Math.max(d.point.y,m)+p+1,q):Math.min(m+p+1,q):Math.min(d.point.y-n,q-1):d.point.y+p+n>q-1?"auto"===l?Math.max(Math.min(d.point.y,
+q)-n,m):Math.max(q-1,m):Math.max(d.point.y+p+n,m),g=-90)):"xySwapped"===this.plotInfo.axisPlacement&&("inside"!==l?(n=b.x1,q=b.x2):(n=d.bounds.x1,q=d.bounds.x2),"horizontal"===r?(f=d.point.y,e=0<=s?d.point.x+m>q-p?"auto"===l?Math.max(Math.min(d.point.x,q)-p,n):Math.max(q-p,n):Math.max(d.point.x+m,n):d.point.x-p-m<n?"auto"===l?Math.min(Math.max(d.point.x,n)+1,q):Math.min(n+1,q):Math.min(d.point.x-p-m,q)):"vertical"===r&&(f=d.point.y+p/2,e=0<=s?d.point.x+h/2+m>q-h/2?"auto"===l?Math.max(Math.min(d.point.x,
+q)-h/2,n):Math.max(q-h/2,n):Math.max(d.point.x+h/2+m,n):d.point.x-h/2-m<n+h/2?"auto"===l?Math.min(Math.max(d.point.x,n)+h/2,q+h/2):Math.min(n+h/2,q+h/2):Math.min(d.point.x-h/2-m,q+h/2),g=-90))):(n=5,"horizontal"===r?(e=d.point.x-p/2,"bubble"===d.chartType&&(n=-h/2),f=0<s?Math.max(d.point.y-h/2-n,b.y1+h/2):Math.min(d.point.y+h/2+n,b.y2-h/2)):"vertical"===r&&(e=d.point.x,"bubble"===d.chartType&&(n=-p/2),f=0<s?Math.max(d.point.y-n,b.y1+p):Math.min(d.point.y+p+n,b.y2),g=-90)),a.save(),a.translate(e,f),
+a.rotate(Math.PI/180*g),a.fillText(k,0,0),a.restore())}return{source:a,dest:this.plotArea.ctx,animationCallback:y.fadeInAnimation,easingFunction:y.easing.easeInQuad,animationBase:0,startTimePercent:0.7}};v.prototype.renderLine=function(a){var b=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var c=this._eventManager.ghostCtx;b.save();var d=this.plotArea;b.beginPath();b.rect(d.x1,d.y1,d.width,d.height);b.clip();for(var d=[],e=0;e<a.dataSeriesIndexes.length;e++){var f=a.dataSeriesIndexes[e],
+g=this.data[f];b.lineWidth=g.lineThickness;var k=g.dataPoints,p=g.id;this._eventManager.objectMap[p]={objectType:"dataSeries",dataSeriesIndex:f};p=C(p);c.strokeStyle=p;c.lineWidth=0<g.lineThickness?Math.max(g.lineThickness,4):0;p=g._colorSet[0];b.strokeStyle=p;var h=!0,l=0,r,m;b.beginPath();if(0<k.length){for(var q=!1,l=0;l<k.length;l++)if(r=k[l].x.getTime?k[l].x.getTime():k[l].x,!(r<a.axisX.dataInfo.viewPortMin||r>a.axisX.dataInfo.viewPortMax))if("number"!==typeof k[l].y)0<l&&(b.stroke(),t&&c.stroke()),
+q=!0;else{r=a.axisX.conversionParameters.reference+a.axisX.conversionParameters.pixelPerUnit*(r-a.axisX.conversionParameters.minimum)+0.5<<0;m=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(k[l].y-a.axisY.conversionParameters.minimum)+0.5<<0;var n=g.dataPointIds[l];this._eventManager.objectMap[n]={id:n,objectType:"dataPoint",dataSeriesIndex:f,dataPointIndex:l,x1:r,y1:m};h||q?(b.beginPath(),b.moveTo(r,m),t&&(c.beginPath(),c.moveTo(r,m)),q=h=!1):(b.lineTo(r,m),t&&
+c.lineTo(r,m),0==l%500&&(b.stroke(),b.beginPath(),b.moveTo(r,m),t&&(c.stroke(),c.beginPath(),c.moveTo(r,m))));if(0<k[l].markerSize||0<g.markerSize){var s=g.getMarkerProperties(l,r,m,b);d.push(s);n=C(n);t&&d.push({x:r,y:m,ctx:c,type:s.type,size:s.size,color:n,borderColor:n,borderThickness:s.borderThickness})}(k[l].indexLabel||g.indexLabel)&&this._indexLabels.push({chartType:"line",dataPoint:k[l],dataSeries:g,point:{x:r,y:m},direction:0<=k[l].y?1:-1,color:p})}b.stroke();t&&c.stroke()}}J.drawMarkers(d);
+b.restore();b.beginPath();t&&c.beginPath();return{source:b,dest:this.plotArea.ctx,animationCallback:y.xClipAnimation,easingFunction:y.easing.linear,animationBase:0}}};v.prototype.renderStepLine=function(a){var b=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var c=this._eventManager.ghostCtx;b.save();var d=this.plotArea;b.beginPath();b.rect(d.x1,d.y1,d.width,d.height);b.clip();for(var d=[],e=0;e<a.dataSeriesIndexes.length;e++){var f=a.dataSeriesIndexes[e],g=this.data[f];
+b.lineWidth=g.lineThickness;var k=g.dataPoints,p=g.id;this._eventManager.objectMap[p]={objectType:"dataSeries",dataSeriesIndex:f};p=C(p);c.strokeStyle=p;c.lineWidth=0<g.lineThickness?Math.max(g.lineThickness,4):0;p=g._colorSet[0];b.strokeStyle=p;var h=!0,l=0,r,m;b.beginPath();if(0<k.length){for(var q=!1,l=0;l<k.length;l++)if(r=k[l].getTime?k[l].x.getTime():k[l].x,!(r<a.axisX.dataInfo.viewPortMin||r>a.axisX.dataInfo.viewPortMax))if("number"!==typeof k[l].y)0<l&&(b.stroke(),t&&c.stroke()),q=!0;else{var n=
+m;r=a.axisX.conversionParameters.reference+a.axisX.conversionParameters.pixelPerUnit*(r-a.axisX.conversionParameters.minimum)+0.5<<0;m=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(k[l].y-a.axisY.conversionParameters.minimum)+0.5<<0;var s=g.dataPointIds[l];this._eventManager.objectMap[s]={id:s,objectType:"dataPoint",dataSeriesIndex:f,dataPointIndex:l,x1:r,y1:m};h||q?(b.beginPath(),b.moveTo(r,m),t&&(c.beginPath(),c.moveTo(r,m)),q=h=!1):(b.lineTo(r,n),t&&c.lineTo(r,
+n),b.lineTo(r,m),t&&c.lineTo(r,m),0==l%500&&(b.stroke(),b.beginPath(),b.moveTo(r,m),t&&(c.stroke(),c.beginPath(),c.moveTo(r,m))));if(0<k[l].markerSize||0<g.markerSize)n=g.getMarkerProperties(l,r,m,b),d.push(n),s=C(s),t&&d.push({x:r,y:m,ctx:c,type:n.type,size:n.size,color:s,borderColor:s,borderThickness:n.borderThickness});(k[l].indexLabel||g.indexLabel)&&this._indexLabels.push({chartType:"stepLine",dataPoint:k[l],dataSeries:g,point:{x:r,y:m},direction:0<=k[l].y?1:-1,color:p})}b.stroke();t&&c.stroke()}}J.drawMarkers(d);
+b.restore();b.beginPath();t&&c.beginPath();return{source:b,dest:this.plotArea.ctx,animationCallback:y.xClipAnimation,easingFunction:y.easing.linear,animationBase:0}}};v.prototype.renderSpline=function(a){function b(a){a=fa(a,2);if(0<a.length){c.beginPath();t&&d.beginPath();c.moveTo(a[0].x,a[0].y);t&&d.moveTo(a[0].x,a[0].y);for(var b=0;b<a.length-3;b+=3)c.bezierCurveTo(a[b+1].x,a[b+1].y,a[b+2].x,a[b+2].y,a[b+3].x,a[b+3].y),t&&d.bezierCurveTo(a[b+1].x,a[b+1].y,a[b+2].x,a[b+2].y,a[b+3].x,a[b+3].y),0<
+b&&0===b%3E3&&(c.stroke(),c.beginPath(),c.moveTo(a[b+3].x,a[b+3].y),t&&(d.stroke(),d.beginPath(),d.moveTo(a[b+3].x,a[b+3].y)));c.stroke();t&&d.stroke()}}var c=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var d=this._eventManager.ghostCtx;c.save();var e=this.plotArea;c.beginPath();c.rect(e.x1,e.y1,e.width,e.height);c.clip();for(var e=[],f=0;f<a.dataSeriesIndexes.length;f++){var g=a.dataSeriesIndexes[f],k=this.data[g];c.lineWidth=k.lineThickness;var p=k.dataPoints,h=k.id;
+this._eventManager.objectMap[h]={objectType:"dataSeries",dataSeriesIndex:g};h=C(h);d.strokeStyle=h;d.lineWidth=0<k.lineThickness?Math.max(k.lineThickness,4):0;h=k._colorSet[0];c.strokeStyle=h;var l=0,r,m,q=[];c.beginPath();if(0<p.length)for(l=0;l<p.length;l++)if(r=p[l].getTime?p[l].x.getTime():p[l].x,!(r<a.axisX.dataInfo.viewPortMin||r>a.axisX.dataInfo.viewPortMax))if("number"!==typeof p[l].y)0<l&&(b(q),q=[]);else{r=a.axisX.conversionParameters.reference+a.axisX.conversionParameters.pixelPerUnit*
+(r-a.axisX.conversionParameters.minimum)+0.5<<0;m=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(p[l].y-a.axisY.conversionParameters.minimum)+0.5<<0;var n=k.dataPointIds[l];this._eventManager.objectMap[n]={id:n,objectType:"dataPoint",dataSeriesIndex:g,dataPointIndex:l,x1:r,y1:m};q[q.length]={x:r,y:m};if(0<p[l].markerSize||0<k.markerSize){var s=k.getMarkerProperties(l,r,m,c);e.push(s);n=C(n);t&&e.push({x:r,y:m,ctx:d,type:s.type,size:s.size,color:n,borderColor:n,borderThickness:s.borderThickness})}(p[l].indexLabel||
+k.indexLabel)&&this._indexLabels.push({chartType:"spline",dataPoint:p[l],dataSeries:k,point:{x:r,y:m},direction:0<=p[l].y?1:-1,color:h})}b(q)}J.drawMarkers(e);c.restore();c.beginPath();t&&d.beginPath();return{source:c,dest:this.plotArea.ctx,animationCallback:y.xClipAnimation,easingFunction:y.easing.linear,animationBase:0}}};var F=function(a,b,c,d,e,f,g,k,p,h,l,r,m){"undefined"===typeof m&&(m=1);g=g||0;k=k||"black";var q=15<d-b&&15<e-c?8:0.35*Math.min(d-b,e-c);a.beginPath();a.moveTo(b,c);a.save();
+a.fillStyle=f;a.globalAlpha=m;a.fillRect(b,c,d-b,e-c);a.globalAlpha=1;0<g&&(m=0===g%2?0:0.5,a.beginPath(),a.lineWidth=g,a.strokeStyle=k,a.moveTo(b,c),a.rect(b-m,c-m,d-b+2*m,e-c+2*m),a.stroke());a.restore();!0===p&&(a.save(),a.beginPath(),a.moveTo(b,c),a.lineTo(b+q,c+q),a.lineTo(d-q,c+q),a.lineTo(d,c),a.closePath(),g=a.createLinearGradient((d+b)/2,c+q,(d+b)/2,c),g.addColorStop(0,f),g.addColorStop(1,"rgba(255, 255, 255, .4)"),a.fillStyle=g,a.fill(),a.restore());!0===h&&(a.save(),a.beginPath(),a.moveTo(b,
+e),a.lineTo(b+q,e-q),a.lineTo(d-q,e-q),a.lineTo(d,e),a.closePath(),g=a.createLinearGradient((d+b)/2,e-q,(d+b)/2,e),g.addColorStop(0,f),g.addColorStop(1,"rgba(255, 255, 255, .4)"),a.fillStyle=g,a.fill(),a.restore());!0===l&&(a.save(),a.beginPath(),a.moveTo(b,c),a.lineTo(b+q,c+q),a.lineTo(b+q,e-q),a.lineTo(b,e),a.closePath(),g=a.createLinearGradient(b+q,(e+c)/2,b,(e+c)/2),g.addColorStop(0,f),g.addColorStop(1,"rgba(255, 255, 255, 0.1)"),a.fillStyle=g,a.fill(),a.restore());!0===r&&(a.save(),a.beginPath(),
+a.moveTo(d,c),a.lineTo(d-q,c+q),a.lineTo(d-q,e-q),a.lineTo(d,e),g=a.createLinearGradient(d-q,(e+c)/2,d,(e+c)/2),g.addColorStop(0,f),g.addColorStop(1,"rgba(255, 255, 255, 0.1)"),a.fillStyle=g,g.addColorStop(0,f),g.addColorStop(1,"rgba(255, 255, 255, 0.1)"),a.fillStyle=g,a.fill(),a.closePath(),a.restore())};v.prototype.renderColumn=function(a){var b=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var c=null,d=this.plotArea,e=0,f,g,k,p=a.axisY.conversionParameters.reference+
+a.axisY.conversionParameters.pixelPerUnit*(0-a.axisY.conversionParameters.minimum)<<0,e=Math.min(0.15*this.width,0.9*(this.plotArea.width/a.plotType.totalDataSeries))<<0,h=a.axisX.dataInfo.minDiff,l=0.9*(d.width/Math.abs(a.axisX.maximum-a.axisX.minimum)*Math.abs(h)/a.plotType.totalDataSeries)<<0;l>e?l=e:Infinity===h?l=e:1>l&&(l=1);b.save();t&&this._eventManager.ghostCtx.save();b.beginPath();b.rect(d.x1,d.y1,d.width,d.height);b.clip();t&&(this._eventManager.ghostCtx.rect(d.x1,d.y1,d.width,d.height),
+this._eventManager.ghostCtx.clip());for(d=0;d<a.dataSeriesIndexes.length;d++){var h=a.dataSeriesIndexes[d],r=this.data[h],m=r.dataPoints;if(0<m.length)for(var q=5<l&&r.bevelEnabled?!0:!1,e=0;e<m.length;e++)if(m[e].getTime?k=m[e].x.getTime():k=m[e].x,!(k<a.axisX.dataInfo.viewPortMin||k>a.axisX.dataInfo.viewPortMax)&&"number"===typeof m[e].y){f=a.axisX.conversionParameters.reference+a.axisX.conversionParameters.pixelPerUnit*(k-a.axisX.conversionParameters.minimum)+0.5<<0;g=a.axisY.conversionParameters.reference+
+a.axisY.conversionParameters.pixelPerUnit*(m[e].y-a.axisY.conversionParameters.minimum)+0.5<<0;f=f-a.plotType.totalDataSeries*l/2+(a.previousDataSeriesCount+d)*l<<0;var n=f+l<<0,s;0<=m[e].y?s=p:(s=g,g=p);g>s&&(s=g=s);c=m[e].color?m[e].color:r._colorSet[e%r._colorSet.length];F(b,f,g,n,s,c,0,null,q&&0<=m[e].y,0>m[e].y&&q,!1,!1,r.fillOpacity);c=r.dataPointIds[e];this._eventManager.objectMap[c]={id:c,objectType:"dataPoint",dataSeriesIndex:h,dataPointIndex:e,x1:f,y1:g,x2:n,y2:s};c=C(c);t&&F(this._eventManager.ghostCtx,
+f,g,n,s,c,0,null,!1,!1,!1,!1);(m[e].indexLabel||r.indexLabel)&&this._indexLabels.push({chartType:"column",dataPoint:m[e],dataSeries:r,point:{x:f+(n-f)/2,y:0<=m[e].y?g:s},direction:0<=m[e].y?1:-1,bounds:{x1:f,y1:Math.min(g,s),x2:n,y2:Math.max(g,s)},color:c})}}b.restore();t&&this._eventManager.ghostCtx.restore();a=Math.min(p,a.axisY.boundingRect.y2);return{source:b,dest:this.plotArea.ctx,animationCallback:y.yScaleAnimation,easingFunction:y.easing.easeOutQuart,animationBase:a}}};v.prototype.renderStackedColumn=
+function(a){var b=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var c=null,d=this.plotArea,e=[],f=[],g=0,k,p=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(0-a.axisY.conversionParameters.minimum)<<0,g=0.15*this.width<<0,h=a.axisX.dataInfo.minDiff,l=0.9*(d.width/Math.abs(a.axisX.maximum-a.axisX.minimum)*Math.abs(h)/a.plotType.plotUnits.length)<<0;l>g?l=g:Infinity===h?l=g:1>l&&(l=1);b.save();t&&this._eventManager.ghostCtx.save();b.beginPath();
+b.rect(d.x1,d.y1,d.width,d.height);b.clip();t&&(this._eventManager.ghostCtx.rect(d.x1,d.y1,d.width,d.height),this._eventManager.ghostCtx.clip());for(h=0;h<a.dataSeriesIndexes.length;h++){var r=a.dataSeriesIndexes[h],m=this.data[r],q=m.dataPoints;if(0<q.length){var n=5<l&&m.bevelEnabled?!0:!1;b.strokeStyle="#4572A7 ";for(g=0;g<q.length;g++)if(c=q[g].x.getTime?q[g].x.getTime():q[g].x,!(c<a.axisX.dataInfo.viewPortMin||c>a.axisX.dataInfo.viewPortMax)&&"number"===typeof q[g].y){d=a.axisX.conversionParameters.reference+
+a.axisX.conversionParameters.pixelPerUnit*(c-a.axisX.conversionParameters.minimum)+0.5<<0;k=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(q[g].y-a.axisY.conversionParameters.minimum);var s=d-a.plotType.plotUnits.length*l/2+a.index*l<<0,B=s+l<<0,u;if(0<=q[g].y){var x=e[c]?e[c]:0;k-=x;u=p-x;e[c]=x+(u-k)}else x=f[c]?f[c]:0,u=k+x,k=p+x,f[c]=x+(u-k);c=q[g].color?q[g].color:m._colorSet[g%m._colorSet.length];F(b,s,k,B,u,c,0,null,n&&0<=q[g].y,0>q[g].y&&n,!1,!1,m.fillOpacity);
+c=m.dataPointIds[g];this._eventManager.objectMap[c]={id:c,objectType:"dataPoint",dataSeriesIndex:r,dataPointIndex:g,x1:s,y1:k,x2:B,y2:u};c=C(c);t&&F(this._eventManager.ghostCtx,s,k,B,u,c,0,null,!1,!1,!1,!1);(q[g].indexLabel||m.indexLabel)&&this._indexLabels.push({chartType:"stackedColumn",dataPoint:q[g],dataSeries:m,point:{x:d,y:0<=q[g].y?k:u},direction:0<=q[g].y?1:-1,bounds:{x1:s,y1:Math.min(k,u),x2:B,y2:Math.max(k,u)},color:c})}}}b.restore();t&&this._eventManager.ghostCtx.restore();a=Math.min(p,
+a.axisY.boundingRect.y2);return{source:b,dest:this.plotArea.ctx,animationCallback:y.yScaleAnimation,easingFunction:y.easing.easeOutQuart,animationBase:a}}};v.prototype.renderStackedColumn100=function(a){var b=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var c=null,d=this.plotArea,e=[],f=[],g=0,k,p=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(0-a.axisY.conversionParameters.minimum)<<0,g=0.15*this.width<<0,h=a.axisX.dataInfo.minDiff,
+l=0.9*(d.width/Math.abs(a.axisX.maximum-a.axisX.minimum)*Math.abs(h)/a.plotType.plotUnits.length)<<0;l>g?l=g:Infinity===h?l=g:1>l&&(l=1);b.save();t&&this._eventManager.ghostCtx.save();b.beginPath();b.rect(d.x1,d.y1,d.width,d.height);b.clip();t&&(this._eventManager.ghostCtx.rect(d.x1,d.y1,d.width,d.height),this._eventManager.ghostCtx.clip());for(h=0;h<a.dataSeriesIndexes.length;h++){var r=a.dataSeriesIndexes[h],m=this.data[r],q=m.dataPoints;if(0<q.length)for(var n=5<l&&m.bevelEnabled?!0:!1,g=0;g<q.length;g++)if(c=
+q[g].x.getTime?q[g].x.getTime():q[g].x,!(c<a.axisX.dataInfo.viewPortMin||c>a.axisX.dataInfo.viewPortMax)&&"number"===typeof q[g].y){d=a.axisX.conversionParameters.reference+a.axisX.conversionParameters.pixelPerUnit*(c-a.axisX.conversionParameters.minimum)+0.5<<0;k=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*((0!==a.dataPointYSums[c]?100*(q[g].y/a.dataPointYSums[c]):0)-a.axisY.conversionParameters.minimum);var s=d-a.plotType.plotUnits.length*l/2+a.index*l<<0,B=
+s+l<<0,u;if(0<=q[g].y){var x=e[c]?e[c]:0;k-=x;u=p-x;e[c]=x+(u-k)}else x=f[c]?f[c]:0,u=k+x,k=p+x,f[c]=x+(u-k);c=q[g].color?q[g].color:m._colorSet[g%m._colorSet.length];F(b,s,k,B,u,c,0,null,n&&0<=q[g].y,0>q[g].y&&n,!1,!1,m.fillOpacity);c=m.dataPointIds[g];this._eventManager.objectMap[c]={id:c,objectType:"dataPoint",dataSeriesIndex:r,dataPointIndex:g,x1:s,y1:k,x2:B,y2:u};c=C(c);t&&F(this._eventManager.ghostCtx,s,k,B,u,c,0,null,!1,!1,!1,!1);(q[g].indexLabel||m.indexLabel)&&this._indexLabels.push({chartType:"stackedColumn100",
+dataPoint:q[g],dataSeries:m,point:{x:d,y:0<=q[g].y?k:u},direction:0<=q[g].y?1:-1,bounds:{x1:s,y1:Math.min(k,u),x2:B,y2:Math.max(k,u)},color:c})}}b.restore();t&&this._eventManager.ghostCtx.restore();a=Math.min(p,a.axisY.boundingRect.y2);return{source:b,dest:this.plotArea.ctx,animationCallback:y.yScaleAnimation,easingFunction:y.easing.easeOutQuart,animationBase:a}}};v.prototype.renderBar=function(a){var b=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var c=null,d=this.plotArea,
+e=0,f,g,k,p=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(0-a.axisY.conversionParameters.minimum)<<0,e=Math.min(0.15*this.height,0.9*(this.plotArea.height/a.plotType.totalDataSeries))<<0,h=a.axisX.dataInfo.minDiff,l=0.9*(d.height/Math.abs(a.axisX.maximum-a.axisX.minimum)*Math.abs(h)/a.plotType.totalDataSeries)<<0;l>e?l=e:Infinity===h?l=e:1>l&&(l=1);b.save();t&&this._eventManager.ghostCtx.save();b.beginPath();b.rect(d.x1,d.y1,d.width,d.height);b.clip();t&&(this._eventManager.ghostCtx.rect(d.x1,
+d.y1,d.width,d.height),this._eventManager.ghostCtx.clip());for(d=0;d<a.dataSeriesIndexes.length;d++){var h=a.dataSeriesIndexes[d],r=this.data[h],m=r.dataPoints;if(0<m.length){var q=5<l&&r.bevelEnabled?!0:!1;b.strokeStyle="#4572A7 ";for(e=0;e<m.length;e++)if(m[e].getTime?k=m[e].x.getTime():k=m[e].x,!(k<a.axisX.dataInfo.viewPortMin||k>a.axisX.dataInfo.viewPortMax)&&"number"===typeof m[e].y){g=a.axisX.conversionParameters.reference+a.axisX.conversionParameters.pixelPerUnit*(k-a.axisX.conversionParameters.minimum)+
+0.5<<0;f=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(m[e].y-a.axisY.conversionParameters.minimum)+0.5<<0;g=g-a.plotType.totalDataSeries*l/2+(a.previousDataSeriesCount+d)*l<<0;var n=g+l<<0,s;0<=m[e].y?s=p:(s=f,f=p);c=m[e].color?m[e].color:r._colorSet[e%r._colorSet.length];F(b,s,g,f,n,c,0,null,q,!1,!1,!1,r.fillOpacity);c=r.dataPointIds[e];this._eventManager.objectMap[c]={id:c,objectType:"dataPoint",dataSeriesIndex:h,dataPointIndex:e,x1:s,y1:g,x2:f,y2:n};c=C(c);
+t&&F(this._eventManager.ghostCtx,s,g,f,n,c,0,null,!1,!1,!1,!1);this._indexLabels.push({chartType:"bar",dataPoint:m[e],dataSeries:r,point:{x:0<=m[e].y?f:s,y:g+(n-g)/2},direction:0<=m[e].y?1:-1,bounds:{x1:Math.min(s,f),y1:g,x2:Math.max(s,f),y2:n},color:c})}}}b.restore();t&&this._eventManager.ghostCtx.restore();a=Math.max(p,a.axisX.boundingRect.x2);return{source:b,dest:this.plotArea.ctx,animationCallback:y.xScaleAnimation,easingFunction:y.easing.easeOutQuart,animationBase:a}}};v.prototype.renderStackedBar=
+function(a){var b=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var c=null,d=this.plotArea,e=[],f=[],g=0,k,p=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(0-a.axisY.conversionParameters.minimum)<<0,g=0.15*this.height<<0,h=a.axisX.dataInfo.minDiff,l=0.9*(d.height/Math.abs(a.axisX.maximum-a.axisX.minimum)*Math.abs(h)/a.plotType.plotUnits.length)<<0;l>g?l=g:Infinity===h?l=g:1>l&&(l=1);b.save();t&&this._eventManager.ghostCtx.save();b.beginPath();
+b.rect(d.x1,d.y1,d.width,d.height);b.clip();t&&(this._eventManager.ghostCtx.rect(d.x1,d.y1,d.width,d.height),this._eventManager.ghostCtx.clip());for(h=0;h<a.dataSeriesIndexes.length;h++){var r=a.dataSeriesIndexes[h],m=this.data[r],q=m.dataPoints;if(0<q.length){var n=5<l&&m.bevelEnabled?!0:!1;b.strokeStyle="#4572A7 ";for(g=0;g<q.length;g++)if(c=q[g].x.getTime?q[g].x.getTime():q[g].x,!(c<a.axisX.dataInfo.viewPortMin||c>a.axisX.dataInfo.viewPortMax)&&"number"===typeof q[g].y){d=a.axisX.conversionParameters.reference+
+a.axisX.conversionParameters.pixelPerUnit*(c-a.axisX.conversionParameters.minimum)+0.5<<0;k=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(q[g].y-a.axisY.conversionParameters.minimum);var s=d-a.plotType.plotUnits.length*l/2+a.index*l<<0,B=s+l<<0,u;if(0<=q[g].y){var x=e[c]?e[c]:0;u=p+x;k+=x;e[c]=x+(k-u)}else x=f[c]?f[c]:0,u=k-x,k=p-x,f[c]=x+(k-u);c=q[g].color?q[g].color:m._colorSet[g%m._colorSet.length];F(b,u,s,k,B,c,0,null,n,!1,!1,!1,m.fillOpacity);c=m.dataPointIds[g];
+this._eventManager.objectMap[c]={id:c,objectType:"dataPoint",dataSeriesIndex:r,dataPointIndex:g,x1:u,y1:s,x2:k,y2:B};c=C(c);t&&F(this._eventManager.ghostCtx,u,s,k,B,c,0,null,!1,!1,!1,!1);this._indexLabels.push({chartType:"stackedBar",dataPoint:q[g],dataSeries:m,point:{x:0<=q[g].y?k:u,y:d},direction:0<=q[g].y?1:-1,bounds:{x1:Math.min(u,k),y1:s,x2:Math.max(u,k),y2:B},color:c})}}}b.restore();t&&this._eventManager.ghostCtx.restore();a=Math.max(p,a.axisX.boundingRect.x2);return{source:b,dest:this.plotArea.ctx,
+animationCallback:y.xScaleAnimation,easingFunction:y.easing.easeOutQuart,animationBase:a}}};v.prototype.renderStackedBar100=function(a){var b=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var c=null,d=this.plotArea,e=[],f=[],g=0,k,p=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(0-a.axisY.conversionParameters.minimum)<<0,g=0.15*this.height<<0,h=a.axisX.dataInfo.minDiff,l=0.9*(d.height/Math.abs(a.axisX.maximum-a.axisX.minimum)*Math.abs(h)/
+a.plotType.plotUnits.length)<<0;l>g?l=g:Infinity===h?l=g:1>l&&(l=1);b.save();t&&this._eventManager.ghostCtx.save();b.beginPath();b.rect(d.x1,d.y1,d.width,d.height);b.clip();t&&(this._eventManager.ghostCtx.rect(d.x1,d.y1,d.width,d.height),this._eventManager.ghostCtx.clip());for(h=0;h<a.dataSeriesIndexes.length;h++){var r=a.dataSeriesIndexes[h],m=this.data[r],q=m.dataPoints;if(0<q.length){var n=5<l&&m.bevelEnabled?!0:!1;b.strokeStyle="#4572A7 ";for(g=0;g<q.length;g++)if(c=q[g].x.getTime?q[g].x.getTime():
+q[g].x,!(c<a.axisX.dataInfo.viewPortMin||c>a.axisX.dataInfo.viewPortMax)&&"number"===typeof q[g].y){d=a.axisX.conversionParameters.reference+a.axisX.conversionParameters.pixelPerUnit*(c-a.axisX.conversionParameters.minimum)+0.5<<0;k=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*((0!==a.dataPointYSums[c]?100*(q[g].y/a.dataPointYSums[c]):0)-a.axisY.conversionParameters.minimum);var s=d-a.plotType.plotUnits.length*l/2+a.index*l<<0,B=s+l<<0,u;if(0<=q[g].y){var x=e[c]?
+e[c]:0;u=p+x;k+=x;e[c]=x+(k-u)}else x=f[c]?f[c]:0,u=k-x,k=p-x,f[c]=x+(k-u);c=q[g].color?q[g].color:m._colorSet[g%m._colorSet.length];F(b,u,s,k,B,c,0,null,n,!1,!1,!1,m.fillOpacity);c=m.dataPointIds[g];this._eventManager.objectMap[c]={id:c,objectType:"dataPoint",dataSeriesIndex:r,dataPointIndex:g,x1:u,y1:s,x2:k,y2:B};c=C(c);t&&F(this._eventManager.ghostCtx,u,s,k,B,c,0,null,!1,!1,!1,!1);this._indexLabels.push({chartType:"stackedBar100",dataPoint:q[g],dataSeries:m,point:{x:0<=q[g].y?k:u,y:d},direction:0<=
+q[g].y?1:-1,bounds:{x1:Math.min(u,k),y1:s,x2:Math.max(u,k),y2:B},color:c})}}}b.restore();t&&this._eventManager.ghostCtx.restore();a=Math.max(p,a.axisX.boundingRect.x2);return{source:b,dest:this.plotArea.ctx,animationCallback:y.xScaleAnimation,easingFunction:y.easing.easeOutQuart,animationBase:a}}};v.prototype.renderArea=function(a){function b(){x&&(0<h.lineThickness&&c.stroke(),0>=a.axisY.minimum&&0<=a.axisY.maximum?u=B:0>a.axisY.maximum?u=f.y1:0<a.axisY.minimum&&(u=e.y2),c.lineTo(q,u),c.lineTo(x.x,
+u),c.closePath(),c.globalAlpha=h.fillOpacity,c.fill(),c.globalAlpha=1,t&&(d.lineTo(q,u),d.lineTo(x.x,u),d.closePath(),d.fill()),c.beginPath(),c.moveTo(q,n),d.beginPath(),d.moveTo(q,n),x={x:q,y:n})}var c=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var d=this._eventManager.ghostCtx,e=a.axisX.lineCoordinates,f=a.axisY.lineCoordinates,g=[],k=this.plotArea;c.save();t&&d.save();c.beginPath();c.rect(k.x1,k.y1,k.width,k.height);c.clip();t&&(d.beginPath(),d.rect(k.x1,k.y1,k.width,
+k.height),d.clip());for(k=0;k<a.dataSeriesIndexes.length;k++){var p=a.dataSeriesIndexes[k],h=this.data[p],l=h.dataPoints,g=h.id;this._eventManager.objectMap[g]={objectType:"dataSeries",dataSeriesIndex:p};g=C(g);d.fillStyle=g;var g=[],r=!0,m=0,q,n,s,B=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(0-a.axisY.conversionParameters.minimum)+0.5<<0,u,x=null;if(0<l.length){var w=h._colorSet[m%h._colorSet.length];c.fillStyle=w;c.strokeStyle=w;c.lineWidth=h.lineThickness;
+for(var Q=!0;m<l.length;m++)if(s=l[m].x.getTime?l[m].x.getTime():l[m].x,!(s<a.axisX.dataInfo.viewPortMin||s>a.axisX.dataInfo.viewPortMax))if("number"!==typeof l[m].y)b(),Q=!0;else{q=a.axisX.conversionParameters.reference+a.axisX.conversionParameters.pixelPerUnit*(s-a.axisX.conversionParameters.minimum)+0.5<<0;n=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(l[m].y-a.axisY.conversionParameters.minimum)+0.5<<0;r||Q?(c.beginPath(),c.moveTo(q,n),x={x:q,y:n},t&&(d.beginPath(),
+d.moveTo(q,n)),Q=r=!1):(c.lineTo(q,n),t&&d.lineTo(q,n),0==m%250&&b());var G=h.dataPointIds[m];this._eventManager.objectMap[G]={id:G,objectType:"dataPoint",dataSeriesIndex:p,dataPointIndex:m,x1:q,y1:n};0!==l[m].markerSize&&(0<l[m].markerSize||0<h.markerSize)&&(s=h.getMarkerProperties(m,q,n,c),g.push(s),G=C(G),t&&g.push({x:q,y:n,ctx:d,type:s.type,size:s.size,color:G,borderColor:G,borderThickness:s.borderThickness}));(l[m].indexLabel||h.indexLabel)&&this._indexLabels.push({chartType:"area",dataPoint:l[m],
+dataSeries:h,point:{x:q,y:n},direction:0<=l[m].y?1:-1,color:w})}b();J.drawMarkers(g)}}c.restore();t&&this._eventManager.ghostCtx.restore();return{source:c,dest:this.plotArea.ctx,animationCallback:y.xClipAnimation,easingFunction:y.easing.linear,animationBase:0}}};v.prototype.renderSplineArea=function(a){function b(){var b=fa(u,2);if(0<b.length){c.beginPath();c.moveTo(b[0].x,b[0].y);t&&(d.beginPath(),d.moveTo(b[0].x,b[0].y));for(var g=0;g<b.length-3;g+=3)c.bezierCurveTo(b[g+1].x,b[g+1].y,b[g+2].x,b[g+
+2].y,b[g+3].x,b[g+3].y),t&&d.bezierCurveTo(b[g+1].x,b[g+1].y,b[g+2].x,b[g+2].y,b[g+3].x,b[g+3].y);0<h.lineThickness&&c.stroke();0>=a.axisY.minimum&&0<=a.axisY.maximum?s=n:0>a.axisY.maximum?s=f.y1:0<a.axisY.minimum&&(s=e.y2);B={x:b[0].x,y:b[0].y};c.lineTo(b[b.length-1].x,s);c.lineTo(B.x,s);c.closePath();c.globalAlpha=h.fillOpacity;c.fill();c.globalAlpha=1;t&&(d.lineTo(b[b.length-1].x,s),d.lineTo(B.x,s),d.closePath(),d.fill())}}var c=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var d=
+this._eventManager.ghostCtx,e=a.axisX.lineCoordinates,f=a.axisY.lineCoordinates,g=[],k=this.plotArea;c.save();t&&d.save();c.beginPath();c.rect(k.x1,k.y1,k.width,k.height);c.clip();t&&(d.beginPath(),d.rect(k.x1,k.y1,k.width,k.height),d.clip());for(k=0;k<a.dataSeriesIndexes.length;k++){var p=a.dataSeriesIndexes[k],h=this.data[p],l=h.dataPoints,g=h.id;this._eventManager.objectMap[g]={objectType:"dataSeries",dataSeriesIndex:p};g=C(g);d.fillStyle=g;var g=[],r=0,m,q,n=a.axisY.conversionParameters.reference+
+a.axisY.conversionParameters.pixelPerUnit*(0-a.axisY.conversionParameters.minimum)+0.5<<0,s,B=null,u=[];if(0<l.length){color=h._colorSet[r%h._colorSet.length];c.fillStyle=color;c.strokeStyle=color;for(c.lineWidth=h.lineThickness;r<l.length;r++)if(m=l[r].x.getTime?l[r].x.getTime():l[r].x,!(m<a.axisX.dataInfo.viewPortMin||m>a.axisX.dataInfo.viewPortMax))if("number"!==typeof l[r].y)0<r&&(b(),u=[]);else{m=a.axisX.conversionParameters.reference+a.axisX.conversionParameters.pixelPerUnit*(m-a.axisX.conversionParameters.minimum)+
+0.5<<0;q=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(l[r].y-a.axisY.conversionParameters.minimum)+0.5<<0;var x=h.dataPointIds[r];this._eventManager.objectMap[x]={id:x,objectType:"dataPoint",dataSeriesIndex:p,dataPointIndex:r,x1:m,y1:q};u[u.length]={x:m,y:q};if(0!==l[r].markerSize&&(0<l[r].markerSize||0<h.markerSize)){var w=h.getMarkerProperties(r,m,q,c);g.push(w);x=C(x);t&&g.push({x:m,y:q,ctx:d,type:w.type,size:w.size,color:x,borderColor:x,borderThickness:w.borderThickness})}(l[r].indexLabel||
+h.indexLabel)&&this._indexLabels.push({chartType:"splineArea",dataPoint:l[r],dataSeries:h,point:{x:m,y:q},direction:0<=l[r].y?1:-1,color:color})}b();J.drawMarkers(g)}}c.restore();t&&this._eventManager.ghostCtx.restore();return{source:c,dest:this.plotArea.ctx,animationCallback:y.xClipAnimation,easingFunction:y.easing.linear,animationBase:0}}};v.prototype.renderStepArea=function(a){function b(){x&&(0<h.lineThickness&&c.stroke(),0>=a.axisY.minimum&&0<=a.axisY.maximum?u=B:0>a.axisY.maximum?u=f.y1:0<a.axisY.minimum&&
+(u=e.y2),c.lineTo(q,u),c.lineTo(x.x,u),c.closePath(),c.globalAlpha=h.fillOpacity,c.fill(),c.globalAlpha=1,t&&(d.lineTo(q,u),d.lineTo(x.x,u),d.closePath(),d.fill()),c.beginPath(),c.moveTo(q,n),d.beginPath(),d.moveTo(q,n),x={x:q,y:n})}var c=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var d=this._eventManager.ghostCtx,e=a.axisX.lineCoordinates,f=a.axisY.lineCoordinates,g=[],k=this.plotArea;c.save();t&&d.save();c.beginPath();c.rect(k.x1,k.y1,k.width,k.height);c.clip();t&&
+(d.beginPath(),d.rect(k.x1,k.y1,k.width,k.height),d.clip());for(k=0;k<a.dataSeriesIndexes.length;k++){var p=a.dataSeriesIndexes[k],h=this.data[p],l=h.dataPoints,g=h.id;this._eventManager.objectMap[g]={objectType:"dataSeries",dataSeriesIndex:p};g=C(g);d.fillStyle=g;var g=[],r=!0,m=0,q,n,s,B=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(0-a.axisY.conversionParameters.minimum)+0.5<<0,u,x=null,w=!1;if(0<l.length){var Q=h._colorSet[m%h._colorSet.length];c.fillStyle=
+Q;c.strokeStyle=Q;for(c.lineWidth=h.lineThickness;m<l.length;m++)if(s=l[m].x.getTime?l[m].x.getTime():l[m].x,!(s<a.axisX.dataInfo.viewPortMin||s>a.axisX.dataInfo.viewPortMax)){var v=n;"number"!==typeof l[m].y?(b(),w=!0):(q=a.axisX.conversionParameters.reference+a.axisX.conversionParameters.pixelPerUnit*(s-a.axisX.conversionParameters.minimum)+0.5<<0,n=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(l[m].y-a.axisY.conversionParameters.minimum)+0.5<<0,r||w?(c.beginPath(),
+c.moveTo(q,n),x={x:q,y:n},t&&(d.beginPath(),d.moveTo(q,n)),w=r=!1):(c.lineTo(q,v),t&&d.lineTo(q,v),c.lineTo(q,n),t&&d.lineTo(q,n),0==m%250&&b()),v=h.dataPointIds[m],this._eventManager.objectMap[v]={id:v,objectType:"dataPoint",dataSeriesIndex:p,dataPointIndex:m,x1:q,y1:n},0!==l[m].markerSize&&(0<l[m].markerSize||0<h.markerSize)&&(s=h.getMarkerProperties(m,q,n,c),g.push(s),v=C(v),t&&g.push({x:q,y:n,ctx:d,type:s.type,size:s.size,color:v,borderColor:v,borderThickness:s.borderThickness})),(l[m].indexLabel||
+h.indexLabel)&&this._indexLabels.push({chartType:"stepArea",dataPoint:l[m],dataSeries:h,point:{x:q,y:n},direction:0<=l[m].y?1:-1,color:Q}))}b();J.drawMarkers(g)}}c.restore();t&&this._eventManager.ghostCtx.restore();return{source:c,dest:this.plotArea.ctx,animationCallback:y.xClipAnimation,easingFunction:y.easing.linear,animationBase:0}}};v.prototype.renderStackedArea=function(a){var b=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var c=null,d=[],e=this.plotArea,f=[],g=[],
+k=0,p,h,l,r=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(0-a.axisY.conversionParameters.minimum)<<0,m=this._eventManager.ghostCtx;t&&m.beginPath();b.save();t&&m.save();b.beginPath();b.rect(e.x1,e.y1,e.width,e.height);b.clip();t&&(m.beginPath(),m.rect(e.x1,e.y1,e.width,e.height),m.clip());xValuePresent=[];for(e=0;e<a.dataSeriesIndexes.length;e++){var q=a.dataSeriesIndexes[e],n=this.data[q],s=n.dataPoints;n.dataPointIndexes=[];for(k=0;k<s.length;k++)q=s[k].x.getTime?
+s[k].x.getTime():s[k].x,n.dataPointIndexes[q]=k,xValuePresent[q]||(g.push(q),xValuePresent[q]=!0);g.sort(ra)}for(e=0;e<a.dataSeriesIndexes.length;e++){var q=a.dataSeriesIndexes[e],n=this.data[q],s=n.dataPoints,B=!0,u=[],k=n.id;this._eventManager.objectMap[k]={objectType:"dataSeries",dataSeriesIndex:q};k=C(k);m.fillStyle=k;if(0<g.length){c=n._colorSet[0];b.fillStyle=c;b.strokeStyle=c;b.lineWidth=n.lineThickness;for(k=0;k<g.length;k++){l=g[k];var x=null,x=0<=n.dataPointIndexes[l]?s[n.dataPointIndexes[l]]:
+{x:l,y:0};if(!(l<a.axisX.dataInfo.viewPortMin||l>a.axisX.dataInfo.viewPortMax)&&"number"===typeof x.y){p=a.axisX.conversionParameters.reference+a.axisX.conversionParameters.pixelPerUnit*(l-a.axisX.conversionParameters.minimum)+0.5<<0;h=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(x.y-a.axisY.conversionParameters.minimum);var w=f[l]?f[l]:0;h-=w;u.push({x:p,y:r-w});f[l]=r-h;if(B)b.beginPath(),b.moveTo(p,h),t&&(m.beginPath(),m.moveTo(p,h)),B=!1;else if(b.lineTo(p,
+h),t&&m.lineTo(p,h),0==k%250){for(0<n.lineThickness&&b.stroke();0<u.length;){var v=u.pop();b.lineTo(v.x,v.y);t&&m.lineTo(v.x,v.y)}b.closePath();b.globalAlpha=n.fillOpacity;b.fill();b.globalAlpha=1;b.beginPath();b.moveTo(p,h);t&&(m.closePath(),m.fill(),m.beginPath(),m.moveTo(p,h));u.push({x:p,y:r-w})}if(0<=n.dataPointIndexes[l]){var G=n.dataPointIds[n.dataPointIndexes[l]];this._eventManager.objectMap[G]={id:G,objectType:"dataPoint",dataSeriesIndex:q,dataPointIndex:n.dataPointIndexes[l],x1:p,y1:h}}0<=
+n.dataPointIndexes[l]&&0!==x.markerSize&&(0<x.markerSize||0<n.markerSize)&&(l=n.getMarkerProperties(k,p,h,b),d.push(l),markerColor=C(G),t&&d.push({x:p,y:h,ctx:m,type:l.type,size:l.size,color:markerColor,borderColor:markerColor,borderThickness:l.borderThickness}));(x.indexLabel||n.indexLabel)&&this._indexLabels.push({chartType:"stackedArea",dataPoint:x,dataSeries:n,point:{x:p,y:h},direction:0<=s[k].y?1:-1,color:c})}}for(0<n.lineThickness&&b.stroke();0<u.length;)v=u.pop(),b.lineTo(v.x,v.y),t&&m.lineTo(v.x,
+v.y);b.closePath();b.globalAlpha=n.fillOpacity;b.fill();b.globalAlpha=1;b.beginPath();b.moveTo(p,h);t&&(m.closePath(),m.fill(),m.beginPath(),m.moveTo(p,h))}delete n.dataPointIndexes}J.drawMarkers(d);b.restore();t&&m.restore();return{source:b,dest:this.plotArea.ctx,animationCallback:y.xClipAnimation,easingFunction:y.easing.linear,animationBase:0}}};v.prototype.renderStackedArea100=function(a){var b=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var c=null,d=this.plotArea,
+e=[],f=[],g=[],k=0,p,h,l,r=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(0-a.axisY.conversionParameters.minimum)<<0,m=0.15*this.width<<0,q=a.axisX.dataInfo.minDiff,q=0.9*d.width/Math.abs(a.axisX.maximum-a.axisX.minimum)*Math.abs(q)<<0,n=this._eventManager.ghostCtx;b.save();t&&n.save();b.beginPath();b.rect(d.x1,d.y1,d.width,d.height);b.clip();t&&(n.beginPath(),n.rect(d.x1,d.y1,d.width,d.height),n.clip());xValuePresent=[];for(d=0;d<a.dataSeriesIndexes.length;d++){var s=
+a.dataSeriesIndexes[d],B=this.data[s],u=B.dataPoints;B.dataPointIndexes=[];for(k=0;k<u.length;k++)s=u[k].x.getTime?u[k].x.getTime():u[k].x,B.dataPointIndexes[s]=k,xValuePresent[s]||(g.push(s),xValuePresent[s]=!0);g.sort(ra)}for(d=0;d<a.dataSeriesIndexes.length;d++){var s=a.dataSeriesIndexes[d],B=this.data[s],u=B.dataPoints,x=!0,c=B.id;this._eventManager.objectMap[c]={objectType:"dataSeries",dataSeriesIndex:s};c=C(c);n.fillStyle=c;1==u.length&&(q=m);1>q?q=1:q>m&&(q=m);var w=[];if(0<g.length){c=B._colorSet[k%
+B._colorSet.length];b.fillStyle=c;b.strokeStyle=c;b.lineWidth=B.lineThickness;for(k=0;k<g.length;k++){l=g[k];var v=null,v=0<=B.dataPointIndexes[l]?u[B.dataPointIndexes[l]]:{x:l,y:0};if(!(l<a.axisX.dataInfo.viewPortMin||l>a.axisX.dataInfo.viewPortMax)&&"number"===typeof v.y){h=0!==a.dataPointYSums[l]?100*(v.y/a.dataPointYSums[l]):0;p=a.axisX.conversionParameters.reference+a.axisX.conversionParameters.pixelPerUnit*(l-a.axisX.conversionParameters.minimum)+0.5<<0;h=a.axisY.conversionParameters.reference+
+a.axisY.conversionParameters.pixelPerUnit*(h-a.axisY.conversionParameters.minimum);var G=f[l]?f[l]:0;h-=G;w.push({x:p,y:r-G});f[l]=r-h;if(x)b.beginPath(),b.moveTo(p,h),t&&(n.beginPath(),n.moveTo(p,h)),x=!1;else if(b.lineTo(p,h),t&&n.lineTo(p,h),0==k%250){for(0<B.lineThickness&&b.stroke();0<w.length;){var z=w.pop();b.lineTo(z.x,z.y);t&&n.lineTo(z.x,z.y)}b.closePath();b.globalAlpha=B.fillOpacity;b.fill();b.globalAlpha=1;b.beginPath();b.moveTo(p,h);t&&(n.closePath(),n.fill(),n.beginPath(),n.moveTo(p,
+h));w.push({x:p,y:r-G})}if(0<=B.dataPointIndexes[l]){var A=B.dataPointIds[B.dataPointIndexes[l]];this._eventManager.objectMap[A]={id:A,objectType:"dataPoint",dataSeriesIndex:s,dataPointIndex:B.dataPointIndexes[l],x1:p,y1:h}}0<=B.dataPointIndexes[l]&&0!==v.markerSize&&(0<v.markerSize||0<B.markerSize)&&(l=B.getMarkerProperties(k,p,h,b),e.push(l),markerColor=C(A),t&&e.push({x:p,y:h,ctx:n,type:l.type,size:l.size,color:markerColor,borderColor:markerColor,borderThickness:l.borderThickness}));(v.indexLabel||
+B.indexLabel)&&this._indexLabels.push({chartType:"stackedArea100",dataPoint:v,dataSeries:B,point:{x:p,y:h},direction:0<=u[k].y?1:-1,color:c})}}for(0<B.lineThickness&&b.stroke();0<w.length;)z=w.pop(),b.lineTo(z.x,z.y),t&&n.lineTo(z.x,z.y);b.closePath();b.globalAlpha=B.fillOpacity;b.fill();b.globalAlpha=1;b.beginPath();b.moveTo(p,h);t&&(n.closePath(),n.fill(),n.beginPath(),n.moveTo(p,h))}delete B.dataPointIndexes}J.drawMarkers(e);b.restore();t&&n.restore();return{source:b,dest:this.plotArea.ctx,animationCallback:y.xClipAnimation,
+easingFunction:y.easing.linear,animationBase:0}}};v.prototype.renderBubble=function(a){var b=a.targetCanvasCtx||this.plotArea.ctx,c=a.dataSeriesIndexes.length;if(!(0>=c)){var d=this.plotArea,e=0,f,g,k=0.15*this.width<<0,e=a.axisX.dataInfo.minDiff,c=0.9*(d.width/Math.abs(a.axisX.maximum-a.axisX.minimum)*Math.abs(e)/c)<<0;b.save();t&&this._eventManager.ghostCtx.save();b.beginPath();b.rect(d.x1,d.y1,d.width,d.height);b.clip();t&&(this._eventManager.ghostCtx.rect(d.x1,d.y1,d.width,d.height),this._eventManager.ghostCtx.clip());
+for(var p=-Infinity,h=Infinity,l=0;l<a.dataSeriesIndexes.length;l++)for(var r=a.dataSeriesIndexes[l],m=this.data[r],q=m.dataPoints,n=0,e=0;e<q.length;e++)f=q[e].getTime?f=q[e].x.getTime():f=q[e].x,f<a.axisX.dataInfo.viewPortMin||f>a.axisX.dataInfo.viewPortMax||"undefined"===typeof q[e].z||(n=q[e].z,n>p&&(p=n),n<h&&(h=n));for(var s=25*Math.PI,d=Math.max(Math.pow(0.25*Math.min(d.height,d.width)/2,2)*Math.PI,s),l=0;l<a.dataSeriesIndexes.length;l++)if(r=a.dataSeriesIndexes[l],m=this.data[r],q=m.dataPoints,
+1==q.length&&(c=k),1>c?c=1:c>k&&(c=k),0<q.length)for(b.strokeStyle="#4572A7 ",e=0;e<q.length;e++)if(f=q[e].getTime?f=q[e].x.getTime():f=q[e].x,!(f<a.axisX.dataInfo.viewPortMin||f>a.axisX.dataInfo.viewPortMax)&&"number"===typeof q[e].y){f=a.axisX.conversionParameters.reference+a.axisX.conversionParameters.pixelPerUnit*(f-a.axisX.conversionParameters.minimum)+0.5<<0;g=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(q[e].y-a.axisY.conversionParameters.minimum)+0.5<<
+0;var n=q[e].z,B=2*Math.max(Math.sqrt((p===h?d/2:s+(d-s)/(p-h)*(n-h))/Math.PI)<<0,1),n=m.getMarkerProperties(e,b);n.size=B;b.globalAlpha=m.fillOpacity;J.drawMarker(f,g,b,n.type,n.size,n.color,n.borderColor,n.borderThickness);b.globalAlpha=1;var u=m.dataPointIds[e];this._eventManager.objectMap[u]={id:u,objectType:"dataPoint",dataSeriesIndex:r,dataPointIndex:e,x1:f,y1:g,size:B};B=C(u);t&&J.drawMarker(f,g,this._eventManager.ghostCtx,n.type,n.size,B,B,n.borderThickness);(q[e].indexLabel||m.indexLabel)&&
+this._indexLabels.push({chartType:"bubble",dataPoint:q[e],dataSeries:m,point:{x:f,y:g},direction:1,color:null})}b.restore();t&&this._eventManager.ghostCtx.restore();return{source:b,dest:this.plotArea.ctx,animationCallback:y.fadeInAnimation,easingFunction:y.easing.easeInQuad,animationBase:0}}};v.prototype.renderScatter=function(a){var b=a.targetCanvasCtx||this.plotArea.ctx,c=a.dataSeriesIndexes.length;if(!(0>=c)){var d=this.plotArea,e=0,f,g,k=0.15*this.width<<0,e=a.axisX.dataInfo.minDiff,c=0.9*(d.width/
+Math.abs(a.axisX.maximum-a.axisX.minimum)*Math.abs(e)/c)<<0;b.save();t&&this._eventManager.ghostCtx.save();b.beginPath();b.rect(d.x1,d.y1,d.width,d.height);b.clip();t&&(this._eventManager.ghostCtx.rect(d.x1,d.y1,d.width,d.height),this._eventManager.ghostCtx.clip());for(var p=0;p<a.dataSeriesIndexes.length;p++){var h=a.dataSeriesIndexes[p],l=this.data[h],r=l.dataPoints;1==r.length&&(c=k);1>c?c=1:c>k&&(c=k);if(0<r.length){b.strokeStyle="#4572A7 ";Math.pow(0.3*Math.min(d.height,d.width)/2,2);for(var m=
+0,q=0,e=0;e<r.length;e++)if(f=r[e].getTime?f=r[e].x.getTime():f=r[e].x,!(f<a.axisX.dataInfo.viewPortMin||f>a.axisX.dataInfo.viewPortMax)&&"number"===typeof r[e].y){f=a.axisX.conversionParameters.reference+a.axisX.conversionParameters.pixelPerUnit*(f-a.axisX.conversionParameters.minimum)+0.5<<0;g=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(r[e].y-a.axisY.conversionParameters.minimum)+0.5<<0;var n=l.getMarkerProperties(e,f,g,b);b.globalAlpha=l.fillOpacity;J.drawMarker(n.x,
+n.y,n.ctx,n.type,n.size,n.color,n.borderColor,n.borderThickness);b.globalAlpha=1;Math.sqrt((m-f)*(m-f)+(q-g)*(q-g))<Math.min(n.size,5)&&r.length>Math.min(this.plotArea.width,this.plotArea.height)||(m=l.dataPointIds[e],this._eventManager.objectMap[m]={id:m,objectType:"dataPoint",dataSeriesIndex:h,dataPointIndex:e,x1:f,y1:g},m=C(m),t&&J.drawMarker(n.x,n.y,this._eventManager.ghostCtx,n.type,n.size,m,m,n.borderThickness),(r[e].indexLabel||l.indexLabel)&&this._indexLabels.push({chartType:"scatter",dataPoint:r[e],
+dataSeries:l,point:{x:f,y:g},direction:1,color:null}),m=f,q=g)}}}b.restore();t&&this._eventManager.ghostCtx.restore();return{source:b,dest:this.plotArea.ctx,animationCallback:y.fadeInAnimation,easingFunction:y.easing.easeInQuad,animationBase:0}}};v.prototype.renderCandlestick=function(a){var b=a.targetCanvasCtx||this.plotArea.ctx,c=this._eventManager.ghostCtx;if(!(0>=a.dataSeriesIndexes.length)){var d=null,d=this.plotArea,e=0,f,g,k,p,h,l,e=0.015*this.width;f=a.axisX.dataInfo.minDiff;var r=0.7*d.width/
+Math.abs(a.axisX.maximum-a.axisX.minimum)*Math.abs(f)<<0;r>e?r=e:Infinity===f?r=e:1>r&&(r=1);b.save();t&&c.save();b.beginPath();b.rect(d.x1,d.y1,d.width,d.height);b.clip();t&&(c.rect(d.x1,d.y1,d.width,d.height),c.clip());for(var m=0;m<a.dataSeriesIndexes.length;m++){var q=a.dataSeriesIndexes[m],n=this.data[q],s=n.dataPoints;if(0<s.length)for(var B=5<r&&n.bevelEnabled?!0:!1,e=0;e<s.length;e++)if(s[e].getTime?l=s[e].x.getTime():l=s[e].x,!(l<a.axisX.dataInfo.viewPortMin||l>a.axisX.dataInfo.viewPortMax)&&
+null!==s[e].y&&s[e].y.length&&"number"===typeof s[e].y[0]&&"number"===typeof s[e].y[1]&&"number"===typeof s[e].y[2]&&"number"===typeof s[e].y[3]){f=a.axisX.conversionParameters.reference+a.axisX.conversionParameters.pixelPerUnit*(l-a.axisX.conversionParameters.minimum)+0.5<<0;g=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(s[e].y[0]-a.axisY.conversionParameters.minimum)+0.5<<0;k=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(s[e].y[1]-
+a.axisY.conversionParameters.minimum)+0.5<<0;p=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(s[e].y[2]-a.axisY.conversionParameters.minimum)+0.5<<0;h=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(s[e].y[3]-a.axisY.conversionParameters.minimum)+0.5<<0;var u=f-r/2<<0,x=u+r<<0,d=s[e].color?s[e].color:n._colorSet[0],w=Math.round(Math.max(1,0.15*r)),v=0===w%2?0:0.5,G=n.dataPointIds[e];this._eventManager.objectMap[G]={id:G,objectType:"dataPoint",
+dataSeriesIndex:q,dataPointIndex:e,x1:u,y1:g,x2:x,y2:k,x3:f,y3:p,x4:f,y4:h,borderThickness:w,color:d};b.strokeStyle=d;b.beginPath();b.lineWidth=w;c.lineWidth=Math.max(w,4);"candlestick"===n.type?(b.moveTo(f-v,k),b.lineTo(f-v,Math.min(g,h)),b.stroke(),b.moveTo(f-v,Math.max(g,h)),b.lineTo(f-v,p),b.stroke(),F(b,u,Math.min(g,h),x,Math.max(g,h),s[e].y[0]<=s[e].y[3]?n.risingColor:d,w,d,B,B,!1,!1,n.fillOpacity),t&&(d=C(G),c.strokeStyle=d,c.moveTo(f-v,k),c.lineTo(f-v,Math.min(g,h)),c.stroke(),c.moveTo(f-
+v,Math.max(g,h)),c.lineTo(f-v,p),c.stroke(),F(c,u,Math.min(g,h),x,Math.max(g,h),d,0,null,!1,!1,!1,!1))):"ohlc"===n.type&&(b.moveTo(f-v,k),b.lineTo(f-v,p),b.stroke(),b.beginPath(),b.moveTo(f,g),b.lineTo(u,g),b.stroke(),b.beginPath(),b.moveTo(f,h),b.lineTo(x,h),b.stroke(),t&&(d=C(G),c.strokeStyle=d,c.moveTo(f-v,k),c.lineTo(f-v,p),c.stroke(),c.beginPath(),c.moveTo(f,g),c.lineTo(u,g),c.stroke(),c.beginPath(),c.moveTo(f,h),c.lineTo(x,h),c.stroke()));(s[e].indexLabel||n.indexLabel)&&this._indexLabels.push({chartType:n.type,
+dataPoint:s[e],dataSeries:n,point:{x:u+(x-u)/2,y:k},direction:1,bounds:{x1:u,y1:Math.min(k,p),x2:x,y2:Math.max(k,p)},color:d})}}b.restore();t&&c.restore();return{source:b,dest:this.plotArea.ctx,animationCallback:y.fadeInAnimation,easingFunction:y.easing.easeInQuad,animationBase:0}}};v.prototype.renderRangeColumn=function(a){var b=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var c=null,d=this.plotArea,e=0,f,g,e=0.03*this.width;f=a.axisX.dataInfo.minDiff;var k=0.9*(d.width/
+Math.abs(a.axisX.maximum-a.axisX.minimum)*Math.abs(f)/a.plotType.totalDataSeries)<<0;k>e?k=e:Infinity===f?k=e:1>k&&(k=1);b.save();t&&this._eventManager.ghostCtx.save();b.beginPath();b.rect(d.x1,d.y1,d.width,d.height);b.clip();t&&(this._eventManager.ghostCtx.rect(d.x1,d.y1,d.width,d.height),this._eventManager.ghostCtx.clip());for(var p=0;p<a.dataSeriesIndexes.length;p++){var h=a.dataSeriesIndexes[p],l=this.data[h],r=l.dataPoints;if(0<r.length)for(var m=5<k&&l.bevelEnabled?!0:!1,e=0;e<r.length;e++)if(r[e].getTime?
+g=r[e].x.getTime():g=r[e].x,!(g<a.axisX.dataInfo.viewPortMin||g>a.axisX.dataInfo.viewPortMax)&&null!==r[e].y&&r[e].y.length&&"number"===typeof r[e].y[0]&&"number"===typeof r[e].y[1]){c=a.axisX.conversionParameters.reference+a.axisX.conversionParameters.pixelPerUnit*(g-a.axisX.conversionParameters.minimum)+0.5<<0;d=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(r[e].y[0]-a.axisY.conversionParameters.minimum)+0.5<<0;f=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*
+(r[e].y[1]-a.axisY.conversionParameters.minimum)+0.5<<0;var q=c-a.plotType.totalDataSeries*k/2+(a.previousDataSeriesCount+p)*k<<0,n=q+k<<0,c=r[e].color?r[e].color:l._colorSet[e%l._colorSet.length];if(d>f){var s=d,d=f;f=s}s=l.dataPointIds[e];this._eventManager.objectMap[s]={id:s,objectType:"dataPoint",dataSeriesIndex:h,dataPointIndex:e,x1:q,y1:d,x2:n,y2:f};F(b,q,d,n,f,c,0,c,m,m,!1,!1,l.fillOpacity);c=C(s);t&&F(this._eventManager.ghostCtx,q,d,n,f,c,0,null,!1,!1,!1,!1);if(r[e].indexLabel||l.indexLabel)this._indexLabels.push({chartType:"rangeColumn",
+dataPoint:r[e],dataSeries:l,indexKeyword:0,point:{x:q+(n-q)/2,y:r[e].y[1]>=r[e].y[0]?f:d},direction:r[e].y[1]>=r[e].y[0]?-1:1,bounds:{x1:q,y1:Math.min(d,f),x2:n,y2:Math.max(d,f)},color:c}),this._indexLabels.push({chartType:"rangeColumn",dataPoint:r[e],dataSeries:l,indexKeyword:1,point:{x:q+(n-q)/2,y:r[e].y[1]>=r[e].y[0]?d:f},direction:r[e].y[1]>=r[e].y[0]?1:-1,bounds:{x1:q,y1:Math.min(d,f),x2:n,y2:Math.max(d,f)},color:c})}}b.restore();t&&this._eventManager.ghostCtx.restore();return{source:b,dest:this.plotArea.ctx,
+animationCallback:y.fadeInAnimation,easingFunction:y.easing.easeInQuad,animationBase:0}}};v.prototype.renderRangeBar=function(a){var b=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var c=null,d=this.plotArea,e=0,f,g,k,e=Math.min(0.15*this.height,0.9*(this.plotArea.height/a.plotType.totalDataSeries))<<0;f=a.axisX.dataInfo.minDiff;var p=0.9*(d.height/Math.abs(a.axisX.maximum-a.axisX.minimum)*Math.abs(f)/a.plotType.totalDataSeries)<<0;p>e?p=e:Infinity===f?p=e:1>p&&(p=1);b.save();
+t&&this._eventManager.ghostCtx.save();b.beginPath();b.rect(d.x1,d.y1,d.width,d.height);b.clip();t&&(this._eventManager.ghostCtx.rect(d.x1,d.y1,d.width,d.height),this._eventManager.ghostCtx.clip());for(var h=0;h<a.dataSeriesIndexes.length;h++){var l=a.dataSeriesIndexes[h],r=this.data[l],m=r.dataPoints;if(0<m.length){var q=5<p&&r.bevelEnabled?!0:!1;b.strokeStyle="#4572A7 ";for(e=0;e<m.length;e++)if(m[e].getTime?k=m[e].x.getTime():k=m[e].x,!(k<a.axisX.dataInfo.viewPortMin||k>a.axisX.dataInfo.viewPortMax)&&
+null!==m[e].y&&m[e].y.length&&"number"===typeof m[e].y[0]&&"number"===typeof m[e].y[1]){d=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(m[e].y[0]-a.axisY.conversionParameters.minimum)+0.5<<0;f=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(m[e].y[1]-a.axisY.conversionParameters.minimum)+0.5<<0;g=a.axisX.conversionParameters.reference+a.axisX.conversionParameters.pixelPerUnit*(k-a.axisX.conversionParameters.minimum)+0.5<<0;g=g-
+a.plotType.totalDataSeries*p/2+(a.previousDataSeriesCount+h)*p<<0;var n=g+p<<0;d>f&&(c=d,d=f,f=c);c=m[e].color?m[e].color:r._colorSet[e%r._colorSet.length];F(b,d,g,f,n,c,0,null,q,!1,!1,!1,r.fillOpacity);c=r.dataPointIds[e];this._eventManager.objectMap[c]={id:c,objectType:"dataPoint",dataSeriesIndex:l,dataPointIndex:e,x1:d,y1:g,x2:f,y2:n};c=C(c);t&&F(this._eventManager.ghostCtx,d,g,f,n,c,0,null,!1,!1,!1,!1);if(m[e].indexLabel||r.indexLabel)this._indexLabels.push({chartType:"rangeBar",dataPoint:m[e],
+dataSeries:r,indexKeyword:0,point:{x:m[e].y[1]>=m[e].y[0]?d:f,y:g+(n-g)/2},direction:m[e].y[1]>=m[e].y[0]?-1:1,bounds:{x1:Math.min(d,f),y1:g,x2:Math.max(d,f),y2:n},color:c}),this._indexLabels.push({chartType:"rangeBar",dataPoint:m[e],dataSeries:r,indexKeyword:1,point:{x:m[e].y[1]>=m[e].y[0]?f:d,y:g+(n-g)/2},direction:m[e].y[1]>=m[e].y[0]?1:-1,bounds:{x1:Math.min(d,f),y1:g,x2:Math.max(d,f),y2:n},color:c})}}}b.restore();t&&this._eventManager.ghostCtx.restore();return{source:b,dest:this.plotArea.ctx,
+animationCallback:y.fadeInAnimation,easingFunction:y.easing.easeInQuad,animationBase:0}}};v.prototype.renderRangeArea=function(a){function b(){if(v){var a=null;0<p.lineThickness&&c.stroke();for(var b=g.length-1;0<=b;b--)a=g[b],c.lineTo(a.x,a.y),d.lineTo(a.x,a.y);c.closePath();c.globalAlpha=p.fillOpacity;c.fill();c.globalAlpha=1;d.fill();if(0<p.lineThickness){c.beginPath();c.moveTo(a.x,a.y);for(b=0;b<g.length;b++)a=g[b],c.lineTo(a.x,a.y);c.stroke()}c.beginPath();c.moveTo(m,q);d.beginPath();d.moveTo(m,
+q);v={x:m,y:q};g=[];g.push({x:m,y:n})}}var c=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var d=this._eventManager.ghostCtx,e=[],f=this.plotArea;c.save();t&&d.save();c.beginPath();c.rect(f.x1,f.y1,f.width,f.height);c.clip();t&&(d.beginPath(),d.rect(f.x1,f.y1,f.width,f.height),d.clip());for(f=0;f<a.dataSeriesIndexes.length;f++){var g=[],k=a.dataSeriesIndexes[f],p=this.data[k],h=p.dataPoints,e=p.id;this._eventManager.objectMap[e]={objectType:"dataSeries",dataSeriesIndex:k};
+e=C(e);d.fillStyle=e;var e=[],l=!0,r=0,m,q,n,s,v=null;if(0<h.length){var u=p._colorSet[r%p._colorSet.length];c.fillStyle=u;c.strokeStyle=u;c.lineWidth=p.lineThickness;for(var x=!0;r<h.length;r++)if(s=h[r].x.getTime?h[r].x.getTime():h[r].x,!(s<a.axisX.dataInfo.viewPortMin||s>a.axisX.dataInfo.viewPortMax))if(null!==h[r].y&&h[r].y.length&&"number"===typeof h[r].y[0]&&"number"===typeof h[r].y[1]){m=a.axisX.conversionParameters.reference+a.axisX.conversionParameters.pixelPerUnit*(s-a.axisX.conversionParameters.minimum)+
+0.5<<0;q=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(h[r].y[0]-a.axisY.conversionParameters.minimum)+0.5<<0;n=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(h[r].y[1]-a.axisY.conversionParameters.minimum)+0.5<<0;l||x?(c.beginPath(),c.moveTo(m,q),v={x:m,y:q},g=[],g.push({x:m,y:n}),t&&(d.beginPath(),d.moveTo(m,q)),x=l=!1):(c.lineTo(m,q),g.push({x:m,y:n}),t&&d.lineTo(m,q),0==r%250&&b());s=p.dataPointIds[r];this._eventManager.objectMap[s]=
+{id:s,objectType:"dataPoint",dataSeriesIndex:k,dataPointIndex:r,x1:m,y1:q,y2:n};if(0!==h[r].markerSize&&(0<h[r].markerSize||0<p.markerSize)){var w=p.getMarkerProperties(r,m,n,c);e.push(w);var z=C(s);t&&e.push({x:m,y:n,ctx:d,type:w.type,size:w.size,color:z,borderColor:z,borderThickness:w.borderThickness});w=p.getMarkerProperties(r,m,q,c);e.push(w);z=C(s);t&&e.push({x:m,y:q,ctx:d,type:w.type,size:w.size,color:z,borderColor:z,borderThickness:w.borderThickness})}if(h[r].indexLabel||p.indexLabel)this._indexLabels.push({chartType:"rangeArea",
+dataPoint:h[r],dataSeries:p,indexKeyword:0,point:{x:m,y:q},direction:h[r].y[0]<=h[r].y[1]?-1:1,color:u}),this._indexLabels.push({chartType:"rangeArea",dataPoint:h[r],dataSeries:p,indexKeyword:1,point:{x:m,y:n},direction:h[r].y[0]<=h[r].y[1]?1:-1,color:u})}else b(),x=!0;b();J.drawMarkers(e)}}c.restore();t&&this._eventManager.ghostCtx.restore();return{source:c,dest:this.plotArea.ctx,animationCallback:y.xClipAnimation,easingFunction:y.easing.linear,animationBase:0}}};v.prototype.renderRangeSplineArea=
+function(a){function b(){var a=fa(q,2);if(0<a.length){c.beginPath();c.moveTo(a[0].x,a[0].y);t&&(d.beginPath(),d.moveTo(a[0].x,a[0].y));for(var b=0;b<a.length-3;b+=3)c.bezierCurveTo(a[b+1].x,a[b+1].y,a[b+2].x,a[b+2].y,a[b+3].x,a[b+3].y),t&&d.bezierCurveTo(a[b+1].x,a[b+1].y,a[b+2].x,a[b+2].y,a[b+3].x,a[b+3].y);0<k.lineThickness&&c.stroke();a=fa(n,2);c.lineTo(n[n.length-1].x,n[n.length-1].y);for(b=a.length-1;2<b;b-=3)c.bezierCurveTo(a[b-1].x,a[b-1].y,a[b-2].x,a[b-2].y,a[b-3].x,a[b-3].y),t&&d.bezierCurveTo(a[b-
+1].x,a[b-1].y,a[b-2].x,a[b-2].y,a[b-3].x,a[b-3].y);c.closePath();c.globalAlpha=k.fillOpacity;c.fill();c.globalAlpha=1;if(0<k.lineThickness){c.beginPath();c.moveTo(n[n.length-1].x,n[n.length-1].y);for(b=a.length-1;2<b;b-=3)c.bezierCurveTo(a[b-1].x,a[b-1].y,a[b-2].x,a[b-2].y,a[b-3].x,a[b-3].y),t&&d.bezierCurveTo(a[b-1].x,a[b-1].y,a[b-2].x,a[b-2].y,a[b-3].x,a[b-3].y);c.stroke()}c.beginPath();t&&(d.closePath(),d.fill())}}var c=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var d=
+this._eventManager.ghostCtx,e=[],f=this.plotArea;c.save();t&&d.save();c.beginPath();c.rect(f.x1,f.y1,f.width,f.height);c.clip();t&&(d.beginPath(),d.rect(f.x1,f.y1,f.width,f.height),d.clip());for(f=0;f<a.dataSeriesIndexes.length;f++){var g=a.dataSeriesIndexes[f],k=this.data[g],p=k.dataPoints,e=k.id;this._eventManager.objectMap[e]={objectType:"dataSeries",dataSeriesIndex:g};e=C(e);d.fillStyle=e;var e=[],h=0,l,r,m,q=[],n=[];if(0<p.length){color=k._colorSet[h%k._colorSet.length];c.fillStyle=color;c.strokeStyle=
+color;for(c.lineWidth=k.lineThickness;h<p.length;h++)if(l=p[h].x.getTime?p[h].x.getTime():p[h].x,!(l<a.axisX.dataInfo.viewPortMin||l>a.axisX.dataInfo.viewPortMax))if(null!==p[h].y&&p[h].y.length&&"number"===typeof p[h].y[0]&&"number"===typeof p[h].y[1]){l=a.axisX.conversionParameters.reference+a.axisX.conversionParameters.pixelPerUnit*(l-a.axisX.conversionParameters.minimum)+0.5<<0;r=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(p[h].y[0]-a.axisY.conversionParameters.minimum)+
+0.5<<0;m=a.axisY.conversionParameters.reference+a.axisY.conversionParameters.pixelPerUnit*(p[h].y[1]-a.axisY.conversionParameters.minimum)+0.5<<0;var s=k.dataPointIds[h];this._eventManager.objectMap[s]={id:s,objectType:"dataPoint",dataSeriesIndex:g,dataPointIndex:h,x1:l,y1:r,y2:m};q[q.length]={x:l,y:r};n[n.length]={x:l,y:m};if(0!==p[h].markerSize&&(0<p[h].markerSize||0<k.markerSize)){var v=k.getMarkerProperties(h,l,r,c);e.push(v);var u=C(s);t&&e.push({x:l,y:r,ctx:d,type:v.type,size:v.size,color:u,
+borderColor:u,borderThickness:v.borderThickness});v=k.getMarkerProperties(h,l,m,c);e.push(v);u=C(s);t&&e.push({x:l,y:m,ctx:d,type:v.type,size:v.size,color:u,borderColor:u,borderThickness:v.borderThickness})}if(p[h].indexLabel||k.indexLabel)this._indexLabels.push({chartType:"splineArea",dataPoint:p[h],dataSeries:k,indexKeyword:0,point:{x:l,y:r},direction:p[h].y[0]<=p[h].y[1]?-1:1,color:color}),this._indexLabels.push({chartType:"splineArea",dataPoint:p[h],dataSeries:k,indexKeyword:1,point:{x:l,y:m},
+direction:p[h].y[0]<=p[h].y[1]?1:-1,color:color})}else 0<h&&(b(),q=[],n=[]);b();J.drawMarkers(e)}}c.restore();t&&this._eventManager.ghostCtx.restore();return{source:c,dest:this.plotArea.ctx,animationCallback:y.xClipAnimation,easingFunction:y.easing.linear,animationBase:0}}};var pa=function(a,b,c,d,e,f,g,k){"undefined"===typeof k&&(k=1);if(!t){var p=Number((g%(2*Math.PI)).toFixed(8));Number((f%(2*Math.PI)).toFixed(8))===p&&(g-=1E-4)}a.save();a.globalAlpha=k;"pie"===e?(a.beginPath(),a.moveTo(b.x,b.y),
+a.arc(b.x,b.y,c,f,g,!1),a.fillStyle=d,a.strokeStyle="white",a.lineWidth=2,a.closePath(),a.fill()):"doughnut"===e&&(a.beginPath(),a.arc(b.x,b.y,c,f,g,!1),a.arc(b.x,b.y,0.6*c,g,f,!0),a.closePath(),a.fillStyle=d,a.strokeStyle="white",a.lineWidth=2,a.fill());a.globalAlpha=1;a.restore()};v.prototype.renderPie=function(a){function b(){if(h&&l){var a=0,b=0,c=0,d=0;for(A=0;A<l.length;A++){var e=l[A],g=h.dataPointIds[A],f={id:g,objectType:"dataPoint",dataPointIndex:A,dataSeriesIndex:0};n.push(f);var k=e.indexLabel?
+e.indexLabel:h.indexLabel?h.indexLabel:e.label?e.label:h.label?h.label:"";p._eventManager.objectMap[g]=f;f.center={x:w.x,y:w.y};f.y=e.y;f.radius=y;f.indexLabelText=p.replaceKeywordsWithValue(k,e,h,A);f.indexLabelPlacement=h.indexLabelPlacement;f.indexLabelLineColor=e.indexLabelLineColor?e.indexLabelLineColor:h.indexLabelLineColor?h.indexLabelLineColor:e.color?e.color:h._colorSet[A%h._colorSet.length];f.indexLabelLineThickness=e.indexLabelLineThickness?e.indexLabelLineThickness:h.indexLabelLineThickness;
+f.indexLabelFontColor=e.indexLabelFontColor?e.indexLabelFontColor:h.indexLabelFontColor;f.indexLabelFontStyle=e.indexLabelFontStyle?e.indexLabelFontStyle:h.indexLabelFontStyle;f.indexLabelFontWeight=e.indexLabelFontWeight?e.indexLabelFontWeight:h.indexLabelFontWeight;f.indexLabelFontSize=e.indexLabelFontSize?e.indexLabelFontSize:h.indexLabelFontSize;f.indexLabelFontFamily=e.indexLabelFontFamily?e.indexLabelFontFamily:h.indexLabelFontFamily;f.indexLabelBackgroundColor=e.indexLabelBackgroundColor?e.indexLabelBackgroundColor:
+h.indexLabelBackgroundColor?h.indexLabelBackgroundColor:null;f.indexLabelMaxWidth=e.indexLabelMaxWidth?e.indexLabelMaxWidth:h.indexLabelMaxWidth?h.indexLabelMaxWidth:0.33*m.width;f.indexLabelWrap="undefined"!==typeof e.indexLabelWrap?e.indexLabelWrap:h.indexLabelWrap;f.startAngle=0===A?h.startAngle?h.startAngle/180*Math.PI:0:n[A-1].endAngle;f.startAngle=(f.startAngle+2*Math.PI)%(2*Math.PI);f.endAngle=f.startAngle+2*Math.PI/C*Math.abs(e.y);e=(f.endAngle+f.startAngle)/2;e=(e+2*Math.PI)%(2*Math.PI);
+f.midAngle=e;if(f.midAngle>Math.PI/2-u&&f.midAngle<Math.PI/2+u){if(0===a||n[c].midAngle>f.midAngle)c=A;a++}else if(f.midAngle>3*Math.PI/2-u&&f.midAngle<3*Math.PI/2+u){if(0===b||n[d].midAngle>f.midAngle)d=A;b++}f.hemisphere=e>Math.PI/2&&e<=3*Math.PI/2?"left":"right";f.indexLabelTextBlock=new I(p.plotArea.ctx,{fontSize:f.indexLabelFontSize,fontFamily:f.indexLabelFontFamily,fontColor:f.indexLabelFontColor,fontStyle:f.indexLabelFontStyle,fontWeight:f.indexLabelFontWeight,horizontalAlign:"left",backgroundColor:f.indexLabelBackgroundColor,
+maxWidth:f.indexLabelMaxWidth,maxHeight:f.indexLabelWrap?5*f.indexLabelFontSize:1.5*f.indexLabelFontSize,text:f.indexLabelText,padding:0,textBaseline:"top"});f.indexLabelTextBlock.measureText()}g=e=0;k=!1;for(A=0;A<l.length;A++)f=n[(c+A)%l.length],1<a&&(f.midAngle>Math.PI/2-u&&f.midAngle<Math.PI/2+u)&&(e<=a/2&&!k?(f.hemisphere="right",e++):(f.hemisphere="left",k=!0));k=!1;for(A=0;A<l.length;A++)f=n[(d+A)%l.length],1<b&&(f.midAngle>3*Math.PI/2-u&&f.midAngle<3*Math.PI/2+u)&&(g<=b/2&&!k?(f.hemisphere=
+"left",g++):(f.hemisphere="right",k=!0))}}function c(a){var b=p.plotArea.ctx;b.clearRect(m.x1,m.y1,m.width,m.height);b.fillStyle=p.backgroundColor;b.fillRect(m.x1,m.y1,m.width,m.height);for(b=0;b<l.length;b++){var c=n[b].startAngle,d=n[b].endAngle;if(d>c){var e=0.07*y*Math.cos(n[b].midAngle),f=0.07*y*Math.sin(n[b].midAngle),g=!1;if(l[b].exploded){if(1E-9<Math.abs(n[b].center.x-(w.x+e))||1E-9<Math.abs(n[b].center.y-(w.y+f)))n[b].center.x=w.x+e*a,n[b].center.y=w.y+f*a,g=!0}else if(0<Math.abs(n[b].center.x-
+w.x)||0<Math.abs(n[b].center.y-w.y))n[b].center.x=w.x+e*(1-a),n[b].center.y=w.y+f*(1-a),g=!0;g&&(e={},e.dataSeries=h,e.dataPoint=h.dataPoints[b],e.index=b,p._toolTip.highlightObjects([e]));pa(p.plotArea.ctx,n[b].center,n[b].radius,l[b].color?l[b].color:h._colorSet[b%h._colorSet.length],h.type,c,d,h.fillOpacity)}}a=p.plotArea.ctx;a.fillStyle="black";a.strokeStyle="grey";a.textBaseline="middle";a.lineJoin="round";for(b=b=0;b<l.length;b++)c=n[b],c.indexLabelText&&(c.indexLabelTextBlock.y-=c.indexLabelTextBlock.height/
+2,d=0,d="left"===c.hemisphere?"inside"!==h.indexLabelPlacement?-(c.indexLabelTextBlock.width+r):-c.indexLabelTextBlock.width/2:"inside"!==h.indexLabelPlacement?r:-c.indexLabelTextBlock.width/2,c.indexLabelTextBlock.x+=d,c.indexLabelTextBlock.render(!0),c.indexLabelTextBlock.x-=d,c.indexLabelTextBlock.y+=c.indexLabelTextBlock.height/2,"inside"!==c.indexLabelPlacement&&(d=c.center.x+y*Math.cos(c.midAngle),e=c.center.y+y*Math.sin(c.midAngle),a.strokeStyle=c.indexLabelLineColor,a.lineWidth=c.indexLabelLineThickness,
+a.beginPath(),a.moveTo(d,e),a.lineTo(c.indexLabelTextBlock.x,c.indexLabelTextBlock.y),a.lineTo(c.indexLabelTextBlock.x+("left"===c.hemisphere?-r:r),c.indexLabelTextBlock.y),a.stroke()),a.lineJoin="miter")}function d(a,b){var c=a.indexLabelTextBlock.x,d=a.indexLabelTextBlock.y-a.indexLabelTextBlock.height/2,e=a.indexLabelTextBlock.y+a.indexLabelTextBlock.height/2,f=b.indexLabelTextBlock.y-b.indexLabelTextBlock.height/2,g=b.indexLabelTextBlock.x+b.indexLabelTextBlock.width,l=b.indexLabelTextBlock.y+
+b.indexLabelTextBlock.height/2;return a.indexLabelTextBlock.x+a.indexLabelTextBlock.width<b.indexLabelTextBlock.x-r||c>g+r||d>l+r||e<f-r?!1:!0}function e(a,b){var c=0,c=a.indexLabelTextBlock.y-a.indexLabelTextBlock.height/2,d=a.indexLabelTextBlock.y+a.indexLabelTextBlock.height/2,e=b.indexLabelTextBlock.y-b.indexLabelTextBlock.height/2,f=b.indexLabelTextBlock.y+b.indexLabelTextBlock.height/2;return c=b.indexLabelTextBlock.y>a.indexLabelTextBlock.y?e-d:c-f}function f(a){for(var b=null,c=1;c<l.length;c++)if(b=
+(a+c+n.length)%n.length,n[b].hemisphere!==n[a].hemisphere){b=null;break}else if(n[b].indexLabelText&&b!==a&&(0>e(n[b],n[a])||("right"===n[a].hemisphere?n[b].indexLabelTextBlock.y>=n[a].indexLabelTextBlock.y:n[b].indexLabelTextBlock.y<=n[a].indexLabelTextBlock.y)))break;else b=null;return b}function g(a,b){b=b||0;var c=0,d=w.y-1*z,h=w.y+1*z;if(0<=a&&a<l.length){var m=n[a];if(0>b&&m.indexLabelTextBlock.y<d||0<b&&m.indexLabelTextBlock.y>h)return 0;var k=b,p=0,r=0,r=p=p=0;0>k?m.indexLabelTextBlock.y-
+m.indexLabelTextBlock.height/2>d&&m.indexLabelTextBlock.y-m.indexLabelTextBlock.height/2+k<d&&(k=-(d-(m.indexLabelTextBlock.y-m.indexLabelTextBlock.height/2+k))):m.indexLabelTextBlock.y+m.indexLabelTextBlock.height/2<d&&m.indexLabelTextBlock.y+m.indexLabelTextBlock.height/2+k>h&&(k=m.indexLabelTextBlock.y+m.indexLabelTextBlock.height/2+k-h);k=m.indexLabelTextBlock.y+k;d=0;d="right"===m.hemisphere?w.x+Math.sqrt(Math.pow(z,2)-Math.pow(k-w.y,2)):w.x-Math.sqrt(Math.pow(z,2)-Math.pow(k-w.y,2));r=w.x+y*
+Math.cos(m.midAngle);p=w.y+y*Math.sin(m.midAngle);p=Math.sqrt(Math.pow(d-r,2)+Math.pow(k-p,2));r=Math.acos(y/z);p=Math.acos((z*z+y*y-p*p)/(2*y*z));k=p<r?k-m.indexLabelTextBlock.y:0;d=null;for(h=1;h<l.length;h++)if(d=(a-h+n.length)%n.length,n[d].hemisphere!==n[a].hemisphere){d=null;break}else if(n[d].indexLabelText&&n[d].hemisphere===n[a].hemisphere&&d!==a&&(0>e(n[d],n[a])||("right"===n[a].hemisphere?n[d].indexLabelTextBlock.y<=n[a].indexLabelTextBlock.y:n[d].indexLabelTextBlock.y>=n[a].indexLabelTextBlock.y)))break;
+else d=null;r=d;p=f(a);h=d=0;0>k?(h="right"===m.hemisphere?r:p,c=k,null!==h&&(r=-k,k=m.indexLabelTextBlock.y-m.indexLabelTextBlock.height/2-(n[h].indexLabelTextBlock.y+n[h].indexLabelTextBlock.height/2),k-r<s&&(d=-r,q++,h=g(h,d),+h.toFixed(v)>+d.toFixed(v)&&(c=k>s?-(k-s):-(r-(h-d)))))):0<k&&(h="right"===m.hemisphere?p:r,c=k,null!==h&&(r=k,k=n[h].indexLabelTextBlock.y-n[h].indexLabelTextBlock.height/2-(m.indexLabelTextBlock.y+m.indexLabelTextBlock.height/2),k-r<s&&(d=r,q++,h=g(h,d),+h.toFixed(v)<+d.toFixed(v)&&
+(c=k>s?k-s:r-(d-h)))));c&&(k=m.indexLabelTextBlock.y+c,d=0,d="right"===m.hemisphere?w.x+Math.sqrt(Math.pow(z,2)-Math.pow(k-w.y,2)):w.x-Math.sqrt(Math.pow(z,2)-Math.pow(k-w.y,2)),m.midAngle>Math.PI/2-u&&m.midAngle<Math.PI/2+u?(h=(a-1+n.length)%n.length,h=n[h],r=n[(a+1+n.length)%n.length],"left"===m.hemisphere&&"right"===h.hemisphere&&d>h.indexLabelTextBlock.x?d=h.indexLabelTextBlock.x-15:"right"===m.hemisphere&&("left"===r.hemisphere&&d<r.indexLabelTextBlock.x)&&(d=r.indexLabelTextBlock.x+15)):m.midAngle>
+3*Math.PI/2-u&&m.midAngle<3*Math.PI/2+u&&(h=(a-1+n.length)%n.length,h=n[h],r=n[(a+1+n.length)%n.length],"right"===m.hemisphere&&"left"===h.hemisphere&&d<h.indexLabelTextBlock.x?d=h.indexLabelTextBlock.x+15:"left"===m.hemisphere&&("right"===r.hemisphere&&d>r.indexLabelTextBlock.x)&&(d=r.indexLabelTextBlock.x-15)),m.indexLabelTextBlock.y=k,m.indexLabelTextBlock.x=d,m.indexLabelAngle=Math.atan2(m.indexLabelTextBlock.y-w.y,m.indexLabelTextBlock.x-w.x))}return c}function k(){var a=p.plotArea.ctx;a.fillStyle=
+"grey";a.strokeStyle="grey";a.font="16px Arial";a.textBaseline="middle";for(var b=0,c=a=0,a=0;10>a&&(1>a||0<c);a++){y-=c;c=0;if("inside"!==h.indexLabelPlacement){z=y*t;for(b=0;b<l.length;b++){var k=n[b];k.indexLabelTextBlock.x=w.x+z*Math.cos(k.midAngle);k.indexLabelTextBlock.y=w.y+z*Math.sin(k.midAngle);k.indexLabelAngle=k.midAngle;k.radius=y}for(var q,u,b=0;b<l.length;b++){var k=n[b],A=f(b);if(null!==A){q=n[b];u=n[A];var D=0,D=e(q,u)-s;if(0>D){for(var C=u=q=0;C<l.length;C++)C!==b&&n[C].hemisphere===
+k.hemisphere&&(n[C].indexLabelTextBlock.y<k.indexLabelTextBlock.y?q++:u++);C=D/(q+u||1)*u;q=-1*(D-C);var E=u=0;"right"===k.hemisphere?(u=g(b,C),q=-1*(D-u),E=g(A,q),+E.toFixed(v)<+q.toFixed(v)&&+u.toFixed(v)<=+C.toFixed(v)&&g(b,-(q-E))):(u=g(A,C),q=-1*(D-u),E=g(b,q),+E.toFixed(v)<+q.toFixed(v)&&+u.toFixed(v)<=+C.toFixed(v)&&g(A,-(q-E)))}}}}else for(b=0;b<l.length;b++)k=n[b],z="pie"===h.type?0.7*y:0.8*y,D=w.x+z*Math.cos(k.midAngle),C=w.y+z*Math.sin(k.midAngle),k.indexLabelTextBlock.x=D,k.indexLabelTextBlock.y=
+C;for(b=0;b<l.length;b++)k=n[b],D=k.indexLabelTextBlock.measureText(),0!==D.height&&0!==D.width&&(D=D=0,"right"===k.hemisphere?(D=m.x2-(k.indexLabelTextBlock.x+k.indexLabelTextBlock.width+r),D*=-1):D=m.x1-(k.indexLabelTextBlock.x-k.indexLabelTextBlock.width-r),0<D&&(Math.abs(k.indexLabelTextBlock.y-k.indexLabelTextBlock.height/2-w.y)<y||Math.abs(k.indexLabelTextBlock.y+k.indexLabelTextBlock.height/2-w.y)<y)&&(D/=Math.abs(Math.cos(k.indexLabelAngle)),9<D&&(D*=0.3),D>c&&(c=D)),D=D=0,0<k.indexLabelAngle&&
+k.indexLabelAngle<Math.PI?(D=m.y2-(k.indexLabelTextBlock.y+k.indexLabelTextBlock.height/2+5),D*=-1):D=m.y1-(k.indexLabelTextBlock.y-k.indexLabelTextBlock.height/2-5),0<D&&Math.abs(k.indexLabelTextBlock.x-w.x)<y&&(D/=Math.abs(Math.sin(k.indexLabelAngle)),9<D&&(D*=0.3),D>c&&(c=D)));b=function(a,b,c){for(var d=[],e=0;d.push(n[b]),b!==c;b=(b+1+l.length)%l.length);d.sort(function(a,b){return a.y-b.y});for(b=0;b<d.length;b++)if(c=d[b],e<a)e+=c.indexLabelTextBlock.height,c.indexLabelTextBlock.text="",c.indexLabelText=
+"",c.indexLabelTextBlock.measureText();else break};A=k=-1;for(C=E=0;C<l.length;C++)if(q=n[C],q.indexLabelText){var F=f(C);null!==F&&(u=n[F],D=0,D=e(q,u),0>D&&d(q,u)?(0>k&&(k=C),F!==k&&(A=F),E+=-D):0<E&&(b(E,k,A),A=k=-1,E=0))}0<E&&b(E,k,A)}}var p=this;if(!(0>=a.dataSeriesIndexes.length)){for(var h=this.data[a.dataSeriesIndexes[0]],l=h.dataPoints,r=10,m=this.plotArea,q=0,n=[],s=2,t=1.3,u=20/180*Math.PI,v=6,w={x:(m.x2+m.x1)/2,y:(m.y2+m.y1)/2},y="inside"===h.indexLabelPlacement?0.92*Math.min(m.width,
+m.height)/2:0.8*Math.min(m.width,m.height)/2,z=y*t,C=0,A=0;A<l.length;A++)C+=Math.abs(l[A].y);0!==C&&(this.pieDoughnutClickHandler=function(a){p.isAnimating||(a=a.dataPoint,a.exploded=a.exploded?!1:!0,1<this.dataPoints.length&&p._animator.animate(0,500,function(a){c(a)}))},b(),k(),this.disableToolTip=!0,this._animator.animate(0,this.animatedRender?this.animationDuration:0,function(a){var b=p.plotArea.ctx;b.clearRect(m.x1,m.y1,m.width,m.height);b.fillStyle=p.backgroundColor;b.fillRect(m.x1,m.y1,m.width,
+m.height);a=n[0].startAngle+2*Math.PI*a;for(b=0;b<l.length;b++){var c=0===b?n[b].startAngle:d,d=c+(n[b].endAngle-n[b].startAngle),e=!1;d>a&&(d=a,e=!0);var f=l[b].color?l[b].color:h._colorSet[b%h._colorSet.length];d>c&&pa(p.plotArea.ctx,n[b].center,n[b].radius,f,h.type,c,d,h.fillOpacity);if(e)break}},function(){p.disableToolTip=!1;p._animator.animate(0,p.animatedRender?500:0,function(a){c(a)})}))}};v.prototype.animationRequestId=null;v.prototype.requestAnimFrame=function(){return window.requestAnimationFrame||
+window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){window.setTimeout(a,1E3/60)}}();v.prototype.cancelRequestAnimFrame=window.cancelAnimationFrame||window.webkitCancelRequestAnimationFrame||window.mozCancelRequestAnimationFrame||window.oCancelRequestAnimationFrame||window.msCancelRequestAnimationFrame||clearTimeout;aa.prototype.registerSpace=function(a,b){"top"===a?this._topOccupied+=b.height:"bottom"===a?
+this._bottomOccupied+=b.height:"left"===a?this._leftOccupied+=b.width:"right"===a&&(this._rightOccupied+=b.width)};aa.prototype.unRegisterSpace=function(a,b){"top"===a?this._topOccupied-=b.height:"bottom"===a?this._bottomOccupied-=b.height:"left"===a?this._leftOccupied-=b.width:"right"===a&&(this._rightOccupied-=b.width)};aa.prototype.getFreeSpace=function(){return{x1:this._leftOccupied,y1:this._topOccupied,x2:this.chart.width-this._rightOccupied,y2:this.chart.height-this._bottomOccupied,width:this.chart.width-
+this._rightOccupied-this._leftOccupied,height:this.chart.height-this._bottomOccupied-this._topOccupied}};aa.prototype.reset=function(){this._topOccupied=0;this._bottomOccupied=3;this._rightOccupied=this._leftOccupied=0};O(I,L);I.prototype.render=function(a){a&&this.ctx.save();var b=this.ctx.font;this.ctx.textBaseline=this.textBaseline;var c=0;this._isDirty&&this.measureText(this.ctx);this.ctx.translate(this.x,this.y+c);"middle"===this.textBaseline&&(c=-this._lineHeight/2);this.ctx.font=this._getFontString();
+this.ctx.rotate(Math.PI/180*this.angle);var d=0,e=this.padding,f=null;(0<this.borderThickness&&this.borderColor||this.backgroundColor)&&this.ctx.roundRect(0,c,this.width,this.height,this.cornerRadius,this.borderThickness,this.backgroundColor,this.borderColor);this.ctx.fillStyle=this.fontColor;for(c=0;c<this._wrappedText.lines.length;c++)f=this._wrappedText.lines[c],"right"===this.horizontalAlign?d=this.width-f.width-this.padding:"left"===this.horizontalAlign?d=this.padding:"center"===this.horizontalAlign&&
+(d=(this.width-2*this.padding)/2-f.width/2+this.padding),this.ctx.fillText(f.text,d,e),e+=f.height;this.ctx.font=b;a&&this.ctx.restore()};I.prototype.setText=function(a){this.text=a;this._isDirty=!0;this._wrappedText=null};I.prototype.measureText=function(){if(null===this.maxWidth)throw"Please set maxWidth and height for TextBlock";this._wrapText(this.ctx);this._isDirty=!1;return{width:this.width,height:this.height}};I.prototype._getLineWithWidth=function(a,b,c){a=String(a);if(!a)return{text:"",width:0};
+var d=c=0,e=a.length-1,f=Infinity;for(this.ctx.font=this._getFontString();d<=e;){var f=Math.floor((d+e)/2),g=a.substr(0,f+1);c=this.ctx.measureText(g).width;if(c<b)d=f+1;else if(c>b)e=f-1;else break}c>b&&1<g.length&&(g=g.substr(0,g.length-1),c=this.ctx.measureText(g).width);b=!0;if(g.length===a.length||" "===a[g.length])b=!1;b&&(a=g.split(" "),1<a.length&&a.pop(),g=a.join(" "),c=this.ctx.measureText(g).width);return{text:g,width:c}};I.prototype._wrapText=function(){var a=new String(Z(this.text)),
+b=[],c=this.ctx.font,d=0,e=0;for(this.ctx.font=this._getFontString();0<a.length;){var f=this.maxHeight-2*this.padding,g=this._getLineWithWidth(a,this.maxWidth-2*this.padding,!1);g.height=this._lineHeight;b.push(g);e=Math.max(e,g.width);d+=g.height;a=Z(a.slice(g.text.length,a.length));f&&d>f&&(g=b.pop(),d-=g.height)}this._wrappedText={lines:b,width:e,height:d};this.width=e+2*this.padding;this.height=d+2*this.padding;this.ctx.font=c};I.prototype._getFontString=function(){return ua("",this,null)};O(ba,
+L);ba.prototype.render=function(){if(this.text){var a=this.chart.layoutManager.getFreeSpace(),b=0,c=0,d=0,e=0,f=0,g,k;"top"===this.verticalAlign||"bottom"===this.verticalAlign?(e=a.width-2*this.margin,f=0.5*a.height-2*this.margin,d=0):"center"===this.verticalAlign&&("left"===this.horizontalAlign||"right"===this.horizontalAlign?(e=a.height-2*this.margin,f=0.5*a.width-2*this.margin):"center"===this.horizontalAlign&&(e=a.width-2*this.margin,f=0.5*a.height-2*this.margin));var f=new I(this.ctx,{fontSize:this.fontSize,
+fontFamily:this.fontFamily,fontColor:this.fontColor,fontStyle:this.fontStyle,fontWeight:this.fontWeight,horizontalAlign:this.horizontalAlign,verticalAlign:this.verticalAlign,borderColor:this.borderColor,borderThickness:this.borderThickness,backgroundColor:this.backgroundColor,maxWidth:e,maxHeight:f,cornerRadius:this.cornerRadius,text:this.text,padding:this.padding,textBaseline:"top"}),p=f.measureText();"top"===this.verticalAlign||"bottom"===this.verticalAlign?("top"===this.verticalAlign?(c=this.margin,
+k="top"):"bottom"===this.verticalAlign&&(c=a.y2-this.margin-p.height,k="bottom"),"left"===this.horizontalAlign?b=a.x1+this.margin:"center"===this.horizontalAlign?b=a.x1+(e/2-p.width/2)+this.margin:"right"===this.horizontalAlign&&(b=a.x2-this.margin-p.width),g=this.horizontalAlign,this.width=p.width,this.height=p.height):"center"===this.verticalAlign&&("left"===this.horizontalAlign?(b=a.x1+this.margin,c=a.y2-this.margin-(e/2-p.width/2),d=-90,k="left",this.width=p.height,this.height=p.width):"right"===
+this.horizontalAlign?(b=a.x2-this.margin,c=a.y1+this.margin+(e/2-p.width/2),d=90,k="right",this.width=p.height,this.height=p.width):"center"===this.horizontalAlign&&(c=a.y1+(a.height/2-p.height/2),b=a.x1+(a.width/2-p.width/2),k="center",this.width=p.width,this.height=p.height),g="center");f.x=b;f.y=c;f.angle=d;f.horizontalAlign=g;f.render(!0);this.chart.layoutManager.registerSpace(k,{width:this.width+2*this.margin,height:this.height+2*this.margin});this.bounds={x1:b,y1:c,x2:b+this.width,y2:c+this.height};
+this.ctx.textBaseline="top"}};O(ga,L);ga.prototype.render=function(){var a=this.chart.layoutManager.getFreeSpace(),b=null,c=0,d=0,e=0,f=0,g=[],k=[];"top"===this.verticalAlign||"bottom"===this.verticalAlign?(this.orientation="horizontal",b=this.verticalAlign,e=0.9*a.width,f=0.5*a.height):"center"===this.verticalAlign&&(this.orientation="vertical",b=this.horizontalAlign,e=0.5*a.width,f=0.9*a.height);for(var p=0;p<this.dataSeries.length;p++){var h=this.dataSeries[p],l=h.legendMarkerType?h.legendMarkerType:
+"line"!==h.type&&"stepLine"!==h.type&&"spline"!==h.type&&"scatter"!==h.type&&"bubble"!==h.type||!h.markerType?P.getDefaultLegendMarker(h.type):h.markerType,r=h.legendText?h.legendText:h.name,m=h.legendMarkerColor?h.legendMarkerColor:h.markerColor?h.markerColor:h._colorSet[0],q=h.markerSize||"line"!==h.type&&"stepLine"!==h.type&&"spline"!==h.type?0.6*this.lineHeight:0,n=h.legendMarkerBorderColor?h.legendMarkerBorderColor:h.markerBorderColor,s=h.legendMarkerBorderThickness?h.legendMarkerBorderThickness:
+h.markerBorderThickness?Math.max(1,Math.round(0.2*q)):0;if("pie"!==h.type&&"doughnut"!==h.type&&"funnel"!==h.type)l={markerType:l,markerColor:m,text:r,textBlock:null,chartType:h.type,markerSize:q,lineColor:h._colorSet[0],dataSeriesIndex:h.index,dataPointIndex:null,markerBorderColor:n,markerBorderThickness:s},g.push(l);else for(var t=0;t<h.dataPoints.length;t++)s=h.dataPoints[t],l=s.legendMarkerType?s.legendMarkerType:h.legendMarkerType?h.legendMarkerType:P.getDefaultLegendMarker(h.type),r=s.legendText?
+s.legendText:h.legendText?h.legendText:s.name?s.name:"DataPoint: "+(t+1),m=s.legendMarkerColor?s.legendMarkerColor:h.legendMarkerColor?h.legendMarkerColor:s.color?s.color:h.color?h.color:h._colorSet[t%h._colorSet.length],q=0===s.markerSize||0===h.markerSize&&!s.markerSize?0:0.6*this.lineHeight,n=s.legendMarkerBorderColor?s.legendMarkerBorderColor:h.legendMarkerBorderColor?h.legendMarkerBorderColor:s.markerBorderColor?s.markerBorderColor:h.markerBorderColor,s=s.legendMarkerBorderThickness?s.legendMarkerBorderThickness:
+h.legendMarkerBorderThickness?h.legendMarkerBorderThickness:s.markerBorderThickness||h.markerBorderThickness?Math.max(1,Math.round(0.2*q)):0,l={markerType:l,markerColor:m,text:r,textBlock:null,chartType:h.type,markerSize:q,dataSeriesIndex:p,dataPointIndex:t,markerBorderColor:n,markerBorderThickness:s},g.push(l)}if(0<g.length){h=null;for(p=t=0;p<g.length;p++){l=g[p];if("horizontal"===this.orientation){l.textBlock=new I(this.ctx,{x:0,y:0,maxWidth:e,maxHeight:this.lineHeight,angle:0,text:l.text,horizontalAlign:"left",
+fontSize:this.fontSize,fontFamily:this.fontFamily,fontWeight:this.fontWeight,fontColor:this.fontColor,fontStyle:this.fontStyle,textBaseline:"top"});l.textBlock.measureText();if(!h||h.width+l.textBlock.width+(0===h.width?0:this.horizontalSpacing)>e)h={items:[],width:0},k.push(h),this.height=k.length*(l.textBlock.height+5);l.textBlock.x=h.width;l.textBlock.y=0;h.width+=Math.round(l.textBlock.width+l.textBlock._lineHeight+(0===h.width?0:0.5*l.textBlock._lineHeight))}else this.height+this.lineHeight<
+f?(h={items:[],width:0},k.push(h),this.height=k.length*this.lineHeight):(h=k[t],t=(t+1)%k.length),l.textBlock=new I(this.ctx,{x:0,y:0,maxWidth:e,maxHeight:1.5*this.fontSize,angle:0,text:l.text,horizontalAlign:"left",fontSize:this.fontSize,fontFamily:this.fontFamily,fontWeight:this.fontWeight,fontColor:this.fontColor,fontStyle:this.fontStyle,textBaseline:"top"}),l.textBlock.measureText(),l.textBlock.x=h.width,l.textBlock.y=0,h.width+=l.textBlock.width+l.textBlock._lineHeight+(0===h.width?0:0.5*l.textBlock._lineHeight);
+h.items.push(l);this.width=Math.max(h.width,this.width)}this.height=k.length*this.lineHeight}"top"===this.verticalAlign?(d="left"===this.horizontalAlign?a.x1+2:"right"===this.horizontalAlign?a.x2-this.width-2:a.x1+a.width/2-this.width/2,c=a.y1):"center"===this.verticalAlign?(d="left"===this.horizontalAlign?a.x1+2:"right"===this.horizontalAlign?a.x2-this.width-2:a.x1+a.width/2-this.width/2,c=a.y1+a.height/2-this.height/2):"bottom"===this.verticalAlign&&(d="left"===this.horizontalAlign?a.x1+2:"right"===
+this.horizontalAlign?a.x2-this.width-2:a.x1+a.width/2-this.width/2,c=a.y2-this.height-5);this.items=g;for(p=0;p<this.items.length;p++)l=g[p],l.id=++this.chart._eventManager.lastObjectId,this.chart._eventManager.objectMap[l.id]={id:l.id,objectType:"legendItem",legendItemIndex:p,dataSeriesIndex:l.dataSeriesIndex,dataPointIndex:l.dataPointIndex};for(p=0;p<k.length;p++)for(h=k[p],a=0;a<h.items.length;a++){l=h.items[a];f=l.textBlock.x+d+(0===a?0.2*l.markerSize:0.4*this.lineHeight+0.2*l.markerSize);g=c+
+p*this.lineHeight;e=f;this.chart.data[l.dataSeriesIndex].visible||(this.ctx.globalAlpha=0.5);if("line"===l.chartType||"stepLine"===l.chartType||"spline"===l.chartType)this.ctx.strokeStyle=l.lineColor,this.ctx.lineWidth=Math.ceil(this.lineHeight/8),this.ctx.beginPath(),this.ctx.moveTo(f-0.1*this.lineHeight,g+this.lineHeight/2),this.ctx.lineTo(f+0.7*this.lineHeight,g+this.lineHeight/2),this.ctx.stroke(),e-=0.1*this.lineHeight;J.drawMarker(f+l.markerSize/2,g+this.lineHeight/2,this.ctx,l.markerType,l.markerSize,
+l.markerColor,l.markerBorderColor,l.markerBorderThickness);l.textBlock.x=f+Math.round(0.9*this.lineHeight);l.textBlock.y=g;l.textBlock.render(!0);this.chart.data[l.dataSeriesIndex].visible||(this.ctx.globalAlpha=1);f=C(l.id);this.ghostCtx.fillStyle=f;this.ghostCtx.beginPath();this.ghostCtx.fillRect(e,l.textBlock.y,l.textBlock.x+l.textBlock.width-e,l.textBlock.height);l.x1=this.chart._eventManager.objectMap[l.id].x1=e;l.y1=this.chart._eventManager.objectMap[l.id].y1=l.textBlock.y;l.x2=this.chart._eventManager.objectMap[l.id].x2=
+l.textBlock.x+l.textBlock.width;l.y2=this.chart._eventManager.objectMap[l.id].y2=l.textBlock.y+l.textBlock.height}this.chart.layoutManager.registerSpace(b,{width:this.width+2+2,height:this.height+5+5});this.bounds={x1:d,y1:c,x2:d+this.width,y2:c+this.height}};O(la,L);la.prototype.render=function(){var a=this.chart.layoutManager.getFreeSpace();this.ctx.fillStyle="red";this.ctx.fillRect(a.x1,a.y1,a.x2,a.y2)};O(P,L);P.prototype.getDefaultAxisPlacement=function(){var a=this.type;if("column"===a||"line"===
+a||"stepLine"===a||"spline"===a||"area"===a||"stepArea"===a||"splineArea"===a||"stackedColumn"===a||"stackedLine"===a||"bubble"===a||"scatter"===a||"stackedArea"===a||"stackedColumn100"===a||"stackedLine100"===a||"stackedArea100"===a||"candlestick"===a||"ohlc"===a||"rangeColumn"===a||"rangeArea"===a||"rangeSplineArea"===a)return"normal";if("bar"===a||"stackedBar"===a||"stackedBar100"===a||"rangeBar"===a)return"xySwapped";if("pie"===a||"doughnut"===a||"funnel"===a)return"none";window.console.log("Unknown Chart Type: "+
+a);return null};P.getDefaultLegendMarker=function(a){if("column"===a||"stackedColumn"===a||"stackedLine"===a||"bar"===a||"stackedBar"===a||"stackedBar100"===a||"bubble"===a||"scatter"===a||"stackedColumn100"===a||"stackedLine100"===a||"stepArea"===a||"candlestick"===a||"ohlc"===a||"rangeColumn"===a||"rangeBar"===a||"rangeArea"===a||"rangeSplineArea"===a)return"square";if("line"===a||"stepLine"===a||"spline"===a||"pie"===a||"doughnut"===a||"funnel"===a)return"circle";if("area"===a||"splineArea"===
+a||"stackedArea"===a||"stackedArea100"===a)return"triangle";window.console.log("Unknown Chart Type: "+a);return null};P.prototype.getDataPointAtX=function(a,b){if(!this.dataPoints||0===this.dataPoints.length)return null;var c={dataPoint:null,distance:Infinity,index:NaN},d=null,e=0,f=0,g=1,k=Infinity,p=0,h=0,l=0;"none"!==this.chart.plotInfo.axisPlacement&&(l=this.dataPoints[this.dataPoints.length-1].x-this.dataPoints[0].x,l=0<l?Math.min(Math.max((this.dataPoints.length-1)/l*(a-this.dataPoints[0].x)>>
+0,0),this.dataPoints.length):0);for(;;){f=0<g?l+e:l-e;if(0<=f&&f<this.dataPoints.length){var d=this.dataPoints[f],r=Math.abs(d.x-a);r<c.distance&&(c.dataPoint=d,c.distance=r,c.index=f);d=Math.abs(d.x-a);d<=k?k=d:0<g?p++:h++;if(1E3<p&&1E3<h)break}else if(0>l-e&&l+e>=this.dataPoints.length)break;-1===g?(e++,g=1):g=-1}return b||c.dataPoint.x!==a?b&&null!==c.dataPoint?c:null:c};P.prototype.getDataPointAtXY=function(a,b,c){if(!this.dataPoints||0===this.dataPoints.length)return null;c=c||!1;var d=[],e=
+0,f=0,g=1,k=!1,p=Infinity,h=0,l=0,r=0;"none"!==this.chart.plotInfo.axisPlacement&&(r=this.chart.axisX.getXValueAt({x:a,y:b}),f=this.dataPoints[this.dataPoints.length-1].x-this.dataPoints[0].x,r=0<f?Math.min(Math.max((this.dataPoints.length-1)/f*(r-this.dataPoints[0].x)>>0,0),this.dataPoints.length):0);for(;;){f=0<g?r+e:r-e;if(0<=f&&f<this.dataPoints.length){var m=this.chart._eventManager.objectMap[this.dataPointIds[f]],q=this.dataPoints[f],n=null;if(m){switch(this.type){case "column":case "stackedColumn":case "stackedColumn100":case "bar":case "stackedBar":case "stackedBar100":case "rangeColumn":case "rangeBar":a>=
+m.x1&&(a<=m.x2&&b>=m.y1&&b<=m.y2)&&(d.push({dataPoint:q,dataPointIndex:f,dataSeries:this,distance:Math.min(Math.abs(m.x1-a),Math.abs(m.x2-a),Math.abs(m.y1-b),Math.abs(m.y2-b))}),k=!0);break;case "line":case "stepLine":case "spline":case "area":case "stepArea":case "stackedArea":case "stackedArea100":case "splineArea":case "scatter":var s=T("markerSize",q,this)||4,t=c?20:s,n=Math.sqrt(Math.pow(m.x1-a,2)+Math.pow(m.y1-b,2));n<=t&&d.push({dataPoint:q,dataPointIndex:f,dataSeries:this,distance:n});f=Math.abs(m.x1-
+a);f<=p?p=f:0<g?h++:l++;n<=s/2&&(k=!0);break;case "rangeArea":case "rangeSplineArea":s=T("markerSize",q,this)||4;t=c?20:s;n=Math.min(Math.sqrt(Math.pow(m.x1-a,2)+Math.pow(m.y1-b,2)),Math.sqrt(Math.pow(m.x1-a,2)+Math.pow(m.y2-b,2)));n<=t&&d.push({dataPoint:q,dataPointIndex:f,dataSeries:this,distance:n});f=Math.abs(m.x1-a);f<=p?p=f:0<g?h++:l++;n<=s/2&&(k=!0);break;case "bubble":s=m.size;n=Math.sqrt(Math.pow(m.x1-a,2)+Math.pow(m.y1-b,2));n<=s/2&&(d.push({dataPoint:q,dataPointIndex:f,dataSeries:this,
+distance:n}),k=!0);break;case "pie":case "doughnut":s=m.center;t="doughnut"===this.type?0.6*m.radius:0;n=Math.sqrt(Math.pow(s.x-a,2)+Math.pow(s.y-b,2));n<m.radius&&n>t&&(n=Math.atan2(b-s.y,a-s.x),0>n&&(n+=2*Math.PI),n=Number(((180*(n/Math.PI)%360+360)%360).toFixed(12)),s=Number(((180*(m.startAngle/Math.PI)%360+360)%360).toFixed(12)),t=Number(((180*(m.endAngle/Math.PI)%360+360)%360).toFixed(12)),0===t&&1<m.endAngle&&(t=360),s>=t&&0!==q.y&&(t+=360,n<s&&(n+=360)),n>s&&n<t&&(d.push({dataPoint:q,dataPointIndex:f,
+dataSeries:this,distance:0}),k=!0));break;case "candlestick":if(a>=m.x1-m.borderThickness/2&&a<=m.x2+m.borderThickness/2&&b>=m.y2-m.borderThickness/2&&b<=m.y3+m.borderThickness/2||Math.abs(m.x2-a+m.x1-a)<m.borderThickness&&b>=m.y1&&b<=m.y4)d.push({dataPoint:q,dataPointIndex:f,dataSeries:this,distance:Math.min(Math.abs(m.x1-a),Math.abs(m.x2-a),Math.abs(m.y2-b),Math.abs(m.y3-b))}),k=!0;break;case "ohlc":if(Math.abs(m.x2-a+m.x1-a)<m.borderThickness&&b>=m.y2&&b<=m.y3||a>=m.x1&&a<=(m.x2+m.x1)/2&&b>=m.y1-
+m.borderThickness/2&&b<=m.y1+m.borderThickness/2||a>=(m.x1+m.x2)/2&&a<=m.x2&&b>=m.y4-m.borderThickness/2&&b<=m.y4+m.borderThickness/2)d.push({dataPoint:q,dataPointIndex:f,dataSeries:this,distance:Math.min(Math.abs(m.x1-a),Math.abs(m.x2-a),Math.abs(m.y2-b),Math.abs(m.y3-b))}),k=!0}if(k||1E3<h&&1E3<l)break}}else if(0>r-e&&r+e>=this.dataPoints.length)break;-1===g?(e++,g=1):g=-1}a=null;for(b=0;b<d.length;b++)a?d[b].distance<=a.distance&&(a=d[b]):a=d[b];return a};P.prototype.getMarkerProperties=function(a,
+b,c,d){var e=this.dataPoints;return{x:b,y:c,ctx:d,type:e[a].markerType?e[a].markerType:this.markerType,size:e[a].markerSize?e[a].markerSize:this.markerSize,color:e[a].markerColor?e[a].markerColor:this.markerColor?this.markerColor:e[a].color?e[a].color:this.color?this.color:this._colorSet[a%this._colorSet.length],borderColor:e[a].markerBorderColor?e[a].markerBorderColor:this.markerBorderColor?this.markerBorderColor:null,borderThickness:e[a].markerBorderThickness?e[a].markerBorderThickness:this.markerBorderThickness?
+this.markerBorderThickness:null}};O(A,L);A.prototype.createLabels=function(){var a,b=0,c,d=0,e=0,b=0;if("bottom"===this._position||"top"===this._position)b=this.lineCoordinates.width/Math.abs(this.maximum-this.minimum)*this.interval,d=this.labelAutoFit?"undefined"===typeof this._options.labelMaxWidth?0.9*b>>0:this.labelMaxWidth:"undefined"===typeof this._options.labelMaxWidth?0.7*this.chart.width>>0:this.labelMaxWidth,e="undefined"===typeof this._options.labelWrap||this.labelWrap?0.5*this.chart.height>>
+0:1.5*this.labelFontSize;else if("left"===this._position||"right"===this._position)b=this.lineCoordinates.height/Math.abs(this.maximum-this.minimum)*this.interval,d=this.labelAutoFit?"undefined"===typeof this._options.labelMaxWidth?0.3*this.chart.width>>0:this.labelMaxWidth:"undefined"===typeof this._options.labelMaxWidth?0.5*this.chart.width>>0:this.labelMaxWidth,e="undefined"===typeof this._options.labelWrap||this.labelWrap?2*b>>0:1.5*this.labelFontSize;if("axisX"===this.type&&"dateTime"===this.chart.plotInfo.axisXValueType)for(c=
+qa(new Date(this.maximum),this.interval,this.intervalType),b=this.intervalstartTimePercent;b<c;qa(b,this.interval,this.intervalType))a=b.getTime(),a="axisX"===this.type&&this.labels[a]?this.labels[a]:ya(b,this.valueFormatString,this.chart._cultureInfo),a=new I(this.ctx,{x:0,y:0,maxWidth:d,maxHeight:e,angle:this.labelAngle,text:this.prefix+a+this.suffix,horizontalAlign:"left",fontSize:this.labelFontSize,fontFamily:this.labelFontFamily,fontWeight:this.labelFontWeight,fontColor:this.labelFontColor,fontStyle:this.labelFontStyle,
+textBaseline:"middle"}),this._labels.push({position:b.getTime(),textBlock:a,effectiveHeight:null});else{c=this.maximum;if(this.labels&&this.labels.length){a=Math.ceil(this.interval);for(var f=Math.ceil(this.intervalstartTimePercent),g=!1,b=f;b<this.maximum;b+=a)if(this.labels[b])g=!0;else{g=!1;break}g&&(this.interval=a,this.intervalstartTimePercent=f)}for(b=this.intervalstartTimePercent;b<=c;b=parseFloat((b+this.interval).toFixed(14)))a="axisX"===this.type&&this.labels[b]?this.labels[b]:X(b,this.valueFormatString,
+this.chart._cultureInfo),a=new I(this.ctx,{x:0,y:0,maxWidth:d,maxHeight:e,angle:this.labelAngle,text:this.prefix+a+this.suffix,horizontalAlign:"left",fontSize:this.labelFontSize,fontFamily:this.labelFontFamily,fontWeight:this.labelFontWeight,fontColor:this.labelFontColor,fontStyle:this.labelFontStyle,textBaseline:"middle",borderThickness:0}),this._labels.push({position:b,textBlock:a,effectiveHeight:null})}for(b=0;b<this.stripLines.length;b++)c=this.stripLines[b],a=new I(this.ctx,{x:0,y:0,backgroundColor:c.labelBackgroundColor,
+maxWidth:d,maxHeight:e,angle:this.labelAngle,text:c.label,horizontalAlign:"left",fontSize:c.labelFontSize,fontFamily:c.labelFontFamily,fontWeight:c.labelFontWeight,fontColor:c.labelFontColor,fontStyle:c.labelFontStyle,textBaseline:"middle",borderThickness:0}),this._labels.push({position:c.value,textBlock:a,effectiveHeight:null,stripLine:c})};A.prototype.createLabelsAndCalculateWidth=function(){var a=0;this._labels=[];if("left"===this._position||"right"===this._position)for(this.createLabels(),i=0;i<
+this._labels.length;i++){var b=this._labels[i].textBlock.measureText(),c=0,c=0===this.labelAngle?b.width:b.width*Math.cos(Math.PI/180*Math.abs(this.labelAngle))+b.height/2*Math.sin(Math.PI/180*Math.abs(this.labelAngle));a<c&&(a=c);this._labels[i].effectiveWidth=c}return(this.title?ca(this.titleFontFamily,this.titleFontSize,this.titleFontWeight)+2:0)+a+this.tickLength+5};A.prototype.createLabelsAndCalculateHeight=function(){var a=0;this._labels=[];var b,c=0;this.createLabels();if("bottom"===this._position||
+"top"===this._position)for(c=0;c<this._labels.length;c++){b=this._labels[c].textBlock;b=b.measureText();var d=0,d=0===this.labelAngle?b.height:b.width*Math.sin(Math.PI/180*Math.abs(this.labelAngle))+b.height/2*Math.cos(Math.PI/180*Math.abs(this.labelAngle));a<d&&(a=d);this._labels[c].effectiveHeight=d}return(this.title?ca(this.titleFontFamily,this.titleFontSize,this.titleFontWeight)+2:0)+a+this.tickLength+5};A.setLayoutAndRender=function(a,b,c,d,e){var f,g,k,p=a.chart,h=p.ctx;a.calculateAxisParameters();
+b&&b.calculateAxisParameters();c&&c.calculateAxisParameters();if(b&&c&&"undefined"===typeof b._options.maximum&&"undefined"===typeof b._options.minimum&&"undefined"===typeof b._options.interval&&"undefined"===typeof c._options.maximum&&"undefined"===typeof c._options.minimum&&"undefined"===typeof c._options.interval){k=(b.maximum-b.minimum)/b.interval;var l=(c.maximum-c.minimum)/c.interval;k>l?c.maximum=c.interval*k+c.minimum:l>k&&(b.maximum=b.interval*l+b.minimum)}l=b?b.margin:0;if("normal"===d){a.lineCoordinates=
+{};var r=Math.ceil(b?b.createLabelsAndCalculateWidth():0);f=Math.round(e.x1+r+l);a.lineCoordinates.x1=f;l=Math.ceil(c?c.createLabelsAndCalculateWidth():0);g=Math.round(e.x2-l>a.chart.width-10?a.chart.width-10:e.x2-l);a.lineCoordinates.x2=g;a.lineCoordinates.width=Math.abs(g-f);var m=Math.ceil(a.createLabelsAndCalculateHeight());d=Math.round(e.y2-m-a.margin);k=Math.round(e.y2-a.margin);a.lineCoordinates.y1=d;a.lineCoordinates.y2=d;a.boundingRect={x1:f,y1:d,x2:g,y2:k,width:g-f,height:k-d};b&&(f=Math.round(e.x1+
+b.margin),d=Math.round(10>e.y1?10:e.y1),g=Math.round(e.x1+r+b.margin),k=Math.round(e.y2-m-a.margin),b.lineCoordinates={x1:g,y1:d,x2:g,y2:k,height:Math.abs(k-d)},b.boundingRect={x1:f,y1:d,x2:g,y2:k,width:g-f,height:k-d});c&&(f=Math.round(a.lineCoordinates.x2),d=Math.round(10>e.y1?10:e.y1),g=Math.round(f+l+c.margin),k=Math.round(e.y2-m-a.margin),c.lineCoordinates={x1:f,y1:d,x2:f,y2:k,height:Math.abs(k-d)},c.boundingRect={x1:f,y1:d,x2:g,y2:k,width:g-f,height:k-d});a.calculateValueToPixelconversionParameters();
+b&&b.calculateValueToPixelconversionParameters();c&&c.calculateValueToPixelconversionParameters();h.save();h.rect(5,a.boundingRect.y1,a.chart.width-10,a.boundingRect.height);h.clip();a.renderLabelsTicksAndTitle();h.restore();b&&b.renderLabelsTicksAndTitle();c&&c.renderLabelsTicksAndTitle()}else{r=Math.ceil(a.createLabelsAndCalculateWidth());b&&(b.lineCoordinates={},f=Math.round(e.x1+r+a.margin),g=Math.round(e.x2>b.chart.width-10?b.chart.width-10:e.x2),b.lineCoordinates.x1=f,b.lineCoordinates.x2=g,
+b.lineCoordinates.width=Math.abs(g-f));c&&(c.lineCoordinates={},f=Math.round(e.x1+r+a.margin),g=Math.round(e.x2>c.chart.width-10?c.chart.width-10:e.x2),c.lineCoordinates.x1=f,c.lineCoordinates.x2=g,c.lineCoordinates.width=Math.abs(g-f));var m=Math.ceil(b?b.createLabelsAndCalculateHeight():0),q=Math.ceil(c?c.createLabelsAndCalculateHeight():0);b&&(d=Math.round(e.y2-m-b.margin),k=Math.round(e.y2-l>b.chart.height-10?b.chart.height-10:e.y2-l),b.lineCoordinates.y1=d,b.lineCoordinates.y2=d,b.boundingRect=
+{x1:f,y1:d,x2:g,y2:k,width:g-f,height:m});c&&(d=Math.round(e.y1+c.margin),k=e.y1+c.margin+q,c.lineCoordinates.y1=k,c.lineCoordinates.y2=k,c.boundingRect={x1:f,y1:d,x2:g,y2:k,width:g-f,height:q});f=Math.round(e.x1+a.margin);d=Math.round(c?c.lineCoordinates.y2:10>e.y1?10:e.y1);g=Math.round(e.x1+r+a.margin);k=Math.round(b?b.lineCoordinates.y1:e.y2-l>a.chart.height-10?a.chart.height-10:e.y2-l);a.lineCoordinates={x1:g,y1:d,x2:g,y2:k,height:Math.abs(k-d)};a.boundingRect={x1:f,y1:d,x2:g,y2:k,width:g-f,height:k-
+d};a.calculateValueToPixelconversionParameters();b&&b.calculateValueToPixelconversionParameters();c&&c.calculateValueToPixelconversionParameters();b&&b.renderLabelsTicksAndTitle();c&&c.renderLabelsTicksAndTitle();a.renderLabelsTicksAndTitle()}p.preparePlotArea();e=a.chart.plotArea;h.save();h.rect(e.x1,e.y1,Math.abs(e.x2-e.x1),Math.abs(e.y2-e.y1));h.clip();a.renderStripLinesOfThicknessType("value");b&&b.renderStripLinesOfThicknessType("value");c&&c.renderStripLinesOfThicknessType("value");a.renderInterlacedColors();
+b&&b.renderInterlacedColors();c&&c.renderInterlacedColors();h.restore();a.renderGrid();b&&b.renderGrid();c&&c.renderGrid();a.renderAxisLine();b&&b.renderAxisLine();c&&c.renderAxisLine();a.renderStripLinesOfThicknessType("pixel");b&&b.renderStripLinesOfThicknessType("pixel");c&&c.renderStripLinesOfThicknessType("pixel")};A.prototype.renderLabelsTicksAndTitle=function(){var a=!1,b=0,c=1,d=0;0!==this.labelAngle&&360!==this.labelAngle&&(c=1.2);if("undefined"===typeof this._options.interval){if("bottom"===
+this._position||"top"===this._position){for(e=0;e<this._labels.length;e++)f=this._labels[e],f.position<this.minimum||f.stripLine||(f=f.textBlock.width*Math.cos(Math.PI/180*this.labelAngle)+f.textBlock.height*Math.sin(Math.PI/180*this.labelAngle),b+=f);b>this.lineCoordinates.width*c&&(a=!0)}if("left"===this._position||"right"===this._position){for(e=0;e<this._labels.length;e++)f=this._labels[e],f.position<this.minimum||f.stripLine||(f=f.textBlock.height*Math.cos(Math.PI/180*this.labelAngle)+f.textBlock.width*
+Math.sin(Math.PI/180*this.labelAngle),b+=f);b>this.lineCoordinates.height*c&&(a=!0)}}if("bottom"===this._position){for(var e=0,f,e=0;e<this._labels.length;e++)if(f=this._labels[e],!(f.position<this.minimum||f.position>this.maximum)){b=this.getPixelCoordinatesOnAxis(f.position);if(this.tickThickness&&!this._labels[e].stripLine||this._labels[e].stripLine&&"pixel"===this._labels[e].stripLine._thicknessType)this._labels[e].stripLine?(c=this._labels[e].stripLine,this.ctx.lineWidth=c.thickness,this.ctx.strokeStyle=
+c.color):(this.ctx.lineWidth=this.tickThickness,this.ctx.strokeStyle=this.tickColor),c=1===this.ctx.lineWidth%2?(b.x<<0)+0.5:b.x<<0,this.ctx.beginPath(),this.ctx.moveTo(c,b.y<<0),this.ctx.lineTo(c,b.y+this.tickLength<<0),this.ctx.stroke();if(!a||0===d++%2||this._labels[e].stripLine)0===f.textBlock.angle?(b.x-=f.textBlock.width/2,b.y+=this.tickLength+f.textBlock.fontSize/2):(b.x-=0>this.labelAngle?f.textBlock.width*Math.cos(Math.PI/180*this.labelAngle):0,b.y+=this.tickLength+Math.abs(0>this.labelAngle?
+f.textBlock.width*Math.sin(Math.PI/180*this.labelAngle)-5:5)),f.textBlock.x=b.x,f.textBlock.y=b.y,f.textBlock.render(!0)}this.title&&(this._titleTextBlock=new I(this.ctx,{x:this.lineCoordinates.x1,y:this.boundingRect.y2-this.titleFontSize-5,maxWidth:this.lineCoordinates.width,maxHeight:1.5*this.titleFontSize,angle:0,text:this.title,horizontalAlign:"center",fontSize:this.titleFontSize,fontFamily:this.titleFontFamily,fontWeight:this.titleFontWeight,fontColor:this.titleFontColor,fontStyle:this.titleFontStyle,
+textBaseline:"top"}),this._titleTextBlock.measureText(),this._titleTextBlock.x=this.lineCoordinates.x1+this.lineCoordinates.width/2-this._titleTextBlock.width/2,this._titleTextBlock.y=this.boundingRect.y2-this._titleTextBlock.height-3,this._titleTextBlock.render(!0))}else if("top"===this._position){for(e=0;e<this._labels.length;e++)if(f=this._labels[e],!(f.position<this.minimum||f.position>this.maximum)){b=this.getPixelCoordinatesOnAxis(f.position);if(this.tickThickness&&!this._labels[e].stripLine||
+this._labels[e].stripLine&&"pixel"===this._labels[e].stripLine._thicknessType)this._labels[e].stripLine?(c=this._labels[e].stripLine,this.ctx.lineWidth=c.thickness,this.ctx.strokeStyle=c.color):(this.ctx.lineWidth=this.tickThickness,this.ctx.strokeStyle=this.tickColor),c=1===this.ctx.lineWidth%2?(b.x<<0)+0.5:b.x<<0,this.ctx.beginPath(),this.ctx.moveTo(c,b.y<<0),this.ctx.lineTo(c,b.y-this.tickLength<<0),this.ctx.stroke();if(!a||0===d++%2||this._labels[e].stripLine)0===f.textBlock.angle?(b.x-=f.textBlock.width/
+2,b.y-=this.tickLength+f.textBlock.height/2):(b.x-=0<this.labelAngle?f.textBlock.width*Math.cos(Math.PI/180*this.labelAngle):0,b.y-=this.tickLength+Math.abs(0<this.labelAngle?f.textBlock.width*Math.sin(Math.PI/180*this.labelAngle)+5:5)),f.textBlock.x=b.x,f.textBlock.y=b.y,f.textBlock.render(!0)}this.title&&(this._titleTextBlock=new I(this.ctx,{x:this.lineCoordinates.x1,y:this.boundingRect.y1+1,maxWidth:this.lineCoordinates.width,maxHeight:1.5*this.titleFontSize,angle:0,text:this.title,horizontalAlign:"center",
+fontSize:this.titleFontSize,fontFamily:this.titleFontFamily,fontWeight:this.titleFontWeight,fontColor:this.titleFontColor,fontStyle:this.titleFontStyle,textBaseline:"top"}),this._titleTextBlock.measureText(),this._titleTextBlock.x=this.lineCoordinates.x1+this.lineCoordinates.width/2-this._titleTextBlock.width/2,this._titleTextBlock.render(!0))}else if("left"===this._position){for(e=0;e<this._labels.length;e++)if(f=this._labels[e],!(f.position<this.minimum||f.position>this.maximum)){b=this.getPixelCoordinatesOnAxis(f.position);
+if(this.tickThickness&&!this._labels[e].stripLine||this._labels[e].stripLine&&"pixel"===this._labels[e].stripLine._thicknessType)this._labels[e].stripLine?(c=this._labels[e].stripLine,this.ctx.lineWidth=c.thickness,this.ctx.strokeStyle=c.color):(this.ctx.lineWidth=this.tickThickness,this.ctx.strokeStyle=this.tickColor),c=1===this.ctx.lineWidth%2?(b.y<<0)+0.5:b.y<<0,this.ctx.beginPath(),this.ctx.moveTo(b.x<<0,c),this.ctx.lineTo(b.x-this.tickLength<<0,c),this.ctx.stroke();if(!a||0===d++%2||this._labels[e].stripLine)f.textBlock.x=
+b.x-f.textBlock.width*Math.cos(Math.PI/180*this.labelAngle)-this.tickLength-5,f.textBlock.y=0===this.labelAngle?b.y-f.textBlock.height/2+this.labelFontSize/2:b.y-f.textBlock.width*Math.sin(Math.PI/180*this.labelAngle),f.textBlock.render(!0)}this.title&&(this._titleTextBlock=new I(this.ctx,{x:this.boundingRect.x1+1,y:this.lineCoordinates.y2,maxWidth:this.lineCoordinates.height,maxHeight:1.5*this.titleFontSize,angle:-90,text:this.title,horizontalAlign:"center",fontSize:this.titleFontSize,fontFamily:this.titleFontFamily,
+fontWeight:this.titleFontWeight,fontColor:this.titleFontColor,fontStyle:this.titleFontStyle,textBaseline:"top"}),this._titleTextBlock.measureText(),this._titleTextBlock.y=this.lineCoordinates.height/2+this._titleTextBlock.width/2+this.lineCoordinates.y1,this._titleTextBlock.render(!0))}else if("right"===this._position){for(e=0;e<this._labels.length;e++)if(f=this._labels[e],!(f.position<this.minimum||f.position>this.maximum)){b=this.getPixelCoordinatesOnAxis(f.position);if(this.tickThickness&&!this._labels[e].stripLine||
+this._labels[e].stripLine&&"pixel"===this._labels[e].stripLine._thicknessType)this._labels[e].stripLine?(c=this._labels[e].stripLine,this.ctx.lineWidth=c.thickness,this.ctx.strokeStyle=c.color):(this.ctx.lineWidth=this.tickThickness,this.ctx.strokeStyle=this.tickColor),c=1===this.ctx.lineWidth%2?(b.y<<0)+0.5:b.y<<0,this.ctx.beginPath(),this.ctx.moveTo(b.x<<0,c),this.ctx.lineTo(b.x+this.tickLength<<0,c),this.ctx.stroke();if(!a||0===d++%2||this._labels[e].stripLine)f.textBlock.x=b.x+this.tickLength+
+5,f.textBlock.y=0===this.labelAngle?b.y-f.textBlock.height/2+this.labelFontSize/2:b.y,f.textBlock.render(!0)}this.title&&(this._titleTextBlock=new I(this.ctx,{x:this.boundingRect.x2-1,y:this.lineCoordinates.y2,maxWidth:this.lineCoordinates.height,maxHeight:1.5*this.titleFontSize,angle:90,text:this.title,horizontalAlign:"center",fontSize:this.titleFontSize,fontFamily:this.titleFontFamily,fontWeight:this.titleFontWeight,fontColor:this.titleFontColor,fontStyle:this.titleFontStyle,textBaseline:"top"}),
+this._titleTextBlock.measureText(),this._titleTextBlock.y=this.lineCoordinates.height/2-this._titleTextBlock.width/2+this.lineCoordinates.y1,this._titleTextBlock.render(!0))}};A.prototype.renderInterlacedColors=function(){var a=this.chart.plotArea.ctx,b,c,d=this.chart.plotArea,e=0;b=!0;if(("bottom"===this._position||"top"===this._position)&&this.interlacedColor)for(a.fillStyle=this.interlacedColor,e=0;e<this._labels.length;e++)this._labels[e].stripLine||(b?(b=this.getPixelCoordinatesOnAxis(this._labels[e].position),
+c=e+1>=this._labels.length?this.getPixelCoordinatesOnAxis(this.maximum):this.getPixelCoordinatesOnAxis(this._labels[e+1].position),a.fillRect(b.x,d.y1,Math.abs(c.x-b.x),Math.abs(d.y1-d.y2)),b=!1):b=!0);else if(("left"===this._position||"right"===this._position)&&this.interlacedColor)for(a.fillStyle=this.interlacedColor,e=0;e<this._labels.length;e++)this._labels[e].stripLine||(b?(c=this.getPixelCoordinatesOnAxis(this._labels[e].position),b=e+1>=this._labels.length?this.getPixelCoordinatesOnAxis(this.maximum):
+this.getPixelCoordinatesOnAxis(this._labels[e+1].position),a.fillRect(d.x1,b.y,Math.abs(d.x1-d.x2),Math.abs(b.y-c.y)),b=!1):b=!0);a.beginPath()};A.prototype.renderStripLinesOfThicknessType=function(a){if(this.stripLines&&0<this.stripLines.length&&a)for(var b=this.chart.plotArea.ctx,c=0,c=0;c<this.stripLines.length;c++){var d=this.stripLines[c];if(d._thicknessType===a&&("pixel"!==a||!(d.value<this.minimum||d.value>this.maximum))){var e=this.getPixelCoordinatesOnAxis(d.value),f=Math.abs("pixel"===a?
+d.thickness:this.conversionParameters.pixelPerUnit*d.thickness);if(!(0>=f)){b.strokeStyle=d.color;b.beginPath();C(d.id);var g,k,p,h;b.lineWidth=f;if("bottom"===this._position||"top"===this._position)g=k=1===b.lineWidth%2?(e.x<<0)+0.5:e.x<<0,p=this.chart.plotArea.y1,h=this.chart.plotArea.y2;else if("left"===this._position||"right"===this._position)p=h=1===b.lineWidth%2?(e.y<<0)+0.5:e.y<<0,g=this.chart.plotArea.x1,k=this.chart.plotArea.x2;b.moveTo(g,p);b.lineTo(k,h);b.stroke()}}}};A.prototype.renderGrid=
+function(){if(this.gridThickness&&0<this.gridThickness){var a=this.chart.ctx,b,c=this.chart.plotArea;a.lineWidth=this.gridThickness;a.strokeStyle=this.gridColor;if("bottom"===this._position||"top"===this._position)for(d=0;d<this._labels.length&&!this._labels[d].stripLine;d++)this._labels[d].position<this.minimum||this._labels[d].position>this.maximum||(a.beginPath(),b=this.getPixelCoordinatesOnAxis(this._labels[d].position),b=1===a.lineWidth%2?(b.x<<0)+0.5:b.x<<0,a.moveTo(b,c.y1<<0),a.lineTo(b,c.y2<<
+0),a.stroke());else if("left"===this._position||"right"===this._position)for(var d=0;d<this._labels.length&&!this._labels[d].stripLine;d++)this._labels[d].position<this.minimum||this._labels[d].position>this.maximum||(a.beginPath(),b=this.getPixelCoordinatesOnAxis(this._labels[d].position),b=1===a.lineWidth%2?(b.y<<0)+0.5:b.y<<0,a.moveTo(c.x1<<0,b),a.lineTo(c.x2<<0,b),a.stroke())}};A.prototype.renderAxisLine=function(){var a=this.chart.ctx;if("bottom"===this._position||"top"===this._position){if(this.lineThickness){a.lineWidth=
+this.lineThickness;a.strokeStyle=this.lineColor?this.lineColor:"black";var b=1===this.lineThickness%2?(this.lineCoordinates.y1<<0)+0.5:this.lineCoordinates.y1<<0;a.beginPath();a.moveTo(this.lineCoordinates.x1,b);a.lineTo(this.lineCoordinates.x2,b);a.stroke()}}else"left"!==this._position&&"right"!==this._position||!this.lineThickness||(a.lineWidth=this.lineThickness,a.strokeStyle=this.lineColor,b=1===this.lineThickness%2?(this.lineCoordinates.x1<<0)+0.5:this.lineCoordinates.x1<<0,a.beginPath(),a.moveTo(b,
+this.lineCoordinates.y1),a.lineTo(b,this.lineCoordinates.y2),a.stroke())};A.prototype.getPixelCoordinatesOnAxis=function(a){var b={},c=this.lineCoordinates.width,d=this.lineCoordinates.height;if("bottom"===this._position||"top"===this._position)c/=Math.abs(this.maximum-this.minimum),b.x=this.lineCoordinates.x1+c*(a-this.minimum),b.y=this.lineCoordinates.y1;if("left"===this._position||"right"===this._position)c=d/Math.abs(this.maximum-this.minimum),b.y=this.lineCoordinates.y2-c*(a-this.minimum),b.x=
+this.lineCoordinates.x2;return b};A.prototype.getXValueAt=function(a){if(!a)return null;var b=null;"left"===this._position?b=(this.chart.axisX.maximum-this.chart.axisX.minimum)/this.chart.axisX.lineCoordinates.height*(this.chart.axisX.lineCoordinates.y2-a.y)+this.chart.axisX.minimum:"bottom"===this._position&&(b=(this.chart.axisX.maximum-this.chart.axisX.minimum)/this.chart.axisX.lineCoordinates.width*(a.x-this.chart.axisX.lineCoordinates.x1)+this.chart.axisX.minimum);return b};A.prototype.calculateValueToPixelconversionParameters=
+function(a){a={pixelPerUnit:null,minimum:null,reference:null};var b=this.lineCoordinates.width,c=this.lineCoordinates.height;a.minimum=this.minimum;if("bottom"===this._position||"top"===this._position)a.pixelPerUnit=b/Math.abs(this.maximum-this.minimum),a.reference=this.lineCoordinates.x1;if("left"===this._position||"right"===this._position)a.pixelPerUnit=-1*c/Math.abs(this.maximum-this.minimum),a.reference=this.lineCoordinates.y2;this.conversionParameters=a};A.prototype.calculateAxisParameters=function(){var a=
+this.chart.layoutManager.getFreeSpace();"bottom"===this._position||"top"===this._position?(this.maxWidth=a.width,this.maxHeight=a.height):(this.maxWidth=a.height,this.maxHeight=a.width);var a="axisX"===this.type?500>this.maxWidth?8:Math.max(6,Math.floor(this.maxWidth/62)):Math.max(Math.floor(this.maxWidth/40),2),b,c,d,e;e=0;"axisX"===this.type?(b=null!==this.sessionVariables.internalMinimum?this.sessionVariables.internalMinimum:this.dataInfo.viewPortMin,c=null!==this.sessionVariables.internalMaximum?
+this.sessionVariables.internalMaximum:this.dataInfo.viewPortMax,0===c-b&&(c+=0.4,b-=0.4),d=Infinity!==this.dataInfo.minDiff?this.dataInfo.minDiff:1<c-b?0.5*Math.abs(c-b):1):"axisY"===this.type&&(b="undefined"===typeof this._options.minimum?this.dataInfo.viewPortMin:this._options.minimum,c="undefined"===typeof this._options.maximum?this.dataInfo.viewPortMax:this._options.maximum,0===b&&0===c?(c+=9,b=0):0===c-b?(e=Math.min(Math.abs(0.01*Math.abs(c)),5),c+=e,b-=e):(e=Math.min(Math.abs(0.01*Math.abs(c-
+b)),0.05),0!==c&&(c+=e),0!==b&&(b-=e)),this.includeZero&&"undefined"===typeof this._options.minimum&&0<b&&(b=0),this.includeZero&&"undefined"===typeof this._options.maximum&&0>c&&(c=0));"axisX"===this.type&&"dateTime"===this.chart.plotInfo.axisXValueType?(e=c-b,this.intervalType||(e/1<=a?(this.interval=1,this.intervalType="millisecond"):e/2<=a?(this.interval=2,this.intervalType="millisecond"):e/5<=a?(this.interval=5,this.intervalType="millisecond"):e/10<=a?(this.interval=10,this.intervalType="millisecond"):
+e/20<=a?(this.interval=20,this.intervalType="millisecond"):e/50<=a?(this.interval=50,this.intervalType="millisecond"):e/100<=a?(this.interval=100,this.intervalType="millisecond"):e/200<=a?(this.interval=200,this.intervalType="millisecond"):e/250<=a?(this.interval=250,this.intervalType="millisecond"):e/300<=a?(this.interval=300,this.intervalType="millisecond"):e/400<=a?(this.interval=400,this.intervalType="millisecond"):e/500<=a?(this.interval=500,this.intervalType="millisecond"):e/(1*z.secondDuration)<=
+a?(this.interval=1,this.intervalType="second"):e/(2*z.secondDuration)<=a?(this.interval=2,this.intervalType="second"):e/(5*z.secondDuration)<=a?(this.interval=5,this.intervalType="second"):e/(10*z.secondDuration)<=a?(this.interval=10,this.intervalType="second"):e/(15*z.secondDuration)<=a?(this.interval=15,this.intervalType="second"):e/(20*z.secondDuration)<=a?(this.interval=20,this.intervalType="second"):e/(30*z.secondDuration)<=a?(this.interval=30,this.intervalType="second"):e/(1*z.minuteDuration)<=
+a?(this.interval=1,this.intervalType="minute"):e/(2*z.minuteDuration)<=a?(this.interval=2,this.intervalType="minute"):e/(5*z.minuteDuration)<=a?(this.interval=5,this.intervalType="minute"):e/(10*z.minuteDuration)<=a?(this.interval=10,this.intervalType="minute"):e/(15*z.minuteDuration)<=a?(this.interval=15,this.intervalType="minute"):e/(20*z.minuteDuration)<=a?(this.interval=20,this.intervalType="minute"):e/(30*z.minuteDuration)<=a?(this.interval=30,this.intervalType="minute"):e/(1*z.hourDuration)<=
+a?(this.interval=1,this.intervalType="hour"):e/(2*z.hourDuration)<=a?(this.interval=2,this.intervalType="hour"):e/(3*z.hourDuration)<=a?(this.interval=3,this.intervalType="hour"):e/(6*z.hourDuration)<=a?(this.interval=6,this.intervalType="hour"):e/(1*z.dayDuration)<=a?(this.interval=1,this.intervalType="day"):e/(2*z.dayDuration)<=a?(this.interval=2,this.intervalType="day"):e/(4*z.dayDuration)<=a?(this.interval=4,this.intervalType="day"):e/(1*z.weekDuration)<=a?(this.interval=1,this.intervalType="week"):
+e/(2*z.weekDuration)<=a?(this.interval=2,this.intervalType="week"):e/(3*z.weekDuration)<=a?(this.interval=3,this.intervalType="week"):e/(1*z.monthDuration)<=a?(this.interval=1,this.intervalType="month"):e/(2*z.monthDuration)<=a?(this.interval=2,this.intervalType="month"):e/(3*z.monthDuration)<=a?(this.interval=3,this.intervalType="month"):e/(6*z.monthDuration)<=a?(this.interval=6,this.intervalType="month"):(this.interval=e/(1*z.yearDuration)<=a?1:e/(2*z.yearDuration)<=a?2:e/(4*z.yearDuration)<=a?
+4:Math.floor(A.getNiceNumber(e/(a-1),!0)/z.yearDuration),this.intervalType="year")),this.minimum=null!==this.sessionVariables.internalMinimum?this.sessionVariables.internalMinimum:b-d/2,this.maximum=this.sessionVariables.internalMaximum?this.sessionVariables.internalMaximum:c+d/2,this.valueFormatString||("year"===this.intervalType?this.valueFormatString="YYYY":"month"===this.intervalType?this.valueFormatString="MMM YYYY":"week"===this.intervalType?this.valueFormatString="MMM DD YYYY":"day"===this.intervalType?
+this.valueFormatString="MMM DD YYYY":"hour"===this.intervalType?this.valueFormatString="hh:mm TT":"minute"===this.intervalType?this.valueFormatString="hh:mm TT":"second"===this.intervalType?this.valueFormatString="hh:mm:ss TT":"millisecond"===this.intervalType&&(this.valueFormatString="fff'ms'")),this.intervalstartTimePercent=this.getLabelStartPoint(new Date(this.minimum),this.intervalType,this.interval)):(this.intervalType="number",e=A.getNiceNumber(c-b,!1),this.interval=this._options&&this._options.interval?
+this._options.interval:A.getNiceNumber(e/(a-1),!0),this.minimum=null!==this.sessionVariables.internalMinimum?this.sessionVariables.internalMinimum:Math.floor(b/this.interval)*this.interval,this.maximum=null!==this.sessionVariables.internalMaximum?this.sessionVariables.internalMaximum:Math.ceil(c/this.interval)*this.interval,"axisX"===this.type?(null===this.sessionVariables.internalMinimum&&(this.minimum=b-d/2),this.sessionVariables.internalMaximum||(this.maximum=c+d/2),this.intervalstartTimePercent=
+Math.floor((this.minimum+0.2*this.interval)/this.interval)*this.interval):"axisY"===this.type&&(this.intervalstartTimePercent=this.minimum));"axisX"===this.type&&(this._absoluteMinimum=this._options&&"undefined"!==typeof this._options.minimum?this._options.minimum:this.dataInfo.min-d/2,this._absoluteMaximum=this._options&&"undefined"!==typeof this._options.maximum?this._options.maximum:this.dataInfo.max+d/2);if(!this.valueFormatString&&(this.valueFormatString="#,##0.##",e=Math.abs(this.maximum-this.minimum),
+1>e&&(b=Math.floor(Math.abs(Math.log(e)/Math.LN10))+2,2<b)))for(c=0;c<b-2;c++)this.valueFormatString+="#"};A.getNiceNumber=function(a,b){var c=Math.floor(Math.log(a)/Math.LN10),d=a/Math.pow(10,c);return Number(((b?1.5>d?1:3>d?2:7>d?5:10:1>=d?1:2>=d?2:5>=d?5:10)*Math.pow(10,c)).toFixed(20))};A.prototype.getLabelStartPoint=function(){var a=Y(this.interval,this.intervalType),a=new Date(Math.floor(this.minimum/a)*a);if("millisecond"!==this.intervalType)if("second"===this.intervalType)0<a.getMilliseconds()&&
+(a.setSeconds(a.getSeconds()+1),a.setMilliseconds(0));else if("minute"===this.intervalType){if(0<a.getSeconds()||0<a.getMilliseconds())a.setMinutes(a.getMinutes()+1),a.setSeconds(0),a.setMilliseconds(0)}else if("hour"===this.intervalType){if(0<a.getMinutes()||0<a.getSeconds()||0<a.getMilliseconds())a.setHours(a.getHours()+1),a.setMinutes(0),a.setSeconds(0),a.setMilliseconds(0)}else if("day"===this.intervalType){if(0<a.getHours()||0<a.getMinutes()||0<a.getSeconds()||0<a.getMilliseconds())a.setDate(a.getDate()+
+1),a.setHours(0),a.setMinutes(0),a.setSeconds(0),a.setMilliseconds(0)}else if("week"===this.intervalType){if(0<a.getDay()||0<a.getHours()||0<a.getMinutes()||0<a.getSeconds()||0<a.getMilliseconds())a.setDate(a.getDate()+(7-a.getDay())),a.setHours(0),a.setMinutes(0),a.setSeconds(0),a.setMilliseconds(0)}else if("month"===this.intervalType){if(1<a.getDate()||0<a.getHours()||0<a.getMinutes()||0<a.getSeconds()||0<a.getMilliseconds())a.setMonth(a.getMonth()+1),a.setDate(1),a.setHours(0),a.setMinutes(0),
+a.setSeconds(0),a.setMilliseconds(0)}else"year"===this.intervalType&&(0<a.getMonth()||1<a.getDate()||0<a.getHours()||0<a.getMinutes()||0<a.getSeconds()||0<a.getMilliseconds())&&(a.setFullYear(a.getFullYear()+1),a.setMonth(0),a.setDate(1),a.setHours(0),a.setMinutes(0),a.setSeconds(0),a.setMilliseconds(0));return a};O(ma,L);O(N,L);N.prototype._initialize=function(){if(this.enabled){this.container=document.createElement("div");this.container.setAttribute("class","canvasjs-chart-tooltip");this.container.style.position=
+"absolute";this.container.style.height="auto";this.container.style.boxShadow="1px 1px 2px 2px rgba(0,0,0,0.1)";this.container.style.zIndex="1000";this.container.style.display="none";var a;a='<div style=" width: auto;height: auto;min-width: 50px;';a+="line-height: 20px;";a+="margin: 0px 0px 0px 0px;";a+="padding: 5px;";a+="font-family: Calibri, Arial, Georgia, serif;";a+="font-weight: 400;";a+="font-style: "+(t?"italic;":"normal;");a+="font-size: 14px;";a+="color: #000000;";a+="text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1);";
+a+="text-align: left;";a+="border: 2px solid gray;";a+=t?"background: rgba(255,255,255,.9);":"background: rgb(255,255,255);";a+="text-indent: 0px;";a+="white-space: nowrap;";a+="border-radius: 5px;";a+="-moz-user-select:none;";a+="-khtml-user-select: none;";a+="-webkit-user-select: none;";a+="-ms-user-select: none;";a+="user-select: none;";t||(a+="filter: alpha(opacity = 90);",a+="filter: progid:DXImageTransform.Microsoft.Shadow(Strength=3, Direction=135, Color='#666666');");a+='} "> Sample Tooltip</div>';
+this.container.innerHTML=a;this.contentDiv=this.container.firstChild;this.container.style.borderRadius=this.contentDiv.style.borderRadius;this.chart._canvasJSContainer.appendChild(this.container)}};N.prototype.mouseMoveHandler=function(a,b){this._lastUpdated&&40>(new Date).getTime()-this._lastUpdated||(this._lastUpdated=(new Date).getTime(),this._updateToolTip(a,b))};N.prototype._updateToolTip=function(a,b){if(this.enabled&&!this.chart.disableToolTip){if("undefined"===typeof a||"undefined"===typeof b){if(isNaN(this._prevX)||
+isNaN(this._prevY))return;a=this._prevX;b=this._prevY}else this._prevX=a,this._prevY=b;var c=null,d=null,e=[],f=0;if(this.shared&&"none"!==this.chart.plotInfo.axisPlacement){f="xySwapped"===this.chart.plotInfo.axisPlacement?(this.chart.axisX.maximum-this.chart.axisX.minimum)/this.chart.axisX.lineCoordinates.height*(this.chart.axisX.lineCoordinates.y2-b)+this.chart.axisX.minimum:(this.chart.axisX.maximum-this.chart.axisX.minimum)/this.chart.axisX.lineCoordinates.width*(a-this.chart.axisX.lineCoordinates.x1)+
+this.chart.axisX.minimum;c=[];for(d=0;d<this.chart.data.length;d++){var g=this.chart.data[d].getDataPointAtX(f,!0);g&&0<=g.index&&(g.dataSeries=this.chart.data[d],null!==g.dataPoint.y&&c.push(g))}if(0===c.length)return;c.sort(function(a,b){return a.distance-b.distance});f=c[0];for(d=0;d<c.length;d++)c[d].dataPoint.x.valueOf()===f.dataPoint.x.valueOf()&&e.push(c[d]);c=null}else if((g=this.chart.getDataPointAtXY(a,b,!0))?(this.currentDataPointIndex=g.dataPointIndex,this.currentSeriesIndex=g.dataSeries.index):
+t?(g=ta(a,b,this.chart._eventManager.ghostCtx),0<g&&"undefined"!==typeof this.chart._eventManager.objectMap[g]?(eventObject=this.chart._eventManager.objectMap[g],this.currentSeriesIndex=eventObject.dataSeriesIndex,this.currentDataPointIndex=0<=eventObject.dataPointIndex?eventObject.dataPointIndex:-1):this.currentDataPointIndex=-1):this.currentDataPointIndex=-1,0<=this.currentSeriesIndex){d=this.chart.data[this.currentSeriesIndex];g={};if(0<=this.currentDataPointIndex)c=d.dataPoints[this.currentDataPointIndex],
+g.dataSeries=d,g.dataPoint=c,g.index=this.currentDataPointIndex,g.distance=Math.abs(c.x-f);else if("line"===d.type||"stepLine"===d.type||"spline"===d.type||"area"===d.type||"stepArea"===d.type||"splineArea"===d.type||"stackedArea"===d.type||"stackedArea100"===d.type||"rangeArea"===d.type||"rangeSplineArea"===d.type||"candlestick"===d.type||"ohlc"===d.type)f=(this.chart.axisX.maximum-this.chart.axisX.minimum)/this.chart.axisX.lineCoordinates.width*(a-this.chart.axisX.lineCoordinates.x1)+this.chart.axisX.minimum.valueOf(),
+g=d.getDataPointAtX(f,!0),g.dataSeries=d,this.currentDataPointIndex=g.index,c=g.dataPoint;else return;null!==g.dataPoint.y&&e.push(g)}if(0<e.length)if(this.highlightObjects(e),f="",f=this.getToolTipInnerHTML({entries:e}),null!==f){this.contentDiv.innerHTML=f;this.contentDiv.innerHTML=f;f=!1;"none"===this.container.style.display&&(f=!0,this.container.style.display="block");try{this.contentDiv.style.borderRightColor=this.contentDiv.style.borderLeftColor=this.contentDiv.style.borderColor=this.borderColor?
+this.borderColor:e[0].dataPoint.color?e[0].dataPoint.color:e[0].dataSeries.color?e[0].dataSeries.color:e[0].dataSeries._colorSet[e[0].index%e[0].dataSeries._colorSet.length]}catch(k){}"pie"===e[0].dataSeries.type||"doughnut"===e[0].dataSeries.type||"funnel"===e[0].dataSeries.type||"bar"===e[0].dataSeries.type||"rangeBar"===e[0].dataSeries.type||"stackedBar"===e[0].dataSeries.type||"stackedBar100"===e[0].dataSeries.type?toolTipLeft=a-10-this.container.clientWidth:(toolTipLeft=this.chart.axisX.lineCoordinates.width/
+Math.abs(this.chart.axisX.maximum-this.chart.axisX.minimum)*Math.abs(e[0].dataPoint.x-this.chart.axisX.minimum)+this.chart.axisX.lineCoordinates.x1+0.5-this.container.clientWidth<<0,toolTipLeft-=10);0>toolTipLeft&&(toolTipLeft+=this.container.clientWidth+20);toolTipLeft+this.container.clientWidth>this.chart._container.clientWidth&&(toolTipLeft=Math.max(0,this.chart._container.clientWidth-this.container.clientWidth));toolTipLeft+="px";e=1!==e.length||this.shared||"line"!==e[0].dataSeries.type&&"stepLine"!==
+e[0].dataSeries.type&&"spline"!==e[0].dataSeries.type&&"area"!==e[0].dataSeries.type&&"stepArea"!==e[0].dataSeries.type&&"splineArea"!==e[0].dataSeries.type&&"stackedArea"!==e[0].dataSeries.type&&"stackedArea100"!==e[0].dataSeries.type?"bar"===e[0].dataSeries.type||"rangeBar"===e[0].dataSeries.type||"stackedBar"===e[0].dataSeries.type||"stackedBar100"===e[0].dataSeries.type?e[0].dataSeries.axisX.lineCoordinates.y2-e[0].dataSeries.axisX.lineCoordinates.height/Math.abs(e[0].dataSeries.axisX.maximum-
+e[0].dataSeries.axisX.minimum)*Math.abs(e[0].dataPoint.x-e[0].dataSeries.axisX.minimum)+0.5<<0:b:e[0].dataSeries.axisY.lineCoordinates.y2-e[0].dataSeries.axisY.lineCoordinates.height/Math.abs(e[0].dataSeries.axisY.maximum-e[0].dataSeries.axisY.minimum)*Math.abs(e[0].dataPoint.y-e[0].dataSeries.axisY.minimum)+0.5<<0;e=-e+10;0<e+this.container.clientHeight+5&&(e-=e+this.container.clientHeight+5-0);this.container.style.left=toolTipLeft;this.container.style.bottom=e+"px";!this.animationEnabled||f?this.disableAnimation():
+this.enableAnimation()}else this.hide(!1)}};N.prototype.highlightObjects=function(a){if(this.enabled){var b=this.chart.overlaidCanvasCtx;this.chart.resetOverlayedCanvas();b.save();for(var c=0,d=0;d<a.length;d++){var e=a[d];if((e=this.chart._eventManager.objectMap[e.dataSeries.dataPointIds[e.index]])&&e.objectType&&"dataPoint"===e.objectType){var c=this.chart.data[e.dataSeriesIndex],f=e.dataPointIndex;if("line"===c.type||"stepLine"===c.type||"spline"===c.type||"scatter"===c.type||"area"===c.type||
+"stepArea"===c.type||"splineArea"===c.type||"stackedArea"===c.type||"stackedArea100"===c.type||"rangeArea"===c.type||"rangeSplineArea"===c.type){var g=c.getMarkerProperties(f,e.x1,e.y1,this.chart.overlaidCanvasCtx);g.size=Math.max(1.5*g.size<<0,10);g.borderColor=g.borderColor||"#FFFFFF";g.borderThickness=g.borderThickness||Math.ceil(0.1*g.size);J.drawMarkers([g]);"undefined"!==typeof e.y2&&(g=c.getMarkerProperties(f,e.x1,e.y2,this.chart.overlaidCanvasCtx),g.size=Math.max(1.5*g.size<<0,10),g.borderColor=
+g.borderColor||"#FFFFFF",g.borderThickness=g.borderThickness||Math.ceil(0.1*g.size),J.drawMarkers([g]))}else"bubble"===c.type?(g=c.getMarkerProperties(f,e.x1,e.y1,this.chart.overlaidCanvasCtx),g.size=e.size,g.color="white",g.borderColor="white",b.globalAlpha=0.3,J.drawMarkers([g]),b.globalAlpha=1):"column"===c.type||"stackedColumn"===c.type||"stackedColumn100"===c.type||"bar"===c.type||"rangeBar"===c.type||"stackedBar"===c.type||"stackedBar100"===c.type||"rangeColumn"===c.type?F(b,e.x1,e.y1,e.x2,
+e.y2,"white",0,null,!1,!1,!1,!1,0.3):"pie"===c.type||"doughnut"===c.type?pa(b,e.center,e.radius,"white",c.type,e.startAngle,e.endAngle,0.3):"candlestick"===c.type?(b.globalAlpha=1,b.strokeStyle=e.color,b.lineWidth=2*e.borderThickness,c=0===b.lineWidth%2?0:0.5,b.beginPath(),b.moveTo(e.x3-c,e.y2),b.lineTo(e.x3-c,Math.min(e.y1,e.y4)),b.stroke(),b.beginPath(),b.moveTo(e.x3-c,Math.max(e.y1,e.y4)),b.lineTo(e.x3-c,e.y3),b.stroke(),F(b,e.x1,Math.min(e.y1,e.y4),e.x2,Math.max(e.y1,e.y4),"transparent",2*e.borderThickness,
+e.color,!1,!1,!1,!1),b.globalAlpha=1):"ohlc"===c.type&&(b.globalAlpha=1,b.strokeStyle=e.color,b.lineWidth=2*e.borderThickness,c=0===b.lineWidth%2?0:0.5,b.beginPath(),b.moveTo(e.x3-c,e.y2),b.lineTo(e.x3-c,e.y3),b.stroke(),b.beginPath(),b.moveTo(e.x3,e.y1),b.lineTo(e.x1,e.y1),b.stroke(),b.beginPath(),b.moveTo(e.x3,e.y4),b.lineTo(e.x2,e.y4),b.stroke(),b.globalAlpha=1)}}b.globalAlpha=1;b.beginPath()}};N.prototype.getToolTipInnerHTML=function(a){a=a.entries;for(var b=null,c=null,d=null,e=0,f="",g=!0,k=
+0;k<a.length;k++)if(a[k].dataSeries.toolTipContent||a[k].dataPoint.toolTipContent){g=!1;break}if(g&&this.content&&"function"===typeof this.content)b=this.content({entries:a});else if(this.shared){for(var p="",k=0;k<a.length;k++)if(c=a[k].dataSeries,d=a[k].dataPoint,e=a[k].index,f="",0===k&&(g&&!this.content)&&(p+="undefined"!==typeof this.chart.axisX.labels[d.x]?this.chart.axisX.labels[d.x]:"{x}",p+="</br>",p=this.chart.replaceKeywordsWithValue(p,d,c,e)),null!==d.toolTipContent&&("undefined"!==typeof d.toolTipContent||
+null!==c._options.toolTipContent)){if("line"===c.type||"stepLine"===c.type||"spline"===c.type||"area"===c.type||"stepArea"===c.type||"splineArea"===c.type||"column"===c.type||"bar"===c.type||"scatter"===c.type||"stackedColumn"===c.type||"stackedColumn100"===c.type||"stackedBar"===c.type||"stackedBar100"===c.type||"stackedArea"===c.type||"stackedArea100"===c.type)f+=d.toolTipContent?d.toolTipContent:c.toolTipContent?c.toolTipContent:this.content&&"function"!==typeof this.content?this.content:"<span style='\"'color:{color};'\"'>{name}:</span>&nbsp;&nbsp;{y}";
+else if("bubble"===c.type)f+=d.toolTipContent?d.toolTipContent:c.toolTipContent?c.toolTipContent:this.content&&"function"!==typeof this.content?this.content:"<span style='\"'color:{color};'\"'>{name}:</span>&nbsp;&nbsp;{y}, &nbsp;&nbsp;{z}";else if("pie"===c.type||"doughnut"===c.type||"funnel"===c.type)f+=d.toolTipContent?d.toolTipContent:c.toolTipContent?c.toolTipContent:this.content&&"function"!==typeof this.content?this.content:"&nbsp;&nbsp;{y}";else if("rangeColumn"===c.type||"rangeBar"===c.type||
+"rangeArea"===c.type||"rangeSplineArea"===c.type)f+=d.toolTipContent?d.toolTipContent:c.toolTipContent?c.toolTipContent:this.content&&"function"!==typeof this.content?this.content:"<span style='\"'color:{color};'\"'>{name}:</span>&nbsp;&nbsp;{y[0]},&nbsp;{y[1]}";else if("candlestick"===c.type||"ohlc"===c.type)f+=d.toolTipContent?d.toolTipContent:c.toolTipContent?c.toolTipContent:this.content&&"function"!==typeof this.content?this.content:"<span style='\"'color:{color};'\"'>{name}:</span><br/>Open: &nbsp;&nbsp;{y[0]}<br/>High: &nbsp;&nbsp;&nbsp;{y[1]}<br/>Low:&nbsp;&nbsp;&nbsp;{y[2]}<br/>Close: &nbsp;&nbsp;{y[3]}";
+null===b&&(b="");b+=this.chart.replaceKeywordsWithValue(f,d,c,e);k<a.length-1&&(b+="</br>")}null!==b&&(b=p+b)}else{c=a[0].dataSeries;d=a[0].dataPoint;e=a[0].index;if(null===d.toolTipContent||"undefined"===typeof d.toolTipContent&&null===c._options.toolTipContent)return null;if("line"===c.type||"stepLine"===c.type||"spline"===c.type||"area"===c.type||"stepArea"===c.type||"splineArea"===c.type||"column"===c.type||"bar"===c.type||"scatter"===c.type||"stackedColumn"===c.type||"stackedColumn100"===c.type||
+"stackedBar"===c.type||"stackedBar100"===c.type||"stackedArea"===c.type||"stackedArea100"===c.type)f=d.toolTipContent?d.toolTipContent:c.toolTipContent?c.toolTipContent:this.content&&"function"!==typeof this.content?this.content:"<span style='\"'color:{color};'\"'>"+(d.label?"{label}":"{x}")+" :</span>&nbsp;&nbsp;{y}";else if("bubble"===c.type)f=d.toolTipContent?d.toolTipContent:c.toolTipContent?c.toolTipContent:this.content&&"function"!==typeof this.content?this.content:"<span style='\"'color:{color};'\"'>"+
+(d.label?"{label}":"{x}")+":</span>&nbsp;&nbsp;{y}, &nbsp;&nbsp;{z}";else if("pie"===c.type||"doughnut"===c.type||"funnel"===c.type)f=d.toolTipContent?d.toolTipContent:c.toolTipContent?c.toolTipContent:this.content&&"function"!==typeof this.content?this.content:(d.name?"{name}:&nbsp;&nbsp;":d.label?"{label}:&nbsp;&nbsp;":"")+"{y}";else if("rangeColumn"===c.type||"rangeBar"===c.type||"rangeArea"===c.type||"rangeSplineArea"===c.type)f=d.toolTipContent?d.toolTipContent:c.toolTipContent?c.toolTipContent:
+this.content&&"function"!==typeof this.content?this.content:"<span style='\"'color:{color};'\"'>"+(d.label?"{label}":"{x}")+" :</span>&nbsp;&nbsp;{y[0]}, &nbsp;{y[1]}";else if("candlestick"===c.type||"ohlc"===c.type)f=d.toolTipContent?d.toolTipContent:c.toolTipContent?c.toolTipContent:this.content&&"function"!==typeof this.content?this.content:"<span style='\"'color:{color};'\"'>"+(d.label?"{label}":"{x}")+"</span><br/>Open: &nbsp;&nbsp;{y[0]}<br/>High: &nbsp;&nbsp;&nbsp;{y[1]}<br/>Low: &nbsp;&nbsp;&nbsp;&nbsp;{y[2]}<br/>Close: &nbsp;&nbsp;{y[3]}";
+null===b&&(b="");b+=this.chart.replaceKeywordsWithValue(f,d,c,e)}return b};N.prototype.enableAnimation=function(){this.container.style.WebkitTransition||(this.container.style.WebkitTransition="left .2s ease-out, bottom .2s ease-out",this.container.style.MozTransition="left .2s ease-out, bottom .2s ease-out",this.container.style.MsTransition="left .2s ease-out, bottom .2s ease-out",this.container.style.transition="left .2s ease-out, bottom .2s ease-out")};N.prototype.disableAnimation=function(){this.container.style.WebkitTransition&&
+(this.container.style.WebkitTransition="",this.container.style.MozTransition="",this.container.style.MsTransition="",this.container.style.transition="")};N.prototype.hide=function(a){this.enabled&&(this.container.style.display="none",this.currentSeriesIndex=-1,this._prevY=this._prevX=NaN,("undefined"===typeof a||a)&&this.chart.resetOverlayedCanvas())};v.prototype.replaceKeywordsWithValue=function(a,b,c,d,e){var f=this;e="undefined"===typeof e?0:e;if((0<=c.type.indexOf("stacked")||"pie"===c.type||
+"doughnut"===c.type)&&(0<=a.indexOf("#percent")||0<=a.indexOf("#total"))){var g="#percent",k="#total",p=null;if(0<=c.type.indexOf("stacked"))k=0,p=b.x.getTime?b.x.getTime():b.x,p in c.plotUnit.yTotals&&(k=c.plotUnit.yTotals[p],g=isNaN(b.y)?0:100*(b.y/k));else if("pie"===c.type||"doughnut"===c.type){for(i=k=0;i<c.dataPoints.length;i++)isNaN(c.dataPoints[i].y)||(k+=c.dataPoints[i].y);g=isNaN(b.y)?0:100*(b.y/k)}do{p="";if(c.percentFormatString)p=c.percentFormatString;else{var p="#,##0.",h=Math.max(Math.ceil(Math.log(1/
+Math.abs(g))/Math.LN10),2);if(isNaN(h)||!isFinite(h))h=2;for(var l=0;l<h;l++)p+="#"}a=a.replace("#percent",X(g,p,f._cultureInfo));a=a.replace("#total",X(k,c.yValueFormatString?c.yValueFormatString:"#,##0.########"))}while(0<=a.indexOf("#percent")||0<=a.indexOf("#total"))}return a.replace(/\{.*?\}|"[^"]*"|'[^']*'/g,function(a){if('"'===a[0]&&'"'===a[a.length-1]||"'"===a[0]&&"'"===a[a.length-1])return a.slice(1,a.length-1);a=Z(a.slice(1,a.length-1));a=a.replace("#index",e);var g=null;try{var h=a.match(/(.*?)\s*\[\s*(.*?)\s*\]/);
+h&&0<h.length&&(g=Z(h[2]),a=Z(h[1]))}catch(k){}h=null;if("color"===a)return b.color?b.color:c.color?c.color:c._colorSet[d%c._colorSet.length];if(b.hasOwnProperty(a))h=b;else if(c.hasOwnProperty(a))h=c;else return"";h=h[a];null!==g&&(h=h[g]);return"x"===a?f.axisX&&"dateTime"===f.plotInfo.axisXValueType?ya(h,b.xValueFormatString?b.xValueFormatString:c.xValueFormatString?c.xValueFormatString:f.axisX&&f.axisX.valueFormatString?f.axisX.valueFormatString:"DD MMM YY",f._cultureInfo):X(h,b.xValueFormatString?
+b.xValueFormatString:c.xValueFormatString?c.xValueFormatString:"#,##0.########",f._cultureInfo):"y"===a?X(h,b.yValueFormatString?b.yValueFormatString:c.yValueFormatString?c.yValueFormatString:"#,##0.########",f._cultureInfo):"z"===a?X(h,b.zValueFormatString?b.zValueFormatString:c.zValueFormatString?c.zValueFormatString:"#,##0.########",f._cultureInfo):h})};$.prototype.reset=function(){this.lastObjectId=0;this.objectMap=[];this.rectangularRegionEventSubscriptions=[];this.previousDataPointEventObject=
+null;this.eventObjects=[];t&&(this.ghostCtx.clearRect(0,0,this.chart.width,this.chart.height),this.ghostCtx.beginPath())};$.prototype.getNewObjectTrackingId=function(){return++this.lastObjectId};$.prototype.mouseEventHandler=function(a){if("mousemove"===a.type||"click"===a.type){var b=[],c=ia(a),d=null;if((d=this.chart.getObjectAtXY(c.x,c.y,!1))&&"undefined"!==typeof this.objectMap[d])if(d=this.objectMap[d],"dataPoint"===d.objectType){var e=this.chart.data[d.dataSeriesIndex],f=e.dataPoints[d.dataPointIndex],
+g=d.dataPointIndex;d.eventParameter={x:c.x,y:c.y,dataPoint:f,dataSeries:e._options,dataPointIndex:g,dataSeriesIndex:e.index,chart:this.chart._publicChartReference};d.eventContext={context:f,userContext:f,mouseover:"mouseover",mousemove:"mousemove",mouseout:"mouseout",click:"click"};b.push(d);d=this.objectMap[e.id];d.eventParameter={x:c.x,y:c.y,dataPoint:f,dataSeries:e._options,dataPointIndex:g,dataSeriesIndex:e.index,chart:this.chart._publicChartReference};d.eventContext={context:e,userContext:e._options,
+mouseover:"mouseover",mousemove:"mousemove",mouseout:"mouseout",click:"click"};b.push(this.objectMap[e.id])}else"legendItem"===d.objectType&&(e=this.chart.data[d.dataSeriesIndex],f=null!==d.dataPointIndex?e.dataPoints[d.dataPointIndex]:null,d.eventParameter={x:c.x,y:c.y,dataSeries:e._options,dataPoint:f,dataPointIndex:d.dataPointIndex,dataSeriesIndex:d.dataSeriesIndex,chart:this.chart._publicChartReference},d.eventContext={context:this.chart.legend,userContext:this.chart.legend._options,mouseover:"itemmouseover",
+mousemove:"itemmousemove",mouseout:"itemmouseout",click:"itemclick"},b.push(d));e=[];for(c=0;c<this.mouseoveredObjectMaps.length;c++){f=!0;for(d=0;d<b.length;d++)if(b[d].id===this.mouseoveredObjectMaps[c].id){f=!1;break}f?this.fireEvent(this.mouseoveredObjectMaps[c],"mouseout",a):e.push(this.mouseoveredObjectMaps[c])}this.mouseoveredObjectMaps=e;for(c=0;c<b.length;c++){e=!1;for(d=0;d<this.mouseoveredObjectMaps.length;d++)if(b[c].id===this.mouseoveredObjectMaps[d].id){e=!0;break}e||(this.fireEvent(b[c],
+"mouseover",a),this.mouseoveredObjectMaps.push(b[c]));"click"===a.type?this.fireEvent(b[c],"click",a):"mousemove"===a.type&&this.fireEvent(b[c],"mousemove",a)}}};$.prototype.fireEvent=function(a,b,c){if(a&&b){var d=a.eventParameter,e=a.eventContext,f=a.eventContext.userContext;f&&(e&&f[e[b]])&&f[e[b]].call(f,d);"mouseout"!==b?f.cursor&&f.cursor!==c.target.style.cursor&&(c.target.style.cursor=f.cursor):(c.target.style.cursor=this.chart._defaultCursor,delete a.eventParameter,delete a.eventContext);
+"click"===b&&("dataPoint"===a.objectType&&this.chart.pieDoughnutClickHandler)&&this.chart.pieDoughnutClickHandler.call(this.chart.data[a.dataSeriesIndex],d)}};O(xa,L);oa.prototype.animate=function(a,b,c,d,e){var f=this;this.chart.isAnimating=!0;e=e||y.easing.linear;c&&this.animations.push({startTime:(new Date).getTime()+(a?a:0),duration:b,animationCallback:c,onComplete:d});for(a=[];0<this.animations.length;)if(b=this.animations.shift(),c=(new Date).getTime(),d=0,b.startTime<=c&&(d=e(Math.min(c-b.startTime,
+b.duration),0,1,b.duration),d=Math.min(d,1),isNaN(d)||!isFinite(d))&&(d=1),1>d&&a.push(b),b.animationCallback(d),1<=d&&b.onComplete)b.onComplete();this.animations=a;0<this.animations.length?this.animationRequestId=this.chart.requestAnimFrame.call(window,function(){f.animate.call(f)}):this.chart.isAnimating=!1};oa.prototype.cancelAllAnimations=function(){this.animations=[];this.animationRequestId&&this.chart.cancelRequestAnimFrame.call(window,this.animationRequestId);this.animationRequestId=null;this.chart.isAnimating=
+!1};var y={yScaleAnimation:function(a,b){if(0!==a){var c=b.dest,d=b.source.canvas,e=b.animationBase;c.drawImage(d,0,0,d.width,d.height,0,e-e*a,c.canvas.width/H,a*c.canvas.height/H)}},xScaleAnimation:function(a,b){if(0!==a){var c=b.dest,d=b.source.canvas,e=b.animationBase;c.drawImage(d,0,0,d.width,d.height,e-e*a,0,a*c.canvas.width/H,c.canvas.height/H)}},xClipAnimation:function(a,b){if(0!==a){var c=b.dest,d=b.source.canvas;c.save();0<a&&c.drawImage(d,0,0,d.width*a,d.height,0,0,d.width*a/H,d.height/
+H);c.restore()}},fadeInAnimation:function(a,b){if(0!==a){var c=b.dest,d=b.source.canvas;c.save();c.globalAlpha=a;c.drawImage(d,0,0,d.width,d.height,0,0,c.canvas.width/H,c.canvas.height/H);c.restore()}},easing:{linear:function(a,b,c,d){return c*a/d+b},easeOutQuad:function(a,b,c,d){return-c*(a/=d)*(a-2)+b},easeOutQuart:function(a,b,c,d){return-c*((a=a/d-1)*a*a*a-1)+b},easeInQuad:function(a,b,c,d){return c*(a/=d)*a+b},easeInQuart:function(a,b,c,d){return c*(a/=d)*a*a*a+b}}},J={drawMarker:function(a,
+b,c,d,e,f,g,k){if(c){var p=1;c.fillStyle=f?f:"#000000";c.strokeStyle=g?g:"#000000";c.lineWidth=k?k:0;"circle"===d?(c.moveTo(a,b),c.beginPath(),c.arc(a,b,e/2,0,2*Math.PI,!1),f&&c.fill(),k&&(g?c.stroke():(p=c.globalAlpha,c.globalAlpha=0.15,c.strokeStyle="black",c.stroke(),c.globalAlpha=p))):"square"===d?(c.beginPath(),c.rect(a-e/2,b-e/2,e,e),f&&c.fill(),k&&(g?c.stroke():(p=c.globalAlpha,c.globalAlpha=0.15,c.strokeStyle="black",c.stroke(),c.globalAlpha=p))):"triangle"===d?(c.beginPath(),c.moveTo(a-e/
+2,b+e/2),c.lineTo(a+e/2,b+e/2),c.lineTo(a,b-e/2),c.closePath(),f&&c.fill(),k&&(g?c.stroke():(p=c.globalAlpha,c.globalAlpha=0.15,c.strokeStyle="black",c.stroke(),c.globalAlpha=p)),c.beginPath()):"cross"===d&&(c.strokeStyle=f,c.lineWidth=e/4,c.beginPath(),c.moveTo(a-e/2,b-e/2),c.lineTo(a+e/2,b+e/2),c.stroke(),c.moveTo(a+e/2,b-e/2),c.lineTo(a-e/2,b+e/2),c.stroke())}},drawMarkers:function(a){for(var b=0;b<a.length;b++){var c=a[b];J.drawMarker(c.x,c.y,c.ctx,c.type,c.size,c.color,c.borderColor,c.borderThickness)}}},
+za={Chart:function(a,b){var c=new v(a,b,this);this.render=function(){c.render(this.options)};this.options=c._options},addColorSet:function(a,b){V[a]=b},addCultureInfo:function(a,b){na[a]=b}};za.Chart.version="v1.6.1 GA";window.CanvasJS=za})();
+/*
+  excanvas is used to support IE678 which do not implement HTML5 Canvas Element. You can safely remove the following excanvas code if you don't need to support older browsers.
+
+  Copyright 2006 Google Inc. https://code.google.com/p/explorercanvas/
+  Licensed under the Apache License, Version 2.0
+*/
+document.createElement("canvas").getContext||function(){function V(){return this.context_||(this.context_=new C(this))}function W(a,b,c){var g=M.call(arguments,2);return function(){return a.apply(b,g.concat(M.call(arguments)))}}function N(a){return String(a).replace(/&/g,"&amp;").replace(/"/g,"&quot;")}function O(a){a.namespaces.g_vml_||a.namespaces.add("g_vml_","urn:schemas-microsoft-com:vml","#default#VML");a.namespaces.g_o_||a.namespaces.add("g_o_","urn:schemas-microsoft-com:office:office","#default#VML");
+a.styleSheets.ex_canvas_||(a=a.createStyleSheet(),a.owningElement.id="ex_canvas_",a.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}")}function X(a){var b=a.srcElement;switch(a.propertyName){case "width":b.getContext().clearRect();b.style.width=b.attributes.width.nodeValue+"px";b.firstChild.style.width=b.clientWidth+"px";break;case "height":b.getContext().clearRect(),b.style.height=b.attributes.height.nodeValue+"px",b.firstChild.style.height=b.clientHeight+
+"px"}}function Y(a){a=a.srcElement;a.firstChild&&(a.firstChild.style.width=a.clientWidth+"px",a.firstChild.style.height=a.clientHeight+"px")}function D(){return[[1,0,0],[0,1,0],[0,0,1]]}function t(a,b){for(var c=D(),g=0;3>g;g++)for(var e=0;3>e;e++){for(var f=0,d=0;3>d;d++)f+=a[g][d]*b[d][e];c[g][e]=f}return c}function P(a,b){b.fillStyle=a.fillStyle;b.lineCap=a.lineCap;b.lineJoin=a.lineJoin;b.lineWidth=a.lineWidth;b.miterLimit=a.miterLimit;b.shadowBlur=a.shadowBlur;b.shadowColor=a.shadowColor;b.shadowOffsetX=
+a.shadowOffsetX;b.shadowOffsetY=a.shadowOffsetY;b.strokeStyle=a.strokeStyle;b.globalAlpha=a.globalAlpha;b.font=a.font;b.textAlign=a.textAlign;b.textBaseline=a.textBaseline;b.arcScaleX_=a.arcScaleX_;b.arcScaleY_=a.arcScaleY_;b.lineScale_=a.lineScale_}function Q(a){var b=a.indexOf("(",3),c=a.indexOf(")",b+1),b=a.substring(b+1,c).split(",");if(4!=b.length||"a"!=a.charAt(3))b[3]=1;return b}function E(a,b,c){return Math.min(c,Math.max(b,a))}function F(a,b,c){0>c&&c++;1<c&&c--;return 1>6*c?a+6*(b-a)*c:
+1>2*c?b:2>3*c?a+6*(b-a)*(2/3-c):a}function G(a){if(a in H)return H[a];var b,c=1;a=String(a);if("#"==a.charAt(0))b=a;else if(/^rgb/.test(a)){c=Q(a);b="#";for(var g,e=0;3>e;e++)g=-1!=c[e].indexOf("%")?Math.floor(255*(parseFloat(c[e])/100)):+c[e],b+=v[E(g,0,255)];c=+c[3]}else if(/^hsl/.test(a)){e=c=Q(a);b=parseFloat(e[0])/360%360;0>b&&b++;g=E(parseFloat(e[1])/100,0,1);e=E(parseFloat(e[2])/100,0,1);if(0==g)g=e=b=e;else{var f=0.5>e?e*(1+g):e+g-e*g,d=2*e-f;g=F(d,f,b+1/3);e=F(d,f,b);b=F(d,f,b-1/3)}b="#"+
+v[Math.floor(255*g)]+v[Math.floor(255*e)]+v[Math.floor(255*b)];c=c[3]}else b=Z[a]||a;return H[a]={color:b,alpha:c}}function C(a){this.m_=D();this.mStack_=[];this.aStack_=[];this.currentPath_=[];this.fillStyle=this.strokeStyle="#000";this.lineWidth=1;this.lineJoin="miter";this.lineCap="butt";this.miterLimit=1*q;this.globalAlpha=1;this.font="10px sans-serif";this.textAlign="left";this.textBaseline="alphabetic";this.canvas=a;var b="width:"+a.clientWidth+"px;height:"+a.clientHeight+"px;overflow:hidden;position:absolute",
+c=a.ownerDocument.createElement("div");c.style.cssText=b;a.appendChild(c);b=c.cloneNode(!1);b.style.backgroundColor="red";b.style.filter="alpha(opacity=0)";a.appendChild(b);this.element_=c;this.lineScale_=this.arcScaleY_=this.arcScaleX_=1}function R(a,b,c,g){a.currentPath_.push({type:"bezierCurveTo",cp1x:b.x,cp1y:b.y,cp2x:c.x,cp2y:c.y,x:g.x,y:g.y});a.currentX_=g.x;a.currentY_=g.y}function S(a,b){var c=G(a.strokeStyle),g=c.color,c=c.alpha*a.globalAlpha,e=a.lineScale_*a.lineWidth;1>e&&(c*=e);b.push("<g_vml_:stroke",
+' opacity="',c,'"',' joinstyle="',a.lineJoin,'"',' miterlimit="',a.miterLimit,'"',' endcap="',$[a.lineCap]||"square",'"',' weight="',e,'px"',' color="',g,'" />')}function T(a,b,c,g){var e=a.fillStyle,f=a.arcScaleX_,d=a.arcScaleY_,k=g.x-c.x,n=g.y-c.y;if(e instanceof w){var h=0,l=g=0,u=0,m=1;if("gradient"==e.type_){h=e.x1_/f;c=e.y1_/d;var p=s(a,e.x0_/f,e.y0_/d),h=s(a,h,c),h=180*Math.atan2(h.x-p.x,h.y-p.y)/Math.PI;0>h&&(h+=360);1E-6>h&&(h=0)}else p=s(a,e.x0_,e.y0_),g=(p.x-c.x)/k,l=(p.y-c.y)/n,k/=f*q,
+n/=d*q,m=x.max(k,n),u=2*e.r0_/m,m=2*e.r1_/m-u;f=e.colors_;f.sort(function(a,b){return a.offset-b.offset});d=f.length;p=f[0].color;c=f[d-1].color;k=f[0].alpha*a.globalAlpha;a=f[d-1].alpha*a.globalAlpha;for(var n=[],r=0;r<d;r++){var t=f[r];n.push(t.offset*m+u+" "+t.color)}b.push('<g_vml_:fill type="',e.type_,'"',' method="none" focus="100%"',' color="',p,'"',' color2="',c,'"',' colors="',n.join(","),'"',' opacity="',a,'"',' g_o_:opacity2="',k,'"',' angle="',h,'"',' focusposition="',g,",",l,'" />')}else e instanceof
+I?k&&n&&b.push("<g_vml_:fill",' position="',-c.x/k*f*f,",",-c.y/n*d*d,'"',' type="tile"',' src="',e.src_,'" />'):(e=G(a.fillStyle),b.push('<g_vml_:fill color="',e.color,'" opacity="',e.alpha*a.globalAlpha,'" />'))}function s(a,b,c){a=a.m_;return{x:q*(b*a[0][0]+c*a[1][0]+a[2][0])-r,y:q*(b*a[0][1]+c*a[1][1]+a[2][1])-r}}function z(a,b,c){isFinite(b[0][0])&&(isFinite(b[0][1])&&isFinite(b[1][0])&&isFinite(b[1][1])&&isFinite(b[2][0])&&isFinite(b[2][1]))&&(a.m_=b,c&&(a.lineScale_=aa(ba(b[0][0]*b[1][1]-b[0][1]*
+b[1][0]))))}function w(a){this.type_=a;this.r1_=this.y1_=this.x1_=this.r0_=this.y0_=this.x0_=0;this.colors_=[]}function I(a,b){if(!a||1!=a.nodeType||"IMG"!=a.tagName)throw new A("TYPE_MISMATCH_ERR");if("complete"!=a.readyState)throw new A("INVALID_STATE_ERR");switch(b){case "repeat":case null:case "":this.repetition_="repeat";break;case "repeat-x":case "repeat-y":case "no-repeat":this.repetition_=b;break;default:throw new A("SYNTAX_ERR");}this.src_=a.src;this.width_=a.width;this.height_=a.height}
+function A(a){this.code=this[a];this.message=a+": DOM Exception "+this.code}var x=Math,k=x.round,J=x.sin,K=x.cos,ba=x.abs,aa=x.sqrt,q=10,r=q/2;navigator.userAgent.match(/MSIE ([\d.]+)?/);var M=Array.prototype.slice;O(document);var U={init:function(a){a=a||document;a.createElement("canvas");a.attachEvent("onreadystatechange",W(this.init_,this,a))},init_:function(a){a=a.getElementsByTagName("canvas");for(var b=0;b<a.length;b++)this.initElement(a[b])},initElement:function(a){if(!a.getContext){a.getContext=
+V;O(a.ownerDocument);a.innerHTML="";a.attachEvent("onpropertychange",X);a.attachEvent("onresize",Y);var b=a.attributes;b.width&&b.width.specified?a.style.width=b.width.nodeValue+"px":a.width=a.clientWidth;b.height&&b.height.specified?a.style.height=b.height.nodeValue+"px":a.height=a.clientHeight}return a}};U.init();for(var v=[],d=0;16>d;d++)for(var B=0;16>B;B++)v[16*d+B]=d.toString(16)+B.toString(16);var Z={aliceblue:"#F0F8FF",antiquewhite:"#FAEBD7",aquamarine:"#7FFFD4",azure:"#F0FFFF",beige:"#F5F5DC",
+bisque:"#FFE4C4",black:"#000000",blanchedalmond:"#FFEBCD",blueviolet:"#8A2BE2",brown:"#A52A2A",burlywood:"#DEB887",cadetblue:"#5F9EA0",chartreuse:"#7FFF00",chocolate:"#D2691E",coral:"#FF7F50",cornflowerblue:"#6495ED",cornsilk:"#FFF8DC",crimson:"#DC143C",cyan:"#00FFFF",darkblue:"#00008B",darkcyan:"#008B8B",darkgoldenrod:"#B8860B",darkgray:"#A9A9A9",darkgreen:"#006400",darkgrey:"#A9A9A9",darkkhaki:"#BDB76B",darkmagenta:"#8B008B",darkolivegreen:"#556B2F",darkorange:"#FF8C00",darkorchid:"#9932CC",darkred:"#8B0000",
+darksalmon:"#E9967A",darkseagreen:"#8FBC8F",darkslateblue:"#483D8B",darkslategray:"#2F4F4F",darkslategrey:"#2F4F4F",darkturquoise:"#00CED1",darkviolet:"#9400D3",deeppink:"#FF1493",deepskyblue:"#00BFFF",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1E90FF",firebrick:"#B22222",floralwhite:"#FFFAF0",forestgreen:"#228B22",gainsboro:"#DCDCDC",ghostwhite:"#F8F8FF",gold:"#FFD700",goldenrod:"#DAA520",grey:"#808080",greenyellow:"#ADFF2F",honeydew:"#F0FFF0",hotpink:"#FF69B4",indianred:"#CD5C5C",indigo:"#4B0082",
+ivory:"#FFFFF0",khaki:"#F0E68C",lavender:"#E6E6FA",lavenderblush:"#FFF0F5",lawngreen:"#7CFC00",lemonchiffon:"#FFFACD",lightblue:"#ADD8E6",lightcoral:"#F08080",lightcyan:"#E0FFFF",lightgoldenrodyellow:"#FAFAD2",lightgreen:"#90EE90",lightgrey:"#D3D3D3",lightpink:"#FFB6C1",lightsalmon:"#FFA07A",lightseagreen:"#20B2AA",lightskyblue:"#87CEFA",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#B0C4DE",lightyellow:"#FFFFE0",limegreen:"#32CD32",linen:"#FAF0E6",magenta:"#FF00FF",mediumaquamarine:"#66CDAA",
+mediumblue:"#0000CD",mediumorchid:"#BA55D3",mediumpurple:"#9370DB",mediumseagreen:"#3CB371",mediumslateblue:"#7B68EE",mediumspringgreen:"#00FA9A",mediumturquoise:"#48D1CC",mediumvioletred:"#C71585",midnightblue:"#191970",mintcream:"#F5FFFA",mistyrose:"#FFE4E1",moccasin:"#FFE4B5",navajowhite:"#FFDEAD",oldlace:"#FDF5E6",olivedrab:"#6B8E23",orange:"#FFA500",orangered:"#FF4500",orchid:"#DA70D6",palegoldenrod:"#EEE8AA",palegreen:"#98FB98",paleturquoise:"#AFEEEE",palevioletred:"#DB7093",papayawhip:"#FFEFD5",
+peachpuff:"#FFDAB9",peru:"#CD853F",pink:"#FFC0CB",plum:"#DDA0DD",powderblue:"#B0E0E6",rosybrown:"#BC8F8F",royalblue:"#4169E1",saddlebrown:"#8B4513",salmon:"#FA8072",sandybrown:"#F4A460",seagreen:"#2E8B57",seashell:"#FFF5EE",sienna:"#A0522D",skyblue:"#87CEEB",slateblue:"#6A5ACD",slategray:"#708090",slategrey:"#708090",snow:"#FFFAFA",springgreen:"#00FF7F",steelblue:"#4682B4",tan:"#D2B48C",thistle:"#D8BFD8",tomato:"#FF6347",turquoise:"#40E0D0",violet:"#EE82EE",wheat:"#F5DEB3",whitesmoke:"#F5F5F5",yellowgreen:"#9ACD32"},
+H={},L={},$={butt:"flat",round:"round"},d=C.prototype;d.clearRect=function(){this.textMeasureEl_&&(this.textMeasureEl_.removeNode(!0),this.textMeasureEl_=null);this.element_.innerHTML=""};d.beginPath=function(){this.currentPath_=[]};d.moveTo=function(a,b){var c=s(this,a,b);this.currentPath_.push({type:"moveTo",x:c.x,y:c.y});this.currentX_=c.x;this.currentY_=c.y};d.lineTo=function(a,b){var c=s(this,a,b);this.currentPath_.push({type:"lineTo",x:c.x,y:c.y});this.currentX_=c.x;this.currentY_=c.y};d.bezierCurveTo=
+function(a,b,c,g,e,f){e=s(this,e,f);a=s(this,a,b);c=s(this,c,g);R(this,a,c,e)};d.quadraticCurveTo=function(a,b,c,g){a=s(this,a,b);c=s(this,c,g);g={x:this.currentX_+2/3*(a.x-this.currentX_),y:this.currentY_+2/3*(a.y-this.currentY_)};R(this,g,{x:g.x+(c.x-this.currentX_)/3,y:g.y+(c.y-this.currentY_)/3},c)};d.arc=function(a,b,c,g,e,f){c*=q;var d=f?"at":"wa",k=a+K(g)*c-r,n=b+J(g)*c-r;g=a+K(e)*c-r;e=b+J(e)*c-r;k!=g||f||(k+=0.125);a=s(this,a,b);k=s(this,k,n);g=s(this,g,e);this.currentPath_.push({type:d,
+x:a.x,y:a.y,radius:c,xStart:k.x,yStart:k.y,xEnd:g.x,yEnd:g.y})};d.rect=function(a,b,c,g){this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+c,b+g);this.lineTo(a,b+g);this.closePath()};d.strokeRect=function(a,b,c,g){var e=this.currentPath_;this.beginPath();this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+c,b+g);this.lineTo(a,b+g);this.closePath();this.stroke();this.currentPath_=e};d.fillRect=function(a,b,c,g){var e=this.currentPath_;this.beginPath();this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+
+c,b+g);this.lineTo(a,b+g);this.closePath();this.fill();this.currentPath_=e};d.createLinearGradient=function(a,b,c,g){var e=new w("gradient");e.x0_=a;e.y0_=b;e.x1_=c;e.y1_=g;return e};d.createRadialGradient=function(a,b,c,g,e,f){var d=new w("gradientradial");d.x0_=a;d.y0_=b;d.r0_=c;d.x1_=g;d.y1_=e;d.r1_=f;return d};d.drawImage=function(a,b){var c,g,e,d,r,y,n,h;e=a.runtimeStyle.width;d=a.runtimeStyle.height;a.runtimeStyle.width="auto";a.runtimeStyle.height="auto";var l=a.width,u=a.height;a.runtimeStyle.width=
+e;a.runtimeStyle.height=d;if(3==arguments.length)c=arguments[1],g=arguments[2],r=y=0,n=e=l,h=d=u;else if(5==arguments.length)c=arguments[1],g=arguments[2],e=arguments[3],d=arguments[4],r=y=0,n=l,h=u;else if(9==arguments.length)r=arguments[1],y=arguments[2],n=arguments[3],h=arguments[4],c=arguments[5],g=arguments[6],e=arguments[7],d=arguments[8];else throw Error("Invalid number of arguments");var m=s(this,c,g),p=[];p.push(" <g_vml_:group",' coordsize="',10*q,",",10*q,'"',' coordorigin="0,0"',' style="width:',
+10,"px;height:",10,"px;position:absolute;");if(1!=this.m_[0][0]||this.m_[0][1]||1!=this.m_[1][1]||this.m_[1][0]){var t=[];t.push("M11=",this.m_[0][0],",","M12=",this.m_[1][0],",","M21=",this.m_[0][1],",","M22=",this.m_[1][1],",","Dx=",k(m.x/q),",","Dy=",k(m.y/q),"");var v=s(this,c+e,g),w=s(this,c,g+d);c=s(this,c+e,g+d);m.x=x.max(m.x,v.x,w.x,c.x);m.y=x.max(m.y,v.y,w.y,c.y);p.push("padding:0 ",k(m.x/q),"px ",k(m.y/q),"px 0;filter:progid:DXImageTransform.Microsoft.Matrix(",t.join(""),", sizingmethod='clip');")}else p.push("top:",
+k(m.y/q),"px;left:",k(m.x/q),"px;");p.push(' ">','<g_vml_:image src="',a.src,'"',' style="width:',q*e,"px;"," height:",q*d,'px"',' cropleft="',r/l,'"',' croptop="',y/u,'"',' cropright="',(l-r-n)/l,'"',' cropbottom="',(u-y-h)/u,'"'," />","</g_vml_:group>");this.element_.insertAdjacentHTML("BeforeEnd",p.join(""))};d.stroke=function(a){var b=[];b.push("<g_vml_:shape",' filled="',!!a,'"',' style="position:absolute;width:',10,"px;height:",10,'px;"',' coordorigin="0,0"',' coordsize="',10*q,",",10*q,'"',
+' stroked="',!a,'"',' path="');for(var c={x:null,y:null},d={x:null,y:null},e=0;e<this.currentPath_.length;e++){var f=this.currentPath_[e];switch(f.type){case "moveTo":b.push(" m ",k(f.x),",",k(f.y));break;case "lineTo":b.push(" l ",k(f.x),",",k(f.y));break;case "close":b.push(" x ");f=null;break;case "bezierCurveTo":b.push(" c ",k(f.cp1x),",",k(f.cp1y),",",k(f.cp2x),",",k(f.cp2y),",",k(f.x),",",k(f.y));break;case "at":case "wa":b.push(" ",f.type," ",k(f.x-this.arcScaleX_*f.radius),",",k(f.y-this.arcScaleY_*
+f.radius)," ",k(f.x+this.arcScaleX_*f.radius),",",k(f.y+this.arcScaleY_*f.radius)," ",k(f.xStart),",",k(f.yStart)," ",k(f.xEnd),",",k(f.yEnd))}if(f){if(null==c.x||f.x<c.x)c.x=f.x;if(null==d.x||f.x>d.x)d.x=f.x;if(null==c.y||f.y<c.y)c.y=f.y;if(null==d.y||f.y>d.y)d.y=f.y}}b.push(' ">');a?T(this,b,c,d):S(this,b);b.push("</g_vml_:shape>");this.element_.insertAdjacentHTML("beforeEnd",b.join(""))};d.fill=function(){this.stroke(!0)};d.closePath=function(){this.currentPath_.push({type:"close"})};d.save=function(){var a=
+{};P(this,a);this.aStack_.push(a);this.mStack_.push(this.m_);this.m_=t(D(),this.m_)};d.restore=function(){this.aStack_.length&&(P(this.aStack_.pop(),this),this.m_=this.mStack_.pop())};d.translate=function(a,b){z(this,t([[1,0,0],[0,1,0],[a,b,1]],this.m_),!1)};d.rotate=function(a){var b=K(a);a=J(a);z(this,t([[b,a,0],[-a,b,0],[0,0,1]],this.m_),!1)};d.scale=function(a,b){this.arcScaleX_*=a;this.arcScaleY_*=b;z(this,t([[a,0,0],[0,b,0],[0,0,1]],this.m_),!0)};d.transform=function(a,b,c,d,e,f){z(this,t([[a,
+b,0],[c,d,0],[e,f,1]],this.m_),!0)};d.setTransform=function(a,b,c,d,e,f){z(this,[[a,b,0],[c,d,0],[e,f,1]],!0)};d.drawText_=function(a,b,c,d,e){var f=this.m_;d=0;var r=1E3,t=0,n=[],h;h=this.font;if(L[h])h=L[h];else{var l=document.createElement("div").style;try{l.font=h}catch(u){}h=L[h]={style:l.fontStyle||"normal",variant:l.fontVariant||"normal",weight:l.fontWeight||"normal",size:l.fontSize||10,family:l.fontFamily||"sans-serif"}}var l=h,m=this.element_;h={};for(var p in l)h[p]=l[p];p=parseFloat(m.currentStyle.fontSize);
+m=parseFloat(l.size);"number"==typeof l.size?h.size=l.size:-1!=l.size.indexOf("px")?h.size=m:-1!=l.size.indexOf("em")?h.size=p*m:-1!=l.size.indexOf("%")?h.size=p/100*m:-1!=l.size.indexOf("pt")?h.size=m/0.75:h.size=p;h.size*=0.981;p=h.style+" "+h.variant+" "+h.weight+" "+h.size+"px "+h.family;m=this.element_.currentStyle;l=this.textAlign.toLowerCase();switch(l){case "left":case "center":case "right":break;case "end":l="ltr"==m.direction?"right":"left";break;case "start":l="rtl"==m.direction?"right":
+"left";break;default:l="left"}switch(this.textBaseline){case "hanging":case "top":t=h.size/1.75;break;case "middle":break;default:case null:case "alphabetic":case "ideographic":case "bottom":t=-h.size/2.25}switch(l){case "right":d=1E3;r=0.05;break;case "center":d=r=500}b=s(this,b+0,c+t);n.push('<g_vml_:line from="',-d,' 0" to="',r,' 0.05" ',' coordsize="100 100" coordorigin="0 0"',' filled="',!e,'" stroked="',!!e,'" style="position:absolute;width:1px;height:1px;">');e?S(this,n):T(this,n,{x:-d,y:0},
+{x:r,y:h.size});e=f[0][0].toFixed(3)+","+f[1][0].toFixed(3)+","+f[0][1].toFixed(3)+","+f[1][1].toFixed(3)+",0,0";b=k(b.x/q)+","+k(b.y/q);n.push('<g_vml_:skew on="t" matrix="',e,'" ',' offset="',b,'" origin="',d,' 0" />','<g_vml_:path textpathok="true" />','<g_vml_:textpath on="true" string="',N(a),'" style="v-text-align:',l,";font:",N(p),'" /></g_vml_:line>');this.element_.insertAdjacentHTML("beforeEnd",n.join(""))};d.fillText=function(a,b,c,d){this.drawText_(a,b,c,d,!1)};d.strokeText=function(a,
+b,c,d){this.drawText_(a,b,c,d,!0)};d.measureText=function(a){this.textMeasureEl_||(this.element_.insertAdjacentHTML("beforeEnd",'<span style="position:absolute;top:-20000px;left:0;padding:0;margin:0;border:none;white-space:pre;"></span>'),this.textMeasureEl_=this.element_.lastChild);var b=this.element_.ownerDocument;this.textMeasureEl_.innerHTML="";this.textMeasureEl_.style.font=this.font;this.textMeasureEl_.appendChild(b.createTextNode(a));return{width:this.textMeasureEl_.offsetWidth}};d.clip=function(){};
+d.arcTo=function(){};d.createPattern=function(a,b){return new I(a,b)};w.prototype.addColorStop=function(a,b){b=G(b);this.colors_.push({offset:a,color:b.color,alpha:b.alpha})};d=A.prototype=Error();d.INDEX_SIZE_ERR=1;d.DOMSTRING_SIZE_ERR=2;d.HIERARCHY_REQUEST_ERR=3;d.WRONG_DOCUMENT_ERR=4;d.INVALID_CHARACTER_ERR=5;d.NO_DATA_ALLOWED_ERR=6;d.NO_MODIFICATION_ALLOWED_ERR=7;d.NOT_FOUND_ERR=8;d.NOT_SUPPORTED_ERR=9;d.INUSE_ATTRIBUTE_ERR=10;d.INVALID_STATE_ERR=11;d.SYNTAX_ERR=12;d.INVALID_MODIFICATION_ERR=
+13;d.NAMESPACE_ERR=14;d.INVALID_ACCESS_ERR=15;d.VALIDATION_ERR=16;d.TYPE_MISMATCH_ERR=17;G_vmlCanvasManager=U;CanvasRenderingContext2D=C;CanvasGradient=w;CanvasPattern=I;DOMException=A}();
diff --git a/y2015/http_status/www/lib/jquery-1.4.4.js b/y2015/http_status/www/lib/jquery-1.4.4.js
new file mode 100644
index 0000000..a4f1145
--- /dev/null
+++ b/y2015/http_status/www/lib/jquery-1.4.4.js
@@ -0,0 +1,7179 @@
+/*!
+ * jQuery JavaScript Library v1.4.4
+ * http://jquery.com/
+ *
+ * Copyright 2010, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2010, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Thu Nov 11 19:04:53 2010 -0500
+ */
+(function( window, undefined ) {
+
+// Use the correct document accordingly with window argument (sandbox)
+var document = window.document;
+var jQuery = (function() {
+
+// Define a local copy of jQuery
+var jQuery = function( selector, context ) {
+		// The jQuery object is actually just the init constructor 'enhanced'
+		return new jQuery.fn.init( selector, context );
+	},
+
+	// Map over jQuery in case of overwrite
+	_jQuery = window.jQuery,
+
+	// Map over the $ in case of overwrite
+	_$ = window.$,
+
+	// A central reference to the root jQuery(document)
+	rootjQuery,
+
+	// A simple way to check for HTML strings or ID strings
+	// (both of which we optimize for)
+	quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,
+
+	// Is it a simple selector
+	isSimple = /^.[^:#\[\.,]*$/,
+
+	// Check if a string has a non-whitespace character in it
+	rnotwhite = /\S/,
+	rwhite = /\s/,
+
+	// Used for trimming whitespace
+	trimLeft = /^\s+/,
+	trimRight = /\s+$/,
+
+	// Check for non-word characters
+	rnonword = /\W/,
+
+	// Check for digits
+	rdigit = /\d/,
+
+	// Match a standalone tag
+	rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
+
+	// JSON RegExp
+	rvalidchars = /^[\],:{}\s]*$/,
+	rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
+	rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
+	rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
+
+	// Useragent RegExp
+	rwebkit = /(webkit)[ \/]([\w.]+)/,
+	ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
+	rmsie = /(msie) ([\w.]+)/,
+	rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
+
+	// Keep a UserAgent string for use with jQuery.browser
+	userAgent = navigator.userAgent,
+
+	// For matching the engine and version of the browser
+	browserMatch,
+	
+	// Has the ready events already been bound?
+	readyBound = false,
+	
+	// The functions to execute on DOM ready
+	readyList = [],
+
+	// The ready event handler
+	DOMContentLoaded,
+
+	// Save a reference to some core methods
+	toString = Object.prototype.toString,
+	hasOwn = Object.prototype.hasOwnProperty,
+	push = Array.prototype.push,
+	slice = Array.prototype.slice,
+	trim = String.prototype.trim,
+	indexOf = Array.prototype.indexOf,
+	
+	// [[Class]] -> type pairs
+	class2type = {};
+
+jQuery.fn = jQuery.prototype = {
+	init: function( selector, context ) {
+		var match, elem, ret, doc;
+
+		// Handle $(""), $(null), or $(undefined)
+		if ( !selector ) {
+			return this;
+		}
+
+		// Handle $(DOMElement)
+		if ( selector.nodeType ) {
+			this.context = this[0] = selector;
+			this.length = 1;
+			return this;
+		}
+		
+		// The body element only exists once, optimize finding it
+		if ( selector === "body" && !context && document.body ) {
+			this.context = document;
+			this[0] = document.body;
+			this.selector = "body";
+			this.length = 1;
+			return this;
+		}
+
+		// Handle HTML strings
+		if ( typeof selector === "string" ) {
+			// Are we dealing with HTML string or an ID?
+			match = quickExpr.exec( selector );
+
+			// Verify a match, and that no context was specified for #id
+			if ( match && (match[1] || !context) ) {
+
+				// HANDLE: $(html) -> $(array)
+				if ( match[1] ) {
+					doc = (context ? context.ownerDocument || context : document);
+
+					// If a single string is passed in and it's a single tag
+					// just do a createElement and skip the rest
+					ret = rsingleTag.exec( selector );
+
+					if ( ret ) {
+						if ( jQuery.isPlainObject( context ) ) {
+							selector = [ document.createElement( ret[1] ) ];
+							jQuery.fn.attr.call( selector, context, true );
+
+						} else {
+							selector = [ doc.createElement( ret[1] ) ];
+						}
+
+					} else {
+						ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
+						selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes;
+					}
+					
+					return jQuery.merge( this, selector );
+					
+				// HANDLE: $("#id")
+				} else {
+					elem = document.getElementById( match[2] );
+
+					// Check parentNode to catch when Blackberry 4.6 returns
+					// nodes that are no longer in the document #6963
+					if ( elem && elem.parentNode ) {
+						// Handle the case where IE and Opera return items
+						// by name instead of ID
+						if ( elem.id !== match[2] ) {
+							return rootjQuery.find( selector );
+						}
+
+						// Otherwise, we inject the element directly into the jQuery object
+						this.length = 1;
+						this[0] = elem;
+					}
+
+					this.context = document;
+					this.selector = selector;
+					return this;
+				}
+
+			// HANDLE: $("TAG")
+			} else if ( !context && !rnonword.test( selector ) ) {
+				this.selector = selector;
+				this.context = document;
+				selector = document.getElementsByTagName( selector );
+				return jQuery.merge( this, selector );
+
+			// HANDLE: $(expr, $(...))
+			} else if ( !context || context.jquery ) {
+				return (context || rootjQuery).find( selector );
+
+			// HANDLE: $(expr, context)
+			// (which is just equivalent to: $(context).find(expr)
+			} else {
+				return jQuery( context ).find( selector );
+			}
+
+		// HANDLE: $(function)
+		// Shortcut for document ready
+		} else if ( jQuery.isFunction( selector ) ) {
+			return rootjQuery.ready( selector );
+		}
+
+		if (selector.selector !== undefined) {
+			this.selector = selector.selector;
+			this.context = selector.context;
+		}
+
+		return jQuery.makeArray( selector, this );
+	},
+
+	// Start with an empty selector
+	selector: "",
+
+	// The current version of jQuery being used
+	jquery: "1.4.4",
+
+	// The default length of a jQuery object is 0
+	length: 0,
+
+	// The number of elements contained in the matched element set
+	size: function() {
+		return this.length;
+	},
+
+	toArray: function() {
+		return slice.call( this, 0 );
+	},
+
+	// Get the Nth element in the matched element set OR
+	// Get the whole matched element set as a clean array
+	get: function( num ) {
+		return num == null ?
+
+			// Return a 'clean' array
+			this.toArray() :
+
+			// Return just the object
+			( num < 0 ? this.slice(num)[ 0 ] : this[ num ] );
+	},
+
+	// Take an array of elements and push it onto the stack
+	// (returning the new matched element set)
+	pushStack: function( elems, name, selector ) {
+		// Build a new jQuery matched element set
+		var ret = jQuery();
+
+		if ( jQuery.isArray( elems ) ) {
+			push.apply( ret, elems );
+		
+		} else {
+			jQuery.merge( ret, elems );
+		}
+
+		// Add the old object onto the stack (as a reference)
+		ret.prevObject = this;
+
+		ret.context = this.context;
+
+		if ( name === "find" ) {
+			ret.selector = this.selector + (this.selector ? " " : "") + selector;
+		} else if ( name ) {
+			ret.selector = this.selector + "." + name + "(" + selector + ")";
+		}
+
+		// Return the newly-formed element set
+		return ret;
+	},
+
+	// Execute a callback for every element in the matched set.
+	// (You can seed the arguments with an array of args, but this is
+	// only used internally.)
+	each: function( callback, args ) {
+		return jQuery.each( this, callback, args );
+	},
+	
+	ready: function( fn ) {
+		// Attach the listeners
+		jQuery.bindReady();
+
+		// If the DOM is already ready
+		if ( jQuery.isReady ) {
+			// Execute the function immediately
+			fn.call( document, jQuery );
+
+		// Otherwise, remember the function for later
+		} else if ( readyList ) {
+			// Add the function to the wait list
+			readyList.push( fn );
+		}
+
+		return this;
+	},
+	
+	eq: function( i ) {
+		return i === -1 ?
+			this.slice( i ) :
+			this.slice( i, +i + 1 );
+	},
+
+	first: function() {
+		return this.eq( 0 );
+	},
+
+	last: function() {
+		return this.eq( -1 );
+	},
+
+	slice: function() {
+		return this.pushStack( slice.apply( this, arguments ),
+			"slice", slice.call(arguments).join(",") );
+	},
+
+	map: function( callback ) {
+		return this.pushStack( jQuery.map(this, function( elem, i ) {
+			return callback.call( elem, i, elem );
+		}));
+	},
+	
+	end: function() {
+		return this.prevObject || jQuery(null);
+	},
+
+	// For internal use only.
+	// Behaves like an Array's method, not like a jQuery method.
+	push: push,
+	sort: [].sort,
+	splice: [].splice
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+jQuery.extend = jQuery.fn.extend = function() {
+	 var options, name, src, copy, copyIsArray, clone,
+		target = arguments[0] || {},
+		i = 1,
+		length = arguments.length,
+		deep = false;
+
+	// Handle a deep copy situation
+	if ( typeof target === "boolean" ) {
+		deep = target;
+		target = arguments[1] || {};
+		// skip the boolean and the target
+		i = 2;
+	}
+
+	// Handle case when target is a string or something (possible in deep copy)
+	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+		target = {};
+	}
+
+	// extend jQuery itself if only one argument is passed
+	if ( length === i ) {
+		target = this;
+		--i;
+	}
+
+	for ( ; i < length; i++ ) {
+		// Only deal with non-null/undefined values
+		if ( (options = arguments[ i ]) != null ) {
+			// Extend the base object
+			for ( name in options ) {
+				src = target[ name ];
+				copy = options[ name ];
+
+				// Prevent never-ending loop
+				if ( target === copy ) {
+					continue;
+				}
+
+				// Recurse if we're merging plain objects or arrays
+				if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+					if ( copyIsArray ) {
+						copyIsArray = false;
+						clone = src && jQuery.isArray(src) ? src : [];
+
+					} else {
+						clone = src && jQuery.isPlainObject(src) ? src : {};
+					}
+
+					// Never move original objects, clone them
+					target[ name ] = jQuery.extend( deep, clone, copy );
+
+				// Don't bring in undefined values
+				} else if ( copy !== undefined ) {
+					target[ name ] = copy;
+				}
+			}
+		}
+	}
+
+	// Return the modified object
+	return target;
+};
+
+jQuery.extend({
+	noConflict: function( deep ) {
+		window.$ = _$;
+
+		if ( deep ) {
+			window.jQuery = _jQuery;
+		}
+
+		return jQuery;
+	},
+	
+	// Is the DOM ready to be used? Set to true once it occurs.
+	isReady: false,
+
+	// A counter to track how many items to wait for before
+	// the ready event fires. See #6781
+	readyWait: 1,
+	
+	// Handle when the DOM is ready
+	ready: function( wait ) {
+		// A third-party is pushing the ready event forwards
+		if ( wait === true ) {
+			jQuery.readyWait--;
+		}
+
+		// Make sure that the DOM is not already loaded
+		if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) {
+			// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+			if ( !document.body ) {
+				return setTimeout( jQuery.ready, 1 );
+			}
+
+			// Remember that the DOM is ready
+			jQuery.isReady = true;
+
+			// If a normal DOM Ready event fired, decrement, and wait if need be
+			if ( wait !== true && --jQuery.readyWait > 0 ) {
+				return;
+			}
+
+			// If there are functions bound, to execute
+			if ( readyList ) {
+				// Execute all of them
+				var fn,
+					i = 0,
+					ready = readyList;
+
+				// Reset the list of functions
+				readyList = null;
+
+				while ( (fn = ready[ i++ ]) ) {
+					fn.call( document, jQuery );
+				}
+
+				// Trigger any bound ready events
+				if ( jQuery.fn.trigger ) {
+					jQuery( document ).trigger( "ready" ).unbind( "ready" );
+				}
+			}
+		}
+	},
+	
+	bindReady: function() {
+		if ( readyBound ) {
+			return;
+		}
+
+		readyBound = true;
+
+		// Catch cases where $(document).ready() is called after the
+		// browser event has already occurred.
+		if ( document.readyState === "complete" ) {
+			// Handle it asynchronously to allow scripts the opportunity to delay ready
+			return setTimeout( jQuery.ready, 1 );
+		}
+
+		// Mozilla, Opera and webkit nightlies currently support this event
+		if ( document.addEventListener ) {
+			// Use the handy event callback
+			document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+			
+			// A fallback to window.onload, that will always work
+			window.addEventListener( "load", jQuery.ready, false );
+
+		// If IE event model is used
+		} else if ( document.attachEvent ) {
+			// ensure firing before onload,
+			// maybe late but safe also for iframes
+			document.attachEvent("onreadystatechange", DOMContentLoaded);
+			
+			// A fallback to window.onload, that will always work
+			window.attachEvent( "onload", jQuery.ready );
+
+			// If IE and not a frame
+			// continually check to see if the document is ready
+			var toplevel = false;
+
+			try {
+				toplevel = window.frameElement == null;
+			} catch(e) {}
+
+			if ( document.documentElement.doScroll && toplevel ) {
+				doScrollCheck();
+			}
+		}
+	},
+
+	// See test/unit/core.js for details concerning isFunction.
+	// Since version 1.3, DOM methods and functions like alert
+	// aren't supported. They return false on IE (#2968).
+	isFunction: function( obj ) {
+		return jQuery.type(obj) === "function";
+	},
+
+	isArray: Array.isArray || function( obj ) {
+		return jQuery.type(obj) === "array";
+	},
+
+	// A crude way of determining if an object is a window
+	isWindow: function( obj ) {
+		return obj && typeof obj === "object" && "setInterval" in obj;
+	},
+
+	isNaN: function( obj ) {
+		return obj == null || !rdigit.test( obj ) || isNaN( obj );
+	},
+
+	type: function( obj ) {
+		return obj == null ?
+			String( obj ) :
+			class2type[ toString.call(obj) ] || "object";
+	},
+
+	isPlainObject: function( obj ) {
+		// Must be an Object.
+		// Because of IE, we also have to check the presence of the constructor property.
+		// Make sure that DOM nodes and window objects don't pass through, as well
+		if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+			return false;
+		}
+		
+		// Not own constructor property must be Object
+		if ( obj.constructor &&
+			!hasOwn.call(obj, "constructor") &&
+			!hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+			return false;
+		}
+		
+		// Own properties are enumerated firstly, so to speed up,
+		// if last one is own, then all properties are own.
+	
+		var key;
+		for ( key in obj ) {}
+		
+		return key === undefined || hasOwn.call( obj, key );
+	},
+
+	isEmptyObject: function( obj ) {
+		for ( var name in obj ) {
+			return false;
+		}
+		return true;
+	},
+	
+	error: function( msg ) {
+		throw msg;
+	},
+	
+	parseJSON: function( data ) {
+		if ( typeof data !== "string" || !data ) {
+			return null;
+		}
+
+		// Make sure leading/trailing whitespace is removed (IE can't handle it)
+		data = jQuery.trim( data );
+		
+		// Make sure the incoming data is actual JSON
+		// Logic borrowed from http://json.org/json2.js
+		if ( rvalidchars.test(data.replace(rvalidescape, "@")
+			.replace(rvalidtokens, "]")
+			.replace(rvalidbraces, "")) ) {
+
+			// Try to use the native JSON parser first
+			return window.JSON && window.JSON.parse ?
+				window.JSON.parse( data ) :
+				(new Function("return " + data))();
+
+		} else {
+			jQuery.error( "Invalid JSON: " + data );
+		}
+	},
+
+	noop: function() {},
+
+	// Evalulates a script in a global context
+	globalEval: function( data ) {
+		if ( data && rnotwhite.test(data) ) {
+			// Inspired by code by Andrea Giammarchi
+			// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
+			var head = document.getElementsByTagName("head")[0] || document.documentElement,
+				script = document.createElement("script");
+
+			script.type = "text/javascript";
+
+			if ( jQuery.support.scriptEval ) {
+				script.appendChild( document.createTextNode( data ) );
+			} else {
+				script.text = data;
+			}
+
+			// Use insertBefore instead of appendChild to circumvent an IE6 bug.
+			// This arises when a base node is used (#2709).
+			head.insertBefore( script, head.firstChild );
+			head.removeChild( script );
+		}
+	},
+
+	nodeName: function( elem, name ) {
+		return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
+	},
+
+	// args is for internal usage only
+	each: function( object, callback, args ) {
+		var name, i = 0,
+			length = object.length,
+			isObj = length === undefined || jQuery.isFunction(object);
+
+		if ( args ) {
+			if ( isObj ) {
+				for ( name in object ) {
+					if ( callback.apply( object[ name ], args ) === false ) {
+						break;
+					}
+				}
+			} else {
+				for ( ; i < length; ) {
+					if ( callback.apply( object[ i++ ], args ) === false ) {
+						break;
+					}
+				}
+			}
+
+		// A special, fast, case for the most common use of each
+		} else {
+			if ( isObj ) {
+				for ( name in object ) {
+					if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
+						break;
+					}
+				}
+			} else {
+				for ( var value = object[0];
+					i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {}
+			}
+		}
+
+		return object;
+	},
+
+	// Use native String.trim function wherever possible
+	trim: trim ?
+		function( text ) {
+			return text == null ?
+				"" :
+				trim.call( text );
+		} :
+
+		// Otherwise use our own trimming functionality
+		function( text ) {
+			return text == null ?
+				"" :
+				text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
+		},
+
+	// results is for internal usage only
+	makeArray: function( array, results ) {
+		var ret = results || [];
+
+		if ( array != null ) {
+			// The window, strings (and functions) also have 'length'
+			// The extra typeof function check is to prevent crashes
+			// in Safari 2 (See: #3039)
+			// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
+			var type = jQuery.type(array);
+
+			if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
+				push.call( ret, array );
+			} else {
+				jQuery.merge( ret, array );
+			}
+		}
+
+		return ret;
+	},
+
+	inArray: function( elem, array ) {
+		if ( array.indexOf ) {
+			return array.indexOf( elem );
+		}
+
+		for ( var i = 0, length = array.length; i < length; i++ ) {
+			if ( array[ i ] === elem ) {
+				return i;
+			}
+		}
+
+		return -1;
+	},
+
+	merge: function( first, second ) {
+		var i = first.length,
+			j = 0;
+
+		if ( typeof second.length === "number" ) {
+			for ( var l = second.length; j < l; j++ ) {
+				first[ i++ ] = second[ j ];
+			}
+		
+		} else {
+			while ( second[j] !== undefined ) {
+				first[ i++ ] = second[ j++ ];
+			}
+		}
+
+		first.length = i;
+
+		return first;
+	},
+
+	grep: function( elems, callback, inv ) {
+		var ret = [], retVal;
+		inv = !!inv;
+
+		// Go through the array, only saving the items
+		// that pass the validator function
+		for ( var i = 0, length = elems.length; i < length; i++ ) {
+			retVal = !!callback( elems[ i ], i );
+			if ( inv !== retVal ) {
+				ret.push( elems[ i ] );
+			}
+		}
+
+		return ret;
+	},
+
+	// arg is for internal usage only
+	map: function( elems, callback, arg ) {
+		var ret = [], value;
+
+		// Go through the array, translating each of the items to their
+		// new value (or values).
+		for ( var i = 0, length = elems.length; i < length; i++ ) {
+			value = callback( elems[ i ], i, arg );
+
+			if ( value != null ) {
+				ret[ ret.length ] = value;
+			}
+		}
+
+		return ret.concat.apply( [], ret );
+	},
+
+	// A global GUID counter for objects
+	guid: 1,
+
+	proxy: function( fn, proxy, thisObject ) {
+		if ( arguments.length === 2 ) {
+			if ( typeof proxy === "string" ) {
+				thisObject = fn;
+				fn = thisObject[ proxy ];
+				proxy = undefined;
+
+			} else if ( proxy && !jQuery.isFunction( proxy ) ) {
+				thisObject = proxy;
+				proxy = undefined;
+			}
+		}
+
+		if ( !proxy && fn ) {
+			proxy = function() {
+				return fn.apply( thisObject || this, arguments );
+			};
+		}
+
+		// Set the guid of unique handler to the same of original handler, so it can be removed
+		if ( fn ) {
+			proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
+		}
+
+		// So proxy can be declared as an argument
+		return proxy;
+	},
+
+	// Mutifunctional method to get and set values to a collection
+	// The value/s can be optionally by executed if its a function
+	access: function( elems, key, value, exec, fn, pass ) {
+		var length = elems.length;
+	
+		// Setting many attributes
+		if ( typeof key === "object" ) {
+			for ( var k in key ) {
+				jQuery.access( elems, k, key[k], exec, fn, value );
+			}
+			return elems;
+		}
+	
+		// Setting one attribute
+		if ( value !== undefined ) {
+			// Optionally, function values get executed if exec is true
+			exec = !pass && exec && jQuery.isFunction(value);
+		
+			for ( var i = 0; i < length; i++ ) {
+				fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
+			}
+		
+			return elems;
+		}
+	
+		// Getting an attribute
+		return length ? fn( elems[0], key ) : undefined;
+	},
+
+	now: function() {
+		return (new Date()).getTime();
+	},
+
+	// Use of jQuery.browser is frowned upon.
+	// More details: http://docs.jquery.com/Utilities/jQuery.browser
+	uaMatch: function( ua ) {
+		ua = ua.toLowerCase();
+
+		var match = rwebkit.exec( ua ) ||
+			ropera.exec( ua ) ||
+			rmsie.exec( ua ) ||
+			ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
+			[];
+
+		return { browser: match[1] || "", version: match[2] || "0" };
+	},
+
+	browser: {}
+});
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
+	class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+browserMatch = jQuery.uaMatch( userAgent );
+if ( browserMatch.browser ) {
+	jQuery.browser[ browserMatch.browser ] = true;
+	jQuery.browser.version = browserMatch.version;
+}
+
+// Deprecated, use jQuery.browser.webkit instead
+if ( jQuery.browser.webkit ) {
+	jQuery.browser.safari = true;
+}
+
+if ( indexOf ) {
+	jQuery.inArray = function( elem, array ) {
+		return indexOf.call( array, elem );
+	};
+}
+
+// Verify that \s matches non-breaking spaces
+// (IE fails on this test)
+if ( !rwhite.test( "\xA0" ) ) {
+	trimLeft = /^[\s\xA0]+/;
+	trimRight = /[\s\xA0]+$/;
+}
+
+// All jQuery objects should point back to these
+rootjQuery = jQuery(document);
+
+// Cleanup functions for the document ready method
+if ( document.addEventListener ) {
+	DOMContentLoaded = function() {
+		document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+		jQuery.ready();
+	};
+
+} else if ( document.attachEvent ) {
+	DOMContentLoaded = function() {
+		// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+		if ( document.readyState === "complete" ) {
+			document.detachEvent( "onreadystatechange", DOMContentLoaded );
+			jQuery.ready();
+		}
+	};
+}
+
+// The DOM ready check for Internet Explorer
+function doScrollCheck() {
+	if ( jQuery.isReady ) {
+		return;
+	}
+
+	try {
+		// If IE is used, use the trick by Diego Perini
+		// http://javascript.nwbox.com/IEContentLoaded/
+		document.documentElement.doScroll("left");
+	} catch(e) {
+		setTimeout( doScrollCheck, 1 );
+		return;
+	}
+
+	// and execute any waiting functions
+	jQuery.ready();
+}
+
+// Expose jQuery to the global object
+return (window.jQuery = window.$ = jQuery);
+
+})();
+
+
+(function() {
+
+	jQuery.support = {};
+
+	var root = document.documentElement,
+		script = document.createElement("script"),
+		div = document.createElement("div"),
+		id = "script" + jQuery.now();
+
+	div.style.display = "none";
+	div.innerHTML = "   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
+
+	var all = div.getElementsByTagName("*"),
+		a = div.getElementsByTagName("a")[0],
+		select = document.createElement("select"),
+		opt = select.appendChild( document.createElement("option") );
+
+	// Can't get basic test support
+	if ( !all || !all.length || !a ) {
+		return;
+	}
+
+	jQuery.support = {
+		// IE strips leading whitespace when .innerHTML is used
+		leadingWhitespace: div.firstChild.nodeType === 3,
+
+		// Make sure that tbody elements aren't automatically inserted
+		// IE will insert them into empty tables
+		tbody: !div.getElementsByTagName("tbody").length,
+
+		// Make sure that link elements get serialized correctly by innerHTML
+		// This requires a wrapper element in IE
+		htmlSerialize: !!div.getElementsByTagName("link").length,
+
+		// Get the style information from getAttribute
+		// (IE uses .cssText insted)
+		style: /red/.test( a.getAttribute("style") ),
+
+		// Make sure that URLs aren't manipulated
+		// (IE normalizes it by default)
+		hrefNormalized: a.getAttribute("href") === "/a",
+
+		// Make sure that element opacity exists
+		// (IE uses filter instead)
+		// Use a regex to work around a WebKit issue. See #5145
+		opacity: /^0.55$/.test( a.style.opacity ),
+
+		// Verify style float existence
+		// (IE uses styleFloat instead of cssFloat)
+		cssFloat: !!a.style.cssFloat,
+
+		// Make sure that if no value is specified for a checkbox
+		// that it defaults to "on".
+		// (WebKit defaults to "" instead)
+		checkOn: div.getElementsByTagName("input")[0].value === "on",
+
+		// Make sure that a selected-by-default option has a working selected property.
+		// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+		optSelected: opt.selected,
+
+		// Will be defined later
+		deleteExpando: true,
+		optDisabled: false,
+		checkClone: false,
+		scriptEval: false,
+		noCloneEvent: true,
+		boxModel: null,
+		inlineBlockNeedsLayout: false,
+		shrinkWrapBlocks: false,
+		reliableHiddenOffsets: true
+	};
+
+	// Make sure that the options inside disabled selects aren't marked as disabled
+	// (WebKit marks them as diabled)
+	select.disabled = true;
+	jQuery.support.optDisabled = !opt.disabled;
+
+	script.type = "text/javascript";
+	try {
+		script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
+	} catch(e) {}
+
+	root.insertBefore( script, root.firstChild );
+
+	// Make sure that the execution of code works by injecting a script
+	// tag with appendChild/createTextNode
+	// (IE doesn't support this, fails, and uses .text instead)
+	if ( window[ id ] ) {
+		jQuery.support.scriptEval = true;
+		delete window[ id ];
+	}
+
+	// Test to see if it's possible to delete an expando from an element
+	// Fails in Internet Explorer
+	try {
+		delete script.test;
+
+	} catch(e) {
+		jQuery.support.deleteExpando = false;
+	}
+
+	root.removeChild( script );
+
+	if ( div.attachEvent && div.fireEvent ) {
+		div.attachEvent("onclick", function click() {
+			// Cloning a node shouldn't copy over any
+			// bound event handlers (IE does this)
+			jQuery.support.noCloneEvent = false;
+			div.detachEvent("onclick", click);
+		});
+		div.cloneNode(true).fireEvent("onclick");
+	}
+
+	div = document.createElement("div");
+	div.innerHTML = "<input type='radio' name='radiotest' checked='checked'/>";
+
+	var fragment = document.createDocumentFragment();
+	fragment.appendChild( div.firstChild );
+
+	// WebKit doesn't clone checked state correctly in fragments
+	jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked;
+
+	// Figure out if the W3C box model works as expected
+	// document.body must exist before we can do this
+	jQuery(function() {
+		var div = document.createElement("div");
+		div.style.width = div.style.paddingLeft = "1px";
+
+		document.body.appendChild( div );
+		jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
+
+		if ( "zoom" in div.style ) {
+			// Check if natively block-level elements act like inline-block
+			// elements when setting their display to 'inline' and giving
+			// them layout
+			// (IE < 8 does this)
+			div.style.display = "inline";
+			div.style.zoom = 1;
+			jQuery.support.inlineBlockNeedsLayout = div.offsetWidth === 2;
+
+			// Check if elements with layout shrink-wrap their children
+			// (IE 6 does this)
+			div.style.display = "";
+			div.innerHTML = "<div style='width:4px;'></div>";
+			jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2;
+		}
+
+		div.innerHTML = "<table><tr><td style='padding:0;display:none'></td><td>t</td></tr></table>";
+		var tds = div.getElementsByTagName("td");
+
+		// Check if table cells still have offsetWidth/Height when they are set
+		// to display:none and there are still other visible table cells in a
+		// table row; if so, offsetWidth/Height are not reliable for use when
+		// determining if an element has been hidden directly using
+		// display:none (it is still safe to use offsets if a parent element is
+		// hidden; don safety goggles and see bug #4512 for more information).
+		// (only IE 8 fails this test)
+		jQuery.support.reliableHiddenOffsets = tds[0].offsetHeight === 0;
+
+		tds[0].style.display = "";
+		tds[1].style.display = "none";
+
+		// Check if empty table cells still have offsetWidth/Height
+		// (IE < 8 fail this test)
+		jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets && tds[0].offsetHeight === 0;
+		div.innerHTML = "";
+
+		document.body.removeChild( div ).style.display = "none";
+		div = tds = null;
+	});
+
+	// Technique from Juriy Zaytsev
+	// http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
+	var eventSupported = function( eventName ) {
+		var el = document.createElement("div");
+		eventName = "on" + eventName;
+
+		var isSupported = (eventName in el);
+		if ( !isSupported ) {
+			el.setAttribute(eventName, "return;");
+			isSupported = typeof el[eventName] === "function";
+		}
+		el = null;
+
+		return isSupported;
+	};
+
+	jQuery.support.submitBubbles = eventSupported("submit");
+	jQuery.support.changeBubbles = eventSupported("change");
+
+	// release memory in IE
+	root = script = div = all = a = null;
+})();
+
+
+
+var windowData = {},
+	rbrace = /^(?:\{.*\}|\[.*\])$/;
+
+jQuery.extend({
+	cache: {},
+
+	// Please use with caution
+	uuid: 0,
+
+	// Unique for each copy of jQuery on the page	
+	expando: "jQuery" + jQuery.now(),
+
+	// The following elements throw uncatchable exceptions if you
+	// attempt to add expando properties to them.
+	noData: {
+		"embed": true,
+		// Ban all objects except for Flash (which handle expandos)
+		"object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
+		"applet": true
+	},
+
+	data: function( elem, name, data ) {
+		if ( !jQuery.acceptData( elem ) ) {
+			return;
+		}
+
+		elem = elem == window ?
+			windowData :
+			elem;
+
+		var isNode = elem.nodeType,
+			id = isNode ? elem[ jQuery.expando ] : null,
+			cache = jQuery.cache, thisCache;
+
+		if ( isNode && !id && typeof name === "string" && data === undefined ) {
+			return;
+		}
+
+		// Get the data from the object directly
+		if ( !isNode ) {
+			cache = elem;
+
+		// Compute a unique ID for the element
+		} else if ( !id ) {
+			elem[ jQuery.expando ] = id = ++jQuery.uuid;
+		}
+
+		// Avoid generating a new cache unless none exists and we
+		// want to manipulate it.
+		if ( typeof name === "object" ) {
+			if ( isNode ) {
+				cache[ id ] = jQuery.extend(cache[ id ], name);
+
+			} else {
+				jQuery.extend( cache, name );
+			}
+
+		} else if ( isNode && !cache[ id ] ) {
+			cache[ id ] = {};
+		}
+
+		thisCache = isNode ? cache[ id ] : cache;
+
+		// Prevent overriding the named cache with undefined values
+		if ( data !== undefined ) {
+			thisCache[ name ] = data;
+		}
+
+		return typeof name === "string" ? thisCache[ name ] : thisCache;
+	},
+
+	removeData: function( elem, name ) {
+		if ( !jQuery.acceptData( elem ) ) {
+			return;
+		}
+
+		elem = elem == window ?
+			windowData :
+			elem;
+
+		var isNode = elem.nodeType,
+			id = isNode ? elem[ jQuery.expando ] : elem,
+			cache = jQuery.cache,
+			thisCache = isNode ? cache[ id ] : id;
+
+		// If we want to remove a specific section of the element's data
+		if ( name ) {
+			if ( thisCache ) {
+				// Remove the section of cache data
+				delete thisCache[ name ];
+
+				// If we've removed all the data, remove the element's cache
+				if ( isNode && jQuery.isEmptyObject(thisCache) ) {
+					jQuery.removeData( elem );
+				}
+			}
+
+		// Otherwise, we want to remove all of the element's data
+		} else {
+			if ( isNode && jQuery.support.deleteExpando ) {
+				delete elem[ jQuery.expando ];
+
+			} else if ( elem.removeAttribute ) {
+				elem.removeAttribute( jQuery.expando );
+
+			// Completely remove the data cache
+			} else if ( isNode ) {
+				delete cache[ id ];
+
+			// Remove all fields from the object
+			} else {
+				for ( var n in elem ) {
+					delete elem[ n ];
+				}
+			}
+		}
+	},
+
+	// A method for determining if a DOM node can handle the data expando
+	acceptData: function( elem ) {
+		if ( elem.nodeName ) {
+			var match = jQuery.noData[ elem.nodeName.toLowerCase() ];
+
+			if ( match ) {
+				return !(match === true || elem.getAttribute("classid") !== match);
+			}
+		}
+
+		return true;
+	}
+});
+
+jQuery.fn.extend({
+	data: function( key, value ) {
+		var data = null;
+
+		if ( typeof key === "undefined" ) {
+			if ( this.length ) {
+				var attr = this[0].attributes, name;
+				data = jQuery.data( this[0] );
+
+				for ( var i = 0, l = attr.length; i < l; i++ ) {
+					name = attr[i].name;
+
+					if ( name.indexOf( "data-" ) === 0 ) {
+						name = name.substr( 5 );
+						dataAttr( this[0], name, data[ name ] );
+					}
+				}
+			}
+
+			return data;
+
+		} else if ( typeof key === "object" ) {
+			return this.each(function() {
+				jQuery.data( this, key );
+			});
+		}
+
+		var parts = key.split(".");
+		parts[1] = parts[1] ? "." + parts[1] : "";
+
+		if ( value === undefined ) {
+			data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
+
+			// Try to fetch any internally stored data first
+			if ( data === undefined && this.length ) {
+				data = jQuery.data( this[0], key );
+				data = dataAttr( this[0], key, data );
+			}
+
+			return data === undefined && parts[1] ?
+				this.data( parts[0] ) :
+				data;
+
+		} else {
+			return this.each(function() {
+				var $this = jQuery( this ),
+					args = [ parts[0], value ];
+
+				$this.triggerHandler( "setData" + parts[1] + "!", args );
+				jQuery.data( this, key, value );
+				$this.triggerHandler( "changeData" + parts[1] + "!", args );
+			});
+		}
+	},
+
+	removeData: function( key ) {
+		return this.each(function() {
+			jQuery.removeData( this, key );
+		});
+	}
+});
+
+function dataAttr( elem, key, data ) {
+	// If nothing was found internally, try to fetch any
+	// data from the HTML5 data-* attribute
+	if ( data === undefined && elem.nodeType === 1 ) {
+		data = elem.getAttribute( "data-" + key );
+
+		if ( typeof data === "string" ) {
+			try {
+				data = data === "true" ? true :
+				data === "false" ? false :
+				data === "null" ? null :
+				!jQuery.isNaN( data ) ? parseFloat( data ) :
+					rbrace.test( data ) ? jQuery.parseJSON( data ) :
+					data;
+			} catch( e ) {}
+
+			// Make sure we set the data so it isn't changed later
+			jQuery.data( elem, key, data );
+
+		} else {
+			data = undefined;
+		}
+	}
+
+	return data;
+}
+
+
+
+
+jQuery.extend({
+	queue: function( elem, type, data ) {
+		if ( !elem ) {
+			return;
+		}
+
+		type = (type || "fx") + "queue";
+		var q = jQuery.data( elem, type );
+
+		// Speed up dequeue by getting out quickly if this is just a lookup
+		if ( !data ) {
+			return q || [];
+		}
+
+		if ( !q || jQuery.isArray(data) ) {
+			q = jQuery.data( elem, type, jQuery.makeArray(data) );
+
+		} else {
+			q.push( data );
+		}
+
+		return q;
+	},
+
+	dequeue: function( elem, type ) {
+		type = type || "fx";
+
+		var queue = jQuery.queue( elem, type ),
+			fn = queue.shift();
+
+		// If the fx queue is dequeued, always remove the progress sentinel
+		if ( fn === "inprogress" ) {
+			fn = queue.shift();
+		}
+
+		if ( fn ) {
+			// Add a progress sentinel to prevent the fx queue from being
+			// automatically dequeued
+			if ( type === "fx" ) {
+				queue.unshift("inprogress");
+			}
+
+			fn.call(elem, function() {
+				jQuery.dequeue(elem, type);
+			});
+		}
+	}
+});
+
+jQuery.fn.extend({
+	queue: function( type, data ) {
+		if ( typeof type !== "string" ) {
+			data = type;
+			type = "fx";
+		}
+
+		if ( data === undefined ) {
+			return jQuery.queue( this[0], type );
+		}
+		return this.each(function( i ) {
+			var queue = jQuery.queue( this, type, data );
+
+			if ( type === "fx" && queue[0] !== "inprogress" ) {
+				jQuery.dequeue( this, type );
+			}
+		});
+	},
+	dequeue: function( type ) {
+		return this.each(function() {
+			jQuery.dequeue( this, type );
+		});
+	},
+
+	// Based off of the plugin by Clint Helfers, with permission.
+	// http://blindsignals.com/index.php/2009/07/jquery-delay/
+	delay: function( time, type ) {
+		time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
+		type = type || "fx";
+
+		return this.queue( type, function() {
+			var elem = this;
+			setTimeout(function() {
+				jQuery.dequeue( elem, type );
+			}, time );
+		});
+	},
+
+	clearQueue: function( type ) {
+		return this.queue( type || "fx", [] );
+	}
+});
+
+
+
+
+var rclass = /[\n\t]/g,
+	rspaces = /\s+/,
+	rreturn = /\r/g,
+	rspecialurl = /^(?:href|src|style)$/,
+	rtype = /^(?:button|input)$/i,
+	rfocusable = /^(?:button|input|object|select|textarea)$/i,
+	rclickable = /^a(?:rea)?$/i,
+	rradiocheck = /^(?:radio|checkbox)$/i;
+
+jQuery.props = {
+	"for": "htmlFor",
+	"class": "className",
+	readonly: "readOnly",
+	maxlength: "maxLength",
+	cellspacing: "cellSpacing",
+	rowspan: "rowSpan",
+	colspan: "colSpan",
+	tabindex: "tabIndex",
+	usemap: "useMap",
+	frameborder: "frameBorder"
+};
+
+jQuery.fn.extend({
+	attr: function( name, value ) {
+		return jQuery.access( this, name, value, true, jQuery.attr );
+	},
+
+	removeAttr: function( name, fn ) {
+		return this.each(function(){
+			jQuery.attr( this, name, "" );
+			if ( this.nodeType === 1 ) {
+				this.removeAttribute( name );
+			}
+		});
+	},
+
+	addClass: function( value ) {
+		if ( jQuery.isFunction(value) ) {
+			return this.each(function(i) {
+				var self = jQuery(this);
+				self.addClass( value.call(this, i, self.attr("class")) );
+			});
+		}
+
+		if ( value && typeof value === "string" ) {
+			var classNames = (value || "").split( rspaces );
+
+			for ( var i = 0, l = this.length; i < l; i++ ) {
+				var elem = this[i];
+
+				if ( elem.nodeType === 1 ) {
+					if ( !elem.className ) {
+						elem.className = value;
+
+					} else {
+						var className = " " + elem.className + " ",
+							setClass = elem.className;
+
+						for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
+							if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) {
+								setClass += " " + classNames[c];
+							}
+						}
+						elem.className = jQuery.trim( setClass );
+					}
+				}
+			}
+		}
+
+		return this;
+	},
+
+	removeClass: function( value ) {
+		if ( jQuery.isFunction(value) ) {
+			return this.each(function(i) {
+				var self = jQuery(this);
+				self.removeClass( value.call(this, i, self.attr("class")) );
+			});
+		}
+
+		if ( (value && typeof value === "string") || value === undefined ) {
+			var classNames = (value || "").split( rspaces );
+
+			for ( var i = 0, l = this.length; i < l; i++ ) {
+				var elem = this[i];
+
+				if ( elem.nodeType === 1 && elem.className ) {
+					if ( value ) {
+						var className = (" " + elem.className + " ").replace(rclass, " ");
+						for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
+							className = className.replace(" " + classNames[c] + " ", " ");
+						}
+						elem.className = jQuery.trim( className );
+
+					} else {
+						elem.className = "";
+					}
+				}
+			}
+		}
+
+		return this;
+	},
+
+	toggleClass: function( value, stateVal ) {
+		var type = typeof value,
+			isBool = typeof stateVal === "boolean";
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function(i) {
+				var self = jQuery(this);
+				self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal );
+			});
+		}
+
+		return this.each(function() {
+			if ( type === "string" ) {
+				// toggle individual class names
+				var className,
+					i = 0,
+					self = jQuery( this ),
+					state = stateVal,
+					classNames = value.split( rspaces );
+
+				while ( (className = classNames[ i++ ]) ) {
+					// check each className given, space seperated list
+					state = isBool ? state : !self.hasClass( className );
+					self[ state ? "addClass" : "removeClass" ]( className );
+				}
+
+			} else if ( type === "undefined" || type === "boolean" ) {
+				if ( this.className ) {
+					// store className if set
+					jQuery.data( this, "__className__", this.className );
+				}
+
+				// toggle whole className
+				this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || "";
+			}
+		});
+	},
+
+	hasClass: function( selector ) {
+		var className = " " + selector + " ";
+		for ( var i = 0, l = this.length; i < l; i++ ) {
+			if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
+				return true;
+			}
+		}
+
+		return false;
+	},
+
+	val: function( value ) {
+		if ( !arguments.length ) {
+			var elem = this[0];
+
+			if ( elem ) {
+				if ( jQuery.nodeName( elem, "option" ) ) {
+					// attributes.value is undefined in Blackberry 4.7 but
+					// uses .value. See #6932
+					var val = elem.attributes.value;
+					return !val || val.specified ? elem.value : elem.text;
+				}
+
+				// We need to handle select boxes special
+				if ( jQuery.nodeName( elem, "select" ) ) {
+					var index = elem.selectedIndex,
+						values = [],
+						options = elem.options,
+						one = elem.type === "select-one";
+
+					// Nothing was selected
+					if ( index < 0 ) {
+						return null;
+					}
+
+					// Loop through all the selected options
+					for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
+						var option = options[ i ];
+
+						// Don't return options that are disabled or in a disabled optgroup
+						if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && 
+								(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
+
+							// Get the specific value for the option
+							value = jQuery(option).val();
+
+							// We don't need an array for one selects
+							if ( one ) {
+								return value;
+							}
+
+							// Multi-Selects return an array
+							values.push( value );
+						}
+					}
+
+					return values;
+				}
+
+				// Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
+				if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) {
+					return elem.getAttribute("value") === null ? "on" : elem.value;
+				}
+				
+
+				// Everything else, we just grab the value
+				return (elem.value || "").replace(rreturn, "");
+
+			}
+
+			return undefined;
+		}
+
+		var isFunction = jQuery.isFunction(value);
+
+		return this.each(function(i) {
+			var self = jQuery(this), val = value;
+
+			if ( this.nodeType !== 1 ) {
+				return;
+			}
+
+			if ( isFunction ) {
+				val = value.call(this, i, self.val());
+			}
+
+			// Treat null/undefined as ""; convert numbers to string
+			if ( val == null ) {
+				val = "";
+			} else if ( typeof val === "number" ) {
+				val += "";
+			} else if ( jQuery.isArray(val) ) {
+				val = jQuery.map(val, function (value) {
+					return value == null ? "" : value + "";
+				});
+			}
+
+			if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) {
+				this.checked = jQuery.inArray( self.val(), val ) >= 0;
+
+			} else if ( jQuery.nodeName( this, "select" ) ) {
+				var values = jQuery.makeArray(val);
+
+				jQuery( "option", this ).each(function() {
+					this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
+				});
+
+				if ( !values.length ) {
+					this.selectedIndex = -1;
+				}
+
+			} else {
+				this.value = val;
+			}
+		});
+	}
+});
+
+jQuery.extend({
+	attrFn: {
+		val: true,
+		css: true,
+		html: true,
+		text: true,
+		data: true,
+		width: true,
+		height: true,
+		offset: true
+	},
+		
+	attr: function( elem, name, value, pass ) {
+		// don't set attributes on text and comment nodes
+		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
+			return undefined;
+		}
+
+		if ( pass && name in jQuery.attrFn ) {
+			return jQuery(elem)[name](value);
+		}
+
+		var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ),
+			// Whether we are setting (or getting)
+			set = value !== undefined;
+
+		// Try to normalize/fix the name
+		name = notxml && jQuery.props[ name ] || name;
+
+		// These attributes require special treatment
+		var special = rspecialurl.test( name );
+
+		// Safari mis-reports the default selected property of an option
+		// Accessing the parent's selectedIndex property fixes it
+		if ( name === "selected" && !jQuery.support.optSelected ) {
+			var parent = elem.parentNode;
+			if ( parent ) {
+				parent.selectedIndex;
+
+				// Make sure that it also works with optgroups, see #5701
+				if ( parent.parentNode ) {
+					parent.parentNode.selectedIndex;
+				}
+			}
+		}
+
+		// If applicable, access the attribute via the DOM 0 way
+		// 'in' checks fail in Blackberry 4.7 #6931
+		if ( (name in elem || elem[ name ] !== undefined) && notxml && !special ) {
+			if ( set ) {
+				// We can't allow the type property to be changed (since it causes problems in IE)
+				if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) {
+					jQuery.error( "type property can't be changed" );
+				}
+
+				if ( value === null ) {
+					if ( elem.nodeType === 1 ) {
+						elem.removeAttribute( name );
+					}
+
+				} else {
+					elem[ name ] = value;
+				}
+			}
+
+			// browsers index elements by id/name on forms, give priority to attributes.
+			if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) {
+				return elem.getAttributeNode( name ).nodeValue;
+			}
+
+			// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+			// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+			if ( name === "tabIndex" ) {
+				var attributeNode = elem.getAttributeNode( "tabIndex" );
+
+				return attributeNode && attributeNode.specified ?
+					attributeNode.value :
+					rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
+						0 :
+						undefined;
+			}
+
+			return elem[ name ];
+		}
+
+		if ( !jQuery.support.style && notxml && name === "style" ) {
+			if ( set ) {
+				elem.style.cssText = "" + value;
+			}
+
+			return elem.style.cssText;
+		}
+
+		if ( set ) {
+			// convert the value to a string (all browsers do this but IE) see #1070
+			elem.setAttribute( name, "" + value );
+		}
+
+		// Ensure that missing attributes return undefined
+		// Blackberry 4.7 returns "" from getAttribute #6938
+		if ( !elem.attributes[ name ] && (elem.hasAttribute && !elem.hasAttribute( name )) ) {
+			return undefined;
+		}
+
+		var attr = !jQuery.support.hrefNormalized && notxml && special ?
+				// Some attributes require a special call on IE
+				elem.getAttribute( name, 2 ) :
+				elem.getAttribute( name );
+
+		// Non-existent attributes return null, we normalize to undefined
+		return attr === null ? undefined : attr;
+	}
+});
+
+
+
+
+var rnamespaces = /\.(.*)$/,
+	rformElems = /^(?:textarea|input|select)$/i,
+	rperiod = /\./g,
+	rspace = / /g,
+	rescape = /[^\w\s.|`]/g,
+	fcleanup = function( nm ) {
+		return nm.replace(rescape, "\\$&");
+	},
+	focusCounts = { focusin: 0, focusout: 0 };
+
+/*
+ * A number of helper functions used for managing events.
+ * Many of the ideas behind this code originated from
+ * Dean Edwards' addEvent library.
+ */
+jQuery.event = {
+
+	// Bind an event to an element
+	// Original by Dean Edwards
+	add: function( elem, types, handler, data ) {
+		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+			return;
+		}
+
+		// For whatever reason, IE has trouble passing the window object
+		// around, causing it to be cloned in the process
+		if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) {
+			elem = window;
+		}
+
+		if ( handler === false ) {
+			handler = returnFalse;
+		} else if ( !handler ) {
+			// Fixes bug #7229. Fix recommended by jdalton
+		  return;
+		}
+
+		var handleObjIn, handleObj;
+
+		if ( handler.handler ) {
+			handleObjIn = handler;
+			handler = handleObjIn.handler;
+		}
+
+		// Make sure that the function being executed has a unique ID
+		if ( !handler.guid ) {
+			handler.guid = jQuery.guid++;
+		}
+
+		// Init the element's event structure
+		var elemData = jQuery.data( elem );
+
+		// If no elemData is found then we must be trying to bind to one of the
+		// banned noData elements
+		if ( !elemData ) {
+			return;
+		}
+
+		// Use a key less likely to result in collisions for plain JS objects.
+		// Fixes bug #7150.
+		var eventKey = elem.nodeType ? "events" : "__events__",
+			events = elemData[ eventKey ],
+			eventHandle = elemData.handle;
+			
+		if ( typeof events === "function" ) {
+			// On plain objects events is a fn that holds the the data
+			// which prevents this data from being JSON serialized
+			// the function does not need to be called, it just contains the data
+			eventHandle = events.handle;
+			events = events.events;
+
+		} else if ( !events ) {
+			if ( !elem.nodeType ) {
+				// On plain objects, create a fn that acts as the holder
+				// of the values to avoid JSON serialization of event data
+				elemData[ eventKey ] = elemData = function(){};
+			}
+
+			elemData.events = events = {};
+		}
+
+		if ( !eventHandle ) {
+			elemData.handle = eventHandle = function() {
+				// Handle the second event of a trigger and when
+				// an event is called after a page has unloaded
+				return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
+					jQuery.event.handle.apply( eventHandle.elem, arguments ) :
+					undefined;
+			};
+		}
+
+		// Add elem as a property of the handle function
+		// This is to prevent a memory leak with non-native events in IE.
+		eventHandle.elem = elem;
+
+		// Handle multiple events separated by a space
+		// jQuery(...).bind("mouseover mouseout", fn);
+		types = types.split(" ");
+
+		var type, i = 0, namespaces;
+
+		while ( (type = types[ i++ ]) ) {
+			handleObj = handleObjIn ?
+				jQuery.extend({}, handleObjIn) :
+				{ handler: handler, data: data };
+
+			// Namespaced event handlers
+			if ( type.indexOf(".") > -1 ) {
+				namespaces = type.split(".");
+				type = namespaces.shift();
+				handleObj.namespace = namespaces.slice(0).sort().join(".");
+
+			} else {
+				namespaces = [];
+				handleObj.namespace = "";
+			}
+
+			handleObj.type = type;
+			if ( !handleObj.guid ) {
+				handleObj.guid = handler.guid;
+			}
+
+			// Get the current list of functions bound to this event
+			var handlers = events[ type ],
+				special = jQuery.event.special[ type ] || {};
+
+			// Init the event handler queue
+			if ( !handlers ) {
+				handlers = events[ type ] = [];
+
+				// Check for a special event handler
+				// Only use addEventListener/attachEvent if the special
+				// events handler returns false
+				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+					// Bind the global event handler to the element
+					if ( elem.addEventListener ) {
+						elem.addEventListener( type, eventHandle, false );
+
+					} else if ( elem.attachEvent ) {
+						elem.attachEvent( "on" + type, eventHandle );
+					}
+				}
+			}
+			
+			if ( special.add ) { 
+				special.add.call( elem, handleObj ); 
+
+				if ( !handleObj.handler.guid ) {
+					handleObj.handler.guid = handler.guid;
+				}
+			}
+
+			// Add the function to the element's handler list
+			handlers.push( handleObj );
+
+			// Keep track of which events have been used, for global triggering
+			jQuery.event.global[ type ] = true;
+		}
+
+		// Nullify elem to prevent memory leaks in IE
+		elem = null;
+	},
+
+	global: {},
+
+	// Detach an event or set of events from an element
+	remove: function( elem, types, handler, pos ) {
+		// don't do events on text and comment nodes
+		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+			return;
+		}
+
+		if ( handler === false ) {
+			handler = returnFalse;
+		}
+
+		var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
+			eventKey = elem.nodeType ? "events" : "__events__",
+			elemData = jQuery.data( elem ),
+			events = elemData && elemData[ eventKey ];
+
+		if ( !elemData || !events ) {
+			return;
+		}
+		
+		if ( typeof events === "function" ) {
+			elemData = events;
+			events = events.events;
+		}
+
+		// types is actually an event object here
+		if ( types && types.type ) {
+			handler = types.handler;
+			types = types.type;
+		}
+
+		// Unbind all events for the element
+		if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
+			types = types || "";
+
+			for ( type in events ) {
+				jQuery.event.remove( elem, type + types );
+			}
+
+			return;
+		}
+
+		// Handle multiple events separated by a space
+		// jQuery(...).unbind("mouseover mouseout", fn);
+		types = types.split(" ");
+
+		while ( (type = types[ i++ ]) ) {
+			origType = type;
+			handleObj = null;
+			all = type.indexOf(".") < 0;
+			namespaces = [];
+
+			if ( !all ) {
+				// Namespaced event handlers
+				namespaces = type.split(".");
+				type = namespaces.shift();
+
+				namespace = new RegExp("(^|\\.)" + 
+					jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)");
+			}
+
+			eventType = events[ type ];
+
+			if ( !eventType ) {
+				continue;
+			}
+
+			if ( !handler ) {
+				for ( j = 0; j < eventType.length; j++ ) {
+					handleObj = eventType[ j ];
+
+					if ( all || namespace.test( handleObj.namespace ) ) {
+						jQuery.event.remove( elem, origType, handleObj.handler, j );
+						eventType.splice( j--, 1 );
+					}
+				}
+
+				continue;
+			}
+
+			special = jQuery.event.special[ type ] || {};
+
+			for ( j = pos || 0; j < eventType.length; j++ ) {
+				handleObj = eventType[ j ];
+
+				if ( handler.guid === handleObj.guid ) {
+					// remove the given handler for the given type
+					if ( all || namespace.test( handleObj.namespace ) ) {
+						if ( pos == null ) {
+							eventType.splice( j--, 1 );
+						}
+
+						if ( special.remove ) {
+							special.remove.call( elem, handleObj );
+						}
+					}
+
+					if ( pos != null ) {
+						break;
+					}
+				}
+			}
+
+			// remove generic event handler if no more handlers exist
+			if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
+				if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
+					jQuery.removeEvent( elem, type, elemData.handle );
+				}
+
+				ret = null;
+				delete events[ type ];
+			}
+		}
+
+		// Remove the expando if it's no longer used
+		if ( jQuery.isEmptyObject( events ) ) {
+			var handle = elemData.handle;
+			if ( handle ) {
+				handle.elem = null;
+			}
+
+			delete elemData.events;
+			delete elemData.handle;
+
+			if ( typeof elemData === "function" ) {
+				jQuery.removeData( elem, eventKey );
+
+			} else if ( jQuery.isEmptyObject( elemData ) ) {
+				jQuery.removeData( elem );
+			}
+		}
+	},
+
+	// bubbling is internal
+	trigger: function( event, data, elem /*, bubbling */ ) {
+		// Event object or event type
+		var type = event.type || event,
+			bubbling = arguments[3];
+
+		if ( !bubbling ) {
+			event = typeof event === "object" ?
+				// jQuery.Event object
+				event[ jQuery.expando ] ? event :
+				// Object literal
+				jQuery.extend( jQuery.Event(type), event ) :
+				// Just the event type (string)
+				jQuery.Event(type);
+
+			if ( type.indexOf("!") >= 0 ) {
+				event.type = type = type.slice(0, -1);
+				event.exclusive = true;
+			}
+
+			// Handle a global trigger
+			if ( !elem ) {
+				// Don't bubble custom events when global (to avoid too much overhead)
+				event.stopPropagation();
+
+				// Only trigger if we've ever bound an event for it
+				if ( jQuery.event.global[ type ] ) {
+					jQuery.each( jQuery.cache, function() {
+						if ( this.events && this.events[type] ) {
+							jQuery.event.trigger( event, data, this.handle.elem );
+						}
+					});
+				}
+			}
+
+			// Handle triggering a single element
+
+			// don't do events on text and comment nodes
+			if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
+				return undefined;
+			}
+
+			// Clean up in case it is reused
+			event.result = undefined;
+			event.target = elem;
+
+			// Clone the incoming data, if any
+			data = jQuery.makeArray( data );
+			data.unshift( event );
+		}
+
+		event.currentTarget = elem;
+
+		// Trigger the event, it is assumed that "handle" is a function
+		var handle = elem.nodeType ?
+			jQuery.data( elem, "handle" ) :
+			(jQuery.data( elem, "__events__" ) || {}).handle;
+
+		if ( handle ) {
+			handle.apply( elem, data );
+		}
+
+		var parent = elem.parentNode || elem.ownerDocument;
+
+		// Trigger an inline bound script
+		try {
+			if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
+				if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
+					event.result = false;
+					event.preventDefault();
+				}
+			}
+
+		// prevent IE from throwing an error for some elements with some event types, see #3533
+		} catch (inlineError) {}
+
+		if ( !event.isPropagationStopped() && parent ) {
+			jQuery.event.trigger( event, data, parent, true );
+
+		} else if ( !event.isDefaultPrevented() ) {
+			var old,
+				target = event.target,
+				targetType = type.replace( rnamespaces, "" ),
+				isClick = jQuery.nodeName( target, "a" ) && targetType === "click",
+				special = jQuery.event.special[ targetType ] || {};
+
+			if ( (!special._default || special._default.call( elem, event ) === false) && 
+				!isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
+
+				try {
+					if ( target[ targetType ] ) {
+						// Make sure that we don't accidentally re-trigger the onFOO events
+						old = target[ "on" + targetType ];
+
+						if ( old ) {
+							target[ "on" + targetType ] = null;
+						}
+
+						jQuery.event.triggered = true;
+						target[ targetType ]();
+					}
+
+				// prevent IE from throwing an error for some elements with some event types, see #3533
+				} catch (triggerError) {}
+
+				if ( old ) {
+					target[ "on" + targetType ] = old;
+				}
+
+				jQuery.event.triggered = false;
+			}
+		}
+	},
+
+	handle: function( event ) {
+		var all, handlers, namespaces, namespace_re, events,
+			namespace_sort = [],
+			args = jQuery.makeArray( arguments );
+
+		event = args[0] = jQuery.event.fix( event || window.event );
+		event.currentTarget = this;
+
+		// Namespaced event handlers
+		all = event.type.indexOf(".") < 0 && !event.exclusive;
+
+		if ( !all ) {
+			namespaces = event.type.split(".");
+			event.type = namespaces.shift();
+			namespace_sort = namespaces.slice(0).sort();
+			namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)");
+		}
+
+		event.namespace = event.namespace || namespace_sort.join(".");
+
+		events = jQuery.data(this, this.nodeType ? "events" : "__events__");
+
+		if ( typeof events === "function" ) {
+			events = events.events;
+		}
+
+		handlers = (events || {})[ event.type ];
+
+		if ( events && handlers ) {
+			// Clone the handlers to prevent manipulation
+			handlers = handlers.slice(0);
+
+			for ( var j = 0, l = handlers.length; j < l; j++ ) {
+				var handleObj = handlers[ j ];
+
+				// Filter the functions by class
+				if ( all || namespace_re.test( handleObj.namespace ) ) {
+					// Pass in a reference to the handler function itself
+					// So that we can later remove it
+					event.handler = handleObj.handler;
+					event.data = handleObj.data;
+					event.handleObj = handleObj;
+	
+					var ret = handleObj.handler.apply( this, args );
+
+					if ( ret !== undefined ) {
+						event.result = ret;
+						if ( ret === false ) {
+							event.preventDefault();
+							event.stopPropagation();
+						}
+					}
+
+					if ( event.isImmediatePropagationStopped() ) {
+						break;
+					}
+				}
+			}
+		}
+
+		return event.result;
+	},
+
+	props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
+
+	fix: function( event ) {
+		if ( event[ jQuery.expando ] ) {
+			return event;
+		}
+
+		// store a copy of the original event object
+		// and "clone" to set read-only properties
+		var originalEvent = event;
+		event = jQuery.Event( originalEvent );
+
+		for ( var i = this.props.length, prop; i; ) {
+			prop = this.props[ --i ];
+			event[ prop ] = originalEvent[ prop ];
+		}
+
+		// Fix target property, if necessary
+		if ( !event.target ) {
+			// Fixes #1925 where srcElement might not be defined either
+			event.target = event.srcElement || document;
+		}
+
+		// check if target is a textnode (safari)
+		if ( event.target.nodeType === 3 ) {
+			event.target = event.target.parentNode;
+		}
+
+		// Add relatedTarget, if necessary
+		if ( !event.relatedTarget && event.fromElement ) {
+			event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
+		}
+
+		// Calculate pageX/Y if missing and clientX/Y available
+		if ( event.pageX == null && event.clientX != null ) {
+			var doc = document.documentElement,
+				body = document.body;
+
+			event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
+			event.pageY = event.clientY + (doc && doc.scrollTop  || body && body.scrollTop  || 0) - (doc && doc.clientTop  || body && body.clientTop  || 0);
+		}
+
+		// Add which for key events
+		if ( event.which == null && (event.charCode != null || event.keyCode != null) ) {
+			event.which = event.charCode != null ? event.charCode : event.keyCode;
+		}
+
+		// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
+		if ( !event.metaKey && event.ctrlKey ) {
+			event.metaKey = event.ctrlKey;
+		}
+
+		// Add which for click: 1 === left; 2 === middle; 3 === right
+		// Note: button is not normalized, so don't use it
+		if ( !event.which && event.button !== undefined ) {
+			event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
+		}
+
+		return event;
+	},
+
+	// Deprecated, use jQuery.guid instead
+	guid: 1E8,
+
+	// Deprecated, use jQuery.proxy instead
+	proxy: jQuery.proxy,
+
+	special: {
+		ready: {
+			// Make sure the ready event is setup
+			setup: jQuery.bindReady,
+			teardown: jQuery.noop
+		},
+
+		live: {
+			add: function( handleObj ) {
+				jQuery.event.add( this,
+					liveConvert( handleObj.origType, handleObj.selector ),
+					jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); 
+			},
+
+			remove: function( handleObj ) {
+				jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );
+			}
+		},
+
+		beforeunload: {
+			setup: function( data, namespaces, eventHandle ) {
+				// We only want to do this special case on windows
+				if ( jQuery.isWindow( this ) ) {
+					this.onbeforeunload = eventHandle;
+				}
+			},
+
+			teardown: function( namespaces, eventHandle ) {
+				if ( this.onbeforeunload === eventHandle ) {
+					this.onbeforeunload = null;
+				}
+			}
+		}
+	}
+};
+
+jQuery.removeEvent = document.removeEventListener ?
+	function( elem, type, handle ) {
+		if ( elem.removeEventListener ) {
+			elem.removeEventListener( type, handle, false );
+		}
+	} : 
+	function( elem, type, handle ) {
+		if ( elem.detachEvent ) {
+			elem.detachEvent( "on" + type, handle );
+		}
+	};
+
+jQuery.Event = function( src ) {
+	// Allow instantiation without the 'new' keyword
+	if ( !this.preventDefault ) {
+		return new jQuery.Event( src );
+	}
+
+	// Event object
+	if ( src && src.type ) {
+		this.originalEvent = src;
+		this.type = src.type;
+	// Event type
+	} else {
+		this.type = src;
+	}
+
+	// timeStamp is buggy for some events on Firefox(#3843)
+	// So we won't rely on the native value
+	this.timeStamp = jQuery.now();
+
+	// Mark it as fixed
+	this[ jQuery.expando ] = true;
+};
+
+function returnFalse() {
+	return false;
+}
+function returnTrue() {
+	return true;
+}
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+	preventDefault: function() {
+		this.isDefaultPrevented = returnTrue;
+
+		var e = this.originalEvent;
+		if ( !e ) {
+			return;
+		}
+		
+		// if preventDefault exists run it on the original event
+		if ( e.preventDefault ) {
+			e.preventDefault();
+
+		// otherwise set the returnValue property of the original event to false (IE)
+		} else {
+			e.returnValue = false;
+		}
+	},
+	stopPropagation: function() {
+		this.isPropagationStopped = returnTrue;
+
+		var e = this.originalEvent;
+		if ( !e ) {
+			return;
+		}
+		// if stopPropagation exists run it on the original event
+		if ( e.stopPropagation ) {
+			e.stopPropagation();
+		}
+		// otherwise set the cancelBubble property of the original event to true (IE)
+		e.cancelBubble = true;
+	},
+	stopImmediatePropagation: function() {
+		this.isImmediatePropagationStopped = returnTrue;
+		this.stopPropagation();
+	},
+	isDefaultPrevented: returnFalse,
+	isPropagationStopped: returnFalse,
+	isImmediatePropagationStopped: returnFalse
+};
+
+// Checks if an event happened on an element within another element
+// Used in jQuery.event.special.mouseenter and mouseleave handlers
+var withinElement = function( event ) {
+	// Check if mouse(over|out) are still within the same parent element
+	var parent = event.relatedTarget;
+
+	// Firefox sometimes assigns relatedTarget a XUL element
+	// which we cannot access the parentNode property of
+	try {
+		// Traverse up the tree
+		while ( parent && parent !== this ) {
+			parent = parent.parentNode;
+		}
+
+		if ( parent !== this ) {
+			// set the correct event type
+			event.type = event.data;
+
+			// handle event if we actually just moused on to a non sub-element
+			jQuery.event.handle.apply( this, arguments );
+		}
+
+	// assuming we've left the element since we most likely mousedover a xul element
+	} catch(e) { }
+},
+
+// In case of event delegation, we only need to rename the event.type,
+// liveHandler will take care of the rest.
+delegate = function( event ) {
+	event.type = event.data;
+	jQuery.event.handle.apply( this, arguments );
+};
+
+// Create mouseenter and mouseleave events
+jQuery.each({
+	mouseenter: "mouseover",
+	mouseleave: "mouseout"
+}, function( orig, fix ) {
+	jQuery.event.special[ orig ] = {
+		setup: function( data ) {
+			jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
+		},
+		teardown: function( data ) {
+			jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
+		}
+	};
+});
+
+// submit delegation
+if ( !jQuery.support.submitBubbles ) {
+
+	jQuery.event.special.submit = {
+		setup: function( data, namespaces ) {
+			if ( this.nodeName.toLowerCase() !== "form" ) {
+				jQuery.event.add(this, "click.specialSubmit", function( e ) {
+					var elem = e.target,
+						type = elem.type;
+
+					if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
+						e.liveFired = undefined;
+						return trigger( "submit", this, arguments );
+					}
+				});
+	 
+				jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
+					var elem = e.target,
+						type = elem.type;
+
+					if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
+						e.liveFired = undefined;
+						return trigger( "submit", this, arguments );
+					}
+				});
+
+			} else {
+				return false;
+			}
+		},
+
+		teardown: function( namespaces ) {
+			jQuery.event.remove( this, ".specialSubmit" );
+		}
+	};
+
+}
+
+// change delegation, happens here so we have bind.
+if ( !jQuery.support.changeBubbles ) {
+
+	var changeFilters,
+
+	getVal = function( elem ) {
+		var type = elem.type, val = elem.value;
+
+		if ( type === "radio" || type === "checkbox" ) {
+			val = elem.checked;
+
+		} else if ( type === "select-multiple" ) {
+			val = elem.selectedIndex > -1 ?
+				jQuery.map( elem.options, function( elem ) {
+					return elem.selected;
+				}).join("-") :
+				"";
+
+		} else if ( elem.nodeName.toLowerCase() === "select" ) {
+			val = elem.selectedIndex;
+		}
+
+		return val;
+	},
+
+	testChange = function testChange( e ) {
+		var elem = e.target, data, val;
+
+		if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {
+			return;
+		}
+
+		data = jQuery.data( elem, "_change_data" );
+		val = getVal(elem);
+
+		// the current data will be also retrieved by beforeactivate
+		if ( e.type !== "focusout" || elem.type !== "radio" ) {
+			jQuery.data( elem, "_change_data", val );
+		}
+		
+		if ( data === undefined || val === data ) {
+			return;
+		}
+
+		if ( data != null || val ) {
+			e.type = "change";
+			e.liveFired = undefined;
+			return jQuery.event.trigger( e, arguments[1], elem );
+		}
+	};
+
+	jQuery.event.special.change = {
+		filters: {
+			focusout: testChange, 
+
+			beforedeactivate: testChange,
+
+			click: function( e ) {
+				var elem = e.target, type = elem.type;
+
+				if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
+					return testChange.call( this, e );
+				}
+			},
+
+			// Change has to be called before submit
+			// Keydown will be called before keypress, which is used in submit-event delegation
+			keydown: function( e ) {
+				var elem = e.target, type = elem.type;
+
+				if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
+					(e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
+					type === "select-multiple" ) {
+					return testChange.call( this, e );
+				}
+			},
+
+			// Beforeactivate happens also before the previous element is blurred
+			// with this event you can't trigger a change event, but you can store
+			// information
+			beforeactivate: function( e ) {
+				var elem = e.target;
+				jQuery.data( elem, "_change_data", getVal(elem) );
+			}
+		},
+
+		setup: function( data, namespaces ) {
+			if ( this.type === "file" ) {
+				return false;
+			}
+
+			for ( var type in changeFilters ) {
+				jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
+			}
+
+			return rformElems.test( this.nodeName );
+		},
+
+		teardown: function( namespaces ) {
+			jQuery.event.remove( this, ".specialChange" );
+
+			return rformElems.test( this.nodeName );
+		}
+	};
+
+	changeFilters = jQuery.event.special.change.filters;
+
+	// Handle when the input is .focus()'d
+	changeFilters.focus = changeFilters.beforeactivate;
+}
+
+function trigger( type, elem, args ) {
+	args[0].type = type;
+	return jQuery.event.handle.apply( elem, args );
+}
+
+// Create "bubbling" focus and blur events
+if ( document.addEventListener ) {
+	jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+		jQuery.event.special[ fix ] = {
+			setup: function() {
+				if ( focusCounts[fix]++ === 0 ) {
+					document.addEventListener( orig, handler, true );
+				}
+			}, 
+			teardown: function() { 
+				if ( --focusCounts[fix] === 0 ) {
+					document.removeEventListener( orig, handler, true );
+				}
+			}
+		};
+
+		function handler( e ) { 
+			e = jQuery.event.fix( e );
+			e.type = fix;
+			return jQuery.event.trigger( e, null, e.target );
+		}
+	});
+}
+
+jQuery.each(["bind", "one"], function( i, name ) {
+	jQuery.fn[ name ] = function( type, data, fn ) {
+		// Handle object literals
+		if ( typeof type === "object" ) {
+			for ( var key in type ) {
+				this[ name ](key, data, type[key], fn);
+			}
+			return this;
+		}
+		
+		if ( jQuery.isFunction( data ) || data === false ) {
+			fn = data;
+			data = undefined;
+		}
+
+		var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
+			jQuery( this ).unbind( event, handler );
+			return fn.apply( this, arguments );
+		}) : fn;
+
+		if ( type === "unload" && name !== "one" ) {
+			this.one( type, data, fn );
+
+		} else {
+			for ( var i = 0, l = this.length; i < l; i++ ) {
+				jQuery.event.add( this[i], type, handler, data );
+			}
+		}
+
+		return this;
+	};
+});
+
+jQuery.fn.extend({
+	unbind: function( type, fn ) {
+		// Handle object literals
+		if ( typeof type === "object" && !type.preventDefault ) {
+			for ( var key in type ) {
+				this.unbind(key, type[key]);
+			}
+
+		} else {
+			for ( var i = 0, l = this.length; i < l; i++ ) {
+				jQuery.event.remove( this[i], type, fn );
+			}
+		}
+
+		return this;
+	},
+	
+	delegate: function( selector, types, data, fn ) {
+		return this.live( types, data, fn, selector );
+	},
+	
+	undelegate: function( selector, types, fn ) {
+		if ( arguments.length === 0 ) {
+				return this.unbind( "live" );
+		
+		} else {
+			return this.die( types, null, fn, selector );
+		}
+	},
+	
+	trigger: function( type, data ) {
+		return this.each(function() {
+			jQuery.event.trigger( type, data, this );
+		});
+	},
+
+	triggerHandler: function( type, data ) {
+		if ( this[0] ) {
+			var event = jQuery.Event( type );
+			event.preventDefault();
+			event.stopPropagation();
+			jQuery.event.trigger( event, data, this[0] );
+			return event.result;
+		}
+	},
+
+	toggle: function( fn ) {
+		// Save reference to arguments for access in closure
+		var args = arguments,
+			i = 1;
+
+		// link all the functions, so any of them can unbind this click handler
+		while ( i < args.length ) {
+			jQuery.proxy( fn, args[ i++ ] );
+		}
+
+		return this.click( jQuery.proxy( fn, function( event ) {
+			// Figure out which function to execute
+			var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
+			jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
+
+			// Make sure that clicks stop
+			event.preventDefault();
+
+			// and execute the function
+			return args[ lastToggle ].apply( this, arguments ) || false;
+		}));
+	},
+
+	hover: function( fnOver, fnOut ) {
+		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+	}
+});
+
+var liveMap = {
+	focus: "focusin",
+	blur: "focusout",
+	mouseenter: "mouseover",
+	mouseleave: "mouseout"
+};
+
+jQuery.each(["live", "die"], function( i, name ) {
+	jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
+		var type, i = 0, match, namespaces, preType,
+			selector = origSelector || this.selector,
+			context = origSelector ? this : jQuery( this.context );
+		
+		if ( typeof types === "object" && !types.preventDefault ) {
+			for ( var key in types ) {
+				context[ name ]( key, data, types[key], selector );
+			}
+			
+			return this;
+		}
+
+		if ( jQuery.isFunction( data ) ) {
+			fn = data;
+			data = undefined;
+		}
+
+		types = (types || "").split(" ");
+
+		while ( (type = types[ i++ ]) != null ) {
+			match = rnamespaces.exec( type );
+			namespaces = "";
+
+			if ( match )  {
+				namespaces = match[0];
+				type = type.replace( rnamespaces, "" );
+			}
+
+			if ( type === "hover" ) {
+				types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
+				continue;
+			}
+
+			preType = type;
+
+			if ( type === "focus" || type === "blur" ) {
+				types.push( liveMap[ type ] + namespaces );
+				type = type + namespaces;
+
+			} else {
+				type = (liveMap[ type ] || type) + namespaces;
+			}
+
+			if ( name === "live" ) {
+				// bind live handler
+				for ( var j = 0, l = context.length; j < l; j++ ) {
+					jQuery.event.add( context[j], "live." + liveConvert( type, selector ),
+						{ data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
+				}
+
+			} else {
+				// unbind live handler
+				context.unbind( "live." + liveConvert( type, selector ), fn );
+			}
+		}
+		
+		return this;
+	};
+});
+
+function liveHandler( event ) {
+	var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
+		elems = [],
+		selectors = [],
+		events = jQuery.data( this, this.nodeType ? "events" : "__events__" );
+
+	if ( typeof events === "function" ) {
+		events = events.events;
+	}
+
+	// Make sure we avoid non-left-click bubbling in Firefox (#3861)
+	if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) {
+		return;
+	}
+	
+	if ( event.namespace ) {
+		namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)");
+	}
+
+	event.liveFired = this;
+
+	var live = events.live.slice(0);
+
+	for ( j = 0; j < live.length; j++ ) {
+		handleObj = live[j];
+
+		if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
+			selectors.push( handleObj.selector );
+
+		} else {
+			live.splice( j--, 1 );
+		}
+	}
+
+	match = jQuery( event.target ).closest( selectors, event.currentTarget );
+
+	for ( i = 0, l = match.length; i < l; i++ ) {
+		close = match[i];
+
+		for ( j = 0; j < live.length; j++ ) {
+			handleObj = live[j];
+
+			if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) ) {
+				elem = close.elem;
+				related = null;
+
+				// Those two events require additional checking
+				if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
+					event.type = handleObj.preType;
+					related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
+				}
+
+				if ( !related || related !== elem ) {
+					elems.push({ elem: elem, handleObj: handleObj, level: close.level });
+				}
+			}
+		}
+	}
+
+	for ( i = 0, l = elems.length; i < l; i++ ) {
+		match = elems[i];
+
+		if ( maxLevel && match.level > maxLevel ) {
+			break;
+		}
+
+		event.currentTarget = match.elem;
+		event.data = match.handleObj.data;
+		event.handleObj = match.handleObj;
+
+		ret = match.handleObj.origHandler.apply( match.elem, arguments );
+
+		if ( ret === false || event.isPropagationStopped() ) {
+			maxLevel = match.level;
+
+			if ( ret === false ) {
+				stop = false;
+			}
+			if ( event.isImmediatePropagationStopped() ) {
+				break;
+			}
+		}
+	}
+
+	return stop;
+}
+
+function liveConvert( type, selector ) {
+	return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&");
+}
+
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
+	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+	"change select submit keydown keypress keyup error").split(" "), function( i, name ) {
+
+	// Handle event binding
+	jQuery.fn[ name ] = function( data, fn ) {
+		if ( fn == null ) {
+			fn = data;
+			data = null;
+		}
+
+		return arguments.length > 0 ?
+			this.bind( name, data, fn ) :
+			this.trigger( name );
+	};
+
+	if ( jQuery.attrFn ) {
+		jQuery.attrFn[ name ] = true;
+	}
+});
+
+// Prevent memory leaks in IE
+// Window isn't included so as not to unbind existing unload events
+// More info:
+//  - http://isaacschlueter.com/2006/10/msie-memory-leaks/
+if ( window.attachEvent && !window.addEventListener ) {
+	jQuery(window).bind("unload", function() {
+		for ( var id in jQuery.cache ) {
+			if ( jQuery.cache[ id ].handle ) {
+				// Try/Catch is to handle iframes being unloaded, see #4280
+				try {
+					jQuery.event.remove( jQuery.cache[ id ].handle.elem );
+				} catch(e) {}
+			}
+		}
+	});
+}
+
+
+/*!
+ * Sizzle CSS Selector Engine - v1.0
+ *  Copyright 2009, The Dojo Foundation
+ *  Released under the MIT, BSD, and GPL Licenses.
+ *  More information: http://sizzlejs.com/
+ */
+(function(){
+
+var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
+	done = 0,
+	toString = Object.prototype.toString,
+	hasDuplicate = false,
+	baseHasDuplicate = true;
+
+// Here we check if the JavaScript engine is using some sort of
+// optimization where it does not always call our comparision
+// function. If that is the case, discard the hasDuplicate value.
+//   Thus far that includes Google Chrome.
+[0, 0].sort(function() {
+	baseHasDuplicate = false;
+	return 0;
+});
+
+var Sizzle = function( selector, context, results, seed ) {
+	results = results || [];
+	context = context || document;
+
+	var origContext = context;
+
+	if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
+		return [];
+	}
+	
+	if ( !selector || typeof selector !== "string" ) {
+		return results;
+	}
+
+	var m, set, checkSet, extra, ret, cur, pop, i,
+		prune = true,
+		contextXML = Sizzle.isXML( context ),
+		parts = [],
+		soFar = selector;
+	
+	// Reset the position of the chunker regexp (start from head)
+	do {
+		chunker.exec( "" );
+		m = chunker.exec( soFar );
+
+		if ( m ) {
+			soFar = m[3];
+		
+			parts.push( m[1] );
+		
+			if ( m[2] ) {
+				extra = m[3];
+				break;
+			}
+		}
+	} while ( m );
+
+	if ( parts.length > 1 && origPOS.exec( selector ) ) {
+
+		if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
+			set = posProcess( parts[0] + parts[1], context );
+
+		} else {
+			set = Expr.relative[ parts[0] ] ?
+				[ context ] :
+				Sizzle( parts.shift(), context );
+
+			while ( parts.length ) {
+				selector = parts.shift();
+
+				if ( Expr.relative[ selector ] ) {
+					selector += parts.shift();
+				}
+				
+				set = posProcess( selector, set );
+			}
+		}
+
+	} else {
+		// Take a shortcut and set the context if the root selector is an ID
+		// (but not if it'll be faster if the inner selector is an ID)
+		if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
+				Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
+
+			ret = Sizzle.find( parts.shift(), context, contextXML );
+			context = ret.expr ?
+				Sizzle.filter( ret.expr, ret.set )[0] :
+				ret.set[0];
+		}
+
+		if ( context ) {
+			ret = seed ?
+				{ expr: parts.pop(), set: makeArray(seed) } :
+				Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
+
+			set = ret.expr ?
+				Sizzle.filter( ret.expr, ret.set ) :
+				ret.set;
+
+			if ( parts.length > 0 ) {
+				checkSet = makeArray( set );
+
+			} else {
+				prune = false;
+			}
+
+			while ( parts.length ) {
+				cur = parts.pop();
+				pop = cur;
+
+				if ( !Expr.relative[ cur ] ) {
+					cur = "";
+				} else {
+					pop = parts.pop();
+				}
+
+				if ( pop == null ) {
+					pop = context;
+				}
+
+				Expr.relative[ cur ]( checkSet, pop, contextXML );
+			}
+
+		} else {
+			checkSet = parts = [];
+		}
+	}
+
+	if ( !checkSet ) {
+		checkSet = set;
+	}
+
+	if ( !checkSet ) {
+		Sizzle.error( cur || selector );
+	}
+
+	if ( toString.call(checkSet) === "[object Array]" ) {
+		if ( !prune ) {
+			results.push.apply( results, checkSet );
+
+		} else if ( context && context.nodeType === 1 ) {
+			for ( i = 0; checkSet[i] != null; i++ ) {
+				if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
+					results.push( set[i] );
+				}
+			}
+
+		} else {
+			for ( i = 0; checkSet[i] != null; i++ ) {
+				if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
+					results.push( set[i] );
+				}
+			}
+		}
+
+	} else {
+		makeArray( checkSet, results );
+	}
+
+	if ( extra ) {
+		Sizzle( extra, origContext, results, seed );
+		Sizzle.uniqueSort( results );
+	}
+
+	return results;
+};
+
+Sizzle.uniqueSort = function( results ) {
+	if ( sortOrder ) {
+		hasDuplicate = baseHasDuplicate;
+		results.sort( sortOrder );
+
+		if ( hasDuplicate ) {
+			for ( var i = 1; i < results.length; i++ ) {
+				if ( results[i] === results[ i - 1 ] ) {
+					results.splice( i--, 1 );
+				}
+			}
+		}
+	}
+
+	return results;
+};
+
+Sizzle.matches = function( expr, set ) {
+	return Sizzle( expr, null, null, set );
+};
+
+Sizzle.matchesSelector = function( node, expr ) {
+	return Sizzle( expr, null, null, [node] ).length > 0;
+};
+
+Sizzle.find = function( expr, context, isXML ) {
+	var set;
+
+	if ( !expr ) {
+		return [];
+	}
+
+	for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
+		var match,
+			type = Expr.order[i];
+		
+		if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
+			var left = match[1];
+			match.splice( 1, 1 );
+
+			if ( left.substr( left.length - 1 ) !== "\\" ) {
+				match[1] = (match[1] || "").replace(/\\/g, "");
+				set = Expr.find[ type ]( match, context, isXML );
+
+				if ( set != null ) {
+					expr = expr.replace( Expr.match[ type ], "" );
+					break;
+				}
+			}
+		}
+	}
+
+	if ( !set ) {
+		set = context.getElementsByTagName( "*" );
+	}
+
+	return { set: set, expr: expr };
+};
+
+Sizzle.filter = function( expr, set, inplace, not ) {
+	var match, anyFound,
+		old = expr,
+		result = [],
+		curLoop = set,
+		isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
+
+	while ( expr && set.length ) {
+		for ( var type in Expr.filter ) {
+			if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
+				var found, item,
+					filter = Expr.filter[ type ],
+					left = match[1];
+
+				anyFound = false;
+
+				match.splice(1,1);
+
+				if ( left.substr( left.length - 1 ) === "\\" ) {
+					continue;
+				}
+
+				if ( curLoop === result ) {
+					result = [];
+				}
+
+				if ( Expr.preFilter[ type ] ) {
+					match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
+
+					if ( !match ) {
+						anyFound = found = true;
+
+					} else if ( match === true ) {
+						continue;
+					}
+				}
+
+				if ( match ) {
+					for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
+						if ( item ) {
+							found = filter( item, match, i, curLoop );
+							var pass = not ^ !!found;
+
+							if ( inplace && found != null ) {
+								if ( pass ) {
+									anyFound = true;
+
+								} else {
+									curLoop[i] = false;
+								}
+
+							} else if ( pass ) {
+								result.push( item );
+								anyFound = true;
+							}
+						}
+					}
+				}
+
+				if ( found !== undefined ) {
+					if ( !inplace ) {
+						curLoop = result;
+					}
+
+					expr = expr.replace( Expr.match[ type ], "" );
+
+					if ( !anyFound ) {
+						return [];
+					}
+
+					break;
+				}
+			}
+		}
+
+		// Improper expression
+		if ( expr === old ) {
+			if ( anyFound == null ) {
+				Sizzle.error( expr );
+
+			} else {
+				break;
+			}
+		}
+
+		old = expr;
+	}
+
+	return curLoop;
+};
+
+Sizzle.error = function( msg ) {
+	throw "Syntax error, unrecognized expression: " + msg;
+};
+
+var Expr = Sizzle.selectors = {
+	order: [ "ID", "NAME", "TAG" ],
+
+	match: {
+		ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
+		CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
+		NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
+		ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
+		TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
+		CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+\-]*)\))?/,
+		POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
+		PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
+	},
+
+	leftMatch: {},
+
+	attrMap: {
+		"class": "className",
+		"for": "htmlFor"
+	},
+
+	attrHandle: {
+		href: function( elem ) {
+			return elem.getAttribute( "href" );
+		}
+	},
+
+	relative: {
+		"+": function(checkSet, part){
+			var isPartStr = typeof part === "string",
+				isTag = isPartStr && !/\W/.test( part ),
+				isPartStrNotTag = isPartStr && !isTag;
+
+			if ( isTag ) {
+				part = part.toLowerCase();
+			}
+
+			for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
+				if ( (elem = checkSet[i]) ) {
+					while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
+
+					checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
+						elem || false :
+						elem === part;
+				}
+			}
+
+			if ( isPartStrNotTag ) {
+				Sizzle.filter( part, checkSet, true );
+			}
+		},
+
+		">": function( checkSet, part ) {
+			var elem,
+				isPartStr = typeof part === "string",
+				i = 0,
+				l = checkSet.length;
+
+			if ( isPartStr && !/\W/.test( part ) ) {
+				part = part.toLowerCase();
+
+				for ( ; i < l; i++ ) {
+					elem = checkSet[i];
+
+					if ( elem ) {
+						var parent = elem.parentNode;
+						checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
+					}
+				}
+
+			} else {
+				for ( ; i < l; i++ ) {
+					elem = checkSet[i];
+
+					if ( elem ) {
+						checkSet[i] = isPartStr ?
+							elem.parentNode :
+							elem.parentNode === part;
+					}
+				}
+
+				if ( isPartStr ) {
+					Sizzle.filter( part, checkSet, true );
+				}
+			}
+		},
+
+		"": function(checkSet, part, isXML){
+			var nodeCheck,
+				doneName = done++,
+				checkFn = dirCheck;
+
+			if ( typeof part === "string" && !/\W/.test(part) ) {
+				part = part.toLowerCase();
+				nodeCheck = part;
+				checkFn = dirNodeCheck;
+			}
+
+			checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
+		},
+
+		"~": function( checkSet, part, isXML ) {
+			var nodeCheck,
+				doneName = done++,
+				checkFn = dirCheck;
+
+			if ( typeof part === "string" && !/\W/.test( part ) ) {
+				part = part.toLowerCase();
+				nodeCheck = part;
+				checkFn = dirNodeCheck;
+			}
+
+			checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
+		}
+	},
+
+	find: {
+		ID: function( match, context, isXML ) {
+			if ( typeof context.getElementById !== "undefined" && !isXML ) {
+				var m = context.getElementById(match[1]);
+				// Check parentNode to catch when Blackberry 4.6 returns
+				// nodes that are no longer in the document #6963
+				return m && m.parentNode ? [m] : [];
+			}
+		},
+
+		NAME: function( match, context ) {
+			if ( typeof context.getElementsByName !== "undefined" ) {
+				var ret = [],
+					results = context.getElementsByName( match[1] );
+
+				for ( var i = 0, l = results.length; i < l; i++ ) {
+					if ( results[i].getAttribute("name") === match[1] ) {
+						ret.push( results[i] );
+					}
+				}
+
+				return ret.length === 0 ? null : ret;
+			}
+		},
+
+		TAG: function( match, context ) {
+			return context.getElementsByTagName( match[1] );
+		}
+	},
+	preFilter: {
+		CLASS: function( match, curLoop, inplace, result, not, isXML ) {
+			match = " " + match[1].replace(/\\/g, "") + " ";
+
+			if ( isXML ) {
+				return match;
+			}
+
+			for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
+				if ( elem ) {
+					if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) {
+						if ( !inplace ) {
+							result.push( elem );
+						}
+
+					} else if ( inplace ) {
+						curLoop[i] = false;
+					}
+				}
+			}
+
+			return false;
+		},
+
+		ID: function( match ) {
+			return match[1].replace(/\\/g, "");
+		},
+
+		TAG: function( match, curLoop ) {
+			return match[1].toLowerCase();
+		},
+
+		CHILD: function( match ) {
+			if ( match[1] === "nth" ) {
+				// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
+				var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
+					match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
+					!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
+
+				// calculate the numbers (first)n+(last) including if they are negative
+				match[2] = (test[1] + (test[2] || 1)) - 0;
+				match[3] = test[3] - 0;
+			}
+
+			// TODO: Move to normal caching system
+			match[0] = done++;
+
+			return match;
+		},
+
+		ATTR: function( match, curLoop, inplace, result, not, isXML ) {
+			var name = match[1].replace(/\\/g, "");
+			
+			if ( !isXML && Expr.attrMap[name] ) {
+				match[1] = Expr.attrMap[name];
+			}
+
+			if ( match[2] === "~=" ) {
+				match[4] = " " + match[4] + " ";
+			}
+
+			return match;
+		},
+
+		PSEUDO: function( match, curLoop, inplace, result, not ) {
+			if ( match[1] === "not" ) {
+				// If we're dealing with a complex expression, or a simple one
+				if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
+					match[3] = Sizzle(match[3], null, null, curLoop);
+
+				} else {
+					var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
+
+					if ( !inplace ) {
+						result.push.apply( result, ret );
+					}
+
+					return false;
+				}
+
+			} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
+				return true;
+			}
+			
+			return match;
+		},
+
+		POS: function( match ) {
+			match.unshift( true );
+
+			return match;
+		}
+	},
+	
+	filters: {
+		enabled: function( elem ) {
+			return elem.disabled === false && elem.type !== "hidden";
+		},
+
+		disabled: function( elem ) {
+			return elem.disabled === true;
+		},
+
+		checked: function( elem ) {
+			return elem.checked === true;
+		},
+		
+		selected: function( elem ) {
+			// Accessing this property makes selected-by-default
+			// options in Safari work properly
+			elem.parentNode.selectedIndex;
+			
+			return elem.selected === true;
+		},
+
+		parent: function( elem ) {
+			return !!elem.firstChild;
+		},
+
+		empty: function( elem ) {
+			return !elem.firstChild;
+		},
+
+		has: function( elem, i, match ) {
+			return !!Sizzle( match[3], elem ).length;
+		},
+
+		header: function( elem ) {
+			return (/h\d/i).test( elem.nodeName );
+		},
+
+		text: function( elem ) {
+			return "text" === elem.type;
+		},
+		radio: function( elem ) {
+			return "radio" === elem.type;
+		},
+
+		checkbox: function( elem ) {
+			return "checkbox" === elem.type;
+		},
+
+		file: function( elem ) {
+			return "file" === elem.type;
+		},
+		password: function( elem ) {
+			return "password" === elem.type;
+		},
+
+		submit: function( elem ) {
+			return "submit" === elem.type;
+		},
+
+		image: function( elem ) {
+			return "image" === elem.type;
+		},
+
+		reset: function( elem ) {
+			return "reset" === elem.type;
+		},
+
+		button: function( elem ) {
+			return "button" === elem.type || elem.nodeName.toLowerCase() === "button";
+		},
+
+		input: function( elem ) {
+			return (/input|select|textarea|button/i).test( elem.nodeName );
+		}
+	},
+	setFilters: {
+		first: function( elem, i ) {
+			return i === 0;
+		},
+
+		last: function( elem, i, match, array ) {
+			return i === array.length - 1;
+		},
+
+		even: function( elem, i ) {
+			return i % 2 === 0;
+		},
+
+		odd: function( elem, i ) {
+			return i % 2 === 1;
+		},
+
+		lt: function( elem, i, match ) {
+			return i < match[3] - 0;
+		},
+
+		gt: function( elem, i, match ) {
+			return i > match[3] - 0;
+		},
+
+		nth: function( elem, i, match ) {
+			return match[3] - 0 === i;
+		},
+
+		eq: function( elem, i, match ) {
+			return match[3] - 0 === i;
+		}
+	},
+	filter: {
+		PSEUDO: function( elem, match, i, array ) {
+			var name = match[1],
+				filter = Expr.filters[ name ];
+
+			if ( filter ) {
+				return filter( elem, i, match, array );
+
+			} else if ( name === "contains" ) {
+				return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0;
+
+			} else if ( name === "not" ) {
+				var not = match[3];
+
+				for ( var j = 0, l = not.length; j < l; j++ ) {
+					if ( not[j] === elem ) {
+						return false;
+					}
+				}
+
+				return true;
+
+			} else {
+				Sizzle.error( "Syntax error, unrecognized expression: " + name );
+			}
+		},
+
+		CHILD: function( elem, match ) {
+			var type = match[1],
+				node = elem;
+
+			switch ( type ) {
+				case "only":
+				case "first":
+					while ( (node = node.previousSibling) )	 {
+						if ( node.nodeType === 1 ) { 
+							return false; 
+						}
+					}
+
+					if ( type === "first" ) { 
+						return true; 
+					}
+
+					node = elem;
+
+				case "last":
+					while ( (node = node.nextSibling) )	 {
+						if ( node.nodeType === 1 ) { 
+							return false; 
+						}
+					}
+
+					return true;
+
+				case "nth":
+					var first = match[2],
+						last = match[3];
+
+					if ( first === 1 && last === 0 ) {
+						return true;
+					}
+					
+					var doneName = match[0],
+						parent = elem.parentNode;
+	
+					if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
+						var count = 0;
+						
+						for ( node = parent.firstChild; node; node = node.nextSibling ) {
+							if ( node.nodeType === 1 ) {
+								node.nodeIndex = ++count;
+							}
+						} 
+
+						parent.sizcache = doneName;
+					}
+					
+					var diff = elem.nodeIndex - last;
+
+					if ( first === 0 ) {
+						return diff === 0;
+
+					} else {
+						return ( diff % first === 0 && diff / first >= 0 );
+					}
+			}
+		},
+
+		ID: function( elem, match ) {
+			return elem.nodeType === 1 && elem.getAttribute("id") === match;
+		},
+
+		TAG: function( elem, match ) {
+			return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;
+		},
+		
+		CLASS: function( elem, match ) {
+			return (" " + (elem.className || elem.getAttribute("class")) + " ")
+				.indexOf( match ) > -1;
+		},
+
+		ATTR: function( elem, match ) {
+			var name = match[1],
+				result = Expr.attrHandle[ name ] ?
+					Expr.attrHandle[ name ]( elem ) :
+					elem[ name ] != null ?
+						elem[ name ] :
+						elem.getAttribute( name ),
+				value = result + "",
+				type = match[2],
+				check = match[4];
+
+			return result == null ?
+				type === "!=" :
+				type === "=" ?
+				value === check :
+				type === "*=" ?
+				value.indexOf(check) >= 0 :
+				type === "~=" ?
+				(" " + value + " ").indexOf(check) >= 0 :
+				!check ?
+				value && result !== false :
+				type === "!=" ?
+				value !== check :
+				type === "^=" ?
+				value.indexOf(check) === 0 :
+				type === "$=" ?
+				value.substr(value.length - check.length) === check :
+				type === "|=" ?
+				value === check || value.substr(0, check.length + 1) === check + "-" :
+				false;
+		},
+
+		POS: function( elem, match, i, array ) {
+			var name = match[2],
+				filter = Expr.setFilters[ name ];
+
+			if ( filter ) {
+				return filter( elem, i, match, array );
+			}
+		}
+	}
+};
+
+var origPOS = Expr.match.POS,
+	fescape = function(all, num){
+		return "\\" + (num - 0 + 1);
+	};
+
+for ( var type in Expr.match ) {
+	Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
+	Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
+}
+
+var makeArray = function( array, results ) {
+	array = Array.prototype.slice.call( array, 0 );
+
+	if ( results ) {
+		results.push.apply( results, array );
+		return results;
+	}
+	
+	return array;
+};
+
+// Perform a simple check to determine if the browser is capable of
+// converting a NodeList to an array using builtin methods.
+// Also verifies that the returned array holds DOM nodes
+// (which is not the case in the Blackberry browser)
+try {
+	Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
+
+// Provide a fallback method if it does not work
+} catch( e ) {
+	makeArray = function( array, results ) {
+		var i = 0,
+			ret = results || [];
+
+		if ( toString.call(array) === "[object Array]" ) {
+			Array.prototype.push.apply( ret, array );
+
+		} else {
+			if ( typeof array.length === "number" ) {
+				for ( var l = array.length; i < l; i++ ) {
+					ret.push( array[i] );
+				}
+
+			} else {
+				for ( ; array[i]; i++ ) {
+					ret.push( array[i] );
+				}
+			}
+		}
+
+		return ret;
+	};
+}
+
+var sortOrder, siblingCheck;
+
+if ( document.documentElement.compareDocumentPosition ) {
+	sortOrder = function( a, b ) {
+		if ( a === b ) {
+			hasDuplicate = true;
+			return 0;
+		}
+
+		if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
+			return a.compareDocumentPosition ? -1 : 1;
+		}
+
+		return a.compareDocumentPosition(b) & 4 ? -1 : 1;
+	};
+
+} else {
+	sortOrder = function( a, b ) {
+		var al, bl,
+			ap = [],
+			bp = [],
+			aup = a.parentNode,
+			bup = b.parentNode,
+			cur = aup;
+
+		// The nodes are identical, we can exit early
+		if ( a === b ) {
+			hasDuplicate = true;
+			return 0;
+
+		// If the nodes are siblings (or identical) we can do a quick check
+		} else if ( aup === bup ) {
+			return siblingCheck( a, b );
+
+		// If no parents were found then the nodes are disconnected
+		} else if ( !aup ) {
+			return -1;
+
+		} else if ( !bup ) {
+			return 1;
+		}
+
+		// Otherwise they're somewhere else in the tree so we need
+		// to build up a full list of the parentNodes for comparison
+		while ( cur ) {
+			ap.unshift( cur );
+			cur = cur.parentNode;
+		}
+
+		cur = bup;
+
+		while ( cur ) {
+			bp.unshift( cur );
+			cur = cur.parentNode;
+		}
+
+		al = ap.length;
+		bl = bp.length;
+
+		// Start walking down the tree looking for a discrepancy
+		for ( var i = 0; i < al && i < bl; i++ ) {
+			if ( ap[i] !== bp[i] ) {
+				return siblingCheck( ap[i], bp[i] );
+			}
+		}
+
+		// We ended someplace up the tree so do a sibling check
+		return i === al ?
+			siblingCheck( a, bp[i], -1 ) :
+			siblingCheck( ap[i], b, 1 );
+	};
+
+	siblingCheck = function( a, b, ret ) {
+		if ( a === b ) {
+			return ret;
+		}
+
+		var cur = a.nextSibling;
+
+		while ( cur ) {
+			if ( cur === b ) {
+				return -1;
+			}
+
+			cur = cur.nextSibling;
+		}
+
+		return 1;
+	};
+}
+
+// Utility function for retreiving the text value of an array of DOM nodes
+Sizzle.getText = function( elems ) {
+	var ret = "", elem;
+
+	for ( var i = 0; elems[i]; i++ ) {
+		elem = elems[i];
+
+		// Get the text from text nodes and CDATA nodes
+		if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
+			ret += elem.nodeValue;
+
+		// Traverse everything else, except comment nodes
+		} else if ( elem.nodeType !== 8 ) {
+			ret += Sizzle.getText( elem.childNodes );
+		}
+	}
+
+	return ret;
+};
+
+// Check to see if the browser returns elements by name when
+// querying by getElementById (and provide a workaround)
+(function(){
+	// We're going to inject a fake input element with a specified name
+	var form = document.createElement("div"),
+		id = "script" + (new Date()).getTime(),
+		root = document.documentElement;
+
+	form.innerHTML = "<a name='" + id + "'/>";
+
+	// Inject it into the root element, check its status, and remove it quickly
+	root.insertBefore( form, root.firstChild );
+
+	// The workaround has to do additional checks after a getElementById
+	// Which slows things down for other browsers (hence the branching)
+	if ( document.getElementById( id ) ) {
+		Expr.find.ID = function( match, context, isXML ) {
+			if ( typeof context.getElementById !== "undefined" && !isXML ) {
+				var m = context.getElementById(match[1]);
+
+				return m ?
+					m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
+						[m] :
+						undefined :
+					[];
+			}
+		};
+
+		Expr.filter.ID = function( elem, match ) {
+			var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
+
+			return elem.nodeType === 1 && node && node.nodeValue === match;
+		};
+	}
+
+	root.removeChild( form );
+
+	// release memory in IE
+	root = form = null;
+})();
+
+(function(){
+	// Check to see if the browser returns only elements
+	// when doing getElementsByTagName("*")
+
+	// Create a fake element
+	var div = document.createElement("div");
+	div.appendChild( document.createComment("") );
+
+	// Make sure no comments are found
+	if ( div.getElementsByTagName("*").length > 0 ) {
+		Expr.find.TAG = function( match, context ) {
+			var results = context.getElementsByTagName( match[1] );
+
+			// Filter out possible comments
+			if ( match[1] === "*" ) {
+				var tmp = [];
+
+				for ( var i = 0; results[i]; i++ ) {
+					if ( results[i].nodeType === 1 ) {
+						tmp.push( results[i] );
+					}
+				}
+
+				results = tmp;
+			}
+
+			return results;
+		};
+	}
+
+	// Check to see if an attribute returns normalized href attributes
+	div.innerHTML = "<a href='#'></a>";
+
+	if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
+			div.firstChild.getAttribute("href") !== "#" ) {
+
+		Expr.attrHandle.href = function( elem ) {
+			return elem.getAttribute( "href", 2 );
+		};
+	}
+
+	// release memory in IE
+	div = null;
+})();
+
+if ( document.querySelectorAll ) {
+	(function(){
+		var oldSizzle = Sizzle,
+			div = document.createElement("div"),
+			id = "__sizzle__";
+
+		div.innerHTML = "<p class='TEST'></p>";
+
+		// Safari can't handle uppercase or unicode characters when
+		// in quirks mode.
+		if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
+			return;
+		}
+	
+		Sizzle = function( query, context, extra, seed ) {
+			context = context || document;
+
+			// Make sure that attribute selectors are quoted
+			query = query.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
+
+			// Only use querySelectorAll on non-XML documents
+			// (ID selectors don't work in non-HTML documents)
+			if ( !seed && !Sizzle.isXML(context) ) {
+				if ( context.nodeType === 9 ) {
+					try {
+						return makeArray( context.querySelectorAll(query), extra );
+					} catch(qsaError) {}
+
+				// qSA works strangely on Element-rooted queries
+				// We can work around this by specifying an extra ID on the root
+				// and working up from there (Thanks to Andrew Dupont for the technique)
+				// IE 8 doesn't work on object elements
+				} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
+					var old = context.getAttribute( "id" ),
+						nid = old || id;
+
+					if ( !old ) {
+						context.setAttribute( "id", nid );
+					}
+
+					try {
+						return makeArray( context.querySelectorAll( "#" + nid + " " + query ), extra );
+
+					} catch(pseudoError) {
+					} finally {
+						if ( !old ) {
+							context.removeAttribute( "id" );
+						}
+					}
+				}
+			}
+		
+			return oldSizzle(query, context, extra, seed);
+		};
+
+		for ( var prop in oldSizzle ) {
+			Sizzle[ prop ] = oldSizzle[ prop ];
+		}
+
+		// release memory in IE
+		div = null;
+	})();
+}
+
+(function(){
+	var html = document.documentElement,
+		matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector,
+		pseudoWorks = false;
+
+	try {
+		// This should fail with an exception
+		// Gecko does not error, returns false instead
+		matches.call( document.documentElement, "[test!='']:sizzle" );
+	
+	} catch( pseudoError ) {
+		pseudoWorks = true;
+	}
+
+	if ( matches ) {
+		Sizzle.matchesSelector = function( node, expr ) {
+			// Make sure that attribute selectors are quoted
+			expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
+
+			if ( !Sizzle.isXML( node ) ) {
+				try { 
+					if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
+						return matches.call( node, expr );
+					}
+				} catch(e) {}
+			}
+
+			return Sizzle(expr, null, null, [node]).length > 0;
+		};
+	}
+})();
+
+(function(){
+	var div = document.createElement("div");
+
+	div.innerHTML = "<div class='test e'></div><div class='test'></div>";
+
+	// Opera can't find a second classname (in 9.6)
+	// Also, make sure that getElementsByClassName actually exists
+	if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
+		return;
+	}
+
+	// Safari caches class attributes, doesn't catch changes (in 3.2)
+	div.lastChild.className = "e";
+
+	if ( div.getElementsByClassName("e").length === 1 ) {
+		return;
+	}
+	
+	Expr.order.splice(1, 0, "CLASS");
+	Expr.find.CLASS = function( match, context, isXML ) {
+		if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
+			return context.getElementsByClassName(match[1]);
+		}
+	};
+
+	// release memory in IE
+	div = null;
+})();
+
+function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+		var elem = checkSet[i];
+
+		if ( elem ) {
+			var match = false;
+
+			elem = elem[dir];
+
+			while ( elem ) {
+				if ( elem.sizcache === doneName ) {
+					match = checkSet[elem.sizset];
+					break;
+				}
+
+				if ( elem.nodeType === 1 && !isXML ){
+					elem.sizcache = doneName;
+					elem.sizset = i;
+				}
+
+				if ( elem.nodeName.toLowerCase() === cur ) {
+					match = elem;
+					break;
+				}
+
+				elem = elem[dir];
+			}
+
+			checkSet[i] = match;
+		}
+	}
+}
+
+function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+		var elem = checkSet[i];
+
+		if ( elem ) {
+			var match = false;
+			
+			elem = elem[dir];
+
+			while ( elem ) {
+				if ( elem.sizcache === doneName ) {
+					match = checkSet[elem.sizset];
+					break;
+				}
+
+				if ( elem.nodeType === 1 ) {
+					if ( !isXML ) {
+						elem.sizcache = doneName;
+						elem.sizset = i;
+					}
+
+					if ( typeof cur !== "string" ) {
+						if ( elem === cur ) {
+							match = true;
+							break;
+						}
+
+					} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
+						match = elem;
+						break;
+					}
+				}
+
+				elem = elem[dir];
+			}
+
+			checkSet[i] = match;
+		}
+	}
+}
+
+if ( document.documentElement.contains ) {
+	Sizzle.contains = function( a, b ) {
+		return a !== b && (a.contains ? a.contains(b) : true);
+	};
+
+} else if ( document.documentElement.compareDocumentPosition ) {
+	Sizzle.contains = function( a, b ) {
+		return !!(a.compareDocumentPosition(b) & 16);
+	};
+
+} else {
+	Sizzle.contains = function() {
+		return false;
+	};
+}
+
+Sizzle.isXML = function( elem ) {
+	// documentElement is verified for cases where it doesn't yet exist
+	// (such as loading iframes in IE - #4833) 
+	var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
+
+	return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+var posProcess = function( selector, context ) {
+	var match,
+		tmpSet = [],
+		later = "",
+		root = context.nodeType ? [context] : context;
+
+	// Position selectors must be done after the filter
+	// And so must :not(positional) so we move all PSEUDOs to the end
+	while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
+		later += match[0];
+		selector = selector.replace( Expr.match.PSEUDO, "" );
+	}
+
+	selector = Expr.relative[selector] ? selector + "*" : selector;
+
+	for ( var i = 0, l = root.length; i < l; i++ ) {
+		Sizzle( selector, root[i], tmpSet );
+	}
+
+	return Sizzle.filter( later, tmpSet );
+};
+
+// EXPOSE
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.filters;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+})();
+
+
+var runtil = /Until$/,
+	rparentsprev = /^(?:parents|prevUntil|prevAll)/,
+	// Note: This RegExp should be improved, or likely pulled from Sizzle
+	rmultiselector = /,/,
+	isSimple = /^.[^:#\[\.,]*$/,
+	slice = Array.prototype.slice,
+	POS = jQuery.expr.match.POS;
+
+jQuery.fn.extend({
+	find: function( selector ) {
+		var ret = this.pushStack( "", "find", selector ),
+			length = 0;
+
+		for ( var i = 0, l = this.length; i < l; i++ ) {
+			length = ret.length;
+			jQuery.find( selector, this[i], ret );
+
+			if ( i > 0 ) {
+				// Make sure that the results are unique
+				for ( var n = length; n < ret.length; n++ ) {
+					for ( var r = 0; r < length; r++ ) {
+						if ( ret[r] === ret[n] ) {
+							ret.splice(n--, 1);
+							break;
+						}
+					}
+				}
+			}
+		}
+
+		return ret;
+	},
+
+	has: function( target ) {
+		var targets = jQuery( target );
+		return this.filter(function() {
+			for ( var i = 0, l = targets.length; i < l; i++ ) {
+				if ( jQuery.contains( this, targets[i] ) ) {
+					return true;
+				}
+			}
+		});
+	},
+
+	not: function( selector ) {
+		return this.pushStack( winnow(this, selector, false), "not", selector);
+	},
+
+	filter: function( selector ) {
+		return this.pushStack( winnow(this, selector, true), "filter", selector );
+	},
+	
+	is: function( selector ) {
+		return !!selector && jQuery.filter( selector, this ).length > 0;
+	},
+
+	closest: function( selectors, context ) {
+		var ret = [], i, l, cur = this[0];
+
+		if ( jQuery.isArray( selectors ) ) {
+			var match, selector,
+				matches = {},
+				level = 1;
+
+			if ( cur && selectors.length ) {
+				for ( i = 0, l = selectors.length; i < l; i++ ) {
+					selector = selectors[i];
+
+					if ( !matches[selector] ) {
+						matches[selector] = jQuery.expr.match.POS.test( selector ) ? 
+							jQuery( selector, context || this.context ) :
+							selector;
+					}
+				}
+
+				while ( cur && cur.ownerDocument && cur !== context ) {
+					for ( selector in matches ) {
+						match = matches[selector];
+
+						if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) {
+							ret.push({ selector: selector, elem: cur, level: level });
+						}
+					}
+
+					cur = cur.parentNode;
+					level++;
+				}
+			}
+
+			return ret;
+		}
+
+		var pos = POS.test( selectors ) ? 
+			jQuery( selectors, context || this.context ) : null;
+
+		for ( i = 0, l = this.length; i < l; i++ ) {
+			cur = this[i];
+
+			while ( cur ) {
+				if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
+					ret.push( cur );
+					break;
+
+				} else {
+					cur = cur.parentNode;
+					if ( !cur || !cur.ownerDocument || cur === context ) {
+						break;
+					}
+				}
+			}
+		}
+
+		ret = ret.length > 1 ? jQuery.unique(ret) : ret;
+		
+		return this.pushStack( ret, "closest", selectors );
+	},
+	
+	// Determine the position of an element within
+	// the matched set of elements
+	index: function( elem ) {
+		if ( !elem || typeof elem === "string" ) {
+			return jQuery.inArray( this[0],
+				// If it receives a string, the selector is used
+				// If it receives nothing, the siblings are used
+				elem ? jQuery( elem ) : this.parent().children() );
+		}
+		// Locate the position of the desired element
+		return jQuery.inArray(
+			// If it receives a jQuery object, the first element is used
+			elem.jquery ? elem[0] : elem, this );
+	},
+
+	add: function( selector, context ) {
+		var set = typeof selector === "string" ?
+				jQuery( selector, context || this.context ) :
+				jQuery.makeArray( selector ),
+			all = jQuery.merge( this.get(), set );
+
+		return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
+			all :
+			jQuery.unique( all ) );
+	},
+
+	andSelf: function() {
+		return this.add( this.prevObject );
+	}
+});
+
+// A painfully simple check to see if an element is disconnected
+// from a document (should be improved, where feasible).
+function isDisconnected( node ) {
+	return !node || !node.parentNode || node.parentNode.nodeType === 11;
+}
+
+jQuery.each({
+	parent: function( elem ) {
+		var parent = elem.parentNode;
+		return parent && parent.nodeType !== 11 ? parent : null;
+	},
+	parents: function( elem ) {
+		return jQuery.dir( elem, "parentNode" );
+	},
+	parentsUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "parentNode", until );
+	},
+	next: function( elem ) {
+		return jQuery.nth( elem, 2, "nextSibling" );
+	},
+	prev: function( elem ) {
+		return jQuery.nth( elem, 2, "previousSibling" );
+	},
+	nextAll: function( elem ) {
+		return jQuery.dir( elem, "nextSibling" );
+	},
+	prevAll: function( elem ) {
+		return jQuery.dir( elem, "previousSibling" );
+	},
+	nextUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "nextSibling", until );
+	},
+	prevUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "previousSibling", until );
+	},
+	siblings: function( elem ) {
+		return jQuery.sibling( elem.parentNode.firstChild, elem );
+	},
+	children: function( elem ) {
+		return jQuery.sibling( elem.firstChild );
+	},
+	contents: function( elem ) {
+		return jQuery.nodeName( elem, "iframe" ) ?
+			elem.contentDocument || elem.contentWindow.document :
+			jQuery.makeArray( elem.childNodes );
+	}
+}, function( name, fn ) {
+	jQuery.fn[ name ] = function( until, selector ) {
+		var ret = jQuery.map( this, fn, until );
+		
+		if ( !runtil.test( name ) ) {
+			selector = until;
+		}
+
+		if ( selector && typeof selector === "string" ) {
+			ret = jQuery.filter( selector, ret );
+		}
+
+		ret = this.length > 1 ? jQuery.unique( ret ) : ret;
+
+		if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
+			ret = ret.reverse();
+		}
+
+		return this.pushStack( ret, name, slice.call(arguments).join(",") );
+	};
+});
+
+jQuery.extend({
+	filter: function( expr, elems, not ) {
+		if ( not ) {
+			expr = ":not(" + expr + ")";
+		}
+
+		return elems.length === 1 ?
+			jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
+			jQuery.find.matches(expr, elems);
+	},
+	
+	dir: function( elem, dir, until ) {
+		var matched = [],
+			cur = elem[ dir ];
+
+		while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
+			if ( cur.nodeType === 1 ) {
+				matched.push( cur );
+			}
+			cur = cur[dir];
+		}
+		return matched;
+	},
+
+	nth: function( cur, result, dir, elem ) {
+		result = result || 1;
+		var num = 0;
+
+		for ( ; cur; cur = cur[dir] ) {
+			if ( cur.nodeType === 1 && ++num === result ) {
+				break;
+			}
+		}
+
+		return cur;
+	},
+
+	sibling: function( n, elem ) {
+		var r = [];
+
+		for ( ; n; n = n.nextSibling ) {
+			if ( n.nodeType === 1 && n !== elem ) {
+				r.push( n );
+			}
+		}
+
+		return r;
+	}
+});
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, keep ) {
+	if ( jQuery.isFunction( qualifier ) ) {
+		return jQuery.grep(elements, function( elem, i ) {
+			var retVal = !!qualifier.call( elem, i, elem );
+			return retVal === keep;
+		});
+
+	} else if ( qualifier.nodeType ) {
+		return jQuery.grep(elements, function( elem, i ) {
+			return (elem === qualifier) === keep;
+		});
+
+	} else if ( typeof qualifier === "string" ) {
+		var filtered = jQuery.grep(elements, function( elem ) {
+			return elem.nodeType === 1;
+		});
+
+		if ( isSimple.test( qualifier ) ) {
+			return jQuery.filter(qualifier, filtered, !keep);
+		} else {
+			qualifier = jQuery.filter( qualifier, filtered );
+		}
+	}
+
+	return jQuery.grep(elements, function( elem, i ) {
+		return (jQuery.inArray( elem, qualifier ) >= 0) === keep;
+	});
+}
+
+
+
+
+var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
+	rleadingWhitespace = /^\s+/,
+	rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
+	rtagName = /<([\w:]+)/,
+	rtbody = /<tbody/i,
+	rhtml = /<|&#?\w+;/,
+	rnocache = /<(?:script|object|embed|option|style)/i,
+	// checked="checked" or checked (html5)
+	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+	raction = /\=([^="'>\s]+\/)>/g,
+	wrapMap = {
+		option: [ 1, "<select multiple='multiple'>", "</select>" ],
+		legend: [ 1, "<fieldset>", "</fieldset>" ],
+		thead: [ 1, "<table>", "</table>" ],
+		tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+		td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+		col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
+		area: [ 1, "<map>", "</map>" ],
+		_default: [ 0, "", "" ]
+	};
+
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+// IE can't serialize <link> and <script> tags normally
+if ( !jQuery.support.htmlSerialize ) {
+	wrapMap._default = [ 1, "div<div>", "</div>" ];
+}
+
+jQuery.fn.extend({
+	text: function( text ) {
+		if ( jQuery.isFunction(text) ) {
+			return this.each(function(i) {
+				var self = jQuery( this );
+
+				self.text( text.call(this, i, self.text()) );
+			});
+		}
+
+		if ( typeof text !== "object" && text !== undefined ) {
+			return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
+		}
+
+		return jQuery.text( this );
+	},
+
+	wrapAll: function( html ) {
+		if ( jQuery.isFunction( html ) ) {
+			return this.each(function(i) {
+				jQuery(this).wrapAll( html.call(this, i) );
+			});
+		}
+
+		if ( this[0] ) {
+			// The elements to wrap the target around
+			var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
+
+			if ( this[0].parentNode ) {
+				wrap.insertBefore( this[0] );
+			}
+
+			wrap.map(function() {
+				var elem = this;
+
+				while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
+					elem = elem.firstChild;
+				}
+
+				return elem;
+			}).append(this);
+		}
+
+		return this;
+	},
+
+	wrapInner: function( html ) {
+		if ( jQuery.isFunction( html ) ) {
+			return this.each(function(i) {
+				jQuery(this).wrapInner( html.call(this, i) );
+			});
+		}
+
+		return this.each(function() {
+			var self = jQuery( this ),
+				contents = self.contents();
+
+			if ( contents.length ) {
+				contents.wrapAll( html );
+
+			} else {
+				self.append( html );
+			}
+		});
+	},
+
+	wrap: function( html ) {
+		return this.each(function() {
+			jQuery( this ).wrapAll( html );
+		});
+	},
+
+	unwrap: function() {
+		return this.parent().each(function() {
+			if ( !jQuery.nodeName( this, "body" ) ) {
+				jQuery( this ).replaceWith( this.childNodes );
+			}
+		}).end();
+	},
+
+	append: function() {
+		return this.domManip(arguments, true, function( elem ) {
+			if ( this.nodeType === 1 ) {
+				this.appendChild( elem );
+			}
+		});
+	},
+
+	prepend: function() {
+		return this.domManip(arguments, true, function( elem ) {
+			if ( this.nodeType === 1 ) {
+				this.insertBefore( elem, this.firstChild );
+			}
+		});
+	},
+
+	before: function() {
+		if ( this[0] && this[0].parentNode ) {
+			return this.domManip(arguments, false, function( elem ) {
+				this.parentNode.insertBefore( elem, this );
+			});
+		} else if ( arguments.length ) {
+			var set = jQuery(arguments[0]);
+			set.push.apply( set, this.toArray() );
+			return this.pushStack( set, "before", arguments );
+		}
+	},
+
+	after: function() {
+		if ( this[0] && this[0].parentNode ) {
+			return this.domManip(arguments, false, function( elem ) {
+				this.parentNode.insertBefore( elem, this.nextSibling );
+			});
+		} else if ( arguments.length ) {
+			var set = this.pushStack( this, "after", arguments );
+			set.push.apply( set, jQuery(arguments[0]).toArray() );
+			return set;
+		}
+	},
+	
+	// keepData is for internal use only--do not document
+	remove: function( selector, keepData ) {
+		for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
+			if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
+				if ( !keepData && elem.nodeType === 1 ) {
+					jQuery.cleanData( elem.getElementsByTagName("*") );
+					jQuery.cleanData( [ elem ] );
+				}
+
+				if ( elem.parentNode ) {
+					 elem.parentNode.removeChild( elem );
+				}
+			}
+		}
+		
+		return this;
+	},
+
+	empty: function() {
+		for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
+			// Remove element nodes and prevent memory leaks
+			if ( elem.nodeType === 1 ) {
+				jQuery.cleanData( elem.getElementsByTagName("*") );
+			}
+
+			// Remove any remaining nodes
+			while ( elem.firstChild ) {
+				elem.removeChild( elem.firstChild );
+			}
+		}
+		
+		return this;
+	},
+
+	clone: function( events ) {
+		// Do the clone
+		var ret = this.map(function() {
+			if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
+				// IE copies events bound via attachEvent when
+				// using cloneNode. Calling detachEvent on the
+				// clone will also remove the events from the orignal
+				// In order to get around this, we use innerHTML.
+				// Unfortunately, this means some modifications to
+				// attributes in IE that are actually only stored
+				// as properties will not be copied (such as the
+				// the name attribute on an input).
+				var html = this.outerHTML,
+					ownerDocument = this.ownerDocument;
+
+				if ( !html ) {
+					var div = ownerDocument.createElement("div");
+					div.appendChild( this.cloneNode(true) );
+					html = div.innerHTML;
+				}
+
+				return jQuery.clean([html.replace(rinlinejQuery, "")
+					// Handle the case in IE 8 where action=/test/> self-closes a tag
+					.replace(raction, '="$1">')
+					.replace(rleadingWhitespace, "")], ownerDocument)[0];
+			} else {
+				return this.cloneNode(true);
+			}
+		});
+
+		// Copy the events from the original to the clone
+		if ( events === true ) {
+			cloneCopyEvent( this, ret );
+			cloneCopyEvent( this.find("*"), ret.find("*") );
+		}
+
+		// Return the cloned set
+		return ret;
+	},
+
+	html: function( value ) {
+		if ( value === undefined ) {
+			return this[0] && this[0].nodeType === 1 ?
+				this[0].innerHTML.replace(rinlinejQuery, "") :
+				null;
+
+		// See if we can take a shortcut and just use innerHTML
+		} else if ( typeof value === "string" && !rnocache.test( value ) &&
+			(jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
+			!wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
+
+			value = value.replace(rxhtmlTag, "<$1></$2>");
+
+			try {
+				for ( var i = 0, l = this.length; i < l; i++ ) {
+					// Remove element nodes and prevent memory leaks
+					if ( this[i].nodeType === 1 ) {
+						jQuery.cleanData( this[i].getElementsByTagName("*") );
+						this[i].innerHTML = value;
+					}
+				}
+
+			// If using innerHTML throws an exception, use the fallback method
+			} catch(e) {
+				this.empty().append( value );
+			}
+
+		} else if ( jQuery.isFunction( value ) ) {
+			this.each(function(i){
+				var self = jQuery( this );
+
+				self.html( value.call(this, i, self.html()) );
+			});
+
+		} else {
+			this.empty().append( value );
+		}
+
+		return this;
+	},
+
+	replaceWith: function( value ) {
+		if ( this[0] && this[0].parentNode ) {
+			// Make sure that the elements are removed from the DOM before they are inserted
+			// this can help fix replacing a parent with child elements
+			if ( jQuery.isFunction( value ) ) {
+				return this.each(function(i) {
+					var self = jQuery(this), old = self.html();
+					self.replaceWith( value.call( this, i, old ) );
+				});
+			}
+
+			if ( typeof value !== "string" ) {
+				value = jQuery( value ).detach();
+			}
+
+			return this.each(function() {
+				var next = this.nextSibling,
+					parent = this.parentNode;
+
+				jQuery( this ).remove();
+
+				if ( next ) {
+					jQuery(next).before( value );
+				} else {
+					jQuery(parent).append( value );
+				}
+			});
+		} else {
+			return this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value );
+		}
+	},
+
+	detach: function( selector ) {
+		return this.remove( selector, true );
+	},
+
+	domManip: function( args, table, callback ) {
+		var results, first, fragment, parent,
+			value = args[0],
+			scripts = [];
+
+		// We can't cloneNode fragments that contain checked, in WebKit
+		if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
+			return this.each(function() {
+				jQuery(this).domManip( args, table, callback, true );
+			});
+		}
+
+		if ( jQuery.isFunction(value) ) {
+			return this.each(function(i) {
+				var self = jQuery(this);
+				args[0] = value.call(this, i, table ? self.html() : undefined);
+				self.domManip( args, table, callback );
+			});
+		}
+
+		if ( this[0] ) {
+			parent = value && value.parentNode;
+
+			// If we're in a fragment, just use that instead of building a new one
+			if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
+				results = { fragment: parent };
+
+			} else {
+				results = jQuery.buildFragment( args, this, scripts );
+			}
+			
+			fragment = results.fragment;
+			
+			if ( fragment.childNodes.length === 1 ) {
+				first = fragment = fragment.firstChild;
+			} else {
+				first = fragment.firstChild;
+			}
+
+			if ( first ) {
+				table = table && jQuery.nodeName( first, "tr" );
+
+				for ( var i = 0, l = this.length; i < l; i++ ) {
+					callback.call(
+						table ?
+							root(this[i], first) :
+							this[i],
+						i > 0 || results.cacheable || this.length > 1  ?
+							fragment.cloneNode(true) :
+							fragment
+					);
+				}
+			}
+
+			if ( scripts.length ) {
+				jQuery.each( scripts, evalScript );
+			}
+		}
+
+		return this;
+	}
+});
+
+function root( elem, cur ) {
+	return jQuery.nodeName(elem, "table") ?
+		(elem.getElementsByTagName("tbody")[0] ||
+		elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
+		elem;
+}
+
+function cloneCopyEvent(orig, ret) {
+	var i = 0;
+
+	ret.each(function() {
+		if ( this.nodeName !== (orig[i] && orig[i].nodeName) ) {
+			return;
+		}
+
+		var oldData = jQuery.data( orig[i++] ),
+			curData = jQuery.data( this, oldData ),
+			events = oldData && oldData.events;
+
+		if ( events ) {
+			delete curData.handle;
+			curData.events = {};
+
+			for ( var type in events ) {
+				for ( var handler in events[ type ] ) {
+					jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
+				}
+			}
+		}
+	});
+}
+
+jQuery.buildFragment = function( args, nodes, scripts ) {
+	var fragment, cacheable, cacheresults,
+		doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);
+
+	// Only cache "small" (1/2 KB) strings that are associated with the main document
+	// Cloning options loses the selected state, so don't cache them
+	// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
+	// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
+	if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document &&
+		!rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {
+
+		cacheable = true;
+		cacheresults = jQuery.fragments[ args[0] ];
+		if ( cacheresults ) {
+			if ( cacheresults !== 1 ) {
+				fragment = cacheresults;
+			}
+		}
+	}
+
+	if ( !fragment ) {
+		fragment = doc.createDocumentFragment();
+		jQuery.clean( args, doc, fragment, scripts );
+	}
+
+	if ( cacheable ) {
+		jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;
+	}
+
+	return { fragment: fragment, cacheable: cacheable };
+};
+
+jQuery.fragments = {};
+
+jQuery.each({
+	appendTo: "append",
+	prependTo: "prepend",
+	insertBefore: "before",
+	insertAfter: "after",
+	replaceAll: "replaceWith"
+}, function( name, original ) {
+	jQuery.fn[ name ] = function( selector ) {
+		var ret = [],
+			insert = jQuery( selector ),
+			parent = this.length === 1 && this[0].parentNode;
+		
+		if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
+			insert[ original ]( this[0] );
+			return this;
+			
+		} else {
+			for ( var i = 0, l = insert.length; i < l; i++ ) {
+				var elems = (i > 0 ? this.clone(true) : this).get();
+				jQuery( insert[i] )[ original ]( elems );
+				ret = ret.concat( elems );
+			}
+		
+			return this.pushStack( ret, name, insert.selector );
+		}
+	};
+});
+
+jQuery.extend({
+	clean: function( elems, context, fragment, scripts ) {
+		context = context || document;
+
+		// !context.createElement fails in IE with an error but returns typeof 'object'
+		if ( typeof context.createElement === "undefined" ) {
+			context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
+		}
+
+		var ret = [];
+
+		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+			if ( typeof elem === "number" ) {
+				elem += "";
+			}
+
+			if ( !elem ) {
+				continue;
+			}
+
+			// Convert html string into DOM nodes
+			if ( typeof elem === "string" && !rhtml.test( elem ) ) {
+				elem = context.createTextNode( elem );
+
+			} else if ( typeof elem === "string" ) {
+				// Fix "XHTML"-style tags in all browsers
+				elem = elem.replace(rxhtmlTag, "<$1></$2>");
+
+				// Trim whitespace, otherwise indexOf won't work as expected
+				var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(),
+					wrap = wrapMap[ tag ] || wrapMap._default,
+					depth = wrap[0],
+					div = context.createElement("div");
+
+				// Go to html and back, then peel off extra wrappers
+				div.innerHTML = wrap[1] + elem + wrap[2];
+
+				// Move to the right depth
+				while ( depth-- ) {
+					div = div.lastChild;
+				}
+
+				// Remove IE's autoinserted <tbody> from table fragments
+				if ( !jQuery.support.tbody ) {
+
+					// String was a <table>, *may* have spurious <tbody>
+					var hasBody = rtbody.test(elem),
+						tbody = tag === "table" && !hasBody ?
+							div.firstChild && div.firstChild.childNodes :
+
+							// String was a bare <thead> or <tfoot>
+							wrap[1] === "<table>" && !hasBody ?
+								div.childNodes :
+								[];
+
+					for ( var j = tbody.length - 1; j >= 0 ; --j ) {
+						if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
+							tbody[ j ].parentNode.removeChild( tbody[ j ] );
+						}
+					}
+
+				}
+
+				// IE completely kills leading whitespace when innerHTML is used
+				if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
+					div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
+				}
+
+				elem = div.childNodes;
+			}
+
+			if ( elem.nodeType ) {
+				ret.push( elem );
+			} else {
+				ret = jQuery.merge( ret, elem );
+			}
+		}
+
+		if ( fragment ) {
+			for ( i = 0; ret[i]; i++ ) {
+				if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
+					scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
+				
+				} else {
+					if ( ret[i].nodeType === 1 ) {
+						ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
+					}
+					fragment.appendChild( ret[i] );
+				}
+			}
+		}
+
+		return ret;
+	},
+	
+	cleanData: function( elems ) {
+		var data, id, cache = jQuery.cache,
+			special = jQuery.event.special,
+			deleteExpando = jQuery.support.deleteExpando;
+		
+		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+			if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
+				continue;
+			}
+
+			id = elem[ jQuery.expando ];
+			
+			if ( id ) {
+				data = cache[ id ];
+				
+				if ( data && data.events ) {
+					for ( var type in data.events ) {
+						if ( special[ type ] ) {
+							jQuery.event.remove( elem, type );
+
+						} else {
+							jQuery.removeEvent( elem, type, data.handle );
+						}
+					}
+				}
+				
+				if ( deleteExpando ) {
+					delete elem[ jQuery.expando ];
+
+				} else if ( elem.removeAttribute ) {
+					elem.removeAttribute( jQuery.expando );
+				}
+				
+				delete cache[ id ];
+			}
+		}
+	}
+});
+
+function evalScript( i, elem ) {
+	if ( elem.src ) {
+		jQuery.ajax({
+			url: elem.src,
+			async: false,
+			dataType: "script"
+		});
+	} else {
+		jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
+	}
+
+	if ( elem.parentNode ) {
+		elem.parentNode.removeChild( elem );
+	}
+}
+
+
+
+
+var ralpha = /alpha\([^)]*\)/i,
+	ropacity = /opacity=([^)]*)/,
+	rdashAlpha = /-([a-z])/ig,
+	rupper = /([A-Z])/g,
+	rnumpx = /^-?\d+(?:px)?$/i,
+	rnum = /^-?\d/,
+
+	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+	cssWidth = [ "Left", "Right" ],
+	cssHeight = [ "Top", "Bottom" ],
+	curCSS,
+
+	getComputedStyle,
+	currentStyle,
+
+	fcamelCase = function( all, letter ) {
+		return letter.toUpperCase();
+	};
+
+jQuery.fn.css = function( name, value ) {
+	// Setting 'undefined' is a no-op
+	if ( arguments.length === 2 && value === undefined ) {
+		return this;
+	}
+
+	return jQuery.access( this, name, value, true, function( elem, name, value ) {
+		return value !== undefined ?
+			jQuery.style( elem, name, value ) :
+			jQuery.css( elem, name );
+	});
+};
+
+jQuery.extend({
+	// Add in style property hooks for overriding the default
+	// behavior of getting and setting a style property
+	cssHooks: {
+		opacity: {
+			get: function( elem, computed ) {
+				if ( computed ) {
+					// We should always get a number back from opacity
+					var ret = curCSS( elem, "opacity", "opacity" );
+					return ret === "" ? "1" : ret;
+
+				} else {
+					return elem.style.opacity;
+				}
+			}
+		}
+	},
+
+	// Exclude the following css properties to add px
+	cssNumber: {
+		"zIndex": true,
+		"fontWeight": true,
+		"opacity": true,
+		"zoom": true,
+		"lineHeight": true
+	},
+
+	// Add in properties whose names you wish to fix before
+	// setting or getting the value
+	cssProps: {
+		// normalize float css property
+		"float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
+	},
+
+	// Get and set the style property on a DOM Node
+	style: function( elem, name, value, extra ) {
+		// Don't set styles on text and comment nodes
+		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+			return;
+		}
+
+		// Make sure that we're working with the right name
+		var ret, origName = jQuery.camelCase( name ),
+			style = elem.style, hooks = jQuery.cssHooks[ origName ];
+
+		name = jQuery.cssProps[ origName ] || origName;
+
+		// Check if we're setting a value
+		if ( value !== undefined ) {
+			// Make sure that NaN and null values aren't set. See: #7116
+			if ( typeof value === "number" && isNaN( value ) || value == null ) {
+				return;
+			}
+
+			// If a number was passed in, add 'px' to the (except for certain CSS properties)
+			if ( typeof value === "number" && !jQuery.cssNumber[ origName ] ) {
+				value += "px";
+			}
+
+			// If a hook was provided, use that value, otherwise just set the specified value
+			if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {
+				// Wrapped to prevent IE from throwing errors when 'invalid' values are provided
+				// Fixes bug #5509
+				try {
+					style[ name ] = value;
+				} catch(e) {}
+			}
+
+		} else {
+			// If a hook was provided get the non-computed value from there
+			if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
+				return ret;
+			}
+
+			// Otherwise just get the value from the style object
+			return style[ name ];
+		}
+	},
+
+	css: function( elem, name, extra ) {
+		// Make sure that we're working with the right name
+		var ret, origName = jQuery.camelCase( name ),
+			hooks = jQuery.cssHooks[ origName ];
+
+		name = jQuery.cssProps[ origName ] || origName;
+
+		// If a hook was provided get the computed value from there
+		if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {
+			return ret;
+
+		// Otherwise, if a way to get the computed value exists, use that
+		} else if ( curCSS ) {
+			return curCSS( elem, name, origName );
+		}
+	},
+
+	// A method for quickly swapping in/out CSS properties to get correct calculations
+	swap: function( elem, options, callback ) {
+		var old = {};
+
+		// Remember the old values, and insert the new ones
+		for ( var name in options ) {
+			old[ name ] = elem.style[ name ];
+			elem.style[ name ] = options[ name ];
+		}
+
+		callback.call( elem );
+
+		// Revert the old values
+		for ( name in options ) {
+			elem.style[ name ] = old[ name ];
+		}
+	},
+
+	camelCase: function( string ) {
+		return string.replace( rdashAlpha, fcamelCase );
+	}
+});
+
+// DEPRECATED, Use jQuery.css() instead
+jQuery.curCSS = jQuery.css;
+
+jQuery.each(["height", "width"], function( i, name ) {
+	jQuery.cssHooks[ name ] = {
+		get: function( elem, computed, extra ) {
+			var val;
+
+			if ( computed ) {
+				if ( elem.offsetWidth !== 0 ) {
+					val = getWH( elem, name, extra );
+
+				} else {
+					jQuery.swap( elem, cssShow, function() {
+						val = getWH( elem, name, extra );
+					});
+				}
+
+				if ( val <= 0 ) {
+					val = curCSS( elem, name, name );
+
+					if ( val === "0px" && currentStyle ) {
+						val = currentStyle( elem, name, name );
+					}
+
+					if ( val != null ) {
+						// Should return "auto" instead of 0, use 0 for
+						// temporary backwards-compat
+						return val === "" || val === "auto" ? "0px" : val;
+					}
+				}
+
+				if ( val < 0 || val == null ) {
+					val = elem.style[ name ];
+
+					// Should return "auto" instead of 0, use 0 for
+					// temporary backwards-compat
+					return val === "" || val === "auto" ? "0px" : val;
+				}
+
+				return typeof val === "string" ? val : val + "px";
+			}
+		},
+
+		set: function( elem, value ) {
+			if ( rnumpx.test( value ) ) {
+				// ignore negative width and height values #1599
+				value = parseFloat(value);
+
+				if ( value >= 0 ) {
+					return value + "px";
+				}
+
+			} else {
+				return value;
+			}
+		}
+	};
+});
+
+if ( !jQuery.support.opacity ) {
+	jQuery.cssHooks.opacity = {
+		get: function( elem, computed ) {
+			// IE uses filters for opacity
+			return ropacity.test((computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "") ?
+				(parseFloat(RegExp.$1) / 100) + "" :
+				computed ? "1" : "";
+		},
+
+		set: function( elem, value ) {
+			var style = elem.style;
+
+			// IE has trouble with opacity if it does not have layout
+			// Force it by setting the zoom level
+			style.zoom = 1;
+
+			// Set the alpha filter to set the opacity
+			var opacity = jQuery.isNaN(value) ?
+				"" :
+				"alpha(opacity=" + value * 100 + ")",
+				filter = style.filter || "";
+
+			style.filter = ralpha.test(filter) ?
+				filter.replace(ralpha, opacity) :
+				style.filter + ' ' + opacity;
+		}
+	};
+}
+
+if ( document.defaultView && document.defaultView.getComputedStyle ) {
+	getComputedStyle = function( elem, newName, name ) {
+		var ret, defaultView, computedStyle;
+
+		name = name.replace( rupper, "-$1" ).toLowerCase();
+
+		if ( !(defaultView = elem.ownerDocument.defaultView) ) {
+			return undefined;
+		}
+
+		if ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) {
+			ret = computedStyle.getPropertyValue( name );
+			if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
+				ret = jQuery.style( elem, name );
+			}
+		}
+
+		return ret;
+	};
+}
+
+if ( document.documentElement.currentStyle ) {
+	currentStyle = function( elem, name ) {
+		var left, rsLeft,
+			ret = elem.currentStyle && elem.currentStyle[ name ],
+			style = elem.style;
+
+		// From the awesome hack by Dean Edwards
+		// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+		// If we're not dealing with a regular pixel number
+		// but a number that has a weird ending, we need to convert it to pixels
+		if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
+			// Remember the original values
+			left = style.left;
+			rsLeft = elem.runtimeStyle.left;
+
+			// Put in the new values to get a computed value out
+			elem.runtimeStyle.left = elem.currentStyle.left;
+			style.left = name === "fontSize" ? "1em" : (ret || 0);
+			ret = style.pixelLeft + "px";
+
+			// Revert the changed values
+			style.left = left;
+			elem.runtimeStyle.left = rsLeft;
+		}
+
+		return ret === "" ? "auto" : ret;
+	};
+}
+
+curCSS = getComputedStyle || currentStyle;
+
+function getWH( elem, name, extra ) {
+	var which = name === "width" ? cssWidth : cssHeight,
+		val = name === "width" ? elem.offsetWidth : elem.offsetHeight;
+
+	if ( extra === "border" ) {
+		return val;
+	}
+
+	jQuery.each( which, function() {
+		if ( !extra ) {
+			val -= parseFloat(jQuery.css( elem, "padding" + this )) || 0;
+		}
+
+		if ( extra === "margin" ) {
+			val += parseFloat(jQuery.css( elem, "margin" + this )) || 0;
+
+		} else {
+			val -= parseFloat(jQuery.css( elem, "border" + this + "Width" )) || 0;
+		}
+	});
+
+	return val;
+}
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+	jQuery.expr.filters.hidden = function( elem ) {
+		var width = elem.offsetWidth,
+			height = elem.offsetHeight;
+
+		return (width === 0 && height === 0) || (!jQuery.support.reliableHiddenOffsets && (elem.style.display || jQuery.css( elem, "display" )) === "none");
+	};
+
+	jQuery.expr.filters.visible = function( elem ) {
+		return !jQuery.expr.filters.hidden( elem );
+	};
+}
+
+
+
+
+var jsc = jQuery.now(),
+	rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
+	rselectTextarea = /^(?:select|textarea)/i,
+	rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
+	rnoContent = /^(?:GET|HEAD)$/,
+	rbracket = /\[\]$/,
+	jsre = /\=\?(&|$)/,
+	rquery = /\?/,
+	rts = /([?&])_=[^&]*/,
+	rurl = /^(\w+:)?\/\/([^\/?#]+)/,
+	r20 = /%20/g,
+	rhash = /#.*$/,
+
+	// Keep a copy of the old load method
+	_load = jQuery.fn.load;
+
+jQuery.fn.extend({
+	load: function( url, params, callback ) {
+		if ( typeof url !== "string" && _load ) {
+			return _load.apply( this, arguments );
+
+		// Don't do a request if no elements are being requested
+		} else if ( !this.length ) {
+			return this;
+		}
+
+		var off = url.indexOf(" ");
+		if ( off >= 0 ) {
+			var selector = url.slice(off, url.length);
+			url = url.slice(0, off);
+		}
+
+		// Default to a GET request
+		var type = "GET";
+
+		// If the second parameter was provided
+		if ( params ) {
+			// If it's a function
+			if ( jQuery.isFunction( params ) ) {
+				// We assume that it's the callback
+				callback = params;
+				params = null;
+
+			// Otherwise, build a param string
+			} else if ( typeof params === "object" ) {
+				params = jQuery.param( params, jQuery.ajaxSettings.traditional );
+				type = "POST";
+			}
+		}
+
+		var self = this;
+
+		// Request the remote document
+		jQuery.ajax({
+			url: url,
+			type: type,
+			dataType: "html",
+			data: params,
+			complete: function( res, status ) {
+				// If successful, inject the HTML into all the matched elements
+				if ( status === "success" || status === "notmodified" ) {
+					// See if a selector was specified
+					self.html( selector ?
+						// Create a dummy div to hold the results
+						jQuery("<div>")
+							// inject the contents of the document in, removing the scripts
+							// to avoid any 'Permission Denied' errors in IE
+							.append(res.responseText.replace(rscript, ""))
+
+							// Locate the specified elements
+							.find(selector) :
+
+						// If not, just inject the full result
+						res.responseText );
+				}
+
+				if ( callback ) {
+					self.each( callback, [res.responseText, status, res] );
+				}
+			}
+		});
+
+		return this;
+	},
+
+	serialize: function() {
+		return jQuery.param(this.serializeArray());
+	},
+
+	serializeArray: function() {
+		return this.map(function() {
+			return this.elements ? jQuery.makeArray(this.elements) : this;
+		})
+		.filter(function() {
+			return this.name && !this.disabled &&
+				(this.checked || rselectTextarea.test(this.nodeName) ||
+					rinput.test(this.type));
+		})
+		.map(function( i, elem ) {
+			var val = jQuery(this).val();
+
+			return val == null ?
+				null :
+				jQuery.isArray(val) ?
+					jQuery.map( val, function( val, i ) {
+						return { name: elem.name, value: val };
+					}) :
+					{ name: elem.name, value: val };
+		}).get();
+	}
+});
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), function( i, o ) {
+	jQuery.fn[o] = function( f ) {
+		return this.bind(o, f);
+	};
+});
+
+jQuery.extend({
+	get: function( url, data, callback, type ) {
+		// shift arguments if data argument was omited
+		if ( jQuery.isFunction( data ) ) {
+			type = type || callback;
+			callback = data;
+			data = null;
+		}
+
+		return jQuery.ajax({
+			type: "GET",
+			url: url,
+			data: data,
+			success: callback,
+			dataType: type
+		});
+	},
+
+	getScript: function( url, callback ) {
+		return jQuery.get(url, null, callback, "script");
+	},
+
+	getJSON: function( url, data, callback ) {
+		return jQuery.get(url, data, callback, "json");
+	},
+
+	post: function( url, data, callback, type ) {
+		// shift arguments if data argument was omited
+		if ( jQuery.isFunction( data ) ) {
+			type = type || callback;
+			callback = data;
+			data = {};
+		}
+
+		return jQuery.ajax({
+			type: "POST",
+			url: url,
+			data: data,
+			success: callback,
+			dataType: type
+		});
+	},
+
+	ajaxSetup: function( settings ) {
+		jQuery.extend( jQuery.ajaxSettings, settings );
+	},
+
+	ajaxSettings: {
+		url: location.href,
+		global: true,
+		type: "GET",
+		contentType: "application/x-www-form-urlencoded",
+		processData: true,
+		async: true,
+		/*
+		timeout: 0,
+		data: null,
+		username: null,
+		password: null,
+		traditional: false,
+		*/
+		// This function can be overriden by calling jQuery.ajaxSetup
+		xhr: function() {
+			return new window.XMLHttpRequest();
+		},
+		accepts: {
+			xml: "application/xml, text/xml",
+			html: "text/html",
+			script: "text/javascript, application/javascript",
+			json: "application/json, text/javascript",
+			text: "text/plain",
+			_default: "*/*"
+		}
+	},
+
+	ajax: function( origSettings ) {
+		var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings),
+			jsonp, status, data, type = s.type.toUpperCase(), noContent = rnoContent.test(type);
+
+		s.url = s.url.replace( rhash, "" );
+
+		// Use original (not extended) context object if it was provided
+		s.context = origSettings && origSettings.context != null ? origSettings.context : s;
+
+		// convert data if not already a string
+		if ( s.data && s.processData && typeof s.data !== "string" ) {
+			s.data = jQuery.param( s.data, s.traditional );
+		}
+
+		// Handle JSONP Parameter Callbacks
+		if ( s.dataType === "jsonp" ) {
+			if ( type === "GET" ) {
+				if ( !jsre.test( s.url ) ) {
+					s.url += (rquery.test( s.url ) ? "&" : "?") + (s.jsonp || "callback") + "=?";
+				}
+			} else if ( !s.data || !jsre.test(s.data) ) {
+				s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
+			}
+			s.dataType = "json";
+		}
+
+		// Build temporary JSONP function
+		if ( s.dataType === "json" && (s.data && jsre.test(s.data) || jsre.test(s.url)) ) {
+			jsonp = s.jsonpCallback || ("jsonp" + jsc++);
+
+			// Replace the =? sequence both in the query string and the data
+			if ( s.data ) {
+				s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
+			}
+
+			s.url = s.url.replace(jsre, "=" + jsonp + "$1");
+
+			// We need to make sure
+			// that a JSONP style response is executed properly
+			s.dataType = "script";
+
+			// Handle JSONP-style loading
+			var customJsonp = window[ jsonp ];
+
+			window[ jsonp ] = function( tmp ) {
+				if ( jQuery.isFunction( customJsonp ) ) {
+					customJsonp( tmp );
+
+				} else {
+					// Garbage collect
+					window[ jsonp ] = undefined;
+
+					try {
+						delete window[ jsonp ];
+					} catch( jsonpError ) {}
+				}
+
+				data = tmp;
+				jQuery.handleSuccess( s, xhr, status, data );
+				jQuery.handleComplete( s, xhr, status, data );
+				
+				if ( head ) {
+					head.removeChild( script );
+				}
+			};
+		}
+
+		if ( s.dataType === "script" && s.cache === null ) {
+			s.cache = false;
+		}
+
+		if ( s.cache === false && noContent ) {
+			var ts = jQuery.now();
+
+			// try replacing _= if it is there
+			var ret = s.url.replace(rts, "$1_=" + ts);
+
+			// if nothing was replaced, add timestamp to the end
+			s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "");
+		}
+
+		// If data is available, append data to url for GET/HEAD requests
+		if ( s.data && noContent ) {
+			s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
+		}
+
+		// Watch for a new set of requests
+		if ( s.global && jQuery.active++ === 0 ) {
+			jQuery.event.trigger( "ajaxStart" );
+		}
+
+		// Matches an absolute URL, and saves the domain
+		var parts = rurl.exec( s.url ),
+			remote = parts && (parts[1] && parts[1].toLowerCase() !== location.protocol || parts[2].toLowerCase() !== location.host);
+
+		// If we're requesting a remote document
+		// and trying to load JSON or Script with a GET
+		if ( s.dataType === "script" && type === "GET" && remote ) {
+			var head = document.getElementsByTagName("head")[0] || document.documentElement;
+			var script = document.createElement("script");
+			if ( s.scriptCharset ) {
+				script.charset = s.scriptCharset;
+			}
+			script.src = s.url;
+
+			// Handle Script loading
+			if ( !jsonp ) {
+				var done = false;
+
+				// Attach handlers for all browsers
+				script.onload = script.onreadystatechange = function() {
+					if ( !done && (!this.readyState ||
+							this.readyState === "loaded" || this.readyState === "complete") ) {
+						done = true;
+						jQuery.handleSuccess( s, xhr, status, data );
+						jQuery.handleComplete( s, xhr, status, data );
+
+						// Handle memory leak in IE
+						script.onload = script.onreadystatechange = null;
+						if ( head && script.parentNode ) {
+							head.removeChild( script );
+						}
+					}
+				};
+			}
+
+			// Use insertBefore instead of appendChild  to circumvent an IE6 bug.
+			// This arises when a base node is used (#2709 and #4378).
+			head.insertBefore( script, head.firstChild );
+
+			// We handle everything using the script element injection
+			return undefined;
+		}
+
+		var requestDone = false;
+
+		// Create the request object
+		var xhr = s.xhr();
+
+		if ( !xhr ) {
+			return;
+		}
+
+		// Open the socket
+		// Passing null username, generates a login popup on Opera (#2865)
+		if ( s.username ) {
+			xhr.open(type, s.url, s.async, s.username, s.password);
+		} else {
+			xhr.open(type, s.url, s.async);
+		}
+
+		// Need an extra try/catch for cross domain requests in Firefox 3
+		try {
+			// Set content-type if data specified and content-body is valid for this type
+			if ( (s.data != null && !noContent) || (origSettings && origSettings.contentType) ) {
+				xhr.setRequestHeader("Content-Type", s.contentType);
+			}
+
+			// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+			if ( s.ifModified ) {
+				if ( jQuery.lastModified[s.url] ) {
+					xhr.setRequestHeader("If-Modified-Since", jQuery.lastModified[s.url]);
+				}
+
+				if ( jQuery.etag[s.url] ) {
+					xhr.setRequestHeader("If-None-Match", jQuery.etag[s.url]);
+				}
+			}
+
+			// Set header so the called script knows that it's an XMLHttpRequest
+			// Only send the header if it's not a remote XHR
+			if ( !remote ) {
+				xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+			}
+
+			// Set the Accepts header for the server, depending on the dataType
+			xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
+				s.accepts[ s.dataType ] + ", */*; q=0.01" :
+				s.accepts._default );
+		} catch( headerError ) {}
+
+		// Allow custom headers/mimetypes and early abort
+		if ( s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false ) {
+			// Handle the global AJAX counter
+			if ( s.global && jQuery.active-- === 1 ) {
+				jQuery.event.trigger( "ajaxStop" );
+			}
+
+			// close opended socket
+			xhr.abort();
+			return false;
+		}
+
+		if ( s.global ) {
+			jQuery.triggerGlobal( s, "ajaxSend", [xhr, s] );
+		}
+
+		// Wait for a response to come back
+		var onreadystatechange = xhr.onreadystatechange = function( isTimeout ) {
+			// The request was aborted
+			if ( !xhr || xhr.readyState === 0 || isTimeout === "abort" ) {
+				// Opera doesn't call onreadystatechange before this point
+				// so we simulate the call
+				if ( !requestDone ) {
+					jQuery.handleComplete( s, xhr, status, data );
+				}
+
+				requestDone = true;
+				if ( xhr ) {
+					xhr.onreadystatechange = jQuery.noop;
+				}
+
+			// The transfer is complete and the data is available, or the request timed out
+			} else if ( !requestDone && xhr && (xhr.readyState === 4 || isTimeout === "timeout") ) {
+				requestDone = true;
+				xhr.onreadystatechange = jQuery.noop;
+
+				status = isTimeout === "timeout" ?
+					"timeout" :
+					!jQuery.httpSuccess( xhr ) ?
+						"error" :
+						s.ifModified && jQuery.httpNotModified( xhr, s.url ) ?
+							"notmodified" :
+							"success";
+
+				var errMsg;
+
+				if ( status === "success" ) {
+					// Watch for, and catch, XML document parse errors
+					try {
+						// process the data (runs the xml through httpData regardless of callback)
+						data = jQuery.httpData( xhr, s.dataType, s );
+					} catch( parserError ) {
+						status = "parsererror";
+						errMsg = parserError;
+					}
+				}
+
+				// Make sure that the request was successful or notmodified
+				if ( status === "success" || status === "notmodified" ) {
+					// JSONP handles its own success callback
+					if ( !jsonp ) {
+						jQuery.handleSuccess( s, xhr, status, data );
+					}
+				} else {
+					jQuery.handleError( s, xhr, status, errMsg );
+				}
+
+				// Fire the complete handlers
+				if ( !jsonp ) {
+					jQuery.handleComplete( s, xhr, status, data );
+				}
+
+				if ( isTimeout === "timeout" ) {
+					xhr.abort();
+				}
+
+				// Stop memory leaks
+				if ( s.async ) {
+					xhr = null;
+				}
+			}
+		};
+
+		// Override the abort handler, if we can (IE 6 doesn't allow it, but that's OK)
+		// Opera doesn't fire onreadystatechange at all on abort
+		try {
+			var oldAbort = xhr.abort;
+			xhr.abort = function() {
+				if ( xhr ) {
+					// oldAbort has no call property in IE7 so
+					// just do it this way, which works in all
+					// browsers
+					Function.prototype.call.call( oldAbort, xhr );
+				}
+
+				onreadystatechange( "abort" );
+			};
+		} catch( abortError ) {}
+
+		// Timeout checker
+		if ( s.async && s.timeout > 0 ) {
+			setTimeout(function() {
+				// Check to see if the request is still happening
+				if ( xhr && !requestDone ) {
+					onreadystatechange( "timeout" );
+				}
+			}, s.timeout);
+		}
+
+		// Send the data
+		try {
+			xhr.send( noContent || s.data == null ? null : s.data );
+
+		} catch( sendError ) {
+			jQuery.handleError( s, xhr, null, sendError );
+
+			// Fire the complete handlers
+			jQuery.handleComplete( s, xhr, status, data );
+		}
+
+		// firefox 1.5 doesn't fire statechange for sync requests
+		if ( !s.async ) {
+			onreadystatechange();
+		}
+
+		// return XMLHttpRequest to allow aborting the request etc.
+		return xhr;
+	},
+
+	// Serialize an array of form elements or a set of
+	// key/values into a query string
+	param: function( a, traditional ) {
+		var s = [],
+			add = function( key, value ) {
+				// If value is a function, invoke it and return its value
+				value = jQuery.isFunction(value) ? value() : value;
+				s[ s.length ] = encodeURIComponent(key) + "=" + encodeURIComponent(value);
+			};
+		
+		// Set traditional to true for jQuery <= 1.3.2 behavior.
+		if ( traditional === undefined ) {
+			traditional = jQuery.ajaxSettings.traditional;
+		}
+		
+		// If an array was passed in, assume that it is an array of form elements.
+		if ( jQuery.isArray(a) || a.jquery ) {
+			// Serialize the form elements
+			jQuery.each( a, function() {
+				add( this.name, this.value );
+			});
+			
+		} else {
+			// If traditional, encode the "old" way (the way 1.3.2 or older
+			// did it), otherwise encode params recursively.
+			for ( var prefix in a ) {
+				buildParams( prefix, a[prefix], traditional, add );
+			}
+		}
+
+		// Return the resulting serialization
+		return s.join("&").replace(r20, "+");
+	}
+});
+
+function buildParams( prefix, obj, traditional, add ) {
+	if ( jQuery.isArray(obj) && obj.length ) {
+		// Serialize array item.
+		jQuery.each( obj, function( i, v ) {
+			if ( traditional || rbracket.test( prefix ) ) {
+				// Treat each array item as a scalar.
+				add( prefix, v );
+
+			} else {
+				// If array item is non-scalar (array or object), encode its
+				// numeric index to resolve deserialization ambiguity issues.
+				// Note that rack (as of 1.0.0) can't currently deserialize
+				// nested arrays properly, and attempting to do so may cause
+				// a server error. Possible fixes are to modify rack's
+				// deserialization algorithm or to provide an option or flag
+				// to force array serialization to be shallow.
+				buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add );
+			}
+		});
+			
+	} else if ( !traditional && obj != null && typeof obj === "object" ) {
+		if ( jQuery.isEmptyObject( obj ) ) {
+			add( prefix, "" );
+
+		// Serialize object item.
+		} else {
+			jQuery.each( obj, function( k, v ) {
+				buildParams( prefix + "[" + k + "]", v, traditional, add );
+			});
+		}
+					
+	} else {
+		// Serialize scalar item.
+		add( prefix, obj );
+	}
+}
+
+// This is still on the jQuery object... for now
+// Want to move this to jQuery.ajax some day
+jQuery.extend({
+
+	// Counter for holding the number of active queries
+	active: 0,
+
+	// Last-Modified header cache for next request
+	lastModified: {},
+	etag: {},
+
+	handleError: function( s, xhr, status, e ) {
+		// If a local callback was specified, fire it
+		if ( s.error ) {
+			s.error.call( s.context, xhr, status, e );
+		}
+
+		// Fire the global callback
+		if ( s.global ) {
+			jQuery.triggerGlobal( s, "ajaxError", [xhr, s, e] );
+		}
+	},
+
+	handleSuccess: function( s, xhr, status, data ) {
+		// If a local callback was specified, fire it and pass it the data
+		if ( s.success ) {
+			s.success.call( s.context, data, status, xhr );
+		}
+
+		// Fire the global callback
+		if ( s.global ) {
+			jQuery.triggerGlobal( s, "ajaxSuccess", [xhr, s] );
+		}
+	},
+
+	handleComplete: function( s, xhr, status ) {
+		// Process result
+		if ( s.complete ) {
+			s.complete.call( s.context, xhr, status );
+		}
+
+		// The request was completed
+		if ( s.global ) {
+			jQuery.triggerGlobal( s, "ajaxComplete", [xhr, s] );
+		}
+
+		// Handle the global AJAX counter
+		if ( s.global && jQuery.active-- === 1 ) {
+			jQuery.event.trigger( "ajaxStop" );
+		}
+	},
+		
+	triggerGlobal: function( s, type, args ) {
+		(s.context && s.context.url == null ? jQuery(s.context) : jQuery.event).trigger(type, args);
+	},
+
+	// Determines if an XMLHttpRequest was successful or not
+	httpSuccess: function( xhr ) {
+		try {
+			// IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
+			return !xhr.status && location.protocol === "file:" ||
+				xhr.status >= 200 && xhr.status < 300 ||
+				xhr.status === 304 || xhr.status === 1223;
+		} catch(e) {}
+
+		return false;
+	},
+
+	// Determines if an XMLHttpRequest returns NotModified
+	httpNotModified: function( xhr, url ) {
+		var lastModified = xhr.getResponseHeader("Last-Modified"),
+			etag = xhr.getResponseHeader("Etag");
+
+		if ( lastModified ) {
+			jQuery.lastModified[url] = lastModified;
+		}
+
+		if ( etag ) {
+			jQuery.etag[url] = etag;
+		}
+
+		return xhr.status === 304;
+	},
+
+	httpData: function( xhr, type, s ) {
+		var ct = xhr.getResponseHeader("content-type") || "",
+			xml = type === "xml" || !type && ct.indexOf("xml") >= 0,
+			data = xml ? xhr.responseXML : xhr.responseText;
+
+		if ( xml && data.documentElement.nodeName === "parsererror" ) {
+			jQuery.error( "parsererror" );
+		}
+
+		// Allow a pre-filtering function to sanitize the response
+		// s is checked to keep backwards compatibility
+		if ( s && s.dataFilter ) {
+			data = s.dataFilter( data, type );
+		}
+
+		// The filter can actually parse the response
+		if ( typeof data === "string" ) {
+			// Get the JavaScript object, if JSON is used.
+			if ( type === "json" || !type && ct.indexOf("json") >= 0 ) {
+				data = jQuery.parseJSON( data );
+
+			// If the type is "script", eval it in global context
+			} else if ( type === "script" || !type && ct.indexOf("javascript") >= 0 ) {
+				jQuery.globalEval( data );
+			}
+		}
+
+		return data;
+	}
+
+});
+
+/*
+ * Create the request object; Microsoft failed to properly
+ * implement the XMLHttpRequest in IE7 (can't request local files),
+ * so we use the ActiveXObject when it is available
+ * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
+ * we need a fallback.
+ */
+if ( window.ActiveXObject ) {
+	jQuery.ajaxSettings.xhr = function() {
+		if ( window.location.protocol !== "file:" ) {
+			try {
+				return new window.XMLHttpRequest();
+			} catch(xhrError) {}
+		}
+
+		try {
+			return new window.ActiveXObject("Microsoft.XMLHTTP");
+		} catch(activeError) {}
+	};
+}
+
+// Does this browser support XHR requests?
+jQuery.support.ajax = !!jQuery.ajaxSettings.xhr();
+
+
+
+
+var elemdisplay = {},
+	rfxtypes = /^(?:toggle|show|hide)$/,
+	rfxnum = /^([+\-]=)?([\d+.\-]+)(.*)$/,
+	timerId,
+	fxAttrs = [
+		// height animations
+		[ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
+		// width animations
+		[ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
+		// opacity animations
+		[ "opacity" ]
+	];
+
+jQuery.fn.extend({
+	show: function( speed, easing, callback ) {
+		var elem, display;
+
+		if ( speed || speed === 0 ) {
+			return this.animate( genFx("show", 3), speed, easing, callback);
+
+		} else {
+			for ( var i = 0, j = this.length; i < j; i++ ) {
+				elem = this[i];
+				display = elem.style.display;
+
+				// Reset the inline display of this element to learn if it is
+				// being hidden by cascaded rules or not
+				if ( !jQuery.data(elem, "olddisplay") && display === "none" ) {
+					display = elem.style.display = "";
+				}
+
+				// Set elements which have been overridden with display: none
+				// in a stylesheet to whatever the default browser style is
+				// for such an element
+				if ( display === "" && jQuery.css( elem, "display" ) === "none" ) {
+					jQuery.data(elem, "olddisplay", defaultDisplay(elem.nodeName));
+				}
+			}
+
+			// Set the display of most of the elements in a second loop
+			// to avoid the constant reflow
+			for ( i = 0; i < j; i++ ) {
+				elem = this[i];
+				display = elem.style.display;
+
+				if ( display === "" || display === "none" ) {
+					elem.style.display = jQuery.data(elem, "olddisplay") || "";
+				}
+			}
+
+			return this;
+		}
+	},
+
+	hide: function( speed, easing, callback ) {
+		if ( speed || speed === 0 ) {
+			return this.animate( genFx("hide", 3), speed, easing, callback);
+
+		} else {
+			for ( var i = 0, j = this.length; i < j; i++ ) {
+				var display = jQuery.css( this[i], "display" );
+
+				if ( display !== "none" ) {
+					jQuery.data( this[i], "olddisplay", display );
+				}
+			}
+
+			// Set the display of the elements in a second loop
+			// to avoid the constant reflow
+			for ( i = 0; i < j; i++ ) {
+				this[i].style.display = "none";
+			}
+
+			return this;
+		}
+	},
+
+	// Save the old toggle function
+	_toggle: jQuery.fn.toggle,
+
+	toggle: function( fn, fn2, callback ) {
+		var bool = typeof fn === "boolean";
+
+		if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
+			this._toggle.apply( this, arguments );
+
+		} else if ( fn == null || bool ) {
+			this.each(function() {
+				var state = bool ? fn : jQuery(this).is(":hidden");
+				jQuery(this)[ state ? "show" : "hide" ]();
+			});
+
+		} else {
+			this.animate(genFx("toggle", 3), fn, fn2, callback);
+		}
+
+		return this;
+	},
+
+	fadeTo: function( speed, to, easing, callback ) {
+		return this.filter(":hidden").css("opacity", 0).show().end()
+					.animate({opacity: to}, speed, easing, callback);
+	},
+
+	animate: function( prop, speed, easing, callback ) {
+		var optall = jQuery.speed(speed, easing, callback);
+
+		if ( jQuery.isEmptyObject( prop ) ) {
+			return this.each( optall.complete );
+		}
+
+		return this[ optall.queue === false ? "each" : "queue" ](function() {
+			// XXX 'this' does not always have a nodeName when running the
+			// test suite
+
+			var opt = jQuery.extend({}, optall), p,
+				isElement = this.nodeType === 1,
+				hidden = isElement && jQuery(this).is(":hidden"),
+				self = this;
+
+			for ( p in prop ) {
+				var name = jQuery.camelCase( p );
+
+				if ( p !== name ) {
+					prop[ name ] = prop[ p ];
+					delete prop[ p ];
+					p = name;
+				}
+
+				if ( prop[p] === "hide" && hidden || prop[p] === "show" && !hidden ) {
+					return opt.complete.call(this);
+				}
+
+				if ( isElement && ( p === "height" || p === "width" ) ) {
+					// Make sure that nothing sneaks out
+					// Record all 3 overflow attributes because IE does not
+					// change the overflow attribute when overflowX and
+					// overflowY are set to the same value
+					opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];
+
+					// Set display property to inline-block for height/width
+					// animations on inline elements that are having width/height
+					// animated
+					if ( jQuery.css( this, "display" ) === "inline" &&
+							jQuery.css( this, "float" ) === "none" ) {
+						if ( !jQuery.support.inlineBlockNeedsLayout ) {
+							this.style.display = "inline-block";
+
+						} else {
+							var display = defaultDisplay(this.nodeName);
+
+							// inline-level elements accept inline-block;
+							// block-level elements need to be inline with layout
+							if ( display === "inline" ) {
+								this.style.display = "inline-block";
+
+							} else {
+								this.style.display = "inline";
+								this.style.zoom = 1;
+							}
+						}
+					}
+				}
+
+				if ( jQuery.isArray( prop[p] ) ) {
+					// Create (if needed) and add to specialEasing
+					(opt.specialEasing = opt.specialEasing || {})[p] = prop[p][1];
+					prop[p] = prop[p][0];
+				}
+			}
+
+			if ( opt.overflow != null ) {
+				this.style.overflow = "hidden";
+			}
+
+			opt.curAnim = jQuery.extend({}, prop);
+
+			jQuery.each( prop, function( name, val ) {
+				var e = new jQuery.fx( self, opt, name );
+
+				if ( rfxtypes.test(val) ) {
+					e[ val === "toggle" ? hidden ? "show" : "hide" : val ]( prop );
+
+				} else {
+					var parts = rfxnum.exec(val),
+						start = e.cur() || 0;
+
+					if ( parts ) {
+						var end = parseFloat( parts[2] ),
+							unit = parts[3] || "px";
+
+						// We need to compute starting value
+						if ( unit !== "px" ) {
+							jQuery.style( self, name, (end || 1) + unit);
+							start = ((end || 1) / e.cur()) * start;
+							jQuery.style( self, name, start + unit);
+						}
+
+						// If a +=/-= token was provided, we're doing a relative animation
+						if ( parts[1] ) {
+							end = ((parts[1] === "-=" ? -1 : 1) * end) + start;
+						}
+
+						e.custom( start, end, unit );
+
+					} else {
+						e.custom( start, val, "" );
+					}
+				}
+			});
+
+			// For JS strict compliance
+			return true;
+		});
+	},
+
+	stop: function( clearQueue, gotoEnd ) {
+		var timers = jQuery.timers;
+
+		if ( clearQueue ) {
+			this.queue([]);
+		}
+
+		this.each(function() {
+			// go in reverse order so anything added to the queue during the loop is ignored
+			for ( var i = timers.length - 1; i >= 0; i-- ) {
+				if ( timers[i].elem === this ) {
+					if (gotoEnd) {
+						// force the next step to be the last
+						timers[i](true);
+					}
+
+					timers.splice(i, 1);
+				}
+			}
+		});
+
+		// start the next in the queue if the last step wasn't forced
+		if ( !gotoEnd ) {
+			this.dequeue();
+		}
+
+		return this;
+	}
+
+});
+
+function genFx( type, num ) {
+	var obj = {};
+
+	jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() {
+		obj[ this ] = type;
+	});
+
+	return obj;
+}
+
+// Generate shortcuts for custom animations
+jQuery.each({
+	slideDown: genFx("show", 1),
+	slideUp: genFx("hide", 1),
+	slideToggle: genFx("toggle", 1),
+	fadeIn: { opacity: "show" },
+	fadeOut: { opacity: "hide" },
+	fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+	jQuery.fn[ name ] = function( speed, easing, callback ) {
+		return this.animate( props, speed, easing, callback );
+	};
+});
+
+jQuery.extend({
+	speed: function( speed, easing, fn ) {
+		var opt = speed && typeof speed === "object" ? jQuery.extend({}, speed) : {
+			complete: fn || !fn && easing ||
+				jQuery.isFunction( speed ) && speed,
+			duration: speed,
+			easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
+		};
+
+		opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+			opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[opt.duration] : jQuery.fx.speeds._default;
+
+		// Queueing
+		opt.old = opt.complete;
+		opt.complete = function() {
+			if ( opt.queue !== false ) {
+				jQuery(this).dequeue();
+			}
+			if ( jQuery.isFunction( opt.old ) ) {
+				opt.old.call( this );
+			}
+		};
+
+		return opt;
+	},
+
+	easing: {
+		linear: function( p, n, firstNum, diff ) {
+			return firstNum + diff * p;
+		},
+		swing: function( p, n, firstNum, diff ) {
+			return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
+		}
+	},
+
+	timers: [],
+
+	fx: function( elem, options, prop ) {
+		this.options = options;
+		this.elem = elem;
+		this.prop = prop;
+
+		if ( !options.orig ) {
+			options.orig = {};
+		}
+	}
+
+});
+
+jQuery.fx.prototype = {
+	// Simple function for setting a style value
+	update: function() {
+		if ( this.options.step ) {
+			this.options.step.call( this.elem, this.now, this );
+		}
+
+		(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
+	},
+
+	// Get the current size
+	cur: function() {
+		if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) {
+			return this.elem[ this.prop ];
+		}
+
+		var r = parseFloat( jQuery.css( this.elem, this.prop ) );
+		return r && r > -10000 ? r : 0;
+	},
+
+	// Start an animation from one number to another
+	custom: function( from, to, unit ) {
+		var self = this,
+			fx = jQuery.fx;
+
+		this.startTime = jQuery.now();
+		this.start = from;
+		this.end = to;
+		this.unit = unit || this.unit || "px";
+		this.now = this.start;
+		this.pos = this.state = 0;
+
+		function t( gotoEnd ) {
+			return self.step(gotoEnd);
+		}
+
+		t.elem = this.elem;
+
+		if ( t() && jQuery.timers.push(t) && !timerId ) {
+			timerId = setInterval(fx.tick, fx.interval);
+		}
+	},
+
+	// Simple 'show' function
+	show: function() {
+		// Remember where we started, so that we can go back to it later
+		this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
+		this.options.show = true;
+
+		// Begin the animation
+		// Make sure that we start at a small width/height to avoid any
+		// flash of content
+		this.custom(this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur());
+
+		// Start by showing the element
+		jQuery( this.elem ).show();
+	},
+
+	// Simple 'hide' function
+	hide: function() {
+		// Remember where we started, so that we can go back to it later
+		this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
+		this.options.hide = true;
+
+		// Begin the animation
+		this.custom(this.cur(), 0);
+	},
+
+	// Each step of an animation
+	step: function( gotoEnd ) {
+		var t = jQuery.now(), done = true;
+
+		if ( gotoEnd || t >= this.options.duration + this.startTime ) {
+			this.now = this.end;
+			this.pos = this.state = 1;
+			this.update();
+
+			this.options.curAnim[ this.prop ] = true;
+
+			for ( var i in this.options.curAnim ) {
+				if ( this.options.curAnim[i] !== true ) {
+					done = false;
+				}
+			}
+
+			if ( done ) {
+				// Reset the overflow
+				if ( this.options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {
+					var elem = this.elem,
+						options = this.options;
+
+					jQuery.each( [ "", "X", "Y" ], function (index, value) {
+						elem.style[ "overflow" + value ] = options.overflow[index];
+					} );
+				}
+
+				// Hide the element if the "hide" operation was done
+				if ( this.options.hide ) {
+					jQuery(this.elem).hide();
+				}
+
+				// Reset the properties, if the item has been hidden or shown
+				if ( this.options.hide || this.options.show ) {
+					for ( var p in this.options.curAnim ) {
+						jQuery.style( this.elem, p, this.options.orig[p] );
+					}
+				}
+
+				// Execute the complete function
+				this.options.complete.call( this.elem );
+			}
+
+			return false;
+
+		} else {
+			var n = t - this.startTime;
+			this.state = n / this.options.duration;
+
+			// Perform the easing function, defaults to swing
+			var specialEasing = this.options.specialEasing && this.options.specialEasing[this.prop];
+			var defaultEasing = this.options.easing || (jQuery.easing.swing ? "swing" : "linear");
+			this.pos = jQuery.easing[specialEasing || defaultEasing](this.state, n, 0, 1, this.options.duration);
+			this.now = this.start + ((this.end - this.start) * this.pos);
+
+			// Perform the next step of the animation
+			this.update();
+		}
+
+		return true;
+	}
+};
+
+jQuery.extend( jQuery.fx, {
+	tick: function() {
+		var timers = jQuery.timers;
+
+		for ( var i = 0; i < timers.length; i++ ) {
+			if ( !timers[i]() ) {
+				timers.splice(i--, 1);
+			}
+		}
+
+		if ( !timers.length ) {
+			jQuery.fx.stop();
+		}
+	},
+
+	interval: 13,
+
+	stop: function() {
+		clearInterval( timerId );
+		timerId = null;
+	},
+
+	speeds: {
+		slow: 600,
+		fast: 200,
+		// Default speed
+		_default: 400
+	},
+
+	step: {
+		opacity: function( fx ) {
+			jQuery.style( fx.elem, "opacity", fx.now );
+		},
+
+		_default: function( fx ) {
+			if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
+				fx.elem.style[ fx.prop ] = (fx.prop === "width" || fx.prop === "height" ? Math.max(0, fx.now) : fx.now) + fx.unit;
+			} else {
+				fx.elem[ fx.prop ] = fx.now;
+			}
+		}
+	}
+});
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+	jQuery.expr.filters.animated = function( elem ) {
+		return jQuery.grep(jQuery.timers, function( fn ) {
+			return elem === fn.elem;
+		}).length;
+	};
+}
+
+function defaultDisplay( nodeName ) {
+	if ( !elemdisplay[ nodeName ] ) {
+		var elem = jQuery("<" + nodeName + ">").appendTo("body"),
+			display = elem.css("display");
+
+		elem.remove();
+
+		if ( display === "none" || display === "" ) {
+			display = "block";
+		}
+
+		elemdisplay[ nodeName ] = display;
+	}
+
+	return elemdisplay[ nodeName ];
+}
+
+
+
+
+var rtable = /^t(?:able|d|h)$/i,
+	rroot = /^(?:body|html)$/i;
+
+if ( "getBoundingClientRect" in document.documentElement ) {
+	jQuery.fn.offset = function( options ) {
+		var elem = this[0], box;
+
+		if ( options ) { 
+			return this.each(function( i ) {
+				jQuery.offset.setOffset( this, options, i );
+			});
+		}
+
+		if ( !elem || !elem.ownerDocument ) {
+			return null;
+		}
+
+		if ( elem === elem.ownerDocument.body ) {
+			return jQuery.offset.bodyOffset( elem );
+		}
+
+		try {
+			box = elem.getBoundingClientRect();
+		} catch(e) {}
+
+		var doc = elem.ownerDocument,
+			docElem = doc.documentElement;
+
+		// Make sure we're not dealing with a disconnected DOM node
+		if ( !box || !jQuery.contains( docElem, elem ) ) {
+			return box || { top: 0, left: 0 };
+		}
+
+		var body = doc.body,
+			win = getWindow(doc),
+			clientTop  = docElem.clientTop  || body.clientTop  || 0,
+			clientLeft = docElem.clientLeft || body.clientLeft || 0,
+			scrollTop  = (win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop ),
+			scrollLeft = (win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft),
+			top  = box.top  + scrollTop  - clientTop,
+			left = box.left + scrollLeft - clientLeft;
+
+		return { top: top, left: left };
+	};
+
+} else {
+	jQuery.fn.offset = function( options ) {
+		var elem = this[0];
+
+		if ( options ) { 
+			return this.each(function( i ) {
+				jQuery.offset.setOffset( this, options, i );
+			});
+		}
+
+		if ( !elem || !elem.ownerDocument ) {
+			return null;
+		}
+
+		if ( elem === elem.ownerDocument.body ) {
+			return jQuery.offset.bodyOffset( elem );
+		}
+
+		jQuery.offset.initialize();
+
+		var computedStyle,
+			offsetParent = elem.offsetParent,
+			prevOffsetParent = elem,
+			doc = elem.ownerDocument,
+			docElem = doc.documentElement,
+			body = doc.body,
+			defaultView = doc.defaultView,
+			prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
+			top = elem.offsetTop,
+			left = elem.offsetLeft;
+
+		while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
+			if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
+				break;
+			}
+
+			computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
+			top  -= elem.scrollTop;
+			left -= elem.scrollLeft;
+
+			if ( elem === offsetParent ) {
+				top  += elem.offsetTop;
+				left += elem.offsetLeft;
+
+				if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {
+					top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
+					left += parseFloat( computedStyle.borderLeftWidth ) || 0;
+				}
+
+				prevOffsetParent = offsetParent;
+				offsetParent = elem.offsetParent;
+			}
+
+			if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
+				top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
+				left += parseFloat( computedStyle.borderLeftWidth ) || 0;
+			}
+
+			prevComputedStyle = computedStyle;
+		}
+
+		if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
+			top  += body.offsetTop;
+			left += body.offsetLeft;
+		}
+
+		if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
+			top  += Math.max( docElem.scrollTop, body.scrollTop );
+			left += Math.max( docElem.scrollLeft, body.scrollLeft );
+		}
+
+		return { top: top, left: left };
+	};
+}
+
+jQuery.offset = {
+	initialize: function() {
+		var body = document.body, container = document.createElement("div"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.css(body, "marginTop") ) || 0,
+			html = "<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
+
+		jQuery.extend( container.style, { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" } );
+
+		container.innerHTML = html;
+		body.insertBefore( container, body.firstChild );
+		innerDiv = container.firstChild;
+		checkDiv = innerDiv.firstChild;
+		td = innerDiv.nextSibling.firstChild.firstChild;
+
+		this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
+		this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
+
+		checkDiv.style.position = "fixed";
+		checkDiv.style.top = "20px";
+
+		// safari subtracts parent border width here which is 5px
+		this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);
+		checkDiv.style.position = checkDiv.style.top = "";
+
+		innerDiv.style.overflow = "hidden";
+		innerDiv.style.position = "relative";
+
+		this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
+
+		this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);
+
+		body.removeChild( container );
+		body = container = innerDiv = checkDiv = table = td = null;
+		jQuery.offset.initialize = jQuery.noop;
+	},
+
+	bodyOffset: function( body ) {
+		var top = body.offsetTop,
+			left = body.offsetLeft;
+
+		jQuery.offset.initialize();
+
+		if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {
+			top  += parseFloat( jQuery.css(body, "marginTop") ) || 0;
+			left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
+		}
+
+		return { top: top, left: left };
+	},
+	
+	setOffset: function( elem, options, i ) {
+		var position = jQuery.css( elem, "position" );
+
+		// set position first, in-case top/left are set even on static elem
+		if ( position === "static" ) {
+			elem.style.position = "relative";
+		}
+
+		var curElem = jQuery( elem ),
+			curOffset = curElem.offset(),
+			curCSSTop = jQuery.css( elem, "top" ),
+			curCSSLeft = jQuery.css( elem, "left" ),
+			calculatePosition = (position === "absolute" && jQuery.inArray('auto', [curCSSTop, curCSSLeft]) > -1),
+			props = {}, curPosition = {}, curTop, curLeft;
+
+		// need to be able to calculate position if either top or left is auto and position is absolute
+		if ( calculatePosition ) {
+			curPosition = curElem.position();
+		}
+
+		curTop  = calculatePosition ? curPosition.top  : parseInt( curCSSTop,  10 ) || 0;
+		curLeft = calculatePosition ? curPosition.left : parseInt( curCSSLeft, 10 ) || 0;
+
+		if ( jQuery.isFunction( options ) ) {
+			options = options.call( elem, i, curOffset );
+		}
+
+		if (options.top != null) {
+			props.top = (options.top - curOffset.top) + curTop;
+		}
+		if (options.left != null) {
+			props.left = (options.left - curOffset.left) + curLeft;
+		}
+		
+		if ( "using" in options ) {
+			options.using.call( elem, props );
+		} else {
+			curElem.css( props );
+		}
+	}
+};
+
+
+jQuery.fn.extend({
+	position: function() {
+		if ( !this[0] ) {
+			return null;
+		}
+
+		var elem = this[0],
+
+		// Get *real* offsetParent
+		offsetParent = this.offsetParent(),
+
+		// Get correct offsets
+		offset       = this.offset(),
+		parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
+
+		// Subtract element margins
+		// note: when an element has margin: auto the offsetLeft and marginLeft
+		// are the same in Safari causing offset.left to incorrectly be 0
+		offset.top  -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
+		offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;
+
+		// Add offsetParent borders
+		parentOffset.top  += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
+		parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;
+
+		// Subtract the two offsets
+		return {
+			top:  offset.top  - parentOffset.top,
+			left: offset.left - parentOffset.left
+		};
+	},
+
+	offsetParent: function() {
+		return this.map(function() {
+			var offsetParent = this.offsetParent || document.body;
+			while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
+				offsetParent = offsetParent.offsetParent;
+			}
+			return offsetParent;
+		});
+	}
+});
+
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( ["Left", "Top"], function( i, name ) {
+	var method = "scroll" + name;
+
+	jQuery.fn[ method ] = function(val) {
+		var elem = this[0], win;
+		
+		if ( !elem ) {
+			return null;
+		}
+
+		if ( val !== undefined ) {
+			// Set the scroll offset
+			return this.each(function() {
+				win = getWindow( this );
+
+				if ( win ) {
+					win.scrollTo(
+						!i ? val : jQuery(win).scrollLeft(),
+						 i ? val : jQuery(win).scrollTop()
+					);
+
+				} else {
+					this[ method ] = val;
+				}
+			});
+		} else {
+			win = getWindow( elem );
+
+			// Return the scroll offset
+			return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
+				jQuery.support.boxModel && win.document.documentElement[ method ] ||
+					win.document.body[ method ] :
+				elem[ method ];
+		}
+	};
+});
+
+function getWindow( elem ) {
+	return jQuery.isWindow( elem ) ?
+		elem :
+		elem.nodeType === 9 ?
+			elem.defaultView || elem.parentWindow :
+			false;
+}
+
+
+
+
+// Create innerHeight, innerWidth, outerHeight and outerWidth methods
+jQuery.each([ "Height", "Width" ], function( i, name ) {
+
+	var type = name.toLowerCase();
+
+	// innerHeight and innerWidth
+	jQuery.fn["inner" + name] = function() {
+		return this[0] ?
+			parseFloat( jQuery.css( this[0], type, "padding" ) ) :
+			null;
+	};
+
+	// outerHeight and outerWidth
+	jQuery.fn["outer" + name] = function( margin ) {
+		return this[0] ?
+			parseFloat( jQuery.css( this[0], type, margin ? "margin" : "border" ) ) :
+			null;
+	};
+
+	jQuery.fn[ type ] = function( size ) {
+		// Get window width or height
+		var elem = this[0];
+		if ( !elem ) {
+			return size == null ? null : this;
+		}
+		
+		if ( jQuery.isFunction( size ) ) {
+			return this.each(function( i ) {
+				var self = jQuery( this );
+				self[ type ]( size.call( this, i, self[ type ]() ) );
+			});
+		}
+
+		if ( jQuery.isWindow( elem ) ) {
+			// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
+			return elem.document.compatMode === "CSS1Compat" && elem.document.documentElement[ "client" + name ] ||
+				elem.document.body[ "client" + name ];
+
+		// Get document width or height
+		} else if ( elem.nodeType === 9 ) {
+			// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
+			return Math.max(
+				elem.documentElement["client" + name],
+				elem.body["scroll" + name], elem.documentElement["scroll" + name],
+				elem.body["offset" + name], elem.documentElement["offset" + name]
+			);
+
+		// Get or set width or height on the element
+		} else if ( size === undefined ) {
+			var orig = jQuery.css( elem, type ),
+				ret = parseFloat( orig );
+
+			return jQuery.isNaN( ret ) ? orig : ret;
+
+		// Set the width or height on the element (default to pixels if value is unitless)
+		} else {
+			return this.css( type, typeof size === "string" ? size : size + "px" );
+		}
+	};
+
+});
+
+
+})(window);
diff --git a/y2015/http_status/www/lib/reconnecting-websocket.min.js b/y2015/http_status/www/lib/reconnecting-websocket.min.js
new file mode 100644
index 0000000..f40b6c7
--- /dev/null
+++ b/y2015/http_status/www/lib/reconnecting-websocket.min.js
@@ -0,0 +1,96 @@
+// MIT License:
+//
+// Copyright (c) 2010-2012, Joe Walnes
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+/**
+ * This behaves like a WebSocket in every way, except if it fails to connect,
+ * or it gets disconnected, it will repeatedly poll until it successfully connects
+ * again.
+ *
+ * It is API compatible, so when you have:
+ *   ws = new WebSocket('ws://....');
+ * you can replace with:
+ *   ws = new ReconnectingWebSocket('ws://....');
+ *
+ * The event stream will typically look like:
+ *  onconnecting
+ *  onopen
+ *  onmessage
+ *  onmessage
+ *  onclose // lost connection
+ *  onconnecting
+ *  onopen  // sometime later...
+ *  onmessage
+ *  onmessage
+ *  etc...
+ *
+ * It is API compatible with the standard WebSocket API, apart from the following members:
+ *
+ * - `bufferedAmount`
+ * - `extensions`
+ * - `binaryType`
+ *
+ * Latest version: https://github.com/joewalnes/reconnecting-websocket/
+ * - Joe Walnes
+ *
+ * Syntax
+ * ======
+ * var socket = new ReconnectingWebSocket(url, protocols, options);
+ *
+ * Parameters
+ * ==========
+ * url - The url you are connecting to.
+ * protocols - Optional string or array of protocols.
+ * options - See below
+ *
+ * Options
+ * =======
+ * Options can either be passed upon instantiation or set after instantiation:
+ *
+ * var socket = new ReconnectingWebSocket(url, null, { debug: true, reconnectInterval: 4000 });
+ *
+ * or
+ *
+ * var socket = new ReconnectingWebSocket(url);
+ * socket.debug = true;
+ * socket.reconnectInterval = 4000;
+ *
+ * debug
+ * - Whether this instance should log debug messages. Accepts true or false. Default: false.
+ *
+ * automaticOpen
+ * - Whether or not the websocket should attempt to connect immediately upon instantiation. The socket can be manually opened or closed at any time using ws.open() and ws.close().
+ *
+ * reconnectInterval
+ * - The number of milliseconds to delay before attempting to reconnect. Accepts integer. Default: 1000.
+ *
+ * maxReconnectInterval
+ * - The maximum number of milliseconds to delay a reconnection attempt. Accepts integer. Default: 30000.
+ *
+ * reconnectDecay
+ * - The rate of increase of the reconnect delay. Allows reconnect attempts to back off when problems persist. Accepts integer or float. Default: 1.5.
+ *
+ * timeoutInterval
+ * - The maximum time in milliseconds to wait for a connection to succeed before closing and retrying. Accepts integer. Default: 2000.
+ *
+ */
+
+!function(a,b){"function"==typeof define&&define.amd?define([],b):"undefined"!=typeof module&&module.exports?module.exports=b():a.ReconnectingWebSocket=b()}(this,function(){function a(b,c,d){function l(a,b){var c=document.createEvent("CustomEvent");return c.initCustomEvent(a,!1,!1,b),c}var e={debug:!1,automaticOpen:!0,reconnectInterval:1e3,maxReconnectInterval:3e4,reconnectDecay:1.5,timeoutInterval:2e3};d||(d={});for(var f in e)this[f]="undefined"!=typeof d[f]?d[f]:e[f];this.url=b,this.reconnectAttempts=0,this.readyState=WebSocket.CONNECTING,this.protocol=null;var h,g=this,i=!1,j=!1,k=document.createElement("div");k.addEventListener("open",function(a){g.onopen(a)}),k.addEventListener("close",function(a){g.onclose(a)}),k.addEventListener("connecting",function(a){g.onconnecting(a)}),k.addEventListener("message",function(a){g.onmessage(a)}),k.addEventListener("error",function(a){g.onerror(a)}),this.addEventListener=k.addEventListener.bind(k),this.removeEventListener=k.removeEventListener.bind(k),this.dispatchEvent=k.dispatchEvent.bind(k),this.open=function(b){h=new WebSocket(g.url,c||[]),b||k.dispatchEvent(l("connecting")),(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","attempt-connect",g.url);var d=h,e=setTimeout(function(){(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","connection-timeout",g.url),j=!0,d.close(),j=!1},g.timeoutInterval);h.onopen=function(){clearTimeout(e),(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","onopen",g.url),g.protocol=h.protocol,g.readyState=WebSocket.OPEN,g.reconnectAttempts=0;var d=l("open");d.isReconnect=b,b=!1,k.dispatchEvent(d)},h.onclose=function(c){if(clearTimeout(e),h=null,i)g.readyState=WebSocket.CLOSED,k.dispatchEvent(l("close"));else{g.readyState=WebSocket.CONNECTING;var d=l("connecting");d.code=c.code,d.reason=c.reason,d.wasClean=c.wasClean,k.dispatchEvent(d),b||j||((g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","onclose",g.url),k.dispatchEvent(l("close")));var e=g.reconnectInterval*Math.pow(g.reconnectDecay,g.reconnectAttempts);setTimeout(function(){g.reconnectAttempts++,g.open(!0)},e>g.maxReconnectInterval?g.maxReconnectInterval:e)}},h.onmessage=function(b){(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","onmessage",g.url,b.data);var c=l("message");c.data=b.data,k.dispatchEvent(c)},h.onerror=function(b){(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","onerror",g.url,b),k.dispatchEvent(l("error"))}},1==this.automaticOpen&&this.open(!1),this.send=function(b){if(h)return(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","send",g.url,b),h.send(b);throw"INVALID_STATE_ERR : Pausing to reconnect websocket"},this.close=function(a,b){"undefined"==typeof a&&(a=1e3),i=!0,h&&h.close(a,b)},this.refresh=function(){h&&h.close()}}return a.prototype.onopen=function(){},a.prototype.onclose=function(){},a.prototype.onconnecting=function(){},a.prototype.onmessage=function(){},a.prototype.onerror=function(){},a.debugAll=!1,a.CONNECTING=WebSocket.CONNECTING,a.OPEN=WebSocket.OPEN,a.CLOSING=WebSocket.CLOSING,a.CLOSED=WebSocket.CLOSED,a});
diff --git a/y2015/http_status/www_defaults/_404.png b/y2015/http_status/www_defaults/_404.png
new file mode 100644
index 0000000..8a43cb8
--- /dev/null
+++ b/y2015/http_status/www_defaults/_404.png
Binary files differ
diff --git a/y2015/http_status/www_defaults/_error.css b/y2015/http_status/www_defaults/_error.css
new file mode 100644
index 0000000..565d0a4
--- /dev/null
+++ b/y2015/http_status/www_defaults/_error.css
@@ -0,0 +1,60 @@
+/*
+From Seasocks version 1.1.2, under /src/main/web
+
+Copyright (c) 2013, Matt Godbolt
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this 
+list of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this 
+list of conditions and the following disclaimer in the documentation and/or 
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+body {
+    font-family: segoe ui, tahoma, arial, sans-serif;
+    color: #ffffff;
+    background-color: #c21e29;
+    text-align: center;
+}
+
+a {
+    color: #ffff00;
+}
+
+.footer {
+    font-style: italic;
+}
+
+.message {
+    display: inline-block;
+    border: 1px solid white;
+    padding: 50px;
+    font-size: 20px;
+}
+
+.headline {
+    padding: 50px;
+    font-weight: bold;
+    font-size: 32px;
+}
+
+.footer {
+    padding-top: 50px;
+    font-size: 12px;
+}
+
diff --git a/y2015/http_status/www_defaults/_error.html b/y2015/http_status/www_defaults/_error.html
new file mode 100644
index 0000000..e3d422d
--- /dev/null
+++ b/y2015/http_status/www_defaults/_error.html
@@ -0,0 +1,42 @@
+<!--
+From Seasocks version 1.1.2, under /src/main/web
+
+Copyright (c) 2013, Matt Godbolt
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this 
+list of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this 
+list of conditions and the following disclaimer in the documentation and/or 
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<html DOCTYPE=html>
+<head>
+  <title>%%ERRORCODE%% - %%MESSAGE%% - Keep Calm And Carry On!</title>
+  <link href="/_error.css" rel="stylesheet">
+</head>
+<body>
+  <div class="message">
+    <img src="/_404.png" height="200" width="107">
+    <div class="headline">HTTP_STATUS: %%ERRORCODE%% &#8212; %%MESSAGE%%</div>
+    <div class="info">%%BODY%%</div>
+  </div>
+
+  <div class="footer">http_status developed by 971 Spartan Robotics. Server powered by <a href="https://github.com/mattgodbolt/seasocks">SeaSocks</a>. Contact Comran Morshed(comranmorsh@gmail.com) if this 404 error should not be happening...</div>
+</body>
+</html>
diff --git a/y2015/http_status/www_defaults/_seasocks.css b/y2015/http_status/www_defaults/_seasocks.css
new file mode 100644
index 0000000..5f0b655
--- /dev/null
+++ b/y2015/http_status/www_defaults/_seasocks.css
@@ -0,0 +1,49 @@
+/*
+From Seasocks version 1.1.2, under /src/main/web
+
+Copyright (c) 2013, Matt Godbolt
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this 
+list of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this 
+list of conditions and the following disclaimer in the documentation and/or 
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+body {
+    font-family: segoe ui, tahoma, arial, sans-serif;
+    font-size: 12px;
+    color: #ffffff;
+    background-color: #333333;
+    margin: 0;
+}
+
+a {
+    color: #ffff00;
+}
+
+table {
+    border-collapse: collapse;
+    width: 100%;
+    text-align: center;
+}
+
+.template {
+    display: none;
+}
+
diff --git a/y2015/http_status/www_defaults/_stats.html b/y2015/http_status/www_defaults/_stats.html
new file mode 100644
index 0000000..2390334
--- /dev/null
+++ b/y2015/http_status/www_defaults/_stats.html
@@ -0,0 +1,88 @@
+<!--
+From Seasocks version 1.1.2, under /src/main/web
+
+Copyright (c) 2013, Matt Godbolt
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this 
+list of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this 
+list of conditions and the following disclaimer in the documentation and/or 
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<html DOCTYPE=html>
+<head>
+  <title>SeaSocks Stats</title>
+  <link href="/_seasocks.css" rel="stylesheet">
+  <script src="/_jquery.min.js" type="text/javascript"></script>
+  <script>
+  function clear() {
+    $('#cx tbody tr:visible').remove();
+  }
+  function connection(stats) {
+    c = $('#cx .template').clone().removeClass('template').appendTo('#cx');
+    for (stat in stats) {
+      c.find('.' + stat).text(stats[stat]);
+    }
+  }
+  function refresh() {
+    var stats = new XMLHttpRequest();
+    stats.open("GET", "/_livestats.js", false);
+    stats.send(null);
+    eval(stats.responseText);
+  }
+  $(function() {
+    setInterval(refresh, 1000);
+    refresh();
+  });
+  </script>
+</head>
+<body><h1>SeaSocks Stats</h1></body>
+
+<h2>Connections</h2>
+<table id="cx">
+  <thead>
+    <tr>
+      <th>Connection time</th>
+      <th>Fd</th>
+      <th>Addr</th>
+      <th>URI</th>
+      <th>Username</th>
+      <th>Pending read</th>
+      <th>Bytes read</th>
+      <th>Pending send</th>
+      <th>Bytes sent</th>
+    </tr>
+  </thead>
+  <tbody>
+    <tr class="template">
+      <td class="since"></td>
+      <td class="fd"></td>
+      <td class="addr"></td>
+      <td class="uri"></td>
+      <td class="user"></td>
+      <td class="input"></td>
+      <td class="read"></td>
+      <td class="output"></td>
+      <td class="written"></td>
+    </tr>
+  </tbody>
+</table>
+
+</body>
+</html>
diff --git a/y2015/http_status/www_defaults/favicon.ico b/y2015/http_status/www_defaults/favicon.ico
new file mode 100644
index 0000000..30a95b9
--- /dev/null
+++ b/y2015/http_status/www_defaults/favicon.ico
Binary files differ
diff --git a/y2015/joystick_reader.cc b/y2015/joystick_reader.cc
new file mode 100644
index 0000000..01b5431
--- /dev/null
+++ b/y2015/joystick_reader.cc
@@ -0,0 +1,549 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <math.h>
+
+#include "aos/linux_code/init.h"
+#include "aos/prime/input/joystick_input.h"
+#include "aos/common/input/driver_station_data.h"
+#include "aos/common/logging/logging.h"
+#include "aos/common/util/log_interval.h"
+#include "aos/common/time.h"
+#include "aos/common/actions/actions.h"
+
+#include "y2015/control_loops/claw/claw.q.h"
+#include "y2015/control_loops/drivetrain/drivetrain.q.h"
+#include "y2015/control_loops/fridge/fridge.q.h"
+#include "y2015/constants.h"
+#include "frc971/queues/gyro.q.h"
+#include "frc971/autonomous/auto.q.h"
+#include "y2015/actors/pickup_actor.h"
+#include "y2015/actors/stack_actor.h"
+#include "y2015/actors/score_actor.h"
+#include "y2015/actors/stack_and_lift_actor.h"
+#include "y2015/actors/stack_and_hold_actor.h"
+#include "y2015/actors/held_to_lift_actor.h"
+#include "y2015/actors/lift_actor.h"
+#include "y2015/actors/can_pickup_actor.h"
+#include "y2015/actors/horizontal_can_pickup_actor.h"
+
+using ::frc971::control_loops::claw_queue;
+using ::frc971::control_loops::drivetrain_queue;
+using ::frc971::control_loops::fridge_queue;
+using ::frc971::sensors::gyro_reading;
+
+using ::aos::input::driver_station::ButtonLocation;
+using ::aos::input::driver_station::POVLocation;
+using ::aos::input::driver_station::JoystickAxis;
+using ::aos::input::driver_station::ControlBit;
+
+namespace frc971 {
+namespace input {
+namespace joysticks {
+
+// Actions needed.
+
+// Human Player Station Intake Button
+// Claw open
+// Claw close
+// Claw down
+
+// Stack + Lift (together)
+// Place
+
+// Hold stack
+
+// Horizontal can pickup
+// Vertical can pickup
+
+// TODO(austin): Pull a lot of the constants below out up here so they can be
+// globally changed easier.
+
+// preset motion limits
+constexpr actors::ProfileParams kArmMove{0.5, 1.0};
+constexpr actors::ProfileParams kElevatorMove{0.3, 1.0};
+
+const JoystickAxis kSteeringWheel(1, 1), kDriveThrottle(2, 2);
+const ButtonLocation kShiftHigh(2, 1), kShiftLow(2, 3);
+const ButtonLocation kQuickTurn(1, 5);
+
+//const ButtonLocation kClawClosed(3, 5);
+//const ButtonLocation kFridgeClosed(3, 1);
+
+
+const ButtonLocation kStackAndHold(3, 5);
+const ButtonLocation kRollersIn(3, 2);
+const ButtonLocation kHorizontalCanRollersIn(4, 5);
+const ButtonLocation kClawToggle(4, 1);
+
+const POVLocation kElevatorCanUp(4, 0);
+
+// POV stick 3, 180
+const POVLocation kCanPickup(4, 180);
+const ButtonLocation kToteChute(4, 6);
+const ButtonLocation kStackAndLift(4, 7);
+
+// Pull in the 6th tote.
+//const ButtonLocation kSixthTote(4, 10);
+const ButtonLocation kCanUp(4, 10);
+
+const ButtonLocation kHeldToLift(4, 11);
+const ButtonLocation kPickup(4, 9);
+
+const ButtonLocation kStack(4, 2);
+
+// Move the fridge out with the stack in preparation for scoring.
+const ButtonLocation kScore(4, 8);
+const ButtonLocation kCoopTop(3, 8);
+const ButtonLocation kCoopTopRetract(3, 7);
+const ButtonLocation kCoopBottom(3, 6);
+const ButtonLocation kCoopBottomRetract(4, 12);
+
+const ButtonLocation kCanReset(3, 9);
+
+const POVLocation kFridgeToggle(4, 270);
+const ButtonLocation kSpit(4, 3);
+
+// Set stack down in the bot.
+const POVLocation kSetStackDownAndHold(4, 90);
+
+const double kClawTotePackAngle = 0.90;
+const double kArmRaiseLowerClearance = -0.08;
+const double kClawStackClearance = 0.55;
+const double kHorizontalCanClawAngle = 0.12;
+
+const double kStackUpHeight = 0.60;
+const double kStackUpArm = 0.0;
+
+class Reader : public ::aos::input::JoystickInput {
+ public:
+  Reader() : was_running_(false) {}
+
+  static actors::ScoreParams MakeScoreParams() {
+    actors::ScoreParams r;
+    r.move_the_stack = r.place_the_stack = true;
+    r.upper_move_height = 0.14;
+    r.begin_horizontal_move_height = 0.13;
+    r.horizontal_move_target = -0.7;
+    r.horizontal_start_lowering = -0.65;
+    r.home_lift_horizontal_start_position = -0.60;
+    r.place_height = -0.10;
+    r.home_return_height = 0.05;
+    return r;
+  }
+
+  static actors::ScoreParams MakeCoopTopParams(bool place_the_stack) {
+    actors::ScoreParams r;
+    r.move_the_stack = !place_the_stack;
+    r.place_the_stack = place_the_stack;
+    r.upper_move_height = 0.52;
+    r.begin_horizontal_move_height = 0.5;
+    r.horizontal_move_target = -0.48;
+    r.horizontal_start_lowering = r.horizontal_move_target;
+    r.home_lift_horizontal_start_position = -0.3;
+    r.place_height = 0.35;
+    r.home_return_height = 0.1;
+    return r;
+  }
+
+  static actors::ScoreParams MakeCoopBottomParams(bool place_the_stack) {
+    actors::ScoreParams r;
+    r.move_the_stack = !place_the_stack;
+    r.place_the_stack = place_the_stack;
+    r.upper_move_height = 0.17;
+    r.begin_horizontal_move_height = 0.16;
+    r.horizontal_move_target = -0.7;
+    r.horizontal_start_lowering = r.horizontal_move_target;
+    r.home_lift_horizontal_start_position = -0.3;
+    r.place_height = 0.0;
+    r.home_return_height = 0.1;
+    return r;
+  }
+
+  virtual void RunIteration(const ::aos::input::driver_station::Data &data) {
+    bool last_auto_running = auto_running_;
+    auto_running_ = data.GetControlBit(ControlBit::kAutonomous) &&
+                    data.GetControlBit(ControlBit::kEnabled);
+    if (auto_running_ != last_auto_running) {
+      if (auto_running_) {
+        StartAuto();
+      } else {
+        StopAuto();
+      }
+    }
+
+    if (!data.GetControlBit(ControlBit::kAutonomous)) {
+      HandleDrivetrain(data);
+      HandleTeleop(data);
+    }
+  }
+
+  void HandleDrivetrain(const ::aos::input::driver_station::Data &data) {
+    const double wheel = -data.GetAxis(kSteeringWheel);
+    const double throttle = -data.GetAxis(kDriveThrottle);
+
+    if (!drivetrain_queue.goal.MakeWithBuilder()
+             .steering(wheel)
+             .throttle(throttle)
+             .quickturn(data.IsPressed(kQuickTurn))
+             .control_loop_driving(false)
+             .Send()) {
+      LOG(WARNING, "sending stick values failed\n");
+    }
+  }
+
+  void HandleTeleop(const ::aos::input::driver_station::Data &data) {
+    double intake_power = 0.0;
+    if (!data.GetControlBit(ControlBit::kEnabled)) {
+      action_queue_.CancelAllActions();
+      LOG(DEBUG, "Canceling\n");
+    }
+
+    if (data.IsPressed(kRollersIn)) {
+      intake_power = 10.0;
+      claw_goal_ = 0.0;
+    }
+    if (data.IsPressed(kHorizontalCanRollersIn)) {
+      intake_power = 10.0;
+      claw_goal_ = kHorizontalCanClawAngle;
+    }
+    if (data.IsPressed(kSpit)) {
+      intake_power = -12.0;
+      action_queue_.CancelAllActions();
+    }
+
+    // Toggle button for the claw
+    if (data.PosEdge(kClawToggle)) {
+      claw_rollers_closed_ = !claw_rollers_closed_;
+    }
+
+    /*
+    if (data.IsPressed(kClawClosed)) {
+      claw_rollers_closed_ = true;
+    }
+    */
+
+    // Horizontal can pickup.
+    if (data.PosEdge(kElevatorCanUp)) {
+      actors::HorizontalCanPickupParams params;
+      params.elevator_height = 0.3;
+      params.pickup_angle = 0.80 + kHorizontalCanClawAngle;
+      params.spit_time = 0.01;
+      params.spit_power = -8.0;
+
+      params.suck_time = 0.10;
+      params.suck_power = 10.0;
+
+      params.claw_settle_time = 0.05;
+      params.claw_settle_power = 5.0;
+      params.claw_full_lift_angle = 1.35;
+      params.claw_end_angle = 0.5;
+
+      // End low so we don't drop it.
+      params.elevator_end_height = 0.28;
+      params.arm_end_angle = 0.0;
+      action_queue_.EnqueueAction(
+          actors::MakeHorizontalCanPickupAction(params));
+      fridge_closed_ = true;
+    }
+
+    // -0.942503 arm, 0.374752 elevator
+    // Vertical can pickup.
+    if (data.PosEdge(kCanPickup)) {
+      actors::CanPickupParams params;
+      params.pickup_x = 0.6;
+      params.pickup_y = 0.1;
+      params.lift_height = 0.25;
+      params.pickup_goal_before_move_height = 0.3;
+      params.start_lowering_x = 0.1;
+      // End low so the can is supported.
+      params.before_place_height = 0.4;
+      params.end_height = 0.28;
+      params.end_angle = 0.0;
+      action_queue_.EnqueueAction(actors::MakeCanPickupAction(params));
+      fridge_closed_ = true;
+    }
+
+    if (data.PosEdge(kCanReset)) {
+      action_queue_.CancelAllActions();
+      elevator_goal_ = 0.28;
+      arm_goal_ = 0.0;
+    }
+
+    // Tote chute pull in when button is pressed, pack when done.
+    if (data.IsPressed(kToteChute)) {
+      claw_goal_ = 0.8;
+      intake_power = 6.0;
+    }
+    if (data.NegEdge(kToteChute)) {
+      claw_goal_ = kClawTotePackAngle;
+    }
+
+    if (data.PosEdge(kStackAndLift)) {
+      actors::StackAndLiftParams params;
+      params.stack_params.claw_out_angle = kClawTotePackAngle;
+      params.stack_params.bottom = 0.020;
+      params.stack_params.over_box_before_place_height = 0.39;
+      params.stack_params.arm_clearance = kArmRaiseLowerClearance;
+
+      params.grab_after_stack = true;
+      params.clamp_pause_time = 0.0;
+      params.lift_params.lift_height = kStackUpHeight;
+      params.lift_params.lift_arm = kStackUpArm;
+      params.lift_params.second_lift = false;
+      params.grab_after_lift = true;
+      fridge_closed_ = true;
+
+      action_queue_.EnqueueAction(actors::MakeStackAndLiftAction(params));
+    }
+
+    if (data.PosEdge(kStackAndHold) || data.PosEdge(kSetStackDownAndHold)) {
+      actors::StackAndHoldParams params;
+      params.bottom = 0.020;
+      params.over_box_before_place_height = 0.39;
+
+      params.arm_clearance = kArmRaiseLowerClearance;
+      params.clamp_pause_time = 0.25;
+      params.claw_clamp_angle = kClawTotePackAngle;
+
+      params.hold_height = 0.68;
+      params.claw_out_angle = kClawTotePackAngle;
+
+      if (data.PosEdge(kSetStackDownAndHold)) {
+        params.place_not_stack = true;
+        params.clamp_pause_time = 0.1;
+        //params.claw_clamp_angle = kClawTotePackAngle - 0.5;
+      } else {
+        params.place_not_stack = false;
+      }
+
+      action_queue_.EnqueueAction(actors::MakeStackAndHoldAction(params));
+      fridge_closed_ = true;
+    }
+
+    // TODO(austin): Figure out what action needed to pull the 6th tote into the
+    // claw.
+
+    // Lower the fridge from holding the stack, grab the stack, and then lift.
+    if (data.PosEdge(kHeldToLift)) {
+      actors::HeldToLiftParams params;
+      params.arm_clearance = kArmRaiseLowerClearance;
+      params.clamp_pause_time = 0.1;
+      params.before_lift_settle_time = 0.1;
+      params.bottom_height = 0.020;
+      params.claw_out_angle = kClawStackClearance;
+      params.lift_params.lift_height = kStackUpHeight;
+      params.lift_params.lift_arm = kStackUpArm;
+      params.lift_params.second_lift = false;
+      fridge_closed_ = true;
+
+      action_queue_.EnqueueAction(actors::MakeHeldToLiftAction(params));
+    }
+
+    // Lift the can up.
+    if (data.PosEdge(kCanUp)) {
+      actors::LiftParams params;
+      params.lift_height = 0.68;
+      params.lift_arm = 0.3;
+      params.pack_claw = false;
+      params.pack_claw_angle = 0;
+      params.intermediate_lift_height = 0.37;
+      params.second_lift = true;
+      fridge_closed_ = true;
+
+      action_queue_.EnqueueAction(actors::MakeLiftAction(params));
+    }
+
+    // Pick up a tote from the ground and put it in the bottom of the bot.
+    if (data.PosEdge(kPickup)) {
+      actors::PickupParams params;
+      // TODO(austin): These parameters are coppied into auto right now, need
+      // to dedup...
+
+      // Lift to here initially.
+      params.pickup_angle = 0.9;
+      // Start sucking here
+      params.suck_angle = 0.8;
+      // Go back down to here to finish sucking.
+      params.suck_angle_finish = 0.4;
+      // Pack the box back in here.
+      params.pickup_finish_angle = kClawTotePackAngle;
+      params.intake_time = 0.8;
+      params.intake_voltage = 7.0;
+      action_queue_.EnqueueAction(actors::MakePickupAction(params));
+    }
+
+    // Place stack on a tote in the tray, and grab it.
+    if (data.PosEdge(kStack)) {
+      actors::StackParams params;
+      params.claw_out_angle = kClawTotePackAngle;
+      params.bottom = 0.020;
+      params.only_place = false;
+      params.arm_clearance = kArmRaiseLowerClearance;
+      params.over_box_before_place_height = 0.39;
+      action_queue_.EnqueueAction(actors::MakeStackAction(params));
+      claw_rollers_closed_ = true;
+      fridge_closed_ = true;
+    }
+
+    if (data.PosEdge(kScore)) {
+      action_queue_.EnqueueAction(
+          actors::MakeScoreAction(MakeScoreParams()));
+      fridge_closed_ = false;
+    }
+
+    if (data.PosEdge(kCoopTop)) {
+      action_queue_.EnqueueAction(
+          actors::MakeScoreAction(MakeCoopTopParams(false)));
+    }
+    if (data.PosEdge(kCoopTopRetract)) {
+      action_queue_.EnqueueAction(
+          actors::MakeScoreAction(MakeCoopTopParams(true)));
+      fridge_closed_ = false;
+    }
+
+    if (data.PosEdge(kCoopBottom)) {
+      action_queue_.EnqueueAction(
+          actors::MakeScoreAction(MakeCoopBottomParams(false)));
+    }
+    if (data.PosEdge(kCoopBottomRetract)) {
+      action_queue_.EnqueueAction(
+          actors::MakeScoreAction(MakeCoopBottomParams(true)));
+      fridge_closed_ = false;
+    }
+
+    if (data.PosEdge(kFridgeToggle)) {
+      fridge_closed_ = !fridge_closed_;
+    }
+
+    if (data.PosEdge(ControlBit::kEnabled)) {
+      // If we got enabled, wait for everything to zero.
+      LOG(INFO, "Waiting for zero.\n");
+      waiting_for_zero_ = true;
+    }
+
+    claw_queue.status.FetchLatest();
+    fridge_queue.status.FetchLatest();
+    if (!claw_queue.status.get()) {
+      LOG(ERROR, "Got no claw status packet.\n");
+    }
+    if (!fridge_queue.status.get()) {
+      LOG(ERROR, "Got no fridge status packet.\n");
+    }
+
+    if (claw_queue.status.get() && fridge_queue.status.get() &&
+        claw_queue.status->zeroed && fridge_queue.status->zeroed) {
+      if (waiting_for_zero_) {
+        LOG(INFO, "Zeroed! Starting teleop mode.\n");
+        waiting_for_zero_ = false;
+
+        // Set the initial goals to where we are now.
+        elevator_goal_ = 0.3;
+        arm_goal_ = 0.0;
+        claw_goal_ = 0.6;
+      }
+    } else {
+      waiting_for_zero_ = true;
+    }
+
+    if (!waiting_for_zero_) {
+      if (!action_queue_.Running()) {
+        auto new_fridge_goal = fridge_queue.goal.MakeMessage();
+        new_fridge_goal->max_velocity = elevator_params_.velocity;
+        new_fridge_goal->max_acceleration = elevator_params_.acceleration;
+        new_fridge_goal->profiling_type = 0;
+        new_fridge_goal->height = elevator_goal_;
+        new_fridge_goal->velocity = 0.0;
+        new_fridge_goal->max_angular_velocity = arm_params_.velocity;
+        new_fridge_goal->max_angular_acceleration = arm_params_.acceleration;
+        new_fridge_goal->angle = arm_goal_;
+        new_fridge_goal->angular_velocity = 0.0;
+        new_fridge_goal->grabbers.top_front = fridge_closed_;
+        new_fridge_goal->grabbers.top_back = fridge_closed_;
+        new_fridge_goal->grabbers.bottom_front = fridge_closed_;
+        new_fridge_goal->grabbers.bottom_back = fridge_closed_;
+
+        if (!new_fridge_goal.Send()) {
+          LOG(ERROR, "Sending fridge goal failed.\n");
+        } else {
+          LOG(DEBUG, "sending goals: elevator: %f, arm: %f\n", elevator_goal_,
+              arm_goal_);
+        }
+        if (!claw_queue.goal.MakeWithBuilder()
+                 .angle(claw_goal_)
+                 .rollers_closed(claw_rollers_closed_)
+                 .max_velocity(5.0)
+                 .max_acceleration(6.0)
+                 .intake(intake_power)
+                 .Send()) {
+          LOG(ERROR, "Sending claw goal failed.\n");
+        }
+      }
+    }
+
+    if (action_queue_.Running()) {
+      // If we are running an action, update our goals to the current goals.
+      control_loops::fridge_queue.status.FetchLatest();
+      if (control_loops::fridge_queue.status.get()) {
+        arm_goal_ = control_loops::fridge_queue.status->goal_angle;
+        elevator_goal_ = control_loops::fridge_queue.status->goal_height;
+      } else {
+        LOG(ERROR, "No fridge status!\n");
+      }
+
+      // If we are running an action, update our goals to the current goals.
+      control_loops::claw_queue.status.FetchLatest();
+      if (control_loops::claw_queue.status.get()) {
+        claw_goal_ = control_loops::claw_queue.status->goal_angle;
+      } else {
+        LOG(ERROR, "No claw status!\n");
+      }
+    }
+    action_queue_.Tick();
+    was_running_ = action_queue_.Running();
+  }
+
+ private:
+  void StartAuto() {
+    LOG(INFO, "Starting auto mode\n");
+    ::frc971::autonomous::autonomous.MakeWithBuilder().run_auto(true).Send();
+  }
+
+  void StopAuto() {
+    LOG(INFO, "Stopping auto mode\n");
+    ::frc971::autonomous::autonomous.MakeWithBuilder().run_auto(false).Send();
+  }
+
+  bool was_running_;
+
+  // Previous goals for systems.
+  double elevator_goal_ = 0.2;
+  double arm_goal_ = 0.0;
+  double claw_goal_ = 0.0;
+  bool claw_rollers_closed_ = false;
+  bool fridge_closed_ = false;
+  actors::ProfileParams arm_params_ = kArmMove;
+  actors::ProfileParams elevator_params_ = kElevatorMove;
+
+  // If we're waiting for the subsystems to zero.
+  bool waiting_for_zero_ = true;
+
+  bool auto_running_ = false;
+
+  ::aos::common::actions::ActionQueue action_queue_;
+
+  ::aos::util::SimpleLogInterval no_drivetrain_status_ =
+      ::aos::util::SimpleLogInterval(::aos::time::Time::InSeconds(0.2), WARNING,
+                                     "no drivetrain status");
+};
+
+}  // namespace joysticks
+}  // namespace input
+}  // namespace frc971
+
+int main() {
+  ::aos::Init();
+  ::frc971::input::joysticks::Reader reader;
+  reader.Run();
+  ::aos::Cleanup();
+}
diff --git a/y2015/prime/build.sh b/y2015/prime/build.sh
new file mode 100755
index 0000000..46cff40
--- /dev/null
+++ b/y2015/prime/build.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+cd $(dirname $0)
+
+exec ../../aos/build/build.py $0 prime y2015 prime.gyp "$@"
diff --git a/y2015/prime/compile_loop.sh b/y2015/prime/compile_loop.sh
new file mode 100755
index 0000000..de6b0d3
--- /dev/null
+++ b/y2015/prime/compile_loop.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+# Runs `build.sh all` and then waits for a file to be modified in a loop.
+# Useful for making changes to the code while continuously making sure they
+# compile.
+# Requires the util-linux and inotify-tools packages.
+
+chrt -i -p 0 $$
+ionice -c 3 -p $$
+
+while true; do
+	$(dirname $0)/build.sh all
+	echo 'compile_loop.sh: Waiting for a file modification...' 1>&2
+	inotifywait -e close_write -r aos frc971 bbb_cape
+	echo 'compile_loop.sh: Done waiting for a file modification' 1>&2
+done
diff --git a/y2015/prime/prime.gyp b/y2015/prime/prime.gyp
new file mode 100644
index 0000000..5a8b006
--- /dev/null
+++ b/y2015/prime/prime.gyp
@@ -0,0 +1,41 @@
+{
+  'targets': [
+    {
+      'target_name': 'All',
+      'type': 'none',
+      'dependencies': [
+        '../../frc971/frc971.gyp:All',
+
+        '../control_loops/drivetrain/drivetrain.gyp:drivetrain',
+        '../control_loops/drivetrain/drivetrain.gyp:drivetrain_lib_test',
+        '../control_loops/drivetrain/drivetrain.gyp:replay_drivetrain',
+        '../control_loops/fridge/fridge.gyp:fridge',
+        '../control_loops/fridge/fridge.gyp:fridge_lib_test',
+        '../control_loops/fridge/fridge.gyp:replay_fridge',
+        '../control_loops/claw/claw.gyp:claw',
+        '../control_loops/claw/claw.gyp:claw_lib_test',
+        '../control_loops/claw/claw.gyp:replay_claw',
+        '../autonomous/autonomous.gyp:auto',
+        '../y2015.gyp:joystick_reader',
+        '../http_status/http_status.gyp:http_status',
+        '../util/util.gyp:kinematics_test',
+        '../actors/actors.gyp:binaries',
+      ],
+      'copies': [
+        {
+          'destination': '<(rsync_dir)',
+          'files': [
+            'start_list.txt',
+          ],
+        },
+      ],
+      'conditions': [
+        ['ARCHITECTURE=="arm_frc"', {
+          'dependencies': [
+            '../wpilib/wpilib.gyp:wpilib_interface',
+          ],
+        }],
+      ],
+    },
+  ],
+}
diff --git a/y2015/prime/start_list.txt b/y2015/prime/start_list.txt
new file mode 100644
index 0000000..e4f0a8a
--- /dev/null
+++ b/y2015/prime/start_list.txt
@@ -0,0 +1,18 @@
+can_pickup_action
+joystick_reader
+pickup_action
+score_action
+stack_action
+wpilib_interface
+binary_log_writer
+claw
+fridge
+horizontal_can_pickup_action
+lift_action
+stack_and_lift_action
+stack_and_hold_action
+held_to_lift_action
+drivetrain
+auto
+drivetrain_action
+http_status
diff --git a/y2015/util/kinematics.h b/y2015/util/kinematics.h
new file mode 100644
index 0000000..611012e
--- /dev/null
+++ b/y2015/util/kinematics.h
@@ -0,0 +1,388 @@
+#ifndef Y2015_UTIL_KINEMATICS_H_
+#define Y2015_UTIL_KINEMATICS_H_
+
+#include <cmath>
+#include "Eigen/Dense"
+#include "y2015/constants.h"
+
+namespace aos {
+namespace util {
+
+// A class for performing forward and inverse kinematics on the elevator-arm
+// system. It can calculate where the fridge grabbers will be if the arm and
+// elevator are at a given position, as well as where the arm and elevator
+// should go in order to get the grabbers to a specific location.
+class ElevatorArmKinematics {
+ public:
+  typedef enum {
+    // These specify the particular region that an invalid request was in. Right
+    // is toward the front of the robot, left is toward the back.
+
+    // Request is valid.
+    REGION_VALID = 0,
+    // Request is farther right than the arm can extend.
+    REGION_RIGHT = 1 << 0,
+    // Request is towards the front of the robot but higher than we can extend
+    // with the elevator and the arm.
+    REGION_UPPER_RIGHT = 1 << 1,
+    // We can get the x part of the request, which is towards the front of the
+    // robot, but not the h part, which is too high.
+    REGION_INSIDE_UPPER_RIGHT = 1 << 2,
+    // We can get the x part of the request, which is towards the front of the
+    // robot, but not the h part, which is too low.
+    REGION_INSIDE_LOWER_RIGHT = 1 << 3,
+    // Request is towards the front of the robot but lower than we can extend
+    // with the elevator and the arm.
+    REGION_LOWER_RIGHT = 1 << 4,
+    // Request is farther left than the arm can extend.
+    REGION_LEFT = 1 << 5,
+    // Request is towards the back of the robot but higher than we can extend
+    // with the elevator and the arm.
+    REGION_UPPER_LEFT = 1 << 6,
+    // We can get the x part of the request, which is towards the front of the
+    // robot, but not the h part, which is too high.
+    REGION_INSIDE_UPPER_LEFT = 1 << 7,
+    // We can get the x part of the request, which is towards the back of the
+    // robot, but not the h part, which is too low.
+    REGION_INSIDE_LOWER_LEFT = 1 << 8,
+    // Request is towards the back of the robot but lower than we can extend
+    // with the elevator and the arm.
+    REGION_LOWER_LEFT = 1 << 9,
+    // Request is invalid, but don't know where it is out of range.
+    REGION_UNKNOWN = 1 << 10,
+  } Region;
+
+  class KinematicResult {
+   public:
+    // The elevator height result from an inverse kinematic.
+    double elevator_height;
+    // The arm angle result from an inverse kinematic.
+    double arm_angle;
+    // Resulting velocity of the elevator given x,y velocities.
+    double elevator_velocity;
+    // Resulting velocity of the arm given x,y velocities.
+    double arm_velocity;
+    // The fridge height value from a forward kinematic.
+    double fridge_h;
+    // The fridge x value from a forward kinematic.
+    double fridge_x;
+    // Resulting velocity of the fridge height given arm and elevator
+    // velocities.
+    double fridge_h_velocity;
+    // Resulting velocity of the fridge x given arm and elevator velocities.
+    double fridge_x_velocity;
+  };
+
+  // If we use the default constructor we wil just always not be able to move.
+  ElevatorArmKinematics()
+      : length_arm_(1.0),
+        elevator_max_(0.0),
+        elevator_min_(0.0),
+        upper_angle_limit_(0.0),
+        lower_angle_limit_(0.0) {}
+
+  ElevatorArmKinematics(double length_arm, double height_max, double height_min,
+                        double angle_max, double angle_min)
+      : length_arm_(length_arm),
+        elevator_max_(height_max),
+        elevator_min_(height_min),
+        upper_angle_limit_(angle_max),
+        lower_angle_limit_(angle_min),
+        geometry_(frc971::constants::GetValues().clawGeometry) {}
+
+  ~ElevatorArmKinematics() {}
+
+  // Limit a number to the speed of light. The loops should handle this a lot
+  // better than overflow.
+  void LimitLightSpeed(double* num) {
+    if (*num > 299792458.0) {
+      *num = 299792458.0;
+    }
+    if (*num < -299792458.0) {
+      *num = -299792458.0;
+    }
+    if (!::std::isfinite(*num)) {
+      *num = 0.0;
+    }
+  }
+
+  // Calculates the arm angle in radians and the elevator height in meters for
+  // a desired Fridge grabber height and x location. x is positive going
+  // toward the front of the robot.
+  // h is positive going up. x=0 and h=0 is the location of the top fridge
+  // grabber when the elevator is at 0 height and the arm angle is 0 (vertical).
+  // Both the x and h values are given in meters.
+  // Returns the region of the request.
+  // Result is:
+  // the angle of the arm in radians
+  // the height of the elevator in meters
+  // the resulting x
+  // and the resulting h
+  // If an impossible location is requested, the arm angle and elevator height
+  // returned are the closest possible for the requested fridge grabber height.
+  // If the requested height is above the max possible height, the angle
+  // will be 0 and the height will be the max possible height of the elevator.
+  int InverseKinematic(double request_x, double request_h,
+                       double request_x_velocity, double request_y_velocity,
+                       KinematicResult* result) {
+    int valid_or_invalid = REGION_VALID;
+
+    double square_arm = length_arm_ * length_arm_;
+    double term = ::std::sqrt(square_arm - request_x * request_x);
+
+    // Check to see if the x location can be satisfied.  If the requested x
+    // location
+    // is further out than the arm can go, it is not possible for any elevator
+    // location.
+    if (request_x > length_arm_) {
+      result->arm_angle = -M_PI * 0.5;
+      valid_or_invalid |= REGION_RIGHT;
+    } else if (request_x < -length_arm_) {
+      result->arm_angle = M_PI * 0.5;
+      valid_or_invalid |= REGION_LEFT;
+    } else {
+      result->arm_angle = ::std::asin(-request_x / length_arm_);
+      result->arm_velocity = (-1.0 / term) * request_x_velocity;
+      LimitLightSpeed(&result->arm_velocity);
+    }
+
+    result->elevator_height =
+        request_h + length_arm_ * (1.0 - ::std::cos(result->arm_angle));
+    result->elevator_velocity =
+        (request_x / (square_arm * term)) * request_x_velocity +
+        request_y_velocity;
+    LimitLightSpeed(&result->elevator_velocity);
+
+    // Check to see if the requested elevator height is possible
+    if (request_h > elevator_max_) {
+      // The elevator cannot go high enough with any arm angle to satisfy this
+      // request. So position the elevator at the top and the arm angle set to
+      // vertical.
+      result->elevator_height = elevator_max_;
+      result->arm_angle = 0.0;
+      if (request_x >= 0) {
+        valid_or_invalid |= REGION_UPPER_RIGHT;
+      } else {
+        valid_or_invalid |= REGION_UPPER_LEFT;
+      }
+    } else if (request_h < -length_arm_ + elevator_min_) {
+      // The elevator cannot go low enough with any arm angle to satisfy this
+      // request. So position the elevator at the bottom and the arm angle to
+      // satisfy the x request The elevator will move up as the grabber moves to
+      // the center of the robot when in this part of the motion space.
+      result->elevator_height = elevator_min_;
+      if (request_x >= 0) {
+        valid_or_invalid |= REGION_LOWER_RIGHT;
+      } else {
+        valid_or_invalid |= REGION_LOWER_LEFT;
+      }
+    } else if (result->elevator_height > elevator_max_) {
+      // Impossibly high request.  So get as close to the x request with the
+      // elevator at the top of its range.
+      result->elevator_height = elevator_max_;
+      if (request_x >= 0) {
+        result->arm_angle =
+            -::std::acos((length_arm_ + request_h - elevator_max_) /
+                         length_arm_);
+        valid_or_invalid |= REGION_INSIDE_UPPER_RIGHT;
+      } else {
+        result->arm_angle = ::std::acos(
+            (length_arm_ + request_h - elevator_max_) / length_arm_);
+        valid_or_invalid |= REGION_INSIDE_UPPER_LEFT;
+      }
+    } else if (result->elevator_height < elevator_min_) {
+      // Impossibly low request.  So satisfy the x request with the elevator
+      // at the bottom of its range.
+      // The elevator will move up as the grabber moves to the center of the
+      // robot
+      // when in this part of the motion space.
+      result->elevator_height = elevator_min_;
+      if (request_x >= 0) {
+        valid_or_invalid |= REGION_INSIDE_LOWER_RIGHT;
+      } else {
+        valid_or_invalid |= REGION_INSIDE_LOWER_LEFT;
+      }
+    }
+
+    // if we are not in a valid region we will zero the velocity for now
+    if (valid_or_invalid != REGION_VALID) {
+      result->arm_velocity = 0.0;
+      result->elevator_velocity = 0.0;
+    }
+
+    if (ForwardKinematic(result->elevator_height, result->arm_angle,
+                         result->elevator_velocity, result->arm_velocity,
+                         result) == REGION_UNKNOWN) {
+      return REGION_UNKNOWN;
+    }
+    return valid_or_invalid;
+  }
+
+  // Takes an elevator height and arm angle and projects these to the resulting
+  // fridge height and x offset. Returns REGION_UNKNOWN if the values are
+  // outside
+  // limits. This will result in the height/angle being bounded and the
+  // resulting position will be returned.
+  Region ForwardKinematic(double elevator_height, double arm_angle,
+                          double elevator_velocity, double arm_velocity,
+                          KinematicResult* result) {
+    result->elevator_height = elevator_height;
+    result->arm_angle = arm_angle;
+
+    Region valid = REGION_VALID;
+    if (elevator_height < elevator_min_) {
+      LOG(WARNING, "elevator %.2f limited at %.2f\n", result->elevator_height,
+          elevator_min_);
+      result->elevator_height = elevator_min_;
+      valid = REGION_UNKNOWN;
+    }
+    if (elevator_height > elevator_max_) {
+      LOG(WARNING, "elevator %.2f limited at %.2f\n", result->elevator_height,
+          elevator_max_);
+      result->elevator_height = elevator_max_;
+      valid = REGION_UNKNOWN;
+    }
+    if (arm_angle < lower_angle_limit_) {
+      LOG(WARNING, "arm %.2f limited at %.2f\n", result->arm_angle,
+          lower_angle_limit_);
+      result->arm_angle = lower_angle_limit_;
+      valid = REGION_UNKNOWN;
+    }
+    if (arm_angle > upper_angle_limit_) {
+      result->arm_angle = upper_angle_limit_;
+      LOG(WARNING, "arm %.2f limited at %.2f\n", result->arm_angle,
+          upper_angle_limit_);
+      valid = REGION_UNKNOWN;
+    }
+    // Compute the fridge grabber height and x location using the computed
+    // elevator height and arm angle.
+    result->fridge_h = result->elevator_height +
+                       (::std::cos(result->arm_angle) - 1.0) * length_arm_;
+    result->fridge_x = -::std::sin(result->arm_angle) * length_arm_;
+    // velocity based on joacobian
+    result->fridge_x_velocity =
+        -length_arm_ * ::std::cos(result->arm_angle) * arm_velocity;
+    LimitLightSpeed(&result->fridge_x_velocity);
+    result->fridge_h_velocity =
+        -length_arm_ * ::std::sin(result->arm_angle) * arm_velocity +
+        elevator_velocity;
+    LimitLightSpeed(&result->fridge_h_velocity);
+    return valid;
+  }
+
+  // Same as ForwardKinematic but without any checking.
+  Eigen::Vector2d ForwardKinematicNoChecking(double elevator_height,
+                                             double arm_angle) {
+    // Compute the fridge grabber height and x location using the computed
+    // elevator height and arm angle.
+    Eigen::Vector2d grabber_location;
+    grabber_location.y() =
+        elevator_height + (::std::cos(arm_angle) - 1.0) * length_arm_;
+    grabber_location.x() = -::std::sin(arm_angle) * length_arm_;
+    return grabber_location;
+  }
+
+  // 2 dimensional version of cross product
+  double Cross(Eigen::Vector2d a, Eigen::Vector2d b) {
+    double crossProduct = a.x() * b.y() - a.y() * b.x();
+    return crossProduct;
+  }
+
+  // Tell whether or not it is safe to move the grabber to a position.
+  // Returns true if the current move is safe.
+  // If it returns false then a safe_claw_angle that is greater than zero is
+  // acceptable otherwise if safe_claw_angle is less than zero there will be no
+  // valid solution.
+  bool GrabberArmIntersectionCheck(double elevator_height, double arm_angle,
+                                   double claw_angle, double* safe_claw_angle) {
+    Eigen::Vector2d grabber_location =
+        ForwardKinematicNoChecking(elevator_height, arm_angle);
+    if (grabber_location.x() < geometry_.grabber_always_safe_x_max ||
+        grabber_location.y() > geometry_.grabber_always_safe_h_min) {
+      *safe_claw_angle = claw_angle;
+      return true;
+    }
+    Eigen::Vector2d grabber_bottom_end;
+    Eigen::Vector2d claw_i_unit_direction(::std::cos(claw_angle),
+                                          sin(claw_angle));
+    Eigen::Vector2d claw_j_unit_direction(-::std::sin(claw_angle),
+                                          cos(claw_angle));
+
+    // Vector from the center of the arm rotation axis to front bottom
+    // corner of the grabber.
+    Eigen::Vector2d grabber_end_location_from_arm_axis(
+        geometry_.grabber_half_length, -geometry_.grabber_delta_y);
+
+    // Bottom front corner of the grabber.  This is what will usually hit the
+    // claw first.
+    grabber_bottom_end = grabber_location + grabber_end_location_from_arm_axis;
+
+    // Location of the claw horizontal axis of rotation relative to the
+    // arm axis of rotation with the elevator at 0 and the arm angle of 0
+    // The horizontal axis is the up and down motion axis.
+    Eigen::Vector2d claw_updown_axis(geometry_.grabber_arm_horz_separation,
+                                     -geometry_.grabber_arm_vert_separation);
+
+    // This point is used to make a cross product with the bottom end of the
+    // grabber
+    // The result of the cross product tells if the parts intersect or not.
+    Eigen::Vector2d claw_top_ref_point =
+        claw_updown_axis + geometry_.claw_top_thickness * claw_j_unit_direction;
+
+    Eigen::Vector2d claw_top_ref_point_to_grabber_bottom_end =
+        grabber_bottom_end - claw_top_ref_point;
+    double claw_grabber_check =
+        Cross(claw_i_unit_direction, claw_top_ref_point_to_grabber_bottom_end);
+
+    // Now set the safe claw angle.
+    if (claw_grabber_check > 0.0) {
+      *safe_claw_angle = claw_angle;
+      return true;
+    } else if (grabber_bottom_end.y() <
+               claw_updown_axis.y() +
+                   geometry_.claw_top_thickness) {  // grabber is too close
+      *safe_claw_angle = -1.0;
+      return false;
+    } else {
+      //  To find the safe angle for the claw, draw a line between the claw
+      //  rotation axis and the lower front corner of the grabber.  The angle of
+      //  this line is used with the angle between the edge of the claw and the
+      //  center line of the claw to determine the angle of the claw.
+      Eigen::Vector2d claw_axis_to_grabber_bottom_end =
+          grabber_bottom_end - claw_updown_axis;
+      double hypot = claw_axis_to_grabber_bottom_end.norm();
+      double angleDiff = ::std::asin(geometry_.claw_top_thickness / hypot);
+      *safe_claw_angle = ::std::atan2(claw_axis_to_grabber_bottom_end.y(),
+                                      claw_axis_to_grabber_bottom_end.x()) -
+                         angleDiff;
+      return false;
+    }
+  }
+
+  double get_elevator_min() { return elevator_min_; }
+
+  double get_elevator_max() { return elevator_max_; }
+
+  double get_upper_angle_limit() { return upper_angle_limit_; }
+
+  double get_lower_angle_limit() { return lower_angle_limit_; }
+
+ private:
+  // length of the arm
+  double length_arm_;
+  // max height the elevator can go.
+  double elevator_max_;
+  // min height the elevator can go.
+  double elevator_min_;
+  // arm angle upper limit
+  double upper_angle_limit_;
+  // arm angle lower limit
+  double lower_angle_limit_;
+  // Geometry of the arm + fridge
+  frc971::constants::Values::ClawGeometry geometry_;
+};
+
+}  // namespace util
+}  // namespace aos
+
+#endif  // Y2015_UTIL_KINEMATICS_H_
diff --git a/y2015/util/kinematics_test.cc b/y2015/util/kinematics_test.cc
new file mode 100644
index 0000000..be1645e
--- /dev/null
+++ b/y2015/util/kinematics_test.cc
@@ -0,0 +1,242 @@
+#include <cmath>
+
+#include "gtest/gtest.h"
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/queue_testutils.h"
+#include "y2015/util/kinematics.h"
+#include "frc971/control_loops/team_number_test_environment.h"
+
+namespace aos {
+namespace util {
+namespace testing {
+
+// For verifcation against Mr. Schuh's internal tests.
+// Please do not comment on this in a code review. We can remove this after the
+// season to satisfy any OCD.
+bool k_internal_debug = false;
+
+class KinematicsTest : public ::testing::Test {
+ public:
+  KinematicsTest()
+      : lower_height_limit_(0.01),
+        upper_height_limit_(0.65),
+        lower_angle_limit_(-M_PI / 2.0),
+        upper_angle_limit_(M_PI / 2.0) {}
+
+  void SetUp() {
+      ::aos::common::testing::EnableTestLogging();
+      kinematics_ = ElevatorArmKinematics(arm_length_, upper_height_limit_, lower_height_limit_,
+                    upper_angle_limit_, lower_angle_limit_);
+  }
+
+ protected:
+  double lower_height_limit_;
+  double upper_height_limit_;
+  double lower_angle_limit_;
+  double upper_angle_limit_;
+  double arm_length_ = 0.7366;
+
+  ElevatorArmKinematics kinematics_;
+};
+
+// Used for internal debugging and verification only not acctual testing.
+// Please do not comment on this in a code review. We can remove this after
+// the season to satisfy any OCD.
+TEST_F(KinematicsTest,
+       PrintPointsSoWeCanHandVerifyThemUntilABetterTestIsMadeAndBrianIsHappy) {
+  if (k_internal_debug) {
+    for (double y = -1.0; y <= 1.0; y += 0.2) {
+      for (double x = -1.0; x <= 1.0; x += 0.2) {
+        ElevatorArmKinematics::KinematicResult res;
+        int region = kinematics_.InverseKinematic(x, y, 0.0, 0.0, &res);
+        printf(
+            " %12.3f %12.3f   %8.3f  %9.3f  %8.2f %12d   %12.4f      %10.4f "
+            "%15.4f %16.4f\n",
+            x, y, res.elevator_height, res.arm_angle,
+            res.arm_angle * 180.0 / M_PI, region, res.fridge_x, res.fridge_h,
+            res.fridge_x - x, res.fridge_h - y);
+      }
+    }
+
+    // Make a set of calls to test the grabber arm intersection test code.
+    printf(
+        "#  ArmAngle (degrees) ElevatorHeight  ClawAngle (degrees) GrabberX "
+        "GrabberH intersectReturn SafeClawAngle (degrees)\n");
+    for (double elevator_height = kinematics_.get_elevator_min();
+         elevator_height <= kinematics_.get_elevator_max();
+         elevator_height += 0.10) {
+      for (double arm_angle = kinematics_.get_lower_angle_limit();
+           arm_angle <= kinematics_.get_upper_angle_limit() + 0.01;
+           arm_angle += M_PI * 0.5 / 9.0) {
+        double claw_angle = M_PI * 0.25;
+        double safe_claw_angle;
+        double intersectReturnValue = kinematics_.GrabberArmIntersectionCheck(
+            elevator_height, arm_angle, claw_angle, &safe_claw_angle);
+        Eigen::Vector2d grabber_location =
+            kinematics_.ForwardKinematicNoChecking(elevator_height, arm_angle);
+
+        printf(
+            "  %8.4f %8.2f   %8.2f %14.4f %9.2f %9.2f %9.2f %10.3f  %13.4f "
+            "%12.3f\n",
+            arm_angle, arm_angle * 180.0 / M_PI, elevator_height, claw_angle,
+            claw_angle * 180.0 / M_PI, grabber_location.x(),
+            grabber_location.y(), intersectReturnValue, safe_claw_angle,
+            safe_claw_angle * 180.0 / M_PI);
+      }
+      printf("\n");
+    }
+  }
+}
+
+TEST_F(KinematicsTest, ValidIntersectCheckPointAtBottomOfElevatorRange) {
+  double safe_claw_angle;
+  double elevator_height = 0.01;
+  double arm_angle = 30.0 * M_PI / 180.0;
+  double claw_angle = M_PI * 0.25;
+  bool intersectReturnValue = kinematics_.GrabberArmIntersectionCheck(
+      elevator_height, arm_angle, claw_angle, &safe_claw_angle);
+  EXPECT_TRUE(intersectReturnValue);
+  EXPECT_EQ(safe_claw_angle, claw_angle);
+}
+
+TEST_F(KinematicsTest, ValidIntersectCheckPointAtMiddleOfElevatorRange) {
+  double safe_claw_angle;
+  double elevator_height = 0.4;
+  double arm_angle = 30.0 * M_PI / 180.0;
+  double claw_angle = M_PI * 0.25;
+  bool intersectReturnValue = kinematics_.GrabberArmIntersectionCheck(
+      elevator_height, arm_angle, claw_angle, &safe_claw_angle);
+  EXPECT_TRUE(intersectReturnValue);
+  EXPECT_EQ(safe_claw_angle, claw_angle);
+}
+
+TEST_F(KinematicsTest,
+       invalidIntersectCheckPointAtBottomOfElevatorRangeWithSafeClawAngle) {
+  double safe_claw_angle;
+  double elevator_height = 0.01;
+  double arm_angle = -20.0 * M_PI / 180.0;
+  double claw_angle = M_PI * 0.25;
+  bool intersectReturnValue = kinematics_.GrabberArmIntersectionCheck(
+      elevator_height, arm_angle, claw_angle, &safe_claw_angle);
+  EXPECT_FALSE(intersectReturnValue);
+  EXPECT_NEAR(safe_claw_angle, 0.0435733, 0.000001);
+}
+
+TEST_F(KinematicsTest,
+       invalidIntersectCheckPointAtMiddleOfElevatorRangeWithSafeClawAngle) {
+  double safe_claw_angle;
+  double elevator_height = 0.41;
+  double arm_angle = -60.0 * M_PI / 180.0;
+  double claw_angle = M_PI * 0.25;
+  bool intersectReturnValue = kinematics_.GrabberArmIntersectionCheck(
+      elevator_height, arm_angle, claw_angle, &safe_claw_angle);
+  EXPECT_FALSE(intersectReturnValue);
+  EXPECT_NEAR(safe_claw_angle, 0.12655341, 0.000001);
+}
+
+TEST_F(KinematicsTest,
+       invalidIntersectCheckPointAtBottomOfElevatorRangeNoSafeClawAngle) {
+  double safe_claw_angle;
+  double elevator_height = 0.01;
+  double arm_angle = -30.0 * M_PI / 180.0;
+  double claw_angle = M_PI * 0.25;
+  bool intersectReturnValue = kinematics_.GrabberArmIntersectionCheck(
+      elevator_height, arm_angle, claw_angle, &safe_claw_angle);
+  EXPECT_FALSE(intersectReturnValue);
+  EXPECT_EQ(safe_claw_angle, -1.0);
+}
+
+TEST_F(KinematicsTest,
+       invalidIntersectCheckPointAtMiddleOfElevatorRangeNoSafeClawAngle) {
+  double safe_claw_angle;
+  double elevator_height = 0.41;
+  double arm_angle = -70.0 * M_PI / 180.0;
+  double claw_angle = M_PI * 0.25;
+  bool intersectReturnValue = kinematics_.GrabberArmIntersectionCheck(
+      elevator_height, arm_angle, claw_angle, &safe_claw_angle);
+  EXPECT_FALSE(intersectReturnValue);
+  EXPECT_EQ(safe_claw_angle, -1.0);
+}
+
+// Tests that velocity calulations are correct
+TEST_F(KinematicsTest, InverseKinematicVelocity) {
+  ElevatorArmKinematics::KinematicResult result;
+  // move striaght up and verify that only hieght changes
+  EXPECT_EQ(0, kinematics_.InverseKinematic(0.0, 0.2, 0.0, 0.7, &result));
+  EXPECT_NEAR(0.0, result.arm_velocity, 0.00001);
+  EXPECT_NEAR(0.7, result.elevator_velocity, 0.00001);
+  // check the negative
+  EXPECT_EQ(0, kinematics_.InverseKinematic(0.0, 0.2, 0.0, -0.7, &result));
+  EXPECT_NEAR(0.0, result.arm_velocity, 0.00001);
+  EXPECT_NEAR(-0.7, result.elevator_velocity, 0.00001);
+  // even with the arm out we should still just move up
+  EXPECT_EQ(0, kinematics_.InverseKinematic(M_PI / 6, 0.2, 0.0, 0.7, &result));
+  EXPECT_NEAR(0.0, result.arm_velocity, 0.00001);
+  EXPECT_NEAR(0.7, result.elevator_velocity, 0.00001);
+  // even with the arm back we should still just move up
+  EXPECT_EQ(0, kinematics_.InverseKinematic(-M_PI / 6, 0.2, 0.0, 0.7, &result));
+  EXPECT_NEAR(0.0, result.arm_velocity, 0.00001);
+  EXPECT_NEAR(0.7, result.elevator_velocity, 0.00001);
+
+  // should move only angle forward
+  EXPECT_EQ(0, kinematics_.InverseKinematic(0.0, 0.2, 1.0, 0.0, &result));
+  EXPECT_NEAR(-1.35759, result.arm_velocity, 0.00001);
+  EXPECT_NEAR(0.0, result.elevator_velocity, 0.00001);
+  // check the negative
+  EXPECT_EQ(0, kinematics_.InverseKinematic(0.0, 0.2, -1.0, 0.0, &result));
+  EXPECT_NEAR(1.35759, result.arm_velocity, 0.00001);
+  EXPECT_NEAR(0.0, result.elevator_velocity, 0.00001);
+  // with the arm out a change in x should make arm angle greater and
+  // bring the evevator down.
+  EXPECT_EQ(0, kinematics_.InverseKinematic(0.2, 0.2, 1.0, 0.0, &result));
+  EXPECT_GT(0.0, result.arm_velocity);
+  EXPECT_LT(0.0, result.elevator_velocity);
+  // with the arm out a change in x should make arm angle greater and
+  // bring the evevator down.
+  EXPECT_EQ(0, kinematics_.InverseKinematic(-0.2, 0.2, 1.0, 0.0, &result));
+  EXPECT_GT(0.0, result.arm_velocity);
+  EXPECT_GT(0.0, result.elevator_velocity);
+}
+
+// Tests that velocity calulations are correct
+TEST_F(KinematicsTest, ForwardKinematicVelocity) {
+  ElevatorArmKinematics::KinematicResult result;
+
+  // moving the arm forward at zero should result in x velocity
+  EXPECT_EQ(0, kinematics_.ForwardKinematic(0.2, 0.0, 0.0, 1.35759, &result));
+  EXPECT_NEAR(-1.0, result.fridge_x_velocity, 0.00001);
+  EXPECT_NEAR(0.0, result.fridge_h_velocity, 0.00001);
+  // check the negative
+  EXPECT_EQ(0, kinematics_.ForwardKinematic(0.2, 0.0, 0.0, -1.35759, &result));
+  EXPECT_NEAR(1.0, result.fridge_x_velocity, 0.00001);
+  EXPECT_NEAR(0.0, result.fridge_h_velocity, 0.00001);
+  // moving the arm up at zero should result in h velocity
+  EXPECT_EQ(0, kinematics_.ForwardKinematic(0.2, 0.0, 1.0, 0.0, &result));
+  EXPECT_NEAR(0.0, result.fridge_x_velocity, 0.00001);
+  EXPECT_NEAR(1.0, result.fridge_h_velocity, 0.00001);
+  // check the negative
+  EXPECT_EQ(0, kinematics_.ForwardKinematic(0.2, 0.0, -1.0, 0.0, &result));
+  EXPECT_NEAR(0.0, result.fridge_x_velocity, 0.00001);
+  EXPECT_NEAR(-1.0, result.fridge_h_velocity, 0.00001);
+  // arm is forward a negative angle should make x head forward and y head down.
+  EXPECT_EQ(0, kinematics_.ForwardKinematic(0.5, -0.2, 0.0, -1.0, &result));
+  EXPECT_GT(result.fridge_x_velocity, 0.0);
+  EXPECT_LT(result.fridge_h_velocity, 0.0);
+  // arm is forward a positive angle should make x head backwardward and y head up.
+  EXPECT_EQ(0, kinematics_.ForwardKinematic(0.5, -0.2, 0.0, 1.0, &result));
+  EXPECT_LT(result.fridge_x_velocity, 0.0);
+  EXPECT_GT(result.fridge_h_velocity, 0.0);
+  // arm is backward a negative angle should make x head forward and y head down.
+  EXPECT_EQ(0, kinematics_.ForwardKinematic(0.5, 0.2, 0.0, -1.0, &result));
+  EXPECT_GT(result.fridge_x_velocity, 0.0);
+  EXPECT_GT(result.fridge_h_velocity, 0.0);
+  // arm is backward a negative angle should make x head forward and y head down.
+  EXPECT_EQ(0, kinematics_.ForwardKinematic(0.5, 0.2, 0.0, 1.0, &result));
+  EXPECT_LT(result.fridge_x_velocity, 0.0);
+  EXPECT_LT(result.fridge_h_velocity, 0.0);
+}
+
+}  // namespace testing
+}  // namespace util
+}  // namespace aos
diff --git a/y2015/util/util.gyp b/y2015/util/util.gyp
new file mode 100644
index 0000000..00079c1
--- /dev/null
+++ b/y2015/util/util.gyp
@@ -0,0 +1,33 @@
+{
+  'targets': [
+    {
+      'target_name': 'kinematics',
+      'type': 'static_library',
+      'sources': [
+        #'kinematics.h',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):eigen',
+        '<(DEPTH)/y2015/y2015.gyp:constants',
+      ],
+      'export_dependent_settings': [
+        '<(EXTERNALS):eigen',
+        '<(DEPTH)/y2015/y2015.gyp:constants',
+      ],
+    },
+    {
+      'target_name': 'kinematics_test',
+      'type': 'executable',
+      'sources': [
+        'kinematics_test.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+        '<(AOS)/common/common.gyp:queue_testutils',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:team_number_test_environment',
+        'kinematics'
+      ],
+    },
+  ],
+}
diff --git a/y2015/wpilib/wpilib.gyp b/y2015/wpilib/wpilib.gyp
new file mode 100644
index 0000000..8c1be39
--- /dev/null
+++ b/y2015/wpilib/wpilib.gyp
@@ -0,0 +1,38 @@
+{
+  'targets': [
+    {
+      'target_name': 'wpilib_interface',
+      'type': 'executable',
+      'sources': [
+        'wpilib_interface.cc'
+      ],
+      'dependencies': [
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(AOS)/common/common.gyp:stl_mutex',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(EXTERNALS):WPILib',
+        '<(DEPTH)/y2015/y2015.gyp:constants',
+        '<(DEPTH)/y2015/control_loops/drivetrain/drivetrain.gyp:drivetrain_queue',
+        '<(DEPTH)/y2015/control_loops/fridge/fridge.gyp:fridge_queue',
+        '<(DEPTH)/y2015/control_loops/claw/claw.gyp:claw_queue',
+        '<(AOS)/common/controls/controls.gyp:control_loop',
+        '<(AOS)/common/util/util.gyp:log_interval',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/common/logging/logging.gyp:queue_logging',
+        '<(AOS)/common/messages/messages.gyp:robot_state',
+        '<(AOS)/common/util/util.gyp:phased_loop',
+        '<(AOS)/common/messages/messages.gyp:robot_state',
+        '<(DEPTH)/frc971/wpilib/wpilib.gyp:hall_effect',
+        '<(DEPTH)/frc971/wpilib/wpilib.gyp:joystick_sender',
+        '<(DEPTH)/frc971/wpilib/wpilib.gyp:loop_output_handler',
+        '<(DEPTH)/frc971/wpilib/wpilib.gyp:buffered_pcm',
+        '<(DEPTH)/frc971/wpilib/wpilib.gyp:gyro_sender',
+        '<(DEPTH)/frc971/wpilib/wpilib.gyp:dma_edge_counting',
+        '<(DEPTH)/frc971/wpilib/wpilib.gyp:interrupt_edge_counting',
+        '<(DEPTH)/frc971/wpilib/wpilib.gyp:encoder_and_potentiometer',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:queues',
+        '<(DEPTH)/frc971/wpilib/wpilib.gyp:logging_queue',
+      ],
+    },
+  ],
+}
diff --git a/y2015/wpilib/wpilib_interface.cc b/y2015/wpilib/wpilib_interface.cc
new file mode 100644
index 0000000..ff836a1
--- /dev/null
+++ b/y2015/wpilib/wpilib_interface.cc
@@ -0,0 +1,716 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <thread>
+#include <mutex>
+#include <functional>
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/logging/queue_logging.h"
+#include "aos/common/time.h"
+#include "aos/common/util/log_interval.h"
+#include "aos/common/util/phased_loop.h"
+#include "aos/common/util/wrapping_counter.h"
+#include "aos/common/stl_mutex.h"
+#include "aos/linux_code/init.h"
+#include "aos/common/messages/robot_state.q.h"
+
+#include "y2015/constants.h"
+#include "frc971/control_loops/control_loops.q.h"
+#include "y2015/control_loops/drivetrain/drivetrain.q.h"
+#include "y2015/control_loops/fridge/fridge.q.h"
+#include "y2015/control_loops/claw/claw.q.h"
+
+#include "frc971/wpilib/hall_effect.h"
+#include "frc971/wpilib/joystick_sender.h"
+#include "frc971/wpilib/loop_output_handler.h"
+#include "frc971/wpilib/buffered_solenoid.h"
+#include "frc971/wpilib/buffered_pcm.h"
+#include "frc971/wpilib/gyro_sender.h"
+#include "frc971/wpilib/dma_edge_counting.h"
+#include "frc971/wpilib/interrupt_edge_counting.h"
+#include "frc971/wpilib/encoder_and_potentiometer.h"
+#include "frc971/wpilib/logging.q.h"
+
+#include "Encoder.h"
+#include "Talon.h"
+#include "DriverStation.h"
+#include "AnalogInput.h"
+#include "Compressor.h"
+#include "Relay.h"
+#include "RobotBase.h"
+#include "dma.h"
+#include "ControllerPower.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+using ::aos::util::SimpleLogInterval;
+using ::frc971::control_loops::drivetrain_queue;
+using ::frc971::control_loops::fridge_queue;
+using ::frc971::control_loops::claw_queue;
+
+namespace frc971 {
+namespace wpilib {
+
+double drivetrain_translate(int32_t in) {
+  return static_cast<double>(in) /
+         (256.0 /*cpr*/ * 4.0 /*4x*/) *
+         constants::GetValues().drivetrain_encoder_ratio *
+         (4 /*wheel diameter*/ * 2.54 / 100.0 * M_PI);
+}
+
+double arm_translate(int32_t in) {
+  return -static_cast<double>(in) /
+          (512.0 /*cpr*/ * 4.0 /*4x*/) *
+          constants::GetValues().arm_encoder_ratio *
+          (2 * M_PI /*radians*/);
+}
+
+double arm_potentiometer_translate(double voltage) {
+  return voltage *
+          constants::GetValues().arm_pot_ratio *
+          (5.0 /*turns*/ / 5.0 /*volts*/) *
+          (2 * M_PI /*radians*/);
+}
+
+double elevator_translate(int32_t in) {
+  return static_cast<double>(in) /
+          (512.0 /*cpr*/ * 4.0 /*4x*/) *
+          constants::GetValues().elev_encoder_ratio *
+          (2 * M_PI /*radians*/) *
+          constants::GetValues().elev_distance_per_radian;
+}
+
+double elevator_potentiometer_translate(double voltage) {
+  return -voltage *
+          constants::GetValues().elev_pot_ratio *
+          (2 * M_PI /*radians*/) *
+          constants::GetValues().elev_distance_per_radian *
+          (5.0 /*turns*/ / 5.0 /*volts*/);
+}
+
+double claw_translate(int32_t in) {
+  return static_cast<double>(in) /
+          (512.0 /*cpr*/ * 4.0 /*4x*/) *
+          constants::GetValues().claw_encoder_ratio *
+          (2 * M_PI /*radians*/);
+}
+
+double claw_potentiometer_translate(double voltage) {
+  return -voltage *
+          constants::GetValues().claw_pot_ratio *
+          (5.0 /*turns*/ / 5.0 /*volts*/) *
+          (2 * M_PI /*radians*/);
+}
+
+static const double kMaximumEncoderPulsesPerSecond =
+    19500.0 /* free speed RPM */ * 12.0 / 56.0 /* belt reduction */ /
+    60.0 /* seconds / minute */ * 256.0 /* CPR */ *
+    4.0 /* index pulse = 1/4 cycle */;
+
+class SensorReader {
+ public:
+  SensorReader() {
+    // Set it to filter out anything shorter than 1/4 of the minimum pulse width
+    // we should ever see.
+    filter_.SetPeriodNanoSeconds(
+        static_cast<int>(1 / 4.0 / kMaximumEncoderPulsesPerSecond * 1e9 + 0.5));
+  }
+
+  void set_arm_left_encoder(::std::unique_ptr<Encoder> encoder) {
+    filter_.Add(encoder.get());
+    arm_left_encoder_.set_encoder(::std::move(encoder));
+  }
+
+  void set_arm_left_index(::std::unique_ptr<DigitalSource> index) {
+    filter_.Add(index.get());
+    arm_left_encoder_.set_index(::std::move(index));
+  }
+
+  void set_arm_left_potentiometer(
+      ::std::unique_ptr<AnalogInput> potentiometer) {
+    arm_left_encoder_.set_potentiometer(::std::move(potentiometer));
+  }
+
+  void set_arm_right_encoder(::std::unique_ptr<Encoder> encoder) {
+    filter_.Add(encoder.get());
+    arm_right_encoder_.set_encoder(::std::move(encoder));
+  }
+
+  void set_arm_right_index(::std::unique_ptr<DigitalSource> index) {
+    filter_.Add(index.get());
+    arm_right_encoder_.set_index(::std::move(index));
+  }
+
+  void set_arm_right_potentiometer(
+      ::std::unique_ptr<AnalogInput> potentiometer) {
+    arm_right_encoder_.set_potentiometer(::std::move(potentiometer));
+  }
+
+  void set_elevator_left_encoder(::std::unique_ptr<Encoder> encoder) {
+    filter_.Add(encoder.get());
+    elevator_left_encoder_.set_encoder(::std::move(encoder));
+  }
+
+  void set_elevator_left_index(::std::unique_ptr<DigitalSource> index) {
+    filter_.Add(index.get());
+    elevator_left_encoder_.set_index(::std::move(index));
+  }
+
+  void set_elevator_left_potentiometer(
+      ::std::unique_ptr<AnalogInput> potentiometer) {
+    elevator_left_encoder_.set_potentiometer(::std::move(potentiometer));
+  }
+
+  void set_elevator_right_encoder(::std::unique_ptr<Encoder> encoder) {
+    filter_.Add(encoder.get());
+    elevator_right_encoder_.set_encoder(::std::move(encoder));
+  }
+
+  void set_elevator_right_index(::std::unique_ptr<DigitalSource> index) {
+    filter_.Add(index.get());
+    elevator_right_encoder_.set_index(::std::move(index));
+  }
+
+  void set_elevator_right_potentiometer(
+      ::std::unique_ptr<AnalogInput> potentiometer) {
+    elevator_right_encoder_.set_potentiometer(::std::move(potentiometer));
+  }
+
+  void set_wrist_encoder(::std::unique_ptr<Encoder> encoder) {
+    filter_.Add(encoder.get());
+    wrist_encoder_.set_encoder(::std::move(encoder));
+  }
+
+  void set_wrist_index(::std::unique_ptr<DigitalSource> index) {
+    filter_.Add(index.get());
+    wrist_encoder_.set_index(::std::move(index));
+  }
+
+  void set_wrist_potentiometer(::std::unique_ptr<AnalogInput> potentiometer) {
+    wrist_encoder_.set_potentiometer(::std::move(potentiometer));
+  }
+
+  void set_left_encoder(::std::unique_ptr<Encoder> left_encoder) {
+    left_encoder_ = ::std::move(left_encoder);
+  }
+
+  void set_right_encoder(::std::unique_ptr<Encoder> right_encoder) {
+    right_encoder_ = ::std::move(right_encoder);
+  }
+
+  // All of the DMA-related set_* calls must be made before this, and it doesn't
+  // hurt to do all of them.
+  void set_dma(::std::unique_ptr<DMA> dma) {
+    dma_synchronizer_.reset(new DMASynchronizer(::std::move(dma)));
+    dma_synchronizer_->Add(&arm_left_encoder_);
+    dma_synchronizer_->Add(&elevator_left_encoder_);
+    dma_synchronizer_->Add(&arm_right_encoder_);
+    dma_synchronizer_->Add(&elevator_right_encoder_);
+  }
+
+  void operator()() {
+    LOG(INFO, "In sensor reader thread\n");
+    ::aos::SetCurrentThreadName("SensorReader");
+
+    my_pid_ = getpid();
+    ds_ = DriverStation::GetInstance();
+
+    wrist_encoder_.Start();
+    dma_synchronizer_->Start();
+    LOG(INFO, "Things are now started\n");
+
+    ::aos::SetCurrentThreadRealtimePriority(kPriority);
+    while (run_) {
+      ::aos::time::PhasedLoopXMS(5, 4000);
+      RunIteration();
+    }
+
+    wrist_encoder_.Stop();
+  }
+
+  void RunIteration() {
+    {
+      auto new_state = ::aos::robot_state.MakeMessage();
+
+      new_state->reader_pid = my_pid_;
+      new_state->outputs_enabled = ds_->IsSysActive();
+      new_state->browned_out = ds_->IsSysBrownedOut();
+
+      new_state->is_3v3_active = ControllerPower::GetEnabled3V3();
+      new_state->is_5v_active = ControllerPower::GetEnabled5V();
+      new_state->voltage_3v3 = ControllerPower::GetVoltage3V3();
+      new_state->voltage_5v = ControllerPower::GetVoltage5V();
+
+      new_state->voltage_roborio_in = ControllerPower::GetInputVoltage();
+      new_state->voltage_battery = ds_->GetBatteryVoltage();
+
+      LOG_STRUCT(DEBUG, "robot_state", *new_state);
+
+      new_state.Send();
+    }
+
+    {
+      auto drivetrain_message = drivetrain_queue.position.MakeMessage();
+      drivetrain_message->right_encoder =
+          -drivetrain_translate(right_encoder_->GetRaw());
+      drivetrain_message->left_encoder =
+          drivetrain_translate(left_encoder_->GetRaw());
+
+      drivetrain_message.Send();
+    }
+
+    dma_synchronizer_->RunIteration();
+
+    const auto &values = constants::GetValues();
+
+    {
+      auto fridge_message = fridge_queue.position.MakeMessage();
+      CopyPotAndIndexPosition(arm_left_encoder_, &fridge_message->arm.left,
+                              arm_translate, arm_potentiometer_translate, false,
+                              values.fridge.left_arm_potentiometer_offset);
+      CopyPotAndIndexPosition(
+          arm_right_encoder_, &fridge_message->arm.right, arm_translate,
+          arm_potentiometer_translate, true,
+          values.fridge.right_arm_potentiometer_offset);
+      CopyPotAndIndexPosition(
+          elevator_left_encoder_, &fridge_message->elevator.left,
+          elevator_translate, elevator_potentiometer_translate, false,
+          values.fridge.left_elevator_potentiometer_offset);
+      CopyPotAndIndexPosition(
+          elevator_right_encoder_, &fridge_message->elevator.right,
+          elevator_translate, elevator_potentiometer_translate, true,
+          values.fridge.right_elevator_potentiometer_offset);
+      fridge_message.Send();
+    }
+
+    {
+      auto claw_message = claw_queue.position.MakeMessage();
+      CopyPotAndIndexPosition(wrist_encoder_, &claw_message->joint,
+                              claw_translate, claw_potentiometer_translate,
+                              false, values.claw.potentiometer_offset);
+      claw_message.Send();
+    }
+  }
+
+  void Quit() { run_ = false; }
+
+ private:
+  static const int kPriority = 30;
+  static const int kInterruptPriority = 55;
+
+  int32_t my_pid_;
+  DriverStation *ds_;
+
+  void CopyPotAndIndexPosition(
+      const DMAEncoderAndPotentiometer &encoder, PotAndIndexPosition *position,
+      ::std::function<double(int32_t)> encoder_translate,
+      ::std::function<double(double)> potentiometer_translate, bool reverse,
+      double potentiometer_offset) {
+    const double multiplier = reverse ? -1.0 : 1.0;
+    position->encoder =
+        multiplier * encoder_translate(encoder.polled_encoder_value());
+    position->pot = multiplier * potentiometer_translate(
+                                     encoder.polled_potentiometer_voltage()) +
+                    potentiometer_offset;
+    position->latched_encoder =
+        multiplier * encoder_translate(encoder.last_encoder_value());
+    position->latched_pot =
+        multiplier *
+            potentiometer_translate(encoder.last_potentiometer_voltage()) +
+        potentiometer_offset;
+    position->index_pulses = encoder.index_posedge_count();
+  }
+
+  void CopyPotAndIndexPosition(
+      const InterruptEncoderAndPotentiometer &encoder,
+      PotAndIndexPosition *position,
+      ::std::function<double(int32_t)> encoder_translate,
+      ::std::function<double(double)> potentiometer_translate, bool reverse,
+      double potentiometer_offset) {
+    const double multiplier = reverse ? -1.0 : 1.0;
+    position->encoder =
+        multiplier * encoder_translate(encoder.encoder()->GetRaw());
+    position->pot = multiplier * potentiometer_translate(
+                                     encoder.potentiometer()->GetVoltage()) +
+                    potentiometer_offset;
+    position->latched_encoder =
+        multiplier * encoder_translate(encoder.last_encoder_value());
+    position->latched_pot =
+        multiplier *
+            potentiometer_translate(encoder.last_potentiometer_voltage()) +
+        potentiometer_offset;
+    position->index_pulses = encoder.index_posedge_count();
+  }
+
+  ::std::unique_ptr<DMASynchronizer> dma_synchronizer_;
+
+  DMAEncoderAndPotentiometer arm_left_encoder_, arm_right_encoder_,
+      elevator_left_encoder_, elevator_right_encoder_;
+
+  InterruptEncoderAndPotentiometer wrist_encoder_{kInterruptPriority};
+
+  ::std::unique_ptr<Encoder> left_encoder_;
+  ::std::unique_ptr<Encoder> right_encoder_;
+
+  ::std::atomic<bool> run_{true};
+  DigitalGlitchFilter filter_;
+};
+
+class SolenoidWriter {
+ public:
+  SolenoidWriter(const ::std::unique_ptr<BufferedPcm> &pcm)
+      : pcm_(pcm),
+        fridge_(".frc971.control_loops.fridge_queue.output"),
+        claw_(".frc971.control_loops.claw_queue.output") {}
+
+  void set_pressure_switch(::std::unique_ptr<DigitalSource> pressure_switch) {
+    pressure_switch_ = ::std::move(pressure_switch);
+  }
+
+  void set_compressor_relay(::std::unique_ptr<Relay> compressor_relay) {
+    compressor_relay_ = ::std::move(compressor_relay);
+  }
+
+  void set_fridge_grabbers_top_front(::std::unique_ptr<BufferedSolenoid> s) {
+    fridge_grabbers_top_front_ = ::std::move(s);
+  }
+
+  void set_fridge_grabbers_top_back(::std::unique_ptr<BufferedSolenoid> s) {
+    fridge_grabbers_top_back_ = ::std::move(s);
+  }
+
+  void set_fridge_grabbers_bottom_front(
+      ::std::unique_ptr<BufferedSolenoid> s) {
+    fridge_grabbers_bottom_front_ = ::std::move(s);
+  }
+
+  void set_fridge_grabbers_bottom_back(
+      ::std::unique_ptr<BufferedSolenoid> s) {
+    fridge_grabbers_bottom_back_ = ::std::move(s);
+  }
+
+  void set_claw_pinchers(::std::unique_ptr<BufferedSolenoid> s) {
+    claw_pinchers_ = ::std::move(s);
+  }
+
+  void set_grabber_latch_release(::std::unique_ptr<BufferedSolenoid> s) {
+    grabber_latch_release_ = ::std::move(s);
+  }
+
+  void set_grabber_fold_up(::std::unique_ptr<BufferedSolenoid> s) {
+    grabber_fold_up_ = ::std::move(s);
+  }
+
+  void operator()() {
+    ::aos::SetCurrentThreadName("Solenoids");
+    ::aos::SetCurrentThreadRealtimePriority(30);
+
+    while (run_) {
+      ::aos::time::PhasedLoopXMS(20, 1000);
+
+      {
+        fridge_.FetchLatest();
+        if (fridge_.get()) {
+          LOG_STRUCT(DEBUG, "solenoids", *fridge_);
+          fridge_grabbers_top_front_->Set(!fridge_->grabbers.top_front);
+          fridge_grabbers_top_back_->Set(!fridge_->grabbers.top_back);
+          fridge_grabbers_bottom_front_->Set(!fridge_->grabbers.bottom_front);
+          fridge_grabbers_bottom_back_->Set(!fridge_->grabbers.bottom_back);
+        }
+      }
+
+      {
+        claw_.FetchLatest();
+        if (claw_.get()) {
+          LOG_STRUCT(DEBUG, "solenoids", *claw_);
+          claw_pinchers_->Set(claw_->rollers_closed);
+        }
+      }
+
+      ::aos::joystick_state.FetchLatest();
+      grabber_latch_release_->Set(::aos::joystick_state.get() != nullptr &&
+                                  ::aos::joystick_state->autonomous);
+      grabber_fold_up_->Set(::aos::joystick_state.get() != nullptr &&
+                            ::aos::joystick_state->joysticks[1].buttons & 1);
+
+      {
+        PneumaticsToLog to_log;
+        {
+          const bool compressor_on = !pressure_switch_->Get();
+          to_log.compressor_on = compressor_on;
+          if (compressor_on) {
+            compressor_relay_->Set(Relay::kForward);
+          } else {
+            compressor_relay_->Set(Relay::kOff);
+          }
+        }
+
+        pcm_->Flush();
+        to_log.read_solenoids = pcm_->GetAll();
+        LOG_STRUCT(DEBUG, "pneumatics info", to_log);
+      }
+    }
+  }
+
+  void Quit() { run_ = false; }
+
+ private:
+  const ::std::unique_ptr<BufferedPcm> &pcm_;
+  ::std::unique_ptr<BufferedSolenoid> fridge_grabbers_top_front_;
+  ::std::unique_ptr<BufferedSolenoid> fridge_grabbers_top_back_;
+  ::std::unique_ptr<BufferedSolenoid> fridge_grabbers_bottom_front_;
+  ::std::unique_ptr<BufferedSolenoid> fridge_grabbers_bottom_back_;
+  ::std::unique_ptr<BufferedSolenoid> claw_pinchers_;
+  ::std::unique_ptr<BufferedSolenoid> grabber_latch_release_;
+  ::std::unique_ptr<BufferedSolenoid> grabber_fold_up_;
+  ::std::unique_ptr<DigitalSource> pressure_switch_;
+  ::std::unique_ptr<Relay> compressor_relay_;
+
+  ::aos::Queue<::frc971::control_loops::FridgeQueue::Output> fridge_;
+  ::aos::Queue<::frc971::control_loops::ClawQueue::Output> claw_;
+
+  ::std::atomic<bool> run_{true};
+};
+
+class DrivetrainWriter : public LoopOutputHandler {
+ public:
+  void set_left_drivetrain_talon(::std::unique_ptr<Talon> t) {
+    left_drivetrain_talon_ = ::std::move(t);
+  }
+
+  void set_right_drivetrain_talon(::std::unique_ptr<Talon> t) {
+    right_drivetrain_talon_ = ::std::move(t);
+  }
+
+ private:
+  virtual void Read() override {
+    ::frc971::control_loops::drivetrain_queue.output.FetchAnother();
+  }
+
+  virtual void Write() override {
+    auto &queue = ::frc971::control_loops::drivetrain_queue.output;
+    LOG_STRUCT(DEBUG, "will output", *queue);
+    left_drivetrain_talon_->Set(queue->left_voltage / 12.0);
+    right_drivetrain_talon_->Set(-queue->right_voltage / 12.0);
+  }
+
+  virtual void Stop() override {
+    LOG(WARNING, "drivetrain output too old\n");
+    left_drivetrain_talon_->Disable();
+    right_drivetrain_talon_->Disable();
+  }
+
+  ::std::unique_ptr<Talon> left_drivetrain_talon_;
+  ::std::unique_ptr<Talon> right_drivetrain_talon_;
+};
+
+class FridgeWriter : public LoopOutputHandler {
+ public:
+  void set_left_arm_talon(::std::unique_ptr<Talon> t) {
+    left_arm_talon_ = ::std::move(t);
+  }
+
+  void set_right_arm_talon(::std::unique_ptr<Talon> t) {
+    right_arm_talon_ = ::std::move(t);
+  }
+
+  void set_left_elevator_talon(::std::unique_ptr<Talon> t) {
+    left_elevator_talon_ = ::std::move(t);
+  }
+
+  void set_right_elevator_talon(::std::unique_ptr<Talon> t) {
+    right_elevator_talon_ = ::std::move(t);
+  }
+
+ private:
+  virtual void Read() override {
+    ::frc971::control_loops::fridge_queue.output.FetchAnother();
+  }
+
+  virtual void Write() override {
+    auto &queue = ::frc971::control_loops::fridge_queue.output;
+    LOG_STRUCT(DEBUG, "will output", *queue);
+    left_arm_talon_->Set(queue->left_arm / 12.0);
+    right_arm_talon_->Set(-queue->right_arm / 12.0);
+    left_elevator_talon_->Set(queue->left_elevator / 12.0);
+    right_elevator_talon_->Set(-queue->right_elevator / 12.0);
+  }
+
+  virtual void Stop() override {
+    LOG(WARNING, "Fridge output too old.\n");
+    left_arm_talon_->Disable();
+    right_arm_talon_->Disable();
+    left_elevator_talon_->Disable();
+    right_elevator_talon_->Disable();
+  }
+
+  ::std::unique_ptr<Talon> left_arm_talon_;
+  ::std::unique_ptr<Talon> right_arm_talon_;
+  ::std::unique_ptr<Talon> left_elevator_talon_;
+  ::std::unique_ptr<Talon> right_elevator_talon_;
+};
+
+class ClawWriter : public LoopOutputHandler {
+ public:
+  void set_left_intake_talon(::std::unique_ptr<Talon> t) {
+    left_intake_talon_ = ::std::move(t);
+  }
+
+  void set_right_intake_talon(::std::unique_ptr<Talon> t) {
+    right_intake_talon_ = ::std::move(t);
+  }
+
+  void set_wrist_talon(::std::unique_ptr<Talon> t) {
+    wrist_talon_ = ::std::move(t);
+  }
+
+ private:
+  virtual void Read() override {
+    ::frc971::control_loops::claw_queue.output.FetchAnother();
+  }
+
+  virtual void Write() override {
+    auto &queue = ::frc971::control_loops::claw_queue.output;
+    LOG_STRUCT(DEBUG, "will output", *queue);
+    left_intake_talon_->Set(queue->intake_voltage / 12.0);
+    right_intake_talon_->Set(-queue->intake_voltage / 12.0);
+    wrist_talon_->Set(-queue->voltage / 12.0);
+  }
+
+  virtual void Stop() override {
+    LOG(WARNING, "Claw output too old.\n");
+    left_intake_talon_->Disable();
+    right_intake_talon_->Disable();
+    wrist_talon_->Disable();
+  }
+
+  ::std::unique_ptr<Talon> left_intake_talon_;
+  ::std::unique_ptr<Talon> right_intake_talon_;
+  ::std::unique_ptr<Talon> wrist_talon_;
+};
+
+// TODO(brian): Replace this with ::std::make_unique once all our toolchains
+// have support.
+template <class T, class... U>
+std::unique_ptr<T> make_unique(U &&... u) {
+  return std::unique_ptr<T>(new T(std::forward<U>(u)...));
+}
+
+class WPILibRobot : public RobotBase {
+ public:
+  ::std::unique_ptr<Encoder> encoder(int index) {
+    return make_unique<Encoder>(10 + index * 2, 11 + index * 2, false,
+                                Encoder::k4X);
+  }
+  virtual void StartCompetition() {
+    ::aos::InitNRT();
+    ::aos::SetCurrentThreadName("StartCompetition");
+
+    JoystickSender joystick_sender;
+    ::std::thread joystick_thread(::std::ref(joystick_sender));
+    // TODO(austin): Compressor needs to use a spike.
+
+    SensorReader reader;
+    LOG(INFO, "Creating the reader\n");
+    reader.set_arm_left_encoder(encoder(1));
+    reader.set_arm_left_index(make_unique<DigitalInput>(1));
+    reader.set_arm_left_potentiometer(make_unique<AnalogInput>(1));
+
+    reader.set_arm_right_encoder(encoder(5));
+    reader.set_arm_right_index(make_unique<DigitalInput>(5));
+    reader.set_arm_right_potentiometer(make_unique<AnalogInput>(5));
+
+    reader.set_elevator_left_encoder(encoder(0));
+    reader.set_elevator_left_index(make_unique<DigitalInput>(0));
+    reader.set_elevator_left_potentiometer(make_unique<AnalogInput>(0));
+
+    reader.set_elevator_right_encoder(encoder(4));
+    reader.set_elevator_right_index(make_unique<DigitalInput>(4));
+    reader.set_elevator_right_potentiometer(make_unique<AnalogInput>(4));
+
+    reader.set_wrist_encoder(encoder(6));
+    reader.set_wrist_index(make_unique<DigitalInput>(6));
+    reader.set_wrist_potentiometer(make_unique<AnalogInput>(6));
+
+    reader.set_left_encoder(encoder(2));
+    reader.set_right_encoder(encoder(3));
+    reader.set_dma(make_unique<DMA>());
+    ::std::thread reader_thread(::std::ref(reader));
+    GyroSender gyro_sender;
+    ::std::thread gyro_thread(::std::ref(gyro_sender));
+
+    DrivetrainWriter drivetrain_writer;
+    drivetrain_writer.set_left_drivetrain_talon(
+        ::std::unique_ptr<Talon>(new Talon(8)));
+    drivetrain_writer.set_right_drivetrain_talon(
+        ::std::unique_ptr<Talon>(new Talon(0)));
+    ::std::thread drivetrain_writer_thread(::std::ref(drivetrain_writer));
+
+    // TODO(sensors): Get real PWM output and relay numbers for the fridge and
+    // claw.
+    FridgeWriter fridge_writer;
+    fridge_writer.set_left_arm_talon(
+        ::std::unique_ptr<Talon>(new Talon(6)));
+    fridge_writer.set_right_arm_talon(
+        ::std::unique_ptr<Talon>(new Talon(2)));
+    fridge_writer.set_left_elevator_talon(
+        ::std::unique_ptr<Talon>(new Talon(7)));
+    fridge_writer.set_right_elevator_talon(
+        ::std::unique_ptr<Talon>(new Talon(1)));
+    ::std::thread fridge_writer_thread(::std::ref(fridge_writer));
+
+    ClawWriter claw_writer;
+    claw_writer.set_left_intake_talon(
+        ::std::unique_ptr<Talon>(new Talon(5)));
+    claw_writer.set_right_intake_talon(
+        ::std::unique_ptr<Talon>(new Talon(3)));
+    claw_writer.set_wrist_talon(
+        ::std::unique_ptr<Talon>(new Talon(4)));
+    ::std::thread claw_writer_thread(::std::ref(claw_writer));
+
+    ::std::unique_ptr<::frc971::wpilib::BufferedPcm> pcm(
+        new ::frc971::wpilib::BufferedPcm());
+    SolenoidWriter solenoid_writer(pcm);
+    solenoid_writer.set_fridge_grabbers_top_front(pcm->MakeSolenoid(0));
+    solenoid_writer.set_fridge_grabbers_top_back(pcm->MakeSolenoid(0));
+    solenoid_writer.set_fridge_grabbers_bottom_front(pcm->MakeSolenoid(2));
+    solenoid_writer.set_fridge_grabbers_bottom_back(pcm->MakeSolenoid(1));
+    solenoid_writer.set_claw_pinchers(pcm->MakeSolenoid(4));
+    solenoid_writer.set_grabber_latch_release(pcm->MakeSolenoid(7));
+    solenoid_writer.set_grabber_fold_up(pcm->MakeSolenoid(5));
+
+    solenoid_writer.set_pressure_switch(make_unique<DigitalInput>(9));
+    solenoid_writer.set_compressor_relay(make_unique<Relay>(0));
+    ::std::thread solenoid_thread(::std::ref(solenoid_writer));
+
+    // Wait forever. Not much else to do...
+    PCHECK(select(0, nullptr, nullptr, nullptr, nullptr));
+
+    LOG(ERROR, "Exiting WPILibRobot\n");
+
+    joystick_sender.Quit();
+    joystick_thread.join();
+    reader.Quit();
+    reader_thread.join();
+    gyro_sender.Quit();
+    gyro_thread.join();
+
+    drivetrain_writer.Quit();
+    drivetrain_writer_thread.join();
+    solenoid_writer.Quit();
+    solenoid_thread.join();
+
+    ::aos::Cleanup();
+  }
+};
+
+}  // namespace wpilib
+}  // namespace frc971
+
+
+START_ROBOT_CLASS(::frc971::wpilib::WPILibRobot);
diff --git a/y2015/y2015.gyp b/y2015/y2015.gyp
new file mode 100644
index 0000000..7f929d9
--- /dev/null
+++ b/y2015/y2015.gyp
@@ -0,0 +1,53 @@
+{
+  'targets': [
+    {
+      'target_name': 'constants',
+      'type': 'static_library',
+      'sources': [
+        'constants.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/common.gyp:once',
+        '<(AOS)/common/network/network.gyp:team_number',
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+        '<(DEPTH)/y2015/control_loops/drivetrain/drivetrain.gyp:polydrivetrain_plants',
+      ],
+      'export_dependent_settings': [
+        '<(DEPTH)/frc971/control_loops/control_loops.gyp:state_feedback_loop',
+      ],
+    },
+    {
+      'target_name': 'joystick_reader',
+      'type': 'executable',
+      'sources': [
+        'joystick_reader.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/prime/input/input.gyp:joystick_input',
+        '<(AOS)/linux_code/linux_code.gyp:init',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/common/util/util.gyp:log_interval',
+        '<(AOS)/common/actions/actions.gyp:action_lib',
+
+        '<(DEPTH)/frc971/queues/queues.gyp:gyro',
+        '<(DEPTH)/y2015/control_loops/claw/claw.gyp:claw_queue',
+        '<(DEPTH)/y2015/control_loops/drivetrain/drivetrain.gyp:drivetrain_queue',
+        '<(DEPTH)/y2015/control_loops/fridge/fridge.gyp:fridge_queue',
+        '<(DEPTH)/y2015/y2015.gyp:constants',
+        '<(DEPTH)/frc971/autonomous/autonomous.gyp:auto_queue',
+        '<(DEPTH)/y2015/actors/actors.gyp:stack_action_lib',
+        '<(DEPTH)/y2015/actors/actors.gyp:stack_and_lift_action_lib',
+        '<(DEPTH)/y2015/actors/actors.gyp:stack_and_hold_action_lib',
+        '<(DEPTH)/y2015/actors/actors.gyp:pickup_action_lib',
+        '<(DEPTH)/y2015/actors/actors.gyp:lift_action_lib',
+        '<(DEPTH)/y2015/actors/actors.gyp:held_to_lift_action_lib',
+        '<(DEPTH)/y2015/actors/actors.gyp:can_pickup_action_lib',
+        '<(DEPTH)/y2015/actors/actors.gyp:score_action_lib',
+        '<(DEPTH)/y2015/actors/actors.gyp:horizontal_can_pickup_action_lib',
+        '<(DEPTH)/y2015/actors/actors.gyp:fridge_profile_lib',
+      ],
+    },
+  ],
+}